From: root Date: Tue, 25 Jan 2011 13:56:18 +0000 (+0800) Subject: Remove wireless directory first. X-Git-Tag: firefly_0821_release~10785^2~12^2~15 X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=1ee596ad94032d2cab89e6693cd665a275e580ef;p=firefly-linux-kernel-4.4.55.git Remove wireless directory first. --- diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig deleted file mode 100644 index 9c85f82ec83e..000000000000 --- a/drivers/net/wireless/Kconfig +++ /dev/null @@ -1,493 +0,0 @@ -# -# Wireless LAN device configuration -# - -menuconfig WLAN - bool "Wireless LAN" - depends on !S390 - default y - ---help--- - This section contains all the pre 802.11 and 802.11 wireless - device drivers. For a complete list of drivers and documentation - on them refer to the wireless wiki: - - http://wireless.kernel.org/en/users/Drivers - -if WLAN - -menuconfig WLAN_PRE80211 - bool "Wireless LAN (pre-802.11)" - depends on NETDEVICES - ---help--- - Say Y if you have any pre-802.11 wireless LAN hardware. - - This option does not affect the kernel build, it only - lets you choose drivers. - -config STRIP - tristate "STRIP (Metricom starmode radio IP)" - depends on INET && WLAN_PRE80211 - select WIRELESS_EXT - ---help--- - Say Y if you have a Metricom radio and intend to use Starmode Radio - IP. STRIP is a radio protocol developed for the MosquitoNet project - to send Internet traffic using Metricom radios. Metricom radios are - small, battery powered, 100kbit/sec packet radio transceivers, about - the size and weight of a cellular telephone. (You may also have heard - them called "Metricom modems" but we avoid the term "modem" because - it misleads many people into thinking that you can plug a Metricom - modem into a phone line and use it as a modem.) - - You can use STRIP on any Linux machine with a serial port, although - it is obviously most useful for people with laptop computers. If you - think you might get a Metricom radio in the future, there is no harm - in saying Y to STRIP now, except that it makes the kernel a bit - bigger. - - To compile this as a module, choose M here: the module will be - called strip. - -config ARLAN - tristate "Aironet Arlan 655 & IC2200 DS support" - depends on ISA && !64BIT && WLAN_PRE80211 - select WIRELESS_EXT - ---help--- - Aironet makes Arlan, a class of wireless LAN adapters. These use the - www.Telxon.com chip, which is also used on several similar cards. - This driver is tested on the 655 and IC2200 series cards. Look at - for the latest information. - - The driver is built as two modules, arlan and arlan-proc. The latter - is the /proc interface and is not needed most of time. - - On some computers the card ends up in non-valid state after some - time. Use a ping-reset script to clear it. - -config WAVELAN - tristate "AT&T/Lucent old WaveLAN & DEC RoamAbout DS ISA support" - depends on ISA && WLAN_PRE80211 - select WIRELESS_EXT - ---help--- - The Lucent WaveLAN (formerly NCR and AT&T; or DEC RoamAbout DS) is - a Radio LAN (wireless Ethernet-like Local Area Network) using the - radio frequencies 900 MHz and 2.4 GHz. - - If you want to use an ISA WaveLAN card under Linux, say Y and read - the Ethernet-HOWTO, available from - . Some more specific - information is contained in - and in the source code - . - - You will also need the wireless tools package available from - . - Please read the man pages contained therein. - - To compile this driver as a module, choose M here: the module will be - called wavelan. - -config PCMCIA_WAVELAN - tristate "AT&T/Lucent old WaveLAN Pcmcia wireless support" - depends on PCMCIA && WLAN_PRE80211 - select WIRELESS_EXT - help - Say Y here if you intend to attach an AT&T/Lucent Wavelan PCMCIA - (PC-card) wireless Ethernet networking card to your computer. This - driver is for the non-IEEE-802.11 Wavelan cards. - - To compile this driver as a module, choose M here: the module will be - called wavelan_cs. If unsure, say N. - -config PCMCIA_NETWAVE - tristate "Xircom Netwave AirSurfer Pcmcia wireless support" - depends on PCMCIA && WLAN_PRE80211 - select WIRELESS_EXT - help - Say Y here if you intend to attach this type of PCMCIA (PC-card) - wireless Ethernet networking card to your computer. - - To compile this driver as a module, choose M here: the module will be - called netwave_cs. If unsure, say N. - - -menuconfig WLAN_80211 - bool "Wireless LAN (IEEE 802.11)" - depends on NETDEVICES - ---help--- - Say Y if you have any 802.11 wireless LAN hardware. - - This option does not affect the kernel build, it only - lets you choose drivers. - -config PCMCIA_RAYCS - tristate "Aviator/Raytheon 2.4GHz wireless support" - depends on PCMCIA && WLAN_80211 - select WIRELESS_EXT - ---help--- - Say Y here if you intend to attach an Aviator/Raytheon PCMCIA - (PC-card) wireless Ethernet networking card to your computer. - Please read the file for - details. - - To compile this driver as a module, choose M here: the module will be - called ray_cs. If unsure, say N. - -config LIBERTAS - tristate "Marvell 8xxx Libertas WLAN driver support" - depends on WLAN_80211 - select WIRELESS_EXT - select LIB80211 - select FW_LOADER - ---help--- - A library for Marvell Libertas 8xxx devices. - -config LIBERTAS_USB - tristate "Marvell Libertas 8388 USB 802.11b/g cards" - depends on LIBERTAS && USB - ---help--- - A driver for Marvell Libertas 8388 USB devices. - -config LIBERTAS_CS - tristate "Marvell Libertas 8385 CompactFlash 802.11b/g cards" - depends on LIBERTAS && PCMCIA - select FW_LOADER - ---help--- - A driver for Marvell Libertas 8385 CompactFlash devices. - -config LIBERTAS_SDIO - tristate "Marvell Libertas 8385/8686/8688 SDIO 802.11b/g cards" - depends on LIBERTAS && MMC - ---help--- - A driver for Marvell Libertas 8385/8686/8688 SDIO devices. - -config LIBERTAS_SPI - tristate "Marvell Libertas 8686 SPI 802.11b/g cards" - depends on LIBERTAS && SPI - ---help--- - A driver for Marvell Libertas 8686 SPI devices. - -config LIBERTAS_DEBUG - bool "Enable full debugging output in the Libertas module." - depends on LIBERTAS - ---help--- - Debugging support. - -config LIBERTAS_THINFIRM - tristate "Marvell 8xxx Libertas WLAN driver support with thin firmware" - depends on WLAN_80211 && MAC80211 - select FW_LOADER - ---help--- - A library for Marvell Libertas 8xxx devices using thinfirm. - -config LIBERTAS_THINFIRM_USB - tristate "Marvell Libertas 8388 USB 802.11b/g cards with thin firmware" - depends on LIBERTAS_THINFIRM && USB - ---help--- - A driver for Marvell Libertas 8388 USB devices using thinfirm. - -config AIRO - tristate "Cisco/Aironet 34X/35X/4500/4800 ISA and PCI cards" - depends on ISA_DMA_API && WLAN_80211 && (PCI || BROKEN) - select WIRELESS_EXT - select CRYPTO - ---help--- - This is the standard Linux driver to support Cisco/Aironet ISA and - PCI 802.11 wireless cards. - It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X - - with or without encryption) as well as card before the Cisco - acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). - - This driver support both the standard Linux Wireless Extensions - and Cisco proprietary API, so both the Linux Wireless Tools and the - Cisco Linux utilities can be used to configure the card. - - The driver can be compiled as a module and will be named "airo". - -config ATMEL - tristate "Atmel at76c50x chipset 802.11b support" - depends on (PCI || PCMCIA) && WLAN_80211 - select WIRELESS_EXT - select FW_LOADER - select CRC32 - ---help--- - A driver 802.11b wireless cards based on the Atmel fast-vnet - chips. This driver supports standard Linux wireless extensions. - - Many cards based on this chipset do not have flash memory - and need their firmware loaded at start-up. If yours is - one of these, you will need to provide a firmware image - to be loaded into the card by the driver. The Atmel - firmware package can be downloaded from - - -config PCI_ATMEL - tristate "Atmel at76c506 PCI cards" - depends on ATMEL && PCI - ---help--- - Enable support for PCI and mini-PCI cards containing the - Atmel at76c506 chip. - -config PCMCIA_ATMEL - tristate "Atmel at76c502/at76c504 PCMCIA cards" - depends on ATMEL && PCMCIA - select WIRELESS_EXT - select FW_LOADER - select CRC32 - ---help--- - Enable support for PCMCIA cards containing the - Atmel at76c502 and at76c504 chips. - -config AT76C50X_USB - tristate "Atmel at76c503/at76c505/at76c505a USB cards" - depends on MAC80211 && WLAN_80211 && USB - select FW_LOADER - ---help--- - Enable support for USB Wireless devices using Atmel at76c503, - at76c505 or at76c505a chips. - -config AIRO_CS - tristate "Cisco/Aironet 34X/35X/4500/4800 PCMCIA cards" - depends on PCMCIA && (BROKEN || !M32R) && WLAN_80211 - select WIRELESS_EXT - select CRYPTO - select CRYPTO_AES - ---help--- - This is the standard Linux driver to support Cisco/Aironet PCMCIA - 802.11 wireless cards. This driver is the same as the Aironet - driver part of the Linux Pcmcia package. - It supports the new 802.11b cards from Cisco (Cisco 34X, Cisco 35X - - with or without encryption) as well as card before the Cisco - acquisition (Aironet 4500, Aironet 4800, Aironet 4800B). It also - supports OEM of Cisco such as the DELL TrueMobile 4800 and Xircom - 802.11b cards. - - This driver support both the standard Linux Wireless Extensions - and Cisco proprietary API, so both the Linux Wireless Tools and the - Cisco Linux utilities can be used to configure the card. - -config PCMCIA_WL3501 - tristate "Planet WL3501 PCMCIA cards" - depends on EXPERIMENTAL && PCMCIA && WLAN_80211 - select WIRELESS_EXT - ---help--- - A driver for WL3501 PCMCIA 802.11 wireless cards made by Planet. - It has basic support for Linux wireless extensions and initial - micro support for ethtool. - -config PRISM54 - tristate 'Intersil Prism GT/Duette/Indigo PCI/Cardbus (DEPRECATED)' - depends on PCI && EXPERIMENTAL && WLAN_80211 - select WIRELESS_EXT - select FW_LOADER - ---help--- - This enables support for FullMAC PCI/Cardbus prism54 devices. This - driver is now deprecated in favor for the SoftMAC driver, p54pci. - p54pci supports FullMAC PCI/Cardbus devices as well. For details on - the scheduled removal of this driver on the kernel see the feature - removal schedule: - - Documentation/feature-removal-schedule.txt - - For more information refer to the p54 wiki: - - http://wireless.kernel.org/en/users/Drivers/p54 - - Note: You need a motherboard with DMA support to use any of these cards - - When built as module you get the module prism54 - -config USB_ZD1201 - tristate "USB ZD1201 based Wireless device support" - depends on USB && WLAN_80211 - select WIRELESS_EXT - select FW_LOADER - ---help--- - Say Y if you want to use wireless LAN adapters based on the ZyDAS - ZD1201 chip. - - This driver makes the adapter appear as a normal Ethernet interface, - typically on wlan0. - - The zd1201 device requires external firmware to be loaded. - This can be found at http://linux-lc100020.sourceforge.net/ - - To compile this driver as a module, choose M here: the - module will be called zd1201. - -config USB_NET_RNDIS_WLAN - tristate "Wireless RNDIS USB support" - depends on USB && WLAN_80211 && EXPERIMENTAL - depends on CFG80211 - select USB_USBNET - select USB_NET_CDCETHER - select USB_NET_RNDIS_HOST - ---help--- - This is a driver for wireless RNDIS devices. - These are USB based adapters found in devices such as: - - Buffalo WLI-U2-KG125S - U.S. Robotics USR5421 - Belkin F5D7051 - Linksys WUSB54GSv2 - Linksys WUSB54GSC - Asus WL169gE - Eminent EM4045 - BT Voyager 1055 - Linksys WUSB54GSv1 - U.S. Robotics USR5420 - BUFFALO WLI-USB-G54 - - All of these devices are based on Broadcom 4320 chip which is the - only wireless RNDIS chip known to date. - - If you choose to build a module, it'll be called rndis_wlan. - -config RTL8180 - tristate "Realtek 8180/8185 PCI support" - depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL - select EEPROM_93CX6 - ---help--- - This is a driver for RTL8180 and RTL8185 based cards. - These are PCI based chips found in cards such as: - - (RTL8185 802.11g) - A-Link WL54PC - - (RTL8180 802.11b) - Belkin F5D6020 v3 - Belkin F5D6020 v3 - Dlink DWL-610 - Dlink DWL-510 - Netgear MA521 - Level-One WPC-0101 - Acer Aspire 1357 LMi - VCTnet PC-11B1 - Ovislink AirLive WL-1120PCM - Mentor WL-PCI - Linksys WPC11 v4 - TrendNET TEW-288PI - D-Link DWL-520 Rev D - Repotec RP-WP7126 - TP-Link TL-WN250/251 - Zonet ZEW1000 - Longshine LCS-8031-R - HomeLine HLW-PCC200 - GigaFast WF721-AEX - Planet WL-3553 - Encore ENLWI-PCI1-NT - TrendNET TEW-266PC - Gigabyte GN-WLMR101 - Siemens-fujitsu Amilo D1840W - Edimax EW-7126 - PheeNet WL-11PCIR - Tonze PC-2100T - Planet WL-8303 - Dlink DWL-650 v M1 - Edimax EW-7106 - Q-Tec 770WC - Topcom Skyr@cer 4011b - Roper FreeLan 802.11b (edition 2004) - Wistron Neweb Corp CB-200B - Pentagram HorNET - QTec 775WC - TwinMOS Booming B Series - Micronet SP906BB - Sweex LC700010 - Surecom EP-9428 - Safecom SWLCR-1100 - - Thanks to Realtek for their support! - -config RTL8187 - tristate "Realtek 8187 and 8187B USB support" - depends on MAC80211 && USB && WLAN_80211 - select EEPROM_93CX6 - ---help--- - This is a driver for RTL8187 and RTL8187B based cards. - These are USB based chips found in devices such as: - - Netgear WG111v2 - Level 1 WNC-0301USB - Micronet SP907GK V5 - Encore ENUWI-G2 - Trendnet TEW-424UB - ASUS P5B Deluxe/P5K Premium motherboards - Toshiba Satellite Pro series of laptops - Asus Wireless Link - Linksys WUSB54GC-EU v2 - (v1 = rt73usb; v3 is rt2070-based, - use staging/rt3070 or try rt2800usb) - - Thanks to Realtek for their support! - -# If possible, automatically enable LEDs for RTL8187. - -config RTL8187_LEDS - bool - depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187) - default y - -config ADM8211 - tristate "ADMtek ADM8211 support" - depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL - select CRC32 - select EEPROM_93CX6 - ---help--- - This driver is for ADM8211A, ADM8211B, and ADM8211C based cards. - These are PCI/mini-PCI/Cardbus 802.11b chips found in cards such as: - - Xterasys Cardbus XN-2411b - Blitz NetWave Point PC - TrendNet 221pc - Belkin F5D6001 - SMC 2635W - Linksys WPC11 v1 - Fiberline FL-WL-200X - 3com Office Connect (3CRSHPW796) - Corega WLPCIB-11 - SMC 2602W V2 EU - D-Link DWL-520 Revision C - - However, some of these cards have been replaced with other chips - like the RTL8180L (Xterasys Cardbus XN-2411b, Belkin F5D6001) or - the Ralink RT2400 (SMC2635W) without a model number change. - - Thanks to Infineon-ADMtek for their support of this driver. - -config MAC80211_HWSIM - tristate "Simulated radio testing tool for mac80211" - depends on MAC80211 && WLAN_80211 - ---help--- - This driver is a developer testing tool that can be used to test - IEEE 802.11 networking stack (mac80211) functionality. This is not - needed for normal wireless LAN usage and is only for testing. See - Documentation/networking/mac80211_hwsim for more information on how - to use this tool. - - To compile this driver as a module, choose M here: the module will be - called mac80211_hwsim. If unsure, say N. - -config MWL8K - tristate "Marvell 88W8xxx PCI/PCIe Wireless support" - depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL - ---help--- - This driver supports Marvell TOPDOG 802.11 wireless cards. - - To compile this driver as a module, choose M here: the module - will be called mwl8k. If unsure, say N. - -source "drivers/net/wireless/p54/Kconfig" -source "drivers/net/wireless/ath/Kconfig" -source "drivers/net/wireless/ipw2x00/Kconfig" -source "drivers/net/wireless/iwlwifi/Kconfig" -source "drivers/net/wireless/hostap/Kconfig" -source "drivers/net/wireless/b43/Kconfig" -source "drivers/net/wireless/b43legacy/Kconfig" -source "drivers/net/wireless/zd1211rw/Kconfig" -source "drivers/net/wireless/rt2x00/Kconfig" -source "drivers/net/wireless/orinoco/Kconfig" -source "drivers/net/wireless/wl12xx/Kconfig" -source "drivers/net/wireless/iwmc3200wifi/Kconfig" -source "drivers/net/wireless/bcm4329/Kconfig" - -endif # WLAN diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile deleted file mode 100644 index 81e81f7b5250..000000000000 --- a/drivers/net/wireless/Makefile +++ /dev/null @@ -1,66 +0,0 @@ -# -# Makefile for the Linux Wireless network device drivers. -# - -obj-$(CONFIG_IPW2100) += ipw2x00/ -obj-$(CONFIG_IPW2200) += ipw2x00/ - -obj-$(CONFIG_STRIP) += strip.o -obj-$(CONFIG_ARLAN) += arlan.o - -arlan-objs := arlan-main.o arlan-proc.o - -# Obsolete cards -obj-$(CONFIG_WAVELAN) += wavelan.o -obj-$(CONFIG_PCMCIA_NETWAVE) += netwave_cs.o -obj-$(CONFIG_PCMCIA_WAVELAN) += wavelan_cs.o - -obj-$(CONFIG_HERMES) += orinoco/ - -obj-$(CONFIG_AIRO) += airo.o -obj-$(CONFIG_AIRO_CS) += airo_cs.o airo.o - -obj-$(CONFIG_ATMEL) += atmel.o -obj-$(CONFIG_PCI_ATMEL) += atmel_pci.o -obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o - -obj-$(CONFIG_AT76C50X_USB) += at76c50x-usb.o - -obj-$(CONFIG_PRISM54) += prism54/ - -obj-$(CONFIG_HOSTAP) += hostap/ -obj-$(CONFIG_B43) += b43/ -obj-$(CONFIG_B43LEGACY) += b43legacy/ -obj-$(CONFIG_ZD1211RW) += zd1211rw/ -obj-$(CONFIG_RTL8180) += rtl818x/ -obj-$(CONFIG_RTL8187) += rtl818x/ - -# 16-bit wireless PCMCIA client drivers -obj-$(CONFIG_PCMCIA_RAYCS) += ray_cs.o -obj-$(CONFIG_PCMCIA_WL3501) += wl3501_cs.o - -obj-$(CONFIG_USB_NET_RNDIS_WLAN) += rndis_wlan.o - -obj-$(CONFIG_USB_ZD1201) += zd1201.o -obj-$(CONFIG_LIBERTAS) += libertas/ - -obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf/ - -obj-$(CONFIG_ADM8211) += adm8211.o - -obj-$(CONFIG_MWL8K) += mwl8k.o - -obj-$(CONFIG_IWLWIFI) += iwlwifi/ -obj-$(CONFIG_RT2X00) += rt2x00/ - -obj-$(CONFIG_P54_COMMON) += p54/ - -obj-$(CONFIG_ATH_COMMON) += ath/ - -obj-$(CONFIG_MAC80211_HWSIM) += mac80211_hwsim.o - -obj-$(CONFIG_WL12XX) += wl12xx/ - -obj-$(CONFIG_IWM) += iwmc3200wifi/ -obj-$(CONFIG_BCM4329) += bcm4329/ -#obj-m += wlan/ diff --git a/drivers/net/wireless/adm8211.c b/drivers/net/wireless/adm8211.c deleted file mode 100644 index b80f514877d8..000000000000 --- a/drivers/net/wireless/adm8211.c +++ /dev/null @@ -1,2024 +0,0 @@ - -/* - * Linux device driver for ADMtek ADM8211 (IEEE 802.11b MAC/BBP) - * - * Copyright (c) 2003, Jouni Malinen - * Copyright (c) 2004-2007, Michael Wu - * Some parts copyright (c) 2003 by David Young - * and used with permission. - * - * Much thanks to Infineon-ADMtek for their support of this driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "adm8211.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_AUTHOR("Jouni Malinen "); -MODULE_DESCRIPTION("Driver for IEEE 802.11b wireless cards based on ADMtek ADM8211"); -MODULE_SUPPORTED_DEVICE("ADM8211"); -MODULE_LICENSE("GPL"); - -static unsigned int tx_ring_size __read_mostly = 16; -static unsigned int rx_ring_size __read_mostly = 16; - -module_param(tx_ring_size, uint, 0); -module_param(rx_ring_size, uint, 0); - -static struct pci_device_id adm8211_pci_id_table[] __devinitdata = { - /* ADMtek ADM8211 */ - { PCI_DEVICE(0x10B7, 0x6000) }, /* 3Com 3CRSHPW796 */ - { PCI_DEVICE(0x1200, 0x8201) }, /* ? */ - { PCI_DEVICE(0x1317, 0x8201) }, /* ADM8211A */ - { PCI_DEVICE(0x1317, 0x8211) }, /* ADM8211B/C */ - { 0 } -}; - -static struct ieee80211_rate adm8211_rates[] = { - { .bitrate = 10, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 220, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, /* XX ?? */ -}; - -static const struct ieee80211_channel adm8211_channels[] = { - { .center_freq = 2412}, - { .center_freq = 2417}, - { .center_freq = 2422}, - { .center_freq = 2427}, - { .center_freq = 2432}, - { .center_freq = 2437}, - { .center_freq = 2442}, - { .center_freq = 2447}, - { .center_freq = 2452}, - { .center_freq = 2457}, - { .center_freq = 2462}, - { .center_freq = 2467}, - { .center_freq = 2472}, - { .center_freq = 2484}, -}; - - -static void adm8211_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct adm8211_priv *priv = eeprom->data; - u32 reg = ADM8211_CSR_READ(SPR); - - eeprom->reg_data_in = reg & ADM8211_SPR_SDI; - eeprom->reg_data_out = reg & ADM8211_SPR_SDO; - eeprom->reg_data_clock = reg & ADM8211_SPR_SCLK; - eeprom->reg_chip_select = reg & ADM8211_SPR_SCS; -} - -static void adm8211_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct adm8211_priv *priv = eeprom->data; - u32 reg = 0x4000 | ADM8211_SPR_SRS; - - if (eeprom->reg_data_in) - reg |= ADM8211_SPR_SDI; - if (eeprom->reg_data_out) - reg |= ADM8211_SPR_SDO; - if (eeprom->reg_data_clock) - reg |= ADM8211_SPR_SCLK; - if (eeprom->reg_chip_select) - reg |= ADM8211_SPR_SCS; - - ADM8211_CSR_WRITE(SPR, reg); - ADM8211_CSR_READ(SPR); /* eeprom_delay */ -} - -static int adm8211_read_eeprom(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - unsigned int words, i; - struct ieee80211_chan_range chan_range; - u16 cr49; - struct eeprom_93cx6 eeprom = { - .data = priv, - .register_read = adm8211_eeprom_register_read, - .register_write = adm8211_eeprom_register_write - }; - - if (ADM8211_CSR_READ(CSR_TEST0) & ADM8211_CSR_TEST0_EPTYP) { - /* 256 * 16-bit = 512 bytes */ - eeprom.width = PCI_EEPROM_WIDTH_93C66; - words = 256; - } else { - /* 64 * 16-bit = 128 bytes */ - eeprom.width = PCI_EEPROM_WIDTH_93C46; - words = 64; - } - - priv->eeprom_len = words * 2; - priv->eeprom = kmalloc(priv->eeprom_len, GFP_KERNEL); - if (!priv->eeprom) - return -ENOMEM; - - eeprom_93cx6_multiread(&eeprom, 0, (__le16 *)priv->eeprom, words); - - cr49 = le16_to_cpu(priv->eeprom->cr49); - priv->rf_type = (cr49 >> 3) & 0x7; - switch (priv->rf_type) { - case ADM8211_TYPE_INTERSIL: - case ADM8211_TYPE_RFMD: - case ADM8211_TYPE_MARVEL: - case ADM8211_TYPE_AIROHA: - case ADM8211_TYPE_ADMTEK: - break; - - default: - if (priv->pdev->revision < ADM8211_REV_CA) - priv->rf_type = ADM8211_TYPE_RFMD; - else - priv->rf_type = ADM8211_TYPE_AIROHA; - - printk(KERN_WARNING "%s (adm8211): Unknown RFtype %d\n", - pci_name(priv->pdev), (cr49 >> 3) & 0x7); - } - - priv->bbp_type = cr49 & 0x7; - switch (priv->bbp_type) { - case ADM8211_TYPE_INTERSIL: - case ADM8211_TYPE_RFMD: - case ADM8211_TYPE_MARVEL: - case ADM8211_TYPE_AIROHA: - case ADM8211_TYPE_ADMTEK: - break; - default: - if (priv->pdev->revision < ADM8211_REV_CA) - priv->bbp_type = ADM8211_TYPE_RFMD; - else - priv->bbp_type = ADM8211_TYPE_ADMTEK; - - printk(KERN_WARNING "%s (adm8211): Unknown BBPtype: %d\n", - pci_name(priv->pdev), cr49 >> 3); - } - - if (priv->eeprom->country_code >= ARRAY_SIZE(cranges)) { - printk(KERN_WARNING "%s (adm8211): Invalid country code (%d)\n", - pci_name(priv->pdev), priv->eeprom->country_code); - - chan_range = cranges[2]; - } else - chan_range = cranges[priv->eeprom->country_code]; - - printk(KERN_DEBUG "%s (adm8211): Channel range: %d - %d\n", - pci_name(priv->pdev), (int)chan_range.min, (int)chan_range.max); - - BUILD_BUG_ON(sizeof(priv->channels) != sizeof(adm8211_channels)); - - memcpy(priv->channels, adm8211_channels, sizeof(priv->channels)); - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(adm8211_channels); - priv->band.bitrates = adm8211_rates; - priv->band.n_bitrates = ARRAY_SIZE(adm8211_rates); - - for (i = 1; i <= ARRAY_SIZE(adm8211_channels); i++) - if (i < chan_range.min || i > chan_range.max) - priv->channels[i - 1].flags |= IEEE80211_CHAN_DISABLED; - - switch (priv->eeprom->specific_bbptype) { - case ADM8211_BBP_RFMD3000: - case ADM8211_BBP_RFMD3002: - case ADM8211_BBP_ADM8011: - priv->specific_bbptype = priv->eeprom->specific_bbptype; - break; - - default: - if (priv->pdev->revision < ADM8211_REV_CA) - priv->specific_bbptype = ADM8211_BBP_RFMD3000; - else - priv->specific_bbptype = ADM8211_BBP_ADM8011; - - printk(KERN_WARNING "%s (adm8211): Unknown specific BBP: %d\n", - pci_name(priv->pdev), priv->eeprom->specific_bbptype); - } - - switch (priv->eeprom->specific_rftype) { - case ADM8211_RFMD2948: - case ADM8211_RFMD2958: - case ADM8211_RFMD2958_RF3000_CONTROL_POWER: - case ADM8211_MAX2820: - case ADM8211_AL2210L: - priv->transceiver_type = priv->eeprom->specific_rftype; - break; - - default: - if (priv->pdev->revision == ADM8211_REV_BA) - priv->transceiver_type = ADM8211_RFMD2958_RF3000_CONTROL_POWER; - else if (priv->pdev->revision == ADM8211_REV_CA) - priv->transceiver_type = ADM8211_AL2210L; - else if (priv->pdev->revision == ADM8211_REV_AB) - priv->transceiver_type = ADM8211_RFMD2948; - - printk(KERN_WARNING "%s (adm8211): Unknown transceiver: %d\n", - pci_name(priv->pdev), priv->eeprom->specific_rftype); - - break; - } - - printk(KERN_DEBUG "%s (adm8211): RFtype=%d BBPtype=%d Specific BBP=%d " - "Transceiver=%d\n", pci_name(priv->pdev), priv->rf_type, - priv->bbp_type, priv->specific_bbptype, priv->transceiver_type); - - return 0; -} - -static inline void adm8211_write_sram(struct ieee80211_hw *dev, - u32 addr, u32 data) -{ - struct adm8211_priv *priv = dev->priv; - - ADM8211_CSR_WRITE(WEPCTL, addr | ADM8211_WEPCTL_TABLE_WR | - (priv->pdev->revision < ADM8211_REV_BA ? - 0 : ADM8211_WEPCTL_SEL_WEPTABLE )); - ADM8211_CSR_READ(WEPCTL); - msleep(1); - - ADM8211_CSR_WRITE(WESK, data); - ADM8211_CSR_READ(WESK); - msleep(1); -} - -static void adm8211_write_sram_bytes(struct ieee80211_hw *dev, - unsigned int addr, u8 *buf, - unsigned int len) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg = ADM8211_CSR_READ(WEPCTL); - unsigned int i; - - if (priv->pdev->revision < ADM8211_REV_BA) { - for (i = 0; i < len; i += 2) { - u16 val = buf[i] | (buf[i + 1] << 8); - adm8211_write_sram(dev, addr + i / 2, val); - } - } else { - for (i = 0; i < len; i += 4) { - u32 val = (buf[i + 0] << 0 ) | (buf[i + 1] << 8 ) | - (buf[i + 2] << 16) | (buf[i + 3] << 24); - adm8211_write_sram(dev, addr + i / 4, val); - } - } - - ADM8211_CSR_WRITE(WEPCTL, reg); -} - -static void adm8211_clear_sram(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg = ADM8211_CSR_READ(WEPCTL); - unsigned int addr; - - for (addr = 0; addr < ADM8211_SRAM_SIZE; addr++) - adm8211_write_sram(dev, addr, 0); - - ADM8211_CSR_WRITE(WEPCTL, reg); -} - -static int adm8211_get_stats(struct ieee80211_hw *dev, - struct ieee80211_low_level_stats *stats) -{ - struct adm8211_priv *priv = dev->priv; - - memcpy(stats, &priv->stats, sizeof(*stats)); - - return 0; -} - -static int adm8211_get_tx_stats(struct ieee80211_hw *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct adm8211_priv *priv = dev->priv; - - stats[0].len = priv->cur_tx - priv->dirty_tx; - stats[0].limit = priv->tx_ring_size - 2; - stats[0].count = priv->dirty_tx; - - return 0; -} - -static void adm8211_interrupt_tci(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - unsigned int dirty_tx; - - spin_lock(&priv->lock); - - for (dirty_tx = priv->dirty_tx; priv->cur_tx - dirty_tx; dirty_tx++) { - unsigned int entry = dirty_tx % priv->tx_ring_size; - u32 status = le32_to_cpu(priv->tx_ring[entry].status); - struct ieee80211_tx_info *txi; - struct adm8211_tx_ring_info *info; - struct sk_buff *skb; - - if (status & TDES0_CONTROL_OWN || - !(status & TDES0_CONTROL_DONE)) - break; - - info = &priv->tx_buffers[entry]; - skb = info->skb; - txi = IEEE80211_SKB_CB(skb); - - /* TODO: check TDES0_STATUS_TUF and TDES0_STATUS_TRO */ - - pci_unmap_single(priv->pdev, info->mapping, - info->skb->len, PCI_DMA_TODEVICE); - - ieee80211_tx_info_clear_status(txi); - - skb_pull(skb, sizeof(struct adm8211_tx_hdr)); - memcpy(skb_push(skb, info->hdrlen), skb->cb, info->hdrlen); - if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && - !(status & TDES0_STATUS_ES)) - txi->flags |= IEEE80211_TX_STAT_ACK; - - ieee80211_tx_status_irqsafe(dev, skb); - - info->skb = NULL; - } - - if (priv->cur_tx - dirty_tx < priv->tx_ring_size - 2) - ieee80211_wake_queue(dev, 0); - - priv->dirty_tx = dirty_tx; - spin_unlock(&priv->lock); -} - - -static void adm8211_interrupt_rci(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - unsigned int entry = priv->cur_rx % priv->rx_ring_size; - u32 status; - unsigned int pktlen; - struct sk_buff *skb, *newskb; - unsigned int limit = priv->rx_ring_size; - u8 rssi, rate; - - while (!(priv->rx_ring[entry].status & cpu_to_le32(RDES0_STATUS_OWN))) { - if (!limit--) - break; - - status = le32_to_cpu(priv->rx_ring[entry].status); - rate = (status & RDES0_STATUS_RXDR) >> 12; - rssi = le32_to_cpu(priv->rx_ring[entry].length) & - RDES1_STATUS_RSSI; - - pktlen = status & RDES0_STATUS_FL; - if (pktlen > RX_PKT_SIZE) { - if (net_ratelimit()) - printk(KERN_DEBUG "%s: frame too long (%d)\n", - wiphy_name(dev->wiphy), pktlen); - pktlen = RX_PKT_SIZE; - } - - if (!priv->soft_rx_crc && status & RDES0_STATUS_ES) { - skb = NULL; /* old buffer will be reused */ - /* TODO: update RX error stats */ - /* TODO: check RDES0_STATUS_CRC*E */ - } else if (pktlen < RX_COPY_BREAK) { - skb = dev_alloc_skb(pktlen); - if (skb) { - pci_dma_sync_single_for_cpu( - priv->pdev, - priv->rx_buffers[entry].mapping, - pktlen, PCI_DMA_FROMDEVICE); - memcpy(skb_put(skb, pktlen), - skb_tail_pointer(priv->rx_buffers[entry].skb), - pktlen); - pci_dma_sync_single_for_device( - priv->pdev, - priv->rx_buffers[entry].mapping, - RX_PKT_SIZE, PCI_DMA_FROMDEVICE); - } - } else { - newskb = dev_alloc_skb(RX_PKT_SIZE); - if (newskb) { - skb = priv->rx_buffers[entry].skb; - skb_put(skb, pktlen); - pci_unmap_single( - priv->pdev, - priv->rx_buffers[entry].mapping, - RX_PKT_SIZE, PCI_DMA_FROMDEVICE); - priv->rx_buffers[entry].skb = newskb; - priv->rx_buffers[entry].mapping = - pci_map_single(priv->pdev, - skb_tail_pointer(newskb), - RX_PKT_SIZE, - PCI_DMA_FROMDEVICE); - } else { - skb = NULL; - /* TODO: update rx dropped stats */ - } - - priv->rx_ring[entry].buffer1 = - cpu_to_le32(priv->rx_buffers[entry].mapping); - } - - priv->rx_ring[entry].status = cpu_to_le32(RDES0_STATUS_OWN | - RDES0_STATUS_SQL); - priv->rx_ring[entry].length = - cpu_to_le32(RX_PKT_SIZE | - (entry == priv->rx_ring_size - 1 ? - RDES1_CONTROL_RER : 0)); - - if (skb) { - struct ieee80211_rx_status rx_status = {0}; - - if (priv->pdev->revision < ADM8211_REV_CA) - rx_status.signal = rssi; - else - rx_status.signal = 100 - rssi; - - rx_status.rate_idx = rate; - - rx_status.freq = adm8211_channels[priv->channel - 1].center_freq; - rx_status.band = IEEE80211_BAND_2GHZ; - - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(dev, skb); - } - - entry = (++priv->cur_rx) % priv->rx_ring_size; - } - - /* TODO: check LPC and update stats? */ -} - - -static irqreturn_t adm8211_interrupt(int irq, void *dev_id) -{ -#define ADM8211_INT(x) \ -do { \ - if (unlikely(stsr & ADM8211_STSR_ ## x)) \ - printk(KERN_DEBUG "%s: " #x "\n", wiphy_name(dev->wiphy)); \ -} while (0) - - struct ieee80211_hw *dev = dev_id; - struct adm8211_priv *priv = dev->priv; - u32 stsr = ADM8211_CSR_READ(STSR); - ADM8211_CSR_WRITE(STSR, stsr); - if (stsr == 0xffffffff) - return IRQ_HANDLED; - - if (!(stsr & (ADM8211_STSR_NISS | ADM8211_STSR_AISS))) - return IRQ_HANDLED; - - if (stsr & ADM8211_STSR_RCI) - adm8211_interrupt_rci(dev); - if (stsr & ADM8211_STSR_TCI) - adm8211_interrupt_tci(dev); - - ADM8211_INT(PCF); - ADM8211_INT(BCNTC); - ADM8211_INT(GPINT); - ADM8211_INT(ATIMTC); - ADM8211_INT(TSFTF); - ADM8211_INT(TSCZ); - ADM8211_INT(SQL); - ADM8211_INT(WEPTD); - ADM8211_INT(ATIME); - ADM8211_INT(TEIS); - ADM8211_INT(FBE); - ADM8211_INT(REIS); - ADM8211_INT(GPTT); - ADM8211_INT(RPS); - ADM8211_INT(RDU); - ADM8211_INT(TUF); - ADM8211_INT(TPS); - - return IRQ_HANDLED; - -#undef ADM8211_INT -} - -#define WRITE_SYN(name,v_mask,v_shift,a_mask,a_shift,bits,prewrite,postwrite)\ -static void adm8211_rf_write_syn_ ## name (struct ieee80211_hw *dev, \ - u16 addr, u32 value) { \ - struct adm8211_priv *priv = dev->priv; \ - unsigned int i; \ - u32 reg, bitbuf; \ - \ - value &= v_mask; \ - addr &= a_mask; \ - bitbuf = (value << v_shift) | (addr << a_shift); \ - \ - ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_IF_SELECT_1); \ - ADM8211_CSR_READ(SYNRF); \ - ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_IF_SELECT_0); \ - ADM8211_CSR_READ(SYNRF); \ - \ - if (prewrite) { \ - ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_WRITE_SYNDATA_0); \ - ADM8211_CSR_READ(SYNRF); \ - } \ - \ - for (i = 0; i <= bits; i++) { \ - if (bitbuf & (1 << (bits - i))) \ - reg = ADM8211_SYNRF_WRITE_SYNDATA_1; \ - else \ - reg = ADM8211_SYNRF_WRITE_SYNDATA_0; \ - \ - ADM8211_CSR_WRITE(SYNRF, reg); \ - ADM8211_CSR_READ(SYNRF); \ - \ - ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_WRITE_CLOCK_1); \ - ADM8211_CSR_READ(SYNRF); \ - ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_WRITE_CLOCK_0); \ - ADM8211_CSR_READ(SYNRF); \ - } \ - \ - if (postwrite == 1) { \ - ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_IF_SELECT_0); \ - ADM8211_CSR_READ(SYNRF); \ - } \ - if (postwrite == 2) { \ - ADM8211_CSR_WRITE(SYNRF, reg | ADM8211_SYNRF_IF_SELECT_1); \ - ADM8211_CSR_READ(SYNRF); \ - } \ - \ - ADM8211_CSR_WRITE(SYNRF, 0); \ - ADM8211_CSR_READ(SYNRF); \ -} - -WRITE_SYN(max2820, 0x00FFF, 0, 0x0F, 12, 15, 1, 1) -WRITE_SYN(al2210l, 0xFFFFF, 4, 0x0F, 0, 23, 1, 1) -WRITE_SYN(rfmd2958, 0x3FFFF, 0, 0x1F, 18, 23, 0, 1) -WRITE_SYN(rfmd2948, 0x0FFFF, 4, 0x0F, 0, 21, 0, 2) - -#undef WRITE_SYN - -static int adm8211_write_bbp(struct ieee80211_hw *dev, u8 addr, u8 data) -{ - struct adm8211_priv *priv = dev->priv; - unsigned int timeout; - u32 reg; - - timeout = 10; - while (timeout > 0) { - reg = ADM8211_CSR_READ(BBPCTL); - if (!(reg & (ADM8211_BBPCTL_WR | ADM8211_BBPCTL_RD))) - break; - timeout--; - msleep(2); - } - - if (timeout == 0) { - printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed" - " prewrite (reg=0x%08x)\n", - wiphy_name(dev->wiphy), addr, data, reg); - return -ETIMEDOUT; - } - - switch (priv->bbp_type) { - case ADM8211_TYPE_INTERSIL: - reg = ADM8211_BBPCTL_MMISEL; /* three wire interface */ - break; - case ADM8211_TYPE_RFMD: - reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP | - (0x01 << 18); - break; - case ADM8211_TYPE_ADMTEK: - reg = (0x20 << 24) | ADM8211_BBPCTL_TXCE | ADM8211_BBPCTL_CCAP | - (0x05 << 18); - break; - } - reg |= ADM8211_BBPCTL_WR | (addr << 8) | data; - - ADM8211_CSR_WRITE(BBPCTL, reg); - - timeout = 10; - while (timeout > 0) { - reg = ADM8211_CSR_READ(BBPCTL); - if (!(reg & ADM8211_BBPCTL_WR)) - break; - timeout--; - msleep(2); - } - - if (timeout == 0) { - ADM8211_CSR_WRITE(BBPCTL, ADM8211_CSR_READ(BBPCTL) & - ~ADM8211_BBPCTL_WR); - printk(KERN_DEBUG "%s: adm8211_write_bbp(%d,%d) failed" - " postwrite (reg=0x%08x)\n", - wiphy_name(dev->wiphy), addr, data, reg); - return -ETIMEDOUT; - } - - return 0; -} - -static int adm8211_rf_set_channel(struct ieee80211_hw *dev, unsigned int chan) -{ - static const u32 adm8211_rfmd2958_reg5[] = - {0x22BD, 0x22D2, 0x22E8, 0x22FE, 0x2314, 0x232A, 0x2340, - 0x2355, 0x236B, 0x2381, 0x2397, 0x23AD, 0x23C2, 0x23F7}; - static const u32 adm8211_rfmd2958_reg6[] = - {0x05D17, 0x3A2E8, 0x2E8BA, 0x22E8B, 0x1745D, 0x0BA2E, 0x00000, - 0x345D1, 0x28BA2, 0x1D174, 0x11745, 0x05D17, 0x3A2E8, 0x11745}; - - struct adm8211_priv *priv = dev->priv; - u8 ant_power = priv->ant_power > 0x3F ? - priv->eeprom->antenna_power[chan - 1] : priv->ant_power; - u8 tx_power = priv->tx_power > 0x3F ? - priv->eeprom->tx_power[chan - 1] : priv->tx_power; - u8 lpf_cutoff = priv->lpf_cutoff == 0xFF ? - priv->eeprom->lpf_cutoff[chan - 1] : priv->lpf_cutoff; - u8 lnags_thresh = priv->lnags_threshold == 0xFF ? - priv->eeprom->lnags_threshold[chan - 1] : priv->lnags_threshold; - u32 reg; - - ADM8211_IDLE(); - - /* Program synthesizer to new channel */ - switch (priv->transceiver_type) { - case ADM8211_RFMD2958: - case ADM8211_RFMD2958_RF3000_CONTROL_POWER: - adm8211_rf_write_syn_rfmd2958(dev, 0x00, 0x04007); - adm8211_rf_write_syn_rfmd2958(dev, 0x02, 0x00033); - - adm8211_rf_write_syn_rfmd2958(dev, 0x05, - adm8211_rfmd2958_reg5[chan - 1]); - adm8211_rf_write_syn_rfmd2958(dev, 0x06, - adm8211_rfmd2958_reg6[chan - 1]); - break; - - case ADM8211_RFMD2948: - adm8211_rf_write_syn_rfmd2948(dev, SI4126_MAIN_CONF, - SI4126_MAIN_XINDIV2); - adm8211_rf_write_syn_rfmd2948(dev, SI4126_POWERDOWN, - SI4126_POWERDOWN_PDIB | - SI4126_POWERDOWN_PDRB); - adm8211_rf_write_syn_rfmd2948(dev, SI4126_PHASE_DET_GAIN, 0); - adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_N_DIV, - (chan == 14 ? - 2110 : (2033 + (chan * 5)))); - adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_N_DIV, 1496); - adm8211_rf_write_syn_rfmd2948(dev, SI4126_RF2_R_DIV, 44); - adm8211_rf_write_syn_rfmd2948(dev, SI4126_IF_R_DIV, 44); - break; - - case ADM8211_MAX2820: - adm8211_rf_write_syn_max2820(dev, 0x3, - (chan == 14 ? 0x054 : (0x7 + (chan * 5)))); - break; - - case ADM8211_AL2210L: - adm8211_rf_write_syn_al2210l(dev, 0x0, - (chan == 14 ? 0x229B4 : (0x22967 + (chan * 5)))); - break; - - default: - printk(KERN_DEBUG "%s: unsupported transceiver type %d\n", - wiphy_name(dev->wiphy), priv->transceiver_type); - break; - } - - /* write BBP regs */ - if (priv->bbp_type == ADM8211_TYPE_RFMD) { - - /* SMC 2635W specific? adm8211b doesn't use the 2948 though.. */ - /* TODO: remove if SMC 2635W doesn't need this */ - if (priv->transceiver_type == ADM8211_RFMD2948) { - reg = ADM8211_CSR_READ(GPIO); - reg &= 0xfffc0000; - reg |= ADM8211_CSR_GPIO_EN0; - if (chan != 14) - reg |= ADM8211_CSR_GPIO_O0; - ADM8211_CSR_WRITE(GPIO, reg); - } - - if (priv->transceiver_type == ADM8211_RFMD2958) { - /* set PCNT2 */ - adm8211_rf_write_syn_rfmd2958(dev, 0x0B, 0x07100); - /* set PCNT1 P_DESIRED/MID_BIAS */ - reg = le16_to_cpu(priv->eeprom->cr49); - reg >>= 13; - reg <<= 15; - reg |= ant_power << 9; - adm8211_rf_write_syn_rfmd2958(dev, 0x0A, reg); - /* set TXRX TX_GAIN */ - adm8211_rf_write_syn_rfmd2958(dev, 0x09, 0x00050 | - (priv->pdev->revision < ADM8211_REV_CA ? tx_power : 0)); - } else { - reg = ADM8211_CSR_READ(PLCPHD); - reg &= 0xff00ffff; - reg |= tx_power << 18; - ADM8211_CSR_WRITE(PLCPHD, reg); - } - - ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_SELRF | - ADM8211_SYNRF_PE1 | ADM8211_SYNRF_PHYRST); - ADM8211_CSR_READ(SYNRF); - msleep(30); - - /* RF3000 BBP */ - if (priv->transceiver_type != ADM8211_RFMD2958) - adm8211_write_bbp(dev, RF3000_TX_VAR_GAIN__TX_LEN_EXT, - tx_power<<2); - adm8211_write_bbp(dev, RF3000_LOW_GAIN_CALIB, lpf_cutoff); - adm8211_write_bbp(dev, RF3000_HIGH_GAIN_CALIB, lnags_thresh); - adm8211_write_bbp(dev, 0x1c, priv->pdev->revision == ADM8211_REV_BA ? - priv->eeprom->cr28 : 0); - adm8211_write_bbp(dev, 0x1d, priv->eeprom->cr29); - - ADM8211_CSR_WRITE(SYNRF, 0); - - /* Nothing to do for ADMtek BBP */ - } else if (priv->bbp_type != ADM8211_TYPE_ADMTEK) - printk(KERN_DEBUG "%s: unsupported BBP type %d\n", - wiphy_name(dev->wiphy), priv->bbp_type); - - ADM8211_RESTORE(); - - /* update current channel for adhoc (and maybe AP mode) */ - reg = ADM8211_CSR_READ(CAP0); - reg &= ~0xF; - reg |= chan; - ADM8211_CSR_WRITE(CAP0, reg); - - return 0; -} - -static void adm8211_update_mode(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - - ADM8211_IDLE(); - - priv->soft_rx_crc = 0; - switch (priv->mode) { - case NL80211_IFTYPE_STATION: - priv->nar &= ~(ADM8211_NAR_PR | ADM8211_NAR_EA); - priv->nar |= ADM8211_NAR_ST | ADM8211_NAR_SR; - break; - case NL80211_IFTYPE_ADHOC: - priv->nar &= ~ADM8211_NAR_PR; - priv->nar |= ADM8211_NAR_EA | ADM8211_NAR_ST | ADM8211_NAR_SR; - - /* don't trust the error bits on rev 0x20 and up in adhoc */ - if (priv->pdev->revision >= ADM8211_REV_BA) - priv->soft_rx_crc = 1; - break; - case NL80211_IFTYPE_MONITOR: - priv->nar &= ~(ADM8211_NAR_EA | ADM8211_NAR_ST); - priv->nar |= ADM8211_NAR_PR | ADM8211_NAR_SR; - break; - } - - ADM8211_RESTORE(); -} - -static void adm8211_hw_init_syn(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - - switch (priv->transceiver_type) { - case ADM8211_RFMD2958: - case ADM8211_RFMD2958_RF3000_CONTROL_POWER: - /* comments taken from ADMtek vendor driver */ - - /* Reset RF2958 after power on */ - adm8211_rf_write_syn_rfmd2958(dev, 0x1F, 0x00000); - /* Initialize RF VCO Core Bias to maximum */ - adm8211_rf_write_syn_rfmd2958(dev, 0x0C, 0x3001F); - /* Initialize IF PLL */ - adm8211_rf_write_syn_rfmd2958(dev, 0x01, 0x29C03); - /* Initialize IF PLL Coarse Tuning */ - adm8211_rf_write_syn_rfmd2958(dev, 0x03, 0x1FF6F); - /* Initialize RF PLL */ - adm8211_rf_write_syn_rfmd2958(dev, 0x04, 0x29403); - /* Initialize RF PLL Coarse Tuning */ - adm8211_rf_write_syn_rfmd2958(dev, 0x07, 0x1456F); - /* Initialize TX gain and filter BW (R9) */ - adm8211_rf_write_syn_rfmd2958(dev, 0x09, - (priv->transceiver_type == ADM8211_RFMD2958 ? - 0x10050 : 0x00050)); - /* Initialize CAL register */ - adm8211_rf_write_syn_rfmd2958(dev, 0x08, 0x3FFF8); - break; - - case ADM8211_MAX2820: - adm8211_rf_write_syn_max2820(dev, 0x1, 0x01E); - adm8211_rf_write_syn_max2820(dev, 0x2, 0x001); - adm8211_rf_write_syn_max2820(dev, 0x3, 0x054); - adm8211_rf_write_syn_max2820(dev, 0x4, 0x310); - adm8211_rf_write_syn_max2820(dev, 0x5, 0x000); - break; - - case ADM8211_AL2210L: - adm8211_rf_write_syn_al2210l(dev, 0x0, 0x0196C); - adm8211_rf_write_syn_al2210l(dev, 0x1, 0x007CB); - adm8211_rf_write_syn_al2210l(dev, 0x2, 0x3582F); - adm8211_rf_write_syn_al2210l(dev, 0x3, 0x010A9); - adm8211_rf_write_syn_al2210l(dev, 0x4, 0x77280); - adm8211_rf_write_syn_al2210l(dev, 0x5, 0x45641); - adm8211_rf_write_syn_al2210l(dev, 0x6, 0xEA130); - adm8211_rf_write_syn_al2210l(dev, 0x7, 0x80000); - adm8211_rf_write_syn_al2210l(dev, 0x8, 0x7850F); - adm8211_rf_write_syn_al2210l(dev, 0x9, 0xF900C); - adm8211_rf_write_syn_al2210l(dev, 0xA, 0x00000); - adm8211_rf_write_syn_al2210l(dev, 0xB, 0x00000); - break; - - case ADM8211_RFMD2948: - default: - break; - } -} - -static int adm8211_hw_init_bbp(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg; - - /* write addresses */ - if (priv->bbp_type == ADM8211_TYPE_INTERSIL) { - ADM8211_CSR_WRITE(MMIWA, 0x100E0C0A); - ADM8211_CSR_WRITE(MMIRD0, 0x00007C7E); - ADM8211_CSR_WRITE(MMIRD1, 0x00100000); - } else if (priv->bbp_type == ADM8211_TYPE_RFMD || - priv->bbp_type == ADM8211_TYPE_ADMTEK) { - /* check specific BBP type */ - switch (priv->specific_bbptype) { - case ADM8211_BBP_RFMD3000: - case ADM8211_BBP_RFMD3002: - ADM8211_CSR_WRITE(MMIWA, 0x00009101); - ADM8211_CSR_WRITE(MMIRD0, 0x00000301); - break; - - case ADM8211_BBP_ADM8011: - ADM8211_CSR_WRITE(MMIWA, 0x00008903); - ADM8211_CSR_WRITE(MMIRD0, 0x00001716); - - reg = ADM8211_CSR_READ(BBPCTL); - reg &= ~ADM8211_BBPCTL_TYPE; - reg |= 0x5 << 18; - ADM8211_CSR_WRITE(BBPCTL, reg); - break; - } - - switch (priv->pdev->revision) { - case ADM8211_REV_CA: - if (priv->transceiver_type == ADM8211_RFMD2958 || - priv->transceiver_type == ADM8211_RFMD2958_RF3000_CONTROL_POWER || - priv->transceiver_type == ADM8211_RFMD2948) - ADM8211_CSR_WRITE(SYNCTL, 0x1 << 22); - else if (priv->transceiver_type == ADM8211_MAX2820 || - priv->transceiver_type == ADM8211_AL2210L) - ADM8211_CSR_WRITE(SYNCTL, 0x3 << 22); - break; - - case ADM8211_REV_BA: - reg = ADM8211_CSR_READ(MMIRD1); - reg &= 0x0000FFFF; - reg |= 0x7e100000; - ADM8211_CSR_WRITE(MMIRD1, reg); - break; - - case ADM8211_REV_AB: - case ADM8211_REV_AF: - default: - ADM8211_CSR_WRITE(MMIRD1, 0x7e100000); - break; - } - - /* For RFMD */ - ADM8211_CSR_WRITE(MACTEST, 0x800); - } - - adm8211_hw_init_syn(dev); - - /* Set RF Power control IF pin to PE1+PHYRST# */ - ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_SELRF | - ADM8211_SYNRF_PE1 | ADM8211_SYNRF_PHYRST); - ADM8211_CSR_READ(SYNRF); - msleep(20); - - /* write BBP regs */ - if (priv->bbp_type == ADM8211_TYPE_RFMD) { - /* RF3000 BBP */ - /* another set: - * 11: c8 - * 14: 14 - * 15: 50 (chan 1..13; chan 14: d0) - * 1c: 00 - * 1d: 84 - */ - adm8211_write_bbp(dev, RF3000_CCA_CTRL, 0x80); - /* antenna selection: diversity */ - adm8211_write_bbp(dev, RF3000_DIVERSITY__RSSI, 0x80); - adm8211_write_bbp(dev, RF3000_TX_VAR_GAIN__TX_LEN_EXT, 0x74); - adm8211_write_bbp(dev, RF3000_LOW_GAIN_CALIB, 0x38); - adm8211_write_bbp(dev, RF3000_HIGH_GAIN_CALIB, 0x40); - - if (priv->eeprom->major_version < 2) { - adm8211_write_bbp(dev, 0x1c, 0x00); - adm8211_write_bbp(dev, 0x1d, 0x80); - } else { - if (priv->pdev->revision == ADM8211_REV_BA) - adm8211_write_bbp(dev, 0x1c, priv->eeprom->cr28); - else - adm8211_write_bbp(dev, 0x1c, 0x00); - - adm8211_write_bbp(dev, 0x1d, priv->eeprom->cr29); - } - } else if (priv->bbp_type == ADM8211_TYPE_ADMTEK) { - /* reset baseband */ - adm8211_write_bbp(dev, 0x00, 0xFF); - /* antenna selection: diversity */ - adm8211_write_bbp(dev, 0x07, 0x0A); - - /* TODO: find documentation for this */ - switch (priv->transceiver_type) { - case ADM8211_RFMD2958: - case ADM8211_RFMD2958_RF3000_CONTROL_POWER: - adm8211_write_bbp(dev, 0x00, 0x00); - adm8211_write_bbp(dev, 0x01, 0x00); - adm8211_write_bbp(dev, 0x02, 0x00); - adm8211_write_bbp(dev, 0x03, 0x00); - adm8211_write_bbp(dev, 0x06, 0x0f); - adm8211_write_bbp(dev, 0x09, 0x00); - adm8211_write_bbp(dev, 0x0a, 0x00); - adm8211_write_bbp(dev, 0x0b, 0x00); - adm8211_write_bbp(dev, 0x0c, 0x00); - adm8211_write_bbp(dev, 0x0f, 0xAA); - adm8211_write_bbp(dev, 0x10, 0x8c); - adm8211_write_bbp(dev, 0x11, 0x43); - adm8211_write_bbp(dev, 0x18, 0x40); - adm8211_write_bbp(dev, 0x20, 0x23); - adm8211_write_bbp(dev, 0x21, 0x02); - adm8211_write_bbp(dev, 0x22, 0x28); - adm8211_write_bbp(dev, 0x23, 0x30); - adm8211_write_bbp(dev, 0x24, 0x2d); - adm8211_write_bbp(dev, 0x28, 0x35); - adm8211_write_bbp(dev, 0x2a, 0x8c); - adm8211_write_bbp(dev, 0x2b, 0x81); - adm8211_write_bbp(dev, 0x2c, 0x44); - adm8211_write_bbp(dev, 0x2d, 0x0A); - adm8211_write_bbp(dev, 0x29, 0x40); - adm8211_write_bbp(dev, 0x60, 0x08); - adm8211_write_bbp(dev, 0x64, 0x01); - break; - - case ADM8211_MAX2820: - adm8211_write_bbp(dev, 0x00, 0x00); - adm8211_write_bbp(dev, 0x01, 0x00); - adm8211_write_bbp(dev, 0x02, 0x00); - adm8211_write_bbp(dev, 0x03, 0x00); - adm8211_write_bbp(dev, 0x06, 0x0f); - adm8211_write_bbp(dev, 0x09, 0x05); - adm8211_write_bbp(dev, 0x0a, 0x02); - adm8211_write_bbp(dev, 0x0b, 0x00); - adm8211_write_bbp(dev, 0x0c, 0x0f); - adm8211_write_bbp(dev, 0x0f, 0x55); - adm8211_write_bbp(dev, 0x10, 0x8d); - adm8211_write_bbp(dev, 0x11, 0x43); - adm8211_write_bbp(dev, 0x18, 0x4a); - adm8211_write_bbp(dev, 0x20, 0x20); - adm8211_write_bbp(dev, 0x21, 0x02); - adm8211_write_bbp(dev, 0x22, 0x23); - adm8211_write_bbp(dev, 0x23, 0x30); - adm8211_write_bbp(dev, 0x24, 0x2d); - adm8211_write_bbp(dev, 0x2a, 0x8c); - adm8211_write_bbp(dev, 0x2b, 0x81); - adm8211_write_bbp(dev, 0x2c, 0x44); - adm8211_write_bbp(dev, 0x29, 0x4a); - adm8211_write_bbp(dev, 0x60, 0x2b); - adm8211_write_bbp(dev, 0x64, 0x01); - break; - - case ADM8211_AL2210L: - adm8211_write_bbp(dev, 0x00, 0x00); - adm8211_write_bbp(dev, 0x01, 0x00); - adm8211_write_bbp(dev, 0x02, 0x00); - adm8211_write_bbp(dev, 0x03, 0x00); - adm8211_write_bbp(dev, 0x06, 0x0f); - adm8211_write_bbp(dev, 0x07, 0x05); - adm8211_write_bbp(dev, 0x08, 0x03); - adm8211_write_bbp(dev, 0x09, 0x00); - adm8211_write_bbp(dev, 0x0a, 0x00); - adm8211_write_bbp(dev, 0x0b, 0x00); - adm8211_write_bbp(dev, 0x0c, 0x10); - adm8211_write_bbp(dev, 0x0f, 0x55); - adm8211_write_bbp(dev, 0x10, 0x8d); - adm8211_write_bbp(dev, 0x11, 0x43); - adm8211_write_bbp(dev, 0x18, 0x4a); - adm8211_write_bbp(dev, 0x20, 0x20); - adm8211_write_bbp(dev, 0x21, 0x02); - adm8211_write_bbp(dev, 0x22, 0x23); - adm8211_write_bbp(dev, 0x23, 0x30); - adm8211_write_bbp(dev, 0x24, 0x2d); - adm8211_write_bbp(dev, 0x2a, 0xaa); - adm8211_write_bbp(dev, 0x2b, 0x81); - adm8211_write_bbp(dev, 0x2c, 0x44); - adm8211_write_bbp(dev, 0x29, 0xfa); - adm8211_write_bbp(dev, 0x60, 0x2d); - adm8211_write_bbp(dev, 0x64, 0x01); - break; - - case ADM8211_RFMD2948: - break; - - default: - printk(KERN_DEBUG "%s: unsupported transceiver %d\n", - wiphy_name(dev->wiphy), priv->transceiver_type); - break; - } - } else - printk(KERN_DEBUG "%s: unsupported BBP %d\n", - wiphy_name(dev->wiphy), priv->bbp_type); - - ADM8211_CSR_WRITE(SYNRF, 0); - - /* Set RF CAL control source to MAC control */ - reg = ADM8211_CSR_READ(SYNCTL); - reg |= ADM8211_SYNCTL_SELCAL; - ADM8211_CSR_WRITE(SYNCTL, reg); - - return 0; -} - -/* configures hw beacons/probe responses */ -static int adm8211_set_rate(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg; - int i = 0; - u8 rate_buf[12] = {0}; - - /* write supported rates */ - if (priv->pdev->revision != ADM8211_REV_BA) { - rate_buf[0] = ARRAY_SIZE(adm8211_rates); - for (i = 0; i < ARRAY_SIZE(adm8211_rates); i++) - rate_buf[i + 1] = (adm8211_rates[i].bitrate / 5) | 0x80; - } else { - /* workaround for rev BA specific bug */ - rate_buf[0] = 0x04; - rate_buf[1] = 0x82; - rate_buf[2] = 0x04; - rate_buf[3] = 0x0b; - rate_buf[4] = 0x16; - } - - adm8211_write_sram_bytes(dev, ADM8211_SRAM_SUPP_RATE, rate_buf, - ARRAY_SIZE(adm8211_rates) + 1); - - reg = ADM8211_CSR_READ(PLCPHD) & 0x00FFFFFF; /* keep bits 0-23 */ - reg |= 1 << 15; /* short preamble */ - reg |= 110 << 24; - ADM8211_CSR_WRITE(PLCPHD, reg); - - /* MTMLT = 512 TU (max TX MSDU lifetime) - * BCNTSIG = plcp_signal (beacon, probe resp, and atim TX rate) - * SRTYLIM = 224 (short retry limit, TX header value is default) */ - ADM8211_CSR_WRITE(TXLMT, (512 << 16) | (110 << 8) | (224 << 0)); - - return 0; -} - -static void adm8211_hw_init(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg; - u8 cline; - - reg = ADM8211_CSR_READ(PAR); - reg |= ADM8211_PAR_MRLE | ADM8211_PAR_MRME; - reg &= ~(ADM8211_PAR_BAR | ADM8211_PAR_CAL); - - if (!pci_set_mwi(priv->pdev)) { - reg |= 0x1 << 24; - pci_read_config_byte(priv->pdev, PCI_CACHE_LINE_SIZE, &cline); - - switch (cline) { - case 0x8: reg |= (0x1 << 14); - break; - case 0x16: reg |= (0x2 << 14); - break; - case 0x32: reg |= (0x3 << 14); - break; - default: reg |= (0x0 << 14); - break; - } - } - - ADM8211_CSR_WRITE(PAR, reg); - - reg = ADM8211_CSR_READ(CSR_TEST1); - reg &= ~(0xF << 28); - reg |= (1 << 28) | (1 << 31); - ADM8211_CSR_WRITE(CSR_TEST1, reg); - - /* lose link after 4 lost beacons */ - reg = (0x04 << 21) | ADM8211_WCSR_TSFTWE | ADM8211_WCSR_LSOE; - ADM8211_CSR_WRITE(WCSR, reg); - - /* Disable APM, enable receive FIFO threshold, and set drain receive - * threshold to store-and-forward */ - reg = ADM8211_CSR_READ(CMDR); - reg &= ~(ADM8211_CMDR_APM | ADM8211_CMDR_DRT); - reg |= ADM8211_CMDR_RTE | ADM8211_CMDR_DRT_SF; - ADM8211_CSR_WRITE(CMDR, reg); - - adm8211_set_rate(dev); - - /* 4-bit values: - * PWR1UP = 8 * 2 ms - * PWR0PAPE = 8 us or 5 us - * PWR1PAPE = 1 us or 3 us - * PWR0TRSW = 5 us - * PWR1TRSW = 12 us - * PWR0PE2 = 13 us - * PWR1PE2 = 1 us - * PWR0TXPE = 8 or 6 */ - if (priv->pdev->revision < ADM8211_REV_CA) - ADM8211_CSR_WRITE(TOFS2, 0x8815cd18); - else - ADM8211_CSR_WRITE(TOFS2, 0x8535cd16); - - /* Enable store and forward for transmit */ - priv->nar = ADM8211_NAR_SF | ADM8211_NAR_PB; - ADM8211_CSR_WRITE(NAR, priv->nar); - - /* Reset RF */ - ADM8211_CSR_WRITE(SYNRF, ADM8211_SYNRF_RADIO); - ADM8211_CSR_READ(SYNRF); - msleep(10); - ADM8211_CSR_WRITE(SYNRF, 0); - ADM8211_CSR_READ(SYNRF); - msleep(5); - - /* Set CFP Max Duration to 0x10 TU */ - reg = ADM8211_CSR_READ(CFPP); - reg &= ~(0xffff << 8); - reg |= 0x0010 << 8; - ADM8211_CSR_WRITE(CFPP, reg); - - /* USCNT = 0x16 (number of system clocks, 22 MHz, in 1us - * TUCNT = 0x3ff - Tu counter 1024 us */ - ADM8211_CSR_WRITE(TOFS0, (0x16 << 24) | 0x3ff); - - /* SLOT=20 us, SIFS=110 cycles of 22 MHz (5 us), - * DIFS=50 us, EIFS=100 us */ - if (priv->pdev->revision < ADM8211_REV_CA) - ADM8211_CSR_WRITE(IFST, (20 << 23) | (110 << 15) | - (50 << 9) | 100); - else - ADM8211_CSR_WRITE(IFST, (20 << 23) | (24 << 15) | - (50 << 9) | 100); - - /* PCNT = 1 (MAC idle time awake/sleep, unit S) - * RMRD = 2346 * 8 + 1 us (max RX duration) */ - ADM8211_CSR_WRITE(RMD, (1 << 16) | 18769); - - /* MART=65535 us, MIRT=256 us, TSFTOFST=0 us */ - ADM8211_CSR_WRITE(RSPT, 0xffffff00); - - /* Initialize BBP (and SYN) */ - adm8211_hw_init_bbp(dev); - - /* make sure interrupts are off */ - ADM8211_CSR_WRITE(IER, 0); - - /* ACK interrupts */ - ADM8211_CSR_WRITE(STSR, ADM8211_CSR_READ(STSR)); - - /* Setup WEP (turns it off for now) */ - reg = ADM8211_CSR_READ(MACTEST); - reg &= ~(7 << 20); - ADM8211_CSR_WRITE(MACTEST, reg); - - reg = ADM8211_CSR_READ(WEPCTL); - reg &= ~ADM8211_WEPCTL_WEPENABLE; - reg |= ADM8211_WEPCTL_WEPRXBYP; - ADM8211_CSR_WRITE(WEPCTL, reg); - - /* Clear the missed-packet counter. */ - ADM8211_CSR_READ(LPC); -} - -static int adm8211_hw_reset(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg, tmp; - int timeout = 100; - - /* Power-on issue */ - /* TODO: check if this is necessary */ - ADM8211_CSR_WRITE(FRCTL, 0); - - /* Reset the chip */ - tmp = ADM8211_CSR_READ(PAR); - ADM8211_CSR_WRITE(PAR, ADM8211_PAR_SWR); - - while ((ADM8211_CSR_READ(PAR) & ADM8211_PAR_SWR) && timeout--) - msleep(50); - - if (timeout <= 0) - return -ETIMEDOUT; - - ADM8211_CSR_WRITE(PAR, tmp); - - if (priv->pdev->revision == ADM8211_REV_BA && - (priv->transceiver_type == ADM8211_RFMD2958_RF3000_CONTROL_POWER || - priv->transceiver_type == ADM8211_RFMD2958)) { - reg = ADM8211_CSR_READ(CSR_TEST1); - reg |= (1 << 4) | (1 << 5); - ADM8211_CSR_WRITE(CSR_TEST1, reg); - } else if (priv->pdev->revision == ADM8211_REV_CA) { - reg = ADM8211_CSR_READ(CSR_TEST1); - reg &= ~((1 << 4) | (1 << 5)); - ADM8211_CSR_WRITE(CSR_TEST1, reg); - } - - ADM8211_CSR_WRITE(FRCTL, 0); - - reg = ADM8211_CSR_READ(CSR_TEST0); - reg |= ADM8211_CSR_TEST0_EPRLD; /* EEPROM Recall */ - ADM8211_CSR_WRITE(CSR_TEST0, reg); - - adm8211_clear_sram(dev); - - return 0; -} - -static u64 adm8211_get_tsft(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - u32 tsftl; - u64 tsft; - - tsftl = ADM8211_CSR_READ(TSFTL); - tsft = ADM8211_CSR_READ(TSFTH); - tsft <<= 32; - tsft |= tsftl; - - return tsft; -} - -static void adm8211_set_interval(struct ieee80211_hw *dev, - unsigned short bi, unsigned short li) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg; - - /* BP (beacon interval) = data->beacon_interval - * LI (listen interval) = data->listen_interval (in beacon intervals) */ - reg = (bi << 16) | li; - ADM8211_CSR_WRITE(BPLI, reg); -} - -static void adm8211_set_bssid(struct ieee80211_hw *dev, const u8 *bssid) -{ - struct adm8211_priv *priv = dev->priv; - u32 reg; - - ADM8211_CSR_WRITE(BSSID0, le32_to_cpu(*(__le32 *)bssid)); - reg = ADM8211_CSR_READ(ABDA1); - reg &= 0x0000ffff; - reg |= (bssid[4] << 16) | (bssid[5] << 24); - ADM8211_CSR_WRITE(ABDA1, reg); -} - -static int adm8211_config(struct ieee80211_hw *dev, u32 changed) -{ - struct adm8211_priv *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - - if (channel != priv->channel) { - priv->channel = channel; - adm8211_rf_set_channel(dev, priv->channel); - } - - return 0; -} - -static void adm8211_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, - u32 changes) -{ - struct adm8211_priv *priv = dev->priv; - - if (!(changes & BSS_CHANGED_BSSID)) - return; - - if (memcmp(conf->bssid, priv->bssid, ETH_ALEN)) { - adm8211_set_bssid(dev, conf->bssid); - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - } -} - -static u64 adm8211_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - unsigned int bit_nr, i; - u32 mc_filter[2]; - - mc_filter[1] = mc_filter[0] = 0; - - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - - bit_nr &= 0x3F; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - mclist = mclist->next; - } - - return mc_filter[0] | ((u64)(mc_filter[1]) << 32); -} - -static void adm8211_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - static const u8 bcast[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - struct adm8211_priv *priv = dev->priv; - unsigned int new_flags; - u32 mc_filter[2]; - - mc_filter[0] = multicast; - mc_filter[1] = multicast >> 32; - - new_flags = 0; - - if (*total_flags & FIF_PROMISC_IN_BSS) { - new_flags |= FIF_PROMISC_IN_BSS; - priv->nar |= ADM8211_NAR_PR; - priv->nar &= ~ADM8211_NAR_MM; - mc_filter[1] = mc_filter[0] = ~0; - } else if (*total_flags & FIF_ALLMULTI || multicast == ~(0ULL)) { - new_flags |= FIF_ALLMULTI; - priv->nar &= ~ADM8211_NAR_PR; - priv->nar |= ADM8211_NAR_MM; - mc_filter[1] = mc_filter[0] = ~0; - } else { - priv->nar &= ~(ADM8211_NAR_MM | ADM8211_NAR_PR); - } - - ADM8211_IDLE_RX(); - - ADM8211_CSR_WRITE(MAR0, mc_filter[0]); - ADM8211_CSR_WRITE(MAR1, mc_filter[1]); - ADM8211_CSR_READ(NAR); - - if (priv->nar & ADM8211_NAR_PR) - dev->flags |= IEEE80211_HW_RX_INCLUDES_FCS; - else - dev->flags &= ~IEEE80211_HW_RX_INCLUDES_FCS; - - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - adm8211_set_bssid(dev, bcast); - else - adm8211_set_bssid(dev, priv->bssid); - - ADM8211_RESTORE(); - - *total_flags = new_flags; -} - -static int adm8211_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct adm8211_priv *priv = dev->priv; - if (priv->mode != NL80211_IFTYPE_MONITOR) - return -EOPNOTSUPP; - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - priv->mode = conf->type; - break; - default: - return -EOPNOTSUPP; - } - - ADM8211_IDLE(); - - ADM8211_CSR_WRITE(PAR0, le32_to_cpu(*(__le32 *)conf->mac_addr)); - ADM8211_CSR_WRITE(PAR1, le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); - - adm8211_update_mode(dev); - - ADM8211_RESTORE(); - - return 0; -} - -static void adm8211_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct adm8211_priv *priv = dev->priv; - priv->mode = NL80211_IFTYPE_MONITOR; -} - -static int adm8211_init_rings(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - struct adm8211_desc *desc = NULL; - struct adm8211_rx_ring_info *rx_info; - struct adm8211_tx_ring_info *tx_info; - unsigned int i; - - for (i = 0; i < priv->rx_ring_size; i++) { - desc = &priv->rx_ring[i]; - desc->status = 0; - desc->length = cpu_to_le32(RX_PKT_SIZE); - priv->rx_buffers[i].skb = NULL; - } - /* Mark the end of RX ring; hw returns to base address after this - * descriptor */ - desc->length |= cpu_to_le32(RDES1_CONTROL_RER); - - for (i = 0; i < priv->rx_ring_size; i++) { - desc = &priv->rx_ring[i]; - rx_info = &priv->rx_buffers[i]; - - rx_info->skb = dev_alloc_skb(RX_PKT_SIZE); - if (rx_info->skb == NULL) - break; - rx_info->mapping = pci_map_single(priv->pdev, - skb_tail_pointer(rx_info->skb), - RX_PKT_SIZE, - PCI_DMA_FROMDEVICE); - desc->buffer1 = cpu_to_le32(rx_info->mapping); - desc->status = cpu_to_le32(RDES0_STATUS_OWN | RDES0_STATUS_SQL); - } - - /* Setup TX ring. TX buffers descriptors will be filled in as needed */ - for (i = 0; i < priv->tx_ring_size; i++) { - desc = &priv->tx_ring[i]; - tx_info = &priv->tx_buffers[i]; - - tx_info->skb = NULL; - tx_info->mapping = 0; - desc->status = 0; - } - desc->length = cpu_to_le32(TDES1_CONTROL_TER); - - priv->cur_rx = priv->cur_tx = priv->dirty_tx = 0; - ADM8211_CSR_WRITE(RDB, priv->rx_ring_dma); - ADM8211_CSR_WRITE(TDBD, priv->tx_ring_dma); - - return 0; -} - -static void adm8211_free_rings(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - unsigned int i; - - for (i = 0; i < priv->rx_ring_size; i++) { - if (!priv->rx_buffers[i].skb) - continue; - - pci_unmap_single( - priv->pdev, - priv->rx_buffers[i].mapping, - RX_PKT_SIZE, PCI_DMA_FROMDEVICE); - - dev_kfree_skb(priv->rx_buffers[i].skb); - } - - for (i = 0; i < priv->tx_ring_size; i++) { - if (!priv->tx_buffers[i].skb) - continue; - - pci_unmap_single(priv->pdev, - priv->tx_buffers[i].mapping, - priv->tx_buffers[i].skb->len, - PCI_DMA_TODEVICE); - - dev_kfree_skb(priv->tx_buffers[i].skb); - } -} - -static int adm8211_start(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - int retval; - - /* Power up MAC and RF chips */ - retval = adm8211_hw_reset(dev); - if (retval) { - printk(KERN_ERR "%s: hardware reset failed\n", - wiphy_name(dev->wiphy)); - goto fail; - } - - retval = adm8211_init_rings(dev); - if (retval) { - printk(KERN_ERR "%s: failed to initialize rings\n", - wiphy_name(dev->wiphy)); - goto fail; - } - - /* Init hardware */ - adm8211_hw_init(dev); - adm8211_rf_set_channel(dev, priv->channel); - - retval = request_irq(priv->pdev->irq, &adm8211_interrupt, - IRQF_SHARED, "adm8211", dev); - if (retval) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); - goto fail; - } - - ADM8211_CSR_WRITE(IER, ADM8211_IER_NIE | ADM8211_IER_AIE | - ADM8211_IER_RCIE | ADM8211_IER_TCIE | - ADM8211_IER_TDUIE | ADM8211_IER_GPTIE); - priv->mode = NL80211_IFTYPE_MONITOR; - adm8211_update_mode(dev); - ADM8211_CSR_WRITE(RDR, 0); - - adm8211_set_interval(dev, 100, 10); - return 0; - -fail: - return retval; -} - -static void adm8211_stop(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - priv->nar = 0; - ADM8211_CSR_WRITE(NAR, 0); - ADM8211_CSR_WRITE(IER, 0); - ADM8211_CSR_READ(NAR); - - free_irq(priv->pdev->irq, dev); - - adm8211_free_rings(dev); -} - -static void adm8211_calc_durations(int *dur, int *plcp, size_t payload_len, int len, - int plcp_signal, int short_preamble) -{ - /* Alternative calculation from NetBSD: */ - -/* IEEE 802.11b durations for DSSS PHY in microseconds */ -#define IEEE80211_DUR_DS_LONG_PREAMBLE 144 -#define IEEE80211_DUR_DS_SHORT_PREAMBLE 72 -#define IEEE80211_DUR_DS_FAST_PLCPHDR 24 -#define IEEE80211_DUR_DS_SLOW_PLCPHDR 48 -#define IEEE80211_DUR_DS_SLOW_ACK 112 -#define IEEE80211_DUR_DS_FAST_ACK 56 -#define IEEE80211_DUR_DS_SLOW_CTS 112 -#define IEEE80211_DUR_DS_FAST_CTS 56 -#define IEEE80211_DUR_DS_SLOT 20 -#define IEEE80211_DUR_DS_SIFS 10 - - int remainder; - - *dur = (80 * (24 + payload_len) + plcp_signal - 1) - / plcp_signal; - - if (plcp_signal <= PLCP_SIGNAL_2M) - /* 1-2Mbps WLAN: send ACK/CTS at 1Mbps */ - *dur += 3 * (IEEE80211_DUR_DS_SIFS + - IEEE80211_DUR_DS_SHORT_PREAMBLE + - IEEE80211_DUR_DS_FAST_PLCPHDR) + - IEEE80211_DUR_DS_SLOW_CTS + IEEE80211_DUR_DS_SLOW_ACK; - else - /* 5-11Mbps WLAN: send ACK/CTS at 2Mbps */ - *dur += 3 * (IEEE80211_DUR_DS_SIFS + - IEEE80211_DUR_DS_SHORT_PREAMBLE + - IEEE80211_DUR_DS_FAST_PLCPHDR) + - IEEE80211_DUR_DS_FAST_CTS + IEEE80211_DUR_DS_FAST_ACK; - - /* lengthen duration if long preamble */ - if (!short_preamble) - *dur += 3 * (IEEE80211_DUR_DS_LONG_PREAMBLE - - IEEE80211_DUR_DS_SHORT_PREAMBLE) + - 3 * (IEEE80211_DUR_DS_SLOW_PLCPHDR - - IEEE80211_DUR_DS_FAST_PLCPHDR); - - - *plcp = (80 * len) / plcp_signal; - remainder = (80 * len) % plcp_signal; - if (plcp_signal == PLCP_SIGNAL_11M && - remainder <= 30 && remainder > 0) - *plcp = (*plcp | 0x8000) + 1; - else if (remainder) - (*plcp)++; -} - -/* Transmit skb w/adm8211_tx_hdr (802.11 header created by hardware) */ -static void adm8211_tx_raw(struct ieee80211_hw *dev, struct sk_buff *skb, - u16 plcp_signal, - size_t hdrlen) -{ - struct adm8211_priv *priv = dev->priv; - unsigned long flags; - dma_addr_t mapping; - unsigned int entry; - u32 flag; - - mapping = pci_map_single(priv->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size / 2) - flag = TDES1_CONTROL_IC | TDES1_CONTROL_LS | TDES1_CONTROL_FS; - else - flag = TDES1_CONTROL_LS | TDES1_CONTROL_FS; - - if (priv->cur_tx - priv->dirty_tx == priv->tx_ring_size - 2) - ieee80211_stop_queue(dev, 0); - - entry = priv->cur_tx % priv->tx_ring_size; - - priv->tx_buffers[entry].skb = skb; - priv->tx_buffers[entry].mapping = mapping; - priv->tx_buffers[entry].hdrlen = hdrlen; - priv->tx_ring[entry].buffer1 = cpu_to_le32(mapping); - - if (entry == priv->tx_ring_size - 1) - flag |= TDES1_CONTROL_TER; - priv->tx_ring[entry].length = cpu_to_le32(flag | skb->len); - - /* Set TX rate (SIGNAL field in PLCP PPDU format) */ - flag = TDES0_CONTROL_OWN | (plcp_signal << 20) | 8 /* ? */; - priv->tx_ring[entry].status = cpu_to_le32(flag); - - priv->cur_tx++; - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Trigger transmit poll */ - ADM8211_CSR_WRITE(TDR, 0); -} - -/* Put adm8211_tx_hdr on skb and transmit */ -static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct adm8211_tx_hdr *txhdr; - size_t payload_len, hdrlen; - int plcp, dur, len, plcp_signal, short_preamble; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_rate *txrate = ieee80211_get_tx_rate(dev, info); - u8 rc_flags; - - rc_flags = info->control.rates[0].flags; - short_preamble = !!(rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE); - plcp_signal = txrate->bitrate; - - hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_hdrlen(hdr->frame_control); - memcpy(skb->cb, skb->data, hdrlen); - hdr = (struct ieee80211_hdr *)skb->cb; - skb_pull(skb, hdrlen); - payload_len = skb->len; - - txhdr = (struct adm8211_tx_hdr *) skb_push(skb, sizeof(*txhdr)); - memset(txhdr, 0, sizeof(*txhdr)); - memcpy(txhdr->da, ieee80211_get_DA(hdr), ETH_ALEN); - txhdr->signal = plcp_signal; - txhdr->frame_body_size = cpu_to_le16(payload_len); - txhdr->frame_control = hdr->frame_control; - - len = hdrlen + payload_len + FCS_LEN; - - txhdr->frag = cpu_to_le16(0x0FFF); - adm8211_calc_durations(&dur, &plcp, payload_len, - len, plcp_signal, short_preamble); - txhdr->plcp_frag_head_len = cpu_to_le16(plcp); - txhdr->plcp_frag_tail_len = cpu_to_le16(plcp); - txhdr->dur_frag_head = cpu_to_le16(dur); - txhdr->dur_frag_tail = cpu_to_le16(dur); - - txhdr->header_control = cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_EXTEND_HEADER); - - if (short_preamble) - txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_SHORT_PREAMBLE); - - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) - txhdr->header_control |= cpu_to_le16(ADM8211_TXHDRCTL_ENABLE_RTS); - - txhdr->retry_limit = info->control.rates[0].count; - - adm8211_tx_raw(dev, skb, plcp_signal, hdrlen); - - return NETDEV_TX_OK; -} - -static int adm8211_alloc_rings(struct ieee80211_hw *dev) -{ - struct adm8211_priv *priv = dev->priv; - unsigned int ring_size; - - priv->rx_buffers = kmalloc(sizeof(*priv->rx_buffers) * priv->rx_ring_size + - sizeof(*priv->tx_buffers) * priv->tx_ring_size, GFP_KERNEL); - if (!priv->rx_buffers) - return -ENOMEM; - - priv->tx_buffers = (void *)priv->rx_buffers + - sizeof(*priv->rx_buffers) * priv->rx_ring_size; - - /* Allocate TX/RX descriptors */ - ring_size = sizeof(struct adm8211_desc) * priv->rx_ring_size + - sizeof(struct adm8211_desc) * priv->tx_ring_size; - priv->rx_ring = pci_alloc_consistent(priv->pdev, ring_size, - &priv->rx_ring_dma); - - if (!priv->rx_ring) { - kfree(priv->rx_buffers); - priv->rx_buffers = NULL; - priv->tx_buffers = NULL; - return -ENOMEM; - } - - priv->tx_ring = (struct adm8211_desc *)(priv->rx_ring + - priv->rx_ring_size); - priv->tx_ring_dma = priv->rx_ring_dma + - sizeof(struct adm8211_desc) * priv->rx_ring_size; - - return 0; -} - -static const struct ieee80211_ops adm8211_ops = { - .tx = adm8211_tx, - .start = adm8211_start, - .stop = adm8211_stop, - .add_interface = adm8211_add_interface, - .remove_interface = adm8211_remove_interface, - .config = adm8211_config, - .bss_info_changed = adm8211_bss_info_changed, - .prepare_multicast = adm8211_prepare_multicast, - .configure_filter = adm8211_configure_filter, - .get_stats = adm8211_get_stats, - .get_tx_stats = adm8211_get_tx_stats, - .get_tsf = adm8211_get_tsft -}; - -static int __devinit adm8211_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct ieee80211_hw *dev; - struct adm8211_priv *priv; - unsigned long mem_addr, mem_len; - unsigned int io_addr, io_len; - int err; - u32 reg; - u8 perm_addr[ETH_ALEN]; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s (adm8211): Cannot enable new PCI device\n", - pci_name(pdev)); - return err; - } - - io_addr = pci_resource_start(pdev, 0); - io_len = pci_resource_len(pdev, 0); - mem_addr = pci_resource_start(pdev, 1); - mem_len = pci_resource_len(pdev, 1); - if (io_len < 256 || mem_len < 1024) { - printk(KERN_ERR "%s (adm8211): Too short PCI resources\n", - pci_name(pdev)); - goto err_disable_pdev; - } - - - /* check signature */ - pci_read_config_dword(pdev, 0x80 /* CR32 */, ®); - if (reg != ADM8211_SIG1 && reg != ADM8211_SIG2) { - printk(KERN_ERR "%s (adm8211): Invalid signature (0x%x)\n", - pci_name(pdev), reg); - goto err_disable_pdev; - } - - err = pci_request_regions(pdev, "adm8211"); - if (err) { - printk(KERN_ERR "%s (adm8211): Cannot obtain PCI resources\n", - pci_name(pdev)); - return err; /* someone else grabbed it? don't disable it */ - } - - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || - pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - printk(KERN_ERR "%s (adm8211): No suitable DMA available\n", - pci_name(pdev)); - goto err_free_reg; - } - - pci_set_master(pdev); - - dev = ieee80211_alloc_hw(sizeof(*priv), &adm8211_ops); - if (!dev) { - printk(KERN_ERR "%s (adm8211): ieee80211 alloc failed\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_free_reg; - } - priv = dev->priv; - priv->pdev = pdev; - - spin_lock_init(&priv->lock); - - SET_IEEE80211_DEV(dev, &pdev->dev); - - pci_set_drvdata(pdev, dev); - - priv->map = pci_iomap(pdev, 1, mem_len); - if (!priv->map) - priv->map = pci_iomap(pdev, 0, io_len); - - if (!priv->map) { - printk(KERN_ERR "%s (adm8211): Cannot map device memory\n", - pci_name(pdev)); - goto err_free_dev; - } - - priv->rx_ring_size = rx_ring_size; - priv->tx_ring_size = tx_ring_size; - - if (adm8211_alloc_rings(dev)) { - printk(KERN_ERR "%s (adm8211): Cannot allocate TX/RX ring\n", - pci_name(pdev)); - goto err_iounmap; - } - - *(__le32 *)perm_addr = cpu_to_le32(ADM8211_CSR_READ(PAR0)); - *(__le16 *)&perm_addr[4] = - cpu_to_le16(ADM8211_CSR_READ(PAR1) & 0xFFFF); - - if (!is_valid_ether_addr(perm_addr)) { - printk(KERN_WARNING "%s (adm8211): Invalid hwaddr in EEPROM!\n", - pci_name(pdev)); - random_ether_addr(perm_addr); - } - SET_IEEE80211_PERM_ADDR(dev, perm_addr); - - dev->extra_tx_headroom = sizeof(struct adm8211_tx_hdr); - /* dev->flags = IEEE80211_HW_RX_INCLUDES_FCS in promisc mode */ - dev->flags = IEEE80211_HW_SIGNAL_UNSPEC; - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - - dev->channel_change_time = 1000; - dev->max_signal = 100; /* FIXME: find better value */ - - dev->queues = 1; /* ADM8211C supports more, maybe ADM8211B too */ - - priv->retry_limit = 3; - priv->ant_power = 0x40; - priv->tx_power = 0x40; - priv->lpf_cutoff = 0xFF; - priv->lnags_threshold = 0xFF; - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - - /* Power-on issue. EEPROM won't read correctly without */ - if (pdev->revision >= ADM8211_REV_BA) { - ADM8211_CSR_WRITE(FRCTL, 0); - ADM8211_CSR_READ(FRCTL); - ADM8211_CSR_WRITE(FRCTL, 1); - ADM8211_CSR_READ(FRCTL); - msleep(100); - } - - err = adm8211_read_eeprom(dev); - if (err) { - printk(KERN_ERR "%s (adm8211): Can't alloc eeprom buffer\n", - pci_name(pdev)); - goto err_free_desc; - } - - priv->channel = 1; - - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "%s (adm8211): Cannot register device\n", - pci_name(pdev)); - goto err_free_desc; - } - - printk(KERN_INFO "%s: hwaddr %pM, Rev 0x%02x\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - pdev->revision); - - return 0; - - err_free_desc: - pci_free_consistent(pdev, - sizeof(struct adm8211_desc) * priv->rx_ring_size + - sizeof(struct adm8211_desc) * priv->tx_ring_size, - priv->rx_ring, priv->rx_ring_dma); - kfree(priv->rx_buffers); - - err_iounmap: - pci_iounmap(pdev, priv->map); - - err_free_dev: - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(dev); - - err_free_reg: - pci_release_regions(pdev); - - err_disable_pdev: - pci_disable_device(pdev); - return err; -} - - -static void __devexit adm8211_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct adm8211_priv *priv; - - if (!dev) - return; - - ieee80211_unregister_hw(dev); - - priv = dev->priv; - - pci_free_consistent(pdev, - sizeof(struct adm8211_desc) * priv->rx_ring_size + - sizeof(struct adm8211_desc) * priv->tx_ring_size, - priv->rx_ring, priv->rx_ring_dma); - - kfree(priv->rx_buffers); - kfree(priv->eeprom); - pci_iounmap(pdev, priv->map); - pci_release_regions(pdev); - pci_disable_device(pdev); - ieee80211_free_hw(dev); -} - - -#ifdef CONFIG_PM -static int adm8211_suspend(struct pci_dev *pdev, pm_message_t state) -{ - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int adm8211_resume(struct pci_dev *pdev) -{ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - return 0; -} -#endif /* CONFIG_PM */ - - -MODULE_DEVICE_TABLE(pci, adm8211_pci_id_table); - -/* TODO: implement enable_wake */ -static struct pci_driver adm8211_driver = { - .name = "adm8211", - .id_table = adm8211_pci_id_table, - .probe = adm8211_probe, - .remove = __devexit_p(adm8211_remove), -#ifdef CONFIG_PM - .suspend = adm8211_suspend, - .resume = adm8211_resume, -#endif /* CONFIG_PM */ -}; - - - -static int __init adm8211_init(void) -{ - return pci_register_driver(&adm8211_driver); -} - - -static void __exit adm8211_exit(void) -{ - pci_unregister_driver(&adm8211_driver); -} - - -module_init(adm8211_init); -module_exit(adm8211_exit); diff --git a/drivers/net/wireless/adm8211.h b/drivers/net/wireless/adm8211.h deleted file mode 100644 index b07e4d3a6b4d..000000000000 --- a/drivers/net/wireless/adm8211.h +++ /dev/null @@ -1,602 +0,0 @@ -#ifndef ADM8211_H -#define ADM8211_H - -/* ADM8211 Registers */ - -/* CR32 (SIG) signature */ -#define ADM8211_SIG1 0x82011317 /* ADM8211A */ -#define ADM8211_SIG2 0x82111317 /* ADM8211B/ADM8211C */ - -#define ADM8211_CSR_READ(r) ioread32(&priv->map->r) -#define ADM8211_CSR_WRITE(r, val) iowrite32((val), &priv->map->r) - -/* CSR (Host Control and Status Registers) */ -struct adm8211_csr { - __le32 PAR; /* 0x00 CSR0 */ - __le32 FRCTL; /* 0x04 CSR0A */ - __le32 TDR; /* 0x08 CSR1 */ - __le32 WTDP; /* 0x0C CSR1A */ - __le32 RDR; /* 0x10 CSR2 */ - __le32 WRDP; /* 0x14 CSR2A */ - __le32 RDB; /* 0x18 CSR3 */ - __le32 TDBH; /* 0x1C CSR3A */ - __le32 TDBD; /* 0x20 CSR4 */ - __le32 TDBP; /* 0x24 CSR4A */ - __le32 STSR; /* 0x28 CSR5 */ - __le32 TDBB; /* 0x2C CSR5A */ - __le32 NAR; /* 0x30 CSR6 */ - __le32 CSR6A; /* reserved */ - __le32 IER; /* 0x38 CSR7 */ - __le32 TKIPSCEP; /* 0x3C CSR7A */ - __le32 LPC; /* 0x40 CSR8 */ - __le32 CSR_TEST1; /* 0x44 CSR8A */ - __le32 SPR; /* 0x48 CSR9 */ - __le32 CSR_TEST0; /* 0x4C CSR9A */ - __le32 WCSR; /* 0x50 CSR10 */ - __le32 WPDR; /* 0x54 CSR10A */ - __le32 GPTMR; /* 0x58 CSR11 */ - __le32 GPIO; /* 0x5C CSR11A */ - __le32 BBPCTL; /* 0x60 CSR12 */ - __le32 SYNCTL; /* 0x64 CSR12A */ - __le32 PLCPHD; /* 0x68 CSR13 */ - __le32 MMIWA; /* 0x6C CSR13A */ - __le32 MMIRD0; /* 0x70 CSR14 */ - __le32 MMIRD1; /* 0x74 CSR14A */ - __le32 TXBR; /* 0x78 CSR15 */ - __le32 SYNDATA; /* 0x7C CSR15A */ - __le32 ALCS; /* 0x80 CSR16 */ - __le32 TOFS2; /* 0x84 CSR17 */ - __le32 CMDR; /* 0x88 CSR18 */ - __le32 PCIC; /* 0x8C CSR19 */ - __le32 PMCSR; /* 0x90 CSR20 */ - __le32 PAR0; /* 0x94 CSR21 */ - __le32 PAR1; /* 0x98 CSR22 */ - __le32 MAR0; /* 0x9C CSR23 */ - __le32 MAR1; /* 0xA0 CSR24 */ - __le32 ATIMDA0; /* 0xA4 CSR25 */ - __le32 ABDA1; /* 0xA8 CSR26 */ - __le32 BSSID0; /* 0xAC CSR27 */ - __le32 TXLMT; /* 0xB0 CSR28 */ - __le32 MIBCNT; /* 0xB4 CSR29 */ - __le32 BCNT; /* 0xB8 CSR30 */ - __le32 TSFTH; /* 0xBC CSR31 */ - __le32 TSC; /* 0xC0 CSR32 */ - __le32 SYNRF; /* 0xC4 CSR33 */ - __le32 BPLI; /* 0xC8 CSR34 */ - __le32 CAP0; /* 0xCC CSR35 */ - __le32 CAP1; /* 0xD0 CSR36 */ - __le32 RMD; /* 0xD4 CSR37 */ - __le32 CFPP; /* 0xD8 CSR38 */ - __le32 TOFS0; /* 0xDC CSR39 */ - __le32 TOFS1; /* 0xE0 CSR40 */ - __le32 IFST; /* 0xE4 CSR41 */ - __le32 RSPT; /* 0xE8 CSR42 */ - __le32 TSFTL; /* 0xEC CSR43 */ - __le32 WEPCTL; /* 0xF0 CSR44 */ - __le32 WESK; /* 0xF4 CSR45 */ - __le32 WEPCNT; /* 0xF8 CSR46 */ - __le32 MACTEST; /* 0xFC CSR47 */ - __le32 FER; /* 0x100 */ - __le32 FEMR; /* 0x104 */ - __le32 FPSR; /* 0x108 */ - __le32 FFER; /* 0x10C */ -} __attribute__ ((packed)); - -/* CSR0 - PAR (PCI Address Register) */ -#define ADM8211_PAR_MWIE (1 << 24) -#define ADM8211_PAR_MRLE (1 << 23) -#define ADM8211_PAR_MRME (1 << 21) -#define ADM8211_PAR_RAP ((1 << 18) | (1 << 17)) -#define ADM8211_PAR_CAL ((1 << 15) | (1 << 14)) -#define ADM8211_PAR_PBL 0x00003f00 -#define ADM8211_PAR_BLE (1 << 7) -#define ADM8211_PAR_DSL 0x0000007c -#define ADM8211_PAR_BAR (1 << 1) -#define ADM8211_PAR_SWR (1 << 0) - -/* CSR1 - FRCTL (Frame Control Register) */ -#define ADM8211_FRCTL_PWRMGT (1 << 31) -#define ADM8211_FRCTL_MAXPSP (1 << 27) -#define ADM8211_FRCTL_DRVPRSP (1 << 26) -#define ADM8211_FRCTL_DRVBCON (1 << 25) -#define ADM8211_FRCTL_AID 0x0000ffff -#define ADM8211_FRCTL_AID_ON 0x0000c000 - -/* CSR5 - STSR (Status Register) */ -#define ADM8211_STSR_PCF (1 << 31) -#define ADM8211_STSR_BCNTC (1 << 30) -#define ADM8211_STSR_GPINT (1 << 29) -#define ADM8211_STSR_LinkOff (1 << 28) -#define ADM8211_STSR_ATIMTC (1 << 27) -#define ADM8211_STSR_TSFTF (1 << 26) -#define ADM8211_STSR_TSCZ (1 << 25) -#define ADM8211_STSR_LinkOn (1 << 24) -#define ADM8211_STSR_SQL (1 << 23) -#define ADM8211_STSR_WEPTD (1 << 22) -#define ADM8211_STSR_ATIME (1 << 21) -#define ADM8211_STSR_TBTT (1 << 20) -#define ADM8211_STSR_NISS (1 << 16) -#define ADM8211_STSR_AISS (1 << 15) -#define ADM8211_STSR_TEIS (1 << 14) -#define ADM8211_STSR_FBE (1 << 13) -#define ADM8211_STSR_REIS (1 << 12) -#define ADM8211_STSR_GPTT (1 << 11) -#define ADM8211_STSR_RPS (1 << 8) -#define ADM8211_STSR_RDU (1 << 7) -#define ADM8211_STSR_RCI (1 << 6) -#define ADM8211_STSR_TUF (1 << 5) -#define ADM8211_STSR_TRT (1 << 4) -#define ADM8211_STSR_TLT (1 << 3) -#define ADM8211_STSR_TDU (1 << 2) -#define ADM8211_STSR_TPS (1 << 1) -#define ADM8211_STSR_TCI (1 << 0) - -/* CSR6 - NAR (Network Access Register) */ -#define ADM8211_NAR_TXCF (1 << 31) -#define ADM8211_NAR_HF (1 << 30) -#define ADM8211_NAR_UTR (1 << 29) -#define ADM8211_NAR_SQ (1 << 28) -#define ADM8211_NAR_CFP (1 << 27) -#define ADM8211_NAR_SF (1 << 21) -#define ADM8211_NAR_TR ((1 << 15) | (1 << 14)) -#define ADM8211_NAR_ST (1 << 13) -#define ADM8211_NAR_OM ((1 << 11) | (1 << 10)) -#define ADM8211_NAR_MM (1 << 7) -#define ADM8211_NAR_PR (1 << 6) -#define ADM8211_NAR_EA (1 << 5) -#define ADM8211_NAR_PB (1 << 3) -#define ADM8211_NAR_STPDMA (1 << 2) -#define ADM8211_NAR_SR (1 << 1) -#define ADM8211_NAR_CTX (1 << 0) - -#define ADM8211_IDLE() \ -do { \ - if (priv->nar & (ADM8211_NAR_SR | ADM8211_NAR_ST)) { \ - ADM8211_CSR_WRITE(NAR, priv->nar & \ - ~(ADM8211_NAR_SR | ADM8211_NAR_ST));\ - ADM8211_CSR_READ(NAR); \ - msleep(20); \ - } \ -} while (0) - -#define ADM8211_IDLE_RX() \ -do { \ - if (priv->nar & ADM8211_NAR_SR) { \ - ADM8211_CSR_WRITE(NAR, priv->nar & ~ADM8211_NAR_SR); \ - ADM8211_CSR_READ(NAR); \ - mdelay(20); \ - } \ -} while (0) - -#define ADM8211_RESTORE() \ -do { \ - if (priv->nar & (ADM8211_NAR_SR | ADM8211_NAR_ST)) \ - ADM8211_CSR_WRITE(NAR, priv->nar); \ -} while (0) - -/* CSR7 - IER (Interrupt Enable Register) */ -#define ADM8211_IER_PCFIE (1 << 31) -#define ADM8211_IER_BCNTCIE (1 << 30) -#define ADM8211_IER_GPIE (1 << 29) -#define ADM8211_IER_LinkOffIE (1 << 28) -#define ADM8211_IER_ATIMTCIE (1 << 27) -#define ADM8211_IER_TSFTFIE (1 << 26) -#define ADM8211_IER_TSCZE (1 << 25) -#define ADM8211_IER_LinkOnIE (1 << 24) -#define ADM8211_IER_SQLIE (1 << 23) -#define ADM8211_IER_WEPIE (1 << 22) -#define ADM8211_IER_ATIMEIE (1 << 21) -#define ADM8211_IER_TBTTIE (1 << 20) -#define ADM8211_IER_NIE (1 << 16) -#define ADM8211_IER_AIE (1 << 15) -#define ADM8211_IER_TEIE (1 << 14) -#define ADM8211_IER_FBEIE (1 << 13) -#define ADM8211_IER_REIE (1 << 12) -#define ADM8211_IER_GPTIE (1 << 11) -#define ADM8211_IER_RSIE (1 << 8) -#define ADM8211_IER_RUIE (1 << 7) -#define ADM8211_IER_RCIE (1 << 6) -#define ADM8211_IER_TUIE (1 << 5) -#define ADM8211_IER_TRTIE (1 << 4) -#define ADM8211_IER_TLTTIE (1 << 3) -#define ADM8211_IER_TDUIE (1 << 2) -#define ADM8211_IER_TPSIE (1 << 1) -#define ADM8211_IER_TCIE (1 << 0) - -/* CSR9 - SPR (Serial Port Register) */ -#define ADM8211_SPR_SRS (1 << 11) -#define ADM8211_SPR_SDO (1 << 3) -#define ADM8211_SPR_SDI (1 << 2) -#define ADM8211_SPR_SCLK (1 << 1) -#define ADM8211_SPR_SCS (1 << 0) - -/* CSR9A - CSR_TEST0 */ -#define ADM8211_CSR_TEST0_EPNE (1 << 18) -#define ADM8211_CSR_TEST0_EPSNM (1 << 17) -#define ADM8211_CSR_TEST0_EPTYP (1 << 16) -#define ADM8211_CSR_TEST0_EPRLD (1 << 15) - -/* CSR10 - WCSR (Wake-up Control/Status Register) */ -#define ADM8211_WCSR_CRCT (1 << 30) -#define ADM8211_WCSR_TSFTWE (1 << 20) -#define ADM8211_WCSR_TIMWE (1 << 19) -#define ADM8211_WCSR_ATIMWE (1 << 18) -#define ADM8211_WCSR_KEYWE (1 << 17) -#define ADM8211_WCSR_MPRE (1 << 9) -#define ADM8211_WCSR_LSOE (1 << 8) -#define ADM8211_WCSR_KEYUP (1 << 6) -#define ADM8211_WCSR_TSFTW (1 << 5) -#define ADM8211_WCSR_TIMW (1 << 4) -#define ADM8211_WCSR_ATIMW (1 << 3) -#define ADM8211_WCSR_MPR (1 << 1) -#define ADM8211_WCSR_LSO (1 << 0) - -/* CSR11A - GPIO */ -#define ADM8211_CSR_GPIO_EN5 (1 << 17) -#define ADM8211_CSR_GPIO_EN4 (1 << 16) -#define ADM8211_CSR_GPIO_EN3 (1 << 15) -#define ADM8211_CSR_GPIO_EN2 (1 << 14) -#define ADM8211_CSR_GPIO_EN1 (1 << 13) -#define ADM8211_CSR_GPIO_EN0 (1 << 12) -#define ADM8211_CSR_GPIO_O5 (1 << 11) -#define ADM8211_CSR_GPIO_O4 (1 << 10) -#define ADM8211_CSR_GPIO_O3 (1 << 9) -#define ADM8211_CSR_GPIO_O2 (1 << 8) -#define ADM8211_CSR_GPIO_O1 (1 << 7) -#define ADM8211_CSR_GPIO_O0 (1 << 6) -#define ADM8211_CSR_GPIO_IN 0x0000003f - -/* CSR12 - BBPCTL (BBP Control port) */ -#define ADM8211_BBPCTL_MMISEL (1 << 31) -#define ADM8211_BBPCTL_SPICADD (0x7F << 24) -#define ADM8211_BBPCTL_RF3000 (0x20 << 24) -#define ADM8211_BBPCTL_TXCE (1 << 23) -#define ADM8211_BBPCTL_RXCE (1 << 22) -#define ADM8211_BBPCTL_CCAP (1 << 21) -#define ADM8211_BBPCTL_TYPE 0x001c0000 -#define ADM8211_BBPCTL_WR (1 << 17) -#define ADM8211_BBPCTL_RD (1 << 16) -#define ADM8211_BBPCTL_ADDR 0x0000ff00 -#define ADM8211_BBPCTL_DATA 0x000000ff - -/* CSR12A - SYNCTL (Synthesizer Control port) */ -#define ADM8211_SYNCTL_WR (1 << 31) -#define ADM8211_SYNCTL_RD (1 << 30) -#define ADM8211_SYNCTL_CS0 (1 << 29) -#define ADM8211_SYNCTL_CS1 (1 << 28) -#define ADM8211_SYNCTL_CAL (1 << 27) -#define ADM8211_SYNCTL_SELCAL (1 << 26) -#define ADM8211_SYNCTL_RFtype ((1 << 24) | (1 << 23) | (1 << 22)) -#define ADM8211_SYNCTL_RFMD (1 << 22) -#define ADM8211_SYNCTL_GENERAL (0x7 << 22) -/* SYNCTL 21:0 Data (Si4126: 18-bit data, 4-bit address) */ - -/* CSR18 - CMDR (Command Register) */ -#define ADM8211_CMDR_PM (1 << 19) -#define ADM8211_CMDR_APM (1 << 18) -#define ADM8211_CMDR_RTE (1 << 4) -#define ADM8211_CMDR_DRT ((1 << 3) | (1 << 2)) -#define ADM8211_CMDR_DRT_8DW (0x0 << 2) -#define ADM8211_CMDR_DRT_16DW (0x1 << 2) -#define ADM8211_CMDR_DRT_SF (0x2 << 2) - -/* CSR33 - SYNRF (SYNRF direct control) */ -#define ADM8211_SYNRF_SELSYN (1 << 31) -#define ADM8211_SYNRF_SELRF (1 << 30) -#define ADM8211_SYNRF_LERF (1 << 29) -#define ADM8211_SYNRF_LEIF (1 << 28) -#define ADM8211_SYNRF_SYNCLK (1 << 27) -#define ADM8211_SYNRF_SYNDATA (1 << 26) -#define ADM8211_SYNRF_PE1 (1 << 25) -#define ADM8211_SYNRF_PE2 (1 << 24) -#define ADM8211_SYNRF_PA_PE (1 << 23) -#define ADM8211_SYNRF_TR_SW (1 << 22) -#define ADM8211_SYNRF_TR_SWN (1 << 21) -#define ADM8211_SYNRF_RADIO (1 << 20) -#define ADM8211_SYNRF_CAL_EN (1 << 19) -#define ADM8211_SYNRF_PHYRST (1 << 18) - -#define ADM8211_SYNRF_IF_SELECT_0 (1 << 31) -#define ADM8211_SYNRF_IF_SELECT_1 ((1 << 31) | (1 << 28)) -#define ADM8211_SYNRF_WRITE_SYNDATA_0 (1 << 31) -#define ADM8211_SYNRF_WRITE_SYNDATA_1 ((1 << 31) | (1 << 26)) -#define ADM8211_SYNRF_WRITE_CLOCK_0 (1 << 31) -#define ADM8211_SYNRF_WRITE_CLOCK_1 ((1 << 31) | (1 << 27)) - -/* CSR44 - WEPCTL (WEP Control) */ -#define ADM8211_WEPCTL_WEPENABLE (1 << 31) -#define ADM8211_WEPCTL_WPAENABLE (1 << 30) -#define ADM8211_WEPCTL_CURRENT_TABLE (1 << 29) -#define ADM8211_WEPCTL_TABLE_WR (1 << 28) -#define ADM8211_WEPCTL_TABLE_RD (1 << 27) -#define ADM8211_WEPCTL_WEPRXBYP (1 << 25) -#define ADM8211_WEPCTL_SEL_WEPTABLE (1 << 23) -#define ADM8211_WEPCTL_ADDR (0x000001ff) - -/* CSR45 - WESK (Data Entry for Share/Individual Key) */ -#define ADM8211_WESK_DATA (0x0000ffff) - -/* FER (Function Event Register) */ -#define ADM8211_FER_INTR_EV_ENT (1 << 15) - - -/* Si4126 RF Synthesizer - Control Registers */ -#define SI4126_MAIN_CONF 0 -#define SI4126_PHASE_DET_GAIN 1 -#define SI4126_POWERDOWN 2 -#define SI4126_RF1_N_DIV 3 /* only Si4136 */ -#define SI4126_RF2_N_DIV 4 -#define SI4126_IF_N_DIV 5 -#define SI4126_RF1_R_DIV 6 /* only Si4136 */ -#define SI4126_RF2_R_DIV 7 -#define SI4126_IF_R_DIV 8 - -/* Main Configuration */ -#define SI4126_MAIN_XINDIV2 (1 << 6) -#define SI4126_MAIN_IFDIV ((1 << 11) | (1 << 10)) -/* Powerdown */ -#define SI4126_POWERDOWN_PDIB (1 << 1) -#define SI4126_POWERDOWN_PDRB (1 << 0) - - -/* RF3000 BBP - Control Port Registers */ -/* 0x00 - reserved */ -#define RF3000_MODEM_CTRL__RX_STATUS 0x01 -#define RF3000_CCA_CTRL 0x02 -#define RF3000_DIVERSITY__RSSI 0x03 -#define RF3000_RX_SIGNAL_FIELD 0x04 -#define RF3000_RX_LEN_MSB 0x05 -#define RF3000_RX_LEN_LSB 0x06 -#define RF3000_RX_SERVICE_FIELD 0x07 -#define RF3000_TX_VAR_GAIN__TX_LEN_EXT 0x11 -#define RF3000_TX_LEN_MSB 0x12 -#define RF3000_TX_LEN_LSB 0x13 -#define RF3000_LOW_GAIN_CALIB 0x14 -#define RF3000_HIGH_GAIN_CALIB 0x15 - -/* ADM8211 revisions */ -#define ADM8211_REV_AB 0x11 -#define ADM8211_REV_AF 0x15 -#define ADM8211_REV_BA 0x20 -#define ADM8211_REV_CA 0x30 - -struct adm8211_desc { - __le32 status; - __le32 length; - __le32 buffer1; - __le32 buffer2; -}; - -#define RDES0_STATUS_OWN (1 << 31) -#define RDES0_STATUS_ES (1 << 30) -#define RDES0_STATUS_SQL (1 << 29) -#define RDES0_STATUS_DE (1 << 28) -#define RDES0_STATUS_FS (1 << 27) -#define RDES0_STATUS_LS (1 << 26) -#define RDES0_STATUS_PCF (1 << 25) -#define RDES0_STATUS_SFDE (1 << 24) -#define RDES0_STATUS_SIGE (1 << 23) -#define RDES0_STATUS_CRC16E (1 << 22) -#define RDES0_STATUS_RXTOE (1 << 21) -#define RDES0_STATUS_CRC32E (1 << 20) -#define RDES0_STATUS_ICVE (1 << 19) -#define RDES0_STATUS_DA1 (1 << 17) -#define RDES0_STATUS_DA0 (1 << 16) -#define RDES0_STATUS_RXDR ((1 << 15) | (1 << 14) | (1 << 13) | (1 << 12)) -#define RDES0_STATUS_FL (0x00000fff) - -#define RDES1_CONTROL_RER (1 << 25) -#define RDES1_CONTROL_RCH (1 << 24) -#define RDES1_CONTROL_RBS2 (0x00fff000) -#define RDES1_CONTROL_RBS1 (0x00000fff) - -#define RDES1_STATUS_RSSI (0x0000007f) - - -#define TDES0_CONTROL_OWN (1 << 31) -#define TDES0_CONTROL_DONE (1 << 30) -#define TDES0_CONTROL_TXDR (0x0ff00000) - -#define TDES0_STATUS_OWN (1 << 31) -#define TDES0_STATUS_DONE (1 << 30) -#define TDES0_STATUS_ES (1 << 29) -#define TDES0_STATUS_TLT (1 << 28) -#define TDES0_STATUS_TRT (1 << 27) -#define TDES0_STATUS_TUF (1 << 26) -#define TDES0_STATUS_TRO (1 << 25) -#define TDES0_STATUS_SOFBR (1 << 24) -#define TDES0_STATUS_ACR (0x00000fff) - -#define TDES1_CONTROL_IC (1 << 31) -#define TDES1_CONTROL_LS (1 << 30) -#define TDES1_CONTROL_FS (1 << 29) -#define TDES1_CONTROL_TER (1 << 25) -#define TDES1_CONTROL_TCH (1 << 24) -#define TDES1_CONTROL_RBS2 (0x00fff000) -#define TDES1_CONTROL_RBS1 (0x00000fff) - -/* SRAM offsets */ -#define ADM8211_SRAM(x) (priv->pdev->revision < ADM8211_REV_BA ? \ - ADM8211_SRAM_A_ ## x : ADM8211_SRAM_B_ ## x) - -#define ADM8211_SRAM_INDIV_KEY 0x0000 -#define ADM8211_SRAM_A_SHARE_KEY 0x0160 -#define ADM8211_SRAM_B_SHARE_KEY 0x00c0 - -#define ADM8211_SRAM_A_SSID 0x0180 -#define ADM8211_SRAM_B_SSID 0x00d4 -#define ADM8211_SRAM_SSID ADM8211_SRAM(SSID) - -#define ADM8211_SRAM_A_SUPP_RATE 0x0191 -#define ADM8211_SRAM_B_SUPP_RATE 0x00dd -#define ADM8211_SRAM_SUPP_RATE ADM8211_SRAM(SUPP_RATE) - -#define ADM8211_SRAM_A_SIZE 0x0200 -#define ADM8211_SRAM_B_SIZE 0x01c0 -#define ADM8211_SRAM_SIZE ADM8211_SRAM(SIZE) - -struct adm8211_rx_ring_info { - struct sk_buff *skb; - dma_addr_t mapping; -}; - -struct adm8211_tx_ring_info { - struct sk_buff *skb; - dma_addr_t mapping; - size_t hdrlen; -}; - -#define PLCP_SIGNAL_1M 0x0a -#define PLCP_SIGNAL_2M 0x14 -#define PLCP_SIGNAL_5M5 0x37 -#define PLCP_SIGNAL_11M 0x6e - -struct adm8211_tx_hdr { - u8 da[6]; - u8 signal; /* PLCP signal / TX rate in 100 Kbps */ - u8 service; - __le16 frame_body_size; - __le16 frame_control; - __le16 plcp_frag_tail_len; - __le16 plcp_frag_head_len; - __le16 dur_frag_tail; - __le16 dur_frag_head; - u8 addr4[6]; - -#define ADM8211_TXHDRCTL_SHORT_PREAMBLE (1 << 0) -#define ADM8211_TXHDRCTL_MORE_FRAG (1 << 1) -#define ADM8211_TXHDRCTL_MORE_DATA (1 << 2) -#define ADM8211_TXHDRCTL_FRAG_NO (1 << 3) /* ? */ -#define ADM8211_TXHDRCTL_ENABLE_RTS (1 << 4) -#define ADM8211_TXHDRCTL_ENABLE_WEP_ENGINE (1 << 5) -#define ADM8211_TXHDRCTL_ENABLE_EXTEND_HEADER (1 << 15) /* ? */ - __le16 header_control; - __le16 frag; - u8 reserved_0; - u8 retry_limit; - - u32 wep2key0; - u32 wep2key1; - u32 wep2key2; - u32 wep2key3; - - u8 keyid; - u8 entry_control; // huh?? - u16 reserved_1; - u32 reserved_2; -} __attribute__ ((packed)); - - -#define RX_COPY_BREAK 128 -#define RX_PKT_SIZE 2500 - -struct adm8211_eeprom { - __le16 signature; /* 0x00 */ - u8 major_version; /* 0x02 */ - u8 minor_version; /* 0x03 */ - u8 reserved_1[4]; /* 0x04 */ - u8 hwaddr[6]; /* 0x08 */ - u8 reserved_2[8]; /* 0x1E */ - __le16 cr49; /* 0x16 */ - u8 cr03; /* 0x18 */ - u8 cr28; /* 0x19 */ - u8 cr29; /* 0x1A */ - u8 country_code; /* 0x1B */ - -/* specific bbp types */ -#define ADM8211_BBP_RFMD3000 0x00 -#define ADM8211_BBP_RFMD3002 0x01 -#define ADM8211_BBP_ADM8011 0x04 - u8 specific_bbptype; /* 0x1C */ - u8 specific_rftype; /* 0x1D */ - u8 reserved_3[2]; /* 0x1E */ - __le16 device_id; /* 0x20 */ - __le16 vendor_id; /* 0x22 */ - __le16 subsystem_id; /* 0x24 */ - __le16 subsystem_vendor_id; /* 0x26 */ - u8 maxlat; /* 0x28 */ - u8 mingnt; /* 0x29 */ - __le16 cis_pointer_low; /* 0x2A */ - __le16 cis_pointer_high; /* 0x2C */ - __le16 csr18; /* 0x2E */ - u8 reserved_4[16]; /* 0x30 */ - u8 d1_pwrdara; /* 0x40 */ - u8 d0_pwrdara; /* 0x41 */ - u8 d3_pwrdara; /* 0x42 */ - u8 d2_pwrdara; /* 0x43 */ - u8 antenna_power[14]; /* 0x44 */ - __le16 cis_wordcnt; /* 0x52 */ - u8 tx_power[14]; /* 0x54 */ - u8 lpf_cutoff[14]; /* 0x62 */ - u8 lnags_threshold[14]; /* 0x70 */ - __le16 checksum; /* 0x7E */ - u8 cis_data[0]; /* 0x80, 384 bytes */ -} __attribute__ ((packed)); - -struct adm8211_priv { - struct pci_dev *pdev; - spinlock_t lock; - struct adm8211_csr __iomem *map; - struct adm8211_desc *rx_ring; - struct adm8211_desc *tx_ring; - dma_addr_t rx_ring_dma; - dma_addr_t tx_ring_dma; - struct adm8211_rx_ring_info *rx_buffers; - struct adm8211_tx_ring_info *tx_buffers; - unsigned int rx_ring_size, tx_ring_size; - unsigned int cur_tx, dirty_tx, cur_rx; - - struct ieee80211_low_level_stats stats; - struct ieee80211_supported_band band; - struct ieee80211_channel channels[14]; - int mode; - - int channel; - u8 bssid[ETH_ALEN]; - - u8 soft_rx_crc; - u8 retry_limit; - - u8 ant_power; - u8 tx_power; - u8 lpf_cutoff; - u8 lnags_threshold; - struct adm8211_eeprom *eeprom; - size_t eeprom_len; - - u32 nar; - -#define ADM8211_TYPE_INTERSIL 0x00 -#define ADM8211_TYPE_RFMD 0x01 -#define ADM8211_TYPE_MARVEL 0x02 -#define ADM8211_TYPE_AIROHA 0x03 -#define ADM8211_TYPE_ADMTEK 0x05 - unsigned int rf_type:3; - unsigned int bbp_type:3; - - u8 specific_bbptype; - enum { - ADM8211_RFMD2948 = 0x0, - ADM8211_RFMD2958 = 0x1, - ADM8211_RFMD2958_RF3000_CONTROL_POWER = 0x2, - ADM8211_MAX2820 = 0x8, - ADM8211_AL2210L = 0xC, /* Airoha */ - } transceiver_type; -}; - -struct ieee80211_chan_range { - u8 min; - u8 max; -}; - -static const struct ieee80211_chan_range cranges[] = { - {1, 11}, /* FCC */ - {1, 11}, /* IC */ - {1, 13}, /* ETSI */ - {10, 11}, /* SPAIN */ - {10, 13}, /* FRANCE */ - {14, 14}, /* MMK */ - {1, 14}, /* MMK2 */ -}; - -#endif /* ADM8211_H */ diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c deleted file mode 100644 index 6c26840bfe0b..000000000000 --- a/drivers/net/wireless/airo.c +++ /dev/null @@ -1,8276 +0,0 @@ -/*====================================================================== - - Aironet driver for 4500 and 4800 series cards - - This code is released under both the GPL version 2 and BSD licenses. - Either license may be used. The respective licenses are found at - the end of this file. - - This code was developed by Benjamin Reed - including portions of which come from the Aironet PC4500 - Developer's Reference Manual and used with permission. Copyright - (C) 1999 Benjamin Reed. All Rights Reserved. Permission to use - code in the Developer's manual was granted for this driver by - Aironet. Major code contributions were received from Javier Achirica - and Jean Tourrilhes . - Code was also integrated from the Cisco Aironet driver for Linux. - Support for MPI350 cards was added by Fabrice Bellet - . - -======================================================================*/ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "airo.h" - -#define DRV_NAME "airo" - -#ifdef CONFIG_PCI -static struct pci_device_id card_ids[] = { - { 0x14b9, 1, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x14b9, 0x4500, PCI_ANY_ID, PCI_ANY_ID }, - { 0x14b9, 0x4800, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x14b9, 0x0340, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x14b9, 0x0350, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x14b9, 0x5000, PCI_ANY_ID, PCI_ANY_ID, }, - { 0x14b9, 0xa504, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, card_ids); - -static int airo_pci_probe(struct pci_dev *, const struct pci_device_id *); -static void airo_pci_remove(struct pci_dev *); -static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state); -static int airo_pci_resume(struct pci_dev *pdev); - -static struct pci_driver airo_driver = { - .name = DRV_NAME, - .id_table = card_ids, - .probe = airo_pci_probe, - .remove = __devexit_p(airo_pci_remove), - .suspend = airo_pci_suspend, - .resume = airo_pci_resume, -}; -#endif /* CONFIG_PCI */ - -/* Include Wireless Extension definition and check version - Jean II */ -#include -#define WIRELESS_SPY /* enable iwspy support */ -#include /* New driver API */ - -#define CISCO_EXT /* enable Cisco extensions */ -#ifdef CISCO_EXT -#include -#endif - -/* Hack to do some power saving */ -#define POWER_ON_DOWN - -/* As you can see this list is HUGH! - I really don't know what a lot of these counts are about, but they - are all here for completeness. If the IGNLABEL macro is put in - infront of the label, that statistic will not be included in the list - of statistics in the /proc filesystem */ - -#define IGNLABEL(comment) NULL -static char *statsLabels[] = { - "RxOverrun", - IGNLABEL("RxPlcpCrcErr"), - IGNLABEL("RxPlcpFormatErr"), - IGNLABEL("RxPlcpLengthErr"), - "RxMacCrcErr", - "RxMacCrcOk", - "RxWepErr", - "RxWepOk", - "RetryLong", - "RetryShort", - "MaxRetries", - "NoAck", - "NoCts", - "RxAck", - "RxCts", - "TxAck", - "TxRts", - "TxCts", - "TxMc", - "TxBc", - "TxUcFrags", - "TxUcPackets", - "TxBeacon", - "RxBeacon", - "TxSinColl", - "TxMulColl", - "DefersNo", - "DefersProt", - "DefersEngy", - "DupFram", - "RxFragDisc", - "TxAged", - "RxAged", - "LostSync-MaxRetry", - "LostSync-MissedBeacons", - "LostSync-ArlExceeded", - "LostSync-Deauth", - "LostSync-Disassoced", - "LostSync-TsfTiming", - "HostTxMc", - "HostTxBc", - "HostTxUc", - "HostTxFail", - "HostRxMc", - "HostRxBc", - "HostRxUc", - "HostRxDiscard", - IGNLABEL("HmacTxMc"), - IGNLABEL("HmacTxBc"), - IGNLABEL("HmacTxUc"), - IGNLABEL("HmacTxFail"), - IGNLABEL("HmacRxMc"), - IGNLABEL("HmacRxBc"), - IGNLABEL("HmacRxUc"), - IGNLABEL("HmacRxDiscard"), - IGNLABEL("HmacRxAccepted"), - "SsidMismatch", - "ApMismatch", - "RatesMismatch", - "AuthReject", - "AuthTimeout", - "AssocReject", - "AssocTimeout", - IGNLABEL("ReasonOutsideTable"), - IGNLABEL("ReasonStatus1"), - IGNLABEL("ReasonStatus2"), - IGNLABEL("ReasonStatus3"), - IGNLABEL("ReasonStatus4"), - IGNLABEL("ReasonStatus5"), - IGNLABEL("ReasonStatus6"), - IGNLABEL("ReasonStatus7"), - IGNLABEL("ReasonStatus8"), - IGNLABEL("ReasonStatus9"), - IGNLABEL("ReasonStatus10"), - IGNLABEL("ReasonStatus11"), - IGNLABEL("ReasonStatus12"), - IGNLABEL("ReasonStatus13"), - IGNLABEL("ReasonStatus14"), - IGNLABEL("ReasonStatus15"), - IGNLABEL("ReasonStatus16"), - IGNLABEL("ReasonStatus17"), - IGNLABEL("ReasonStatus18"), - IGNLABEL("ReasonStatus19"), - "RxMan", - "TxMan", - "RxRefresh", - "TxRefresh", - "RxPoll", - "TxPoll", - "HostRetries", - "LostSync-HostReq", - "HostTxBytes", - "HostRxBytes", - "ElapsedUsec", - "ElapsedSec", - "LostSyncBetterAP", - "PrivacyMismatch", - "Jammed", - "DiscRxNotWepped", - "PhyEleMismatch", - (char*)-1 }; -#ifndef RUN_AT -#define RUN_AT(x) (jiffies+(x)) -#endif - - -/* These variables are for insmod, since it seems that the rates - can only be set in setup_card. Rates should be a comma separated - (no spaces) list of rates (up to 8). */ - -static int rates[8]; -static int basic_rate; -static char *ssids[3]; - -static int io[4]; -static int irq[4]; - -static -int maxencrypt /* = 0 */; /* The highest rate that the card can encrypt at. - 0 means no limit. For old cards this was 4 */ - -static int auto_wep /* = 0 */; /* If set, it tries to figure out the wep mode */ -static int aux_bap /* = 0 */; /* Checks to see if the aux ports are needed to read - the bap, needed on some older cards and buses. */ -static int adhoc; - -static int probe = 1; - -static int proc_uid /* = 0 */; - -static int proc_gid /* = 0 */; - -static int airo_perm = 0555; - -static int proc_perm = 0644; - -MODULE_AUTHOR("Benjamin Reed"); -MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet \ -cards. Direct support for ISA/PCI/MPI cards and support \ -for PCMCIA when used with airo_cs."); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340/350"); -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param(basic_rate, int, 0); -module_param_array(rates, int, NULL, 0); -module_param_array(ssids, charp, NULL, 0); -module_param(auto_wep, int, 0); -MODULE_PARM_DESC(auto_wep, "If non-zero, the driver will keep looping through \ -the authentication options until an association is made. The value of \ -auto_wep is number of the wep keys to check. A value of 2 will try using \ -the key at index 0 and index 1."); -module_param(aux_bap, int, 0); -MODULE_PARM_DESC(aux_bap, "If non-zero, the driver will switch into a mode \ -than seems to work better for older cards with some older buses. Before \ -switching it checks that the switch is needed."); -module_param(maxencrypt, int, 0); -MODULE_PARM_DESC(maxencrypt, "The maximum speed that the card can do \ -encryption. Units are in 512kbs. Zero (default) means there is no limit. \ -Older cards used to be limited to 2mbs (4)."); -module_param(adhoc, int, 0); -MODULE_PARM_DESC(adhoc, "If non-zero, the card will start in adhoc mode."); -module_param(probe, int, 0); -MODULE_PARM_DESC(probe, "If zero, the driver won't start the card."); - -module_param(proc_uid, int, 0); -MODULE_PARM_DESC(proc_uid, "The uid that the /proc files will belong to."); -module_param(proc_gid, int, 0); -MODULE_PARM_DESC(proc_gid, "The gid that the /proc files will belong to."); -module_param(airo_perm, int, 0); -MODULE_PARM_DESC(airo_perm, "The permission bits of /proc/[driver/]aironet."); -module_param(proc_perm, int, 0); -MODULE_PARM_DESC(proc_perm, "The permission bits of the files in /proc"); - -/* This is a kind of sloppy hack to get this information to OUT4500 and - IN4500. I would be extremely interested in the situation where this - doesn't work though!!! */ -static int do8bitIO /* = 0 */; - -/* Return codes */ -#define SUCCESS 0 -#define ERROR -1 -#define NO_PACKET -2 - -/* Commands */ -#define NOP2 0x0000 -#define MAC_ENABLE 0x0001 -#define MAC_DISABLE 0x0002 -#define CMD_LOSE_SYNC 0x0003 /* Not sure what this does... */ -#define CMD_SOFTRESET 0x0004 -#define HOSTSLEEP 0x0005 -#define CMD_MAGIC_PKT 0x0006 -#define CMD_SETWAKEMASK 0x0007 -#define CMD_READCFG 0x0008 -#define CMD_SETMODE 0x0009 -#define CMD_ALLOCATETX 0x000a -#define CMD_TRANSMIT 0x000b -#define CMD_DEALLOCATETX 0x000c -#define NOP 0x0010 -#define CMD_WORKAROUND 0x0011 -#define CMD_ALLOCATEAUX 0x0020 -#define CMD_ACCESS 0x0021 -#define CMD_PCIBAP 0x0022 -#define CMD_PCIAUX 0x0023 -#define CMD_ALLOCBUF 0x0028 -#define CMD_GETTLV 0x0029 -#define CMD_PUTTLV 0x002a -#define CMD_DELTLV 0x002b -#define CMD_FINDNEXTTLV 0x002c -#define CMD_PSPNODES 0x0030 -#define CMD_SETCW 0x0031 -#define CMD_SETPCF 0x0032 -#define CMD_SETPHYREG 0x003e -#define CMD_TXTEST 0x003f -#define MAC_ENABLETX 0x0101 -#define CMD_LISTBSS 0x0103 -#define CMD_SAVECFG 0x0108 -#define CMD_ENABLEAUX 0x0111 -#define CMD_WRITERID 0x0121 -#define CMD_USEPSPNODES 0x0130 -#define MAC_ENABLERX 0x0201 - -/* Command errors */ -#define ERROR_QUALIF 0x00 -#define ERROR_ILLCMD 0x01 -#define ERROR_ILLFMT 0x02 -#define ERROR_INVFID 0x03 -#define ERROR_INVRID 0x04 -#define ERROR_LARGE 0x05 -#define ERROR_NDISABL 0x06 -#define ERROR_ALLOCBSY 0x07 -#define ERROR_NORD 0x0B -#define ERROR_NOWR 0x0C -#define ERROR_INVFIDTX 0x0D -#define ERROR_TESTACT 0x0E -#define ERROR_TAGNFND 0x12 -#define ERROR_DECODE 0x20 -#define ERROR_DESCUNAV 0x21 -#define ERROR_BADLEN 0x22 -#define ERROR_MODE 0x80 -#define ERROR_HOP 0x81 -#define ERROR_BINTER 0x82 -#define ERROR_RXMODE 0x83 -#define ERROR_MACADDR 0x84 -#define ERROR_RATES 0x85 -#define ERROR_ORDER 0x86 -#define ERROR_SCAN 0x87 -#define ERROR_AUTH 0x88 -#define ERROR_PSMODE 0x89 -#define ERROR_RTYPE 0x8A -#define ERROR_DIVER 0x8B -#define ERROR_SSID 0x8C -#define ERROR_APLIST 0x8D -#define ERROR_AUTOWAKE 0x8E -#define ERROR_LEAP 0x8F - -/* Registers */ -#define COMMAND 0x00 -#define PARAM0 0x02 -#define PARAM1 0x04 -#define PARAM2 0x06 -#define STATUS 0x08 -#define RESP0 0x0a -#define RESP1 0x0c -#define RESP2 0x0e -#define LINKSTAT 0x10 -#define SELECT0 0x18 -#define OFFSET0 0x1c -#define RXFID 0x20 -#define TXALLOCFID 0x22 -#define TXCOMPLFID 0x24 -#define DATA0 0x36 -#define EVSTAT 0x30 -#define EVINTEN 0x32 -#define EVACK 0x34 -#define SWS0 0x28 -#define SWS1 0x2a -#define SWS2 0x2c -#define SWS3 0x2e -#define AUXPAGE 0x3A -#define AUXOFF 0x3C -#define AUXDATA 0x3E - -#define FID_TX 1 -#define FID_RX 2 -/* Offset into aux memory for descriptors */ -#define AUX_OFFSET 0x800 -/* Size of allocated packets */ -#define PKTSIZE 1840 -#define RIDSIZE 2048 -/* Size of the transmit queue */ -#define MAXTXQ 64 - -/* BAP selectors */ -#define BAP0 0 /* Used for receiving packets */ -#define BAP1 2 /* Used for xmiting packets and working with RIDS */ - -/* Flags */ -#define COMMAND_BUSY 0x8000 - -#define BAP_BUSY 0x8000 -#define BAP_ERR 0x4000 -#define BAP_DONE 0x2000 - -#define PROMISC 0xffff -#define NOPROMISC 0x0000 - -#define EV_CMD 0x10 -#define EV_CLEARCOMMANDBUSY 0x4000 -#define EV_RX 0x01 -#define EV_TX 0x02 -#define EV_TXEXC 0x04 -#define EV_ALLOC 0x08 -#define EV_LINK 0x80 -#define EV_AWAKE 0x100 -#define EV_TXCPY 0x400 -#define EV_UNKNOWN 0x800 -#define EV_MIC 0x1000 /* Message Integrity Check Interrupt */ -#define EV_AWAKEN 0x2000 -#define STATUS_INTS (EV_AWAKE|EV_LINK|EV_TXEXC|EV_TX|EV_TXCPY|EV_RX|EV_MIC) - -#ifdef CHECK_UNKNOWN_INTS -#define IGNORE_INTS ( EV_CMD | EV_UNKNOWN) -#else -#define IGNORE_INTS (~STATUS_INTS) -#endif - -/* RID TYPES */ -#define RID_RW 0x20 - -/* The RIDs */ -#define RID_CAPABILITIES 0xFF00 -#define RID_APINFO 0xFF01 -#define RID_RADIOINFO 0xFF02 -#define RID_UNKNOWN3 0xFF03 -#define RID_RSSI 0xFF04 -#define RID_CONFIG 0xFF10 -#define RID_SSID 0xFF11 -#define RID_APLIST 0xFF12 -#define RID_DRVNAME 0xFF13 -#define RID_ETHERENCAP 0xFF14 -#define RID_WEP_TEMP 0xFF15 -#define RID_WEP_PERM 0xFF16 -#define RID_MODULATION 0xFF17 -#define RID_OPTIONS 0xFF18 -#define RID_ACTUALCONFIG 0xFF20 /*readonly*/ -#define RID_FACTORYCONFIG 0xFF21 -#define RID_UNKNOWN22 0xFF22 -#define RID_LEAPUSERNAME 0xFF23 -#define RID_LEAPPASSWORD 0xFF24 -#define RID_STATUS 0xFF50 -#define RID_BEACON_HST 0xFF51 -#define RID_BUSY_HST 0xFF52 -#define RID_RETRIES_HST 0xFF53 -#define RID_UNKNOWN54 0xFF54 -#define RID_UNKNOWN55 0xFF55 -#define RID_UNKNOWN56 0xFF56 -#define RID_MIC 0xFF57 -#define RID_STATS16 0xFF60 -#define RID_STATS16DELTA 0xFF61 -#define RID_STATS16DELTACLEAR 0xFF62 -#define RID_STATS 0xFF68 -#define RID_STATSDELTA 0xFF69 -#define RID_STATSDELTACLEAR 0xFF6A -#define RID_ECHOTEST_RID 0xFF70 -#define RID_ECHOTEST_RESULTS 0xFF71 -#define RID_BSSLISTFIRST 0xFF72 -#define RID_BSSLISTNEXT 0xFF73 -#define RID_WPA_BSSLISTFIRST 0xFF74 -#define RID_WPA_BSSLISTNEXT 0xFF75 - -typedef struct { - u16 cmd; - u16 parm0; - u16 parm1; - u16 parm2; -} Cmd; - -typedef struct { - u16 status; - u16 rsp0; - u16 rsp1; - u16 rsp2; -} Resp; - -/* - * Rids and endian-ness: The Rids will always be in cpu endian, since - * this all the patches from the big-endian guys end up doing that. - * so all rid access should use the read/writeXXXRid routines. - */ - -/* This structure came from an email sent to me from an engineer at - aironet for inclusion into this driver */ -typedef struct WepKeyRid WepKeyRid; -struct WepKeyRid { - __le16 len; - __le16 kindex; - u8 mac[ETH_ALEN]; - __le16 klen; - u8 key[16]; -} __attribute__ ((packed)); - -/* These structures are from the Aironet's PC4500 Developers Manual */ -typedef struct Ssid Ssid; -struct Ssid { - __le16 len; - u8 ssid[32]; -} __attribute__ ((packed)); - -typedef struct SsidRid SsidRid; -struct SsidRid { - __le16 len; - Ssid ssids[3]; -} __attribute__ ((packed)); - -typedef struct ModulationRid ModulationRid; -struct ModulationRid { - __le16 len; - __le16 modulation; -#define MOD_DEFAULT cpu_to_le16(0) -#define MOD_CCK cpu_to_le16(1) -#define MOD_MOK cpu_to_le16(2) -} __attribute__ ((packed)); - -typedef struct ConfigRid ConfigRid; -struct ConfigRid { - __le16 len; /* sizeof(ConfigRid) */ - __le16 opmode; /* operating mode */ -#define MODE_STA_IBSS cpu_to_le16(0) -#define MODE_STA_ESS cpu_to_le16(1) -#define MODE_AP cpu_to_le16(2) -#define MODE_AP_RPTR cpu_to_le16(3) -#define MODE_CFG_MASK cpu_to_le16(0xff) -#define MODE_ETHERNET_HOST cpu_to_le16(0<<8) /* rx payloads converted */ -#define MODE_LLC_HOST cpu_to_le16(1<<8) /* rx payloads left as is */ -#define MODE_AIRONET_EXTEND cpu_to_le16(1<<9) /* enable Aironet extenstions */ -#define MODE_AP_INTERFACE cpu_to_le16(1<<10) /* enable ap interface extensions */ -#define MODE_ANTENNA_ALIGN cpu_to_le16(1<<11) /* enable antenna alignment */ -#define MODE_ETHER_LLC cpu_to_le16(1<<12) /* enable ethernet LLC */ -#define MODE_LEAF_NODE cpu_to_le16(1<<13) /* enable leaf node bridge */ -#define MODE_CF_POLLABLE cpu_to_le16(1<<14) /* enable CF pollable */ -#define MODE_MIC cpu_to_le16(1<<15) /* enable MIC */ - __le16 rmode; /* receive mode */ -#define RXMODE_BC_MC_ADDR cpu_to_le16(0) -#define RXMODE_BC_ADDR cpu_to_le16(1) /* ignore multicasts */ -#define RXMODE_ADDR cpu_to_le16(2) /* ignore multicast and broadcast */ -#define RXMODE_RFMON cpu_to_le16(3) /* wireless monitor mode */ -#define RXMODE_RFMON_ANYBSS cpu_to_le16(4) -#define RXMODE_LANMON cpu_to_le16(5) /* lan style monitor -- data packets only */ -#define RXMODE_MASK cpu_to_le16(255) -#define RXMODE_DISABLE_802_3_HEADER cpu_to_le16(1<<8) /* disables 802.3 header on rx */ -#define RXMODE_FULL_MASK (RXMODE_MASK | RXMODE_DISABLE_802_3_HEADER) -#define RXMODE_NORMALIZED_RSSI cpu_to_le16(1<<9) /* return normalized RSSI */ - __le16 fragThresh; - __le16 rtsThres; - u8 macAddr[ETH_ALEN]; - u8 rates[8]; - __le16 shortRetryLimit; - __le16 longRetryLimit; - __le16 txLifetime; /* in kusec */ - __le16 rxLifetime; /* in kusec */ - __le16 stationary; - __le16 ordering; - __le16 u16deviceType; /* for overriding device type */ - __le16 cfpRate; - __le16 cfpDuration; - __le16 _reserved1[3]; - /*---------- Scanning/Associating ----------*/ - __le16 scanMode; -#define SCANMODE_ACTIVE cpu_to_le16(0) -#define SCANMODE_PASSIVE cpu_to_le16(1) -#define SCANMODE_AIROSCAN cpu_to_le16(2) - __le16 probeDelay; /* in kusec */ - __le16 probeEnergyTimeout; /* in kusec */ - __le16 probeResponseTimeout; - __le16 beaconListenTimeout; - __le16 joinNetTimeout; - __le16 authTimeout; - __le16 authType; -#define AUTH_OPEN cpu_to_le16(0x1) -#define AUTH_ENCRYPT cpu_to_le16(0x101) -#define AUTH_SHAREDKEY cpu_to_le16(0x102) -#define AUTH_ALLOW_UNENCRYPTED cpu_to_le16(0x200) - __le16 associationTimeout; - __le16 specifiedApTimeout; - __le16 offlineScanInterval; - __le16 offlineScanDuration; - __le16 linkLossDelay; - __le16 maxBeaconLostTime; - __le16 refreshInterval; -#define DISABLE_REFRESH cpu_to_le16(0xFFFF) - __le16 _reserved1a[1]; - /*---------- Power save operation ----------*/ - __le16 powerSaveMode; -#define POWERSAVE_CAM cpu_to_le16(0) -#define POWERSAVE_PSP cpu_to_le16(1) -#define POWERSAVE_PSPCAM cpu_to_le16(2) - __le16 sleepForDtims; - __le16 listenInterval; - __le16 fastListenInterval; - __le16 listenDecay; - __le16 fastListenDelay; - __le16 _reserved2[2]; - /*---------- Ap/Ibss config items ----------*/ - __le16 beaconPeriod; - __le16 atimDuration; - __le16 hopPeriod; - __le16 channelSet; - __le16 channel; - __le16 dtimPeriod; - __le16 bridgeDistance; - __le16 radioID; - /*---------- Radio configuration ----------*/ - __le16 radioType; -#define RADIOTYPE_DEFAULT cpu_to_le16(0) -#define RADIOTYPE_802_11 cpu_to_le16(1) -#define RADIOTYPE_LEGACY cpu_to_le16(2) - u8 rxDiversity; - u8 txDiversity; - __le16 txPower; -#define TXPOWER_DEFAULT 0 - __le16 rssiThreshold; -#define RSSI_DEFAULT 0 - __le16 modulation; -#define PREAMBLE_AUTO cpu_to_le16(0) -#define PREAMBLE_LONG cpu_to_le16(1) -#define PREAMBLE_SHORT cpu_to_le16(2) - __le16 preamble; - __le16 homeProduct; - __le16 radioSpecific; - /*---------- Aironet Extensions ----------*/ - u8 nodeName[16]; - __le16 arlThreshold; - __le16 arlDecay; - __le16 arlDelay; - __le16 _reserved4[1]; - /*---------- Aironet Extensions ----------*/ - u8 magicAction; -#define MAGIC_ACTION_STSCHG 1 -#define MAGIC_ACTION_RESUME 2 -#define MAGIC_IGNORE_MCAST (1<<8) -#define MAGIC_IGNORE_BCAST (1<<9) -#define MAGIC_SWITCH_TO_PSP (0<<10) -#define MAGIC_STAY_IN_CAM (1<<10) - u8 magicControl; - __le16 autoWake; -} __attribute__ ((packed)); - -typedef struct StatusRid StatusRid; -struct StatusRid { - __le16 len; - u8 mac[ETH_ALEN]; - __le16 mode; - __le16 errorCode; - __le16 sigQuality; - __le16 SSIDlen; - char SSID[32]; - char apName[16]; - u8 bssid[4][ETH_ALEN]; - __le16 beaconPeriod; - __le16 dimPeriod; - __le16 atimDuration; - __le16 hopPeriod; - __le16 channelSet; - __le16 channel; - __le16 hopsToBackbone; - __le16 apTotalLoad; - __le16 generatedLoad; - __le16 accumulatedArl; - __le16 signalQuality; - __le16 currentXmitRate; - __le16 apDevExtensions; - __le16 normalizedSignalStrength; - __le16 shortPreamble; - u8 apIP[4]; - u8 noisePercent; /* Noise percent in last second */ - u8 noisedBm; /* Noise dBm in last second */ - u8 noiseAvePercent; /* Noise percent in last minute */ - u8 noiseAvedBm; /* Noise dBm in last minute */ - u8 noiseMaxPercent; /* Highest noise percent in last minute */ - u8 noiseMaxdBm; /* Highest noise dbm in last minute */ - __le16 load; - u8 carrier[4]; - __le16 assocStatus; -#define STAT_NOPACKETS 0 -#define STAT_NOCARRIERSET 10 -#define STAT_GOTCARRIERSET 11 -#define STAT_WRONGSSID 20 -#define STAT_BADCHANNEL 25 -#define STAT_BADBITRATES 30 -#define STAT_BADPRIVACY 35 -#define STAT_APFOUND 40 -#define STAT_APREJECTED 50 -#define STAT_AUTHENTICATING 60 -#define STAT_DEAUTHENTICATED 61 -#define STAT_AUTHTIMEOUT 62 -#define STAT_ASSOCIATING 70 -#define STAT_DEASSOCIATED 71 -#define STAT_ASSOCTIMEOUT 72 -#define STAT_NOTAIROAP 73 -#define STAT_ASSOCIATED 80 -#define STAT_LEAPING 90 -#define STAT_LEAPFAILED 91 -#define STAT_LEAPTIMEDOUT 92 -#define STAT_LEAPCOMPLETE 93 -} __attribute__ ((packed)); - -typedef struct StatsRid StatsRid; -struct StatsRid { - __le16 len; - __le16 spacer; - __le32 vals[100]; -} __attribute__ ((packed)); - -typedef struct APListRid APListRid; -struct APListRid { - __le16 len; - u8 ap[4][ETH_ALEN]; -} __attribute__ ((packed)); - -typedef struct CapabilityRid CapabilityRid; -struct CapabilityRid { - __le16 len; - char oui[3]; - char zero; - __le16 prodNum; - char manName[32]; - char prodName[16]; - char prodVer[8]; - char factoryAddr[ETH_ALEN]; - char aironetAddr[ETH_ALEN]; - __le16 radioType; - __le16 country; - char callid[ETH_ALEN]; - char supportedRates[8]; - char rxDiversity; - char txDiversity; - __le16 txPowerLevels[8]; - __le16 hardVer; - __le16 hardCap; - __le16 tempRange; - __le16 softVer; - __le16 softSubVer; - __le16 interfaceVer; - __le16 softCap; - __le16 bootBlockVer; - __le16 requiredHard; - __le16 extSoftCap; -} __attribute__ ((packed)); - -/* Only present on firmware >= 5.30.17 */ -typedef struct BSSListRidExtra BSSListRidExtra; -struct BSSListRidExtra { - __le16 unknown[4]; - u8 fixed[12]; /* WLAN management frame */ - u8 iep[624]; -} __attribute__ ((packed)); - -typedef struct BSSListRid BSSListRid; -struct BSSListRid { - __le16 len; - __le16 index; /* First is 0 and 0xffff means end of list */ -#define RADIO_FH 1 /* Frequency hopping radio type */ -#define RADIO_DS 2 /* Direct sequence radio type */ -#define RADIO_TMA 4 /* Proprietary radio used in old cards (2500) */ - __le16 radioType; - u8 bssid[ETH_ALEN]; /* Mac address of the BSS */ - u8 zero; - u8 ssidLen; - u8 ssid[32]; - __le16 dBm; -#define CAP_ESS cpu_to_le16(1<<0) -#define CAP_IBSS cpu_to_le16(1<<1) -#define CAP_PRIVACY cpu_to_le16(1<<4) -#define CAP_SHORTHDR cpu_to_le16(1<<5) - __le16 cap; - __le16 beaconInterval; - u8 rates[8]; /* Same as rates for config rid */ - struct { /* For frequency hopping only */ - __le16 dwell; - u8 hopSet; - u8 hopPattern; - u8 hopIndex; - u8 fill; - } fh; - __le16 dsChannel; - __le16 atimWindow; - - /* Only present on firmware >= 5.30.17 */ - BSSListRidExtra extra; -} __attribute__ ((packed)); - -typedef struct { - BSSListRid bss; - struct list_head list; -} BSSListElement; - -typedef struct tdsRssiEntry tdsRssiEntry; -struct tdsRssiEntry { - u8 rssipct; - u8 rssidBm; -} __attribute__ ((packed)); - -typedef struct tdsRssiRid tdsRssiRid; -struct tdsRssiRid { - u16 len; - tdsRssiEntry x[256]; -} __attribute__ ((packed)); - -typedef struct MICRid MICRid; -struct MICRid { - __le16 len; - __le16 state; - __le16 multicastValid; - u8 multicast[16]; - __le16 unicastValid; - u8 unicast[16]; -} __attribute__ ((packed)); - -typedef struct MICBuffer MICBuffer; -struct MICBuffer { - __be16 typelen; - - union { - u8 snap[8]; - struct { - u8 dsap; - u8 ssap; - u8 control; - u8 orgcode[3]; - u8 fieldtype[2]; - } llc; - } u; - __be32 mic; - __be32 seq; -} __attribute__ ((packed)); - -typedef struct { - u8 da[ETH_ALEN]; - u8 sa[ETH_ALEN]; -} etherHead; - -#define TXCTL_TXOK (1<<1) /* report if tx is ok */ -#define TXCTL_TXEX (1<<2) /* report if tx fails */ -#define TXCTL_802_3 (0<<3) /* 802.3 packet */ -#define TXCTL_802_11 (1<<3) /* 802.11 mac packet */ -#define TXCTL_ETHERNET (0<<4) /* payload has ethertype */ -#define TXCTL_LLC (1<<4) /* payload is llc */ -#define TXCTL_RELEASE (0<<5) /* release after completion */ -#define TXCTL_NORELEASE (1<<5) /* on completion returns to host */ - -#define BUSY_FID 0x10000 - -#ifdef CISCO_EXT -#define AIROMAGIC 0xa55a -/* Warning : SIOCDEVPRIVATE may disapear during 2.5.X - Jean II */ -#ifdef SIOCIWFIRSTPRIV -#ifdef SIOCDEVPRIVATE -#define AIROOLDIOCTL SIOCDEVPRIVATE -#define AIROOLDIDIFC AIROOLDIOCTL + 1 -#endif /* SIOCDEVPRIVATE */ -#else /* SIOCIWFIRSTPRIV */ -#define SIOCIWFIRSTPRIV SIOCDEVPRIVATE -#endif /* SIOCIWFIRSTPRIV */ -/* This may be wrong. When using the new SIOCIWFIRSTPRIV range, we probably - * should use only "GET" ioctls (last bit set to 1). "SET" ioctls are root - * only and don't return the modified struct ifreq to the application which - * is usually a problem. - Jean II */ -#define AIROIOCTL SIOCIWFIRSTPRIV -#define AIROIDIFC AIROIOCTL + 1 - -/* Ioctl constants to be used in airo_ioctl.command */ - -#define AIROGCAP 0 // Capability rid -#define AIROGCFG 1 // USED A LOT -#define AIROGSLIST 2 // System ID list -#define AIROGVLIST 3 // List of specified AP's -#define AIROGDRVNAM 4 // NOTUSED -#define AIROGEHTENC 5 // NOTUSED -#define AIROGWEPKTMP 6 -#define AIROGWEPKNV 7 -#define AIROGSTAT 8 -#define AIROGSTATSC32 9 -#define AIROGSTATSD32 10 -#define AIROGMICRID 11 -#define AIROGMICSTATS 12 -#define AIROGFLAGS 13 -#define AIROGID 14 -#define AIRORRID 15 -#define AIRORSWVERSION 17 - -/* Leave gap of 40 commands after AIROGSTATSD32 for future */ - -#define AIROPCAP AIROGSTATSD32 + 40 -#define AIROPVLIST AIROPCAP + 1 -#define AIROPSLIST AIROPVLIST + 1 -#define AIROPCFG AIROPSLIST + 1 -#define AIROPSIDS AIROPCFG + 1 -#define AIROPAPLIST AIROPSIDS + 1 -#define AIROPMACON AIROPAPLIST + 1 /* Enable mac */ -#define AIROPMACOFF AIROPMACON + 1 /* Disable mac */ -#define AIROPSTCLR AIROPMACOFF + 1 -#define AIROPWEPKEY AIROPSTCLR + 1 -#define AIROPWEPKEYNV AIROPWEPKEY + 1 -#define AIROPLEAPPWD AIROPWEPKEYNV + 1 -#define AIROPLEAPUSR AIROPLEAPPWD + 1 - -/* Flash codes */ - -#define AIROFLSHRST AIROPWEPKEYNV + 40 -#define AIROFLSHGCHR AIROFLSHRST + 1 -#define AIROFLSHSTFL AIROFLSHGCHR + 1 -#define AIROFLSHPCHR AIROFLSHSTFL + 1 -#define AIROFLPUTBUF AIROFLSHPCHR + 1 -#define AIRORESTART AIROFLPUTBUF + 1 - -#define FLASHSIZE 32768 -#define AUXMEMSIZE (256 * 1024) - -typedef struct aironet_ioctl { - unsigned short command; // What to do - unsigned short len; // Len of data - unsigned short ridnum; // rid number - unsigned char __user *data; // d-data -} aironet_ioctl; - -static char swversion[] = "2.1"; -#endif /* CISCO_EXT */ - -#define NUM_MODULES 2 -#define MIC_MSGLEN_MAX 2400 -#define EMMH32_MSGLEN_MAX MIC_MSGLEN_MAX -#define AIRO_DEF_MTU 2312 - -typedef struct { - u32 size; // size - u8 enabled; // MIC enabled or not - u32 rxSuccess; // successful packets received - u32 rxIncorrectMIC; // pkts dropped due to incorrect MIC comparison - u32 rxNotMICed; // pkts dropped due to not being MIC'd - u32 rxMICPlummed; // pkts dropped due to not having a MIC plummed - u32 rxWrongSequence; // pkts dropped due to sequence number violation - u32 reserve[32]; -} mic_statistics; - -typedef struct { - u32 coeff[((EMMH32_MSGLEN_MAX)+3)>>2]; - u64 accum; // accumulated mic, reduced to u32 in final() - int position; // current position (byte offset) in message - union { - u8 d8[4]; - __be32 d32; - } part; // saves partial message word across update() calls -} emmh32_context; - -typedef struct { - emmh32_context seed; // Context - the seed - u32 rx; // Received sequence number - u32 tx; // Tx sequence number - u32 window; // Start of window - u8 valid; // Flag to say if context is valid or not - u8 key[16]; -} miccntx; - -typedef struct { - miccntx mCtx; // Multicast context - miccntx uCtx; // Unicast context -} mic_module; - -typedef struct { - unsigned int rid: 16; - unsigned int len: 15; - unsigned int valid: 1; - dma_addr_t host_addr; -} Rid; - -typedef struct { - unsigned int offset: 15; - unsigned int eoc: 1; - unsigned int len: 15; - unsigned int valid: 1; - dma_addr_t host_addr; -} TxFid; - -struct rx_hdr { - __le16 status, len; - u8 rssi[2]; - u8 rate; - u8 freq; - __le16 tmp[4]; -} __attribute__ ((packed)); - -typedef struct { - unsigned int ctl: 15; - unsigned int rdy: 1; - unsigned int len: 15; - unsigned int valid: 1; - dma_addr_t host_addr; -} RxFid; - -/* - * Host receive descriptor - */ -typedef struct { - unsigned char __iomem *card_ram_off; /* offset into card memory of the - desc */ - RxFid rx_desc; /* card receive descriptor */ - char *virtual_host_addr; /* virtual address of host receive - buffer */ - int pending; -} HostRxDesc; - -/* - * Host transmit descriptor - */ -typedef struct { - unsigned char __iomem *card_ram_off; /* offset into card memory of the - desc */ - TxFid tx_desc; /* card transmit descriptor */ - char *virtual_host_addr; /* virtual address of host receive - buffer */ - int pending; -} HostTxDesc; - -/* - * Host RID descriptor - */ -typedef struct { - unsigned char __iomem *card_ram_off; /* offset into card memory of the - descriptor */ - Rid rid_desc; /* card RID descriptor */ - char *virtual_host_addr; /* virtual address of host receive - buffer */ -} HostRidDesc; - -typedef struct { - u16 sw0; - u16 sw1; - u16 status; - u16 len; -#define HOST_SET (1 << 0) -#define HOST_INT_TX (1 << 1) /* Interrupt on successful TX */ -#define HOST_INT_TXERR (1 << 2) /* Interrupt on unseccessful TX */ -#define HOST_LCC_PAYLOAD (1 << 4) /* LLC payload, 0 = Ethertype */ -#define HOST_DONT_RLSE (1 << 5) /* Don't release buffer when done */ -#define HOST_DONT_RETRY (1 << 6) /* Don't retry trasmit */ -#define HOST_CLR_AID (1 << 7) /* clear AID failure */ -#define HOST_RTS (1 << 9) /* Force RTS use */ -#define HOST_SHORT (1 << 10) /* Do short preamble */ - u16 ctl; - u16 aid; - u16 retries; - u16 fill; -} TxCtlHdr; - -typedef struct { - u16 ctl; - u16 duration; - char addr1[6]; - char addr2[6]; - char addr3[6]; - u16 seq; - char addr4[6]; -} WifiHdr; - - -typedef struct { - TxCtlHdr ctlhdr; - u16 fill1; - u16 fill2; - WifiHdr wifihdr; - u16 gaplen; - u16 status; -} WifiCtlHdr; - -static WifiCtlHdr wifictlhdr8023 = { - .ctlhdr = { - .ctl = HOST_DONT_RLSE, - } -}; - -// A few details needed for WEP (Wireless Equivalent Privacy) -#define MAX_KEY_SIZE 13 // 128 (?) bits -#define MIN_KEY_SIZE 5 // 40 bits RC4 - WEP -typedef struct wep_key_t { - u16 len; - u8 key[16]; /* 40-bit and 104-bit keys */ -} wep_key_t; - -/* List of Wireless Handlers (new API) */ -static const struct iw_handler_def airo_handler_def; - -static const char version[] = "airo.c 0.6 (Ben Reed & Javier Achirica)"; - -struct airo_info; - -static int get_dec_u16( char *buffer, int *start, int limit ); -static void OUT4500( struct airo_info *, u16 register, u16 value ); -static unsigned short IN4500( struct airo_info *, u16 register ); -static u16 setup_card(struct airo_info*, u8 *mac, int lock); -static int enable_MAC(struct airo_info *ai, int lock); -static void disable_MAC(struct airo_info *ai, int lock); -static void enable_interrupts(struct airo_info*); -static void disable_interrupts(struct airo_info*); -static u16 issuecommand(struct airo_info*, Cmd *pCmd, Resp *pRsp); -static int bap_setup(struct airo_info*, u16 rid, u16 offset, int whichbap); -static int aux_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen, - int whichbap); -static int fast_bap_read(struct airo_info*, __le16 *pu16Dst, int bytelen, - int whichbap); -static int bap_write(struct airo_info*, const __le16 *pu16Src, int bytelen, - int whichbap); -static int PC4500_accessrid(struct airo_info*, u16 rid, u16 accmd); -static int PC4500_readrid(struct airo_info*, u16 rid, void *pBuf, int len, int lock); -static int PC4500_writerid(struct airo_info*, u16 rid, const void - *pBuf, int len, int lock); -static int do_writerid( struct airo_info*, u16 rid, const void *rid_data, - int len, int dummy ); -static u16 transmit_allocate(struct airo_info*, int lenPayload, int raw); -static int transmit_802_3_packet(struct airo_info*, int len, char *pPacket); -static int transmit_802_11_packet(struct airo_info*, int len, char *pPacket); - -static int mpi_send_packet (struct net_device *dev); -static void mpi_unmap_card(struct pci_dev *pci); -static void mpi_receive_802_3(struct airo_info *ai); -static void mpi_receive_802_11(struct airo_info *ai); -static int waitbusy (struct airo_info *ai); - -static irqreturn_t airo_interrupt( int irq, void* dev_id); -static int airo_thread(void *data); -static void timer_func( struct net_device *dev ); -static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static struct iw_statistics *airo_get_wireless_stats (struct net_device *dev); -static void airo_read_wireless_stats (struct airo_info *local); -#ifdef CISCO_EXT -static int readrids(struct net_device *dev, aironet_ioctl *comp); -static int writerids(struct net_device *dev, aironet_ioctl *comp); -static int flashcard(struct net_device *dev, aironet_ioctl *comp); -#endif /* CISCO_EXT */ -static void micinit(struct airo_info *ai); -static int micsetup(struct airo_info *ai); -static int encapsulate(struct airo_info *ai, etherHead *pPacket, MICBuffer *buffer, int len); -static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *pPacket, u16 payLen); - -static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi); -static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm); - -static void airo_networks_free(struct airo_info *ai); - -struct airo_info { - struct net_device *dev; - struct list_head dev_list; - /* Note, we can have MAX_FIDS outstanding. FIDs are 16-bits, so we - use the high bit to mark whether it is in use. */ -#define MAX_FIDS 6 -#define MPI_MAX_FIDS 1 - u32 fids[MAX_FIDS]; - ConfigRid config; - char keyindex; // Used with auto wep - char defindex; // Used with auto wep - struct proc_dir_entry *proc_entry; - spinlock_t aux_lock; -#define FLAG_RADIO_OFF 0 /* User disabling of MAC */ -#define FLAG_RADIO_DOWN 1 /* ifup/ifdown disabling of MAC */ -#define FLAG_RADIO_MASK 0x03 -#define FLAG_ENABLED 2 -#define FLAG_ADHOC 3 /* Needed by MIC */ -#define FLAG_MIC_CAPABLE 4 -#define FLAG_UPDATE_MULTI 5 -#define FLAG_UPDATE_UNI 6 -#define FLAG_802_11 7 -#define FLAG_PROMISC 8 /* IFF_PROMISC 0x100 - include/linux/if.h */ -#define FLAG_PENDING_XMIT 9 -#define FLAG_PENDING_XMIT11 10 -#define FLAG_MPI 11 -#define FLAG_REGISTERED 12 -#define FLAG_COMMIT 13 -#define FLAG_RESET 14 -#define FLAG_FLASHING 15 -#define FLAG_WPA_CAPABLE 16 - unsigned long flags; -#define JOB_DIE 0 -#define JOB_XMIT 1 -#define JOB_XMIT11 2 -#define JOB_STATS 3 -#define JOB_PROMISC 4 -#define JOB_MIC 5 -#define JOB_EVENT 6 -#define JOB_AUTOWEP 7 -#define JOB_WSTATS 8 -#define JOB_SCAN_RESULTS 9 - unsigned long jobs; - int (*bap_read)(struct airo_info*, __le16 *pu16Dst, int bytelen, - int whichbap); - unsigned short *flash; - tdsRssiEntry *rssi; - struct task_struct *list_bss_task; - struct task_struct *airo_thread_task; - struct semaphore sem; - wait_queue_head_t thr_wait; - unsigned long expires; - struct { - struct sk_buff *skb; - int fid; - } xmit, xmit11; - struct net_device *wifidev; - struct iw_statistics wstats; // wireless stats - unsigned long scan_timeout; /* Time scan should be read */ - struct iw_spy_data spy_data; - struct iw_public_data wireless_data; - /* MIC stuff */ - struct crypto_cipher *tfm; - mic_module mod[2]; - mic_statistics micstats; - HostRxDesc rxfids[MPI_MAX_FIDS]; // rx/tx/config MPI350 descriptors - HostTxDesc txfids[MPI_MAX_FIDS]; - HostRidDesc config_desc; - unsigned long ridbus; // phys addr of config_desc - struct sk_buff_head txq;// tx queue used by mpi350 code - struct pci_dev *pci; - unsigned char __iomem *pcimem; - unsigned char __iomem *pciaux; - unsigned char *shared; - dma_addr_t shared_dma; - pm_message_t power; - SsidRid *SSID; - APListRid *APList; -#define PCI_SHARED_LEN 2*MPI_MAX_FIDS*PKTSIZE+RIDSIZE - char proc_name[IFNAMSIZ]; - - int wep_capable; - int max_wep_idx; - - /* WPA-related stuff */ - unsigned int bssListFirst; - unsigned int bssListNext; - unsigned int bssListRidLen; - - struct list_head network_list; - struct list_head network_free_list; - BSSListElement *networks; -}; - -static inline int bap_read(struct airo_info *ai, __le16 *pu16Dst, int bytelen, - int whichbap) -{ - return ai->bap_read(ai, pu16Dst, bytelen, whichbap); -} - -static int setup_proc_entry( struct net_device *dev, - struct airo_info *apriv ); -static int takedown_proc_entry( struct net_device *dev, - struct airo_info *apriv ); - -static int cmdreset(struct airo_info *ai); -static int setflashmode (struct airo_info *ai); -static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime); -static int flashputbuf(struct airo_info *ai); -static int flashrestart(struct airo_info *ai,struct net_device *dev); - -#define airo_print(type, name, fmt, args...) \ - printk(type DRV_NAME "(%s): " fmt "\n", name, ##args) - -#define airo_print_info(name, fmt, args...) \ - airo_print(KERN_INFO, name, fmt, ##args) - -#define airo_print_dbg(name, fmt, args...) \ - airo_print(KERN_DEBUG, name, fmt, ##args) - -#define airo_print_warn(name, fmt, args...) \ - airo_print(KERN_WARNING, name, fmt, ##args) - -#define airo_print_err(name, fmt, args...) \ - airo_print(KERN_ERR, name, fmt, ##args) - -#define AIRO_FLASH(dev) (((struct airo_info *)dev->ml_priv)->flash) - -/*********************************************************************** - * MIC ROUTINES * - *********************************************************************** - */ - -static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq); -static void MoveWindow(miccntx *context, u32 micSeq); -static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, - struct crypto_cipher *tfm); -static void emmh32_init(emmh32_context *context); -static void emmh32_update(emmh32_context *context, u8 *pOctets, int len); -static void emmh32_final(emmh32_context *context, u8 digest[4]); -static int flashpchar(struct airo_info *ai,int byte,int dwelltime); - -static void age_mic_context(miccntx *cur, miccntx *old, u8 *key, int key_len, - struct crypto_cipher *tfm) -{ - /* If the current MIC context is valid and its key is the same as - * the MIC register, there's nothing to do. - */ - if (cur->valid && (memcmp(cur->key, key, key_len) == 0)) - return; - - /* Age current mic Context */ - memcpy(old, cur, sizeof(*cur)); - - /* Initialize new context */ - memcpy(cur->key, key, key_len); - cur->window = 33; /* Window always points to the middle */ - cur->rx = 0; /* Rx Sequence numbers */ - cur->tx = 0; /* Tx sequence numbers */ - cur->valid = 1; /* Key is now valid */ - - /* Give key to mic seed */ - emmh32_setseed(&cur->seed, key, key_len, tfm); -} - -/* micinit - Initialize mic seed */ - -static void micinit(struct airo_info *ai) -{ - MICRid mic_rid; - - clear_bit(JOB_MIC, &ai->jobs); - PC4500_readrid(ai, RID_MIC, &mic_rid, sizeof(mic_rid), 0); - up(&ai->sem); - - ai->micstats.enabled = (le16_to_cpu(mic_rid.state) & 0x00FF) ? 1 : 0; - if (!ai->micstats.enabled) { - /* So next time we have a valid key and mic is enabled, we will - * update the sequence number if the key is the same as before. - */ - ai->mod[0].uCtx.valid = 0; - ai->mod[0].mCtx.valid = 0; - return; - } - - if (mic_rid.multicastValid) { - age_mic_context(&ai->mod[0].mCtx, &ai->mod[1].mCtx, - mic_rid.multicast, sizeof(mic_rid.multicast), - ai->tfm); - } - - if (mic_rid.unicastValid) { - age_mic_context(&ai->mod[0].uCtx, &ai->mod[1].uCtx, - mic_rid.unicast, sizeof(mic_rid.unicast), - ai->tfm); - } -} - -/* micsetup - Get ready for business */ - -static int micsetup(struct airo_info *ai) { - int i; - - if (ai->tfm == NULL) - ai->tfm = crypto_alloc_cipher("aes", 0, CRYPTO_ALG_ASYNC); - - if (IS_ERR(ai->tfm)) { - airo_print_err(ai->dev->name, "failed to load transform for AES"); - ai->tfm = NULL; - return ERROR; - } - - for (i=0; i < NUM_MODULES; i++) { - memset(&ai->mod[i].mCtx,0,sizeof(miccntx)); - memset(&ai->mod[i].uCtx,0,sizeof(miccntx)); - } - return SUCCESS; -} - -static char micsnap[] = {0xAA,0xAA,0x03,0x00,0x40,0x96,0x00,0x02}; - -/*=========================================================================== - * Description: Mic a packet - * - * Inputs: etherHead * pointer to an 802.3 frame - * - * Returns: BOOLEAN if successful, otherwise false. - * PacketTxLen will be updated with the mic'd packets size. - * - * Caveats: It is assumed that the frame buffer will already - * be big enough to hold the largets mic message possible. - * (No memory allocation is done here). - * - * Author: sbraneky (10/15/01) - * Merciless hacks by rwilcher (1/14/02) - */ - -static int encapsulate(struct airo_info *ai ,etherHead *frame, MICBuffer *mic, int payLen) -{ - miccntx *context; - - // Determine correct context - // If not adhoc, always use unicast key - - if (test_bit(FLAG_ADHOC, &ai->flags) && (frame->da[0] & 0x1)) - context = &ai->mod[0].mCtx; - else - context = &ai->mod[0].uCtx; - - if (!context->valid) - return ERROR; - - mic->typelen = htons(payLen + 16); //Length of Mic'd packet - - memcpy(&mic->u.snap, micsnap, sizeof(micsnap)); // Add Snap - - // Add Tx sequence - mic->seq = htonl(context->tx); - context->tx += 2; - - emmh32_init(&context->seed); // Mic the packet - emmh32_update(&context->seed,frame->da,ETH_ALEN * 2); // DA,SA - emmh32_update(&context->seed,(u8*)&mic->typelen,10); // Type/Length and Snap - emmh32_update(&context->seed,(u8*)&mic->seq,sizeof(mic->seq)); //SEQ - emmh32_update(&context->seed,frame->da + ETH_ALEN * 2,payLen); //payload - emmh32_final(&context->seed, (u8*)&mic->mic); - - /* New Type/length ?????????? */ - mic->typelen = 0; //Let NIC know it could be an oversized packet - return SUCCESS; -} - -typedef enum { - NONE, - NOMIC, - NOMICPLUMMED, - SEQUENCE, - INCORRECTMIC, -} mic_error; - -/*=========================================================================== - * Description: Decapsulates a MIC'd packet and returns the 802.3 packet - * (removes the MIC stuff) if packet is a valid packet. - * - * Inputs: etherHead pointer to the 802.3 packet - * - * Returns: BOOLEAN - TRUE if packet should be dropped otherwise FALSE - * - * Author: sbraneky (10/15/01) - * Merciless hacks by rwilcher (1/14/02) - *--------------------------------------------------------------------------- - */ - -static int decapsulate(struct airo_info *ai, MICBuffer *mic, etherHead *eth, u16 payLen) -{ - int i; - u32 micSEQ; - miccntx *context; - u8 digest[4]; - mic_error micError = NONE; - - // Check if the packet is a Mic'd packet - - if (!ai->micstats.enabled) { - //No Mic set or Mic OFF but we received a MIC'd packet. - if (memcmp ((u8*)eth + 14, micsnap, sizeof(micsnap)) == 0) { - ai->micstats.rxMICPlummed++; - return ERROR; - } - return SUCCESS; - } - - if (ntohs(mic->typelen) == 0x888E) - return SUCCESS; - - if (memcmp (mic->u.snap, micsnap, sizeof(micsnap)) != 0) { - // Mic enabled but packet isn't Mic'd - ai->micstats.rxMICPlummed++; - return ERROR; - } - - micSEQ = ntohl(mic->seq); //store SEQ as CPU order - - //At this point we a have a mic'd packet and mic is enabled - //Now do the mic error checking. - - //Receive seq must be odd - if ( (micSEQ & 1) == 0 ) { - ai->micstats.rxWrongSequence++; - return ERROR; - } - - for (i = 0; i < NUM_MODULES; i++) { - int mcast = eth->da[0] & 1; - //Determine proper context - context = mcast ? &ai->mod[i].mCtx : &ai->mod[i].uCtx; - - //Make sure context is valid - if (!context->valid) { - if (i == 0) - micError = NOMICPLUMMED; - continue; - } - //DeMic it - - if (!mic->typelen) - mic->typelen = htons(payLen + sizeof(MICBuffer) - 2); - - emmh32_init(&context->seed); - emmh32_update(&context->seed, eth->da, ETH_ALEN*2); - emmh32_update(&context->seed, (u8 *)&mic->typelen, sizeof(mic->typelen)+sizeof(mic->u.snap)); - emmh32_update(&context->seed, (u8 *)&mic->seq,sizeof(mic->seq)); - emmh32_update(&context->seed, eth->da + ETH_ALEN*2,payLen); - //Calculate MIC - emmh32_final(&context->seed, digest); - - if (memcmp(digest, &mic->mic, 4)) { //Make sure the mics match - //Invalid Mic - if (i == 0) - micError = INCORRECTMIC; - continue; - } - - //Check Sequence number if mics pass - if (RxSeqValid(ai, context, mcast, micSEQ) == SUCCESS) { - ai->micstats.rxSuccess++; - return SUCCESS; - } - if (i == 0) - micError = SEQUENCE; - } - - // Update statistics - switch (micError) { - case NOMICPLUMMED: ai->micstats.rxMICPlummed++; break; - case SEQUENCE: ai->micstats.rxWrongSequence++; break; - case INCORRECTMIC: ai->micstats.rxIncorrectMIC++; break; - case NONE: break; - case NOMIC: break; - } - return ERROR; -} - -/*=========================================================================== - * Description: Checks the Rx Seq number to make sure it is valid - * and hasn't already been received - * - * Inputs: miccntx - mic context to check seq against - * micSeq - the Mic seq number - * - * Returns: TRUE if valid otherwise FALSE. - * - * Author: sbraneky (10/15/01) - * Merciless hacks by rwilcher (1/14/02) - *--------------------------------------------------------------------------- - */ - -static int RxSeqValid (struct airo_info *ai,miccntx *context,int mcast,u32 micSeq) -{ - u32 seq,index; - - //Allow for the ap being rebooted - if it is then use the next - //sequence number of the current sequence number - might go backwards - - if (mcast) { - if (test_bit(FLAG_UPDATE_MULTI, &ai->flags)) { - clear_bit (FLAG_UPDATE_MULTI, &ai->flags); - context->window = (micSeq > 33) ? micSeq : 33; - context->rx = 0; // Reset rx - } - } else if (test_bit(FLAG_UPDATE_UNI, &ai->flags)) { - clear_bit (FLAG_UPDATE_UNI, &ai->flags); - context->window = (micSeq > 33) ? micSeq : 33; // Move window - context->rx = 0; // Reset rx - } - - //Make sequence number relative to START of window - seq = micSeq - (context->window - 33); - - //Too old of a SEQ number to check. - if ((s32)seq < 0) - return ERROR; - - if ( seq > 64 ) { - //Window is infinite forward - MoveWindow(context,micSeq); - return SUCCESS; - } - - // We are in the window. Now check the context rx bit to see if it was already sent - seq >>= 1; //divide by 2 because we only have odd numbers - index = 1 << seq; //Get an index number - - if (!(context->rx & index)) { - //micSEQ falls inside the window. - //Add seqence number to the list of received numbers. - context->rx |= index; - - MoveWindow(context,micSeq); - - return SUCCESS; - } - return ERROR; -} - -static void MoveWindow(miccntx *context, u32 micSeq) -{ - u32 shift; - - //Move window if seq greater than the middle of the window - if (micSeq > context->window) { - shift = (micSeq - context->window) >> 1; - - //Shift out old - if (shift < 32) - context->rx >>= shift; - else - context->rx = 0; - - context->window = micSeq; //Move window - } -} - -/*==============================================*/ -/*========== EMMH ROUTINES ====================*/ -/*==============================================*/ - -/* mic accumulate */ -#define MIC_ACCUM(val) \ - context->accum += (u64)(val) * context->coeff[coeff_position++]; - -static unsigned char aes_counter[16]; - -/* expand the key to fill the MMH coefficient array */ -static void emmh32_setseed(emmh32_context *context, u8 *pkey, int keylen, - struct crypto_cipher *tfm) -{ - /* take the keying material, expand if necessary, truncate at 16-bytes */ - /* run through AES counter mode to generate context->coeff[] */ - - int i,j; - u32 counter; - u8 *cipher, plain[16]; - - crypto_cipher_setkey(tfm, pkey, 16); - counter = 0; - for (i = 0; i < ARRAY_SIZE(context->coeff); ) { - aes_counter[15] = (u8)(counter >> 0); - aes_counter[14] = (u8)(counter >> 8); - aes_counter[13] = (u8)(counter >> 16); - aes_counter[12] = (u8)(counter >> 24); - counter++; - memcpy (plain, aes_counter, 16); - crypto_cipher_encrypt_one(tfm, plain, plain); - cipher = plain; - for (j = 0; (j < 16) && (i < ARRAY_SIZE(context->coeff)); ) { - context->coeff[i++] = ntohl(*(__be32 *)&cipher[j]); - j += 4; - } - } -} - -/* prepare for calculation of a new mic */ -static void emmh32_init(emmh32_context *context) -{ - /* prepare for new mic calculation */ - context->accum = 0; - context->position = 0; -} - -/* add some bytes to the mic calculation */ -static void emmh32_update(emmh32_context *context, u8 *pOctets, int len) -{ - int coeff_position, byte_position; - - if (len == 0) return; - - coeff_position = context->position >> 2; - - /* deal with partial 32-bit word left over from last update */ - byte_position = context->position & 3; - if (byte_position) { - /* have a partial word in part to deal with */ - do { - if (len == 0) return; - context->part.d8[byte_position++] = *pOctets++; - context->position++; - len--; - } while (byte_position < 4); - MIC_ACCUM(ntohl(context->part.d32)); - } - - /* deal with full 32-bit words */ - while (len >= 4) { - MIC_ACCUM(ntohl(*(__be32 *)pOctets)); - context->position += 4; - pOctets += 4; - len -= 4; - } - - /* deal with partial 32-bit word that will be left over from this update */ - byte_position = 0; - while (len > 0) { - context->part.d8[byte_position++] = *pOctets++; - context->position++; - len--; - } -} - -/* mask used to zero empty bytes for final partial word */ -static u32 mask32[4] = { 0x00000000L, 0xFF000000L, 0xFFFF0000L, 0xFFFFFF00L }; - -/* calculate the mic */ -static void emmh32_final(emmh32_context *context, u8 digest[4]) -{ - int coeff_position, byte_position; - u32 val; - - u64 sum, utmp; - s64 stmp; - - coeff_position = context->position >> 2; - - /* deal with partial 32-bit word left over from last update */ - byte_position = context->position & 3; - if (byte_position) { - /* have a partial word in part to deal with */ - val = ntohl(context->part.d32); - MIC_ACCUM(val & mask32[byte_position]); /* zero empty bytes */ - } - - /* reduce the accumulated u64 to a 32-bit MIC */ - sum = context->accum; - stmp = (sum & 0xffffffffLL) - ((sum >> 32) * 15); - utmp = (stmp & 0xffffffffLL) - ((stmp >> 32) * 15); - sum = utmp & 0xffffffffLL; - if (utmp > 0x10000000fLL) - sum -= 15; - - val = (u32)sum; - digest[0] = (val>>24) & 0xFF; - digest[1] = (val>>16) & 0xFF; - digest[2] = (val>>8) & 0xFF; - digest[3] = val & 0xFF; -} - -static int readBSSListRid(struct airo_info *ai, int first, - BSSListRid *list) -{ - Cmd cmd; - Resp rsp; - - if (first == 1) { - if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd=CMD_LISTBSS; - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; - ai->list_bss_task = current; - issuecommand(ai, &cmd, &rsp); - up(&ai->sem); - /* Let the command take effect */ - schedule_timeout_uninterruptible(3 * HZ); - ai->list_bss_task = NULL; - } - return PC4500_readrid(ai, first ? ai->bssListFirst : ai->bssListNext, - list, ai->bssListRidLen, 1); -} - -static int readWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int temp, int lock) -{ - return PC4500_readrid(ai, temp ? RID_WEP_TEMP : RID_WEP_PERM, - wkr, sizeof(*wkr), lock); -} - -static int writeWepKeyRid(struct airo_info *ai, WepKeyRid *wkr, int perm, int lock) -{ - int rc; - rc = PC4500_writerid(ai, RID_WEP_TEMP, wkr, sizeof(*wkr), lock); - if (rc!=SUCCESS) - airo_print_err(ai->dev->name, "WEP_TEMP set %x", rc); - if (perm) { - rc = PC4500_writerid(ai, RID_WEP_PERM, wkr, sizeof(*wkr), lock); - if (rc!=SUCCESS) - airo_print_err(ai->dev->name, "WEP_PERM set %x", rc); - } - return rc; -} - -static int readSsidRid(struct airo_info*ai, SsidRid *ssidr) -{ - return PC4500_readrid(ai, RID_SSID, ssidr, sizeof(*ssidr), 1); -} - -static int writeSsidRid(struct airo_info*ai, SsidRid *pssidr, int lock) -{ - return PC4500_writerid(ai, RID_SSID, pssidr, sizeof(*pssidr), lock); -} - -static int readConfigRid(struct airo_info *ai, int lock) -{ - int rc; - ConfigRid cfg; - - if (ai->config.len) - return SUCCESS; - - rc = PC4500_readrid(ai, RID_ACTUALCONFIG, &cfg, sizeof(cfg), lock); - if (rc != SUCCESS) - return rc; - - ai->config = cfg; - return SUCCESS; -} - -static inline void checkThrottle(struct airo_info *ai) -{ - int i; -/* Old hardware had a limit on encryption speed */ - if (ai->config.authType != AUTH_OPEN && maxencrypt) { - for(i=0; i<8; i++) { - if (ai->config.rates[i] > maxencrypt) { - ai->config.rates[i] = 0; - } - } - } -} - -static int writeConfigRid(struct airo_info *ai, int lock) -{ - ConfigRid cfgr; - - if (!test_bit (FLAG_COMMIT, &ai->flags)) - return SUCCESS; - - clear_bit (FLAG_COMMIT, &ai->flags); - clear_bit (FLAG_RESET, &ai->flags); - checkThrottle(ai); - cfgr = ai->config; - - if ((cfgr.opmode & MODE_CFG_MASK) == MODE_STA_IBSS) - set_bit(FLAG_ADHOC, &ai->flags); - else - clear_bit(FLAG_ADHOC, &ai->flags); - - return PC4500_writerid( ai, RID_CONFIG, &cfgr, sizeof(cfgr), lock); -} - -static int readStatusRid(struct airo_info *ai, StatusRid *statr, int lock) -{ - return PC4500_readrid(ai, RID_STATUS, statr, sizeof(*statr), lock); -} - -static int readAPListRid(struct airo_info *ai, APListRid *aplr) -{ - return PC4500_readrid(ai, RID_APLIST, aplr, sizeof(*aplr), 1); -} - -static int writeAPListRid(struct airo_info *ai, APListRid *aplr, int lock) -{ - return PC4500_writerid(ai, RID_APLIST, aplr, sizeof(*aplr), lock); -} - -static int readCapabilityRid(struct airo_info *ai, CapabilityRid *capr, int lock) -{ - return PC4500_readrid(ai, RID_CAPABILITIES, capr, sizeof(*capr), lock); -} - -static int readStatsRid(struct airo_info*ai, StatsRid *sr, int rid, int lock) -{ - return PC4500_readrid(ai, rid, sr, sizeof(*sr), lock); -} - -static void try_auto_wep(struct airo_info *ai) -{ - if (auto_wep && !(ai->flags & FLAG_RADIO_DOWN)) { - ai->expires = RUN_AT(3*HZ); - wake_up_interruptible(&ai->thr_wait); - } -} - -static int airo_open(struct net_device *dev) { - struct airo_info *ai = dev->ml_priv; - int rc = 0; - - if (test_bit(FLAG_FLASHING, &ai->flags)) - return -EIO; - - /* Make sure the card is configured. - * Wireless Extensions may postpone config changes until the card - * is open (to pipeline changes and speed-up card setup). If - * those changes are not yet commited, do it now - Jean II */ - if (test_bit(FLAG_COMMIT, &ai->flags)) { - disable_MAC(ai, 1); - writeConfigRid(ai, 1); - } - - if (ai->wifidev != dev) { - clear_bit(JOB_DIE, &ai->jobs); - ai->airo_thread_task = kthread_run(airo_thread, dev, dev->name); - if (IS_ERR(ai->airo_thread_task)) - return (int)PTR_ERR(ai->airo_thread_task); - - rc = request_irq(dev->irq, airo_interrupt, IRQF_SHARED, - dev->name, dev); - if (rc) { - airo_print_err(dev->name, - "register interrupt %d failed, rc %d", - dev->irq, rc); - set_bit(JOB_DIE, &ai->jobs); - kthread_stop(ai->airo_thread_task); - return rc; - } - - /* Power on the MAC controller (which may have been disabled) */ - clear_bit(FLAG_RADIO_DOWN, &ai->flags); - enable_interrupts(ai); - - try_auto_wep(ai); - } - enable_MAC(ai, 1); - - netif_start_queue(dev); - return 0; -} - -static netdev_tx_t mpi_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - int npacks, pending; - unsigned long flags; - struct airo_info *ai = dev->ml_priv; - - if (!skb) { - airo_print_err(dev->name, "%s: skb == NULL!",__func__); - return NETDEV_TX_OK; - } - npacks = skb_queue_len (&ai->txq); - - if (npacks >= MAXTXQ - 1) { - netif_stop_queue (dev); - if (npacks > MAXTXQ) { - dev->stats.tx_fifo_errors++; - return NETDEV_TX_BUSY; - } - skb_queue_tail (&ai->txq, skb); - return NETDEV_TX_OK; - } - - spin_lock_irqsave(&ai->aux_lock, flags); - skb_queue_tail (&ai->txq, skb); - pending = test_bit(FLAG_PENDING_XMIT, &ai->flags); - spin_unlock_irqrestore(&ai->aux_lock,flags); - netif_wake_queue (dev); - - if (pending == 0) { - set_bit(FLAG_PENDING_XMIT, &ai->flags); - mpi_send_packet (dev); - } - return NETDEV_TX_OK; -} - -/* - * @mpi_send_packet - * - * Attempt to transmit a packet. Can be called from interrupt - * or transmit . return number of packets we tried to send - */ - -static int mpi_send_packet (struct net_device *dev) -{ - struct sk_buff *skb; - unsigned char *buffer; - s16 len; - __le16 *payloadLen; - struct airo_info *ai = dev->ml_priv; - u8 *sendbuf; - - /* get a packet to send */ - - if ((skb = skb_dequeue(&ai->txq)) == NULL) { - airo_print_err(dev->name, - "%s: Dequeue'd zero in send_packet()", - __func__); - return 0; - } - - /* check min length*/ - len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - buffer = skb->data; - - ai->txfids[0].tx_desc.offset = 0; - ai->txfids[0].tx_desc.valid = 1; - ai->txfids[0].tx_desc.eoc = 1; - ai->txfids[0].tx_desc.len =len+sizeof(WifiHdr); - -/* - * Magic, the cards firmware needs a length count (2 bytes) in the host buffer - * right after TXFID_HDR.The TXFID_HDR contains the status short so payloadlen - * is immediatly after it. ------------------------------------------------ - * |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA| - * ------------------------------------------------ - */ - - memcpy((char *)ai->txfids[0].virtual_host_addr, - (char *)&wifictlhdr8023, sizeof(wifictlhdr8023)); - - payloadLen = (__le16 *)(ai->txfids[0].virtual_host_addr + - sizeof(wifictlhdr8023)); - sendbuf = ai->txfids[0].virtual_host_addr + - sizeof(wifictlhdr8023) + 2 ; - - /* - * Firmware automaticly puts 802 header on so - * we don't need to account for it in the length - */ - if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && - (ntohs(((__be16 *)buffer)[6]) != 0x888E)) { - MICBuffer pMic; - - if (encapsulate(ai, (etherHead *)buffer, &pMic, len - sizeof(etherHead)) != SUCCESS) - return ERROR; - - *payloadLen = cpu_to_le16(len-sizeof(etherHead)+sizeof(pMic)); - ai->txfids[0].tx_desc.len += sizeof(pMic); - /* copy data into airo dma buffer */ - memcpy (sendbuf, buffer, sizeof(etherHead)); - buffer += sizeof(etherHead); - sendbuf += sizeof(etherHead); - memcpy (sendbuf, &pMic, sizeof(pMic)); - sendbuf += sizeof(pMic); - memcpy (sendbuf, buffer, len - sizeof(etherHead)); - } else { - *payloadLen = cpu_to_le16(len - sizeof(etherHead)); - - dev->trans_start = jiffies; - - /* copy data into airo dma buffer */ - memcpy(sendbuf, buffer, len); - } - - memcpy_toio(ai->txfids[0].card_ram_off, - &ai->txfids[0].tx_desc, sizeof(TxFid)); - - OUT4500(ai, EVACK, 8); - - dev_kfree_skb_any(skb); - return 1; -} - -static void get_tx_error(struct airo_info *ai, s32 fid) -{ - __le16 status; - - if (fid < 0) - status = ((WifiCtlHdr *)ai->txfids[0].virtual_host_addr)->ctlhdr.status; - else { - if (bap_setup(ai, ai->fids[fid] & 0xffff, 4, BAP0) != SUCCESS) - return; - bap_read(ai, &status, 2, BAP0); - } - if (le16_to_cpu(status) & 2) /* Too many retries */ - ai->dev->stats.tx_aborted_errors++; - if (le16_to_cpu(status) & 4) /* Transmit lifetime exceeded */ - ai->dev->stats.tx_heartbeat_errors++; - if (le16_to_cpu(status) & 8) /* Aid fail */ - { } - if (le16_to_cpu(status) & 0x10) /* MAC disabled */ - ai->dev->stats.tx_carrier_errors++; - if (le16_to_cpu(status) & 0x20) /* Association lost */ - { } - /* We produce a TXDROP event only for retry or lifetime - * exceeded, because that's the only status that really mean - * that this particular node went away. - * Other errors means that *we* screwed up. - Jean II */ - if ((le16_to_cpu(status) & 2) || - (le16_to_cpu(status) & 4)) { - union iwreq_data wrqu; - char junk[0x18]; - - /* Faster to skip over useless data than to do - * another bap_setup(). We are at offset 0x6 and - * need to go to 0x18 and read 6 bytes - Jean II */ - bap_read(ai, (__le16 *) junk, 0x18, BAP0); - - /* Copy 802.11 dest address. - * We use the 802.11 header because the frame may - * not be 802.3 or may be mangled... - * In Ad-Hoc mode, it will be the node address. - * In managed mode, it will be most likely the AP addr - * User space will figure out how to convert it to - * whatever it needs (IP address or else). - * - Jean II */ - memcpy(wrqu.addr.sa_data, junk + 0x12, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(ai->dev, IWEVTXDROP, &wrqu, NULL); - } -} - -static void airo_end_xmit(struct net_device *dev) { - u16 status; - int i; - struct airo_info *priv = dev->ml_priv; - struct sk_buff *skb = priv->xmit.skb; - int fid = priv->xmit.fid; - u32 *fids = priv->fids; - - clear_bit(JOB_XMIT, &priv->jobs); - clear_bit(FLAG_PENDING_XMIT, &priv->flags); - status = transmit_802_3_packet (priv, fids[fid], skb->data); - up(&priv->sem); - - i = 0; - if ( status == SUCCESS ) { - dev->trans_start = jiffies; - for (; i < MAX_FIDS / 2 && (priv->fids[i] & 0xffff0000); i++); - } else { - priv->fids[fid] &= 0xffff; - dev->stats.tx_window_errors++; - } - if (i < MAX_FIDS / 2) - netif_wake_queue(dev); - dev_kfree_skb(skb); -} - -static netdev_tx_t airo_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - s16 len; - int i, j; - struct airo_info *priv = dev->ml_priv; - u32 *fids = priv->fids; - - if ( skb == NULL ) { - airo_print_err(dev->name, "%s: skb == NULL!", __func__); - return NETDEV_TX_OK; - } - - /* Find a vacant FID */ - for( i = 0; i < MAX_FIDS / 2 && (fids[i] & 0xffff0000); i++ ); - for( j = i + 1; j < MAX_FIDS / 2 && (fids[j] & 0xffff0000); j++ ); - - if ( j >= MAX_FIDS / 2 ) { - netif_stop_queue(dev); - - if (i == MAX_FIDS / 2) { - dev->stats.tx_fifo_errors++; - return NETDEV_TX_BUSY; - } - } - /* check min length*/ - len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - /* Mark fid as used & save length for later */ - fids[i] |= (len << 16); - priv->xmit.skb = skb; - priv->xmit.fid = i; - if (down_trylock(&priv->sem) != 0) { - set_bit(FLAG_PENDING_XMIT, &priv->flags); - netif_stop_queue(dev); - set_bit(JOB_XMIT, &priv->jobs); - wake_up_interruptible(&priv->thr_wait); - } else - airo_end_xmit(dev); - return NETDEV_TX_OK; -} - -static void airo_end_xmit11(struct net_device *dev) { - u16 status; - int i; - struct airo_info *priv = dev->ml_priv; - struct sk_buff *skb = priv->xmit11.skb; - int fid = priv->xmit11.fid; - u32 *fids = priv->fids; - - clear_bit(JOB_XMIT11, &priv->jobs); - clear_bit(FLAG_PENDING_XMIT11, &priv->flags); - status = transmit_802_11_packet (priv, fids[fid], skb->data); - up(&priv->sem); - - i = MAX_FIDS / 2; - if ( status == SUCCESS ) { - dev->trans_start = jiffies; - for (; i < MAX_FIDS && (priv->fids[i] & 0xffff0000); i++); - } else { - priv->fids[fid] &= 0xffff; - dev->stats.tx_window_errors++; - } - if (i < MAX_FIDS) - netif_wake_queue(dev); - dev_kfree_skb(skb); -} - -static netdev_tx_t airo_start_xmit11(struct sk_buff *skb, - struct net_device *dev) -{ - s16 len; - int i, j; - struct airo_info *priv = dev->ml_priv; - u32 *fids = priv->fids; - - if (test_bit(FLAG_MPI, &priv->flags)) { - /* Not implemented yet for MPI350 */ - netif_stop_queue(dev); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if ( skb == NULL ) { - airo_print_err(dev->name, "%s: skb == NULL!", __func__); - return NETDEV_TX_OK; - } - - /* Find a vacant FID */ - for( i = MAX_FIDS / 2; i < MAX_FIDS && (fids[i] & 0xffff0000); i++ ); - for( j = i + 1; j < MAX_FIDS && (fids[j] & 0xffff0000); j++ ); - - if ( j >= MAX_FIDS ) { - netif_stop_queue(dev); - - if (i == MAX_FIDS) { - dev->stats.tx_fifo_errors++; - return NETDEV_TX_BUSY; - } - } - /* check min length*/ - len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - /* Mark fid as used & save length for later */ - fids[i] |= (len << 16); - priv->xmit11.skb = skb; - priv->xmit11.fid = i; - if (down_trylock(&priv->sem) != 0) { - set_bit(FLAG_PENDING_XMIT11, &priv->flags); - netif_stop_queue(dev); - set_bit(JOB_XMIT11, &priv->jobs); - wake_up_interruptible(&priv->thr_wait); - } else - airo_end_xmit11(dev); - return NETDEV_TX_OK; -} - -static void airo_read_stats(struct net_device *dev) -{ - struct airo_info *ai = dev->ml_priv; - StatsRid stats_rid; - __le32 *vals = stats_rid.vals; - - clear_bit(JOB_STATS, &ai->jobs); - if (ai->power.event) { - up(&ai->sem); - return; - } - readStatsRid(ai, &stats_rid, RID_STATS, 0); - up(&ai->sem); - - dev->stats.rx_packets = le32_to_cpu(vals[43]) + le32_to_cpu(vals[44]) + - le32_to_cpu(vals[45]); - dev->stats.tx_packets = le32_to_cpu(vals[39]) + le32_to_cpu(vals[40]) + - le32_to_cpu(vals[41]); - dev->stats.rx_bytes = le32_to_cpu(vals[92]); - dev->stats.tx_bytes = le32_to_cpu(vals[91]); - dev->stats.rx_errors = le32_to_cpu(vals[0]) + le32_to_cpu(vals[2]) + - le32_to_cpu(vals[3]) + le32_to_cpu(vals[4]); - dev->stats.tx_errors = le32_to_cpu(vals[42]) + - dev->stats.tx_fifo_errors; - dev->stats.multicast = le32_to_cpu(vals[43]); - dev->stats.collisions = le32_to_cpu(vals[89]); - - /* detailed rx_errors: */ - dev->stats.rx_length_errors = le32_to_cpu(vals[3]); - dev->stats.rx_crc_errors = le32_to_cpu(vals[4]); - dev->stats.rx_frame_errors = le32_to_cpu(vals[2]); - dev->stats.rx_fifo_errors = le32_to_cpu(vals[0]); -} - -static struct net_device_stats *airo_get_stats(struct net_device *dev) -{ - struct airo_info *local = dev->ml_priv; - - if (!test_bit(JOB_STATS, &local->jobs)) { - /* Get stats out of the card if available */ - if (down_trylock(&local->sem) != 0) { - set_bit(JOB_STATS, &local->jobs); - wake_up_interruptible(&local->thr_wait); - } else - airo_read_stats(dev); - } - - return &dev->stats; -} - -static void airo_set_promisc(struct airo_info *ai) { - Cmd cmd; - Resp rsp; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd=CMD_SETMODE; - clear_bit(JOB_PROMISC, &ai->jobs); - cmd.parm0=(ai->flags&IFF_PROMISC) ? PROMISC : NOPROMISC; - issuecommand(ai, &cmd, &rsp); - up(&ai->sem); -} - -static void airo_set_multicast_list(struct net_device *dev) { - struct airo_info *ai = dev->ml_priv; - - if ((dev->flags ^ ai->flags) & IFF_PROMISC) { - change_bit(FLAG_PROMISC, &ai->flags); - if (down_trylock(&ai->sem) != 0) { - set_bit(JOB_PROMISC, &ai->jobs); - wake_up_interruptible(&ai->thr_wait); - } else - airo_set_promisc(ai); - } - - if ((dev->flags&IFF_ALLMULTI)||dev->mc_count>0) { - /* Turn on multicast. (Should be already setup...) */ - } -} - -static int airo_set_mac_address(struct net_device *dev, void *p) -{ - struct airo_info *ai = dev->ml_priv; - struct sockaddr *addr = p; - - readConfigRid(ai, 1); - memcpy (ai->config.macAddr, addr->sa_data, dev->addr_len); - set_bit (FLAG_COMMIT, &ai->flags); - disable_MAC(ai, 1); - writeConfigRid (ai, 1); - enable_MAC(ai, 1); - memcpy (ai->dev->dev_addr, addr->sa_data, dev->addr_len); - if (ai->wifidev) - memcpy (ai->wifidev->dev_addr, addr->sa_data, dev->addr_len); - return 0; -} - -static int airo_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 2400)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -static LIST_HEAD(airo_devices); - -static void add_airo_dev(struct airo_info *ai) -{ - /* Upper layers already keep track of PCI devices, - * so we only need to remember our non-PCI cards. */ - if (!ai->pci) - list_add_tail(&ai->dev_list, &airo_devices); -} - -static void del_airo_dev(struct airo_info *ai) -{ - if (!ai->pci) - list_del(&ai->dev_list); -} - -static int airo_close(struct net_device *dev) { - struct airo_info *ai = dev->ml_priv; - - netif_stop_queue(dev); - - if (ai->wifidev != dev) { -#ifdef POWER_ON_DOWN - /* Shut power to the card. The idea is that the user can save - * power when he doesn't need the card with "ifconfig down". - * That's the method that is most friendly towards the network - * stack (i.e. the network stack won't try to broadcast - * anything on the interface and routes are gone. Jean II */ - set_bit(FLAG_RADIO_DOWN, &ai->flags); - disable_MAC(ai, 1); -#endif - disable_interrupts( ai ); - - free_irq(dev->irq, dev); - - set_bit(JOB_DIE, &ai->jobs); - kthread_stop(ai->airo_thread_task); - } - return 0; -} - -void stop_airo_card( struct net_device *dev, int freeres ) -{ - struct airo_info *ai = dev->ml_priv; - - set_bit(FLAG_RADIO_DOWN, &ai->flags); - disable_MAC(ai, 1); - disable_interrupts(ai); - takedown_proc_entry( dev, ai ); - if (test_bit(FLAG_REGISTERED, &ai->flags)) { - unregister_netdev( dev ); - if (ai->wifidev) { - unregister_netdev(ai->wifidev); - free_netdev(ai->wifidev); - ai->wifidev = NULL; - } - clear_bit(FLAG_REGISTERED, &ai->flags); - } - /* - * Clean out tx queue - */ - if (test_bit(FLAG_MPI, &ai->flags) && !skb_queue_empty(&ai->txq)) { - struct sk_buff *skb = NULL; - for (;(skb = skb_dequeue(&ai->txq));) - dev_kfree_skb(skb); - } - - airo_networks_free (ai); - - kfree(ai->flash); - kfree(ai->rssi); - kfree(ai->APList); - kfree(ai->SSID); - if (freeres) { - /* PCMCIA frees this stuff, so only for PCI and ISA */ - release_region( dev->base_addr, 64 ); - if (test_bit(FLAG_MPI, &ai->flags)) { - if (ai->pci) - mpi_unmap_card(ai->pci); - if (ai->pcimem) - iounmap(ai->pcimem); - if (ai->pciaux) - iounmap(ai->pciaux); - pci_free_consistent(ai->pci, PCI_SHARED_LEN, - ai->shared, ai->shared_dma); - } - } - crypto_free_cipher(ai->tfm); - del_airo_dev(ai); - free_netdev( dev ); -} - -EXPORT_SYMBOL(stop_airo_card); - -static int wll_header_parse(const struct sk_buff *skb, unsigned char *haddr) -{ - memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); - return ETH_ALEN; -} - -static void mpi_unmap_card(struct pci_dev *pci) -{ - unsigned long mem_start = pci_resource_start(pci, 1); - unsigned long mem_len = pci_resource_len(pci, 1); - unsigned long aux_start = pci_resource_start(pci, 2); - unsigned long aux_len = AUXMEMSIZE; - - release_mem_region(aux_start, aux_len); - release_mem_region(mem_start, mem_len); -} - -/************************************************************* - * This routine assumes that descriptors have been setup . - * Run at insmod time or after reset when the decriptors - * have been initialized . Returns 0 if all is well nz - * otherwise . Does not allocate memory but sets up card - * using previously allocated descriptors. - */ -static int mpi_init_descriptors (struct airo_info *ai) -{ - Cmd cmd; - Resp rsp; - int i; - int rc = SUCCESS; - - /* Alloc card RX descriptors */ - netif_stop_queue(ai->dev); - - memset(&rsp,0,sizeof(rsp)); - memset(&cmd,0,sizeof(cmd)); - - cmd.cmd = CMD_ALLOCATEAUX; - cmd.parm0 = FID_RX; - cmd.parm1 = (ai->rxfids[0].card_ram_off - ai->pciaux); - cmd.parm2 = MPI_MAX_FIDS; - rc=issuecommand(ai, &cmd, &rsp); - if (rc != SUCCESS) { - airo_print_err(ai->dev->name, "Couldn't allocate RX FID"); - return rc; - } - - for (i=0; irxfids[i].card_ram_off, - &ai->rxfids[i].rx_desc, sizeof(RxFid)); - } - - /* Alloc card TX descriptors */ - - memset(&rsp,0,sizeof(rsp)); - memset(&cmd,0,sizeof(cmd)); - - cmd.cmd = CMD_ALLOCATEAUX; - cmd.parm0 = FID_TX; - cmd.parm1 = (ai->txfids[0].card_ram_off - ai->pciaux); - cmd.parm2 = MPI_MAX_FIDS; - - for (i=0; itxfids[i].tx_desc.valid = 1; - memcpy_toio(ai->txfids[i].card_ram_off, - &ai->txfids[i].tx_desc, sizeof(TxFid)); - } - ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */ - - rc=issuecommand(ai, &cmd, &rsp); - if (rc != SUCCESS) { - airo_print_err(ai->dev->name, "Couldn't allocate TX FID"); - return rc; - } - - /* Alloc card Rid descriptor */ - memset(&rsp,0,sizeof(rsp)); - memset(&cmd,0,sizeof(cmd)); - - cmd.cmd = CMD_ALLOCATEAUX; - cmd.parm0 = RID_RW; - cmd.parm1 = (ai->config_desc.card_ram_off - ai->pciaux); - cmd.parm2 = 1; /* Magic number... */ - rc=issuecommand(ai, &cmd, &rsp); - if (rc != SUCCESS) { - airo_print_err(ai->dev->name, "Couldn't allocate RID"); - return rc; - } - - memcpy_toio(ai->config_desc.card_ram_off, - &ai->config_desc.rid_desc, sizeof(Rid)); - - return rc; -} - -/* - * We are setting up three things here: - * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid. - * 2) Map PCI memory for issueing commands. - * 3) Allocate memory (shared) to send and receive ethernet frames. - */ -static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci) -{ - unsigned long mem_start, mem_len, aux_start, aux_len; - int rc = -1; - int i; - dma_addr_t busaddroff; - unsigned char *vpackoff; - unsigned char __iomem *pciaddroff; - - mem_start = pci_resource_start(pci, 1); - mem_len = pci_resource_len(pci, 1); - aux_start = pci_resource_start(pci, 2); - aux_len = AUXMEMSIZE; - - if (!request_mem_region(mem_start, mem_len, DRV_NAME)) { - airo_print_err("", "Couldn't get region %x[%x]", - (int)mem_start, (int)mem_len); - goto out; - } - if (!request_mem_region(aux_start, aux_len, DRV_NAME)) { - airo_print_err("", "Couldn't get region %x[%x]", - (int)aux_start, (int)aux_len); - goto free_region1; - } - - ai->pcimem = ioremap(mem_start, mem_len); - if (!ai->pcimem) { - airo_print_err("", "Couldn't map region %x[%x]", - (int)mem_start, (int)mem_len); - goto free_region2; - } - ai->pciaux = ioremap(aux_start, aux_len); - if (!ai->pciaux) { - airo_print_err("", "Couldn't map region %x[%x]", - (int)aux_start, (int)aux_len); - goto free_memmap; - } - - /* Reserve PKTSIZE for each fid and 2K for the Rids */ - ai->shared = pci_alloc_consistent(pci, PCI_SHARED_LEN, &ai->shared_dma); - if (!ai->shared) { - airo_print_err("", "Couldn't alloc_consistent %d", - PCI_SHARED_LEN); - goto free_auxmap; - } - - /* - * Setup descriptor RX, TX, CONFIG - */ - busaddroff = ai->shared_dma; - pciaddroff = ai->pciaux + AUX_OFFSET; - vpackoff = ai->shared; - - /* RX descriptor setup */ - for(i = 0; i < MPI_MAX_FIDS; i++) { - ai->rxfids[i].pending = 0; - ai->rxfids[i].card_ram_off = pciaddroff; - ai->rxfids[i].virtual_host_addr = vpackoff; - ai->rxfids[i].rx_desc.host_addr = busaddroff; - ai->rxfids[i].rx_desc.valid = 1; - ai->rxfids[i].rx_desc.len = PKTSIZE; - ai->rxfids[i].rx_desc.rdy = 0; - - pciaddroff += sizeof(RxFid); - busaddroff += PKTSIZE; - vpackoff += PKTSIZE; - } - - /* TX descriptor setup */ - for(i = 0; i < MPI_MAX_FIDS; i++) { - ai->txfids[i].card_ram_off = pciaddroff; - ai->txfids[i].virtual_host_addr = vpackoff; - ai->txfids[i].tx_desc.valid = 1; - ai->txfids[i].tx_desc.host_addr = busaddroff; - memcpy(ai->txfids[i].virtual_host_addr, - &wifictlhdr8023, sizeof(wifictlhdr8023)); - - pciaddroff += sizeof(TxFid); - busaddroff += PKTSIZE; - vpackoff += PKTSIZE; - } - ai->txfids[i-1].tx_desc.eoc = 1; /* Last descriptor has EOC set */ - - /* Rid descriptor setup */ - ai->config_desc.card_ram_off = pciaddroff; - ai->config_desc.virtual_host_addr = vpackoff; - ai->config_desc.rid_desc.host_addr = busaddroff; - ai->ridbus = busaddroff; - ai->config_desc.rid_desc.rid = 0; - ai->config_desc.rid_desc.len = RIDSIZE; - ai->config_desc.rid_desc.valid = 1; - pciaddroff += sizeof(Rid); - busaddroff += RIDSIZE; - vpackoff += RIDSIZE; - - /* Tell card about descriptors */ - if (mpi_init_descriptors (ai) != SUCCESS) - goto free_shared; - - return 0; - free_shared: - pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma); - free_auxmap: - iounmap(ai->pciaux); - free_memmap: - iounmap(ai->pcimem); - free_region2: - release_mem_region(aux_start, aux_len); - free_region1: - release_mem_region(mem_start, mem_len); - out: - return rc; -} - -static const struct header_ops airo_header_ops = { - .parse = wll_header_parse, -}; - -static const struct net_device_ops airo11_netdev_ops = { - .ndo_open = airo_open, - .ndo_stop = airo_close, - .ndo_start_xmit = airo_start_xmit11, - .ndo_get_stats = airo_get_stats, - .ndo_set_mac_address = airo_set_mac_address, - .ndo_do_ioctl = airo_ioctl, - .ndo_change_mtu = airo_change_mtu, -}; - -static void wifi_setup(struct net_device *dev) -{ - dev->netdev_ops = &airo11_netdev_ops; - dev->header_ops = &airo_header_ops; - dev->wireless_handlers = &airo_handler_def; - - dev->type = ARPHRD_IEEE80211; - dev->hard_header_len = ETH_HLEN; - dev->mtu = AIRO_DEF_MTU; - dev->addr_len = ETH_ALEN; - dev->tx_queue_len = 100; - - memset(dev->broadcast,0xFF, ETH_ALEN); - - dev->flags = IFF_BROADCAST|IFF_MULTICAST; -} - -static struct net_device *init_wifidev(struct airo_info *ai, - struct net_device *ethdev) -{ - int err; - struct net_device *dev = alloc_netdev(0, "wifi%d", wifi_setup); - if (!dev) - return NULL; - dev->ml_priv = ethdev->ml_priv; - dev->irq = ethdev->irq; - dev->base_addr = ethdev->base_addr; - dev->wireless_data = ethdev->wireless_data; - SET_NETDEV_DEV(dev, ethdev->dev.parent); - memcpy(dev->dev_addr, ethdev->dev_addr, dev->addr_len); - err = register_netdev(dev); - if (err<0) { - free_netdev(dev); - return NULL; - } - return dev; -} - -static int reset_card( struct net_device *dev , int lock) { - struct airo_info *ai = dev->ml_priv; - - if (lock && down_interruptible(&ai->sem)) - return -1; - waitbusy (ai); - OUT4500(ai,COMMAND,CMD_SOFTRESET); - msleep(200); - waitbusy (ai); - msleep(200); - if (lock) - up(&ai->sem); - return 0; -} - -#define AIRO_MAX_NETWORK_COUNT 64 -static int airo_networks_allocate(struct airo_info *ai) -{ - if (ai->networks) - return 0; - - ai->networks = - kzalloc(AIRO_MAX_NETWORK_COUNT * sizeof(BSSListElement), - GFP_KERNEL); - if (!ai->networks) { - airo_print_warn("", "Out of memory allocating beacons"); - return -ENOMEM; - } - - return 0; -} - -static void airo_networks_free(struct airo_info *ai) -{ - kfree(ai->networks); - ai->networks = NULL; -} - -static void airo_networks_initialize(struct airo_info *ai) -{ - int i; - - INIT_LIST_HEAD(&ai->network_free_list); - INIT_LIST_HEAD(&ai->network_list); - for (i = 0; i < AIRO_MAX_NETWORK_COUNT; i++) - list_add_tail(&ai->networks[i].list, - &ai->network_free_list); -} - -static const struct net_device_ops airo_netdev_ops = { - .ndo_open = airo_open, - .ndo_stop = airo_close, - .ndo_start_xmit = airo_start_xmit, - .ndo_get_stats = airo_get_stats, - .ndo_set_multicast_list = airo_set_multicast_list, - .ndo_set_mac_address = airo_set_mac_address, - .ndo_do_ioctl = airo_ioctl, - .ndo_change_mtu = airo_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -static const struct net_device_ops mpi_netdev_ops = { - .ndo_open = airo_open, - .ndo_stop = airo_close, - .ndo_start_xmit = mpi_start_xmit, - .ndo_get_stats = airo_get_stats, - .ndo_set_multicast_list = airo_set_multicast_list, - .ndo_set_mac_address = airo_set_mac_address, - .ndo_do_ioctl = airo_ioctl, - .ndo_change_mtu = airo_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - - -static struct net_device *_init_airo_card( unsigned short irq, int port, - int is_pcmcia, struct pci_dev *pci, - struct device *dmdev ) -{ - struct net_device *dev; - struct airo_info *ai; - int i, rc; - CapabilityRid cap_rid; - - /* Create the network device object. */ - dev = alloc_netdev(sizeof(*ai), "", ether_setup); - if (!dev) { - airo_print_err("", "Couldn't alloc_etherdev"); - return NULL; - } - - ai = dev->ml_priv = netdev_priv(dev); - ai->wifidev = NULL; - ai->flags = 1 << FLAG_RADIO_DOWN; - ai->jobs = 0; - ai->dev = dev; - if (pci && (pci->device == 0x5000 || pci->device == 0xa504)) { - airo_print_dbg("", "Found an MPI350 card"); - set_bit(FLAG_MPI, &ai->flags); - } - spin_lock_init(&ai->aux_lock); - sema_init(&ai->sem, 1); - ai->config.len = 0; - ai->pci = pci; - init_waitqueue_head (&ai->thr_wait); - ai->tfm = NULL; - add_airo_dev(ai); - - if (airo_networks_allocate (ai)) - goto err_out_free; - airo_networks_initialize (ai); - - skb_queue_head_init (&ai->txq); - - /* The Airo-specific entries in the device structure. */ - if (test_bit(FLAG_MPI,&ai->flags)) - dev->netdev_ops = &mpi_netdev_ops; - else - dev->netdev_ops = &airo_netdev_ops; - dev->wireless_handlers = &airo_handler_def; - ai->wireless_data.spy_data = &ai->spy_data; - dev->wireless_data = &ai->wireless_data; - dev->irq = irq; - dev->base_addr = port; - - SET_NETDEV_DEV(dev, dmdev); - - reset_card (dev, 1); - msleep(400); - - if (!is_pcmcia) { - if (!request_region(dev->base_addr, 64, DRV_NAME)) { - rc = -EBUSY; - airo_print_err(dev->name, "Couldn't request region"); - goto err_out_nets; - } - } - - if (test_bit(FLAG_MPI,&ai->flags)) { - if (mpi_map_card(ai, pci)) { - airo_print_err("", "Could not map memory"); - goto err_out_res; - } - } - - if (probe) { - if (setup_card(ai, dev->dev_addr, 1) != SUCCESS) { - airo_print_err(dev->name, "MAC could not be enabled" ); - rc = -EIO; - goto err_out_map; - } - } else if (!test_bit(FLAG_MPI,&ai->flags)) { - ai->bap_read = fast_bap_read; - set_bit(FLAG_FLASHING, &ai->flags); - } - - strcpy(dev->name, "eth%d"); - rc = register_netdev(dev); - if (rc) { - airo_print_err(dev->name, "Couldn't register_netdev"); - goto err_out_map; - } - ai->wifidev = init_wifidev(ai, dev); - if (!ai->wifidev) - goto err_out_reg; - - rc = readCapabilityRid(ai, &cap_rid, 1); - if (rc != SUCCESS) { - rc = -EIO; - goto err_out_wifi; - } - /* WEP capability discovery */ - ai->wep_capable = (cap_rid.softCap & cpu_to_le16(0x02)) ? 1 : 0; - ai->max_wep_idx = (cap_rid.softCap & cpu_to_le16(0x80)) ? 3 : 0; - - airo_print_info(dev->name, "Firmware version %x.%x.%02x", - ((le16_to_cpu(cap_rid.softVer) >> 8) & 0xF), - (le16_to_cpu(cap_rid.softVer) & 0xFF), - le16_to_cpu(cap_rid.softSubVer)); - - /* Test for WPA support */ - /* Only firmware versions 5.30.17 or better can do WPA */ - if (le16_to_cpu(cap_rid.softVer) > 0x530 - || (le16_to_cpu(cap_rid.softVer) == 0x530 - && le16_to_cpu(cap_rid.softSubVer) >= 17)) { - airo_print_info(ai->dev->name, "WPA supported."); - - set_bit(FLAG_WPA_CAPABLE, &ai->flags); - ai->bssListFirst = RID_WPA_BSSLISTFIRST; - ai->bssListNext = RID_WPA_BSSLISTNEXT; - ai->bssListRidLen = sizeof(BSSListRid); - } else { - airo_print_info(ai->dev->name, "WPA unsupported with firmware " - "versions older than 5.30.17."); - - ai->bssListFirst = RID_BSSLISTFIRST; - ai->bssListNext = RID_BSSLISTNEXT; - ai->bssListRidLen = sizeof(BSSListRid) - sizeof(BSSListRidExtra); - } - - set_bit(FLAG_REGISTERED,&ai->flags); - airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); - - /* Allocate the transmit buffers */ - if (probe && !test_bit(FLAG_MPI,&ai->flags)) - for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate(ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); - - if (setup_proc_entry(dev, dev->ml_priv) < 0) - goto err_out_wifi; - - return dev; - -err_out_wifi: - unregister_netdev(ai->wifidev); - free_netdev(ai->wifidev); -err_out_reg: - unregister_netdev(dev); -err_out_map: - if (test_bit(FLAG_MPI,&ai->flags) && pci) { - pci_free_consistent(pci, PCI_SHARED_LEN, ai->shared, ai->shared_dma); - iounmap(ai->pciaux); - iounmap(ai->pcimem); - mpi_unmap_card(ai->pci); - } -err_out_res: - if (!is_pcmcia) - release_region( dev->base_addr, 64 ); -err_out_nets: - airo_networks_free(ai); - del_airo_dev(ai); -err_out_free: - free_netdev(dev); - return NULL; -} - -struct net_device *init_airo_card( unsigned short irq, int port, int is_pcmcia, - struct device *dmdev) -{ - return _init_airo_card ( irq, port, is_pcmcia, NULL, dmdev); -} - -EXPORT_SYMBOL(init_airo_card); - -static int waitbusy (struct airo_info *ai) { - int delay = 0; - while ((IN4500(ai, COMMAND) & COMMAND_BUSY) && (delay < 10000)) { - udelay (10); - if ((++delay % 20) == 0) - OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); - } - return delay < 10000; -} - -int reset_airo_card( struct net_device *dev ) -{ - int i; - struct airo_info *ai = dev->ml_priv; - - if (reset_card (dev, 1)) - return -1; - - if ( setup_card(ai, dev->dev_addr, 1 ) != SUCCESS ) { - airo_print_err(dev->name, "MAC could not be enabled"); - return -1; - } - airo_print_info(dev->name, "MAC enabled %pM", dev->dev_addr); - /* Allocate the transmit buffers if needed */ - if (!test_bit(FLAG_MPI,&ai->flags)) - for( i = 0; i < MAX_FIDS; i++ ) - ai->fids[i] = transmit_allocate (ai,AIRO_DEF_MTU,i>=MAX_FIDS/2); - - enable_interrupts( ai ); - netif_wake_queue(dev); - return 0; -} - -EXPORT_SYMBOL(reset_airo_card); - -static void airo_send_event(struct net_device *dev) { - struct airo_info *ai = dev->ml_priv; - union iwreq_data wrqu; - StatusRid status_rid; - - clear_bit(JOB_EVENT, &ai->jobs); - PC4500_readrid(ai, RID_STATUS, &status_rid, sizeof(status_rid), 0); - up(&ai->sem); - wrqu.data.length = 0; - wrqu.data.flags = 0; - memcpy(wrqu.ap_addr.sa_data, status_rid.bssid[0], ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); -} - -static void airo_process_scan_results (struct airo_info *ai) { - union iwreq_data wrqu; - BSSListRid bss; - int rc; - BSSListElement * loop_net; - BSSListElement * tmp_net; - - /* Blow away current list of scan results */ - list_for_each_entry_safe (loop_net, tmp_net, &ai->network_list, list) { - list_move_tail (&loop_net->list, &ai->network_free_list); - /* Don't blow away ->list, just BSS data */ - memset (loop_net, 0, sizeof (loop_net->bss)); - } - - /* Try to read the first entry of the scan result */ - rc = PC4500_readrid(ai, ai->bssListFirst, &bss, ai->bssListRidLen, 0); - if((rc) || (bss.index == cpu_to_le16(0xffff))) { - /* No scan results */ - goto out; - } - - /* Read and parse all entries */ - tmp_net = NULL; - while((!rc) && (bss.index != cpu_to_le16(0xffff))) { - /* Grab a network off the free list */ - if (!list_empty(&ai->network_free_list)) { - tmp_net = list_entry(ai->network_free_list.next, - BSSListElement, list); - list_del(ai->network_free_list.next); - } - - if (tmp_net != NULL) { - memcpy(tmp_net, &bss, sizeof(tmp_net->bss)); - list_add_tail(&tmp_net->list, &ai->network_list); - tmp_net = NULL; - } - - /* Read next entry */ - rc = PC4500_readrid(ai, ai->bssListNext, - &bss, ai->bssListRidLen, 0); - } - -out: - ai->scan_timeout = 0; - clear_bit(JOB_SCAN_RESULTS, &ai->jobs); - up(&ai->sem); - - /* Send an empty event to user space. - * We don't send the received data on - * the event because it would require - * us to do complex transcoding, and - * we want to minimise the work done in - * the irq handler. Use a request to - * extract the data - Jean II */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(ai->dev, SIOCGIWSCAN, &wrqu, NULL); -} - -static int airo_thread(void *data) { - struct net_device *dev = data; - struct airo_info *ai = dev->ml_priv; - int locked; - - set_freezable(); - while(1) { - /* make swsusp happy with our thread */ - try_to_freeze(); - - if (test_bit(JOB_DIE, &ai->jobs)) - break; - - if (ai->jobs) { - locked = down_interruptible(&ai->sem); - } else { - wait_queue_t wait; - - init_waitqueue_entry(&wait, current); - add_wait_queue(&ai->thr_wait, &wait); - for (;;) { - set_current_state(TASK_INTERRUPTIBLE); - if (ai->jobs) - break; - if (ai->expires || ai->scan_timeout) { - if (ai->scan_timeout && - time_after_eq(jiffies,ai->scan_timeout)){ - set_bit(JOB_SCAN_RESULTS, &ai->jobs); - break; - } else if (ai->expires && - time_after_eq(jiffies,ai->expires)){ - set_bit(JOB_AUTOWEP, &ai->jobs); - break; - } - if (!kthread_should_stop() && - !freezing(current)) { - unsigned long wake_at; - if (!ai->expires || !ai->scan_timeout) { - wake_at = max(ai->expires, - ai->scan_timeout); - } else { - wake_at = min(ai->expires, - ai->scan_timeout); - } - schedule_timeout(wake_at - jiffies); - continue; - } - } else if (!kthread_should_stop() && - !freezing(current)) { - schedule(); - continue; - } - break; - } - current->state = TASK_RUNNING; - remove_wait_queue(&ai->thr_wait, &wait); - locked = 1; - } - - if (locked) - continue; - - if (test_bit(JOB_DIE, &ai->jobs)) { - up(&ai->sem); - break; - } - - if (ai->power.event || test_bit(FLAG_FLASHING, &ai->flags)) { - up(&ai->sem); - continue; - } - - if (test_bit(JOB_XMIT, &ai->jobs)) - airo_end_xmit(dev); - else if (test_bit(JOB_XMIT11, &ai->jobs)) - airo_end_xmit11(dev); - else if (test_bit(JOB_STATS, &ai->jobs)) - airo_read_stats(dev); - else if (test_bit(JOB_WSTATS, &ai->jobs)) - airo_read_wireless_stats(ai); - else if (test_bit(JOB_PROMISC, &ai->jobs)) - airo_set_promisc(ai); - else if (test_bit(JOB_MIC, &ai->jobs)) - micinit(ai); - else if (test_bit(JOB_EVENT, &ai->jobs)) - airo_send_event(dev); - else if (test_bit(JOB_AUTOWEP, &ai->jobs)) - timer_func(dev); - else if (test_bit(JOB_SCAN_RESULTS, &ai->jobs)) - airo_process_scan_results(ai); - else /* Shouldn't get here, but we make sure to unlock */ - up(&ai->sem); - } - - return 0; -} - -static int header_len(__le16 ctl) -{ - u16 fc = le16_to_cpu(ctl); - switch (fc & 0xc) { - case 4: - if ((fc & 0xe0) == 0xc0) - return 10; /* one-address control packet */ - return 16; /* two-address control packet */ - case 8: - if ((fc & 0x300) == 0x300) - return 30; /* WDS packet */ - } - return 24; -} - -static void airo_handle_cisco_mic(struct airo_info *ai) -{ - if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) { - set_bit(JOB_MIC, &ai->jobs); - wake_up_interruptible(&ai->thr_wait); - } -} - -/* Airo Status codes */ -#define STAT_NOBEACON 0x8000 /* Loss of sync - missed beacons */ -#define STAT_MAXRETRIES 0x8001 /* Loss of sync - max retries */ -#define STAT_MAXARL 0x8002 /* Loss of sync - average retry level exceeded*/ -#define STAT_FORCELOSS 0x8003 /* Loss of sync - host request */ -#define STAT_TSFSYNC 0x8004 /* Loss of sync - TSF synchronization */ -#define STAT_DEAUTH 0x8100 /* low byte is 802.11 reason code */ -#define STAT_DISASSOC 0x8200 /* low byte is 802.11 reason code */ -#define STAT_ASSOC_FAIL 0x8400 /* low byte is 802.11 reason code */ -#define STAT_AUTH_FAIL 0x0300 /* low byte is 802.11 reason code */ -#define STAT_ASSOC 0x0400 /* Associated */ -#define STAT_REASSOC 0x0600 /* Reassociated? Only on firmware >= 5.30.17 */ - -static void airo_print_status(const char *devname, u16 status) -{ - u8 reason = status & 0xFF; - - switch (status) { - case STAT_NOBEACON: - airo_print_dbg(devname, "link lost (missed beacons)"); - break; - case STAT_MAXRETRIES: - case STAT_MAXARL: - airo_print_dbg(devname, "link lost (max retries)"); - break; - case STAT_FORCELOSS: - airo_print_dbg(devname, "link lost (local choice)"); - break; - case STAT_TSFSYNC: - airo_print_dbg(devname, "link lost (TSF sync lost)"); - break; - case STAT_DEAUTH: - airo_print_dbg(devname, "deauthenticated (reason: %d)", reason); - break; - case STAT_DISASSOC: - airo_print_dbg(devname, "disassociated (reason: %d)", reason); - break; - case STAT_ASSOC_FAIL: - airo_print_dbg(devname, "association failed (reason: %d)", - reason); - break; - case STAT_AUTH_FAIL: - airo_print_dbg(devname, "authentication failed (reason: %d)", - reason); - break; - default: - break; - } -} - -static void airo_handle_link(struct airo_info *ai) -{ - union iwreq_data wrqu; - int scan_forceloss = 0; - u16 status; - - /* Get new status and acknowledge the link change */ - status = le16_to_cpu(IN4500(ai, LINKSTAT)); - OUT4500(ai, EVACK, EV_LINK); - - if ((status == STAT_FORCELOSS) && (ai->scan_timeout > 0)) - scan_forceloss = 1; - - airo_print_status(ai->dev->name, status); - - if ((status == STAT_ASSOC) || (status == STAT_REASSOC)) { - if (auto_wep) - ai->expires = 0; - if (ai->list_bss_task) - wake_up_process(ai->list_bss_task); - set_bit(FLAG_UPDATE_UNI, &ai->flags); - set_bit(FLAG_UPDATE_MULTI, &ai->flags); - - if (down_trylock(&ai->sem) != 0) { - set_bit(JOB_EVENT, &ai->jobs); - wake_up_interruptible(&ai->thr_wait); - } else - airo_send_event(ai->dev); - } else if (!scan_forceloss) { - if (auto_wep && !ai->expires) { - ai->expires = RUN_AT(3*HZ); - wake_up_interruptible(&ai->thr_wait); - } - - /* Send event to user space */ - memset(wrqu.ap_addr.sa_data, '\0', ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(ai->dev, SIOCGIWAP, &wrqu, NULL); - } -} - -static void airo_handle_rx(struct airo_info *ai) -{ - struct sk_buff *skb = NULL; - __le16 fc, v, *buffer, tmpbuf[4]; - u16 len, hdrlen = 0, gap, fid; - struct rx_hdr hdr; - int success = 0; - - if (test_bit(FLAG_MPI, &ai->flags)) { - if (test_bit(FLAG_802_11, &ai->flags)) - mpi_receive_802_11(ai); - else - mpi_receive_802_3(ai); - OUT4500(ai, EVACK, EV_RX); - return; - } - - fid = IN4500(ai, RXFID); - - /* Get the packet length */ - if (test_bit(FLAG_802_11, &ai->flags)) { - bap_setup (ai, fid, 4, BAP0); - bap_read (ai, (__le16*)&hdr, sizeof(hdr), BAP0); - /* Bad CRC. Ignore packet */ - if (le16_to_cpu(hdr.status) & 2) - hdr.len = 0; - if (ai->wifidev == NULL) - hdr.len = 0; - } else { - bap_setup(ai, fid, 0x36, BAP0); - bap_read(ai, &hdr.len, 2, BAP0); - } - len = le16_to_cpu(hdr.len); - - if (len > AIRO_DEF_MTU) { - airo_print_err(ai->dev->name, "Bad size %d", len); - goto done; - } - if (len == 0) - goto done; - - if (test_bit(FLAG_802_11, &ai->flags)) { - bap_read(ai, &fc, sizeof (fc), BAP0); - hdrlen = header_len(fc); - } else - hdrlen = ETH_ALEN * 2; - - skb = dev_alloc_skb(len + hdrlen + 2 + 2); - if (!skb) { - ai->dev->stats.rx_dropped++; - goto done; - } - - skb_reserve(skb, 2); /* This way the IP header is aligned */ - buffer = (__le16 *) skb_put(skb, len + hdrlen); - if (test_bit(FLAG_802_11, &ai->flags)) { - buffer[0] = fc; - bap_read(ai, buffer + 1, hdrlen - 2, BAP0); - if (hdrlen == 24) - bap_read(ai, tmpbuf, 6, BAP0); - - bap_read(ai, &v, sizeof(v), BAP0); - gap = le16_to_cpu(v); - if (gap) { - if (gap <= 8) { - bap_read(ai, tmpbuf, gap, BAP0); - } else { - airo_print_err(ai->dev->name, "gaplen too " - "big. Problems will follow..."); - } - } - bap_read(ai, buffer + hdrlen/2, len, BAP0); - } else { - MICBuffer micbuf; - - bap_read(ai, buffer, ETH_ALEN * 2, BAP0); - if (ai->micstats.enabled) { - bap_read(ai, (__le16 *) &micbuf, sizeof (micbuf), BAP0); - if (ntohs(micbuf.typelen) > 0x05DC) - bap_setup(ai, fid, 0x44, BAP0); - else { - if (len <= sizeof (micbuf)) { - dev_kfree_skb_irq(skb); - goto done; - } - - len -= sizeof(micbuf); - skb_trim(skb, len + hdrlen); - } - } - - bap_read(ai, buffer + ETH_ALEN, len, BAP0); - if (decapsulate(ai, &micbuf, (etherHead*) buffer, len)) - dev_kfree_skb_irq (skb); - else - success = 1; - } - -#ifdef WIRELESS_SPY - if (success && (ai->spy_data.spy_number > 0)) { - char *sa; - struct iw_quality wstats; - - /* Prepare spy data : addr + qual */ - if (!test_bit(FLAG_802_11, &ai->flags)) { - sa = (char *) buffer + 6; - bap_setup(ai, fid, 8, BAP0); - bap_read(ai, (__le16 *) hdr.rssi, 2, BAP0); - } else - sa = (char *) buffer + 10; - wstats.qual = hdr.rssi[0]; - if (ai->rssi) - wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; - else - wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.noise = ai->wstats.qual.noise; - wstats.updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_QUAL_UPDATED - | IW_QUAL_DBM; - /* Update spy records */ - wireless_spy_update(ai->dev, sa, &wstats); - } -#endif /* WIRELESS_SPY */ - -done: - OUT4500(ai, EVACK, EV_RX); - - if (success) { - if (test_bit(FLAG_802_11, &ai->flags)) { - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_OTHERHOST; - skb->dev = ai->wifidev; - skb->protocol = htons(ETH_P_802_2); - } else - skb->protocol = eth_type_trans(skb, ai->dev); - skb->ip_summed = CHECKSUM_NONE; - - netif_rx(skb); - } -} - -static void airo_handle_tx(struct airo_info *ai, u16 status) -{ - int i, len = 0, index = -1; - u16 fid; - - if (test_bit(FLAG_MPI, &ai->flags)) { - unsigned long flags; - - if (status & EV_TXEXC) - get_tx_error(ai, -1); - - spin_lock_irqsave(&ai->aux_lock, flags); - if (!skb_queue_empty(&ai->txq)) { - spin_unlock_irqrestore(&ai->aux_lock,flags); - mpi_send_packet(ai->dev); - } else { - clear_bit(FLAG_PENDING_XMIT, &ai->flags); - spin_unlock_irqrestore(&ai->aux_lock,flags); - netif_wake_queue(ai->dev); - } - OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - return; - } - - fid = IN4500(ai, TXCOMPLFID); - - for(i = 0; i < MAX_FIDS; i++) { - if ((ai->fids[i] & 0xffff) == fid) { - len = ai->fids[i] >> 16; - index = i; - } - } - - if (index != -1) { - if (status & EV_TXEXC) - get_tx_error(ai, index); - - OUT4500(ai, EVACK, status & (EV_TX | EV_TXEXC)); - - /* Set up to be used again */ - ai->fids[index] &= 0xffff; - if (index < MAX_FIDS / 2) { - if (!test_bit(FLAG_PENDING_XMIT, &ai->flags)) - netif_wake_queue(ai->dev); - } else { - if (!test_bit(FLAG_PENDING_XMIT11, &ai->flags)) - netif_wake_queue(ai->wifidev); - } - } else { - OUT4500(ai, EVACK, status & (EV_TX | EV_TXCPY | EV_TXEXC)); - airo_print_err(ai->dev->name, "Unallocated FID was used to xmit"); - } -} - -static irqreturn_t airo_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - u16 status, savedInterrupts = 0; - struct airo_info *ai = dev->ml_priv; - int handled = 0; - - if (!netif_device_present(dev)) - return IRQ_NONE; - - for (;;) { - status = IN4500(ai, EVSTAT); - if (!(status & STATUS_INTS) || (status == 0xffff)) - break; - - handled = 1; - - if (status & EV_AWAKE) { - OUT4500(ai, EVACK, EV_AWAKE); - OUT4500(ai, EVACK, EV_AWAKE); - } - - if (!savedInterrupts) { - savedInterrupts = IN4500(ai, EVINTEN); - OUT4500(ai, EVINTEN, 0); - } - - if (status & EV_MIC) { - OUT4500(ai, EVACK, EV_MIC); - airo_handle_cisco_mic(ai); - } - - if (status & EV_LINK) { - /* Link status changed */ - airo_handle_link(ai); - } - - /* Check to see if there is something to receive */ - if (status & EV_RX) - airo_handle_rx(ai); - - /* Check to see if a packet has been transmitted */ - if (status & (EV_TX | EV_TXCPY | EV_TXEXC)) - airo_handle_tx(ai, status); - - if ( status & ~STATUS_INTS & ~IGNORE_INTS ) { - airo_print_warn(ai->dev->name, "Got weird status %x", - status & ~STATUS_INTS & ~IGNORE_INTS ); - } - } - - if (savedInterrupts) - OUT4500(ai, EVINTEN, savedInterrupts); - - return IRQ_RETVAL(handled); -} - -/* - * Routines to talk to the card - */ - -/* - * This was originally written for the 4500, hence the name - * NOTE: If use with 8bit mode and SMP bad things will happen! - * Why would some one do 8 bit IO in an SMP machine?!? - */ -static void OUT4500( struct airo_info *ai, u16 reg, u16 val ) { - if (test_bit(FLAG_MPI,&ai->flags)) - reg <<= 1; - if ( !do8bitIO ) - outw( val, ai->dev->base_addr + reg ); - else { - outb( val & 0xff, ai->dev->base_addr + reg ); - outb( val >> 8, ai->dev->base_addr + reg + 1 ); - } -} - -static u16 IN4500( struct airo_info *ai, u16 reg ) { - unsigned short rc; - - if (test_bit(FLAG_MPI,&ai->flags)) - reg <<= 1; - if ( !do8bitIO ) - rc = inw( ai->dev->base_addr + reg ); - else { - rc = inb( ai->dev->base_addr + reg ); - rc += ((int)inb( ai->dev->base_addr + reg + 1 )) << 8; - } - return rc; -} - -static int enable_MAC(struct airo_info *ai, int lock) -{ - int rc; - Cmd cmd; - Resp rsp; - - /* FLAG_RADIO_OFF : Radio disabled via /proc or Wireless Extensions - * FLAG_RADIO_DOWN : Radio disabled via "ifconfig ethX down" - * Note : we could try to use !netif_running(dev) in enable_MAC() - * instead of this flag, but I don't trust it *within* the - * open/close functions, and testing both flags together is - * "cheaper" - Jean II */ - if (ai->flags & FLAG_RADIO_MASK) return SUCCESS; - - if (lock && down_interruptible(&ai->sem)) - return -ERESTARTSYS; - - if (!test_bit(FLAG_ENABLED, &ai->flags)) { - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = MAC_ENABLE; - rc = issuecommand(ai, &cmd, &rsp); - if (rc == SUCCESS) - set_bit(FLAG_ENABLED, &ai->flags); - } else - rc = SUCCESS; - - if (lock) - up(&ai->sem); - - if (rc) - airo_print_err(ai->dev->name, "Cannot enable MAC"); - else if ((rsp.status & 0xFF00) != 0) { - airo_print_err(ai->dev->name, "Bad MAC enable reason=%x, " - "rid=%x, offset=%d", rsp.rsp0, rsp.rsp1, rsp.rsp2); - rc = ERROR; - } - return rc; -} - -static void disable_MAC( struct airo_info *ai, int lock ) { - Cmd cmd; - Resp rsp; - - if (lock && down_interruptible(&ai->sem)) - return; - - if (test_bit(FLAG_ENABLED, &ai->flags)) { - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = MAC_DISABLE; // disable in case already enabled - issuecommand(ai, &cmd, &rsp); - clear_bit(FLAG_ENABLED, &ai->flags); - } - if (lock) - up(&ai->sem); -} - -static void enable_interrupts( struct airo_info *ai ) { - /* Enable the interrupts */ - OUT4500( ai, EVINTEN, STATUS_INTS ); -} - -static void disable_interrupts( struct airo_info *ai ) { - OUT4500( ai, EVINTEN, 0 ); -} - -static void mpi_receive_802_3(struct airo_info *ai) -{ - RxFid rxd; - int len = 0; - struct sk_buff *skb; - char *buffer; - int off = 0; - MICBuffer micbuf; - - memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); - /* Make sure we got something */ - if (rxd.rdy && rxd.valid == 0) { - len = rxd.len + 12; - if (len < 12 || len > 2048) - goto badrx; - - skb = dev_alloc_skb(len); - if (!skb) { - ai->dev->stats.rx_dropped++; - goto badrx; - } - buffer = skb_put(skb,len); - memcpy(buffer, ai->rxfids[0].virtual_host_addr, ETH_ALEN * 2); - if (ai->micstats.enabled) { - memcpy(&micbuf, - ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2, - sizeof(micbuf)); - if (ntohs(micbuf.typelen) <= 0x05DC) { - if (len <= sizeof(micbuf) + ETH_ALEN * 2) - goto badmic; - - off = sizeof(micbuf); - skb_trim (skb, len - off); - } - } - memcpy(buffer + ETH_ALEN * 2, - ai->rxfids[0].virtual_host_addr + ETH_ALEN * 2 + off, - len - ETH_ALEN * 2 - off); - if (decapsulate (ai, &micbuf, (etherHead*)buffer, len - off - ETH_ALEN * 2)) { -badmic: - dev_kfree_skb_irq (skb); - goto badrx; - } -#ifdef WIRELESS_SPY - if (ai->spy_data.spy_number > 0) { - char *sa; - struct iw_quality wstats; - /* Prepare spy data : addr + qual */ - sa = buffer + ETH_ALEN; - wstats.qual = 0; /* XXX Where do I get that info from ??? */ - wstats.level = 0; - wstats.updated = 0; - /* Update spy records */ - wireless_spy_update(ai->dev, sa, &wstats); - } -#endif /* WIRELESS_SPY */ - - skb->ip_summed = CHECKSUM_NONE; - skb->protocol = eth_type_trans(skb, ai->dev); - netif_rx(skb); - } -badrx: - if (rxd.valid == 0) { - rxd.valid = 1; - rxd.rdy = 0; - rxd.len = PKTSIZE; - memcpy_toio(ai->rxfids[0].card_ram_off, &rxd, sizeof(rxd)); - } -} - -static void mpi_receive_802_11(struct airo_info *ai) -{ - RxFid rxd; - struct sk_buff *skb = NULL; - u16 len, hdrlen = 0; - __le16 fc; - struct rx_hdr hdr; - u16 gap; - u16 *buffer; - char *ptr = ai->rxfids[0].virtual_host_addr + 4; - - memcpy_fromio(&rxd, ai->rxfids[0].card_ram_off, sizeof(rxd)); - memcpy ((char *)&hdr, ptr, sizeof(hdr)); - ptr += sizeof(hdr); - /* Bad CRC. Ignore packet */ - if (le16_to_cpu(hdr.status) & 2) - hdr.len = 0; - if (ai->wifidev == NULL) - hdr.len = 0; - len = le16_to_cpu(hdr.len); - if (len > AIRO_DEF_MTU) { - airo_print_err(ai->dev->name, "Bad size %d", len); - goto badrx; - } - if (len == 0) - goto badrx; - - fc = get_unaligned((__le16 *)ptr); - hdrlen = header_len(fc); - - skb = dev_alloc_skb( len + hdrlen + 2 ); - if ( !skb ) { - ai->dev->stats.rx_dropped++; - goto badrx; - } - buffer = (u16*)skb_put (skb, len + hdrlen); - memcpy ((char *)buffer, ptr, hdrlen); - ptr += hdrlen; - if (hdrlen == 24) - ptr += 6; - gap = get_unaligned_le16(ptr); - ptr += sizeof(__le16); - if (gap) { - if (gap <= 8) - ptr += gap; - else - airo_print_err(ai->dev->name, - "gaplen too big. Problems will follow..."); - } - memcpy ((char *)buffer + hdrlen, ptr, len); - ptr += len; -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ - if (ai->spy_data.spy_number > 0) { - char *sa; - struct iw_quality wstats; - /* Prepare spy data : addr + qual */ - sa = (char*)buffer + 10; - wstats.qual = hdr.rssi[0]; - if (ai->rssi) - wstats.level = 0x100 - ai->rssi[hdr.rssi[1]].rssidBm; - else - wstats.level = (hdr.rssi[1] + 321) / 2; - wstats.noise = ai->wstats.qual.noise; - wstats.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_DBM; - /* Update spy records */ - wireless_spy_update(ai->dev, sa, &wstats); - } -#endif /* IW_WIRELESS_SPY */ - skb_reset_mac_header(skb); - skb->pkt_type = PACKET_OTHERHOST; - skb->dev = ai->wifidev; - skb->protocol = htons(ETH_P_802_2); - skb->ip_summed = CHECKSUM_NONE; - netif_rx( skb ); - -badrx: - if (rxd.valid == 0) { - rxd.valid = 1; - rxd.rdy = 0; - rxd.len = PKTSIZE; - memcpy_toio(ai->rxfids[0].card_ram_off, &rxd, sizeof(rxd)); - } -} - -static u16 setup_card(struct airo_info *ai, u8 *mac, int lock) -{ - Cmd cmd; - Resp rsp; - int status; - SsidRid mySsid; - __le16 lastindex; - WepKeyRid wkr; - int rc; - - memset( &mySsid, 0, sizeof( mySsid ) ); - kfree (ai->flash); - ai->flash = NULL; - - /* The NOP is the first step in getting the card going */ - cmd.cmd = NOP; - cmd.parm0 = cmd.parm1 = cmd.parm2 = 0; - if (lock && down_interruptible(&ai->sem)) - return ERROR; - if ( issuecommand( ai, &cmd, &rsp ) != SUCCESS ) { - if (lock) - up(&ai->sem); - return ERROR; - } - disable_MAC( ai, 0); - - // Let's figure out if we need to use the AUX port - if (!test_bit(FLAG_MPI,&ai->flags)) { - cmd.cmd = CMD_ENABLEAUX; - if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { - if (lock) - up(&ai->sem); - airo_print_err(ai->dev->name, "Error checking for AUX port"); - return ERROR; - } - if (!aux_bap || rsp.status & 0xff00) { - ai->bap_read = fast_bap_read; - airo_print_dbg(ai->dev->name, "Doing fast bap_reads"); - } else { - ai->bap_read = aux_bap_read; - airo_print_dbg(ai->dev->name, "Doing AUX bap_reads"); - } - } - if (lock) - up(&ai->sem); - if (ai->config.len == 0) { - int i; - tdsRssiRid rssi_rid; - CapabilityRid cap_rid; - - kfree(ai->APList); - ai->APList = NULL; - kfree(ai->SSID); - ai->SSID = NULL; - // general configuration (read/modify/write) - status = readConfigRid(ai, lock); - if ( status != SUCCESS ) return ERROR; - - status = readCapabilityRid(ai, &cap_rid, lock); - if ( status != SUCCESS ) return ERROR; - - status = PC4500_readrid(ai,RID_RSSI,&rssi_rid,sizeof(rssi_rid),lock); - if ( status == SUCCESS ) { - if (ai->rssi || (ai->rssi = kmalloc(512, GFP_KERNEL)) != NULL) - memcpy(ai->rssi, (u8*)&rssi_rid + 2, 512); /* Skip RID length member */ - } - else { - kfree(ai->rssi); - ai->rssi = NULL; - if (cap_rid.softCap & cpu_to_le16(8)) - ai->config.rmode |= RXMODE_NORMALIZED_RSSI; - else - airo_print_warn(ai->dev->name, "unknown received signal " - "level scale"); - } - ai->config.opmode = adhoc ? MODE_STA_IBSS : MODE_STA_ESS; - ai->config.authType = AUTH_OPEN; - ai->config.modulation = MOD_CCK; - - if (le16_to_cpu(cap_rid.len) >= sizeof(cap_rid) && - (cap_rid.extSoftCap & cpu_to_le16(1)) && - micsetup(ai) == SUCCESS) { - ai->config.opmode |= MODE_MIC; - set_bit(FLAG_MIC_CAPABLE, &ai->flags); - } - - /* Save off the MAC */ - for( i = 0; i < ETH_ALEN; i++ ) { - mac[i] = ai->config.macAddr[i]; - } - - /* Check to see if there are any insmod configured - rates to add */ - if ( rates[0] ) { - memset(ai->config.rates,0,sizeof(ai->config.rates)); - for( i = 0; i < 8 && rates[i]; i++ ) { - ai->config.rates[i] = rates[i]; - } - } - if ( basic_rate > 0 ) { - for( i = 0; i < 8; i++ ) { - if ( ai->config.rates[i] == basic_rate || - !ai->config.rates ) { - ai->config.rates[i] = basic_rate | 0x80; - break; - } - } - } - set_bit (FLAG_COMMIT, &ai->flags); - } - - /* Setup the SSIDs if present */ - if ( ssids[0] ) { - int i; - for( i = 0; i < 3 && ssids[i]; i++ ) { - size_t len = strlen(ssids[i]); - if (len > 32) - len = 32; - mySsid.ssids[i].len = cpu_to_le16(len); - memcpy(mySsid.ssids[i].ssid, ssids[i], len); - } - mySsid.len = cpu_to_le16(sizeof(mySsid)); - } - - status = writeConfigRid(ai, lock); - if ( status != SUCCESS ) return ERROR; - - /* Set up the SSID list */ - if ( ssids[0] ) { - status = writeSsidRid(ai, &mySsid, lock); - if ( status != SUCCESS ) return ERROR; - } - - status = enable_MAC(ai, lock); - if (status != SUCCESS) - return ERROR; - - /* Grab the initial wep key, we gotta save it for auto_wep */ - rc = readWepKeyRid(ai, &wkr, 1, lock); - if (rc == SUCCESS) do { - lastindex = wkr.kindex; - if (wkr.kindex == cpu_to_le16(0xffff)) { - ai->defindex = wkr.mac[0]; - } - rc = readWepKeyRid(ai, &wkr, 0, lock); - } while(lastindex != wkr.kindex); - - try_auto_wep(ai); - - return SUCCESS; -} - -static u16 issuecommand(struct airo_info *ai, Cmd *pCmd, Resp *pRsp) { - // Im really paranoid about letting it run forever! - int max_tries = 600000; - - if (IN4500(ai, EVSTAT) & EV_CMD) - OUT4500(ai, EVACK, EV_CMD); - - OUT4500(ai, PARAM0, pCmd->parm0); - OUT4500(ai, PARAM1, pCmd->parm1); - OUT4500(ai, PARAM2, pCmd->parm2); - OUT4500(ai, COMMAND, pCmd->cmd); - - while (max_tries-- && (IN4500(ai, EVSTAT) & EV_CMD) == 0) { - if ((IN4500(ai, COMMAND)) == pCmd->cmd) - // PC4500 didn't notice command, try again - OUT4500(ai, COMMAND, pCmd->cmd); - if (!in_atomic() && (max_tries & 255) == 0) - schedule(); - } - - if ( max_tries == -1 ) { - airo_print_err(ai->dev->name, - "Max tries exceeded when issueing command"); - if (IN4500(ai, COMMAND) & COMMAND_BUSY) - OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); - return ERROR; - } - - // command completed - pRsp->status = IN4500(ai, STATUS); - pRsp->rsp0 = IN4500(ai, RESP0); - pRsp->rsp1 = IN4500(ai, RESP1); - pRsp->rsp2 = IN4500(ai, RESP2); - if ((pRsp->status & 0xff00)!=0 && pCmd->cmd != CMD_SOFTRESET) - airo_print_err(ai->dev->name, - "cmd:%x status:%x rsp0:%x rsp1:%x rsp2:%x", - pCmd->cmd, pRsp->status, pRsp->rsp0, pRsp->rsp1, - pRsp->rsp2); - - // clear stuck command busy if necessary - if (IN4500(ai, COMMAND) & COMMAND_BUSY) { - OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY); - } - // acknowledge processing the status/response - OUT4500(ai, EVACK, EV_CMD); - - return SUCCESS; -} - -/* Sets up the bap to start exchange data. whichbap should - * be one of the BAP0 or BAP1 defines. Locks should be held before - * calling! */ -static int bap_setup(struct airo_info *ai, u16 rid, u16 offset, int whichbap ) -{ - int timeout = 50; - int max_tries = 3; - - OUT4500(ai, SELECT0+whichbap, rid); - OUT4500(ai, OFFSET0+whichbap, offset); - while (1) { - int status = IN4500(ai, OFFSET0+whichbap); - if (status & BAP_BUSY) { - /* This isn't really a timeout, but its kinda - close */ - if (timeout--) { - continue; - } - } else if ( status & BAP_ERR ) { - /* invalid rid or offset */ - airo_print_err(ai->dev->name, "BAP error %x %d", - status, whichbap ); - return ERROR; - } else if (status & BAP_DONE) { // success - return SUCCESS; - } - if ( !(max_tries--) ) { - airo_print_err(ai->dev->name, - "BAP setup error too many retries\n"); - return ERROR; - } - // -- PC4500 missed it, try again - OUT4500(ai, SELECT0+whichbap, rid); - OUT4500(ai, OFFSET0+whichbap, offset); - timeout = 50; - } -} - -/* should only be called by aux_bap_read. This aux function and the - following use concepts not documented in the developers guide. I - got them from a patch given to my by Aironet */ -static u16 aux_setup(struct airo_info *ai, u16 page, - u16 offset, u16 *len) -{ - u16 next; - - OUT4500(ai, AUXPAGE, page); - OUT4500(ai, AUXOFF, 0); - next = IN4500(ai, AUXDATA); - *len = IN4500(ai, AUXDATA)&0xff; - if (offset != 4) OUT4500(ai, AUXOFF, offset); - return next; -} - -/* requires call to bap_setup() first */ -static int aux_bap_read(struct airo_info *ai, __le16 *pu16Dst, - int bytelen, int whichbap) -{ - u16 len; - u16 page; - u16 offset; - u16 next; - int words; - int i; - unsigned long flags; - - spin_lock_irqsave(&ai->aux_lock, flags); - page = IN4500(ai, SWS0+whichbap); - offset = IN4500(ai, SWS2+whichbap); - next = aux_setup(ai, page, offset, &len); - words = (bytelen+1)>>1; - - for (i=0; i>1) < (words-i) ? (len>>1) : (words-i); - if ( !do8bitIO ) - insw( ai->dev->base_addr+DATA0+whichbap, - pu16Dst+i,count ); - else - insb( ai->dev->base_addr+DATA0+whichbap, - pu16Dst+i, count << 1 ); - i += count; - if (iaux_lock, flags); - return SUCCESS; -} - - -/* requires call to bap_setup() first */ -static int fast_bap_read(struct airo_info *ai, __le16 *pu16Dst, - int bytelen, int whichbap) -{ - bytelen = (bytelen + 1) & (~1); // round up to even value - if ( !do8bitIO ) - insw( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen>>1 ); - else - insb( ai->dev->base_addr+DATA0+whichbap, pu16Dst, bytelen ); - return SUCCESS; -} - -/* requires call to bap_setup() first */ -static int bap_write(struct airo_info *ai, const __le16 *pu16Src, - int bytelen, int whichbap) -{ - bytelen = (bytelen + 1) & (~1); // round up to even value - if ( !do8bitIO ) - outsw( ai->dev->base_addr+DATA0+whichbap, - pu16Src, bytelen>>1 ); - else - outsb( ai->dev->base_addr+DATA0+whichbap, pu16Src, bytelen ); - return SUCCESS; -} - -static int PC4500_accessrid(struct airo_info *ai, u16 rid, u16 accmd) -{ - Cmd cmd; /* for issuing commands */ - Resp rsp; /* response from commands */ - u16 status; - - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd = accmd; - cmd.parm0 = rid; - status = issuecommand(ai, &cmd, &rsp); - if (status != 0) return status; - if ( (rsp.status & 0x7F00) != 0) { - return (accmd << 8) + (rsp.rsp0 & 0xFF); - } - return 0; -} - -/* Note, that we are using BAP1 which is also used by transmit, so - * we must get a lock. */ -static int PC4500_readrid(struct airo_info *ai, u16 rid, void *pBuf, int len, int lock) -{ - u16 status; - int rc = SUCCESS; - - if (lock) { - if (down_interruptible(&ai->sem)) - return ERROR; - } - if (test_bit(FLAG_MPI,&ai->flags)) { - Cmd cmd; - Resp rsp; - - memset(&cmd, 0, sizeof(cmd)); - memset(&rsp, 0, sizeof(rsp)); - ai->config_desc.rid_desc.valid = 1; - ai->config_desc.rid_desc.len = RIDSIZE; - ai->config_desc.rid_desc.rid = 0; - ai->config_desc.rid_desc.host_addr = ai->ridbus; - - cmd.cmd = CMD_ACCESS; - cmd.parm0 = rid; - - memcpy_toio(ai->config_desc.card_ram_off, - &ai->config_desc.rid_desc, sizeof(Rid)); - - rc = issuecommand(ai, &cmd, &rsp); - - if (rsp.status & 0x7f00) - rc = rsp.rsp0; - if (!rc) - memcpy(pBuf, ai->config_desc.virtual_host_addr, len); - goto done; - } else { - if ((status = PC4500_accessrid(ai, rid, CMD_ACCESS))!=SUCCESS) { - rc = status; - goto done; - } - if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) { - rc = ERROR; - goto done; - } - // read the rid length field - bap_read(ai, pBuf, 2, BAP1); - // length for remaining part of rid - len = min(len, (int)le16_to_cpu(*(__le16*)pBuf)) - 2; - - if ( len <= 2 ) { - airo_print_err(ai->dev->name, - "Rid %x has a length of %d which is too short", - (int)rid, (int)len ); - rc = ERROR; - goto done; - } - // read remainder of the rid - rc = bap_read(ai, ((__le16*)pBuf)+1, len, BAP1); - } -done: - if (lock) - up(&ai->sem); - return rc; -} - -/* Note, that we are using BAP1 which is also used by transmit, so - * make sure this isnt called when a transmit is happening */ -static int PC4500_writerid(struct airo_info *ai, u16 rid, - const void *pBuf, int len, int lock) -{ - u16 status; - int rc = SUCCESS; - - *(__le16*)pBuf = cpu_to_le16((u16)len); - - if (lock) { - if (down_interruptible(&ai->sem)) - return ERROR; - } - if (test_bit(FLAG_MPI,&ai->flags)) { - Cmd cmd; - Resp rsp; - - if (test_bit(FLAG_ENABLED, &ai->flags) && (RID_WEP_TEMP != rid)) - airo_print_err(ai->dev->name, - "%s: MAC should be disabled (rid=%04x)", - __func__, rid); - memset(&cmd, 0, sizeof(cmd)); - memset(&rsp, 0, sizeof(rsp)); - - ai->config_desc.rid_desc.valid = 1; - ai->config_desc.rid_desc.len = *((u16 *)pBuf); - ai->config_desc.rid_desc.rid = 0; - - cmd.cmd = CMD_WRITERID; - cmd.parm0 = rid; - - memcpy_toio(ai->config_desc.card_ram_off, - &ai->config_desc.rid_desc, sizeof(Rid)); - - if (len < 4 || len > 2047) { - airo_print_err(ai->dev->name, "%s: len=%d", __func__, len); - rc = -1; - } else { - memcpy((char *)ai->config_desc.virtual_host_addr, - pBuf, len); - - rc = issuecommand(ai, &cmd, &rsp); - if ((rc & 0xff00) != 0) { - airo_print_err(ai->dev->name, "%s: Write rid Error %d", - __func__, rc); - airo_print_err(ai->dev->name, "%s: Cmd=%04x", - __func__, cmd.cmd); - } - - if ((rsp.status & 0x7f00)) - rc = rsp.rsp0; - } - } else { - // --- first access so that we can write the rid data - if ( (status = PC4500_accessrid(ai, rid, CMD_ACCESS)) != 0) { - rc = status; - goto done; - } - // --- now write the rid data - if (bap_setup(ai, rid, 0, BAP1) != SUCCESS) { - rc = ERROR; - goto done; - } - bap_write(ai, pBuf, len, BAP1); - // ---now commit the rid data - rc = PC4500_accessrid(ai, rid, 0x100|CMD_ACCESS); - } -done: - if (lock) - up(&ai->sem); - return rc; -} - -/* Allocates a FID to be used for transmitting packets. We only use - one for now. */ -static u16 transmit_allocate(struct airo_info *ai, int lenPayload, int raw) -{ - unsigned int loop = 3000; - Cmd cmd; - Resp rsp; - u16 txFid; - __le16 txControl; - - cmd.cmd = CMD_ALLOCATETX; - cmd.parm0 = lenPayload; - if (down_interruptible(&ai->sem)) - return ERROR; - if (issuecommand(ai, &cmd, &rsp) != SUCCESS) { - txFid = ERROR; - goto done; - } - if ( (rsp.status & 0xFF00) != 0) { - txFid = ERROR; - goto done; - } - /* wait for the allocate event/indication - * It makes me kind of nervous that this can just sit here and spin, - * but in practice it only loops like four times. */ - while (((IN4500(ai, EVSTAT) & EV_ALLOC) == 0) && --loop); - if (!loop) { - txFid = ERROR; - goto done; - } - - // get the allocated fid and acknowledge - txFid = IN4500(ai, TXALLOCFID); - OUT4500(ai, EVACK, EV_ALLOC); - - /* The CARD is pretty cool since it converts the ethernet packet - * into 802.11. Also note that we don't release the FID since we - * will be using the same one over and over again. */ - /* We only have to setup the control once since we are not - * releasing the fid. */ - if (raw) - txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_11 - | TXCTL_ETHERNET | TXCTL_NORELEASE); - else - txControl = cpu_to_le16(TXCTL_TXOK | TXCTL_TXEX | TXCTL_802_3 - | TXCTL_ETHERNET | TXCTL_NORELEASE); - if (bap_setup(ai, txFid, 0x0008, BAP1) != SUCCESS) - txFid = ERROR; - else - bap_write(ai, &txControl, sizeof(txControl), BAP1); - -done: - up(&ai->sem); - - return txFid; -} - -/* In general BAP1 is dedicated to transmiting packets. However, - since we need a BAP when accessing RIDs, we also use BAP1 for that. - Make sure the BAP1 spinlock is held when this is called. */ -static int transmit_802_3_packet(struct airo_info *ai, int len, char *pPacket) -{ - __le16 payloadLen; - Cmd cmd; - Resp rsp; - int miclen = 0; - u16 txFid = len; - MICBuffer pMic; - - len >>= 16; - - if (len <= ETH_ALEN * 2) { - airo_print_warn(ai->dev->name, "Short packet %d", len); - return ERROR; - } - len -= ETH_ALEN * 2; - - if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled && - (ntohs(((__be16 *)pPacket)[6]) != 0x888E)) { - if (encapsulate(ai,(etherHead *)pPacket,&pMic,len) != SUCCESS) - return ERROR; - miclen = sizeof(pMic); - } - // packet is destination[6], source[6], payload[len-12] - // write the payload length and dst/src/payload - if (bap_setup(ai, txFid, 0x0036, BAP1) != SUCCESS) return ERROR; - /* The hardware addresses aren't counted as part of the payload, so - * we have to subtract the 12 bytes for the addresses off */ - payloadLen = cpu_to_le16(len + miclen); - bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); - bap_write(ai, (__le16*)pPacket, sizeof(etherHead), BAP1); - if (miclen) - bap_write(ai, (__le16*)&pMic, miclen, BAP1); - bap_write(ai, (__le16*)(pPacket + sizeof(etherHead)), len, BAP1); - // issue the transmit command - memset( &cmd, 0, sizeof( cmd ) ); - cmd.cmd = CMD_TRANSMIT; - cmd.parm0 = txFid; - if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR; - if ( (rsp.status & 0xFF00) != 0) return ERROR; - return SUCCESS; -} - -static int transmit_802_11_packet(struct airo_info *ai, int len, char *pPacket) -{ - __le16 fc, payloadLen; - Cmd cmd; - Resp rsp; - int hdrlen; - static u8 tail[(30-10) + 2 + 6] = {[30-10] = 6}; - /* padding of header to full size + le16 gaplen (6) + gaplen bytes */ - u16 txFid = len; - len >>= 16; - - fc = *(__le16*)pPacket; - hdrlen = header_len(fc); - - if (len < hdrlen) { - airo_print_warn(ai->dev->name, "Short packet %d", len); - return ERROR; - } - - /* packet is 802.11 header + payload - * write the payload length and dst/src/payload */ - if (bap_setup(ai, txFid, 6, BAP1) != SUCCESS) return ERROR; - /* The 802.11 header aren't counted as part of the payload, so - * we have to subtract the header bytes off */ - payloadLen = cpu_to_le16(len-hdrlen); - bap_write(ai, &payloadLen, sizeof(payloadLen),BAP1); - if (bap_setup(ai, txFid, 0x0014, BAP1) != SUCCESS) return ERROR; - bap_write(ai, (__le16 *)pPacket, hdrlen, BAP1); - bap_write(ai, (__le16 *)(tail + (hdrlen - 10)), 38 - hdrlen, BAP1); - - bap_write(ai, (__le16 *)(pPacket + hdrlen), len - hdrlen, BAP1); - // issue the transmit command - memset( &cmd, 0, sizeof( cmd ) ); - cmd.cmd = CMD_TRANSMIT; - cmd.parm0 = txFid; - if (issuecommand(ai, &cmd, &rsp) != SUCCESS) return ERROR; - if ( (rsp.status & 0xFF00) != 0) return ERROR; - return SUCCESS; -} - -/* - * This is the proc_fs routines. It is a bit messier than I would - * like! Feel free to clean it up! - */ - -static ssize_t proc_read( struct file *file, - char __user *buffer, - size_t len, - loff_t *offset); - -static ssize_t proc_write( struct file *file, - const char __user *buffer, - size_t len, - loff_t *offset ); -static int proc_close( struct inode *inode, struct file *file ); - -static int proc_stats_open( struct inode *inode, struct file *file ); -static int proc_statsdelta_open( struct inode *inode, struct file *file ); -static int proc_status_open( struct inode *inode, struct file *file ); -static int proc_SSID_open( struct inode *inode, struct file *file ); -static int proc_APList_open( struct inode *inode, struct file *file ); -static int proc_BSSList_open( struct inode *inode, struct file *file ); -static int proc_config_open( struct inode *inode, struct file *file ); -static int proc_wepkey_open( struct inode *inode, struct file *file ); - -static const struct file_operations proc_statsdelta_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .open = proc_statsdelta_open, - .release = proc_close -}; - -static const struct file_operations proc_stats_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .open = proc_stats_open, - .release = proc_close -}; - -static const struct file_operations proc_status_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .open = proc_status_open, - .release = proc_close -}; - -static const struct file_operations proc_SSID_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_SSID_open, - .release = proc_close -}; - -static const struct file_operations proc_BSSList_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_BSSList_open, - .release = proc_close -}; - -static const struct file_operations proc_APList_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_APList_open, - .release = proc_close -}; - -static const struct file_operations proc_config_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_config_open, - .release = proc_close -}; - -static const struct file_operations proc_wepkey_ops = { - .owner = THIS_MODULE, - .read = proc_read, - .write = proc_write, - .open = proc_wepkey_open, - .release = proc_close -}; - -static struct proc_dir_entry *airo_entry; - -struct proc_data { - int release_buffer; - int readlen; - char *rbuffer; - int writelen; - int maxwritelen; - char *wbuffer; - void (*on_close) (struct inode *, struct file *); -}; - -static int setup_proc_entry( struct net_device *dev, - struct airo_info *apriv ) { - struct proc_dir_entry *entry; - /* First setup the device directory */ - strcpy(apriv->proc_name,dev->name); - apriv->proc_entry = create_proc_entry(apriv->proc_name, - S_IFDIR|airo_perm, - airo_entry); - if (!apriv->proc_entry) - goto fail; - apriv->proc_entry->uid = proc_uid; - apriv->proc_entry->gid = proc_gid; - - /* Setup the StatsDelta */ - entry = proc_create_data("StatsDelta", - S_IFREG | (S_IRUGO&proc_perm), - apriv->proc_entry, &proc_statsdelta_ops, dev); - if (!entry) - goto fail_stats_delta; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the Stats */ - entry = proc_create_data("Stats", - S_IFREG | (S_IRUGO&proc_perm), - apriv->proc_entry, &proc_stats_ops, dev); - if (!entry) - goto fail_stats; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the Status */ - entry = proc_create_data("Status", - S_IFREG | (S_IRUGO&proc_perm), - apriv->proc_entry, &proc_status_ops, dev); - if (!entry) - goto fail_status; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the Config */ - entry = proc_create_data("Config", - S_IFREG | proc_perm, - apriv->proc_entry, &proc_config_ops, dev); - if (!entry) - goto fail_config; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the SSID */ - entry = proc_create_data("SSID", - S_IFREG | proc_perm, - apriv->proc_entry, &proc_SSID_ops, dev); - if (!entry) - goto fail_ssid; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the APList */ - entry = proc_create_data("APList", - S_IFREG | proc_perm, - apriv->proc_entry, &proc_APList_ops, dev); - if (!entry) - goto fail_aplist; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the BSSList */ - entry = proc_create_data("BSSList", - S_IFREG | proc_perm, - apriv->proc_entry, &proc_BSSList_ops, dev); - if (!entry) - goto fail_bsslist; - entry->uid = proc_uid; - entry->gid = proc_gid; - - /* Setup the WepKey */ - entry = proc_create_data("WepKey", - S_IFREG | proc_perm, - apriv->proc_entry, &proc_wepkey_ops, dev); - if (!entry) - goto fail_wepkey; - entry->uid = proc_uid; - entry->gid = proc_gid; - - return 0; - -fail_wepkey: - remove_proc_entry("BSSList", apriv->proc_entry); -fail_bsslist: - remove_proc_entry("APList", apriv->proc_entry); -fail_aplist: - remove_proc_entry("SSID", apriv->proc_entry); -fail_ssid: - remove_proc_entry("Config", apriv->proc_entry); -fail_config: - remove_proc_entry("Status", apriv->proc_entry); -fail_status: - remove_proc_entry("Stats", apriv->proc_entry); -fail_stats: - remove_proc_entry("StatsDelta", apriv->proc_entry); -fail_stats_delta: - remove_proc_entry(apriv->proc_name, airo_entry); -fail: - return -ENOMEM; -} - -static int takedown_proc_entry( struct net_device *dev, - struct airo_info *apriv ) { - if ( !apriv->proc_entry->namelen ) return 0; - remove_proc_entry("Stats",apriv->proc_entry); - remove_proc_entry("StatsDelta",apriv->proc_entry); - remove_proc_entry("Status",apriv->proc_entry); - remove_proc_entry("Config",apriv->proc_entry); - remove_proc_entry("SSID",apriv->proc_entry); - remove_proc_entry("APList",apriv->proc_entry); - remove_proc_entry("BSSList",apriv->proc_entry); - remove_proc_entry("WepKey",apriv->proc_entry); - remove_proc_entry(apriv->proc_name,airo_entry); - return 0; -} - -/* - * What we want from the proc_fs is to be able to efficiently read - * and write the configuration. To do this, we want to read the - * configuration when the file is opened and write it when the file is - * closed. So basically we allocate a read buffer at open and fill it - * with data, and allocate a write buffer and read it at close. - */ - -/* - * The read routine is generic, it relies on the preallocated rbuffer - * to supply the data. - */ -static ssize_t proc_read( struct file *file, - char __user *buffer, - size_t len, - loff_t *offset ) -{ - struct proc_data *priv = file->private_data; - - if (!priv->rbuffer) - return -EINVAL; - - return simple_read_from_buffer(buffer, len, offset, priv->rbuffer, - priv->readlen); -} - -/* - * The write routine is generic, it fills in a preallocated rbuffer - * to supply the data. - */ -static ssize_t proc_write( struct file *file, - const char __user *buffer, - size_t len, - loff_t *offset ) -{ - loff_t pos = *offset; - struct proc_data *priv = (struct proc_data*)file->private_data; - - if (!priv->wbuffer) - return -EINVAL; - - if (pos < 0) - return -EINVAL; - if (pos >= priv->maxwritelen) - return 0; - if (len > priv->maxwritelen - pos) - len = priv->maxwritelen - pos; - if (copy_from_user(priv->wbuffer + pos, buffer, len)) - return -EFAULT; - if ( pos + len > priv->writelen ) - priv->writelen = len + file->f_pos; - *offset = pos + len; - return len; -} - -static int proc_status_open(struct inode *inode, struct file *file) -{ - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *apriv = dev->ml_priv; - CapabilityRid cap_rid; - StatusRid status_rid; - u16 mode; - int i; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - - readStatusRid(apriv, &status_rid, 1); - readCapabilityRid(apriv, &cap_rid, 1); - - mode = le16_to_cpu(status_rid.mode); - - i = sprintf(data->rbuffer, "Status: %s%s%s%s%s%s%s%s%s\n", - mode & 1 ? "CFG ": "", - mode & 2 ? "ACT ": "", - mode & 0x10 ? "SYN ": "", - mode & 0x20 ? "LNK ": "", - mode & 0x40 ? "LEAP ": "", - mode & 0x80 ? "PRIV ": "", - mode & 0x100 ? "KEY ": "", - mode & 0x200 ? "WEP ": "", - mode & 0x8000 ? "ERR ": ""); - sprintf( data->rbuffer+i, "Mode: %x\n" - "Signal Strength: %d\n" - "Signal Quality: %d\n" - "SSID: %-.*s\n" - "AP: %-.16s\n" - "Freq: %d\n" - "BitRate: %dmbs\n" - "Driver Version: %s\n" - "Device: %s\nManufacturer: %s\nFirmware Version: %s\n" - "Radio type: %x\nCountry: %x\nHardware Version: %x\n" - "Software Version: %x\nSoftware Subversion: %x\n" - "Boot block version: %x\n", - le16_to_cpu(status_rid.mode), - le16_to_cpu(status_rid.normalizedSignalStrength), - le16_to_cpu(status_rid.signalQuality), - le16_to_cpu(status_rid.SSIDlen), - status_rid.SSID, - status_rid.apName, - le16_to_cpu(status_rid.channel), - le16_to_cpu(status_rid.currentXmitRate) / 2, - version, - cap_rid.prodName, - cap_rid.manName, - cap_rid.prodVer, - le16_to_cpu(cap_rid.radioType), - le16_to_cpu(cap_rid.country), - le16_to_cpu(cap_rid.hardVer), - le16_to_cpu(cap_rid.softVer), - le16_to_cpu(cap_rid.softSubVer), - le16_to_cpu(cap_rid.bootBlockVer)); - data->readlen = strlen( data->rbuffer ); - return 0; -} - -static int proc_stats_rid_open(struct inode*, struct file*, u16); -static int proc_statsdelta_open( struct inode *inode, - struct file *file ) { - if (file->f_mode&FMODE_WRITE) { - return proc_stats_rid_open(inode, file, RID_STATSDELTACLEAR); - } - return proc_stats_rid_open(inode, file, RID_STATSDELTA); -} - -static int proc_stats_open( struct inode *inode, struct file *file ) { - return proc_stats_rid_open(inode, file, RID_STATS); -} - -static int proc_stats_rid_open( struct inode *inode, - struct file *file, - u16 rid ) -{ - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *apriv = dev->ml_priv; - StatsRid stats; - int i, j; - __le32 *vals = stats.vals; - int len; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 4096, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - - readStatsRid(apriv, &stats, rid, 1); - len = le16_to_cpu(stats.len); - - j = 0; - for(i=0; statsLabels[i]!=(char *)-1 && i*44096) { - airo_print_warn(apriv->dev->name, - "Potentially disasterous buffer overflow averted!"); - break; - } - j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i], - le32_to_cpu(vals[i])); - } - if (i*4 >= len) { - airo_print_warn(apriv->dev->name, "Got a short rid"); - } - data->readlen = j; - return 0; -} - -static int get_dec_u16( char *buffer, int *start, int limit ) { - u16 value; - int valid = 0; - for (value = 0; *start < limit && buffer[*start] >= '0' && - buffer[*start] <= '9'; (*start)++) { - valid = 1; - value *= 10; - value += buffer[*start] - '0'; - } - if ( !valid ) return -1; - return value; -} - -static int airo_config_commit(struct net_device *dev, - struct iw_request_info *info, void *zwrq, - char *extra); - -static inline int sniffing_mode(struct airo_info *ai) -{ - return le16_to_cpu(ai->config.rmode & RXMODE_MASK) >= - le16_to_cpu(RXMODE_RFMON); -} - -static void proc_config_on_close(struct inode *inode, struct file *file) -{ - struct proc_data *data = file->private_data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - char *line; - - if ( !data->writelen ) return; - - readConfigRid(ai, 1); - set_bit (FLAG_COMMIT, &ai->flags); - - line = data->wbuffer; - while( line[0] ) { -/*** Mode processing */ - if ( !strncmp( line, "Mode: ", 6 ) ) { - line += 6; - if (sniffing_mode(ai)) - set_bit (FLAG_RESET, &ai->flags); - ai->config.rmode &= ~RXMODE_FULL_MASK; - clear_bit (FLAG_802_11, &ai->flags); - ai->config.opmode &= ~MODE_CFG_MASK; - ai->config.scanMode = SCANMODE_ACTIVE; - if ( line[0] == 'a' ) { - ai->config.opmode |= MODE_STA_IBSS; - } else { - ai->config.opmode |= MODE_STA_ESS; - if ( line[0] == 'r' ) { - ai->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; - ai->config.scanMode = SCANMODE_PASSIVE; - set_bit (FLAG_802_11, &ai->flags); - } else if ( line[0] == 'y' ) { - ai->config.rmode |= RXMODE_RFMON_ANYBSS | RXMODE_DISABLE_802_3_HEADER; - ai->config.scanMode = SCANMODE_PASSIVE; - set_bit (FLAG_802_11, &ai->flags); - } else if ( line[0] == 'l' ) - ai->config.rmode |= RXMODE_LANMON; - } - set_bit (FLAG_COMMIT, &ai->flags); - } - -/*** Radio status */ - else if (!strncmp(line,"Radio: ", 7)) { - line += 7; - if (!strncmp(line,"off",3)) { - set_bit (FLAG_RADIO_OFF, &ai->flags); - } else { - clear_bit (FLAG_RADIO_OFF, &ai->flags); - } - } -/*** NodeName processing */ - else if ( !strncmp( line, "NodeName: ", 10 ) ) { - int j; - - line += 10; - memset( ai->config.nodeName, 0, 16 ); -/* Do the name, assume a space between the mode and node name */ - for( j = 0; j < 16 && line[j] != '\n'; j++ ) { - ai->config.nodeName[j] = line[j]; - } - set_bit (FLAG_COMMIT, &ai->flags); - } - -/*** PowerMode processing */ - else if ( !strncmp( line, "PowerMode: ", 11 ) ) { - line += 11; - if ( !strncmp( line, "PSPCAM", 6 ) ) { - ai->config.powerSaveMode = POWERSAVE_PSPCAM; - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "PSP", 3 ) ) { - ai->config.powerSaveMode = POWERSAVE_PSP; - set_bit (FLAG_COMMIT, &ai->flags); - } else { - ai->config.powerSaveMode = POWERSAVE_CAM; - set_bit (FLAG_COMMIT, &ai->flags); - } - } else if ( !strncmp( line, "DataRates: ", 11 ) ) { - int v, i = 0, k = 0; /* i is index into line, - k is index to rates */ - - line += 11; - while((v = get_dec_u16(line, &i, 3))!=-1) { - ai->config.rates[k++] = (u8)v; - line += i + 1; - i = 0; - } - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "Channel: ", 9 ) ) { - int v, i = 0; - line += 9; - v = get_dec_u16(line, &i, i+3); - if ( v != -1 ) { - ai->config.channelSet = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } - } else if ( !strncmp( line, "XmitPower: ", 11 ) ) { - int v, i = 0; - line += 11; - v = get_dec_u16(line, &i, i+3); - if ( v != -1 ) { - ai->config.txPower = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } - } else if ( !strncmp( line, "WEP: ", 5 ) ) { - line += 5; - switch( line[0] ) { - case 's': - ai->config.authType = AUTH_SHAREDKEY; - break; - case 'e': - ai->config.authType = AUTH_ENCRYPT; - break; - default: - ai->config.authType = AUTH_OPEN; - break; - } - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "LongRetryLimit: ", 16 ) ) { - int v, i = 0; - - line += 16; - v = get_dec_u16(line, &i, 3); - v = (v<0) ? 0 : ((v>255) ? 255 : v); - ai->config.longRetryLimit = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "ShortRetryLimit: ", 17 ) ) { - int v, i = 0; - - line += 17; - v = get_dec_u16(line, &i, 3); - v = (v<0) ? 0 : ((v>255) ? 255 : v); - ai->config.shortRetryLimit = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "RTSThreshold: ", 14 ) ) { - int v, i = 0; - - line += 14; - v = get_dec_u16(line, &i, 4); - v = (v<0) ? 0 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); - ai->config.rtsThres = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "TXMSDULifetime: ", 16 ) ) { - int v, i = 0; - - line += 16; - v = get_dec_u16(line, &i, 5); - v = (v<0) ? 0 : v; - ai->config.txLifetime = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "RXMSDULifetime: ", 16 ) ) { - int v, i = 0; - - line += 16; - v = get_dec_u16(line, &i, 5); - v = (v<0) ? 0 : v; - ai->config.rxLifetime = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "TXDiversity: ", 13 ) ) { - ai->config.txDiversity = - (line[13]=='l') ? 1 : - ((line[13]=='r')? 2: 3); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "RXDiversity: ", 13 ) ) { - ai->config.rxDiversity = - (line[13]=='l') ? 1 : - ((line[13]=='r')? 2: 3); - set_bit (FLAG_COMMIT, &ai->flags); - } else if ( !strncmp( line, "FragThreshold: ", 15 ) ) { - int v, i = 0; - - line += 15; - v = get_dec_u16(line, &i, 4); - v = (v<256) ? 256 : ((v>AIRO_DEF_MTU) ? AIRO_DEF_MTU : v); - v = v & 0xfffe; /* Make sure its even */ - ai->config.fragThresh = cpu_to_le16(v); - set_bit (FLAG_COMMIT, &ai->flags); - } else if (!strncmp(line, "Modulation: ", 12)) { - line += 12; - switch(*line) { - case 'd': ai->config.modulation=MOD_DEFAULT; set_bit(FLAG_COMMIT, &ai->flags); break; - case 'c': ai->config.modulation=MOD_CCK; set_bit(FLAG_COMMIT, &ai->flags); break; - case 'm': ai->config.modulation=MOD_MOK; set_bit(FLAG_COMMIT, &ai->flags); break; - default: airo_print_warn(ai->dev->name, "Unknown modulation"); - } - } else if (!strncmp(line, "Preamble: ", 10)) { - line += 10; - switch(*line) { - case 'a': ai->config.preamble=PREAMBLE_AUTO; set_bit(FLAG_COMMIT, &ai->flags); break; - case 'l': ai->config.preamble=PREAMBLE_LONG; set_bit(FLAG_COMMIT, &ai->flags); break; - case 's': ai->config.preamble=PREAMBLE_SHORT; set_bit(FLAG_COMMIT, &ai->flags); break; - default: airo_print_warn(ai->dev->name, "Unknown preamble"); - } - } else { - airo_print_warn(ai->dev->name, "Couldn't figure out %s", line); - } - while( line[0] && line[0] != '\n' ) line++; - if ( line[0] ) line++; - } - airo_config_commit(dev, NULL, NULL, NULL); -} - -static char *get_rmode(__le16 mode) -{ - switch(mode & RXMODE_MASK) { - case RXMODE_RFMON: return "rfmon"; - case RXMODE_RFMON_ANYBSS: return "yna (any) bss rfmon"; - case RXMODE_LANMON: return "lanmon"; - } - return "ESS"; -} - -static int proc_config_open(struct inode *inode, struct file *file) -{ - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - int i; - __le16 mode; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 2048, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - if ((data->wbuffer = kzalloc( 2048, GFP_KERNEL )) == NULL) { - kfree (data->rbuffer); - kfree (file->private_data); - return -ENOMEM; - } - data->maxwritelen = 2048; - data->on_close = proc_config_on_close; - - readConfigRid(ai, 1); - - mode = ai->config.opmode & MODE_CFG_MASK; - i = sprintf( data->rbuffer, - "Mode: %s\n" - "Radio: %s\n" - "NodeName: %-16s\n" - "PowerMode: %s\n" - "DataRates: %d %d %d %d %d %d %d %d\n" - "Channel: %d\n" - "XmitPower: %d\n", - mode == MODE_STA_IBSS ? "adhoc" : - mode == MODE_STA_ESS ? get_rmode(ai->config.rmode): - mode == MODE_AP ? "AP" : - mode == MODE_AP_RPTR ? "AP RPTR" : "Error", - test_bit(FLAG_RADIO_OFF, &ai->flags) ? "off" : "on", - ai->config.nodeName, - ai->config.powerSaveMode == POWERSAVE_CAM ? "CAM" : - ai->config.powerSaveMode == POWERSAVE_PSP ? "PSP" : - ai->config.powerSaveMode == POWERSAVE_PSPCAM ? "PSPCAM" : - "Error", - (int)ai->config.rates[0], - (int)ai->config.rates[1], - (int)ai->config.rates[2], - (int)ai->config.rates[3], - (int)ai->config.rates[4], - (int)ai->config.rates[5], - (int)ai->config.rates[6], - (int)ai->config.rates[7], - le16_to_cpu(ai->config.channelSet), - le16_to_cpu(ai->config.txPower) - ); - sprintf( data->rbuffer + i, - "LongRetryLimit: %d\n" - "ShortRetryLimit: %d\n" - "RTSThreshold: %d\n" - "TXMSDULifetime: %d\n" - "RXMSDULifetime: %d\n" - "TXDiversity: %s\n" - "RXDiversity: %s\n" - "FragThreshold: %d\n" - "WEP: %s\n" - "Modulation: %s\n" - "Preamble: %s\n", - le16_to_cpu(ai->config.longRetryLimit), - le16_to_cpu(ai->config.shortRetryLimit), - le16_to_cpu(ai->config.rtsThres), - le16_to_cpu(ai->config.txLifetime), - le16_to_cpu(ai->config.rxLifetime), - ai->config.txDiversity == 1 ? "left" : - ai->config.txDiversity == 2 ? "right" : "both", - ai->config.rxDiversity == 1 ? "left" : - ai->config.rxDiversity == 2 ? "right" : "both", - le16_to_cpu(ai->config.fragThresh), - ai->config.authType == AUTH_ENCRYPT ? "encrypt" : - ai->config.authType == AUTH_SHAREDKEY ? "shared" : "open", - ai->config.modulation == MOD_DEFAULT ? "default" : - ai->config.modulation == MOD_CCK ? "cck" : - ai->config.modulation == MOD_MOK ? "mok" : "error", - ai->config.preamble == PREAMBLE_AUTO ? "auto" : - ai->config.preamble == PREAMBLE_LONG ? "long" : - ai->config.preamble == PREAMBLE_SHORT ? "short" : "error" - ); - data->readlen = strlen( data->rbuffer ); - return 0; -} - -static void proc_SSID_on_close(struct inode *inode, struct file *file) -{ - struct proc_data *data = (struct proc_data *)file->private_data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - SsidRid SSID_rid; - int i; - char *p = data->wbuffer; - char *end = p + data->writelen; - - if (!data->writelen) - return; - - *end = '\n'; /* sentinel; we have space for it */ - - memset(&SSID_rid, 0, sizeof(SSID_rid)); - - for (i = 0; i < 3 && p < end; i++) { - int j = 0; - /* copy up to 32 characters from this line */ - while (*p != '\n' && j < 32) - SSID_rid.ssids[i].ssid[j++] = *p++; - if (j == 0) - break; - SSID_rid.ssids[i].len = cpu_to_le16(j); - /* skip to the beginning of the next line */ - while (*p++ != '\n') - ; - } - if (i) - SSID_rid.len = cpu_to_le16(sizeof(SSID_rid)); - disable_MAC(ai, 1); - writeSsidRid(ai, &SSID_rid, 1); - enable_MAC(ai, 1); -} - -static inline u8 hexVal(char c) { - if (c>='0' && c<='9') return c -= '0'; - if (c>='a' && c<='f') return c -= 'a'-10; - if (c>='A' && c<='F') return c -= 'A'-10; - return 0; -} - -static void proc_APList_on_close( struct inode *inode, struct file *file ) { - struct proc_data *data = (struct proc_data *)file->private_data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - APListRid APList_rid; - int i; - - if ( !data->writelen ) return; - - memset( &APList_rid, 0, sizeof(APList_rid) ); - APList_rid.len = cpu_to_le16(sizeof(APList_rid)); - - for( i = 0; i < 4 && data->writelen >= (i+1)*6*3; i++ ) { - int j; - for( j = 0; j < 6*3 && data->wbuffer[j+i*6*3]; j++ ) { - switch(j%3) { - case 0: - APList_rid.ap[i][j/3]= - hexVal(data->wbuffer[j+i*6*3])<<4; - break; - case 1: - APList_rid.ap[i][j/3]|= - hexVal(data->wbuffer[j+i*6*3]); - break; - } - } - } - disable_MAC(ai, 1); - writeAPListRid(ai, &APList_rid, 1); - enable_MAC(ai, 1); -} - -/* This function wraps PC4500_writerid with a MAC disable */ -static int do_writerid( struct airo_info *ai, u16 rid, const void *rid_data, - int len, int dummy ) { - int rc; - - disable_MAC(ai, 1); - rc = PC4500_writerid(ai, rid, rid_data, len, 1); - enable_MAC(ai, 1); - return rc; -} - -/* Returns the WEP key at the specified index, or -1 if that key does - * not exist. The buffer is assumed to be at least 16 bytes in length. - */ -static int get_wep_key(struct airo_info *ai, u16 index, char *buf, u16 buflen) -{ - WepKeyRid wkr; - int rc; - __le16 lastindex; - - rc = readWepKeyRid(ai, &wkr, 1, 1); - if (rc != SUCCESS) - return -1; - do { - lastindex = wkr.kindex; - if (le16_to_cpu(wkr.kindex) == index) { - int klen = min_t(int, buflen, le16_to_cpu(wkr.klen)); - memcpy(buf, wkr.key, klen); - return klen; - } - rc = readWepKeyRid(ai, &wkr, 0, 1); - if (rc != SUCCESS) - return -1; - } while (lastindex != wkr.kindex); - return -1; -} - -static int get_wep_tx_idx(struct airo_info *ai) -{ - WepKeyRid wkr; - int rc; - __le16 lastindex; - - rc = readWepKeyRid(ai, &wkr, 1, 1); - if (rc != SUCCESS) - return -1; - do { - lastindex = wkr.kindex; - if (wkr.kindex == cpu_to_le16(0xffff)) - return wkr.mac[0]; - rc = readWepKeyRid(ai, &wkr, 0, 1); - if (rc != SUCCESS) - return -1; - } while (lastindex != wkr.kindex); - return -1; -} - -static int set_wep_key(struct airo_info *ai, u16 index, const char *key, - u16 keylen, int perm, int lock) -{ - static const unsigned char macaddr[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; - WepKeyRid wkr; - int rc; - - WARN_ON(keylen == 0); - - memset(&wkr, 0, sizeof(wkr)); - wkr.len = cpu_to_le16(sizeof(wkr)); - wkr.kindex = cpu_to_le16(index); - wkr.klen = cpu_to_le16(keylen); - memcpy(wkr.key, key, keylen); - memcpy(wkr.mac, macaddr, ETH_ALEN); - - if (perm) disable_MAC(ai, lock); - rc = writeWepKeyRid(ai, &wkr, perm, lock); - if (perm) enable_MAC(ai, lock); - return rc; -} - -static int set_wep_tx_idx(struct airo_info *ai, u16 index, int perm, int lock) -{ - WepKeyRid wkr; - int rc; - - memset(&wkr, 0, sizeof(wkr)); - wkr.len = cpu_to_le16(sizeof(wkr)); - wkr.kindex = cpu_to_le16(0xffff); - wkr.mac[0] = (char)index; - - if (perm) { - ai->defindex = (char)index; - disable_MAC(ai, lock); - } - - rc = writeWepKeyRid(ai, &wkr, perm, lock); - - if (perm) - enable_MAC(ai, lock); - return rc; -} - -static void proc_wepkey_on_close( struct inode *inode, struct file *file ) { - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - int i, rc; - char key[16]; - u16 index = 0; - int j = 0; - - memset(key, 0, sizeof(key)); - - data = (struct proc_data *)file->private_data; - if ( !data->writelen ) return; - - if (data->wbuffer[0] >= '0' && data->wbuffer[0] <= '3' && - (data->wbuffer[1] == ' ' || data->wbuffer[1] == '\n')) { - index = data->wbuffer[0] - '0'; - if (data->wbuffer[1] == '\n') { - rc = set_wep_tx_idx(ai, index, 1, 1); - if (rc < 0) { - airo_print_err(ai->dev->name, "failed to set " - "WEP transmit index to %d: %d.", - index, rc); - } - return; - } - j = 2; - } else { - airo_print_err(ai->dev->name, "WepKey passed invalid key index"); - return; - } - - for( i = 0; i < 16*3 && data->wbuffer[i+j]; i++ ) { - switch(i%3) { - case 0: - key[i/3] = hexVal(data->wbuffer[i+j])<<4; - break; - case 1: - key[i/3] |= hexVal(data->wbuffer[i+j]); - break; - } - } - - rc = set_wep_key(ai, index, key, i/3, 1, 1); - if (rc < 0) { - airo_print_err(ai->dev->name, "failed to set WEP key at index " - "%d: %d.", index, rc); - } -} - -static int proc_wepkey_open( struct inode *inode, struct file *file ) -{ - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - char *ptr; - WepKeyRid wkr; - __le16 lastindex; - int j=0; - int rc; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - memset(&wkr, 0, sizeof(wkr)); - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kzalloc( 180, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - data->writelen = 0; - data->maxwritelen = 80; - if ((data->wbuffer = kzalloc( 80, GFP_KERNEL )) == NULL) { - kfree (data->rbuffer); - kfree (file->private_data); - return -ENOMEM; - } - data->on_close = proc_wepkey_on_close; - - ptr = data->rbuffer; - strcpy(ptr, "No wep keys\n"); - rc = readWepKeyRid(ai, &wkr, 1, 1); - if (rc == SUCCESS) do { - lastindex = wkr.kindex; - if (wkr.kindex == cpu_to_le16(0xffff)) { - j += sprintf(ptr+j, "Tx key = %d\n", - (int)wkr.mac[0]); - } else { - j += sprintf(ptr+j, "Key %d set with length = %d\n", - le16_to_cpu(wkr.kindex), - le16_to_cpu(wkr.klen)); - } - readWepKeyRid(ai, &wkr, 0, 1); - } while((lastindex != wkr.kindex) && (j < 180-30)); - - data->readlen = strlen( data->rbuffer ); - return 0; -} - -static int proc_SSID_open(struct inode *inode, struct file *file) -{ - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - int i; - char *ptr; - SsidRid SSID_rid; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - data->writelen = 0; - data->maxwritelen = 33*3; - /* allocate maxwritelen + 1; we'll want a sentinel */ - if ((data->wbuffer = kzalloc(33*3 + 1, GFP_KERNEL)) == NULL) { - kfree (data->rbuffer); - kfree (file->private_data); - return -ENOMEM; - } - data->on_close = proc_SSID_on_close; - - readSsidRid(ai, &SSID_rid); - ptr = data->rbuffer; - for (i = 0; i < 3; i++) { - int j; - size_t len = le16_to_cpu(SSID_rid.ssids[i].len); - if (!len) - break; - if (len > 32) - len = 32; - for (j = 0; j < len && SSID_rid.ssids[i].ssid[j]; j++) - *ptr++ = SSID_rid.ssids[i].ssid[j]; - *ptr++ = '\n'; - } - *ptr = '\0'; - data->readlen = strlen( data->rbuffer ); - return 0; -} - -static int proc_APList_open( struct inode *inode, struct file *file ) { - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - int i; - char *ptr; - APListRid APList_rid; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 104, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - data->writelen = 0; - data->maxwritelen = 4*6*3; - if ((data->wbuffer = kzalloc( data->maxwritelen, GFP_KERNEL )) == NULL) { - kfree (data->rbuffer); - kfree (file->private_data); - return -ENOMEM; - } - data->on_close = proc_APList_on_close; - - readAPListRid(ai, &APList_rid); - ptr = data->rbuffer; - for( i = 0; i < 4; i++ ) { -// We end when we find a zero MAC - if ( !*(int*)APList_rid.ap[i] && - !*(int*)&APList_rid.ap[i][2]) break; - ptr += sprintf(ptr, "%pM\n", APList_rid.ap[i]); - } - if (i==0) ptr += sprintf(ptr, "Not using specific APs\n"); - - *ptr = '\0'; - data->readlen = strlen( data->rbuffer ); - return 0; -} - -static int proc_BSSList_open( struct inode *inode, struct file *file ) { - struct proc_data *data; - struct proc_dir_entry *dp = PDE(inode); - struct net_device *dev = dp->data; - struct airo_info *ai = dev->ml_priv; - char *ptr; - BSSListRid BSSList_rid; - int rc; - /* If doLoseSync is not 1, we won't do a Lose Sync */ - int doLoseSync = -1; - - if ((file->private_data = kzalloc(sizeof(struct proc_data ), GFP_KERNEL)) == NULL) - return -ENOMEM; - data = (struct proc_data *)file->private_data; - if ((data->rbuffer = kmalloc( 1024, GFP_KERNEL )) == NULL) { - kfree (file->private_data); - return -ENOMEM; - } - data->writelen = 0; - data->maxwritelen = 0; - data->wbuffer = NULL; - data->on_close = NULL; - - if (file->f_mode & FMODE_WRITE) { - if (!(file->f_mode & FMODE_READ)) { - Cmd cmd; - Resp rsp; - - if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd=CMD_LISTBSS; - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; - issuecommand(ai, &cmd, &rsp); - up(&ai->sem); - data->readlen = 0; - return 0; - } - doLoseSync = 1; - } - ptr = data->rbuffer; - /* There is a race condition here if there are concurrent opens. - Since it is a rare condition, we'll just live with it, otherwise - we have to add a spin lock... */ - rc = readBSSListRid(ai, doLoseSync, &BSSList_rid); - while(rc == 0 && BSSList_rid.index != cpu_to_le16(0xffff)) { - ptr += sprintf(ptr, "%pM %*s rssi = %d", - BSSList_rid.bssid, - (int)BSSList_rid.ssidLen, - BSSList_rid.ssid, - le16_to_cpu(BSSList_rid.dBm)); - ptr += sprintf(ptr, " channel = %d %s %s %s %s\n", - le16_to_cpu(BSSList_rid.dsChannel), - BSSList_rid.cap & CAP_ESS ? "ESS" : "", - BSSList_rid.cap & CAP_IBSS ? "adhoc" : "", - BSSList_rid.cap & CAP_PRIVACY ? "wep" : "", - BSSList_rid.cap & CAP_SHORTHDR ? "shorthdr" : ""); - rc = readBSSListRid(ai, 0, &BSSList_rid); - } - *ptr = '\0'; - data->readlen = strlen( data->rbuffer ); - return 0; -} - -static int proc_close( struct inode *inode, struct file *file ) -{ - struct proc_data *data = file->private_data; - - if (data->on_close != NULL) - data->on_close(inode, file); - kfree(data->rbuffer); - kfree(data->wbuffer); - kfree(data); - return 0; -} - -/* Since the card doesn't automatically switch to the right WEP mode, - we will make it do it. If the card isn't associated, every secs we - will switch WEP modes to see if that will help. If the card is - associated we will check every minute to see if anything has - changed. */ -static void timer_func( struct net_device *dev ) { - struct airo_info *apriv = dev->ml_priv; - -/* We don't have a link so try changing the authtype */ - readConfigRid(apriv, 0); - disable_MAC(apriv, 0); - switch(apriv->config.authType) { - case AUTH_ENCRYPT: -/* So drop to OPEN */ - apriv->config.authType = AUTH_OPEN; - break; - case AUTH_SHAREDKEY: - if (apriv->keyindex < auto_wep) { - set_wep_tx_idx(apriv, apriv->keyindex, 0, 0); - apriv->config.authType = AUTH_SHAREDKEY; - apriv->keyindex++; - } else { - /* Drop to ENCRYPT */ - apriv->keyindex = 0; - set_wep_tx_idx(apriv, apriv->defindex, 0, 0); - apriv->config.authType = AUTH_ENCRYPT; - } - break; - default: /* We'll escalate to SHAREDKEY */ - apriv->config.authType = AUTH_SHAREDKEY; - } - set_bit (FLAG_COMMIT, &apriv->flags); - writeConfigRid(apriv, 0); - enable_MAC(apriv, 0); - up(&apriv->sem); - -/* Schedule check to see if the change worked */ - clear_bit(JOB_AUTOWEP, &apriv->jobs); - apriv->expires = RUN_AT(HZ*3); -} - -#ifdef CONFIG_PCI -static int __devinit airo_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *pent) -{ - struct net_device *dev; - - if (pci_enable_device(pdev)) - return -ENODEV; - pci_set_master(pdev); - - if (pdev->device == 0x5000 || pdev->device == 0xa504) - dev = _init_airo_card(pdev->irq, pdev->resource[0].start, 0, pdev, &pdev->dev); - else - dev = _init_airo_card(pdev->irq, pdev->resource[2].start, 0, pdev, &pdev->dev); - if (!dev) { - pci_disable_device(pdev); - return -ENODEV; - } - - pci_set_drvdata(pdev, dev); - return 0; -} - -static void __devexit airo_pci_remove(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - airo_print_info(dev->name, "Unregistering..."); - stop_airo_card(dev, 1); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); -} - -static int airo_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct airo_info *ai = dev->ml_priv; - Cmd cmd; - Resp rsp; - - if (!ai->APList) - ai->APList = kmalloc(sizeof(APListRid), GFP_KERNEL); - if (!ai->APList) - return -ENOMEM; - if (!ai->SSID) - ai->SSID = kmalloc(sizeof(SsidRid), GFP_KERNEL); - if (!ai->SSID) - return -ENOMEM; - readAPListRid(ai, ai->APList); - readSsidRid(ai, ai->SSID); - memset(&cmd, 0, sizeof(cmd)); - /* the lock will be released at the end of the resume callback */ - if (down_interruptible(&ai->sem)) - return -EAGAIN; - disable_MAC(ai, 0); - netif_device_detach(dev); - ai->power = state; - cmd.cmd = HOSTSLEEP; - issuecommand(ai, &cmd, &rsp); - - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); - pci_save_state(pdev); - return pci_set_power_state(pdev, pci_choose_state(pdev, state)); -} - -static int airo_pci_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct airo_info *ai = dev->ml_priv; - pci_power_t prev_state = pdev->current_state; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_enable_wake(pdev, PCI_D0, 0); - - if (prev_state != PCI_D1) { - reset_card(dev, 0); - mpi_init_descriptors(ai); - setup_card(ai, dev->dev_addr, 0); - clear_bit(FLAG_RADIO_OFF, &ai->flags); - clear_bit(FLAG_PENDING_XMIT, &ai->flags); - } else { - OUT4500(ai, EVACK, EV_AWAKEN); - OUT4500(ai, EVACK, EV_AWAKEN); - msleep(100); - } - - set_bit(FLAG_COMMIT, &ai->flags); - disable_MAC(ai, 0); - msleep(200); - if (ai->SSID) { - writeSsidRid(ai, ai->SSID, 0); - kfree(ai->SSID); - ai->SSID = NULL; - } - if (ai->APList) { - writeAPListRid(ai, ai->APList, 0); - kfree(ai->APList); - ai->APList = NULL; - } - writeConfigRid(ai, 0); - enable_MAC(ai, 0); - ai->power = PMSG_ON; - netif_device_attach(dev); - netif_wake_queue(dev); - enable_interrupts(ai); - up(&ai->sem); - return 0; -} -#endif - -static int __init airo_init_module( void ) -{ - int i; - - airo_entry = create_proc_entry("driver/aironet", - S_IFDIR | airo_perm, - NULL); - - if (airo_entry) { - airo_entry->uid = proc_uid; - airo_entry->gid = proc_gid; - } - - for (i = 0; i < 4 && io[i] && irq[i]; i++) { - airo_print_info("", "Trying to configure ISA adapter at irq=%d " - "io=0x%x", irq[i], io[i] ); - if (init_airo_card( irq[i], io[i], 0, NULL )) - /* do nothing */ ; - } - -#ifdef CONFIG_PCI - airo_print_info("", "Probing for PCI adapters"); - i = pci_register_driver(&airo_driver); - airo_print_info("", "Finished probing for PCI adapters"); - - if (i) { - remove_proc_entry("driver/aironet", NULL); - return i; - } -#endif - - /* Always exit with success, as we are a library module - * as well as a driver module - */ - return 0; -} - -static void __exit airo_cleanup_module( void ) -{ - struct airo_info *ai; - while(!list_empty(&airo_devices)) { - ai = list_entry(airo_devices.next, struct airo_info, dev_list); - airo_print_info(ai->dev->name, "Unregistering..."); - stop_airo_card(ai->dev, 1); - } -#ifdef CONFIG_PCI - pci_unregister_driver(&airo_driver); -#endif - remove_proc_entry("driver/aironet", NULL); -} - -/* - * Initial Wireless Extension code for Aironet driver by : - * Jean Tourrilhes - HPL - 17 November 00 - * Conversion to new driver API by : - * Jean Tourrilhes - HPL - 26 March 02 - * Javier also did a good amount of work here, adding some new extensions - * and fixing my code. Let's just say that without him this code just - * would not work at all... - Jean II - */ - -static u8 airo_rssi_to_dbm (tdsRssiEntry *rssi_rid, u8 rssi) -{ - if (!rssi_rid) - return 0; - - return (0x100 - rssi_rid[rssi].rssidBm); -} - -static u8 airo_dbm_to_pct (tdsRssiEntry *rssi_rid, u8 dbm) -{ - int i; - - if (!rssi_rid) - return 0; - - for (i = 0; i < 256; i++) - if (rssi_rid[i].rssidBm == dbm) - return rssi_rid[i].rssipct; - - return 0; -} - - -static int airo_get_quality (StatusRid *status_rid, CapabilityRid *cap_rid) -{ - int quality = 0; - u16 sq; - - if ((status_rid->mode & cpu_to_le16(0x3f)) != cpu_to_le16(0x3f)) - return 0; - - if (!(cap_rid->hardCap & cpu_to_le16(8))) - return 0; - - sq = le16_to_cpu(status_rid->signalQuality); - if (memcmp(cap_rid->prodName, "350", 3)) - if (sq > 0x20) - quality = 0; - else - quality = 0x20 - sq; - else - if (sq > 0xb0) - quality = 0; - else if (sq < 0x10) - quality = 0xa0; - else - quality = 0xb0 - sq; - return quality; -} - -#define airo_get_max_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x20 : 0xa0) -#define airo_get_avg_quality(cap_rid) (memcmp((cap_rid)->prodName, "350", 3) ? 0x10 : 0x50); - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get protocol name - */ -static int airo_get_name(struct net_device *dev, - struct iw_request_info *info, - char *cwrq, - char *extra) -{ - strcpy(cwrq, "IEEE 802.11-DS"); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set frequency - */ -static int airo_set_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int rc = -EINPROGRESS; /* Call commit handler */ - - /* If setting by frequency, convert to a channel */ - if(fwrq->e == 1) { - int f = fwrq->m / 100000; - - /* Hack to fall through... */ - fwrq->e = 0; - fwrq->m = ieee80211_freq_to_dsss_chan(f); - } - /* Setting by channel number */ - if((fwrq->m > 1000) || (fwrq->e > 0)) - rc = -EOPNOTSUPP; - else { - int channel = fwrq->m; - /* We should do a better check than that, - * based on the card capability !!! */ - if((channel < 1) || (channel > 14)) { - airo_print_dbg(dev->name, "New channel value of %d is invalid!", - fwrq->m); - rc = -EINVAL; - } else { - readConfigRid(local, 1); - /* Yes ! We can set it !!! */ - local->config.channelSet = cpu_to_le16(channel); - set_bit (FLAG_COMMIT, &local->flags); - } - } - return rc; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get frequency - */ -static int airo_get_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - StatusRid status_rid; /* Card status info */ - int ch; - - readConfigRid(local, 1); - if ((local->config.opmode & MODE_CFG_MASK) == MODE_STA_ESS) - status_rid.channel = local->config.channelSet; - else - readStatusRid(local, &status_rid, 1); - - ch = le16_to_cpu(status_rid.channel); - if((ch > 0) && (ch < 15)) { - fwrq->m = ieee80211_dsss_chan_to_freq(ch) * 100000; - fwrq->e = 1; - } else { - fwrq->m = ch; - fwrq->e = 0; - } - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set ESSID - */ -static int airo_set_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - SsidRid SSID_rid; /* SSIDs */ - - /* Reload the list of current SSID */ - readSsidRid(local, &SSID_rid); - - /* Check if we asked for `any' */ - if (dwrq->flags == 0) { - /* Just send an empty SSID list */ - memset(&SSID_rid, 0, sizeof(SSID_rid)); - } else { - unsigned index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - - /* Check the size of the string */ - if (dwrq->length > IW_ESSID_MAX_SIZE) - return -E2BIG ; - - /* Check if index is valid */ - if (index >= ARRAY_SIZE(SSID_rid.ssids)) - return -EINVAL; - - /* Set the SSID */ - memset(SSID_rid.ssids[index].ssid, 0, - sizeof(SSID_rid.ssids[index].ssid)); - memcpy(SSID_rid.ssids[index].ssid, extra, dwrq->length); - SSID_rid.ssids[index].len = cpu_to_le16(dwrq->length); - } - SSID_rid.len = cpu_to_le16(sizeof(SSID_rid)); - /* Write it to the card */ - disable_MAC(local, 1); - writeSsidRid(local, &SSID_rid, 1); - enable_MAC(local, 1); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get ESSID - */ -static int airo_get_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - StatusRid status_rid; /* Card status info */ - - readStatusRid(local, &status_rid, 1); - - /* Note : if dwrq->flags != 0, we should - * get the relevant SSID from the SSID list... */ - - /* Get the current SSID */ - memcpy(extra, status_rid.SSID, le16_to_cpu(status_rid.SSIDlen)); - /* If none, we may want to get the one that was set */ - - /* Push it out ! */ - dwrq->length = le16_to_cpu(status_rid.SSIDlen); - dwrq->flags = 1; /* active */ - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set AP address - */ -static int airo_set_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - Cmd cmd; - Resp rsp; - APListRid APList_rid; - static const u8 any[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - static const u8 off[ETH_ALEN] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - - if (awrq->sa_family != ARPHRD_ETHER) - return -EINVAL; - else if (!memcmp(any, awrq->sa_data, ETH_ALEN) || - !memcmp(off, awrq->sa_data, ETH_ALEN)) { - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd=CMD_LOSE_SYNC; - if (down_interruptible(&local->sem)) - return -ERESTARTSYS; - issuecommand(local, &cmd, &rsp); - up(&local->sem); - } else { - memset(&APList_rid, 0, sizeof(APList_rid)); - APList_rid.len = cpu_to_le16(sizeof(APList_rid)); - memcpy(APList_rid.ap[0], awrq->sa_data, ETH_ALEN); - disable_MAC(local, 1); - writeAPListRid(local, &APList_rid, 1); - enable_MAC(local, 1); - } - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get AP address - */ -static int airo_get_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - StatusRid status_rid; /* Card status info */ - - readStatusRid(local, &status_rid, 1); - - /* Tentative. This seems to work, wow, I'm lucky !!! */ - memcpy(awrq->sa_data, status_rid.bssid[0], ETH_ALEN); - awrq->sa_family = ARPHRD_ETHER; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Nickname - */ -static int airo_set_nick(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - /* Check the size of the string */ - if(dwrq->length > 16) { - return -E2BIG; - } - readConfigRid(local, 1); - memset(local->config.nodeName, 0, sizeof(local->config.nodeName)); - memcpy(local->config.nodeName, extra, dwrq->length); - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Nickname - */ -static int airo_get_nick(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - strncpy(extra, local->config.nodeName, 16); - extra[16] = '\0'; - dwrq->length = strlen(extra); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Bit-Rate - */ -static int airo_set_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - CapabilityRid cap_rid; /* Card capability info */ - u8 brate = 0; - int i; - - /* First : get a valid bit rate value */ - readCapabilityRid(local, &cap_rid, 1); - - /* Which type of value ? */ - if((vwrq->value < 8) && (vwrq->value >= 0)) { - /* Setting by rate index */ - /* Find value in the magic rate table */ - brate = cap_rid.supportedRates[vwrq->value]; - } else { - /* Setting by frequency value */ - u8 normvalue = (u8) (vwrq->value/500000); - - /* Check if rate is valid */ - for(i = 0 ; i < 8 ; i++) { - if(normvalue == cap_rid.supportedRates[i]) { - brate = normvalue; - break; - } - } - } - /* -1 designed the max rate (mostly auto mode) */ - if(vwrq->value == -1) { - /* Get the highest available rate */ - for(i = 0 ; i < 8 ; i++) { - if(cap_rid.supportedRates[i] == 0) - break; - } - if(i != 0) - brate = cap_rid.supportedRates[i - 1]; - } - /* Check that it is valid */ - if(brate == 0) { - return -EINVAL; - } - - readConfigRid(local, 1); - /* Now, check if we want a fixed or auto value */ - if(vwrq->fixed == 0) { - /* Fill all the rates up to this max rate */ - memset(local->config.rates, 0, 8); - for(i = 0 ; i < 8 ; i++) { - local->config.rates[i] = cap_rid.supportedRates[i]; - if(local->config.rates[i] == brate) - break; - } - } else { - /* Fixed mode */ - /* One rate, fixed */ - memset(local->config.rates, 0, 8); - local->config.rates[0] = brate; - } - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Bit-Rate - */ -static int airo_get_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - StatusRid status_rid; /* Card status info */ - - readStatusRid(local, &status_rid, 1); - - vwrq->value = le16_to_cpu(status_rid.currentXmitRate) * 500000; - /* If more than one rate, set auto */ - readConfigRid(local, 1); - vwrq->fixed = (local->config.rates[1] == 0); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set RTS threshold - */ -static int airo_set_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int rthr = vwrq->value; - - if(vwrq->disabled) - rthr = AIRO_DEF_MTU; - if((rthr < 0) || (rthr > AIRO_DEF_MTU)) { - return -EINVAL; - } - readConfigRid(local, 1); - local->config.rtsThres = cpu_to_le16(rthr); - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get RTS threshold - */ -static int airo_get_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - vwrq->value = le16_to_cpu(local->config.rtsThres); - vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); - vwrq->fixed = 1; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Fragmentation threshold - */ -static int airo_set_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int fthr = vwrq->value; - - if(vwrq->disabled) - fthr = AIRO_DEF_MTU; - if((fthr < 256) || (fthr > AIRO_DEF_MTU)) { - return -EINVAL; - } - fthr &= ~0x1; /* Get an even value - is it really needed ??? */ - readConfigRid(local, 1); - local->config.fragThresh = cpu_to_le16(fthr); - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Fragmentation threshold - */ -static int airo_get_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - vwrq->value = le16_to_cpu(local->config.fragThresh); - vwrq->disabled = (vwrq->value >= AIRO_DEF_MTU); - vwrq->fixed = 1; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Mode of Operation - */ -static int airo_set_mode(struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int reset = 0; - - readConfigRid(local, 1); - if (sniffing_mode(local)) - reset = 1; - - switch(*uwrq) { - case IW_MODE_ADHOC: - local->config.opmode &= ~MODE_CFG_MASK; - local->config.opmode |= MODE_STA_IBSS; - local->config.rmode &= ~RXMODE_FULL_MASK; - local->config.scanMode = SCANMODE_ACTIVE; - clear_bit (FLAG_802_11, &local->flags); - break; - case IW_MODE_INFRA: - local->config.opmode &= ~MODE_CFG_MASK; - local->config.opmode |= MODE_STA_ESS; - local->config.rmode &= ~RXMODE_FULL_MASK; - local->config.scanMode = SCANMODE_ACTIVE; - clear_bit (FLAG_802_11, &local->flags); - break; - case IW_MODE_MASTER: - local->config.opmode &= ~MODE_CFG_MASK; - local->config.opmode |= MODE_AP; - local->config.rmode &= ~RXMODE_FULL_MASK; - local->config.scanMode = SCANMODE_ACTIVE; - clear_bit (FLAG_802_11, &local->flags); - break; - case IW_MODE_REPEAT: - local->config.opmode &= ~MODE_CFG_MASK; - local->config.opmode |= MODE_AP_RPTR; - local->config.rmode &= ~RXMODE_FULL_MASK; - local->config.scanMode = SCANMODE_ACTIVE; - clear_bit (FLAG_802_11, &local->flags); - break; - case IW_MODE_MONITOR: - local->config.opmode &= ~MODE_CFG_MASK; - local->config.opmode |= MODE_STA_ESS; - local->config.rmode &= ~RXMODE_FULL_MASK; - local->config.rmode |= RXMODE_RFMON | RXMODE_DISABLE_802_3_HEADER; - local->config.scanMode = SCANMODE_PASSIVE; - set_bit (FLAG_802_11, &local->flags); - break; - default: - return -EINVAL; - } - if (reset) - set_bit (FLAG_RESET, &local->flags); - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Mode of Operation - */ -static int airo_get_mode(struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - /* If not managed, assume it's ad-hoc */ - switch (local->config.opmode & MODE_CFG_MASK) { - case MODE_STA_ESS: - *uwrq = IW_MODE_INFRA; - break; - case MODE_AP: - *uwrq = IW_MODE_MASTER; - break; - case MODE_AP_RPTR: - *uwrq = IW_MODE_REPEAT; - break; - default: - *uwrq = IW_MODE_ADHOC; - } - - return 0; -} - -static inline int valid_index(struct airo_info *ai, int index) -{ - return (index >= 0) && (index <= ai->max_wep_idx); -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Encryption Key - */ -static int airo_set_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int perm = (dwrq->flags & IW_ENCODE_TEMP ? 0 : 1); - __le16 currentAuthType = local->config.authType; - int rc = 0; - - if (!local->wep_capable) - return -EOPNOTSUPP; - - readConfigRid(local, 1); - - /* Basic checking: do we have a key to set ? - * Note : with the new API, it's impossible to get a NULL pointer. - * Therefore, we need to check a key size == 0 instead. - * New version of iwconfig properly set the IW_ENCODE_NOKEY flag - * when no key is present (only change flags), but older versions - * don't do it. - Jean II */ - if (dwrq->length > 0) { - wep_key_t key; - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - int current_index; - - /* Check the size of the key */ - if (dwrq->length > MAX_KEY_SIZE) { - return -EINVAL; - } - - current_index = get_wep_tx_idx(local); - if (current_index < 0) - current_index = 0; - - /* Check the index (none -> use current) */ - if (!valid_index(local, index)) - index = current_index; - - /* Set the length */ - if (dwrq->length > MIN_KEY_SIZE) - key.len = MAX_KEY_SIZE; - else - key.len = MIN_KEY_SIZE; - /* Check if the key is not marked as invalid */ - if(!(dwrq->flags & IW_ENCODE_NOKEY)) { - /* Cleanup */ - memset(key.key, 0, MAX_KEY_SIZE); - /* Copy the key in the driver */ - memcpy(key.key, extra, dwrq->length); - /* Send the key to the card */ - rc = set_wep_key(local, index, key.key, key.len, perm, 1); - if (rc < 0) { - airo_print_err(local->dev->name, "failed to set" - " WEP key at index %d: %d.", - index, rc); - return rc; - } - } - /* WE specify that if a valid key is set, encryption - * should be enabled (user may turn it off later) - * This is also how "iwconfig ethX key on" works */ - if((index == current_index) && (key.len > 0) && - (local->config.authType == AUTH_OPEN)) { - local->config.authType = AUTH_ENCRYPT; - } - } else { - /* Do we want to just set the transmit key index ? */ - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (valid_index(local, index)) { - rc = set_wep_tx_idx(local, index, perm, 1); - if (rc < 0) { - airo_print_err(local->dev->name, "failed to set" - " WEP transmit index to %d: %d.", - index, rc); - return rc; - } - } else { - /* Don't complain if only change the mode */ - if (!(dwrq->flags & IW_ENCODE_MODE)) - return -EINVAL; - } - } - /* Read the flags */ - if(dwrq->flags & IW_ENCODE_DISABLED) - local->config.authType = AUTH_OPEN; // disable encryption - if(dwrq->flags & IW_ENCODE_RESTRICTED) - local->config.authType = AUTH_SHAREDKEY; // Only Both - if(dwrq->flags & IW_ENCODE_OPEN) - local->config.authType = AUTH_ENCRYPT; // Only Wep - /* Commit the changes to flags if needed */ - if (local->config.authType != currentAuthType) - set_bit (FLAG_COMMIT, &local->flags); - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Encryption Key - */ -static int airo_get_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - int wep_key_len; - u8 buf[16]; - - if (!local->wep_capable) - return -EOPNOTSUPP; - - readConfigRid(local, 1); - - /* Check encryption mode */ - switch(local->config.authType) { - case AUTH_ENCRYPT: - dwrq->flags = IW_ENCODE_OPEN; - break; - case AUTH_SHAREDKEY: - dwrq->flags = IW_ENCODE_RESTRICTED; - break; - default: - case AUTH_OPEN: - dwrq->flags = IW_ENCODE_DISABLED; - break; - } - /* We can't return the key, so set the proper flag and return zero */ - dwrq->flags |= IW_ENCODE_NOKEY; - memset(extra, 0, 16); - - /* Which key do we want ? -1 -> tx index */ - if (!valid_index(local, index)) { - index = get_wep_tx_idx(local); - if (index < 0) - index = 0; - } - dwrq->flags |= index + 1; - - /* Copy the key to the user buffer */ - wep_key_len = get_wep_key(local, index, &buf[0], sizeof(buf)); - if (wep_key_len < 0) { - dwrq->length = 0; - } else { - dwrq->length = wep_key_len; - memcpy(extra, buf, dwrq->length); - } - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set extended Encryption parameters - */ -static int airo_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int perm = ( encoding->flags & IW_ENCODE_TEMP ? 0 : 1 ); - __le16 currentAuthType = local->config.authType; - int idx, key_len, alg = ext->alg, set_key = 1, rc; - wep_key_t key; - - if (!local->wep_capable) - return -EOPNOTSUPP; - - readConfigRid(local, 1); - - /* Determine and validate the key index */ - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (!valid_index(local, idx - 1)) - return -EINVAL; - idx--; - } else { - idx = get_wep_tx_idx(local); - if (idx < 0) - idx = 0; - } - - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - /* Only set transmit key index here, actual - * key is set below if needed. - */ - rc = set_wep_tx_idx(local, idx, perm, 1); - if (rc < 0) { - airo_print_err(local->dev->name, "failed to set " - "WEP transmit index to %d: %d.", - idx, rc); - return rc; - } - set_key = ext->key_len > 0 ? 1 : 0; - } - - if (set_key) { - /* Set the requested key first */ - memset(key.key, 0, MAX_KEY_SIZE); - switch (alg) { - case IW_ENCODE_ALG_NONE: - key.len = 0; - break; - case IW_ENCODE_ALG_WEP: - if (ext->key_len > MIN_KEY_SIZE) { - key.len = MAX_KEY_SIZE; - } else if (ext->key_len > 0) { - key.len = MIN_KEY_SIZE; - } else { - return -EINVAL; - } - key_len = min (ext->key_len, key.len); - memcpy(key.key, ext->key, key_len); - break; - default: - return -EINVAL; - } - if (key.len == 0) { - rc = set_wep_tx_idx(local, idx, perm, 1); - if (rc < 0) { - airo_print_err(local->dev->name, - "failed to set WEP transmit index to %d: %d.", - idx, rc); - return rc; - } - } else { - rc = set_wep_key(local, idx, key.key, key.len, perm, 1); - if (rc < 0) { - airo_print_err(local->dev->name, - "failed to set WEP key at index %d: %d.", - idx, rc); - return rc; - } - } - } - - /* Read the flags */ - if(encoding->flags & IW_ENCODE_DISABLED) - local->config.authType = AUTH_OPEN; // disable encryption - if(encoding->flags & IW_ENCODE_RESTRICTED) - local->config.authType = AUTH_SHAREDKEY; // Only Both - if(encoding->flags & IW_ENCODE_OPEN) - local->config.authType = AUTH_ENCRYPT; // Only Wep - /* Commit the changes to flags if needed */ - if (local->config.authType != currentAuthType) - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; -} - - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get extended Encryption parameters - */ -static int airo_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, max_key_len, wep_key_len; - u8 buf[16]; - - if (!local->wep_capable) - return -EOPNOTSUPP; - - readConfigRid(local, 1); - - max_key_len = encoding->length - sizeof(*ext); - if (max_key_len < 0) - return -EINVAL; - - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (!valid_index(local, idx - 1)) - return -EINVAL; - idx--; - } else { - idx = get_wep_tx_idx(local); - if (idx < 0) - idx = 0; - } - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - /* Check encryption mode */ - switch(local->config.authType) { - case AUTH_ENCRYPT: - encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED; - break; - case AUTH_SHAREDKEY: - encoding->flags = IW_ENCODE_ALG_WEP | IW_ENCODE_ENABLED; - break; - default: - case AUTH_OPEN: - encoding->flags = IW_ENCODE_ALG_NONE | IW_ENCODE_DISABLED; - break; - } - /* We can't return the key, so set the proper flag and return zero */ - encoding->flags |= IW_ENCODE_NOKEY; - memset(extra, 0, 16); - - /* Copy the key to the user buffer */ - wep_key_len = get_wep_key(local, idx, &buf[0], sizeof(buf)); - if (wep_key_len < 0) { - ext->key_len = 0; - } else { - ext->key_len = wep_key_len; - memcpy(extra, buf, ext->key_len); - } - - return 0; -} - - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set extended authentication parameters - */ -static int airo_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct airo_info *local = dev->ml_priv; - struct iw_param *param = &wrqu->param; - __le16 currentAuthType = local->config.authType; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - case IW_AUTH_PRIVACY_INVOKED: - /* - * airo does not use these parameters - */ - break; - - case IW_AUTH_DROP_UNENCRYPTED: - if (param->value) { - /* Only change auth type if unencrypted */ - if (currentAuthType == AUTH_OPEN) - local->config.authType = AUTH_ENCRYPT; - } else { - local->config.authType = AUTH_OPEN; - } - - /* Commit the changes to flags if needed */ - if (local->config.authType != currentAuthType) - set_bit (FLAG_COMMIT, &local->flags); - break; - - case IW_AUTH_80211_AUTH_ALG: { - /* FIXME: What about AUTH_OPEN? This API seems to - * disallow setting our auth to AUTH_OPEN. - */ - if (param->value & IW_AUTH_ALG_SHARED_KEY) { - local->config.authType = AUTH_SHAREDKEY; - } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - local->config.authType = AUTH_ENCRYPT; - } else - return -EINVAL; - - /* Commit the changes to flags if needed */ - if (local->config.authType != currentAuthType) - set_bit (FLAG_COMMIT, &local->flags); - break; - } - - case IW_AUTH_WPA_ENABLED: - /* Silently accept disable of WPA */ - if (param->value > 0) - return -EOPNOTSUPP; - break; - - default: - return -EOPNOTSUPP; - } - return -EINPROGRESS; -} - - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get extended authentication parameters - */ -static int airo_get_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct airo_info *local = dev->ml_priv; - struct iw_param *param = &wrqu->param; - __le16 currentAuthType = local->config.authType; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - switch (currentAuthType) { - case AUTH_SHAREDKEY: - case AUTH_ENCRYPT: - param->value = 1; - break; - default: - param->value = 0; - break; - } - break; - - case IW_AUTH_80211_AUTH_ALG: - switch (currentAuthType) { - case AUTH_SHAREDKEY: - param->value = IW_AUTH_ALG_SHARED_KEY; - break; - case AUTH_ENCRYPT: - default: - param->value = IW_AUTH_ALG_OPEN_SYSTEM; - break; - } - break; - - case IW_AUTH_WPA_ENABLED: - param->value = 0; - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Tx-Power - */ -static int airo_set_txpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - CapabilityRid cap_rid; /* Card capability info */ - int i; - int rc = -EINVAL; - __le16 v = cpu_to_le16(vwrq->value); - - readCapabilityRid(local, &cap_rid, 1); - - if (vwrq->disabled) { - set_bit (FLAG_RADIO_OFF, &local->flags); - set_bit (FLAG_COMMIT, &local->flags); - return -EINPROGRESS; /* Call commit handler */ - } - if (vwrq->flags != IW_TXPOW_MWATT) { - return -EINVAL; - } - clear_bit (FLAG_RADIO_OFF, &local->flags); - for (i = 0; i < 8 && cap_rid.txPowerLevels[i]; i++) - if (v == cap_rid.txPowerLevels[i]) { - readConfigRid(local, 1); - local->config.txPower = v; - set_bit (FLAG_COMMIT, &local->flags); - rc = -EINPROGRESS; /* Call commit handler */ - break; - } - return rc; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Tx-Power - */ -static int airo_get_txpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - vwrq->value = le16_to_cpu(local->config.txPower); - vwrq->fixed = 1; /* No power control */ - vwrq->disabled = test_bit(FLAG_RADIO_OFF, &local->flags); - vwrq->flags = IW_TXPOW_MWATT; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Retry limits - */ -static int airo_set_retry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - int rc = -EINVAL; - - if(vwrq->disabled) { - return -EINVAL; - } - readConfigRid(local, 1); - if(vwrq->flags & IW_RETRY_LIMIT) { - __le16 v = cpu_to_le16(vwrq->value); - if(vwrq->flags & IW_RETRY_LONG) - local->config.longRetryLimit = v; - else if (vwrq->flags & IW_RETRY_SHORT) - local->config.shortRetryLimit = v; - else { - /* No modifier : set both */ - local->config.longRetryLimit = v; - local->config.shortRetryLimit = v; - } - set_bit (FLAG_COMMIT, &local->flags); - rc = -EINPROGRESS; /* Call commit handler */ - } - if(vwrq->flags & IW_RETRY_LIFETIME) { - local->config.txLifetime = cpu_to_le16(vwrq->value / 1024); - set_bit (FLAG_COMMIT, &local->flags); - rc = -EINPROGRESS; /* Call commit handler */ - } - return rc; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Retry limits - */ -static int airo_get_retry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - vwrq->disabled = 0; /* Can't be disabled */ - - readConfigRid(local, 1); - /* Note : by default, display the min retry number */ - if((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - vwrq->flags = IW_RETRY_LIFETIME; - vwrq->value = le16_to_cpu(local->config.txLifetime) * 1024; - } else if((vwrq->flags & IW_RETRY_LONG)) { - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - vwrq->value = le16_to_cpu(local->config.longRetryLimit); - } else { - vwrq->flags = IW_RETRY_LIMIT; - vwrq->value = le16_to_cpu(local->config.shortRetryLimit); - if(local->config.shortRetryLimit != local->config.longRetryLimit) - vwrq->flags |= IW_RETRY_SHORT; - } - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get range info - */ -static int airo_get_range(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - struct iw_range *range = (struct iw_range *) extra; - CapabilityRid cap_rid; /* Card capability info */ - int i; - int k; - - readCapabilityRid(local, &cap_rid, 1); - - dwrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(*range)); - range->min_nwid = 0x0000; - range->max_nwid = 0x0000; - range->num_channels = 14; - /* Should be based on cap_rid.country to give only - * what the current card support */ - k = 0; - for(i = 0; i < 14; i++) { - range->freq[k].i = i + 1; /* List index */ - range->freq[k].m = ieee80211_dsss_chan_to_freq(i + 1) * 100000; - range->freq[k++].e = 1; /* Values in MHz -> * 10^5 * 10 */ - } - range->num_frequency = k; - - range->sensitivity = 65535; - - /* Hum... Should put the right values there */ - if (local->rssi) - range->max_qual.qual = 100; /* % */ - else - range->max_qual.qual = airo_get_max_quality(&cap_rid); - range->max_qual.level = 0x100 - 120; /* -120 dBm */ - range->max_qual.noise = 0x100 - 120; /* -120 dBm */ - - /* Experimental measurements - boundary 11/5.5 Mb/s */ - /* Note : with or without the (local->rssi), results - * are somewhat different. - Jean II */ - if (local->rssi) { - range->avg_qual.qual = 50; /* % */ - range->avg_qual.level = 0x100 - 70; /* -70 dBm */ - } else { - range->avg_qual.qual = airo_get_avg_quality(&cap_rid); - range->avg_qual.level = 0x100 - 80; /* -80 dBm */ - } - range->avg_qual.noise = 0x100 - 85; /* -85 dBm */ - - for(i = 0 ; i < 8 ; i++) { - range->bitrate[i] = cap_rid.supportedRates[i] * 500000; - if(range->bitrate[i] == 0) - break; - } - range->num_bitrates = i; - - /* Set an indication of the max TCP throughput - * in bit/s that we can expect using this interface. - * May be use for QoS stuff... Jean II */ - if(i > 2) - range->throughput = 5000 * 1000; - else - range->throughput = 1500 * 1000; - - range->min_rts = 0; - range->max_rts = AIRO_DEF_MTU; - range->min_frag = 256; - range->max_frag = AIRO_DEF_MTU; - - if(cap_rid.softCap & cpu_to_le16(2)) { - // WEP: RC4 40 bits - range->encoding_size[0] = 5; - // RC4 ~128 bits - if (cap_rid.softCap & cpu_to_le16(0x100)) { - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - } else - range->num_encoding_sizes = 1; - range->max_encoding_tokens = - cap_rid.softCap & cpu_to_le16(0x80) ? 4 : 1; - } else { - range->num_encoding_sizes = 0; - range->max_encoding_tokens = 0; - } - range->min_pmp = 0; - range->max_pmp = 5000000; /* 5 secs */ - range->min_pmt = 0; - range->max_pmt = 65535 * 1024; /* ??? */ - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | IW_POWER_ALL_R; - - /* Transmit Power - values are in mW */ - for(i = 0 ; i < 8 ; i++) { - range->txpower[i] = le16_to_cpu(cap_rid.txPowerLevels[i]); - if(range->txpower[i] == 0) - break; - } - range->num_txpower = i; - range->txpower_capa = IW_TXPOW_MWATT; - range->we_version_source = 19; - range->we_version_compiled = WIRELESS_EXT; - range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; - range->retry_flags = IW_RETRY_LIMIT; - range->r_time_flags = IW_RETRY_LIFETIME; - range->min_retry = 1; - range->max_retry = 65535; - range->min_r_time = 1024; - range->max_r_time = 65535 * 1024; - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVTXDROP); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Power Management - */ -static int airo_set_power(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - if (vwrq->disabled) { - if (sniffing_mode(local)) - return -EINVAL; - local->config.powerSaveMode = POWERSAVE_CAM; - local->config.rmode &= ~RXMODE_MASK; - local->config.rmode |= RXMODE_BC_MC_ADDR; - set_bit (FLAG_COMMIT, &local->flags); - return -EINPROGRESS; /* Call commit handler */ - } - if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - local->config.fastListenDelay = cpu_to_le16((vwrq->value + 500) / 1024); - local->config.powerSaveMode = POWERSAVE_PSPCAM; - set_bit (FLAG_COMMIT, &local->flags); - } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { - local->config.fastListenInterval = - local->config.listenInterval = - cpu_to_le16((vwrq->value + 500) / 1024); - local->config.powerSaveMode = POWERSAVE_PSPCAM; - set_bit (FLAG_COMMIT, &local->flags); - } - switch (vwrq->flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - if (sniffing_mode(local)) - return -EINVAL; - local->config.rmode &= ~RXMODE_MASK; - local->config.rmode |= RXMODE_ADDR; - set_bit (FLAG_COMMIT, &local->flags); - break; - case IW_POWER_ALL_R: - if (sniffing_mode(local)) - return -EINVAL; - local->config.rmode &= ~RXMODE_MASK; - local->config.rmode |= RXMODE_BC_MC_ADDR; - set_bit (FLAG_COMMIT, &local->flags); - case IW_POWER_ON: - /* This is broken, fixme ;-) */ - break; - default: - return -EINVAL; - } - // Note : we may want to factor local->need_commit here - // Note2 : may also want to factor RXMODE_RFMON test - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Power Management - */ -static int airo_get_power(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - __le16 mode; - - readConfigRid(local, 1); - mode = local->config.powerSaveMode; - if ((vwrq->disabled = (mode == POWERSAVE_CAM))) - return 0; - if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - vwrq->value = le16_to_cpu(local->config.fastListenDelay) * 1024; - vwrq->flags = IW_POWER_TIMEOUT; - } else { - vwrq->value = le16_to_cpu(local->config.fastListenInterval) * 1024; - vwrq->flags = IW_POWER_PERIOD; - } - if ((local->config.rmode & RXMODE_MASK) == RXMODE_ADDR) - vwrq->flags |= IW_POWER_UNICAST_R; - else - vwrq->flags |= IW_POWER_ALL_R; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Sensitivity - */ -static int airo_set_sens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - local->config.rssiThreshold = - cpu_to_le16(vwrq->disabled ? RSSI_DEFAULT : vwrq->value); - set_bit (FLAG_COMMIT, &local->flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Sensitivity - */ -static int airo_get_sens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - - readConfigRid(local, 1); - vwrq->value = le16_to_cpu(local->config.rssiThreshold); - vwrq->disabled = (vwrq->value == 0); - vwrq->fixed = 1; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get AP List - * Note : this is deprecated in favor of IWSCAN - */ -static int airo_get_aplist(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *local = dev->ml_priv; - struct sockaddr *address = (struct sockaddr *) extra; - struct iw_quality *qual; - BSSListRid BSSList; - int i; - int loseSync = capable(CAP_NET_ADMIN) ? 1: -1; - - qual = kmalloc(IW_MAX_AP * sizeof(*qual), GFP_KERNEL); - if (!qual) - return -ENOMEM; - - for (i = 0; i < IW_MAX_AP; i++) { - u16 dBm; - if (readBSSListRid(local, loseSync, &BSSList)) - break; - loseSync = 0; - memcpy(address[i].sa_data, BSSList.bssid, ETH_ALEN); - address[i].sa_family = ARPHRD_ETHER; - dBm = le16_to_cpu(BSSList.dBm); - if (local->rssi) { - qual[i].level = 0x100 - dBm; - qual[i].qual = airo_dbm_to_pct(local->rssi, dBm); - qual[i].updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_DBM; - } else { - qual[i].level = (dBm + 321) / 2; - qual[i].qual = 0; - qual[i].updated = IW_QUAL_QUAL_INVALID - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_DBM; - } - qual[i].noise = local->wstats.qual.noise; - if (BSSList.index == cpu_to_le16(0xffff)) - break; - } - if (!i) { - StatusRid status_rid; /* Card status info */ - readStatusRid(local, &status_rid, 1); - for (i = 0; - i < min(IW_MAX_AP, 4) && - (status_rid.bssid[i][0] - & status_rid.bssid[i][1] - & status_rid.bssid[i][2] - & status_rid.bssid[i][3] - & status_rid.bssid[i][4] - & status_rid.bssid[i][5])!=0xff && - (status_rid.bssid[i][0] - | status_rid.bssid[i][1] - | status_rid.bssid[i][2] - | status_rid.bssid[i][3] - | status_rid.bssid[i][4] - | status_rid.bssid[i][5]); - i++) { - memcpy(address[i].sa_data, - status_rid.bssid[i], ETH_ALEN); - address[i].sa_family = ARPHRD_ETHER; - } - } else { - dwrq->flags = 1; /* Should be define'd */ - memcpy(extra + sizeof(struct sockaddr)*i, - &qual, sizeof(struct iw_quality)*i); - } - dwrq->length = i; - - kfree(qual); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : Initiate Scan - */ -static int airo_set_scan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *ai = dev->ml_priv; - Cmd cmd; - Resp rsp; - int wake = 0; - - /* Note : you may have realised that, as this is a SET operation, - * this is privileged and therefore a normal user can't - * perform scanning. - * This is not an error, while the device perform scanning, - * traffic doesn't flow, so it's a perfect DoS... - * Jean II */ - if (ai->flags & FLAG_RADIO_MASK) return -ENETDOWN; - - if (down_interruptible(&ai->sem)) - return -ERESTARTSYS; - - /* If there's already a scan in progress, don't - * trigger another one. */ - if (ai->scan_timeout > 0) - goto out; - - /* Initiate a scan command */ - ai->scan_timeout = RUN_AT(3*HZ); - memset(&cmd, 0, sizeof(cmd)); - cmd.cmd=CMD_LISTBSS; - issuecommand(ai, &cmd, &rsp); - wake = 1; - -out: - up(&ai->sem); - if (wake) - wake_up_interruptible(&ai->thr_wait); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Translate scan data returned from the card to a card independent - * format that the Wireless Tools will understand - Jean II - */ -static inline char *airo_translate_scan(struct net_device *dev, - struct iw_request_info *info, - char *current_ev, - char *end_buf, - BSSListRid *bss) -{ - struct airo_info *ai = dev->ml_priv; - struct iw_event iwe; /* Temporary buffer */ - __le16 capabilities; - char * current_val; /* For rates */ - int i; - char * buf; - u16 dBm; - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bss->bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); - - /* Other entries will be displayed in the order we give them */ - - /* Add the ESSID */ - iwe.u.data.length = bss->ssidLen; - if(iwe.u.data.length > 32) - iwe.u.data.length = 32; - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid); - - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - capabilities = bss->cap; - if(capabilities & (CAP_ESS | CAP_IBSS)) { - if(capabilities & CAP_ESS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); - } - - /* Add frequency */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = le16_to_cpu(bss->dsChannel); - iwe.u.freq.m = ieee80211_dsss_chan_to_freq(iwe.u.freq.m) * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); - - dBm = le16_to_cpu(bss->dBm); - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - if (ai->rssi) { - iwe.u.qual.level = 0x100 - dBm; - iwe.u.qual.qual = airo_dbm_to_pct(ai->rssi, dBm); - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_DBM; - } else { - iwe.u.qual.level = (dBm + 321) / 2; - iwe.u.qual.qual = 0; - iwe.u.qual.updated = IW_QUAL_QUAL_INVALID - | IW_QUAL_LEVEL_UPDATED - | IW_QUAL_DBM; - } - iwe.u.qual.noise = ai->wstats.qual.noise; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if(capabilities & CAP_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid); - - /* Rate : stuffing multiple values in a single event require a bit - * more of magic - Jean II */ - current_val = current_ev + iwe_stream_lcp_len(info); - - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - /* Max 8 values */ - for(i = 0 ; i < 8 ; i++) { - /* NULL terminated */ - if(bss->rates[i] == 0) - break; - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((bss->rates[i] & 0x7f) * 500000); - /* Add new value to event */ - current_val = iwe_stream_add_value(info, current_ev, - current_val, end_buf, - &iwe, IW_EV_PARAM_LEN); - } - /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) - current_ev = current_val; - - /* Beacon interval */ - buf = kmalloc(30, GFP_KERNEL); - if (buf) { - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "bcn_int=%d", bss->beaconInterval); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); - kfree(buf); - } - - /* Put WPA/RSN Information Elements into the event stream */ - if (test_bit(FLAG_WPA_CAPABLE, &ai->flags)) { - unsigned int num_null_ies = 0; - u16 length = sizeof (bss->extra.iep); - u8 *ie = (void *)&bss->extra.iep; - - while ((length >= 2) && (num_null_ies < 2)) { - if (2 + ie[1] > length) { - /* Invalid element, don't continue parsing IE */ - break; - } - - switch (ie[0]) { - case WLAN_EID_SSID: - /* Two zero-length SSID elements - * mean we're done parsing elements */ - if (!ie[1]) - num_null_ies++; - break; - - case WLAN_EID_GENERIC: - if (ie[1] >= 4 && - ie[2] == 0x00 && - ie[3] == 0x50 && - ie[4] == 0xf2 && - ie[5] == 0x01) { - iwe.cmd = IWEVGENIE; - /* 64 is an arbitrary cut-off */ - iwe.u.data.length = min(ie[1] + 2, - 64); - current_ev = iwe_stream_add_point( - info, current_ev, - end_buf, &iwe, ie); - } - break; - - case WLAN_EID_RSN: - iwe.cmd = IWEVGENIE; - /* 64 is an arbitrary cut-off */ - iwe.u.data.length = min(ie[1] + 2, 64); - current_ev = iwe_stream_add_point( - info, current_ev, end_buf, - &iwe, ie); - break; - - default: - break; - } - - length -= 2 + ie[1]; - ie += 2 + ie[1]; - } - } - return current_ev; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : Read Scan Results - */ -static int airo_get_scan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct airo_info *ai = dev->ml_priv; - BSSListElement *net; - int err = 0; - char *current_ev = extra; - - /* If a scan is in-progress, return -EAGAIN */ - if (ai->scan_timeout > 0) - return -EAGAIN; - - if (down_interruptible(&ai->sem)) - return -EAGAIN; - - list_for_each_entry (net, &ai->network_list, list) { - /* Translate to WE format this entry */ - current_ev = airo_translate_scan(dev, info, current_ev, - extra + dwrq->length, - &net->bss); - - /* Check if there is space for one more entry */ - if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { - /* Ask user space to try again with a bigger buffer */ - err = -E2BIG; - goto out; - } - } - - /* Length of data */ - dwrq->length = (current_ev - extra); - dwrq->flags = 0; /* todo */ - -out: - up(&ai->sem); - return err; -} - -/*------------------------------------------------------------------*/ -/* - * Commit handler : called after a bunch of SET operations - */ -static int airo_config_commit(struct net_device *dev, - struct iw_request_info *info, /* NULL */ - void *zwrq, /* NULL */ - char *extra) /* NULL */ -{ - struct airo_info *local = dev->ml_priv; - - if (!test_bit (FLAG_COMMIT, &local->flags)) - return 0; - - /* Some of the "SET" function may have modified some of the - * parameters. It's now time to commit them in the card */ - disable_MAC(local, 1); - if (test_bit (FLAG_RESET, &local->flags)) { - APListRid APList_rid; - SsidRid SSID_rid; - - readAPListRid(local, &APList_rid); - readSsidRid(local, &SSID_rid); - if (test_bit(FLAG_MPI,&local->flags)) - setup_card(local, dev->dev_addr, 1 ); - else - reset_airo_card(dev); - disable_MAC(local, 1); - writeSsidRid(local, &SSID_rid, 1); - writeAPListRid(local, &APList_rid, 1); - } - if (down_interruptible(&local->sem)) - return -ERESTARTSYS; - writeConfigRid(local, 0); - enable_MAC(local, 0); - if (test_bit (FLAG_RESET, &local->flags)) - airo_set_promisc(local); - else - up(&local->sem); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Structures to export the Wireless Handlers - */ - -static const struct iw_priv_args airo_private_args[] = { -/*{ cmd, set_args, get_args, name } */ - { AIROIOCTL, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), - IW_PRIV_TYPE_BYTE | 2047, "airoioctl" }, - { AIROIDIFC, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof (aironet_ioctl), - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "airoidifc" }, -}; - -static const iw_handler airo_handler[] = -{ - (iw_handler) airo_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) airo_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) airo_set_freq, /* SIOCSIWFREQ */ - (iw_handler) airo_get_freq, /* SIOCGIWFREQ */ - (iw_handler) airo_set_mode, /* SIOCSIWMODE */ - (iw_handler) airo_get_mode, /* SIOCGIWMODE */ - (iw_handler) airo_set_sens, /* SIOCSIWSENS */ - (iw_handler) airo_get_sens, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) airo_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) airo_set_wap, /* SIOCSIWAP */ - (iw_handler) airo_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) airo_get_aplist, /* SIOCGIWAPLIST */ - (iw_handler) airo_set_scan, /* SIOCSIWSCAN */ - (iw_handler) airo_get_scan, /* SIOCGIWSCAN */ - (iw_handler) airo_set_essid, /* SIOCSIWESSID */ - (iw_handler) airo_get_essid, /* SIOCGIWESSID */ - (iw_handler) airo_set_nick, /* SIOCSIWNICKN */ - (iw_handler) airo_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) airo_set_rate, /* SIOCSIWRATE */ - (iw_handler) airo_get_rate, /* SIOCGIWRATE */ - (iw_handler) airo_set_rts, /* SIOCSIWRTS */ - (iw_handler) airo_get_rts, /* SIOCGIWRTS */ - (iw_handler) airo_set_frag, /* SIOCSIWFRAG */ - (iw_handler) airo_get_frag, /* SIOCGIWFRAG */ - (iw_handler) airo_set_txpow, /* SIOCSIWTXPOW */ - (iw_handler) airo_get_txpow, /* SIOCGIWTXPOW */ - (iw_handler) airo_set_retry, /* SIOCSIWRETRY */ - (iw_handler) airo_get_retry, /* SIOCGIWRETRY */ - (iw_handler) airo_set_encode, /* SIOCSIWENCODE */ - (iw_handler) airo_get_encode, /* SIOCGIWENCODE */ - (iw_handler) airo_set_power, /* SIOCSIWPOWER */ - (iw_handler) airo_get_power, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWGENIE */ - (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) airo_set_auth, /* SIOCSIWAUTH */ - (iw_handler) airo_get_auth, /* SIOCGIWAUTH */ - (iw_handler) airo_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) airo_get_encodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; - -/* Note : don't describe AIROIDIFC and AIROOLDIDIFC in here. - * We want to force the use of the ioctl code, because those can't be - * won't work the iw_handler code (because they simultaneously read - * and write data and iw_handler can't do that). - * Note that it's perfectly legal to read/write on a single ioctl command, - * you just can't use iwpriv and need to force it via the ioctl handler. - * Jean II */ -static const iw_handler airo_private_handler[] = -{ - NULL, /* SIOCIWFIRSTPRIV */ -}; - -static const struct iw_handler_def airo_handler_def = -{ - .num_standard = ARRAY_SIZE(airo_handler), - .num_private = ARRAY_SIZE(airo_private_handler), - .num_private_args = ARRAY_SIZE(airo_private_args), - .standard = airo_handler, - .private = airo_private_handler, - .private_args = airo_private_args, - .get_wireless_stats = airo_get_wireless_stats, -}; - -/* - * This defines the configuration part of the Wireless Extensions - * Note : irq and spinlock protection will occur in the subroutines - * - * TODO : - * o Check input value more carefully and fill correct values in range - * o Test and shakeout the bugs (if any) - * - * Jean II - * - * Javier Achirica did a great job of merging code from the unnamed CISCO - * developer that added support for flashing the card. - */ -static int airo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - int rc = 0; - struct airo_info *ai = dev->ml_priv; - - if (ai->power.event) - return 0; - - switch (cmd) { -#ifdef CISCO_EXT - case AIROIDIFC: -#ifdef AIROOLDIDIFC - case AIROOLDIDIFC: -#endif - { - int val = AIROMAGIC; - aironet_ioctl com; - if (copy_from_user(&com,rq->ifr_data,sizeof(com))) - rc = -EFAULT; - else if (copy_to_user(com.data,(char *)&val,sizeof(val))) - rc = -EFAULT; - } - break; - - case AIROIOCTL: -#ifdef AIROOLDIOCTL - case AIROOLDIOCTL: -#endif - /* Get the command struct and hand it off for evaluation by - * the proper subfunction - */ - { - aironet_ioctl com; - if (copy_from_user(&com,rq->ifr_data,sizeof(com))) { - rc = -EFAULT; - break; - } - - /* Separate R/W functions bracket legality here - */ - if ( com.command == AIRORSWVERSION ) { - if (copy_to_user(com.data, swversion, sizeof(swversion))) - rc = -EFAULT; - else - rc = 0; - } - else if ( com.command <= AIRORRID) - rc = readrids(dev,&com); - else if ( com.command >= AIROPCAP && com.command <= (AIROPLEAPUSR+2) ) - rc = writerids(dev,&com); - else if ( com.command >= AIROFLSHRST && com.command <= AIRORESTART ) - rc = flashcard(dev,&com); - else - rc = -EINVAL; /* Bad command in ioctl */ - } - break; -#endif /* CISCO_EXT */ - - // All other calls are currently unsupported - default: - rc = -EOPNOTSUPP; - } - return rc; -} - -/* - * Get the Wireless stats out of the driver - * Note : irq and spinlock protection will occur in the subroutines - * - * TODO : - * o Check if work in Ad-Hoc mode (otherwise, use SPY, as in wvlan_cs) - * - * Jean - */ -static void airo_read_wireless_stats(struct airo_info *local) -{ - StatusRid status_rid; - StatsRid stats_rid; - CapabilityRid cap_rid; - __le32 *vals = stats_rid.vals; - - /* Get stats out of the card */ - clear_bit(JOB_WSTATS, &local->jobs); - if (local->power.event) { - up(&local->sem); - return; - } - readCapabilityRid(local, &cap_rid, 0); - readStatusRid(local, &status_rid, 0); - readStatsRid(local, &stats_rid, RID_STATS, 0); - up(&local->sem); - - /* The status */ - local->wstats.status = le16_to_cpu(status_rid.mode); - - /* Signal quality and co */ - if (local->rssi) { - local->wstats.qual.level = - airo_rssi_to_dbm(local->rssi, - le16_to_cpu(status_rid.sigQuality)); - /* normalizedSignalStrength appears to be a percentage */ - local->wstats.qual.qual = - le16_to_cpu(status_rid.normalizedSignalStrength); - } else { - local->wstats.qual.level = - (le16_to_cpu(status_rid.normalizedSignalStrength) + 321) / 2; - local->wstats.qual.qual = airo_get_quality(&status_rid, &cap_rid); - } - if (le16_to_cpu(status_rid.len) >= 124) { - local->wstats.qual.noise = 0x100 - status_rid.noisedBm; - local->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - } else { - local->wstats.qual.noise = 0; - local->wstats.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID | IW_QUAL_DBM; - } - - /* Packets discarded in the wireless adapter due to wireless - * specific problems */ - local->wstats.discard.nwid = le32_to_cpu(vals[56]) + - le32_to_cpu(vals[57]) + - le32_to_cpu(vals[58]); /* SSID Mismatch */ - local->wstats.discard.code = le32_to_cpu(vals[6]);/* RxWepErr */ - local->wstats.discard.fragment = le32_to_cpu(vals[30]); - local->wstats.discard.retries = le32_to_cpu(vals[10]); - local->wstats.discard.misc = le32_to_cpu(vals[1]) + - le32_to_cpu(vals[32]); - local->wstats.miss.beacon = le32_to_cpu(vals[34]); -} - -static struct iw_statistics *airo_get_wireless_stats(struct net_device *dev) -{ - struct airo_info *local = dev->ml_priv; - - if (!test_bit(JOB_WSTATS, &local->jobs)) { - /* Get stats out of the card if available */ - if (down_trylock(&local->sem) != 0) { - set_bit(JOB_WSTATS, &local->jobs); - wake_up_interruptible(&local->thr_wait); - } else - airo_read_wireless_stats(local); - } - - return &local->wstats; -} - -#ifdef CISCO_EXT -/* - * This just translates from driver IOCTL codes to the command codes to - * feed to the radio's host interface. Things can be added/deleted - * as needed. This represents the READ side of control I/O to - * the card - */ -static int readrids(struct net_device *dev, aironet_ioctl *comp) { - unsigned short ridcode; - unsigned char *iobuf; - int len; - struct airo_info *ai = dev->ml_priv; - - if (test_bit(FLAG_FLASHING, &ai->flags)) - return -EIO; - - switch(comp->command) - { - case AIROGCAP: ridcode = RID_CAPABILITIES; break; - case AIROGCFG: ridcode = RID_CONFIG; - if (test_bit(FLAG_COMMIT, &ai->flags)) { - disable_MAC (ai, 1); - writeConfigRid (ai, 1); - enable_MAC(ai, 1); - } - break; - case AIROGSLIST: ridcode = RID_SSID; break; - case AIROGVLIST: ridcode = RID_APLIST; break; - case AIROGDRVNAM: ridcode = RID_DRVNAME; break; - case AIROGEHTENC: ridcode = RID_ETHERENCAP; break; - case AIROGWEPKTMP: ridcode = RID_WEP_TEMP; - /* Only super-user can read WEP keys */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - break; - case AIROGWEPKNV: ridcode = RID_WEP_PERM; - /* Only super-user can read WEP keys */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - break; - case AIROGSTAT: ridcode = RID_STATUS; break; - case AIROGSTATSD32: ridcode = RID_STATSDELTA; break; - case AIROGSTATSC32: ridcode = RID_STATS; break; - case AIROGMICSTATS: - if (copy_to_user(comp->data, &ai->micstats, - min((int)comp->len,(int)sizeof(ai->micstats)))) - return -EFAULT; - return 0; - case AIRORRID: ridcode = comp->ridnum; break; - default: - return -EINVAL; - break; - } - - if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - - PC4500_readrid(ai,ridcode,iobuf,RIDSIZE, 1); - /* get the count of bytes in the rid docs say 1st 2 bytes is it. - * then return it to the user - * 9/22/2000 Honor user given length - */ - len = comp->len; - - if (copy_to_user(comp->data, iobuf, min(len, (int)RIDSIZE))) { - kfree (iobuf); - return -EFAULT; - } - kfree (iobuf); - return 0; -} - -/* - * Danger Will Robinson write the rids here - */ - -static int writerids(struct net_device *dev, aironet_ioctl *comp) { - struct airo_info *ai = dev->ml_priv; - int ridcode; - int enabled; - static int (* writer)(struct airo_info *, u16 rid, const void *, int, int); - unsigned char *iobuf; - - /* Only super-user can write RIDs */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (test_bit(FLAG_FLASHING, &ai->flags)) - return -EIO; - - ridcode = 0; - writer = do_writerid; - - switch(comp->command) - { - case AIROPSIDS: ridcode = RID_SSID; break; - case AIROPCAP: ridcode = RID_CAPABILITIES; break; - case AIROPAPLIST: ridcode = RID_APLIST; break; - case AIROPCFG: ai->config.len = 0; - clear_bit(FLAG_COMMIT, &ai->flags); - ridcode = RID_CONFIG; break; - case AIROPWEPKEYNV: ridcode = RID_WEP_PERM; break; - case AIROPLEAPUSR: ridcode = RID_LEAPUSERNAME; break; - case AIROPLEAPPWD: ridcode = RID_LEAPPASSWORD; break; - case AIROPWEPKEY: ridcode = RID_WEP_TEMP; writer = PC4500_writerid; - break; - case AIROPLEAPUSR+1: ridcode = 0xFF2A; break; - case AIROPLEAPUSR+2: ridcode = 0xFF2B; break; - - /* this is not really a rid but a command given to the card - * same with MAC off - */ - case AIROPMACON: - if (enable_MAC(ai, 1) != 0) - return -EIO; - return 0; - - /* - * Evidently this code in the airo driver does not get a symbol - * as disable_MAC. it's probably so short the compiler does not gen one. - */ - case AIROPMACOFF: - disable_MAC(ai, 1); - return 0; - - /* This command merely clears the counts does not actually store any data - * only reads rid. But as it changes the cards state, I put it in the - * writerid routines. - */ - case AIROPSTCLR: - if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - - PC4500_readrid(ai,RID_STATSDELTACLEAR,iobuf,RIDSIZE, 1); - - enabled = ai->micstats.enabled; - memset(&ai->micstats,0,sizeof(ai->micstats)); - ai->micstats.enabled = enabled; - - if (copy_to_user(comp->data, iobuf, - min((int)comp->len, (int)RIDSIZE))) { - kfree (iobuf); - return -EFAULT; - } - kfree (iobuf); - return 0; - - default: - return -EOPNOTSUPP; /* Blarg! */ - } - if(comp->len > RIDSIZE) - return -EINVAL; - - if ((iobuf = kmalloc(RIDSIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - - if (copy_from_user(iobuf,comp->data,comp->len)) { - kfree (iobuf); - return -EFAULT; - } - - if (comp->command == AIROPCFG) { - ConfigRid *cfg = (ConfigRid *)iobuf; - - if (test_bit(FLAG_MIC_CAPABLE, &ai->flags)) - cfg->opmode |= MODE_MIC; - - if ((cfg->opmode & MODE_CFG_MASK) == MODE_STA_IBSS) - set_bit (FLAG_ADHOC, &ai->flags); - else - clear_bit (FLAG_ADHOC, &ai->flags); - } - - if((*writer)(ai, ridcode, iobuf,comp->len,1)) { - kfree (iobuf); - return -EIO; - } - kfree (iobuf); - return 0; -} - -/***************************************************************************** - * Ancillary flash / mod functions much black magic lurkes here * - ***************************************************************************** - */ - -/* - * Flash command switch table - */ - -static int flashcard(struct net_device *dev, aironet_ioctl *comp) { - int z; - - /* Only super-user can modify flash */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - switch(comp->command) - { - case AIROFLSHRST: - return cmdreset((struct airo_info *)dev->ml_priv); - - case AIROFLSHSTFL: - if (!AIRO_FLASH(dev) && - (AIRO_FLASH(dev) = kmalloc(FLASHSIZE, GFP_KERNEL)) == NULL) - return -ENOMEM; - return setflashmode((struct airo_info *)dev->ml_priv); - - case AIROFLSHGCHR: /* Get char from aux */ - if(comp->len != sizeof(int)) - return -EINVAL; - if (copy_from_user(&z,comp->data,comp->len)) - return -EFAULT; - return flashgchar((struct airo_info *)dev->ml_priv, z, 8000); - - case AIROFLSHPCHR: /* Send char to card. */ - if(comp->len != sizeof(int)) - return -EINVAL; - if (copy_from_user(&z,comp->data,comp->len)) - return -EFAULT; - return flashpchar((struct airo_info *)dev->ml_priv, z, 8000); - - case AIROFLPUTBUF: /* Send 32k to card */ - if (!AIRO_FLASH(dev)) - return -ENOMEM; - if(comp->len > FLASHSIZE) - return -EINVAL; - if (copy_from_user(AIRO_FLASH(dev), comp->data, comp->len)) - return -EFAULT; - - flashputbuf((struct airo_info *)dev->ml_priv); - return 0; - - case AIRORESTART: - if (flashrestart((struct airo_info *)dev->ml_priv, dev)) - return -EIO; - return 0; - } - return -EINVAL; -} - -#define FLASH_COMMAND 0x7e7e - -/* - * STEP 1) - * Disable MAC and do soft reset on - * card. - */ - -static int cmdreset(struct airo_info *ai) { - disable_MAC(ai, 1); - - if(!waitbusy (ai)){ - airo_print_info(ai->dev->name, "Waitbusy hang before RESET"); - return -EBUSY; - } - - OUT4500(ai,COMMAND,CMD_SOFTRESET); - - ssleep(1); /* WAS 600 12/7/00 */ - - if(!waitbusy (ai)){ - airo_print_info(ai->dev->name, "Waitbusy hang AFTER RESET"); - return -EBUSY; - } - return 0; -} - -/* STEP 2) - * Put the card in legendary flash - * mode - */ - -static int setflashmode (struct airo_info *ai) { - set_bit (FLAG_FLASHING, &ai->flags); - - OUT4500(ai, SWS0, FLASH_COMMAND); - OUT4500(ai, SWS1, FLASH_COMMAND); - if (probe) { - OUT4500(ai, SWS0, FLASH_COMMAND); - OUT4500(ai, COMMAND,0x10); - } else { - OUT4500(ai, SWS2, FLASH_COMMAND); - OUT4500(ai, SWS3, FLASH_COMMAND); - OUT4500(ai, COMMAND,0); - } - msleep(500); /* 500ms delay */ - - if(!waitbusy(ai)) { - clear_bit (FLAG_FLASHING, &ai->flags); - airo_print_info(ai->dev->name, "Waitbusy hang after setflash mode"); - return -EIO; - } - return 0; -} - -/* Put character to SWS0 wait for dwelltime - * x 50us for echo . - */ - -static int flashpchar(struct airo_info *ai,int byte,int dwelltime) { - int echo; - int waittime; - - byte |= 0x8000; - - if(dwelltime == 0 ) - dwelltime = 200; - - waittime=dwelltime; - - /* Wait for busy bit d15 to go false indicating buffer empty */ - while ((IN4500 (ai, SWS0) & 0x8000) && waittime > 0) { - udelay (50); - waittime -= 50; - } - - /* timeout for busy clear wait */ - if(waittime <= 0 ){ - airo_print_info(ai->dev->name, "flash putchar busywait timeout!"); - return -EBUSY; - } - - /* Port is clear now write byte and wait for it to echo back */ - do { - OUT4500(ai,SWS0,byte); - udelay(50); - dwelltime -= 50; - echo = IN4500(ai,SWS1); - } while (dwelltime >= 0 && echo != byte); - - OUT4500(ai,SWS1,0); - - return (echo == byte) ? 0 : -EIO; -} - -/* - * Get a character from the card matching matchbyte - * Step 3) - */ -static int flashgchar(struct airo_info *ai,int matchbyte,int dwelltime){ - int rchar; - unsigned char rbyte=0; - - do { - rchar = IN4500(ai,SWS1); - - if(dwelltime && !(0x8000 & rchar)){ - dwelltime -= 10; - mdelay(10); - continue; - } - rbyte = 0xff & rchar; - - if( (rbyte == matchbyte) && (0x8000 & rchar) ){ - OUT4500(ai,SWS1,0); - return 0; - } - if( rbyte == 0x81 || rbyte == 0x82 || rbyte == 0x83 || rbyte == 0x1a || 0xffff == rchar) - break; - OUT4500(ai,SWS1,0); - - }while(dwelltime > 0); - return -EIO; -} - -/* - * Transfer 32k of firmware data from user buffer to our buffer and - * send to the card - */ - -static int flashputbuf(struct airo_info *ai){ - int nwords; - - /* Write stuff */ - if (test_bit(FLAG_MPI,&ai->flags)) - memcpy_toio(ai->pciaux + 0x8000, ai->flash, FLASHSIZE); - else { - OUT4500(ai,AUXPAGE,0x100); - OUT4500(ai,AUXOFF,0); - - for(nwords=0;nwords != FLASHSIZE / 2;nwords++){ - OUT4500(ai,AUXDATA,ai->flash[nwords] & 0xffff); - } - } - OUT4500(ai,SWS0,0x8000); - - return 0; -} - -/* - * - */ -static int flashrestart(struct airo_info *ai,struct net_device *dev){ - int i,status; - - ssleep(1); /* Added 12/7/00 */ - clear_bit (FLAG_FLASHING, &ai->flags); - if (test_bit(FLAG_MPI, &ai->flags)) { - status = mpi_init_descriptors(ai); - if (status != SUCCESS) - return status; - } - status = setup_card(ai, dev->dev_addr, 1); - - if (!test_bit(FLAG_MPI,&ai->flags)) - for( i = 0; i < MAX_FIDS; i++ ) { - ai->fids[i] = transmit_allocate - ( ai, AIRO_DEF_MTU, i >= MAX_FIDS / 2 ); - } - - ssleep(1); /* Added 12/7/00 */ - return status; -} -#endif /* CISCO_EXT */ - -/* - 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. - - In addition: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -module_init(airo_init_module); -module_exit(airo_cleanup_module); diff --git a/drivers/net/wireless/airo.h b/drivers/net/wireless/airo.h deleted file mode 100644 index e480adf86be6..000000000000 --- a/drivers/net/wireless/airo.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef _AIRO_H_ -#define _AIRO_H_ - -struct net_device *init_airo_card(unsigned short irq, int port, int is_pcmcia, - struct device *dmdev); -int reset_airo_card(struct net_device *dev); -void stop_airo_card(struct net_device *dev, int freeres); - -#endif /* _AIRO_H_ */ diff --git a/drivers/net/wireless/airo_cs.c b/drivers/net/wireless/airo_cs.c deleted file mode 100644 index d0593ed9170e..000000000000 --- a/drivers/net/wireless/airo_cs.c +++ /dev/null @@ -1,485 +0,0 @@ -/*====================================================================== - - Aironet driver for 4500 and 4800 series cards - - This code is released under both the GPL version 2 and BSD licenses. - Either license may be used. The respective licenses are found at - the end of this file. - - This code was developed by Benjamin Reed - including portions of which come from the Aironet PC4500 - Developer's Reference Manual and used with permission. Copyright - (C) 1999 Benjamin Reed. All Rights Reserved. Permission to use - code in the Developer's manual was granted for this driver by - Aironet. - - In addition this module was derived from dummy_cs. - The initial developer of dummy_cs is David A. Hinds - . Portions created by David A. Hinds - are Copyright (C) 1999 David A. Hinds. All Rights Reserved. - -======================================================================*/ - -#ifdef __IN_PCMCIA_PACKAGE__ -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include - -#include "airo.h" - -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -static char *version = "$Revision: 1.2 $"; -#define DEBUG(n, args...) if (pc_debug > (n)) printk(KERN_DEBUG args); -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -MODULE_AUTHOR("Benjamin Reed"); -MODULE_DESCRIPTION("Support for Cisco/Aironet 802.11 wireless ethernet " - "cards. This is the module that links the PCMCIA card " - "with the airo module."); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_SUPPORTED_DEVICE("Aironet 4500, 4800 and Cisco 340 PCMCIA cards"); - -/*====================================================================*/ - -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card - insertion and ejection events. They are invoked from the airo_cs - event handler. -*/ - -static int airo_config(struct pcmcia_device *link); -static void airo_release(struct pcmcia_device *link); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - -static void airo_detach(struct pcmcia_device *p_dev); - -/* - You'll also need to prototype all the functions that will actually - be used to talk to your device. See 'pcmem_cs' for a good example - of a fully self-sufficient driver; the other drivers rely more or - less on other parts of the kernel. -*/ - -/* - A linked list of "instances" of the aironet device. Each actual - PCMCIA card corresponds to one device instance, and is described - by one struct pcmcia_device structure (defined in ds.h). - - You may not want to use a linked list for this -- for example, the - memory card driver uses an array of struct pcmcia_device pointers, - where minor device numbers are used to derive the corresponding - array index. -*/ - -/* - A driver needs to provide a dev_node_t structure for each device - on a card. In some cases, there is only one device per card (for - example, ethernet cards, modems). In other cases, there may be - many actual or logical devices (SCSI adapters, memory cards with - multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a struct pcmcia_device - structure. We allocate them in the card's private data structure, - because they generally shouldn't be allocated dynamically. - - In this case, we also provide a flag to indicate if a device is - "stopped" due to a power management event, or card ejection. The - device IO routines can use a flag like this to throttle IO to a - card that is not ready to accept it. -*/ - -typedef struct local_info_t { - dev_node_t node; - struct net_device *eth_dev; -} local_info_t; - -/*====================================================================== - - airo_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - - ======================================================================*/ - -static int airo_probe(struct pcmcia_device *p_dev) -{ - local_info_t *local; - - DEBUG(0, "airo_attach()\n"); - - /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - p_dev->irq.Handler = NULL; - - /* - General socket configuration defaults can go here. In this - client, we assume very little, and rely on the CIS for almost - everything. In most clients, many details (i.e., number, sizes, - and attributes of IO windows) are fixed by the nature of the - device, and can be hard-wired here. - */ - p_dev->conf.Attributes = 0; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - - /* Allocate space for private device-specific data */ - local = kzalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) { - printk(KERN_ERR "airo_cs: no memory for new device\n"); - return -ENOMEM; - } - p_dev->priv = local; - - return airo_config(p_dev); -} /* airo_attach */ - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - - ======================================================================*/ - -static void airo_detach(struct pcmcia_device *link) -{ - DEBUG(0, "airo_detach(0x%p)\n", link); - - airo_release(link); - - if (((local_info_t *)link->priv)->eth_dev) { - stop_airo_card(((local_info_t *)link->priv)->eth_dev, 0); - } - ((local_info_t *)link->priv)->eth_dev = NULL; - - kfree(link->priv); -} /* airo_detach */ - -/*====================================================================== - - airo_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - device available to the system. - - ======================================================================*/ - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -static int airo_cs_config_check(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) -{ - win_req_t *req = priv_data; - - if (cfg->index == 0) - return -ENODEV; - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - p_dev->conf.Attributes |= CONF_ENABLE_SPKR; - p_dev->conf.Status = CCSR_AUDIO_ENA; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vpp1.present & (1<conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt->vpp1.present & (1<conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; - } - } - - /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) - return -ENODEV; - - /* - Now set up a common memory window, if needed. There is room - in the struct pcmcia_device structure for one memory window handle, - but if the base addresses need to be saved, or if multiple - windows are needed, the info should go in the private data - structure for this device. - - Note that the memory window base is a physical address, and - needs to be mapped to virtual space with ioremap() before it - is used. - */ - if ((cfg->mem.nwin > 0) || (dflt->mem.nwin > 0)) { - cistpl_mem_t *mem = (cfg->mem.nwin) ? &cfg->mem : &dflt->mem; - memreq_t map; - req->Attributes = WIN_DATA_WIDTH_16|WIN_MEMORY_TYPE_CM; - req->Base = mem->win[0].host_addr; - req->Size = mem->win[0].len; - req->AccessSpeed = 0; - if (pcmcia_request_window(&p_dev, req, &p_dev->win) != 0) - return -ENODEV; - map.Page = 0; - map.CardOffset = mem->win[0].card_addr; - if (pcmcia_map_mem_page(p_dev->win, &map) != 0) - return -ENODEV; - } - /* If we got this far, we're cool! */ - return 0; -} - - -static int airo_config(struct pcmcia_device *link) -{ - local_info_t *dev; - win_req_t *req; - int last_fn, last_ret; - - dev = link->priv; - - DEBUG(0, "airo_config(0x%p)\n", link); - - req = kzalloc(sizeof(win_req_t), GFP_KERNEL); - if (!req) - return -ENOMEM; - - /* - * In this loop, we scan the CIS for configuration table - * entries, each of which describes a valid card - * configuration, including voltage, IO window, memory window, - * and interrupt settings. - * - * We make no assumptions about the card to be configured: we - * use just the information available in the CIS. In an ideal - * world, this would work for any PCMCIA card, but it requires - * a complete and accurate CIS. In practice, a driver usually - * "knows" most of these things without consulting the CIS, - * and most client drivers will only use the CIS to fill in - * implementation-defined details. - */ - last_ret = pcmcia_loop_config(link, airo_cs_config_check, req); - if (last_ret) - goto failed; - - /* - Allocate an interrupt line. Note that this does not assign a - handler to the interrupt, unless the 'Handler' member of the - irq structure is initialized. - */ - if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - - /* - This actually configures the PCMCIA socket -- setting up - the I/O windows and the interrupt mapping, and putting the - card and host interface into "Memory and IO" mode. - */ - CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link, &link->conf)); - ((local_info_t *)link->priv)->eth_dev = - init_airo_card(link->irq.AssignedIRQ, - link->io.BasePort1, 1, &handle_to_dev(link)); - if (!((local_info_t *)link->priv)->eth_dev) - goto cs_failed; - - /* - At this point, the dev_node_t structure(s) need to be - initialized and arranged in a linked list at link->dev_node. - */ - strcpy(dev->node.dev_name, ((local_info_t *)link->priv)->eth_dev->name); - dev->node.major = dev->node.minor = 0; - link->dev_node = &dev->node; - - /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: ", - dev->node.dev_name, link->conf.ConfigIndex); - if (link->conf.Vpp) - printk(", Vpp %d.%d", link->conf.Vpp/10, link->conf.Vpp%10); - if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %d", link->irq.AssignedIRQ); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); - if (link->win) - printk(", mem 0x%06lx-0x%06lx", req->Base, - req->Base+req->Size-1); - printk("\n"); - kfree(req); - return 0; - - cs_failed: - cs_error(link, last_fn, last_ret); - failed: - airo_release(link); - kfree(req); - return -ENODEV; -} /* airo_config */ - -/*====================================================================== - - After a card is removed, airo_release() will unregister the - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - - ======================================================================*/ - -static void airo_release(struct pcmcia_device *link) -{ - DEBUG(0, "airo_release(0x%p)\n", link); - pcmcia_disable_device(link); -} - -static int airo_suspend(struct pcmcia_device *link) -{ - local_info_t *local = link->priv; - - netif_device_detach(local->eth_dev); - - return 0; -} - -static int airo_resume(struct pcmcia_device *link) -{ - local_info_t *local = link->priv; - - if (link->open) { - reset_airo_card(local->eth_dev); - netif_device_attach(local->eth_dev); - } - - return 0; -} - -static struct pcmcia_device_id airo_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x015f, 0x000a), - PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0005), - PCMCIA_DEVICE_MANF_CARD(0x015f, 0x0007), - PCMCIA_DEVICE_MANF_CARD(0x0105, 0x0007), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, airo_ids); - -static struct pcmcia_driver airo_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "airo_cs", - }, - .probe = airo_probe, - .remove = airo_detach, - .id_table = airo_ids, - .suspend = airo_suspend, - .resume = airo_resume, -}; - -static int airo_cs_init(void) -{ - return pcmcia_register_driver(&airo_driver); -} - -static void airo_cs_cleanup(void) -{ - pcmcia_unregister_driver(&airo_driver); -} - -/* - 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. - - In addition: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -module_init(airo_cs_init); -module_exit(airo_cs_cleanup); diff --git a/drivers/net/wireless/arlan-main.c b/drivers/net/wireless/arlan-main.c deleted file mode 100644 index 921a082487a1..000000000000 --- a/drivers/net/wireless/arlan-main.c +++ /dev/null @@ -1,1887 +0,0 @@ -/* - * Copyright (C) 1997 Cullen Jennings - * Copyright (C) 1998 Elmer Joandiu, elmer@ylenurme.ee - * GNU General Public License applies - * This module provides support for the Arlan 655 card made by Aironet - */ - -#include "arlan.h" - -#if BITS_PER_LONG != 32 -# error FIXME: this driver requires a 32-bit platform -#endif - -static const char *arlan_version = "C.Jennigs 97 & Elmer.Joandi@ut.ee Oct'98, http://www.ylenurme.ee/~elmer/655/"; - -struct net_device *arlan_device[MAX_ARLANS]; - -static int SID = SIDUNKNOWN; -static int radioNodeId = radioNodeIdUNKNOWN; -static char encryptionKey[12] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'}; -int arlan_debug = debugUNKNOWN; -static int spreadingCode = spreadingCodeUNKNOWN; -static int channelNumber = channelNumberUNKNOWN; -static int channelSet = channelSetUNKNOWN; -static int systemId = systemIdUNKNOWN; -static int registrationMode = registrationModeUNKNOWN; -static int keyStart; -static int tx_delay_ms; -static int retries = 5; -static int tx_queue_len = 1; -static int arlan_EEPROM_bad; - -#ifdef ARLAN_DEBUGGING - -static int testMemory = testMemoryUNKNOWN; -static int irq = irqUNKNOWN; -static int txScrambled = 1; -static int mdebug; - -module_param(irq, int, 0); -module_param(mdebug, int, 0); -module_param(testMemory, int, 0); -module_param(txScrambled, int, 0); -MODULE_PARM_DESC(irq, "(unused)"); -MODULE_PARM_DESC(testMemory, "(unused)"); -MODULE_PARM_DESC(mdebug, "Arlan multicast debugging (0-1)"); -#endif - -module_param_named(debug, arlan_debug, int, 0); -module_param(spreadingCode, int, 0); -module_param(channelNumber, int, 0); -module_param(channelSet, int, 0); -module_param(systemId, int, 0); -module_param(registrationMode, int, 0); -module_param(radioNodeId, int, 0); -module_param(SID, int, 0); -module_param(keyStart, int, 0); -module_param(tx_delay_ms, int, 0); -module_param(retries, int, 0); -module_param(tx_queue_len, int, 0); -module_param_named(EEPROM_bad, arlan_EEPROM_bad, int, 0); -MODULE_PARM_DESC(debug, "Arlan debug enable (0-1)"); -MODULE_PARM_DESC(retries, "Arlan maximum packet retransmisions"); -#ifdef ARLAN_ENTRY_EXIT_DEBUGGING -static int arlan_entry_debug; -static int arlan_exit_debug; -static int arlan_entry_and_exit_debug; -module_param_named(entry_debug, arlan_entry_debug, int, 0); -module_param_named(exit_debug, arlan_exit_debug, int, 0); -module_param_named(entry_and_exit_debug, arlan_entry_and_exit_debug, int, 0); -MODULE_PARM_DESC(entry_debug, "Arlan driver function entry debugging"); -MODULE_PARM_DESC(exit_debug, "Arlan driver function exit debugging"); -MODULE_PARM_DESC(entry_and_exit_debug, "Arlan driver function entry and exit debugging"); -#endif - -struct arlan_conf_stru arlan_conf[MAX_ARLANS]; -static int arlans_found; - -static int arlan_open(struct net_device *dev); -static netdev_tx_t arlan_tx(struct sk_buff *skb, struct net_device *dev); -static irqreturn_t arlan_interrupt(int irq, void *dev_id); -static int arlan_close(struct net_device *dev); -static struct net_device_stats * - arlan_statistics (struct net_device *dev); -static void arlan_set_multicast (struct net_device *dev); -static int arlan_hw_tx (struct net_device* dev, char *buf, int length ); -static int arlan_hw_config (struct net_device * dev); -static void arlan_tx_done_interrupt (struct net_device * dev, int status); -static void arlan_rx_interrupt (struct net_device * dev, u_char rxStatus, u_short, u_short); -static void arlan_process_interrupt (struct net_device * dev); -static void arlan_tx_timeout (struct net_device *dev); - -static inline long us2ticks(int us) -{ - return us * (1000000 / HZ); -} - - -#ifdef ARLAN_ENTRY_EXIT_DEBUGGING -#define ARLAN_DEBUG_ENTRY(name) \ - {\ - struct timeval timev;\ - do_gettimeofday(&timev);\ - if (arlan_entry_debug || arlan_entry_and_exit_debug)\ - printk("--->>>" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec));\ - } -#define ARLAN_DEBUG_EXIT(name) \ - {\ - struct timeval timev;\ - do_gettimeofday(&timev);\ - if (arlan_exit_debug || arlan_entry_and_exit_debug)\ - printk("<<<---" name " %ld " "\n",((long int) timev.tv_sec * 1000000 + timev.tv_usec) );\ - } -#else -#define ARLAN_DEBUG_ENTRY(name) -#define ARLAN_DEBUG_EXIT(name) -#endif - - -#define arlan_interrupt_ack(dev)\ - clearClearInterrupt(dev);\ - setClearInterrupt(dev); - -static inline int arlan_drop_tx(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - dev->stats.tx_errors++; - if (priv->Conf->tx_delay_ms) - { - priv->tx_done_delayed = jiffies + priv->Conf->tx_delay_ms * HZ / 1000 + 1; - } - else - { - priv->waiting_command_mask &= ~ARLAN_COMMAND_TX; - TXHEAD(dev).offset = 0; - TXTAIL(dev).offset = 0; - priv->txLast = 0; - priv->bad = 0; - if (!priv->under_reset && !priv->under_config) - netif_wake_queue (dev); - } - return 1; -} - - -int arlan_command(struct net_device *dev, int command_p) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - struct arlan_conf_stru *conf = priv->Conf; - int udelayed = 0; - int i = 0; - unsigned long flags; - - ARLAN_DEBUG_ENTRY("arlan_command"); - - if (priv->card_polling_interval) - priv->card_polling_interval = 1; - - if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) - printk(KERN_DEBUG "arlan_command, %lx commandByte %x waiting %lx incoming %x \n", - jiffies, READSHMB(arlan->commandByte), - priv->waiting_command_mask, command_p); - - priv->waiting_command_mask |= command_p; - - if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) - if (time_after(jiffies, priv->lastReset + 5 * HZ)) - priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET; - - if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ACK) - { - arlan_interrupt_ack(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ACK; - } - if (priv->waiting_command_mask & ARLAN_COMMAND_INT_ENABLE) - { - setInterruptEnable(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_ENABLE; - } - - /* Card access serializing lock */ - spin_lock_irqsave(&priv->lock, flags); - - /* Check cards status and waiting */ - - if (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW)) - { - while (priv->waiting_command_mask & (ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW)) - { - if (READSHMB(arlan->resetFlag) || - READSHMB(arlan->commandByte)) /* || - (readControlRegister(dev) & ARLAN_ACCESS)) - */ - udelay(40); - else - priv->waiting_command_mask &= ~(ARLAN_COMMAND_LONG_WAIT_NOW | ARLAN_COMMAND_WAIT_NOW); - - udelayed++; - - if (priv->waiting_command_mask & ARLAN_COMMAND_LONG_WAIT_NOW) - { - if (udelayed * 40 > 1000000) - { - printk(KERN_ERR "%s long wait too long \n", dev->name); - priv->waiting_command_mask |= ARLAN_COMMAND_RESET; - break; - } - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_WAIT_NOW) - { - if (udelayed * 40 > 1000) - { - printk(KERN_ERR "%s short wait too long \n", dev->name); - goto bad_end; - } - } - } - } - else - { - i = 0; - while ((READSHMB(arlan->resetFlag) || - READSHMB(arlan->commandByte)) && - conf->pre_Command_Wait > (i++) * 10) - udelay(10); - - - if ((READSHMB(arlan->resetFlag) || - READSHMB(arlan->commandByte)) && - !(priv->waiting_command_mask & ARLAN_COMMAND_RESET)) - { - goto card_busy_end; - } - } - if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) - priv->under_reset = 1; - if (priv->waiting_command_mask & ARLAN_COMMAND_CONF) - priv->under_config = 1; - - /* Issuing command */ - arlan_lock_card_access(dev); - if (priv->waiting_command_mask & ARLAN_COMMAND_POWERUP) - { - // if (readControlRegister(dev) & (ARLAN_ACCESS && ARLAN_POWER)) - setPowerOn(dev); - arlan_interrupt_lancpu(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERUP; - priv->waiting_command_mask |= ARLAN_COMMAND_RESET; - priv->card_polling_interval = HZ / 10; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_ACTIVATE) - { - WRITESHMB(arlan->commandByte, ARLAN_COM_ACTIVATE); - arlan_interrupt_lancpu(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_ACTIVATE; - priv->card_polling_interval = HZ / 10; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_RX_ABORT) - { - if (priv->rx_command_given) - { - WRITESHMB(arlan->commandByte, ARLAN_COM_RX_ABORT); - arlan_interrupt_lancpu(dev); - priv->rx_command_given = 0; - } - priv->waiting_command_mask &= ~ARLAN_COMMAND_RX_ABORT; - priv->card_polling_interval = 1; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_TX_ABORT) - { - if (priv->tx_command_given) - { - WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ABORT); - arlan_interrupt_lancpu(dev); - priv->tx_command_given = 0; - } - priv->waiting_command_mask &= ~ARLAN_COMMAND_TX_ABORT; - priv->card_polling_interval = 1; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_RESET) - { - priv->under_reset=1; - netif_stop_queue (dev); - - arlan_drop_tx(dev); - if (priv->tx_command_given || priv->rx_command_given) - { - printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name); - } - netif_stop_queue (dev); - if (arlan_debug & ARLAN_DEBUG_RESET) - printk(KERN_ERR "%s: Doing chip reset\n", dev->name); - priv->lastReset = jiffies; - WRITESHM(arlan->commandByte, 0, u_char); - /* hold card in reset state */ - setHardwareReset(dev); - /* set reset flag and then release reset */ - WRITESHM(arlan->resetFlag, 0xff, u_char); - clearChannelAttention(dev); - clearHardwareReset(dev); - priv->card_polling_interval = HZ / 4; - priv->waiting_command_mask &= ~ARLAN_COMMAND_RESET; - priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK; -// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RENABLE; -// priv->waiting_command_mask |= ARLAN_COMMAND_RX; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RACK) - { - clearHardwareReset(dev); - clearClearInterrupt(dev); - setClearInterrupt(dev); - setInterruptEnable(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RACK; - priv->waiting_command_mask |= ARLAN_COMMAND_CONF; - priv->under_config = 1; - priv->under_reset = 0; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_INT_RENABLE) - { - setInterruptEnable(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_INT_RENABLE; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF) - { - if (priv->tx_command_given || priv->rx_command_given) - { - printk(KERN_ERR "%s: Reset under tx or rx command \n", dev->name); - } - arlan_drop_tx(dev); - setInterruptEnable(dev); - arlan_hw_config(dev); - arlan_interrupt_lancpu(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF; - priv->card_polling_interval = HZ / 10; -// priv->waiting_command_mask |= ARLAN_COMMAND_INT_RACK; -// priv->waiting_command_mask |= ARLAN_COMMAND_INT_ENABLE; - priv->waiting_command_mask |= ARLAN_COMMAND_CONF_WAIT; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_CONF_WAIT) - { - if (READSHMB(arlan->configuredStatusFlag) != 0 && - READSHMB(arlan->diagnosticInfo) == 0xff) - { - priv->waiting_command_mask &= ~ARLAN_COMMAND_CONF_WAIT; - priv->waiting_command_mask |= ARLAN_COMMAND_RX; - priv->waiting_command_mask |= ARLAN_COMMAND_TBUSY_CLEAR; - priv->card_polling_interval = HZ / 10; - priv->tx_command_given = 0; - priv->under_config = 0; - } - else - { - priv->card_polling_interval = 1; - if (arlan_debug & ARLAN_DEBUG_TIMING) - printk(KERN_ERR "configure delayed \n"); - } - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_RX) - { - if (!registrationBad(dev)) - { - setInterruptEnable(dev); - memset_io(arlan->commandParameter, 0, 0xf); - WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_RX_ENABLE); - WRITESHMB(arlan->commandParameter[0], conf->rxParameter); - arlan_interrupt_lancpu(dev); - priv->rx_command_given = 0; // mnjah, bad - priv->waiting_command_mask &= ~ARLAN_COMMAND_RX; - priv->card_polling_interval = 1; - } - else - priv->card_polling_interval = 2; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_TBUSY_CLEAR) - { - if ( !registrationBad(dev) && - (netif_queue_stopped(dev) || !netif_running(dev)) ) - { - priv->waiting_command_mask &= ~ARLAN_COMMAND_TBUSY_CLEAR; - netif_wake_queue (dev); - } - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_TX) - { - if (!test_and_set_bit(0, (void *) &priv->tx_command_given)) - { - if (time_after(jiffies, - priv->tx_last_sent + us2ticks(conf->rx_tweak1)) - || time_before(jiffies, - priv->last_rx_int_ack_time + us2ticks(conf->rx_tweak2))) - { - setInterruptEnable(dev); - memset_io(arlan->commandParameter, 0, 0xf); - WRITESHMB(arlan->commandByte, ARLAN_COM_TX_ENABLE | ARLAN_COM_INT); - memcpy_toio(arlan->commandParameter, &TXLAST(dev), 14); -// for ( i=1 ; i < 15 ; i++) printk("%02x:",READSHMB(arlan->commandParameter[i])); - priv->tx_last_sent = jiffies; - arlan_interrupt_lancpu(dev); - priv->tx_command_given = 1; - priv->waiting_command_mask &= ~ARLAN_COMMAND_TX; - priv->card_polling_interval = 1; - } - else - { - priv->tx_command_given = 0; - priv->card_polling_interval = 1; - } - } - else if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) - printk(KERN_ERR "tx command when tx chain locked \n"); - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOPINT) - { - { - WRITESHMB(arlan->commandByte, ARLAN_COM_NOP | ARLAN_COM_INT); - } - arlan_interrupt_lancpu(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOPINT; - priv->card_polling_interval = HZ / 3; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_NOOP) - { - WRITESHMB(arlan->commandByte, ARLAN_COM_NOP); - arlan_interrupt_lancpu(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_NOOP; - priv->card_polling_interval = HZ / 3; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_SLOW_POLL) - { - WRITESHMB(arlan->commandByte, ARLAN_COM_GOTO_SLOW_POLL); - arlan_interrupt_lancpu(dev); - priv->waiting_command_mask &= ~ARLAN_COMMAND_SLOW_POLL; - priv->card_polling_interval = HZ / 3; - } - else if (priv->waiting_command_mask & ARLAN_COMMAND_POWERDOWN) - { - setPowerOff(dev); - if (arlan_debug & ARLAN_DEBUG_CARD_STATE) - printk(KERN_WARNING "%s: Arlan Going Standby\n", dev->name); - priv->waiting_command_mask &= ~ARLAN_COMMAND_POWERDOWN; - priv->card_polling_interval = 3 * HZ; - } - arlan_unlock_card_access(dev); - for (i = 0; READSHMB(arlan->commandByte) && i < 20; i++) - udelay(10); - if (READSHMB(arlan->commandByte)) - if (arlan_debug & ARLAN_DEBUG_CARD_STATE) - printk(KERN_ERR "card busy leaving command %lx\n", priv->waiting_command_mask); - - spin_unlock_irqrestore(&priv->lock, flags); - ARLAN_DEBUG_EXIT("arlan_command"); - priv->last_command_buff_free_time = jiffies; - return 0; - -card_busy_end: - if (time_after(jiffies, priv->last_command_buff_free_time + HZ)) - priv->waiting_command_mask |= ARLAN_COMMAND_CLEAN_AND_RESET; - - if (arlan_debug & ARLAN_DEBUG_CARD_STATE) - printk(KERN_ERR "%s arlan_command card busy end \n", dev->name); - spin_unlock_irqrestore(&priv->lock, flags); - ARLAN_DEBUG_EXIT("arlan_command"); - return 1; - -bad_end: - printk(KERN_ERR "%s arlan_command bad end \n", dev->name); - - spin_unlock_irqrestore(&priv->lock, flags); - ARLAN_DEBUG_EXIT("arlan_command"); - - return -1; -} - -static inline void arlan_command_process(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - int times = 0; - while (priv->waiting_command_mask && times < 8) - { - if (priv->waiting_command_mask) - { - if (arlan_command(dev, 0)) - break; - times++; - } - /* if long command, we won't repeat trying */ ; - if (priv->card_polling_interval > 1) - break; - times++; - } -} - - -static inline void arlan_retransmit_now(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - - ARLAN_DEBUG_ENTRY("arlan_retransmit_now"); - if (TXLAST(dev).offset == 0) - { - if (TXHEAD(dev).offset) - { - priv->txLast = 0; - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to head \n"); - - } - else if (TXTAIL(dev).offset) - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_DEBUG "TX buff switch to tail \n"); - priv->txLast = 1; - } - else - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "ReTransmit buff empty"); - netif_wake_queue (dev); - return; - - } - arlan_command(dev, ARLAN_COMMAND_TX); - - priv->Conf->driverRetransmissions++; - priv->retransmissions++; - - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("Retransmit %d bytes \n", TXLAST(dev).length); - - ARLAN_DEBUG_EXIT("arlan_retransmit_now"); -} - - - -static void arlan_registration_timer(unsigned long data) -{ - struct net_device *dev = (struct net_device *) data; - struct arlan_private *priv = netdev_priv(dev); - int bh_mark_needed = 0; - int next_tick = 1; - long lostTime = ((long)jiffies - (long)priv->registrationLastSeen) - * (1000/HZ); - - if (registrationBad(dev)) - { - priv->registrationLostCount++; - if (lostTime > 7000 && lostTime < 7200) - { - printk(KERN_NOTICE "%s registration Lost \n", dev->name); - } - if (lostTime / priv->reRegisterExp > 2000) - arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF); - if (lostTime / (priv->reRegisterExp) > 3500) - arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); - if (priv->reRegisterExp < 400) - priv->reRegisterExp += 2; - if (lostTime > 7200) - { - next_tick = HZ; - arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); - } - } - else - { - if (priv->Conf->registrationMode && lostTime > 10000 && - priv->registrationLostCount) - { - printk(KERN_NOTICE "%s registration is back after %ld milliseconds\n", - dev->name, lostTime); - } - priv->registrationLastSeen = jiffies; - priv->registrationLostCount = 0; - priv->reRegisterExp = 1; - if (!netif_running(dev) ) - netif_wake_queue(dev); - if (time_after(priv->tx_last_sent,priv->tx_last_cleared) && - time_after(jiffies, priv->tx_last_sent * 5*HZ) ){ - arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); - priv->tx_last_cleared = jiffies; - } - } - - - if (!registrationBad(dev) && priv->ReTransmitRequested) - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk(KERN_ERR "Retransmit from timer \n"); - priv->ReTransmitRequested = 0; - arlan_retransmit_now(dev); - } - if (!registrationBad(dev) && - time_after(jiffies, priv->tx_done_delayed) && - priv->tx_done_delayed != 0) - { - TXLAST(dev).offset = 0; - if (priv->txLast) - priv->txLast = 0; - else if (TXTAIL(dev).offset) - priv->txLast = 1; - if (TXLAST(dev).offset) - { - arlan_retransmit_now(dev); - dev->trans_start = jiffies; - } - if (!(TXHEAD(dev).offset && TXTAIL(dev).offset)) - { - netif_wake_queue (dev); - } - priv->tx_done_delayed = 0; - bh_mark_needed = 1; - } - if (bh_mark_needed) - { - netif_wake_queue (dev); - } - arlan_process_interrupt(dev); - - if (next_tick < priv->card_polling_interval) - next_tick = priv->card_polling_interval; - - priv->timer.expires = jiffies + next_tick; - - add_timer(&priv->timer); -} - - -#ifdef ARLAN_DEBUGGING - -static void arlan_print_registers(struct net_device *dev, int line) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem *arlan = priv->card; - - u_char hostcpuLock, lancpuLock, controlRegister, cntrlRegImage, - txStatus, rxStatus, interruptInProgress, commandByte; - - - ARLAN_DEBUG_ENTRY("arlan_print_registers"); - READSHM(interruptInProgress, arlan->interruptInProgress, u_char); - READSHM(hostcpuLock, arlan->hostcpuLock, u_char); - READSHM(lancpuLock, arlan->lancpuLock, u_char); - READSHM(controlRegister, arlan->controlRegister, u_char); - READSHM(cntrlRegImage, arlan->cntrlRegImage, u_char); - READSHM(txStatus, arlan->txStatus, u_char); - READSHM(rxStatus, arlan->rxStatus, u_char); - READSHM(commandByte, arlan->commandByte, u_char); - - printk(KERN_WARNING "line %04d IP %02x HL %02x LL %02x CB %02x CR %02x CRI %02x TX %02x RX %02x\n", - line, interruptInProgress, hostcpuLock, lancpuLock, commandByte, - controlRegister, cntrlRegImage, txStatus, rxStatus); - - ARLAN_DEBUG_EXIT("arlan_print_registers"); -} -#endif - - -static int arlan_hw_tx(struct net_device *dev, char *buf, int length) -{ - int i; - - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - struct arlan_conf_stru *conf = priv->Conf; - - int tailStarts = 0x800; - int headEnds = 0x0; - - - ARLAN_DEBUG_ENTRY("arlan_hw_tx"); - if (TXHEAD(dev).offset) - headEnds = (((TXHEAD(dev).offset + TXHEAD(dev).length - offsetof(struct arlan_shmem, txBuffer)) / 64) + 1) * 64; - if (TXTAIL(dev).offset) - tailStarts = 0x800 - (((TXTAIL(dev).offset - offsetof(struct arlan_shmem, txBuffer)) / 64) + 2) * 64; - - - if (!TXHEAD(dev).offset && length < tailStarts) - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk(KERN_ERR "TXHEAD insert, tailStart %d\n", tailStarts); - - TXHEAD(dev).offset = - offsetof(struct arlan_shmem, txBuffer); - TXHEAD(dev).length = length - ARLAN_FAKE_HDR_LEN; - for (i = 0; i < 6; i++) - TXHEAD(dev).dest[i] = buf[i]; - TXHEAD(dev).clear = conf->txClear; - TXHEAD(dev).retries = conf->txRetries; /* 0 is use default */ - TXHEAD(dev).routing = conf->txRouting; - TXHEAD(dev).scrambled = conf->txScrambled; - memcpy_toio((char __iomem *)arlan + TXHEAD(dev).offset, buf + ARLAN_FAKE_HDR_LEN, TXHEAD(dev).length); - } - else if (!TXTAIL(dev).offset && length < (0x800 - headEnds)) - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk(KERN_ERR "TXTAIL insert, headEnd %d\n", headEnds); - - TXTAIL(dev).offset = - offsetof(struct arlan_shmem, txBuffer) + 0x800 - (length / 64 + 2) * 64; - TXTAIL(dev).length = length - ARLAN_FAKE_HDR_LEN; - for (i = 0; i < 6; i++) - TXTAIL(dev).dest[i] = buf[i]; - TXTAIL(dev).clear = conf->txClear; - TXTAIL(dev).retries = conf->txRetries; - TXTAIL(dev).routing = conf->txRouting; - TXTAIL(dev).scrambled = conf->txScrambled; - memcpy_toio(((char __iomem *)arlan + TXTAIL(dev).offset), buf + ARLAN_FAKE_HDR_LEN, TXTAIL(dev).length); - } - else - { - netif_stop_queue (dev); - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk(KERN_ERR "TX TAIL & HEAD full, return, tailStart %d headEnd %d\n", tailStarts, headEnds); - return -1; - } - priv->out_bytes += length; - priv->out_bytes10 += length; - if (conf->measure_rate < 1) - conf->measure_rate = 1; - if (time_after(jiffies, priv->out_time + conf->measure_rate * HZ)) - { - conf->out_speed = priv->out_bytes / conf->measure_rate; - priv->out_bytes = 0; - priv->out_time = jiffies; - } - if (time_after(jiffies, priv->out_time10 + conf->measure_rate * 10*HZ)) - { - conf->out_speed10 = priv->out_bytes10 / (10 * conf->measure_rate); - priv->out_bytes10 = 0; - priv->out_time10 = jiffies; - } - if (TXHEAD(dev).offset && TXTAIL(dev).offset) - { - netif_stop_queue (dev); - return 0; - } - else - netif_start_queue (dev); - - - IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) - printk(KERN_WARNING "%s Transmit t %2x:%2x:%2x:%2x:%2x:%2x f %2x:%2x:%2x:%2x:%2x:%2x \n", dev->name, - (unsigned char) buf[0], (unsigned char) buf[1], (unsigned char) buf[2], (unsigned char) buf[3], - (unsigned char) buf[4], (unsigned char) buf[5], (unsigned char) buf[6], (unsigned char) buf[7], - (unsigned char) buf[8], (unsigned char) buf[9], (unsigned char) buf[10], (unsigned char) buf[11]); - - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk(KERN_ERR "TX command prepare for buffer %d\n", priv->txLast); - - arlan_command(dev, ARLAN_COMMAND_TX); - - priv->tx_last_sent = jiffies; - - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) printk("%s TX Qued %d bytes \n", dev->name, length); - - ARLAN_DEBUG_EXIT("arlan_hw_tx"); - - return 0; -} - - -static int arlan_hw_config(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - struct arlan_conf_stru *conf = priv->Conf; - - ARLAN_DEBUG_ENTRY("arlan_hw_config"); - - printk(KERN_NOTICE "%s arlan configure called \n", dev->name); - if (arlan_EEPROM_bad) - printk(KERN_NOTICE "arlan configure with eeprom bad option \n"); - - - WRITESHM(arlan->spreadingCode, conf->spreadingCode, u_char); - WRITESHM(arlan->channelSet, conf->channelSet, u_char); - - if (arlan_EEPROM_bad) - WRITESHM(arlan->defaultChannelSet, conf->channelSet, u_char); - - WRITESHM(arlan->channelNumber, conf->channelNumber, u_char); - - WRITESHM(arlan->scramblingDisable, conf->scramblingDisable, u_char); - WRITESHM(arlan->txAttenuation, conf->txAttenuation, u_char); - - WRITESHM(arlan->systemId, conf->systemId, u_int); - - WRITESHM(arlan->maxRetries, conf->maxRetries, u_char); - WRITESHM(arlan->receiveMode, conf->receiveMode, u_char); - WRITESHM(arlan->priority, conf->priority, u_char); - WRITESHM(arlan->rootOrRepeater, conf->rootOrRepeater, u_char); - WRITESHM(arlan->SID, conf->SID, u_int); - - WRITESHM(arlan->registrationMode, conf->registrationMode, u_char); - - WRITESHM(arlan->registrationFill, conf->registrationFill, u_char); - WRITESHM(arlan->localTalkAddress, conf->localTalkAddress, u_char); - WRITESHM(arlan->codeFormat, conf->codeFormat, u_char); - WRITESHM(arlan->numChannels, conf->numChannels, u_char); - WRITESHM(arlan->channel1, conf->channel1, u_char); - WRITESHM(arlan->channel2, conf->channel2, u_char); - WRITESHM(arlan->channel3, conf->channel3, u_char); - WRITESHM(arlan->channel4, conf->channel4, u_char); - WRITESHM(arlan->radioNodeId, conf->radioNodeId, u_short); - WRITESHM(arlan->SID, conf->SID, u_int); - WRITESHM(arlan->waitTime, conf->waitTime, u_short); - WRITESHM(arlan->lParameter, conf->lParameter, u_short); - memcpy_toio(&(arlan->_15), &(conf->_15), 3); - WRITESHM(arlan->_15, conf->_15, u_short); - WRITESHM(arlan->headerSize, conf->headerSize, u_short); - if (arlan_EEPROM_bad) - WRITESHM(arlan->hardwareType, conf->hardwareType, u_char); - WRITESHM(arlan->radioType, conf->radioType, u_char); - if (arlan_EEPROM_bad) - WRITESHM(arlan->radioModule, conf->radioType, u_char); - - memcpy_toio(arlan->encryptionKey + keyStart, encryptionKey, 8); - memcpy_toio(arlan->name, conf->siteName, 16); - - WRITESHMB(arlan->commandByte, ARLAN_COM_INT | ARLAN_COM_CONF); /* do configure */ - memset_io(arlan->commandParameter, 0, 0xf); /* 0xf */ - memset_io(arlan->commandParameter + 1, 0, 2); - if (conf->writeEEPROM) - { - memset_io(arlan->commandParameter, conf->writeEEPROM, 1); -// conf->writeEEPROM=0; - } - if (conf->registrationMode && conf->registrationInterrupts) - memset_io(arlan->commandParameter + 3, 1, 1); - else - memset_io(arlan->commandParameter + 3, 0, 1); - - priv->irq_test_done = 0; - - if (conf->tx_queue_len) - dev->tx_queue_len = conf->tx_queue_len; - udelay(100); - - ARLAN_DEBUG_EXIT("arlan_hw_config"); - return 0; -} - - -static int arlan_read_card_configuration(struct net_device *dev) -{ - u_char tlx415; - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - struct arlan_conf_stru *conf = priv->Conf; - - ARLAN_DEBUG_ENTRY("arlan_read_card_configuration"); - - if (radioNodeId == radioNodeIdUNKNOWN) - { - READSHM(conf->radioNodeId, arlan->radioNodeId, u_short); - } - else - conf->radioNodeId = radioNodeId; - - if (SID == SIDUNKNOWN) - { - READSHM(conf->SID, arlan->SID, u_int); - } - else conf->SID = SID; - - if (spreadingCode == spreadingCodeUNKNOWN) - { - READSHM(conf->spreadingCode, arlan->spreadingCode, u_char); - } - else - conf->spreadingCode = spreadingCode; - - if (channelSet == channelSetUNKNOWN) - { - READSHM(conf->channelSet, arlan->channelSet, u_char); - } - else conf->channelSet = channelSet; - - if (channelNumber == channelNumberUNKNOWN) - { - READSHM(conf->channelNumber, arlan->channelNumber, u_char); - } - else conf->channelNumber = channelNumber; - - READSHM(conf->scramblingDisable, arlan->scramblingDisable, u_char); - READSHM(conf->txAttenuation, arlan->txAttenuation, u_char); - - if (systemId == systemIdUNKNOWN) - { - READSHM(conf->systemId, arlan->systemId, u_int); - } - else conf->systemId = systemId; - - READSHM(conf->maxDatagramSize, arlan->maxDatagramSize, u_short); - READSHM(conf->maxFrameSize, arlan->maxFrameSize, u_short); - READSHM(conf->maxRetries, arlan->maxRetries, u_char); - READSHM(conf->receiveMode, arlan->receiveMode, u_char); - READSHM(conf->priority, arlan->priority, u_char); - READSHM(conf->rootOrRepeater, arlan->rootOrRepeater, u_char); - - if (SID == SIDUNKNOWN) - { - READSHM(conf->SID, arlan->SID, u_int); - } - else conf->SID = SID; - - if (registrationMode == registrationModeUNKNOWN) - { - READSHM(conf->registrationMode, arlan->registrationMode, u_char); - } - else conf->registrationMode = registrationMode; - - READSHM(conf->registrationFill, arlan->registrationFill, u_char); - READSHM(conf->localTalkAddress, arlan->localTalkAddress, u_char); - READSHM(conf->codeFormat, arlan->codeFormat, u_char); - READSHM(conf->numChannels, arlan->numChannels, u_char); - READSHM(conf->channel1, arlan->channel1, u_char); - READSHM(conf->channel2, arlan->channel2, u_char); - READSHM(conf->channel3, arlan->channel3, u_char); - READSHM(conf->channel4, arlan->channel4, u_char); - READSHM(conf->waitTime, arlan->waitTime, u_short); - READSHM(conf->lParameter, arlan->lParameter, u_short); - READSHM(conf->_15, arlan->_15, u_short); - READSHM(conf->headerSize, arlan->headerSize, u_short); - READSHM(conf->hardwareType, arlan->hardwareType, u_char); - READSHM(conf->radioType, arlan->radioModule, u_char); - - if (conf->radioType == 0) - conf->radioType = 0xc; - - WRITESHM(arlan->configStatus, 0xA5, u_char); - READSHM(tlx415, arlan->configStatus, u_char); - - if (tlx415 != 0xA5) - printk(KERN_INFO "%s tlx415 chip \n", dev->name); - - conf->txClear = 0; - conf->txRetries = 1; - conf->txRouting = 1; - conf->txScrambled = 0; - conf->rxParameter = 1; - conf->txTimeoutMs = 4000; - conf->waitCardTimeout = 100000; - conf->receiveMode = ARLAN_RCV_CLEAN; - memcpy_fromio(conf->siteName, arlan->name, 16); - conf->siteName[16] = '\0'; - conf->retries = retries; - conf->tx_delay_ms = tx_delay_ms; - conf->ReTransmitPacketMaxSize = 200; - conf->waitReTransmitPacketMaxSize = 200; - conf->txAckTimeoutMs = 900; - conf->fastReTransCount = 3; - - ARLAN_DEBUG_EXIT("arlan_read_card_configuration"); - - return 0; -} - - -static int lastFoundAt = 0xbe000; - - -/* - * This is the real probe routine. Linux has a history of friendly device - * probes on the ISA bus. A good device probes avoids doing writes, and - * verifies that the correct device exists and functions. - */ -#define ARLAN_SHMEM_SIZE 0x2000 -static int __init arlan_check_fingerprint(unsigned long memaddr) -{ - static const char probeText[] = "TELESYSTEM SLW INC. ARLAN \0"; - volatile struct arlan_shmem __iomem *arlan = (struct arlan_shmem *) memaddr; - unsigned long paddr = virt_to_phys((void *) memaddr); - char tempBuf[49]; - - ARLAN_DEBUG_ENTRY("arlan_check_fingerprint"); - - if (!request_mem_region(paddr, ARLAN_SHMEM_SIZE, "arlan")) { - // printk(KERN_WARNING "arlan: memory region %lx excluded from probing \n",paddr); - return -ENODEV; - } - - memcpy_fromio(tempBuf, arlan->textRegion, 29); - tempBuf[30] = 0; - - /* check for card at this address */ - if (0 != strncmp(tempBuf, probeText, 29)){ - release_mem_region(paddr, ARLAN_SHMEM_SIZE); - return -ENODEV; - } - -// printk(KERN_INFO "arlan found at 0x%x \n",memaddr); - ARLAN_DEBUG_EXIT("arlan_check_fingerprint"); - - return 0; -} - -static int arlan_change_mtu(struct net_device *dev, int new_mtu) -{ - struct arlan_private *priv = netdev_priv(dev); - struct arlan_conf_stru *conf = priv->Conf; - - ARLAN_DEBUG_ENTRY("arlan_change_mtu"); - if (new_mtu > 2032) - return -EINVAL; - dev->mtu = new_mtu; - if (new_mtu < 256) - new_mtu = 256; /* cards book suggests 1600 */ - conf->maxDatagramSize = new_mtu; - conf->maxFrameSize = new_mtu + 48; - - arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_CONF); - printk(KERN_NOTICE "%s mtu changed to %d \n", dev->name, new_mtu); - - ARLAN_DEBUG_EXIT("arlan_change_mtu"); - - return 0; -} - -static int arlan_mac_addr(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - - ARLAN_DEBUG_ENTRY("arlan_mac_addr"); - return -EINVAL; - - if (netif_running(dev)) - return -EBUSY; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - ARLAN_DEBUG_EXIT("arlan_mac_addr"); - return 0; -} - -static const struct net_device_ops arlan_netdev_ops = { - .ndo_open = arlan_open, - .ndo_stop = arlan_close, - .ndo_start_xmit = arlan_tx, - .ndo_get_stats = arlan_statistics, - .ndo_set_multicast_list = arlan_set_multicast, - .ndo_change_mtu = arlan_change_mtu, - .ndo_set_mac_address = arlan_mac_addr, - .ndo_tx_timeout = arlan_tx_timeout, - .ndo_validate_addr = eth_validate_addr, -}; - -static int __init arlan_setup_device(struct net_device *dev, int num) -{ - struct arlan_private *ap = netdev_priv(dev); - int err; - - ARLAN_DEBUG_ENTRY("arlan_setup_device"); - - ap->conf = (struct arlan_shmem *)(ap+1); - - dev->tx_queue_len = tx_queue_len; - dev->netdev_ops = &arlan_netdev_ops; - dev->watchdog_timeo = 3*HZ; - - ap->irq_test_done = 0; - ap->Conf = &arlan_conf[num]; - - ap->Conf->pre_Command_Wait = 40; - ap->Conf->rx_tweak1 = 30; - ap->Conf->rx_tweak2 = 0; - - - err = register_netdev(dev); - if (err) { - release_mem_region(virt_to_phys((void *) dev->mem_start), - ARLAN_SHMEM_SIZE); - free_netdev(dev); - return err; - } - arlan_device[num] = dev; - ARLAN_DEBUG_EXIT("arlan_setup_device"); - return 0; -} - -static int __init arlan_probe_here(struct net_device *dev, - unsigned long memaddr) -{ - struct arlan_private *ap = netdev_priv(dev); - - ARLAN_DEBUG_ENTRY("arlan_probe_here"); - - if (arlan_check_fingerprint(memaddr)) - return -ENODEV; - - printk(KERN_NOTICE "%s: Arlan found at %llx, \n ", dev->name, - (u64) virt_to_phys((void*)memaddr)); - - ap->card = (void *) memaddr; - dev->mem_start = memaddr; - dev->mem_end = memaddr + ARLAN_SHMEM_SIZE-1; - - if (dev->irq < 2) - { - READSHM(dev->irq, ap->card->irqLevel, u_char); - } else if (dev->irq == 2) - dev->irq = 9; - - arlan_read_card_configuration(dev); - - ARLAN_DEBUG_EXIT("arlan_probe_here"); - return 0; -} - - -static int arlan_open(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - int ret = 0; - - ARLAN_DEBUG_ENTRY("arlan_open"); - - ret = request_irq(dev->irq, &arlan_interrupt, 0, dev->name, dev); - if (ret) - { - printk(KERN_ERR "%s: unable to get IRQ %d .\n", - dev->name, dev->irq); - return ret; - } - - - priv->bad = 0; - priv->lastReset = 0; - priv->reset = 0; - memcpy_fromio(dev->dev_addr, arlan->lanCardNodeId, 6); - memset(dev->broadcast, 0xff, 6); - dev->tx_queue_len = tx_queue_len; - priv->interrupt_processing_active = 0; - spin_lock_init(&priv->lock); - - netif_start_queue (dev); - - priv->registrationLostCount = 0; - priv->registrationLastSeen = jiffies; - priv->txLast = 0; - priv->tx_command_given = 0; - priv->rx_command_given = 0; - - priv->reRegisterExp = 1; - priv->tx_last_sent = jiffies - 1; - priv->tx_last_cleared = jiffies; - priv->Conf->writeEEPROM = 0; - priv->Conf->registrationInterrupts = 1; - - init_timer(&priv->timer); - priv->timer.expires = jiffies + HZ / 10; - priv->timer.data = (unsigned long) dev; - priv->timer.function = &arlan_registration_timer; /* timer handler */ - - arlan_command(dev, ARLAN_COMMAND_POWERUP | ARLAN_COMMAND_LONG_WAIT_NOW); - mdelay(200); - add_timer(&priv->timer); - - ARLAN_DEBUG_EXIT("arlan_open"); - return 0; -} - - -static void arlan_tx_timeout (struct net_device *dev) -{ - printk(KERN_ERR "%s: arlan transmit timed out, kernel decided\n", dev->name); - /* Try to restart the adaptor. */ - arlan_command(dev, ARLAN_COMMAND_CLEAN_AND_RESET); - // dev->trans_start = jiffies; - // netif_start_queue (dev); -} - - -static netdev_tx_t arlan_tx(struct sk_buff *skb, struct net_device *dev) -{ - short length; - unsigned char *buf; - - ARLAN_DEBUG_ENTRY("arlan_tx"); - - length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - buf = skb->data; - - if (length + 0x12 > 0x800) { - printk(KERN_ERR "TX RING overflow \n"); - netif_stop_queue (dev); - } - - if (arlan_hw_tx(dev, buf, length) == -1) - goto bad_end; - - dev->trans_start = jiffies; - - dev_kfree_skb(skb); - - arlan_process_interrupt(dev); - ARLAN_DEBUG_EXIT("arlan_tx"); - return NETDEV_TX_OK; - -bad_end: - arlan_process_interrupt(dev); - netif_stop_queue (dev); - ARLAN_DEBUG_EXIT("arlan_tx"); - return NETDEV_TX_BUSY; -} - - -static inline int DoNotReTransmitCrap(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - if (TXLAST(dev).length < priv->Conf->ReTransmitPacketMaxSize) - return 1; - return 0; - -} - -static inline int DoNotWaitReTransmitCrap(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - if (TXLAST(dev).length < priv->Conf->waitReTransmitPacketMaxSize) - return 1; - return 0; -} - -static inline void arlan_queue_retransmit(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - ARLAN_DEBUG_ENTRY("arlan_queue_retransmit"); - - if (DoNotWaitReTransmitCrap(dev)) - { - arlan_drop_tx(dev); - } else - priv->ReTransmitRequested++; - - ARLAN_DEBUG_EXIT("arlan_queue_retransmit"); -} - -static inline void RetryOrFail(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - ARLAN_DEBUG_ENTRY("RetryOrFail"); - - if (priv->retransmissions > priv->Conf->retries || - DoNotReTransmitCrap(dev)) - { - arlan_drop_tx(dev); - } - else if (priv->bad <= priv->Conf->fastReTransCount) - { - arlan_retransmit_now(dev); - } - else arlan_queue_retransmit(dev); - - ARLAN_DEBUG_EXIT("RetryOrFail"); -} - - -static void arlan_tx_done_interrupt(struct net_device *dev, int status) -{ - struct arlan_private *priv = netdev_priv(dev); - - ARLAN_DEBUG_ENTRY("arlan_tx_done_interrupt"); - - priv->tx_last_cleared = jiffies; - priv->tx_command_given = 0; - switch (status) - { - case 1: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit OK\n"); - dev->stats.tx_packets++; - priv->bad = 0; - priv->reset = 0; - priv->retransmissions = 0; - if (priv->Conf->tx_delay_ms) - { - priv->tx_done_delayed = jiffies + (priv->Conf->tx_delay_ms * HZ) / 1000 + 1; - } - else - { - TXLAST(dev).offset = 0; - if (priv->txLast) - priv->txLast = 0; - else if (TXTAIL(dev).offset) - priv->txLast = 1; - if (TXLAST(dev).offset) - { - arlan_retransmit_now(dev); - dev->trans_start = jiffies; - } - if (!TXHEAD(dev).offset || !TXTAIL(dev).offset) - { - netif_wake_queue (dev); - } - } - } - break; - - case 2: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit timed out\n"); - priv->bad += 1; - //arlan_queue_retransmit(dev); - RetryOrFail(dev); - } - break; - - case 3: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit max retries\n"); - priv->bad += 1; - priv->reset = 0; - //arlan_queue_retransmit(dev); - RetryOrFail(dev); - } - break; - - case 4: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit aborted\n"); - priv->bad += 1; - arlan_queue_retransmit(dev); - //RetryOrFail(dev); - } - break; - - case 5: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit not registered\n"); - priv->bad += 1; - //debug=101; - arlan_queue_retransmit(dev); - } - break; - - case 6: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit destination full\n"); - priv->bad += 1; - priv->reset = 0; - //arlan_drop_tx(dev); - arlan_queue_retransmit(dev); - } - break; - - case 7: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit unknown ack\n"); - priv->bad += 1; - priv->reset = 0; - arlan_queue_retransmit(dev); - } - break; - - case 8: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit dest mail box full\n"); - priv->bad += 1; - priv->reset = 0; - //arlan_drop_tx(dev); - arlan_queue_retransmit(dev); - } - break; - - case 9: - { - IFDEBUG(ARLAN_DEBUG_TX_CHAIN) - printk("arlan intr: transmit root dest not reg.\n"); - priv->bad += 1; - priv->reset = 1; - //arlan_drop_tx(dev); - arlan_queue_retransmit(dev); - } - break; - - default: - { - printk(KERN_ERR "arlan intr: transmit status unknown\n"); - priv->bad += 1; - priv->reset = 1; - arlan_drop_tx(dev); - } - } - - ARLAN_DEBUG_EXIT("arlan_tx_done_interrupt"); -} - - -static void arlan_rx_interrupt(struct net_device *dev, u_char rxStatus, u_short rxOffset, u_short pkt_len) -{ - char *skbtmp; - int i = 0; - - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - struct arlan_conf_stru *conf = priv->Conf; - - - ARLAN_DEBUG_ENTRY("arlan_rx_interrupt"); - // by spec, not WRITESHMB(arlan->rxStatus,0x00); - // prohibited here arlan_command(dev, ARLAN_COMMAND_RX); - - if (pkt_len < 10 || pkt_len > 2048) - { - printk(KERN_WARNING "%s: got too short or long packet, len %d \n", dev->name, pkt_len); - return; - } - if (rxOffset + pkt_len > 0x2000) - { - printk("%s: got too long packet, len %d offset %x\n", dev->name, pkt_len, rxOffset); - return; - } - priv->in_bytes += pkt_len; - priv->in_bytes10 += pkt_len; - if (conf->measure_rate < 1) - conf->measure_rate = 1; - if (time_after(jiffies, priv->in_time + conf->measure_rate * HZ)) - { - conf->in_speed = priv->in_bytes / conf->measure_rate; - priv->in_bytes = 0; - priv->in_time = jiffies; - } - if (time_after(jiffies, priv->in_time10 + conf->measure_rate * 10*HZ)) - { - conf->in_speed10 = priv->in_bytes10 / (10 * conf->measure_rate); - priv->in_bytes10 = 0; - priv->in_time10 = jiffies; - } - DEBUGSHM(1, "arlan rcv pkt rxStatus= %d ", arlan->rxStatus, u_char); - switch (rxStatus) - { - case 1: - case 2: - case 3: - { - /* Malloc up new buffer. */ - struct sk_buff *skb; - - DEBUGSHM(50, "arlan recv pkt offs=%d\n", arlan->rxOffset, u_short); - DEBUGSHM(1, "arlan rxFrmType = %d \n", arlan->rxFrmType, u_char); - DEBUGSHM(1, KERN_INFO "arlan rx scrambled = %d \n", arlan->scrambled, u_char); - - /* here we do multicast filtering to avoid slow 8-bit memcopy */ -#ifdef ARLAN_MULTICAST - if (!(dev->flags & IFF_ALLMULTI) && - !(dev->flags & IFF_PROMISC) && - dev->mc_list) - { - char hw_dst_addr[6]; - struct dev_mc_list *dmi = dev->mc_list; - int i; - - memcpy_fromio(hw_dst_addr, arlan->ultimateDestAddress, 6); - if (hw_dst_addr[0] == 0x01) - { - if (mdebug) - if (hw_dst_addr[1] == 0x00) - printk(KERN_ERR "%s mcast 0x0100 \n", dev->name); - else if (hw_dst_addr[1] == 0x40) - printk(KERN_ERR "%s m/bcast 0x0140 \n", dev->name); - while (dmi) - { - if (dmi->dmi_addrlen == 6) { - if (arlan_debug & ARLAN_DEBUG_HEADER_DUMP) - printk(KERN_ERR "%s mcl %pM\n", - dev->name, dmi->dmi_addr); - for (i = 0; i < 6; i++) - if (dmi->dmi_addr[i] != hw_dst_addr[i]) - break; - if (i == 6) - break; - } else - printk(KERN_ERR "%s: invalid multicast address length given.\n", dev->name); - dmi = dmi->next; - } - /* we reach here if multicast filtering is on and packet - * is multicast and not for receive */ - goto end_of_interrupt; - } - } -#endif // ARLAN_MULTICAST - /* multicast filtering ends here */ - pkt_len += ARLAN_FAKE_HDR_LEN; - - skb = dev_alloc_skb(pkt_len + 4); - if (skb == NULL) - { - printk(KERN_ERR "%s: Memory squeeze, dropping packet.\n", dev->name); - dev->stats.rx_dropped++; - break; - } - skb_reserve(skb, 2); - skbtmp = skb_put(skb, pkt_len); - - memcpy_fromio(skbtmp + ARLAN_FAKE_HDR_LEN, ((char __iomem *) arlan) + rxOffset, pkt_len - ARLAN_FAKE_HDR_LEN); - memcpy_fromio(skbtmp, arlan->ultimateDestAddress, 6); - memcpy_fromio(skbtmp + 6, arlan->rxSrc, 6); - WRITESHMB(arlan->rxStatus, 0x00); - arlan_command(dev, ARLAN_COMMAND_RX); - - IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) - { - char immedDestAddress[6]; - char immedSrcAddress[6]; - memcpy_fromio(immedDestAddress, arlan->immedDestAddress, 6); - memcpy_fromio(immedSrcAddress, arlan->immedSrcAddress, 6); - - printk(KERN_WARNING "%s t %pM f %pM imd %pM ims %pM\n", - dev->name, skbtmp, - &skbtmp[6], - immedDestAddress, - immedSrcAddress); - } - skb->protocol = eth_type_trans(skb, dev); - IFDEBUG(ARLAN_DEBUG_HEADER_DUMP) - if (skb->protocol != 0x608 && skb->protocol != 0x8) - { - for (i = 0; i <= 22; i++) - printk("%02x:", (u_char) skbtmp[i + 12]); - printk(KERN_ERR "\n"); - printk(KERN_WARNING "arlan kernel pkt type trans %x \n", skb->protocol); - } - netif_rx(skb); - dev->stats.rx_packets++; - dev->stats.rx_bytes += pkt_len; - } - break; - - default: - printk(KERN_ERR "arlan intr: received unknown status\n"); - dev->stats.rx_crc_errors++; - break; - } - ARLAN_DEBUG_EXIT("arlan_rx_interrupt"); -} - -static void arlan_process_interrupt(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - u_char rxStatus = READSHMB(arlan->rxStatus); - u_char txStatus = READSHMB(arlan->txStatus); - u_short rxOffset = READSHMS(arlan->rxOffset); - u_short pkt_len = READSHMS(arlan->rxLength); - int interrupt_count = 0; - - ARLAN_DEBUG_ENTRY("arlan_process_interrupt"); - - if (test_and_set_bit(0, (void *) &priv->interrupt_processing_active)) - { - if (arlan_debug & ARLAN_DEBUG_CHAIN_LOCKS) - printk(KERN_ERR "interrupt chain reentering \n"); - goto end_int_process; - } - while ((rxStatus || txStatus || priv->interrupt_ack_requested) - && (interrupt_count < 5)) - { - if (rxStatus) - priv->last_rx_int_ack_time = jiffies; - - arlan_command(dev, ARLAN_COMMAND_INT_ACK); - arlan_command(dev, ARLAN_COMMAND_INT_ENABLE); - - IFDEBUG(ARLAN_DEBUG_INTERRUPT) - printk(KERN_ERR "%s: got IRQ rx %x tx %x comm %x rxOff %x rxLen %x \n", - dev->name, rxStatus, txStatus, READSHMB(arlan->commandByte), - rxOffset, pkt_len); - - if (rxStatus == 0 && txStatus == 0) - { - if (priv->irq_test_done) - { - if (!registrationBad(dev)) - IFDEBUG(ARLAN_DEBUG_INTERRUPT) printk(KERN_ERR "%s unknown interrupt(nop? regLost ?) reason tx %d rx %d ", - dev->name, txStatus, rxStatus); - } else { - IFDEBUG(ARLAN_DEBUG_INTERRUPT) - printk(KERN_INFO "%s irq $%d test OK \n", dev->name, dev->irq); - - } - priv->interrupt_ack_requested = 0; - goto ends; - } - if (txStatus != 0) - { - WRITESHMB(arlan->txStatus, 0x00); - arlan_tx_done_interrupt(dev, txStatus); - goto ends; - } - if (rxStatus == 1 || rxStatus == 2) - { /* a packet waiting */ - arlan_rx_interrupt(dev, rxStatus, rxOffset, pkt_len); - goto ends; - } - if (rxStatus > 2 && rxStatus < 0xff) - { - WRITESHMB(arlan->rxStatus, 0x00); - printk(KERN_ERR "%s unknown rxStatus reason tx %d rx %d ", - dev->name, txStatus, rxStatus); - goto ends; - } - if (rxStatus == 0xff) - { - WRITESHMB(arlan->rxStatus, 0x00); - arlan_command(dev, ARLAN_COMMAND_RX); - if (registrationBad(dev)) - netif_device_detach(dev); - if (!registrationBad(dev)) - { - priv->registrationLastSeen = jiffies; - if (!netif_queue_stopped(dev) && !priv->under_reset && !priv->under_config) - netif_wake_queue (dev); - } - goto ends; - } -ends: - - arlan_command_process(dev); - - rxStatus = READSHMB(arlan->rxStatus); - txStatus = READSHMB(arlan->txStatus); - rxOffset = READSHMS(arlan->rxOffset); - pkt_len = READSHMS(arlan->rxLength); - - - priv->irq_test_done = 1; - - interrupt_count++; - } - priv->interrupt_processing_active = 0; - -end_int_process: - arlan_command_process(dev); - - ARLAN_DEBUG_EXIT("arlan_process_interrupt"); - return; -} - -static irqreturn_t arlan_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - u_char rxStatus = READSHMB(arlan->rxStatus); - u_char txStatus = READSHMB(arlan->txStatus); - - ARLAN_DEBUG_ENTRY("arlan_interrupt"); - - - if (!rxStatus && !txStatus) - priv->interrupt_ack_requested++; - - arlan_process_interrupt(dev); - - priv->irq_test_done = 1; - - ARLAN_DEBUG_EXIT("arlan_interrupt"); - return IRQ_HANDLED; - -} - - -static int arlan_close(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - - ARLAN_DEBUG_ENTRY("arlan_close"); - - del_timer_sync(&priv->timer); - - arlan_command(dev, ARLAN_COMMAND_POWERDOWN); - - IFDEBUG(ARLAN_DEBUG_STARTUP) - printk(KERN_NOTICE "%s: Closing device\n", dev->name); - - netif_stop_queue(dev); - free_irq(dev->irq, dev); - - ARLAN_DEBUG_EXIT("arlan_close"); - return 0; -} - -#ifdef ARLAN_DEBUGGING -static long alignLong(volatile u_char * ptr) -{ - long ret; - memcpy_fromio(&ret, (void *) ptr, 4); - return ret; -} -#endif - -/* - * Get the current statistics. - * This may be called with the card open or closed. - */ - -static struct net_device_stats *arlan_statistics(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - - - ARLAN_DEBUG_ENTRY("arlan_statistics"); - - /* Update the statistics from the device registers. */ - - READSHM(dev->stats.collisions, arlan->numReTransmissions, u_int); - READSHM(dev->stats.rx_crc_errors, arlan->numCRCErrors, u_int); - READSHM(dev->stats.rx_dropped, arlan->numFramesDiscarded, u_int); - READSHM(dev->stats.rx_fifo_errors, arlan->numRXBufferOverflows, u_int); - READSHM(dev->stats.rx_frame_errors, arlan->numReceiveFramesLost, u_int); - READSHM(dev->stats.rx_over_errors, arlan->numRXOverruns, u_int); - READSHM(dev->stats.rx_packets, arlan->numDatagramsReceived, u_int); - READSHM(dev->stats.tx_aborted_errors, arlan->numAbortErrors, u_int); - READSHM(dev->stats.tx_carrier_errors, arlan->numStatusTimeouts, u_int); - READSHM(dev->stats.tx_dropped, arlan->numDatagramsDiscarded, u_int); - READSHM(dev->stats.tx_fifo_errors, arlan->numTXUnderruns, u_int); - READSHM(dev->stats.tx_packets, arlan->numDatagramsTransmitted, u_int); - READSHM(dev->stats.tx_window_errors, arlan->numHoldOffs, u_int); - - ARLAN_DEBUG_EXIT("arlan_statistics"); - - return &dev->stats; -} - - -static void arlan_set_multicast(struct net_device *dev) -{ - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - struct arlan_conf_stru *conf = priv->Conf; - int board_conf_needed = 0; - - - ARLAN_DEBUG_ENTRY("arlan_set_multicast"); - - if (dev->flags & IFF_PROMISC) - { - unsigned char recMode; - READSHM(recMode, arlan->receiveMode, u_char); - conf->receiveMode = (ARLAN_RCV_PROMISC | ARLAN_RCV_CONTROL); - if (conf->receiveMode != recMode) - board_conf_needed = 1; - } - else - { - /* turn off promiscuous mode */ - unsigned char recMode; - READSHM(recMode, arlan->receiveMode, u_char); - conf->receiveMode = ARLAN_RCV_CLEAN | ARLAN_RCV_CONTROL; - if (conf->receiveMode != recMode) - board_conf_needed = 1; - } - if (board_conf_needed) - arlan_command(dev, ARLAN_COMMAND_CONF); - - ARLAN_DEBUG_EXIT("arlan_set_multicast"); -} - - -struct net_device * __init arlan_probe(int unit) -{ - struct net_device *dev; - int err; - int m; - - ARLAN_DEBUG_ENTRY("arlan_probe"); - - if (arlans_found == MAX_ARLANS) - return ERR_PTR(-ENODEV); - - /* - * Reserve space for local data and a copy of the shared memory - * that is used by the /proc interface. - */ - dev = alloc_etherdev(sizeof(struct arlan_private) - + sizeof(struct arlan_shmem)); - if (!dev) - return ERR_PTR(-ENOMEM); - - if (unit >= 0) { - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - - if (dev->mem_start) { - if (arlan_probe_here(dev, dev->mem_start) == 0) - goto found; - goto not_found; - } - - } - - - for (m = (int)phys_to_virt(lastFoundAt) + ARLAN_SHMEM_SIZE; - m <= (int)phys_to_virt(0xDE000); - m += ARLAN_SHMEM_SIZE) - { - if (arlan_probe_here(dev, m) == 0) - { - lastFoundAt = (int)virt_to_phys((void*)m); - goto found; - } - } - - if (lastFoundAt == 0xbe000) - printk(KERN_ERR "arlan: No Arlan devices found \n"); - - not_found: - free_netdev(dev); - return ERR_PTR(-ENODEV); - - found: - err = arlan_setup_device(dev, arlans_found); - if (err) - dev = ERR_PTR(err); - else if (!arlans_found++) - printk(KERN_INFO "Arlan driver %s\n", arlan_version); - - return dev; -} - -#ifdef MODULE -int __init init_module(void) -{ - int i = 0; - - ARLAN_DEBUG_ENTRY("init_module"); - - if (channelSet != channelSetUNKNOWN || channelNumber != channelNumberUNKNOWN || systemId != systemIdUNKNOWN) - return -EINVAL; - - for (i = 0; i < MAX_ARLANS; i++) { - struct net_device *dev = arlan_probe(i); - - if (IS_ERR(dev)) - return PTR_ERR(dev); - } - init_arlan_proc(); - printk(KERN_INFO "Arlan driver %s\n", arlan_version); - ARLAN_DEBUG_EXIT("init_module"); - return 0; -} - - -void __exit cleanup_module(void) -{ - int i = 0; - struct net_device *dev; - - ARLAN_DEBUG_ENTRY("cleanup_module"); - - IFDEBUG(ARLAN_DEBUG_SHUTDOWN) - printk(KERN_INFO "arlan: unloading module\n"); - - cleanup_arlan_proc(); - - for (i = 0; i < MAX_ARLANS; i++) - { - dev = arlan_device[i]; - if (dev) { - arlan_command(dev, ARLAN_COMMAND_POWERDOWN ); - - unregister_netdev(dev); - release_mem_region(virt_to_phys((void *) dev->mem_start), - ARLAN_SHMEM_SIZE); - free_netdev(dev); - arlan_device[i] = NULL; - } - } - - ARLAN_DEBUG_EXIT("cleanup_module"); -} - - -#endif -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/arlan-proc.c b/drivers/net/wireless/arlan-proc.c deleted file mode 100644 index a8b689635a3b..000000000000 --- a/drivers/net/wireless/arlan-proc.c +++ /dev/null @@ -1,1253 +0,0 @@ -#include "arlan.h" - -#include - -#ifdef CONFIG_PROC_FS - -/* void enableReceive(struct net_device* dev); -*/ - - - -#define ARLAN_STR_SIZE 0x2ff0 -#define DEV_ARLAN_INFO 1 -#define DEV_ARLAN 1 -#define SARLG(type,var) {\ - pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n", #var, READSHMB(priva->card->var)); \ - } - -#define SARLBN(type,var,nn) {\ - pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x",#var);\ - for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\ - pos += sprintf(arlan_drive_info+pos, "\n"); \ - } - -#define SARLBNpln(type,var,nn) {\ - for (i=0; i < nn; i++ ) pos += sprintf(arlan_drive_info+pos, "%02x",READSHMB(priva->card->var[i]));\ - } - -#define SARLSTR(var,nn) {\ - char tmpStr[400];\ - int tmpLn = nn;\ - if (nn > 399 ) tmpLn = 399; \ - memcpy(tmpStr,(char *) priva->conf->var,tmpLn);\ - tmpStr[tmpLn] = 0; \ - pos += sprintf(arlan_drive_info+pos, "%s\t=\t%s \n",#var,priva->conf->var);\ - } - -#define SARLUC(var) SARLG(u_char, var) -#define SARLUCN(var,nn) SARLBN(u_char,var, nn) -#define SARLUS(var) SARLG(u_short, var) -#define SARLUSN(var,nn) SARLBN(u_short,var, nn) -#define SARLUI(var) SARLG(u_int, var) - -#define SARLUSA(var) {\ - u_short tmpVar;\ - memcpy(&tmpVar, (short *) priva->conf->var,2); \ - pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\ -} - -#define SARLUIA(var) {\ - u_int tmpVar;\ - memcpy(&tmpVar, (int* )priva->conf->var,4); \ - pos += sprintf(arlan_drive_info+pos, "%s\t=\t0x%x\n",#var, tmpVar);\ -} - - -static const char *arlan_diagnostic_info_string(struct net_device *dev) -{ - - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - u_char diagnosticInfo; - - READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char); - - switch (diagnosticInfo) - { - case 0xFF: - return "Diagnostic info is OK"; - case 0xFE: - return "ERROR EPROM Checksum error "; - case 0xFD: - return "ERROR Local Ram Test Failed "; - case 0xFC: - return "ERROR SCC failure "; - case 0xFB: - return "ERROR BackBone failure "; - case 0xFA: - return "ERROR transceiver not found "; - case 0xF9: - return "ERROR no more address space "; - case 0xF8: - return "ERROR Checksum error "; - case 0xF7: - return "ERROR Missing SS Code"; - case 0xF6: - return "ERROR Invalid config format"; - case 0xF5: - return "ERROR Reserved errorcode F5"; - case 0xF4: - return "ERROR Invalid spreading code/channel number"; - case 0xF3: - return "ERROR Load Code Error"; - case 0xF2: - return "ERROR Reserver errorcode F2 "; - case 0xF1: - return "ERROR Invalid command receivec by LAN card "; - case 0xF0: - return "ERROR Invalid parameter found in command "; - case 0xEF: - return "ERROR On-chip timer failure "; - case 0xEE: - return "ERROR T410 timer failure "; - case 0xED: - return "ERROR Too Many TxEnable commands "; - case 0xEC: - return "ERROR EEPROM error on radio module "; - default: - return "ERROR unknown Diagnostic info reply code "; - } -} - -static const char *arlan_hardware_type_string(struct net_device *dev) -{ - u_char hardwareType; - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - - READSHM(hardwareType, arlan->hardwareType, u_char); - switch (hardwareType) - { - case 0x00: - return "type A450"; - case 0x01: - return "type A650 "; - case 0x04: - return "type TMA coproc"; - case 0x0D: - return "type A650E "; - case 0x18: - return "type TMA coproc Australian"; - case 0x19: - return "type A650A "; - case 0x26: - return "type TMA coproc European"; - case 0x2E: - return "type A655 "; - case 0x2F: - return "type A655A "; - case 0x30: - return "type A655E "; - case 0x0B: - return "type A670 "; - case 0x0C: - return "type A670E "; - case 0x2D: - return "type A670A "; - case 0x0F: - return "type A411T"; - case 0x16: - return "type A411TA"; - case 0x1B: - return "type A440T"; - case 0x1C: - return "type A412T"; - case 0x1E: - return "type A412TA"; - case 0x22: - return "type A411TE"; - case 0x24: - return "type A412TE"; - case 0x27: - return "type A671T "; - case 0x29: - return "type A671TA "; - case 0x2B: - return "type A671TE "; - case 0x31: - return "type A415T "; - case 0x33: - return "type A415TA "; - case 0x35: - return "type A415TE "; - case 0x37: - return "type A672"; - case 0x39: - return "type A672A "; - case 0x3B: - return "type A672T"; - case 0x6B: - return "type IC2200"; - default: - return "type A672T"; - } -} -#ifdef ARLAN_DEBUGGING -static void arlan_print_diagnostic_info(struct net_device *dev) -{ - int i; - u_char diagnosticInfo; - u_short diagnosticOffset; - u_char hardwareType; - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - - // ARLAN_DEBUG_ENTRY("arlan_print_diagnostic_info"); - - if (READSHMB(arlan->configuredStatusFlag) == 0) - printk("Arlan: Card NOT configured\n"); - else - printk("Arlan: Card is configured\n"); - - READSHM(diagnosticInfo, arlan->diagnosticInfo, u_char); - READSHM(diagnosticOffset, arlan->diagnosticOffset, u_short); - - printk(KERN_INFO "%s\n", arlan_diagnostic_info_string(dev)); - - if (diagnosticInfo != 0xff) - printk("%s arlan: Diagnostic Offset %d \n", dev->name, diagnosticOffset); - - printk("arlan: LAN CODE ID = "); - for (i = 0; i < 6; i++) - DEBUGSHM(1, "%03d:", arlan->lanCardNodeId[i], u_char); - printk("\n"); - - printk("arlan: Arlan BroadCast address = "); - for (i = 0; i < 6; i++) - DEBUGSHM(1, "%03d:", arlan->broadcastAddress[i], u_char); - printk("\n"); - - READSHM(hardwareType, arlan->hardwareType, u_char); - printk(KERN_INFO "%s\n", arlan_hardware_type_string(dev)); - - - DEBUGSHM(1, "arlan: channelNumber=%d\n", arlan->channelNumber, u_char); - DEBUGSHM(1, "arlan: channelSet=%d\n", arlan->channelSet, u_char); - DEBUGSHM(1, "arlan: spreadingCode=%d\n", arlan->spreadingCode, u_char); - DEBUGSHM(1, "arlan: radioNodeId=%d\n", arlan->radioNodeId, u_short); - DEBUGSHM(1, "arlan: SID =%d\n", arlan->SID, u_short); - DEBUGSHM(1, "arlan: rxOffset=%d\n", arlan->rxOffset, u_short); - - DEBUGSHM(1, "arlan: registration mode is %d\n", arlan->registrationMode, u_char); - - printk("arlan: name= "); - IFDEBUG(1) - - for (i = 0; i < 16; i++) - { - char c; - READSHM(c, arlan->name[i], char); - if (c) - printk("%c", c); - } - printk("\n"); - -// ARLAN_DEBUG_EXIT("arlan_print_diagnostic_info"); - -} - - -/****************************** TEST MEMORY **************/ - -static int arlan_hw_test_memory(struct net_device *dev) -{ - u_char *ptr; - int i; - int memlen = sizeof(struct arlan_shmem) - 0xF; /* avoid control register */ - volatile char *arlan_mem = (char *) (dev->mem_start); - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - char pattern; - - ptr = NULL; - - /* hold card in reset state */ - setHardwareReset(dev); - - /* test memory */ - pattern = 0; - for (i = 0; i < memlen; i++) - WRITESHM(arlan_mem[i], ((u_char) pattern++), u_char); - - pattern = 0; - for (i = 0; i < memlen; i++) - { - char res; - READSHM(res, arlan_mem[i], char); - if (res != pattern++) - { - printk(KERN_ERR "Arlan driver memory test 1 failed \n"); - return -1; - } - } - - pattern = 0; - for (i = 0; i < memlen; i++) - WRITESHM(arlan_mem[i], ~(pattern++), char); - - pattern = 0; - for (i = 0; i < memlen; i++) - { - char res; - READSHM(res, arlan_mem[i], char); - if (res != ~(pattern++)) - { - printk(KERN_ERR "Arlan driver memory test 2 failed \n"); - return -1; - } - } - - /* zero memory */ - for (i = 0; i < memlen; i++) - WRITESHM(arlan_mem[i], 0x00, char); - - IFDEBUG(1) printk(KERN_INFO "Arlan: memory tests ok\n"); - - /* set reset flag and then release reset */ - WRITESHM(arlan->resetFlag, 0xff, u_char); - - clearChannelAttention(dev); - clearHardwareReset(dev); - - /* wait for reset flag to become zero, we'll wait for two seconds */ - if (arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW)) - { - printk(KERN_ERR "%s arlan: failed to come back from memory test\n", dev->name); - return -1; - } - return 0; -} - -static int arlan_setup_card_by_book(struct net_device *dev) -{ - u_char irqLevel, configuredStatusFlag; - struct arlan_private *priv = netdev_priv(dev); - volatile struct arlan_shmem __iomem *arlan = priv->card; - -// ARLAN_DEBUG_ENTRY("arlan_setup_card"); - - READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char); - - IFDEBUG(10) - if (configuredStatusFlag != 0) - IFDEBUG(10) printk("arlan: CARD IS CONFIGURED\n"); - else - IFDEBUG(10) printk("arlan: card is NOT configured\n"); - - if (testMemory || (READSHMB(arlan->diagnosticInfo) != 0xff)) - if (arlan_hw_test_memory(dev)) - return -1; - - DEBUGSHM(4, "arlan configuredStatus = %d \n", arlan->configuredStatusFlag, u_char); - DEBUGSHM(4, "arlan driver diagnostic: 0x%2x\n", arlan->diagnosticInfo, u_char); - - /* issue nop command - no interrupt */ - arlan_command(dev, ARLAN_COMMAND_NOOP); - if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0) - return -1; - - IFDEBUG(50) printk("1st Noop successfully executed !!\n"); - - /* try to turn on the arlan interrupts */ - clearClearInterrupt(dev); - setClearInterrupt(dev); - setInterruptEnable(dev); - - /* issue nop command - with interrupt */ - - arlan_command(dev, ARLAN_COMMAND_NOOPINT); - if (arlan_command(dev, ARLAN_COMMAND_WAIT_NOW) != 0) - return -1; - - - IFDEBUG(50) printk("2nd Noop successfully executed !!\n"); - - READSHM(irqLevel, arlan->irqLevel, u_char) - - if (irqLevel != dev->irq) - { - IFDEBUG(1) printk(KERN_WARNING "arlan dip switches set irq to %d\n", irqLevel); - printk(KERN_WARNING "device driver irq set to %d - does not match\n", dev->irq); - dev->irq = irqLevel; - } - else - IFDEBUG(2) printk("irq level is OK\n"); - - - IFDEBUG(3) arlan_print_diagnostic_info(dev); - - arlan_command(dev, ARLAN_COMMAND_CONF); - - READSHM(configuredStatusFlag, arlan->configuredStatusFlag, u_char); - if (configuredStatusFlag == 0) - { - printk(KERN_WARNING "arlan configure failed\n"); - return -1; - } - arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW); - arlan_command(dev, ARLAN_COMMAND_RX); - arlan_command(dev, ARLAN_COMMAND_LONG_WAIT_NOW); - printk(KERN_NOTICE "%s: arlan driver version %s loaded\n", - dev->name, arlan_version); - -// ARLAN_DEBUG_EXIT("arlan_setup_card"); - - return 0; /* no errors */ -} -#endif - -#ifdef ARLAN_PROC_INTERFACE -#ifdef ARLAN_PROC_SHM_DUMP - -static char arlan_drive_info[ARLAN_STR_SIZE] = "A655\n\0"; - -static int arlan_sysctl_info(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int i; - int retv, pos, devnum; - struct arlan_private *priva = NULL; - struct net_device *dev; - pos = 0; - if (write) - { - printk("wrirte: "); - for (i = 0; i < 100; i++) - printk("adi %x \n", arlan_drive_info[i]); - } - if (ctl->procname == NULL || arlan_drive_info == NULL) - { - printk(KERN_WARNING " procname is NULL in sysctl_table or arlan_drive_info is NULL \n at arlan module\n "); - return -1; - } - devnum = ctl->procname[5] - '0'; - if (devnum < 0 || devnum > MAX_ARLANS - 1) - { - printk(KERN_WARNING "too strange devnum in procfs parse\n "); - return -1; - } - else if (arlan_device[devnum] == NULL) - { - if (ctl->procname) - pos += sprintf(arlan_drive_info + pos, "\t%s\n\n", ctl->procname); - pos += sprintf(arlan_drive_info + pos, "No device found here \n"); - goto final; - } - else - priva = netdev_priv(arlan_device[devnum]); - - if (priva == NULL) - { - printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); - return -1; - } - dev = arlan_device[devnum]; - - memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); - - pos = sprintf(arlan_drive_info, "Arlan info \n"); - /* Header Signature */ - SARLSTR(textRegion, 48); - SARLUC(resetFlag); - pos += sprintf(arlan_drive_info + pos, "diagnosticInfo\t=\t%s \n", arlan_diagnostic_info_string(dev)); - SARLUC(diagnosticInfo); - SARLUS(diagnosticOffset); - SARLUCN(_1, 12); - SARLUCN(lanCardNodeId, 6); - SARLUCN(broadcastAddress, 6); - pos += sprintf(arlan_drive_info + pos, "hardwareType =\t %s \n", arlan_hardware_type_string(dev)); - SARLUC(hardwareType); - SARLUC(majorHardwareVersion); - SARLUC(minorHardwareVersion); - SARLUC(radioModule); - SARLUC(defaultChannelSet); - SARLUCN(_2, 47); - - /* Control/Status Block - 0x0080 */ - SARLUC(interruptInProgress); - SARLUC(cntrlRegImage); - - SARLUCN(_3, 14); - SARLUC(commandByte); - SARLUCN(commandParameter, 15); - - /* Receive Status - 0x00a0 */ - SARLUC(rxStatus); - SARLUC(rxFrmType); - SARLUS(rxOffset); - SARLUS(rxLength); - SARLUCN(rxSrc, 6); - SARLUC(rxBroadcastFlag); - SARLUC(rxQuality); - SARLUC(scrambled); - SARLUCN(_4, 1); - - /* Transmit Status - 0x00b0 */ - SARLUC(txStatus); - SARLUC(txAckQuality); - SARLUC(numRetries); - SARLUCN(_5, 14); - SARLUCN(registeredRouter, 6); - SARLUCN(backboneRouter, 6); - SARLUC(registrationStatus); - SARLUC(configuredStatusFlag); - SARLUCN(_6, 1); - SARLUCN(ultimateDestAddress, 6); - SARLUCN(immedDestAddress, 6); - SARLUCN(immedSrcAddress, 6); - SARLUS(rxSequenceNumber); - SARLUC(assignedLocaltalkAddress); - SARLUCN(_7, 27); - - /* System Parameter Block */ - - /* - Driver Parameters (Novell Specific) */ - - SARLUS(txTimeout); - SARLUS(transportTime); - SARLUCN(_8, 4); - - /* - Configuration Parameters */ - SARLUC(irqLevel); - SARLUC(spreadingCode); - SARLUC(channelSet); - SARLUC(channelNumber); - SARLUS(radioNodeId); - SARLUCN(_9, 2); - SARLUC(scramblingDisable); - SARLUC(radioType); - SARLUS(routerId); - SARLUCN(_10, 9); - SARLUC(txAttenuation); - SARLUIA(systemId); - SARLUS(globalChecksum); - SARLUCN(_11, 4); - SARLUS(maxDatagramSize); - SARLUS(maxFrameSize); - SARLUC(maxRetries); - SARLUC(receiveMode); - SARLUC(priority); - SARLUC(rootOrRepeater); - SARLUCN(specifiedRouter, 6); - SARLUS(fastPollPeriod); - SARLUC(pollDecay); - SARLUSA(fastPollDelay); - SARLUC(arlThreshold); - SARLUC(arlDecay); - SARLUCN(_12, 1); - SARLUS(specRouterTimeout); - SARLUCN(_13, 5); - - /* Scrambled Area */ - SARLUIA(SID); - SARLUCN(encryptionKey, 12); - SARLUIA(_14); - SARLUSA(waitTime); - SARLUSA(lParameter); - SARLUCN(_15, 3); - SARLUS(headerSize); - SARLUS(sectionChecksum); - - SARLUC(registrationMode); - SARLUC(registrationFill); - SARLUS(pollPeriod); - SARLUS(refreshPeriod); - SARLSTR(name, 16); - SARLUCN(NID, 6); - SARLUC(localTalkAddress); - SARLUC(codeFormat); - SARLUC(numChannels); - SARLUC(channel1); - SARLUC(channel2); - SARLUC(channel3); - SARLUC(channel4); - SARLUCN(SSCode, 59); - -/* SARLUCN( _16, 0x140); - */ - /* Statistics Block - 0x0300 */ - SARLUC(hostcpuLock); - SARLUC(lancpuLock); - SARLUCN(resetTime, 18); - SARLUIA(numDatagramsTransmitted); - SARLUIA(numReTransmissions); - SARLUIA(numFramesDiscarded); - SARLUIA(numDatagramsReceived); - SARLUIA(numDuplicateReceivedFrames); - SARLUIA(numDatagramsDiscarded); - SARLUS(maxNumReTransmitDatagram); - SARLUS(maxNumReTransmitFrames); - SARLUS(maxNumConsecutiveDuplicateFrames); - /* misaligned here so we have to go to characters */ - SARLUIA(numBytesTransmitted); - SARLUIA(numBytesReceived); - SARLUIA(numCRCErrors); - SARLUIA(numLengthErrors); - SARLUIA(numAbortErrors); - SARLUIA(numTXUnderruns); - SARLUIA(numRXOverruns); - SARLUIA(numHoldOffs); - SARLUIA(numFramesTransmitted); - SARLUIA(numFramesReceived); - SARLUIA(numReceiveFramesLost); - SARLUIA(numRXBufferOverflows); - SARLUIA(numFramesDiscardedAddrMismatch); - SARLUIA(numFramesDiscardedSIDMismatch); - SARLUIA(numPollsTransmistted); - SARLUIA(numPollAcknowledges); - SARLUIA(numStatusTimeouts); - SARLUIA(numNACKReceived); - SARLUS(auxCmd); - SARLUCN(dumpPtr, 4); - SARLUC(dumpVal); - SARLUC(wireTest); - - /* next 4 seems too long for procfs, over single page ? - SARLUCN( _17, 0x86); - SARLUCN( txBuffer, 0x800); - SARLUCN( rxBuffer, 0x800); - SARLUCN( _18, 0x0bff); - */ - - pos += sprintf(arlan_drive_info + pos, "rxRing\t=\t0x"); - for (i = 0; i < 0x50; i++) - pos += sprintf(arlan_drive_info + pos, "%02x", ((char *) priva->conf)[priva->conf->rxOffset + i]); - pos += sprintf(arlan_drive_info + pos, "\n"); - - SARLUC(configStatus); - SARLUC(_22); - SARLUC(progIOCtrl); - SARLUC(shareMBase); - SARLUC(controlRegister); - - pos += sprintf(arlan_drive_info + pos, " total %d chars\n", pos); - if (ctl) - if (ctl->procname) - pos += sprintf(arlan_drive_info + pos, " driver name : %s\n", ctl->procname); -final: - *lenp = pos; - - if (!write) - retv = proc_dostring(ctl, write, buffer, lenp, ppos); - else - { - *lenp = 0; - return -1; - } - return retv; -} - - -static int arlan_sysctl_info161719(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int i; - int retv, pos, devnum; - struct arlan_private *priva = NULL; - - pos = 0; - devnum = ctl->procname[5] - '0'; - if (arlan_device[devnum] == NULL) - { - pos += sprintf(arlan_drive_info + pos, "No device found here \n"); - goto final; - } - else - priva = netdev_priv(arlan_device[devnum]); - if (priva == NULL) - { - printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); - return -1; - } - memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); - SARLUCN(_16, 0xC0); - SARLUCN(_17, 0x6A); - SARLUCN(_18, 14); - SARLUCN(_19, 0x86); - SARLUCN(_21, 0x3fd); - -final: - *lenp = pos; - retv = proc_dostring(ctl, write, buffer, lenp, ppos); - return retv; -} - -static int arlan_sysctl_infotxRing(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int i; - int retv, pos, devnum; - struct arlan_private *priva = NULL; - - pos = 0; - devnum = ctl->procname[5] - '0'; - if (arlan_device[devnum] == NULL) - { - pos += sprintf(arlan_drive_info + pos, "No device found here \n"); - goto final; - } - else - priva = netdev_priv(arlan_device[devnum]); - if (priva == NULL) - { - printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); - return -1; - } - memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); - SARLBNpln(u_char, txBuffer, 0x800); -final: - *lenp = pos; - retv = proc_dostring(ctl, write, buffer, lenp, ppos); - return retv; -} - -static int arlan_sysctl_inforxRing(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int i; - int retv, pos, devnum; - struct arlan_private *priva = NULL; - - pos = 0; - devnum = ctl->procname[5] - '0'; - if (arlan_device[devnum] == NULL) - { - pos += sprintf(arlan_drive_info + pos, "No device found here \n"); - goto final; - } else - priva = netdev_priv(arlan_device[devnum]); - if (priva == NULL) - { - printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); - return -1; - } - memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); - SARLBNpln(u_char, rxBuffer, 0x800); -final: - *lenp = pos; - retv = proc_dostring(ctl, write, buffer, lenp, ppos); - return retv; -} - -static int arlan_sysctl_info18(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int i; - int retv, pos, devnum; - struct arlan_private *priva = NULL; - - pos = 0; - devnum = ctl->procname[5] - '0'; - if (arlan_device[devnum] == NULL) - { - pos += sprintf(arlan_drive_info + pos, "No device found here \n"); - goto final; - } - else - priva = netdev_priv(arlan_device[devnum]); - if (priva == NULL) - { - printk(KERN_WARNING " Could not find the device private in arlan procsys, bad\n "); - return -1; - } - memcpy_fromio(priva->conf, priva->card, sizeof(struct arlan_shmem)); - SARLBNpln(u_char, _18, 0x800); - -final: - *lenp = pos; - retv = proc_dostring(ctl, write, buffer, lenp, ppos); - return retv; -} - - -#endif /* #ifdef ARLAN_PROC_SHM_DUMP */ - - -static char conf_reset_result[200]; - -static int arlan_configure(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int pos = 0; - int devnum = ctl->procname[6] - '0'; - struct arlan_private *priv; - - if (devnum < 0 || devnum > MAX_ARLANS - 1) - { - printk(KERN_WARNING "too strange devnum in procfs parse\n "); - return -1; - } - else if (arlan_device[devnum] != NULL) - { - priv = netdev_priv(arlan_device[devnum]); - - arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_CONF); - } - else - return -1; - - *lenp = pos; - return proc_dostring(ctl, write, buffer, lenp, ppos); -} - -static int arlan_sysctl_reset(ctl_table * ctl, int write, - void __user *buffer, size_t * lenp, loff_t *ppos) -{ - int pos = 0; - int devnum = ctl->procname[5] - '0'; - struct arlan_private *priv; - - if (devnum < 0 || devnum > MAX_ARLANS - 1) - { - printk(KERN_WARNING "too strange devnum in procfs parse\n "); - return -1; - } - else if (arlan_device[devnum] != NULL) - { - priv = netdev_priv(arlan_device[devnum]); - arlan_command(arlan_device[devnum], ARLAN_COMMAND_CLEAN_AND_RESET); - - } else - return -1; - *lenp = pos + 3; - return proc_dostring(ctl, write, buffer, lenp, ppos); -} - - -/* Place files in /proc/sys/dev/arlan */ -#define CTBLN(num,card,nam) \ - { .ctl_name = num,\ - .procname = #nam,\ - .data = &(arlan_conf[card].nam),\ - .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec} -#ifdef ARLAN_DEBUGGING - -#define ARLAN_PROC_DEBUG_ENTRIES \ - { .ctl_name = 48, .procname = "entry_exit_debug",\ - .data = &arlan_entry_and_exit_debug,\ - .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec},\ - { .ctl_name = 49, .procname = "debug", .data = &arlan_debug,\ - .maxlen = sizeof(int), .mode = 0600, .proc_handler = &proc_dointvec}, -#else -#define ARLAN_PROC_DEBUG_ENTRIES -#endif - -#define ARLAN_SYSCTL_TABLE_TOTAL(cardNo)\ - CTBLN(1,cardNo,spreadingCode),\ - CTBLN(2,cardNo, channelNumber),\ - CTBLN(3,cardNo, scramblingDisable),\ - CTBLN(4,cardNo, txAttenuation),\ - CTBLN(5,cardNo, systemId), \ - CTBLN(6,cardNo, maxDatagramSize),\ - CTBLN(7,cardNo, maxFrameSize),\ - CTBLN(8,cardNo, maxRetries),\ - CTBLN(9,cardNo, receiveMode),\ - CTBLN(10,cardNo, priority),\ - CTBLN(11,cardNo, rootOrRepeater),\ - CTBLN(12,cardNo, SID),\ - CTBLN(13,cardNo, registrationMode),\ - CTBLN(14,cardNo, registrationFill),\ - CTBLN(15,cardNo, localTalkAddress),\ - CTBLN(16,cardNo, codeFormat),\ - CTBLN(17,cardNo, numChannels),\ - CTBLN(18,cardNo, channel1),\ - CTBLN(19,cardNo, channel2),\ - CTBLN(20,cardNo, channel3),\ - CTBLN(21,cardNo, channel4),\ - CTBLN(22,cardNo, txClear),\ - CTBLN(23,cardNo, txRetries),\ - CTBLN(24,cardNo, txRouting),\ - CTBLN(25,cardNo, txScrambled),\ - CTBLN(26,cardNo, rxParameter),\ - CTBLN(27,cardNo, txTimeoutMs),\ - CTBLN(28,cardNo, waitCardTimeout),\ - CTBLN(29,cardNo, channelSet), \ - {.ctl_name = 30, .procname = "name",\ - .data = arlan_conf[cardNo].siteName,\ - .maxlen = 16, .mode = 0600, .proc_handler = &proc_dostring},\ - CTBLN(31,cardNo,waitTime),\ - CTBLN(32,cardNo,lParameter),\ - CTBLN(33,cardNo,_15),\ - CTBLN(34,cardNo,headerSize),\ - CTBLN(36,cardNo,tx_delay_ms),\ - CTBLN(37,cardNo,retries),\ - CTBLN(38,cardNo,ReTransmitPacketMaxSize),\ - CTBLN(39,cardNo,waitReTransmitPacketMaxSize),\ - CTBLN(40,cardNo,fastReTransCount),\ - CTBLN(41,cardNo,driverRetransmissions),\ - CTBLN(42,cardNo,txAckTimeoutMs),\ - CTBLN(43,cardNo,registrationInterrupts),\ - CTBLN(44,cardNo,hardwareType),\ - CTBLN(45,cardNo,radioType),\ - CTBLN(46,cardNo,writeEEPROM),\ - CTBLN(47,cardNo,writeRadioType),\ - ARLAN_PROC_DEBUG_ENTRIES\ - CTBLN(50,cardNo,in_speed),\ - CTBLN(51,cardNo,out_speed),\ - CTBLN(52,cardNo,in_speed10),\ - CTBLN(53,cardNo,out_speed10),\ - CTBLN(54,cardNo,in_speed_max),\ - CTBLN(55,cardNo,out_speed_max),\ - CTBLN(56,cardNo,measure_rate),\ - CTBLN(57,cardNo,pre_Command_Wait),\ - CTBLN(58,cardNo,rx_tweak1),\ - CTBLN(59,cardNo,rx_tweak2),\ - CTBLN(60,cardNo,tx_queue_len),\ - - - -static ctl_table arlan_conf_table0[] = -{ - ARLAN_SYSCTL_TABLE_TOTAL(0) - -#ifdef ARLAN_PROC_SHM_DUMP - { - .ctl_name = 150, - .procname = "arlan0-txRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_infotxRing, - }, - { - .ctl_name = 151, - .procname = "arlan0-rxRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_inforxRing, - }, - { - .ctl_name = 152, - .procname = "arlan0-18", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info18, - }, - { - .ctl_name = 153, - .procname = "arlan0-ring", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info161719, - }, - { - .ctl_name = 154, - .procname = "arlan0-shm-cpy", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info, - }, -#endif - { - .ctl_name = 155, - .procname = "config0", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_configure - }, - { - .ctl_name = 156, - .procname = "reset0", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_sysctl_reset, - }, - { .ctl_name = 0 } -}; - -static ctl_table arlan_conf_table1[] = -{ - - ARLAN_SYSCTL_TABLE_TOTAL(1) - -#ifdef ARLAN_PROC_SHM_DUMP - { - .ctl_name = 150, - .procname = "arlan1-txRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_infotxRing, - }, - { - .ctl_name = 151, - .procname = "arlan1-rxRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_inforxRing, - }, - { - .ctl_name = 152, - .procname = "arlan1-18", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info18, - }, - { - .ctl_name = 153, - .procname = "arlan1-ring", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info161719, - }, - { - .ctl_name = 154, - .procname = "arlan1-shm-cpy", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info, - }, -#endif - { - .ctl_name = 155, - .procname = "config1", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_configure, - }, - { - .ctl_name = 156, - .procname = "reset1", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_sysctl_reset, - }, - { .ctl_name = 0 } -}; - -static ctl_table arlan_conf_table2[] = -{ - - ARLAN_SYSCTL_TABLE_TOTAL(2) - -#ifdef ARLAN_PROC_SHM_DUMP - { - .ctl_name = 150, - .procname = "arlan2-txRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_infotxRing, - }, - { - .ctl_name = 151, - .procname = "arlan2-rxRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_inforxRing, - }, - { - .ctl_name = 152, - .procname = "arlan2-18", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info18, - }, - { - .ctl_name = 153, - .procname = "arlan2-ring", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info161719, - }, - { - .ctl_name = 154, - .procname = "arlan2-shm-cpy", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info, - }, -#endif - { - .ctl_name = 155, - .procname = "config2", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_configure, - }, - { - .ctl_name = 156, - .procname = "reset2", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_sysctl_reset, - }, - { .ctl_name = 0 } -}; - -static ctl_table arlan_conf_table3[] = -{ - - ARLAN_SYSCTL_TABLE_TOTAL(3) - -#ifdef ARLAN_PROC_SHM_DUMP - { - .ctl_name = 150, - .procname = "arlan3-txRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_infotxRing, - }, - { - .ctl_name = 151, - .procname = "arlan3-rxRing", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_inforxRing, - }, - { - .ctl_name = 152, - .procname = "arlan3-18", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info18, - }, - { - .ctl_name = 153, - .procname = "arlan3-ring", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info161719, - }, - { - .ctl_name = 154, - .procname = "arlan3-shm-cpy", - .data = &arlan_drive_info, - .maxlen = ARLAN_STR_SIZE, - .mode = 0400, - .proc_handler = &arlan_sysctl_info, - }, -#endif - { - .ctl_name = 155, - .procname = "config3", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_configure, - }, - { - .ctl_name = 156, - .procname = "reset3", - .data = &conf_reset_result, - .maxlen = 100, - .mode = 0400, - .proc_handler = &arlan_sysctl_reset, - }, - { .ctl_name = 0 } -}; - - - -static ctl_table arlan_table[] = -{ - { - .ctl_name = 0, - .procname = "arlan0", - .maxlen = 0, - .mode = 0600, - .child = arlan_conf_table0, - }, - { - .ctl_name = 0, - .procname = "arlan1", - .maxlen = 0, - .mode = 0600, - .child = arlan_conf_table1, - }, - { - .ctl_name = 0, - .procname = "arlan2", - .maxlen = 0, - .mode = 0600, - .child = arlan_conf_table2, - }, - { - .ctl_name = 0, - .procname = "arlan3", - .maxlen = 0, - .mode = 0600, - .child = arlan_conf_table3, - }, - { .ctl_name = 0 } -}; - -#else - -static ctl_table arlan_table[MAX_ARLANS + 1] = -{ - { .ctl_name = 0 } -}; -#endif - - -// static int mmtu = 1234; - -static ctl_table arlan_root_table[] = -{ - { - .ctl_name = CTL_ARLAN, - .procname = "arlan", - .maxlen = 0, - .mode = 0555, - .child = arlan_table, - }, - { .ctl_name = 0 } -}; - -/* Make sure that /proc/sys/dev is there */ -//static ctl_table arlan_device_root_table[] = -//{ -// {CTL_DEV, "dev", NULL, 0, 0555, arlan_root_table}, -// {0} -//}; - - -static struct ctl_table_header *arlan_device_sysctl_header; - -int __init init_arlan_proc(void) -{ - - int i = 0; - if (arlan_device_sysctl_header) - return 0; - for (i = 0; i < MAX_ARLANS && arlan_device[i]; i++) - arlan_table[i].ctl_name = i + 1; - arlan_device_sysctl_header = register_sysctl_table(arlan_root_table); - if (!arlan_device_sysctl_header) - return -1; - - return 0; - -} - -void __exit cleanup_arlan_proc(void) -{ - unregister_sysctl_table(arlan_device_sysctl_header); - arlan_device_sysctl_header = NULL; - -} -#endif diff --git a/drivers/net/wireless/arlan.h b/drivers/net/wireless/arlan.h deleted file mode 100644 index fb3ad51a1caf..000000000000 --- a/drivers/net/wireless/arlan.h +++ /dev/null @@ -1,539 +0,0 @@ -/* - * Copyright (C) 1997 Cullen Jennings - * Copyright (C) 1998 Elmer.Joandi@ut.ee, +37-255-13500 - * GNU General Public License applies - */ - -#include -#include -#include -#include -#include /* For the statistics structure. */ -#include /* For ARPHRD_ETHER */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - - -//#define ARLAN_DEBUGGING 1 - -#define ARLAN_PROC_INTERFACE -#define MAX_ARLANS 4 /* not more than 4 ! */ -#define ARLAN_PROC_SHM_DUMP /* shows all card registers, makes driver way larger */ - -#define ARLAN_MAX_MULTICAST_ADDRS 16 -#define ARLAN_RCV_CLEAN 0 -#define ARLAN_RCV_PROMISC 1 -#define ARLAN_RCV_CONTROL 2 - -#ifdef CONFIG_PROC_FS -extern int init_arlan_proc(void); -extern void cleanup_arlan_proc(void); -#else -#define init_arlan_proc() ({ 0; }) -#define cleanup_arlan_proc() do { } while (0) -#endif - -extern struct net_device *arlan_device[MAX_ARLANS]; -extern int arlan_debug; -extern int arlan_entry_debug; -extern int arlan_exit_debug; -extern int testMemory; -extern int arlan_command(struct net_device * dev, int command); - -#define SIDUNKNOWN -1 -#define radioNodeIdUNKNOWN -1 -#define irqUNKNOWN 0 -#define debugUNKNOWN 0 -#define testMemoryUNKNOWN 1 -#define spreadingCodeUNKNOWN 0 -#define channelNumberUNKNOWN 0 -#define channelSetUNKNOWN 0 -#define systemIdUNKNOWN -1 -#define registrationModeUNKNOWN -1 - - -#define IFDEBUG( L ) if ( (L) & arlan_debug ) -#define ARLAN_FAKE_HDR_LEN 12 - -#ifdef ARLAN_DEBUGGING - #define DEBUG 1 - #define ARLAN_ENTRY_EXIT_DEBUGGING 1 - #define ARLAN_DEBUG(a,b) printk(KERN_DEBUG a, b) -#else - #define ARLAN_DEBUG(a,b) -#endif - -#define ARLAN_SHMEM_SIZE 0x2000 - -struct arlan_shmem -{ - /* Header Signature */ - volatile char textRegion[48]; - volatile u_char resetFlag; - volatile u_char diagnosticInfo; - volatile u_short diagnosticOffset; - volatile u_char _1[12]; - volatile u_char lanCardNodeId[6]; - volatile u_char broadcastAddress[6]; - volatile u_char hardwareType; - volatile u_char majorHardwareVersion; - volatile u_char minorHardwareVersion; - volatile u_char radioModule;// shows EEPROM, can be overridden at 0x111 - volatile u_char defaultChannelSet; // shows EEProm, can be overriiden at 0x10A - volatile u_char _2[47]; - - /* Control/Status Block - 0x0080 */ - volatile u_char interruptInProgress; /* not used by lancpu */ - volatile u_char cntrlRegImage; /* not used by lancpu */ - volatile u_char _3[13]; - volatile u_char dumpByte; - volatile u_char commandByte; /* non-zero = active */ - volatile u_char commandParameter[15]; - - /* Receive Status - 0x00a0 */ - volatile u_char rxStatus; /* 1- data, 2-control, 0xff - registr change */ - volatile u_char rxFrmType; - volatile u_short rxOffset; - volatile u_short rxLength; - volatile u_char rxSrc[6]; - volatile u_char rxBroadcastFlag; - volatile u_char rxQuality; - volatile u_char scrambled; - volatile u_char _4[1]; - - /* Transmit Status - 0x00b0 */ - volatile u_char txStatus; - volatile u_char txAckQuality; - volatile u_char numRetries; - volatile u_char _5[14]; - volatile u_char registeredRouter[6]; - volatile u_char backboneRouter[6]; - volatile u_char registrationStatus; - volatile u_char configuredStatusFlag; - volatile u_char _6[1]; - volatile u_char ultimateDestAddress[6]; - volatile u_char immedDestAddress[6]; - volatile u_char immedSrcAddress[6]; - volatile u_short rxSequenceNumber; - volatile u_char assignedLocaltalkAddress; - volatile u_char _7[27]; - - /* System Parameter Block */ - - /* - Driver Parameters (Novell Specific) */ - - volatile u_short txTimeout; - volatile u_short transportTime; - volatile u_char _8[4]; - - /* - Configuration Parameters */ - volatile u_char irqLevel; - volatile u_char spreadingCode; - volatile u_char channelSet; - volatile u_char channelNumber; - volatile u_short radioNodeId; - volatile u_char _9[2]; - volatile u_char scramblingDisable; - volatile u_char radioType; - volatile u_short routerId; - volatile u_char _10[9]; - volatile u_char txAttenuation; - volatile u_char systemId[4]; - volatile u_short globalChecksum; - volatile u_char _11[4]; - volatile u_short maxDatagramSize; - volatile u_short maxFrameSize; - volatile u_char maxRetries; - volatile u_char receiveMode; - volatile u_char priority; - volatile u_char rootOrRepeater; - volatile u_char specifiedRouter[6]; - volatile u_short fastPollPeriod; - volatile u_char pollDecay; - volatile u_char fastPollDelay[2]; - volatile u_char arlThreshold; - volatile u_char arlDecay; - volatile u_char _12[1]; - volatile u_short specRouterTimeout; - volatile u_char _13[5]; - - /* Scrambled Area */ - volatile u_char SID[4]; - volatile u_char encryptionKey[12]; - volatile u_char _14[2]; - volatile u_char waitTime[2]; - volatile u_char lParameter[2]; - volatile u_char _15[3]; - volatile u_short headerSize; - volatile u_short sectionChecksum; - - volatile u_char registrationMode; - volatile u_char registrationFill; - volatile u_short pollPeriod; - volatile u_short refreshPeriod; - volatile u_char name[16]; - volatile u_char NID[6]; - volatile u_char localTalkAddress; - volatile u_char codeFormat; - volatile u_char numChannels; - volatile u_char channel1; - volatile u_char channel2; - volatile u_char channel3; - volatile u_char channel4; - volatile u_char SSCode[59]; - - volatile u_char _16[0xC0]; - volatile u_short auxCmd; - volatile u_char dumpPtr[4]; - volatile u_char dumpVal; - volatile u_char _17[0x6A]; - volatile u_char wireTest; - volatile u_char _18[14]; - - /* Statistics Block - 0x0300 */ - volatile u_char hostcpuLock; - volatile u_char lancpuLock; - volatile u_char resetTime[18]; - - volatile u_char numDatagramsTransmitted[4]; - volatile u_char numReTransmissions[4]; - volatile u_char numFramesDiscarded[4]; - volatile u_char numDatagramsReceived[4]; - volatile u_char numDuplicateReceivedFrames[4]; - volatile u_char numDatagramsDiscarded[4]; - - volatile u_short maxNumReTransmitDatagram; - volatile u_short maxNumReTransmitFrames; - volatile u_short maxNumConsecutiveDuplicateFrames; - /* misaligned here so we have to go to characters */ - - volatile u_char numBytesTransmitted[4]; - volatile u_char numBytesReceived[4]; - volatile u_char numCRCErrors[4]; - volatile u_char numLengthErrors[4]; - volatile u_char numAbortErrors[4]; - volatile u_char numTXUnderruns[4]; - volatile u_char numRXOverruns[4]; - volatile u_char numHoldOffs[4]; - volatile u_char numFramesTransmitted[4]; - volatile u_char numFramesReceived[4]; - volatile u_char numReceiveFramesLost[4]; - volatile u_char numRXBufferOverflows[4]; - volatile u_char numFramesDiscardedAddrMismatch[4]; - volatile u_char numFramesDiscardedSIDMismatch[4]; - volatile u_char numPollsTransmistted[4]; - volatile u_char numPollAcknowledges[4]; - volatile u_char numStatusTimeouts[4]; - volatile u_char numNACKReceived[4]; - - volatile u_char _19[0x86]; - - volatile u_char txBuffer[0x800]; - volatile u_char rxBuffer[0x800]; - - volatile u_char _20[0x800]; - volatile u_char _21[0x3fb]; - volatile u_char configStatus; - volatile u_char _22; - volatile u_char progIOCtrl; - volatile u_char shareMBase; - volatile u_char controlRegister; -}; - -struct arlan_conf_stru { - int spreadingCode; - int channelSet; - int channelNumber; - int scramblingDisable; - int txAttenuation; - int systemId; - int maxDatagramSize; - int maxFrameSize; - int maxRetries; - int receiveMode; - int priority; - int rootOrRepeater; - int SID; - int radioNodeId; - int registrationMode; - int registrationFill; - int localTalkAddress; - int codeFormat; - int numChannels; - int channel1; - int channel2; - int channel3; - int channel4; - int txClear; - int txRetries; - int txRouting; - int txScrambled; - int rxParameter; - int txTimeoutMs; - int txAckTimeoutMs; - int waitCardTimeout; - int waitTime; - int lParameter; - int _15; - int headerSize; - int retries; - int tx_delay_ms; - int waitReTransmitPacketMaxSize; - int ReTransmitPacketMaxSize; - int fastReTransCount; - int driverRetransmissions; - int registrationInterrupts; - int hardwareType; - int radioType; - int writeRadioType; - int writeEEPROM; - char siteName[17]; - int measure_rate; - int in_speed; - int out_speed; - int in_speed10; - int out_speed10; - int in_speed_max; - int out_speed_max; - int pre_Command_Wait; - int rx_tweak1; - int rx_tweak2; - int tx_queue_len; -}; - -extern struct arlan_conf_stru arlan_conf[MAX_ARLANS]; - -struct TxParam -{ - volatile short offset; - volatile short length; - volatile u_char dest[6]; - volatile unsigned char clear; - volatile unsigned char retries; - volatile unsigned char routing; - volatile unsigned char scrambled; -}; - -#define TX_RING_SIZE 2 -/* Information that need to be kept for each board. */ -struct arlan_private { - struct arlan_shmem __iomem * card; - struct arlan_shmem * conf; - - struct arlan_conf_stru * Conf; - int bad; - int reset; - unsigned long lastReset; - struct timer_list timer; - struct timer_list tx_delay_timer; - struct timer_list tx_retry_timer; - struct timer_list rx_check_timer; - - int registrationLostCount; - int reRegisterExp; - int irq_test_done; - - struct TxParam txRing[TX_RING_SIZE]; - char reTransmitBuff[0x800]; - int txLast; - unsigned ReTransmitRequested; - unsigned long tx_done_delayed; - unsigned long registrationLastSeen; - - unsigned long tx_last_sent; - unsigned long tx_last_cleared; - unsigned long retransmissions; - unsigned long interrupt_ack_requested; - spinlock_t lock; - unsigned long waiting_command_mask; - unsigned long card_polling_interval; - unsigned long last_command_buff_free_time; - - int under_reset; - int under_config; - int rx_command_given; - int tx_command_given; - unsigned long interrupt_processing_active; - unsigned long last_rx_int_ack_time; - unsigned long in_bytes; - unsigned long out_bytes; - unsigned long in_time; - unsigned long out_time; - unsigned long in_time10; - unsigned long out_time10; - unsigned long in_bytes10; - unsigned long out_bytes10; - int init_etherdev_alloc; -}; - - - -#define ARLAN_CLEAR 0x00 -#define ARLAN_RESET 0x01 -#define ARLAN_CHANNEL_ATTENTION 0x02 -#define ARLAN_INTERRUPT_ENABLE 0x04 -#define ARLAN_CLEAR_INTERRUPT 0x08 -#define ARLAN_POWER 0x40 -#define ARLAN_ACCESS 0x80 - -#define ARLAN_COM_CONF 0x01 -#define ARLAN_COM_RX_ENABLE 0x03 -#define ARLAN_COM_RX_ABORT 0x04 -#define ARLAN_COM_TX_ENABLE 0x05 -#define ARLAN_COM_TX_ABORT 0x06 -#define ARLAN_COM_NOP 0x07 -#define ARLAN_COM_STANDBY 0x08 -#define ARLAN_COM_ACTIVATE 0x09 -#define ARLAN_COM_GOTO_SLOW_POLL 0x0a -#define ARLAN_COM_INT 0x80 - - -#define TXLAST(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[((struct arlan_private *)netdev_priv(dev))->txLast]) -#define TXHEAD(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[0]) -#define TXTAIL(dev) (((struct arlan_private *)netdev_priv(dev))->txRing[1]) - -#define TXBuffStart(dev) offsetof(struct arlan_shmem, txBuffer) -#define TXBuffEnd(dev) offsetof(struct arlan_shmem, xxBuffer) - -#define READSHM(to,from,atype) {\ - atype tmp;\ - memcpy_fromio(&(tmp),&(from),sizeof(atype));\ - to = tmp;\ - } - -#define READSHMEM(from,atype)\ - atype from; \ - READSHM(from, arlan->from, atype); - -#define WRITESHM(to,from,atype) \ - { atype tmpSHM = from;\ - memcpy_toio(&(to),&tmpSHM,sizeof(atype));\ - } - -#define DEBUGSHM(levelSHM,stringSHM,stuff,atype) \ - { atype tmpSHM; \ - memcpy_fromio(&tmpSHM,&(stuff),sizeof(atype));\ - IFDEBUG(levelSHM) printk(stringSHM,tmpSHM);\ - } - -#define WRITESHMB(to, val) \ - writeb(val,&(to)) -#define READSHMB(to) \ - readb(&(to)) -#define WRITESHMS(to, val) \ - writew(val,&(to)) -#define READSHMS(to) \ - readw(&(to)) -#define WRITESHMI(to, val) \ - writel(val,&(to)) -#define READSHMI(to) \ - readl(&(to)) - - - - - -#define registrationBad(dev)\ - ( ( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationMode) > 0) && \ - ( READSHMB(((struct arlan_private *)netdev_priv(dev))->card->registrationStatus) == 0) ) - - -#define readControlRegister(dev)\ - READSHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage) - -#define writeControlRegister(dev, v){\ - WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->cntrlRegImage ,((v) &0xF) );\ - WRITESHMB(((struct arlan_private *)netdev_priv(dev))->card->controlRegister ,(v) );} - - -#define arlan_interrupt_lancpu(dev) {\ - int cr; \ - \ - cr = readControlRegister(dev);\ - if (cr & ARLAN_CHANNEL_ATTENTION){ \ - writeControlRegister(dev, (cr & ~ARLAN_CHANNEL_ATTENTION));\ - }else \ - writeControlRegister(dev, (cr | ARLAN_CHANNEL_ATTENTION));\ -} - -#define clearChannelAttention(dev){ \ - writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CHANNEL_ATTENTION);} -#define setHardwareReset(dev) {\ - writeControlRegister(dev,readControlRegister(dev) | ARLAN_RESET);} -#define clearHardwareReset(dev) {\ - writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_RESET);} -#define setInterruptEnable(dev){\ - writeControlRegister(dev,readControlRegister(dev) | ARLAN_INTERRUPT_ENABLE) ;} -#define clearInterruptEnable(dev){\ - writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_INTERRUPT_ENABLE) ;} -#define setClearInterrupt(dev){\ - writeControlRegister(dev,readControlRegister(dev) | ARLAN_CLEAR_INTERRUPT) ;} -#define clearClearInterrupt(dev){\ - writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_CLEAR_INTERRUPT);} -#define setPowerOff(dev){\ - writeControlRegister(dev,readControlRegister(dev) | (ARLAN_POWER && ARLAN_ACCESS));\ - writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);} -#define setPowerOn(dev){\ - writeControlRegister(dev,readControlRegister(dev) & ~(ARLAN_POWER)); } -#define arlan_lock_card_access(dev){\ - writeControlRegister(dev,readControlRegister(dev) & ~ARLAN_ACCESS);} -#define arlan_unlock_card_access(dev){\ - writeControlRegister(dev,readControlRegister(dev) | ARLAN_ACCESS ); } - - - - -#define ARLAN_COMMAND_RX 0x000001 -#define ARLAN_COMMAND_NOOP 0x000002 -#define ARLAN_COMMAND_NOOPINT 0x000004 -#define ARLAN_COMMAND_TX 0x000008 -#define ARLAN_COMMAND_CONF 0x000010 -#define ARLAN_COMMAND_RESET 0x000020 -#define ARLAN_COMMAND_TX_ABORT 0x000040 -#define ARLAN_COMMAND_RX_ABORT 0x000080 -#define ARLAN_COMMAND_POWERDOWN 0x000100 -#define ARLAN_COMMAND_POWERUP 0x000200 -#define ARLAN_COMMAND_SLOW_POLL 0x000400 -#define ARLAN_COMMAND_ACTIVATE 0x000800 -#define ARLAN_COMMAND_INT_ACK 0x001000 -#define ARLAN_COMMAND_INT_ENABLE 0x002000 -#define ARLAN_COMMAND_WAIT_NOW 0x004000 -#define ARLAN_COMMAND_LONG_WAIT_NOW 0x008000 -#define ARLAN_COMMAND_STANDBY 0x010000 -#define ARLAN_COMMAND_INT_RACK 0x020000 -#define ARLAN_COMMAND_INT_RENABLE 0x040000 -#define ARLAN_COMMAND_CONF_WAIT 0x080000 -#define ARLAN_COMMAND_TBUSY_CLEAR 0x100000 -#define ARLAN_COMMAND_CLEAN_AND_CONF (ARLAN_COMMAND_TX_ABORT\ - | ARLAN_COMMAND_RX_ABORT\ - | ARLAN_COMMAND_CONF) -#define ARLAN_COMMAND_CLEAN_AND_RESET (ARLAN_COMMAND_TX_ABORT\ - | ARLAN_COMMAND_RX_ABORT\ - | ARLAN_COMMAND_RESET) - - - -#define ARLAN_DEBUG_CHAIN_LOCKS 0x00001 -#define ARLAN_DEBUG_RESET 0x00002 -#define ARLAN_DEBUG_TIMING 0x00004 -#define ARLAN_DEBUG_CARD_STATE 0x00008 -#define ARLAN_DEBUG_TX_CHAIN 0x00010 -#define ARLAN_DEBUG_MULTICAST 0x00020 -#define ARLAN_DEBUG_HEADER_DUMP 0x00040 -#define ARLAN_DEBUG_INTERRUPT 0x00080 -#define ARLAN_DEBUG_STARTUP 0x00100 -#define ARLAN_DEBUG_SHUTDOWN 0x00200 - diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c deleted file mode 100644 index 8e1a55dec351..000000000000 --- a/drivers/net/wireless/at76c50x-usb.c +++ /dev/null @@ -1,2505 +0,0 @@ -/* - * at76c503/at76c505 USB driver - * - * Copyright (c) 2002 - 2003 Oliver Kurth - * Copyright (c) 2004 Joerg Albert - * Copyright (c) 2004 Nick Jones - * Copyright (c) 2004 Balint Seeber - * Copyright (c) 2007 Guido Guenther - * Copyright (c) 2007 Kalle Valo - * - * 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 file is part of the Berlios driver for WLAN USB devices based on the - * Atmel AT76C503A/505/505A. - * - * Some iw_handler code was taken from airo.c, (C) 1999 Benjamin Reed - * - * TODO list is at the wiki: - * - * http://wireless.kernel.org/en/users/Drivers/at76c50x-usb#TODO - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "at76c50x-usb.h" - -/* Version information */ -#define DRIVER_NAME "at76c50x-usb" -#define DRIVER_VERSION "0.17" -#define DRIVER_DESC "Atmel at76x USB Wireless LAN Driver" - -/* at76_debug bits */ -#define DBG_PROGRESS 0x00000001 /* authentication/accociation */ -#define DBG_BSS_TABLE 0x00000002 /* show BSS table after scans */ -#define DBG_IOCTL 0x00000004 /* ioctl calls / settings */ -#define DBG_MAC_STATE 0x00000008 /* MAC state transitions */ -#define DBG_TX_DATA 0x00000010 /* tx header */ -#define DBG_TX_DATA_CONTENT 0x00000020 /* tx content */ -#define DBG_TX_MGMT 0x00000040 /* tx management */ -#define DBG_RX_DATA 0x00000080 /* rx data header */ -#define DBG_RX_DATA_CONTENT 0x00000100 /* rx data content */ -#define DBG_RX_MGMT 0x00000200 /* rx mgmt frame headers */ -#define DBG_RX_BEACON 0x00000400 /* rx beacon */ -#define DBG_RX_CTRL 0x00000800 /* rx control */ -#define DBG_RX_MGMT_CONTENT 0x00001000 /* rx mgmt content */ -#define DBG_RX_FRAGS 0x00002000 /* rx data fragment handling */ -#define DBG_DEVSTART 0x00004000 /* fw download, device start */ -#define DBG_URB 0x00008000 /* rx urb status, ... */ -#define DBG_RX_ATMEL_HDR 0x00010000 /* Atmel-specific Rx headers */ -#define DBG_PROC_ENTRY 0x00020000 /* procedure entries/exits */ -#define DBG_PM 0x00040000 /* power management settings */ -#define DBG_BSS_MATCH 0x00080000 /* BSS match failures */ -#define DBG_PARAMS 0x00100000 /* show configured parameters */ -#define DBG_WAIT_COMPLETE 0x00200000 /* command completion */ -#define DBG_RX_FRAGS_SKB 0x00400000 /* skb header of Rx fragments */ -#define DBG_BSS_TABLE_RM 0x00800000 /* purging bss table entries */ -#define DBG_MONITOR_MODE 0x01000000 /* monitor mode */ -#define DBG_MIB 0x02000000 /* dump all MIBs on startup */ -#define DBG_MGMT_TIMER 0x04000000 /* dump mgmt_timer ops */ -#define DBG_WE_EVENTS 0x08000000 /* dump wireless events */ -#define DBG_FW 0x10000000 /* firmware download */ -#define DBG_DFU 0x20000000 /* device firmware upgrade */ -#define DBG_CMD 0x40000000 -#define DBG_MAC80211 0x80000000 - -#define DBG_DEFAULTS 0 - -/* Use our own dbg macro */ -#define at76_dbg(bits, format, arg...) \ - do { \ - if (at76_debug & (bits)) \ - printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \ - ## arg); \ - } while (0) - -#define at76_dbg_dump(bits, buf, len, format, arg...) \ - do { \ - if (at76_debug & (bits)) { \ - printk(KERN_DEBUG DRIVER_NAME ": " format "\n" , \ - ## arg); \ - print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, \ - buf, len); \ - } \ - } while (0) - -static uint at76_debug = DBG_DEFAULTS; - -/* Protect against concurrent firmware loading and parsing */ -static struct mutex fw_mutex; - -static struct fwentry firmwares[] = { - [0] = { "" }, - [BOARD_503_ISL3861] = { "atmel_at76c503-i3861.bin" }, - [BOARD_503_ISL3863] = { "atmel_at76c503-i3863.bin" }, - [BOARD_503] = { "atmel_at76c503-rfmd.bin" }, - [BOARD_503_ACC] = { "atmel_at76c503-rfmd-acc.bin" }, - [BOARD_505] = { "atmel_at76c505-rfmd.bin" }, - [BOARD_505_2958] = { "atmel_at76c505-rfmd2958.bin" }, - [BOARD_505A] = { "atmel_at76c505a-rfmd2958.bin" }, - [BOARD_505AMX] = { "atmel_at76c505amx-rfmd.bin" }, -}; - -#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops) - -static struct usb_device_id dev_table[] = { - /* - * at76c503-i3861 - */ - /* Generic AT76C503/3861 device */ - { USB_DEVICE(0x03eb, 0x7603), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Linksys WUSB11 v2.1/v2.6 */ - { USB_DEVICE(0x066b, 0x2211), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Netgear MA101 rev. A */ - { USB_DEVICE(0x0864, 0x4100), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Tekram U300C / Allnet ALL0193 */ - { USB_DEVICE(0x0b3b, 0x1612), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* HP HN210W J7801A */ - { USB_DEVICE(0x03f0, 0x011c), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Sitecom/Z-Com/Zyxel M4Y-750 */ - { USB_DEVICE(0x0cde, 0x0001), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Dynalink/Askey WLL013 (intersil) */ - { USB_DEVICE(0x069a, 0x0320), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* EZ connect 11Mpbs Wireless USB Adapter SMC2662W v1 */ - { USB_DEVICE(0x0d5c, 0xa001), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* BenQ AWL300 */ - { USB_DEVICE(0x04a5, 0x9000), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Addtron AWU-120, Compex WLU11 */ - { USB_DEVICE(0x05dd, 0xff31), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Intel AP310 AnyPoint II USB */ - { USB_DEVICE(0x8086, 0x0200), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Dynalink L11U */ - { USB_DEVICE(0x0d8e, 0x7100), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* Arescom WL-210, FCC id 07J-GL2411USB */ - { USB_DEVICE(0x0d8e, 0x7110), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* I-O DATA WN-B11/USB */ - { USB_DEVICE(0x04bb, 0x0919), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* BT Voyager 1010 */ - { USB_DEVICE(0x069a, 0x0821), USB_DEVICE_DATA(BOARD_503_ISL3861) }, - /* - * at76c503-i3863 - */ - /* Generic AT76C503/3863 device */ - { USB_DEVICE(0x03eb, 0x7604), USB_DEVICE_DATA(BOARD_503_ISL3863) }, - /* Samsung SWL-2100U */ - { USB_DEVICE(0x055d, 0xa000), USB_DEVICE_DATA(BOARD_503_ISL3863) }, - /* - * at76c503-rfmd - */ - /* Generic AT76C503/RFMD device */ - { USB_DEVICE(0x03eb, 0x7605), USB_DEVICE_DATA(BOARD_503) }, - /* Dynalink/Askey WLL013 (rfmd) */ - { USB_DEVICE(0x069a, 0x0321), USB_DEVICE_DATA(BOARD_503) }, - /* Linksys WUSB11 v2.6 */ - { USB_DEVICE(0x077b, 0x2219), USB_DEVICE_DATA(BOARD_503) }, - /* Network Everywhere NWU11B */ - { USB_DEVICE(0x077b, 0x2227), USB_DEVICE_DATA(BOARD_503) }, - /* Netgear MA101 rev. B */ - { USB_DEVICE(0x0864, 0x4102), USB_DEVICE_DATA(BOARD_503) }, - /* D-Link DWL-120 rev. E */ - { USB_DEVICE(0x2001, 0x3200), USB_DEVICE_DATA(BOARD_503) }, - /* Actiontec 802UAT1, HWU01150-01UK */ - { USB_DEVICE(0x1668, 0x7605), USB_DEVICE_DATA(BOARD_503) }, - /* AirVast W-Buddie WN210 */ - { USB_DEVICE(0x03eb, 0x4102), USB_DEVICE_DATA(BOARD_503) }, - /* Dick Smith Electronics XH1153 802.11b USB adapter */ - { USB_DEVICE(0x1371, 0x5743), USB_DEVICE_DATA(BOARD_503) }, - /* CNet CNUSB611 */ - { USB_DEVICE(0x1371, 0x0001), USB_DEVICE_DATA(BOARD_503) }, - /* FiberLine FL-WL200U */ - { USB_DEVICE(0x1371, 0x0002), USB_DEVICE_DATA(BOARD_503) }, - /* BenQ AWL400 USB stick */ - { USB_DEVICE(0x04a5, 0x9001), USB_DEVICE_DATA(BOARD_503) }, - /* 3Com 3CRSHEW696 */ - { USB_DEVICE(0x0506, 0x0a01), USB_DEVICE_DATA(BOARD_503) }, - /* Siemens Santis ADSL WLAN USB adapter WLL 013 */ - { USB_DEVICE(0x0681, 0x001b), USB_DEVICE_DATA(BOARD_503) }, - /* Belkin F5D6050, version 2 */ - { USB_DEVICE(0x050d, 0x0050), USB_DEVICE_DATA(BOARD_503) }, - /* iBlitzz, BWU613 (not *B or *SB) */ - { USB_DEVICE(0x07b8, 0xb000), USB_DEVICE_DATA(BOARD_503) }, - /* Gigabyte GN-WLBM101 */ - { USB_DEVICE(0x1044, 0x8003), USB_DEVICE_DATA(BOARD_503) }, - /* Planex GW-US11S */ - { USB_DEVICE(0x2019, 0x3220), USB_DEVICE_DATA(BOARD_503) }, - /* Internal WLAN adapter in h5[4,5]xx series iPAQs */ - { USB_DEVICE(0x049f, 0x0032), USB_DEVICE_DATA(BOARD_503) }, - /* Corega Wireless LAN USB-11 mini */ - { USB_DEVICE(0x07aa, 0x0011), USB_DEVICE_DATA(BOARD_503) }, - /* Corega Wireless LAN USB-11 mini2 */ - { USB_DEVICE(0x07aa, 0x0018), USB_DEVICE_DATA(BOARD_503) }, - /* Uniden PCW100 */ - { USB_DEVICE(0x05dd, 0xff35), USB_DEVICE_DATA(BOARD_503) }, - /* - * at76c503-rfmd-acc - */ - /* SMC2664W */ - { USB_DEVICE(0x083a, 0x3501), USB_DEVICE_DATA(BOARD_503_ACC) }, - /* Belkin F5D6050, SMC2662W v2, SMC2662W-AR */ - { USB_DEVICE(0x0d5c, 0xa002), USB_DEVICE_DATA(BOARD_503_ACC) }, - /* - * at76c505-rfmd - */ - /* Generic AT76C505/RFMD */ - { USB_DEVICE(0x03eb, 0x7606), USB_DEVICE_DATA(BOARD_505) }, - /* - * at76c505-rfmd2958 - */ - /* Generic AT76C505/RFMD, OvisLink WL-1130USB */ - { USB_DEVICE(0x03eb, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) }, - /* Fiberline FL-WL240U */ - { USB_DEVICE(0x1371, 0x0014), USB_DEVICE_DATA(BOARD_505_2958) }, - /* CNet CNUSB-611G */ - { USB_DEVICE(0x1371, 0x0013), USB_DEVICE_DATA(BOARD_505_2958) }, - /* Linksys WUSB11 v2.8 */ - { USB_DEVICE(0x1915, 0x2233), USB_DEVICE_DATA(BOARD_505_2958) }, - /* Xterasys XN-2122B, IBlitzz BWU613B/BWU613SB */ - { USB_DEVICE(0x12fd, 0x1001), USB_DEVICE_DATA(BOARD_505_2958) }, - /* Corega WLAN USB Stick 11 */ - { USB_DEVICE(0x07aa, 0x7613), USB_DEVICE_DATA(BOARD_505_2958) }, - /* Microstar MSI Box MS6978 */ - { USB_DEVICE(0x0db0, 0x1020), USB_DEVICE_DATA(BOARD_505_2958) }, - /* - * at76c505a-rfmd2958 - */ - /* Generic AT76C505A device */ - { USB_DEVICE(0x03eb, 0x7614), USB_DEVICE_DATA(BOARD_505A) }, - /* Generic AT76C505AS device */ - { USB_DEVICE(0x03eb, 0x7617), USB_DEVICE_DATA(BOARD_505A) }, - /* Siemens Gigaset USB WLAN Adapter 11 */ - { USB_DEVICE(0x1690, 0x0701), USB_DEVICE_DATA(BOARD_505A) }, - /* OQO Model 01+ Internal Wi-Fi */ - { USB_DEVICE(0x1557, 0x0002), USB_DEVICE_DATA(BOARD_505A) }, - /* - * at76c505amx-rfmd - */ - /* Generic AT76C505AMX device */ - { USB_DEVICE(0x03eb, 0x7615), USB_DEVICE_DATA(BOARD_505AMX) }, - { } -}; - -MODULE_DEVICE_TABLE(usb, dev_table); - -/* Supported rates of this hardware, bit 7 marks basic rates */ -static const u8 hw_rates[] = { 0x82, 0x84, 0x0b, 0x16 }; - -static const char *const preambles[] = { "long", "short", "auto" }; - -/* Firmware download */ -/* DFU states */ -#define STATE_IDLE 0x00 -#define STATE_DETACH 0x01 -#define STATE_DFU_IDLE 0x02 -#define STATE_DFU_DOWNLOAD_SYNC 0x03 -#define STATE_DFU_DOWNLOAD_BUSY 0x04 -#define STATE_DFU_DOWNLOAD_IDLE 0x05 -#define STATE_DFU_MANIFEST_SYNC 0x06 -#define STATE_DFU_MANIFEST 0x07 -#define STATE_DFU_MANIFEST_WAIT_RESET 0x08 -#define STATE_DFU_UPLOAD_IDLE 0x09 -#define STATE_DFU_ERROR 0x0a - -/* DFU commands */ -#define DFU_DETACH 0 -#define DFU_DNLOAD 1 -#define DFU_UPLOAD 2 -#define DFU_GETSTATUS 3 -#define DFU_CLRSTATUS 4 -#define DFU_GETSTATE 5 -#define DFU_ABORT 6 - -#define FW_BLOCK_SIZE 1024 - -struct dfu_status { - unsigned char status; - unsigned char poll_timeout[3]; - unsigned char state; - unsigned char string; -} __attribute__((packed)); - -static inline int at76_is_intersil(enum board_type board) -{ - return (board == BOARD_503_ISL3861 || board == BOARD_503_ISL3863); -} - -static inline int at76_is_503rfmd(enum board_type board) -{ - return (board == BOARD_503 || board == BOARD_503_ACC); -} - -static inline int at76_is_505a(enum board_type board) -{ - return (board == BOARD_505A || board == BOARD_505AMX); -} - -/* Load a block of the first (internal) part of the firmware */ -static int at76_load_int_fw_block(struct usb_device *udev, int blockno, - void *block, int size) -{ - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), DFU_DNLOAD, - USB_TYPE_CLASS | USB_DIR_OUT | - USB_RECIP_INTERFACE, blockno, 0, block, size, - USB_CTRL_GET_TIMEOUT); -} - -static int at76_dfu_get_status(struct usb_device *udev, - struct dfu_status *status) -{ - int ret; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATUS, - USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, - 0, 0, status, sizeof(struct dfu_status), - USB_CTRL_GET_TIMEOUT); - return ret; -} - -static u8 at76_dfu_get_state(struct usb_device *udev, u8 *state) -{ - int ret; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), DFU_GETSTATE, - USB_TYPE_CLASS | USB_DIR_IN | USB_RECIP_INTERFACE, - 0, 0, state, 1, USB_CTRL_GET_TIMEOUT); - return ret; -} - -/* Convert timeout from the DFU status to jiffies */ -static inline unsigned long at76_get_timeout(struct dfu_status *s) -{ - return msecs_to_jiffies((s->poll_timeout[2] << 16) - | (s->poll_timeout[1] << 8) - | (s->poll_timeout[0])); -} - -/* Load internal firmware from the buffer. If manifest_sync_timeout > 0, use - * its value in jiffies in the MANIFEST_SYNC state. */ -static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size, - int manifest_sync_timeout) -{ - u8 *block; - struct dfu_status dfu_stat_buf; - int ret = 0; - int need_dfu_state = 1; - int is_done = 0; - u8 dfu_state = 0; - u32 dfu_timeout = 0; - int bsize = 0; - int blockno = 0; - - at76_dbg(DBG_DFU, "%s( %p, %u, %d)", __func__, buf, size, - manifest_sync_timeout); - - if (!size) { - dev_printk(KERN_ERR, &udev->dev, "FW buffer length invalid!\n"); - return -EINVAL; - } - - block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL); - if (!block) - return -ENOMEM; - - do { - if (need_dfu_state) { - ret = at76_dfu_get_state(udev, &dfu_state); - if (ret < 0) { - dev_printk(KERN_ERR, &udev->dev, - "cannot get DFU state: %d\n", ret); - goto exit; - } - need_dfu_state = 0; - } - - switch (dfu_state) { - case STATE_DFU_DOWNLOAD_SYNC: - at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC"); - ret = at76_dfu_get_status(udev, &dfu_stat_buf); - if (ret >= 0) { - dfu_state = dfu_stat_buf.state; - dfu_timeout = at76_get_timeout(&dfu_stat_buf); - need_dfu_state = 0; - } else - dev_printk(KERN_ERR, &udev->dev, - "at76_dfu_get_status returned %d\n", - ret); - break; - - case STATE_DFU_DOWNLOAD_BUSY: - at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_BUSY"); - need_dfu_state = 1; - - at76_dbg(DBG_DFU, "DFU: Resetting device"); - schedule_timeout_interruptible(dfu_timeout); - break; - - case STATE_DFU_DOWNLOAD_IDLE: - at76_dbg(DBG_DFU, "DOWNLOAD..."); - /* fall through */ - case STATE_DFU_IDLE: - at76_dbg(DBG_DFU, "DFU IDLE"); - - bsize = min_t(int, size, FW_BLOCK_SIZE); - memcpy(block, buf, bsize); - at76_dbg(DBG_DFU, "int fw, size left = %5d, " - "bsize = %4d, blockno = %2d", size, bsize, - blockno); - ret = - at76_load_int_fw_block(udev, blockno, block, bsize); - buf += bsize; - size -= bsize; - blockno++; - - if (ret != bsize) - dev_printk(KERN_ERR, &udev->dev, - "at76_load_int_fw_block " - "returned %d\n", ret); - need_dfu_state = 1; - break; - - case STATE_DFU_MANIFEST_SYNC: - at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC"); - - ret = at76_dfu_get_status(udev, &dfu_stat_buf); - if (ret < 0) - break; - - dfu_state = dfu_stat_buf.state; - dfu_timeout = at76_get_timeout(&dfu_stat_buf); - need_dfu_state = 0; - - /* override the timeout from the status response, - needed for AT76C505A */ - if (manifest_sync_timeout > 0) - dfu_timeout = manifest_sync_timeout; - - at76_dbg(DBG_DFU, "DFU: Waiting for manifest phase"); - schedule_timeout_interruptible(dfu_timeout); - break; - - case STATE_DFU_MANIFEST: - at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST"); - is_done = 1; - break; - - case STATE_DFU_MANIFEST_WAIT_RESET: - at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_WAIT_RESET"); - is_done = 1; - break; - - case STATE_DFU_UPLOAD_IDLE: - at76_dbg(DBG_DFU, "STATE_DFU_UPLOAD_IDLE"); - break; - - case STATE_DFU_ERROR: - at76_dbg(DBG_DFU, "STATE_DFU_ERROR"); - ret = -EPIPE; - break; - - default: - at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state); - ret = -EINVAL; - break; - } - } while (!is_done && (ret >= 0)); - -exit: - kfree(block); - if (ret >= 0) - ret = 0; - - return ret; -} - -#define HEX2STR_BUFFERS 4 -#define HEX2STR_MAX_LEN 64 -#define BIN2HEX(x) ((x) < 10 ? '0' + (x) : (x) + 'A' - 10) - -/* Convert binary data into hex string */ -static char *hex2str(void *buf, int len) -{ - static atomic_t a = ATOMIC_INIT(0); - static char bufs[HEX2STR_BUFFERS][3 * HEX2STR_MAX_LEN + 1]; - char *ret = bufs[atomic_inc_return(&a) & (HEX2STR_BUFFERS - 1)]; - char *obuf = ret; - u8 *ibuf = buf; - - if (len > HEX2STR_MAX_LEN) - len = HEX2STR_MAX_LEN; - - if (len <= 0) { - ret[0] = '\0'; - return ret; - } - - while (len--) { - *obuf++ = BIN2HEX(*ibuf >> 4); - *obuf++ = BIN2HEX(*ibuf & 0xf); - *obuf++ = '-'; - ibuf++; - } - *(--obuf) = '\0'; - - return ret; -} - -#define MAC2STR_BUFFERS 4 - -static inline char *mac2str(u8 *mac) -{ - static atomic_t a = ATOMIC_INIT(0); - static char bufs[MAC2STR_BUFFERS][6 * 3]; - char *str; - - str = bufs[atomic_inc_return(&a) & (MAC2STR_BUFFERS - 1)]; - sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]); - return str; -} - -/* LED trigger */ -static int tx_activity; -static void at76_ledtrig_tx_timerfunc(unsigned long data); -static DEFINE_TIMER(ledtrig_tx_timer, at76_ledtrig_tx_timerfunc, 0, 0); -DEFINE_LED_TRIGGER(ledtrig_tx); - -static void at76_ledtrig_tx_timerfunc(unsigned long data) -{ - static int tx_lastactivity; - - if (tx_lastactivity != tx_activity) { - tx_lastactivity = tx_activity; - led_trigger_event(ledtrig_tx, LED_FULL); - mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4); - } else - led_trigger_event(ledtrig_tx, LED_OFF); -} - -static void at76_ledtrig_tx_activity(void) -{ - tx_activity++; - if (!timer_pending(&ledtrig_tx_timer)) - mod_timer(&ledtrig_tx_timer, jiffies + HZ / 4); -} - -static int at76_remap(struct usb_device *udev) -{ - int ret; - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0a, - USB_TYPE_VENDOR | USB_DIR_OUT | - USB_RECIP_INTERFACE, 0, 0, NULL, 0, - USB_CTRL_GET_TIMEOUT); - if (ret < 0) - return ret; - return 0; -} - -static int at76_get_op_mode(struct usb_device *udev) -{ - int ret; - u8 saved; - u8 *op_mode; - - op_mode = kmalloc(1, GFP_NOIO); - if (!op_mode) - return -ENOMEM; - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33, - USB_TYPE_VENDOR | USB_DIR_IN | - USB_RECIP_INTERFACE, 0x01, 0, op_mode, 1, - USB_CTRL_GET_TIMEOUT); - saved = *op_mode; - kfree(op_mode); - - if (ret < 0) - return ret; - else if (ret < 1) - return -EIO; - else - return saved; -} - -/* Load a block of the second ("external") part of the firmware */ -static inline int at76_load_ext_fw_block(struct usb_device *udev, int blockno, - void *block, int size) -{ - return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - 0x0802, blockno, block, size, - USB_CTRL_GET_TIMEOUT); -} - -static inline int at76_get_hw_cfg(struct usb_device *udev, - union at76_hwcfg *buf, int buf_size) -{ - return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33, - USB_TYPE_VENDOR | USB_DIR_IN | - USB_RECIP_INTERFACE, 0x0a02, 0, - buf, buf_size, USB_CTRL_GET_TIMEOUT); -} - -/* Intersil boards use a different "value" for GetHWConfig requests */ -static inline int at76_get_hw_cfg_intersil(struct usb_device *udev, - union at76_hwcfg *buf, int buf_size) -{ - return usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33, - USB_TYPE_VENDOR | USB_DIR_IN | - USB_RECIP_INTERFACE, 0x0902, 0, - buf, buf_size, USB_CTRL_GET_TIMEOUT); -} - -/* Get the hardware configuration for the adapter and put it to the appropriate - * fields of 'priv' (the GetHWConfig request and interpretation of the result - * depends on the board type) */ -static int at76_get_hw_config(struct at76_priv *priv) -{ - int ret; - union at76_hwcfg *hwcfg = kmalloc(sizeof(*hwcfg), GFP_KERNEL); - - if (!hwcfg) - return -ENOMEM; - - if (at76_is_intersil(priv->board_type)) { - ret = at76_get_hw_cfg_intersil(priv->udev, hwcfg, - sizeof(hwcfg->i)); - if (ret < 0) - goto exit; - memcpy(priv->mac_addr, hwcfg->i.mac_addr, ETH_ALEN); - priv->regulatory_domain = hwcfg->i.regulatory_domain; - } else if (at76_is_503rfmd(priv->board_type)) { - ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r3)); - if (ret < 0) - goto exit; - memcpy(priv->mac_addr, hwcfg->r3.mac_addr, ETH_ALEN); - priv->regulatory_domain = hwcfg->r3.regulatory_domain; - } else { - ret = at76_get_hw_cfg(priv->udev, hwcfg, sizeof(hwcfg->r5)); - if (ret < 0) - goto exit; - memcpy(priv->mac_addr, hwcfg->r5.mac_addr, ETH_ALEN); - priv->regulatory_domain = hwcfg->r5.regulatory_domain; - } - -exit: - kfree(hwcfg); - if (ret < 0) - printk(KERN_ERR "%s: cannot get HW Config (error %d)\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static struct reg_domain const *at76_get_reg_domain(u16 code) -{ - int i; - static struct reg_domain const fd_tab[] = { - { 0x10, "FCC (USA)", 0x7ff }, /* ch 1-11 */ - { 0x20, "IC (Canada)", 0x7ff }, /* ch 1-11 */ - { 0x30, "ETSI (most of Europe)", 0x1fff }, /* ch 1-13 */ - { 0x31, "Spain", 0x600 }, /* ch 10-11 */ - { 0x32, "France", 0x1e00 }, /* ch 10-13 */ - { 0x40, "MKK (Japan)", 0x2000 }, /* ch 14 */ - { 0x41, "MKK1 (Japan)", 0x3fff }, /* ch 1-14 */ - { 0x50, "Israel", 0x3fc }, /* ch 3-9 */ - { 0x00, "", 0xffffffff } /* ch 1-32 */ - }; - - /* Last entry is fallback for unknown domain code */ - for (i = 0; i < ARRAY_SIZE(fd_tab) - 1; i++) - if (code == fd_tab[i].code) - break; - - return &fd_tab[i]; -} - -static inline int at76_get_mib(struct usb_device *udev, u16 mib, void *buf, - int buf_size) -{ - int ret; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x33, - USB_TYPE_VENDOR | USB_DIR_IN | - USB_RECIP_INTERFACE, mib << 8, 0, buf, buf_size, - USB_CTRL_GET_TIMEOUT); - if (ret >= 0 && ret != buf_size) - return -EIO; - return ret; -} - -/* Return positive number for status, negative for an error */ -static inline int at76_get_cmd_status(struct usb_device *udev, u8 cmd) -{ - u8 *stat_buf; - int ret; - - stat_buf = kmalloc(40, GFP_NOIO); - if (!stat_buf) - return -ENOMEM; - - ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x22, - USB_TYPE_VENDOR | USB_DIR_IN | - USB_RECIP_INTERFACE, cmd, 0, stat_buf, - 40, USB_CTRL_GET_TIMEOUT); - if (ret >= 0) - ret = stat_buf[5]; - kfree(stat_buf); - - return ret; -} - -#define MAKE_CMD_CASE(c) case (c): return #c -static const char *at76_get_cmd_string(u8 cmd_status) -{ - switch (cmd_status) { - MAKE_CMD_CASE(CMD_SET_MIB); - MAKE_CMD_CASE(CMD_GET_MIB); - MAKE_CMD_CASE(CMD_SCAN); - MAKE_CMD_CASE(CMD_JOIN); - MAKE_CMD_CASE(CMD_START_IBSS); - MAKE_CMD_CASE(CMD_RADIO_ON); - MAKE_CMD_CASE(CMD_RADIO_OFF); - MAKE_CMD_CASE(CMD_STARTUP); - } - - return "UNKNOWN"; -} - -static int at76_set_card_command(struct usb_device *udev, u8 cmd, void *buf, - int buf_size) -{ - int ret; - struct at76_command *cmd_buf = kmalloc(sizeof(struct at76_command) + - buf_size, GFP_KERNEL); - - if (!cmd_buf) - return -ENOMEM; - - cmd_buf->cmd = cmd; - cmd_buf->reserved = 0; - cmd_buf->size = cpu_to_le16(buf_size); - memcpy(cmd_buf->data, buf, buf_size); - - at76_dbg_dump(DBG_CMD, cmd_buf, sizeof(struct at76_command) + buf_size, - "issuing command %s (0x%02x)", - at76_get_cmd_string(cmd), cmd); - - ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x0e, - USB_TYPE_VENDOR | USB_DIR_OUT | USB_RECIP_DEVICE, - 0, 0, cmd_buf, - sizeof(struct at76_command) + buf_size, - USB_CTRL_GET_TIMEOUT); - kfree(cmd_buf); - return ret; -} - -#define MAKE_CMD_STATUS_CASE(c) case (c): return #c -static const char *at76_get_cmd_status_string(u8 cmd_status) -{ - switch (cmd_status) { - MAKE_CMD_STATUS_CASE(CMD_STATUS_IDLE); - MAKE_CMD_STATUS_CASE(CMD_STATUS_COMPLETE); - MAKE_CMD_STATUS_CASE(CMD_STATUS_UNKNOWN); - MAKE_CMD_STATUS_CASE(CMD_STATUS_INVALID_PARAMETER); - MAKE_CMD_STATUS_CASE(CMD_STATUS_FUNCTION_NOT_SUPPORTED); - MAKE_CMD_STATUS_CASE(CMD_STATUS_TIME_OUT); - MAKE_CMD_STATUS_CASE(CMD_STATUS_IN_PROGRESS); - MAKE_CMD_STATUS_CASE(CMD_STATUS_HOST_FAILURE); - MAKE_CMD_STATUS_CASE(CMD_STATUS_SCAN_FAILED); - } - - return "UNKNOWN"; -} - -/* Wait until the command is completed */ -static int at76_wait_completion(struct at76_priv *priv, int cmd) -{ - int status = 0; - unsigned long timeout = jiffies + CMD_COMPLETION_TIMEOUT; - - do { - status = at76_get_cmd_status(priv->udev, cmd); - if (status < 0) { - printk(KERN_ERR "%s: at76_get_cmd_status failed: %d\n", - wiphy_name(priv->hw->wiphy), status); - break; - } - - at76_dbg(DBG_WAIT_COMPLETE, - "%s: Waiting on cmd %d, status = %d (%s)", - wiphy_name(priv->hw->wiphy), cmd, status, - at76_get_cmd_status_string(status)); - - if (status != CMD_STATUS_IN_PROGRESS - && status != CMD_STATUS_IDLE) - break; - - schedule_timeout_interruptible(HZ / 10); /* 100 ms */ - if (time_after(jiffies, timeout)) { - printk(KERN_ERR - "%s: completion timeout for command %d\n", - wiphy_name(priv->hw->wiphy), cmd); - status = -ETIMEDOUT; - break; - } - } while (1); - - return status; -} - -static int at76_set_mib(struct at76_priv *priv, struct set_mib_buffer *buf) -{ - int ret; - - ret = at76_set_card_command(priv->udev, CMD_SET_MIB, buf, - offsetof(struct set_mib_buffer, - data) + buf->size); - if (ret < 0) - return ret; - - ret = at76_wait_completion(priv, CMD_SET_MIB); - if (ret != CMD_STATUS_COMPLETE) { - printk(KERN_INFO - "%s: set_mib: at76_wait_completion failed " - "with %d\n", wiphy_name(priv->hw->wiphy), ret); - ret = -EIO; - } - - return ret; -} - -/* Return < 0 on error, == 0 if no command sent, == 1 if cmd sent */ -static int at76_set_radio(struct at76_priv *priv, int enable) -{ - int ret; - int cmd; - - if (priv->radio_on == enable) - return 0; - - cmd = enable ? CMD_RADIO_ON : CMD_RADIO_OFF; - - ret = at76_set_card_command(priv->udev, cmd, NULL, 0); - if (ret < 0) - printk(KERN_ERR "%s: at76_set_card_command(%d) failed: %d\n", - wiphy_name(priv->hw->wiphy), cmd, ret); - else - ret = 1; - - priv->radio_on = enable; - return ret; -} - -/* Set current power save mode (AT76_PM_OFF/AT76_PM_ON/AT76_PM_SMART) */ -static int at76_set_pm_mode(struct at76_priv *priv) -{ - int ret = 0; - - priv->mib_buf.type = MIB_MAC_MGMT; - priv->mib_buf.size = 1; - priv->mib_buf.index = offsetof(struct mib_mac_mgmt, power_mgmt_mode); - priv->mib_buf.data.byte = priv->pm_mode; - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (pm_mode) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static int at76_set_preamble(struct at76_priv *priv, u8 type) -{ - int ret = 0; - - priv->mib_buf.type = MIB_LOCAL; - priv->mib_buf.size = 1; - priv->mib_buf.index = offsetof(struct mib_local, preamble_type); - priv->mib_buf.data.byte = type; - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (preamble) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static int at76_set_frag(struct at76_priv *priv, u16 size) -{ - int ret = 0; - - priv->mib_buf.type = MIB_MAC; - priv->mib_buf.size = 2; - priv->mib_buf.index = offsetof(struct mib_mac, frag_threshold); - priv->mib_buf.data.word = cpu_to_le16(size); - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (frag threshold) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static int at76_set_rts(struct at76_priv *priv, u16 size) -{ - int ret = 0; - - priv->mib_buf.type = MIB_MAC; - priv->mib_buf.size = 2; - priv->mib_buf.index = offsetof(struct mib_mac, rts_threshold); - priv->mib_buf.data.word = cpu_to_le16(size); - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (rts) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static int at76_set_autorate_fallback(struct at76_priv *priv, int onoff) -{ - int ret = 0; - - priv->mib_buf.type = MIB_LOCAL; - priv->mib_buf.size = 1; - priv->mib_buf.index = offsetof(struct mib_local, txautorate_fallback); - priv->mib_buf.data.byte = onoff; - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (autorate fallback) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - return ret; -} - -static void at76_dump_mib_mac_addr(struct at76_priv *priv) -{ - int i; - int ret; - struct mib_mac_addr *m = kmalloc(sizeof(struct mib_mac_addr), - GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_MAC_ADDR, m, - sizeof(struct mib_mac_addr)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC_ADDR) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: mac_addr %s res 0x%x 0x%x", - wiphy_name(priv->hw->wiphy), - mac2str(m->mac_addr), m->res[0], m->res[1]); - for (i = 0; i < ARRAY_SIZE(m->group_addr); i++) - at76_dbg(DBG_MIB, "%s: MIB MAC_ADDR: group addr %d: %s, " - "status %d", wiphy_name(priv->hw->wiphy), i, - mac2str(m->group_addr[i]), m->group_addr_status[i]); -exit: - kfree(m); -} - -static void at76_dump_mib_mac_wep(struct at76_priv *priv) -{ - int i; - int ret; - int key_len; - struct mib_mac_wep *m = kmalloc(sizeof(struct mib_mac_wep), GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_MAC_WEP, m, - sizeof(struct mib_mac_wep)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC_WEP) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: priv_invoked %u def_key_id %u " - "key_len %u excl_unencr %u wep_icv_err %u wep_excluded %u " - "encr_level %u key %d", wiphy_name(priv->hw->wiphy), - m->privacy_invoked, m->wep_default_key_id, - m->wep_key_mapping_len, m->exclude_unencrypted, - le32_to_cpu(m->wep_icv_error_count), - le32_to_cpu(m->wep_excluded_count), m->encryption_level, - m->wep_default_key_id); - - key_len = (m->encryption_level == 1) ? - WEP_SMALL_KEY_LEN : WEP_LARGE_KEY_LEN; - - for (i = 0; i < WEP_KEYS; i++) - at76_dbg(DBG_MIB, "%s: MIB MAC_WEP: key %d: %s", - wiphy_name(priv->hw->wiphy), i, - hex2str(m->wep_default_keyvalue[i], key_len)); -exit: - kfree(m); -} - -static void at76_dump_mib_mac_mgmt(struct at76_priv *priv) -{ - int ret; - struct mib_mac_mgmt *m = kmalloc(sizeof(struct mib_mac_mgmt), - GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_MAC_MGMT, m, - sizeof(struct mib_mac_mgmt)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC_MGMT) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB MAC_MGMT: beacon_period %d CFP_max_duration " - "%d medium_occupancy_limit %d station_id 0x%x ATIM_window %d " - "CFP_mode %d privacy_opt_impl %d DTIM_period %d CFP_period %d " - "current_bssid %s current_essid %s current_bss_type %d " - "pm_mode %d ibss_change %d res %d " - "multi_domain_capability_implemented %d " - "international_roaming %d country_string %.3s", - wiphy_name(priv->hw->wiphy), le16_to_cpu(m->beacon_period), - le16_to_cpu(m->CFP_max_duration), - le16_to_cpu(m->medium_occupancy_limit), - le16_to_cpu(m->station_id), le16_to_cpu(m->ATIM_window), - m->CFP_mode, m->privacy_option_implemented, m->DTIM_period, - m->CFP_period, mac2str(m->current_bssid), - hex2str(m->current_essid, IW_ESSID_MAX_SIZE), - m->current_bss_type, m->power_mgmt_mode, m->ibss_change, - m->res, m->multi_domain_capability_implemented, - m->multi_domain_capability_enabled, m->country_string); -exit: - kfree(m); -} - -static void at76_dump_mib_mac(struct at76_priv *priv) -{ - int ret; - struct mib_mac *m = kmalloc(sizeof(struct mib_mac), GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_MAC, m, sizeof(struct mib_mac)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MAC) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB MAC: max_tx_msdu_lifetime %d " - "max_rx_lifetime %d frag_threshold %d rts_threshold %d " - "cwmin %d cwmax %d short_retry_time %d long_retry_time %d " - "scan_type %d scan_channel %d probe_delay %u " - "min_channel_time %d max_channel_time %d listen_int %d " - "desired_ssid %s desired_bssid %s desired_bsstype %d", - wiphy_name(priv->hw->wiphy), - le32_to_cpu(m->max_tx_msdu_lifetime), - le32_to_cpu(m->max_rx_lifetime), - le16_to_cpu(m->frag_threshold), le16_to_cpu(m->rts_threshold), - le16_to_cpu(m->cwmin), le16_to_cpu(m->cwmax), - m->short_retry_time, m->long_retry_time, m->scan_type, - m->scan_channel, le16_to_cpu(m->probe_delay), - le16_to_cpu(m->min_channel_time), - le16_to_cpu(m->max_channel_time), - le16_to_cpu(m->listen_interval), - hex2str(m->desired_ssid, IW_ESSID_MAX_SIZE), - mac2str(m->desired_bssid), m->desired_bsstype); -exit: - kfree(m); -} - -static void at76_dump_mib_phy(struct at76_priv *priv) -{ - int ret; - struct mib_phy *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_PHY, m, sizeof(struct mib_phy)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (PHY) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB PHY: ed_threshold %d slot_time %d " - "sifs_time %d preamble_length %d plcp_header_length %d " - "mpdu_max_length %d cca_mode_supported %d operation_rate_set " - "0x%x 0x%x 0x%x 0x%x channel_id %d current_cca_mode %d " - "phy_type %d current_reg_domain %d", - wiphy_name(priv->hw->wiphy), le32_to_cpu(m->ed_threshold), - le16_to_cpu(m->slot_time), le16_to_cpu(m->sifs_time), - le16_to_cpu(m->preamble_length), - le16_to_cpu(m->plcp_header_length), - le16_to_cpu(m->mpdu_max_length), - le16_to_cpu(m->cca_mode_supported), m->operation_rate_set[0], - m->operation_rate_set[1], m->operation_rate_set[2], - m->operation_rate_set[3], m->channel_id, m->current_cca_mode, - m->phy_type, m->current_reg_domain); -exit: - kfree(m); -} - -static void at76_dump_mib_local(struct at76_priv *priv) -{ - int ret; - struct mib_local *m = kmalloc(sizeof(struct mib_phy), GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_LOCAL, m, sizeof(struct mib_local)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (LOCAL) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB LOCAL: beacon_enable %d " - "txautorate_fallback %d ssid_size %d promiscuous_mode %d " - "preamble_type %d", wiphy_name(priv->hw->wiphy), - m->beacon_enable, - m->txautorate_fallback, m->ssid_size, m->promiscuous_mode, - m->preamble_type); -exit: - kfree(m); -} - -static void at76_dump_mib_mdomain(struct at76_priv *priv) -{ - int ret; - struct mib_mdomain *m = kmalloc(sizeof(struct mib_mdomain), GFP_KERNEL); - - if (!m) - return; - - ret = at76_get_mib(priv->udev, MIB_MDOMAIN, m, - sizeof(struct mib_mdomain)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_get_mib (MDOMAIN) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto exit; - } - - at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: channel_list %s", - wiphy_name(priv->hw->wiphy), - hex2str(m->channel_list, sizeof(m->channel_list))); - - at76_dbg(DBG_MIB, "%s: MIB MDOMAIN: tx_powerlevel %s", - wiphy_name(priv->hw->wiphy), - hex2str(m->tx_powerlevel, sizeof(m->tx_powerlevel))); -exit: - kfree(m); -} - -/* Enable monitor mode */ -static int at76_start_monitor(struct at76_priv *priv) -{ - struct at76_req_scan scan; - int ret; - - memset(&scan, 0, sizeof(struct at76_req_scan)); - memset(scan.bssid, 0xff, ETH_ALEN); - - scan.channel = priv->channel; - scan.scan_type = SCAN_TYPE_PASSIVE; - scan.international_scan = 0; - - ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan)); - if (ret >= 0) - ret = at76_get_cmd_status(priv->udev, CMD_SCAN); - - return ret; -} - -/* Calculate padding from txbuf->wlength (which excludes the USB TX header), - likely to compensate a flaw in the AT76C503A USB part ... */ -static inline int at76_calc_padding(int wlen) -{ - /* add the USB TX header */ - wlen += AT76_TX_HDRLEN; - - wlen = wlen % 64; - - if (wlen < 50) - return 50 - wlen; - - if (wlen >= 61) - return 64 + 50 - wlen; - - return 0; -} - -static void at76_rx_callback(struct urb *urb) -{ - struct at76_priv *priv = urb->context; - - priv->rx_tasklet.data = (unsigned long)urb; - tasklet_schedule(&priv->rx_tasklet); - return; -} - -static int at76_submit_rx_urb(struct at76_priv *priv) -{ - int ret; - int size; - struct sk_buff *skb = priv->rx_skb; - - if (!priv->rx_urb) { - printk(KERN_ERR "%s: %s: priv->rx_urb is NULL\n", - wiphy_name(priv->hw->wiphy), __func__); - return -EFAULT; - } - - if (!skb) { - skb = dev_alloc_skb(sizeof(struct at76_rx_buffer)); - if (!skb) { - printk(KERN_ERR "%s: cannot allocate rx skbuff\n", - wiphy_name(priv->hw->wiphy)); - ret = -ENOMEM; - goto exit; - } - priv->rx_skb = skb; - } else { - skb_push(skb, skb_headroom(skb)); - skb_trim(skb, 0); - } - - size = skb_tailroom(skb); - usb_fill_bulk_urb(priv->rx_urb, priv->udev, priv->rx_pipe, - skb_put(skb, size), size, at76_rx_callback, priv); - ret = usb_submit_urb(priv->rx_urb, GFP_ATOMIC); - if (ret < 0) { - if (ret == -ENODEV) - at76_dbg(DBG_DEVSTART, - "usb_submit_urb returned -ENODEV"); - else - printk(KERN_ERR "%s: rx, usb_submit_urb failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - } - -exit: - if (ret < 0 && ret != -ENODEV) - printk(KERN_ERR "%s: cannot submit rx urb - please unload the " - "driver and/or power cycle the device\n", - wiphy_name(priv->hw->wiphy)); - - return ret; -} - -/* Download external firmware */ -static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe) -{ - int ret; - int op_mode; - int blockno = 0; - int bsize; - u8 *block; - u8 *buf = fwe->extfw; - int size = fwe->extfw_size; - - if (!buf || !size) - return -ENOENT; - - op_mode = at76_get_op_mode(udev); - at76_dbg(DBG_DEVSTART, "opmode %d", op_mode); - - if (op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) { - dev_printk(KERN_ERR, &udev->dev, "unexpected opmode %d\n", - op_mode); - return -EINVAL; - } - - block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL); - if (!block) - return -ENOMEM; - - at76_dbg(DBG_DEVSTART, "downloading external firmware"); - - /* for fw >= 0.100, the device needs an extra empty block */ - do { - bsize = min_t(int, size, FW_BLOCK_SIZE); - memcpy(block, buf, bsize); - at76_dbg(DBG_DEVSTART, - "ext fw, size left = %5d, bsize = %4d, blockno = %2d", - size, bsize, blockno); - ret = at76_load_ext_fw_block(udev, blockno, block, bsize); - if (ret != bsize) { - dev_printk(KERN_ERR, &udev->dev, - "loading %dth firmware block failed: %d\n", - blockno, ret); - goto exit; - } - buf += bsize; - size -= bsize; - blockno++; - } while (bsize > 0); - - if (at76_is_505a(fwe->board_type)) { - at76_dbg(DBG_DEVSTART, "200 ms delay for 505a"); - schedule_timeout_interruptible(HZ / 5 + 1); - } - -exit: - kfree(block); - if (ret < 0) - dev_printk(KERN_ERR, &udev->dev, - "downloading external firmware failed: %d\n", ret); - return ret; -} - -/* Download internal firmware */ -static int at76_load_internal_fw(struct usb_device *udev, struct fwentry *fwe) -{ - int ret; - int need_remap = !at76_is_505a(fwe->board_type); - - ret = at76_usbdfu_download(udev, fwe->intfw, fwe->intfw_size, - need_remap ? 0 : 2 * HZ); - - if (ret < 0) { - dev_printk(KERN_ERR, &udev->dev, - "downloading internal fw failed with %d\n", ret); - goto exit; - } - - at76_dbg(DBG_DEVSTART, "sending REMAP"); - - /* no REMAP for 505A (see SF driver) */ - if (need_remap) { - ret = at76_remap(udev); - if (ret < 0) { - dev_printk(KERN_ERR, &udev->dev, - "sending REMAP failed with %d\n", ret); - goto exit; - } - } - - at76_dbg(DBG_DEVSTART, "sleeping for 2 seconds"); - schedule_timeout_interruptible(2 * HZ + 1); - usb_reset_device(udev); - -exit: - return ret; -} - -static int at76_startup_device(struct at76_priv *priv) -{ - struct at76_card_config *ccfg = &priv->card_config; - int ret; - - at76_dbg(DBG_PARAMS, - "%s param: ssid %.*s (%s) mode %s ch %d wep %s key %d " - "keylen %d", wiphy_name(priv->hw->wiphy), priv->essid_size, - priv->essid, hex2str(priv->essid, IW_ESSID_MAX_SIZE), - priv->iw_mode == IW_MODE_ADHOC ? "adhoc" : "infra", - priv->channel, priv->wep_enabled ? "enabled" : "disabled", - priv->wep_key_id, priv->wep_keys_len[priv->wep_key_id]); - at76_dbg(DBG_PARAMS, - "%s param: preamble %s rts %d retry %d frag %d " - "txrate %s auth_mode %d", wiphy_name(priv->hw->wiphy), - preambles[priv->preamble_type], priv->rts_threshold, - priv->short_retry_limit, priv->frag_threshold, - priv->txrate == TX_RATE_1MBIT ? "1MBit" : priv->txrate == - TX_RATE_2MBIT ? "2MBit" : priv->txrate == - TX_RATE_5_5MBIT ? "5.5MBit" : priv->txrate == - TX_RATE_11MBIT ? "11MBit" : priv->txrate == - TX_RATE_AUTO ? "auto" : "", priv->auth_mode); - at76_dbg(DBG_PARAMS, - "%s param: pm_mode %d pm_period %d auth_mode %s " - "scan_times %d %d scan_mode %s", - wiphy_name(priv->hw->wiphy), priv->pm_mode, priv->pm_period, - priv->auth_mode == WLAN_AUTH_OPEN ? "open" : "shared_secret", - priv->scan_min_time, priv->scan_max_time, - priv->scan_mode == SCAN_TYPE_ACTIVE ? "active" : "passive"); - - memset(ccfg, 0, sizeof(struct at76_card_config)); - ccfg->promiscuous_mode = 0; - ccfg->short_retry_limit = priv->short_retry_limit; - - if (priv->wep_enabled) { - if (priv->wep_keys_len[priv->wep_key_id] > WEP_SMALL_KEY_LEN) - ccfg->encryption_type = 2; - else - ccfg->encryption_type = 1; - - /* jal: always exclude unencrypted if WEP is active */ - ccfg->exclude_unencrypted = 1; - } else { - ccfg->exclude_unencrypted = 0; - ccfg->encryption_type = 0; - } - - ccfg->rts_threshold = cpu_to_le16(priv->rts_threshold); - ccfg->fragmentation_threshold = cpu_to_le16(priv->frag_threshold); - - memcpy(ccfg->basic_rate_set, hw_rates, 4); - /* jal: really needed, we do a set_mib for autorate later ??? */ - ccfg->auto_rate_fallback = (priv->txrate == TX_RATE_AUTO ? 1 : 0); - ccfg->channel = priv->channel; - ccfg->privacy_invoked = priv->wep_enabled; - memcpy(ccfg->current_ssid, priv->essid, IW_ESSID_MAX_SIZE); - ccfg->ssid_len = priv->essid_size; - - ccfg->wep_default_key_id = priv->wep_key_id; - memcpy(ccfg->wep_default_key_value, priv->wep_keys, - sizeof(priv->wep_keys)); - - ccfg->short_preamble = priv->preamble_type; - ccfg->beacon_period = cpu_to_le16(priv->beacon_period); - - ret = at76_set_card_command(priv->udev, CMD_STARTUP, &priv->card_config, - sizeof(struct at76_card_config)); - if (ret < 0) { - printk(KERN_ERR "%s: at76_set_card_command failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - return ret; - } - - at76_wait_completion(priv, CMD_STARTUP); - - /* remove BSSID from previous run */ - memset(priv->bssid, 0, ETH_ALEN); - - if (at76_set_radio(priv, 1) == 1) - at76_wait_completion(priv, CMD_RADIO_ON); - - ret = at76_set_preamble(priv, priv->preamble_type); - if (ret < 0) - return ret; - - ret = at76_set_frag(priv, priv->frag_threshold); - if (ret < 0) - return ret; - - ret = at76_set_rts(priv, priv->rts_threshold); - if (ret < 0) - return ret; - - ret = at76_set_autorate_fallback(priv, - priv->txrate == TX_RATE_AUTO ? 1 : 0); - if (ret < 0) - return ret; - - ret = at76_set_pm_mode(priv); - if (ret < 0) - return ret; - - if (at76_debug & DBG_MIB) { - at76_dump_mib_mac(priv); - at76_dump_mib_mac_addr(priv); - at76_dump_mib_mac_mgmt(priv); - at76_dump_mib_mac_wep(priv); - at76_dump_mib_mdomain(priv); - at76_dump_mib_phy(priv); - at76_dump_mib_local(priv); - } - - return 0; -} - -/* Enable or disable promiscuous mode */ -static void at76_work_set_promisc(struct work_struct *work) -{ - struct at76_priv *priv = container_of(work, struct at76_priv, - work_set_promisc); - int ret = 0; - - if (priv->device_unplugged) - return; - - mutex_lock(&priv->mtx); - - priv->mib_buf.type = MIB_LOCAL; - priv->mib_buf.size = 1; - priv->mib_buf.index = offsetof(struct mib_local, promiscuous_mode); - priv->mib_buf.data.byte = priv->promisc ? 1 : 0; - - ret = at76_set_mib(priv, &priv->mib_buf); - if (ret < 0) - printk(KERN_ERR "%s: set_mib (promiscuous_mode) failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - - mutex_unlock(&priv->mtx); -} - -/* Submit Rx urb back to the device */ -static void at76_work_submit_rx(struct work_struct *work) -{ - struct at76_priv *priv = container_of(work, struct at76_priv, - work_submit_rx); - - mutex_lock(&priv->mtx); - at76_submit_rx_urb(priv); - mutex_unlock(&priv->mtx); -} - -static void at76_rx_tasklet(unsigned long param) -{ - struct urb *urb = (struct urb *)param; - struct at76_priv *priv = urb->context; - struct at76_rx_buffer *buf; - struct ieee80211_rx_status rx_status = { 0 }; - - if (priv->device_unplugged) { - at76_dbg(DBG_DEVSTART, "device unplugged"); - if (urb) - at76_dbg(DBG_DEVSTART, "urb status %d", urb->status); - return; - } - - if (!priv->rx_skb || !priv->rx_skb->data) - return; - - buf = (struct at76_rx_buffer *)priv->rx_skb->data; - - if (urb->status != 0) { - if (urb->status != -ENOENT && urb->status != -ECONNRESET) - at76_dbg(DBG_URB, - "%s %s: - nonzero Rx bulk status received: %d", - __func__, wiphy_name(priv->hw->wiphy), - urb->status); - return; - } - - at76_dbg(DBG_RX_ATMEL_HDR, - "%s: rx frame: rate %d rssi %d noise %d link %d", - wiphy_name(priv->hw->wiphy), buf->rx_rate, buf->rssi, - buf->noise_level, buf->link_quality); - - skb_pull(priv->rx_skb, AT76_RX_HDRLEN); - skb_trim(priv->rx_skb, le16_to_cpu(buf->wlength)); - at76_dbg_dump(DBG_RX_DATA, priv->rx_skb->data, - priv->rx_skb->len, "RX: len=%d", priv->rx_skb->len); - - rx_status.signal = buf->rssi; - rx_status.flag |= RX_FLAG_DECRYPTED; - rx_status.flag |= RX_FLAG_IV_STRIPPED; - - at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d", - priv->rx_skb->len, priv->rx_skb->data_len); - memcpy(IEEE80211_SKB_RXCB(priv->rx_skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(priv->hw, priv->rx_skb); - - /* Use a new skb for the next receive */ - priv->rx_skb = NULL; - - at76_submit_rx_urb(priv); -} - -/* Load firmware into kernel memory and parse it */ -static struct fwentry *at76_load_firmware(struct usb_device *udev, - enum board_type board_type) -{ - int ret; - char *str; - struct at76_fw_header *fwh; - struct fwentry *fwe = &firmwares[board_type]; - - mutex_lock(&fw_mutex); - - if (fwe->loaded) { - at76_dbg(DBG_FW, "re-using previously loaded fw"); - goto exit; - } - - at76_dbg(DBG_FW, "downloading firmware %s", fwe->fwname); - ret = request_firmware(&fwe->fw, fwe->fwname, &udev->dev); - if (ret < 0) { - dev_printk(KERN_ERR, &udev->dev, "firmware %s not found!\n", - fwe->fwname); - dev_printk(KERN_ERR, &udev->dev, - "you may need to download the firmware from " - "http://developer.berlios.de/projects/at76c503a/\n"); - goto exit; - } - - at76_dbg(DBG_FW, "got it."); - fwh = (struct at76_fw_header *)(fwe->fw->data); - - if (fwe->fw->size <= sizeof(*fwh)) { - dev_printk(KERN_ERR, &udev->dev, - "firmware is too short (0x%zx)\n", fwe->fw->size); - goto exit; - } - - /* CRC currently not checked */ - fwe->board_type = le32_to_cpu(fwh->board_type); - if (fwe->board_type != board_type) { - dev_printk(KERN_ERR, &udev->dev, - "board type mismatch, requested %u, got %u\n", - board_type, fwe->board_type); - goto exit; - } - - fwe->fw_version.major = fwh->major; - fwe->fw_version.minor = fwh->minor; - fwe->fw_version.patch = fwh->patch; - fwe->fw_version.build = fwh->build; - - str = (char *)fwh + le32_to_cpu(fwh->str_offset); - fwe->intfw = (u8 *)fwh + le32_to_cpu(fwh->int_fw_offset); - fwe->intfw_size = le32_to_cpu(fwh->int_fw_len); - fwe->extfw = (u8 *)fwh + le32_to_cpu(fwh->ext_fw_offset); - fwe->extfw_size = le32_to_cpu(fwh->ext_fw_len); - - fwe->loaded = 1; - - dev_printk(KERN_DEBUG, &udev->dev, - "using firmware %s (version %d.%d.%d-%d)\n", - fwe->fwname, fwh->major, fwh->minor, fwh->patch, fwh->build); - - at76_dbg(DBG_DEVSTART, "board %u, int %d:%d, ext %d:%d", board_type, - le32_to_cpu(fwh->int_fw_offset), le32_to_cpu(fwh->int_fw_len), - le32_to_cpu(fwh->ext_fw_offset), le32_to_cpu(fwh->ext_fw_len)); - at76_dbg(DBG_DEVSTART, "firmware id %s", str); - -exit: - mutex_unlock(&fw_mutex); - - if (fwe->loaded) - return fwe; - else - return NULL; -} - -static void at76_mac80211_tx_callback(struct urb *urb) -{ - struct at76_priv *priv = urb->context; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb); - - at76_dbg(DBG_MAC80211, "%s()", __func__); - - switch (urb->status) { - case 0: - /* success */ - info->flags |= IEEE80211_TX_STAT_ACK; - break; - case -ENOENT: - case -ECONNRESET: - /* fail, urb has been unlinked */ - /* FIXME: add error message */ - break; - default: - at76_dbg(DBG_URB, "%s - nonzero tx status received: %d", - __func__, urb->status); - break; - } - - memset(&info->status, 0, sizeof(info->status)); - - ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb); - - priv->tx_skb = NULL; - - ieee80211_wake_queues(priv->hw); -} - -static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct at76_priv *priv = hw->priv; - struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int padding, submit_len, ret; - - at76_dbg(DBG_MAC80211, "%s()", __func__); - - if (priv->tx_urb->status == -EINPROGRESS) { - printk(KERN_ERR "%s: %s called while tx urb is pending\n", - wiphy_name(priv->hw->wiphy), __func__); - return NETDEV_TX_BUSY; - } - - ieee80211_stop_queues(hw); - - at76_ledtrig_tx_activity(); /* tell ledtrigger we send a packet */ - - WARN_ON(priv->tx_skb != NULL); - - priv->tx_skb = skb; - padding = at76_calc_padding(skb->len); - submit_len = AT76_TX_HDRLEN + skb->len + padding; - - /* setup 'Atmel' header */ - memset(tx_buffer, 0, sizeof(*tx_buffer)); - tx_buffer->padding = padding; - tx_buffer->wlength = cpu_to_le16(skb->len); - tx_buffer->tx_rate = ieee80211_get_tx_rate(hw, info)->hw_value; - memset(tx_buffer->reserved, 0, sizeof(tx_buffer->reserved)); - memcpy(tx_buffer->packet, skb->data, skb->len); - - at76_dbg(DBG_TX_DATA, "%s tx: wlen 0x%x pad 0x%x rate %d hdr", - wiphy_name(priv->hw->wiphy), le16_to_cpu(tx_buffer->wlength), - tx_buffer->padding, tx_buffer->tx_rate); - - /* send stuff */ - at76_dbg_dump(DBG_TX_DATA_CONTENT, tx_buffer, submit_len, - "%s(): tx_buffer %d bytes:", __func__, submit_len); - usb_fill_bulk_urb(priv->tx_urb, priv->udev, priv->tx_pipe, tx_buffer, - submit_len, at76_mac80211_tx_callback, priv); - ret = usb_submit_urb(priv->tx_urb, GFP_ATOMIC); - if (ret) { - printk(KERN_ERR "%s: error in tx submit urb: %d\n", - wiphy_name(priv->hw->wiphy), ret); - if (ret == -EINVAL) - printk(KERN_ERR - "%s: -EINVAL: tx urb %p hcpriv %p complete %p\n", - wiphy_name(priv->hw->wiphy), priv->tx_urb, - priv->tx_urb->hcpriv, priv->tx_urb->complete); - } - - return 0; -} - -static int at76_mac80211_start(struct ieee80211_hw *hw) -{ - struct at76_priv *priv = hw->priv; - int ret; - - at76_dbg(DBG_MAC80211, "%s()", __func__); - - mutex_lock(&priv->mtx); - - ret = at76_submit_rx_urb(priv); - if (ret < 0) { - printk(KERN_ERR "%s: open: submit_rx_urb failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - goto error; - } - - at76_startup_device(priv); - - at76_start_monitor(priv); - -error: - mutex_unlock(&priv->mtx); - - return 0; -} - -static void at76_mac80211_stop(struct ieee80211_hw *hw) -{ - struct at76_priv *priv = hw->priv; - - at76_dbg(DBG_MAC80211, "%s()", __func__); - - cancel_delayed_work(&priv->dwork_hw_scan); - cancel_work_sync(&priv->work_set_promisc); - - mutex_lock(&priv->mtx); - - if (!priv->device_unplugged) { - /* We are called by "ifconfig ethX down", not because the - * device is not available anymore. */ - at76_set_radio(priv, 0); - - /* We unlink rx_urb because at76_open() re-submits it. - * If unplugged, at76_delete_device() takes care of it. */ - usb_kill_urb(priv->rx_urb); - } - - mutex_unlock(&priv->mtx); -} - -static int at76_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct at76_priv *priv = hw->priv; - int ret = 0; - - at76_dbg(DBG_MAC80211, "%s()", __func__); - - mutex_lock(&priv->mtx); - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - priv->iw_mode = IW_MODE_INFRA; - break; - default: - ret = -EOPNOTSUPP; - goto exit; - } - -exit: - mutex_unlock(&priv->mtx); - - return ret; -} - -static void at76_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - at76_dbg(DBG_MAC80211, "%s()", __func__); -} - -static int at76_join(struct at76_priv *priv) -{ - struct at76_req_join join; - int ret; - - memset(&join, 0, sizeof(struct at76_req_join)); - memcpy(join.essid, priv->essid, priv->essid_size); - join.essid_size = priv->essid_size; - memcpy(join.bssid, priv->bssid, ETH_ALEN); - join.bss_type = INFRASTRUCTURE_MODE; - join.channel = priv->channel; - join.timeout = cpu_to_le16(2000); - - at76_dbg(DBG_MAC80211, "%s: sending CMD_JOIN", __func__); - ret = at76_set_card_command(priv->udev, CMD_JOIN, &join, - sizeof(struct at76_req_join)); - - if (ret < 0) { - printk(KERN_ERR "%s: at76_set_card_command failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - return 0; - } - - ret = at76_wait_completion(priv, CMD_JOIN); - at76_dbg(DBG_MAC80211, "%s: CMD_JOIN returned: 0x%02x", __func__, ret); - if (ret != CMD_STATUS_COMPLETE) { - printk(KERN_ERR "%s: at76_wait_completion failed: %d\n", - wiphy_name(priv->hw->wiphy), ret); - return 0; - } - - at76_set_pm_mode(priv); - - return 0; -} - -static void at76_dwork_hw_scan(struct work_struct *work) -{ - struct at76_priv *priv = container_of(work, struct at76_priv, - dwork_hw_scan.work); - int ret; - - if (priv->device_unplugged) - return; - - mutex_lock(&priv->mtx); - - ret = at76_get_cmd_status(priv->udev, CMD_SCAN); - at76_dbg(DBG_MAC80211, "%s: CMD_SCAN status 0x%02x", __func__, ret); - - /* FIXME: add maximum time for scan to complete */ - - if (ret != CMD_STATUS_COMPLETE) { - ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan, - SCAN_POLL_INTERVAL); - mutex_unlock(&priv->mtx); - return; - } - - if (is_valid_ether_addr(priv->bssid)) - at76_join(priv); - - mutex_unlock(&priv->mtx); - - ieee80211_scan_completed(priv->hw, false); - - ieee80211_wake_queues(priv->hw); -} - -static int at76_hw_scan(struct ieee80211_hw *hw, - struct cfg80211_scan_request *req) -{ - struct at76_priv *priv = hw->priv; - struct at76_req_scan scan; - u8 *ssid = NULL; - int ret, len = 0; - - at76_dbg(DBG_MAC80211, "%s():", __func__); - - if (priv->device_unplugged) - return 0; - - mutex_lock(&priv->mtx); - - ieee80211_stop_queues(hw); - - memset(&scan, 0, sizeof(struct at76_req_scan)); - memset(scan.bssid, 0xFF, ETH_ALEN); - - if (req->n_ssids) { - scan.scan_type = SCAN_TYPE_ACTIVE; - ssid = req->ssids[0].ssid; - len = req->ssids[0].ssid_len; - } else { - scan.scan_type = SCAN_TYPE_PASSIVE; - } - - if (len) { - memcpy(scan.essid, ssid, len); - scan.essid_size = len; - } - - scan.min_channel_time = cpu_to_le16(priv->scan_min_time); - scan.max_channel_time = cpu_to_le16(priv->scan_max_time); - scan.probe_delay = cpu_to_le16(priv->scan_min_time * 1000); - scan.international_scan = 0; - - at76_dbg(DBG_MAC80211, "%s: sending CMD_SCAN", __func__); - ret = at76_set_card_command(priv->udev, CMD_SCAN, &scan, sizeof(scan)); - - if (ret < 0) { - err("CMD_SCAN failed: %d", ret); - goto exit; - } - - ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan, - SCAN_POLL_INTERVAL); - -exit: - mutex_unlock(&priv->mtx); - - return 0; -} - -static int at76_config(struct ieee80211_hw *hw, u32 changed) -{ - struct at76_priv *priv = hw->priv; - - at76_dbg(DBG_MAC80211, "%s(): channel %d", - __func__, hw->conf.channel->hw_value); - at76_dbg_dump(DBG_MAC80211, priv->bssid, ETH_ALEN, "bssid:"); - - mutex_lock(&priv->mtx); - - priv->channel = hw->conf.channel->hw_value; - - if (is_valid_ether_addr(priv->bssid)) - at76_join(priv); - else - at76_start_monitor(priv); - - mutex_unlock(&priv->mtx); - - return 0; -} - -static void at76_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, - u32 changed) -{ - struct at76_priv *priv = hw->priv; - - at76_dbg(DBG_MAC80211, "%s():", __func__); - - if (!(changed & BSS_CHANGED_BSSID)) - return; - - at76_dbg_dump(DBG_MAC80211, conf->bssid, ETH_ALEN, "bssid:"); - - mutex_lock(&priv->mtx); - - memcpy(priv->bssid, conf->bssid, ETH_ALEN); - - if (is_valid_ether_addr(priv->bssid)) - /* mac80211 is joining a bss */ - at76_join(priv); - - mutex_unlock(&priv->mtx); -} - -/* must be atomic */ -static void at76_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast) -{ - struct at76_priv *priv = hw->priv; - int flags; - - at76_dbg(DBG_MAC80211, "%s(): changed_flags=0x%08x " - "total_flags=0x%08x", - __func__, changed_flags, *total_flags); - - flags = changed_flags & AT76_SUPPORTED_FILTERS; - *total_flags = AT76_SUPPORTED_FILTERS; - - /* Bail out after updating flags to prevent a WARN_ON in mac80211. */ - if (priv->device_unplugged) - return; - - /* FIXME: access to priv->promisc should be protected with - * priv->mtx, but it's impossible because this function needs to be - * atomic */ - - if (flags && !priv->promisc) { - /* mac80211 wants us to enable promiscuous mode */ - priv->promisc = 1; - } else if (!flags && priv->promisc) { - /* we need to disable promiscuous mode */ - priv->promisc = 0; - } else - return; - - ieee80211_queue_work(hw, &priv->work_set_promisc); -} - -static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct at76_priv *priv = hw->priv; - - int i; - - at76_dbg(DBG_MAC80211, "%s(): cmd %d key->alg %d key->keyidx %d " - "key->keylen %d", - __func__, cmd, key->alg, key->keyidx, key->keylen); - - if (key->alg != ALG_WEP) - return -EOPNOTSUPP; - - key->hw_key_idx = key->keyidx; - - mutex_lock(&priv->mtx); - - switch (cmd) { - case SET_KEY: - memcpy(priv->wep_keys[key->keyidx], key->key, key->keylen); - priv->wep_keys_len[key->keyidx] = key->keylen; - - /* FIXME: find out how to do this properly */ - priv->wep_key_id = key->keyidx; - - break; - case DISABLE_KEY: - default: - priv->wep_keys_len[key->keyidx] = 0; - break; - } - - priv->wep_enabled = 0; - - for (i = 0; i < WEP_KEYS; i++) { - if (priv->wep_keys_len[i] != 0) - priv->wep_enabled = 1; - } - - at76_startup_device(priv); - - mutex_unlock(&priv->mtx); - - return 0; -} - -static const struct ieee80211_ops at76_ops = { - .tx = at76_mac80211_tx, - .add_interface = at76_add_interface, - .remove_interface = at76_remove_interface, - .config = at76_config, - .bss_info_changed = at76_bss_info_changed, - .configure_filter = at76_configure_filter, - .start = at76_mac80211_start, - .stop = at76_mac80211_stop, - .hw_scan = at76_hw_scan, - .set_key = at76_set_key, -}; - -/* Allocate network device and initialize private data */ -static struct at76_priv *at76_alloc_new_device(struct usb_device *udev) -{ - struct ieee80211_hw *hw; - struct at76_priv *priv; - - hw = ieee80211_alloc_hw(sizeof(struct at76_priv), &at76_ops); - if (!hw) { - printk(KERN_ERR DRIVER_NAME ": could not register" - " ieee80211_hw\n"); - return NULL; - } - - priv = hw->priv; - priv->hw = hw; - - priv->udev = udev; - - mutex_init(&priv->mtx); - INIT_WORK(&priv->work_set_promisc, at76_work_set_promisc); - INIT_WORK(&priv->work_submit_rx, at76_work_submit_rx); - INIT_DELAYED_WORK(&priv->dwork_hw_scan, at76_dwork_hw_scan); - - tasklet_init(&priv->rx_tasklet, at76_rx_tasklet, 0); - - priv->pm_mode = AT76_PM_OFF; - priv->pm_period = 0; - - /* unit us */ - priv->hw->channel_change_time = 100000; - - return priv; -} - -static int at76_alloc_urbs(struct at76_priv *priv, - struct usb_interface *interface) -{ - struct usb_endpoint_descriptor *endpoint, *ep_in, *ep_out; - int i; - int buffer_size; - struct usb_host_interface *iface_desc; - - at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__); - - at76_dbg(DBG_URB, "%s: NumEndpoints %d ", __func__, - interface->altsetting[0].desc.bNumEndpoints); - - ep_in = NULL; - ep_out = NULL; - iface_desc = interface->cur_altsetting; - for (i = 0; i < iface_desc->desc.bNumEndpoints; i++) { - endpoint = &iface_desc->endpoint[i].desc; - - at76_dbg(DBG_URB, "%s: %d. endpoint: addr 0x%x attr 0x%x", - __func__, i, endpoint->bEndpointAddress, - endpoint->bmAttributes); - - if (!ep_in && usb_endpoint_is_bulk_in(endpoint)) - ep_in = endpoint; - - if (!ep_out && usb_endpoint_is_bulk_out(endpoint)) - ep_out = endpoint; - } - - if (!ep_in || !ep_out) { - dev_printk(KERN_ERR, &interface->dev, - "bulk endpoints missing\n"); - return -ENXIO; - } - - priv->rx_pipe = usb_rcvbulkpipe(priv->udev, ep_in->bEndpointAddress); - priv->tx_pipe = usb_sndbulkpipe(priv->udev, ep_out->bEndpointAddress); - - priv->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - priv->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!priv->rx_urb || !priv->tx_urb) { - dev_printk(KERN_ERR, &interface->dev, "cannot allocate URB\n"); - return -ENOMEM; - } - - buffer_size = sizeof(struct at76_tx_buffer) + MAX_PADDING_SIZE; - priv->bulk_out_buffer = kmalloc(buffer_size, GFP_KERNEL); - if (!priv->bulk_out_buffer) { - dev_printk(KERN_ERR, &interface->dev, - "cannot allocate output buffer\n"); - return -ENOMEM; - } - - at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__); - - return 0; -} - -static struct ieee80211_rate at76_rates[] = { - { .bitrate = 10, .hw_value = TX_RATE_1MBIT, }, - { .bitrate = 20, .hw_value = TX_RATE_2MBIT, }, - { .bitrate = 55, .hw_value = TX_RATE_5_5MBIT, }, - { .bitrate = 110, .hw_value = TX_RATE_11MBIT, }, -}; - -static struct ieee80211_channel at76_channels[] = { - { .center_freq = 2412, .hw_value = 1 }, - { .center_freq = 2417, .hw_value = 2 }, - { .center_freq = 2422, .hw_value = 3 }, - { .center_freq = 2427, .hw_value = 4 }, - { .center_freq = 2432, .hw_value = 5 }, - { .center_freq = 2437, .hw_value = 6 }, - { .center_freq = 2442, .hw_value = 7 }, - { .center_freq = 2447, .hw_value = 8 }, - { .center_freq = 2452, .hw_value = 9 }, - { .center_freq = 2457, .hw_value = 10 }, - { .center_freq = 2462, .hw_value = 11 }, - { .center_freq = 2467, .hw_value = 12 }, - { .center_freq = 2472, .hw_value = 13 }, - { .center_freq = 2484, .hw_value = 14 } -}; - -static struct ieee80211_supported_band at76_supported_band = { - .channels = at76_channels, - .n_channels = ARRAY_SIZE(at76_channels), - .bitrates = at76_rates, - .n_bitrates = ARRAY_SIZE(at76_rates), -}; - -/* Register network device and initialize the hardware */ -static int at76_init_new_device(struct at76_priv *priv, - struct usb_interface *interface) -{ - int ret; - - /* set up the endpoint information */ - /* check out the endpoints */ - - at76_dbg(DBG_DEVSTART, "USB interface: %d endpoints", - interface->cur_altsetting->desc.bNumEndpoints); - - ret = at76_alloc_urbs(priv, interface); - if (ret < 0) - goto exit; - - /* MAC address */ - ret = at76_get_hw_config(priv); - if (ret < 0) { - dev_printk(KERN_ERR, &interface->dev, - "cannot get MAC address\n"); - goto exit; - } - - priv->domain = at76_get_reg_domain(priv->regulatory_domain); - - priv->channel = DEF_CHANNEL; - priv->iw_mode = IW_MODE_INFRA; - priv->rts_threshold = DEF_RTS_THRESHOLD; - priv->frag_threshold = DEF_FRAG_THRESHOLD; - priv->short_retry_limit = DEF_SHORT_RETRY_LIMIT; - priv->txrate = TX_RATE_AUTO; - priv->preamble_type = PREAMBLE_TYPE_LONG; - priv->beacon_period = 100; - priv->auth_mode = WLAN_AUTH_OPEN; - priv->scan_min_time = DEF_SCAN_MIN_TIME; - priv->scan_max_time = DEF_SCAN_MAX_TIME; - priv->scan_mode = SCAN_TYPE_ACTIVE; - priv->device_unplugged = 0; - - /* mac80211 initialisation */ - priv->hw->wiphy->max_scan_ssids = 1; - priv->hw->wiphy->max_scan_ie_len = 0; - priv->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &at76_supported_band; - priv->hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_UNSPEC; - priv->hw->max_signal = 100; - - SET_IEEE80211_DEV(priv->hw, &interface->dev); - SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); - - ret = ieee80211_register_hw(priv->hw); - if (ret) { - printk(KERN_ERR "cannot register mac80211 hw (status %d)!\n", - ret); - goto exit; - } - - priv->mac80211_registered = 1; - - printk(KERN_INFO "%s: USB %s, MAC %s, firmware %d.%d.%d-%d\n", - wiphy_name(priv->hw->wiphy), - dev_name(&interface->dev), mac2str(priv->mac_addr), - priv->fw_version.major, priv->fw_version.minor, - priv->fw_version.patch, priv->fw_version.build); - printk(KERN_INFO "%s: regulatory domain 0x%02x: %s\n", - wiphy_name(priv->hw->wiphy), - priv->regulatory_domain, priv->domain->name); - -exit: - return ret; -} - -static void at76_delete_device(struct at76_priv *priv) -{ - at76_dbg(DBG_PROC_ENTRY, "%s: ENTER", __func__); - - /* The device is gone, don't bother turning it off */ - priv->device_unplugged = 1; - - tasklet_kill(&priv->rx_tasklet); - - if (priv->mac80211_registered) - ieee80211_unregister_hw(priv->hw); - - if (priv->tx_urb) { - usb_kill_urb(priv->tx_urb); - usb_free_urb(priv->tx_urb); - } - if (priv->rx_urb) { - usb_kill_urb(priv->rx_urb); - usb_free_urb(priv->rx_urb); - } - - at76_dbg(DBG_PROC_ENTRY, "%s: unlinked urbs", __func__); - - kfree(priv->bulk_out_buffer); - - del_timer_sync(&ledtrig_tx_timer); - - kfree_skb(priv->rx_skb); - - usb_put_dev(priv->udev); - - at76_dbg(DBG_PROC_ENTRY, "%s: before freeing priv/ieee80211_hw", - __func__); - ieee80211_free_hw(priv->hw); - - at76_dbg(DBG_PROC_ENTRY, "%s: EXIT", __func__); -} - -static int at76_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - int ret; - struct at76_priv *priv; - struct fwentry *fwe; - struct usb_device *udev; - int op_mode; - int need_ext_fw = 0; - struct mib_fw_version fwv; - int board_type = (int)id->driver_info; - - udev = usb_get_dev(interface_to_usbdev(interface)); - - /* Load firmware into kernel memory */ - fwe = at76_load_firmware(udev, board_type); - if (!fwe) { - ret = -ENOENT; - goto error; - } - - op_mode = at76_get_op_mode(udev); - - at76_dbg(DBG_DEVSTART, "opmode %d", op_mode); - - /* we get OPMODE_NONE with 2.4.23, SMC2662W-AR ??? - we get 204 with 2.4.23, Fiberline FL-WL240u (505A+RFMD2958) ??? */ - - if (op_mode == OPMODE_HW_CONFIG_MODE) { - dev_printk(KERN_ERR, &interface->dev, - "cannot handle a device in HW_CONFIG_MODE\n"); - ret = -EBUSY; - goto error; - } - - if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH - && op_mode != OPMODE_NORMAL_NIC_WITHOUT_FLASH) { - /* download internal firmware part */ - dev_printk(KERN_DEBUG, &interface->dev, - "downloading internal firmware\n"); - ret = at76_load_internal_fw(udev, fwe); - if (ret < 0) { - dev_printk(KERN_ERR, &interface->dev, - "error %d downloading internal firmware\n", - ret); - goto error; - } - usb_put_dev(udev); - return ret; - } - - /* Internal firmware already inside the device. Get firmware - * version to test if external firmware is loaded. - * This works only for newer firmware, e.g. the Intersil 0.90.x - * says "control timeout on ep0in" and subsequent - * at76_get_op_mode() fail too :-( */ - - /* if version >= 0.100.x.y or device with built-in flash we can - * query the device for the fw version */ - if ((fwe->fw_version.major > 0 || fwe->fw_version.minor >= 100) - || (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) { - ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv)); - if (ret < 0 || (fwv.major | fwv.minor) == 0) - need_ext_fw = 1; - } else - /* No way to check firmware version, reload to be sure */ - need_ext_fw = 1; - - if (need_ext_fw) { - dev_printk(KERN_DEBUG, &interface->dev, - "downloading external firmware\n"); - - ret = at76_load_external_fw(udev, fwe); - if (ret) - goto error; - - /* Re-check firmware version */ - ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv)); - if (ret < 0) { - dev_printk(KERN_ERR, &interface->dev, - "error %d getting firmware version\n", ret); - goto error; - } - } - - priv = at76_alloc_new_device(udev); - if (!priv) { - ret = -ENOMEM; - goto error; - } - - usb_set_intfdata(interface, priv); - - memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version)); - priv->board_type = board_type; - - ret = at76_init_new_device(priv, interface); - if (ret < 0) - at76_delete_device(priv); - - return ret; - -error: - usb_put_dev(udev); - return ret; -} - -static void at76_disconnect(struct usb_interface *interface) -{ - struct at76_priv *priv; - - priv = usb_get_intfdata(interface); - usb_set_intfdata(interface, NULL); - - /* Disconnect after loading internal firmware */ - if (!priv) - return; - - printk(KERN_INFO "%s: disconnecting\n", wiphy_name(priv->hw->wiphy)); - at76_delete_device(priv); - dev_printk(KERN_INFO, &interface->dev, "disconnected\n"); -} - -/* Structure for registering this driver with the USB subsystem */ -static struct usb_driver at76_driver = { - .name = DRIVER_NAME, - .probe = at76_probe, - .disconnect = at76_disconnect, - .id_table = dev_table, -}; - -static int __init at76_mod_init(void) -{ - int result; - - printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " loading\n"); - - mutex_init(&fw_mutex); - - /* register this driver with the USB subsystem */ - result = usb_register(&at76_driver); - if (result < 0) - printk(KERN_ERR DRIVER_NAME - ": usb_register failed (status %d)\n", result); - - led_trigger_register_simple("at76_usb-tx", &ledtrig_tx); - return result; -} - -static void __exit at76_mod_exit(void) -{ - int i; - - printk(KERN_INFO DRIVER_DESC " " DRIVER_VERSION " unloading\n"); - usb_deregister(&at76_driver); - for (i = 0; i < ARRAY_SIZE(firmwares); i++) { - if (firmwares[i].fw) - release_firmware(firmwares[i].fw); - } - led_trigger_unregister_simple(ledtrig_tx); -} - -module_param_named(debug, at76_debug, uint, 0600); -MODULE_PARM_DESC(debug, "Debugging level"); - -module_init(at76_mod_init); -module_exit(at76_mod_exit); - -MODULE_AUTHOR("Oliver Kurth "); -MODULE_AUTHOR("Joerg Albert "); -MODULE_AUTHOR("Alex "); -MODULE_AUTHOR("Nick Jones"); -MODULE_AUTHOR("Balint Seeber "); -MODULE_AUTHOR("Pavel Roskin "); -MODULE_AUTHOR("Guido Guenther "); -MODULE_AUTHOR("Kalle Valo "); -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/at76c50x-usb.h b/drivers/net/wireless/at76c50x-usb.h deleted file mode 100644 index 1ec5ccffdbc0..000000000000 --- a/drivers/net/wireless/at76c50x-usb.h +++ /dev/null @@ -1,463 +0,0 @@ -/* - * Copyright (c) 2002,2003 Oliver Kurth - * (c) 2003,2004 Joerg Albert - * (c) 2007 Guido Guenther - * - * 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 driver was based on information from the Sourceforge driver - * released and maintained by Atmel: - * - * http://sourceforge.net/projects/atmelwlandriver/ - * - * Although the code was completely re-written, - * it would have been impossible without Atmel's decision to - * release an Open Source driver (unfortunately the firmware was - * kept binary only). Thanks for that decision to Atmel! - */ - -#ifndef _AT76_USB_H -#define _AT76_USB_H - -/* Board types */ -enum board_type { - BOARD_503_ISL3861 = 1, - BOARD_503_ISL3863 = 2, - BOARD_503 = 3, - BOARD_503_ACC = 4, - BOARD_505 = 5, - BOARD_505_2958 = 6, - BOARD_505A = 7, - BOARD_505AMX = 8 -}; - -#define CMD_STATUS_IDLE 0x00 -#define CMD_STATUS_COMPLETE 0x01 -#define CMD_STATUS_UNKNOWN 0x02 -#define CMD_STATUS_INVALID_PARAMETER 0x03 -#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04 -#define CMD_STATUS_TIME_OUT 0x07 -#define CMD_STATUS_IN_PROGRESS 0x08 -#define CMD_STATUS_HOST_FAILURE 0xff -#define CMD_STATUS_SCAN_FAILED 0xf0 - -/* answers to get op mode */ -#define OPMODE_NONE 0x00 -#define OPMODE_NORMAL_NIC_WITH_FLASH 0x01 -#define OPMODE_HW_CONFIG_MODE 0x02 -#define OPMODE_DFU_MODE_WITH_FLASH 0x03 -#define OPMODE_NORMAL_NIC_WITHOUT_FLASH 0x04 - -#define CMD_SET_MIB 0x01 -#define CMD_GET_MIB 0x02 -#define CMD_SCAN 0x03 -#define CMD_JOIN 0x04 -#define CMD_START_IBSS 0x05 -#define CMD_RADIO_ON 0x06 -#define CMD_RADIO_OFF 0x07 -#define CMD_STARTUP 0x0B - -#define MIB_LOCAL 0x01 -#define MIB_MAC_ADDR 0x02 -#define MIB_MAC 0x03 -#define MIB_MAC_MGMT 0x05 -#define MIB_MAC_WEP 0x06 -#define MIB_PHY 0x07 -#define MIB_FW_VERSION 0x08 -#define MIB_MDOMAIN 0x09 - -#define ADHOC_MODE 1 -#define INFRASTRUCTURE_MODE 2 - -/* values for struct mib_local, field preamble_type */ -#define PREAMBLE_TYPE_LONG 0 -#define PREAMBLE_TYPE_SHORT 1 -#define PREAMBLE_TYPE_AUTO 2 - -/* values for tx_rate */ -#define TX_RATE_1MBIT 0 -#define TX_RATE_2MBIT 1 -#define TX_RATE_5_5MBIT 2 -#define TX_RATE_11MBIT 3 -#define TX_RATE_AUTO 4 - -/* power management modes */ -#define AT76_PM_OFF 1 -#define AT76_PM_ON 2 -#define AT76_PM_SMART 3 - -struct hwcfg_r505 { - u8 cr39_values[14]; - u8 reserved1[14]; - u8 bb_cr[14]; - u8 pidvid[4]; - u8 mac_addr[ETH_ALEN]; - u8 regulatory_domain; - u8 reserved2[14]; - u8 cr15_values[14]; - u8 reserved3[3]; -} __attribute__((packed)); - -struct hwcfg_rfmd { - u8 cr20_values[14]; - u8 cr21_values[14]; - u8 bb_cr[14]; - u8 pidvid[4]; - u8 mac_addr[ETH_ALEN]; - u8 regulatory_domain; - u8 low_power_values[14]; - u8 normal_power_values[14]; - u8 reserved1[3]; -} __attribute__((packed)); - -struct hwcfg_intersil { - u8 mac_addr[ETH_ALEN]; - u8 cr31_values[14]; - u8 cr58_values[14]; - u8 pidvid[4]; - u8 regulatory_domain; - u8 reserved[1]; -} __attribute__((packed)); - -union at76_hwcfg { - struct hwcfg_intersil i; - struct hwcfg_rfmd r3; - struct hwcfg_r505 r5; -}; - -#define WEP_SMALL_KEY_LEN (40 / 8) -#define WEP_LARGE_KEY_LEN (104 / 8) -#define WEP_KEYS (4) - -struct at76_card_config { - u8 exclude_unencrypted; - u8 promiscuous_mode; - u8 short_retry_limit; - u8 encryption_type; - __le16 rts_threshold; - __le16 fragmentation_threshold; /* 256..2346 */ - u8 basic_rate_set[4]; - u8 auto_rate_fallback; /* 0,1 */ - u8 channel; - u8 privacy_invoked; - u8 wep_default_key_id; /* 0..3 */ - u8 current_ssid[32]; - u8 wep_default_key_value[4][WEP_LARGE_KEY_LEN]; - u8 ssid_len; - u8 short_preamble; - __le16 beacon_period; -} __attribute__((packed)); - -struct at76_command { - u8 cmd; - u8 reserved; - __le16 size; - u8 data[0]; -} __attribute__((packed)); - -/* Length of Atmel-specific Rx header before 802.11 frame */ -#define AT76_RX_HDRLEN offsetof(struct at76_rx_buffer, packet) - -struct at76_rx_buffer { - __le16 wlength; - u8 rx_rate; - u8 newbss; - u8 fragmentation; - u8 rssi; - u8 link_quality; - u8 noise_level; - __le32 rx_time; - u8 packet[IEEE80211_MAX_FRAG_THRESHOLD]; -} __attribute__((packed)); - -/* Length of Atmel-specific Tx header before 802.11 frame */ -#define AT76_TX_HDRLEN offsetof(struct at76_tx_buffer, packet) - -struct at76_tx_buffer { - __le16 wlength; - u8 tx_rate; - u8 padding; - u8 reserved[4]; - u8 packet[IEEE80211_MAX_FRAG_THRESHOLD]; -} __attribute__((packed)); - -/* defines for scan_type below */ -#define SCAN_TYPE_ACTIVE 0 -#define SCAN_TYPE_PASSIVE 1 - -struct at76_req_scan { - u8 bssid[ETH_ALEN]; - u8 essid[32]; - u8 scan_type; - u8 channel; - __le16 probe_delay; - __le16 min_channel_time; - __le16 max_channel_time; - u8 essid_size; - u8 international_scan; -} __attribute__((packed)); - -struct at76_req_ibss { - u8 bssid[ETH_ALEN]; - u8 essid[32]; - u8 bss_type; - u8 channel; - u8 essid_size; - u8 reserved[3]; -} __attribute__((packed)); - -struct at76_req_join { - u8 bssid[ETH_ALEN]; - u8 essid[32]; - u8 bss_type; - u8 channel; - __le16 timeout; - u8 essid_size; - u8 reserved; -} __attribute__((packed)); - -struct set_mib_buffer { - u8 type; - u8 size; - u8 index; - u8 reserved; - union { - u8 byte; - __le16 word; - u8 addr[ETH_ALEN]; - } data; -} __attribute__((packed)); - -struct mib_local { - u16 reserved0; - u8 beacon_enable; - u8 txautorate_fallback; - u8 reserved1; - u8 ssid_size; - u8 promiscuous_mode; - u16 reserved2; - u8 preamble_type; - u16 reserved3; -} __attribute__((packed)); - -struct mib_mac_addr { - u8 mac_addr[ETH_ALEN]; - u8 res[2]; /* ??? */ - u8 group_addr[4][ETH_ALEN]; - u8 group_addr_status[4]; -} __attribute__((packed)); - -struct mib_mac { - __le32 max_tx_msdu_lifetime; - __le32 max_rx_lifetime; - __le16 frag_threshold; - __le16 rts_threshold; - __le16 cwmin; - __le16 cwmax; - u8 short_retry_time; - u8 long_retry_time; - u8 scan_type; /* active or passive */ - u8 scan_channel; - __le16 probe_delay; /* delay before ProbeReq in active scan, RO */ - __le16 min_channel_time; - __le16 max_channel_time; - __le16 listen_interval; - u8 desired_ssid[32]; - u8 desired_bssid[ETH_ALEN]; - u8 desired_bsstype; /* ad-hoc or infrastructure */ - u8 reserved2; -} __attribute__((packed)); - -struct mib_mac_mgmt { - __le16 beacon_period; - __le16 CFP_max_duration; - __le16 medium_occupancy_limit; - __le16 station_id; /* assoc id */ - __le16 ATIM_window; - u8 CFP_mode; - u8 privacy_option_implemented; - u8 DTIM_period; - u8 CFP_period; - u8 current_bssid[ETH_ALEN]; - u8 current_essid[32]; - u8 current_bss_type; - u8 power_mgmt_mode; - /* rfmd and 505 */ - u8 ibss_change; - u8 res; - u8 multi_domain_capability_implemented; - u8 multi_domain_capability_enabled; - u8 country_string[3]; - u8 reserved[3]; -} __attribute__((packed)); - -struct mib_mac_wep { - u8 privacy_invoked; /* 0 disable encr., 1 enable encr */ - u8 wep_default_key_id; - u8 wep_key_mapping_len; - u8 exclude_unencrypted; - __le32 wep_icv_error_count; - __le32 wep_excluded_count; - u8 wep_default_keyvalue[WEP_KEYS][WEP_LARGE_KEY_LEN]; - u8 encryption_level; /* 1 for 40bit, 2 for 104bit encryption */ -} __attribute__((packed)); - -struct mib_phy { - __le32 ed_threshold; - - __le16 slot_time; - __le16 sifs_time; - __le16 preamble_length; - __le16 plcp_header_length; - __le16 mpdu_max_length; - __le16 cca_mode_supported; - - u8 operation_rate_set[4]; - u8 channel_id; - u8 current_cca_mode; - u8 phy_type; - u8 current_reg_domain; -} __attribute__((packed)); - -struct mib_fw_version { - u8 major; - u8 minor; - u8 patch; - u8 build; -} __attribute__((packed)); - -struct mib_mdomain { - u8 tx_powerlevel[14]; - u8 channel_list[14]; /* 0 for invalid channels */ -} __attribute__((packed)); - -struct at76_fw_header { - __le32 crc; /* CRC32 of the whole image */ - __le32 board_type; /* firmware compatibility code */ - u8 build; /* firmware build number */ - u8 patch; /* firmware patch level */ - u8 minor; /* firmware minor version */ - u8 major; /* firmware major version */ - __le32 str_offset; /* offset of the copyright string */ - __le32 int_fw_offset; /* internal firmware image offset */ - __le32 int_fw_len; /* internal firmware image length */ - __le32 ext_fw_offset; /* external firmware image offset */ - __le32 ext_fw_len; /* external firmware image length */ -} __attribute__((packed)); - -/* a description of a regulatory domain and the allowed channels */ -struct reg_domain { - u16 code; - char const *name; - u32 channel_map; /* if bit N is set, channel (N+1) is allowed */ -}; - -/* Data for one loaded firmware file */ -struct fwentry { - const char *const fwname; - const struct firmware *fw; - int extfw_size; - int intfw_size; - /* pointer to loaded firmware, no need to free */ - u8 *extfw; /* external firmware, extfw_size bytes long */ - u8 *intfw; /* internal firmware, intfw_size bytes long */ - enum board_type board_type; /* board type */ - struct mib_fw_version fw_version; - int loaded; /* Loaded and parsed successfully */ -}; - -struct at76_priv { - struct usb_device *udev; /* USB device pointer */ - - struct sk_buff *rx_skb; /* skbuff for receiving data */ - struct sk_buff *tx_skb; /* skbuff for transmitting data */ - void *bulk_out_buffer; /* buffer for sending data */ - - struct urb *tx_urb; /* URB for sending data */ - struct urb *rx_urb; /* URB for receiving data */ - - unsigned int tx_pipe; /* bulk out pipe */ - unsigned int rx_pipe; /* bulk in pipe */ - - struct mutex mtx; /* locks this structure */ - - /* work queues */ - struct work_struct work_set_promisc; - struct work_struct work_submit_rx; - struct delayed_work dwork_hw_scan; - - struct tasklet_struct rx_tasklet; - - /* the WEP stuff */ - int wep_enabled; /* 1 if WEP is enabled */ - int wep_key_id; /* key id to be used */ - u8 wep_keys[WEP_KEYS][WEP_LARGE_KEY_LEN]; /* WEP keys */ - u8 wep_keys_len[WEP_KEYS]; /* length of WEP keys */ - - int channel; - int iw_mode; - u8 bssid[ETH_ALEN]; - u8 essid[IW_ESSID_MAX_SIZE]; - int essid_size; - int radio_on; - int promisc; - - int preamble_type; /* 0 - long, 1 - short, 2 - auto */ - int auth_mode; /* authentication type: 0 open, 1 shared key */ - int txrate; /* 0,1,2,3 = 1,2,5.5,11 Mbps, 4 is auto */ - int frag_threshold; /* threshold for fragmentation of tx packets */ - int rts_threshold; /* threshold for RTS mechanism */ - int short_retry_limit; - - int scan_min_time; /* scan min channel time */ - int scan_max_time; /* scan max channel time */ - int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */ - int scan_need_any; /* if set, need to scan for any ESSID */ - - u16 assoc_id; /* current association ID, if associated */ - - u8 pm_mode; /* power management mode */ - u32 pm_period; /* power management period in microseconds */ - - struct reg_domain const *domain; /* reg domain description */ - - /* These fields contain HW config provided by the device (not all of - * these fields are used by all board types) */ - u8 mac_addr[ETH_ALEN]; - u8 regulatory_domain; - - struct at76_card_config card_config; - - enum board_type board_type; - struct mib_fw_version fw_version; - - unsigned int device_unplugged:1; - unsigned int netdev_registered:1; - struct set_mib_buffer mib_buf; /* global buffer for set_mib calls */ - - int beacon_period; /* period of mgmt beacons, Kus */ - - struct ieee80211_hw *hw; - int mac80211_registered; -}; - -#define AT76_SUPPORTED_FILTERS FIF_PROMISC_IN_BSS - -#define SCAN_POLL_INTERVAL (HZ / 4) - -#define CMD_COMPLETION_TIMEOUT (5 * HZ) - -#define DEF_RTS_THRESHOLD 1536 -#define DEF_FRAG_THRESHOLD 1536 -#define DEF_SHORT_RETRY_LIMIT 8 -#define DEF_CHANNEL 10 -#define DEF_SCAN_MIN_TIME 10 -#define DEF_SCAN_MAX_TIME 120 - -/* the max padding size for tx in bytes (see calc_padding) */ -#define MAX_PADDING_SIZE 53 - -#endif /* _AT76_USB_H */ diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig deleted file mode 100644 index 11ded150b932..000000000000 --- a/drivers/net/wireless/ath/Kconfig +++ /dev/null @@ -1,22 +0,0 @@ -menuconfig ATH_COMMON - tristate "Atheros Wireless Cards" - depends on WLAN_80211 - depends on CFG80211 - ---help--- - This will enable the support for the Atheros wireless drivers. - ath5k, ath9k and ar9170 drivers share some common code, this option - enables the common ath.ko module which shares common helpers. - - For more information and documentation on this module you can visit: - - http://wireless.kernel.org/en/users/Drivers/ath - - For information on all Atheros wireless drivers visit: - - http://wireless.kernel.org/en/users/Drivers/Atheros - -if ATH_COMMON -source "drivers/net/wireless/ath/ath5k/Kconfig" -source "drivers/net/wireless/ath/ath9k/Kconfig" -source "drivers/net/wireless/ath/ar9170/Kconfig" -endif diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile deleted file mode 100644 index 4bb0132ada37..000000000000 --- a/drivers/net/wireless/ath/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -obj-$(CONFIG_ATH5K) += ath5k/ -obj-$(CONFIG_ATH9K) += ath9k/ -obj-$(CONFIG_AR9170_USB) += ar9170/ - -obj-$(CONFIG_ATH_COMMON) += ath.o -ath-objs := main.o regd.o diff --git a/drivers/net/wireless/ath/ar9170/Kconfig b/drivers/net/wireless/ath/ar9170/Kconfig deleted file mode 100644 index 05918f1e685a..000000000000 --- a/drivers/net/wireless/ath/ar9170/Kconfig +++ /dev/null @@ -1,18 +0,0 @@ -config AR9170_USB - tristate "Atheros AR9170 802.11n USB support" - depends on USB && MAC80211 && WLAN_80211 - select FW_LOADER - help - This is a driver for the Atheros "otus" 802.11n USB devices. - - These devices require additional firmware (2 files). - For now, these files can be downloaded from here: - - http://wireless.kernel.org/en/users/Drivers/ar9170 - - If you choose to build a module, it'll be called ar9170usb. - -config AR9170_LEDS - bool - depends on AR9170_USB && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = AR9170_USB) - default y diff --git a/drivers/net/wireless/ath/ar9170/Makefile b/drivers/net/wireless/ath/ar9170/Makefile deleted file mode 100644 index 8d91c7ee3215..000000000000 --- a/drivers/net/wireless/ath/ar9170/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -ar9170usb-objs := usb.o main.o cmd.o mac.o phy.o led.o - -obj-$(CONFIG_AR9170_USB) += ar9170usb.o diff --git a/drivers/net/wireless/ath/ar9170/ar9170.h b/drivers/net/wireless/ath/ar9170/ar9170.h deleted file mode 100644 index 914e4718a9a8..000000000000 --- a/drivers/net/wireless/ath/ar9170/ar9170.h +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Driver specific definitions - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __AR9170_H -#define __AR9170_H - -#include -#include -#include -#include -#ifdef CONFIG_AR9170_LEDS -#include -#endif /* CONFIG_AR9170_LEDS */ -#include "eeprom.h" -#include "hw.h" - -#include "../regd.h" - -#define PAYLOAD_MAX (AR9170_MAX_CMD_LEN/4 - 1) - -enum ar9170_bw { - AR9170_BW_20, - AR9170_BW_40_BELOW, - AR9170_BW_40_ABOVE, - - __AR9170_NUM_BW, -}; - -static inline enum ar9170_bw nl80211_to_ar9170(enum nl80211_channel_type type) -{ - switch (type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - return AR9170_BW_20; - case NL80211_CHAN_HT40MINUS: - return AR9170_BW_40_BELOW; - case NL80211_CHAN_HT40PLUS: - return AR9170_BW_40_ABOVE; - default: - BUG(); - } -} - -enum ar9170_rf_init_mode { - AR9170_RFI_NONE, - AR9170_RFI_WARM, - AR9170_RFI_COLD, -}; - -#define AR9170_MAX_RX_BUFFER_SIZE 8192 - -#ifdef CONFIG_AR9170_LEDS -struct ar9170; - -struct ar9170_led { - struct ar9170 *ar; - struct led_classdev l; - char name[32]; - unsigned int toggled; - bool last_state; - bool registered; -}; - -#endif /* CONFIG_AR9170_LEDS */ - -enum ar9170_device_state { - AR9170_UNKNOWN_STATE, - AR9170_STOPPED, - AR9170_IDLE, - AR9170_STARTED, -}; - -struct ar9170_rxstream_mpdu_merge { - struct ar9170_rx_head plcp; - bool has_plcp; -}; - -#define AR9170_NUM_MAX_BA_RETRY 5 -#define AR9170_NUM_TID 16 -#define WME_BA_BMP_SIZE 64 -#define AR9170_NUM_MAX_AGG_LEN (2 * WME_BA_BMP_SIZE) - -#define WME_AC_BE 2 -#define WME_AC_BK 3 -#define WME_AC_VI 1 -#define WME_AC_VO 0 - -#define TID_TO_WME_AC(_tid) \ - ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ - (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ - (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ - WME_AC_VO) - -#define BAW_WITHIN(_start, _bawsz, _seqno) \ - ((((_seqno) - (_start)) & 0xfff) < (_bawsz)) - -enum ar9170_tid_state { - AR9170_TID_STATE_INVALID, - AR9170_TID_STATE_SHUTDOWN, - AR9170_TID_STATE_PROGRESS, - AR9170_TID_STATE_COMPLETE, -}; - -struct ar9170_sta_tid { - struct list_head list; - struct sk_buff_head queue; - u8 addr[ETH_ALEN]; - u16 ssn; - u16 tid; - enum ar9170_tid_state state; - bool active; - u8 retry; -}; - -#define AR9170_QUEUE_TIMEOUT 64 -#define AR9170_TX_TIMEOUT 8 -#define AR9170_BA_TIMEOUT 4 -#define AR9170_JANITOR_DELAY 128 -#define AR9170_TX_INVALID_RATE 0xffffffff - -#define AR9170_NUM_TX_STATUS 128 -#define AR9170_NUM_TX_AGG_MAX 30 - -struct ar9170 { - struct ieee80211_hw *hw; - struct ath_common common; - struct mutex mutex; - enum ar9170_device_state state; - unsigned long bad_hw_nagger; - - int (*open)(struct ar9170 *); - void (*stop)(struct ar9170 *); - int (*tx)(struct ar9170 *, struct sk_buff *); - int (*exec_cmd)(struct ar9170 *, enum ar9170_cmd, u32 , - void *, u32 , void *); - void (*callback_cmd)(struct ar9170 *, u32 , void *); - int (*flush)(struct ar9170 *); - - /* interface mode settings */ - struct ieee80211_vif *vif; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - - /* beaconing */ - struct sk_buff *beacon; - struct work_struct beacon_work; - bool enable_beacon; - - /* cryptographic engine */ - u64 usedkeys; - bool rx_software_decryption; - bool disable_offload; - - /* filter settings */ - u64 cur_mc_hash; - u32 cur_filter; - unsigned int filter_state; - bool sniffer_enabled; - - /* PHY */ - struct ieee80211_channel *channel; - int noise[4]; - - /* power calibration data */ - u8 power_5G_leg[4]; - u8 power_2G_cck[4]; - u8 power_2G_ofdm[4]; - u8 power_5G_ht20[8]; - u8 power_5G_ht40[8]; - u8 power_2G_ht20[8]; - u8 power_2G_ht40[8]; - -#ifdef CONFIG_AR9170_LEDS - struct delayed_work led_work; - struct ar9170_led leds[AR9170_NUM_LEDS]; -#endif /* CONFIG_AR9170_LEDS */ - - /* qos queue settings */ - spinlock_t tx_stats_lock; - struct ieee80211_tx_queue_stats tx_stats[5]; - struct ieee80211_tx_queue_params edcf[5]; - - spinlock_t cmdlock; - __le32 cmdbuf[PAYLOAD_MAX + 1]; - - /* MAC statistics */ - struct ieee80211_low_level_stats stats; - - /* EEPROM */ - struct ar9170_eeprom eeprom; - - /* tx queues - as seen by hw - */ - struct sk_buff_head tx_pending[__AR9170_NUM_TXQ]; - struct sk_buff_head tx_status[__AR9170_NUM_TXQ]; - struct delayed_work tx_janitor; - /* tx ampdu */ - struct sk_buff_head tx_status_ampdu; - spinlock_t tx_ampdu_list_lock; - struct list_head tx_ampdu_list; - unsigned int tx_ampdu_pending; - - /* rxstream mpdu merge */ - struct ar9170_rxstream_mpdu_merge rx_mpdu; - struct sk_buff *rx_failover; - int rx_failover_missing; - - /* (cached) HW A-MPDU settings */ - u8 global_ampdu_density; - u8 global_ampdu_factor; -}; - -struct ar9170_sta_info { - struct ar9170_sta_tid agg[AR9170_NUM_TID]; - unsigned int ampdu_max_len; -}; - -#define AR9170_TX_FLAG_WAIT_FOR_ACK BIT(0) -#define AR9170_TX_FLAG_NO_ACK BIT(1) -#define AR9170_TX_FLAG_BLOCK_ACK BIT(2) - -struct ar9170_tx_info { - unsigned long timeout; - unsigned int flags; -}; - -#define IS_STARTED(a) (((struct ar9170 *)a)->state >= AR9170_STARTED) -#define IS_ACCEPTING_CMD(a) (((struct ar9170 *)a)->state >= AR9170_IDLE) - -/* exported interface */ -void *ar9170_alloc(size_t priv_size); -int ar9170_register(struct ar9170 *ar, struct device *pdev); -void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb); -void ar9170_unregister(struct ar9170 *ar); -void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb); -void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len); -int ar9170_nag_limiter(struct ar9170 *ar); - -/* MAC */ -int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -int ar9170_init_mac(struct ar9170 *ar); -int ar9170_set_qos(struct ar9170 *ar); -int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hast); -int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter); -int ar9170_set_operating_mode(struct ar9170 *ar); -int ar9170_set_beacon_timers(struct ar9170 *ar); -int ar9170_set_dyn_sifs_ack(struct ar9170 *ar); -int ar9170_set_slot_time(struct ar9170 *ar); -int ar9170_set_basic_rates(struct ar9170 *ar); -int ar9170_set_hwretry_limit(struct ar9170 *ar, u32 max_retry); -int ar9170_update_beacon(struct ar9170 *ar); -void ar9170_new_beacon(struct work_struct *work); -int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, - u8 keyidx, u8 *keydata, int keylen); -int ar9170_disable_key(struct ar9170 *ar, u8 id); - -/* LEDs */ -#ifdef CONFIG_AR9170_LEDS -int ar9170_register_leds(struct ar9170 *ar); -void ar9170_unregister_leds(struct ar9170 *ar); -#endif /* CONFIG_AR9170_LEDS */ -int ar9170_init_leds(struct ar9170 *ar); -int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state); - -/* PHY / RF */ -int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band); -int ar9170_init_rf(struct ar9170 *ar); -int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum ar9170_rf_init_mode rfi, enum ar9170_bw bw); - -#endif /* __AR9170_H */ diff --git a/drivers/net/wireless/ath/ar9170/cmd.c b/drivers/net/wireless/ath/ar9170/cmd.c deleted file mode 100644 index f57a6200167b..000000000000 --- a/drivers/net/wireless/ath/ar9170/cmd.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Basic HW register/memory/command access functions - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ar9170.h" -#include "cmd.h" - -int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len) -{ - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - err = ar->exec_cmd(ar, AR9170_CMD_WMEM, len, (u8 *) data, 0, NULL); - if (err) - printk(KERN_DEBUG "%s: writing memory failed\n", - wiphy_name(ar->hw->wiphy)); - return err; -} - -int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val) -{ - __le32 buf[2] = { - cpu_to_le32(reg), - cpu_to_le32(val), - }; - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - err = ar->exec_cmd(ar, AR9170_CMD_WREG, sizeof(buf), - (u8 *) buf, 0, NULL); - if (err) - printk(KERN_DEBUG "%s: writing reg %#x (val %#x) failed\n", - wiphy_name(ar->hw->wiphy), reg, val); - return err; -} - -static int ar9170_read_mreg(struct ar9170 *ar, int nregs, - const u32 *regs, u32 *out) -{ - int i, err; - __le32 *offs, *res; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return 0; - - /* abuse "out" for the register offsets, must be same length */ - offs = (__le32 *)out; - for (i = 0; i < nregs; i++) - offs[i] = cpu_to_le32(regs[i]); - - /* also use the same buffer for the input */ - res = (__le32 *)out; - - err = ar->exec_cmd(ar, AR9170_CMD_RREG, - 4 * nregs, (u8 *)offs, - 4 * nregs, (u8 *)res); - if (err) - return err; - - /* convert result to cpu endian */ - for (i = 0; i < nregs; i++) - out[i] = le32_to_cpu(res[i]); - - return 0; -} - -int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val) -{ - return ar9170_read_mreg(ar, 1, ®, val); -} - -int ar9170_echo_test(struct ar9170 *ar, u32 v) -{ - __le32 echobuf = cpu_to_le32(v); - __le32 echores; - int err; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return -ENODEV; - - err = ar->exec_cmd(ar, AR9170_CMD_ECHO, - 4, (u8 *)&echobuf, - 4, (u8 *)&echores); - if (err) - return err; - - if (echobuf != echores) - return -EINVAL; - - return 0; -} diff --git a/drivers/net/wireless/ath/ar9170/cmd.h b/drivers/net/wireless/ath/ar9170/cmd.h deleted file mode 100644 index a4f0e50e52b4..000000000000 --- a/drivers/net/wireless/ath/ar9170/cmd.h +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Basic HW register/memory/command access functions - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __CMD_H -#define __CMD_H - -#include "ar9170.h" - -/* basic HW access */ -int ar9170_write_mem(struct ar9170 *ar, const __le32 *data, size_t len); -int ar9170_write_reg(struct ar9170 *ar, const u32 reg, const u32 val); -int ar9170_read_reg(struct ar9170 *ar, u32 reg, u32 *val); -int ar9170_echo_test(struct ar9170 *ar, u32 v); - -/* - * Macros to facilitate writing multiple registers in a single - * write-combining USB command. Note that when the first group - * fails the whole thing will fail without any others attempted, - * but you won't know which write in the group failed. - */ -#define ar9170_regwrite_begin(ar) \ -do { \ - int __nreg = 0, __err = 0; \ - struct ar9170 *__ar = ar; - -#define ar9170_regwrite(r, v) do { \ - __ar->cmdbuf[2 * __nreg + 1] = cpu_to_le32(r); \ - __ar->cmdbuf[2 * __nreg + 2] = cpu_to_le32(v); \ - __nreg++; \ - if ((__nreg >= PAYLOAD_MAX/2)) { \ - if (IS_ACCEPTING_CMD(__ar)) \ - __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ - (u8 *) &__ar->cmdbuf[1], \ - 0, NULL); \ - __nreg = 0; \ - if (__err) \ - goto __regwrite_out; \ - } \ -} while (0) - -#define ar9170_regwrite_finish() \ -__regwrite_out : \ - if (__nreg) { \ - if (IS_ACCEPTING_CMD(__ar)) \ - __err = ar->exec_cmd(__ar, AR9170_CMD_WREG, \ - 8 * __nreg, \ - (u8 *) &__ar->cmdbuf[1], \ - 0, NULL); \ - __nreg = 0; \ - } - -#define ar9170_regwrite_result() \ - __err; \ -} while (0); - -#endif /* __CMD_H */ diff --git a/drivers/net/wireless/ath/ar9170/eeprom.h b/drivers/net/wireless/ath/ar9170/eeprom.h deleted file mode 100644 index d2c8cc83f1dd..000000000000 --- a/drivers/net/wireless/ath/ar9170/eeprom.h +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Atheros AR9170 driver - * - * EEPROM layout - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __AR9170_EEPROM_H -#define __AR9170_EEPROM_H - -#define AR5416_MAX_CHAINS 2 -#define AR5416_MODAL_SPURS 5 - -struct ar9170_eeprom_modal { - __le32 antCtrlChain[AR5416_MAX_CHAINS]; - __le32 antCtrlCommon; - s8 antennaGainCh[AR5416_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR5416_MAX_CHAINS]; - u8 rxTxMarginCh[AR5416_MAX_CHAINS]; - s8 adcDesiredSize; - s8 pgaDesiredSize; - u8 xlnaGainCh[AR5416_MAX_CHAINS]; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - s8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - s8 iqCalICh[AR5416_MAX_CHAINS]; - s8 iqCalQCh[AR5416_MAX_CHAINS]; - u8 pdGainOverlap; - u8 ob; - u8 db; - u8 xpaBiasLvl; - u8 pwrDecreaseFor2Chain; - u8 pwrDecreaseFor3Chain; - u8 txFrameToDataStart; - u8 txFrameToPaOn; - u8 ht40PowerIncForPdadc; - u8 bswAtten[AR5416_MAX_CHAINS]; - u8 bswMargin[AR5416_MAX_CHAINS]; - u8 swSettleHt40; - u8 reserved[22]; - struct spur_channel { - __le16 spurChan; - u8 spurRangeLow; - u8 spurRangeHigh; - } __packed spur_channels[AR5416_MODAL_SPURS]; -} __packed; - -#define AR5416_NUM_PD_GAINS 4 -#define AR5416_PD_GAIN_ICEPTS 5 - -struct ar9170_calibration_data_per_freq { - u8 pwr_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; - u8 vpd_pdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; -} __packed; - -#define AR5416_NUM_5G_CAL_PIERS 8 -#define AR5416_NUM_2G_CAL_PIERS 4 - -#define AR5416_NUM_5G_TARGET_PWRS 8 -#define AR5416_NUM_2G_CCK_TARGET_PWRS 3 -#define AR5416_NUM_2G_OFDM_TARGET_PWRS 4 -#define AR5416_MAX_NUM_TGT_PWRS 8 - -struct ar9170_calibration_target_power_legacy { - u8 freq; - u8 power[4]; -} __packed; - -struct ar9170_calibration_target_power_ht { - u8 freq; - u8 power[8]; -} __packed; - -#define AR5416_NUM_CTLS 24 - -struct ar9170_calctl_edges { - u8 channel; -#define AR9170_CALCTL_EDGE_FLAGS 0xC0 - u8 power_flags; -} __packed; - -#define AR5416_NUM_BAND_EDGES 8 - -struct ar9170_calctl_data { - struct ar9170_calctl_edges - control_edges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; -} __packed; - - -struct ar9170_eeprom { - __le16 length; - __le16 checksum; - __le16 version; - u8 operating_flags; -#define AR9170_OPFLAG_5GHZ 1 -#define AR9170_OPFLAG_2GHZ 2 - u8 misc; - __le16 reg_domain[2]; - u8 mac_address[6]; - u8 rx_mask; - u8 tx_mask; - __le16 rf_silent; - __le16 bluetooth_options; - __le16 device_capabilities; - __le32 build_number; - u8 deviceType; - u8 reserved[33]; - - u8 customer_data[64]; - - struct ar9170_eeprom_modal - modal_header[2]; - - u8 cal_freq_pier_5G[AR5416_NUM_5G_CAL_PIERS]; - u8 cal_freq_pier_2G[AR5416_NUM_2G_CAL_PIERS]; - - struct ar9170_calibration_data_per_freq - cal_pier_data_5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS], - cal_pier_data_2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; - - /* power calibration data */ - struct ar9170_calibration_target_power_legacy - cal_tgt_pwr_5G[AR5416_NUM_5G_TARGET_PWRS]; - struct ar9170_calibration_target_power_ht - cal_tgt_pwr_5G_ht20[AR5416_NUM_5G_TARGET_PWRS], - cal_tgt_pwr_5G_ht40[AR5416_NUM_5G_TARGET_PWRS]; - - struct ar9170_calibration_target_power_legacy - cal_tgt_pwr_2G_cck[AR5416_NUM_2G_CCK_TARGET_PWRS], - cal_tgt_pwr_2G_ofdm[AR5416_NUM_2G_OFDM_TARGET_PWRS]; - struct ar9170_calibration_target_power_ht - cal_tgt_pwr_2G_ht20[AR5416_NUM_2G_OFDM_TARGET_PWRS], - cal_tgt_pwr_2G_ht40[AR5416_NUM_2G_OFDM_TARGET_PWRS]; - - /* conformance testing limits */ - u8 ctl_index[AR5416_NUM_CTLS]; - struct ar9170_calctl_data - ctl_data[AR5416_NUM_CTLS]; - - u8 pad; - __le16 subsystem_id; -} __packed; - -#endif /* __AR9170_EEPROM_H */ diff --git a/drivers/net/wireless/ath/ar9170/hw.h b/drivers/net/wireless/ath/ar9170/hw.h deleted file mode 100644 index 3931181f4d93..000000000000 --- a/drivers/net/wireless/ath/ar9170/hw.h +++ /dev/null @@ -1,427 +0,0 @@ -/* - * Atheros AR9170 driver - * - * Hardware-specific definitions - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __AR9170_HW_H -#define __AR9170_HW_H - -#define AR9170_MAX_CMD_LEN 64 - -enum ar9170_cmd { - AR9170_CMD_RREG = 0x00, - AR9170_CMD_WREG = 0x01, - AR9170_CMD_RMEM = 0x02, - AR9170_CMD_WMEM = 0x03, - AR9170_CMD_BITAND = 0x04, - AR9170_CMD_BITOR = 0x05, - AR9170_CMD_EKEY = 0x28, - AR9170_CMD_DKEY = 0x29, - AR9170_CMD_FREQUENCY = 0x30, - AR9170_CMD_RF_INIT = 0x31, - AR9170_CMD_SYNTH = 0x32, - AR9170_CMD_FREQ_START = 0x33, - AR9170_CMD_ECHO = 0x80, - AR9170_CMD_TALLY = 0x81, - AR9170_CMD_TALLY_APD = 0x82, - AR9170_CMD_CONFIG = 0x83, - AR9170_CMD_RESET = 0x90, - AR9170_CMD_DKRESET = 0x91, - AR9170_CMD_DKTX_STATUS = 0x92, - AR9170_CMD_FDC = 0xA0, - AR9170_CMD_WREEPROM = 0xB0, - AR9170_CMD_WFLASH = 0xB0, - AR9170_CMD_FLASH_ERASE = 0xB1, - AR9170_CMD_FLASH_PROG = 0xB2, - AR9170_CMD_FLASH_CHKSUM = 0xB3, - AR9170_CMD_FLASH_READ = 0xB4, - AR9170_CMD_FW_DL_INIT = 0xB5, - AR9170_CMD_MEM_WREEPROM = 0xBB, -}; - -/* endpoints */ -#define AR9170_EP_TX 1 -#define AR9170_EP_RX 2 -#define AR9170_EP_IRQ 3 -#define AR9170_EP_CMD 4 - -#define AR9170_EEPROM_START 0x1600 - -#define AR9170_GPIO_REG_BASE 0x1d0100 -#define AR9170_GPIO_REG_PORT_TYPE AR9170_GPIO_REG_BASE -#define AR9170_GPIO_REG_DATA (AR9170_GPIO_REG_BASE + 4) -#define AR9170_NUM_LEDS 2 - - -#define AR9170_USB_REG_BASE 0x1e1000 -#define AR9170_USB_REG_DMA_CTL (AR9170_USB_REG_BASE + 0x108) -#define AR9170_DMA_CTL_ENABLE_TO_DEVICE 0x1 -#define AR9170_DMA_CTL_ENABLE_FROM_DEVICE 0x2 -#define AR9170_DMA_CTL_HIGH_SPEED 0x4 -#define AR9170_DMA_CTL_PACKET_MODE 0x8 - -#define AR9170_USB_REG_MAX_AGG_UPLOAD (AR9170_USB_REG_BASE + 0x110) -#define AR9170_USB_REG_UPLOAD_TIME_CTL (AR9170_USB_REG_BASE + 0x114) - - - -#define AR9170_MAC_REG_BASE 0x1c3000 - -#define AR9170_MAC_REG_TSF_L (AR9170_MAC_REG_BASE + 0x514) -#define AR9170_MAC_REG_TSF_H (AR9170_MAC_REG_BASE + 0x518) - -#define AR9170_MAC_REG_ATIM_WINDOW (AR9170_MAC_REG_BASE + 0x51C) -#define AR9170_MAC_REG_BCN_PERIOD (AR9170_MAC_REG_BASE + 0x520) -#define AR9170_MAC_REG_PRETBTT (AR9170_MAC_REG_BASE + 0x524) - -#define AR9170_MAC_REG_MAC_ADDR_L (AR9170_MAC_REG_BASE + 0x610) -#define AR9170_MAC_REG_MAC_ADDR_H (AR9170_MAC_REG_BASE + 0x614) -#define AR9170_MAC_REG_BSSID_L (AR9170_MAC_REG_BASE + 0x618) -#define AR9170_MAC_REG_BSSID_H (AR9170_MAC_REG_BASE + 0x61c) - -#define AR9170_MAC_REG_GROUP_HASH_TBL_L (AR9170_MAC_REG_BASE + 0x624) -#define AR9170_MAC_REG_GROUP_HASH_TBL_H (AR9170_MAC_REG_BASE + 0x628) - -#define AR9170_MAC_REG_RX_TIMEOUT (AR9170_MAC_REG_BASE + 0x62C) - -#define AR9170_MAC_REG_BASIC_RATE (AR9170_MAC_REG_BASE + 0x630) -#define AR9170_MAC_REG_MANDATORY_RATE (AR9170_MAC_REG_BASE + 0x634) -#define AR9170_MAC_REG_RTS_CTS_RATE (AR9170_MAC_REG_BASE + 0x638) -#define AR9170_MAC_REG_BACKOFF_PROTECT (AR9170_MAC_REG_BASE + 0x63c) -#define AR9170_MAC_REG_RX_THRESHOLD (AR9170_MAC_REG_BASE + 0x640) -#define AR9170_MAC_REG_RX_PE_DELAY (AR9170_MAC_REG_BASE + 0x64C) - -#define AR9170_MAC_REG_DYNAMIC_SIFS_ACK (AR9170_MAC_REG_BASE + 0x658) -#define AR9170_MAC_REG_SNIFFER (AR9170_MAC_REG_BASE + 0x674) -#define AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC BIT(0) -#define AR9170_MAC_REG_SNIFFER_DEFAULTS 0x02000000 -#define AR9170_MAC_REG_ENCRYPTION (AR9170_MAC_REG_BASE + 0x678) -#define AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE BIT(3) -#define AR9170_MAC_REG_ENCRYPTION_DEFAULTS 0x70 - -#define AR9170_MAC_REG_MISC_680 (AR9170_MAC_REG_BASE + 0x680) -#define AR9170_MAC_REG_TX_UNDERRUN (AR9170_MAC_REG_BASE + 0x688) - -#define AR9170_MAC_REG_FRAMETYPE_FILTER (AR9170_MAC_REG_BASE + 0x68c) -#define AR9170_MAC_REG_FTF_ASSOC_REQ BIT(0) -#define AR9170_MAC_REG_FTF_ASSOC_RESP BIT(1) -#define AR9170_MAC_REG_FTF_REASSOC_REQ BIT(2) -#define AR9170_MAC_REG_FTF_REASSOC_RESP BIT(3) -#define AR9170_MAC_REG_FTF_PRB_REQ BIT(4) -#define AR9170_MAC_REG_FTF_PRB_RESP BIT(5) -#define AR9170_MAC_REG_FTF_BIT6 BIT(6) -#define AR9170_MAC_REG_FTF_BIT7 BIT(7) -#define AR9170_MAC_REG_FTF_BEACON BIT(8) -#define AR9170_MAC_REG_FTF_ATIM BIT(9) -#define AR9170_MAC_REG_FTF_DEASSOC BIT(10) -#define AR9170_MAC_REG_FTF_AUTH BIT(11) -#define AR9170_MAC_REG_FTF_DEAUTH BIT(12) -#define AR9170_MAC_REG_FTF_BIT13 BIT(13) -#define AR9170_MAC_REG_FTF_BIT14 BIT(14) -#define AR9170_MAC_REG_FTF_BIT15 BIT(15) -#define AR9170_MAC_REG_FTF_BAR BIT(24) -#define AR9170_MAC_REG_FTF_BIT25 BIT(25) -#define AR9170_MAC_REG_FTF_PSPOLL BIT(26) -#define AR9170_MAC_REG_FTF_RTS BIT(27) -#define AR9170_MAC_REG_FTF_CTS BIT(28) -#define AR9170_MAC_REG_FTF_ACK BIT(29) -#define AR9170_MAC_REG_FTF_CFE BIT(30) -#define AR9170_MAC_REG_FTF_CFE_ACK BIT(31) -#define AR9170_MAC_REG_FTF_DEFAULTS 0x0500ffff -#define AR9170_MAC_REG_FTF_MONITOR 0xfd00ffff - -#define AR9170_MAC_REG_RX_TOTAL (AR9170_MAC_REG_BASE + 0x6A0) -#define AR9170_MAC_REG_RX_CRC32 (AR9170_MAC_REG_BASE + 0x6A4) -#define AR9170_MAC_REG_RX_CRC16 (AR9170_MAC_REG_BASE + 0x6A8) -#define AR9170_MAC_REG_RX_ERR_DECRYPTION_UNI (AR9170_MAC_REG_BASE + 0x6AC) -#define AR9170_MAC_REG_RX_OVERRUN (AR9170_MAC_REG_BASE + 0x6B0) -#define AR9170_MAC_REG_RX_ERR_DECRYPTION_MUL (AR9170_MAC_REG_BASE + 0x6BC) -#define AR9170_MAC_REG_TX_RETRY (AR9170_MAC_REG_BASE + 0x6CC) -#define AR9170_MAC_REG_TX_TOTAL (AR9170_MAC_REG_BASE + 0x6F4) - - -#define AR9170_MAC_REG_ACK_EXTENSION (AR9170_MAC_REG_BASE + 0x690) -#define AR9170_MAC_REG_EIFS_AND_SIFS (AR9170_MAC_REG_BASE + 0x698) - -#define AR9170_MAC_REG_SLOT_TIME (AR9170_MAC_REG_BASE + 0x6F0) - -#define AR9170_MAC_REG_POWERMANAGEMENT (AR9170_MAC_REG_BASE + 0x700) -#define AR9170_MAC_REG_POWERMGT_IBSS 0xe0 -#define AR9170_MAC_REG_POWERMGT_AP 0xa1 -#define AR9170_MAC_REG_POWERMGT_STA 0x2 -#define AR9170_MAC_REG_POWERMGT_AP_WDS 0x3 -#define AR9170_MAC_REG_POWERMGT_DEFAULTS (0xf << 24) - -#define AR9170_MAC_REG_ROLL_CALL_TBL_L (AR9170_MAC_REG_BASE + 0x704) -#define AR9170_MAC_REG_ROLL_CALL_TBL_H (AR9170_MAC_REG_BASE + 0x708) - -#define AR9170_MAC_REG_AC0_CW (AR9170_MAC_REG_BASE + 0xB00) -#define AR9170_MAC_REG_AC1_CW (AR9170_MAC_REG_BASE + 0xB04) -#define AR9170_MAC_REG_AC2_CW (AR9170_MAC_REG_BASE + 0xB08) -#define AR9170_MAC_REG_AC3_CW (AR9170_MAC_REG_BASE + 0xB0C) -#define AR9170_MAC_REG_AC4_CW (AR9170_MAC_REG_BASE + 0xB10) -#define AR9170_MAC_REG_AC1_AC0_AIFS (AR9170_MAC_REG_BASE + 0xB14) -#define AR9170_MAC_REG_AC3_AC2_AIFS (AR9170_MAC_REG_BASE + 0xB18) - -#define AR9170_MAC_REG_RETRY_MAX (AR9170_MAC_REG_BASE + 0xB28) - -#define AR9170_MAC_REG_FCS_SELECT (AR9170_MAC_REG_BASE + 0xBB0) -#define AR9170_MAC_FCS_SWFCS 0x1 -#define AR9170_MAC_FCS_FIFO_PROT 0x4 - - -#define AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND (AR9170_MAC_REG_BASE + 0xB30) - -#define AR9170_MAC_REG_AC1_AC0_TXOP (AR9170_MAC_REG_BASE + 0xB44) -#define AR9170_MAC_REG_AC3_AC2_TXOP (AR9170_MAC_REG_BASE + 0xB48) - -#define AR9170_MAC_REG_AMPDU_FACTOR (AR9170_MAC_REG_BASE + 0xB9C) -#define AR9170_MAC_REG_AMPDU_DENSITY (AR9170_MAC_REG_BASE + 0xBA0) - -#define AR9170_MAC_REG_ACK_TABLE (AR9170_MAC_REG_BASE + 0xC00) -#define AR9170_MAC_REG_AMPDU_RX_THRESH (AR9170_MAC_REG_BASE + 0xC50) - -#define AR9170_MAC_REG_TXRX_MPI (AR9170_MAC_REG_BASE + 0xD7C) -#define AR9170_MAC_TXRX_MPI_TX_MPI_MASK 0x0000000f -#define AR9170_MAC_TXRX_MPI_TX_TO_MASK 0x0000fff0 -#define AR9170_MAC_TXRX_MPI_RX_MPI_MASK 0x000f0000 -#define AR9170_MAC_TXRX_MPI_RX_TO_MASK 0xfff00000 - -#define AR9170_MAC_REG_BCN_ADDR (AR9170_MAC_REG_BASE + 0xD84) -#define AR9170_MAC_REG_BCN_LENGTH (AR9170_MAC_REG_BASE + 0xD88) -#define AR9170_MAC_REG_BCN_PLCP (AR9170_MAC_REG_BASE + 0xD90) -#define AR9170_MAC_REG_BCN_CTRL (AR9170_MAC_REG_BASE + 0xD94) -#define AR9170_MAC_REG_BCN_HT1 (AR9170_MAC_REG_BASE + 0xDA0) -#define AR9170_MAC_REG_BCN_HT2 (AR9170_MAC_REG_BASE + 0xDA4) - - -#define AR9170_PWR_REG_BASE 0x1D4000 - -#define AR9170_PWR_REG_CLOCK_SEL (AR9170_PWR_REG_BASE + 0x008) -#define AR9170_PWR_CLK_AHB_40MHZ 0 -#define AR9170_PWR_CLK_AHB_20_22MHZ 1 -#define AR9170_PWR_CLK_AHB_40_44MHZ 2 -#define AR9170_PWR_CLK_AHB_80_88MHZ 3 -#define AR9170_PWR_CLK_DAC_160_INV_DLY 0x70 - - -/* put beacon here in memory */ -#define AR9170_BEACON_BUFFER_ADDRESS 0x117900 - - -struct ar9170_tx_control { - __le16 length; - __le16 mac_control; - __le32 phy_control; - u8 frame_data[0]; -} __packed; - -/* these are either-or */ -#define AR9170_TX_MAC_PROT_RTS 0x0001 -#define AR9170_TX_MAC_PROT_CTS 0x0002 - -#define AR9170_TX_MAC_NO_ACK 0x0004 -/* if unset, MAC will only do SIFS space before frame */ -#define AR9170_TX_MAC_BACKOFF 0x0008 -#define AR9170_TX_MAC_BURST 0x0010 -#define AR9170_TX_MAC_AGGR 0x0020 - -/* encryption is a two-bit field */ -#define AR9170_TX_MAC_ENCR_NONE 0x0000 -#define AR9170_TX_MAC_ENCR_RC4 0x0040 -#define AR9170_TX_MAC_ENCR_CENC 0x0080 -#define AR9170_TX_MAC_ENCR_AES 0x00c0 - -#define AR9170_TX_MAC_MMIC 0x0100 -#define AR9170_TX_MAC_HW_DURATION 0x0200 -#define AR9170_TX_MAC_QOS_SHIFT 10 -#define AR9170_TX_MAC_QOS_MASK (3 << AR9170_TX_MAC_QOS_SHIFT) -#define AR9170_TX_MAC_AGGR_QOS_BIT1 0x0400 -#define AR9170_TX_MAC_AGGR_QOS_BIT2 0x0800 -#define AR9170_TX_MAC_DISABLE_TXOP 0x1000 -#define AR9170_TX_MAC_TXOP_RIFS 0x2000 -#define AR9170_TX_MAC_IMM_AMPDU 0x4000 -#define AR9170_TX_MAC_RATE_PROBE 0x8000 - -/* either-or */ -#define AR9170_TX_PHY_MOD_CCK 0x00000000 -#define AR9170_TX_PHY_MOD_OFDM 0x00000001 -#define AR9170_TX_PHY_MOD_HT 0x00000002 - -/* depends on modulation */ -#define AR9170_TX_PHY_SHORT_PREAMBLE 0x00000004 -#define AR9170_TX_PHY_GREENFIELD 0x00000004 - -#define AR9170_TX_PHY_BW_SHIFT 3 -#define AR9170_TX_PHY_BW_MASK (3 << AR9170_TX_PHY_BW_SHIFT) -#define AR9170_TX_PHY_BW_20MHZ 0 -#define AR9170_TX_PHY_BW_40MHZ 2 -#define AR9170_TX_PHY_BW_40MHZ_DUP 3 - -#define AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT 6 -#define AR9170_TX_PHY_TX_HEAVY_CLIP_MASK (7 << AR9170_TX_PHY_TX_HEAVY_CLIP_SHIFT) - -#define AR9170_TX_PHY_TX_PWR_SHIFT 9 -#define AR9170_TX_PHY_TX_PWR_MASK (0x3f << AR9170_TX_PHY_TX_PWR_SHIFT) - -/* not part of the hw-spec */ -#define AR9170_TX_PHY_QOS_SHIFT 25 -#define AR9170_TX_PHY_QOS_MASK (3 << AR9170_TX_PHY_QOS_SHIFT) - -#define AR9170_TX_PHY_TXCHAIN_SHIFT 15 -#define AR9170_TX_PHY_TXCHAIN_MASK (7 << AR9170_TX_PHY_TXCHAIN_SHIFT) -#define AR9170_TX_PHY_TXCHAIN_1 1 -/* use for cck, ofdm 6/9/12/18/24 and HT if capable */ -#define AR9170_TX_PHY_TXCHAIN_2 5 - -#define AR9170_TX_PHY_MCS_SHIFT 18 -#define AR9170_TX_PHY_MCS_MASK (0x7f << AR9170_TX_PHY_MCS_SHIFT) - -#define AR9170_TX_PHY_SHORT_GI 0x80000000 - -struct ar9170_rx_head { - u8 plcp[12]; -} __packed; - -struct ar9170_rx_phystatus { - union { - struct { - u8 rssi_ant0, rssi_ant1, rssi_ant2, - rssi_ant0x, rssi_ant1x, rssi_ant2x, - rssi_combined; - } __packed; - u8 rssi[7]; - } __packed; - - u8 evm_stream0[6], evm_stream1[6]; - u8 phy_err; -} __packed; - -struct ar9170_rx_macstatus { - u8 SAidx, DAidx; - u8 error; - u8 status; -} __packed; - -#define AR9170_ENC_ALG_NONE 0x0 -#define AR9170_ENC_ALG_WEP64 0x1 -#define AR9170_ENC_ALG_TKIP 0x2 -#define AR9170_ENC_ALG_AESCCMP 0x4 -#define AR9170_ENC_ALG_WEP128 0x5 -#define AR9170_ENC_ALG_WEP256 0x6 -#define AR9170_ENC_ALG_CENC 0x7 - -#define AR9170_RX_ENC_SOFTWARE 0x8 - -static inline u8 ar9170_get_decrypt_type(struct ar9170_rx_macstatus *t) -{ - return (t->SAidx & 0xc0) >> 4 | - (t->DAidx & 0xc0) >> 6; -} - -#define AR9170_RX_STATUS_MODULATION_MASK 0x03 -#define AR9170_RX_STATUS_MODULATION_CCK 0x00 -#define AR9170_RX_STATUS_MODULATION_OFDM 0x01 -#define AR9170_RX_STATUS_MODULATION_HT 0x02 -#define AR9170_RX_STATUS_MODULATION_DUPOFDM 0x03 - -/* depends on modulation */ -#define AR9170_RX_STATUS_SHORT_PREAMBLE 0x08 -#define AR9170_RX_STATUS_GREENFIELD 0x08 - -#define AR9170_RX_STATUS_MPDU_MASK 0x30 -#define AR9170_RX_STATUS_MPDU_SINGLE 0x00 -#define AR9170_RX_STATUS_MPDU_FIRST 0x20 -#define AR9170_RX_STATUS_MPDU_MIDDLE 0x30 -#define AR9170_RX_STATUS_MPDU_LAST 0x10 - -#define AR9170_RX_ERROR_RXTO 0x01 -#define AR9170_RX_ERROR_OVERRUN 0x02 -#define AR9170_RX_ERROR_DECRYPT 0x04 -#define AR9170_RX_ERROR_FCS 0x08 -#define AR9170_RX_ERROR_WRONG_RA 0x10 -#define AR9170_RX_ERROR_PLCP 0x20 -#define AR9170_RX_ERROR_MMIC 0x40 -#define AR9170_RX_ERROR_FATAL 0x80 - -struct ar9170_cmd_tx_status { - u8 dst[ETH_ALEN]; - __le32 rate; - __le16 status; -} __packed; - -#define AR9170_TX_STATUS_COMPLETE 0x00 -#define AR9170_TX_STATUS_RETRY 0x01 -#define AR9170_TX_STATUS_FAILED 0x02 - -struct ar9170_cmd_ba_failed_count { - __le16 failed; - __le16 rate; -} __packed; - -struct ar9170_cmd_response { - u8 flag; - u8 type; - __le16 padding; - - union { - struct ar9170_cmd_tx_status tx_status; - struct ar9170_cmd_ba_failed_count ba_fail_cnt; - u8 data[0]; - }; -} __packed; - -/* QoS */ - -/* mac80211 queue to HW/FW map */ -static const u8 ar9170_qos_hwmap[4] = { 3, 2, 0, 1 }; - -/* HW/FW queue to mac80211 map */ -static const u8 ar9170_qos_mac80211map[4] = { 2, 3, 1, 0 }; - -enum ar9170_txq { - AR9170_TXQ_BE, - AR9170_TXQ_BK, - AR9170_TXQ_VI, - AR9170_TXQ_VO, - - __AR9170_NUM_TXQ, -}; - -#define AR9170_TXQ_DEPTH 32 -#define AR9170_TX_MAX_PENDING 128 -#define AR9170_RX_STREAM_MAX_SIZE 65535 - -#endif /* __AR9170_HW_H */ diff --git a/drivers/net/wireless/ath/ar9170/led.c b/drivers/net/wireless/ath/ar9170/led.c deleted file mode 100644 index 86c4e79f6bc8..000000000000 --- a/drivers/net/wireless/ath/ar9170/led.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Atheros AR9170 driver - * - * LED handling - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ar9170.h" -#include "cmd.h" - -int ar9170_set_leds_state(struct ar9170 *ar, u32 led_state) -{ - return ar9170_write_reg(ar, AR9170_GPIO_REG_DATA, led_state); -} - -int ar9170_init_leds(struct ar9170 *ar) -{ - int err; - - /* disable LEDs */ - /* GPIO [0/1 mode: output, 2/3: input] */ - err = ar9170_write_reg(ar, AR9170_GPIO_REG_PORT_TYPE, 3); - if (err) - goto out; - - /* GPIO 0/1 value: off */ - err = ar9170_set_leds_state(ar, 0); - -out: - return err; -} - -#ifdef CONFIG_AR9170_LEDS -static void ar9170_update_leds(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, led_work.work); - int i, tmp, blink_delay = 1000; - u32 led_val = 0; - bool rerun = false; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return ; - - mutex_lock(&ar->mutex); - for (i = 0; i < AR9170_NUM_LEDS; i++) - if (ar->leds[i].registered && ar->leds[i].toggled) { - led_val |= 1 << i; - - tmp = 70 + 200 / (ar->leds[i].toggled); - if (tmp < blink_delay) - blink_delay = tmp; - - if (ar->leds[i].toggled > 1) - ar->leds[i].toggled = 0; - - rerun = true; - } - - ar9170_set_leds_state(ar, led_val); - mutex_unlock(&ar->mutex); - - if (!rerun) - return; - - ieee80211_queue_delayed_work(ar->hw, - &ar->led_work, - msecs_to_jiffies(blink_delay)); -} - -static void ar9170_led_brightness_set(struct led_classdev *led, - enum led_brightness brightness) -{ - struct ar9170_led *arl = container_of(led, struct ar9170_led, l); - struct ar9170 *ar = arl->ar; - - if (unlikely(!arl->registered)) - return ; - - if (arl->last_state != !!brightness) { - arl->toggled++; - arl->last_state = !!brightness; - } - - if (likely(IS_ACCEPTING_CMD(ar) && arl->toggled)) - ieee80211_queue_delayed_work(ar->hw, &ar->led_work, HZ/10); -} - -static int ar9170_register_led(struct ar9170 *ar, int i, char *name, - char *trigger) -{ - int err; - - snprintf(ar->leds[i].name, sizeof(ar->leds[i].name), - "ar9170-%s::%s", wiphy_name(ar->hw->wiphy), name); - - ar->leds[i].ar = ar; - ar->leds[i].l.name = ar->leds[i].name; - ar->leds[i].l.brightness_set = ar9170_led_brightness_set; - ar->leds[i].l.brightness = 0; - ar->leds[i].l.default_trigger = trigger; - - err = led_classdev_register(wiphy_dev(ar->hw->wiphy), - &ar->leds[i].l); - if (err) - printk(KERN_ERR "%s: failed to register %s LED (%d).\n", - wiphy_name(ar->hw->wiphy), ar->leds[i].name, err); - else - ar->leds[i].registered = true; - - return err; -} - -void ar9170_unregister_leds(struct ar9170 *ar) -{ - int i; - - for (i = 0; i < AR9170_NUM_LEDS; i++) - if (ar->leds[i].registered) { - led_classdev_unregister(&ar->leds[i].l); - ar->leds[i].registered = false; - ar->leds[i].toggled = 0; - } - - cancel_delayed_work_sync(&ar->led_work); -} - -int ar9170_register_leds(struct ar9170 *ar) -{ - int err; - - INIT_DELAYED_WORK(&ar->led_work, ar9170_update_leds); - - err = ar9170_register_led(ar, 0, "tx", - ieee80211_get_tx_led_name(ar->hw)); - if (err) - goto fail; - - err = ar9170_register_led(ar, 1, "assoc", - ieee80211_get_assoc_led_name(ar->hw)); - if (err) - goto fail; - - return 0; - -fail: - ar9170_unregister_leds(ar); - return err; -} - -#endif /* CONFIG_AR9170_LEDS */ diff --git a/drivers/net/wireless/ath/ar9170/mac.c b/drivers/net/wireless/ath/ar9170/mac.c deleted file mode 100644 index 614e3218a2bc..000000000000 --- a/drivers/net/wireless/ath/ar9170/mac.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * Atheros AR9170 driver - * - * MAC programming - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#include "ar9170.h" -#include "cmd.h" - -int ar9170_set_dyn_sifs_ack(struct ar9170 *ar) -{ - u32 val; - - if (conf_is_ht40(&ar->hw->conf)) - val = 0x010a; - else { - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) - val = 0x105; - else - val = 0x104; - } - - return ar9170_write_reg(ar, AR9170_MAC_REG_DYNAMIC_SIFS_ACK, val); -} - -int ar9170_set_slot_time(struct ar9170 *ar) -{ - u32 slottime = 20; - - if (!ar->vif) - return 0; - - if ((ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) || - ar->vif->bss_conf.use_short_slot) - slottime = 9; - - return ar9170_write_reg(ar, AR9170_MAC_REG_SLOT_TIME, slottime << 10); -} - -int ar9170_set_basic_rates(struct ar9170 *ar) -{ - u8 cck, ofdm; - - if (!ar->vif) - return 0; - - ofdm = ar->vif->bss_conf.basic_rates >> 4; - - /* FIXME: is still necessary? */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_5GHZ) - cck = 0; - else - cck = ar->vif->bss_conf.basic_rates & 0xf; - - return ar9170_write_reg(ar, AR9170_MAC_REG_BASIC_RATE, - ofdm << 8 | cck); -} - -int ar9170_set_qos(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_AC0_CW, ar->edcf[0].cw_min | - (ar->edcf[0].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC1_CW, ar->edcf[1].cw_min | - (ar->edcf[1].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC2_CW, ar->edcf[2].cw_min | - (ar->edcf[2].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC3_CW, ar->edcf[3].cw_min | - (ar->edcf[3].cw_max << 16)); - ar9170_regwrite(AR9170_MAC_REG_AC4_CW, ar->edcf[4].cw_min | - (ar->edcf[4].cw_max << 16)); - - ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_AIFS, - ((ar->edcf[0].aifs * 9 + 10)) | - ((ar->edcf[1].aifs * 9 + 10) << 12) | - ((ar->edcf[2].aifs * 9 + 10) << 24)); - ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_AIFS, - ((ar->edcf[2].aifs * 9 + 10) >> 8) | - ((ar->edcf[3].aifs * 9 + 10) << 4) | - ((ar->edcf[4].aifs * 9 + 10) << 16)); - - ar9170_regwrite(AR9170_MAC_REG_AC1_AC0_TXOP, - ar->edcf[0].txop | ar->edcf[1].txop << 16); - ar9170_regwrite(AR9170_MAC_REG_AC3_AC2_TXOP, - ar->edcf[1].txop | ar->edcf[3].txop << 16); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -static int ar9170_set_ampdu_density(struct ar9170 *ar, u8 mpdudensity) -{ - u32 val; - - /* don't allow AMPDU density > 8us */ - if (mpdudensity > 6) - return -EINVAL; - - /* Watch out! Otus uses slightly different density values. */ - val = 0x140a00 | (mpdudensity ? (mpdudensity + 1) : 0); - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_AMPDU_DENSITY, val); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_init_mac(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_ACK_EXTENSION, 0x40); - - ar9170_regwrite(AR9170_MAC_REG_RETRY_MAX, 0); - - /* enable MMIC */ - ar9170_regwrite(AR9170_MAC_REG_SNIFFER, - AR9170_MAC_REG_SNIFFER_DEFAULTS); - - ar9170_regwrite(AR9170_MAC_REG_RX_THRESHOLD, 0xc1f80); - - ar9170_regwrite(AR9170_MAC_REG_RX_PE_DELAY, 0x70); - ar9170_regwrite(AR9170_MAC_REG_EIFS_AND_SIFS, 0xa144000); - ar9170_regwrite(AR9170_MAC_REG_SLOT_TIME, 9 << 10); - - /* CF-END mode */ - ar9170_regwrite(0x1c3b2c, 0x19000000); - - /* NAV protects ACK only (in TXOP) */ - ar9170_regwrite(0x1c3b38, 0x201); - - /* Set Beacon PHY CTRL's TPC to 0x7, TA1=1 */ - /* OTUS set AM to 0x1 */ - ar9170_regwrite(AR9170_MAC_REG_BCN_HT1, 0x8000170); - - ar9170_regwrite(AR9170_MAC_REG_BACKOFF_PROTECT, 0x105); - - /* AGG test code*/ - /* Aggregation MAX number and timeout */ - ar9170_regwrite(0x1c3b9c, 0x10000a); - - ar9170_regwrite(AR9170_MAC_REG_FRAMETYPE_FILTER, - AR9170_MAC_REG_FTF_DEFAULTS); - - /* Enable deaggregator, response in sniffer mode */ - ar9170_regwrite(0x1c3c40, 0x1 | 1<<30); - - /* rate sets */ - ar9170_regwrite(AR9170_MAC_REG_BASIC_RATE, 0x150f); - ar9170_regwrite(AR9170_MAC_REG_MANDATORY_RATE, 0x150f); - ar9170_regwrite(AR9170_MAC_REG_RTS_CTS_RATE, 0x10b01bb); - - /* MIMO response control */ - ar9170_regwrite(0x1c3694, 0x4003C1E);/* bit 26~28 otus-AM */ - - /* switch MAC to OTUS interface */ - ar9170_regwrite(0x1c3600, 0x3); - - ar9170_regwrite(AR9170_MAC_REG_AMPDU_RX_THRESH, 0xffff); - - /* set PHY register read timeout (??) */ - ar9170_regwrite(AR9170_MAC_REG_MISC_680, 0xf00008); - - /* Disable Rx TimeOut, workaround for BB. */ - ar9170_regwrite(AR9170_MAC_REG_RX_TIMEOUT, 0x0); - - /* Set CPU clock frequency to 88/80MHz */ - ar9170_regwrite(AR9170_PWR_REG_CLOCK_SEL, - AR9170_PWR_CLK_AHB_80_88MHZ | - AR9170_PWR_CLK_DAC_160_INV_DLY); - - /* Set WLAN DMA interrupt mode: generate int per packet */ - ar9170_regwrite(AR9170_MAC_REG_TXRX_MPI, 0x110011); - - ar9170_regwrite(AR9170_MAC_REG_FCS_SELECT, - AR9170_MAC_FCS_FIFO_PROT); - - /* Disables the CF_END frame, undocumented register */ - ar9170_regwrite(AR9170_MAC_REG_TXOP_NOT_ENOUGH_IND, - 0x141E0F48); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -static int ar9170_set_mac_reg(struct ar9170 *ar, const u32 reg, const u8 *mac) -{ - static const u8 zero[ETH_ALEN] = { 0 }; - - if (!mac) - mac = zero; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(reg, - (mac[3] << 24) | (mac[2] << 16) | - (mac[1] << 8) | mac[0]); - - ar9170_regwrite(reg + 4, (mac[5] << 8) | mac[4]); - - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_update_multicast(struct ar9170 *ar, const u64 mc_hash) -{ - int err; - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_H, mc_hash >> 32); - ar9170_regwrite(AR9170_MAC_REG_GROUP_HASH_TBL_L, mc_hash); - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - ar->cur_mc_hash = mc_hash; - return 0; -} - -int ar9170_update_frame_filter(struct ar9170 *ar, const u32 filter) -{ - int err; - - err = ar9170_write_reg(ar, AR9170_MAC_REG_FRAMETYPE_FILTER, filter); - if (err) - return err; - - ar->cur_filter = filter; - return 0; -} - -static int ar9170_set_promiscouous(struct ar9170 *ar) -{ - u32 encr_mode, sniffer; - int err; - - err = ar9170_read_reg(ar, AR9170_MAC_REG_SNIFFER, &sniffer); - if (err) - return err; - - err = ar9170_read_reg(ar, AR9170_MAC_REG_ENCRYPTION, &encr_mode); - if (err) - return err; - - if (ar->sniffer_enabled) { - sniffer |= AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; - - /* - * Rx decryption works in place. - * - * If we don't disable it, the hardware will render all - * encrypted frames which are encrypted with an unknown - * key useless. - */ - - encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - ar->sniffer_enabled = true; - } else { - sniffer &= ~AR9170_MAC_REG_SNIFFER_ENABLE_PROMISC; - - if (ar->rx_software_decryption) - encr_mode |= AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - else - encr_mode &= ~AR9170_MAC_REG_ENCRYPTION_RX_SOFTWARE; - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_ENCRYPTION, encr_mode); - ar9170_regwrite(AR9170_MAC_REG_SNIFFER, sniffer); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_set_operating_mode(struct ar9170 *ar) -{ - u32 pm_mode = AR9170_MAC_REG_POWERMGT_DEFAULTS; - u8 *mac_addr, *bssid; - int err; - - if (ar->vif) { - mac_addr = ar->mac_addr; - bssid = ar->bssid; - - switch (ar->vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - pm_mode |= AR9170_MAC_REG_POWERMGT_IBSS; - break; - case NL80211_IFTYPE_AP: - pm_mode |= AR9170_MAC_REG_POWERMGT_AP; - break; - case NL80211_IFTYPE_WDS: - pm_mode |= AR9170_MAC_REG_POWERMGT_AP_WDS; - break; - case NL80211_IFTYPE_MONITOR: - ar->sniffer_enabled = true; - ar->rx_software_decryption = true; - break; - default: - pm_mode |= AR9170_MAC_REG_POWERMGT_STA; - break; - } - } else { - mac_addr = NULL; - bssid = NULL; - } - - err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_MAC_ADDR_L, mac_addr); - if (err) - return err; - - err = ar9170_set_mac_reg(ar, AR9170_MAC_REG_BSSID_L, bssid); - if (err) - return err; - - err = ar9170_set_promiscouous(ar); - if (err) - return err; - - /* set AMPDU density to 8us. */ - err = ar9170_set_ampdu_density(ar, 6); - if (err) - return err; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(AR9170_MAC_REG_POWERMANAGEMENT, pm_mode); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_set_hwretry_limit(struct ar9170 *ar, unsigned int max_retry) -{ - u32 tmp = min_t(u32, 0x33333, max_retry * 0x11111); - - return ar9170_write_reg(ar, AR9170_MAC_REG_RETRY_MAX, tmp); -} - -int ar9170_set_beacon_timers(struct ar9170 *ar) -{ - u32 v = 0; - u32 pretbtt = 0; - - if (ar->vif) { - v |= ar->vif->bss_conf.beacon_int; - - if (ar->enable_beacon) { - switch (ar->vif->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_ADHOC: - v |= BIT(25); - break; - case NL80211_IFTYPE_AP: - v |= BIT(24); - pretbtt = (ar->vif->bss_conf.beacon_int - 6) << - 16; - break; - default: - break; - } - } - - v |= ar->vif->bss_conf.dtim_period << 16; - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_PRETBTT, pretbtt); - ar9170_regwrite(AR9170_MAC_REG_BCN_PERIOD, v); - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -int ar9170_update_beacon(struct ar9170 *ar) -{ - struct sk_buff *skb; - __le32 *data, *old = NULL; - u32 word; - int i; - - skb = ieee80211_beacon_get(ar->hw, ar->vif); - if (!skb) - return -ENOMEM; - - data = (__le32 *)skb->data; - if (ar->beacon) - old = (__le32 *)ar->beacon->data; - - ar9170_regwrite_begin(ar); - for (i = 0; i < DIV_ROUND_UP(skb->len, 4); i++) { - /* - * XXX: This accesses beyond skb data for up - * to the last 3 bytes!! - */ - - if (old && (data[i] == old[i])) - continue; - - word = le32_to_cpu(data[i]); - ar9170_regwrite(AR9170_BEACON_BUFFER_ADDRESS + 4 * i, word); - } - - /* XXX: use skb->cb info */ - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) - ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << (3 + 16)) + 0x0400); - else - ar9170_regwrite(AR9170_MAC_REG_BCN_PLCP, - ((skb->len + 4) << 16) + 0x001b); - - ar9170_regwrite(AR9170_MAC_REG_BCN_LENGTH, skb->len + 4); - ar9170_regwrite(AR9170_MAC_REG_BCN_ADDR, AR9170_BEACON_BUFFER_ADDRESS); - ar9170_regwrite(AR9170_MAC_REG_BCN_CTRL, 1); - - ar9170_regwrite_finish(); - - dev_kfree_skb(ar->beacon); - ar->beacon = skb; - - return ar9170_regwrite_result(); -} - -void ar9170_new_beacon(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - beacon_work); - struct sk_buff *skb; - - if (unlikely(!IS_STARTED(ar))) - return ; - - mutex_lock(&ar->mutex); - - if (!ar->vif) - goto out; - - ar9170_update_beacon(ar); - - rcu_read_lock(); - while ((skb = ieee80211_get_buffered_bc(ar->hw, ar->vif))) - ar9170_op_tx(ar->hw, skb); - - rcu_read_unlock(); - - out: - mutex_unlock(&ar->mutex); -} - -int ar9170_upload_key(struct ar9170 *ar, u8 id, const u8 *mac, u8 ktype, - u8 keyidx, u8 *keydata, int keylen) -{ - __le32 vals[7]; - static const u8 bcast[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - u8 dummy; - - mac = mac ? : bcast; - - vals[0] = cpu_to_le32((keyidx << 16) + id); - vals[1] = cpu_to_le32(mac[1] << 24 | mac[0] << 16 | ktype); - vals[2] = cpu_to_le32(mac[5] << 24 | mac[4] << 16 | - mac[3] << 8 | mac[2]); - memset(&vals[3], 0, 16); - if (keydata) - memcpy(&vals[3], keydata, keylen); - - return ar->exec_cmd(ar, AR9170_CMD_EKEY, - sizeof(vals), (u8 *)vals, - 1, &dummy); -} - -int ar9170_disable_key(struct ar9170 *ar, u8 id) -{ - __le32 val = cpu_to_le32(id); - u8 dummy; - - return ar->exec_cmd(ar, AR9170_CMD_EKEY, - sizeof(val), (u8 *)&val, - 1, &dummy); -} diff --git a/drivers/net/wireless/ath/ar9170/main.c b/drivers/net/wireless/ath/ar9170/main.c deleted file mode 100644 index a6514c1ffbbb..000000000000 --- a/drivers/net/wireless/ath/ar9170/main.c +++ /dev/null @@ -1,2733 +0,0 @@ -/* - * Atheros AR9170 driver - * - * mac80211 interaction code - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include "ar9170.h" -#include "hw.h" -#include "cmd.h" - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -static int modparam_ht; -module_param_named(ht, modparam_ht, bool, S_IRUGO); -MODULE_PARM_DESC(ht, "enable MPDU aggregation."); - -#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \ - .bitrate = (_bitrate), \ - .flags = (_flags), \ - .hw_value = (_hw_rate) | (_txpidx) << 4, \ -} - -static struct ieee80211_rate __ar9170_ratetable[] = { - RATE(10, 0, 0, 0), - RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE), - RATE(60, 0xb, 0, 0), - RATE(90, 0xf, 0, 0), - RATE(120, 0xa, 0, 0), - RATE(180, 0xe, 0, 0), - RATE(240, 0x9, 0, 0), - RATE(360, 0xd, 1, 0), - RATE(480, 0x8, 2, 0), - RATE(540, 0xc, 3, 0), -}; -#undef RATE - -#define ar9170_g_ratetable (__ar9170_ratetable + 0) -#define ar9170_g_ratetable_size 12 -#define ar9170_a_ratetable (__ar9170_ratetable + 4) -#define ar9170_a_ratetable_size 8 - -/* - * NB: The hw_value is used as an index into the ar9170_phy_freq_params - * array in phy.c so that we don't have to do frequency lookups! - */ -#define CHAN(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 18, /* XXX */ \ -} - -static struct ieee80211_channel ar9170_2ghz_chantable[] = { - CHAN(2412, 0), - CHAN(2417, 1), - CHAN(2422, 2), - CHAN(2427, 3), - CHAN(2432, 4), - CHAN(2437, 5), - CHAN(2442, 6), - CHAN(2447, 7), - CHAN(2452, 8), - CHAN(2457, 9), - CHAN(2462, 10), - CHAN(2467, 11), - CHAN(2472, 12), - CHAN(2484, 13), -}; - -static struct ieee80211_channel ar9170_5ghz_chantable[] = { - CHAN(4920, 14), - CHAN(4940, 15), - CHAN(4960, 16), - CHAN(4980, 17), - CHAN(5040, 18), - CHAN(5060, 19), - CHAN(5080, 20), - CHAN(5180, 21), - CHAN(5200, 22), - CHAN(5220, 23), - CHAN(5240, 24), - CHAN(5260, 25), - CHAN(5280, 26), - CHAN(5300, 27), - CHAN(5320, 28), - CHAN(5500, 29), - CHAN(5520, 30), - CHAN(5540, 31), - CHAN(5560, 32), - CHAN(5580, 33), - CHAN(5600, 34), - CHAN(5620, 35), - CHAN(5640, 36), - CHAN(5660, 37), - CHAN(5680, 38), - CHAN(5700, 39), - CHAN(5745, 40), - CHAN(5765, 41), - CHAN(5785, 42), - CHAN(5805, 43), - CHAN(5825, 44), - CHAN(5170, 45), - CHAN(5190, 46), - CHAN(5210, 47), - CHAN(5230, 48), -}; -#undef CHAN - -#define AR9170_HT_CAP \ -{ \ - .ht_supported = true, \ - .cap = IEEE80211_HT_CAP_MAX_AMSDU | \ - IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \ - IEEE80211_HT_CAP_SGI_40 | \ - IEEE80211_HT_CAP_GRN_FLD | \ - IEEE80211_HT_CAP_DSSSCCK40 | \ - IEEE80211_HT_CAP_SM_PS, \ - .ampdu_factor = 3, \ - .ampdu_density = 6, \ - .mcs = { \ - .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \ - .rx_highest = cpu_to_le16(300), \ - .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \ - }, \ -} - -static struct ieee80211_supported_band ar9170_band_2GHz = { - .channels = ar9170_2ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable), - .bitrates = ar9170_g_ratetable, - .n_bitrates = ar9170_g_ratetable_size, - .ht_cap = AR9170_HT_CAP, -}; - -static struct ieee80211_supported_band ar9170_band_5GHz = { - .channels = ar9170_5ghz_chantable, - .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable), - .bitrates = ar9170_a_ratetable, - .n_bitrates = ar9170_a_ratetable_size, - .ht_cap = AR9170_HT_CAP, -}; - -static void ar9170_tx(struct ar9170 *ar); -static bool ar9170_tx_ampdu(struct ar9170 *ar); - -static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr) -{ - return le16_to_cpu(hdr->seq_ctrl) >> 4; -} - -static inline u16 ar9170_get_seq(struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - return ar9170_get_seq_h((void *) txc->frame_data); -} - -static inline u16 ar9170_get_tid(struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - - return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK; -} - -#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff) -#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb))) - -#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG) -static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); - struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - - printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d " - "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n", - wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb), - ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr), - le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control), - jiffies_to_msecs(arinfo->timeout - jiffies)); -} - -static void __ar9170_dump_txqueue(struct ar9170 *ar, - struct sk_buff_head *queue) -{ - struct sk_buff *skb; - int i = 0; - return; - printk(KERN_DEBUG "---[ cut here ]---\n"); - printk(KERN_DEBUG "%s: %d entries in queue.\n", - wiphy_name(ar->hw->wiphy), skb_queue_len(queue)); - - skb_queue_walk(queue, skb) { - printk(KERN_DEBUG "index:%d => \n", i++); - ar9170_print_txheader(ar, skb); - } - if (i != skb_queue_len(queue)) - printk(KERN_DEBUG "WARNING: queue frame counter " - "mismatch %d != %d\n", skb_queue_len(queue), i); - printk(KERN_DEBUG "---[ end ]---\n"); -} -#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */ - -#ifdef AR9170_QUEUE_DEBUG -static void ar9170_dump_txqueue(struct ar9170 *ar, - struct sk_buff_head *queue) -{ - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - __ar9170_dump_txqueue(ar, queue); - spin_unlock_irqrestore(&queue->lock, flags); -} -#endif /* AR9170_QUEUE_DEBUG */ - -#ifdef AR9170_QUEUE_STOP_DEBUG -static void __ar9170_dump_txstats(struct ar9170 *ar) -{ - int i; - - printk(KERN_DEBUG "%s: QoS queue stats\n", - wiphy_name(ar->hw->wiphy)); - - for (i = 0; i < __AR9170_NUM_TXQ; i++) - printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d " - " stopped:%d\n", wiphy_name(ar->hw->wiphy), i, - ar->tx_stats[i].limit, ar->tx_stats[i].len, - skb_queue_len(&ar->tx_status[i]), - ieee80211_queue_stopped(ar->hw, i)); -} -#endif /* AR9170_QUEUE_STOP_DEBUG */ - -#ifdef AR9170_TXAGG_DEBUG -static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar) -{ - unsigned long flags; - - spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags); - printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n", - wiphy_name(ar->hw->wiphy)); - __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu); - spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags); -} - -#endif /* AR9170_TXAGG_DEBUG */ - -/* caller must guarantee exclusive access for _bin_ queue. */ -static void ar9170_recycle_expired(struct ar9170 *ar, - struct sk_buff_head *queue, - struct sk_buff_head *bin) -{ - struct sk_buff *skb, *old = NULL; - unsigned long flags; - - spin_lock_irqsave(&queue->lock, flags); - while ((skb = skb_peek(queue))) { - struct ieee80211_tx_info *txinfo; - struct ar9170_tx_info *arinfo; - - txinfo = IEEE80211_SKB_CB(skb); - arinfo = (void *) txinfo->rate_driver_data; - - if (time_is_before_jiffies(arinfo->timeout)) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => " - "recycle \n", wiphy_name(ar->hw->wiphy), - jiffies, arinfo->timeout); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - __skb_unlink(skb, queue); - __skb_queue_tail(bin, skb); - } else { - break; - } - - if (unlikely(old == skb)) { - /* bail out - queue is shot. */ - - WARN_ON(1); - break; - } - old = skb; - } - spin_unlock_irqrestore(&queue->lock, flags); -} - -static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb, - u16 tx_status) -{ - struct ieee80211_tx_info *txinfo; - unsigned int retries = 0; - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - switch (tx_status) { - case AR9170_TX_STATUS_RETRY: - retries = 2; - case AR9170_TX_STATUS_COMPLETE: - txinfo->flags |= IEEE80211_TX_STAT_ACK; - break; - - case AR9170_TX_STATUS_FAILED: - retries = ar->hw->conf.long_frame_max_tx_count; - break; - - default: - printk(KERN_ERR "%s: invalid tx_status response (%x).\n", - wiphy_name(ar->hw->wiphy), tx_status); - break; - } - - txinfo->status.rates[0].count = retries + 1; - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); -} - -static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar) -{ - struct sk_buff_head success; - struct sk_buff *skb; - unsigned int i; - unsigned long queue_bitmap = 0; - - skb_queue_head_init(&success); - - while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS) - __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu)); - - ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success); - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n", - wiphy_name(ar->hw->wiphy), skb_queue_len(&success)); - __ar9170_dump_txqueue(ar, &success); -#endif /* AR9170_TXAGG_DEBUG */ - - while ((skb = __skb_dequeue(&success))) { - struct ieee80211_tx_info *txinfo; - - queue_bitmap |= BIT(skb_get_queue_mapping(skb)); - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - txinfo->flags |= IEEE80211_TX_STAT_ACK; - txinfo->status.rates[0].count = 1; - - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); - } - - for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) { -#ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: wake queue %d\n", - wiphy_name(ar->hw->wiphy), i); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_wake_queue(ar->hw, i); - } - - if (queue_bitmap) - ar9170_tx(ar); -} - -static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb); - struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data; - - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_BA_TIMEOUT); - - skb_queue_tail(&ar->tx_status_ampdu, skb); - ar9170_tx_fake_ampdu_status(ar); - ar->tx_ampdu_pending--; - - if (!list_empty(&ar->tx_ampdu_list) && !ar->tx_ampdu_pending) - ar9170_tx_ampdu(ar); -} - -void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data; - unsigned int queue = skb_get_queue_mapping(skb); - unsigned long flags; - - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[queue].len--; - - if (skb_queue_empty(&ar->tx_pending[queue])) { -#ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: wake queue %d\n", - wiphy_name(ar->hw->wiphy), queue); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_wake_queue(ar->hw, queue); - } - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - - if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) { - ar9170_tx_ampdu_callback(ar, skb); - } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) { - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); - - skb_queue_tail(&ar->tx_status[queue], skb); - } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) { - ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED); - } else { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: unsupported frame flags!\n", - wiphy_name(ar->hw->wiphy)); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - dev_kfree_skb_any(skb); - } - - if (!ar->tx_stats[queue].len && - !skb_queue_empty(&ar->tx_pending[queue])) { - ar9170_tx(ar); - } -} - -static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar, - const u8 *mac, - struct sk_buff_head *queue, - const u32 rate) -{ - unsigned long flags; - struct sk_buff *skb; - - /* - * Unfortunately, the firmware does not tell to which (queued) frame - * this transmission status report belongs to. - * - * So we have to make risky guesses - with the scarce information - * the firmware provided (-> destination MAC, and phy_control) - - * and hope that we picked the right one... - */ - - spin_lock_irqsave(&queue->lock, flags); - skb_queue_walk(queue, skb) { - struct ar9170_tx_control *txc = (void *) skb->data; - struct ieee80211_hdr *hdr = (void *) txc->frame_data; - u32 r; - - if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n", - wiphy_name(ar->hw->wiphy), mac, - ieee80211_get_DA(hdr)); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - continue; - } - - r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >> - AR9170_TX_PHY_MCS_SHIFT; - - if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n", - wiphy_name(ar->hw->wiphy), rate, r); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - continue; - } - - __skb_unlink(skb, queue); - spin_unlock_irqrestore(&queue->lock, flags); - return skb; - } - -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_ERR "%s: ESS:[%pM] does not have any " - "outstanding frames in queue.\n", - wiphy_name(ar->hw->wiphy), mac); - __ar9170_dump_txqueue(ar, queue); -#endif /* AR9170_QUEUE_DEBUG */ - spin_unlock_irqrestore(&queue->lock, flags); - - return NULL; -} - -static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r) -{ - struct sk_buff *skb; - struct ieee80211_tx_info *txinfo; - - while (count) { - skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r); - if (!skb) - break; - - txinfo = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(txinfo); - - /* FIXME: maybe more ? */ - txinfo->status.rates[0].count = 1; - - skb_pull(skb, sizeof(struct ar9170_tx_control)); - ieee80211_tx_status_irqsafe(ar->hw, skb); - count--; - } - -#ifdef AR9170_TXAGG_DEBUG - if (count) { - printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more " - "suitable frames left in tx_status queue.\n", - wiphy_name(ar->hw->wiphy), count); - - ar9170_dump_tx_status_ampdu(ar); - } -#endif /* AR9170_TXAGG_DEBUG */ -} - -/* - * This worker tries to keeps an maintain tx_status queues. - * So we can guarantee that incoming tx_status reports are - * actually for a pending frame. - */ - -static void ar9170_tx_janitor(struct work_struct *work) -{ - struct ar9170 *ar = container_of(work, struct ar9170, - tx_janitor.work); - struct sk_buff_head waste; - unsigned int i; - bool resched = false; - - if (unlikely(!IS_STARTED(ar))) - return ; - - skb_queue_head_init(&waste); - - for (i = 0; i < __AR9170_NUM_TXQ; i++) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n", - wiphy_name(ar->hw->wiphy), i); - ar9170_dump_txqueue(ar, &ar->tx_pending[i]); - ar9170_dump_txqueue(ar, &ar->tx_status[i]); -#endif /* AR9170_QUEUE_DEBUG */ - - ar9170_recycle_expired(ar, &ar->tx_status[i], &waste); - ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste); - skb_queue_purge(&waste); - - if (!skb_queue_empty(&ar->tx_status[i]) || - !skb_queue_empty(&ar->tx_pending[i])) - resched = true; - } - - ar9170_tx_fake_ampdu_status(ar); - - if (!resched) - return; - - ieee80211_queue_delayed_work(ar->hw, - &ar->tx_janitor, - msecs_to_jiffies(AR9170_JANITOR_DELAY)); -} - -void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) -{ - struct ar9170_cmd_response *cmd = (void *) buf; - - if ((cmd->type & 0xc0) != 0xc0) { - ar->callback_cmd(ar, len, buf); - return; - } - - /* hardware event handlers */ - switch (cmd->type) { - case 0xc1: { - /* - * TX status notification: - * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1 - * - * XX always 81 - * YY always 00 - * M1-M6 is the MAC address - * R1-R4 is the transmit rate - * S1-S2 is the transmit status - */ - - struct sk_buff *skb; - u32 phy = le32_to_cpu(cmd->tx_status.rate); - u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >> - AR9170_TX_PHY_QOS_SHIFT; -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n", - wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q); -#endif /* AR9170_QUEUE_DEBUG */ - - skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst, - &ar->tx_status[q], - AR9170_TX_INVALID_RATE); - if (unlikely(!skb)) - return ; - - ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status)); - break; - } - - case 0xc0: - /* - * pre-TBTT event - */ - if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP) - ieee80211_queue_work(ar->hw, &ar->beacon_work); - break; - - case 0xc2: - /* - * (IBSS) beacon send notification - * bytes: 04 c2 XX YY B4 B3 B2 B1 - * - * XX always 80 - * YY always 00 - * B1-B4 "should" be the number of send out beacons. - */ - break; - - case 0xc3: - /* End of Atim Window */ - break; - - case 0xc4: - /* BlockACK bitmap */ - break; - - case 0xc5: - /* BlockACK events */ - ar9170_handle_block_ack(ar, - le16_to_cpu(cmd->ba_fail_cnt.failed), - le16_to_cpu(cmd->ba_fail_cnt.rate)); - ar9170_tx_fake_ampdu_status(ar); - break; - - case 0xc6: - /* Watchdog Interrupt */ - break; - - case 0xc9: - /* retransmission issue / SIFS/EIFS collision ?! */ - break; - - /* firmware debug */ - case 0xca: - printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4); - break; - case 0xcb: - len -= 4; - - switch (len) { - case 1: - printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n", - *((char *)buf + 4)); - break; - case 2: - printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n", - le16_to_cpup((__le16 *)((char *)buf + 4))); - break; - case 4: - printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n", - le32_to_cpup((__le32 *)((char *)buf + 4))); - break; - case 8: - printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n", - (unsigned long)le64_to_cpup( - (__le64 *)((char *)buf + 4))); - break; - } - break; - case 0xcc: - print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE, - (char *)buf + 4, len - 4); - break; - - default: - printk(KERN_INFO "received unhandled event %x\n", cmd->type); - print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len); - break; - } -} - -static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar) -{ - memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head)); - ar->rx_mpdu.has_plcp = false; -} - -int ar9170_nag_limiter(struct ar9170 *ar) -{ - bool print_message; - - /* - * we expect all sorts of errors in promiscuous mode. - * don't bother with it, it's OK! - */ - if (ar->sniffer_enabled) - return false; - - /* - * only go for frequent errors! The hardware tends to - * do some stupid thing once in a while under load, in - * noisy environments or just for fun! - */ - if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit()) - print_message = true; - else - print_message = false; - - /* reset threshold for "once in a while" */ - ar->bad_hw_nagger = jiffies + HZ / 4; - return print_message; -} - -static int ar9170_rx_mac_status(struct ar9170 *ar, - struct ar9170_rx_head *head, - struct ar9170_rx_macstatus *mac, - struct ieee80211_rx_status *status) -{ - u8 error, decrypt; - - BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12); - BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4); - - error = mac->error; - if (error & AR9170_RX_ERROR_MMIC) { - status->flag |= RX_FLAG_MMIC_ERROR; - error &= ~AR9170_RX_ERROR_MMIC; - } - - if (error & AR9170_RX_ERROR_PLCP) { - status->flag |= RX_FLAG_FAILED_PLCP_CRC; - error &= ~AR9170_RX_ERROR_PLCP; - - if (!(ar->filter_state & FIF_PLCPFAIL)) - return -EINVAL; - } - - if (error & AR9170_RX_ERROR_FCS) { - status->flag |= RX_FLAG_FAILED_FCS_CRC; - error &= ~AR9170_RX_ERROR_FCS; - - if (!(ar->filter_state & FIF_FCSFAIL)) - return -EINVAL; - } - - decrypt = ar9170_get_decrypt_type(mac); - if (!(decrypt & AR9170_RX_ENC_SOFTWARE) && - decrypt != AR9170_ENC_ALG_NONE) - status->flag |= RX_FLAG_DECRYPTED; - - /* ignore wrong RA errors */ - error &= ~AR9170_RX_ERROR_WRONG_RA; - - if (error & AR9170_RX_ERROR_DECRYPT) { - error &= ~AR9170_RX_ERROR_DECRYPT; - /* - * Rx decryption is done in place, - * the original data is lost anyway. - */ - - return -EINVAL; - } - - /* drop any other error frames */ - if (unlikely(error)) { - /* TODO: update netdevice's RX dropped/errors statistics */ - - if (ar9170_nag_limiter(ar)) - printk(KERN_DEBUG "%s: received frame with " - "suspicious error code (%#x).\n", - wiphy_name(ar->hw->wiphy), error); - - return -EINVAL; - } - - status->band = ar->channel->band; - status->freq = ar->channel->center_freq; - - switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) { - case AR9170_RX_STATUS_MODULATION_CCK: - if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE) - status->flag |= RX_FLAG_SHORTPRE; - switch (head->plcp[0]) { - case 0x0a: - status->rate_idx = 0; - break; - case 0x14: - status->rate_idx = 1; - break; - case 0x37: - status->rate_idx = 2; - break; - case 0x6e: - status->rate_idx = 3; - break; - default: - if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: invalid plcp cck rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); - return -EINVAL; - } - break; - - case AR9170_RX_STATUS_MODULATION_OFDM: - switch (head->plcp[0] & 0xf) { - case 0xb: - status->rate_idx = 0; - break; - case 0xf: - status->rate_idx = 1; - break; - case 0xa: - status->rate_idx = 2; - break; - case 0xe: - status->rate_idx = 3; - break; - case 0x9: - status->rate_idx = 4; - break; - case 0xd: - status->rate_idx = 5; - break; - case 0x8: - status->rate_idx = 6; - break; - case 0xc: - status->rate_idx = 7; - break; - default: - if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: invalid plcp ofdm rate " - "(%x).\n", wiphy_name(ar->hw->wiphy), - head->plcp[0]); - return -EINVAL; - } - if (status->band == IEEE80211_BAND_2GHZ) - status->rate_idx += 4; - break; - - case AR9170_RX_STATUS_MODULATION_HT: - if (head->plcp[3] & 0x80) - status->flag |= RX_FLAG_40MHZ; - if (head->plcp[6] & 0x80) - status->flag |= RX_FLAG_SHORT_GI; - - status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f); - status->flag |= RX_FLAG_HT; - break; - - case AR9170_RX_STATUS_MODULATION_DUPOFDM: - /* XXX */ - if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: invalid modulation\n", - wiphy_name(ar->hw->wiphy)); - return -EINVAL; - } - - return 0; -} - -static void ar9170_rx_phy_status(struct ar9170 *ar, - struct ar9170_rx_phystatus *phy, - struct ieee80211_rx_status *status) -{ - int i; - - BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20); - - for (i = 0; i < 3; i++) - if (phy->rssi[i] != 0x80) - status->antenna |= BIT(i); - - /* post-process RSSI */ - for (i = 0; i < 7; i++) - if (phy->rssi[i] & 0x80) - phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f; - - /* TODO: we could do something with phy_errors */ - status->signal = ar->noise[0] + phy->rssi_combined; - status->noise = ar->noise[0]; -} - -static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len) -{ - struct sk_buff *skb; - int reserved = 0; - struct ieee80211_hdr *hdr = (void *) buf; - - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - reserved += NET_IP_ALIGN; - - if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) - reserved += NET_IP_ALIGN; - } - - if (ieee80211_has_a4(hdr->frame_control)) - reserved += NET_IP_ALIGN; - - reserved = 32 + (reserved & NET_IP_ALIGN); - - skb = dev_alloc_skb(len + reserved); - if (likely(skb)) { - skb_reserve(skb, reserved); - memcpy(skb_put(skb, len), buf, len); - } - - return skb; -} - -/* - * If the frame alignment is right (or the kernel has - * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there - * is only a single MPDU in the USB frame, then we could - * submit to mac80211 the SKB directly. However, since - * there may be multiple packets in one SKB in stream - * mode, and we need to observe the proper ordering, - * this is non-trivial. - */ - -static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) -{ - struct ar9170_rx_head *head; - struct ar9170_rx_macstatus *mac; - struct ar9170_rx_phystatus *phy = NULL; - struct ieee80211_rx_status status; - struct sk_buff *skb; - int mpdu_len; - - if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac)))) - return ; - - /* Received MPDU */ - mpdu_len = len - sizeof(*mac); - - mac = (void *)(buf + mpdu_len); - if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) { - /* this frame is too damaged and can't be used - drop it */ - - return ; - } - - switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) { - case AR9170_RX_STATUS_MPDU_FIRST: - /* first mpdu packet has the plcp header */ - if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { - head = (void *) buf; - memcpy(&ar->rx_mpdu.plcp, (void *) buf, - sizeof(struct ar9170_rx_head)); - - mpdu_len -= sizeof(struct ar9170_rx_head); - buf += sizeof(struct ar9170_rx_head); - ar->rx_mpdu.has_plcp = true; - } else { - if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: plcp info is clipped.\n", - wiphy_name(ar->hw->wiphy)); - return ; - } - break; - - case AR9170_RX_STATUS_MPDU_LAST: - /* last mpdu has a extra tail with phy status information */ - - if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) { - mpdu_len -= sizeof(struct ar9170_rx_phystatus); - phy = (void *)(buf + mpdu_len); - } else { - if (ar9170_nag_limiter(ar)) - printk(KERN_ERR "%s: frame tail is clipped.\n", - wiphy_name(ar->hw->wiphy)); - return ; - } - - case AR9170_RX_STATUS_MPDU_MIDDLE: - /* middle mpdus are just data */ - if (unlikely(!ar->rx_mpdu.has_plcp)) { - if (!ar9170_nag_limiter(ar)) - return ; - - printk(KERN_ERR "%s: rx stream did not start " - "with a first_mpdu frame tag.\n", - wiphy_name(ar->hw->wiphy)); - - return ; - } - - head = &ar->rx_mpdu.plcp; - break; - - case AR9170_RX_STATUS_MPDU_SINGLE: - /* single mpdu - has plcp (head) and phy status (tail) */ - head = (void *) buf; - - mpdu_len -= sizeof(struct ar9170_rx_head); - mpdu_len -= sizeof(struct ar9170_rx_phystatus); - - buf += sizeof(struct ar9170_rx_head); - phy = (void *)(buf + mpdu_len); - break; - - default: - BUG_ON(1); - break; - } - - if (unlikely(mpdu_len < FCS_LEN)) - return ; - - memset(&status, 0, sizeof(status)); - if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status))) - return ; - - if (phy) - ar9170_rx_phy_status(ar, phy, &status); - - skb = ar9170_rx_copy_data(buf, mpdu_len); - if (likely(skb)) { - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx_irqsafe(ar->hw, skb); - } -} - -void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb) -{ - unsigned int i, tlen, resplen, wlen = 0, clen = 0; - u8 *tbuf, *respbuf; - - tbuf = skb->data; - tlen = skb->len; - - while (tlen >= 4) { - clen = tbuf[1] << 8 | tbuf[0]; - wlen = ALIGN(clen, 4); - - /* check if this is stream has a valid tag.*/ - if (tbuf[2] != 0 || tbuf[3] != 0x4e) { - /* - * TODO: handle the highly unlikely event that the - * corrupted stream has the TAG at the right position. - */ - - /* check if the frame can be repaired. */ - if (!ar->rx_failover_missing) { - /* this is no "short read". */ - if (ar9170_nag_limiter(ar)) { - printk(KERN_ERR "%s: missing tag!\n", - wiphy_name(ar->hw->wiphy)); - goto err_telluser; - } else - goto err_silent; - } - - if (ar->rx_failover_missing > tlen) { - if (ar9170_nag_limiter(ar)) { - printk(KERN_ERR "%s: possible multi " - "stream corruption!\n", - wiphy_name(ar->hw->wiphy)); - goto err_telluser; - } else - goto err_silent; - } - - memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); - ar->rx_failover_missing -= tlen; - - if (ar->rx_failover_missing <= 0) { - /* - * nested ar9170_rx call! - * termination is guranteed, even when the - * combined frame also have a element with - * a bad tag. - */ - - ar->rx_failover_missing = 0; - ar9170_rx(ar, ar->rx_failover); - - skb_reset_tail_pointer(ar->rx_failover); - skb_trim(ar->rx_failover, 0); - } - - return ; - } - - /* check if stream is clipped */ - if (wlen > tlen - 4) { - if (ar->rx_failover_missing) { - /* TODO: handle double stream corruption. */ - if (ar9170_nag_limiter(ar)) { - printk(KERN_ERR "%s: double rx stream " - "corruption!\n", - wiphy_name(ar->hw->wiphy)); - goto err_telluser; - } else - goto err_silent; - } - - /* - * save incomplete data set. - * the firmware will resend the missing bits when - * the rx - descriptor comes round again. - */ - - memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen); - ar->rx_failover_missing = clen - tlen; - return ; - } - resplen = clen; - respbuf = tbuf + 4; - tbuf += wlen + 4; - tlen -= wlen + 4; - - i = 0; - - /* weird thing, but this is the same in the original driver */ - while (resplen > 2 && i < 12 && - respbuf[0] == 0xff && respbuf[1] == 0xff) { - i += 2; - resplen -= 2; - respbuf += 2; - } - - if (resplen < 4) - continue; - - /* found the 6 * 0xffff marker? */ - if (i == 12) - ar9170_handle_command_response(ar, respbuf, resplen); - else - ar9170_handle_mpdu(ar, respbuf, clen); - } - - if (tlen) { - if (net_ratelimit()) - printk(KERN_ERR "%s: %d bytes of unprocessed " - "data left in rx stream!\n", - wiphy_name(ar->hw->wiphy), tlen); - - goto err_telluser; - } - - return ; - -err_telluser: - printk(KERN_ERR "%s: damaged RX stream data [want:%d, " - "data:%d, rx:%d, pending:%d ]\n", - wiphy_name(ar->hw->wiphy), clen, wlen, tlen, - ar->rx_failover_missing); - - if (ar->rx_failover_missing) - print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET, - ar->rx_failover->data, - ar->rx_failover->len); - - print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET, - skb->data, skb->len); - - printk(KERN_ERR "%s: please check your hardware and cables, if " - "you see this message frequently.\n", - wiphy_name(ar->hw->wiphy)); - -err_silent: - if (ar->rx_failover_missing) { - skb_reset_tail_pointer(ar->rx_failover); - skb_trim(ar->rx_failover, 0); - ar->rx_failover_missing = 0; - } -} - -#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \ -do { \ - queue.aifs = ai_fs; \ - queue.cw_min = cwmin; \ - queue.cw_max = cwmax; \ - queue.txop = _txop; \ -} while (0) - -static int ar9170_op_start(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - int err, i; - - mutex_lock(&ar->mutex); - - /* reinitialize queues statistics */ - memset(&ar->tx_stats, 0, sizeof(ar->tx_stats)); - for (i = 0; i < __AR9170_NUM_TXQ; i++) - ar->tx_stats[i].limit = AR9170_TXQ_DEPTH; - - /* reset QoS defaults */ - AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/ - AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */ - AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */ - AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */ - AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */ - - /* set sane AMPDU defaults */ - ar->global_ampdu_density = 6; - ar->global_ampdu_factor = 3; - - ar->bad_hw_nagger = jiffies; - - err = ar->open(ar); - if (err) - goto out; - - err = ar9170_init_mac(ar); - if (err) - goto out; - - err = ar9170_set_qos(ar); - if (err) - goto out; - - err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ); - if (err) - goto out; - - err = ar9170_init_rf(ar); - if (err) - goto out; - - /* start DMA */ - err = ar9170_write_reg(ar, 0x1c3d30, 0x100); - if (err) - goto out; - - ar->state = AR9170_STARTED; - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_op_stop(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - unsigned int i; - - if (IS_STARTED(ar)) - ar->state = AR9170_IDLE; - - cancel_delayed_work_sync(&ar->tx_janitor); -#ifdef CONFIG_AR9170_LEDS - cancel_delayed_work_sync(&ar->led_work); -#endif - cancel_work_sync(&ar->beacon_work); - - mutex_lock(&ar->mutex); - - if (IS_ACCEPTING_CMD(ar)) { - ar9170_set_leds_state(ar, 0); - - /* stop DMA */ - ar9170_write_reg(ar, 0x1c3d30, 0); - ar->stop(ar); - } - - for (i = 0; i < __AR9170_NUM_TXQ; i++) { - skb_queue_purge(&ar->tx_pending[i]); - skb_queue_purge(&ar->tx_status[i]); - } - skb_queue_purge(&ar->tx_status_ampdu); - - mutex_unlock(&ar->mutex); -} - -static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc = (void *) skb->data; - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU); -} - -static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst, - struct sk_buff *src) -{ - struct ar9170_tx_control *dst_txc, *src_txc; - struct ieee80211_tx_info *dst_info, *src_info; - struct ar9170_tx_info *dst_arinfo, *src_arinfo; - - src_txc = (void *) src->data; - src_info = IEEE80211_SKB_CB(src); - src_arinfo = (void *) src_info->rate_driver_data; - - dst_txc = (void *) dst->data; - dst_info = IEEE80211_SKB_CB(dst); - dst_arinfo = (void *) dst_info->rate_driver_data; - - dst_txc->phy_control = src_txc->phy_control; - - /* same MCS for the whole aggregate */ - memcpy(dst_info->driver_rates, src_info->driver_rates, - sizeof(dst_info->driver_rates)); -} - -static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - struct ar9170_tx_control *txc; - struct ieee80211_tx_info *info; - struct ieee80211_tx_rate *txrate; - struct ar9170_tx_info *arinfo; - unsigned int queue = skb_get_queue_mapping(skb); - u16 keytype = 0; - u16 len, icv = 0; - - BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); - - hdr = (void *)skb->data; - info = IEEE80211_SKB_CB(skb); - len = skb->len; - - txc = (void *)skb_push(skb, sizeof(*txc)); - - if (info->control.hw_key) { - icv = info->control.hw_key->icv_len; - - switch (info->control.hw_key->alg) { - case ALG_WEP: - keytype = AR9170_TX_MAC_ENCR_RC4; - break; - case ALG_TKIP: - keytype = AR9170_TX_MAC_ENCR_RC4; - break; - case ALG_CCMP: - keytype = AR9170_TX_MAC_ENCR_AES; - break; - default: - WARN_ON(1); - goto err_out; - } - } - - /* Length */ - txc->length = cpu_to_le16(len + icv + 4); - - txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION | - AR9170_TX_MAC_BACKOFF); - txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] << - AR9170_TX_MAC_QOS_SHIFT); - txc->mac_control |= cpu_to_le16(keytype); - txc->phy_control = cpu_to_le32(0); - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK); - - txrate = &info->control.rates[0]; - if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS); - else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS) - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS); - - arinfo = (void *)info->rate_driver_data; - arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT); - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (is_valid_ether_addr(ieee80211_get_DA(hdr)))) { - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - if (unlikely(!info->control.sta)) - goto err_out; - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR); - arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK; - - goto out; - } - - txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE); - /* - * WARNING: - * Putting the QoS queue bits into an unexplored territory is - * certainly not elegant. - * - * In my defense: This idea provides a reasonable way to - * smuggle valuable information to the tx_status callback. - * Also, the idea behind this bit-abuse came straight from - * the original driver code. - */ - - txc->phy_control |= - cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT); - arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK; - } else { - arinfo->flags = AR9170_TX_FLAG_NO_ACK; - } - -out: - return 0; - -err_out: - skb_pull(skb, sizeof(*txc)); - return -EINVAL; -} - -static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_tx_control *txc; - struct ieee80211_tx_info *info; - struct ieee80211_rate *rate = NULL; - struct ieee80211_tx_rate *txrate; - u32 power, chains; - - txc = (void *) skb->data; - info = IEEE80211_SKB_CB(skb); - txrate = &info->control.rates[0]; - - if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD); - - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE); - - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ); - /* this works because 40 MHz is 2 and dup is 3 */ - if (txrate->flags & IEEE80211_TX_RC_DUP_DATA) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP); - - if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI); - - if (txrate->flags & IEEE80211_TX_RC_MCS) { - u32 r = txrate->idx; - u8 *txpower; - - /* heavy clip control */ - txc->phy_control |= cpu_to_le32((r & 0x7) << 7); - - r <<= AR9170_TX_PHY_MCS_SHIFT; - BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK); - - txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK); - txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT); - - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht40; - else - txpower = ar->power_2G_ht40; - } else { - if (info->band == IEEE80211_BAND_5GHZ) - txpower = ar->power_5G_ht20; - else - txpower = ar->power_2G_ht20; - } - - power = txpower[(txrate->idx) & 7]; - } else { - u8 *txpower; - u32 mod; - u32 phyrate; - u8 idx = txrate->idx; - - if (info->band != IEEE80211_BAND_2GHZ) { - idx += 4; - txpower = ar->power_5G_leg; - mod = AR9170_TX_PHY_MOD_OFDM; - } else { - if (idx < 4) { - txpower = ar->power_2G_cck; - mod = AR9170_TX_PHY_MOD_CCK; - } else { - mod = AR9170_TX_PHY_MOD_OFDM; - txpower = ar->power_2G_ofdm; - } - } - - rate = &__ar9170_ratetable[idx]; - - phyrate = rate->hw_value & 0xF; - power = txpower[(rate->hw_value & 0x30) >> 4]; - phyrate <<= AR9170_TX_PHY_MCS_SHIFT; - - txc->phy_control |= cpu_to_le32(mod); - txc->phy_control |= cpu_to_le32(phyrate); - } - - power <<= AR9170_TX_PHY_TX_PWR_SHIFT; - power &= AR9170_TX_PHY_TX_PWR_MASK; - txc->phy_control |= cpu_to_le32(power); - - /* set TX chains */ - if (ar->eeprom.tx_mask == 1) { - chains = AR9170_TX_PHY_TXCHAIN_1; - } else { - chains = AR9170_TX_PHY_TXCHAIN_2; - - /* >= 36M legacy OFDM - use only one chain */ - if (rate && rate->bitrate >= 360) - chains = AR9170_TX_PHY_TXCHAIN_1; - } - txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT); -} - -static bool ar9170_tx_ampdu(struct ar9170 *ar) -{ - struct sk_buff_head agg; - struct ar9170_sta_tid *tid_info = NULL, *tmp; - struct sk_buff *skb, *first = NULL; - unsigned long flags, f2; - unsigned int i = 0; - u16 seq, queue, tmpssn; - bool run = false; - - skb_queue_head_init(&agg); - - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - if (list_empty(&ar->tx_ampdu_list)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: aggregation list is empty.\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - goto out_unlock; - } - - list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) { - if (tid_info->state != AR9170_TID_STATE_COMPLETE) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: dangling aggregation entry!\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - continue; - } - - if (++i > 64) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: enough frames aggregated.\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - break; - } - - queue = TID_TO_WME_AC(tid_info->tid); - - if (skb_queue_len(&ar->tx_pending[queue]) >= - AR9170_NUM_TX_AGG_MAX) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: queue %d full.\n", - wiphy_name(ar->hw->wiphy), queue); -#endif /* AR9170_TXAGG_DEBUG */ - continue; - } - - list_del_init(&tid_info->list); - - spin_lock_irqsave(&tid_info->queue.lock, f2); - tmpssn = seq = tid_info->ssn; - first = skb_peek(&tid_info->queue); - - if (likely(first)) - tmpssn = ar9170_get_seq(first); - - if (unlikely(tmpssn != seq)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.", - wiphy_name(ar->hw->wiphy), seq, tmpssn); -#endif /* AR9170_TXAGG_DEBUG */ - tid_info->ssn = tmpssn; - } - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with " - "%d queued frames.\n", wiphy_name(ar->hw->wiphy), - tid_info->tid, tid_info->ssn, - skb_queue_len(&tid_info->queue)); - __ar9170_dump_txqueue(ar, &tid_info->queue); -#endif /* AR9170_TXAGG_DEBUG */ - - while ((skb = skb_peek(&tid_info->queue))) { - if (unlikely(ar9170_get_seq(skb) != seq)) - break; - - __skb_unlink(skb, &tid_info->queue); - tid_info->ssn = seq = GET_NEXT_SEQ(seq); - - if (unlikely(skb_get_queue_mapping(skb) != queue)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d " - "!match.\n", wiphy_name(ar->hw->wiphy), - tid_info->tid, - TID_TO_WME_AC(tid_info->tid), - skb_get_queue_mapping(skb)); -#endif /* AR9170_TXAGG_DEBUG */ - dev_kfree_skb_any(skb); - continue; - } - - if (unlikely(first == skb)) { - ar9170_tx_prepare_phy(ar, skb); - __skb_queue_tail(&agg, skb); - first = skb; - } else { - ar9170_tx_copy_phy(ar, skb, first); - __skb_queue_tail(&agg, skb); - } - - if (unlikely(skb_queue_len(&agg) == - AR9170_NUM_TX_AGG_MAX)) - break; - } - - if (skb_queue_empty(&tid_info->queue)) - tid_info->active = false; - else - list_add_tail(&tid_info->list, - &ar->tx_ampdu_list); - - spin_unlock_irqrestore(&tid_info->queue.lock, f2); - - if (unlikely(skb_queue_empty(&agg))) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: queued empty list!\n", - wiphy_name(ar->hw->wiphy)); -#endif /* AR9170_TXAGG_DEBUG */ - continue; - } - - /* - * tell the FW/HW that this is the last frame, - * that way it will wait for the immediate block ack. - */ - if (likely(skb_peek_tail(&agg))) - ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg)); - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n", - wiphy_name(ar->hw->wiphy)); - __ar9170_dump_txqueue(ar, &agg); -#endif /* AR9170_TXAGG_DEBUG */ - - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - - spin_lock_irqsave(&ar->tx_pending[queue].lock, flags); - skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]); - spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags); - run = true; - - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - } - -out_unlock: - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - __skb_queue_purge(&agg); - - return run; -} - -static void ar9170_tx(struct ar9170 *ar) -{ - struct sk_buff *skb; - unsigned long flags; - struct ieee80211_tx_info *info; - struct ar9170_tx_info *arinfo; - unsigned int i, frames, frames_failed, remaining_space; - int err; - bool schedule_garbagecollector = false; - - BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data)); - - if (unlikely(!IS_STARTED(ar))) - return ; - - remaining_space = AR9170_TX_MAX_PENDING; - - for (i = 0; i < __AR9170_NUM_TXQ; i++) { - spin_lock_irqsave(&ar->tx_stats_lock, flags); - if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: queue %d full\n", - wiphy_name(ar->hw->wiphy), i); - - printk(KERN_DEBUG "%s: stuck frames: ===> \n", - wiphy_name(ar->hw->wiphy)); - ar9170_dump_txqueue(ar, &ar->tx_pending[i]); - ar9170_dump_txqueue(ar, &ar->tx_status[i]); -#endif /* AR9170_QUEUE_DEBUG */ - -#ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: stop queue %d\n", - wiphy_name(ar->hw->wiphy), i); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_stop_queue(ar->hw, i); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - continue; - } - - frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len, - skb_queue_len(&ar->tx_pending[i])); - - if (remaining_space < frames) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: tx quota reached queue:%d, " - "remaining slots:%d, needed:%d\n", - wiphy_name(ar->hw->wiphy), i, remaining_space, - frames); -#endif /* AR9170_QUEUE_DEBUG */ - frames = remaining_space; - } - - ar->tx_stats[i].len += frames; - ar->tx_stats[i].count += frames; - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - - if (!frames) - continue; - - frames_failed = 0; - while (frames) { - skb = skb_dequeue(&ar->tx_pending[i]); - if (unlikely(!skb)) { - frames_failed += frames; - frames = 0; - break; - } - - info = IEEE80211_SKB_CB(skb); - arinfo = (void *) info->rate_driver_data; - - /* TODO: cancel stuck frames */ - arinfo->timeout = jiffies + - msecs_to_jiffies(AR9170_TX_TIMEOUT); - - if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) - ar->tx_ampdu_pending++; - -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: send frame q:%d =>\n", - wiphy_name(ar->hw->wiphy), i); - ar9170_print_txheader(ar, skb); -#endif /* AR9170_QUEUE_DEBUG */ - - err = ar->tx(ar, skb); - if (unlikely(err)) { - if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK) - ar->tx_ampdu_pending--; - - frames_failed++; - dev_kfree_skb_any(skb); - } else { - remaining_space--; - schedule_garbagecollector = true; - } - - frames--; - } - -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n", - wiphy_name(ar->hw->wiphy), i); - - printk(KERN_DEBUG "%s: unprocessed pending frames left:\n", - wiphy_name(ar->hw->wiphy)); - ar9170_dump_txqueue(ar, &ar->tx_pending[i]); -#endif /* AR9170_QUEUE_DEBUG */ - - if (unlikely(frames_failed)) { -#ifdef AR9170_QUEUE_DEBUG - printk(KERN_DEBUG "%s: frames failed %d =>\n", - wiphy_name(ar->hw->wiphy), frames_failed); -#endif /* AR9170_QUEUE_DEBUG */ - - spin_lock_irqsave(&ar->tx_stats_lock, flags); - ar->tx_stats[i].len -= frames_failed; - ar->tx_stats[i].count -= frames_failed; -#ifdef AR9170_QUEUE_STOP_DEBUG - printk(KERN_DEBUG "%s: wake queue %d\n", - wiphy_name(ar->hw->wiphy), i); - __ar9170_dump_txstats(ar); -#endif /* AR9170_QUEUE_STOP_DEBUG */ - ieee80211_wake_queue(ar->hw, i); - spin_unlock_irqrestore(&ar->tx_stats_lock, flags); - } - } - - if (!schedule_garbagecollector) - return; - - ieee80211_queue_delayed_work(ar->hw, - &ar->tx_janitor, - msecs_to_jiffies(AR9170_JANITOR_DELAY)); -} - -static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ieee80211_tx_info *txinfo; - struct ar9170_sta_info *sta_info; - struct ar9170_sta_tid *agg; - struct sk_buff *iter; - unsigned long flags, f2; - unsigned int max; - u16 tid, seq, qseq; - bool run = false, queue = false; - - tid = ar9170_get_tid(skb); - seq = ar9170_get_seq(skb); - txinfo = IEEE80211_SKB_CB(skb); - sta_info = (void *) txinfo->control.sta->drv_priv; - agg = &sta_info->agg[tid]; - max = sta_info->ampdu_max_len; - - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - - if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: BlockACK session not fully initialized " - "for ESS:%pM tid:%d state:%d.\n", - wiphy_name(ar->hw->wiphy), agg->addr, agg->tid, - agg->state); -#endif /* AR9170_TXAGG_DEBUG */ - goto err_unlock; - } - - if (!agg->active) { - agg->active = true; - agg->ssn = seq; - queue = true; - } - - /* check if seq is within the BA window */ - if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) { -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not " - "fit into BA window (%d - %d)\n", - wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn, - (agg->ssn + max) & 0xfff); -#endif /* AR9170_TXAGG_DEBUG */ - goto err_unlock; - } - - spin_lock_irqsave(&agg->queue.lock, f2); - - skb_queue_reverse_walk(&agg->queue, iter) { - qseq = ar9170_get_seq(iter); - - if (GET_NEXT_SEQ(qseq) == seq) { - __skb_queue_after(&agg->queue, iter, skb); - goto queued; - } - } - - __skb_queue_head(&agg->queue, skb); - -queued: - spin_unlock_irqrestore(&agg->queue.lock, f2); - -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_DEBUG "%s: new aggregate %p queued.\n", - wiphy_name(ar->hw->wiphy), skb); - __ar9170_dump_txqueue(ar, &agg->queue); -#endif /* AR9170_TXAGG_DEBUG */ - - if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX) - run = true; - - if (queue) - list_add_tail(&agg->list, &ar->tx_ampdu_list); - - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - return run; - -err_unlock: - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - dev_kfree_skb_irq(skb); - return false; -} - -int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ar9170 *ar = hw->priv; - struct ieee80211_tx_info *info; - - if (unlikely(!IS_STARTED(ar))) - goto err_free; - - if (unlikely(ar9170_tx_prepare(ar, skb))) - goto err_free; - - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_AMPDU) { - bool run = ar9170_tx_ampdu_queue(ar, skb); - - if (run || !ar->tx_ampdu_pending) - ar9170_tx_ampdu(ar); - } else { - unsigned int queue = skb_get_queue_mapping(skb); - - ar9170_tx_prepare_phy(ar, skb); - skb_queue_tail(&ar->tx_pending[queue], skb); - } - - ar9170_tx(ar); - return NETDEV_TX_OK; - -err_free: - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -static int ar9170_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (ar->vif) { - err = -EBUSY; - goto unlock; - } - - ar->vif = conf->vif; - memcpy(ar->mac_addr, conf->mac_addr, ETH_ALEN); - - if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) { - ar->rx_software_decryption = true; - ar->disable_offload = true; - } - - ar->cur_filter = 0; - err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS); - if (err) - goto unlock; - - err = ar9170_set_operating_mode(ar); - -unlock: - mutex_unlock(&ar->mutex); - return err; -} - -static void ar9170_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ar9170 *ar = hw->priv; - - mutex_lock(&ar->mutex); - ar->vif = NULL; - ar9170_update_frame_filter(ar, 0); - ar9170_set_beacon_timers(ar); - dev_kfree_skb(ar->beacon); - ar->beacon = NULL; - ar->sniffer_enabled = false; - ar->rx_software_decryption = false; - ar9170_set_operating_mode(ar); - mutex_unlock(&ar->mutex); -} - -static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - /* TODO */ - err = 0; - } - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) { - /* - * is it long_frame_max_tx_count or short_frame_max_tx_count? - */ - - err = ar9170_set_hwretry_limit(ar, - ar->hw->conf.long_frame_max_tx_count); - if (err) - goto out; - } - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - - /* adjust slot time for 5 GHz */ - err = ar9170_set_slot_time(ar); - if (err) - goto out; - - err = ar9170_set_dyn_sifs_ack(ar); - if (err) - goto out; - - err = ar9170_set_channel(ar, hw->conf.channel, - AR9170_RFI_NONE, - nl80211_to_ar9170(hw->conf.channel_type)); - if (err) - goto out; - } - -out: - mutex_unlock(&ar->mutex); - return err; -} - -static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count, - struct dev_addr_list *mclist) -{ - u64 mchash; - int i; - - /* always get broadcast frames */ - mchash = 1ULL << (0xff >> 2); - - for (i = 0; i < mc_count; i++) { - if (WARN_ON(!mclist)) - break; - mchash |= 1ULL << (mclist->dmi_addr[5] >> 2); - mclist = mclist->next; - } - - return mchash; -} - -static void ar9170_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast) -{ - struct ar9170 *ar = hw->priv; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return ; - - mutex_lock(&ar->mutex); - - /* mask supported flags */ - *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC | - FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL; - ar->filter_state = *new_flags; - /* - * We can support more by setting the sniffer bit and - * then checking the error flags, later. - */ - - if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI) - multicast = ~0ULL; - - if (multicast != ar->cur_mc_hash) - ar9170_update_multicast(ar, multicast); - - if (changed_flags & FIF_CONTROL) { - u32 filter = AR9170_MAC_REG_FTF_PSPOLL | - AR9170_MAC_REG_FTF_RTS | - AR9170_MAC_REG_FTF_CTS | - AR9170_MAC_REG_FTF_ACK | - AR9170_MAC_REG_FTF_CFE | - AR9170_MAC_REG_FTF_CFE_ACK; - - if (*new_flags & FIF_CONTROL) - filter |= ar->cur_filter; - else - filter &= (~ar->cur_filter); - - ar9170_update_frame_filter(ar, filter); - } - - if (changed_flags & FIF_PROMISC_IN_BSS) { - ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0; - ar9170_set_operating_mode(ar); - } - - mutex_unlock(&ar->mutex); -} - - -static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct ar9170 *ar = hw->priv; - int err = 0; - - mutex_lock(&ar->mutex); - - if (changed & BSS_CHANGED_BSSID) { - memcpy(ar->bssid, bss_conf->bssid, ETH_ALEN); - err = ar9170_set_operating_mode(ar); - if (err) - goto out; - } - - if (changed & BSS_CHANGED_BEACON_ENABLED) - ar->enable_beacon = bss_conf->enable_beacon; - - if (changed & BSS_CHANGED_BEACON) { - err = ar9170_update_beacon(ar); - if (err) - goto out; - } - - if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON | - BSS_CHANGED_BEACON_INT)) { - err = ar9170_set_beacon_timers(ar); - if (err) - goto out; - } - - if (changed & BSS_CHANGED_ASSOC) { -#ifndef CONFIG_AR9170_LEDS - /* enable assoc LED. */ - err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0); -#endif /* CONFIG_AR9170_LEDS */ - } - - if (changed & BSS_CHANGED_HT) { - /* TODO */ - err = 0; - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - err = ar9170_set_slot_time(ar); - if (err) - goto out; - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - err = ar9170_set_basic_rates(ar); - if (err) - goto out; - } - -out: - mutex_unlock(&ar->mutex); -} - -static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw) -{ - struct ar9170 *ar = hw->priv; - int err; - u32 tsf_low; - u32 tsf_high; - u64 tsf; - - mutex_lock(&ar->mutex); - err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_L, &tsf_low); - if (!err) - err = ar9170_read_reg(ar, AR9170_MAC_REG_TSF_H, &tsf_high); - mutex_unlock(&ar->mutex); - - if (WARN_ON(err)) - return 0; - - tsf = tsf_high; - tsf = (tsf << 32) | tsf_low; - return tsf; -} - -static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ar9170 *ar = hw->priv; - int err = 0, i; - u8 ktype; - - if ((!ar->vif) || (ar->disable_offload)) - return -EOPNOTSUPP; - - switch (key->alg) { - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - ktype = AR9170_ENC_ALG_WEP64; - else - ktype = AR9170_ENC_ALG_WEP128; - break; - case ALG_TKIP: - ktype = AR9170_ENC_ALG_TKIP; - break; - case ALG_CCMP: - ktype = AR9170_ENC_ALG_AESCCMP; - break; - default: - return -EOPNOTSUPP; - } - - mutex_lock(&ar->mutex); - if (cmd == SET_KEY) { - if (unlikely(!IS_STARTED(ar))) { - err = -EOPNOTSUPP; - goto out; - } - - /* group keys need all-zeroes address */ - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) - sta = NULL; - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { - for (i = 0; i < 64; i++) - if (!(ar->usedkeys & BIT(i))) - break; - if (i == 64) { - ar->rx_software_decryption = true; - ar9170_set_operating_mode(ar); - err = -ENOSPC; - goto out; - } - } else { - i = 64 + key->keyidx; - } - - key->hw_key_idx = i; - - err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0, - key->key, min_t(u8, 16, key->keylen)); - if (err) - goto out; - - if (key->alg == ALG_TKIP) { - err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, - ktype, 1, key->key + 16, 16); - if (err) - goto out; - - /* - * hardware is not capable generating the MMIC - * for fragmented frames! - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - } - - if (i < 64) - ar->usedkeys |= BIT(i); - - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } else { - if (unlikely(!IS_STARTED(ar))) { - /* The device is gone... together with the key ;-) */ - err = 0; - goto out; - } - - err = ar9170_disable_key(ar, key->hw_key_idx); - if (err) - goto out; - - if (key->hw_key_idx < 64) { - ar->usedkeys &= ~BIT(key->hw_key_idx); - } else { - err = ar9170_upload_key(ar, key->hw_key_idx, NULL, - AR9170_ENC_ALG_NONE, 0, - NULL, 0); - if (err) - goto out; - - if (key->alg == ALG_TKIP) { - err = ar9170_upload_key(ar, key->hw_key_idx, - NULL, - AR9170_ENC_ALG_NONE, 1, - NULL, 0); - if (err) - goto out; - } - - } - } - - ar9170_regwrite_begin(ar); - ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys); - ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32); - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - -out: - mutex_unlock(&ar->mutex); - - return err; -} - -static void ar9170_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct ar9170 *ar = hw->priv; - struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; - unsigned int i; - - switch (cmd) { - case STA_NOTIFY_ADD: - memset(sta_info, 0, sizeof(*sta_info)); - - if (!sta->ht_cap.ht_supported) - break; - - if (sta->ht_cap.ampdu_density > ar->global_ampdu_density) - ar->global_ampdu_density = sta->ht_cap.ampdu_density; - - if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor) - ar->global_ampdu_factor = sta->ht_cap.ampdu_factor; - - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN; - sta_info->agg[i].active = false; - sta_info->agg[i].ssn = 0; - sta_info->agg[i].retry = 0; - sta_info->agg[i].tid = i; - INIT_LIST_HEAD(&sta_info->agg[i].list); - skb_queue_head_init(&sta_info->agg[i].queue); - } - - sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor); - break; - - case STA_NOTIFY_REMOVE: - if (!sta->ht_cap.ht_supported) - break; - - for (i = 0; i < AR9170_NUM_TID; i++) { - sta_info->agg[i].state = AR9170_TID_STATE_INVALID; - skb_queue_purge(&sta_info->agg[i].queue); - } - - break; - - default: - break; - } -} - -static int ar9170_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ar9170 *ar = hw->priv; - u32 val; - int err; - - mutex_lock(&ar->mutex); - err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val); - ar->stats.dot11ACKFailureCount += val; - - memcpy(stats, &ar->stats, sizeof(*stats)); - mutex_unlock(&ar->mutex); - - return 0; -} - -static int ar9170_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *tx_stats) -{ - struct ar9170 *ar = hw->priv; - - spin_lock_bh(&ar->tx_stats_lock); - memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues); - spin_unlock_bh(&ar->tx_stats_lock); - - return 0; -} - -static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *param) -{ - struct ar9170 *ar = hw->priv; - int ret; - - mutex_lock(&ar->mutex); - if (queue < __AR9170_NUM_TXQ) { - memcpy(&ar->edcf[ar9170_qos_hwmap[queue]], - param, sizeof(*param)); - - ret = ar9170_set_qos(ar); - } else { - ret = -EINVAL; - } - - mutex_unlock(&ar->mutex); - return ret; -} - -static int ar9170_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) -{ - struct ar9170 *ar = hw->priv; - struct ar9170_sta_info *sta_info = (void *) sta->drv_priv; - struct ar9170_sta_tid *tid_info = &sta_info->agg[tid]; - unsigned long flags; - - if (!modparam_ht) - return -EOPNOTSUPP; - - switch (action) { - case IEEE80211_AMPDU_TX_START: - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - if (tid_info->state != AR9170_TID_STATE_SHUTDOWN || - !list_empty(&tid_info->list)) { - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] " - "is in a very bad state!\n", - wiphy_name(hw->wiphy), sta->addr, tid); -#endif /* AR9170_TXAGG_DEBUG */ - return -EBUSY; - } - - *ssn = tid_info->ssn; - tid_info->state = AR9170_TID_STATE_PROGRESS; - tid_info->active = false; - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); - break; - - case IEEE80211_AMPDU_TX_STOP: - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - tid_info->state = AR9170_TID_STATE_SHUTDOWN; - list_del_init(&tid_info->list); - tid_info->active = false; - skb_queue_purge(&tid_info->queue); - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); - break; - - case IEEE80211_AMPDU_TX_OPERATIONAL: -#ifdef AR9170_TXAGG_DEBUG - printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n", - wiphy_name(hw->wiphy), sta->addr, tid); -#endif /* AR9170_TXAGG_DEBUG */ - spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags); - sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE; - spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags); - break; - - case IEEE80211_AMPDU_RX_START: - case IEEE80211_AMPDU_RX_STOP: - /* Handled by firmware */ - break; - - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static const struct ieee80211_ops ar9170_ops = { - .start = ar9170_op_start, - .stop = ar9170_op_stop, - .tx = ar9170_op_tx, - .add_interface = ar9170_op_add_interface, - .remove_interface = ar9170_op_remove_interface, - .config = ar9170_op_config, - .prepare_multicast = ar9170_op_prepare_multicast, - .configure_filter = ar9170_op_configure_filter, - .conf_tx = ar9170_conf_tx, - .bss_info_changed = ar9170_op_bss_info_changed, - .get_tsf = ar9170_op_get_tsf, - .set_key = ar9170_set_key, - .sta_notify = ar9170_sta_notify, - .get_stats = ar9170_get_stats, - .get_tx_stats = ar9170_get_tx_stats, - .ampdu_action = ar9170_ampdu_action, -}; - -void *ar9170_alloc(size_t priv_size) -{ - struct ieee80211_hw *hw; - struct ar9170 *ar; - struct sk_buff *skb; - int i; - - /* - * this buffer is used for rx stream reconstruction. - * Under heavy load this device (or the transport layer?) - * tends to split the streams into seperate rx descriptors. - */ - - skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL); - if (!skb) - goto err_nomem; - - hw = ieee80211_alloc_hw(priv_size, &ar9170_ops); - if (!hw) - goto err_nomem; - - ar = hw->priv; - ar->hw = hw; - ar->rx_failover = skb; - - mutex_init(&ar->mutex); - spin_lock_init(&ar->cmdlock); - spin_lock_init(&ar->tx_stats_lock); - spin_lock_init(&ar->tx_ampdu_list_lock); - skb_queue_head_init(&ar->tx_status_ampdu); - for (i = 0; i < __AR9170_NUM_TXQ; i++) { - skb_queue_head_init(&ar->tx_status[i]); - skb_queue_head_init(&ar->tx_pending[i]); - } - ar9170_rx_reset_rx_mpdu(ar); - INIT_WORK(&ar->beacon_work, ar9170_new_beacon); - INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor); - INIT_LIST_HEAD(&ar->tx_ampdu_list); - - /* all hw supports 2.4 GHz, so set channel to 1 by default */ - ar->channel = &ar9170_2ghz_chantable[0]; - - /* first part of wiphy init */ - ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_WDS) | - BIT(NL80211_IFTYPE_ADHOC); - ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - if (modparam_ht) { - ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; - } else { - ar9170_band_2GHz.ht_cap.ht_supported = false; - ar9170_band_5GHz.ht_cap.ht_supported = false; - } - - ar->hw->queues = __AR9170_NUM_TXQ; - ar->hw->extra_tx_headroom = 8; - ar->hw->sta_data_size = sizeof(struct ar9170_sta_info); - - ar->hw->max_rates = 1; - ar->hw->max_rate_tries = 3; - - for (i = 0; i < ARRAY_SIZE(ar->noise); i++) - ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */ - - return ar; - -err_nomem: - kfree_skb(skb); - return ERR_PTR(-ENOMEM); -} - -static int ar9170_read_eeprom(struct ar9170 *ar) -{ -#define RW 8 /* number of words to read at once */ -#define RB (sizeof(u32) * RW) - struct ath_regulatory *regulatory = &ar->common.regulatory; - u8 *eeprom = (void *)&ar->eeprom; - u8 *addr = ar->eeprom.mac_address; - __le32 offsets[RW]; - unsigned int rx_streams, tx_streams, tx_params = 0; - int i, j, err, bands = 0; - - BUILD_BUG_ON(sizeof(ar->eeprom) & 3); - - BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4); -#ifndef __CHECKER__ - /* don't want to handle trailing remains */ - BUILD_BUG_ON(sizeof(ar->eeprom) % RB); -#endif - - for (i = 0; i < sizeof(ar->eeprom)/RB; i++) { - for (j = 0; j < RW; j++) - offsets[j] = cpu_to_le32(AR9170_EEPROM_START + - RB * i + 4 * j); - - err = ar->exec_cmd(ar, AR9170_CMD_RREG, - RB, (u8 *) &offsets, - RB, eeprom + RB * i); - if (err) - return err; - } - -#undef RW -#undef RB - - if (ar->eeprom.length == cpu_to_le16(0xFFFF)) - return -ENODATA; - - if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz; - bands++; - } - if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) { - ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz; - bands++; - } - - rx_streams = hweight8(ar->eeprom.rx_mask); - tx_streams = hweight8(ar->eeprom.tx_mask); - - if (rx_streams != tx_streams) - tx_params = IEEE80211_HT_MCS_TX_RX_DIFF; - - if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS) - tx_params = (tx_streams - 1) << - IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT; - - ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params; - ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params; - - /* - * I measured this, a bandswitch takes roughly - * 135 ms and a frequency switch about 80. - * - * FIXME: measure these values again once EEPROM settings - * are used, that will influence them! - */ - if (bands == 2) - ar->hw->channel_change_time = 135 * 1000; - else - ar->hw->channel_change_time = 80 * 1000; - - regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]); - regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]); - - /* second part of wiphy init */ - SET_IEEE80211_PERM_ADDR(ar->hw, addr); - - return bands ? 0 : -EINVAL; -} - -static int ar9170_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ar9170 *ar = hw->priv; - - return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory); -} - -int ar9170_register(struct ar9170 *ar, struct device *pdev) -{ - struct ath_regulatory *regulatory = &ar->common.regulatory; - int err; - - /* try to read EEPROM, init MAC addr */ - err = ar9170_read_eeprom(ar); - if (err) - goto err_out; - - err = ath_regd_init(regulatory, ar->hw->wiphy, - ar9170_reg_notifier); - if (err) - goto err_out; - - err = ieee80211_register_hw(ar->hw); - if (err) - goto err_out; - - if (!ath_is_world_regd(regulatory)) - regulatory_hint(ar->hw->wiphy, regulatory->alpha2); - - err = ar9170_init_leds(ar); - if (err) - goto err_unreg; - -#ifdef CONFIG_AR9170_LEDS - err = ar9170_register_leds(ar); - if (err) - goto err_unreg; -#endif /* CONFIG_AR9170_LEDS */ - - dev_info(pdev, "Atheros AR9170 is registered as '%s'\n", - wiphy_name(ar->hw->wiphy)); - - return err; - -err_unreg: - ieee80211_unregister_hw(ar->hw); - -err_out: - return err; -} - -void ar9170_unregister(struct ar9170 *ar) -{ -#ifdef CONFIG_AR9170_LEDS - ar9170_unregister_leds(ar); -#endif /* CONFIG_AR9170_LEDS */ - - kfree_skb(ar->rx_failover); - ieee80211_unregister_hw(ar->hw); - mutex_destroy(&ar->mutex); -} diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c deleted file mode 100644 index dbd488da18b1..000000000000 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ /dev/null @@ -1,1656 +0,0 @@ -/* - * Atheros AR9170 driver - * - * PHY and RF code - * - * Copyright 2008, Johannes Berg - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "ar9170.h" -#include "cmd.h" - -static int ar9170_init_power_cal(struct ar9170 *ar) -{ - ar9170_regwrite_begin(ar); - - ar9170_regwrite(0x1bc000 + 0x993c, 0x7f); - ar9170_regwrite(0x1bc000 + 0x9934, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0x9938, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa234, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa238, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa38c, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa390, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3cc, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3d0, 0x3f3f3f3f); - ar9170_regwrite(0x1bc000 + 0xa3d4, 0x3f3f3f3f); - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -struct ar9170_phy_init { - u32 reg, _5ghz_20, _5ghz_40, _2ghz_40, _2ghz_20; -}; - -static struct ar9170_phy_init ar5416_phy_init[] = { - { 0x1c5800, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c5804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, }, - { 0x1c5808, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c580c, 0xad848e19, 0xad848e19, 0xad848e19, 0xad848e19, }, - { 0x1c5810, 0x7d14e000, 0x7d14e000, 0x7d14e000, 0x7d14e000, }, - { 0x1c5814, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, 0x9c0a9f6b, }, - { 0x1c5818, 0x00000090, 0x00000090, 0x00000090, 0x00000090, }, - { 0x1c581c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, }, - { 0x1c5824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, - { 0x1c5828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, }, - { 0x1c582c, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, - { 0x1c5830, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, }, - { 0x1c5838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c583c, 0x00200400, 0x00200400, 0x00200400, 0x00200400, }, - { 0x1c5840, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e, }, - { 0x1c5844, 0x1372161e, 0x13721c1e, 0x13721c24, 0x137216a4, }, - { 0x1c5848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, }, - { 0x1c584c, 0x1284233c, 0x1284233c, 0x1284233c, 0x1284233c, }, - { 0x1c5850, 0x6c48b4e4, 0x6c48b4e4, 0x6c48b0e4, 0x6c48b0e4, }, - { 0x1c5854, 0x00000859, 0x00000859, 0x00000859, 0x00000859, }, - { 0x1c5858, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, }, - { 0x1c585c, 0x31395c5e, 0x31395c5e, 0x31395c5e, 0x31395c5e, }, - { 0x1c5860, 0x0004dd10, 0x0004dd10, 0x0004dd20, 0x0004dd20, }, - { 0x1c5868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, }, - { 0x1c586c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, }, - { 0x1c5900, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5904, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5908, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c590c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, }, - { 0x1c5918, 0x00000118, 0x00000230, 0x00000268, 0x00000134, }, - { 0x1c591c, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff, }, - { 0x1c5920, 0x0510081c, 0x0510081c, 0x0510001c, 0x0510001c, }, - { 0x1c5924, 0xd0058a15, 0xd0058a15, 0xd0058a15, 0xd0058a15, }, - { 0x1c5928, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c592c, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, - { 0x1c5934, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c5938, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c593c, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, }, - { 0x1c5944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, }, - { 0x1c5948, 0x9280b212, 0x9280b212, 0x9280b212, 0x9280b212, }, - { 0x1c594c, 0x00020028, 0x00020028, 0x00020028, 0x00020028, }, - { 0x1c5954, 0x5d50e188, 0x5d50e188, 0x5d50e188, 0x5d50e188, }, - { 0x1c5958, 0x00081fff, 0x00081fff, 0x00081fff, 0x00081fff, }, - { 0x1c5960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c5964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, }, - { 0x1c5970, 0x190fb515, 0x190fb515, 0x190fb515, 0x190fb515, }, - { 0x1c5974, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5978, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c597c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5980, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5984, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5988, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c598c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5990, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5994, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5998, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c599c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59a4, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c59a8, 0x001fff00, 0x001fff00, 0x001fff00, 0x001fff00, }, - { 0x1c59ac, 0x006f00c4, 0x006f00c4, 0x006f00c4, 0x006f00c4, }, - { 0x1c59b0, 0x03051000, 0x03051000, 0x03051000, 0x03051000, }, - { 0x1c59b4, 0x00000820, 0x00000820, 0x00000820, 0x00000820, }, - { 0x1c59c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, }, - { 0x1c59c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, }, - { 0x1c59c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, }, - { 0x1c59cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, }, - { 0x1c59d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, }, - { 0x1c59d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59dc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59e0, 0x00000200, 0x00000200, 0x00000200, 0x00000200, }, - { 0x1c59e4, 0x64646464, 0x64646464, 0x64646464, 0x64646464, }, - { 0x1c59e8, 0x3c787878, 0x3c787878, 0x3c787878, 0x3c787878, }, - { 0x1c59ec, 0x000000aa, 0x000000aa, 0x000000aa, 0x000000aa, }, - { 0x1c59f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c59fc, 0x00001042, 0x00001042, 0x00001042, 0x00001042, }, - { 0x1c5a00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5a04, 0x00000040, 0x00000040, 0x00000040, 0x00000040, }, - { 0x1c5a08, 0x00000080, 0x00000080, 0x00000080, 0x00000080, }, - { 0x1c5a0c, 0x000001a1, 0x000001a1, 0x00000141, 0x00000141, }, - { 0x1c5a10, 0x000001e1, 0x000001e1, 0x00000181, 0x00000181, }, - { 0x1c5a14, 0x00000021, 0x00000021, 0x000001c1, 0x000001c1, }, - { 0x1c5a18, 0x00000061, 0x00000061, 0x00000001, 0x00000001, }, - { 0x1c5a1c, 0x00000168, 0x00000168, 0x00000041, 0x00000041, }, - { 0x1c5a20, 0x000001a8, 0x000001a8, 0x000001a8, 0x000001a8, }, - { 0x1c5a24, 0x000001e8, 0x000001e8, 0x000001e8, 0x000001e8, }, - { 0x1c5a28, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, - { 0x1c5a2c, 0x00000068, 0x00000068, 0x00000068, 0x00000068, }, - { 0x1c5a30, 0x00000189, 0x00000189, 0x000000a8, 0x000000a8, }, - { 0x1c5a34, 0x000001c9, 0x000001c9, 0x00000169, 0x00000169, }, - { 0x1c5a38, 0x00000009, 0x00000009, 0x000001a9, 0x000001a9, }, - { 0x1c5a3c, 0x00000049, 0x00000049, 0x000001e9, 0x000001e9, }, - { 0x1c5a40, 0x00000089, 0x00000089, 0x00000029, 0x00000029, }, - { 0x1c5a44, 0x00000170, 0x00000170, 0x00000069, 0x00000069, }, - { 0x1c5a48, 0x000001b0, 0x000001b0, 0x00000190, 0x00000190, }, - { 0x1c5a4c, 0x000001f0, 0x000001f0, 0x000001d0, 0x000001d0, }, - { 0x1c5a50, 0x00000030, 0x00000030, 0x00000010, 0x00000010, }, - { 0x1c5a54, 0x00000070, 0x00000070, 0x00000050, 0x00000050, }, - { 0x1c5a58, 0x00000191, 0x00000191, 0x00000090, 0x00000090, }, - { 0x1c5a5c, 0x000001d1, 0x000001d1, 0x00000151, 0x00000151, }, - { 0x1c5a60, 0x00000011, 0x00000011, 0x00000191, 0x00000191, }, - { 0x1c5a64, 0x00000051, 0x00000051, 0x000001d1, 0x000001d1, }, - { 0x1c5a68, 0x00000091, 0x00000091, 0x00000011, 0x00000011, }, - { 0x1c5a6c, 0x000001b8, 0x000001b8, 0x00000051, 0x00000051, }, - { 0x1c5a70, 0x000001f8, 0x000001f8, 0x00000198, 0x00000198, }, - { 0x1c5a74, 0x00000038, 0x00000038, 0x000001d8, 0x000001d8, }, - { 0x1c5a78, 0x00000078, 0x00000078, 0x00000018, 0x00000018, }, - { 0x1c5a7c, 0x00000199, 0x00000199, 0x00000058, 0x00000058, }, - { 0x1c5a80, 0x000001d9, 0x000001d9, 0x00000098, 0x00000098, }, - { 0x1c5a84, 0x00000019, 0x00000019, 0x00000159, 0x00000159, }, - { 0x1c5a88, 0x00000059, 0x00000059, 0x00000199, 0x00000199, }, - { 0x1c5a8c, 0x00000099, 0x00000099, 0x000001d9, 0x000001d9, }, - { 0x1c5a90, 0x000000d9, 0x000000d9, 0x00000019, 0x00000019, }, - { 0x1c5a94, 0x000000f9, 0x000000f9, 0x00000059, 0x00000059, }, - { 0x1c5a98, 0x000000f9, 0x000000f9, 0x00000099, 0x00000099, }, - { 0x1c5a9c, 0x000000f9, 0x000000f9, 0x000000d9, 0x000000d9, }, - { 0x1c5aa0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aa4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aa8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aac, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ab8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5abc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ac8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5acc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ad8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5adc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5ae8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5aec, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af0, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af4, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5af8, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5afc, 0x000000f9, 0x000000f9, 0x000000f9, 0x000000f9, }, - { 0x1c5b00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5b04, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c5b08, 0x00000002, 0x00000002, 0x00000002, 0x00000002, }, - { 0x1c5b0c, 0x00000003, 0x00000003, 0x00000003, 0x00000003, }, - { 0x1c5b10, 0x00000004, 0x00000004, 0x00000004, 0x00000004, }, - { 0x1c5b14, 0x00000005, 0x00000005, 0x00000005, 0x00000005, }, - { 0x1c5b18, 0x00000008, 0x00000008, 0x00000008, 0x00000008, }, - { 0x1c5b1c, 0x00000009, 0x00000009, 0x00000009, 0x00000009, }, - { 0x1c5b20, 0x0000000a, 0x0000000a, 0x0000000a, 0x0000000a, }, - { 0x1c5b24, 0x0000000b, 0x0000000b, 0x0000000b, 0x0000000b, }, - { 0x1c5b28, 0x0000000c, 0x0000000c, 0x0000000c, 0x0000000c, }, - { 0x1c5b2c, 0x0000000d, 0x0000000d, 0x0000000d, 0x0000000d, }, - { 0x1c5b30, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, - { 0x1c5b34, 0x00000011, 0x00000011, 0x00000011, 0x00000011, }, - { 0x1c5b38, 0x00000012, 0x00000012, 0x00000012, 0x00000012, }, - { 0x1c5b3c, 0x00000013, 0x00000013, 0x00000013, 0x00000013, }, - { 0x1c5b40, 0x00000014, 0x00000014, 0x00000014, 0x00000014, }, - { 0x1c5b44, 0x00000015, 0x00000015, 0x00000015, 0x00000015, }, - { 0x1c5b48, 0x00000018, 0x00000018, 0x00000018, 0x00000018, }, - { 0x1c5b4c, 0x00000019, 0x00000019, 0x00000019, 0x00000019, }, - { 0x1c5b50, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, - { 0x1c5b54, 0x0000001b, 0x0000001b, 0x0000001b, 0x0000001b, }, - { 0x1c5b58, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, }, - { 0x1c5b5c, 0x0000001d, 0x0000001d, 0x0000001d, 0x0000001d, }, - { 0x1c5b60, 0x00000020, 0x00000020, 0x00000020, 0x00000020, }, - { 0x1c5b64, 0x00000021, 0x00000021, 0x00000021, 0x00000021, }, - { 0x1c5b68, 0x00000022, 0x00000022, 0x00000022, 0x00000022, }, - { 0x1c5b6c, 0x00000023, 0x00000023, 0x00000023, 0x00000023, }, - { 0x1c5b70, 0x00000024, 0x00000024, 0x00000024, 0x00000024, }, - { 0x1c5b74, 0x00000025, 0x00000025, 0x00000025, 0x00000025, }, - { 0x1c5b78, 0x00000028, 0x00000028, 0x00000028, 0x00000028, }, - { 0x1c5b7c, 0x00000029, 0x00000029, 0x00000029, 0x00000029, }, - { 0x1c5b80, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a, }, - { 0x1c5b84, 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b, }, - { 0x1c5b88, 0x0000002c, 0x0000002c, 0x0000002c, 0x0000002c, }, - { 0x1c5b8c, 0x0000002d, 0x0000002d, 0x0000002d, 0x0000002d, }, - { 0x1c5b90, 0x00000030, 0x00000030, 0x00000030, 0x00000030, }, - { 0x1c5b94, 0x00000031, 0x00000031, 0x00000031, 0x00000031, }, - { 0x1c5b98, 0x00000032, 0x00000032, 0x00000032, 0x00000032, }, - { 0x1c5b9c, 0x00000033, 0x00000033, 0x00000033, 0x00000033, }, - { 0x1c5ba0, 0x00000034, 0x00000034, 0x00000034, 0x00000034, }, - { 0x1c5ba4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5ba8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bac, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bb8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bbc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bc8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bcc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bd8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bdc, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5be8, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bec, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf0, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf4, 0x00000035, 0x00000035, 0x00000035, 0x00000035, }, - { 0x1c5bf8, 0x00000010, 0x00000010, 0x00000010, 0x00000010, }, - { 0x1c5bfc, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, }, - { 0x1c5c00, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c0c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c10, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c14, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c18, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c1c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c20, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c24, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c28, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c2c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c30, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c34, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c38, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5c3c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cf8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c5cfc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6200, 0x00000008, 0x00000008, 0x0000000e, 0x0000000e, }, - { 0x1c6204, 0x00000440, 0x00000440, 0x00000440, 0x00000440, }, - { 0x1c6208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, }, - { 0x1c620c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c6210, 0x40806333, 0x40806333, 0x40806333, 0x40806333, }, - { 0x1c6214, 0x00106c10, 0x00106c10, 0x00106c10, 0x00106c10, }, - { 0x1c6218, 0x009c4060, 0x009c4060, 0x009c4060, 0x009c4060, }, - { 0x1c621c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, }, - { 0x1c6220, 0x018830c6, 0x018830c6, 0x018830c6, 0x018830c6, }, - { 0x1c6224, 0x00000400, 0x00000400, 0x00000400, 0x00000400, }, - { 0x1c6228, 0x000009b5, 0x000009b5, 0x000009b5, 0x000009b5, }, - { 0x1c622c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6230, 0x00000108, 0x00000210, 0x00000210, 0x00000108, }, - { 0x1c6234, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6238, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c623c, 0x13c889af, 0x13c889af, 0x13c889af, 0x13c889af, }, - { 0x1c6240, 0x38490a20, 0x38490a20, 0x38490a20, 0x38490a20, }, - { 0x1c6244, 0x00007bb6, 0x00007bb6, 0x00007bb6, 0x00007bb6, }, - { 0x1c6248, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, 0x0fff3ffc, }, - { 0x1c624c, 0x00000001, 0x00000001, 0x00000001, 0x00000001, }, - { 0x1c6250, 0x0000a000, 0x0000a000, 0x0000a000, 0x0000a000, }, - { 0x1c6254, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6258, 0x0cc75380, 0x0cc75380, 0x0cc75380, 0x0cc75380, }, - { 0x1c625c, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, 0x0f0f0f01, }, - { 0x1c6260, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, 0xdfa91f01, }, - { 0x1c6264, 0x00418a11, 0x00418a11, 0x00418a11, 0x00418a11, }, - { 0x1c6268, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c626c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, - { 0x1c6274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, }, - { 0x1c6278, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c627c, 0x051701ce, 0x051701ce, 0x051701ce, 0x051701ce, }, - { 0x1c6300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, }, - { 0x1c6304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, }, - { 0x1c6308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, }, - { 0x1c630c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, }, - { 0x1c6310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, }, - { 0x1c6314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, }, - { 0x1c6318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, }, - { 0x1c631c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, }, - { 0x1c6320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, }, - { 0x1c6324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, }, - { 0x1c6328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, }, - { 0x1c632c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6338, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c633c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6340, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6344, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c6348, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c634c, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c6350, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, }, - { 0x1c6354, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, }, - { 0x1c6358, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, 0x79a8aa1f, }, - { 0x1c6388, 0x08000000, 0x08000000, 0x08000000, 0x08000000, }, - { 0x1c638c, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6390, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c6394, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c6398, 0x000001ce, 0x000001ce, 0x000001ce, 0x000001ce, }, - { 0x1c639c, 0x00000007, 0x00000007, 0x00000007, 0x00000007, }, - { 0x1c63a0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63a4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63a8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63ac, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63b8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63bc, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63c8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63cc, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d0, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d4, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, 0x3f3f3f3f, }, - { 0x1c63d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, - { 0x1c63dc, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, 0x1ce739ce, }, - { 0x1c63e0, 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0, }, - { 0x1c6848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, - { 0x1c6920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, - { 0x1c6960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c720c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c726c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, - { 0x1c7848, 0x00180a65, 0x00180a65, 0x00180a68, 0x00180a68, }, - { 0x1c7920, 0x0510001c, 0x0510001c, 0x0510001c, 0x0510001c, }, - { 0x1c7960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, }, - { 0x1c820c, 0x012e8160, 0x012e8160, 0x012a8160, 0x012a8160, }, - { 0x1c826c, 0x09249126, 0x09249126, 0x09249126, 0x09249126, }, -/* { 0x1c8864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, }, */ - { 0x1c8864, 0x0001c600, 0x0001c600, 0x0001c600, 0x0001c600, }, - { 0x1c895c, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, 0x004b6a8e, }, - { 0x1c8968, 0x000003ce, 0x000003ce, 0x000003ce, 0x000003ce, }, - { 0x1c89bc, 0x00181400, 0x00181400, 0x00181400, 0x00181400, }, - { 0x1c9270, 0x00820820, 0x00820820, 0x00820820, 0x00820820, }, - { 0x1c935c, 0x066c420f, 0x066c420f, 0x066c420f, 0x066c420f, }, - { 0x1c9360, 0x0f282207, 0x0f282207, 0x0f282207, 0x0f282207, }, - { 0x1c9364, 0x17601685, 0x17601685, 0x17601685, 0x17601685, }, - { 0x1c9368, 0x1f801104, 0x1f801104, 0x1f801104, 0x1f801104, }, - { 0x1c936c, 0x37a00c03, 0x37a00c03, 0x37a00c03, 0x37a00c03, }, - { 0x1c9370, 0x3fc40883, 0x3fc40883, 0x3fc40883, 0x3fc40883, }, - { 0x1c9374, 0x57c00803, 0x57c00803, 0x57c00803, 0x57c00803, }, - { 0x1c9378, 0x5fd80682, 0x5fd80682, 0x5fd80682, 0x5fd80682, }, - { 0x1c937c, 0x7fe00482, 0x7fe00482, 0x7fe00482, 0x7fe00482, }, - { 0x1c9380, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, 0x7f3c7bba, }, - { 0x1c9384, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, 0xf3307ff0, } -}; - -/* - * look up a certain register in ar5416_phy_init[] and return the init. value - * for the band and bandwidth given. Return 0 if register address not found. - */ -static u32 ar9170_get_default_phy_reg_val(u32 reg, bool is_2ghz, bool is_40mhz) -{ - unsigned int i; - for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { - if (ar5416_phy_init[i].reg != reg) - continue; - - if (is_2ghz) { - if (is_40mhz) - return ar5416_phy_init[i]._2ghz_40; - else - return ar5416_phy_init[i]._2ghz_20; - } else { - if (is_40mhz) - return ar5416_phy_init[i]._5ghz_40; - else - return ar5416_phy_init[i]._5ghz_20; - } - } - return 0; -} - -/* - * initialize some phy regs from eeprom values in modal_header[] - * acc. to band and bandwith - */ -static int ar9170_init_phy_from_eeprom(struct ar9170 *ar, - bool is_2ghz, bool is_40mhz) -{ - static const u8 xpd2pd[16] = { - 0x2, 0x2, 0x2, 0x1, 0x2, 0x2, 0x6, 0x2, - 0x2, 0x3, 0x7, 0x2, 0xB, 0x2, 0x2, 0x2 - }; - u32 defval, newval; - /* pointer to the modal_header acc. to band */ - struct ar9170_eeprom_modal *m = &ar->eeprom.modal_header[is_2ghz]; - - ar9170_regwrite_begin(ar); - - /* ant common control (index 0) */ - newval = le32_to_cpu(m->antCtrlCommon); - ar9170_regwrite(0x1c5964, newval); - - /* ant control chain 0 (index 1) */ - newval = le32_to_cpu(m->antCtrlChain[0]); - ar9170_regwrite(0x1c5960, newval); - - /* ant control chain 2 (index 2) */ - newval = le32_to_cpu(m->antCtrlChain[1]); - ar9170_regwrite(0x1c7960, newval); - - /* SwSettle (index 3) */ - if (!is_40mhz) { - defval = ar9170_get_default_phy_reg_val(0x1c5844, - is_2ghz, is_40mhz); - newval = (defval & ~0x3f80) | - ((m->switchSettling & 0x7f) << 7); - ar9170_regwrite(0x1c5844, newval); - } - - /* adcDesired, pdaDesired (index 4) */ - defval = ar9170_get_default_phy_reg_val(0x1c5850, is_2ghz, is_40mhz); - newval = (defval & ~0xffff) | ((u8)m->pgaDesiredSize << 8) | - ((u8)m->adcDesiredSize); - ar9170_regwrite(0x1c5850, newval); - - /* TxEndToXpaOff, TxFrameToXpaOn (index 5) */ - defval = ar9170_get_default_phy_reg_val(0x1c5834, is_2ghz, is_40mhz); - newval = (m->txEndToXpaOff << 24) | (m->txEndToXpaOff << 16) | - (m->txFrameToXpaOn << 8) | m->txFrameToXpaOn; - ar9170_regwrite(0x1c5834, newval); - - /* TxEndToRxOn (index 6) */ - defval = ar9170_get_default_phy_reg_val(0x1c5828, is_2ghz, is_40mhz); - newval = (defval & ~0xff0000) | (m->txEndToRxOn << 16); - ar9170_regwrite(0x1c5828, newval); - - /* thresh62 (index 7) */ - defval = ar9170_get_default_phy_reg_val(0x1c8864, is_2ghz, is_40mhz); - newval = (defval & ~0x7f000) | (m->thresh62 << 12); - ar9170_regwrite(0x1c8864, newval); - - /* tx/rx attenuation chain 0 (index 8) */ - defval = ar9170_get_default_phy_reg_val(0x1c5848, is_2ghz, is_40mhz); - newval = (defval & ~0x3f000) | ((m->txRxAttenCh[0] & 0x3f) << 12); - ar9170_regwrite(0x1c5848, newval); - - /* tx/rx attenuation chain 2 (index 9) */ - defval = ar9170_get_default_phy_reg_val(0x1c7848, is_2ghz, is_40mhz); - newval = (defval & ~0x3f000) | ((m->txRxAttenCh[1] & 0x3f) << 12); - ar9170_regwrite(0x1c7848, newval); - - /* tx/rx margin chain 0 (index 10) */ - defval = ar9170_get_default_phy_reg_val(0x1c620c, is_2ghz, is_40mhz); - newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[0] & 0x3f) << 18); - /* bsw margin chain 0 for 5GHz only */ - if (!is_2ghz) - newval = (newval & ~0x3c00) | ((m->bswMargin[0] & 0xf) << 10); - ar9170_regwrite(0x1c620c, newval); - - /* tx/rx margin chain 2 (index 11) */ - defval = ar9170_get_default_phy_reg_val(0x1c820c, is_2ghz, is_40mhz); - newval = (defval & ~0xfc0000) | ((m->rxTxMarginCh[1] & 0x3f) << 18); - ar9170_regwrite(0x1c820c, newval); - - /* iqCall, iqCallq chain 0 (index 12) */ - defval = ar9170_get_default_phy_reg_val(0x1c5920, is_2ghz, is_40mhz); - newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[0] & 0x3f) << 5) | - ((u8)m->iqCalQCh[0] & 0x1f); - ar9170_regwrite(0x1c5920, newval); - - /* iqCall, iqCallq chain 2 (index 13) */ - defval = ar9170_get_default_phy_reg_val(0x1c7920, is_2ghz, is_40mhz); - newval = (defval & ~0x7ff) | (((u8)m->iqCalICh[1] & 0x3f) << 5) | - ((u8)m->iqCalQCh[1] & 0x1f); - ar9170_regwrite(0x1c7920, newval); - - /* xpd gain mask (index 14) */ - defval = ar9170_get_default_phy_reg_val(0x1c6258, is_2ghz, is_40mhz); - newval = (defval & ~0xf0000) | (xpd2pd[m->xpdGain & 0xf] << 16); - ar9170_regwrite(0x1c6258, newval); - ar9170_regwrite_finish(); - - return ar9170_regwrite_result(); -} - -int ar9170_init_phy(struct ar9170 *ar, enum ieee80211_band band) -{ - int i, err; - u32 val; - bool is_2ghz = band == IEEE80211_BAND_2GHZ; - bool is_40mhz = conf_is_ht40(&ar->hw->conf); - - ar9170_regwrite_begin(ar); - - for (i = 0; i < ARRAY_SIZE(ar5416_phy_init); i++) { - if (is_40mhz) { - if (is_2ghz) - val = ar5416_phy_init[i]._2ghz_40; - else - val = ar5416_phy_init[i]._5ghz_40; - } else { - if (is_2ghz) - val = ar5416_phy_init[i]._2ghz_20; - else - val = ar5416_phy_init[i]._5ghz_20; - } - - ar9170_regwrite(ar5416_phy_init[i].reg, val); - } - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - err = ar9170_init_phy_from_eeprom(ar, is_2ghz, is_40mhz); - if (err) - return err; - - err = ar9170_init_power_cal(ar); - if (err) - return err; - - /* XXX: remove magic! */ - if (is_2ghz) - err = ar9170_write_reg(ar, 0x1d4014, 0x5163); - else - err = ar9170_write_reg(ar, 0x1d4014, 0x5143); - - return err; -} - -struct ar9170_rf_init { - u32 reg, _5ghz, _2ghz; -}; - -static struct ar9170_rf_init ar9170_rf_init[] = { - /* bank 0 */ - { 0x1c58b0, 0x1e5795e5, 0x1e5795e5}, - { 0x1c58e0, 0x02008020, 0x02008020}, - /* bank 1 */ - { 0x1c58b0, 0x02108421, 0x02108421}, - { 0x1c58ec, 0x00000008, 0x00000008}, - /* bank 2 */ - { 0x1c58b0, 0x0e73ff17, 0x0e73ff17}, - { 0x1c58e0, 0x00000420, 0x00000420}, - /* bank 3 */ - { 0x1c58f0, 0x01400018, 0x01c00018}, - /* bank 4 */ - { 0x1c58b0, 0x000001a1, 0x000001a1}, - { 0x1c58e8, 0x00000001, 0x00000001}, - /* bank 5 */ - { 0x1c58b0, 0x00000013, 0x00000013}, - { 0x1c58e4, 0x00000002, 0x00000002}, - /* bank 6 */ - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00002c00, 0x00002c00}, - { 0x1c58b0, 0x00004800, 0x00004800}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00006000, 0x00006000}, - { 0x1c58b0, 0x00001000, 0x00001000}, - { 0x1c58b0, 0x00004000, 0x00004000}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00087c00, 0x00087c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00005400, 0x00005400}, - { 0x1c58b0, 0x00000c00, 0x00000c00}, - { 0x1c58b0, 0x00001800, 0x00001800}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00006c00, 0x00006c00}, - { 0x1c58b0, 0x00007c00, 0x00007c00}, - { 0x1c58b0, 0x00002c00, 0x00002c00}, - { 0x1c58b0, 0x00003c00, 0x00003c00}, - { 0x1c58b0, 0x00003800, 0x00003800}, - { 0x1c58b0, 0x00001c00, 0x00001c00}, - { 0x1c58b0, 0x00000800, 0x00000800}, - { 0x1c58b0, 0x00000408, 0x00000408}, - { 0x1c58b0, 0x00004c15, 0x00004c15}, - { 0x1c58b0, 0x00004188, 0x00004188}, - { 0x1c58b0, 0x0000201e, 0x0000201e}, - { 0x1c58b0, 0x00010408, 0x00010408}, - { 0x1c58b0, 0x00000801, 0x00000801}, - { 0x1c58b0, 0x00000c08, 0x00000c08}, - { 0x1c58b0, 0x0000181e, 0x0000181e}, - { 0x1c58b0, 0x00001016, 0x00001016}, - { 0x1c58b0, 0x00002800, 0x00002800}, - { 0x1c58b0, 0x00004010, 0x00004010}, - { 0x1c58b0, 0x0000081c, 0x0000081c}, - { 0x1c58b0, 0x00000115, 0x00000115}, - { 0x1c58b0, 0x00000015, 0x00000015}, - { 0x1c58b0, 0x00000066, 0x00000066}, - { 0x1c58b0, 0x0000001c, 0x0000001c}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000004, 0x00000004}, - { 0x1c58b0, 0x00000015, 0x00000015}, - { 0x1c58b0, 0x0000001f, 0x0000001f}, - { 0x1c58e0, 0x00000000, 0x00000400}, - /* bank 7 */ - { 0x1c58b0, 0x000000a0, 0x000000a0}, - { 0x1c58b0, 0x00000000, 0x00000000}, - { 0x1c58b0, 0x00000040, 0x00000040}, - { 0x1c58f0, 0x0000001c, 0x0000001c}, -}; - -static int ar9170_init_rf_banks_0_7(struct ar9170 *ar, bool band5ghz) -{ - int err, i; - - ar9170_regwrite_begin(ar); - - for (i = 0; i < ARRAY_SIZE(ar9170_rf_init); i++) - ar9170_regwrite(ar9170_rf_init[i].reg, - band5ghz ? ar9170_rf_init[i]._5ghz - : ar9170_rf_init[i]._2ghz); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - printk(KERN_ERR "%s: rf init failed\n", - wiphy_name(ar->hw->wiphy)); - return err; -} - -static int ar9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, - u32 freq, enum ar9170_bw bw) -{ - int err; - u32 d0, d1, td0, td1, fd0, fd1; - u8 chansel; - u8 refsel0 = 1, refsel1 = 0; - u8 lf_synth = 0; - - switch (bw) { - case AR9170_BW_40_ABOVE: - freq += 10; - break; - case AR9170_BW_40_BELOW: - freq -= 10; - break; - case AR9170_BW_20: - break; - case __AR9170_NUM_BW: - BUG(); - } - - if (band5ghz) { - if (freq % 10) { - chansel = (freq - 4800) / 5; - } else { - chansel = ((freq - 4800) / 10) * 2; - refsel0 = 0; - refsel1 = 1; - } - chansel = byte_rev_table[chansel]; - } else { - if (freq == 2484) { - chansel = 10 + (freq - 2274) / 5; - lf_synth = 1; - } else - chansel = 16 + (freq - 2272) / 5; - chansel *= 4; - chansel = byte_rev_table[chansel]; - } - - d1 = chansel; - d0 = 0x21 | - refsel0 << 3 | - refsel1 << 2 | - lf_synth << 1; - td0 = d0 & 0x1f; - td1 = d1 & 0x1f; - fd0 = td1 << 5 | td0; - - td0 = (d0 >> 5) & 0x7; - td1 = (d1 >> 5) & 0x7; - fd1 = td1 << 5 | td0; - - ar9170_regwrite_begin(ar); - - ar9170_regwrite(0x1c58b0, fd0); - ar9170_regwrite(0x1c58e8, fd1); - - ar9170_regwrite_finish(); - err = ar9170_regwrite_result(); - if (err) - return err; - - msleep(10); - - return 0; -} - -struct ar9170_phy_freq_params { - u8 coeff_exp; - u16 coeff_man; - u8 coeff_exp_shgi; - u16 coeff_man_shgi; -}; - -struct ar9170_phy_freq_entry { - u16 freq; - struct ar9170_phy_freq_params params[__AR9170_NUM_BW]; -}; - -/* NB: must be in sync with channel tables in main! */ -static const struct ar9170_phy_freq_entry ar9170_phy_freq_params[] = { -/* - * freq, - * 20MHz, - * 40MHz (below), - * 40Mhz (above), - */ - { 2412, { - { 3, 21737, 3, 19563, }, - { 3, 21827, 3, 19644, }, - { 3, 21647, 3, 19482, }, - } }, - { 2417, { - { 3, 21692, 3, 19523, }, - { 3, 21782, 3, 19604, }, - { 3, 21602, 3, 19442, }, - } }, - { 2422, { - { 3, 21647, 3, 19482, }, - { 3, 21737, 3, 19563, }, - { 3, 21558, 3, 19402, }, - } }, - { 2427, { - { 3, 21602, 3, 19442, }, - { 3, 21692, 3, 19523, }, - { 3, 21514, 3, 19362, }, - } }, - { 2432, { - { 3, 21558, 3, 19402, }, - { 3, 21647, 3, 19482, }, - { 3, 21470, 3, 19323, }, - } }, - { 2437, { - { 3, 21514, 3, 19362, }, - { 3, 21602, 3, 19442, }, - { 3, 21426, 3, 19283, }, - } }, - { 2442, { - { 3, 21470, 3, 19323, }, - { 3, 21558, 3, 19402, }, - { 3, 21382, 3, 19244, }, - } }, - { 2447, { - { 3, 21426, 3, 19283, }, - { 3, 21514, 3, 19362, }, - { 3, 21339, 3, 19205, }, - } }, - { 2452, { - { 3, 21382, 3, 19244, }, - { 3, 21470, 3, 19323, }, - { 3, 21295, 3, 19166, }, - } }, - { 2457, { - { 3, 21339, 3, 19205, }, - { 3, 21426, 3, 19283, }, - { 3, 21252, 3, 19127, }, - } }, - { 2462, { - { 3, 21295, 3, 19166, }, - { 3, 21382, 3, 19244, }, - { 3, 21209, 3, 19088, }, - } }, - { 2467, { - { 3, 21252, 3, 19127, }, - { 3, 21339, 3, 19205, }, - { 3, 21166, 3, 19050, }, - } }, - { 2472, { - { 3, 21209, 3, 19088, }, - { 3, 21295, 3, 19166, }, - { 3, 21124, 3, 19011, }, - } }, - { 2484, { - { 3, 21107, 3, 18996, }, - { 3, 21192, 3, 19073, }, - { 3, 21022, 3, 18920, }, - } }, - { 4920, { - { 4, 21313, 4, 19181, }, - { 4, 21356, 4, 19220, }, - { 4, 21269, 4, 19142, }, - } }, - { 4940, { - { 4, 21226, 4, 19104, }, - { 4, 21269, 4, 19142, }, - { 4, 21183, 4, 19065, }, - } }, - { 4960, { - { 4, 21141, 4, 19027, }, - { 4, 21183, 4, 19065, }, - { 4, 21098, 4, 18988, }, - } }, - { 4980, { - { 4, 21056, 4, 18950, }, - { 4, 21098, 4, 18988, }, - { 4, 21014, 4, 18912, }, - } }, - { 5040, { - { 4, 20805, 4, 18725, }, - { 4, 20846, 4, 18762, }, - { 4, 20764, 4, 18687, }, - } }, - { 5060, { - { 4, 20723, 4, 18651, }, - { 4, 20764, 4, 18687, }, - { 4, 20682, 4, 18614, }, - } }, - { 5080, { - { 4, 20641, 4, 18577, }, - { 4, 20682, 4, 18614, }, - { 4, 20601, 4, 18541, }, - } }, - { 5180, { - { 4, 20243, 4, 18219, }, - { 4, 20282, 4, 18254, }, - { 4, 20204, 4, 18183, }, - } }, - { 5200, { - { 4, 20165, 4, 18148, }, - { 4, 20204, 4, 18183, }, - { 4, 20126, 4, 18114, }, - } }, - { 5220, { - { 4, 20088, 4, 18079, }, - { 4, 20126, 4, 18114, }, - { 4, 20049, 4, 18044, }, - } }, - { 5240, { - { 4, 20011, 4, 18010, }, - { 4, 20049, 4, 18044, }, - { 4, 19973, 4, 17976, }, - } }, - { 5260, { - { 4, 19935, 4, 17941, }, - { 4, 19973, 4, 17976, }, - { 4, 19897, 4, 17907, }, - } }, - { 5280, { - { 4, 19859, 4, 17873, }, - { 4, 19897, 4, 17907, }, - { 4, 19822, 4, 17840, }, - } }, - { 5300, { - { 4, 19784, 4, 17806, }, - { 4, 19822, 4, 17840, }, - { 4, 19747, 4, 17772, }, - } }, - { 5320, { - { 4, 19710, 4, 17739, }, - { 4, 19747, 4, 17772, }, - { 4, 19673, 4, 17706, }, - } }, - { 5500, { - { 4, 19065, 4, 17159, }, - { 4, 19100, 4, 17190, }, - { 4, 19030, 4, 17127, }, - } }, - { 5520, { - { 4, 18996, 4, 17096, }, - { 4, 19030, 4, 17127, }, - { 4, 18962, 4, 17065, }, - } }, - { 5540, { - { 4, 18927, 4, 17035, }, - { 4, 18962, 4, 17065, }, - { 4, 18893, 4, 17004, }, - } }, - { 5560, { - { 4, 18859, 4, 16973, }, - { 4, 18893, 4, 17004, }, - { 4, 18825, 4, 16943, }, - } }, - { 5580, { - { 4, 18792, 4, 16913, }, - { 4, 18825, 4, 16943, }, - { 4, 18758, 4, 16882, }, - } }, - { 5600, { - { 4, 18725, 4, 16852, }, - { 4, 18758, 4, 16882, }, - { 4, 18691, 4, 16822, }, - } }, - { 5620, { - { 4, 18658, 4, 16792, }, - { 4, 18691, 4, 16822, }, - { 4, 18625, 4, 16762, }, - } }, - { 5640, { - { 4, 18592, 4, 16733, }, - { 4, 18625, 4, 16762, }, - { 4, 18559, 4, 16703, }, - } }, - { 5660, { - { 4, 18526, 4, 16673, }, - { 4, 18559, 4, 16703, }, - { 4, 18493, 4, 16644, }, - } }, - { 5680, { - { 4, 18461, 4, 16615, }, - { 4, 18493, 4, 16644, }, - { 4, 18428, 4, 16586, }, - } }, - { 5700, { - { 4, 18396, 4, 16556, }, - { 4, 18428, 4, 16586, }, - { 4, 18364, 4, 16527, }, - } }, - { 5745, { - { 4, 18252, 4, 16427, }, - { 4, 18284, 4, 16455, }, - { 4, 18220, 4, 16398, }, - } }, - { 5765, { - { 4, 18189, 5, 32740, }, - { 4, 18220, 4, 16398, }, - { 4, 18157, 5, 32683, }, - } }, - { 5785, { - { 4, 18126, 5, 32626, }, - { 4, 18157, 5, 32683, }, - { 4, 18094, 5, 32570, }, - } }, - { 5805, { - { 4, 18063, 5, 32514, }, - { 4, 18094, 5, 32570, }, - { 4, 18032, 5, 32458, }, - } }, - { 5825, { - { 4, 18001, 5, 32402, }, - { 4, 18032, 5, 32458, }, - { 4, 17970, 5, 32347, }, - } }, - { 5170, { - { 4, 20282, 4, 18254, }, - { 4, 20321, 4, 18289, }, - { 4, 20243, 4, 18219, }, - } }, - { 5190, { - { 4, 20204, 4, 18183, }, - { 4, 20243, 4, 18219, }, - { 4, 20165, 4, 18148, }, - } }, - { 5210, { - { 4, 20126, 4, 18114, }, - { 4, 20165, 4, 18148, }, - { 4, 20088, 4, 18079, }, - } }, - { 5230, { - { 4, 20049, 4, 18044, }, - { 4, 20088, 4, 18079, }, - { 4, 20011, 4, 18010, }, - } }, -}; - -static const struct ar9170_phy_freq_params * -ar9170_get_hw_dyn_params(struct ieee80211_channel *channel, - enum ar9170_bw bw) -{ - unsigned int chanidx = 0; - u16 freq = 2412; - - if (channel) { - chanidx = channel->hw_value; - freq = channel->center_freq; - } - - BUG_ON(chanidx >= ARRAY_SIZE(ar9170_phy_freq_params)); - - BUILD_BUG_ON(__AR9170_NUM_BW != 3); - - WARN_ON(ar9170_phy_freq_params[chanidx].freq != freq); - - return &ar9170_phy_freq_params[chanidx].params[bw]; -} - - -int ar9170_init_rf(struct ar9170 *ar) -{ - const struct ar9170_phy_freq_params *freqpar; - __le32 cmd[7]; - int err; - - err = ar9170_init_rf_banks_0_7(ar, false); - if (err) - return err; - - err = ar9170_init_rf_bank4_pwr(ar, false, 2412, AR9170_BW_20); - if (err) - return err; - - freqpar = ar9170_get_hw_dyn_params(NULL, AR9170_BW_20); - - cmd[0] = cpu_to_le32(2412 * 1000); - cmd[1] = cpu_to_le32(0); - cmd[2] = cpu_to_le32(1); - cmd[3] = cpu_to_le32(freqpar->coeff_exp); - cmd[4] = cpu_to_le32(freqpar->coeff_man); - cmd[5] = cpu_to_le32(freqpar->coeff_exp_shgi); - cmd[6] = cpu_to_le32(freqpar->coeff_man_shgi); - - /* RF_INIT echoes the command back to us */ - err = ar->exec_cmd(ar, AR9170_CMD_RF_INIT, - sizeof(cmd), (u8 *)cmd, - sizeof(cmd), (u8 *)cmd); - if (err) - return err; - - msleep(1000); - - return ar9170_echo_test(ar, 0xaabbccdd); -} - -static int ar9170_find_freq_idx(int nfreqs, u8 *freqs, u8 f) -{ - int idx = nfreqs - 2; - - while (idx >= 0) { - if (f >= freqs[idx]) - return idx; - idx--; - } - - return 0; -} - -static s32 ar9170_interpolate_s32(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) -{ - /* nothing to interpolate, it's horizontal */ - if (y2 == y1) - return y1; - - /* check if we hit one of the edges */ - if (x == x1) - return y1; - if (x == x2) - return y2; - - /* x1 == x2 is bad, hopefully == x */ - if (x2 == x1) - return y1; - - return y1 + (((y2 - y1) * (x - x1)) / (x2 - x1)); -} - -static u8 ar9170_interpolate_u8(u8 x, u8 x1, u8 y1, u8 x2, u8 y2) -{ -#define SHIFT 8 - s32 y; - - y = ar9170_interpolate_s32(x << SHIFT, - x1 << SHIFT, y1 << SHIFT, - x2 << SHIFT, y2 << SHIFT); - - /* - * XXX: unwrap this expression - * Isn't it just DIV_ROUND_UP(y, 1<> SHIFT) + ((y & (1<<(SHIFT-1))) >> (SHIFT - 1)); -#undef SHIFT -} - -static u8 ar9170_interpolate_val(u8 x, u8 *x_array, u8 *y_array) -{ - int i; - - for (i = 0; i < 3; i++) - if (x <= x_array[i + 1]) - break; - - return ar9170_interpolate_u8(x, - x_array[i], - y_array[i], - x_array[i + 1], - y_array[i + 1]); -} - -static int ar9170_set_freq_cal_data(struct ar9170 *ar, - struct ieee80211_channel *channel) -{ - u8 *cal_freq_pier; - u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; - u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; - int chain, idx, i; - u32 phy_data = 0; - u8 f, tmp; - - switch (channel->band) { - case IEEE80211_BAND_2GHZ: - f = channel->center_freq - 2300; - cal_freq_pier = ar->eeprom.cal_freq_pier_2G; - i = AR5416_NUM_2G_CAL_PIERS - 1; - break; - - case IEEE80211_BAND_5GHZ: - f = (channel->center_freq - 4800) / 5; - cal_freq_pier = ar->eeprom.cal_freq_pier_5G; - i = AR5416_NUM_5G_CAL_PIERS - 1; - break; - - default: - return -EINVAL; - break; - } - - for (; i >= 0; i--) { - if (cal_freq_pier[i] != 0xff) - break; - } - if (i < 0) - return -EINVAL; - - idx = ar9170_find_freq_idx(i, cal_freq_pier, f); - - ar9170_regwrite_begin(ar); - - for (chain = 0; chain < AR5416_MAX_CHAINS; chain++) { - for (i = 0; i < AR5416_PD_GAIN_ICEPTS; i++) { - struct ar9170_calibration_data_per_freq *cal_pier_data; - int j; - - switch (channel->band) { - case IEEE80211_BAND_2GHZ: - cal_pier_data = &ar->eeprom. - cal_pier_data_2G[chain][idx]; - break; - - case IEEE80211_BAND_5GHZ: - cal_pier_data = &ar->eeprom. - cal_pier_data_5G[chain][idx]; - break; - - default: - return -EINVAL; - } - - for (j = 0; j < 2; j++) { - vpds[j][i] = ar9170_interpolate_u8(f, - cal_freq_pier[idx], - cal_pier_data->vpd_pdg[j][i], - cal_freq_pier[idx + 1], - cal_pier_data[1].vpd_pdg[j][i]); - - pwrs[j][i] = ar9170_interpolate_u8(f, - cal_freq_pier[idx], - cal_pier_data->pwr_pdg[j][i], - cal_freq_pier[idx + 1], - cal_pier_data[1].pwr_pdg[j][i]) / 2; - } - } - - for (i = 0; i < 76; i++) { - if (i < 25) { - tmp = ar9170_interpolate_val(i, &pwrs[0][0], - &vpds[0][0]); - } else { - tmp = ar9170_interpolate_val(i - 12, - &pwrs[1][0], - &vpds[1][0]); - } - - phy_data |= tmp << ((i & 3) << 3); - if ((i & 3) == 3) { - ar9170_regwrite(0x1c6280 + chain * 0x1000 + - (i & ~3), phy_data); - phy_data = 0; - } - } - - for (i = 19; i < 32; i++) - ar9170_regwrite(0x1c6280 + chain * 0x1000 + (i << 2), - 0x0); - } - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -static u8 ar9170_get_max_edge_power(struct ar9170 *ar, - struct ar9170_calctl_edges edges[], - u32 freq) -{ -/* TODO: move somewhere else */ -#define AR5416_MAX_RATE_POWER 63 - - int i; - u8 rc = AR5416_MAX_RATE_POWER; - u8 f; - if (freq < 3000) - f = freq - 2300; - else - f = (freq - 4800) / 5; - - for (i = 0; i < AR5416_NUM_BAND_EDGES; i++) { - if (edges[i].channel == 0xff) - break; - if (f == edges[i].channel) { - /* exact freq match */ - rc = edges[i].power_flags & ~AR9170_CALCTL_EDGE_FLAGS; - break; - } - if (i > 0 && f < edges[i].channel) { - if (f > edges[i-1].channel && - edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { - /* lower channel has the inband flag set */ - rc = edges[i-1].power_flags & - ~AR9170_CALCTL_EDGE_FLAGS; - } - break; - } - } - - if (i == AR5416_NUM_BAND_EDGES) { - if (f > edges[i-1].channel && - edges[i-1].power_flags & AR9170_CALCTL_EDGE_FLAGS) { - /* lower channel has the inband flag set */ - rc = edges[i-1].power_flags & - ~AR9170_CALCTL_EDGE_FLAGS; - } - } - return rc; -} - -/* calculate the conformance test limits and apply them to ar->power* - * (derived from otus hal/hpmain.c, line 3706 ff.) - */ -static void ar9170_calc_ctl(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) -{ - u8 ctl_grp; /* CTL group */ - u8 ctl_idx; /* CTL index */ - int i, j; - struct ctl_modes { - u8 ctl_mode; - u8 max_power; - u8 *pwr_cal_data; - int pwr_cal_len; - } *modes; - - /* order is relevant in the mode_list_*: we fall back to the - * lower indices if any mode is missed in the EEPROM. - */ - struct ctl_modes mode_list_2ghz[] = { - { CTL_11B, 0, ar->power_2G_cck, 4 }, - { CTL_11G, 0, ar->power_2G_ofdm, 4 }, - { CTL_2GHT20, 0, ar->power_2G_ht20, 8 }, - { CTL_2GHT40, 0, ar->power_2G_ht40, 8 }, - }; - struct ctl_modes mode_list_5ghz[] = { - { CTL_11A, 0, ar->power_5G_leg, 4 }, - { CTL_5GHT20, 0, ar->power_5G_ht20, 8 }, - { CTL_5GHT40, 0, ar->power_5G_ht40, 8 }, - }; - int nr_modes; - -#define EDGES(c, n) (ar->eeprom.ctl_data[c].control_edges[n]) - - /* TODO: investigate the differences between OTUS' - * hpreg.c::zfHpGetRegulatoryDomain() and - * ath/regd.c::ath_regd_get_band_ctl() - - * e.g. for FCC3_WORLD the OTUS procedure - * always returns CTL_FCC, while the one in ath/ delivers - * CTL_ETSI for 2GHz and CTL_FCC for 5GHz. - */ - ctl_grp = ath_regd_get_band_ctl(&ar->common.regulatory, - ar->hw->conf.channel->band); - - /* ctl group not found - either invalid band (NO_CTL) or ww roaming */ - if (ctl_grp == NO_CTL || ctl_grp == SD_NO_CTL) - ctl_grp = CTL_FCC; - - if (ctl_grp != CTL_FCC) - /* skip CTL and heavy clip for CTL_MKK and CTL_ETSI */ - return; - - if (ar->hw->conf.channel->band == IEEE80211_BAND_2GHZ) { - modes = mode_list_2ghz; - nr_modes = ARRAY_SIZE(mode_list_2ghz); - } else { - modes = mode_list_5ghz; - nr_modes = ARRAY_SIZE(mode_list_5ghz); - } - - for (i = 0; i < nr_modes; i++) { - u8 c = ctl_grp | modes[i].ctl_mode; - for (ctl_idx = 0; ctl_idx < AR5416_NUM_CTLS; ctl_idx++) - if (c == ar->eeprom.ctl_index[ctl_idx]) - break; - if (ctl_idx < AR5416_NUM_CTLS) { - int f_off = 0; - - /* adjust freq for 40MHz */ - if (modes[i].ctl_mode == CTL_2GHT40 || - modes[i].ctl_mode == CTL_5GHT40) { - if (bw == AR9170_BW_40_BELOW) - f_off = -10; - else - f_off = 10; - } - - modes[i].max_power = - ar9170_get_max_edge_power(ar, EDGES(ctl_idx, 1), - freq+f_off); - - /* TODO: check if the regulatory max. power is - * controlled by cfg80211 for DFS - * (hpmain applies it to max_power itself for DFS freq) - */ - - } else { - /* Workaround in otus driver, hpmain.c, line 3906: - * if no data for 5GHT20 are found, take the - * legacy 5G value. - * We extend this here to fallback from any other *HT or - * 11G, too. - */ - int k = i; - - modes[i].max_power = AR5416_MAX_RATE_POWER; - while (k-- > 0) { - if (modes[k].max_power != - AR5416_MAX_RATE_POWER) { - modes[i].max_power = modes[k].max_power; - break; - } - } - } - - /* apply max power to pwr_cal_data (ar->power_*) */ - for (j = 0; j < modes[i].pwr_cal_len; j++) { - modes[i].pwr_cal_data[j] = min(modes[i].pwr_cal_data[j], - modes[i].max_power); - } - } -#undef EDGES -} - -static int ar9170_set_power_cal(struct ar9170 *ar, u32 freq, enum ar9170_bw bw) -{ - struct ar9170_calibration_target_power_legacy *ctpl; - struct ar9170_calibration_target_power_ht *ctph; - u8 *ctpres; - int ntargets; - int idx, i, n; - u8 ackpower, ackchains, f; - u8 pwr_freqs[AR5416_MAX_NUM_TGT_PWRS]; - - if (freq < 3000) - f = freq - 2300; - else - f = (freq - 4800)/5; - - /* - * cycle through the various modes - * - * legacy modes first: 5G, 2G CCK, 2G OFDM - */ - for (i = 0; i < 3; i++) { - switch (i) { - case 0: /* 5 GHz legacy */ - ctpl = &ar->eeprom.cal_tgt_pwr_5G[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_leg; - break; - case 1: /* 2.4 GHz CCK */ - ctpl = &ar->eeprom.cal_tgt_pwr_2G_cck[0]; - ntargets = AR5416_NUM_2G_CCK_TARGET_PWRS; - ctpres = ar->power_2G_cck; - break; - case 2: /* 2.4 GHz OFDM */ - ctpl = &ar->eeprom.cal_tgt_pwr_2G_ofdm[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ofdm; - break; - default: - BUG(); - } - - for (n = 0; n < ntargets; n++) { - if (ctpl[n].freq == 0xff) - break; - pwr_freqs[n] = ctpl[n].freq; - } - ntargets = n; - idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); - for (n = 0; n < 4; n++) - ctpres[n] = ar9170_interpolate_u8( - f, - ctpl[idx + 0].freq, - ctpl[idx + 0].power[n], - ctpl[idx + 1].freq, - ctpl[idx + 1].power[n]); - } - - /* - * HT modes now: 5G HT20, 5G HT40, 2G CCK, 2G OFDM, 2G HT20, 2G HT40 - */ - for (i = 0; i < 4; i++) { - switch (i) { - case 0: /* 5 GHz HT 20 */ - ctph = &ar->eeprom.cal_tgt_pwr_5G_ht20[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_ht20; - break; - case 1: /* 5 GHz HT 40 */ - ctph = &ar->eeprom.cal_tgt_pwr_5G_ht40[0]; - ntargets = AR5416_NUM_5G_TARGET_PWRS; - ctpres = ar->power_5G_ht40; - break; - case 2: /* 2.4 GHz HT 20 */ - ctph = &ar->eeprom.cal_tgt_pwr_2G_ht20[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ht20; - break; - case 3: /* 2.4 GHz HT 40 */ - ctph = &ar->eeprom.cal_tgt_pwr_2G_ht40[0]; - ntargets = AR5416_NUM_2G_OFDM_TARGET_PWRS; - ctpres = ar->power_2G_ht40; - break; - default: - BUG(); - } - - for (n = 0; n < ntargets; n++) { - if (ctph[n].freq == 0xff) - break; - pwr_freqs[n] = ctph[n].freq; - } - ntargets = n; - idx = ar9170_find_freq_idx(ntargets, pwr_freqs, f); - for (n = 0; n < 8; n++) - ctpres[n] = ar9170_interpolate_u8( - f, - ctph[idx + 0].freq, - ctph[idx + 0].power[n], - ctph[idx + 1].freq, - ctph[idx + 1].power[n]); - } - - - /* calc. conformance test limits and apply to ar->power*[] */ - ar9170_calc_ctl(ar, freq, bw); - - /* TODO: (heavy clip) regulatory domain power level fine-tuning. */ - - /* set ACK/CTS TX power */ - ar9170_regwrite_begin(ar); - - if (ar->eeprom.tx_mask != 1) - ackchains = AR9170_TX_PHY_TXCHAIN_2; - else - ackchains = AR9170_TX_PHY_TXCHAIN_1; - - if (freq < 3000) - ackpower = ar->power_2G_ofdm[0] & 0x3f; - else - ackpower = ar->power_5G_leg[0] & 0x3f; - - ar9170_regwrite(0x1c3694, ackpower << 20 | ackchains << 26); - ar9170_regwrite(0x1c3bb4, ackpower << 5 | ackchains << 11 | - ackpower << 21 | ackchains << 27); - - ar9170_regwrite_finish(); - return ar9170_regwrite_result(); -} - -static int ar9170_calc_noise_dbm(u32 raw_noise) -{ - if (raw_noise & 0x100) - return ~((raw_noise & 0x0ff) >> 1); - else - return (raw_noise & 0xff) >> 1; -} - -int ar9170_set_channel(struct ar9170 *ar, struct ieee80211_channel *channel, - enum ar9170_rf_init_mode rfi, enum ar9170_bw bw) -{ - const struct ar9170_phy_freq_params *freqpar; - u32 cmd, tmp, offs; - __le32 vals[8]; - int i, err; - bool bandswitch; - - /* clear BB heavy clip enable */ - err = ar9170_write_reg(ar, 0x1c59e0, 0x200); - if (err) - return err; - - /* may be NULL at first setup */ - if (ar->channel) - bandswitch = ar->channel->band != channel->band; - else - bandswitch = true; - - /* HW workaround */ - if (!ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] && - channel->center_freq <= 2417) - bandswitch = true; - - err = ar->exec_cmd(ar, AR9170_CMD_FREQ_START, 0, NULL, 0, NULL); - if (err) - return err; - - if (rfi != AR9170_RFI_NONE || bandswitch) { - u32 val = 0x400; - - if (rfi == AR9170_RFI_COLD) - val = 0x800; - - /* warm/cold reset BB/ADDA */ - err = ar9170_write_reg(ar, 0x1d4004, val); - if (err) - return err; - - err = ar9170_write_reg(ar, 0x1d4004, 0x0); - if (err) - return err; - - err = ar9170_init_phy(ar, channel->band); - if (err) - return err; - - err = ar9170_init_rf_banks_0_7(ar, - channel->band == IEEE80211_BAND_5GHZ); - if (err) - return err; - - cmd = AR9170_CMD_RF_INIT; - } else { - cmd = AR9170_CMD_FREQUENCY; - } - - err = ar9170_init_rf_bank4_pwr(ar, - channel->band == IEEE80211_BAND_5GHZ, - channel->center_freq, bw); - if (err) - return err; - - switch (bw) { - case AR9170_BW_20: - tmp = 0x240; - offs = 0; - break; - case AR9170_BW_40_BELOW: - tmp = 0x2c4; - offs = 3; - break; - case AR9170_BW_40_ABOVE: - tmp = 0x2d4; - offs = 1; - break; - default: - BUG(); - return -ENOSYS; - } - - if (ar->eeprom.tx_mask != 1) - tmp |= 0x100; - - err = ar9170_write_reg(ar, 0x1c5804, tmp); - if (err) - return err; - - err = ar9170_set_freq_cal_data(ar, channel); - if (err) - return err; - - err = ar9170_set_power_cal(ar, channel->center_freq, bw); - if (err) - return err; - - freqpar = ar9170_get_hw_dyn_params(channel, bw); - - vals[0] = cpu_to_le32(channel->center_freq * 1000); - vals[1] = cpu_to_le32(conf_is_ht40(&ar->hw->conf)); - vals[2] = cpu_to_le32(offs << 2 | 1); - vals[3] = cpu_to_le32(freqpar->coeff_exp); - vals[4] = cpu_to_le32(freqpar->coeff_man); - vals[5] = cpu_to_le32(freqpar->coeff_exp_shgi); - vals[6] = cpu_to_le32(freqpar->coeff_man_shgi); - vals[7] = cpu_to_le32(1000); - - err = ar->exec_cmd(ar, cmd, sizeof(vals), (u8 *)vals, - sizeof(vals), (u8 *)vals); - if (err) - return err; - - for (i = 0; i < 2; i++) { - ar->noise[i] = ar9170_calc_noise_dbm( - (le32_to_cpu(vals[2 + i]) >> 19) & 0x1ff); - - ar->noise[i + 2] = ar9170_calc_noise_dbm( - (le32_to_cpu(vals[5 + i]) >> 23) & 0x1ff); - } - - ar->channel = channel; - return 0; -} diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c deleted file mode 100644 index dbcb72930fa3..000000000000 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ /dev/null @@ -1,947 +0,0 @@ -/* - * Atheros AR9170 driver - * - * USB - frontend - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include "ar9170.h" -#include "cmd.h" -#include "hw.h" -#include "usb.h" - -MODULE_AUTHOR("Johannes Berg "); -MODULE_AUTHOR("Christian Lamparter "); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Atheros AR9170 802.11n USB wireless"); -MODULE_FIRMWARE("ar9170.fw"); -MODULE_FIRMWARE("ar9170-1.fw"); -MODULE_FIRMWARE("ar9170-2.fw"); - -enum ar9170_requirements { - AR9170_REQ_FW1_ONLY = 1, -}; - -static struct usb_device_id ar9170_usb_ids[] = { - /* Atheros 9170 */ - { USB_DEVICE(0x0cf3, 0x9170) }, - /* Atheros TG121N */ - { USB_DEVICE(0x0cf3, 0x1001) }, - /* TP-Link TL-WN821N v2 */ - { USB_DEVICE(0x0cf3, 0x1002) }, - /* 3Com Dual Band 802.11n USB Adapter */ - { USB_DEVICE(0x0cf3, 0x1010) }, - /* H3C Dual Band 802.11n USB Adapter */ - { USB_DEVICE(0x0cf3, 0x1011) }, - /* Cace Airpcap NX */ - { USB_DEVICE(0xcace, 0x0300) }, - /* D-Link DWA 160 A1 */ - { USB_DEVICE(0x07d1, 0x3c10) }, - /* D-Link DWA 160 A2 */ - { USB_DEVICE(0x07d1, 0x3a09) }, - /* Netgear WNA1000 */ - { USB_DEVICE(0x0846, 0x9040) }, - /* Netgear WNDA3100 */ - { USB_DEVICE(0x0846, 0x9010) }, - /* Netgear WN111 v2 */ - { USB_DEVICE(0x0846, 0x9001) }, - /* Zydas ZD1221 */ - { USB_DEVICE(0x0ace, 0x1221) }, - /* Proxim ORiNOCO 802.11n USB */ - { USB_DEVICE(0x1435, 0x0804) }, - /* WNC Generic 11n USB Dongle */ - { USB_DEVICE(0x1435, 0x0326) }, - /* ZyXEL NWD271N */ - { USB_DEVICE(0x0586, 0x3417) }, - /* Z-Com UB81 BG */ - { USB_DEVICE(0x0cde, 0x0023) }, - /* Z-Com UB82 ABG */ - { USB_DEVICE(0x0cde, 0x0026) }, - /* Arcadyan WN7512 */ - { USB_DEVICE(0x083a, 0xf522) }, - /* Planex GWUS300 */ - { USB_DEVICE(0x2019, 0x5304) }, - /* IO-Data WNGDNUS2 */ - { USB_DEVICE(0x04bb, 0x093f) }, - /* AVM FRITZ!WLAN USB Stick N */ - { USB_DEVICE(0x057C, 0x8401) }, - /* AVM FRITZ!WLAN USB Stick N 2.4 */ - { USB_DEVICE(0x057C, 0x8402), .driver_info = AR9170_REQ_FW1_ONLY }, - - /* terminate */ - {} -}; -MODULE_DEVICE_TABLE(usb, ar9170_usb_ids); - -static void ar9170_usb_submit_urb(struct ar9170_usb *aru) -{ - struct urb *urb; - unsigned long flags; - int err; - - if (unlikely(!IS_STARTED(&aru->common))) - return ; - - spin_lock_irqsave(&aru->tx_urb_lock, flags); - if (aru->tx_submitted_urbs >= AR9170_NUM_TX_URBS) { - spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - return ; - } - aru->tx_submitted_urbs++; - - urb = usb_get_from_anchor(&aru->tx_pending); - if (!urb) { - aru->tx_submitted_urbs--; - spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - - return ; - } - spin_unlock_irqrestore(&aru->tx_urb_lock, flags); - - aru->tx_pending_urbs--; - usb_anchor_urb(urb, &aru->tx_submitted); - - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) { - if (ar9170_nag_limiter(&aru->common)) - dev_err(&aru->udev->dev, "submit_urb failed (%d).\n", - err); - - usb_unanchor_urb(urb); - aru->tx_submitted_urbs--; - ar9170_tx_callback(&aru->common, urb->context); - } - - usb_free_urb(urb); -} - -static void ar9170_usb_tx_urb_complete_frame(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - - if (unlikely(!aru)) { - dev_kfree_skb_irq(skb); - return ; - } - - aru->tx_submitted_urbs--; - - ar9170_tx_callback(&aru->common, skb); - - ar9170_usb_submit_urb(aru); -} - -static void ar9170_usb_tx_urb_complete(struct urb *urb) -{ -} - -static void ar9170_usb_irq_completed(struct urb *urb) -{ - struct ar9170_usb *aru = urb->context; - - switch (urb->status) { - /* everything is fine */ - case 0: - break; - - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - - default: - goto resubmit; - } - - ar9170_handle_command_response(&aru->common, urb->transfer_buffer, - urb->actual_length); - -resubmit: - usb_anchor_urb(urb, &aru->rx_submitted); - if (usb_submit_urb(urb, GFP_ATOMIC)) { - usb_unanchor_urb(urb); - goto free; - } - - return; - -free: - usb_buffer_free(aru->udev, 64, urb->transfer_buffer, urb->transfer_dma); -} - -static void ar9170_usb_rx_completed(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ar9170_usb *aru = (struct ar9170_usb *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - int err; - - if (!aru) - goto free; - - switch (urb->status) { - /* everything is fine */ - case 0: - break; - - /* disconnect */ - case -ENOENT: - case -ECONNRESET: - case -ENODEV: - case -ESHUTDOWN: - goto free; - - default: - goto resubmit; - } - - skb_put(skb, urb->actual_length); - ar9170_rx(&aru->common, skb); - -resubmit: - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) { - usb_unanchor_urb(urb); - goto free; - } - - return ; - -free: - dev_kfree_skb_irq(skb); -} - -static int ar9170_usb_prep_rx_urb(struct ar9170_usb *aru, - struct urb *urb, gfp_t gfp) -{ - struct sk_buff *skb; - - skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE + 32, gfp); - if (!skb) - return -ENOMEM; - - /* reserve some space for mac80211's radiotap */ - skb_reserve(skb, 32); - - usb_fill_bulk_urb(urb, aru->udev, - usb_rcvbulkpipe(aru->udev, AR9170_EP_RX), - skb->data, min(skb_tailroom(skb), - AR9170_MAX_RX_BUFFER_SIZE), - ar9170_usb_rx_completed, skb); - - return 0; -} - -static int ar9170_usb_alloc_rx_irq_urb(struct ar9170_usb *aru) -{ - struct urb *urb = NULL; - void *ibuf; - int err = -ENOMEM; - - /* initialize interrupt endpoint */ - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto out; - - ibuf = usb_buffer_alloc(aru->udev, 64, GFP_KERNEL, &urb->transfer_dma); - if (!ibuf) - goto out; - - usb_fill_int_urb(urb, aru->udev, - usb_rcvintpipe(aru->udev, AR9170_EP_IRQ), ibuf, - 64, ar9170_usb_irq_completed, aru, 1); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - usb_unanchor_urb(urb); - usb_buffer_free(aru->udev, 64, urb->transfer_buffer, - urb->transfer_dma); - } - -out: - usb_free_urb(urb); - return err; -} - -static int ar9170_usb_alloc_rx_bulk_urbs(struct ar9170_usb *aru) -{ - struct urb *urb; - int i; - int err = -EINVAL; - - for (i = 0; i < AR9170_NUM_RX_URBS; i++) { - err = -ENOMEM; - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - goto err_out; - - err = ar9170_usb_prep_rx_urb(aru, urb, GFP_KERNEL); - if (err) { - usb_free_urb(urb); - goto err_out; - } - - usb_anchor_urb(urb, &aru->rx_submitted); - err = usb_submit_urb(urb, GFP_KERNEL); - if (err) { - usb_unanchor_urb(urb); - dev_kfree_skb_any((void *) urb->transfer_buffer); - usb_free_urb(urb); - goto err_out; - } - usb_free_urb(urb); - } - - /* the device now waiting for a firmware. */ - aru->common.state = AR9170_IDLE; - return 0; - -err_out: - - usb_kill_anchored_urbs(&aru->rx_submitted); - return err; -} - -static int ar9170_usb_flush(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - struct urb *urb; - int ret, err = 0; - - if (IS_STARTED(ar)) - aru->common.state = AR9170_IDLE; - - usb_wait_anchor_empty_timeout(&aru->tx_pending, - msecs_to_jiffies(800)); - while ((urb = usb_get_from_anchor(&aru->tx_pending))) { - ar9170_tx_callback(&aru->common, (void *) urb->context); - usb_free_urb(urb); - } - - /* lets wait a while until the tx - queues are dried out */ - ret = usb_wait_anchor_empty_timeout(&aru->tx_submitted, - msecs_to_jiffies(100)); - if (ret == 0) - err = -ETIMEDOUT; - - usb_kill_anchored_urbs(&aru->tx_submitted); - - if (IS_ACCEPTING_CMD(ar)) - aru->common.state = AR9170_STARTED; - - return err; -} - -static void ar9170_usb_cancel_urbs(struct ar9170_usb *aru) -{ - int err; - - aru->common.state = AR9170_UNKNOWN_STATE; - - err = ar9170_usb_flush(&aru->common); - if (err) - dev_err(&aru->udev->dev, "stuck tx urbs!\n"); - - usb_poison_anchored_urbs(&aru->tx_submitted); - usb_poison_anchored_urbs(&aru->rx_submitted); -} - -static int ar9170_usb_exec_cmd(struct ar9170 *ar, enum ar9170_cmd cmd, - unsigned int plen, void *payload, - unsigned int outlen, void *out) -{ - struct ar9170_usb *aru = (void *) ar; - struct urb *urb = NULL; - unsigned long flags; - int err = -ENOMEM; - - if (unlikely(!IS_ACCEPTING_CMD(ar))) - return -EPERM; - - if (WARN_ON(plen > AR9170_MAX_CMD_LEN - 4)) - return -EINVAL; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (unlikely(!urb)) - goto err_free; - - ar->cmdbuf[0] = cpu_to_le32(plen); - ar->cmdbuf[0] |= cpu_to_le32(cmd << 8); - /* writing multiple regs fills this buffer already */ - if (plen && payload != (u8 *)(&ar->cmdbuf[1])) - memcpy(&ar->cmdbuf[1], payload, plen); - - spin_lock_irqsave(&aru->common.cmdlock, flags); - aru->readbuf = (u8 *)out; - aru->readlen = outlen; - spin_unlock_irqrestore(&aru->common.cmdlock, flags); - - usb_fill_int_urb(urb, aru->udev, - usb_sndintpipe(aru->udev, AR9170_EP_CMD), - aru->common.cmdbuf, plen + 4, - ar9170_usb_tx_urb_complete, NULL, 1); - - usb_anchor_urb(urb, &aru->tx_submitted); - err = usb_submit_urb(urb, GFP_ATOMIC); - if (unlikely(err)) { - usb_unanchor_urb(urb); - usb_free_urb(urb); - goto err_unbuf; - } - usb_free_urb(urb); - - err = wait_for_completion_timeout(&aru->cmd_wait, HZ); - if (err == 0) { - err = -ETIMEDOUT; - goto err_unbuf; - } - - if (aru->readlen != outlen) { - err = -EMSGSIZE; - goto err_unbuf; - } - - return 0; - -err_unbuf: - /* Maybe the device was removed in the second we were waiting? */ - if (IS_STARTED(ar)) { - dev_err(&aru->udev->dev, "no command feedback " - "received (%d).\n", err); - - /* provide some maybe useful debug information */ - print_hex_dump_bytes("ar9170 cmd: ", DUMP_PREFIX_NONE, - aru->common.cmdbuf, plen + 4); - dump_stack(); - } - - /* invalidate to avoid completing the next prematurely */ - spin_lock_irqsave(&aru->common.cmdlock, flags); - aru->readbuf = NULL; - aru->readlen = 0; - spin_unlock_irqrestore(&aru->common.cmdlock, flags); - -err_free: - - return err; -} - -static int ar9170_usb_tx(struct ar9170 *ar, struct sk_buff *skb) -{ - struct ar9170_usb *aru = (struct ar9170_usb *) ar; - struct urb *urb; - - if (unlikely(!IS_STARTED(ar))) { - /* Seriously, what were you drink... err... thinking!? */ - return -EPERM; - } - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (unlikely(!urb)) - return -ENOMEM; - - usb_fill_bulk_urb(urb, aru->udev, - usb_sndbulkpipe(aru->udev, AR9170_EP_TX), - skb->data, skb->len, - ar9170_usb_tx_urb_complete_frame, skb); - urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(urb, &aru->tx_pending); - aru->tx_pending_urbs++; - - usb_free_urb(urb); - - ar9170_usb_submit_urb(aru); - return 0; -} - -static void ar9170_usb_callback_cmd(struct ar9170 *ar, u32 len , void *buffer) -{ - struct ar9170_usb *aru = (void *) ar; - unsigned long flags; - u32 in, out; - - if (unlikely(!buffer)) - return ; - - in = le32_to_cpup((__le32 *)buffer); - out = le32_to_cpu(ar->cmdbuf[0]); - - /* mask off length byte */ - out &= ~0xFF; - - if (aru->readlen >= 0) { - /* add expected length */ - out |= aru->readlen; - } else { - /* add obtained length */ - out |= in & 0xFF; - } - - /* - * Some commands (e.g: AR9170_CMD_FREQUENCY) have a variable response - * length and we cannot predict the correct length in advance. - * So we only check if we provided enough space for the data. - */ - if (unlikely(out < in)) { - dev_warn(&aru->udev->dev, "received invalid command response " - "got %d bytes, instead of %d bytes " - "and the resp length is %d bytes\n", - in, out, len); - print_hex_dump_bytes("ar9170 invalid resp: ", - DUMP_PREFIX_OFFSET, buffer, len); - /* - * Do not complete, then the command times out, - * and we get a stack trace from there. - */ - return ; - } - - spin_lock_irqsave(&aru->common.cmdlock, flags); - if (aru->readbuf && len > 0) { - memcpy(aru->readbuf, buffer + 4, len - 4); - aru->readbuf = NULL; - } - complete(&aru->cmd_wait); - spin_unlock_irqrestore(&aru->common.cmdlock, flags); -} - -static int ar9170_usb_upload(struct ar9170_usb *aru, const void *data, - size_t len, u32 addr, bool complete) -{ - int transfer, err; - u8 *buf = kmalloc(4096, GFP_KERNEL); - - if (!buf) - return -ENOMEM; - - while (len) { - transfer = min_t(int, len, 4096); - memcpy(buf, data, transfer); - - err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), - 0x30 /* FW DL */, 0x40 | USB_DIR_OUT, - addr >> 8, 0, buf, transfer, 1000); - - if (err < 0) { - kfree(buf); - return err; - } - - len -= transfer; - data += transfer; - addr += transfer; - } - kfree(buf); - - if (complete) { - err = usb_control_msg(aru->udev, usb_sndctrlpipe(aru->udev, 0), - 0x31 /* FW DL COMPLETE */, - 0x40 | USB_DIR_OUT, 0, 0, NULL, 0, 5000); - } - - return 0; -} - -static int ar9170_usb_request_firmware(struct ar9170_usb *aru) -{ - int err = 0; - - err = request_firmware(&aru->firmware, "ar9170.fw", - &aru->udev->dev); - if (!err) { - aru->init_values = NULL; - return 0; - } - - if (aru->req_one_stage_fw) { - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found and is required for this device\n"); - return -EINVAL; - } - - dev_err(&aru->udev->dev, "ar9170.fw firmware file " - "not found, trying old firmware...\n"); - - err = request_firmware(&aru->init_values, "ar9170-1.fw", - &aru->udev->dev); - if (err) { - dev_err(&aru->udev->dev, "file with init values not found.\n"); - return err; - } - - err = request_firmware(&aru->firmware, "ar9170-2.fw", &aru->udev->dev); - if (err) { - release_firmware(aru->init_values); - dev_err(&aru->udev->dev, "firmware file not found.\n"); - return err; - } - - return err; -} - -static int ar9170_usb_reset(struct ar9170_usb *aru) -{ - int ret, lock = (aru->intf->condition != USB_INTERFACE_BINDING); - - if (lock) { - ret = usb_lock_device_for_reset(aru->udev, aru->intf); - if (ret < 0) { - dev_err(&aru->udev->dev, "unable to lock device " - "for reset (%d).\n", ret); - return ret; - } - } - - ret = usb_reset_device(aru->udev); - if (lock) - usb_unlock_device(aru->udev); - - /* let it rest - for a second - */ - msleep(1000); - - return ret; -} - -static int ar9170_usb_upload_firmware(struct ar9170_usb *aru) -{ - int err; - - if (!aru->init_values) - goto upload_fw_start; - - /* First, upload initial values to device RAM */ - err = ar9170_usb_upload(aru, aru->init_values->data, - aru->init_values->size, 0x102800, false); - if (err) { - dev_err(&aru->udev->dev, "firmware part 1 " - "upload failed (%d).\n", err); - return err; - } - -upload_fw_start: - - /* Then, upload the firmware itself and start it */ - return ar9170_usb_upload(aru, aru->firmware->data, aru->firmware->size, - 0x200000, true); -} - -static int ar9170_usb_init_transport(struct ar9170_usb *aru) -{ - struct ar9170 *ar = (void *) &aru->common; - int err; - - ar9170_regwrite_begin(ar); - - /* Set USB Rx stream mode MAX packet number to 2 */ - ar9170_regwrite(AR9170_USB_REG_MAX_AGG_UPLOAD, 0x4); - - /* Set USB Rx stream mode timeout to 10us */ - ar9170_regwrite(AR9170_USB_REG_UPLOAD_TIME_CTL, 0x80); - - ar9170_regwrite_finish(); - - err = ar9170_regwrite_result(); - if (err) - dev_err(&aru->udev->dev, "USB setup failed (%d).\n", err); - - return err; -} - -static void ar9170_usb_stop(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - int ret; - - if (IS_ACCEPTING_CMD(ar)) - aru->common.state = AR9170_STOPPED; - - ret = ar9170_usb_flush(ar); - if (ret) - dev_err(&aru->udev->dev, "kill pending tx urbs.\n"); - - usb_poison_anchored_urbs(&aru->tx_submitted); - - /* - * Note: - * So far we freed all tx urbs, but we won't dare to touch any rx urbs. - * Else we would end up with a unresponsive device... - */ -} - -static int ar9170_usb_open(struct ar9170 *ar) -{ - struct ar9170_usb *aru = (void *) ar; - int err; - - usb_unpoison_anchored_urbs(&aru->tx_submitted); - err = ar9170_usb_init_transport(aru); - if (err) { - usb_poison_anchored_urbs(&aru->tx_submitted); - return err; - } - - aru->common.state = AR9170_IDLE; - return 0; -} - -static int ar9170_usb_init_device(struct ar9170_usb *aru) -{ - int err; - - err = ar9170_usb_alloc_rx_irq_urb(aru); - if (err) - goto err_out; - - err = ar9170_usb_alloc_rx_bulk_urbs(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_upload_firmware(aru); - if (err) { - err = ar9170_echo_test(&aru->common, 0x60d43110); - if (err) { - /* force user invention, by disabling the device */ - err = usb_driver_set_configuration(aru->udev, -1); - dev_err(&aru->udev->dev, "device is in a bad state. " - "please reconnect it!\n"); - goto err_unrx; - } - } - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_out: - return err; -} - -static bool ar9170_requires_one_stage(const struct usb_device_id *id) -{ - if (!id->driver_info) - return false; - if (id->driver_info == AR9170_REQ_FW1_ONLY) - return true; - return false; -} - -static int ar9170_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct ar9170_usb *aru; - struct ar9170 *ar; - struct usb_device *udev; - int err; - - aru = ar9170_alloc(sizeof(*aru)); - if (IS_ERR(aru)) { - err = PTR_ERR(aru); - goto out; - } - - udev = interface_to_usbdev(intf); - usb_get_dev(udev); - aru->udev = udev; - aru->intf = intf; - ar = &aru->common; - - aru->req_one_stage_fw = ar9170_requires_one_stage(id); - - usb_set_intfdata(intf, aru); - SET_IEEE80211_DEV(ar->hw, &intf->dev); - - init_usb_anchor(&aru->rx_submitted); - init_usb_anchor(&aru->tx_pending); - init_usb_anchor(&aru->tx_submitted); - init_completion(&aru->cmd_wait); - spin_lock_init(&aru->tx_urb_lock); - - aru->tx_pending_urbs = 0; - aru->tx_submitted_urbs = 0; - - aru->common.stop = ar9170_usb_stop; - aru->common.flush = ar9170_usb_flush; - aru->common.open = ar9170_usb_open; - aru->common.tx = ar9170_usb_tx; - aru->common.exec_cmd = ar9170_usb_exec_cmd; - aru->common.callback_cmd = ar9170_usb_callback_cmd; - -#ifdef CONFIG_PM - udev->reset_resume = 1; -#endif /* CONFIG_PM */ - err = ar9170_usb_reset(aru); - if (err) - goto err_freehw; - - err = ar9170_usb_request_firmware(aru); - if (err) - goto err_freehw; - - err = ar9170_usb_init_device(aru); - if (err) - goto err_freefw; - - err = ar9170_usb_open(ar); - if (err) - goto err_unrx; - - err = ar9170_register(ar, &udev->dev); - - ar9170_usb_stop(ar); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - ar9170_usb_cancel_urbs(aru); - -err_freefw: - release_firmware(aru->init_values); - release_firmware(aru->firmware); - -err_freehw: - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - ieee80211_free_hw(ar->hw); -out: - return err; -} - -static void ar9170_usb_disconnect(struct usb_interface *intf) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - - if (!aru) - return; - - aru->common.state = AR9170_IDLE; - ar9170_unregister(&aru->common); - ar9170_usb_cancel_urbs(aru); - - release_firmware(aru->init_values); - release_firmware(aru->firmware); - - usb_put_dev(aru->udev); - usb_set_intfdata(intf, NULL); - ieee80211_free_hw(aru->common.hw); -} - -#ifdef CONFIG_PM -static int ar9170_suspend(struct usb_interface *intf, - pm_message_t message) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - - if (!aru) - return -ENODEV; - - aru->common.state = AR9170_IDLE; - ar9170_usb_cancel_urbs(aru); - - return 0; -} - -static int ar9170_resume(struct usb_interface *intf) -{ - struct ar9170_usb *aru = usb_get_intfdata(intf); - int err; - - if (!aru) - return -ENODEV; - - usb_unpoison_anchored_urbs(&aru->rx_submitted); - usb_unpoison_anchored_urbs(&aru->tx_submitted); - - err = ar9170_usb_init_device(aru); - if (err) - goto err_unrx; - - err = ar9170_usb_open(&aru->common); - if (err) - goto err_unrx; - - return 0; - -err_unrx: - aru->common.state = AR9170_IDLE; - ar9170_usb_cancel_urbs(aru); - - return err; -} -#endif /* CONFIG_PM */ - -static struct usb_driver ar9170_driver = { - .name = "ar9170usb", - .probe = ar9170_usb_probe, - .disconnect = ar9170_usb_disconnect, - .id_table = ar9170_usb_ids, - .soft_unbind = 1, -#ifdef CONFIG_PM - .suspend = ar9170_suspend, - .resume = ar9170_resume, - .reset_resume = ar9170_resume, -#endif /* CONFIG_PM */ -}; - -static int __init ar9170_init(void) -{ - return usb_register(&ar9170_driver); -} - -static void __exit ar9170_exit(void) -{ - usb_deregister(&ar9170_driver); -} - -module_init(ar9170_init); -module_exit(ar9170_exit); diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h deleted file mode 100644 index d098f4d5d2f2..000000000000 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Atheros AR9170 USB driver - * - * Driver specific definitions - * - * Copyright 2008, Johannes Berg - * Copyright 2009, Christian Lamparter - * - * 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; see the file COPYING. If not, see - * http://www.gnu.org/licenses/. - * - * This file incorporates work covered by the following copyright and - * permission notice: - * Copyright (c) 2007-2008 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ -#ifndef __USB_H -#define __USB_H - -#include -#include -#include -#include -#include -#include -#include -#include "eeprom.h" -#include "hw.h" -#include "ar9170.h" - -#define AR9170_NUM_RX_URBS 16 -#define AR9170_NUM_TX_URBS 8 - -struct firmware; - -struct ar9170_usb { - struct ar9170 common; - struct usb_device *udev; - struct usb_interface *intf; - - struct usb_anchor rx_submitted; - struct usb_anchor tx_pending; - struct usb_anchor tx_submitted; - - bool req_one_stage_fw; - - spinlock_t tx_urb_lock; - unsigned int tx_submitted_urbs; - unsigned int tx_pending_urbs; - - struct completion cmd_wait; - int readlen; - u8 *readbuf; - - const struct firmware *init_values; - const struct firmware *firmware; -}; - -#endif /* __USB_H */ diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h deleted file mode 100644 index a63e90cbf9e5..000000000000 --- a/drivers/net/wireless/ath/ath.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef ATH_H -#define ATH_H - -#include - -struct reg_dmn_pair_mapping { - u16 regDmnEnum; - u16 reg_5ghz_ctl; - u16 reg_2ghz_ctl; -}; - -struct ath_regulatory { - char alpha2[2]; - u16 country_code; - u16 max_power_level; - u32 tp_scale; - u16 current_rd; - u16 current_rd_ext; - int16_t power_limit; - struct reg_dmn_pair_mapping *regpair; -}; - -struct ath_common { - u16 cachelsz; - struct ath_regulatory regulatory; -}; - -struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, - u32 len, - gfp_t gfp_mask); - -#endif /* ATH_H */ diff --git a/drivers/net/wireless/ath/ath5k/Kconfig b/drivers/net/wireless/ath/ath5k/Kconfig deleted file mode 100644 index 06d006675d7d..000000000000 --- a/drivers/net/wireless/ath/ath5k/Kconfig +++ /dev/null @@ -1,39 +0,0 @@ -config ATH5K - tristate "Atheros 5xxx wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS - ---help--- - This module adds support for wireless adapters based on - Atheros 5xxx chipset. - - Currently the following chip versions are supported: - - MAC: AR5211 AR5212 - PHY: RF5111/2111 RF5112/2112 RF5413/2413 - - This driver uses the kernel's mac80211 subsystem. - - If you choose to build a module, it'll be called ath5k. Say M if - unsure. - -config ATH5K_DEBUG - bool "Atheros 5xxx debugging" - depends on ATH5K - ---help--- - Atheros 5xxx debugging messages. - - Say Y, if and you will get debug options for ath5k. - To use this, you need to mount debugfs: - - mount -t debugfs debug /sys/kernel/debug - - You will get access to files under: - /sys/kernel/debug/ath5k/phy0/ - - To enable debug, pass the debug level to the debug module - parameter. For example: - - modprobe ath5k debug=0x00000400 - diff --git a/drivers/net/wireless/ath/ath5k/Makefile b/drivers/net/wireless/ath/ath5k/Makefile deleted file mode 100644 index 090dc6d268a3..000000000000 --- a/drivers/net/wireless/ath/ath5k/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -ath5k-y += caps.o -ath5k-y += initvals.o -ath5k-y += eeprom.o -ath5k-y += gpio.o -ath5k-y += desc.o -ath5k-y += dma.o -ath5k-y += qcu.o -ath5k-y += pcu.o -ath5k-y += phy.o -ath5k-y += reset.o -ath5k-y += attach.o -ath5k-y += base.o -ath5k-y += led.o -ath5k-y += rfkill.o -ath5k-$(CONFIG_ATH5K_DEBUG) += debug.o -obj-$(CONFIG_ATH5K) += ath5k.o diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h deleted file mode 100644 index 2c79c78ef2d7..000000000000 --- a/drivers/net/wireless/ath/ath5k/ath5k.h +++ /dev/null @@ -1,1387 +0,0 @@ -/* - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2007 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef _ATH5K_H -#define _ATH5K_H - -/* TODO: Clean up channel debuging -doesn't work anyway- and start - * working on reg. control code using all available eeprom information - * -rev. engineering needed- */ -#define CHAN_DEBUG 0 - -#include -#include -#include - -/* RX/TX descriptor hw structs - * TODO: Driver part should only see sw structs */ -#include "desc.h" - -/* EEPROM structs/offsets - * TODO: Make a more generic struct (eg. add more stuff to ath5k_capabilities) - * and clean up common bits, then introduce set/get functions in eeprom.c */ -#include "eeprom.h" - -/* PCI IDs */ -#define PCI_DEVICE_ID_ATHEROS_AR5210 0x0007 /* AR5210 */ -#define PCI_DEVICE_ID_ATHEROS_AR5311 0x0011 /* AR5311 */ -#define PCI_DEVICE_ID_ATHEROS_AR5211 0x0012 /* AR5211 */ -#define PCI_DEVICE_ID_ATHEROS_AR5212 0x0013 /* AR5212 */ -#define PCI_DEVICE_ID_3COM_3CRDAG675 0x0013 /* 3CRDAG675 (Atheros AR5212) */ -#define PCI_DEVICE_ID_3COM_2_3CRPAG175 0x0013 /* 3CRPAG175 (Atheros AR5212) */ -#define PCI_DEVICE_ID_ATHEROS_AR5210_AP 0x0207 /* AR5210 (Early) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_IBM 0x1014 /* AR5212 (IBM MiniPCI) */ -#define PCI_DEVICE_ID_ATHEROS_AR5210_DEFAULT 0x1107 /* AR5210 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_DEFAULT 0x1113 /* AR5212 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_DEFAULT 0x1112 /* AR5211 (no eeprom) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_FPGA 0xf013 /* AR5212 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_LEGACY 0xff12 /* AR5211 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5211_FPGA11B 0xf11b /* AR5211 (emulation board) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV2 0x0052 /* AR5312 WMAC (AP31) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV7 0x0057 /* AR5312 WMAC (AP30-040) */ -#define PCI_DEVICE_ID_ATHEROS_AR5312_REV8 0x0058 /* AR5312 WMAC (AP43-030) */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0014 0x0014 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0015 0x0015 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0016 0x0016 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0017 0x0017 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0018 0x0018 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR5212_0019 0x0019 /* AR5212 compatible */ -#define PCI_DEVICE_ID_ATHEROS_AR2413 0x001a /* AR2413 (Griffin-lite) */ -#define PCI_DEVICE_ID_ATHEROS_AR5413 0x001b /* AR5413 (Eagle) */ -#define PCI_DEVICE_ID_ATHEROS_AR5424 0x001c /* AR5424 (Condor PCI-E) */ -#define PCI_DEVICE_ID_ATHEROS_AR5416 0x0023 /* AR5416 */ -#define PCI_DEVICE_ID_ATHEROS_AR5418 0x0024 /* AR5418 */ - -/****************************\ - GENERIC DRIVER DEFINITIONS -\****************************/ - -#define ATH5K_PRINTF(fmt, ...) printk("%s: " fmt, __func__, ##__VA_ARGS__) - -#define ATH5K_PRINTK(_sc, _level, _fmt, ...) \ - printk(_level "ath5k %s: " _fmt, \ - ((_sc) && (_sc)->hw) ? wiphy_name((_sc)->hw->wiphy) : "", \ - ##__VA_ARGS__) - -#define ATH5K_PRINTK_LIMIT(_sc, _level, _fmt, ...) do { \ - if (net_ratelimit()) \ - ATH5K_PRINTK(_sc, _level, _fmt, ##__VA_ARGS__); \ - } while (0) - -#define ATH5K_INFO(_sc, _fmt, ...) \ - ATH5K_PRINTK(_sc, KERN_INFO, _fmt, ##__VA_ARGS__) - -#define ATH5K_WARN(_sc, _fmt, ...) \ - ATH5K_PRINTK_LIMIT(_sc, KERN_WARNING, _fmt, ##__VA_ARGS__) - -#define ATH5K_ERR(_sc, _fmt, ...) \ - ATH5K_PRINTK_LIMIT(_sc, KERN_ERR, _fmt, ##__VA_ARGS__) - -/* - * AR5K REGISTER ACCESS - */ - -/* Some macros to read/write fields */ - -/* First shift, then mask */ -#define AR5K_REG_SM(_val, _flags) \ - (((_val) << _flags##_S) & (_flags)) - -/* First mask, then shift */ -#define AR5K_REG_MS(_val, _flags) \ - (((_val) & (_flags)) >> _flags##_S) - -/* Some registers can hold multiple values of interest. For this - * reason when we want to write to these registers we must first - * retrieve the values which we do not want to clear (lets call this - * old_data) and then set the register with this and our new_value: - * ( old_data | new_value) */ -#define AR5K_REG_WRITE_BITS(ah, _reg, _flags, _val) \ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & ~(_flags)) | \ - (((_val) << _flags##_S) & (_flags)), _reg) - -#define AR5K_REG_MASKED_BITS(ah, _reg, _flags, _mask) \ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, _reg) & \ - (_mask)) | (_flags), _reg) - -#define AR5K_REG_ENABLE_BITS(ah, _reg, _flags) \ - ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) | (_flags), _reg) - -#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ - ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) - -/* Access to PHY registers */ -#define AR5K_PHY_READ(ah, _reg) \ - ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2)) - -#define AR5K_PHY_WRITE(ah, _reg, _val) \ - ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2)) - -/* Access QCU registers per queue */ -#define AR5K_REG_READ_Q(ah, _reg, _queue) \ - (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ - -#define AR5K_REG_WRITE_Q(ah, _reg, _queue) \ - ath5k_hw_reg_write(ah, (1 << _queue), _reg) - -#define AR5K_Q_ENABLE_BITS(_reg, _queue) do { \ - _reg |= 1 << _queue; \ -} while (0) - -#define AR5K_Q_DISABLE_BITS(_reg, _queue) do { \ - _reg &= ~(1 << _queue); \ -} while (0) - -/* Used while writing initvals */ -#define AR5K_REG_WAIT(_i) do { \ - if (_i % 64) \ - udelay(1); \ -} while (0) - -/* Register dumps are done per operation mode */ -#define AR5K_INI_RFGAIN_5GHZ 0 -#define AR5K_INI_RFGAIN_2GHZ 1 - -/* TODO: Clean this up */ -#define AR5K_INI_VAL_11A 0 -#define AR5K_INI_VAL_11A_TURBO 1 -#define AR5K_INI_VAL_11B 2 -#define AR5K_INI_VAL_11G 3 -#define AR5K_INI_VAL_11G_TURBO 4 -#define AR5K_INI_VAL_XR 0 -#define AR5K_INI_VAL_MAX 5 - -/* Used for BSSID etc manipulation */ -#define AR5K_LOW_ID(_a)( \ -(_a)[0] | (_a)[1] << 8 | (_a)[2] << 16 | (_a)[3] << 24 \ -) - -#define AR5K_HIGH_ID(_a) ((_a)[4] | (_a)[5] << 8) - -/* - * Some tuneable values (these should be changeable by the user) - * TODO: Make use of them and add more options OR use debug/configfs - */ -#define AR5K_TUNE_DMA_BEACON_RESP 2 -#define AR5K_TUNE_SW_BEACON_RESP 10 -#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 -#define AR5K_TUNE_RADAR_ALERT false -#define AR5K_TUNE_MIN_TX_FIFO_THRES 1 -#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_LEN / 64) + 1) -#define AR5K_TUNE_REGISTER_TIMEOUT 20000 -/* Register for RSSI threshold has a mask of 0xff, so 255 seems to - * be the max value. */ -#define AR5K_TUNE_RSSI_THRES 129 -/* This must be set when setting the RSSI threshold otherwise it can - * prevent a reset. If AR5K_RSSI_THR is read after writing to it - * the BMISS_THRES will be seen as 0, seems harware doesn't keep - * track of it. Max value depends on harware. For AR5210 this is just 7. - * For AR5211+ this seems to be up to 255. */ -#define AR5K_TUNE_BMISS_THRES 7 -#define AR5K_TUNE_REGISTER_DWELL_TIME 20000 -#define AR5K_TUNE_BEACON_INTERVAL 100 -#define AR5K_TUNE_AIFS 2 -#define AR5K_TUNE_AIFS_11B 2 -#define AR5K_TUNE_AIFS_XR 0 -#define AR5K_TUNE_CWMIN 15 -#define AR5K_TUNE_CWMIN_11B 31 -#define AR5K_TUNE_CWMIN_XR 3 -#define AR5K_TUNE_CWMAX 1023 -#define AR5K_TUNE_CWMAX_11B 1023 -#define AR5K_TUNE_CWMAX_XR 7 -#define AR5K_TUNE_NOISE_FLOOR -72 -#define AR5K_TUNE_MAX_TXPOWER 63 -#define AR5K_TUNE_DEFAULT_TXPOWER 25 -#define AR5K_TUNE_TPC_TXPOWER false -#define AR5K_TUNE_HWTXTRIES 4 - -#define AR5K_INIT_CARR_SENSE_EN 1 - -/*Swap RX/TX Descriptor for big endian archs*/ -#if defined(__BIG_ENDIAN) -#define AR5K_INIT_CFG ( \ - AR5K_CFG_SWTD | AR5K_CFG_SWRD \ -) -#else -#define AR5K_INIT_CFG 0x00000000 -#endif - -/* Initial values */ -#define AR5K_INIT_CYCRSSI_THR1 2 -#define AR5K_INIT_TX_LATENCY 502 -#define AR5K_INIT_USEC 39 -#define AR5K_INIT_USEC_TURBO 79 -#define AR5K_INIT_USEC_32 31 -#define AR5K_INIT_SLOT_TIME 396 -#define AR5K_INIT_SLOT_TIME_TURBO 480 -#define AR5K_INIT_ACK_CTS_TIMEOUT 1024 -#define AR5K_INIT_ACK_CTS_TIMEOUT_TURBO 0x08000800 -#define AR5K_INIT_PROG_IFS 920 -#define AR5K_INIT_PROG_IFS_TURBO 960 -#define AR5K_INIT_EIFS 3440 -#define AR5K_INIT_EIFS_TURBO 6880 -#define AR5K_INIT_SIFS 560 -#define AR5K_INIT_SIFS_TURBO 480 -#define AR5K_INIT_SH_RETRY 10 -#define AR5K_INIT_LG_RETRY AR5K_INIT_SH_RETRY -#define AR5K_INIT_SSH_RETRY 32 -#define AR5K_INIT_SLG_RETRY AR5K_INIT_SSH_RETRY -#define AR5K_INIT_TX_RETRY 10 - -#define AR5K_INIT_TRANSMIT_LATENCY ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC) \ -) -#define AR5K_INIT_TRANSMIT_LATENCY_TURBO ( \ - (AR5K_INIT_TX_LATENCY << 14) | (AR5K_INIT_USEC_32 << 7) | \ - (AR5K_INIT_USEC_TURBO) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS << 12) | \ - (AR5K_INIT_PROG_IFS) \ -) -#define AR5K_INIT_PROTO_TIME_CNTRL_TURBO ( \ - (AR5K_INIT_CARR_SENSE_EN << 26) | (AR5K_INIT_EIFS_TURBO << 12) | \ - (AR5K_INIT_PROG_IFS_TURBO) \ -) - -/* token to use for aifs, cwmin, cwmax in MadWiFi */ -#define AR5K_TXQ_USEDEFAULT ((u32) -1) - -/* GENERIC CHIPSET DEFINITIONS */ - -/* MAC Chips */ -enum ath5k_version { - AR5K_AR5210 = 0, - AR5K_AR5211 = 1, - AR5K_AR5212 = 2, -}; - -/* PHY Chips */ -enum ath5k_radio { - AR5K_RF5110 = 0, - AR5K_RF5111 = 1, - AR5K_RF5112 = 2, - AR5K_RF2413 = 3, - AR5K_RF5413 = 4, - AR5K_RF2316 = 5, - AR5K_RF2317 = 6, - AR5K_RF2425 = 7, -}; - -/* - * Common silicon revision/version values - */ - -enum ath5k_srev_type { - AR5K_VERSION_MAC, - AR5K_VERSION_RAD, -}; - -struct ath5k_srev_name { - const char *sr_name; - enum ath5k_srev_type sr_type; - u_int sr_val; -}; - -#define AR5K_SREV_UNKNOWN 0xffff - -#define AR5K_SREV_AR5210 0x00 /* Crete */ -#define AR5K_SREV_AR5311 0x10 /* Maui 1 */ -#define AR5K_SREV_AR5311A 0x20 /* Maui 2 */ -#define AR5K_SREV_AR5311B 0x30 /* Spirit */ -#define AR5K_SREV_AR5211 0x40 /* Oahu */ -#define AR5K_SREV_AR5212 0x50 /* Venice */ -#define AR5K_SREV_AR5212_V4 0x54 /* ??? */ -#define AR5K_SREV_AR5213 0x55 /* ??? */ -#define AR5K_SREV_AR5213A 0x59 /* Hainan */ -#define AR5K_SREV_AR2413 0x78 /* Griffin lite */ -#define AR5K_SREV_AR2414 0x70 /* Griffin */ -#define AR5K_SREV_AR5424 0x90 /* Condor */ -#define AR5K_SREV_AR5413 0xa4 /* Eagle lite */ -#define AR5K_SREV_AR5414 0xa0 /* Eagle */ -#define AR5K_SREV_AR2415 0xb0 /* Talon */ -#define AR5K_SREV_AR5416 0xc0 /* PCI-E */ -#define AR5K_SREV_AR5418 0xca /* PCI-E */ -#define AR5K_SREV_AR2425 0xe0 /* Swan */ -#define AR5K_SREV_AR2417 0xf0 /* Nala */ - -#define AR5K_SREV_RAD_5110 0x00 -#define AR5K_SREV_RAD_5111 0x10 -#define AR5K_SREV_RAD_5111A 0x15 -#define AR5K_SREV_RAD_2111 0x20 -#define AR5K_SREV_RAD_5112 0x30 -#define AR5K_SREV_RAD_5112A 0x35 -#define AR5K_SREV_RAD_5112B 0x36 -#define AR5K_SREV_RAD_2112 0x40 -#define AR5K_SREV_RAD_2112A 0x45 -#define AR5K_SREV_RAD_2112B 0x46 -#define AR5K_SREV_RAD_2413 0x50 -#define AR5K_SREV_RAD_5413 0x60 -#define AR5K_SREV_RAD_2316 0x70 /* Cobra SoC */ -#define AR5K_SREV_RAD_2317 0x80 -#define AR5K_SREV_RAD_5424 0xa0 /* Mostly same as 5413 */ -#define AR5K_SREV_RAD_2425 0xa2 -#define AR5K_SREV_RAD_5133 0xc0 - -#define AR5K_SREV_PHY_5211 0x30 -#define AR5K_SREV_PHY_5212 0x41 -#define AR5K_SREV_PHY_5212A 0x42 -#define AR5K_SREV_PHY_5212B 0x43 -#define AR5K_SREV_PHY_2413 0x45 -#define AR5K_SREV_PHY_5413 0x61 -#define AR5K_SREV_PHY_2425 0x70 - -/* IEEE defs */ -#define IEEE80211_MAX_LEN 2500 - -/* TODO add support to mac80211 for vendor-specific rates and modes */ - -/* - * Some of this information is based on Documentation from: - * - * http://madwifi.org/wiki/ChipsetFeatures/SuperAG - * - * Modulation for Atheros' eXtended Range - range enhancing extension that is - * supposed to double the distance an Atheros client device can keep a - * connection with an Atheros access point. This is achieved by increasing - * the receiver sensitivity up to, -105dBm, which is about 20dB above what - * the 802.11 specifications demand. In addition, new (proprietary) data rates - * are introduced: 3, 2, 1, 0.5 and 0.25 MBit/s. - * - * Please note that can you either use XR or TURBO but you cannot use both, - * they are exclusive. - * - */ -#define MODULATION_XR 0x00000200 -/* - * Modulation for Atheros' Turbo G and Turbo A, its supposed to provide a - * throughput transmission speed up to 40Mbit/s-60Mbit/s at a 108Mbit/s - * signaling rate achieved through the bonding of two 54Mbit/s 802.11g - * channels. To use this feature your Access Point must also suport it. - * There is also a distinction between "static" and "dynamic" turbo modes: - * - * - Static: is the dumb version: devices set to this mode stick to it until - * the mode is turned off. - * - Dynamic: is the intelligent version, the network decides itself if it - * is ok to use turbo. As soon as traffic is detected on adjacent channels - * (which would get used in turbo mode), or when a non-turbo station joins - * the network, turbo mode won't be used until the situation changes again. - * Dynamic mode is achieved by Atheros' Adaptive Radio (AR) feature which - * monitors the used radio band in order to decide whether turbo mode may - * be used or not. - * - * This article claims Super G sticks to bonding of channels 5 and 6 for - * USA: - * - * http://www.pcworld.com/article/id,113428-page,1/article.html - * - * The channel bonding seems to be driver specific though. In addition to - * deciding what channels will be used, these "Turbo" modes are accomplished - * by also enabling the following features: - * - * - Bursting: allows multiple frames to be sent at once, rather than pausing - * after each frame. Bursting is a standards-compliant feature that can be - * used with any Access Point. - * - Fast frames: increases the amount of information that can be sent per - * frame, also resulting in a reduction of transmission overhead. It is a - * proprietary feature that needs to be supported by the Access Point. - * - Compression: data frames are compressed in real time using a Lempel Ziv - * algorithm. This is done transparently. Once this feature is enabled, - * compression and decompression takes place inside the chipset, without - * putting additional load on the host CPU. - * - */ -#define MODULATION_TURBO 0x00000080 - -enum ath5k_driver_mode { - AR5K_MODE_11A = 0, - AR5K_MODE_11A_TURBO = 1, - AR5K_MODE_11B = 2, - AR5K_MODE_11G = 3, - AR5K_MODE_11G_TURBO = 4, - AR5K_MODE_XR = 0, - AR5K_MODE_MAX = 5 -}; - -enum ath5k_ant_mode { - AR5K_ANTMODE_DEFAULT = 0, /* default antenna setup */ - AR5K_ANTMODE_FIXED_A = 1, /* only antenna A is present */ - AR5K_ANTMODE_FIXED_B = 2, /* only antenna B is present */ - AR5K_ANTMODE_SINGLE_AP = 3, /* sta locked on a single ap */ - AR5K_ANTMODE_SECTOR_AP = 4, /* AP with tx antenna set on tx desc */ - AR5K_ANTMODE_SECTOR_STA = 5, /* STA with tx antenna set on tx desc */ - AR5K_ANTMODE_DEBUG = 6, /* Debug mode -A -> Rx, B-> Tx- */ - AR5K_ANTMODE_MAX, -}; - - -/****************\ - TX DEFINITIONS -\****************/ - -/* - * TX Status descriptor - */ -struct ath5k_tx_status { - u16 ts_seqnum; - u16 ts_tstamp; - u8 ts_status; - u8 ts_rate[4]; - u8 ts_retry[4]; - u8 ts_final_idx; - s8 ts_rssi; - u8 ts_shortretry; - u8 ts_longretry; - u8 ts_virtcol; - u8 ts_antenna; -}; - -#define AR5K_TXSTAT_ALTRATE 0x80 -#define AR5K_TXERR_XRETRY 0x01 -#define AR5K_TXERR_FILT 0x02 -#define AR5K_TXERR_FIFO 0x04 - -/** - * enum ath5k_tx_queue - Queue types used to classify tx queues. - * @AR5K_TX_QUEUE_INACTIVE: q is unused -- see ath5k_hw_release_tx_queue - * @AR5K_TX_QUEUE_DATA: A normal data queue - * @AR5K_TX_QUEUE_XR_DATA: An XR-data queue - * @AR5K_TX_QUEUE_BEACON: The beacon queue - * @AR5K_TX_QUEUE_CAB: The after-beacon queue - * @AR5K_TX_QUEUE_UAPSD: Unscheduled Automatic Power Save Delivery queue - */ -enum ath5k_tx_queue { - AR5K_TX_QUEUE_INACTIVE = 0, - AR5K_TX_QUEUE_DATA, - AR5K_TX_QUEUE_XR_DATA, - AR5K_TX_QUEUE_BEACON, - AR5K_TX_QUEUE_CAB, - AR5K_TX_QUEUE_UAPSD, -}; - -#define AR5K_NUM_TX_QUEUES 10 -#define AR5K_NUM_TX_QUEUES_NOQCU 2 - -/* - * Queue syb-types to classify normal data queues. - * These are the 4 Access Categories as defined in - * WME spec. 0 is the lowest priority and 4 is the - * highest. Normal data that hasn't been classified - * goes to the Best Effort AC. - */ -enum ath5k_tx_queue_subtype { - AR5K_WME_AC_BK = 0, /*Background traffic*/ - AR5K_WME_AC_BE, /*Best-effort (normal) traffic)*/ - AR5K_WME_AC_VI, /*Video traffic*/ - AR5K_WME_AC_VO, /*Voice traffic*/ -}; - -/* - * Queue ID numbers as returned by the hw functions, each number - * represents a hw queue. If hw does not support hw queues - * (eg 5210) all data goes in one queue. These match - * d80211 definitions (net80211/MadWiFi don't use them). - */ -enum ath5k_tx_queue_id { - AR5K_TX_QUEUE_ID_NOQCU_DATA = 0, - AR5K_TX_QUEUE_ID_NOQCU_BEACON = 1, - AR5K_TX_QUEUE_ID_DATA_MIN = 0, /*IEEE80211_TX_QUEUE_DATA0*/ - AR5K_TX_QUEUE_ID_DATA_MAX = 4, /*IEEE80211_TX_QUEUE_DATA4*/ - AR5K_TX_QUEUE_ID_DATA_SVP = 5, /*IEEE80211_TX_QUEUE_SVP - Spectralink Voice Protocol*/ - AR5K_TX_QUEUE_ID_CAB = 6, /*IEEE80211_TX_QUEUE_AFTER_BEACON*/ - AR5K_TX_QUEUE_ID_BEACON = 7, /*IEEE80211_TX_QUEUE_BEACON*/ - AR5K_TX_QUEUE_ID_UAPSD = 8, - AR5K_TX_QUEUE_ID_XR_DATA = 9, -}; - -/* - * Flags to set hw queue's parameters... - */ -#define AR5K_TXQ_FLAG_TXOKINT_ENABLE 0x0001 /* Enable TXOK interrupt */ -#define AR5K_TXQ_FLAG_TXERRINT_ENABLE 0x0002 /* Enable TXERR interrupt */ -#define AR5K_TXQ_FLAG_TXEOLINT_ENABLE 0x0004 /* Enable TXEOL interrupt -not used- */ -#define AR5K_TXQ_FLAG_TXDESCINT_ENABLE 0x0008 /* Enable TXDESC interrupt -not used- */ -#define AR5K_TXQ_FLAG_TXURNINT_ENABLE 0x0010 /* Enable TXURN interrupt */ -#define AR5K_TXQ_FLAG_CBRORNINT_ENABLE 0x0020 /* Enable CBRORN interrupt */ -#define AR5K_TXQ_FLAG_CBRURNINT_ENABLE 0x0040 /* Enable CBRURN interrupt */ -#define AR5K_TXQ_FLAG_QTRIGINT_ENABLE 0x0080 /* Enable QTRIG interrupt */ -#define AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE 0x0100 /* Enable TXNOFRM interrupt */ -#define AR5K_TXQ_FLAG_BACKOFF_DISABLE 0x0200 /* Disable random post-backoff */ -#define AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE 0x0300 /* Enable ready time expiry policy (?)*/ -#define AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE 0x0800 /* Enable backoff while bursting */ -#define AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS 0x1000 /* Disable backoff while bursting */ -#define AR5K_TXQ_FLAG_COMPRESSION_ENABLE 0x2000 /* Enable hw compression -not implemented-*/ - -/* - * A struct to hold tx queue's parameters - */ -struct ath5k_txq_info { - enum ath5k_tx_queue tqi_type; - enum ath5k_tx_queue_subtype tqi_subtype; - u16 tqi_flags; /* Tx queue flags (see above) */ - u32 tqi_aifs; /* Arbitrated Interframe Space */ - s32 tqi_cw_min; /* Minimum Contention Window */ - s32 tqi_cw_max; /* Maximum Contention Window */ - u32 tqi_cbr_period; /* Constant bit rate period */ - u32 tqi_cbr_overflow_limit; - u32 tqi_burst_time; - u32 tqi_ready_time; /* Time queue waits after an event */ -}; - -/* - * Transmit packet types. - * used on tx control descriptor - */ -enum ath5k_pkt_type { - AR5K_PKT_TYPE_NORMAL = 0, - AR5K_PKT_TYPE_ATIM = 1, - AR5K_PKT_TYPE_PSPOLL = 2, - AR5K_PKT_TYPE_BEACON = 3, - AR5K_PKT_TYPE_PROBE_RESP = 4, - AR5K_PKT_TYPE_PIFS = 5, -}; - -/* - * TX power and TPC settings - */ -#define AR5K_TXPOWER_OFDM(_r, _v) ( \ - ((0 & 1) << ((_v) + 6)) | \ - (((ah->ah_txpower.txp_rates_power_table[(_r)]) & 0x3f) << (_v)) \ -) - -#define AR5K_TXPOWER_CCK(_r, _v) ( \ - (ah->ah_txpower.txp_rates_power_table[(_r)] & 0x3f) << (_v) \ -) - -/* - * DMA size definitions (2^n+2) - */ -enum ath5k_dmasize { - AR5K_DMASIZE_4B = 0, - AR5K_DMASIZE_8B, - AR5K_DMASIZE_16B, - AR5K_DMASIZE_32B, - AR5K_DMASIZE_64B, - AR5K_DMASIZE_128B, - AR5K_DMASIZE_256B, - AR5K_DMASIZE_512B -}; - - -/****************\ - RX DEFINITIONS -\****************/ - -/* - * RX Status descriptor - */ -struct ath5k_rx_status { - u16 rs_datalen; - u16 rs_tstamp; - u8 rs_status; - u8 rs_phyerr; - s8 rs_rssi; - u8 rs_keyix; - u8 rs_rate; - u8 rs_antenna; - u8 rs_more; -}; - -#define AR5K_RXERR_CRC 0x01 -#define AR5K_RXERR_PHY 0x02 -#define AR5K_RXERR_FIFO 0x04 -#define AR5K_RXERR_DECRYPT 0x08 -#define AR5K_RXERR_MIC 0x10 -#define AR5K_RXKEYIX_INVALID ((u8) - 1) -#define AR5K_TXKEYIX_INVALID ((u32) - 1) - - -/**************************\ - BEACON TIMERS DEFINITIONS -\**************************/ - -#define AR5K_BEACON_PERIOD 0x0000ffff -#define AR5K_BEACON_ENA 0x00800000 /*enable beacon xmit*/ -#define AR5K_BEACON_RESET_TSF 0x01000000 /*force a TSF reset*/ - -#if 0 -/** - * struct ath5k_beacon_state - Per-station beacon timer state. - * @bs_interval: in TU's, can also include the above flags - * @bs_cfp_max_duration: if non-zero hw is setup to coexist with a - * Point Coordination Function capable AP - */ -struct ath5k_beacon_state { - u32 bs_next_beacon; - u32 bs_next_dtim; - u32 bs_interval; - u8 bs_dtim_period; - u8 bs_cfp_period; - u16 bs_cfp_max_duration; - u16 bs_cfp_du_remain; - u16 bs_tim_offset; - u16 bs_sleep_duration; - u16 bs_bmiss_threshold; - u32 bs_cfp_next; -}; -#endif - - -/* - * TSF to TU conversion: - * - * TSF is a 64bit value in usec (microseconds). - * TU is a 32bit value and defined by IEEE802.11 (page 6) as "A measurement of - * time equal to 1024 usec", so it's roughly milliseconds (usec / 1024). - */ -#define TSF_TO_TU(_tsf) (u32)((_tsf) >> 10) - - -/*******************************\ - GAIN OPTIMIZATION DEFINITIONS -\*******************************/ - -enum ath5k_rfgain { - AR5K_RFGAIN_INACTIVE = 0, - AR5K_RFGAIN_ACTIVE, - AR5K_RFGAIN_READ_REQUESTED, - AR5K_RFGAIN_NEED_CHANGE, -}; - -struct ath5k_gain { - u8 g_step_idx; - u8 g_current; - u8 g_target; - u8 g_low; - u8 g_high; - u8 g_f_corr; - u8 g_state; -}; - -/********************\ - COMMON DEFINITIONS -\********************/ - -#define AR5K_SLOT_TIME_9 396 -#define AR5K_SLOT_TIME_20 880 -#define AR5K_SLOT_TIME_MAX 0xffff - -/* channel_flags */ -#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */ -#define CHANNEL_TURBO 0x0010 /* Turbo Channel */ -#define CHANNEL_CCK 0x0020 /* CCK channel */ -#define CHANNEL_OFDM 0x0040 /* OFDM channel */ -#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */ -#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */ -#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */ -#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */ -#define CHANNEL_XR 0x0800 /* XR channel */ - -#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) -#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) -#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) -#define CHANNEL_T (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_TG (CHANNEL_2GHZ|CHANNEL_OFDM|CHANNEL_TURBO) -#define CHANNEL_108A CHANNEL_T -#define CHANNEL_108G CHANNEL_TG -#define CHANNEL_X (CHANNEL_5GHZ|CHANNEL_OFDM|CHANNEL_XR) - -#define CHANNEL_ALL (CHANNEL_OFDM|CHANNEL_CCK|CHANNEL_2GHZ|CHANNEL_5GHZ| \ - CHANNEL_TURBO) - -#define CHANNEL_ALL_NOTURBO (CHANNEL_ALL & ~CHANNEL_TURBO) -#define CHANNEL_MODES CHANNEL_ALL - -/* - * Used internaly for reset_tx_queue). - * Also see struct struct ieee80211_channel. - */ -#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0) -#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0) - -/* - * The following structure is used to map 2GHz channels to - * 5GHz Atheros channels. - * TODO: Clean up - */ -struct ath5k_athchan_2ghz { - u32 a2_flags; - u16 a2_athchan; -}; - - -/******************\ - RATE DEFINITIONS -\******************/ - -/** - * Seems the ar5xxx harware supports up to 32 rates, indexed by 1-32. - * - * The rate code is used to get the RX rate or set the TX rate on the - * hardware descriptors. It is also used for internal modulation control - * and settings. - * - * This is the hardware rate map we are aware of: - * - * rate_code 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 - * rate_kbps 3000 1000 ? ? ? 2000 500 48000 - * - * rate_code 0x09 0x0A 0x0B 0x0C 0x0D 0x0E 0x0F 0x10 - * rate_kbps 24000 12000 6000 54000 36000 18000 9000 ? - * - * rate_code 17 18 19 20 21 22 23 24 - * rate_kbps ? ? ? ? ? ? ? 11000 - * - * rate_code 25 26 27 28 29 30 31 32 - * rate_kbps 5500 2000 1000 11000S 5500S 2000S ? ? - * - * "S" indicates CCK rates with short preamble. - * - * AR5211 has different rate codes for CCK (802.11B) rates. It only uses the - * lowest 4 bits, so they are the same as below with a 0xF mask. - * (0xB, 0xA, 0x9 and 0x8 for 1M, 2M, 5.5M and 11M). - * We handle this in ath5k_setup_bands(). - */ -#define AR5K_MAX_RATES 32 - -/* B */ -#define ATH5K_RATE_CODE_1M 0x1B -#define ATH5K_RATE_CODE_2M 0x1A -#define ATH5K_RATE_CODE_5_5M 0x19 -#define ATH5K_RATE_CODE_11M 0x18 -/* A and G */ -#define ATH5K_RATE_CODE_6M 0x0B -#define ATH5K_RATE_CODE_9M 0x0F -#define ATH5K_RATE_CODE_12M 0x0A -#define ATH5K_RATE_CODE_18M 0x0E -#define ATH5K_RATE_CODE_24M 0x09 -#define ATH5K_RATE_CODE_36M 0x0D -#define ATH5K_RATE_CODE_48M 0x08 -#define ATH5K_RATE_CODE_54M 0x0C -/* XR */ -#define ATH5K_RATE_CODE_XR_500K 0x07 -#define ATH5K_RATE_CODE_XR_1M 0x02 -#define ATH5K_RATE_CODE_XR_2M 0x06 -#define ATH5K_RATE_CODE_XR_3M 0x01 - -/* adding this flag to rate_code enables short preamble */ -#define AR5K_SET_SHORT_PREAMBLE 0x04 - -/* - * Crypto definitions - */ - -#define AR5K_KEYCACHE_SIZE 8 - -/***********************\ - HW RELATED DEFINITIONS -\***********************/ - -/* - * Misc definitions - */ -#define AR5K_RSSI_EP_MULTIPLIER (1<<7) - -#define AR5K_ASSERT_ENTRY(_e, _s) do { \ - if (_e >= _s) \ - return (false); \ -} while (0) - -/* - * Hardware interrupt abstraction - */ - -/** - * enum ath5k_int - Hardware interrupt masks helpers - * - * @AR5K_INT_RX: mask to identify received frame interrupts, of type - * AR5K_ISR_RXOK or AR5K_ISR_RXERR - * @AR5K_INT_RXDESC: Request RX descriptor/Read RX descriptor (?) - * @AR5K_INT_RXNOFRM: No frame received (?) - * @AR5K_INT_RXEOL: received End Of List for VEOL (Virtual End Of List). The - * Queue Control Unit (QCU) signals an EOL interrupt only if a descriptor's - * LinkPtr is NULL. For more details, refer to: - * http://www.freepatentsonline.com/20030225739.html - * @AR5K_INT_RXORN: Indicates we got RX overrun (eg. no more descriptors). - * Note that Rx overrun is not always fatal, on some chips we can continue - * operation without reseting the card, that's why int_fatal is not - * common for all chips. - * @AR5K_INT_TX: mask to identify received frame interrupts, of type - * AR5K_ISR_TXOK or AR5K_ISR_TXERR - * @AR5K_INT_TXDESC: Request TX descriptor/Read TX status descriptor (?) - * @AR5K_INT_TXURN: received when we should increase the TX trigger threshold - * We currently do increments on interrupt by - * (AR5K_TUNE_MAX_TX_FIFO_THRES - current_trigger_level) / 2 - * @AR5K_INT_MIB: Indicates the Management Information Base counters should be - * checked. We should do this with ath5k_hw_update_mib_counters() but - * it seems we should also then do some noise immunity work. - * @AR5K_INT_RXPHY: RX PHY Error - * @AR5K_INT_RXKCM: RX Key cache miss - * @AR5K_INT_SWBA: SoftWare Beacon Alert - indicates its time to send a - * beacon that must be handled in software. The alternative is if you - * have VEOL support, in that case you let the hardware deal with things. - * @AR5K_INT_BMISS: If in STA mode this indicates we have stopped seeing - * beacons from the AP have associated with, we should probably try to - * reassociate. When in IBSS mode this might mean we have not received - * any beacons from any local stations. Note that every station in an - * IBSS schedules to send beacons at the Target Beacon Transmission Time - * (TBTT) with a random backoff. - * @AR5K_INT_BNR: Beacon Not Ready interrupt - ?? - * @AR5K_INT_GPIO: GPIO interrupt is used for RF Kill, disabled for now - * until properly handled - * @AR5K_INT_FATAL: Fatal errors were encountered, typically caused by DMA - * errors. These types of errors we can enable seem to be of type - * AR5K_SIMR2_MCABT, AR5K_SIMR2_SSERR and AR5K_SIMR2_DPERR. - * @AR5K_INT_GLOBAL: Used to clear and set the IER - * @AR5K_INT_NOCARD: signals the card has been removed - * @AR5K_INT_COMMON: common interrupts shared amogst MACs with the same - * bit value - * - * These are mapped to take advantage of some common bits - * between the MACs, to be able to set intr properties - * easier. Some of them are not used yet inside hw.c. Most map - * to the respective hw interrupt value as they are common amogst different - * MACs. - */ -enum ath5k_int { - AR5K_INT_RXOK = 0x00000001, - AR5K_INT_RXDESC = 0x00000002, - AR5K_INT_RXERR = 0x00000004, - AR5K_INT_RXNOFRM = 0x00000008, - AR5K_INT_RXEOL = 0x00000010, - AR5K_INT_RXORN = 0x00000020, - AR5K_INT_TXOK = 0x00000040, - AR5K_INT_TXDESC = 0x00000080, - AR5K_INT_TXERR = 0x00000100, - AR5K_INT_TXNOFRM = 0x00000200, - AR5K_INT_TXEOL = 0x00000400, - AR5K_INT_TXURN = 0x00000800, - AR5K_INT_MIB = 0x00001000, - AR5K_INT_SWI = 0x00002000, - AR5K_INT_RXPHY = 0x00004000, - AR5K_INT_RXKCM = 0x00008000, - AR5K_INT_SWBA = 0x00010000, - AR5K_INT_BRSSI = 0x00020000, - AR5K_INT_BMISS = 0x00040000, - AR5K_INT_FATAL = 0x00080000, /* Non common */ - AR5K_INT_BNR = 0x00100000, /* Non common */ - AR5K_INT_TIM = 0x00200000, /* Non common */ - AR5K_INT_DTIM = 0x00400000, /* Non common */ - AR5K_INT_DTIM_SYNC = 0x00800000, /* Non common */ - AR5K_INT_GPIO = 0x01000000, - AR5K_INT_BCN_TIMEOUT = 0x02000000, /* Non common */ - AR5K_INT_CAB_TIMEOUT = 0x04000000, /* Non common */ - AR5K_INT_RX_DOPPLER = 0x08000000, /* Non common */ - AR5K_INT_QCBRORN = 0x10000000, /* Non common */ - AR5K_INT_QCBRURN = 0x20000000, /* Non common */ - AR5K_INT_QTRIG = 0x40000000, /* Non common */ - AR5K_INT_GLOBAL = 0x80000000, - - AR5K_INT_COMMON = AR5K_INT_RXOK - | AR5K_INT_RXDESC - | AR5K_INT_RXERR - | AR5K_INT_RXNOFRM - | AR5K_INT_RXEOL - | AR5K_INT_RXORN - | AR5K_INT_TXOK - | AR5K_INT_TXDESC - | AR5K_INT_TXERR - | AR5K_INT_TXNOFRM - | AR5K_INT_TXEOL - | AR5K_INT_TXURN - | AR5K_INT_MIB - | AR5K_INT_SWI - | AR5K_INT_RXPHY - | AR5K_INT_RXKCM - | AR5K_INT_SWBA - | AR5K_INT_BRSSI - | AR5K_INT_BMISS - | AR5K_INT_GPIO - | AR5K_INT_GLOBAL, - - AR5K_INT_NOCARD = 0xffffffff -}; - -/* Software interrupts used for calibration */ -enum ath5k_software_interrupt { - AR5K_SWI_FULL_CALIBRATION = 0x01, - AR5K_SWI_SHORT_CALIBRATION = 0x02, -}; - -/* - * Power management - */ -enum ath5k_power_mode { - AR5K_PM_UNDEFINED = 0, - AR5K_PM_AUTO, - AR5K_PM_AWAKE, - AR5K_PM_FULL_SLEEP, - AR5K_PM_NETWORK_SLEEP, -}; - -/* - * These match net80211 definitions (not used in - * mac80211). - * TODO: Clean this up - */ -#define AR5K_LED_INIT 0 /*IEEE80211_S_INIT*/ -#define AR5K_LED_SCAN 1 /*IEEE80211_S_SCAN*/ -#define AR5K_LED_AUTH 2 /*IEEE80211_S_AUTH*/ -#define AR5K_LED_ASSOC 3 /*IEEE80211_S_ASSOC*/ -#define AR5K_LED_RUN 4 /*IEEE80211_S_RUN*/ - -/* GPIO-controlled software LED */ -#define AR5K_SOFTLED_PIN 0 -#define AR5K_SOFTLED_ON 0 -#define AR5K_SOFTLED_OFF 1 - -/* - * Chipset capabilities -see ath5k_hw_get_capability- - * get_capability function is not yet fully implemented - * in ath5k so most of these don't work yet... - * TODO: Implement these & merge with _TUNE_ stuff above - */ -enum ath5k_capability_type { - AR5K_CAP_REG_DMN = 0, /* Used to get current reg. domain id */ - AR5K_CAP_TKIP_MIC = 2, /* Can handle TKIP MIC in hardware */ - AR5K_CAP_TKIP_SPLIT = 3, /* TKIP uses split keys */ - AR5K_CAP_PHYCOUNTERS = 4, /* PHY error counters */ - AR5K_CAP_DIVERSITY = 5, /* Supports fast diversity */ - AR5K_CAP_NUM_TXQUEUES = 6, /* Used to get max number of hw txqueues */ - AR5K_CAP_VEOL = 7, /* Supports virtual EOL */ - AR5K_CAP_COMPRESSION = 8, /* Supports compression */ - AR5K_CAP_BURST = 9, /* Supports packet bursting */ - AR5K_CAP_FASTFRAME = 10, /* Supports fast frames */ - AR5K_CAP_TXPOW = 11, /* Used to get global tx power limit */ - AR5K_CAP_TPC = 12, /* Can do per-packet tx power control (needed for 802.11a) */ - AR5K_CAP_BSSIDMASK = 13, /* Supports bssid mask */ - AR5K_CAP_MCAST_KEYSRCH = 14, /* Supports multicast key search */ - AR5K_CAP_TSF_ADJUST = 15, /* Supports beacon tsf adjust */ - AR5K_CAP_XR = 16, /* Supports XR mode */ - AR5K_CAP_WME_TKIPMIC = 17, /* Supports TKIP MIC when using WMM */ - AR5K_CAP_CHAN_HALFRATE = 18, /* Supports half rate channels */ - AR5K_CAP_CHAN_QUARTERRATE = 19, /* Supports quarter rate channels */ - AR5K_CAP_RFSILENT = 20, /* Supports RFsilent */ -}; - - -/* XXX: we *may* move cap_range stuff to struct wiphy */ -struct ath5k_capabilities { - /* - * Supported PHY modes - * (ie. CHANNEL_A, CHANNEL_B, ...) - */ - DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX); - - /* - * Frequency range (without regulation restrictions) - */ - struct { - u16 range_2ghz_min; - u16 range_2ghz_max; - u16 range_5ghz_min; - u16 range_5ghz_max; - } cap_range; - - /* - * Values stored in the EEPROM (some of them...) - */ - struct ath5k_eeprom_info cap_eeprom; - - /* - * Queue information - */ - struct { - u8 q_tx_num; - } cap_queues; -}; - - -/***************************************\ - HARDWARE ABSTRACTION LAYER STRUCTURE -\***************************************/ - -/* - * Misc defines - */ - -#define AR5K_MAX_GPIO 10 -#define AR5K_MAX_RF_BANKS 8 - -/* TODO: Clean up and merge with ath5k_softc */ -struct ath5k_hw { - u32 ah_magic; - - struct ath5k_softc *ah_sc; - void __iomem *ah_iobase; - - enum ath5k_int ah_imr; - - enum nl80211_iftype ah_op_mode; - struct ieee80211_channel *ah_current_channel; - bool ah_turbo; - bool ah_calibration; - bool ah_single_chip; - bool ah_aes_support; - bool ah_combined_mic; - - enum ath5k_version ah_version; - enum ath5k_radio ah_radio; - u32 ah_phy; - u32 ah_mac_srev; - u16 ah_mac_version; - u16 ah_mac_revision; - u16 ah_phy_revision; - u16 ah_radio_5ghz_revision; - u16 ah_radio_2ghz_revision; - -#define ah_modes ah_capabilities.cap_mode -#define ah_ee_version ah_capabilities.cap_eeprom.ee_version - - u32 ah_atim_window; - u32 ah_aifs; - u32 ah_cw_min; - u32 ah_cw_max; - u32 ah_limit_tx_retries; - - /* Antenna Control */ - u32 ah_ant_ctl[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; - u8 ah_ant_mode; - u8 ah_tx_ant; - u8 ah_def_ant; - bool ah_software_retry; - - u8 ah_sta_id[ETH_ALEN]; - - /* Current BSSID we are trying to assoc to / create. - * This is passed by mac80211 on config_interface() and cached here for - * use in resets */ - u8 ah_bssid[ETH_ALEN]; - u8 ah_bssid_mask[ETH_ALEN]; - - int ah_gpio_npins; - - struct ath5k_capabilities ah_capabilities; - - struct ath5k_txq_info ah_txq[AR5K_NUM_TX_QUEUES]; - u32 ah_txq_status; - u32 ah_txq_imr_txok; - u32 ah_txq_imr_txerr; - u32 ah_txq_imr_txurn; - u32 ah_txq_imr_txdesc; - u32 ah_txq_imr_txeol; - u32 ah_txq_imr_cbrorn; - u32 ah_txq_imr_cbrurn; - u32 ah_txq_imr_qtrig; - u32 ah_txq_imr_nofrm; - u32 ah_txq_isr; - u32 *ah_rf_banks; - size_t ah_rf_banks_size; - size_t ah_rf_regs_count; - struct ath5k_gain ah_gain; - u8 ah_offset[AR5K_MAX_RF_BANKS]; - - - struct { - /* Temporary tables used for interpolation */ - u8 tmpL[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_POWER_TABLE_SIZE]; - u8 tmpR[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_POWER_TABLE_SIZE]; - u8 txp_pd_table[AR5K_EEPROM_POWER_TABLE_SIZE * 2]; - u16 txp_rates_power_table[AR5K_MAX_RATES]; - u8 txp_min_idx; - bool txp_tpc; - /* Values in 0.25dB units */ - s16 txp_min_pwr; - s16 txp_max_pwr; - /* Values in 0.5dB units */ - s16 txp_offset; - s16 txp_ofdm; - s16 txp_cck_ofdm_gainf_delta; - /* Value in dB units */ - s16 txp_cck_ofdm_pwr_delta; - } ah_txpower; - - struct { - bool r_enabled; - int r_last_alert; - struct ieee80211_channel r_last_channel; - } ah_radar; - - /* noise floor from last periodic calibration */ - s32 ah_noise_floor; - - /* Calibration timestamp */ - unsigned long ah_cal_tstamp; - - /* Calibration interval (secs) */ - u8 ah_cal_intval; - - /* Software interrupt mask */ - u8 ah_swi_mask; - - /* - * Function pointers - */ - int (*ah_setup_rx_desc)(struct ath5k_hw *ah, struct ath5k_desc *desc, - u32 size, unsigned int flags); - int (*ah_setup_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - unsigned int, unsigned int, enum ath5k_pkt_type, unsigned int, - unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int, unsigned int); - int (*ah_setup_mrr_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - unsigned int, unsigned int, unsigned int, unsigned int, - unsigned int, unsigned int); - int (*ah_proc_tx_desc)(struct ath5k_hw *, struct ath5k_desc *, - struct ath5k_tx_status *); - int (*ah_proc_rx_desc)(struct ath5k_hw *, struct ath5k_desc *, - struct ath5k_rx_status *); -}; - -/* - * Prototypes - */ - -/* Attach/Detach Functions */ -extern struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc); -extern void ath5k_hw_detach(struct ath5k_hw *ah); - -/* LED functions */ -extern int ath5k_init_leds(struct ath5k_softc *sc); -extern void ath5k_led_enable(struct ath5k_softc *sc); -extern void ath5k_led_off(struct ath5k_softc *sc); -extern void ath5k_unregister_leds(struct ath5k_softc *sc); - -/* Reset Functions */ -extern int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); -extern int ath5k_hw_on_hold(struct ath5k_hw *ah); -extern int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, struct ieee80211_channel *channel, bool change_channel); -/* Power management functions */ -extern int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, bool set_chip, u16 sleep_duration); - -/* DMA Related Functions */ -extern void ath5k_hw_start_rx_dma(struct ath5k_hw *ah); -extern int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah); -extern u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah); -extern void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr); -extern int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue); -extern u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, - u32 phys_addr); -extern int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase); -/* Interrupt handling */ -extern bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah); -extern int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask); -extern enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum -ath5k_int new_mask); -extern void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, struct ieee80211_low_level_stats *stats); - -/* EEPROM access functions */ -extern int ath5k_eeprom_init(struct ath5k_hw *ah); -extern void ath5k_eeprom_detach(struct ath5k_hw *ah); -extern int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac); -extern bool ath5k_eeprom_is_hb63(struct ath5k_hw *ah); - -/* Protocol Control Unit Functions */ -extern int ath5k_hw_set_opmode(struct ath5k_hw *ah); -/* BSSID Functions */ -extern void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac); -extern int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac); -extern void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id); -extern int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask); -/* Receive start/stop functions */ -extern void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah); -extern void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah); -/* RX Filter functions */ -extern void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1); -extern int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index); -extern int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index); -extern u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah); -extern void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter); -/* Beacon control functions */ -extern u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah); -extern u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah); -extern void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64); -extern void ath5k_hw_reset_tsf(struct ath5k_hw *ah); -extern void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval); -#if 0 -extern int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, const struct ath5k_beacon_state *state); -extern void ath5k_hw_reset_beacon(struct ath5k_hw *ah); -extern int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr); -#endif -/* ACK bit rate */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high); -/* ACK/CTS Timeouts */ -extern int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout); -extern unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah); -extern int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout); -extern unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah); -/* Key table (WEP) functions */ -extern int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry); -extern int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry); -extern int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, const struct ieee80211_key_conf *key, const u8 *mac); -extern int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac); - -/* Queue Control Unit, DFS Control Unit Functions */ -extern int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, struct ath5k_txq_info *queue_info); -extern int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, - const struct ath5k_txq_info *queue_info); -extern int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, - enum ath5k_tx_queue queue_type, - struct ath5k_txq_info *queue_info); -extern u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue); -extern void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue); -extern unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah); -extern int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time); - -/* Hardware Descriptor Functions */ -extern int ath5k_hw_init_desc_functions(struct ath5k_hw *ah); - -/* GPIO Functions */ -extern void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state); -extern int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio); -extern int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio); -extern u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio); -extern int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val); -extern void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, u32 interrupt_level); - -/* rfkill Functions */ -extern void ath5k_rfkill_hw_start(struct ath5k_hw *ah); -extern void ath5k_rfkill_hw_stop(struct ath5k_hw *ah); - -/* Misc functions */ -int ath5k_hw_set_capabilities(struct ath5k_hw *ah); -extern int ath5k_hw_get_capability(struct ath5k_hw *ah, enum ath5k_capability_type cap_type, u32 capability, u32 *result); -extern int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, u16 assoc_id); -extern int ath5k_hw_disable_pspoll(struct ath5k_hw *ah); - -/* Initial register settings functions */ -extern int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel); - -/* Initialize RF */ -extern int ath5k_hw_rfregs_init(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - unsigned int mode); -extern int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq); -extern enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); -extern int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); -/* PHY/RF channel functions */ -extern bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); -extern int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel); -/* PHY calibration */ -extern int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, struct ieee80211_channel *channel); -extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq); -extern void ath5k_hw_calibration_poll(struct ath5k_hw *ah); -/* Spur mitigation */ -bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel); -void ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, - struct ieee80211_channel *channel); -/* Misc PHY functions */ -extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); -extern int ath5k_hw_phy_disable(struct ath5k_hw *ah); -/* Antenna control */ -extern void ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode); -extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant); -extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah); -/* TX power setup */ -extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, u8 ee_mode, u8 txpower); -extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower); - -/* - * Functions used internaly - */ - -/* - * Translate usec to hw clock units - * TODO: Half/quarter rate - */ -static inline unsigned int ath5k_hw_htoclock(unsigned int usec, bool turbo) -{ - return turbo ? (usec * 80) : (usec * 40); -} - -/* - * Translate hw clock units to usec - * TODO: Half/quarter rate - */ -static inline unsigned int ath5k_hw_clocktoh(unsigned int clock, bool turbo) -{ - return turbo ? (clock / 80) : (clock / 40); -} - -/* - * Read from a register - */ -static inline u32 ath5k_hw_reg_read(struct ath5k_hw *ah, u16 reg) -{ - return ioread32(ah->ah_iobase + reg); -} - -/* - * Write to a register - */ -static inline void ath5k_hw_reg_write(struct ath5k_hw *ah, u32 val, u16 reg) -{ - iowrite32(val, ah->ah_iobase + reg); -} - -#if defined(_ATH5K_RESET) || defined(_ATH5K_PHY) -/* - * Check if a register write has been completed - */ -static int ath5k_hw_register_timeout(struct ath5k_hw *ah, u32 reg, u32 flag, - u32 val, bool is_set) -{ - int i; - u32 data; - - for (i = AR5K_TUNE_REGISTER_TIMEOUT; i > 0; i--) { - data = ath5k_hw_reg_read(ah, reg); - if (is_set && (data & flag)) - break; - else if ((data & flag) == val) - break; - udelay(15); - } - - return (i <= 0) ? -EAGAIN : 0; -} -#endif - -static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) -{ - u32 retval = 0, bit, i; - - for (i = 0; i < bits; i++) { - bit = (val >> i) & 1; - retval = (retval << 1) | bit; - } - - return retval; -} - -static inline int ath5k_pad_size(int hdrlen) -{ - return (hdrlen < 24) ? 0 : hdrlen & 3; -} - -#endif diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c deleted file mode 100644 index 88663dfe3b3d..000000000000 --- a/drivers/net/wireless/ath/ath5k/attach.c +++ /dev/null @@ -1,374 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*************************************\ -* Attach/Detach Functions and helpers * -\*************************************/ - -#include -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/** - * ath5k_hw_post - Power On Self Test helper function - * - * @ah: The &struct ath5k_hw - */ -static int ath5k_hw_post(struct ath5k_hw *ah) -{ - - static const u32 static_pattern[4] = { - 0x55555555, 0xaaaaaaaa, - 0x66666666, 0x99999999 - }; - static const u16 regs[2] = { AR5K_STA_ID0, AR5K_PHY(8) }; - int i, c; - u16 cur_reg; - u32 var_pattern; - u32 init_val; - u32 cur_val; - - for (c = 0; c < 2; c++) { - - cur_reg = regs[c]; - - /* Save previous value */ - init_val = ath5k_hw_reg_read(ah, cur_reg); - - for (i = 0; i < 256; i++) { - var_pattern = i << 16 | i; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - cur_val = ath5k_hw_reg_read(ah, cur_reg); - - if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); - return -EAGAIN; - } - - /* Found on ndiswrapper dumps */ - var_pattern = 0x0039080f; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - } - - for (i = 0; i < 4; i++) { - var_pattern = static_pattern[i]; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - cur_val = ath5k_hw_reg_read(ah, cur_reg); - - if (cur_val != var_pattern) { - ATH5K_ERR(ah->ah_sc, "POST Failed !!!\n"); - return -EAGAIN; - } - - /* Found on ndiswrapper dumps */ - var_pattern = 0x003b080f; - ath5k_hw_reg_write(ah, var_pattern, cur_reg); - } - - /* Restore previous value */ - ath5k_hw_reg_write(ah, init_val, cur_reg); - - } - - return 0; - -} - -/** - * ath5k_hw_attach - Check if hw is supported and init the needed structs - * - * @sc: The &struct ath5k_softc we got from the driver's attach function - * - * Check if the device is supported, perform a POST and initialize the needed - * structs. Returns -ENOMEM if we don't have memory for the needed structs, - * -ENODEV if the device is not supported or prints an error msg if something - * else went wrong. - */ -struct ath5k_hw *ath5k_hw_attach(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah; - struct pci_dev *pdev = sc->pdev; - struct ath5k_eeprom_info *ee; - int ret; - u32 srev; - - /*If we passed the test malloc a ath5k_hw struct*/ - ah = kzalloc(sizeof(struct ath5k_hw), GFP_KERNEL); - if (ah == NULL) { - ret = -ENOMEM; - ATH5K_ERR(sc, "out of memory\n"); - goto err; - } - - ah->ah_sc = sc; - ah->ah_iobase = sc->iobase; - - /* - * HW information - */ - ah->ah_op_mode = NL80211_IFTYPE_STATION; - ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT; - ah->ah_turbo = false; - ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; - ah->ah_imr = 0; - ah->ah_atim_window = 0; - ah->ah_aifs = AR5K_TUNE_AIFS; - ah->ah_cw_min = AR5K_TUNE_CWMIN; - ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY; - ah->ah_software_retry = false; - ah->ah_current_channel = &sc->channels[0]; - - /* - * Find the mac version - */ - srev = ath5k_hw_reg_read(ah, AR5K_SREV); - if (srev < AR5K_SREV_AR5311) - ah->ah_version = AR5K_AR5210; - else if (srev < AR5K_SREV_AR5212) - ah->ah_version = AR5K_AR5211; - else - ah->ah_version = AR5K_AR5212; - - /*Fill the ath5k_hw struct with the needed functions*/ - ret = ath5k_hw_init_desc_functions(ah); - if (ret) - goto err_free; - - /* Bring device out of sleep and reset it's units */ - ret = ath5k_hw_nic_wakeup(ah, 0, true); - if (ret) - goto err_free; - - /* Get MAC, PHY and RADIO revisions */ - ah->ah_mac_srev = srev; - ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); - ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV); - ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & - 0xffffffff; - ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_5GHZ); - ah->ah_phy = AR5K_PHY(0); - - /* Try to identify radio chip based on it's srev */ - switch (ah->ah_radio_5ghz_revision & 0xf0) { - case AR5K_SREV_RAD_5111: - ah->ah_radio = AR5K_RF5111; - ah->ah_single_chip = false; - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - break; - case AR5K_SREV_RAD_5112: - case AR5K_SREV_RAD_2112: - ah->ah_radio = AR5K_RF5112; - ah->ah_single_chip = false; - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - break; - case AR5K_SREV_RAD_2413: - ah->ah_radio = AR5K_RF2413; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_5413: - ah->ah_radio = AR5K_RF5413; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_2316: - ah->ah_radio = AR5K_RF2316; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_2317: - ah->ah_radio = AR5K_RF2317; - ah->ah_single_chip = true; - break; - case AR5K_SREV_RAD_5424: - if (ah->ah_mac_version == AR5K_SREV_AR2425 || - ah->ah_mac_version == AR5K_SREV_AR2417){ - ah->ah_radio = AR5K_RF2425; - ah->ah_single_chip = true; - } else { - ah->ah_radio = AR5K_RF5413; - ah->ah_single_chip = true; - } - break; - default: - /* Identify radio based on mac/phy srev */ - if (ah->ah_version == AR5K_AR5210) { - ah->ah_radio = AR5K_RF5110; - ah->ah_single_chip = false; - } else if (ah->ah_version == AR5K_AR5211) { - ah->ah_radio = AR5K_RF5111; - ah->ah_single_chip = false; - ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, - CHANNEL_2GHZ); - } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || - ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || - ah->ah_phy_revision == AR5K_SREV_PHY_2425) { - ah->ah_radio = AR5K_RF2425; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2425; - } else if (srev == AR5K_SREV_AR5213A && - ah->ah_phy_revision == AR5K_SREV_PHY_5212B) { - ah->ah_radio = AR5K_RF5112; - ah->ah_single_chip = false; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5112B; - } else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4)) { - ah->ah_radio = AR5K_RF2316; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316; - } else if (ah->ah_mac_version == (AR5K_SREV_AR5414 >> 4) || - ah->ah_phy_revision == AR5K_SREV_PHY_5413) { - ah->ah_radio = AR5K_RF5413; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_5413; - } else if (ah->ah_mac_version == (AR5K_SREV_AR2414 >> 4) || - ah->ah_phy_revision == AR5K_SREV_PHY_2413) { - ah->ah_radio = AR5K_RF2413; - ah->ah_single_chip = true; - ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2413; - } else { - ATH5K_ERR(sc, "Couldn't identify radio revision.\n"); - ret = -ENODEV; - goto err_free; - } - } - - - /* Return on unsuported chips (unsupported eeprom etc) */ - if ((srev >= AR5K_SREV_AR5416) && - (srev < AR5K_SREV_AR2425)) { - ATH5K_ERR(sc, "Device not yet supported.\n"); - ret = -ENODEV; - goto err_free; - } - - /* - * POST - */ - ret = ath5k_hw_post(ah); - if (ret) - goto err_free; - - /* Enable pci core retry fix on Hainan (5213A) and later chips */ - if (srev >= AR5K_SREV_AR5213A) - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_RETRY_FIX); - - /* - * Get card capabilities, calibration values etc - * TODO: EEPROM work - */ - ret = ath5k_eeprom_init(ah); - if (ret) { - ATH5K_ERR(sc, "unable to init EEPROM\n"); - goto err_free; - } - - /* - * Write PCI-E power save settings - */ - if ((ah->ah_version == AR5K_AR5212) && (pdev->is_pcie)) { - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - - ath5k_hw_reg_write(ah, 0x9248fc00, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x24924924, AR5K_PCIE_SERDES); - - /* Shut off RX when elecidle is asserted */ - ath5k_hw_reg_write(ah, 0x28000039, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x53160824, AR5K_PCIE_SERDES); - - /* If serdes programing is enabled, increase PCI-E - * tx power for systems with long trace from host - * to minicard connector. */ - if (ee->ee_serdes) - ath5k_hw_reg_write(ah, 0xe5980579, AR5K_PCIE_SERDES); - else - ath5k_hw_reg_write(ah, 0xf6800579, AR5K_PCIE_SERDES); - - /* Shut off PLL and CLKREQ active in L1 */ - ath5k_hw_reg_write(ah, 0x001defff, AR5K_PCIE_SERDES); - - /* Preserve other settings */ - ath5k_hw_reg_write(ah, 0x1aaabe40, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0xbe105554, AR5K_PCIE_SERDES); - ath5k_hw_reg_write(ah, 0x000e3007, AR5K_PCIE_SERDES); - - /* Reset SERDES to load new settings */ - ath5k_hw_reg_write(ah, 0x00000000, AR5K_PCIE_SERDES_RESET); - mdelay(1); - } - - /* Get misc capabilities */ - ret = ath5k_hw_set_capabilities(ah); - if (ret) { - ATH5K_ERR(sc, "unable to get device capabilities: 0x%04x\n", - sc->pdev->device); - goto err_free; - } - - /* Crypto settings */ - ee = &ah->ah_capabilities.cap_eeprom; - ah->ah_aes_support = srev >= AR5K_SREV_AR5212_V4 && - (ee->ee_version >= AR5K_EEPROM_VERSION_5_0 && - !AR5K_EEPROM_AES_DIS(ee->ee_misc5)); - - if (srev >= AR5K_SREV_AR2414) { - ah->ah_combined_mic = true; - AR5K_REG_ENABLE_BITS(ah, AR5K_MISC_MODE, - AR5K_MISC_MODE_COMBINED_MIC); - } - - /* MAC address is cleared until add_interface */ - ath5k_hw_set_lladdr(ah, (u8[ETH_ALEN]){}); - - /* Set BSSID to bcast address: ff:ff:ff:ff:ff:ff for now */ - memset(ah->ah_bssid, 0xff, ETH_ALEN); - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - ath5k_hw_set_opmode(ah); - - ath5k_hw_rfgain_opt_init(ah); - - /* turn on HW LEDs */ - ath5k_hw_set_ledstate(ah, AR5K_LED_INIT); - - return ah; -err_free: - kfree(ah); -err: - return ERR_PTR(ret); -} - -/** - * ath5k_hw_detach - Free the ath5k_hw struct - * - * @ah: The &struct ath5k_hw - */ -void ath5k_hw_detach(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - __set_bit(ATH_STAT_INVALID, ah->ah_sc->status); - - if (ah->ah_rf_banks != NULL) - kfree(ah->ah_rf_banks); - - ath5k_eeprom_detach(ah); - - /* assume interrupts are down */ - kfree(ah); -} diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c deleted file mode 100644 index 2c4914a52789..000000000000 --- a/drivers/net/wireless/ath/ath5k/base.c +++ /dev/null @@ -1,3297 +0,0 @@ -/*- - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2006 Devicescape Software, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2007 Luis R. Rodriguez - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#include "base.h" -#include "reg.h" -#include "debug.h" - -static u8 ath5k_calinterval = 10; /* Calibrate PHY every 10 secs (TODO: Fixme) */ -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -static int modparam_all_channels; -module_param_named(all_channels, modparam_all_channels, bool, S_IRUGO); -MODULE_PARM_DESC(all_channels, "Expose all channels the device can use."); - - -/******************\ -* Internal defines * -\******************/ - -/* Module info */ -MODULE_AUTHOR("Jiri Slaby"); -MODULE_AUTHOR("Nick Kossifidis"); -MODULE_DESCRIPTION("Support for 5xxx series of Atheros 802.11 wireless LAN cards."); -MODULE_SUPPORTED_DEVICE("Atheros 5xxx WLAN cards"); -MODULE_LICENSE("Dual BSD/GPL"); -MODULE_VERSION("0.6.0 (EXPERIMENTAL)"); - - -/* Known PCI ids */ -static const struct pci_device_id ath5k_pci_id_table[] = { - { PCI_VDEVICE(ATHEROS, 0x0207) }, /* 5210 early */ - { PCI_VDEVICE(ATHEROS, 0x0007) }, /* 5210 */ - { PCI_VDEVICE(ATHEROS, 0x0011) }, /* 5311 - this is on AHB bus !*/ - { PCI_VDEVICE(ATHEROS, 0x0012) }, /* 5211 */ - { PCI_VDEVICE(ATHEROS, 0x0013) }, /* 5212 */ - { PCI_VDEVICE(3COM_2, 0x0013) }, /* 3com 5212 */ - { PCI_VDEVICE(3COM, 0x0013) }, /* 3com 3CRDAG675 5212 */ - { PCI_VDEVICE(ATHEROS, 0x1014) }, /* IBM minipci 5212 */ - { PCI_VDEVICE(ATHEROS, 0x0014) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0015) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0016) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0017) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0018) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x0019) }, /* 5212 combatible */ - { PCI_VDEVICE(ATHEROS, 0x001a) }, /* 2413 Griffin-lite */ - { PCI_VDEVICE(ATHEROS, 0x001b) }, /* 5413 Eagle */ - { PCI_VDEVICE(ATHEROS, 0x001c) }, /* PCI-E cards */ - { PCI_VDEVICE(ATHEROS, 0x001d) }, /* 2417 Nala */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, ath5k_pci_id_table); - -/* Known SREVs */ -static const struct ath5k_srev_name srev_names[] = { - { "5210", AR5K_VERSION_MAC, AR5K_SREV_AR5210 }, - { "5311", AR5K_VERSION_MAC, AR5K_SREV_AR5311 }, - { "5311A", AR5K_VERSION_MAC, AR5K_SREV_AR5311A }, - { "5311B", AR5K_VERSION_MAC, AR5K_SREV_AR5311B }, - { "5211", AR5K_VERSION_MAC, AR5K_SREV_AR5211 }, - { "5212", AR5K_VERSION_MAC, AR5K_SREV_AR5212 }, - { "5213", AR5K_VERSION_MAC, AR5K_SREV_AR5213 }, - { "5213A", AR5K_VERSION_MAC, AR5K_SREV_AR5213A }, - { "2413", AR5K_VERSION_MAC, AR5K_SREV_AR2413 }, - { "2414", AR5K_VERSION_MAC, AR5K_SREV_AR2414 }, - { "5424", AR5K_VERSION_MAC, AR5K_SREV_AR5424 }, - { "5413", AR5K_VERSION_MAC, AR5K_SREV_AR5413 }, - { "5414", AR5K_VERSION_MAC, AR5K_SREV_AR5414 }, - { "2415", AR5K_VERSION_MAC, AR5K_SREV_AR2415 }, - { "5416", AR5K_VERSION_MAC, AR5K_SREV_AR5416 }, - { "5418", AR5K_VERSION_MAC, AR5K_SREV_AR5418 }, - { "2425", AR5K_VERSION_MAC, AR5K_SREV_AR2425 }, - { "2417", AR5K_VERSION_MAC, AR5K_SREV_AR2417 }, - { "xxxxx", AR5K_VERSION_MAC, AR5K_SREV_UNKNOWN }, - { "5110", AR5K_VERSION_RAD, AR5K_SREV_RAD_5110 }, - { "5111", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111 }, - { "5111A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5111A }, - { "2111", AR5K_VERSION_RAD, AR5K_SREV_RAD_2111 }, - { "5112", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112 }, - { "5112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112A }, - { "5112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_5112B }, - { "2112", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112 }, - { "2112A", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112A }, - { "2112B", AR5K_VERSION_RAD, AR5K_SREV_RAD_2112B }, - { "2413", AR5K_VERSION_RAD, AR5K_SREV_RAD_2413 }, - { "5413", AR5K_VERSION_RAD, AR5K_SREV_RAD_5413 }, - { "2316", AR5K_VERSION_RAD, AR5K_SREV_RAD_2316 }, - { "2317", AR5K_VERSION_RAD, AR5K_SREV_RAD_2317 }, - { "5424", AR5K_VERSION_RAD, AR5K_SREV_RAD_5424 }, - { "5133", AR5K_VERSION_RAD, AR5K_SREV_RAD_5133 }, - { "xxxxx", AR5K_VERSION_RAD, AR5K_SREV_UNKNOWN }, -}; - -static const struct ieee80211_rate ath5k_rates[] = { - { .bitrate = 10, - .hw_value = ATH5K_RATE_CODE_1M, }, - { .bitrate = 20, - .hw_value = ATH5K_RATE_CODE_2M, - .hw_value_short = ATH5K_RATE_CODE_2M | AR5K_SET_SHORT_PREAMBLE, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, - .hw_value = ATH5K_RATE_CODE_5_5M, - .hw_value_short = ATH5K_RATE_CODE_5_5M | AR5K_SET_SHORT_PREAMBLE, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, - .hw_value = ATH5K_RATE_CODE_11M, - .hw_value_short = ATH5K_RATE_CODE_11M | AR5K_SET_SHORT_PREAMBLE, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, - .hw_value = ATH5K_RATE_CODE_6M, - .flags = 0 }, - { .bitrate = 90, - .hw_value = ATH5K_RATE_CODE_9M, - .flags = 0 }, - { .bitrate = 120, - .hw_value = ATH5K_RATE_CODE_12M, - .flags = 0 }, - { .bitrate = 180, - .hw_value = ATH5K_RATE_CODE_18M, - .flags = 0 }, - { .bitrate = 240, - .hw_value = ATH5K_RATE_CODE_24M, - .flags = 0 }, - { .bitrate = 360, - .hw_value = ATH5K_RATE_CODE_36M, - .flags = 0 }, - { .bitrate = 480, - .hw_value = ATH5K_RATE_CODE_48M, - .flags = 0 }, - { .bitrate = 540, - .hw_value = ATH5K_RATE_CODE_54M, - .flags = 0 }, - /* XR missing */ -}; - -/* - * Prototypes - PCI stack related functions - */ -static int __devinit ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id); -static void __devexit ath5k_pci_remove(struct pci_dev *pdev); -#ifdef CONFIG_PM -static int ath5k_pci_suspend(struct pci_dev *pdev, - pm_message_t state); -static int ath5k_pci_resume(struct pci_dev *pdev); -#else -#define ath5k_pci_suspend NULL -#define ath5k_pci_resume NULL -#endif /* CONFIG_PM */ - -static struct pci_driver ath5k_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = ath5k_pci_id_table, - .probe = ath5k_pci_probe, - .remove = __devexit_p(ath5k_pci_remove), - .suspend = ath5k_pci_suspend, - .resume = ath5k_pci_resume, -}; - - - -/* - * Prototypes - MAC 802.11 stack related functions - */ -static int ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath5k_txq *txq); -static int ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan); -static int ath5k_reset_wake(struct ath5k_softc *sc); -static int ath5k_start(struct ieee80211_hw *hw); -static void ath5k_stop(struct ieee80211_hw *hw); -static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -static void ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -static int ath5k_config(struct ieee80211_hw *hw, u32 changed); -static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mc_list); -static void ath5k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast); -static int ath5k_set_key(struct ieee80211_hw *hw, - enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -static int ath5k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats); -static int ath5k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); -static u64 ath5k_get_tsf(struct ieee80211_hw *hw); -static void ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf); -static void ath5k_reset_tsf(struct ieee80211_hw *hw); -static int ath5k_beacon_update(struct ieee80211_hw *hw, - struct ieee80211_vif *vif); -static void ath5k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes); -static void ath5k_sw_scan_start(struct ieee80211_hw *hw); -static void ath5k_sw_scan_complete(struct ieee80211_hw *hw); - -static const struct ieee80211_ops ath5k_hw_ops = { - .tx = ath5k_tx, - .start = ath5k_start, - .stop = ath5k_stop, - .add_interface = ath5k_add_interface, - .remove_interface = ath5k_remove_interface, - .config = ath5k_config, - .prepare_multicast = ath5k_prepare_multicast, - .configure_filter = ath5k_configure_filter, - .set_key = ath5k_set_key, - .get_stats = ath5k_get_stats, - .conf_tx = NULL, - .get_tx_stats = ath5k_get_tx_stats, - .get_tsf = ath5k_get_tsf, - .set_tsf = ath5k_set_tsf, - .reset_tsf = ath5k_reset_tsf, - .bss_info_changed = ath5k_bss_info_changed, - .sw_scan_start = ath5k_sw_scan_start, - .sw_scan_complete = ath5k_sw_scan_complete, -}; - -/* - * Prototypes - Internal functions - */ -/* Attach detach */ -static int ath5k_attach(struct pci_dev *pdev, - struct ieee80211_hw *hw); -static void ath5k_detach(struct pci_dev *pdev, - struct ieee80211_hw *hw); -/* Channel/mode setup */ -static inline short ath5k_ieee2mhz(short chan); -static unsigned int ath5k_copy_channels(struct ath5k_hw *ah, - struct ieee80211_channel *channels, - unsigned int mode, - unsigned int max); -static int ath5k_setup_bands(struct ieee80211_hw *hw); -static int ath5k_chan_set(struct ath5k_softc *sc, - struct ieee80211_channel *chan); -static void ath5k_setcurmode(struct ath5k_softc *sc, - unsigned int mode); -static void ath5k_mode_setup(struct ath5k_softc *sc); - -/* Descriptor setup */ -static int ath5k_desc_alloc(struct ath5k_softc *sc, - struct pci_dev *pdev); -static void ath5k_desc_free(struct ath5k_softc *sc, - struct pci_dev *pdev); -/* Buffers setup */ -static int ath5k_rxbuf_setup(struct ath5k_softc *sc, - struct ath5k_buf *bf); -static int ath5k_txbuf_setup(struct ath5k_softc *sc, - struct ath5k_buf *bf, - struct ath5k_txq *txq); -static inline void ath5k_txbuf_free(struct ath5k_softc *sc, - struct ath5k_buf *bf) -{ - BUG_ON(!bf); - if (!bf->skb) - return; - pci_unmap_single(sc->pdev, bf->skbaddr, bf->skb->len, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(bf->skb); - bf->skb = NULL; -} - -static inline void ath5k_rxbuf_free(struct ath5k_softc *sc, - struct ath5k_buf *bf) -{ - BUG_ON(!bf); - if (!bf->skb) - return; - pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(bf->skb); - bf->skb = NULL; -} - - -/* Queues setup */ -static struct ath5k_txq *ath5k_txq_setup(struct ath5k_softc *sc, - int qtype, int subtype); -static int ath5k_beaconq_setup(struct ath5k_hw *ah); -static int ath5k_beaconq_config(struct ath5k_softc *sc); -static void ath5k_txq_drainq(struct ath5k_softc *sc, - struct ath5k_txq *txq); -static void ath5k_txq_cleanup(struct ath5k_softc *sc); -static void ath5k_txq_release(struct ath5k_softc *sc); -/* Rx handling */ -static int ath5k_rx_start(struct ath5k_softc *sc); -static void ath5k_rx_stop(struct ath5k_softc *sc); -static unsigned int ath5k_rx_decrypted(struct ath5k_softc *sc, - struct ath5k_desc *ds, - struct sk_buff *skb, - struct ath5k_rx_status *rs); -static void ath5k_tasklet_rx(unsigned long data); -/* Tx handling */ -static void ath5k_tx_processq(struct ath5k_softc *sc, - struct ath5k_txq *txq); -static void ath5k_tasklet_tx(unsigned long data); -/* Beacon handling */ -static int ath5k_beacon_setup(struct ath5k_softc *sc, - struct ath5k_buf *bf); -static void ath5k_beacon_send(struct ath5k_softc *sc); -static void ath5k_beacon_config(struct ath5k_softc *sc); -static void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf); -static void ath5k_tasklet_beacon(unsigned long data); - -static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp) -{ - u64 tsf = ath5k_hw_get_tsf64(ah); - - if ((tsf & 0x7fff) < rstamp) - tsf -= 0x8000; - - return (tsf & ~0x7fff) | rstamp; -} - -/* Interrupt handling */ -static int ath5k_init(struct ath5k_softc *sc); -static int ath5k_stop_locked(struct ath5k_softc *sc); -static int ath5k_stop_hw(struct ath5k_softc *sc); -static irqreturn_t ath5k_intr(int irq, void *dev_id); -static void ath5k_tasklet_reset(unsigned long data); - -static void ath5k_tasklet_calibrate(unsigned long data); - -/* - * Module init/exit functions - */ -static int __init -init_ath5k_pci(void) -{ - int ret; - - ath5k_debug_init(); - - ret = pci_register_driver(&ath5k_pci_driver); - if (ret) { - printk(KERN_ERR "ath5k_pci: can't register pci driver\n"); - return ret; - } - - return 0; -} - -static void __exit -exit_ath5k_pci(void) -{ - pci_unregister_driver(&ath5k_pci_driver); - - ath5k_debug_finish(); -} - -module_init(init_ath5k_pci); -module_exit(exit_ath5k_pci); - - -/********************\ -* PCI Initialization * -\********************/ - -static const char * -ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val) -{ - const char *name = "xxxxx"; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(srev_names); i++) { - if (srev_names[i].sr_type != type) - continue; - - if ((val & 0xf0) == srev_names[i].sr_val) - name = srev_names[i].sr_name; - - if ((val & 0xff) == srev_names[i].sr_val) { - name = srev_names[i].sr_name; - break; - } - } - - return name; -} - -static int __devinit -ath5k_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath5k_softc *sc; - struct ieee80211_hw *hw; - int ret; - u8 csz; - - /* - * L0s needs to be disabled on all ath5k cards. - * - * For distributions shipping with CONFIG_PCIEASPM (this will be enabled - * by default in the future in 2.6.36) this will also mean both L1 and - * L0s will be disabled when a pre 1.1 PCIe device is detected. We do - * know L1 works correctly even for all ath5k pre 1.1 PCIe devices - * though but cannot currently undue the effect of a blacklist, for - * details you can read pcie_aspm_sanity_check() and see how it adjusts - * the device link capability. - * - * It may be possible in the future to implement some PCI API to allow - * drivers to override blacklists for pre 1.1 PCIe but for now it is - * best to accept that both L0s and L1 will be disabled completely for - * distributions shipping with CONFIG_PCIEASPM rather than having this - * issue present. Motivation for adding this new API will be to help - * with power consumption for some of these devices. - */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S); - - ret = pci_enable_device(pdev); - if (ret) { - dev_err(&pdev->dev, "can't enable device\n"); - goto err; - } - - /* XXX 32-bit addressing only */ - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - dev_err(&pdev->dev, "32-bit DMA not available\n"); - goto err_dis; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES >> 2; - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - /* Enable bus mastering */ - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_write_config_byte(pdev, 0x41, 0); - - ret = pci_request_region(pdev, 0, "ath5k"); - if (ret) { - dev_err(&pdev->dev, "cannot reserve PCI memory region\n"); - goto err_dis; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - dev_err(&pdev->dev, "cannot remap PCI memory region\n") ; - ret = -EIO; - goto err_reg; - } - - /* - * Allocate hw (mac80211 main struct) - * and hw->priv (driver private data) - */ - hw = ieee80211_alloc_hw(sizeof(*sc), &ath5k_hw_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "cannot allocate ieee80211_hw\n"); - ret = -ENOMEM; - goto err_map; - } - - dev_info(&pdev->dev, "registered as '%s'\n", wiphy_name(hw->wiphy)); - - /* Initialize driver private data */ - SET_IEEE80211_DEV(hw, &pdev->dev); - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->extra_tx_headroom = 2; - hw->channel_change_time = 5000; - sc = hw->priv; - sc->hw = hw; - sc->pdev = pdev; - - ath5k_debug_init_device(sc); - - /* - * Mark the device as detached to avoid processing - * interrupts until setup is complete. - */ - __set_bit(ATH_STAT_INVALID, sc->status); - - sc->iobase = mem; /* So we can unmap it on detach */ - sc->common.cachelsz = csz << 2; /* convert to bytes */ - sc->opmode = NL80211_IFTYPE_STATION; - sc->bintval = 1000; - mutex_init(&sc->lock); - spin_lock_init(&sc->rxbuflock); - spin_lock_init(&sc->txbuflock); - spin_lock_init(&sc->block); - - /* Set private data */ - pci_set_drvdata(pdev, hw); - - /* Setup interrupt handler */ - ret = request_irq(pdev->irq, ath5k_intr, IRQF_SHARED, "ath", sc); - if (ret) { - ATH5K_ERR(sc, "request_irq failed\n"); - goto err_free; - } - - /* Initialize device */ - sc->ah = ath5k_hw_attach(sc); - if (IS_ERR(sc->ah)) { - ret = PTR_ERR(sc->ah); - goto err_irq; - } - - /* set up multi-rate retry capabilities */ - if (sc->ah->ah_version == AR5K_AR5212) { - hw->max_rates = 4; - hw->max_rate_tries = 11; - } - - /* Finish private driver data initialization */ - ret = ath5k_attach(pdev, hw); - if (ret) - goto err_ah; - - ATH5K_INFO(sc, "Atheros AR%s chip found (MAC: 0x%x, PHY: 0x%x)\n", - ath5k_chip_name(AR5K_VERSION_MAC, sc->ah->ah_mac_srev), - sc->ah->ah_mac_srev, - sc->ah->ah_phy_revision); - - if (!sc->ah->ah_single_chip) { - /* Single chip radio (!RF5111) */ - if (sc->ah->ah_radio_5ghz_revision && - !sc->ah->ah_radio_2ghz_revision) { - /* No 5GHz support -> report 2GHz radio */ - if (!test_bit(AR5K_MODE_11A, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* No 2GHz support (5110 and some - * 5Ghz only cards) -> report 5Ghz radio */ - } else if (!test_bit(AR5K_MODE_11B, - sc->ah->ah_capabilities.cap_mode)) { - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - /* Multiband radio */ - } else { - ATH5K_INFO(sc, "RF%s multiband radio found" - " (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - } - } - /* Multi chip radio (RF5111 - RF2111) -> - * report both 2GHz/5GHz radios */ - else if (sc->ah->ah_radio_5ghz_revision && - sc->ah->ah_radio_2ghz_revision){ - ATH5K_INFO(sc, "RF%s 5GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_5ghz_revision), - sc->ah->ah_radio_5ghz_revision); - ATH5K_INFO(sc, "RF%s 2GHz radio found (0x%x)\n", - ath5k_chip_name(AR5K_VERSION_RAD, - sc->ah->ah_radio_2ghz_revision), - sc->ah->ah_radio_2ghz_revision); - } - } - - - /* ready to process interrupts */ - __clear_bit(ATH_STAT_INVALID, sc->status); - - return 0; -err_ah: - ath5k_hw_detach(sc->ah); -err_irq: - free_irq(pdev->irq, sc); -err_free: - ieee80211_free_hw(hw); -err_map: - pci_iounmap(pdev, mem); -err_reg: - pci_release_region(pdev, 0); -err_dis: - pci_disable_device(pdev); -err: - return ret; -} - -static void __devexit -ath5k_pci_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; - - ath5k_debug_finish_device(sc); - ath5k_detach(pdev, hw); - ath5k_hw_detach(sc->ah); - free_irq(pdev->irq, sc); - pci_iounmap(pdev, sc->iobase); - pci_release_region(pdev, 0); - pci_disable_device(pdev); - ieee80211_free_hw(hw); -} - -#ifdef CONFIG_PM -static int -ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; - - ath5k_led_off(sc); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int -ath5k_pci_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath5k_softc *sc = hw->priv; - int err; - - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) - return err; - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_write_config_byte(pdev, 0x41, 0); - - ath5k_led_enable(sc); - return 0; -} -#endif /* CONFIG_PM */ - - -/***********************\ -* Driver Initialization * -\***********************/ - -static int ath5k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath5k_softc *sc = hw->priv; - struct ath_regulatory *regulatory = &sc->common.regulatory; - - return ath_reg_notifier_apply(wiphy, request, regulatory); -} - -static int -ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ath_regulatory *regulatory = &sc->common.regulatory; - u8 mac[ETH_ALEN] = {}; - int ret; - - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device); - - /* - * Check if the MAC has multi-rate retry support. - * We do this by trying to setup a fake extended - * descriptor. MAC's that don't have support will - * return false w/o doing anything. MAC's that do - * support it will return true w/o doing anything. - */ - ret = ah->ah_setup_mrr_tx_desc(ah, NULL, 0, 0, 0, 0, 0, 0); - if (ret < 0) - goto err; - if (ret > 0) - __set_bit(ATH_STAT_MRRETRY, sc->status); - - /* - * Collect the channel list. The 802.11 layer - * is resposible for filtering this list based - * on settings like the phy mode and regulatory - * domain restrictions. - */ - ret = ath5k_setup_bands(hw); - if (ret) { - ATH5K_ERR(sc, "can't get channels\n"); - goto err; - } - - /* NB: setup here so ath5k_rate_update is happy */ - if (test_bit(AR5K_MODE_11A, ah->ah_modes)) - ath5k_setcurmode(sc, AR5K_MODE_11A); - else - ath5k_setcurmode(sc, AR5K_MODE_11B); - - /* - * Allocate tx+rx descriptors and populate the lists. - */ - ret = ath5k_desc_alloc(sc, pdev); - if (ret) { - ATH5K_ERR(sc, "can't allocate descriptors\n"); - goto err; - } - - /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS - * priority. Note that hw functions handle reseting - * these queues at the needed time. - */ - ret = ath5k_beaconq_setup(ah); - if (ret < 0) { - ATH5K_ERR(sc, "can't setup a beacon xmit queue\n"); - goto err_desc; - } - sc->bhalq = ret; - sc->cabq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_CAB, 0); - if (IS_ERR(sc->cabq)) { - ATH5K_ERR(sc, "can't setup cab queue\n"); - ret = PTR_ERR(sc->cabq); - goto err_bhal; - } - - sc->txq = ath5k_txq_setup(sc, AR5K_TX_QUEUE_DATA, AR5K_WME_AC_BK); - if (IS_ERR(sc->txq)) { - ATH5K_ERR(sc, "can't setup xmit queue\n"); - ret = PTR_ERR(sc->txq); - goto err_queues; - } - - tasklet_init(&sc->rxtq, ath5k_tasklet_rx, (unsigned long)sc); - tasklet_init(&sc->txtq, ath5k_tasklet_tx, (unsigned long)sc); - tasklet_init(&sc->restq, ath5k_tasklet_reset, (unsigned long)sc); - tasklet_init(&sc->calib, ath5k_tasklet_calibrate, (unsigned long)sc); - tasklet_init(&sc->beacontq, ath5k_tasklet_beacon, (unsigned long)sc); - - ret = ath5k_eeprom_read_mac(ah, mac); - if (ret) { - ATH5K_ERR(sc, "unable to read address from EEPROM: 0x%04x\n", - sc->pdev->device); - goto err_queues; - } - - SET_IEEE80211_PERM_ADDR(hw, mac); - /* All MAC address bits matter for ACKs */ - memset(sc->bssidmask, 0xff, ETH_ALEN); - ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask); - - regulatory->current_rd = ah->ah_capabilities.cap_eeprom.ee_regdomain; - ret = ath_regd_init(regulatory, hw->wiphy, ath5k_reg_notifier); - if (ret) { - ATH5K_ERR(sc, "can't initialize regulatory system\n"); - goto err_queues; - } - - ret = ieee80211_register_hw(hw); - if (ret) { - ATH5K_ERR(sc, "can't register ieee80211 hw\n"); - goto err_queues; - } - - if (!ath_is_world_regd(regulatory)) - regulatory_hint(hw->wiphy, regulatory->alpha2); - - ath5k_init_leds(sc); - - return 0; -err_queues: - ath5k_txq_release(sc); -err_bhal: - ath5k_hw_release_tx_queue(ah, sc->bhalq); -err_desc: - ath5k_desc_free(sc, pdev); -err: - return ret; -} - -static void -ath5k_detach(struct pci_dev *pdev, struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - /* - * NB: the order of these is important: - * o call the 802.11 layer before detaching ath5k_hw to - * insure callbacks into the driver to delete global - * key cache entries can be handled - * o reclaim the tx queue data structures after calling - * the 802.11 layer as we'll get called back to reclaim - * node state and potentially want to use them - * o to cleanup the tx queues the hal is called, so detach - * it last - * XXX: ??? detach ath5k_hw ??? - * Other than that, it's straightforward... - */ - ieee80211_unregister_hw(hw); - ath5k_desc_free(sc, pdev); - ath5k_txq_release(sc); - ath5k_hw_release_tx_queue(sc->ah, sc->bhalq); - ath5k_unregister_leds(sc); - - /* - * NB: can't reclaim these until after ieee80211_ifdetach - * returns because we'll get called back to reclaim node - * state and potentially want to use them. - */ -} - - - - -/********************\ -* Channel/mode setup * -\********************/ - -/* - * Convert IEEE channel number to MHz frequency. - */ -static inline short -ath5k_ieee2mhz(short chan) -{ - if (chan <= 14 || chan >= 27) - return ieee80211chan2mhz(chan); - else - return 2212 + chan * 20; -} - -/* - * Returns true for the channel numbers used without all_channels modparam. - */ -static bool ath5k_is_standard_channel(short chan) -{ - return ((chan <= 14) || - /* UNII 1,2 */ - ((chan & 3) == 0 && chan >= 36 && chan <= 64) || - /* midband */ - ((chan & 3) == 0 && chan >= 100 && chan <= 140) || - /* UNII-3 */ - ((chan & 3) == 1 && chan >= 149 && chan <= 165)); -} - -static unsigned int -ath5k_copy_channels(struct ath5k_hw *ah, - struct ieee80211_channel *channels, - unsigned int mode, - unsigned int max) -{ - unsigned int i, count, size, chfreq, freq, ch; - - if (!test_bit(mode, ah->ah_modes)) - return 0; - - switch (mode) { - case AR5K_MODE_11A: - case AR5K_MODE_11A_TURBO: - /* 1..220, but 2GHz frequencies are filtered by check_channel */ - size = 220 ; - chfreq = CHANNEL_5GHZ; - break; - case AR5K_MODE_11B: - case AR5K_MODE_11G: - case AR5K_MODE_11G_TURBO: - size = 26; - chfreq = CHANNEL_2GHZ; - break; - default: - ATH5K_WARN(ah->ah_sc, "bad mode, not copying channels\n"); - return 0; - } - - for (i = 0, count = 0; i < size && max > 0; i++) { - ch = i + 1 ; - freq = ath5k_ieee2mhz(ch); - - /* Check if channel is supported by the chipset */ - if (!ath5k_channel_ok(ah, freq, chfreq)) - continue; - - if (!modparam_all_channels && !ath5k_is_standard_channel(ch)) - continue; - - /* Write channel info and increment counter */ - channels[count].center_freq = freq; - channels[count].band = (chfreq == CHANNEL_2GHZ) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - switch (mode) { - case AR5K_MODE_11A: - case AR5K_MODE_11G: - channels[count].hw_value = chfreq | CHANNEL_OFDM; - break; - case AR5K_MODE_11A_TURBO: - case AR5K_MODE_11G_TURBO: - channels[count].hw_value = chfreq | - CHANNEL_OFDM | CHANNEL_TURBO; - break; - case AR5K_MODE_11B: - channels[count].hw_value = CHANNEL_B; - } - - count++; - max--; - } - - return count; -} - -static void -ath5k_setup_rate_idx(struct ath5k_softc *sc, struct ieee80211_supported_band *b) -{ - u8 i; - - for (i = 0; i < AR5K_MAX_RATES; i++) - sc->rate_idx[b->band][i] = -1; - - for (i = 0; i < b->n_bitrates; i++) { - sc->rate_idx[b->band][b->bitrates[i].hw_value] = i; - if (b->bitrates[i].hw_value_short) - sc->rate_idx[b->band][b->bitrates[i].hw_value_short] = i; - } -} - -static int -ath5k_setup_bands(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ieee80211_supported_band *sband; - int max_c, count_c = 0; - int i; - - BUILD_BUG_ON(ARRAY_SIZE(sc->sbands) < IEEE80211_NUM_BANDS); - max_c = ARRAY_SIZE(sc->channels); - - /* 2GHz band */ - sband = &sc->sbands[IEEE80211_BAND_2GHZ]; - sband->band = IEEE80211_BAND_2GHZ; - sband->bitrates = &sc->rates[IEEE80211_BAND_2GHZ][0]; - - if (test_bit(AR5K_MODE_11G, sc->ah->ah_capabilities.cap_mode)) { - /* G mode */ - memcpy(sband->bitrates, &ath5k_rates[0], - sizeof(struct ieee80211_rate) * 12); - sband->n_bitrates = 12; - - sband->channels = sc->channels; - sband->n_channels = ath5k_copy_channels(ah, sband->channels, - AR5K_MODE_11G, max_c); - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - count_c = sband->n_channels; - max_c -= count_c; - } else if (test_bit(AR5K_MODE_11B, sc->ah->ah_capabilities.cap_mode)) { - /* B mode */ - memcpy(sband->bitrates, &ath5k_rates[0], - sizeof(struct ieee80211_rate) * 4); - sband->n_bitrates = 4; - - /* 5211 only supports B rates and uses 4bit rate codes - * (e.g normally we have 0x1B for 1M, but on 5211 we have 0x0B) - * fix them up here: - */ - if (ah->ah_version == AR5K_AR5211) { - for (i = 0; i < 4; i++) { - sband->bitrates[i].hw_value = - sband->bitrates[i].hw_value & 0xF; - sband->bitrates[i].hw_value_short = - sband->bitrates[i].hw_value_short & 0xF; - } - } - - sband->channels = sc->channels; - sband->n_channels = ath5k_copy_channels(ah, sband->channels, - AR5K_MODE_11B, max_c); - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband; - count_c = sband->n_channels; - max_c -= count_c; - } - ath5k_setup_rate_idx(sc, sband); - - /* 5GHz band, A mode */ - if (test_bit(AR5K_MODE_11A, sc->ah->ah_capabilities.cap_mode)) { - sband = &sc->sbands[IEEE80211_BAND_5GHZ]; - sband->band = IEEE80211_BAND_5GHZ; - sband->bitrates = &sc->rates[IEEE80211_BAND_5GHZ][0]; - - memcpy(sband->bitrates, &ath5k_rates[4], - sizeof(struct ieee80211_rate) * 8); - sband->n_bitrates = 8; - - sband->channels = &sc->channels[count_c]; - sband->n_channels = ath5k_copy_channels(ah, sband->channels, - AR5K_MODE_11A, max_c); - - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband; - } - ath5k_setup_rate_idx(sc, sband); - - ath5k_debug_dump_bands(sc); - - return 0; -} - -/* - * Set/change channels. We always reset the chip. - * To accomplish this we must first cleanup any pending DMA, - * then restart stuff after a la ath5k_init. - * - * Called with sc->lock. - */ -static int -ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan) -{ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "(%u MHz) -> (%u MHz)\n", - sc->curchan->center_freq, chan->center_freq); - - /* - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the - * hardware at the new frequency, and then re-enable - * the relevant bits of the h/w. - */ - return ath5k_reset(sc, chan); -} - -static void -ath5k_setcurmode(struct ath5k_softc *sc, unsigned int mode) -{ - sc->curmode = mode; - - if (mode == AR5K_MODE_11A) { - sc->curband = &sc->sbands[IEEE80211_BAND_5GHZ]; - } else { - sc->curband = &sc->sbands[IEEE80211_BAND_2GHZ]; - } -} - -static void -ath5k_mode_setup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - u32 rfilt; - - ah->ah_op_mode = sc->opmode; - - /* configure rx filter */ - rfilt = sc->filter_flags; - ath5k_hw_set_rx_filter(ah, rfilt); - - if (ath5k_hw_hasbssidmask(ah)) - ath5k_hw_set_bssid_mask(ah, sc->bssidmask); - - /* configure operational mode */ - ath5k_hw_set_opmode(ah); - - ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt); -} - -static inline int -ath5k_hw_to_driver_rix(struct ath5k_softc *sc, int hw_rix) -{ - int rix; - - /* return base rate on errors */ - if (WARN(hw_rix < 0 || hw_rix >= AR5K_MAX_RATES, - "hw_rix out of bounds: %x\n", hw_rix)) - return 0; - - rix = sc->rate_idx[sc->curband->band][hw_rix]; - if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix)) - rix = 0; - - return rix; -} - -/***************\ -* Buffers setup * -\***************/ - -static -struct sk_buff *ath5k_rx_skb_alloc(struct ath5k_softc *sc, dma_addr_t *skb_addr) -{ - struct sk_buff *skb; - - /* - * Allocate buffer with headroom_needed space for the - * fake physical layer header at the start. - */ - skb = ath_rxbuf_alloc(&sc->common, - sc->rxbufsize + sc->common.cachelsz - 1, - GFP_ATOMIC); - - if (!skb) { - ATH5K_ERR(sc, "can't alloc skbuff of size %u\n", - sc->rxbufsize + sc->common.cachelsz - 1); - return NULL; - } - - *skb_addr = pci_map_single(sc->pdev, - skb->data, sc->rxbufsize, PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(sc->pdev, *skb_addr))) { - ATH5K_ERR(sc, "%s: DMA mapping failed\n", __func__); - dev_kfree_skb(skb); - return NULL; - } - return skb; -} - -static int -ath5k_rxbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct ath5k_hw *ah = sc->ah; - struct sk_buff *skb = bf->skb; - struct ath5k_desc *ds; - - if (!skb) { - skb = ath5k_rx_skb_alloc(sc, &bf->skbaddr); - if (!skb) - return -ENOMEM; - bf->skb = skb; - } - - /* - * Setup descriptors. For receive we always terminate - * the descriptor list with a self-linked entry so we'll - * not get overrun under high load (as can happen with a - * 5212 when ANI processing enables PHY error frames). - * - * To insure the last descriptor is self-linked we create - * each descriptor as self-linked and add it to the end. As - * each additional descriptor is added the previous self-linked - * entry is ``fixed'' naturally. This should be safe even - * if DMA is happening. When processing RX interrupts we - * never remove/process the last, self-linked, entry on the - * descriptor list. This insures the hardware always has - * someplace to write a new frame. - */ - ds = bf->desc; - ds->ds_link = bf->daddr; /* link to self */ - ds->ds_data = bf->skbaddr; - ah->ah_setup_rx_desc(ah, ds, - skb_tailroom(skb), /* buffer size */ - 0); - - if (sc->rxlink != NULL) - *sc->rxlink = bf->daddr; - sc->rxlink = &ds->ds_link; - return 0; -} - -static enum ath5k_pkt_type get_hw_packet_type(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - enum ath5k_pkt_type htype; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - if (ieee80211_is_beacon(fc)) - htype = AR5K_PKT_TYPE_BEACON; - else if (ieee80211_is_probe_resp(fc)) - htype = AR5K_PKT_TYPE_PROBE_RESP; - else if (ieee80211_is_atim(fc)) - htype = AR5K_PKT_TYPE_ATIM; - else if (ieee80211_is_pspoll(fc)) - htype = AR5K_PKT_TYPE_PSPOLL; - else - htype = AR5K_PKT_TYPE_NORMAL; - - return htype; -} - -static int -ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf, - struct ath5k_txq *txq) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_desc *ds = bf->desc; - struct sk_buff *skb = bf->skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - unsigned int pktlen, flags, keyidx = AR5K_TXKEYIX_INVALID; - struct ieee80211_rate *rate; - unsigned int mrr_rate[3], mrr_tries[3]; - int i, ret; - u16 hw_rate; - u16 cts_rate = 0; - u16 duration = 0; - u8 rc_flags; - - flags = AR5K_TXDESC_INTREQ | AR5K_TXDESC_CLRDMASK; - - /* XXX endianness */ - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - - rate = ieee80211_get_tx_rate(sc->hw, info); - if (!rate) { - ret = -EINVAL; - goto err_unmap; - } - - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - flags |= AR5K_TXDESC_NOACK; - - rc_flags = info->control.rates[0].flags; - hw_rate = (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) ? - rate->hw_value_short : rate->hw_value; - - pktlen = skb->len; - - /* FIXME: If we are in g mode and rate is a CCK rate - * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta - * from tx power (value is in dB units already) */ - if (info->control.hw_key) { - keyidx = info->control.hw_key->hw_key_idx; - pktlen += info->control.hw_key->icv_len; - } - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - flags |= AR5K_TXDESC_RTSENA; - cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; - duration = le16_to_cpu(ieee80211_rts_duration(sc->hw, - sc->vif, pktlen, info)); - } - if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - flags |= AR5K_TXDESC_CTSENA; - cts_rate = ieee80211_get_rts_cts_rate(sc->hw, info)->hw_value; - duration = le16_to_cpu(ieee80211_ctstoself_duration(sc->hw, - sc->vif, pktlen, info)); - } - ret = ah->ah_setup_tx_desc(ah, ds, pktlen, - ieee80211_get_hdrlen_from_skb(skb), - get_hw_packet_type(skb), - (sc->power_level * 2), - hw_rate, - info->control.rates[0].count, keyidx, ah->ah_tx_ant, flags, - cts_rate, duration); - if (ret) - goto err_unmap; - - memset(mrr_rate, 0, sizeof(mrr_rate)); - memset(mrr_tries, 0, sizeof(mrr_tries)); - for (i = 0; i < 3; i++) { - rate = ieee80211_get_alt_retry_rate(sc->hw, info, i); - if (!rate) - break; - - mrr_rate[i] = rate->hw_value; - mrr_tries[i] = info->control.rates[i + 1].count; - } - - ah->ah_setup_mrr_tx_desc(ah, ds, - mrr_rate[0], mrr_tries[0], - mrr_rate[1], mrr_tries[1], - mrr_rate[2], mrr_tries[2]); - - ds->ds_link = 0; - ds->ds_data = bf->skbaddr; - - spin_lock_bh(&txq->lock); - list_add_tail(&bf->list, &txq->q); - sc->tx_stats[txq->qnum].len++; - if (txq->link == NULL) /* is this first packet? */ - ath5k_hw_set_txdp(ah, txq->qnum, bf->daddr); - else /* no, so only link it */ - *txq->link = bf->daddr; - - txq->link = &ds->ds_link; - ath5k_hw_start_tx_dma(ah, txq->qnum); - mmiowb(); - spin_unlock_bh(&txq->lock); - - return 0; -err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); - return ret; -} - -/*******************\ -* Descriptors setup * -\*******************/ - -static int -ath5k_desc_alloc(struct ath5k_softc *sc, struct pci_dev *pdev) -{ - struct ath5k_desc *ds; - struct ath5k_buf *bf; - dma_addr_t da; - unsigned int i; - int ret; - - /* allocate descriptors */ - sc->desc_len = sizeof(struct ath5k_desc) * - (ATH_TXBUF + ATH_RXBUF + ATH_BCBUF + 1); - sc->desc = pci_alloc_consistent(pdev, sc->desc_len, &sc->desc_daddr); - if (sc->desc == NULL) { - ATH5K_ERR(sc, "can't allocate descriptors\n"); - ret = -ENOMEM; - goto err; - } - ds = sc->desc; - da = sc->desc_daddr; - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "DMA map: %p (%zu) -> %llx\n", - ds, sc->desc_len, (unsigned long long)sc->desc_daddr); - - bf = kcalloc(1 + ATH_TXBUF + ATH_RXBUF + ATH_BCBUF, - sizeof(struct ath5k_buf), GFP_KERNEL); - if (bf == NULL) { - ATH5K_ERR(sc, "can't allocate bufptr\n"); - ret = -ENOMEM; - goto err_free; - } - sc->bufptr = bf; - - INIT_LIST_HEAD(&sc->rxbuf); - for (i = 0; i < ATH_RXBUF; i++, bf++, ds++, da += sizeof(*ds)) { - bf->desc = ds; - bf->daddr = da; - list_add_tail(&bf->list, &sc->rxbuf); - } - - INIT_LIST_HEAD(&sc->txbuf); - sc->txbuf_len = ATH_TXBUF; - for (i = 0; i < ATH_TXBUF; i++, bf++, ds++, - da += sizeof(*ds)) { - bf->desc = ds; - bf->daddr = da; - list_add_tail(&bf->list, &sc->txbuf); - } - - /* beacon buffer */ - bf->desc = ds; - bf->daddr = da; - sc->bbuf = bf; - - return 0; -err_free: - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); -err: - sc->desc = NULL; - return ret; -} - -static void -ath5k_desc_free(struct ath5k_softc *sc, struct pci_dev *pdev) -{ - struct ath5k_buf *bf; - - ath5k_txbuf_free(sc, sc->bbuf); - list_for_each_entry(bf, &sc->txbuf, list) - ath5k_txbuf_free(sc, bf); - list_for_each_entry(bf, &sc->rxbuf, list) - ath5k_rxbuf_free(sc, bf); - - /* Free memory associated with all descriptors */ - pci_free_consistent(pdev, sc->desc_len, sc->desc, sc->desc_daddr); - - kfree(sc->bufptr); - sc->bufptr = NULL; -} - - - - - -/**************\ -* Queues setup * -\**************/ - -static struct ath5k_txq * -ath5k_txq_setup(struct ath5k_softc *sc, - int qtype, int subtype) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_txq *txq; - struct ath5k_txq_info qi = { - .tqi_subtype = subtype, - .tqi_aifs = AR5K_TXQ_USEDEFAULT, - .tqi_cw_min = AR5K_TXQ_USEDEFAULT, - .tqi_cw_max = AR5K_TXQ_USEDEFAULT - }; - int qnum; - - /* - * Enable interrupts only for EOL and DESC conditions. - * We mark tx descriptors to receive a DESC interrupt - * when a tx queue gets deep; otherwise waiting for the - * EOL to reap descriptors. Note that this is done to - * reduce interrupt load and this only defers reaping - * descriptors, never transmitting frames. Aside from - * reducing interrupts this also permits more concurrency. - * The only potential downside is if the tx queue backs - * up in which case the top half of the kernel may backup - * due to a lack of tx descriptors. - */ - qi.tqi_flags = AR5K_TXQ_FLAG_TXEOLINT_ENABLE | - AR5K_TXQ_FLAG_TXDESCINT_ENABLE; - qnum = ath5k_hw_setup_tx_queue(ah, qtype, &qi); - if (qnum < 0) { - /* - * NB: don't print a message, this happens - * normally on parts with too few tx queues - */ - return ERR_PTR(qnum); - } - if (qnum >= ARRAY_SIZE(sc->txqs)) { - ATH5K_ERR(sc, "hw qnum %u out of range, max %tu!\n", - qnum, ARRAY_SIZE(sc->txqs)); - ath5k_hw_release_tx_queue(ah, qnum); - return ERR_PTR(-EINVAL); - } - txq = &sc->txqs[qnum]; - if (!txq->setup) { - txq->qnum = qnum; - txq->link = NULL; - INIT_LIST_HEAD(&txq->q); - spin_lock_init(&txq->lock); - txq->setup = true; - } - return &sc->txqs[qnum]; -} - -static int -ath5k_beaconq_setup(struct ath5k_hw *ah) -{ - struct ath5k_txq_info qi = { - .tqi_aifs = AR5K_TXQ_USEDEFAULT, - .tqi_cw_min = AR5K_TXQ_USEDEFAULT, - .tqi_cw_max = AR5K_TXQ_USEDEFAULT, - /* NB: for dynamic turbo, don't enable any other interrupts */ - .tqi_flags = AR5K_TXQ_FLAG_TXDESCINT_ENABLE - }; - - return ath5k_hw_setup_tx_queue(ah, AR5K_TX_QUEUE_BEACON, &qi); -} - -static int -ath5k_beaconq_config(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_txq_info qi; - int ret; - - ret = ath5k_hw_get_tx_queueprops(ah, sc->bhalq, &qi); - if (ret) - goto err; - - if (sc->opmode == NL80211_IFTYPE_AP || - sc->opmode == NL80211_IFTYPE_MESH_POINT) { - /* - * Always burst out beacon and CAB traffic - * (aifs = cwmin = cwmax = 0) - */ - qi.tqi_aifs = 0; - qi.tqi_cw_min = 0; - qi.tqi_cw_max = 0; - } else if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* - * Adhoc mode; backoff between 0 and (2 * cw_min). - */ - qi.tqi_aifs = 0; - qi.tqi_cw_min = 0; - qi.tqi_cw_max = 2 * ah->ah_cw_min; - } - - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "beacon queueprops tqi_aifs:%d tqi_cw_min:%d tqi_cw_max:%d\n", - qi.tqi_aifs, qi.tqi_cw_min, qi.tqi_cw_max); - - ret = ath5k_hw_set_tx_queueprops(ah, sc->bhalq, &qi); - if (ret) { - ATH5K_ERR(sc, "%s: unable to update parameters for beacon " - "hardware queue!\n", __func__); - goto err; - } - ret = ath5k_hw_reset_tx_queue(ah, sc->bhalq); /* push to h/w */ - if (ret) - goto err; - - /* reconfigure cabq with ready time to 80% of beacon_interval */ - ret = ath5k_hw_get_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); - if (ret) - goto err; - - qi.tqi_ready_time = (sc->bintval * 80) / 100; - ret = ath5k_hw_set_tx_queueprops(ah, AR5K_TX_QUEUE_ID_CAB, &qi); - if (ret) - goto err; - - ret = ath5k_hw_reset_tx_queue(ah, AR5K_TX_QUEUE_ID_CAB); -err: - return ret; -} - -static void -ath5k_txq_drainq(struct ath5k_softc *sc, struct ath5k_txq *txq) -{ - struct ath5k_buf *bf, *bf0; - - /* - * NB: this assumes output has been stopped and - * we do not need to block ath5k_tx_tasklet - */ - spin_lock_bh(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ath5k_debug_printtxbuf(sc, bf); - - ath5k_txbuf_free(sc, bf); - - spin_lock_bh(&sc->txbuflock); - sc->tx_stats[txq->qnum].len--; - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock_bh(&sc->txbuflock); - } - txq->link = NULL; - spin_unlock_bh(&txq->lock); -} - -/* - * Drain the transmit queues and reclaim resources. - */ -static void -ath5k_txq_cleanup(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned int i; - - /* XXX return value */ - if (likely(!test_bit(ATH_STAT_INVALID, sc->status))) { - /* don't touch the hardware if marked invalid */ - ath5k_hw_stop_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "beacon queue %x\n", - ath5k_hw_get_txdp(ah, sc->bhalq)); - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) { - ath5k_hw_stop_tx_dma(ah, sc->txqs[i].qnum); - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "txq [%u] %x, " - "link %p\n", - sc->txqs[i].qnum, - ath5k_hw_get_txdp(ah, - sc->txqs[i].qnum), - sc->txqs[i].link); - } - } - ieee80211_wake_queues(sc->hw); /* XXX move to callers */ - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++) - if (sc->txqs[i].setup) - ath5k_txq_drainq(sc, &sc->txqs[i]); -} - -static void -ath5k_txq_release(struct ath5k_softc *sc) -{ - struct ath5k_txq *txq = sc->txqs; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(sc->txqs); i++, txq++) - if (txq->setup) { - ath5k_hw_release_tx_queue(sc->ah, txq->qnum); - txq->setup = false; - } -} - - - - -/*************\ -* RX Handling * -\*************/ - -/* - * Enable the receive h/w following a reset. - */ -static int -ath5k_rx_start(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - struct ath5k_buf *bf; - int ret; - - sc->rxbufsize = roundup(IEEE80211_MAX_LEN, sc->common.cachelsz); - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "cachelsz %u rxbufsize %u\n", - sc->common.cachelsz, sc->rxbufsize); - - spin_lock_bh(&sc->rxbuflock); - sc->rxlink = NULL; - list_for_each_entry(bf, &sc->rxbuf, list) { - ret = ath5k_rxbuf_setup(sc, bf); - if (ret != 0) { - spin_unlock_bh(&sc->rxbuflock); - goto err; - } - } - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); - ath5k_hw_set_rxdp(ah, bf->daddr); - spin_unlock_bh(&sc->rxbuflock); - - ath5k_hw_start_rx_dma(ah); /* enable recv descriptors */ - ath5k_mode_setup(sc); /* set filters, etc. */ - ath5k_hw_start_rx_pcu(ah); /* re-enable PCU/DMA engine */ - - return 0; -err: - return ret; -} - -/* - * Disable the receive h/w in preparation for a reset. - */ -static void -ath5k_rx_stop(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - - ath5k_hw_stop_rx_pcu(ah); /* disable PCU */ - ath5k_hw_set_rx_filter(ah, 0); /* clear recv filter */ - ath5k_hw_stop_rx_dma(ah); /* disable DMA engine */ - - ath5k_debug_printrxbuffs(sc, ah); - - sc->rxlink = NULL; /* just in case */ -} - -static unsigned int -ath5k_rx_decrypted(struct ath5k_softc *sc, struct ath5k_desc *ds, - struct sk_buff *skb, struct ath5k_rx_status *rs) -{ - struct ieee80211_hdr *hdr = (void *)skb->data; - unsigned int keyix, hlen; - - if (!(rs->rs_status & AR5K_RXERR_DECRYPT) && - rs->rs_keyix != AR5K_RXKEYIX_INVALID) - return RX_FLAG_DECRYPTED; - - /* Apparently when a default key is used to decrypt the packet - the hw does not set the index used to decrypt. In such cases - get the index from the packet. */ - hlen = ieee80211_hdrlen(hdr->frame_control); - if (ieee80211_has_protected(hdr->frame_control) && - !(rs->rs_status & AR5K_RXERR_DECRYPT) && - skb->len >= hlen + 4) { - keyix = skb->data[hlen + 3] >> 6; - - if (test_bit(keyix, sc->keymap)) - return RX_FLAG_DECRYPTED; - } - - return 0; -} - - -static void -ath5k_check_ibss_tsf(struct ath5k_softc *sc, struct sk_buff *skb, - struct ieee80211_rx_status *rxs) -{ - u64 tsf, bc_tstamp; - u32 hw_tu; - struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb->data; - - if (ieee80211_is_beacon(mgmt->frame_control) && - le16_to_cpu(mgmt->u.beacon.capab_info) & WLAN_CAPABILITY_IBSS && - memcmp(mgmt->bssid, sc->ah->ah_bssid, ETH_ALEN) == 0) { - /* - * Received an IBSS beacon with the same BSSID. Hardware *must* - * have updated the local TSF. We have to work around various - * hardware bugs, though... - */ - tsf = ath5k_hw_get_tsf64(sc->ah); - bc_tstamp = le64_to_cpu(mgmt->u.beacon.timestamp); - hw_tu = TSF_TO_TU(tsf); - - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "beacon %llx mactime %llx (diff %lld) tsf now %llx\n", - (unsigned long long)bc_tstamp, - (unsigned long long)rxs->mactime, - (unsigned long long)(rxs->mactime - bc_tstamp), - (unsigned long long)tsf); - - /* - * Sometimes the HW will give us a wrong tstamp in the rx - * status, causing the timestamp extension to go wrong. - * (This seems to happen especially with beacon frames bigger - * than 78 byte (incl. FCS)) - * But we know that the receive timestamp must be later than the - * timestamp of the beacon since HW must have synced to that. - * - * NOTE: here we assume mactime to be after the frame was - * received, not like mac80211 which defines it at the start. - */ - if (bc_tstamp > rxs->mactime) { - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "fixing mactime from %llx to %llx\n", - (unsigned long long)rxs->mactime, - (unsigned long long)tsf); - rxs->mactime = tsf; - } - - /* - * Local TSF might have moved higher than our beacon timers, - * in that case we have to update them to continue sending - * beacons. This also takes care of synchronizing beacon sending - * times with other stations. - */ - if (hw_tu >= sc->nexttbtt) - ath5k_beacon_update_timers(sc, bc_tstamp); - } -} - -static void -ath5k_tasklet_rx(unsigned long data) -{ - struct ieee80211_rx_status *rxs; - struct ath5k_rx_status rs = {}; - struct sk_buff *skb, *next_skb; - dma_addr_t next_skb_addr; - struct ath5k_softc *sc = (void *)data; - struct ath5k_buf *bf; - struct ath5k_desc *ds; - int ret; - int hdrlen; - int padsize; - int rx_flag; - - spin_lock(&sc->rxbuflock); - if (list_empty(&sc->rxbuf)) { - ATH5K_WARN(sc, "empty rx buf pool\n"); - goto unlock; - } - do { - rx_flag = 0; - - bf = list_first_entry(&sc->rxbuf, struct ath5k_buf, list); - BUG_ON(bf->skb == NULL); - skb = bf->skb; - ds = bf->desc; - - /* bail if HW is still using self-linked descriptor */ - if (ath5k_hw_get_rxdp(sc->ah) == bf->daddr) - break; - - ret = sc->ah->ah_proc_rx_desc(sc->ah, ds, &rs); - if (unlikely(ret == -EINPROGRESS)) - break; - else if (unlikely(ret)) { - ATH5K_ERR(sc, "error in processing rx descriptor\n"); - spin_unlock(&sc->rxbuflock); - return; - } - - if (unlikely(rs.rs_status)) { - if (rs.rs_status & AR5K_RXERR_PHY) - goto next; - if (rs.rs_status & AR5K_RXERR_DECRYPT) { - /* - * Decrypt error. If the error occurred - * because there was no hardware key, then - * let the frame through so the upper layers - * can process it. This is necessary for 5210 - * parts which have no way to setup a ``clear'' - * key cache entry. - * - * XXX do key cache faulting - */ - if (rs.rs_keyix == AR5K_RXKEYIX_INVALID && - !(rs.rs_status & AR5K_RXERR_CRC)) - goto accept; - } - if (rs.rs_status & AR5K_RXERR_MIC) { - rx_flag |= RX_FLAG_MMIC_ERROR; - goto accept; - } - - /* let crypto-error packets fall through in MNTR */ - if ((rs.rs_status & - ~(AR5K_RXERR_DECRYPT|AR5K_RXERR_MIC)) || - sc->opmode != NL80211_IFTYPE_MONITOR) - goto next; - } - if (unlikely(rs.rs_more)) - goto next; -accept: - next_skb = ath5k_rx_skb_alloc(sc, &next_skb_addr); - - /* - * If we can't replace bf->skb with a new skb under memory - * pressure, just skip this packet - */ - if (!next_skb) - goto next; - - pci_unmap_single(sc->pdev, bf->skbaddr, sc->rxbufsize, - PCI_DMA_FROMDEVICE); - skb_put(skb, rs.rs_datalen); - - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - hdrlen % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = ath5k_pad_size(hdrlen); - if (padsize) { - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - rxs = IEEE80211_SKB_RXCB(skb); - - /* - * always extend the mac timestamp, since this information is - * also needed for proper IBSS merging. - * - * XXX: it might be too late to do it here, since rs_tstamp is - * 15bit only. that means TSF extension has to be done within - * 32768usec (about 32ms). it might be necessary to move this to - * the interrupt handler, like it is done in madwifi. - * - * Unfortunately we don't know when the hardware takes the rx - * timestamp (beginning of phy frame, data frame, end of rx?). - * The only thing we know is that it is hardware specific... - * On AR5213 it seems the rx timestamp is at the end of the - * frame, but i'm not sure. - * - * NOTE: mac80211 defines mactime at the beginning of the first - * data symbol. Since we don't have any time references it's - * impossible to comply to that. This affects IBSS merge only - * right now, so it's not too bad... - */ - rxs->mactime = ath5k_extend_tsf(sc->ah, rs.rs_tstamp); - rxs->flag = rx_flag | RX_FLAG_TSFT; - - rxs->freq = sc->curchan->center_freq; - rxs->band = sc->curband->band; - - rxs->noise = sc->ah->ah_noise_floor; - rxs->signal = rxs->noise + rs.rs_rssi; - - /* An rssi of 35 indicates you should be able use - * 54 Mbps reliably. A more elaborate scheme can be used - * here but it requires a map of SNR/throughput for each - * possible mode used */ - rxs->qual = rs.rs_rssi * 100 / 35; - - /* rssi can be more than 35 though, anything above that - * should be considered at 100% */ - if (rxs->qual > 100) - rxs->qual = 100; - - rxs->antenna = rs.rs_antenna; - rxs->rate_idx = ath5k_hw_to_driver_rix(sc, rs.rs_rate); - rxs->flag |= ath5k_rx_decrypted(sc, ds, skb, &rs); - - if (rxs->rate_idx >= 0 && rs.rs_rate == - sc->curband->bitrates[rxs->rate_idx].hw_value_short) - rxs->flag |= RX_FLAG_SHORTPRE; - - ath5k_debug_dump_skb(sc, skb, "RX ", 0); - - /* check beacons in IBSS mode */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_check_ibss_tsf(sc, skb, rxs); - - ieee80211_rx(sc->hw, skb); - - bf->skb = next_skb; - bf->skbaddr = next_skb_addr; -next: - list_move_tail(&bf->list, &sc->rxbuf); - } while (ath5k_rxbuf_setup(sc, bf) == 0); -unlock: - spin_unlock(&sc->rxbuflock); -} - - - - -/*************\ -* TX Handling * -\*************/ - -static void -ath5k_tx_processq(struct ath5k_softc *sc, struct ath5k_txq *txq) -{ - struct ath5k_tx_status ts = {}; - struct ath5k_buf *bf, *bf0; - struct ath5k_desc *ds; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - int i, ret; - - spin_lock(&txq->lock); - list_for_each_entry_safe(bf, bf0, &txq->q, list) { - ds = bf->desc; - - ret = sc->ah->ah_proc_tx_desc(sc->ah, ds, &ts); - if (unlikely(ret == -EINPROGRESS)) - break; - else if (unlikely(ret)) { - ATH5K_ERR(sc, "error %d while processing queue %u\n", - ret, txq->qnum); - break; - } - - skb = bf->skb; - info = IEEE80211_SKB_CB(skb); - bf->skb = NULL; - - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, - PCI_DMA_TODEVICE); - - ieee80211_tx_info_clear_status(info); - for (i = 0; i < 4; i++) { - struct ieee80211_tx_rate *r = - &info->status.rates[i]; - - if (ts.ts_rate[i]) { - r->idx = ath5k_hw_to_driver_rix(sc, ts.ts_rate[i]); - r->count = ts.ts_retry[i]; - } else { - r->idx = -1; - r->count = 0; - } - } - - /* count the successful attempt as well */ - info->status.rates[ts.ts_final_idx].count++; - - if (unlikely(ts.ts_status)) { - sc->ll_stats.dot11ACKFailureCount++; - if (ts.ts_status & AR5K_TXERR_FILT) - info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - } else { - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.ack_signal = ts.ts_rssi; - } - - ieee80211_tx_status(sc->hw, skb); - sc->tx_stats[txq->qnum].count++; - - spin_lock(&sc->txbuflock); - sc->tx_stats[txq->qnum].len--; - list_move_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock(&sc->txbuflock); - } - if (likely(list_empty(&txq->q))) - txq->link = NULL; - spin_unlock(&txq->lock); - if (sc->txbuf_len > ATH_TXBUF / 5) - ieee80211_wake_queues(sc->hw); -} - -static void -ath5k_tasklet_tx(unsigned long data) -{ - int i; - struct ath5k_softc *sc = (void *)data; - - for (i=0; i < AR5K_NUM_TX_QUEUES; i++) - if (sc->txqs[i].setup && (sc->ah->ah_txq_isr & BIT(i))) - ath5k_tx_processq(sc, &sc->txqs[i]); -} - - -/*****************\ -* Beacon handling * -\*****************/ - -/* - * Setup the beacon frame for transmit. - */ -static int -ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct sk_buff *skb = bf->skb; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath5k_hw *ah = sc->ah; - struct ath5k_desc *ds; - int ret = 0; - u8 antenna; - u32 flags; - - bf->skbaddr = pci_map_single(sc->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "skb %p [data %p len %u] " - "skbaddr %llx\n", skb, skb->data, skb->len, - (unsigned long long)bf->skbaddr); - if (pci_dma_mapping_error(sc->pdev, bf->skbaddr)) { - ATH5K_ERR(sc, "beacon DMA mapping failed\n"); - return -EIO; - } - - ds = bf->desc; - antenna = ah->ah_tx_ant; - - flags = AR5K_TXDESC_NOACK; - if (sc->opmode == NL80211_IFTYPE_ADHOC && ath5k_hw_hasveol(ah)) { - ds->ds_link = bf->daddr; /* self-linked */ - flags |= AR5K_TXDESC_VEOL; - } else - ds->ds_link = 0; - - /* - * If we use multiple antennas on AP and use - * the Sectored AP scenario, switch antenna every - * 4 beacons to make sure everybody hears our AP. - * When a client tries to associate, hw will keep - * track of the tx antenna to be used for this client - * automaticaly, based on ACKed packets. - * - * Note: AP still listens and transmits RTS on the - * default antenna which is supposed to be an omni. - * - * Note2: On sectored scenarios it's possible to have - * multiple antennas (1omni -the default- and 14 sectors) - * so if we choose to actually support this mode we need - * to allow user to set how many antennas we have and tweak - * the code below to send beacons on all of them. - */ - if (ah->ah_ant_mode == AR5K_ANTMODE_SECTOR_AP) - antenna = sc->bsent & 4 ? 2 : 1; - - - /* FIXME: If we are in g mode and rate is a CCK rate - * subtract ah->ah_txpower.txp_cck_ofdm_pwr_delta - * from tx power (value is in dB units already) */ - ds->ds_data = bf->skbaddr; - ret = ah->ah_setup_tx_desc(ah, ds, skb->len, - ieee80211_get_hdrlen_from_skb(skb), - AR5K_PKT_TYPE_BEACON, (sc->power_level * 2), - ieee80211_get_tx_rate(sc->hw, info)->hw_value, - 1, AR5K_TXKEYIX_INVALID, - antenna, flags, 0, 0); - if (ret) - goto err_unmap; - - return 0; -err_unmap: - pci_unmap_single(sc->pdev, bf->skbaddr, skb->len, PCI_DMA_TODEVICE); - return ret; -} - -/* - * Transmit a beacon frame at SWBA. Dynamic updates to the - * frame contents are done as needed and the slot time is - * also adjusted based on current state. - * - * This is called from software irq context (beacontq or restq - * tasklets) or user context from ath5k_beacon_config. - */ -static void -ath5k_beacon_send(struct ath5k_softc *sc) -{ - struct ath5k_buf *bf = sc->bbuf; - struct ath5k_hw *ah = sc->ah; - struct sk_buff *skb; - - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "in beacon_send\n"); - - if (unlikely(bf->skb == NULL || sc->opmode == NL80211_IFTYPE_STATION || - sc->opmode == NL80211_IFTYPE_MONITOR)) { - ATH5K_WARN(sc, "bf=%p bf_skb=%p\n", bf, bf ? bf->skb : NULL); - return; - } - /* - * Check if the previous beacon has gone out. If - * not don't don't try to post another, skip this - * period and wait for the next. Missed beacons - * indicate a problem and should not occur. If we - * miss too many consecutive beacons reset the device. - */ - if (unlikely(ath5k_hw_num_tx_pending(ah, sc->bhalq) != 0)) { - sc->bmisscount++; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "missed %u consecutive beacons\n", sc->bmisscount); - if (sc->bmisscount > 10) { /* NB: 10 is a guess */ - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "stuck beacon time (%u missed)\n", - sc->bmisscount); - tasklet_schedule(&sc->restq); - } - return; - } - if (unlikely(sc->bmisscount != 0)) { - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "resume beacon xmit after %u misses\n", - sc->bmisscount); - sc->bmisscount = 0; - } - - /* - * Stop any current dma and put the new frame on the queue. - * This should never fail since we check above that no frames - * are still pending on the queue. - */ - if (unlikely(ath5k_hw_stop_tx_dma(ah, sc->bhalq))) { - ATH5K_WARN(sc, "beacon queue %u didn't start/stop ?\n", sc->bhalq); - /* NB: hw still stops DMA, so proceed */ - } - - /* refresh the beacon for AP mode */ - if (sc->opmode == NL80211_IFTYPE_AP) - ath5k_beacon_update(sc->hw, sc->vif); - - ath5k_hw_set_txdp(ah, sc->bhalq, bf->daddr); - ath5k_hw_start_tx_dma(ah, sc->bhalq); - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, "TXDP[%u] = %llx (%p)\n", - sc->bhalq, (unsigned long long)bf->daddr, bf->desc); - - skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); - while (skb) { - ath5k_tx_queue(sc->hw, skb, sc->cabq); - skb = ieee80211_get_buffered_bc(sc->hw, sc->vif); - } - - sc->bsent++; -} - - -/** - * ath5k_beacon_update_timers - update beacon timers - * - * @sc: struct ath5k_softc pointer we are operating on - * @bc_tsf: the timestamp of the beacon. 0 to reset the TSF. -1 to perform a - * beacon timer update based on the current HW TSF. - * - * Calculate the next target beacon transmit time (TBTT) based on the timestamp - * of a received beacon or the current local hardware TSF and write it to the - * beacon timer registers. - * - * This is called in a variety of situations, e.g. when a beacon is received, - * when a TSF update has been detected, but also when an new IBSS is created or - * when we otherwise know we have to update the timers, but we keep it in this - * function to have it all together in one place. - */ -static void -ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf) -{ - struct ath5k_hw *ah = sc->ah; - u32 nexttbtt, intval, hw_tu, bc_tu; - u64 hw_tsf; - - intval = sc->bintval & AR5K_BEACON_PERIOD; - if (WARN_ON(!intval)) - return; - - /* beacon TSF converted to TU */ - bc_tu = TSF_TO_TU(bc_tsf); - - /* current TSF converted to TU */ - hw_tsf = ath5k_hw_get_tsf64(ah); - hw_tu = TSF_TO_TU(hw_tsf); - -#define FUDGE 3 - /* we use FUDGE to make sure the next TBTT is ahead of the current TU */ - if (bc_tsf == -1) { - /* - * no beacons received, called internally. - * just need to refresh timers based on HW TSF. - */ - nexttbtt = roundup(hw_tu + FUDGE, intval); - } else if (bc_tsf == 0) { - /* - * no beacon received, probably called by ath5k_reset_tsf(). - * reset TSF to start with 0. - */ - nexttbtt = intval; - intval |= AR5K_BEACON_RESET_TSF; - } else if (bc_tsf > hw_tsf) { - /* - * beacon received, SW merge happend but HW TSF not yet updated. - * not possible to reconfigure timers yet, but next time we - * receive a beacon with the same BSSID, the hardware will - * automatically update the TSF and then we need to reconfigure - * the timers. - */ - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "need to wait for HW TSF sync\n"); - return; - } else { - /* - * most important case for beacon synchronization between STA. - * - * beacon received and HW TSF has been already updated by HW. - * update next TBTT based on the TSF of the beacon, but make - * sure it is ahead of our local TSF timer. - */ - nexttbtt = bc_tu + roundup(hw_tu + FUDGE - bc_tu, intval); - } -#undef FUDGE - - sc->nexttbtt = nexttbtt; - - intval |= AR5K_BEACON_ENA; - ath5k_hw_init_beacon(ah, nexttbtt, intval); - - /* - * debugging output last in order to preserve the time critical aspect - * of this function - */ - if (bc_tsf == -1) - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "reconfigured timers based on HW TSF\n"); - else if (bc_tsf == 0) - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "reset HW TSF and timers\n"); - else - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "updated timers based on beacon TSF\n"); - - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, - "bc_tsf %llx hw_tsf %llx bc_tu %u hw_tu %u nexttbtt %u\n", - (unsigned long long) bc_tsf, - (unsigned long long) hw_tsf, bc_tu, hw_tu, nexttbtt); - ATH5K_DBG_UNLIMIT(sc, ATH5K_DEBUG_BEACON, "intval %u %s %s\n", - intval & AR5K_BEACON_PERIOD, - intval & AR5K_BEACON_ENA ? "AR5K_BEACON_ENA" : "", - intval & AR5K_BEACON_RESET_TSF ? "AR5K_BEACON_RESET_TSF" : ""); -} - - -/** - * ath5k_beacon_config - Configure the beacon queues and interrupts - * - * @sc: struct ath5k_softc pointer we are operating on - * - * In IBSS mode we use a self-linked tx descriptor if possible. We enable SWBA - * interrupts to detect TSF updates only. - */ -static void -ath5k_beacon_config(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - unsigned long flags; - - spin_lock_irqsave(&sc->block, flags); - sc->bmisscount = 0; - sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); - - if (sc->enable_beacon) { - /* - * In IBSS mode we use a self-linked tx descriptor and let the - * hardware send the beacons automatically. We have to load it - * only once here. - * We use the SWBA interrupt only to keep track of the beacon - * timers in order to detect automatic TSF updates. - */ - ath5k_beaconq_config(sc); - - sc->imask |= AR5K_INT_SWBA; - - if (sc->opmode == NL80211_IFTYPE_ADHOC) { - if (ath5k_hw_hasveol(ah)) - ath5k_beacon_send(sc); - } else - ath5k_beacon_update_timers(sc, -1); - } else { - ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq); - } - - ath5k_hw_set_imr(ah, sc->imask); - mmiowb(); - spin_unlock_irqrestore(&sc->block, flags); -} - -static void ath5k_tasklet_beacon(unsigned long data) -{ - struct ath5k_softc *sc = (struct ath5k_softc *) data; - - /* - * Software beacon alert--time to send a beacon. - * - * In IBSS mode we use this interrupt just to - * keep track of the next TBTT (target beacon - * transmission time) in order to detect wether - * automatic TSF updates happened. - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) { - /* XXX: only if VEOL suppported */ - u64 tsf = ath5k_hw_get_tsf64(sc->ah); - sc->nexttbtt += sc->bintval; - ATH5K_DBG(sc, ATH5K_DEBUG_BEACON, - "SWBA nexttbtt: %x hw_tu: %x " - "TSF: %llx\n", - sc->nexttbtt, - TSF_TO_TU(tsf), - (unsigned long long) tsf); - } else { - spin_lock(&sc->block); - ath5k_beacon_send(sc); - spin_unlock(&sc->block); - } -} - - -/********************\ -* Interrupt handling * -\********************/ - -static int -ath5k_init(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - int ret, i; - - mutex_lock(&sc->lock); - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode); - - /* - * Stop anything previously setup. This is safe - * no matter this is the first time through or not. - */ - ath5k_stop_locked(sc); - - /* Set PHY calibration interval */ - ah->ah_cal_intval = ath5k_calinterval; - - /* - * The basic interface to setting the hardware in a good - * state is ``reset''. On return the hardware is known to - * be powered up and with interrupts disabled. This must - * be followed by initialization of the appropriate bits - * and then setup of the interrupt mask. - */ - sc->curchan = sc->hw->conf.channel; - sc->curband = &sc->sbands[sc->curchan->band]; - sc->imask = AR5K_INT_RXOK | AR5K_INT_RXERR | AR5K_INT_RXEOL | - AR5K_INT_RXORN | AR5K_INT_TXDESC | AR5K_INT_TXEOL | - AR5K_INT_FATAL | AR5K_INT_GLOBAL | AR5K_INT_SWI; - ret = ath5k_reset(sc, NULL); - if (ret) - goto done; - - ath5k_rfkill_hw_start(ah); - - /* - * Reset the key cache since some parts do not reset the - * contents on initial power up or resume from suspend. - */ - for (i = 0; i < AR5K_KEYTABLE_SIZE; i++) - ath5k_hw_reset_key(ah, i); - - /* Set ack to be sent at low bit-rates */ - ath5k_hw_set_ack_bitrate_high(ah, false); - ret = 0; -done: - mmiowb(); - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_stop_locked(struct ath5k_softc *sc) -{ - struct ath5k_hw *ah = sc->ah; - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "invalid %u\n", - test_bit(ATH_STAT_INVALID, sc->status)); - - /* - * Shutdown the hardware and driver: - * stop output from above - * disable interrupts - * turn off timers - * turn off the radio - * clear transmit machinery - * clear receive machinery - * drain and release tx queues - * reclaim beacon resources - * power down hardware - * - * Note that some of this work is not possible if the - * hardware is gone (invalid). - */ - ieee80211_stop_queues(sc->hw); - - if (!test_bit(ATH_STAT_INVALID, sc->status)) { - ath5k_led_off(sc); - ath5k_hw_set_imr(ah, 0); - synchronize_irq(sc->pdev->irq); - } - ath5k_txq_cleanup(sc); - if (!test_bit(ATH_STAT_INVALID, sc->status)) { - ath5k_rx_stop(sc); - ath5k_hw_phy_disable(ah); - } else - sc->rxlink = NULL; - - return 0; -} - -/* - * Stop the device, grabbing the top-level lock to protect - * against concurrent entry through ath5k_init (which can happen - * if another thread does a system call and the thread doing the - * stop is preempted). - */ -static int -ath5k_stop_hw(struct ath5k_softc *sc) -{ - int ret; - - mutex_lock(&sc->lock); - ret = ath5k_stop_locked(sc); - if (ret == 0 && !test_bit(ATH_STAT_INVALID, sc->status)) { - /* - * Don't set the card in full sleep mode! - * - * a) When the device is in this state it must be carefully - * woken up or references to registers in the PCI clock - * domain may freeze the bus (and system). This varies - * by chip and is mostly an issue with newer parts - * (madwifi sources mentioned srev >= 0x78) that go to - * sleep more quickly. - * - * b) On older chips full sleep results a weird behaviour - * during wakeup. I tested various cards with srev < 0x78 - * and they don't wake up after module reload, a second - * module reload is needed to bring the card up again. - * - * Until we figure out what's going on don't enable - * full chip reset on any chip (this is what Legacy HAL - * and Sam's HAL do anyway). Instead Perform a full reset - * on the device (same as initial state after attach) and - * leave it idle (keep MAC/BB on warm reset) */ - ret = ath5k_hw_on_hold(sc->ah); - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, - "putting device to sleep\n"); - } - ath5k_txbuf_free(sc, sc->bbuf); - - mmiowb(); - mutex_unlock(&sc->lock); - - tasklet_kill(&sc->rxtq); - tasklet_kill(&sc->txtq); - tasklet_kill(&sc->restq); - tasklet_kill(&sc->calib); - tasklet_kill(&sc->beacontq); - - ath5k_rfkill_hw_stop(sc->ah); - - return ret; -} - -static irqreturn_t -ath5k_intr(int irq, void *dev_id) -{ - struct ath5k_softc *sc = dev_id; - struct ath5k_hw *ah = sc->ah; - enum ath5k_int status; - unsigned int counter = 1000; - - if (unlikely(test_bit(ATH_STAT_INVALID, sc->status) || - !ath5k_hw_is_intr_pending(ah))) - return IRQ_NONE; - - do { - ath5k_hw_get_isr(ah, &status); /* NB: clears IRQ too */ - ATH5K_DBG(sc, ATH5K_DEBUG_INTR, "status 0x%x/0x%x\n", - status, sc->imask); - if (unlikely(status & AR5K_INT_FATAL)) { - /* - * Fatal errors are unrecoverable. - * Typically these are caused by DMA errors. - */ - tasklet_schedule(&sc->restq); - } else if (unlikely(status & AR5K_INT_RXORN)) { - tasklet_schedule(&sc->restq); - } else { - if (status & AR5K_INT_SWBA) { - tasklet_hi_schedule(&sc->beacontq); - } - if (status & AR5K_INT_RXEOL) { - /* - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work at - * least on older hardware revs. - */ - sc->rxlink = NULL; - } - if (status & AR5K_INT_TXURN) { - /* bump tx trigger level */ - ath5k_hw_update_tx_triglevel(ah, true); - } - if (status & (AR5K_INT_RXOK | AR5K_INT_RXERR)) - tasklet_schedule(&sc->rxtq); - if (status & (AR5K_INT_TXOK | AR5K_INT_TXDESC - | AR5K_INT_TXERR | AR5K_INT_TXEOL)) - tasklet_schedule(&sc->txtq); - if (status & AR5K_INT_BMISS) { - /* TODO */ - } - if (status & AR5K_INT_SWI) { - tasklet_schedule(&sc->calib); - } - if (status & AR5K_INT_MIB) { - /* - * These stats are also used for ANI i think - * so how about updating them more often ? - */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); - } - if (status & AR5K_INT_GPIO) - tasklet_schedule(&sc->rf_kill.toggleq); - - } - } while (ath5k_hw_is_intr_pending(ah) && --counter > 0); - - if (unlikely(!counter)) - ATH5K_WARN(sc, "too many interrupts, giving up for now\n"); - - ath5k_hw_calibration_poll(ah); - - return IRQ_HANDLED; -} - -static void -ath5k_tasklet_reset(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - - ath5k_reset_wake(sc); -} - -/* - * Periodically recalibrate the PHY to account - * for temperature/environment changes. - */ -static void -ath5k_tasklet_calibrate(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - struct ath5k_hw *ah = sc->ah; - - /* Only full calibration for now */ - if (ah->ah_swi_mask != AR5K_SWI_FULL_CALIBRATION) - return; - - /* Stop queues so that calibration - * doesn't interfere with tx */ - ieee80211_stop_queues(sc->hw); - - ATH5K_DBG(sc, ATH5K_DEBUG_CALIBRATE, "channel %u/%x\n", - ieee80211_frequency_to_channel(sc->curchan->center_freq), - sc->curchan->hw_value); - - if (ath5k_hw_gainf_calibrate(ah) == AR5K_RFGAIN_NEED_CHANGE) { - /* - * Rfgain is out of bounds, reset the chip - * to load new gain values. - */ - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "calibration, resetting\n"); - ath5k_reset_wake(sc); - } - if (ath5k_hw_phy_calibrate(ah, sc->curchan)) - ATH5K_ERR(sc, "calibration of channel %u failed\n", - ieee80211_frequency_to_channel( - sc->curchan->center_freq)); - - ah->ah_swi_mask = 0; - - /* Wake queues */ - ieee80211_wake_queues(sc->hw); - -} - - -/********************\ -* Mac80211 functions * -\********************/ - -static int -ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath5k_softc *sc = hw->priv; - - return ath5k_tx_queue(hw, skb, sc->txq); -} - -static int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath5k_txq *txq) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_buf *bf; - unsigned long flags; - int hdrlen; - int padsize; - - ath5k_debug_dump_skb(sc, skb, "TX ", 1); - - if (sc->opmode == NL80211_IFTYPE_MONITOR) - ATH5K_DBG(sc, ATH5K_DEBUG_XMIT, "tx in monitor (scan?)\n"); - - /* - * the hardware expects the header padded to 4 byte boundaries - * if this is not the case we add the padding after the header - */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = ath5k_pad_size(hdrlen); - if (padsize) { - - if (skb_headroom(skb) < padsize) { - ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" - " headroom to pad %d\n", hdrlen, padsize); - goto drop_packet; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data+padsize, hdrlen); - } - - spin_lock_irqsave(&sc->txbuflock, flags); - if (list_empty(&sc->txbuf)) { - ATH5K_ERR(sc, "no further txbuf available, dropping packet\n"); - spin_unlock_irqrestore(&sc->txbuflock, flags); - ieee80211_stop_queue(hw, skb_get_queue_mapping(skb)); - goto drop_packet; - } - bf = list_first_entry(&sc->txbuf, struct ath5k_buf, list); - list_del(&bf->list); - sc->txbuf_len--; - if (list_empty(&sc->txbuf)) - ieee80211_stop_queues(hw); - spin_unlock_irqrestore(&sc->txbuflock, flags); - - bf->skb = skb; - - if (ath5k_txbuf_setup(sc, bf, txq)) { - bf->skb = NULL; - spin_lock_irqsave(&sc->txbuflock, flags); - list_add_tail(&bf->list, &sc->txbuf); - sc->txbuf_len++; - spin_unlock_irqrestore(&sc->txbuflock, flags); - goto drop_packet; - } - return NETDEV_TX_OK; - -drop_packet: - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - -/* - * Reset the hardware. If chan is not NULL, then also pause rx/tx - * and change to the given channel. - */ -static int -ath5k_reset(struct ath5k_softc *sc, struct ieee80211_channel *chan) -{ - struct ath5k_hw *ah = sc->ah; - int ret; - - ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "resetting\n"); - - if (chan) { - ath5k_hw_set_imr(ah, 0); - ath5k_txq_cleanup(sc); - ath5k_rx_stop(sc); - - sc->curchan = chan; - sc->curband = &sc->sbands[chan->band]; - } - ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL); - if (ret) { - ATH5K_ERR(sc, "can't reset hardware (%d)\n", ret); - goto err; - } - - ret = ath5k_rx_start(sc); - if (ret) { - ATH5K_ERR(sc, "can't start recv logic\n"); - goto err; - } - - /* - * Change channels and update the h/w rate map if we're switching; - * e.g. 11a to 11b/g. - * - * We may be doing a reset in response to an ioctl that changes the - * channel so update any state that might change as a result. - * - * XXX needed? - */ -/* ath5k_chan_change(sc, c); */ - - ath5k_beacon_config(sc); - /* intrs are enabled by ath5k_beacon_config */ - - return 0; -err: - return ret; -} - -static int -ath5k_reset_wake(struct ath5k_softc *sc) -{ - int ret; - - ret = ath5k_reset(sc, sc->curchan); - if (!ret) - ieee80211_wake_queues(sc->hw); - - return ret; -} - -static int ath5k_start(struct ieee80211_hw *hw) -{ - return ath5k_init(hw->priv); -} - -static void ath5k_stop(struct ieee80211_hw *hw) -{ - ath5k_stop_hw(hw->priv); -} - -static int ath5k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath5k_softc *sc = hw->priv; - int ret; - - mutex_lock(&sc->lock); - if (sc->vif) { - ret = 0; - goto end; - } - - sc->vif = conf->vif; - - switch (conf->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_MONITOR: - sc->opmode = conf->type; - break; - default: - ret = -EOPNOTSUPP; - goto end; - } - - ath5k_hw_set_lladdr(sc->ah, conf->mac_addr); - ath5k_mode_setup(sc); - - ret = 0; -end: - mutex_unlock(&sc->lock); - return ret; -} - -static void -ath5k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath5k_softc *sc = hw->priv; - u8 mac[ETH_ALEN] = {}; - - mutex_lock(&sc->lock); - if (sc->vif != conf->vif) - goto end; - - ath5k_hw_set_lladdr(sc->ah, mac); - sc->vif = NULL; -end: - mutex_unlock(&sc->lock); -} - -/* - * TODO: Phy disable/diversity etc - */ -static int -ath5k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - struct ieee80211_conf *conf = &hw->conf; - int ret = 0; - - mutex_lock(&sc->lock); - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ret = ath5k_chan_set(sc, conf->channel); - if (ret < 0) - goto unlock; - } - - if ((changed & IEEE80211_CONF_CHANGE_POWER) && - (sc->power_level != conf->power_level)) { - sc->power_level = conf->power_level; - - /* Half dB steps */ - ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2)); - } - - /* TODO: - * 1) Move this on config_interface and handle each case - * separately eg. when we have only one STA vif, use - * AR5K_ANTMODE_SINGLE_AP - * - * 2) Allow the user to change antenna mode eg. when only - * one antenna is present - * - * 3) Allow the user to set default/tx antenna when possible - * - * 4) Default mode should handle 90% of the cases, together - * with fixed a/b and single AP modes we should be able to - * handle 99%. Sectored modes are extreme cases and i still - * haven't found a usage for them. If we decide to support them, - * then we must allow the user to set how many tx antennas we - * have available - */ - ath5k_hw_set_antenna_mode(ah, AR5K_ANTMODE_DEFAULT); - -unlock: - mutex_unlock(&sc->lock); - return ret; -} - -static u64 ath5k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - u32 mfilt[2], val; - int i; - u8 pos; - - mfilt[0] = 0; - mfilt[1] = 1; - - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - /* calculate XOR of eight 6-bit values */ - val = get_unaligned_le32(mclist->dmi_addr + 0); - pos = (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - val = get_unaligned_le32(mclist->dmi_addr + 3); - pos ^= (val >> 18) ^ (val >> 12) ^ (val >> 6) ^ val; - pos &= 0x3f; - mfilt[pos / 32] |= (1 << (pos % 32)); - /* XXX: we might be able to just do this instead, - * but not sure, needs testing, if we do use this we'd - * neet to inform below to not reset the mcast */ - /* ath5k_hw_set_mcast_filterindex(ah, - * mclist->dmi_addr[5]); */ - mclist = mclist->next; - } - - return ((u64)(mfilt[1]) << 32) | mfilt[0]; -} - -#define SUPPORTED_FIF_FLAGS \ - FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | \ - FIF_PLCPFAIL | FIF_CONTROL | FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC -/* - * o always accept unicast, broadcast, and multicast traffic - * o multicast traffic for all BSSIDs will be enabled if mac80211 - * says it should be - * o maintain current state of phy ofdm or phy cck error reception. - * If the hardware detects any of these type of errors then - * ath5k_hw_get_rx_filter() will pass to us the respective - * hardware filters to be able to receive these type of frames. - * o probe request frames are accepted only when operating in - * hostap, adhoc, or monitor modes - * o enable promiscuous mode according to the interface state - * o accept beacons: - * - when operating in adhoc mode so the 802.11 layer creates - * node table entries for peers, - * - when operating in station mode for collecting rssi data when - * the station is otherwise quiet, or - * - when scanning - */ -static void ath5k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - u32 mfilt[2], rfilt; - - mutex_lock(&sc->lock); - - mfilt[0] = multicast; - mfilt[1] = multicast >> 32; - - /* Only deal with supported flags */ - changed_flags &= SUPPORTED_FIF_FLAGS; - *new_flags &= SUPPORTED_FIF_FLAGS; - - /* If HW detects any phy or radar errors, leave those filters on. - * Also, always enable Unicast, Broadcasts and Multicast - * XXX: move unicast, bssid broadcasts and multicast to mac80211 */ - rfilt = (ath5k_hw_get_rx_filter(ah) & (AR5K_RX_FILTER_PHYERR)) | - (AR5K_RX_FILTER_UCAST | AR5K_RX_FILTER_BCAST | - AR5K_RX_FILTER_MCAST); - - if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) { - if (*new_flags & FIF_PROMISC_IN_BSS) { - __set_bit(ATH_STAT_PROMISC, sc->status); - } else { - __clear_bit(ATH_STAT_PROMISC, sc->status); - } - } - - if (test_bit(ATH_STAT_PROMISC, sc->status)) - rfilt |= AR5K_RX_FILTER_PROM; - - /* Note, AR5K_RX_FILTER_MCAST is already enabled */ - if (*new_flags & FIF_ALLMULTI) { - mfilt[0] = ~0; - mfilt[1] = ~0; - } - - /* This is the best we can do */ - if (*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)) - rfilt |= AR5K_RX_FILTER_PHYERR; - - /* FIF_BCN_PRBRESP_PROMISC really means to enable beacons - * and probes for any BSSID, this needs testing */ - if (*new_flags & FIF_BCN_PRBRESP_PROMISC) - rfilt |= AR5K_RX_FILTER_BEACON | AR5K_RX_FILTER_PROBEREQ; - - /* FIF_CONTROL doc says that if FIF_PROMISC_IN_BSS is not - * set we should only pass on control frames for this - * station. This needs testing. I believe right now this - * enables *all* control frames, which is OK.. but - * but we should see if we can improve on granularity */ - if (*new_flags & FIF_CONTROL) - rfilt |= AR5K_RX_FILTER_CONTROL; - - /* Additional settings per mode -- this is per ath5k */ - - /* XXX move these to mac80211, and add a beacon IFF flag to mac80211 */ - - switch (sc->opmode) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_MONITOR: - rfilt |= AR5K_RX_FILTER_CONTROL | - AR5K_RX_FILTER_BEACON | - AR5K_RX_FILTER_PROBEREQ | - AR5K_RX_FILTER_PROM; - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_ADHOC: - rfilt |= AR5K_RX_FILTER_PROBEREQ | - AR5K_RX_FILTER_BEACON; - break; - case NL80211_IFTYPE_STATION: - if (sc->assoc) - rfilt |= AR5K_RX_FILTER_BEACON; - default: - break; - } - - /* Set filters */ - ath5k_hw_set_rx_filter(ah, rfilt); - - /* Set multicast bits */ - ath5k_hw_set_mcast_filter(ah, mfilt[0], mfilt[1]); - /* Set the cached hw filter flags, this will alter actually - * be set in HW */ - sc->filter_flags = rfilt; - - mutex_unlock(&sc->lock); -} - -static int -ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath5k_softc *sc = hw->priv; - int ret = 0; - - if (modparam_nohwcrypt) - return -EOPNOTSUPP; - - if (sc->opmode == NL80211_IFTYPE_AP) - return -EOPNOTSUPP; - - switch (key->alg) { - case ALG_WEP: - case ALG_TKIP: - break; - case ALG_CCMP: - if (sc->ah->ah_aes_support) - break; - - return -EOPNOTSUPP; - default: - WARN_ON(1); - return -EINVAL; - } - - mutex_lock(&sc->lock); - - switch (cmd) { - case SET_KEY: - ret = ath5k_hw_set_key(sc->ah, key->keyidx, key, - sta ? sta->addr : NULL); - if (ret) { - ATH5K_ERR(sc, "can't set the key\n"); - goto unlock; - } - __set_bit(key->keyidx, sc->keymap); - key->hw_key_idx = key->keyidx; - key->flags |= (IEEE80211_KEY_FLAG_GENERATE_IV | - IEEE80211_KEY_FLAG_GENERATE_MMIC); - break; - case DISABLE_KEY: - ath5k_hw_reset_key(sc->ah, key->keyidx); - __clear_bit(key->keyidx, sc->keymap); - break; - default: - ret = -EINVAL; - goto unlock; - } - -unlock: - mmiowb(); - mutex_unlock(&sc->lock); - return ret; -} - -static int -ath5k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - - /* Force update */ - ath5k_hw_update_mib_counters(ah, &sc->ll_stats); - - memcpy(stats, &sc->ll_stats, sizeof(sc->ll_stats)); - - return 0; -} - -static int -ath5k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct ath5k_softc *sc = hw->priv; - - memcpy(stats, &sc->tx_stats, sizeof(sc->tx_stats)); - - return 0; -} - -static u64 -ath5k_get_tsf(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - return ath5k_hw_get_tsf64(sc->ah); -} - -static void -ath5k_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct ath5k_softc *sc = hw->priv; - - ath5k_hw_set_tsf64(sc->ah, tsf); -} - -static void -ath5k_reset_tsf(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - - /* - * in IBSS mode we need to update the beacon timers too. - * this will also reset the TSF if we call it with 0 - */ - if (sc->opmode == NL80211_IFTYPE_ADHOC) - ath5k_beacon_update_timers(sc, 0); - else - ath5k_hw_reset_tsf(sc->ah); -} - -/* - * Updates the beacon that is sent by ath5k_beacon_send. For adhoc, - * this is called only once at config_bss time, for AP we do it every - * SWBA interrupt so that the TIM will reflect buffered frames. - * - * Called with the beacon lock. - */ -static int -ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif) -{ - int ret; - struct ath5k_softc *sc = hw->priv; - struct sk_buff *skb; - - if (WARN_ON(!vif)) { - ret = -EINVAL; - goto out; - } - - skb = ieee80211_beacon_get(hw, vif); - - if (!skb) { - ret = -ENOMEM; - goto out; - } - - ath5k_debug_dump_skb(sc, skb, "BC ", 1); - - ath5k_txbuf_free(sc, sc->bbuf); - sc->bbuf->skb = skb; - ret = ath5k_beacon_setup(sc, sc->bbuf); - if (ret) - sc->bbuf->skb = NULL; -out: - return ret; -} - -static void -set_beacon_filter(struct ieee80211_hw *hw, bool enable) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - u32 rfilt; - rfilt = ath5k_hw_get_rx_filter(ah); - if (enable) - rfilt |= AR5K_RX_FILTER_BEACON; - else - rfilt &= ~AR5K_RX_FILTER_BEACON; - ath5k_hw_set_rx_filter(ah, rfilt); - sc->filter_flags = rfilt; -} - -static void ath5k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct ath5k_softc *sc = hw->priv; - struct ath5k_hw *ah = sc->ah; - unsigned long flags; - - mutex_lock(&sc->lock); - if (WARN_ON(sc->vif != vif)) - goto unlock; - - if (changes & BSS_CHANGED_BSSID) { - /* Cache for later use during resets */ - memcpy(ah->ah_bssid, bss_conf->bssid, ETH_ALEN); - /* XXX: assoc id is set to 0 for now, mac80211 doesn't have - * a clean way of letting us retrieve this yet. */ - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - mmiowb(); - } - - if (changes & BSS_CHANGED_BEACON_INT) - sc->bintval = bss_conf->beacon_int; - - if (changes & BSS_CHANGED_ASSOC) { - sc->assoc = bss_conf->assoc; - if (sc->opmode == NL80211_IFTYPE_STATION) - set_beacon_filter(hw, sc->assoc); - ath5k_hw_set_ledstate(sc->ah, sc->assoc ? - AR5K_LED_ASSOC : AR5K_LED_INIT); - } - - if (changes & BSS_CHANGED_BEACON) { - spin_lock_irqsave(&sc->block, flags); - ath5k_beacon_update(hw, vif); - spin_unlock_irqrestore(&sc->block, flags); - } - - if (changes & BSS_CHANGED_BEACON_ENABLED) - sc->enable_beacon = bss_conf->enable_beacon; - - if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED | - BSS_CHANGED_BEACON_INT)) - ath5k_beacon_config(sc); - - unlock: - mutex_unlock(&sc->lock); -} - -static void ath5k_sw_scan_start(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - if (!sc->assoc) - ath5k_hw_set_ledstate(sc->ah, AR5K_LED_SCAN); -} - -static void ath5k_sw_scan_complete(struct ieee80211_hw *hw) -{ - struct ath5k_softc *sc = hw->priv; - ath5k_hw_set_ledstate(sc->ah, sc->assoc ? - AR5K_LED_ASSOC : AR5K_LED_INIT); -} diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h deleted file mode 100644 index a28c42f32c9d..000000000000 --- a/drivers/net/wireless/ath/ath5k/base.h +++ /dev/null @@ -1,216 +0,0 @@ -/*- - * Copyright (c) 2002-2007 Sam Leffler, Errno Consulting - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -/* - * Defintions for the Atheros Wireless LAN controller driver. - */ -#ifndef _DEV_ATH_ATHVAR_H -#define _DEV_ATH_ATHVAR_H - -#include -#include -#include -#include -#include -#include - -#include "ath5k.h" -#include "debug.h" - -#include "../regd.h" -#include "../ath.h" - -#define ATH_RXBUF 40 /* number of RX buffers */ -#define ATH_TXBUF 200 /* number of TX buffers */ -#define ATH_BCBUF 1 /* number of beacon buffers */ - -struct ath5k_buf { - struct list_head list; - struct ath5k_desc *desc; /* virtual addr of desc */ - dma_addr_t daddr; /* physical addr of desc */ - struct sk_buff *skb; /* skbuff for buf */ - dma_addr_t skbaddr;/* physical addr of skb data */ -}; - -/* - * Data transmit queue state. One of these exists for each - * hardware transmit queue. Packets sent to us from above - * are assigned to queues based on their priority. Not all - * devices support a complete set of hardware transmit queues. - * For those devices the array sc_ac2q will map multiple - * priorities to fewer hardware queues (typically all to one - * hardware queue). - */ -struct ath5k_txq { - unsigned int qnum; /* hardware q number */ - u32 *link; /* link ptr in last TX desc */ - struct list_head q; /* transmit queue */ - spinlock_t lock; /* lock on q and link */ - bool setup; -}; - -#define ATH5K_LED_MAX_NAME_LEN 31 - -/* - * State for LED triggers - */ -struct ath5k_led -{ - char name[ATH5K_LED_MAX_NAME_LEN + 1]; /* name of the LED in sysfs */ - struct ath5k_softc *sc; /* driver state */ - struct led_classdev led_dev; /* led classdev */ -}; - -/* Rfkill */ -struct ath5k_rfkill { - /* GPIO PIN for rfkill */ - u16 gpio; - /* polarity of rfkill GPIO PIN */ - bool polarity; - /* RFKILL toggle tasklet */ - struct tasklet_struct toggleq; -}; - -#if CHAN_DEBUG -#define ATH_CHAN_MAX (26+26+26+200+200) -#else -#define ATH_CHAN_MAX (14+14+14+252+20) -#endif - -/* Software Carrier, keeps track of the driver state - * associated with an instance of a device */ -struct ath5k_softc { - struct pci_dev *pdev; /* for dma mapping */ - struct ath_common common; - void __iomem *iobase; /* address of the device */ - struct mutex lock; /* dev-level lock */ - struct ieee80211_tx_queue_stats tx_stats[AR5K_NUM_TX_QUEUES]; - struct ieee80211_low_level_stats ll_stats; - struct ieee80211_hw *hw; /* IEEE 802.11 common */ - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - struct ieee80211_channel channels[ATH_CHAN_MAX]; - struct ieee80211_rate rates[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - s8 rate_idx[IEEE80211_NUM_BANDS][AR5K_MAX_RATES]; - enum nl80211_iftype opmode; - struct ath5k_hw *ah; /* Atheros HW */ - - struct ieee80211_supported_band *curband; - -#ifdef CONFIG_ATH5K_DEBUG - struct ath5k_dbg_info debug; /* debug info */ -#endif /* CONFIG_ATH5K_DEBUG */ - - struct ath5k_buf *bufptr; /* allocated buffer ptr */ - struct ath5k_desc *desc; /* TX/RX descriptors */ - dma_addr_t desc_daddr; /* DMA (physical) address */ - size_t desc_len; /* size of TX/RX descriptors */ - - DECLARE_BITMAP(status, 5); -#define ATH_STAT_INVALID 0 /* disable hardware accesses */ -#define ATH_STAT_MRRETRY 1 /* multi-rate retry support */ -#define ATH_STAT_PROMISC 2 -#define ATH_STAT_LEDSOFT 3 /* enable LED gpio status */ -#define ATH_STAT_STARTED 4 /* opened & irqs enabled */ - - unsigned int filter_flags; /* HW flags, AR5K_RX_FILTER_* */ - unsigned int curmode; /* current phy mode */ - struct ieee80211_channel *curchan; /* current h/w channel */ - - struct ieee80211_vif *vif; - - enum ath5k_int imask; /* interrupt mask copy */ - - DECLARE_BITMAP(keymap, AR5K_KEYCACHE_SIZE); /* key use bit map */ - - u8 bssidmask[ETH_ALEN]; - - unsigned int led_pin, /* GPIO pin for driving LED */ - led_on; /* pin setting for LED on */ - - struct tasklet_struct restq; /* reset tasklet */ - - unsigned int rxbufsize; /* rx size based on mtu */ - struct list_head rxbuf; /* receive buffer */ - spinlock_t rxbuflock; - u32 *rxlink; /* link ptr in last RX desc */ - struct tasklet_struct rxtq; /* rx intr tasklet */ - struct ath5k_led rx_led; /* rx led */ - - struct list_head txbuf; /* transmit buffer */ - spinlock_t txbuflock; - unsigned int txbuf_len; /* buf count in txbuf list */ - struct ath5k_txq txqs[AR5K_NUM_TX_QUEUES]; /* tx queues */ - struct ath5k_txq *txq; /* main tx queue */ - struct tasklet_struct txtq; /* tx intr tasklet */ - struct ath5k_led tx_led; /* tx led */ - - struct ath5k_rfkill rf_kill; - - struct tasklet_struct calib; /* calibration tasklet */ - - spinlock_t block; /* protects beacon */ - struct tasklet_struct beacontq; /* beacon intr tasklet */ - struct ath5k_buf *bbuf; /* beacon buffer */ - unsigned int bhalq, /* SW q for outgoing beacons */ - bmisscount, /* missed beacon transmits */ - bintval, /* beacon interval in TU */ - bsent; - unsigned int nexttbtt; /* next beacon time in TU */ - struct ath5k_txq *cabq; /* content after beacon */ - - int power_level; /* Requested tx power in dbm */ - bool assoc; /* assocate state */ - bool enable_beacon; /* true if beacons are on */ -}; - -#define ath5k_hw_hasbssidmask(_ah) \ - (ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0) -#define ath5k_hw_hasveol(_ah) \ - (ath5k_hw_get_capability(_ah, AR5K_CAP_VEOL, 0, NULL) == 0) - -static inline struct ath_common *ath5k_hw_common(struct ath5k_hw *ah) -{ - return &ah->ah_sc->common; -} - -static inline struct ath_regulatory *ath5k_hw_regulatory(struct ath5k_hw *ah) -{ - return &(ath5k_hw_common(ah)->regulatory); - -} - -#endif diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c deleted file mode 100644 index 367a6c7d3cc7..000000000000 --- a/drivers/net/wireless/ath/ath5k/caps.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/**************\ -* Capabilities * -\**************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Fill the capabilities struct - * TODO: Merge this with EEPROM code when we are done with it - */ -int ath5k_hw_set_capabilities(struct ath5k_hw *ah) -{ - u16 ee_header; - - ATH5K_TRACE(ah->ah_sc); - /* Capabilities stored in the EEPROM */ - ee_header = ah->ah_capabilities.cap_eeprom.ee_header; - - if (ah->ah_version == AR5K_AR5210) { - /* - * Set radio capabilities - * (The AR5110 only supports the middle 5GHz band) - */ - ah->ah_capabilities.cap_range.range_5ghz_min = 5120; - ah->ah_capabilities.cap_range.range_5ghz_max = 5430; - ah->ah_capabilities.cap_range.range_2ghz_min = 0; - ah->ah_capabilities.cap_range.range_2ghz_max = 0; - - /* Set supported modes */ - __set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, ah->ah_capabilities.cap_mode); - } else { - /* - * XXX The tranceiver supports frequencies from 4920 to 6100GHz - * XXX and from 2312 to 2732GHz. There are problems with the - * XXX current ieee80211 implementation because the IEEE - * XXX channel mapping does not support negative channel - * XXX numbers (2312MHz is channel -19). Of course, this - * XXX doesn't matter because these channels are out of range - * XXX but some regulation domains like MKK (Japan) will - * XXX support frequencies somewhere around 4.8GHz. - */ - - /* - * Set radio capabilities - */ - - if (AR5K_EEPROM_HDR_11A(ee_header)) { - /* 4920 */ - ah->ah_capabilities.cap_range.range_5ghz_min = 5005; - ah->ah_capabilities.cap_range.range_5ghz_max = 6100; - - /* Set supported modes */ - __set_bit(AR5K_MODE_11A, - ah->ah_capabilities.cap_mode); - __set_bit(AR5K_MODE_11A_TURBO, - ah->ah_capabilities.cap_mode); - if (ah->ah_version == AR5K_AR5212) - __set_bit(AR5K_MODE_11G_TURBO, - ah->ah_capabilities.cap_mode); - } - - /* Enable 802.11b if a 2GHz capable radio (2111/5112) is - * connected */ - if (AR5K_EEPROM_HDR_11B(ee_header) || - (AR5K_EEPROM_HDR_11G(ee_header) && - ah->ah_version != AR5K_AR5211)) { - /* 2312 */ - ah->ah_capabilities.cap_range.range_2ghz_min = 2412; - ah->ah_capabilities.cap_range.range_2ghz_max = 2732; - - if (AR5K_EEPROM_HDR_11B(ee_header)) - __set_bit(AR5K_MODE_11B, - ah->ah_capabilities.cap_mode); - - if (AR5K_EEPROM_HDR_11G(ee_header) && - ah->ah_version != AR5K_AR5211) - __set_bit(AR5K_MODE_11G, - ah->ah_capabilities.cap_mode); - } - } - - /* GPIO */ - ah->ah_gpio_npins = AR5K_NUM_GPIO; - - /* Set number of supported TX queues */ - if (ah->ah_version == AR5K_AR5210) - ah->ah_capabilities.cap_queues.q_tx_num = - AR5K_NUM_TX_QUEUES_NOQCU; - else - ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES; - - return 0; -} - -/* Main function used by the driver part to check caps */ -int ath5k_hw_get_capability(struct ath5k_hw *ah, - enum ath5k_capability_type cap_type, - u32 capability, u32 *result) -{ - ATH5K_TRACE(ah->ah_sc); - - switch (cap_type) { - case AR5K_CAP_NUM_TXQUEUES: - if (result) { - if (ah->ah_version == AR5K_AR5210) - *result = AR5K_NUM_TX_QUEUES_NOQCU; - else - *result = AR5K_NUM_TX_QUEUES; - goto yes; - } - case AR5K_CAP_VEOL: - goto yes; - case AR5K_CAP_COMPRESSION: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - case AR5K_CAP_BURST: - goto yes; - case AR5K_CAP_TPC: - goto yes; - case AR5K_CAP_BSSIDMASK: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - case AR5K_CAP_XR: - if (ah->ah_version == AR5K_AR5212) - goto yes; - else - goto no; - default: - goto no; - } - -no: - return -EINVAL; -yes: - return 0; -} - -/* - * TODO: Following functions should be part of a new function - * set_capability - */ - -int ath5k_hw_enable_pspoll(struct ath5k_hw *ah, u8 *bssid, - u16 assoc_id) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); - return 0; - } - - return -EIO; -} - -int ath5k_hw_disable_pspoll(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_NO_PSPOLL | AR5K_STA_ID1_DEFAULT_ANTENNA); - return 0; - } - - return -EIO; -} diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c deleted file mode 100644 index 747508c15d34..000000000000 --- a/drivers/net/wireless/ath/ath5k/debug.c +++ /dev/null @@ -1,540 +0,0 @@ -/* - * Copyright (c) 2007-2008 Bruno Randolf - * - * This file is free software: you may copy, redistribute 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 file 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, see . - * - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2006 Devicescape Software, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2007 Luis R. Rodriguez - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -#include "base.h" -#include "debug.h" - -static unsigned int ath5k_debug; -module_param_named(debug, ath5k_debug, uint, 0); - - -#ifdef CONFIG_ATH5K_DEBUG - -#include -#include "reg.h" - -static struct dentry *ath5k_global_debugfs; - -static int ath5k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - - -/* debugfs: registers */ - -struct reg { - const char *name; - int addr; -}; - -#define REG_STRUCT_INIT(r) { #r, r } - -/* just a few random registers, might want to add more */ -static const struct reg regs[] = { - REG_STRUCT_INIT(AR5K_CR), - REG_STRUCT_INIT(AR5K_RXDP), - REG_STRUCT_INIT(AR5K_CFG), - REG_STRUCT_INIT(AR5K_IER), - REG_STRUCT_INIT(AR5K_BCR), - REG_STRUCT_INIT(AR5K_RTSD0), - REG_STRUCT_INIT(AR5K_RTSD1), - REG_STRUCT_INIT(AR5K_TXCFG), - REG_STRUCT_INIT(AR5K_RXCFG), - REG_STRUCT_INIT(AR5K_RXJLA), - REG_STRUCT_INIT(AR5K_MIBC), - REG_STRUCT_INIT(AR5K_TOPS), - REG_STRUCT_INIT(AR5K_RXNOFRM), - REG_STRUCT_INIT(AR5K_TXNOFRM), - REG_STRUCT_INIT(AR5K_RPGTO), - REG_STRUCT_INIT(AR5K_RFCNT), - REG_STRUCT_INIT(AR5K_MISC), - REG_STRUCT_INIT(AR5K_QCUDCU_CLKGT), - REG_STRUCT_INIT(AR5K_ISR), - REG_STRUCT_INIT(AR5K_PISR), - REG_STRUCT_INIT(AR5K_SISR0), - REG_STRUCT_INIT(AR5K_SISR1), - REG_STRUCT_INIT(AR5K_SISR2), - REG_STRUCT_INIT(AR5K_SISR3), - REG_STRUCT_INIT(AR5K_SISR4), - REG_STRUCT_INIT(AR5K_IMR), - REG_STRUCT_INIT(AR5K_PIMR), - REG_STRUCT_INIT(AR5K_SIMR0), - REG_STRUCT_INIT(AR5K_SIMR1), - REG_STRUCT_INIT(AR5K_SIMR2), - REG_STRUCT_INIT(AR5K_SIMR3), - REG_STRUCT_INIT(AR5K_SIMR4), - REG_STRUCT_INIT(AR5K_DCM_ADDR), - REG_STRUCT_INIT(AR5K_DCCFG), - REG_STRUCT_INIT(AR5K_CCFG), - REG_STRUCT_INIT(AR5K_CPC0), - REG_STRUCT_INIT(AR5K_CPC1), - REG_STRUCT_INIT(AR5K_CPC2), - REG_STRUCT_INIT(AR5K_CPC3), - REG_STRUCT_INIT(AR5K_CPCOVF), - REG_STRUCT_INIT(AR5K_RESET_CTL), - REG_STRUCT_INIT(AR5K_SLEEP_CTL), - REG_STRUCT_INIT(AR5K_INTPEND), - REG_STRUCT_INIT(AR5K_SFR), - REG_STRUCT_INIT(AR5K_PCICFG), - REG_STRUCT_INIT(AR5K_GPIOCR), - REG_STRUCT_INIT(AR5K_GPIODO), - REG_STRUCT_INIT(AR5K_SREV), -}; - -static void *reg_start(struct seq_file *seq, loff_t *pos) -{ - return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; -} - -static void reg_stop(struct seq_file *seq, void *p) -{ - /* nothing to do */ -} - -static void *reg_next(struct seq_file *seq, void *p, loff_t *pos) -{ - ++*pos; - return *pos < ARRAY_SIZE(regs) ? (void *)®s[*pos] : NULL; -} - -static int reg_show(struct seq_file *seq, void *p) -{ - struct ath5k_softc *sc = seq->private; - struct reg *r = p; - seq_printf(seq, "%-25s0x%08x\n", r->name, - ath5k_hw_reg_read(sc->ah, r->addr)); - return 0; -} - -static const struct seq_operations register_seq_ops = { - .start = reg_start, - .next = reg_next, - .stop = reg_stop, - .show = reg_show -}; - -static int open_file_registers(struct inode *inode, struct file *file) -{ - struct seq_file *s; - int res; - res = seq_open(file, ®ister_seq_ops); - if (res == 0) { - s = file->private_data; - s->private = inode->i_private; - } - return res; -} - -static const struct file_operations fops_registers = { - .open = open_file_registers, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, - .owner = THIS_MODULE, -}; - - -/* debugfs: beacons */ - -static ssize_t read_file_beacon(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - struct ath5k_hw *ah = sc->ah; - char buf[500]; - unsigned int len = 0; - unsigned int v; - u64 tsf; - - v = ath5k_hw_reg_read(sc->ah, AR5K_BEACON); - len += snprintf(buf+len, sizeof(buf)-len, - "%-24s0x%08x\tintval: %d\tTIM: 0x%x\n", - "AR5K_BEACON", v, v & AR5K_BEACON_PERIOD, - (v & AR5K_BEACON_TIM) >> AR5K_BEACON_TIM_S); - - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n", - "AR5K_LAST_TSTP", ath5k_hw_reg_read(sc->ah, AR5K_LAST_TSTP)); - - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\n\n", - "AR5K_BEACON_CNT", ath5k_hw_reg_read(sc->ah, AR5K_BEACON_CNT)); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER0); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER0 (TBTT)", v, v); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER1); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER1 (DMA)", v, v >> 3); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER2); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER2 (SWBA)", v, v >> 3); - - v = ath5k_hw_reg_read(sc->ah, AR5K_TIMER3); - len += snprintf(buf+len, sizeof(buf)-len, "%-24s0x%08x\tTU: %08x\n", - "AR5K_TIMER3 (ATIM)", v, v); - - tsf = ath5k_hw_get_tsf64(sc->ah); - len += snprintf(buf+len, sizeof(buf)-len, - "TSF\t\t0x%016llx\tTU: %08x\n", - (unsigned long long)tsf, TSF_TO_TU(tsf)); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_beacon(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - struct ath5k_hw *ah = sc->ah; - char buf[20]; - - if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) - return -EFAULT; - - if (strncmp(buf, "disable", 7) == 0) { - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); - printk(KERN_INFO "debugfs disable beacons\n"); - } else if (strncmp(buf, "enable", 6) == 0) { - AR5K_REG_ENABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE); - printk(KERN_INFO "debugfs enable beacons\n"); - } - return count; -} - -static const struct file_operations fops_beacon = { - .read = read_file_beacon, - .write = write_file_beacon, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - -/* debugfs: reset */ - -static ssize_t write_file_reset(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - tasklet_schedule(&sc->restq); - return count; -} - -static const struct file_operations fops_reset = { - .write = write_file_reset, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - -/* debugfs: debug level */ - -static const struct { - enum ath5k_debug_level level; - const char *name; - const char *desc; -} dbg_info[] = { - { ATH5K_DEBUG_RESET, "reset", "reset and initialization" }, - { ATH5K_DEBUG_INTR, "intr", "interrupt handling" }, - { ATH5K_DEBUG_MODE, "mode", "mode init/setup" }, - { ATH5K_DEBUG_XMIT, "xmit", "basic xmit operation" }, - { ATH5K_DEBUG_BEACON, "beacon", "beacon handling" }, - { ATH5K_DEBUG_CALIBRATE, "calib", "periodic calibration" }, - { ATH5K_DEBUG_TXPOWER, "txpower", "transmit power setting" }, - { ATH5K_DEBUG_LED, "led", "LED management" }, - { ATH5K_DEBUG_DUMP_RX, "dumprx", "print received skb content" }, - { ATH5K_DEBUG_DUMP_TX, "dumptx", "print transmit skb content" }, - { ATH5K_DEBUG_DUMPBANDS, "dumpbands", "dump bands" }, - { ATH5K_DEBUG_TRACE, "trace", "trace function calls" }, - { ATH5K_DEBUG_ANY, "all", "show all debug levels" }, -}; - -static ssize_t read_file_debug(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - char buf[700]; - unsigned int len = 0; - unsigned int i; - - len += snprintf(buf+len, sizeof(buf)-len, - "DEBUG LEVEL: 0x%08x\n\n", sc->debug.level); - - for (i = 0; i < ARRAY_SIZE(dbg_info) - 1; i++) { - len += snprintf(buf+len, sizeof(buf)-len, - "%10s %c 0x%08x - %s\n", dbg_info[i].name, - sc->debug.level & dbg_info[i].level ? '+' : ' ', - dbg_info[i].level, dbg_info[i].desc); - } - len += snprintf(buf+len, sizeof(buf)-len, - "%10s %c 0x%08x - %s\n", dbg_info[i].name, - sc->debug.level == dbg_info[i].level ? '+' : ' ', - dbg_info[i].level, dbg_info[i].desc); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_debug(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct ath5k_softc *sc = file->private_data; - unsigned int i; - char buf[20]; - - if (copy_from_user(buf, userbuf, min(count, sizeof(buf)))) - return -EFAULT; - - for (i = 0; i < ARRAY_SIZE(dbg_info); i++) { - if (strncmp(buf, dbg_info[i].name, - strlen(dbg_info[i].name)) == 0) { - sc->debug.level ^= dbg_info[i].level; /* toggle bit */ - break; - } - } - return count; -} - -static const struct file_operations fops_debug = { - .read = read_file_debug, - .write = write_file_debug, - .open = ath5k_debugfs_open, - .owner = THIS_MODULE, -}; - - -/* init */ - -void -ath5k_debug_init(void) -{ - ath5k_global_debugfs = debugfs_create_dir("ath5k", NULL); -} - -void -ath5k_debug_init_device(struct ath5k_softc *sc) -{ - sc->debug.level = ath5k_debug; - - sc->debug.debugfs_phydir = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath5k_global_debugfs); - - sc->debug.debugfs_debug = debugfs_create_file("debug", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_debug); - - sc->debug.debugfs_registers = debugfs_create_file("registers", S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_registers); - - sc->debug.debugfs_beacon = debugfs_create_file("beacon", - S_IWUSR | S_IRUSR, - sc->debug.debugfs_phydir, sc, &fops_beacon); - - sc->debug.debugfs_reset = debugfs_create_file("reset", S_IWUSR, - sc->debug.debugfs_phydir, sc, &fops_reset); -} - -void -ath5k_debug_finish(void) -{ - debugfs_remove(ath5k_global_debugfs); -} - -void -ath5k_debug_finish_device(struct ath5k_softc *sc) -{ - debugfs_remove(sc->debug.debugfs_debug); - debugfs_remove(sc->debug.debugfs_registers); - debugfs_remove(sc->debug.debugfs_beacon); - debugfs_remove(sc->debug.debugfs_reset); - debugfs_remove(sc->debug.debugfs_phydir); -} - - -/* functions used in other places */ - -void -ath5k_debug_dump_bands(struct ath5k_softc *sc) -{ - unsigned int b, i; - - if (likely(!(sc->debug.level & ATH5K_DEBUG_DUMPBANDS))) - return; - - BUG_ON(!sc->sbands); - - for (b = 0; b < IEEE80211_NUM_BANDS; b++) { - struct ieee80211_supported_band *band = &sc->sbands[b]; - char bname[6]; - switch (band->band) { - case IEEE80211_BAND_2GHZ: - strcpy(bname, "2 GHz"); - break; - case IEEE80211_BAND_5GHZ: - strcpy(bname, "5 GHz"); - break; - default: - printk(KERN_DEBUG "Band not supported: %d\n", - band->band); - return; - } - printk(KERN_DEBUG "Band %s: channels %d, rates %d\n", bname, - band->n_channels, band->n_bitrates); - printk(KERN_DEBUG " channels:\n"); - for (i = 0; i < band->n_channels; i++) - printk(KERN_DEBUG " %3d %d %.4x %.4x\n", - ieee80211_frequency_to_channel( - band->channels[i].center_freq), - band->channels[i].center_freq, - band->channels[i].hw_value, - band->channels[i].flags); - printk(KERN_DEBUG " rates:\n"); - for (i = 0; i < band->n_bitrates; i++) - printk(KERN_DEBUG " %4d %.4x %.4x %.4x\n", - band->bitrates[i].bitrate, - band->bitrates[i].hw_value, - band->bitrates[i].flags, - band->bitrates[i].hw_value_short); - } -} - -static inline void -ath5k_debug_printrxbuf(struct ath5k_buf *bf, int done, - struct ath5k_rx_status *rs) -{ - struct ath5k_desc *ds = bf->desc; - struct ath5k_hw_all_rx_desc *rd = &ds->ud.ds_rx; - - printk(KERN_DEBUG "R (%p %llx) %08x %08x %08x %08x %08x %08x %c\n", - ds, (unsigned long long)bf->daddr, - ds->ds_link, ds->ds_data, - rd->rx_ctl.rx_control_0, rd->rx_ctl.rx_control_1, - rd->u.rx_stat.rx_status_0, rd->u.rx_stat.rx_status_0, - !done ? ' ' : (rs->rs_status == 0) ? '*' : '!'); -} - -void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) -{ - struct ath5k_desc *ds; - struct ath5k_buf *bf; - struct ath5k_rx_status rs = {}; - int status; - - if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) - return; - - printk(KERN_DEBUG "rx queue %x, link %p\n", - ath5k_hw_get_rxdp(ah), sc->rxlink); - - spin_lock_bh(&sc->rxbuflock); - list_for_each_entry(bf, &sc->rxbuf, list) { - ds = bf->desc; - status = ah->ah_proc_rx_desc(ah, ds, &rs); - if (!status) - ath5k_debug_printrxbuf(bf, status == 0, &rs); - } - spin_unlock_bh(&sc->rxbuflock); -} - -void -ath5k_debug_dump_skb(struct ath5k_softc *sc, - struct sk_buff *skb, const char *prefix, int tx) -{ - char buf[16]; - - if (likely(!((tx && (sc->debug.level & ATH5K_DEBUG_DUMP_TX)) || - (!tx && (sc->debug.level & ATH5K_DEBUG_DUMP_RX))))) - return; - - snprintf(buf, sizeof(buf), "%s %s", wiphy_name(sc->hw->wiphy), prefix); - - print_hex_dump_bytes(buf, DUMP_PREFIX_NONE, skb->data, - min(200U, skb->len)); - - printk(KERN_DEBUG "\n"); -} - -void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) -{ - struct ath5k_desc *ds = bf->desc; - struct ath5k_hw_5212_tx_desc *td = &ds->ud.ds_tx5212; - struct ath5k_tx_status ts = {}; - int done; - - if (likely(!(sc->debug.level & ATH5K_DEBUG_RESET))) - return; - - done = sc->ah->ah_proc_tx_desc(sc->ah, bf->desc, &ts); - - printk(KERN_DEBUG "T (%p %llx) %08x %08x %08x %08x %08x %08x %08x " - "%08x %c\n", ds, (unsigned long long)bf->daddr, ds->ds_link, - ds->ds_data, td->tx_ctl.tx_control_0, td->tx_ctl.tx_control_1, - td->tx_ctl.tx_control_2, td->tx_ctl.tx_control_3, - td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, - done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); -} - -#endif /* ifdef CONFIG_ATH5K_DEBUG */ diff --git a/drivers/net/wireless/ath/ath5k/debug.h b/drivers/net/wireless/ath/ath5k/debug.h deleted file mode 100644 index 66f69f04e55e..000000000000 --- a/drivers/net/wireless/ath/ath5k/debug.h +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright (c) 2007 Bruno Randolf - * - * This file is free software: you may copy, redistribute 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 file 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, see . - * - * - * This file incorporates work covered by the following copyright and - * permission notice: - * - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2006 Devicescape Software, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2007 Luis R. Rodriguez - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -#ifndef _ATH5K_DEBUG_H -#define _ATH5K_DEBUG_H - -struct ath5k_softc; -struct ath5k_hw; -struct sk_buff; -struct ath5k_buf; - -struct ath5k_dbg_info { - unsigned int level; /* debug level */ - /* debugfs entries */ - struct dentry *debugfs_phydir; - struct dentry *debugfs_debug; - struct dentry *debugfs_registers; - struct dentry *debugfs_beacon; - struct dentry *debugfs_reset; -}; - -/** - * enum ath5k_debug_level - ath5k debug level - * - * @ATH5K_DEBUG_RESET: reset processing - * @ATH5K_DEBUG_INTR: interrupt handling - * @ATH5K_DEBUG_MODE: mode init/setup - * @ATH5K_DEBUG_XMIT: basic xmit operation - * @ATH5K_DEBUG_BEACON: beacon handling - * @ATH5K_DEBUG_CALIBRATE: periodic calibration - * @ATH5K_DEBUG_TXPOWER: transmit power setting - * @ATH5K_DEBUG_LED: led management - * @ATH5K_DEBUG_DUMP_RX: print received skb content - * @ATH5K_DEBUG_DUMP_TX: print transmit skb content - * @ATH5K_DEBUG_DUMPBANDS: dump bands - * @ATH5K_DEBUG_TRACE: trace function calls - * @ATH5K_DEBUG_ANY: show at any debug level - * - * The debug level is used to control the amount and type of debugging output - * we want to see. The debug level is given in calls to ATH5K_DBG to specify - * where the message should appear, and the user can control the debugging - * messages he wants to see, either by the module parameter 'debug' on module - * load, or dynamically by using debugfs 'ath5k/phyX/debug'. these levels can - * be combined together by bitwise OR. - */ -enum ath5k_debug_level { - ATH5K_DEBUG_RESET = 0x00000001, - ATH5K_DEBUG_INTR = 0x00000002, - ATH5K_DEBUG_MODE = 0x00000004, - ATH5K_DEBUG_XMIT = 0x00000008, - ATH5K_DEBUG_BEACON = 0x00000010, - ATH5K_DEBUG_CALIBRATE = 0x00000020, - ATH5K_DEBUG_TXPOWER = 0x00000040, - ATH5K_DEBUG_LED = 0x00000080, - ATH5K_DEBUG_DUMP_RX = 0x00000100, - ATH5K_DEBUG_DUMP_TX = 0x00000200, - ATH5K_DEBUG_DUMPBANDS = 0x00000400, - ATH5K_DEBUG_TRACE = 0x00001000, - ATH5K_DEBUG_ANY = 0xffffffff -}; - -#ifdef CONFIG_ATH5K_DEBUG - -#define ATH5K_TRACE(_sc) do { \ - if (unlikely((_sc)->debug.level & ATH5K_DEBUG_TRACE)) \ - printk(KERN_DEBUG "ath5k trace %s:%d\n", __func__, __LINE__); \ - } while (0) - -#define ATH5K_DBG(_sc, _m, _fmt, ...) do { \ - if (unlikely((_sc)->debug.level & (_m) && net_ratelimit())) \ - ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ - __func__, __LINE__, ##__VA_ARGS__); \ - } while (0) - -#define ATH5K_DBG_UNLIMIT(_sc, _m, _fmt, ...) do { \ - if (unlikely((_sc)->debug.level & (_m))) \ - ATH5K_PRINTK(_sc, KERN_DEBUG, "(%s:%d): " _fmt, \ - __func__, __LINE__, ##__VA_ARGS__); \ - } while (0) - -void -ath5k_debug_init(void); - -void -ath5k_debug_init_device(struct ath5k_softc *sc); - -void -ath5k_debug_finish(void); - -void -ath5k_debug_finish_device(struct ath5k_softc *sc); - -void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah); - -void -ath5k_debug_dump_bands(struct ath5k_softc *sc); - -void -ath5k_debug_dump_skb(struct ath5k_softc *sc, - struct sk_buff *skb, const char *prefix, int tx); - -void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf); - -#else /* no debugging */ - -#include - -#define ATH5K_TRACE(_sc) typecheck(struct ath5k_softc *, (_sc)) - -static inline void __attribute__ ((format (printf, 3, 4))) -ATH5K_DBG(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) {} - -static inline void __attribute__ ((format (printf, 3, 4))) -ATH5K_DBG_UNLIMIT(struct ath5k_softc *sc, unsigned int m, const char *fmt, ...) -{} - -static inline void -ath5k_debug_init(void) {} - -static inline void -ath5k_debug_init_device(struct ath5k_softc *sc) {} - -static inline void -ath5k_debug_finish(void) {} - -static inline void -ath5k_debug_finish_device(struct ath5k_softc *sc) {} - -static inline void -ath5k_debug_printrxbuffs(struct ath5k_softc *sc, struct ath5k_hw *ah) {} - -static inline void -ath5k_debug_dump_bands(struct ath5k_softc *sc) {} - -static inline void -ath5k_debug_dump_skb(struct ath5k_softc *sc, - struct sk_buff *skb, const char *prefix, int tx) {} - -static inline void -ath5k_debug_printtxbuf(struct ath5k_softc *sc, struct ath5k_buf *bf) {} - -#endif /* ifdef CONFIG_ATH5K_DEBUG */ - -#endif /* ifndef _ATH5K_DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c deleted file mode 100644 index dc30a2b70a6b..000000000000 --- a/drivers/net/wireless/ath/ath5k/desc.c +++ /dev/null @@ -1,696 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Pavel Roskin - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/******************************\ - Hardware Descriptor Functions -\******************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * TX Descriptors - */ - -/* - * Initialize the 2-word tx control descriptor on 5210/5211 - */ -static int -ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int pkt_len, unsigned int hdr_len, enum ath5k_pkt_type type, - unsigned int tx_power, unsigned int tx_rate0, unsigned int tx_tries0, - unsigned int key_index, unsigned int antenna_mode, unsigned int flags, - unsigned int rtscts_rate, unsigned int rtscts_duration) -{ - u32 frame_type; - struct ath5k_hw_2w_tx_ctl *tx_ctl; - unsigned int frame_len; - - tx_ctl = &desc->ud.ds_tx5210.tx_ctl; - - /* - * Validate input - * - Zero retries don't make sense. - * - A zero rate will put the HW into a mode where it continously sends - * noise on the channel, so it is important to avoid this. - */ - if (unlikely(tx_tries0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero retries\n"); - WARN_ON(1); - return -EINVAL; - } - if (unlikely(tx_rate0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); - WARN_ON(1); - return -EINVAL; - } - - /* Clear descriptor */ - memset(&desc->ud.ds_tx5210, 0, sizeof(struct ath5k_hw_5210_tx_desc)); - - /* Setup control descriptor */ - - /* Verify and set frame length */ - - /* remove padding we might have added before */ - frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; - - if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) - return -EINVAL; - - tx_ctl->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; - - /* Verify and set buffer length */ - - /* NB: beacon's BufLen must be a multiple of 4 bytes */ - if (type == AR5K_PKT_TYPE_BEACON) - pkt_len = roundup(pkt_len, 4); - - if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) - return -EINVAL; - - tx_ctl->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; - - /* - * Verify and set header length - * XXX: I only found that on 5210 code, does it work on 5211 ? - */ - if (ah->ah_version == AR5K_AR5210) { - if (hdr_len & ~AR5K_2W_TX_DESC_CTL0_HEADER_LEN) - return -EINVAL; - tx_ctl->tx_control_0 |= - AR5K_REG_SM(hdr_len, AR5K_2W_TX_DESC_CTL0_HEADER_LEN); - } - - /*Diferences between 5210-5211*/ - if (ah->ah_version == AR5K_AR5210) { - switch (type) { - case AR5K_PKT_TYPE_BEACON: - case AR5K_PKT_TYPE_PROBE_RESP: - frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY; - case AR5K_PKT_TYPE_PIFS: - frame_type = AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS; - default: - frame_type = type /*<< 2 ?*/; - } - - tx_ctl->tx_control_0 |= - AR5K_REG_SM(frame_type, AR5K_2W_TX_DESC_CTL0_FRAME_TYPE) | - AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE); - - } else { - tx_ctl->tx_control_0 |= - AR5K_REG_SM(tx_rate0, AR5K_2W_TX_DESC_CTL0_XMIT_RATE) | - AR5K_REG_SM(antenna_mode, - AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_ctl->tx_control_1 |= - AR5K_REG_SM(type, AR5K_2W_TX_DESC_CTL1_FRAME_TYPE); - } -#define _TX_FLAGS(_c, _flag) \ - if (flags & AR5K_TXDESC_##_flag) { \ - tx_ctl->tx_control_##_c |= \ - AR5K_2W_TX_DESC_CTL##_c##_##_flag; \ - } - - _TX_FLAGS(0, CLRDMASK); - _TX_FLAGS(0, VEOL); - _TX_FLAGS(0, INTREQ); - _TX_FLAGS(0, RTSENA); - _TX_FLAGS(1, NOACK); - -#undef _TX_FLAGS - - /* - * WEP crap - */ - if (key_index != AR5K_TXKEYIX_INVALID) { - tx_ctl->tx_control_0 |= - AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_ctl->tx_control_1 |= - AR5K_REG_SM(key_index, - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); - } - - /* - * RTS/CTS Duration [5210 ?] - */ - if ((ah->ah_version == AR5K_AR5210) && - (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA))) - tx_ctl->tx_control_1 |= rtscts_duration & - AR5K_2W_TX_DESC_CTL1_RTS_DURATION; - - return 0; -} - -/* - * Initialize the 4-word tx control descriptor on 5212 - */ -static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, - struct ath5k_desc *desc, unsigned int pkt_len, unsigned int hdr_len, - enum ath5k_pkt_type type, unsigned int tx_power, unsigned int tx_rate0, - unsigned int tx_tries0, unsigned int key_index, - unsigned int antenna_mode, unsigned int flags, - unsigned int rtscts_rate, - unsigned int rtscts_duration) -{ - struct ath5k_hw_4w_tx_ctl *tx_ctl; - unsigned int frame_len; - - ATH5K_TRACE(ah->ah_sc); - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; - - /* - * Validate input - * - Zero retries don't make sense. - * - A zero rate will put the HW into a mode where it continously sends - * noise on the channel, so it is important to avoid this. - */ - if (unlikely(tx_tries0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero retries\n"); - WARN_ON(1); - return -EINVAL; - } - if (unlikely(tx_rate0 == 0)) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); - WARN_ON(1); - return -EINVAL; - } - - tx_power += ah->ah_txpower.txp_offset; - if (tx_power > AR5K_TUNE_MAX_TXPOWER) - tx_power = AR5K_TUNE_MAX_TXPOWER; - - /* Clear descriptor */ - memset(&desc->ud.ds_tx5212, 0, sizeof(struct ath5k_hw_5212_tx_desc)); - - /* Setup control descriptor */ - - /* Verify and set frame length */ - - /* remove padding we might have added before */ - frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; - - if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) - return -EINVAL; - - tx_ctl->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; - - /* Verify and set buffer length */ - - /* NB: beacon's BufLen must be a multiple of 4 bytes */ - if (type == AR5K_PKT_TYPE_BEACON) - pkt_len = roundup(pkt_len, 4); - - if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) - return -EINVAL; - - tx_ctl->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; - - tx_ctl->tx_control_0 |= - AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | - AR5K_REG_SM(antenna_mode, AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT); - tx_ctl->tx_control_1 |= AR5K_REG_SM(type, - AR5K_4W_TX_DESC_CTL1_FRAME_TYPE); - tx_ctl->tx_control_2 = AR5K_REG_SM(tx_tries0 + AR5K_TUNE_HWTXTRIES, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0); - tx_ctl->tx_control_3 = tx_rate0 & AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; - -#define _TX_FLAGS(_c, _flag) \ - if (flags & AR5K_TXDESC_##_flag) { \ - tx_ctl->tx_control_##_c |= \ - AR5K_4W_TX_DESC_CTL##_c##_##_flag; \ - } - - _TX_FLAGS(0, CLRDMASK); - _TX_FLAGS(0, VEOL); - _TX_FLAGS(0, INTREQ); - _TX_FLAGS(0, RTSENA); - _TX_FLAGS(0, CTSENA); - _TX_FLAGS(1, NOACK); - -#undef _TX_FLAGS - - /* - * WEP crap - */ - if (key_index != AR5K_TXKEYIX_INVALID) { - tx_ctl->tx_control_0 |= AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID; - tx_ctl->tx_control_1 |= AR5K_REG_SM(key_index, - AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX); - } - - /* - * RTS/CTS - */ - if (flags & (AR5K_TXDESC_RTSENA | AR5K_TXDESC_CTSENA)) { - if ((flags & AR5K_TXDESC_RTSENA) && - (flags & AR5K_TXDESC_CTSENA)) - return -EINVAL; - tx_ctl->tx_control_2 |= rtscts_duration & - AR5K_4W_TX_DESC_CTL2_RTS_DURATION; - tx_ctl->tx_control_3 |= AR5K_REG_SM(rtscts_rate, - AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE); - } - - return 0; -} - -/* - * Initialize a 4-word multi rate retry tx control descriptor on 5212 - */ -static int -ath5k_hw_setup_mrr_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, - u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) -{ - struct ath5k_hw_4w_tx_ctl *tx_ctl; - - /* - * Rates can be 0 as long as the retry count is 0 too. - * A zero rate and nonzero retry count will put the HW into a mode where - * it continously sends noise on the channel, so it is important to - * avoid this. - */ - if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) || - (tx_rate2 == 0 && tx_tries2 != 0) || - (tx_rate3 == 0 && tx_tries3 != 0))) { - ATH5K_ERR(ah->ah_sc, "zero rate\n"); - WARN_ON(1); - return -EINVAL; - } - - if (ah->ah_version == AR5K_AR5212) { - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; - -#define _XTX_TRIES(_n) \ - if (tx_tries##_n) { \ - tx_ctl->tx_control_2 |= \ - AR5K_REG_SM(tx_tries##_n, \ - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES##_n); \ - tx_ctl->tx_control_3 |= \ - AR5K_REG_SM(tx_rate##_n, \ - AR5K_4W_TX_DESC_CTL3_XMIT_RATE##_n); \ - } - - _XTX_TRIES(1); - _XTX_TRIES(2); - _XTX_TRIES(3); - -#undef _XTX_TRIES - - return 1; - } - - return 0; -} - -/* no mrr support for cards older than 5212 */ -static int -ath5k_hw_setup_no_mrr(struct ath5k_hw *ah, struct ath5k_desc *desc, - unsigned int tx_rate1, u_int tx_tries1, u_int tx_rate2, - u_int tx_tries2, unsigned int tx_rate3, u_int tx_tries3) -{ - return 0; -} - -/* - * Proccess the tx status descriptor on 5210/5211 - */ -static int ath5k_hw_proc_2word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_tx_status *ts) -{ - struct ath5k_hw_2w_tx_ctl *tx_ctl; - struct ath5k_hw_tx_status *tx_status; - - ATH5K_TRACE(ah->ah_sc); - - tx_ctl = &desc->ud.ds_tx5210.tx_ctl; - tx_status = &desc->ud.ds_tx5210.tx_stat; - - /* No frame has been send or error */ - if (unlikely((tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE) == 0)) - return -EINPROGRESS; - - /* - * Get descriptor status - */ - ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - /*TODO: ts->ts_virtcol + test*/ - ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_SEQ_NUM); - ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - ts->ts_antenna = 1; - ts->ts_status = 0; - ts->ts_rate[0] = AR5K_REG_MS(tx_ctl->tx_control_0, - AR5K_2W_TX_DESC_CTL0_XMIT_RATE); - ts->ts_retry[0] = ts->ts_longretry; - ts->ts_final_idx = 0; - - if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { - if (tx_status->tx_status_0 & - AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) - ts->ts_status |= AR5K_TXERR_XRETRY; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) - ts->ts_status |= AR5K_TXERR_FIFO; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) - ts->ts_status |= AR5K_TXERR_FILT; - } - - return 0; -} - -/* - * Proccess a tx status descriptor on 5212 - */ -static int ath5k_hw_proc_4word_tx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_tx_status *ts) -{ - struct ath5k_hw_4w_tx_ctl *tx_ctl; - struct ath5k_hw_tx_status *tx_status; - - ATH5K_TRACE(ah->ah_sc); - - tx_ctl = &desc->ud.ds_tx5212.tx_ctl; - tx_status = &desc->ud.ds_tx5212.tx_stat; - - /* No frame has been send or error */ - if (unlikely(!(tx_status->tx_status_1 & AR5K_DESC_TX_STATUS1_DONE))) - return -EINPROGRESS; - - /* - * Get descriptor status - */ - ts->ts_tstamp = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP); - ts->ts_shortretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT); - ts->ts_longretry = AR5K_REG_MS(tx_status->tx_status_0, - AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT); - ts->ts_seqnum = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_SEQ_NUM); - ts->ts_rssi = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH); - ts->ts_antenna = (tx_status->tx_status_1 & - AR5K_DESC_TX_STATUS1_XMIT_ANTENNA) ? 2 : 1; - ts->ts_status = 0; - - ts->ts_final_idx = AR5K_REG_MS(tx_status->tx_status_1, - AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX); - - /* The longretry counter has the number of un-acked retries - * for the final rate. To get the total number of retries - * we have to add the retry counters for the other rates - * as well - */ - ts->ts_retry[ts->ts_final_idx] = ts->ts_longretry; - switch (ts->ts_final_idx) { - case 3: - ts->ts_rate[3] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE3); - - ts->ts_retry[2] = AR5K_REG_MS(tx_ctl->tx_control_2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2); - ts->ts_longretry += ts->ts_retry[2]; - /* fall through */ - case 2: - ts->ts_rate[2] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE2); - - ts->ts_retry[1] = AR5K_REG_MS(tx_ctl->tx_control_2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); - ts->ts_longretry += ts->ts_retry[1]; - /* fall through */ - case 1: - ts->ts_rate[1] = AR5K_REG_MS(tx_ctl->tx_control_3, - AR5K_4W_TX_DESC_CTL3_XMIT_RATE1); - - ts->ts_retry[0] = AR5K_REG_MS(tx_ctl->tx_control_2, - AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1); - ts->ts_longretry += ts->ts_retry[0]; - /* fall through */ - case 0: - ts->ts_rate[0] = tx_ctl->tx_control_3 & - AR5K_4W_TX_DESC_CTL3_XMIT_RATE0; - break; - } - - /* TX error */ - if (!(tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK)) { - if (tx_status->tx_status_0 & - AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES) - ts->ts_status |= AR5K_TXERR_XRETRY; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN) - ts->ts_status |= AR5K_TXERR_FIFO; - - if (tx_status->tx_status_0 & AR5K_DESC_TX_STATUS0_FILTERED) - ts->ts_status |= AR5K_TXERR_FILT; - } - - return 0; -} - -/* - * RX Descriptors - */ - -/* - * Initialize an rx control descriptor - */ -static int ath5k_hw_setup_rx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, - u32 size, unsigned int flags) -{ - struct ath5k_hw_rx_ctl *rx_ctl; - - ATH5K_TRACE(ah->ah_sc); - rx_ctl = &desc->ud.ds_rx.rx_ctl; - - /* - * Clear the descriptor - * If we don't clean the status descriptor, - * while scanning we get too many results, - * most of them virtual, after some secs - * of scanning system hangs. M.F. - */ - memset(&desc->ud.ds_rx, 0, sizeof(struct ath5k_hw_all_rx_desc)); - - /* Setup descriptor */ - rx_ctl->rx_control_1 = size & AR5K_DESC_RX_CTL1_BUF_LEN; - if (unlikely(rx_ctl->rx_control_1 != size)) - return -EINVAL; - - if (flags & AR5K_RXDESC_INTREQ) - rx_ctl->rx_control_1 |= AR5K_DESC_RX_CTL1_INTREQ; - - return 0; -} - -/* - * Proccess the rx status descriptor on 5210/5211 - */ -static int ath5k_hw_proc_5210_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_rx_status *rs) -{ - struct ath5k_hw_rx_status *rx_status; - - rx_status = &desc->ud.ds_rx.u.rx_stat; - - /* No frame received / not ready */ - if (unlikely(!(rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_DONE))) - return -EINPROGRESS; - - /* - * Frame receive status - */ - rs->rs_datalen = rx_status->rx_status_0 & - AR5K_5210_RX_DESC_STATUS0_DATA_LEN; - rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL); - rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA); - rs->rs_more = !!(rx_status->rx_status_0 & - AR5K_5210_RX_DESC_STATUS0_MORE); - /* TODO: this timestamp is 13 bit, later on we assume 15 bit */ - rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - rs->rs_status = 0; - rs->rs_phyerr = 0; - - /* - * Key table status - */ - if (rx_status->rx_status_1 & AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID) - rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_KEY_INDEX); - else - rs->rs_keyix = AR5K_RXKEYIX_INVALID; - - /* - * Receive/descriptor errors - */ - if (!(rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_CRC; - - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN) - rs->rs_status |= AR5K_RXERR_FIFO; - - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_PHY_ERROR) { - rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr |= AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5210_RX_DESC_STATUS1_PHY_ERROR); - } - - if (rx_status->rx_status_1 & - AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_DECRYPT; - } - - return 0; -} - -/* - * Proccess the rx status descriptor on 5212 - */ -static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah, - struct ath5k_desc *desc, struct ath5k_rx_status *rs) -{ - struct ath5k_hw_rx_status *rx_status; - struct ath5k_hw_rx_error *rx_err; - - ATH5K_TRACE(ah->ah_sc); - rx_status = &desc->ud.ds_rx.u.rx_stat; - - /* Overlay on error */ - rx_err = &desc->ud.ds_rx.u.rx_err; - - /* No frame received / not ready */ - if (unlikely(!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DONE))) - return -EINPROGRESS; - - /* - * Frame receive status - */ - rs->rs_datalen = rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_DATA_LEN; - rs->rs_rssi = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL); - rs->rs_rate = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE); - rs->rs_antenna = AR5K_REG_MS(rx_status->rx_status_0, - AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA); - rs->rs_more = !!(rx_status->rx_status_0 & - AR5K_5212_RX_DESC_STATUS0_MORE); - rs->rs_tstamp = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP); - rs->rs_status = 0; - rs->rs_phyerr = 0; - - /* - * Key table status - */ - if (rx_status->rx_status_1 & AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID) - rs->rs_keyix = AR5K_REG_MS(rx_status->rx_status_1, - AR5K_5212_RX_DESC_STATUS1_KEY_INDEX); - else - rs->rs_keyix = AR5K_RXKEYIX_INVALID; - - /* - * Receive/descriptor errors - */ - if (!(rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK)) { - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_CRC; - - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_PHY_ERROR) { - rs->rs_status |= AR5K_RXERR_PHY; - rs->rs_phyerr |= AR5K_REG_MS(rx_err->rx_error_1, - AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE); - } - - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR) - rs->rs_status |= AR5K_RXERR_DECRYPT; - - if (rx_status->rx_status_1 & - AR5K_5212_RX_DESC_STATUS1_MIC_ERROR) - rs->rs_status |= AR5K_RXERR_MIC; - } - - return 0; -} - -/* - * Init function pointers inside ath5k_hw struct - */ -int ath5k_hw_init_desc_functions(struct ath5k_hw *ah) -{ - - if (ah->ah_version != AR5K_AR5210 && - ah->ah_version != AR5K_AR5211 && - ah->ah_version != AR5K_AR5212) - return -ENOTSUPP; - - /* XXX: What is this magic value and where is it used ? */ - if (ah->ah_version == AR5K_AR5212) - ah->ah_magic = AR5K_EEPROM_MAGIC_5212; - else if (ah->ah_version == AR5K_AR5211) - ah->ah_magic = AR5K_EEPROM_MAGIC_5211; - - if (ah->ah_version == AR5K_AR5212) { - ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; - ah->ah_setup_tx_desc = ath5k_hw_setup_4word_tx_desc; - ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_mrr_tx_desc; - ah->ah_proc_tx_desc = ath5k_hw_proc_4word_tx_status; - } else { - ah->ah_setup_rx_desc = ath5k_hw_setup_rx_desc; - ah->ah_setup_tx_desc = ath5k_hw_setup_2word_tx_desc; - ah->ah_setup_mrr_tx_desc = ath5k_hw_setup_no_mrr; - ah->ah_proc_tx_desc = ath5k_hw_proc_2word_tx_status; - } - - if (ah->ah_version == AR5K_AR5212) - ah->ah_proc_rx_desc = ath5k_hw_proc_5212_rx_status; - else if (ah->ah_version <= AR5K_AR5211) - ah->ah_proc_rx_desc = ath5k_hw_proc_5210_rx_status; - - return 0; -} - diff --git a/drivers/net/wireless/ath/ath5k/desc.h b/drivers/net/wireless/ath/ath5k/desc.h deleted file mode 100644 index 56158c804e3e..000000000000 --- a/drivers/net/wireless/ath/ath5k/desc.h +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Internal RX/TX descriptor structures - * (rX: reserved fields possibily used by future versions of the ar5k chipset) - */ - -/* - * common hardware RX control descriptor - */ -struct ath5k_hw_rx_ctl { - u32 rx_control_0; /* RX control word 0 */ - u32 rx_control_1; /* RX control word 1 */ -} __packed; - -/* RX control word 0 field/sflags */ -#define AR5K_DESC_RX_CTL0 0x00000000 - -/* RX control word 1 fields/flags */ -#define AR5K_DESC_RX_CTL1_BUF_LEN 0x00000fff -#define AR5K_DESC_RX_CTL1_INTREQ 0x00002000 - -/* - * common hardware RX status descriptor - * 5210/11 and 5212 differ only in the flags defined below - */ -struct ath5k_hw_rx_status { - u32 rx_status_0; /* RX status word 0 */ - u32 rx_status_1; /* RX status word 1 */ -} __packed; - -/* 5210/5211 */ -/* RX status word 0 fields/flags */ -#define AR5K_5210_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_5210_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE 0x00078000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x07f80000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 19 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA 0x38000000 -#define AR5K_5210_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 27 - -/* RX status word 1 fields/flags */ -#define AR5K_5210_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_5210_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_5210_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_5210_RX_DESC_STATUS1_FIFO_OVERRUN 0x00000008 -#define AR5K_5210_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000010 -#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR 0x000000e0 -#define AR5K_5210_RX_DESC_STATUS1_PHY_ERROR_S 5 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX 0x00007e00 -#define AR5K_5210_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x0fff8000 -#define AR5K_5210_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 15 -#define AR5K_5210_RX_DESC_STATUS1_KEY_CACHE_MISS 0x10000000 - -/* 5212 */ -/* RX status word 0 fields/flags */ -#define AR5K_5212_RX_DESC_STATUS0_DATA_LEN 0x00000fff -#define AR5K_5212_RX_DESC_STATUS0_MORE 0x00001000 -#define AR5K_5212_RX_DESC_STATUS0_DECOMP_CRC_ERROR 0x00002000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE 0x000f8000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_RATE_S 15 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL 0x0ff00000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_SIGNAL_S 20 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA 0xf0000000 -#define AR5K_5212_RX_DESC_STATUS0_RECEIVE_ANTENNA_S 28 - -/* RX status word 1 fields/flags */ -#define AR5K_5212_RX_DESC_STATUS1_DONE 0x00000001 -#define AR5K_5212_RX_DESC_STATUS1_FRAME_RECEIVE_OK 0x00000002 -#define AR5K_5212_RX_DESC_STATUS1_CRC_ERROR 0x00000004 -#define AR5K_5212_RX_DESC_STATUS1_DECRYPT_CRC_ERROR 0x00000008 -#define AR5K_5212_RX_DESC_STATUS1_PHY_ERROR 0x00000010 -#define AR5K_5212_RX_DESC_STATUS1_MIC_ERROR 0x00000020 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_VALID 0x00000100 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX 0x0000fe00 -#define AR5K_5212_RX_DESC_STATUS1_KEY_INDEX_S 9 -#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP 0x7fff0000 -#define AR5K_5212_RX_DESC_STATUS1_RECEIVE_TIMESTAMP_S 16 -#define AR5K_5212_RX_DESC_STATUS1_KEY_CACHE_MISS 0x80000000 - -/* - * common hardware RX error descriptor - */ -struct ath5k_hw_rx_error { - u32 rx_error_0; /* RX status word 0 */ - u32 rx_error_1; /* RX status word 1 */ -} __packed; - -/* RX error word 0 fields/flags */ -#define AR5K_RX_DESC_ERROR0 0x00000000 - -/* RX error word 1 fields/flags */ -#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE 0x0000ff00 -#define AR5K_RX_DESC_ERROR1_PHY_ERROR_CODE_S 8 - -/* PHY Error codes */ -#define AR5K_DESC_RX_PHY_ERROR_NONE 0x00 -#define AR5K_DESC_RX_PHY_ERROR_TIMING 0x20 -#define AR5K_DESC_RX_PHY_ERROR_PARITY 0x40 -#define AR5K_DESC_RX_PHY_ERROR_RATE 0x60 -#define AR5K_DESC_RX_PHY_ERROR_LENGTH 0x80 -#define AR5K_DESC_RX_PHY_ERROR_64QAM 0xa0 -#define AR5K_DESC_RX_PHY_ERROR_SERVICE 0xc0 -#define AR5K_DESC_RX_PHY_ERROR_TRANSMITOVR 0xe0 - -/* - * 5210/5211 hardware 2-word TX control descriptor - */ -struct ath5k_hw_2w_tx_ctl { - u32 tx_control_0; /* TX control word 0 */ - u32 tx_control_1; /* TX control word 1 */ -} __packed; - -/* TX control word 0 fields/flags */ -#define AR5K_2W_TX_DESC_CTL0_FRAME_LEN 0x00000fff -#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN 0x0003f000 /*[5210 ?]*/ -#define AR5K_2W_TX_DESC_CTL0_HEADER_LEN_S 12 -#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE 0x003c0000 -#define AR5K_2W_TX_DESC_CTL0_XMIT_RATE_S 18 -#define AR5K_2W_TX_DESC_CTL0_RTSENA 0x00400000 -#define AR5K_2W_TX_DESC_CTL0_CLRDMASK 0x01000000 -#define AR5K_2W_TX_DESC_CTL0_LONG_PACKET 0x00800000 /*[5210]*/ -#define AR5K_2W_TX_DESC_CTL0_VEOL 0x00800000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE 0x1c000000 /*[5210]*/ -#define AR5K_2W_TX_DESC_CTL0_FRAME_TYPE_S 26 -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 0x02000000 -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211 0x1e000000 - -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT \ - (ah->ah_version == AR5K_AR5210 ? \ - AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5210 : \ - AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_5211) - -#define AR5K_2W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 -#define AR5K_2W_TX_DESC_CTL0_INTREQ 0x20000000 -#define AR5K_2W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 - -/* TX control word 1 fields/flags */ -#define AR5K_2W_TX_DESC_CTL1_BUF_LEN 0x00000fff -#define AR5K_2W_TX_DESC_CTL1_MORE 0x00001000 -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 0x0007e000 -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211 0x000fe000 - -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX \ - (ah->ah_version == AR5K_AR5210 ? \ - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5210 : \ - AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_5211) - -#define AR5K_2W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 -#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE 0x00700000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL1_FRAME_TYPE_S 20 -#define AR5K_2W_TX_DESC_CTL1_NOACK 0x00800000 /*[5211]*/ -#define AR5K_2W_TX_DESC_CTL1_RTS_DURATION 0xfff80000 /*[5210 ?]*/ - -/* Frame types */ -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NORMAL 0x00 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_ATIM 0x04 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PSPOLL 0x08 -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_NO_DELAY 0x0c -#define AR5K_AR5210_TX_DESC_FRAME_TYPE_PIFS 0x10 - -/* - * 5212 hardware 4-word TX control descriptor - */ -struct ath5k_hw_4w_tx_ctl { - u32 tx_control_0; /* TX control word 0 */ - -#define AR5K_4W_TX_DESC_CTL0_FRAME_LEN 0x00000fff -#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER 0x003f0000 -#define AR5K_4W_TX_DESC_CTL0_XMIT_POWER_S 16 -#define AR5K_4W_TX_DESC_CTL0_RTSENA 0x00400000 -#define AR5K_4W_TX_DESC_CTL0_VEOL 0x00800000 -#define AR5K_4W_TX_DESC_CTL0_CLRDMASK 0x01000000 -#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT 0x1e000000 -#define AR5K_4W_TX_DESC_CTL0_ANT_MODE_XMIT_S 25 -#define AR5K_4W_TX_DESC_CTL0_INTREQ 0x20000000 -#define AR5K_4W_TX_DESC_CTL0_ENCRYPT_KEY_VALID 0x40000000 -#define AR5K_4W_TX_DESC_CTL0_CTSENA 0x80000000 - - u32 tx_control_1; /* TX control word 1 */ - -#define AR5K_4W_TX_DESC_CTL1_BUF_LEN 0x00000fff -#define AR5K_4W_TX_DESC_CTL1_MORE 0x00001000 -#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX 0x000fe000 -#define AR5K_4W_TX_DESC_CTL1_ENCRYPT_KEY_INDEX_S 13 -#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE 0x00f00000 -#define AR5K_4W_TX_DESC_CTL1_FRAME_TYPE_S 20 -#define AR5K_4W_TX_DESC_CTL1_NOACK 0x01000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_PROC 0x06000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_PROC_S 25 -#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN 0x18000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_IV_LEN_S 27 -#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN 0x60000000 -#define AR5K_4W_TX_DESC_CTL1_COMP_ICV_LEN_S 29 - - u32 tx_control_2; /* TX control word 2 */ - -#define AR5K_4W_TX_DESC_CTL2_RTS_DURATION 0x00007fff -#define AR5K_4W_TX_DESC_CTL2_DURATION_UPDATE_ENABLE 0x00008000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0 0x000f0000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES0_S 16 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1 0x00f00000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES1_S 20 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2 0x0f000000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES2_S 24 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3 0xf0000000 -#define AR5K_4W_TX_DESC_CTL2_XMIT_TRIES3_S 28 - - u32 tx_control_3; /* TX control word 3 */ - -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE0 0x0000001f -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1 0x000003e0 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE1_S 5 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2 0x00007c00 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE2_S 10 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3 0x000f8000 -#define AR5K_4W_TX_DESC_CTL3_XMIT_RATE3_S 15 -#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE 0x01f00000 -#define AR5K_4W_TX_DESC_CTL3_RTS_CTS_RATE_S 20 -} __packed; - -/* - * Common TX status descriptor - */ -struct ath5k_hw_tx_status { - u32 tx_status_0; /* TX status word 0 */ - u32 tx_status_1; /* TX status word 1 */ -} __packed; - -/* TX status word 0 fields/flags */ -#define AR5K_DESC_TX_STATUS0_FRAME_XMIT_OK 0x00000001 -#define AR5K_DESC_TX_STATUS0_EXCESSIVE_RETRIES 0x00000002 -#define AR5K_DESC_TX_STATUS0_FIFO_UNDERRUN 0x00000004 -#define AR5K_DESC_TX_STATUS0_FILTERED 0x00000008 -/*??? -#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT 0x000000f0 -#define AR5K_DESC_TX_STATUS0_RTS_FAIL_COUNT_S 4 -*/ -#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT 0x000000f0 -#define AR5K_DESC_TX_STATUS0_SHORT_RETRY_COUNT_S 4 -/*??? -#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT 0x00000f00 -#define AR5K_DESC_TX_STATUS0_DATA_FAIL_COUNT_S 8 -*/ -#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT 0x00000f00 -#define AR5K_DESC_TX_STATUS0_LONG_RETRY_COUNT_S 8 -#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT 0x0000f000 -#define AR5K_DESC_TX_STATUS0_VIRT_COLL_COUNT_S 12 -#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP 0xffff0000 -#define AR5K_DESC_TX_STATUS0_SEND_TIMESTAMP_S 16 - -/* TX status word 1 fields/flags */ -#define AR5K_DESC_TX_STATUS1_DONE 0x00000001 -#define AR5K_DESC_TX_STATUS1_SEQ_NUM 0x00001ffe -#define AR5K_DESC_TX_STATUS1_SEQ_NUM_S 1 -#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH 0x001fe000 -#define AR5K_DESC_TX_STATUS1_ACK_SIG_STRENGTH_S 13 -#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX 0x00600000 -#define AR5K_DESC_TX_STATUS1_FINAL_TS_INDEX_S 21 -#define AR5K_DESC_TX_STATUS1_COMP_SUCCESS 0x00800000 -#define AR5K_DESC_TX_STATUS1_XMIT_ANTENNA 0x01000000 - -/* - * 5210/5211 hardware TX descriptor - */ -struct ath5k_hw_5210_tx_desc { - struct ath5k_hw_2w_tx_ctl tx_ctl; - struct ath5k_hw_tx_status tx_stat; -} __packed; - -/* - * 5212 hardware TX descriptor - */ -struct ath5k_hw_5212_tx_desc { - struct ath5k_hw_4w_tx_ctl tx_ctl; - struct ath5k_hw_tx_status tx_stat; -} __packed; - -/* - * common hardware RX descriptor - */ -struct ath5k_hw_all_rx_desc { - struct ath5k_hw_rx_ctl rx_ctl; - union { - struct ath5k_hw_rx_status rx_stat; - struct ath5k_hw_rx_error rx_err; - } u; -} __packed; - -/* - * Atheros hardware descriptor - * This is read and written to by the hardware - */ -struct ath5k_desc { - u32 ds_link; /* physical address of the next descriptor */ - u32 ds_data; /* physical address of data buffer (skb) */ - - union { - struct ath5k_hw_5210_tx_desc ds_tx5210; - struct ath5k_hw_5212_tx_desc ds_tx5212; - struct ath5k_hw_all_rx_desc ds_rx; - } ud; -} __packed; - -#define AR5K_RXDESC_INTREQ 0x0020 - -#define AR5K_TXDESC_CLRDMASK 0x0001 -#define AR5K_TXDESC_NOACK 0x0002 /*[5211+]*/ -#define AR5K_TXDESC_RTSENA 0x0004 -#define AR5K_TXDESC_CTSENA 0x0008 -#define AR5K_TXDESC_INTREQ 0x0010 -#define AR5K_TXDESC_VEOL 0x0020 /*[5211+]*/ - diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c deleted file mode 100644 index 941b51130a6f..000000000000 --- a/drivers/net/wireless/ath/ath5k/dma.c +++ /dev/null @@ -1,703 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*************************************\ -* DMA and interrupt masking functions * -\*************************************/ - -/* - * dma.c - DMA and interrupt masking functions - * - * Here we setup descriptor pointers (rxdp/txdp) start/stop dma engine and - * handle queue setup for 5210 chipset (rest are handled on qcu.c). - * Also we setup interrupt mask register (IMR) and read the various iterrupt - * status registers (ISR). - * - * TODO: Handle SISR on 5211+ and introduce a function to return the queue - * number that resulted the interrupt. - */ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/*********\ -* Receive * -\*********/ - -/** - * ath5k_hw_start_rx_dma - Start DMA receive - * - * @ah: The &struct ath5k_hw - */ -void ath5k_hw_start_rx_dma(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - ath5k_hw_reg_write(ah, AR5K_CR_RXE, AR5K_CR); - ath5k_hw_reg_read(ah, AR5K_CR); -} - -/** - * ath5k_hw_stop_rx_dma - Stop DMA receive - * - * @ah: The &struct ath5k_hw - */ -int ath5k_hw_stop_rx_dma(struct ath5k_hw *ah) -{ - unsigned int i; - - ATH5K_TRACE(ah->ah_sc); - ath5k_hw_reg_write(ah, AR5K_CR_RXD, AR5K_CR); - - /* - * It may take some time to disable the DMA receive unit - */ - for (i = 1000; i > 0 && - (ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_CR_RXE) != 0; - i--) - udelay(10); - - return i ? 0 : -EBUSY; -} - -/** - * ath5k_hw_get_rxdp - Get RX Descriptor's address - * - * @ah: The &struct ath5k_hw - */ -u32 ath5k_hw_get_rxdp(struct ath5k_hw *ah) -{ - return ath5k_hw_reg_read(ah, AR5K_RXDP); -} - -/** - * ath5k_hw_set_rxdp - Set RX Descriptor's address - * - * @ah: The &struct ath5k_hw - * @phys_addr: RX descriptor address - * - * XXX: Should we check if rx is enabled before setting rxdp ? - */ -void ath5k_hw_set_rxdp(struct ath5k_hw *ah, u32 phys_addr) -{ - ATH5K_TRACE(ah->ah_sc); - - ath5k_hw_reg_write(ah, phys_addr, AR5K_RXDP); -} - - -/**********\ -* Transmit * -\**********/ - -/** - * ath5k_hw_start_tx_dma - Start DMA transmit for a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Start DMA transmit for a specific queue and since 5210 doesn't have - * QCU/DCU, set up queue parameters for 5210 here based on queue type (one - * queue for normal data and one queue for beacons). For queue setup - * on newer chips check out qcu.c. Returns -EINVAL if queue number is out - * of range or if queue is already disabled. - * - * NOTE: Must be called after setting up tx control descriptor for that - * queue (see below). - */ -int ath5k_hw_start_tx_dma(struct ath5k_hw *ah, unsigned int queue) -{ - u32 tx_queue; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; - - if (ah->ah_version == AR5K_AR5210) { - tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); - - /* - * Set the queue by type on 5210 - */ - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_queue |= AR5K_CR_TXE0 & ~AR5K_CR_TXD0; - break; - case AR5K_TX_QUEUE_BEACON: - tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, - AR5K_BSR); - break; - case AR5K_TX_QUEUE_CAB: - tx_queue |= AR5K_CR_TXE1 & ~AR5K_CR_TXD1; - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1FV | AR5K_BCR_TQ1V | - AR5K_BCR_BDMAE, AR5K_BSR); - break; - default: - return -EINVAL; - } - /* Start queue */ - ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); - ath5k_hw_reg_read(ah, AR5K_CR); - } else { - /* Return if queue is disabled */ - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXD, queue)) - return -EIO; - - /* Start queue */ - AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXE, queue); - } - - return 0; -} - -/** - * ath5k_hw_stop_tx_dma - Stop DMA transmit on a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Stop DMA transmit on a specific hw queue and drain queue so we don't - * have any pending frames. Returns -EBUSY if we still have pending frames, - * -EINVAL if queue number is out of range. - * - */ -int ath5k_hw_stop_tx_dma(struct ath5k_hw *ah, unsigned int queue) -{ - unsigned int i = 40; - u32 tx_queue, pending; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; - - if (ah->ah_version == AR5K_AR5210) { - tx_queue = ath5k_hw_reg_read(ah, AR5K_CR); - - /* - * Set by queue type - */ - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_queue |= AR5K_CR_TXD0 & ~AR5K_CR_TXE0; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - /* XXX Fix me... */ - tx_queue |= AR5K_CR_TXD1 & ~AR5K_CR_TXD1; - ath5k_hw_reg_write(ah, 0, AR5K_BSR); - break; - default: - return -EINVAL; - } - - /* Stop queue */ - ath5k_hw_reg_write(ah, tx_queue, AR5K_CR); - ath5k_hw_reg_read(ah, AR5K_CR); - } else { - /* - * Schedule TX disable and wait until queue is empty - */ - AR5K_REG_WRITE_Q(ah, AR5K_QCU_TXD, queue); - - /*Check for pending frames*/ - do { - pending = ath5k_hw_reg_read(ah, - AR5K_QUEUE_STATUS(queue)) & - AR5K_QCU_STS_FRMPENDCNT; - udelay(100); - } while (--i && pending); - - /* For 2413+ order PCU to drop packets using - * QUIET mechanism */ - if (ah->ah_mac_version >= (AR5K_SREV_AR2414 >> 4) && - pending){ - /* Set periodicity and duration */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(100, AR5K_QUIET_CTL2_QT_PER)| - AR5K_REG_SM(10, AR5K_QUIET_CTL2_QT_DUR), - AR5K_QUIET_CTL2); - - /* Enable quiet period for current TSF */ - ath5k_hw_reg_write(ah, - AR5K_QUIET_CTL1_QT_EN | - AR5K_REG_SM(ath5k_hw_reg_read(ah, - AR5K_TSF_L32_5211) >> 10, - AR5K_QUIET_CTL1_NEXT_QT_TSF), - AR5K_QUIET_CTL1); - - /* Force channel idle high */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_CHANEL_IDLE_HIGH); - - /* Wait a while and disable mechanism */ - udelay(200); - AR5K_REG_DISABLE_BITS(ah, AR5K_QUIET_CTL1, - AR5K_QUIET_CTL1_QT_EN); - - /* Re-check for pending frames */ - i = 40; - do { - pending = ath5k_hw_reg_read(ah, - AR5K_QUEUE_STATUS(queue)) & - AR5K_QCU_STS_FRMPENDCNT; - udelay(100); - } while (--i && pending); - - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_CHANEL_IDLE_HIGH); - } - - /* Clear register */ - ath5k_hw_reg_write(ah, 0, AR5K_QCU_TXD); - if (pending) - return -EBUSY; - } - - /* TODO: Check for success on 5210 else return error */ - return 0; -} - -/** - * ath5k_hw_get_txdp - Get TX Descriptor's address for a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Get TX descriptor's address for a specific queue. For 5210 we ignore - * the queue number and use tx queue type since we only have 2 queues. - * We use TXDP0 for normal data queue and TXDP1 for beacon queue. - * For newer chips with QCU/DCU we just read the corresponding TXDP register. - * - * XXX: Is TXDP read and clear ? - */ -u32 ath5k_hw_get_txdp(struct ath5k_hw *ah, unsigned int queue) -{ - u16 tx_reg; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* - * Get the transmit queue descriptor pointer from the selected queue - */ - /*5210 doesn't have QCU*/ - if (ah->ah_version == AR5K_AR5210) { - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_reg = AR5K_NOQCU_TXDP0; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - tx_reg = AR5K_NOQCU_TXDP1; - break; - default: - return 0xffffffff; - } - } else { - tx_reg = AR5K_QUEUE_TXDP(queue); - } - - return ath5k_hw_reg_read(ah, tx_reg); -} - -/** - * ath5k_hw_set_txdp - Set TX Descriptor's address for a specific queue - * - * @ah: The &struct ath5k_hw - * @queue: The hw queue number - * - * Set TX descriptor's address for a specific queue. For 5210 we ignore - * the queue number and we use tx queue type since we only have 2 queues - * so as above we use TXDP0 for normal data queue and TXDP1 for beacon queue. - * For newer chips with QCU/DCU we just set the corresponding TXDP register. - * Returns -EINVAL if queue type is invalid for 5210 and -EIO if queue is still - * active. - */ -int ath5k_hw_set_txdp(struct ath5k_hw *ah, unsigned int queue, u32 phys_addr) -{ - u16 tx_reg; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* - * Set the transmit queue descriptor pointer register by type - * on 5210 - */ - if (ah->ah_version == AR5K_AR5210) { - switch (ah->ah_txq[queue].tqi_type) { - case AR5K_TX_QUEUE_DATA: - tx_reg = AR5K_NOQCU_TXDP0; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - tx_reg = AR5K_NOQCU_TXDP1; - break; - default: - return -EINVAL; - } - } else { - /* - * Set the transmit queue descriptor pointer for - * the selected queue on QCU for 5211+ - * (this won't work if the queue is still active) - */ - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - return -EIO; - - tx_reg = AR5K_QUEUE_TXDP(queue); - } - - /* Set descriptor pointer */ - ath5k_hw_reg_write(ah, phys_addr, tx_reg); - - return 0; -} - -/** - * ath5k_hw_update_tx_triglevel - Update tx trigger level - * - * @ah: The &struct ath5k_hw - * @increase: Flag to force increase of trigger level - * - * This function increases/decreases the tx trigger level for the tx fifo - * buffer (aka FIFO threshold) that is used to indicate when PCU flushes - * the buffer and transmits it's data. Lowering this results sending small - * frames more quickly but can lead to tx underruns, raising it a lot can - * result other problems (i think bmiss is related). Right now we start with - * the lowest possible (64Bytes) and if we get tx underrun we increase it using - * the increase flag. Returns -EIO if we have have reached maximum/minimum. - * - * XXX: Link this with tx DMA size ? - * XXX: Use it to save interrupts ? - * TODO: Needs testing, i think it's related to bmiss... - */ -int ath5k_hw_update_tx_triglevel(struct ath5k_hw *ah, bool increase) -{ - u32 trigger_level, imr; - int ret = -EIO; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Disable interrupts by setting the mask - */ - imr = ath5k_hw_set_imr(ah, ah->ah_imr & ~AR5K_INT_GLOBAL); - - trigger_level = AR5K_REG_MS(ath5k_hw_reg_read(ah, AR5K_TXCFG), - AR5K_TXCFG_TXFULL); - - if (!increase) { - if (--trigger_level < AR5K_TUNE_MIN_TX_FIFO_THRES) - goto done; - } else - trigger_level += - ((AR5K_TUNE_MAX_TX_FIFO_THRES - trigger_level) / 2); - - /* - * Update trigger level on success - */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, trigger_level, AR5K_TRIG_LVL); - else - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_TXFULL, trigger_level); - - ret = 0; - -done: - /* - * Restore interrupt mask - */ - ath5k_hw_set_imr(ah, imr); - - return ret; -} - -/*******************\ -* Interrupt masking * -\*******************/ - -/** - * ath5k_hw_is_intr_pending - Check if we have pending interrupts - * - * @ah: The &struct ath5k_hw - * - * Check if we have pending interrupts to process. Returns 1 if we - * have pending interrupts and 0 if we haven't. - */ -bool ath5k_hw_is_intr_pending(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_INTPEND) == 1 ? 1 : 0; -} - -/** - * ath5k_hw_get_isr - Get interrupt status - * - * @ah: The @struct ath5k_hw - * @interrupt_mask: Driver's interrupt mask used to filter out - * interrupts in sw. - * - * This function is used inside our interrupt handler to determine the reason - * for the interrupt by reading Primary Interrupt Status Register. Returns an - * abstract interrupt status mask which is mostly ISR with some uncommon bits - * being mapped on some standard non hw-specific positions - * (check out &ath5k_int). - * - * NOTE: We use read-and-clear register, so after this function is called ISR - * is zeroed. - */ -int ath5k_hw_get_isr(struct ath5k_hw *ah, enum ath5k_int *interrupt_mask) -{ - u32 data; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Read interrupt status from the Interrupt Status register - * on 5210 - */ - if (ah->ah_version == AR5K_AR5210) { - data = ath5k_hw_reg_read(ah, AR5K_ISR); - if (unlikely(data == AR5K_INT_NOCARD)) { - *interrupt_mask = data; - return -ENODEV; - } - } else { - /* - * Read interrupt status from Interrupt - * Status Register shadow copy (Read And Clear) - * - * Note: PISR/SISR Not available on 5210 - */ - data = ath5k_hw_reg_read(ah, AR5K_RAC_PISR); - if (unlikely(data == AR5K_INT_NOCARD)) { - *interrupt_mask = data; - return -ENODEV; - } - } - - /* - * Get abstract interrupt mask (driver-compatible) - */ - *interrupt_mask = (data & AR5K_INT_COMMON) & ah->ah_imr; - - if (ah->ah_version != AR5K_AR5210) { - u32 sisr2 = ath5k_hw_reg_read(ah, AR5K_RAC_SISR2); - - /*HIU = Host Interface Unit (PCI etc)*/ - if (unlikely(data & (AR5K_ISR_HIUERR))) - *interrupt_mask |= AR5K_INT_FATAL; - - /*Beacon Not Ready*/ - if (unlikely(data & (AR5K_ISR_BNR))) - *interrupt_mask |= AR5K_INT_BNR; - - if (unlikely(sisr2 & (AR5K_SISR2_SSERR | - AR5K_SISR2_DPERR | - AR5K_SISR2_MCABT))) - *interrupt_mask |= AR5K_INT_FATAL; - - if (data & AR5K_ISR_TIM) - *interrupt_mask |= AR5K_INT_TIM; - - if (data & AR5K_ISR_BCNMISC) { - if (sisr2 & AR5K_SISR2_TIM) - *interrupt_mask |= AR5K_INT_TIM; - if (sisr2 & AR5K_SISR2_DTIM) - *interrupt_mask |= AR5K_INT_DTIM; - if (sisr2 & AR5K_SISR2_DTIM_SYNC) - *interrupt_mask |= AR5K_INT_DTIM_SYNC; - if (sisr2 & AR5K_SISR2_BCN_TIMEOUT) - *interrupt_mask |= AR5K_INT_BCN_TIMEOUT; - if (sisr2 & AR5K_SISR2_CAB_TIMEOUT) - *interrupt_mask |= AR5K_INT_CAB_TIMEOUT; - } - - if (data & AR5K_ISR_RXDOPPLER) - *interrupt_mask |= AR5K_INT_RX_DOPPLER; - if (data & AR5K_ISR_QCBRORN) { - *interrupt_mask |= AR5K_INT_QCBRORN; - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), - AR5K_SISR3_QCBRORN); - } - if (data & AR5K_ISR_QCBRURN) { - *interrupt_mask |= AR5K_INT_QCBRURN; - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR3), - AR5K_SISR3_QCBRURN); - } - if (data & AR5K_ISR_QTRIG) { - *interrupt_mask |= AR5K_INT_QTRIG; - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR4), - AR5K_SISR4_QTRIG); - } - - if (data & AR5K_ISR_TXOK) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), - AR5K_SISR0_QCU_TXOK); - - if (data & AR5K_ISR_TXDESC) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR0), - AR5K_SISR0_QCU_TXDESC); - - if (data & AR5K_ISR_TXERR) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), - AR5K_SISR1_QCU_TXERR); - - if (data & AR5K_ISR_TXEOL) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR1), - AR5K_SISR1_QCU_TXEOL); - - if (data & AR5K_ISR_TXURN) - ah->ah_txq_isr |= AR5K_REG_MS( - ath5k_hw_reg_read(ah, AR5K_RAC_SISR2), - AR5K_SISR2_QCU_TXURN); - } else { - if (unlikely(data & (AR5K_ISR_SSERR | AR5K_ISR_MCABT - | AR5K_ISR_HIUERR | AR5K_ISR_DPERR))) - *interrupt_mask |= AR5K_INT_FATAL; - - /* - * XXX: BMISS interrupts may occur after association. - * I found this on 5210 code but it needs testing. If this is - * true we should disable them before assoc and re-enable them - * after a successful assoc + some jiffies. - interrupt_mask &= ~AR5K_INT_BMISS; - */ - } - - /* - * In case we didn't handle anything, - * print the register value. - */ - if (unlikely(*interrupt_mask == 0 && net_ratelimit())) - ATH5K_PRINTF("ISR: 0x%08x IMR: 0x%08x\n", data, ah->ah_imr); - - return 0; -} - -/** - * ath5k_hw_set_imr - Set interrupt mask - * - * @ah: The &struct ath5k_hw - * @new_mask: The new interrupt mask to be set - * - * Set the interrupt mask in hw to save interrupts. We do that by mapping - * ath5k_int bits to hw-specific bits to remove abstraction and writing - * Interrupt Mask Register. - */ -enum ath5k_int ath5k_hw_set_imr(struct ath5k_hw *ah, enum ath5k_int new_mask) -{ - enum ath5k_int old_mask, int_mask; - - old_mask = ah->ah_imr; - - /* - * Disable card interrupts to prevent any race conditions - * (they will be re-enabled afterwards if AR5K_INT GLOBAL - * is set again on the new mask). - */ - if (old_mask & AR5K_INT_GLOBAL) { - ath5k_hw_reg_write(ah, AR5K_IER_DISABLE, AR5K_IER); - ath5k_hw_reg_read(ah, AR5K_IER); - } - - /* - * Add additional, chipset-dependent interrupt mask flags - * and write them to the IMR (interrupt mask register). - */ - int_mask = new_mask & AR5K_INT_COMMON; - - if (ah->ah_version != AR5K_AR5210) { - /* Preserve per queue TXURN interrupt mask */ - u32 simr2 = ath5k_hw_reg_read(ah, AR5K_SIMR2) - & AR5K_SIMR2_QCU_TXURN; - - if (new_mask & AR5K_INT_FATAL) { - int_mask |= AR5K_IMR_HIUERR; - simr2 |= (AR5K_SIMR2_MCABT | AR5K_SIMR2_SSERR - | AR5K_SIMR2_DPERR); - } - - /*Beacon Not Ready*/ - if (new_mask & AR5K_INT_BNR) - int_mask |= AR5K_INT_BNR; - - if (new_mask & AR5K_INT_TIM) - int_mask |= AR5K_IMR_TIM; - - if (new_mask & AR5K_INT_TIM) - simr2 |= AR5K_SISR2_TIM; - if (new_mask & AR5K_INT_DTIM) - simr2 |= AR5K_SISR2_DTIM; - if (new_mask & AR5K_INT_DTIM_SYNC) - simr2 |= AR5K_SISR2_DTIM_SYNC; - if (new_mask & AR5K_INT_BCN_TIMEOUT) - simr2 |= AR5K_SISR2_BCN_TIMEOUT; - if (new_mask & AR5K_INT_CAB_TIMEOUT) - simr2 |= AR5K_SISR2_CAB_TIMEOUT; - - if (new_mask & AR5K_INT_RX_DOPPLER) - int_mask |= AR5K_IMR_RXDOPPLER; - - /* Note: Per queue interrupt masks - * are set via reset_tx_queue (qcu.c) */ - ath5k_hw_reg_write(ah, int_mask, AR5K_PIMR); - ath5k_hw_reg_write(ah, simr2, AR5K_SIMR2); - - } else { - if (new_mask & AR5K_INT_FATAL) - int_mask |= (AR5K_IMR_SSERR | AR5K_IMR_MCABT - | AR5K_IMR_HIUERR | AR5K_IMR_DPERR); - - ath5k_hw_reg_write(ah, int_mask, AR5K_IMR); - } - - /* If RXNOFRM interrupt is masked disable it - * by setting AR5K_RXNOFRM to zero */ - if (!(new_mask & AR5K_INT_RXNOFRM)) - ath5k_hw_reg_write(ah, 0, AR5K_RXNOFRM); - - /* Store new interrupt mask */ - ah->ah_imr = new_mask; - - /* ..re-enable interrupts if AR5K_INT_GLOBAL is set */ - if (new_mask & AR5K_INT_GLOBAL) { - ath5k_hw_reg_write(ah, AR5K_IER_ENABLE, AR5K_IER); - ath5k_hw_reg_read(ah, AR5K_IER); - } - - return old_mask; -} - diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c deleted file mode 100644 index 9a96550006ad..000000000000 --- a/drivers/net/wireless/ath/ath5k/eeprom.c +++ /dev/null @@ -1,1818 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2008-2009 Felix Fietkau - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*************************************\ -* EEPROM access functions and helpers * -\*************************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Read from eeprom - */ -static int ath5k_hw_eeprom_read(struct ath5k_hw *ah, u32 offset, u16 *data) -{ - u32 status, timeout; - - ATH5K_TRACE(ah->ah_sc); - /* - * Initialize EEPROM access - */ - if (ah->ah_version == AR5K_AR5210) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_EEAE); - (void)ath5k_hw_reg_read(ah, AR5K_EEPROM_BASE + (4 * offset)); - } else { - ath5k_hw_reg_write(ah, offset, AR5K_EEPROM_BASE); - AR5K_REG_ENABLE_BITS(ah, AR5K_EEPROM_CMD, - AR5K_EEPROM_CMD_READ); - } - - for (timeout = AR5K_TUNE_REGISTER_TIMEOUT; timeout > 0; timeout--) { - status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS); - if (status & AR5K_EEPROM_STAT_RDDONE) { - if (status & AR5K_EEPROM_STAT_RDERR) - return -EIO; - *data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) & - 0xffff); - return 0; - } - udelay(15); - } - - return -ETIMEDOUT; -} - -/* - * Translate binary channel representation in EEPROM to frequency - */ -static u16 ath5k_eeprom_bin2freq(struct ath5k_eeprom_info *ee, u16 bin, - unsigned int mode) -{ - u16 val; - - if (bin == AR5K_EEPROM_CHANNEL_DIS) - return bin; - - if (mode == AR5K_EEPROM_MODE_11A) { - if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) - val = (5 * bin) + 4800; - else - val = bin > 62 ? (10 * 62) + (5 * (bin - 62)) + 5100 : - (bin * 10) + 5100; - } else { - if (ee->ee_version > AR5K_EEPROM_VERSION_3_2) - val = bin + 2300; - else - val = bin + 2400; - } - - return val; -} - -/* - * Initialize eeprom & capabilities structs - */ -static int -ath5k_eeprom_init_header(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - int ret; - u16 val; - u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX; - - /* - * Read values from EEPROM and store them in the capability structure - */ - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MAGIC, ee_magic); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_PROTECT, ee_protect); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_REG_DOMAIN, ee_regdomain); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_VERSION, ee_version); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_HDR, ee_header); - - /* Return if we have an old EEPROM */ - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_0) - return 0; - - /* - * Validate the checksum of the EEPROM date. There are some - * devices with invalid EEPROMs. - */ - AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_UPPER, val); - if (val) { - eep_max = (val & AR5K_EEPROM_SIZE_UPPER_MASK) << - AR5K_EEPROM_SIZE_ENDLOC_SHIFT; - AR5K_EEPROM_READ(AR5K_EEPROM_SIZE_LOWER, val); - eep_max = (eep_max | val) - AR5K_EEPROM_INFO_BASE; - - /* - * Fail safe check to prevent stupid loops due - * to busted EEPROMs. XXX: This value is likely too - * big still, waiting on a better value. - */ - if (eep_max > (3 * AR5K_EEPROM_INFO_MAX)) { - ATH5K_ERR(ah->ah_sc, "Invalid max custom EEPROM size: " - "%d (0x%04x) max expected: %d (0x%04x)\n", - eep_max, eep_max, - 3 * AR5K_EEPROM_INFO_MAX, - 3 * AR5K_EEPROM_INFO_MAX); - return -EIO; - } - } - - for (cksum = 0, offset = 0; offset < eep_max; offset++) { - AR5K_EEPROM_READ(AR5K_EEPROM_INFO(offset), val); - cksum ^= val; - } - if (cksum != AR5K_EEPROM_INFO_CKSUM) { - ATH5K_ERR(ah->ah_sc, "Invalid EEPROM " - "checksum: 0x%04x eep_max: 0x%04x (%s)\n", - cksum, eep_max, - eep_max == AR5K_EEPROM_INFO_MAX ? - "default size" : "custom size"); - return -EIO; - } - - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_ANT_GAIN(ah->ah_ee_version), - ee_ant_gain); - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) { - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC0, ee_misc0); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC1, ee_misc1); - - /* XXX: Don't know which versions include these two */ - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC2, ee_misc2); - - if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC3, ee_misc3); - - if (ee->ee_version >= AR5K_EEPROM_VERSION_5_0) { - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC4, ee_misc4); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC5, ee_misc5); - AR5K_EEPROM_READ_HDR(AR5K_EEPROM_MISC6, ee_misc6); - } - } - - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_3) { - AR5K_EEPROM_READ(AR5K_EEPROM_OBDB0_2GHZ, val); - ee->ee_ob[AR5K_EEPROM_MODE_11B][0] = val & 0x7; - ee->ee_db[AR5K_EEPROM_MODE_11B][0] = (val >> 3) & 0x7; - - AR5K_EEPROM_READ(AR5K_EEPROM_OBDB1_2GHZ, val); - ee->ee_ob[AR5K_EEPROM_MODE_11G][0] = val & 0x7; - ee->ee_db[AR5K_EEPROM_MODE_11G][0] = (val >> 3) & 0x7; - } - - AR5K_EEPROM_READ(AR5K_EEPROM_IS_HB63, val); - - if ((ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4)) && val) - ee->ee_is_hb63 = true; - else - ee->ee_is_hb63 = false; - - AR5K_EEPROM_READ(AR5K_EEPROM_RFKILL, val); - ee->ee_rfkill_pin = (u8) AR5K_REG_MS(val, AR5K_EEPROM_RFKILL_GPIO_SEL); - ee->ee_rfkill_pol = val & AR5K_EEPROM_RFKILL_POLARITY ? true : false; - - /* Check if PCIE_OFFSET points to PCIE_SERDES_SECTION - * and enable serdes programming if needed. - * - * XXX: Serdes values seem to be fixed so - * no need to read them here, we write them - * during ath5k_hw_attach */ - AR5K_EEPROM_READ(AR5K_EEPROM_PCIE_OFFSET, val); - ee->ee_serdes = (val == AR5K_EEPROM_PCIE_SERDES_SECTION) ? - true : false; - - return 0; -} - - -/* - * Read antenna infos from eeprom - */ -static int ath5k_eeprom_read_ants(struct ath5k_hw *ah, u32 *offset, - unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 o = *offset; - u16 val; - int ret, i = 0; - - AR5K_EEPROM_READ(o++, val); - ee->ee_switch_settling[mode] = (val >> 8) & 0x7f; - ee->ee_atn_tx_rx[mode] = (val >> 2) & 0x3f; - ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; - ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; - ee->ee_ant_control[mode][i++] = val & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] = (val >> 10) & 0x3f; - ee->ee_ant_control[mode][i++] = (val >> 4) & 0x3f; - ee->ee_ant_control[mode][i] = (val << 2) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] |= (val >> 14) & 0x3; - ee->ee_ant_control[mode][i++] = (val >> 8) & 0x3f; - ee->ee_ant_control[mode][i++] = (val >> 2) & 0x3f; - ee->ee_ant_control[mode][i] = (val << 4) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ant_control[mode][i++] |= (val >> 12) & 0xf; - ee->ee_ant_control[mode][i++] = (val >> 6) & 0x3f; - ee->ee_ant_control[mode][i++] = val & 0x3f; - - /* Get antenna switch tables */ - ah->ah_ant_ctl[mode][AR5K_ANT_CTL] = - (ee->ee_ant_control[mode][0] << 4); - ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_A] = - ee->ee_ant_control[mode][1] | - (ee->ee_ant_control[mode][2] << 6) | - (ee->ee_ant_control[mode][3] << 12) | - (ee->ee_ant_control[mode][4] << 18) | - (ee->ee_ant_control[mode][5] << 24); - ah->ah_ant_ctl[mode][AR5K_ANT_SWTABLE_B] = - ee->ee_ant_control[mode][6] | - (ee->ee_ant_control[mode][7] << 6) | - (ee->ee_ant_control[mode][8] << 12) | - (ee->ee_ant_control[mode][9] << 18) | - (ee->ee_ant_control[mode][10] << 24); - - /* return new offset */ - *offset = o; - - return 0; -} - -/* - * Read supported modes and some mode-specific calibration data - * from eeprom - */ -static int ath5k_eeprom_read_modes(struct ath5k_hw *ah, u32 *offset, - unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 o = *offset; - u16 val; - int ret; - - ee->ee_n_piers[mode] = 0; - AR5K_EEPROM_READ(o++, val); - ee->ee_adc_desired_size[mode] = (s8)((val >> 8) & 0xff); - switch(mode) { - case AR5K_EEPROM_MODE_11A: - ee->ee_ob[mode][3] = (val >> 5) & 0x7; - ee->ee_db[mode][3] = (val >> 2) & 0x7; - ee->ee_ob[mode][2] = (val << 1) & 0x7; - - AR5K_EEPROM_READ(o++, val); - ee->ee_ob[mode][2] |= (val >> 15) & 0x1; - ee->ee_db[mode][2] = (val >> 12) & 0x7; - ee->ee_ob[mode][1] = (val >> 9) & 0x7; - ee->ee_db[mode][1] = (val >> 6) & 0x7; - ee->ee_ob[mode][0] = (val >> 3) & 0x7; - ee->ee_db[mode][0] = val & 0x7; - break; - case AR5K_EEPROM_MODE_11G: - case AR5K_EEPROM_MODE_11B: - ee->ee_ob[mode][1] = (val >> 4) & 0x7; - ee->ee_db[mode][1] = val & 0x7; - break; - } - - AR5K_EEPROM_READ(o++, val); - ee->ee_tx_end2xlna_enable[mode] = (val >> 8) & 0xff; - ee->ee_thr_62[mode] = val & 0xff; - - if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) - ee->ee_thr_62[mode] = mode == AR5K_EEPROM_MODE_11A ? 15 : 28; - - AR5K_EEPROM_READ(o++, val); - ee->ee_tx_end2xpa_disable[mode] = (val >> 8) & 0xff; - ee->ee_tx_frm2xpa_enable[mode] = val & 0xff; - - AR5K_EEPROM_READ(o++, val); - ee->ee_pga_desired_size[mode] = (val >> 8) & 0xff; - - if ((val & 0xff) & 0x80) - ee->ee_noise_floor_thr[mode] = -((((val & 0xff) ^ 0xff)) + 1); - else - ee->ee_noise_floor_thr[mode] = val & 0xff; - - if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) - ee->ee_noise_floor_thr[mode] = - mode == AR5K_EEPROM_MODE_11A ? -54 : -1; - - AR5K_EEPROM_READ(o++, val); - ee->ee_xlna_gain[mode] = (val >> 5) & 0xff; - ee->ee_x_gain[mode] = (val >> 1) & 0xf; - ee->ee_xpd[mode] = val & 0x1; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) - ee->ee_fixed_bias[mode] = (val >> 13) & 0x1; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_3) { - AR5K_EEPROM_READ(o++, val); - ee->ee_false_detect[mode] = (val >> 6) & 0x7f; - - if (mode == AR5K_EEPROM_MODE_11A) - ee->ee_xr_power[mode] = val & 0x3f; - else { - ee->ee_ob[mode][0] = val & 0x7; - ee->ee_db[mode][0] = (val >> 3) & 0x7; - } - } - - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_3_4) { - ee->ee_i_gain[mode] = AR5K_EEPROM_I_GAIN; - ee->ee_cck_ofdm_power_delta = AR5K_EEPROM_CCK_OFDM_DELTA; - } else { - ee->ee_i_gain[mode] = (val >> 13) & 0x7; - - AR5K_EEPROM_READ(o++, val); - ee->ee_i_gain[mode] |= (val << 3) & 0x38; - - if (mode == AR5K_EEPROM_MODE_11G) { - ee->ee_cck_ofdm_power_delta = (val >> 3) & 0xff; - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_6) - ee->ee_scaled_cck_delta = (val >> 11) & 0x1f; - } - } - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0 && - mode == AR5K_EEPROM_MODE_11A) { - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; - } - - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_0) - goto done; - - /* Note: >= v5 have bg freq piers on another location - * so these freq piers are ignored for >= v5 (should be 0xff - * anyway) */ - switch(mode) { - case AR5K_EEPROM_MODE_11A: - if (ah->ah_ee_version < AR5K_EEPROM_VERSION_4_1) - break; - - AR5K_EEPROM_READ(o++, val); - ee->ee_margin_tx_rx[mode] = val & 0x3f; - break; - case AR5K_EEPROM_MODE_11B: - AR5K_EEPROM_READ(o++, val); - - ee->ee_pwr_cal_b[0].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_b[0].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - ee->ee_pwr_cal_b[1].freq = - ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); - if (ee->ee_pwr_cal_b[1].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - AR5K_EEPROM_READ(o++, val); - ee->ee_pwr_cal_b[2].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_b[2].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; - break; - case AR5K_EEPROM_MODE_11G: - AR5K_EEPROM_READ(o++, val); - - ee->ee_pwr_cal_g[0].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_g[0].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - ee->ee_pwr_cal_g[1].freq = - ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); - if (ee->ee_pwr_cal_g[1].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - AR5K_EEPROM_READ(o++, val); - ee->ee_turbo_max_power[mode] = val & 0x7f; - ee->ee_xr_power[mode] = (val >> 7) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_pwr_cal_g[2].freq = - ath5k_eeprom_bin2freq(ee, val & 0xff, mode); - if (ee->ee_pwr_cal_g[2].freq != AR5K_EEPROM_CHANNEL_DIS) - ee->ee_n_piers[mode]++; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - ee->ee_margin_tx_rx[mode] = (val >> 8) & 0x3f; - - AR5K_EEPROM_READ(o++, val); - ee->ee_i_cal[mode] = (val >> 8) & 0x3f; - ee->ee_q_cal[mode] = (val >> 3) & 0x1f; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_2) { - AR5K_EEPROM_READ(o++, val); - ee->ee_cck_ofdm_gain_delta = val & 0xff; - } - break; - } - - /* - * Read turbo mode information on newer EEPROM versions - */ - if (ee->ee_version < AR5K_EEPROM_VERSION_5_0) - goto done; - - switch (mode){ - case AR5K_EEPROM_MODE_11A: - ee->ee_switch_settling_turbo[mode] = (val >> 6) & 0x7f; - - ee->ee_atn_tx_rx_turbo[mode] = (val >> 13) & 0x7; - AR5K_EEPROM_READ(o++, val); - ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x7) << 3; - ee->ee_margin_tx_rx_turbo[mode] = (val >> 3) & 0x3f; - - ee->ee_adc_desired_size_turbo[mode] = (val >> 9) & 0x7f; - AR5K_EEPROM_READ(o++, val); - ee->ee_adc_desired_size_turbo[mode] |= (val & 0x1) << 7; - ee->ee_pga_desired_size_turbo[mode] = (val >> 1) & 0xff; - - if (AR5K_EEPROM_EEMAP(ee->ee_misc0) >=2) - ee->ee_pd_gain_overlap = (val >> 9) & 0xf; - break; - case AR5K_EEPROM_MODE_11G: - ee->ee_switch_settling_turbo[mode] = (val >> 8) & 0x7f; - - ee->ee_atn_tx_rx_turbo[mode] = (val >> 15) & 0x7; - AR5K_EEPROM_READ(o++, val); - ee->ee_atn_tx_rx_turbo[mode] |= (val & 0x1f) << 1; - ee->ee_margin_tx_rx_turbo[mode] = (val >> 5) & 0x3f; - - ee->ee_adc_desired_size_turbo[mode] = (val >> 11) & 0x7f; - AR5K_EEPROM_READ(o++, val); - ee->ee_adc_desired_size_turbo[mode] |= (val & 0x7) << 5; - ee->ee_pga_desired_size_turbo[mode] = (val >> 3) & 0xff; - break; - } - -done: - /* return new offset */ - *offset = o; - - return 0; -} - -/* Read mode-specific data (except power calibration data) */ -static int -ath5k_eeprom_init_modes(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 mode_offset[3]; - unsigned int mode; - u32 offset; - int ret; - - /* - * Get values for all modes - */ - mode_offset[AR5K_EEPROM_MODE_11A] = AR5K_EEPROM_MODES_11A(ah->ah_ee_version); - mode_offset[AR5K_EEPROM_MODE_11B] = AR5K_EEPROM_MODES_11B(ah->ah_ee_version); - mode_offset[AR5K_EEPROM_MODE_11G] = AR5K_EEPROM_MODES_11G(ah->ah_ee_version); - - ee->ee_turbo_max_power[AR5K_EEPROM_MODE_11A] = - AR5K_EEPROM_HDR_T_5GHZ_DBM(ee->ee_header); - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) { - offset = mode_offset[mode]; - - ret = ath5k_eeprom_read_ants(ah, &offset, mode); - if (ret) - return ret; - - ret = ath5k_eeprom_read_modes(ah, &offset, mode); - if (ret) - return ret; - } - - /* override for older eeprom versions for better performance */ - if (ah->ah_ee_version <= AR5K_EEPROM_VERSION_3_2) { - ee->ee_thr_62[AR5K_EEPROM_MODE_11A] = 15; - ee->ee_thr_62[AR5K_EEPROM_MODE_11B] = 28; - ee->ee_thr_62[AR5K_EEPROM_MODE_11G] = 28; - } - - return 0; -} - -/* Read the frequency piers for each mode (mostly used on newer eeproms with 0xff - * frequency mask) */ -static inline int -ath5k_eeprom_read_freq_list(struct ath5k_hw *ah, int *offset, int max, - struct ath5k_chan_pcal_info *pc, unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - int o = *offset; - int i = 0; - u8 freq1, freq2; - int ret; - u16 val; - - ee->ee_n_piers[mode] = 0; - while(i < max) { - AR5K_EEPROM_READ(o++, val); - - freq1 = val & 0xff; - if (!freq1) - break; - - pc[i++].freq = ath5k_eeprom_bin2freq(ee, - freq1, mode); - ee->ee_n_piers[mode]++; - - freq2 = (val >> 8) & 0xff; - if (!freq2) - break; - - pc[i++].freq = ath5k_eeprom_bin2freq(ee, - freq2, mode); - ee->ee_n_piers[mode]++; - } - - /* return new offset */ - *offset = o; - - return 0; -} - -/* Read frequency piers for 802.11a */ -static int -ath5k_eeprom_init_11a_pcal_freq(struct ath5k_hw *ah, int offset) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a; - int i, ret; - u16 val; - u8 mask; - - if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { - ath5k_eeprom_read_freq_list(ah, &offset, - AR5K_EEPROM_N_5GHZ_CHAN, pcal, - AR5K_EEPROM_MODE_11A); - } else { - mask = AR5K_EEPROM_FREQ_M(ah->ah_ee_version); - - AR5K_EEPROM_READ(offset++, val); - pcal[0].freq = (val >> 9) & mask; - pcal[1].freq = (val >> 2) & mask; - pcal[2].freq = (val << 5) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[2].freq |= (val >> 11) & 0x1f; - pcal[3].freq = (val >> 4) & mask; - pcal[4].freq = (val << 3) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[4].freq |= (val >> 13) & 0x7; - pcal[5].freq = (val >> 6) & mask; - pcal[6].freq = (val << 1) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[6].freq |= (val >> 15) & 0x1; - pcal[7].freq = (val >> 8) & mask; - pcal[8].freq = (val >> 1) & mask; - pcal[9].freq = (val << 6) & mask; - - AR5K_EEPROM_READ(offset++, val); - pcal[9].freq |= (val >> 10) & 0x3f; - - /* Fixed number of piers */ - ee->ee_n_piers[AR5K_EEPROM_MODE_11A] = 10; - - for (i = 0; i < AR5K_EEPROM_N_5GHZ_CHAN; i++) { - pcal[i].freq = ath5k_eeprom_bin2freq(ee, - pcal[i].freq, AR5K_EEPROM_MODE_11A); - } - } - - return 0; -} - -/* Read frequency piers for 802.11bg on eeprom versions >= 5 and eemap >= 2 */ -static inline int -ath5k_eeprom_init_11bg_2413(struct ath5k_hw *ah, unsigned int mode, int offset) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcal; - - switch(mode) { - case AR5K_EEPROM_MODE_11B: - pcal = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - pcal = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - ath5k_eeprom_read_freq_list(ah, &offset, - AR5K_EEPROM_N_2GHZ_CHAN_2413, pcal, - mode); - - return 0; -} - -/* - * Read power calibration for RF5111 chips - * - * For RF5111 we have an XPD -eXternal Power Detector- curve - * for each calibrated channel. Each curve has 0,5dB Power steps - * on x axis and PCDAC steps (offsets) on y axis and looks like an - * exponential function. To recreate the curve we read 11 points - * here and interpolate later. - */ - -/* Used to match PCDAC steps with power values on RF5111 chips - * (eeprom versions < 4). For RF5111 we have 11 pre-defined PCDAC - * steps that match with the power values we read from eeprom. On - * older eeprom versions (< 3.2) these steps are equaly spaced at - * 10% of the pcdac curve -until the curve reaches it's maximum- - * (11 steps from 0 to 100%) but on newer eeprom versions (>= 3.2) - * these 11 steps are spaced in a different way. This function returns - * the pcdac steps based on eeprom version and curve min/max so that we - * can have pcdac/pwr points. - */ -static inline void -ath5k_get_pcdac_intercepts(struct ath5k_hw *ah, u8 min, u8 max, u8 *vp) -{ - static const u16 intercepts3[] = - { 0, 5, 10, 20, 30, 50, 70, 85, 90, 95, 100 }; - static const u16 intercepts3_2[] = - { 0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100 }; - const u16 *ip; - int i; - - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_3_2) - ip = intercepts3_2; - else - ip = intercepts3; - - for (i = 0; i < ARRAY_SIZE(intercepts3); i++) - vp[i] = (ip[i] * max + (100 - ip[i]) * min) / 100; -} - -/* Convert RF5111 specific data to generic raw data - * used by interpolation code */ -static int -ath5k_eeprom_convert_pcal_info_5111(struct ath5k_hw *ah, int mode, - struct ath5k_chan_pcal_info *chinfo) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf5111 *pcinfo; - struct ath5k_pdgain_info *pd; - u8 pier, point, idx; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - - /* Fill raw data for each calibration pier */ - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - - pcinfo = &chinfo[pier].rf5111_info; - - /* Allocate pd_curves for this cal pier */ - chinfo[pier].pd_curves = - kcalloc(AR5K_EEPROM_N_PD_CURVES, - sizeof(struct ath5k_pdgain_info), - GFP_KERNEL); - - if (!chinfo[pier].pd_curves) - return -ENOMEM; - - /* Only one curve for RF5111 - * find out which one and place - * in in pd_curves. - * Note: ee_x_gain is reversed here */ - for (idx = 0; idx < AR5K_EEPROM_N_PD_CURVES; idx++) { - - if (!((ee->ee_x_gain[mode] >> idx) & 0x1)) { - pdgain_idx[0] = idx; - break; - } - } - - ee->ee_pd_gains[mode] = 1; - - pd = &chinfo[pier].pd_curves[idx]; - - pd->pd_points = AR5K_EEPROM_N_PWR_POINTS_5111; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, - sizeof(u8), GFP_KERNEL); - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(AR5K_EEPROM_N_PWR_POINTS_5111, - sizeof(s16), GFP_KERNEL); - if (!pd->pd_pwr) - return -ENOMEM; - - /* Fill raw dataset - * (convert power to 0.25dB units - * for RF5112 combatibility) */ - for (point = 0; point < pd->pd_points; point++) { - - /* Absolute values */ - pd->pd_pwr[point] = 2 * pcinfo->pwr[point]; - - /* Already sorted */ - pd->pd_step[point] = pcinfo->pcdac[point]; - } - - /* Set min/max pwr */ - chinfo[pier].min_pwr = pd->pd_pwr[0]; - chinfo[pier].max_pwr = pd->pd_pwr[10]; - - } - - return 0; -} - -/* Parse EEPROM data */ -static int -ath5k_eeprom_read_pcal_info_5111(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcal; - int offset, ret; - int i; - u16 val; - - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - switch(mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - - ret = ath5k_eeprom_init_11a_pcal_freq(ah, - offset + AR5K_EEPROM_GROUP1_OFFSET); - if (ret < 0) - return ret; - - offset += AR5K_EEPROM_GROUP2_OFFSET; - pcal = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header) && - !AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - - pcal = ee->ee_pwr_cal_b; - offset += AR5K_EEPROM_GROUP3_OFFSET; - - /* fixed piers */ - pcal[0].freq = 2412; - pcal[1].freq = 2447; - pcal[2].freq = 2484; - ee->ee_n_piers[mode] = 3; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - - pcal = ee->ee_pwr_cal_g; - offset += AR5K_EEPROM_GROUP4_OFFSET; - - /* fixed piers */ - pcal[0].freq = 2312; - pcal[1].freq = 2412; - pcal[2].freq = 2484; - ee->ee_n_piers[mode] = 3; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - struct ath5k_chan_pcal_info_rf5111 *cdata = - &pcal[i].rf5111_info; - - AR5K_EEPROM_READ(offset++, val); - cdata->pcdac_max = ((val >> 10) & AR5K_EEPROM_PCDAC_M); - cdata->pcdac_min = ((val >> 4) & AR5K_EEPROM_PCDAC_M); - cdata->pwr[0] = ((val << 2) & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[0] |= ((val >> 14) & 0x3); - cdata->pwr[1] = ((val >> 8) & AR5K_EEPROM_POWER_M); - cdata->pwr[2] = ((val >> 2) & AR5K_EEPROM_POWER_M); - cdata->pwr[3] = ((val << 4) & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[3] |= ((val >> 12) & 0xf); - cdata->pwr[4] = ((val >> 6) & AR5K_EEPROM_POWER_M); - cdata->pwr[5] = (val & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[6] = ((val >> 10) & AR5K_EEPROM_POWER_M); - cdata->pwr[7] = ((val >> 4) & AR5K_EEPROM_POWER_M); - cdata->pwr[8] = ((val << 2) & AR5K_EEPROM_POWER_M); - - AR5K_EEPROM_READ(offset++, val); - cdata->pwr[8] |= ((val >> 14) & 0x3); - cdata->pwr[9] = ((val >> 8) & AR5K_EEPROM_POWER_M); - cdata->pwr[10] = ((val >> 2) & AR5K_EEPROM_POWER_M); - - ath5k_get_pcdac_intercepts(ah, cdata->pcdac_min, - cdata->pcdac_max, cdata->pcdac); - } - - return ath5k_eeprom_convert_pcal_info_5111(ah, mode, pcal); -} - - -/* - * Read power calibration for RF5112 chips - * - * For RF5112 we have 4 XPD -eXternal Power Detector- curves - * for each calibrated channel on 0, -6, -12 and -18dbm but we only - * use the higher (3) and the lower (0) curves. Each curve has 0.5dB - * power steps on x axis and PCDAC steps on y axis and looks like a - * linear function. To recreate the curve and pass the power values - * on hw, we read 4 points for xpd 0 (lower gain -> max power) - * and 3 points for xpd 3 (higher gain -> lower power) here and - * interpolate later. - * - * Note: Many vendors just use xpd 0 so xpd 3 is zeroed. - */ - -/* Convert RF5112 specific data to generic raw data - * used by interpolation code */ -static int -ath5k_eeprom_convert_pcal_info_5112(struct ath5k_hw *ah, int mode, - struct ath5k_chan_pcal_info *chinfo) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf5112 *pcinfo; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - unsigned int pier, pdg, point; - - /* Fill raw data for each calibration pier */ - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - - pcinfo = &chinfo[pier].rf5112_info; - - /* Allocate pd_curves for this cal pier */ - chinfo[pier].pd_curves = - kcalloc(AR5K_EEPROM_N_PD_CURVES, - sizeof(struct ath5k_pdgain_info), - GFP_KERNEL); - - if (!chinfo[pier].pd_curves) - return -ENOMEM; - - /* Fill pd_curves */ - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - - u8 idx = pdgain_idx[pdg]; - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[idx]; - - /* Lowest gain curve (max power) */ - if (pdg == 0) { - /* One more point for better accuracy */ - pd->pd_points = AR5K_EEPROM_N_XPD0_POINTS; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(pd->pd_points, - sizeof(u8), GFP_KERNEL); - - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(pd->pd_points, - sizeof(s16), GFP_KERNEL); - - if (!pd->pd_pwr) - return -ENOMEM; - - - /* Fill raw dataset - * (all power levels are in 0.25dB units) */ - pd->pd_step[0] = pcinfo->pcdac_x0[0]; - pd->pd_pwr[0] = pcinfo->pwr_x0[0]; - - for (point = 1; point < pd->pd_points; - point++) { - /* Absolute values */ - pd->pd_pwr[point] = - pcinfo->pwr_x0[point]; - - /* Deltas */ - pd->pd_step[point] = - pd->pd_step[point - 1] + - pcinfo->pcdac_x0[point]; - } - - /* Set min power for this frequency */ - chinfo[pier].min_pwr = pd->pd_pwr[0]; - - /* Highest gain curve (min power) */ - } else if (pdg == 1) { - - pd->pd_points = AR5K_EEPROM_N_XPD3_POINTS; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(pd->pd_points, - sizeof(u8), GFP_KERNEL); - - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(pd->pd_points, - sizeof(s16), GFP_KERNEL); - - if (!pd->pd_pwr) - return -ENOMEM; - - /* Fill raw dataset - * (all power levels are in 0.25dB units) */ - for (point = 0; point < pd->pd_points; - point++) { - /* Absolute values */ - pd->pd_pwr[point] = - pcinfo->pwr_x3[point]; - - /* Fixed points */ - pd->pd_step[point] = - pcinfo->pcdac_x3[point]; - } - - /* Since we have a higher gain curve - * override min power */ - chinfo[pier].min_pwr = pd->pd_pwr[0]; - } - } - } - - return 0; -} - -/* Parse EEPROM data */ -static int -ath5k_eeprom_read_pcal_info_5112(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf5112 *chan_pcal_info; - struct ath5k_chan_pcal_info *gen_chan_info; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - u32 offset; - u8 i, c; - u16 val; - int ret; - u8 pd_gains = 0; - - /* Count how many curves we have and - * identify them (which one of the 4 - * available curves we have on each count). - * Curves are stored from lower (x0) to - * higher (x3) gain */ - for (i = 0; i < AR5K_EEPROM_N_PD_CURVES; i++) { - /* ee_x_gain[mode] is x gain mask */ - if ((ee->ee_x_gain[mode] >> i) & 0x1) - pdgain_idx[pd_gains++] = i; - } - ee->ee_pd_gains[mode] = pd_gains; - - if (pd_gains == 0 || pd_gains > 2) - return -EINVAL; - - switch (mode) { - case AR5K_EEPROM_MODE_11A: - /* - * Read 5GHz EEPROM channels - */ - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - ath5k_eeprom_init_11a_pcal_freq(ah, offset); - - offset += AR5K_EEPROM_GROUP2_OFFSET; - gen_chan_info = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += AR5K_EEPROM_GROUP3_OFFSET; - - /* NB: frequency piers parsed during mode init */ - gen_chan_info = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - offset = AR5K_EEPROM_GROUPS_START(ee->ee_version); - if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += AR5K_EEPROM_GROUP4_OFFSET; - else if (AR5K_EEPROM_HDR_11B(ee->ee_header)) - offset += AR5K_EEPROM_GROUP2_OFFSET; - - /* NB: frequency piers parsed during mode init */ - gen_chan_info = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - chan_pcal_info = &gen_chan_info[i].rf5112_info; - - /* Power values in quarter dB - * for the lower xpd gain curve - * (0 dBm -> higher output power) */ - for (c = 0; c < AR5K_EEPROM_N_XPD0_POINTS; c++) { - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x0[c] = (s8) (val & 0xff); - chan_pcal_info->pwr_x0[++c] = (s8) ((val >> 8) & 0xff); - } - - /* PCDAC steps - * corresponding to the above power - * measurements */ - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pcdac_x0[1] = (val & 0x1f); - chan_pcal_info->pcdac_x0[2] = ((val >> 5) & 0x1f); - chan_pcal_info->pcdac_x0[3] = ((val >> 10) & 0x1f); - - /* Power values in quarter dB - * for the higher xpd gain curve - * (18 dBm -> lower output power) */ - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x3[0] = (s8) (val & 0xff); - chan_pcal_info->pwr_x3[1] = (s8) ((val >> 8) & 0xff); - - AR5K_EEPROM_READ(offset++, val); - chan_pcal_info->pwr_x3[2] = (val & 0xff); - - /* PCDAC steps - * corresponding to the above power - * measurements (fixed) */ - chan_pcal_info->pcdac_x3[0] = 20; - chan_pcal_info->pcdac_x3[1] = 35; - chan_pcal_info->pcdac_x3[2] = 63; - - if (ee->ee_version >= AR5K_EEPROM_VERSION_4_3) { - chan_pcal_info->pcdac_x0[0] = ((val >> 8) & 0x3f); - - /* Last xpd0 power level is also channel maximum */ - gen_chan_info[i].max_pwr = chan_pcal_info->pwr_x0[3]; - } else { - chan_pcal_info->pcdac_x0[0] = 1; - gen_chan_info[i].max_pwr = (s8) ((val >> 8) & 0xff); - } - - } - - return ath5k_eeprom_convert_pcal_info_5112(ah, mode, gen_chan_info); -} - - -/* - * Read power calibration for RF2413 chips - * - * For RF2413 we have a Power to PDDAC table (Power Detector) - * instead of a PCDAC and 4 pd gain curves for each calibrated channel. - * Each curve has power on x axis in 0.5 db steps and PDDADC steps on y - * axis and looks like an exponential function like the RF5111 curve. - * - * To recreate the curves we read here the points and interpolate - * later. Note that in most cases only 2 (higher and lower) curves are - * used (like RF5112) but vendors have the oportunity to include all - * 4 curves on eeprom. The final curve (higher power) has an extra - * point for better accuracy like RF5112. - */ - -/* For RF2413 power calibration data doesn't start on a fixed location and - * if a mode is not supported, it's section is missing -not zeroed-. - * So we need to calculate the starting offset for each section by using - * these two functions */ - -/* Return the size of each section based on the mode and the number of pd - * gains available (maximum 4). */ -static inline unsigned int -ath5k_pdgains_size_2413(struct ath5k_eeprom_info *ee, unsigned int mode) -{ - static const unsigned int pdgains_size[] = { 4, 6, 9, 12 }; - unsigned int sz; - - sz = pdgains_size[ee->ee_pd_gains[mode] - 1]; - sz *= ee->ee_n_piers[mode]; - - return sz; -} - -/* Return the starting offset for a section based on the modes supported - * and each section's size. */ -static unsigned int -ath5k_cal_data_offset_2413(struct ath5k_eeprom_info *ee, int mode) -{ - u32 offset = AR5K_EEPROM_CAL_DATA_START(ee->ee_misc4); - - switch(mode) { - case AR5K_EEPROM_MODE_11G: - if (AR5K_EEPROM_HDR_11B(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, - AR5K_EEPROM_MODE_11B) + - AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - /* fall through */ - case AR5K_EEPROM_MODE_11B: - if (AR5K_EEPROM_HDR_11A(ee->ee_header)) - offset += ath5k_pdgains_size_2413(ee, - AR5K_EEPROM_MODE_11A) + - AR5K_EEPROM_N_5GHZ_CHAN / 2; - /* fall through */ - case AR5K_EEPROM_MODE_11A: - break; - default: - break; - } - - return offset; -} - -/* Convert RF2413 specific data to generic raw data - * used by interpolation code */ -static int -ath5k_eeprom_convert_pcal_info_2413(struct ath5k_hw *ah, int mode, - struct ath5k_chan_pcal_info *chinfo) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf2413 *pcinfo; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - unsigned int pier, pdg, point; - - /* Fill raw data for each calibration pier */ - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - - pcinfo = &chinfo[pier].rf2413_info; - - /* Allocate pd_curves for this cal pier */ - chinfo[pier].pd_curves = - kcalloc(AR5K_EEPROM_N_PD_CURVES, - sizeof(struct ath5k_pdgain_info), - GFP_KERNEL); - - if (!chinfo[pier].pd_curves) - return -ENOMEM; - - /* Fill pd_curves */ - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - - u8 idx = pdgain_idx[pdg]; - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[idx]; - - /* One more point for the highest power - * curve (lowest gain) */ - if (pdg == ee->ee_pd_gains[mode] - 1) - pd->pd_points = AR5K_EEPROM_N_PD_POINTS; - else - pd->pd_points = AR5K_EEPROM_N_PD_POINTS - 1; - - /* Allocate pd points for this curve */ - pd->pd_step = kcalloc(pd->pd_points, - sizeof(u8), GFP_KERNEL); - - if (!pd->pd_step) - return -ENOMEM; - - pd->pd_pwr = kcalloc(pd->pd_points, - sizeof(s16), GFP_KERNEL); - - if (!pd->pd_pwr) - return -ENOMEM; - - /* Fill raw dataset - * convert all pwr levels to - * quarter dB for RF5112 combatibility */ - pd->pd_step[0] = pcinfo->pddac_i[pdg]; - pd->pd_pwr[0] = 4 * pcinfo->pwr_i[pdg]; - - for (point = 1; point < pd->pd_points; point++) { - - pd->pd_pwr[point] = pd->pd_pwr[point - 1] + - 2 * pcinfo->pwr[pdg][point - 1]; - - pd->pd_step[point] = pd->pd_step[point - 1] + - pcinfo->pddac[pdg][point - 1]; - - } - - /* Highest gain curve -> min power */ - if (pdg == 0) - chinfo[pier].min_pwr = pd->pd_pwr[0]; - - /* Lowest gain curve -> max power */ - if (pdg == ee->ee_pd_gains[mode] - 1) - chinfo[pier].max_pwr = - pd->pd_pwr[pd->pd_points - 1]; - } - } - - return 0; -} - -/* Parse EEPROM data */ -static int -ath5k_eeprom_read_pcal_info_2413(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info_rf2413 *pcinfo; - struct ath5k_chan_pcal_info *chinfo; - u8 *pdgain_idx = ee->ee_pdc_to_idx[mode]; - u32 offset; - int idx, i, ret; - u16 val; - u8 pd_gains = 0; - - /* Count how many curves we have and - * identify them (which one of the 4 - * available curves we have on each count). - * Curves are stored from higher to - * lower gain so we go backwards */ - for (idx = AR5K_EEPROM_N_PD_CURVES - 1; idx >= 0; idx--) { - /* ee_x_gain[mode] is x gain mask */ - if ((ee->ee_x_gain[mode] >> idx) & 0x1) - pdgain_idx[pd_gains++] = idx; - - } - ee->ee_pd_gains[mode] = pd_gains; - - if (pd_gains == 0) - return -EINVAL; - - offset = ath5k_cal_data_offset_2413(ee, mode); - switch (mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - - ath5k_eeprom_init_11a_pcal_freq(ah, offset); - offset += AR5K_EEPROM_N_5GHZ_CHAN / 2; - chinfo = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) - return 0; - - ath5k_eeprom_init_11bg_2413(ah, mode, offset); - offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - chinfo = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - - ath5k_eeprom_init_11bg_2413(ah, mode, offset); - offset += AR5K_EEPROM_N_2GHZ_CHAN_2413 / 2; - chinfo = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (i = 0; i < ee->ee_n_piers[mode]; i++) { - pcinfo = &chinfo[i].rf2413_info; - - /* - * Read pwr_i, pddac_i and the first - * 2 pd points (pwr, pddac) - */ - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr_i[0] = val & 0x1f; - pcinfo->pddac_i[0] = (val >> 5) & 0x7f; - pcinfo->pwr[0][0] = (val >> 12) & 0xf; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[0][0] = val & 0x3f; - pcinfo->pwr[0][1] = (val >> 6) & 0xf; - pcinfo->pddac[0][1] = (val >> 10) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[0][2] = val & 0xf; - pcinfo->pddac[0][2] = (val >> 4) & 0x3f; - - pcinfo->pwr[0][3] = 0; - pcinfo->pddac[0][3] = 0; - - if (pd_gains > 1) { - /* - * Pd gain 0 is not the last pd gain - * so it only has 2 pd points. - * Continue wih pd gain 1. - */ - pcinfo->pwr_i[1] = (val >> 10) & 0x1f; - - pcinfo->pddac_i[1] = (val >> 15) & 0x1; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac_i[1] |= (val & 0x3F) << 1; - - pcinfo->pwr[1][0] = (val >> 6) & 0xf; - pcinfo->pddac[1][0] = (val >> 10) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[1][1] = val & 0xf; - pcinfo->pddac[1][1] = (val >> 4) & 0x3f; - pcinfo->pwr[1][2] = (val >> 10) & 0xf; - - pcinfo->pddac[1][2] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[1][2] |= (val & 0xF) << 2; - - pcinfo->pwr[1][3] = 0; - pcinfo->pddac[1][3] = 0; - } else if (pd_gains == 1) { - /* - * Pd gain 0 is the last one so - * read the extra point. - */ - pcinfo->pwr[0][3] = (val >> 10) & 0xf; - - pcinfo->pddac[0][3] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[0][3] |= (val & 0xF) << 2; - } - - /* - * Proceed with the other pd_gains - * as above. - */ - if (pd_gains > 2) { - pcinfo->pwr_i[2] = (val >> 4) & 0x1f; - pcinfo->pddac_i[2] = (val >> 9) & 0x7f; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[2][0] = (val >> 0) & 0xf; - pcinfo->pddac[2][0] = (val >> 4) & 0x3f; - pcinfo->pwr[2][1] = (val >> 10) & 0xf; - - pcinfo->pddac[2][1] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[2][1] |= (val & 0xF) << 2; - - pcinfo->pwr[2][2] = (val >> 4) & 0xf; - pcinfo->pddac[2][2] = (val >> 8) & 0x3f; - - pcinfo->pwr[2][3] = 0; - pcinfo->pddac[2][3] = 0; - } else if (pd_gains == 2) { - pcinfo->pwr[1][3] = (val >> 4) & 0xf; - pcinfo->pddac[1][3] = (val >> 8) & 0x3f; - } - - if (pd_gains > 3) { - pcinfo->pwr_i[3] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr_i[3] |= ((val >> 0) & 0x7) << 2; - - pcinfo->pddac_i[3] = (val >> 3) & 0x7f; - pcinfo->pwr[3][0] = (val >> 10) & 0xf; - pcinfo->pddac[3][0] = (val >> 14) & 0x3; - - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[3][0] |= (val & 0xF) << 2; - pcinfo->pwr[3][1] = (val >> 4) & 0xf; - pcinfo->pddac[3][1] = (val >> 8) & 0x3f; - - pcinfo->pwr[3][2] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[3][2] |= ((val >> 0) & 0x3) << 2; - - pcinfo->pddac[3][2] = (val >> 2) & 0x3f; - pcinfo->pwr[3][3] = (val >> 8) & 0xf; - - pcinfo->pddac[3][3] = (val >> 12) & 0xF; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pddac[3][3] |= ((val >> 0) & 0x3) << 4; - } else if (pd_gains == 3) { - pcinfo->pwr[2][3] = (val >> 14) & 0x3; - AR5K_EEPROM_READ(offset++, val); - pcinfo->pwr[2][3] |= ((val >> 0) & 0x3) << 2; - - pcinfo->pddac[2][3] = (val >> 2) & 0x3f; - } - } - - return ath5k_eeprom_convert_pcal_info_2413(ah, mode, chinfo); -} - - -/* - * Read per rate target power (this is the maximum tx power - * supported by the card). This info is used when setting - * tx power, no matter the channel. - * - * This also works for v5 EEPROMs. - */ -static int -ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_rate_pcal_info *rate_pcal_info; - u8 *rate_target_pwr_num; - u32 offset; - u16 val; - int ret, i; - - offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1); - rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode]; - switch (mode) { - case AR5K_EEPROM_MODE_11A: - offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version); - rate_pcal_info = ee->ee_rate_tpwr_a; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN; - break; - case AR5K_EEPROM_MODE_11B: - offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version); - rate_pcal_info = ee->ee_rate_tpwr_b; - ee->ee_rate_target_pwr_num[mode] = 2; /* 3rd is g mode's 1st */ - break; - case AR5K_EEPROM_MODE_11G: - offset += AR5K_EEPROM_TARGET_PWR_OFF_11G(ee->ee_version); - rate_pcal_info = ee->ee_rate_tpwr_g; - ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_2GHZ_CHAN; - break; - default: - return -EINVAL; - } - - /* Different freq mask for older eeproms (<= v3.2) */ - if (ee->ee_version <= AR5K_EEPROM_VERSION_3_2) { - for (i = 0; i < (*rate_target_pwr_num); i++) { - AR5K_EEPROM_READ(offset++, val); - rate_pcal_info[i].freq = - ath5k_eeprom_bin2freq(ee, (val >> 9) & 0x7f, mode); - - rate_pcal_info[i].target_power_6to24 = ((val >> 3) & 0x3f); - rate_pcal_info[i].target_power_36 = (val << 3) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - - if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || - val == 0) { - (*rate_target_pwr_num) = i; - break; - } - - rate_pcal_info[i].target_power_36 |= ((val >> 13) & 0x7); - rate_pcal_info[i].target_power_48 = ((val >> 7) & 0x3f); - rate_pcal_info[i].target_power_54 = ((val >> 1) & 0x3f); - } - } else { - for (i = 0; i < (*rate_target_pwr_num); i++) { - AR5K_EEPROM_READ(offset++, val); - rate_pcal_info[i].freq = - ath5k_eeprom_bin2freq(ee, (val >> 8) & 0xff, mode); - - rate_pcal_info[i].target_power_6to24 = ((val >> 2) & 0x3f); - rate_pcal_info[i].target_power_36 = (val << 4) & 0x3f; - - AR5K_EEPROM_READ(offset++, val); - - if (rate_pcal_info[i].freq == AR5K_EEPROM_CHANNEL_DIS || - val == 0) { - (*rate_target_pwr_num) = i; - break; - } - - rate_pcal_info[i].target_power_36 |= (val >> 12) & 0xf; - rate_pcal_info[i].target_power_48 = ((val >> 6) & 0x3f); - rate_pcal_info[i].target_power_54 = (val & 0x3f); - } - } - - return 0; -} - -/* - * Read per channel calibration info from EEPROM - * - * This info is used to calibrate the baseband power table. Imagine - * that for each channel there is a power curve that's hw specific - * (depends on amplifier etc) and we try to "correct" this curve using - * offests we pass on to phy chip (baseband -> before amplifier) so that - * it can use accurate power values when setting tx power (takes amplifier's - * performance on each channel into account). - * - * EEPROM provides us with the offsets for some pre-calibrated channels - * and we have to interpolate to create the full table for these channels and - * also the table for any channel. - */ -static int -ath5k_eeprom_read_pcal_info(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - int (*read_pcal)(struct ath5k_hw *hw, int mode); - int mode; - int err; - - if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_0) && - (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 1)) - read_pcal = ath5k_eeprom_read_pcal_info_5112; - else if ((ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0) && - (AR5K_EEPROM_EEMAP(ee->ee_misc0) == 2)) - read_pcal = ath5k_eeprom_read_pcal_info_2413; - else - read_pcal = ath5k_eeprom_read_pcal_info_5111; - - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; - mode++) { - err = read_pcal(ah, mode); - if (err) - return err; - - err = ath5k_eeprom_read_target_rate_pwr_info(ah, mode); - if (err < 0) - return err; - } - - return 0; -} - -static int -ath5k_eeprom_free_pcal_info(struct ath5k_hw *ah, int mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *chinfo; - u8 pier, pdg; - - switch (mode) { - case AR5K_EEPROM_MODE_11A: - if (!AR5K_EEPROM_HDR_11A(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_a; - break; - case AR5K_EEPROM_MODE_11B: - if (!AR5K_EEPROM_HDR_11B(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_b; - break; - case AR5K_EEPROM_MODE_11G: - if (!AR5K_EEPROM_HDR_11G(ee->ee_header)) - return 0; - chinfo = ee->ee_pwr_cal_g; - break; - default: - return -EINVAL; - } - - for (pier = 0; pier < ee->ee_n_piers[mode]; pier++) { - if (!chinfo[pier].pd_curves) - continue; - - for (pdg = 0; pdg < ee->ee_pd_gains[mode]; pdg++) { - struct ath5k_pdgain_info *pd = - &chinfo[pier].pd_curves[pdg]; - - if (pd != NULL) { - kfree(pd->pd_step); - kfree(pd->pd_pwr); - } - } - - kfree(chinfo[pier].pd_curves); - } - - return 0; -} - -void -ath5k_eeprom_detach(struct ath5k_hw *ah) -{ - u8 mode; - - for (mode = AR5K_EEPROM_MODE_11A; mode <= AR5K_EEPROM_MODE_11G; mode++) - ath5k_eeprom_free_pcal_info(ah, mode); -} - -/* Read conformance test limits used for regulatory control */ -static int -ath5k_eeprom_read_ctl_info(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_edge_power *rep; - unsigned int fmask, pmask; - unsigned int ctl_mode; - int ret, i, j; - u32 offset; - u16 val; - - pmask = AR5K_EEPROM_POWER_M; - fmask = AR5K_EEPROM_FREQ_M(ee->ee_version); - offset = AR5K_EEPROM_CTL(ee->ee_version); - ee->ee_ctls = AR5K_EEPROM_N_CTLS(ee->ee_version); - for (i = 0; i < ee->ee_ctls; i += 2) { - AR5K_EEPROM_READ(offset++, val); - ee->ee_ctl[i] = (val >> 8) & 0xff; - ee->ee_ctl[i + 1] = val & 0xff; - } - - offset = AR5K_EEPROM_GROUP8_OFFSET; - if (ee->ee_version >= AR5K_EEPROM_VERSION_4_0) - offset += AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1) - - AR5K_EEPROM_GROUP5_OFFSET; - else - offset += AR5K_EEPROM_GROUPS_START(ee->ee_version); - - rep = ee->ee_ctl_pwr; - for(i = 0; i < ee->ee_ctls; i++) { - switch(ee->ee_ctl[i] & AR5K_CTL_MODE_M) { - case AR5K_CTL_11A: - case AR5K_CTL_TURBO: - ctl_mode = AR5K_EEPROM_MODE_11A; - break; - default: - ctl_mode = AR5K_EEPROM_MODE_11G; - break; - } - if (ee->ee_ctl[i] == 0) { - if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) - offset += 8; - else - offset += 7; - rep += AR5K_EEPROM_N_EDGES; - continue; - } - if (ee->ee_version >= AR5K_EEPROM_VERSION_3_3) { - for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { - AR5K_EEPROM_READ(offset++, val); - rep[j].freq = (val >> 8) & fmask; - rep[j + 1].freq = val & fmask; - } - for (j = 0; j < AR5K_EEPROM_N_EDGES; j += 2) { - AR5K_EEPROM_READ(offset++, val); - rep[j].edge = (val >> 8) & pmask; - rep[j].flag = (val >> 14) & 1; - rep[j + 1].edge = val & pmask; - rep[j + 1].flag = (val >> 6) & 1; - } - } else { - AR5K_EEPROM_READ(offset++, val); - rep[0].freq = (val >> 9) & fmask; - rep[1].freq = (val >> 2) & fmask; - rep[2].freq = (val << 5) & fmask; - - AR5K_EEPROM_READ(offset++, val); - rep[2].freq |= (val >> 11) & 0x1f; - rep[3].freq = (val >> 4) & fmask; - rep[4].freq = (val << 3) & fmask; - - AR5K_EEPROM_READ(offset++, val); - rep[4].freq |= (val >> 13) & 0x7; - rep[5].freq = (val >> 6) & fmask; - rep[6].freq = (val << 1) & fmask; - - AR5K_EEPROM_READ(offset++, val); - rep[6].freq |= (val >> 15) & 0x1; - rep[7].freq = (val >> 8) & fmask; - - rep[0].edge = (val >> 2) & pmask; - rep[1].edge = (val << 4) & pmask; - - AR5K_EEPROM_READ(offset++, val); - rep[1].edge |= (val >> 12) & 0xf; - rep[2].edge = (val >> 6) & pmask; - rep[3].edge = val & pmask; - - AR5K_EEPROM_READ(offset++, val); - rep[4].edge = (val >> 10) & pmask; - rep[5].edge = (val >> 4) & pmask; - rep[6].edge = (val << 2) & pmask; - - AR5K_EEPROM_READ(offset++, val); - rep[6].edge |= (val >> 14) & 0x3; - rep[7].edge = (val >> 8) & pmask; - } - for (j = 0; j < AR5K_EEPROM_N_EDGES; j++) { - rep[j].freq = ath5k_eeprom_bin2freq(ee, - rep[j].freq, ctl_mode); - } - rep += AR5K_EEPROM_N_EDGES; - } - - return 0; -} - -static int -ath5k_eeprom_read_spur_chans(struct ath5k_hw *ah) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 offset; - u16 val; - int ret = 0, i; - - offset = AR5K_EEPROM_CTL(ee->ee_version) + - AR5K_EEPROM_N_CTLS(ee->ee_version); - - if (ee->ee_version < AR5K_EEPROM_VERSION_5_3) { - /* No spur info for 5GHz */ - ee->ee_spur_chans[0][0] = AR5K_EEPROM_NO_SPUR; - /* 2 channels for 2GHz (2464/2420) */ - ee->ee_spur_chans[0][1] = AR5K_EEPROM_5413_SPUR_CHAN_1; - ee->ee_spur_chans[1][1] = AR5K_EEPROM_5413_SPUR_CHAN_2; - ee->ee_spur_chans[2][1] = AR5K_EEPROM_NO_SPUR; - } else if (ee->ee_version >= AR5K_EEPROM_VERSION_5_3) { - for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { - AR5K_EEPROM_READ(offset, val); - ee->ee_spur_chans[i][0] = val; - AR5K_EEPROM_READ(offset + AR5K_EEPROM_N_SPUR_CHANS, - val); - ee->ee_spur_chans[i][1] = val; - offset++; - } - } - - return ret; -} - -/* - * Initialize eeprom data structure - */ -int -ath5k_eeprom_init(struct ath5k_hw *ah) -{ - int err; - - err = ath5k_eeprom_init_header(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_init_modes(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_read_pcal_info(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_read_ctl_info(ah); - if (err < 0) - return err; - - err = ath5k_eeprom_read_spur_chans(ah); - if (err < 0) - return err; - - return 0; -} - -/* - * Read the MAC address from eeprom - */ -int ath5k_eeprom_read_mac(struct ath5k_hw *ah, u8 *mac) -{ - u8 mac_d[ETH_ALEN] = {}; - u32 total, offset; - u16 data; - int octet, ret; - - ret = ath5k_hw_eeprom_read(ah, 0x20, &data); - if (ret) - return ret; - - for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) { - ret = ath5k_hw_eeprom_read(ah, offset, &data); - if (ret) - return ret; - - total += data; - mac_d[octet + 1] = data & 0xff; - mac_d[octet] = data >> 8; - octet += 2; - } - - if (!total || total == 3 * 0xffff) - return -EINVAL; - - memcpy(mac, mac_d, ETH_ALEN); - - return 0; -} diff --git a/drivers/net/wireless/ath/ath5k/eeprom.h b/drivers/net/wireless/ath/ath5k/eeprom.h deleted file mode 100644 index 473a483bb9c3..000000000000 --- a/drivers/net/wireless/ath/ath5k/eeprom.h +++ /dev/null @@ -1,479 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Common ar5xxx EEPROM data offsets (set these on AR5K_EEPROM_BASE) - */ -#define AR5K_EEPROM_PCIE_OFFSET 0x02 /* Contains offset to PCI-E infos */ -#define AR5K_EEPROM_PCIE_SERDES_SECTION 0x40 /* PCIE_OFFSET points here when - * SERDES infos are present */ -#define AR5K_EEPROM_MAGIC 0x003d /* EEPROM Magic number */ -#define AR5K_EEPROM_MAGIC_VALUE 0x5aa5 /* Default - found on EEPROM */ -#define AR5K_EEPROM_MAGIC_5212 0x0000145c /* 5212 */ -#define AR5K_EEPROM_MAGIC_5211 0x0000145b /* 5211 */ -#define AR5K_EEPROM_MAGIC_5210 0x0000145a /* 5210 */ - -#define AR5K_EEPROM_IS_HB63 0x000b /* Talon detect */ - -#define AR5K_EEPROM_RFKILL 0x0f -#define AR5K_EEPROM_RFKILL_GPIO_SEL 0x0000001c -#define AR5K_EEPROM_RFKILL_GPIO_SEL_S 2 -#define AR5K_EEPROM_RFKILL_POLARITY 0x00000002 -#define AR5K_EEPROM_RFKILL_POLARITY_S 1 - -#define AR5K_EEPROM_REG_DOMAIN 0x00bf /* EEPROM regdom */ - -/* FLASH(EEPROM) Defines for AR531X chips */ -#define AR5K_EEPROM_SIZE_LOWER 0x1b /* size info -- lower */ -#define AR5K_EEPROM_SIZE_UPPER 0x1c /* size info -- upper */ -#define AR5K_EEPROM_SIZE_UPPER_MASK 0xfff0 -#define AR5K_EEPROM_SIZE_UPPER_SHIFT 4 -#define AR5K_EEPROM_SIZE_ENDLOC_SHIFT 12 - -#define AR5K_EEPROM_CHECKSUM 0x00c0 /* EEPROM checksum */ -#define AR5K_EEPROM_INFO_BASE 0x00c0 /* EEPROM header */ -#define AR5K_EEPROM_INFO_MAX (0x400 - AR5K_EEPROM_INFO_BASE) -#define AR5K_EEPROM_INFO_CKSUM 0xffff -#define AR5K_EEPROM_INFO(_n) (AR5K_EEPROM_INFO_BASE + (_n)) - -#define AR5K_EEPROM_VERSION AR5K_EEPROM_INFO(1) /* EEPROM Version */ -#define AR5K_EEPROM_VERSION_3_0 0x3000 /* No idea what's going on before this version */ -#define AR5K_EEPROM_VERSION_3_1 0x3001 /* ob/db values for 2Ghz (ar5211_rfregs) */ -#define AR5K_EEPROM_VERSION_3_2 0x3002 /* different frequency representation (eeprom_bin2freq) */ -#define AR5K_EEPROM_VERSION_3_3 0x3003 /* offsets changed, has 32 CTLs (see below) and ee_false_detect (eeprom_read_modes) */ -#define AR5K_EEPROM_VERSION_3_4 0x3004 /* has ee_i_gain, ee_cck_ofdm_power_delta (eeprom_read_modes) */ -#define AR5K_EEPROM_VERSION_4_0 0x4000 /* has ee_misc, ee_cal_pier, ee_turbo_max_power and ee_xr_power (eeprom_init) */ -#define AR5K_EEPROM_VERSION_4_1 0x4001 /* has ee_margin_tx_rx (eeprom_init) */ -#define AR5K_EEPROM_VERSION_4_2 0x4002 /* has ee_cck_ofdm_gain_delta (eeprom_init) */ -#define AR5K_EEPROM_VERSION_4_3 0x4003 /* power calibration changes */ -#define AR5K_EEPROM_VERSION_4_4 0x4004 -#define AR5K_EEPROM_VERSION_4_5 0x4005 -#define AR5K_EEPROM_VERSION_4_6 0x4006 /* has ee_scaled_cck_delta */ -#define AR5K_EEPROM_VERSION_4_7 0x3007 /* 4007 ? */ -#define AR5K_EEPROM_VERSION_4_9 0x4009 /* EAR futureproofing */ -#define AR5K_EEPROM_VERSION_5_0 0x5000 /* Has 2413 PDADC calibration etc */ -#define AR5K_EEPROM_VERSION_5_1 0x5001 /* Has capability values */ -#define AR5K_EEPROM_VERSION_5_3 0x5003 /* Has spur mitigation tables */ - -#define AR5K_EEPROM_MODE_11A 0 -#define AR5K_EEPROM_MODE_11B 1 -#define AR5K_EEPROM_MODE_11G 2 - -#define AR5K_EEPROM_HDR AR5K_EEPROM_INFO(2) /* Header that contains the device caps */ -#define AR5K_EEPROM_HDR_11A(_v) (((_v) >> AR5K_EEPROM_MODE_11A) & 0x1) -#define AR5K_EEPROM_HDR_11B(_v) (((_v) >> AR5K_EEPROM_MODE_11B) & 0x1) -#define AR5K_EEPROM_HDR_11G(_v) (((_v) >> AR5K_EEPROM_MODE_11G) & 0x1) -#define AR5K_EEPROM_HDR_T_2GHZ_DIS(_v) (((_v) >> 3) & 0x1) /* Disable turbo for 2Ghz (?) */ -#define AR5K_EEPROM_HDR_T_5GHZ_DBM(_v) (((_v) >> 4) & 0x7f) /* Max turbo power for a/XR mode (eeprom_init) */ -#define AR5K_EEPROM_HDR_DEVICE(_v) (((_v) >> 11) & 0x7) -#define AR5K_EEPROM_HDR_RFKILL(_v) (((_v) >> 14) & 0x1) /* Device has RFKill support */ -#define AR5K_EEPROM_HDR_T_5GHZ_DIS(_v) (((_v) >> 15) & 0x1) /* Disable turbo for 5Ghz */ - -/* Newer EEPROMs are using a different offset */ -#define AR5K_EEPROM_OFF(_v, _v3_0, _v3_3) \ - (((_v) >= AR5K_EEPROM_VERSION_3_3) ? _v3_3 : _v3_0) - -#define AR5K_EEPROM_ANT_GAIN(_v) AR5K_EEPROM_OFF(_v, 0x00c4, 0x00c3) -#define AR5K_EEPROM_ANT_GAIN_5GHZ(_v) ((s8)(((_v) >> 8) & 0xff)) -#define AR5K_EEPROM_ANT_GAIN_2GHZ(_v) ((s8)((_v) & 0xff)) - -/* Misc values available since EEPROM 4.0 */ -#define AR5K_EEPROM_MISC0 AR5K_EEPROM_INFO(4) -#define AR5K_EEPROM_EARSTART(_v) ((_v) & 0xfff) -#define AR5K_EEPROM_HDR_XR2_DIS(_v) (((_v) >> 12) & 0x1) -#define AR5K_EEPROM_HDR_XR5_DIS(_v) (((_v) >> 13) & 0x1) -#define AR5K_EEPROM_EEMAP(_v) (((_v) >> 14) & 0x3) - -#define AR5K_EEPROM_MISC1 AR5K_EEPROM_INFO(5) -#define AR5K_EEPROM_TARGET_PWRSTART(_v) ((_v) & 0xfff) -#define AR5K_EEPROM_HAS32KHZCRYSTAL(_v) (((_v) >> 14) & 0x1) -#define AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(_v) (((_v) >> 15) & 0x1) - -#define AR5K_EEPROM_MISC2 AR5K_EEPROM_INFO(6) -#define AR5K_EEPROM_EEP_FILE_VERSION(_v) (((_v) >> 8) & 0xff) -#define AR5K_EEPROM_EAR_FILE_VERSION(_v) ((_v) & 0xff) - -#define AR5K_EEPROM_MISC3 AR5K_EEPROM_INFO(7) -#define AR5K_EEPROM_ART_BUILD_NUM(_v) (((_v) >> 10) & 0x3f) -#define AR5K_EEPROM_EAR_FILE_ID(_v) ((_v) & 0xff) - -#define AR5K_EEPROM_MISC4 AR5K_EEPROM_INFO(8) -#define AR5K_EEPROM_CAL_DATA_START(_v) (((_v) >> 4) & 0xfff) -#define AR5K_EEPROM_MASK_R0(_v) (((_v) >> 2) & 0x3) -#define AR5K_EEPROM_MASK_R1(_v) ((_v) & 0x3) - -#define AR5K_EEPROM_MISC5 AR5K_EEPROM_INFO(9) -#define AR5K_EEPROM_COMP_DIS(_v) ((_v) & 0x1) -#define AR5K_EEPROM_AES_DIS(_v) (((_v) >> 1) & 0x1) -#define AR5K_EEPROM_FF_DIS(_v) (((_v) >> 2) & 0x1) -#define AR5K_EEPROM_BURST_DIS(_v) (((_v) >> 3) & 0x1) -#define AR5K_EEPROM_MAX_QCU(_v) (((_v) >> 4) & 0xf) -#define AR5K_EEPROM_HEAVY_CLIP_EN(_v) (((_v) >> 8) & 0x1) -#define AR5K_EEPROM_KEY_CACHE_SIZE(_v) (((_v) >> 12) & 0xf) - -#define AR5K_EEPROM_MISC6 AR5K_EEPROM_INFO(10) -#define AR5K_EEPROM_TX_CHAIN_DIS ((_v) & 0x8) -#define AR5K_EEPROM_RX_CHAIN_DIS (((_v) >> 3) & 0x8) -#define AR5K_EEPROM_FCC_MID_EN (((_v) >> 6) & 0x1) -#define AR5K_EEPROM_JAP_U1EVEN_EN (((_v) >> 7) & 0x1) -#define AR5K_EEPROM_JAP_U2_EN (((_v) >> 8) & 0x1) -#define AR5K_EEPROM_JAP_U1ODD_EN (((_v) >> 9) & 0x1) -#define AR5K_EEPROM_JAP_11A_NEW_EN (((_v) >> 10) & 0x1) - -/* calibration settings */ -#define AR5K_EEPROM_MODES_11A(_v) AR5K_EEPROM_OFF(_v, 0x00c5, 0x00d4) -#define AR5K_EEPROM_MODES_11B(_v) AR5K_EEPROM_OFF(_v, 0x00d0, 0x00f2) -#define AR5K_EEPROM_MODES_11G(_v) AR5K_EEPROM_OFF(_v, 0x00da, 0x010d) -#define AR5K_EEPROM_CTL(_v) AR5K_EEPROM_OFF(_v, 0x00e4, 0x0128) /* Conformance test limits */ -#define AR5K_EEPROM_GROUPS_START(_v) AR5K_EEPROM_OFF(_v, 0x0100, 0x0150) /* Start of Groups */ -#define AR5K_EEPROM_GROUP1_OFFSET 0x0 -#define AR5K_EEPROM_GROUP2_OFFSET 0x5 -#define AR5K_EEPROM_GROUP3_OFFSET 0x37 -#define AR5K_EEPROM_GROUP4_OFFSET 0x46 -#define AR5K_EEPROM_GROUP5_OFFSET 0x55 -#define AR5K_EEPROM_GROUP6_OFFSET 0x65 -#define AR5K_EEPROM_GROUP7_OFFSET 0x69 -#define AR5K_EEPROM_GROUP8_OFFSET 0x6f - -#define AR5K_EEPROM_TARGET_PWR_OFF_11A(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ - AR5K_EEPROM_GROUP5_OFFSET, 0x0000) -#define AR5K_EEPROM_TARGET_PWR_OFF_11B(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ - AR5K_EEPROM_GROUP6_OFFSET, 0x0010) -#define AR5K_EEPROM_TARGET_PWR_OFF_11G(_v) AR5K_EEPROM_OFF(_v, AR5K_EEPROM_GROUPS_START(_v) + \ - AR5K_EEPROM_GROUP7_OFFSET, 0x0014) - -/* [3.1 - 3.3] */ -#define AR5K_EEPROM_OBDB0_2GHZ 0x00ec -#define AR5K_EEPROM_OBDB1_2GHZ 0x00ed - -#define AR5K_EEPROM_PROTECT 0x003f /* EEPROM protect status */ -#define AR5K_EEPROM_PROTECT_RD_0_31 0x0001 /* Read protection bit for offsets 0x0 - 0x1f */ -#define AR5K_EEPROM_PROTECT_WR_0_31 0x0002 /* Write protection bit for offsets 0x0 - 0x1f */ -#define AR5K_EEPROM_PROTECT_RD_32_63 0x0004 /* 0x20 - 0x3f */ -#define AR5K_EEPROM_PROTECT_WR_32_63 0x0008 -#define AR5K_EEPROM_PROTECT_RD_64_127 0x0010 /* 0x40 - 0x7f */ -#define AR5K_EEPROM_PROTECT_WR_64_127 0x0020 -#define AR5K_EEPROM_PROTECT_RD_128_191 0x0040 /* 0x80 - 0xbf (regdom) */ -#define AR5K_EEPROM_PROTECT_WR_128_191 0x0080 -#define AR5K_EEPROM_PROTECT_RD_192_207 0x0100 /* 0xc0 - 0xcf */ -#define AR5K_EEPROM_PROTECT_WR_192_207 0x0200 -#define AR5K_EEPROM_PROTECT_RD_208_223 0x0400 /* 0xd0 - 0xdf */ -#define AR5K_EEPROM_PROTECT_WR_208_223 0x0800 -#define AR5K_EEPROM_PROTECT_RD_224_239 0x1000 /* 0xe0 - 0xef */ -#define AR5K_EEPROM_PROTECT_WR_224_239 0x2000 -#define AR5K_EEPROM_PROTECT_RD_240_255 0x4000 /* 0xf0 - 0xff */ -#define AR5K_EEPROM_PROTECT_WR_240_255 0x8000 - -/* Some EEPROM defines */ -#define AR5K_EEPROM_EEP_SCALE 100 -#define AR5K_EEPROM_EEP_DELTA 10 -#define AR5K_EEPROM_N_MODES 3 -#define AR5K_EEPROM_N_5GHZ_CHAN 10 -#define AR5K_EEPROM_N_2GHZ_CHAN 3 -#define AR5K_EEPROM_N_2GHZ_CHAN_2413 4 -#define AR5K_EEPROM_N_2GHZ_CHAN_MAX 4 -#define AR5K_EEPROM_MAX_CHAN 10 -#define AR5K_EEPROM_N_PWR_POINTS_5111 11 -#define AR5K_EEPROM_N_PCDAC 11 -#define AR5K_EEPROM_N_PHASE_CAL 5 -#define AR5K_EEPROM_N_TEST_FREQ 8 -#define AR5K_EEPROM_N_EDGES 8 -#define AR5K_EEPROM_N_INTERCEPTS 11 -#define AR5K_EEPROM_FREQ_M(_v) AR5K_EEPROM_OFF(_v, 0x7f, 0xff) -#define AR5K_EEPROM_PCDAC_M 0x3f -#define AR5K_EEPROM_PCDAC_START 1 -#define AR5K_EEPROM_PCDAC_STOP 63 -#define AR5K_EEPROM_PCDAC_STEP 1 -#define AR5K_EEPROM_NON_EDGE_M 0x40 -#define AR5K_EEPROM_CHANNEL_POWER 8 -#define AR5K_EEPROM_N_OBDB 4 -#define AR5K_EEPROM_OBDB_DIS 0xffff -#define AR5K_EEPROM_CHANNEL_DIS 0xff -#define AR5K_EEPROM_SCALE_OC_DELTA(_x) (((_x) * 2) / 10) -#define AR5K_EEPROM_N_CTLS(_v) AR5K_EEPROM_OFF(_v, 16, 32) -#define AR5K_EEPROM_MAX_CTLS 32 -#define AR5K_EEPROM_N_PD_CURVES 4 -#define AR5K_EEPROM_N_XPD0_POINTS 4 -#define AR5K_EEPROM_N_XPD3_POINTS 3 -#define AR5K_EEPROM_N_PD_GAINS 4 -#define AR5K_EEPROM_N_PD_POINTS 5 -#define AR5K_EEPROM_N_INTERCEPT_10_2GHZ 35 -#define AR5K_EEPROM_N_INTERCEPT_10_5GHZ 55 -#define AR5K_EEPROM_POWER_M 0x3f -#define AR5K_EEPROM_POWER_MIN 0 -#define AR5K_EEPROM_POWER_MAX 3150 -#define AR5K_EEPROM_POWER_STEP 50 -#define AR5K_EEPROM_POWER_TABLE_SIZE 64 -#define AR5K_EEPROM_N_POWER_LOC_11B 4 -#define AR5K_EEPROM_N_POWER_LOC_11G 6 -#define AR5K_EEPROM_I_GAIN 10 -#define AR5K_EEPROM_CCK_OFDM_DELTA 15 -#define AR5K_EEPROM_N_IQ_CAL 2 -/* 5GHz/2GHz */ -enum ath5k_eeprom_freq_bands{ - AR5K_EEPROM_BAND_5GHZ = 0, - AR5K_EEPROM_BAND_2GHZ = 1, - AR5K_EEPROM_N_FREQ_BANDS, -}; -/* Spur chans per freq band */ -#define AR5K_EEPROM_N_SPUR_CHANS 5 -/* fbin value for chan 2464 x2 */ -#define AR5K_EEPROM_5413_SPUR_CHAN_1 1640 -/* fbin value for chan 2420 x2 */ -#define AR5K_EEPROM_5413_SPUR_CHAN_2 1200 -#define AR5K_EEPROM_SPUR_CHAN_MASK 0x3FFF -#define AR5K_EEPROM_NO_SPUR 0x8000 -#define AR5K_SPUR_CHAN_WIDTH 87 -#define AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz 3125 -#define AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz 6250 - -#define AR5K_EEPROM_READ(_o, _v) do { \ - ret = ath5k_hw_eeprom_read(ah, (_o), &(_v)); \ - if (ret) \ - return ret; \ -} while (0) - -#define AR5K_EEPROM_READ_HDR(_o, _v) \ - AR5K_EEPROM_READ(_o, ah->ah_capabilities.cap_eeprom._v); \ - -enum ath5k_ant_table { - AR5K_ANT_CTL = 0, /* Idle switch table settings */ - AR5K_ANT_SWTABLE_A = 1, /* Switch table for antenna A */ - AR5K_ANT_SWTABLE_B = 2, /* Switch table for antenna B */ - AR5K_ANT_MAX, -}; - -enum ath5k_ctl_mode { - AR5K_CTL_11A = 0, - AR5K_CTL_11B = 1, - AR5K_CTL_11G = 2, - AR5K_CTL_TURBO = 3, - AR5K_CTL_TURBOG = 4, - AR5K_CTL_2GHT20 = 5, - AR5K_CTL_5GHT20 = 6, - AR5K_CTL_2GHT40 = 7, - AR5K_CTL_5GHT40 = 8, - AR5K_CTL_MODE_M = 15, -}; - -/* Default CTL ids for the 3 main reg domains. - * Atheros only uses these by default but vendors - * can have up to 32 different CTLs for different - * scenarios. Note that theese values are ORed with - * the mode id (above) so we can have up to 24 CTL - * datasets out of these 3 main regdomains. That leaves - * 8 ids that can be used by vendors and since 0x20 is - * missing from HAL sources i guess this is the set of - * custom CTLs vendors can use. */ -#define AR5K_CTL_FCC 0x10 -#define AR5K_CTL_CUSTOM 0x20 -#define AR5K_CTL_ETSI 0x30 -#define AR5K_CTL_MKK 0x40 - -/* Indicates a CTL with only mode set and - * no reg domain mapping, such CTLs are used - * for world roaming domains or simply when - * a reg domain is not set */ -#define AR5K_CTL_NO_REGDOMAIN 0xf0 - -/* Indicates an empty (invalid) CTL */ -#define AR5K_CTL_NO_CTL 0xff - -/* Per channel calibration data, used for power table setup */ -struct ath5k_chan_pcal_info_rf5111 { - /* Power levels in half dbm units - * for one power curve. */ - u8 pwr[AR5K_EEPROM_N_PWR_POINTS_5111]; - /* PCDAC table steps - * for the above values */ - u8 pcdac[AR5K_EEPROM_N_PWR_POINTS_5111]; - /* Starting PCDAC step */ - u8 pcdac_min; - /* Final PCDAC step */ - u8 pcdac_max; -}; - -struct ath5k_chan_pcal_info_rf5112 { - /* Power levels in quarter dBm units - * for lower (0) and higher (3) - * level curves in 0.25dB units */ - s8 pwr_x0[AR5K_EEPROM_N_XPD0_POINTS]; - s8 pwr_x3[AR5K_EEPROM_N_XPD3_POINTS]; - /* PCDAC table steps - * for the above values */ - u8 pcdac_x0[AR5K_EEPROM_N_XPD0_POINTS]; - u8 pcdac_x3[AR5K_EEPROM_N_XPD3_POINTS]; -}; - -struct ath5k_chan_pcal_info_rf2413 { - /* Starting pwr/pddac values */ - s8 pwr_i[AR5K_EEPROM_N_PD_GAINS]; - u8 pddac_i[AR5K_EEPROM_N_PD_GAINS]; - /* (pwr,pddac) points - * power levels in 0.5dB units */ - s8 pwr[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_N_PD_POINTS]; - u8 pddac[AR5K_EEPROM_N_PD_GAINS] - [AR5K_EEPROM_N_PD_POINTS]; -}; - -enum ath5k_powertable_type { - AR5K_PWRTABLE_PWR_TO_PCDAC = 0, - AR5K_PWRTABLE_LINEAR_PCDAC = 1, - AR5K_PWRTABLE_PWR_TO_PDADC = 2, -}; - -struct ath5k_pdgain_info { - u8 pd_points; - u8 *pd_step; - /* Power values are in - * 0.25dB units */ - s16 *pd_pwr; -}; - -struct ath5k_chan_pcal_info { - /* Frequency */ - u16 freq; - /* Tx power boundaries */ - s16 max_pwr; - s16 min_pwr; - union { - struct ath5k_chan_pcal_info_rf5111 rf5111_info; - struct ath5k_chan_pcal_info_rf5112 rf5112_info; - struct ath5k_chan_pcal_info_rf2413 rf2413_info; - }; - /* Raw values used by phy code - * Curves are stored in order from lower - * gain to higher gain (max txpower -> min txpower) */ - struct ath5k_pdgain_info *pd_curves; -}; - -/* Per rate calibration data for each mode, - * used for rate power table setup. - * Note: Values in 0.5dB units */ -struct ath5k_rate_pcal_info { - u16 freq; /* Frequency */ - /* Power level for 6-24Mbit/s rates or - * 1Mb rate */ - u16 target_power_6to24; - /* Power level for 36Mbit rate or - * 2Mb rate */ - u16 target_power_36; - /* Power level for 48Mbit rate or - * 5.5Mbit rate */ - u16 target_power_48; - /* Power level for 54Mbit rate or - * 11Mbit rate */ - u16 target_power_54; -}; - -/* Power edges for conformance test limits */ -struct ath5k_edge_power { - u16 freq; - u16 edge; /* in half dBm */ - bool flag; -}; - -/* EEPROM calibration data */ -struct ath5k_eeprom_info { - - /* Header information */ - u16 ee_magic; - u16 ee_protect; - u16 ee_regdomain; - u16 ee_version; - u16 ee_header; - u16 ee_ant_gain; - u8 ee_rfkill_pin; - bool ee_rfkill_pol; - bool ee_is_hb63; - bool ee_serdes; - u16 ee_misc0; - u16 ee_misc1; - u16 ee_misc2; - u16 ee_misc3; - u16 ee_misc4; - u16 ee_misc5; - u16 ee_misc6; - u16 ee_cck_ofdm_gain_delta; - u16 ee_cck_ofdm_power_delta; - u16 ee_scaled_cck_delta; - - /* RF Calibration settings (reset, rfregs) */ - u16 ee_i_cal[AR5K_EEPROM_N_MODES]; - u16 ee_q_cal[AR5K_EEPROM_N_MODES]; - u16 ee_fixed_bias[AR5K_EEPROM_N_MODES]; - u16 ee_turbo_max_power[AR5K_EEPROM_N_MODES]; - u16 ee_xr_power[AR5K_EEPROM_N_MODES]; - u16 ee_switch_settling[AR5K_EEPROM_N_MODES]; - u16 ee_atn_tx_rx[AR5K_EEPROM_N_MODES]; - u16 ee_ant_control[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PCDAC]; - u16 ee_ob[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; - u16 ee_db[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_OBDB]; - u16 ee_tx_end2xlna_enable[AR5K_EEPROM_N_MODES]; - u16 ee_tx_end2xpa_disable[AR5K_EEPROM_N_MODES]; - u16 ee_tx_frm2xpa_enable[AR5K_EEPROM_N_MODES]; - u16 ee_thr_62[AR5K_EEPROM_N_MODES]; - u16 ee_xlna_gain[AR5K_EEPROM_N_MODES]; - u16 ee_xpd[AR5K_EEPROM_N_MODES]; - u16 ee_x_gain[AR5K_EEPROM_N_MODES]; - u16 ee_i_gain[AR5K_EEPROM_N_MODES]; - u16 ee_margin_tx_rx[AR5K_EEPROM_N_MODES]; - u16 ee_switch_settling_turbo[AR5K_EEPROM_N_MODES]; - u16 ee_margin_tx_rx_turbo[AR5K_EEPROM_N_MODES]; - u16 ee_atn_tx_rx_turbo[AR5K_EEPROM_N_MODES]; - - /* Power calibration data */ - u16 ee_false_detect[AR5K_EEPROM_N_MODES]; - - /* Number of pd gain curves per mode */ - u8 ee_pd_gains[AR5K_EEPROM_N_MODES]; - /* Back mapping pdcurve number -> pdcurve index in pd->pd_curves */ - u8 ee_pdc_to_idx[AR5K_EEPROM_N_MODES][AR5K_EEPROM_N_PD_GAINS]; - - u8 ee_n_piers[AR5K_EEPROM_N_MODES]; - struct ath5k_chan_pcal_info ee_pwr_cal_a[AR5K_EEPROM_N_5GHZ_CHAN]; - struct ath5k_chan_pcal_info ee_pwr_cal_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - struct ath5k_chan_pcal_info ee_pwr_cal_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - - /* Per rate target power levels */ - u8 ee_rate_target_pwr_num[AR5K_EEPROM_N_MODES]; - struct ath5k_rate_pcal_info ee_rate_tpwr_a[AR5K_EEPROM_N_5GHZ_CHAN]; - struct ath5k_rate_pcal_info ee_rate_tpwr_b[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - struct ath5k_rate_pcal_info ee_rate_tpwr_g[AR5K_EEPROM_N_2GHZ_CHAN_MAX]; - - /* Conformance test limits (Unused) */ - u8 ee_ctls; - u8 ee_ctl[AR5K_EEPROM_MAX_CTLS]; - struct ath5k_edge_power ee_ctl_pwr[AR5K_EEPROM_N_EDGES * AR5K_EEPROM_MAX_CTLS]; - - /* Noise Floor Calibration settings */ - s16 ee_noise_floor_thr[AR5K_EEPROM_N_MODES]; - s8 ee_adc_desired_size[AR5K_EEPROM_N_MODES]; - s8 ee_pga_desired_size[AR5K_EEPROM_N_MODES]; - s8 ee_adc_desired_size_turbo[AR5K_EEPROM_N_MODES]; - s8 ee_pga_desired_size_turbo[AR5K_EEPROM_N_MODES]; - s8 ee_pd_gain_overlap; - - /* Spur mitigation data (fbin values for spur channels) */ - u16 ee_spur_chans[AR5K_EEPROM_N_SPUR_CHANS][AR5K_EEPROM_N_FREQ_BANDS]; - - /* Antenna raw switch tables */ - u32 ee_antenna[AR5K_EEPROM_N_MODES][AR5K_ANT_MAX]; -}; - diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c deleted file mode 100644 index 64a27e73d02e..000000000000 --- a/drivers/net/wireless/ath/ath5k/gpio.c +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/****************\ - GPIO Functions -\****************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Set led state - */ -void ath5k_hw_set_ledstate(struct ath5k_hw *ah, unsigned int state) -{ - u32 led; - /*5210 has different led mode handling*/ - u32 led_5210; - - ATH5K_TRACE(ah->ah_sc); - - /*Reset led status*/ - if (ah->ah_version != AR5K_AR5210) - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_LEDMODE | AR5K_PCICFG_LED); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, AR5K_PCICFG_LED); - - /* - * Some blinking values, define at your wish - */ - switch (state) { - case AR5K_LED_SCAN: - case AR5K_LED_AUTH: - led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_PEND; - led_5210 = AR5K_PCICFG_LED_PEND | AR5K_PCICFG_LED_BCTL; - break; - - case AR5K_LED_INIT: - led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_NONE; - led_5210 = AR5K_PCICFG_LED_PEND; - break; - - case AR5K_LED_ASSOC: - case AR5K_LED_RUN: - led = AR5K_PCICFG_LEDMODE_PROP | AR5K_PCICFG_LED_ASSOC; - led_5210 = AR5K_PCICFG_LED_ASSOC; - break; - - default: - led = AR5K_PCICFG_LEDMODE_PROM | AR5K_PCICFG_LED_NONE; - led_5210 = AR5K_PCICFG_LED_PEND; - break; - } - - /*Write new status to the register*/ - if (ah->ah_version != AR5K_AR5210) - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led); - else - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, led_5210); -} - -/* - * Set GPIO inputs - */ -int ath5k_hw_set_gpio_input(struct ath5k_hw *ah, u32 gpio) -{ - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return -EINVAL; - - ath5k_hw_reg_write(ah, - (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) - | AR5K_GPIOCR_IN(gpio), AR5K_GPIOCR); - - return 0; -} - -/* - * Set GPIO outputs - */ -int ath5k_hw_set_gpio_output(struct ath5k_hw *ah, u32 gpio) -{ - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return -EINVAL; - - ath5k_hw_reg_write(ah, - (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & ~AR5K_GPIOCR_OUT(gpio)) - | AR5K_GPIOCR_OUT(gpio), AR5K_GPIOCR); - - return 0; -} - -/* - * Get GPIO state - */ -u32 ath5k_hw_get_gpio(struct ath5k_hw *ah, u32 gpio) -{ - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return 0xffffffff; - - /* GPIO input magic */ - return ((ath5k_hw_reg_read(ah, AR5K_GPIODI) & AR5K_GPIODI_M) >> gpio) & - 0x1; -} - -/* - * Set GPIO state - */ -int ath5k_hw_set_gpio(struct ath5k_hw *ah, u32 gpio, u32 val) -{ - u32 data; - ATH5K_TRACE(ah->ah_sc); - - if (gpio >= AR5K_NUM_GPIO) - return -EINVAL; - - /* GPIO output magic */ - data = ath5k_hw_reg_read(ah, AR5K_GPIODO); - - data &= ~(1 << gpio); - data |= (val & 1) << gpio; - - ath5k_hw_reg_write(ah, data, AR5K_GPIODO); - - return 0; -} - -/* - * Initialize the GPIO interrupt (RFKill switch) - */ -void ath5k_hw_set_gpio_intr(struct ath5k_hw *ah, unsigned int gpio, - u32 interrupt_level) -{ - u32 data; - - ATH5K_TRACE(ah->ah_sc); - if (gpio >= AR5K_NUM_GPIO) - return; - - /* - * Set the GPIO interrupt - */ - data = (ath5k_hw_reg_read(ah, AR5K_GPIOCR) & - ~(AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_SELH | - AR5K_GPIOCR_INT_ENA | AR5K_GPIOCR_OUT(gpio))) | - (AR5K_GPIOCR_INT_SEL(gpio) | AR5K_GPIOCR_INT_ENA); - - ath5k_hw_reg_write(ah, interrupt_level ? data : - (data | AR5K_GPIOCR_INT_SELH), AR5K_GPIOCR); - - ah->ah_imr |= AR5K_IMR_GPIO; - - /* Enable GPIO interrupts */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PIMR, AR5K_IMR_GPIO); -} - diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c deleted file mode 100644 index 18eb5190ce4b..000000000000 --- a/drivers/net/wireless/ath/ath5k/initvals.c +++ /dev/null @@ -1,1555 +0,0 @@ -/* - * Initial register settings functions - * - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Mode-independent initial register writes - */ - -struct ath5k_ini { - u16 ini_register; - u32 ini_value; - - enum { - AR5K_INI_WRITE = 0, /* Default */ - AR5K_INI_READ = 1, /* Cleared on read */ - } ini_mode; -}; - -/* - * Mode specific initial register values - */ - -struct ath5k_ini_mode { - u16 mode_register; - u32 mode_value[5]; -}; - -/* Initial register settings for AR5210 */ -static const struct ath5k_ini ar5210_ini[] = { - /* PCU and MAC registers */ - { AR5K_NOQCU_TXDP0, 0 }, - { AR5K_NOQCU_TXDP1, 0 }, - { AR5K_RXDP, 0 }, - { AR5K_CR, 0 }, - { AR5K_ISR, 0, AR5K_INI_READ }, - { AR5K_IMR, 0 }, - { AR5K_IER, AR5K_IER_DISABLE }, - { AR5K_BSR, 0, AR5K_INI_READ }, - { AR5K_TXCFG, AR5K_DMASIZE_128B }, - { AR5K_RXCFG, AR5K_DMASIZE_128B }, - { AR5K_CFG, AR5K_INIT_CFG }, - { AR5K_TOPS, 8 }, - { AR5K_RXNOFRM, 8 }, - { AR5K_RPGTO, 0 }, - { AR5K_TXNOFRM, 0 }, - { AR5K_SFR, 0 }, - { AR5K_MIBC, 0 }, - { AR5K_MISC, 0 }, - { AR5K_RX_FILTER_5210, 0 }, - { AR5K_MCAST_FILTER0_5210, 0 }, - { AR5K_MCAST_FILTER1_5210, 0 }, - { AR5K_TX_MASK0, 0 }, - { AR5K_TX_MASK1, 0 }, - { AR5K_CLR_TMASK, 0 }, - { AR5K_TRIG_LVL, AR5K_TUNE_MIN_TX_FIFO_THRES }, - { AR5K_DIAG_SW_5210, 0 }, - { AR5K_RSSI_THR, AR5K_TUNE_RSSI_THRES }, - { AR5K_TSF_L32_5210, 0 }, - { AR5K_TIMER0_5210, 0 }, - { AR5K_TIMER1_5210, 0xffffffff }, - { AR5K_TIMER2_5210, 0xffffffff }, - { AR5K_TIMER3_5210, 1 }, - { AR5K_CFP_DUR_5210, 0 }, - { AR5K_CFP_PERIOD_5210, 0 }, - /* PHY registers */ - { AR5K_PHY(0), 0x00000047 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY(3), 0x09848ea6 }, - { AR5K_PHY(4), 0x3d32e000 }, - { AR5K_PHY(5), 0x0000076b }, - { AR5K_PHY_ACT, AR5K_PHY_ACT_DISABLE }, - { AR5K_PHY(8), 0x02020200 }, - { AR5K_PHY(9), 0x00000e0e }, - { AR5K_PHY(10), 0x0a020201 }, - { AR5K_PHY(11), 0x00036ffc }, - { AR5K_PHY(12), 0x00000000 }, - { AR5K_PHY(13), 0x00000e0e }, - { AR5K_PHY(14), 0x00000007 }, - { AR5K_PHY(15), 0x00020100 }, - { AR5K_PHY(16), 0x89630000 }, - { AR5K_PHY(17), 0x1372169c }, - { AR5K_PHY(18), 0x0018b633 }, - { AR5K_PHY(19), 0x1284613c }, - { AR5K_PHY(20), 0x0de8b8e0 }, - { AR5K_PHY(21), 0x00074859 }, - { AR5K_PHY(22), 0x7e80beba }, - { AR5K_PHY(23), 0x313a665e }, - { AR5K_PHY_AGCCTL, 0x00001d08 }, - { AR5K_PHY(25), 0x0001ce00 }, - { AR5K_PHY(26), 0x409a4190 }, - { AR5K_PHY(28), 0x0000000f }, - { AR5K_PHY(29), 0x00000080 }, - { AR5K_PHY(30), 0x00000004 }, - { AR5K_PHY(31), 0x00000018 }, /* 0x987c */ - { AR5K_PHY(64), 0x00000000 }, /* 0x9900 */ - { AR5K_PHY(65), 0x00000000 }, - { AR5K_PHY(66), 0x00000000 }, - { AR5K_PHY(67), 0x00800000 }, - { AR5K_PHY(68), 0x00000003 }, - /* BB gain table (64bytes) */ - { AR5K_BB_GAIN(0), 0x00000000 }, - { AR5K_BB_GAIN(1), 0x00000020 }, - { AR5K_BB_GAIN(2), 0x00000010 }, - { AR5K_BB_GAIN(3), 0x00000030 }, - { AR5K_BB_GAIN(4), 0x00000008 }, - { AR5K_BB_GAIN(5), 0x00000028 }, - { AR5K_BB_GAIN(6), 0x00000028 }, - { AR5K_BB_GAIN(7), 0x00000004 }, - { AR5K_BB_GAIN(8), 0x00000024 }, - { AR5K_BB_GAIN(9), 0x00000014 }, - { AR5K_BB_GAIN(10), 0x00000034 }, - { AR5K_BB_GAIN(11), 0x0000000c }, - { AR5K_BB_GAIN(12), 0x0000002c }, - { AR5K_BB_GAIN(13), 0x00000002 }, - { AR5K_BB_GAIN(14), 0x00000022 }, - { AR5K_BB_GAIN(15), 0x00000012 }, - { AR5K_BB_GAIN(16), 0x00000032 }, - { AR5K_BB_GAIN(17), 0x0000000a }, - { AR5K_BB_GAIN(18), 0x0000002a }, - { AR5K_BB_GAIN(19), 0x00000001 }, - { AR5K_BB_GAIN(20), 0x00000021 }, - { AR5K_BB_GAIN(21), 0x00000011 }, - { AR5K_BB_GAIN(22), 0x00000031 }, - { AR5K_BB_GAIN(23), 0x00000009 }, - { AR5K_BB_GAIN(24), 0x00000029 }, - { AR5K_BB_GAIN(25), 0x00000005 }, - { AR5K_BB_GAIN(26), 0x00000025 }, - { AR5K_BB_GAIN(27), 0x00000015 }, - { AR5K_BB_GAIN(28), 0x00000035 }, - { AR5K_BB_GAIN(29), 0x0000000d }, - { AR5K_BB_GAIN(30), 0x0000002d }, - { AR5K_BB_GAIN(31), 0x00000003 }, - { AR5K_BB_GAIN(32), 0x00000023 }, - { AR5K_BB_GAIN(33), 0x00000013 }, - { AR5K_BB_GAIN(34), 0x00000033 }, - { AR5K_BB_GAIN(35), 0x0000000b }, - { AR5K_BB_GAIN(36), 0x0000002b }, - { AR5K_BB_GAIN(37), 0x00000007 }, - { AR5K_BB_GAIN(38), 0x00000027 }, - { AR5K_BB_GAIN(39), 0x00000017 }, - { AR5K_BB_GAIN(40), 0x00000037 }, - { AR5K_BB_GAIN(41), 0x0000000f }, - { AR5K_BB_GAIN(42), 0x0000002f }, - { AR5K_BB_GAIN(43), 0x0000002f }, - { AR5K_BB_GAIN(44), 0x0000002f }, - { AR5K_BB_GAIN(45), 0x0000002f }, - { AR5K_BB_GAIN(46), 0x0000002f }, - { AR5K_BB_GAIN(47), 0x0000002f }, - { AR5K_BB_GAIN(48), 0x0000002f }, - { AR5K_BB_GAIN(49), 0x0000002f }, - { AR5K_BB_GAIN(50), 0x0000002f }, - { AR5K_BB_GAIN(51), 0x0000002f }, - { AR5K_BB_GAIN(52), 0x0000002f }, - { AR5K_BB_GAIN(53), 0x0000002f }, - { AR5K_BB_GAIN(54), 0x0000002f }, - { AR5K_BB_GAIN(55), 0x0000002f }, - { AR5K_BB_GAIN(56), 0x0000002f }, - { AR5K_BB_GAIN(57), 0x0000002f }, - { AR5K_BB_GAIN(58), 0x0000002f }, - { AR5K_BB_GAIN(59), 0x0000002f }, - { AR5K_BB_GAIN(60), 0x0000002f }, - { AR5K_BB_GAIN(61), 0x0000002f }, - { AR5K_BB_GAIN(62), 0x0000002f }, - { AR5K_BB_GAIN(63), 0x0000002f }, - /* 5110 RF gain table (64btes) */ - { AR5K_RF_GAIN(0), 0x0000001d }, - { AR5K_RF_GAIN(1), 0x0000005d }, - { AR5K_RF_GAIN(2), 0x0000009d }, - { AR5K_RF_GAIN(3), 0x000000dd }, - { AR5K_RF_GAIN(4), 0x0000011d }, - { AR5K_RF_GAIN(5), 0x00000021 }, - { AR5K_RF_GAIN(6), 0x00000061 }, - { AR5K_RF_GAIN(7), 0x000000a1 }, - { AR5K_RF_GAIN(8), 0x000000e1 }, - { AR5K_RF_GAIN(9), 0x00000031 }, - { AR5K_RF_GAIN(10), 0x00000071 }, - { AR5K_RF_GAIN(11), 0x000000b1 }, - { AR5K_RF_GAIN(12), 0x0000001c }, - { AR5K_RF_GAIN(13), 0x0000005c }, - { AR5K_RF_GAIN(14), 0x00000029 }, - { AR5K_RF_GAIN(15), 0x00000069 }, - { AR5K_RF_GAIN(16), 0x000000a9 }, - { AR5K_RF_GAIN(17), 0x00000020 }, - { AR5K_RF_GAIN(18), 0x00000019 }, - { AR5K_RF_GAIN(19), 0x00000059 }, - { AR5K_RF_GAIN(20), 0x00000099 }, - { AR5K_RF_GAIN(21), 0x00000030 }, - { AR5K_RF_GAIN(22), 0x00000005 }, - { AR5K_RF_GAIN(23), 0x00000025 }, - { AR5K_RF_GAIN(24), 0x00000065 }, - { AR5K_RF_GAIN(25), 0x000000a5 }, - { AR5K_RF_GAIN(26), 0x00000028 }, - { AR5K_RF_GAIN(27), 0x00000068 }, - { AR5K_RF_GAIN(28), 0x0000001f }, - { AR5K_RF_GAIN(29), 0x0000001e }, - { AR5K_RF_GAIN(30), 0x00000018 }, - { AR5K_RF_GAIN(31), 0x00000058 }, - { AR5K_RF_GAIN(32), 0x00000098 }, - { AR5K_RF_GAIN(33), 0x00000003 }, - { AR5K_RF_GAIN(34), 0x00000004 }, - { AR5K_RF_GAIN(35), 0x00000044 }, - { AR5K_RF_GAIN(36), 0x00000084 }, - { AR5K_RF_GAIN(37), 0x00000013 }, - { AR5K_RF_GAIN(38), 0x00000012 }, - { AR5K_RF_GAIN(39), 0x00000052 }, - { AR5K_RF_GAIN(40), 0x00000092 }, - { AR5K_RF_GAIN(41), 0x000000d2 }, - { AR5K_RF_GAIN(42), 0x0000002b }, - { AR5K_RF_GAIN(43), 0x0000002a }, - { AR5K_RF_GAIN(44), 0x0000006a }, - { AR5K_RF_GAIN(45), 0x000000aa }, - { AR5K_RF_GAIN(46), 0x0000001b }, - { AR5K_RF_GAIN(47), 0x0000001a }, - { AR5K_RF_GAIN(48), 0x0000005a }, - { AR5K_RF_GAIN(49), 0x0000009a }, - { AR5K_RF_GAIN(50), 0x000000da }, - { AR5K_RF_GAIN(51), 0x00000006 }, - { AR5K_RF_GAIN(52), 0x00000006 }, - { AR5K_RF_GAIN(53), 0x00000006 }, - { AR5K_RF_GAIN(54), 0x00000006 }, - { AR5K_RF_GAIN(55), 0x00000006 }, - { AR5K_RF_GAIN(56), 0x00000006 }, - { AR5K_RF_GAIN(57), 0x00000006 }, - { AR5K_RF_GAIN(58), 0x00000006 }, - { AR5K_RF_GAIN(59), 0x00000006 }, - { AR5K_RF_GAIN(60), 0x00000006 }, - { AR5K_RF_GAIN(61), 0x00000006 }, - { AR5K_RF_GAIN(62), 0x00000006 }, - { AR5K_RF_GAIN(63), 0x00000006 }, - /* PHY activation */ - { AR5K_PHY(53), 0x00000020 }, - { AR5K_PHY(51), 0x00000004 }, - { AR5K_PHY(50), 0x00060106 }, - { AR5K_PHY(39), 0x0000006d }, - { AR5K_PHY(48), 0x00000000 }, - { AR5K_PHY(52), 0x00000014 }, - { AR5K_PHY_ACT, AR5K_PHY_ACT_ENABLE }, -}; - -/* Initial register settings for AR5211 */ -static const struct ath5k_ini ar5211_ini[] = { - { AR5K_RXDP, 0x00000000 }, - { AR5K_RTSD0, 0x84849c9c }, - { AR5K_RTSD1, 0x7c7c7c7c }, - { AR5K_RXCFG, 0x00000005 }, - { AR5K_MIBC, 0x00000000 }, - { AR5K_TOPS, 0x00000008 }, - { AR5K_RXNOFRM, 0x00000008 }, - { AR5K_TXNOFRM, 0x00000010 }, - { AR5K_RPGTO, 0x00000000 }, - { AR5K_RFCNT, 0x0000001f }, - { AR5K_QUEUE_TXDP(0), 0x00000000 }, - { AR5K_QUEUE_TXDP(1), 0x00000000 }, - { AR5K_QUEUE_TXDP(2), 0x00000000 }, - { AR5K_QUEUE_TXDP(3), 0x00000000 }, - { AR5K_QUEUE_TXDP(4), 0x00000000 }, - { AR5K_QUEUE_TXDP(5), 0x00000000 }, - { AR5K_QUEUE_TXDP(6), 0x00000000 }, - { AR5K_QUEUE_TXDP(7), 0x00000000 }, - { AR5K_QUEUE_TXDP(8), 0x00000000 }, - { AR5K_QUEUE_TXDP(9), 0x00000000 }, - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_STA_ID1, 0x00000000 }, - { AR5K_BSS_ID0, 0x00000000 }, - { AR5K_BSS_ID1, 0x00000000 }, - { AR5K_RSSI_THR, 0x00000000 }, - { AR5K_CFP_PERIOD_5211, 0x00000000 }, - { AR5K_TIMER0_5211, 0x00000030 }, - { AR5K_TIMER1_5211, 0x0007ffff }, - { AR5K_TIMER2_5211, 0x01ffffff }, - { AR5K_TIMER3_5211, 0x00000031 }, - { AR5K_CFP_DUR_5211, 0x00000000 }, - { AR5K_RX_FILTER_5211, 0x00000000 }, - { AR5K_MCAST_FILTER0_5211, 0x00000000 }, - { AR5K_MCAST_FILTER1_5211, 0x00000002 }, - { AR5K_DIAG_SW_5211, 0x00000000 }, - { AR5K_ADDAC_TEST, 0x00000000 }, - { AR5K_DEFAULT_ANTENNA, 0x00000000 }, - /* PHY registers */ - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY(3), 0x2d849093 }, - { AR5K_PHY(4), 0x7d32e000 }, - { AR5K_PHY(5), 0x00000f6b }, - { AR5K_PHY_ACT, 0x00000000 }, - { AR5K_PHY(11), 0x00026ffe }, - { AR5K_PHY(12), 0x00000000 }, - { AR5K_PHY(15), 0x00020100 }, - { AR5K_PHY(16), 0x206a017a }, - { AR5K_PHY(19), 0x1284613c }, - { AR5K_PHY(21), 0x00000859 }, - { AR5K_PHY(26), 0x409a4190 }, /* 0x9868 */ - { AR5K_PHY(27), 0x050cb081 }, - { AR5K_PHY(28), 0x0000000f }, - { AR5K_PHY(29), 0x00000080 }, - { AR5K_PHY(30), 0x0000000c }, - { AR5K_PHY(64), 0x00000000 }, - { AR5K_PHY(65), 0x00000000 }, - { AR5K_PHY(66), 0x00000000 }, - { AR5K_PHY(67), 0x00800000 }, - { AR5K_PHY(68), 0x00000001 }, - { AR5K_PHY(71), 0x0000092a }, - { AR5K_PHY_IQ, 0x00000000 }, - { AR5K_PHY(73), 0x00058a05 }, - { AR5K_PHY(74), 0x00000001 }, - { AR5K_PHY(75), 0x00000000 }, - { AR5K_PHY_PAPD_PROBE, 0x00000000 }, - { AR5K_PHY(77), 0x00000000 }, /* 0x9934 */ - { AR5K_PHY(78), 0x00000000 }, /* 0x9938 */ - { AR5K_PHY(79), 0x0000003f }, /* 0x993c */ - { AR5K_PHY(80), 0x00000004 }, - { AR5K_PHY(82), 0x00000000 }, - { AR5K_PHY(83), 0x00000000 }, - { AR5K_PHY(84), 0x00000000 }, - { AR5K_PHY_RADAR, 0x5d50f14c }, - { AR5K_PHY(86), 0x00000018 }, - { AR5K_PHY(87), 0x004b6a8e }, - /* Initial Power table (32bytes) - * common on all cards/modes. - * Note: Table is rewritten during - * txpower setup later using calibration - * data etc. so next write is non-common */ - { AR5K_PHY_PCDAC_TXPOWER(1), 0x06ff05ff }, - { AR5K_PHY_PCDAC_TXPOWER(2), 0x07ff07ff }, - { AR5K_PHY_PCDAC_TXPOWER(3), 0x08ff08ff }, - { AR5K_PHY_PCDAC_TXPOWER(4), 0x09ff09ff }, - { AR5K_PHY_PCDAC_TXPOWER(5), 0x0aff0aff }, - { AR5K_PHY_PCDAC_TXPOWER(6), 0x0bff0bff }, - { AR5K_PHY_PCDAC_TXPOWER(7), 0x0cff0cff }, - { AR5K_PHY_PCDAC_TXPOWER(8), 0x0dff0dff }, - { AR5K_PHY_PCDAC_TXPOWER(9), 0x0fff0eff }, - { AR5K_PHY_PCDAC_TXPOWER(10), 0x12ff12ff }, - { AR5K_PHY_PCDAC_TXPOWER(11), 0x14ff13ff }, - { AR5K_PHY_PCDAC_TXPOWER(12), 0x16ff15ff }, - { AR5K_PHY_PCDAC_TXPOWER(13), 0x19ff17ff }, - { AR5K_PHY_PCDAC_TXPOWER(14), 0x1bff1aff }, - { AR5K_PHY_PCDAC_TXPOWER(15), 0x1eff1dff }, - { AR5K_PHY_PCDAC_TXPOWER(16), 0x23ff20ff }, - { AR5K_PHY_PCDAC_TXPOWER(17), 0x27ff25ff }, - { AR5K_PHY_PCDAC_TXPOWER(18), 0x2cff29ff }, - { AR5K_PHY_PCDAC_TXPOWER(19), 0x31ff2fff }, - { AR5K_PHY_PCDAC_TXPOWER(20), 0x37ff34ff }, - { AR5K_PHY_PCDAC_TXPOWER(21), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(22), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(23), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(24), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(25), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(26), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(27), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(28), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(29), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(30), 0x3aff3aff }, - { AR5K_PHY_PCDAC_TXPOWER(31), 0x3aff3aff }, - { AR5K_PHY_CCKTXCTL, 0x00000000 }, - { AR5K_PHY(642), 0x503e4646 }, - { AR5K_PHY_GAIN_2GHZ, 0x6480416c }, - { AR5K_PHY(644), 0x0199a003 }, - { AR5K_PHY(645), 0x044cd610 }, - { AR5K_PHY(646), 0x13800040 }, - { AR5K_PHY(647), 0x1be00060 }, - { AR5K_PHY(648), 0x0c53800a }, - { AR5K_PHY(649), 0x0014df3b }, - { AR5K_PHY(650), 0x000001b5 }, - { AR5K_PHY(651), 0x00000020 }, -}; - -/* Initial mode-specific settings for AR5211 - * 5211 supports OFDM-only g (draft g) but we - * need to test it ! - */ -static const struct ath5k_ini_mode ar5211_ini_mode[] = { - { AR5K_TXCFG, - /* a aTurbo b g (OFDM) */ - { 0x00000015, 0x00000015, 0x0000001d, 0x00000015 } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(0), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f } }, - { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x00000168 } }, - { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000230 } }, - { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000d98, 0x00001180, 0x00001f48, 0x00000d98 } }, - { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000a0e0 } }, - { AR5K_TIME_OUT, - { 0x04000400, 0x08000800, 0x20003000, 0x04000400 } }, - { AR5K_USEC_5211, - { 0x0e8d8fa7, 0x0e8d8fcf, 0x01608f95, 0x0e8d8fa7 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000 } }, - { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200 } }, - { AR5K_PHY(9), - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e } }, - { AR5K_PHY(10), - { 0x0a020001, 0x0a020001, 0x05010000, 0x0a020001 } }, - { AR5K_PHY(13), - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY(14), - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b } }, - { AR5K_PHY(17), - { 0x1372169c, 0x137216a5, 0x137216a8, 0x1372169c } }, - { AR5K_PHY(18), - { 0x0018ba67, 0x0018ba67, 0x0018ba69, 0x0018ba69 } }, - { AR5K_PHY(20), - { 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0, 0x0c28b4e0 } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ec00d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x31375d5e, 0x31375d5e, 0x313a5d5e, 0x31375d5e } }, - { AR5K_PHY_AGCCTL, - { 0x0000bd10, 0x0000bd10, 0x0000bd38, 0x0000bd10 } }, - { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, - { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002710 } }, - { AR5K_PHY(70), - { 0x00000190, 0x00000190, 0x00000084, 0x00000190 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0x6fe01020, 0x6fe01020, 0x6fe00920, 0x6fe01020 } }, - { AR5K_PHY_PCDAC_TXPOWER_BASE, - { 0x05ff14ff, 0x05ff14ff, 0x05ff14ff, 0x05ff19ff } }, - { AR5K_RF_BUFFER_CONTROL_4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010 } }, -}; - -/* Initial register settings for AR5212 */ -static const struct ath5k_ini ar5212_ini_common_start[] = { - { AR5K_RXDP, 0x00000000 }, - { AR5K_RXCFG, 0x00000005 }, - { AR5K_MIBC, 0x00000000 }, - { AR5K_TOPS, 0x00000008 }, - { AR5K_RXNOFRM, 0x00000008 }, - { AR5K_TXNOFRM, 0x00000010 }, - { AR5K_RPGTO, 0x00000000 }, - { AR5K_RFCNT, 0x0000001f }, - { AR5K_QUEUE_TXDP(0), 0x00000000 }, - { AR5K_QUEUE_TXDP(1), 0x00000000 }, - { AR5K_QUEUE_TXDP(2), 0x00000000 }, - { AR5K_QUEUE_TXDP(3), 0x00000000 }, - { AR5K_QUEUE_TXDP(4), 0x00000000 }, - { AR5K_QUEUE_TXDP(5), 0x00000000 }, - { AR5K_QUEUE_TXDP(6), 0x00000000 }, - { AR5K_QUEUE_TXDP(7), 0x00000000 }, - { AR5K_QUEUE_TXDP(8), 0x00000000 }, - { AR5K_QUEUE_TXDP(9), 0x00000000 }, - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_DCU_TXP, 0x00000000 }, - /* Tx filter table 0 (32 entries) */ - { AR5K_DCU_TX_FILTER_0(0), 0x00000000 }, /* DCU 0 */ - { AR5K_DCU_TX_FILTER_0(1), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(2), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(3), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(4), 0x00000000 }, /* DCU 1 */ - { AR5K_DCU_TX_FILTER_0(5), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(6), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(7), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(8), 0x00000000 }, /* DCU 2 */ - { AR5K_DCU_TX_FILTER_0(9), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(10), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(11), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(12), 0x00000000 }, /* DCU 3 */ - { AR5K_DCU_TX_FILTER_0(13), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(14), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(15), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(16), 0x00000000 }, /* DCU 4 */ - { AR5K_DCU_TX_FILTER_0(17), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(18), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(19), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(20), 0x00000000 }, /* DCU 5 */ - { AR5K_DCU_TX_FILTER_0(21), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(22), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(23), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(24), 0x00000000 }, /* DCU 6 */ - { AR5K_DCU_TX_FILTER_0(25), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(26), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(27), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(28), 0x00000000 }, /* DCU 7 */ - { AR5K_DCU_TX_FILTER_0(29), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(30), 0x00000000 }, - { AR5K_DCU_TX_FILTER_0(31), 0x00000000 }, - /* Tx filter table 1 (16 entries) */ - { AR5K_DCU_TX_FILTER_1(0), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(1), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(2), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(3), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(4), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(5), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(6), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(7), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(8), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(9), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(10), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(11), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(12), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(13), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(14), 0x00000000 }, - { AR5K_DCU_TX_FILTER_1(15), 0x00000000 }, - { AR5K_DCU_TX_FILTER_CLR, 0x00000000 }, - { AR5K_DCU_TX_FILTER_SET, 0x00000000 }, - { AR5K_STA_ID1, 0x00000000 }, - { AR5K_BSS_ID0, 0x00000000 }, - { AR5K_BSS_ID1, 0x00000000 }, - { AR5K_BEACON_5211, 0x00000000 }, - { AR5K_CFP_PERIOD_5211, 0x00000000 }, - { AR5K_TIMER0_5211, 0x00000030 }, - { AR5K_TIMER1_5211, 0x0007ffff }, - { AR5K_TIMER2_5211, 0x01ffffff }, - { AR5K_TIMER3_5211, 0x00000031 }, - { AR5K_CFP_DUR_5211, 0x00000000 }, - { AR5K_RX_FILTER_5211, 0x00000000 }, - { AR5K_DIAG_SW_5211, 0x00000000 }, - { AR5K_ADDAC_TEST, 0x00000000 }, - { AR5K_DEFAULT_ANTENNA, 0x00000000 }, - { AR5K_FRAME_CTL_QOSM, 0x000fc78f }, - { AR5K_XRMODE, 0x2a82301a }, - { AR5K_XRDELAY, 0x05dc01e0 }, - { AR5K_XRTIMEOUT, 0x1f402710 }, - { AR5K_XRCHIRP, 0x01f40000 }, - { AR5K_XRSTOMP, 0x00001e1c }, - { AR5K_SLEEP0, 0x0002aaaa }, - { AR5K_SLEEP1, 0x02005555 }, - { AR5K_SLEEP2, 0x00000000 }, - { AR5K_BSS_IDM0, 0xffffffff }, - { AR5K_BSS_IDM1, 0x0000ffff }, - { AR5K_TXPC, 0x00000000 }, - { AR5K_PROFCNT_TX, 0x00000000 }, - { AR5K_PROFCNT_RX, 0x00000000 }, - { AR5K_PROFCNT_RXCLR, 0x00000000 }, - { AR5K_PROFCNT_CYCLE, 0x00000000 }, - { AR5K_QUIET_CTL1, 0x00000088 }, - /* Initial rate duration table (32 entries )*/ - { AR5K_RATE_DUR(0), 0x00000000 }, - { AR5K_RATE_DUR(1), 0x0000008c }, - { AR5K_RATE_DUR(2), 0x000000e4 }, - { AR5K_RATE_DUR(3), 0x000002d5 }, - { AR5K_RATE_DUR(4), 0x00000000 }, - { AR5K_RATE_DUR(5), 0x00000000 }, - { AR5K_RATE_DUR(6), 0x000000a0 }, - { AR5K_RATE_DUR(7), 0x000001c9 }, - { AR5K_RATE_DUR(8), 0x0000002c }, - { AR5K_RATE_DUR(9), 0x0000002c }, - { AR5K_RATE_DUR(10), 0x00000030 }, - { AR5K_RATE_DUR(11), 0x0000003c }, - { AR5K_RATE_DUR(12), 0x0000002c }, - { AR5K_RATE_DUR(13), 0x0000002c }, - { AR5K_RATE_DUR(14), 0x00000030 }, - { AR5K_RATE_DUR(15), 0x0000003c }, - { AR5K_RATE_DUR(16), 0x00000000 }, - { AR5K_RATE_DUR(17), 0x00000000 }, - { AR5K_RATE_DUR(18), 0x00000000 }, - { AR5K_RATE_DUR(19), 0x00000000 }, - { AR5K_RATE_DUR(20), 0x00000000 }, - { AR5K_RATE_DUR(21), 0x00000000 }, - { AR5K_RATE_DUR(22), 0x00000000 }, - { AR5K_RATE_DUR(23), 0x00000000 }, - { AR5K_RATE_DUR(24), 0x000000d5 }, - { AR5K_RATE_DUR(25), 0x000000df }, - { AR5K_RATE_DUR(26), 0x00000102 }, - { AR5K_RATE_DUR(27), 0x0000013a }, - { AR5K_RATE_DUR(28), 0x00000075 }, - { AR5K_RATE_DUR(29), 0x0000007f }, - { AR5K_RATE_DUR(30), 0x000000a2 }, - { AR5K_RATE_DUR(31), 0x00000000 }, - { AR5K_QUIET_CTL2, 0x00010002 }, - { AR5K_TSF_PARM, 0x00000001 }, - { AR5K_QOS_NOACK, 0x000000c0 }, - { AR5K_PHY_ERR_FIL, 0x00000000 }, - { AR5K_XRLAT_TX, 0x00000168 }, - { AR5K_ACKSIFS, 0x00000000 }, - /* Rate -> db table - * notice ...03<-02<-01<-00 ! */ - { AR5K_RATE2DB(0), 0x03020100 }, - { AR5K_RATE2DB(1), 0x07060504 }, - { AR5K_RATE2DB(2), 0x0b0a0908 }, - { AR5K_RATE2DB(3), 0x0f0e0d0c }, - { AR5K_RATE2DB(4), 0x13121110 }, - { AR5K_RATE2DB(5), 0x17161514 }, - { AR5K_RATE2DB(6), 0x1b1a1918 }, - { AR5K_RATE2DB(7), 0x1f1e1d1c }, - /* Db -> Rate table */ - { AR5K_DB2RATE(0), 0x03020100 }, - { AR5K_DB2RATE(1), 0x07060504 }, - { AR5K_DB2RATE(2), 0x0b0a0908 }, - { AR5K_DB2RATE(3), 0x0f0e0d0c }, - { AR5K_DB2RATE(4), 0x13121110 }, - { AR5K_DB2RATE(5), 0x17161514 }, - { AR5K_DB2RATE(6), 0x1b1a1918 }, - { AR5K_DB2RATE(7), 0x1f1e1d1c }, - /* PHY registers (Common settings - * for all chips/modes) */ - { AR5K_PHY(3), 0xad848e19 }, - { AR5K_PHY(4), 0x7d28e000 }, - { AR5K_PHY_TIMING_3, 0x9c0a9f6b }, - { AR5K_PHY_ACT, 0x00000000 }, - { AR5K_PHY(16), 0x206a017a }, - { AR5K_PHY(21), 0x00000859 }, - { AR5K_PHY_BIN_MASK_1, 0x00000000 }, - { AR5K_PHY_BIN_MASK_2, 0x00000000 }, - { AR5K_PHY_BIN_MASK_3, 0x00000000 }, - { AR5K_PHY_BIN_MASK_CTL, 0x00800000 }, - { AR5K_PHY_ANT_CTL, 0x00000001 }, - /*{ AR5K_PHY(71), 0x0000092a },*/ /* Old value */ - { AR5K_PHY_MAX_RX_LEN, 0x00000c80 }, - { AR5K_PHY_IQ, 0x05100000 }, - { AR5K_PHY_WARM_RESET, 0x00000001 }, - { AR5K_PHY_CTL, 0x00000004 }, - { AR5K_PHY_TXPOWER_RATE1, 0x1e1f2022 }, - { AR5K_PHY_TXPOWER_RATE2, 0x0a0b0c0d }, - { AR5K_PHY_TXPOWER_RATE_MAX, 0x0000003f }, - { AR5K_PHY(82), 0x9280b212 }, - { AR5K_PHY_RADAR, 0x5d50e188 }, - /*{ AR5K_PHY(86), 0x000000ff },*/ - { AR5K_PHY(87), 0x004b6a8e }, - { AR5K_PHY_NFTHRES, 0x000003ce }, - { AR5K_PHY_RESTART, 0x192fb515 }, - { AR5K_PHY(94), 0x00000001 }, - { AR5K_PHY_RFBUS_REQ, 0x00000000 }, - /*{ AR5K_PHY(644), 0x0080a333 },*/ /* Old value */ - /*{ AR5K_PHY(645), 0x00206c10 },*/ /* Old value */ - { AR5K_PHY(644), 0x00806333 }, - { AR5K_PHY(645), 0x00106c10 }, - { AR5K_PHY(646), 0x009c4060 }, - /* { AR5K_PHY(647), 0x1483800a }, */ - /* { AR5K_PHY(648), 0x01831061 }, */ /* Old value */ - { AR5K_PHY(648), 0x018830c6 }, - { AR5K_PHY(649), 0x00000400 }, - /*{ AR5K_PHY(650), 0x000001b5 },*/ - { AR5K_PHY(651), 0x00000000 }, - { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, - { AR5K_PHY_TXPOWER_RATE4, 0x20202020 }, - /*{ AR5K_PHY(655), 0x13c889af },*/ - { AR5K_PHY(656), 0x38490a20 }, - { AR5K_PHY(657), 0x00007bb6 }, - { AR5K_PHY(658), 0x0fff3ffc }, -}; - -/* Initial mode-specific settings for AR5212 (Written before ar5212_ini) */ -static const struct ath5k_ini_mode ar5212_ini_mode_start[] = { - { AR5K_QUEUE_DFS_LOCAL_IFS(0), - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(1), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(2), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(3), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(4), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(5), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(6), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(7), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(8), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_QUEUE_DFS_LOCAL_IFS(9), - { 0x002ffc0f, 0x002ffc0f, 0x002ffc1f, 0x002ffc0f, 0x002ffc0f } }, - { AR5K_DCU_GBL_IFS_SIFS, - { 0x00000230, 0x000001e0, 0x000000b0, 0x00000160, 0x000001e0 } }, - { AR5K_DCU_GBL_IFS_SLOT, - { 0x00000168, 0x000001e0, 0x000001b8, 0x0000018c, 0x000001e0 } }, - { AR5K_DCU_GBL_IFS_EIFS, - { 0x00000e60, 0x00001180, 0x00001f1c, 0x00003e38, 0x00001180 } }, - { AR5K_DCU_GBL_IFS_MISC, - { 0x0000a0e0, 0x00014068, 0x00005880, 0x0000b0e0, 0x00014068 } }, - { AR5K_TIME_OUT, - { 0x03e803e8, 0x06e006e0, 0x04200420, 0x08400840, 0x06e006e0 } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000003, 0x00000000, 0x00000000, 0x00000003 } }, - { AR5K_PHY(8), - { 0x02020200, 0x02020200, 0x02010200, 0x02020200, 0x02020200 } }, - { AR5K_PHY_RF_CTL2, - { 0x00000e0e, 0x00000e0e, 0x00000707, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x137216a2, 0x13721c25 } }, - { AR5K_PHY_AGCCTL, - { 0x00009d10, 0x00009d10, 0x00009d18, 0x00009d18, 0x00009d10 } }, - { AR5K_PHY_NF, - { 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 } }, - { AR5K_PHY_WEAK_OFDM_HIGH_THR, - { 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 } }, - { AR5K_PHY(70), - { 0x000001b8, 0x000001b8, 0x00000084, 0x00000108, 0x000001b8 } }, - { AR5K_PHY_OFDM_SELFCORR, - { 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05, 0x10058a05 } }, - { 0xa230, - { 0x00000000, 0x00000000, 0x00000000, 0x00000108, 0x00000000 } }, -}; - -/* Initial mode-specific settings for AR5212 + RF5111 (Written after ar5212_ini) */ -static const struct ath5k_ini_mode rf5111_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, - { AR5K_USEC_5211, - { 0x128d8fa7, 0x09880fcf, 0x04e00f95, 0x12e00fab, 0x09880fcf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05010100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_GAIN, - { 0x0018da5a, 0x0018da5a, 0x0018ca69, 0x0018ca69, 0x0018ca69 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee84d2e, 0x7ee84d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137615e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb080, 0x050cb080 } }, - { AR5K_PHY_RX_DELAY, - { 0x00002710, 0x00002710, 0x0000157c, 0x00002af8, 0x00002710 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d20, 0xf7b81020, 0xf7b81020 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x642c416a, 0x642c416a, 0x6440416a, 0x6440416a, 0x6440416a } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, -}; - -static const struct ath5k_ini rf5111_ini_common_end[] = { - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x00022ffe }, - { 0x983c, 0x00020100 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284613c }, - { AR5K_PHY_PAPD_PROBE, 0x00004883 }, - { 0x9940, 0x00000004 }, - { 0x9958, 0x000000ff }, - { 0x9974, 0x00000000 }, - { AR5K_PHY_SPENDING, 0x00000018 }, - { AR5K_PHY_CCKTXCTL, 0x00000000 }, - { AR5K_PHY_CCK_CROSSCORR, 0xd03e6788 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 }, - { 0xa23c, 0x13c889af }, -}; - -/* Initial mode-specific settings for AR5212 + RF5112 (Written after ar5212_ini) */ -static const struct ath5k_ini_mode rf5112_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00008015, 0x00008015, 0x00008015, 0x00008015, 0x00008015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x0018ca75, 0x0018ca75, 0x0018ca75 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0, 0x0de8b4e0 } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ee80d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e, 0x3137665e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81020, 0xf7b81020, 0xf7b80d10, 0xf7b81010, 0xf7b81010 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000008, 0x00000008, 0x00000008 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x642c0140, 0x642c0140, 0x6442c160, 0x6442c160, 0x6442c160 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1873800a, 0x1883800a, 0x1883800a } }, -}; - -static const struct ath5k_ini rf5112_ini_common_end[] = { - { AR5K_DCU_FP, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x00022ffe }, - { 0x983c, 0x00020100 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284613c }, - { AR5K_PHY_PAPD_PROBE, 0x00004882 }, - { 0x9940, 0x00000004 }, - { 0x9958, 0x000000ff }, - { 0x9974, 0x00000000 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000001b5 }, - { 0xa23c, 0x13c889af }, -}; - -/* Initial mode-specific settings for RF5413/5414 (Written after ar5212_ini) */ -static const struct ath5k_ini_mode rf5413_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000007, 0x00000007, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x001a1a63, 0x001a1a63, 0x001a1a63 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, - { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, - { 0xa300, - { 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 } }, - { 0xa304, - { 0x30032602, 0x30032602, 0x30032602, 0x30032602, 0x30032602 } }, - { 0xa308, - { 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06, 0x48073e06 } }, - { 0xa30c, - { 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a, 0x560b4c0a } }, - { 0xa310, - { 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f, 0x641a600f } }, - { 0xa314, - { 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b, 0x784f6e1b } }, - { 0xa318, - { 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a, 0x868f7c5a } }, - { 0xa31c, - { 0x90cf865b, 0x90cf865b, 0x8ecf865b, 0x8ecf865b, 0x8ecf865b } }, - { 0xa320, - { 0x9d4f970f, 0x9d4f970f, 0x9b4f970f, 0x9b4f970f, 0x9b4f970f } }, - { 0xa324, - { 0xa7cfa38f, 0xa7cfa38f, 0xa3cf9f8f, 0xa3cf9f8f, 0xa3cf9f8f } }, - { 0xa328, - { 0xb55faf1f, 0xb55faf1f, 0xb35faf1f, 0xb35faf1f, 0xb35faf1f } }, - { 0xa32c, - { 0xbddfb99f, 0xbddfb99f, 0xbbdfb99f, 0xbbdfb99f, 0xbbdfb99f } }, - { 0xa330, - { 0xcb7fc53f, 0xcb7fc53f, 0xcb7fc73f, 0xcb7fc73f, 0xcb7fc73f } }, - { 0xa334, - { 0xd5ffd1bf, 0xd5ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf, 0xd3ffd1bf } }, -}; - -static const struct ath5k_ini rf5413_ini_common_end[] = { - { AR5K_DCU_FP, 0x000003e0 }, - { AR5K_5414_CBCFG, 0x00000010 }, - { AR5K_SEQ_MASK, 0x0000000f }, - { 0x809c, 0x00000000 }, - { 0x80a0, 0x00000000 }, - { AR5K_MIC_QOS_CTL, 0x00000000 }, - { AR5K_MIC_QOS_SEL, 0x00000000 }, - { AR5K_MISC_MODE, 0x00000000 }, - { AR5K_OFDM_FIL_CNT, 0x00000000 }, - { AR5K_CCK_FIL_CNT, 0x00000000 }, - { AR5K_PHYERR_CNT1, 0x00000000 }, - { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, - { AR5K_PHYERR_CNT2, 0x00000000 }, - { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, - { AR5K_TSF_THRES, 0x00000000 }, - { 0x8140, 0x800003f9 }, - { 0x8144, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x0000a000 }, - { 0x983c, 0x00200400 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, - { AR5K_PHY_SCR, 0x0000001f }, - { AR5K_PHY_SLMT, 0x00000080 }, - { AR5K_PHY_SCAL, 0x0000000e }, - { 0x9958, 0x00081fff }, - { AR5K_PHY_TIMING_7, 0x00000000 }, - { AR5K_PHY_TIMING_8, 0x02800000 }, - { AR5K_PHY_TIMING_11, 0x00000000 }, - { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, - { 0x99e4, 0xaaaaaaaa }, - { 0x99e8, 0x3c466478 }, - { 0x99ec, 0x000000aa }, - { AR5K_PHY_SCLOCK, 0x0000000c }, - { AR5K_PHY_SDELAY, 0x000000ff }, - { AR5K_PHY_SPENDING, 0x00000014 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, - { 0xa23c, 0x93c889af }, - { AR5K_PHY_FAST_ADC, 0x00000001 }, - { 0xa250, 0x0000a000 }, - { AR5K_PHY_BLUETOOTH, 0x00000000 }, - { AR5K_PHY_TPC_RG1, 0x0cc75380 }, - { 0xa25c, 0x0f0f0f01 }, - { 0xa260, 0x5f690f01 }, - { 0xa264, 0x00418a11 }, - { 0xa268, 0x00000000 }, - { AR5K_PHY_TPC_RG5, 0x0c30c16a }, - { 0xa270, 0x00820820 }, - { 0xa274, 0x081b7caa }, - { 0xa278, 0x1ce739ce }, - { 0xa27c, 0x051701ce }, - { 0xa338, 0x00000000 }, - { 0xa33c, 0x00000000 }, - { 0xa340, 0x00000000 }, - { 0xa344, 0x00000000 }, - { 0xa348, 0x3fffffff }, - { 0xa34c, 0x3fffffff }, - { 0xa350, 0x3fffffff }, - { 0xa354, 0x0003ffff }, - { 0xa358, 0x79a8aa1f }, - { 0xa35c, 0x066c420f }, - { 0xa360, 0x0f282207 }, - { 0xa364, 0x17601685 }, - { 0xa368, 0x1f801104 }, - { 0xa36c, 0x37a00c03 }, - { 0xa370, 0x3fc40883 }, - { 0xa374, 0x57c00803 }, - { 0xa378, 0x5fd80682 }, - { 0xa37c, 0x7fe00482 }, - { 0xa380, 0x7f3c7bba }, - { 0xa384, 0xf3307ff0 }, -}; - -/* Initial mode-specific settings for RF2413/2414 (Written after ar5212_ini) */ -/* XXX: a mode ? */ -static const struct ath5k_ini_mode rf2413_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020000, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00, 0x00000e00 } }, - { AR5K_PHY_PA_CTL, - { 0x00000002, 0x00000002, 0x0000000a, 0x0000000a, 0x0000000a } }, - { AR5K_PHY_GAIN, - { 0x0018da6d, 0x0018da6d, 0x001a6a64, 0x001a6a64, 0x001a6a64 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0de8b4e0, 0x0de8b4e0, 0x0de8b0da, 0x0c98b0da, 0x0de8b0da } }, - { AR5K_PHY_SIG, - { 0x7e800d2e, 0x7e800d2e, 0x7ee80d2e, 0x7ec80d2e, 0x7e800d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3137665e, 0x3137665e, 0x3137665e, 0x3139605e, 0x3137665e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x002c0140, 0x002c0140, 0x0042c140, 0x0042c140, 0x0042c140 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, -}; - -static const struct ath5k_ini rf2413_ini_common_end[] = { - { AR5K_DCU_FP, 0x000003e0 }, - { AR5K_SEQ_MASK, 0x0000000f }, - { AR5K_MIC_QOS_CTL, 0x00000000 }, - { AR5K_MIC_QOS_SEL, 0x00000000 }, - { AR5K_MISC_MODE, 0x00000000 }, - { AR5K_OFDM_FIL_CNT, 0x00000000 }, - { AR5K_CCK_FIL_CNT, 0x00000000 }, - { AR5K_PHYERR_CNT1, 0x00000000 }, - { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, - { AR5K_PHYERR_CNT2, 0x00000000 }, - { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, - { AR5K_TSF_THRES, 0x00000000 }, - { 0x8140, 0x800000a8 }, - { 0x8144, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x0000a000 }, - { 0x983c, 0x00200400 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, - { AR5K_PHY_SCR, 0x0000001f }, - { AR5K_PHY_SLMT, 0x00000080 }, - { AR5K_PHY_SCAL, 0x0000000e }, - { 0x9958, 0x000000ff }, - { AR5K_PHY_TIMING_7, 0x00000000 }, - { AR5K_PHY_TIMING_8, 0x02800000 }, - { AR5K_PHY_TIMING_11, 0x00000000 }, - { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, - { 0x99e4, 0xaaaaaaaa }, - { 0x99e8, 0x3c466478 }, - { 0x99ec, 0x000000aa }, - { AR5K_PHY_SCLOCK, 0x0000000c }, - { AR5K_PHY_SDELAY, 0x000000ff }, - { AR5K_PHY_SPENDING, 0x00000014 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, - { 0xa23c, 0x93c889af }, - { AR5K_PHY_FAST_ADC, 0x00000001 }, - { 0xa250, 0x0000a000 }, - { AR5K_PHY_BLUETOOTH, 0x00000000 }, - { AR5K_PHY_TPC_RG1, 0x0cc75380 }, - { 0xa25c, 0x0f0f0f01 }, - { 0xa260, 0x5f690f01 }, - { 0xa264, 0x00418a11 }, - { 0xa268, 0x00000000 }, - { AR5K_PHY_TPC_RG5, 0x0c30c16a }, - { 0xa270, 0x00820820 }, - { 0xa274, 0x001b7caa }, - { 0xa278, 0x1ce739ce }, - { 0xa27c, 0x051701ce }, - { 0xa300, 0x18010000 }, - { 0xa304, 0x30032602 }, - { 0xa308, 0x48073e06 }, - { 0xa30c, 0x560b4c0a }, - { 0xa310, 0x641a600f }, - { 0xa314, 0x784f6e1b }, - { 0xa318, 0x868f7c5a }, - { 0xa31c, 0x8ecf865b }, - { 0xa320, 0x9d4f970f }, - { 0xa324, 0xa5cfa18f }, - { 0xa328, 0xb55faf1f }, - { 0xa32c, 0xbddfb99f }, - { 0xa330, 0xcd7fc73f }, - { 0xa334, 0xd5ffd1bf }, - { 0xa338, 0x00000000 }, - { 0xa33c, 0x00000000 }, - { 0xa340, 0x00000000 }, - { 0xa344, 0x00000000 }, - { 0xa348, 0x3fffffff }, - { 0xa34c, 0x3fffffff }, - { 0xa350, 0x3fffffff }, - { 0xa354, 0x0003ffff }, - { 0xa358, 0x79a8aa1f }, - { 0xa35c, 0x066c420f }, - { 0xa360, 0x0f282207 }, - { 0xa364, 0x17601685 }, - { 0xa368, 0x1f801104 }, - { 0xa36c, 0x37a00c03 }, - { 0xa370, 0x3fc40883 }, - { 0xa374, 0x57c00803 }, - { 0xa378, 0x5fd80682 }, - { 0xa37c, 0x7fe00482 }, - { 0xa380, 0x7f3c7bba }, - { 0xa384, 0xf3307ff0 }, -}; - -/* Initial mode-specific settings for RF2425 (Written after ar5212_ini) */ -/* XXX: a mode ? */ -static const struct ath5k_ini_mode rf2425_ini_mode_end[] = { - { AR5K_TXCFG, - /* a/XR aTurbo b g (DYN) gTurbo */ - { 0x00000015, 0x00000015, 0x00000015, 0x00000015, 0x00000015 } }, - { AR5K_USEC_5211, - { 0x128d93a7, 0x098813cf, 0x04e01395, 0x12e013ab, 0x098813cf } }, - { AR5K_PHY_TURBO, - { 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000001 } }, - { AR5K_PHY_RF_CTL3, - { 0x0a020001, 0x0a020001, 0x05020100, 0x0a020001, 0x0a020001 } }, - { AR5K_PHY_RF_CTL4, - { 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e } }, - { AR5K_PHY_PA_CTL, - { 0x00000003, 0x00000003, 0x0000000b, 0x0000000b, 0x0000000b } }, - { AR5K_PHY_SETTLING, - { 0x1372161c, 0x13721c25, 0x13721722, 0x13721422, 0x13721c25 } }, - { AR5K_PHY_GAIN, - { 0x0018fa61, 0x0018fa61, 0x00199a65, 0x00199a65, 0x00199a65 } }, - { AR5K_PHY_DESIRED_SIZE, - { 0x0c98b4e0, 0x0c98b4e0, 0x0c98b0da, 0x0c98b0da, 0x0c98b0da } }, - { AR5K_PHY_SIG, - { 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e, 0x7ec80d2e } }, - { AR5K_PHY_AGCCOARSE, - { 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e } }, - { AR5K_PHY_WEAK_OFDM_LOW_THR, - { 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 } }, - { AR5K_PHY_RX_DELAY, - { 0x000007d0, 0x000007d0, 0x0000044c, 0x00000898, 0x000007d0 } }, - { AR5K_PHY_FRAME_CTL_5211, - { 0xf7b81000, 0xf7b81000, 0xf7b80d00, 0xf7b81000, 0xf7b81000 } }, - { AR5K_PHY_CCKTXCTL, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { AR5K_PHY_CCK_CROSSCORR, - { 0xd6be6788, 0xd6be6788, 0xd03e6788, 0xd03e6788, 0xd03e6788 } }, - { AR5K_PHY_GAIN_2GHZ, - { 0x00000140, 0x00000140, 0x0052c140, 0x0052c140, 0x0052c140 } }, - { AR5K_PHY_CCK_RX_CTL_4, - { 0x1883800a, 0x1883800a, 0x1863800a, 0x1883800a, 0x1883800a } }, - { 0xa324, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa328, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa32c, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa330, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, - { 0xa334, - { 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf, 0xa7cfa7cf } }, -}; - -static const struct ath5k_ini rf2425_ini_common_end[] = { - { AR5K_DCU_FP, 0x000003e0 }, - { AR5K_SEQ_MASK, 0x0000000f }, - { 0x809c, 0x00000000 }, - { 0x80a0, 0x00000000 }, - { AR5K_MIC_QOS_CTL, 0x00000000 }, - { AR5K_MIC_QOS_SEL, 0x00000000 }, - { AR5K_MISC_MODE, 0x00000000 }, - { AR5K_OFDM_FIL_CNT, 0x00000000 }, - { AR5K_CCK_FIL_CNT, 0x00000000 }, - { AR5K_PHYERR_CNT1, 0x00000000 }, - { AR5K_PHYERR_CNT1_MASK, 0x00000000 }, - { AR5K_PHYERR_CNT2, 0x00000000 }, - { AR5K_PHYERR_CNT2_MASK, 0x00000000 }, - { AR5K_TSF_THRES, 0x00000000 }, - { 0x8140, 0x800003f9 }, - { 0x8144, 0x00000000 }, - { AR5K_PHY_AGC, 0x00000000 }, - { AR5K_PHY_ADC_CTL, 0x0000a000 }, - { 0x983c, 0x00200400 }, - { AR5K_PHY_GAIN_OFFSET, 0x1284233c }, - { AR5K_PHY_SCR, 0x0000001f }, - { AR5K_PHY_SLMT, 0x00000080 }, - { AR5K_PHY_SCAL, 0x0000000e }, - { 0x9958, 0x00081fff }, - { AR5K_PHY_TIMING_7, 0x00000000 }, - { AR5K_PHY_TIMING_8, 0x02800000 }, - { AR5K_PHY_TIMING_11, 0x00000000 }, - { 0x99dc, 0xfebadbe8 }, - { AR5K_PHY_HEAVY_CLIP_ENABLE, 0x00000000 }, - { 0x99e4, 0xaaaaaaaa }, - { 0x99e8, 0x3c466478 }, - { 0x99ec, 0x000000aa }, - { AR5K_PHY_SCLOCK, 0x0000000c }, - { AR5K_PHY_SDELAY, 0x000000ff }, - { AR5K_PHY_SPENDING, 0x00000014 }, - { AR5K_PHY_DAG_CCK_CTL, 0x000009b5 }, - { AR5K_PHY_TXPOWER_RATE3, 0x20202020 }, - { AR5K_PHY_TXPOWER_RATE4, 0x20202020 }, - { 0xa23c, 0x93c889af }, - { AR5K_PHY_FAST_ADC, 0x00000001 }, - { 0xa250, 0x0000a000 }, - { AR5K_PHY_BLUETOOTH, 0x00000000 }, - { AR5K_PHY_TPC_RG1, 0x0cc75380 }, - { 0xa25c, 0x0f0f0f01 }, - { 0xa260, 0x5f690f01 }, - { 0xa264, 0x00418a11 }, - { 0xa268, 0x00000000 }, - { AR5K_PHY_TPC_RG5, 0x0c30c166 }, - { 0xa270, 0x00820820 }, - { 0xa274, 0x081a3caa }, - { 0xa278, 0x1ce739ce }, - { 0xa27c, 0x051701ce }, - { 0xa300, 0x16010000 }, - { 0xa304, 0x2c032402 }, - { 0xa308, 0x48433e42 }, - { 0xa30c, 0x5a0f500b }, - { 0xa310, 0x6c4b624a }, - { 0xa314, 0x7e8b748a }, - { 0xa318, 0x96cf8ccb }, - { 0xa31c, 0xa34f9d0f }, - { 0xa320, 0xa7cfa58f }, - { 0xa348, 0x3fffffff }, - { 0xa34c, 0x3fffffff }, - { 0xa350, 0x3fffffff }, - { 0xa354, 0x0003ffff }, - { 0xa358, 0x79a8aa1f }, - { 0xa35c, 0x066c420f }, - { 0xa360, 0x0f282207 }, - { 0xa364, 0x17601685 }, - { 0xa368, 0x1f801104 }, - { 0xa36c, 0x37a00c03 }, - { 0xa370, 0x3fc40883 }, - { 0xa374, 0x57c00803 }, - { 0xa378, 0x5fd80682 }, - { 0xa37c, 0x7fe00482 }, - { 0xa380, 0x7f3c7bba }, - { 0xa384, 0xf3307ff0 }, -}; - -/* - * Initial BaseBand Gain settings for RF5111/5112 (AR5210 comes with - * RF5110 only so initial BB Gain settings are included in AR5K_AR5210_INI) - */ - -/* RF5111 Initial BaseBand Gain settings */ -static const struct ath5k_ini rf5111_ini_bbgain[] = { - { AR5K_BB_GAIN(0), 0x00000000 }, - { AR5K_BB_GAIN(1), 0x00000020 }, - { AR5K_BB_GAIN(2), 0x00000010 }, - { AR5K_BB_GAIN(3), 0x00000030 }, - { AR5K_BB_GAIN(4), 0x00000008 }, - { AR5K_BB_GAIN(5), 0x00000028 }, - { AR5K_BB_GAIN(6), 0x00000004 }, - { AR5K_BB_GAIN(7), 0x00000024 }, - { AR5K_BB_GAIN(8), 0x00000014 }, - { AR5K_BB_GAIN(9), 0x00000034 }, - { AR5K_BB_GAIN(10), 0x0000000c }, - { AR5K_BB_GAIN(11), 0x0000002c }, - { AR5K_BB_GAIN(12), 0x00000002 }, - { AR5K_BB_GAIN(13), 0x00000022 }, - { AR5K_BB_GAIN(14), 0x00000012 }, - { AR5K_BB_GAIN(15), 0x00000032 }, - { AR5K_BB_GAIN(16), 0x0000000a }, - { AR5K_BB_GAIN(17), 0x0000002a }, - { AR5K_BB_GAIN(18), 0x00000006 }, - { AR5K_BB_GAIN(19), 0x00000026 }, - { AR5K_BB_GAIN(20), 0x00000016 }, - { AR5K_BB_GAIN(21), 0x00000036 }, - { AR5K_BB_GAIN(22), 0x0000000e }, - { AR5K_BB_GAIN(23), 0x0000002e }, - { AR5K_BB_GAIN(24), 0x00000001 }, - { AR5K_BB_GAIN(25), 0x00000021 }, - { AR5K_BB_GAIN(26), 0x00000011 }, - { AR5K_BB_GAIN(27), 0x00000031 }, - { AR5K_BB_GAIN(28), 0x00000009 }, - { AR5K_BB_GAIN(29), 0x00000029 }, - { AR5K_BB_GAIN(30), 0x00000005 }, - { AR5K_BB_GAIN(31), 0x00000025 }, - { AR5K_BB_GAIN(32), 0x00000015 }, - { AR5K_BB_GAIN(33), 0x00000035 }, - { AR5K_BB_GAIN(34), 0x0000000d }, - { AR5K_BB_GAIN(35), 0x0000002d }, - { AR5K_BB_GAIN(36), 0x00000003 }, - { AR5K_BB_GAIN(37), 0x00000023 }, - { AR5K_BB_GAIN(38), 0x00000013 }, - { AR5K_BB_GAIN(39), 0x00000033 }, - { AR5K_BB_GAIN(40), 0x0000000b }, - { AR5K_BB_GAIN(41), 0x0000002b }, - { AR5K_BB_GAIN(42), 0x0000002b }, - { AR5K_BB_GAIN(43), 0x0000002b }, - { AR5K_BB_GAIN(44), 0x0000002b }, - { AR5K_BB_GAIN(45), 0x0000002b }, - { AR5K_BB_GAIN(46), 0x0000002b }, - { AR5K_BB_GAIN(47), 0x0000002b }, - { AR5K_BB_GAIN(48), 0x0000002b }, - { AR5K_BB_GAIN(49), 0x0000002b }, - { AR5K_BB_GAIN(50), 0x0000002b }, - { AR5K_BB_GAIN(51), 0x0000002b }, - { AR5K_BB_GAIN(52), 0x0000002b }, - { AR5K_BB_GAIN(53), 0x0000002b }, - { AR5K_BB_GAIN(54), 0x0000002b }, - { AR5K_BB_GAIN(55), 0x0000002b }, - { AR5K_BB_GAIN(56), 0x0000002b }, - { AR5K_BB_GAIN(57), 0x0000002b }, - { AR5K_BB_GAIN(58), 0x0000002b }, - { AR5K_BB_GAIN(59), 0x0000002b }, - { AR5K_BB_GAIN(60), 0x0000002b }, - { AR5K_BB_GAIN(61), 0x0000002b }, - { AR5K_BB_GAIN(62), 0x00000002 }, - { AR5K_BB_GAIN(63), 0x00000016 }, -}; - -/* RF5112 Initial BaseBand Gain settings (Same for RF5413/5414+) */ -static const struct ath5k_ini rf5112_ini_bbgain[] = { - { AR5K_BB_GAIN(0), 0x00000000 }, - { AR5K_BB_GAIN(1), 0x00000001 }, - { AR5K_BB_GAIN(2), 0x00000002 }, - { AR5K_BB_GAIN(3), 0x00000003 }, - { AR5K_BB_GAIN(4), 0x00000004 }, - { AR5K_BB_GAIN(5), 0x00000005 }, - { AR5K_BB_GAIN(6), 0x00000008 }, - { AR5K_BB_GAIN(7), 0x00000009 }, - { AR5K_BB_GAIN(8), 0x0000000a }, - { AR5K_BB_GAIN(9), 0x0000000b }, - { AR5K_BB_GAIN(10), 0x0000000c }, - { AR5K_BB_GAIN(11), 0x0000000d }, - { AR5K_BB_GAIN(12), 0x00000010 }, - { AR5K_BB_GAIN(13), 0x00000011 }, - { AR5K_BB_GAIN(14), 0x00000012 }, - { AR5K_BB_GAIN(15), 0x00000013 }, - { AR5K_BB_GAIN(16), 0x00000014 }, - { AR5K_BB_GAIN(17), 0x00000015 }, - { AR5K_BB_GAIN(18), 0x00000018 }, - { AR5K_BB_GAIN(19), 0x00000019 }, - { AR5K_BB_GAIN(20), 0x0000001a }, - { AR5K_BB_GAIN(21), 0x0000001b }, - { AR5K_BB_GAIN(22), 0x0000001c }, - { AR5K_BB_GAIN(23), 0x0000001d }, - { AR5K_BB_GAIN(24), 0x00000020 }, - { AR5K_BB_GAIN(25), 0x00000021 }, - { AR5K_BB_GAIN(26), 0x00000022 }, - { AR5K_BB_GAIN(27), 0x00000023 }, - { AR5K_BB_GAIN(28), 0x00000024 }, - { AR5K_BB_GAIN(29), 0x00000025 }, - { AR5K_BB_GAIN(30), 0x00000028 }, - { AR5K_BB_GAIN(31), 0x00000029 }, - { AR5K_BB_GAIN(32), 0x0000002a }, - { AR5K_BB_GAIN(33), 0x0000002b }, - { AR5K_BB_GAIN(34), 0x0000002c }, - { AR5K_BB_GAIN(35), 0x0000002d }, - { AR5K_BB_GAIN(36), 0x00000030 }, - { AR5K_BB_GAIN(37), 0x00000031 }, - { AR5K_BB_GAIN(38), 0x00000032 }, - { AR5K_BB_GAIN(39), 0x00000033 }, - { AR5K_BB_GAIN(40), 0x00000034 }, - { AR5K_BB_GAIN(41), 0x00000035 }, - { AR5K_BB_GAIN(42), 0x00000035 }, - { AR5K_BB_GAIN(43), 0x00000035 }, - { AR5K_BB_GAIN(44), 0x00000035 }, - { AR5K_BB_GAIN(45), 0x00000035 }, - { AR5K_BB_GAIN(46), 0x00000035 }, - { AR5K_BB_GAIN(47), 0x00000035 }, - { AR5K_BB_GAIN(48), 0x00000035 }, - { AR5K_BB_GAIN(49), 0x00000035 }, - { AR5K_BB_GAIN(50), 0x00000035 }, - { AR5K_BB_GAIN(51), 0x00000035 }, - { AR5K_BB_GAIN(52), 0x00000035 }, - { AR5K_BB_GAIN(53), 0x00000035 }, - { AR5K_BB_GAIN(54), 0x00000035 }, - { AR5K_BB_GAIN(55), 0x00000035 }, - { AR5K_BB_GAIN(56), 0x00000035 }, - { AR5K_BB_GAIN(57), 0x00000035 }, - { AR5K_BB_GAIN(58), 0x00000035 }, - { AR5K_BB_GAIN(59), 0x00000035 }, - { AR5K_BB_GAIN(60), 0x00000035 }, - { AR5K_BB_GAIN(61), 0x00000035 }, - { AR5K_BB_GAIN(62), 0x00000010 }, - { AR5K_BB_GAIN(63), 0x0000001a }, -}; - - -/* - * Write initial register dump - */ -static void ath5k_hw_ini_registers(struct ath5k_hw *ah, unsigned int size, - const struct ath5k_ini *ini_regs, bool change_channel) -{ - unsigned int i; - - /* Write initial registers */ - for (i = 0; i < size; i++) { - /* On channel change there is - * no need to mess with PCU */ - if (change_channel && - ini_regs[i].ini_register >= AR5K_PCU_MIN && - ini_regs[i].ini_register <= AR5K_PCU_MAX) - continue; - - switch (ini_regs[i].ini_mode) { - case AR5K_INI_READ: - /* Cleared on read */ - ath5k_hw_reg_read(ah, ini_regs[i].ini_register); - break; - case AR5K_INI_WRITE: - default: - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ini_regs[i].ini_value, - ini_regs[i].ini_register); - } - } -} - -static void ath5k_hw_ini_mode_registers(struct ath5k_hw *ah, - unsigned int size, const struct ath5k_ini_mode *ini_mode, - u8 mode) -{ - unsigned int i; - - for (i = 0; i < size; i++) { - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ini_mode[i].mode_value[mode], - (u32)ini_mode[i].mode_register); - } - -} - -int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel) -{ - /* - * Write initial register settings - */ - - /* For AR5212 and combatible */ - if (ah->ah_version == AR5K_AR5212) { - - /* First set of mode-specific settings */ - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(ar5212_ini_mode_start), - ar5212_ini_mode_start, mode); - - /* - * Write initial settings common for all modes - */ - ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5212_ini_common_start), - ar5212_ini_common_start, change_channel); - - /* Second set of mode-specific settings */ - switch (ah->ah_radio) { - case AR5K_RF5111: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf5111_ini_mode_end), - rf5111_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5111_ini_common_end), - rf5111_ini_common_end, change_channel); - - /* Baseband gain table */ - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); - - break; - case AR5K_RF5112: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf5112_ini_mode_end), - rf5112_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_common_end), - rf5112_ini_common_end, change_channel); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - - break; - case AR5K_RF5413: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf5413_ini_mode_end), - rf5413_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5413_ini_common_end), - rf5413_ini_common_end, change_channel); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - - break; - case AR5K_RF2316: - case AR5K_RF2413: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf2413_ini_mode_end), - rf2413_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf2413_ini_common_end), - rf2413_ini_common_end, change_channel); - - /* Override settings from rf2413_ini_common_end */ - if (ah->ah_radio == AR5K_RF2316) { - ath5k_hw_reg_write(ah, 0x00004000, - AR5K_PHY_AGC); - ath5k_hw_reg_write(ah, 0x081b7caa, - 0xa274); - } - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - break; - case AR5K_RF2317: - case AR5K_RF2425: - - ath5k_hw_ini_mode_registers(ah, - ARRAY_SIZE(rf2425_ini_mode_end), - rf2425_ini_mode_end, mode); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf2425_ini_common_end), - rf2425_ini_common_end, change_channel); - - ath5k_hw_ini_registers(ah, - ARRAY_SIZE(rf5112_ini_bbgain), - rf5112_ini_bbgain, change_channel); - break; - default: - return -EINVAL; - - } - - /* For AR5211 */ - } else if (ah->ah_version == AR5K_AR5211) { - - /* AR5K_MODE_11B */ - if (mode > 2) { - ATH5K_ERR(ah->ah_sc, - "unsupported channel mode: %d\n", mode); - return -EINVAL; - } - - /* Mode-specific settings */ - ath5k_hw_ini_mode_registers(ah, ARRAY_SIZE(ar5211_ini_mode), - ar5211_ini_mode, mode); - - /* - * Write initial settings common for all modes - */ - ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5211_ini), - ar5211_ini, change_channel); - - /* AR5211 only comes with 5111 */ - - /* Baseband gain table */ - ath5k_hw_ini_registers(ah, ARRAY_SIZE(rf5111_ini_bbgain), - rf5111_ini_bbgain, change_channel); - /* For AR5210 (for mode settings check out ath5k_hw_reset_tx_queue) */ - } else if (ah->ah_version == AR5K_AR5210) { - ath5k_hw_ini_registers(ah, ARRAY_SIZE(ar5210_ini), - ar5210_ini, change_channel); - } - - return 0; -} diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c deleted file mode 100644 index b548c8eaaae1..000000000000 --- a/drivers/net/wireless/ath/ath5k/led.c +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * Copyright (c) 2004-2005 Atheros Communications, Inc. - * Copyright (c) 2007 Jiri Slaby - * Copyright (c) 2009 Bob Copeland - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - * - */ - -#include -#include "ath5k.h" -#include "base.h" - -#define ATH_SDEVICE(subv,subd) \ - .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ - .subvendor = (subv), .subdevice = (subd) - -#define ATH_LED(pin,polarity) .driver_data = (((pin) << 8) | (polarity)) -#define ATH_PIN(data) ((data) >> 8) -#define ATH_POLARITY(data) ((data) & 0xff) - -/* Devices we match on for LED config info (typically laptops) */ -static const struct pci_device_id ath5k_led_devices[] = { - /* AR5211 */ - { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5211), ATH_LED(0, 0) }, - /* HP Compaq nc6xx, nc4000, nx6000 */ - { ATH_SDEVICE(PCI_VENDOR_ID_COMPAQ, PCI_ANY_ID), ATH_LED(1, 1) }, - /* Acer Aspire One A150 (maximlevitsky@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_FOXCONN, 0xe008), ATH_LED(3, 0) }, - /* Acer Ferrari 5000 (russ.dill@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0422), ATH_LED(1, 1) }, - /* E-machines E510 (tuliom@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_AMBIT, 0x0428), ATH_LED(3, 0) }, - /* BenQ Joybook R55v (nowymarluk@wp.pl) */ - { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0100), ATH_LED(1, 0) }, - /* Acer Extensa 5620z (nekoreeve@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_QMI, 0x0105), ATH_LED(3, 0) }, - /* Fukato Datacask Jupiter 1014a (mrb74@gmx.at) */ - { ATH_SDEVICE(PCI_VENDOR_ID_AZWAVE, 0x1026), ATH_LED(3, 0) }, - /* IBM ThinkPad AR5BXB6 (legovini@spiro.fisica.unipd.it) */ - { ATH_SDEVICE(PCI_VENDOR_ID_IBM, 0x058a), ATH_LED(1, 0) }, - /* HP Compaq CQ60-206US (ddreggors@jumptv.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137a), ATH_LED(3, 1) }, - /* HP Compaq C700 (nitrousnrg@gmail.com) */ - { ATH_SDEVICE(PCI_VENDOR_ID_HP, 0x0137b), ATH_LED(3, 1) }, - /* IBM-specific AR5212 (all others) */ - { PCI_VDEVICE(ATHEROS, PCI_DEVICE_ID_ATHEROS_AR5212_IBM), ATH_LED(0, 0) }, - { } -}; - -void ath5k_led_enable(struct ath5k_softc *sc) -{ - if (test_bit(ATH_STAT_LEDSOFT, sc->status)) { - ath5k_hw_set_gpio_output(sc->ah, sc->led_pin); - ath5k_led_off(sc); - } -} - -static void ath5k_led_on(struct ath5k_softc *sc) -{ - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, sc->led_on); -} - -void ath5k_led_off(struct ath5k_softc *sc) -{ - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - return; - ath5k_hw_set_gpio(sc->ah, sc->led_pin, !sc->led_on); -} - -static void -ath5k_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct ath5k_led *led = container_of(led_dev, struct ath5k_led, - led_dev); - - if (brightness == LED_OFF) - ath5k_led_off(led->sc); - else - ath5k_led_on(led->sc); -} - -static int -ath5k_register_led(struct ath5k_softc *sc, struct ath5k_led *led, - const char *name, char *trigger) -{ - int err; - - led->sc = sc; - strncpy(led->name, name, sizeof(led->name)); - led->led_dev.name = led->name; - led->led_dev.default_trigger = trigger; - led->led_dev.brightness_set = ath5k_led_brightness_set; - - err = led_classdev_register(&sc->pdev->dev, &led->led_dev); - if (err) { - ATH5K_WARN(sc, "could not register LED %s\n", name); - led->sc = NULL; - } - return err; -} - -static void -ath5k_unregister_led(struct ath5k_led *led) -{ - if (!led->sc) - return; - led_classdev_unregister(&led->led_dev); - ath5k_led_off(led->sc); - led->sc = NULL; -} - -void ath5k_unregister_leds(struct ath5k_softc *sc) -{ - ath5k_unregister_led(&sc->rx_led); - ath5k_unregister_led(&sc->tx_led); -} - -int ath5k_init_leds(struct ath5k_softc *sc) -{ - int ret = 0; - struct ieee80211_hw *hw = sc->hw; - struct pci_dev *pdev = sc->pdev; - char name[ATH5K_LED_MAX_NAME_LEN + 1]; - const struct pci_device_id *match; - - match = pci_match_id(&ath5k_led_devices[0], pdev); - if (match) { - __set_bit(ATH_STAT_LEDSOFT, sc->status); - sc->led_pin = ATH_PIN(match->driver_data); - sc->led_on = ATH_POLARITY(match->driver_data); - } - - if (!test_bit(ATH_STAT_LEDSOFT, sc->status)) - goto out; - - ath5k_led_enable(sc); - - snprintf(name, sizeof(name), "ath5k-%s::rx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->rx_led, name, - ieee80211_get_rx_led_name(hw)); - if (ret) - goto out; - - snprintf(name, sizeof(name), "ath5k-%s::tx", wiphy_name(hw->wiphy)); - ret = ath5k_register_led(sc, &sc->tx_led, name, - ieee80211_get_tx_led_name(hw)); -out: - return ret; -} - diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c deleted file mode 100644 index 2942f13c9c4a..000000000000 --- a/drivers/net/wireless/ath/ath5k/pcu.c +++ /dev/null @@ -1,1175 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Matthew W. S. Bell - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/*********************************\ -* Protocol Control Unit Functions * -\*********************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/*******************\ -* Generic functions * -\*******************/ - -/** - * ath5k_hw_set_opmode - Set PCU operating mode - * - * @ah: The &struct ath5k_hw - * - * Initialize PCU for the various operating modes (AP/STA etc) - * - * NOTE: ah->ah_op_mode must be set before calling this. - */ -int ath5k_hw_set_opmode(struct ath5k_hw *ah) -{ - u32 pcu_reg, beacon_reg, low_id, high_id; - - - /* Preserve rest settings */ - pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; - pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP - | AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); - - beacon_reg = 0; - - ATH5K_TRACE(ah->ah_sc); - - switch (ah->ah_op_mode) { - case NL80211_IFTYPE_ADHOC: - pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_ADHOC; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; - - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; - beacon_reg |= AR5K_BCR_AP; - if (ah->ah_version == AR5K_AR5210) - pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; - else - AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); - break; - - case NL80211_IFTYPE_STATION: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_PWR_SV : 0); - case NL80211_IFTYPE_MONITOR: - pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE - | (ah->ah_version == AR5K_AR5210 ? - AR5K_STA_ID1_NO_PSPOLL : 0); - break; - - default: - return -EINVAL; - } - - /* - * Set PCU registers - */ - low_id = AR5K_LOW_ID(ah->ah_sta_id); - high_id = AR5K_HIGH_ID(ah->ah_sta_id); - ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); - ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); - - /* - * Set Beacon Control Register on 5210 - */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); - - return 0; -} - -/** - * ath5k_hw_update - Update mib counters (mac layer statistics) - * - * @ah: The &struct ath5k_hw - * @stats: The &struct ieee80211_low_level_stats we use to track - * statistics on the driver - * - * Reads MIB counters from PCU and updates sw statistics. Must be - * called after a MIB interrupt. - */ -void ath5k_hw_update_mib_counters(struct ath5k_hw *ah, - struct ieee80211_low_level_stats *stats) -{ - ATH5K_TRACE(ah->ah_sc); - - /* Read-And-Clear */ - stats->dot11ACKFailureCount += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); - stats->dot11RTSFailureCount += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); - stats->dot11RTSSuccessCount += ath5k_hw_reg_read(ah, AR5K_RTS_OK); - stats->dot11FCSErrorCount += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); - - /* XXX: Should we use this to track beacon count ? - * -we read it anyway to clear the register */ - ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); - - /* Reset profile count registers on 5212*/ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_TX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RX); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_RXCLR); - ath5k_hw_reg_write(ah, 0, AR5K_PROFCNT_CYCLE); - } - - /* TODO: Handle ANI stats */ -} - -/** - * ath5k_hw_set_ack_bitrate - set bitrate for ACKs - * - * @ah: The &struct ath5k_hw - * @high: Flag to determine if we want to use high transmition rate - * for ACKs or not - * - * If high flag is set, we tell hw to use a set of control rates based on - * the current transmition rate (check out control_rates array inside reset.c). - * If not hw just uses the lowest rate available for the current modulation - * scheme being used (1Mbit for CCK and 6Mbits for OFDM). - */ -void ath5k_hw_set_ack_bitrate_high(struct ath5k_hw *ah, bool high) -{ - if (ah->ah_version != AR5K_AR5212) - return; - else { - u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; - if (high) - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); - } -} - - -/******************\ -* ACK/CTS Timeouts * -\******************/ - -/** - * ath5k_hw_het_ack_timeout - Get ACK timeout from PCU in usec - * - * @ah: The &struct ath5k_hw - */ -unsigned int ath5k_hw_get_ack_timeout(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_ACK), ah->ah_turbo); -} - -/** - * ath5k_hw_set_ack_timeout - Set ACK timeout on PCU - * - * @ah: The &struct ath5k_hw - * @timeout: Timeout in usec - */ -int ath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) -{ - ATH5K_TRACE(ah->ah_sc); - if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK), - ah->ah_turbo) <= timeout) - return -EINVAL; - - AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, - ath5k_hw_htoclock(timeout, ah->ah_turbo)); - - return 0; -} - -/** - * ath5k_hw_get_cts_timeout - Get CTS timeout from PCU in usec - * - * @ah: The &struct ath5k_hw - */ -unsigned int ath5k_hw_get_cts_timeout(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_clocktoh(AR5K_REG_MS(ath5k_hw_reg_read(ah, - AR5K_TIME_OUT), AR5K_TIME_OUT_CTS), ah->ah_turbo); -} - -/** - * ath5k_hw_set_cts_timeout - Set CTS timeout on PCU - * - * @ah: The &struct ath5k_hw - * @timeout: Timeout in usec - */ -int ath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) -{ - ATH5K_TRACE(ah->ah_sc); - if (ath5k_hw_clocktoh(AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS), - ah->ah_turbo) <= timeout) - return -EINVAL; - - AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, - ath5k_hw_htoclock(timeout, ah->ah_turbo)); - - return 0; -} - - -/****************\ -* BSSID handling * -\****************/ - -/** - * ath5k_hw_get_lladdr - Get station id - * - * @ah: The &struct ath5k_hw - * @mac: The card's mac address - * - * Initialize ah->ah_sta_id using the mac address provided - * (just a memcpy). - * - * TODO: Remove it once we merge ath5k_softc and ath5k_hw - */ -void ath5k_hw_get_lladdr(struct ath5k_hw *ah, u8 *mac) -{ - ATH5K_TRACE(ah->ah_sc); - memcpy(mac, ah->ah_sta_id, ETH_ALEN); -} - -/** - * ath5k_hw_set_lladdr - Set station id - * - * @ah: The &struct ath5k_hw - * @mac: The card's mac address - * - * Set station id on hw using the provided mac address - */ -int ath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) -{ - u32 low_id, high_id; - u32 pcu_reg; - - ATH5K_TRACE(ah->ah_sc); - /* Set new station ID */ - memcpy(ah->ah_sta_id, mac, ETH_ALEN); - - pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; - - low_id = AR5K_LOW_ID(mac); - high_id = AR5K_HIGH_ID(mac); - - ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); - ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); - - return 0; -} - -/** - * ath5k_hw_set_associd - Set BSSID for association - * - * @ah: The &struct ath5k_hw - * @bssid: BSSID - * @assoc_id: Assoc id - * - * Sets the BSSID which trigers the "SME Join" operation - */ -void ath5k_hw_set_associd(struct ath5k_hw *ah, const u8 *bssid, u16 assoc_id) -{ - u32 low_id, high_id; - u16 tim_offset = 0; - - /* - * Set simple BSSID mask on 5212 - */ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_bssid_mask), - AR5K_BSS_IDM0); - ath5k_hw_reg_write(ah, AR5K_HIGH_ID(ah->ah_bssid_mask), - AR5K_BSS_IDM1); - } - - /* - * Set BSSID which triggers the "SME Join" operation - */ - low_id = AR5K_LOW_ID(bssid); - high_id = AR5K_HIGH_ID(bssid); - ath5k_hw_reg_write(ah, low_id, AR5K_BSS_ID0); - ath5k_hw_reg_write(ah, high_id | ((assoc_id & 0x3fff) << - AR5K_BSS_ID1_AID_S), AR5K_BSS_ID1); - - if (assoc_id == 0) { - ath5k_hw_disable_pspoll(ah); - return; - } - - AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, - tim_offset ? tim_offset + 4 : 0); - - ath5k_hw_enable_pspoll(ah, NULL, 0); -} - -/** - * ath5k_hw_set_bssid_mask - filter out bssids we listen - * - * @ah: the &struct ath5k_hw - * @mask: the bssid_mask, a u8 array of size ETH_ALEN - * - * BSSID masking is a method used by AR5212 and newer hardware to inform PCU - * which bits of the interface's MAC address should be looked at when trying - * to decide which packets to ACK. In station mode and AP mode with a single - * BSS every bit matters since we lock to only one BSS. In AP mode with - * multiple BSSes (virtual interfaces) not every bit matters because hw must - * accept frames for all BSSes and so we tweak some bits of our mac address - * in order to have multiple BSSes. - * - * NOTE: This is a simple filter and does *not* filter out all - * relevant frames. Some frames that are not for us might get ACKed from us - * by PCU because they just match the mask. - * - * When handling multiple BSSes you can get the BSSID mask by computing the - * set of ~ ( MAC XOR BSSID ) for all bssids we handle. - * - * When you do this you are essentially computing the common bits of all your - * BSSes. Later it is assumed the harware will "and" (&) the BSSID mask with - * the MAC address to obtain the relevant bits and compare the result with - * (frame's BSSID & mask) to see if they match. - */ -/* - * Simple example: on your card you have have two BSSes you have created with - * BSSID-01 and BSSID-02. Lets assume BSSID-01 will not use the MAC address. - * There is another BSSID-03 but you are not part of it. For simplicity's sake, - * assuming only 4 bits for a mac address and for BSSIDs you can then have: - * - * \ - * MAC: 0001 | - * BSSID-01: 0100 | --> Belongs to us - * BSSID-02: 1001 | - * / - * ------------------- - * BSSID-03: 0110 | --> External - * ------------------- - * - * Our bssid_mask would then be: - * - * On loop iteration for BSSID-01: - * ~(0001 ^ 0100) -> ~(0101) - * -> 1010 - * bssid_mask = 1010 - * - * On loop iteration for BSSID-02: - * bssid_mask &= ~(0001 ^ 1001) - * bssid_mask = (1010) & ~(0001 ^ 1001) - * bssid_mask = (1010) & ~(1001) - * bssid_mask = (1010) & (0110) - * bssid_mask = 0010 - * - * A bssid_mask of 0010 means "only pay attention to the second least - * significant bit". This is because its the only bit common - * amongst the MAC and all BSSIDs we support. To findout what the real - * common bit is we can simply "&" the bssid_mask now with any BSSID we have - * or our MAC address (we assume the hardware uses the MAC address). - * - * Now, suppose there's an incoming frame for BSSID-03: - * - * IFRAME-01: 0110 - * - * An easy eye-inspeciton of this already should tell you that this frame - * will not pass our check. This is beacuse the bssid_mask tells the - * hardware to only look at the second least significant bit and the - * common bit amongst the MAC and BSSIDs is 0, this frame has the 2nd LSB - * as 1, which does not match 0. - * - * So with IFRAME-01 we *assume* the hardware will do: - * - * allow = (IFRAME-01 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; - * --> allow = (0110 & 0010) == (0010 & 0001) ? 1 : 0; - * --> allow = (0010) == 0000 ? 1 : 0; - * --> allow = 0 - * - * Lets now test a frame that should work: - * - * IFRAME-02: 0001 (we should allow) - * - * allow = (0001 & 1010) == 1010 - * - * allow = (IFRAME-02 & bssid_mask) == (bssid_mask & MAC) ? 1 : 0; - * --> allow = (0001 & 0010) == (0010 & 0001) ? 1 :0; - * --> allow = (0010) == (0010) - * --> allow = 1 - * - * Other examples: - * - * IFRAME-03: 0100 --> allowed - * IFRAME-04: 1001 --> allowed - * IFRAME-05: 1101 --> allowed but its not for us!!! - * - */ -int ath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) -{ - u32 low_id, high_id; - ATH5K_TRACE(ah->ah_sc); - - /* Cache bssid mask so that we can restore it - * on reset */ - memcpy(ah->ah_bssid_mask, mask, ETH_ALEN); - if (ah->ah_version == AR5K_AR5212) { - low_id = AR5K_LOW_ID(mask); - high_id = AR5K_HIGH_ID(mask); - - ath5k_hw_reg_write(ah, low_id, AR5K_BSS_IDM0); - ath5k_hw_reg_write(ah, high_id, AR5K_BSS_IDM1); - - return 0; - } - - return -EIO; -} - - -/************\ -* RX Control * -\************/ - -/** - * ath5k_hw_start_rx_pcu - Start RX engine - * - * @ah: The &struct ath5k_hw - * - * Starts RX engine on PCU so that hw can process RXed frames - * (ACK etc). - * - * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma - * TODO: Init ANI here - */ -void ath5k_hw_start_rx_pcu(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - -/** - * at5k_hw_stop_rx_pcu - Stop RX engine - * - * @ah: The &struct ath5k_hw - * - * Stops RX engine on PCU - * - * TODO: Detach ANI here - */ -void ath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); -} - -/* - * Set multicast filter - */ -void ath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) -{ - ATH5K_TRACE(ah->ah_sc); - /* Set the multicat filter */ - ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); - ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); -} - -/* - * Set multicast filter by index - */ -int ath5k_hw_set_mcast_filter_idx(struct ath5k_hw *ah, u32 index) -{ - - ATH5K_TRACE(ah->ah_sc); - if (index >= 64) - return -EINVAL; - else if (index >= 32) - AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER1, - (1 << (index - 32))); - else - AR5K_REG_ENABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); - - return 0; -} - -/* - * Clear Multicast filter by index - */ -int ath5k_hw_clear_mcast_filter_idx(struct ath5k_hw *ah, u32 index) -{ - - ATH5K_TRACE(ah->ah_sc); - if (index >= 64) - return -EINVAL; - else if (index >= 32) - AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER1, - (1 << (index - 32))); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_MCAST_FILTER0, (1 << index)); - - return 0; -} - -/** - * ath5k_hw_get_rx_filter - Get current rx filter - * - * @ah: The &struct ath5k_hw - * - * Returns the RX filter by reading rx filter and - * phy error filter registers. RX filter is used - * to set the allowed frame types that PCU will accept - * and pass to the driver. For a list of frame types - * check out reg.h. - */ -u32 ath5k_hw_get_rx_filter(struct ath5k_hw *ah) -{ - u32 data, filter = 0; - - ATH5K_TRACE(ah->ah_sc); - filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); - - /*Radar detection for 5212*/ - if (ah->ah_version == AR5K_AR5212) { - data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); - - if (data & AR5K_PHY_ERR_FIL_RADAR) - filter |= AR5K_RX_FILTER_RADARERR; - if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) - filter |= AR5K_RX_FILTER_PHYERR; - } - - return filter; -} - -/** - * ath5k_hw_set_rx_filter - Set rx filter - * - * @ah: The &struct ath5k_hw - * @filter: RX filter mask (see reg.h) - * - * Sets RX filter register and also handles PHY error filter - * register on 5212 and newer chips so that we have proper PHY - * error reporting. - */ -void ath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) -{ - u32 data = 0; - - ATH5K_TRACE(ah->ah_sc); - - /* Set PHY error filter register on 5212*/ - if (ah->ah_version == AR5K_AR5212) { - if (filter & AR5K_RX_FILTER_RADARERR) - data |= AR5K_PHY_ERR_FIL_RADAR; - if (filter & AR5K_RX_FILTER_PHYERR) - data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; - } - - /* - * The AR5210 uses promiscous mode to detect radar activity - */ - if (ah->ah_version == AR5K_AR5210 && - (filter & AR5K_RX_FILTER_RADARERR)) { - filter &= ~AR5K_RX_FILTER_RADARERR; - filter |= AR5K_RX_FILTER_PROM; - } - - /*Zero length DMA (phy error reporting) */ - if (data) - AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); - - /*Write RX Filter register*/ - ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); - - /*Write PHY error filter register on 5212*/ - if (ah->ah_version == AR5K_AR5212) - ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); - -} - - -/****************\ -* Beacon control * -\****************/ - -/** - * ath5k_hw_get_tsf32 - Get a 32bit TSF - * - * @ah: The &struct ath5k_hw - * - * Returns lower 32 bits of current TSF - */ -u32 ath5k_hw_get_tsf32(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - return ath5k_hw_reg_read(ah, AR5K_TSF_L32); -} - -/** - * ath5k_hw_get_tsf64 - Get the full 64bit TSF - * - * @ah: The &struct ath5k_hw - * - * Returns the current TSF - */ -u64 ath5k_hw_get_tsf64(struct ath5k_hw *ah) -{ - u64 tsf = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - ATH5K_TRACE(ah->ah_sc); - - return ath5k_hw_reg_read(ah, AR5K_TSF_L32) | (tsf << 32); -} - -/** - * ath5k_hw_set_tsf64 - Set a new 64bit TSF - * - * @ah: The &struct ath5k_hw - * @tsf64: The new 64bit TSF - * - * Sets the new TSF - */ -void ath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) -{ - ATH5K_TRACE(ah->ah_sc); - - ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); - ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); -} - -/** - * ath5k_hw_reset_tsf - Force a TSF reset - * - * @ah: The &struct ath5k_hw - * - * Forces a TSF reset on PCU - */ -void ath5k_hw_reset_tsf(struct ath5k_hw *ah) -{ - u32 val; - - ATH5K_TRACE(ah->ah_sc); - - val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; - - /* - * Each write to the RESET_TSF bit toggles a hardware internal - * signal to reset TSF, but if left high it will cause a TSF reset - * on the next chip reset as well. Thus we always write the value - * twice to clear the signal. - */ - ath5k_hw_reg_write(ah, val, AR5K_BEACON); - ath5k_hw_reg_write(ah, val, AR5K_BEACON); -} - -/* - * Initialize beacon timers - */ -void ath5k_hw_init_beacon(struct ath5k_hw *ah, u32 next_beacon, u32 interval) -{ - u32 timer1, timer2, timer3; - - ATH5K_TRACE(ah->ah_sc); - /* - * Set the additional timers by mode - */ - switch (ah->ah_op_mode) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_STATION: - /* In STA mode timer1 is used as next wakeup - * timer and timer2 as next CFP duration start - * timer. Both in 1/8TUs. */ - /* TODO: PCF handling */ - if (ah->ah_version == AR5K_AR5210) { - timer1 = 0xffffffff; - timer2 = 0xffffffff; - } else { - timer1 = 0x0000ffff; - timer2 = 0x0007ffff; - } - /* Mark associated AP as PCF incapable for now */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); - break; - case NL80211_IFTYPE_ADHOC: - AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); - default: - /* On non-STA modes timer1 is used as next DMA - * beacon alert (DBA) timer and timer2 as next - * software beacon alert. Both in 1/8TUs. */ - timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; - timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; - break; - } - - /* Timer3 marks the end of our ATIM window - * a zero length window is not allowed because - * we 'll get no beacons */ - timer3 = next_beacon + (ah->ah_atim_window ? ah->ah_atim_window : 1); - - /* - * Set the beacon register and enable all timers. - */ - /* When in AP or Mesh Point mode zero timer0 to start TSF */ - if (ah->ah_op_mode == NL80211_IFTYPE_AP || - ah->ah_op_mode == NL80211_IFTYPE_MESH_POINT) - ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - - ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); - ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); - ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); - ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); - - /* Force a TSF reset if requested and enable beacons */ - if (interval & AR5K_BEACON_RESET_TSF) - ath5k_hw_reset_tsf(ah); - - ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | - AR5K_BEACON_ENABLE), - AR5K_BEACON); - - /* Flush any pending BMISS interrupts on ISR by - * performing a clear-on-write operation on PISR - * register for the BMISS bit (writing a bit on - * ISR togles a reset for that bit and leaves - * the rest bits intact) */ - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); - else - ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); - - /* TODO: Set enchanced sleep registers on AR5212 - * based on vif->bss_conf params, until then - * disable power save reporting.*/ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); - -} - -#if 0 -/* - * Set beacon timers - */ -int ath5k_hw_set_beacon_timers(struct ath5k_hw *ah, - const struct ath5k_beacon_state *state) -{ - u32 cfp_period, next_cfp, dtim, interval, next_beacon; - - /* - * TODO: should be changed through *state - * review struct ath5k_beacon_state struct - * - * XXX: These are used for cfp period bellow, are they - * ok ? Is it O.K. for tsf here to be 0 or should we use - * get_tsf ? - */ - u32 dtim_count = 0; /* XXX */ - u32 cfp_count = 0; /* XXX */ - u32 tsf = 0; /* XXX */ - - ATH5K_TRACE(ah->ah_sc); - /* Return on an invalid beacon state */ - if (state->bs_interval < 1) - return -EINVAL; - - interval = state->bs_interval; - dtim = state->bs_dtim_period; - - /* - * PCF support? - */ - if (state->bs_cfp_period > 0) { - /* - * Enable PCF mode and set the CFP - * (Contention Free Period) and timer registers - */ - cfp_period = state->bs_cfp_period * state->bs_dtim_period * - state->bs_interval; - next_cfp = (cfp_count * state->bs_dtim_period + dtim_count) * - state->bs_interval; - - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_PCF); - ath5k_hw_reg_write(ah, cfp_period, AR5K_CFP_PERIOD); - ath5k_hw_reg_write(ah, state->bs_cfp_max_duration, - AR5K_CFP_DUR); - ath5k_hw_reg_write(ah, (tsf + (next_cfp == 0 ? cfp_period : - next_cfp)) << 3, AR5K_TIMER2); - } else { - /* Disable PCF mode */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_PCF); - } - - /* - * Enable the beacon timer register - */ - ath5k_hw_reg_write(ah, state->bs_next_beacon, AR5K_TIMER0); - - /* - * Start the beacon timers - */ - ath5k_hw_reg_write(ah, (ath5k_hw_reg_read(ah, AR5K_BEACON) & - ~(AR5K_BEACON_PERIOD | AR5K_BEACON_TIM)) | - AR5K_REG_SM(state->bs_tim_offset ? state->bs_tim_offset + 4 : 0, - AR5K_BEACON_TIM) | AR5K_REG_SM(state->bs_interval, - AR5K_BEACON_PERIOD), AR5K_BEACON); - - /* - * Write new beacon miss threshold, if it appears to be valid - * XXX: Figure out right values for min <= bs_bmiss_threshold <= max - * and return if its not in range. We can test this by reading value and - * setting value to a largest value and seeing which values register. - */ - - AR5K_REG_WRITE_BITS(ah, AR5K_RSSI_THR, AR5K_RSSI_THR_BMISS, - state->bs_bmiss_threshold); - - /* - * Set sleep control register - * XXX: Didn't find this in 5210 code but since this register - * exists also in ar5k's 5210 headers i leave it as common code. - */ - AR5K_REG_WRITE_BITS(ah, AR5K_SLEEP_CTL, AR5K_SLEEP_CTL_SLDUR, - (state->bs_sleep_duration - 3) << 3); - - /* - * Set enhanced sleep registers on 5212 - */ - if (ah->ah_version == AR5K_AR5212) { - if (state->bs_sleep_duration > state->bs_interval && - roundup(state->bs_sleep_duration, interval) == - state->bs_sleep_duration) - interval = state->bs_sleep_duration; - - if (state->bs_sleep_duration > dtim && (dtim == 0 || - roundup(state->bs_sleep_duration, dtim) == - state->bs_sleep_duration)) - dtim = state->bs_sleep_duration; - - if (interval > dtim) - return -EINVAL; - - next_beacon = interval == dtim ? state->bs_next_dtim : - state->bs_next_beacon; - - ath5k_hw_reg_write(ah, - AR5K_REG_SM((state->bs_next_dtim - 3) << 3, - AR5K_SLEEP0_NEXT_DTIM) | - AR5K_REG_SM(10, AR5K_SLEEP0_CABTO) | - AR5K_SLEEP0_ENH_SLEEP_EN | - AR5K_SLEEP0_ASSUME_DTIM, AR5K_SLEEP0); - - ath5k_hw_reg_write(ah, AR5K_REG_SM((next_beacon - 3) << 3, - AR5K_SLEEP1_NEXT_TIM) | - AR5K_REG_SM(10, AR5K_SLEEP1_BEACON_TO), AR5K_SLEEP1); - - ath5k_hw_reg_write(ah, - AR5K_REG_SM(interval, AR5K_SLEEP2_TIM_PER) | - AR5K_REG_SM(dtim, AR5K_SLEEP2_DTIM_PER), AR5K_SLEEP2); - } - - return 0; -} - -/* - * Reset beacon timers - */ -void ath5k_hw_reset_beacon(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - /* - * Disable beacon timer - */ - ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); - - /* - * Disable some beacon register values - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, - AR5K_STA_ID1_DEFAULT_ANTENNA | AR5K_STA_ID1_PCF); - ath5k_hw_reg_write(ah, AR5K_BEACON_PERIOD, AR5K_BEACON); -} - -/* - * Wait for beacon queue to finish - */ -int ath5k_hw_beaconq_finish(struct ath5k_hw *ah, unsigned long phys_addr) -{ - unsigned int i; - int ret; - - ATH5K_TRACE(ah->ah_sc); - - /* 5210 doesn't have QCU*/ - if (ah->ah_version == AR5K_AR5210) { - /* - * Wait for beaconn queue to finish by checking - * Control Register and Beacon Status Register. - */ - for (i = AR5K_TUNE_BEACON_INTERVAL / 2; i > 0; i--) { - if (!(ath5k_hw_reg_read(ah, AR5K_BSR) & AR5K_BSR_TXQ1F) - || - !(ath5k_hw_reg_read(ah, AR5K_CR) & AR5K_BSR_TXQ1F)) - break; - udelay(10); - } - - /* Timeout... */ - if (i <= 0) { - /* - * Re-schedule the beacon queue - */ - ath5k_hw_reg_write(ah, phys_addr, AR5K_NOQCU_TXDP1); - ath5k_hw_reg_write(ah, AR5K_BCR_TQ1V | AR5K_BCR_BDMAE, - AR5K_BCR); - - return -EIO; - } - ret = 0; - } else { - /*5211/5212*/ - ret = ath5k_hw_register_timeout(ah, - AR5K_QUEUE_STATUS(AR5K_TX_QUEUE_ID_BEACON), - AR5K_QCU_STS_FRMPENDCNT, 0, false); - - if (AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, AR5K_TX_QUEUE_ID_BEACON)) - return -EIO; - } - - return ret; -} -#endif - - -/*********************\ -* Key table functions * -\*********************/ - -/* - * Reset a key entry on the table - */ -int ath5k_hw_reset_key(struct ath5k_hw *ah, u16 entry) -{ - unsigned int i, type; - u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - type = ath5k_hw_reg_read(ah, AR5K_KEYTABLE_TYPE(entry)); - - for (i = 0; i < AR5K_KEYCACHE_SIZE; i++) - ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_OFF(entry, i)); - - /* Reset associated MIC entry if TKIP - * is enabled located at offset (entry + 64) */ - if (type == AR5K_KEYTABLE_TYPE_TKIP) { - AR5K_ASSERT_ENTRY(micentry, AR5K_KEYTABLE_SIZE); - for (i = 0; i < AR5K_KEYCACHE_SIZE / 2 ; i++) - ath5k_hw_reg_write(ah, 0, - AR5K_KEYTABLE_OFF(micentry, i)); - } - - /* - * Set NULL encryption on AR5212+ - * - * Note: AR5K_KEYTABLE_TYPE -> AR5K_KEYTABLE_OFF(entry, 5) - * AR5K_KEYTABLE_TYPE_NULL -> 0x00000007 - * - * Note2: Windows driver (ndiswrapper) sets this to - * 0x00000714 instead of 0x00000007 - */ - if (ah->ah_version >= AR5K_AR5211) { - ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, - AR5K_KEYTABLE_TYPE(entry)); - - if (type == AR5K_KEYTABLE_TYPE_TKIP) { - ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, - AR5K_KEYTABLE_TYPE(micentry)); - } - } - - return 0; -} - -/* - * Check if a table entry is valid - */ -int ath5k_hw_is_key_valid(struct ath5k_hw *ah, u16 entry) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - /* Check the validation flag at the end of the entry */ - return ath5k_hw_reg_read(ah, AR5K_KEYTABLE_MAC1(entry)) & - AR5K_KEYTABLE_VALID; -} - -static -int ath5k_keycache_type(const struct ieee80211_key_conf *key) -{ - switch (key->alg) { - case ALG_TKIP: - return AR5K_KEYTABLE_TYPE_TKIP; - case ALG_CCMP: - return AR5K_KEYTABLE_TYPE_CCM; - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - return AR5K_KEYTABLE_TYPE_40; - else if (key->keylen == WLAN_KEY_LEN_WEP104) - return AR5K_KEYTABLE_TYPE_104; - return -EINVAL; - default: - return -EINVAL; - } - return -EINVAL; -} - -/* - * Set a key entry on the table - */ -int ath5k_hw_set_key(struct ath5k_hw *ah, u16 entry, - const struct ieee80211_key_conf *key, const u8 *mac) -{ - unsigned int i; - int keylen; - __le32 key_v[5] = {}; - __le32 key0 = 0, key1 = 0; - __le32 *rxmic, *txmic; - int keytype; - u16 micentry = entry + AR5K_KEYTABLE_MIC_OFFSET; - bool is_tkip; - const u8 *key_ptr; - - ATH5K_TRACE(ah->ah_sc); - - is_tkip = (key->alg == ALG_TKIP); - - /* - * key->keylen comes in from mac80211 in bytes. - * TKIP is 128 bit + 128 bit mic - */ - keylen = (is_tkip) ? (128 / 8) : key->keylen; - - if (entry > AR5K_KEYTABLE_SIZE || - (is_tkip && micentry > AR5K_KEYTABLE_SIZE)) - return -EOPNOTSUPP; - - if (unlikely(keylen > 16)) - return -EOPNOTSUPP; - - keytype = ath5k_keycache_type(key); - if (keytype < 0) - return keytype; - - /* - * each key block is 6 bytes wide, written as pairs of - * alternating 32 and 16 bit le values. - */ - key_ptr = key->key; - for (i = 0; keylen >= 6; keylen -= 6) { - memcpy(&key_v[i], key_ptr, 6); - i += 2; - key_ptr += 6; - } - if (keylen) - memcpy(&key_v[i], key_ptr, keylen); - - /* intentionally corrupt key until mic is installed */ - if (is_tkip) { - key0 = key_v[0] = ~key_v[0]; - key1 = key_v[1] = ~key_v[1]; - } - - for (i = 0; i < ARRAY_SIZE(key_v); i++) - ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), - AR5K_KEYTABLE_OFF(entry, i)); - - ath5k_hw_reg_write(ah, keytype, AR5K_KEYTABLE_TYPE(entry)); - - if (is_tkip) { - /* Install rx/tx MIC */ - rxmic = (__le32 *) &key->key[16]; - txmic = (__le32 *) &key->key[24]; - - if (ah->ah_combined_mic) { - key_v[0] = rxmic[0]; - key_v[1] = cpu_to_le32(le32_to_cpu(txmic[0]) >> 16); - key_v[2] = rxmic[1]; - key_v[3] = cpu_to_le32(le32_to_cpu(txmic[0]) & 0xffff); - key_v[4] = txmic[1]; - } else { - key_v[0] = rxmic[0]; - key_v[1] = 0; - key_v[2] = rxmic[1]; - key_v[3] = 0; - key_v[4] = 0; - } - for (i = 0; i < ARRAY_SIZE(key_v); i++) - ath5k_hw_reg_write(ah, le32_to_cpu(key_v[i]), - AR5K_KEYTABLE_OFF(micentry, i)); - - ath5k_hw_reg_write(ah, AR5K_KEYTABLE_TYPE_NULL, - AR5K_KEYTABLE_TYPE(micentry)); - ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC0(micentry)); - ath5k_hw_reg_write(ah, 0, AR5K_KEYTABLE_MAC1(micentry)); - - /* restore first 2 words of key */ - ath5k_hw_reg_write(ah, le32_to_cpu(~key0), - AR5K_KEYTABLE_OFF(entry, 0)); - ath5k_hw_reg_write(ah, le32_to_cpu(~key1), - AR5K_KEYTABLE_OFF(entry, 1)); - } - - return ath5k_hw_set_key_lladdr(ah, entry, mac); -} - -int ath5k_hw_set_key_lladdr(struct ath5k_hw *ah, u16 entry, const u8 *mac) -{ - u32 low_id, high_id; - - ATH5K_TRACE(ah->ah_sc); - /* Invalid entry (key table overflow) */ - AR5K_ASSERT_ENTRY(entry, AR5K_KEYTABLE_SIZE); - - /* MAC may be NULL if it's a broadcast key. In this case no need to - * to compute AR5K_LOW_ID and AR5K_HIGH_ID as we already know it. */ - if (!mac) { - low_id = 0xffffffff; - high_id = 0xffff | AR5K_KEYTABLE_VALID; - } else { - low_id = AR5K_LOW_ID(mac); - high_id = AR5K_HIGH_ID(mac) | AR5K_KEYTABLE_VALID; - } - - ath5k_hw_reg_write(ah, low_id, AR5K_KEYTABLE_MAC0(entry)); - ath5k_hw_reg_write(ah, high_id, AR5K_KEYTABLE_MAC1(entry)); - - return 0; -} - diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c deleted file mode 100644 index 9d676474839d..000000000000 --- a/drivers/net/wireless/ath/ath5k/phy.c +++ /dev/null @@ -1,3075 +0,0 @@ -/* - * PHY functions - * - * Copyright (c) 2004-2007 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * Copyright (c) 2007-2008 Jiri Slaby - * Copyright (c) 2008-2009 Felix Fietkau - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#define _ATH5K_PHY - -#include - -#include "ath5k.h" -#include "reg.h" -#include "base.h" -#include "rfbuffer.h" -#include "rfgain.h" - -/* - * Used to modify RF Banks before writing them to AR5K_RF_BUFFER - */ -static unsigned int ath5k_hw_rfb_op(struct ath5k_hw *ah, - const struct ath5k_rf_reg *rf_regs, - u32 val, u8 reg_id, bool set) -{ - const struct ath5k_rf_reg *rfreg = NULL; - u8 offset, bank, num_bits, col, position; - u16 entry; - u32 mask, data, last_bit, bits_shifted, first_bit; - u32 *rfb; - s32 bits_left; - int i; - - data = 0; - rfb = ah->ah_rf_banks; - - for (i = 0; i < ah->ah_rf_regs_count; i++) { - if (rf_regs[i].index == reg_id) { - rfreg = &rf_regs[i]; - break; - } - } - - if (rfb == NULL || rfreg == NULL) { - ATH5K_PRINTF("Rf register not found!\n"); - /* should not happen */ - return 0; - } - - bank = rfreg->bank; - num_bits = rfreg->field.len; - first_bit = rfreg->field.pos; - col = rfreg->field.col; - - /* first_bit is an offset from bank's - * start. Since we have all banks on - * the same array, we use this offset - * to mark each bank's start */ - offset = ah->ah_offset[bank]; - - /* Boundary check */ - if (!(col <= 3 && num_bits <= 32 && first_bit + num_bits <= 319)) { - ATH5K_PRINTF("invalid values at offset %u\n", offset); - return 0; - } - - entry = ((first_bit - 1) / 8) + offset; - position = (first_bit - 1) % 8; - - if (set) - data = ath5k_hw_bitswap(val, num_bits); - - for (bits_shifted = 0, bits_left = num_bits; bits_left > 0; - position = 0, entry++) { - - last_bit = (position + bits_left > 8) ? 8 : - position + bits_left; - - mask = (((1 << last_bit) - 1) ^ ((1 << position) - 1)) << - (col * 8); - - if (set) { - rfb[entry] &= ~mask; - rfb[entry] |= ((data << position) << (col * 8)) & mask; - data >>= (8 - position); - } else { - data |= (((rfb[entry] & mask) >> (col * 8)) >> position) - << bits_shifted; - bits_shifted += last_bit - position; - } - - bits_left -= 8 - position; - } - - data = set ? 1 : ath5k_hw_bitswap(data, num_bits); - - return data; -} - -/**********************\ -* RF Gain optimization * -\**********************/ - -/* - * This code is used to optimize rf gain on different environments - * (temprature mostly) based on feedback from a power detector. - * - * It's only used on RF5111 and RF5112, later RF chips seem to have - * auto adjustment on hw -notice they have a much smaller BANK 7 and - * no gain optimization ladder-. - * - * For more infos check out this patent doc - * http://www.freepatentsonline.com/7400691.html - * - * This paper describes power drops as seen on the receiver due to - * probe packets - * http://www.cnri.dit.ie/publications/ICT08%20-%20Practical%20Issues - * %20of%20Power%20Control.pdf - * - * And this is the MadWiFi bug entry related to the above - * http://madwifi-project.org/ticket/1659 - * with various measurements and diagrams - * - * TODO: Deal with power drops due to probes by setting an apropriate - * tx power on the probe packets ! Make this part of the calibration process. - */ - -/* Initialize ah_gain durring attach */ -int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah) -{ - /* Initialize the gain optimization values */ - switch (ah->ah_radio) { - case AR5K_RF5111: - ah->ah_gain.g_step_idx = rfgain_opt_5111.go_default; - ah->ah_gain.g_low = 20; - ah->ah_gain.g_high = 35; - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - break; - case AR5K_RF5112: - ah->ah_gain.g_step_idx = rfgain_opt_5112.go_default; - ah->ah_gain.g_low = 20; - ah->ah_gain.g_high = 85; - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - break; - default: - return -EINVAL; - } - - return 0; -} - -/* Schedule a gain probe check on the next transmited packet. - * That means our next packet is going to be sent with lower - * tx power and a Peak to Average Power Detector (PAPD) will try - * to measure the gain. - * - * XXX: How about forcing a tx packet (bypassing PCU arbitrator etc) - * just after we enable the probe so that we don't mess with - * standard traffic ? Maybe it's time to use sw interrupts and - * a probe tasklet !!! - */ -static void ath5k_hw_request_rfgain_probe(struct ath5k_hw *ah) -{ - - /* Skip if gain calibration is inactive or - * we already handle a probe request */ - if (ah->ah_gain.g_state != AR5K_RFGAIN_ACTIVE) - return; - - /* Send the packet with 2dB below max power as - * patent doc suggest */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txpower.txp_ofdm - 4, - AR5K_PHY_PAPD_PROBE_TXPOWER) | - AR5K_PHY_PAPD_PROBE_TX_NEXT, AR5K_PHY_PAPD_PROBE); - - ah->ah_gain.g_state = AR5K_RFGAIN_READ_REQUESTED; - -} - -/* Calculate gain_F measurement correction - * based on the current step for RF5112 rev. 2 */ -static u32 ath5k_hw_rf_gainf_corr(struct ath5k_hw *ah) -{ - u32 mix, step; - u32 *rf; - const struct ath5k_gain_opt *go; - const struct ath5k_gain_opt_step *g_step; - const struct ath5k_rf_reg *rf_regs; - - /* Only RF5112 Rev. 2 supports it */ - if ((ah->ah_radio != AR5K_RF5112) || - (ah->ah_radio_5ghz_revision <= AR5K_SREV_RAD_5112A)) - return 0; - - go = &rfgain_opt_5112; - rf_regs = rf_regs_5112a; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); - - g_step = &go->go_step[ah->ah_gain.g_step_idx]; - - if (ah->ah_rf_banks == NULL) - return 0; - - rf = ah->ah_rf_banks; - ah->ah_gain.g_f_corr = 0; - - /* No VGA (Variable Gain Amplifier) override, skip */ - if (ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, false) != 1) - return 0; - - /* Mix gain stepping */ - step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXGAIN_STEP, false); - - /* Mix gain override */ - mix = g_step->gos_param[0]; - - switch (mix) { - case 3: - ah->ah_gain.g_f_corr = step * 2; - break; - case 2: - ah->ah_gain.g_f_corr = (step - 5) * 2; - break; - case 1: - ah->ah_gain.g_f_corr = step; - break; - default: - ah->ah_gain.g_f_corr = 0; - break; - } - - return ah->ah_gain.g_f_corr; -} - -/* Check if current gain_F measurement is in the range of our - * power detector windows. If we get a measurement outside range - * we know it's not accurate (detectors can't measure anything outside - * their detection window) so we must ignore it */ -static bool ath5k_hw_rf_check_gainf_readback(struct ath5k_hw *ah) -{ - const struct ath5k_rf_reg *rf_regs; - u32 step, mix_ovr, level[4]; - u32 *rf; - - if (ah->ah_rf_banks == NULL) - return false; - - rf = ah->ah_rf_banks; - - if (ah->ah_radio == AR5K_RF5111) { - - rf_regs = rf_regs_5111; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); - - step = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_RFGAIN_STEP, - false); - - level[0] = 0; - level[1] = (step == 63) ? 50 : step + 4; - level[2] = (step != 63) ? 64 : level[0]; - level[3] = level[2] + 50 ; - - ah->ah_gain.g_high = level[3] - - (step == 63 ? AR5K_GAIN_DYN_ADJUST_HI_MARGIN : -5); - ah->ah_gain.g_low = level[0] + - (step == 63 ? AR5K_GAIN_DYN_ADJUST_LO_MARGIN : 0); - } else { - - rf_regs = rf_regs_5112; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); - - mix_ovr = ath5k_hw_rfb_op(ah, rf_regs, 0, AR5K_RF_MIXVGA_OVR, - false); - - level[0] = level[2] = 0; - - if (mix_ovr == 1) { - level[1] = level[3] = 83; - } else { - level[1] = level[3] = 107; - ah->ah_gain.g_high = 55; - } - } - - return (ah->ah_gain.g_current >= level[0] && - ah->ah_gain.g_current <= level[1]) || - (ah->ah_gain.g_current >= level[2] && - ah->ah_gain.g_current <= level[3]); -} - -/* Perform gain_F adjustment by choosing the right set - * of parameters from rf gain optimization ladder */ -static s8 ath5k_hw_rf_gainf_adjust(struct ath5k_hw *ah) -{ - const struct ath5k_gain_opt *go; - const struct ath5k_gain_opt_step *g_step; - int ret = 0; - - switch (ah->ah_radio) { - case AR5K_RF5111: - go = &rfgain_opt_5111; - break; - case AR5K_RF5112: - go = &rfgain_opt_5112; - break; - default: - return 0; - } - - g_step = &go->go_step[ah->ah_gain.g_step_idx]; - - if (ah->ah_gain.g_current >= ah->ah_gain.g_high) { - - /* Reached maximum */ - if (ah->ah_gain.g_step_idx == 0) - return -1; - - for (ah->ah_gain.g_target = ah->ah_gain.g_current; - ah->ah_gain.g_target >= ah->ah_gain.g_high && - ah->ah_gain.g_step_idx > 0; - g_step = &go->go_step[ah->ah_gain.g_step_idx]) - ah->ah_gain.g_target -= 2 * - (go->go_step[--(ah->ah_gain.g_step_idx)].gos_gain - - g_step->gos_gain); - - ret = 1; - goto done; - } - - if (ah->ah_gain.g_current <= ah->ah_gain.g_low) { - - /* Reached minimum */ - if (ah->ah_gain.g_step_idx == (go->go_steps_count - 1)) - return -2; - - for (ah->ah_gain.g_target = ah->ah_gain.g_current; - ah->ah_gain.g_target <= ah->ah_gain.g_low && - ah->ah_gain.g_step_idx < go->go_steps_count-1; - g_step = &go->go_step[ah->ah_gain.g_step_idx]) - ah->ah_gain.g_target -= 2 * - (go->go_step[++ah->ah_gain.g_step_idx].gos_gain - - g_step->gos_gain); - - ret = 2; - goto done; - } - -done: - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, - "ret %d, gain step %u, current gain %u, target gain %u\n", - ret, ah->ah_gain.g_step_idx, ah->ah_gain.g_current, - ah->ah_gain.g_target); - - return ret; -} - -/* Main callback for thermal rf gain calibration engine - * Check for a new gain reading and schedule an adjustment - * if needed. - * - * TODO: Use sw interrupt to schedule reset if gain_F needs - * adjustment */ -enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah) -{ - u32 data, type; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_rf_banks == NULL || - ah->ah_gain.g_state == AR5K_RFGAIN_INACTIVE) - return AR5K_RFGAIN_INACTIVE; - - /* No check requested, either engine is inactive - * or an adjustment is already requested */ - if (ah->ah_gain.g_state != AR5K_RFGAIN_READ_REQUESTED) - goto done; - - /* Read the PAPD (Peak to Average Power Detector) - * register */ - data = ath5k_hw_reg_read(ah, AR5K_PHY_PAPD_PROBE); - - /* No probe is scheduled, read gain_F measurement */ - if (!(data & AR5K_PHY_PAPD_PROBE_TX_NEXT)) { - ah->ah_gain.g_current = data >> AR5K_PHY_PAPD_PROBE_GAINF_S; - type = AR5K_REG_MS(data, AR5K_PHY_PAPD_PROBE_TYPE); - - /* If tx packet is CCK correct the gain_F measurement - * by cck ofdm gain delta */ - if (type == AR5K_PHY_PAPD_PROBE_TYPE_CCK) { - if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) - ah->ah_gain.g_current += - ee->ee_cck_ofdm_gain_delta; - else - ah->ah_gain.g_current += - AR5K_GAIN_CCK_PROBE_CORR; - } - - /* Further correct gain_F measurement for - * RF5112A radios */ - if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { - ath5k_hw_rf_gainf_corr(ah); - ah->ah_gain.g_current = - ah->ah_gain.g_current >= ah->ah_gain.g_f_corr ? - (ah->ah_gain.g_current-ah->ah_gain.g_f_corr) : - 0; - } - - /* Check if measurement is ok and if we need - * to adjust gain, schedule a gain adjustment, - * else switch back to the acive state */ - if (ath5k_hw_rf_check_gainf_readback(ah) && - AR5K_GAIN_CHECK_ADJUST(&ah->ah_gain) && - ath5k_hw_rf_gainf_adjust(ah)) { - ah->ah_gain.g_state = AR5K_RFGAIN_NEED_CHANGE; - } else { - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - } - } - -done: - return ah->ah_gain.g_state; -} - -/* Write initial rf gain table to set the RF sensitivity - * this one works on all RF chips and has nothing to do - * with gain_F calibration */ -int ath5k_hw_rfgain_init(struct ath5k_hw *ah, unsigned int freq) -{ - const struct ath5k_ini_rfgain *ath5k_rfg; - unsigned int i, size; - - switch (ah->ah_radio) { - case AR5K_RF5111: - ath5k_rfg = rfgain_5111; - size = ARRAY_SIZE(rfgain_5111); - break; - case AR5K_RF5112: - ath5k_rfg = rfgain_5112; - size = ARRAY_SIZE(rfgain_5112); - break; - case AR5K_RF2413: - ath5k_rfg = rfgain_2413; - size = ARRAY_SIZE(rfgain_2413); - break; - case AR5K_RF2316: - ath5k_rfg = rfgain_2316; - size = ARRAY_SIZE(rfgain_2316); - break; - case AR5K_RF5413: - ath5k_rfg = rfgain_5413; - size = ARRAY_SIZE(rfgain_5413); - break; - case AR5K_RF2317: - case AR5K_RF2425: - ath5k_rfg = rfgain_2425; - size = ARRAY_SIZE(rfgain_2425); - break; - default: - return -EINVAL; - } - - switch (freq) { - case AR5K_INI_RFGAIN_2GHZ: - case AR5K_INI_RFGAIN_5GHZ: - break; - default: - return -EINVAL; - } - - for (i = 0; i < size; i++) { - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, ath5k_rfg[i].rfg_value[freq], - (u32)ath5k_rfg[i].rfg_register); - } - - return 0; -} - - - -/********************\ -* RF Registers setup * -\********************/ - - -/* - * Setup RF registers by writing rf buffer on hw - */ -int ath5k_hw_rfregs_init(struct ath5k_hw *ah, struct ieee80211_channel *channel, - unsigned int mode) -{ - const struct ath5k_rf_reg *rf_regs; - const struct ath5k_ini_rfbuffer *ini_rfb; - const struct ath5k_gain_opt *go = NULL; - const struct ath5k_gain_opt_step *g_step; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u8 ee_mode = 0; - u32 *rfb; - int i, obdb = -1, bank = -1; - - switch (ah->ah_radio) { - case AR5K_RF5111: - rf_regs = rf_regs_5111; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5111); - ini_rfb = rfb_5111; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5111); - go = &rfgain_opt_5111; - break; - case AR5K_RF5112: - if (ah->ah_radio_5ghz_revision >= AR5K_SREV_RAD_5112A) { - rf_regs = rf_regs_5112a; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112a); - ini_rfb = rfb_5112a; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112a); - } else { - rf_regs = rf_regs_5112; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5112); - ini_rfb = rfb_5112; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5112); - } - go = &rfgain_opt_5112; - break; - case AR5K_RF2413: - rf_regs = rf_regs_2413; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2413); - ini_rfb = rfb_2413; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2413); - break; - case AR5K_RF2316: - rf_regs = rf_regs_2316; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2316); - ini_rfb = rfb_2316; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2316); - break; - case AR5K_RF5413: - rf_regs = rf_regs_5413; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_5413); - ini_rfb = rfb_5413; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_5413); - break; - case AR5K_RF2317: - rf_regs = rf_regs_2425; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); - ini_rfb = rfb_2317; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2317); - break; - case AR5K_RF2425: - rf_regs = rf_regs_2425; - ah->ah_rf_regs_count = ARRAY_SIZE(rf_regs_2425); - if (ah->ah_mac_srev < AR5K_SREV_AR2417) { - ini_rfb = rfb_2425; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2425); - } else { - ini_rfb = rfb_2417; - ah->ah_rf_banks_size = ARRAY_SIZE(rfb_2417); - } - break; - default: - return -EINVAL; - } - - /* If it's the first time we set rf buffer, allocate - * ah->ah_rf_banks based on ah->ah_rf_banks_size - * we set above */ - if (ah->ah_rf_banks == NULL) { - ah->ah_rf_banks = kmalloc(sizeof(u32) * ah->ah_rf_banks_size, - GFP_KERNEL); - if (ah->ah_rf_banks == NULL) { - ATH5K_ERR(ah->ah_sc, "out of memory\n"); - return -ENOMEM; - } - } - - /* Copy values to modify them */ - rfb = ah->ah_rf_banks; - - for (i = 0; i < ah->ah_rf_banks_size; i++) { - if (ini_rfb[i].rfb_bank >= AR5K_MAX_RF_BANKS) { - ATH5K_ERR(ah->ah_sc, "invalid bank\n"); - return -EINVAL; - } - - /* Bank changed, write down the offset */ - if (bank != ini_rfb[i].rfb_bank) { - bank = ini_rfb[i].rfb_bank; - ah->ah_offset[bank] = i; - } - - rfb[i] = ini_rfb[i].rfb_mode_data[mode]; - } - - /* Set Output and Driver bias current (OB/DB) */ - if (channel->hw_value & CHANNEL_2GHZ) { - - if (channel->hw_value & CHANNEL_CCK) - ee_mode = AR5K_EEPROM_MODE_11B; - else - ee_mode = AR5K_EEPROM_MODE_11G; - - /* For RF511X/RF211X combination we - * use b_OB and b_DB parameters stored - * in eeprom on ee->ee_ob[ee_mode][0] - * - * For all other chips we use OB/DB for 2Ghz - * stored in the b/g modal section just like - * 802.11a on ee->ee_ob[ee_mode][1] */ - if ((ah->ah_radio == AR5K_RF5111) || - (ah->ah_radio == AR5K_RF5112)) - obdb = 0; - else - obdb = 1; - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], - AR5K_RF_OB_2GHZ, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], - AR5K_RF_DB_2GHZ, true); - - /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */ - } else if ((channel->hw_value & CHANNEL_5GHZ) || - (ah->ah_radio == AR5K_RF5111)) { - - /* For 11a, Turbo and XR we need to choose - * OB/DB based on frequency range */ - ee_mode = AR5K_EEPROM_MODE_11A; - obdb = channel->center_freq >= 5725 ? 3 : - (channel->center_freq >= 5500 ? 2 : - (channel->center_freq >= 5260 ? 1 : - (channel->center_freq > 4000 ? 0 : -1))); - - if (obdb < 0) - return -EINVAL; - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_ob[ee_mode][obdb], - AR5K_RF_OB_5GHZ, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_db[ee_mode][obdb], - AR5K_RF_DB_5GHZ, true); - } - - g_step = &go->go_step[ah->ah_gain.g_step_idx]; - - /* Bank Modifications (chip-specific) */ - if (ah->ah_radio == AR5K_RF5111) { - - /* Set gain_F settings according to current step */ - if (channel->hw_value & CHANNEL_OFDM) { - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, - AR5K_PHY_FRAME_CTL_TX_CLIP, - g_step->gos_param[0]); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], - AR5K_RF_PWD_90, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], - AR5K_RF_PWD_84, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], - AR5K_RF_RFGAIN_SEL, true); - - /* We programmed gain_F parameters, switch back - * to active state */ - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - - } - - /* Bank 6/7 setup */ - - ath5k_hw_rfb_op(ah, rf_regs, !ee->ee_xpd[ee_mode], - AR5K_RF_PWD_XPD, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_x_gain[ee_mode], - AR5K_RF_XPD_GAIN, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], - AR5K_RF_GAIN_I, true); - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], - AR5K_RF_PLO_SEL, true); - - /* TODO: Half/quarter channel support */ - } - - if (ah->ah_radio == AR5K_RF5112) { - - /* Set gain_F settings according to current step */ - if (channel->hw_value & CHANNEL_OFDM) { - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0], - AR5K_RF_MIXGAIN_OVR, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[1], - AR5K_RF_PWD_138, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[2], - AR5K_RF_PWD_137, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[3], - AR5K_RF_PWD_136, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[4], - AR5K_RF_PWD_132, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[5], - AR5K_RF_PWD_131, true); - - ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[6], - AR5K_RF_PWD_130, true); - - /* We programmed gain_F parameters, switch back - * to active state */ - ah->ah_gain.g_state = AR5K_RFGAIN_ACTIVE; - } - - /* Bank 6/7 setup */ - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_xpd[ee_mode], - AR5K_RF_XPD_SEL, true); - - if (ah->ah_radio_5ghz_revision < AR5K_SREV_RAD_5112A) { - /* Rev. 1 supports only one xpd */ - ath5k_hw_rfb_op(ah, rf_regs, - ee->ee_x_gain[ee_mode], - AR5K_RF_XPD_GAIN, true); - - } else { - u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode]; - if (ee->ee_pd_gains[ee_mode] > 1) { - ath5k_hw_rfb_op(ah, rf_regs, - pdg_curve_to_idx[0], - AR5K_RF_PD_GAIN_LO, true); - ath5k_hw_rfb_op(ah, rf_regs, - pdg_curve_to_idx[1], - AR5K_RF_PD_GAIN_HI, true); - } else { - ath5k_hw_rfb_op(ah, rf_regs, - pdg_curve_to_idx[0], - AR5K_RF_PD_GAIN_LO, true); - ath5k_hw_rfb_op(ah, rf_regs, - pdg_curve_to_idx[0], - AR5K_RF_PD_GAIN_HI, true); - } - - /* Lower synth voltage on Rev 2 */ - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_HIGH_VC_CP, true); - - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_MID_VC_CP, true); - - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_LOW_VC_CP, true); - - ath5k_hw_rfb_op(ah, rf_regs, 2, - AR5K_RF_PUSH_UP, true); - - /* Decrease power consumption on 5213+ BaseBand */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_PAD2GND, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_XB2_LVL, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_XB5_LVL, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_PWD_167, true); - - ath5k_hw_rfb_op(ah, rf_regs, 1, - AR5K_RF_PWD_166, true); - } - } - - ath5k_hw_rfb_op(ah, rf_regs, ee->ee_i_gain[ee_mode], - AR5K_RF_GAIN_I, true); - - /* TODO: Half/quarter channel support */ - - } - - if (ah->ah_radio == AR5K_RF5413 && - channel->hw_value & CHANNEL_2GHZ) { - - ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE, - true); - - /* Set optimum value for early revisions (on pci-e chips) */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5424 && - ah->ah_mac_srev < AR5K_SREV_AR5413) - ath5k_hw_rfb_op(ah, rf_regs, ath5k_hw_bitswap(6, 3), - AR5K_RF_PWD_ICLOBUF_2G, true); - - } - - /* Write RF banks on hw */ - for (i = 0; i < ah->ah_rf_banks_size; i++) { - AR5K_REG_WAIT(i); - ath5k_hw_reg_write(ah, rfb[i], ini_rfb[i].rfb_ctrl_register); - } - - return 0; -} - - -/**************************\ - PHY/RF channel functions -\**************************/ - -/* - * Check if a channel is supported - */ -bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) -{ - /* Check if the channel is in our supported range */ - if (flags & CHANNEL_2GHZ) { - if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) - return true; - } else if (flags & CHANNEL_5GHZ) - if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && - (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) - return true; - - return false; -} - -/* - * Convertion needed for RF5110 - */ -static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel) -{ - u32 athchan; - - /* - * Convert IEEE channel/MHz to an internal channel value used - * by the AR5210 chipset. This has not been verified with - * newer chipsets like the AR5212A who have a completely - * different RF/PHY part. - */ - athchan = (ath5k_hw_bitswap( - (ieee80211_frequency_to_channel( - channel->center_freq) - 24) / 2, 5) - << 1) | (1 << 6) | 0x1; - return athchan; -} - -/* - * Set channel on RF5110 - */ -static int ath5k_hw_rf5110_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 data; - - /* - * Set the channel and wait - */ - data = ath5k_hw_rf5110_chan2athchan(channel); - ath5k_hw_reg_write(ah, data, AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, 0, AR5K_RF_BUFFER_CONTROL_0); - mdelay(1); - - return 0; -} - -/* - * Convertion needed for 5111 - */ -static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee, - struct ath5k_athchan_2ghz *athchan) -{ - int channel; - - /* Cast this value to catch negative channel numbers (>= -19) */ - channel = (int)ieee; - - /* - * Map 2GHz IEEE channel to 5GHz Atheros channel - */ - if (channel <= 13) { - athchan->a2_athchan = 115 + channel; - athchan->a2_flags = 0x46; - } else if (channel == 14) { - athchan->a2_athchan = 124; - athchan->a2_flags = 0x44; - } else if (channel >= 15 && channel <= 26) { - athchan->a2_athchan = ((channel - 14) * 4) + 132; - athchan->a2_flags = 0x46; - } else - return -EINVAL; - - return 0; -} - -/* - * Set channel on 5111 - */ -static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - struct ath5k_athchan_2ghz ath5k_channel_2ghz; - unsigned int ath5k_channel = - ieee80211_frequency_to_channel(channel->center_freq); - u32 data0, data1, clock; - int ret; - - /* - * Set the channel on the RF5111 radio - */ - data0 = data1 = 0; - - if (channel->hw_value & CHANNEL_2GHZ) { - /* Map 2GHz channel to 5GHz Atheros channel ID */ - ret = ath5k_hw_rf5111_chan2athchan( - ieee80211_frequency_to_channel(channel->center_freq), - &ath5k_channel_2ghz); - if (ret) - return ret; - - ath5k_channel = ath5k_channel_2ghz.a2_athchan; - data0 = ((ath5k_hw_bitswap(ath5k_channel_2ghz.a2_flags, 8) & 0xff) - << 5) | (1 << 4); - } - - if (ath5k_channel < 145 || !(ath5k_channel & 1)) { - clock = 1; - data1 = ((ath5k_hw_bitswap(ath5k_channel - 24, 8) & 0xff) << 2) | - (clock << 1) | (1 << 10) | 1; - } else { - clock = 0; - data1 = ((ath5k_hw_bitswap((ath5k_channel - 24) / 2, 8) & 0xff) - << 2) | (clock << 1) | (1 << 10) | 1; - } - - ath5k_hw_reg_write(ah, (data1 & 0xff) | ((data0 & 0xff) << 8), - AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, ((data1 >> 8) & 0xff) | (data0 & 0xff00), - AR5K_RF_BUFFER_CONTROL_3); - - return 0; -} - -/* - * Set channel on 5112 and newer - */ -static int ath5k_hw_rf5112_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 data, data0, data1, data2; - u16 c; - - data = data0 = data1 = data2 = 0; - c = channel->center_freq; - - if (c < 4800) { - if (!((c - 2224) % 5)) { - data0 = ((2 * (c - 704)) - 3040) / 10; - data1 = 1; - } else if (!((c - 2192) % 5)) { - data0 = ((2 * (c - 672)) - 3040) / 10; - data1 = 0; - } else - return -EINVAL; - - data0 = ath5k_hw_bitswap((data0 << 2) & 0xff, 8); - } else if ((c - (c % 5)) != 2 || c > 5435) { - if (!(c % 20) && c >= 5120) { - data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); - data2 = ath5k_hw_bitswap(3, 2); - } else if (!(c % 10)) { - data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); - data2 = ath5k_hw_bitswap(2, 2); - } else if (!(c % 5)) { - data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); - data2 = ath5k_hw_bitswap(1, 2); - } else - return -EINVAL; - } else { - data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); - data2 = ath5k_hw_bitswap(0, 2); - } - - data = (data0 << 4) | (data1 << 1) | (data2 << 2) | 0x1001; - - ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); - - return 0; -} - -/* - * Set the channel on the RF2425 - */ -static int ath5k_hw_rf2425_channel(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 data, data0, data2; - u16 c; - - data = data0 = data2 = 0; - c = channel->center_freq; - - if (c < 4800) { - data0 = ath5k_hw_bitswap((c - 2272), 8); - data2 = 0; - /* ? 5GHz ? */ - } else if ((c - (c % 5)) != 2 || c > 5435) { - if (!(c % 20) && c < 5120) - data0 = ath5k_hw_bitswap(((c - 4800) / 20 << 2), 8); - else if (!(c % 10)) - data0 = ath5k_hw_bitswap(((c - 4800) / 10 << 1), 8); - else if (!(c % 5)) - data0 = ath5k_hw_bitswap((c - 4800) / 5, 8); - else - return -EINVAL; - data2 = ath5k_hw_bitswap(1, 2); - } else { - data0 = ath5k_hw_bitswap((10 * (c - 2) - 4800) / 25 + 1, 8); - data2 = ath5k_hw_bitswap(0, 2); - } - - data = (data0 << 4) | data2 << 2 | 0x1001; - - ath5k_hw_reg_write(ah, data & 0xff, AR5K_RF_BUFFER); - ath5k_hw_reg_write(ah, (data >> 8) & 0x7f, AR5K_RF_BUFFER_CONTROL_5); - - return 0; -} - -/* - * Set a channel on the radio chip - */ -int ath5k_hw_channel(struct ath5k_hw *ah, struct ieee80211_channel *channel) -{ - int ret; - /* - * Check bounds supported by the PHY (we don't care about regultory - * restrictions at this point). Note: hw_value already has the band - * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok() - * of the band by that */ - if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) { - ATH5K_ERR(ah->ah_sc, - "channel frequency (%u MHz) out of supported " - "band range\n", - channel->center_freq); - return -EINVAL; - } - - /* - * Set the channel and wait - */ - switch (ah->ah_radio) { - case AR5K_RF5110: - ret = ath5k_hw_rf5110_channel(ah, channel); - break; - case AR5K_RF5111: - ret = ath5k_hw_rf5111_channel(ah, channel); - break; - case AR5K_RF2425: - ret = ath5k_hw_rf2425_channel(ah, channel); - break; - default: - ret = ath5k_hw_rf5112_channel(ah, channel); - break; - } - - if (ret) - return ret; - - /* Set JAPAN setting for channel 14 */ - if (channel->center_freq == 2484) { - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, - AR5K_PHY_CCKTXCTL_JAPAN); - } else { - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_CCKTXCTL, - AR5K_PHY_CCKTXCTL_WORLD); - } - - ah->ah_current_channel = channel; - ah->ah_turbo = channel->hw_value == CHANNEL_T ? true : false; - - return 0; -} - -/*****************\ - PHY calibration -\*****************/ - -void -ath5k_hw_calibration_poll(struct ath5k_hw *ah) -{ - /* Calibration interval in jiffies */ - unsigned long cal_intval; - - cal_intval = msecs_to_jiffies(ah->ah_cal_intval * 1000); - - /* Initialize timestamp if needed */ - if (!ah->ah_cal_tstamp) - ah->ah_cal_tstamp = jiffies; - - /* For now we always do full calibration - * Mark software interrupt mask and fire software - * interrupt (bit gets auto-cleared) */ - if (time_is_before_eq_jiffies(ah->ah_cal_tstamp + cal_intval)) { - ah->ah_cal_tstamp = jiffies; - ah->ah_swi_mask = AR5K_SWI_FULL_CALIBRATION; - AR5K_REG_ENABLE_BITS(ah, AR5K_CR, AR5K_CR_SWI); - } - -} - -/** - * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration - * - * @ah: struct ath5k_hw pointer we are operating on - * @freq: the channel frequency, just used for error logging - * - * This function performs a noise floor calibration of the PHY and waits for - * it to complete. Then the noise floor value is compared to some maximum - * noise floor we consider valid. - * - * Note that this is different from what the madwifi HAL does: it reads the - * noise floor and afterwards initiates the calibration. Since the noise floor - * calibration can take some time to finish, depending on the current channel - * use, that avoids the occasional timeout warnings we are seeing now. - * - * See the following link for an Atheros patent on noise floor calibration: - * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \ - * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7 - * - * XXX: Since during noise floor calibration antennas are detached according to - * the patent, we should stop tx queues here. - */ -int -ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq) -{ - int ret; - unsigned int i; - s32 noise_floor; - - /* - * Enable noise floor calibration - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_NF); - - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_NF, 0, false); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "noise floor calibration timeout (%uMHz)\n", freq); - return -EAGAIN; - } - - /* Wait until the noise floor is calibrated and read the value */ - for (i = 20; i > 0; i--) { - mdelay(1); - noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF); - noise_floor = AR5K_PHY_NF_RVAL(noise_floor); - if (noise_floor & AR5K_PHY_NF_ACTIVE) { - noise_floor = AR5K_PHY_NF_AVAL(noise_floor); - - if (noise_floor <= AR5K_TUNE_NOISE_FLOOR) - break; - } - } - - ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE, - "noise floor %d\n", noise_floor); - - if (noise_floor > AR5K_TUNE_NOISE_FLOOR) { - ATH5K_ERR(ah->ah_sc, - "noise floor calibration failed (%uMHz)\n", freq); - return -EAGAIN; - } - - ah->ah_noise_floor = noise_floor; - - return 0; -} - -/* - * Perform a PHY calibration on RF5110 - * -Fix BPSK/QAM Constellation (I/Q correction) - * -Calculate Noise Floor - */ -static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 phy_sig, phy_agc, phy_sat, beacon; - int ret; - - /* - * Disable beacons and RX/TX queues, wait - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); - beacon = ath5k_hw_reg_read(ah, AR5K_BEACON_5210); - ath5k_hw_reg_write(ah, beacon & ~AR5K_BEACON_ENABLE, AR5K_BEACON_5210); - - mdelay(2); - - /* - * Set the channel (with AGC turned off) - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - udelay(10); - ret = ath5k_hw_channel(ah, channel); - - /* - * Activate PHY and wait - */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - mdelay(1); - - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - - if (ret) - return ret; - - /* - * Calibrate the radio chip - */ - - /* Remember normal state */ - phy_sig = ath5k_hw_reg_read(ah, AR5K_PHY_SIG); - phy_agc = ath5k_hw_reg_read(ah, AR5K_PHY_AGCCOARSE); - phy_sat = ath5k_hw_reg_read(ah, AR5K_PHY_ADCSAT); - - /* Update radio registers */ - ath5k_hw_reg_write(ah, (phy_sig & ~(AR5K_PHY_SIG_FIRPWR)) | - AR5K_REG_SM(-1, AR5K_PHY_SIG_FIRPWR), AR5K_PHY_SIG); - - ath5k_hw_reg_write(ah, (phy_agc & ~(AR5K_PHY_AGCCOARSE_HI | - AR5K_PHY_AGCCOARSE_LO)) | - AR5K_REG_SM(-1, AR5K_PHY_AGCCOARSE_HI) | - AR5K_REG_SM(-127, AR5K_PHY_AGCCOARSE_LO), AR5K_PHY_AGCCOARSE); - - ath5k_hw_reg_write(ah, (phy_sat & ~(AR5K_PHY_ADCSAT_ICNT | - AR5K_PHY_ADCSAT_THR)) | - AR5K_REG_SM(2, AR5K_PHY_ADCSAT_ICNT) | - AR5K_REG_SM(12, AR5K_PHY_ADCSAT_THR), AR5K_PHY_ADCSAT); - - udelay(20); - - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - udelay(10); - ath5k_hw_reg_write(ah, AR5K_PHY_RFSTG_DISABLE, AR5K_PHY_RFSTG); - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGC, AR5K_PHY_AGC_DISABLE); - - mdelay(1); - - /* - * Enable calibration and wait until completion - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_CAL); - - ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false); - - /* Reset to normal state */ - ath5k_hw_reg_write(ah, phy_sig, AR5K_PHY_SIG); - ath5k_hw_reg_write(ah, phy_agc, AR5K_PHY_AGCCOARSE); - ath5k_hw_reg_write(ah, phy_sat, AR5K_PHY_ADCSAT); - - if (ret) { - ATH5K_ERR(ah->ah_sc, "calibration timeout (%uMHz)\n", - channel->center_freq); - return ret; - } - - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - - /* - * Re-enable RX/TX and beacons - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW_5210, - AR5K_DIAG_SW_DIS_TX | AR5K_DIAG_SW_DIS_RX_5210); - ath5k_hw_reg_write(ah, beacon, AR5K_BEACON_5210); - - return 0; -} - -/* - * Perform a PHY calibration on RF5111/5112 and newer chips - */ -static int ath5k_hw_rf511x_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u32 i_pwr, q_pwr; - s32 iq_corr, i_coff, i_coffd, q_coff, q_coffd; - int i; - ATH5K_TRACE(ah->ah_sc); - - if (!ah->ah_calibration || - ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & AR5K_PHY_IQ_RUN) - goto done; - - /* Calibration has finished, get the results and re-run */ - for (i = 0; i <= 10; i++) { - iq_corr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_CORR); - i_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_I); - q_pwr = ath5k_hw_reg_read(ah, AR5K_PHY_IQRES_CAL_PWR_Q); - } - - i_coffd = ((i_pwr >> 1) + (q_pwr >> 1)) >> 7; - q_coffd = q_pwr >> 7; - - /* No correction */ - if (i_coffd == 0 || q_coffd == 0) - goto done; - - i_coff = ((-iq_corr) / i_coffd) & 0x3f; - - /* Boundary check */ - if (i_coff > 31) - i_coff = 31; - if (i_coff < -32) - i_coff = -32; - - q_coff = (((s32)i_pwr / q_coffd) - 128) & 0x1f; - - /* Boundary check */ - if (q_coff > 15) - q_coff = 15; - if (q_coff < -16) - q_coff = -16; - - /* Commit new I/Q value */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_CORR_ENABLE | - ((u32)q_coff) | ((u32)i_coff << AR5K_PHY_IQ_CORR_Q_I_COFF_S)); - - /* Re-enable calibration -if we don't we'll commit - * the same values again and again */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, AR5K_PHY_IQ_RUN); - -done: - - /* TODO: Separate noise floor calibration from I/Q calibration - * since noise floor calibration interrupts rx path while I/Q - * calibration doesn't. We don't need to run noise floor calibration - * as often as I/Q calibration.*/ - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - - /* Initiate a gain_F calibration */ - ath5k_hw_request_rfgain_probe(ah); - - return 0; -} - -/* - * Perform a PHY calibration - */ -int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - int ret; - - if (ah->ah_radio == AR5K_RF5110) - ret = ath5k_hw_rf5110_calibrate(ah, channel); - else - ret = ath5k_hw_rf511x_calibrate(ah, channel); - - return ret; -} - -/***************************\ -* Spur mitigation functions * -\***************************/ - -bool ath5k_hw_chan_has_spur_noise(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - u8 refclk_freq; - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - refclk_freq = 40; - else - refclk_freq = 32; - - if ((channel->center_freq % refclk_freq != 0) && - ((channel->center_freq % refclk_freq < 10) || - (channel->center_freq % refclk_freq > 22))) - return true; - else - return false; -} - -void -ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 mag_mask[4] = {0, 0, 0, 0}; - u32 pilot_mask[2] = {0, 0}; - /* Note: fbin values are scaled up by 2 */ - u16 spur_chan_fbin, chan_fbin, symbol_width, spur_detection_window; - s32 spur_delta_phase, spur_freq_sigma_delta; - s32 spur_offset, num_symbols_x16; - u8 num_symbol_offsets, i, freq_band; - - /* Convert current frequency to fbin value (the same way channels - * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale - * up by 2 so we can compare it later */ - if (channel->hw_value & CHANNEL_2GHZ) { - chan_fbin = (channel->center_freq - 2300) * 10; - freq_band = AR5K_EEPROM_BAND_2GHZ; - } else { - chan_fbin = (channel->center_freq - 4900) * 10; - freq_band = AR5K_EEPROM_BAND_5GHZ; - } - - /* Check if any spur_chan_fbin from EEPROM is - * within our current channel's spur detection range */ - spur_chan_fbin = AR5K_EEPROM_NO_SPUR; - spur_detection_window = AR5K_SPUR_CHAN_WIDTH; - /* XXX: Half/Quarter channels ?*/ - if (channel->hw_value & CHANNEL_TURBO) - spur_detection_window *= 2; - - for (i = 0; i < AR5K_EEPROM_N_SPUR_CHANS; i++) { - spur_chan_fbin = ee->ee_spur_chans[i][freq_band]; - - /* Note: mask cleans AR5K_EEPROM_NO_SPUR flag - * so it's zero if we got nothing from EEPROM */ - if (spur_chan_fbin == AR5K_EEPROM_NO_SPUR) { - spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; - break; - } - - if ((chan_fbin - spur_detection_window <= - (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK)) && - (chan_fbin + spur_detection_window >= - (spur_chan_fbin & AR5K_EEPROM_SPUR_CHAN_MASK))) { - spur_chan_fbin &= AR5K_EEPROM_SPUR_CHAN_MASK; - break; - } - } - - /* We need to enable spur filter for this channel */ - if (spur_chan_fbin) { - spur_offset = spur_chan_fbin - chan_fbin; - /* - * Calculate deltas: - * spur_freq_sigma_delta -> spur_offset / sample_freq << 21 - * spur_delta_phase -> spur_offset / chip_freq << 11 - * Note: Both values have 100KHz resolution - */ - /* XXX: Half/Quarter rate channels ? */ - switch (channel->hw_value) { - case CHANNEL_A: - /* Both sample_freq and chip_freq are 40MHz */ - spur_delta_phase = (spur_offset << 17) / 25; - spur_freq_sigma_delta = (spur_delta_phase >> 10); - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; - break; - case CHANNEL_G: - /* sample_freq -> 40MHz chip_freq -> 44MHz - * (for b compatibility) */ - spur_freq_sigma_delta = (spur_offset << 8) / 55; - spur_delta_phase = (spur_offset << 17) / 25; - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz; - break; - case CHANNEL_T: - case CHANNEL_TG: - /* Both sample_freq and chip_freq are 80MHz */ - spur_delta_phase = (spur_offset << 16) / 25; - spur_freq_sigma_delta = (spur_delta_phase >> 10); - symbol_width = AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz; - break; - default: - return; - } - - /* Calculate pilot and magnitude masks */ - - /* Scale up spur_offset by 1000 to switch to 100HZ resolution - * and divide by symbol_width to find how many symbols we have - * Note: number of symbols is scaled up by 16 */ - num_symbols_x16 = ((spur_offset * 1000) << 4) / symbol_width; - - /* Spur is on a symbol if num_symbols_x16 % 16 is zero */ - if (!(num_symbols_x16 & 0xF)) - /* _X_ */ - num_symbol_offsets = 3; - else - /* _xx_ */ - num_symbol_offsets = 4; - - for (i = 0; i < num_symbol_offsets; i++) { - - /* Calculate pilot mask */ - s32 curr_sym_off = - (num_symbols_x16 / 16) + i + 25; - - /* Pilot magnitude mask seems to be a way to - * declare the boundaries for our detection - * window or something, it's 2 for the middle - * value(s) where the symbol is expected to be - * and 1 on the boundary values */ - u8 plt_mag_map = - (i == 0 || i == (num_symbol_offsets - 1)) - ? 1 : 2; - - if (curr_sym_off >= 0 && curr_sym_off <= 32) { - if (curr_sym_off <= 25) - pilot_mask[0] |= 1 << curr_sym_off; - else if (curr_sym_off >= 27) - pilot_mask[0] |= 1 << (curr_sym_off - 1); - } else if (curr_sym_off >= 33 && curr_sym_off <= 52) - pilot_mask[1] |= 1 << (curr_sym_off - 33); - - /* Calculate magnitude mask (for viterbi decoder) */ - if (curr_sym_off >= -1 && curr_sym_off <= 14) - mag_mask[0] |= - plt_mag_map << (curr_sym_off + 1) * 2; - else if (curr_sym_off >= 15 && curr_sym_off <= 30) - mag_mask[1] |= - plt_mag_map << (curr_sym_off - 15) * 2; - else if (curr_sym_off >= 31 && curr_sym_off <= 46) - mag_mask[2] |= - plt_mag_map << (curr_sym_off - 31) * 2; - else if (curr_sym_off >= 46 && curr_sym_off <= 53) - mag_mask[3] |= - plt_mag_map << (curr_sym_off - 47) * 2; - - } - - /* Write settings on hw to enable spur filter */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, - AR5K_PHY_BIN_MASK_CTL_RATE, 0xff); - /* XXX: Self correlator also ? */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_PILOT_MASK_EN | - AR5K_PHY_IQ_CHAN_MASK_EN | - AR5K_PHY_IQ_SPUR_FILT_EN); - - /* Set delta phase and freq sigma delta */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(spur_delta_phase, - AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE) | - AR5K_REG_SM(spur_freq_sigma_delta, - AR5K_PHY_TIMING_11_SPUR_FREQ_SD) | - AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC, - AR5K_PHY_TIMING_11); - - /* Write pilot masks */ - ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_7); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, - AR5K_PHY_TIMING_8_PILOT_MASK_2, - pilot_mask[1]); - - ath5k_hw_reg_write(ah, pilot_mask[0], AR5K_PHY_TIMING_9); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, - AR5K_PHY_TIMING_10_PILOT_MASK_2, - pilot_mask[1]); - - /* Write magnitude masks */ - ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK_1); - ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK_2); - ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK_3); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, - AR5K_PHY_BIN_MASK_CTL_MASK_4, - mag_mask[3]); - - ath5k_hw_reg_write(ah, mag_mask[0], AR5K_PHY_BIN_MASK2_1); - ath5k_hw_reg_write(ah, mag_mask[1], AR5K_PHY_BIN_MASK2_2); - ath5k_hw_reg_write(ah, mag_mask[2], AR5K_PHY_BIN_MASK2_3); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, - AR5K_PHY_BIN_MASK2_4_MASK_4, - mag_mask[3]); - - } else if (ath5k_hw_reg_read(ah, AR5K_PHY_IQ) & - AR5K_PHY_IQ_SPUR_FILT_EN) { - /* Clean up spur mitigation settings and disable fliter */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, - AR5K_PHY_BIN_MASK_CTL_RATE, 0); - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_PILOT_MASK_EN | - AR5K_PHY_IQ_CHAN_MASK_EN | - AR5K_PHY_IQ_SPUR_FILT_EN); - ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_11); - - /* Clear pilot masks */ - ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_7); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_8, - AR5K_PHY_TIMING_8_PILOT_MASK_2, - 0); - - ath5k_hw_reg_write(ah, 0, AR5K_PHY_TIMING_9); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_10, - AR5K_PHY_TIMING_10_PILOT_MASK_2, - 0); - - /* Clear magnitude masks */ - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_1); - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_2); - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK_3); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK_CTL, - AR5K_PHY_BIN_MASK_CTL_MASK_4, - 0); - - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_1); - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_2); - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BIN_MASK2_3); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_BIN_MASK2_4, - AR5K_PHY_BIN_MASK2_4_MASK_4, - 0); - } -} - -/********************\ - Misc PHY functions -\********************/ - -int ath5k_hw_phy_disable(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - /*Just a try M.F.*/ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - - return 0; -} - -/* - * Get the PHY Chip revision - */ -u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) -{ - unsigned int i; - u32 srev; - u16 ret; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Set the radio chip access register - */ - switch (chan) { - case CHANNEL_2GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); - break; - case CHANNEL_5GHZ: - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - break; - default: - return 0; - } - - mdelay(2); - - /* ...wait until PHY is ready and read the selected radio revision */ - ath5k_hw_reg_write(ah, 0x00001c16, AR5K_PHY(0x34)); - - for (i = 0; i < 8; i++) - ath5k_hw_reg_write(ah, 0x00010000, AR5K_PHY(0x20)); - - if (ah->ah_version == AR5K_AR5210) { - srev = ath5k_hw_reg_read(ah, AR5K_PHY(256) >> 28) & 0xf; - ret = (u16)ath5k_hw_bitswap(srev, 4) + 1; - } else { - srev = (ath5k_hw_reg_read(ah, AR5K_PHY(0x100)) >> 24) & 0xff; - ret = (u16)ath5k_hw_bitswap(((srev & 0xf0) >> 4) | - ((srev & 0x0f) << 4), 8); - } - - /* Reset to the 5GHz mode */ - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - - return ret; -} - -/*****************\ -* Antenna control * -\*****************/ - -void /*TODO:Boundary check*/ -ath5k_hw_set_def_antenna(struct ath5k_hw *ah, u8 ant) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, ant & 0x7, AR5K_DEFAULT_ANTENNA); -} - -unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - - if (ah->ah_version != AR5K_AR5210) - return ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA) & 0x7; - - return false; /*XXX: What do we return for 5210 ?*/ -} - -/* - * Enable/disable fast rx antenna diversity - */ -static void -ath5k_hw_set_fast_div(struct ath5k_hw *ah, u8 ee_mode, bool enable) -{ - switch (ee_mode) { - case AR5K_EEPROM_MODE_11G: - /* XXX: This is set to - * disabled on initvals !!! */ - case AR5K_EEPROM_MODE_11A: - if (enable) - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_OFDM_DIV_DIS); - else - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_OFDM_DIV_DIS); - break; - case AR5K_EEPROM_MODE_11B: - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_OFDM_DIV_DIS); - break; - default: - return; - } - - if (enable) { - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, - AR5K_PHY_RESTART_DIV_GC, 0xc); - - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, - AR5K_PHY_FAST_ANT_DIV_EN); - } else { - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RESTART, - AR5K_PHY_RESTART_DIV_GC, 0x8); - - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_FAST_ANT_DIV, - AR5K_PHY_FAST_ANT_DIV_EN); - } -} - -/* - * Set antenna operating mode - */ -void -ath5k_hw_set_antenna_mode(struct ath5k_hw *ah, u8 ant_mode) -{ - struct ieee80211_channel *channel = ah->ah_current_channel; - bool use_def_for_tx, update_def_on_tx, use_def_for_rts, fast_div; - bool use_def_for_sg; - u8 def_ant, tx_ant, ee_mode; - u32 sta_id1 = 0; - - def_ant = ah->ah_def_ant; - - ATH5K_TRACE(ah->ah_sc); - - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - case CHANNEL_T: - case CHANNEL_XR: - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - case CHANNEL_TG: - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - ee_mode = AR5K_EEPROM_MODE_11B; - break; - default: - ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); - return; - } - - switch (ant_mode) { - case AR5K_ANTMODE_DEFAULT: - tx_ant = 0; - use_def_for_tx = false; - update_def_on_tx = false; - use_def_for_rts = false; - use_def_for_sg = false; - fast_div = true; - break; - case AR5K_ANTMODE_FIXED_A: - def_ant = 1; - tx_ant = 0; - use_def_for_tx = true; - update_def_on_tx = false; - use_def_for_rts = true; - use_def_for_sg = true; - fast_div = false; - break; - case AR5K_ANTMODE_FIXED_B: - def_ant = 2; - tx_ant = 0; - use_def_for_tx = true; - update_def_on_tx = false; - use_def_for_rts = true; - use_def_for_sg = true; - fast_div = false; - break; - case AR5K_ANTMODE_SINGLE_AP: - def_ant = 1; /* updated on tx */ - tx_ant = 0; - use_def_for_tx = true; - update_def_on_tx = true; - use_def_for_rts = true; - use_def_for_sg = true; - fast_div = true; - break; - case AR5K_ANTMODE_SECTOR_AP: - tx_ant = 1; /* variable */ - use_def_for_tx = false; - update_def_on_tx = false; - use_def_for_rts = true; - use_def_for_sg = false; - fast_div = false; - break; - case AR5K_ANTMODE_SECTOR_STA: - tx_ant = 1; /* variable */ - use_def_for_tx = true; - update_def_on_tx = false; - use_def_for_rts = true; - use_def_for_sg = false; - fast_div = true; - break; - case AR5K_ANTMODE_DEBUG: - def_ant = 1; - tx_ant = 2; - use_def_for_tx = false; - update_def_on_tx = false; - use_def_for_rts = false; - use_def_for_sg = false; - fast_div = false; - break; - default: - return; - } - - ah->ah_tx_ant = tx_ant; - ah->ah_ant_mode = ant_mode; - - sta_id1 |= use_def_for_tx ? AR5K_STA_ID1_DEFAULT_ANTENNA : 0; - sta_id1 |= update_def_on_tx ? AR5K_STA_ID1_DESC_ANTENNA : 0; - sta_id1 |= use_def_for_rts ? AR5K_STA_ID1_RTS_DEF_ANTENNA : 0; - sta_id1 |= use_def_for_sg ? AR5K_STA_ID1_SELFGEN_DEF_ANT : 0; - - AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_ANTENNA_SETTINGS); - - if (sta_id1) - AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, sta_id1); - - /* Note: set diversity before default antenna - * because it won't work correctly */ - ath5k_hw_set_fast_div(ah, ee_mode, fast_div); - ath5k_hw_set_def_antenna(ah, def_ant); -} - - -/****************\ -* TX power setup * -\****************/ - -/* - * Helper functions - */ - -/* - * Do linear interpolation between two given (x, y) points - */ -static s16 -ath5k_get_interpolated_value(s16 target, s16 x_left, s16 x_right, - s16 y_left, s16 y_right) -{ - s16 ratio, result; - - /* Avoid divide by zero and skip interpolation - * if we have the same point */ - if ((x_left == x_right) || (y_left == y_right)) - return y_left; - - /* - * Since we use ints and not fps, we need to scale up in - * order to get a sane ratio value (or else we 'll eg. get - * always 1 instead of 1.25, 1.75 etc). We scale up by 100 - * to have some accuracy both for 0.5 and 0.25 steps. - */ - ratio = ((100 * y_right - 100 * y_left)/(x_right - x_left)); - - /* Now scale down to be in range */ - result = y_left + (ratio * (target - x_left) / 100); - - return result; -} - -/* - * Find vertical boundary (min pwr) for the linear PCDAC curve. - * - * Since we have the top of the curve and we draw the line below - * until we reach 1 (1 pcdac step) we need to know which point - * (x value) that is so that we don't go below y axis and have negative - * pcdac values when creating the curve, or fill the table with zeroes. - */ -static s16 -ath5k_get_linear_pcdac_min(const u8 *stepL, const u8 *stepR, - const s16 *pwrL, const s16 *pwrR) -{ - s8 tmp; - s16 min_pwrL, min_pwrR; - s16 pwr_i; - - /* Some vendors write the same pcdac value twice !!! */ - if (stepL[0] == stepL[1] || stepR[0] == stepR[1]) - return max(pwrL[0], pwrR[0]); - - if (pwrL[0] == pwrL[1]) - min_pwrL = pwrL[0]; - else { - pwr_i = pwrL[0]; - do { - pwr_i--; - tmp = (s8) ath5k_get_interpolated_value(pwr_i, - pwrL[0], pwrL[1], - stepL[0], stepL[1]); - } while (tmp > 1); - - min_pwrL = pwr_i; - } - - if (pwrR[0] == pwrR[1]) - min_pwrR = pwrR[0]; - else { - pwr_i = pwrR[0]; - do { - pwr_i--; - tmp = (s8) ath5k_get_interpolated_value(pwr_i, - pwrR[0], pwrR[1], - stepR[0], stepR[1]); - } while (tmp > 1); - - min_pwrR = pwr_i; - } - - /* Keep the right boundary so that it works for both curves */ - return max(min_pwrL, min_pwrR); -} - -/* - * Interpolate (pwr,vpd) points to create a Power to PDADC or a - * Power to PCDAC curve. - * - * Each curve has power on x axis (in 0.5dB units) and PCDAC/PDADC - * steps (offsets) on y axis. Power can go up to 31.5dB and max - * PCDAC/PDADC step for each curve is 64 but we can write more than - * one curves on hw so we can go up to 128 (which is the max step we - * can write on the final table). - * - * We write y values (PCDAC/PDADC steps) on hw. - */ -static void -ath5k_create_power_curve(s16 pmin, s16 pmax, - const s16 *pwr, const u8 *vpd, - u8 num_points, - u8 *vpd_table, u8 type) -{ - u8 idx[2] = { 0, 1 }; - s16 pwr_i = 2*pmin; - int i; - - if (num_points < 2) - return; - - /* We want the whole line, so adjust boundaries - * to cover the entire power range. Note that - * power values are already 0.25dB so no need - * to multiply pwr_i by 2 */ - if (type == AR5K_PWRTABLE_LINEAR_PCDAC) { - pwr_i = pmin; - pmin = 0; - pmax = 63; - } - - /* Find surrounding turning points (TPs) - * and interpolate between them */ - for (i = 0; (i <= (u16) (pmax - pmin)) && - (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { - - /* We passed the right TP, move to the next set of TPs - * if we pass the last TP, extrapolate above using the last - * two TPs for ratio */ - if ((pwr_i > pwr[idx[1]]) && (idx[1] < num_points - 1)) { - idx[0]++; - idx[1]++; - } - - vpd_table[i] = (u8) ath5k_get_interpolated_value(pwr_i, - pwr[idx[0]], pwr[idx[1]], - vpd[idx[0]], vpd[idx[1]]); - - /* Increase by 0.5dB - * (0.25 dB units) */ - pwr_i += 2; - } -} - -/* - * Get the surrounding per-channel power calibration piers - * for a given frequency so that we can interpolate between - * them and come up with an apropriate dataset for our current - * channel. - */ -static void -ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - struct ath5k_chan_pcal_info **pcinfo_l, - struct ath5k_chan_pcal_info **pcinfo_r) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_chan_pcal_info *pcinfo; - u8 idx_l, idx_r; - u8 mode, max, i; - u32 target = channel->center_freq; - - idx_l = 0; - idx_r = 0; - - if (!(channel->hw_value & CHANNEL_OFDM)) { - pcinfo = ee->ee_pwr_cal_b; - mode = AR5K_EEPROM_MODE_11B; - } else if (channel->hw_value & CHANNEL_2GHZ) { - pcinfo = ee->ee_pwr_cal_g; - mode = AR5K_EEPROM_MODE_11G; - } else { - pcinfo = ee->ee_pwr_cal_a; - mode = AR5K_EEPROM_MODE_11A; - } - max = ee->ee_n_piers[mode] - 1; - - /* Frequency is below our calibrated - * range. Use the lowest power curve - * we have */ - if (target < pcinfo[0].freq) { - idx_l = idx_r = 0; - goto done; - } - - /* Frequency is above our calibrated - * range. Use the highest power curve - * we have */ - if (target > pcinfo[max].freq) { - idx_l = idx_r = max; - goto done; - } - - /* Frequency is inside our calibrated - * channel range. Pick the surrounding - * calibration piers so that we can - * interpolate */ - for (i = 0; i <= max; i++) { - - /* Frequency matches one of our calibration - * piers, no need to interpolate, just use - * that calibration pier */ - if (pcinfo[i].freq == target) { - idx_l = idx_r = i; - goto done; - } - - /* We found a calibration pier that's above - * frequency, use this pier and the previous - * one to interpolate */ - if (target < pcinfo[i].freq) { - idx_r = i; - idx_l = idx_r - 1; - goto done; - } - } - -done: - *pcinfo_l = &pcinfo[idx_l]; - *pcinfo_r = &pcinfo[idx_r]; - - return; -} - -/* - * Get the surrounding per-rate power calibration data - * for a given frequency and interpolate between power - * values to set max target power supported by hw for - * each rate. - */ -static void -ath5k_get_rate_pcal_data(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - struct ath5k_rate_pcal_info *rates) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_rate_pcal_info *rpinfo; - u8 idx_l, idx_r; - u8 mode, max, i; - u32 target = channel->center_freq; - - idx_l = 0; - idx_r = 0; - - if (!(channel->hw_value & CHANNEL_OFDM)) { - rpinfo = ee->ee_rate_tpwr_b; - mode = AR5K_EEPROM_MODE_11B; - } else if (channel->hw_value & CHANNEL_2GHZ) { - rpinfo = ee->ee_rate_tpwr_g; - mode = AR5K_EEPROM_MODE_11G; - } else { - rpinfo = ee->ee_rate_tpwr_a; - mode = AR5K_EEPROM_MODE_11A; - } - max = ee->ee_rate_target_pwr_num[mode] - 1; - - /* Get the surrounding calibration - * piers - same as above */ - if (target < rpinfo[0].freq) { - idx_l = idx_r = 0; - goto done; - } - - if (target > rpinfo[max].freq) { - idx_l = idx_r = max; - goto done; - } - - for (i = 0; i <= max; i++) { - - if (rpinfo[i].freq == target) { - idx_l = idx_r = i; - goto done; - } - - if (target < rpinfo[i].freq) { - idx_r = i; - idx_l = idx_r - 1; - goto done; - } - } - -done: - /* Now interpolate power value, based on the frequency */ - rates->freq = target; - - rates->target_power_6to24 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_6to24, - rpinfo[idx_r].target_power_6to24); - - rates->target_power_36 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_36, - rpinfo[idx_r].target_power_36); - - rates->target_power_48 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_48, - rpinfo[idx_r].target_power_48); - - rates->target_power_54 = - ath5k_get_interpolated_value(target, rpinfo[idx_l].freq, - rpinfo[idx_r].freq, - rpinfo[idx_l].target_power_54, - rpinfo[idx_r].target_power_54); -} - -/* - * Get the max edge power for this channel if - * we have such data from EEPROM's Conformance Test - * Limits (CTL), and limit max power if needed. - */ -static void -ath5k_get_max_ctl_power(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - struct ath_regulatory *regulatory = ath5k_hw_regulatory(ah); - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - struct ath5k_edge_power *rep = ee->ee_ctl_pwr; - u8 *ctl_val = ee->ee_ctl; - s16 max_chan_pwr = ah->ah_txpower.txp_max_pwr / 4; - s16 edge_pwr = 0; - u8 rep_idx; - u8 i, ctl_mode; - u8 ctl_idx = 0xFF; - u32 target = channel->center_freq; - - ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band); - - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - ctl_mode |= AR5K_CTL_11A; - break; - case CHANNEL_G: - ctl_mode |= AR5K_CTL_11G; - break; - case CHANNEL_B: - ctl_mode |= AR5K_CTL_11B; - break; - case CHANNEL_T: - ctl_mode |= AR5K_CTL_TURBO; - break; - case CHANNEL_TG: - ctl_mode |= AR5K_CTL_TURBOG; - break; - case CHANNEL_XR: - /* Fall through */ - default: - return; - } - - for (i = 0; i < ee->ee_ctls; i++) { - if (ctl_val[i] == ctl_mode) { - ctl_idx = i; - break; - } - } - - /* If we have a CTL dataset available grab it and find the - * edge power for our frequency */ - if (ctl_idx == 0xFF) - return; - - /* Edge powers are sorted by frequency from lower - * to higher. Each CTL corresponds to 8 edge power - * measurements. */ - rep_idx = ctl_idx * AR5K_EEPROM_N_EDGES; - - /* Don't do boundaries check because we - * might have more that one bands defined - * for this mode */ - - /* Get the edge power that's closer to our - * frequency */ - for (i = 0; i < AR5K_EEPROM_N_EDGES; i++) { - rep_idx += i; - if (target <= rep[rep_idx].freq) - edge_pwr = (s16) rep[rep_idx].edge; - } - - if (edge_pwr) - ah->ah_txpower.txp_max_pwr = 4*min(edge_pwr, max_chan_pwr); -} - - -/* - * Power to PCDAC table functions - */ - -/* - * Fill Power to PCDAC table on RF5111 - * - * No further processing is needed for RF5111, the only thing we have to - * do is fill the values below and above calibration range since eeprom data - * may not cover the entire PCDAC table. - */ -static void -ath5k_fill_pwr_to_pcdac_table(struct ath5k_hw *ah, s16* table_min, - s16 *table_max) -{ - u8 *pcdac_out = ah->ah_txpower.txp_pd_table; - u8 *pcdac_tmp = ah->ah_txpower.tmpL[0]; - u8 pcdac_0, pcdac_n, pcdac_i, pwr_idx, i; - s16 min_pwr, max_pwr; - - /* Get table boundaries */ - min_pwr = table_min[0]; - pcdac_0 = pcdac_tmp[0]; - - max_pwr = table_max[0]; - pcdac_n = pcdac_tmp[table_max[0] - table_min[0]]; - - /* Extrapolate below minimum using pcdac_0 */ - pcdac_i = 0; - for (i = 0; i < min_pwr; i++) - pcdac_out[pcdac_i++] = pcdac_0; - - /* Copy values from pcdac_tmp */ - pwr_idx = min_pwr; - for (i = 0 ; pwr_idx <= max_pwr && - pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE; i++) { - pcdac_out[pcdac_i++] = pcdac_tmp[i]; - pwr_idx++; - } - - /* Extrapolate above maximum */ - while (pcdac_i < AR5K_EEPROM_POWER_TABLE_SIZE) - pcdac_out[pcdac_i++] = pcdac_n; - -} - -/* - * Combine available XPD Curves and fill Linear Power to PCDAC table - * on RF5112 - * - * RFX112 can have up to 2 curves (one for low txpower range and one for - * higher txpower range). We need to put them both on pcdac_out and place - * them in the correct location. In case we only have one curve available - * just fit it on pcdac_out (it's supposed to cover the entire range of - * available pwr levels since it's always the higher power curve). Extrapolate - * below and above final table if needed. - */ -static void -ath5k_combine_linear_pcdac_curves(struct ath5k_hw *ah, s16* table_min, - s16 *table_max, u8 pdcurves) -{ - u8 *pcdac_out = ah->ah_txpower.txp_pd_table; - u8 *pcdac_low_pwr; - u8 *pcdac_high_pwr; - u8 *pcdac_tmp; - u8 pwr; - s16 max_pwr_idx; - s16 min_pwr_idx; - s16 mid_pwr_idx = 0; - /* Edge flag turs on the 7nth bit on the PCDAC - * to delcare the higher power curve (force values - * to be greater than 64). If we only have one curve - * we don't need to set this, if we have 2 curves and - * fill the table backwards this can also be used to - * switch from higher power curve to lower power curve */ - u8 edge_flag; - int i; - - /* When we have only one curve available - * that's the higher power curve. If we have - * two curves the first is the high power curve - * and the next is the low power curve. */ - if (pdcurves > 1) { - pcdac_low_pwr = ah->ah_txpower.tmpL[1]; - pcdac_high_pwr = ah->ah_txpower.tmpL[0]; - mid_pwr_idx = table_max[1] - table_min[1] - 1; - max_pwr_idx = (table_max[0] - table_min[0]) / 2; - - /* If table size goes beyond 31.5dB, keep the - * upper 31.5dB range when setting tx power. - * Note: 126 = 31.5 dB in quarter dB steps */ - if (table_max[0] - table_min[1] > 126) - min_pwr_idx = table_max[0] - 126; - else - min_pwr_idx = table_min[1]; - - /* Since we fill table backwards - * start from high power curve */ - pcdac_tmp = pcdac_high_pwr; - - edge_flag = 0x40; -#if 0 - /* If both min and max power limits are in lower - * power curve's range, only use the low power curve. - * TODO: min/max levels are related to target - * power values requested from driver/user - * XXX: Is this really needed ? */ - if (min_pwr < table_max[1] && - max_pwr < table_max[1]) { - edge_flag = 0; - pcdac_tmp = pcdac_low_pwr; - max_pwr_idx = (table_max[1] - table_min[1])/2; - } -#endif - } else { - pcdac_low_pwr = ah->ah_txpower.tmpL[1]; /* Zeroed */ - pcdac_high_pwr = ah->ah_txpower.tmpL[0]; - min_pwr_idx = table_min[0]; - max_pwr_idx = (table_max[0] - table_min[0]) / 2; - pcdac_tmp = pcdac_high_pwr; - edge_flag = 0; - } - - /* This is used when setting tx power*/ - ah->ah_txpower.txp_min_idx = min_pwr_idx/2; - - /* Fill Power to PCDAC table backwards */ - pwr = max_pwr_idx; - for (i = 63; i >= 0; i--) { - /* Entering lower power range, reset - * edge flag and set pcdac_tmp to lower - * power curve.*/ - if (edge_flag == 0x40 && - (2*pwr <= (table_max[1] - table_min[0]) || pwr == 0)) { - edge_flag = 0x00; - pcdac_tmp = pcdac_low_pwr; - pwr = mid_pwr_idx/2; - } - - /* Don't go below 1, extrapolate below if we have - * already swithced to the lower power curve -or - * we only have one curve and edge_flag is zero - * anyway */ - if (pcdac_tmp[pwr] < 1 && (edge_flag == 0x00)) { - while (i >= 0) { - pcdac_out[i] = pcdac_out[i + 1]; - i--; - } - break; - } - - pcdac_out[i] = pcdac_tmp[pwr] | edge_flag; - - /* Extrapolate above if pcdac is greater than - * 126 -this can happen because we OR pcdac_out - * value with edge_flag on high power curve */ - if (pcdac_out[i] > 126) - pcdac_out[i] = 126; - - /* Decrease by a 0.5dB step */ - pwr--; - } -} - -/* Write PCDAC values on hw */ -static void -ath5k_setup_pcdac_table(struct ath5k_hw *ah) -{ - u8 *pcdac_out = ah->ah_txpower.txp_pd_table; - int i; - - /* - * Write TX power values - */ - for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { - ath5k_hw_reg_write(ah, - (((pcdac_out[2*i + 0] << 8 | 0xff) & 0xffff) << 0) | - (((pcdac_out[2*i + 1] << 8 | 0xff) & 0xffff) << 16), - AR5K_PHY_PCDAC_TXPOWER(i)); - } -} - - -/* - * Power to PDADC table functions - */ - -/* - * Set the gain boundaries and create final Power to PDADC table - * - * We can have up to 4 pd curves, we need to do a simmilar process - * as we do for RF5112. This time we don't have an edge_flag but we - * set the gain boundaries on a separate register. - */ -static void -ath5k_combine_pwr_to_pdadc_curves(struct ath5k_hw *ah, - s16 *pwr_min, s16 *pwr_max, u8 pdcurves) -{ - u8 gain_boundaries[AR5K_EEPROM_N_PD_GAINS]; - u8 *pdadc_out = ah->ah_txpower.txp_pd_table; - u8 *pdadc_tmp; - s16 pdadc_0; - u8 pdadc_i, pdadc_n, pwr_step, pdg, max_idx, table_size; - u8 pd_gain_overlap; - - /* Note: Register value is initialized on initvals - * there is no feedback from hw. - * XXX: What about pd_gain_overlap from EEPROM ? */ - pd_gain_overlap = (u8) ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG5) & - AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP; - - /* Create final PDADC table */ - for (pdg = 0, pdadc_i = 0; pdg < pdcurves; pdg++) { - pdadc_tmp = ah->ah_txpower.tmpL[pdg]; - - if (pdg == pdcurves - 1) - /* 2 dB boundary stretch for last - * (higher power) curve */ - gain_boundaries[pdg] = pwr_max[pdg] + 4; - else - /* Set gain boundary in the middle - * between this curve and the next one */ - gain_boundaries[pdg] = - (pwr_max[pdg] + pwr_min[pdg + 1]) / 2; - - /* Sanity check in case our 2 db stretch got out of - * range. */ - if (gain_boundaries[pdg] > AR5K_TUNE_MAX_TXPOWER) - gain_boundaries[pdg] = AR5K_TUNE_MAX_TXPOWER; - - /* For the first curve (lower power) - * start from 0 dB */ - if (pdg == 0) - pdadc_0 = 0; - else - /* For the other curves use the gain overlap */ - pdadc_0 = (gain_boundaries[pdg - 1] - pwr_min[pdg]) - - pd_gain_overlap; - - /* Force each power step to be at least 0.5 dB */ - if ((pdadc_tmp[1] - pdadc_tmp[0]) > 1) - pwr_step = pdadc_tmp[1] - pdadc_tmp[0]; - else - pwr_step = 1; - - /* If pdadc_0 is negative, we need to extrapolate - * below this pdgain by a number of pwr_steps */ - while ((pdadc_0 < 0) && (pdadc_i < 128)) { - s16 tmp = pdadc_tmp[0] + pdadc_0 * pwr_step; - pdadc_out[pdadc_i++] = (tmp < 0) ? 0 : (u8) tmp; - pdadc_0++; - } - - /* Set last pwr level, using gain boundaries */ - pdadc_n = gain_boundaries[pdg] + pd_gain_overlap - pwr_min[pdg]; - /* Limit it to be inside pwr range */ - table_size = pwr_max[pdg] - pwr_min[pdg]; - max_idx = (pdadc_n < table_size) ? pdadc_n : table_size; - - /* Fill pdadc_out table */ - while (pdadc_0 < max_idx) - pdadc_out[pdadc_i++] = pdadc_tmp[pdadc_0++]; - - /* Need to extrapolate above this pdgain? */ - if (pdadc_n <= max_idx) - continue; - - /* Force each power step to be at least 0.5 dB */ - if ((pdadc_tmp[table_size - 1] - pdadc_tmp[table_size - 2]) > 1) - pwr_step = pdadc_tmp[table_size - 1] - - pdadc_tmp[table_size - 2]; - else - pwr_step = 1; - - /* Extrapolate above */ - while ((pdadc_0 < (s16) pdadc_n) && - (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2)) { - s16 tmp = pdadc_tmp[table_size - 1] + - (pdadc_0 - max_idx) * pwr_step; - pdadc_out[pdadc_i++] = (tmp > 127) ? 127 : (u8) tmp; - pdadc_0++; - } - } - - while (pdg < AR5K_EEPROM_N_PD_GAINS) { - gain_boundaries[pdg] = gain_boundaries[pdg - 1]; - pdg++; - } - - while (pdadc_i < AR5K_EEPROM_POWER_TABLE_SIZE * 2) { - pdadc_out[pdadc_i] = pdadc_out[pdadc_i - 1]; - pdadc_i++; - } - - /* Set gain boundaries */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(pd_gain_overlap, - AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP) | - AR5K_REG_SM(gain_boundaries[0], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1) | - AR5K_REG_SM(gain_boundaries[1], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2) | - AR5K_REG_SM(gain_boundaries[2], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3) | - AR5K_REG_SM(gain_boundaries[3], - AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4), - AR5K_PHY_TPC_RG5); - - /* Used for setting rate power table */ - ah->ah_txpower.txp_min_idx = pwr_min[0]; - -} - -/* Write PDADC values on hw */ -static void -ath5k_setup_pwr_to_pdadc_table(struct ath5k_hw *ah, - u8 pdcurves, u8 *pdg_to_idx) -{ - u8 *pdadc_out = ah->ah_txpower.txp_pd_table; - u32 reg; - u8 i; - - /* Select the right pdgain curves */ - - /* Clear current settings */ - reg = ath5k_hw_reg_read(ah, AR5K_PHY_TPC_RG1); - reg &= ~(AR5K_PHY_TPC_RG1_PDGAIN_1 | - AR5K_PHY_TPC_RG1_PDGAIN_2 | - AR5K_PHY_TPC_RG1_PDGAIN_3 | - AR5K_PHY_TPC_RG1_NUM_PD_GAIN); - - /* - * Use pd_gains curve from eeprom - * - * This overrides the default setting from initvals - * in case some vendors (e.g. Zcomax) don't use the default - * curves. If we don't honor their settings we 'll get a - * 5dB (1 * gain overlap ?) drop. - */ - reg |= AR5K_REG_SM(pdcurves, AR5K_PHY_TPC_RG1_NUM_PD_GAIN); - - switch (pdcurves) { - case 3: - reg |= AR5K_REG_SM(pdg_to_idx[2], AR5K_PHY_TPC_RG1_PDGAIN_3); - /* Fall through */ - case 2: - reg |= AR5K_REG_SM(pdg_to_idx[1], AR5K_PHY_TPC_RG1_PDGAIN_2); - /* Fall through */ - case 1: - reg |= AR5K_REG_SM(pdg_to_idx[0], AR5K_PHY_TPC_RG1_PDGAIN_1); - break; - } - ath5k_hw_reg_write(ah, reg, AR5K_PHY_TPC_RG1); - - /* - * Write TX power values - */ - for (i = 0; i < (AR5K_EEPROM_POWER_TABLE_SIZE / 2); i++) { - ath5k_hw_reg_write(ah, - ((pdadc_out[4*i + 0] & 0xff) << 0) | - ((pdadc_out[4*i + 1] & 0xff) << 8) | - ((pdadc_out[4*i + 2] & 0xff) << 16) | - ((pdadc_out[4*i + 3] & 0xff) << 24), - AR5K_PHY_PDADC_TXPOWER(i)); - } -} - - -/* - * Common code for PCDAC/PDADC tables - */ - -/* - * This is the main function that uses all of the above - * to set PCDAC/PDADC table on hw for the current channel. - * This table is used for tx power calibration on the basband, - * without it we get weird tx power levels and in some cases - * distorted spectral mask - */ -static int -ath5k_setup_channel_powertable(struct ath5k_hw *ah, - struct ieee80211_channel *channel, - u8 ee_mode, u8 type) -{ - struct ath5k_pdgain_info *pdg_L, *pdg_R; - struct ath5k_chan_pcal_info *pcinfo_L; - struct ath5k_chan_pcal_info *pcinfo_R; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u8 *pdg_curve_to_idx = ee->ee_pdc_to_idx[ee_mode]; - s16 table_min[AR5K_EEPROM_N_PD_GAINS]; - s16 table_max[AR5K_EEPROM_N_PD_GAINS]; - u8 *tmpL; - u8 *tmpR; - u32 target = channel->center_freq; - int pdg, i; - - /* Get surounding freq piers for this channel */ - ath5k_get_chan_pcal_surrounding_piers(ah, channel, - &pcinfo_L, - &pcinfo_R); - - /* Loop over pd gain curves on - * surounding freq piers by index */ - for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) { - - /* Fill curves in reverse order - * from lower power (max gain) - * to higher power. Use curve -> idx - * backmaping we did on eeprom init */ - u8 idx = pdg_curve_to_idx[pdg]; - - /* Grab the needed curves by index */ - pdg_L = &pcinfo_L->pd_curves[idx]; - pdg_R = &pcinfo_R->pd_curves[idx]; - - /* Initialize the temp tables */ - tmpL = ah->ah_txpower.tmpL[pdg]; - tmpR = ah->ah_txpower.tmpR[pdg]; - - /* Set curve's x boundaries and create - * curves so that they cover the same - * range (if we don't do that one table - * will have values on some range and the - * other one won't have any so interpolation - * will fail) */ - table_min[pdg] = min(pdg_L->pd_pwr[0], - pdg_R->pd_pwr[0]) / 2; - - table_max[pdg] = max(pdg_L->pd_pwr[pdg_L->pd_points - 1], - pdg_R->pd_pwr[pdg_R->pd_points - 1]) / 2; - - /* Now create the curves on surrounding channels - * and interpolate if needed to get the final - * curve for this gain on this channel */ - switch (type) { - case AR5K_PWRTABLE_LINEAR_PCDAC: - /* Override min/max so that we don't loose - * accuracy (don't divide by 2) */ - table_min[pdg] = min(pdg_L->pd_pwr[0], - pdg_R->pd_pwr[0]); - - table_max[pdg] = - max(pdg_L->pd_pwr[pdg_L->pd_points - 1], - pdg_R->pd_pwr[pdg_R->pd_points - 1]); - - /* Override minimum so that we don't get - * out of bounds while extrapolating - * below. Don't do this when we have 2 - * curves and we are on the high power curve - * because table_min is ok in this case */ - if (!(ee->ee_pd_gains[ee_mode] > 1 && pdg == 0)) { - - table_min[pdg] = - ath5k_get_linear_pcdac_min(pdg_L->pd_step, - pdg_R->pd_step, - pdg_L->pd_pwr, - pdg_R->pd_pwr); - - /* Don't go too low because we will - * miss the upper part of the curve. - * Note: 126 = 31.5dB (max power supported) - * in 0.25dB units */ - if (table_max[pdg] - table_min[pdg] > 126) - table_min[pdg] = table_max[pdg] - 126; - } - - /* Fall through */ - case AR5K_PWRTABLE_PWR_TO_PCDAC: - case AR5K_PWRTABLE_PWR_TO_PDADC: - - ath5k_create_power_curve(table_min[pdg], - table_max[pdg], - pdg_L->pd_pwr, - pdg_L->pd_step, - pdg_L->pd_points, tmpL, type); - - /* We are in a calibration - * pier, no need to interpolate - * between freq piers */ - if (pcinfo_L == pcinfo_R) - continue; - - ath5k_create_power_curve(table_min[pdg], - table_max[pdg], - pdg_R->pd_pwr, - pdg_R->pd_step, - pdg_R->pd_points, tmpR, type); - break; - default: - return -EINVAL; - } - - /* Interpolate between curves - * of surounding freq piers to - * get the final curve for this - * pd gain. Re-use tmpL for interpolation - * output */ - for (i = 0; (i < (u16) (table_max[pdg] - table_min[pdg])) && - (i < AR5K_EEPROM_POWER_TABLE_SIZE); i++) { - tmpL[i] = (u8) ath5k_get_interpolated_value(target, - (s16) pcinfo_L->freq, - (s16) pcinfo_R->freq, - (s16) tmpL[i], - (s16) tmpR[i]); - } - } - - /* Now we have a set of curves for this - * channel on tmpL (x range is table_max - table_min - * and y values are tmpL[pdg][]) sorted in the same - * order as EEPROM (because we've used the backmaping). - * So for RF5112 it's from higher power to lower power - * and for RF2413 it's from lower power to higher power. - * For RF5111 we only have one curve. */ - - /* Fill min and max power levels for this - * channel by interpolating the values on - * surounding channels to complete the dataset */ - ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target, - (s16) pcinfo_L->freq, - (s16) pcinfo_R->freq, - pcinfo_L->min_pwr, pcinfo_R->min_pwr); - - ah->ah_txpower.txp_max_pwr = ath5k_get_interpolated_value(target, - (s16) pcinfo_L->freq, - (s16) pcinfo_R->freq, - pcinfo_L->max_pwr, pcinfo_R->max_pwr); - - /* We are ready to go, fill PCDAC/PDADC - * table and write settings on hardware */ - switch (type) { - case AR5K_PWRTABLE_LINEAR_PCDAC: - /* For RF5112 we can have one or two curves - * and each curve covers a certain power lvl - * range so we need to do some more processing */ - ath5k_combine_linear_pcdac_curves(ah, table_min, table_max, - ee->ee_pd_gains[ee_mode]); - - /* Set txp.offset so that we can - * match max power value with max - * table index */ - ah->ah_txpower.txp_offset = 64 - (table_max[0] / 2); - - /* Write settings on hw */ - ath5k_setup_pcdac_table(ah); - break; - case AR5K_PWRTABLE_PWR_TO_PCDAC: - /* We are done for RF5111 since it has only - * one curve, just fit the curve on the table */ - ath5k_fill_pwr_to_pcdac_table(ah, table_min, table_max); - - /* No rate powertable adjustment for RF5111 */ - ah->ah_txpower.txp_min_idx = 0; - ah->ah_txpower.txp_offset = 0; - - /* Write settings on hw */ - ath5k_setup_pcdac_table(ah); - break; - case AR5K_PWRTABLE_PWR_TO_PDADC: - /* Set PDADC boundaries and fill - * final PDADC table */ - ath5k_combine_pwr_to_pdadc_curves(ah, table_min, table_max, - ee->ee_pd_gains[ee_mode]); - - /* Write settings on hw */ - ath5k_setup_pwr_to_pdadc_table(ah, pdg, pdg_curve_to_idx); - - /* Set txp.offset, note that table_min - * can be negative */ - ah->ah_txpower.txp_offset = table_min[0]; - break; - default: - return -EINVAL; - } - - return 0; -} - - -/* - * Per-rate tx power setting - * - * This is the code that sets the desired tx power (below - * maximum) on hw for each rate (we also have TPC that sets - * power per packet). We do that by providing an index on the - * PCDAC/PDADC table we set up. - */ - -/* - * Set rate power table - * - * For now we only limit txpower based on maximum tx power - * supported by hw (what's inside rate_info). We need to limit - * this even more, based on regulatory domain etc. - * - * Rate power table contains indices to PCDAC/PDADC table (0.5dB steps) - * and is indexed as follows: - * rates[0] - rates[7] -> OFDM rates - * rates[8] - rates[14] -> CCK rates - * rates[15] -> XR rates (they all have the same power) - */ -static void -ath5k_setup_rate_powertable(struct ath5k_hw *ah, u16 max_pwr, - struct ath5k_rate_pcal_info *rate_info, - u8 ee_mode) -{ - unsigned int i; - u16 *rates; - - /* max_pwr is power level we got from driver/user in 0.5dB - * units, switch to 0.25dB units so we can compare */ - max_pwr *= 2; - max_pwr = min(max_pwr, (u16) ah->ah_txpower.txp_max_pwr) / 2; - - /* apply rate limits */ - rates = ah->ah_txpower.txp_rates_power_table; - - /* OFDM rates 6 to 24Mb/s */ - for (i = 0; i < 5; i++) - rates[i] = min(max_pwr, rate_info->target_power_6to24); - - /* Rest OFDM rates */ - rates[5] = min(rates[0], rate_info->target_power_36); - rates[6] = min(rates[0], rate_info->target_power_48); - rates[7] = min(rates[0], rate_info->target_power_54); - - /* CCK rates */ - /* 1L */ - rates[8] = min(rates[0], rate_info->target_power_6to24); - /* 2L */ - rates[9] = min(rates[0], rate_info->target_power_36); - /* 2S */ - rates[10] = min(rates[0], rate_info->target_power_36); - /* 5L */ - rates[11] = min(rates[0], rate_info->target_power_48); - /* 5S */ - rates[12] = min(rates[0], rate_info->target_power_48); - /* 11L */ - rates[13] = min(rates[0], rate_info->target_power_54); - /* 11S */ - rates[14] = min(rates[0], rate_info->target_power_54); - - /* XR rates */ - rates[15] = min(rates[0], rate_info->target_power_6to24); - - /* CCK rates have different peak to average ratio - * so we have to tweak their power so that gainf - * correction works ok. For this we use OFDM to - * CCK delta from eeprom */ - if ((ee_mode == AR5K_EEPROM_MODE_11G) && - (ah->ah_phy_revision < AR5K_SREV_PHY_5212A)) - for (i = 8; i <= 15; i++) - rates[i] -= ah->ah_txpower.txp_cck_ofdm_gainf_delta; - - /* Now that we have all rates setup use table offset to - * match the power range set by user with the power indices - * on PCDAC/PDADC table */ - for (i = 0; i < 16; i++) { - rates[i] += ah->ah_txpower.txp_offset; - /* Don't get out of bounds */ - if (rates[i] > 63) - rates[i] = 63; - } - - /* Min/max in 0.25dB units */ - ah->ah_txpower.txp_min_pwr = 2 * rates[7]; - ah->ah_txpower.txp_max_pwr = 2 * rates[0]; - ah->ah_txpower.txp_ofdm = rates[7]; -} - - -/* - * Set transmition power - */ -int -ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel *channel, - u8 ee_mode, u8 txpower) -{ - struct ath5k_rate_pcal_info rate_info; - u8 type; - int ret; - - ATH5K_TRACE(ah->ah_sc); - if (txpower > AR5K_TUNE_MAX_TXPOWER) { - ATH5K_ERR(ah->ah_sc, "invalid tx power: %u\n", txpower); - return -EINVAL; - } - - /* Reset TX power values */ - memset(&ah->ah_txpower, 0, sizeof(ah->ah_txpower)); - ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; - ah->ah_txpower.txp_min_pwr = 0; - ah->ah_txpower.txp_max_pwr = AR5K_TUNE_MAX_TXPOWER; - - /* Initialize TX power table */ - switch (ah->ah_radio) { - case AR5K_RF5111: - type = AR5K_PWRTABLE_PWR_TO_PCDAC; - break; - case AR5K_RF5112: - type = AR5K_PWRTABLE_LINEAR_PCDAC; - break; - case AR5K_RF2413: - case AR5K_RF5413: - case AR5K_RF2316: - case AR5K_RF2317: - case AR5K_RF2425: - type = AR5K_PWRTABLE_PWR_TO_PDADC; - break; - default: - return -EINVAL; - } - - /* FIXME: Only on channel/mode change */ - ret = ath5k_setup_channel_powertable(ah, channel, ee_mode, type); - if (ret) - return ret; - - /* Limit max power if we have a CTL available */ - ath5k_get_max_ctl_power(ah, channel); - - /* FIXME: Tx power limit for this regdomain - * XXX: Mac80211/CRDA will do that anyway ? */ - - /* FIXME: Antenna reduction stuff */ - - /* FIXME: Limit power on turbo modes */ - - /* FIXME: TPC scale reduction */ - - /* Get surounding channels for per-rate power table - * calibration */ - ath5k_get_rate_pcal_data(ah, channel, &rate_info); - - /* Setup rate power table */ - ath5k_setup_rate_powertable(ah, txpower, &rate_info, ee_mode); - - /* Write rate power table on hw */ - ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(3, 24) | - AR5K_TXPOWER_OFDM(2, 16) | AR5K_TXPOWER_OFDM(1, 8) | - AR5K_TXPOWER_OFDM(0, 0), AR5K_PHY_TXPOWER_RATE1); - - ath5k_hw_reg_write(ah, AR5K_TXPOWER_OFDM(7, 24) | - AR5K_TXPOWER_OFDM(6, 16) | AR5K_TXPOWER_OFDM(5, 8) | - AR5K_TXPOWER_OFDM(4, 0), AR5K_PHY_TXPOWER_RATE2); - - ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(10, 24) | - AR5K_TXPOWER_CCK(9, 16) | AR5K_TXPOWER_CCK(15, 8) | - AR5K_TXPOWER_CCK(8, 0), AR5K_PHY_TXPOWER_RATE3); - - ath5k_hw_reg_write(ah, AR5K_TXPOWER_CCK(14, 24) | - AR5K_TXPOWER_CCK(13, 16) | AR5K_TXPOWER_CCK(12, 8) | - AR5K_TXPOWER_CCK(11, 0), AR5K_PHY_TXPOWER_RATE4); - - /* FIXME: TPC support */ - if (ah->ah_txpower.txp_tpc) { - ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE | - AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); - - ath5k_hw_reg_write(ah, - AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_ACK) | - AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CTS) | - AR5K_REG_MS(AR5K_TUNE_MAX_TXPOWER, AR5K_TPC_CHIRP), - AR5K_TPC); - } else { - ath5k_hw_reg_write(ah, AR5K_PHY_TXPOWER_RATE_MAX | - AR5K_TUNE_MAX_TXPOWER, AR5K_PHY_TXPOWER_RATE_MAX); - } - - return 0; -} - -int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, u8 txpower) -{ - /*Just a try M.F.*/ - struct ieee80211_channel *channel = ah->ah_current_channel; - u8 ee_mode; - - ATH5K_TRACE(ah->ah_sc); - - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - case CHANNEL_T: - case CHANNEL_XR: - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - case CHANNEL_TG: - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - ee_mode = AR5K_EEPROM_MODE_11B; - break; - default: - ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); - return -EINVAL; - } - - ATH5K_DBG(ah->ah_sc, ATH5K_DEBUG_TXPOWER, - "changing txpower to %d\n", txpower); - - return ath5k_hw_txpower(ah, channel, ee_mode, txpower); -} - -#undef _ATH5K_PHY diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c deleted file mode 100644 index b7c57259f134..000000000000 --- a/drivers/net/wireless/ath/ath5k/qcu.c +++ /dev/null @@ -1,549 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/********************************************\ -Queue Control Unit, DFS Control Unit Functions -\********************************************/ - -#include "ath5k.h" -#include "reg.h" -#include "debug.h" -#include "base.h" - -/* - * Get properties for a transmit queue - */ -int ath5k_hw_get_tx_queueprops(struct ath5k_hw *ah, int queue, - struct ath5k_txq_info *queue_info) -{ - ATH5K_TRACE(ah->ah_sc); - memcpy(queue_info, &ah->ah_txq[queue], sizeof(struct ath5k_txq_info)); - return 0; -} - -/* - * Set properties for a transmit queue - */ -int ath5k_hw_set_tx_queueprops(struct ath5k_hw *ah, int queue, - const struct ath5k_txq_info *queue_info) -{ - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return -EIO; - - memcpy(&ah->ah_txq[queue], queue_info, sizeof(struct ath5k_txq_info)); - - /*XXX: Is this supported on 5210 ?*/ - if ((queue_info->tqi_type == AR5K_TX_QUEUE_DATA && - ((queue_info->tqi_subtype == AR5K_WME_AC_VI) || - (queue_info->tqi_subtype == AR5K_WME_AC_VO))) || - queue_info->tqi_type == AR5K_TX_QUEUE_UAPSD) - ah->ah_txq[queue].tqi_flags |= AR5K_TXQ_FLAG_POST_FR_BKOFF_DIS; - - return 0; -} - -/* - * Initialize a transmit queue - */ -int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type, - struct ath5k_txq_info *queue_info) -{ - unsigned int queue; - int ret; - - ATH5K_TRACE(ah->ah_sc); - - /* - * Get queue by type - */ - /*5210 only has 2 queues*/ - if (ah->ah_version == AR5K_AR5210) { - switch (queue_type) { - case AR5K_TX_QUEUE_DATA: - queue = AR5K_TX_QUEUE_ID_NOQCU_DATA; - break; - case AR5K_TX_QUEUE_BEACON: - case AR5K_TX_QUEUE_CAB: - queue = AR5K_TX_QUEUE_ID_NOQCU_BEACON; - break; - default: - return -EINVAL; - } - } else { - switch (queue_type) { - case AR5K_TX_QUEUE_DATA: - for (queue = AR5K_TX_QUEUE_ID_DATA_MIN; - ah->ah_txq[queue].tqi_type != - AR5K_TX_QUEUE_INACTIVE; queue++) { - - if (queue > AR5K_TX_QUEUE_ID_DATA_MAX) - return -EINVAL; - } - break; - case AR5K_TX_QUEUE_UAPSD: - queue = AR5K_TX_QUEUE_ID_UAPSD; - break; - case AR5K_TX_QUEUE_BEACON: - queue = AR5K_TX_QUEUE_ID_BEACON; - break; - case AR5K_TX_QUEUE_CAB: - queue = AR5K_TX_QUEUE_ID_CAB; - break; - case AR5K_TX_QUEUE_XR_DATA: - if (ah->ah_version != AR5K_AR5212) - ATH5K_ERR(ah->ah_sc, - "XR data queues only supported in" - " 5212!\n"); - queue = AR5K_TX_QUEUE_ID_XR_DATA; - break; - default: - return -EINVAL; - } - } - - /* - * Setup internal queue structure - */ - memset(&ah->ah_txq[queue], 0, sizeof(struct ath5k_txq_info)); - ah->ah_txq[queue].tqi_type = queue_type; - - if (queue_info != NULL) { - queue_info->tqi_type = queue_type; - ret = ath5k_hw_set_tx_queueprops(ah, queue, queue_info); - if (ret) - return ret; - } - - /* - * We use ah_txq_status to hold a temp value for - * the Secondary interrupt mask registers on 5211+ - * check out ath5k_hw_reset_tx_queue - */ - AR5K_Q_ENABLE_BITS(ah->ah_txq_status, queue); - - return queue; -} - -/* - * Get number of pending frames - * for a specific queue [5211+] - */ -u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue) -{ - u32 pending; - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - /* Return if queue is declared inactive */ - if (ah->ah_txq[queue].tqi_type == AR5K_TX_QUEUE_INACTIVE) - return false; - - /* XXX: How about AR5K_CFG_TXCNT ? */ - if (ah->ah_version == AR5K_AR5210) - return false; - - pending = ath5k_hw_reg_read(ah, AR5K_QUEUE_STATUS(queue)); - pending &= AR5K_QCU_STS_FRMPENDCNT; - - /* It's possible to have no frames pending even if TXE - * is set. To indicate that q has not stopped return - * true */ - if (!pending && AR5K_REG_READ_Q(ah, AR5K_QCU_TXE, queue)) - return true; - - return pending; -} - -/* - * Set a transmit queue inactive - */ -void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue) -{ - ATH5K_TRACE(ah->ah_sc); - if (WARN_ON(queue >= ah->ah_capabilities.cap_queues.q_tx_num)) - return; - - /* This queue will be skipped in further operations */ - ah->ah_txq[queue].tqi_type = AR5K_TX_QUEUE_INACTIVE; - /*For SIMR setup*/ - AR5K_Q_DISABLE_BITS(ah->ah_txq_status, queue); -} - -/* - * Set DFS properties for a transmit queue on DCU - */ -int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue) -{ - u32 cw_min, cw_max, retry_lg, retry_sh; - struct ath5k_txq_info *tq = &ah->ah_txq[queue]; - - ATH5K_TRACE(ah->ah_sc); - AR5K_ASSERT_ENTRY(queue, ah->ah_capabilities.cap_queues.q_tx_num); - - tq = &ah->ah_txq[queue]; - - if (tq->tqi_type == AR5K_TX_QUEUE_INACTIVE) - return 0; - - if (ah->ah_version == AR5K_AR5210) { - /* Only handle data queues, others will be ignored */ - if (tq->tqi_type != AR5K_TX_QUEUE_DATA) - return 0; - - /* Set Slot time */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_SLOT_TIME_TURBO : AR5K_INIT_SLOT_TIME, - AR5K_SLOT_TIME); - /* Set ACK_CTS timeout */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_ACK_CTS_TIMEOUT_TURBO : - AR5K_INIT_ACK_CTS_TIMEOUT, AR5K_SLOT_TIME); - /* Set Transmit Latency */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_TRANSMIT_LATENCY_TURBO : - AR5K_INIT_TRANSMIT_LATENCY, AR5K_USEC_5210); - - /* Set IFS0 */ - if (ah->ah_turbo) { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS_TURBO + - (ah->ah_aifs + tq->tqi_aifs) * - AR5K_INIT_SLOT_TIME_TURBO) << - AR5K_IFS0_DIFS_S) | AR5K_INIT_SIFS_TURBO, - AR5K_IFS0); - } else { - ath5k_hw_reg_write(ah, ((AR5K_INIT_SIFS + - (ah->ah_aifs + tq->tqi_aifs) * - AR5K_INIT_SLOT_TIME) << AR5K_IFS0_DIFS_S) | - AR5K_INIT_SIFS, AR5K_IFS0); - } - - /* Set IFS1 */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - AR5K_INIT_PROTO_TIME_CNTRL_TURBO : - AR5K_INIT_PROTO_TIME_CNTRL, AR5K_IFS1); - /* Set AR5K_PHY_SETTLING */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x38 : - (ath5k_hw_reg_read(ah, AR5K_PHY_SETTLING) & ~0x7F) - | 0x1C, - AR5K_PHY_SETTLING); - /* Set Frame Control Register */ - ath5k_hw_reg_write(ah, ah->ah_turbo ? - (AR5K_PHY_FRAME_CTL_INI | AR5K_PHY_TURBO_MODE | - AR5K_PHY_TURBO_SHORT | 0x2020) : - (AR5K_PHY_FRAME_CTL_INI | 0x1020), - AR5K_PHY_FRAME_CTL_5210); - } - - /* - * Calculate cwmin/max by channel mode - */ - cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN; - cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX; - ah->ah_aifs = AR5K_TUNE_AIFS; - /*XR is only supported on 5212*/ - if (IS_CHAN_XR(ah->ah_current_channel) && - ah->ah_version == AR5K_AR5212) { - cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_XR; - cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_XR; - ah->ah_aifs = AR5K_TUNE_AIFS_XR; - /*B mode is not supported on 5210*/ - } else if (IS_CHAN_B(ah->ah_current_channel) && - ah->ah_version != AR5K_AR5210) { - cw_min = ah->ah_cw_min = AR5K_TUNE_CWMIN_11B; - cw_max = ah->ah_cw_max = AR5K_TUNE_CWMAX_11B; - ah->ah_aifs = AR5K_TUNE_AIFS_11B; - } - - cw_min = 1; - while (cw_min < ah->ah_cw_min) - cw_min = (cw_min << 1) | 1; - - cw_min = tq->tqi_cw_min < 0 ? (cw_min >> (-tq->tqi_cw_min)) : - ((cw_min << tq->tqi_cw_min) + (1 << tq->tqi_cw_min) - 1); - cw_max = tq->tqi_cw_max < 0 ? (cw_max >> (-tq->tqi_cw_max)) : - ((cw_max << tq->tqi_cw_max) + (1 << tq->tqi_cw_max) - 1); - - /* - * Calculate and set retry limits - */ - if (ah->ah_software_retry) { - /* XXX Need to test this */ - retry_lg = ah->ah_limit_tx_retries; - retry_sh = retry_lg = retry_lg > AR5K_DCU_RETRY_LMT_SH_RETRY ? - AR5K_DCU_RETRY_LMT_SH_RETRY : retry_lg; - } else { - retry_lg = AR5K_INIT_LG_RETRY; - retry_sh = AR5K_INIT_SH_RETRY; - } - - /*No QCU/DCU [5210]*/ - if (ah->ah_version == AR5K_AR5210) { - ath5k_hw_reg_write(ah, - (cw_min << AR5K_NODCU_RETRY_LMT_CW_MIN_S) - | AR5K_REG_SM(AR5K_INIT_SLG_RETRY, - AR5K_NODCU_RETRY_LMT_SLG_RETRY) - | AR5K_REG_SM(AR5K_INIT_SSH_RETRY, - AR5K_NODCU_RETRY_LMT_SSH_RETRY) - | AR5K_REG_SM(retry_lg, AR5K_NODCU_RETRY_LMT_LG_RETRY) - | AR5K_REG_SM(retry_sh, AR5K_NODCU_RETRY_LMT_SH_RETRY), - AR5K_NODCU_RETRY_LMT); - } else { - /*QCU/DCU [5211+]*/ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(AR5K_INIT_SLG_RETRY, - AR5K_DCU_RETRY_LMT_SLG_RETRY) | - AR5K_REG_SM(AR5K_INIT_SSH_RETRY, - AR5K_DCU_RETRY_LMT_SSH_RETRY) | - AR5K_REG_SM(retry_lg, AR5K_DCU_RETRY_LMT_LG_RETRY) | - AR5K_REG_SM(retry_sh, AR5K_DCU_RETRY_LMT_SH_RETRY), - AR5K_QUEUE_DFS_RETRY_LIMIT(queue)); - - /*===Rest is also for QCU/DCU only [5211+]===*/ - - /* - * Set initial content window (cw_min/cw_max) - * and arbitrated interframe space (aifs)... - */ - ath5k_hw_reg_write(ah, - AR5K_REG_SM(cw_min, AR5K_DCU_LCL_IFS_CW_MIN) | - AR5K_REG_SM(cw_max, AR5K_DCU_LCL_IFS_CW_MAX) | - AR5K_REG_SM(ah->ah_aifs + tq->tqi_aifs, - AR5K_DCU_LCL_IFS_AIFS), - AR5K_QUEUE_DFS_LOCAL_IFS(queue)); - - /* - * Set misc registers - */ - /* Enable DCU early termination for this queue */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_DCU_EARLY); - - /* Enable DCU to wait for next fragment from QCU */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_FRAG_WAIT); - - /* On Maui and Spirit use the global seqnum on DCU */ - if (ah->ah_mac_version < AR5K_SREV_AR5211) - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - AR5K_DCU_MISC_SEQNUM_CTL); - - if (tq->tqi_cbr_period) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_cbr_period, - AR5K_QCU_CBRCFG_INTVAL) | - AR5K_REG_SM(tq->tqi_cbr_overflow_limit, - AR5K_QCU_CBRCFG_ORN_THRES), - AR5K_QUEUE_CBRCFG(queue)); - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_CBR); - if (tq->tqi_cbr_overflow_limit) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBR_THRES_ENABLE); - } - - if (tq->tqi_ready_time && - (tq->tqi_type != AR5K_TX_QUEUE_CAB)) - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_ready_time, - AR5K_QCU_RDYTIMECFG_INTVAL) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); - - if (tq->tqi_burst_time) { - ath5k_hw_reg_write(ah, AR5K_REG_SM(tq->tqi_burst_time, - AR5K_DCU_CHAN_TIME_DUR) | - AR5K_DCU_CHAN_TIME_ENABLE, - AR5K_QUEUE_DFS_CHANNEL_TIME(queue)); - - if (tq->tqi_flags - & AR5K_TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE) - AR5K_REG_ENABLE_BITS(ah, - AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_RDY_VEOL_POLICY); - } - - if (tq->tqi_flags & AR5K_TXQ_FLAG_BACKOFF_DISABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_POST_FR_BKOFF_DIS, - AR5K_QUEUE_DFS_MISC(queue)); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) - ath5k_hw_reg_write(ah, AR5K_DCU_MISC_BACKOFF_FRAG, - AR5K_QUEUE_DFS_MISC(queue)); - - /* - * Set registers by queue type - */ - switch (tq->tqi_type) { - case AR5K_TX_QUEUE_BEACON: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_BCN_DIS | - AR5K_QCU_MISC_BCN_ENABLE); - - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << - AR5K_DCU_MISC_ARBLOCK_CTL_S) | - AR5K_DCU_MISC_ARBLOCK_IGNORE | - AR5K_DCU_MISC_POST_FR_BKOFF_DIS | - AR5K_DCU_MISC_BCN_ENABLE); - break; - - case AR5K_TX_QUEUE_CAB: - /* XXX: use BCN_SENT_GT, if we can figure out how */ - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_FRSHED_DBA_GT | - AR5K_QCU_MISC_CBREXP_DIS | - AR5K_QCU_MISC_CBREXP_BCN_DIS); - - ath5k_hw_reg_write(ah, ((tq->tqi_ready_time - - (AR5K_TUNE_SW_BEACON_RESP - - AR5K_TUNE_DMA_BEACON_RESP) - - AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF) * 1024) | - AR5K_QCU_RDYTIMECFG_ENABLE, - AR5K_QUEUE_RDYTIMECFG(queue)); - - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_DFS_MISC(queue), - (AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL << - AR5K_DCU_MISC_ARBLOCK_CTL_S)); - break; - - case AR5K_TX_QUEUE_UAPSD: - AR5K_REG_ENABLE_BITS(ah, AR5K_QUEUE_MISC(queue), - AR5K_QCU_MISC_CBREXP_DIS); - break; - - case AR5K_TX_QUEUE_DATA: - default: - break; - } - - /* TODO: Handle frame compression */ - - /* - * Enable interrupts for this tx queue - * in the secondary interrupt mask registers - */ - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXOKINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txok, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXERRINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txerr, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXDESCINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txdesc, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXEOLINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_txeol, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRORNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrorn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_CBRURNINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_cbrurn, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_QTRIGINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_qtrig, queue); - - if (tq->tqi_flags & AR5K_TXQ_FLAG_TXNOFRMINT_ENABLE) - AR5K_Q_ENABLE_BITS(ah->ah_txq_imr_nofrm, queue); - - /* Update secondary interrupt mask registers */ - - /* Filter out inactive queues */ - ah->ah_txq_imr_txok &= ah->ah_txq_status; - ah->ah_txq_imr_txerr &= ah->ah_txq_status; - ah->ah_txq_imr_txurn &= ah->ah_txq_status; - ah->ah_txq_imr_txdesc &= ah->ah_txq_status; - ah->ah_txq_imr_txeol &= ah->ah_txq_status; - ah->ah_txq_imr_cbrorn &= ah->ah_txq_status; - ah->ah_txq_imr_cbrurn &= ah->ah_txq_status; - ah->ah_txq_imr_qtrig &= ah->ah_txq_status; - ah->ah_txq_imr_nofrm &= ah->ah_txq_status; - - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txok, - AR5K_SIMR0_QCU_TXOK) | - AR5K_REG_SM(ah->ah_txq_imr_txdesc, - AR5K_SIMR0_QCU_TXDESC), AR5K_SIMR0); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_txerr, - AR5K_SIMR1_QCU_TXERR) | - AR5K_REG_SM(ah->ah_txq_imr_txeol, - AR5K_SIMR1_QCU_TXEOL), AR5K_SIMR1); - /* Update simr2 but don't overwrite rest simr2 settings */ - AR5K_REG_DISABLE_BITS(ah, AR5K_SIMR2, AR5K_SIMR2_QCU_TXURN); - AR5K_REG_ENABLE_BITS(ah, AR5K_SIMR2, - AR5K_REG_SM(ah->ah_txq_imr_txurn, - AR5K_SIMR2_QCU_TXURN)); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_cbrorn, - AR5K_SIMR3_QCBRORN) | - AR5K_REG_SM(ah->ah_txq_imr_cbrurn, - AR5K_SIMR3_QCBRURN), AR5K_SIMR3); - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_qtrig, - AR5K_SIMR4_QTRIG), AR5K_SIMR4); - /* Set TXNOFRM_QCU for the queues with TXNOFRM enabled */ - ath5k_hw_reg_write(ah, AR5K_REG_SM(ah->ah_txq_imr_nofrm, - AR5K_TXNOFRM_QCU), AR5K_TXNOFRM); - /* No queue has TXNOFRM enabled, disable the interrupt - * by setting AR5K_TXNOFRM to zero */ - if (ah->ah_txq_imr_nofrm == 0) - ath5k_hw_reg_write(ah, 0, AR5K_TXNOFRM); - - /* Set QCU mask for this DCU to save power */ - AR5K_REG_WRITE_Q(ah, AR5K_QUEUE_QCUMASK(queue), queue); - } - - return 0; -} - -/* - * Get slot time from DCU - */ -unsigned int ath5k_hw_get_slot_time(struct ath5k_hw *ah) -{ - ATH5K_TRACE(ah->ah_sc); - if (ah->ah_version == AR5K_AR5210) - return ath5k_hw_clocktoh(ath5k_hw_reg_read(ah, - AR5K_SLOT_TIME) & 0xffff, ah->ah_turbo); - else - return ath5k_hw_reg_read(ah, AR5K_DCU_GBL_IFS_SLOT) & 0xffff; -} - -/* - * Set slot time on DCU - */ -int ath5k_hw_set_slot_time(struct ath5k_hw *ah, unsigned int slot_time) -{ - ATH5K_TRACE(ah->ah_sc); - if (slot_time < AR5K_SLOT_TIME_9 || slot_time > AR5K_SLOT_TIME_MAX) - return -EINVAL; - - if (ah->ah_version == AR5K_AR5210) - ath5k_hw_reg_write(ah, ath5k_hw_htoclock(slot_time, - ah->ah_turbo), AR5K_SLOT_TIME); - else - ath5k_hw_reg_write(ah, slot_time, AR5K_DCU_GBL_IFS_SLOT); - - return 0; -} - diff --git a/drivers/net/wireless/ath/ath5k/reg.h b/drivers/net/wireless/ath/ath5k/reg.h deleted file mode 100644 index c63ea6afd96f..000000000000 --- a/drivers/net/wireless/ath/ath5k/reg.h +++ /dev/null @@ -1,2596 +0,0 @@ -/* - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2007-2008 Michael Taylor - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Register values for Atheros 5210/5211/5212 cards from OpenBSD's ar5k - * maintained by Reyk Floeter - * - * I tried to document those registers by looking at ar5k code, some - * 802.11 (802.11e mostly) papers and by reading various public available - * Atheros presentations and papers like these: - * - * 5210 - http://nova.stanford.edu/~bbaas/ps/isscc2002_slides.pdf - * http://www.it.iitb.ac.in/~janak/wifire/01222734.pdf - * - * 5211 - http://www.hotchips.org/archives/hc14/3_Tue/16_mcfarland.pdf - * - * This file also contains register values found on a memory dump of - * Atheros's ART program (Atheros Radio Test), on ath9k, on legacy-hal - * released by Atheros and on various debug messages found on the net. - */ - - - -/*====MAC DMA REGISTERS====*/ - -/* - * AR5210-Specific TXDP registers - * 5210 has only 2 transmit queues so no DCU/QCU, just - * 2 transmit descriptor pointers... - */ -#define AR5K_NOQCU_TXDP0 0x0000 /* Queue 0 - data */ -#define AR5K_NOQCU_TXDP1 0x0004 /* Queue 1 - beacons */ - -/* - * Mac Control Register - */ -#define AR5K_CR 0x0008 /* Register Address */ -#define AR5K_CR_TXE0 0x00000001 /* TX Enable for queue 0 on 5210 */ -#define AR5K_CR_TXE1 0x00000002 /* TX Enable for queue 1 on 5210 */ -#define AR5K_CR_RXE 0x00000004 /* RX Enable */ -#define AR5K_CR_TXD0 0x00000008 /* TX Disable for queue 0 on 5210 */ -#define AR5K_CR_TXD1 0x00000010 /* TX Disable for queue 1 on 5210 */ -#define AR5K_CR_RXD 0x00000020 /* RX Disable */ -#define AR5K_CR_SWI 0x00000040 /* Software Interrupt */ - -/* - * RX Descriptor Pointer register - */ -#define AR5K_RXDP 0x000c - -/* - * Configuration and status register - */ -#define AR5K_CFG 0x0014 /* Register Address */ -#define AR5K_CFG_SWTD 0x00000001 /* Byte-swap TX descriptor (for big endian archs) */ -#define AR5K_CFG_SWTB 0x00000002 /* Byte-swap TX buffer */ -#define AR5K_CFG_SWRD 0x00000004 /* Byte-swap RX descriptor */ -#define AR5K_CFG_SWRB 0x00000008 /* Byte-swap RX buffer */ -#define AR5K_CFG_SWRG 0x00000010 /* Byte-swap Register access */ -#define AR5K_CFG_IBSS 0x00000020 /* 0-BSS, 1-IBSS [5211+] */ -#define AR5K_CFG_PHY_OK 0x00000100 /* [5211+] */ -#define AR5K_CFG_EEBS 0x00000200 /* EEPROM is busy */ -#define AR5K_CFG_CLKGD 0x00000400 /* Clock gated (Disable dynamic clock) */ -#define AR5K_CFG_TXCNT 0x00007800 /* Tx frame count (?) [5210] */ -#define AR5K_CFG_TXCNT_S 11 -#define AR5K_CFG_TXFSTAT 0x00008000 /* Tx frame status (?) [5210] */ -#define AR5K_CFG_TXFSTRT 0x00010000 /* [5210] */ -#define AR5K_CFG_PCI_THRES 0x00060000 /* PCI Master req q threshold [5211+] */ -#define AR5K_CFG_PCI_THRES_S 17 - -/* - * Interrupt enable register - */ -#define AR5K_IER 0x0024 /* Register Address */ -#define AR5K_IER_DISABLE 0x00000000 /* Disable card interrupts */ -#define AR5K_IER_ENABLE 0x00000001 /* Enable card interrupts */ - - -/* - * 0x0028 is Beacon Control Register on 5210 - * and first RTS duration register on 5211 - */ - -/* - * Beacon control register [5210] - */ -#define AR5K_BCR 0x0028 /* Register Address */ -#define AR5K_BCR_AP 0x00000000 /* AP mode */ -#define AR5K_BCR_ADHOC 0x00000001 /* Ad-Hoc mode */ -#define AR5K_BCR_BDMAE 0x00000002 /* DMA enable */ -#define AR5K_BCR_TQ1FV 0x00000004 /* Use Queue1 for CAB traffic */ -#define AR5K_BCR_TQ1V 0x00000008 /* Use Queue1 for Beacon traffic */ -#define AR5K_BCR_BCGET 0x00000010 - -/* - * First RTS duration register [5211] - */ -#define AR5K_RTSD0 0x0028 /* Register Address */ -#define AR5K_RTSD0_6 0x000000ff /* 6Mb RTS duration mask (?) */ -#define AR5K_RTSD0_6_S 0 /* 6Mb RTS duration shift (?) */ -#define AR5K_RTSD0_9 0x0000ff00 /* 9Mb*/ -#define AR5K_RTSD0_9_S 8 -#define AR5K_RTSD0_12 0x00ff0000 /* 12Mb*/ -#define AR5K_RTSD0_12_S 16 -#define AR5K_RTSD0_18 0xff000000 /* 16Mb*/ -#define AR5K_RTSD0_18_S 24 - - -/* - * 0x002c is Beacon Status Register on 5210 - * and second RTS duration register on 5211 - */ - -/* - * Beacon status register [5210] - * - * As i can see in ar5k_ar5210_tx_start Reyk uses some of the values of BCR - * for this register, so i guess TQ1V,TQ1FV and BDMAE have the same meaning - * here and SNP/SNAP means "snapshot" (so this register gets synced with BCR). - * So SNAPPEDBCRVALID sould also stand for "snapped BCR -values- valid", so i - * renamed it to SNAPSHOTSVALID to make more sense. I realy have no idea what - * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR. - */ -#define AR5K_BSR 0x002c /* Register Address */ -#define AR5K_BSR_BDLYSW 0x00000001 /* SW Beacon delay (?) */ -#define AR5K_BSR_BDLYDMA 0x00000002 /* DMA Beacon delay (?) */ -#define AR5K_BSR_TXQ1F 0x00000004 /* Beacon queue (1) finished */ -#define AR5K_BSR_ATIMDLY 0x00000008 /* ATIM delay (?) */ -#define AR5K_BSR_SNPADHOC 0x00000100 /* Ad-hoc mode set (?) */ -#define AR5K_BSR_SNPBDMAE 0x00000200 /* Beacon DMA enabled (?) */ -#define AR5K_BSR_SNPTQ1FV 0x00000400 /* Queue1 is used for CAB traffic (?) */ -#define AR5K_BSR_SNPTQ1V 0x00000800 /* Queue1 is used for Beacon traffic (?) */ -#define AR5K_BSR_SNAPSHOTSVALID 0x00001000 /* BCR snapshots are valid (?) */ -#define AR5K_BSR_SWBA_CNT 0x00ff0000 - -/* - * Second RTS duration register [5211] - */ -#define AR5K_RTSD1 0x002c /* Register Address */ -#define AR5K_RTSD1_24 0x000000ff /* 24Mb */ -#define AR5K_RTSD1_24_S 0 -#define AR5K_RTSD1_36 0x0000ff00 /* 36Mb */ -#define AR5K_RTSD1_36_S 8 -#define AR5K_RTSD1_48 0x00ff0000 /* 48Mb */ -#define AR5K_RTSD1_48_S 16 -#define AR5K_RTSD1_54 0xff000000 /* 54Mb */ -#define AR5K_RTSD1_54_S 24 - - -/* - * Transmit configuration register - */ -#define AR5K_TXCFG 0x0030 /* Register Address */ -#define AR5K_TXCFG_SDMAMR 0x00000007 /* DMA size (read) */ -#define AR5K_TXCFG_SDMAMR_S 0 -#define AR5K_TXCFG_B_MODE 0x00000008 /* Set b mode for 5111 (enable 2111) */ -#define AR5K_TXCFG_TXFSTP 0x00000008 /* TX DMA full Stop [5210] */ -#define AR5K_TXCFG_TXFULL 0x000003f0 /* TX Triger level mask */ -#define AR5K_TXCFG_TXFULL_S 4 -#define AR5K_TXCFG_TXFULL_0B 0x00000000 -#define AR5K_TXCFG_TXFULL_64B 0x00000010 -#define AR5K_TXCFG_TXFULL_128B 0x00000020 -#define AR5K_TXCFG_TXFULL_192B 0x00000030 -#define AR5K_TXCFG_TXFULL_256B 0x00000040 -#define AR5K_TXCFG_TXCONT_EN 0x00000080 -#define AR5K_TXCFG_DMASIZE 0x00000100 /* Flag for passing DMA size [5210] */ -#define AR5K_TXCFG_JUMBO_DESC_EN 0x00000400 /* Enable jumbo tx descriptors [5211+] */ -#define AR5K_TXCFG_ADHOC_BCN_ATIM 0x00000800 /* Adhoc Beacon ATIM Policy */ -#define AR5K_TXCFG_ATIM_WINDOW_DEF_DIS 0x00001000 /* Disable ATIM window defer [5211+] */ -#define AR5K_TXCFG_RTSRND 0x00001000 /* [5211+] */ -#define AR5K_TXCFG_FRMPAD_DIS 0x00002000 /* [5211+] */ -#define AR5K_TXCFG_RDY_CBR_DIS 0x00004000 /* Ready time CBR disable [5211+] */ -#define AR5K_TXCFG_JUMBO_FRM_MODE 0x00008000 /* Jumbo frame mode [5211+] */ -#define AR5K_TXCFG_DCU_DBL_BUF_DIS 0x00008000 /* Disable double buffering on DCU */ -#define AR5K_TXCFG_DCU_CACHING_DIS 0x00010000 /* Disable DCU caching */ - -/* - * Receive configuration register - */ -#define AR5K_RXCFG 0x0034 /* Register Address */ -#define AR5K_RXCFG_SDMAMW 0x00000007 /* DMA size (write) */ -#define AR5K_RXCFG_SDMAMW_S 0 -#define AR5K_RXCFG_ZLFDMA 0x00000008 /* Enable Zero-length frame DMA */ -#define AR5K_RXCFG_DEF_ANTENNA 0x00000010 /* Default antenna (?) */ -#define AR5K_RXCFG_JUMBO_RXE 0x00000020 /* Enable jumbo rx descriptors [5211+] */ -#define AR5K_RXCFG_JUMBO_WRAP 0x00000040 /* Wrap jumbo frames [5211+] */ -#define AR5K_RXCFG_SLE_ENTRY 0x00000080 /* Sleep entry policy */ - -/* - * Receive jumbo descriptor last address register - * Only found in 5211 (?) - */ -#define AR5K_RXJLA 0x0038 - -/* - * MIB control register - */ -#define AR5K_MIBC 0x0040 /* Register Address */ -#define AR5K_MIBC_COW 0x00000001 /* Warn test indicator */ -#define AR5K_MIBC_FMC 0x00000002 /* Freeze MIB Counters */ -#define AR5K_MIBC_CMC 0x00000004 /* Clean MIB Counters */ -#define AR5K_MIBC_MCS 0x00000008 /* MIB counter strobe */ - -/* - * Timeout prescale register - */ -#define AR5K_TOPS 0x0044 -#define AR5K_TOPS_M 0x0000ffff - -/* - * Receive timeout register (no frame received) - */ -#define AR5K_RXNOFRM 0x0048 -#define AR5K_RXNOFRM_M 0x000003ff - -/* - * Transmit timeout register (no frame sent) - */ -#define AR5K_TXNOFRM 0x004c -#define AR5K_TXNOFRM_M 0x000003ff -#define AR5K_TXNOFRM_QCU 0x000ffc00 -#define AR5K_TXNOFRM_QCU_S 10 - -/* - * Receive frame gap timeout register - */ -#define AR5K_RPGTO 0x0050 -#define AR5K_RPGTO_M 0x000003ff - -/* - * Receive frame count limit register - */ -#define AR5K_RFCNT 0x0054 -#define AR5K_RFCNT_M 0x0000001f /* [5211+] (?) */ -#define AR5K_RFCNT_RFCL 0x0000000f /* [5210] */ - -/* - * Misc settings register - * (reserved0-3) - */ -#define AR5K_MISC 0x0058 /* Register Address */ -#define AR5K_MISC_DMA_OBS_M 0x000001e0 -#define AR5K_MISC_DMA_OBS_S 5 -#define AR5K_MISC_MISC_OBS_M 0x00000e00 -#define AR5K_MISC_MISC_OBS_S 9 -#define AR5K_MISC_MAC_OBS_LSB_M 0x00007000 -#define AR5K_MISC_MAC_OBS_LSB_S 12 -#define AR5K_MISC_MAC_OBS_MSB_M 0x00038000 -#define AR5K_MISC_MAC_OBS_MSB_S 15 -#define AR5K_MISC_LED_DECAY 0x001c0000 /* [5210] */ -#define AR5K_MISC_LED_BLINK 0x00e00000 /* [5210] */ - -/* - * QCU/DCU clock gating register (5311) - * (reserved4-5) - */ -#define AR5K_QCUDCU_CLKGT 0x005c /* Register Address (?) */ -#define AR5K_QCUDCU_CLKGT_QCU 0x0000ffff /* Mask for QCU clock */ -#define AR5K_QCUDCU_CLKGT_DCU 0x07ff0000 /* Mask for DCU clock */ - -/* - * Interrupt Status Registers - * - * For 5210 there is only one status register but for - * 5211/5212 we have one primary and 4 secondary registers. - * So we have AR5K_ISR for 5210 and AR5K_PISR /SISRx for 5211/5212. - * Most of these bits are common for all chipsets. - */ -#define AR5K_ISR 0x001c /* Register Address [5210] */ -#define AR5K_PISR 0x0080 /* Register Address [5211+] */ -#define AR5K_ISR_RXOK 0x00000001 /* Frame successfuly recieved */ -#define AR5K_ISR_RXDESC 0x00000002 /* RX descriptor request */ -#define AR5K_ISR_RXERR 0x00000004 /* Receive error */ -#define AR5K_ISR_RXNOFRM 0x00000008 /* No frame received (receive timeout) */ -#define AR5K_ISR_RXEOL 0x00000010 /* Empty RX descriptor */ -#define AR5K_ISR_RXORN 0x00000020 /* Receive FIFO overrun */ -#define AR5K_ISR_TXOK 0x00000040 /* Frame successfuly transmited */ -#define AR5K_ISR_TXDESC 0x00000080 /* TX descriptor request */ -#define AR5K_ISR_TXERR 0x00000100 /* Transmit error */ -#define AR5K_ISR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout) */ -#define AR5K_ISR_TXEOL 0x00000400 /* Empty TX descriptor */ -#define AR5K_ISR_TXURN 0x00000800 /* Transmit FIFO underrun */ -#define AR5K_ISR_MIB 0x00001000 /* Update MIB counters */ -#define AR5K_ISR_SWI 0x00002000 /* Software interrupt */ -#define AR5K_ISR_RXPHY 0x00004000 /* PHY error */ -#define AR5K_ISR_RXKCM 0x00008000 /* RX Key cache miss */ -#define AR5K_ISR_SWBA 0x00010000 /* Software beacon alert */ -#define AR5K_ISR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ -#define AR5K_ISR_BMISS 0x00040000 /* Beacon missed */ -#define AR5K_ISR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ -#define AR5K_ISR_BNR 0x00100000 /* Beacon not ready [5211+] */ -#define AR5K_ISR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ -#define AR5K_ISR_RXCHIRP 0x00200000 /* CHIRP Received [5212+] */ -#define AR5K_ISR_SSERR 0x00200000 /* Signaled System Error [5210] */ -#define AR5K_ISR_DPERR 0x00400000 /* Det par Error (?) [5210] */ -#define AR5K_ISR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ -#define AR5K_ISR_TIM 0x00800000 /* [5211+] */ -#define AR5K_ISR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, - CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ -#define AR5K_ISR_GPIO 0x01000000 /* GPIO (rf kill) */ -#define AR5K_ISR_QCBRORN 0x02000000 /* QCU CBR overrun [5211+] */ -#define AR5K_ISR_QCBRURN 0x04000000 /* QCU CBR underrun [5211+] */ -#define AR5K_ISR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ - -/* - * Secondary status registers [5211+] (0 - 4) - * - * These give the status for each QCU, only QCUs 0-9 are - * represented. - */ -#define AR5K_SISR0 0x0084 /* Register Address [5211+] */ -#define AR5K_SISR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ -#define AR5K_SISR0_QCU_TXOK_S 0 -#define AR5K_SISR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ -#define AR5K_SISR0_QCU_TXDESC_S 16 - -#define AR5K_SISR1 0x0088 /* Register Address [5211+] */ -#define AR5K_SISR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ -#define AR5K_SISR1_QCU_TXERR_S 0 -#define AR5K_SISR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ -#define AR5K_SISR1_QCU_TXEOL_S 16 - -#define AR5K_SISR2 0x008c /* Register Address [5211+] */ -#define AR5K_SISR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ -#define AR5K_SISR2_QCU_TXURN_S 0 -#define AR5K_SISR2_MCABT 0x00010000 /* Master Cycle Abort */ -#define AR5K_SISR2_SSERR 0x00020000 /* Signaled System Error */ -#define AR5K_SISR2_DPERR 0x00040000 /* Bus parity error */ -#define AR5K_SISR2_TIM 0x01000000 /* [5212+] */ -#define AR5K_SISR2_CAB_END 0x02000000 /* [5212+] */ -#define AR5K_SISR2_DTIM_SYNC 0x04000000 /* DTIM sync lost [5212+] */ -#define AR5K_SISR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ -#define AR5K_SISR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ -#define AR5K_SISR2_DTIM 0x20000000 /* [5212+] */ -#define AR5K_SISR2_TSFOOR 0x80000000 /* TSF OOR (?) */ - -#define AR5K_SISR3 0x0090 /* Register Address [5211+] */ -#define AR5K_SISR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ -#define AR5K_SISR3_QCBRORN_S 0 -#define AR5K_SISR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ -#define AR5K_SISR3_QCBRURN_S 16 - -#define AR5K_SISR4 0x0094 /* Register Address [5211+] */ -#define AR5K_SISR4_QTRIG 0x000003ff /* Mask for QTRIG */ -#define AR5K_SISR4_QTRIG_S 0 - -/* - * Shadow read-and-clear interrupt status registers [5211+] - */ -#define AR5K_RAC_PISR 0x00c0 /* Read and clear PISR */ -#define AR5K_RAC_SISR0 0x00c4 /* Read and clear SISR0 */ -#define AR5K_RAC_SISR1 0x00c8 /* Read and clear SISR1 */ -#define AR5K_RAC_SISR2 0x00cc /* Read and clear SISR2 */ -#define AR5K_RAC_SISR3 0x00d0 /* Read and clear SISR3 */ -#define AR5K_RAC_SISR4 0x00d4 /* Read and clear SISR4 */ - -/* - * Interrupt Mask Registers - * - * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary - * (AR5K_PIMR) and 4 secondary IMRs (AR5K_SIMRx). Note that ISR/IMR flags match. - */ -#define AR5K_IMR 0x0020 /* Register Address [5210] */ -#define AR5K_PIMR 0x00a0 /* Register Address [5211+] */ -#define AR5K_IMR_RXOK 0x00000001 /* Frame successfuly recieved*/ -#define AR5K_IMR_RXDESC 0x00000002 /* RX descriptor request*/ -#define AR5K_IMR_RXERR 0x00000004 /* Receive error*/ -#define AR5K_IMR_RXNOFRM 0x00000008 /* No frame received (receive timeout)*/ -#define AR5K_IMR_RXEOL 0x00000010 /* Empty RX descriptor*/ -#define AR5K_IMR_RXORN 0x00000020 /* Receive FIFO overrun*/ -#define AR5K_IMR_TXOK 0x00000040 /* Frame successfuly transmited*/ -#define AR5K_IMR_TXDESC 0x00000080 /* TX descriptor request*/ -#define AR5K_IMR_TXERR 0x00000100 /* Transmit error*/ -#define AR5K_IMR_TXNOFRM 0x00000200 /* No frame transmited (transmit timeout)*/ -#define AR5K_IMR_TXEOL 0x00000400 /* Empty TX descriptor*/ -#define AR5K_IMR_TXURN 0x00000800 /* Transmit FIFO underrun*/ -#define AR5K_IMR_MIB 0x00001000 /* Update MIB counters*/ -#define AR5K_IMR_SWI 0x00002000 /* Software interrupt */ -#define AR5K_IMR_RXPHY 0x00004000 /* PHY error*/ -#define AR5K_IMR_RXKCM 0x00008000 /* RX Key cache miss */ -#define AR5K_IMR_SWBA 0x00010000 /* Software beacon alert*/ -#define AR5K_IMR_BRSSI 0x00020000 /* Beacon rssi below threshold (?) */ -#define AR5K_IMR_BMISS 0x00040000 /* Beacon missed*/ -#define AR5K_IMR_HIUERR 0x00080000 /* Host Interface Unit error [5211+] */ -#define AR5K_IMR_BNR 0x00100000 /* Beacon not ready [5211+] */ -#define AR5K_IMR_MCABT 0x00100000 /* Master Cycle Abort [5210] */ -#define AR5K_IMR_RXCHIRP 0x00200000 /* CHIRP Received [5212+]*/ -#define AR5K_IMR_SSERR 0x00200000 /* Signaled System Error [5210] */ -#define AR5K_IMR_DPERR 0x00400000 /* Det par Error (?) [5210] */ -#define AR5K_IMR_RXDOPPLER 0x00400000 /* Doppler chirp received [5212+] */ -#define AR5K_IMR_TIM 0x00800000 /* [5211+] */ -#define AR5K_IMR_BCNMISC 0x00800000 /* 'or' of TIM, CAB_END, DTIM_SYNC, BCN_TIMEOUT, - CAB_TIMEOUT and DTIM bits from SISR2 [5212+] */ -#define AR5K_IMR_GPIO 0x01000000 /* GPIO (rf kill)*/ -#define AR5K_IMR_QCBRORN 0x02000000 /* QCU CBR overrun (?) [5211+] */ -#define AR5K_IMR_QCBRURN 0x04000000 /* QCU CBR underrun (?) [5211+] */ -#define AR5K_IMR_QTRIG 0x08000000 /* QCU scheduling trigger [5211+] */ - -/* - * Secondary interrupt mask registers [5211+] (0 - 4) - */ -#define AR5K_SIMR0 0x00a4 /* Register Address [5211+] */ -#define AR5K_SIMR0_QCU_TXOK 0x000003ff /* Mask for QCU_TXOK */ -#define AR5K_SIMR0_QCU_TXOK_S 0 -#define AR5K_SIMR0_QCU_TXDESC 0x03ff0000 /* Mask for QCU_TXDESC */ -#define AR5K_SIMR0_QCU_TXDESC_S 16 - -#define AR5K_SIMR1 0x00a8 /* Register Address [5211+] */ -#define AR5K_SIMR1_QCU_TXERR 0x000003ff /* Mask for QCU_TXERR */ -#define AR5K_SIMR1_QCU_TXERR_S 0 -#define AR5K_SIMR1_QCU_TXEOL 0x03ff0000 /* Mask for QCU_TXEOL */ -#define AR5K_SIMR1_QCU_TXEOL_S 16 - -#define AR5K_SIMR2 0x00ac /* Register Address [5211+] */ -#define AR5K_SIMR2_QCU_TXURN 0x000003ff /* Mask for QCU_TXURN */ -#define AR5K_SIMR2_QCU_TXURN_S 0 -#define AR5K_SIMR2_MCABT 0x00010000 /* Master Cycle Abort */ -#define AR5K_SIMR2_SSERR 0x00020000 /* Signaled System Error */ -#define AR5K_SIMR2_DPERR 0x00040000 /* Bus parity error */ -#define AR5K_SIMR2_TIM 0x01000000 /* [5212+] */ -#define AR5K_SIMR2_CAB_END 0x02000000 /* [5212+] */ -#define AR5K_SIMR2_DTIM_SYNC 0x04000000 /* DTIM Sync lost [5212+] */ -#define AR5K_SIMR2_BCN_TIMEOUT 0x08000000 /* Beacon Timeout [5212+] */ -#define AR5K_SIMR2_CAB_TIMEOUT 0x10000000 /* CAB Timeout [5212+] */ -#define AR5K_SIMR2_DTIM 0x20000000 /* [5212+] */ -#define AR5K_SIMR2_TSFOOR 0x80000000 /* TSF OOR (?) */ - -#define AR5K_SIMR3 0x00b0 /* Register Address [5211+] */ -#define AR5K_SIMR3_QCBRORN 0x000003ff /* Mask for QCBRORN */ -#define AR5K_SIMR3_QCBRORN_S 0 -#define AR5K_SIMR3_QCBRURN 0x03ff0000 /* Mask for QCBRURN */ -#define AR5K_SIMR3_QCBRURN_S 16 - -#define AR5K_SIMR4 0x00b4 /* Register Address [5211+] */ -#define AR5K_SIMR4_QTRIG 0x000003ff /* Mask for QTRIG */ -#define AR5K_SIMR4_QTRIG_S 0 - -/* - * DMA Debug registers 0-7 - * 0xe0 - 0xfc - */ - -/* - * Decompression mask registers [5212+] - */ -#define AR5K_DCM_ADDR 0x0400 /*Decompression mask address (index) */ -#define AR5K_DCM_DATA 0x0404 /*Decompression mask data */ - -/* - * Wake On Wireless pattern control register [5212+] - */ -#define AR5K_WOW_PCFG 0x0410 /* Register Address */ -#define AR5K_WOW_PCFG_PAT_MATCH_EN 0x00000001 /* Pattern match enable */ -#define AR5K_WOW_PCFG_LONG_FRAME_POL 0x00000002 /* Long frame policy */ -#define AR5K_WOW_PCFG_WOBMISS 0x00000004 /* Wake on bea(con) miss (?) */ -#define AR5K_WOW_PCFG_PAT_0_EN 0x00000100 /* Enable pattern 0 */ -#define AR5K_WOW_PCFG_PAT_1_EN 0x00000200 /* Enable pattern 1 */ -#define AR5K_WOW_PCFG_PAT_2_EN 0x00000400 /* Enable pattern 2 */ -#define AR5K_WOW_PCFG_PAT_3_EN 0x00000800 /* Enable pattern 3 */ -#define AR5K_WOW_PCFG_PAT_4_EN 0x00001000 /* Enable pattern 4 */ -#define AR5K_WOW_PCFG_PAT_5_EN 0x00002000 /* Enable pattern 5 */ - -/* - * Wake On Wireless pattern index register (?) [5212+] - */ -#define AR5K_WOW_PAT_IDX 0x0414 - -/* - * Wake On Wireless pattern data register [5212+] - */ -#define AR5K_WOW_PAT_DATA 0x0418 /* Register Address */ -#define AR5K_WOW_PAT_DATA_0_3_V 0x00000001 /* Pattern 0, 3 value */ -#define AR5K_WOW_PAT_DATA_1_4_V 0x00000100 /* Pattern 1, 4 value */ -#define AR5K_WOW_PAT_DATA_2_5_V 0x00010000 /* Pattern 2, 5 value */ -#define AR5K_WOW_PAT_DATA_0_3_M 0x01000000 /* Pattern 0, 3 mask */ -#define AR5K_WOW_PAT_DATA_1_4_M 0x04000000 /* Pattern 1, 4 mask */ -#define AR5K_WOW_PAT_DATA_2_5_M 0x10000000 /* Pattern 2, 5 mask */ - -/* - * Decompression configuration registers [5212+] - */ -#define AR5K_DCCFG 0x0420 /* Register Address */ -#define AR5K_DCCFG_GLOBAL_EN 0x00000001 /* Enable decompression on all queues */ -#define AR5K_DCCFG_BYPASS_EN 0x00000002 /* Bypass decompression */ -#define AR5K_DCCFG_BCAST_EN 0x00000004 /* Enable decompression for bcast frames */ -#define AR5K_DCCFG_MCAST_EN 0x00000008 /* Enable decompression for mcast frames */ - -/* - * Compression configuration registers [5212+] - */ -#define AR5K_CCFG 0x0600 /* Register Address */ -#define AR5K_CCFG_WINDOW_SIZE 0x00000007 /* Compression window size */ -#define AR5K_CCFG_CPC_EN 0x00000008 /* Enable performance counters */ - -#define AR5K_CCFG_CCU 0x0604 /* Register Address */ -#define AR5K_CCFG_CCU_CUP_EN 0x00000001 /* CCU Catchup enable */ -#define AR5K_CCFG_CCU_CREDIT 0x00000002 /* CCU Credit (field) */ -#define AR5K_CCFG_CCU_CD_THRES 0x00000080 /* CCU Cyc(lic?) debt threshold (field) */ -#define AR5K_CCFG_CCU_CUP_LCNT 0x00010000 /* CCU Catchup lit(?) count */ -#define AR5K_CCFG_CCU_INIT 0x00100200 /* Initial value during reset */ - -/* - * Compression performance counter registers [5212+] - */ -#define AR5K_CPC0 0x0610 /* Compression performance counter 0 */ -#define AR5K_CPC1 0x0614 /* Compression performance counter 1*/ -#define AR5K_CPC2 0x0618 /* Compression performance counter 2 */ -#define AR5K_CPC3 0x061c /* Compression performance counter 3 */ -#define AR5K_CPCOVF 0x0620 /* Compression performance overflow */ - - -/* - * Queue control unit (QCU) registers [5211+] - * - * Card has 12 TX Queues but i see that only 0-9 are used (?) - * both in binary HAL (see ah.h) and ar5k. Each queue has it's own - * TXDP at addresses 0x0800 - 0x082c, a CBR (Constant Bit Rate) - * configuration register (0x08c0 - 0x08ec), a ready time configuration - * register (0x0900 - 0x092c), a misc configuration register (0x09c0 - - * 0x09ec) and a status register (0x0a00 - 0x0a2c). We also have some - * global registers, QCU transmit enable/disable and "one shot arm (?)" - * set/clear, which contain status for all queues (we shift by 1 for each - * queue). To access these registers easily we define some macros here - * that are used inside HAL. For more infos check out *_tx_queue functs. - */ - -/* - * Generic QCU Register access macros - */ -#define AR5K_QUEUE_REG(_r, _q) (((_q) << 2) + _r) -#define AR5K_QCU_GLOBAL_READ(_r, _q) (AR5K_REG_READ(_r) & (1 << _q)) -#define AR5K_QCU_GLOBAL_WRITE(_r, _q) AR5K_REG_WRITE(_r, (1 << _q)) - -/* - * QCU Transmit descriptor pointer registers - */ -#define AR5K_QCU_TXDP_BASE 0x0800 /* Register Address - Queue0 TXDP */ -#define AR5K_QUEUE_TXDP(_q) AR5K_QUEUE_REG(AR5K_QCU_TXDP_BASE, _q) - -/* - * QCU Transmit enable register - */ -#define AR5K_QCU_TXE 0x0840 -#define AR5K_ENABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXE, _q) -#define AR5K_QUEUE_ENABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXE, _q) - -/* - * QCU Transmit disable register - */ -#define AR5K_QCU_TXD 0x0880 -#define AR5K_DISABLE_QUEUE(_q) AR5K_QCU_GLOBAL_WRITE(AR5K_QCU_TXD, _q) -#define AR5K_QUEUE_DISABLED(_q) AR5K_QCU_GLOBAL_READ(AR5K_QCU_TXD, _q) - -/* - * QCU Constant Bit Rate configuration registers - */ -#define AR5K_QCU_CBRCFG_BASE 0x08c0 /* Register Address - Queue0 CBRCFG */ -#define AR5K_QCU_CBRCFG_INTVAL 0x00ffffff /* CBR Interval mask */ -#define AR5K_QCU_CBRCFG_INTVAL_S 0 -#define AR5K_QCU_CBRCFG_ORN_THRES 0xff000000 /* CBR overrun threshold mask */ -#define AR5K_QCU_CBRCFG_ORN_THRES_S 24 -#define AR5K_QUEUE_CBRCFG(_q) AR5K_QUEUE_REG(AR5K_QCU_CBRCFG_BASE, _q) - -/* - * QCU Ready time configuration registers - */ -#define AR5K_QCU_RDYTIMECFG_BASE 0x0900 /* Register Address - Queue0 RDYTIMECFG */ -#define AR5K_QCU_RDYTIMECFG_INTVAL 0x00ffffff /* Ready time interval mask */ -#define AR5K_QCU_RDYTIMECFG_INTVAL_S 0 -#define AR5K_QCU_RDYTIMECFG_ENABLE 0x01000000 /* Ready time enable mask */ -#define AR5K_QUEUE_RDYTIMECFG(_q) AR5K_QUEUE_REG(AR5K_QCU_RDYTIMECFG_BASE, _q) - -/* - * QCU one shot arm set registers - */ -#define AR5K_QCU_ONESHOTARM_SET 0x0940 /* Register Address -QCU "one shot arm set (?)" */ -#define AR5K_QCU_ONESHOTARM_SET_M 0x0000ffff - -/* - * QCU one shot arm clear registers - */ -#define AR5K_QCU_ONESHOTARM_CLEAR 0x0980 /* Register Address -QCU "one shot arm clear (?)" */ -#define AR5K_QCU_ONESHOTARM_CLEAR_M 0x0000ffff - -/* - * QCU misc registers - */ -#define AR5K_QCU_MISC_BASE 0x09c0 /* Register Address -Queue0 MISC */ -#define AR5K_QCU_MISC_FRSHED_M 0x0000000f /* Frame sheduling mask */ -#define AR5K_QCU_MISC_FRSHED_ASAP 0 /* ASAP */ -#define AR5K_QCU_MISC_FRSHED_CBR 1 /* Constant Bit Rate */ -#define AR5K_QCU_MISC_FRSHED_DBA_GT 2 /* DMA Beacon alert gated */ -#define AR5K_QCU_MISC_FRSHED_TIM_GT 3 /* TIMT gated */ -#define AR5K_QCU_MISC_FRSHED_BCN_SENT_GT 4 /* Beacon sent gated */ -#define AR5K_QCU_MISC_ONESHOT_ENABLE 0x00000010 /* Oneshot enable */ -#define AR5K_QCU_MISC_CBREXP_DIS 0x00000020 /* Disable CBR expired counter (normal queue) */ -#define AR5K_QCU_MISC_CBREXP_BCN_DIS 0x00000040 /* Disable CBR expired counter (beacon queue) */ -#define AR5K_QCU_MISC_BCN_ENABLE 0x00000080 /* Enable Beacon use */ -#define AR5K_QCU_MISC_CBR_THRES_ENABLE 0x00000100 /* CBR expired threshold enabled */ -#define AR5K_QCU_MISC_RDY_VEOL_POLICY 0x00000200 /* TXE reset when RDYTIME expired or VEOL */ -#define AR5K_QCU_MISC_CBR_RESET_CNT 0x00000400 /* CBR threshold (counter) reset */ -#define AR5K_QCU_MISC_DCU_EARLY 0x00000800 /* DCU early termination */ -#define AR5K_QCU_MISC_DCU_CMP_EN 0x00001000 /* Enable frame compression */ -#define AR5K_QUEUE_MISC(_q) AR5K_QUEUE_REG(AR5K_QCU_MISC_BASE, _q) - - -/* - * QCU status registers - */ -#define AR5K_QCU_STS_BASE 0x0a00 /* Register Address - Queue0 STS */ -#define AR5K_QCU_STS_FRMPENDCNT 0x00000003 /* Frames pending counter */ -#define AR5K_QCU_STS_CBREXPCNT 0x0000ff00 /* CBR expired counter */ -#define AR5K_QUEUE_STATUS(_q) AR5K_QUEUE_REG(AR5K_QCU_STS_BASE, _q) - -/* - * QCU ready time shutdown register - */ -#define AR5K_QCU_RDYTIMESHDN 0x0a40 -#define AR5K_QCU_RDYTIMESHDN_M 0x000003ff - -/* - * QCU compression buffer base registers [5212+] - */ -#define AR5K_QCU_CBB_SELECT 0x0b00 -#define AR5K_QCU_CBB_ADDR 0x0b04 -#define AR5K_QCU_CBB_ADDR_S 9 - -/* - * QCU compression buffer configuration register [5212+] - * (buffer size) - */ -#define AR5K_QCU_CBCFG 0x0b08 - - - -/* - * Distributed Coordination Function (DCF) control unit (DCU) - * registers [5211+] - * - * These registers control the various characteristics of each queue - * for 802.11e (WME) combatibility so they go together with - * QCU registers in pairs. For each queue we have a QCU mask register, - * (0x1000 - 0x102c), a local-IFS settings register (0x1040 - 0x106c), - * a retry limit register (0x1080 - 0x10ac), a channel time register - * (0x10c0 - 0x10ec), a misc-settings register (0x1100 - 0x112c) and - * a sequence number register (0x1140 - 0x116c). It seems that "global" - * registers here afect all queues (see use of DCU_GBL_IFS_SLOT in ar5k). - * We use the same macros here for easier register access. - * - */ - -/* - * DCU QCU mask registers - */ -#define AR5K_DCU_QCUMASK_BASE 0x1000 /* Register Address -Queue0 DCU_QCUMASK */ -#define AR5K_DCU_QCUMASK_M 0x000003ff -#define AR5K_QUEUE_QCUMASK(_q) AR5K_QUEUE_REG(AR5K_DCU_QCUMASK_BASE, _q) - -/* - * DCU local Inter Frame Space settings register - */ -#define AR5K_DCU_LCL_IFS_BASE 0x1040 /* Register Address -Queue0 DCU_LCL_IFS */ -#define AR5K_DCU_LCL_IFS_CW_MIN 0x000003ff /* Minimum Contention Window */ -#define AR5K_DCU_LCL_IFS_CW_MIN_S 0 -#define AR5K_DCU_LCL_IFS_CW_MAX 0x000ffc00 /* Maximum Contention Window */ -#define AR5K_DCU_LCL_IFS_CW_MAX_S 10 -#define AR5K_DCU_LCL_IFS_AIFS 0x0ff00000 /* Arbitrated Interframe Space */ -#define AR5K_DCU_LCL_IFS_AIFS_S 20 -#define AR5K_DCU_LCL_IFS_AIFS_MAX 0xfc /* Anything above that can cause DCU to hang */ -#define AR5K_QUEUE_DFS_LOCAL_IFS(_q) AR5K_QUEUE_REG(AR5K_DCU_LCL_IFS_BASE, _q) - -/* - * DCU retry limit registers - */ -#define AR5K_DCU_RETRY_LMT_BASE 0x1080 /* Register Address -Queue0 DCU_RETRY_LMT */ -#define AR5K_DCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ -#define AR5K_DCU_RETRY_LMT_SH_RETRY_S 0 -#define AR5K_DCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry limit mask */ -#define AR5K_DCU_RETRY_LMT_LG_RETRY_S 4 -#define AR5K_DCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask (?) */ -#define AR5K_DCU_RETRY_LMT_SSH_RETRY_S 8 -#define AR5K_DCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask (?) */ -#define AR5K_DCU_RETRY_LMT_SLG_RETRY_S 14 -#define AR5K_QUEUE_DFS_RETRY_LIMIT(_q) AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q) - -/* - * DCU channel time registers - */ -#define AR5K_DCU_CHAN_TIME_BASE 0x10c0 /* Register Address -Queue0 DCU_CHAN_TIME */ -#define AR5K_DCU_CHAN_TIME_DUR 0x000fffff /* Channel time duration */ -#define AR5K_DCU_CHAN_TIME_DUR_S 0 -#define AR5K_DCU_CHAN_TIME_ENABLE 0x00100000 /* Enable channel time */ -#define AR5K_QUEUE_DFS_CHANNEL_TIME(_q) AR5K_QUEUE_REG(AR5K_DCU_CHAN_TIME_BASE, _q) - -/* - * DCU misc registers [5211+] - * - * Note: Arbiter lockout control controls the - * behaviour on low priority queues when we have multiple queues - * with pending frames. Intra-frame lockout means we wait until - * the queue's current frame transmits (with post frame backoff and bursting) - * before we transmit anything else and global lockout means we - * wait for the whole queue to finish before higher priority queues - * can transmit (this is used on beacon and CAB queues). - * No lockout means there is no special handling. - */ -#define AR5K_DCU_MISC_BASE 0x1100 /* Register Address -Queue0 DCU_MISC */ -#define AR5K_DCU_MISC_BACKOFF 0x0000003f /* Mask for backoff threshold */ -#define AR5K_DCU_MISC_ETS_RTS_POL 0x00000040 /* End of transmission series - station RTS/data failure count - reset policy (?) */ -#define AR5K_DCU_MISC_ETS_CW_POL 0x00000080 /* End of transmission series - CW reset policy */ -#define AR5K_DCU_MISC_FRAG_WAIT 0x00000100 /* Wait for next fragment */ -#define AR5K_DCU_MISC_BACKOFF_FRAG 0x00000200 /* Enable backoff while bursting */ -#define AR5K_DCU_MISC_HCFPOLL_ENABLE 0x00000800 /* CF - Poll enable */ -#define AR5K_DCU_MISC_BACKOFF_PERSIST 0x00001000 /* Persistent backoff */ -#define AR5K_DCU_MISC_FRMPRFTCH_ENABLE 0x00002000 /* Enable frame pre-fetch */ -#define AR5K_DCU_MISC_VIRTCOL 0x0000c000 /* Mask for Virtual Collision (?) */ -#define AR5K_DCU_MISC_VIRTCOL_NORMAL 0 -#define AR5K_DCU_MISC_VIRTCOL_IGNORE 1 -#define AR5K_DCU_MISC_BCN_ENABLE 0x00010000 /* Enable Beacon use */ -#define AR5K_DCU_MISC_ARBLOCK_CTL 0x00060000 /* Arbiter lockout control mask */ -#define AR5K_DCU_MISC_ARBLOCK_CTL_S 17 -#define AR5K_DCU_MISC_ARBLOCK_CTL_NONE 0 /* No arbiter lockout */ -#define AR5K_DCU_MISC_ARBLOCK_CTL_INTFRM 1 /* Intra-frame lockout */ -#define AR5K_DCU_MISC_ARBLOCK_CTL_GLOBAL 2 /* Global lockout */ -#define AR5K_DCU_MISC_ARBLOCK_IGNORE 0x00080000 /* Ignore Arbiter lockout */ -#define AR5K_DCU_MISC_SEQ_NUM_INCR_DIS 0x00100000 /* Disable sequence number increment */ -#define AR5K_DCU_MISC_POST_FR_BKOFF_DIS 0x00200000 /* Disable post-frame backoff */ -#define AR5K_DCU_MISC_VIRT_COLL_POLICY 0x00400000 /* Virtual Collision cw policy */ -#define AR5K_DCU_MISC_BLOWN_IFS_POLICY 0x00800000 /* Blown IFS policy (?) */ -#define AR5K_DCU_MISC_SEQNUM_CTL 0x01000000 /* Sequence number control (?) */ -#define AR5K_QUEUE_DFS_MISC(_q) AR5K_QUEUE_REG(AR5K_DCU_MISC_BASE, _q) - -/* - * DCU frame sequence number registers - */ -#define AR5K_DCU_SEQNUM_BASE 0x1140 -#define AR5K_DCU_SEQNUM_M 0x00000fff -#define AR5K_QUEUE_DCU_SEQNUM(_q) AR5K_QUEUE_REG(AR5K_DCU_SEQNUM_BASE, _q) - -/* - * DCU global IFS SIFS register - */ -#define AR5K_DCU_GBL_IFS_SIFS 0x1030 -#define AR5K_DCU_GBL_IFS_SIFS_M 0x0000ffff - -/* - * DCU global IFS slot interval register - */ -#define AR5K_DCU_GBL_IFS_SLOT 0x1070 -#define AR5K_DCU_GBL_IFS_SLOT_M 0x0000ffff - -/* - * DCU global IFS EIFS register - */ -#define AR5K_DCU_GBL_IFS_EIFS 0x10b0 -#define AR5K_DCU_GBL_IFS_EIFS_M 0x0000ffff - -/* - * DCU global IFS misc register - * - * LFSR stands for Linear Feedback Shift Register - * and it's used for generating pseudo-random - * number sequences. - * - * (If i understand corectly, random numbers are - * used for idle sensing -multiplied with cwmin/max etc-) - */ -#define AR5K_DCU_GBL_IFS_MISC 0x10f0 /* Register Address */ -#define AR5K_DCU_GBL_IFS_MISC_LFSR_SLICE 0x00000007 /* LFSR Slice Select */ -#define AR5K_DCU_GBL_IFS_MISC_TURBO_MODE 0x00000008 /* Turbo mode */ -#define AR5K_DCU_GBL_IFS_MISC_SIFS_DUR_USEC 0x000003f0 /* SIFS Duration mask */ -#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR 0x000ffc00 /* USEC Duration mask */ -#define AR5K_DCU_GBL_IFS_MISC_USEC_DUR_S 10 -#define AR5K_DCU_GBL_IFS_MISC_DCU_ARB_DELAY 0x00300000 /* DCU Arbiter delay mask */ -#define AR5K_DCU_GBL_IFS_MISC_SIFS_CNT_RST 0x00400000 /* SIFS cnt reset policy (?) */ -#define AR5K_DCU_GBL_IFS_MISC_AIFS_CNT_RST 0x00800000 /* AIFS cnt reset policy (?) */ -#define AR5K_DCU_GBL_IFS_MISC_RND_LFSR_SL_DIS 0x01000000 /* Disable random LFSR slice */ - -/* - * DCU frame prefetch control register - */ -#define AR5K_DCU_FP 0x1230 /* Register Address */ -#define AR5K_DCU_FP_NOBURST_DCU_EN 0x00000001 /* Enable non-burst prefetch on DCU (?) */ -#define AR5K_DCU_FP_NOBURST_EN 0x00000010 /* Enable non-burst prefetch (?) */ -#define AR5K_DCU_FP_BURST_DCU_EN 0x00000020 /* Enable burst prefetch on DCU (?) */ - -/* - * DCU transmit pause control/status register - */ -#define AR5K_DCU_TXP 0x1270 /* Register Address */ -#define AR5K_DCU_TXP_M 0x000003ff /* Tx pause mask */ -#define AR5K_DCU_TXP_STATUS 0x00010000 /* Tx pause status */ - -/* - * DCU transmit filter table 0 (32 entries) - * each entry contains a 32bit slice of the - * 128bit tx filter for each DCU (4 slices per DCU) - */ -#define AR5K_DCU_TX_FILTER_0_BASE 0x1038 -#define AR5K_DCU_TX_FILTER_0(_n) (AR5K_DCU_TX_FILTER_0_BASE + (_n * 64)) - -/* - * DCU transmit filter table 1 (16 entries) - */ -#define AR5K_DCU_TX_FILTER_1_BASE 0x103c -#define AR5K_DCU_TX_FILTER_1(_n) (AR5K_DCU_TX_FILTER_1_BASE + (_n * 64)) - -/* - * DCU clear transmit filter register - */ -#define AR5K_DCU_TX_FILTER_CLR 0x143c - -/* - * DCU set transmit filter register - */ -#define AR5K_DCU_TX_FILTER_SET 0x147c - -/* - * Reset control register - */ -#define AR5K_RESET_CTL 0x4000 /* Register Address */ -#define AR5K_RESET_CTL_PCU 0x00000001 /* Protocol Control Unit reset */ -#define AR5K_RESET_CTL_DMA 0x00000002 /* DMA (Rx/Tx) reset [5210] */ -#define AR5K_RESET_CTL_BASEBAND 0x00000002 /* Baseband reset [5211+] */ -#define AR5K_RESET_CTL_MAC 0x00000004 /* MAC reset (PCU+Baseband ?) [5210] */ -#define AR5K_RESET_CTL_PHY 0x00000008 /* PHY reset [5210] */ -#define AR5K_RESET_CTL_PCI 0x00000010 /* PCI Core reset (interrupts etc) */ - -/* - * Sleep control register - */ -#define AR5K_SLEEP_CTL 0x4004 /* Register Address */ -#define AR5K_SLEEP_CTL_SLDUR 0x0000ffff /* Sleep duration mask */ -#define AR5K_SLEEP_CTL_SLDUR_S 0 -#define AR5K_SLEEP_CTL_SLE 0x00030000 /* Sleep enable mask */ -#define AR5K_SLEEP_CTL_SLE_S 16 -#define AR5K_SLEEP_CTL_SLE_WAKE 0x00000000 /* Force chip awake */ -#define AR5K_SLEEP_CTL_SLE_SLP 0x00010000 /* Force chip sleep */ -#define AR5K_SLEEP_CTL_SLE_ALLOW 0x00020000 /* Normal sleep policy */ -#define AR5K_SLEEP_CTL_SLE_UNITS 0x00000008 /* [5211+] */ -#define AR5K_SLEEP_CTL_DUR_TIM_POL 0x00040000 /* Sleep duration timing policy */ -#define AR5K_SLEEP_CTL_DUR_WRITE_POL 0x00080000 /* Sleep duration write policy */ -#define AR5K_SLEEP_CTL_SLE_POL 0x00100000 /* Sleep policy mode */ - -/* - * Interrupt pending register - */ -#define AR5K_INTPEND 0x4008 -#define AR5K_INTPEND_M 0x00000001 - -/* - * Sleep force register - */ -#define AR5K_SFR 0x400c -#define AR5K_SFR_EN 0x00000001 - -/* - * PCI configuration register - * TODO: Fix LED stuff - */ -#define AR5K_PCICFG 0x4010 /* Register Address */ -#define AR5K_PCICFG_EEAE 0x00000001 /* Eeprom access enable [5210] */ -#define AR5K_PCICFG_SLEEP_CLOCK_EN 0x00000002 /* Enable sleep clock */ -#define AR5K_PCICFG_CLKRUNEN 0x00000004 /* CLKRUN enable [5211+] */ -#define AR5K_PCICFG_EESIZE 0x00000018 /* Mask for EEPROM size [5211+] */ -#define AR5K_PCICFG_EESIZE_S 3 -#define AR5K_PCICFG_EESIZE_4K 0 /* 4K */ -#define AR5K_PCICFG_EESIZE_8K 1 /* 8K */ -#define AR5K_PCICFG_EESIZE_16K 2 /* 16K */ -#define AR5K_PCICFG_EESIZE_FAIL 3 /* Failed to get size [5211+] */ -#define AR5K_PCICFG_LED 0x00000060 /* Led status [5211+] */ -#define AR5K_PCICFG_LED_NONE 0x00000000 /* Default [5211+] */ -#define AR5K_PCICFG_LED_PEND 0x00000020 /* Scan / Auth pending */ -#define AR5K_PCICFG_LED_ASSOC 0x00000040 /* Associated */ -#define AR5K_PCICFG_BUS_SEL 0x00000380 /* Mask for "bus select" [5211+] (?) */ -#define AR5K_PCICFG_CBEFIX_DIS 0x00000400 /* Disable CBE fix */ -#define AR5K_PCICFG_SL_INTEN 0x00000800 /* Enable interrupts when asleep */ -#define AR5K_PCICFG_LED_BCTL 0x00001000 /* Led blink (?) [5210] */ -#define AR5K_PCICFG_RETRY_FIX 0x00001000 /* Enable pci core retry fix */ -#define AR5K_PCICFG_SL_INPEN 0x00002000 /* Sleep even whith pending interrupts*/ -#define AR5K_PCICFG_SPWR_DN 0x00010000 /* Mask for power status */ -#define AR5K_PCICFG_LEDMODE 0x000e0000 /* Ledmode [5211+] */ -#define AR5K_PCICFG_LEDMODE_PROP 0x00000000 /* Blink on standard traffic [5211+] */ -#define AR5K_PCICFG_LEDMODE_PROM 0x00020000 /* Default mode (blink on any traffic) [5211+] */ -#define AR5K_PCICFG_LEDMODE_PWR 0x00040000 /* Some other blinking mode (?) [5211+] */ -#define AR5K_PCICFG_LEDMODE_RAND 0x00060000 /* Random blinking (?) [5211+] */ -#define AR5K_PCICFG_LEDBLINK 0x00700000 /* Led blink rate */ -#define AR5K_PCICFG_LEDBLINK_S 20 -#define AR5K_PCICFG_LEDSLOW 0x00800000 /* Slowest led blink rate [5211+] */ -#define AR5K_PCICFG_LEDSTATE \ - (AR5K_PCICFG_LED | AR5K_PCICFG_LEDMODE | \ - AR5K_PCICFG_LEDBLINK | AR5K_PCICFG_LEDSLOW) -#define AR5K_PCICFG_SLEEP_CLOCK_RATE 0x03000000 /* Sleep clock rate */ -#define AR5K_PCICFG_SLEEP_CLOCK_RATE_S 24 - -/* - * "General Purpose Input/Output" (GPIO) control register - * - * I'm not sure about this but after looking at the code - * for all chipsets here is what i got. - * - * We have 6 GPIOs (pins), each GPIO has 4 modes (2 bits) - * Mode 0 -> always input - * Mode 1 -> output when GPIODO for this GPIO is set to 0 - * Mode 2 -> output when GPIODO for this GPIO is set to 1 - * Mode 3 -> always output - * - * For more infos check out get_gpio/set_gpio and - * set_gpio_input/set_gpio_output functs. - * For more infos on gpio interrupt check out set_gpio_intr. - */ -#define AR5K_NUM_GPIO 6 - -#define AR5K_GPIOCR 0x4014 /* Register Address */ -#define AR5K_GPIOCR_INT_ENA 0x00008000 /* Enable GPIO interrupt */ -#define AR5K_GPIOCR_INT_SELL 0x00000000 /* Generate interrupt when pin is low */ -#define AR5K_GPIOCR_INT_SELH 0x00010000 /* Generate interrupt when pin is high */ -#define AR5K_GPIOCR_IN(n) (0 << ((n) * 2)) /* Mode 0 for pin n */ -#define AR5K_GPIOCR_OUT0(n) (1 << ((n) * 2)) /* Mode 1 for pin n */ -#define AR5K_GPIOCR_OUT1(n) (2 << ((n) * 2)) /* Mode 2 for pin n */ -#define AR5K_GPIOCR_OUT(n) (3 << ((n) * 2)) /* Mode 3 for pin n */ -#define AR5K_GPIOCR_INT_SEL(n) ((n) << 12) /* Interrupt for GPIO pin n */ - -/* - * "General Purpose Input/Output" (GPIO) data output register - */ -#define AR5K_GPIODO 0x4018 - -/* - * "General Purpose Input/Output" (GPIO) data input register - */ -#define AR5K_GPIODI 0x401c -#define AR5K_GPIODI_M 0x0000002f - -/* - * Silicon revision register - */ -#define AR5K_SREV 0x4020 /* Register Address */ -#define AR5K_SREV_REV 0x0000000f /* Mask for revision */ -#define AR5K_SREV_REV_S 0 -#define AR5K_SREV_VER 0x000000ff /* Mask for version */ -#define AR5K_SREV_VER_S 4 - -/* - * TXE write posting register - */ -#define AR5K_TXEPOST 0x4028 - -/* - * QCU sleep mask - */ -#define AR5K_QCU_SLEEP_MASK 0x402c - -/* 0x4068 is compression buffer configuration - * register on 5414 and pm configuration register - * on 5424 and newer pci-e chips. */ - -/* - * Compression buffer configuration - * register (enable/disable) [5414] - */ -#define AR5K_5414_CBCFG 0x4068 -#define AR5K_5414_CBCFG_BUF_DIS 0x10 /* Disable buffer */ - -/* - * PCI-E Power management configuration - * and status register [5424+] - */ -#define AR5K_PCIE_PM_CTL 0x4068 /* Register address */ -/* Only 5424 */ -#define AR5K_PCIE_PM_CTL_L1_WHEN_D2 0x00000001 /* enable PCIe core enter L1 - when d2_sleep_en is asserted */ -#define AR5K_PCIE_PM_CTL_L0_L0S_CLEAR 0x00000002 /* Clear L0 and L0S counters */ -#define AR5K_PCIE_PM_CTL_L0_L0S_EN 0x00000004 /* Start L0 nd L0S counters */ -#define AR5K_PCIE_PM_CTL_LDRESET_EN 0x00000008 /* Enable reset when link goes - down */ -/* Wake On Wireless */ -#define AR5K_PCIE_PM_CTL_PME_EN 0x00000010 /* PME Enable */ -#define AR5K_PCIE_PM_CTL_AUX_PWR_DET 0x00000020 /* Aux power detect */ -#define AR5K_PCIE_PM_CTL_PME_CLEAR 0x00000040 /* Clear PME */ -#define AR5K_PCIE_PM_CTL_PSM_D0 0x00000080 -#define AR5K_PCIE_PM_CTL_PSM_D1 0x00000100 -#define AR5K_PCIE_PM_CTL_PSM_D2 0x00000200 -#define AR5K_PCIE_PM_CTL_PSM_D3 0x00000400 - -/* - * PCI-E Workaround enable register - */ -#define AR5K_PCIE_WAEN 0x407c - -/* - * PCI-E Serializer/Desirializer - * registers - */ -#define AR5K_PCIE_SERDES 0x4080 -#define AR5K_PCIE_SERDES_RESET 0x4084 - -/*====EEPROM REGISTERS====*/ - -/* - * EEPROM access registers - * - * Here we got a difference between 5210/5211-12 - * read data register for 5210 is at 0x6800 and - * status register is at 0x6c00. There is also - * no eeprom command register on 5210 and the - * offsets are different. - * - * To read eeprom data for a specific offset: - * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) - * read AR5K_EEPROM_BASE +(4 * offset) - * check the eeprom status register - * and read eeprom data register. - * - * 5211 - write offset to AR5K_EEPROM_BASE - * 5212 write AR5K_EEPROM_CMD_READ on AR5K_EEPROM_CMD - * check the eeprom status register - * and read eeprom data register. - * - * To write eeprom data for a specific offset: - * 5210 - enable eeprom access (AR5K_PCICFG_EEAE) - * write data to AR5K_EEPROM_BASE +(4 * offset) - * check the eeprom status register - * 5211 - write AR5K_EEPROM_CMD_RESET on AR5K_EEPROM_CMD - * 5212 write offset to AR5K_EEPROM_BASE - * write data to data register - * write AR5K_EEPROM_CMD_WRITE on AR5K_EEPROM_CMD - * check the eeprom status register - * - * For more infos check eeprom_* functs and the ar5k.c - * file posted in madwifi-devel mailing list. - * http://sourceforge.net/mailarchive/message.php?msg_id=8966525 - * - */ -#define AR5K_EEPROM_BASE 0x6000 - -/* - * EEPROM data register - */ -#define AR5K_EEPROM_DATA_5211 0x6004 -#define AR5K_EEPROM_DATA_5210 0x6800 -#define AR5K_EEPROM_DATA (ah->ah_version == AR5K_AR5210 ? \ - AR5K_EEPROM_DATA_5210 : AR5K_EEPROM_DATA_5211) - -/* - * EEPROM command register - */ -#define AR5K_EEPROM_CMD 0x6008 /* Register Addres */ -#define AR5K_EEPROM_CMD_READ 0x00000001 /* EEPROM read */ -#define AR5K_EEPROM_CMD_WRITE 0x00000002 /* EEPROM write */ -#define AR5K_EEPROM_CMD_RESET 0x00000004 /* EEPROM reset */ - -/* - * EEPROM status register - */ -#define AR5K_EEPROM_STAT_5210 0x6c00 /* Register Address [5210] */ -#define AR5K_EEPROM_STAT_5211 0x600c /* Register Address [5211+] */ -#define AR5K_EEPROM_STATUS (ah->ah_version == AR5K_AR5210 ? \ - AR5K_EEPROM_STAT_5210 : AR5K_EEPROM_STAT_5211) -#define AR5K_EEPROM_STAT_RDERR 0x00000001 /* EEPROM read failed */ -#define AR5K_EEPROM_STAT_RDDONE 0x00000002 /* EEPROM read successful */ -#define AR5K_EEPROM_STAT_WRERR 0x00000004 /* EEPROM write failed */ -#define AR5K_EEPROM_STAT_WRDONE 0x00000008 /* EEPROM write successful */ - -/* - * EEPROM config register - */ -#define AR5K_EEPROM_CFG 0x6010 /* Register Addres */ -#define AR5K_EEPROM_CFG_SIZE 0x00000003 /* Size determination override */ -#define AR5K_EEPROM_CFG_SIZE_AUTO 0 -#define AR5K_EEPROM_CFG_SIZE_4KBIT 1 -#define AR5K_EEPROM_CFG_SIZE_8KBIT 2 -#define AR5K_EEPROM_CFG_SIZE_16KBIT 3 -#define AR5K_EEPROM_CFG_WR_WAIT_DIS 0x00000004 /* Disable write wait */ -#define AR5K_EEPROM_CFG_CLK_RATE 0x00000018 /* Clock rate */ -#define AR5K_EEPROM_CFG_CLK_RATE_S 3 -#define AR5K_EEPROM_CFG_CLK_RATE_156KHZ 0 -#define AR5K_EEPROM_CFG_CLK_RATE_312KHZ 1 -#define AR5K_EEPROM_CFG_CLK_RATE_625KHZ 2 -#define AR5K_EEPROM_CFG_PROT_KEY 0x00ffff00 /* Protection key */ -#define AR5K_EEPROM_CFG_PROT_KEY_S 8 -#define AR5K_EEPROM_CFG_LIND_EN 0x01000000 /* Enable length indicator (?) */ - - -/* - * TODO: Wake On Wireless registers - * Range 0x7000 - 0x7ce0 - */ - -/* - * Protocol Control Unit (PCU) registers - */ -/* - * Used for checking initial register writes - * during channel reset (see reset func) - */ -#define AR5K_PCU_MIN 0x8000 -#define AR5K_PCU_MAX 0x8fff - -/* - * First station id register (Lower 32 bits of MAC address) - */ -#define AR5K_STA_ID0 0x8000 -#define AR5K_STA_ID0_ARRD_L32 0xffffffff - -/* - * Second station id register (Upper 16 bits of MAC address + PCU settings) - */ -#define AR5K_STA_ID1 0x8004 /* Register Address */ -#define AR5K_STA_ID1_ADDR_U16 0x0000ffff /* Upper 16 bits of MAC addres */ -#define AR5K_STA_ID1_AP 0x00010000 /* Set AP mode */ -#define AR5K_STA_ID1_ADHOC 0x00020000 /* Set Ad-Hoc mode */ -#define AR5K_STA_ID1_PWR_SV 0x00040000 /* Power save reporting */ -#define AR5K_STA_ID1_NO_KEYSRCH 0x00080000 /* No key search */ -#define AR5K_STA_ID1_NO_PSPOLL 0x00100000 /* No power save polling [5210] */ -#define AR5K_STA_ID1_PCF_5211 0x00100000 /* Enable PCF on [5211+] */ -#define AR5K_STA_ID1_PCF_5210 0x00200000 /* Enable PCF on [5210]*/ -#define AR5K_STA_ID1_PCF (ah->ah_version == AR5K_AR5210 ? \ - AR5K_STA_ID1_PCF_5210 : AR5K_STA_ID1_PCF_5211) -#define AR5K_STA_ID1_DEFAULT_ANTENNA 0x00200000 /* Use default antenna */ -#define AR5K_STA_ID1_DESC_ANTENNA 0x00400000 /* Update antenna from descriptor */ -#define AR5K_STA_ID1_RTS_DEF_ANTENNA 0x00800000 /* Use default antenna for RTS */ -#define AR5K_STA_ID1_ACKCTS_6MB 0x01000000 /* Use 6Mbit/s for ACK/CTS */ -#define AR5K_STA_ID1_BASE_RATE_11B 0x02000000 /* Use 11b base rate for ACK/CTS [5211+] */ -#define AR5K_STA_ID1_SELFGEN_DEF_ANT 0x04000000 /* Use def. antenna for self generated frames */ -#define AR5K_STA_ID1_CRYPT_MIC_EN 0x08000000 /* Enable MIC */ -#define AR5K_STA_ID1_KEYSRCH_MODE 0x10000000 /* Look up key when key id != 0 */ -#define AR5K_STA_ID1_PRESERVE_SEQ_NUM 0x20000000 /* Preserve sequence number */ -#define AR5K_STA_ID1_CBCIV_ENDIAN 0x40000000 /* ??? */ -#define AR5K_STA_ID1_KEYSRCH_MCAST 0x80000000 /* Do key cache search for mcast frames */ - -#define AR5K_STA_ID1_ANTENNA_SETTINGS (AR5K_STA_ID1_DEFAULT_ANTENNA | \ - AR5K_STA_ID1_DESC_ANTENNA | \ - AR5K_STA_ID1_RTS_DEF_ANTENNA | \ - AR5K_STA_ID1_SELFGEN_DEF_ANT) - -/* - * First BSSID register (MAC address, lower 32bits) - */ -#define AR5K_BSS_ID0 0x8008 - -/* - * Second BSSID register (MAC address in upper 16 bits) - * - * AID: Association ID - */ -#define AR5K_BSS_ID1 0x800c -#define AR5K_BSS_ID1_AID 0xffff0000 -#define AR5K_BSS_ID1_AID_S 16 - -/* - * Backoff slot time register - */ -#define AR5K_SLOT_TIME 0x8010 - -/* - * ACK/CTS timeout register - */ -#define AR5K_TIME_OUT 0x8014 /* Register Address */ -#define AR5K_TIME_OUT_ACK 0x00001fff /* ACK timeout mask */ -#define AR5K_TIME_OUT_ACK_S 0 -#define AR5K_TIME_OUT_CTS 0x1fff0000 /* CTS timeout mask */ -#define AR5K_TIME_OUT_CTS_S 16 - -/* - * RSSI threshold register - */ -#define AR5K_RSSI_THR 0x8018 /* Register Address */ -#define AR5K_RSSI_THR_M 0x000000ff /* Mask for RSSI threshold [5211+] */ -#define AR5K_RSSI_THR_BMISS_5210 0x00000700 /* Mask for Beacon Missed threshold [5210] */ -#define AR5K_RSSI_THR_BMISS_5210_S 8 -#define AR5K_RSSI_THR_BMISS_5211 0x0000ff00 /* Mask for Beacon Missed threshold [5211+] */ -#define AR5K_RSSI_THR_BMISS_5211_S 8 -#define AR5K_RSSI_THR_BMISS (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RSSI_THR_BMISS_5210 : AR5K_RSSI_THR_BMISS_5211) -#define AR5K_RSSI_THR_BMISS_S 8 - -/* - * 5210 has more PCU registers because there is no QCU/DCU - * so queue parameters are set here, this way a lot common - * registers have different address for 5210. To make things - * easier we define a macro based on ah->ah_version for common - * registers with different addresses and common flags. - */ - -/* - * Retry limit register - * - * Retry limit register for 5210 (no QCU/DCU so it's done in PCU) - */ -#define AR5K_NODCU_RETRY_LMT 0x801c /* Register Address */ -#define AR5K_NODCU_RETRY_LMT_SH_RETRY 0x0000000f /* Short retry limit mask */ -#define AR5K_NODCU_RETRY_LMT_SH_RETRY_S 0 -#define AR5K_NODCU_RETRY_LMT_LG_RETRY 0x000000f0 /* Long retry mask */ -#define AR5K_NODCU_RETRY_LMT_LG_RETRY_S 4 -#define AR5K_NODCU_RETRY_LMT_SSH_RETRY 0x00003f00 /* Station short retry limit mask */ -#define AR5K_NODCU_RETRY_LMT_SSH_RETRY_S 8 -#define AR5K_NODCU_RETRY_LMT_SLG_RETRY 0x000fc000 /* Station long retry limit mask */ -#define AR5K_NODCU_RETRY_LMT_SLG_RETRY_S 14 -#define AR5K_NODCU_RETRY_LMT_CW_MIN 0x3ff00000 /* Minimum contention window mask */ -#define AR5K_NODCU_RETRY_LMT_CW_MIN_S 20 - -/* - * Transmit latency register - */ -#define AR5K_USEC_5210 0x8020 /* Register Address [5210] */ -#define AR5K_USEC_5211 0x801c /* Register Address [5211+] */ -#define AR5K_USEC (ah->ah_version == AR5K_AR5210 ? \ - AR5K_USEC_5210 : AR5K_USEC_5211) -#define AR5K_USEC_1 0x0000007f /* clock cycles for 1us */ -#define AR5K_USEC_1_S 0 -#define AR5K_USEC_32 0x00003f80 /* clock cycles for 1us while on 32Mhz clock */ -#define AR5K_USEC_32_S 7 -#define AR5K_USEC_TX_LATENCY_5211 0x007fc000 -#define AR5K_USEC_TX_LATENCY_5211_S 14 -#define AR5K_USEC_RX_LATENCY_5211 0x1f800000 -#define AR5K_USEC_RX_LATENCY_5211_S 23 -#define AR5K_USEC_TX_LATENCY_5210 0x000fc000 /* also for 5311 */ -#define AR5K_USEC_TX_LATENCY_5210_S 14 -#define AR5K_USEC_RX_LATENCY_5210 0x03f00000 /* also for 5311 */ -#define AR5K_USEC_RX_LATENCY_5210_S 20 - -/* - * PCU beacon control register - */ -#define AR5K_BEACON_5210 0x8024 /*Register Address [5210] */ -#define AR5K_BEACON_5211 0x8020 /*Register Address [5211+] */ -#define AR5K_BEACON (ah->ah_version == AR5K_AR5210 ? \ - AR5K_BEACON_5210 : AR5K_BEACON_5211) -#define AR5K_BEACON_PERIOD 0x0000ffff /* Mask for beacon period */ -#define AR5K_BEACON_PERIOD_S 0 -#define AR5K_BEACON_TIM 0x007f0000 /* Mask for TIM offset */ -#define AR5K_BEACON_TIM_S 16 -#define AR5K_BEACON_ENABLE 0x00800000 /* Enable beacons */ -#define AR5K_BEACON_RESET_TSF 0x01000000 /* Force TSF reset */ - -/* - * CFP period register - */ -#define AR5K_CFP_PERIOD_5210 0x8028 -#define AR5K_CFP_PERIOD_5211 0x8024 -#define AR5K_CFP_PERIOD (ah->ah_version == AR5K_AR5210 ? \ - AR5K_CFP_PERIOD_5210 : AR5K_CFP_PERIOD_5211) - -/* - * Next beacon time register - */ -#define AR5K_TIMER0_5210 0x802c -#define AR5K_TIMER0_5211 0x8028 -#define AR5K_TIMER0 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER0_5210 : AR5K_TIMER0_5211) - -/* - * Next DMA beacon alert register - */ -#define AR5K_TIMER1_5210 0x8030 -#define AR5K_TIMER1_5211 0x802c -#define AR5K_TIMER1 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER1_5210 : AR5K_TIMER1_5211) - -/* - * Next software beacon alert register - */ -#define AR5K_TIMER2_5210 0x8034 -#define AR5K_TIMER2_5211 0x8030 -#define AR5K_TIMER2 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER2_5210 : AR5K_TIMER2_5211) - -/* - * Next ATIM window time register - */ -#define AR5K_TIMER3_5210 0x8038 -#define AR5K_TIMER3_5211 0x8034 -#define AR5K_TIMER3 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TIMER3_5210 : AR5K_TIMER3_5211) - - -/* - * 5210 First inter frame spacing register (IFS) - */ -#define AR5K_IFS0 0x8040 -#define AR5K_IFS0_SIFS 0x000007ff -#define AR5K_IFS0_SIFS_S 0 -#define AR5K_IFS0_DIFS 0x007ff800 -#define AR5K_IFS0_DIFS_S 11 - -/* - * 5210 Second inter frame spacing register (IFS) - */ -#define AR5K_IFS1 0x8044 -#define AR5K_IFS1_PIFS 0x00000fff -#define AR5K_IFS1_PIFS_S 0 -#define AR5K_IFS1_EIFS 0x03fff000 -#define AR5K_IFS1_EIFS_S 12 -#define AR5K_IFS1_CS_EN 0x04000000 - - -/* - * CFP duration register - */ -#define AR5K_CFP_DUR_5210 0x8048 -#define AR5K_CFP_DUR_5211 0x8038 -#define AR5K_CFP_DUR (ah->ah_version == AR5K_AR5210 ? \ - AR5K_CFP_DUR_5210 : AR5K_CFP_DUR_5211) - -/* - * Receive filter register - */ -#define AR5K_RX_FILTER_5210 0x804c /* Register Address [5210] */ -#define AR5K_RX_FILTER_5211 0x803c /* Register Address [5211+] */ -#define AR5K_RX_FILTER (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RX_FILTER_5210 : AR5K_RX_FILTER_5211) -#define AR5K_RX_FILTER_UCAST 0x00000001 /* Don't filter unicast frames */ -#define AR5K_RX_FILTER_MCAST 0x00000002 /* Don't filter multicast frames */ -#define AR5K_RX_FILTER_BCAST 0x00000004 /* Don't filter broadcast frames */ -#define AR5K_RX_FILTER_CONTROL 0x00000008 /* Don't filter control frames */ -#define AR5K_RX_FILTER_BEACON 0x00000010 /* Don't filter beacon frames */ -#define AR5K_RX_FILTER_PROM 0x00000020 /* Set promiscuous mode */ -#define AR5K_RX_FILTER_XRPOLL 0x00000040 /* Don't filter XR poll frame [5212+] */ -#define AR5K_RX_FILTER_PROBEREQ 0x00000080 /* Don't filter probe requests [5212+] */ -#define AR5K_RX_FILTER_PHYERR_5212 0x00000100 /* Don't filter phy errors [5212+] */ -#define AR5K_RX_FILTER_RADARERR_5212 0x00000200 /* Don't filter phy radar errors [5212+] */ -#define AR5K_RX_FILTER_PHYERR_5211 0x00000040 /* [5211] */ -#define AR5K_RX_FILTER_RADARERR_5211 0x00000080 /* [5211] */ -#define AR5K_RX_FILTER_PHYERR \ - ((ah->ah_version == AR5K_AR5211 ? \ - AR5K_RX_FILTER_PHYERR_5211 : AR5K_RX_FILTER_PHYERR_5212)) -#define AR5K_RX_FILTER_RADARERR \ - ((ah->ah_version == AR5K_AR5211 ? \ - AR5K_RX_FILTER_RADARERR_5211 : AR5K_RX_FILTER_RADARERR_5212)) - -/* - * Multicast filter register (lower 32 bits) - */ -#define AR5K_MCAST_FILTER0_5210 0x8050 -#define AR5K_MCAST_FILTER0_5211 0x8040 -#define AR5K_MCAST_FILTER0 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_MCAST_FILTER0_5210 : AR5K_MCAST_FILTER0_5211) - -/* - * Multicast filter register (higher 16 bits) - */ -#define AR5K_MCAST_FILTER1_5210 0x8054 -#define AR5K_MCAST_FILTER1_5211 0x8044 -#define AR5K_MCAST_FILTER1 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_MCAST_FILTER1_5210 : AR5K_MCAST_FILTER1_5211) - - -/* - * Transmit mask register (lower 32 bits) [5210] - */ -#define AR5K_TX_MASK0 0x8058 - -/* - * Transmit mask register (higher 16 bits) [5210] - */ -#define AR5K_TX_MASK1 0x805c - -/* - * Clear transmit mask [5210] - */ -#define AR5K_CLR_TMASK 0x8060 - -/* - * Trigger level register (before transmission) [5210] - */ -#define AR5K_TRIG_LVL 0x8064 - - -/* - * PCU control register - * - * Only DIS_RX is used in the code, the rest i guess are - * for tweaking/diagnostics. - */ -#define AR5K_DIAG_SW_5210 0x8068 /* Register Address [5210] */ -#define AR5K_DIAG_SW_5211 0x8048 /* Register Address [5211+] */ -#define AR5K_DIAG_SW (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_5210 : AR5K_DIAG_SW_5211) -#define AR5K_DIAG_SW_DIS_WEP_ACK 0x00000001 /* Disable ACKs if WEP key is invalid */ -#define AR5K_DIAG_SW_DIS_ACK 0x00000002 /* Disable ACKs */ -#define AR5K_DIAG_SW_DIS_CTS 0x00000004 /* Disable CTSs */ -#define AR5K_DIAG_SW_DIS_ENC 0x00000008 /* Disable encryption */ -#define AR5K_DIAG_SW_DIS_DEC 0x00000010 /* Disable decryption */ -#define AR5K_DIAG_SW_DIS_TX 0x00000020 /* Disable transmit [5210] */ -#define AR5K_DIAG_SW_DIS_RX_5210 0x00000040 /* Disable recieve */ -#define AR5K_DIAG_SW_DIS_RX_5211 0x00000020 -#define AR5K_DIAG_SW_DIS_RX (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_DIS_RX_5210 : AR5K_DIAG_SW_DIS_RX_5211) -#define AR5K_DIAG_SW_LOOP_BACK_5210 0x00000080 /* Loopback (i guess it goes with DIS_TX) [5210] */ -#define AR5K_DIAG_SW_LOOP_BACK_5211 0x00000040 -#define AR5K_DIAG_SW_LOOP_BACK (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_LOOP_BACK_5210 : AR5K_DIAG_SW_LOOP_BACK_5211) -#define AR5K_DIAG_SW_CORR_FCS_5210 0x00000100 /* Corrupted FCS */ -#define AR5K_DIAG_SW_CORR_FCS_5211 0x00000080 -#define AR5K_DIAG_SW_CORR_FCS (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_CORR_FCS_5210 : AR5K_DIAG_SW_CORR_FCS_5211) -#define AR5K_DIAG_SW_CHAN_INFO_5210 0x00000200 /* Dump channel info */ -#define AR5K_DIAG_SW_CHAN_INFO_5211 0x00000100 -#define AR5K_DIAG_SW_CHAN_INFO (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_CHAN_INFO_5210 : AR5K_DIAG_SW_CHAN_INFO_5211) -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5210 0x00000400 /* Enable fixed scrambler seed */ -#define AR5K_DIAG_SW_EN_SCRAM_SEED_5211 0x00000200 -#define AR5K_DIAG_SW_EN_SCRAM_SEED (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_EN_SCRAM_SEED_5210 : AR5K_DIAG_SW_EN_SCRAM_SEED_5211) -#define AR5K_DIAG_SW_ECO_ENABLE 0x00000400 /* [5211+] */ -#define AR5K_DIAG_SW_SCVRAM_SEED 0x0003f800 /* [5210] */ -#define AR5K_DIAG_SW_SCRAM_SEED_M 0x0001fc00 /* Scrambler seed mask */ -#define AR5K_DIAG_SW_SCRAM_SEED_S 10 -#define AR5K_DIAG_SW_DIS_SEQ_INC 0x00040000 /* Disable seqnum increment (?)[5210] */ -#define AR5K_DIAG_SW_FRAME_NV0_5210 0x00080000 -#define AR5K_DIAG_SW_FRAME_NV0_5211 0x00020000 /* Accept frames of non-zero protocol number */ -#define AR5K_DIAG_SW_FRAME_NV0 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_DIAG_SW_FRAME_NV0_5210 : AR5K_DIAG_SW_FRAME_NV0_5211) -#define AR5K_DIAG_SW_OBSPT_M 0x000c0000 /* Observation point select (?) */ -#define AR5K_DIAG_SW_OBSPT_S 18 -#define AR5K_DIAG_SW_RX_CLEAR_HIGH 0x0010000 /* Force RX Clear high */ -#define AR5K_DIAG_SW_IGNORE_CARR_SENSE 0x0020000 /* Ignore virtual carrier sense */ -#define AR5K_DIAG_SW_CHANEL_IDLE_HIGH 0x0040000 /* Force channel idle high */ -#define AR5K_DIAG_SW_PHEAR_ME 0x0080000 /* ??? */ - -/* - * TSF (clock) register (lower 32 bits) - */ -#define AR5K_TSF_L32_5210 0x806c -#define AR5K_TSF_L32_5211 0x804c -#define AR5K_TSF_L32 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TSF_L32_5210 : AR5K_TSF_L32_5211) - -/* - * TSF (clock) register (higher 32 bits) - */ -#define AR5K_TSF_U32_5210 0x8070 -#define AR5K_TSF_U32_5211 0x8050 -#define AR5K_TSF_U32 (ah->ah_version == AR5K_AR5210 ? \ - AR5K_TSF_U32_5210 : AR5K_TSF_U32_5211) - -/* - * Last beacon timestamp register (Read Only) - */ -#define AR5K_LAST_TSTP 0x8080 - -/* - * ADDAC test register [5211+] - */ -#define AR5K_ADDAC_TEST 0x8054 /* Register Address */ -#define AR5K_ADDAC_TEST_TXCONT 0x00000001 /* Test continuous tx */ -#define AR5K_ADDAC_TEST_TST_MODE 0x00000002 /* Test mode */ -#define AR5K_ADDAC_TEST_LOOP_EN 0x00000004 /* Enable loop */ -#define AR5K_ADDAC_TEST_LOOP_LEN 0x00000008 /* Loop length (field) */ -#define AR5K_ADDAC_TEST_USE_U8 0x00004000 /* Use upper 8 bits */ -#define AR5K_ADDAC_TEST_MSB 0x00008000 /* State of MSB */ -#define AR5K_ADDAC_TEST_TRIG_SEL 0x00010000 /* Trigger select */ -#define AR5K_ADDAC_TEST_TRIG_PTY 0x00020000 /* Trigger polarity */ -#define AR5K_ADDAC_TEST_RXCONT 0x00040000 /* Continuous capture */ -#define AR5K_ADDAC_TEST_CAPTURE 0x00080000 /* Begin capture */ -#define AR5K_ADDAC_TEST_TST_ARM 0x00100000 /* ARM rx buffer for capture */ - -/* - * Default antenna register [5211+] - */ -#define AR5K_DEFAULT_ANTENNA 0x8058 - -/* - * Frame control QoS mask register (?) [5211+] - * (FC_QOS_MASK) - */ -#define AR5K_FRAME_CTL_QOSM 0x805c - -/* - * Seq mask register (?) [5211+] - */ -#define AR5K_SEQ_MASK 0x8060 - -/* - * Retry count register [5210] - */ -#define AR5K_RETRY_CNT 0x8084 /* Register Address [5210] */ -#define AR5K_RETRY_CNT_SSH 0x0000003f /* Station short retry count (?) */ -#define AR5K_RETRY_CNT_SLG 0x00000fc0 /* Station long retry count (?) */ - -/* - * Back-off status register [5210] - */ -#define AR5K_BACKOFF 0x8088 /* Register Address [5210] */ -#define AR5K_BACKOFF_CW 0x000003ff /* Backoff Contention Window (?) */ -#define AR5K_BACKOFF_CNT 0x03ff0000 /* Backoff count (?) */ - - - -/* - * NAV register (current) - */ -#define AR5K_NAV_5210 0x808c -#define AR5K_NAV_5211 0x8084 -#define AR5K_NAV (ah->ah_version == AR5K_AR5210 ? \ - AR5K_NAV_5210 : AR5K_NAV_5211) - -/* - * RTS success register - */ -#define AR5K_RTS_OK_5210 0x8090 -#define AR5K_RTS_OK_5211 0x8088 -#define AR5K_RTS_OK (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RTS_OK_5210 : AR5K_RTS_OK_5211) - -/* - * RTS failure register - */ -#define AR5K_RTS_FAIL_5210 0x8094 -#define AR5K_RTS_FAIL_5211 0x808c -#define AR5K_RTS_FAIL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_RTS_FAIL_5210 : AR5K_RTS_FAIL_5211) - -/* - * ACK failure register - */ -#define AR5K_ACK_FAIL_5210 0x8098 -#define AR5K_ACK_FAIL_5211 0x8090 -#define AR5K_ACK_FAIL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_ACK_FAIL_5210 : AR5K_ACK_FAIL_5211) - -/* - * FCS failure register - */ -#define AR5K_FCS_FAIL_5210 0x809c -#define AR5K_FCS_FAIL_5211 0x8094 -#define AR5K_FCS_FAIL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_FCS_FAIL_5210 : AR5K_FCS_FAIL_5211) - -/* - * Beacon count register - */ -#define AR5K_BEACON_CNT_5210 0x80a0 -#define AR5K_BEACON_CNT_5211 0x8098 -#define AR5K_BEACON_CNT (ah->ah_version == AR5K_AR5210 ? \ - AR5K_BEACON_CNT_5210 : AR5K_BEACON_CNT_5211) - - -/*===5212 Specific PCU registers===*/ - -/* - * Transmit power control register - */ -#define AR5K_TPC 0x80e8 -#define AR5K_TPC_ACK 0x0000003f /* ack frames */ -#define AR5K_TPC_ACK_S 0 -#define AR5K_TPC_CTS 0x00003f00 /* cts frames */ -#define AR5K_TPC_CTS_S 8 -#define AR5K_TPC_CHIRP 0x003f0000 /* chirp frames */ -#define AR5K_TPC_CHIRP_S 16 -#define AR5K_TPC_DOPPLER 0x0f000000 /* doppler chirp span */ -#define AR5K_TPC_DOPPLER_S 24 - -/* - * XR (eXtended Range) mode register - */ -#define AR5K_XRMODE 0x80c0 /* Register Address */ -#define AR5K_XRMODE_POLL_TYPE_M 0x0000003f /* Mask for Poll type (?) */ -#define AR5K_XRMODE_POLL_TYPE_S 0 -#define AR5K_XRMODE_POLL_SUBTYPE_M 0x0000003c /* Mask for Poll subtype (?) */ -#define AR5K_XRMODE_POLL_SUBTYPE_S 2 -#define AR5K_XRMODE_POLL_WAIT_ALL 0x00000080 /* Wait for poll */ -#define AR5K_XRMODE_SIFS_DELAY 0x000fff00 /* Mask for SIFS delay */ -#define AR5K_XRMODE_FRAME_HOLD_M 0xfff00000 /* Mask for frame hold (?) */ -#define AR5K_XRMODE_FRAME_HOLD_S 20 - -/* - * XR delay register - */ -#define AR5K_XRDELAY 0x80c4 /* Register Address */ -#define AR5K_XRDELAY_SLOT_DELAY_M 0x0000ffff /* Mask for slot delay */ -#define AR5K_XRDELAY_SLOT_DELAY_S 0 -#define AR5K_XRDELAY_CHIRP_DELAY_M 0xffff0000 /* Mask for CHIRP data delay */ -#define AR5K_XRDELAY_CHIRP_DELAY_S 16 - -/* - * XR timeout register - */ -#define AR5K_XRTIMEOUT 0x80c8 /* Register Address */ -#define AR5K_XRTIMEOUT_CHIRP_M 0x0000ffff /* Mask for CHIRP timeout */ -#define AR5K_XRTIMEOUT_CHIRP_S 0 -#define AR5K_XRTIMEOUT_POLL_M 0xffff0000 /* Mask for Poll timeout */ -#define AR5K_XRTIMEOUT_POLL_S 16 - -/* - * XR chirp register - */ -#define AR5K_XRCHIRP 0x80cc /* Register Address */ -#define AR5K_XRCHIRP_SEND 0x00000001 /* Send CHIRP */ -#define AR5K_XRCHIRP_GAP 0xffff0000 /* Mask for CHIRP gap (?) */ - -/* - * XR stomp register - */ -#define AR5K_XRSTOMP 0x80d0 /* Register Address */ -#define AR5K_XRSTOMP_TX 0x00000001 /* Stomp Tx (?) */ -#define AR5K_XRSTOMP_RX 0x00000002 /* Stomp Rx (?) */ -#define AR5K_XRSTOMP_TX_RSSI 0x00000004 /* Stomp Tx RSSI (?) */ -#define AR5K_XRSTOMP_TX_BSSID 0x00000008 /* Stomp Tx BSSID (?) */ -#define AR5K_XRSTOMP_DATA 0x00000010 /* Stomp data (?)*/ -#define AR5K_XRSTOMP_RSSI_THRES 0x0000ff00 /* Mask for XR RSSI threshold */ - -/* - * First enhanced sleep register - */ -#define AR5K_SLEEP0 0x80d4 /* Register Address */ -#define AR5K_SLEEP0_NEXT_DTIM 0x0007ffff /* Mask for next DTIM (?) */ -#define AR5K_SLEEP0_NEXT_DTIM_S 0 -#define AR5K_SLEEP0_ASSUME_DTIM 0x00080000 /* Assume DTIM */ -#define AR5K_SLEEP0_ENH_SLEEP_EN 0x00100000 /* Enable enchanced sleep control */ -#define AR5K_SLEEP0_CABTO 0xff000000 /* Mask for CAB Time Out */ -#define AR5K_SLEEP0_CABTO_S 24 - -/* - * Second enhanced sleep register - */ -#define AR5K_SLEEP1 0x80d8 /* Register Address */ -#define AR5K_SLEEP1_NEXT_TIM 0x0007ffff /* Mask for next TIM (?) */ -#define AR5K_SLEEP1_NEXT_TIM_S 0 -#define AR5K_SLEEP1_BEACON_TO 0xff000000 /* Mask for Beacon Time Out */ -#define AR5K_SLEEP1_BEACON_TO_S 24 - -/* - * Third enhanced sleep register - */ -#define AR5K_SLEEP2 0x80dc /* Register Address */ -#define AR5K_SLEEP2_TIM_PER 0x0000ffff /* Mask for TIM period (?) */ -#define AR5K_SLEEP2_TIM_PER_S 0 -#define AR5K_SLEEP2_DTIM_PER 0xffff0000 /* Mask for DTIM period (?) */ -#define AR5K_SLEEP2_DTIM_PER_S 16 - -/* - * BSSID mask registers - */ -#define AR5K_BSS_IDM0 0x80e0 /* Upper bits */ -#define AR5K_BSS_IDM1 0x80e4 /* Lower bits */ - -/* - * TX power control (TPC) register - * - * XXX: PCDAC steps (0.5dbm) or DBM ? - * - */ -#define AR5K_TXPC 0x80e8 /* Register Address */ -#define AR5K_TXPC_ACK_M 0x0000003f /* ACK tx power */ -#define AR5K_TXPC_ACK_S 0 -#define AR5K_TXPC_CTS_M 0x00003f00 /* CTS tx power */ -#define AR5K_TXPC_CTS_S 8 -#define AR5K_TXPC_CHIRP_M 0x003f0000 /* CHIRP tx power */ -#define AR5K_TXPC_CHIRP_S 16 -#define AR5K_TXPC_DOPPLER 0x0f000000 /* Doppler chirp span (?) */ -#define AR5K_TXPC_DOPPLER_S 24 - -/* - * Profile count registers - */ -#define AR5K_PROFCNT_TX 0x80ec /* Tx count */ -#define AR5K_PROFCNT_RX 0x80f0 /* Rx count */ -#define AR5K_PROFCNT_RXCLR 0x80f4 /* Clear Rx count */ -#define AR5K_PROFCNT_CYCLE 0x80f8 /* Cycle count (?) */ - -/* - * Quiet period control registers - */ -#define AR5K_QUIET_CTL1 0x80fc /* Register Address */ -#define AR5K_QUIET_CTL1_NEXT_QT_TSF 0x0000ffff /* Next quiet period TSF (TU) */ -#define AR5K_QUIET_CTL1_NEXT_QT_TSF_S 0 -#define AR5K_QUIET_CTL1_QT_EN 0x00010000 /* Enable quiet period */ -#define AR5K_QUIET_CTL1_ACK_CTS_EN 0x00020000 /* Send ACK/CTS during quiet period */ - -#define AR5K_QUIET_CTL2 0x8100 /* Register Address */ -#define AR5K_QUIET_CTL2_QT_PER 0x0000ffff /* Mask for quiet period periodicity */ -#define AR5K_QUIET_CTL2_QT_PER_S 0 -#define AR5K_QUIET_CTL2_QT_DUR 0xffff0000 /* Mask for quiet period duration */ -#define AR5K_QUIET_CTL2_QT_DUR_S 16 - -/* - * TSF parameter register - */ -#define AR5K_TSF_PARM 0x8104 /* Register Address */ -#define AR5K_TSF_PARM_INC 0x000000ff /* Mask for TSF increment */ -#define AR5K_TSF_PARM_INC_S 0 - -/* - * QoS NOACK policy - */ -#define AR5K_QOS_NOACK 0x8108 /* Register Address */ -#define AR5K_QOS_NOACK_2BIT_VALUES 0x0000000f /* ??? */ -#define AR5K_QOS_NOACK_2BIT_VALUES_S 0 -#define AR5K_QOS_NOACK_BIT_OFFSET 0x00000070 /* ??? */ -#define AR5K_QOS_NOACK_BIT_OFFSET_S 4 -#define AR5K_QOS_NOACK_BYTE_OFFSET 0x00000180 /* ??? */ -#define AR5K_QOS_NOACK_BYTE_OFFSET_S 7 - -/* - * PHY error filter register - */ -#define AR5K_PHY_ERR_FIL 0x810c -#define AR5K_PHY_ERR_FIL_RADAR 0x00000020 /* Radar signal */ -#define AR5K_PHY_ERR_FIL_OFDM 0x00020000 /* OFDM false detect (ANI) */ -#define AR5K_PHY_ERR_FIL_CCK 0x02000000 /* CCK false detect (ANI) */ - -/* - * XR latency register - */ -#define AR5K_XRLAT_TX 0x8110 - -/* - * ACK SIFS register - */ -#define AR5K_ACKSIFS 0x8114 /* Register Address */ -#define AR5K_ACKSIFS_INC 0x00000000 /* ACK SIFS Increment (field) */ - -/* - * MIC QoS control register (?) - */ -#define AR5K_MIC_QOS_CTL 0x8118 /* Register Address */ -#define AR5K_MIC_QOS_CTL_OFF(_n) (1 << (_n * 2)) -#define AR5K_MIC_QOS_CTL_MQ_EN 0x00010000 /* Enable MIC QoS */ - -/* - * MIC QoS select register (?) - */ -#define AR5K_MIC_QOS_SEL 0x811c -#define AR5K_MIC_QOS_SEL_OFF(_n) (1 << (_n * 4)) - -/* - * Misc mode control register (?) - */ -#define AR5K_MISC_MODE 0x8120 /* Register Address */ -#define AR5K_MISC_MODE_FBSSID_MATCH 0x00000001 /* Force BSSID match */ -#define AR5K_MISC_MODE_ACKSIFS_MEM 0x00000002 /* ACK SIFS memory (?) */ -#define AR5K_MISC_MODE_COMBINED_MIC 0x00000004 /* use rx/tx MIC key */ -/* more bits */ - -/* - * OFDM Filter counter - */ -#define AR5K_OFDM_FIL_CNT 0x8124 - -/* - * CCK Filter counter - */ -#define AR5K_CCK_FIL_CNT 0x8128 - -/* - * PHY Error Counters (?) - */ -#define AR5K_PHYERR_CNT1 0x812c -#define AR5K_PHYERR_CNT1_MASK 0x8130 - -#define AR5K_PHYERR_CNT2 0x8134 -#define AR5K_PHYERR_CNT2_MASK 0x8138 - -/* - * TSF Threshold register (?) - */ -#define AR5K_TSF_THRES 0x813c - -/* - * TODO: Wake On Wireless registers - * Range: 0x8147 - 0x818c - */ - -/* - * Rate -> ACK SIFS mapping table (32 entries) - */ -#define AR5K_RATE_ACKSIFS_BASE 0x8680 /* Register Address */ -#define AR5K_RATE_ACKSIFS(_n) (AR5K_RATE_ACKSIFS_BSE + ((_n) << 2)) -#define AR5K_RATE_ACKSIFS_NORMAL 0x00000001 /* Normal SIFS (field) */ -#define AR5K_RATE_ACKSIFS_TURBO 0x00000400 /* Turbo SIFS (field) */ - -/* - * Rate -> duration mapping table (32 entries) - */ -#define AR5K_RATE_DUR_BASE 0x8700 -#define AR5K_RATE_DUR(_n) (AR5K_RATE_DUR_BASE + ((_n) << 2)) - -/* - * Rate -> db mapping table - * (8 entries, each one has 4 8bit fields) - */ -#define AR5K_RATE2DB_BASE 0x87c0 -#define AR5K_RATE2DB(_n) (AR5K_RATE2DB_BASE + ((_n) << 2)) - -/* - * db -> Rate mapping table - * (8 entries, each one has 4 8bit fields) - */ -#define AR5K_DB2RATE_BASE 0x87e0 -#define AR5K_DB2RATE(_n) (AR5K_DB2RATE_BASE + ((_n) << 2)) - -/*===5212 end===*/ - -/* - * Key table (WEP) register - */ -#define AR5K_KEYTABLE_0_5210 0x9000 -#define AR5K_KEYTABLE_0_5211 0x8800 -#define AR5K_KEYTABLE_5210(_n) (AR5K_KEYTABLE_0_5210 + ((_n) << 5)) -#define AR5K_KEYTABLE_5211(_n) (AR5K_KEYTABLE_0_5211 + ((_n) << 5)) -#define AR5K_KEYTABLE(_n) (ah->ah_version == AR5K_AR5210 ? \ - AR5K_KEYTABLE_5210(_n) : AR5K_KEYTABLE_5211(_n)) -#define AR5K_KEYTABLE_OFF(_n, x) (AR5K_KEYTABLE(_n) + (x << 2)) -#define AR5K_KEYTABLE_TYPE(_n) AR5K_KEYTABLE_OFF(_n, 5) -#define AR5K_KEYTABLE_TYPE_40 0x00000000 -#define AR5K_KEYTABLE_TYPE_104 0x00000001 -#define AR5K_KEYTABLE_TYPE_128 0x00000003 -#define AR5K_KEYTABLE_TYPE_TKIP 0x00000004 /* [5212+] */ -#define AR5K_KEYTABLE_TYPE_AES 0x00000005 /* [5211+] */ -#define AR5K_KEYTABLE_TYPE_CCM 0x00000006 /* [5212+] */ -#define AR5K_KEYTABLE_TYPE_NULL 0x00000007 /* [5211+] */ -#define AR5K_KEYTABLE_ANTENNA 0x00000008 /* [5212+] */ -#define AR5K_KEYTABLE_MAC0(_n) AR5K_KEYTABLE_OFF(_n, 6) -#define AR5K_KEYTABLE_MAC1(_n) AR5K_KEYTABLE_OFF(_n, 7) -#define AR5K_KEYTABLE_VALID 0x00008000 - -/* If key type is TKIP and MIC is enabled - * MIC key goes in offset entry + 64 */ -#define AR5K_KEYTABLE_MIC_OFFSET 64 - -/* WEP 40-bit = 40-bit entered key + 24 bit IV = 64-bit - * WEP 104-bit = 104-bit entered key + 24-bit IV = 128-bit - * WEP 128-bit = 128-bit entered key + 24 bit IV = 152-bit - * - * Some vendors have introduced bigger WEP keys to address - * security vulnerabilities in WEP. This includes: - * - * WEP 232-bit = 232-bit entered key + 24 bit IV = 256-bit - * - * We can expand this if we find ar5k Atheros cards with a larger - * key table size. - */ -#define AR5K_KEYTABLE_SIZE_5210 64 -#define AR5K_KEYTABLE_SIZE_5211 128 -#define AR5K_KEYTABLE_SIZE (ah->ah_version == AR5K_AR5210 ? \ - AR5K_KEYTABLE_SIZE_5210 : AR5K_KEYTABLE_SIZE_5211) - - -/*===PHY REGISTERS===*/ - -/* - * PHY registers start - */ -#define AR5K_PHY_BASE 0x9800 -#define AR5K_PHY(_n) (AR5K_PHY_BASE + ((_n) << 2)) - -/* - * TST_2 (Misc config parameters) - */ -#define AR5K_PHY_TST2 0x9800 /* Register Address */ -#define AR5K_PHY_TST2_TRIG_SEL 0x00000007 /* Trigger select (?)*/ -#define AR5K_PHY_TST2_TRIG 0x00000010 /* Trigger (?) */ -#define AR5K_PHY_TST2_CBUS_MODE 0x00000060 /* Cardbus mode (?) */ -#define AR5K_PHY_TST2_CLK32 0x00000400 /* CLK_OUT is CLK32 (32Khz external) */ -#define AR5K_PHY_TST2_CHANCOR_DUMP_EN 0x00000800 /* Enable Chancor dump (?) */ -#define AR5K_PHY_TST2_EVEN_CHANCOR_DUMP 0x00001000 /* Even Chancor dump (?) */ -#define AR5K_PHY_TST2_RFSILENT_EN 0x00002000 /* Enable RFSILENT */ -#define AR5K_PHY_TST2_ALT_RFDATA 0x00004000 /* Alternate RFDATA (5-2GHz switch ?) */ -#define AR5K_PHY_TST2_MINI_OBS_EN 0x00008000 /* Enable mini OBS (?) */ -#define AR5K_PHY_TST2_RX2_IS_RX5_INV 0x00010000 /* 2GHz rx path is the 5GHz path inverted (?) */ -#define AR5K_PHY_TST2_SLOW_CLK160 0x00020000 /* Slow CLK160 (?) */ -#define AR5K_PHY_TST2_AGC_OBS_SEL_3 0x00040000 /* AGC OBS Select 3 (?) */ -#define AR5K_PHY_TST2_BBB_OBS_SEL 0x00080000 /* BB OBS Select (field ?) */ -#define AR5K_PHY_TST2_ADC_OBS_SEL 0x00800000 /* ADC OBS Select (field ?) */ -#define AR5K_PHY_TST2_RX_CLR_SEL 0x08000000 /* RX Clear Select (?) */ -#define AR5K_PHY_TST2_FORCE_AGC_CLR 0x10000000 /* Force AGC clear (?) */ -#define AR5K_PHY_SHIFT_2GHZ 0x00004007 /* Used to access 2GHz radios */ -#define AR5K_PHY_SHIFT_5GHZ 0x00000007 /* Used to access 5GHz radios (default) */ - -/* - * PHY frame control register [5110] /turbo mode register [5111+] - * - * There is another frame control register for [5111+] - * at address 0x9944 (see below) but the 2 first flags - * are common here between 5110 frame control register - * and [5111+] turbo mode register, so this also works as - * a "turbo mode register" for 5110. We treat this one as - * a frame control register for 5110 below. - */ -#define AR5K_PHY_TURBO 0x9804 /* Register Address */ -#define AR5K_PHY_TURBO_MODE 0x00000001 /* Enable turbo mode */ -#define AR5K_PHY_TURBO_SHORT 0x00000002 /* Set short symbols to turbo mode */ -#define AR5K_PHY_TURBO_MIMO 0x00000004 /* Set turbo for mimo mimo */ - -/* - * PHY agility command register - * (aka TST_1) - */ -#define AR5K_PHY_AGC 0x9808 /* Register Address */ -#define AR5K_PHY_TST1 0x9808 -#define AR5K_PHY_AGC_DISABLE 0x08000000 /* Disable AGC to A2 (?)*/ -#define AR5K_PHY_TST1_TXHOLD 0x00003800 /* Set tx hold (?) */ -#define AR5K_PHY_TST1_TXSRC_SRC 0x00000002 /* Used with bit 7 (?) */ -#define AR5K_PHY_TST1_TXSRC_SRC_S 1 -#define AR5K_PHY_TST1_TXSRC_ALT 0x00000080 /* Set input to tsdac (?) */ -#define AR5K_PHY_TST1_TXSRC_ALT_S 7 - - -/* - * PHY timing register 3 [5112+] - */ -#define AR5K_PHY_TIMING_3 0x9814 -#define AR5K_PHY_TIMING_3_DSC_MAN 0xfffe0000 -#define AR5K_PHY_TIMING_3_DSC_MAN_S 17 -#define AR5K_PHY_TIMING_3_DSC_EXP 0x0001e000 -#define AR5K_PHY_TIMING_3_DSC_EXP_S 13 - -/* - * PHY chip revision register - */ -#define AR5K_PHY_CHIP_ID 0x9818 - -/* - * PHY activation register - */ -#define AR5K_PHY_ACT 0x981c /* Register Address */ -#define AR5K_PHY_ACT_ENABLE 0x00000001 /* Activate PHY */ -#define AR5K_PHY_ACT_DISABLE 0x00000002 /* Deactivate PHY */ - -/* - * PHY RF control registers - */ -#define AR5K_PHY_RF_CTL2 0x9824 /* Register Address */ -#define AR5K_PHY_RF_CTL2_TXF2TXD_START 0x0000000f /* TX frame to TX data start */ -#define AR5K_PHY_RF_CTL2_TXF2TXD_START_S 0 - -#define AR5K_PHY_RF_CTL3 0x9828 /* Register Address */ -#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON 0x0000ff00 /* TX end to XLNA on */ -#define AR5K_PHY_RF_CTL3_TXE2XLNA_ON_S 8 - -#define AR5K_PHY_ADC_CTL 0x982c -#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF 0x00000003 -#define AR5K_PHY_ADC_CTL_INBUFGAIN_OFF_S 0 -#define AR5K_PHY_ADC_CTL_PWD_DAC_OFF 0x00002000 -#define AR5K_PHY_ADC_CTL_PWD_BAND_GAP_OFF 0x00004000 -#define AR5K_PHY_ADC_CTL_PWD_ADC_OFF 0x00008000 -#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON 0x00030000 -#define AR5K_PHY_ADC_CTL_INBUFGAIN_ON_S 16 - -#define AR5K_PHY_RF_CTL4 0x9834 /* Register Address */ -#define AR5K_PHY_RF_CTL4_TXF2XPA_A_ON 0x00000001 /* TX frame to XPA A on (field) */ -#define AR5K_PHY_RF_CTL4_TXF2XPA_B_ON 0x00000100 /* TX frame to XPA B on (field) */ -#define AR5K_PHY_RF_CTL4_TXE2XPA_A_OFF 0x00010000 /* TX end to XPA A off (field) */ -#define AR5K_PHY_RF_CTL4_TXE2XPA_B_OFF 0x01000000 /* TX end to XPA B off (field) */ - -/* - * Pre-Amplifier control register - * (XPA -> external pre-amplifier) - */ -#define AR5K_PHY_PA_CTL 0x9838 /* Register Address */ -#define AR5K_PHY_PA_CTL_XPA_A_HI 0x00000001 /* XPA A high (?) */ -#define AR5K_PHY_PA_CTL_XPA_B_HI 0x00000002 /* XPA B high (?) */ -#define AR5K_PHY_PA_CTL_XPA_A_EN 0x00000004 /* Enable XPA A */ -#define AR5K_PHY_PA_CTL_XPA_B_EN 0x00000008 /* Enable XPA B */ - -/* - * PHY settling register - */ -#define AR5K_PHY_SETTLING 0x9844 /* Register Address */ -#define AR5K_PHY_SETTLING_AGC 0x0000007f /* AGC settling time */ -#define AR5K_PHY_SETTLING_AGC_S 0 -#define AR5K_PHY_SETTLING_SWITCH 0x00003f80 /* Switch settlig time */ -#define AR5K_PHY_SETTLING_SWITCH_S 7 - -/* - * PHY Gain registers - */ -#define AR5K_PHY_GAIN 0x9848 /* Register Address */ -#define AR5K_PHY_GAIN_TXRX_ATTEN 0x0003f000 /* TX-RX Attenuation */ -#define AR5K_PHY_GAIN_TXRX_ATTEN_S 12 -#define AR5K_PHY_GAIN_TXRX_RF_MAX 0x007c0000 -#define AR5K_PHY_GAIN_TXRX_RF_MAX_S 18 - -#define AR5K_PHY_GAIN_OFFSET 0x984c /* Register Address */ -#define AR5K_PHY_GAIN_OFFSET_RXTX_FLAG 0x00020000 /* RX-TX flag (?) */ - -/* - * Desired ADC/PGA size register - * (for more infos read ANI patent) - */ -#define AR5K_PHY_DESIRED_SIZE 0x9850 /* Register Address */ -#define AR5K_PHY_DESIRED_SIZE_ADC 0x000000ff /* ADC desired size */ -#define AR5K_PHY_DESIRED_SIZE_ADC_S 0 -#define AR5K_PHY_DESIRED_SIZE_PGA 0x0000ff00 /* PGA desired size */ -#define AR5K_PHY_DESIRED_SIZE_PGA_S 8 -#define AR5K_PHY_DESIRED_SIZE_TOT 0x0ff00000 /* Total desired size */ -#define AR5K_PHY_DESIRED_SIZE_TOT_S 20 - -/* - * PHY signal register - * (for more infos read ANI patent) - */ -#define AR5K_PHY_SIG 0x9858 /* Register Address */ -#define AR5K_PHY_SIG_FIRSTEP 0x0003f000 /* FIRSTEP */ -#define AR5K_PHY_SIG_FIRSTEP_S 12 -#define AR5K_PHY_SIG_FIRPWR 0x03fc0000 /* FIPWR */ -#define AR5K_PHY_SIG_FIRPWR_S 18 - -/* - * PHY coarse agility control register - * (for more infos read ANI patent) - */ -#define AR5K_PHY_AGCCOARSE 0x985c /* Register Address */ -#define AR5K_PHY_AGCCOARSE_LO 0x00007f80 /* AGC Coarse low */ -#define AR5K_PHY_AGCCOARSE_LO_S 7 -#define AR5K_PHY_AGCCOARSE_HI 0x003f8000 /* AGC Coarse high */ -#define AR5K_PHY_AGCCOARSE_HI_S 15 - -/* - * PHY agility control register - */ -#define AR5K_PHY_AGCCTL 0x9860 /* Register address */ -#define AR5K_PHY_AGCCTL_CAL 0x00000001 /* Enable PHY calibration */ -#define AR5K_PHY_AGCCTL_NF 0x00000002 /* Enable Noise Floor calibration */ -#define AR5K_PHY_AGCCTL_OFDM_DIV_DIS 0x00000008 /* Disable antenna diversity on OFDM modes */ -#define AR5K_PHY_AGCCTL_NF_EN 0x00008000 /* Enable nf calibration to happen (?) */ -#define AR5K_PHY_AGCTL_FLTR_CAL 0x00010000 /* Allow filter calibration (?) */ -#define AR5K_PHY_AGCCTL_NF_NOUPDATE 0x00020000 /* Don't update nf automaticaly */ - -/* - * PHY noise floor status register - */ -#define AR5K_PHY_NF 0x9864 /* Register address */ -#define AR5K_PHY_NF_M 0x000001ff /* Noise floor mask */ -#define AR5K_PHY_NF_ACTIVE 0x00000100 /* Noise floor calibration still active */ -#define AR5K_PHY_NF_RVAL(_n) (((_n) >> 19) & AR5K_PHY_NF_M) -#define AR5K_PHY_NF_AVAL(_n) (-((_n) ^ AR5K_PHY_NF_M) + 1) -#define AR5K_PHY_NF_SVAL(_n) (((_n) & AR5K_PHY_NF_M) | (1 << 9)) -#define AR5K_PHY_NF_THRESH62 0x0007f000 /* Thresh62 -check ANI patent- (field) */ -#define AR5K_PHY_NF_THRESH62_S 12 -#define AR5K_PHY_NF_MINCCA_PWR 0x0ff80000 /* ??? */ -#define AR5K_PHY_NF_MINCCA_PWR_S 19 - -/* - * PHY ADC saturation register [5110] - */ -#define AR5K_PHY_ADCSAT 0x9868 -#define AR5K_PHY_ADCSAT_ICNT 0x0001f800 -#define AR5K_PHY_ADCSAT_ICNT_S 11 -#define AR5K_PHY_ADCSAT_THR 0x000007e0 -#define AR5K_PHY_ADCSAT_THR_S 5 - -/* - * PHY Weak ofdm signal detection threshold registers (ANI) [5212+] - */ - -/* High thresholds */ -#define AR5K_PHY_WEAK_OFDM_HIGH_THR 0x9868 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT 0x0000001f -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_COUNT_S 0 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1 0x00fe0000 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M1_S 17 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2 0x7f000000 -#define AR5K_PHY_WEAK_OFDM_HIGH_THR_M2_S 24 - -/* Low thresholds */ -#define AR5K_PHY_WEAK_OFDM_LOW_THR 0x986c -#define AR5K_PHY_WEAK_OFDM_LOW_THR_SELFCOR_EN 0x00000001 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT 0x00003f00 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_COUNT_S 8 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1 0x001fc000 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M1_S 14 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2 0x0fe00000 -#define AR5K_PHY_WEAK_OFDM_LOW_THR_M2_S 21 - - -/* - * PHY sleep registers [5112+] - */ -#define AR5K_PHY_SCR 0x9870 - -#define AR5K_PHY_SLMT 0x9874 -#define AR5K_PHY_SLMT_32MHZ 0x0000007f - -#define AR5K_PHY_SCAL 0x9878 -#define AR5K_PHY_SCAL_32MHZ 0x0000000e -#define AR5K_PHY_SCAL_32MHZ_2417 0x0000000a -#define AR5K_PHY_SCAL_32MHZ_HB63 0x00000032 - -/* - * PHY PLL (Phase Locked Loop) control register - */ -#define AR5K_PHY_PLL 0x987c -#define AR5K_PHY_PLL_20MHZ 0x00000013 /* For half rate (?) */ -/* 40MHz -> 5GHz band */ -#define AR5K_PHY_PLL_40MHZ_5211 0x00000018 -#define AR5K_PHY_PLL_40MHZ_5212 0x000000aa -#define AR5K_PHY_PLL_40MHZ_5413 0x00000004 -#define AR5K_PHY_PLL_40MHZ (ah->ah_version == AR5K_AR5211 ? \ - AR5K_PHY_PLL_40MHZ_5211 : AR5K_PHY_PLL_40MHZ_5212) -/* 44MHz -> 2.4GHz band */ -#define AR5K_PHY_PLL_44MHZ_5211 0x00000019 -#define AR5K_PHY_PLL_44MHZ_5212 0x000000ab -#define AR5K_PHY_PLL_44MHZ (ah->ah_version == AR5K_AR5211 ? \ - AR5K_PHY_PLL_44MHZ_5211 : AR5K_PHY_PLL_44MHZ_5212) - -#define AR5K_PHY_PLL_RF5111 0x00000000 -#define AR5K_PHY_PLL_RF5112 0x00000040 -#define AR5K_PHY_PLL_HALF_RATE 0x00000100 -#define AR5K_PHY_PLL_QUARTER_RATE 0x00000200 - -/* - * RF Buffer register - * - * It's obvious from the code that 0x989c is the buffer register but - * for the other special registers that we write to after sending each - * packet, i have no idea. So i'll name them BUFFER_CONTROL_X registers - * for now. It's interesting that they are also used for some other operations. - */ - -#define AR5K_RF_BUFFER 0x989c -#define AR5K_RF_BUFFER_CONTROL_0 0x98c0 /* Channel on 5110 */ -#define AR5K_RF_BUFFER_CONTROL_1 0x98c4 /* Bank 7 on 5112 */ -#define AR5K_RF_BUFFER_CONTROL_2 0x98cc /* Bank 7 on 5111 */ - -#define AR5K_RF_BUFFER_CONTROL_3 0x98d0 /* Bank 2 on 5112 */ - /* Channel set on 5111 */ - /* Used to read radio revision*/ - -#define AR5K_RF_BUFFER_CONTROL_4 0x98d4 /* RF Stage register on 5110 */ - /* Bank 0,1,2,6 on 5111 */ - /* Bank 1 on 5112 */ - /* Used during activation on 5111 */ - -#define AR5K_RF_BUFFER_CONTROL_5 0x98d8 /* Bank 3 on 5111 */ - /* Used during activation on 5111 */ - /* Channel on 5112 */ - /* Bank 6 on 5112 */ - -#define AR5K_RF_BUFFER_CONTROL_6 0x98dc /* Bank 3 on 5112 */ - -/* - * PHY RF stage register [5210] - */ -#define AR5K_PHY_RFSTG 0x98d4 -#define AR5K_PHY_RFSTG_DISABLE 0x00000021 - -/* - * BIN masks (?) - */ -#define AR5K_PHY_BIN_MASK_1 0x9900 -#define AR5K_PHY_BIN_MASK_2 0x9904 -#define AR5K_PHY_BIN_MASK_3 0x9908 - -#define AR5K_PHY_BIN_MASK_CTL 0x990c -#define AR5K_PHY_BIN_MASK_CTL_MASK_4 0x00003fff -#define AR5K_PHY_BIN_MASK_CTL_MASK_4_S 0 -#define AR5K_PHY_BIN_MASK_CTL_RATE 0xff000000 -#define AR5K_PHY_BIN_MASK_CTL_RATE_S 24 - -/* - * PHY Antenna control register - */ -#define AR5K_PHY_ANT_CTL 0x9910 /* Register Address */ -#define AR5K_PHY_ANT_CTL_TXRX_EN 0x00000001 /* Enable TX/RX (?) */ -#define AR5K_PHY_ANT_CTL_SECTORED_ANT 0x00000004 /* Sectored Antenna */ -#define AR5K_PHY_ANT_CTL_HITUNE5 0x00000008 /* Hitune5 (?) */ -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE 0x000003f0 /* Switch table idle (?) */ -#define AR5K_PHY_ANT_CTL_SWTABLE_IDLE_S 4 - -/* - * PHY receiver delay register [5111+] - */ -#define AR5K_PHY_RX_DELAY 0x9914 /* Register Address */ -#define AR5K_PHY_RX_DELAY_M 0x00003fff /* Mask for RX activate to receive delay (/100ns) */ - -/* - * PHY max rx length register (?) [5111] - */ -#define AR5K_PHY_MAX_RX_LEN 0x991c - -/* - * PHY timing register 4 - * I(nphase)/Q(adrature) calibration register [5111+] - */ -#define AR5K_PHY_IQ 0x9920 /* Register Address */ -#define AR5K_PHY_IQ_CORR_Q_Q_COFF 0x0000001f /* Mask for q correction info */ -#define AR5K_PHY_IQ_CORR_Q_I_COFF 0x000007e0 /* Mask for i correction info */ -#define AR5K_PHY_IQ_CORR_Q_I_COFF_S 5 -#define AR5K_PHY_IQ_CORR_ENABLE 0x00000800 /* Enable i/q correction */ -#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX 0x0000f000 /* Mask for max number of samples in log scale */ -#define AR5K_PHY_IQ_CAL_NUM_LOG_MAX_S 12 -#define AR5K_PHY_IQ_RUN 0x00010000 /* Run i/q calibration */ -#define AR5K_PHY_IQ_USE_PT_DF 0x00020000 /* Use pilot track df (?) */ -#define AR5K_PHY_IQ_EARLY_TRIG_THR 0x00200000 /* Early trigger threshold (?) (field) */ -#define AR5K_PHY_IQ_PILOT_MASK_EN 0x10000000 /* Enable pilot mask (?) */ -#define AR5K_PHY_IQ_CHAN_MASK_EN 0x20000000 /* Enable channel mask (?) */ -#define AR5K_PHY_IQ_SPUR_FILT_EN 0x40000000 /* Enable spur filter */ -#define AR5K_PHY_IQ_SPUR_RSSI_EN 0x80000000 /* Enable spur rssi */ - -/* - * PHY timing register 5 - * OFDM Self-correlator Cyclic RSSI threshold params - * (Check out bb_cycpwr_thr1 on ANI patent) - */ -#define AR5K_PHY_OFDM_SELFCORR 0x9924 /* Register Address */ -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_EN 0x00000001 /* Enable cyclic RSSI thr 1 */ -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1 0x000000fe /* Mask for Cyclic RSSI threshold 1 */ -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1_S 1 -#define AR5K_PHY_OFDM_SELFCORR_CYPWR_THR3 0x00000100 /* Cyclic RSSI threshold 3 (field) (?) */ -#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR_EN 0x00008000 /* Enable 1A RSSI threshold (?) */ -#define AR5K_PHY_OFDM_SELFCORR_RSSI_1ATHR 0x00010000 /* 1A RSSI threshold (field) (?) */ -#define AR5K_PHY_OFDM_SELFCORR_LSCTHR_HIRSSI 0x00800000 /* Long sc threshold hi rssi (?) */ - -/* - * PHY-only warm reset register - */ -#define AR5K_PHY_WARM_RESET 0x9928 - -/* - * PHY-only control register - */ -#define AR5K_PHY_CTL 0x992c /* Register Address */ -#define AR5K_PHY_CTL_RX_DRAIN_RATE 0x00000001 /* RX drain rate (?) */ -#define AR5K_PHY_CTL_LATE_TX_SIG_SYM 0x00000002 /* Late tx signal symbol (?) */ -#define AR5K_PHY_CTL_GEN_SCRAMBLER 0x00000004 /* Generate scrambler */ -#define AR5K_PHY_CTL_TX_ANT_SEL 0x00000008 /* TX antenna select */ -#define AR5K_PHY_CTL_TX_ANT_STATIC 0x00000010 /* Static TX antenna */ -#define AR5K_PHY_CTL_RX_ANT_SEL 0x00000020 /* RX antenna select */ -#define AR5K_PHY_CTL_RX_ANT_STATIC 0x00000040 /* Static RX antenna */ -#define AR5K_PHY_CTL_LOW_FREQ_SLE_EN 0x00000080 /* Enable low freq sleep */ - -/* - * PHY PAPD probe register [5111+] - */ -#define AR5K_PHY_PAPD_PROBE 0x9930 -#define AR5K_PHY_PAPD_PROBE_SH_HI_PAR 0x00000001 -#define AR5K_PHY_PAPD_PROBE_PCDAC_BIAS 0x00000002 -#define AR5K_PHY_PAPD_PROBE_COMP_GAIN 0x00000040 -#define AR5K_PHY_PAPD_PROBE_TXPOWER 0x00007e00 -#define AR5K_PHY_PAPD_PROBE_TXPOWER_S 9 -#define AR5K_PHY_PAPD_PROBE_TX_NEXT 0x00008000 -#define AR5K_PHY_PAPD_PROBE_PREDIST_EN 0x00010000 -#define AR5K_PHY_PAPD_PROBE_TYPE 0x01800000 /* [5112+] */ -#define AR5K_PHY_PAPD_PROBE_TYPE_S 23 -#define AR5K_PHY_PAPD_PROBE_TYPE_OFDM 0 -#define AR5K_PHY_PAPD_PROBE_TYPE_XR 1 -#define AR5K_PHY_PAPD_PROBE_TYPE_CCK 2 -#define AR5K_PHY_PAPD_PROBE_GAINF 0xfe000000 -#define AR5K_PHY_PAPD_PROBE_GAINF_S 25 -#define AR5K_PHY_PAPD_PROBE_INI_5111 0x00004883 /* [5212+] */ -#define AR5K_PHY_PAPD_PROBE_INI_5112 0x00004882 /* [5212+] */ - -/* - * PHY TX rate power registers [5112+] - */ -#define AR5K_PHY_TXPOWER_RATE1 0x9934 -#define AR5K_PHY_TXPOWER_RATE2 0x9938 -#define AR5K_PHY_TXPOWER_RATE_MAX 0x993c -#define AR5K_PHY_TXPOWER_RATE_MAX_TPC_ENABLE 0x00000040 -#define AR5K_PHY_TXPOWER_RATE3 0xa234 -#define AR5K_PHY_TXPOWER_RATE4 0xa238 - -/* - * PHY frame control register [5111+] - */ -#define AR5K_PHY_FRAME_CTL_5210 0x9804 -#define AR5K_PHY_FRAME_CTL_5211 0x9944 -#define AR5K_PHY_FRAME_CTL (ah->ah_version == AR5K_AR5210 ? \ - AR5K_PHY_FRAME_CTL_5210 : AR5K_PHY_FRAME_CTL_5211) -/*---[5111+]---*/ -#define AR5K_PHY_FRAME_CTL_TX_CLIP 0x00000038 /* Mask for tx clip (?) */ -#define AR5K_PHY_FRAME_CTL_TX_CLIP_S 3 -#define AR5K_PHY_FRAME_CTL_PREP_CHINFO 0x00010000 /* Prepend chan info */ -#define AR5K_PHY_FRAME_CTL_EMU 0x80000000 -#define AR5K_PHY_FRAME_CTL_EMU_S 31 -/*---[5110/5111]---*/ -#define AR5K_PHY_FRAME_CTL_TIMING_ERR 0x01000000 /* PHY timing error */ -#define AR5K_PHY_FRAME_CTL_PARITY_ERR 0x02000000 /* Parity error */ -#define AR5K_PHY_FRAME_CTL_ILLRATE_ERR 0x04000000 /* Illegal rate */ -#define AR5K_PHY_FRAME_CTL_ILLLEN_ERR 0x08000000 /* Illegal length */ -#define AR5K_PHY_FRAME_CTL_SERVICE_ERR 0x20000000 -#define AR5K_PHY_FRAME_CTL_TXURN_ERR 0x40000000 /* TX underrun */ -#define AR5K_PHY_FRAME_CTL_INI AR5K_PHY_FRAME_CTL_SERVICE_ERR | \ - AR5K_PHY_FRAME_CTL_TXURN_ERR | \ - AR5K_PHY_FRAME_CTL_ILLLEN_ERR | \ - AR5K_PHY_FRAME_CTL_ILLRATE_ERR | \ - AR5K_PHY_FRAME_CTL_PARITY_ERR | \ - AR5K_PHY_FRAME_CTL_TIMING_ERR - -/* - * PHY Tx Power adjustment register [5212A+] - */ -#define AR5K_PHY_TX_PWR_ADJ 0x994c -#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA 0x00000fc0 -#define AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA_S 6 -#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX 0x00fc0000 -#define AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX_S 18 - -/* - * PHY radar detection register [5111+] - */ -#define AR5K_PHY_RADAR 0x9954 -#define AR5K_PHY_RADAR_ENABLE 0x00000001 -#define AR5K_PHY_RADAR_DISABLE 0x00000000 -#define AR5K_PHY_RADAR_INBANDTHR 0x0000003e /* Inband threshold - 5-bits, units unknown {0..31} - (? MHz ?) */ -#define AR5K_PHY_RADAR_INBANDTHR_S 1 - -#define AR5K_PHY_RADAR_PRSSI_THR 0x00000fc0 /* Pulse RSSI/SNR threshold - 6-bits, dBm range {0..63} - in dBm units. */ -#define AR5K_PHY_RADAR_PRSSI_THR_S 6 - -#define AR5K_PHY_RADAR_PHEIGHT_THR 0x0003f000 /* Pulse height threshold - 6-bits, dBm range {0..63} - in dBm units. */ -#define AR5K_PHY_RADAR_PHEIGHT_THR_S 12 - -#define AR5K_PHY_RADAR_RSSI_THR 0x00fc0000 /* Radar RSSI/SNR threshold. - 6-bits, dBm range {0..63} - in dBm units. */ -#define AR5K_PHY_RADAR_RSSI_THR_S 18 - -#define AR5K_PHY_RADAR_FIRPWR_THR 0x7f000000 /* Finite Impulse Response - filter power out threshold. - 7-bits, standard power range - {0..127} in 1/2 dBm units. */ -#define AR5K_PHY_RADAR_FIRPWR_THRS 24 - -/* - * PHY antenna switch table registers - */ -#define AR5K_PHY_ANT_SWITCH_TABLE_0 0x9960 -#define AR5K_PHY_ANT_SWITCH_TABLE_1 0x9964 - -/* - * PHY Noise floor threshold - */ -#define AR5K_PHY_NFTHRES 0x9968 - -/* - * Sigma Delta register (?) [5213] - */ -#define AR5K_PHY_SIGMA_DELTA 0x996C -#define AR5K_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 -#define AR5K_PHY_SIGMA_DELTA_ADC_SEL_S 0 -#define AR5K_PHY_SIGMA_DELTA_FILT2 0x000000f8 -#define AR5K_PHY_SIGMA_DELTA_FILT2_S 3 -#define AR5K_PHY_SIGMA_DELTA_FILT1 0x00001f00 -#define AR5K_PHY_SIGMA_DELTA_FILT1_S 8 -#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP 0x01ffe000 -#define AR5K_PHY_SIGMA_DELTA_ADC_CLIP_S 13 - -/* - * RF restart register [5112+] (?) - */ -#define AR5K_PHY_RESTART 0x9970 /* restart */ -#define AR5K_PHY_RESTART_DIV_GC 0x001c0000 /* Fast diversity gc_limit (?) */ -#define AR5K_PHY_RESTART_DIV_GC_S 18 - -/* - * RF Bus access request register (for synth-oly channel switching) - */ -#define AR5K_PHY_RFBUS_REQ 0x997C -#define AR5K_PHY_RFBUS_REQ_REQUEST 0x00000001 - -/* - * Spur mitigation masks (?) - */ -#define AR5K_PHY_TIMING_7 0x9980 -#define AR5K_PHY_TIMING_8 0x9984 -#define AR5K_PHY_TIMING_8_PILOT_MASK_2 0x000fffff -#define AR5K_PHY_TIMING_8_PILOT_MASK_2_S 0 - -#define AR5K_PHY_BIN_MASK2_1 0x9988 -#define AR5K_PHY_BIN_MASK2_2 0x998c -#define AR5K_PHY_BIN_MASK2_3 0x9990 - -#define AR5K_PHY_BIN_MASK2_4 0x9994 -#define AR5K_PHY_BIN_MASK2_4_MASK_4 0x00003fff -#define AR5K_PHY_BIN_MASK2_4_MASK_4_S 0 - -#define AR5K_PHY_TIMING_9 0x9998 -#define AR5K_PHY_TIMING_10 0x999c -#define AR5K_PHY_TIMING_10_PILOT_MASK_2 0x000fffff -#define AR5K_PHY_TIMING_10_PILOT_MASK_2_S 0 - -/* - * Spur mitigation control - */ -#define AR5K_PHY_TIMING_11 0x99a0 /* Register address */ -#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE 0x000fffff /* Spur delta phase */ -#define AR5K_PHY_TIMING_11_SPUR_DELTA_PHASE_S 0 -#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD 0x3ff00000 /* Freq sigma delta */ -#define AR5K_PHY_TIMING_11_SPUR_FREQ_SD_S 20 -#define AR5K_PHY_TIMING_11_USE_SPUR_IN_AGC 0x40000000 /* Spur filter in AGC detector */ -#define AR5K_PHY_TIMING_11_USE_SPUR_IN_SELFCOR 0x80000000 /* Spur filter in OFDM self correlator */ - -/* - * Gain tables - */ -#define AR5K_BB_GAIN_BASE 0x9b00 /* BaseBand Amplifier Gain table base address */ -#define AR5K_BB_GAIN(_n) (AR5K_BB_GAIN_BASE + ((_n) << 2)) -#define AR5K_RF_GAIN_BASE 0x9a00 /* RF Amplrifier Gain table base address */ -#define AR5K_RF_GAIN(_n) (AR5K_RF_GAIN_BASE + ((_n) << 2)) - -/* - * PHY timing IQ calibration result register [5111+] - */ -#define AR5K_PHY_IQRES_CAL_PWR_I 0x9c10 /* I (Inphase) power value */ -#define AR5K_PHY_IQRES_CAL_PWR_Q 0x9c14 /* Q (Quadrature) power value */ -#define AR5K_PHY_IQRES_CAL_CORR 0x9c18 /* I/Q Correlation */ - -/* - * PHY current RSSI register [5111+] - */ -#define AR5K_PHY_CURRENT_RSSI 0x9c1c - -/* - * PHY RF Bus grant register - */ -#define AR5K_PHY_RFBUS_GRANT 0x9c20 -#define AR5K_PHY_RFBUS_GRANT_OK 0x00000001 - -/* - * PHY ADC test register - */ -#define AR5K_PHY_ADC_TEST 0x9c24 -#define AR5K_PHY_ADC_TEST_I 0x00000001 -#define AR5K_PHY_ADC_TEST_Q 0x00000200 - -/* - * PHY DAC test register - */ -#define AR5K_PHY_DAC_TEST 0x9c28 -#define AR5K_PHY_DAC_TEST_I 0x00000001 -#define AR5K_PHY_DAC_TEST_Q 0x00000200 - -/* - * PHY PTAT register (?) - */ -#define AR5K_PHY_PTAT 0x9c2c - -/* - * PHY Illegal TX rate register [5112+] - */ -#define AR5K_PHY_BAD_TX_RATE 0x9c30 - -/* - * PHY SPUR Power register [5112+] - */ -#define AR5K_PHY_SPUR_PWR 0x9c34 /* Register Address */ -#define AR5K_PHY_SPUR_PWR_I 0x00000001 /* SPUR Power estimate for I (field) */ -#define AR5K_PHY_SPUR_PWR_Q 0x00000100 /* SPUR Power estimate for Q (field) */ -#define AR5K_PHY_SPUR_PWR_FILT 0x00010000 /* Power with SPUR removed (field) */ - -/* - * PHY Channel status register [5112+] (?) - */ -#define AR5K_PHY_CHAN_STATUS 0x9c38 -#define AR5K_PHY_CHAN_STATUS_BT_ACT 0x00000001 -#define AR5K_PHY_CHAN_STATUS_RX_CLR_RAW 0x00000002 -#define AR5K_PHY_CHAN_STATUS_RX_CLR_MAC 0x00000004 -#define AR5K_PHY_CHAN_STATUS_RX_CLR_PAP 0x00000008 - -/* - * Heavy clip enable register - */ -#define AR5K_PHY_HEAVY_CLIP_ENABLE 0x99e0 - -/* - * PHY clock sleep registers [5112+] - */ -#define AR5K_PHY_SCLOCK 0x99f0 -#define AR5K_PHY_SCLOCK_32MHZ 0x0000000c -#define AR5K_PHY_SDELAY 0x99f4 -#define AR5K_PHY_SDELAY_32MHZ 0x000000ff -#define AR5K_PHY_SPENDING 0x99f8 - - -/* - * PHY PAPD I (power?) table (?) - * (92! entries) - */ -#define AR5K_PHY_PAPD_I_BASE 0xa000 -#define AR5K_PHY_PAPD_I(_n) (AR5K_PHY_PAPD_I_BASE + ((_n) << 2)) - -/* - * PHY PCDAC TX power table - */ -#define AR5K_PHY_PCDAC_TXPOWER_BASE 0xa180 -#define AR5K_PHY_PCDAC_TXPOWER(_n) (AR5K_PHY_PCDAC_TXPOWER_BASE + ((_n) << 2)) - -/* - * PHY mode register [5111+] - */ -#define AR5K_PHY_MODE 0x0a200 /* Register Address */ -#define AR5K_PHY_MODE_MOD 0x00000001 /* PHY Modulation bit */ -#define AR5K_PHY_MODE_MOD_OFDM 0 -#define AR5K_PHY_MODE_MOD_CCK 1 -#define AR5K_PHY_MODE_FREQ 0x00000002 /* Freq mode bit */ -#define AR5K_PHY_MODE_FREQ_5GHZ 0 -#define AR5K_PHY_MODE_FREQ_2GHZ 2 -#define AR5K_PHY_MODE_MOD_DYN 0x00000004 /* Enable Dynamic OFDM/CCK mode [5112+] */ -#define AR5K_PHY_MODE_RAD 0x00000008 /* [5212+] */ -#define AR5K_PHY_MODE_RAD_RF5111 0 -#define AR5K_PHY_MODE_RAD_RF5112 8 -#define AR5K_PHY_MODE_XR 0x00000010 /* Enable XR mode [5112+] */ -#define AR5K_PHY_MODE_HALF_RATE 0x00000020 /* Enable Half rate (test) */ -#define AR5K_PHY_MODE_QUARTER_RATE 0x00000040 /* Enable Quarter rat (test) */ - -/* - * PHY CCK transmit control register [5111+ (?)] - */ -#define AR5K_PHY_CCKTXCTL 0xa204 -#define AR5K_PHY_CCKTXCTL_WORLD 0x00000000 -#define AR5K_PHY_CCKTXCTL_JAPAN 0x00000010 -#define AR5K_PHY_CCKTXCTL_SCRAMBLER_DIS 0x00000001 -#define AR5K_PHY_CCKTXCTK_DAC_SCALE 0x00000004 - -/* - * PHY CCK Cross-correlator Barker RSSI threshold register [5212+] - */ -#define AR5K_PHY_CCK_CROSSCORR 0xa208 -#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR 0x0000003f -#define AR5K_PHY_CCK_CROSSCORR_WEAK_SIG_THR_S 0 - -/* Same address is used for antenna diversity activation */ -#define AR5K_PHY_FAST_ANT_DIV 0xa208 -#define AR5K_PHY_FAST_ANT_DIV_EN 0x00002000 - -/* - * PHY 2GHz gain register [5111+] - */ -#define AR5K_PHY_GAIN_2GHZ 0xa20c -#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX 0x00fc0000 -#define AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX_S 18 -#define AR5K_PHY_GAIN_2GHZ_INI_5111 0x6480416c - -#define AR5K_PHY_CCK_RX_CTL_4 0xa21c -#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT 0x01f80000 -#define AR5K_PHY_CCK_RX_CTL_4_FREQ_EST_SHORT_S 19 - -#define AR5K_PHY_DAG_CCK_CTL 0xa228 -#define AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR 0x00000200 -#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR 0x0001fc00 -#define AR5K_PHY_DAG_CCK_CTL_RSSI_THR_S 10 - -#define AR5K_PHY_FAST_ADC 0xa24c - -#define AR5K_PHY_BLUETOOTH 0xa254 - -/* - * Transmit Power Control register - * [2413+] - */ -#define AR5K_PHY_TPC_RG1 0xa258 -#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN 0x0000c000 -#define AR5K_PHY_TPC_RG1_NUM_PD_GAIN_S 14 -#define AR5K_PHY_TPC_RG1_PDGAIN_1 0x00030000 -#define AR5K_PHY_TPC_RG1_PDGAIN_1_S 16 -#define AR5K_PHY_TPC_RG1_PDGAIN_2 0x000c0000 -#define AR5K_PHY_TPC_RG1_PDGAIN_2_S 18 -#define AR5K_PHY_TPC_RG1_PDGAIN_3 0x00300000 -#define AR5K_PHY_TPC_RG1_PDGAIN_3_S 20 - -#define AR5K_PHY_TPC_RG5 0xa26C -#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP 0x0000000F -#define AR5K_PHY_TPC_RG5_PD_GAIN_OVERLAP_S 0 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1 0x000003F0 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_1_S 4 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2 0x0000FC00 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_2_S 10 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3 0x003F0000 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_3_S 16 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4 0x0FC00000 -#define AR5K_PHY_TPC_RG5_PD_GAIN_BOUNDARY_4_S 22 - -/* - * PHY PDADC Tx power table - */ -#define AR5K_PHY_PDADC_TXPOWER_BASE 0xa280 -#define AR5K_PHY_PDADC_TXPOWER(_n) (AR5K_PHY_PDADC_TXPOWER_BASE + ((_n) << 2)) diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c deleted file mode 100644 index 257ea18c849f..000000000000 --- a/drivers/net/wireless/ath/ath5k/reset.c +++ /dev/null @@ -1,1398 +0,0 @@ -/* - * Copyright (c) 2004-2008 Reyk Floeter - * Copyright (c) 2006-2008 Nick Kossifidis - * Copyright (c) 2007-2008 Luis Rodriguez - * Copyright (c) 2007-2008 Pavel Roskin - * Copyright (c) 2007-2008 Jiri Slaby - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -#define _ATH5K_RESET - -/*****************************\ - Reset functions and helpers -\*****************************/ - -#include /* To determine if a card is pci-e */ -#include -#include "ath5k.h" -#include "reg.h" -#include "base.h" -#include "debug.h" - -/** - * ath5k_hw_write_ofdm_timings - set OFDM timings on AR5212 - * - * @ah: the &struct ath5k_hw - * @channel: the currently set channel upon reset - * - * Write the delta slope coefficient (used on pilot tracking ?) for OFDM - * operation on the AR5212 upon reset. This is a helper for ath5k_hw_reset(). - * - * Since delta slope is floating point we split it on its exponent and - * mantissa and provide these values on hw. - * - * For more infos i think this patent is related - * http://www.freepatentsonline.com/7184495.html - */ -static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - /* Get exponent and mantissa and set it */ - u32 coef_scaled, coef_exp, coef_man, - ds_coef_exp, ds_coef_man, clock; - - BUG_ON(!(ah->ah_version == AR5K_AR5212) || - !(channel->hw_value & CHANNEL_OFDM)); - - /* Get coefficient - * ALGO: coef = (5 * clock * carrier_freq) / 2) - * we scale coef by shifting clock value by 24 for - * better precision since we use integers */ - /* TODO: Half/quarter rate */ - clock = ath5k_hw_htoclock(1, channel->hw_value & CHANNEL_TURBO); - - coef_scaled = ((5 * (clock << 24)) / 2) / channel->center_freq; - - /* Get exponent - * ALGO: coef_exp = 14 - highest set bit position */ - coef_exp = ilog2(coef_scaled); - - /* Doesn't make sense if it's zero*/ - if (!coef_scaled || !coef_exp) - return -EINVAL; - - /* Note: we've shifted coef_scaled by 24 */ - coef_exp = 14 - (coef_exp - 24); - - - /* Get mantissa (significant digits) - * ALGO: coef_mant = floor(coef_scaled* 2^coef_exp+0.5) */ - coef_man = coef_scaled + - (1 << (24 - coef_exp - 1)); - - /* Calculate delta slope coefficient exponent - * and mantissa (remove scaling) and set them on hw */ - ds_coef_man = coef_man >> (24 - coef_exp); - ds_coef_exp = coef_exp - 16; - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_MAN, ds_coef_man); - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_TIMING_3, - AR5K_PHY_TIMING_3_DSC_EXP, ds_coef_exp); - - return 0; -} - - -/* - * index into rates for control rates, we can set it up like this because - * this is only used for AR5212 and we know it supports G mode - */ -static const unsigned int control_rates[] = - { 0, 1, 1, 1, 4, 4, 6, 6, 8, 8, 8, 8 }; - -/** - * ath5k_hw_write_rate_duration - fill rate code to duration table - * - * @ah: the &struct ath5k_hw - * @mode: one of enum ath5k_driver_mode - * - * Write the rate code to duration table upon hw reset. This is a helper for - * ath5k_hw_reset(). It seems all this is doing is setting an ACK timeout on - * the hardware, based on current mode, for each rate. The rates which are - * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have - * different rate code so we write their value twice (one for long preample - * and one for short). - * - * Note: Band doesn't matter here, if we set the values for OFDM it works - * on both a and g modes. So all we have to do is set values for all g rates - * that include all OFDM and CCK rates. If we operate in turbo or xr/half/ - * quarter rate mode, we need to use another set of bitrates (that's why we - * need the mode parameter) but we don't handle these proprietary modes yet. - */ -static inline void ath5k_hw_write_rate_duration(struct ath5k_hw *ah, - unsigned int mode) -{ - struct ath5k_softc *sc = ah->ah_sc; - struct ieee80211_rate *rate; - unsigned int i; - - /* Write rate duration table */ - for (i = 0; i < sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates; i++) { - u32 reg; - u16 tx_time; - - rate = &sc->sbands[IEEE80211_BAND_2GHZ].bitrates[control_rates[i]]; - - /* Set ACK timeout */ - reg = AR5K_RATE_DUR(rate->hw_value); - - /* An ACK frame consists of 10 bytes. If you add the FCS, - * which ieee80211_generic_frame_duration() adds, - * its 14 bytes. Note we use the control rate and not the - * actual rate for this rate. See mac80211 tx.c - * ieee80211_duration() for a brief description of - * what rate we should choose to TX ACKs. */ - tx_time = le16_to_cpu(ieee80211_generic_frame_duration(sc->hw, - sc->vif, 10, rate)); - - ath5k_hw_reg_write(ah, tx_time, reg); - - if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) - continue; - - /* - * We're not distinguishing short preamble here, - * This is true, all we'll get is a longer value here - * which is not necessarilly bad. We could use - * export ieee80211_frame_duration() but that needs to be - * fixed first to be properly used by mac802111 drivers: - * - * - remove erp stuff and let the routine figure ofdm - * erp rates - * - remove passing argument ieee80211_local as - * drivers don't have access to it - * - move drivers using ieee80211_generic_frame_duration() - * to this - */ - ath5k_hw_reg_write(ah, tx_time, - reg + (AR5K_SET_SHORT_PREAMBLE << 2)); - } -} - -/* - * Reset chipset - */ -static int ath5k_hw_nic_reset(struct ath5k_hw *ah, u32 val) -{ - int ret; - u32 mask = val ? val : ~0U; - - ATH5K_TRACE(ah->ah_sc); - - /* Read-and-clear RX Descriptor Pointer*/ - ath5k_hw_reg_read(ah, AR5K_RXDP); - - /* - * Reset the device and wait until success - */ - ath5k_hw_reg_write(ah, val, AR5K_RESET_CTL); - - /* Wait at least 128 PCI clocks */ - udelay(15); - - if (ah->ah_version == AR5K_AR5210) { - val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA - | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; - mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_DMA - | AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_PHY; - } else { - val &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; - mask &= AR5K_RESET_CTL_PCU | AR5K_RESET_CTL_BASEBAND; - } - - ret = ath5k_hw_register_timeout(ah, AR5K_RESET_CTL, mask, val, false); - - /* - * Reset configuration register (for hw byte-swap). Note that this - * is only set for big endian. We do the necessary magic in - * AR5K_INIT_CFG. - */ - if ((val & AR5K_RESET_CTL_PCU) == 0) - ath5k_hw_reg_write(ah, AR5K_INIT_CFG, AR5K_CFG); - - return ret; -} - -/* - * Sleep control - */ -int ath5k_hw_set_power(struct ath5k_hw *ah, enum ath5k_power_mode mode, - bool set_chip, u16 sleep_duration) -{ - unsigned int i; - u32 staid, data; - - ATH5K_TRACE(ah->ah_sc); - staid = ath5k_hw_reg_read(ah, AR5K_STA_ID1); - - switch (mode) { - case AR5K_PM_AUTO: - staid &= ~AR5K_STA_ID1_DEFAULT_ANTENNA; - /* fallthrough */ - case AR5K_PM_NETWORK_SLEEP: - if (set_chip) - ath5k_hw_reg_write(ah, - AR5K_SLEEP_CTL_SLE_ALLOW | - sleep_duration, - AR5K_SLEEP_CTL); - - staid |= AR5K_STA_ID1_PWR_SV; - break; - - case AR5K_PM_FULL_SLEEP: - if (set_chip) - ath5k_hw_reg_write(ah, AR5K_SLEEP_CTL_SLE_SLP, - AR5K_SLEEP_CTL); - - staid |= AR5K_STA_ID1_PWR_SV; - break; - - case AR5K_PM_AWAKE: - - staid &= ~AR5K_STA_ID1_PWR_SV; - - if (!set_chip) - goto commit; - - data = ath5k_hw_reg_read(ah, AR5K_SLEEP_CTL); - - /* If card is down we 'll get 0xffff... so we - * need to clean this up before we write the register - */ - if (data & 0xffc00000) - data = 0; - else - /* Preserve sleep duration etc */ - data = data & ~AR5K_SLEEP_CTL_SLE; - - ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); - udelay(15); - - for (i = 200; i > 0; i--) { - /* Check if the chip did wake up */ - if ((ath5k_hw_reg_read(ah, AR5K_PCICFG) & - AR5K_PCICFG_SPWR_DN) == 0) - break; - - /* Wait a bit and retry */ - udelay(50); - ath5k_hw_reg_write(ah, data | AR5K_SLEEP_CTL_SLE_WAKE, - AR5K_SLEEP_CTL); - } - - /* Fail if the chip didn't wake up */ - if (i == 0) - return -EIO; - - break; - - default: - return -EINVAL; - } - -commit: - ath5k_hw_reg_write(ah, staid, AR5K_STA_ID1); - - return 0; -} - -/* - * Put device on hold - * - * Put MAC and Baseband on warm reset and - * keep that state (don't clean sleep control - * register). After this MAC and Baseband are - * disabled and a full reset is needed to come - * back. This way we save as much power as possible - * without puting the card on full sleep. - */ -int ath5k_hw_on_hold(struct ath5k_hw *ah) -{ - struct pci_dev *pdev = ah->ah_sc->pdev; - u32 bus_flags; - int ret; - - /* Make sure device is awake */ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); - return ret; - } - - /* - * Put chipset on warm reset... - * - * Note: puting PCI core on warm reset on PCI-E cards - * results card to hang and always return 0xffff... so - * we ingore that flag for PCI-E cards. On PCI cards - * this flag gets cleared after 64 PCI clocks. - */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; - - if (ah->ah_version == AR5K_AR5210) { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | - AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - mdelay(2); - } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); - } - - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to put device on warm reset\n"); - return -EIO; - } - - /* ...wakeup again!*/ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to put device on hold\n"); - return ret; - } - - return ret; -} - -/* - * Bring up MAC + PHY Chips and program PLL - * TODO: Half/Quarter rate support - */ -int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) -{ - struct pci_dev *pdev = ah->ah_sc->pdev; - u32 turbo, mode, clock, bus_flags; - int ret; - - turbo = 0; - mode = 0; - clock = 0; - - ATH5K_TRACE(ah->ah_sc); - - /* Wakeup the device */ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to wakeup the MAC Chip\n"); - return ret; - } - - /* - * Put chipset on warm reset... - * - * Note: puting PCI core on warm reset on PCI-E cards - * results card to hang and always return 0xffff... so - * we ingore that flag for PCI-E cards. On PCI cards - * this flag gets cleared after 64 PCI clocks. - */ - bus_flags = (pdev->is_pcie) ? 0 : AR5K_RESET_CTL_PCI; - - if (ah->ah_version == AR5K_AR5210) { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_MAC | AR5K_RESET_CTL_DMA | - AR5K_RESET_CTL_PHY | AR5K_RESET_CTL_PCI); - mdelay(2); - } else { - ret = ath5k_hw_nic_reset(ah, AR5K_RESET_CTL_PCU | - AR5K_RESET_CTL_BASEBAND | bus_flags); - } - - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to reset the MAC Chip\n"); - return -EIO; - } - - /* ...wakeup again!...*/ - ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); - if (ret) { - ATH5K_ERR(ah->ah_sc, "failed to resume the MAC Chip\n"); - return ret; - } - - /* ...clear reset control register and pull device out of - * warm reset */ - if (ath5k_hw_nic_reset(ah, 0)) { - ATH5K_ERR(ah->ah_sc, "failed to warm reset the MAC Chip\n"); - return -EIO; - } - - /* On initialization skip PLL programming since we don't have - * a channel / mode set yet */ - if (initial) - return 0; - - if (ah->ah_version != AR5K_AR5210) { - /* - * Get channel mode flags - */ - - if (ah->ah_radio >= AR5K_RF5112) { - mode = AR5K_PHY_MODE_RAD_RF5112; - clock = AR5K_PHY_PLL_RF5112; - } else { - mode = AR5K_PHY_MODE_RAD_RF5111; /*Zero*/ - clock = AR5K_PHY_PLL_RF5111; /*Zero*/ - } - - if (flags & CHANNEL_2GHZ) { - mode |= AR5K_PHY_MODE_FREQ_2GHZ; - clock |= AR5K_PHY_PLL_44MHZ; - - if (flags & CHANNEL_CCK) { - mode |= AR5K_PHY_MODE_MOD_CCK; - } else if (flags & CHANNEL_OFDM) { - /* XXX Dynamic OFDM/CCK is not supported by the - * AR5211 so we set MOD_OFDM for plain g (no - * CCK headers) operation. We need to test - * this, 5211 might support ofdm-only g after - * all, there are also initial register values - * in the code for g mode (see initvals.c). */ - if (ah->ah_version == AR5K_AR5211) - mode |= AR5K_PHY_MODE_MOD_OFDM; - else - mode |= AR5K_PHY_MODE_MOD_DYN; - } else { - ATH5K_ERR(ah->ah_sc, - "invalid radio modulation mode\n"); - return -EINVAL; - } - } else if (flags & CHANNEL_5GHZ) { - mode |= AR5K_PHY_MODE_FREQ_5GHZ; - - if (ah->ah_radio == AR5K_RF5413) - clock = AR5K_PHY_PLL_40MHZ_5413; - else - clock |= AR5K_PHY_PLL_40MHZ; - - if (flags & CHANNEL_OFDM) - mode |= AR5K_PHY_MODE_MOD_OFDM; - else { - ATH5K_ERR(ah->ah_sc, - "invalid radio modulation mode\n"); - return -EINVAL; - } - } else { - ATH5K_ERR(ah->ah_sc, "invalid radio frequency mode\n"); - return -EINVAL; - } - - if (flags & CHANNEL_TURBO) - turbo = AR5K_PHY_TURBO_MODE | AR5K_PHY_TURBO_SHORT; - } else { /* Reset the device */ - - /* ...enable Atheros turbo mode if requested */ - if (flags & CHANNEL_TURBO) - ath5k_hw_reg_write(ah, AR5K_PHY_TURBO_MODE, - AR5K_PHY_TURBO); - } - - if (ah->ah_version != AR5K_AR5210) { - - /* ...update PLL if needed */ - if (ath5k_hw_reg_read(ah, AR5K_PHY_PLL) != clock) { - ath5k_hw_reg_write(ah, clock, AR5K_PHY_PLL); - udelay(300); - } - - /* ...set the PHY operating mode */ - ath5k_hw_reg_write(ah, mode, AR5K_PHY_MODE); - ath5k_hw_reg_write(ah, turbo, AR5K_PHY_TURBO); - } - - return 0; -} - -/* - * If there is an external 32KHz crystal available, use it - * as ref. clock instead of 32/40MHz clock and baseband clocks - * to save power during sleep or restore normal 32/40MHz - * operation. - * - * XXX: When operating on 32KHz certain PHY registers (27 - 31, - * 123 - 127) require delay on access. - */ -static void ath5k_hw_set_sleep_clock(struct ath5k_hw *ah, bool enable) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - u32 scal, spending, usec32; - - /* Only set 32KHz settings if we have an external - * 32KHz crystal present */ - if ((AR5K_EEPROM_HAS32KHZCRYSTAL(ee->ee_misc1) || - AR5K_EEPROM_HAS32KHZCRYSTAL_OLD(ee->ee_misc1)) && - enable) { - - /* 1 usec/cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, 1); - /* Set up tsf increment on each cycle */ - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 61); - - /* Set baseband sleep control registers - * and sleep control rate */ - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - ath5k_hw_reg_write(ah, 0x26, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0d, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x07, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x3f, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x02); - } else { - ath5k_hw_reg_write(ah, 0x0a, AR5K_PHY_SLMT); - ath5k_hw_reg_write(ah, 0x0c, AR5K_PHY_SCAL); - ath5k_hw_reg_write(ah, 0x03, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, 0x20, AR5K_PHY_SDELAY); - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0x03); - } - - /* Enable sleep clock operation */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - } else { - - /* Disable sleep clock operation and - * restore default parameters */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_EN); - - AR5K_REG_WRITE_BITS(ah, AR5K_PCICFG, - AR5K_PCICFG_SLEEP_CLOCK_RATE, 0); - - ath5k_hw_reg_write(ah, 0x1f, AR5K_PHY_SCR); - ath5k_hw_reg_write(ah, AR5K_PHY_SLMT_32MHZ, AR5K_PHY_SLMT); - - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - - ath5k_hw_reg_write(ah, AR5K_PHY_SCLOCK_32MHZ, AR5K_PHY_SCLOCK); - ath5k_hw_reg_write(ah, AR5K_PHY_SDELAY_32MHZ, AR5K_PHY_SDELAY); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) - spending = 0x14; - else - spending = 0x18; - ath5k_hw_reg_write(ah, spending, AR5K_PHY_SPENDING); - - if ((ah->ah_radio == AR5K_RF5112) || - (ah->ah_radio == AR5K_RF5413)) - usec32 = 39; - else - usec32 = 31; - AR5K_REG_WRITE_BITS(ah, AR5K_USEC_5211, AR5K_USEC_32, usec32); - - AR5K_REG_WRITE_BITS(ah, AR5K_TSF_PARM, AR5K_TSF_PARM_INC, 1); - } - return; -} - -/* TODO: Half/Quarter rate */ -static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel) -{ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - - /* Setup ADC control */ - ath5k_hw_reg_write(ah, - (AR5K_REG_SM(2, - AR5K_PHY_ADC_CTL_INBUFGAIN_OFF) | - AR5K_REG_SM(2, - AR5K_PHY_ADC_CTL_INBUFGAIN_ON) | - AR5K_PHY_ADC_CTL_PWD_DAC_OFF | - AR5K_PHY_ADC_CTL_PWD_ADC_OFF), - AR5K_PHY_ADC_CTL); - - - - /* Disable barker RSSI threshold */ - AR5K_REG_DISABLE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, - AR5K_PHY_DAG_CCK_CTL_EN_RSSI_THR); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DAG_CCK_CTL, - AR5K_PHY_DAG_CCK_CTL_RSSI_THR, 2); - - /* Set the mute mask */ - ath5k_hw_reg_write(ah, 0x0000000f, AR5K_SEQ_MASK); - } - - /* Clear PHY_BLUETOOTH to allow RX_CLEAR line debug */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212B) - ath5k_hw_reg_write(ah, 0, AR5K_PHY_BLUETOOTH); - - /* Enable DCU double buffering */ - if (ah->ah_phy_revision > AR5K_SREV_PHY_5212B) - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_DCU_DBL_BUF_DIS); - - /* Set DAC/ADC delays */ - if (ah->ah_version == AR5K_AR5212) { - u32 scal; - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - if (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4)) - scal = AR5K_PHY_SCAL_32MHZ_2417; - else if (ee->ee_is_hb63) - scal = AR5K_PHY_SCAL_32MHZ_HB63; - else - scal = AR5K_PHY_SCAL_32MHZ; - ath5k_hw_reg_write(ah, scal, AR5K_PHY_SCAL); - } - - /* Set fast ADC */ - if ((ah->ah_radio == AR5K_RF5413) || - (ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4))) { - u32 fast_adc = true; - - if (channel->center_freq == 2462 || - channel->center_freq == 2467) - fast_adc = 0; - - /* Only update if needed */ - if (ath5k_hw_reg_read(ah, AR5K_PHY_FAST_ADC) != fast_adc) - ath5k_hw_reg_write(ah, fast_adc, - AR5K_PHY_FAST_ADC); - } - - /* Fix for first revision of the RF5112 RF chipset */ - if (ah->ah_radio == AR5K_RF5112 && - ah->ah_radio_5ghz_revision < - AR5K_SREV_RAD_5112A) { - u32 data; - ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, - AR5K_PHY_CCKTXCTL); - if (channel->hw_value & CHANNEL_5GHZ) - data = 0xffb81020; - else - data = 0xffb80d20; - ath5k_hw_reg_write(ah, data, AR5K_PHY_FRAME_CTL); - } - - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - u32 usec_reg; - /* 5311 has different tx/rx latency masks - * from 5211, since we deal 5311 the same - * as 5211 when setting initvals, shift - * values here to their proper locations */ - usec_reg = ath5k_hw_reg_read(ah, AR5K_USEC_5211); - ath5k_hw_reg_write(ah, usec_reg & (AR5K_USEC_1 | - AR5K_USEC_32 | - AR5K_USEC_TX_LATENCY_5211 | - AR5K_REG_SM(29, - AR5K_USEC_RX_LATENCY_5210)), - AR5K_USEC_5211); - /* Clear QCU/DCU clock gating register */ - ath5k_hw_reg_write(ah, 0, AR5K_QCUDCU_CLKGT); - /* Set DAC/ADC delays */ - ath5k_hw_reg_write(ah, 0x08, AR5K_PHY_SCAL); - /* Enable PCU FIFO corruption ECO */ - AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW_5211, - AR5K_DIAG_SW_ECO_ENABLE); - } -} - -static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah, - struct ieee80211_channel *channel, u8 *ant, u8 ee_mode) -{ - struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom; - s16 cck_ofdm_pwr_delta; - - /* Adjust power delta for channel 14 */ - if (channel->center_freq == 2484) - cck_ofdm_pwr_delta = - ((ee->ee_cck_ofdm_power_delta - - ee->ee_scaled_cck_delta) * 2) / 10; - else - cck_ofdm_pwr_delta = - (ee->ee_cck_ofdm_power_delta * 2) / 10; - - /* Set CCK to OFDM power delta on tx power - * adjustment register */ - if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { - if (channel->hw_value == CHANNEL_G) - ath5k_hw_reg_write(ah, - AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), - AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | - AR5K_REG_SM((cck_ofdm_pwr_delta * -1), - AR5K_PHY_TX_PWR_ADJ_CCK_PCDAC_INDEX), - AR5K_PHY_TX_PWR_ADJ); - else - ath5k_hw_reg_write(ah, 0, AR5K_PHY_TX_PWR_ADJ); - } else { - /* For older revs we scale power on sw during tx power - * setup */ - ah->ah_txpower.txp_cck_ofdm_pwr_delta = cck_ofdm_pwr_delta; - ah->ah_txpower.txp_cck_ofdm_gainf_delta = - ee->ee_cck_ofdm_gain_delta; - } - - /* Set antenna idle switch table */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_ANT_CTL, - AR5K_PHY_ANT_CTL_SWTABLE_IDLE, - (ah->ah_ant_ctl[ee_mode][0] | - AR5K_PHY_ANT_CTL_TXRX_EN)); - - /* Set antenna switch tables */ - ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[0]], - AR5K_PHY_ANT_SWITCH_TABLE_0); - ath5k_hw_reg_write(ah, ah->ah_ant_ctl[ee_mode][ant[1]], - AR5K_PHY_ANT_SWITCH_TABLE_1); - - /* Noise floor threshold */ - ath5k_hw_reg_write(ah, - AR5K_PHY_NF_SVAL(ee->ee_noise_floor_thr[ee_mode]), - AR5K_PHY_NFTHRES); - - if ((channel->hw_value & CHANNEL_TURBO) && - (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_0)) { - /* Switch settling time (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - ee->ee_switch_settling_turbo[ee_mode]); - - /* Tx/Rx attenuation (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, - AR5K_PHY_GAIN_TXRX_ATTEN, - ee->ee_atn_tx_rx_turbo[ee_mode]); - - /* ADC/PGA desired size (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_ADC, - ee->ee_adc_desired_size_turbo[ee_mode]); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_PGA, - ee->ee_pga_desired_size_turbo[ee_mode]); - - /* Tx/Rx margin (Turbo) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, - AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, - ee->ee_margin_tx_rx_turbo[ee_mode]); - - } else { - /* Switch settling time */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_SETTLING, - AR5K_PHY_SETTLING_SWITCH, - ee->ee_switch_settling[ee_mode]); - - /* Tx/Rx attenuation */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN, - AR5K_PHY_GAIN_TXRX_ATTEN, - ee->ee_atn_tx_rx[ee_mode]); - - /* ADC/PGA desired size */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_ADC, - ee->ee_adc_desired_size[ee_mode]); - - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_DESIRED_SIZE, - AR5K_PHY_DESIRED_SIZE_PGA, - ee->ee_pga_desired_size[ee_mode]); - - /* Tx/Rx margin */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_4_1) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_GAIN_2GHZ, - AR5K_PHY_GAIN_2GHZ_MARGIN_TXRX, - ee->ee_margin_tx_rx[ee_mode]); - } - - /* XPA delays */ - ath5k_hw_reg_write(ah, - (ee->ee_tx_end2xpa_disable[ee_mode] << 24) | - (ee->ee_tx_end2xpa_disable[ee_mode] << 16) | - (ee->ee_tx_frm2xpa_enable[ee_mode] << 8) | - (ee->ee_tx_frm2xpa_enable[ee_mode]), AR5K_PHY_RF_CTL4); - - /* XLNA delay */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_RF_CTL3, - AR5K_PHY_RF_CTL3_TXE2XLNA_ON, - ee->ee_tx_end2xlna_enable[ee_mode]); - - /* Thresh64 (ANI) */ - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_NF, - AR5K_PHY_NF_THRESH62, - ee->ee_thr_62[ee_mode]); - - - /* False detect backoff for channels - * that have spur noise. Write the new - * cyclic power RSSI threshold. */ - if (ath5k_hw_chan_has_spur_noise(ah, channel)) - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, - AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, - AR5K_INIT_CYCRSSI_THR1 + - ee->ee_false_detect[ee_mode]); - else - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_OFDM_SELFCORR, - AR5K_PHY_OFDM_SELFCORR_CYPWR_THR1, - AR5K_INIT_CYCRSSI_THR1); - - /* I/Q correction - * TODO: Per channel i/q infos ? */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CORR_ENABLE | - (ee->ee_i_cal[ee_mode] << AR5K_PHY_IQ_CORR_Q_I_COFF_S) | - ee->ee_q_cal[ee_mode]); - - /* Heavy clipping -disable for now */ - if (ah->ah_ee_version >= AR5K_EEPROM_VERSION_5_1) - ath5k_hw_reg_write(ah, 0, AR5K_PHY_HEAVY_CLIP_ENABLE); - - return; -} - -/* - * Main reset function - */ -int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, - struct ieee80211_channel *channel, bool change_channel) -{ - u32 s_seq[10], s_ant, s_led[3], staid1_flags, tsf_up, tsf_lo; - u32 phy_tst1; - u8 mode, freq, ee_mode, ant[2]; - int i, ret; - - ATH5K_TRACE(ah->ah_sc); - - s_ant = 0; - ee_mode = 0; - staid1_flags = 0; - tsf_up = 0; - tsf_lo = 0; - freq = 0; - mode = 0; - - /* - * Save some registers before a reset - */ - /*DCU/Antenna selection not available on 5210*/ - if (ah->ah_version != AR5K_AR5210) { - - switch (channel->hw_value & CHANNEL_MODES) { - case CHANNEL_A: - mode = AR5K_MODE_11A; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_G: - mode = AR5K_MODE_11G; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_B: - mode = AR5K_MODE_11B; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11B; - break; - case CHANNEL_T: - mode = AR5K_MODE_11A_TURBO; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - case CHANNEL_TG: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "TurboG mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_11G_TURBO; - freq = AR5K_INI_RFGAIN_2GHZ; - ee_mode = AR5K_EEPROM_MODE_11G; - break; - case CHANNEL_XR: - if (ah->ah_version == AR5K_AR5211) { - ATH5K_ERR(ah->ah_sc, - "XR mode not available on 5211"); - return -EINVAL; - } - mode = AR5K_MODE_XR; - freq = AR5K_INI_RFGAIN_5GHZ; - ee_mode = AR5K_EEPROM_MODE_11A; - break; - default: - ATH5K_ERR(ah->ah_sc, - "invalid channel: %d\n", channel->center_freq); - return -EINVAL; - } - - if (change_channel) { - /* - * Save frame sequence count - * For revs. after Oahu, only save - * seq num for DCU 0 (Global seq num) - */ - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - - for (i = 0; i < 10; i++) - s_seq[i] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(i)); - - } else { - s_seq[0] = ath5k_hw_reg_read(ah, - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - /* TSF accelerates on AR5211 durring reset - * As a workaround save it here and restore - * it later so that it's back in time after - * reset. This way it'll get re-synced on the - * next beacon without breaking ad-hoc. - * - * On AR5212 TSF is almost preserved across a - * reset so it stays back in time anyway and - * we don't have to save/restore it. - * - * XXX: Since this breaks power saving we have - * to disable power saving until we receive the - * next beacon, so we can resync beacon timers */ - if (ah->ah_version == AR5K_AR5211) { - tsf_up = ath5k_hw_reg_read(ah, AR5K_TSF_U32); - tsf_lo = ath5k_hw_reg_read(ah, AR5K_TSF_L32); - } - } - - /* Save default antenna */ - s_ant = ath5k_hw_reg_read(ah, AR5K_DEFAULT_ANTENNA); - - if (ah->ah_version == AR5K_AR5212) { - /* Restore normal 32/40MHz clock operation - * to avoid register access delay on certain - * PHY registers */ - ath5k_hw_set_sleep_clock(ah, false); - - /* Since we are going to write rf buffer - * check if we have any pending gain_F - * optimization settings */ - if (change_channel && ah->ah_rf_banks != NULL) - ath5k_hw_gainf_calibrate(ah); - } - } - - /*GPIOs*/ - s_led[0] = ath5k_hw_reg_read(ah, AR5K_PCICFG) & - AR5K_PCICFG_LEDSTATE; - s_led[1] = ath5k_hw_reg_read(ah, AR5K_GPIOCR); - s_led[2] = ath5k_hw_reg_read(ah, AR5K_GPIODO); - - /* AR5K_STA_ID1 flags, only preserve antenna - * settings and ack/cts rate mode */ - staid1_flags = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & - (AR5K_STA_ID1_DEFAULT_ANTENNA | - AR5K_STA_ID1_DESC_ANTENNA | - AR5K_STA_ID1_RTS_DEF_ANTENNA | - AR5K_STA_ID1_ACKCTS_6MB | - AR5K_STA_ID1_BASE_RATE_11B | - AR5K_STA_ID1_SELFGEN_DEF_ANT); - - /* Wakeup the device */ - ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); - if (ret) - return ret; - - /* - * Initialize operating mode - */ - ah->ah_op_mode = op_mode; - - /* PHY access enable */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5211) - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); - else - ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ | 0x40, - AR5K_PHY(0)); - - /* Write initial settings */ - ret = ath5k_hw_write_initvals(ah, mode, change_channel); - if (ret) - return ret; - - /* - * 5211/5212 Specific - */ - if (ah->ah_version != AR5K_AR5210) { - - /* - * Write initial RF gain settings - * This should work for both 5111/5112 - */ - ret = ath5k_hw_rfgain_init(ah, freq); - if (ret) - return ret; - - mdelay(1); - - /* - * Tweak initval settings for revised - * chipsets and add some more config - * bits - */ - ath5k_hw_tweak_initval_settings(ah, channel); - - /* - * Set TX power - */ - ret = ath5k_hw_txpower(ah, channel, ee_mode, - ah->ah_txpower.txp_max_pwr / 2); - if (ret) - return ret; - - /* Write rate duration table only on AR5212 and if - * virtual interface has already been brought up - * XXX: rethink this after new mode changes to - * mac80211 are integrated */ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_sc->vif != NULL) - ath5k_hw_write_rate_duration(ah, mode); - - /* - * Write RF buffer - */ - ret = ath5k_hw_rfregs_init(ah, channel, mode); - if (ret) - return ret; - - - /* Write OFDM timings on 5212*/ - if (ah->ah_version == AR5K_AR5212 && - channel->hw_value & CHANNEL_OFDM) { - struct ath5k_eeprom_info *ee = - &ah->ah_capabilities.cap_eeprom; - - ret = ath5k_hw_write_ofdm_timings(ah, channel); - if (ret) - return ret; - - /* Note: According to docs we can have a newer - * EEPROM on old hardware, so we need to verify - * that our hardware is new enough to have spur - * mitigation registers (delta phase etc) */ - if (ah->ah_mac_srev >= AR5K_SREV_AR5424 || - (ah->ah_mac_srev >= AR5K_SREV_AR5424 && - ee->ee_version >= AR5K_EEPROM_VERSION_5_3)) - ath5k_hw_set_spur_mitigation_filter(ah, - channel); - } - - /*Enable/disable 802.11b mode on 5111 - (enable 2111 frequency converter + CCK)*/ - if (ah->ah_radio == AR5K_RF5111) { - if (mode == AR5K_MODE_11B) - AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - else - AR5K_REG_DISABLE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_B_MODE); - } - - /* - * In case a fixed antenna was set as default - * use the same switch table twice. - */ - if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_A) - ant[0] = ant[1] = AR5K_ANT_SWTABLE_A; - else if (ah->ah_ant_mode == AR5K_ANTMODE_FIXED_B) - ant[0] = ant[1] = AR5K_ANT_SWTABLE_B; - else { - ant[0] = AR5K_ANT_SWTABLE_A; - ant[1] = AR5K_ANT_SWTABLE_B; - } - - /* Commit values from EEPROM */ - ath5k_hw_commit_eeprom_settings(ah, channel, ant, ee_mode); - - } else { - /* - * For 5210 we do all initialization using - * initvals, so we don't have to modify - * any settings (5210 also only supports - * a/aturbo modes) - */ - mdelay(1); - /* Disable phy and wait */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_DISABLE, AR5K_PHY_ACT); - mdelay(1); - } - - /* - * Restore saved values - */ - - /*DCU/Antenna selection not available on 5210*/ - if (ah->ah_version != AR5K_AR5210) { - - if (change_channel) { - if (ah->ah_mac_srev < AR5K_SREV_AR5211) { - for (i = 0; i < 10; i++) - ath5k_hw_reg_write(ah, s_seq[i], - AR5K_QUEUE_DCU_SEQNUM(i)); - } else { - ath5k_hw_reg_write(ah, s_seq[0], - AR5K_QUEUE_DCU_SEQNUM(0)); - } - - - if (ah->ah_version == AR5K_AR5211) { - ath5k_hw_reg_write(ah, tsf_up, AR5K_TSF_U32); - ath5k_hw_reg_write(ah, tsf_lo, AR5K_TSF_L32); - } - } - - ath5k_hw_reg_write(ah, s_ant, AR5K_DEFAULT_ANTENNA); - } - - /* Ledstate */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PCICFG, s_led[0]); - - /* Gpio settings */ - ath5k_hw_reg_write(ah, s_led[1], AR5K_GPIOCR); - ath5k_hw_reg_write(ah, s_led[2], AR5K_GPIODO); - - /* Restore sta_id flags and preserve our mac address*/ - ath5k_hw_reg_write(ah, AR5K_LOW_ID(ah->ah_sta_id), - AR5K_STA_ID0); - ath5k_hw_reg_write(ah, staid1_flags | AR5K_HIGH_ID(ah->ah_sta_id), - AR5K_STA_ID1); - - - /* - * Configure PCU - */ - - /* Restore bssid and bssid mask */ - /* XXX: add ah->aid once mac80211 gives this to us */ - ath5k_hw_set_associd(ah, ah->ah_bssid, 0); - - /* Set PCU config */ - ath5k_hw_set_opmode(ah); - - /* Clear any pending interrupts - * PISR/SISR Not available on 5210 */ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_reg_write(ah, 0xffffffff, AR5K_PISR); - - /* Set RSSI/BRSSI thresholds - * - * Note: If we decide to set this value - * dynamicaly, have in mind that when AR5K_RSSI_THR - * register is read it might return 0x40 if we haven't - * wrote anything to it plus BMISS RSSI threshold is zeroed. - * So doing a save/restore procedure here isn't the right - * choice. Instead store it on ath5k_hw */ - ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | - AR5K_TUNE_BMISS_THRES << - AR5K_RSSI_THR_BMISS_S), - AR5K_RSSI_THR); - - /* MIC QoS support */ - if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { - ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); - ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); - } - - /* QoS NOACK Policy */ - if (ah->ah_version == AR5K_AR5212) { - ath5k_hw_reg_write(ah, - AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | - AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | - AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), - AR5K_QOS_NOACK); - } - - - /* - * Configure PHY - */ - - /* Set channel on PHY */ - ret = ath5k_hw_channel(ah, channel); - if (ret) - return ret; - - /* - * Enable the PHY and wait until completion - * This includes BaseBand and Synthesizer - * activation. - */ - ath5k_hw_reg_write(ah, AR5K_PHY_ACT_ENABLE, AR5K_PHY_ACT); - - /* - * On 5211+ read activation -> rx delay - * and use it. - * - * TODO: Half/quarter rate support - */ - if (ah->ah_version != AR5K_AR5210) { - u32 delay; - delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & - AR5K_PHY_RX_DELAY_M; - delay = (channel->hw_value & CHANNEL_CCK) ? - ((delay << 2) / 22) : (delay / 10); - - udelay(100 + (2 * delay)); - } else { - mdelay(1); - } - - /* - * Perform ADC test to see if baseband is ready - * Set tx hold and check adc test register - */ - phy_tst1 = ath5k_hw_reg_read(ah, AR5K_PHY_TST1); - ath5k_hw_reg_write(ah, AR5K_PHY_TST1_TXHOLD, AR5K_PHY_TST1); - for (i = 0; i <= 20; i++) { - if (!(ath5k_hw_reg_read(ah, AR5K_PHY_ADC_TEST) & 0x10)) - break; - udelay(200); - } - ath5k_hw_reg_write(ah, phy_tst1, AR5K_PHY_TST1); - - /* - * Start automatic gain control calibration - * - * During AGC calibration RX path is re-routed to - * a power detector so we don't receive anything. - * - * This method is used to calibrate some static offsets - * used together with on-the fly I/Q calibration (the - * one performed via ath5k_hw_phy_calibrate), that doesn't - * interrupt rx path. - * - * While rx path is re-routed to the power detector we also - * start a noise floor calibration, to measure the - * card's noise floor (the noise we measure when we are not - * transmiting or receiving anything). - * - * If we are in a noisy environment AGC calibration may time - * out and/or noise floor calibration might timeout. - */ - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL); - - /* At the same time start I/Q calibration for QAM constellation - * -no need for CCK- */ - ah->ah_calibration = false; - if (!(mode == AR5K_MODE_11B)) { - ah->ah_calibration = true; - AR5K_REG_WRITE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_CAL_NUM_LOG_MAX, 15); - AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_IQ, - AR5K_PHY_IQ_RUN); - } - - /* Wait for gain calibration to finish (we check for I/Q calibration - * during ath5k_phy_calibrate) */ - if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL, - AR5K_PHY_AGCCTL_CAL, 0, false)) { - ATH5K_ERR(ah->ah_sc, "gain calibration timeout (%uMHz)\n", - channel->center_freq); - } - - /* - * If we run NF calibration before AGC, it always times out. - * Binary HAL starts NF and AGC calibration at the same time - * and only waits for AGC to finish. Also if AGC or NF cal. - * times out, reset doesn't fail on binary HAL. I believe - * that's wrong because since rx path is routed to a detector, - * if cal. doesn't finish we won't have RX. Sam's HAL for AR5210/5211 - * enables noise floor calibration after offset calibration and if noise - * floor calibration fails, reset fails. I believe that's - * a better approach, we just need to find a polling interval - * that suits best, even if reset continues we need to make - * sure that rx path is ready. - */ - ath5k_hw_noise_floor_calibration(ah, channel->center_freq); - - /* Restore antenna mode */ - ath5k_hw_set_antenna_mode(ah, ah->ah_ant_mode); - - /* - * Configure QCUs/DCUs - */ - - /* TODO: HW Compression support for data queues */ - /* TODO: Burst prefetch for data queues */ - - /* - * Reset queues and start beacon timers at the end of the reset routine - * This also sets QCU mask on each DCU for 1:1 qcu to dcu mapping - * Note: If we want we can assign multiple qcus on one dcu. - */ - for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++) { - ret = ath5k_hw_reset_tx_queue(ah, i); - if (ret) { - ATH5K_ERR(ah->ah_sc, - "failed to reset TX queue #%d\n", i); - return ret; - } - } - - - /* - * Configure DMA/Interrupts - */ - - /* - * Set Rx/Tx DMA Configuration - * - * Set standard DMA size (128). Note that - * a DMA size of 512 causes rx overruns and tx errors - * on pci-e cards (tested on 5424 but since rx overruns - * also occur on 5416/5418 with madwifi we set 128 - * for all PCI-E cards to be safe). - * - * XXX: need to check 5210 for this - * TODO: Check out tx triger level, it's always 64 on dumps but I - * guess we can tweak it and see how it goes ;-) - */ - if (ah->ah_version != AR5K_AR5210) { - AR5K_REG_WRITE_BITS(ah, AR5K_TXCFG, - AR5K_TXCFG_SDMAMR, AR5K_DMASIZE_128B); - AR5K_REG_WRITE_BITS(ah, AR5K_RXCFG, - AR5K_RXCFG_SDMAMW, AR5K_DMASIZE_128B); - } - - /* Pre-enable interrupts on 5211/5212*/ - if (ah->ah_version != AR5K_AR5210) - ath5k_hw_set_imr(ah, ah->ah_imr); - - /* Enable 32KHz clock function for AR5212+ chips - * Set clocks to 32KHz operation and use an - * external 32KHz crystal when sleeping if one - * exists */ - if (ah->ah_version == AR5K_AR5212 && - ah->ah_op_mode != NL80211_IFTYPE_AP) - ath5k_hw_set_sleep_clock(ah, true); - - /* - * Disable beacons and reset the register - */ - AR5K_REG_DISABLE_BITS(ah, AR5K_BEACON, AR5K_BEACON_ENABLE | - AR5K_BEACON_RESET_TSF); - - return 0; -} - -#undef _ATH5K_RESET diff --git a/drivers/net/wireless/ath/ath5k/rfbuffer.h b/drivers/net/wireless/ath/ath5k/rfbuffer.h deleted file mode 100644 index e50baff66175..000000000000 --- a/drivers/net/wireless/ath/ath5k/rfbuffer.h +++ /dev/null @@ -1,1181 +0,0 @@ -/* - * RF Buffer handling functions - * - * Copyright (c) 2009 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - - -/* - * There are some special registers on the RF chip - * that control various operation settings related mostly to - * the analog parts (channel, gain adjustment etc). - * - * We don't write on those registers directly but - * we send a data packet on the chip, using a special register, - * that holds all the settings we need. After we 've sent the - * data packet, we write on another special register to notify hw - * to apply the settings. This is done so that control registers - * can be dynamicaly programmed during operation and the settings - * are applied faster on the hw. - * - * We call each data packet an "RF Bank" and all the data we write - * (all RF Banks) "RF Buffer". This file holds initial RF Buffer - * data for the different RF chips, and various info to match RF - * Buffer offsets with specific RF registers so that we can access - * them. We tweak these settings on rfregs_init function. - * - * Also check out reg.h and U.S. Patent 6677779 B1 (about buffer - * registers and control registers): - * - * http://www.google.com/patents?id=qNURAAAAEBAJ - */ - - -/* - * Struct to hold default mode specific RF - * register values (RF Banks) - */ -struct ath5k_ini_rfbuffer { - u8 rfb_bank; /* RF Bank number */ - u16 rfb_ctrl_register; /* RF Buffer control register */ - u32 rfb_mode_data[5]; /* RF Buffer data for each mode */ -}; - -/* - * Struct to hold RF Buffer field - * infos used to access certain RF - * analog registers - */ -struct ath5k_rfb_field { - u8 len; /* Field length */ - u16 pos; /* Offset on the raw packet */ - u8 col; /* Column -used for shifting */ -}; - -/* - * RF analog register definition - */ -struct ath5k_rf_reg { - u8 bank; /* RF Buffer Bank number */ - u8 index; /* Register's index on rf_regs_idx */ - struct ath5k_rfb_field field; /* RF Buffer field for this register */ -}; - -/* Map RF registers to indexes - * We do this to handle common bits and make our - * life easier by using an index for each register - * instead of a full rfb_field */ -enum ath5k_rf_regs_idx { - /* BANK 6 */ - AR5K_RF_OB_2GHZ = 0, - AR5K_RF_OB_5GHZ, - AR5K_RF_DB_2GHZ, - AR5K_RF_DB_5GHZ, - AR5K_RF_FIXED_BIAS_A, - AR5K_RF_FIXED_BIAS_B, - AR5K_RF_PWD_XPD, - AR5K_RF_XPD_SEL, - AR5K_RF_XPD_GAIN, - AR5K_RF_PD_GAIN_LO, - AR5K_RF_PD_GAIN_HI, - AR5K_RF_HIGH_VC_CP, - AR5K_RF_MID_VC_CP, - AR5K_RF_LOW_VC_CP, - AR5K_RF_PUSH_UP, - AR5K_RF_PAD2GND, - AR5K_RF_XB2_LVL, - AR5K_RF_XB5_LVL, - AR5K_RF_PWD_ICLOBUF_2G, - AR5K_RF_PWD_84, - AR5K_RF_PWD_90, - AR5K_RF_PWD_130, - AR5K_RF_PWD_131, - AR5K_RF_PWD_132, - AR5K_RF_PWD_136, - AR5K_RF_PWD_137, - AR5K_RF_PWD_138, - AR5K_RF_PWD_166, - AR5K_RF_PWD_167, - AR5K_RF_DERBY_CHAN_SEL_MODE, - /* BANK 7 */ - AR5K_RF_GAIN_I, - AR5K_RF_PLO_SEL, - AR5K_RF_RFGAIN_SEL, - AR5K_RF_RFGAIN_STEP, - AR5K_RF_WAIT_S, - AR5K_RF_WAIT_I, - AR5K_RF_MAX_TIME, - AR5K_RF_MIXVGA_OVR, - AR5K_RF_MIXGAIN_OVR, - AR5K_RF_MIXGAIN_STEP, - AR5K_RF_PD_DELAY_A, - AR5K_RF_PD_DELAY_B, - AR5K_RF_PD_DELAY_XR, - AR5K_RF_PD_PERIOD_A, - AR5K_RF_PD_PERIOD_B, - AR5K_RF_PD_PERIOD_XR, -}; - - -/*******************\ -* RF5111 (Sombrero) * -\*******************/ - -/* BANK 6 len pos col */ -#define AR5K_RF5111_OB_2GHZ { 3, 119, 0 } -#define AR5K_RF5111_DB_2GHZ { 3, 122, 0 } - -#define AR5K_RF5111_OB_5GHZ { 3, 104, 0 } -#define AR5K_RF5111_DB_5GHZ { 3, 107, 0 } - -#define AR5K_RF5111_PWD_XPD { 1, 95, 0 } -#define AR5K_RF5111_XPD_GAIN { 4, 96, 0 } - -/* Access to PWD registers */ -#define AR5K_RF5111_PWD(_n) { 1, (135 - _n), 3 } - -/* BANK 7 len pos col */ -#define AR5K_RF5111_GAIN_I { 6, 29, 0 } -#define AR5K_RF5111_PLO_SEL { 1, 4, 0 } -#define AR5K_RF5111_RFGAIN_SEL { 1, 36, 0 } -#define AR5K_RF5111_RFGAIN_STEP { 6, 37, 0 } -/* Only on AR5212 BaseBand and up */ -#define AR5K_RF5111_WAIT_S { 5, 19, 0 } -#define AR5K_RF5111_WAIT_I { 5, 24, 0 } -#define AR5K_RF5111_MAX_TIME { 2, 49, 0 } - -static const struct ath5k_rf_reg rf_regs_5111[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5111_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5111_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5111_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5111_DB_5GHZ}, - {6, AR5K_RF_PWD_XPD, AR5K_RF5111_PWD_XPD}, - {6, AR5K_RF_XPD_GAIN, AR5K_RF5111_XPD_GAIN}, - {6, AR5K_RF_PWD_84, AR5K_RF5111_PWD(84)}, - {6, AR5K_RF_PWD_90, AR5K_RF5111_PWD(90)}, - {7, AR5K_RF_GAIN_I, AR5K_RF5111_GAIN_I}, - {7, AR5K_RF_PLO_SEL, AR5K_RF5111_PLO_SEL}, - {7, AR5K_RF_RFGAIN_SEL, AR5K_RF5111_RFGAIN_SEL}, - {7, AR5K_RF_RFGAIN_STEP, AR5K_RF5111_RFGAIN_STEP}, - {7, AR5K_RF_WAIT_S, AR5K_RF5111_WAIT_S}, - {7, AR5K_RF_WAIT_I, AR5K_RF5111_WAIT_I}, - {7, AR5K_RF_MAX_TIME, AR5K_RF5111_MAX_TIME} -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5111[] = { - { 0, 0x989c, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00380000, 0x00380000, 0x00380000, 0x00380000, 0x00380000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 0, 0x989c, - { 0x00000000, 0x00000000, 0x000000c0, 0x00000080, 0x00000080 } }, - { 0, 0x989c, - { 0x000400f9, 0x000400f9, 0x000400ff, 0x000400fd, 0x000400fd } }, - { 0, 0x98d4, - { 0x00000000, 0x00000000, 0x00000004, 0x00000004, 0x00000004 } }, - { 1, 0x98d4, - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d4, - { 0x00000010, 0x00000014, 0x00000010, 0x00000010, 0x00000014 } }, - { 3, 0x98d8, - { 0x00601068, 0x00601068, 0x00601068, 0x00601068, 0x00601068 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x04000000, 0x04000000, 0x04000000, 0x04000000, 0x04000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x0a000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x003800c0, 0x00380080, 0x023800c0, 0x003800c0, 0x003800c0 } }, - { 6, 0x989c, - { 0x00020006, 0x00020006, 0x00000006, 0x00020006, 0x00020006 } }, - { 6, 0x989c, - { 0x00000089, 0x00000089, 0x00000089, 0x00000089, 0x00000089 } }, - { 6, 0x989c, - { 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0, 0x000000a0 } }, - { 6, 0x989c, - { 0x00040007, 0x00040007, 0x00040007, 0x00040007, 0x00040007 } }, - { 6, 0x98d4, - { 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a } }, - { 7, 0x989c, - { 0x00000040, 0x00000048, 0x00000040, 0x00000040, 0x00000040 } }, - { 7, 0x989c, - { 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 } }, - { 7, 0x989c, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 7, 0x989c, - { 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f, 0x0000004f } }, - { 7, 0x989c, - { 0x000000f1, 0x000000f1, 0x00000061, 0x000000f1, 0x000000f1 } }, - { 7, 0x989c, - { 0x0000904f, 0x0000904f, 0x0000904c, 0x0000904f, 0x0000904f } }, - { 7, 0x989c, - { 0x0000125a, 0x0000125a, 0x0000129a, 0x0000125a, 0x0000125a } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000f, 0x0000000e, 0x0000000e } }, -}; - - - -/***********************\ -* RF5112/RF2112 (Derby) * -\***********************/ - -/* BANK 7 (Common) len pos col */ -#define AR5K_RF5112X_GAIN_I { 6, 14, 0 } -#define AR5K_RF5112X_MIXVGA_OVR { 1, 36, 0 } -#define AR5K_RF5112X_MIXGAIN_OVR { 2, 37, 0 } -#define AR5K_RF5112X_MIXGAIN_STEP { 4, 32, 0 } -#define AR5K_RF5112X_PD_DELAY_A { 4, 58, 0 } -#define AR5K_RF5112X_PD_DELAY_B { 4, 62, 0 } -#define AR5K_RF5112X_PD_DELAY_XR { 4, 66, 0 } -#define AR5K_RF5112X_PD_PERIOD_A { 4, 70, 0 } -#define AR5K_RF5112X_PD_PERIOD_B { 4, 74, 0 } -#define AR5K_RF5112X_PD_PERIOD_XR { 4, 78, 0 } - -/* RFX112 (Derby 1) */ - -/* BANK 6 len pos col */ -#define AR5K_RF5112_OB_2GHZ { 3, 269, 0 } -#define AR5K_RF5112_DB_2GHZ { 3, 272, 0 } - -#define AR5K_RF5112_OB_5GHZ { 3, 261, 0 } -#define AR5K_RF5112_DB_5GHZ { 3, 264, 0 } - -#define AR5K_RF5112_FIXED_BIAS_A { 1, 260, 0 } -#define AR5K_RF5112_FIXED_BIAS_B { 1, 259, 0 } - -#define AR5K_RF5112_XPD_SEL { 1, 284, 0 } -#define AR5K_RF5112_XPD_GAIN { 2, 252, 0 } - -/* Access to PWD registers */ -#define AR5K_RF5112_PWD(_n) { 1, (302 - _n), 3 } - -static const struct ath5k_rf_reg rf_regs_5112[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5112_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5112_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5112_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5112_DB_5GHZ}, - {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112_FIXED_BIAS_A}, - {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112_FIXED_BIAS_B}, - {6, AR5K_RF_XPD_SEL, AR5K_RF5112_XPD_SEL}, - {6, AR5K_RF_XPD_GAIN, AR5K_RF5112_XPD_GAIN}, - {6, AR5K_RF_PWD_130, AR5K_RF5112_PWD(130)}, - {6, AR5K_RF_PWD_131, AR5K_RF5112_PWD(131)}, - {6, AR5K_RF_PWD_132, AR5K_RF5112_PWD(132)}, - {6, AR5K_RF_PWD_136, AR5K_RF5112_PWD(136)}, - {6, AR5K_RF_PWD_137, AR5K_RF5112_PWD(137)}, - {6, AR5K_RF_PWD_138, AR5K_RF5112_PWD(138)}, - {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I}, - {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR}, - {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR}, - {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP}, - {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A}, - {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B}, - {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR}, - {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A}, - {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B}, - {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5112[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a0c0c0, 0x00a0c0c0, 0x00e0c0c0, 0x00e0c0c0, 0x00e0c0c0 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000, 0x00a00000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00660000, 0x00660000, 0x00660000, 0x00660000, 0x00660000 } }, - { 6, 0x989c, - { 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000, 0x00db0000 } }, - { 6, 0x989c, - { 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000, 0x00f10000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000, 0x008b0000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x00600000, 0x00600000, 0x00600000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00640000, 0x00640000, 0x00640000, 0x00640000, 0x00640000 } }, - { 6, 0x989c, - { 0x00200000, 0x00200000, 0x00200000, 0x00200000, 0x00200000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00250000, 0x00250000, 0x00250000, 0x00250000, 0x00250000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x00510000, 0x00510000, 0x00510000, 0x00510000, 0x00510000 } }, - { 6, 0x989c, - { 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000, 0x1c040000 } }, - { 6, 0x989c, - { 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000, 0x000a0000 } }, - { 6, 0x989c, - { 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000, 0x00a10000 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x00400000, 0x00400000, 0x00400000 } }, - { 6, 0x989c, - { 0x03090000, 0x03090000, 0x03090000, 0x03090000, 0x03090000 } }, - { 6, 0x989c, - { 0x06000000, 0x06000000, 0x06000000, 0x06000000, 0x06000000 } }, - { 6, 0x989c, - { 0x000000b0, 0x000000b0, 0x000000a8, 0x000000a8, 0x000000a8 } }, - { 6, 0x989c, - { 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e, 0x0000002e } }, - { 6, 0x989c, - { 0x006c4a41, 0x006c4a41, 0x006c4af1, 0x006c4a61, 0x006c4a61 } }, - { 6, 0x989c, - { 0x0050892a, 0x0050892a, 0x0050892b, 0x0050892b, 0x0050892b } }, - { 6, 0x989c, - { 0x00842400, 0x00842400, 0x00842400, 0x00842400, 0x00842400 } }, - { 6, 0x989c, - { 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200, 0x00c69200 } }, - { 6, 0x98d0, - { 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c, 0x0002000c } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x0000000a, 0x0000000a, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1, 0x000000c1 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x00000022, 0x00000022, 0x00000022, 0x00000022, 0x00000022 } }, - { 7, 0x989c, - { 0x00000092, 0x00000092, 0x00000092, 0x00000092, 0x00000092 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, -}; - -/* RFX112A (Derby 2) */ - -/* BANK 6 len pos col */ -#define AR5K_RF5112A_OB_2GHZ { 3, 287, 0 } -#define AR5K_RF5112A_DB_2GHZ { 3, 290, 0 } - -#define AR5K_RF5112A_OB_5GHZ { 3, 279, 0 } -#define AR5K_RF5112A_DB_5GHZ { 3, 282, 0 } - -#define AR5K_RF5112A_FIXED_BIAS_A { 1, 278, 0 } -#define AR5K_RF5112A_FIXED_BIAS_B { 1, 277, 0 } - -#define AR5K_RF5112A_XPD_SEL { 1, 302, 0 } -#define AR5K_RF5112A_PDGAINLO { 2, 270, 0 } -#define AR5K_RF5112A_PDGAINHI { 2, 257, 0 } - -/* Access to PWD registers */ -#define AR5K_RF5112A_PWD(_n) { 1, (306 - _n), 3 } - -/* Voltage regulators */ -#define AR5K_RF5112A_HIGH_VC_CP { 2, 90, 2 } -#define AR5K_RF5112A_MID_VC_CP { 2, 92, 2 } -#define AR5K_RF5112A_LOW_VC_CP { 2, 94, 2 } -#define AR5K_RF5112A_PUSH_UP { 1, 254, 2 } - -/* Power consumption */ -#define AR5K_RF5112A_PAD2GND { 1, 281, 1 } -#define AR5K_RF5112A_XB2_LVL { 2, 1, 3 } -#define AR5K_RF5112A_XB5_LVL { 2, 3, 3 } - -static const struct ath5k_rf_reg rf_regs_5112a[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5112A_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5112A_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5112A_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5112A_DB_5GHZ}, - {6, AR5K_RF_FIXED_BIAS_A, AR5K_RF5112A_FIXED_BIAS_A}, - {6, AR5K_RF_FIXED_BIAS_B, AR5K_RF5112A_FIXED_BIAS_B}, - {6, AR5K_RF_XPD_SEL, AR5K_RF5112A_XPD_SEL}, - {6, AR5K_RF_PD_GAIN_LO, AR5K_RF5112A_PDGAINLO}, - {6, AR5K_RF_PD_GAIN_HI, AR5K_RF5112A_PDGAINHI}, - {6, AR5K_RF_PWD_130, AR5K_RF5112A_PWD(130)}, - {6, AR5K_RF_PWD_131, AR5K_RF5112A_PWD(131)}, - {6, AR5K_RF_PWD_132, AR5K_RF5112A_PWD(132)}, - {6, AR5K_RF_PWD_136, AR5K_RF5112A_PWD(136)}, - {6, AR5K_RF_PWD_137, AR5K_RF5112A_PWD(137)}, - {6, AR5K_RF_PWD_138, AR5K_RF5112A_PWD(138)}, - {6, AR5K_RF_PWD_166, AR5K_RF5112A_PWD(166)}, - {6, AR5K_RF_PWD_167, AR5K_RF5112A_PWD(167)}, - {6, AR5K_RF_HIGH_VC_CP, AR5K_RF5112A_HIGH_VC_CP}, - {6, AR5K_RF_MID_VC_CP, AR5K_RF5112A_MID_VC_CP}, - {6, AR5K_RF_LOW_VC_CP, AR5K_RF5112A_LOW_VC_CP}, - {6, AR5K_RF_PUSH_UP, AR5K_RF5112A_PUSH_UP}, - {6, AR5K_RF_PAD2GND, AR5K_RF5112A_PAD2GND}, - {6, AR5K_RF_XB2_LVL, AR5K_RF5112A_XB2_LVL}, - {6, AR5K_RF_XB5_LVL, AR5K_RF5112A_XB5_LVL}, - {7, AR5K_RF_GAIN_I, AR5K_RF5112X_GAIN_I}, - {7, AR5K_RF_MIXVGA_OVR, AR5K_RF5112X_MIXVGA_OVR}, - {7, AR5K_RF_MIXGAIN_OVR, AR5K_RF5112X_MIXGAIN_OVR}, - {7, AR5K_RF_MIXGAIN_STEP, AR5K_RF5112X_MIXGAIN_STEP}, - {7, AR5K_RF_PD_DELAY_A, AR5K_RF5112X_PD_DELAY_A}, - {7, AR5K_RF_PD_DELAY_B, AR5K_RF5112X_PD_DELAY_B}, - {7, AR5K_RF_PD_DELAY_XR, AR5K_RF5112X_PD_DELAY_XR}, - {7, AR5K_RF_PD_PERIOD_A, AR5K_RF5112X_PD_PERIOD_A}, - {7, AR5K_RF_PD_PERIOD_B, AR5K_RF5112X_PD_PERIOD_B}, - {7, AR5K_RF_PD_PERIOD_XR, AR5K_RF5112X_PD_PERIOD_XR}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5112a[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x03060408, 0x03070408, 0x03060408, 0x03060408, 0x03070408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00800000, 0x00800000, 0x00800000, 0x00800000, 0x00800000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00180000, 0x00180000, 0x00180000, 0x00180000, 0x00180000 } }, - { 6, 0x989c, - { 0x00600000, 0x00600000, 0x006e0000, 0x006e0000, 0x006e0000 } }, - { 6, 0x989c, - { 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000, 0x00c70000 } }, - { 6, 0x989c, - { 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000, 0x004b0000 } }, - { 6, 0x989c, - { 0x04480000, 0x04480000, 0x04480000, 0x04480000, 0x04480000 } }, - { 6, 0x989c, - { 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000, 0x004c0000 } }, - { 6, 0x989c, - { 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000, 0x00e40000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000, 0x00fc0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000, 0x043f0000 } }, - { 6, 0x989c, - { 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000, 0x000c0000 } }, - { 6, 0x989c, - { 0x02190000, 0x02190000, 0x02190000, 0x02190000, 0x02190000 } }, - { 6, 0x989c, - { 0x00240000, 0x00240000, 0x00240000, 0x00240000, 0x00240000 } }, - { 6, 0x989c, - { 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000, 0x00b40000 } }, - { 6, 0x989c, - { 0x00990000, 0x00990000, 0x00990000, 0x00990000, 0x00990000 } }, - { 6, 0x989c, - { 0x00500000, 0x00500000, 0x00500000, 0x00500000, 0x00500000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00120000, 0x00120000, 0x00120000, 0x00120000, 0x00120000 } }, - { 6, 0x989c, - { 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000, 0xc0320000 } }, - { 6, 0x989c, - { 0x01740000, 0x01740000, 0x01740000, 0x01740000, 0x01740000 } }, - { 6, 0x989c, - { 0x00110000, 0x00110000, 0x00110000, 0x00110000, 0x00110000 } }, - { 6, 0x989c, - { 0x86280000, 0x86280000, 0x86280000, 0x86280000, 0x86280000 } }, - { 6, 0x989c, - { 0x31840000, 0x31840000, 0x31840000, 0x31840000, 0x31840000 } }, - { 6, 0x989c, - { 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080, 0x00f20080 } }, - { 6, 0x989c, - { 0x00270019, 0x00270019, 0x00270019, 0x00270019, 0x00270019 } }, - { 6, 0x989c, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2, 0x000000b2 } }, - { 6, 0x989c, - { 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084, 0x00b02084 } }, - { 6, 0x989c, - { 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4, 0x004125a4 } }, - { 6, 0x989c, - { 0x00119220, 0x00119220, 0x00119220, 0x00119220, 0x00119220 } }, - { 6, 0x989c, - { 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800, 0x001a4800 } }, - { 6, 0x98d8, - { 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230, 0x000b0230 } }, - { 7, 0x989c, - { 0x00000094, 0x00000094, 0x00000094, 0x00000094, 0x00000094 } }, - { 7, 0x989c, - { 0x00000091, 0x00000091, 0x00000091, 0x00000091, 0x00000091 } }, - { 7, 0x989c, - { 0x00000012, 0x00000012, 0x00000012, 0x00000012, 0x00000012 } }, - { 7, 0x989c, - { 0x00000080, 0x00000080, 0x00000080, 0x00000080, 0x00000080 } }, - { 7, 0x989c, - { 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9, 0x000000d9 } }, - { 7, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 7, 0x989c, - { 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0, 0x000000f0 } }, - { 7, 0x989c, - { 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2, 0x000000a2 } }, - { 7, 0x989c, - { 0x00000052, 0x00000052, 0x00000052, 0x00000052, 0x00000052 } }, - { 7, 0x989c, - { 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4, 0x000000d4 } }, - { 7, 0x989c, - { 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc, 0x000014cc } }, - { 7, 0x989c, - { 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c, 0x0000048c } }, - { 7, 0x98c4, - { 0x00000003, 0x00000003, 0x00000003, 0x00000003, 0x00000003 } }, -}; - - - -/******************\ -* RF2413 (Griffin) * -\******************/ - -/* BANK 6 len pos col */ -#define AR5K_RF2413_OB_2GHZ { 3, 168, 0 } -#define AR5K_RF2413_DB_2GHZ { 3, 165, 0 } - -static const struct ath5k_rf_reg rf_regs_2413[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF2413_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF2413_DB_2GHZ}, -}; - -/* Default mode specific settings - * XXX: a/aTurbo ??? - */ -static const struct ath5k_ini_rfbuffer rfb_2413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000, 0xf0000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x03000000, 0x03000000, 0x03000000, 0x03000000, 0x03000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x40400000, 0x40400000, 0x40400000, 0x40400000, 0x40400000 } }, - { 6, 0x989c, - { 0x65050000, 0x65050000, 0x65050000, 0x65050000, 0x65050000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00420000, 0x00420000, 0x00420000, 0x00420000, 0x00420000 } }, - { 6, 0x989c, - { 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000, 0x00b50000 } }, - { 6, 0x989c, - { 0x00030000, 0x00030000, 0x00030000, 0x00030000, 0x00030000 } }, - { 6, 0x989c, - { 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000, 0x00f70000 } }, - { 6, 0x989c, - { 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000, 0x009d0000 } }, - { 6, 0x989c, - { 0x00220000, 0x00220000, 0x00220000, 0x00220000, 0x00220000 } }, - { 6, 0x989c, - { 0x04220000, 0x04220000, 0x04220000, 0x04220000, 0x04220000 } }, - { 6, 0x989c, - { 0x00230018, 0x00230018, 0x00230018, 0x00230018, 0x00230018 } }, - { 6, 0x989c, - { 0x00280000, 0x00280000, 0x00280060, 0x00280060, 0x00280060 } }, - { 6, 0x989c, - { 0x005000c0, 0x005000c0, 0x005000c3, 0x005000c3, 0x005000c3 } }, - { 6, 0x989c, - { 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f, 0x0004007f } }, - { 6, 0x989c, - { 0x00000458, 0x00000458, 0x00000458, 0x00000458, 0x00000458 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000, 0x0000c000 } }, - { 6, 0x98d8, - { 0x00400230, 0x00400230, 0x00400230, 0x00400230, 0x00400230 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - - - -/***************************\ -* RF2315/RF2316 (Cobra SoC) * -\***************************/ - -/* BANK 6 len pos col */ -#define AR5K_RF2316_OB_2GHZ { 3, 178, 0 } -#define AR5K_RF2316_DB_2GHZ { 3, 175, 0 } - -static const struct ath5k_rf_reg rf_regs_2316[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF2316_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF2316_DB_2GHZ}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_2316[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000, 0xc0000000 } }, - { 6, 0x989c, - { 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000, 0x0f000000 } }, - { 6, 0x989c, - { 0x02000000, 0x02000000, 0x02000000, 0x02000000, 0x02000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000, 0xf8000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x95150000, 0x95150000, 0x95150000, 0x95150000, 0x95150000 } }, - { 6, 0x989c, - { 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000, 0xc1000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00080000, 0x00080000, 0x00080000, 0x00080000, 0x00080000 } }, - { 6, 0x989c, - { 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000, 0x00d50000 } }, - { 6, 0x989c, - { 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000, 0x000e0000 } }, - { 6, 0x989c, - { 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000, 0x00dc0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000, 0x008a0000 } }, - { 6, 0x989c, - { 0x10880000, 0x10880000, 0x10880000, 0x10880000, 0x10880000 } }, - { 6, 0x989c, - { 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060, 0x008c0060 } }, - { 6, 0x989c, - { 0x00a00000, 0x00a00000, 0x00a00080, 0x00a00080, 0x00a00080 } }, - { 6, 0x989c, - { 0x00400000, 0x00400000, 0x0040000d, 0x0040000d, 0x0040000d } }, - { 6, 0x989c, - { 0x00110400, 0x00110400, 0x00110400, 0x00110400, 0x00110400 } }, - { 6, 0x989c, - { 0x00000060, 0x00000060, 0x00000060, 0x00000060, 0x00000060 } }, - { 6, 0x989c, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 6, 0x989c, - { 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b00 } }, - { 6, 0x989c, - { 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8, 0x00000be8 } }, - { 6, 0x98c0, - { 0x00010000, 0x00010000, 0x00010000, 0x00010000, 0x00010000 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - - - -/******************************\ -* RF5413/RF5424 (Eagle/Condor) * -\******************************/ - -/* BANK 6 len pos col */ -#define AR5K_RF5413_OB_2GHZ { 3, 241, 0 } -#define AR5K_RF5413_DB_2GHZ { 3, 238, 0 } - -#define AR5K_RF5413_OB_5GHZ { 3, 247, 0 } -#define AR5K_RF5413_DB_5GHZ { 3, 244, 0 } - -#define AR5K_RF5413_PWD_ICLOBUF2G { 3, 131, 3 } -#define AR5K_RF5413_DERBY_CHAN_SEL_MODE { 1, 291, 2 } - -static const struct ath5k_rf_reg rf_regs_5413[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF5413_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF5413_DB_2GHZ}, - {6, AR5K_RF_OB_5GHZ, AR5K_RF5413_OB_5GHZ}, - {6, AR5K_RF_DB_5GHZ, AR5K_RF5413_DB_5GHZ}, - {6, AR5K_RF_PWD_ICLOBUF_2G, AR5K_RF5413_PWD_ICLOBUF2G}, - {6, AR5K_RF_DERBY_CHAN_SEL_MODE, AR5K_RF5413_DERBY_CHAN_SEL_MODE}, -}; - -/* Default mode specific settings */ -static const struct ath5k_ini_rfbuffer rfb_5413[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x00000008, 0x00000008, 0x00000008, 0x00000008, 0x00000008 } }, - { 3, 0x98dc, - { 0x00a000c0, 0x00a000c0, 0x00e000c0, 0x00e000c0, 0x00e000c0 } }, - { 6, 0x989c, - { 0x33000000, 0x33000000, 0x33000000, 0x33000000, 0x33000000 } }, - { 6, 0x989c, - { 0x01000000, 0x01000000, 0x01000000, 0x01000000, 0x01000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000, 0x1f000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000, 0x00b80000 } }, - { 6, 0x989c, - { 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000, 0x00b70000 } }, - { 6, 0x989c, - { 0x00840000, 0x00840000, 0x00840000, 0x00840000, 0x00840000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000, 0x00c00000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000, 0x00ff0000 } }, - { 6, 0x989c, - { 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000, 0x00d70000 } }, - { 6, 0x989c, - { 0x00610000, 0x00610000, 0x00610000, 0x00610000, 0x00610000 } }, - { 6, 0x989c, - { 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000, 0x00fe0000 } }, - { 6, 0x989c, - { 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000, 0x00de0000 } }, - { 6, 0x989c, - { 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000, 0x007f0000 } }, - { 6, 0x989c, - { 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000, 0x043d0000 } }, - { 6, 0x989c, - { 0x00770000, 0x00770000, 0x00770000, 0x00770000, 0x00770000 } }, - { 6, 0x989c, - { 0x00440000, 0x00440000, 0x00440000, 0x00440000, 0x00440000 } }, - { 6, 0x989c, - { 0x00980000, 0x00980000, 0x00980000, 0x00980000, 0x00980000 } }, - { 6, 0x989c, - { 0x00100080, 0x00100080, 0x00100080, 0x00100080, 0x00100080 } }, - { 6, 0x989c, - { 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034, 0x0005c034 } }, - { 6, 0x989c, - { 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0, 0x003100f0 } }, - { 6, 0x989c, - { 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f, 0x000c011f } }, - { 6, 0x989c, - { 0x00510040, 0x00510040, 0x00510040, 0x00510040, 0x00510040 } }, - { 6, 0x989c, - { 0x005000da, 0x005000da, 0x005000da, 0x005000da, 0x005000da } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00004044, 0x00004044, 0x00004044, 0x00004044, 0x00004044 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0, 0x000060c0 } }, - { 6, 0x989c, - { 0x00002c00, 0x00002c00, 0x00003600, 0x00003600, 0x00002c00 } }, - { 6, 0x98c8, - { 0x00000403, 0x00000403, 0x00040403, 0x00040403, 0x00040403 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - - - -/***************************\ -* RF2425/RF2417 (Swan/Nala) * -* AR2317 (Spider SoC) * -\***************************/ - -/* BANK 6 len pos col */ -#define AR5K_RF2425_OB_2GHZ { 3, 193, 0 } -#define AR5K_RF2425_DB_2GHZ { 3, 190, 0 } - -static const struct ath5k_rf_reg rf_regs_2425[] = { - {6, AR5K_RF_OB_2GHZ, AR5K_RF2425_OB_2GHZ}, - {6, AR5K_RF_DB_2GHZ, AR5K_RF2425_DB_2GHZ}, -}; - -/* Default mode specific settings - * XXX: a/aTurbo ? - */ -static const struct ath5k_ini_rfbuffer rfb_2425[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - -/* - * TODO: Handle the few differences with swan during - * bank modification and get rid of this - */ -static const struct ath5k_ini_rfbuffer rfb_2317[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02011408, 0x02001408, 0x02001408, 0x02011408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140100, 0x00140100, 0x00140100, 0x00140100, 0x00140100 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00009688, 0x00009688, 0x00009688, 0x00009688, 0x00009688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; - -/* - * TODO: Handle the few differences with swan during - * bank modification and get rid of this - * XXX: a/aTurbo ? - */ -static const struct ath5k_ini_rfbuffer rfb_2417[] = { - { 1, 0x98d4, - /* mode a/XR mode aTurbo mode b mode g mode gTurbo */ - { 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000020 } }, - { 2, 0x98d0, - { 0x02001408, 0x02001408, 0x02001408, 0x02001408, 0x02001408 } }, - { 3, 0x98dc, - { 0x00a020c0, 0x00a020c0, 0x00e020c0, 0x00e020c0, 0x00e020c0 } }, - { 6, 0x989c, - { 0x10000000, 0x10000000, 0x10000000, 0x10000000, 0x10000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000, 0x002a0000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00100000, 0x00100000, 0x00100000, 0x00100000, 0x00100000 } }, - { 6, 0x989c, - { 0x00020000, 0x00020000, 0x00020000, 0x00020000, 0x00020000 } }, - { 6, 0x989c, - { 0x00730000, 0x00730000, 0x00730000, 0x00730000, 0x00730000 } }, - { 6, 0x989c, - { 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000, 0x00f80000 } }, - { 6, 0x989c, - { 0x00e70000, 0x00e70000, 0x80e70000, 0x80e70000, 0x00e70000 } }, - { 6, 0x989c, - { 0x00140000, 0x00140000, 0x00140000, 0x00140000, 0x00140000 } }, - { 6, 0x989c, - { 0x00910040, 0x00910040, 0x00910040, 0x00910040, 0x00910040 } }, - { 6, 0x989c, - { 0x0007001a, 0x0007001a, 0x0207001a, 0x0207001a, 0x0007001a } }, - { 6, 0x989c, - { 0x00410000, 0x00410000, 0x00410000, 0x00410000, 0x00410000 } }, - { 6, 0x989c, - { 0x00810000, 0x00810000, 0x00810060, 0x00810060, 0x00810060 } }, - { 6, 0x989c, - { 0x00020800, 0x00020800, 0x00020803, 0x00020803, 0x00020803 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 } }, - { 6, 0x989c, - { 0x00001660, 0x00001660, 0x00001660, 0x00001660, 0x00001660 } }, - { 6, 0x989c, - { 0x00001688, 0x00001688, 0x00001688, 0x00001688, 0x00001688 } }, - { 6, 0x98c4, - { 0x00000001, 0x00000001, 0x00000001, 0x00000001, 0x00000001 } }, - { 7, 0x989c, - { 0x00006400, 0x00006400, 0x00006400, 0x00006400, 0x00006400 } }, - { 7, 0x989c, - { 0x00000800, 0x00000800, 0x00000800, 0x00000800, 0x00000800 } }, - { 7, 0x98cc, - { 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e, 0x0000000e } }, -}; diff --git a/drivers/net/wireless/ath/ath5k/rfgain.h b/drivers/net/wireless/ath/ath5k/rfgain.h deleted file mode 100644 index 1354d8c392c8..000000000000 --- a/drivers/net/wireless/ath/ath5k/rfgain.h +++ /dev/null @@ -1,516 +0,0 @@ -/* - * RF Gain optimization - * - * Copyright (c) 2004-2009 Reyk Floeter - * Copyright (c) 2006-2009 Nick Kossifidis - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - */ - -/* - * Mode-specific RF Gain table (64bytes) for RF5111/5112 - * (RF5110 only comes with AR5210 and only supports a/turbo a mode so initial - * RF Gain values are included in AR5K_AR5210_INI) - */ -struct ath5k_ini_rfgain { - u16 rfg_register; /* RF Gain register address */ - u32 rfg_value[2]; /* [freq (see below)] */ -}; - -/* Initial RF Gain settings for RF5111 */ -static const struct ath5k_ini_rfgain rfgain_5111[] = { - /* 5Ghz 2Ghz */ - { AR5K_RF_GAIN(0), { 0x000001a9, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x000001e9, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000029, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000069, 0x00000150 } }, - { AR5K_RF_GAIN(4), { 0x00000199, 0x00000190 } }, - { AR5K_RF_GAIN(5), { 0x000001d9, 0x000001d0 } }, - { AR5K_RF_GAIN(6), { 0x00000019, 0x00000010 } }, - { AR5K_RF_GAIN(7), { 0x00000059, 0x00000044 } }, - { AR5K_RF_GAIN(8), { 0x00000099, 0x00000084 } }, - { AR5K_RF_GAIN(9), { 0x000001a5, 0x00000148 } }, - { AR5K_RF_GAIN(10), { 0x000001e5, 0x00000188 } }, - { AR5K_RF_GAIN(11), { 0x00000025, 0x000001c8 } }, - { AR5K_RF_GAIN(12), { 0x000001c8, 0x00000014 } }, - { AR5K_RF_GAIN(13), { 0x00000008, 0x00000042 } }, - { AR5K_RF_GAIN(14), { 0x00000048, 0x00000082 } }, - { AR5K_RF_GAIN(15), { 0x00000088, 0x00000178 } }, - { AR5K_RF_GAIN(16), { 0x00000198, 0x000001b8 } }, - { AR5K_RF_GAIN(17), { 0x000001d8, 0x000001f8 } }, - { AR5K_RF_GAIN(18), { 0x00000018, 0x00000012 } }, - { AR5K_RF_GAIN(19), { 0x00000058, 0x00000052 } }, - { AR5K_RF_GAIN(20), { 0x00000098, 0x00000092 } }, - { AR5K_RF_GAIN(21), { 0x000001a4, 0x0000017c } }, - { AR5K_RF_GAIN(22), { 0x000001e4, 0x000001bc } }, - { AR5K_RF_GAIN(23), { 0x00000024, 0x000001fc } }, - { AR5K_RF_GAIN(24), { 0x00000064, 0x0000000a } }, - { AR5K_RF_GAIN(25), { 0x000000a4, 0x0000004a } }, - { AR5K_RF_GAIN(26), { 0x000000e4, 0x0000008a } }, - { AR5K_RF_GAIN(27), { 0x0000010a, 0x0000015a } }, - { AR5K_RF_GAIN(28), { 0x0000014a, 0x0000019a } }, - { AR5K_RF_GAIN(29), { 0x0000018a, 0x000001da } }, - { AR5K_RF_GAIN(30), { 0x000001ca, 0x0000000e } }, - { AR5K_RF_GAIN(31), { 0x0000000a, 0x0000004e } }, - { AR5K_RF_GAIN(32), { 0x0000004a, 0x0000008e } }, - { AR5K_RF_GAIN(33), { 0x0000008a, 0x0000015e } }, - { AR5K_RF_GAIN(34), { 0x000001ba, 0x0000019e } }, - { AR5K_RF_GAIN(35), { 0x000001fa, 0x000001de } }, - { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000009 } }, - { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000049 } }, - { AR5K_RF_GAIN(38), { 0x00000186, 0x00000089 } }, - { AR5K_RF_GAIN(39), { 0x000001c6, 0x00000179 } }, - { AR5K_RF_GAIN(40), { 0x00000006, 0x000001b9 } }, - { AR5K_RF_GAIN(41), { 0x00000046, 0x000001f9 } }, - { AR5K_RF_GAIN(42), { 0x00000086, 0x00000039 } }, - { AR5K_RF_GAIN(43), { 0x000000c6, 0x00000079 } }, - { AR5K_RF_GAIN(44), { 0x000000c6, 0x000000b9 } }, - { AR5K_RF_GAIN(45), { 0x000000c6, 0x000001bd } }, - { AR5K_RF_GAIN(46), { 0x000000c6, 0x000001fd } }, - { AR5K_RF_GAIN(47), { 0x000000c6, 0x0000003d } }, - { AR5K_RF_GAIN(48), { 0x000000c6, 0x0000007d } }, - { AR5K_RF_GAIN(49), { 0x000000c6, 0x000000bd } }, - { AR5K_RF_GAIN(50), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(51), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(52), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(53), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(54), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(55), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(56), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(57), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(58), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(59), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(60), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(61), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(62), { 0x000000c6, 0x000000fd } }, - { AR5K_RF_GAIN(63), { 0x000000c6, 0x000000fd } }, -}; - -/* Initial RF Gain settings for RF5112 */ -static const struct ath5k_ini_rfgain rfgain_5112[] = { - /* 5Ghz 2Ghz */ - { AR5K_RF_GAIN(0), { 0x00000007, 0x00000007 } }, - { AR5K_RF_GAIN(1), { 0x00000047, 0x00000047 } }, - { AR5K_RF_GAIN(2), { 0x00000087, 0x00000087 } }, - { AR5K_RF_GAIN(3), { 0x000001a0, 0x000001a0 } }, - { AR5K_RF_GAIN(4), { 0x000001e0, 0x000001e0 } }, - { AR5K_RF_GAIN(5), { 0x00000020, 0x00000020 } }, - { AR5K_RF_GAIN(6), { 0x00000060, 0x00000060 } }, - { AR5K_RF_GAIN(7), { 0x000001a1, 0x000001a1 } }, - { AR5K_RF_GAIN(8), { 0x000001e1, 0x000001e1 } }, - { AR5K_RF_GAIN(9), { 0x00000021, 0x00000021 } }, - { AR5K_RF_GAIN(10), { 0x00000061, 0x00000061 } }, - { AR5K_RF_GAIN(11), { 0x00000162, 0x00000162 } }, - { AR5K_RF_GAIN(12), { 0x000001a2, 0x000001a2 } }, - { AR5K_RF_GAIN(13), { 0x000001e2, 0x000001e2 } }, - { AR5K_RF_GAIN(14), { 0x00000022, 0x00000022 } }, - { AR5K_RF_GAIN(15), { 0x00000062, 0x00000062 } }, - { AR5K_RF_GAIN(16), { 0x00000163, 0x00000163 } }, - { AR5K_RF_GAIN(17), { 0x000001a3, 0x000001a3 } }, - { AR5K_RF_GAIN(18), { 0x000001e3, 0x000001e3 } }, - { AR5K_RF_GAIN(19), { 0x00000023, 0x00000023 } }, - { AR5K_RF_GAIN(20), { 0x00000063, 0x00000063 } }, - { AR5K_RF_GAIN(21), { 0x00000184, 0x00000184 } }, - { AR5K_RF_GAIN(22), { 0x000001c4, 0x000001c4 } }, - { AR5K_RF_GAIN(23), { 0x00000004, 0x00000004 } }, - { AR5K_RF_GAIN(24), { 0x000001ea, 0x0000000b } }, - { AR5K_RF_GAIN(25), { 0x0000002a, 0x0000004b } }, - { AR5K_RF_GAIN(26), { 0x0000006a, 0x0000008b } }, - { AR5K_RF_GAIN(27), { 0x000000aa, 0x000001ac } }, - { AR5K_RF_GAIN(28), { 0x000001ab, 0x000001ec } }, - { AR5K_RF_GAIN(29), { 0x000001eb, 0x0000002c } }, - { AR5K_RF_GAIN(30), { 0x0000002b, 0x00000012 } }, - { AR5K_RF_GAIN(31), { 0x0000006b, 0x00000052 } }, - { AR5K_RF_GAIN(32), { 0x000000ab, 0x00000092 } }, - { AR5K_RF_GAIN(33), { 0x000001ac, 0x00000193 } }, - { AR5K_RF_GAIN(34), { 0x000001ec, 0x000001d3 } }, - { AR5K_RF_GAIN(35), { 0x0000002c, 0x00000013 } }, - { AR5K_RF_GAIN(36), { 0x0000003a, 0x00000053 } }, - { AR5K_RF_GAIN(37), { 0x0000007a, 0x00000093 } }, - { AR5K_RF_GAIN(38), { 0x000000ba, 0x00000194 } }, - { AR5K_RF_GAIN(39), { 0x000001bb, 0x000001d4 } }, - { AR5K_RF_GAIN(40), { 0x000001fb, 0x00000014 } }, - { AR5K_RF_GAIN(41), { 0x0000003b, 0x0000003a } }, - { AR5K_RF_GAIN(42), { 0x0000007b, 0x0000007a } }, - { AR5K_RF_GAIN(43), { 0x000000bb, 0x000000ba } }, - { AR5K_RF_GAIN(44), { 0x000001bc, 0x000001bb } }, - { AR5K_RF_GAIN(45), { 0x000001fc, 0x000001fb } }, - { AR5K_RF_GAIN(46), { 0x0000003c, 0x0000003b } }, - { AR5K_RF_GAIN(47), { 0x0000007c, 0x0000007b } }, - { AR5K_RF_GAIN(48), { 0x000000bc, 0x000000bb } }, - { AR5K_RF_GAIN(49), { 0x000000fc, 0x000001bc } }, - { AR5K_RF_GAIN(50), { 0x000000fc, 0x000001fc } }, - { AR5K_RF_GAIN(51), { 0x000000fc, 0x0000003c } }, - { AR5K_RF_GAIN(52), { 0x000000fc, 0x0000007c } }, - { AR5K_RF_GAIN(53), { 0x000000fc, 0x000000bc } }, - { AR5K_RF_GAIN(54), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(55), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(56), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(57), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(58), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(59), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(60), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(61), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(62), { 0x000000fc, 0x000000fc } }, - { AR5K_RF_GAIN(63), { 0x000000fc, 0x000000fc } }, -}; - -/* Initial RF Gain settings for RF2413 */ -static const struct ath5k_ini_rfgain rfgain_2413[] = { - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } }, - { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } }, - { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } }, - { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } }, - { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } }, - { AR5K_RF_GAIN(8), { 0x00000000, 0x00000168 } }, - { AR5K_RF_GAIN(9), { 0x00000000, 0x000001a8 } }, - { AR5K_RF_GAIN(10), { 0x00000000, 0x000001e8 } }, - { AR5K_RF_GAIN(11), { 0x00000000, 0x00000028 } }, - { AR5K_RF_GAIN(12), { 0x00000000, 0x00000068 } }, - { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } }, - { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } }, - { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } }, - { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } }, - { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } }, - { AR5K_RF_GAIN(18), { 0x00000000, 0x00000190 } }, - { AR5K_RF_GAIN(19), { 0x00000000, 0x000001d0 } }, - { AR5K_RF_GAIN(20), { 0x00000000, 0x00000010 } }, - { AR5K_RF_GAIN(21), { 0x00000000, 0x00000050 } }, - { AR5K_RF_GAIN(22), { 0x00000000, 0x00000090 } }, - { AR5K_RF_GAIN(23), { 0x00000000, 0x00000191 } }, - { AR5K_RF_GAIN(24), { 0x00000000, 0x000001d1 } }, - { AR5K_RF_GAIN(25), { 0x00000000, 0x00000011 } }, - { AR5K_RF_GAIN(26), { 0x00000000, 0x00000051 } }, - { AR5K_RF_GAIN(27), { 0x00000000, 0x00000091 } }, - { AR5K_RF_GAIN(28), { 0x00000000, 0x00000178 } }, - { AR5K_RF_GAIN(29), { 0x00000000, 0x000001b8 } }, - { AR5K_RF_GAIN(30), { 0x00000000, 0x000001f8 } }, - { AR5K_RF_GAIN(31), { 0x00000000, 0x00000038 } }, - { AR5K_RF_GAIN(32), { 0x00000000, 0x00000078 } }, - { AR5K_RF_GAIN(33), { 0x00000000, 0x00000199 } }, - { AR5K_RF_GAIN(34), { 0x00000000, 0x000001d9 } }, - { AR5K_RF_GAIN(35), { 0x00000000, 0x00000019 } }, - { AR5K_RF_GAIN(36), { 0x00000000, 0x00000059 } }, - { AR5K_RF_GAIN(37), { 0x00000000, 0x00000099 } }, - { AR5K_RF_GAIN(38), { 0x00000000, 0x000000d9 } }, - { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } }, -}; - -/* Initial RF Gain settings for AR2316 */ -static const struct ath5k_ini_rfgain rfgain_2316[] = { - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000000, 0x000000c0 } }, - { AR5K_RF_GAIN(4), { 0x00000000, 0x000000e0 } }, - { AR5K_RF_GAIN(5), { 0x00000000, 0x000000e0 } }, - { AR5K_RF_GAIN(6), { 0x00000000, 0x00000128 } }, - { AR5K_RF_GAIN(7), { 0x00000000, 0x00000128 } }, - { AR5K_RF_GAIN(8), { 0x00000000, 0x00000128 } }, - { AR5K_RF_GAIN(9), { 0x00000000, 0x00000168 } }, - { AR5K_RF_GAIN(10), { 0x00000000, 0x000001a8 } }, - { AR5K_RF_GAIN(11), { 0x00000000, 0x000001e8 } }, - { AR5K_RF_GAIN(12), { 0x00000000, 0x00000028 } }, - { AR5K_RF_GAIN(13), { 0x00000000, 0x00000068 } }, - { AR5K_RF_GAIN(14), { 0x00000000, 0x000000a8 } }, - { AR5K_RF_GAIN(15), { 0x00000000, 0x000000e8 } }, - { AR5K_RF_GAIN(16), { 0x00000000, 0x000000e8 } }, - { AR5K_RF_GAIN(17), { 0x00000000, 0x00000130 } }, - { AR5K_RF_GAIN(18), { 0x00000000, 0x00000130 } }, - { AR5K_RF_GAIN(19), { 0x00000000, 0x00000170 } }, - { AR5K_RF_GAIN(20), { 0x00000000, 0x000001b0 } }, - { AR5K_RF_GAIN(21), { 0x00000000, 0x000001f0 } }, - { AR5K_RF_GAIN(22), { 0x00000000, 0x00000030 } }, - { AR5K_RF_GAIN(23), { 0x00000000, 0x00000070 } }, - { AR5K_RF_GAIN(24), { 0x00000000, 0x000000b0 } }, - { AR5K_RF_GAIN(25), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(26), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(27), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(28), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(29), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(30), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(31), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(32), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(33), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(34), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(35), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(36), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f0 } }, - { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f0 } }, -}; - - -/* Initial RF Gain settings for RF5413 */ -static const struct ath5k_ini_rfgain rfgain_5413[] = { - /* 5Ghz 2Ghz */ - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000040, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000080, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x000001a1, 0x00000161 } }, - { AR5K_RF_GAIN(4), { 0x000001e1, 0x000001a1 } }, - { AR5K_RF_GAIN(5), { 0x00000021, 0x000001e1 } }, - { AR5K_RF_GAIN(6), { 0x00000061, 0x00000021 } }, - { AR5K_RF_GAIN(7), { 0x00000188, 0x00000061 } }, - { AR5K_RF_GAIN(8), { 0x000001c8, 0x00000188 } }, - { AR5K_RF_GAIN(9), { 0x00000008, 0x000001c8 } }, - { AR5K_RF_GAIN(10), { 0x00000048, 0x00000008 } }, - { AR5K_RF_GAIN(11), { 0x00000088, 0x00000048 } }, - { AR5K_RF_GAIN(12), { 0x000001a9, 0x00000088 } }, - { AR5K_RF_GAIN(13), { 0x000001e9, 0x00000169 } }, - { AR5K_RF_GAIN(14), { 0x00000029, 0x000001a9 } }, - { AR5K_RF_GAIN(15), { 0x00000069, 0x000001e9 } }, - { AR5K_RF_GAIN(16), { 0x000001d0, 0x00000029 } }, - { AR5K_RF_GAIN(17), { 0x00000010, 0x00000069 } }, - { AR5K_RF_GAIN(18), { 0x00000050, 0x00000190 } }, - { AR5K_RF_GAIN(19), { 0x00000090, 0x000001d0 } }, - { AR5K_RF_GAIN(20), { 0x000001b1, 0x00000010 } }, - { AR5K_RF_GAIN(21), { 0x000001f1, 0x00000050 } }, - { AR5K_RF_GAIN(22), { 0x00000031, 0x00000090 } }, - { AR5K_RF_GAIN(23), { 0x00000071, 0x00000171 } }, - { AR5K_RF_GAIN(24), { 0x000001b8, 0x000001b1 } }, - { AR5K_RF_GAIN(25), { 0x000001f8, 0x000001f1 } }, - { AR5K_RF_GAIN(26), { 0x00000038, 0x00000031 } }, - { AR5K_RF_GAIN(27), { 0x00000078, 0x00000071 } }, - { AR5K_RF_GAIN(28), { 0x00000199, 0x00000198 } }, - { AR5K_RF_GAIN(29), { 0x000001d9, 0x000001d8 } }, - { AR5K_RF_GAIN(30), { 0x00000019, 0x00000018 } }, - { AR5K_RF_GAIN(31), { 0x00000059, 0x00000058 } }, - { AR5K_RF_GAIN(32), { 0x00000099, 0x00000098 } }, - { AR5K_RF_GAIN(33), { 0x000000d9, 0x00000179 } }, - { AR5K_RF_GAIN(34), { 0x000000f9, 0x000001b9 } }, - { AR5K_RF_GAIN(35), { 0x000000f9, 0x000001f9 } }, - { AR5K_RF_GAIN(36), { 0x000000f9, 0x00000039 } }, - { AR5K_RF_GAIN(37), { 0x000000f9, 0x00000079 } }, - { AR5K_RF_GAIN(38), { 0x000000f9, 0x000000b9 } }, - { AR5K_RF_GAIN(39), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(40), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(41), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(42), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(43), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(44), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(45), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(46), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(47), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(48), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(49), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(50), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(51), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(52), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(53), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(54), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(55), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(56), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(57), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(58), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(59), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(60), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(61), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(62), { 0x000000f9, 0x000000f9 } }, - { AR5K_RF_GAIN(63), { 0x000000f9, 0x000000f9 } }, -}; - - -/* Initial RF Gain settings for RF2425 */ -static const struct ath5k_ini_rfgain rfgain_2425[] = { - { AR5K_RF_GAIN(0), { 0x00000000, 0x00000000 } }, - { AR5K_RF_GAIN(1), { 0x00000000, 0x00000040 } }, - { AR5K_RF_GAIN(2), { 0x00000000, 0x00000080 } }, - { AR5K_RF_GAIN(3), { 0x00000000, 0x00000181 } }, - { AR5K_RF_GAIN(4), { 0x00000000, 0x000001c1 } }, - { AR5K_RF_GAIN(5), { 0x00000000, 0x00000001 } }, - { AR5K_RF_GAIN(6), { 0x00000000, 0x00000041 } }, - { AR5K_RF_GAIN(7), { 0x00000000, 0x00000081 } }, - { AR5K_RF_GAIN(8), { 0x00000000, 0x00000188 } }, - { AR5K_RF_GAIN(9), { 0x00000000, 0x000001c8 } }, - { AR5K_RF_GAIN(10), { 0x00000000, 0x00000008 } }, - { AR5K_RF_GAIN(11), { 0x00000000, 0x00000048 } }, - { AR5K_RF_GAIN(12), { 0x00000000, 0x00000088 } }, - { AR5K_RF_GAIN(13), { 0x00000000, 0x00000189 } }, - { AR5K_RF_GAIN(14), { 0x00000000, 0x000001c9 } }, - { AR5K_RF_GAIN(15), { 0x00000000, 0x00000009 } }, - { AR5K_RF_GAIN(16), { 0x00000000, 0x00000049 } }, - { AR5K_RF_GAIN(17), { 0x00000000, 0x00000089 } }, - { AR5K_RF_GAIN(18), { 0x00000000, 0x000001b0 } }, - { AR5K_RF_GAIN(19), { 0x00000000, 0x000001f0 } }, - { AR5K_RF_GAIN(20), { 0x00000000, 0x00000030 } }, - { AR5K_RF_GAIN(21), { 0x00000000, 0x00000070 } }, - { AR5K_RF_GAIN(22), { 0x00000000, 0x00000171 } }, - { AR5K_RF_GAIN(23), { 0x00000000, 0x000001b1 } }, - { AR5K_RF_GAIN(24), { 0x00000000, 0x000001f1 } }, - { AR5K_RF_GAIN(25), { 0x00000000, 0x00000031 } }, - { AR5K_RF_GAIN(26), { 0x00000000, 0x00000071 } }, - { AR5K_RF_GAIN(27), { 0x00000000, 0x000001b8 } }, - { AR5K_RF_GAIN(28), { 0x00000000, 0x000001f8 } }, - { AR5K_RF_GAIN(29), { 0x00000000, 0x00000038 } }, - { AR5K_RF_GAIN(30), { 0x00000000, 0x00000078 } }, - { AR5K_RF_GAIN(31), { 0x00000000, 0x000000b8 } }, - { AR5K_RF_GAIN(32), { 0x00000000, 0x000001b9 } }, - { AR5K_RF_GAIN(33), { 0x00000000, 0x000001f9 } }, - { AR5K_RF_GAIN(34), { 0x00000000, 0x00000039 } }, - { AR5K_RF_GAIN(35), { 0x00000000, 0x00000079 } }, - { AR5K_RF_GAIN(36), { 0x00000000, 0x000000b9 } }, - { AR5K_RF_GAIN(37), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(38), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(39), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(40), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(41), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(42), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(43), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(44), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(45), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(46), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(47), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(48), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(49), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(50), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(51), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(52), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(53), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(54), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(55), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(56), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(57), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(58), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(59), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(60), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(61), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(62), { 0x00000000, 0x000000f9 } }, - { AR5K_RF_GAIN(63), { 0x00000000, 0x000000f9 } }, -}; - -#define AR5K_GAIN_CRN_FIX_BITS_5111 4 -#define AR5K_GAIN_CRN_FIX_BITS_5112 7 -#define AR5K_GAIN_CRN_MAX_FIX_BITS AR5K_GAIN_CRN_FIX_BITS_5112 -#define AR5K_GAIN_DYN_ADJUST_HI_MARGIN 15 -#define AR5K_GAIN_DYN_ADJUST_LO_MARGIN 20 -#define AR5K_GAIN_CCK_PROBE_CORR 5 -#define AR5K_GAIN_CCK_OFDM_GAIN_DELTA 15 -#define AR5K_GAIN_STEP_COUNT 10 - -/* Check if our current measurement is inside our - * current variable attenuation window */ -#define AR5K_GAIN_CHECK_ADJUST(_g) \ - ((_g)->g_current <= (_g)->g_low || (_g)->g_current >= (_g)->g_high) - -struct ath5k_gain_opt_step { - s8 gos_param[AR5K_GAIN_CRN_MAX_FIX_BITS]; - s8 gos_gain; -}; - -struct ath5k_gain_opt { - u8 go_default; - u8 go_steps_count; - const struct ath5k_gain_opt_step go_step[AR5K_GAIN_STEP_COUNT]; -}; - -/* - * Parameters on gos_param: - * 1) Tx clip PHY register - * 2) PWD 90 RF register - * 3) PWD 84 RF register - * 4) RFGainSel RF register - */ -static const struct ath5k_gain_opt rfgain_opt_5111 = { - 4, - 9, - { - { { 4, 1, 1, 1 }, 6 }, - { { 4, 0, 1, 1 }, 4 }, - { { 3, 1, 1, 1 }, 3 }, - { { 4, 0, 0, 1 }, 1 }, - { { 4, 1, 1, 0 }, 0 }, - { { 4, 0, 1, 0 }, -2 }, - { { 3, 1, 1, 0 }, -3 }, - { { 4, 0, 0, 0 }, -4 }, - { { 2, 1, 1, 0 }, -6 } - } -}; - -/* - * Parameters on gos_param: - * 1) Mixgain ovr RF register - * 2) PWD 138 RF register - * 3) PWD 137 RF register - * 4) PWD 136 RF register - * 5) PWD 132 RF register - * 6) PWD 131 RF register - * 7) PWD 130 RF register - */ -static const struct ath5k_gain_opt rfgain_opt_5112 = { - 1, - 8, - { - { { 3, 0, 0, 0, 0, 0, 0 }, 6 }, - { { 2, 0, 0, 0, 0, 0, 0 }, 0 }, - { { 1, 0, 0, 0, 0, 0, 0 }, -3 }, - { { 0, 0, 0, 0, 0, 0, 0 }, -6 }, - { { 0, 1, 1, 0, 0, 0, 0 }, -8 }, - { { 0, 1, 1, 0, 1, 1, 0 }, -10 }, - { { 0, 1, 0, 1, 1, 1, 0 }, -13 }, - { { 0, 1, 0, 1, 1, 0, 1 }, -16 }, - } -}; - diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c deleted file mode 100644 index 41a877b73fce..000000000000 --- a/drivers/net/wireless/ath/ath5k/rfkill.c +++ /dev/null @@ -1,121 +0,0 @@ -/* - * RFKILL support for ath5k - * - * Copyright (c) 2009 Tobias Doerffel - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any - * redistribution must be conditioned upon including a substantially - * similar Disclaimer requirement for further binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY - * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, - * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER - * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF - * THE POSSIBILITY OF SUCH DAMAGES. - */ - -#include "base.h" - - -static inline void ath5k_rfkill_disable(struct ath5k_softc *sc) -{ - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill disable (gpio:%d polarity:%d)\n", - sc->rf_kill.gpio, sc->rf_kill.polarity); - ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); - ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, !sc->rf_kill.polarity); -} - - -static inline void ath5k_rfkill_enable(struct ath5k_softc *sc) -{ - ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "rfkill enable (gpio:%d polarity:%d)\n", - sc->rf_kill.gpio, sc->rf_kill.polarity); - ath5k_hw_set_gpio_output(sc->ah, sc->rf_kill.gpio); - ath5k_hw_set_gpio(sc->ah, sc->rf_kill.gpio, sc->rf_kill.polarity); -} - -static inline void ath5k_rfkill_set_intr(struct ath5k_softc *sc, bool enable) -{ - struct ath5k_hw *ah = sc->ah; - u32 curval; - - ath5k_hw_set_gpio_input(ah, sc->rf_kill.gpio); - curval = ath5k_hw_get_gpio(ah, sc->rf_kill.gpio); - ath5k_hw_set_gpio_intr(ah, sc->rf_kill.gpio, enable ? - !!curval : !curval); -} - -static bool -ath5k_is_rfkill_set(struct ath5k_softc *sc) -{ - /* configuring GPIO for input for some reason disables rfkill */ - /*ath5k_hw_set_gpio_input(sc->ah, sc->rf_kill.gpio);*/ - return ath5k_hw_get_gpio(sc->ah, sc->rf_kill.gpio) == - sc->rf_kill.polarity; -} - -static void -ath5k_tasklet_rfkill_toggle(unsigned long data) -{ - struct ath5k_softc *sc = (void *)data; - bool blocked; - - blocked = ath5k_is_rfkill_set(sc); - wiphy_rfkill_set_hw_state(sc->hw->wiphy, blocked); -} - - -void -ath5k_rfkill_hw_start(struct ath5k_hw *ah) -{ - struct ath5k_softc *sc = ah->ah_sc; - - /* read rfkill GPIO configuration from EEPROM header */ - sc->rf_kill.gpio = ah->ah_capabilities.cap_eeprom.ee_rfkill_pin; - sc->rf_kill.polarity = ah->ah_capabilities.cap_eeprom.ee_rfkill_pol; - - tasklet_init(&sc->rf_kill.toggleq, ath5k_tasklet_rfkill_toggle, - (unsigned long)sc); - - ath5k_rfkill_disable(sc); - - /* enable interrupt for rfkill switch */ - if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) - ath5k_rfkill_set_intr(sc, true); -} - - -void -ath5k_rfkill_hw_stop(struct ath5k_hw *ah) -{ - struct ath5k_softc *sc = ah->ah_sc; - - /* disable interrupt for rfkill switch */ - if (AR5K_EEPROM_HDR_RFKILL(ah->ah_capabilities.cap_eeprom.ee_header)) - ath5k_rfkill_set_intr(sc, false); - - tasklet_kill(&sc->rf_kill.toggleq); - - /* enable RFKILL when stopping HW so Wifi LED is turned off */ - ath5k_rfkill_enable(sc); -} - diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig deleted file mode 100644 index ef5f59c4dd80..000000000000 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ /dev/null @@ -1,28 +0,0 @@ -config ATH9K - tristate "Atheros 802.11n wireless cards support" - depends on PCI && MAC80211 && WLAN_80211 - select MAC80211_LEDS - select LEDS_CLASS - select NEW_LEDS - ---help--- - This module adds support for wireless adapters based on - Atheros IEEE 802.11n AR5008, AR9001 and AR9002 family - of chipsets. For a specific list of supported external - cards, laptops that already ship with these cards and - APs that come with these cards refer to to ath9k wiki - products page: - - http://wireless.kernel.org/en/users/Drivers/ath9k/products - - If you choose to build a module, it'll be called ath9k. - -config ATH9K_DEBUG - bool "Atheros ath9k debugging" - depends on ATH9K - ---help--- - Say Y, if you need ath9k to display debug messages. - Pass the debug mask as a module parameter: - - modprobe ath9k debug=0x00000200 - - Look in ath9k/debug.h for possible debug masks diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile deleted file mode 100644 index ff2c9a26c10c..000000000000 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -ath9k-y += hw.o \ - eeprom.o \ - eeprom_def.o \ - eeprom_4k.o \ - eeprom_9287.o \ - mac.o \ - calib.o \ - ani.o \ - phy.o \ - beacon.o \ - main.o \ - recv.o \ - xmit.o \ - virtual.o \ - rc.o \ - btcoex.o - -ath9k-$(CONFIG_PCI) += pci.o -ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o -ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o - -obj-$(CONFIG_ATH9K) += ath9k.o diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c deleted file mode 100644 index 2ad7d0280f7a..000000000000 --- a/drivers/net/wireless/ath/ath9k/ahb.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * Copyright (c) 2009 Gabor Juhos - * Copyright (c) 2009 Imre Kaloz - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include "ath9k.h" - -/* return bus cachesize in 4B word units */ -static void ath_ahb_read_cachesize(struct ath_softc *sc, int *csz) -{ - *csz = L1_CACHE_BYTES >> 2; -} - -static void ath_ahb_cleanup(struct ath_softc *sc) -{ - iounmap(sc->mem); -} - -static bool ath_ahb_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) -{ - struct ath_softc *sc = ah->ah_sc; - struct platform_device *pdev = to_platform_device(sc->dev); - struct ath9k_platform_data *pdata; - - pdata = (struct ath9k_platform_data *) pdev->dev.platform_data; - if (off >= (ARRAY_SIZE(pdata->eeprom_data))) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "%s: flash read failed, offset %08x is out of range\n", - __func__, off); - return false; - } - - *data = pdata->eeprom_data[off]; - return true; -} - -static struct ath_bus_ops ath_ahb_bus_ops = { - .read_cachesize = ath_ahb_read_cachesize, - .cleanup = ath_ahb_cleanup, - - .eeprom_read = ath_ahb_eeprom_read, -}; - -static int ath_ahb_probe(struct platform_device *pdev) -{ - void __iomem *mem; - struct ath_wiphy *aphy; - struct ath_softc *sc; - struct ieee80211_hw *hw; - struct resource *res; - int irq; - int ret = 0; - struct ath_hw *ah; - - if (!pdev->dev.platform_data) { - dev_err(&pdev->dev, "no platform data specified\n"); - ret = -EINVAL; - goto err_out; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no memory resource found\n"); - ret = -ENXIO; - goto err_out; - } - - mem = ioremap_nocache(res->start, res->end - res->start + 1); - if (mem == NULL) { - dev_err(&pdev->dev, "ioremap failed\n"); - ret = -ENOMEM; - goto err_out; - } - - res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); - if (res == NULL) { - dev_err(&pdev->dev, "no IRQ resource found\n"); - ret = -ENXIO; - goto err_iounmap; - } - - irq = res->start; - - hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + - sizeof(struct ath_softc), &ath9k_ops); - if (hw == NULL) { - dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); - ret = -ENOMEM; - goto err_iounmap; - } - - SET_IEEE80211_DEV(hw, &pdev->dev); - platform_set_drvdata(pdev, hw); - - aphy = hw->priv; - sc = (struct ath_softc *) (aphy + 1); - aphy->sc = sc; - aphy->hw = hw; - sc->pri_wiphy = aphy; - sc->hw = hw; - sc->dev = &pdev->dev; - sc->mem = mem; - sc->bus_ops = &ath_ahb_bus_ops; - sc->irq = irq; - - ret = ath_init_device(AR5416_AR9100_DEVID, sc, 0x0); - if (ret) { - dev_err(&pdev->dev, "failed to initialize device\n"); - goto err_free_hw; - } - - ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc); - if (ret) { - dev_err(&pdev->dev, "request_irq failed\n"); - goto err_detach; - } - - ah = sc->sc_ah; - printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x, " - "AR%s RF Rev:%x, mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev, - (unsigned long)mem, irq); - - return 0; - - err_detach: - ath_detach(sc); - err_free_hw: - ieee80211_free_hw(hw); - platform_set_drvdata(pdev, NULL); - err_iounmap: - iounmap(mem); - err_out: - return ret; -} - -static int ath_ahb_remove(struct platform_device *pdev) -{ - struct ieee80211_hw *hw = platform_get_drvdata(pdev); - - if (hw) { - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - ath_cleanup(sc); - platform_set_drvdata(pdev, NULL); - } - - return 0; -} - -static struct platform_driver ath_ahb_driver = { - .probe = ath_ahb_probe, - .remove = ath_ahb_remove, - .driver = { - .name = "ath9k", - .owner = THIS_MODULE, - }, -}; - -int ath_ahb_init(void) -{ - return platform_driver_register(&ath_ahb_driver); -} - -void ath_ahb_exit(void) -{ - platform_driver_unregister(&ath_ahb_driver); -} diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c deleted file mode 100644 index 2b493742ef10..000000000000 --- a/drivers/net/wireless/ath/ath9k/ani.c +++ /dev/null @@ -1,811 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static int ath9k_hw_get_ani_channel_idx(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { - if (ah->ani[i].c && - ah->ani[i].c->channel == chan->channel) - return i; - if (ah->ani[i].c == NULL) { - ah->ani[i].c = chan; - return i; - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "No more channel states left. Using channel 0\n"); - - return 0; -} - -static bool ath9k_hw_ani_control(struct ath_hw *ah, - enum ath9k_ani_cmd cmd, int param) -{ - struct ar5416AniState *aniState = ah->curani; - - switch (cmd & ah->ani_function) { - case ATH9K_ANI_NOISE_IMMUNITY_LEVEL:{ - u32 level = param; - - if (level >= ARRAY_SIZE(ah->totalSizeDesired)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned)ARRAY_SIZE(ah->totalSizeDesired)); - return false; - } - - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_TOT_DES, - ah->totalSizeDesired[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, - AR_PHY_AGC_CTL1_COARSE_LOW, - ah->coarse_low[level]); - REG_RMW_FIELD(ah, AR_PHY_AGC_CTL1, - AR_PHY_AGC_CTL1_COARSE_HIGH, - ah->coarse_high[level]); - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRPWR, - ah->firpwr[level]); - - if (level > aniState->noiseImmunityLevel) - ah->stats.ast_ani_niup++; - else if (level < aniState->noiseImmunityLevel) - ah->stats.ast_ani_nidown++; - aniState->noiseImmunityLevel = level; - break; - } - case ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION:{ - const int m1ThreshLow[] = { 127, 50 }; - const int m2ThreshLow[] = { 127, 40 }; - const int m1Thresh[] = { 127, 0x4d }; - const int m2Thresh[] = { 127, 0x40 }; - const int m2CountThr[] = { 31, 16 }; - const int m2CountThrLow[] = { 63, 48 }; - u32 on = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M1_THRESH_LOW, - m1ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M2_THRESH_LOW, - m2ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M1_THRESH, - m1Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2_THRESH, - m2Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR, - AR_PHY_SFCORR_M2COUNT_THR, - m2CountThr[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW, - m2CountThrLow[on]); - - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH_LOW, - m1ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH_LOW, - m2ThreshLow[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M1_THRESH, - m1Thresh[on]); - REG_RMW_FIELD(ah, AR_PHY_SFCORR_EXT, - AR_PHY_SFCORR_EXT_M2_THRESH, - m2Thresh[on]); - - if (on) - REG_SET_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - else - REG_CLR_BIT(ah, AR_PHY_SFCORR_LOW, - AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW); - - if (!on != aniState->ofdmWeakSigDetectOff) { - if (on) - ah->stats.ast_ani_ofdmon++; - else - ah->stats.ast_ani_ofdmoff++; - aniState->ofdmWeakSigDetectOff = !on; - } - break; - } - case ATH9K_ANI_CCK_WEAK_SIGNAL_THR:{ - const int weakSigThrCck[] = { 8, 6 }; - u32 high = param ? 1 : 0; - - REG_RMW_FIELD(ah, AR_PHY_CCK_DETECT, - AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK, - weakSigThrCck[high]); - if (high != aniState->cckWeakSigThreshold) { - if (high) - ah->stats.ast_ani_cckhigh++; - else - ah->stats.ast_ani_ccklow++; - aniState->cckWeakSigThreshold = high; - } - break; - } - case ATH9K_ANI_FIRSTEP_LEVEL:{ - const int firstep[] = { 0, 4, 8 }; - u32 level = param; - - if (level >= ARRAY_SIZE(firstep)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) ARRAY_SIZE(firstep)); - return false; - } - REG_RMW_FIELD(ah, AR_PHY_FIND_SIG, - AR_PHY_FIND_SIG_FIRSTEP, - firstep[level]); - if (level > aniState->firstepLevel) - ah->stats.ast_ani_stepup++; - else if (level < aniState->firstepLevel) - ah->stats.ast_ani_stepdown++; - aniState->firstepLevel = level; - break; - } - case ATH9K_ANI_SPUR_IMMUNITY_LEVEL:{ - const int cycpwrThr1[] = - { 2, 4, 6, 8, 10, 12, 14, 16 }; - u32 level = param; - - if (level >= ARRAY_SIZE(cycpwrThr1)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "level out of range (%u > %u)\n", - level, - (unsigned) - ARRAY_SIZE(cycpwrThr1)); - return false; - } - REG_RMW_FIELD(ah, AR_PHY_TIMING5, - AR_PHY_TIMING5_CYCPWR_THR1, - cycpwrThr1[level]); - if (level > aniState->spurImmunityLevel) - ah->stats.ast_ani_spurup++; - else if (level < aniState->spurImmunityLevel) - ah->stats.ast_ani_spurdown++; - aniState->spurImmunityLevel = level; - break; - } - case ATH9K_ANI_PRESENT: - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "invalid cmd %u\n", cmd); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "ANI parameters:\n"); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "noiseImmunityLevel=%d, spurImmunityLevel=%d, " - "ofdmWeakSigDetectOff=%d\n", - aniState->noiseImmunityLevel, aniState->spurImmunityLevel, - !aniState->ofdmWeakSigDetectOff); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "cckWeakSigThreshold=%d, " - "firstepLevel=%d, listenTime=%d\n", - aniState->cckWeakSigThreshold, aniState->firstepLevel, - aniState->listenTime); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "cycleCount=%d, ofdmPhyErrCount=%d, cckPhyErrCount=%d\n\n", - aniState->cycleCount, aniState->ofdmPhyErrCount, - aniState->cckPhyErrCount); - - return true; -} - -static void ath9k_hw_update_mibstats(struct ath_hw *ah, - struct ath9k_mib_stats *stats) -{ - stats->ackrcv_bad += REG_READ(ah, AR_ACK_FAIL); - stats->rts_bad += REG_READ(ah, AR_RTS_FAIL); - stats->fcs_bad += REG_READ(ah, AR_FCS_FAIL); - stats->rts_good += REG_READ(ah, AR_RTS_OK); - stats->beacons += REG_READ(ah, AR_BEACON_CNT); -} - -static void ath9k_ani_restart(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - aniState->listenTime = 0; - - if (aniState->ofdmTrigHigh > AR_PHY_COUNTMAX) { - aniState->ofdmPhyErrBase = 0; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "OFDM Trigger is too high for hw counters\n"); - } else { - aniState->ofdmPhyErrBase = - AR_PHY_COUNTMAX - aniState->ofdmTrigHigh; - } - if (aniState->cckTrigHigh > AR_PHY_COUNTMAX) { - aniState->cckPhyErrBase = 0; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "CCK Trigger is too high for hw counters\n"); - } else { - aniState->cckPhyErrBase = - AR_PHY_COUNTMAX - aniState->cckTrigHigh; - } - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Writing ofdmbase=%u cckbase=%u\n", - aniState->ofdmPhyErrBase, - aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_1, aniState->ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_2, aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); - - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - - aniState->ofdmPhyErrCount = 0; - aniState->cckPhyErrCount = 0; -} - -static void ath9k_hw_ani_ofdm_err_trigger(struct ath_hw *ah) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct ar5416AniState *aniState; - int32_t rssi; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - - if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel + 1)) { - return; - } - } - - if (aniState->spurImmunityLevel < HAL_SPUR_IMMUNE_MAX) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, - aniState->spurImmunityLevel + 1)) { - return; - } - } - - if (ah->opmode == NL80211_IFTYPE_AP) { - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - } - return; - } - rssi = BEACON_RSSI(ah); - if (rssi > aniState->rssiThrHigh) { - if (!aniState->ofdmWeakSigDetectOff) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - false)) { - ath9k_hw_ani_control(ah, - ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); - return; - } - } - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - return; - } - } else if (rssi > aniState->rssiThrLow) { - if (aniState->ofdmWeakSigDetectOff) - ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - true); - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - return; - } else { - if ((conf->channel->band == IEEE80211_BAND_2GHZ) && - !conf_is_ht(conf)) { - if (!aniState->ofdmWeakSigDetectOff) - ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - false); - if (aniState->firstepLevel > 0) - ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, 0); - return; - } - } -} - -static void ath9k_hw_ani_cck_err_trigger(struct ath_hw *ah) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct ar5416AniState *aniState; - int32_t rssi; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - if (aniState->noiseImmunityLevel < HAL_NOISE_IMMUNE_MAX) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel + 1)) { - return; - } - } - if (ah->opmode == NL80211_IFTYPE_AP) { - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) { - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - } - return; - } - rssi = BEACON_RSSI(ah); - if (rssi > aniState->rssiThrLow) { - if (aniState->firstepLevel < HAL_FIRST_STEP_MAX) - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel + 1); - } else { - if ((conf->channel->band == IEEE80211_BAND_2GHZ) && - !conf_is_ht(conf)) { - if (aniState->firstepLevel > 0) - ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, 0); - } - } -} - -static void ath9k_hw_ani_lower_immunity(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - int32_t rssi; - - aniState = ah->curani; - - if (ah->opmode == NL80211_IFTYPE_AP) { - if (aniState->firstepLevel > 0) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel - 1)) - return; - } - } else { - rssi = BEACON_RSSI(ah); - if (rssi > aniState->rssiThrHigh) { - /* XXX: Handle me */ - } else if (rssi > aniState->rssiThrLow) { - if (aniState->ofdmWeakSigDetectOff) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - true) == true) - return; - } - if (aniState->firstepLevel > 0) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel - 1) == true) - return; - } - } else { - if (aniState->firstepLevel > 0) { - if (ath9k_hw_ani_control(ah, - ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel - 1) == true) - return; - } - } - } - - if (aniState->spurImmunityLevel > 0) { - if (ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, - aniState->spurImmunityLevel - 1)) - return; - } - - if (aniState->noiseImmunityLevel > 0) { - ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel - 1); - return; - } -} - -static int32_t ath9k_hw_ani_get_listen_time(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - u32 txFrameCount, rxFrameCount, cycleCount; - int32_t listenTime; - - txFrameCount = REG_READ(ah, AR_TFCNT); - rxFrameCount = REG_READ(ah, AR_RFCNT); - cycleCount = REG_READ(ah, AR_CCCNT); - - aniState = ah->curani; - if (aniState->cycleCount == 0 || aniState->cycleCount > cycleCount) { - - listenTime = 0; - ah->stats.ast_ani_lzero++; - } else { - int32_t ccdelta = cycleCount - aniState->cycleCount; - int32_t rfdelta = rxFrameCount - aniState->rxFrameCount; - int32_t tfdelta = txFrameCount - aniState->txFrameCount; - listenTime = (ccdelta - rfdelta - tfdelta) / 44000; - } - aniState->cycleCount = cycleCount; - aniState->txFrameCount = txFrameCount; - aniState->rxFrameCount = rxFrameCount; - - return listenTime; -} - -void ath9k_ani_reset(struct ath_hw *ah) -{ - struct ar5416AniState *aniState; - struct ath9k_channel *chan = ah->curchan; - int index; - - if (!DO_ANI(ah)) - return; - - index = ath9k_hw_get_ani_channel_idx(ah, chan); - aniState = &ah->ani[index]; - ah->curani = aniState; - - if (DO_ANI(ah) && ah->opmode != NL80211_IFTYPE_STATION - && ah->opmode != NL80211_IFTYPE_ADHOC) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Reset ANI state opmode %u\n", ah->opmode); - ah->stats.ast_ani_reset++; - - if (ah->opmode == NL80211_IFTYPE_AP) { - /* - * ath9k_hw_ani_control() will only process items set on - * ah->ani_function - */ - if (IS_CHAN_2GHZ(chan)) - ah->ani_function = (ATH9K_ANI_SPUR_IMMUNITY_LEVEL | - ATH9K_ANI_FIRSTEP_LEVEL); - else - ah->ani_function = 0; - } - - ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, 0); - ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, 0); - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, 0); - ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - !ATH9K_ANI_USE_OFDM_WEAK_SIG); - ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, - ATH9K_ANI_CCK_WEAK_SIG_THR); - - ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) | - ATH9K_RX_FILTER_PHYERR); - - if (ah->opmode == NL80211_IFTYPE_AP) { - ah->curani->ofdmTrigHigh = - ah->config.ofdm_trig_high; - ah->curani->ofdmTrigLow = - ah->config.ofdm_trig_low; - ah->curani->cckTrigHigh = - ah->config.cck_trig_high; - ah->curani->cckTrigLow = - ah->config.cck_trig_low; - } - ath9k_ani_restart(ah); - return; - } - - if (aniState->noiseImmunityLevel != 0) - ath9k_hw_ani_control(ah, ATH9K_ANI_NOISE_IMMUNITY_LEVEL, - aniState->noiseImmunityLevel); - if (aniState->spurImmunityLevel != 0) - ath9k_hw_ani_control(ah, ATH9K_ANI_SPUR_IMMUNITY_LEVEL, - aniState->spurImmunityLevel); - if (aniState->ofdmWeakSigDetectOff) - ath9k_hw_ani_control(ah, ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION, - !aniState->ofdmWeakSigDetectOff); - if (aniState->cckWeakSigThreshold) - ath9k_hw_ani_control(ah, ATH9K_ANI_CCK_WEAK_SIGNAL_THR, - aniState->cckWeakSigThreshold); - if (aniState->firstepLevel != 0) - ath9k_hw_ani_control(ah, ATH9K_ANI_FIRSTEP_LEVEL, - aniState->firstepLevel); - - ath9k_hw_setrxfilter(ah, ath9k_hw_getrxfilter(ah) & - ~ATH9K_RX_FILTER_PHYERR); - ath9k_ani_restart(ah); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); -} - -void ath9k_hw_ani_monitor(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416AniState *aniState; - int32_t listenTime; - u32 phyCnt1, phyCnt2; - u32 ofdmPhyErrCnt, cckPhyErrCnt; - - if (!DO_ANI(ah)) - return; - - aniState = ah->curani; - - listenTime = ath9k_hw_ani_get_listen_time(ah); - if (listenTime < 0) { - ah->stats.ast_ani_lneg++; - ath9k_ani_restart(ah); - return; - } - - aniState->listenTime += listenTime; - - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - - phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); - phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); - - if (phyCnt1 < aniState->ofdmPhyErrBase || - phyCnt2 < aniState->cckPhyErrBase) { - if (phyCnt1 < aniState->ofdmPhyErrBase) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "phyCnt1 0x%x, resetting " - "counter value to 0x%x\n", - phyCnt1, aniState->ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_1, - aniState->ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, - AR_PHY_ERR_OFDM_TIMING); - } - if (phyCnt2 < aniState->cckPhyErrBase) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "phyCnt2 0x%x, resetting " - "counter value to 0x%x\n", - phyCnt2, aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_2, - aniState->cckPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, - AR_PHY_ERR_CCK_TIMING); - } - return; - } - - ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; - ah->stats.ast_ani_ofdmerrs += - ofdmPhyErrCnt - aniState->ofdmPhyErrCount; - aniState->ofdmPhyErrCount = ofdmPhyErrCnt; - - cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; - ah->stats.ast_ani_cckerrs += - cckPhyErrCnt - aniState->cckPhyErrCount; - aniState->cckPhyErrCount = cckPhyErrCnt; - - if (aniState->listenTime > 5 * ah->aniperiod) { - if (aniState->ofdmPhyErrCount <= aniState->listenTime * - aniState->ofdmTrigLow / 1000 && - aniState->cckPhyErrCount <= aniState->listenTime * - aniState->cckTrigLow / 1000) - ath9k_hw_ani_lower_immunity(ah); - ath9k_ani_restart(ah); - } else if (aniState->listenTime > ah->aniperiod) { - if (aniState->ofdmPhyErrCount > aniState->listenTime * - aniState->ofdmTrigHigh / 1000) { - ath9k_hw_ani_ofdm_err_trigger(ah); - ath9k_ani_restart(ah); - } else if (aniState->cckPhyErrCount > - aniState->listenTime * aniState->cckTrigHigh / - 1000) { - ath9k_hw_ani_cck_err_trigger(ah); - ath9k_ani_restart(ah); - } - } -} - -void ath9k_enable_mib_counters(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Enable MIB counters\n"); - - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - - REG_WRITE(ah, AR_FILT_OFDM, 0); - REG_WRITE(ah, AR_FILT_CCK, 0); - REG_WRITE(ah, AR_MIBC, - ~(AR_MIBC_COW | AR_MIBC_FMC | AR_MIBC_CMC | AR_MIBC_MCS) - & 0x0f); - REG_WRITE(ah, AR_PHY_ERR_MASK_1, AR_PHY_ERR_OFDM_TIMING); - REG_WRITE(ah, AR_PHY_ERR_MASK_2, AR_PHY_ERR_CCK_TIMING); -} - -/* Freeze the MIB counters, get the stats and then clear them */ -void ath9k_hw_disable_mib_counters(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disable MIB counters\n"); - REG_WRITE(ah, AR_MIBC, AR_MIBC_FMC); - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - REG_WRITE(ah, AR_MIBC, AR_MIBC_CMC); - REG_WRITE(ah, AR_FILT_OFDM, 0); - REG_WRITE(ah, AR_FILT_CCK, 0); -} - -u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, - u32 *rxc_pcnt, - u32 *rxf_pcnt, - u32 *txf_pcnt) -{ - static u32 cycles, rx_clear, rx_frame, tx_frame; - u32 good = 1; - - u32 rc = REG_READ(ah, AR_RCCNT); - u32 rf = REG_READ(ah, AR_RFCNT); - u32 tf = REG_READ(ah, AR_TFCNT); - u32 cc = REG_READ(ah, AR_CCCNT); - - if (cycles == 0 || cycles > cc) { - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "cycle counter wrap. ExtBusy = 0\n"); - good = 0; - } else { - u32 cc_d = cc - cycles; - u32 rc_d = rc - rx_clear; - u32 rf_d = rf - rx_frame; - u32 tf_d = tf - tx_frame; - - if (cc_d != 0) { - *rxc_pcnt = rc_d * 100 / cc_d; - *rxf_pcnt = rf_d * 100 / cc_d; - *txf_pcnt = tf_d * 100 / cc_d; - } else { - good = 0; - } - } - - cycles = cc; - rx_frame = rf; - rx_clear = rc; - tx_frame = tf; - - return good; -} - -/* - * Process a MIB interrupt. We may potentially be invoked because - * any of the MIB counters overflow/trigger so don't assume we're - * here because a PHY error counter triggered. - */ -void ath9k_hw_procmibevent(struct ath_hw *ah) -{ - u32 phyCnt1, phyCnt2; - - /* Reset these counters regardless */ - REG_WRITE(ah, AR_FILT_OFDM, 0); - REG_WRITE(ah, AR_FILT_CCK, 0); - if (!(REG_READ(ah, AR_SLP_MIB_CTRL) & AR_SLP_MIB_PENDING)) - REG_WRITE(ah, AR_SLP_MIB_CTRL, AR_SLP_MIB_CLEAR); - - /* Clear the mib counters and save them in the stats */ - ath9k_hw_update_mibstats(ah, &ah->ah_mibStats); - - if (!DO_ANI(ah)) - return; - - /* NB: these are not reset-on-read */ - phyCnt1 = REG_READ(ah, AR_PHY_ERR_1); - phyCnt2 = REG_READ(ah, AR_PHY_ERR_2); - if (((phyCnt1 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK) || - ((phyCnt2 & AR_MIBCNT_INTRMASK) == AR_MIBCNT_INTRMASK)) { - struct ar5416AniState *aniState = ah->curani; - u32 ofdmPhyErrCnt, cckPhyErrCnt; - - /* NB: only use ast_ani_*errs with AH_PRIVATE_DIAG */ - ofdmPhyErrCnt = phyCnt1 - aniState->ofdmPhyErrBase; - ah->stats.ast_ani_ofdmerrs += - ofdmPhyErrCnt - aniState->ofdmPhyErrCount; - aniState->ofdmPhyErrCount = ofdmPhyErrCnt; - - cckPhyErrCnt = phyCnt2 - aniState->cckPhyErrBase; - ah->stats.ast_ani_cckerrs += - cckPhyErrCnt - aniState->cckPhyErrCount; - aniState->cckPhyErrCount = cckPhyErrCnt; - - /* - * NB: figure out which counter triggered. If both - * trigger we'll only deal with one as the processing - * clobbers the error counter so the trigger threshold - * check will never be true. - */ - if (aniState->ofdmPhyErrCount > aniState->ofdmTrigHigh) - ath9k_hw_ani_ofdm_err_trigger(ah); - if (aniState->cckPhyErrCount > aniState->cckTrigHigh) - ath9k_hw_ani_cck_err_trigger(ah); - /* NB: always restart to insure the h/w counters are reset */ - ath9k_ani_restart(ah); - } -} - -void ath9k_hw_ani_setup(struct ath_hw *ah) -{ - int i; - - const int totalSizeDesired[] = { -55, -55, -55, -55, -62 }; - const int coarseHigh[] = { -14, -14, -14, -14, -12 }; - const int coarseLow[] = { -64, -64, -64, -64, -70 }; - const int firpwr[] = { -78, -78, -78, -78, -80 }; - - for (i = 0; i < 5; i++) { - ah->totalSizeDesired[i] = totalSizeDesired[i]; - ah->coarse_high[i] = coarseHigh[i]; - ah->coarse_low[i] = coarseLow[i]; - ah->firpwr[i] = firpwr[i]; - } -} - -void ath9k_hw_ani_init(struct ath_hw *ah) -{ - int i; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Initialize ANI\n"); - - memset(ah->ani, 0, sizeof(ah->ani)); - for (i = 0; i < ARRAY_SIZE(ah->ani); i++) { - ah->ani[i].ofdmTrigHigh = ATH9K_ANI_OFDM_TRIG_HIGH; - ah->ani[i].ofdmTrigLow = ATH9K_ANI_OFDM_TRIG_LOW; - ah->ani[i].cckTrigHigh = ATH9K_ANI_CCK_TRIG_HIGH; - ah->ani[i].cckTrigLow = ATH9K_ANI_CCK_TRIG_LOW; - ah->ani[i].rssiThrHigh = ATH9K_ANI_RSSI_THR_HIGH; - ah->ani[i].rssiThrLow = ATH9K_ANI_RSSI_THR_LOW; - ah->ani[i].ofdmWeakSigDetectOff = - !ATH9K_ANI_USE_OFDM_WEAK_SIG; - ah->ani[i].cckWeakSigThreshold = - ATH9K_ANI_CCK_WEAK_SIG_THR; - ah->ani[i].spurImmunityLevel = ATH9K_ANI_SPUR_IMMUNE_LVL; - ah->ani[i].firstepLevel = ATH9K_ANI_FIRSTEP_LVL; - ah->ani[i].ofdmPhyErrBase = - AR_PHY_COUNTMAX - ATH9K_ANI_OFDM_TRIG_HIGH; - ah->ani[i].cckPhyErrBase = - AR_PHY_COUNTMAX - ATH9K_ANI_CCK_TRIG_HIGH; - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Setting OfdmErrBase = 0x%08x\n", - ah->ani[0].ofdmPhyErrBase); - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Setting cckErrBase = 0x%08x\n", - ah->ani[0].cckPhyErrBase); - - REG_WRITE(ah, AR_PHY_ERR_1, ah->ani[0].ofdmPhyErrBase); - REG_WRITE(ah, AR_PHY_ERR_2, ah->ani[0].cckPhyErrBase); - ath9k_enable_mib_counters(ah); - - ah->aniperiod = ATH9K_ANI_PERIOD; - if (ah->config.enable_ani) - ah->proc_phyerr |= HAL_PROCESS_ANI; -} - -void ath9k_hw_ani_disable(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_ANI, "Disabling ANI\n"); - - ath9k_hw_disable_mib_counters(ah); - REG_WRITE(ah, AR_PHY_ERR_1, 0); - REG_WRITE(ah, AR_PHY_ERR_2, 0); -} diff --git a/drivers/net/wireless/ath/ath9k/ani.h b/drivers/net/wireless/ath/ath9k/ani.h deleted file mode 100644 index 4e1ab94a5153..000000000000 --- a/drivers/net/wireless/ath/ath9k/ani.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef ANI_H -#define ANI_H - -#define HAL_PROCESS_ANI 0x00000001 - -#define DO_ANI(ah) (((ah)->proc_phyerr & HAL_PROCESS_ANI)) - -#define BEACON_RSSI(ahp) (ahp->stats.avgbrssi) - -#define ATH9K_ANI_OFDM_TRIG_HIGH 500 -#define ATH9K_ANI_OFDM_TRIG_LOW 200 -#define ATH9K_ANI_CCK_TRIG_HIGH 200 -#define ATH9K_ANI_CCK_TRIG_LOW 100 -#define ATH9K_ANI_NOISE_IMMUNE_LVL 4 -#define ATH9K_ANI_USE_OFDM_WEAK_SIG true -#define ATH9K_ANI_CCK_WEAK_SIG_THR false -#define ATH9K_ANI_SPUR_IMMUNE_LVL 7 -#define ATH9K_ANI_FIRSTEP_LVL 0 -#define ATH9K_ANI_RSSI_THR_HIGH 40 -#define ATH9K_ANI_RSSI_THR_LOW 7 -#define ATH9K_ANI_PERIOD 100 - -#define HAL_NOISE_IMMUNE_MAX 4 -#define HAL_SPUR_IMMUNE_MAX 7 -#define HAL_FIRST_STEP_MAX 2 - -enum ath9k_ani_cmd { - ATH9K_ANI_PRESENT = 0x1, - ATH9K_ANI_NOISE_IMMUNITY_LEVEL = 0x2, - ATH9K_ANI_OFDM_WEAK_SIGNAL_DETECTION = 0x4, - ATH9K_ANI_CCK_WEAK_SIGNAL_THR = 0x8, - ATH9K_ANI_FIRSTEP_LEVEL = 0x10, - ATH9K_ANI_SPUR_IMMUNITY_LEVEL = 0x20, - ATH9K_ANI_MODE = 0x40, - ATH9K_ANI_PHYERR_RESET = 0x80, - ATH9K_ANI_ALL = 0xff -}; - -struct ath9k_mib_stats { - u32 ackrcv_bad; - u32 rts_bad; - u32 rts_good; - u32 fcs_bad; - u32 beacons; -}; - -struct ar5416AniState { - struct ath9k_channel *c; - u8 noiseImmunityLevel; - u8 spurImmunityLevel; - u8 firstepLevel; - u8 ofdmWeakSigDetectOff; - u8 cckWeakSigThreshold; - u32 listenTime; - u32 ofdmTrigHigh; - u32 ofdmTrigLow; - int32_t cckTrigHigh; - int32_t cckTrigLow; - int32_t rssiThrLow; - int32_t rssiThrHigh; - u32 noiseFloor; - u32 txFrameCount; - u32 rxFrameCount; - u32 cycleCount; - u32 ofdmPhyErrCount; - u32 cckPhyErrCount; - u32 ofdmPhyErrBase; - u32 cckPhyErrBase; - int16_t pktRssi[2]; - int16_t ofdmErrRssi[2]; - int16_t cckErrRssi[2]; -}; - -struct ar5416Stats { - u32 ast_ani_niup; - u32 ast_ani_nidown; - u32 ast_ani_spurup; - u32 ast_ani_spurdown; - u32 ast_ani_ofdmon; - u32 ast_ani_ofdmoff; - u32 ast_ani_cckhigh; - u32 ast_ani_ccklow; - u32 ast_ani_stepup; - u32 ast_ani_stepdown; - u32 ast_ani_ofdmerrs; - u32 ast_ani_cckerrs; - u32 ast_ani_reset; - u32 ast_ani_lzero; - u32 ast_ani_lneg; - u32 avgbrssi; - struct ath9k_mib_stats ast_mibstats; -}; -#define ah_mibStats stats.ast_mibstats - -void ath9k_ani_reset(struct ath_hw *ah); -void ath9k_hw_ani_monitor(struct ath_hw *ah, - struct ath9k_channel *chan); -void ath9k_enable_mib_counters(struct ath_hw *ah); -void ath9k_hw_disable_mib_counters(struct ath_hw *ah); -u32 ath9k_hw_GetMibCycleCountsPct(struct ath_hw *ah, u32 *rxc_pcnt, - u32 *rxf_pcnt, u32 *txf_pcnt); -void ath9k_hw_procmibevent(struct ath_hw *ah); -void ath9k_hw_ani_setup(struct ath_hw *ah); -void ath9k_hw_ani_init(struct ath_hw *ah); -void ath9k_hw_ani_disable(struct ath_hw *ah); - -#endif /* ANI_H */ diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h deleted file mode 100644 index ad1196946c43..000000000000 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ /dev/null @@ -1,717 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef ATH9K_H -#define ATH9K_H - -#include -#include -#include -#include - -#include "hw.h" -#include "rc.h" -#include "debug.h" -#include "../ath.h" -#include "btcoex.h" - -struct ath_node; - -/* Macro to expand scalars to 64-bit objects */ - -#define ito64(x) (sizeof(x) == 8) ? \ - (((unsigned long long int)(x)) & (0xff)) : \ - (sizeof(x) == 16) ? \ - (((unsigned long long int)(x)) & 0xffff) : \ - ((sizeof(x) == 32) ? \ - (((unsigned long long int)(x)) & 0xffffffff) : \ - (unsigned long long int)(x)) - -/* increment with wrap-around */ -#define INCR(_l, _sz) do { \ - (_l)++; \ - (_l) &= ((_sz) - 1); \ - } while (0) - -/* decrement with wrap-around */ -#define DECR(_l, _sz) do { \ - (_l)--; \ - (_l) &= ((_sz) - 1); \ - } while (0) - -#define A_MAX(a, b) ((a) > (b) ? (a) : (b)) - -#define ASSERT(exp) BUG_ON(!(exp)) - -#define TSF_TO_TU(_h,_l) \ - ((((u32)(_h)) << 22) | (((u32)(_l)) >> 10)) - -#define ATH_TXQ_SETUP(sc, i) ((sc)->tx.txqsetup & (1<bf_stale = false; \ - (_bf)->bf_lastbf = NULL; \ - (_bf)->bf_next = NULL; \ - memset(&((_bf)->bf_state), 0, \ - sizeof(struct ath_buf_state)); \ - } while (0) - -#define ATH_RXBUF_RESET(_bf) do { \ - (_bf)->bf_stale = false; \ - } while (0) - -/** - * enum buffer_type - Buffer type flags - * - * @BUF_HT: Send this buffer using HT capabilities - * @BUF_AMPDU: This buffer is an ampdu, as part of an aggregate (during TX) - * @BUF_AGGR: Indicates whether the buffer can be aggregated - * (used in aggregation scheduling) - * @BUF_RETRY: Indicates whether the buffer is retried - * @BUF_XRETRY: To denote excessive retries of the buffer - */ -enum buffer_type { - BUF_HT = BIT(1), - BUF_AMPDU = BIT(2), - BUF_AGGR = BIT(3), - BUF_RETRY = BIT(4), - BUF_XRETRY = BIT(5), -}; - -struct ath_buf_state { - int bfs_nframes; - u16 bfs_al; - u16 bfs_frmlen; - int bfs_seqno; - int bfs_tidno; - int bfs_retries; - u8 bf_type; - u32 bfs_keyix; - enum ath9k_key_type bfs_keytype; -}; - -#define bf_nframes bf_state.bfs_nframes -#define bf_al bf_state.bfs_al -#define bf_frmlen bf_state.bfs_frmlen -#define bf_retries bf_state.bfs_retries -#define bf_seqno bf_state.bfs_seqno -#define bf_tidno bf_state.bfs_tidno -#define bf_keyix bf_state.bfs_keyix -#define bf_keytype bf_state.bfs_keytype -#define bf_isht(bf) (bf->bf_state.bf_type & BUF_HT) -#define bf_isampdu(bf) (bf->bf_state.bf_type & BUF_AMPDU) -#define bf_isaggr(bf) (bf->bf_state.bf_type & BUF_AGGR) -#define bf_isretried(bf) (bf->bf_state.bf_type & BUF_RETRY) -#define bf_isxretried(bf) (bf->bf_state.bf_type & BUF_XRETRY) - -struct ath_buf { - struct list_head list; - struct ath_buf *bf_lastbf; /* last buf of this unit (a frame or - an aggregate) */ - struct ath_buf *bf_next; /* next subframe in the aggregate */ - struct sk_buff *bf_mpdu; /* enclosing frame structure */ - struct ath_desc *bf_desc; /* virtual addr of desc */ - dma_addr_t bf_daddr; /* physical addr of desc */ - dma_addr_t bf_buf_addr; /* physical addr of data buffer */ - bool bf_stale; - bool bf_isnullfunc; - u16 bf_flags; - struct ath_buf_state bf_state; - dma_addr_t bf_dmacontext; -}; - -struct ath_descdma { - struct ath_desc *dd_desc; - dma_addr_t dd_desc_paddr; - u32 dd_desc_len; - struct ath_buf *dd_bufptr; -}; - -int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head, const char *name, - int nbuf, int ndesc); -void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head); - -/***********/ -/* RX / TX */ -/***********/ - -#define ATH_MAX_ANTENNA 3 -#define ATH_RXBUF 512 -#define WME_NUM_TID 16 -#define ATH_TXBUF 512 -#define ATH_TXMAXTRY 13 -#define ATH_MGT_TXMAXTRY 4 -#define WME_BA_BMP_SIZE 64 -#define WME_MAX_BA WME_BA_BMP_SIZE -#define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) - -#define TID_TO_WME_AC(_tid) \ - ((((_tid) == 0) || ((_tid) == 3)) ? WME_AC_BE : \ - (((_tid) == 1) || ((_tid) == 2)) ? WME_AC_BK : \ - (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI : \ - WME_AC_VO) - -#define WME_AC_BE 0 -#define WME_AC_BK 1 -#define WME_AC_VI 2 -#define WME_AC_VO 3 -#define WME_NUM_AC 4 - -#define ADDBA_EXCHANGE_ATTEMPTS 10 -#define ATH_AGGR_DELIM_SZ 4 -#define ATH_AGGR_MINPLEN 256 /* in bytes, minimum packet length */ -/* number of delimiters for encryption padding */ -#define ATH_AGGR_ENCRYPTDELIM 10 -/* minimum h/w qdepth to be sustained to maximize aggregation */ -#define ATH_AGGR_MIN_QDEPTH 2 -#define ATH_AMPDU_SUBFRAME_DEFAULT 32 -#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1) - -#define IEEE80211_SEQ_SEQ_SHIFT 4 -#define IEEE80211_SEQ_MAX 4096 -#define IEEE80211_WEP_IVLEN 3 -#define IEEE80211_WEP_KIDLEN 1 -#define IEEE80211_WEP_CRCLEN 4 -#define IEEE80211_MAX_MPDU_LEN (3840 + FCS_LEN + \ - (IEEE80211_WEP_IVLEN + \ - IEEE80211_WEP_KIDLEN + \ - IEEE80211_WEP_CRCLEN)) - -/* return whether a bit at index _n in bitmap _bm is set - * _sz is the size of the bitmap */ -#define ATH_BA_ISSET(_bm, _n) (((_n) < (WME_BA_BMP_SIZE)) && \ - ((_bm)[(_n) >> 5] & (1 << ((_n) & 31)))) - -/* return block-ack bitmap index given sequence and starting sequence */ -#define ATH_BA_INDEX(_st, _seq) (((_seq) - (_st)) & (IEEE80211_SEQ_MAX - 1)) - -/* returns delimiter padding required given the packet length */ -#define ATH_AGGR_GET_NDELIM(_len) \ - (((((_len) + ATH_AGGR_DELIM_SZ) < ATH_AGGR_MINPLEN) ? \ - (ATH_AGGR_MINPLEN - (_len) - ATH_AGGR_DELIM_SZ) : 0) >> 2) - -#define BAW_WITHIN(_start, _bawsz, _seqno) \ - ((((_seqno) - (_start)) & 4095) < (_bawsz)) - -#define ATH_DS_BA_SEQ(_ds) ((_ds)->ds_us.tx.ts_seqnum) -#define ATH_DS_BA_BITMAP(_ds) (&(_ds)->ds_us.tx.ba_low) -#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) -#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) - -#define ATH_TX_COMPLETE_POLL_INT 1000 - -enum ATH_AGGR_STATUS { - ATH_AGGR_DONE, - ATH_AGGR_BAW_CLOSED, - ATH_AGGR_LIMITED, -}; - -struct ath_txq { - u32 axq_qnum; - u32 *axq_link; - struct list_head axq_q; - spinlock_t axq_lock; - u32 axq_depth; - u8 axq_aggr_depth; - bool stopped; - bool axq_tx_inprogress; - struct ath_buf *axq_linkbuf; - - /* first desc of the last descriptor that contains CTS */ - struct ath_desc *axq_lastdsWithCTS; - - /* final desc of the gating desc that determines whether - lastdsWithCTS has been DMA'ed or not */ - struct ath_desc *axq_gatingds; - - struct list_head axq_acq; -}; - -#define AGGR_CLEANUP BIT(1) -#define AGGR_ADDBA_COMPLETE BIT(2) -#define AGGR_ADDBA_PROGRESS BIT(3) - -struct ath_atx_tid { - struct list_head list; - struct list_head buf_q; - struct ath_node *an; - struct ath_atx_ac *ac; - struct ath_buf *tx_buf[ATH_TID_MAX_BUFS]; - u16 seq_start; - u16 seq_next; - u16 baw_size; - int tidno; - int baw_head; /* first un-acked tx buffer */ - int baw_tail; /* next unused tx buffer slot */ - int sched; - int paused; - u8 state; -}; - -struct ath_atx_ac { - int sched; - int qnum; - struct list_head list; - struct list_head tid_q; -}; - -struct ath_tx_control { - struct ath_txq *txq; - int if_id; - enum ath9k_internal_frame_type frame_type; -}; - -#define ATH_TX_ERROR 0x01 -#define ATH_TX_XRETRY 0x02 -#define ATH_TX_BAR 0x04 - -#define ATH_RSSI_LPF_LEN 10 -#define RSSI_LPF_THRESHOLD -20 -#define ATH9K_RSSI_BAD 0x80 -#define ATH_RSSI_EP_MULTIPLIER (1<<7) -#define ATH_EP_MUL(x, mul) ((x) * (mul)) -#define ATH_RSSI_IN(x) (ATH_EP_MUL((x), ATH_RSSI_EP_MULTIPLIER)) -#define ATH_LPF_RSSI(x, y, len) \ - ((x != ATH_RSSI_DUMMY_MARKER) ? (((x) * ((len) - 1) + (y)) / (len)) : (y)) -#define ATH_RSSI_LPF(x, y) do { \ - if ((y) >= RSSI_LPF_THRESHOLD) \ - x = ATH_LPF_RSSI((x), ATH_RSSI_IN((y)), ATH_RSSI_LPF_LEN); \ -} while (0) -#define ATH_EP_RND(x, mul) \ - ((((x)%(mul)) >= ((mul)/2)) ? ((x) + ((mul) - 1)) / (mul) : (x)/(mul)) - -struct ath_node { - struct ath_softc *an_sc; - struct ath_atx_tid tid[WME_NUM_TID]; - struct ath_atx_ac ac[WME_NUM_AC]; - u16 maxampdu; - u8 mpdudensity; - int last_rssi; -}; - -struct ath_tx { - u16 seq_no; - u32 txqsetup; - int hwq_map[ATH9K_WME_AC_VO+1]; - spinlock_t txbuflock; - struct list_head txbuf; - struct ath_txq txq[ATH9K_NUM_TX_QUEUES]; - struct ath_descdma txdma; -}; - -struct ath_rx { - u8 defant; - u8 rxotherant; - u32 *rxlink; - int bufsize; - unsigned int rxfilter; - spinlock_t rxflushlock; - spinlock_t rxbuflock; - struct list_head rxbuf; - struct ath_descdma rxdma; -}; - -int ath_startrecv(struct ath_softc *sc); -bool ath_stoprecv(struct ath_softc *sc); -void ath_flushrecv(struct ath_softc *sc); -u32 ath_calcrxfilter(struct ath_softc *sc); -int ath_rx_init(struct ath_softc *sc, int nbufs); -void ath_rx_cleanup(struct ath_softc *sc); -int ath_rx_tasklet(struct ath_softc *sc, int flush); -struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype); -void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq); -int ath_tx_setup(struct ath_softc *sc, int haltype); -void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx); -void ath_draintxq(struct ath_softc *sc, - struct ath_txq *txq, bool retry_tx); -void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); -void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); -void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); -int ath_tx_init(struct ath_softc *sc, int nbufs); -void ath_tx_cleanup(struct ath_softc *sc); -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb); -int ath_txq_update(struct ath_softc *sc, int qnum, - struct ath9k_tx_queue_info *q); -int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath_tx_control *txctl); -void ath_tx_tasklet(struct ath_softc *sc); -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb); -bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno); -void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, - u16 tid, u16 *ssn); -void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); -void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid); -void ath9k_enable_ps(struct ath_softc *sc); - -/********/ -/* VIFs */ -/********/ - -struct ath_vif { - int av_bslot; - __le64 tsf_adjust; /* TSF adjustment for staggered beacons */ - enum nl80211_iftype av_opmode; - struct ath_buf *av_bcbuf; - struct ath_tx_control av_btxctl; - u8 bssid[ETH_ALEN]; /* current BSSID from config_interface */ -}; - -/*******************/ -/* Beacon Handling */ -/*******************/ - -/* - * Regardless of the number of beacons we stagger, (i.e. regardless of the - * number of BSSIDs) if a given beacon does not go out even after waiting this - * number of beacon intervals, the game's up. - */ -#define BSTUCK_THRESH (9 * ATH_BCBUF) -#define ATH_BCBUF 4 -#define ATH_DEFAULT_BINTVAL 100 /* TU */ -#define ATH_DEFAULT_BMISS_LIMIT 10 -#define IEEE80211_MS_TO_TU(x) (((x) * 1000) / 1024) - -struct ath_beacon_config { - u16 beacon_interval; - u16 listen_interval; - u16 dtim_period; - u16 bmiss_timeout; - u8 dtim_count; -}; - -struct ath_beacon { - enum { - OK, /* no change needed */ - UPDATE, /* update pending */ - COMMIT /* beacon sent, commit change */ - } updateslot; /* slot time update fsm */ - - u32 beaconq; - u32 bmisscnt; - u32 ast_be_xmit; - u64 bc_tstamp; - struct ieee80211_vif *bslot[ATH_BCBUF]; - struct ath_wiphy *bslot_aphy[ATH_BCBUF]; - int slottime; - int slotupdate; - struct ath9k_tx_queue_info beacon_qi; - struct ath_descdma bdma; - struct ath_txq *cabq; - struct list_head bbuf; -}; - -void ath_beacon_tasklet(unsigned long data); -void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); -int ath_beaconq_setup(struct ath_hw *ah); -int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); -void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); - -/*******/ -/* ANI */ -/*******/ - -#define ATH_STA_SHORT_CALINTERVAL 1000 /* 1 second */ -#define ATH_AP_SHORT_CALINTERVAL 100 /* 100 ms */ -#define ATH_ANI_POLLINTERVAL 100 /* 100 ms */ -#define ATH_LONG_CALINTERVAL 30000 /* 30 seconds */ -#define ATH_RESTART_CALINTERVAL 1200000 /* 20 minutes */ - -struct ath_ani { - bool caldone; - int16_t noise_floor; - unsigned int longcal_timer; - unsigned int shortcal_timer; - unsigned int resetcal_timer; - unsigned int checkani_timer; - struct timer_list timer; -}; - -/********************/ -/* LED Control */ -/********************/ - -#define ATH_LED_PIN_DEF 1 -#define ATH_LED_PIN_9287 8 -#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */ -#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */ - -enum ath_led_type { - ATH_LED_RADIO, - ATH_LED_ASSOC, - ATH_LED_TX, - ATH_LED_RX -}; - -struct ath_led { - struct ath_softc *sc; - struct led_classdev led_cdev; - enum ath_led_type led_type; - char name[32]; - bool registered; -}; - -/********************/ -/* Main driver core */ -/********************/ - -/* - * Default cache line size, in bytes. - * Used when PCI device not fully initialized by bootrom/BIOS -*/ -#define DEFAULT_CACHELINE 32 -#define ATH_DEFAULT_NOISE_FLOOR -95 -#define ATH_REGCLASSIDS_MAX 10 -#define ATH_CABQ_READY_TIME 80 /* % of beacon interval */ -#define ATH_MAX_SW_RETRIES 10 -#define ATH_CHAN_MAX 255 -#define IEEE80211_WEP_NKID 4 /* number of key ids */ - -/* - * The key cache is used for h/w cipher state and also for - * tracking station state such as the current tx antenna. - * We also setup a mapping table between key cache slot indices - * and station state to short-circuit node lookups on rx. - * Different parts have different size key caches. We handle - * up to ATH_KEYMAX entries (could dynamically allocate state). - */ -#define ATH_KEYMAX 128 /* max key cache size we handle */ - -#define ATH_TXPOWER_MAX 100 /* .5 dBm units */ -#define ATH_RSSI_DUMMY_MARKER 0x127 -#define ATH_RATE_DUMMY_MARKER 0 - -#define SC_OP_INVALID BIT(0) -#define SC_OP_BEACONS BIT(1) -#define SC_OP_RXAGGR BIT(2) -#define SC_OP_TXAGGR BIT(3) -#define SC_OP_FULL_RESET BIT(4) -#define SC_OP_PREAMBLE_SHORT BIT(5) -#define SC_OP_PROTECT_ENABLE BIT(6) -#define SC_OP_RXFLUSH BIT(7) -#define SC_OP_LED_ASSOCIATED BIT(8) -#define SC_OP_WAIT_FOR_BEACON BIT(12) -#define SC_OP_LED_ON BIT(13) -#define SC_OP_SCANNING BIT(14) -#define SC_OP_TSF_RESET BIT(15) -#define SC_OP_WAIT_FOR_CAB BIT(16) -#define SC_OP_WAIT_FOR_PSPOLL_DATA BIT(17) -#define SC_OP_WAIT_FOR_TX_ACK BIT(18) -#define SC_OP_BEACON_SYNC BIT(19) -#define SC_OP_BTCOEX_ENABLED BIT(20) -#define SC_OP_BT_PRIORITY_DETECTED BIT(21) -#define SC_OP_NULLFUNC_COMPLETED BIT(22) -#define SC_OP_PS_ENABLED BIT(23) - -struct ath_bus_ops { - void (*read_cachesize)(struct ath_softc *sc, int *csz); - void (*cleanup)(struct ath_softc *sc); - bool (*eeprom_read)(struct ath_hw *ah, u32 off, u16 *data); -}; - -struct ath_wiphy; - -struct ath_softc { - struct ieee80211_hw *hw; - struct device *dev; - - struct ath_common common; - - spinlock_t wiphy_lock; /* spinlock to protect ath_wiphy data */ - struct ath_wiphy *pri_wiphy; - struct ath_wiphy **sec_wiphy; /* secondary wiphys (virtual radios); may - * have NULL entries */ - int num_sec_wiphy; /* number of sec_wiphy pointers in the array */ - int chan_idx; - int chan_is_ht; - struct ath_wiphy *next_wiphy; - struct work_struct chan_work; - int wiphy_select_failures; - unsigned long wiphy_select_first_fail; - struct delayed_work wiphy_work; - unsigned long wiphy_scheduler_int; - int wiphy_scheduler_index; - - struct tasklet_struct intr_tq; - struct tasklet_struct bcon_tasklet; - struct ath_hw *sc_ah; - void __iomem *mem; - int irq; - spinlock_t sc_resetlock; - spinlock_t sc_serial_rw; - spinlock_t ani_lock; - spinlock_t sc_pm_lock; - struct mutex mutex; - - u8 curbssid[ETH_ALEN]; - u8 bssidmask[ETH_ALEN]; - u32 intrstatus; - u32 sc_flags; /* SC_OP_* */ - u16 curtxpow; - u16 curaid; - u8 nbcnvifs; - u16 nvifs; - u8 tx_chainmask; - u8 rx_chainmask; - u32 keymax; - DECLARE_BITMAP(keymap, ATH_KEYMAX); - u8 splitmic; - bool ps_enabled; - unsigned long ps_usecount; - enum ath9k_int imask; - enum ath9k_ht_extprotspacing ht_extprotspacing; - enum ath9k_ht_macmode tx_chan_width; - - struct ath_config config; - struct ath_rx rx; - struct ath_tx tx; - struct ath_beacon beacon; - struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX]; - const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX]; - const struct ath_rate_table *cur_rate_table; - struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; - - struct ath_led radio_led; - struct ath_led assoc_led; - struct ath_led tx_led; - struct ath_led rx_led; - struct delayed_work ath_led_blink_work; - int led_on_duration; - int led_off_duration; - int led_on_cnt; - int led_off_cnt; - - int beacon_interval; - - struct ath_ani ani; -#ifdef CONFIG_ATH9K_DEBUG - struct ath9k_debug debug; -#endif - struct ath_bus_ops *bus_ops; - struct ath_beacon_config cur_beacon_conf; - struct delayed_work tx_complete_work; - struct ath_btcoex_info btcoex_info; -}; - -struct ath_wiphy { - struct ath_softc *sc; /* shared for all virtual wiphys */ - struct ieee80211_hw *hw; - enum ath_wiphy_state { - ATH_WIPHY_INACTIVE, - ATH_WIPHY_ACTIVE, - ATH_WIPHY_PAUSING, - ATH_WIPHY_PAUSED, - ATH_WIPHY_SCAN, - } state; - int chan_idx; - int chan_is_ht; -}; - -int ath_reset(struct ath_softc *sc, bool retry_tx); -int ath_get_hal_qnum(u16 queue, struct ath_softc *sc); -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc); -int ath_cabq_update(struct ath_softc *); - -static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah) -{ - return &ah->ah_sc->common; -} - -static inline struct ath_regulatory *ath9k_hw_regulatory(struct ath_hw *ah) -{ - return &(ath9k_hw_common(ah)->regulatory); -} - -static inline void ath_read_cachesize(struct ath_softc *sc, int *csz) -{ - sc->bus_ops->read_cachesize(sc, csz); -} - -static inline void ath_bus_cleanup(struct ath_softc *sc) -{ - sc->bus_ops->cleanup(sc); -} - -extern struct ieee80211_ops ath9k_ops; - -irqreturn_t ath_isr(int irq, void *dev); -void ath_cleanup(struct ath_softc *sc); -int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid); -void ath_detach(struct ath_softc *sc); -const char *ath_mac_bb_name(u32 mac_bb_version); -const char *ath_rf_name(u16 rf_version); -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); -void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *ichan); -void ath_update_chainmask(struct ath_softc *sc, int is_ht); -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *hchan); -void ath_radio_enable(struct ath_softc *sc); -void ath_radio_disable(struct ath_softc *sc); - -#ifdef CONFIG_PCI -int ath_pci_init(void); -void ath_pci_exit(void); -#else -static inline int ath_pci_init(void) { return 0; }; -static inline void ath_pci_exit(void) {}; -#endif - -#ifdef CONFIG_ATHEROS_AR71XX -int ath_ahb_init(void); -void ath_ahb_exit(void); -#else -static inline int ath_ahb_init(void) { return 0; }; -static inline void ath_ahb_exit(void) {}; -#endif - -void ath9k_ps_wakeup(struct ath_softc *sc); -void ath9k_ps_restore(struct ath_softc *sc); - -void ath9k_set_bssid_mask(struct ieee80211_hw *hw); -int ath9k_wiphy_add(struct ath_softc *sc); -int ath9k_wiphy_del(struct ath_wiphy *aphy); -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb); -int ath9k_wiphy_pause(struct ath_wiphy *aphy); -int ath9k_wiphy_unpause(struct ath_wiphy *aphy); -int ath9k_wiphy_select(struct ath_wiphy *aphy); -void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int); -void ath9k_wiphy_chan_work(struct work_struct *work); -bool ath9k_wiphy_started(struct ath_softc *sc); -void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, - struct ath_wiphy *selected); -bool ath9k_wiphy_scanning(struct ath_softc *sc); -void ath9k_wiphy_work(struct work_struct *work); -bool ath9k_all_wiphys_idle(struct ath_softc *sc); - -void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val); -unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset); - -int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype); -#endif /* ATH9K_H */ diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c deleted file mode 100644 index 72e24559ec4b..000000000000 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -#define FUDGE 2 - -/* - * This function will modify certain transmit queue properties depending on - * the operating mode of the station (AP or AdHoc). Parameters are AIFS - * settings and channel width min/max -*/ -static int ath_beaconq_config(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_tx_queue_info qi; - - ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { - /* Always burst out beacon and CAB traffic. */ - qi.tqi_aifs = 1; - qi.tqi_cwmin = 0; - qi.tqi_cwmax = 0; - } else { - /* Adhoc mode; important thing is to use 2x cwmin. */ - qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs; - qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin; - qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax; - } - - if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to update h/w beacon queue parameters\n"); - return 0; - } else { - ath9k_hw_resettxqueue(ah, sc->beacon.beaconq); - return 1; - } -} - -/* - * Associates the beacon frame buffer with a transmit descriptor. Will set - * up all required antenna switch parameters, rate codes, and channel flags. - * Beacons are always sent out at the lowest rate, and are not retried. -*/ -static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, - struct ath_buf *bf) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ath_hw *ah = sc->sc_ah; - struct ath_desc *ds; - struct ath9k_11n_rate_series series[4]; - const struct ath_rate_table *rt; - int flags, antenna, ctsrate = 0, ctsduration = 0; - u8 rate; - - ds = bf->bf_desc; - flags = ATH9K_TXDESC_NOACK; - - if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) && - (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { - ds->ds_link = bf->bf_daddr; /* self-linked */ - flags |= ATH9K_TXDESC_VEOL; - /* Let hardware handle antenna switching. */ - antenna = 0; - } else { - ds->ds_link = 0; - /* - * Switch antenna every beacon. - * Should only switch every beacon period, not for every SWBA - * XXX assumes two antennae - */ - antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); - } - - ds->ds_data = bf->bf_buf_addr; - - rt = sc->cur_rate_table; - rate = rt->info[0].ratecode; - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - rate |= rt->info[0].short_preamble; - - ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, - ATH9K_PKT_TYPE_BEACON, - MAX_RATE_POWER, - ATH9K_TXKEYIX_INVALID, - ATH9K_KEY_TYPE_CLEAR, - flags); - - /* NB: beacon's BufLen must be a multiple of 4 bytes */ - ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), - true, true, ds); - - memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - series[0].Tries = 1; - series[0].Rate = rate; - series[0].ChSel = sc->tx_chainmask; - series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; - ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, - series, 4, 0); -} - -static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_buf *bf; - struct ath_vif *avp; - struct sk_buff *skb; - struct ath_txq *cabq; - struct ieee80211_tx_info *info; - int cabq_depth; - - if (aphy->state != ATH_WIPHY_ACTIVE) - return NULL; - - avp = (void *)vif->drv_priv; - cabq = sc->beacon.cabq; - - if (avp->av_bcbuf == NULL) - return NULL; - - /* Release the old beacon first */ - - bf = avp->av_bcbuf; - skb = bf->bf_mpdu; - if (skb) { - dma_unmap_single(sc->dev, bf->bf_dmacontext, - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - } - - /* Get a new beacon from mac80211 */ - - skb = ieee80211_beacon_get(hw, vif); - bf->bf_mpdu = skb; - if (skb == NULL) - return NULL; - ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = - avp->tsf_adjust; - - info = IEEE80211_SKB_CB(skb); - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - /* - * TODO: make sure the seq# gets assigned properly (vs. other - * TX frames) - */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - bf->bf_buf_addr = bf->bf_dmacontext = - dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n"); - return NULL; - } - - skb = ieee80211_get_buffered_bc(hw, vif); - - /* - * if the CABQ traffic from previous DTIM is pending and the current - * beacon is also a DTIM. - * 1) if there is only one vif let the cab traffic continue. - * 2) if there are more than one vif and we are using staggered - * beacons, then drain the cabq by dropping all the frames in - * the cabq so that the current vifs cab traffic can be scheduled. - */ - spin_lock_bh(&cabq->axq_lock); - cabq_depth = cabq->axq_depth; - spin_unlock_bh(&cabq->axq_lock); - - if (skb && cabq_depth) { - if (sc->nvifs > 1) { - DPRINTF(sc, ATH_DBG_BEACON, - "Flushing previous cabq traffic\n"); - ath_draintxq(sc, cabq, false); - } - } - - ath_beacon_setup(sc, avp, bf); - - while (skb) { - ath_tx_cabq(hw, skb); - skb = ieee80211_get_buffered_bc(hw, vif); - } - - return bf; -} - -/* - * Startup beacon transmission for adhoc mode when they are sent entirely - * by the hardware using the self-linked descriptor + veol trick. -*/ -static void ath_beacon_start_adhoc(struct ath_softc *sc, - struct ieee80211_vif *vif) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf; - struct ath_vif *avp; - struct sk_buff *skb; - - avp = (void *)vif->drv_priv; - - if (avp->av_bcbuf == NULL) - return; - - bf = avp->av_bcbuf; - skb = bf->bf_mpdu; - - ath_beacon_setup(sc, avp, bf); - - /* NB: caller is known to have already stopped tx dma */ - ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr); - ath9k_hw_txstart(ah, sc->beacon.beaconq); - DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n", - sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc); -} - -int ath_beaconq_setup(struct ath_hw *ah) -{ - struct ath9k_tx_queue_info qi; - - memset(&qi, 0, sizeof(qi)); - qi.tqi_aifs = 1; - qi.tqi_cwmin = 0; - qi.tqi_cwmax = 0; - /* NB: don't enable any interrupts */ - return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi); -} - -int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif) -{ - struct ath_softc *sc = aphy->sc; - struct ath_vif *avp; - struct ath_buf *bf; - struct sk_buff *skb; - __le64 tstamp; - - avp = (void *)vif->drv_priv; - - /* Allocate a beacon descriptor if we haven't done so. */ - if (!avp->av_bcbuf) { - /* Allocate beacon state for hostap/ibss. We know - * a buffer is available. */ - avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf, - struct ath_buf, list); - list_del(&avp->av_bcbuf->list); - - if (sc->sc_ah->opmode == NL80211_IFTYPE_AP || - !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) { - int slot; - /* - * Assign the vif to a beacon xmit slot. As - * above, this cannot fail to find one. - */ - avp->av_bslot = 0; - for (slot = 0; slot < ATH_BCBUF; slot++) - if (sc->beacon.bslot[slot] == NULL) { - /* - * XXX hack, space out slots to better - * deal with misses - */ - if (slot+1 < ATH_BCBUF && - sc->beacon.bslot[slot+1] == NULL) { - avp->av_bslot = slot+1; - break; - } - avp->av_bslot = slot; - /* NB: keep looking for a double slot */ - } - BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL); - sc->beacon.bslot[avp->av_bslot] = vif; - sc->beacon.bslot_aphy[avp->av_bslot] = aphy; - sc->nbcnvifs++; - } - } - - /* release the previous beacon frame, if it already exists. */ - bf = avp->av_bcbuf; - if (bf->bf_mpdu != NULL) { - skb = bf->bf_mpdu; - dma_unmap_single(sc->dev, bf->bf_dmacontext, - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - } - - /* NB: the beacon data buffer must be 32-bit aligned. */ - skb = ieee80211_beacon_get(sc->hw, vif); - if (skb == NULL) { - DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n"); - return -ENOMEM; - } - - tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - sc->beacon.bc_tstamp = le64_to_cpu(tstamp); - /* Calculate a TSF adjustment factor required for staggered beacons. */ - if (avp->av_bslot > 0) { - u64 tsfadjust; - int intval; - - intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; - - /* - * Calculate the TSF offset for this beacon slot, i.e., the - * number of usecs that need to be added to the timestamp field - * in Beacon and Probe Response frames. Beacon slot 0 is - * processed at the correct offset, so it does not require TSF - * adjustment. Other slots are adjusted to get the timestamp - * close to the TBTT for the BSS. - */ - tsfadjust = intval * avp->av_bslot / ATH_BCBUF; - avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust)); - - DPRINTF(sc, ATH_DBG_BEACON, - "stagger beacons, bslot %d intval %u tsfadjust %llu\n", - avp->av_bslot, intval, (unsigned long long)tsfadjust); - - ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp = - avp->tsf_adjust; - } else - avp->tsf_adjust = cpu_to_le64(0); - - bf->bf_mpdu = skb; - bf->bf_buf_addr = bf->bf_dmacontext = - dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error on beacon alloc\n"); - return -ENOMEM; - } - - return 0; -} - -void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp) -{ - if (avp->av_bcbuf != NULL) { - struct ath_buf *bf; - - if (avp->av_bslot != -1) { - sc->beacon.bslot[avp->av_bslot] = NULL; - sc->beacon.bslot_aphy[avp->av_bslot] = NULL; - sc->nbcnvifs--; - } - - bf = avp->av_bcbuf; - if (bf->bf_mpdu != NULL) { - struct sk_buff *skb = bf->bf_mpdu; - dma_unmap_single(sc->dev, bf->bf_dmacontext, - skb->len, DMA_TO_DEVICE); - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - } - list_add_tail(&bf->list, &sc->beacon.bbuf); - - avp->av_bcbuf = NULL; - } -} - -void ath_beacon_tasklet(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf = NULL; - struct ieee80211_vif *vif; - struct ath_wiphy *aphy; - int slot; - u32 bfaddr, bc = 0, tsftu; - u64 tsf; - u16 intval; - - /* - * Check if the previous beacon has gone out. If - * not don't try to post another, skip this period - * and wait for the next. Missed beacons indicate - * a problem and should not occur. If we miss too - * many consecutive beacons reset the device. - */ - if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) { - sc->beacon.bmisscnt++; - - if (sc->beacon.bmisscnt < BSTUCK_THRESH) { - DPRINTF(sc, ATH_DBG_BEACON, - "missed %u consecutive beacons\n", - sc->beacon.bmisscnt); - } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { - DPRINTF(sc, ATH_DBG_BEACON, - "beacon is officially stuck\n"); - sc->sc_flags |= SC_OP_TSF_RESET; - ath_reset(sc, false); - } - - return; - } - - if (sc->beacon.bmisscnt != 0) { - DPRINTF(sc, ATH_DBG_BEACON, - "resume beacon xmit after %u misses\n", - sc->beacon.bmisscnt); - sc->beacon.bmisscnt = 0; - } - - /* - * Generate beacon frames. we are sending frames - * staggered so calculate the slot for this frame based - * on the tsf to safeguard against missing an swba. - */ - - intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL; - - tsf = ath9k_hw_gettsf64(ah); - tsftu = TSF_TO_TU(tsf>>32, tsf); - slot = ((tsftu % intval) * ATH_BCBUF) / intval; - /* - * Reverse the slot order to get slot 0 on the TBTT offset that does - * not require TSF adjustment and other slots adding - * slot/ATH_BCBUF * beacon_int to timestamp. For example, with - * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. - * and slot 0 is at correct offset to TBTT. - */ - slot = ATH_BCBUF - slot - 1; - vif = sc->beacon.bslot[slot]; - aphy = sc->beacon.bslot_aphy[slot]; - - DPRINTF(sc, ATH_DBG_BEACON, - "slot %d [tsf %llu tsftu %u intval %u] vif %p\n", - slot, tsf, tsftu, intval, vif); - - bfaddr = 0; - if (vif) { - bf = ath_beacon_generate(aphy->hw, vif); - if (bf != NULL) { - bfaddr = bf->bf_daddr; - bc = 1; - } - } - - /* - * Handle slot time change when a non-ERP station joins/leaves - * an 11g network. The 802.11 layer notifies us via callback, - * we mark updateslot, then wait one beacon before effecting - * the change. This gives associated stations at least one - * beacon interval to note the state change. - * - * NB: The slot time change state machine is clocked according - * to whether we are bursting or staggering beacons. We - * recognize the request to update and record the current - * slot then don't transition until that slot is reached - * again. If we miss a beacon for that slot then we'll be - * slow to transition but we'll be sure at least one beacon - * interval has passed. When bursting slot is always left - * set to ATH_BCBUF so this check is a noop. - */ - if (sc->beacon.updateslot == UPDATE) { - sc->beacon.updateslot = COMMIT; /* commit next beacon */ - sc->beacon.slotupdate = slot; - } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) { - ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime); - sc->beacon.updateslot = OK; - } - if (bfaddr != 0) { - /* - * Stop any current dma and put the new frame(s) on the queue. - * This should never fail since we check above that no frames - * are still pending on the queue. - */ - if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) { - DPRINTF(sc, ATH_DBG_FATAL, - "beacon queue %u did not stop?\n", sc->beacon.beaconq); - } - - /* NB: cabq traffic should already be queued and primed */ - ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); - ath9k_hw_txstart(ah, sc->beacon.beaconq); - - sc->beacon.ast_be_xmit += bc; /* XXX per-vif? */ - } -} - -/* - * For multi-bss ap support beacons are either staggered evenly over N slots or - * burst together. For the former arrange for the SWBA to be delivered for each - * slot. Slots that are not occupied will generate nothing. - */ -static void ath_beacon_config_ap(struct ath_softc *sc, - struct ath_beacon_config *conf) -{ - u32 nexttbtt, intval; - - /* NB: the beacon interval is kept internally in TU's */ - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - intval /= ATH_BCBUF; /* for staggered beacons */ - nexttbtt = intval; - - if (sc->sc_flags & SC_OP_TSF_RESET) - intval |= ATH9K_BEACON_RESET_TSF; - - /* - * In AP mode we enable the beacon timers and SWBA interrupts to - * prepare beacon frames. - */ - intval |= ATH9K_BEACON_ENA; - sc->imask |= ATH9K_INT_SWBA; - ath_beaconq_config(sc); - - /* Set the computed AP beacon timers */ - - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); - sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - /* Clear the reset TSF flag, so that subsequent beacon updation - will not reset the HW TSF. */ - - sc->sc_flags &= ~SC_OP_TSF_RESET; -} - -/* - * This sets up the beacon timers according to the timestamp of the last - * received beacon and the current TSF, configures PCF and DTIM - * handling, programs the sleep registers so the hardware will wakeup in - * time to receive beacons, and configures the beacon miss handling so - * we'll receive a BMISS interrupt when we stop seeing beacons from the AP - * we've associated with. - */ -static void ath_beacon_config_sta(struct ath_softc *sc, - struct ath_beacon_config *conf) -{ - struct ath9k_beacon_state bs; - int dtimperiod, dtimcount, sleepduration; - int cfpperiod, cfpcount; - u32 nexttbtt = 0, intval, tsftu; - u64 tsf; - int num_beacons, offset, dtim_dec_count, cfp_dec_count; - - memset(&bs, 0, sizeof(bs)); - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - - /* - * Setup dtim and cfp parameters according to - * last beacon we received (which may be none). - */ - dtimperiod = conf->dtim_period; - if (dtimperiod <= 0) /* NB: 0 if not known */ - dtimperiod = 1; - dtimcount = conf->dtim_count; - if (dtimcount >= dtimperiod) /* NB: sanity check */ - dtimcount = 0; - cfpperiod = 1; /* NB: no PCF support yet */ - cfpcount = 0; - - sleepduration = conf->listen_interval * intval; - if (sleepduration <= 0) - sleepduration = intval; - - /* - * Pull nexttbtt forward to reflect the current - * TSF and calculate dtim+cfp state for the result. - */ - tsf = ath9k_hw_gettsf64(sc->sc_ah); - tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE; - - num_beacons = tsftu / intval + 1; - offset = tsftu % intval; - nexttbtt = tsftu - offset; - if (offset) - nexttbtt += intval; - - /* DTIM Beacon every dtimperiod Beacon */ - dtim_dec_count = num_beacons % dtimperiod; - /* CFP every cfpperiod DTIM Beacon */ - cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod; - if (dtim_dec_count) - cfp_dec_count++; - - dtimcount -= dtim_dec_count; - if (dtimcount < 0) - dtimcount += dtimperiod; - - cfpcount -= cfp_dec_count; - if (cfpcount < 0) - cfpcount += cfpperiod; - - bs.bs_intval = intval; - bs.bs_nexttbtt = nexttbtt; - bs.bs_dtimperiod = dtimperiod*intval; - bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval; - bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod; - bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod; - bs.bs_cfpmaxduration = 0; - - /* - * Calculate the number of consecutive beacons to miss* before taking - * a BMISS interrupt. The configuration is specified in TU so we only - * need calculate based on the beacon interval. Note that we clamp the - * result to at most 15 beacons. - */ - if (sleepduration > intval) { - bs.bs_bmissthreshold = conf->listen_interval * - ATH_DEFAULT_BMISS_LIMIT / 2; - } else { - bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval); - if (bs.bs_bmissthreshold > 15) - bs.bs_bmissthreshold = 15; - else if (bs.bs_bmissthreshold <= 0) - bs.bs_bmissthreshold = 1; - } - - /* - * Calculate sleep duration. The configuration is given in ms. - * We ensure a multiple of the beacon period is used. Also, if the sleep - * duration is greater than the DTIM period then it makes senses - * to make it a multiple of that. - * - * XXX fixed at 100ms - */ - - bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration); - if (bs.bs_sleepduration > bs.bs_dtimperiod) - bs.bs_sleepduration = bs.bs_dtimperiod; - - /* TSF out of range threshold fixed at 1 second */ - bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD; - - DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu); - DPRINTF(sc, ATH_DBG_BEACON, - "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n", - bs.bs_bmissthreshold, bs.bs_sleepduration, - bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext); - - /* Set the computed STA beacon timers */ - - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs); - sc->imask |= ATH9K_INT_BMISS; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); -} - -static void ath_beacon_config_adhoc(struct ath_softc *sc, - struct ath_beacon_config *conf, - struct ieee80211_vif *vif) -{ - u64 tsf; - u32 tsftu, intval, nexttbtt; - - intval = conf->beacon_interval & ATH9K_BEACON_PERIOD; - - - /* Pull nexttbtt forward to reflect the current TSF */ - - nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp); - if (nexttbtt == 0) - nexttbtt = intval; - else if (intval) - nexttbtt = roundup(nexttbtt, intval); - - tsf = ath9k_hw_gettsf64(sc->sc_ah); - tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE; - do { - nexttbtt += intval; - } while (nexttbtt < tsftu); - - DPRINTF(sc, ATH_DBG_BEACON, - "IBSS nexttbtt %u intval %u (%u)\n", - nexttbtt, intval, conf->beacon_interval); - - /* - * In IBSS mode enable the beacon timers but only enable SWBA interrupts - * if we need to manually prepare beacon frames. Otherwise we use a - * self-linked tx descriptor and let the hardware deal with things. - */ - intval |= ATH9K_BEACON_ENA; - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) - sc->imask |= ATH9K_INT_SWBA; - - ath_beaconq_config(sc); - - /* Set the computed ADHOC beacon timers */ - - ath9k_hw_set_interrupts(sc->sc_ah, 0); - ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval); - sc->beacon.bmisscnt = 0; - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - /* FIXME: Handle properly when vif is NULL */ - if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL) - ath_beacon_start_adhoc(sc, vif); -} - -void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif) -{ - struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf; - enum nl80211_iftype iftype; - - /* Setup the beacon configuration parameters */ - - if (vif) { - struct ieee80211_bss_conf *bss_conf = &vif->bss_conf; - - iftype = vif->type; - - cur_conf->beacon_interval = bss_conf->beacon_int; - cur_conf->dtim_period = bss_conf->dtim_period; - cur_conf->listen_interval = 1; - cur_conf->dtim_count = 1; - cur_conf->bmiss_timeout = - ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval; - } else { - iftype = sc->sc_ah->opmode; - } - - /* - * It looks like mac80211 may end up using beacon interval of zero in - * some cases (at least for mesh point). Avoid getting into an - * infinite loop by using a bit safer value instead. To be safe, - * do sanity check on beacon interval for all operating modes. - */ - if (cur_conf->beacon_interval == 0) - cur_conf->beacon_interval = 100; - - switch (iftype) { - case NL80211_IFTYPE_AP: - ath_beacon_config_ap(sc, cur_conf); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - ath_beacon_config_adhoc(sc, cur_conf, vif); - break; - case NL80211_IFTYPE_STATION: - ath_beacon_config_sta(sc, cur_conf); - break; - default: - DPRINTF(sc, ATH_DBG_CONFIG, - "Unsupported beaconing mode\n"); - return; - } - - sc->sc_flags |= SC_OP_BEACONS; -} diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c deleted file mode 100644 index 55f607b7699e..000000000000 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright (c) 2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static const struct ath_btcoex_config ath_bt_config = { 0, true, true, - ATH_BT_COEX_MODE_SLOTTED, true, true, 2, 5, true }; - -static const u16 ath_subsysid_tbl[] = { - AR9280_COEX2WIRE_SUBSYSID, - AT9285_COEX3WIRE_SA_SUBSYSID, - AT9285_COEX3WIRE_DA_SUBSYSID -}; - -/* - * Checks the subsystem id of the device to see if it - * supports btcoex - */ -bool ath_btcoex_supported(u16 subsysid) -{ - int i; - - if (!subsysid) - return false; - - for (i = 0; i < ARRAY_SIZE(ath_subsysid_tbl); i++) - if (subsysid == ath_subsysid_tbl[i]) - return true; - - return false; -} - -/* - * Detects if there is any priority bt traffic - */ -static void ath_detect_bt_priority(struct ath_softc *sc) -{ - struct ath_btcoex_info *btinfo = &sc->btcoex_info; - - if (ath9k_hw_gpio_get(sc->sc_ah, btinfo->btpriority_gpio)) - btinfo->bt_priority_cnt++; - - if (time_after(jiffies, btinfo->bt_priority_time + - msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) { - if (btinfo->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) { - DPRINTF(sc, ATH_DBG_BTCOEX, - "BT priority traffic detected"); - sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED; - } else { - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; - } - - btinfo->bt_priority_cnt = 0; - btinfo->bt_priority_time = jiffies; - } -} - -/* - * Configures appropriate weight based on stomp type. - */ -static void ath_btcoex_bt_stomp(struct ath_softc *sc, - struct ath_btcoex_info *btinfo, - int stomp_type) -{ - - switch (stomp_type) { - case ATH_BTCOEX_STOMP_ALL: - ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_LOW: - ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - break; - case ATH_BTCOEX_STOMP_NONE: - ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT); - break; - default: - DPRINTF(sc, ATH_DBG_BTCOEX, "Invalid Stomptype\n"); - break; - } - - ath9k_hw_btcoex_enable(sc->sc_ah); -} - -/* - * This is the master bt coex timer which runs for every - * 45ms, bt traffic will be given priority during 55% of this - * period while wlan gets remaining 45% - */ - -static void ath_btcoex_period_timer(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *) data; - struct ath_btcoex_info *btinfo = &sc->btcoex_info; - - ath_detect_bt_priority(sc); - - spin_lock_bh(&btinfo->btcoex_lock); - - ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type); - - spin_unlock_bh(&btinfo->btcoex_lock); - - if (btinfo->btcoex_period != btinfo->btcoex_no_stomp) { - if (btinfo->hw_timer_enabled) - ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); - - ath_gen_timer_start(sc->sc_ah, - btinfo->no_stomp_timer, - (ath9k_hw_gettsf32(sc->sc_ah) + - btinfo->btcoex_no_stomp), - btinfo->btcoex_no_stomp * 10); - btinfo->hw_timer_enabled = true; - } - - mod_timer(&btinfo->period_timer, jiffies + - msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD)); -} - -/* - * Generic tsf based hw timer which configures weight - * registers to time slice between wlan and bt traffic - */ - -static void ath_btcoex_no_stomp_timer(void *arg) -{ - struct ath_softc *sc = (struct ath_softc *)arg; - struct ath_btcoex_info *btinfo = &sc->btcoex_info; - - DPRINTF(sc, ATH_DBG_BTCOEX, "no stomp timer running \n"); - - spin_lock_bh(&btinfo->btcoex_lock); - - if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW) - ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE); - else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL) - ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW); - - spin_unlock_bh(&btinfo->btcoex_lock); -} - -static int ath_init_btcoex_info(struct ath_hw *hw, - struct ath_btcoex_info *btcoex_info) -{ - u32 i; - int qnum; - - qnum = ath_tx_get_qnum(hw->ah_sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); - - btcoex_info->bt_coex_mode = - (btcoex_info->bt_coex_mode & AR_BT_QCU_THRESH) | - SM(ath_bt_config.bt_time_extend, AR_BT_TIME_EXTEND) | - SM(ath_bt_config.bt_txstate_extend, AR_BT_TXSTATE_EXTEND) | - SM(ath_bt_config.bt_txframe_extend, AR_BT_TX_FRAME_EXTEND) | - SM(ath_bt_config.bt_mode, AR_BT_MODE) | - SM(ath_bt_config.bt_quiet_collision, AR_BT_QUIET) | - SM(ath_bt_config.bt_rxclear_polarity, AR_BT_RX_CLEAR_POLARITY) | - SM(ath_bt_config.bt_priority_time, AR_BT_PRIORITY_TIME) | - SM(ath_bt_config.bt_first_slot_time, AR_BT_FIRST_SLOT_TIME) | - SM(qnum, AR_BT_QCU_THRESH); - - btcoex_info->bt_coex_mode2 = - SM(ath_bt_config.bt_hold_rx_clear, AR_BT_HOLD_RX_CLEAR) | - SM(ATH_BTCOEX_BMISS_THRESH, AR_BT_BCN_MISS_THRESH) | - AR_BT_DISABLE_BT_ANT; - - btcoex_info->bt_stomp_type = ATH_BTCOEX_STOMP_LOW; - - btcoex_info->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000; - - btcoex_info->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) * - btcoex_info->btcoex_period / 100; - - for (i = 0; i < 32; i++) - hw->hw_gen_timers.gen_timer_index[(debruijn32 << i) >> 27] = i; - - setup_timer(&btcoex_info->period_timer, ath_btcoex_period_timer, - (unsigned long) hw->ah_sc); - - btcoex_info->no_stomp_timer = ath_gen_timer_alloc(hw, - ath_btcoex_no_stomp_timer, - ath_btcoex_no_stomp_timer, - (void *)hw->ah_sc, AR_FIRST_NDP_TIMER); - - if (btcoex_info->no_stomp_timer == NULL) - return -ENOMEM; - - spin_lock_init(&btcoex_info->btcoex_lock); - - return 0; -} - -int ath9k_hw_btcoex_init(struct ath_hw *ah) -{ - struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; - int ret = 0; - - if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { - /* connect bt_active to baseband */ - REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL, - (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF | - AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF)); - - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB); - - /* Set input mux for bt_active to gpio pin */ - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_ACTIVE, - btcoex_info->btactive_gpio); - - /* Configure the desired gpio port for input */ - ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); - } else { - /* btcoex 3-wire */ - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - (AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB | - AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB)); - - /* Set input mux for bt_prority_async and - * bt_active_async to GPIO pins */ - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_ACTIVE, - btcoex_info->btactive_gpio); - - REG_RMW_FIELD(ah, AR_GPIO_INPUT_MUX1, - AR_GPIO_INPUT_MUX1_BT_PRIORITY, - btcoex_info->btpriority_gpio); - - /* Configure the desired GPIO ports for input */ - - ath9k_hw_cfg_gpio_input(ah, btcoex_info->btactive_gpio); - ath9k_hw_cfg_gpio_input(ah, btcoex_info->btpriority_gpio); - - ret = ath_init_btcoex_info(ah, btcoex_info); - } - - return ret; -} - -void ath9k_hw_btcoex_enable(struct ath_hw *ah) -{ - struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; - - if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_2WIRE) { - /* Configure the desired GPIO port for TX_FRAME output */ - ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); - } else { - /* - * Program coex mode and weight registers to - * enable coex 3-wire - */ - REG_WRITE(ah, AR_BT_COEX_MODE, btcoex_info->bt_coex_mode); - REG_WRITE(ah, AR_BT_COEX_WEIGHT, btcoex_info->bt_coex_weights); - REG_WRITE(ah, AR_BT_COEX_MODE2, btcoex_info->bt_coex_mode2); - - REG_RMW_FIELD(ah, AR_QUIET1, - AR_QUIET1_QUIET_ACK_CTS_ENABLE, 1); - REG_RMW_FIELD(ah, AR_PCU_MISC, - AR_PCU_BT_ANT_PREVENT_RX, 0); - - ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL); - } - - REG_RMW(ah, AR_GPIO_PDPU, - (0x2 << (btcoex_info->btactive_gpio * 2)), - (0x3 << (btcoex_info->btactive_gpio * 2))); - - ah->ah_sc->sc_flags |= SC_OP_BTCOEX_ENABLED; -} - -void ath9k_hw_btcoex_disable(struct ath_hw *ah) -{ - struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; - - ath9k_hw_set_gpio(ah, btcoex_info->wlanactive_gpio, 0); - - ath9k_hw_cfg_output(ah, btcoex_info->wlanactive_gpio, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - - if (btcoex_info->btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) { - REG_WRITE(ah, AR_BT_COEX_MODE, AR_BT_QUIET | AR_BT_MODE); - REG_WRITE(ah, AR_BT_COEX_WEIGHT, 0); - REG_WRITE(ah, AR_BT_COEX_MODE2, 0); - } - - ah->ah_sc->sc_flags &= ~SC_OP_BTCOEX_ENABLED; -} - -/* - * Pause btcoex timer and bt duty cycle timer - */ -void ath_btcoex_timer_pause(struct ath_softc *sc, - struct ath_btcoex_info *btinfo) -{ - - del_timer_sync(&btinfo->period_timer); - - if (btinfo->hw_timer_enabled) - ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); - - btinfo->hw_timer_enabled = false; -} - -/* - * (Re)start btcoex timers - */ -void ath_btcoex_timer_resume(struct ath_softc *sc, - struct ath_btcoex_info *btinfo) -{ - - DPRINTF(sc, ATH_DBG_BTCOEX, "Starting btcoex timers"); - - /* make sure duty cycle timer is also stopped when resuming */ - if (btinfo->hw_timer_enabled) - ath_gen_timer_stop(sc->sc_ah, btinfo->no_stomp_timer); - - btinfo->bt_priority_cnt = 0; - btinfo->bt_priority_time = jiffies; - sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED; - - mod_timer(&btinfo->period_timer, jiffies); -} diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h deleted file mode 100644 index 297b027fd3c3..000000000000 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef BTCOEX_H -#define BTCOEX_H - -#define ATH_WLANACTIVE_GPIO 5 -#define ATH_BTACTIVE_GPIO 6 -#define ATH_BTPRIORITY_GPIO 7 - -#define ATH_BTCOEX_DEF_BT_PERIOD 45 -#define ATH_BTCOEX_DEF_DUTY_CYCLE 55 -#define ATH_BTCOEX_BMISS_THRESH 50 - -#define ATH_BT_PRIORITY_TIME_THRESHOLD 1000 /* ms */ -#define ATH_BT_CNT_THRESHOLD 3 - -enum ath_btcoex_scheme { - ATH_BTCOEX_CFG_NONE, - ATH_BTCOEX_CFG_2WIRE, - ATH_BTCOEX_CFG_3WIRE, -}; - -enum ath_stomp_type { - ATH_BTCOEX_NO_STOMP, - ATH_BTCOEX_STOMP_ALL, - ATH_BTCOEX_STOMP_LOW, - ATH_BTCOEX_STOMP_NONE -}; - -enum ath_bt_mode { - ATH_BT_COEX_MODE_LEGACY, /* legacy rx_clear mode */ - ATH_BT_COEX_MODE_UNSLOTTED, /* untimed/unslotted mode */ - ATH_BT_COEX_MODE_SLOTTED, /* slotted mode */ - ATH_BT_COEX_MODE_DISALBED, /* coexistence disabled */ -}; - -struct ath_btcoex_config { - u8 bt_time_extend; - bool bt_txstate_extend; - bool bt_txframe_extend; - enum ath_bt_mode bt_mode; /* coexistence mode */ - bool bt_quiet_collision; - bool bt_rxclear_polarity; /* invert rx_clear as WLAN_ACTIVE*/ - u8 bt_priority_time; - u8 bt_first_slot_time; - bool bt_hold_rx_clear; -}; - -struct ath_btcoex_info { - enum ath_btcoex_scheme btcoex_scheme; - u8 wlanactive_gpio; - u8 btactive_gpio; - u8 btpriority_gpio; - u8 bt_duty_cycle; /* BT duty cycle in percentage */ - int bt_stomp_type; /* Types of BT stomping */ - u32 bt_coex_mode; /* Register setting for AR_BT_COEX_MODE */ - u32 bt_coex_weights; /* Register setting for AR_BT_COEX_WEIGHT */ - u32 bt_coex_mode2; /* Register setting for AR_BT_COEX_MODE2 */ - u32 btcoex_no_stomp; /* in usec */ - u32 btcoex_period; /* in usec */ - u32 bt_priority_cnt; - unsigned long bt_priority_time; - bool hw_timer_enabled; - spinlock_t btcoex_lock; - struct timer_list period_timer; /* Timer for BT period */ - struct ath_gen_timer *no_stomp_timer; /*Timer for no BT stomping*/ -}; - -bool ath_btcoex_supported(u16 subsysid); -int ath9k_hw_btcoex_init(struct ath_hw *ah); -void ath9k_hw_btcoex_enable(struct ath_hw *ah); -void ath9k_hw_btcoex_disable(struct ath_hw *ah); -void ath_btcoex_timer_resume(struct ath_softc *sc, - struct ath_btcoex_info *btinfo); -void ath_btcoex_timer_pause(struct ath_softc *sc, - struct ath_btcoex_info *btinfo); - -static inline void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info, - u32 bt_weight, - u32 wlan_weight) -{ - btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | - SM(wlan_weight, AR_BTCOEX_WL_WGHT); -} - -#endif diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c deleted file mode 100644 index 0ad6d0b76e9e..000000000000 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ /dev/null @@ -1,1206 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -/* We can tune this as we go by monitoring really low values */ -#define ATH9K_NF_TOO_LOW -60 - -/* AR5416 may return very high value (like -31 dBm), in those cases the nf - * is incorrect and we should use the static NF value. Later we can try to - * find out why they are reporting these values */ - -static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) -{ - if (nf > ATH9K_NF_TOO_LOW) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "noise floor value detected (%d) is " - "lower than what we think is a " - "reasonable value (%d)\n", - nf, ATH9K_NF_TOO_LOW); - return false; - } - return true; -} - -static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) -{ - int16_t nfval; - int16_t sort[ATH9K_NF_CAL_HIST_MAX]; - int i, j; - - for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++) - sort[i] = nfCalBuffer[i]; - - for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) { - for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) { - if (sort[j] > sort[j - 1]) { - nfval = sort[j]; - sort[j] = sort[j - 1]; - sort[j - 1] = nfval; - } - } - } - nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1]; - - return nfval; -} - -static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h, - int16_t *nfarray) -{ - int i; - - for (i = 0; i < NUM_NF_READINGS; i++) { - h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; - - if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) - h[i].currIndex = 0; - - if (h[i].invalidNFcount > 0) { - if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE || - nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) { - h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX; - } else { - h[i].invalidNFcount--; - h[i].privNF = nfarray[i]; - } - } else { - h[i].privNF = - ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer); - } - } - return; -} - -static void ath9k_hw_do_getnf(struct ath_hw *ah, - int16_t nfarray[NUM_NF_READINGS]) -{ - int16_t nf; - - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CCA), AR9280_PHY_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CCA), AR_PHY_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 0] is %d\n", nf); - nfarray[0] = nf; - - if (!AR_SREV_9285(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR9280_PHY_CH1_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR_PHY_CH1_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 1] is %d\n", nf); - nfarray[1] = nf; - - if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), - AR_PHY_CH2_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[2] = nf; - } - } - - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), - AR9280_PHY_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), - AR_PHY_EXT_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 0] is %d\n", nf); - nfarray[3] = nf; - - if (!AR_SREV_9285(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR9280_PHY_CH1_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR_PHY_CH1_EXT_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 1] is %d\n", nf); - nfarray[4] = nf; - - if (!AR_SREV_9280(ah) && !AR_SREV_9287(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), - AR_PHY_CH2_EXT_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 2] is %d\n", nf); - nfarray[5] = nf; - } - } -} - -static bool getNoiseFloorThresh(struct ath_hw *ah, - enum ieee80211_band band, - int16_t *nft) -{ - switch (band) { - case IEEE80211_BAND_5GHZ: - *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5); - break; - case IEEE80211_BAND_2GHZ: - *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2); - break; - default: - BUG_ON(1); - return false; - } - - return true; -} - -static void ath9k_hw_setup_calibration(struct ath_hw *ah, - struct ath9k_cal_list *currCal) -{ - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX, - currCal->calData->calCountMax); - - switch (currCal->calData->calType) { - case IQ_MISMATCH_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_IQ); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting IQ Mismatch Calibration\n"); - break; - case ADC_GAIN_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_GAIN); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting ADC Gain Calibration\n"); - break; - case ADC_DC_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_PER); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting ADC DC Calibration\n"); - break; - case ADC_DC_INIT_CAL: - REG_WRITE(ah, AR_PHY_CALMODE, AR_PHY_CALMODE_ADC_DC_INIT); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "starting Init ADC DC Calibration\n"); - break; - } - - REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_DO_CAL); -} - -static void ath9k_hw_reset_calibration(struct ath_hw *ah, - struct ath9k_cal_list *currCal) -{ - int i; - - ath9k_hw_setup_calibration(ah, currCal); - - currCal->calState = CAL_RUNNING; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->meas0.sign[i] = 0; - ah->meas1.sign[i] = 0; - ah->meas2.sign[i] = 0; - ah->meas3.sign[i] = 0; - } - - ah->cal_samples = 0; -} - -static bool ath9k_hw_per_calibration(struct ath_hw *ah, - struct ath9k_channel *ichan, - u8 rxchainmask, - struct ath9k_cal_list *currCal) -{ - bool iscaldone = false; - - if (currCal->calState == CAL_RUNNING) { - if (!(REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & - AR_PHY_TIMING_CTRL4_DO_CAL)) { - - currCal->calData->calCollect(ah); - ah->cal_samples++; - - if (ah->cal_samples >= currCal->calData->calNumSamples) { - int i, numChains = 0; - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (rxchainmask & (1 << i)) - numChains++; - } - - currCal->calData->calPostProc(ah, numChains); - ichan->CalValid |= currCal->calData->calType; - currCal->calState = CAL_DONE; - iscaldone = true; - } else { - ath9k_hw_setup_calibration(ah, currCal); - } - } - } else if (!(ichan->CalValid & currCal->calData->calType)) { - ath9k_hw_reset_calibration(ah, currCal); - } - - return iscaldone; -} - -/* Assumes you are talking about the currently configured channel */ -static bool ath9k_hw_iscal_supported(struct ath_hw *ah, - enum ath9k_cal_types calType) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - switch (calType & ah->supp_cals) { - case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ - return true; - case ADC_GAIN_CAL: - case ADC_DC_CAL: - if (!(conf->channel->band == IEEE80211_BAND_2GHZ && - conf_is_ht20(conf))) - return true; - break; - } - return false; -} - -static void ath9k_hw_iqcal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalPowerMeasI[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalPowerMeasQ[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalIqCorrMeas[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "%d: Chn %d pmi=0x%08x;pmq=0x%08x;iqcm=0x%08x;\n", - ah->cal_samples, i, ah->totalPowerMeasI[i], - ah->totalPowerMeasQ[i], - ah->totalIqCorrMeas[i]); - } -} - -static void ath9k_hw_adc_gaincal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalAdcIOddPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalAdcIEvenPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalAdcQOddPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ah->totalAdcQEvenPhase[i] += - REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcIOddPhase[i], - ah->totalAdcIEvenPhase[i], - ah->totalAdcQOddPhase[i], - ah->totalAdcQEvenPhase[i]); - } -} - -static void ath9k_hw_adc_dccal_collect(struct ath_hw *ah) -{ - int i; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - ah->totalAdcDcOffsetIOddPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_0(i)); - ah->totalAdcDcOffsetIEvenPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_1(i)); - ah->totalAdcDcOffsetQOddPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_2(i)); - ah->totalAdcDcOffsetQEvenPhase[i] += - (int32_t) REG_READ(ah, AR_PHY_CAL_MEAS_3(i)); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "%d: Chn %d oddi=0x%08x; eveni=0x%08x; " - "oddq=0x%08x; evenq=0x%08x;\n", - ah->cal_samples, i, - ah->totalAdcDcOffsetIOddPhase[i], - ah->totalAdcDcOffsetIEvenPhase[i], - ah->totalAdcDcOffsetQOddPhase[i], - ah->totalAdcDcOffsetQEvenPhase[i]); - } -} - -static void ath9k_hw_iqcalibrate(struct ath_hw *ah, u8 numChains) -{ - u32 powerMeasQ, powerMeasI, iqCorrMeas; - u32 qCoffDenom, iCoffDenom; - int32_t qCoff, iCoff; - int iqCorrNeg, i; - - for (i = 0; i < numChains; i++) { - powerMeasI = ah->totalPowerMeasI[i]; - powerMeasQ = ah->totalPowerMeasQ[i]; - iqCorrMeas = ah->totalIqCorrMeas[i]; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Starting IQ Cal and Correction for Chain %d\n", - i); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Orignal: Chn %diq_corr_meas = 0x%08x\n", - i, ah->totalIqCorrMeas[i]); - - iqCorrNeg = 0; - - if (iqCorrMeas > 0x80000000) { - iqCorrMeas = (0xffffffff - iqCorrMeas) + 1; - iqCorrNeg = 1; - } - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_i = 0x%08x\n", i, powerMeasI); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_q = 0x%08x\n", i, powerMeasQ); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "iqCorrNeg is 0x%08x\n", - iqCorrNeg); - - iCoffDenom = (powerMeasI / 2 + powerMeasQ / 2) / 128; - qCoffDenom = powerMeasQ / 64; - - if (powerMeasQ != 0) { - iCoff = iqCorrMeas / iCoffDenom; - qCoff = powerMeasI / qCoffDenom - 64; - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d iCoff = 0x%08x\n", i, iCoff); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d qCoff = 0x%08x\n", i, qCoff); - - iCoff = iCoff & 0x3f; - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "New: Chn %d iCoff = 0x%08x\n", i, iCoff); - if (iqCorrNeg == 0x0) - iCoff = 0x40 - iCoff; - - if (qCoff > 15) - qCoff = 15; - else if (qCoff <= -16) - qCoff = 16; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d : iCoff = 0x%x qCoff = 0x%x\n", - i, iCoff, qCoff); - - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF, - iCoff); - REG_RMW_FIELD(ah, AR_PHY_TIMING_CTRL4(i), - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF, - qCoff); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "IQ Cal and Correction done for Chain %d\n", - i); - } - } - - REG_SET_BIT(ah, AR_PHY_TIMING_CTRL4(0), - AR_PHY_TIMING_CTRL4_IQCORR_ENABLE); -} - -static void ath9k_hw_adc_gaincal_calibrate(struct ath_hw *ah, u8 numChains) -{ - u32 iOddMeasOffset, iEvenMeasOffset, qOddMeasOffset, qEvenMeasOffset; - u32 qGainMismatch, iGainMismatch, val, i; - - for (i = 0; i < numChains; i++) { - iOddMeasOffset = ah->totalAdcIOddPhase[i]; - iEvenMeasOffset = ah->totalAdcIEvenPhase[i]; - qOddMeasOffset = ah->totalAdcQOddPhase[i]; - qEvenMeasOffset = ah->totalAdcQEvenPhase[i]; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Starting ADC Gain Cal for Chain %d\n", i); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = 0x%08x\n", i, - iOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = 0x%08x\n", i, - iEvenMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = 0x%08x\n", i, - qOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = 0x%08x\n", i, - qEvenMeasOffset); - - if (iOddMeasOffset != 0 && qEvenMeasOffset != 0) { - iGainMismatch = - ((iEvenMeasOffset * 32) / - iOddMeasOffset) & 0x3f; - qGainMismatch = - ((qOddMeasOffset * 32) / - qEvenMeasOffset) & 0x3f; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_i = 0x%08x\n", i, - iGainMismatch); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d gain_mismatch_q = 0x%08x\n", i, - qGainMismatch); - - val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xfffff000; - val |= (qGainMismatch) | (iGainMismatch << 6); - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "ADC Gain Cal done for Chain %d\n", i); - } - } - - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | - AR_PHY_NEW_ADC_GAIN_CORR_ENABLE); -} - -static void ath9k_hw_adc_dccal_calibrate(struct ath_hw *ah, u8 numChains) -{ - u32 iOddMeasOffset, iEvenMeasOffset, val, i; - int32_t qOddMeasOffset, qEvenMeasOffset, qDcMismatch, iDcMismatch; - const struct ath9k_percal_data *calData = - ah->cal_list_curr->calData; - u32 numSamples = - (1 << (calData->calCountMax + 5)) * calData->calNumSamples; - - for (i = 0; i < numChains; i++) { - iOddMeasOffset = ah->totalAdcDcOffsetIOddPhase[i]; - iEvenMeasOffset = ah->totalAdcDcOffsetIEvenPhase[i]; - qOddMeasOffset = ah->totalAdcDcOffsetQOddPhase[i]; - qEvenMeasOffset = ah->totalAdcDcOffsetQEvenPhase[i]; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Starting ADC DC Offset Cal for Chain %d\n", i); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_i = %d\n", i, - iOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_i = %d\n", i, - iEvenMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_odd_q = %d\n", i, - qOddMeasOffset); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d pwr_meas_even_q = %d\n", i, - qEvenMeasOffset); - - iDcMismatch = (((iEvenMeasOffset - iOddMeasOffset) * 2) / - numSamples) & 0x1ff; - qDcMismatch = (((qOddMeasOffset - qEvenMeasOffset) * 2) / - numSamples) & 0x1ff; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_i = 0x%08x\n", i, - iDcMismatch); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Chn %d dc_offset_mismatch_q = 0x%08x\n", i, - qDcMismatch); - - val = REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i)); - val &= 0xc0000fff; - val |= (qDcMismatch << 12) | (iDcMismatch << 21); - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(i), val); - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "ADC DC Offset Cal done for Chain %d\n", i); - } - - REG_WRITE(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0), - REG_READ(ah, AR_PHY_NEW_ADC_DC_GAIN_CORR(0)) | - AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); -} - -/* This is done for the currently configured channel */ -bool ath9k_hw_reset_calvalid(struct ath_hw *ah) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - struct ath9k_cal_list *currCal = ah->cal_list_curr; - - if (!ah->curchan) - return true; - - if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) - return true; - - if (currCal == NULL) - return true; - - if (currCal->calState != CAL_DONE) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Calibration state incorrect, %d\n", - currCal->calState); - return true; - } - - if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) - return true; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Resetting Cal %d state for channel %u\n", - currCal->calData->calType, conf->channel->center_freq); - - ah->curchan->CalValid &= ~currCal->calData->calType; - currCal->calState = CAL_WAITING; - - return false; -} - -void ath9k_hw_start_nfcal(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_ENABLE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); -} - -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) -{ - struct ath9k_nfcal_hist *h; - int i, j; - int32_t val; - const u32 ar5416_cca_regs[6] = { - AR_PHY_CCA, - AR_PHY_CH1_CCA, - AR_PHY_CH2_CCA, - AR_PHY_EXT_CCA, - AR_PHY_CH1_EXT_CCA, - AR_PHY_CH2_EXT_CCA - }; - u8 chainmask, rx_chain_status; - - rx_chain_status = REG_READ(ah, AR_PHY_RX_CHAINMASK); - if (AR_SREV_9285(ah)) - chainmask = 0x9; - else if (AR_SREV_9280(ah) || AR_SREV_9287(ah)) { - if ((rx_chain_status & 0x2) || (rx_chain_status & 0x4)) - chainmask = 0x1B; - else - chainmask = 0x09; - } else { - if (rx_chain_status & 0x4) - chainmask = 0x3F; - else if (rx_chain_status & 0x2) - chainmask = 0x1B; - else - chainmask = 0x09; - } - - h = ah->nfCalHist; - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (chainmask & (1 << i)) { - val = REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((u32) (h[i].privNF) << 1) & 0x1ff); - REG_WRITE(ah, ar5416_cca_regs[i], val); - } - } - - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_ENABLE_NF); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_NO_UPDATE_NF); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); - - for (j = 0; j < 1000; j++) { - if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & - AR_PHY_AGC_CONTROL_NF) == 0) - break; - udelay(10); - } - - for (i = 0; i < NUM_NF_READINGS; i++) { - if (chainmask & (1 << i)) { - val = REG_READ(ah, ar5416_cca_regs[i]); - val &= 0xFFFFFE00; - val |= (((u32) (-50) << 1) & 0x1ff); - REG_WRITE(ah, ar5416_cca_regs[i], val); - } - } -} - -int16_t ath9k_hw_getnf(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - int16_t nf, nfThresh; - int16_t nfarray[NUM_NF_READINGS] = { 0 }; - struct ath9k_nfcal_hist *h; - struct ieee80211_channel *c = chan->chan; - - chan->channelFlags &= (~CHANNEL_CW_INT); - if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF did not complete in calibration window\n"); - nf = 0; - chan->rawNoiseFloor = nf; - return chan->rawNoiseFloor; - } else { - ath9k_hw_do_getnf(ah, nfarray); - nf = nfarray[0]; - if (getNoiseFloorThresh(ah, c->band, &nfThresh) - && nf > nfThresh) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "noise floor failed detected; " - "detected %d, threshold %d\n", - nf, nfThresh); - chan->channelFlags |= CHANNEL_CW_INT; - } - } - - h = ah->nfCalHist; - - ath9k_hw_update_nfcal_hist_buffer(h, nfarray); - chan->rawNoiseFloor = h[0].privNF; - - return chan->rawNoiseFloor; -} - -void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) -{ - int i, j; - s16 noise_floor; - - if (AR_SREV_9280(ah)) - noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE; - else if (AR_SREV_9285(ah)) - noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE; - else if (AR_SREV_9287(ah)) - noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE; - else - noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE; - - for (i = 0; i < NUM_NF_READINGS; i++) { - ah->nfCalHist[i].currIndex = 0; - ah->nfCalHist[i].privNF = noise_floor; - ah->nfCalHist[i].invalidNFcount = - AR_PHY_CCA_FILTERWINDOW_LENGTH; - for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { - ah->nfCalHist[i].nfCalBuffer[j] = noise_floor; - } - } -} - -s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) -{ - s16 nf; - - if (chan->rawNoiseFloor == 0) - nf = -96; - else - nf = chan->rawNoiseFloor; - - if (!ath9k_hw_nf_in_range(ah, nf)) - nf = ATH_DEFAULT_NOISE_FLOOR; - - return nf; -} - -static void ath9k_olc_temp_compensation(struct ath_hw *ah) -{ - u32 rddata, i; - int delta, currPDADC, regval, slope; - - rddata = REG_READ(ah, AR_PHY_TX_PWRCTRL4); - currPDADC = MS(rddata, AR_PHY_TX_PWRCTRL_PD_AVG_OUT); - - - if (OLC_FOR_AR9287_10_LATER) { - if (ah->initPDADC == 0 || currPDADC == 0) { - return; - } else { - slope = ah->eep_ops->get_eeprom(ah, EEP_TEMPSENSE_SLOPE); - if (slope == 0) - delta = 0; - else - delta = ((currPDADC - ah->initPDADC)*4) / slope; - REG_RMW_FIELD(ah, AR_PHY_CH0_TX_PWRCTRL11, - AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); - REG_RMW_FIELD(ah, AR_PHY_CH1_TX_PWRCTRL11, - AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP, delta); - } - } else { - if (ah->eep_ops->get_eeprom(ah, EEP_DAC_HPWR_5G)) - delta = (currPDADC - ah->initPDADC + 4) / 8; - else - delta = (currPDADC - ah->initPDADC + 5) / 10; - - if (delta != ah->PDADCdelta) { - ah->PDADCdelta = delta; - for (i = 1; i < AR9280_TX_GAIN_TABLE_SIZE; i++) { - regval = ah->originalGain[i] - delta; - if (regval < 0) - regval = 0; - - REG_RMW_FIELD(ah, AR_PHY_TX_GAIN_TBL1 + i * 4, - AR_PHY_TX_GAIN, regval); - } - } - } -} - -static void ath9k_hw_9271_pa_cal(struct ath_hw *ah) -{ - u32 regVal; - unsigned int i; - u32 regList [][2] = { - { 0x786c, 0 }, - { 0x7854, 0 }, - { 0x7820, 0 }, - { 0x7824, 0 }, - { 0x7868, 0 }, - { 0x783c, 0 }, - { 0x7838, 0 } , - { 0x7828, 0 } , - }; - - for (i = 0; i < ARRAY_SIZE(regList); i++) - regList[i][1] = REG_READ(ah, regList[i][0]); - - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1)); - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal |= (0x1 << 27); - REG_WRITE(ah, 0x9808, regVal); - - /* 786c,b23,1, pwddac=1 */ - REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); - /* 7854, b5,1, pdrxtxbb=1 */ - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); - /* 7854, b7,1, pdv2i=1 */ - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); - /* 7854, b8,1, pddacinterface=1 */ - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); - /* 7824,b12,0, offcal=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); - /* 7838, b1,0, pwddb=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); - /* 7820,b11,0, enpacal=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); - /* 7820,b25,1, pdpadrv1=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); - /* 7820,b24,0, pdpadrv2=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1,AR9285_AN_RF2G1_PDPADRV2,0); - /* 7820,b23,0, pdpaout=0 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); - /* 783c,b14-16,7, padrvgn2tab_0=7 */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G8,AR9285_AN_RF2G8_PADRVGN2TAB0, 7); - /* - * 7838,b29-31,0, padrvgn1tab_0=0 - * does not matter since we turn it off - */ - REG_RMW_FIELD(ah, AR9285_AN_RF2G7,AR9285_AN_RF2G7_PADRVGN2TAB0, 0); - - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9271_AN_RF2G3_CCOMP, 0xfff); - - /* Set: - * localmode=1,bmode=1,bmoderxtx=1,synthon=1, - * txon=1,paon=1,oscon=1,synthon_force=1 - */ - REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); - udelay(30); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0); - - /* find off_6_1; */ - for (i = 6; i >= 0; i--) { - regVal = REG_READ(ah, 0x7834); - regVal |= (1 << (20 + i)); - REG_WRITE(ah, 0x7834, regVal); - udelay(1); - //regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1 << (20 + i))); - regVal |= (MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9) - << (20 + i)); - REG_WRITE(ah, 0x7834, regVal); - } - - /* Empirical offset correction */ -#if 0 - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9271_AN_RF2G6_OFFS, 0x20); -#endif - - regVal = REG_READ(ah, 0x7834); - regVal |= 0x1; - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal &= (~(0x1 << 27)); - REG_WRITE(ah, 0x9808, regVal); - - for (i = 0; i < ARRAY_SIZE(regList); i++) - REG_WRITE(ah, regList[i][0], regList[i][1]); -} - -static inline void ath9k_hw_9285_pa_cal(struct ath_hw *ah, bool is_reset) -{ - - u32 regVal; - int i, offset, offs_6_1, offs_0; - u32 ccomp_org, reg_field; - u32 regList[][2] = { - { 0x786c, 0 }, - { 0x7854, 0 }, - { 0x7820, 0 }, - { 0x7824, 0 }, - { 0x7868, 0 }, - { 0x783c, 0 }, - { 0x7838, 0 }, - }; - - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Running PA Calibration\n"); - - /* PA CAL is not needed for high power solution */ - if (ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE) == - AR5416_EEP_TXGAIN_HIGH_POWER) - return; - - if (AR_SREV_9285_11(ah)) { - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); - udelay(10); - } - - for (i = 0; i < ARRAY_SIZE(regList); i++) - regList[i][1] = REG_READ(ah, regList[i][0]); - - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1)); - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal |= (0x1 << 27); - REG_WRITE(ah, 0x9808, regVal); - - REG_RMW_FIELD(ah, AR9285_AN_TOP3, AR9285_AN_TOP3_PWDDAC, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDRXTXBB1, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDV2I, 1); - REG_RMW_FIELD(ah, AR9285_AN_RXTXBB1, AR9285_AN_RXTXBB1_PDDACIF, 1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G2, AR9285_AN_RF2G2_OFFCAL, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PWDDB, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_ENPACAL, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV1, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPADRV2, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G1, AR9285_AN_RF2G1_PDPAOUT, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G8, AR9285_AN_RF2G8_PADRVGN2TAB0, 7); - REG_RMW_FIELD(ah, AR9285_AN_RF2G7, AR9285_AN_RF2G7_PADRVGN2TAB0, 0); - ccomp_org = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_CCOMP); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, 0xf); - - REG_WRITE(ah, AR9285_AN_TOP2, 0xca0358a0); - udelay(30); - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, 0); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 0); - - for (i = 6; i > 0; i--) { - regVal = REG_READ(ah, 0x7834); - regVal |= (1 << (19 + i)); - REG_WRITE(ah, 0x7834, regVal); - udelay(1); - regVal = REG_READ(ah, 0x7834); - regVal &= (~(0x1 << (19 + i))); - reg_field = MS(REG_READ(ah, 0x7840), AR9285_AN_RXTXBB1_SPARE9); - regVal |= (reg_field << (19 + i)); - REG_WRITE(ah, 0x7834, regVal); - } - - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, 1); - udelay(1); - reg_field = MS(REG_READ(ah, AR9285_AN_RF2G9), AR9285_AN_RXTXBB1_SPARE9); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, reg_field); - offs_6_1 = MS(REG_READ(ah, AR9285_AN_RF2G6), AR9285_AN_RF2G6_OFFS); - offs_0 = MS(REG_READ(ah, AR9285_AN_RF2G3), AR9285_AN_RF2G3_PDVCCOMP); - - offset = (offs_6_1<<1) | offs_0; - offset = offset - 0; - offs_6_1 = offset>>1; - offs_0 = offset & 1; - - if ((!is_reset) && (ah->pacal_info.prev_offset == offset)) { - if (ah->pacal_info.max_skipcount < MAX_PACAL_SKIPCOUNT) - ah->pacal_info.max_skipcount = - 2 * ah->pacal_info.max_skipcount; - ah->pacal_info.skipcount = ah->pacal_info.max_skipcount; - } else { - ah->pacal_info.max_skipcount = 1; - ah->pacal_info.skipcount = 0; - ah->pacal_info.prev_offset = offset; - } - - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_OFFS, offs_6_1); - REG_RMW_FIELD(ah, AR9285_AN_RF2G3, AR9285_AN_RF2G3_PDVCCOMP, offs_0); - - regVal = REG_READ(ah, 0x7834); - regVal |= 0x1; - REG_WRITE(ah, 0x7834, regVal); - regVal = REG_READ(ah, 0x9808); - regVal &= (~(0x1 << 27)); - REG_WRITE(ah, 0x9808, regVal); - - for (i = 0; i < ARRAY_SIZE(regList); i++) - REG_WRITE(ah, regList[i][0], regList[i][1]); - - REG_RMW_FIELD(ah, AR9285_AN_RF2G6, AR9285_AN_RF2G6_CCOMP, ccomp_org); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - -} - -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal) -{ - bool iscaldone = true; - struct ath9k_cal_list *currCal = ah->cal_list_curr; - - if (currCal && - (currCal->calState == CAL_RUNNING || - currCal->calState == CAL_WAITING)) { - iscaldone = ath9k_hw_per_calibration(ah, chan, - rxchainmask, currCal); - if (iscaldone) { - ah->cal_list_curr = currCal = currCal->calNext; - - if (currCal->calState == CAL_WAITING) { - iscaldone = false; - ath9k_hw_reset_calibration(ah, currCal); - } - } - } - - /* Do NF cal only at longer intervals */ - if (longcal) { - /* Do periodic PAOffset Cal */ - if (AR_SREV_9271(ah)) - ath9k_hw_9271_pa_cal(ah); - else if (AR_SREV_9285_11_OR_LATER(ah)) { - if (!ah->pacal_info.skipcount) - ath9k_hw_9285_pa_cal(ah, false); - else - ah->pacal_info.skipcount--; - } - - if (OLC_FOR_AR9280_20_LATER || OLC_FOR_AR9287_10_LATER) - ath9k_olc_temp_compensation(ah); - - /* Get the value from the previous NF cal and update history buffer */ - ath9k_hw_getnf(ah, chan); - - /* - * Load the NF from history buffer of the current channel. - * NF is slow time-variant, so it is OK to use a historical value. - */ - ath9k_hw_loadnf(ah, ah->curchan); - - ath9k_hw_start_nfcal(ah); - } - - return iscaldone; -} - -static bool ar9285_clc(struct ath_hw *ah, struct ath9k_channel *chan) -{ - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - if (IS_CHAN_HT20(chan)) { - REG_SET_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_CLR_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_CAL, 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset " - "calibration failed to complete in " - "1ms; noisy ??\n"); - return false; - } - REG_CLR_BIT(ah, AR_PHY_TURBO, AR_PHY_FC_DYN2040_EN); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_PARALLEL_CAL_ENABLE); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - } - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - REG_SET_BIT(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_CAL_ENABLE); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL); - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "offset calibration " - "failed to complete in 1ms; noisy ??\n"); - return false; - } - - REG_SET_BIT(ah, AR_PHY_ADC_CTL, AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_CL_CAL_CTL, AR_PHY_CL_CAL_ENABLE); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_FLTR_CAL); - - return true; -} - -bool ath9k_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) -{ - if (AR_SREV_9285_12_OR_LATER(ah)) { - if (!ar9285_clc(ah, chan)) - return false; - } else { - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!AR_SREV_9287_10_OR_LATER(ah)) - REG_CLR_BIT(ah, AR_PHY_ADC_CTL, - AR_PHY_ADC_CTL_OFF_PWDADC); - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - } - - /* Calibrate the AGC */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | - AR_PHY_AGC_CONTROL_CAL); - - /* Poll for offset calibration complete */ - if (!ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_CAL, - 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "offset calibration failed to complete in 1ms; " - "noisy environment?\n"); - return false; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (!AR_SREV_9287_10_OR_LATER(ah)) - REG_SET_BIT(ah, AR_PHY_ADC_CTL, - AR_PHY_ADC_CTL_OFF_PWDADC); - REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, - AR_PHY_AGC_CONTROL_FLTR_CAL); - } - } - - /* Do PA Calibration */ - if (AR_SREV_9285_11_OR_LATER(ah)) - ath9k_hw_9285_pa_cal(ah, true); - - /* Do NF Calibration after DC offset and other calibrations */ - REG_WRITE(ah, AR_PHY_AGC_CONTROL, - REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); - - ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; - - /* Enable IQ, ADC Gain and ADC DC offset CALs */ - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { - if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { - INIT_CAL(&ah->adcgain_caldata); - INSERT_CAL(ah, &ah->adcgain_caldata); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC Gain Calibration.\n"); - } - if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { - INIT_CAL(&ah->adcdc_caldata); - INSERT_CAL(ah, &ah->adcdc_caldata); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling ADC DC Calibration.\n"); - } - if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { - INIT_CAL(&ah->iq_caldata); - INSERT_CAL(ah, &ah->iq_caldata); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "enabling IQ Calibration.\n"); - } - - ah->cal_list_curr = ah->cal_list; - - if (ah->cal_list_curr) - ath9k_hw_reset_calibration(ah, ah->cal_list_curr); - } - - chan->CalValid = 0; - - return true; -} - -const struct ath9k_percal_data iq_cal_multi_sample = { - IQ_MISMATCH_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_iqcal_collect, - ath9k_hw_iqcalibrate -}; -const struct ath9k_percal_data iq_cal_single_sample = { - IQ_MISMATCH_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_iqcal_collect, - ath9k_hw_iqcalibrate -}; -const struct ath9k_percal_data adc_gain_cal_multi_sample = { - ADC_GAIN_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_adc_gaincal_collect, - ath9k_hw_adc_gaincal_calibrate -}; -const struct ath9k_percal_data adc_gain_cal_single_sample = { - ADC_GAIN_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_adc_gaincal_collect, - ath9k_hw_adc_gaincal_calibrate -}; -const struct ath9k_percal_data adc_dc_cal_multi_sample = { - ADC_DC_CAL, - MAX_CAL_SAMPLES, - PER_MIN_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; -const struct ath9k_percal_data adc_dc_cal_single_sample = { - ADC_DC_CAL, - MIN_CAL_SAMPLES, - PER_MAX_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; -const struct ath9k_percal_data adc_init_dc_cal = { - ADC_DC_INIT_CAL, - MIN_CAL_SAMPLES, - INIT_LOG_COUNT, - ath9k_hw_adc_dccal_collect, - ath9k_hw_adc_dccal_calibrate -}; diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h deleted file mode 100644 index 9028ab193e42..000000000000 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef CALIB_H -#define CALIB_H - -extern const struct ath9k_percal_data iq_cal_multi_sample; -extern const struct ath9k_percal_data iq_cal_single_sample; -extern const struct ath9k_percal_data adc_gain_cal_multi_sample; -extern const struct ath9k_percal_data adc_gain_cal_single_sample; -extern const struct ath9k_percal_data adc_dc_cal_multi_sample; -extern const struct ath9k_percal_data adc_dc_cal_single_sample; -extern const struct ath9k_percal_data adc_init_dc_cal; - -#define AR_PHY_CCA_MAX_AR5416_GOOD_VALUE -85 -#define AR_PHY_CCA_MAX_AR9280_GOOD_VALUE -112 -#define AR_PHY_CCA_MAX_AR9285_GOOD_VALUE -118 -#define AR_PHY_CCA_MAX_AR9287_GOOD_VALUE -118 -#define AR_PHY_CCA_MAX_HIGH_VALUE -62 -#define AR_PHY_CCA_MIN_BAD_VALUE -140 -#define AR_PHY_CCA_FILTERWINDOW_LENGTH_INIT 3 -#define AR_PHY_CCA_FILTERWINDOW_LENGTH 5 - -#define NUM_NF_READINGS 6 -#define ATH9K_NF_CAL_HIST_MAX 5 - -struct ar5416IniArray { - u32 *ia_array; - u32 ia_rows; - u32 ia_columns; -}; - -#define INIT_INI_ARRAY(iniarray, array, rows, columns) do { \ - (iniarray)->ia_array = (u32 *)(array); \ - (iniarray)->ia_rows = (rows); \ - (iniarray)->ia_columns = (columns); \ - } while (0) - -#define INI_RA(iniarray, row, column) \ - (((iniarray)->ia_array)[(row) * ((iniarray)->ia_columns) + (column)]) - -#define INIT_CAL(_perCal) do { \ - (_perCal)->calState = CAL_WAITING; \ - (_perCal)->calNext = NULL; \ - } while (0) - -#define INSERT_CAL(_ahp, _perCal) \ - do { \ - if ((_ahp)->cal_list_last == NULL) { \ - (_ahp)->cal_list = \ - (_ahp)->cal_list_last = (_perCal); \ - ((_ahp)->cal_list_last)->calNext = (_perCal); \ - } else { \ - ((_ahp)->cal_list_last)->calNext = (_perCal); \ - (_ahp)->cal_list_last = (_perCal); \ - (_perCal)->calNext = (_ahp)->cal_list; \ - } \ - } while (0) - -enum ath9k_cal_types { - ADC_DC_INIT_CAL = 0x1, - ADC_GAIN_CAL = 0x2, - ADC_DC_CAL = 0x4, - IQ_MISMATCH_CAL = 0x8 -}; - -enum ath9k_cal_state { - CAL_INACTIVE, - CAL_WAITING, - CAL_RUNNING, - CAL_DONE -}; - -#define MIN_CAL_SAMPLES 1 -#define MAX_CAL_SAMPLES 64 -#define INIT_LOG_COUNT 5 -#define PER_MIN_LOG_COUNT 2 -#define PER_MAX_LOG_COUNT 10 - -struct ath9k_percal_data { - enum ath9k_cal_types calType; - u32 calNumSamples; - u32 calCountMax; - void (*calCollect) (struct ath_hw *); - void (*calPostProc) (struct ath_hw *, u8); -}; - -struct ath9k_cal_list { - const struct ath9k_percal_data *calData; - enum ath9k_cal_state calState; - struct ath9k_cal_list *calNext; -}; - -struct ath9k_nfcal_hist { - int16_t nfCalBuffer[ATH9K_NF_CAL_HIST_MAX]; - u8 currIndex; - int16_t privNF; - u8 invalidNFcount; -}; - -#define MAX_PACAL_SKIPCOUNT 8 -struct ath9k_pacal_info{ - int32_t prev_offset; /* Previous value of PA offset value */ - int8_t max_skipcount; /* Max No. of times PACAL can be skipped */ - int8_t skipcount; /* No. of times the PACAL to be skipped */ -}; - -bool ath9k_hw_reset_calvalid(struct ath_hw *ah); -void ath9k_hw_start_nfcal(struct ath_hw *ah); -void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); -int16_t ath9k_hw_getnf(struct ath_hw *ah, - struct ath9k_channel *chan); -void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); -s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); -bool ath9k_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, - u8 rxchainmask, bool longcal); -bool ath9k_hw_init_cal(struct ath_hw *ah, - struct ath9k_channel *chan); - -#endif /* CALIB_H */ diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c deleted file mode 100644 index 2be4c2252047..000000000000 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include "ath9k.h" - -static unsigned int ath9k_debug = DBG_DEFAULT; -module_param_named(debug, ath9k_debug, uint, 0); - -static struct dentry *ath9k_debugfs_root; - -void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...) -{ - if (!sc) - return; - - if (sc->debug.debug_mask & dbg_mask) { - va_list args; - - va_start(args, fmt); - printk(KERN_DEBUG "ath9k: "); - vprintk(fmt, args); - va_end(args); - } -} - -static int ath9k_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t read_file_debug(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[32]; - unsigned int len; - - len = snprintf(buf, sizeof(buf), "0x%08x\n", sc->debug.debug_mask); - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static ssize_t write_file_debug(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - unsigned long mask; - char buf[32]; - ssize_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EINVAL; - - buf[len] = '\0'; - if (strict_strtoul(buf, 0, &mask)) - return -EINVAL; - - sc->debug.debug_mask = mask; - return count; -} - -static const struct file_operations fops_debug = { - .read = read_file_debug, - .write = write_file_debug, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -static ssize_t read_file_dma(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - struct ath_hw *ah = sc->sc_ah; - char buf[1024]; - unsigned int len = 0; - u32 val[ATH9K_NUM_DMA_DEBUG_REGS]; - int i, qcuOffset = 0, dcuOffset = 0; - u32 *qcuBase = &val[0], *dcuBase = &val[4]; - - ath9k_ps_wakeup(sc); - - REG_WRITE(ah, AR_MACMISC, - ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | - (AR_MACMISC_MISC_OBS_BUS_1 << - AR_MACMISC_MISC_OBS_BUS_MSB_S))); - - len += snprintf(buf + len, sizeof(buf) - len, - "Raw DMA Debug values:\n"); - - for (i = 0; i < ATH9K_NUM_DMA_DEBUG_REGS; i++) { - if (i % 4 == 0) - len += snprintf(buf + len, sizeof(buf) - len, "\n"); - - val[i] = REG_READ(ah, AR_DMADBG_0 + (i * sizeof(u32))); - len += snprintf(buf + len, sizeof(buf) - len, "%d: %08x ", - i, val[i]); - } - - len += snprintf(buf + len, sizeof(buf) - len, "\n\n"); - len += snprintf(buf + len, sizeof(buf) - len, - "Num QCU: chain_st fsp_ok fsp_st DCU: chain_st\n"); - - for (i = 0; i < ATH9K_NUM_QUEUES; i++, qcuOffset += 4, dcuOffset += 5) { - if (i == 8) { - qcuOffset = 0; - qcuBase++; - } - - if (i == 6) { - dcuOffset = 0; - dcuBase++; - } - - len += snprintf(buf + len, sizeof(buf) - len, - "%2d %2x %1x %2x %2x\n", - i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, - (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), - val[2] & (0x7 << (i * 3)) >> (i * 3), - (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); - } - - len += snprintf(buf + len, sizeof(buf) - len, "\n"); - - len += snprintf(buf + len, sizeof(buf) - len, - "qcu_stitch state: %2x qcu_fetch state: %2x\n", - (val[3] & 0x003c0000) >> 18, (val[3] & 0x03c00000) >> 22); - len += snprintf(buf + len, sizeof(buf) - len, - "qcu_complete state: %2x dcu_complete state: %2x\n", - (val[3] & 0x1c000000) >> 26, (val[6] & 0x3)); - len += snprintf(buf + len, sizeof(buf) - len, - "dcu_arb state: %2x dcu_fp state: %2x\n", - (val[5] & 0x06000000) >> 25, (val[5] & 0x38000000) >> 27); - len += snprintf(buf + len, sizeof(buf) - len, - "chan_idle_dur: %3d chan_idle_dur_valid: %1d\n", - (val[6] & 0x000003fc) >> 2, (val[6] & 0x00000400) >> 10); - len += snprintf(buf + len, sizeof(buf) - len, - "txfifo_valid_0: %1d txfifo_valid_1: %1d\n", - (val[6] & 0x00000800) >> 11, (val[6] & 0x00001000) >> 12); - len += snprintf(buf + len, sizeof(buf) - len, - "txfifo_dcu_num_0: %2d txfifo_dcu_num_1: %2d\n", - (val[6] & 0x0001e000) >> 13, (val[6] & 0x001e0000) >> 17); - - len += snprintf(buf + len, sizeof(buf) - len, "pcu observe: 0x%x \n", - REG_READ(ah, AR_OBS_BUS_1)); - len += snprintf(buf + len, sizeof(buf) - len, - "AR_CR: 0x%x \n", REG_READ(ah, AR_CR)); - - ath9k_ps_restore(sc); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_dma = { - .read = read_file_dma, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - - -void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) -{ - if (status) - sc->debug.stats.istats.total++; - if (status & ATH9K_INT_RX) - sc->debug.stats.istats.rxok++; - if (status & ATH9K_INT_RXEOL) - sc->debug.stats.istats.rxeol++; - if (status & ATH9K_INT_RXORN) - sc->debug.stats.istats.rxorn++; - if (status & ATH9K_INT_TX) - sc->debug.stats.istats.txok++; - if (status & ATH9K_INT_TXURN) - sc->debug.stats.istats.txurn++; - if (status & ATH9K_INT_MIB) - sc->debug.stats.istats.mib++; - if (status & ATH9K_INT_RXPHY) - sc->debug.stats.istats.rxphyerr++; - if (status & ATH9K_INT_RXKCM) - sc->debug.stats.istats.rx_keycache_miss++; - if (status & ATH9K_INT_SWBA) - sc->debug.stats.istats.swba++; - if (status & ATH9K_INT_BMISS) - sc->debug.stats.istats.bmiss++; - if (status & ATH9K_INT_BNR) - sc->debug.stats.istats.bnr++; - if (status & ATH9K_INT_CST) - sc->debug.stats.istats.cst++; - if (status & ATH9K_INT_GTT) - sc->debug.stats.istats.gtt++; - if (status & ATH9K_INT_TIM) - sc->debug.stats.istats.tim++; - if (status & ATH9K_INT_CABEND) - sc->debug.stats.istats.cabend++; - if (status & ATH9K_INT_DTIMSYNC) - sc->debug.stats.istats.dtimsync++; - if (status & ATH9K_INT_DTIM) - sc->debug.stats.istats.dtim++; -} - -static ssize_t read_file_interrupt(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[512]; - unsigned int len = 0; - - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RX", sc->debug.stats.istats.rxok); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXEOL", sc->debug.stats.istats.rxeol); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXORN", sc->debug.stats.istats.rxorn); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TX", sc->debug.stats.istats.txok); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TXURN", sc->debug.stats.istats.txurn); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "MIB", sc->debug.stats.istats.mib); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXPHY", sc->debug.stats.istats.rxphyerr); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "RXKCM", sc->debug.stats.istats.rx_keycache_miss); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "SWBA", sc->debug.stats.istats.swba); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "BMISS", sc->debug.stats.istats.bmiss); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "BNR", sc->debug.stats.istats.bnr); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "CST", sc->debug.stats.istats.cst); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "GTT", sc->debug.stats.istats.gtt); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TIM", sc->debug.stats.istats.tim); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "CABEND", sc->debug.stats.istats.cabend); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "DTIMSYNC", sc->debug.stats.istats.dtimsync); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "DTIM", sc->debug.stats.istats.dtim); - len += snprintf(buf + len, sizeof(buf) - len, - "%8s: %10u\n", "TOTAL", sc->debug.stats.istats.total); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static const struct file_operations fops_interrupt = { - .read = read_file_interrupt, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_tx_info_priv *tx_info_priv = NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->status.rates; - int final_ts_idx, idx; - struct ath_rc_stats *stats; - - tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - final_ts_idx = tx_info_priv->tx.ts_rateindex; - idx = rates[final_ts_idx].idx; - stats = &sc->debug.stats.rcstats[idx]; - stats->success++; -} - -void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per) -{ - struct ath_rc_stats *stats = &sc->debug.stats.rcstats[rix]; - - stats->xretries += xretries; - stats->retries += retries; - stats->per = per; -} - -static ssize_t read_file_rcstat(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char *buf; - unsigned int len = 0, max; - int i = 0; - ssize_t retval; - - if (sc->cur_rate_table == NULL) - return 0; - - max = 80 + sc->cur_rate_table->rate_cnt * 64; - buf = kmalloc(max + 1, GFP_KERNEL); - if (buf == NULL) - return 0; - buf[max] = 0; - - len += sprintf(buf, "%5s %15s %8s %9s %3s\n\n", "Rate", "Success", - "Retries", "XRetries", "PER"); - - for (i = 0; i < sc->cur_rate_table->rate_cnt; i++) { - u32 ratekbps = sc->cur_rate_table->info[i].ratekbps; - struct ath_rc_stats *stats = &sc->debug.stats.rcstats[i]; - - len += snprintf(buf + len, max - len, - "%3u.%d: %8u %8u %8u %8u\n", ratekbps / 1000, - (ratekbps % 1000) / 100, stats->success, - stats->retries, stats->xretries, - stats->per); - } - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - return retval; -} - -static const struct file_operations fops_rcstat = { - .read = read_file_rcstat, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -static const char * ath_wiphy_state_str(enum ath_wiphy_state state) -{ - switch (state) { - case ATH_WIPHY_INACTIVE: - return "INACTIVE"; - case ATH_WIPHY_ACTIVE: - return "ACTIVE"; - case ATH_WIPHY_PAUSING: - return "PAUSING"; - case ATH_WIPHY_PAUSED: - return "PAUSED"; - case ATH_WIPHY_SCAN: - return "SCAN"; - } - return "?"; -} - -static ssize_t read_file_wiphy(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[512]; - unsigned int len = 0; - int i; - u8 addr[ETH_ALEN]; - - len += snprintf(buf + len, sizeof(buf) - len, - "primary: %s (%s chan=%d ht=%d)\n", - wiphy_name(sc->pri_wiphy->hw->wiphy), - ath_wiphy_state_str(sc->pri_wiphy->state), - sc->pri_wiphy->chan_idx, sc->pri_wiphy->chan_is_ht); - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - len += snprintf(buf + len, sizeof(buf) - len, - "secondary: %s (%s chan=%d ht=%d)\n", - wiphy_name(aphy->hw->wiphy), - ath_wiphy_state_str(aphy->state), - aphy->chan_idx, aphy->chan_is_ht); - } - - put_unaligned_le32(REG_READ(sc->sc_ah, AR_STA_ID0), addr); - put_unaligned_le16(REG_READ(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4); - len += snprintf(buf + len, sizeof(buf) - len, - "addr: %pM\n", addr); - put_unaligned_le32(REG_READ(sc->sc_ah, AR_BSSMSKL), addr); - put_unaligned_le16(REG_READ(sc->sc_ah, AR_BSSMSKU) & 0xffff, addr + 4); - len += snprintf(buf + len, sizeof(buf) - len, - "addrmask: %pM\n", addr); - - return simple_read_from_buffer(user_buf, count, ppos, buf, len); -} - -static struct ath_wiphy * get_wiphy(struct ath_softc *sc, const char *name) -{ - int i; - if (strcmp(name, wiphy_name(sc->pri_wiphy->hw->wiphy)) == 0) - return sc->pri_wiphy; - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy && strcmp(name, wiphy_name(aphy->hw->wiphy)) == 0) - return aphy; - } - return NULL; -} - -static int del_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_del(aphy); -} - -static int pause_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_pause(aphy); -} - -static int unpause_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_unpause(aphy); -} - -static int select_wiphy(struct ath_softc *sc, const char *name) -{ - struct ath_wiphy *aphy = get_wiphy(sc, name); - if (!aphy) - return -ENOENT; - return ath9k_wiphy_select(aphy); -} - -static int schedule_wiphy(struct ath_softc *sc, const char *msec) -{ - ath9k_wiphy_set_scheduler(sc, simple_strtoul(msec, NULL, 0)); - return 0; -} - -static ssize_t write_file_wiphy(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char buf[50]; - size_t len; - - len = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, len)) - return -EFAULT; - buf[len] = '\0'; - if (len > 0 && buf[len - 1] == '\n') - buf[len - 1] = '\0'; - - if (strncmp(buf, "add", 3) == 0) { - int res = ath9k_wiphy_add(sc); - if (res < 0) - return res; - } else if (strncmp(buf, "del=", 4) == 0) { - int res = del_wiphy(sc, buf + 4); - if (res < 0) - return res; - } else if (strncmp(buf, "pause=", 6) == 0) { - int res = pause_wiphy(sc, buf + 6); - if (res < 0) - return res; - } else if (strncmp(buf, "unpause=", 8) == 0) { - int res = unpause_wiphy(sc, buf + 8); - if (res < 0) - return res; - } else if (strncmp(buf, "select=", 7) == 0) { - int res = select_wiphy(sc, buf + 7); - if (res < 0) - return res; - } else if (strncmp(buf, "schedule=", 9) == 0) { - int res = schedule_wiphy(sc, buf + 9); - if (res < 0) - return res; - } else - return -EOPNOTSUPP; - - return count; -} - -static const struct file_operations fops_wiphy = { - .read = read_file_wiphy, - .write = write_file_wiphy, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -#define PR(str, elem) \ - do { \ - len += snprintf(buf + len, size - len, \ - "%s%13u%11u%10u%10u\n", str, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \ - sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \ -} while(0) - -static ssize_t read_file_xmit(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct ath_softc *sc = file->private_data; - char *buf; - unsigned int len = 0, size = 2048; - ssize_t retval = 0; - - buf = kzalloc(size, GFP_KERNEL); - if (buf == NULL) - return 0; - - len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO"); - - PR("MPDUs Queued: ", queued); - PR("MPDUs Completed: ", completed); - PR("Aggregates: ", a_aggr); - PR("AMPDUs Queued: ", a_queued); - PR("AMPDUs Completed:", a_completed); - PR("AMPDUs Retried: ", a_retries); - PR("AMPDUs XRetried: ", a_xretries); - PR("FIFO Underrun: ", fifo_underrun); - PR("TXOP Exceeded: ", xtxop); - PR("TXTIMER Expiry: ", timer_exp); - PR("DESC CFG Error: ", desc_cfg_err); - PR("DATA Underrun: ", data_underrun); - PR("DELIM Underrun: ", delim_underrun); - - retval = simple_read_from_buffer(user_buf, count, ppos, buf, len); - kfree(buf); - - return retval; -} - -void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) -{ - struct ath_desc *ds = bf->bf_desc; - - if (bf_isampdu(bf)) { - if (bf_isxretried(bf)) - TX_STAT_INC(txq->axq_qnum, a_xretries); - else - TX_STAT_INC(txq->axq_qnum, a_completed); - } else { - TX_STAT_INC(txq->axq_qnum, completed); - } - - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO) - TX_STAT_INC(txq->axq_qnum, fifo_underrun); - if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP) - TX_STAT_INC(txq->axq_qnum, xtxop); - if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED) - TX_STAT_INC(txq->axq_qnum, timer_exp); - if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR) - TX_STAT_INC(txq->axq_qnum, desc_cfg_err); - if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN) - TX_STAT_INC(txq->axq_qnum, data_underrun); - if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN) - TX_STAT_INC(txq->axq_qnum, delim_underrun); -} - -static const struct file_operations fops_xmit = { - .read = read_file_xmit, - .open = ath9k_debugfs_open, - .owner = THIS_MODULE -}; - -int ath9k_init_debug(struct ath_softc *sc) -{ - sc->debug.debug_mask = ath9k_debug; - - if (!ath9k_debugfs_root) - return -ENOENT; - - sc->debug.debugfs_phy = debugfs_create_dir(wiphy_name(sc->hw->wiphy), - ath9k_debugfs_root); - if (!sc->debug.debugfs_phy) - goto err; - - sc->debug.debugfs_debug = debugfs_create_file("debug", - S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug); - if (!sc->debug.debugfs_debug) - goto err; - - sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR, - sc->debug.debugfs_phy, sc, &fops_dma); - if (!sc->debug.debugfs_dma) - goto err; - - sc->debug.debugfs_interrupt = debugfs_create_file("interrupt", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_interrupt); - if (!sc->debug.debugfs_interrupt) - goto err; - - sc->debug.debugfs_rcstat = debugfs_create_file("rcstat", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_rcstat); - if (!sc->debug.debugfs_rcstat) - goto err; - - sc->debug.debugfs_wiphy = debugfs_create_file( - "wiphy", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, - &fops_wiphy); - if (!sc->debug.debugfs_wiphy) - goto err; - - sc->debug.debugfs_xmit = debugfs_create_file("xmit", - S_IRUSR, - sc->debug.debugfs_phy, - sc, &fops_xmit); - if (!sc->debug.debugfs_xmit) - goto err; - - return 0; -err: - ath9k_exit_debug(sc); - return -ENOMEM; -} - -void ath9k_exit_debug(struct ath_softc *sc) -{ - debugfs_remove(sc->debug.debugfs_xmit); - debugfs_remove(sc->debug.debugfs_wiphy); - debugfs_remove(sc->debug.debugfs_rcstat); - debugfs_remove(sc->debug.debugfs_interrupt); - debugfs_remove(sc->debug.debugfs_dma); - debugfs_remove(sc->debug.debugfs_debug); - debugfs_remove(sc->debug.debugfs_phy); -} - -int ath9k_debug_create_root(void) -{ - ath9k_debugfs_root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!ath9k_debugfs_root) - return -ENOENT; - - return 0; -} - -void ath9k_debug_remove_root(void) -{ - debugfs_remove(ath9k_debugfs_root); - ath9k_debugfs_root = NULL; -} diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h deleted file mode 100644 index 7241f4748338..000000000000 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ /dev/null @@ -1,214 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef DEBUG_H -#define DEBUG_H - -enum ATH_DEBUG { - ATH_DBG_RESET = 0x00000001, - ATH_DBG_QUEUE = 0x00000002, - ATH_DBG_EEPROM = 0x00000004, - ATH_DBG_CALIBRATE = 0x00000008, - ATH_DBG_INTERRUPT = 0x00000010, - ATH_DBG_REGULATORY = 0x00000020, - ATH_DBG_ANI = 0x00000040, - ATH_DBG_XMIT = 0x00000080, - ATH_DBG_BEACON = 0x00000100, - ATH_DBG_CONFIG = 0x00000200, - ATH_DBG_FATAL = 0x00000400, - ATH_DBG_PS = 0x00000800, - ATH_DBG_HWTIMER = 0x00001000, - ATH_DBG_BTCOEX = 0x00002000, - ATH_DBG_ANY = 0xffffffff -}; - -#define DBG_DEFAULT (ATH_DBG_FATAL) - -struct ath_txq; -struct ath_buf; - -#ifdef CONFIG_ATH9K_DEBUG -#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ -#else -#define TX_STAT_INC(q, c) do { } while (0) -#endif - -#ifdef CONFIG_ATH9K_DEBUG - -/** - * struct ath_interrupt_stats - Contains statistics about interrupts - * @total: Total no. of interrupts generated so far - * @rxok: RX with no errors - * @rxeol: RX with no more RXDESC available - * @rxorn: RX FIFO overrun - * @txok: TX completed at the requested rate - * @txurn: TX FIFO underrun - * @mib: MIB regs reaching its threshold - * @rxphyerr: RX with phy errors - * @rx_keycache_miss: RX with key cache misses - * @swba: Software Beacon Alert - * @bmiss: Beacon Miss - * @bnr: Beacon Not Ready - * @cst: Carrier Sense TImeout - * @gtt: Global TX Timeout - * @tim: RX beacon TIM occurrence - * @cabend: RX End of CAB traffic - * @dtimsync: DTIM sync lossage - * @dtim: RX Beacon with DTIM - */ -struct ath_interrupt_stats { - u32 total; - u32 rxok; - u32 rxeol; - u32 rxorn; - u32 txok; - u32 txeol; - u32 txurn; - u32 mib; - u32 rxphyerr; - u32 rx_keycache_miss; - u32 swba; - u32 bmiss; - u32 bnr; - u32 cst; - u32 gtt; - u32 tim; - u32 cabend; - u32 dtimsync; - u32 dtim; -}; - -struct ath_rc_stats { - u32 success; - u32 retries; - u32 xretries; - u8 per; -}; - -/** - * struct ath_tx_stats - Statistics about TX - * @queued: Total MPDUs (non-aggr) queued - * @completed: Total MPDUs (non-aggr) completed - * @a_aggr: Total no. of aggregates queued - * @a_queued: Total AMPDUs queued - * @a_completed: Total AMPDUs completed - * @a_retries: No. of AMPDUs retried (SW) - * @a_xretries: No. of AMPDUs dropped due to xretries - * @fifo_underrun: FIFO underrun occurrences - Valid only for: - - non-aggregate condition. - - first packet of aggregate. - * @xtxop: No. of frames filtered because of TXOP limit - * @timer_exp: Transmit timer expiry - * @desc_cfg_err: Descriptor configuration errors - * @data_urn: TX data underrun errors - * @delim_urn: TX delimiter underrun errors - */ -struct ath_tx_stats { - u32 queued; - u32 completed; - u32 a_aggr; - u32 a_queued; - u32 a_completed; - u32 a_retries; - u32 a_xretries; - u32 fifo_underrun; - u32 xtxop; - u32 timer_exp; - u32 desc_cfg_err; - u32 data_underrun; - u32 delim_underrun; -}; - -struct ath_stats { - struct ath_interrupt_stats istats; - struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; - struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES]; -}; - -struct ath9k_debug { - int debug_mask; - struct dentry *debugfs_phy; - struct dentry *debugfs_debug; - struct dentry *debugfs_dma; - struct dentry *debugfs_interrupt; - struct dentry *debugfs_rcstat; - struct dentry *debugfs_wiphy; - struct dentry *debugfs_xmit; - struct ath_stats stats; -}; - -void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...); -int ath9k_init_debug(struct ath_softc *sc); -void ath9k_exit_debug(struct ath_softc *sc); -int ath9k_debug_create_root(void); -void ath9k_debug_remove_root(void); -void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); -void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); -void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf); -void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per); - -#else - -static inline void DPRINTF(struct ath_softc *sc, int dbg_mask, - const char *fmt, ...) -{ -} - -static inline int ath9k_init_debug(struct ath_softc *sc) -{ - return 0; -} - -static inline void ath9k_exit_debug(struct ath_softc *sc) -{ -} - -static inline int ath9k_debug_create_root(void) -{ - return 0; -} - -static inline void ath9k_debug_remove_root(void) -{ -} - -static inline void ath_debug_stat_interrupt(struct ath_softc *sc, - enum ath9k_int status) -{ -} - -static inline void ath_debug_stat_rc(struct ath_softc *sc, - struct sk_buff *skb) -{ -} - -static inline void ath_debug_stat_tx(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_buf *bf) -{ -} - -static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix, - int xretries, int retries, u8 per) -{ -} - -#endif /* CONFIG_ATH9K_DEBUG */ - -#endif /* DEBUG_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c deleted file mode 100644 index b6e52d0f8c48..000000000000 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ /dev/null @@ -1,278 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static inline u16 ath9k_hw_fbin2freq(u8 fbin, bool is2GHz) -{ - if (fbin == AR5416_BCHAN_UNUSED) - return fbin; - - return (u16) ((is2GHz) ? (2300 + fbin) : (4800 + 5 * fbin)); -} - -void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, - u32 shift, u32 val) -{ - u32 regVal; - - regVal = REG_READ(ah, reg) & ~mask; - regVal |= (val << shift) & mask; - - REG_WRITE(ah, reg, regVal); - - if (ah->config.analog_shiftreg) - udelay(100); - - return; -} - -int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, - int16_t targetLeft, int16_t targetRight) -{ - int16_t rv; - - if (srcRight == srcLeft) { - rv = targetLeft; - } else { - rv = (int16_t) (((target - srcLeft) * targetRight + - (srcRight - target) * targetLeft) / - (srcRight - srcLeft)); - } - return rv; -} - -bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, - u16 *indexL, u16 *indexR) -{ - u16 i; - - if (target <= pList[0]) { - *indexL = *indexR = 0; - return true; - } - if (target >= pList[listSize - 1]) { - *indexL = *indexR = (u16) (listSize - 1); - return true; - } - - for (i = 0; i < listSize - 1; i++) { - if (pList[i] == target) { - *indexL = *indexR = i; - return true; - } - if (target < pList[i + 1]) { - *indexL = i; - *indexR = (u16) (i + 1); - return false; - } - } - return false; -} - -bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) -{ - struct ath_softc *sc = ah->ah_sc; - - return sc->bus_ops->eeprom_read(ah, off, data); -} - -void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, - u8 *pVpdList, u16 numIntercepts, - u8 *pRetVpdList) -{ - u16 i, k; - u8 currPwr = pwrMin; - u16 idxL = 0, idxR = 0; - - for (i = 0; i <= (pwrMax - pwrMin) / 2; i++) { - ath9k_hw_get_lower_upper_index(currPwr, pPwrList, - numIntercepts, &(idxL), - &(idxR)); - if (idxR < 1) - idxR = 1; - if (idxL == numIntercepts - 1) - idxL = (u16) (numIntercepts - 2); - if (pPwrList[idxL] == pPwrList[idxR]) - k = pVpdList[idxL]; - else - k = (u16)(((currPwr - pPwrList[idxL]) * pVpdList[idxR] + - (pPwrList[idxR] - currPwr) * pVpdList[idxL]) / - (pPwrList[idxR] - pPwrList[idxL])); - pRetVpdList[i] = (u8) k; - currPwr += 2; - } -} - -void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_target_power_leg *powInfo, - u16 numChannels, - struct cal_target_power_leg *pNewPower, - u16 numRates, bool isExtTarget) -{ - struct chan_centers centers; - u16 clo, chi; - int i; - int matchIndex = -1, lowIndex = -1; - u16 freq; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = (isExtTarget) ? centers.ext_center : centers.ctl_center; - - if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, - IS_CHAN_2GHZ(chan))) { - matchIndex = 0; - } else { - for (i = 0; (i < numChannels) && - (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { - if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan))) { - matchIndex = i; - break; - } else if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan)) && i > 0 && - freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, - IS_CHAN_2GHZ(chan))) { - lowIndex = i - 1; - break; - } - } - if ((matchIndex == -1) && (lowIndex == -1)) - matchIndex = i - 1; - } - - if (matchIndex != -1) { - *pNewPower = powInfo[matchIndex]; - } else { - clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, - IS_CHAN_2GHZ(chan)); - chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, - IS_CHAN_2GHZ(chan)); - - for (i = 0; i < numRates; i++) { - pNewPower->tPow2x[i] = - (u8)ath9k_hw_interpolate(freq, clo, chi, - powInfo[lowIndex].tPow2x[i], - powInfo[lowIndex + 1].tPow2x[i]); - } - } -} - -void ath9k_hw_get_target_powers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_target_power_ht *powInfo, - u16 numChannels, - struct cal_target_power_ht *pNewPower, - u16 numRates, bool isHt40Target) -{ - struct chan_centers centers; - u16 clo, chi; - int i; - int matchIndex = -1, lowIndex = -1; - u16 freq; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = isHt40Target ? centers.synth_center : centers.ctl_center; - - if (freq <= ath9k_hw_fbin2freq(powInfo[0].bChannel, IS_CHAN_2GHZ(chan))) { - matchIndex = 0; - } else { - for (i = 0; (i < numChannels) && - (powInfo[i].bChannel != AR5416_BCHAN_UNUSED); i++) { - if (freq == ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan))) { - matchIndex = i; - break; - } else - if (freq < ath9k_hw_fbin2freq(powInfo[i].bChannel, - IS_CHAN_2GHZ(chan)) && i > 0 && - freq > ath9k_hw_fbin2freq(powInfo[i - 1].bChannel, - IS_CHAN_2GHZ(chan))) { - lowIndex = i - 1; - break; - } - } - if ((matchIndex == -1) && (lowIndex == -1)) - matchIndex = i - 1; - } - - if (matchIndex != -1) { - *pNewPower = powInfo[matchIndex]; - } else { - clo = ath9k_hw_fbin2freq(powInfo[lowIndex].bChannel, - IS_CHAN_2GHZ(chan)); - chi = ath9k_hw_fbin2freq(powInfo[lowIndex + 1].bChannel, - IS_CHAN_2GHZ(chan)); - - for (i = 0; i < numRates; i++) { - pNewPower->tPow2x[i] = (u8)ath9k_hw_interpolate(freq, - clo, chi, - powInfo[lowIndex].tPow2x[i], - powInfo[lowIndex + 1].tPow2x[i]); - } - } -} - -u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, - bool is2GHz, int num_band_edges) -{ - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - int i; - - for (i = 0; (i < num_band_edges) && - (pRdEdgesPower[i].bChannel != AR5416_BCHAN_UNUSED); i++) { - if (freq == ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, is2GHz)) { - twiceMaxEdgePower = pRdEdgesPower[i].tPower; - break; - } else if ((i > 0) && - (freq < ath9k_hw_fbin2freq(pRdEdgesPower[i].bChannel, - is2GHz))) { - if (ath9k_hw_fbin2freq(pRdEdgesPower[i - 1].bChannel, - is2GHz) < freq && - pRdEdgesPower[i - 1].flag) { - twiceMaxEdgePower = - pRdEdgesPower[i - 1].tPower; - } - break; - } - } - - return twiceMaxEdgePower; -} - -int ath9k_hw_eeprom_init(struct ath_hw *ah) -{ - int status; - - if (AR_SREV_9287(ah)) { - ah->eep_map = EEP_MAP_AR9287; - ah->eep_ops = &eep_AR9287_ops; - } else if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) { - ah->eep_map = EEP_MAP_4KBITS; - ah->eep_ops = &eep_4k_ops; - } else { - ah->eep_map = EEP_MAP_DEFAULT; - ah->eep_ops = &eep_def_ops; - } - - if (!ah->eep_ops->fill_eeprom(ah)) - return -EIO; - - status = ah->eep_ops->check_eeprom(ah); - - return status; -} diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h deleted file mode 100644 index a5daa0d318cb..000000000000 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ /dev/null @@ -1,715 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef EEPROM_H -#define EEPROM_H - -#include - -#define AH_USE_EEPROM 0x1 - -#ifdef __BIG_ENDIAN -#define AR5416_EEPROM_MAGIC 0x5aa5 -#else -#define AR5416_EEPROM_MAGIC 0xa55a -#endif - -#define CTRY_DEBUG 0x1ff -#define CTRY_DEFAULT 0 - -#define AR_EEPROM_EEPCAP_COMPRESS_DIS 0x0001 -#define AR_EEPROM_EEPCAP_AES_DIS 0x0002 -#define AR_EEPROM_EEPCAP_FASTFRAME_DIS 0x0004 -#define AR_EEPROM_EEPCAP_BURST_DIS 0x0008 -#define AR_EEPROM_EEPCAP_MAXQCU 0x01F0 -#define AR_EEPROM_EEPCAP_MAXQCU_S 4 -#define AR_EEPROM_EEPCAP_HEAVY_CLIP_EN 0x0200 -#define AR_EEPROM_EEPCAP_KC_ENTRIES 0xF000 -#define AR_EEPROM_EEPCAP_KC_ENTRIES_S 12 - -#define AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND 0x0040 -#define AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN 0x0080 -#define AR_EEPROM_EEREGCAP_EN_KK_U2 0x0100 -#define AR_EEPROM_EEREGCAP_EN_KK_MIDBAND 0x0200 -#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD 0x0400 -#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A 0x0800 - -#define AR_EEPROM_EEREGCAP_EN_KK_U1_ODD_PRE4_0 0x4000 -#define AR_EEPROM_EEREGCAP_EN_KK_NEW_11A_PRE4_0 0x8000 - -#define AR5416_EEPROM_MAGIC_OFFSET 0x0 -#define AR5416_EEPROM_S 2 -#define AR5416_EEPROM_OFFSET 0x2000 -#define AR5416_EEPROM_MAX 0xae0 - -#define AR5416_EEPROM_START_ADDR \ - (AR_SREV_9100(ah)) ? 0x1fff1000 : 0x503f1200 - -#define SD_NO_CTL 0xE0 -#define NO_CTL 0xff -#define CTL_MODE_M 0xf -#define CTL_11A 0 -#define CTL_11B 1 -#define CTL_11G 2 -#define CTL_2GHT20 5 -#define CTL_5GHT20 6 -#define CTL_2GHT40 7 -#define CTL_5GHT40 8 - -#define EXT_ADDITIVE (0x8000) -#define CTL_11A_EXT (CTL_11A | EXT_ADDITIVE) -#define CTL_11G_EXT (CTL_11G | EXT_ADDITIVE) -#define CTL_11B_EXT (CTL_11B | EXT_ADDITIVE) - -#define SUB_NUM_CTL_MODES_AT_5G_40 2 -#define SUB_NUM_CTL_MODES_AT_2G_40 3 - -#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ -#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 /* 10*log10(3)*2 */ - -/* - * For AR9285 and later chipsets, the following bits are not being programmed - * in EEPROM and so need to be enabled always. - * - * Bit 0: en_fcc_mid - * Bit 1: en_jap_mid - * Bit 2: en_fcc_dfs_ht40 - * Bit 3: en_jap_ht40 - * Bit 4: en_jap_dfs_ht40 - */ -#define AR9285_RDEXT_DEFAULT 0x1F - -#define AR_EEPROM_MAC(i) (0x1d+(i)) -#define ATH9K_POW_SM(_r, _s) (((_r) & 0x3f) << (_s)) -#define FREQ2FBIN(x, y) ((y) ? ((x) - 2300) : (((x) - 4800) / 5)) -#define ath9k_hw_use_flash(_ah) (!(_ah->ah_flags & AH_USE_EEPROM)) - -#define AR5416_VER_MASK (eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) -#define OLC_FOR_AR9280_20_LATER (AR_SREV_9280_20_OR_LATER(ah) && \ - ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) -#define OLC_FOR_AR9287_10_LATER (AR_SREV_9287_10_OR_LATER(ah) && \ - ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) - -#define AR_EEPROM_RFSILENT_GPIO_SEL 0x001c -#define AR_EEPROM_RFSILENT_GPIO_SEL_S 2 -#define AR_EEPROM_RFSILENT_POLARITY 0x0002 -#define AR_EEPROM_RFSILENT_POLARITY_S 1 - -#define EEP_RFSILENT_ENABLED 0x0001 -#define EEP_RFSILENT_ENABLED_S 0 -#define EEP_RFSILENT_POLARITY 0x0002 -#define EEP_RFSILENT_POLARITY_S 1 -#define EEP_RFSILENT_GPIO_SEL 0x001c -#define EEP_RFSILENT_GPIO_SEL_S 2 - -#define AR5416_OPFLAGS_11A 0x01 -#define AR5416_OPFLAGS_11G 0x02 -#define AR5416_OPFLAGS_N_5G_HT40 0x04 -#define AR5416_OPFLAGS_N_2G_HT40 0x08 -#define AR5416_OPFLAGS_N_5G_HT20 0x10 -#define AR5416_OPFLAGS_N_2G_HT20 0x20 - -#define AR5416_EEP_NO_BACK_VER 0x1 -#define AR5416_EEP_VER 0xE -#define AR5416_EEP_VER_MINOR_MASK 0x0FFF -#define AR5416_EEP_MINOR_VER_2 0x2 -#define AR5416_EEP_MINOR_VER_3 0x3 -#define AR5416_EEP_MINOR_VER_7 0x7 -#define AR5416_EEP_MINOR_VER_9 0x9 -#define AR5416_EEP_MINOR_VER_16 0x10 -#define AR5416_EEP_MINOR_VER_17 0x11 -#define AR5416_EEP_MINOR_VER_19 0x13 -#define AR5416_EEP_MINOR_VER_20 0x14 -#define AR5416_EEP_MINOR_VER_22 0x16 - -#define AR5416_NUM_5G_CAL_PIERS 8 -#define AR5416_NUM_2G_CAL_PIERS 4 -#define AR5416_NUM_5G_20_TARGET_POWERS 8 -#define AR5416_NUM_5G_40_TARGET_POWERS 8 -#define AR5416_NUM_2G_CCK_TARGET_POWERS 3 -#define AR5416_NUM_2G_20_TARGET_POWERS 4 -#define AR5416_NUM_2G_40_TARGET_POWERS 4 -#define AR5416_NUM_CTLS 24 -#define AR5416_NUM_BAND_EDGES 8 -#define AR5416_NUM_PD_GAINS 4 -#define AR5416_PD_GAINS_IN_MASK 4 -#define AR5416_PD_GAIN_ICEPTS 5 -#define AR5416_EEPROM_MODAL_SPURS 5 -#define AR5416_MAX_RATE_POWER 63 -#define AR5416_NUM_PDADC_VALUES 128 -#define AR5416_BCHAN_UNUSED 0xFF -#define AR5416_MAX_PWR_RANGE_IN_HALF_DB 64 -#define AR5416_MAX_CHAINS 3 -#define AR5416_PWR_TABLE_OFFSET -5 - -/* Rx gain type values */ -#define AR5416_EEP_RXGAIN_23DB_BACKOFF 0 -#define AR5416_EEP_RXGAIN_13DB_BACKOFF 1 -#define AR5416_EEP_RXGAIN_ORIG 2 - -/* Tx gain type values */ -#define AR5416_EEP_TXGAIN_ORIGINAL 0 -#define AR5416_EEP_TXGAIN_HIGH_POWER 1 - -#define AR5416_EEP4K_START_LOC 64 -#define AR5416_EEP4K_NUM_2G_CAL_PIERS 3 -#define AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS 3 -#define AR5416_EEP4K_NUM_2G_20_TARGET_POWERS 3 -#define AR5416_EEP4K_NUM_2G_40_TARGET_POWERS 3 -#define AR5416_EEP4K_NUM_CTLS 12 -#define AR5416_EEP4K_NUM_BAND_EDGES 4 -#define AR5416_EEP4K_NUM_PD_GAINS 2 -#define AR5416_EEP4K_PD_GAINS_IN_MASK 4 -#define AR5416_EEP4K_PD_GAIN_ICEPTS 5 -#define AR5416_EEP4K_MAX_CHAINS 1 - -#define AR9280_TX_GAIN_TABLE_SIZE 22 - -#define AR9287_EEP_VER 0xE -#define AR9287_EEP_VER_MINOR_MASK 0xFFF -#define AR9287_EEP_MINOR_VER_1 0x1 -#define AR9287_EEP_MINOR_VER_2 0x2 -#define AR9287_EEP_MINOR_VER_3 0x3 -#define AR9287_EEP_MINOR_VER AR9287_EEP_MINOR_VER_3 -#define AR9287_EEP_MINOR_VER_b AR9287_EEP_MINOR_VER -#define AR9287_EEP_NO_BACK_VER AR9287_EEP_MINOR_VER_1 - -#define AR9287_EEP_START_LOC 128 -#define AR9287_NUM_2G_CAL_PIERS 3 -#define AR9287_NUM_2G_CCK_TARGET_POWERS 3 -#define AR9287_NUM_2G_20_TARGET_POWERS 3 -#define AR9287_NUM_2G_40_TARGET_POWERS 3 -#define AR9287_NUM_CTLS 12 -#define AR9287_NUM_BAND_EDGES 4 -#define AR9287_NUM_PD_GAINS 4 -#define AR9287_PD_GAINS_IN_MASK 4 -#define AR9287_PD_GAIN_ICEPTS 1 -#define AR9287_EEPROM_MODAL_SPURS 5 -#define AR9287_MAX_RATE_POWER 63 -#define AR9287_NUM_PDADC_VALUES 128 -#define AR9287_NUM_RATES 16 -#define AR9287_BCHAN_UNUSED 0xFF -#define AR9287_MAX_PWR_RANGE_IN_HALF_DB 64 -#define AR9287_OPFLAGS_11A 0x01 -#define AR9287_OPFLAGS_11G 0x02 -#define AR9287_OPFLAGS_2G_HT40 0x08 -#define AR9287_OPFLAGS_2G_HT20 0x20 -#define AR9287_OPFLAGS_5G_HT40 0x04 -#define AR9287_OPFLAGS_5G_HT20 0x10 -#define AR9287_EEPMISC_BIG_ENDIAN 0x01 -#define AR9287_EEPMISC_WOW 0x02 -#define AR9287_MAX_CHAINS 2 -#define AR9287_ANT_16S 32 -#define AR9287_custdatasize 20 - -#define AR9287_NUM_ANT_CHAIN_FIELDS 6 -#define AR9287_NUM_ANT_COMMON_FIELDS 4 -#define AR9287_SIZE_ANT_CHAIN_FIELD 2 -#define AR9287_SIZE_ANT_COMMON_FIELD 4 -#define AR9287_ANT_CHAIN_MASK 0x3 -#define AR9287_ANT_COMMON_MASK 0xf -#define AR9287_CHAIN_0_IDX 0 -#define AR9287_CHAIN_1_IDX 1 -#define AR9287_DATA_SZ 32 - -#define AR9287_PWR_TABLE_OFFSET_DB -5 - -#define AR9287_CHECKSUM_LOCATION (AR9287_EEP_START_LOC + 1) - -enum eeprom_param { - EEP_NFTHRESH_5, - EEP_NFTHRESH_2, - EEP_MAC_MSW, - EEP_MAC_MID, - EEP_MAC_LSW, - EEP_REG_0, - EEP_REG_1, - EEP_OP_CAP, - EEP_OP_MODE, - EEP_RF_SILENT, - EEP_OB_5, - EEP_DB_5, - EEP_OB_2, - EEP_DB_2, - EEP_MINOR_REV, - EEP_TX_MASK, - EEP_RX_MASK, - EEP_RXGAIN_TYPE, - EEP_TXGAIN_TYPE, - EEP_OL_PWRCTRL, - EEP_RC_CHAIN_MASK, - EEP_DAC_HPWR_5G, - EEP_FRAC_N_5G, - EEP_DEV_TYPE, - EEP_TEMPSENSE_SLOPE, - EEP_TEMPSENSE_SLOPE_PAL_ON, - EEP_PWR_TABLE_OFFSET -}; - -enum ar5416_rates { - rate6mb, rate9mb, rate12mb, rate18mb, - rate24mb, rate36mb, rate48mb, rate54mb, - rate1l, rate2l, rate2s, rate5_5l, - rate5_5s, rate11l, rate11s, rateXr, - rateHt20_0, rateHt20_1, rateHt20_2, rateHt20_3, - rateHt20_4, rateHt20_5, rateHt20_6, rateHt20_7, - rateHt40_0, rateHt40_1, rateHt40_2, rateHt40_3, - rateHt40_4, rateHt40_5, rateHt40_6, rateHt40_7, - rateDupCck, rateDupOfdm, rateExtCck, rateExtOfdm, - Ar5416RateSize -}; - -enum ath9k_hal_freq_band { - ATH9K_HAL_FREQ_BAND_5GHZ = 0, - ATH9K_HAL_FREQ_BAND_2GHZ = 1 -}; - -struct base_eep_header { - u16 length; - u16 checksum; - u16 version; - u8 opCapFlags; - u8 eepMisc; - u16 regDmn[2]; - u8 macAddr[6]; - u8 rxMask; - u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; - u8 deviceType; - u8 pwdclkind; - u8 futureBase_1[2]; - u8 rxGainType; - u8 dacHiPwrMode_5G; - u8 openLoopPwrCntl; - u8 dacLpMode; - u8 txGainType; - u8 rcChainMask; - u8 desiredScaleCCK; - u8 power_table_offset; - u8 frac_n_5g; - u8 futureBase_3[21]; -} __packed; - -struct base_eep_header_4k { - u16 length; - u16 checksum; - u16 version; - u8 opCapFlags; - u8 eepMisc; - u16 regDmn[2]; - u8 macAddr[6]; - u8 rxMask; - u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; - u8 deviceType; - u8 txGainType; -} __packed; - - -struct spur_chan { - u16 spurChan; - u8 spurRangeLow; - u8 spurRangeHigh; -} __packed; - -struct modal_eep_header { - u32 antCtrlChain[AR5416_MAX_CHAINS]; - u32 antCtrlCommon; - u8 antennaGainCh[AR5416_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR5416_MAX_CHAINS]; - u8 rxTxMarginCh[AR5416_MAX_CHAINS]; - u8 adcDesiredSize; - u8 pgaDesiredSize; - u8 xlnaGainCh[AR5416_MAX_CHAINS]; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - u8 noiseFloorThreshCh[AR5416_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - u8 iqCalICh[AR5416_MAX_CHAINS]; - u8 iqCalQCh[AR5416_MAX_CHAINS]; - u8 pdGainOverlap; - u8 ob; - u8 db; - u8 xpaBiasLvl; - u8 pwrDecreaseFor2Chain; - u8 pwrDecreaseFor3Chain; - u8 txFrameToDataStart; - u8 txFrameToPaOn; - u8 ht40PowerIncForPdadc; - u8 bswAtten[AR5416_MAX_CHAINS]; - u8 bswMargin[AR5416_MAX_CHAINS]; - u8 swSettleHt40; - u8 xatten2Db[AR5416_MAX_CHAINS]; - u8 xatten2Margin[AR5416_MAX_CHAINS]; - u8 ob_ch1; - u8 db_ch1; - u8 useAnt1:1, - force_xpaon:1, - local_bias:1, - femBandSelectUsed:1, xlnabufin:1, xlnaisel:2, xlnabufmode:1; - u8 miscBits; - u16 xpaBiasLvlFreq[3]; - u8 futureModal[6]; - - struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; -} __packed; - -struct calDataPerFreqOpLoop { - u8 pwrPdg[2][5]; - u8 vpdPdg[2][5]; - u8 pcdac[2][5]; - u8 empty[2][5]; -} __packed; - -struct modal_eep_4k_header { - u32 antCtrlChain[AR5416_EEP4K_MAX_CHAINS]; - u32 antCtrlCommon; - u8 antennaGainCh[AR5416_EEP4K_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR5416_EEP4K_MAX_CHAINS]; - u8 rxTxMarginCh[AR5416_EEP4K_MAX_CHAINS]; - u8 adcDesiredSize; - u8 pgaDesiredSize; - u8 xlnaGainCh[AR5416_EEP4K_MAX_CHAINS]; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - u8 noiseFloorThreshCh[AR5416_EEP4K_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - u8 iqCalICh[AR5416_EEP4K_MAX_CHAINS]; - u8 iqCalQCh[AR5416_EEP4K_MAX_CHAINS]; - u8 pdGainOverlap; -#ifdef __BIG_ENDIAN_BITFIELD - u8 ob_1:4, ob_0:4; - u8 db1_1:4, db1_0:4; -#else - u8 ob_0:4, ob_1:4; - u8 db1_0:4, db1_1:4; -#endif - u8 xpaBiasLvl; - u8 txFrameToDataStart; - u8 txFrameToPaOn; - u8 ht40PowerIncForPdadc; - u8 bswAtten[AR5416_EEP4K_MAX_CHAINS]; - u8 bswMargin[AR5416_EEP4K_MAX_CHAINS]; - u8 swSettleHt40; - u8 xatten2Db[AR5416_EEP4K_MAX_CHAINS]; - u8 xatten2Margin[AR5416_EEP4K_MAX_CHAINS]; -#ifdef __BIG_ENDIAN_BITFIELD - u8 db2_1:4, db2_0:4; -#else - u8 db2_0:4, db2_1:4; -#endif - u8 version; -#ifdef __BIG_ENDIAN_BITFIELD - u8 ob_3:4, ob_2:4; - u8 antdiv_ctl1:4, ob_4:4; - u8 db1_3:4, db1_2:4; - u8 antdiv_ctl2:4, db1_4:4; - u8 db2_2:4, db2_3:4; - u8 reserved:4, db2_4:4; -#else - u8 ob_2:4, ob_3:4; - u8 ob_4:4, antdiv_ctl1:4; - u8 db1_2:4, db1_3:4; - u8 db1_4:4, antdiv_ctl2:4; - u8 db2_2:4, db2_3:4; - u8 db2_4:4, reserved:4; -#endif - u8 futureModal[4]; - struct spur_chan spurChans[AR5416_EEPROM_MODAL_SPURS]; -} __packed; - -struct base_eep_ar9287_header { - u16 length; - u16 checksum; - u16 version; - u8 opCapFlags; - u8 eepMisc; - u16 regDmn[2]; - u8 macAddr[6]; - u8 rxMask; - u8 txMask; - u16 rfSilent; - u16 blueToothOptions; - u16 deviceCap; - u32 binBuildNumber; - u8 deviceType; - u8 openLoopPwrCntl; - int8_t pwrTableOffset; - int8_t tempSensSlope; - int8_t tempSensSlopePalOn; - u8 futureBase[29]; -} __packed; - -struct modal_eep_ar9287_header { - u32 antCtrlChain[AR9287_MAX_CHAINS]; - u32 antCtrlCommon; - int8_t antennaGainCh[AR9287_MAX_CHAINS]; - u8 switchSettling; - u8 txRxAttenCh[AR9287_MAX_CHAINS]; - u8 rxTxMarginCh[AR9287_MAX_CHAINS]; - int8_t adcDesiredSize; - u8 txEndToXpaOff; - u8 txEndToRxOn; - u8 txFrameToXpaOn; - u8 thresh62; - int8_t noiseFloorThreshCh[AR9287_MAX_CHAINS]; - u8 xpdGain; - u8 xpd; - int8_t iqCalICh[AR9287_MAX_CHAINS]; - int8_t iqCalQCh[AR9287_MAX_CHAINS]; - u8 pdGainOverlap; - u8 xpaBiasLvl; - u8 txFrameToDataStart; - u8 txFrameToPaOn; - u8 ht40PowerIncForPdadc; - u8 bswAtten[AR9287_MAX_CHAINS]; - u8 bswMargin[AR9287_MAX_CHAINS]; - u8 swSettleHt40; - u8 version; - u8 db1; - u8 db2; - u8 ob_cck; - u8 ob_psk; - u8 ob_qam; - u8 ob_pal_off; - u8 futureModal[30]; - struct spur_chan spurChans[AR9287_EEPROM_MODAL_SPURS]; -} __packed; - -struct cal_data_per_freq { - u8 pwrPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR5416_NUM_PD_GAINS][AR5416_PD_GAIN_ICEPTS]; -} __packed; - -struct cal_data_per_freq_4k { - u8 pwrPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR5416_EEP4K_NUM_PD_GAINS][AR5416_EEP4K_PD_GAIN_ICEPTS]; -} __packed; - -struct cal_target_power_leg { - u8 bChannel; - u8 tPow2x[4]; -} __packed; - -struct cal_target_power_ht { - u8 bChannel; - u8 tPow2x[8]; -} __packed; - - -#ifdef __BIG_ENDIAN_BITFIELD -struct cal_ctl_edges { - u8 bChannel; - u8 flag:2, tPower:6; -} __packed; -#else -struct cal_ctl_edges { - u8 bChannel; - u8 tPower:6, flag:2; -} __packed; -#endif - -struct cal_data_op_loop_ar9287 { - u8 pwrPdg[2][5]; - u8 vpdPdg[2][5]; - u8 pcdac[2][5]; - u8 empty[2][5]; -} __packed; - -struct cal_data_per_freq_ar9287 { - u8 pwrPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; - u8 vpdPdg[AR9287_NUM_PD_GAINS][AR9287_PD_GAIN_ICEPTS]; -} __packed; - -union cal_data_per_freq_ar9287_u { - struct cal_data_op_loop_ar9287 calDataOpen; - struct cal_data_per_freq_ar9287 calDataClose; -} __packed; - -struct cal_ctl_data_ar9287 { - struct cal_ctl_edges - ctlEdges[AR9287_MAX_CHAINS][AR9287_NUM_BAND_EDGES]; -} __packed; - -struct cal_ctl_data { - struct cal_ctl_edges - ctlEdges[AR5416_MAX_CHAINS][AR5416_NUM_BAND_EDGES]; -} __packed; - -struct cal_ctl_data_4k { - struct cal_ctl_edges - ctlEdges[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_BAND_EDGES]; -} __packed; - -struct ar5416_eeprom_def { - struct base_eep_header baseEepHeader; - u8 custData[64]; - struct modal_eep_header modalHeader[2]; - u8 calFreqPier5G[AR5416_NUM_5G_CAL_PIERS]; - u8 calFreqPier2G[AR5416_NUM_2G_CAL_PIERS]; - struct cal_data_per_freq - calPierData5G[AR5416_MAX_CHAINS][AR5416_NUM_5G_CAL_PIERS]; - struct cal_data_per_freq - calPierData2G[AR5416_MAX_CHAINS][AR5416_NUM_2G_CAL_PIERS]; - struct cal_target_power_leg - calTargetPower5G[AR5416_NUM_5G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower5GHT20[AR5416_NUM_5G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower5GHT40[AR5416_NUM_5G_40_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPowerCck[AR5416_NUM_2G_CCK_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPower2G[AR5416_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT20[AR5416_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT40[AR5416_NUM_2G_40_TARGET_POWERS]; - u8 ctlIndex[AR5416_NUM_CTLS]; - struct cal_ctl_data ctlData[AR5416_NUM_CTLS]; - u8 padding; -} __packed; - -struct ar5416_eeprom_4k { - struct base_eep_header_4k baseEepHeader; - u8 custData[20]; - struct modal_eep_4k_header modalHeader; - u8 calFreqPier2G[AR5416_EEP4K_NUM_2G_CAL_PIERS]; - struct cal_data_per_freq_4k - calPierData2G[AR5416_EEP4K_MAX_CHAINS][AR5416_EEP4K_NUM_2G_CAL_PIERS]; - struct cal_target_power_leg - calTargetPowerCck[AR5416_EEP4K_NUM_2G_CCK_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPower2G[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT20[AR5416_EEP4K_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT40[AR5416_EEP4K_NUM_2G_40_TARGET_POWERS]; - u8 ctlIndex[AR5416_EEP4K_NUM_CTLS]; - struct cal_ctl_data_4k ctlData[AR5416_EEP4K_NUM_CTLS]; - u8 padding; -} __packed; - -struct ar9287_eeprom { - struct base_eep_ar9287_header baseEepHeader; - u8 custData[AR9287_DATA_SZ]; - struct modal_eep_ar9287_header modalHeader; - u8 calFreqPier2G[AR9287_NUM_2G_CAL_PIERS]; - union cal_data_per_freq_ar9287_u - calPierData2G[AR9287_MAX_CHAINS][AR9287_NUM_2G_CAL_PIERS]; - struct cal_target_power_leg - calTargetPowerCck[AR9287_NUM_2G_CCK_TARGET_POWERS]; - struct cal_target_power_leg - calTargetPower2G[AR9287_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT20[AR9287_NUM_2G_20_TARGET_POWERS]; - struct cal_target_power_ht - calTargetPower2GHT40[AR9287_NUM_2G_40_TARGET_POWERS]; - u8 ctlIndex[AR9287_NUM_CTLS]; - struct cal_ctl_data_ar9287 ctlData[AR9287_NUM_CTLS]; - u8 padding; -} __packed; - -enum reg_ext_bitmap { - REG_EXT_JAPAN_MIDBAND = 1, - REG_EXT_FCC_DFS_HT40 = 2, - REG_EXT_JAPAN_NONDFS_HT40 = 3, - REG_EXT_JAPAN_DFS_HT40 = 4 -}; - -struct ath9k_country_entry { - u16 countryCode; - u16 regDmnEnum; - u16 regDmn5G; - u16 regDmn2G; - u8 isMultidomain; - u8 iso[3]; -}; - -enum ath9k_eep_map { - EEP_MAP_DEFAULT = 0x0, - EEP_MAP_4KBITS, - EEP_MAP_AR9287, - EEP_MAP_MAX -}; - -struct eeprom_ops { - int (*check_eeprom)(struct ath_hw *hw); - u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param); - bool (*fill_eeprom)(struct ath_hw *hw); - int (*get_eeprom_ver)(struct ath_hw *hw); - int (*get_eeprom_rev)(struct ath_hw *hw); - u8 (*get_num_ant_config)(struct ath_hw *hw, enum ieee80211_band band); - u16 (*get_eeprom_antenna_cfg)(struct ath_hw *hw, - struct ath9k_channel *chan); - void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); - void (*set_addac)(struct ath_hw *hw, struct ath9k_channel *chan); - void (*set_txpower)(struct ath_hw *hw, struct ath9k_channel *chan, - u16 cfgCtl, u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, u8 powerLimit); - u16 (*get_spur_channel)(struct ath_hw *ah, u16 i, bool is2GHz); -}; - -void ath9k_hw_analog_shift_rmw(struct ath_hw *ah, u32 reg, u32 mask, - u32 shift, u32 val); -int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, - int16_t targetLeft, - int16_t targetRight); -bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, - u16 *indexL, u16 *indexR); -bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); -void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, - u8 *pVpdList, u16 numIntercepts, - u8 *pRetVpdList); -void ath9k_hw_get_legacy_target_powers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_target_power_leg *powInfo, - u16 numChannels, - struct cal_target_power_leg *pNewPower, - u16 numRates, bool isExtTarget); -void ath9k_hw_get_target_powers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_target_power_ht *powInfo, - u16 numChannels, - struct cal_target_power_ht *pNewPower, - u16 numRates, bool isHt40Target); -u16 ath9k_hw_get_max_edge_power(u16 freq, struct cal_ctl_edges *pRdEdgesPower, - bool is2GHz, int num_band_edges); -int ath9k_hw_eeprom_init(struct ath_hw *ah); - -#define ar5416_get_ntxchains(_txchainmask) \ - (((_txchainmask >> 2) & 1) + \ - ((_txchainmask >> 1) & 1) + (_txchainmask & 1)) - -extern const struct eeprom_ops eep_def_ops; -extern const struct eeprom_ops eep_4k_ops; -extern const struct eeprom_ops eep_AR9287_ops; - -#endif /* EEPROM_H */ diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c deleted file mode 100644 index b8eca7be5f3a..000000000000 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ /dev/null @@ -1,1188 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static int ath9k_hw_4k_get_eeprom_ver(struct ath_hw *ah) -{ - return ((ah->eeprom.map4k.baseEepHeader.version >> 12) & 0xF); -} - -static int ath9k_hw_4k_get_eeprom_rev(struct ath_hw *ah) -{ - return ((ah->eeprom.map4k.baseEepHeader.version) & 0xFFF); -} - -static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah) -{ -#define SIZE_EEPROM_4K (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) - u16 *eep_data = (u16 *)&ah->eeprom.map4k; - int addr, eep_start_loc = 0; - - eep_start_loc = 64; - - if (!ath9k_hw_use_flash(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Reading from EEPROM, not flash\n"); - } - - for (addr = 0; addr < SIZE_EEPROM_4K; addr++) { - if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Unable to read eeprom region \n"); - return false; - } - eep_data++; - } - - return true; -#undef SIZE_EEPROM_4K -} - -static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) -{ -#define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) - struct ar5416_eeprom_4k *eep = - (struct ar5416_eeprom_4k *) &ah->eeprom.map4k; - u16 *eepdata, temp, magic, magic2; - u32 sum = 0, el; - bool need_swap = false; - int i, addr; - - - if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, - &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Reading Magic # failed\n"); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); - - if (magic != AR5416_EEPROM_MAGIC) { - magic2 = swab16(magic); - - if (magic2 == AR5416_EEPROM_MAGIC) { - need_swap = true; - eepdata = (u16 *) (&ah->eeprom); - - for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { - temp = swab16(*eepdata); - *eepdata = temp; - eepdata++; - } - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "endianness mismatch.\n"); - return -EINVAL; - } - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); - - if (need_swap) - el = swab16(ah->eeprom.map4k.baseEepHeader.length); - else - el = ah->eeprom.map4k.baseEepHeader.length; - - if (el > sizeof(struct ar5416_eeprom_4k)) - el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); - else - el = el / sizeof(u16); - - eepdata = (u16 *)(&ah->eeprom); - - for (i = 0; i < el; i++) - sum ^= *eepdata++; - - if (need_swap) { - u32 integer; - u16 word; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing\n"); - - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - integer = swab32(eep->modalHeader.antCtrlCommon); - eep->modalHeader.antCtrlCommon = integer; - - for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { - integer = swab32(eep->modalHeader.antCtrlChain[i]); - eep->modalHeader.antCtrlChain[i] = integer; - } - - for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { - word = swab16(eep->modalHeader.spurChans[i].spurChan); - eep->modalHeader.spurChans[i].spurChan = word; - } - } - - if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || - ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); - return -EINVAL; - } - - return 0; -#undef EEPROM_4K_SIZE -} - -static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, - enum eeprom_param param) -{ - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &eep->modalHeader; - struct base_eep_header_4k *pBase = &eep->baseEepHeader; - - switch (param) { - case EEP_NFTHRESH_2: - return pModal->noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; - case EEP_REG_0: - return pBase->regDmn[0]; - case EEP_REG_1: - return pBase->regDmn[1]; - case EEP_OP_CAP: - return pBase->deviceCap; - case EEP_OP_MODE: - return pBase->opCapFlags; - case EEP_RF_SILENT: - return pBase->rfSilent; - case EEP_OB_2: - return pModal->ob_0; - case EEP_DB_2: - return pModal->db1_1; - case EEP_MINOR_REV: - return pBase->version & AR5416_EEP_VER_MINOR_MASK; - case EEP_TX_MASK: - return pBase->txMask; - case EEP_RX_MASK: - return pBase->rxMask; - case EEP_FRAC_N_5G: - return 0; - default: - return 0; - } -} - -static void ath9k_hw_get_4k_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq_4k *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ -#define TMP_VAL_VPD_TABLE \ - ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; - u8 maxPwrT4[AR5416_EEP4K_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; -#define PD_GAIN_BOUNDARY_DEFAULT 58; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), bChans, numPiers, - &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableI[i]); - } - } else { - for (i = 0; i < numXpdGains; i++) { - pVpdL = pRawDataSet[idxL].vpdPdg[i]; - pPwrL = pRawDataSet[idxL].pwrPdg[i]; - pVpdR = pRawDataSet[idxR].vpdPdg[i]; - pPwrR = pRawDataSet[idxR].pwrPdg[i]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR5416_EEP4K_PD_GAIN_ICEPTS - 1], - pPwrR[AR5416_EEP4K_PD_GAIN_ICEPTS - 1]); - - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR5416_EEP4K_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. - synth_center, - IS_CHAN_2GHZ - (chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); - - pPdGainBoundaries[i] = - min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else { - minDelta = 0; - } - - if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - ss = (int16_t)((pPdGainBoundaries[i - 1] - - (minPwrT4[i] / 2)) - - tPdGainOverlap + 1 + minDelta); - } - vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - - (minPwrT4[i] / 2)); - maxIndex = (tgtIndex < sizeCurrVpdTable) ? - tgtIndex : sizeCurrVpdTable; - - while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) - pPDADCValues[k++] = vpdTableI[i][ss++]; - - vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - - vpdTableI[i][sizeCurrVpdTable - 2]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - if (tgtIndex >= maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t) TMP_VAL_VPD_TABLE; - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - while (i < AR5416_EEP4K_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = PD_GAIN_BOUNDARY_DEFAULT; - i++; - } - - while (k < AR5416_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k - 1]; - k++; - } - - return; -#undef TMP_VAL_VPD_TABLE -} - -static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *pTxPowerIndexOffset) -{ - struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; - struct cal_data_per_freq_4k *pRawDataset; - u8 *pCalBChans = NULL; - u16 pdGainOverlap_t2; - static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR5416_EEP4K_PD_GAINS_IN_MASK]; - u16 numPiers, i, j; - int16_t tMinCalPower; - u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR5416_EEP4K_NUM_PD_GAINS] = { 0, 0 }; - u32 reg32, regOffset, regChainOffset; - - xpdMask = pEepData->modalHeader.xpdGain; - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - pdGainOverlap_t2 = - pEepData->modalHeader.pdGainOverlap; - } else { - pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); - } - - pCalBChans = pEepData->calFreqPier2G; - numPiers = AR5416_EEP4K_NUM_2G_CAL_PIERS; - - numXpdGain = 0; - - for (i = 1; i <= AR5416_EEP4K_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_EEP4K_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR5416_EEP4K_NUM_PD_GAINS) - break; - xpdGainValues[numXpdGain] = - (u16)(AR5416_EEP4K_PD_GAINS_IN_MASK - i); - numXpdGain++; - } - } - - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, - (numXpdGain - 1) & 0x3); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, - xpdGainValues[0]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, - xpdGainValues[1]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, 0); - - for (i = 0; i < AR5416_EEP4K_MAX_CHAINS; i++) { - if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) && - (i != 0)) { - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else - regChainOffset = i * 0x1000; - - if (pEepData->baseEepHeader.txMask & (1 << i)) { - pRawDataset = pEepData->calPierData2G[i]; - - ath9k_hw_get_4k_gain_boundaries_pdadcs(ah, chan, - pRawDataset, pCalBChans, - numPiers, pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, - pdadcValues, numXpdGain); - - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { - REG_WRITE(ah, AR_PHY_TPCRG5 + regChainOffset, - SM(pdGainOverlap_t2, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP) - | SM(gainBoundaries[0], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) - | SM(gainBoundaries[1], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) - | SM(gainBoundaries[2], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) - | SM(gainBoundaries[3], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); - } - - regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | - ((pdadcValues[4 * j + 1] & 0xFF) << 8) | - ((pdadcValues[4 * j + 2] & 0xFF) << 16)| - ((pdadcValues[4 * j + 3] & 0xFF) << 24); - REG_WRITE(ah, regOffset, reg32); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC: Chain %d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, pdadcValues[4 * j + 1], - 4 * j + 2, pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); - - regOffset += 4; - } - } - } - - *pTxPowerIndexOffset = 0; -} - -static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *ratesArray, - u16 cfgCtl, - u16 AntennaReduction, - u16 twiceMaxRegulatoryPower, - u16 powerLimit) -{ -#define CMP_TEST_GRP \ - (((cfgCtl & ~CTL_MODE_M)| (pCtlMode[ctlMode] & CTL_MODE_M)) == \ - pEepData->ctlIndex[i]) \ - || (((cfgCtl & ~CTL_MODE_M) | (pCtlMode[ctlMode] & CTL_MODE_M)) == \ - ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL)) - - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - int i; - int16_t twiceLargestAntenna; - u16 twiceMinEdgePower; - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 numCtlModes, *pCtlMode, ctlMode, freq; - struct chan_centers centers; - struct cal_ctl_data_4k *rep; - struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; - static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; - struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { - 0, { 0, 0, 0, 0} - }; - struct cal_target_power_leg targetPowerOfdmExt = { - 0, { 0, 0, 0, 0} }, targetPowerCckExt = { - 0, { 0, 0, 0, 0 } - }; - struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { - 0, {0, 0, 0, 0} - }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - twiceLargestAntenna = pEepData->modalHeader.antennaGainCh[0]; - twiceLargestAntenna = (int16_t)min(AntennaReduction - - twiceLargestAntenna, 0); - - maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { - maxRegAllowedPower -= - (tpScaleReductionTable[(regulatory->tp_scale)] * 2); - } - - scaledPower = min(powerLimit, maxRegAllowedPower); - scaledPower = max((u16)0, scaledPower); - - numCtlModes = ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; - pCtlMode = ctlModesFor11g; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCck, 4, false); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT20, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT40, - AR5416_NUM_2G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCckExt, 4, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - - for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || - (pCtlMode[ctlMode] == CTL_2GHT40); - - if (isHt40CtlMode) - freq = centers.synth_center; - else if (pCtlMode[ctlMode] & EXT_ADDITIVE) - freq = centers.ext_center; - else - freq = centers.ctl_center; - - if (ah->eep_ops->get_eeprom_ver(ah) == 14 && - ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - - for (i = 0; (i < AR5416_EEP4K_NUM_CTLS) && - pEepData->ctlIndex[i]; i++) { - - if (CMP_TEST_GRP) { - rep = &(pEepData->ctlData[i]); - - twiceMinEdgePower = ath9k_hw_get_max_edge_power( - freq, - rep->ctlEdges[ - ar5416_get_ntxchains(ah->txchainmask) - 1], - IS_CHAN_2GHZ(chan), - AR5416_EEP4K_NUM_BAND_EDGES); - - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { - twiceMaxEdgePower = - min(twiceMaxEdgePower, - twiceMinEdgePower); - } else { - twiceMaxEdgePower = twiceMinEdgePower; - break; - } - } - } - - minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - - switch (pCtlMode[ctlMode]) { - case CTL_11B: - for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { - targetPowerCck.tPow2x[i] = - min((u16)targetPowerCck.tPow2x[i], - minCtlPower); - } - break; - case CTL_11G: - for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { - targetPowerOfdm.tPow2x[i] = - min((u16)targetPowerOfdm.tPow2x[i], - minCtlPower); - } - break; - case CTL_2GHT20: - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { - targetPowerHt20.tPow2x[i] = - min((u16)targetPowerHt20.tPow2x[i], - minCtlPower); - } - break; - case CTL_11B_EXT: - targetPowerCckExt.tPow2x[0] = - min((u16)targetPowerCckExt.tPow2x[0], - minCtlPower); - break; - case CTL_11G_EXT: - targetPowerOfdmExt.tPow2x[0] = - min((u16)targetPowerOfdmExt.tPow2x[0], - minCtlPower); - break; - case CTL_2GHT40: - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - targetPowerHt40.tPow2x[i] = - min((u16)targetPowerHt40.tPow2x[i], - minCtlPower); - } - break; - default: - break; - } - } - - ratesArray[rate6mb] = - ratesArray[rate9mb] = - ratesArray[rate12mb] = - ratesArray[rate18mb] = - ratesArray[rate24mb] = - targetPowerOfdm.tPow2x[0]; - - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; - - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = targetPowerCck.tPow2x[3]; - - if (IS_CHAN_HT40(chan)) { - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - ratesArray[rateHt40_0 + i] = - targetPowerHt40.tPow2x[i]; - } - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; - } - -#undef CMP_TEST_GRP -} - -static void ath9k_hw_4k_set_txpower(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 cfgCtl, - u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, - u8 powerLimit) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &pEepData->modalHeader; - int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; - u8 ht40PowerIncForPdadc = 2; - int i; - - memset(ratesArray, 0, sizeof(ratesArray)); - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } - - ath9k_hw_set_4k_power_per_rate_table(ah, chan, - &ratesArray[0], cfgCtl, - twiceAntennaReduction, - twiceMaxRegulatoryPower, - powerLimit); - - ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); - - for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { - ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; - } - - - /* Update regulatory */ - - i = rate6mb; - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - regulatory->max_power_level = ratesArray[i]; - - if (AR_SREV_9280_10_OR_LATER(ah)) { - for (i = 0; i < Ar5416RateSize; i++) - ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; - } - - /* OFDM power per rate */ - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) - | ATH9K_POW_SM(ratesArray[rate12mb], 16) - | ATH9K_POW_SM(ratesArray[rate9mb], 8) - | ATH9K_POW_SM(ratesArray[rate6mb], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, - ATH9K_POW_SM(ratesArray[rate54mb], 24) - | ATH9K_POW_SM(ratesArray[rate48mb], 16) - | ATH9K_POW_SM(ratesArray[rate36mb], 8) - | ATH9K_POW_SM(ratesArray[rate24mb], 0)); - - /* CCK power per rate */ - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(ratesArray[rate2s], 24) - | ATH9K_POW_SM(ratesArray[rate2l], 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(ratesArray[rate1l], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(ratesArray[rate11s], 24) - | ATH9K_POW_SM(ratesArray[rate11l], 16) - | ATH9K_POW_SM(ratesArray[rate5_5s], 8) - | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); - - /* HT20 power per rate */ - REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, - ATH9K_POW_SM(ratesArray[rateHt20_3], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, - ATH9K_POW_SM(ratesArray[rateHt20_7], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); - - /* HT40 power per rate */ - if (IS_CHAN_HT40(chan)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - ATH9K_POW_SM(ratesArray[rateHt40_3] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_2] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_1] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_0] + - ht40PowerIncForPdadc, 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - ATH9K_POW_SM(ratesArray[rateHt40_7] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_6] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_5] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_4] + - ht40PowerIncForPdadc, 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(ratesArray[rateExtCck], 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); - } -} - -static void ath9k_hw_4k_set_addac(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct modal_eep_4k_header *pModal; - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - u8 biaslevel; - - if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) - return; - - if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) - return; - - pModal = &eep->modalHeader; - - if (pModal->xpaBiasLvl != 0xff) { - biaslevel = pModal->xpaBiasLvl; - INI_RA(&ah->iniAddac, 7, 1) = - (INI_RA(&ah->iniAddac, 7, 1) & (~0x18)) | biaslevel << 3; - } -} - -static void ath9k_hw_4k_set_gain(struct ath_hw *ah, - struct modal_eep_4k_header *pModal, - struct ar5416_eeprom_4k *eep, - u8 txRxAttenLocal) -{ - REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0, - pModal->antCtrlChain[0]); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), - (REG_READ(ah, AR_PHY_TIMING_CTRL4(0)) & - ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[0], AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { - txRxAttenLocal = pModal->txRxAttenCh[0]; - - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, pModal->bswMargin[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal->xatten2Margin[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, pModal->xatten2Db[0]); - - /* Set the block 1 value to block 0 value */ - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, - pModal->bswMargin[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, pModal->bswAtten[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal->xatten2Margin[0]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + 0x1000, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, - pModal->xatten2Db[0]); - } - - REG_RMW_FIELD(ah, AR_PHY_RXGAIN, - AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); - REG_RMW_FIELD(ah, AR_PHY_RXGAIN, - AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); - - REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, - AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); - REG_RMW_FIELD(ah, AR_PHY_RXGAIN + 0x1000, - AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[0]); - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, (AR9285_AN_TOP4_DEFAULT | 0x14)); -} - -/* - * Read EEPROM header info and program the device for correct operation - * given the channel value. - */ -static void ath9k_hw_4k_set_board_values(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct modal_eep_4k_header *pModal; - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - u8 txRxAttenLocal; - u8 ob[5], db1[5], db2[5]; - u8 ant_div_control1, ant_div_control2; - u32 regVal; - - pModal = &eep->modalHeader; - txRxAttenLocal = 23; - - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); - - /* Single chain for 4K EEPROM*/ - ath9k_hw_4k_set_gain(ah, pModal, eep, txRxAttenLocal); - - /* Initialize Ant Diversity settings from EEPROM */ - if (pModal->version >= 3) { - ant_div_control1 = pModal->antdiv_ctl1; - ant_div_control2 = pModal->antdiv_ctl2; - - regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); - regVal &= (~(AR_PHY_9285_ANT_DIV_CTL_ALL)); - - regVal |= SM(ant_div_control1, - AR_PHY_9285_ANT_DIV_CTL); - regVal |= SM(ant_div_control2, - AR_PHY_9285_ANT_DIV_ALT_LNACONF); - regVal |= SM((ant_div_control2 >> 2), - AR_PHY_9285_ANT_DIV_MAIN_LNACONF); - regVal |= SM((ant_div_control1 >> 1), - AR_PHY_9285_ANT_DIV_ALT_GAINTB); - regVal |= SM((ant_div_control1 >> 2), - AR_PHY_9285_ANT_DIV_MAIN_GAINTB); - - - REG_WRITE(ah, AR_PHY_MULTICHAIN_GAIN_CTL, regVal); - regVal = REG_READ(ah, AR_PHY_MULTICHAIN_GAIN_CTL); - regVal = REG_READ(ah, AR_PHY_CCK_DETECT); - regVal &= (~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); - regVal |= SM((ant_div_control1 >> 3), - AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV); - - REG_WRITE(ah, AR_PHY_CCK_DETECT, regVal); - regVal = REG_READ(ah, AR_PHY_CCK_DETECT); - } - - if (pModal->version >= 2) { - ob[0] = pModal->ob_0; - ob[1] = pModal->ob_1; - ob[2] = pModal->ob_2; - ob[3] = pModal->ob_3; - ob[4] = pModal->ob_4; - - db1[0] = pModal->db1_0; - db1[1] = pModal->db1_1; - db1[2] = pModal->db1_2; - db1[3] = pModal->db1_3; - db1[4] = pModal->db1_4; - - db2[0] = pModal->db2_0; - db2[1] = pModal->db2_1; - db2[2] = pModal->db2_2; - db2[3] = pModal->db2_3; - db2[4] = pModal->db2_4; - } else if (pModal->version == 1) { - ob[0] = pModal->ob_0; - ob[1] = ob[2] = ob[3] = ob[4] = pModal->ob_1; - db1[0] = pModal->db1_0; - db1[1] = db1[2] = db1[3] = db1[4] = pModal->db1_1; - db2[0] = pModal->db2_0; - db2[1] = db2[2] = db2[3] = db2[4] = pModal->db2_1; - } else { - int i; - - for (i = 0; i < 5; i++) { - ob[i] = pModal->ob_0; - db1[i] = pModal->db1_0; - db2[i] = pModal->db1_0; - } - } - - if (AR_SREV_9271(ah)) { - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9271_AN_RF2G3_OB_cck, - AR9271_AN_RF2G3_OB_cck_S, - ob[0]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9271_AN_RF2G3_OB_psk, - AR9271_AN_RF2G3_OB_psk_S, - ob[1]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9271_AN_RF2G3_OB_qam, - AR9271_AN_RF2G3_OB_qam_S, - ob[2]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9271_AN_RF2G3_DB_1, - AR9271_AN_RF2G3_DB_1_S, - db1[0]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9271_AN_RF2G4_DB_2, - AR9271_AN_RF2G4_DB_2_S, - db2[0]); - } else { - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_0, - AR9285_AN_RF2G3_OB_0_S, - ob[0]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_1, - AR9285_AN_RF2G3_OB_1_S, - ob[1]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_2, - AR9285_AN_RF2G3_OB_2_S, - ob[2]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_3, - AR9285_AN_RF2G3_OB_3_S, - ob[3]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_OB_4, - AR9285_AN_RF2G3_OB_4_S, - ob[4]); - - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_DB1_0, - AR9285_AN_RF2G3_DB1_0_S, - db1[0]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_DB1_1, - AR9285_AN_RF2G3_DB1_1_S, - db1[1]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G3, - AR9285_AN_RF2G3_DB1_2, - AR9285_AN_RF2G3_DB1_2_S, - db1[2]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB1_3, - AR9285_AN_RF2G4_DB1_3_S, - db1[3]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB1_4, - AR9285_AN_RF2G4_DB1_4_S, db1[4]); - - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_0, - AR9285_AN_RF2G4_DB2_0_S, - db2[0]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_1, - AR9285_AN_RF2G4_DB2_1_S, - db2[1]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_2, - AR9285_AN_RF2G4_DB2_2_S, - db2[2]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_3, - AR9285_AN_RF2G4_DB2_3_S, - db2[3]); - ath9k_hw_analog_shift_rmw(ah, - AR9285_AN_RF2G4, - AR9285_AN_RF2G4_DB2_4, - AR9285_AN_RF2G4_DB2_4_S, - db2[4]); - } - - - if (AR_SREV_9285_11(ah)) - REG_WRITE(ah, AR9285_AN_TOP4, AR9285_AN_TOP4_DEFAULT); - - REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, - pModal->switchSettling); - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, - pModal->adcDesiredSize); - - REG_WRITE(ah, AR_PHY_RF_CTL4, - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) | - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) | - SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) | - SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - - REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, - pModal->txEndToRxOn); - REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, - pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, AR_PHY_EXT_CCA0_THRESH62, - pModal->thresh62); - - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_DATA_START, - pModal->txFrameToDataStart); - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, - pModal->txFrameToPaOn); - } - - if ((eep->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_3) { - if (IS_CHAN_HT40(chan)) - REG_RMW_FIELD(ah, AR_PHY_SETTLING, - AR_PHY_SETTLING_SWITCH, - pModal->swSettleHt40); - } -} - -static u16 ath9k_hw_4k_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; - struct modal_eep_4k_header *pModal = &eep->modalHeader; - - return pModal->antCtrlCommon & 0xFFFF; -} - -static u8 ath9k_hw_4k_get_num_ant_config(struct ath_hw *ah, - enum ieee80211_band freq_band) -{ - return 1; -} - -static u16 ath9k_hw_4k_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -{ -#define EEP_MAP4K_SPURCHAN \ - (ah->eeprom.map4k.modalHeader.spurChans[i].spurChan) - - u16 spur_val = AR_NO_SPUR; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); - - switch (ah->config.spurmode) { - case SPUR_DISABLE: - break; - case SPUR_ENABLE_IOCTL: - spur_val = ah->config.spurchans[i][is2GHz]; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); - break; - case SPUR_ENABLE_EEPROM: - spur_val = EEP_MAP4K_SPURCHAN; - break; - } - - return spur_val; - -#undef EEP_MAP4K_SPURCHAN -} - -const struct eeprom_ops eep_4k_ops = { - .check_eeprom = ath9k_hw_4k_check_eeprom, - .get_eeprom = ath9k_hw_4k_get_eeprom, - .fill_eeprom = ath9k_hw_4k_fill_eeprom, - .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, - .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_4k_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_4k_get_eeprom_antenna_cfg, - .set_board_values = ath9k_hw_4k_set_board_values, - .set_addac = ath9k_hw_4k_set_addac, - .set_txpower = ath9k_hw_4k_set_txpower, - .get_spur_channel = ath9k_hw_4k_get_spur_channel -}; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c deleted file mode 100644 index c20c21a79b21..000000000000 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ /dev/null @@ -1,1177 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static int ath9k_hw_AR9287_get_eeprom_ver(struct ath_hw *ah) -{ - return (ah->eeprom.map9287.baseEepHeader.version >> 12) & 0xF; -} - -static int ath9k_hw_AR9287_get_eeprom_rev(struct ath_hw *ah) -{ - return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF; -} - -static bool ath9k_hw_AR9287_fill_eeprom(struct ath_hw *ah) -{ - struct ar9287_eeprom *eep = &ah->eeprom.map9287; - u16 *eep_data; - int addr, eep_start_loc = AR9287_EEP_START_LOC; - eep_data = (u16 *)eep; - - if (!ath9k_hw_use_flash(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Reading from EEPROM, not flash\n"); - } - - for (addr = 0; addr < sizeof(struct ar9287_eeprom) / sizeof(u16); - addr++) { - if (!ath9k_hw_nvram_read(ah, addr + eep_start_loc, eep_data)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Unable to read eeprom region \n"); - return false; - } - eep_data++; - } - return true; -} - -static int ath9k_hw_AR9287_check_eeprom(struct ath_hw *ah) -{ - u32 sum = 0, el, integer; - u16 temp, word, magic, magic2, *eepdata; - int i, addr; - bool need_swap = false; - struct ar9287_eeprom *eep = &ah->eeprom.map9287; - - if (!ath9k_hw_use_flash(ah)) { - if (!ath9k_hw_nvram_read - (ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Reading Magic # failed\n"); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); - if (magic != AR5416_EEPROM_MAGIC) { - magic2 = swab16(magic); - - if (magic2 == AR5416_EEPROM_MAGIC) { - need_swap = true; - eepdata = (u16 *)(&ah->eeprom); - - for (addr = 0; - addr < sizeof(struct ar9287_eeprom) / sizeof(u16); - addr++) { - temp = swab16(*eepdata); - *eepdata = temp; - eepdata++; - } - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "endianness mismatch.\n"); - return -EINVAL; - } - } - } - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", need_swap ? - "True" : "False"); - - if (need_swap) - el = swab16(ah->eeprom.map9287.baseEepHeader.length); - else - el = ah->eeprom.map9287.baseEepHeader.length; - - if (el > sizeof(struct ar9287_eeprom)) - el = sizeof(struct ar9287_eeprom) / sizeof(u16); - else - el = el / sizeof(u16); - - eepdata = (u16 *)(&ah->eeprom); - for (i = 0; i < el; i++) - sum ^= *eepdata++; - - if (need_swap) { - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - integer = swab32(eep->modalHeader.antCtrlCommon); - eep->modalHeader.antCtrlCommon = integer; - - for (i = 0; i < AR9287_MAX_CHAINS; i++) { - integer = swab32(eep->modalHeader.antCtrlChain[i]); - eep->modalHeader.antCtrlChain[i] = integer; - } - - for (i = 0; i < AR9287_EEPROM_MODAL_SPURS; i++) { - word = swab16(eep->modalHeader.spurChans[i].spurChan); - eep->modalHeader.spurChans[i].spurChan = word; - } - } - - if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER - || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); - return -EINVAL; - } - - return 0; -} - -static u32 ath9k_hw_AR9287_get_eeprom(struct ath_hw *ah, - enum eeprom_param param) -{ - struct ar9287_eeprom *eep = &ah->eeprom.map9287; - struct modal_eep_ar9287_header *pModal = &eep->modalHeader; - struct base_eep_ar9287_header *pBase = &eep->baseEepHeader; - u16 ver_minor; - - ver_minor = pBase->version & AR9287_EEP_VER_MINOR_MASK; - switch (param) { - case EEP_NFTHRESH_2: - return pModal->noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; - case EEP_REG_0: - return pBase->regDmn[0]; - case EEP_REG_1: - return pBase->regDmn[1]; - case EEP_OP_CAP: - return pBase->deviceCap; - case EEP_OP_MODE: - return pBase->opCapFlags; - case EEP_RF_SILENT: - return pBase->rfSilent; - case EEP_MINOR_REV: - return ver_minor; - case EEP_TX_MASK: - return pBase->txMask; - case EEP_RX_MASK: - return pBase->rxMask; - case EEP_DEV_TYPE: - return pBase->deviceType; - case EEP_OL_PWRCTRL: - return pBase->openLoopPwrCntl; - case EEP_TEMPSENSE_SLOPE: - if (ver_minor >= AR9287_EEP_MINOR_VER_2) - return pBase->tempSensSlope; - else - return 0; - case EEP_TEMPSENSE_SLOPE_PAL_ON: - if (ver_minor >= AR9287_EEP_MINOR_VER_3) - return pBase->tempSensSlopePalOn; - else - return 0; - default: - return 0; - } -} - - -static void ath9k_hw_get_AR9287_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq_ar9287 *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ -#define TMP_VAL_VPD_TABLE \ - ((vpdTableI[i][sizeCurrVpdTable - 1] + (ss - maxIndex + 1) * vpdStep)); - - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR9287_NUM_PD_GAINS]; - u8 maxPwrT4[AR9287_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; - static u8 vpdTableL[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_EEP4K_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR9287_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), bChans, numPiers, - &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR9287_PD_GAIN_ICEPTS, vpdTableI[i]); - } - } else { - for (i = 0; i < numXpdGains; i++) { - pVpdL = pRawDataSet[idxL].vpdPdg[i]; - pPwrL = pRawDataSet[idxL].pwrPdg[i]; - pVpdR = pRawDataSet[idxR].vpdPdg[i]; - pPwrR = pRawDataSet[idxR].pwrPdg[i]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR9287_PD_GAIN_ICEPTS - 1], - pPwrR[AR9287_PD_GAIN_ICEPTS - 1]); - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR9287_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR9287_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. synth_center, - IS_CHAN_2GHZ(chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - - k = 0; - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = (u16)((maxPwrT4[i] + - minPwrT4[i+1]) / 4); - - pPdGainBoundaries[i] = min((u16)AR5416_MAX_RATE_POWER, - pPdGainBoundaries[i]); - - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else - minDelta = 0; - - if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else - ss = (int16_t)((pPdGainBoundaries[i-1] - - (minPwrT4[i] / 2)) - - tPdGainOverlap + 1 + minDelta); - - vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - while ((ss < 0) && (k < (AR9287_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8)((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(pPdGainBoundaries[i] + - tPdGainOverlap - (minPwrT4[i] / 2)); - maxIndex = (tgtIndex < sizeCurrVpdTable) ? - tgtIndex : sizeCurrVpdTable; - - while ((ss < maxIndex) && (k < (AR9287_NUM_PDADC_VALUES - 1))) - pPDADCValues[k++] = vpdTableI[i][ss++]; - - vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - - vpdTableI[i][sizeCurrVpdTable - 2]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - if (tgtIndex > maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR9287_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t) TMP_VAL_VPD_TABLE; - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - while (i < AR9287_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = pPdGainBoundaries[i-1]; - i++; - } - - while (k < AR9287_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k-1]; - k++; - } - -#undef TMP_VAL_VPD_TABLE -} - -static void ar9287_eeprom_get_tx_gain_index(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_op_loop_ar9287 *pRawDatasetOpLoop, - u8 *pCalChans, u16 availPiers, - int8_t *pPwr) -{ - u16 idxL = 0, idxR = 0, numPiers; - bool match; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (pCalChans[numPiers] == AR9287_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), - pCalChans, numPiers, - &idxL, &idxR); - - if (match) { - *pPwr = (int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0]; - } else { - *pPwr = ((int8_t) pRawDatasetOpLoop[idxL].pwrPdg[0][0] + - (int8_t) pRawDatasetOpLoop[idxR].pwrPdg[0][0])/2; - } - -} - -static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah, - int32_t txPower, u16 chain) -{ - u32 tmpVal; - u32 a; - - tmpVal = REG_READ(ah, 0xa270); - tmpVal = tmpVal & 0xFCFFFFFF; - tmpVal = tmpVal | (0x3 << 24); - REG_WRITE(ah, 0xa270, tmpVal); - - tmpVal = REG_READ(ah, 0xb270); - tmpVal = tmpVal & 0xFCFFFFFF; - tmpVal = tmpVal | (0x3 << 24); - REG_WRITE(ah, 0xb270, tmpVal); - - if (chain == 0) { - tmpVal = REG_READ(ah, 0xa398); - tmpVal = tmpVal & 0xff00ffff; - a = (txPower)&0xff; - tmpVal = tmpVal | (a << 16); - REG_WRITE(ah, 0xa398, tmpVal); - } - - if (chain == 1) { - tmpVal = REG_READ(ah, 0xb398); - tmpVal = tmpVal & 0xff00ffff; - a = (txPower)&0xff; - tmpVal = tmpVal | (a << 16); - REG_WRITE(ah, 0xb398, tmpVal); - } -} - -static void ath9k_hw_set_AR9287_power_cal_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *pTxPowerIndexOffset) -{ - struct cal_data_per_freq_ar9287 *pRawDataset; - struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; - u8 *pCalBChans = NULL; - u16 pdGainOverlap_t2; - u8 pdadcValues[AR9287_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR9287_PD_GAINS_IN_MASK]; - u16 numPiers = 0, i, j; - int16_t tMinCalPower; - u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR9287_NUM_PD_GAINS] = {0, 0, 0, 0}; - u32 reg32, regOffset, regChainOffset; - int16_t modalIdx, diff = 0; - struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; - modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; - xpdMask = pEepData->modalHeader.xpdGain; - if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= - AR9287_EEP_MINOR_VER_2) - pdGainOverlap_t2 = pEepData->modalHeader.pdGainOverlap; - else - pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); - - if (IS_CHAN_2GHZ(chan)) { - pCalBChans = pEepData->calFreqPier2G; - numPiers = AR9287_NUM_2G_CAL_PIERS; - if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { - pRawDatasetOpenLoop = - (struct cal_data_op_loop_ar9287 *) - pEepData->calPierData2G[0]; - ah->initPDADC = pRawDatasetOpenLoop->vpdPdg[0][0]; - } - } - - numXpdGain = 0; - for (i = 1; i <= AR9287_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR9287_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR9287_NUM_PD_GAINS) - break; - xpdGainValues[numXpdGain] = - (u16)(AR9287_PD_GAINS_IN_MASK-i); - numXpdGain++; - } - } - - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, - (numXpdGain - 1) & 0x3); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, - xpdGainValues[0]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, - xpdGainValues[1]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, - xpdGainValues[2]); - - for (i = 0; i < AR9287_MAX_CHAINS; i++) { - regChainOffset = i * 0x1000; - if (pEepData->baseEepHeader.txMask & (1 << i)) { - pRawDatasetOpenLoop = (struct cal_data_op_loop_ar9287 *) - pEepData->calPierData2G[i]; - if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { - int8_t txPower; - ar9287_eeprom_get_tx_gain_index(ah, chan, - pRawDatasetOpenLoop, - pCalBChans, numPiers, - &txPower); - ar9287_eeprom_olpc_set_pdadcs(ah, txPower, i); - } else { - pRawDataset = - (struct cal_data_per_freq_ar9287 *) - pEepData->calPierData2G[i]; - ath9k_hw_get_AR9287_gain_boundaries_pdadcs( - ah, chan, pRawDataset, - pCalBChans, numPiers, - pdGainOverlap_t2, - &tMinCalPower, gainBoundaries, - pdadcValues, numXpdGain); - } - - if (i == 0) { - if (!ath9k_hw_AR9287_get_eeprom( - ah, EEP_OL_PWRCTRL)) { - REG_WRITE(ah, AR_PHY_TPCRG5 + - regChainOffset, - SM(pdGainOverlap_t2, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | - SM(gainBoundaries[0], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1) - | SM(gainBoundaries[1], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2) - | SM(gainBoundaries[2], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3) - | SM(gainBoundaries[3], - AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4)); - } - } - - if ((int32_t)AR9287_PWR_TABLE_OFFSET_DB != - pEepData->baseEepHeader.pwrTableOffset) { - diff = (u16) - (pEepData->baseEepHeader.pwrTableOffset - - (int32_t)AR9287_PWR_TABLE_OFFSET_DB); - diff *= 2; - - for (j = 0; - j < ((u16)AR9287_NUM_PDADC_VALUES-diff); - j++) - pdadcValues[j] = pdadcValues[j+diff]; - - for (j = (u16)(AR9287_NUM_PDADC_VALUES-diff); - j < AR9287_NUM_PDADC_VALUES; j++) - pdadcValues[j] = - pdadcValues[ - AR9287_NUM_PDADC_VALUES-diff]; - } - - if (!ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { - regOffset = AR_PHY_BASE + (672 << 2) + - regChainOffset; - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4*j + 0] - & 0xFF) << 0) | - ((pdadcValues[4*j + 1] - & 0xFF) << 8) | - ((pdadcValues[4*j + 2] - & 0xFF) << 16) | - ((pdadcValues[4*j + 3] - & 0xFF) << 24) ; - REG_WRITE(ah, regOffset, reg32); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC: Chain %d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d | " - "PDADC %3d Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, - pdadcValues[4 * j + 1], - 4 * j + 2, - pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); - - regOffset += 4; - } - } - } - } - - *pTxPowerIndexOffset = 0; -} - -static void ath9k_hw_set_AR9287_power_per_rate_table(struct ath_hw *ah, - struct ath9k_channel *chan, int16_t *ratesArray, u16 cfgCtl, - u16 AntennaReduction, u16 twiceMaxRegulatoryPower, - u16 powerLimit) -{ -#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 -#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 10 - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; - int i; - int16_t twiceLargestAntenna; - struct cal_ctl_data_ar9287 *rep; - struct cal_target_power_leg targetPowerOfdm = {0, {0, 0, 0, 0} }, - targetPowerCck = {0, {0, 0, 0, 0} }; - struct cal_target_power_leg targetPowerOfdmExt = {0, {0, 0, 0, 0} }, - targetPowerCckExt = {0, {0, 0, 0, 0} }; - struct cal_target_power_ht targetPowerHt20, - targetPowerHt40 = {0, {0, 0, 0, 0} }; - u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11g[] = - {CTL_11B, CTL_11G, CTL_2GHT20, - CTL_11B_EXT, CTL_11G_EXT, CTL_2GHT40}; - u16 numCtlModes = 0, *pCtlMode = NULL, ctlMode, freq; - struct chan_centers centers; - int tx_chainmask; - u16 twiceMinEdgePower; - struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; - tx_chainmask = ah->txchainmask; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - twiceLargestAntenna = max(pEepData->modalHeader.antennaGainCh[0], - pEepData->modalHeader.antennaGainCh[1]); - - twiceLargestAntenna = (int16_t)min((AntennaReduction) - - twiceLargestAntenna, 0); - - maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) - maxRegAllowedPower -= - (tpScaleReductionTable[(regulatory->tp_scale)] * 2); - - scaledPower = min(powerLimit, maxRegAllowedPower); - - switch (ar5416_get_ntxchains(tx_chainmask)) { - case 1: - break; - case 2: - scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; - break; - case 3: - scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; - break; - } - scaledPower = max((u16)0, scaledPower); - - if (IS_CHAN_2GHZ(chan)) { - numCtlModes = - ARRAY_SIZE(ctlModesFor11g) - SUB_NUM_CTL_MODES_AT_2G_40; - pCtlMode = ctlModesFor11g; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR9287_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCck, 4, false); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR9287_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT20, - AR9287_NUM_2G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT40, - AR9287_NUM_2G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR9287_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCckExt, 4, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR9287_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - } - - for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || - (pCtlMode[ctlMode] == CTL_2GHT40); - if (isHt40CtlMode) - freq = centers.synth_center; - else if (pCtlMode[ctlMode] & EXT_ADDITIVE) - freq = centers.ext_center; - else - freq = centers.ctl_center; - - if (ah->eep_ops->get_eeprom_ver(ah) == 14 && - ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - - for (i = 0; (i < AR9287_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - if ((((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - pEepData->ctlIndex[i]) || - (((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ((pEepData->ctlIndex[i] & - CTL_MODE_M) | SD_NO_CTL))) { - - rep = &(pEepData->ctlData[i]); - twiceMinEdgePower = ath9k_hw_get_max_edge_power( - freq, - rep->ctlEdges[ar5416_get_ntxchains( - tx_chainmask) - 1], - IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); - - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) - twiceMaxEdgePower = min( - twiceMaxEdgePower, - twiceMinEdgePower); - else { - twiceMaxEdgePower = twiceMinEdgePower; - break; - } - } - } - - minCtlPower = (u8)min(twiceMaxEdgePower, scaledPower); - - switch (pCtlMode[ctlMode]) { - case CTL_11B: - for (i = 0; - i < ARRAY_SIZE(targetPowerCck.tPow2x); - i++) { - targetPowerCck.tPow2x[i] = (u8)min( - (u16)targetPowerCck.tPow2x[i], - minCtlPower); - } - break; - case CTL_11A: - case CTL_11G: - for (i = 0; - i < ARRAY_SIZE(targetPowerOfdm.tPow2x); - i++) { - targetPowerOfdm.tPow2x[i] = (u8)min( - (u16)targetPowerOfdm.tPow2x[i], - minCtlPower); - } - break; - case CTL_5GHT20: - case CTL_2GHT20: - for (i = 0; - i < ARRAY_SIZE(targetPowerHt20.tPow2x); - i++) { - targetPowerHt20.tPow2x[i] = (u8)min( - (u16)targetPowerHt20.tPow2x[i], - minCtlPower); - } - break; - case CTL_11B_EXT: - targetPowerCckExt.tPow2x[0] = (u8)min( - (u16)targetPowerCckExt.tPow2x[0], - minCtlPower); - break; - case CTL_11A_EXT: - case CTL_11G_EXT: - targetPowerOfdmExt.tPow2x[0] = (u8)min( - (u16)targetPowerOfdmExt.tPow2x[0], - minCtlPower); - break; - case CTL_5GHT40: - case CTL_2GHT40: - for (i = 0; - i < ARRAY_SIZE(targetPowerHt40.tPow2x); - i++) { - targetPowerHt40.tPow2x[i] = (u8)min( - (u16)targetPowerHt40.tPow2x[i], - minCtlPower); - } - break; - default: - break; - } - } - - ratesArray[rate6mb] = - ratesArray[rate9mb] = - ratesArray[rate12mb] = - ratesArray[rate18mb] = - ratesArray[rate24mb] = - targetPowerOfdm.tPow2x[0]; - - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; - - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - - if (IS_CHAN_2GHZ(chan)) { - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = - targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = - targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = - targetPowerCck.tPow2x[3]; - } - if (IS_CHAN_HT40(chan)) { - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) - ratesArray[rateHt40_0 + i] = targetPowerHt40.tPow2x[i]; - - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - if (IS_CHAN_2GHZ(chan)) - ratesArray[rateExtCck] = targetPowerCckExt.tPow2x[0]; - } - -#undef REDUCE_SCALED_POWER_BY_TWO_CHAIN -#undef REDUCE_SCALED_POWER_BY_THREE_CHAIN -} - -static void ath9k_hw_AR9287_set_txpower(struct ath_hw *ah, - struct ath9k_channel *chan, u16 cfgCtl, - u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, - u8 powerLimit) -{ -#define INCREASE_MAXPOW_BY_TWO_CHAIN 6 -#define INCREASE_MAXPOW_BY_THREE_CHAIN 10 - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; - struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; - int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; - u8 ht40PowerIncForPdadc = 2; - int i; - - memset(ratesArray, 0, sizeof(ratesArray)); - - if ((pEepData->baseEepHeader.version & AR9287_EEP_VER_MINOR_MASK) >= - AR9287_EEP_MINOR_VER_2) - ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - - ath9k_hw_set_AR9287_power_per_rate_table(ah, chan, - &ratesArray[0], cfgCtl, - twiceAntennaReduction, - twiceMaxRegulatoryPower, - powerLimit); - - ath9k_hw_set_AR9287_power_cal_table(ah, chan, &txPowerIndexOffset); - - for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { - ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR9287_MAX_RATE_POWER) - ratesArray[i] = AR9287_MAX_RATE_POWER; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - for (i = 0; i < Ar5416RateSize; i++) - ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) - | ATH9K_POW_SM(ratesArray[rate12mb], 16) - | ATH9K_POW_SM(ratesArray[rate9mb], 8) - | ATH9K_POW_SM(ratesArray[rate6mb], 0)); - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, - ATH9K_POW_SM(ratesArray[rate54mb], 24) - | ATH9K_POW_SM(ratesArray[rate48mb], 16) - | ATH9K_POW_SM(ratesArray[rate36mb], 8) - | ATH9K_POW_SM(ratesArray[rate24mb], 0)); - - if (IS_CHAN_2GHZ(chan)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(ratesArray[rate2s], 24) - | ATH9K_POW_SM(ratesArray[rate2l], 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(ratesArray[rate1l], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(ratesArray[rate11s], 24) - | ATH9K_POW_SM(ratesArray[rate11l], 16) - | ATH9K_POW_SM(ratesArray[rate5_5s], 8) - | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, - ATH9K_POW_SM(ratesArray[rateHt20_3], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, - ATH9K_POW_SM(ratesArray[rateHt20_7], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); - - if (IS_CHAN_HT40(chan)) { - if (ath9k_hw_AR9287_get_eeprom(ah, EEP_OL_PWRCTRL)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - ATH9K_POW_SM(ratesArray[rateHt40_3], 24) - | ATH9K_POW_SM(ratesArray[rateHt40_2], 16) - | ATH9K_POW_SM(ratesArray[rateHt40_1], 8) - | ATH9K_POW_SM(ratesArray[rateHt40_0], 0)); - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - ATH9K_POW_SM(ratesArray[rateHt40_7], 24) - | ATH9K_POW_SM(ratesArray[rateHt40_6], 16) - | ATH9K_POW_SM(ratesArray[rateHt40_5], 8) - | ATH9K_POW_SM(ratesArray[rateHt40_4], 0)); - } else { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - ATH9K_POW_SM(ratesArray[rateHt40_3] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_2] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_1] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_0] + - ht40PowerIncForPdadc, 0)); - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - ATH9K_POW_SM(ratesArray[rateHt40_7] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_6] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_5] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_4] + - ht40PowerIncForPdadc, 0)); - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(ratesArray[rateExtCck], 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); - } - - if (IS_CHAN_2GHZ(chan)) - i = rate1l; - else - i = rate6mb; - - if (AR_SREV_9280_10_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR9287_PWR_TABLE_OFFSET_DB * 2; - else - regulatory->max_power_level = ratesArray[i]; - - switch (ar5416_get_ntxchains(ah->txchainmask)) { - case 1: - break; - case 2: - regulatory->max_power_level += - INCREASE_MAXPOW_BY_TWO_CHAIN; - break; - case 3: - regulatory->max_power_level += - INCREASE_MAXPOW_BY_THREE_CHAIN; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } -} - -static void ath9k_hw_AR9287_set_addac(struct ath_hw *ah, - struct ath9k_channel *chan) -{ -} - -static void ath9k_hw_AR9287_set_board_values(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar9287_eeprom *eep = &ah->eeprom.map9287; - struct modal_eep_ar9287_header *pModal = &eep->modalHeader; - u16 antWrites[AR9287_ANT_16S]; - u32 regChainOffset; - u8 txRxAttenLocal; - int i, j, offset_num; - - pModal = &eep->modalHeader; - - antWrites[0] = (u16)((pModal->antCtrlCommon >> 28) & 0xF); - antWrites[1] = (u16)((pModal->antCtrlCommon >> 24) & 0xF); - antWrites[2] = (u16)((pModal->antCtrlCommon >> 20) & 0xF); - antWrites[3] = (u16)((pModal->antCtrlCommon >> 16) & 0xF); - antWrites[4] = (u16)((pModal->antCtrlCommon >> 12) & 0xF); - antWrites[5] = (u16)((pModal->antCtrlCommon >> 8) & 0xF); - antWrites[6] = (u16)((pModal->antCtrlCommon >> 4) & 0xF); - antWrites[7] = (u16)(pModal->antCtrlCommon & 0xF); - - offset_num = 8; - - for (i = 0, j = offset_num; i < AR9287_MAX_CHAINS; i++) { - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 28) & 0xf); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 10) & 0x3); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 8) & 0x3); - antWrites[j++] = 0; - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 6) & 0x3); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 4) & 0x3); - antWrites[j++] = (u16)((pModal->antCtrlChain[i] >> 2) & 0x3); - antWrites[j++] = (u16)(pModal->antCtrlChain[i] & 0x3); - } - - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); - - for (i = 0; i < AR9287_MAX_CHAINS; i++) { - regChainOffset = i * 0x1000; - - REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, - pModal->antCtrlChain[i]); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, - (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) - & ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[i], - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[i], - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - - txRxAttenLocal = pModal->txRxAttenCh[i]; - - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, - pModal->bswMargin[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, - pModal->bswAtten[i]); - REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_ATTEN, - txRxAttenLocal); - REG_RMW_FIELD(ah, AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_MARGIN, - pModal->rxTxMarginCh[i]); - } - - - if (IS_CHAN_HT40(chan)) - REG_RMW_FIELD(ah, AR_PHY_SETTLING, - AR_PHY_SETTLING_SWITCH, pModal->swSettleHt40); - else - REG_RMW_FIELD(ah, AR_PHY_SETTLING, - AR_PHY_SETTLING_SWITCH, pModal->switchSettling); - - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_ADC, pModal->adcDesiredSize); - - REG_WRITE(ah, AR_PHY_RF_CTL4, - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) - | SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAB_OFF) - | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAA_ON) - | SM(pModal->txFrameToXpaOn, AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - - REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, - AR_PHY_TX_END_TO_A2_RX_ON, pModal->txEndToRxOn); - - REG_RMW_FIELD(ah, AR_PHY_CCA, - AR9280_PHY_CCA_THRESH62, pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, - AR_PHY_EXT_CCA0_THRESH62, pModal->thresh62); - - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB1, - AR9287_AN_RF2G3_DB1_S, pModal->db1); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, AR9287_AN_RF2G3_DB2, - AR9287_AN_RF2G3_DB2_S, pModal->db2); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_CCK, - AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_PSK, - AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_QAM, - AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH0, - AR9287_AN_RF2G3_OB_PAL_OFF, - AR9287_AN_RF2G3_OB_PAL_OFF_S, - pModal->ob_pal_off); - - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_DB1, AR9287_AN_RF2G3_DB1_S, - pModal->db1); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, AR9287_AN_RF2G3_DB2, - AR9287_AN_RF2G3_DB2_S, pModal->db2); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_CCK, - AR9287_AN_RF2G3_OB_CCK_S, pModal->ob_cck); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_PSK, - AR9287_AN_RF2G3_OB_PSK_S, pModal->ob_psk); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_QAM, - AR9287_AN_RF2G3_OB_QAM_S, pModal->ob_qam); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_RF2G3_CH1, - AR9287_AN_RF2G3_OB_PAL_OFF, - AR9287_AN_RF2G3_OB_PAL_OFF_S, - pModal->ob_pal_off); - - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, - AR_PHY_TX_END_DATA_START, pModal->txFrameToDataStart); - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, - AR_PHY_TX_END_PA_ON, pModal->txFrameToPaOn); - - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TOP2, - AR9287_AN_TOP2_XPABIAS_LVL, - AR9287_AN_TOP2_XPABIAS_LVL_S, - pModal->xpaBiasLvl); -} - -static u8 ath9k_hw_AR9287_get_num_ant_config(struct ath_hw *ah, - enum ieee80211_band freq_band) -{ - return 1; -} - -static u16 ath9k_hw_AR9287_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar9287_eeprom *eep = &ah->eeprom.map9287; - struct modal_eep_ar9287_header *pModal = &eep->modalHeader; - - return pModal->antCtrlCommon & 0xFFFF; -} - -static u16 ath9k_hw_AR9287_get_spur_channel(struct ath_hw *ah, - u16 i, bool is2GHz) -{ -#define EEP_MAP9287_SPURCHAN \ - (ah->eeprom.map9287.modalHeader.spurChans[i].spurChan) - u16 spur_val = AR_NO_SPUR; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); - - switch (ah->config.spurmode) { - case SPUR_DISABLE: - break; - case SPUR_ENABLE_IOCTL: - spur_val = ah->config.spurchans[i][is2GHz]; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); - break; - case SPUR_ENABLE_EEPROM: - spur_val = EEP_MAP9287_SPURCHAN; - break; - } - - return spur_val; - -#undef EEP_MAP9287_SPURCHAN -} - -const struct eeprom_ops eep_AR9287_ops = { - .check_eeprom = ath9k_hw_AR9287_check_eeprom, - .get_eeprom = ath9k_hw_AR9287_get_eeprom, - .fill_eeprom = ath9k_hw_AR9287_fill_eeprom, - .get_eeprom_ver = ath9k_hw_AR9287_get_eeprom_ver, - .get_eeprom_rev = ath9k_hw_AR9287_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_AR9287_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_AR9287_get_eeprom_antenna_cfg, - .set_board_values = ath9k_hw_AR9287_set_board_values, - .set_addac = ath9k_hw_AR9287_set_addac, - .set_txpower = ath9k_hw_AR9287_set_txpower, - .get_spur_channel = ath9k_hw_AR9287_get_spur_channel -}; diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c deleted file mode 100644 index 95105782794c..000000000000 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static void ath9k_get_txgain_index(struct ath_hw *ah, - struct ath9k_channel *chan, - struct calDataPerFreqOpLoop *rawDatasetOpLoop, - u8 *calChans, u16 availPiers, u8 *pwr, u8 *pcdacIdx) -{ - u8 pcdac, i = 0; - u16 idxL = 0, idxR = 0, numPiers; - bool match; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) - if (calChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - - match = ath9k_hw_get_lower_upper_index( - (u8)FREQ2FBIN(centers.synth_center, IS_CHAN_2GHZ(chan)), - calChans, numPiers, &idxL, &idxR); - if (match) { - pcdac = rawDatasetOpLoop[idxL].pcdac[0][0]; - *pwr = rawDatasetOpLoop[idxL].pwrPdg[0][0]; - } else { - pcdac = rawDatasetOpLoop[idxR].pcdac[0][0]; - *pwr = (rawDatasetOpLoop[idxL].pwrPdg[0][0] + - rawDatasetOpLoop[idxR].pwrPdg[0][0])/2; - } - - while (pcdac > ah->originalGain[i] && - i < (AR9280_TX_GAIN_TABLE_SIZE - 1)) - i++; - - *pcdacIdx = i; - return; -} - -static void ath9k_olc_get_pdadcs(struct ath_hw *ah, - u32 initTxGain, - int txPower, - u8 *pPDADCValues) -{ - u32 i; - u32 offset; - - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_0, - AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL6_1, - AR_PHY_TX_PWRCTRL_ERR_EST_MODE, 3); - - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL7, - AR_PHY_TX_PWRCTRL_INIT_TX_GAIN, initTxGain); - - offset = txPower; - for (i = 0; i < AR5416_NUM_PDADC_VALUES; i++) - if (i < offset) - pPDADCValues[i] = 0x0; - else - pPDADCValues[i] = 0xFF; -} - -static int ath9k_hw_def_get_eeprom_ver(struct ath_hw *ah) -{ - return ((ah->eeprom.def.baseEepHeader.version >> 12) & 0xF); -} - -static int ath9k_hw_def_get_eeprom_rev(struct ath_hw *ah) -{ - return ((ah->eeprom.def.baseEepHeader.version) & 0xFFF); -} - -static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) -{ -#define SIZE_EEPROM_DEF (sizeof(struct ar5416_eeprom_def) / sizeof(u16)) - u16 *eep_data = (u16 *)&ah->eeprom.def; - int addr, ar5416_eep_start_loc = 0x100; - - for (addr = 0; addr < SIZE_EEPROM_DEF; addr++) { - if (!ath9k_hw_nvram_read(ah, addr + ar5416_eep_start_loc, - eep_data)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unable to read eeprom region\n"); - return false; - } - eep_data++; - } - return true; -#undef SIZE_EEPROM_DEF -} - -static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) -{ - struct ar5416_eeprom_def *eep = - (struct ar5416_eeprom_def *) &ah->eeprom.def; - u16 *eepdata, temp, magic, magic2; - u32 sum = 0, el; - bool need_swap = false; - int i, addr, size; - - if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Reading Magic # failed\n"); - return false; - } - - if (!ath9k_hw_use_flash(ah)) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Read Magic = 0x%04X\n", magic); - - if (magic != AR5416_EEPROM_MAGIC) { - magic2 = swab16(magic); - - if (magic2 == AR5416_EEPROM_MAGIC) { - size = sizeof(struct ar5416_eeprom_def); - need_swap = true; - eepdata = (u16 *) (&ah->eeprom); - - for (addr = 0; addr < size / sizeof(u16); addr++) { - temp = swab16(*eepdata); - *eepdata = temp; - eepdata++; - } - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid EEPROM Magic. " - "Endianness mismatch.\n"); - return -EINVAL; - } - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, "need_swap = %s.\n", - need_swap ? "True" : "False"); - - if (need_swap) - el = swab16(ah->eeprom.def.baseEepHeader.length); - else - el = ah->eeprom.def.baseEepHeader.length; - - if (el > sizeof(struct ar5416_eeprom_def)) - el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); - else - el = el / sizeof(u16); - - eepdata = (u16 *)(&ah->eeprom); - - for (i = 0; i < el; i++) - sum ^= *eepdata++; - - if (need_swap) { - u32 integer, j; - u16 word; - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "EEPROM Endianness is not native.. Changing.\n"); - - word = swab16(eep->baseEepHeader.length); - eep->baseEepHeader.length = word; - - word = swab16(eep->baseEepHeader.checksum); - eep->baseEepHeader.checksum = word; - - word = swab16(eep->baseEepHeader.version); - eep->baseEepHeader.version = word; - - word = swab16(eep->baseEepHeader.regDmn[0]); - eep->baseEepHeader.regDmn[0] = word; - - word = swab16(eep->baseEepHeader.regDmn[1]); - eep->baseEepHeader.regDmn[1] = word; - - word = swab16(eep->baseEepHeader.rfSilent); - eep->baseEepHeader.rfSilent = word; - - word = swab16(eep->baseEepHeader.blueToothOptions); - eep->baseEepHeader.blueToothOptions = word; - - word = swab16(eep->baseEepHeader.deviceCap); - eep->baseEepHeader.deviceCap = word; - - for (j = 0; j < ARRAY_SIZE(eep->modalHeader); j++) { - struct modal_eep_header *pModal = - &eep->modalHeader[j]; - integer = swab32(pModal->antCtrlCommon); - pModal->antCtrlCommon = integer; - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - integer = swab32(pModal->antCtrlChain[i]); - pModal->antCtrlChain[i] = integer; - } - - for (i = 0; i < AR5416_EEPROM_MODAL_SPURS; i++) { - word = swab16(pModal->spurChans[i].spurChan); - pModal->spurChans[i].spurChan = word; - } - } - } - - if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || - ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Bad EEPROM checksum 0x%x or revision 0x%04x\n", - sum, ah->eep_ops->get_eeprom_ver(ah)); - return -EINVAL; - } - - return 0; -} - -static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, - enum eeprom_param param) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = eep->modalHeader; - struct base_eep_header *pBase = &eep->baseEepHeader; - - switch (param) { - case EEP_NFTHRESH_5: - return pModal[0].noiseFloorThreshCh[0]; - case EEP_NFTHRESH_2: - return pModal[1].noiseFloorThreshCh[0]; - case AR_EEPROM_MAC(0): - return pBase->macAddr[0] << 8 | pBase->macAddr[1]; - case AR_EEPROM_MAC(1): - return pBase->macAddr[2] << 8 | pBase->macAddr[3]; - case AR_EEPROM_MAC(2): - return pBase->macAddr[4] << 8 | pBase->macAddr[5]; - case EEP_REG_0: - return pBase->regDmn[0]; - case EEP_REG_1: - return pBase->regDmn[1]; - case EEP_OP_CAP: - return pBase->deviceCap; - case EEP_OP_MODE: - return pBase->opCapFlags; - case EEP_RF_SILENT: - return pBase->rfSilent; - case EEP_OB_5: - return pModal[0].ob; - case EEP_DB_5: - return pModal[0].db; - case EEP_OB_2: - return pModal[1].ob; - case EEP_DB_2: - return pModal[1].db; - case EEP_MINOR_REV: - return AR5416_VER_MASK; - case EEP_TX_MASK: - return pBase->txMask; - case EEP_RX_MASK: - return pBase->rxMask; - case EEP_RXGAIN_TYPE: - return pBase->rxGainType; - case EEP_TXGAIN_TYPE: - return pBase->txGainType; - case EEP_OL_PWRCTRL: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) - return pBase->openLoopPwrCntl ? true : false; - else - return false; - case EEP_RC_CHAIN_MASK: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) - return pBase->rcChainMask; - else - return 0; - case EEP_DAC_HPWR_5G: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) - return pBase->dacHiPwrMode_5G; - else - return 0; - case EEP_FRAC_N_5G: - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_22) - return pBase->frac_n_5g; - else - return 0; - default: - return 0; - } -} - -static void ath9k_hw_def_set_gain(struct ath_hw *ah, - struct modal_eep_header *pModal, - struct ar5416_eeprom_def *eep, - u8 txRxAttenLocal, int regChainOffset, int i) -{ - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { - txRxAttenLocal = pModal->txRxAttenCh[i]; - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN, - pModal->bswMargin[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN1_DB, - pModal->bswAtten[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN, - pModal->xatten2Margin[i]); - REG_RMW_FIELD(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - AR_PHY_GAIN_2GHZ_XATTEN2_DB, - pModal->xatten2Db[i]); - } else { - REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & - ~AR_PHY_GAIN_2GHZ_BSW_MARGIN) - | SM(pModal-> bswMargin[i], - AR_PHY_GAIN_2GHZ_BSW_MARGIN)); - REG_WRITE(ah, AR_PHY_GAIN_2GHZ + regChainOffset, - (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & - ~AR_PHY_GAIN_2GHZ_BSW_ATTEN) - | SM(pModal->bswAtten[i], - AR_PHY_GAIN_2GHZ_BSW_ATTEN)); - } - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, - AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_ATTEN, txRxAttenLocal); - REG_RMW_FIELD(ah, - AR_PHY_RXGAIN + regChainOffset, - AR9280_PHY_RXGAIN_TXRX_MARGIN, pModal->rxTxMarginCh[i]); - } else { - REG_WRITE(ah, - AR_PHY_RXGAIN + regChainOffset, - (REG_READ(ah, AR_PHY_RXGAIN + regChainOffset) & - ~AR_PHY_RXGAIN_TXRX_ATTEN) - | SM(txRxAttenLocal, AR_PHY_RXGAIN_TXRX_ATTEN)); - REG_WRITE(ah, - AR_PHY_GAIN_2GHZ + regChainOffset, - (REG_READ(ah, AR_PHY_GAIN_2GHZ + regChainOffset) & - ~AR_PHY_GAIN_2GHZ_RXTX_MARGIN) | - SM(pModal->rxTxMarginCh[i], AR_PHY_GAIN_2GHZ_RXTX_MARGIN)); - } -} - -static void ath9k_hw_def_set_board_values(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct modal_eep_header *pModal; - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - int i, regChainOffset; - u8 txRxAttenLocal; - - pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - txRxAttenLocal = IS_CHAN_2GHZ(chan) ? 23 : 44; - - REG_WRITE(ah, AR_PHY_SWITCH_COM, - ah->eep_ops->get_eeprom_antenna_cfg(ah, chan)); - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (AR_SREV_9280(ah)) { - if (i >= 2) - break; - } - - if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) && (i != 0)) - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - else - regChainOffset = i * 0x1000; - - REG_WRITE(ah, AR_PHY_SWITCH_CHAIN_0 + regChainOffset, - pModal->antCtrlChain[i]); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset, - (REG_READ(ah, AR_PHY_TIMING_CTRL4(0) + regChainOffset) & - ~(AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF | - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF)) | - SM(pModal->iqCalICh[i], - AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF) | - SM(pModal->iqCalQCh[i], - AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF)); - - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) - ath9k_hw_def_set_gain(ah, pModal, eep, txRxAttenLocal, - regChainOffset, i); - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - if (IS_CHAN_2GHZ(chan)) { - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, - AR_AN_RF2G1_CH0_OB, - AR_AN_RF2G1_CH0_OB_S, - pModal->ob); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH0, - AR_AN_RF2G1_CH0_DB, - AR_AN_RF2G1_CH0_DB_S, - pModal->db); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, - AR_AN_RF2G1_CH1_OB, - AR_AN_RF2G1_CH1_OB_S, - pModal->ob_ch1); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF2G1_CH1, - AR_AN_RF2G1_CH1_DB, - AR_AN_RF2G1_CH1_DB_S, - pModal->db_ch1); - } else { - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, - AR_AN_RF5G1_CH0_OB5, - AR_AN_RF5G1_CH0_OB5_S, - pModal->ob); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH0, - AR_AN_RF5G1_CH0_DB5, - AR_AN_RF5G1_CH0_DB5_S, - pModal->db); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, - AR_AN_RF5G1_CH1_OB5, - AR_AN_RF5G1_CH1_OB5_S, - pModal->ob_ch1); - ath9k_hw_analog_shift_rmw(ah, AR_AN_RF5G1_CH1, - AR_AN_RF5G1_CH1_DB5, - AR_AN_RF5G1_CH1_DB5_S, - pModal->db_ch1); - } - ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, - AR_AN_TOP2_XPABIAS_LVL, - AR_AN_TOP2_XPABIAS_LVL_S, - pModal->xpaBiasLvl); - ath9k_hw_analog_shift_rmw(ah, AR_AN_TOP2, - AR_AN_TOP2_LOCALBIAS, - AR_AN_TOP2_LOCALBIAS_S, - pModal->local_bias); - REG_RMW_FIELD(ah, AR_PHY_XPA_CFG, AR_PHY_FORCE_XPA_CFG, - pModal->force_xpaon); - } - - REG_RMW_FIELD(ah, AR_PHY_SETTLING, AR_PHY_SETTLING_SWITCH, - pModal->switchSettling); - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, AR_PHY_DESIRED_SZ_ADC, - pModal->adcDesiredSize); - - if (!AR_SREV_9280_10_OR_LATER(ah)) - REG_RMW_FIELD(ah, AR_PHY_DESIRED_SZ, - AR_PHY_DESIRED_SZ_PGA, - pModal->pgaDesiredSize); - - REG_WRITE(ah, AR_PHY_RF_CTL4, - SM(pModal->txEndToXpaOff, AR_PHY_RF_CTL4_TX_END_XPAA_OFF) - | SM(pModal->txEndToXpaOff, - AR_PHY_RF_CTL4_TX_END_XPAB_OFF) - | SM(pModal->txFrameToXpaOn, - AR_PHY_RF_CTL4_FRAME_XPAA_ON) - | SM(pModal->txFrameToXpaOn, - AR_PHY_RF_CTL4_FRAME_XPAB_ON)); - - REG_RMW_FIELD(ah, AR_PHY_RF_CTL3, AR_PHY_TX_END_TO_A2_RX_ON, - pModal->txEndToRxOn); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - REG_RMW_FIELD(ah, AR_PHY_CCA, AR9280_PHY_CCA_THRESH62, - pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA0, - AR_PHY_EXT_CCA0_THRESH62, - pModal->thresh62); - } else { - REG_RMW_FIELD(ah, AR_PHY_CCA, AR_PHY_CCA_THRESH62, - pModal->thresh62); - REG_RMW_FIELD(ah, AR_PHY_EXT_CCA, - AR_PHY_EXT_CCA_THRESH62, - pModal->thresh62); - } - - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_2) { - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, - AR_PHY_TX_END_DATA_START, - pModal->txFrameToDataStart); - REG_RMW_FIELD(ah, AR_PHY_RF_CTL2, AR_PHY_TX_END_PA_ON, - pModal->txFrameToPaOn); - } - - if (AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_3) { - if (IS_CHAN_HT40(chan)) - REG_RMW_FIELD(ah, AR_PHY_SETTLING, - AR_PHY_SETTLING_SWITCH, - pModal->swSettleHt40); - } - - if (AR_SREV_9280_20_OR_LATER(ah) && - AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_19) - REG_RMW_FIELD(ah, AR_PHY_CCK_TX_CTRL, - AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK, - pModal->miscBits); - - - if (AR_SREV_9280_20(ah) && AR5416_VER_MASK >= AR5416_EEP_MINOR_VER_20) { - if (IS_CHAN_2GHZ(chan)) - REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, - eep->baseEepHeader.dacLpMode); - else if (eep->baseEepHeader.dacHiPwrMode_5G) - REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, 0); - else - REG_RMW_FIELD(ah, AR_AN_TOP1, AR_AN_TOP1_DACIPMODE, - eep->baseEepHeader.dacLpMode); - - udelay(100); - - REG_RMW_FIELD(ah, AR_PHY_FRAME_CTL, AR_PHY_FRAME_CTL_TX_CLIP, - pModal->miscBits >> 2); - - REG_RMW_FIELD(ah, AR_PHY_TX_PWRCTRL9, - AR_PHY_TX_DESIRED_SCALE_CCK, - eep->baseEepHeader.desiredScaleCCK); - } -} - -static void ath9k_hw_def_set_addac(struct ath_hw *ah, - struct ath9k_channel *chan) -{ -#define XPA_LVL_FREQ(cnt) (pModal->xpaBiasLvlFreq[cnt]) - struct modal_eep_header *pModal; - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - u8 biaslevel; - - if (ah->hw_version.macVersion != AR_SREV_VERSION_9160) - return; - - if (ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_MINOR_VER_7) - return; - - pModal = &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - - if (pModal->xpaBiasLvl != 0xff) { - biaslevel = pModal->xpaBiasLvl; - } else { - u16 resetFreqBin, freqBin, freqCount = 0; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - resetFreqBin = FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)); - freqBin = XPA_LVL_FREQ(0) & 0xff; - biaslevel = (u8) (XPA_LVL_FREQ(0) >> 14); - - freqCount++; - - while (freqCount < 3) { - if (XPA_LVL_FREQ(freqCount) == 0x0) - break; - - freqBin = XPA_LVL_FREQ(freqCount) & 0xff; - if (resetFreqBin >= freqBin) - biaslevel = (u8)(XPA_LVL_FREQ(freqCount) >> 14); - else - break; - freqCount++; - } - } - - if (IS_CHAN_2GHZ(chan)) { - INI_RA(&ah->iniAddac, 7, 1) = (INI_RA(&ah->iniAddac, - 7, 1) & (~0x18)) | biaslevel << 3; - } else { - INI_RA(&ah->iniAddac, 6, 1) = (INI_RA(&ah->iniAddac, - 6, 1) & (~0xc0)) | biaslevel << 6; - } -#undef XPA_LVL_FREQ -} - -static void ath9k_hw_get_def_gain_boundaries_pdadcs(struct ath_hw *ah, - struct ath9k_channel *chan, - struct cal_data_per_freq *pRawDataSet, - u8 *bChans, u16 availPiers, - u16 tPdGainOverlap, int16_t *pMinCalPower, - u16 *pPdGainBoundaries, u8 *pPDADCValues, - u16 numXpdGains) -{ - int i, j, k; - int16_t ss; - u16 idxL = 0, idxR = 0, numPiers; - static u8 vpdTableL[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableR[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - static u8 vpdTableI[AR5416_NUM_PD_GAINS] - [AR5416_MAX_PWR_RANGE_IN_HALF_DB]; - - u8 *pVpdL, *pVpdR, *pPwrL, *pPwrR; - u8 minPwrT4[AR5416_NUM_PD_GAINS]; - u8 maxPwrT4[AR5416_NUM_PD_GAINS]; - int16_t vpdStep; - int16_t tmpVal; - u16 sizeCurrVpdTable, maxIndex, tgtIndex; - bool match; - int16_t minDelta = 0; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - for (numPiers = 0; numPiers < availPiers; numPiers++) { - if (bChans[numPiers] == AR5416_BCHAN_UNUSED) - break; - } - - match = ath9k_hw_get_lower_upper_index((u8)FREQ2FBIN(centers.synth_center, - IS_CHAN_2GHZ(chan)), - bChans, numPiers, &idxL, &idxR); - - if (match) { - for (i = 0; i < numXpdGains; i++) { - minPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][0]; - maxPwrT4[i] = pRawDataSet[idxL].pwrPdg[i][4]; - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pRawDataSet[idxL].pwrPdg[i], - pRawDataSet[idxL].vpdPdg[i], - AR5416_PD_GAIN_ICEPTS, - vpdTableI[i]); - } - } else { - for (i = 0; i < numXpdGains; i++) { - pVpdL = pRawDataSet[idxL].vpdPdg[i]; - pPwrL = pRawDataSet[idxL].pwrPdg[i]; - pVpdR = pRawDataSet[idxR].vpdPdg[i]; - pPwrR = pRawDataSet[idxR].pwrPdg[i]; - - minPwrT4[i] = max(pPwrL[0], pPwrR[0]); - - maxPwrT4[i] = - min(pPwrL[AR5416_PD_GAIN_ICEPTS - 1], - pPwrR[AR5416_PD_GAIN_ICEPTS - 1]); - - - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrL, pVpdL, - AR5416_PD_GAIN_ICEPTS, - vpdTableL[i]); - ath9k_hw_fill_vpd_table(minPwrT4[i], maxPwrT4[i], - pPwrR, pVpdR, - AR5416_PD_GAIN_ICEPTS, - vpdTableR[i]); - - for (j = 0; j <= (maxPwrT4[i] - minPwrT4[i]) / 2; j++) { - vpdTableI[i][j] = - (u8)(ath9k_hw_interpolate((u16) - FREQ2FBIN(centers. - synth_center, - IS_CHAN_2GHZ - (chan)), - bChans[idxL], bChans[idxR], - vpdTableL[i][j], vpdTableR[i][j])); - } - } - } - - *pMinCalPower = (int16_t)(minPwrT4[0] / 2); - - k = 0; - - for (i = 0; i < numXpdGains; i++) { - if (i == (numXpdGains - 1)) - pPdGainBoundaries[i] = - (u16)(maxPwrT4[i] / 2); - else - pPdGainBoundaries[i] = - (u16)((maxPwrT4[i] + minPwrT4[i + 1]) / 4); - - pPdGainBoundaries[i] = - min((u16)AR5416_MAX_RATE_POWER, pPdGainBoundaries[i]); - - if ((i == 0) && !AR_SREV_5416_20_OR_LATER(ah)) { - minDelta = pPdGainBoundaries[0] - 23; - pPdGainBoundaries[0] = 23; - } else { - minDelta = 0; - } - - if (i == 0) { - if (AR_SREV_9280_10_OR_LATER(ah)) - ss = (int16_t)(0 - (minPwrT4[i] / 2)); - else - ss = 0; - } else { - ss = (int16_t)((pPdGainBoundaries[i - 1] - - (minPwrT4[i] / 2)) - - tPdGainOverlap + 1 + minDelta); - } - vpdStep = (int16_t)(vpdTableI[i][1] - vpdTableI[i][0]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - while ((ss < 0) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)(vpdTableI[i][0] + ss * vpdStep); - pPDADCValues[k++] = (u8)((tmpVal < 0) ? 0 : tmpVal); - ss++; - } - - sizeCurrVpdTable = (u8) ((maxPwrT4[i] - minPwrT4[i]) / 2 + 1); - tgtIndex = (u8)(pPdGainBoundaries[i] + tPdGainOverlap - - (minPwrT4[i] / 2)); - maxIndex = (tgtIndex < sizeCurrVpdTable) ? - tgtIndex : sizeCurrVpdTable; - - while ((ss < maxIndex) && (k < (AR5416_NUM_PDADC_VALUES - 1))) { - pPDADCValues[k++] = vpdTableI[i][ss++]; - } - - vpdStep = (int16_t)(vpdTableI[i][sizeCurrVpdTable - 1] - - vpdTableI[i][sizeCurrVpdTable - 2]); - vpdStep = (int16_t)((vpdStep < 1) ? 1 : vpdStep); - - if (tgtIndex >= maxIndex) { - while ((ss <= tgtIndex) && - (k < (AR5416_NUM_PDADC_VALUES - 1))) { - tmpVal = (int16_t)((vpdTableI[i][sizeCurrVpdTable - 1] + - (ss - maxIndex + 1) * vpdStep)); - pPDADCValues[k++] = (u8)((tmpVal > 255) ? - 255 : tmpVal); - ss++; - } - } - } - - while (i < AR5416_PD_GAINS_IN_MASK) { - pPdGainBoundaries[i] = pPdGainBoundaries[i - 1]; - i++; - } - - while (k < AR5416_NUM_PDADC_VALUES) { - pPDADCValues[k] = pPDADCValues[k - 1]; - k++; - } - - return; -} - -static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *pTxPowerIndexOffset) -{ -#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) -#define SM_PDGAIN_B(x, y) \ - SM((gainBoundaries[x]), AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##y) - - struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - struct cal_data_per_freq *pRawDataset; - u8 *pCalBChans = NULL; - u16 pdGainOverlap_t2; - static u8 pdadcValues[AR5416_NUM_PDADC_VALUES]; - u16 gainBoundaries[AR5416_PD_GAINS_IN_MASK]; - u16 numPiers, i, j; - int16_t tMinCalPower; - u16 numXpdGain, xpdMask; - u16 xpdGainValues[AR5416_NUM_PD_GAINS] = { 0, 0, 0, 0 }; - u32 reg32, regOffset, regChainOffset; - int16_t modalIdx; - - modalIdx = IS_CHAN_2GHZ(chan) ? 1 : 0; - xpdMask = pEepData->modalHeader[modalIdx].xpdGain; - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - pdGainOverlap_t2 = - pEepData->modalHeader[modalIdx].pdGainOverlap; - } else { - pdGainOverlap_t2 = (u16)(MS(REG_READ(ah, AR_PHY_TPCRG5), - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)); - } - - if (IS_CHAN_2GHZ(chan)) { - pCalBChans = pEepData->calFreqPier2G; - numPiers = AR5416_NUM_2G_CAL_PIERS; - } else { - pCalBChans = pEepData->calFreqPier5G; - numPiers = AR5416_NUM_5G_CAL_PIERS; - } - - if (OLC_FOR_AR9280_20_LATER && IS_CHAN_2GHZ(chan)) { - pRawDataset = pEepData->calPierData2G[0]; - ah->initPDADC = ((struct calDataPerFreqOpLoop *) - pRawDataset)->vpdPdg[0][0]; - } - - numXpdGain = 0; - - for (i = 1; i <= AR5416_PD_GAINS_IN_MASK; i++) { - if ((xpdMask >> (AR5416_PD_GAINS_IN_MASK - i)) & 1) { - if (numXpdGain >= AR5416_NUM_PD_GAINS) - break; - xpdGainValues[numXpdGain] = - (u16)(AR5416_PD_GAINS_IN_MASK - i); - numXpdGain++; - } - } - - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_NUM_PD_GAIN, - (numXpdGain - 1) & 0x3); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_1, - xpdGainValues[0]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_2, - xpdGainValues[1]); - REG_RMW_FIELD(ah, AR_PHY_TPCRG1, AR_PHY_TPCRG1_PD_GAIN_3, - xpdGainValues[2]); - - for (i = 0; i < AR5416_MAX_CHAINS; i++) { - if (AR_SREV_5416_20_OR_LATER(ah) && - (ah->rxchainmask == 5 || ah->txchainmask == 5) && - (i != 0)) { - regChainOffset = (i == 1) ? 0x2000 : 0x1000; - } else - regChainOffset = i * 0x1000; - - if (pEepData->baseEepHeader.txMask & (1 << i)) { - if (IS_CHAN_2GHZ(chan)) - pRawDataset = pEepData->calPierData2G[i]; - else - pRawDataset = pEepData->calPierData5G[i]; - - - if (OLC_FOR_AR9280_20_LATER) { - u8 pcdacIdx; - u8 txPower; - - ath9k_get_txgain_index(ah, chan, - (struct calDataPerFreqOpLoop *)pRawDataset, - pCalBChans, numPiers, &txPower, &pcdacIdx); - ath9k_olc_get_pdadcs(ah, pcdacIdx, - txPower/2, pdadcValues); - } else { - ath9k_hw_get_def_gain_boundaries_pdadcs(ah, - chan, pRawDataset, - pCalBChans, numPiers, - pdGainOverlap_t2, - &tMinCalPower, - gainBoundaries, - pdadcValues, - numXpdGain); - } - - if ((i == 0) || AR_SREV_5416_20_OR_LATER(ah)) { - if (OLC_FOR_AR9280_20_LATER) { - REG_WRITE(ah, - AR_PHY_TPCRG5 + regChainOffset, - SM(0x6, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP) | - SM_PD_GAIN(1) | SM_PD_GAIN(2) | - SM_PD_GAIN(3) | SM_PD_GAIN(4)); - } else { - REG_WRITE(ah, - AR_PHY_TPCRG5 + regChainOffset, - SM(pdGainOverlap_t2, - AR_PHY_TPCRG5_PD_GAIN_OVERLAP)| - SM_PDGAIN_B(0, 1) | - SM_PDGAIN_B(1, 2) | - SM_PDGAIN_B(2, 3) | - SM_PDGAIN_B(3, 4)); - } - } - - regOffset = AR_PHY_BASE + (672 << 2) + regChainOffset; - for (j = 0; j < 32; j++) { - reg32 = ((pdadcValues[4 * j + 0] & 0xFF) << 0) | - ((pdadcValues[4 * j + 1] & 0xFF) << 8) | - ((pdadcValues[4 * j + 2] & 0xFF) << 16)| - ((pdadcValues[4 * j + 3] & 0xFF) << 24); - REG_WRITE(ah, regOffset, reg32); - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC (%d,%4x): %4.4x %8.8x\n", - i, regChainOffset, regOffset, - reg32); - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PDADC: Chain %d | PDADC %3d " - "Value %3d | PDADC %3d Value %3d | " - "PDADC %3d Value %3d | PDADC %3d " - "Value %3d |\n", - i, 4 * j, pdadcValues[4 * j], - 4 * j + 1, pdadcValues[4 * j + 1], - 4 * j + 2, pdadcValues[4 * j + 2], - 4 * j + 3, - pdadcValues[4 * j + 3]); - - regOffset += 4; - } - } - } - - *pTxPowerIndexOffset = 0; -#undef SM_PD_GAIN -#undef SM_PDGAIN_B -} - -static void ath9k_hw_set_def_power_per_rate_table(struct ath_hw *ah, - struct ath9k_channel *chan, - int16_t *ratesArray, - u16 cfgCtl, - u16 AntennaReduction, - u16 twiceMaxRegulatoryPower, - u16 powerLimit) -{ -#define REDUCE_SCALED_POWER_BY_TWO_CHAIN 6 /* 10*log10(2)*2 */ -#define REDUCE_SCALED_POWER_BY_THREE_CHAIN 9 /* 10*log10(3)*2 */ - - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - u16 twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - static const u16 tpScaleReductionTable[5] = - { 0, 3, 6, 9, AR5416_MAX_RATE_POWER }; - - int i; - int16_t twiceLargestAntenna; - struct cal_ctl_data *rep; - struct cal_target_power_leg targetPowerOfdm, targetPowerCck = { - 0, { 0, 0, 0, 0} - }; - struct cal_target_power_leg targetPowerOfdmExt = { - 0, { 0, 0, 0, 0} }, targetPowerCckExt = { - 0, { 0, 0, 0, 0 } - }; - struct cal_target_power_ht targetPowerHt20, targetPowerHt40 = { - 0, {0, 0, 0, 0} - }; - u16 scaledPower = 0, minCtlPower, maxRegAllowedPower; - u16 ctlModesFor11a[] = - { CTL_11A, CTL_5GHT20, CTL_11A_EXT, CTL_5GHT40 }; - u16 ctlModesFor11g[] = - { CTL_11B, CTL_11G, CTL_2GHT20, CTL_11B_EXT, CTL_11G_EXT, - CTL_2GHT40 - }; - u16 numCtlModes, *pCtlMode, ctlMode, freq; - struct chan_centers centers; - int tx_chainmask; - u16 twiceMinEdgePower; - - tx_chainmask = ah->txchainmask; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - - twiceLargestAntenna = max( - pEepData->modalHeader - [IS_CHAN_2GHZ(chan)].antennaGainCh[0], - pEepData->modalHeader - [IS_CHAN_2GHZ(chan)].antennaGainCh[1]); - - twiceLargestAntenna = max((u8)twiceLargestAntenna, - pEepData->modalHeader - [IS_CHAN_2GHZ(chan)].antennaGainCh[2]); - - twiceLargestAntenna = (int16_t)min(AntennaReduction - - twiceLargestAntenna, 0); - - maxRegAllowedPower = twiceMaxRegulatoryPower + twiceLargestAntenna; - - if (regulatory->tp_scale != ATH9K_TP_SCALE_MAX) { - maxRegAllowedPower -= - (tpScaleReductionTable[(regulatory->tp_scale)] * 2); - } - - scaledPower = min(powerLimit, maxRegAllowedPower); - - switch (ar5416_get_ntxchains(tx_chainmask)) { - case 1: - break; - case 2: - scaledPower -= REDUCE_SCALED_POWER_BY_TWO_CHAIN; - break; - case 3: - scaledPower -= REDUCE_SCALED_POWER_BY_THREE_CHAIN; - break; - } - - scaledPower = max((u16)0, scaledPower); - - if (IS_CHAN_2GHZ(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g) - - SUB_NUM_CTL_MODES_AT_2G_40; - pCtlMode = ctlModesFor11g; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCck, 4, false); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT20, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11g); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower2GHT40, - AR5416_NUM_2G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPowerCck, - AR5416_NUM_2G_CCK_TARGET_POWERS, - &targetPowerCckExt, 4, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower2G, - AR5416_NUM_2G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - } else { - numCtlModes = ARRAY_SIZE(ctlModesFor11a) - - SUB_NUM_CTL_MODES_AT_5G_40; - pCtlMode = ctlModesFor11a; - - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower5G, - AR5416_NUM_5G_20_TARGET_POWERS, - &targetPowerOfdm, 4, false); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower5GHT20, - AR5416_NUM_5G_20_TARGET_POWERS, - &targetPowerHt20, 8, false); - - if (IS_CHAN_HT40(chan)) { - numCtlModes = ARRAY_SIZE(ctlModesFor11a); - ath9k_hw_get_target_powers(ah, chan, - pEepData->calTargetPower5GHT40, - AR5416_NUM_5G_40_TARGET_POWERS, - &targetPowerHt40, 8, true); - ath9k_hw_get_legacy_target_powers(ah, chan, - pEepData->calTargetPower5G, - AR5416_NUM_5G_20_TARGET_POWERS, - &targetPowerOfdmExt, 4, true); - } - } - - for (ctlMode = 0; ctlMode < numCtlModes; ctlMode++) { - bool isHt40CtlMode = (pCtlMode[ctlMode] == CTL_5GHT40) || - (pCtlMode[ctlMode] == CTL_2GHT40); - if (isHt40CtlMode) - freq = centers.synth_center; - else if (pCtlMode[ctlMode] & EXT_ADDITIVE) - freq = centers.ext_center; - else - freq = centers.ctl_center; - - if (ah->eep_ops->get_eeprom_ver(ah) == 14 && - ah->eep_ops->get_eeprom_rev(ah) <= 2) - twiceMaxEdgePower = AR5416_MAX_RATE_POWER; - - for (i = 0; (i < AR5416_NUM_CTLS) && pEepData->ctlIndex[i]; i++) { - if ((((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - pEepData->ctlIndex[i]) || - (((cfgCtl & ~CTL_MODE_M) | - (pCtlMode[ctlMode] & CTL_MODE_M)) == - ((pEepData->ctlIndex[i] & CTL_MODE_M) | SD_NO_CTL))) { - rep = &(pEepData->ctlData[i]); - - twiceMinEdgePower = ath9k_hw_get_max_edge_power(freq, - rep->ctlEdges[ar5416_get_ntxchains(tx_chainmask) - 1], - IS_CHAN_2GHZ(chan), AR5416_NUM_BAND_EDGES); - - if ((cfgCtl & ~CTL_MODE_M) == SD_NO_CTL) { - twiceMaxEdgePower = min(twiceMaxEdgePower, - twiceMinEdgePower); - } else { - twiceMaxEdgePower = twiceMinEdgePower; - break; - } - } - } - - minCtlPower = min(twiceMaxEdgePower, scaledPower); - - switch (pCtlMode[ctlMode]) { - case CTL_11B: - for (i = 0; i < ARRAY_SIZE(targetPowerCck.tPow2x); i++) { - targetPowerCck.tPow2x[i] = - min((u16)targetPowerCck.tPow2x[i], - minCtlPower); - } - break; - case CTL_11A: - case CTL_11G: - for (i = 0; i < ARRAY_SIZE(targetPowerOfdm.tPow2x); i++) { - targetPowerOfdm.tPow2x[i] = - min((u16)targetPowerOfdm.tPow2x[i], - minCtlPower); - } - break; - case CTL_5GHT20: - case CTL_2GHT20: - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) { - targetPowerHt20.tPow2x[i] = - min((u16)targetPowerHt20.tPow2x[i], - minCtlPower); - } - break; - case CTL_11B_EXT: - targetPowerCckExt.tPow2x[0] = min((u16) - targetPowerCckExt.tPow2x[0], - minCtlPower); - break; - case CTL_11A_EXT: - case CTL_11G_EXT: - targetPowerOfdmExt.tPow2x[0] = min((u16) - targetPowerOfdmExt.tPow2x[0], - minCtlPower); - break; - case CTL_5GHT40: - case CTL_2GHT40: - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - targetPowerHt40.tPow2x[i] = - min((u16)targetPowerHt40.tPow2x[i], - minCtlPower); - } - break; - default: - break; - } - } - - ratesArray[rate6mb] = ratesArray[rate9mb] = ratesArray[rate12mb] = - ratesArray[rate18mb] = ratesArray[rate24mb] = - targetPowerOfdm.tPow2x[0]; - ratesArray[rate36mb] = targetPowerOfdm.tPow2x[1]; - ratesArray[rate48mb] = targetPowerOfdm.tPow2x[2]; - ratesArray[rate54mb] = targetPowerOfdm.tPow2x[3]; - ratesArray[rateXr] = targetPowerOfdm.tPow2x[0]; - - for (i = 0; i < ARRAY_SIZE(targetPowerHt20.tPow2x); i++) - ratesArray[rateHt20_0 + i] = targetPowerHt20.tPow2x[i]; - - if (IS_CHAN_2GHZ(chan)) { - ratesArray[rate1l] = targetPowerCck.tPow2x[0]; - ratesArray[rate2s] = ratesArray[rate2l] = - targetPowerCck.tPow2x[1]; - ratesArray[rate5_5s] = ratesArray[rate5_5l] = - targetPowerCck.tPow2x[2]; - ratesArray[rate11s] = ratesArray[rate11l] = - targetPowerCck.tPow2x[3]; - } - if (IS_CHAN_HT40(chan)) { - for (i = 0; i < ARRAY_SIZE(targetPowerHt40.tPow2x); i++) { - ratesArray[rateHt40_0 + i] = - targetPowerHt40.tPow2x[i]; - } - ratesArray[rateDupOfdm] = targetPowerHt40.tPow2x[0]; - ratesArray[rateDupCck] = targetPowerHt40.tPow2x[0]; - ratesArray[rateExtOfdm] = targetPowerOfdmExt.tPow2x[0]; - if (IS_CHAN_2GHZ(chan)) { - ratesArray[rateExtCck] = - targetPowerCckExt.tPow2x[0]; - } - } -} - -static void ath9k_hw_def_set_txpower(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 cfgCtl, - u8 twiceAntennaReduction, - u8 twiceMaxRegulatoryPower, - u8 powerLimit) -{ -#define RT_AR_DELTA(x) (ratesArray[x] - cck_ofdm_delta) - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ar5416_eeprom_def *pEepData = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); - int16_t ratesArray[Ar5416RateSize]; - int16_t txPowerIndexOffset = 0; - u8 ht40PowerIncForPdadc = 2; - int i, cck_ofdm_delta = 0; - - memset(ratesArray, 0, sizeof(ratesArray)); - - if ((pEepData->baseEepHeader.version & AR5416_EEP_VER_MINOR_MASK) >= - AR5416_EEP_MINOR_VER_2) { - ht40PowerIncForPdadc = pModal->ht40PowerIncForPdadc; - } - - ath9k_hw_set_def_power_per_rate_table(ah, chan, - &ratesArray[0], cfgCtl, - twiceAntennaReduction, - twiceMaxRegulatoryPower, - powerLimit); - - ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); - - for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { - ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]); - if (ratesArray[i] > AR5416_MAX_RATE_POWER) - ratesArray[i] = AR5416_MAX_RATE_POWER; - } - - if (AR_SREV_9280_10_OR_LATER(ah)) { - for (i = 0; i < Ar5416RateSize; i++) - ratesArray[i] -= AR5416_PWR_TABLE_OFFSET * 2; - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE1, - ATH9K_POW_SM(ratesArray[rate18mb], 24) - | ATH9K_POW_SM(ratesArray[rate12mb], 16) - | ATH9K_POW_SM(ratesArray[rate9mb], 8) - | ATH9K_POW_SM(ratesArray[rate6mb], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE2, - ATH9K_POW_SM(ratesArray[rate54mb], 24) - | ATH9K_POW_SM(ratesArray[rate48mb], 16) - | ATH9K_POW_SM(ratesArray[rate36mb], 8) - | ATH9K_POW_SM(ratesArray[rate24mb], 0)); - - if (IS_CHAN_2GHZ(chan)) { - if (OLC_FOR_AR9280_20_LATER) { - cck_ofdm_delta = 2; - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(RT_AR_DELTA(rate2s), 24) - | ATH9K_POW_SM(RT_AR_DELTA(rate2l), 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(RT_AR_DELTA(rate1l), 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(RT_AR_DELTA(rate11s), 24) - | ATH9K_POW_SM(RT_AR_DELTA(rate11l), 16) - | ATH9K_POW_SM(RT_AR_DELTA(rate5_5s), 8) - | ATH9K_POW_SM(RT_AR_DELTA(rate5_5l), 0)); - } else { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE3, - ATH9K_POW_SM(ratesArray[rate2s], 24) - | ATH9K_POW_SM(ratesArray[rate2l], 16) - | ATH9K_POW_SM(ratesArray[rateXr], 8) - | ATH9K_POW_SM(ratesArray[rate1l], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE4, - ATH9K_POW_SM(ratesArray[rate11s], 24) - | ATH9K_POW_SM(ratesArray[rate11l], 16) - | ATH9K_POW_SM(ratesArray[rate5_5s], 8) - | ATH9K_POW_SM(ratesArray[rate5_5l], 0)); - } - } - - REG_WRITE(ah, AR_PHY_POWER_TX_RATE5, - ATH9K_POW_SM(ratesArray[rateHt20_3], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_2], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_1], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_0], 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE6, - ATH9K_POW_SM(ratesArray[rateHt20_7], 24) - | ATH9K_POW_SM(ratesArray[rateHt20_6], 16) - | ATH9K_POW_SM(ratesArray[rateHt20_5], 8) - | ATH9K_POW_SM(ratesArray[rateHt20_4], 0)); - - if (IS_CHAN_HT40(chan)) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE7, - ATH9K_POW_SM(ratesArray[rateHt40_3] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_2] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_1] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_0] + - ht40PowerIncForPdadc, 0)); - REG_WRITE(ah, AR_PHY_POWER_TX_RATE8, - ATH9K_POW_SM(ratesArray[rateHt40_7] + - ht40PowerIncForPdadc, 24) - | ATH9K_POW_SM(ratesArray[rateHt40_6] + - ht40PowerIncForPdadc, 16) - | ATH9K_POW_SM(ratesArray[rateHt40_5] + - ht40PowerIncForPdadc, 8) - | ATH9K_POW_SM(ratesArray[rateHt40_4] + - ht40PowerIncForPdadc, 0)); - if (OLC_FOR_AR9280_20_LATER) { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(RT_AR_DELTA(rateExtCck), 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(RT_AR_DELTA(rateDupCck), 0)); - } else { - REG_WRITE(ah, AR_PHY_POWER_TX_RATE9, - ATH9K_POW_SM(ratesArray[rateExtOfdm], 24) - | ATH9K_POW_SM(ratesArray[rateExtCck], 16) - | ATH9K_POW_SM(ratesArray[rateDupOfdm], 8) - | ATH9K_POW_SM(ratesArray[rateDupCck], 0)); - } - } - - REG_WRITE(ah, AR_PHY_POWER_TX_SUB, - ATH9K_POW_SM(pModal->pwrDecreaseFor3Chain, 6) - | ATH9K_POW_SM(pModal->pwrDecreaseFor2Chain, 0)); - - i = rate6mb; - - if (IS_CHAN_HT40(chan)) - i = rateHt40_0; - else if (IS_CHAN_HT20(chan)) - i = rateHt20_0; - - if (AR_SREV_9280_10_OR_LATER(ah)) - regulatory->max_power_level = - ratesArray[i] + AR5416_PWR_TABLE_OFFSET * 2; - else - regulatory->max_power_level = ratesArray[i]; - - switch(ar5416_get_ntxchains(ah->txchainmask)) { - case 1: - break; - case 2: - regulatory->max_power_level += INCREASE_MAXPOW_BY_TWO_CHAIN; - break; - case 3: - regulatory->max_power_level += INCREASE_MAXPOW_BY_THREE_CHAIN; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "Invalid chainmask configuration\n"); - break; - } -} - -static u8 ath9k_hw_def_get_num_ant_config(struct ath_hw *ah, - enum ieee80211_band freq_band) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(eep->modalHeader[ATH9K_HAL_FREQ_BAND_2GHZ == freq_band]); - struct base_eep_header *pBase = &eep->baseEepHeader; - u8 num_ant_config; - - num_ant_config = 1; - - if (pBase->version >= 0x0E0D) - if (pModal->useAnt1) - num_ant_config += 1; - - return num_ant_config; -} - -static u16 ath9k_hw_def_get_eeprom_antenna_cfg(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - struct ar5416_eeprom_def *eep = &ah->eeprom.def; - struct modal_eep_header *pModal = - &(eep->modalHeader[IS_CHAN_2GHZ(chan)]); - - return pModal->antCtrlCommon & 0xFFFF; -} - -static u16 ath9k_hw_def_get_spur_channel(struct ath_hw *ah, u16 i, bool is2GHz) -{ -#define EEP_DEF_SPURCHAN \ - (ah->eeprom.def.modalHeader[is2GHz].spurChans[i].spurChan) - - u16 spur_val = AR_NO_SPUR; - - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur idx %d is2Ghz. %d val %x\n", - i, is2GHz, ah->config.spurchans[i][is2GHz]); - - switch (ah->config.spurmode) { - case SPUR_DISABLE: - break; - case SPUR_ENABLE_IOCTL: - spur_val = ah->config.spurchans[i][is2GHz]; - DPRINTF(ah->ah_sc, ATH_DBG_ANI, - "Getting spur val from new loc. %d\n", spur_val); - break; - case SPUR_ENABLE_EEPROM: - spur_val = EEP_DEF_SPURCHAN; - break; - } - - return spur_val; - -#undef EEP_DEF_SPURCHAN -} - -const struct eeprom_ops eep_def_ops = { - .check_eeprom = ath9k_hw_def_check_eeprom, - .get_eeprom = ath9k_hw_def_get_eeprom, - .fill_eeprom = ath9k_hw_def_fill_eeprom, - .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, - .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, - .get_num_ant_config = ath9k_hw_def_get_num_ant_config, - .get_eeprom_antenna_cfg = ath9k_hw_def_get_eeprom_antenna_cfg, - .set_board_values = ath9k_hw_def_set_board_values, - .set_addac = ath9k_hw_def_set_addac, - .set_txpower = ath9k_hw_def_set_txpower, - .get_spur_channel = ath9k_hw_def_get_spur_channel -}; diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c deleted file mode 100644 index aed75eb4d2b7..000000000000 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ /dev/null @@ -1,4389 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include - -#include "ath9k.h" -#include "initvals.h" - -#define ATH9K_CLOCK_RATE_CCK 22 -#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40 -#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44 - -static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type); -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode); -static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value); -static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); -static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan); - -/********************/ -/* Helper Functions */ -/********************/ - -static u32 ath9k_hw_mac_usec(struct ath_hw *ah, u32 clks) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (!ah->curchan) /* should really check for CCK instead */ - return clks / ATH9K_CLOCK_RATE_CCK; - if (conf->channel->band == IEEE80211_BAND_2GHZ) - return clks / ATH9K_CLOCK_RATE_2GHZ_OFDM; - - return clks / ATH9K_CLOCK_RATE_5GHZ_OFDM; -} - -static u32 ath9k_hw_mac_to_usec(struct ath_hw *ah, u32 clks) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (conf_is_ht40(conf)) - return ath9k_hw_mac_usec(ah, clks) / 2; - else - return ath9k_hw_mac_usec(ah, clks); -} - -static u32 ath9k_hw_mac_clks(struct ath_hw *ah, u32 usecs) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (!ah->curchan) /* should really check for CCK instead */ - return usecs *ATH9K_CLOCK_RATE_CCK; - if (conf->channel->band == IEEE80211_BAND_2GHZ) - return usecs *ATH9K_CLOCK_RATE_2GHZ_OFDM; - return usecs *ATH9K_CLOCK_RATE_5GHZ_OFDM; -} - -static u32 ath9k_hw_mac_to_clks(struct ath_hw *ah, u32 usecs) -{ - struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; - - if (conf_is_ht40(conf)) - return ath9k_hw_mac_clks(ah, usecs) * 2; - else - return ath9k_hw_mac_clks(ah, usecs); -} - -/* - * Read and write, they both share the same lock. We do this to serialize - * reads and writes on Atheros 802.11n PCI devices only. This is required - * as the FIFO on these devices can only accept sanely 2 requests. After - * that the device goes bananas. Serializing the reads/writes prevents this - * from happening. - */ - -void ath9k_iowrite32(struct ath_hw *ah, u32 reg_offset, u32 val) -{ - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - iowrite32(val, ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - iowrite32(val, ah->ah_sc->mem + reg_offset); -} - -unsigned int ath9k_ioread32(struct ath_hw *ah, u32 reg_offset) -{ - u32 val; - if (ah->config.serialize_regmode == SER_REG_MODE_ON) { - unsigned long flags; - spin_lock_irqsave(&ah->ah_sc->sc_serial_rw, flags); - val = ioread32(ah->ah_sc->mem + reg_offset); - spin_unlock_irqrestore(&ah->ah_sc->sc_serial_rw, flags); - } else - val = ioread32(ah->ah_sc->mem + reg_offset); - return val; -} - -bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout) -{ - int i; - - BUG_ON(timeout < AH_TIME_QUANTUM); - - for (i = 0; i < (timeout / AH_TIME_QUANTUM); i++) { - if ((REG_READ(ah, reg) & mask) == val) - return true; - - udelay(AH_TIME_QUANTUM); - } - - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "timeout (%d us) on reg 0x%x: 0x%08x & 0x%08x != 0x%08x\n", - timeout, reg, REG_READ(ah, reg), mask, val); - - return false; -} - -u32 ath9k_hw_reverse_bits(u32 val, u32 n) -{ - u32 retval; - int i; - - for (i = 0, retval = 0; i < n; i++) { - retval = (retval << 1) | (val & 1); - val >>= 1; - } - return retval; -} - -bool ath9k_get_channel_edges(struct ath_hw *ah, - u16 flags, u16 *low, - u16 *high) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - - if (flags & CHANNEL_5GHZ) { - *low = pCap->low_5ghz_chan; - *high = pCap->high_5ghz_chan; - return true; - } - if ((flags & CHANNEL_2GHZ)) { - *low = pCap->low_2ghz_chan; - *high = pCap->high_2ghz_chan; - return true; - } - return false; -} - -u16 ath9k_hw_computetxtime(struct ath_hw *ah, - const struct ath_rate_table *rates, - u32 frameLen, u16 rateix, - bool shortPreamble) -{ - u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; - u32 kbps; - - kbps = rates->info[rateix].ratekbps; - - if (kbps == 0) - return 0; - - switch (rates->info[rateix].phy) { - case WLAN_RC_PHY_CCK: - phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; - if (shortPreamble && rates->info[rateix].short_preamble) - phyTime >>= 1; - numBits = frameLen << 3; - txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); - break; - case WLAN_RC_PHY_OFDM: - if (ah->curchan && IS_CHAN_QUARTER_RATE(ah->curchan)) { - bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_QUARTER) / 1000; - numBits = OFDM_PLCP_BITS + (frameLen << 3); - numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME_QUARTER - + OFDM_PREAMBLE_TIME_QUARTER - + (numSymbols * OFDM_SYMBOL_TIME_QUARTER); - } else if (ah->curchan && - IS_CHAN_HALF_RATE(ah->curchan)) { - bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME_HALF) / 1000; - numBits = OFDM_PLCP_BITS + (frameLen << 3); - numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME_HALF + - OFDM_PREAMBLE_TIME_HALF - + (numSymbols * OFDM_SYMBOL_TIME_HALF); - } else { - bitsPerSymbol = (kbps * OFDM_SYMBOL_TIME) / 1000; - numBits = OFDM_PLCP_BITS + (frameLen << 3); - numSymbols = DIV_ROUND_UP(numBits, bitsPerSymbol); - txTime = OFDM_SIFS_TIME + OFDM_PREAMBLE_TIME - + (numSymbols * OFDM_SYMBOL_TIME); - } - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unknown phy %u (rate ix %u)\n", - rates->info[rateix].phy, rateix); - txTime = 0; - break; - } - - return txTime; -} - -void ath9k_hw_get_channel_centers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct chan_centers *centers) -{ - int8_t extoff; - - if (!IS_CHAN_HT40(chan)) { - centers->ctl_center = centers->ext_center = - centers->synth_center = chan->channel; - return; - } - - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || - (chan->chanmode == CHANNEL_G_HT40PLUS)) { - centers->synth_center = - chan->channel + HT40_CHANNEL_CENTER_SHIFT; - extoff = 1; - } else { - centers->synth_center = - chan->channel - HT40_CHANNEL_CENTER_SHIFT; - extoff = -1; - } - - centers->ctl_center = - centers->synth_center - (extoff * HT40_CHANNEL_CENTER_SHIFT); - centers->ext_center = - centers->synth_center + (extoff * - ((ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_20) ? - HT40_CHANNEL_CENTER_SHIFT : 15)); -} - -/******************/ -/* Chip Revisions */ -/******************/ - -static void ath9k_hw_read_revisions(struct ath_hw *ah) -{ - u32 val; - - val = REG_READ(ah, AR_SREV) & AR_SREV_ID; - - if (val == 0xFF) { - val = REG_READ(ah, AR_SREV); - ah->hw_version.macVersion = - (val & AR_SREV_VERSION2) >> AR_SREV_TYPE2_S; - ah->hw_version.macRev = MS(val, AR_SREV_REVISION2); - ah->is_pciexpress = (val & AR_SREV_TYPE2_HOST_MODE) ? 0 : 1; - } else { - if (!AR_SREV_9100(ah)) - ah->hw_version.macVersion = MS(val, AR_SREV_VERSION); - - ah->hw_version.macRev = val & AR_SREV_REVISION; - - if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE) - ah->is_pciexpress = true; - } -} - -static int ath9k_hw_get_radiorev(struct ath_hw *ah) -{ - u32 val; - int i; - - REG_WRITE(ah, AR_PHY(0x36), 0x00007058); - - for (i = 0; i < 8; i++) - REG_WRITE(ah, AR_PHY(0x20), 0x00010000); - val = (REG_READ(ah, AR_PHY(256)) >> 24) & 0xff; - val = ((val & 0xf0) >> 4) | ((val & 0x0f) << 4); - - return ath9k_hw_reverse_bits(val, 8); -} - -/************************************/ -/* HW Attach, Detach, Init Routines */ -/************************************/ - -static void ath9k_hw_disablepcie(struct ath_hw *ah) -{ - if (AR_SREV_9100(ah)) - return; - - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - REG_WRITE(ah, AR_PCIE_SERDES, 0x28000029); - REG_WRITE(ah, AR_PCIE_SERDES, 0x57160824); - REG_WRITE(ah, AR_PCIE_SERDES, 0x25980579); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00000000); - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x000e1007); - - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); -} - -static bool ath9k_hw_chip_test(struct ath_hw *ah) -{ - u32 regAddr[2] = { AR_STA_ID0, AR_PHY_BASE + (8 << 2) }; - u32 regHold[2]; - u32 patternData[4] = { 0x55555555, - 0xaaaaaaaa, - 0x66666666, - 0x99999999 }; - int i, j; - - for (i = 0; i < 2; i++) { - u32 addr = regAddr[i]; - u32 wrData, rdData; - - regHold[i] = REG_READ(ah, addr); - for (j = 0; j < 0x100; j++) { - wrData = (j << 16) | j; - REG_WRITE(ah, addr, wrData); - rdData = REG_READ(ah, addr); - if (rdData != wrData) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", - addr, wrData, rdData); - return false; - } - } - for (j = 0; j < 4; j++) { - wrData = patternData[j]; - REG_WRITE(ah, addr, wrData); - rdData = REG_READ(ah, addr); - if (wrData != rdData) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "address test failed " - "addr: 0x%08x - wr:0x%08x != rd:0x%08x\n", - addr, wrData, rdData); - return false; - } - } - REG_WRITE(ah, regAddr[i], regHold[i]); - } - udelay(100); - - return true; -} - -static const char *ath9k_hw_devname(u16 devid) -{ - switch (devid) { - case AR5416_DEVID_PCI: - return "Atheros 5416"; - case AR5416_DEVID_PCIE: - return "Atheros 5418"; - case AR9160_DEVID_PCI: - return "Atheros 9160"; - case AR5416_AR9100_DEVID: - return "Atheros 9100"; - case AR9280_DEVID_PCI: - case AR9280_DEVID_PCIE: - return "Atheros 9280"; - case AR9285_DEVID_PCIE: - return "Atheros 9285"; - case AR5416_DEVID_AR9287_PCI: - case AR5416_DEVID_AR9287_PCIE: - return "Atheros 9287"; - } - - return NULL; -} - -static void ath9k_hw_init_config(struct ath_hw *ah) -{ - int i; - - ah->config.dma_beacon_response_time = 2; - ah->config.sw_beacon_response_time = 10; - ah->config.additional_swba_backoff = 0; - ah->config.ack_6mb = 0x0; - ah->config.cwm_ignore_extcca = 0; - ah->config.pcie_powersave_enable = 0; - ah->config.pcie_clock_req = 0; - ah->config.pcie_waen = 0; - ah->config.analog_shiftreg = 1; - ah->config.ofdm_trig_low = 200; - ah->config.ofdm_trig_high = 500; - ah->config.cck_trig_high = 200; - ah->config.cck_trig_low = 100; - ah->config.enable_ani = 1; - ah->config.diversity_control = ATH9K_ANT_VARIABLE; - ah->config.antenna_switch_swap = 0; - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - ah->config.spurchans[i][0] = AR_NO_SPUR; - ah->config.spurchans[i][1] = AR_NO_SPUR; - } - - if (ah->hw_version.devid != AR2427_DEVID_PCIE) - ah->config.ht_enable = 1; - else - ah->config.ht_enable = 0; - - ah->config.intr_mitigation = true; - - /* - * We need this for PCI devices only (Cardbus, PCI, miniPCI) - * _and_ if on non-uniprocessor systems (Multiprocessor/HT). - * This means we use it for all AR5416 devices, and the few - * minor PCI AR9280 devices out there. - * - * Serialization is required because these devices do not handle - * well the case of two concurrent reads/writes due to the latency - * involved. During one read/write another read/write can be issued - * on another CPU while the previous read/write may still be working - * on our hardware, if we hit this case the hardware poops in a loop. - * We prevent this by serializing reads and writes. - * - * This issue is not present on PCI-Express devices or pre-AR5416 - * devices (legacy, 802.11abg). - */ - if (num_possible_cpus() > 1) - ah->config.serialize_regmode = SER_REG_MODE_AUTO; -} - -static void ath9k_hw_init_defaults(struct ath_hw *ah) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - - regulatory->country_code = CTRY_DEFAULT; - regulatory->power_limit = MAX_RATE_POWER; - regulatory->tp_scale = ATH9K_TP_SCALE_MAX; - - ah->hw_version.magic = AR5416_MAGIC; - ah->hw_version.subvendorid = 0; - - ah->ah_flags = 0; - if (ah->hw_version.devid == AR5416_AR9100_DEVID) - ah->hw_version.macVersion = AR_SREV_VERSION_9100; - if (!AR_SREV_9100(ah)) - ah->ah_flags = AH_USE_EEPROM; - - ah->atim_window = 0; - ah->sta_id1_defaults = AR_STA_ID1_CRPT_MIC_ENABLE; - ah->beacon_interval = 100; - ah->enable_32kHz_clock = DONT_USE_32KHZ; - ah->slottime = (u32) -1; - ah->acktimeout = (u32) -1; - ah->ctstimeout = (u32) -1; - ah->globaltxtimeout = (u32) -1; - - ah->gbeacon_rate = 0; - - ah->power_mode = ATH9K_PM_UNDEFINED; -} - -static int ath9k_hw_rfattach(struct ath_hw *ah) -{ - bool rfStatus = false; - int ecode = 0; - - rfStatus = ath9k_hw_init_rf(ah, &ecode); - if (!rfStatus) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "RF setup failed, status: %u\n", ecode); - return ecode; - } - - return 0; -} - -static int ath9k_hw_rf_claim(struct ath_hw *ah) -{ - u32 val; - - REG_WRITE(ah, AR_PHY(0), 0x00000007); - - val = ath9k_hw_get_radiorev(ah); - switch (val & AR_RADIO_SREV_MAJOR) { - case 0: - val = AR_RAD5133_SREV_MAJOR; - break; - case AR_RAD5133_SREV_MAJOR: - case AR_RAD5122_SREV_MAJOR: - case AR_RAD2133_SREV_MAJOR: - case AR_RAD2122_SREV_MAJOR: - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Radio Chip Rev 0x%02X not supported\n", - val & AR_RADIO_SREV_MAJOR); - return -EOPNOTSUPP; - } - - ah->hw_version.analog5GhzRev = val; - - return 0; -} - -static int ath9k_hw_init_macaddr(struct ath_hw *ah) -{ - u32 sum; - int i; - u16 eeval; - - sum = 0; - for (i = 0; i < 3; i++) { - eeval = ah->eep_ops->get_eeprom(ah, AR_EEPROM_MAC(i)); - sum += eeval; - ah->macaddr[2 * i] = eeval >> 8; - ah->macaddr[2 * i + 1] = eeval & 0xff; - } - if (sum == 0 || sum == 0xffff * 3) - return -EADDRNOTAVAIL; - - return 0; -} - -static void ath9k_hw_init_rxgain_ini(struct ath_hw *ah) -{ - u32 rxgain_type; - - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_17) { - rxgain_type = ah->eep_ops->get_eeprom(ah, EEP_RXGAIN_TYPE); - - if (rxgain_type == AR5416_EEP_RXGAIN_13DB_BACKOFF) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_backoff_13db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_13db_rxgain_9280_2), 6); - else if (rxgain_type == AR5416_EEP_RXGAIN_23DB_BACKOFF) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_backoff_23db_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_backoff_23db_rxgain_9280_2), 6); - else - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9280Modes_original_rxgain_9280_2, - ARRAY_SIZE(ar9280Modes_original_rxgain_9280_2), 6); - } -} - -static void ath9k_hw_init_txgain_ini(struct ath_hw *ah) -{ - u32 txgain_type; - - if (ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV) >= AR5416_EEP_MINOR_VER_19) { - txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - - if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_high_power_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_high_power_tx_gain_9280_2), 6); - else - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9280Modes_original_tx_gain_9280_2, - ARRAY_SIZE(ar9280Modes_original_tx_gain_9280_2), 6); - } -} - -static int ath9k_hw_post_init(struct ath_hw *ah) -{ - int ecode; - - if (!ath9k_hw_chip_test(ah)) - return -ENODEV; - - ecode = ath9k_hw_rf_claim(ah); - if (ecode != 0) - return ecode; - - ecode = ath9k_hw_eeprom_init(ah); - if (ecode != 0) - return ecode; - - DPRINTF(ah->ah_sc, ATH_DBG_CONFIG, "Eeprom VER: %d, REV: %d\n", - ah->eep_ops->get_eeprom_ver(ah), ah->eep_ops->get_eeprom_rev(ah)); - - ecode = ath9k_hw_rfattach(ah); - if (ecode != 0) - return ecode; - - if (!AR_SREV_9100(ah)) { - ath9k_hw_ani_setup(ah); - ath9k_hw_ani_init(ah); - } - - return 0; -} - -static bool ath9k_hw_devid_supported(u16 devid) -{ - switch (devid) { - case AR5416_DEVID_PCI: - case AR5416_DEVID_PCIE: - case AR5416_AR9100_DEVID: - case AR9160_DEVID_PCI: - case AR9280_DEVID_PCI: - case AR9280_DEVID_PCIE: - case AR9285_DEVID_PCIE: - case AR5416_DEVID_AR9287_PCI: - case AR5416_DEVID_AR9287_PCIE: - case AR2427_DEVID_PCIE: - return true; - default: - break; - } - return false; -} - -static bool ath9k_hw_macversion_supported(u32 macversion) -{ - switch (macversion) { - case AR_SREV_VERSION_5416_PCI: - case AR_SREV_VERSION_5416_PCIE: - case AR_SREV_VERSION_9160: - case AR_SREV_VERSION_9100: - case AR_SREV_VERSION_9280: - case AR_SREV_VERSION_9285: - case AR_SREV_VERSION_9287: - return true; - /* Not yet */ - case AR_SREV_VERSION_9271: - default: - break; - } - return false; -} - -static void ath9k_hw_init_cal_settings(struct ath_hw *ah) -{ - if (AR_SREV_9160_10_OR_LATER(ah)) { - if (AR_SREV_9280_10_OR_LATER(ah)) { - ah->iq_caldata.calData = &iq_cal_single_sample; - ah->adcgain_caldata.calData = - &adc_gain_cal_single_sample; - ah->adcdc_caldata.calData = - &adc_dc_cal_single_sample; - ah->adcdc_calinitdata.calData = - &adc_init_dc_cal; - } else { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->adcgain_caldata.calData = - &adc_gain_cal_multi_sample; - ah->adcdc_caldata.calData = - &adc_dc_cal_multi_sample; - ah->adcdc_calinitdata.calData = - &adc_init_dc_cal; - } - ah->supp_cals = ADC_GAIN_CAL | ADC_DC_CAL | IQ_MISMATCH_CAL; - } -} - -static void ath9k_hw_init_mode_regs(struct ath_hw *ah) -{ - if (AR_SREV_9271(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9271Modes_9271_1_0, - ARRAY_SIZE(ar9271Modes_9271_1_0), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9271Common_9271_1_0, - ARRAY_SIZE(ar9271Common_9271_1_0), 2); - return; - } - - if (AR_SREV_9287_11_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_1, - ARRAY_SIZE(ar9287Modes_9287_1_1), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_1, - ARRAY_SIZE(ar9287Common_9287_1_1), 2); - if (ah->config.pcie_clock_req) - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_off_L1_9287_1_1, - ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_1), 2); - else - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_always_on_L1_9287_1_1, - ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_1), - 2); - } else if (AR_SREV_9287_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9287Modes_9287_1_0, - ARRAY_SIZE(ar9287Modes_9287_1_0), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9287Common_9287_1_0, - ARRAY_SIZE(ar9287Common_9287_1_0), 2); - - if (ah->config.pcie_clock_req) - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_off_L1_9287_1_0, - ARRAY_SIZE(ar9287PciePhy_clkreq_off_L1_9287_1_0), 2); - else - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9287PciePhy_clkreq_always_on_L1_9287_1_0, - ARRAY_SIZE(ar9287PciePhy_clkreq_always_on_L1_9287_1_0), - 2); - } else if (AR_SREV_9285_12_OR_LATER(ah)) { - - - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285_1_2, - ARRAY_SIZE(ar9285Modes_9285_1_2), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285_1_2, - ARRAY_SIZE(ar9285Common_9285_1_2), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285_1_2, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285_1_2), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285_1_2, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285_1_2), - 2); - } - } else if (AR_SREV_9285_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9285Modes_9285, - ARRAY_SIZE(ar9285Modes_9285), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9285Common_9285, - ARRAY_SIZE(ar9285Common_9285), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_off_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_off_L1_9285), 2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9285PciePhy_clkreq_always_on_L1_9285, - ARRAY_SIZE(ar9285PciePhy_clkreq_always_on_L1_9285), 2); - } - } else if (AR_SREV_9280_20_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280_2, - ARRAY_SIZE(ar9280Modes_9280_2), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280_2, - ARRAY_SIZE(ar9280Common_9280_2), 2); - - if (ah->config.pcie_clock_req) { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9280PciePhy_clkreq_off_L1_9280, - ARRAY_SIZE(ar9280PciePhy_clkreq_off_L1_9280),2); - } else { - INIT_INI_ARRAY(&ah->iniPcieSerdes, - ar9280PciePhy_clkreq_always_on_L1_9280, - ARRAY_SIZE(ar9280PciePhy_clkreq_always_on_L1_9280), 2); - } - INIT_INI_ARRAY(&ah->iniModesAdditional, - ar9280Modes_fast_clock_9280_2, - ARRAY_SIZE(ar9280Modes_fast_clock_9280_2), 3); - } else if (AR_SREV_9280_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar9280Modes_9280, - ARRAY_SIZE(ar9280Modes_9280), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar9280Common_9280, - ARRAY_SIZE(ar9280Common_9280), 2); - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9160, - ARRAY_SIZE(ar5416Modes_9160), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9160, - ARRAY_SIZE(ar5416Common_9160), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9160, - ARRAY_SIZE(ar5416Bank0_9160), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9160, - ARRAY_SIZE(ar5416BB_RfGain_9160), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9160, - ARRAY_SIZE(ar5416Bank1_9160), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9160, - ARRAY_SIZE(ar5416Bank2_9160), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9160, - ARRAY_SIZE(ar5416Bank3_9160), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9160, - ARRAY_SIZE(ar5416Bank6_9160), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9160, - ARRAY_SIZE(ar5416Bank6TPC_9160), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9160, - ARRAY_SIZE(ar5416Bank7_9160), 2); - if (AR_SREV_9160_11(ah)) { - INIT_INI_ARRAY(&ah->iniAddac, - ar5416Addac_91601_1, - ARRAY_SIZE(ar5416Addac_91601_1), 2); - } else { - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9160, - ARRAY_SIZE(ar5416Addac_9160), 2); - } - } else if (AR_SREV_9100_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes_9100, - ARRAY_SIZE(ar5416Modes_9100), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common_9100, - ARRAY_SIZE(ar5416Common_9100), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0_9100, - ARRAY_SIZE(ar5416Bank0_9100), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain_9100, - ARRAY_SIZE(ar5416BB_RfGain_9100), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1_9100, - ARRAY_SIZE(ar5416Bank1_9100), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2_9100, - ARRAY_SIZE(ar5416Bank2_9100), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3_9100, - ARRAY_SIZE(ar5416Bank3_9100), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6_9100, - ARRAY_SIZE(ar5416Bank6_9100), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC_9100, - ARRAY_SIZE(ar5416Bank6TPC_9100), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7_9100, - ARRAY_SIZE(ar5416Bank7_9100), 2); - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac_9100, - ARRAY_SIZE(ar5416Addac_9100), 2); - } else { - INIT_INI_ARRAY(&ah->iniModes, ar5416Modes, - ARRAY_SIZE(ar5416Modes), 6); - INIT_INI_ARRAY(&ah->iniCommon, ar5416Common, - ARRAY_SIZE(ar5416Common), 2); - INIT_INI_ARRAY(&ah->iniBank0, ar5416Bank0, - ARRAY_SIZE(ar5416Bank0), 2); - INIT_INI_ARRAY(&ah->iniBB_RfGain, ar5416BB_RfGain, - ARRAY_SIZE(ar5416BB_RfGain), 3); - INIT_INI_ARRAY(&ah->iniBank1, ar5416Bank1, - ARRAY_SIZE(ar5416Bank1), 2); - INIT_INI_ARRAY(&ah->iniBank2, ar5416Bank2, - ARRAY_SIZE(ar5416Bank2), 2); - INIT_INI_ARRAY(&ah->iniBank3, ar5416Bank3, - ARRAY_SIZE(ar5416Bank3), 3); - INIT_INI_ARRAY(&ah->iniBank6, ar5416Bank6, - ARRAY_SIZE(ar5416Bank6), 3); - INIT_INI_ARRAY(&ah->iniBank6TPC, ar5416Bank6TPC, - ARRAY_SIZE(ar5416Bank6TPC), 3); - INIT_INI_ARRAY(&ah->iniBank7, ar5416Bank7, - ARRAY_SIZE(ar5416Bank7), 2); - INIT_INI_ARRAY(&ah->iniAddac, ar5416Addac, - ARRAY_SIZE(ar5416Addac), 2); - } -} - -static void ath9k_hw_init_mode_gain_regs(struct ath_hw *ah) -{ - if (AR_SREV_9287_11_OR_LATER(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9287Modes_rx_gain_9287_1_1, - ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_1), 6); - else if (AR_SREV_9287_10(ah)) - INIT_INI_ARRAY(&ah->iniModesRxGain, - ar9287Modes_rx_gain_9287_1_0, - ARRAY_SIZE(ar9287Modes_rx_gain_9287_1_0), 6); - else if (AR_SREV_9280_20(ah)) - ath9k_hw_init_rxgain_ini(ah); - - if (AR_SREV_9287_11_OR_LATER(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9287Modes_tx_gain_9287_1_1, - ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_1), 6); - } else if (AR_SREV_9287_10(ah)) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9287Modes_tx_gain_9287_1_0, - ARRAY_SIZE(ar9287Modes_tx_gain_9287_1_0), 6); - } else if (AR_SREV_9280_20(ah)) { - ath9k_hw_init_txgain_ini(ah); - } else if (AR_SREV_9285_12_OR_LATER(ah)) { - u32 txgain_type = ah->eep_ops->get_eeprom(ah, EEP_TXGAIN_TYPE); - - /* txgain table */ - if (txgain_type == AR5416_EEP_TXGAIN_HIGH_POWER) { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_high_power_tx_gain_9285_1_2, - ARRAY_SIZE(ar9285Modes_high_power_tx_gain_9285_1_2), 6); - } else { - INIT_INI_ARRAY(&ah->iniModesTxGain, - ar9285Modes_original_tx_gain_9285_1_2, - ARRAY_SIZE(ar9285Modes_original_tx_gain_9285_1_2), 6); - } - - } -} - -static void ath9k_hw_init_eeprom_fix(struct ath_hw *ah) -{ - u32 i, j; - - if (ah->hw_version.devid == AR9280_DEVID_PCI) { - - /* EEPROM Fixup */ - for (i = 0; i < ah->iniModes.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniModes, i, 0); - - for (j = 1; j < ah->iniModes.ia_columns; j++) { - u32 val = INI_RA(&ah->iniModes, i, j); - - INI_RA(&ah->iniModes, i, j) = - ath9k_hw_ini_fixup(ah, - &ah->eeprom.def, - reg, val); - } - } - } -} - -int ath9k_hw_init(struct ath_hw *ah) -{ - int r = 0; - - if (!ath9k_hw_devid_supported(ah->hw_version.devid)) - return -EOPNOTSUPP; - - ath9k_hw_init_defaults(ah); - ath9k_hw_init_config(ah); - - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't reset chip\n"); - return -EIO; - } - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Couldn't wakeup chip\n"); - return -EIO; - } - - if (ah->config.serialize_regmode == SER_REG_MODE_AUTO) { - if (ah->hw_version.macVersion == AR_SREV_VERSION_5416_PCI || - ((AR_SREV_9160(ah) || AR_SREV_9280(ah)) && - !ah->is_pciexpress)) { - ah->config.serialize_regmode = - SER_REG_MODE_ON; - } else { - ah->config.serialize_regmode = - SER_REG_MODE_OFF; - } - } - - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "serialize_regmode is %d\n", - ah->config.serialize_regmode); - - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1; - else - ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD; - - if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Mac Chip Rev 0x%02x.%x is not supported by " - "this driver\n", ah->hw_version.macVersion, - ah->hw_version.macRev); - return -EOPNOTSUPP; - } - - if (AR_SREV_9100(ah)) { - ah->iq_caldata.calData = &iq_cal_multi_sample; - ah->supp_cals = IQ_MISMATCH_CAL; - ah->is_pciexpress = false; - } - - if (AR_SREV_9271(ah)) - ah->is_pciexpress = false; - - ah->hw_version.phyRev = REG_READ(ah, AR_PHY_CHIP_ID); - - ath9k_hw_init_cal_settings(ah); - - ah->ani_function = ATH9K_ANI_ALL; - if (AR_SREV_9280_10_OR_LATER(ah)) - ah->ani_function &= ~ATH9K_ANI_NOISE_IMMUNITY_LEVEL; - - ath9k_hw_init_mode_regs(ah); - - if (ah->is_pciexpress) - ath9k_hw_configpcipowersave(ah, 0, 0); - else - ath9k_hw_disablepcie(ah); - - r = ath9k_hw_post_init(ah); - if (r) - return r; - - ath9k_hw_init_mode_gain_regs(ah); - ath9k_hw_fill_cap_info(ah); - ath9k_hw_init_eeprom_fix(ah); - - r = ath9k_hw_init_macaddr(ah); - if (r) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to initialize MAC address\n"); - return r; - } - - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - ah->tx_trig_level = (AR_FTRIG_256B >> AR_FTRIG_S); - else - ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); - - ath9k_init_nfcal_hist_buffer(ah); - - return 0; -} - -static void ath9k_hw_init_bb(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 synthDelay; - - synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; - if (IS_CHAN_B(chan)) - synthDelay = (4 * synthDelay) / 22; - else - synthDelay /= 10; - - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); - - udelay(synthDelay + BASE_ACTIVATE_DELAY); -} - -static void ath9k_hw_init_qos(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_MIC_QOS_CONTROL, 0x100aa); - REG_WRITE(ah, AR_MIC_QOS_SELECT, 0x3210); - - REG_WRITE(ah, AR_QOS_NO_ACK, - SM(2, AR_QOS_NO_ACK_TWO_BIT) | - SM(5, AR_QOS_NO_ACK_BIT_OFF) | - SM(0, AR_QOS_NO_ACK_BYTE_OFF)); - - REG_WRITE(ah, AR_TXOP_X, AR_TXOP_X_VAL); - REG_WRITE(ah, AR_TXOP_0_3, 0xFFFFFFFF); - REG_WRITE(ah, AR_TXOP_4_7, 0xFFFFFFFF); - REG_WRITE(ah, AR_TXOP_8_11, 0xFFFFFFFF); - REG_WRITE(ah, AR_TXOP_12_15, 0xFFFFFFFF); -} - -static void ath9k_hw_init_pll(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 pll; - - if (AR_SREV_9100(ah)) { - if (chan && IS_CHAN_5GHZ(chan)) - pll = 0x1450; - else - pll = 0x1458; - } else { - if (AR_SREV_9280_10_OR_LATER(ah)) { - pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) { - pll |= SM(0x28, AR_RTC_9160_PLL_DIV); - - - if (AR_SREV_9280_20(ah)) { - if (((chan->channel % 20) == 0) - || ((chan->channel % 10) == 0)) - pll = 0x2850; - else - pll = 0x142c; - } - } else { - pll |= SM(0x2c, AR_RTC_9160_PLL_DIV); - } - - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - - pll = SM(0x5, AR_RTC_9160_PLL_REFDIV); - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_9160_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_9160_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) - pll |= SM(0x50, AR_RTC_9160_PLL_DIV); - else - pll |= SM(0x58, AR_RTC_9160_PLL_DIV); - } else { - pll = AR_RTC_PLL_REFDIV_5 | AR_RTC_PLL_DIV2; - - if (chan && IS_CHAN_HALF_RATE(chan)) - pll |= SM(0x1, AR_RTC_PLL_CLKSEL); - else if (chan && IS_CHAN_QUARTER_RATE(chan)) - pll |= SM(0x2, AR_RTC_PLL_CLKSEL); - - if (chan && IS_CHAN_5GHZ(chan)) - pll |= SM(0xa, AR_RTC_PLL_DIV); - else - pll |= SM(0xb, AR_RTC_PLL_DIV); - } - } - REG_WRITE(ah, AR_RTC_PLL_CONTROL, pll); - - udelay(RTC_PLL_SETTLE_DELAY); - - REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); -} - -static void ath9k_hw_init_chain_masks(struct ath_hw *ah) -{ - int rx_chainmask, tx_chainmask; - - rx_chainmask = ah->rxchainmask; - tx_chainmask = ah->txchainmask; - - switch (rx_chainmask) { - case 0x5: - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - case 0x3: - if (((ah)->hw_version.macVersion <= AR_SREV_VERSION_9160)) { - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, 0x7); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, 0x7); - break; - } - case 0x1: - case 0x2: - case 0x7: - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); - break; - default: - break; - } - - REG_WRITE(ah, AR_SELFGEN_MASK, tx_chainmask); - if (tx_chainmask == 0x5) { - REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, - AR_PHY_SWAP_ALT_CHAIN); - } - if (AR_SREV_9100(ah)) - REG_WRITE(ah, AR_PHY_ANALOG_SWAP, - REG_READ(ah, AR_PHY_ANALOG_SWAP) | 0x00000001); -} - -static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, - enum nl80211_iftype opmode) -{ - ah->mask_reg = AR_IMR_TXERR | - AR_IMR_TXURN | - AR_IMR_RXERR | - AR_IMR_RXORN | - AR_IMR_BCNMISC; - - if (ah->config.intr_mitigation) - ah->mask_reg |= AR_IMR_RXINTM | AR_IMR_RXMINTR; - else - ah->mask_reg |= AR_IMR_RXOK; - - ah->mask_reg |= AR_IMR_TXOK; - - if (opmode == NL80211_IFTYPE_AP) - ah->mask_reg |= AR_IMR_MIB; - - REG_WRITE(ah, AR_IMR, ah->mask_reg); - REG_WRITE(ah, AR_IMR_S2, REG_READ(ah, AR_IMR_S2) | AR_IMR_S2_GTT); - - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_SYNC_CAUSE, 0xFFFFFFFF); - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, 0); - } -} - -static bool ath9k_hw_set_ack_timeout(struct ath_hw *ah, u32 us) -{ - if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_ACK))) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad ack timeout %u\n", us); - ah->acktimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_TIME_OUT, - AR_TIME_OUT_ACK, ath9k_hw_mac_to_clks(ah, us)); - ah->acktimeout = us; - return true; - } -} - -static bool ath9k_hw_set_cts_timeout(struct ath_hw *ah, u32 us) -{ - if (us > ath9k_hw_mac_to_usec(ah, MS(0xffffffff, AR_TIME_OUT_CTS))) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad cts timeout %u\n", us); - ah->ctstimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_TIME_OUT, - AR_TIME_OUT_CTS, ath9k_hw_mac_to_clks(ah, us)); - ah->ctstimeout = us; - return true; - } -} - -static bool ath9k_hw_set_global_txtimeout(struct ath_hw *ah, u32 tu) -{ - if (tu > 0xFFFF) { - DPRINTF(ah->ah_sc, ATH_DBG_XMIT, - "bad global tx timeout %u\n", tu); - ah->globaltxtimeout = (u32) -1; - return false; - } else { - REG_RMW_FIELD(ah, AR_GTXTO, AR_GTXTO_TIMEOUT_LIMIT, tu); - ah->globaltxtimeout = tu; - return true; - } -} - -static void ath9k_hw_init_user_settings(struct ath_hw *ah) -{ - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "ah->misc_mode 0x%x\n", - ah->misc_mode); - - if (ah->misc_mode != 0) - REG_WRITE(ah, AR_PCU_MISC, - REG_READ(ah, AR_PCU_MISC) | ah->misc_mode); - if (ah->slottime != (u32) -1) - ath9k_hw_setslottime(ah, ah->slottime); - if (ah->acktimeout != (u32) -1) - ath9k_hw_set_ack_timeout(ah, ah->acktimeout); - if (ah->ctstimeout != (u32) -1) - ath9k_hw_set_cts_timeout(ah, ah->ctstimeout); - if (ah->globaltxtimeout != (u32) -1) - ath9k_hw_set_global_txtimeout(ah, ah->globaltxtimeout); -} - -const char *ath9k_hw_probe(u16 vendorid, u16 devid) -{ - return vendorid == ATHEROS_VENDOR_ID ? - ath9k_hw_devname(devid) : NULL; -} - -void ath9k_hw_detach(struct ath_hw *ah) -{ - if (!AR_SREV_9100(ah)) - ath9k_hw_ani_disable(ah); - - ath9k_hw_rf_free(ah); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); - kfree(ah); - ah = NULL; -} - -/*******/ -/* INI */ -/*******/ - -static void ath9k_hw_override_ini(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 val; - - if (AR_SREV_9271(ah)) { - /* - * Enable spectral scan to solution for issues with stuck - * beacons on AR9271 1.0. The beacon stuck issue is not seeon on - * AR9271 1.1 - */ - if (AR_SREV_9271_10(ah)) { - val = REG_READ(ah, AR_PHY_SPECTRAL_SCAN) | AR_PHY_SPECTRAL_SCAN_ENABLE; - REG_WRITE(ah, AR_PHY_SPECTRAL_SCAN, val); - } - else if (AR_SREV_9271_11(ah)) - /* - * change AR_PHY_RF_CTL3 setting to fix MAC issue - * present on AR9271 1.1 - */ - REG_WRITE(ah, AR_PHY_RF_CTL3, 0x3a020001); - return; - } - - /* - * Set the RX_ABORT and RX_DIS and clear if off only after - * RXE is set for MAC. This prevents frames with corrupted - * descriptor status. - */ - REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - val = REG_READ(ah, AR_PCU_MISC_MODE2) & - (~AR_PCU_MISC_MODE2_HWWAR1); - - if (AR_SREV_9287_10_OR_LATER(ah)) - val = val & (~AR_PCU_MISC_MODE2_HWWAR2); - - REG_WRITE(ah, AR_PCU_MISC_MODE2, val); - } - - if (!AR_SREV_5416_20_OR_LATER(ah) || - AR_SREV_9280_10_OR_LATER(ah)) - return; - /* - * Disable BB clock gating - * Necessary to avoid issues on AR5416 2.0 - */ - REG_WRITE(ah, 0x9800 + (651 << 2), 0x11); - - /* - * Disable RIFS search on some chips to avoid baseband - * hang issues. - */ - if (AR_SREV_9100(ah) || AR_SREV_9160(ah)) { - val = REG_READ(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS); - val &= ~AR_PHY_RIFS_INIT_DELAY; - REG_WRITE(ah, AR_PHY_HEAVY_CLIP_FACTOR_RIFS, val); - } -} - -static u32 ath9k_hw_def_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value) -{ - struct base_eep_header *pBase = &(pEepData->baseEepHeader); - - switch (ah->hw_version.devid) { - case AR9280_DEVID_PCI: - if (reg == 0x7894) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "ini VAL: %x EEPROM: %x\n", value, - (pBase->version & 0xff)); - - if ((pBase->version & 0xff) > 0x0a) { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PWDCLKIND: %d\n", - pBase->pwdclkind); - value &= ~AR_AN_TOP2_PWDCLKIND; - value |= AR_AN_TOP2_PWDCLKIND & - (pBase->pwdclkind << AR_AN_TOP2_PWDCLKIND_S); - } else { - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "PWDCLKIND Earlier Rev\n"); - } - - DPRINTF(ah->ah_sc, ATH_DBG_EEPROM, - "final ini VAL: %x\n", value); - } - break; - } - - return value; -} - -static u32 ath9k_hw_ini_fixup(struct ath_hw *ah, - struct ar5416_eeprom_def *pEepData, - u32 reg, u32 value) -{ - if (ah->eep_map == EEP_MAP_4KBITS) - return value; - else - return ath9k_hw_def_ini_fixup(ah, pEepData, reg, value); -} - -static void ath9k_olc_init(struct ath_hw *ah) -{ - u32 i; - - if (OLC_FOR_AR9287_10_LATER) { - REG_SET_BIT(ah, AR_PHY_TX_PWRCTRL9, - AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL); - ath9k_hw_analog_shift_rmw(ah, AR9287_AN_TXPC0, - AR9287_AN_TXPC0_TXPCMODE, - AR9287_AN_TXPC0_TXPCMODE_S, - AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE); - udelay(100); - } else { - for (i = 0; i < AR9280_TX_GAIN_TABLE_SIZE; i++) - ah->originalGain[i] = - MS(REG_READ(ah, AR_PHY_TX_GAIN_TBL1 + i * 4), - AR_PHY_TX_GAIN); - ah->PDADCdelta = 0; - } -} - -static u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, - struct ath9k_channel *chan) -{ - u32 ctl = ath_regd_get_band_ctl(reg, chan->chan->band); - - if (IS_CHAN_B(chan)) - ctl |= CTL_11B; - else if (IS_CHAN_G(chan)) - ctl |= CTL_11G; - else - ctl |= CTL_11A; - - return ctl; -} - -static int ath9k_hw_process_ini(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - int i, regWrites = 0; - struct ieee80211_channel *channel = chan->chan; - u32 modesIndex, freqIndex; - - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - modesIndex = 1; - freqIndex = 1; - break; - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: - modesIndex = 2; - freqIndex = 1; - break; - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_B: - modesIndex = 4; - freqIndex = 2; - break; - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: - modesIndex = 3; - freqIndex = 2; - break; - - default: - return -EINVAL; - } - - REG_WRITE(ah, AR_PHY(0), 0x00000007); - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_EXTERNAL_RADIO); - ah->eep_ops->set_addac(ah, chan); - - if (AR_SREV_5416_22_OR_LATER(ah)) { - REG_WRITE_ARRAY(&ah->iniAddac, 1, regWrites); - } else { - struct ar5416IniArray temp; - u32 addacSize = - sizeof(u32) * ah->iniAddac.ia_rows * - ah->iniAddac.ia_columns; - - memcpy(ah->addac5416_21, - ah->iniAddac.ia_array, addacSize); - - (ah->addac5416_21)[31 * ah->iniAddac.ia_columns + 1] = 0; - - temp.ia_array = ah->addac5416_21; - temp.ia_columns = ah->iniAddac.ia_columns; - temp.ia_rows = ah->iniAddac.ia_rows; - REG_WRITE_ARRAY(&temp, 1, regWrites); - } - - REG_WRITE(ah, AR_PHY_ADC_SERIAL_CTL, AR_PHY_SEL_INTERNAL_ADDAC); - - for (i = 0; i < ah->iniModes.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniModes, i, 0); - u32 val = INI_RA(&ah->iniModes, i, modesIndex); - - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { - udelay(100); - } - - DO_DELAY(regWrites); - } - - if (AR_SREV_9280(ah) || AR_SREV_9287_10_OR_LATER(ah)) - REG_WRITE_ARRAY(&ah->iniModesRxGain, modesIndex, regWrites); - - if (AR_SREV_9280(ah) || AR_SREV_9285_12_OR_LATER(ah) || - AR_SREV_9287_10_OR_LATER(ah)) - REG_WRITE_ARRAY(&ah->iniModesTxGain, modesIndex, regWrites); - - for (i = 0; i < ah->iniCommon.ia_rows; i++) { - u32 reg = INI_RA(&ah->iniCommon, i, 0); - u32 val = INI_RA(&ah->iniCommon, i, 1); - - REG_WRITE(ah, reg, val); - - if (reg >= 0x7800 && reg < 0x78a0 - && ah->config.analog_shiftreg) { - udelay(100); - } - - DO_DELAY(regWrites); - } - - ath9k_hw_write_regs(ah, modesIndex, freqIndex, regWrites); - - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) { - REG_WRITE_ARRAY(&ah->iniModesAdditional, modesIndex, - regWrites); - } - - ath9k_hw_override_ini(ah, chan); - ath9k_hw_set_regs(ah, chan, macmode); - ath9k_hw_init_chain_masks(ah); - - if (OLC_FOR_AR9280_20_LATER) - ath9k_olc_init(ah); - - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); - - if (!ath9k_hw_set_rf_regs(ah, chan, freqIndex)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "ar5416SetRfRegs failed\n"); - return -EIO; - } - - return 0; -} - -/****************************************/ -/* Reset and Channel Switching Routines */ -/****************************************/ - -static void ath9k_hw_set_rfmode(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u32 rfMode = 0; - - if (chan == NULL) - return; - - rfMode |= (IS_CHAN_B(chan) || IS_CHAN_G(chan)) - ? AR_PHY_MODE_DYNAMIC : AR_PHY_MODE_OFDM; - - if (!AR_SREV_9280_10_OR_LATER(ah)) - rfMode |= (IS_CHAN_5GHZ(chan)) ? - AR_PHY_MODE_RF5GHZ : AR_PHY_MODE_RF2GHZ; - - if (AR_SREV_9280_20(ah) && IS_CHAN_A_5MHZ_SPACED(chan)) - rfMode |= (AR_PHY_MODE_DYNAMIC | AR_PHY_MODE_DYN_CCK_DISABLE); - - REG_WRITE(ah, AR_PHY_MODE, rfMode); -} - -static void ath9k_hw_mark_phy_inactive(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); -} - -static inline void ath9k_hw_set_dma(struct ath_hw *ah) -{ - u32 regval; - - /* - * set AHB_MODE not to do cacheline prefetches - */ - regval = REG_READ(ah, AR_AHB_MODE); - REG_WRITE(ah, AR_AHB_MODE, regval | AR_AHB_PREFETCH_RD_EN); - - /* - * let mac dma reads be in 128 byte chunks - */ - regval = REG_READ(ah, AR_TXCFG) & ~AR_TXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_TXCFG, regval | AR_TXCFG_DMASZ_128B); - - /* - * Restore TX Trigger Level to its pre-reset value. - * The initial value depends on whether aggregation is enabled, and is - * adjusted whenever underruns are detected. - */ - REG_RMW_FIELD(ah, AR_TXCFG, AR_FTRIG, ah->tx_trig_level); - - /* - * let mac dma writes be in 128 byte chunks - */ - regval = REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_DMASZ_MASK; - REG_WRITE(ah, AR_RXCFG, regval | AR_RXCFG_DMASZ_128B); - - /* - * Setup receive FIFO threshold to hold off TX activities - */ - REG_WRITE(ah, AR_RXFIFO_CFG, 0x200); - - /* - * reduce the number of usable entries in PCU TXBUF to avoid - * wrap around issues. - */ - if (AR_SREV_9285(ah)) { - /* For AR9285 the number of Fifos are reduced to half. - * So set the usable tx buf size also to half to - * avoid data/delimiter underruns - */ - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); - } else if (!AR_SREV_9271(ah)) { - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_PCU_TXBUF_CTRL_USABLE_SIZE); - } -} - -static void ath9k_hw_set_operating_mode(struct ath_hw *ah, int opmode) -{ - u32 val; - - val = REG_READ(ah, AR_STA_ID1); - val &= ~(AR_STA_ID1_STA_AP | AR_STA_ID1_ADHOC); - switch (opmode) { - case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_STA_AP - | AR_STA_ID1_KSRCH_MODE); - REG_CLR_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_ADHOC - | AR_STA_ID1_KSRCH_MODE); - REG_SET_BIT(ah, AR_CFG, AR_CFG_AP_ADHOC_INDICATION); - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_MONITOR: - REG_WRITE(ah, AR_STA_ID1, val | AR_STA_ID1_KSRCH_MODE); - break; - } -} - -static inline void ath9k_hw_get_delta_slope_vals(struct ath_hw *ah, - u32 coef_scaled, - u32 *coef_mantissa, - u32 *coef_exponent) -{ - u32 coef_exp, coef_man; - - for (coef_exp = 31; coef_exp > 0; coef_exp--) - if ((coef_scaled >> coef_exp) & 0x1) - break; - - coef_exp = 14 - (coef_exp - COEF_SCALE_S); - - coef_man = coef_scaled + (1 << (COEF_SCALE_S - coef_exp - 1)); - - *coef_mantissa = coef_man >> (COEF_SCALE_S - coef_exp); - *coef_exponent = coef_exp - 16; -} - -static void ath9k_hw_set_delta_slope(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u32 coef_scaled, ds_coef_exp, ds_coef_man; - u32 clockMhzScaled = 0x64000000; - struct chan_centers centers; - - if (IS_CHAN_HALF_RATE(chan)) - clockMhzScaled = clockMhzScaled >> 1; - else if (IS_CHAN_QUARTER_RATE(chan)) - clockMhzScaled = clockMhzScaled >> 2; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - coef_scaled = clockMhzScaled / centers.synth_center; - - ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, - &ds_coef_exp); - - REG_RMW_FIELD(ah, AR_PHY_TIMING3, - AR_PHY_TIMING3_DSC_MAN, ds_coef_man); - REG_RMW_FIELD(ah, AR_PHY_TIMING3, - AR_PHY_TIMING3_DSC_EXP, ds_coef_exp); - - coef_scaled = (9 * coef_scaled) / 10; - - ath9k_hw_get_delta_slope_vals(ah, coef_scaled, &ds_coef_man, - &ds_coef_exp); - - REG_RMW_FIELD(ah, AR_PHY_HALFGI, - AR_PHY_HALFGI_DSC_MAN, ds_coef_man); - REG_RMW_FIELD(ah, AR_PHY_HALFGI, - AR_PHY_HALFGI_DSC_EXP, ds_coef_exp); -} - -static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) -{ - u32 rst_flags; - u32 tmpReg; - - if (AR_SREV_9100(ah)) { - u32 val = REG_READ(ah, AR_RTC_DERIVED_CLK); - val &= ~AR_RTC_DERIVED_CLK_PERIOD; - val |= SM(1, AR_RTC_DERIVED_CLK_PERIOD); - REG_WRITE(ah, AR_RTC_DERIVED_CLK, val); - (void)REG_READ(ah, AR_RTC_DERIVED_CLK); - } - - REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | - AR_RTC_FORCE_WAKE_ON_INT); - - if (AR_SREV_9100(ah)) { - rst_flags = AR_RTC_RC_MAC_WARM | AR_RTC_RC_MAC_COLD | - AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; - } else { - tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if (tmpReg & - (AR_INTR_SYNC_LOCAL_TIMEOUT | - AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - } else { - REG_WRITE(ah, AR_RC, AR_RC_AHB); - } - - rst_flags = AR_RTC_RC_MAC_WARM; - if (type == ATH9K_RESET_COLD) - rst_flags |= AR_RTC_RC_MAC_COLD; - } - - REG_WRITE(ah, AR_RTC_RC, rst_flags); - udelay(50); - - REG_WRITE(ah, AR_RTC_RC, 0); - if (!ath9k_hw_wait(ah, AR_RTC_RC, AR_RTC_RC_M, 0, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "RTC stuck in MAC reset\n"); - return false; - } - - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, 0); - - ath9k_hw_init_pll(ah, NULL); - - if (AR_SREV_9100(ah)) - udelay(50); - - return true; -} - -static bool ath9k_hw_set_reset_power_on(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_RTC_FORCE_WAKE, AR_RTC_FORCE_WAKE_EN | - AR_RTC_FORCE_WAKE_ON_INT); - - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, AR_RC_AHB); - - REG_WRITE(ah, AR_RTC_RESET, 0); - udelay(2); - - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, 0); - - REG_WRITE(ah, AR_RTC_RESET, 1); - - if (!ath9k_hw_wait(ah, - AR_RTC_STATUS, - AR_RTC_STATUS_M, - AR_RTC_STATUS_ON, - AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "RTC not waking up\n"); - return false; - } - - ath9k_hw_read_revisions(ah); - - return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM); -} - -static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type) -{ - REG_WRITE(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN | AR_RTC_FORCE_WAKE_ON_INT); - - switch (type) { - case ATH9K_RESET_POWER_ON: - return ath9k_hw_set_reset_power_on(ah); - case ATH9K_RESET_WARM: - case ATH9K_RESET_COLD: - return ath9k_hw_set_reset(ah, type); - default: - return false; - } -} - -static void ath9k_hw_set_regs(struct ath_hw *ah, struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) -{ - u32 phymode; - u32 enableDacFifo = 0; - - if (AR_SREV_9285_10_OR_LATER(ah)) - enableDacFifo = (REG_READ(ah, AR_PHY_TURBO) & - AR_PHY_FC_ENABLE_DAC_FIFO); - - phymode = AR_PHY_FC_HT_EN | AR_PHY_FC_SHORT_GI_40 - | AR_PHY_FC_SINGLE_HT_LTF1 | AR_PHY_FC_WALSH | enableDacFifo; - - if (IS_CHAN_HT40(chan)) { - phymode |= AR_PHY_FC_DYN2040_EN; - - if ((chan->chanmode == CHANNEL_A_HT40PLUS) || - (chan->chanmode == CHANNEL_G_HT40PLUS)) - phymode |= AR_PHY_FC_DYN2040_PRI_CH; - - if (ah->extprotspacing == ATH9K_HT_EXTPROTSPACING_25) - phymode |= AR_PHY_FC_DYN2040_EXT_CH; - } - REG_WRITE(ah, AR_PHY_TURBO, phymode); - - ath9k_hw_set11nmac2040(ah, macmode); - - REG_WRITE(ah, AR_GTXTO, 25 << AR_GTXTO_TIMEOUT_LIMIT_S); - REG_WRITE(ah, AR_CST, 0xF << AR_CST_TIMEOUT_LIMIT_S); -} - -static bool ath9k_hw_chip_reset(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - if (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL)) { - if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) - return false; - } else if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM)) - return false; - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return false; - - ah->chip_fullsleep = false; - ath9k_hw_init_pll(ah, chan); - ath9k_hw_set_rfmode(ah, chan); - - return true; -} - -static bool ath9k_hw_channel_change(struct ath_hw *ah, - struct ath9k_channel *chan, - enum ath9k_ht_macmode macmode) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ieee80211_channel *channel = chan->chan; - u32 synthDelay, qnum; - - for (qnum = 0; qnum < AR_NUM_QCU; qnum++) { - if (ath9k_hw_numtxpending(ah, qnum)) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "Transmit frames pending on queue %d\n", qnum); - return false; - } - } - - REG_WRITE(ah, AR_PHY_RFBUS_REQ, AR_PHY_RFBUS_REQ_EN); - if (!ath9k_hw_wait(ah, AR_PHY_RFBUS_GRANT, AR_PHY_RFBUS_GRANT_EN, - AR_PHY_RFBUS_GRANT_EN, AH_WAIT_TIMEOUT)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Could not kill baseband RX\n"); - return false; - } - - ath9k_hw_set_regs(ah, chan, macmode); - - if (AR_SREV_9280_10_OR_LATER(ah)) { - ath9k_hw_ar9280_set_channel(ah, chan); - } else { - if (!(ath9k_hw_set_channel(ah, chan))) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to set channel\n"); - return false; - } - } - - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); - - synthDelay = REG_READ(ah, AR_PHY_RX_DELAY) & AR_PHY_RX_DELAY_DELAY; - if (IS_CHAN_B(chan)) - synthDelay = (4 * synthDelay) / 22; - else - synthDelay /= 10; - - udelay(synthDelay + BASE_ACTIVATE_DELAY); - - REG_WRITE(ah, AR_PHY_RFBUS_REQ, 0); - - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) - ath9k_hw_set_delta_slope(ah, chan); - - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_9280_spur_mitigate(ah, chan); - else - ath9k_hw_spur_mitigate(ah, chan); - - if (!chan->oneTimeCalsDone) - chan->oneTimeCalsDone = true; - - return true; -} - -static void ath9k_hw_9280_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int freq; - int bin, cur_bin; - int bb_spur_off, spur_subchannel_sd; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, newVal; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - struct chan_centers centers; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - ah->config.spurmode = SPUR_ENABLE_EEPROM; - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - - if (is2GHz) - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_2GHZ; - else - cur_bb_spur = (cur_bb_spur / 10) + AR_BASE_FREQ_5GHZ; - - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - freq; - - if (IS_CHAN_HT40(chan)) { - if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT40) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT40)) { - bb_spur = cur_bb_spur; - break; - } - } else if ((cur_bb_spur > -AR_SPUR_FEEQ_BOUND_HT20) && - (cur_bb_spur < AR_SPUR_FEEQ_BOUND_HT20)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - return; - } else { - REG_CLR_BIT(ah, AR_PHY_FORCE_CLKEN_CCK, - AR_PHY_FORCE_CLKEN_CCK_MRC_MUX); - } - - bin = bb_spur * 320; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - - newVal = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), newVal); - - newVal = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, newVal); - - if (IS_CHAN_HT40(chan)) { - if (bb_spur < 0) { - spur_subchannel_sd = 1; - bb_spur_off = bb_spur + 10; - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur - 10; - } - } else { - spur_subchannel_sd = 0; - bb_spur_off = bb_spur; - } - - if (IS_CHAN_HT40(chan)) - spur_delta_phase = - ((bb_spur * 262144) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - else - spur_delta_phase = - ((bb_spur * 524288) / - 10) & AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 44 : 40; - spur_freq_sd = ((bb_spur_off * 2048) / denominator) & 0x3ff; - - newVal = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, newVal); - - newVal = spur_subchannel_sd << AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S; - REG_WRITE(ah, AR_PHY_SFCORR_EXT, newVal); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -static void ath9k_hw_spur_mitigate(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int bb_spur = AR_NO_SPUR; - int bin, cur_bin; - int spur_freq_sd; - int spur_delta_phase; - int denominator; - int upper, lower, cur_vit_mask; - int tmp, new; - int i; - int pilot_mask_reg[4] = { AR_PHY_TIMING7, AR_PHY_TIMING8, - AR_PHY_PILOT_MASK_01_30, AR_PHY_PILOT_MASK_31_60 - }; - int chan_mask_reg[4] = { AR_PHY_TIMING9, AR_PHY_TIMING10, - AR_PHY_CHANNEL_MASK_01_30, AR_PHY_CHANNEL_MASK_31_60 - }; - int inc[4] = { 0, 100, 0, 0 }; - - int8_t mask_m[123]; - int8_t mask_p[123]; - int8_t mask_amt; - int tmp_mask; - int cur_bb_spur; - bool is2GHz = IS_CHAN_2GHZ(chan); - - memset(&mask_m, 0, sizeof(int8_t) * 123); - memset(&mask_p, 0, sizeof(int8_t) * 123); - - for (i = 0; i < AR_EEPROM_MODAL_SPURS; i++) { - cur_bb_spur = ah->eep_ops->get_spur_channel(ah, i, is2GHz); - if (AR_NO_SPUR == cur_bb_spur) - break; - cur_bb_spur = cur_bb_spur - (chan->channel * 10); - if ((cur_bb_spur > -95) && (cur_bb_spur < 95)) { - bb_spur = cur_bb_spur; - break; - } - } - - if (AR_NO_SPUR == bb_spur) - return; - - bin = bb_spur * 32; - - tmp = REG_READ(ah, AR_PHY_TIMING_CTRL4(0)); - new = tmp | (AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI | - AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER | - AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK | - AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK); - - REG_WRITE(ah, AR_PHY_TIMING_CTRL4(0), new); - - new = (AR_PHY_SPUR_REG_MASK_RATE_CNTL | - AR_PHY_SPUR_REG_ENABLE_MASK_PPM | - AR_PHY_SPUR_REG_MASK_RATE_SELECT | - AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI | - SM(SPUR_RSSI_THRESH, AR_PHY_SPUR_REG_SPUR_RSSI_THRESH)); - REG_WRITE(ah, AR_PHY_SPUR_REG, new); - - spur_delta_phase = ((bb_spur * 524288) / 100) & - AR_PHY_TIMING11_SPUR_DELTA_PHASE; - - denominator = IS_CHAN_2GHZ(chan) ? 440 : 400; - spur_freq_sd = ((bb_spur * 2048) / denominator) & 0x3ff; - - new = (AR_PHY_TIMING11_USE_SPUR_IN_AGC | - SM(spur_freq_sd, AR_PHY_TIMING11_SPUR_FREQ_SD) | - SM(spur_delta_phase, AR_PHY_TIMING11_SPUR_DELTA_PHASE)); - REG_WRITE(ah, AR_PHY_TIMING11, new); - - cur_bin = -6000; - upper = bin + 100; - lower = bin - 100; - - for (i = 0; i < 4; i++) { - int pilot_mask = 0; - int chan_mask = 0; - int bp = 0; - for (bp = 0; bp < 30; bp++) { - if ((cur_bin > lower) && (cur_bin < upper)) { - pilot_mask = pilot_mask | 0x1 << bp; - chan_mask = chan_mask | 0x1 << bp; - } - cur_bin += 100; - } - cur_bin += inc[i]; - REG_WRITE(ah, pilot_mask_reg[i], pilot_mask); - REG_WRITE(ah, chan_mask_reg[i], chan_mask); - } - - cur_vit_mask = 6100; - upper = bin + 120; - lower = bin - 120; - - for (i = 0; i < 123; i++) { - if ((cur_vit_mask > lower) && (cur_vit_mask < upper)) { - - /* workaround for gcc bug #37014 */ - volatile int tmp_v = abs(cur_vit_mask - bin); - - if (tmp_v < 75) - mask_amt = 1; - else - mask_amt = 0; - if (cur_vit_mask < 0) - mask_m[abs(cur_vit_mask / 100)] = mask_amt; - else - mask_p[cur_vit_mask / 100] = mask_amt; - } - cur_vit_mask -= 100; - } - - tmp_mask = (mask_m[46] << 30) | (mask_m[47] << 28) - | (mask_m[48] << 26) | (mask_m[49] << 24) - | (mask_m[50] << 22) | (mask_m[51] << 20) - | (mask_m[52] << 18) | (mask_m[53] << 16) - | (mask_m[54] << 14) | (mask_m[55] << 12) - | (mask_m[56] << 10) | (mask_m[57] << 8) - | (mask_m[58] << 6) | (mask_m[59] << 4) - | (mask_m[60] << 2) | (mask_m[61] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_1, tmp_mask); - REG_WRITE(ah, AR_PHY_VIT_MASK2_M_46_61, tmp_mask); - - tmp_mask = (mask_m[31] << 28) - | (mask_m[32] << 26) | (mask_m[33] << 24) - | (mask_m[34] << 22) | (mask_m[35] << 20) - | (mask_m[36] << 18) | (mask_m[37] << 16) - | (mask_m[48] << 14) | (mask_m[39] << 12) - | (mask_m[40] << 10) | (mask_m[41] << 8) - | (mask_m[42] << 6) | (mask_m[43] << 4) - | (mask_m[44] << 2) | (mask_m[45] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_31_45, tmp_mask); - - tmp_mask = (mask_m[16] << 30) | (mask_m[16] << 28) - | (mask_m[18] << 26) | (mask_m[18] << 24) - | (mask_m[20] << 22) | (mask_m[20] << 20) - | (mask_m[22] << 18) | (mask_m[22] << 16) - | (mask_m[24] << 14) | (mask_m[24] << 12) - | (mask_m[25] << 10) | (mask_m[26] << 8) - | (mask_m[27] << 6) | (mask_m[28] << 4) - | (mask_m[29] << 2) | (mask_m[30] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_16_30, tmp_mask); - - tmp_mask = (mask_m[0] << 30) | (mask_m[1] << 28) - | (mask_m[2] << 26) | (mask_m[3] << 24) - | (mask_m[4] << 22) | (mask_m[5] << 20) - | (mask_m[6] << 18) | (mask_m[7] << 16) - | (mask_m[8] << 14) | (mask_m[9] << 12) - | (mask_m[10] << 10) | (mask_m[11] << 8) - | (mask_m[12] << 6) | (mask_m[13] << 4) - | (mask_m[14] << 2) | (mask_m[15] << 0); - REG_WRITE(ah, AR_PHY_MASK_CTL, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_M_00_15, tmp_mask); - - tmp_mask = (mask_p[15] << 28) - | (mask_p[14] << 26) | (mask_p[13] << 24) - | (mask_p[12] << 22) | (mask_p[11] << 20) - | (mask_p[10] << 18) | (mask_p[9] << 16) - | (mask_p[8] << 14) | (mask_p[7] << 12) - | (mask_p[6] << 10) | (mask_p[5] << 8) - | (mask_p[4] << 6) | (mask_p[3] << 4) - | (mask_p[2] << 2) | (mask_p[1] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_1, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_15_01, tmp_mask); - - tmp_mask = (mask_p[30] << 28) - | (mask_p[29] << 26) | (mask_p[28] << 24) - | (mask_p[27] << 22) | (mask_p[26] << 20) - | (mask_p[25] << 18) | (mask_p[24] << 16) - | (mask_p[23] << 14) | (mask_p[22] << 12) - | (mask_p[21] << 10) | (mask_p[20] << 8) - | (mask_p[19] << 6) | (mask_p[18] << 4) - | (mask_p[17] << 2) | (mask_p[16] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_2, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_30_16, tmp_mask); - - tmp_mask = (mask_p[45] << 28) - | (mask_p[44] << 26) | (mask_p[43] << 24) - | (mask_p[42] << 22) | (mask_p[41] << 20) - | (mask_p[40] << 18) | (mask_p[39] << 16) - | (mask_p[38] << 14) | (mask_p[37] << 12) - | (mask_p[36] << 10) | (mask_p[35] << 8) - | (mask_p[34] << 6) | (mask_p[33] << 4) - | (mask_p[32] << 2) | (mask_p[31] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_3, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_45_31, tmp_mask); - - tmp_mask = (mask_p[61] << 30) | (mask_p[60] << 28) - | (mask_p[59] << 26) | (mask_p[58] << 24) - | (mask_p[57] << 22) | (mask_p[56] << 20) - | (mask_p[55] << 18) | (mask_p[54] << 16) - | (mask_p[53] << 14) | (mask_p[52] << 12) - | (mask_p[51] << 10) | (mask_p[50] << 8) - | (mask_p[49] << 6) | (mask_p[48] << 4) - | (mask_p[47] << 2) | (mask_p[46] << 0); - REG_WRITE(ah, AR_PHY_BIN_MASK2_4, tmp_mask); - REG_WRITE(ah, AR_PHY_MASK2_P_61_45, tmp_mask); -} - -static void ath9k_enable_rfkill(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, - AR_GPIO_INPUT_EN_VAL_RFSILENT_BB); - - REG_CLR_BIT(ah, AR_GPIO_INPUT_MUX2, - AR_GPIO_INPUT_MUX2_RFSILENT); - - ath9k_hw_cfg_gpio_input(ah, ah->rfkill_gpio); - REG_SET_BIT(ah, AR_PHY_TEST, RFSILENT_BB); -} - -int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, - bool bChannelChange) -{ - u32 saveLedState; - struct ath_softc *sc = ah->ah_sc; - struct ath9k_channel *curchan = ah->curchan; - u32 saveDefAntenna; - u32 macStaId1; - u64 tsf = 0; - int i, rx_chainmask, r; - - ah->extprotspacing = sc->ht_extprotspacing; - ah->txchainmask = sc->tx_chainmask; - ah->rxchainmask = sc->rx_chainmask; - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return -EIO; - - if (curchan && !ah->chip_fullsleep) - ath9k_hw_getnf(ah, curchan); - - if (bChannelChange && - (ah->chip_fullsleep != true) && - (ah->curchan != NULL) && - (chan->channel != ah->curchan->channel) && - ((chan->channelFlags & CHANNEL_ALL) == - (ah->curchan->channelFlags & CHANNEL_ALL)) && - !(AR_SREV_9280(ah) || IS_CHAN_A_5MHZ_SPACED(chan) || - IS_CHAN_A_5MHZ_SPACED(ah->curchan))) { - - if (ath9k_hw_channel_change(ah, chan, sc->tx_chan_width)) { - ath9k_hw_loadnf(ah, ah->curchan); - ath9k_hw_start_nfcal(ah); - return 0; - } - } - - saveDefAntenna = REG_READ(ah, AR_DEF_ANTENNA); - if (saveDefAntenna == 0) - saveDefAntenna = 1; - - macStaId1 = REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_BASE_RATE_11B; - - /* For chips on which RTC reset is done, save TSF before it gets cleared */ - if (AR_SREV_9100(ah) || - (AR_SREV_9280(ah) && ah->eep_ops->get_eeprom(ah, EEP_OL_PWRCTRL))) - tsf = ath9k_hw_gettsf64(ah); - - saveLedState = REG_READ(ah, AR_CFG_LED) & - (AR_CFG_LED_ASSOC_CTL | AR_CFG_LED_MODE_SEL | - AR_CFG_LED_BLINK_THRESH_SEL | AR_CFG_LED_BLINK_SLOW); - - ath9k_hw_mark_phy_inactive(ah); - - if (AR_SREV_9271(ah) && ah->htc_reset_init) { - REG_WRITE(ah, - AR9271_RESET_POWER_DOWN_CONTROL, - AR9271_RADIO_RF_RST); - udelay(50); - } - - if (!ath9k_hw_chip_reset(ah, chan)) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Chip reset failed\n"); - return -EINVAL; - } - - if (AR_SREV_9271(ah) && ah->htc_reset_init) { - ah->htc_reset_init = false; - REG_WRITE(ah, - AR9271_RESET_POWER_DOWN_CONTROL, - AR9271_GATE_MAC_CTL); - udelay(50); - } - - /* Restore TSF */ - if (tsf) - ath9k_hw_settsf64(ah, tsf); - - if (AR_SREV_9280_10_OR_LATER(ah)) - REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL, AR_GPIO_JTAG_DISABLE); - - if (AR_SREV_9287_12_OR_LATER(ah)) { - /* Enable ASYNC FIFO */ - REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL); - REG_SET_BIT(ah, AR_PHY_MODE, AR_PHY_MODE_ASYNCFIFO); - REG_CLR_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); - REG_SET_BIT(ah, AR_MAC_PCU_ASYNC_FIFO_REG3, - AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET); - } - r = ath9k_hw_process_ini(ah, chan, sc->tx_chan_width); - if (r) - return r; - - /* - * Some AR91xx SoC devices frequently fail to accept TSF writes - * right after the chip reset. When that happens, write a new - * value after the initvals have been applied, with an offset - * based on measured time difference - */ - if (AR_SREV_9100(ah) && (ath9k_hw_gettsf64(ah) < tsf)) { - tsf += 1500; - ath9k_hw_settsf64(ah, tsf); - } - - /* Setup MFP options for CCMP */ - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* Mask Retry(b11), PwrMgt(b12), MoreData(b13) to 0 in mgmt - * frames when constructing CCMP AAD. */ - REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, - 0xc7ff); - ah->sw_mgmt_crypto = false; - } else if (AR_SREV_9160_10_OR_LATER(ah)) { - /* Disable hardware crypto for management frames */ - REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); - REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); - ah->sw_mgmt_crypto = true; - } else - ah->sw_mgmt_crypto = true; - - if (IS_CHAN_OFDM(chan) || IS_CHAN_HT(chan)) - ath9k_hw_set_delta_slope(ah, chan); - - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_9280_spur_mitigate(ah, chan); - else - ath9k_hw_spur_mitigate(ah, chan); - - ah->eep_ops->set_board_values(ah, chan); - - ath9k_hw_decrease_chain_power(ah, chan); - - REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(ah->macaddr)); - REG_WRITE(ah, AR_STA_ID1, get_unaligned_le16(ah->macaddr + 4) - | macStaId1 - | AR_STA_ID1_RTS_USE_DEF - | (ah->config. - ack_6mb ? AR_STA_ID1_ACKCTS_6MB : 0) - | ah->sta_id1_defaults); - ath9k_hw_set_operating_mode(ah, ah->opmode); - - REG_WRITE(ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); - REG_WRITE(ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); - - REG_WRITE(ah, AR_DEF_ANTENNA, saveDefAntenna); - - REG_WRITE(ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); - REG_WRITE(ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | - ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); - - REG_WRITE(ah, AR_ISR, ~0); - - REG_WRITE(ah, AR_RSSI_THR, INIT_RSSI_THR); - - if (AR_SREV_9280_10_OR_LATER(ah)) - ath9k_hw_ar9280_set_channel(ah, chan); - else - if (!(ath9k_hw_set_channel(ah, chan))) - return -EIO; - - for (i = 0; i < AR_NUM_DCU; i++) - REG_WRITE(ah, AR_DQCUMASK(i), 1 << i); - - ah->intr_txqs = 0; - for (i = 0; i < ah->caps.total_queues; i++) - ath9k_hw_resettxqueue(ah, i); - - ath9k_hw_init_interrupt_masks(ah, ah->opmode); - ath9k_hw_init_qos(ah); - - if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - ath9k_enable_rfkill(ah); - - ath9k_hw_init_user_settings(ah); - - if (AR_SREV_9287_12_OR_LATER(ah)) { - REG_WRITE(ah, AR_D_GBL_IFS_SIFS, - AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR); - REG_WRITE(ah, AR_D_GBL_IFS_SLOT, - AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR); - REG_WRITE(ah, AR_D_GBL_IFS_EIFS, - AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR); - - REG_WRITE(ah, AR_TIME_OUT, AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR); - REG_WRITE(ah, AR_USEC, AR_USEC_ASYNC_FIFO_DUR); - - REG_SET_BIT(ah, AR_MAC_PCU_LOGIC_ANALYZER, - AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768); - REG_RMW_FIELD(ah, AR_AHB_MODE, AR_AHB_CUSTOM_BURST_EN, - AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL); - } - if (AR_SREV_9287_12_OR_LATER(ah)) { - REG_SET_BIT(ah, AR_PCU_MISC_MODE2, - AR_PCU_MISC_MODE2_ENABLE_AGGWEP); - } - - REG_WRITE(ah, AR_STA_ID1, - REG_READ(ah, AR_STA_ID1) | AR_STA_ID1_PRESERVE_SEQNUM); - - ath9k_hw_set_dma(ah); - - REG_WRITE(ah, AR_OBS, 8); - - if (ah->config.intr_mitigation) { - REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_LAST, 500); - REG_RMW_FIELD(ah, AR_RIMT, AR_RIMT_FIRST, 2000); - } - - ath9k_hw_init_bb(ah, chan); - - if (!ath9k_hw_init_cal(ah, chan)) - return -EIO; - - rx_chainmask = ah->rxchainmask; - if ((rx_chainmask == 0x5) || (rx_chainmask == 0x3)) { - REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx_chainmask); - REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx_chainmask); - } - - REG_WRITE(ah, AR_CFG_LED, saveLedState | AR_CFG_SCLK_32KHZ); - - /* - * For big endian systems turn on swapping for descriptors - */ - if (AR_SREV_9100(ah)) { - u32 mask; - mask = REG_READ(ah, AR_CFG); - if (mask & (AR_CFG_SWRB | AR_CFG_SWTB | AR_CFG_SWRG)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "CFG Byte Swap Set 0x%x\n", mask); - } else { - mask = - INIT_CONFIG_STATUS | AR_CFG_SWRB | AR_CFG_SWTB; - REG_WRITE(ah, AR_CFG, mask); - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "Setting CFG 0x%x\n", REG_READ(ah, AR_CFG)); - } - } else { - /* Configure AR9271 target WLAN */ - if (AR_SREV_9271(ah)) - REG_WRITE(ah, AR_CFG, AR_CFG_SWRB | AR_CFG_SWTB); -#ifdef __BIG_ENDIAN - else - REG_WRITE(ah, AR_CFG, AR_CFG_SWTD | AR_CFG_SWRD); -#endif - } - - if (ah->ah_sc->sc_flags & SC_OP_BTCOEX_ENABLED) - ath9k_hw_btcoex_enable(ah); - - return 0; -} - -/************************/ -/* Key Cache Management */ -/************************/ - -bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry) -{ - u32 keyType; - - if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); - return false; - } - - keyType = REG_READ(ah, AR_KEYTABLE_TYPE(entry)); - - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), AR_KEYTABLE_TYPE_CLR); - REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), 0); - REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), 0); - - if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { - u16 micentry = entry + 64; - - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); - - } - - return true; -} - -bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac) -{ - u32 macHi, macLo; - - if (entry >= ah->caps.keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keychache entry %u out of range\n", entry); - return false; - } - - if (mac != NULL) { - macHi = (mac[5] << 8) | mac[4]; - macLo = (mac[3] << 24) | - (mac[2] << 16) | - (mac[1] << 8) | - mac[0]; - macLo >>= 1; - macLo |= (macHi & 1) << 31; - macHi >>= 1; - } else { - macLo = macHi = 0; - } - REG_WRITE(ah, AR_KEYTABLE_MAC0(entry), macLo); - REG_WRITE(ah, AR_KEYTABLE_MAC1(entry), macHi | AR_KEYTABLE_VALID); - - return true; -} - -bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, - const struct ath9k_keyval *k, - const u8 *mac) -{ - const struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 key0, key1, key2, key3, key4; - u32 keyType; - - if (entry >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "keycache entry %u out of range\n", entry); - return false; - } - - switch (k->kv_type) { - case ATH9K_CIPHER_AES_OCB: - keyType = AR_KEYTABLE_TYPE_AES; - break; - case ATH9K_CIPHER_AES_CCM: - if (!(pCap->hw_caps & ATH9K_HW_CAP_CIPHER_AESCCM)) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "AES-CCM not supported by mac rev 0x%x\n", - ah->hw_version.macRev); - return false; - } - keyType = AR_KEYTABLE_TYPE_CCM; - break; - case ATH9K_CIPHER_TKIP: - keyType = AR_KEYTABLE_TYPE_TKIP; - if (ATH9K_IS_MIC_ENABLED(ah) - && entry + 64 >= pCap->keycache_size) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "entry %u inappropriate for TKIP\n", entry); - return false; - } - break; - case ATH9K_CIPHER_WEP: - if (k->kv_len < WLAN_KEY_LEN_WEP40) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "WEP key length %u too small\n", k->kv_len); - return false; - } - if (k->kv_len <= WLAN_KEY_LEN_WEP40) - keyType = AR_KEYTABLE_TYPE_40; - else if (k->kv_len <= WLAN_KEY_LEN_WEP104) - keyType = AR_KEYTABLE_TYPE_104; - else - keyType = AR_KEYTABLE_TYPE_128; - break; - case ATH9K_CIPHER_CLR: - keyType = AR_KEYTABLE_TYPE_CLR; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "cipher %u not supported\n", k->kv_type); - return false; - } - - key0 = get_unaligned_le32(k->kv_val + 0); - key1 = get_unaligned_le16(k->kv_val + 4); - key2 = get_unaligned_le32(k->kv_val + 6); - key3 = get_unaligned_le16(k->kv_val + 10); - key4 = get_unaligned_le32(k->kv_val + 12); - if (k->kv_len <= WLAN_KEY_LEN_WEP104) - key4 &= 0xff; - - /* - * Note: Key cache registers access special memory area that requires - * two 32-bit writes to actually update the values in the internal - * memory. Consequently, the exact order and pairs used here must be - * maintained. - */ - - if (keyType == AR_KEYTABLE_TYPE_TKIP && ATH9K_IS_MIC_ENABLED(ah)) { - u16 micentry = entry + 64; - - /* - * Write inverted key[47:0] first to avoid Michael MIC errors - * on frames that could be sent or received at the same time. - * The correct key will be written in the end once everything - * else is ready. - */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), ~key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), ~key1); - - /* Write key[95:48] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); - - /* Write key[127:96] and key type */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); - - /* Write MAC address for the entry */ - (void) ath9k_hw_keysetmac(ah, entry, mac); - - if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) { - /* - * TKIP uses two key cache entries: - * Michael MIC TX/RX keys in the same key cache entry - * (idx = main index + 64): - * key0 [31:0] = RX key [31:0] - * key1 [15:0] = TX key [31:16] - * key1 [31:16] = reserved - * key2 [31:0] = RX key [63:32] - * key3 [15:0] = TX key [15:0] - * key3 [31:16] = reserved - * key4 [31:0] = TX key [63:32] - */ - u32 mic0, mic1, mic2, mic3, mic4; - - mic0 = get_unaligned_le32(k->kv_mic + 0); - mic2 = get_unaligned_le32(k->kv_mic + 4); - mic1 = get_unaligned_le16(k->kv_txmic + 2) & 0xffff; - mic3 = get_unaligned_le16(k->kv_txmic + 0) & 0xffff; - mic4 = get_unaligned_le32(k->kv_txmic + 4); - - /* Write RX[31:0] and TX[31:16] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), mic1); - - /* Write RX[63:32] and TX[15:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), mic3); - - /* Write TX[63:32] and keyType(reserved) */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), mic4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), - AR_KEYTABLE_TYPE_CLR); - - } else { - /* - * TKIP uses four key cache entries (two for group - * keys): - * Michael MIC TX/RX keys are in different key cache - * entries (idx = main index + 64 for TX and - * main index + 32 + 96 for RX): - * key0 [31:0] = TX/RX MIC key [31:0] - * key1 [31:0] = reserved - * key2 [31:0] = TX/RX MIC key [63:32] - * key3 [31:0] = reserved - * key4 [31:0] = reserved - * - * Upper layer code will call this function separately - * for TX and RX keys when these registers offsets are - * used. - */ - u32 mic0, mic2; - - mic0 = get_unaligned_le32(k->kv_mic + 0); - mic2 = get_unaligned_le32(k->kv_mic + 4); - - /* Write MIC key[31:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(micentry), mic0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(micentry), 0); - - /* Write MIC key[63:32] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(micentry), mic2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(micentry), 0); - - /* Write TX[63:32] and keyType(reserved) */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry), - AR_KEYTABLE_TYPE_CLR); - } - - /* MAC address registers are reserved for the MIC entry */ - REG_WRITE(ah, AR_KEYTABLE_MAC0(micentry), 0); - REG_WRITE(ah, AR_KEYTABLE_MAC1(micentry), 0); - - /* - * Write the correct (un-inverted) key[47:0] last to enable - * TKIP now that all other registers are set with correct - * values. - */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); - } else { - /* Write key[47:0] */ - REG_WRITE(ah, AR_KEYTABLE_KEY0(entry), key0); - REG_WRITE(ah, AR_KEYTABLE_KEY1(entry), key1); - - /* Write key[95:48] */ - REG_WRITE(ah, AR_KEYTABLE_KEY2(entry), key2); - REG_WRITE(ah, AR_KEYTABLE_KEY3(entry), key3); - - /* Write key[127:96] and key type */ - REG_WRITE(ah, AR_KEYTABLE_KEY4(entry), key4); - REG_WRITE(ah, AR_KEYTABLE_TYPE(entry), keyType); - - /* Write MAC address for the entry */ - (void) ath9k_hw_keysetmac(ah, entry, mac); - } - - return true; -} - -bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry) -{ - if (entry < ah->caps.keycache_size) { - u32 val = REG_READ(ah, AR_KEYTABLE_MAC1(entry)); - if (val & AR_KEYTABLE_VALID) - return true; - } - return false; -} - -/******************************/ -/* Power Management (Chipset) */ -/******************************/ - -static void ath9k_set_power_sleep(struct ath_hw *ah, int setChip) -{ - REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - if (setChip) { - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - if (!AR_SREV_9100(ah)) - REG_WRITE(ah, AR_RC, AR_RC_AHB | AR_RC_HOSTIF); - - REG_CLR_BIT(ah, (AR_RTC_RESET), - AR_RTC_RESET_EN); - } -} - -static void ath9k_set_power_network_sleep(struct ath_hw *ah, int setChip) -{ - REG_SET_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - if (setChip) { - struct ath9k_hw_capabilities *pCap = &ah->caps; - - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - REG_WRITE(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_ON_INT); - } else { - REG_CLR_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - } - } -} - -static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip) -{ - u32 val; - int i; - - if (setChip) { - if ((REG_READ(ah, AR_RTC_STATUS) & - AR_RTC_STATUS_M) == AR_RTC_STATUS_SHUTDOWN) { - if (ath9k_hw_set_reset_reg(ah, - ATH9K_RESET_POWER_ON) != true) { - return false; - } - } - if (AR_SREV_9100(ah)) - REG_SET_BIT(ah, AR_RTC_RESET, - AR_RTC_RESET_EN); - - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - udelay(50); - - for (i = POWER_UP_TIME / 50; i > 0; i--) { - val = REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M; - if (val == AR_RTC_STATUS_ON) - break; - udelay(50); - REG_SET_BIT(ah, AR_RTC_FORCE_WAKE, - AR_RTC_FORCE_WAKE_EN); - } - if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to wakeup in %uus\n", POWER_UP_TIME / 20); - return false; - } - } - - REG_CLR_BIT(ah, AR_STA_ID1, AR_STA_ID1_PWR_SAV); - - return true; -} - -static bool ath9k_hw_setpower_nolock(struct ath_hw *ah, - enum ath9k_power_mode mode) -{ - int status = true, setChip = true; - static const char *modes[] = { - "AWAKE", - "FULL-SLEEP", - "NETWORK SLEEP", - "UNDEFINED" - }; - - if (ah->power_mode == mode) - return status; - - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "%s -> %s\n", - modes[ah->power_mode], modes[mode]); - - switch (mode) { - case ATH9K_PM_AWAKE: - status = ath9k_hw_set_power_awake(ah, setChip); - break; - case ATH9K_PM_FULL_SLEEP: - ath9k_set_power_sleep(ah, setChip); - ah->chip_fullsleep = true; - break; - case ATH9K_PM_NETWORK_SLEEP: - ath9k_set_power_network_sleep(ah, setChip); - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Unknown power mode %u\n", mode); - return false; - } - ah->power_mode = mode; - - return status; -} - -bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode) -{ - unsigned long flags; - bool ret; - - spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags); - ret = ath9k_hw_setpower_nolock(ah, mode); - spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags); - - return ret; -} - -void ath9k_ps_wakeup(struct ath_softc *sc) -{ - unsigned long flags; - - spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (++sc->ps_usecount != 1) - goto unlock; - - ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); - - unlock: - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); -} - -void ath9k_ps_restore(struct ath_softc *sc) -{ - unsigned long flags; - - spin_lock_irqsave(&sc->sc_pm_lock, flags); - if (--sc->ps_usecount != 0) - goto unlock; - - if (sc->ps_enabled && - !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK))) - ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); - - unlock: - spin_unlock_irqrestore(&sc->sc_pm_lock, flags); -} - -/* - * Helper for ASPM support. - * - * Disable PLL when in L0s as well as receiver clock when in L1. - * This power saving option must be enabled through the SerDes. - * - * Programming the SerDes must go through the same 288 bit serial shift - * register as the other analog registers. Hence the 9 writes. - */ -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off) -{ - u8 i; - u32 val; - - if (ah->is_pciexpress != true) - return; - - /* Do not touch SerDes registers */ - if (ah->config.pcie_powersave_enable == 2) - return; - - /* Nothing to do on restore for 11N */ - if (!restore) { - if (AR_SREV_9280_20_OR_LATER(ah)) { - /* - * AR9280 2.0 or later chips use SerDes values from the - * initvals.h initialized depending on chipset during - * ath9k_hw_init() - */ - for (i = 0; i < ah->iniPcieSerdes.ia_rows; i++) { - REG_WRITE(ah, INI_RA(&ah->iniPcieSerdes, i, 0), - INI_RA(&ah->iniPcieSerdes, i, 1)); - } - } else if (AR_SREV_9280(ah) && - (ah->hw_version.macRev == AR_SREV_REVISION_9280_10)) { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fd00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0xa8000019); - REG_WRITE(ah, AR_PCIE_SERDES, 0x13160820); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980560); - - /* Shut off CLKREQ active in L1 */ - if (ah->config.pcie_clock_req) - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffc); - else - REG_WRITE(ah, AR_PCIE_SERDES, 0x401deffd); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x00043007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - - } else { - REG_WRITE(ah, AR_PCIE_SERDES, 0x9248fc00); - REG_WRITE(ah, AR_PCIE_SERDES, 0x24924924); - - /* RX shut off when elecidle is asserted */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x28000039); - REG_WRITE(ah, AR_PCIE_SERDES, 0x53160824); - REG_WRITE(ah, AR_PCIE_SERDES, 0xe5980579); - - /* - * Ignore ah->ah_config.pcie_clock_req setting for - * pre-AR9280 11n - */ - REG_WRITE(ah, AR_PCIE_SERDES, 0x001defff); - - REG_WRITE(ah, AR_PCIE_SERDES, 0x1aaabe40); - REG_WRITE(ah, AR_PCIE_SERDES, 0xbe105554); - REG_WRITE(ah, AR_PCIE_SERDES, 0x000e3007); - - /* Load the new settings */ - REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000); - } - - udelay(1000); - - /* set bit 19 to allow forcing of pcie core into L1 state */ - REG_SET_BIT(ah, AR_PCIE_PM_CTRL, AR_PCIE_PM_CTRL_ENA); - - /* Several PCIe massages to ensure proper behaviour */ - if (ah->config.pcie_waen) { - val = ah->config.pcie_waen; - if (!power_off) - val &= (~AR_WA_D3_L1_DISABLE); - } else { - if (AR_SREV_9285(ah) || AR_SREV_9271(ah) || - AR_SREV_9287(ah)) { - val = AR9285_WA_DEFAULT; - if (!power_off) - val &= (~AR_WA_D3_L1_DISABLE); - } else if (AR_SREV_9280(ah)) { - /* - * On AR9280 chips bit 22 of 0x4004 needs to be - * set otherwise card may disappear. - */ - val = AR9280_WA_DEFAULT; - if (!power_off) - val &= (~AR_WA_D3_L1_DISABLE); - } else - val = AR_WA_DEFAULT; - } - - REG_WRITE(ah, AR_WA, val); - } - - if (power_off) { - /* - * Set PCIe workaround bits - * bit 14 in WA register (disable L1) should only - * be set when device enters D3 and be cleared - * when device comes back to D0. - */ - if (ah->config.pcie_waen) { - if (ah->config.pcie_waen & AR_WA_D3_L1_DISABLE) - REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); - } else { - if (((AR_SREV_9285(ah) || AR_SREV_9271(ah) || - AR_SREV_9287(ah)) && - (AR9285_WA_DEFAULT & AR_WA_D3_L1_DISABLE)) || - (AR_SREV_9280(ah) && - (AR9280_WA_DEFAULT & AR_WA_D3_L1_DISABLE))) { - REG_SET_BIT(ah, AR_WA, AR_WA_D3_L1_DISABLE); - } - } - } -} - -/**********************/ -/* Interrupt Handling */ -/**********************/ - -bool ath9k_hw_intrpend(struct ath_hw *ah) -{ - u32 host_isr; - - if (AR_SREV_9100(ah)) - return true; - - host_isr = REG_READ(ah, AR_INTR_ASYNC_CAUSE); - if ((host_isr & AR_INTR_MAC_IRQ) && (host_isr != AR_INTR_SPURIOUS)) - return true; - - host_isr = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if ((host_isr & AR_INTR_SYNC_DEFAULT) - && (host_isr != AR_INTR_SPURIOUS)) - return true; - - return false; -} - -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked) -{ - u32 isr = 0; - u32 mask2 = 0; - struct ath9k_hw_capabilities *pCap = &ah->caps; - u32 sync_cause = 0; - bool fatal_int = false; - - if (!AR_SREV_9100(ah)) { - if (REG_READ(ah, AR_INTR_ASYNC_CAUSE) & AR_INTR_MAC_IRQ) { - if ((REG_READ(ah, AR_RTC_STATUS) & AR_RTC_STATUS_M) - == AR_RTC_STATUS_ON) { - isr = REG_READ(ah, AR_ISR); - } - } - - sync_cause = REG_READ(ah, AR_INTR_SYNC_CAUSE) & - AR_INTR_SYNC_DEFAULT; - - *masked = 0; - - if (!isr && !sync_cause) - return false; - } else { - *masked = 0; - isr = REG_READ(ah, AR_ISR); - } - - if (isr) { - if (isr & AR_ISR_BCNMISC) { - u32 isr2; - isr2 = REG_READ(ah, AR_ISR_S2); - if (isr2 & AR_ISR_S2_TIM) - mask2 |= ATH9K_INT_TIM; - if (isr2 & AR_ISR_S2_DTIM) - mask2 |= ATH9K_INT_DTIM; - if (isr2 & AR_ISR_S2_DTIMSYNC) - mask2 |= ATH9K_INT_DTIMSYNC; - if (isr2 & (AR_ISR_S2_CABEND)) - mask2 |= ATH9K_INT_CABEND; - if (isr2 & AR_ISR_S2_GTT) - mask2 |= ATH9K_INT_GTT; - if (isr2 & AR_ISR_S2_CST) - mask2 |= ATH9K_INT_CST; - if (isr2 & AR_ISR_S2_TSFOOR) - mask2 |= ATH9K_INT_TSFOOR; - } - - isr = REG_READ(ah, AR_ISR_RAC); - if (isr == 0xffffffff) { - *masked = 0; - return false; - } - - *masked = isr & ATH9K_INT_COMMON; - - if (ah->config.intr_mitigation) { - if (isr & (AR_ISR_RXMINTR | AR_ISR_RXINTM)) - *masked |= ATH9K_INT_RX; - } - - if (isr & (AR_ISR_RXOK | AR_ISR_RXERR)) - *masked |= ATH9K_INT_RX; - if (isr & - (AR_ISR_TXOK | AR_ISR_TXDESC | AR_ISR_TXERR | - AR_ISR_TXEOL)) { - u32 s0_s, s1_s; - - *masked |= ATH9K_INT_TX; - - s0_s = REG_READ(ah, AR_ISR_S0_S); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXOK); - ah->intr_txqs |= MS(s0_s, AR_ISR_S0_QCU_TXDESC); - - s1_s = REG_READ(ah, AR_ISR_S1_S); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXERR); - ah->intr_txqs |= MS(s1_s, AR_ISR_S1_QCU_TXEOL); - } - - if (isr & AR_ISR_RXORN) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "receive FIFO overrun interrupt\n"); - } - - if (!AR_SREV_9100(ah)) { - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - u32 isr5 = REG_READ(ah, AR_ISR_S5_S); - if (isr5 & AR_ISR_S5_TIM_TIMER) - *masked |= ATH9K_INT_TIM_TIMER; - } - } - - *masked |= mask2; - } - - if (AR_SREV_9100(ah)) - return true; - - if (isr & AR_ISR_GENTMR) { - u32 s5_s; - - s5_s = REG_READ(ah, AR_ISR_S5_S); - if (isr & AR_ISR_GENTMR) { - ah->intr_gen_timer_trigger = - MS(s5_s, AR_ISR_S5_GENTIMER_TRIG); - - ah->intr_gen_timer_thresh = - MS(s5_s, AR_ISR_S5_GENTIMER_THRESH); - - if (ah->intr_gen_timer_trigger) - *masked |= ATH9K_INT_GENTIMER; - - } - } - - if (sync_cause) { - fatal_int = - (sync_cause & - (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) - ? true : false; - - if (fatal_int) { - if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "received PCI FATAL interrupt\n"); - } - if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { - DPRINTF(ah->ah_sc, ATH_DBG_ANY, - "received PCI PERR interrupt\n"); - } - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_RADM_CPL_TIMEOUT\n"); - REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); - REG_WRITE(ah, AR_RC, 0); - *masked |= ATH9K_INT_FATAL; - } - if (sync_cause & AR_INTR_SYNC_LOCAL_TIMEOUT) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "AR_INTR_SYNC_LOCAL_TIMEOUT\n"); - } - - REG_WRITE(ah, AR_INTR_SYNC_CAUSE_CLR, sync_cause); - (void) REG_READ(ah, AR_INTR_SYNC_CAUSE_CLR); - } - - return true; -} - -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints) -{ - u32 omask = ah->mask_reg; - u32 mask, mask2; - struct ath9k_hw_capabilities *pCap = &ah->caps; - - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); - - if (omask & ATH9K_INT_GLOBAL) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "disable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_DISABLE); - (void) REG_READ(ah, AR_IER); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_ASYNC_ENABLE); - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); - (void) REG_READ(ah, AR_INTR_SYNC_ENABLE); - } - } - - mask = ints & ATH9K_INT_COMMON; - mask2 = 0; - - if (ints & ATH9K_INT_TX) { - if (ah->txok_interrupt_mask) - mask |= AR_IMR_TXOK; - if (ah->txdesc_interrupt_mask) - mask |= AR_IMR_TXDESC; - if (ah->txerr_interrupt_mask) - mask |= AR_IMR_TXERR; - if (ah->txeol_interrupt_mask) - mask |= AR_IMR_TXEOL; - } - if (ints & ATH9K_INT_RX) { - mask |= AR_IMR_RXERR; - if (ah->config.intr_mitigation) - mask |= AR_IMR_RXMINTR | AR_IMR_RXINTM; - else - mask |= AR_IMR_RXOK | AR_IMR_RXDESC; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - mask |= AR_IMR_GENTMR; - } - - if (ints & (ATH9K_INT_BMISC)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_TIM) - mask2 |= AR_IMR_S2_TIM; - if (ints & ATH9K_INT_DTIM) - mask2 |= AR_IMR_S2_DTIM; - if (ints & ATH9K_INT_DTIMSYNC) - mask2 |= AR_IMR_S2_DTIMSYNC; - if (ints & ATH9K_INT_CABEND) - mask2 |= AR_IMR_S2_CABEND; - if (ints & ATH9K_INT_TSFOOR) - mask2 |= AR_IMR_S2_TSFOOR; - } - - if (ints & (ATH9K_INT_GTT | ATH9K_INT_CST)) { - mask |= AR_IMR_BCNMISC; - if (ints & ATH9K_INT_GTT) - mask2 |= AR_IMR_S2_GTT; - if (ints & ATH9K_INT_CST) - mask2 |= AR_IMR_S2_CST; - } - - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "new IMR 0x%x\n", mask); - REG_WRITE(ah, AR_IMR, mask); - mask = REG_READ(ah, AR_IMR_S2) & ~(AR_IMR_S2_TIM | - AR_IMR_S2_DTIM | - AR_IMR_S2_DTIMSYNC | - AR_IMR_S2_CABEND | - AR_IMR_S2_CABTO | - AR_IMR_S2_TSFOOR | - AR_IMR_S2_GTT | AR_IMR_S2_CST); - REG_WRITE(ah, AR_IMR_S2, mask | mask2); - ah->mask_reg = ints; - - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - if (ints & ATH9K_INT_TIM_TIMER) - REG_SET_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); - else - REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); - } - - if (ints & ATH9K_INT_GLOBAL) { - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "enable IER\n"); - REG_WRITE(ah, AR_IER, AR_IER_ENABLE); - if (!AR_SREV_9100(ah)) { - REG_WRITE(ah, AR_INTR_ASYNC_ENABLE, - AR_INTR_MAC_IRQ); - REG_WRITE(ah, AR_INTR_ASYNC_MASK, AR_INTR_MAC_IRQ); - - - REG_WRITE(ah, AR_INTR_SYNC_ENABLE, - AR_INTR_SYNC_DEFAULT); - REG_WRITE(ah, AR_INTR_SYNC_MASK, - AR_INTR_SYNC_DEFAULT); - } - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, "AR_IMR 0x%x IER 0x%x\n", - REG_READ(ah, AR_IMR), REG_READ(ah, AR_IER)); - } - - return omask; -} - -/*******************/ -/* Beacon Handling */ -/*******************/ - -void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period) -{ - int flags = 0; - - ah->beacon_interval = beacon_period; - - switch (ah->opmode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_MONITOR: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, 0xffff); - REG_WRITE(ah, AR_NEXT_SWBA, 0x7ffff); - flags |= AR_TBTT_TIMER_EN; - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - REG_SET_BIT(ah, AR_TXCFG, - AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY); - REG_WRITE(ah, AR_NEXT_NDP_TIMER, - TU_TO_USEC(next_beacon + - (ah->atim_window ? ah-> - atim_window : 1))); - flags |= AR_NDP_TIMER_EN; - case NL80211_IFTYPE_AP: - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(next_beacon)); - REG_WRITE(ah, AR_NEXT_DMA_BEACON_ALERT, - TU_TO_USEC(next_beacon - - ah->config. - dma_beacon_response_time)); - REG_WRITE(ah, AR_NEXT_SWBA, - TU_TO_USEC(next_beacon - - ah->config. - sw_beacon_response_time)); - flags |= - AR_TBTT_TIMER_EN | AR_DBA_TIMER_EN | AR_SWBA_TIMER_EN; - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, - "%s: unsupported opmode: %d\n", - __func__, ah->opmode); - return; - break; - } - - REG_WRITE(ah, AR_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_SWBA_PERIOD, TU_TO_USEC(beacon_period)); - REG_WRITE(ah, AR_NDP_PERIOD, TU_TO_USEC(beacon_period)); - - beacon_period &= ~ATH9K_BEACON_ENA; - if (beacon_period & ATH9K_BEACON_RESET_TSF) { - beacon_period &= ~ATH9K_BEACON_RESET_TSF; - ath9k_hw_reset_tsf(ah); - } - - REG_SET_BIT(ah, AR_TIMER_MODE, flags); -} - -void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, - const struct ath9k_beacon_state *bs) -{ - u32 nextTbtt, beaconintval, dtimperiod, beacontimeout; - struct ath9k_hw_capabilities *pCap = &ah->caps; - - REG_WRITE(ah, AR_NEXT_TBTT_TIMER, TU_TO_USEC(bs->bs_nexttbtt)); - - REG_WRITE(ah, AR_BEACON_PERIOD, - TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); - REG_WRITE(ah, AR_DMA_BEACON_PERIOD, - TU_TO_USEC(bs->bs_intval & ATH9K_BEACON_PERIOD)); - - REG_RMW_FIELD(ah, AR_RSSI_THR, - AR_RSSI_THR_BM_THR, bs->bs_bmissthreshold); - - beaconintval = bs->bs_intval & ATH9K_BEACON_PERIOD; - - if (bs->bs_sleepduration > beaconintval) - beaconintval = bs->bs_sleepduration; - - dtimperiod = bs->bs_dtimperiod; - if (bs->bs_sleepduration > dtimperiod) - dtimperiod = bs->bs_sleepduration; - - if (beaconintval == dtimperiod) - nextTbtt = bs->bs_nextdtim; - else - nextTbtt = bs->bs_nexttbtt; - - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next DTIM %d\n", bs->bs_nextdtim); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "next beacon %d\n", nextTbtt); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "beacon period %d\n", beaconintval); - DPRINTF(ah->ah_sc, ATH_DBG_BEACON, "DTIM period %d\n", dtimperiod); - - REG_WRITE(ah, AR_NEXT_DTIM, - TU_TO_USEC(bs->bs_nextdtim - SLEEP_SLOP)); - REG_WRITE(ah, AR_NEXT_TIM, TU_TO_USEC(nextTbtt - SLEEP_SLOP)); - - REG_WRITE(ah, AR_SLEEP1, - SM((CAB_TIMEOUT_VAL << 3), AR_SLEEP1_CAB_TIMEOUT) - | AR_SLEEP1_ASSUME_DTIM); - - if (pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP) - beacontimeout = (BEACON_TIMEOUT_VAL << 3); - else - beacontimeout = MIN_BEACON_TIMEOUT_VAL; - - REG_WRITE(ah, AR_SLEEP2, - SM(beacontimeout, AR_SLEEP2_BEACON_TIMEOUT)); - - REG_WRITE(ah, AR_TIM_PERIOD, TU_TO_USEC(beaconintval)); - REG_WRITE(ah, AR_DTIM_PERIOD, TU_TO_USEC(dtimperiod)); - - REG_SET_BIT(ah, AR_TIMER_MODE, - AR_TBTT_TIMER_EN | AR_TIM_TIMER_EN | - AR_DTIM_TIMER_EN); - - /* TSF Out of Range Threshold */ - REG_WRITE(ah, AR_TSFOOR_THRESHOLD, bs->bs_tsfoor_threshold); -} - -/*******************/ -/* HW Capabilities */ -/*******************/ - -void ath9k_hw_fill_cap_info(struct ath_hw *ah) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ath_btcoex_info *btcoex_info = &ah->ah_sc->btcoex_info; - - u16 capField = 0, eeval; - - eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_0); - regulatory->current_rd = eeval; - - eeval = ah->eep_ops->get_eeprom(ah, EEP_REG_1); - if (AR_SREV_9285_10_OR_LATER(ah)) - eeval |= AR9285_RDEXT_DEFAULT; - regulatory->current_rd_ext = eeval; - - capField = ah->eep_ops->get_eeprom(ah, EEP_OP_CAP); - - if (ah->opmode != NL80211_IFTYPE_AP && - ah->hw_version.subvendorid == AR_SUBVENDOR_ID_NEW_A) { - if (regulatory->current_rd == 0x64 || - regulatory->current_rd == 0x65) - regulatory->current_rd += 5; - else if (regulatory->current_rd == 0x41) - regulatory->current_rd = 0x43; - DPRINTF(ah->ah_sc, ATH_DBG_REGULATORY, - "regdomain mapped to 0x%x\n", regulatory->current_rd); - } - - eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); - bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); - - if (eeval & AR5416_OPFLAGS_11A) { - set_bit(ATH9K_MODE_11A, pCap->wireless_modes); - if (ah->config.ht_enable) { - if (!(eeval & AR5416_OPFLAGS_N_5G_HT20)) - set_bit(ATH9K_MODE_11NA_HT20, - pCap->wireless_modes); - if (!(eeval & AR5416_OPFLAGS_N_5G_HT40)) { - set_bit(ATH9K_MODE_11NA_HT40PLUS, - pCap->wireless_modes); - set_bit(ATH9K_MODE_11NA_HT40MINUS, - pCap->wireless_modes); - } - } - } - - if (eeval & AR5416_OPFLAGS_11G) { - set_bit(ATH9K_MODE_11G, pCap->wireless_modes); - if (ah->config.ht_enable) { - if (!(eeval & AR5416_OPFLAGS_N_2G_HT20)) - set_bit(ATH9K_MODE_11NG_HT20, - pCap->wireless_modes); - if (!(eeval & AR5416_OPFLAGS_N_2G_HT40)) { - set_bit(ATH9K_MODE_11NG_HT40PLUS, - pCap->wireless_modes); - set_bit(ATH9K_MODE_11NG_HT40MINUS, - pCap->wireless_modes); - } - } - } - - pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); - /* - * For AR9271 we will temporarilly uses the rx chainmax as read from - * the EEPROM. - */ - if ((ah->hw_version.devid == AR5416_DEVID_PCI) && - !(eeval & AR5416_OPFLAGS_11A) && - !(AR_SREV_9271(ah))) - /* CB71: GPIO 0 is pulled down to indicate 3 rx chains */ - pCap->rx_chainmask = ath9k_hw_gpio_get(ah, 0) ? 0x5 : 0x7; - else - /* Use rx_chainmask from EEPROM. */ - pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); - - if (!(AR_SREV_9280(ah) && (ah->hw_version.macRev == 0))) - ah->misc_mode |= AR_PCU_MIC_NEW_LOC_ENA; - - pCap->low_2ghz_chan = 2312; - pCap->high_2ghz_chan = 2732; - - pCap->low_5ghz_chan = 4920; - pCap->high_5ghz_chan = 6100; - - pCap->hw_caps &= ~ATH9K_HW_CAP_CIPHER_CKIP; - pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_TKIP; - pCap->hw_caps |= ATH9K_HW_CAP_CIPHER_AESCCM; - - pCap->hw_caps &= ~ATH9K_HW_CAP_MIC_CKIP; - pCap->hw_caps |= ATH9K_HW_CAP_MIC_TKIP; - pCap->hw_caps |= ATH9K_HW_CAP_MIC_AESCCM; - - if (ah->config.ht_enable) - pCap->hw_caps |= ATH9K_HW_CAP_HT; - else - pCap->hw_caps &= ~ATH9K_HW_CAP_HT; - - pCap->hw_caps |= ATH9K_HW_CAP_GTT; - pCap->hw_caps |= ATH9K_HW_CAP_VEOL; - pCap->hw_caps |= ATH9K_HW_CAP_BSSIDMASK; - pCap->hw_caps &= ~ATH9K_HW_CAP_MCAST_KEYSEARCH; - - if (capField & AR_EEPROM_EEPCAP_MAXQCU) - pCap->total_queues = - MS(capField, AR_EEPROM_EEPCAP_MAXQCU); - else - pCap->total_queues = ATH9K_NUM_TX_QUEUES; - - if (capField & AR_EEPROM_EEPCAP_KC_ENTRIES) - pCap->keycache_size = - 1 << MS(capField, AR_EEPROM_EEPCAP_KC_ENTRIES); - else - pCap->keycache_size = AR_KEYTABLE_SIZE; - - pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; - - if (AR_SREV_9285(ah) || AR_SREV_9271(ah)) - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1; - else - pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; - - if (AR_SREV_9285_10_OR_LATER(ah)) - pCap->num_gpio_pins = AR9285_NUM_GPIO; - else if (AR_SREV_9280_10_OR_LATER(ah)) - pCap->num_gpio_pins = AR928X_NUM_GPIO; - else - pCap->num_gpio_pins = AR_NUM_GPIO; - - if (AR_SREV_9160_10_OR_LATER(ah) || AR_SREV_9100(ah)) { - pCap->hw_caps |= ATH9K_HW_CAP_CST; - pCap->rts_aggr_limit = ATH_AMPDU_LIMIT_MAX; - } else { - pCap->rts_aggr_limit = (8 * 1024); - } - - pCap->hw_caps |= ATH9K_HW_CAP_ENHANCEDPM; - -#if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) - ah->rfsilent = ah->eep_ops->get_eeprom(ah, EEP_RF_SILENT); - if (ah->rfsilent & EEP_RFSILENT_ENABLED) { - ah->rfkill_gpio = - MS(ah->rfsilent, EEP_RFSILENT_GPIO_SEL); - ah->rfkill_polarity = - MS(ah->rfsilent, EEP_RFSILENT_POLARITY); - - pCap->hw_caps |= ATH9K_HW_CAP_RFSILENT; - } -#endif - - pCap->hw_caps &= ~ATH9K_HW_CAP_AUTOSLEEP; - - if (AR_SREV_9280(ah) || AR_SREV_9285(ah)) - pCap->hw_caps &= ~ATH9K_HW_CAP_4KB_SPLITTRANS; - else - pCap->hw_caps |= ATH9K_HW_CAP_4KB_SPLITTRANS; - - if (regulatory->current_rd_ext & (1 << REG_EXT_JAPAN_MIDBAND)) { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN | - AR_EEPROM_EEREGCAP_EN_KK_U2 | - AR_EEPROM_EEREGCAP_EN_KK_MIDBAND; - } else { - pCap->reg_cap = - AR_EEPROM_EEREGCAP_EN_KK_NEW_11A | - AR_EEPROM_EEREGCAP_EN_KK_U1_EVEN; - } - - pCap->reg_cap |= AR_EEPROM_EEREGCAP_EN_FCC_MIDBAND; - - pCap->num_antcfg_5ghz = - ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_5GHZ); - pCap->num_antcfg_2ghz = - ah->eep_ops->get_num_ant_config(ah, ATH9K_HAL_FREQ_BAND_2GHZ); - - if (AR_SREV_9280_10_OR_LATER(ah) && - ath_btcoex_supported(ah->hw_version.subsysid)) { - btcoex_info->btactive_gpio = ATH_BTACTIVE_GPIO; - btcoex_info->wlanactive_gpio = ATH_WLANACTIVE_GPIO; - - if (AR_SREV_9285(ah)) { - btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_3WIRE; - btcoex_info->btpriority_gpio = ATH_BTPRIORITY_GPIO; - } else { - btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_2WIRE; - } - } else { - btcoex_info->btcoex_scheme = ATH_BTCOEX_CFG_NONE; - } -} - -bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - switch (type) { - case ATH9K_CAP_CIPHER: - switch (capability) { - case ATH9K_CIPHER_AES_CCM: - case ATH9K_CIPHER_AES_OCB: - case ATH9K_CIPHER_TKIP: - case ATH9K_CIPHER_WEP: - case ATH9K_CIPHER_MIC: - case ATH9K_CIPHER_CLR: - return true; - default: - return false; - } - case ATH9K_CAP_TKIP_MIC: - switch (capability) { - case 0: - return true; - case 1: - return (ah->sta_id1_defaults & - AR_STA_ID1_CRPT_MIC_ENABLE) ? true : - false; - } - case ATH9K_CAP_TKIP_SPLIT: - return (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) ? - false : true; - case ATH9K_CAP_DIVERSITY: - return (REG_READ(ah, AR_PHY_CCK_DETECT) & - AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV) ? - true : false; - case ATH9K_CAP_MCAST_KEYSRCH: - switch (capability) { - case 0: - return true; - case 1: - if (REG_READ(ah, AR_STA_ID1) & AR_STA_ID1_ADHOC) { - return false; - } else { - return (ah->sta_id1_defaults & - AR_STA_ID1_MCAST_KSRCH) ? true : - false; - } - } - return false; - case ATH9K_CAP_TXPOW: - switch (capability) { - case 0: - return 0; - case 1: - *result = regulatory->power_limit; - return 0; - case 2: - *result = regulatory->max_power_level; - return 0; - case 3: - *result = regulatory->tp_scale; - return 0; - } - return false; - case ATH9K_CAP_DS: - return (AR_SREV_9280_20_OR_LATER(ah) && - (ah->eep_ops->get_eeprom(ah, EEP_RC_CHAIN_MASK) == 1)) - ? false : true; - default: - return false; - } -} - -bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 setting, int *status) -{ - u32 v; - - switch (type) { - case ATH9K_CAP_TKIP_MIC: - if (setting) - ah->sta_id1_defaults |= - AR_STA_ID1_CRPT_MIC_ENABLE; - else - ah->sta_id1_defaults &= - ~AR_STA_ID1_CRPT_MIC_ENABLE; - return true; - case ATH9K_CAP_DIVERSITY: - v = REG_READ(ah, AR_PHY_CCK_DETECT); - if (setting) - v |= AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - else - v &= ~AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV; - REG_WRITE(ah, AR_PHY_CCK_DETECT, v); - return true; - case ATH9K_CAP_MCAST_KEYSRCH: - if (setting) - ah->sta_id1_defaults |= AR_STA_ID1_MCAST_KSRCH; - else - ah->sta_id1_defaults &= ~AR_STA_ID1_MCAST_KSRCH; - return true; - default: - return false; - } -} - -/****************************/ -/* GPIO / RFKILL / Antennae */ -/****************************/ - -static void ath9k_hw_gpio_cfg_output_mux(struct ath_hw *ah, - u32 gpio, u32 type) -{ - int addr; - u32 gpio_shift, tmp; - - if (gpio > 11) - addr = AR_GPIO_OUTPUT_MUX3; - else if (gpio > 5) - addr = AR_GPIO_OUTPUT_MUX2; - else - addr = AR_GPIO_OUTPUT_MUX1; - - gpio_shift = (gpio % 6) * 5; - - if (AR_SREV_9280_20_OR_LATER(ah) - || (addr != AR_GPIO_OUTPUT_MUX1)) { - REG_RMW(ah, addr, (type << gpio_shift), - (0x1f << gpio_shift)); - } else { - tmp = REG_READ(ah, addr); - tmp = ((tmp & 0x1F0) << 1) | (tmp & ~0x1F0); - tmp &= ~(0x1f << gpio_shift); - tmp |= (type << gpio_shift); - REG_WRITE(ah, addr, tmp); - } -} - -void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio) -{ - u32 gpio_shift; - - ASSERT(gpio < ah->caps.num_gpio_pins); - - gpio_shift = gpio << 1; - - REG_RMW(ah, - AR_GPIO_OE_OUT, - (AR_GPIO_OE_OUT_DRV_NO << gpio_shift), - (AR_GPIO_OE_OUT_DRV << gpio_shift)); -} - -u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio) -{ -#define MS_REG_READ(x, y) \ - (MS(REG_READ(ah, AR_GPIO_IN_OUT), x##_GPIO_IN_VAL) & (AR_GPIO_BIT(y))) - - if (gpio >= ah->caps.num_gpio_pins) - return 0xffffffff; - - if (AR_SREV_9287_10_OR_LATER(ah)) - return MS_REG_READ(AR9287, gpio) != 0; - else if (AR_SREV_9285_10_OR_LATER(ah)) - return MS_REG_READ(AR9285, gpio) != 0; - else if (AR_SREV_9280_10_OR_LATER(ah)) - return MS_REG_READ(AR928X, gpio) != 0; - else - return MS_REG_READ(AR, gpio) != 0; -} - -void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, - u32 ah_signal_type) -{ - u32 gpio_shift; - - ath9k_hw_gpio_cfg_output_mux(ah, gpio, ah_signal_type); - - gpio_shift = 2 * gpio; - - REG_RMW(ah, - AR_GPIO_OE_OUT, - (AR_GPIO_OE_OUT_DRV_ALL << gpio_shift), - (AR_GPIO_OE_OUT_DRV << gpio_shift)); -} - -void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val) -{ - REG_RMW(ah, AR_GPIO_IN_OUT, ((val & 1) << gpio), - AR_GPIO_BIT(gpio)); -} - -u32 ath9k_hw_getdefantenna(struct ath_hw *ah) -{ - return REG_READ(ah, AR_DEF_ANTENNA) & 0x7; -} - -void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna) -{ - REG_WRITE(ah, AR_DEF_ANTENNA, (antenna & 0x7)); -} - -bool ath9k_hw_setantennaswitch(struct ath_hw *ah, - enum ath9k_ant_setting settings, - struct ath9k_channel *chan, - u8 *tx_chainmask, - u8 *rx_chainmask, - u8 *antenna_cfgd) -{ - static u8 tx_chainmask_cfg, rx_chainmask_cfg; - - if (AR_SREV_9280(ah)) { - if (!tx_chainmask_cfg) { - - tx_chainmask_cfg = *tx_chainmask; - rx_chainmask_cfg = *rx_chainmask; - } - - switch (settings) { - case ATH9K_ANT_FIXED_A: - *tx_chainmask = ATH9K_ANTENNA0_CHAINMASK; - *rx_chainmask = ATH9K_ANTENNA0_CHAINMASK; - *antenna_cfgd = true; - break; - case ATH9K_ANT_FIXED_B: - if (ah->caps.tx_chainmask > - ATH9K_ANTENNA1_CHAINMASK) { - *tx_chainmask = ATH9K_ANTENNA1_CHAINMASK; - } - *rx_chainmask = ATH9K_ANTENNA1_CHAINMASK; - *antenna_cfgd = true; - break; - case ATH9K_ANT_VARIABLE: - *tx_chainmask = tx_chainmask_cfg; - *rx_chainmask = rx_chainmask_cfg; - *antenna_cfgd = true; - break; - default: - break; - } - } else { - ah->config.diversity_control = settings; - } - - return true; -} - -/*********************/ -/* General Operation */ -/*********************/ - -u32 ath9k_hw_getrxfilter(struct ath_hw *ah) -{ - u32 bits = REG_READ(ah, AR_RX_FILTER); - u32 phybits = REG_READ(ah, AR_PHY_ERR); - - if (phybits & AR_PHY_ERR_RADAR) - bits |= ATH9K_RX_FILTER_PHYRADAR; - if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) - bits |= ATH9K_RX_FILTER_PHYERR; - - return bits; -} - -void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) -{ - u32 phybits; - - REG_WRITE(ah, AR_RX_FILTER, bits); - - phybits = 0; - if (bits & ATH9K_RX_FILTER_PHYRADAR) - phybits |= AR_PHY_ERR_RADAR; - if (bits & ATH9K_RX_FILTER_PHYERR) - phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING; - REG_WRITE(ah, AR_PHY_ERR, phybits); - - if (phybits) - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA); - else - REG_WRITE(ah, AR_RXCFG, - REG_READ(ah, AR_RXCFG) & ~AR_RXCFG_ZLFDMA); -} - -bool ath9k_hw_phy_disable(struct ath_hw *ah) -{ - return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_WARM); -} - -bool ath9k_hw_disable(struct ath_hw *ah) -{ - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return false; - - return ath9k_hw_set_reset_reg(ah, ATH9K_RESET_COLD); -} - -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit) -{ - struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); - struct ath9k_channel *chan = ah->curchan; - struct ieee80211_channel *channel = chan->chan; - - regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); - - ah->eep_ops->set_txpower(ah, chan, - ath9k_regd_get_ctl(regulatory, chan), - channel->max_antenna_gain * 2, - channel->max_power * 2, - min((u32) MAX_RATE_POWER, - (u32) regulatory->power_limit)); -} - -void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac) -{ - memcpy(ah->macaddr, mac, ETH_ALEN); -} - -void ath9k_hw_setopmode(struct ath_hw *ah) -{ - ath9k_hw_set_operating_mode(ah, ah->opmode); -} - -void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1) -{ - REG_WRITE(ah, AR_MCAST_FIL0, filter0); - REG_WRITE(ah, AR_MCAST_FIL1, filter1); -} - -void ath9k_hw_setbssidmask(struct ath_softc *sc) -{ - REG_WRITE(sc->sc_ah, AR_BSSMSKL, get_unaligned_le32(sc->bssidmask)); - REG_WRITE(sc->sc_ah, AR_BSSMSKU, get_unaligned_le16(sc->bssidmask + 4)); -} - -void ath9k_hw_write_associd(struct ath_softc *sc) -{ - REG_WRITE(sc->sc_ah, AR_BSS_ID0, get_unaligned_le32(sc->curbssid)); - REG_WRITE(sc->sc_ah, AR_BSS_ID1, get_unaligned_le16(sc->curbssid + 4) | - ((sc->curaid & 0x3fff) << AR_BSS_ID1_AID_S)); -} - -u64 ath9k_hw_gettsf64(struct ath_hw *ah) -{ - u64 tsf; - - tsf = REG_READ(ah, AR_TSF_U32); - tsf = (tsf << 32) | REG_READ(ah, AR_TSF_L32); - - return tsf; -} - -void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64) -{ - REG_WRITE(ah, AR_TSF_L32, tsf64 & 0xffffffff); - REG_WRITE(ah, AR_TSF_U32, (tsf64 >> 32) & 0xffffffff); -} - -void ath9k_hw_reset_tsf(struct ath_hw *ah) -{ - ath9k_ps_wakeup(ah->ah_sc); - if (!ath9k_hw_wait(ah, AR_SLP32_MODE, AR_SLP32_TSF_WRITE_STATUS, 0, - AH_TSF_WRITE_TIMEOUT)) - DPRINTF(ah->ah_sc, ATH_DBG_RESET, - "AR_SLP32_TSF_WRITE_STATUS limit exceeded\n"); - - REG_WRITE(ah, AR_RESET_TSF, AR_RESET_TSF_ONCE); - ath9k_ps_restore(ah->ah_sc); -} - -void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting) -{ - if (setting) - ah->misc_mode |= AR_PCU_TX_ADD_TSF; - else - ah->misc_mode &= ~AR_PCU_TX_ADD_TSF; -} - -bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us) -{ - if (us < ATH9K_SLOT_TIME_9 || us > ath9k_hw_mac_to_usec(ah, 0xffff)) { - DPRINTF(ah->ah_sc, ATH_DBG_RESET, "bad slot time %u\n", us); - ah->slottime = (u32) -1; - return false; - } else { - REG_WRITE(ah, AR_D_GBL_IFS_SLOT, ath9k_hw_mac_to_clks(ah, us)); - ah->slottime = us; - return true; - } -} - -void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode) -{ - u32 macmode; - - if (mode == ATH9K_HT_MACMODE_2040 && - !ah->config.cwm_ignore_extcca) - macmode = AR_2040_JOINED_RX_CLEAR; - else - macmode = 0; - - REG_WRITE(ah, AR_2040_MODE, macmode); -} - -/* HW Generic timers configuration */ - -static const struct ath_gen_timer_configuration gen_tmr_configuration[] = -{ - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP_TIMER, AR_NDP_PERIOD, AR_TIMER_MODE, 0x0080}, - {AR_NEXT_NDP2_TIMER, AR_NDP2_PERIOD, AR_NDP2_TIMER_MODE, 0x0001}, - {AR_NEXT_NDP2_TIMER + 1*4, AR_NDP2_PERIOD + 1*4, - AR_NDP2_TIMER_MODE, 0x0002}, - {AR_NEXT_NDP2_TIMER + 2*4, AR_NDP2_PERIOD + 2*4, - AR_NDP2_TIMER_MODE, 0x0004}, - {AR_NEXT_NDP2_TIMER + 3*4, AR_NDP2_PERIOD + 3*4, - AR_NDP2_TIMER_MODE, 0x0008}, - {AR_NEXT_NDP2_TIMER + 4*4, AR_NDP2_PERIOD + 4*4, - AR_NDP2_TIMER_MODE, 0x0010}, - {AR_NEXT_NDP2_TIMER + 5*4, AR_NDP2_PERIOD + 5*4, - AR_NDP2_TIMER_MODE, 0x0020}, - {AR_NEXT_NDP2_TIMER + 6*4, AR_NDP2_PERIOD + 6*4, - AR_NDP2_TIMER_MODE, 0x0040}, - {AR_NEXT_NDP2_TIMER + 7*4, AR_NDP2_PERIOD + 7*4, - AR_NDP2_TIMER_MODE, 0x0080} -}; - -/* HW generic timer primitives */ - -/* compute and clear index of rightmost 1 */ -static u32 rightmost_index(struct ath_gen_timer_table *timer_table, u32 *mask) -{ - u32 b; - - b = *mask; - b &= (0-b); - *mask &= ~b; - b *= debruijn32; - b >>= 27; - - return timer_table->gen_timer_index[b]; -} - -u32 ath9k_hw_gettsf32(struct ath_hw *ah) -{ - return REG_READ(ah, AR_TSF_L32); -} - -struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, - void (*trigger)(void *), - void (*overflow)(void *), - void *arg, - u8 timer_index) -{ - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - struct ath_gen_timer *timer; - - timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); - - if (timer == NULL) { - printk(KERN_DEBUG "Failed to allocate memory" - "for hw timer[%d]\n", timer_index); - return NULL; - } - - /* allocate a hardware generic timer slot */ - timer_table->timers[timer_index] = timer; - timer->index = timer_index; - timer->trigger = trigger; - timer->overflow = overflow; - timer->arg = arg; - - return timer; -} - -void ath_gen_timer_start(struct ath_hw *ah, - struct ath_gen_timer *timer, - u32 timer_next, u32 timer_period) -{ - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - u32 tsf; - - BUG_ON(!timer_period); - - set_bit(timer->index, &timer_table->timer_mask.timer_bits); - - tsf = ath9k_hw_gettsf32(ah); - - DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, "curent tsf %x period %x" - "timer_next %x\n", tsf, timer_period, timer_next); - - /* - * Pull timer_next forward if the current TSF already passed it - * because of software latency - */ - if (timer_next < tsf) - timer_next = tsf + timer_period; - - /* - * Program generic timer registers - */ - REG_WRITE(ah, gen_tmr_configuration[timer->index].next_addr, - timer_next); - REG_WRITE(ah, gen_tmr_configuration[timer->index].period_addr, - timer_period); - REG_SET_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, - gen_tmr_configuration[timer->index].mode_mask); - - /* Enable both trigger and thresh interrupt masks */ - REG_SET_BIT(ah, AR_IMR_S5, - (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | - SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); - - if ((ah->ah_sc->imask & ATH9K_INT_GENTIMER) == 0) { - ath9k_hw_set_interrupts(ah, 0); - ah->ah_sc->imask |= ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, ah->ah_sc->imask); - } -} - -void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer) -{ - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - - if ((timer->index < AR_FIRST_NDP_TIMER) || - (timer->index >= ATH_MAX_GEN_TIMER)) { - return; - } - - /* Clear generic timer enable bits. */ - REG_CLR_BIT(ah, gen_tmr_configuration[timer->index].mode_addr, - gen_tmr_configuration[timer->index].mode_mask); - - /* Disable both trigger and thresh interrupt masks */ - REG_CLR_BIT(ah, AR_IMR_S5, - (SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_THRESH) | - SM(AR_GENTMR_BIT(timer->index), AR_IMR_S5_GENTIMER_TRIG))); - - clear_bit(timer->index, &timer_table->timer_mask.timer_bits); - - /* if no timer is enabled, turn off interrupt mask */ - if (timer_table->timer_mask.val == 0) { - ath9k_hw_set_interrupts(ah, 0); - ah->ah_sc->imask &= ~ATH9K_INT_GENTIMER; - ath9k_hw_set_interrupts(ah, ah->ah_sc->imask); - } -} - -void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer) -{ - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - - /* free the hardware generic timer slot */ - timer_table->timers[timer->index] = NULL; - kfree(timer); -} - -/* - * Generic Timer Interrupts handling - */ -void ath_gen_timer_isr(struct ath_hw *ah) -{ - struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; - struct ath_gen_timer *timer; - u32 trigger_mask, thresh_mask, index; - - /* get hardware generic timer interrupt status */ - trigger_mask = ah->intr_gen_timer_trigger; - thresh_mask = ah->intr_gen_timer_thresh; - trigger_mask &= timer_table->timer_mask.val; - thresh_mask &= timer_table->timer_mask.val; - - trigger_mask &= ~thresh_mask; - - while (thresh_mask) { - index = rightmost_index(timer_table, &thresh_mask); - timer = timer_table->timers[index]; - BUG_ON(!timer); - DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, - "TSF overflow for Gen timer %d\n", index); - timer->overflow(timer->arg); - } - - while (trigger_mask) { - index = rightmost_index(timer_table, &trigger_mask); - timer = timer_table->timers[index]; - BUG_ON(!timer); - DPRINTF(ah->ah_sc, ATH_DBG_HWTIMER, - "Gen timer[%d] trigger\n", index); - timer->trigger(timer->arg); - } -} - -/* - * Primitive to disable ASPM - */ -void ath_pcie_aspm_disable(struct ath_softc *sc) -{ - struct pci_dev *pdev = to_pci_dev(sc->dev); - u8 aspm; - - pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm); - aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1); - pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm); -} diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h deleted file mode 100644 index 262556ad62f2..000000000000 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef HW_H -#define HW_H - -#include -#include -#include - -#include "mac.h" -#include "ani.h" -#include "eeprom.h" -#include "calib.h" -#include "reg.h" -#include "phy.h" - -#include "../regd.h" - -#define ATHEROS_VENDOR_ID 0x168c -#define AR5416_DEVID_PCI 0x0023 -#define AR5416_DEVID_PCIE 0x0024 -#define AR9160_DEVID_PCI 0x0027 -#define AR9280_DEVID_PCI 0x0029 -#define AR9280_DEVID_PCIE 0x002a -#define AR9285_DEVID_PCIE 0x002b -#define AR2427_DEVID_PCIE 0x002c -#define AR5416_AR9100_DEVID 0x000b -#define AR_SUBVENDOR_ID_NOG 0x0e11 -#define AR_SUBVENDOR_ID_NEW_A 0x7065 -#define AR5416_MAGIC 0x19641014 - -#define AR5416_DEVID_AR9287_PCI 0x002D -#define AR5416_DEVID_AR9287_PCIE 0x002E - -#define AR9280_COEX2WIRE_SUBSYSID 0x309b -#define AT9285_COEX3WIRE_SA_SUBSYSID 0x30aa -#define AT9285_COEX3WIRE_DA_SUBSYSID 0x30ab - -/* Register read/write primitives */ -#define REG_WRITE(_ah, _reg, _val) ath9k_iowrite32((_ah), (_reg), (_val)) -#define REG_READ(_ah, _reg) ath9k_ioread32((_ah), (_reg)) - -#define SM(_v, _f) (((_v) << _f##_S) & _f) -#define MS(_v, _f) (((_v) & _f) >> _f##_S) -#define REG_RMW(_a, _r, _set, _clr) \ - REG_WRITE(_a, _r, (REG_READ(_a, _r) & ~(_clr)) | (_set)) -#define REG_RMW_FIELD(_a, _r, _f, _v) \ - REG_WRITE(_a, _r, \ - (REG_READ(_a, _r) & ~_f) | (((_v) << _f##_S) & _f)) -#define REG_SET_BIT(_a, _r, _f) \ - REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) -#define REG_CLR_BIT(_a, _r, _f) \ - REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) - -#define DO_DELAY(x) do { \ - if ((++(x) % 64) == 0) \ - udelay(1); \ - } while (0) - -#define REG_WRITE_ARRAY(iniarray, column, regWr) do { \ - int r; \ - for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), (r), 0), \ - INI_RA((iniarray), r, (column))); \ - DO_DELAY(regWr); \ - } \ - } while (0) - -#define AR_GPIO_OUTPUT_MUX_AS_OUTPUT 0 -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_ATTENTION_LED 1 -#define AR_GPIO_OUTPUT_MUX_AS_PCIE_POWER_LED 2 -#define AR_GPIO_OUTPUT_MUX_AS_TX_FRAME 3 -#define AR_GPIO_OUTPUT_MUX_AS_RX_CLEAR_EXTERNAL 4 -#define AR_GPIO_OUTPUT_MUX_AS_MAC_NETWORK_LED 5 -#define AR_GPIO_OUTPUT_MUX_AS_MAC_POWER_LED 6 - -#define AR_GPIOD_MASK 0x00001FFF -#define AR_GPIO_BIT(_gpio) (1 << (_gpio)) - -#define BASE_ACTIVATE_DELAY 100 -#define RTC_PLL_SETTLE_DELAY 1000 -#define COEF_SCALE_S 24 -#define HT40_CHANNEL_CENTER_SHIFT 10 - -#define ATH9K_ANTENNA0_CHAINMASK 0x1 -#define ATH9K_ANTENNA1_CHAINMASK 0x2 - -#define ATH9K_NUM_DMA_DEBUG_REGS 8 -#define ATH9K_NUM_QUEUES 10 - -#define MAX_RATE_POWER 63 -#define AH_WAIT_TIMEOUT 100000 /* (us) */ -#define AH_TSF_WRITE_TIMEOUT 100 /* (us) */ -#define AH_TIME_QUANTUM 10 -#define AR_KEYTABLE_SIZE 128 -#define POWER_UP_TIME 10000 -#define SPUR_RSSI_THRESH 40 - -#define CAB_TIMEOUT_VAL 10 -#define BEACON_TIMEOUT_VAL 10 -#define MIN_BEACON_TIMEOUT_VAL 1 -#define SLEEP_SLOP 3 - -#define INIT_CONFIG_STATUS 0x00000000 -#define INIT_RSSI_THR 0x00000700 -#define INIT_BCON_CNTRL_REG 0x00000000 - -#define TU_TO_USEC(_tu) ((_tu) << 10) - -enum wireless_mode { - ATH9K_MODE_11A = 0, - ATH9K_MODE_11G, - ATH9K_MODE_11NA_HT20, - ATH9K_MODE_11NG_HT20, - ATH9K_MODE_11NA_HT40PLUS, - ATH9K_MODE_11NA_HT40MINUS, - ATH9K_MODE_11NG_HT40PLUS, - ATH9K_MODE_11NG_HT40MINUS, - ATH9K_MODE_MAX, -}; - -enum ath9k_ant_setting { - ATH9K_ANT_VARIABLE = 0, - ATH9K_ANT_FIXED_A, - ATH9K_ANT_FIXED_B -}; - -enum ath9k_hw_caps { - ATH9K_HW_CAP_MIC_AESCCM = BIT(0), - ATH9K_HW_CAP_MIC_CKIP = BIT(1), - ATH9K_HW_CAP_MIC_TKIP = BIT(2), - ATH9K_HW_CAP_CIPHER_AESCCM = BIT(3), - ATH9K_HW_CAP_CIPHER_CKIP = BIT(4), - ATH9K_HW_CAP_CIPHER_TKIP = BIT(5), - ATH9K_HW_CAP_VEOL = BIT(6), - ATH9K_HW_CAP_BSSIDMASK = BIT(7), - ATH9K_HW_CAP_MCAST_KEYSEARCH = BIT(8), - ATH9K_HW_CAP_HT = BIT(9), - ATH9K_HW_CAP_GTT = BIT(10), - ATH9K_HW_CAP_FASTCC = BIT(11), - ATH9K_HW_CAP_RFSILENT = BIT(12), - ATH9K_HW_CAP_CST = BIT(13), - ATH9K_HW_CAP_ENHANCEDPM = BIT(14), - ATH9K_HW_CAP_AUTOSLEEP = BIT(15), - ATH9K_HW_CAP_4KB_SPLITTRANS = BIT(16), -}; - -enum ath9k_capability_type { - ATH9K_CAP_CIPHER = 0, - ATH9K_CAP_TKIP_MIC, - ATH9K_CAP_TKIP_SPLIT, - ATH9K_CAP_DIVERSITY, - ATH9K_CAP_TXPOW, - ATH9K_CAP_MCAST_KEYSRCH, - ATH9K_CAP_DS -}; - -struct ath9k_hw_capabilities { - u32 hw_caps; /* ATH9K_HW_CAP_* from ath9k_hw_caps */ - DECLARE_BITMAP(wireless_modes, ATH9K_MODE_MAX); /* ATH9K_MODE_* */ - u16 total_queues; - u16 keycache_size; - u16 low_5ghz_chan, high_5ghz_chan; - u16 low_2ghz_chan, high_2ghz_chan; - u16 rts_aggr_limit; - u8 tx_chainmask; - u8 rx_chainmask; - u16 tx_triglevel_max; - u16 reg_cap; - u8 num_gpio_pins; - u8 num_antcfg_2ghz; - u8 num_antcfg_5ghz; -}; - -struct ath9k_ops_config { - int dma_beacon_response_time; - int sw_beacon_response_time; - int additional_swba_backoff; - int ack_6mb; - int cwm_ignore_extcca; - u8 pcie_powersave_enable; - u8 pcie_clock_req; - u32 pcie_waen; - u8 analog_shiftreg; - u8 ht_enable; - u32 ofdm_trig_low; - u32 ofdm_trig_high; - u32 cck_trig_high; - u32 cck_trig_low; - u32 enable_ani; - enum ath9k_ant_setting diversity_control; - u16 antenna_switch_swap; - int serialize_regmode; - bool intr_mitigation; -#define SPUR_DISABLE 0 -#define SPUR_ENABLE_IOCTL 1 -#define SPUR_ENABLE_EEPROM 2 -#define AR_EEPROM_MODAL_SPURS 5 -#define AR_SPUR_5413_1 1640 -#define AR_SPUR_5413_2 1200 -#define AR_NO_SPUR 0x8000 -#define AR_BASE_FREQ_2GHZ 2300 -#define AR_BASE_FREQ_5GHZ 4900 -#define AR_SPUR_FEEQ_BOUND_HT40 19 -#define AR_SPUR_FEEQ_BOUND_HT20 10 - int spurmode; - u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; - u8 max_txtrig_level; -}; - -enum ath9k_int { - ATH9K_INT_RX = 0x00000001, - ATH9K_INT_RXDESC = 0x00000002, - ATH9K_INT_RXNOFRM = 0x00000008, - ATH9K_INT_RXEOL = 0x00000010, - ATH9K_INT_RXORN = 0x00000020, - ATH9K_INT_TX = 0x00000040, - ATH9K_INT_TXDESC = 0x00000080, - ATH9K_INT_TIM_TIMER = 0x00000100, - ATH9K_INT_TXURN = 0x00000800, - ATH9K_INT_MIB = 0x00001000, - ATH9K_INT_RXPHY = 0x00004000, - ATH9K_INT_RXKCM = 0x00008000, - ATH9K_INT_SWBA = 0x00010000, - ATH9K_INT_BMISS = 0x00040000, - ATH9K_INT_BNR = 0x00100000, - ATH9K_INT_TIM = 0x00200000, - ATH9K_INT_DTIM = 0x00400000, - ATH9K_INT_DTIMSYNC = 0x00800000, - ATH9K_INT_GPIO = 0x01000000, - ATH9K_INT_CABEND = 0x02000000, - ATH9K_INT_TSFOOR = 0x04000000, - ATH9K_INT_GENTIMER = 0x08000000, - ATH9K_INT_CST = 0x10000000, - ATH9K_INT_GTT = 0x20000000, - ATH9K_INT_FATAL = 0x40000000, - ATH9K_INT_GLOBAL = 0x80000000, - ATH9K_INT_BMISC = ATH9K_INT_TIM | - ATH9K_INT_DTIM | - ATH9K_INT_DTIMSYNC | - ATH9K_INT_TSFOOR | - ATH9K_INT_CABEND, - ATH9K_INT_COMMON = ATH9K_INT_RXNOFRM | - ATH9K_INT_RXDESC | - ATH9K_INT_RXEOL | - ATH9K_INT_RXORN | - ATH9K_INT_TXURN | - ATH9K_INT_TXDESC | - ATH9K_INT_MIB | - ATH9K_INT_RXPHY | - ATH9K_INT_RXKCM | - ATH9K_INT_SWBA | - ATH9K_INT_BMISS | - ATH9K_INT_GPIO, - ATH9K_INT_NOCARD = 0xffffffff -}; - -#define CHANNEL_CW_INT 0x00002 -#define CHANNEL_CCK 0x00020 -#define CHANNEL_OFDM 0x00040 -#define CHANNEL_2GHZ 0x00080 -#define CHANNEL_5GHZ 0x00100 -#define CHANNEL_PASSIVE 0x00200 -#define CHANNEL_DYN 0x00400 -#define CHANNEL_HALF 0x04000 -#define CHANNEL_QUARTER 0x08000 -#define CHANNEL_HT20 0x10000 -#define CHANNEL_HT40PLUS 0x20000 -#define CHANNEL_HT40MINUS 0x40000 - -#define CHANNEL_A (CHANNEL_5GHZ|CHANNEL_OFDM) -#define CHANNEL_B (CHANNEL_2GHZ|CHANNEL_CCK) -#define CHANNEL_G (CHANNEL_2GHZ|CHANNEL_OFDM) -#define CHANNEL_G_HT20 (CHANNEL_2GHZ|CHANNEL_HT20) -#define CHANNEL_A_HT20 (CHANNEL_5GHZ|CHANNEL_HT20) -#define CHANNEL_G_HT40PLUS (CHANNEL_2GHZ|CHANNEL_HT40PLUS) -#define CHANNEL_G_HT40MINUS (CHANNEL_2GHZ|CHANNEL_HT40MINUS) -#define CHANNEL_A_HT40PLUS (CHANNEL_5GHZ|CHANNEL_HT40PLUS) -#define CHANNEL_A_HT40MINUS (CHANNEL_5GHZ|CHANNEL_HT40MINUS) -#define CHANNEL_ALL \ - (CHANNEL_OFDM| \ - CHANNEL_CCK| \ - CHANNEL_2GHZ | \ - CHANNEL_5GHZ | \ - CHANNEL_HT20 | \ - CHANNEL_HT40PLUS | \ - CHANNEL_HT40MINUS) - -struct ath9k_channel { - struct ieee80211_channel *chan; - u16 channel; - u32 channelFlags; - u32 chanmode; - int32_t CalValid; - bool oneTimeCalsDone; - int8_t iCoff; - int8_t qCoff; - int16_t rawNoiseFloor; -}; - -#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ - (((_c)->channelFlags & CHANNEL_G_HT20) == CHANNEL_G_HT20) || \ - (((_c)->channelFlags & CHANNEL_G_HT40PLUS) == CHANNEL_G_HT40PLUS) || \ - (((_c)->channelFlags & CHANNEL_G_HT40MINUS) == CHANNEL_G_HT40MINUS)) -#define IS_CHAN_OFDM(_c) (((_c)->channelFlags & CHANNEL_OFDM) != 0) -#define IS_CHAN_5GHZ(_c) (((_c)->channelFlags & CHANNEL_5GHZ) != 0) -#define IS_CHAN_2GHZ(_c) (((_c)->channelFlags & CHANNEL_2GHZ) != 0) -#define IS_CHAN_HALF_RATE(_c) (((_c)->channelFlags & CHANNEL_HALF) != 0) -#define IS_CHAN_QUARTER_RATE(_c) (((_c)->channelFlags & CHANNEL_QUARTER) != 0) -#define IS_CHAN_A_5MHZ_SPACED(_c) \ - ((((_c)->channelFlags & CHANNEL_5GHZ) != 0) && \ - (((_c)->channel % 20) != 0) && \ - (((_c)->channel % 10) != 0)) - -/* These macros check chanmode and not channelFlags */ -#define IS_CHAN_B(_c) ((_c)->chanmode == CHANNEL_B) -#define IS_CHAN_HT20(_c) (((_c)->chanmode == CHANNEL_A_HT20) || \ - ((_c)->chanmode == CHANNEL_G_HT20)) -#define IS_CHAN_HT40(_c) (((_c)->chanmode == CHANNEL_A_HT40PLUS) || \ - ((_c)->chanmode == CHANNEL_A_HT40MINUS) || \ - ((_c)->chanmode == CHANNEL_G_HT40PLUS) || \ - ((_c)->chanmode == CHANNEL_G_HT40MINUS)) -#define IS_CHAN_HT(_c) (IS_CHAN_HT20((_c)) || IS_CHAN_HT40((_c))) - -enum ath9k_power_mode { - ATH9K_PM_AWAKE = 0, - ATH9K_PM_FULL_SLEEP, - ATH9K_PM_NETWORK_SLEEP, - ATH9K_PM_UNDEFINED -}; - -enum ath9k_tp_scale { - ATH9K_TP_SCALE_MAX = 0, - ATH9K_TP_SCALE_50, - ATH9K_TP_SCALE_25, - ATH9K_TP_SCALE_12, - ATH9K_TP_SCALE_MIN -}; - -enum ser_reg_mode { - SER_REG_MODE_OFF = 0, - SER_REG_MODE_ON = 1, - SER_REG_MODE_AUTO = 2, -}; - -struct ath9k_beacon_state { - u32 bs_nexttbtt; - u32 bs_nextdtim; - u32 bs_intval; -#define ATH9K_BEACON_PERIOD 0x0000ffff -#define ATH9K_BEACON_ENA 0x00800000 -#define ATH9K_BEACON_RESET_TSF 0x01000000 -#define ATH9K_TSFOOR_THRESHOLD 0x00004240 /* 16k us */ - u32 bs_dtimperiod; - u16 bs_cfpperiod; - u16 bs_cfpmaxduration; - u32 bs_cfpnext; - u16 bs_timoffset; - u16 bs_bmissthreshold; - u32 bs_sleepduration; - u32 bs_tsfoor_threshold; -}; - -struct chan_centers { - u16 synth_center; - u16 ctl_center; - u16 ext_center; -}; - -enum { - ATH9K_RESET_POWER_ON, - ATH9K_RESET_WARM, - ATH9K_RESET_COLD, -}; - -struct ath9k_hw_version { - u32 magic; - u16 devid; - u16 subvendorid; - u32 macVersion; - u16 macRev; - u16 phyRev; - u16 analog5GhzRev; - u16 analog2GhzRev; - u16 subsysid; -}; - -/* Generic TSF timer definitions */ - -#define ATH_MAX_GEN_TIMER 16 - -#define AR_GENTMR_BIT(_index) (1 << (_index)) - -/* - * Using de Bruijin sequence to to look up 1's index in a 32 bit number - * debruijn32 = 0000 0111 0111 1100 1011 0101 0011 0001 - */ -#define debruijn32 0x077CB531U - -struct ath_gen_timer_configuration { - u32 next_addr; - u32 period_addr; - u32 mode_addr; - u32 mode_mask; -}; - -struct ath_gen_timer { - void (*trigger)(void *arg); - void (*overflow)(void *arg); - void *arg; - u8 index; -}; - -struct ath_gen_timer_table { - u32 gen_timer_index[32]; - struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; - union { - unsigned long timer_bits; - u16 val; - } timer_mask; -}; - -struct ath_hw { - struct ath_softc *ah_sc; - struct ath9k_hw_version hw_version; - struct ath9k_ops_config config; - struct ath9k_hw_capabilities caps; - struct ath9k_channel channels[38]; - struct ath9k_channel *curchan; - - union { - struct ar5416_eeprom_def def; - struct ar5416_eeprom_4k map4k; - struct ar9287_eeprom map9287; - } eeprom; - const struct eeprom_ops *eep_ops; - enum ath9k_eep_map eep_map; - - bool sw_mgmt_crypto; - bool is_pciexpress; - u8 macaddr[ETH_ALEN]; - u16 tx_trig_level; - u16 rfsilent; - u32 rfkill_gpio; - u32 rfkill_polarity; - u32 ah_flags; - - bool htc_reset_init; - - enum nl80211_iftype opmode; - enum ath9k_power_mode power_mode; - - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; - struct ath9k_pacal_info pacal_info; - struct ar5416Stats stats; - struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; - - int16_t curchan_rad_index; - u32 mask_reg; - u32 txok_interrupt_mask; - u32 txerr_interrupt_mask; - u32 txdesc_interrupt_mask; - u32 txeol_interrupt_mask; - u32 txurn_interrupt_mask; - bool chip_fullsleep; - u32 atim_window; - - /* Calibration */ - enum ath9k_cal_types supp_cals; - struct ath9k_cal_list iq_caldata; - struct ath9k_cal_list adcgain_caldata; - struct ath9k_cal_list adcdc_calinitdata; - struct ath9k_cal_list adcdc_caldata; - struct ath9k_cal_list *cal_list; - struct ath9k_cal_list *cal_list_last; - struct ath9k_cal_list *cal_list_curr; -#define totalPowerMeasI meas0.unsign -#define totalPowerMeasQ meas1.unsign -#define totalIqCorrMeas meas2.sign -#define totalAdcIOddPhase meas0.unsign -#define totalAdcIEvenPhase meas1.unsign -#define totalAdcQOddPhase meas2.unsign -#define totalAdcQEvenPhase meas3.unsign -#define totalAdcDcOffsetIOddPhase meas0.sign -#define totalAdcDcOffsetIEvenPhase meas1.sign -#define totalAdcDcOffsetQOddPhase meas2.sign -#define totalAdcDcOffsetQEvenPhase meas3.sign - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas0; - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas1; - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas2; - union { - u32 unsign[AR5416_MAX_CHAINS]; - int32_t sign[AR5416_MAX_CHAINS]; - } meas3; - u16 cal_samples; - - u32 sta_id1_defaults; - u32 misc_mode; - enum { - AUTO_32KHZ, - USE_32KHZ, - DONT_USE_32KHZ, - } enable_32kHz_clock; - - /* RF */ - u32 *analogBank0Data; - u32 *analogBank1Data; - u32 *analogBank2Data; - u32 *analogBank3Data; - u32 *analogBank6Data; - u32 *analogBank6TPCData; - u32 *analogBank7Data; - u32 *addac5416_21; - u32 *bank6Temp; - - int16_t txpower_indexoffset; - u32 beacon_interval; - u32 slottime; - u32 acktimeout; - u32 ctstimeout; - u32 globaltxtimeout; - u8 gbeacon_rate; - - /* ANI */ - u32 proc_phyerr; - u32 aniperiod; - struct ar5416AniState *curani; - struct ar5416AniState ani[255]; - int totalSizeDesired[5]; - int coarse_high[5]; - int coarse_low[5]; - int firpwr[5]; - enum ath9k_ani_cmd ani_function; - - u32 intr_txqs; - enum ath9k_ht_extprotspacing extprotspacing; - u8 txchainmask; - u8 rxchainmask; - - u32 originalGain[22]; - int initPDADC; - int PDADCdelta; - u8 led_pin; - - struct ar5416IniArray iniModes; - struct ar5416IniArray iniCommon; - struct ar5416IniArray iniBank0; - struct ar5416IniArray iniBB_RfGain; - struct ar5416IniArray iniBank1; - struct ar5416IniArray iniBank2; - struct ar5416IniArray iniBank3; - struct ar5416IniArray iniBank6; - struct ar5416IniArray iniBank6TPC; - struct ar5416IniArray iniBank7; - struct ar5416IniArray iniAddac; - struct ar5416IniArray iniPcieSerdes; - struct ar5416IniArray iniModesAdditional; - struct ar5416IniArray iniModesRxGain; - struct ar5416IniArray iniModesTxGain; - - u32 intr_gen_timer_trigger; - u32 intr_gen_timer_thresh; - struct ath_gen_timer_table hw_gen_timers; -}; - -/* Initialization, Detach, Reset */ -const char *ath9k_hw_probe(u16 vendorid, u16 devid); -void ath9k_hw_detach(struct ath_hw *ah); -int ath9k_hw_init(struct ath_hw *ah); -void ath9k_hw_rf_free(struct ath_hw *ah); -int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, - bool bChannelChange); -void ath9k_hw_fill_cap_info(struct ath_hw *ah); -bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 *result); -bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, - u32 capability, u32 setting, int *status); - -/* Key Cache Management */ -bool ath9k_hw_keyreset(struct ath_hw *ah, u16 entry); -bool ath9k_hw_keysetmac(struct ath_hw *ah, u16 entry, const u8 *mac); -bool ath9k_hw_set_keycache_entry(struct ath_hw *ah, u16 entry, - const struct ath9k_keyval *k, - const u8 *mac); -bool ath9k_hw_keyisvalid(struct ath_hw *ah, u16 entry); - -/* GPIO / RFKILL / Antennae */ -void ath9k_hw_cfg_gpio_input(struct ath_hw *ah, u32 gpio); -u32 ath9k_hw_gpio_get(struct ath_hw *ah, u32 gpio); -void ath9k_hw_cfg_output(struct ath_hw *ah, u32 gpio, - u32 ah_signal_type); -void ath9k_hw_set_gpio(struct ath_hw *ah, u32 gpio, u32 val); -u32 ath9k_hw_getdefantenna(struct ath_hw *ah); -void ath9k_hw_setantenna(struct ath_hw *ah, u32 antenna); -bool ath9k_hw_setantennaswitch(struct ath_hw *ah, - enum ath9k_ant_setting settings, - struct ath9k_channel *chan, - u8 *tx_chainmask, u8 *rx_chainmask, - u8 *antenna_cfgd); - -/* General Operation */ -bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout); -u32 ath9k_hw_reverse_bits(u32 val, u32 n); -bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); -u16 ath9k_hw_computetxtime(struct ath_hw *ah, - const struct ath_rate_table *rates, - u32 frameLen, u16 rateix, bool shortPreamble); -void ath9k_hw_get_channel_centers(struct ath_hw *ah, - struct ath9k_channel *chan, - struct chan_centers *centers); -u32 ath9k_hw_getrxfilter(struct ath_hw *ah); -void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits); -bool ath9k_hw_phy_disable(struct ath_hw *ah); -bool ath9k_hw_disable(struct ath_hw *ah); -void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit); -void ath9k_hw_setmac(struct ath_hw *ah, const u8 *mac); -void ath9k_hw_setopmode(struct ath_hw *ah); -void ath9k_hw_setmcastfilter(struct ath_hw *ah, u32 filter0, u32 filter1); -void ath9k_hw_setbssidmask(struct ath_softc *sc); -void ath9k_hw_write_associd(struct ath_softc *sc); -u64 ath9k_hw_gettsf64(struct ath_hw *ah); -void ath9k_hw_settsf64(struct ath_hw *ah, u64 tsf64); -void ath9k_hw_reset_tsf(struct ath_hw *ah); -void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting); -bool ath9k_hw_setslottime(struct ath_hw *ah, u32 us); -void ath9k_hw_set11nmac2040(struct ath_hw *ah, enum ath9k_ht_macmode mode); -void ath9k_hw_beaconinit(struct ath_hw *ah, u32 next_beacon, u32 beacon_period); -void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, - const struct ath9k_beacon_state *bs); -bool ath9k_hw_setpower(struct ath_hw *ah, - enum ath9k_power_mode mode); -void ath9k_hw_configpcipowersave(struct ath_hw *ah, int restore, int power_off); - -/* Interrupt Handling */ -bool ath9k_hw_intrpend(struct ath_hw *ah); -bool ath9k_hw_getisr(struct ath_hw *ah, enum ath9k_int *masked); -enum ath9k_int ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints); - -/* Generic hw timer primitives */ -struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, - void (*trigger)(void *), - void (*overflow)(void *), - void *arg, - u8 timer_index); -void ath_gen_timer_start(struct ath_hw *ah, struct ath_gen_timer *timer, - u32 timer_next, u32 timer_period); -void ath_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); -void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); -void ath_gen_timer_isr(struct ath_hw *hw); -u32 ath9k_hw_gettsf32(struct ath_hw *ah); - -#define ATH_PCIE_CAP_LINK_CTRL 0x70 -#define ATH_PCIE_CAP_LINK_L0S 1 -#define ATH_PCIE_CAP_LINK_L1 2 - -void ath_pcie_aspm_disable(struct ath_softc *sc); -#endif diff --git a/drivers/net/wireless/ath/ath9k/initvals.h b/drivers/net/wireless/ath/ath9k/initvals.h deleted file mode 100644 index a21c214a3e4d..000000000000 --- a/drivers/net/wireless/ath/ath9k/initvals.h +++ /dev/null @@ -1,7033 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -static const u32 ar5416Modes[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c48b4e0, 0x6c48b4e0, 0x6c48b0de, 0x6c48b0de, 0x6c48b0de }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18, 0x00049d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190, 0x409a4190 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x000001b8, 0x00000370, 0x00000268, 0x00000134, 0x00000134 }, - { 0x00009924, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b, 0xd0058a0b }, - { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, - { 0x00009960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x0000a960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x0000b960, 0x00000900, 0x00000900, 0x00012d80, 0x00012d80, 0x00012d80 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00001120, 0x00001120, 0x00001120 }, - { 0x0000c9bc, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00, 0x001a0a00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002ec1e0, 0x002ec1e0, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00007010, 0x00000000 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00070000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a002e }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5d50e188 }, - { 0x00009958, 0x00081fff }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x001fff00 }, - { 0x000099ac, 0x00000000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x000000aa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x00000bb5 }, - { 0x0000a22c, 0x00000011 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x051701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa1f }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x08000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1[][2] = { - { 0x000098b0, 0x02108421 }, - { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2[][2] = { - { 0x000098b0, 0x0e73ff17 }, - { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014008f, 0x0014008f }, - { 0x0000989c, 0x00c40003, 0x00c40003 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000f1, 0x000000f1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x201400df, 0x201400df }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007081, 0x00007081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000003 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x0000000c }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000030 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000060 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000058 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9100[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6d48b4e2, 0x6d48b4e2, 0x6d48b0e2, 0x6d48b0e2, 0x6d48b0e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec86d2e, 0x7ec84d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a11, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009940, 0x00754604, 0x00754604, 0xfff81204, 0xfff81204, 0xfff81204 }, - { 0x00009944, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020, 0xdfb81020 }, - { 0x00009954, 0x5f3ca3de, 0x5f3ca3de, 0xe250a51e, 0xe250a51e, 0xe250a51e }, - { 0x00009958, 0x2108ecff, 0x2108ecff, 0x3388ffff, 0x3388ffff, 0x3388ffff }, -#ifdef TB243 - { 0x00009960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x0000a960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x0000b960, 0x00000900, 0x00000900, 0x00009b40, 0x00009b40, 0x00012d80 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00002210, 0x00002210, 0x00001120 }, -#else - { 0x00009960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x0000a960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x0000b960, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0, 0x0001bfc0 }, - { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, -#endif - { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a1000, 0x001a0c00, 0x001a0c00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9100[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00020010, 0x00000003 }, - { 0x00020038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00004000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x001a0bb5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889ae }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000a000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000001 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79a8aa33 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9100[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9100[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9100[][2] = { - { 0x000098b0, 0x02108421}, - { 0x000098ec, 0x00000008}, -}; - -static const u32 ar5416Bank2_9100[][2] = { - { 0x000098b0, 0x0e73ff17}, - { 0x000098e0, 0x00000420}, -}; - -static const u32 ar5416Bank3_9100[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9100[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014000f, 0x0014000f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x000180d6, 0x000180d6 }, - { 0x0000989c, 0x0000c0aa, 0x0000c0aa }, - { 0x0000989c, 0x000000b1, 0x000000b1 }, - { 0x0000989c, 0x00002000, 0x00002000 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - - -static const u32 ar5416Bank6TPC_9100[][3] = { - - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x2014008f, 0x2014008f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007080, 0x00007080 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9100[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static const u32 ar5416Addac_9100[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000010 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000015 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static const u32 ar5416Modes_9160[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d93a7, 0x128d93cf, 0x12e013d7, 0x12e013ab, 0x098813cf }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000a848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x0000b848, 0x001a6a65, 0x001a6a65, 0x00197a68, 0x00197a68, 0x00197a68 }, - { 0x00009850, 0x6c48b4e2, 0x6c48b4e2, 0x6c48b0e2, 0x6c48b0e2, 0x6c48b0e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0, 0x409a40d0 }, - { 0x0000986c, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081, 0x050cb081 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020, 0xffb81020 }, - { 0x00009960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x0000a960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x0000b960, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40, 0x00009b40 }, - { 0x00009964, 0x00001120, 0x00001120, 0x00001120, 0x00001120, 0x00001120 }, - { 0x0000c968, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x0000c9bc, 0x001a0600, 0x001a0600, 0x001a0c00, 0x001a0c00, 0x001a0c00 }, - { 0x000099c0, 0x038919be, 0x038919be, 0x038919be, 0x038919be, 0x038919be }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000880, 0x00000880, 0x00000880, 0x00000880, 0x00000880 }, - { 0x0000a208, 0xd6be4788, 0xd6be4788, 0xd03e4788, 0xd03e4788, 0xd03e4788 }, - { 0x0000a20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000b20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000c20c, 0x002fc160, 0x002fc160, 0x002ac120, 0x002ac120, 0x002ac120 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a1a9caa, 0x0a1a9caa, 0x0a1a7caa, 0x0a1a7caa, 0x0a1a7caa }, - { 0x0000a300, 0x18010000, 0x18010000, 0x18010000, 0x18010000, 0x18010000 }, - { 0x0000a304, 0x30032602, 0x30032602, 0x2e032402, 0x2e032402, 0x2e032402 }, - { 0x0000a308, 0x48073e06, 0x48073e06, 0x4a0a3c06, 0x4a0a3c06, 0x4a0a3c06 }, - { 0x0000a30c, 0x560b4c0a, 0x560b4c0a, 0x621a540b, 0x621a540b, 0x621a540b }, - { 0x0000a310, 0x641a600f, 0x641a600f, 0x764f6c1b, 0x764f6c1b, 0x764f6c1b }, - { 0x0000a314, 0x7a4f6e1b, 0x7a4f6e1b, 0x845b7a5a, 0x845b7a5a, 0x845b7a5a }, - { 0x0000a318, 0x8c5b7e5a, 0x8c5b7e5a, 0x950f8ccf, 0x950f8ccf, 0x950f8ccf }, - { 0x0000a31c, 0x9d0f96cf, 0x9d0f96cf, 0xa5cf9b4f, 0xa5cf9b4f, 0xa5cf9b4f }, - { 0x0000a320, 0xb51fa69f, 0xb51fa69f, 0xbddfaf1f, 0xbddfaf1f, 0xbddfaf1f }, - { 0x0000a324, 0xcb3fbd07, 0xcb3fbcbf, 0xd1ffc93f, 0xd1ffc93f, 0xd1ffc93f }, - { 0x0000a328, 0x0000d7bf, 0x0000d7bf, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u32 ar5416Common_9160[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00007010, 0x00000020 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xad848e19 }, - { 0x00009810, 0x7d14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x1284233c }, - { 0x00009854, 0x00000859 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x05100000 }, - { 0x0000a920, 0x05100000 }, - { 0x0000b920, 0x05100000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280b212 }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009940, 0x00750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000200 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x00009b00, 0x00000000 }, - { 0x00009b04, 0x00000001 }, - { 0x00009b08, 0x00000002 }, - { 0x00009b0c, 0x00000003 }, - { 0x00009b10, 0x00000004 }, - { 0x00009b14, 0x00000005 }, - { 0x00009b18, 0x00000008 }, - { 0x00009b1c, 0x00000009 }, - { 0x00009b20, 0x0000000a }, - { 0x00009b24, 0x0000000b }, - { 0x00009b28, 0x0000000c }, - { 0x00009b2c, 0x0000000d }, - { 0x00009b30, 0x00000010 }, - { 0x00009b34, 0x00000011 }, - { 0x00009b38, 0x00000012 }, - { 0x00009b3c, 0x00000013 }, - { 0x00009b40, 0x00000014 }, - { 0x00009b44, 0x00000015 }, - { 0x00009b48, 0x00000018 }, - { 0x00009b4c, 0x00000019 }, - { 0x00009b50, 0x0000001a }, - { 0x00009b54, 0x0000001b }, - { 0x00009b58, 0x0000001c }, - { 0x00009b5c, 0x0000001d }, - { 0x00009b60, 0x00000020 }, - { 0x00009b64, 0x00000021 }, - { 0x00009b68, 0x00000022 }, - { 0x00009b6c, 0x00000023 }, - { 0x00009b70, 0x00000024 }, - { 0x00009b74, 0x00000025 }, - { 0x00009b78, 0x00000028 }, - { 0x00009b7c, 0x00000029 }, - { 0x00009b80, 0x0000002a }, - { 0x00009b84, 0x0000002b }, - { 0x00009b88, 0x0000002c }, - { 0x00009b8c, 0x0000002d }, - { 0x00009b90, 0x00000030 }, - { 0x00009b94, 0x00000031 }, - { 0x00009b98, 0x00000032 }, - { 0x00009b9c, 0x00000033 }, - { 0x00009ba0, 0x00000034 }, - { 0x00009ba4, 0x00000035 }, - { 0x00009ba8, 0x00000035 }, - { 0x00009bac, 0x00000035 }, - { 0x00009bb0, 0x00000035 }, - { 0x00009bb4, 0x00000035 }, - { 0x00009bb8, 0x00000035 }, - { 0x00009bbc, 0x00000035 }, - { 0x00009bc0, 0x00000035 }, - { 0x00009bc4, 0x00000035 }, - { 0x00009bc8, 0x00000035 }, - { 0x00009bcc, 0x00000035 }, - { 0x00009bd0, 0x00000035 }, - { 0x00009bd4, 0x00000035 }, - { 0x00009bd8, 0x00000035 }, - { 0x00009bdc, 0x00000035 }, - { 0x00009be0, 0x00000035 }, - { 0x00009be4, 0x00000035 }, - { 0x00009be8, 0x00000035 }, - { 0x00009bec, 0x00000035 }, - { 0x00009bf0, 0x00000035 }, - { 0x00009bf4, 0x00000035 }, - { 0x00009bf8, 0x00000010 }, - { 0x00009bfc, 0x0000001a }, - { 0x0000a210, 0x40806333 }, - { 0x0000a214, 0x00106c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x018830c6 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x001a0bb5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x0000e000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cc75380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000001 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000c26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a338, 0x00000000 }, - { 0x0000a33c, 0x00000000 }, - { 0x0000a340, 0x00000000 }, - { 0x0000a344, 0x00000000 }, - { 0x0000a348, 0x3fffffff }, - { 0x0000a34c, 0x3fffffff }, - { 0x0000a350, 0x3fffffff }, - { 0x0000a354, 0x0003ffff }, - { 0x0000a358, 0x79bfaa03 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, -}; - -static const u32 ar5416Bank0_9160[][2] = { - { 0x000098b0, 0x1e5795e5 }, - { 0x000098e0, 0x02008020 }, -}; - -static const u32 ar5416BB_RfGain_9160[][3] = { - { 0x00009a00, 0x00000000, 0x00000000 }, - { 0x00009a04, 0x00000040, 0x00000040 }, - { 0x00009a08, 0x00000080, 0x00000080 }, - { 0x00009a0c, 0x000001a1, 0x00000141 }, - { 0x00009a10, 0x000001e1, 0x00000181 }, - { 0x00009a14, 0x00000021, 0x000001c1 }, - { 0x00009a18, 0x00000061, 0x00000001 }, - { 0x00009a1c, 0x00000168, 0x00000041 }, - { 0x00009a20, 0x000001a8, 0x000001a8 }, - { 0x00009a24, 0x000001e8, 0x000001e8 }, - { 0x00009a28, 0x00000028, 0x00000028 }, - { 0x00009a2c, 0x00000068, 0x00000068 }, - { 0x00009a30, 0x00000189, 0x000000a8 }, - { 0x00009a34, 0x000001c9, 0x00000169 }, - { 0x00009a38, 0x00000009, 0x000001a9 }, - { 0x00009a3c, 0x00000049, 0x000001e9 }, - { 0x00009a40, 0x00000089, 0x00000029 }, - { 0x00009a44, 0x00000170, 0x00000069 }, - { 0x00009a48, 0x000001b0, 0x00000190 }, - { 0x00009a4c, 0x000001f0, 0x000001d0 }, - { 0x00009a50, 0x00000030, 0x00000010 }, - { 0x00009a54, 0x00000070, 0x00000050 }, - { 0x00009a58, 0x00000191, 0x00000090 }, - { 0x00009a5c, 0x000001d1, 0x00000151 }, - { 0x00009a60, 0x00000011, 0x00000191 }, - { 0x00009a64, 0x00000051, 0x000001d1 }, - { 0x00009a68, 0x00000091, 0x00000011 }, - { 0x00009a6c, 0x000001b8, 0x00000051 }, - { 0x00009a70, 0x000001f8, 0x00000198 }, - { 0x00009a74, 0x00000038, 0x000001d8 }, - { 0x00009a78, 0x00000078, 0x00000018 }, - { 0x00009a7c, 0x00000199, 0x00000058 }, - { 0x00009a80, 0x000001d9, 0x00000098 }, - { 0x00009a84, 0x00000019, 0x00000159 }, - { 0x00009a88, 0x00000059, 0x00000199 }, - { 0x00009a8c, 0x00000099, 0x000001d9 }, - { 0x00009a90, 0x000000d9, 0x00000019 }, - { 0x00009a94, 0x000000f9, 0x00000059 }, - { 0x00009a98, 0x000000f9, 0x00000099 }, - { 0x00009a9c, 0x000000f9, 0x000000d9 }, - { 0x00009aa0, 0x000000f9, 0x000000f9 }, - { 0x00009aa4, 0x000000f9, 0x000000f9 }, - { 0x00009aa8, 0x000000f9, 0x000000f9 }, - { 0x00009aac, 0x000000f9, 0x000000f9 }, - { 0x00009ab0, 0x000000f9, 0x000000f9 }, - { 0x00009ab4, 0x000000f9, 0x000000f9 }, - { 0x00009ab8, 0x000000f9, 0x000000f9 }, - { 0x00009abc, 0x000000f9, 0x000000f9 }, - { 0x00009ac0, 0x000000f9, 0x000000f9 }, - { 0x00009ac4, 0x000000f9, 0x000000f9 }, - { 0x00009ac8, 0x000000f9, 0x000000f9 }, - { 0x00009acc, 0x000000f9, 0x000000f9 }, - { 0x00009ad0, 0x000000f9, 0x000000f9 }, - { 0x00009ad4, 0x000000f9, 0x000000f9 }, - { 0x00009ad8, 0x000000f9, 0x000000f9 }, - { 0x00009adc, 0x000000f9, 0x000000f9 }, - { 0x00009ae0, 0x000000f9, 0x000000f9 }, - { 0x00009ae4, 0x000000f9, 0x000000f9 }, - { 0x00009ae8, 0x000000f9, 0x000000f9 }, - { 0x00009aec, 0x000000f9, 0x000000f9 }, - { 0x00009af0, 0x000000f9, 0x000000f9 }, - { 0x00009af4, 0x000000f9, 0x000000f9 }, - { 0x00009af8, 0x000000f9, 0x000000f9 }, - { 0x00009afc, 0x000000f9, 0x000000f9 }, -}; - -static const u32 ar5416Bank1_9160[][2] = { - { 0x000098b0, 0x02108421 }, - { 0x000098ec, 0x00000008 }, -}; - -static const u32 ar5416Bank2_9160[][2] = { - { 0x000098b0, 0x0e73ff17 }, - { 0x000098e0, 0x00000420 }, -}; - -static const u32 ar5416Bank3_9160[][3] = { - { 0x000098f0, 0x01400018, 0x01c00018 }, -}; - -static const u32 ar5416Bank6_9160[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x004210a2, 0x004210a2 }, - { 0x0000989c, 0x0014008f, 0x0014008f }, - { 0x0000989c, 0x00c40003, 0x00c40003 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000f1, 0x000000f1 }, - { 0x0000989c, 0x00002081, 0x00002081 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank6TPC_9160[][3] = { - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00000000, 0x00000000 }, - { 0x0000989c, 0x00e00000, 0x00e00000 }, - { 0x0000989c, 0x005e0000, 0x005e0000 }, - { 0x0000989c, 0x00120000, 0x00120000 }, - { 0x0000989c, 0x00620000, 0x00620000 }, - { 0x0000989c, 0x00020000, 0x00020000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x40ff0000, 0x40ff0000 }, - { 0x0000989c, 0x005f0000, 0x005f0000 }, - { 0x0000989c, 0x00870000, 0x00870000 }, - { 0x0000989c, 0x00f90000, 0x00f90000 }, - { 0x0000989c, 0x007b0000, 0x007b0000 }, - { 0x0000989c, 0x00ff0000, 0x00ff0000 }, - { 0x0000989c, 0x00f50000, 0x00f50000 }, - { 0x0000989c, 0x00dc0000, 0x00dc0000 }, - { 0x0000989c, 0x00110000, 0x00110000 }, - { 0x0000989c, 0x006100a8, 0x006100a8 }, - { 0x0000989c, 0x00423022, 0x00423022 }, - { 0x0000989c, 0x2014008f, 0x2014008f }, - { 0x0000989c, 0x00c40002, 0x00c40002 }, - { 0x0000989c, 0x003000f2, 0x003000f2 }, - { 0x0000989c, 0x00440016, 0x00440016 }, - { 0x0000989c, 0x00410040, 0x00410040 }, - { 0x0000989c, 0x0001805e, 0x0001805e }, - { 0x0000989c, 0x0000c0ab, 0x0000c0ab }, - { 0x0000989c, 0x000000e1, 0x000000e1 }, - { 0x0000989c, 0x00007080, 0x00007080 }, - { 0x0000989c, 0x000000d4, 0x000000d4 }, - { 0x000098d0, 0x0000000f, 0x0010000f }, -}; - -static const u32 ar5416Bank7_9160[][2] = { - { 0x0000989c, 0x00000500 }, - { 0x0000989c, 0x00000800 }, - { 0x000098cc, 0x0000000e }, -}; - -static u32 ar5416Addac_9160[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000018 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000019 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000003 }, - {0x0000989c, 0x00000008 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -static u32 ar5416Addac_91601_1[][2] = { - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000018 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x000000c0 }, - {0x0000989c, 0x00000019 }, - {0x0000989c, 0x00000004 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x0000989c, 0x00000000 }, - {0x000098cc, 0x00000000 }, -}; - -/* XXX 9280 1 */ -static const u32 ar9280Modes_9280[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x0000a000, 0x00014000, 0x00016000, 0x0000b000, 0x00014008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801080, 0x08400840, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009844, 0x1372161e, 0x1372161e, 0x137216a0, 0x137216a0, 0x137216a0 }, - { 0x00009848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, - { 0x0000a848, 0x00028566, 0x00028566, 0x00028563, 0x00028563, 0x00028563 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e, 0x7ec82d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e, 0x3139605e }, - { 0x00009860, 0x00049d18, 0x00049d18, 0x00049d20, 0x00049d20, 0x00049d18 }, - { 0x0000c864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190, 0x5ac64190 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x000007d0, 0x00000898, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a07, 0xd00a8a07, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010, 0xdfbc1010 }, - { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c9b8, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a }, - { 0x0000c9bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c, 0x60f6532c }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00008184, 0x00008184, 0x00000214, 0x00000214, 0x00000214 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000218, 0x00000218, 0x00000218 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000224, 0x00000224, 0x00000224 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000228, 0x00000228, 0x00000228 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000022c, 0x0000022c, 0x0000022c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00000230, 0x00000230, 0x00000230 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x000002a4, 0x000002a4, 0x000002a4 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x000002a8, 0x000002a8, 0x000002a8 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x000002ac, 0x000002ac, 0x000002ac }, - { 0x00009a24, 0x00008210, 0x00008210, 0x000002b0, 0x000002b0, 0x000002b0 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x000002b4, 0x000002b4, 0x000002b4 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x000002b8, 0x000002b8, 0x000002b8 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x00000390, 0x00000390, 0x00000390 }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00000394, 0x00000394, 0x00000394 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00000398, 0x00000398, 0x00000398 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00000334, 0x00000334, 0x00000334 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x00000338, 0x00000338, 0x00000338 }, - { 0x00009a44, 0x00008304, 0x00008304, 0x000003ac, 0x000003ac, 0x000003ac }, - { 0x00009a48, 0x00008308, 0x00008308, 0x000003b0, 0x000003b0, 0x000003b0 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x000003b4, 0x000003b4, 0x000003b4 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x000003b8, 0x000003b8, 0x000003b8 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x000003a5, 0x000003a5, 0x000003a5 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x000003a9, 0x000003a9, 0x000003a9 }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x000003ad, 0x000003ad, 0x000003ad }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a208, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788, 0x803e4788 }, - { 0x0000a20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, - { 0x0000b20c, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019, 0x000c6019 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, - { 0x0000784c, 0x0e4f048c, 0x0e4f048c, 0x0e4d048c, 0x0e4d048c, 0x0e4d048c }, - { 0x00007854, 0x12031828, 0x12031828, 0x12035828, 0x12035828, 0x12035828 }, - { 0x00007870, 0x807ec400, 0x807ec400, 0x807ec000, 0x807ec000, 0x807ec000 }, - { 0x0000788c, 0x00010000, 0x00010000, 0x00110000, 0x00110000, 0x00110000 }, -}; - -static const u32 ar9280Common_9280[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00007010, 0x00000033 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a82301a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x00008300, 0x00000000 }, - { 0x00008304, 0x00000000 }, - { 0x00008308, 0x00000000 }, - { 0x0000830c, 0x00000000 }, - { 0x00008310, 0x00000000 }, - { 0x00008314, 0x00000000 }, - { 0x00008318, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xaf268e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x00009840, 0x206a01ae }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0xe250a51e }, - { 0x00009958, 0x3388ffff }, - { 0x00009940, 0x00781204 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f00c4 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099fc, 0x00001042 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x23277200 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000001 }, - { 0x0000a250, 0x001da000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000a358, 0x7999aa0f }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f38081 }, - { 0x00007800, 0x00040000 }, - { 0x00007804, 0xdb005012 }, - { 0x00007808, 0x04924914 }, - { 0x0000780c, 0x21084210 }, - { 0x00007810, 0x6d801300 }, - { 0x00007814, 0x0019beff }, - { 0x00007818, 0x07e40000 }, - { 0x0000781c, 0x00492000 }, - { 0x00007820, 0x92492480 }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb005012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x6d801300 }, - { 0x00007838, 0x0019beff }, - { 0x0000783c, 0x07e40000 }, - { 0x00007840, 0x00492000 }, - { 0x00007844, 0x92492480 }, - { 0x00007848, 0x00120000 }, - { 0x00007850, 0x54214514 }, - { 0x00007858, 0x92592692 }, - { 0x00007860, 0x52802000 }, - { 0x00007864, 0x0a8e370e }, - { 0x00007868, 0xc0102850 }, - { 0x0000786c, 0x812d4000 }, - { 0x00007874, 0x001b6db0 }, - { 0x00007878, 0x00376b63 }, - { 0x0000787c, 0x06db6db6 }, - { 0x00007880, 0x006d8000 }, - { 0x00007884, 0xffeffffe }, - { 0x00007888, 0xffeffffe }, - { 0x00007890, 0x00060aeb }, - { 0x00007894, 0x5a108000 }, - { 0x00007898, 0x2a850160 }, -}; - -/* XXX 9280 2 */ -static const u32 ar9280Modes_9280_2[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x6c4000e2, 0x6c4000e2, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x31395d5e, 0x31395d5e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00048d18, 0x00048d18, 0x00048d20, 0x00048d20, 0x00048d18 }, - { 0x00009864, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a0b, 0xd00a8a0b, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010, 0xffbc1010 }, - { 0x00009960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000010, 0x00000010, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000210, 0x00000210, 0x00000210, 0x00000210, 0x00000210 }, - { 0x000099b8, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000a00, 0x00000a00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a204, 0x00000444, 0x00000444, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f019, 0x0001f019, 0x0001f019 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x001ff000, 0x001ff000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00007894, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000, 0x5a508000 }, -}; - -static const u32 ar9280Common_9280_2[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x00481043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafa68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x0000c968, 0x000003ce }, - { 0x00009970, 0x190fb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x006f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c88000 }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00007bb6 }, - { 0x0000a248, 0x0fff3ffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9c6 }, - { 0x0000b26c, 0x0ebae9c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00040000 }, - { 0x00007804, 0xdb005012 }, - { 0x00007808, 0x04924914 }, - { 0x0000780c, 0x21084210 }, - { 0x00007810, 0x6d801300 }, - { 0x00007818, 0x07e41000 }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb005012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x6d801300 }, - { 0x0000783c, 0x07e40000 }, - { 0x00007848, 0x00100000 }, - { 0x0000784c, 0x773f0567 }, - { 0x00007850, 0x54214514 }, - { 0x00007854, 0x12035828 }, - { 0x00007858, 0x9259269a }, - { 0x00007860, 0x52802000 }, - { 0x00007864, 0x0a8e370e }, - { 0x00007868, 0xc0102850 }, - { 0x0000786c, 0x812d4000 }, - { 0x00007870, 0x807ec400 }, - { 0x00007874, 0x001b6db0 }, - { 0x00007878, 0x00376b63 }, - { 0x0000787c, 0x06db6db6 }, - { 0x00007880, 0x006d8000 }, - { 0x00007884, 0xffeffffe }, - { 0x00007888, 0xffeffffe }, - { 0x0000788c, 0x00010000 }, - { 0x00007890, 0x02060aeb }, - { 0x00007898, 0x2a850160 }, -}; - -static const u32 ar9280Modes_fast_clock_9280_2[][3] = { - { 0x00001030, 0x00000268, 0x000004d0 }, - { 0x00001070, 0x0000018c, 0x00000318 }, - { 0x000010b0, 0x00000fd0, 0x00001fa0 }, - { 0x00008014, 0x044c044c, 0x08980898 }, - { 0x0000801c, 0x148ec02b, 0x148ec057 }, - { 0x00008318, 0x000044c0, 0x00008980 }, - { 0x00009820, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000f0f, 0x00000f0f }, - { 0x00009828, 0x0b020001, 0x0b020001 }, - { 0x00009834, 0x00000f0f, 0x00000f0f }, - { 0x00009844, 0x03721821, 0x03721821 }, - { 0x00009914, 0x00000898, 0x00001130 }, - { 0x00009918, 0x0000000b, 0x00000016 }, -}; - -static const u32 ar9280Modes_backoff_23db_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b10, 0x00008b10, 0x00008b10 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b14, 0x00008b14, 0x00008b14 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b01, 0x00008b01, 0x00008b01 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b05, 0x00008b05, 0x00008b05 }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b09, 0x00008b09, 0x00008b09 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008b0d, 0x00008b0d, 0x00008b0d }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008b11, 0x00008b11, 0x00008b11 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008b15, 0x00008b15, 0x00008b15 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008b02, 0x00008b02, 0x00008b02 }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008b06, 0x00008b06, 0x00008b06 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00008b0a, 0x00008b0a, 0x00008b0a }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00008b0e, 0x00008b0e, 0x00008b0e }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00008b12, 0x00008b12, 0x00008b12 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00008b16, 0x00008b16, 0x00008b16 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00008b03, 0x00008b03, 0x00008b03 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00008b07, 0x00008b07, 0x00008b07 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00008b0b, 0x00008b0b, 0x00008b0b }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00008b0f, 0x00008b0f, 0x00008b0f }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00008b13, 0x00008b13, 0x00008b13 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00008b17, 0x00008b17, 0x00008b17 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00008b23, 0x00008b23, 0x00008b23 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00008b27, 0x00008b27, 0x00008b27 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00008b2b, 0x00008b2b, 0x00008b2b }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00008b2f, 0x00008b2f, 0x00008b2f }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00008b33, 0x00008b33, 0x00008b33 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00008b37, 0x00008b37, 0x00008b37 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x00008b43, 0x00008b43, 0x00008b43 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x00008b47, 0x00008b47, 0x00008b47 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00008b4b, 0x00008b4b, 0x00008b4b }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00008b4f, 0x00008b4f, 0x00008b4f }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00008b53, 0x00008b53, 0x00008b53 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00008b57, 0x00008b57, 0x00008b57 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x00008b5b, 0x00008b5b, 0x00008b5b }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001050, 0x00001050, 0x00001050 }, -}; - -static const u32 ar9280Modes_original_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x0000930c, 0x0000930c, 0x0000930c }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009384, 0x00009384, 0x00009384 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009388, 0x00009388, 0x00009388 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x00009704, 0x00009704, 0x00009704 }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x000096a4, 0x000096a4, 0x000096a4 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x000096a8, 0x000096a8, 0x000096a8 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009710, 0x00009710, 0x00009710 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009714, 0x00009714, 0x00009714 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009720, 0x00009720, 0x00009720 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x00009724, 0x00009724, 0x00009724 }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009728, 0x00009728, 0x00009728 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x0000972c, 0x0000972c, 0x0000972c }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x000097a0, 0x000097a0, 0x000097a0 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x000097a4, 0x000097a4, 0x000097a4 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x000097a8, 0x000097a8, 0x000097a8 }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x000097b0, 0x000097b0, 0x000097b0 }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x000097b4, 0x000097b4, 0x000097b4 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x000097b8, 0x000097b8, 0x000097b8 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x000097a5, 0x000097a5, 0x000097a5 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x000097a9, 0x000097a9, 0x000097a9 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x000097ad, 0x000097ad, 0x000097ad }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x000097b1, 0x000097b1, 0x000097b1 }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x000097b5, 0x000097b5, 0x000097b5 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x000097b9, 0x000097b9, 0x000097b9 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x000097c5, 0x000097c5, 0x000097c5 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x000097c9, 0x000097c9, 0x000097c9 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x000097d1, 0x000097d1, 0x000097d1 }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x000097d5, 0x000097d5, 0x000097d5 }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x000097d9, 0x000097d9, 0x000097d9 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x000097c6, 0x000097c6, 0x000097c6 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x000097ca, 0x000097ca, 0x000097ca }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x000097ce, 0x000097ce, 0x000097ce }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x000097d2, 0x000097d2, 0x000097d2 }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x000097d6, 0x000097d6, 0x000097d6 }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x000097c3, 0x000097c3, 0x000097c3 }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x000097c7, 0x000097c7, 0x000097c7 }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x000097cb, 0x000097cb, 0x000097cb }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x000097cf, 0x000097cf, 0x000097cf }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x000097d7, 0x000097d7, 0x000097d7 }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x000097db, 0x000097db, 0x000097db }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001063, 0x00001063, 0x00001063 }, -}; - -static const u32 ar9280Modes_backoff_13db_rxgain_9280_2[][6] = { - { 0x00009a00, 0x00008184, 0x00008184, 0x00000290, 0x00000290, 0x00000290 }, - { 0x00009a04, 0x00008188, 0x00008188, 0x00000300, 0x00000300, 0x00000300 }, - { 0x00009a08, 0x0000818c, 0x0000818c, 0x00000304, 0x00000304, 0x00000304 }, - { 0x00009a0c, 0x00008190, 0x00008190, 0x00000308, 0x00000308, 0x00000308 }, - { 0x00009a10, 0x00008194, 0x00008194, 0x0000030c, 0x0000030c, 0x0000030c }, - { 0x00009a14, 0x00008200, 0x00008200, 0x00008000, 0x00008000, 0x00008000 }, - { 0x00009a18, 0x00008204, 0x00008204, 0x00008004, 0x00008004, 0x00008004 }, - { 0x00009a1c, 0x00008208, 0x00008208, 0x00008008, 0x00008008, 0x00008008 }, - { 0x00009a20, 0x0000820c, 0x0000820c, 0x0000800c, 0x0000800c, 0x0000800c }, - { 0x00009a24, 0x00008210, 0x00008210, 0x00008080, 0x00008080, 0x00008080 }, - { 0x00009a28, 0x00008214, 0x00008214, 0x00008084, 0x00008084, 0x00008084 }, - { 0x00009a2c, 0x00008280, 0x00008280, 0x00008088, 0x00008088, 0x00008088 }, - { 0x00009a30, 0x00008284, 0x00008284, 0x0000808c, 0x0000808c, 0x0000808c }, - { 0x00009a34, 0x00008288, 0x00008288, 0x00008100, 0x00008100, 0x00008100 }, - { 0x00009a38, 0x0000828c, 0x0000828c, 0x00008104, 0x00008104, 0x00008104 }, - { 0x00009a3c, 0x00008290, 0x00008290, 0x00008108, 0x00008108, 0x00008108 }, - { 0x00009a40, 0x00008300, 0x00008300, 0x0000810c, 0x0000810c, 0x0000810c }, - { 0x00009a44, 0x00008304, 0x00008304, 0x00008110, 0x00008110, 0x00008110 }, - { 0x00009a48, 0x00008308, 0x00008308, 0x00008114, 0x00008114, 0x00008114 }, - { 0x00009a4c, 0x0000830c, 0x0000830c, 0x00008180, 0x00008180, 0x00008180 }, - { 0x00009a50, 0x00008310, 0x00008310, 0x00008184, 0x00008184, 0x00008184 }, - { 0x00009a54, 0x00008314, 0x00008314, 0x00008188, 0x00008188, 0x00008188 }, - { 0x00009a58, 0x00008380, 0x00008380, 0x0000818c, 0x0000818c, 0x0000818c }, - { 0x00009a5c, 0x00008384, 0x00008384, 0x00008190, 0x00008190, 0x00008190 }, - { 0x00009a60, 0x00008388, 0x00008388, 0x00008194, 0x00008194, 0x00008194 }, - { 0x00009a64, 0x0000838c, 0x0000838c, 0x000081a0, 0x000081a0, 0x000081a0 }, - { 0x00009a68, 0x00008390, 0x00008390, 0x0000820c, 0x0000820c, 0x0000820c }, - { 0x00009a6c, 0x00008394, 0x00008394, 0x000081a8, 0x000081a8, 0x000081a8 }, - { 0x00009a70, 0x0000a380, 0x0000a380, 0x00008284, 0x00008284, 0x00008284 }, - { 0x00009a74, 0x0000a384, 0x0000a384, 0x00008288, 0x00008288, 0x00008288 }, - { 0x00009a78, 0x0000a388, 0x0000a388, 0x00008224, 0x00008224, 0x00008224 }, - { 0x00009a7c, 0x0000a38c, 0x0000a38c, 0x00008290, 0x00008290, 0x00008290 }, - { 0x00009a80, 0x0000a390, 0x0000a390, 0x00008300, 0x00008300, 0x00008300 }, - { 0x00009a84, 0x0000a394, 0x0000a394, 0x00008304, 0x00008304, 0x00008304 }, - { 0x00009a88, 0x0000a780, 0x0000a780, 0x00008308, 0x00008308, 0x00008308 }, - { 0x00009a8c, 0x0000a784, 0x0000a784, 0x0000830c, 0x0000830c, 0x0000830c }, - { 0x00009a90, 0x0000a788, 0x0000a788, 0x00008380, 0x00008380, 0x00008380 }, - { 0x00009a94, 0x0000a78c, 0x0000a78c, 0x00008384, 0x00008384, 0x00008384 }, - { 0x00009a98, 0x0000a790, 0x0000a790, 0x00008700, 0x00008700, 0x00008700 }, - { 0x00009a9c, 0x0000a794, 0x0000a794, 0x00008704, 0x00008704, 0x00008704 }, - { 0x00009aa0, 0x0000ab84, 0x0000ab84, 0x00008708, 0x00008708, 0x00008708 }, - { 0x00009aa4, 0x0000ab88, 0x0000ab88, 0x0000870c, 0x0000870c, 0x0000870c }, - { 0x00009aa8, 0x0000ab8c, 0x0000ab8c, 0x00008780, 0x00008780, 0x00008780 }, - { 0x00009aac, 0x0000ab90, 0x0000ab90, 0x00008784, 0x00008784, 0x00008784 }, - { 0x00009ab0, 0x0000ab94, 0x0000ab94, 0x00008b00, 0x00008b00, 0x00008b00 }, - { 0x00009ab4, 0x0000af80, 0x0000af80, 0x00008b04, 0x00008b04, 0x00008b04 }, - { 0x00009ab8, 0x0000af84, 0x0000af84, 0x00008b08, 0x00008b08, 0x00008b08 }, - { 0x00009abc, 0x0000af88, 0x0000af88, 0x00008b0c, 0x00008b0c, 0x00008b0c }, - { 0x00009ac0, 0x0000af8c, 0x0000af8c, 0x00008b80, 0x00008b80, 0x00008b80 }, - { 0x00009ac4, 0x0000af90, 0x0000af90, 0x00008b84, 0x00008b84, 0x00008b84 }, - { 0x00009ac8, 0x0000af94, 0x0000af94, 0x00008b88, 0x00008b88, 0x00008b88 }, - { 0x00009acc, 0x0000b380, 0x0000b380, 0x00008b8c, 0x00008b8c, 0x00008b8c }, - { 0x00009ad0, 0x0000b384, 0x0000b384, 0x00008b90, 0x00008b90, 0x00008b90 }, - { 0x00009ad4, 0x0000b388, 0x0000b388, 0x00008f80, 0x00008f80, 0x00008f80 }, - { 0x00009ad8, 0x0000b38c, 0x0000b38c, 0x00008f84, 0x00008f84, 0x00008f84 }, - { 0x00009adc, 0x0000b390, 0x0000b390, 0x00008f88, 0x00008f88, 0x00008f88 }, - { 0x00009ae0, 0x0000b394, 0x0000b394, 0x00008f8c, 0x00008f8c, 0x00008f8c }, - { 0x00009ae4, 0x0000b398, 0x0000b398, 0x00008f90, 0x00008f90, 0x00008f90 }, - { 0x00009ae8, 0x0000b780, 0x0000b780, 0x00009310, 0x00009310, 0x00009310 }, - { 0x00009aec, 0x0000b784, 0x0000b784, 0x00009314, 0x00009314, 0x00009314 }, - { 0x00009af0, 0x0000b788, 0x0000b788, 0x00009320, 0x00009320, 0x00009320 }, - { 0x00009af4, 0x0000b78c, 0x0000b78c, 0x00009324, 0x00009324, 0x00009324 }, - { 0x00009af8, 0x0000b790, 0x0000b790, 0x00009328, 0x00009328, 0x00009328 }, - { 0x00009afc, 0x0000b794, 0x0000b794, 0x0000932c, 0x0000932c, 0x0000932c }, - { 0x00009b00, 0x0000b798, 0x0000b798, 0x00009330, 0x00009330, 0x00009330 }, - { 0x00009b04, 0x0000d784, 0x0000d784, 0x00009334, 0x00009334, 0x00009334 }, - { 0x00009b08, 0x0000d788, 0x0000d788, 0x00009321, 0x00009321, 0x00009321 }, - { 0x00009b0c, 0x0000d78c, 0x0000d78c, 0x00009325, 0x00009325, 0x00009325 }, - { 0x00009b10, 0x0000d790, 0x0000d790, 0x00009329, 0x00009329, 0x00009329 }, - { 0x00009b14, 0x0000f780, 0x0000f780, 0x0000932d, 0x0000932d, 0x0000932d }, - { 0x00009b18, 0x0000f784, 0x0000f784, 0x00009331, 0x00009331, 0x00009331 }, - { 0x00009b1c, 0x0000f788, 0x0000f788, 0x00009335, 0x00009335, 0x00009335 }, - { 0x00009b20, 0x0000f78c, 0x0000f78c, 0x00009322, 0x00009322, 0x00009322 }, - { 0x00009b24, 0x0000f790, 0x0000f790, 0x00009326, 0x00009326, 0x00009326 }, - { 0x00009b28, 0x0000f794, 0x0000f794, 0x0000932a, 0x0000932a, 0x0000932a }, - { 0x00009b2c, 0x0000f7a4, 0x0000f7a4, 0x0000932e, 0x0000932e, 0x0000932e }, - { 0x00009b30, 0x0000f7a8, 0x0000f7a8, 0x00009332, 0x00009332, 0x00009332 }, - { 0x00009b34, 0x0000f7ac, 0x0000f7ac, 0x00009336, 0x00009336, 0x00009336 }, - { 0x00009b38, 0x0000f7b0, 0x0000f7b0, 0x00009323, 0x00009323, 0x00009323 }, - { 0x00009b3c, 0x0000f7b4, 0x0000f7b4, 0x00009327, 0x00009327, 0x00009327 }, - { 0x00009b40, 0x0000f7a1, 0x0000f7a1, 0x0000932b, 0x0000932b, 0x0000932b }, - { 0x00009b44, 0x0000f7a5, 0x0000f7a5, 0x0000932f, 0x0000932f, 0x0000932f }, - { 0x00009b48, 0x0000f7a9, 0x0000f7a9, 0x00009333, 0x00009333, 0x00009333 }, - { 0x00009b4c, 0x0000f7ad, 0x0000f7ad, 0x00009337, 0x00009337, 0x00009337 }, - { 0x00009b50, 0x0000f7b1, 0x0000f7b1, 0x00009343, 0x00009343, 0x00009343 }, - { 0x00009b54, 0x0000f7b5, 0x0000f7b5, 0x00009347, 0x00009347, 0x00009347 }, - { 0x00009b58, 0x0000f7c5, 0x0000f7c5, 0x0000934b, 0x0000934b, 0x0000934b }, - { 0x00009b5c, 0x0000f7c9, 0x0000f7c9, 0x0000934f, 0x0000934f, 0x0000934f }, - { 0x00009b60, 0x0000f7cd, 0x0000f7cd, 0x00009353, 0x00009353, 0x00009353 }, - { 0x00009b64, 0x0000f7d1, 0x0000f7d1, 0x00009357, 0x00009357, 0x00009357 }, - { 0x00009b68, 0x0000f7d5, 0x0000f7d5, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b6c, 0x0000f7c2, 0x0000f7c2, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b70, 0x0000f7c6, 0x0000f7c6, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b74, 0x0000f7ca, 0x0000f7ca, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b78, 0x0000f7ce, 0x0000f7ce, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b7c, 0x0000f7d2, 0x0000f7d2, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b80, 0x0000f7d6, 0x0000f7d6, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b84, 0x0000f7c3, 0x0000f7c3, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b88, 0x0000f7c7, 0x0000f7c7, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b8c, 0x0000f7cb, 0x0000f7cb, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b90, 0x0000f7d3, 0x0000f7d3, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b94, 0x0000f7d7, 0x0000f7d7, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b98, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009b9c, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009ba8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bac, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bb8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bbc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bc8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bcc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bd8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bdc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009be8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bec, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf0, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf4, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bf8, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009bfc, 0x0000f7db, 0x0000f7db, 0x0000935b, 0x0000935b, 0x0000935b }, - { 0x00009848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, - { 0x0000a848, 0x00001066, 0x00001066, 0x0000105a, 0x0000105a, 0x0000105a }, -}; - -static const u32 ar9280Modes_high_power_tx_gain_9280_2[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00007008, 0x00007008, 0x00007008 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000c010, 0x0000c010, 0x0000c010 }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x00010012, 0x00010012, 0x00010012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00013014, 0x00013014, 0x00013014 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001820a, 0x0001820a, 0x0001820a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001b211, 0x0001b211, 0x0001b211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00021092, 0x00021092, 0x00022411, 0x00022411, 0x00022411 }, - { 0x0000a328, 0x0002510a, 0x0002510a, 0x00025413, 0x00025413, 0x00025413 }, - { 0x0000a32c, 0x0002910c, 0x0002910c, 0x00029811, 0x00029811, 0x00029811 }, - { 0x0000a330, 0x0002c18b, 0x0002c18b, 0x0002c813, 0x0002c813, 0x0002c813 }, - { 0x0000a334, 0x0002f1cc, 0x0002f1cc, 0x00030a14, 0x00030a14, 0x00030a14 }, - { 0x0000a338, 0x000321eb, 0x000321eb, 0x00035a50, 0x00035a50, 0x00035a50 }, - { 0x0000a33c, 0x000341ec, 0x000341ec, 0x00039c4c, 0x00039c4c, 0x00039c4c }, - { 0x0000a340, 0x000341ec, 0x000341ec, 0x0003de8a, 0x0003de8a, 0x0003de8a }, - { 0x0000a344, 0x000341ec, 0x000341ec, 0x00042e92, 0x00042e92, 0x00042e92 }, - { 0x0000a348, 0x000341ec, 0x000341ec, 0x00046ed2, 0x00046ed2, 0x00046ed2 }, - { 0x0000a34c, 0x000341ec, 0x000341ec, 0x0004bed5, 0x0004bed5, 0x0004bed5 }, - { 0x0000a350, 0x000341ec, 0x000341ec, 0x0004ff54, 0x0004ff54, 0x0004ff54 }, - { 0x0000a354, 0x000341ec, 0x000341ec, 0x00055fd5, 0x00055fd5, 0x00055fd5 }, - { 0x00007814, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x00007838, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff, 0x00198eff }, - { 0x0000781c, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, - { 0x00007840, 0x00172000, 0x00172000, 0x00172000, 0x00172000, 0x00172000 }, - { 0x00007820, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, - { 0x00007844, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480, 0xf258a480 }, - { 0x0000a274, 0x0a19e652, 0x0a19e652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a27c, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce, 0x050739ce }, -}; - -static const u32 ar9280Modes_original_tx_gain_9280_2[][6] = { - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00003002, 0x00003002, 0x00003002, 0x00003002, 0x00003002 }, - { 0x0000a308, 0x00006004, 0x00006004, 0x00008009, 0x00008009, 0x00008009 }, - { 0x0000a30c, 0x0000a006, 0x0000a006, 0x0000b00b, 0x0000b00b, 0x0000b00b }, - { 0x0000a310, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012, 0x0000e012 }, - { 0x0000a314, 0x00011014, 0x00011014, 0x00012048, 0x00012048, 0x00012048 }, - { 0x0000a318, 0x0001504a, 0x0001504a, 0x0001604a, 0x0001604a, 0x0001604a }, - { 0x0000a31c, 0x0001904c, 0x0001904c, 0x0001a211, 0x0001a211, 0x0001a211 }, - { 0x0000a320, 0x0001c04e, 0x0001c04e, 0x0001e213, 0x0001e213, 0x0001e213 }, - { 0x0000a324, 0x00020092, 0x00020092, 0x0002121b, 0x0002121b, 0x0002121b }, - { 0x0000a328, 0x0002410a, 0x0002410a, 0x00024412, 0x00024412, 0x00024412 }, - { 0x0000a32c, 0x0002710c, 0x0002710c, 0x00028414, 0x00028414, 0x00028414 }, - { 0x0000a330, 0x0002b18b, 0x0002b18b, 0x0002b44a, 0x0002b44a, 0x0002b44a }, - { 0x0000a334, 0x0002e1cc, 0x0002e1cc, 0x00030649, 0x00030649, 0x00030649 }, - { 0x0000a338, 0x000321ec, 0x000321ec, 0x0003364b, 0x0003364b, 0x0003364b }, - { 0x0000a33c, 0x000321ec, 0x000321ec, 0x00038a49, 0x00038a49, 0x00038a49 }, - { 0x0000a340, 0x000321ec, 0x000321ec, 0x0003be48, 0x0003be48, 0x0003be48 }, - { 0x0000a344, 0x000321ec, 0x000321ec, 0x0003ee4a, 0x0003ee4a, 0x0003ee4a }, - { 0x0000a348, 0x000321ec, 0x000321ec, 0x00042e88, 0x00042e88, 0x00042e88 }, - { 0x0000a34c, 0x000321ec, 0x000321ec, 0x00046e8a, 0x00046e8a, 0x00046e8a }, - { 0x0000a350, 0x000321ec, 0x000321ec, 0x00049ec9, 0x00049ec9, 0x00049ec9 }, - { 0x0000a354, 0x000321ec, 0x000321ec, 0x0004bf42, 0x0004bf42, 0x0004bf42 }, - { 0x00007814, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x00007838, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff, 0x0019beff }, - { 0x0000781c, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, - { 0x00007840, 0x00392000, 0x00392000, 0x00392000, 0x00392000, 0x00392000 }, - { 0x00007820, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, - { 0x00007844, 0x92592480, 0x92592480, 0x92592480, 0x92592480, 0x92592480 }, - { 0x0000a274, 0x0a19c652, 0x0a19c652, 0x0a1aa652, 0x0a1aa652, 0x0a1aa652 }, - { 0x0000a27c, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce, 0x050701ce }, -}; - -static const u32 ar9280PciePhy_clkreq_off_L1_9280[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u32 ar9280PciePhy_clkreq_always_on_L1_9280[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9285 Revsion 10*/ -static const u_int32_t ar9285Modes_9285[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03720020, 0x03720020, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x0000004e, 0x0000004e, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3136605e, 0x3136605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xdfbc1010, 0xdfbc1010, 0xdfbc1020, 0xdfbc1020, 0xdfbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c, 0x00cf4d1c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329, 0x60f65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00068114, 0x00068114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00068284, 0x00068284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00068288, 0x00068288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00068220, 0x00068220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00068304, 0x00068304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00068380, 0x00068380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00068384, 0x00068384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00068b04, 0x00068b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00068b08, 0x00068b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00068b0c, 0x00068b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00068b80, 0x00068b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00068b84, 0x00068b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00068b88, 0x00068b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00068b8c, 0x00068b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x000b8b90, 0x000b8b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000b8f80, 0x000b8f80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000b8f8c, 0x000b8f8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000b8f90, 0x000b8f90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000bb30c, 0x000bb30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000bb310, 0x000bb310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000bb324, 0x000bb324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000bb704, 0x000bb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000f96a4, 0x000f96a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000f96a8, 0x000f96a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000f9720, 0x000f9720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000f9724, 0x000f9724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000f9728, 0x000f9728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000f972c, 0x000f972c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000f97a0, 0x000f97a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000f97a4, 0x000f97a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000fb7b4, 0x000fb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000fb7ad, 0x000fb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000fb7b9, 0x000fb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000fb7c5, 0x000fb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000fb7d5, 0x000fb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000fb7c7, 0x000fb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000fb7cf, 0x000fb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000fb7d7, 0x000fb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000fb7db, 0x000fb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0006801c, 0x0006801c, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00068080, 0x00068080, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x00068084, 0x00068084, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00068088, 0x00068088, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0006808c, 0x0006808c, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00068100, 0x00068100, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x00068104, 0x00068104, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00068108, 0x00068108, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0006810c, 0x0006810c, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00068110, 0x00068110, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00068180, 0x00068180, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x00068184, 0x00068184, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00068188, 0x00068188, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0006818c, 0x0006818c, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x00068190, 0x00068190, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x00068194, 0x00068194, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000681a0, 0x000681a0, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0006820c, 0x0006820c, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x000681a8, 0x000681a8, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x000681ac, 0x000681ac, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0006821c, 0x0006821c, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00068224, 0x00068224, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00068290, 0x00068290, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00068300, 0x00068300, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x00068308, 0x00068308, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0006830c, 0x0006830c, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00068310, 0x00068310, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068788, 0x00068788, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0006878c, 0x0006878c, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068790, 0x00068790, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x00068794, 0x00068794, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068798, 0x00068798, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0006879c, 0x0006879c, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00068b89, 0x00068b89, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00068b8d, 0x00068b8d, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00068b91, 0x00068b91, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00068b95, 0x00068b95, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00068b99, 0x00068b99, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00068ba5, 0x00068ba5, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00068ba9, 0x00068ba9, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00068bad, 0x00068bad, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x000b8b0c, 0x000b8b0c, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000b8f10, 0x000b8f10, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000b8f14, 0x000b8f14, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000b8f84, 0x000b8f84, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000b8f88, 0x000b8f88, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000bb380, 0x000bb380, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000bb384, 0x000bb384, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000bb388, 0x000bb388, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000bb38c, 0x000bb38c, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000bb394, 0x000bb394, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000bb798, 0x000bb798, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000f970c, 0x000f970c, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000f9710, 0x000f9710, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000f9714, 0x000f9714, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000f9718, 0x000f9718, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000f9705, 0x000f9705, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000f9709, 0x000f9709, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000f970d, 0x000f970d, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000f9711, 0x000f9711, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000f9715, 0x000f9715, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000f9719, 0x000f9719, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000fb7a4, 0x000fb7a4, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000fb7a8, 0x000fb7a8, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000fb7ac, 0x000fb7ac, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000fb7b0, 0x000fb7b0, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000fb7b8, 0x000fb7b8, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000fb7bc, 0x000fb7bc, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000fb7a1, 0x000fb7a1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000fb7a5, 0x000fb7a5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000fb7a9, 0x000fb7a9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000fb7b1, 0x000fb7b1, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000fb7b5, 0x000fb7b5, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000fb7bd, 0x000fb7bd, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000fb7c9, 0x000fb7c9, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000fb7cd, 0x000fb7cd, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000fb7d1, 0x000fb7d1, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000fb7d9, 0x000fb7d9, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000fb7c2, 0x000fb7c2, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000fb7c6, 0x000fb7c6, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000fb7ca, 0x000fb7ca, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000fb7ce, 0x000fb7ce, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000fb7d2, 0x000fb7d2, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000fb7d6, 0x000fb7d6, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000fb7c3, 0x000fb7c3, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000fb7cb, 0x000fb7cb, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000fb7d3, 0x000fb7d3, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x00000000, 0x00000000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x001ff000, 0x001ff000, 0x001ca000, 0x001ca000, 0x001da000 }, - { 0x0000a274, 0x0a81c652, 0x0a81c652, 0x0a820652, 0x0a820652, 0x0a82a652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00007201, 0x00007201, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010408, 0x00010408, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0001860a, 0x0001860a, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00020818, 0x00020818, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x00024858, 0x00024858, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00026859, 0x00026859, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0002985b, 0x0002985b, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002c89a, 0x0002c89a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002e89b, 0x0002e89b, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0003089c, 0x0003089c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0003289d, 0x0003289d, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0003489e, 0x0003489e, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000388de, 0x000388de, 0x00000000 }, - { 0x0000a338, 0x00000000, 0x00000000, 0x0003b91e, 0x0003b91e, 0x00000000 }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003d95e, 0x0003d95e, 0x00000000 }, - { 0x0000a340, 0x00000000, 0x00000000, 0x000419df, 0x000419df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9285Common_9285[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000031 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04800 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0x00000000 }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x00003210 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00000000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00481043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x1927b515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0a00 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e6788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000a278, 0x39ce739c }, - { 0x0000a27c, 0x050e039c }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x39ce739c }, - { 0x0000a398, 0x0000039c }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025820 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, - { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96c }, - { 0x00007834, 0x71400086 }, - { 0x00007838, 0xfac68800 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x0000786c, 0x48609eb4 }, - { 0x00007870, 0x10142c00 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9285 v1_2 PCI Register Writes. Created: 04/13/09 */ -static const u_int32_t ar9285Modes_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f, 0x6af6532f }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9285Common_9285_1_2[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000031 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04810 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x0000320a }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00481043 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x01002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x2108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0400 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a208, 0x803e68c8 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025830 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007824, 0x00d86fff }, - { 0x00007828, 0x26d2491b }, - { 0x0000782c, 0x6e36d97b }, - { 0x00007830, 0xedb6d96e }, - { 0x00007834, 0x71400087 }, - { 0x0000783c, 0x0001fffe }, - { 0x00007840, 0xffeb1a20 }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x00007870, 0x10142c00 }, -}; - -static const u_int32_t ar9285Modes_high_power_tx_gain_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00006200, 0x00006200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008201, 0x00008201, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000b240, 0x0000b240, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0000d241, 0x0000d241, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0000f600, 0x0000f600, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00012800, 0x00012800, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00016802, 0x00016802, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0001b805, 0x0001b805, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x00021a80, 0x00021a80, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028b00, 0x00028b00, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002ab40, 0x0002ab40, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0002cd80, 0x0002cd80, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00033d82, 0x00033d82, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007838, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803, 0xfac68803 }, - { 0x0000786c, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe, 0x08609ebe }, - { 0x00007820, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x0000a274, 0x0a22a652, 0x0a22a652, 0x0a216652, 0x0a216652, 0x0a22a652 }, - { 0x0000a278, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a27c, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7, 0x050380e7 }, - { 0x0000a394, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a398, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, - { 0x0000a3dc, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7, 0x0e739ce7 }, - { 0x0000a3e0, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7, 0x000000e7 }, -}; - -static const u_int32_t ar9285Modes_original_tx_gain_9285_1_2[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x00022618, 0x00022618, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002a6c9, 0x0002a6c9, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00031710, 0x00031710, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x00035718, 0x00035718, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x00038758, 0x00038758, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0003c75a, 0x0003c75a, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004075c, 0x0004075c, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004475e, 0x0004475e, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004679f, 0x0004679f, 0x00000000 }, - { 0x0000a334, 0x00000000, 0x00000000, 0x000487df, 0x000487df, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a348, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a34c, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a350, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a354, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x00007838, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801, 0xfac68801 }, - { 0x0000786c, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4, 0x48609eb4 }, - { 0x00007820, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04, 0x00000c04 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a21a652, 0x0a21a652, 0x0a22a652 }, - { 0x0000a278, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a27c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c, 0x050e039c }, - { 0x0000a394, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a398, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, - { 0x0000a3dc, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c, 0x39ce739c }, - { 0x0000a3e0, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c, 0x0000039c }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_always_on_L1_9285_1_2[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9285PciePhy_clkreq_off_L1_9285_1_2[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9287 Revision 10 */ -static const u_int32_t ar9287Modes_9287_1_0[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x00000000, 0x00000000, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u_int32_t ar9287Common_9287_1_0[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007020, 0x00000000 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x18487320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d4, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x000000ff }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x01c81043 }, - { 0x00008360, 0xffffffff }, - { 0x00008364, 0xffffffff }, - { 0x00008368, 0x00000000 }, - { 0x00008370, 0x00000000 }, - { 0x00008374, 0x000000ff }, - { 0x00008378, 0x00000000 }, - { 0x0000837c, 0x00000000 }, - { 0x00008380, 0xffffffff }, - { 0x00008384, 0xffffffff }, - { 0x00008390, 0x0fffffff }, - { 0x00008394, 0x0fffffff }, - { 0x00008398, 0x00000000 }, - { 0x0000839c, 0x00000000 }, - { 0x000083a0, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x10002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009930, 0x00000000 }, - { 0x0000a930, 0x00000000 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x0108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x990bb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x0c6f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099c4, 0x06336f77 }, - { 0x000099c8, 0x6af65329 }, - { 0x000099cc, 0x08f186c8 }, - { 0x000099d0, 0x00046384 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a1f4, 0x00fffeff }, - { 0x0000a1f8, 0x00f5f9ff }, - { 0x0000a1fc, 0xb79f6427 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a264, 0x00418a11 }, - { 0x0000b264, 0x00418a11 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0e79e5c6 }, - { 0x0000b26c, 0x0e79e5c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000b398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x0000a3f0, 0x01036a1e }, - { 0x0000a3f4, 0x00000000 }, - { 0x0000b3f4, 0x00000000 }, - { 0x0000a7d8, 0x00000001 }, - { 0x00007800, 0x00000800 }, - { 0x00007804, 0x6c35ffb0 }, - { 0x00007808, 0x6db6c000 }, - { 0x0000780c, 0x6db6cb30 }, - { 0x00007810, 0x6db6cb6c }, - { 0x00007814, 0x0501e200 }, - { 0x00007818, 0x0094128d }, - { 0x0000781c, 0x976ee392 }, - { 0x00007820, 0xf75ff6fc }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb003012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x00140000 }, - { 0x00007838, 0x0e4548d8 }, - { 0x0000783c, 0x54214514 }, - { 0x00007840, 0x02025820 }, - { 0x00007844, 0x71c0d388 }, - { 0x00007848, 0x934934a8 }, - { 0x00007850, 0x00000000 }, - { 0x00007854, 0x00000800 }, - { 0x00007858, 0x6c35ffb0 }, - { 0x0000785c, 0x6db6c000 }, - { 0x00007860, 0x6db6cb2c }, - { 0x00007864, 0x6db6cb6c }, - { 0x00007868, 0x0501e200 }, - { 0x0000786c, 0x0094128d }, - { 0x00007870, 0x976ee392 }, - { 0x00007874, 0xf75ff6fc }, - { 0x00007878, 0x00040000 }, - { 0x0000787c, 0xdb003012 }, - { 0x00007880, 0x04924914 }, - { 0x00007884, 0x21084210 }, - { 0x00007888, 0x001b6db0 }, - { 0x0000788c, 0x00376b63 }, - { 0x00007890, 0x06db6db6 }, - { 0x00007894, 0x006d8000 }, - { 0x00007898, 0x48100000 }, - { 0x0000789c, 0x00000000 }, - { 0x000078a0, 0x08000000 }, - { 0x000078a4, 0x0007ffd8 }, - { 0x000078a8, 0x0007ffd8 }, - { 0x000078ac, 0x001c0020 }, - { 0x000078b0, 0x000611eb }, - { 0x000078b4, 0x40008080 }, - { 0x000078b8, 0x2a850160 }, -}; - -static const u_int32_t ar9287Modes_tx_gain_9287_1_0[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b }, - { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a }, - { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc }, - { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 }, - { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc }, - { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede }, - { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e }, - { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e }, - { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e }, - { 0x0000a780, 0x00000000, 0x00000000, 0x00000060, 0x00000060, 0x00000060 }, - { 0x0000a784, 0x00000000, 0x00000000, 0x00004062, 0x00004062, 0x00004062 }, - { 0x0000a788, 0x00000000, 0x00000000, 0x00008064, 0x00008064, 0x00008064 }, - { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0a4, 0x0000c0a4, 0x0000c0a4 }, - { 0x0000a790, 0x00000000, 0x00000000, 0x000100b0, 0x000100b0, 0x000100b0 }, - { 0x0000a794, 0x00000000, 0x00000000, 0x000140b2, 0x000140b2, 0x000140b2 }, - { 0x0000a798, 0x00000000, 0x00000000, 0x000180b4, 0x000180b4, 0x000180b4 }, - { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c0f4, 0x0001c0f4, 0x0001c0f4 }, - { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020134, 0x00020134, 0x00020134 }, - { 0x0000a7a4, 0x00000000, 0x00000000, 0x000240fe, 0x000240fe, 0x000240fe }, - { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002813e, 0x0002813e, 0x0002813e }, - { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c17e, 0x0002c17e, 0x0002c17e }, - { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301be, 0x000301be, 0x000301be }, - { 0x0000a7b4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7b8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7bc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7c0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7c4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7c8, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7cc, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7d0, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a7d4, 0x00000000, 0x00000000, 0x000341fe, 0x000341fe, 0x000341fe }, - { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, -}; - - -static const u_int32_t ar9287Modes_rx_gain_9287_1_0[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, - { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_0[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_0[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -/* AR9287 Revision 11 */ - -static const u_int32_t ar9287Modes_9287_1_1[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00001030, 0x00000000, 0x00000000, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000000, 0x00000000, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000000, 0x00000000, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x00000000, 0x00000000, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x00000000, 0x00000000, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810, 0x08f04810 }, - { 0x000081d0, 0x00003200, 0x00003200, 0x0000320a, 0x0000320a, 0x0000320a }, - { 0x00008318, 0x00000000, 0x00000000, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000000, 0x00000000, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x00000000, 0x00000000, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000000, 0x00000000, 0x01000e0e, 0x01000e0e, 0x01000e0e }, - { 0x00009828, 0x00000000, 0x00000000, 0x3a020001, 0x3a020001, 0x3a020001 }, - { 0x00009834, 0x00000000, 0x00000000, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000003, 0x00000003, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a002e, 0x206a002e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x03720000, 0x03720000, 0x037216a0, 0x037216a0, 0x037216a0 }, - { 0x00009850, 0x60000000, 0x60000000, 0x6d4000e2, 0x6c4000e2, 0x6c4000e2 }, - { 0x00009858, 0x7c000d00, 0x7c000d00, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3100005e, 0x3100005e, 0x3139605e, 0x31395d5e, 0x31395d5e }, - { 0x00009860, 0x00058d00, 0x00058d00, 0x00058d20, 0x00058d20, 0x00058d18 }, - { 0x00009864, 0x00000e00, 0x00000e00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x000040c0, 0x000040c0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x00000080, 0x00000080, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x00000000, 0x00000000, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x00000000, 0x00000000, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8a01, 0xd00a8a01, 0xd00a8a0d, 0xd00a8a0d, 0xd00a8a0d }, - { 0x00009944, 0xefbc0000, 0xefbc0000, 0xefbc1010, 0xefbc1010, 0xefbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x0000a960, 0x00000000, 0x00000000, 0x00000010, 0x00000010, 0x00000010 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000210, 0x00000210, 0x00000210 }, - { 0x0000c968, 0x00000200, 0x00000200, 0x000003ce, 0x000003ce, 0x000003ce }, - { 0x000099b8, 0x00000000, 0x00000000, 0x0000001c, 0x0000001c, 0x0000001c }, - { 0x000099bc, 0x00000000, 0x00000000, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x00000000, 0x00000000, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x0000a204, 0x00000440, 0x00000440, 0x00000444, 0x00000444, 0x00000444 }, - { 0x0000a20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000b20c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a21c, 0x1803800a, 0x1803800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x00000000, 0x00000000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, - { 0x0000a3d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, -}; - -static const u_int32_t ar9287Common_9287_1_1[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020015 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00007010, 0x00000033 }, - { 0x00007020, 0x00000000 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x40000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x00000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x18487320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081c4, 0x00000000 }, - { 0x000081d4, 0x00000000 }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x000000ff }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000007 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x000107ff }, - { 0x00008344, 0x01c81043 }, - { 0x00008360, 0xffffffff }, - { 0x00008364, 0xffffffff }, - { 0x00008368, 0x00000000 }, - { 0x00008370, 0x00000000 }, - { 0x00008374, 0x000000ff }, - { 0x00008378, 0x00000000 }, - { 0x0000837c, 0x00000000 }, - { 0x00008380, 0xffffffff }, - { 0x00008384, 0xffffffff }, - { 0x00008390, 0x0fffffff }, - { 0x00008394, 0x0fffffff }, - { 0x00008398, 0x00000000 }, - { 0x0000839c, 0x00000000 }, - { 0x000083a0, 0x00000000 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x0000a84c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x10002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x0000a920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009930, 0x00000000 }, - { 0x0000a930, 0x00000000 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x0108ecff }, - { 0x00009940, 0x14750604 }, - { 0x0000c95c, 0x004b6a8e }, - { 0x00009970, 0x990bb514 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x0c6f0000 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099c4, 0x06336f77 }, - { 0x000099c8, 0x6af6532f }, - { 0x000099cc, 0x08f186c8 }, - { 0x000099d0, 0x00046384 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x000099fc, 0x00001042 }, - { 0x0000a1f4, 0x00fffeff }, - { 0x0000a1f8, 0x00f5f9ff }, - { 0x0000a1fc, 0xb79f6427 }, - { 0x0000a208, 0x803e4788 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x40206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x233f7180 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a23c, 0x13c889af }, - { 0x0000a240, 0x38490a20 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0cdbd380 }, - { 0x0000a25c, 0x0f0f0f01 }, - { 0x0000a260, 0xdfa91f01 }, - { 0x0000a264, 0x00418a11 }, - { 0x0000b264, 0x00418a11 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0e79e5c6 }, - { 0x0000b26c, 0x0e79e5c6 }, - { 0x0000d270, 0x00820820 }, - { 0x0000a278, 0x1ce739ce }, - { 0x0000a27c, 0x050701ce }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x1ce739ce }, - { 0x0000a398, 0x000001ce }, - { 0x0000b398, 0x000001ce }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3c8, 0x00000246 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x1ce739ce }, - { 0x0000a3e0, 0x000001ce }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x0000a3f0, 0x01036a1e }, - { 0x0000a3f4, 0x00000000 }, - { 0x0000b3f4, 0x00000000 }, - { 0x0000a7d8, 0x000003f1 }, - { 0x00007800, 0x00000800 }, - { 0x00007804, 0x6c35ffc2 }, - { 0x00007808, 0x6db6c000 }, - { 0x0000780c, 0x6db6cb30 }, - { 0x00007810, 0x6db6cb6c }, - { 0x00007814, 0x0501e200 }, - { 0x00007818, 0x0094128d }, - { 0x0000781c, 0x976ee392 }, - { 0x00007820, 0xf75ff6fc }, - { 0x00007824, 0x00040000 }, - { 0x00007828, 0xdb003012 }, - { 0x0000782c, 0x04924914 }, - { 0x00007830, 0x21084210 }, - { 0x00007834, 0x00140000 }, - { 0x00007838, 0x0e4548d8 }, - { 0x0000783c, 0x54214514 }, - { 0x00007840, 0x02025830 }, - { 0x00007844, 0x71c0d388 }, - { 0x00007848, 0x934934a8 }, - { 0x00007850, 0x00000000 }, - { 0x00007854, 0x00000800 }, - { 0x00007858, 0x6c35ffc2 }, - { 0x0000785c, 0x6db6c000 }, - { 0x00007860, 0x6db6cb30 }, - { 0x00007864, 0x6db6cb6c }, - { 0x00007868, 0x0501e200 }, - { 0x0000786c, 0x0094128d }, - { 0x00007870, 0x976ee392 }, - { 0x00007874, 0xf75ff6fc }, - { 0x00007878, 0x00040000 }, - { 0x0000787c, 0xdb003012 }, - { 0x00007880, 0x04924914 }, - { 0x00007884, 0x21084210 }, - { 0x00007888, 0x001b6db0 }, - { 0x0000788c, 0x00376b63 }, - { 0x00007890, 0x06db6db6 }, - { 0x00007894, 0x006d8000 }, - { 0x00007898, 0x48100000 }, - { 0x0000789c, 0x00000000 }, - { 0x000078a0, 0x08000000 }, - { 0x000078a4, 0x0007ffd8 }, - { 0x000078a8, 0x0007ffd8 }, - { 0x000078ac, 0x001c0020 }, - { 0x000078b0, 0x00060aeb }, - { 0x000078b4, 0x40008080 }, - { 0x000078b8, 0x2a850160 }, -}; - -static const u_int32_t ar9287Modes_tx_gain_9287_1_1[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00004002, 0x00004002, 0x00004002 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00008004, 0x00008004, 0x00008004 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x0000c00a, 0x0000c00a, 0x0000c00a }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001000c, 0x0001000c, 0x0001000c }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0001420b, 0x0001420b, 0x0001420b }, - { 0x0000a318, 0x00000000, 0x00000000, 0x0001824a, 0x0001824a, 0x0001824a }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0001c44a, 0x0001c44a, 0x0001c44a }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0002064a, 0x0002064a, 0x0002064a }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0002484a, 0x0002484a, 0x0002484a }, - { 0x0000a328, 0x00000000, 0x00000000, 0x00028a4a, 0x00028a4a, 0x00028a4a }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0002cc4a, 0x0002cc4a, 0x0002cc4a }, - { 0x0000a330, 0x00000000, 0x00000000, 0x00030e4a, 0x00030e4a, 0x00030e4a }, - { 0x0000a334, 0x00000000, 0x00000000, 0x00034e8a, 0x00034e8a, 0x00034e8a }, - { 0x0000a338, 0x00000000, 0x00000000, 0x00038e8c, 0x00038e8c, 0x00038e8c }, - { 0x0000a33c, 0x00000000, 0x00000000, 0x0003cecc, 0x0003cecc, 0x0003cecc }, - { 0x0000a340, 0x00000000, 0x00000000, 0x00040ed4, 0x00040ed4, 0x00040ed4 }, - { 0x0000a344, 0x00000000, 0x00000000, 0x00044edc, 0x00044edc, 0x00044edc }, - { 0x0000a348, 0x00000000, 0x00000000, 0x00048ede, 0x00048ede, 0x00048ede }, - { 0x0000a34c, 0x00000000, 0x00000000, 0x0004cf1e, 0x0004cf1e, 0x0004cf1e }, - { 0x0000a350, 0x00000000, 0x00000000, 0x00050f5e, 0x00050f5e, 0x00050f5e }, - { 0x0000a354, 0x00000000, 0x00000000, 0x00054f9e, 0x00054f9e, 0x00054f9e }, - { 0x0000a780, 0x00000000, 0x00000000, 0x00000062, 0x00000062, 0x00000062 }, - { 0x0000a784, 0x00000000, 0x00000000, 0x00004064, 0x00004064, 0x00004064 }, - { 0x0000a788, 0x00000000, 0x00000000, 0x000080a4, 0x000080a4, 0x000080a4 }, - { 0x0000a78c, 0x00000000, 0x00000000, 0x0000c0aa, 0x0000c0aa, 0x0000c0aa }, - { 0x0000a790, 0x00000000, 0x00000000, 0x000100ac, 0x000100ac, 0x000100ac }, - { 0x0000a794, 0x00000000, 0x00000000, 0x000140b4, 0x000140b4, 0x000140b4 }, - { 0x0000a798, 0x00000000, 0x00000000, 0x000180f4, 0x000180f4, 0x000180f4 }, - { 0x0000a79c, 0x00000000, 0x00000000, 0x0001c134, 0x0001c134, 0x0001c134 }, - { 0x0000a7a0, 0x00000000, 0x00000000, 0x00020174, 0x00020174, 0x00020174 }, - { 0x0000a7a4, 0x00000000, 0x00000000, 0x0002417c, 0x0002417c, 0x0002417c }, - { 0x0000a7a8, 0x00000000, 0x00000000, 0x0002817e, 0x0002817e, 0x0002817e }, - { 0x0000a7ac, 0x00000000, 0x00000000, 0x0002c1be, 0x0002c1be, 0x0002c1be }, - { 0x0000a7b0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7b4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7b8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7bc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7c0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7c4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7c8, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7cc, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7d0, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a7d4, 0x00000000, 0x00000000, 0x000301fe, 0x000301fe, 0x000301fe }, - { 0x0000a274, 0x0a180000, 0x0a180000, 0x0a1aa000, 0x0a1aa000, 0x0a1aa000 }, -}; - -static const u_int32_t ar9287Modes_rx_gain_9287_1_1[][6] = { - /* Address 5G-HT20 5G-HT40 2G-HT40 2G-HT20 Turbo */ - { 0x00009a00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x00009a10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x00009a20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x00009a48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x00009a60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x00009a70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x00009a80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x00009acc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x00009b10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x00009b34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x00009b64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x00009b78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x00009b88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x00009b90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x00009b94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009be8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x0000a120, 0x0000a120, 0x0000a120 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x0000a124, 0x0000a124, 0x0000a124 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0000a128, 0x0000a128, 0x0000a128 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x0000a12c, 0x0000a12c, 0x0000a12c }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x0000a130, 0x0000a130, 0x0000a130 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x0000a194, 0x0000a194, 0x0000a194 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0000a198, 0x0000a198, 0x0000a198 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x0000a20c, 0x0000a20c, 0x0000a20c }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x0000a210, 0x0000a210, 0x0000a210 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x0000a284, 0x0000a284, 0x0000a284 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x0000a288, 0x0000a288, 0x0000a288 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x0000a28c, 0x0000a28c, 0x0000a28c }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0000a290, 0x0000a290, 0x0000a290 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x0000a294, 0x0000a294, 0x0000a294 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x0000a2a0, 0x0000a2a0, 0x0000a2a0 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x0000a2a4, 0x0000a2a4, 0x0000a2a4 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0000a2a8, 0x0000a2a8, 0x0000a2a8 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x0000a2ac, 0x0000a2ac, 0x0000a2ac }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x0000a2b0, 0x0000a2b0, 0x0000a2b0 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x0000a2b4, 0x0000a2b4, 0x0000a2b4 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x0000a2b8, 0x0000a2b8, 0x0000a2b8 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x0000a2c4, 0x0000a2c4, 0x0000a2c4 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x0000a708, 0x0000a708, 0x0000a708 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x0000a70c, 0x0000a70c, 0x0000a70c }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x0000a710, 0x0000a710, 0x0000a710 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0000ab04, 0x0000ab04, 0x0000ab04 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x0000ab08, 0x0000ab08, 0x0000ab08 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x0000ab0c, 0x0000ab0c, 0x0000ab0c }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x0000ab10, 0x0000ab10, 0x0000ab10 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x0000ab14, 0x0000ab14, 0x0000ab14 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x0000ab18, 0x0000ab18, 0x0000ab18 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0000ab8c, 0x0000ab8c, 0x0000ab8c }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x0000ab90, 0x0000ab90, 0x0000ab90 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x0000ab94, 0x0000ab94, 0x0000ab94 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x0000ab98, 0x0000ab98, 0x0000ab98 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x0000aba4, 0x0000aba4, 0x0000aba4 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x0000aba8, 0x0000aba8, 0x0000aba8 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x0000cb04, 0x0000cb04, 0x0000cb04 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x0000cb08, 0x0000cb08, 0x0000cb08 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x0000cb0c, 0x0000cb0c, 0x0000cb0c }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x0000cb10, 0x0000cb10, 0x0000cb10 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x0000cb14, 0x0000cb14, 0x0000cb14 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x0000cb18, 0x0000cb18, 0x0000cb18 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x0000cb8c, 0x0000cb8c, 0x0000cb8c }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x0000cb90, 0x0000cb90, 0x0000cb90 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x0000cf18, 0x0000cf18, 0x0000cf18 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x0000cf24, 0x0000cf24, 0x0000cf24 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x0000cf28, 0x0000cf28, 0x0000cf28 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x0000d314, 0x0000d314, 0x0000d314 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x0000d318, 0x0000d318, 0x0000d318 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x0000d38c, 0x0000d38c, 0x0000d38c }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x0000d390, 0x0000d390, 0x0000d390 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x0000d394, 0x0000d394, 0x0000d394 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x0000d398, 0x0000d398, 0x0000d398 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x0000d3a4, 0x0000d3a4, 0x0000d3a4 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x0000d3a8, 0x0000d3a8, 0x0000d3a8 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x0000d3ac, 0x0000d3ac, 0x0000d3ac }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x0000d3b0, 0x0000d3b0, 0x0000d3b0 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x0000f380, 0x0000f380, 0x0000f380 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x0000f384, 0x0000f384, 0x0000f384 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x0000f388, 0x0000f388, 0x0000f388 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x0000f710, 0x0000f710, 0x0000f710 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x0000f714, 0x0000f714, 0x0000f714 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x0000f718, 0x0000f718, 0x0000f718 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x0000fb10, 0x0000fb10, 0x0000fb10 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x0000fb14, 0x0000fb14, 0x0000fb14 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x0000fb18, 0x0000fb18, 0x0000fb18 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x0000fb8c, 0x0000fb8c, 0x0000fb8c }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x0000fb90, 0x0000fb90, 0x0000fb90 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x0000fb94, 0x0000fb94, 0x0000fb94 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x0000ff8c, 0x0000ff8c, 0x0000ff8c }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x0000ff90, 0x0000ff90, 0x0000ff90 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x0000ff94, 0x0000ff94, 0x0000ff94 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x0000ffa0, 0x0000ffa0, 0x0000ffa0 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x0000ffa4, 0x0000ffa4, 0x0000ffa4 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x0000ffa8, 0x0000ffa8, 0x0000ffa8 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x0000ffac, 0x0000ffac, 0x0000ffac }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x0000ffb0, 0x0000ffb0, 0x0000ffb0 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x0000ffb4, 0x0000ffb4, 0x0000ffb4 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x0000ffa1, 0x0000ffa1, 0x0000ffa1 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x0000ffa5, 0x0000ffa5, 0x0000ffa5 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x0000ffa9, 0x0000ffa9, 0x0000ffa9 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x0000ffad, 0x0000ffad, 0x0000ffad }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x0000ffb1, 0x0000ffb1, 0x0000ffb1 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x0000ffb5, 0x0000ffb5, 0x0000ffb5 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x0000ffb9, 0x0000ffb9, 0x0000ffb9 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x0000ffc5, 0x0000ffc5, 0x0000ffc5 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x0000ffc9, 0x0000ffc9, 0x0000ffc9 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x0000ffcd, 0x0000ffcd, 0x0000ffcd }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x0000ffd1, 0x0000ffd1, 0x0000ffd1 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x0000ffd5, 0x0000ffd5, 0x0000ffd5 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x0000ffc2, 0x0000ffc2, 0x0000ffc2 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x0000ffc6, 0x0000ffc6, 0x0000ffc6 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x0000ffca, 0x0000ffca, 0x0000ffca }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x0000ffce, 0x0000ffce, 0x0000ffce }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x0000ffd2, 0x0000ffd2, 0x0000ffd2 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x0000ffd6, 0x0000ffd6, 0x0000ffd6 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x0000ffda, 0x0000ffda, 0x0000ffda }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x0000ffc7, 0x0000ffc7, 0x0000ffc7 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x0000ffcb, 0x0000ffcb, 0x0000ffcb }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x0000ffcf, 0x0000ffcf, 0x0000ffcf }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x0000ffd3, 0x0000ffd3, 0x0000ffd3 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x0000ffd7, 0x0000ffd7, 0x0000ffd7 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abac, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abec, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x0000ffdb, 0x0000ffdb, 0x0000ffdb }, - { 0x00009848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, - { 0x0000a848, 0x00000000, 0x00000000, 0x00001067, 0x00001067, 0x00001067 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_always_on_L1_9287_1_1[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffd }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - -static const u_int32_t ar9287PciePhy_clkreq_off_L1_9287_1_1[][2] = { - {0x00004040, 0x9248fd00 }, - {0x00004040, 0x24924924 }, - {0x00004040, 0xa8000019 }, - {0x00004040, 0x13160820 }, - {0x00004040, 0xe5980560 }, - {0x00004040, 0xc01dcffc }, - {0x00004040, 0x1aaabe41 }, - {0x00004040, 0xbe105554 }, - {0x00004040, 0x00043007 }, - {0x00004044, 0x00000000 }, -}; - - -/* AR9271 initialization values automaticaly created: 03/23/09 */ -static const u_int32_t ar9271Modes_9271_1_0[][6] = { - { 0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160, 0x000001e0 }, - { 0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c, 0x000001e0 }, - { 0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38, 0x00001180 }, - { 0x000010f0, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008 }, - { 0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00, 0x06e006e0 }, - { 0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b, 0x0988004f }, - { 0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440, 0x00006880 }, - { 0x00009804, 0x00000300, 0x000003c4, 0x000003c4, 0x00000300, 0x00000303 }, - { 0x00009820, 0x02020200, 0x02020200, 0x02020200, 0x02020200, 0x02020200 }, - { 0x00009824, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009828, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001, 0x0a020001 }, - { 0x00009834, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e }, - { 0x00009838, 0x00000007, 0x00000007, 0x00000007, 0x00000007, 0x00000007 }, - { 0x00009840, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e, 0x206a012e }, - { 0x00009844, 0x0372161e, 0x0372161e, 0x03721620, 0x03721620, 0x037216a0 }, - { 0x00009848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x0000a848, 0x00001066, 0x00001066, 0x00001053, 0x00001053, 0x00001059 }, - { 0x00009850, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2, 0x6d4000e2 }, - { 0x00009858, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e, 0x7ec84d2e }, - { 0x0000985c, 0x3139605e, 0x3139605e, 0x3137605e, 0x3137605e, 0x3139605e }, - { 0x00009860, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18, 0x00058d18 }, - { 0x00009864, 0x0000fe00, 0x0000fe00, 0x0001ce00, 0x0001ce00, 0x0001ce00 }, - { 0x00009868, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0 }, - { 0x0000986c, 0x06903081, 0x06903081, 0x06903881, 0x06903881, 0x06903881 }, - { 0x00009914, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898, 0x000007d0 }, - { 0x00009918, 0x0000000a, 0x00000014, 0x00000016, 0x0000000b, 0x00000016 }, - { 0x00009924, 0xd00a8007, 0xd00a8007, 0xd00a800d, 0xd00a800d, 0xd00a800d }, - { 0x00009944, 0xffbc1010, 0xffbc1010, 0xffbc1020, 0xffbc1020, 0xffbc1010 }, - { 0x00009960, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009964, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099b8, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c, 0x0000421c }, - { 0x000099bc, 0x00000600, 0x00000600, 0x00000c00, 0x00000c00, 0x00000c00 }, - { 0x000099c0, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4 }, - { 0x000099c4, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77, 0x06336f77 }, - { 0x000099c8, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329, 0x6af65329 }, - { 0x000099cc, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8, 0x08f186c8 }, - { 0x000099d0, 0x00046384, 0x00046384, 0x00046384, 0x00046384, 0x00046384 }, - { 0x000099d4, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x000099d8, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x00009a00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x00009a04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x00009a08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x00009a0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x00009a10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x00009a14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x00009a18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x00009a1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x00009a20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x00009a24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x00009a28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x00009a2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x00009a30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x00009a34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x00009a38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x00009a3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x00009a40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x00009a44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x00009a48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x00009a4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x00009a50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, - { 0x00009a54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x00009a58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x00009a5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x00009a60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x00009a64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x00009a68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x00009a6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x00009a70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x00009a74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x00009a78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x00009a7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x00009a80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x00009a84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x00009a88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x00009a8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x00009a94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x00009a98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x00009a9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x00009aa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x00009aa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x00009aa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x00009aac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x00009ab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x00009ab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x00009ab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x00009abc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x00009ac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x00009ac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x00009ac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x00009acc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x00009ad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x00009ad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x00009ad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x00009adc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x00009ae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x00009ae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x00009ae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x00009aec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x00009af0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x00009af4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x00009af8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x00009afc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x00009b00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x00009b04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x00009b08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x00009b0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x00009b10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x00009b14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x00009b18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x00009b1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x00009b20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x00009b24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x00009b28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x00009b2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x00009b30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x00009b34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x00009b38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x00009b3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x00009b40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x00009b44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x00009b48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x00009b4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x00009b50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x00009b54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x00009b58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x00009b5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x00009b60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x00009b64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009b9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009ba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009be8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x00009bfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aa00, 0x00000000, 0x00000000, 0x00058084, 0x00058084, 0x00000000 }, - { 0x0000aa04, 0x00000000, 0x00000000, 0x00058088, 0x00058088, 0x00000000 }, - { 0x0000aa08, 0x00000000, 0x00000000, 0x0005808c, 0x0005808c, 0x00000000 }, - { 0x0000aa0c, 0x00000000, 0x00000000, 0x00058100, 0x00058100, 0x00000000 }, - { 0x0000aa10, 0x00000000, 0x00000000, 0x00058104, 0x00058104, 0x00000000 }, - { 0x0000aa14, 0x00000000, 0x00000000, 0x00058108, 0x00058108, 0x00000000 }, - { 0x0000aa18, 0x00000000, 0x00000000, 0x0005810c, 0x0005810c, 0x00000000 }, - { 0x0000aa1c, 0x00000000, 0x00000000, 0x00058110, 0x00058110, 0x00000000 }, - { 0x0000aa20, 0x00000000, 0x00000000, 0x00058114, 0x00058114, 0x00000000 }, - { 0x0000aa24, 0x00000000, 0x00000000, 0x00058180, 0x00058180, 0x00000000 }, - { 0x0000aa28, 0x00000000, 0x00000000, 0x00058184, 0x00058184, 0x00000000 }, - { 0x0000aa2c, 0x00000000, 0x00000000, 0x00058188, 0x00058188, 0x00000000 }, - { 0x0000aa30, 0x00000000, 0x00000000, 0x0005818c, 0x0005818c, 0x00000000 }, - { 0x0000aa34, 0x00000000, 0x00000000, 0x00058190, 0x00058190, 0x00000000 }, - { 0x0000aa38, 0x00000000, 0x00000000, 0x00058194, 0x00058194, 0x00000000 }, - { 0x0000aa3c, 0x00000000, 0x00000000, 0x000581a0, 0x000581a0, 0x00000000 }, - { 0x0000aa40, 0x00000000, 0x00000000, 0x0005820c, 0x0005820c, 0x00000000 }, - { 0x0000aa44, 0x00000000, 0x00000000, 0x000581a8, 0x000581a8, 0x00000000 }, - { 0x0000aa48, 0x00000000, 0x00000000, 0x00058284, 0x00058284, 0x00000000 }, - { 0x0000aa4c, 0x00000000, 0x00000000, 0x00058288, 0x00058288, 0x00000000 }, - { 0x0000aa50, 0x00000000, 0x00000000, 0x00058220, 0x00058220, 0x00000000 }, - { 0x0000aa54, 0x00000000, 0x00000000, 0x00058290, 0x00058290, 0x00000000 }, - { 0x0000aa58, 0x00000000, 0x00000000, 0x00058300, 0x00058300, 0x00000000 }, - { 0x0000aa5c, 0x00000000, 0x00000000, 0x00058304, 0x00058304, 0x00000000 }, - { 0x0000aa60, 0x00000000, 0x00000000, 0x00058308, 0x00058308, 0x00000000 }, - { 0x0000aa64, 0x00000000, 0x00000000, 0x0005830c, 0x0005830c, 0x00000000 }, - { 0x0000aa68, 0x00000000, 0x00000000, 0x00058380, 0x00058380, 0x00000000 }, - { 0x0000aa6c, 0x00000000, 0x00000000, 0x00058384, 0x00058384, 0x00000000 }, - { 0x0000aa70, 0x00000000, 0x00000000, 0x00068700, 0x00068700, 0x00000000 }, - { 0x0000aa74, 0x00000000, 0x00000000, 0x00068704, 0x00068704, 0x00000000 }, - { 0x0000aa78, 0x00000000, 0x00000000, 0x00068708, 0x00068708, 0x00000000 }, - { 0x0000aa7c, 0x00000000, 0x00000000, 0x0006870c, 0x0006870c, 0x00000000 }, - { 0x0000aa80, 0x00000000, 0x00000000, 0x00068780, 0x00068780, 0x00000000 }, - { 0x0000aa84, 0x00000000, 0x00000000, 0x00068784, 0x00068784, 0x00000000 }, - { 0x0000aa88, 0x00000000, 0x00000000, 0x00078b04, 0x00078b04, 0x00000000 }, - { 0x0000aa8c, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa90, 0x00000000, 0x00000000, 0x00078b08, 0x00078b08, 0x00000000 }, - { 0x0000aa94, 0x00000000, 0x00000000, 0x00078b0c, 0x00078b0c, 0x00000000 }, - { 0x0000aa98, 0x00000000, 0x00000000, 0x00078b80, 0x00078b80, 0x00000000 }, - { 0x0000aa9c, 0x00000000, 0x00000000, 0x00078b84, 0x00078b84, 0x00000000 }, - { 0x0000aaa0, 0x00000000, 0x00000000, 0x00078b88, 0x00078b88, 0x00000000 }, - { 0x0000aaa4, 0x00000000, 0x00000000, 0x00078b8c, 0x00078b8c, 0x00000000 }, - { 0x0000aaa8, 0x00000000, 0x00000000, 0x00078b90, 0x00078b90, 0x00000000 }, - { 0x0000aaac, 0x00000000, 0x00000000, 0x000caf80, 0x000caf80, 0x00000000 }, - { 0x0000aab0, 0x00000000, 0x00000000, 0x000caf84, 0x000caf84, 0x00000000 }, - { 0x0000aab4, 0x00000000, 0x00000000, 0x000caf88, 0x000caf88, 0x00000000 }, - { 0x0000aab8, 0x00000000, 0x00000000, 0x000caf8c, 0x000caf8c, 0x00000000 }, - { 0x0000aabc, 0x00000000, 0x00000000, 0x000caf90, 0x000caf90, 0x00000000 }, - { 0x0000aac0, 0x00000000, 0x00000000, 0x000db30c, 0x000db30c, 0x00000000 }, - { 0x0000aac4, 0x00000000, 0x00000000, 0x000db310, 0x000db310, 0x00000000 }, - { 0x0000aac8, 0x00000000, 0x00000000, 0x000db384, 0x000db384, 0x00000000 }, - { 0x0000aacc, 0x00000000, 0x00000000, 0x000db388, 0x000db388, 0x00000000 }, - { 0x0000aad0, 0x00000000, 0x00000000, 0x000db324, 0x000db324, 0x00000000 }, - { 0x0000aad4, 0x00000000, 0x00000000, 0x000eb704, 0x000eb704, 0x00000000 }, - { 0x0000aad8, 0x00000000, 0x00000000, 0x000eb6a4, 0x000eb6a4, 0x00000000 }, - { 0x0000aadc, 0x00000000, 0x00000000, 0x000eb6a8, 0x000eb6a8, 0x00000000 }, - { 0x0000aae0, 0x00000000, 0x00000000, 0x000eb710, 0x000eb710, 0x00000000 }, - { 0x0000aae4, 0x00000000, 0x00000000, 0x000eb714, 0x000eb714, 0x00000000 }, - { 0x0000aae8, 0x00000000, 0x00000000, 0x000eb720, 0x000eb720, 0x00000000 }, - { 0x0000aaec, 0x00000000, 0x00000000, 0x000eb724, 0x000eb724, 0x00000000 }, - { 0x0000aaf0, 0x00000000, 0x00000000, 0x000eb728, 0x000eb728, 0x00000000 }, - { 0x0000aaf4, 0x00000000, 0x00000000, 0x000eb72c, 0x000eb72c, 0x00000000 }, - { 0x0000aaf8, 0x00000000, 0x00000000, 0x000eb7a0, 0x000eb7a0, 0x00000000 }, - { 0x0000aafc, 0x00000000, 0x00000000, 0x000eb7a4, 0x000eb7a4, 0x00000000 }, - { 0x0000ab00, 0x00000000, 0x00000000, 0x000eb7a8, 0x000eb7a8, 0x00000000 }, - { 0x0000ab04, 0x00000000, 0x00000000, 0x000eb7b0, 0x000eb7b0, 0x00000000 }, - { 0x0000ab08, 0x00000000, 0x00000000, 0x000eb7b4, 0x000eb7b4, 0x00000000 }, - { 0x0000ab0c, 0x00000000, 0x00000000, 0x000eb7b8, 0x000eb7b8, 0x00000000 }, - { 0x0000ab10, 0x00000000, 0x00000000, 0x000eb7a5, 0x000eb7a5, 0x00000000 }, - { 0x0000ab14, 0x00000000, 0x00000000, 0x000eb7a9, 0x000eb7a9, 0x00000000 }, - { 0x0000ab18, 0x00000000, 0x00000000, 0x000eb7ad, 0x000eb7ad, 0x00000000 }, - { 0x0000ab1c, 0x00000000, 0x00000000, 0x000eb7b1, 0x000eb7b1, 0x00000000 }, - { 0x0000ab20, 0x00000000, 0x00000000, 0x000eb7b5, 0x000eb7b5, 0x00000000 }, - { 0x0000ab24, 0x00000000, 0x00000000, 0x000eb7b9, 0x000eb7b9, 0x00000000 }, - { 0x0000ab28, 0x00000000, 0x00000000, 0x000eb7c5, 0x000eb7c5, 0x00000000 }, - { 0x0000ab2c, 0x00000000, 0x00000000, 0x000eb7c9, 0x000eb7c9, 0x00000000 }, - { 0x0000ab30, 0x00000000, 0x00000000, 0x000eb7d1, 0x000eb7d1, 0x00000000 }, - { 0x0000ab34, 0x00000000, 0x00000000, 0x000eb7d5, 0x000eb7d5, 0x00000000 }, - { 0x0000ab38, 0x00000000, 0x00000000, 0x000eb7d9, 0x000eb7d9, 0x00000000 }, - { 0x0000ab3c, 0x00000000, 0x00000000, 0x000eb7c6, 0x000eb7c6, 0x00000000 }, - { 0x0000ab40, 0x00000000, 0x00000000, 0x000eb7ca, 0x000eb7ca, 0x00000000 }, - { 0x0000ab44, 0x00000000, 0x00000000, 0x000eb7ce, 0x000eb7ce, 0x00000000 }, - { 0x0000ab48, 0x00000000, 0x00000000, 0x000eb7d2, 0x000eb7d2, 0x00000000 }, - { 0x0000ab4c, 0x00000000, 0x00000000, 0x000eb7d6, 0x000eb7d6, 0x00000000 }, - { 0x0000ab50, 0x00000000, 0x00000000, 0x000eb7c3, 0x000eb7c3, 0x00000000 }, - { 0x0000ab54, 0x00000000, 0x00000000, 0x000eb7c7, 0x000eb7c7, 0x00000000 }, - { 0x0000ab58, 0x00000000, 0x00000000, 0x000eb7cb, 0x000eb7cb, 0x00000000 }, - { 0x0000ab5c, 0x00000000, 0x00000000, 0x000eb7cf, 0x000eb7cf, 0x00000000 }, - { 0x0000ab60, 0x00000000, 0x00000000, 0x000eb7d7, 0x000eb7d7, 0x00000000 }, - { 0x0000ab64, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab68, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab6c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab70, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab74, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab78, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab7c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab80, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab84, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab88, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab8c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab90, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab94, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab98, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000ab9c, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000aba8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abac, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abb8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abbc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abc8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abcc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abd8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abdc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abe8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abec, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf0, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf4, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abf8, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000abfc, 0x00000000, 0x00000000, 0x000eb7db, 0x000eb7db, 0x00000000 }, - { 0x0000a204, 0x00000004, 0x00000004, 0x00000004, 0x00000004, 0x00000004 }, - { 0x0000a20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000b20c, 0x00000014, 0x00000014, 0x0001f000, 0x0001f000, 0x0001f000 }, - { 0x0000a21c, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a, 0x1883800a }, - { 0x0000a230, 0x00000000, 0x00000000, 0x00000210, 0x00000108, 0x00000000 }, - { 0x0000a250, 0x0004f000, 0x0004f000, 0x0004a000, 0x0004a000, 0x0004a000 }, - { 0x0000a274, 0x0a21c652, 0x0a21c652, 0x0a218652, 0x0a218652, 0x0a22a652 }, - { 0x0000a300, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, - { 0x0000a304, 0x00000000, 0x00000000, 0x00009200, 0x00009200, 0x00000000 }, - { 0x0000a308, 0x00000000, 0x00000000, 0x00010208, 0x00010208, 0x00000000 }, - { 0x0000a30c, 0x00000000, 0x00000000, 0x00019608, 0x00019608, 0x00000000 }, - { 0x0000a310, 0x00000000, 0x00000000, 0x0001e610, 0x0001e610, 0x00000000 }, - { 0x0000a314, 0x00000000, 0x00000000, 0x0002d6d0, 0x0002d6d0, 0x00000000 }, - { 0x0000a318, 0x00000000, 0x00000000, 0x00039758, 0x00039758, 0x00000000 }, - { 0x0000a31c, 0x00000000, 0x00000000, 0x0003b759, 0x0003b759, 0x00000000 }, - { 0x0000a320, 0x00000000, 0x00000000, 0x0003d75a, 0x0003d75a, 0x00000000 }, - { 0x0000a324, 0x00000000, 0x00000000, 0x0004175c, 0x0004175c, 0x00000000 }, - { 0x0000a328, 0x00000000, 0x00000000, 0x0004575e, 0x0004575e, 0x00000000 }, - { 0x0000a32c, 0x00000000, 0x00000000, 0x0004979f, 0x0004979f, 0x00000000 }, - { 0x0000a330, 0x00000000, 0x00000000, 0x0004d7df, 0x0004d7df, 0x00000000 }, - { 0x0000a334, 0x000368de, 0x000368de, 0x000368de, 0x000368de, 0x00000000 }, - { 0x0000a338, 0x0003891e, 0x0003891e, 0x0003891e, 0x0003891e, 0x00000000 }, - { 0x0000a33c, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x0003a95e, 0x00000000 }, - { 0x0000a340, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a344, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x0003e9df, 0x00000000 }, - { 0x0000a358, 0x7999aa02, 0x7999aa02, 0x7999aa0e, 0x7999aa0e, 0x7999aa0e }, -}; - -static const u_int32_t ar9271Common_9271_1_0[][2] = { - { 0x0000000c, 0x00000000 }, - { 0x00000030, 0x00020045 }, - { 0x00000034, 0x00000005 }, - { 0x00000040, 0x00000000 }, - { 0x00000044, 0x00000008 }, - { 0x00000048, 0x00000008 }, - { 0x0000004c, 0x00000010 }, - { 0x00000050, 0x00000000 }, - { 0x00000054, 0x0000001f }, - { 0x00000800, 0x00000000 }, - { 0x00000804, 0x00000000 }, - { 0x00000808, 0x00000000 }, - { 0x0000080c, 0x00000000 }, - { 0x00000810, 0x00000000 }, - { 0x00000814, 0x00000000 }, - { 0x00000818, 0x00000000 }, - { 0x0000081c, 0x00000000 }, - { 0x00000820, 0x00000000 }, - { 0x00000824, 0x00000000 }, - { 0x00001040, 0x002ffc0f }, - { 0x00001044, 0x002ffc0f }, - { 0x00001048, 0x002ffc0f }, - { 0x0000104c, 0x002ffc0f }, - { 0x00001050, 0x002ffc0f }, - { 0x00001054, 0x002ffc0f }, - { 0x00001058, 0x002ffc0f }, - { 0x0000105c, 0x002ffc0f }, - { 0x00001060, 0x002ffc0f }, - { 0x00001064, 0x002ffc0f }, - { 0x00001230, 0x00000000 }, - { 0x00001270, 0x00000000 }, - { 0x00001038, 0x00000000 }, - { 0x00001078, 0x00000000 }, - { 0x000010b8, 0x00000000 }, - { 0x000010f8, 0x00000000 }, - { 0x00001138, 0x00000000 }, - { 0x00001178, 0x00000000 }, - { 0x000011b8, 0x00000000 }, - { 0x000011f8, 0x00000000 }, - { 0x00001238, 0x00000000 }, - { 0x00001278, 0x00000000 }, - { 0x000012b8, 0x00000000 }, - { 0x000012f8, 0x00000000 }, - { 0x00001338, 0x00000000 }, - { 0x00001378, 0x00000000 }, - { 0x000013b8, 0x00000000 }, - { 0x000013f8, 0x00000000 }, - { 0x00001438, 0x00000000 }, - { 0x00001478, 0x00000000 }, - { 0x000014b8, 0x00000000 }, - { 0x000014f8, 0x00000000 }, - { 0x00001538, 0x00000000 }, - { 0x00001578, 0x00000000 }, - { 0x000015b8, 0x00000000 }, - { 0x000015f8, 0x00000000 }, - { 0x00001638, 0x00000000 }, - { 0x00001678, 0x00000000 }, - { 0x000016b8, 0x00000000 }, - { 0x000016f8, 0x00000000 }, - { 0x00001738, 0x00000000 }, - { 0x00001778, 0x00000000 }, - { 0x000017b8, 0x00000000 }, - { 0x000017f8, 0x00000000 }, - { 0x0000103c, 0x00000000 }, - { 0x0000107c, 0x00000000 }, - { 0x000010bc, 0x00000000 }, - { 0x000010fc, 0x00000000 }, - { 0x0000113c, 0x00000000 }, - { 0x0000117c, 0x00000000 }, - { 0x000011bc, 0x00000000 }, - { 0x000011fc, 0x00000000 }, - { 0x0000123c, 0x00000000 }, - { 0x0000127c, 0x00000000 }, - { 0x000012bc, 0x00000000 }, - { 0x000012fc, 0x00000000 }, - { 0x0000133c, 0x00000000 }, - { 0x0000137c, 0x00000000 }, - { 0x000013bc, 0x00000000 }, - { 0x000013fc, 0x00000000 }, - { 0x0000143c, 0x00000000 }, - { 0x0000147c, 0x00000000 }, - { 0x00004030, 0x00000002 }, - { 0x0000403c, 0x00000002 }, - { 0x00004024, 0x0000001f }, - { 0x00004060, 0x00000000 }, - { 0x00004064, 0x00000000 }, - { 0x00008004, 0x00000000 }, - { 0x00008008, 0x00000000 }, - { 0x0000800c, 0x00000000 }, - { 0x00008018, 0x00000700 }, - { 0x00008020, 0x00000000 }, - { 0x00008038, 0x00000000 }, - { 0x0000803c, 0x00000000 }, - { 0x00008048, 0x00000000 }, - { 0x00008054, 0x00000000 }, - { 0x00008058, 0x02000000 }, - { 0x0000805c, 0x000fc78f }, - { 0x00008060, 0x0000000f }, - { 0x00008064, 0x00000000 }, - { 0x00008070, 0x00000000 }, - { 0x000080b0, 0x00000000 }, - { 0x000080b4, 0x00000000 }, - { 0x000080b8, 0x00000000 }, - { 0x000080bc, 0x00000000 }, - { 0x000080c0, 0x2a80001a }, - { 0x000080c4, 0x05dc01e0 }, - { 0x000080c8, 0x1f402710 }, - { 0x000080cc, 0x01f40000 }, - { 0x000080d0, 0x00001e00 }, - { 0x000080d4, 0x00000000 }, - { 0x000080d8, 0x00400000 }, - { 0x000080e0, 0xffffffff }, - { 0x000080e4, 0x0000ffff }, - { 0x000080e8, 0x003f3f3f }, - { 0x000080ec, 0x00000000 }, - { 0x000080f0, 0x00000000 }, - { 0x000080f4, 0x00000000 }, - { 0x000080f8, 0x00000000 }, - { 0x000080fc, 0x00020000 }, - { 0x00008100, 0x00020000 }, - { 0x00008104, 0x00000001 }, - { 0x00008108, 0x00000052 }, - { 0x0000810c, 0x00000000 }, - { 0x00008110, 0x00000168 }, - { 0x00008118, 0x000100aa }, - { 0x0000811c, 0x00003210 }, - { 0x00008120, 0x08f04814 }, - { 0x00008124, 0x00000000 }, - { 0x00008128, 0x00000000 }, - { 0x0000812c, 0x00000000 }, - { 0x00008130, 0x00000000 }, - { 0x00008134, 0x00000000 }, - { 0x00008138, 0x00000000 }, - { 0x0000813c, 0x00000000 }, - { 0x00008144, 0xffffffff }, - { 0x00008168, 0x00000000 }, - { 0x0000816c, 0x00000000 }, - { 0x00008170, 0x32143320 }, - { 0x00008174, 0xfaa4fa50 }, - { 0x00008178, 0x00000100 }, - { 0x0000817c, 0x00000000 }, - { 0x000081c0, 0x00000000 }, - { 0x000081d0, 0x0000320a }, - { 0x000081ec, 0x00000000 }, - { 0x000081f0, 0x00000000 }, - { 0x000081f4, 0x00000000 }, - { 0x000081f8, 0x00000000 }, - { 0x000081fc, 0x00000000 }, - { 0x00008200, 0x00000000 }, - { 0x00008204, 0x00000000 }, - { 0x00008208, 0x00000000 }, - { 0x0000820c, 0x00000000 }, - { 0x00008210, 0x00000000 }, - { 0x00008214, 0x00000000 }, - { 0x00008218, 0x00000000 }, - { 0x0000821c, 0x00000000 }, - { 0x00008220, 0x00000000 }, - { 0x00008224, 0x00000000 }, - { 0x00008228, 0x00000000 }, - { 0x0000822c, 0x00000000 }, - { 0x00008230, 0x00000000 }, - { 0x00008234, 0x00000000 }, - { 0x00008238, 0x00000000 }, - { 0x0000823c, 0x00000000 }, - { 0x00008240, 0x00100000 }, - { 0x00008244, 0x0010f400 }, - { 0x00008248, 0x00000100 }, - { 0x0000824c, 0x0001e800 }, - { 0x00008250, 0x00000000 }, - { 0x00008254, 0x00000000 }, - { 0x00008258, 0x00000000 }, - { 0x0000825c, 0x400000ff }, - { 0x00008260, 0x00080922 }, - { 0x00008264, 0x88a00010 }, - { 0x00008270, 0x00000000 }, - { 0x00008274, 0x40000000 }, - { 0x00008278, 0x003e4180 }, - { 0x0000827c, 0x00000000 }, - { 0x00008284, 0x0000002c }, - { 0x00008288, 0x0000002c }, - { 0x0000828c, 0x00000000 }, - { 0x00008294, 0x00000000 }, - { 0x00008298, 0x00000000 }, - { 0x0000829c, 0x00000000 }, - { 0x00008300, 0x00000040 }, - { 0x00008314, 0x00000000 }, - { 0x00008328, 0x00000000 }, - { 0x0000832c, 0x00000001 }, - { 0x00008330, 0x00000302 }, - { 0x00008334, 0x00000e00 }, - { 0x00008338, 0x00ff0000 }, - { 0x0000833c, 0x00000000 }, - { 0x00008340, 0x00010380 }, - { 0x00008344, 0x00581043 }, - { 0x00007010, 0x00000030 }, - { 0x00007034, 0x00000002 }, - { 0x00007038, 0x000004c2 }, - { 0x00007800, 0x00140000 }, - { 0x00007804, 0x0e4548d8 }, - { 0x00007808, 0x54214514 }, - { 0x0000780c, 0x02025820 }, - { 0x00007810, 0x71c0d388 }, - { 0x00007814, 0x924934a8 }, - { 0x0000781c, 0x00000000 }, - { 0x00007820, 0x00000c04 }, - { 0x00007824, 0x00d86bff }, - { 0x00007828, 0x66964300 }, - { 0x0000782c, 0x8db6d961 }, - { 0x00007830, 0x8db6d96c }, - { 0x00007834, 0x6140008b }, - { 0x00007838, 0x00000029 }, - { 0x0000783c, 0x72ee0a72 }, - { 0x00007840, 0xbbfffffc }, - { 0x00007844, 0x000c0db6 }, - { 0x00007848, 0x6db61b6f }, - { 0x0000784c, 0x6d9b66db }, - { 0x00007850, 0x6d8c6dba }, - { 0x00007854, 0x00040000 }, - { 0x00007858, 0xdb003012 }, - { 0x0000785c, 0x04924914 }, - { 0x00007860, 0x21084210 }, - { 0x00007864, 0xf7d7ffde }, - { 0x00007868, 0xc2034080 }, - { 0x0000786c, 0x48609eb4 }, - { 0x00007870, 0x10142c00 }, - { 0x00009808, 0x00000000 }, - { 0x0000980c, 0xafe68e30 }, - { 0x00009810, 0xfd14e000 }, - { 0x00009814, 0x9c0a9f6b }, - { 0x0000981c, 0x00000000 }, - { 0x0000982c, 0x0000a000 }, - { 0x00009830, 0x00000000 }, - { 0x0000983c, 0x00200400 }, - { 0x0000984c, 0x0040233c }, - { 0x00009854, 0x00000044 }, - { 0x00009900, 0x00000000 }, - { 0x00009904, 0x00000000 }, - { 0x00009908, 0x00000000 }, - { 0x0000990c, 0x00000000 }, - { 0x00009910, 0x30002310 }, - { 0x0000991c, 0x10000fff }, - { 0x00009920, 0x04900000 }, - { 0x00009928, 0x00000001 }, - { 0x0000992c, 0x00000004 }, - { 0x00009934, 0x1e1f2022 }, - { 0x00009938, 0x0a0b0c0d }, - { 0x0000993c, 0x00000000 }, - { 0x00009940, 0x14750604 }, - { 0x00009948, 0x9280c00a }, - { 0x0000994c, 0x00020028 }, - { 0x00009954, 0x5f3ca3de }, - { 0x00009958, 0x0108ecff }, - { 0x00009968, 0x000003ce }, - { 0x00009970, 0x192bb515 }, - { 0x00009974, 0x00000000 }, - { 0x00009978, 0x00000001 }, - { 0x0000997c, 0x00000000 }, - { 0x00009980, 0x00000000 }, - { 0x00009984, 0x00000000 }, - { 0x00009988, 0x00000000 }, - { 0x0000998c, 0x00000000 }, - { 0x00009990, 0x00000000 }, - { 0x00009994, 0x00000000 }, - { 0x00009998, 0x00000000 }, - { 0x0000999c, 0x00000000 }, - { 0x000099a0, 0x00000000 }, - { 0x000099a4, 0x00000001 }, - { 0x000099a8, 0x201fff00 }, - { 0x000099ac, 0x2def0400 }, - { 0x000099b0, 0x03051000 }, - { 0x000099b4, 0x00000820 }, - { 0x000099dc, 0x00000000 }, - { 0x000099e0, 0x00000000 }, - { 0x000099e4, 0xaaaaaaaa }, - { 0x000099e8, 0x3c466478 }, - { 0x000099ec, 0x0cc80caa }, - { 0x000099f0, 0x00000000 }, - { 0x0000a1f4, 0x00000000 }, - { 0x0000a1f8, 0x71733d01 }, - { 0x0000a1fc, 0xd0ad5c12 }, - { 0x0000a208, 0x803e68c8 }, - { 0x0000a210, 0x4080a333 }, - { 0x0000a214, 0x00206c10 }, - { 0x0000a218, 0x009c4060 }, - { 0x0000a220, 0x01834061 }, - { 0x0000a224, 0x00000400 }, - { 0x0000a228, 0x000003b5 }, - { 0x0000a22c, 0x00000000 }, - { 0x0000a234, 0x20202020 }, - { 0x0000a238, 0x20202020 }, - { 0x0000a244, 0x00000000 }, - { 0x0000a248, 0xfffffffc }, - { 0x0000a24c, 0x00000000 }, - { 0x0000a254, 0x00000000 }, - { 0x0000a258, 0x0ccb5380 }, - { 0x0000a25c, 0x15151501 }, - { 0x0000a260, 0xdfa90f01 }, - { 0x0000a268, 0x00000000 }, - { 0x0000a26c, 0x0ebae9e6 }, - { 0x0000a278, 0x3bdef7bd }, - { 0x0000a27c, 0x050e83bd }, - { 0x0000a388, 0x0c000000 }, - { 0x0000a38c, 0x20202020 }, - { 0x0000a390, 0x20202020 }, - { 0x0000a394, 0x3bdef7bd }, - { 0x0000a398, 0x000003bd }, - { 0x0000a39c, 0x00000001 }, - { 0x0000a3a0, 0x00000000 }, - { 0x0000a3a4, 0x00000000 }, - { 0x0000a3a8, 0x00000000 }, - { 0x0000a3ac, 0x00000000 }, - { 0x0000a3b0, 0x00000000 }, - { 0x0000a3b4, 0x00000000 }, - { 0x0000a3b8, 0x00000000 }, - { 0x0000a3bc, 0x00000000 }, - { 0x0000a3c0, 0x00000000 }, - { 0x0000a3c4, 0x00000000 }, - { 0x0000a3cc, 0x20202020 }, - { 0x0000a3d0, 0x20202020 }, - { 0x0000a3d4, 0x20202020 }, - { 0x0000a3dc, 0x3bdef7bd }, - { 0x0000a3e0, 0x000003bd }, - { 0x0000a3e4, 0x00000000 }, - { 0x0000a3e8, 0x18c43433 }, - { 0x0000a3ec, 0x00f70081 }, - { 0x0000a3f0, 0x01036a2f }, - { 0x0000a3f4, 0x00000000 }, - { 0x0000d270, 0x0d820820 }, - { 0x0000d35c, 0x07ffffef }, - { 0x0000d360, 0x0fffffe7 }, - { 0x0000d364, 0x17ffffe5 }, - { 0x0000d368, 0x1fffffe4 }, - { 0x0000d36c, 0x37ffffe3 }, - { 0x0000d370, 0x3fffffe3 }, - { 0x0000d374, 0x57ffffe3 }, - { 0x0000d378, 0x5fffffe2 }, - { 0x0000d37c, 0x7fffffe2 }, - { 0x0000d380, 0x7f3c7bba }, - { 0x0000d384, 0xf3307ff0 }, -}; diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c deleted file mode 100644 index 110c16dd465c..000000000000 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ /dev/null @@ -1,985 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static void ath9k_hw_set_txq_interrupts(struct ath_hw *ah, - struct ath9k_tx_queue_info *qi) -{ - DPRINTF(ah->ah_sc, ATH_DBG_INTERRUPT, - "tx ok 0x%x err 0x%x desc 0x%x eol 0x%x urn 0x%x\n", - ah->txok_interrupt_mask, ah->txerr_interrupt_mask, - ah->txdesc_interrupt_mask, ah->txeol_interrupt_mask, - ah->txurn_interrupt_mask); - - REG_WRITE(ah, AR_IMR_S0, - SM(ah->txok_interrupt_mask, AR_IMR_S0_QCU_TXOK) - | SM(ah->txdesc_interrupt_mask, AR_IMR_S0_QCU_TXDESC)); - REG_WRITE(ah, AR_IMR_S1, - SM(ah->txerr_interrupt_mask, AR_IMR_S1_QCU_TXERR) - | SM(ah->txeol_interrupt_mask, AR_IMR_S1_QCU_TXEOL)); - REG_RMW_FIELD(ah, AR_IMR_S2, - AR_IMR_S2_QCU_TXURN, ah->txurn_interrupt_mask); -} - -u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q) -{ - return REG_READ(ah, AR_QTXDP(q)); -} - -void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp) -{ - REG_WRITE(ah, AR_QTXDP(q), txdp); -} - -void ath9k_hw_txstart(struct ath_hw *ah, u32 q) -{ - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Enable TXE on queue: %u\n", q); - REG_WRITE(ah, AR_Q_TXE, 1 << q); -} - -u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q) -{ - u32 npend; - - npend = REG_READ(ah, AR_QSTS(q)) & AR_Q_STS_PEND_FR_CNT; - if (npend == 0) { - - if (REG_READ(ah, AR_Q_TXE) & (1 << q)) - npend = 1; - } - - return npend; -} - -bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) -{ - u32 txcfg, curLevel, newLevel; - enum ath9k_int omask; - - if (ah->tx_trig_level >= ah->config.max_txtrig_level) - return false; - - omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); - - txcfg = REG_READ(ah, AR_TXCFG); - curLevel = MS(txcfg, AR_FTRIG); - newLevel = curLevel; - if (bIncTrigLevel) { - if (curLevel < ah->config.max_txtrig_level) - newLevel++; - } else if (curLevel > MIN_TX_FIFO_THRESHOLD) - newLevel--; - if (newLevel != curLevel) - REG_WRITE(ah, AR_TXCFG, - (txcfg & ~AR_FTRIG) | SM(newLevel, AR_FTRIG)); - - ath9k_hw_set_interrupts(ah, omask); - - ah->tx_trig_level = newLevel; - - return newLevel != curLevel; -} - -bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) -{ -#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ -#define ATH9K_TIME_QUANTUM 100 /* usec */ - - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - u32 tsfLow, j, wait; - u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Stopping TX DMA, " - "inactive queue: %u\n", q); - return false; - } - - REG_WRITE(ah, AR_Q_TXD, 1 << q); - - for (wait = wait_time; wait != 0; wait--) { - if (ath9k_hw_numtxpending(ah, q) == 0) - break; - udelay(ATH9K_TIME_QUANTUM); - } - - if (ath9k_hw_numtxpending(ah, q)) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "%s: Num of pending TX Frames %d on Q %d\n", - __func__, ath9k_hw_numtxpending(ah, q), q); - - for (j = 0; j < 2; j++) { - tsfLow = REG_READ(ah, AR_TSF_L32); - REG_WRITE(ah, AR_QUIET2, - SM(10, AR_QUIET2_QUIET_DUR)); - REG_WRITE(ah, AR_QUIET_PERIOD, 100); - REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10); - REG_SET_BIT(ah, AR_TIMER_MODE, - AR_QUIET_TIMER_EN); - - if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10)) - break; - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, - "TSF has moved while trying to set " - "quiet time TSF: 0x%08x\n", tsfLow); - } - - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); - - udelay(200); - REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN); - - wait = wait_time; - while (ath9k_hw_numtxpending(ah, q)) { - if ((--wait) == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Failed to stop TX DMA in 100 " - "msec after killing last frame\n"); - break; - } - udelay(ATH9K_TIME_QUANTUM); - } - - REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); - } - - REG_WRITE(ah, AR_Q_TXD, 0); - return wait != 0; - -#undef ATH9K_TX_STOP_DMA_TIMEOUT -#undef ATH9K_TIME_QUANTUM -} - -void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (firstSeg) { - ads->ds_ctl1 |= segLen | (lastSeg ? 0 : AR_TxMore); - } else if (lastSeg) { - ads->ds_ctl0 = 0; - ads->ds_ctl1 = segLen; - ads->ds_ctl2 = AR5416DESC_CONST(ds0)->ds_ctl2; - ads->ds_ctl3 = AR5416DESC_CONST(ds0)->ds_ctl3; - } else { - ads->ds_ctl0 = 0; - ads->ds_ctl1 = segLen | AR_TxMore; - ads->ds_ctl2 = 0; - ads->ds_ctl3 = 0; - } - ads->ds_txstatus0 = ads->ds_txstatus1 = 0; - ads->ds_txstatus2 = ads->ds_txstatus3 = 0; - ads->ds_txstatus4 = ads->ds_txstatus5 = 0; - ads->ds_txstatus6 = ads->ds_txstatus7 = 0; - ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} - -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_txstatus0 = ads->ds_txstatus1 = 0; - ads->ds_txstatus2 = ads->ds_txstatus3 = 0; - ads->ds_txstatus4 = ads->ds_txstatus5 = 0; - ads->ds_txstatus6 = ads->ds_txstatus7 = 0; - ads->ds_txstatus8 = ads->ds_txstatus9 = 0; -} - -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if ((ads->ds_txstatus9 & AR_TxDone) == 0) - return -EINPROGRESS; - - ds->ds_txstat.ts_seqnum = MS(ads->ds_txstatus9, AR_SeqNum); - ds->ds_txstat.ts_tstamp = ads->AR_SendTimestamp; - ds->ds_txstat.ts_status = 0; - ds->ds_txstat.ts_flags = 0; - - if (ads->ds_txstatus1 & AR_FrmXmitOK) - ds->ds_txstat.ts_status |= ATH9K_TX_ACKED; - if (ads->ds_txstatus1 & AR_ExcessiveRetries) - ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; - if (ads->ds_txstatus1 & AR_Filtered) - ds->ds_txstat.ts_status |= ATH9K_TXERR_FILT; - if (ads->ds_txstatus1 & AR_FIFOUnderrun) { - ds->ds_txstat.ts_status |= ATH9K_TXERR_FIFO; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus9 & AR_TxOpExceeded) - ds->ds_txstat.ts_status |= ATH9K_TXERR_XTXOP; - if (ads->ds_txstatus1 & AR_TxTimerExpired) - ds->ds_txstat.ts_status |= ATH9K_TXERR_TIMER_EXPIRED; - - if (ads->ds_txstatus1 & AR_DescCfgErr) - ds->ds_txstat.ts_flags |= ATH9K_TX_DESC_CFG_ERR; - if (ads->ds_txstatus1 & AR_TxDataUnderrun) { - ds->ds_txstat.ts_flags |= ATH9K_TX_DATA_UNDERRUN; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus1 & AR_TxDelimUnderrun) { - ds->ds_txstat.ts_flags |= ATH9K_TX_DELIM_UNDERRUN; - ath9k_hw_updatetxtriglevel(ah, true); - } - if (ads->ds_txstatus0 & AR_TxBaStatus) { - ds->ds_txstat.ts_flags |= ATH9K_TX_BA; - ds->ds_txstat.ba_low = ads->AR_BaBitmapLow; - ds->ds_txstat.ba_high = ads->AR_BaBitmapHigh; - } - - ds->ds_txstat.ts_rateindex = MS(ads->ds_txstatus9, AR_FinalTxIdx); - switch (ds->ds_txstat.ts_rateindex) { - case 0: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate0); - break; - case 1: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate1); - break; - case 2: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate2); - break; - case 3: - ds->ds_txstat.ts_ratecode = MS(ads->ds_ctl3, AR_XmitRate3); - break; - } - - ds->ds_txstat.ts_rssi = MS(ads->ds_txstatus5, AR_TxRSSICombined); - ds->ds_txstat.ts_rssi_ctl0 = MS(ads->ds_txstatus0, AR_TxRSSIAnt00); - ds->ds_txstat.ts_rssi_ctl1 = MS(ads->ds_txstatus0, AR_TxRSSIAnt01); - ds->ds_txstat.ts_rssi_ctl2 = MS(ads->ds_txstatus0, AR_TxRSSIAnt02); - ds->ds_txstat.ts_rssi_ext0 = MS(ads->ds_txstatus5, AR_TxRSSIAnt10); - ds->ds_txstat.ts_rssi_ext1 = MS(ads->ds_txstatus5, AR_TxRSSIAnt11); - ds->ds_txstat.ts_rssi_ext2 = MS(ads->ds_txstatus5, AR_TxRSSIAnt12); - ds->ds_txstat.evm0 = ads->AR_TxEVM0; - ds->ds_txstat.evm1 = ads->AR_TxEVM1; - ds->ds_txstat.evm2 = ads->AR_TxEVM2; - ds->ds_txstat.ts_shortretry = MS(ads->ds_txstatus1, AR_RTSFailCnt); - ds->ds_txstat.ts_longretry = MS(ads->ds_txstatus1, AR_DataFailCnt); - ds->ds_txstat.ts_virtcol = MS(ads->ds_txstatus1, AR_VirtRetryCnt); - ds->ds_txstat.ts_antenna = 0; - - return 0; -} - -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - txPower += ah->txpower_indexoffset; - if (txPower > 63) - txPower = 63; - - ads->ds_ctl0 = (pktLen & AR_FrameLen) - | (flags & ATH9K_TXDESC_VMF ? AR_VirtMoreFrag : 0) - | SM(txPower, AR_XmitPower) - | (flags & ATH9K_TXDESC_VEOL ? AR_VEOL : 0) - | (flags & ATH9K_TXDESC_CLRDMASK ? AR_ClrDestMask : 0) - | (flags & ATH9K_TXDESC_INTREQ ? AR_TxIntrReq : 0) - | (keyIx != ATH9K_TXKEYIX_INVALID ? AR_DestIdxValid : 0); - - ads->ds_ctl1 = - (keyIx != ATH9K_TXKEYIX_INVALID ? SM(keyIx, AR_DestIdx) : 0) - | SM(type, AR_FrameType) - | (flags & ATH9K_TXDESC_NOACK ? AR_NoAck : 0) - | (flags & ATH9K_TXDESC_EXT_ONLY ? AR_ExtOnly : 0) - | (flags & ATH9K_TXDESC_EXT_AND_CTL ? AR_ExtAndCtl : 0); - - ads->ds_ctl6 = SM(keyType, AR_EncrType); - - if (AR_SREV_9285(ah)) { - ads->ds_ctl8 = 0; - ads->ds_ctl9 = 0; - ads->ds_ctl10 = 0; - ads->ds_ctl11 = 0; - } -} - -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, - struct ath_desc *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - struct ar5416_desc *last_ads = AR5416DESC(lastds); - u32 ds_ctl0; - - if (flags & (ATH9K_TXDESC_RTSENA | ATH9K_TXDESC_CTSENA)) { - ds_ctl0 = ads->ds_ctl0; - - if (flags & ATH9K_TXDESC_RTSENA) { - ds_ctl0 &= ~AR_CTSEnable; - ds_ctl0 |= AR_RTSEnable; - } else { - ds_ctl0 &= ~AR_RTSEnable; - ds_ctl0 |= AR_CTSEnable; - } - - ads->ds_ctl0 = ds_ctl0; - } else { - ads->ds_ctl0 = - (ads->ds_ctl0 & ~(AR_RTSEnable | AR_CTSEnable)); - } - - ads->ds_ctl2 = set11nTries(series, 0) - | set11nTries(series, 1) - | set11nTries(series, 2) - | set11nTries(series, 3) - | (durUpdateEn ? AR_DurUpdateEna : 0) - | SM(0, AR_BurstDur); - - ads->ds_ctl3 = set11nRate(series, 0) - | set11nRate(series, 1) - | set11nRate(series, 2) - | set11nRate(series, 3); - - ads->ds_ctl4 = set11nPktDurRTSCTS(series, 0) - | set11nPktDurRTSCTS(series, 1); - - ads->ds_ctl5 = set11nPktDurRTSCTS(series, 2) - | set11nPktDurRTSCTS(series, 3); - - ads->ds_ctl7 = set11nRateFlags(series, 0) - | set11nRateFlags(series, 1) - | set11nRateFlags(series, 2) - | set11nRateFlags(series, 3) - | SM(rtsctsRate, AR_RTSCTSRate); - last_ads->ds_ctl2 = ads->ds_ctl2; - last_ads->ds_ctl3 = ads->ds_ctl3; -} - -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, - u32 aggrLen) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - ads->ds_ctl6 &= ~AR_AggrLen; - ads->ds_ctl6 |= SM(aggrLen, AR_AggrLen); -} - -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, - u32 numDelims) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - unsigned int ctl6; - - ads->ds_ctl1 |= (AR_IsAggr | AR_MoreAggr); - - ctl6 = ads->ds_ctl6; - ctl6 &= ~AR_PadDelim; - ctl6 |= SM(numDelims, AR_PadDelim); - ads->ds_ctl6 = ctl6; -} - -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 |= AR_IsAggr; - ads->ds_ctl1 &= ~AR_MoreAggr; - ads->ds_ctl6 &= ~AR_PadDelim; -} - -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl1 &= (~AR_IsAggr & ~AR_MoreAggr); -} - -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, - u32 burstDuration) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - ads->ds_ctl2 &= ~AR_BurstDur; - ads->ds_ctl2 |= SM(burstDuration, AR_BurstDur); -} - -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, - u32 vmf) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - - if (vmf) - ads->ds_ctl0 |= AR_VirtMoreFrag; - else - ads->ds_ctl0 &= ~AR_VirtMoreFrag; -} - -void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) -{ - *txqs &= ah->intr_txqs; - ah->intr_txqs &= ~(*txqs); -} - -bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, - const struct ath9k_tx_queue_info *qinfo) -{ - u32 cw; - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set TXQ properties, " - "inactive queue: %u\n", q); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Set queue properties for: %u\n", q); - - qi->tqi_ver = qinfo->tqi_ver; - qi->tqi_subtype = qinfo->tqi_subtype; - qi->tqi_qflags = qinfo->tqi_qflags; - qi->tqi_priority = qinfo->tqi_priority; - if (qinfo->tqi_aifs != ATH9K_TXQ_USEDEFAULT) - qi->tqi_aifs = min(qinfo->tqi_aifs, 255U); - else - qi->tqi_aifs = INIT_AIFS; - if (qinfo->tqi_cwmin != ATH9K_TXQ_USEDEFAULT) { - cw = min(qinfo->tqi_cwmin, 1024U); - qi->tqi_cwmin = 1; - while (qi->tqi_cwmin < cw) - qi->tqi_cwmin = (qi->tqi_cwmin << 1) | 1; - } else - qi->tqi_cwmin = qinfo->tqi_cwmin; - if (qinfo->tqi_cwmax != ATH9K_TXQ_USEDEFAULT) { - cw = min(qinfo->tqi_cwmax, 1024U); - qi->tqi_cwmax = 1; - while (qi->tqi_cwmax < cw) - qi->tqi_cwmax = (qi->tqi_cwmax << 1) | 1; - } else - qi->tqi_cwmax = INIT_CWMAX; - - if (qinfo->tqi_shretry != 0) - qi->tqi_shretry = min((u32) qinfo->tqi_shretry, 15U); - else - qi->tqi_shretry = INIT_SH_RETRY; - if (qinfo->tqi_lgretry != 0) - qi->tqi_lgretry = min((u32) qinfo->tqi_lgretry, 15U); - else - qi->tqi_lgretry = INIT_LG_RETRY; - qi->tqi_cbrPeriod = qinfo->tqi_cbrPeriod; - qi->tqi_cbrOverflowLimit = qinfo->tqi_cbrOverflowLimit; - qi->tqi_burstTime = qinfo->tqi_burstTime; - qi->tqi_readyTime = qinfo->tqi_readyTime; - - switch (qinfo->tqi_subtype) { - case ATH9K_WME_UPSD: - if (qi->tqi_type == ATH9K_TX_QUEUE_DATA) - qi->tqi_intFlags = ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS; - break; - default: - break; - } - - return true; -} - -bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, - struct ath9k_tx_queue_info *qinfo) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Get TXQ properties, " - "inactive queue: %u\n", q); - return false; - } - - qinfo->tqi_qflags = qi->tqi_qflags; - qinfo->tqi_ver = qi->tqi_ver; - qinfo->tqi_subtype = qi->tqi_subtype; - qinfo->tqi_qflags = qi->tqi_qflags; - qinfo->tqi_priority = qi->tqi_priority; - qinfo->tqi_aifs = qi->tqi_aifs; - qinfo->tqi_cwmin = qi->tqi_cwmin; - qinfo->tqi_cwmax = qi->tqi_cwmax; - qinfo->tqi_shretry = qi->tqi_shretry; - qinfo->tqi_lgretry = qi->tqi_lgretry; - qinfo->tqi_cbrPeriod = qi->tqi_cbrPeriod; - qinfo->tqi_cbrOverflowLimit = qi->tqi_cbrOverflowLimit; - qinfo->tqi_burstTime = qi->tqi_burstTime; - qinfo->tqi_readyTime = qi->tqi_readyTime; - - return true; -} - -int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, - const struct ath9k_tx_queue_info *qinfo) -{ - struct ath9k_tx_queue_info *qi; - struct ath9k_hw_capabilities *pCap = &ah->caps; - int q; - - switch (type) { - case ATH9K_TX_QUEUE_BEACON: - q = pCap->total_queues - 1; - break; - case ATH9K_TX_QUEUE_CAB: - q = pCap->total_queues - 2; - break; - case ATH9K_TX_QUEUE_PSPOLL: - q = 1; - break; - case ATH9K_TX_QUEUE_UAPSD: - q = pCap->total_queues - 3; - break; - case ATH9K_TX_QUEUE_DATA: - for (q = 0; q < pCap->total_queues; q++) - if (ah->txq[q].tqi_type == - ATH9K_TX_QUEUE_INACTIVE) - break; - if (q == pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "No available TX queue\n"); - return -1; - } - break; - default: - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, "Invalid TX queue type: %u\n", - type); - return -1; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Setup TX queue: %u\n", q); - - qi = &ah->txq[q]; - if (qi->tqi_type != ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "TX queue: %u already active\n", q); - return -1; - } - memset(qi, 0, sizeof(struct ath9k_tx_queue_info)); - qi->tqi_type = type; - if (qinfo == NULL) { - qi->tqi_qflags = - TXQ_FLAG_TXOKINT_ENABLE - | TXQ_FLAG_TXERRINT_ENABLE - | TXQ_FLAG_TXDESCINT_ENABLE | TXQ_FLAG_TXURNINT_ENABLE; - qi->tqi_aifs = INIT_AIFS; - qi->tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi->tqi_cwmax = INIT_CWMAX; - qi->tqi_shretry = INIT_SH_RETRY; - qi->tqi_lgretry = INIT_LG_RETRY; - qi->tqi_physCompBuf = 0; - } else { - qi->tqi_physCompBuf = qinfo->tqi_physCompBuf; - (void) ath9k_hw_set_txq_props(ah, q, qinfo); - } - - return q; -} - -bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_tx_queue_info *qi; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " - "invalid queue: %u\n", q); - return false; - } - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TXQ, " - "inactive queue: %u\n", q); - return false; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Release TX queue: %u\n", q); - - qi->tqi_type = ATH9K_TX_QUEUE_INACTIVE; - ah->txok_interrupt_mask &= ~(1 << q); - ah->txerr_interrupt_mask &= ~(1 << q); - ah->txdesc_interrupt_mask &= ~(1 << q); - ah->txeol_interrupt_mask &= ~(1 << q); - ah->txurn_interrupt_mask &= ~(1 << q); - ath9k_hw_set_txq_interrupts(ah, qi); - - return true; -} - -bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) -{ - struct ath9k_hw_capabilities *pCap = &ah->caps; - struct ath9k_channel *chan = ah->curchan; - struct ath9k_tx_queue_info *qi; - u32 cwMin, chanCwMin, value; - - if (q >= pCap->total_queues) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " - "invalid queue: %u\n", q); - return false; - } - - qi = &ah->txq[q]; - if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TXQ, " - "inactive queue: %u\n", q); - return true; - } - - DPRINTF(ah->ah_sc, ATH_DBG_QUEUE, "Reset TX queue: %u\n", q); - - if (qi->tqi_cwmin == ATH9K_TXQ_USEDEFAULT) { - if (chan && IS_CHAN_B(chan)) - chanCwMin = INIT_CWMIN_11B; - else - chanCwMin = INIT_CWMIN; - - for (cwMin = 1; cwMin < chanCwMin; cwMin = (cwMin << 1) | 1); - } else - cwMin = qi->tqi_cwmin; - - REG_WRITE(ah, AR_DLCL_IFS(q), - SM(cwMin, AR_D_LCL_IFS_CWMIN) | - SM(qi->tqi_cwmax, AR_D_LCL_IFS_CWMAX) | - SM(qi->tqi_aifs, AR_D_LCL_IFS_AIFS)); - - REG_WRITE(ah, AR_DRETRY_LIMIT(q), - SM(INIT_SSH_RETRY, AR_D_RETRY_LIMIT_STA_SH) | - SM(INIT_SLG_RETRY, AR_D_RETRY_LIMIT_STA_LG) | - SM(qi->tqi_shretry, AR_D_RETRY_LIMIT_FR_SH)); - - REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); - REG_WRITE(ah, AR_DMISC(q), - AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x2); - - if (qi->tqi_cbrPeriod) { - REG_WRITE(ah, AR_QCBRCFG(q), - SM(qi->tqi_cbrPeriod, AR_Q_CBRCFG_INTERVAL) | - SM(qi->tqi_cbrOverflowLimit, AR_Q_CBRCFG_OVF_THRESH)); - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_FSP_CBR | - (qi->tqi_cbrOverflowLimit ? - AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN : 0)); - } - if (qi->tqi_readyTime && (qi->tqi_type != ATH9K_TX_QUEUE_CAB)) { - REG_WRITE(ah, AR_QRDYTIMECFG(q), - SM(qi->tqi_readyTime, AR_Q_RDYTIMECFG_DURATION) | - AR_Q_RDYTIMECFG_EN); - } - - REG_WRITE(ah, AR_DCHNTIME(q), - SM(qi->tqi_burstTime, AR_D_CHNTIME_DUR) | - (qi->tqi_burstTime ? AR_D_CHNTIME_EN : 0)); - - if (qi->tqi_burstTime - && (qi->tqi_qflags & TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE)) { - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | - AR_Q_MISC_RDYTIME_EXP_POLICY); - - } - - if (qi->tqi_qflags & TXQ_FLAG_BACKOFF_DISABLE) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_POST_FR_BKOFF_DIS); - } - if (qi->tqi_qflags & TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_FRAG_BKOFF_EN); - } - switch (qi->tqi_type) { - case ATH9K_TX_QUEUE_BEACON: - REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) - | AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_BEACON_USE - | AR_Q_MISC_CBR_INCR_DIS1); - - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) - | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << - AR_D_MISC_ARB_LOCKOUT_CNTRL_S) - | AR_D_MISC_BEACON_USE - | AR_D_MISC_POST_FR_BKOFF_DIS); - break; - case ATH9K_TX_QUEUE_CAB: - REG_WRITE(ah, AR_QMISC(q), REG_READ(ah, AR_QMISC(q)) - | AR_Q_MISC_FSP_DBA_GATED - | AR_Q_MISC_CBR_INCR_DIS1 - | AR_Q_MISC_CBR_INCR_DIS0); - value = (qi->tqi_readyTime - - (ah->config.sw_beacon_response_time - - ah->config.dma_beacon_response_time) - - ah->config.additional_swba_backoff) * 1024; - REG_WRITE(ah, AR_QRDYTIMECFG(q), - value | AR_Q_RDYTIMECFG_EN); - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) - | (AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL << - AR_D_MISC_ARB_LOCKOUT_CNTRL_S)); - break; - case ATH9K_TX_QUEUE_PSPOLL: - REG_WRITE(ah, AR_QMISC(q), - REG_READ(ah, AR_QMISC(q)) | AR_Q_MISC_CBR_INCR_DIS1); - break; - case ATH9K_TX_QUEUE_UAPSD: - REG_WRITE(ah, AR_DMISC(q), REG_READ(ah, AR_DMISC(q)) | - AR_D_MISC_POST_FR_BKOFF_DIS); - break; - default: - break; - } - - if (qi->tqi_intFlags & ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS) { - REG_WRITE(ah, AR_DMISC(q), - REG_READ(ah, AR_DMISC(q)) | - SM(AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL, - AR_D_MISC_ARB_LOCKOUT_CNTRL) | - AR_D_MISC_POST_FR_BKOFF_DIS); - } - - if (qi->tqi_qflags & TXQ_FLAG_TXOKINT_ENABLE) - ah->txok_interrupt_mask |= 1 << q; - else - ah->txok_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXERRINT_ENABLE) - ah->txerr_interrupt_mask |= 1 << q; - else - ah->txerr_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXDESCINT_ENABLE) - ah->txdesc_interrupt_mask |= 1 << q; - else - ah->txdesc_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXEOLINT_ENABLE) - ah->txeol_interrupt_mask |= 1 << q; - else - ah->txeol_interrupt_mask &= ~(1 << q); - if (qi->tqi_qflags & TXQ_FLAG_TXURNINT_ENABLE) - ah->txurn_interrupt_mask |= 1 << q; - else - ah->txurn_interrupt_mask &= ~(1 << q); - ath9k_hw_set_txq_interrupts(ah, qi); - - return true; -} - -int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pa, struct ath_desc *nds, u64 tsf) -{ - struct ar5416_desc ads; - struct ar5416_desc *adsp = AR5416DESC(ds); - u32 phyerr; - - if ((adsp->ds_rxstatus8 & AR_RxDone) == 0) - return -EINPROGRESS; - - ads.u.rx = adsp->u.rx; - - ds->ds_rxstat.rs_status = 0; - ds->ds_rxstat.rs_flags = 0; - - ds->ds_rxstat.rs_datalen = ads.ds_rxstatus1 & AR_DataLen; - ds->ds_rxstat.rs_tstamp = ads.AR_RcvTimestamp; - - if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) { - ds->ds_rxstat.rs_rssi = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ctl0 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ctl1 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ctl2 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ext0 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ext1 = ATH9K_RSSI_BAD; - ds->ds_rxstat.rs_rssi_ext2 = ATH9K_RSSI_BAD; - } else { - ds->ds_rxstat.rs_rssi = MS(ads.ds_rxstatus4, AR_RxRSSICombined); - ds->ds_rxstat.rs_rssi_ctl0 = MS(ads.ds_rxstatus0, - AR_RxRSSIAnt00); - ds->ds_rxstat.rs_rssi_ctl1 = MS(ads.ds_rxstatus0, - AR_RxRSSIAnt01); - ds->ds_rxstat.rs_rssi_ctl2 = MS(ads.ds_rxstatus0, - AR_RxRSSIAnt02); - ds->ds_rxstat.rs_rssi_ext0 = MS(ads.ds_rxstatus4, - AR_RxRSSIAnt10); - ds->ds_rxstat.rs_rssi_ext1 = MS(ads.ds_rxstatus4, - AR_RxRSSIAnt11); - ds->ds_rxstat.rs_rssi_ext2 = MS(ads.ds_rxstatus4, - AR_RxRSSIAnt12); - } - if (ads.ds_rxstatus8 & AR_RxKeyIdxValid) - ds->ds_rxstat.rs_keyix = MS(ads.ds_rxstatus8, AR_KeyIdx); - else - ds->ds_rxstat.rs_keyix = ATH9K_RXKEYIX_INVALID; - - ds->ds_rxstat.rs_rate = RXSTATUS_RATE(ah, (&ads)); - ds->ds_rxstat.rs_more = (ads.ds_rxstatus1 & AR_RxMore) ? 1 : 0; - - ds->ds_rxstat.rs_isaggr = (ads.ds_rxstatus8 & AR_RxAggr) ? 1 : 0; - ds->ds_rxstat.rs_moreaggr = - (ads.ds_rxstatus8 & AR_RxMoreAggr) ? 1 : 0; - ds->ds_rxstat.rs_antenna = MS(ads.ds_rxstatus3, AR_RxAntenna); - ds->ds_rxstat.rs_flags = - (ads.ds_rxstatus3 & AR_GI) ? ATH9K_RX_GI : 0; - ds->ds_rxstat.rs_flags |= - (ads.ds_rxstatus3 & AR_2040) ? ATH9K_RX_2040 : 0; - - if (ads.ds_rxstatus8 & AR_PreDelimCRCErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_PRE; - if (ads.ds_rxstatus8 & AR_PostDelimCRCErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DELIM_CRC_POST; - if (ads.ds_rxstatus8 & AR_DecryptBusyErr) - ds->ds_rxstat.rs_flags |= ATH9K_RX_DECRYPT_BUSY; - - if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) { - if (ads.ds_rxstatus8 & AR_CRCErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_CRC; - else if (ads.ds_rxstatus8 & AR_PHYErr) { - ds->ds_rxstat.rs_status |= ATH9K_RXERR_PHY; - phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode); - ds->ds_rxstat.rs_phyerr = phyerr; - } else if (ads.ds_rxstatus8 & AR_DecryptCRCErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_DECRYPT; - else if (ads.ds_rxstatus8 & AR_MichaelErr) - ds->ds_rxstat.rs_status |= ATH9K_RXERR_MIC; - } - - return 0; -} - -void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 size, u32 flags) -{ - struct ar5416_desc *ads = AR5416DESC(ds); - struct ath9k_hw_capabilities *pCap = &ah->caps; - - ads->ds_ctl1 = size & AR_BufLen; - if (flags & ATH9K_RXDESC_INTREQ) - ads->ds_ctl1 |= AR_RxIntrReq; - - ads->ds_rxstatus8 &= ~AR_RxDone; - if (!(pCap->hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - memset(&(ads->u), 0, sizeof(ads->u)); -} - -bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) -{ - u32 reg; - - if (set) { - REG_SET_BIT(ah, AR_DIAG_SW, - (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - - if (!ath9k_hw_wait(ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, - 0, AH_WAIT_TIMEOUT)) { - REG_CLR_BIT(ah, AR_DIAG_SW, - (AR_DIAG_RX_DIS | - AR_DIAG_RX_ABORT)); - - reg = REG_READ(ah, AR_OBS_BUS_1); - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "RX failed to go idle in 10 ms RXSM=0x%x\n", reg); - - return false; - } - } else { - REG_CLR_BIT(ah, AR_DIAG_SW, - (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); - } - - return true; -} - -void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp) -{ - REG_WRITE(ah, AR_RXDP, rxdp); -} - -void ath9k_hw_rxena(struct ath_hw *ah) -{ - REG_WRITE(ah, AR_CR, AR_CR_RXE); -} - -void ath9k_hw_startpcureceive(struct ath_hw *ah) -{ - ath9k_enable_mib_counters(ah); - - ath9k_ani_reset(ah); - - REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT)); -} - -void ath9k_hw_stoppcurecv(struct ath_hw *ah) -{ - REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS); - - ath9k_hw_disable_mib_counters(ah); -} - -bool ath9k_hw_stopdmarecv(struct ath_hw *ah) -{ -#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ -#define AH_RX_TIME_QUANTUM 100 /* usec */ - - int i; - - REG_WRITE(ah, AR_CR, AR_CR_RXD); - - /* Wait for rx enable bit to go low */ - for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { - if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) - break; - udelay(AH_TIME_QUANTUM); - } - - if (i == 0) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "DMA failed to stop in %d ms " - "AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", - AH_RX_STOP_DMA_TIMEOUT / 1000, - REG_READ(ah, AR_CR), - REG_READ(ah, AR_DIAG_SW)); - return false; - } else { - return true; - } - -#undef AH_RX_TIME_QUANTUM -#undef AH_RX_STOP_DMA_TIMEOUT -} diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h deleted file mode 100644 index 9720c4dc9599..000000000000 --- a/drivers/net/wireless/ath/ath9k/mac.h +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef MAC_H -#define MAC_H - -#define RXSTATUS_RATE(ah, ads) (AR_SREV_5416_20_OR_LATER(ah) ? \ - MS(ads->ds_rxstatus0, AR_RxRate) : \ - (ads->ds_rxstatus3 >> 2) & 0xFF) - -#define set11nTries(_series, _index) \ - (SM((_series)[_index].Tries, AR_XmitDataTries##_index)) - -#define set11nRate(_series, _index) \ - (SM((_series)[_index].Rate, AR_XmitRate##_index)) - -#define set11nPktDurRTSCTS(_series, _index) \ - (SM((_series)[_index].PktDuration, AR_PacketDur##_index) | \ - ((_series)[_index].RateFlags & ATH9K_RATESERIES_RTS_CTS ? \ - AR_RTSCTSQual##_index : 0)) - -#define set11nRateFlags(_series, _index) \ - (((_series)[_index].RateFlags & ATH9K_RATESERIES_2040 ? \ - AR_2040_##_index : 0) \ - |((_series)[_index].RateFlags & ATH9K_RATESERIES_HALFGI ? \ - AR_GI##_index : 0) \ - |SM((_series)[_index].ChSel, AR_ChainSel##_index)) - -#define CCK_SIFS_TIME 10 -#define CCK_PREAMBLE_BITS 144 -#define CCK_PLCP_BITS 48 - -#define OFDM_SIFS_TIME 16 -#define OFDM_PREAMBLE_TIME 20 -#define OFDM_PLCP_BITS 22 -#define OFDM_SYMBOL_TIME 4 - -#define OFDM_SIFS_TIME_HALF 32 -#define OFDM_PREAMBLE_TIME_HALF 40 -#define OFDM_PLCP_BITS_HALF 22 -#define OFDM_SYMBOL_TIME_HALF 8 - -#define OFDM_SIFS_TIME_QUARTER 64 -#define OFDM_PREAMBLE_TIME_QUARTER 80 -#define OFDM_PLCP_BITS_QUARTER 22 -#define OFDM_SYMBOL_TIME_QUARTER 16 - -#define INIT_AIFS 2 -#define INIT_CWMIN 15 -#define INIT_CWMIN_11B 31 -#define INIT_CWMAX 1023 -#define INIT_SH_RETRY 10 -#define INIT_LG_RETRY 10 -#define INIT_SSH_RETRY 32 -#define INIT_SLG_RETRY 32 - -#define ATH9K_SLOT_TIME_6 6 -#define ATH9K_SLOT_TIME_9 9 -#define ATH9K_SLOT_TIME_20 20 - -#define ATH9K_TXERR_XRETRY 0x01 -#define ATH9K_TXERR_FILT 0x02 -#define ATH9K_TXERR_FIFO 0x04 -#define ATH9K_TXERR_XTXOP 0x08 -#define ATH9K_TXERR_TIMER_EXPIRED 0x10 -#define ATH9K_TX_ACKED 0x20 -#define ATH9K_TXERR_MASK \ - (ATH9K_TXERR_XRETRY | ATH9K_TXERR_FILT | ATH9K_TXERR_FIFO | \ - ATH9K_TXERR_XTXOP | ATH9K_TXERR_TIMER_EXPIRED) - -#define ATH9K_TX_BA 0x01 -#define ATH9K_TX_PWRMGMT 0x02 -#define ATH9K_TX_DESC_CFG_ERR 0x04 -#define ATH9K_TX_DATA_UNDERRUN 0x08 -#define ATH9K_TX_DELIM_UNDERRUN 0x10 -#define ATH9K_TX_SW_ABORTED 0x40 -#define ATH9K_TX_SW_FILTERED 0x80 - -#define MIN_TX_FIFO_THRESHOLD 0x1 -#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) -#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD - -struct ath_tx_status { - u32 ts_tstamp; - u16 ts_seqnum; - u8 ts_status; - u8 ts_ratecode; - u8 ts_rateindex; - int8_t ts_rssi; - u8 ts_shortretry; - u8 ts_longretry; - u8 ts_virtcol; - u8 ts_antenna; - u8 ts_flags; - int8_t ts_rssi_ctl0; - int8_t ts_rssi_ctl1; - int8_t ts_rssi_ctl2; - int8_t ts_rssi_ext0; - int8_t ts_rssi_ext1; - int8_t ts_rssi_ext2; - u8 pad[3]; - u32 ba_low; - u32 ba_high; - u32 evm0; - u32 evm1; - u32 evm2; -}; - -struct ath_rx_status { - u32 rs_tstamp; - u16 rs_datalen; - u8 rs_status; - u8 rs_phyerr; - int8_t rs_rssi; - u8 rs_keyix; - u8 rs_rate; - u8 rs_antenna; - u8 rs_more; - int8_t rs_rssi_ctl0; - int8_t rs_rssi_ctl1; - int8_t rs_rssi_ctl2; - int8_t rs_rssi_ext0; - int8_t rs_rssi_ext1; - int8_t rs_rssi_ext2; - u8 rs_isaggr; - u8 rs_moreaggr; - u8 rs_num_delims; - u8 rs_flags; - u32 evm0; - u32 evm1; - u32 evm2; -}; - -#define ATH9K_RXERR_CRC 0x01 -#define ATH9K_RXERR_PHY 0x02 -#define ATH9K_RXERR_FIFO 0x04 -#define ATH9K_RXERR_DECRYPT 0x08 -#define ATH9K_RXERR_MIC 0x10 - -#define ATH9K_RX_MORE 0x01 -#define ATH9K_RX_MORE_AGGR 0x02 -#define ATH9K_RX_GI 0x04 -#define ATH9K_RX_2040 0x08 -#define ATH9K_RX_DELIM_CRC_PRE 0x10 -#define ATH9K_RX_DELIM_CRC_POST 0x20 -#define ATH9K_RX_DECRYPT_BUSY 0x40 - -#define ATH9K_RXKEYIX_INVALID ((u8)-1) -#define ATH9K_TXKEYIX_INVALID ((u32)-1) - -struct ath_desc { - u32 ds_link; - u32 ds_data; - u32 ds_ctl0; - u32 ds_ctl1; - u32 ds_hw[20]; - union { - struct ath_tx_status tx; - struct ath_rx_status rx; - void *stats; - } ds_us; - void *ds_vdata; -} __packed; - -#define ds_txstat ds_us.tx -#define ds_rxstat ds_us.rx -#define ds_stat ds_us.stats - -#define ATH9K_TXDESC_CLRDMASK 0x0001 -#define ATH9K_TXDESC_NOACK 0x0002 -#define ATH9K_TXDESC_RTSENA 0x0004 -#define ATH9K_TXDESC_CTSENA 0x0008 -/* ATH9K_TXDESC_INTREQ forces a tx interrupt to be generated for - * the descriptor its marked on. We take a tx interrupt to reap - * descriptors when the h/w hits an EOL condition or - * when the descriptor is specifically marked to generate - * an interrupt with this flag. Descriptors should be - * marked periodically to insure timely replenishing of the - * supply needed for sending frames. Defering interrupts - * reduces system load and potentially allows more concurrent - * work to be done but if done to aggressively can cause - * senders to backup. When the hardware queue is left too - * large rate control information may also be too out of - * date. An Alternative for this is TX interrupt mitigation - * but this needs more testing. */ -#define ATH9K_TXDESC_INTREQ 0x0010 -#define ATH9K_TXDESC_VEOL 0x0020 -#define ATH9K_TXDESC_EXT_ONLY 0x0040 -#define ATH9K_TXDESC_EXT_AND_CTL 0x0080 -#define ATH9K_TXDESC_VMF 0x0100 -#define ATH9K_TXDESC_FRAG_IS_ON 0x0200 -#define ATH9K_TXDESC_CAB 0x0400 - -#define ATH9K_RXDESC_INTREQ 0x0020 - -struct ar5416_desc { - u32 ds_link; - u32 ds_data; - u32 ds_ctl0; - u32 ds_ctl1; - union { - struct { - u32 ctl2; - u32 ctl3; - u32 ctl4; - u32 ctl5; - u32 ctl6; - u32 ctl7; - u32 ctl8; - u32 ctl9; - u32 ctl10; - u32 ctl11; - u32 status0; - u32 status1; - u32 status2; - u32 status3; - u32 status4; - u32 status5; - u32 status6; - u32 status7; - u32 status8; - u32 status9; - } tx; - struct { - u32 status0; - u32 status1; - u32 status2; - u32 status3; - u32 status4; - u32 status5; - u32 status6; - u32 status7; - u32 status8; - } rx; - } u; -} __packed; - -#define AR5416DESC(_ds) ((struct ar5416_desc *)(_ds)) -#define AR5416DESC_CONST(_ds) ((const struct ar5416_desc *)(_ds)) - -#define ds_ctl2 u.tx.ctl2 -#define ds_ctl3 u.tx.ctl3 -#define ds_ctl4 u.tx.ctl4 -#define ds_ctl5 u.tx.ctl5 -#define ds_ctl6 u.tx.ctl6 -#define ds_ctl7 u.tx.ctl7 -#define ds_ctl8 u.tx.ctl8 -#define ds_ctl9 u.tx.ctl9 -#define ds_ctl10 u.tx.ctl10 -#define ds_ctl11 u.tx.ctl11 - -#define ds_txstatus0 u.tx.status0 -#define ds_txstatus1 u.tx.status1 -#define ds_txstatus2 u.tx.status2 -#define ds_txstatus3 u.tx.status3 -#define ds_txstatus4 u.tx.status4 -#define ds_txstatus5 u.tx.status5 -#define ds_txstatus6 u.tx.status6 -#define ds_txstatus7 u.tx.status7 -#define ds_txstatus8 u.tx.status8 -#define ds_txstatus9 u.tx.status9 - -#define ds_rxstatus0 u.rx.status0 -#define ds_rxstatus1 u.rx.status1 -#define ds_rxstatus2 u.rx.status2 -#define ds_rxstatus3 u.rx.status3 -#define ds_rxstatus4 u.rx.status4 -#define ds_rxstatus5 u.rx.status5 -#define ds_rxstatus6 u.rx.status6 -#define ds_rxstatus7 u.rx.status7 -#define ds_rxstatus8 u.rx.status8 - -#define AR_FrameLen 0x00000fff -#define AR_VirtMoreFrag 0x00001000 -#define AR_TxCtlRsvd00 0x0000e000 -#define AR_XmitPower 0x003f0000 -#define AR_XmitPower_S 16 -#define AR_RTSEnable 0x00400000 -#define AR_VEOL 0x00800000 -#define AR_ClrDestMask 0x01000000 -#define AR_TxCtlRsvd01 0x1e000000 -#define AR_TxIntrReq 0x20000000 -#define AR_DestIdxValid 0x40000000 -#define AR_CTSEnable 0x80000000 - -#define AR_BufLen 0x00000fff -#define AR_TxMore 0x00001000 -#define AR_DestIdx 0x000fe000 -#define AR_DestIdx_S 13 -#define AR_FrameType 0x00f00000 -#define AR_FrameType_S 20 -#define AR_NoAck 0x01000000 -#define AR_InsertTS 0x02000000 -#define AR_CorruptFCS 0x04000000 -#define AR_ExtOnly 0x08000000 -#define AR_ExtAndCtl 0x10000000 -#define AR_MoreAggr 0x20000000 -#define AR_IsAggr 0x40000000 - -#define AR_BurstDur 0x00007fff -#define AR_BurstDur_S 0 -#define AR_DurUpdateEna 0x00008000 -#define AR_XmitDataTries0 0x000f0000 -#define AR_XmitDataTries0_S 16 -#define AR_XmitDataTries1 0x00f00000 -#define AR_XmitDataTries1_S 20 -#define AR_XmitDataTries2 0x0f000000 -#define AR_XmitDataTries2_S 24 -#define AR_XmitDataTries3 0xf0000000 -#define AR_XmitDataTries3_S 28 - -#define AR_XmitRate0 0x000000ff -#define AR_XmitRate0_S 0 -#define AR_XmitRate1 0x0000ff00 -#define AR_XmitRate1_S 8 -#define AR_XmitRate2 0x00ff0000 -#define AR_XmitRate2_S 16 -#define AR_XmitRate3 0xff000000 -#define AR_XmitRate3_S 24 - -#define AR_PacketDur0 0x00007fff -#define AR_PacketDur0_S 0 -#define AR_RTSCTSQual0 0x00008000 -#define AR_PacketDur1 0x7fff0000 -#define AR_PacketDur1_S 16 -#define AR_RTSCTSQual1 0x80000000 - -#define AR_PacketDur2 0x00007fff -#define AR_PacketDur2_S 0 -#define AR_RTSCTSQual2 0x00008000 -#define AR_PacketDur3 0x7fff0000 -#define AR_PacketDur3_S 16 -#define AR_RTSCTSQual3 0x80000000 - -#define AR_AggrLen 0x0000ffff -#define AR_AggrLen_S 0 -#define AR_TxCtlRsvd60 0x00030000 -#define AR_PadDelim 0x03fc0000 -#define AR_PadDelim_S 18 -#define AR_EncrType 0x0c000000 -#define AR_EncrType_S 26 -#define AR_TxCtlRsvd61 0xf0000000 - -#define AR_2040_0 0x00000001 -#define AR_GI0 0x00000002 -#define AR_ChainSel0 0x0000001c -#define AR_ChainSel0_S 2 -#define AR_2040_1 0x00000020 -#define AR_GI1 0x00000040 -#define AR_ChainSel1 0x00000380 -#define AR_ChainSel1_S 7 -#define AR_2040_2 0x00000400 -#define AR_GI2 0x00000800 -#define AR_ChainSel2 0x00007000 -#define AR_ChainSel2_S 12 -#define AR_2040_3 0x00008000 -#define AR_GI3 0x00010000 -#define AR_ChainSel3 0x000e0000 -#define AR_ChainSel3_S 17 -#define AR_RTSCTSRate 0x0ff00000 -#define AR_RTSCTSRate_S 20 -#define AR_TxCtlRsvd70 0xf0000000 - -#define AR_TxRSSIAnt00 0x000000ff -#define AR_TxRSSIAnt00_S 0 -#define AR_TxRSSIAnt01 0x0000ff00 -#define AR_TxRSSIAnt01_S 8 -#define AR_TxRSSIAnt02 0x00ff0000 -#define AR_TxRSSIAnt02_S 16 -#define AR_TxStatusRsvd00 0x3f000000 -#define AR_TxBaStatus 0x40000000 -#define AR_TxStatusRsvd01 0x80000000 - -#define AR_FrmXmitOK 0x00000001 -#define AR_ExcessiveRetries 0x00000002 -#define AR_FIFOUnderrun 0x00000004 -#define AR_Filtered 0x00000008 -#define AR_RTSFailCnt 0x000000f0 -#define AR_RTSFailCnt_S 4 -#define AR_DataFailCnt 0x00000f00 -#define AR_DataFailCnt_S 8 -#define AR_VirtRetryCnt 0x0000f000 -#define AR_VirtRetryCnt_S 12 -#define AR_TxDelimUnderrun 0x00010000 -#define AR_TxDataUnderrun 0x00020000 -#define AR_DescCfgErr 0x00040000 -#define AR_TxTimerExpired 0x00080000 -#define AR_TxStatusRsvd10 0xfff00000 - -#define AR_SendTimestamp ds_txstatus2 -#define AR_BaBitmapLow ds_txstatus3 -#define AR_BaBitmapHigh ds_txstatus4 - -#define AR_TxRSSIAnt10 0x000000ff -#define AR_TxRSSIAnt10_S 0 -#define AR_TxRSSIAnt11 0x0000ff00 -#define AR_TxRSSIAnt11_S 8 -#define AR_TxRSSIAnt12 0x00ff0000 -#define AR_TxRSSIAnt12_S 16 -#define AR_TxRSSICombined 0xff000000 -#define AR_TxRSSICombined_S 24 - -#define AR_TxEVM0 ds_txstatus5 -#define AR_TxEVM1 ds_txstatus6 -#define AR_TxEVM2 ds_txstatus7 - -#define AR_TxDone 0x00000001 -#define AR_SeqNum 0x00001ffe -#define AR_SeqNum_S 1 -#define AR_TxStatusRsvd80 0x0001e000 -#define AR_TxOpExceeded 0x00020000 -#define AR_TxStatusRsvd81 0x001c0000 -#define AR_FinalTxIdx 0x00600000 -#define AR_FinalTxIdx_S 21 -#define AR_TxStatusRsvd82 0x01800000 -#define AR_PowerMgmt 0x02000000 -#define AR_TxStatusRsvd83 0xfc000000 - -#define AR_RxCTLRsvd00 0xffffffff - -#define AR_BufLen 0x00000fff -#define AR_RxCtlRsvd00 0x00001000 -#define AR_RxIntrReq 0x00002000 -#define AR_RxCtlRsvd01 0xffffc000 - -#define AR_RxRSSIAnt00 0x000000ff -#define AR_RxRSSIAnt00_S 0 -#define AR_RxRSSIAnt01 0x0000ff00 -#define AR_RxRSSIAnt01_S 8 -#define AR_RxRSSIAnt02 0x00ff0000 -#define AR_RxRSSIAnt02_S 16 -#define AR_RxRate 0xff000000 -#define AR_RxRate_S 24 -#define AR_RxStatusRsvd00 0xff000000 - -#define AR_DataLen 0x00000fff -#define AR_RxMore 0x00001000 -#define AR_NumDelim 0x003fc000 -#define AR_NumDelim_S 14 -#define AR_RxStatusRsvd10 0xff800000 - -#define AR_RcvTimestamp ds_rxstatus2 - -#define AR_GI 0x00000001 -#define AR_2040 0x00000002 -#define AR_Parallel40 0x00000004 -#define AR_Parallel40_S 2 -#define AR_RxStatusRsvd30 0x000000f8 -#define AR_RxAntenna 0xffffff00 -#define AR_RxAntenna_S 8 - -#define AR_RxRSSIAnt10 0x000000ff -#define AR_RxRSSIAnt10_S 0 -#define AR_RxRSSIAnt11 0x0000ff00 -#define AR_RxRSSIAnt11_S 8 -#define AR_RxRSSIAnt12 0x00ff0000 -#define AR_RxRSSIAnt12_S 16 -#define AR_RxRSSICombined 0xff000000 -#define AR_RxRSSICombined_S 24 - -#define AR_RxEVM0 ds_rxstatus4 -#define AR_RxEVM1 ds_rxstatus5 -#define AR_RxEVM2 ds_rxstatus6 - -#define AR_RxDone 0x00000001 -#define AR_RxFrameOK 0x00000002 -#define AR_CRCErr 0x00000004 -#define AR_DecryptCRCErr 0x00000008 -#define AR_PHYErr 0x00000010 -#define AR_MichaelErr 0x00000020 -#define AR_PreDelimCRCErr 0x00000040 -#define AR_RxStatusRsvd70 0x00000080 -#define AR_RxKeyIdxValid 0x00000100 -#define AR_KeyIdx 0x0000fe00 -#define AR_KeyIdx_S 9 -#define AR_PHYErrCode 0x0000ff00 -#define AR_PHYErrCode_S 8 -#define AR_RxMoreAggr 0x00010000 -#define AR_RxAggr 0x00020000 -#define AR_PostDelimCRCErr 0x00040000 -#define AR_RxStatusRsvd71 0x3ff80000 -#define AR_DecryptBusyErr 0x40000000 -#define AR_KeyMiss 0x80000000 - -enum ath9k_tx_queue { - ATH9K_TX_QUEUE_INACTIVE = 0, - ATH9K_TX_QUEUE_DATA, - ATH9K_TX_QUEUE_BEACON, - ATH9K_TX_QUEUE_CAB, - ATH9K_TX_QUEUE_UAPSD, - ATH9K_TX_QUEUE_PSPOLL -}; - -#define ATH9K_NUM_TX_QUEUES 10 - -enum ath9k_tx_queue_subtype { - ATH9K_WME_AC_BK = 0, - ATH9K_WME_AC_BE, - ATH9K_WME_AC_VI, - ATH9K_WME_AC_VO, - ATH9K_WME_UPSD -}; - -enum ath9k_tx_queue_flags { - TXQ_FLAG_TXOKINT_ENABLE = 0x0001, - TXQ_FLAG_TXERRINT_ENABLE = 0x0001, - TXQ_FLAG_TXDESCINT_ENABLE = 0x0002, - TXQ_FLAG_TXEOLINT_ENABLE = 0x0004, - TXQ_FLAG_TXURNINT_ENABLE = 0x0008, - TXQ_FLAG_BACKOFF_DISABLE = 0x0010, - TXQ_FLAG_COMPRESSION_ENABLE = 0x0020, - TXQ_FLAG_RDYTIME_EXP_POLICY_ENABLE = 0x0040, - TXQ_FLAG_FRAG_BURST_BACKOFF_ENABLE = 0x0080, -}; - -#define ATH9K_TXQ_USEDEFAULT ((u32) -1) -#define ATH9K_TXQ_USE_LOCKOUT_BKOFF_DIS 0x00000001 - -#define ATH9K_DECOMP_MASK_SIZE 128 -#define ATH9K_READY_TIME_LO_BOUND 50 -#define ATH9K_READY_TIME_HI_BOUND 96 - -enum ath9k_pkt_type { - ATH9K_PKT_TYPE_NORMAL = 0, - ATH9K_PKT_TYPE_ATIM, - ATH9K_PKT_TYPE_PSPOLL, - ATH9K_PKT_TYPE_BEACON, - ATH9K_PKT_TYPE_PROBE_RESP, - ATH9K_PKT_TYPE_CHIRP, - ATH9K_PKT_TYPE_GRP_POLL, -}; - -struct ath9k_tx_queue_info { - u32 tqi_ver; - enum ath9k_tx_queue tqi_type; - enum ath9k_tx_queue_subtype tqi_subtype; - enum ath9k_tx_queue_flags tqi_qflags; - u32 tqi_priority; - u32 tqi_aifs; - u32 tqi_cwmin; - u32 tqi_cwmax; - u16 tqi_shretry; - u16 tqi_lgretry; - u32 tqi_cbrPeriod; - u32 tqi_cbrOverflowLimit; - u32 tqi_burstTime; - u32 tqi_readyTime; - u32 tqi_physCompBuf; - u32 tqi_intFlags; -}; - -enum ath9k_rx_filter { - ATH9K_RX_FILTER_UCAST = 0x00000001, - ATH9K_RX_FILTER_MCAST = 0x00000002, - ATH9K_RX_FILTER_BCAST = 0x00000004, - ATH9K_RX_FILTER_CONTROL = 0x00000008, - ATH9K_RX_FILTER_BEACON = 0x00000010, - ATH9K_RX_FILTER_PROM = 0x00000020, - ATH9K_RX_FILTER_PROBEREQ = 0x00000080, - ATH9K_RX_FILTER_PHYERR = 0x00000100, - ATH9K_RX_FILTER_MYBEACON = 0x00000200, - ATH9K_RX_FILTER_COMP_BAR = 0x00000400, - ATH9K_RX_FILTER_PSPOLL = 0x00004000, - ATH9K_RX_FILTER_PHYRADAR = 0x00002000, - ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000, -}; - -#define ATH9K_RATESERIES_RTS_CTS 0x0001 -#define ATH9K_RATESERIES_2040 0x0002 -#define ATH9K_RATESERIES_HALFGI 0x0004 - -struct ath9k_11n_rate_series { - u32 Tries; - u32 Rate; - u32 PktDuration; - u32 ChSel; - u32 RateFlags; -}; - -struct ath9k_keyval { - u8 kv_type; - u8 kv_pad; - u16 kv_len; - u8 kv_val[16]; /* TK */ - u8 kv_mic[8]; /* Michael MIC key */ - u8 kv_txmic[8]; /* Michael MIC TX key (used only if the hardware - * supports both MIC keys in the same key cache entry; - * in that case, kv_mic is the RX key) */ -}; - -enum ath9k_key_type { - ATH9K_KEY_TYPE_CLEAR, - ATH9K_KEY_TYPE_WEP, - ATH9K_KEY_TYPE_AES, - ATH9K_KEY_TYPE_TKIP, -}; - -enum ath9k_cipher { - ATH9K_CIPHER_WEP = 0, - ATH9K_CIPHER_AES_OCB = 1, - ATH9K_CIPHER_AES_CCM = 2, - ATH9K_CIPHER_CKIP = 3, - ATH9K_CIPHER_TKIP = 4, - ATH9K_CIPHER_CLR = 5, - ATH9K_CIPHER_MIC = 127 -}; - -enum ath9k_ht_macmode { - ATH9K_HT_MACMODE_20 = 0, - ATH9K_HT_MACMODE_2040 = 1, -}; - -enum ath9k_ht_extprotspacing { - ATH9K_HT_EXTPROTSPACING_20 = 0, - ATH9K_HT_EXTPROTSPACING_25 = 1, -}; - -struct ath_hw; -struct ath9k_channel; -struct ath_rate_table; - -u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); -void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); -void ath9k_hw_txstart(struct ath_hw *ah, u32 q); -u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); -bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); -bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); -void ath9k_hw_filltxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 segLen, bool firstSeg, - bool lastSeg, const struct ath_desc *ds0); -void ath9k_hw_cleartxdesc(struct ath_hw *ah, struct ath_desc *ds); -int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_set11n_txdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pktLen, enum ath9k_pkt_type type, u32 txPower, - u32 keyIx, enum ath9k_key_type keyType, u32 flags); -void ath9k_hw_set11n_ratescenario(struct ath_hw *ah, struct ath_desc *ds, - struct ath_desc *lastds, - u32 durUpdateEn, u32 rtsctsRate, - u32 rtsctsDuration, - struct ath9k_11n_rate_series series[], - u32 nseries, u32 flags); -void ath9k_hw_set11n_aggr_first(struct ath_hw *ah, struct ath_desc *ds, - u32 aggrLen); -void ath9k_hw_set11n_aggr_middle(struct ath_hw *ah, struct ath_desc *ds, - u32 numDelims); -void ath9k_hw_set11n_aggr_last(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_clr11n_aggr(struct ath_hw *ah, struct ath_desc *ds); -void ath9k_hw_set11n_burstduration(struct ath_hw *ah, struct ath_desc *ds, - u32 burstDuration); -void ath9k_hw_set11n_virtualmorefrag(struct ath_hw *ah, struct ath_desc *ds, - u32 vmf); -void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); -bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, - const struct ath9k_tx_queue_info *qinfo); -bool ath9k_hw_get_txq_props(struct ath_hw *ah, int q, - struct ath9k_tx_queue_info *qinfo); -int ath9k_hw_setuptxqueue(struct ath_hw *ah, enum ath9k_tx_queue type, - const struct ath9k_tx_queue_info *qinfo); -bool ath9k_hw_releasetxqueue(struct ath_hw *ah, u32 q); -bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q); -int ath9k_hw_rxprocdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 pa, struct ath_desc *nds, u64 tsf); -void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds, - u32 size, u32 flags); -bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set); -void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); -void ath9k_hw_rxena(struct ath_hw *ah); -void ath9k_hw_startpcureceive(struct ath_hw *ah); -void ath9k_hw_stoppcurecv(struct ath_hw *ah); -bool ath9k_hw_stopdmarecv(struct ath_hw *ah); - -#endif /* MAC_H */ diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c deleted file mode 100644 index 0c349cece951..000000000000 --- a/drivers/net/wireless/ath/ath9k/main.c +++ /dev/null @@ -1,2947 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include "ath9k.h" - -static char *dev_info = "ath9k"; - -MODULE_AUTHOR("Atheros Communications"); -MODULE_DESCRIPTION("Support for Atheros 802.11n wireless LAN cards."); -MODULE_SUPPORTED_DEVICE("Atheros 802.11n WLAN cards"); -MODULE_LICENSE("Dual BSD/GPL"); - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption"); - -/* We use the hw_value as an index into our private channel structure */ - -#define CHAN2G(_freq, _idx) { \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 20, \ -} - -#define CHAN5G(_freq, _idx) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_idx), \ - .max_power = 20, \ -} - -/* Some 2 GHz radios are actually tunable on 2312-2732 - * on 5 MHz steps, we support the channels which we know - * we have calibration data for all cards though to make - * this static */ -static struct ieee80211_channel ath9k_2ghz_chantable[] = { - CHAN2G(2412, 0), /* Channel 1 */ - CHAN2G(2417, 1), /* Channel 2 */ - CHAN2G(2422, 2), /* Channel 3 */ - CHAN2G(2427, 3), /* Channel 4 */ - CHAN2G(2432, 4), /* Channel 5 */ - CHAN2G(2437, 5), /* Channel 6 */ - CHAN2G(2442, 6), /* Channel 7 */ - CHAN2G(2447, 7), /* Channel 8 */ - CHAN2G(2452, 8), /* Channel 9 */ - CHAN2G(2457, 9), /* Channel 10 */ - CHAN2G(2462, 10), /* Channel 11 */ - CHAN2G(2467, 11), /* Channel 12 */ - CHAN2G(2472, 12), /* Channel 13 */ - CHAN2G(2484, 13), /* Channel 14 */ -}; - -/* Some 5 GHz radios are actually tunable on XXXX-YYYY - * on 5 MHz steps, we support the channels which we know - * we have calibration data for all cards though to make - * this static */ -static struct ieee80211_channel ath9k_5ghz_chantable[] = { - /* _We_ call this UNII 1 */ - CHAN5G(5180, 14), /* Channel 36 */ - CHAN5G(5200, 15), /* Channel 40 */ - CHAN5G(5220, 16), /* Channel 44 */ - CHAN5G(5240, 17), /* Channel 48 */ - /* _We_ call this UNII 2 */ - CHAN5G(5260, 18), /* Channel 52 */ - CHAN5G(5280, 19), /* Channel 56 */ - CHAN5G(5300, 20), /* Channel 60 */ - CHAN5G(5320, 21), /* Channel 64 */ - /* _We_ call this "Middle band" */ - CHAN5G(5500, 22), /* Channel 100 */ - CHAN5G(5520, 23), /* Channel 104 */ - CHAN5G(5540, 24), /* Channel 108 */ - CHAN5G(5560, 25), /* Channel 112 */ - CHAN5G(5580, 26), /* Channel 116 */ - CHAN5G(5600, 27), /* Channel 120 */ - CHAN5G(5620, 28), /* Channel 124 */ - CHAN5G(5640, 29), /* Channel 128 */ - CHAN5G(5660, 30), /* Channel 132 */ - CHAN5G(5680, 31), /* Channel 136 */ - CHAN5G(5700, 32), /* Channel 140 */ - /* _We_ call this UNII 3 */ - CHAN5G(5745, 33), /* Channel 149 */ - CHAN5G(5765, 34), /* Channel 153 */ - CHAN5G(5785, 35), /* Channel 157 */ - CHAN5G(5805, 36), /* Channel 161 */ - CHAN5G(5825, 37), /* Channel 165 */ -}; - -static void ath_cache_conf_rate(struct ath_softc *sc, - struct ieee80211_conf *conf) -{ - switch (conf->channel->band) { - case IEEE80211_BAND_2GHZ: - if (conf_is_ht20(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NG_HT20]; - else if (conf_is_ht40_minus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS]; - else if (conf_is_ht40_plus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS]; - else - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11G]; - break; - case IEEE80211_BAND_5GHZ: - if (conf_is_ht20(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NA_HT20]; - else if (conf_is_ht40_minus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS]; - else if (conf_is_ht40_plus(conf)) - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS]; - else - sc->cur_rate_table = - sc->hw_rate_table[ATH9K_MODE_11A]; - break; - default: - BUG_ON(1); - break; - } -} - -static void ath_update_txpow(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - u32 txpow; - - if (sc->curtxpow != sc->config.txpowlimit) { - ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit); - /* read back in case value is clamped */ - ath9k_hw_getcapability(ah, ATH9K_CAP_TXPOW, 1, &txpow); - sc->curtxpow = txpow; - } -} - -static u8 parse_mpdudensity(u8 mpdudensity) -{ - /* - * 802.11n D2.0 defined values for "Minimum MPDU Start Spacing": - * 0 for no restriction - * 1 for 1/4 us - * 2 for 1/2 us - * 3 for 1 us - * 4 for 2 us - * 5 for 4 us - * 6 for 8 us - * 7 for 16 us - */ - switch (mpdudensity) { - case 0: - return 0; - case 1: - case 2: - case 3: - /* Our lower layer calculations limit our precision to - 1 microsecond */ - return 1; - case 4: - return 2; - case 5: - return 4; - case 6: - return 8; - case 7: - return 16; - default: - return 0; - } -} - -static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) -{ - const struct ath_rate_table *rate_table = NULL; - struct ieee80211_supported_band *sband; - struct ieee80211_rate *rate; - int i, maxrates; - - switch (band) { - case IEEE80211_BAND_2GHZ: - rate_table = sc->hw_rate_table[ATH9K_MODE_11G]; - break; - case IEEE80211_BAND_5GHZ: - rate_table = sc->hw_rate_table[ATH9K_MODE_11A]; - break; - default: - break; - } - - if (rate_table == NULL) - return; - - sband = &sc->sbands[band]; - rate = sc->rates[band]; - - if (rate_table->rate_cnt > ATH_RATE_MAX) - maxrates = ATH_RATE_MAX; - else - maxrates = rate_table->rate_cnt; - - for (i = 0; i < maxrates; i++) { - rate[i].bitrate = rate_table->info[i].ratekbps / 100; - rate[i].hw_value = rate_table->info[i].ratecode; - if (rate_table->info[i].short_preamble) { - rate[i].hw_value_short = rate_table->info[i].ratecode | - rate_table->info[i].short_preamble; - rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE; - } - sband->n_bitrates++; - - DPRINTF(sc, ATH_DBG_CONFIG, "Rate: %2dMbps, ratecode: %2d\n", - rate[i].bitrate / 10, rate[i].hw_value); - } -} - -static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, - struct ieee80211_hw *hw) -{ - struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel *channel; - u8 chan_idx; - - chan_idx = curchan->hw_value; - channel = &sc->sc_ah->channels[chan_idx]; - ath9k_update_ichannel(sc, hw, channel); - return channel; -} - -/* - * Set/change channels. If the channel is really being changed, it's done - * by reseting the chip. To accomplish this we must first cleanup any pending - * DMA, then restart stuff. -*/ -int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *hchan) -{ - struct ath_hw *ah = sc->sc_ah; - bool fastcc = true, stopped; - struct ieee80211_channel *channel = hw->conf.channel; - int r; - - if (sc->sc_flags & SC_OP_INVALID) - return -EIO; - - ath9k_ps_wakeup(sc); - - /* - * This is only performed if the channel settings have - * actually changed. - * - * To switch channels clear any pending DMA operations; - * wait long enough for the RX fifo to drain, reset the - * hardware at the new frequency, and then re-enable - * the relevant bits of the h/w. - */ - ath9k_hw_set_interrupts(ah, 0); - ath_drain_all_txq(sc, false); - stopped = ath_stoprecv(sc); - - /* XXX: do not flush receive queue here. We don't want - * to flush data frames already in queue because of - * changing channel. */ - - if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) - fastcc = false; - - DPRINTF(sc, ATH_DBG_CONFIG, - "(%u MHz) -> (%u MHz), chanwidth: %d\n", - sc->sc_ah->curchan->channel, - channel->center_freq, sc->tx_chan_width); - - spin_lock_bh(&sc->sc_resetlock); - - r = ath9k_hw_reset(ah, hchan, fastcc); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel (%u Mhz) " - "reset status %d\n", - channel->center_freq, r); - spin_unlock_bh(&sc->sc_resetlock); - goto ps_restore; - } - spin_unlock_bh(&sc->sc_resetlock); - - sc->sc_flags &= ~SC_OP_FULL_RESET; - - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - r = -EIO; - goto ps_restore; - } - - ath_cache_conf_rate(sc, &hw->conf); - ath_update_txpow(sc); - ath9k_hw_set_interrupts(ah, sc->imask); - - ps_restore: - ath9k_ps_restore(sc); - return r; -} - -/* - * This routine performs the periodic noise floor calibration function - * that is used to adjust and optimize the chip performance. This - * takes environmental changes (location, temperature) into account. - * When the task is complete, it reschedules itself depending on the - * appropriate interval that was calculated. - */ -static void ath_ani_calibrate(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - struct ath_hw *ah = sc->sc_ah; - bool longcal = false; - bool shortcal = false; - bool aniflag = false; - unsigned int timestamp = jiffies_to_msecs(jiffies); - u32 cal_interval, short_cal_interval; - - short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ? - ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL; - - /* - * don't calibrate when we're scanning. - * we are most likely not on our home channel. - */ - spin_lock(&sc->ani_lock); - if (sc->sc_flags & SC_OP_SCANNING) - goto set_timer; - - /* Only calibrate if awake */ - if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) - goto set_timer; - - ath9k_ps_wakeup(sc); - - /* Long calibration runs independently of short calibration. */ - if ((timestamp - sc->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { - longcal = true; - DPRINTF(sc, ATH_DBG_ANI, "longcal @%lu\n", jiffies); - sc->ani.longcal_timer = timestamp; - } - - /* Short calibration applies only while caldone is false */ - if (!sc->ani.caldone) { - if ((timestamp - sc->ani.shortcal_timer) >= short_cal_interval) { - shortcal = true; - DPRINTF(sc, ATH_DBG_ANI, "shortcal @%lu\n", jiffies); - sc->ani.shortcal_timer = timestamp; - sc->ani.resetcal_timer = timestamp; - } - } else { - if ((timestamp - sc->ani.resetcal_timer) >= - ATH_RESTART_CALINTERVAL) { - sc->ani.caldone = ath9k_hw_reset_calvalid(ah); - if (sc->ani.caldone) - sc->ani.resetcal_timer = timestamp; - } - } - - /* Verify whether we must check ANI */ - if ((timestamp - sc->ani.checkani_timer) >= ATH_ANI_POLLINTERVAL) { - aniflag = true; - sc->ani.checkani_timer = timestamp; - } - - /* Skip all processing if there's nothing to do. */ - if (longcal || shortcal || aniflag) { - /* Call ANI routine if necessary */ - if (aniflag) - ath9k_hw_ani_monitor(ah, ah->curchan); - - /* Perform calibration if necessary */ - if (longcal || shortcal) { - sc->ani.caldone = ath9k_hw_calibrate(ah, ah->curchan, - sc->rx_chainmask, longcal); - - if (longcal) - sc->ani.noise_floor = ath9k_hw_getchan_noise(ah, - ah->curchan); - - DPRINTF(sc, ATH_DBG_ANI," calibrate chan %u/%x nf: %d\n", - ah->curchan->channel, ah->curchan->channelFlags, - sc->ani.noise_floor); - } - } - - ath9k_ps_restore(sc); - -set_timer: - spin_unlock(&sc->ani_lock); - /* - * Set timer interval based on previous results. - * The interval must be the shortest necessary to satisfy ANI, - * short calibration and long calibration. - */ - cal_interval = ATH_LONG_CALINTERVAL; - if (sc->sc_ah->config.enable_ani) - cal_interval = min(cal_interval, (u32)ATH_ANI_POLLINTERVAL); - if (!sc->ani.caldone) - cal_interval = min(cal_interval, (u32)short_cal_interval); - - mod_timer(&sc->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); -} - -static void ath_start_ani(struct ath_softc *sc) -{ - unsigned long timestamp = jiffies_to_msecs(jiffies); - - sc->ani.longcal_timer = timestamp; - sc->ani.shortcal_timer = timestamp; - sc->ani.checkani_timer = timestamp; - - mod_timer(&sc->ani.timer, - jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); -} - -/* - * Update tx/rx chainmask. For legacy association, - * hard code chainmask to 1x1, for 11n association, use - * the chainmask configuration, for bt coexistence, use - * the chainmask configuration even in legacy mode. - */ -void ath_update_chainmask(struct ath_softc *sc, int is_ht) -{ - if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || - (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE)) { - sc->tx_chainmask = sc->sc_ah->caps.tx_chainmask; - sc->rx_chainmask = sc->sc_ah->caps.rx_chainmask; - } else { - sc->tx_chainmask = 1; - sc->rx_chainmask = 1; - } - - DPRINTF(sc, ATH_DBG_CONFIG, "tx chmask: %d, rx chmask: %d\n", - sc->tx_chainmask, sc->rx_chainmask); -} - -static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta) -{ - struct ath_node *an; - - an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) { - ath_tx_node_init(sc, an); - an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR + - sta->ht_cap.ampdu_factor); - an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density); - an->last_rssi = ATH_RSSI_DUMMY_MARKER; - } -} - -static void ath_node_detach(struct ath_softc *sc, struct ieee80211_sta *sta) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) - ath_tx_node_cleanup(sc, an); -} - -static void ath9k_tasklet(unsigned long data) -{ - struct ath_softc *sc = (struct ath_softc *)data; - u32 status = sc->intrstatus; - - ath9k_ps_wakeup(sc); - - if (status & ATH9K_INT_FATAL) { - ath_reset(sc, false); - ath9k_ps_restore(sc); - return; - } - - if (status & (ATH9K_INT_RX | ATH9K_INT_RXEOL | ATH9K_INT_RXORN)) { - spin_lock_bh(&sc->rx.rxflushlock); - ath_rx_tasklet(sc, 0); - spin_unlock_bh(&sc->rx.rxflushlock); - } - - if (status & ATH9K_INT_TX) - ath_tx_tasklet(sc); - - if ((status & ATH9K_INT_TSFOOR) && sc->ps_enabled) { - /* - * TSF sync does not look correct; remain awake to sync with - * the next Beacon. - */ - DPRINTF(sc, ATH_DBG_PS, "TSFOOR - Sync with next Beacon\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON | SC_OP_BEACON_SYNC; - } - - if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - if (status & ATH9K_INT_GENTIMER) - ath_gen_timer_isr(sc->sc_ah); - - /* re-enable hardware interrupt */ - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - ath9k_ps_restore(sc); -} - -irqreturn_t ath_isr(int irq, void *dev) -{ -#define SCHED_INTR ( \ - ATH9K_INT_FATAL | \ - ATH9K_INT_RXORN | \ - ATH9K_INT_RXEOL | \ - ATH9K_INT_RX | \ - ATH9K_INT_TX | \ - ATH9K_INT_BMISS | \ - ATH9K_INT_CST | \ - ATH9K_INT_TSFOOR | \ - ATH9K_INT_GENTIMER) - - struct ath_softc *sc = dev; - struct ath_hw *ah = sc->sc_ah; - enum ath9k_int status; - bool sched = false; - - /* - * The hardware is not ready/present, don't - * touch anything. Note this can happen early - * on if the IRQ is shared. - */ - if (sc->sc_flags & SC_OP_INVALID) - return IRQ_NONE; - - - /* shared irq, not for us */ - - if (!ath9k_hw_intrpend(ah)) - return IRQ_NONE; - - /* - * Figure out the reason(s) for the interrupt. Note - * that the hal returns a pseudo-ISR that may include - * bits we haven't explicitly enabled so we mask the - * value to insure we only process bits we requested. - */ - ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ - status &= sc->imask; /* discard unasked-for bits */ - - /* - * If there are no status bits set, then this interrupt was not - * for me (should have been caught above). - */ - if (!status) - return IRQ_NONE; - - /* Cache the status */ - sc->intrstatus = status; - - if (status & SCHED_INTR) - sched = true; - - /* - * If a FATAL or RXORN interrupt is received, we have to reset the - * chip immediately. - */ - if (status & (ATH9K_INT_FATAL | ATH9K_INT_RXORN)) - goto chip_reset; - - if (status & ATH9K_INT_SWBA) - tasklet_schedule(&sc->bcon_tasklet); - - if (status & ATH9K_INT_TXURN) - ath9k_hw_updatetxtriglevel(ah, true); - - if (status & ATH9K_INT_MIB) { - /* - * Disable interrupts until we service the MIB - * interrupt; otherwise it will continue to - * fire. - */ - ath9k_hw_set_interrupts(ah, 0); - /* - * Let the hal handle the event. We assume - * it will clear whatever condition caused - * the interrupt. - */ - ath9k_hw_procmibevent(ah); - ath9k_hw_set_interrupts(ah, sc->imask); - } - - if (!(ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) - if (status & ATH9K_INT_TIM_TIMER) { - /* Clear RxAbort bit so that we can - * receive frames */ - ath9k_hw_setpower(ah, ATH9K_PM_AWAKE); - ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags |= SC_OP_WAIT_FOR_BEACON; - } - -chip_reset: - - ath_debug_stat_interrupt(sc, status); - - if (sched) { - /* turn off every interrupt except SWBA */ - ath9k_hw_set_interrupts(ah, (sc->imask & ATH9K_INT_SWBA)); - tasklet_schedule(&sc->intr_tq); - } - - return IRQ_HANDLED; - -#undef SCHED_INTR -} - -static u32 ath_get_extchanmode(struct ath_softc *sc, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - u32 chanmode = 0; - - switch (chan->band) { - case IEEE80211_BAND_2GHZ: - switch(channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chanmode = CHANNEL_G_HT20; - break; - case NL80211_CHAN_HT40PLUS: - chanmode = CHANNEL_G_HT40PLUS; - break; - case NL80211_CHAN_HT40MINUS: - chanmode = CHANNEL_G_HT40MINUS; - break; - } - break; - case IEEE80211_BAND_5GHZ: - switch(channel_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - chanmode = CHANNEL_A_HT20; - break; - case NL80211_CHAN_HT40PLUS: - chanmode = CHANNEL_A_HT40PLUS; - break; - case NL80211_CHAN_HT40MINUS: - chanmode = CHANNEL_A_HT40MINUS; - break; - } - break; - default: - break; - } - - return chanmode; -} - -static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, - struct ath9k_keyval *hk, const u8 *addr, - bool authenticator) -{ - const u8 *key_rxmic; - const u8 *key_txmic; - - key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; - key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; - - if (addr == NULL) { - /* - * Group key installation - only two key cache entries are used - * regardless of splitmic capability since group key is only - * used either for TX or RX. - */ - if (authenticator) { - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); - } else { - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); - } - return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr); - } - if (!sc->splitmic) { - /* TX and RX keys share the same key cache entry. */ - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); - return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, addr); - } - - /* Separate key cache entries for TX and RX */ - - /* TX key goes at first index, RX key at +32. */ - memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); - if (!ath9k_hw_set_keycache_entry(sc->sc_ah, keyix, hk, NULL)) { - /* TX MIC entry failed. No need to proceed further */ - DPRINTF(sc, ATH_DBG_FATAL, - "Setting TX MIC Key Failed\n"); - return 0; - } - - memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); - /* XXX delete tx key on failure? */ - return ath9k_hw_set_keycache_entry(sc->sc_ah, keyix + 32, hk, addr); -} - -static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc) -{ - int i; - - for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) { - if (test_bit(i, sc->keymap) || - test_bit(i + 64, sc->keymap)) - continue; /* At least one part of TKIP key allocated */ - if (sc->splitmic && - (test_bit(i + 32, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - continue; /* At least one part of TKIP key allocated */ - - /* Found a free slot for a TKIP key */ - return i; - } - return -1; -} - -static int ath_reserve_key_cache_slot(struct ath_softc *sc) -{ - int i; - - /* First, try to find slots that would not be available for TKIP. */ - if (sc->splitmic) { - for (i = IEEE80211_WEP_NKID; i < sc->keymax / 4; i++) { - if (!test_bit(i, sc->keymap) && - (test_bit(i + 32, sc->keymap) || - test_bit(i + 64, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - return i; - if (!test_bit(i + 32, sc->keymap) && - (test_bit(i, sc->keymap) || - test_bit(i + 64, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - return i + 32; - if (!test_bit(i + 64, sc->keymap) && - (test_bit(i , sc->keymap) || - test_bit(i + 32, sc->keymap) || - test_bit(i + 64 + 32, sc->keymap))) - return i + 64; - if (!test_bit(i + 64 + 32, sc->keymap) && - (test_bit(i, sc->keymap) || - test_bit(i + 32, sc->keymap) || - test_bit(i + 64, sc->keymap))) - return i + 64 + 32; - } - } else { - for (i = IEEE80211_WEP_NKID; i < sc->keymax / 2; i++) { - if (!test_bit(i, sc->keymap) && - test_bit(i + 64, sc->keymap)) - return i; - if (test_bit(i, sc->keymap) && - !test_bit(i + 64, sc->keymap)) - return i + 64; - } - } - - /* No partially used TKIP slots, pick any available slot */ - for (i = IEEE80211_WEP_NKID; i < sc->keymax; i++) { - /* Do not allow slots that could be needed for TKIP group keys - * to be used. This limitation could be removed if we know that - * TKIP will not be used. */ - if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) - continue; - if (sc->splitmic) { - if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) - continue; - if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) - continue; - } - - if (!test_bit(i, sc->keymap)) - return i; /* Found a free slot for a key */ - } - - /* No free slot found */ - return -1; -} - -static int ath_key_config(struct ath_softc *sc, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath9k_keyval hk; - const u8 *mac = NULL; - int ret = 0; - int idx; - - memset(&hk, 0, sizeof(hk)); - - switch (key->alg) { - case ALG_WEP: - hk.kv_type = ATH9K_CIPHER_WEP; - break; - case ALG_TKIP: - hk.kv_type = ATH9K_CIPHER_TKIP; - break; - case ALG_CCMP: - hk.kv_type = ATH9K_CIPHER_AES_CCM; - break; - default: - return -EOPNOTSUPP; - } - - hk.kv_len = key->keylen; - memcpy(hk.kv_val, key->key, key->keylen); - - if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { - /* For now, use the default keys for broadcast keys. This may - * need to change with virtual interfaces. */ - idx = key->keyidx; - } else if (key->keyidx) { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (vif->type != NL80211_IFTYPE_AP) { - /* Only keyidx 0 should be used with unicast key, but - * allow this for client mode for now. */ - idx = key->keyidx; - } else - return -EIO; - } else { - if (WARN_ON(!sta)) - return -EOPNOTSUPP; - mac = sta->addr; - - if (key->alg == ALG_TKIP) - idx = ath_reserve_key_cache_slot_tkip(sc); - else - idx = ath_reserve_key_cache_slot(sc); - if (idx < 0) - return -ENOSPC; /* no free key cache entries */ - } - - if (key->alg == ALG_TKIP) - ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac, - vif->type == NL80211_IFTYPE_AP); - else - ret = ath9k_hw_set_keycache_entry(sc->sc_ah, idx, &hk, mac); - - if (!ret) - return -EIO; - - set_bit(idx, sc->keymap); - if (key->alg == ALG_TKIP) { - set_bit(idx + 64, sc->keymap); - if (sc->splitmic) { - set_bit(idx + 32, sc->keymap); - set_bit(idx + 64 + 32, sc->keymap); - } - } - - return idx; -} - -static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) -{ - ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx); - if (key->hw_key_idx < IEEE80211_WEP_NKID) - return; - - clear_bit(key->hw_key_idx, sc->keymap); - if (key->alg != ALG_TKIP) - return; - - clear_bit(key->hw_key_idx + 64, sc->keymap); - if (sc->splitmic) { - clear_bit(key->hw_key_idx + 32, sc->keymap); - clear_bit(key->hw_key_idx + 64 + 32, sc->keymap); - } -} - -static void setup_ht_cap(struct ath_softc *sc, - struct ieee80211_sta_ht_cap *ht_info) -{ - u8 tx_streams, rx_streams; - - ht_info->ht_supported = true; - ht_info->cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_SM_PS | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; - - ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8; - - /* set up supported mcs set */ - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - tx_streams = !(sc->tx_chainmask & (sc->tx_chainmask - 1)) ? 1 : 2; - rx_streams = !(sc->rx_chainmask & (sc->rx_chainmask - 1)) ? 1 : 2; - - if (tx_streams != rx_streams) { - DPRINTF(sc, ATH_DBG_CONFIG, "TX streams %d, RX streams: %d\n", - tx_streams, rx_streams); - ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; - ht_info->mcs.tx_params |= ((tx_streams - 1) << - IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - } - - ht_info->mcs.rx_mask[0] = 0xff; - if (rx_streams >= 2) - ht_info->mcs.rx_mask[1] = 0xff; - - ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_DEFINED; -} - -static void ath9k_bss_assoc_info(struct ath_softc *sc, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf) -{ - - if (bss_conf->assoc) { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", - bss_conf->aid, sc->curbssid); - - /* New association, store aid */ - sc->curaid = bss_conf->aid; - ath9k_hw_write_associd(sc); - - /* - * Request a re-configuration of Beacon related timers - * on the receipt of the first Beacon frame (i.e., - * after time sync with the AP). - */ - sc->sc_flags |= SC_OP_BEACON_SYNC; - - /* Configure the beacon */ - ath_beacon_config(sc, vif); - - /* Reset rssi stats */ - sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER; - - ath_start_ani(sc); - } else { - DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info DISASSOC\n"); - sc->curaid = 0; - /* Stop ANI */ - del_timer_sync(&sc->ani.timer); - } -} - -/********************************/ -/* LED functions */ -/********************************/ - -static void ath_led_blink_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - ath_led_blink_work.work); - - if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED)) - return; - - if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) || - (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE)) - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); - else - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, - (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0); - - ieee80211_queue_delayed_work(sc->hw, - &sc->ath_led_blink_work, - (sc->sc_flags & SC_OP_LED_ON) ? - msecs_to_jiffies(sc->led_off_duration) : - msecs_to_jiffies(sc->led_on_duration)); - - sc->led_on_duration = sc->led_on_cnt ? - max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) : - ATH_LED_ON_DURATION_IDLE; - sc->led_off_duration = sc->led_off_cnt ? - max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) : - ATH_LED_OFF_DURATION_IDLE; - sc->led_on_cnt = sc->led_off_cnt = 0; - if (sc->sc_flags & SC_OP_LED_ON) - sc->sc_flags &= ~SC_OP_LED_ON; - else - sc->sc_flags |= SC_OP_LED_ON; -} - -static void ath_led_brightness(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev); - struct ath_softc *sc = led->sc; - - switch (brightness) { - case LED_OFF: - if (led->led_type == ATH_LED_ASSOC || - led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, - (led->led_type == ATH_LED_RADIO)); - sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - if (led->led_type == ATH_LED_RADIO) - sc->sc_flags &= ~SC_OP_LED_ON; - } else { - sc->led_off_cnt++; - } - break; - case LED_FULL: - if (led->led_type == ATH_LED_ASSOC) { - sc->sc_flags |= SC_OP_LED_ASSOCIATED; - ieee80211_queue_delayed_work(sc->hw, - &sc->ath_led_blink_work, 0); - } else if (led->led_type == ATH_LED_RADIO) { - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0); - sc->sc_flags |= SC_OP_LED_ON; - } else { - sc->led_on_cnt++; - } - break; - default: - break; - } -} - -static int ath_register_led(struct ath_softc *sc, struct ath_led *led, - char *trigger) -{ - int ret; - - led->sc = sc; - led->led_cdev.name = led->name; - led->led_cdev.default_trigger = trigger; - led->led_cdev.brightness_set = ath_led_brightness; - - ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev); - if (ret) - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to register led:%s", led->name); - else - led->registered = 1; - return ret; -} - -static void ath_unregister_led(struct ath_led *led) -{ - if (led->registered) { - led_classdev_unregister(&led->led_cdev); - led->registered = 0; - } -} - -static void ath_deinit_leds(struct ath_softc *sc) -{ - ath_unregister_led(&sc->assoc_led); - sc->sc_flags &= ~SC_OP_LED_ASSOCIATED; - ath_unregister_led(&sc->tx_led); - ath_unregister_led(&sc->rx_led); - ath_unregister_led(&sc->radio_led); - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); -} - -static void ath_init_leds(struct ath_softc *sc) -{ - char *trigger; - int ret; - - if (AR_SREV_9287(sc->sc_ah)) - sc->sc_ah->led_pin = ATH_LED_PIN_9287; - else - sc->sc_ah->led_pin = ATH_LED_PIN_DEF; - - /* Configure gpio 1 for output */ - ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - /* LED off, active low */ - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - - INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work); - - trigger = ieee80211_get_radio_led_name(sc->hw); - snprintf(sc->radio_led.name, sizeof(sc->radio_led.name), - "ath9k-%s::radio", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->radio_led, trigger); - sc->radio_led.led_type = ATH_LED_RADIO; - if (ret) - goto fail; - - trigger = ieee80211_get_assoc_led_name(sc->hw); - snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name), - "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->assoc_led, trigger); - sc->assoc_led.led_type = ATH_LED_ASSOC; - if (ret) - goto fail; - - trigger = ieee80211_get_tx_led_name(sc->hw); - snprintf(sc->tx_led.name, sizeof(sc->tx_led.name), - "ath9k-%s::tx", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->tx_led, trigger); - sc->tx_led.led_type = ATH_LED_TX; - if (ret) - goto fail; - - trigger = ieee80211_get_rx_led_name(sc->hw); - snprintf(sc->rx_led.name, sizeof(sc->rx_led.name), - "ath9k-%s::rx", wiphy_name(sc->hw->wiphy)); - ret = ath_register_led(sc, &sc->rx_led, trigger); - sc->rx_led.led_type = ATH_LED_RX; - if (ret) - goto fail; - - return; - -fail: - cancel_delayed_work_sync(&sc->ath_led_blink_work); - ath_deinit_leds(sc); -} - -void ath_radio_enable(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_channel *channel = sc->hw->conf.channel; - int r; - - ath9k_ps_wakeup(sc); - ath9k_hw_configpcipowersave(ah, 0, 0); - - if (!ah->curchan) - ah->curchan = ath_get_curchannel(sc, sc->hw); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, ah->curchan, false); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) ", - "reset status %d\n", - channel->center_freq, r); - } - spin_unlock_bh(&sc->sc_resetlock); - - ath_update_txpow(sc); - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to restart recv logic\n"); - return; - } - - if (sc->sc_flags & SC_OP_BEACONS) - ath_beacon_config(sc, NULL); /* restart beacons */ - - /* Re-Enable interrupts */ - ath9k_hw_set_interrupts(ah, sc->imask); - - /* Enable LED */ - ath9k_hw_cfg_output(ah, ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(ah, ah->led_pin, 0); - - ieee80211_wake_queues(sc->hw); - ath9k_ps_restore(sc); -} - -void ath_radio_disable(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_channel *channel = sc->hw->conf.channel; - int r; - - ath9k_ps_wakeup(sc); - ieee80211_stop_queues(sc->hw); - - /* Disable LED */ - ath9k_hw_set_gpio(ah, ah->led_pin, 1); - ath9k_hw_cfg_gpio_input(ah, ah->led_pin); - - /* Disable interrupts */ - ath9k_hw_set_interrupts(ah, 0); - - ath_drain_all_txq(sc, false); /* clear pending tx frames */ - ath_stoprecv(sc); /* turn off frame recv */ - ath_flushrecv(sc); /* flush recv queue */ - - if (!ah->curchan) - ah->curchan = ath_get_curchannel(sc, sc->hw); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, ah->curchan, false); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset channel %u (%uMhz) " - "reset status %d\n", - channel->center_freq, r); - } - spin_unlock_bh(&sc->sc_resetlock); - - ath9k_hw_phy_disable(ah); - ath9k_hw_configpcipowersave(ah, 1, 1); - ath9k_ps_restore(sc); - ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); -} - -/*******************/ -/* Rfkill */ -/*******************/ - -static bool ath_is_rfkill_set(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) == - ah->rfkill_polarity; -} - -static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - bool blocked = !!ath_is_rfkill_set(sc); - - wiphy_rfkill_set_hw_state(hw->wiphy, blocked); -} - -static void ath_start_rfkill_poll(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - - if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) - wiphy_rfkill_start_polling(sc->hw->wiphy); -} - -void ath_cleanup(struct ath_softc *sc) -{ - ath_detach(sc); - free_irq(sc->irq, sc); - ath_bus_cleanup(sc); - kfree(sc->sec_wiphy); - ieee80211_free_hw(sc->hw); -} - -void ath_detach(struct ath_softc *sc) -{ - struct ieee80211_hw *hw = sc->hw; - int i = 0; - - ath9k_ps_wakeup(sc); - - DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); - - ath_deinit_leds(sc); - wiphy_rfkill_stop_polling(sc->hw->wiphy); - - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - sc->sec_wiphy[i] = NULL; - ieee80211_unregister_hw(aphy->hw); - ieee80211_free_hw(aphy->hw); - } - ieee80211_unregister_hw(hw); - ath_rx_cleanup(sc); - ath_tx_cleanup(sc); - - tasklet_kill(&sc->intr_tq); - tasklet_kill(&sc->bcon_tasklet); - - if (!(sc->sc_flags & SC_OP_INVALID)) - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - if ((sc->btcoex_info.no_stomp_timer) && - sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - ath_gen_timer_free(sc->sc_ah, sc->btcoex_info.no_stomp_timer); - - ath9k_hw_detach(sc->sc_ah); - sc->sc_ah = NULL; - ath9k_exit_debug(sc); -} - -static int ath9k_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_regulatory *reg = &sc->common.regulatory; - - return ath_reg_notifier_apply(wiphy, request, reg); -} - -/* - * Initialize and fill ath_softc, ath_sofct is the - * "Software Carrier" struct. Historically it has existed - * to allow the separation between hardware specific - * variables (now in ath_hw) and driver specific variables. - */ -static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid) -{ - struct ath_hw *ah = NULL; - int r = 0, i; - int csz = 0; - - /* XXX: hardware will not be ready until ath_open() being called */ - sc->sc_flags |= SC_OP_INVALID; - - if (ath9k_init_debug(sc) < 0) - printk(KERN_ERR "Unable to create debugfs files\n"); - - spin_lock_init(&sc->wiphy_lock); - spin_lock_init(&sc->sc_resetlock); - spin_lock_init(&sc->sc_serial_rw); - spin_lock_init(&sc->ani_lock); - spin_lock_init(&sc->sc_pm_lock); - mutex_init(&sc->mutex); - tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); - tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, - (unsigned long)sc); - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - ath_read_cachesize(sc, &csz); - /* XXX assert csz is non-zero */ - sc->common.cachelsz = csz << 2; /* convert to bytes */ - - ah = kzalloc(sizeof(struct ath_hw), GFP_KERNEL); - if (!ah) { - r = -ENOMEM; - goto bad_no_ah; - } - - ah->ah_sc = sc; - ah->hw_version.devid = devid; - ah->hw_version.subsysid = subsysid; - sc->sc_ah = ah; - - r = ath9k_hw_init(ah); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to initialize hardware; " - "initialization status: %d\n", r); - goto bad; - } - - /* Get the hardware key cache size. */ - sc->keymax = ah->caps.keycache_size; - if (sc->keymax > ATH_KEYMAX) { - DPRINTF(sc, ATH_DBG_ANY, - "Warning, using only %u entries in %u key cache\n", - ATH_KEYMAX, sc->keymax); - sc->keymax = ATH_KEYMAX; - } - - /* - * Reset the key cache since some parts do not - * reset the contents on initial power up. - */ - for (i = 0; i < sc->keymax; i++) - ath9k_hw_keyreset(ah, (u16) i); - - /* default to MONITOR mode */ - sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; - - /* Setup rate tables */ - - ath_rate_attach(sc); - ath_setup_rates(sc, IEEE80211_BAND_2GHZ); - ath_setup_rates(sc, IEEE80211_BAND_5GHZ); - - /* - * Allocate hardware transmit queues: one queue for - * beacon frames and one data queue for each QoS - * priority. Note that the hal handles reseting - * these queues at the needed time. - */ - sc->beacon.beaconq = ath_beaconq_setup(ah); - if (sc->beacon.beaconq == -1) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup a beacon xmit queue\n"); - r = -EIO; - goto bad2; - } - sc->beacon.cabq = ath_txq_setup(sc, ATH9K_TX_QUEUE_CAB, 0); - if (sc->beacon.cabq == NULL) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup CAB xmit queue\n"); - r = -EIO; - goto bad2; - } - - sc->config.cabqReadytime = ATH_CABQ_READY_TIME; - ath_cabq_update(sc); - - for (i = 0; i < ARRAY_SIZE(sc->tx.hwq_map); i++) - sc->tx.hwq_map[i] = -1; - - /* Setup data queues */ - /* NB: ensure BK queue is the lowest priority h/w queue */ - if (!ath_tx_setup(sc, ATH9K_WME_AC_BK)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for BK traffic\n"); - r = -EIO; - goto bad2; - } - - if (!ath_tx_setup(sc, ATH9K_WME_AC_BE)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for BE traffic\n"); - r = -EIO; - goto bad2; - } - if (!ath_tx_setup(sc, ATH9K_WME_AC_VI)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for VI traffic\n"); - r = -EIO; - goto bad2; - } - if (!ath_tx_setup(sc, ATH9K_WME_AC_VO)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to setup xmit queue for VO traffic\n"); - r = -EIO; - goto bad2; - } - - /* Initializes the noise floor to a reasonable default value. - * Later on this will be updated during ANI processing. */ - - sc->ani.noise_floor = ATH_DEFAULT_NOISE_FLOOR; - setup_timer(&sc->ani.timer, ath_ani_calibrate, (unsigned long)sc); - - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL)) { - /* - * Whether we should enable h/w TKIP MIC. - * XXX: if we don't support WME TKIP MIC, then we wouldn't - * report WMM capable, so it's always safe to turn on - * TKIP MIC in this case. - */ - ath9k_hw_setcapability(sc->sc_ah, ATH9K_CAP_TKIP_MIC, - 0, 1, NULL); - } - - /* - * Check whether the separate key cache entries - * are required to handle both tx+rx MIC keys. - * With split mic keys the number of stations is limited - * to 27 otherwise 59. - */ - if (ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_TKIP, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_CIPHER, - ATH9K_CIPHER_MIC, NULL) - && ath9k_hw_getcapability(ah, ATH9K_CAP_TKIP_SPLIT, - 0, NULL)) - sc->splitmic = 1; - - /* turn on mcast key search if possible */ - if (!ath9k_hw_getcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 0, NULL)) - (void)ath9k_hw_setcapability(ah, ATH9K_CAP_MCAST_KEYSRCH, 1, - 1, NULL); - - sc->config.txpowlimit = ATH_TXPOWER_MAX; - - /* 11n Capabilities */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - sc->sc_flags |= SC_OP_TXAGGR; - sc->sc_flags |= SC_OP_RXAGGR; - } - - sc->tx_chainmask = ah->caps.tx_chainmask; - sc->rx_chainmask = ah->caps.rx_chainmask; - - ath9k_hw_setcapability(ah, ATH9K_CAP_DIVERSITY, 1, true, NULL); - sc->rx.defant = ath9k_hw_getdefantenna(ah); - - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - memcpy(sc->bssidmask, ath_bcast_mac, ETH_ALEN); - - sc->beacon.slottime = ATH9K_SLOT_TIME_9; /* default to short slot time */ - - /* initialize beacon slots */ - for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - sc->beacon.bslot[i] = NULL; - sc->beacon.bslot_aphy[i] = NULL; - } - - /* setup channels and rates */ - - sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; - sc->sbands[IEEE80211_BAND_2GHZ].bitrates = - sc->rates[IEEE80211_BAND_2GHZ]; - sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; - sc->sbands[IEEE80211_BAND_2GHZ].n_channels = - ARRAY_SIZE(ath9k_2ghz_chantable); - - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { - sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; - sc->sbands[IEEE80211_BAND_5GHZ].bitrates = - sc->rates[IEEE80211_BAND_5GHZ]; - sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; - sc->sbands[IEEE80211_BAND_5GHZ].n_channels = - ARRAY_SIZE(ath9k_5ghz_chantable); - } - - if (sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) { - r = ath9k_hw_btcoex_init(ah); - if (r) - goto bad2; - } - - return 0; -bad2: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); -bad: - ath9k_hw_detach(ah); - sc->sc_ah = NULL; -bad_no_ah: - ath9k_exit_debug(sc); - - return r; -} - -void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) -{ - struct ath_hw *ah = sc->sc_ah; - - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_REPORTS_TX_ACK_STATUS | - IEEE80211_HW_SPECTRUM_MGMT; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) - hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; - - if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || modparam_nohwcrypt) - hw->flags |= IEEE80211_HW_MFP_CAPABLE; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_MESH_POINT); - - if (AR_SREV_5416(ah)) - hw->wiphy->ps_default = false; - else - hw->wiphy->ps_default = true; - - hw->queues = 4; - hw->max_rates = 4; - hw->channel_change_time = 5000; - hw->max_listen_interval = 10; - /* Hardware supports 10 but we use 4 */ - hw->max_rate_tries = 4; - hw->sta_data_size = sizeof(struct ath_node); - hw->vif_data_size = sizeof(struct ath_vif); - - hw->rate_control_algorithm = "ath9k_rate_control"; - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &sc->sbands[IEEE80211_BAND_2GHZ]; - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &sc->sbands[IEEE80211_BAND_5GHZ]; -} - -/* Device driver core initialization */ -int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid) -{ - struct ieee80211_hw *hw = sc->hw; - int error = 0, i; - struct ath_regulatory *reg; - - DPRINTF(sc, ATH_DBG_CONFIG, "Attach ATH hw\n"); - - error = ath_init_softc(devid, sc, subsysid); - if (error != 0) - return error; - - /* get mac address from hardware and set in mac80211 */ - - SET_IEEE80211_PERM_ADDR(hw, sc->sc_ah->macaddr); - - ath_set_hw_capab(sc, hw); - - error = ath_regd_init(&sc->common.regulatory, sc->hw->wiphy, - ath9k_reg_notifier); - if (error) - return error; - - reg = &sc->common.regulatory; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { - setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); - if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) - setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); - } - - /* initialize tx/rx engine */ - error = ath_tx_init(sc, ATH_TXBUF); - if (error != 0) - goto error_attach; - - error = ath_rx_init(sc, ATH_RXBUF); - if (error != 0) - goto error_attach; - - INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); - INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); - sc->wiphy_scheduler_int = msecs_to_jiffies(500); - - error = ieee80211_register_hw(hw); - - if (!ath_is_world_regd(reg)) { - error = regulatory_hint(hw->wiphy, reg->alpha2); - if (error) - goto error_attach; - } - - /* Initialize LED control */ - ath_init_leds(sc); - - ath_start_rfkill_poll(sc); - - return 0; - -error_attach: - /* cleanup tx queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) - ath_tx_cleanupq(sc, &sc->tx.txq[i]); - - ath9k_hw_detach(sc->sc_ah); - sc->sc_ah = NULL; - ath9k_exit_debug(sc); - - return error; -} - -int ath_reset(struct ath_softc *sc, bool retry_tx) -{ - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_hw *hw = sc->hw; - int r; - - ath9k_hw_set_interrupts(ah, 0); - ath_drain_all_txq(sc, retry_tx); - ath_stoprecv(sc); - ath_flushrecv(sc); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); - if (r) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d\n", r); - spin_unlock_bh(&sc->sc_resetlock); - - if (ath_startrecv(sc) != 0) - DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); - - /* - * We may be doing a reset in response to a request - * that changes the channel so update any state that - * might change as a result. - */ - ath_cache_conf_rate(sc, &hw->conf); - - ath_update_txpow(sc); - - if (sc->sc_flags & SC_OP_BEACONS) - ath_beacon_config(sc, NULL); /* restart beacons */ - - ath9k_hw_set_interrupts(ah, sc->imask); - - if (retry_tx) { - int i; - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - spin_lock_bh(&sc->tx.txq[i].axq_lock); - ath_txq_schedule(sc, &sc->tx.txq[i]); - spin_unlock_bh(&sc->tx.txq[i].axq_lock); - } - } - } - - return r; -} - -/* - * This function will allocate both the DMA descriptor structure, and the - * buffers it contains. These are used to contain the descriptors used - * by the system. -*/ -int ath_descdma_setup(struct ath_softc *sc, struct ath_descdma *dd, - struct list_head *head, const char *name, - int nbuf, int ndesc) -{ -#define DS2PHYS(_dd, _ds) \ - ((_dd)->dd_desc_paddr + ((caddr_t)(_ds) - (caddr_t)(_dd)->dd_desc)) -#define ATH_DESC_4KB_BOUND_CHECK(_daddr) ((((_daddr) & 0xFFF) > 0xF7F) ? 1 : 0) -#define ATH_DESC_4KB_BOUND_NUM_SKIPPED(_len) ((_len) / 4096) - - struct ath_desc *ds; - struct ath_buf *bf; - int i, bsize, error; - - DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA: %u buffers %u desc/buf\n", - name, nbuf, ndesc); - - INIT_LIST_HEAD(head); - /* ath_desc must be a multiple of DWORDs */ - if ((sizeof(struct ath_desc) % 4) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, "ath_desc not DWORD aligned\n"); - ASSERT((sizeof(struct ath_desc) % 4) == 0); - error = -ENOMEM; - goto fail; - } - - dd->dd_desc_len = sizeof(struct ath_desc) * nbuf * ndesc; - - /* - * Need additional DMA memory because we can't use - * descriptors that cross the 4K page boundary. Assume - * one skipped descriptor per 4K page. - */ - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_4KB_SPLITTRANS)) { - u32 ndesc_skipped = - ATH_DESC_4KB_BOUND_NUM_SKIPPED(dd->dd_desc_len); - u32 dma_len; - - while (ndesc_skipped) { - dma_len = ndesc_skipped * sizeof(struct ath_desc); - dd->dd_desc_len += dma_len; - - ndesc_skipped = ATH_DESC_4KB_BOUND_NUM_SKIPPED(dma_len); - }; - } - - /* allocate descriptors */ - dd->dd_desc = dma_alloc_coherent(sc->dev, dd->dd_desc_len, - &dd->dd_desc_paddr, GFP_KERNEL); - if (dd->dd_desc == NULL) { - error = -ENOMEM; - goto fail; - } - ds = dd->dd_desc; - DPRINTF(sc, ATH_DBG_CONFIG, "%s DMA map: %p (%u) -> %llx (%u)\n", - name, ds, (u32) dd->dd_desc_len, - ito64(dd->dd_desc_paddr), /*XXX*/(u32) dd->dd_desc_len); - - /* allocate buffers */ - bsize = sizeof(struct ath_buf) * nbuf; - bf = kzalloc(bsize, GFP_KERNEL); - if (bf == NULL) { - error = -ENOMEM; - goto fail2; - } - dd->dd_bufptr = bf; - - for (i = 0; i < nbuf; i++, bf++, ds += ndesc) { - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(dd, ds); - - if (!(sc->sc_ah->caps.hw_caps & - ATH9K_HW_CAP_4KB_SPLITTRANS)) { - /* - * Skip descriptor addresses which can cause 4KB - * boundary crossing (addr + length) with a 32 dword - * descriptor fetch. - */ - while (ATH_DESC_4KB_BOUND_CHECK(bf->bf_daddr)) { - ASSERT((caddr_t) bf->bf_desc < - ((caddr_t) dd->dd_desc + - dd->dd_desc_len)); - - ds += ndesc; - bf->bf_desc = ds; - bf->bf_daddr = DS2PHYS(dd, ds); - } - } - list_add_tail(&bf->list, head); - } - return 0; -fail2: - dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, - dd->dd_desc_paddr); -fail: - memset(dd, 0, sizeof(*dd)); - return error; -#undef ATH_DESC_4KB_BOUND_CHECK -#undef ATH_DESC_4KB_BOUND_NUM_SKIPPED -#undef DS2PHYS -} - -void ath_descdma_cleanup(struct ath_softc *sc, - struct ath_descdma *dd, - struct list_head *head) -{ - dma_free_coherent(sc->dev, dd->dd_desc_len, dd->dd_desc, - dd->dd_desc_paddr); - - INIT_LIST_HEAD(head); - kfree(dd->dd_bufptr); - memset(dd, 0, sizeof(*dd)); -} - -int ath_get_hal_qnum(u16 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case 0: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_VO]; - break; - case 1: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_VI]; - break; - case 2: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; - break; - case 3: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BK]; - break; - default: - qnum = sc->tx.hwq_map[ATH9K_WME_AC_BE]; - break; - } - - return qnum; -} - -int ath_get_mac80211_qnum(u32 queue, struct ath_softc *sc) -{ - int qnum; - - switch (queue) { - case ATH9K_WME_AC_VO: - qnum = 0; - break; - case ATH9K_WME_AC_VI: - qnum = 1; - break; - case ATH9K_WME_AC_BE: - qnum = 2; - break; - case ATH9K_WME_AC_BK: - qnum = 3; - break; - default: - qnum = -1; - break; - } - - return qnum; -} - -/* XXX: Remove me once we don't depend on ath9k_channel for all - * this redundant data */ -void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw, - struct ath9k_channel *ichan) -{ - struct ieee80211_channel *chan = hw->conf.channel; - struct ieee80211_conf *conf = &hw->conf; - - ichan->channel = chan->center_freq; - ichan->chan = chan; - - if (chan->band == IEEE80211_BAND_2GHZ) { - ichan->chanmode = CHANNEL_G; - ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; - } else { - ichan->chanmode = CHANNEL_A; - ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; - } - - sc->tx_chan_width = ATH9K_HT_MACMODE_20; - - if (conf_is_ht(conf)) { - if (conf_is_ht40(conf)) - sc->tx_chan_width = ATH9K_HT_MACMODE_2040; - - ichan->chanmode = ath_get_extchanmode(sc, chan, - conf->channel_type); - } -} - -/**********************/ -/* mac80211 callbacks */ -/**********************/ - -static int ath9k_start(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ieee80211_channel *curchan = hw->conf.channel; - struct ath9k_channel *init_channel; - int r; - - DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " - "initial channel: %d MHz\n", curchan->center_freq); - - mutex_lock(&sc->mutex); - - if (ath9k_wiphy_started(sc)) { - if (sc->chan_idx == curchan->hw_value) { - /* - * Already on the operational channel, the new wiphy - * can be marked active. - */ - aphy->state = ATH_WIPHY_ACTIVE; - ieee80211_wake_queues(hw); - } else { - /* - * Another wiphy is on another channel, start the new - * wiphy in paused state. - */ - aphy->state = ATH_WIPHY_PAUSED; - ieee80211_stop_queues(hw); - } - mutex_unlock(&sc->mutex); - return 0; - } - aphy->state = ATH_WIPHY_ACTIVE; - - /* setup initial channel */ - - sc->chan_idx = curchan->hw_value; - - init_channel = ath_get_curchannel(sc, hw); - - /* Reset SERDES registers */ - ath9k_hw_configpcipowersave(sc->sc_ah, 0, 0); - - /* - * The basic interface to setting the hardware in a good - * state is ``reset''. On return the hardware is known to - * be powered up and with interrupts disabled. This must - * be followed by initialization of the appropriate bits - * and then setup of the interrupt mask. - */ - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(sc->sc_ah, init_channel, false); - if (r) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d " - "(freq %u MHz)\n", r, - curchan->center_freq); - spin_unlock_bh(&sc->sc_resetlock); - goto mutex_unlock; - } - spin_unlock_bh(&sc->sc_resetlock); - - /* - * This is needed only to setup initial state - * but it's best done after a reset. - */ - ath_update_txpow(sc); - - /* - * Setup the hardware after reset: - * The receive engine is set going. - * Frame transmit is handled entirely - * in the frame output path; there's nothing to do - * here except setup the interrupt mask. - */ - if (ath_startrecv(sc) != 0) { - DPRINTF(sc, ATH_DBG_FATAL, "Unable to start recv logic\n"); - r = -EIO; - goto mutex_unlock; - } - - /* Setup our intr mask. */ - sc->imask = ATH9K_INT_RX | ATH9K_INT_TX - | ATH9K_INT_RXEOL | ATH9K_INT_RXORN - | ATH9K_INT_FATAL | ATH9K_INT_GLOBAL; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_GTT) - sc->imask |= ATH9K_INT_GTT; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) - sc->imask |= ATH9K_INT_CST; - - ath_cache_conf_rate(sc, &hw->conf); - - sc->sc_flags &= ~SC_OP_INVALID; - - /* Disable BMISS interrupt when we're not associated */ - sc->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - ieee80211_wake_queues(hw); - - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); - - if ((sc->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) && - !(sc->sc_flags & SC_OP_BTCOEX_ENABLED)) { - ath_btcoex_set_weight(&sc->btcoex_info, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); - ath9k_hw_btcoex_enable(sc->sc_ah); - - ath_pcie_aspm_disable(sc); - if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - ath_btcoex_timer_resume(sc, &sc->btcoex_info); - } - -mutex_unlock: - mutex_unlock(&sc->mutex); - - return r; -} - -static int ath9k_tx(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_tx_control txctl; - int hdrlen, padsize; - - if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { - printk(KERN_DEBUG "ath9k: %s: TX in unexpected wiphy state " - "%d\n", wiphy_name(hw->wiphy), aphy->state); - goto exit; - } - - if (sc->ps_enabled) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - /* - * mac80211 does not set PM field for normal data frames, so we - * need to update that based on the current PS mode. - */ - if (ieee80211_is_data(hdr->frame_control) && - !ieee80211_is_nullfunc(hdr->frame_control) && - !ieee80211_has_pm(hdr->frame_control)) { - DPRINTF(sc, ATH_DBG_PS, "Add PM=1 for a TX frame " - "while in PS mode\n"); - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - } - } - - if (unlikely(sc->sc_ah->power_mode != ATH9K_PM_AWAKE)) { - /* - * We are using PS-Poll and mac80211 can request TX while in - * power save mode. Need to wake up hardware for the TX to be - * completed and if needed, also for RX of buffered frames. - */ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - ath9k_ps_wakeup(sc); - ath9k_hw_setrxabort(sc->sc_ah, 0); - if (ieee80211_is_pspoll(hdr->frame_control)) { - DPRINTF(sc, ATH_DBG_PS, "Sending PS-Poll to pick a " - "buffered frame\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_PSPOLL_DATA; - } else { - DPRINTF(sc, ATH_DBG_PS, "Wake up to complete TX\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_TX_ACK; - } - /* - * The actual restore operation will happen only after - * the sc_flags bit is cleared. We are just dropping - * the ps_usecount here. - */ - ath9k_ps_restore(sc); - } - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - if (hdrlen & 3) { - padsize = hdrlen % 4; - if (skb_headroom(skb) < padsize) - return -1; - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, hdrlen); - } - - /* Check if a tx queue is available */ - - txctl.txq = ath_test_get_txq(sc, skb); - if (!txctl.txq) - goto exit; - - DPRINTF(sc, ATH_DBG_XMIT, "transmitting packet, skb: %p\n", skb); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - DPRINTF(sc, ATH_DBG_XMIT, "TX failed\n"); - goto exit; - } - - return 0; -exit: - dev_kfree_skb_any(skb); - return 0; -} - -static void ath9k_stop(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - - aphy->state = ATH_WIPHY_INACTIVE; - - cancel_delayed_work_sync(&sc->ath_led_blink_work); - cancel_delayed_work_sync(&sc->tx_complete_work); - - if (!sc->num_sec_wiphy) { - cancel_delayed_work_sync(&sc->wiphy_work); - cancel_work_sync(&sc->chan_work); - } - - if (sc->sc_flags & SC_OP_INVALID) { - DPRINTF(sc, ATH_DBG_ANY, "Device not present\n"); - mutex_unlock(&sc->mutex); - return; - } - - if (ath9k_wiphy_started(sc)) { - mutex_unlock(&sc->mutex); - return; /* another wiphy still in use */ - } - - /* Ensure HW is awake when we try to shut it down. */ - ath9k_ps_wakeup(sc); - - if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { - ath9k_hw_btcoex_disable(sc->sc_ah); - if (sc->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) - ath_btcoex_timer_pause(sc, &sc->btcoex_info); - } - - /* make sure h/w will not generate any interrupt - * before setting the invalid flag. */ - ath9k_hw_set_interrupts(sc->sc_ah, 0); - - if (!(sc->sc_flags & SC_OP_INVALID)) { - ath_drain_all_txq(sc, false); - ath_stoprecv(sc); - ath9k_hw_phy_disable(sc->sc_ah); - } else - sc->rx.rxlink = NULL; - - /* disable HAL and put h/w to sleep */ - ath9k_hw_disable(sc->sc_ah); - ath9k_hw_configpcipowersave(sc->sc_ah, 1, 1); - ath9k_ps_restore(sc); - - /* Finally, put the chip in FULL SLEEP mode */ - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP); - - sc->sc_flags |= SC_OP_INVALID; - - mutex_unlock(&sc->mutex); - - DPRINTF(sc, ATH_DBG_CONFIG, "Driver halt\n"); -} - -static int ath9k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_vif *avp = (void *)conf->vif->drv_priv; - enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED; - int ret = 0; - - mutex_lock(&sc->mutex); - - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) && - sc->nvifs > 0) { - ret = -ENOBUFS; - goto out; - } - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - ic_opmode = NL80211_IFTYPE_STATION; - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - if (sc->nbcnvifs >= ATH_BCBUF) { - ret = -ENOBUFS; - goto out; - } - ic_opmode = conf->type; - break; - default: - DPRINTF(sc, ATH_DBG_FATAL, - "Interface type %d not yet supported\n", conf->type); - ret = -EOPNOTSUPP; - goto out; - } - - DPRINTF(sc, ATH_DBG_CONFIG, "Attach a VIF of type: %d\n", ic_opmode); - - /* Set the VIF opmode */ - avp->av_opmode = ic_opmode; - avp->av_bslot = -1; - - sc->nvifs++; - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - ath9k_set_bssid_mask(hw); - - if (sc->nvifs > 1) - goto out; /* skip global settings for secondary vif */ - - if (ic_opmode == NL80211_IFTYPE_AP) { - ath9k_hw_set_tsfadjust(sc->sc_ah, 1); - sc->sc_flags |= SC_OP_TSF_RESET; - } - - /* Set the device opmode */ - sc->sc_ah->opmode = ic_opmode; - - /* - * Enable MIB interrupts when there are hardware phy counters. - * Note we only do this (at the moment) for station mode. - */ - if ((conf->type == NL80211_IFTYPE_STATION) || - (conf->type == NL80211_IFTYPE_ADHOC) || - (conf->type == NL80211_IFTYPE_MESH_POINT)) { - sc->imask |= ATH9K_INT_MIB; - sc->imask |= ATH9K_INT_TSFOOR; - } - - ath9k_hw_set_interrupts(sc->sc_ah, sc->imask); - - if (conf->type == NL80211_IFTYPE_AP || - conf->type == NL80211_IFTYPE_ADHOC || - conf->type == NL80211_IFTYPE_MONITOR) - ath_start_ani(sc); - -out: - mutex_unlock(&sc->mutex); - return ret; -} - -static void ath9k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_vif *avp = (void *)conf->vif->drv_priv; - int i; - - DPRINTF(sc, ATH_DBG_CONFIG, "Detach Interface\n"); - - mutex_lock(&sc->mutex); - - /* Stop ANI */ - del_timer_sync(&sc->ani.timer); - - /* Reclaim beacon resources */ - if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || - (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) { - ath9k_ps_wakeup(sc); - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - ath9k_ps_restore(sc); - } - - ath_beacon_return(sc, avp); - sc->sc_flags &= ~SC_OP_BEACONS; - - for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) { - if (sc->beacon.bslot[i] == conf->vif) { - printk(KERN_DEBUG "%s: vif had allocated beacon " - "slot\n", __func__); - sc->beacon.bslot[i] = NULL; - sc->beacon.bslot_aphy[i] = NULL; - } - } - - sc->nvifs--; - - mutex_unlock(&sc->mutex); -} - -void ath9k_enable_ps(struct ath_softc *sc) -{ - sc->ps_enabled = true; - if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP)) { - if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { - sc->imask |= ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); - } - } - ath9k_hw_setrxabort(sc->sc_ah, 1); -} - -static int ath9k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ieee80211_conf *conf = &hw->conf; - struct ath_hw *ah = sc->sc_ah; - bool all_wiphys_idle = false, disable_radio = false; - - mutex_lock(&sc->mutex); - - /* Leave this as the first check */ - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - - spin_lock_bh(&sc->wiphy_lock); - all_wiphys_idle = ath9k_all_wiphys_idle(sc); - spin_unlock_bh(&sc->wiphy_lock); - - if (conf->flags & IEEE80211_CONF_IDLE){ - if (all_wiphys_idle) - disable_radio = true; - } - else if (all_wiphys_idle) { - ath_radio_enable(sc); - DPRINTF(sc, ATH_DBG_CONFIG, - "not-idle: enabling radio\n"); - } - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - if (conf->flags & IEEE80211_CONF_PS) { - sc->sc_flags |= SC_OP_PS_ENABLED; - if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) { - sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; - ath9k_enable_ps(sc); - } - } else { - sc->ps_enabled = false; - sc->sc_flags &= ~(SC_OP_PS_ENABLED | - SC_OP_NULLFUNC_COMPLETED); - ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE); - if (!(ah->caps.hw_caps & - ATH9K_HW_CAP_AUTOSLEEP)) { - ath9k_hw_setrxabort(sc->sc_ah, 0); - sc->sc_flags &= ~(SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK); - if (sc->imask & ATH9K_INT_TIM_TIMER) { - sc->imask &= ~ATH9K_INT_TIM_TIMER; - ath9k_hw_set_interrupts(sc->sc_ah, - sc->imask); - } - } - } - } - - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - struct ieee80211_channel *curchan = hw->conf.channel; - int pos = curchan->hw_value; - - aphy->chan_idx = pos; - aphy->chan_is_ht = conf_is_ht(conf); - - if (aphy->state == ATH_WIPHY_SCAN || - aphy->state == ATH_WIPHY_ACTIVE) - ath9k_wiphy_pause_all_forced(sc, aphy); - else { - /* - * Do not change operational channel based on a paused - * wiphy changes. - */ - goto skip_chan_change; - } - - DPRINTF(sc, ATH_DBG_CONFIG, "Set channel: %d MHz\n", - curchan->center_freq); - - /* XXX: remove me eventualy */ - ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]); - - ath_update_chainmask(sc, conf_is_ht(conf)); - - if (ath_set_channel(sc, hw, &sc->sc_ah->channels[pos]) < 0) { - DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); - mutex_unlock(&sc->mutex); - return -EINVAL; - } - } - -skip_chan_change: - if (changed & IEEE80211_CONF_CHANGE_POWER) - sc->config.txpowlimit = 2 * conf->power_level; - - if (disable_radio) { - DPRINTF(sc, ATH_DBG_CONFIG, "idle: disabling radio\n"); - ath_radio_disable(sc); - } - - mutex_unlock(&sc->mutex); - - return 0; -} - -#define SUPPORTED_FILTERS \ - (FIF_PROMISC_IN_BSS | \ - FIF_ALLMULTI | \ - FIF_CONTROL | \ - FIF_PSPOLL | \ - FIF_OTHER_BSS | \ - FIF_BCN_PRBRESP_PROMISC | \ - FIF_FCSFAIL) - -/* FIXME: sc->sc_full_reset ? */ -static void ath9k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - u32 rfilt; - - changed_flags &= SUPPORTED_FILTERS; - *total_flags &= SUPPORTED_FILTERS; - - sc->rx.rxfilter = *total_flags; - ath9k_ps_wakeup(sc); - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(sc->sc_ah, rfilt); - ath9k_ps_restore(sc); - - DPRINTF(sc, ATH_DBG_CONFIG, "Set HW RX filter: 0x%x\n", rfilt); -} - -static void ath9k_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - switch (cmd) { - case STA_NOTIFY_ADD: - ath_node_attach(sc, sta); - break; - case STA_NOTIFY_REMOVE: - ath_node_detach(sc, sta); - break; - default: - break; - } -} - -static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath9k_tx_queue_info qi; - int ret = 0, qnum; - - if (queue >= WME_NUM_AC) - return 0; - - mutex_lock(&sc->mutex); - - memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); - - qi.tqi_aifs = params->aifs; - qi.tqi_cwmin = params->cw_min; - qi.tqi_cwmax = params->cw_max; - qi.tqi_burstTime = params->txop; - qnum = ath_get_hal_qnum(queue, sc); - - DPRINTF(sc, ATH_DBG_CONFIG, - "Configure tx [queue/halq] [%d/%d], " - "aifs: %d, cw_min: %d, cw_max: %d, txop: %d\n", - queue, qnum, params->aifs, params->cw_min, - params->cw_max, params->txop); - - ret = ath_txq_update(sc, qnum, &qi); - if (ret) - DPRINTF(sc, ATH_DBG_FATAL, "TXQ Update failed\n"); - - mutex_unlock(&sc->mutex); - - return ret; -} - -static int ath9k_set_key(struct ieee80211_hw *hw, - enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int ret = 0; - - if (modparam_nohwcrypt) - return -ENOSPC; - - mutex_lock(&sc->mutex); - ath9k_ps_wakeup(sc); - DPRINTF(sc, ATH_DBG_CONFIG, "Set HW Key\n"); - - switch (cmd) { - case SET_KEY: - ret = ath_key_config(sc, vif, sta, key); - if (ret >= 0) { - key->hw_key_idx = ret; - /* push IV and Michael MIC generation to stack */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (key->alg == ALG_TKIP) - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - if (sc->sc_ah->sw_mgmt_crypto && key->alg == ALG_CCMP) - key->flags |= IEEE80211_KEY_FLAG_SW_MGMT; - ret = 0; - } - break; - case DISABLE_KEY: - ath_key_delete(sc, key); - break; - default: - ret = -EINVAL; - } - - ath9k_ps_restore(sc); - mutex_unlock(&sc->mutex); - - return ret; -} - -static void ath9k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_hw *ah = sc->sc_ah; - struct ath_vif *avp = (void *)vif->drv_priv; - u32 rfilt = 0; - int error, i; - - mutex_lock(&sc->mutex); - - /* - * TODO: Need to decide which hw opmode to use for - * multi-interface cases - * XXX: This belongs into add_interface! - */ - if (vif->type == NL80211_IFTYPE_AP && - ah->opmode != NL80211_IFTYPE_AP) { - ah->opmode = NL80211_IFTYPE_STATION; - ath9k_hw_setopmode(ah); - memcpy(sc->curbssid, sc->sc_ah->macaddr, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - /* Request full reset to get hw opmode changed properly */ - sc->sc_flags |= SC_OP_FULL_RESET; - } - - if ((changed & BSS_CHANGED_BSSID) && - !is_zero_ether_addr(bss_conf->bssid)) { - switch (vif->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - /* Set BSSID */ - memcpy(sc->curbssid, bss_conf->bssid, ETH_ALEN); - memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); - sc->curaid = 0; - ath9k_hw_write_associd(sc); - - /* Set aggregation protection mode parameters */ - sc->config.ath_aggr_prot = 0; - - DPRINTF(sc, ATH_DBG_CONFIG, - "RX filter 0x%x bssid %pM aid 0x%x\n", - rfilt, sc->curbssid, sc->curaid); - - /* need to reconfigure the beacon */ - sc->sc_flags &= ~SC_OP_BEACONS ; - - break; - default: - break; - } - } - - if ((vif->type == NL80211_IFTYPE_ADHOC) || - (vif->type == NL80211_IFTYPE_AP) || - (vif->type == NL80211_IFTYPE_MESH_POINT)) { - if ((changed & BSS_CHANGED_BEACON) || - (changed & BSS_CHANGED_BEACON_ENABLED && - bss_conf->enable_beacon)) { - /* - * Allocate and setup the beacon frame. - * - * Stop any previous beacon DMA. This may be - * necessary, for example, when an ibss merge - * causes reconfiguration; we may be called - * with beacon transmission active. - */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - error = ath_beacon_alloc(aphy, vif); - if (!error) - ath_beacon_config(sc, vif); - } - } - - /* Check for WLAN_CAPABILITY_PRIVACY ? */ - if ((avp->av_opmode != NL80211_IFTYPE_STATION)) { - for (i = 0; i < IEEE80211_WEP_NKID; i++) - if (ath9k_hw_keyisvalid(sc->sc_ah, (u16)i)) - ath9k_hw_keysetmac(sc->sc_ah, - (u16)i, - sc->curbssid); - } - - /* Only legacy IBSS for now */ - if (vif->type == NL80211_IFTYPE_ADHOC) - ath_update_chainmask(sc, 0); - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - sc->sc_flags |= SC_OP_PREAMBLE_SHORT; - else - sc->sc_flags &= ~SC_OP_PREAMBLE_SHORT; - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed CTS PROT %d\n", - bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && - hw->conf.channel->band != IEEE80211_BAND_5GHZ) - sc->sc_flags |= SC_OP_PROTECT_ENABLE; - else - sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; - } - - if (changed & BSS_CHANGED_ASSOC) { - DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", - bss_conf->assoc); - ath9k_bss_assoc_info(sc, vif, bss_conf); - } - - /* - * The HW TSF has to be reset when the beacon interval changes. - * We set the flag here, and ath_beacon_config_ap() would take this - * into account when it gets called through the subsequent - * config_interface() call - with IFCC_BEACON in the changed field. - */ - - if (changed & BSS_CHANGED_BEACON_INT) { - sc->sc_flags |= SC_OP_TSF_RESET; - sc->beacon_interval = bss_conf->beacon_int; - } - - mutex_unlock(&sc->mutex); -} - -static u64 ath9k_get_tsf(struct ieee80211_hw *hw) -{ - u64 tsf; - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - tsf = ath9k_hw_gettsf64(sc->sc_ah); - mutex_unlock(&sc->mutex); - - return tsf; -} - -static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - ath9k_hw_settsf64(sc->sc_ah, tsf); - mutex_unlock(&sc->mutex); -} - -static void ath9k_reset_tsf(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - ath9k_hw_reset_tsf(sc->sc_ah); - mutex_unlock(&sc->mutex); -} - -static int ath9k_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, - u16 tid, u16 *ssn) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int ret = 0; - - switch (action) { - case IEEE80211_AMPDU_RX_START: - if (!(sc->sc_flags & SC_OP_RXAGGR)) - ret = -ENOTSUPP; - break; - case IEEE80211_AMPDU_RX_STOP: - break; - case IEEE80211_AMPDU_TX_START: - ath9k_ps_wakeup(sc); - ath_tx_aggr_start(sc, sta, tid, ssn); - ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid); - ath9k_ps_restore(sc); - break; - case IEEE80211_AMPDU_TX_STOP: - ath9k_ps_wakeup(sc); - ath_tx_aggr_stop(sc, sta, tid); - ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid); - ath9k_ps_restore(sc); - break; - case IEEE80211_AMPDU_TX_OPERATIONAL: - ath9k_ps_wakeup(sc); - ath_tx_aggr_resume(sc, sta, tid); - ath9k_ps_restore(sc); - break; - default: - DPRINTF(sc, ATH_DBG_FATAL, "Unknown AMPDU action\n"); - } - - return ret; -} - -static void ath9k_sw_scan_start(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - if (ath9k_wiphy_scanning(sc)) { - printk(KERN_DEBUG "ath9k: Two wiphys trying to scan at the " - "same time\n"); - /* - * Do not allow the concurrent scanning state for now. This - * could be improved with scanning control moved into ath9k. - */ - mutex_unlock(&sc->mutex); - return; - } - - aphy->state = ATH_WIPHY_SCAN; - ath9k_wiphy_pause_all_forced(sc, aphy); - - spin_lock_bh(&sc->ani_lock); - sc->sc_flags |= SC_OP_SCANNING; - spin_unlock_bh(&sc->ani_lock); - mutex_unlock(&sc->mutex); -} - -static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - mutex_lock(&sc->mutex); - spin_lock_bh(&sc->ani_lock); - aphy->state = ATH_WIPHY_ACTIVE; - sc->sc_flags &= ~SC_OP_SCANNING; - sc->sc_flags |= SC_OP_FULL_RESET; - spin_unlock_bh(&sc->ani_lock); - ath_beacon_config(sc, NULL); - mutex_unlock(&sc->mutex); -} - -struct ieee80211_ops ath9k_ops = { - .tx = ath9k_tx, - .start = ath9k_start, - .stop = ath9k_stop, - .add_interface = ath9k_add_interface, - .remove_interface = ath9k_remove_interface, - .config = ath9k_config, - .configure_filter = ath9k_configure_filter, - .sta_notify = ath9k_sta_notify, - .conf_tx = ath9k_conf_tx, - .bss_info_changed = ath9k_bss_info_changed, - .set_key = ath9k_set_key, - .get_tsf = ath9k_get_tsf, - .set_tsf = ath9k_set_tsf, - .reset_tsf = ath9k_reset_tsf, - .ampdu_action = ath9k_ampdu_action, - .sw_scan_start = ath9k_sw_scan_start, - .sw_scan_complete = ath9k_sw_scan_complete, - .rfkill_poll = ath9k_rfkill_poll_state, -}; - -static struct { - u32 version; - const char * name; -} ath_mac_bb_names[] = { - { AR_SREV_VERSION_5416_PCI, "5416" }, - { AR_SREV_VERSION_5416_PCIE, "5418" }, - { AR_SREV_VERSION_9100, "9100" }, - { AR_SREV_VERSION_9160, "9160" }, - { AR_SREV_VERSION_9280, "9280" }, - { AR_SREV_VERSION_9285, "9285" }, - { AR_SREV_VERSION_9287, "9287" } -}; - -static struct { - u16 version; - const char * name; -} ath_rf_names[] = { - { 0, "5133" }, - { AR_RAD5133_SREV_MAJOR, "5133" }, - { AR_RAD5122_SREV_MAJOR, "5122" }, - { AR_RAD2133_SREV_MAJOR, "2133" }, - { AR_RAD2122_SREV_MAJOR, "2122" } -}; - -/* - * Return the MAC/BB name. "????" is returned if the MAC/BB is unknown. - */ -const char * -ath_mac_bb_name(u32 mac_bb_version) -{ - int i; - - for (i=0; i -#include -#include "ath9k.h" - -static struct pci_device_id ath_pci_id_table[] __devinitdata = { - { PCI_VDEVICE(ATHEROS, 0x0023) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x0024) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x0027) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ - { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ - { PCI_VDEVICE(ATHEROS, 0x002D) }, /* PCI */ - { PCI_VDEVICE(ATHEROS, 0x002E) }, /* PCI-E */ - { 0 } -}; - -/* return bus cachesize in 4B word units */ -static void ath_pci_read_cachesize(struct ath_softc *sc, int *csz) -{ - u8 u8tmp; - - pci_read_config_byte(to_pci_dev(sc->dev), PCI_CACHE_LINE_SIZE, &u8tmp); - *csz = (int)u8tmp; - - /* - * This check was put in to avoid "unplesant" consequences if - * the bootrom has not fully initialized all PCI devices. - * Sometimes the cache line size register is not set - */ - - if (*csz == 0) - *csz = DEFAULT_CACHELINE >> 2; /* Use the default size */ -} - -static void ath_pci_cleanup(struct ath_softc *sc) -{ - struct pci_dev *pdev = to_pci_dev(sc->dev); - - pci_iounmap(pdev, sc->mem); - pci_disable_device(pdev); - pci_release_region(pdev, 0); -} - -static bool ath_pci_eeprom_read(struct ath_hw *ah, u32 off, u16 *data) -{ - (void)REG_READ(ah, AR5416_EEPROM_OFFSET + (off << AR5416_EEPROM_S)); - - if (!ath9k_hw_wait(ah, - AR_EEPROM_STATUS_DATA, - AR_EEPROM_STATUS_DATA_BUSY | - AR_EEPROM_STATUS_DATA_PROT_ACCESS, 0, - AH_WAIT_TIMEOUT)) { - return false; - } - - *data = MS(REG_READ(ah, AR_EEPROM_STATUS_DATA), - AR_EEPROM_STATUS_DATA_VAL); - - return true; -} - -static struct ath_bus_ops ath_pci_bus_ops = { - .read_cachesize = ath_pci_read_cachesize, - .cleanup = ath_pci_cleanup, - .eeprom_read = ath_pci_eeprom_read, -}; - -static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - void __iomem *mem; - struct ath_wiphy *aphy; - struct ath_softc *sc; - struct ieee80211_hw *hw; - u8 csz; - u16 subsysid; - u32 val; - int ret = 0; - struct ath_hw *ah; - - if (pci_enable_device(pdev)) - return -EIO; - - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - - if (ret) { - printk(KERN_ERR "ath9k: 32-bit DMA not available\n"); - goto bad; - } - - ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - - if (ret) { - printk(KERN_ERR "ath9k: 32-bit DMA consistent " - "DMA enable failed\n"); - goto bad; - } - - /* - * Cache line size is used to size and align various - * structures used to communicate with the hardware. - */ - pci_read_config_byte(pdev, PCI_CACHE_LINE_SIZE, &csz); - if (csz == 0) { - /* - * Linux 2.4.18 (at least) writes the cache line size - * register as a 16-bit wide register which is wrong. - * We must have this setup properly for rx buffer - * DMA to work so force a reasonable value here if it - * comes up zero. - */ - csz = L1_CACHE_BYTES / sizeof(u32); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, csz); - } - /* - * The default setting of latency timer yields poor results, - * set it to the value used by other systems. It may be worth - * tweaking this setting more. - */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, 0xa8); - - pci_set_master(pdev); - - /* - * Disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state. - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - ret = pci_request_region(pdev, 0, "ath9k"); - if (ret) { - dev_err(&pdev->dev, "PCI memory region reserve error\n"); - ret = -ENODEV; - goto bad; - } - - mem = pci_iomap(pdev, 0, 0); - if (!mem) { - printk(KERN_ERR "PCI memory map error\n") ; - ret = -EIO; - goto bad1; - } - - hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) + - sizeof(struct ath_softc), &ath9k_ops); - if (!hw) { - dev_err(&pdev->dev, "no memory for ieee80211_hw\n"); - ret = -ENOMEM; - goto bad2; - } - - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); - - aphy = hw->priv; - sc = (struct ath_softc *) (aphy + 1); - aphy->sc = sc; - aphy->hw = hw; - sc->pri_wiphy = aphy; - sc->hw = hw; - sc->dev = &pdev->dev; - sc->mem = mem; - sc->bus_ops = &ath_pci_bus_ops; - - pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); - ret = ath_init_device(id->device, sc, subsysid); - if (ret) { - dev_err(&pdev->dev, "failed to initialize device\n"); - goto bad3; - } - - /* setup interrupt service routine */ - - ret = request_irq(pdev->irq, ath_isr, IRQF_SHARED, "ath9k", sc); - if (ret) { - dev_err(&pdev->dev, "request_irq failed\n"); - goto bad4; - } - - sc->irq = pdev->irq; - - ah = sc->sc_ah; - printk(KERN_INFO - "%s: Atheros AR%s MAC/BB Rev:%x " - "AR%s RF Rev:%x: mem=0x%lx, irq=%d\n", - wiphy_name(hw->wiphy), - ath_mac_bb_name(ah->hw_version.macVersion), - ah->hw_version.macRev, - ath_rf_name((ah->hw_version.analog5GhzRev & AR_RADIO_SREV_MAJOR)), - ah->hw_version.phyRev, - (unsigned long)mem, pdev->irq); - - return 0; -bad4: - ath_detach(sc); -bad3: - ieee80211_free_hw(hw); -bad2: - pci_iounmap(pdev, mem); -bad1: - pci_release_region(pdev, 0); -bad: - pci_disable_device(pdev); - return ret; -} - -static void ath_pci_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - ath_cleanup(sc); -} - -#ifdef CONFIG_PM - -static int ath_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int ath_pci_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - u32 val; - int err; - - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) - return err; - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - /* Enable LED */ - ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin, - AR_GPIO_OUTPUT_MUX_AS_OUTPUT); - ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1); - - return 0; -} - -#endif /* CONFIG_PM */ - -MODULE_DEVICE_TABLE(pci, ath_pci_id_table); - -static struct pci_driver ath_pci_driver = { - .name = "ath9k", - .id_table = ath_pci_id_table, - .probe = ath_pci_probe, - .remove = ath_pci_remove, -#ifdef CONFIG_PM - .suspend = ath_pci_suspend, - .resume = ath_pci_resume, -#endif /* CONFIG_PM */ -}; - -int ath_pci_init(void) -{ - return pci_register_driver(&ath_pci_driver); -} - -void ath_pci_exit(void) -{ - pci_unregister_driver(&ath_pci_driver); -} diff --git a/drivers/net/wireless/ath/ath9k/phy.c b/drivers/net/wireless/ath/ath9k/phy.c deleted file mode 100644 index 63bf9a307c6a..000000000000 --- a/drivers/net/wireless/ath/ath9k/phy.c +++ /dev/null @@ -1,398 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -void -ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, u32 freqIndex, - int regWrites) -{ - REG_WRITE_ARRAY(&ah->iniBB_RfGain, freqIndex, regWrites); -} - -bool -ath9k_hw_set_channel(struct ath_hw *ah, struct ath9k_channel *chan) -{ - u32 channelSel = 0; - u32 bModeSynth = 0; - u32 aModeRefSel = 0; - u32 reg32 = 0; - u16 freq; - struct chan_centers centers; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - if (freq < 4800) { - u32 txctl; - - if (((freq - 2192) % 5) == 0) { - channelSel = ((freq - 672) * 2 - 3040) / 10; - bModeSynth = 0; - } else if (((freq - 2224) % 5) == 0) { - channelSel = ((freq - 704) * 2 - 3040) / 10; - bModeSynth = 1; - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return false; - } - - channelSel = (channelSel << 2) & 0xff; - channelSel = ath9k_hw_reverse_bits(channelSel, 8); - - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - - } else if ((freq % 20) == 0 && freq >= 5120) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 20 << 2), 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 10) == 0) { - channelSel = - ath9k_hw_reverse_bits(((freq - 4800) / 10 << 1), 8); - if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) - aModeRefSel = ath9k_hw_reverse_bits(2, 2); - else - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else if ((freq % 5) == 0) { - channelSel = ath9k_hw_reverse_bits((freq - 4800) / 5, 8); - aModeRefSel = ath9k_hw_reverse_bits(1, 2); - } else { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Invalid channel %u MHz\n", freq); - return false; - } - - reg32 = - (channelSel << 8) | (aModeRefSel << 2) | (bModeSynth << 1) | - (1 << 5) | 0x1; - - REG_WRITE(ah, AR_PHY(0x37), reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; - - return true; -} - -void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan) -{ - u16 bMode, fracMode, aModeRefSel = 0; - u32 freq, ndiv, channelSel = 0, channelFrac = 0, reg32 = 0; - struct chan_centers centers; - u32 refDivA = 24; - - ath9k_hw_get_channel_centers(ah, chan, ¢ers); - freq = centers.synth_center; - - reg32 = REG_READ(ah, AR_PHY_SYNTH_CONTROL); - reg32 &= 0xc0000000; - - if (freq < 4800) { - u32 txctl; - - bMode = 1; - fracMode = 1; - aModeRefSel = 0; - channelSel = (freq * 0x10000) / 15; - - txctl = REG_READ(ah, AR_PHY_CCK_TX_CTRL); - if (freq == 2484) { - - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl | AR_PHY_CCK_TX_CTRL_JAPAN); - } else { - REG_WRITE(ah, AR_PHY_CCK_TX_CTRL, - txctl & ~AR_PHY_CCK_TX_CTRL_JAPAN); - } - } else { - bMode = 0; - fracMode = 0; - - switch(ah->eep_ops->get_eeprom(ah, EEP_FRAC_N_5G)) { - case 0: - if ((freq % 20) == 0) { - aModeRefSel = 3; - } else if ((freq % 10) == 0) { - aModeRefSel = 2; - } - if (aModeRefSel) - break; - case 1: - default: - aModeRefSel = 0; - fracMode = 1; - refDivA = 1; - channelSel = (freq * 0x8000) / 15; - - REG_RMW_FIELD(ah, AR_AN_SYNTH9, - AR_AN_SYNTH9_REFDIVA, refDivA); - - } - - if (!fracMode) { - ndiv = (freq * (refDivA >> aModeRefSel)) / 60; - channelSel = ndiv & 0x1ff; - channelFrac = (ndiv & 0xfffffe00) * 2; - channelSel = (channelSel << 17) | channelFrac; - } - } - - reg32 = reg32 | - (bMode << 29) | - (fracMode << 28) | (aModeRefSel << 26) | (channelSel); - - REG_WRITE(ah, AR_PHY_SYNTH_CONTROL, reg32); - - ah->curchan = chan; - ah->curchan_rad_index = -1; -} - -static void -ath9k_phy_modify_rx_buffer(u32 *rfBuf, u32 reg32, - u32 numBits, u32 firstBit, - u32 column) -{ - u32 tmp32, mask, arrayEntry, lastBit; - int32_t bitPosition, bitsLeft; - - tmp32 = ath9k_hw_reverse_bits(reg32, numBits); - arrayEntry = (firstBit - 1) / 8; - bitPosition = (firstBit - 1) % 8; - bitsLeft = numBits; - while (bitsLeft > 0) { - lastBit = (bitPosition + bitsLeft > 8) ? - 8 : bitPosition + bitsLeft; - mask = (((1 << lastBit) - 1) ^ ((1 << bitPosition) - 1)) << - (column * 8); - rfBuf[arrayEntry] &= ~mask; - rfBuf[arrayEntry] |= ((tmp32 << bitPosition) << - (column * 8)) & mask; - bitsLeft -= 8 - bitPosition; - tmp32 = tmp32 >> (8 - bitPosition); - bitPosition = 0; - arrayEntry++; - } -} - -bool -ath9k_hw_set_rf_regs(struct ath_hw *ah, struct ath9k_channel *chan, - u16 modesIndex) -{ - u32 eepMinorRev; - u32 ob5GHz = 0, db5GHz = 0; - u32 ob2GHz = 0, db2GHz = 0; - int regWrites = 0; - - if (AR_SREV_9280_10_OR_LATER(ah)) - return true; - - eepMinorRev = ah->eep_ops->get_eeprom(ah, EEP_MINOR_REV); - - RF_BANK_SETUP(ah->analogBank0Data, &ah->iniBank0, 1); - - RF_BANK_SETUP(ah->analogBank1Data, &ah->iniBank1, 1); - - RF_BANK_SETUP(ah->analogBank2Data, &ah->iniBank2, 1); - - RF_BANK_SETUP(ah->analogBank3Data, &ah->iniBank3, - modesIndex); - { - int i; - for (i = 0; i < ah->iniBank6TPC.ia_rows; i++) { - ah->analogBank6Data[i] = - INI_RA(&ah->iniBank6TPC, i, modesIndex); - } - } - - if (eepMinorRev >= 2) { - if (IS_CHAN_2GHZ(chan)) { - ob2GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_2); - db2GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_2); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - ob2GHz, 3, 197, 0); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - db2GHz, 3, 194, 0); - } else { - ob5GHz = ah->eep_ops->get_eeprom(ah, EEP_OB_5); - db5GHz = ah->eep_ops->get_eeprom(ah, EEP_DB_5); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - ob5GHz, 3, 203, 0); - ath9k_phy_modify_rx_buffer(ah->analogBank6Data, - db5GHz, 3, 200, 0); - } - } - - RF_BANK_SETUP(ah->analogBank7Data, &ah->iniBank7, 1); - - REG_WRITE_RF_ARRAY(&ah->iniBank0, ah->analogBank0Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank1, ah->analogBank1Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank2, ah->analogBank2Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank3, ah->analogBank3Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank6TPC, ah->analogBank6Data, - regWrites); - REG_WRITE_RF_ARRAY(&ah->iniBank7, ah->analogBank7Data, - regWrites); - - return true; -} - -void -ath9k_hw_rf_free(struct ath_hw *ah) -{ -#define ATH_FREE_BANK(bank) do { \ - kfree(bank); \ - bank = NULL; \ - } while (0); - - ATH_FREE_BANK(ah->analogBank0Data); - ATH_FREE_BANK(ah->analogBank1Data); - ATH_FREE_BANK(ah->analogBank2Data); - ATH_FREE_BANK(ah->analogBank3Data); - ATH_FREE_BANK(ah->analogBank6Data); - ATH_FREE_BANK(ah->analogBank6TPCData); - ATH_FREE_BANK(ah->analogBank7Data); - ATH_FREE_BANK(ah->addac5416_21); - ATH_FREE_BANK(ah->bank6Temp); -#undef ATH_FREE_BANK -} - -bool ath9k_hw_init_rf(struct ath_hw *ah, int *status) -{ - if (!AR_SREV_9280_10_OR_LATER(ah)) { - ah->analogBank0Data = - kzalloc((sizeof(u32) * - ah->iniBank0.ia_rows), GFP_KERNEL); - ah->analogBank1Data = - kzalloc((sizeof(u32) * - ah->iniBank1.ia_rows), GFP_KERNEL); - ah->analogBank2Data = - kzalloc((sizeof(u32) * - ah->iniBank2.ia_rows), GFP_KERNEL); - ah->analogBank3Data = - kzalloc((sizeof(u32) * - ah->iniBank3.ia_rows), GFP_KERNEL); - ah->analogBank6Data = - kzalloc((sizeof(u32) * - ah->iniBank6.ia_rows), GFP_KERNEL); - ah->analogBank6TPCData = - kzalloc((sizeof(u32) * - ah->iniBank6TPC.ia_rows), GFP_KERNEL); - ah->analogBank7Data = - kzalloc((sizeof(u32) * - ah->iniBank7.ia_rows), GFP_KERNEL); - - if (ah->analogBank0Data == NULL - || ah->analogBank1Data == NULL - || ah->analogBank2Data == NULL - || ah->analogBank3Data == NULL - || ah->analogBank6Data == NULL - || ah->analogBank6TPCData == NULL - || ah->analogBank7Data == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate RF banks\n"); - *status = -ENOMEM; - return false; - } - - ah->addac5416_21 = - kzalloc((sizeof(u32) * - ah->iniAddac.ia_rows * - ah->iniAddac.ia_columns), GFP_KERNEL); - if (ah->addac5416_21 == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate addac5416_21\n"); - *status = -ENOMEM; - return false; - } - - ah->bank6Temp = - kzalloc((sizeof(u32) * - ah->iniBank6.ia_rows), GFP_KERNEL); - if (ah->bank6Temp == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_FATAL, - "Cannot allocate bank6Temp\n"); - *status = -ENOMEM; - return false; - } - } - - return true; -} - -void -ath9k_hw_decrease_chain_power(struct ath_hw *ah, struct ath9k_channel *chan) -{ - int i, regWrites = 0; - u32 bank6SelMask; - u32 *bank6Temp = ah->bank6Temp; - - switch (ah->config.diversity_control) { - case ATH9K_ANT_FIXED_A: - bank6SelMask = - (ah->config.antenna_switch_swap & ANTSWAP_AB) ? - REDUCE_CHAIN_0 : REDUCE_CHAIN_1; - break; - case ATH9K_ANT_FIXED_B: - bank6SelMask = - (ah->config.antenna_switch_swap & ANTSWAP_AB) ? - REDUCE_CHAIN_1 : REDUCE_CHAIN_0; - break; - case ATH9K_ANT_VARIABLE: - return; - break; - default: - return; - break; - } - - for (i = 0; i < ah->iniBank6.ia_rows; i++) - bank6Temp[i] = ah->analogBank6Data[i]; - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, bank6SelMask); - - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 189, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 190, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 191, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 192, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 193, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 222, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 245, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 246, 0); - ath9k_phy_modify_rx_buffer(bank6Temp, 1, 1, 247, 0); - - REG_WRITE_RF_ARRAY(&ah->iniBank6, bank6Temp, regWrites); - - REG_WRITE(ah, AR_PHY_BASE + 0xD8, 0x00000053); -#ifdef ALTER_SWITCH - REG_WRITE(ah, PHY_SWITCH_CHAIN_0, - (REG_READ(ah, PHY_SWITCH_CHAIN_0) & ~0x38) - | ((REG_READ(ah, PHY_SWITCH_CHAIN_0) >> 3) & 0x38)); -#endif -} diff --git a/drivers/net/wireless/ath/ath9k/phy.h b/drivers/net/wireless/ath/ath9k/phy.h deleted file mode 100644 index b36ec9454460..000000000000 --- a/drivers/net/wireless/ath/ath9k/phy.h +++ /dev/null @@ -1,609 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef PHY_H -#define PHY_H - -void ath9k_hw_ar9280_set_channel(struct ath_hw *ah, - struct ath9k_channel - *chan); -bool ath9k_hw_set_channel(struct ath_hw *ah, - struct ath9k_channel *chan); -void ath9k_hw_write_regs(struct ath_hw *ah, u32 modesIndex, - u32 freqIndex, int regWrites); -bool ath9k_hw_set_rf_regs(struct ath_hw *ah, - struct ath9k_channel *chan, - u16 modesIndex); -void ath9k_hw_decrease_chain_power(struct ath_hw *ah, - struct ath9k_channel *chan); -bool ath9k_hw_init_rf(struct ath_hw *ah, - int *status); - -#define AR_PHY_BASE 0x9800 -#define AR_PHY(_n) (AR_PHY_BASE + ((_n)<<2)) - -#define AR_PHY_TEST 0x9800 -#define PHY_AGC_CLR 0x10000000 -#define RFSILENT_BB 0x00002000 - -#define AR_PHY_TURBO 0x9804 -#define AR_PHY_FC_TURBO_MODE 0x00000001 -#define AR_PHY_FC_TURBO_SHORT 0x00000002 -#define AR_PHY_FC_DYN2040_EN 0x00000004 -#define AR_PHY_FC_DYN2040_PRI_ONLY 0x00000008 -#define AR_PHY_FC_DYN2040_PRI_CH 0x00000010 -#define AR_PHY_FC_DYN2040_EXT_CH 0x00000020 -#define AR_PHY_FC_HT_EN 0x00000040 -#define AR_PHY_FC_SHORT_GI_40 0x00000080 -#define AR_PHY_FC_WALSH 0x00000100 -#define AR_PHY_FC_SINGLE_HT_LTF1 0x00000200 -#define AR_PHY_FC_ENABLE_DAC_FIFO 0x00000800 - -#define AR_PHY_TEST2 0x9808 - -#define AR_PHY_TIMING2 0x9810 -#define AR_PHY_TIMING3 0x9814 -#define AR_PHY_TIMING3_DSC_MAN 0xFFFE0000 -#define AR_PHY_TIMING3_DSC_MAN_S 17 -#define AR_PHY_TIMING3_DSC_EXP 0x0001E000 -#define AR_PHY_TIMING3_DSC_EXP_S 13 - -#define AR_PHY_CHIP_ID 0x9818 -#define AR_PHY_CHIP_ID_REV_0 0x80 -#define AR_PHY_CHIP_ID_REV_1 0x81 -#define AR_PHY_CHIP_ID_9160_REV_0 0xb0 - -#define AR_PHY_ACTIVE 0x981C -#define AR_PHY_ACTIVE_EN 0x00000001 -#define AR_PHY_ACTIVE_DIS 0x00000000 - -#define AR_PHY_RF_CTL2 0x9824 -#define AR_PHY_TX_END_DATA_START 0x000000FF -#define AR_PHY_TX_END_DATA_START_S 0 -#define AR_PHY_TX_END_PA_ON 0x0000FF00 -#define AR_PHY_TX_END_PA_ON_S 8 - -#define AR_PHY_RF_CTL3 0x9828 -#define AR_PHY_TX_END_TO_A2_RX_ON 0x00FF0000 -#define AR_PHY_TX_END_TO_A2_RX_ON_S 16 - -#define AR_PHY_ADC_CTL 0x982C -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN 0x00000003 -#define AR_PHY_ADC_CTL_OFF_INBUFGAIN_S 0 -#define AR_PHY_ADC_CTL_OFF_PWDDAC 0x00002000 -#define AR_PHY_ADC_CTL_OFF_PWDBANDGAP 0x00004000 -#define AR_PHY_ADC_CTL_OFF_PWDADC 0x00008000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN 0x00030000 -#define AR_PHY_ADC_CTL_ON_INBUFGAIN_S 16 - -#define AR_PHY_ADC_SERIAL_CTL 0x9830 -#define AR_PHY_SEL_INTERNAL_ADDAC 0x00000000 -#define AR_PHY_SEL_EXTERNAL_RADIO 0x00000001 - -#define AR_PHY_RF_CTL4 0x9834 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF 0xFF000000 -#define AR_PHY_RF_CTL4_TX_END_XPAB_OFF_S 24 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF 0x00FF0000 -#define AR_PHY_RF_CTL4_TX_END_XPAA_OFF_S 16 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON 0x0000FF00 -#define AR_PHY_RF_CTL4_FRAME_XPAB_ON_S 8 -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON 0x000000FF -#define AR_PHY_RF_CTL4_FRAME_XPAA_ON_S 0 - -#define AR_PHY_TSTDAC_CONST 0x983c - -#define AR_PHY_SETTLING 0x9844 -#define AR_PHY_SETTLING_SWITCH 0x00003F80 -#define AR_PHY_SETTLING_SWITCH_S 7 - -#define AR_PHY_RXGAIN 0x9848 -#define AR_PHY_RXGAIN_TXRX_ATTEN 0x0003F000 -#define AR_PHY_RXGAIN_TXRX_ATTEN_S 12 -#define AR_PHY_RXGAIN_TXRX_RF_MAX 0x007C0000 -#define AR_PHY_RXGAIN_TXRX_RF_MAX_S 18 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN 0x00003F80 -#define AR9280_PHY_RXGAIN_TXRX_ATTEN_S 7 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN 0x001FC000 -#define AR9280_PHY_RXGAIN_TXRX_MARGIN_S 14 - -#define AR_PHY_DESIRED_SZ 0x9850 -#define AR_PHY_DESIRED_SZ_ADC 0x000000FF -#define AR_PHY_DESIRED_SZ_ADC_S 0 -#define AR_PHY_DESIRED_SZ_PGA 0x0000FF00 -#define AR_PHY_DESIRED_SZ_PGA_S 8 -#define AR_PHY_DESIRED_SZ_TOT_DES 0x0FF00000 -#define AR_PHY_DESIRED_SZ_TOT_DES_S 20 - -#define AR_PHY_FIND_SIG 0x9858 -#define AR_PHY_FIND_SIG_FIRSTEP 0x0003F000 -#define AR_PHY_FIND_SIG_FIRSTEP_S 12 -#define AR_PHY_FIND_SIG_FIRPWR 0x03FC0000 -#define AR_PHY_FIND_SIG_FIRPWR_S 18 - -#define AR_PHY_AGC_CTL1 0x985C -#define AR_PHY_AGC_CTL1_COARSE_LOW 0x00007F80 -#define AR_PHY_AGC_CTL1_COARSE_LOW_S 7 -#define AR_PHY_AGC_CTL1_COARSE_HIGH 0x003F8000 -#define AR_PHY_AGC_CTL1_COARSE_HIGH_S 15 - -#define AR_PHY_AGC_CONTROL 0x9860 -#define AR_PHY_AGC_CONTROL_CAL 0x00000001 -#define AR_PHY_AGC_CONTROL_NF 0x00000002 -#define AR_PHY_AGC_CONTROL_ENABLE_NF 0x00008000 -#define AR_PHY_AGC_CONTROL_FLTR_CAL 0x00010000 -#define AR_PHY_AGC_CONTROL_NO_UPDATE_NF 0x00020000 - -#define AR_PHY_CCA 0x9864 -#define AR_PHY_MINCCA_PWR 0x0FF80000 -#define AR_PHY_MINCCA_PWR_S 19 -#define AR_PHY_CCA_THRESH62 0x0007F000 -#define AR_PHY_CCA_THRESH62_S 12 -#define AR9280_PHY_MINCCA_PWR 0x1FF00000 -#define AR9280_PHY_MINCCA_PWR_S 20 -#define AR9280_PHY_CCA_THRESH62 0x000FF000 -#define AR9280_PHY_CCA_THRESH62_S 12 - -#define AR_PHY_SFCORR_LOW 0x986C -#define AR_PHY_SFCORR_LOW_USE_SELF_CORR_LOW 0x00000001 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW 0x00003F00 -#define AR_PHY_SFCORR_LOW_M2COUNT_THR_LOW_S 8 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW 0x001FC000 -#define AR_PHY_SFCORR_LOW_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW 0x0FE00000 -#define AR_PHY_SFCORR_LOW_M2_THRESH_LOW_S 21 - -#define AR_PHY_SFCORR 0x9868 -#define AR_PHY_SFCORR_M2COUNT_THR 0x0000001F -#define AR_PHY_SFCORR_M2COUNT_THR_S 0 -#define AR_PHY_SFCORR_M1_THRESH 0x00FE0000 -#define AR_PHY_SFCORR_M1_THRESH_S 17 -#define AR_PHY_SFCORR_M2_THRESH 0x7F000000 -#define AR_PHY_SFCORR_M2_THRESH_S 24 - -#define AR_PHY_SLEEP_CTR_CONTROL 0x9870 -#define AR_PHY_SLEEP_CTR_LIMIT 0x9874 -#define AR_PHY_SYNTH_CONTROL 0x9874 -#define AR_PHY_SLEEP_SCAL 0x9878 - -#define AR_PHY_PLL_CTL 0x987c -#define AR_PHY_PLL_CTL_40 0xaa -#define AR_PHY_PLL_CTL_40_5413 0x04 -#define AR_PHY_PLL_CTL_44 0xab -#define AR_PHY_PLL_CTL_44_2133 0xeb -#define AR_PHY_PLL_CTL_40_2133 0xea - -#define AR_PHY_SPECTRAL_SCAN 0x9912 -#define AR_PHY_SPECTRAL_SCAN_ENABLE 0x1 - -#define AR_PHY_RX_DELAY 0x9914 -#define AR_PHY_SEARCH_START_DELAY 0x9918 -#define AR_PHY_RX_DELAY_DELAY 0x00003FFF - -#define AR_PHY_TIMING_CTRL4(_i) (0x9920 + ((_i) << 12)) -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF 0x01F -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_Q_COFF_S 0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF 0x7E0 -#define AR_PHY_TIMING_CTRL4_IQCORR_Q_I_COFF_S 5 -#define AR_PHY_TIMING_CTRL4_IQCORR_ENABLE 0x800 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX 0xF000 -#define AR_PHY_TIMING_CTRL4_IQCAL_LOG_COUNT_MAX_S 12 -#define AR_PHY_TIMING_CTRL4_DO_CAL 0x10000 - -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_RSSI 0x80000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_SPUR_FILTER 0x40000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_CHAN_MASK 0x20000000 -#define AR_PHY_TIMING_CTRL4_ENABLE_PILOT_MASK 0x10000000 - -#define AR_PHY_TIMING5 0x9924 -#define AR_PHY_TIMING5_CYCPWR_THR1 0x000000FE -#define AR_PHY_TIMING5_CYCPWR_THR1_S 1 - -#define AR_PHY_POWER_TX_RATE1 0x9934 -#define AR_PHY_POWER_TX_RATE2 0x9938 -#define AR_PHY_POWER_TX_RATE_MAX 0x993c -#define AR_PHY_POWER_TX_RATE_MAX_TPC_ENABLE 0x00000040 - -#define AR_PHY_FRAME_CTL 0x9944 -#define AR_PHY_FRAME_CTL_TX_CLIP 0x00000038 -#define AR_PHY_FRAME_CTL_TX_CLIP_S 3 - -#define AR_PHY_TXPWRADJ 0x994C -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA 0x00000FC0 -#define AR_PHY_TXPWRADJ_CCK_GAIN_DELTA_S 6 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX 0x00FC0000 -#define AR_PHY_TXPWRADJ_CCK_PCDAC_INDEX_S 18 - -#define AR_PHY_RADAR_EXT 0x9940 -#define AR_PHY_RADAR_EXT_ENA 0x00004000 - -#define AR_PHY_RADAR_0 0x9954 -#define AR_PHY_RADAR_0_ENA 0x00000001 -#define AR_PHY_RADAR_0_FFT_ENA 0x80000000 -#define AR_PHY_RADAR_0_INBAND 0x0000003e -#define AR_PHY_RADAR_0_INBAND_S 1 -#define AR_PHY_RADAR_0_PRSSI 0x00000FC0 -#define AR_PHY_RADAR_0_PRSSI_S 6 -#define AR_PHY_RADAR_0_HEIGHT 0x0003F000 -#define AR_PHY_RADAR_0_HEIGHT_S 12 -#define AR_PHY_RADAR_0_RRSSI 0x00FC0000 -#define AR_PHY_RADAR_0_RRSSI_S 18 -#define AR_PHY_RADAR_0_FIRPWR 0x7F000000 -#define AR_PHY_RADAR_0_FIRPWR_S 24 - -#define AR_PHY_RADAR_1 0x9958 -#define AR_PHY_RADAR_1_RELPWR_ENA 0x00800000 -#define AR_PHY_RADAR_1_USE_FIR128 0x00400000 -#define AR_PHY_RADAR_1_RELPWR_THRESH 0x003F0000 -#define AR_PHY_RADAR_1_RELPWR_THRESH_S 16 -#define AR_PHY_RADAR_1_BLOCK_CHECK 0x00008000 -#define AR_PHY_RADAR_1_MAX_RRSSI 0x00004000 -#define AR_PHY_RADAR_1_RELSTEP_CHECK 0x00002000 -#define AR_PHY_RADAR_1_RELSTEP_THRESH 0x00001F00 -#define AR_PHY_RADAR_1_RELSTEP_THRESH_S 8 -#define AR_PHY_RADAR_1_MAXLEN 0x000000FF -#define AR_PHY_RADAR_1_MAXLEN_S 0 - -#define AR_PHY_SWITCH_CHAIN_0 0x9960 -#define AR_PHY_SWITCH_COM 0x9964 - -#define AR_PHY_SIGMA_DELTA 0x996C -#define AR_PHY_SIGMA_DELTA_ADC_SEL 0x00000003 -#define AR_PHY_SIGMA_DELTA_ADC_SEL_S 0 -#define AR_PHY_SIGMA_DELTA_FILT2 0x000000F8 -#define AR_PHY_SIGMA_DELTA_FILT2_S 3 -#define AR_PHY_SIGMA_DELTA_FILT1 0x00001F00 -#define AR_PHY_SIGMA_DELTA_FILT1_S 8 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP 0x01FFE000 -#define AR_PHY_SIGMA_DELTA_ADC_CLIP_S 13 - -#define AR_PHY_RESTART 0x9970 -#define AR_PHY_RESTART_DIV_GC 0x001C0000 -#define AR_PHY_RESTART_DIV_GC_S 18 - -#define AR_PHY_RFBUS_REQ 0x997C -#define AR_PHY_RFBUS_REQ_EN 0x00000001 - -#define AR_PHY_TIMING7 0x9980 -#define AR_PHY_TIMING8 0x9984 -#define AR_PHY_TIMING8_PILOT_MASK_2 0x000FFFFF -#define AR_PHY_TIMING8_PILOT_MASK_2_S 0 - -#define AR_PHY_BIN_MASK2_1 0x9988 -#define AR_PHY_BIN_MASK2_2 0x998c -#define AR_PHY_BIN_MASK2_3 0x9990 -#define AR_PHY_BIN_MASK2_4 0x9994 - -#define AR_PHY_BIN_MASK_1 0x9900 -#define AR_PHY_BIN_MASK_2 0x9904 -#define AR_PHY_BIN_MASK_3 0x9908 - -#define AR_PHY_MASK_CTL 0x990c - -#define AR_PHY_BIN_MASK2_4_MASK_4 0x00003FFF -#define AR_PHY_BIN_MASK2_4_MASK_4_S 0 - -#define AR_PHY_TIMING9 0x9998 -#define AR_PHY_TIMING10 0x999c -#define AR_PHY_TIMING10_PILOT_MASK_2 0x000FFFFF -#define AR_PHY_TIMING10_PILOT_MASK_2_S 0 - -#define AR_PHY_TIMING11 0x99a0 -#define AR_PHY_TIMING11_SPUR_DELTA_PHASE 0x000FFFFF -#define AR_PHY_TIMING11_SPUR_DELTA_PHASE_S 0 -#define AR_PHY_TIMING11_SPUR_FREQ_SD 0x3FF00000 -#define AR_PHY_TIMING11_SPUR_FREQ_SD_S 20 -#define AR_PHY_TIMING11_USE_SPUR_IN_AGC 0x40000000 -#define AR_PHY_TIMING11_USE_SPUR_IN_SELFCOR 0x80000000 - -#define AR_PHY_RX_CHAINMASK 0x99a4 -#define AR_PHY_NEW_ADC_DC_GAIN_CORR(_i) (0x99b4 + ((_i) << 12)) -#define AR_PHY_NEW_ADC_GAIN_CORR_ENABLE 0x40000000 -#define AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE 0x80000000 - -#define AR_PHY_MULTICHAIN_GAIN_CTL 0x99ac -#define AR_PHY_9285_ANT_DIV_CTL_ALL 0x7f000000 -#define AR_PHY_9285_ANT_DIV_CTL 0x01000000 -#define AR_PHY_9285_ANT_DIV_CTL_S 24 -#define AR_PHY_9285_ANT_DIV_ALT_LNACONF 0x06000000 -#define AR_PHY_9285_ANT_DIV_ALT_LNACONF_S 25 -#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF 0x18000000 -#define AR_PHY_9285_ANT_DIV_MAIN_LNACONF_S 27 -#define AR_PHY_9285_ANT_DIV_ALT_GAINTB 0x20000000 -#define AR_PHY_9285_ANT_DIV_ALT_GAINTB_S 29 -#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB 0x40000000 -#define AR_PHY_9285_ANT_DIV_MAIN_GAINTB_S 30 -#define AR_PHY_9285_ANT_DIV_LNA1 2 -#define AR_PHY_9285_ANT_DIV_LNA2 1 -#define AR_PHY_9285_ANT_DIV_LNA1_PLUS_LNA2 3 -#define AR_PHY_9285_ANT_DIV_LNA1_MINUS_LNA2 0 -#define AR_PHY_9285_ANT_DIV_GAINTB_0 0 -#define AR_PHY_9285_ANT_DIV_GAINTB_1 1 - -#define AR_PHY_EXT_CCA0 0x99b8 -#define AR_PHY_EXT_CCA0_THRESH62 0x000000FF -#define AR_PHY_EXT_CCA0_THRESH62_S 0 - -#define AR_PHY_EXT_CCA 0x99bc -#define AR_PHY_EXT_CCA_CYCPWR_THR1 0x0000FE00 -#define AR_PHY_EXT_CCA_CYCPWR_THR1_S 9 -#define AR_PHY_EXT_CCA_THRESH62 0x007F0000 -#define AR_PHY_EXT_CCA_THRESH62_S 16 -#define AR_PHY_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_EXT_MINCCA_PWR 0x01FF0000 -#define AR9280_PHY_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_SFCORR_EXT 0x99c0 -#define AR_PHY_SFCORR_EXT_M1_THRESH 0x0000007F -#define AR_PHY_SFCORR_EXT_M1_THRESH_S 0 -#define AR_PHY_SFCORR_EXT_M2_THRESH 0x00003F80 -#define AR_PHY_SFCORR_EXT_M2_THRESH_S 7 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW 0x001FC000 -#define AR_PHY_SFCORR_EXT_M1_THRESH_LOW_S 14 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW 0x0FE00000 -#define AR_PHY_SFCORR_EXT_M2_THRESH_LOW_S 21 -#define AR_PHY_SFCORR_SPUR_SUBCHNL_SD_S 28 - -#define AR_PHY_HALFGI 0x99D0 -#define AR_PHY_HALFGI_DSC_MAN 0x0007FFF0 -#define AR_PHY_HALFGI_DSC_MAN_S 4 -#define AR_PHY_HALFGI_DSC_EXP 0x0000000F -#define AR_PHY_HALFGI_DSC_EXP_S 0 - -#define AR_PHY_CHAN_INFO_MEMORY 0x99DC -#define AR_PHY_CHAN_INFO_MEMORY_CAPTURE_MASK 0x0001 - -#define AR_PHY_HEAVY_CLIP_ENABLE 0x99E0 - -#define AR_PHY_HEAVY_CLIP_FACTOR_RIFS 0x99EC -#define AR_PHY_RIFS_INIT_DELAY 0x03ff0000 - -#define AR_PHY_M_SLEEP 0x99f0 -#define AR_PHY_REFCLKDLY 0x99f4 -#define AR_PHY_REFCLKPD 0x99f8 - -#define AR_PHY_CALMODE 0x99f0 - -#define AR_PHY_CALMODE_IQ 0x00000000 -#define AR_PHY_CALMODE_ADC_GAIN 0x00000001 -#define AR_PHY_CALMODE_ADC_DC_PER 0x00000002 -#define AR_PHY_CALMODE_ADC_DC_INIT 0x00000003 - -#define AR_PHY_CAL_MEAS_0(_i) (0x9c10 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_1(_i) (0x9c14 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_2(_i) (0x9c18 + ((_i) << 12)) -#define AR_PHY_CAL_MEAS_3(_i) (0x9c1c + ((_i) << 12)) - -#define AR_PHY_CURRENT_RSSI 0x9c1c -#define AR9280_PHY_CURRENT_RSSI 0x9c3c - -#define AR_PHY_RFBUS_GRANT 0x9C20 -#define AR_PHY_RFBUS_GRANT_EN 0x00000001 - -#define AR_PHY_CHAN_INFO_GAIN_DIFF 0x9CF4 -#define AR_PHY_CHAN_INFO_GAIN_DIFF_UPPER_LIMIT 320 - -#define AR_PHY_CHAN_INFO_GAIN 0x9CFC - -#define AR_PHY_MODE 0xA200 -#define AR_PHY_MODE_ASYNCFIFO 0x80 -#define AR_PHY_MODE_AR2133 0x08 -#define AR_PHY_MODE_AR5111 0x00 -#define AR_PHY_MODE_AR5112 0x08 -#define AR_PHY_MODE_DYNAMIC 0x04 -#define AR_PHY_MODE_RF2GHZ 0x02 -#define AR_PHY_MODE_RF5GHZ 0x00 -#define AR_PHY_MODE_CCK 0x01 -#define AR_PHY_MODE_OFDM 0x00 -#define AR_PHY_MODE_DYN_CCK_DISABLE 0x100 - -#define AR_PHY_CCK_TX_CTRL 0xA204 -#define AR_PHY_CCK_TX_CTRL_JAPAN 0x00000010 -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK 0x0000000C -#define AR_PHY_CCK_TX_CTRL_TX_DAC_SCALE_CCK_S 2 - -#define AR_PHY_CCK_DETECT 0xA208 -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK 0x0000003F -#define AR_PHY_CCK_DETECT_WEAK_SIG_THR_CCK_S 0 -/* [12:6] settling time for antenna switch */ -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME 0x00001FC0 -#define AR_PHY_CCK_DETECT_ANT_SWITCH_TIME_S 6 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV 0x2000 -#define AR_PHY_CCK_DETECT_BB_ENABLE_ANT_FAST_DIV_S 13 - -#define AR_PHY_GAIN_2GHZ 0xA20C -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN 0x00FC0000 -#define AR_PHY_GAIN_2GHZ_RXTX_MARGIN_S 18 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN 0x00003C00 -#define AR_PHY_GAIN_2GHZ_BSW_MARGIN_S 10 -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN 0x0000001F -#define AR_PHY_GAIN_2GHZ_BSW_ATTEN_S 0 - -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN 0x003E0000 -#define AR_PHY_GAIN_2GHZ_XATTEN2_MARGIN_S 17 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN 0x0001F000 -#define AR_PHY_GAIN_2GHZ_XATTEN1_MARGIN_S 12 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB 0x00000FC0 -#define AR_PHY_GAIN_2GHZ_XATTEN2_DB_S 6 -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB 0x0000003F -#define AR_PHY_GAIN_2GHZ_XATTEN1_DB_S 0 - -#define AR_PHY_CCK_RXCTRL4 0xA21C -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT 0x01F80000 -#define AR_PHY_CCK_RXCTRL4_FREQ_EST_SHORT_S 19 - -#define AR_PHY_DAG_CTRLCCK 0xA228 -#define AR_PHY_DAG_CTRLCCK_EN_RSSI_THR 0x00000200 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR 0x0001FC00 -#define AR_PHY_DAG_CTRLCCK_RSSI_THR_S 10 - -#define AR_PHY_FORCE_CLKEN_CCK 0xA22C -#define AR_PHY_FORCE_CLKEN_CCK_MRC_MUX 0x00000040 - -#define AR_PHY_POWER_TX_RATE3 0xA234 -#define AR_PHY_POWER_TX_RATE4 0xA238 - -#define AR_PHY_SCRM_SEQ_XR 0xA23C -#define AR_PHY_HEADER_DETECT_XR 0xA240 -#define AR_PHY_CHIRP_DETECTED_XR 0xA244 -#define AR_PHY_BLUETOOTH 0xA254 - -#define AR_PHY_TPCRG1 0xA258 -#define AR_PHY_TPCRG1_NUM_PD_GAIN 0x0000c000 -#define AR_PHY_TPCRG1_NUM_PD_GAIN_S 14 - -#define AR_PHY_TPCRG1_PD_GAIN_1 0x00030000 -#define AR_PHY_TPCRG1_PD_GAIN_1_S 16 -#define AR_PHY_TPCRG1_PD_GAIN_2 0x000C0000 -#define AR_PHY_TPCRG1_PD_GAIN_2_S 18 -#define AR_PHY_TPCRG1_PD_GAIN_3 0x00300000 -#define AR_PHY_TPCRG1_PD_GAIN_3_S 20 - -#define AR_PHY_TPCRG1_PD_CAL_ENABLE 0x00400000 -#define AR_PHY_TPCRG1_PD_CAL_ENABLE_S 22 - -#define AR_PHY_TX_PWRCTRL4 0xa264 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID 0x00000001 -#define AR_PHY_TX_PWRCTRL_PD_AVG_VALID_S 0 -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT 0x000001FE -#define AR_PHY_TX_PWRCTRL_PD_AVG_OUT_S 1 - -#define AR_PHY_TX_PWRCTRL6_0 0xa270 -#define AR_PHY_TX_PWRCTRL6_1 0xb270 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE 0x03000000 -#define AR_PHY_TX_PWRCTRL_ERR_EST_MODE_S 24 - -#define AR_PHY_TX_PWRCTRL7 0xa274 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN 0x01F80000 -#define AR_PHY_TX_PWRCTRL_INIT_TX_GAIN_S 19 - -#define AR_PHY_TX_PWRCTRL9 0xa27C -#define AR_PHY_TX_DESIRED_SCALE_CCK 0x00007C00 -#define AR_PHY_TX_DESIRED_SCALE_CCK_S 10 -#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL 0x80000000 -#define AR_PHY_TX_PWRCTRL9_RES_DC_REMOVAL_S 31 - -#define AR_PHY_TX_GAIN_TBL1 0xa300 -#define AR_PHY_TX_GAIN 0x0007F000 -#define AR_PHY_TX_GAIN_S 12 - -#define AR_PHY_CH0_TX_PWRCTRL11 0xa398 -#define AR_PHY_CH1_TX_PWRCTRL11 0xb398 -#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP 0x0000FC00 -#define AR_PHY_TX_PWRCTRL_OLPC_TEMP_COMP_S 10 - -#define AR_PHY_VIT_MASK2_M_46_61 0xa3a0 -#define AR_PHY_MASK2_M_31_45 0xa3a4 -#define AR_PHY_MASK2_M_16_30 0xa3a8 -#define AR_PHY_MASK2_M_00_15 0xa3ac -#define AR_PHY_MASK2_P_15_01 0xa3b8 -#define AR_PHY_MASK2_P_30_16 0xa3bc -#define AR_PHY_MASK2_P_45_31 0xa3c0 -#define AR_PHY_MASK2_P_61_45 0xa3c4 -#define AR_PHY_SPUR_REG 0x994c - -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL (0xFF << 18) -#define AR_PHY_SPUR_REG_MASK_RATE_CNTL_S 18 - -#define AR_PHY_SPUR_REG_ENABLE_MASK_PPM 0x20000 -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT (0xFF << 9) -#define AR_PHY_SPUR_REG_MASK_RATE_SELECT_S 9 -#define AR_PHY_SPUR_REG_ENABLE_VIT_SPUR_RSSI 0x100 -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH 0x7F -#define AR_PHY_SPUR_REG_SPUR_RSSI_THRESH_S 0 - -#define AR_PHY_PILOT_MASK_01_30 0xa3b0 -#define AR_PHY_PILOT_MASK_31_60 0xa3b4 - -#define AR_PHY_CHANNEL_MASK_01_30 0x99d4 -#define AR_PHY_CHANNEL_MASK_31_60 0x99d8 - -#define AR_PHY_ANALOG_SWAP 0xa268 -#define AR_PHY_SWAP_ALT_CHAIN 0x00000040 - -#define AR_PHY_TPCRG5 0xA26C -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP 0x0000000F -#define AR_PHY_TPCRG5_PD_GAIN_OVERLAP_S 0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1 0x000003F0 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_1_S 4 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2 0x0000FC00 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_2_S 10 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3 0x003F0000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_3_S 16 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4 0x0FC00000 -#define AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_4_S 22 - -/* Carrier leak calibration control, do it after AGC calibration */ -#define AR_PHY_CL_CAL_CTL 0xA358 -#define AR_PHY_CL_CAL_ENABLE 0x00000002 -#define AR_PHY_PARALLEL_CAL_ENABLE 0x00000001 - -#define AR_PHY_POWER_TX_RATE5 0xA38C -#define AR_PHY_POWER_TX_RATE6 0xA390 - -#define AR_PHY_CAL_CHAINMASK 0xA39C - -#define AR_PHY_POWER_TX_SUB 0xA3C8 -#define AR_PHY_POWER_TX_RATE7 0xA3CC -#define AR_PHY_POWER_TX_RATE8 0xA3D0 -#define AR_PHY_POWER_TX_RATE9 0xA3D4 - -#define AR_PHY_XPA_CFG 0xA3D8 -#define AR_PHY_FORCE_XPA_CFG 0x000000001 -#define AR_PHY_FORCE_XPA_CFG_S 0 - -#define AR_PHY_CH1_CCA 0xa864 -#define AR_PHY_CH1_MINCCA_PWR 0x0FF80000 -#define AR_PHY_CH1_MINCCA_PWR_S 19 -#define AR9280_PHY_CH1_MINCCA_PWR 0x1FF00000 -#define AR9280_PHY_CH1_MINCCA_PWR_S 20 - -#define AR_PHY_CH2_CCA 0xb864 -#define AR_PHY_CH2_MINCCA_PWR 0x0FF80000 -#define AR_PHY_CH2_MINCCA_PWR_S 19 - -#define AR_PHY_CH1_EXT_CCA 0xa9bc -#define AR_PHY_CH1_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_CH1_EXT_MINCCA_PWR_S 23 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR 0x01FF0000 -#define AR9280_PHY_CH1_EXT_MINCCA_PWR_S 16 - -#define AR_PHY_CH2_EXT_CCA 0xb9bc -#define AR_PHY_CH2_EXT_MINCCA_PWR 0xFF800000 -#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23 - -#define REG_WRITE_RF_ARRAY(iniarray, regData, regWr) do { \ - int r; \ - for (r = 0; r < ((iniarray)->ia_rows); r++) { \ - REG_WRITE(ah, INI_RA((iniarray), r, 0), (regData)[r]); \ - DO_DELAY(regWr); \ - } \ - } while (0) - -#define ATH9K_IS_MIC_ENABLED(ah) \ - ((ah)->sta_id1_defaults & AR_STA_ID1_CRPT_MIC_ENABLE) - -#define ANTSWAP_AB 0x0001 -#define REDUCE_CHAIN_0 0x00000050 -#define REDUCE_CHAIN_1 0x00000051 - -#define RF_BANK_SETUP(_bank, _iniarray, _col) do { \ - int i; \ - for (i = 0; i < (_iniarray)->ia_rows; i++) \ - (_bank)[i] = INI_RA((_iniarray), i, _col);; \ - } while (0) - -#endif diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c deleted file mode 100644 index fd397aa439c9..000000000000 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ /dev/null @@ -1,1523 +0,0 @@ -/* - * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2004-2009 Atheros Communications, Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static const struct ath_rate_table ar5416_11na_ratetable = { - 42, - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, 12, - 0, 0, 0, 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 0, 1, 1, 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 0x0a, 0x00, 24, - 2, 2, 2, 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 0x0e, 0x00, 36, - 2, 3, 3, 3, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 0x09, 0x00, 48, - 4, 4, 4, 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 0x0d, 0x00, 72, - 4, 5, 5, 5, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 4, 6, 6, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 0x0c, 0x00, 108, - 4, 7, 7, 7, 7, 0 }, - { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0x80, 0x00, 0, - 0, 8, 24, 8, 24, 3216 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 0x81, 0x00, 1, - 2, 9, 25, 9, 25, 6434 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 0x82, 0x00, 2, - 2, 10, 26, 10, 26, 9650 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 0x83, 0x00, 3, - 4, 11, 27, 11, 27, 12868 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 0x84, 0x00, 4, - 4, 12, 28, 12, 28, 19304 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 0x85, 0x00, 5, - 4, 13, 29, 13, 29, 25740 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 0x86, 0x00, 6, - 4, 14, 30, 14, 30, 28956 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 0x87, 0x00, 7, - 4, 15, 31, 15, 32, 32180 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 0x88, 0x00, - 8, 3, 16, 33, 16, 33, 6430 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 0x89, 0x00, 9, - 2, 17, 34, 17, 34, 12860 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 0x8a, 0x00, 10, - 2, 18, 35, 18, 35, 19300 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 0x8b, 0x00, 11, - 4, 19, 36, 19, 36, 25736 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 0x8c, 0x00, 12, - 4, 20, 37, 20, 37, 38600 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 0x8d, 0x00, 13, - 4, 21, 38, 21, 38, 51472 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 0x8e, 0x00, 14, - 4, 22, 39, 22, 39, 57890 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 0x8f, 0x00, 15, - 4, 23, 40, 23, 41, 64320 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0x80, 0x00, 0, - 0, 8, 24, 24, 24, 6684 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 0x81, 0x00, 1, - 2, 9, 25, 25, 25, 13368 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 0x82, 0x00, 2, - 2, 10, 26, 26, 26, 20052 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 0x83, 0x00, 3, - 4, 11, 27, 27, 27, 26738 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 0x84, 0x00, 4, - 4, 12, 28, 28, 28, 40104 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 0x85, 0x00, 5, - 4, 13, 29, 29, 29, 53476 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 0x86, 0x00, 6, - 4, 14, 30, 30, 30, 60156 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 0x87, 0x00, 7, - 4, 15, 31, 32, 32, 66840 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 0x87, 0x00, 7, - 4, 15, 31, 32, 32, 74200 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 0x88, 0x00, 8, - 0, 16, 33, 33, 33, 13360 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 0x89, 0x00, 9, - 2, 17, 34, 34, 34, 26720 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 0x8a, 0x00, 10, - 2, 18, 35, 35, 35, 40080 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 0x8b, 0x00, 11, - 4, 19, 36, 36, 36, 53440 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 0x8c, 0x00, 12, - 4, 20, 37, 37, 37, 80160 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 0x8d, 0x00, 13, - 4, 21, 38, 38, 38, 106880 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 0x8e, 0x00, 14, - 4, 22, 39, 39, 39, 120240 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 0x8f, 0x00, 15, - 4, 23, 40, 41, 41, 133600 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 0x8f, 0x00, 15, - 4, 23, 40, 41, 41, 148400 }, - }, - 50, /* probe interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -}; - -/* 4ms frame limit not used for NG mode. The values filled - * for HT are the 64K max aggregate limit */ - -static const struct ath_rate_table ar5416_11ng_ratetable = { - 46, - { - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0x1b, 0x00, 2, - 0, 0, 0, 0, 0, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 0x1a, 0x04, 4, - 1, 1, 1, 1, 1, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 0x19, 0x04, 11, - 2, 2, 2, 2, 2, 0 }, - { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 0x18, 0x04, 22, - 3, 3, 3, 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, 12, - 4, 4, 4, 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 4, 5, 5, 5, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10100, 0x0a, 0x00, 24, - 6, 6, 6, 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 14100, 0x0e, 0x00, 36, - 6, 7, 7, 7, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17700, 0x09, 0x00, 48, - 8, 8, 8, 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23700, 0x0d, 0x00, 72, - 8, 9, 9, 9, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 8, 10, 10, 10, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 30900, 0x0c, 0x00, 108, - 8, 11, 11, 11, 11, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ - 6400, 0x80, 0x00, 0, - 4, 12, 28, 12, 28, 3216 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ - 12700, 0x81, 0x00, 1, - 6, 13, 29, 13, 29, 6434 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ - 18800, 0x82, 0x00, 2, - 6, 14, 30, 14, 30, 9650 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ - 25000, 0x83, 0x00, 3, - 8, 15, 31, 15, 31, 12868 }, - { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ - 36700, 0x84, 0x00, 4, - 8, 16, 32, 16, 32, 19304 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ - 48100, 0x85, 0x00, 5, - 8, 17, 33, 17, 33, 25740 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ - 53500, 0x86, 0x00, 6, - 8, 18, 34, 18, 34, 28956 }, - { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ - 59000, 0x87, 0x00, 7, - 8, 19, 35, 19, 36, 32180 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ - 12700, 0x88, 0x00, 8, - 4, 20, 37, 20, 37, 6430 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ - 24800, 0x89, 0x00, 9, - 6, 21, 38, 21, 38, 12860 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ - 36600, 0x8a, 0x00, 10, - 6, 22, 39, 22, 39, 19300 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ - 48100, 0x8b, 0x00, 11, - 8, 23, 40, 23, 40, 25736 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ - 69500, 0x8c, 0x00, 12, - 8, 24, 41, 24, 41, 38600 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ - 89500, 0x8d, 0x00, 13, - 8, 25, 42, 25, 42, 51472 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ - 98900, 0x8e, 0x00, 14, - 8, 26, 43, 26, 44, 57890 }, - { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ - 108300, 0x8f, 0x00, 15, - 8, 27, 44, 27, 45, 64320 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ - 13200, 0x80, 0x00, 0, - 8, 12, 28, 28, 28, 6684 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ - 25900, 0x81, 0x00, 1, - 8, 13, 29, 29, 29, 13368 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ - 38600, 0x82, 0x00, 2, - 8, 14, 30, 30, 30, 20052 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ - 49800, 0x83, 0x00, 3, - 8, 15, 31, 31, 31, 26738 }, - { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ - 72200, 0x84, 0x00, 4, - 8, 16, 32, 32, 32, 40104 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ - 92900, 0x85, 0x00, 5, - 8, 17, 33, 33, 33, 53476 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ - 102700, 0x86, 0x00, 6, - 8, 18, 34, 34, 34, 60156 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ - 112000, 0x87, 0x00, 7, - 8, 19, 35, 36, 36, 66840 }, - { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ - 122000, 0x87, 0x00, 7, - 8, 19, 35, 36, 36, 74200 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ - 25800, 0x88, 0x00, 8, - 8, 20, 37, 37, 37, 13360 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ - 49800, 0x89, 0x00, 9, - 8, 21, 38, 38, 38, 26720 }, - { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ - 71900, 0x8a, 0x00, 10, - 8, 22, 39, 39, 39, 40080 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ - 92500, 0x8b, 0x00, 11, - 8, 23, 40, 40, 40, 53440 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ - 130300, 0x8c, 0x00, 12, - 8, 24, 41, 41, 41, 80160 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ - 162800, 0x8d, 0x00, 13, - 8, 25, 42, 42, 42, 106880 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ - 178200, 0x8e, 0x00, 14, - 8, 26, 43, 43, 43, 120240 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ - 192100, 0x8f, 0x00, 15, - 8, 27, 44, 45, 45, 133600 }, - { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ - 207000, 0x8f, 0x00, 15, - 8, 27, 44, 45, 45, 148400 }, - }, - 50, /* probe interval */ - WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ -}; - -static const struct ath_rate_table ar5416_11a_ratetable = { - 8, - { - { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, (0x80|12), - 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 0, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 0x0a, 0x00, (0x80|24), - 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 0x0e, 0x00, 36, - 2, 3, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 0x09, 0x00, (0x80|48), - 4, 4, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 0x0d, 0x00, 72, - 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 4, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 0x0c, 0x00, 108, - 4, 7, 0 }, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ -}; - -static const struct ath_rate_table ar5416_11g_ratetable = { - 12, - { - { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ - 900, 0x1b, 0x00, 2, - 0, 0, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ - 1900, 0x1a, 0x04, 4, - 1, 1, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ - 4900, 0x19, 0x04, 11, - 2, 2, 0 }, - { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ - 8100, 0x18, 0x04, 22, - 3, 3, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ - 5400, 0x0b, 0x00, 12, - 4, 4, 0 }, - { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ - 7800, 0x0f, 0x00, 18, - 4, 5, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ - 10000, 0x0a, 0x00, 24, - 6, 6, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ - 13900, 0x0e, 0x00, 36, - 6, 7, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ - 17300, 0x09, 0x00, 48, - 8, 8, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ - 23000, 0x0d, 0x00, 72, - 8, 9, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ - 27400, 0x08, 0x00, 96, - 8, 10, 0 }, - { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ - 29300, 0x0c, 0x00, 108, - 8, 11, 0 }, - }, - 50, /* probe interval */ - 0, /* Phy rates allowed initially */ -}; - -static inline int8_t median(int8_t a, int8_t b, int8_t c) -{ - if (a >= b) { - if (b >= c) - return b; - else if (a > c) - return c; - else - return a; - } else { - if (a >= c) - return a; - else if (b >= c) - return c; - else - return b; - } -} - -static void ath_rc_sort_validrates(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv) -{ - u8 i, j, idx, idx_next; - - for (i = ath_rc_priv->max_valid_rate - 1; i > 0; i--) { - for (j = 0; j <= i-1; j++) { - idx = ath_rc_priv->valid_rate_index[j]; - idx_next = ath_rc_priv->valid_rate_index[j+1]; - - if (rate_table->info[idx].ratekbps > - rate_table->info[idx_next].ratekbps) { - ath_rc_priv->valid_rate_index[j] = idx_next; - ath_rc_priv->valid_rate_index[j+1] = idx; - } - } - } -} - -static void ath_rc_init_valid_txmask(struct ath_rate_priv *ath_rc_priv) -{ - u8 i; - - for (i = 0; i < ath_rc_priv->rate_table_size; i++) - ath_rc_priv->valid_rate_index[i] = 0; -} - -static inline void ath_rc_set_valid_txmask(struct ath_rate_priv *ath_rc_priv, - u8 index, int valid_tx_rate) -{ - ASSERT(index <= ath_rc_priv->rate_table_size); - ath_rc_priv->valid_rate_index[index] = valid_tx_rate ? 1 : 0; -} - -static inline -int ath_rc_get_nextvalid_txrate(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, - u8 *next_idx) -{ - u8 i; - - for (i = 0; i < ath_rc_priv->max_valid_rate - 1; i++) { - if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { - *next_idx = ath_rc_priv->valid_rate_index[i+1]; - return 1; - } - } - - /* No more valid rates */ - *next_idx = 0; - - return 0; -} - -/* Return true only for single stream */ - -static int ath_rc_valid_phyrate(u32 phy, u32 capflag, int ignore_cw) -{ - if (WLAN_RC_PHY_HT(phy) && !(capflag & WLAN_RC_HT_FLAG)) - return 0; - if (WLAN_RC_PHY_DS(phy) && !(capflag & WLAN_RC_DS_FLAG)) - return 0; - if (WLAN_RC_PHY_SGI(phy) && !(capflag & WLAN_RC_SGI_FLAG)) - return 0; - if (!ignore_cw && WLAN_RC_PHY_HT(phy)) - if (WLAN_RC_PHY_40(phy) && !(capflag & WLAN_RC_40_FLAG)) - return 0; - return 1; -} - -static inline int -ath_rc_get_lower_rix(const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - u8 cur_valid_txrate, u8 *next_idx) -{ - int8_t i; - - for (i = 1; i < ath_rc_priv->max_valid_rate ; i++) { - if (ath_rc_priv->valid_rate_index[i] == cur_valid_txrate) { - *next_idx = ath_rc_priv->valid_rate_index[i-1]; - return 1; - } - } - - return 0; -} - -static u8 ath_rc_init_validrates(struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - u32 capflag) -{ - u8 i, hi = 0; - u32 valid; - - for (i = 0; i < rate_table->rate_cnt; i++) { - valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[i].valid_single_stream : - rate_table->info[i].valid); - if (valid == 1) { - u32 phy = rate_table->info[i].phy; - u8 valid_rate_count = 0; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = ath_rc_priv->valid_phy_ratecnt[phy]; - - ath_rc_priv->valid_phy_rateidx[phy][valid_rate_count] = i; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, i, 1); - hi = A_MAX(hi, i); - } - } - - return hi; -} - -static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - struct ath_rateset *rateset, - u32 capflag) -{ - u8 i, j, hi = 0; - - /* Use intersection of working rates and valid rates */ - for (i = 0; i < rateset->rs_nrates; i++) { - for (j = 0; j < rate_table->rate_cnt; j++) { - u32 phy = rate_table->info[j].phy; - u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; - - /* We allow a rate only if its valid and the - * capflag matches one of the validity - * (VALID/VALID_20/VALID_40) flags */ - - if (((rate & 0x7F) == (dot11rate & 0x7F)) && - ((valid & WLAN_RC_CAP_MODE(capflag)) == - WLAN_RC_CAP_MODE(capflag)) && - !WLAN_RC_PHY_HT(phy)) { - u8 valid_rate_count = 0; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - valid_rate_count = - ath_rc_priv->valid_phy_ratecnt[phy]; - - ath_rc_priv->valid_phy_rateidx[phy] - [valid_rate_count] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, j, 1); - hi = A_MAX(hi, j); - } - } - } - - return hi; -} - -static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - u8 *mcs_set, u32 capflag) -{ - struct ath_rateset *rateset = (struct ath_rateset *)mcs_set; - - u8 i, j, hi = 0; - - /* Use intersection of working rates and valid rates */ - for (i = 0; i < rateset->rs_nrates; i++) { - for (j = 0; j < rate_table->rate_cnt; j++) { - u32 phy = rate_table->info[j].phy; - u32 valid = (!(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG) ? - rate_table->info[j].valid_single_stream : - rate_table->info[j].valid); - u8 rate = rateset->rs_rates[i]; - u8 dot11rate = rate_table->info[j].dot11rate; - - if (((rate & 0x7F) != (dot11rate & 0x7F)) || - !WLAN_RC_PHY_HT(phy) || - !WLAN_RC_PHY_HT_VALID(valid, capflag)) - continue; - - if (!ath_rc_valid_phyrate(phy, capflag, 0)) - continue; - - ath_rc_priv->valid_phy_rateidx[phy] - [ath_rc_priv->valid_phy_ratecnt[phy]] = j; - ath_rc_priv->valid_phy_ratecnt[phy] += 1; - ath_rc_set_valid_txmask(ath_rc_priv, j, 1); - hi = A_MAX(hi, j); - } - } - - return hi; -} - -/* Finds the highest rate index we can use */ -static u8 ath_rc_get_highest_rix(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - const struct ath_rate_table *rate_table, - int *is_probing) -{ - u32 best_thruput, this_thruput, now_msec; - u8 rate, next_rate, best_rate, maxindex, minindex; - int8_t index = 0; - - now_msec = jiffies_to_msecs(jiffies); - *is_probing = 0; - best_thruput = 0; - maxindex = ath_rc_priv->max_valid_rate-1; - minindex = 0; - best_rate = minindex; - - /* - * Try the higher rate first. It will reduce memory moving time - * if we have very good channel characteristics. - */ - for (index = maxindex; index >= minindex ; index--) { - u8 per_thres; - - rate = ath_rc_priv->valid_rate_index[index]; - if (rate > ath_rc_priv->rate_max_phy) - continue; - - /* - * For TCP the average collision rate is around 11%, - * so we ignore PERs less than this. This is to - * prevent the rate we are currently using (whose - * PER might be in the 10-15 range because of TCP - * collisions) looking worse than the next lower - * rate whose PER has decayed close to 0. If we - * used to next lower rate, its PER would grow to - * 10-15 and we would be worse off then staying - * at the current rate. - */ - per_thres = ath_rc_priv->per[rate]; - if (per_thres < 12) - per_thres = 12; - - this_thruput = rate_table->info[rate].user_ratekbps * - (100 - per_thres); - - if (best_thruput <= this_thruput) { - best_thruput = this_thruput; - best_rate = rate; - } - } - - rate = best_rate; - - /* - * Must check the actual rate (ratekbps) to account for - * non-monoticity of 11g's rate table - */ - - if (rate >= ath_rc_priv->rate_max_phy) { - rate = ath_rc_priv->rate_max_phy; - - /* Probe the next allowed phy state */ - if (ath_rc_get_nextvalid_txrate(rate_table, - ath_rc_priv, rate, &next_rate) && - (now_msec - ath_rc_priv->probe_time > - rate_table->probe_interval) && - (ath_rc_priv->hw_maxretry_pktcnt >= 1)) { - rate = next_rate; - ath_rc_priv->probe_rate = rate; - ath_rc_priv->probe_time = now_msec; - ath_rc_priv->hw_maxretry_pktcnt = 0; - *is_probing = 1; - } - } - - if (rate > (ath_rc_priv->rate_table_size - 1)) - rate = ath_rc_priv->rate_table_size - 1; - - if (rate_table->info[rate].valid && - (ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) - return rate; - - if (rate_table->info[rate].valid_single_stream && - !(ath_rc_priv->ht_cap & WLAN_RC_DS_FLAG)) - return rate; - - /* This should not happen */ - WARN_ON(1); - - rate = ath_rc_priv->valid_rate_index[0]; - - return rate; -} - -static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table, - struct ieee80211_tx_rate *rate, - struct ieee80211_tx_rate_control *txrc, - u8 tries, u8 rix, int rtsctsenable) -{ - rate->count = tries; - rate->idx = rix; - - if (txrc->short_preamble) - rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; - if (txrc->rts || rtsctsenable) - rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; - if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_SHORT_GI; - if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) - rate->flags |= IEEE80211_TX_RC_MCS; -} - -static void ath_rc_rate_set_rtscts(struct ath_softc *sc, - const struct ath_rate_table *rate_table, - struct ieee80211_tx_info *tx_info) -{ - struct ieee80211_tx_rate *rates = tx_info->control.rates; - int i = 0, rix = 0, cix, enable_g_protection = 0; - - /* get the cix for the lowest valid rix */ - for (i = 3; i >= 0; i--) { - if (rates[i].count && (rates[i].idx >= 0)) { - rix = rates[i].idx; - break; - } - } - cix = rate_table->info[rix].ctrl_rate; - - /* All protection frames are transmited at 2Mb/s for 802.11g, - * otherwise we transmit them at 1Mb/s */ - if (sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ && - !conf_is_ht(&sc->hw->conf)) - enable_g_protection = 1; - - /* - * If 802.11g protection is enabled, determine whether to use RTS/CTS or - * just CTS. Note that this is only done for OFDM/HT unicast frames. - */ - if ((sc->sc_flags & SC_OP_PROTECT_ENABLE) && - (rate_table->info[rix].phy == WLAN_RC_PHY_OFDM || - WLAN_RC_PHY_HT(rate_table->info[rix].phy))) { - rates[0].flags |= IEEE80211_TX_RC_USE_CTS_PROTECT; - cix = rate_table->info[enable_g_protection].ctrl_rate; - } - - tx_info->control.rts_cts_rate_idx = cix; -} - -static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, - struct ieee80211_tx_rate_control *txrc) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - const struct ath_rate_table *rate_table; - struct sk_buff *skb = txrc->skb; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_rate *rates = tx_info->control.rates; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - __le16 fc = hdr->frame_control; - u8 try_per_rate, i = 0, rix; - int is_probe = 0; - - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - - /* - * For Multi Rate Retry we use a different number of - * retry attempt counts. This ends up looking like this: - * - * MRR[0] = 2 - * MRR[1] = 2 - * MRR[2] = 2 - * MRR[3] = 4 - * - */ - try_per_rate = sc->hw->max_rate_tries; - - rate_table = sc->cur_rate_table; - rix = ath_rc_get_highest_rix(sc, ath_rc_priv, rate_table, &is_probe); - - if (is_probe) { - /* set one try for probe rates. For the - * probes don't enable rts */ - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - 1, rix, 0); - - /* Get the next tried/allowed rate. No RTS for the next series - * after the probe rate - */ - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, rix, 0); - - tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; - } else { - /* Set the choosen rate. No RTS for first series entry. */ - ath_rc_rate_set_series(rate_table, &rates[i++], txrc, - try_per_rate, rix, 0); - } - - /* Fill in the other rates for multirate retry */ - for ( ; i < 4; i++) { - /* Use twice the number of tries for the last MRR segment. */ - if (i + 1 == 4) - try_per_rate = 4; - - ath_rc_get_lower_rix(rate_table, ath_rc_priv, rix, &rix); - /* All other rates in the series have RTS enabled */ - ath_rc_rate_set_series(rate_table, &rates[i], txrc, - try_per_rate, rix, 1); - } - - /* - * NB:Change rate series to enable aggregation when operating - * at lower MCS rates. When first rate in series is MCS2 - * in HT40 @ 2.4GHz, series should look like: - * - * {MCS2, MCS1, MCS0, MCS0}. - * - * When first rate in series is MCS3 in HT20 @ 2.4GHz, series should - * look like: - * - * {MCS3, MCS2, MCS1, MCS1} - * - * So, set fourth rate in series to be same as third one for - * above conditions. - */ - if ((sc->hw->conf.channel->band == IEEE80211_BAND_2GHZ) && - (conf_is_ht(&sc->hw->conf))) { - u8 dot11rate = rate_table->info[rix].dot11rate; - u8 phy = rate_table->info[rix].phy; - if (i == 4 && - ((dot11rate == 2 && phy == WLAN_RC_PHY_HT_40_SS) || - (dot11rate == 3 && phy == WLAN_RC_PHY_HT_20_SS))) { - rates[3].idx = rates[2].idx; - rates[3].flags = rates[2].flags; - } - } - - /* - * Force hardware to use computed duration for next - * fragment by disabling multi-rate retry, which - * updates duration based on the multi-rate duration table. - * - * FIXME: Fix duration - */ - if (ieee80211_has_morefrags(fc) || - (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)) { - rates[1].count = rates[2].count = rates[3].count = 0; - rates[1].idx = rates[2].idx = rates[3].idx = 0; - rates[0].count = ATH_TXMAXTRY; - } - - /* Setup RTS/CTS */ - ath_rc_rate_set_rtscts(sc, rate_table, tx_info); -} - -static bool ath_rc_update_per(struct ath_softc *sc, - const struct ath_rate_table *rate_table, - struct ath_rate_priv *ath_rc_priv, - struct ath_tx_info_priv *tx_info_priv, - int tx_rate, int xretries, int retries, - u32 now_msec) -{ - bool state_change = false; - int count; - u8 last_per; - static u32 nretry_to_per_lookup[10] = { - 100 * 0 / 1, - 100 * 1 / 4, - 100 * 1 / 2, - 100 * 3 / 4, - 100 * 4 / 5, - 100 * 5 / 6, - 100 * 6 / 7, - 100 * 7 / 8, - 100 * 8 / 9, - 100 * 9 / 10 - }; - - last_per = ath_rc_priv->per[tx_rate]; - - if (xretries) { - if (xretries == 1) { - ath_rc_priv->per[tx_rate] += 30; - if (ath_rc_priv->per[tx_rate] > 100) - ath_rc_priv->per[tx_rate] = 100; - } else { - /* xretries == 2 */ - count = ARRAY_SIZE(nretry_to_per_lookup); - if (retries >= count) - retries = count - 1; - - /* new_PER = 7/8*old_PER + 1/8*(currentPER) */ - ath_rc_priv->per[tx_rate] = - (u8)(last_per - (last_per >> 3) + (100 >> 3)); - } - - /* xretries == 1 or 2 */ - - if (ath_rc_priv->probe_rate == tx_rate) - ath_rc_priv->probe_rate = 0; - - } else { /* xretries == 0 */ - count = ARRAY_SIZE(nretry_to_per_lookup); - if (retries >= count) - retries = count - 1; - - if (tx_info_priv->n_bad_frames) { - /* new_PER = 7/8*old_PER + 1/8*(currentPER) - * Assuming that n_frames is not 0. The current PER - * from the retries is 100 * retries / (retries+1), - * since the first retries attempts failed, and the - * next one worked. For the one that worked, - * n_bad_frames subframes out of n_frames wored, - * so the PER for that part is - * 100 * n_bad_frames / n_frames, and it contributes - * 100 * n_bad_frames / (n_frames * (retries+1)) to - * the above PER. The expression below is a - * simplified version of the sum of these two terms. - */ - if (tx_info_priv->n_frames > 0) { - int n_frames, n_bad_frames; - u8 cur_per, new_per; - - n_bad_frames = retries * tx_info_priv->n_frames + - tx_info_priv->n_bad_frames; - n_frames = tx_info_priv->n_frames * (retries + 1); - cur_per = (100 * n_bad_frames / n_frames) >> 3; - new_per = (u8)(last_per - (last_per >> 3) + cur_per); - ath_rc_priv->per[tx_rate] = new_per; - } - } else { - ath_rc_priv->per[tx_rate] = - (u8)(last_per - (last_per >> 3) + - (nretry_to_per_lookup[retries] >> 3)); - } - - - /* - * If we got at most one retry then increase the max rate if - * this was a probe. Otherwise, ignore the probe. - */ - if (ath_rc_priv->probe_rate && ath_rc_priv->probe_rate == tx_rate) { - if (retries > 0 || 2 * tx_info_priv->n_bad_frames > - tx_info_priv->n_frames) { - /* - * Since we probed with just a single attempt, - * any retries means the probe failed. Also, - * if the attempt worked, but more than half - * the subframes were bad then also consider - * the probe a failure. - */ - ath_rc_priv->probe_rate = 0; - } else { - u8 probe_rate = 0; - - ath_rc_priv->rate_max_phy = - ath_rc_priv->probe_rate; - probe_rate = ath_rc_priv->probe_rate; - - if (ath_rc_priv->per[probe_rate] > 30) - ath_rc_priv->per[probe_rate] = 20; - - ath_rc_priv->probe_rate = 0; - - /* - * Since this probe succeeded, we allow the next - * probe twice as soon. This allows the maxRate - * to move up faster if the probes are - * succesful. - */ - ath_rc_priv->probe_time = - now_msec - rate_table->probe_interval / 2; - } - } - - if (retries > 0) { - /* - * Don't update anything. We don't know if - * this was because of collisions or poor signal. - */ - ath_rc_priv->hw_maxretry_pktcnt = 0; - } else { - /* - * It worked with no retries. First ignore bogus (small) - * rssi_ack values. - */ - if (tx_rate == ath_rc_priv->rate_max_phy && - ath_rc_priv->hw_maxretry_pktcnt < 255) { - ath_rc_priv->hw_maxretry_pktcnt++; - } - - } - } - - return state_change; -} - -/* Update PER, RSSI and whatever else that the code thinks it is doing. - If you can make sense of all this, you really need to go out more. */ - -static void ath_rc_update_ht(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ath_tx_info_priv *tx_info_priv, - int tx_rate, int xretries, int retries) -{ - u32 now_msec = jiffies_to_msecs(jiffies); - int rate; - u8 last_per; - bool state_change = false; - const struct ath_rate_table *rate_table = sc->cur_rate_table; - int size = ath_rc_priv->rate_table_size; - - if ((tx_rate < 0) || (tx_rate > rate_table->rate_cnt)) - return; - - last_per = ath_rc_priv->per[tx_rate]; - - /* Update PER first */ - state_change = ath_rc_update_per(sc, rate_table, ath_rc_priv, - tx_info_priv, tx_rate, xretries, - retries, now_msec); - - /* - * If this rate looks bad (high PER) then stop using it for - * a while (except if we are probing). - */ - if (ath_rc_priv->per[tx_rate] >= 55 && tx_rate > 0 && - rate_table->info[tx_rate].ratekbps <= - rate_table->info[ath_rc_priv->rate_max_phy].ratekbps) { - ath_rc_get_lower_rix(rate_table, ath_rc_priv, - (u8)tx_rate, &ath_rc_priv->rate_max_phy); - - /* Don't probe for a little while. */ - ath_rc_priv->probe_time = now_msec; - } - - /* Make sure the rates below this have lower PER */ - /* Monotonicity is kept only for rates below the current rate. */ - if (ath_rc_priv->per[tx_rate] < last_per) { - for (rate = tx_rate - 1; rate >= 0; rate--) { - - if (ath_rc_priv->per[rate] > - ath_rc_priv->per[rate+1]) { - ath_rc_priv->per[rate] = - ath_rc_priv->per[rate+1]; - } - } - } - - /* Maintain monotonicity for rates above the current rate */ - for (rate = tx_rate; rate < size - 1; rate++) { - if (ath_rc_priv->per[rate+1] < - ath_rc_priv->per[rate]) - ath_rc_priv->per[rate+1] = - ath_rc_priv->per[rate]; - } - - /* Every so often, we reduce the thresholds - * and PER (different for CCK and OFDM). */ - if (now_msec - ath_rc_priv->per_down_time >= - rate_table->probe_interval) { - for (rate = 0; rate < size; rate++) { - ath_rc_priv->per[rate] = - 7 * ath_rc_priv->per[rate] / 8; - } - - ath_rc_priv->per_down_time = now_msec; - } - - ath_debug_stat_retries(sc, tx_rate, xretries, retries, - ath_rc_priv->per[tx_rate]); - -} - -static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table, - struct ieee80211_tx_rate *rate) -{ - int rix; - - if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - (rate->flags & IEEE80211_TX_RC_SHORT_GI)) - rix = rate_table->info[rate->idx].ht_index; - else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) - rix = rate_table->info[rate->idx].sgi_index; - else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - rix = rate_table->info[rate->idx].cw40index; - else - rix = rate_table->info[rate->idx].base_index; - - return rix; -} - -static void ath_rc_tx_status(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_tx_info *tx_info, - int final_ts_idx, int xretries, int long_retry) -{ - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - const struct ath_rate_table *rate_table; - struct ieee80211_tx_rate *rates = tx_info->status.rates; - u8 flags; - u32 i = 0, rix; - - rate_table = sc->cur_rate_table; - - /* - * If the first rate is not the final index, there - * are intermediate rate failures to be processed. - */ - if (final_ts_idx != 0) { - /* Process intermediate rates that failed.*/ - for (i = 0; i < final_ts_idx ; i++) { - if (rates[i].count != 0 && (rates[i].idx >= 0)) { - flags = rates[i].flags; - - /* If HT40 and we have switched mode from - * 40 to 20 => don't update */ - - if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) - return; - - rix = ath_rc_get_rateindex(rate_table, &rates[i]); - ath_rc_update_ht(sc, ath_rc_priv, - tx_info_priv, rix, - xretries ? 1 : 2, - rates[i].count); - } - } - } else { - /* - * Handle the special case of MIMO PS burst, where the second - * aggregate is sent out with only one rate and one try. - * Treating it as an excessive retry penalizes the rate - * inordinately. - */ - if (rates[0].count == 1 && xretries == 1) - xretries = 2; - } - - flags = rates[i].flags; - - /* If HT40 and we have switched mode from 40 to 20 => don't update */ - if ((flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && - !(ath_rc_priv->ht_cap & WLAN_RC_40_FLAG)) - return; - - rix = ath_rc_get_rateindex(rate_table, &rates[i]); - ath_rc_update_ht(sc, ath_rc_priv, tx_info_priv, rix, - xretries, long_retry); -} - -static const -struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc, - enum ieee80211_band band, - bool is_ht, - bool is_cw_40) -{ - int mode = 0; - - switch(band) { - case IEEE80211_BAND_2GHZ: - mode = ATH9K_MODE_11G; - if (is_ht) - mode = ATH9K_MODE_11NG_HT20; - if (is_cw_40) - mode = ATH9K_MODE_11NG_HT40PLUS; - break; - case IEEE80211_BAND_5GHZ: - mode = ATH9K_MODE_11A; - if (is_ht) - mode = ATH9K_MODE_11NA_HT20; - if (is_cw_40) - mode = ATH9K_MODE_11NA_HT40PLUS; - break; - default: - DPRINTF(sc, ATH_DBG_CONFIG, "Invalid band\n"); - return NULL; - } - - BUG_ON(mode >= ATH9K_MODE_MAX); - - DPRINTF(sc, ATH_DBG_CONFIG, "Choosing rate table for mode: %d\n", mode); - return sc->hw_rate_table[mode]; -} - -static void ath_rc_init(struct ath_softc *sc, - struct ath_rate_priv *ath_rc_priv, - struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, - const struct ath_rate_table *rate_table) -{ - struct ath_rateset *rateset = &ath_rc_priv->neg_rates; - u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; - u8 i, j, k, hi = 0, hthi = 0; - - if (!rate_table) { - DPRINTF(sc, ATH_DBG_FATAL, "Rate table not initialized\n"); - return; - } - - /* Initial rate table size. Will change depending - * on the working rate set */ - ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; - - /* Initialize thresholds according to the global rate table */ - for (i = 0 ; i < ath_rc_priv->rate_table_size; i++) { - ath_rc_priv->per[i] = 0; - } - - /* Determine the valid rates */ - ath_rc_init_valid_txmask(ath_rc_priv); - - for (i = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < MAX_TX_RATE_PHY; j++) - ath_rc_priv->valid_phy_rateidx[i][j] = 0; - ath_rc_priv->valid_phy_ratecnt[i] = 0; - } - - if (!rateset->rs_nrates) { - /* No working rate, just initialize valid rates */ - hi = ath_rc_init_validrates(ath_rc_priv, rate_table, - ath_rc_priv->ht_cap); - } else { - /* Use intersection of working rates and valid rates */ - hi = ath_rc_setvalid_rates(ath_rc_priv, rate_table, - rateset, ath_rc_priv->ht_cap); - if (ath_rc_priv->ht_cap & WLAN_RC_HT_FLAG) { - hthi = ath_rc_setvalid_htrates(ath_rc_priv, - rate_table, - ht_mcs, - ath_rc_priv->ht_cap); - } - hi = A_MAX(hi, hthi); - } - - ath_rc_priv->rate_table_size = hi + 1; - ath_rc_priv->rate_max_phy = 0; - ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); - - for (i = 0, k = 0; i < WLAN_RC_PHY_MAX; i++) { - for (j = 0; j < ath_rc_priv->valid_phy_ratecnt[i]; j++) { - ath_rc_priv->valid_rate_index[k++] = - ath_rc_priv->valid_phy_rateidx[i][j]; - } - - if (!ath_rc_valid_phyrate(i, rate_table->initial_ratemax, 1) - || !ath_rc_priv->valid_phy_ratecnt[i]) - continue; - - ath_rc_priv->rate_max_phy = ath_rc_priv->valid_phy_rateidx[i][j-1]; - } - ASSERT(ath_rc_priv->rate_table_size <= RATE_TABLE_SIZE); - ASSERT(k <= RATE_TABLE_SIZE); - - ath_rc_priv->max_valid_rate = k; - ath_rc_sort_validrates(rate_table, ath_rc_priv); - ath_rc_priv->rate_max_phy = ath_rc_priv->valid_rate_index[k-4]; - sc->cur_rate_table = rate_table; - - DPRINTF(sc, ATH_DBG_CONFIG, "RC Initialized with capabilities: 0x%x\n", - ath_rc_priv->ht_cap); -} - -static u8 ath_rc_build_ht_caps(struct ath_softc *sc, struct ieee80211_sta *sta, - bool is_cw40, bool is_sgi40) -{ - u8 caps = 0; - - if (sta->ht_cap.ht_supported) { - caps = WLAN_RC_HT_FLAG; - if (sc->sc_ah->caps.tx_chainmask != 1 && - ath9k_hw_getcapability(sc->sc_ah, ATH9K_CAP_DS, 0, NULL)) { - if (sta->ht_cap.mcs.rx_mask[1]) - caps |= WLAN_RC_DS_FLAG; - } - if (is_cw40) - caps |= WLAN_RC_40_FLAG; - if (is_sgi40) - caps |= WLAN_RC_SGI_FLAG; - } - - return caps; -} - -/***********************************/ -/* mac80211 Rate Control callbacks */ -/***********************************/ - -static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - struct ath_tx_info_priv *tx_info_priv = NULL; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; - int final_ts_idx, tx_status = 0, is_underrun = 0; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - final_ts_idx = tx_info_priv->tx.ts_rateindex; - - if (!priv_sta || !ieee80211_is_data(fc) || - !tx_info_priv->update_rc) - goto exit; - - if (tx_info_priv->tx.ts_status & ATH9K_TXERR_FILT) - goto exit; - - /* - * If underrun error is seen assume it as an excessive retry only - * if prefetch trigger level have reached the max (0x3f for 5416) - * Adjust the long retry as if the frame was tried hw->max_rate_tries - * times. This affects how ratectrl updates PER for the failed rate. - */ - if (tx_info_priv->tx.ts_flags & - (ATH9K_TX_DATA_UNDERRUN | ATH9K_TX_DELIM_UNDERRUN) && - ((sc->sc_ah->tx_trig_level) >= ath_rc_priv->tx_triglevel_max)) { - tx_status = 1; - is_underrun = 1; - } - - if ((tx_info_priv->tx.ts_status & ATH9K_TXERR_XRETRY) || - (tx_info_priv->tx.ts_status & ATH9K_TXERR_FIFO)) - tx_status = 1; - - ath_rc_tx_status(sc, ath_rc_priv, tx_info, final_ts_idx, tx_status, - (is_underrun) ? sc->hw->max_rate_tries : - tx_info_priv->tx.ts_longretry); - - /* Check if aggregation has to be enabled for this tid */ - if (conf_is_ht(&sc->hw->conf) && - !(skb->protocol == cpu_to_be16(ETH_P_PAE))) { - if (ieee80211_is_data_qos(fc)) { - u8 *qc, tid; - struct ath_node *an; - - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - an = (struct ath_node *)sta->drv_priv; - - if(ath_tx_aggr_check(sc, an, tid)) - ieee80211_start_tx_ba_session(sc->hw, hdr->addr1, tid); - } - } - - ath_debug_stat_rc(sc, skb); -exit: - kfree(tx_info_priv); -} - -static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - const struct ath_rate_table *rate_table = NULL; - bool is_cw40, is_sgi40; - int i, j = 0; - - for (i = 0; i < sband->n_bitrates; i++) { - if (sta->supp_rates[sband->band] & BIT(i)) { - ath_rc_priv->neg_rates.rs_rates[j] - = (sband->bitrates[i].bitrate * 2) / 10; - j++; - } - } - ath_rc_priv->neg_rates.rs_nrates = j; - - if (sta->ht_cap.ht_supported) { - for (i = 0, j = 0; i < 77; i++) { - if (sta->ht_cap.mcs.rx_mask[i/8] & (1<<(i%8))) - ath_rc_priv->neg_ht_rates.rs_rates[j++] = i; - if (j == ATH_RATE_MAX) - break; - } - ath_rc_priv->neg_ht_rates.rs_nrates = j; - } - - is_cw40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40; - is_sgi40 = sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40; - - /* Choose rate table first */ - - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || - (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, - is_cw40); - } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { - /* cur_rate_table would be set on init through config() */ - rate_table = sc->cur_rate_table; - } - - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); -} - -static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - u32 changed) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *ath_rc_priv = priv_sta; - const struct ath_rate_table *rate_table = NULL; - bool oper_cw40 = false, oper_sgi40; - bool local_cw40 = (ath_rc_priv->ht_cap & WLAN_RC_40_FLAG) ? - true : false; - bool local_sgi40 = (ath_rc_priv->ht_cap & WLAN_RC_SGI_FLAG) ? - true : false; - - /* FIXME: Handle AP mode later when we support CWM */ - - if (changed & IEEE80211_RC_HT_CHANGED) { - if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) - return; - - if (sc->hw->conf.channel_type == NL80211_CHAN_HT40MINUS || - sc->hw->conf.channel_type == NL80211_CHAN_HT40PLUS) - oper_cw40 = true; - - oper_sgi40 = (sta->ht_cap.cap & IEEE80211_HT_CAP_SGI_40) ? - true : false; - - if ((local_cw40 != oper_cw40) || (local_sgi40 != oper_sgi40)) { - rate_table = ath_choose_rate_table(sc, sband->band, - sta->ht_cap.ht_supported, - oper_cw40); - ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, - oper_cw40, oper_sgi40); - ath_rc_init(sc, priv_sta, sband, sta, rate_table); - - DPRINTF(sc, ATH_DBG_CONFIG, - "Operating HT Bandwidth changed to: %d\n", - sc->hw->conf.channel_type); - } - } -} - -static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -{ - struct ath_wiphy *aphy = hw->priv; - return aphy->sc; -} - -static void ath_rate_free(void *priv) -{ - return; -} - -static void *ath_rate_alloc_sta(void *priv, struct ieee80211_sta *sta, gfp_t gfp) -{ - struct ath_softc *sc = priv; - struct ath_rate_priv *rate_priv; - - rate_priv = kzalloc(sizeof(struct ath_rate_priv), gfp); - if (!rate_priv) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to allocate private rc structure\n"); - return NULL; - } - - rate_priv->tx_triglevel_max = sc->sc_ah->caps.tx_triglevel_max; - - return rate_priv; -} - -static void ath_rate_free_sta(void *priv, struct ieee80211_sta *sta, - void *priv_sta) -{ - struct ath_rate_priv *rate_priv = priv_sta; - kfree(rate_priv); -} - -static struct rate_control_ops ath_rate_ops = { - .module = NULL, - .name = "ath9k_rate_control", - .tx_status = ath_tx_status, - .get_rate = ath_get_rate, - .rate_init = ath_rate_init, - .rate_update = ath_rate_update, - .alloc = ath_rate_alloc, - .free = ath_rate_free, - .alloc_sta = ath_rate_alloc_sta, - .free_sta = ath_rate_free_sta, -}; - -void ath_rate_attach(struct ath_softc *sc) -{ - sc->hw_rate_table[ATH9K_MODE_11A] = - &ar5416_11a_ratetable; - sc->hw_rate_table[ATH9K_MODE_11G] = - &ar5416_11g_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT20] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT20] = - &ar5416_11ng_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] = - &ar5416_11na_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] = - &ar5416_11ng_ratetable; - sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] = - &ar5416_11ng_ratetable; -} - -int ath_rate_control_register(void) -{ - return ieee80211_rate_control_register(&ath_rate_ops); -} - -void ath_rate_control_unregister(void) -{ - ieee80211_rate_control_unregister(&ath_rate_ops); -} diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h deleted file mode 100644 index fa21a628ddd0..000000000000 --- a/drivers/net/wireless/ath/ath9k/rc.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright (c) 2004 Sam Leffler, Errno Consulting - * Copyright (c) 2004 Video54 Technologies, Inc. - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef RC_H -#define RC_H - -struct ath_softc; - -#define ATH_RATE_MAX 30 -#define RATE_TABLE_SIZE 64 -#define MAX_TX_RATE_PHY 48 - -/* VALID_ALL - valid for 20/40/Legacy, - * VALID - Legacy only, - * VALID_20 - HT 20 only, - * VALID_40 - HT 40 only */ - -#define INVALID 0x0 -#define VALID 0x1 -#define VALID_20 0x2 -#define VALID_40 0x4 -#define VALID_2040 (VALID_20|VALID_40) -#define VALID_ALL (VALID_2040|VALID) - -enum { - WLAN_RC_PHY_OFDM, - WLAN_RC_PHY_CCK, - WLAN_RC_PHY_HT_20_SS, - WLAN_RC_PHY_HT_20_DS, - WLAN_RC_PHY_HT_40_SS, - WLAN_RC_PHY_HT_40_DS, - WLAN_RC_PHY_HT_20_SS_HGI, - WLAN_RC_PHY_HT_20_DS_HGI, - WLAN_RC_PHY_HT_40_SS_HGI, - WLAN_RC_PHY_HT_40_DS_HGI, - WLAN_RC_PHY_MAX -}; - -#define WLAN_RC_PHY_DS(_phy) ((_phy == WLAN_RC_PHY_HT_20_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) -#define WLAN_RC_PHY_40(_phy) ((_phy == WLAN_RC_PHY_HT_40_SS) \ - || (_phy == WLAN_RC_PHY_HT_40_DS) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) -#define WLAN_RC_PHY_SGI(_phy) ((_phy == WLAN_RC_PHY_HT_20_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_20_DS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_SS_HGI) \ - || (_phy == WLAN_RC_PHY_HT_40_DS_HGI)) - -#define WLAN_RC_PHY_HT(_phy) (_phy >= WLAN_RC_PHY_HT_20_SS) - -#define WLAN_RC_CAP_MODE(capflag) (((capflag & WLAN_RC_HT_FLAG) ? \ - (capflag & WLAN_RC_40_FLAG) ? VALID_40 : VALID_20 : VALID)) - -/* Return TRUE if flag supports HT20 && client supports HT20 or - * return TRUE if flag supports HT40 && client supports HT40. - * This is used becos some rates overlap between HT20/HT40. - */ -#define WLAN_RC_PHY_HT_VALID(flag, capflag) \ - (((flag & VALID_20) && !(capflag & WLAN_RC_40_FLAG)) || \ - ((flag & VALID_40) && (capflag & WLAN_RC_40_FLAG))) - -#define WLAN_RC_DS_FLAG (0x01) -#define WLAN_RC_40_FLAG (0x02) -#define WLAN_RC_SGI_FLAG (0x04) -#define WLAN_RC_HT_FLAG (0x08) - -/** - * struct ath_rate_table - Rate Control table - * @valid: valid for use in rate control - * @valid_single_stream: valid for use in rate control for - * single stream operation - * @phy: CCK/OFDM - * @ratekbps: rate in Kbits per second - * @user_ratekbps: user rate in Kbits per second - * @ratecode: rate that goes into HW descriptors - * @short_preamble: Mask for enabling short preamble in ratecode for CCK - * @dot11rate: value that goes into supported - * rates info element of MLME - * @ctrl_rate: Index of next lower basic rate, used for duration computation - * @max_4ms_framelen: maximum frame length(bytes) for tx duration - * @probe_interval: interval for rate control to probe for other rates - * @rssi_reduce_interval: interval for rate control to reduce rssi - * @initial_ratemax: initial ratemax value - */ -struct ath_rate_table { - int rate_cnt; - struct { - int valid; - int valid_single_stream; - u8 phy; - u32 ratekbps; - u32 user_ratekbps; - u8 ratecode; - u8 short_preamble; - u8 dot11rate; - u8 ctrl_rate; - u8 base_index; - u8 cw40index; - u8 sgi_index; - u8 ht_index; - u32 max_4ms_framelen; - } info[RATE_TABLE_SIZE]; - u32 probe_interval; - u8 initial_ratemax; -}; - -struct ath_rateset { - u8 rs_nrates; - u8 rs_rates[ATH_RATE_MAX]; -}; - -/** - * struct ath_rate_priv - Rate Control priv data - * @state: RC state - * @probe_rate: rate we are probing at - * @probe_time: msec timestamp for last probe - * @hw_maxretry_pktcnt: num of packets since we got HW max retry error - * @max_valid_rate: maximum number of valid rate - * @per_down_time: msec timestamp for last PER down step - * @valid_phy_ratecnt: valid rate count - * @rate_max_phy: phy index for the max rate - * @per: PER for every valid rate in % - * @probe_interval: interval for ratectrl to probe for other rates - * @prev_data_rix: rate idx of last data frame - * @ht_cap: HT capabilities - * @neg_rates: Negotatied rates - * @neg_ht_rates: Negotiated HT rates - */ -struct ath_rate_priv { - u8 rate_table_size; - u8 probe_rate; - u8 hw_maxretry_pktcnt; - u8 max_valid_rate; - u8 valid_rate_index[RATE_TABLE_SIZE]; - u8 ht_cap; - u8 valid_phy_ratecnt[WLAN_RC_PHY_MAX]; - u8 valid_phy_rateidx[WLAN_RC_PHY_MAX][RATE_TABLE_SIZE]; - u8 rate_max_phy; - u8 per[RATE_TABLE_SIZE]; - u32 probe_time; - u32 per_down_time; - u32 probe_interval; - u32 prev_data_rix; - u32 tx_triglevel_max; - struct ath_rateset neg_rates; - struct ath_rateset neg_ht_rates; - struct ath_rate_softc *asc; -}; - -enum ath9k_internal_frame_type { - ATH9K_NOT_INTERNAL, - ATH9K_INT_PAUSE, - ATH9K_INT_UNPAUSE -}; - -struct ath_tx_info_priv { - struct ath_wiphy *aphy; - struct ath_tx_status tx; - int n_frames; - int n_bad_frames; - bool update_rc; - enum ath9k_internal_frame_type frame_type; -}; - -#define ATH_TX_INFO_PRIV(tx_info) \ - ((struct ath_tx_info_priv *)((tx_info)->rate_driver_data[0])) - -void ath_rate_attach(struct ath_softc *sc); -u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate); -int ath_rate_control_register(void); -void ath_rate_control_unregister(void); - -#endif /* RC_H */ diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c deleted file mode 100644 index ec0abf823995..000000000000 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ /dev/null @@ -1,848 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -static struct ieee80211_hw * ath_get_virt_hw(struct ath_softc *sc, - struct ieee80211_hdr *hdr) -{ - struct ieee80211_hw *hw = sc->pri_wiphy->hw; - int i; - - spin_lock_bh(&sc->wiphy_lock); - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (aphy == NULL) - continue; - if (compare_ether_addr(hdr->addr1, aphy->hw->wiphy->perm_addr) - == 0) { - hw = aphy->hw; - break; - } - } - spin_unlock_bh(&sc->wiphy_lock); - return hw; -} - -/* - * Setup and link descriptors. - * - * 11N: we can no longer afford to self link the last descriptor. - * MAC acknowledges BA status as long as it copies frames to host - * buffer (or rx fifo). This can incorrectly acknowledge packets - * to a sender if last desc is self-linked. - */ -static void ath_rx_buf_link(struct ath_softc *sc, struct ath_buf *bf) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_desc *ds; - struct sk_buff *skb; - - ATH_RXBUF_RESET(bf); - - ds = bf->bf_desc; - ds->ds_link = 0; /* link to null */ - ds->ds_data = bf->bf_buf_addr; - - /* virtual addr of the beginning of the buffer. */ - skb = bf->bf_mpdu; - ASSERT(skb != NULL); - ds->ds_vdata = skb->data; - - /* setup rx descriptors. The rx.bufsize here tells the harware - * how much data it can DMA to us and that we are prepared - * to process */ - ath9k_hw_setuprxdesc(ah, ds, - sc->rx.bufsize, - 0); - - if (sc->rx.rxlink == NULL) - ath9k_hw_putrxbuf(ah, bf->bf_daddr); - else - *sc->rx.rxlink = bf->bf_daddr; - - sc->rx.rxlink = &ds->ds_link; - ath9k_hw_rxena(ah); -} - -static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) -{ - /* XXX block beacon interrupts */ - ath9k_hw_setantenna(sc->sc_ah, antenna); - sc->rx.defant = antenna; - sc->rx.rxotherant = 0; -} - -/* - * Extend 15-bit time stamp from rx descriptor to - * a full 64-bit TSF using the current h/w TSF. -*/ -static u64 ath_extend_tsf(struct ath_softc *sc, u32 rstamp) -{ - u64 tsf; - - tsf = ath9k_hw_gettsf64(sc->sc_ah); - if ((tsf & 0x7fff) < rstamp) - tsf -= 0x8000; - return (tsf & ~0x7fff) | rstamp; -} - -/* - * For Decrypt or Demic errors, we only mark packet status here and always push - * up the frame up to let mac80211 handle the actual error case, be it no - * decryption key or real decryption error. This let us keep statistics there. - */ -static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, - struct ieee80211_rx_status *rx_status, bool *decrypt_error, - struct ath_softc *sc) -{ - struct ieee80211_hdr *hdr; - u8 ratecode; - __le16 fc; - struct ieee80211_hw *hw; - struct ieee80211_sta *sta; - struct ath_node *an; - int last_rssi = ATH_RSSI_DUMMY_MARKER; - - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); - hw = ath_get_virt_hw(sc, hdr); - - if (ds->ds_rxstat.rs_more) { - /* - * Frame spans multiple descriptors; this cannot happen yet - * as we don't support jumbograms. If not in monitor mode, - * discard the frame. Enable this if you want to see - * error frames in Monitor mode. - */ - if (sc->sc_ah->opmode != NL80211_IFTYPE_MONITOR) - goto rx_next; - } else if (ds->ds_rxstat.rs_status != 0) { - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_CRC) - rx_status->flag |= RX_FLAG_FAILED_FCS_CRC; - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_PHY) - goto rx_next; - - if (ds->ds_rxstat.rs_status & ATH9K_RXERR_DECRYPT) { - *decrypt_error = true; - } else if (ds->ds_rxstat.rs_status & ATH9K_RXERR_MIC) { - if (ieee80211_is_ctl(fc)) - /* - * Sometimes, we get invalid - * MIC failures on valid control frames. - * Remove these mic errors. - */ - ds->ds_rxstat.rs_status &= ~ATH9K_RXERR_MIC; - else - rx_status->flag |= RX_FLAG_MMIC_ERROR; - } - /* - * Reject error frames with the exception of - * decryption and MIC failures. For monitor mode, - * we also ignore the CRC error. - */ - if (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR) { - if (ds->ds_rxstat.rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | - ATH9K_RXERR_CRC)) - goto rx_next; - } else { - if (ds->ds_rxstat.rs_status & - ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { - goto rx_next; - } - } - } - - ratecode = ds->ds_rxstat.rs_rate; - - if (ratecode & 0x80) { - /* HT rate */ - rx_status->flag |= RX_FLAG_HT; - if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) - rx_status->flag |= RX_FLAG_40MHZ; - if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) - rx_status->flag |= RX_FLAG_SHORT_GI; - rx_status->rate_idx = ratecode & 0x7f; - } else { - int i = 0, cur_band, n_rates; - - cur_band = hw->conf.channel->band; - n_rates = sc->sbands[cur_band].n_bitrates; - - for (i = 0; i < n_rates; i++) { - if (sc->sbands[cur_band].bitrates[i].hw_value == - ratecode) { - rx_status->rate_idx = i; - break; - } - - if (sc->sbands[cur_band].bitrates[i].hw_value_short == - ratecode) { - rx_status->rate_idx = i; - rx_status->flag |= RX_FLAG_SHORTPRE; - break; - } - } - } - - rcu_read_lock(); - sta = ieee80211_find_sta(sc->hw, hdr->addr2); - if (sta) { - an = (struct ath_node *) sta->drv_priv; - if (ds->ds_rxstat.rs_rssi != ATH9K_RSSI_BAD && - !ds->ds_rxstat.rs_moreaggr) - ATH_RSSI_LPF(an->last_rssi, ds->ds_rxstat.rs_rssi); - last_rssi = an->last_rssi; - } - rcu_read_unlock(); - - if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) - ds->ds_rxstat.rs_rssi = ATH_EP_RND(last_rssi, - ATH_RSSI_EP_MULTIPLIER); - if (ds->ds_rxstat.rs_rssi < 0) - ds->ds_rxstat.rs_rssi = 0; - else if (ds->ds_rxstat.rs_rssi > 127) - ds->ds_rxstat.rs_rssi = 127; - - /* Update Beacon RSSI, this is used by ANI. */ - if (ieee80211_is_beacon(fc)) - sc->sc_ah->stats.avgbrssi = ds->ds_rxstat.rs_rssi; - - rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); - rx_status->band = hw->conf.channel->band; - rx_status->freq = hw->conf.channel->center_freq; - rx_status->noise = sc->ani.noise_floor; - rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + ds->ds_rxstat.rs_rssi; - rx_status->antenna = ds->ds_rxstat.rs_antenna; - - /* - * Theory for reporting quality: - * - * At a hardware RSSI of 45 you will be able to use MCS 7 reliably. - * At a hardware RSSI of 45 you will be able to use MCS 15 reliably. - * At a hardware RSSI of 35 you should be able use 54 Mbps reliably. - * - * MCS 7 is the highets MCS index usable by a 1-stream device. - * MCS 15 is the highest MCS index usable by a 2-stream device. - * - * All ath9k devices are either 1-stream or 2-stream. - * - * How many bars you see is derived from the qual reporting. - * - * A more elaborate scheme can be used here but it requires tables - * of SNR/throughput for each possible mode used. For the MCS table - * you can refer to the wireless wiki: - * - * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n - * - */ - if (conf_is_ht(&hw->conf)) - rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 45; - else - rx_status->qual = ds->ds_rxstat.rs_rssi * 100 / 35; - - /* rssi can be more than 45 though, anything above that - * should be considered at 100% */ - if (rx_status->qual > 100) - rx_status->qual = 100; - - rx_status->flag |= RX_FLAG_TSFT; - - return 1; -rx_next: - return 0; -} - -static void ath_opmode_init(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - u32 rfilt, mfilt[2]; - - /* configure rx filter */ - rfilt = ath_calcrxfilter(sc); - ath9k_hw_setrxfilter(ah, rfilt); - - /* configure bssid mask */ - if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) - ath9k_hw_setbssidmask(sc); - - /* configure operational mode */ - ath9k_hw_setopmode(ah); - - /* Handle any link-level address change. */ - ath9k_hw_setmac(ah, sc->sc_ah->macaddr); - - /* calculate and install multicast filter */ - mfilt[0] = mfilt[1] = ~0; - ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); -} - -int ath_rx_init(struct ath_softc *sc, int nbufs) -{ - struct sk_buff *skb; - struct ath_buf *bf; - int error = 0; - - spin_lock_init(&sc->rx.rxflushlock); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_lock_init(&sc->rx.rxbuflock); - - sc->rx.bufsize = roundup(IEEE80211_MAX_MPDU_LEN, - min(sc->common.cachelsz, (u16)64)); - - DPRINTF(sc, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n", - sc->common.cachelsz, sc->rx.bufsize); - - /* Initialize rx descriptors */ - - error = ath_descdma_setup(sc, &sc->rx.rxdma, &sc->rx.rxbuf, - "rx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "failed to allocate rx descriptors: %d\n", error); - goto err; - } - - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_KERNEL); - if (skb == NULL) { - error = -ENOMEM; - goto err; - } - - bf->bf_mpdu = skb; - bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, - sc->rx.bufsize, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error() on RX init\n"); - error = -ENOMEM; - goto err; - } - bf->bf_dmacontext = bf->bf_buf_addr; - } - sc->rx.rxlink = NULL; - -err: - if (error) - ath_rx_cleanup(sc); - - return error; -} - -void ath_rx_cleanup(struct ath_softc *sc) -{ - struct sk_buff *skb; - struct ath_buf *bf; - - list_for_each_entry(bf, &sc->rx.rxbuf, list) { - skb = bf->bf_mpdu; - if (skb) { - dma_unmap_single(sc->dev, bf->bf_buf_addr, - sc->rx.bufsize, DMA_FROM_DEVICE); - dev_kfree_skb(skb); - } - } - - if (sc->rx.rxdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->rx.rxdma, &sc->rx.rxbuf); -} - -/* - * Calculate the receive filter according to the - * operating mode and state: - * - * o always accept unicast, broadcast, and multicast traffic - * o maintain current state of phy error reception (the hal - * may enable phy error frames for noise immunity work) - * o probe request frames are accepted only when operating in - * hostap, adhoc, or monitor modes - * o enable promiscuous mode according to the interface state - * o accept beacons: - * - when operating in adhoc mode so the 802.11 layer creates - * node table entries for peers, - * - when operating in station mode for collecting rssi data when - * the station is otherwise quiet, or - * - when operating as a repeater so we see repeater-sta beacons - * - when scanning - */ - -u32 ath_calcrxfilter(struct ath_softc *sc) -{ -#define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) - - u32 rfilt; - - rfilt = (ath9k_hw_getrxfilter(sc->sc_ah) & RX_FILTER_PRESERVE) - | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST - | ATH9K_RX_FILTER_MCAST; - - /* If not a STA, enable processing of Probe Requests */ - if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION) - rfilt |= ATH9K_RX_FILTER_PROBEREQ; - - /* - * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station - * mode interface or when in monitor mode. AP mode does not need this - * since it receives all in-BSS frames anyway. - */ - if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && - (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) || - (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR)) - rfilt |= ATH9K_RX_FILTER_PROM; - - if (sc->rx.rxfilter & FIF_CONTROL) - rfilt |= ATH9K_RX_FILTER_CONTROL; - - if ((sc->sc_ah->opmode == NL80211_IFTYPE_STATION) && - !(sc->rx.rxfilter & FIF_BCN_PRBRESP_PROMISC)) - rfilt |= ATH9K_RX_FILTER_MYBEACON; - else - rfilt |= ATH9K_RX_FILTER_BEACON; - - if (sc->rx.rxfilter & FIF_PSPOLL) - rfilt |= ATH9K_RX_FILTER_PSPOLL; - - if (conf_is_ht(&sc->hw->conf)) - rfilt |= ATH9K_RX_FILTER_COMP_BAR; - - if (sc->sec_wiphy || (sc->rx.rxfilter & FIF_OTHER_BSS)) { - /* TODO: only needed if more than one BSSID is in use in - * station/adhoc mode */ - /* The following may also be needed for other older chips */ - if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) - rfilt |= ATH9K_RX_FILTER_PROM; - rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; - } - - return rfilt; - -#undef RX_FILTER_PRESERVE -} - -int ath_startrecv(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf, *tbf; - - spin_lock_bh(&sc->rx.rxbuflock); - if (list_empty(&sc->rx.rxbuf)) - goto start_recv; - - sc->rx.rxlink = NULL; - list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) { - ath_rx_buf_link(sc, bf); - } - - /* We could have deleted elements so the list may be empty now */ - if (list_empty(&sc->rx.rxbuf)) - goto start_recv; - - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); - ath9k_hw_putrxbuf(ah, bf->bf_daddr); - ath9k_hw_rxena(ah); - -start_recv: - spin_unlock_bh(&sc->rx.rxbuflock); - ath_opmode_init(sc); - ath9k_hw_startpcureceive(ah); - - return 0; -} - -bool ath_stoprecv(struct ath_softc *sc) -{ - struct ath_hw *ah = sc->sc_ah; - bool stopped; - - ath9k_hw_stoppcurecv(ah); - ath9k_hw_setrxfilter(ah, 0); - stopped = ath9k_hw_stopdmarecv(ah); - sc->rx.rxlink = NULL; - - return stopped; -} - -void ath_flushrecv(struct ath_softc *sc) -{ - spin_lock_bh(&sc->rx.rxflushlock); - sc->sc_flags |= SC_OP_RXFLUSH; - ath_rx_tasklet(sc, 1); - sc->sc_flags &= ~SC_OP_RXFLUSH; - spin_unlock_bh(&sc->rx.rxflushlock); -} - -static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) -{ - /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ - struct ieee80211_mgmt *mgmt; - u8 *pos, *end, id, elen; - struct ieee80211_tim_ie *tim; - - mgmt = (struct ieee80211_mgmt *)skb->data; - pos = mgmt->u.beacon.variable; - end = skb->data + skb->len; - - while (pos + 2 < end) { - id = *pos++; - elen = *pos++; - if (pos + elen > end) - break; - - if (id == WLAN_EID_TIM) { - if (elen < sizeof(*tim)) - break; - tim = (struct ieee80211_tim_ie *) pos; - if (tim->dtim_count != 0) - break; - return tim->bitmap_ctrl & 0x01; - } - - pos += elen; - } - - return false; -} - -static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ieee80211_mgmt *mgmt; - - if (skb->len < 24 + 8 + 2 + 2) - return; - - mgmt = (struct ieee80211_mgmt *)skb->data; - if (memcmp(sc->curbssid, mgmt->bssid, ETH_ALEN) != 0) - return; /* not from our current AP */ - - sc->sc_flags &= ~SC_OP_WAIT_FOR_BEACON; - - if (sc->sc_flags & SC_OP_BEACON_SYNC) { - sc->sc_flags &= ~SC_OP_BEACON_SYNC; - DPRINTF(sc, ATH_DBG_PS, "Reconfigure Beacon timers based on " - "timestamp from the AP\n"); - ath_beacon_config(sc, NULL); - } - - if (ath_beacon_dtim_pending_cab(skb)) { - /* - * Remain awake waiting for buffered broadcast/multicast - * frames. If the last broadcast/multicast frame is not - * received properly, the next beacon frame will work as - * a backup trigger for returning into NETWORK SLEEP state, - * so we are waiting for it as well. - */ - DPRINTF(sc, ATH_DBG_PS, "Received DTIM beacon indicating " - "buffered broadcast/multicast frame(s)\n"); - sc->sc_flags |= SC_OP_WAIT_FOR_CAB | SC_OP_WAIT_FOR_BEACON; - return; - } - - if (sc->sc_flags & SC_OP_WAIT_FOR_CAB) { - /* - * This can happen if a broadcast frame is dropped or the AP - * fails to send a frame indicating that all CAB frames have - * been delivered. - */ - sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; - DPRINTF(sc, ATH_DBG_PS, "PS wait for CAB frames timed out\n"); - } -} - -static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *)skb->data; - - /* Process Beacon and CAB receive in PS state */ - if ((sc->sc_flags & SC_OP_WAIT_FOR_BEACON) && - ieee80211_is_beacon(hdr->frame_control)) - ath_rx_ps_beacon(sc, skb); - else if ((sc->sc_flags & SC_OP_WAIT_FOR_CAB) && - (ieee80211_is_data(hdr->frame_control) || - ieee80211_is_action(hdr->frame_control)) && - is_multicast_ether_addr(hdr->addr1) && - !ieee80211_has_moredata(hdr->frame_control)) { - /* - * No more broadcast/multicast frames to be received at this - * point. - */ - sc->sc_flags &= ~SC_OP_WAIT_FOR_CAB; - DPRINTF(sc, ATH_DBG_PS, "All PS CAB frames received, back to " - "sleep\n"); - } else if ((sc->sc_flags & SC_OP_WAIT_FOR_PSPOLL_DATA) && - !is_multicast_ether_addr(hdr->addr1) && - !ieee80211_has_morefrags(hdr->frame_control)) { - sc->sc_flags &= ~SC_OP_WAIT_FOR_PSPOLL_DATA; - DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having " - "received PS-Poll data (0x%x)\n", - sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK)); - } -} - -static void ath_rx_send_to_mac80211(struct ath_softc *sc, struct sk_buff *skb, - struct ieee80211_rx_status *rx_status) -{ - struct ieee80211_hdr *hdr; - - hdr = (struct ieee80211_hdr *)skb->data; - - /* Send the frame to mac80211 */ - if (is_multicast_ether_addr(hdr->addr1)) { - int i; - /* - * Deliver broadcast/multicast frames to all suitable - * virtual wiphys. - */ - /* TODO: filter based on channel configuration */ - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - struct sk_buff *nskb; - if (aphy == NULL) - continue; - nskb = skb_copy(skb, GFP_ATOMIC); - if (nskb) { - memcpy(IEEE80211_SKB_RXCB(nskb), rx_status, - sizeof(*rx_status)); - ieee80211_rx(aphy->hw, nskb); - } - } - memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); - ieee80211_rx(sc->hw, skb); - } else { - /* Deliver unicast frames based on receiver address */ - memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); - ieee80211_rx(ath_get_virt_hw(sc, hdr), skb); - } -} - -int ath_rx_tasklet(struct ath_softc *sc, int flush) -{ -#define PA2DESC(_sc, _pa) \ - ((struct ath_desc *)((caddr_t)(_sc)->rx.rxdma.dd_desc + \ - ((_pa) - (_sc)->rx.rxdma.dd_desc_paddr))) - - struct ath_buf *bf; - struct ath_desc *ds; - struct sk_buff *skb = NULL, *requeue_skb; - struct ieee80211_rx_status rx_status; - struct ath_hw *ah = sc->sc_ah; - struct ieee80211_hdr *hdr; - int hdrlen, padsize, retval; - bool decrypt_error = false; - u8 keyix; - __le16 fc; - - spin_lock_bh(&sc->rx.rxbuflock); - - do { - /* If handling rx interrupt and flush is in progress => exit */ - if ((sc->sc_flags & SC_OP_RXFLUSH) && (flush == 0)) - break; - - if (list_empty(&sc->rx.rxbuf)) { - sc->rx.rxlink = NULL; - break; - } - - bf = list_first_entry(&sc->rx.rxbuf, struct ath_buf, list); - ds = bf->bf_desc; - - /* - * Must provide the virtual address of the current - * descriptor, the physical address, and the virtual - * address of the next descriptor in the h/w chain. - * This allows the HAL to look ahead to see if the - * hardware is done with a descriptor by checking the - * done bit in the following descriptor and the address - * of the current descriptor the DMA engine is working - * on. All this is necessary because of our use of - * a self-linked list to avoid rx overruns. - */ - retval = ath9k_hw_rxprocdesc(ah, ds, - bf->bf_daddr, - PA2DESC(sc, ds->ds_link), - 0); - if (retval == -EINPROGRESS) { - struct ath_buf *tbf; - struct ath_desc *tds; - - if (list_is_last(&bf->list, &sc->rx.rxbuf)) { - sc->rx.rxlink = NULL; - break; - } - - tbf = list_entry(bf->list.next, struct ath_buf, list); - - /* - * On some hardware the descriptor status words could - * get corrupted, including the done bit. Because of - * this, check if the next descriptor's done bit is - * set or not. - * - * If the next descriptor's done bit is set, the current - * descriptor has been corrupted. Force s/w to discard - * this descriptor and continue... - */ - - tds = tbf->bf_desc; - retval = ath9k_hw_rxprocdesc(ah, tds, tbf->bf_daddr, - PA2DESC(sc, tds->ds_link), 0); - if (retval == -EINPROGRESS) { - break; - } - } - - skb = bf->bf_mpdu; - if (!skb) - continue; - - /* - * Synchronize the DMA transfer with CPU before - * 1. accessing the frame - * 2. requeueing the same buffer to h/w - */ - dma_sync_single_for_cpu(sc->dev, bf->bf_buf_addr, - sc->rx.bufsize, - DMA_FROM_DEVICE); - - /* - * If we're asked to flush receive queue, directly - * chain it back at the queue without processing it. - */ - if (flush) - goto requeue; - - if (!ds->ds_rxstat.rs_datalen) - goto requeue; - - /* The status portion of the descriptor could get corrupted. */ - if (sc->rx.bufsize < ds->ds_rxstat.rs_datalen) - goto requeue; - - if (!ath_rx_prepare(skb, ds, &rx_status, &decrypt_error, sc)) - goto requeue; - - /* Ensure we always have an skb to requeue once we are done - * processing the current buffer's skb */ - requeue_skb = ath_rxbuf_alloc(&sc->common, sc->rx.bufsize, GFP_ATOMIC); - - /* If there is no memory we ignore the current RX'd frame, - * tell hardware it can give us a new frame using the old - * skb and put it at the tail of the sc->rx.rxbuf list for - * processing. */ - if (!requeue_skb) - goto requeue; - - /* Unmap the frame */ - dma_unmap_single(sc->dev, bf->bf_buf_addr, - sc->rx.bufsize, - DMA_FROM_DEVICE); - - skb_put(skb, ds->ds_rxstat.rs_datalen); - - /* see if any padding is done by the hw and remove it */ - hdr = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; - - /* The MAC header is padded to have 32-bit boundary if the - * packet payload is non-zero. The general calculation for - * padsize would take into account odd header lengths: - * padsize = (4 - hdrlen % 4) % 4; However, since only - * even-length headers are used, padding can only be 0 or 2 - * bytes and we can optimize this a bit. In addition, we must - * not try to remove padding from short control frames that do - * not have payload. */ - padsize = hdrlen & 3; - if (padsize && hdrlen >= 24) { - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - keyix = ds->ds_rxstat.rs_keyix; - - if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { - rx_status.flag |= RX_FLAG_DECRYPTED; - } else if (ieee80211_has_protected(fc) - && !decrypt_error && skb->len >= hdrlen + 4) { - keyix = skb->data[hdrlen + 3] >> 6; - - if (test_bit(keyix, sc->keymap)) - rx_status.flag |= RX_FLAG_DECRYPTED; - } - if (ah->sw_mgmt_crypto && - (rx_status.flag & RX_FLAG_DECRYPTED) && - ieee80211_is_mgmt(fc)) { - /* Use software decrypt for management frames. */ - rx_status.flag &= ~RX_FLAG_DECRYPTED; - } - - /* We will now give hardware our shiny new allocated skb */ - bf->bf_mpdu = requeue_skb; - bf->bf_buf_addr = dma_map_single(sc->dev, requeue_skb->data, - sc->rx.bufsize, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, - bf->bf_buf_addr))) { - dev_kfree_skb_any(requeue_skb); - bf->bf_mpdu = NULL; - DPRINTF(sc, ATH_DBG_FATAL, - "dma_mapping_error() on RX\n"); - ath_rx_send_to_mac80211(sc, skb, &rx_status); - break; - } - bf->bf_dmacontext = bf->bf_buf_addr; - - /* - * change the default rx antenna if rx diversity chooses the - * other antenna 3 times in a row. - */ - if (sc->rx.defant != ds->ds_rxstat.rs_antenna) { - if (++sc->rx.rxotherant >= 3) - ath_setdefantenna(sc, ds->ds_rxstat.rs_antenna); - } else { - sc->rx.rxotherant = 0; - } - - if (unlikely(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA))) - ath_rx_ps(sc, skb); - - ath_rx_send_to_mac80211(sc, skb, &rx_status); - -requeue: - list_move_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_buf_link(sc, bf); - } while (1); - - spin_unlock_bh(&sc->rx.rxbuflock); - - return 0; -#undef PA2DESC -} diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h deleted file mode 100644 index c0d7e65bf6d4..000000000000 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ /dev/null @@ -1,1708 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef REG_H -#define REG_H - -#define AR_CR 0x0008 -#define AR_CR_RXE 0x00000004 -#define AR_CR_RXD 0x00000020 -#define AR_CR_SWI 0x00000040 - -#define AR_RXDP 0x000C - -#define AR_CFG 0x0014 -#define AR_CFG_SWTD 0x00000001 -#define AR_CFG_SWTB 0x00000002 -#define AR_CFG_SWRD 0x00000004 -#define AR_CFG_SWRB 0x00000008 -#define AR_CFG_SWRG 0x00000010 -#define AR_CFG_AP_ADHOC_INDICATION 0x00000020 -#define AR_CFG_PHOK 0x00000100 -#define AR_CFG_CLK_GATE_DIS 0x00000400 -#define AR_CFG_EEBS 0x00000200 -#define AR_CFG_PCI_MASTER_REQ_Q_THRESH 0x00060000 -#define AR_CFG_PCI_MASTER_REQ_Q_THRESH_S 17 - -#define AR_MIRT 0x0020 -#define AR_MIRT_VAL 0x0000ffff -#define AR_MIRT_VAL_S 16 - -#define AR_IER 0x0024 -#define AR_IER_ENABLE 0x00000001 -#define AR_IER_DISABLE 0x00000000 - -#define AR_TIMT 0x0028 -#define AR_TIMT_LAST 0x0000ffff -#define AR_TIMT_LAST_S 0 -#define AR_TIMT_FIRST 0xffff0000 -#define AR_TIMT_FIRST_S 16 - -#define AR_RIMT 0x002C -#define AR_RIMT_LAST 0x0000ffff -#define AR_RIMT_LAST_S 0 -#define AR_RIMT_FIRST 0xffff0000 -#define AR_RIMT_FIRST_S 16 - -#define AR_DMASIZE_4B 0x00000000 -#define AR_DMASIZE_8B 0x00000001 -#define AR_DMASIZE_16B 0x00000002 -#define AR_DMASIZE_32B 0x00000003 -#define AR_DMASIZE_64B 0x00000004 -#define AR_DMASIZE_128B 0x00000005 -#define AR_DMASIZE_256B 0x00000006 -#define AR_DMASIZE_512B 0x00000007 - -#define AR_TXCFG 0x0030 -#define AR_TXCFG_DMASZ_MASK 0x00000007 -#define AR_TXCFG_DMASZ_4B 0 -#define AR_TXCFG_DMASZ_8B 1 -#define AR_TXCFG_DMASZ_16B 2 -#define AR_TXCFG_DMASZ_32B 3 -#define AR_TXCFG_DMASZ_64B 4 -#define AR_TXCFG_DMASZ_128B 5 -#define AR_TXCFG_DMASZ_256B 6 -#define AR_TXCFG_DMASZ_512B 7 -#define AR_FTRIG 0x000003F0 -#define AR_FTRIG_S 4 -#define AR_FTRIG_IMMED 0x00000000 -#define AR_FTRIG_64B 0x00000010 -#define AR_FTRIG_128B 0x00000020 -#define AR_FTRIG_192B 0x00000030 -#define AR_FTRIG_256B 0x00000040 -#define AR_FTRIG_512B 0x00000080 -#define AR_TXCFG_ADHOC_BEACON_ATIM_TX_POLICY 0x00000800 - -#define AR_RXCFG 0x0034 -#define AR_RXCFG_CHIRP 0x00000008 -#define AR_RXCFG_ZLFDMA 0x00000010 -#define AR_RXCFG_DMASZ_MASK 0x00000007 -#define AR_RXCFG_DMASZ_4B 0 -#define AR_RXCFG_DMASZ_8B 1 -#define AR_RXCFG_DMASZ_16B 2 -#define AR_RXCFG_DMASZ_32B 3 -#define AR_RXCFG_DMASZ_64B 4 -#define AR_RXCFG_DMASZ_128B 5 -#define AR_RXCFG_DMASZ_256B 6 -#define AR_RXCFG_DMASZ_512B 7 - -#define AR_MIBC 0x0040 -#define AR_MIBC_COW 0x00000001 -#define AR_MIBC_FMC 0x00000002 -#define AR_MIBC_CMC 0x00000004 -#define AR_MIBC_MCS 0x00000008 - -#define AR_TOPS 0x0044 -#define AR_TOPS_MASK 0x0000FFFF - -#define AR_RXNPTO 0x0048 -#define AR_RXNPTO_MASK 0x000003FF - -#define AR_TXNPTO 0x004C -#define AR_TXNPTO_MASK 0x000003FF -#define AR_TXNPTO_QCU_MASK 0x000FFC00 - -#define AR_RPGTO 0x0050 -#define AR_RPGTO_MASK 0x000003FF - -#define AR_RPCNT 0x0054 -#define AR_RPCNT_MASK 0x0000001F - -#define AR_MACMISC 0x0058 -#define AR_MACMISC_PCI_EXT_FORCE 0x00000010 -#define AR_MACMISC_DMA_OBS 0x000001E0 -#define AR_MACMISC_DMA_OBS_S 5 -#define AR_MACMISC_DMA_OBS_LINE_0 0 -#define AR_MACMISC_DMA_OBS_LINE_1 1 -#define AR_MACMISC_DMA_OBS_LINE_2 2 -#define AR_MACMISC_DMA_OBS_LINE_3 3 -#define AR_MACMISC_DMA_OBS_LINE_4 4 -#define AR_MACMISC_DMA_OBS_LINE_5 5 -#define AR_MACMISC_DMA_OBS_LINE_6 6 -#define AR_MACMISC_DMA_OBS_LINE_7 7 -#define AR_MACMISC_DMA_OBS_LINE_8 8 -#define AR_MACMISC_MISC_OBS 0x00000E00 -#define AR_MACMISC_MISC_OBS_S 9 -#define AR_MACMISC_MISC_OBS_BUS_LSB 0x00007000 -#define AR_MACMISC_MISC_OBS_BUS_LSB_S 12 -#define AR_MACMISC_MISC_OBS_BUS_MSB 0x00038000 -#define AR_MACMISC_MISC_OBS_BUS_MSB_S 15 -#define AR_MACMISC_MISC_OBS_BUS_1 1 - -#define AR_GTXTO 0x0064 -#define AR_GTXTO_TIMEOUT_COUNTER 0x0000FFFF -#define AR_GTXTO_TIMEOUT_LIMIT 0xFFFF0000 -#define AR_GTXTO_TIMEOUT_LIMIT_S 16 - -#define AR_GTTM 0x0068 -#define AR_GTTM_USEC 0x00000001 -#define AR_GTTM_IGNORE_IDLE 0x00000002 -#define AR_GTTM_RESET_IDLE 0x00000004 -#define AR_GTTM_CST_USEC 0x00000008 - -#define AR_CST 0x006C -#define AR_CST_TIMEOUT_COUNTER 0x0000FFFF -#define AR_CST_TIMEOUT_LIMIT 0xFFFF0000 -#define AR_CST_TIMEOUT_LIMIT_S 16 - -#define AR_ISR 0x0080 -#define AR_ISR_RXOK 0x00000001 -#define AR_ISR_RXDESC 0x00000002 -#define AR_ISR_RXERR 0x00000004 -#define AR_ISR_RXNOPKT 0x00000008 -#define AR_ISR_RXEOL 0x00000010 -#define AR_ISR_RXORN 0x00000020 -#define AR_ISR_TXOK 0x00000040 -#define AR_ISR_TXDESC 0x00000080 -#define AR_ISR_TXERR 0x00000100 -#define AR_ISR_TXNOPKT 0x00000200 -#define AR_ISR_TXEOL 0x00000400 -#define AR_ISR_TXURN 0x00000800 -#define AR_ISR_MIB 0x00001000 -#define AR_ISR_SWI 0x00002000 -#define AR_ISR_RXPHY 0x00004000 -#define AR_ISR_RXKCM 0x00008000 -#define AR_ISR_SWBA 0x00010000 -#define AR_ISR_BRSSI 0x00020000 -#define AR_ISR_BMISS 0x00040000 -#define AR_ISR_BNR 0x00100000 -#define AR_ISR_RXCHIRP 0x00200000 -#define AR_ISR_BCNMISC 0x00800000 -#define AR_ISR_TIM 0x00800000 -#define AR_ISR_QCBROVF 0x02000000 -#define AR_ISR_QCBRURN 0x04000000 -#define AR_ISR_QTRIG 0x08000000 -#define AR_ISR_GENTMR 0x10000000 - -#define AR_ISR_TXMINTR 0x00080000 -#define AR_ISR_RXMINTR 0x01000000 -#define AR_ISR_TXINTM 0x40000000 -#define AR_ISR_RXINTM 0x80000000 - -#define AR_ISR_S0 0x0084 -#define AR_ISR_S0_QCU_TXOK 0x000003FF -#define AR_ISR_S0_QCU_TXOK_S 0 -#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 -#define AR_ISR_S0_QCU_TXDESC_S 16 - -#define AR_ISR_S1 0x0088 -#define AR_ISR_S1_QCU_TXERR 0x000003FF -#define AR_ISR_S1_QCU_TXERR_S 0 -#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 -#define AR_ISR_S1_QCU_TXEOL_S 16 - -#define AR_ISR_S2 0x008c -#define AR_ISR_S2_QCU_TXURN 0x000003FF -#define AR_ISR_S2_CST 0x00400000 -#define AR_ISR_S2_GTT 0x00800000 -#define AR_ISR_S2_TIM 0x01000000 -#define AR_ISR_S2_CABEND 0x02000000 -#define AR_ISR_S2_DTIMSYNC 0x04000000 -#define AR_ISR_S2_BCNTO 0x08000000 -#define AR_ISR_S2_CABTO 0x10000000 -#define AR_ISR_S2_DTIM 0x20000000 -#define AR_ISR_S2_TSFOOR 0x40000000 -#define AR_ISR_S2_TBTT_TIME 0x80000000 - -#define AR_ISR_S3 0x0090 -#define AR_ISR_S3_QCU_QCBROVF 0x000003FF -#define AR_ISR_S3_QCU_QCBRURN 0x03FF0000 - -#define AR_ISR_S4 0x0094 -#define AR_ISR_S4_QCU_QTRIG 0x000003FF -#define AR_ISR_S4_RESV0 0xFFFFFC00 - -#define AR_ISR_S5 0x0098 -#define AR_ISR_S5_TIMER_TRIG 0x000000FF -#define AR_ISR_S5_TIMER_THRESH 0x0007FE00 -#define AR_ISR_S5_TIM_TIMER 0x00000010 -#define AR_ISR_S5_DTIM_TIMER 0x00000020 -#define AR_ISR_S5_S 0x00d8 -#define AR_IMR_S5 0x00b8 -#define AR_IMR_S5_TIM_TIMER 0x00000010 -#define AR_IMR_S5_DTIM_TIMER 0x00000020 -#define AR_ISR_S5_GENTIMER_TRIG 0x0000FF80 -#define AR_ISR_S5_GENTIMER_TRIG_S 0 -#define AR_ISR_S5_GENTIMER_THRESH 0xFF800000 -#define AR_ISR_S5_GENTIMER_THRESH_S 16 -#define AR_ISR_S5_S 0x00d8 -#define AR_IMR_S5_GENTIMER_TRIG 0x0000FF80 -#define AR_IMR_S5_GENTIMER_TRIG_S 0 -#define AR_IMR_S5_GENTIMER_THRESH 0xFF800000 -#define AR_IMR_S5_GENTIMER_THRESH_S 16 - -#define AR_IMR 0x00a0 -#define AR_IMR_RXOK 0x00000001 -#define AR_IMR_RXDESC 0x00000002 -#define AR_IMR_RXERR 0x00000004 -#define AR_IMR_RXNOPKT 0x00000008 -#define AR_IMR_RXEOL 0x00000010 -#define AR_IMR_RXORN 0x00000020 -#define AR_IMR_TXOK 0x00000040 -#define AR_IMR_TXDESC 0x00000080 -#define AR_IMR_TXERR 0x00000100 -#define AR_IMR_TXNOPKT 0x00000200 -#define AR_IMR_TXEOL 0x00000400 -#define AR_IMR_TXURN 0x00000800 -#define AR_IMR_MIB 0x00001000 -#define AR_IMR_SWI 0x00002000 -#define AR_IMR_RXPHY 0x00004000 -#define AR_IMR_RXKCM 0x00008000 -#define AR_IMR_SWBA 0x00010000 -#define AR_IMR_BRSSI 0x00020000 -#define AR_IMR_BMISS 0x00040000 -#define AR_IMR_BNR 0x00100000 -#define AR_IMR_RXCHIRP 0x00200000 -#define AR_IMR_BCNMISC 0x00800000 -#define AR_IMR_TIM 0x00800000 -#define AR_IMR_QCBROVF 0x02000000 -#define AR_IMR_QCBRURN 0x04000000 -#define AR_IMR_QTRIG 0x08000000 -#define AR_IMR_GENTMR 0x10000000 - -#define AR_IMR_TXMINTR 0x00080000 -#define AR_IMR_RXMINTR 0x01000000 -#define AR_IMR_TXINTM 0x40000000 -#define AR_IMR_RXINTM 0x80000000 - -#define AR_IMR_S0 0x00a4 -#define AR_IMR_S0_QCU_TXOK 0x000003FF -#define AR_IMR_S0_QCU_TXOK_S 0 -#define AR_IMR_S0_QCU_TXDESC 0x03FF0000 -#define AR_IMR_S0_QCU_TXDESC_S 16 - -#define AR_IMR_S1 0x00a8 -#define AR_IMR_S1_QCU_TXERR 0x000003FF -#define AR_IMR_S1_QCU_TXERR_S 0 -#define AR_IMR_S1_QCU_TXEOL 0x03FF0000 -#define AR_IMR_S1_QCU_TXEOL_S 16 - -#define AR_IMR_S2 0x00ac -#define AR_IMR_S2_QCU_TXURN 0x000003FF -#define AR_IMR_S2_QCU_TXURN_S 0 -#define AR_IMR_S2_CST 0x00400000 -#define AR_IMR_S2_GTT 0x00800000 -#define AR_IMR_S2_TIM 0x01000000 -#define AR_IMR_S2_CABEND 0x02000000 -#define AR_IMR_S2_DTIMSYNC 0x04000000 -#define AR_IMR_S2_BCNTO 0x08000000 -#define AR_IMR_S2_CABTO 0x10000000 -#define AR_IMR_S2_DTIM 0x20000000 -#define AR_IMR_S2_TSFOOR 0x40000000 - -#define AR_IMR_S3 0x00b0 -#define AR_IMR_S3_QCU_QCBROVF 0x000003FF -#define AR_IMR_S3_QCU_QCBRURN 0x03FF0000 -#define AR_IMR_S3_QCU_QCBRURN_S 16 - -#define AR_IMR_S4 0x00b4 -#define AR_IMR_S4_QCU_QTRIG 0x000003FF -#define AR_IMR_S4_RESV0 0xFFFFFC00 - -#define AR_IMR_S5 0x00b8 -#define AR_IMR_S5_TIMER_TRIG 0x000000FF -#define AR_IMR_S5_TIMER_THRESH 0x0000FF00 - - -#define AR_ISR_RAC 0x00c0 -#define AR_ISR_S0_S 0x00c4 -#define AR_ISR_S0_QCU_TXOK 0x000003FF -#define AR_ISR_S0_QCU_TXOK_S 0 -#define AR_ISR_S0_QCU_TXDESC 0x03FF0000 -#define AR_ISR_S0_QCU_TXDESC_S 16 - -#define AR_ISR_S1_S 0x00c8 -#define AR_ISR_S1_QCU_TXERR 0x000003FF -#define AR_ISR_S1_QCU_TXERR_S 0 -#define AR_ISR_S1_QCU_TXEOL 0x03FF0000 -#define AR_ISR_S1_QCU_TXEOL_S 16 - -#define AR_ISR_S2_S 0x00cc -#define AR_ISR_S3_S 0x00d0 -#define AR_ISR_S4_S 0x00d4 -#define AR_ISR_S5_S 0x00d8 -#define AR_DMADBG_0 0x00e0 -#define AR_DMADBG_1 0x00e4 -#define AR_DMADBG_2 0x00e8 -#define AR_DMADBG_3 0x00ec -#define AR_DMADBG_4 0x00f0 -#define AR_DMADBG_5 0x00f4 -#define AR_DMADBG_6 0x00f8 -#define AR_DMADBG_7 0x00fc - -#define AR_NUM_QCU 10 -#define AR_QCU_0 0x0001 -#define AR_QCU_1 0x0002 -#define AR_QCU_2 0x0004 -#define AR_QCU_3 0x0008 -#define AR_QCU_4 0x0010 -#define AR_QCU_5 0x0020 -#define AR_QCU_6 0x0040 -#define AR_QCU_7 0x0080 -#define AR_QCU_8 0x0100 -#define AR_QCU_9 0x0200 - -#define AR_Q0_TXDP 0x0800 -#define AR_Q1_TXDP 0x0804 -#define AR_Q2_TXDP 0x0808 -#define AR_Q3_TXDP 0x080c -#define AR_Q4_TXDP 0x0810 -#define AR_Q5_TXDP 0x0814 -#define AR_Q6_TXDP 0x0818 -#define AR_Q7_TXDP 0x081c -#define AR_Q8_TXDP 0x0820 -#define AR_Q9_TXDP 0x0824 -#define AR_QTXDP(_i) (AR_Q0_TXDP + ((_i)<<2)) - -#define AR_Q_TXE 0x0840 -#define AR_Q_TXE_M 0x000003FF - -#define AR_Q_TXD 0x0880 -#define AR_Q_TXD_M 0x000003FF - -#define AR_Q0_CBRCFG 0x08c0 -#define AR_Q1_CBRCFG 0x08c4 -#define AR_Q2_CBRCFG 0x08c8 -#define AR_Q3_CBRCFG 0x08cc -#define AR_Q4_CBRCFG 0x08d0 -#define AR_Q5_CBRCFG 0x08d4 -#define AR_Q6_CBRCFG 0x08d8 -#define AR_Q7_CBRCFG 0x08dc -#define AR_Q8_CBRCFG 0x08e0 -#define AR_Q9_CBRCFG 0x08e4 -#define AR_QCBRCFG(_i) (AR_Q0_CBRCFG + ((_i)<<2)) -#define AR_Q_CBRCFG_INTERVAL 0x00FFFFFF -#define AR_Q_CBRCFG_INTERVAL_S 0 -#define AR_Q_CBRCFG_OVF_THRESH 0xFF000000 -#define AR_Q_CBRCFG_OVF_THRESH_S 24 - -#define AR_Q0_RDYTIMECFG 0x0900 -#define AR_Q1_RDYTIMECFG 0x0904 -#define AR_Q2_RDYTIMECFG 0x0908 -#define AR_Q3_RDYTIMECFG 0x090c -#define AR_Q4_RDYTIMECFG 0x0910 -#define AR_Q5_RDYTIMECFG 0x0914 -#define AR_Q6_RDYTIMECFG 0x0918 -#define AR_Q7_RDYTIMECFG 0x091c -#define AR_Q8_RDYTIMECFG 0x0920 -#define AR_Q9_RDYTIMECFG 0x0924 -#define AR_QRDYTIMECFG(_i) (AR_Q0_RDYTIMECFG + ((_i)<<2)) -#define AR_Q_RDYTIMECFG_DURATION 0x00FFFFFF -#define AR_Q_RDYTIMECFG_DURATION_S 0 -#define AR_Q_RDYTIMECFG_EN 0x01000000 - -#define AR_Q_ONESHOTARM_SC 0x0940 -#define AR_Q_ONESHOTARM_SC_M 0x000003FF -#define AR_Q_ONESHOTARM_SC_RESV0 0xFFFFFC00 - -#define AR_Q_ONESHOTARM_CC 0x0980 -#define AR_Q_ONESHOTARM_CC_M 0x000003FF -#define AR_Q_ONESHOTARM_CC_RESV0 0xFFFFFC00 - -#define AR_Q0_MISC 0x09c0 -#define AR_Q1_MISC 0x09c4 -#define AR_Q2_MISC 0x09c8 -#define AR_Q3_MISC 0x09cc -#define AR_Q4_MISC 0x09d0 -#define AR_Q5_MISC 0x09d4 -#define AR_Q6_MISC 0x09d8 -#define AR_Q7_MISC 0x09dc -#define AR_Q8_MISC 0x09e0 -#define AR_Q9_MISC 0x09e4 -#define AR_QMISC(_i) (AR_Q0_MISC + ((_i)<<2)) -#define AR_Q_MISC_FSP 0x0000000F -#define AR_Q_MISC_FSP_ASAP 0 -#define AR_Q_MISC_FSP_CBR 1 -#define AR_Q_MISC_FSP_DBA_GATED 2 -#define AR_Q_MISC_FSP_TIM_GATED 3 -#define AR_Q_MISC_FSP_BEACON_SENT_GATED 4 -#define AR_Q_MISC_FSP_BEACON_RCVD_GATED 5 -#define AR_Q_MISC_ONE_SHOT_EN 0x00000010 -#define AR_Q_MISC_CBR_INCR_DIS1 0x00000020 -#define AR_Q_MISC_CBR_INCR_DIS0 0x00000040 -#define AR_Q_MISC_BEACON_USE 0x00000080 -#define AR_Q_MISC_CBR_EXP_CNTR_LIMIT_EN 0x00000100 -#define AR_Q_MISC_RDYTIME_EXP_POLICY 0x00000200 -#define AR_Q_MISC_RESET_CBR_EXP_CTR 0x00000400 -#define AR_Q_MISC_DCU_EARLY_TERM_REQ 0x00000800 -#define AR_Q_MISC_RESV0 0xFFFFF000 - -#define AR_Q0_STS 0x0a00 -#define AR_Q1_STS 0x0a04 -#define AR_Q2_STS 0x0a08 -#define AR_Q3_STS 0x0a0c -#define AR_Q4_STS 0x0a10 -#define AR_Q5_STS 0x0a14 -#define AR_Q6_STS 0x0a18 -#define AR_Q7_STS 0x0a1c -#define AR_Q8_STS 0x0a20 -#define AR_Q9_STS 0x0a24 -#define AR_QSTS(_i) (AR_Q0_STS + ((_i)<<2)) -#define AR_Q_STS_PEND_FR_CNT 0x00000003 -#define AR_Q_STS_RESV0 0x000000FC -#define AR_Q_STS_CBR_EXP_CNT 0x0000FF00 -#define AR_Q_STS_RESV1 0xFFFF0000 - -#define AR_Q_RDYTIMESHDN 0x0a40 -#define AR_Q_RDYTIMESHDN_M 0x000003FF - - -#define AR_NUM_DCU 10 -#define AR_DCU_0 0x0001 -#define AR_DCU_1 0x0002 -#define AR_DCU_2 0x0004 -#define AR_DCU_3 0x0008 -#define AR_DCU_4 0x0010 -#define AR_DCU_5 0x0020 -#define AR_DCU_6 0x0040 -#define AR_DCU_7 0x0080 -#define AR_DCU_8 0x0100 -#define AR_DCU_9 0x0200 - -#define AR_D0_QCUMASK 0x1000 -#define AR_D1_QCUMASK 0x1004 -#define AR_D2_QCUMASK 0x1008 -#define AR_D3_QCUMASK 0x100c -#define AR_D4_QCUMASK 0x1010 -#define AR_D5_QCUMASK 0x1014 -#define AR_D6_QCUMASK 0x1018 -#define AR_D7_QCUMASK 0x101c -#define AR_D8_QCUMASK 0x1020 -#define AR_D9_QCUMASK 0x1024 -#define AR_DQCUMASK(_i) (AR_D0_QCUMASK + ((_i)<<2)) -#define AR_D_QCUMASK 0x000003FF -#define AR_D_QCUMASK_RESV0 0xFFFFFC00 - -#define AR_D_TXBLK_CMD 0x1038 -#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i)) - -#define AR_D0_LCL_IFS 0x1040 -#define AR_D1_LCL_IFS 0x1044 -#define AR_D2_LCL_IFS 0x1048 -#define AR_D3_LCL_IFS 0x104c -#define AR_D4_LCL_IFS 0x1050 -#define AR_D5_LCL_IFS 0x1054 -#define AR_D6_LCL_IFS 0x1058 -#define AR_D7_LCL_IFS 0x105c -#define AR_D8_LCL_IFS 0x1060 -#define AR_D9_LCL_IFS 0x1064 -#define AR_DLCL_IFS(_i) (AR_D0_LCL_IFS + ((_i)<<2)) -#define AR_D_LCL_IFS_CWMIN 0x000003FF -#define AR_D_LCL_IFS_CWMIN_S 0 -#define AR_D_LCL_IFS_CWMAX 0x000FFC00 -#define AR_D_LCL_IFS_CWMAX_S 10 -#define AR_D_LCL_IFS_AIFS 0x0FF00000 -#define AR_D_LCL_IFS_AIFS_S 20 - -#define AR_D_LCL_IFS_RESV0 0xF0000000 - -#define AR_D0_RETRY_LIMIT 0x1080 -#define AR_D1_RETRY_LIMIT 0x1084 -#define AR_D2_RETRY_LIMIT 0x1088 -#define AR_D3_RETRY_LIMIT 0x108c -#define AR_D4_RETRY_LIMIT 0x1090 -#define AR_D5_RETRY_LIMIT 0x1094 -#define AR_D6_RETRY_LIMIT 0x1098 -#define AR_D7_RETRY_LIMIT 0x109c -#define AR_D8_RETRY_LIMIT 0x10a0 -#define AR_D9_RETRY_LIMIT 0x10a4 -#define AR_DRETRY_LIMIT(_i) (AR_D0_RETRY_LIMIT + ((_i)<<2)) -#define AR_D_RETRY_LIMIT_FR_SH 0x0000000F -#define AR_D_RETRY_LIMIT_FR_SH_S 0 -#define AR_D_RETRY_LIMIT_STA_SH 0x00003F00 -#define AR_D_RETRY_LIMIT_STA_SH_S 8 -#define AR_D_RETRY_LIMIT_STA_LG 0x000FC000 -#define AR_D_RETRY_LIMIT_STA_LG_S 14 -#define AR_D_RETRY_LIMIT_RESV0 0xFFF00000 - -#define AR_D0_CHNTIME 0x10c0 -#define AR_D1_CHNTIME 0x10c4 -#define AR_D2_CHNTIME 0x10c8 -#define AR_D3_CHNTIME 0x10cc -#define AR_D4_CHNTIME 0x10d0 -#define AR_D5_CHNTIME 0x10d4 -#define AR_D6_CHNTIME 0x10d8 -#define AR_D7_CHNTIME 0x10dc -#define AR_D8_CHNTIME 0x10e0 -#define AR_D9_CHNTIME 0x10e4 -#define AR_DCHNTIME(_i) (AR_D0_CHNTIME + ((_i)<<2)) -#define AR_D_CHNTIME_DUR 0x000FFFFF -#define AR_D_CHNTIME_DUR_S 0 -#define AR_D_CHNTIME_EN 0x00100000 -#define AR_D_CHNTIME_RESV0 0xFFE00000 - -#define AR_D0_MISC 0x1100 -#define AR_D1_MISC 0x1104 -#define AR_D2_MISC 0x1108 -#define AR_D3_MISC 0x110c -#define AR_D4_MISC 0x1110 -#define AR_D5_MISC 0x1114 -#define AR_D6_MISC 0x1118 -#define AR_D7_MISC 0x111c -#define AR_D8_MISC 0x1120 -#define AR_D9_MISC 0x1124 -#define AR_DMISC(_i) (AR_D0_MISC + ((_i)<<2)) -#define AR_D_MISC_BKOFF_THRESH 0x0000003F -#define AR_D_MISC_RETRY_CNT_RESET_EN 0x00000040 -#define AR_D_MISC_CW_RESET_EN 0x00000080 -#define AR_D_MISC_FRAG_WAIT_EN 0x00000100 -#define AR_D_MISC_FRAG_BKOFF_EN 0x00000200 -#define AR_D_MISC_CW_BKOFF_EN 0x00001000 -#define AR_D_MISC_VIR_COL_HANDLING 0x0000C000 -#define AR_D_MISC_VIR_COL_HANDLING_S 14 -#define AR_D_MISC_VIR_COL_HANDLING_DEFAULT 0 -#define AR_D_MISC_VIR_COL_HANDLING_IGNORE 1 -#define AR_D_MISC_BEACON_USE 0x00010000 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL 0x00060000 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_S 17 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_NONE 0 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_INTRA_FR 1 -#define AR_D_MISC_ARB_LOCKOUT_CNTRL_GLOBAL 2 -#define AR_D_MISC_ARB_LOCKOUT_IGNORE 0x00080000 -#define AR_D_MISC_SEQ_NUM_INCR_DIS 0x00100000 -#define AR_D_MISC_POST_FR_BKOFF_DIS 0x00200000 -#define AR_D_MISC_VIT_COL_CW_BKOFF_EN 0x00400000 -#define AR_D_MISC_BLOWN_IFS_RETRY_EN 0x00800000 -#define AR_D_MISC_RESV0 0xFF000000 - -#define AR_D_SEQNUM 0x1140 - -#define AR_D_GBL_IFS_SIFS 0x1030 -#define AR_D_GBL_IFS_SIFS_M 0x0000FFFF -#define AR_D_GBL_IFS_SIFS_ASYNC_FIFO_DUR 0x000003AB -#define AR_D_GBL_IFS_SIFS_RESV0 0xFFFFFFFF - -#define AR_D_TXBLK_BASE 0x1038 -#define AR_D_TXBLK_WRITE_BITMASK 0x0000FFFF -#define AR_D_TXBLK_WRITE_BITMASK_S 0 -#define AR_D_TXBLK_WRITE_SLICE 0x000F0000 -#define AR_D_TXBLK_WRITE_SLICE_S 16 -#define AR_D_TXBLK_WRITE_DCU 0x00F00000 -#define AR_D_TXBLK_WRITE_DCU_S 20 -#define AR_D_TXBLK_WRITE_COMMAND 0x0F000000 -#define AR_D_TXBLK_WRITE_COMMAND_S 24 - -#define AR_D_GBL_IFS_SLOT 0x1070 -#define AR_D_GBL_IFS_SLOT_M 0x0000FFFF -#define AR_D_GBL_IFS_SLOT_RESV0 0xFFFF0000 -#define AR_D_GBL_IFS_SLOT_ASYNC_FIFO_DUR 0x00000420 - -#define AR_D_GBL_IFS_EIFS 0x10b0 -#define AR_D_GBL_IFS_EIFS_M 0x0000FFFF -#define AR_D_GBL_IFS_EIFS_RESV0 0xFFFF0000 -#define AR_D_GBL_IFS_EIFS_ASYNC_FIFO_DUR 0x0000A5EB - -#define AR_D_GBL_IFS_MISC 0x10f0 -#define AR_D_GBL_IFS_MISC_LFSR_SLICE_SEL 0x00000007 -#define AR_D_GBL_IFS_MISC_TURBO_MODE 0x00000008 -#define AR_D_GBL_IFS_MISC_USEC_DURATION 0x000FFC00 -#define AR_D_GBL_IFS_MISC_DCU_ARBITER_DLY 0x00300000 -#define AR_D_GBL_IFS_MISC_RANDOM_LFSR_SLICE_DIS 0x01000000 -#define AR_D_GBL_IFS_MISC_SLOT_XMIT_WIND_LEN 0x06000000 -#define AR_D_GBL_IFS_MISC_FORCE_XMIT_SLOT_BOUND 0x08000000 -#define AR_D_GBL_IFS_MISC_IGNORE_BACKOFF 0x10000000 - -#define AR_D_FPCTL 0x1230 -#define AR_D_FPCTL_DCU 0x0000000F -#define AR_D_FPCTL_DCU_S 0 -#define AR_D_FPCTL_PREFETCH_EN 0x00000010 -#define AR_D_FPCTL_BURST_PREFETCH 0x00007FE0 -#define AR_D_FPCTL_BURST_PREFETCH_S 5 - -#define AR_D_TXPSE 0x1270 -#define AR_D_TXPSE_CTRL 0x000003FF -#define AR_D_TXPSE_RESV0 0x0000FC00 -#define AR_D_TXPSE_STATUS 0x00010000 -#define AR_D_TXPSE_RESV1 0xFFFE0000 - -#define AR_D_TXSLOTMASK 0x12f0 -#define AR_D_TXSLOTMASK_NUM 0x0000000F - -#define AR_CFG_LED 0x1f04 -#define AR_CFG_SCLK_RATE_IND 0x00000003 -#define AR_CFG_SCLK_RATE_IND_S 0 -#define AR_CFG_SCLK_32MHZ 0x00000000 -#define AR_CFG_SCLK_4MHZ 0x00000001 -#define AR_CFG_SCLK_1MHZ 0x00000002 -#define AR_CFG_SCLK_32KHZ 0x00000003 -#define AR_CFG_LED_BLINK_SLOW 0x00000008 -#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 -#define AR_CFG_LED_MODE_SEL 0x00000380 -#define AR_CFG_LED_MODE_SEL_S 7 -#define AR_CFG_LED_POWER 0x00000280 -#define AR_CFG_LED_POWER_S 7 -#define AR_CFG_LED_NETWORK 0x00000300 -#define AR_CFG_LED_NETWORK_S 7 -#define AR_CFG_LED_MODE_PROP 0x0 -#define AR_CFG_LED_MODE_RPROP 0x1 -#define AR_CFG_LED_MODE_SPLIT 0x2 -#define AR_CFG_LED_MODE_RAND 0x3 -#define AR_CFG_LED_MODE_POWER_OFF 0x4 -#define AR_CFG_LED_MODE_POWER_ON 0x5 -#define AR_CFG_LED_MODE_NETWORK_OFF 0x4 -#define AR_CFG_LED_MODE_NETWORK_ON 0x6 -#define AR_CFG_LED_ASSOC_CTL 0x00000c00 -#define AR_CFG_LED_ASSOC_CTL_S 10 -#define AR_CFG_LED_ASSOC_NONE 0x0 -#define AR_CFG_LED_ASSOC_ACTIVE 0x1 -#define AR_CFG_LED_ASSOC_PENDING 0x2 - -#define AR_CFG_LED_BLINK_SLOW 0x00000008 -#define AR_CFG_LED_BLINK_SLOW_S 3 - -#define AR_CFG_LED_BLINK_THRESH_SEL 0x00000070 -#define AR_CFG_LED_BLINK_THRESH_SEL_S 4 - -#define AR_MAC_SLEEP 0x1f00 -#define AR_MAC_SLEEP_MAC_AWAKE 0x00000000 -#define AR_MAC_SLEEP_MAC_ASLEEP 0x00000001 - -#define AR_RC 0x4000 -#define AR_RC_AHB 0x00000001 -#define AR_RC_APB 0x00000002 -#define AR_RC_HOSTIF 0x00000100 - -#define AR_WA 0x4004 -#define AR_WA_D3_L1_DISABLE (1 << 14) -#define AR9285_WA_DEFAULT 0x004a05cb -#define AR9280_WA_DEFAULT 0x0040073b -#define AR_WA_DEFAULT 0x0000073f - - -#define AR_PM_STATE 0x4008 -#define AR_PM_STATE_PME_D3COLD_VAUX 0x00100000 - -#define AR_HOST_TIMEOUT 0x4018 -#define AR_HOST_TIMEOUT_APB_CNTR 0x0000FFFF -#define AR_HOST_TIMEOUT_APB_CNTR_S 0 -#define AR_HOST_TIMEOUT_LCL_CNTR 0xFFFF0000 -#define AR_HOST_TIMEOUT_LCL_CNTR_S 16 - -#define AR_EEPROM 0x401c -#define AR_EEPROM_ABSENT 0x00000100 -#define AR_EEPROM_CORRUPT 0x00000200 -#define AR_EEPROM_PROT_MASK 0x03FFFC00 -#define AR_EEPROM_PROT_MASK_S 10 - -#define EEPROM_PROTECT_RP_0_31 0x0001 -#define EEPROM_PROTECT_WP_0_31 0x0002 -#define EEPROM_PROTECT_RP_32_63 0x0004 -#define EEPROM_PROTECT_WP_32_63 0x0008 -#define EEPROM_PROTECT_RP_64_127 0x0010 -#define EEPROM_PROTECT_WP_64_127 0x0020 -#define EEPROM_PROTECT_RP_128_191 0x0040 -#define EEPROM_PROTECT_WP_128_191 0x0080 -#define EEPROM_PROTECT_RP_192_255 0x0100 -#define EEPROM_PROTECT_WP_192_255 0x0200 -#define EEPROM_PROTECT_RP_256_511 0x0400 -#define EEPROM_PROTECT_WP_256_511 0x0800 -#define EEPROM_PROTECT_RP_512_1023 0x1000 -#define EEPROM_PROTECT_WP_512_1023 0x2000 -#define EEPROM_PROTECT_RP_1024_2047 0x4000 -#define EEPROM_PROTECT_WP_1024_2047 0x8000 - -#define AR_SREV \ - ((AR_SREV_9100(ah)) ? 0x0600 : 0x4020) - -#define AR_SREV_ID \ - ((AR_SREV_9100(ah)) ? 0x00000FFF : 0x000000FF) -#define AR_SREV_VERSION 0x000000F0 -#define AR_SREV_VERSION_S 4 -#define AR_SREV_REVISION 0x00000007 - -#define AR_SREV_ID2 0xFFFFFFFF -#define AR_SREV_VERSION2 0xFFFC0000 -#define AR_SREV_VERSION2_S 18 -#define AR_SREV_TYPE2 0x0003F000 -#define AR_SREV_TYPE2_S 12 -#define AR_SREV_TYPE2_CHAIN 0x00001000 -#define AR_SREV_TYPE2_HOST_MODE 0x00002000 -#define AR_SREV_REVISION2 0x00000F00 -#define AR_SREV_REVISION2_S 8 - -#define AR_SREV_VERSION_5416_PCI 0xD -#define AR_SREV_VERSION_5416_PCIE 0xC -#define AR_SREV_REVISION_5416_10 0 -#define AR_SREV_REVISION_5416_20 1 -#define AR_SREV_REVISION_5416_22 2 -#define AR_SREV_VERSION_9100 0x14 -#define AR_SREV_VERSION_9160 0x40 -#define AR_SREV_REVISION_9160_10 0 -#define AR_SREV_REVISION_9160_11 1 -#define AR_SREV_VERSION_9280 0x80 -#define AR_SREV_REVISION_9280_10 0 -#define AR_SREV_REVISION_9280_20 1 -#define AR_SREV_REVISION_9280_21 2 -#define AR_SREV_VERSION_9285 0xC0 -#define AR_SREV_REVISION_9285_10 0 -#define AR_SREV_REVISION_9285_11 1 -#define AR_SREV_REVISION_9285_12 2 -#define AR_SREV_VERSION_9287 0x180 -#define AR_SREV_REVISION_9287_10 0 -#define AR_SREV_REVISION_9287_11 1 -#define AR_SREV_REVISION_9287_12 2 -#define AR_SREV_VERSION_9271 0x140 -#define AR_SREV_REVISION_9271_10 0 -#define AR_SREV_REVISION_9271_11 1 - -#define AR_SREV_5416(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \ - ((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCIE)) -#define AR_SREV_5416_20_OR_LATER(_ah) \ - (((AR_SREV_5416(_ah)) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_20)) || \ - ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) -#define AR_SREV_5416_22_OR_LATER(_ah) \ - (((AR_SREV_5416(_ah)) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_5416_22)) || \ - ((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) - -#define AR_SREV_9100(ah) \ - ((ah->hw_version.macVersion) == AR_SREV_VERSION_9100) -#define AR_SREV_9100_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9100)) - -#define AR_SREV_9160(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9160)) -#define AR_SREV_9160_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9160)) -#define AR_SREV_9160_11(_ah) \ - (AR_SREV_9160(_ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9160_11)) -#define AR_SREV_9280(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280)) -#define AR_SREV_9280_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9280)) -#define AR_SREV_9280_20(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20)) -#define AR_SREV_9280_20_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9280) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9280) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9280_20))) - -#define AR_SREV_9285(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9285)) -#define AR_SREV_9285_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9285)) -#define AR_SREV_9285_11(_ah) \ - (AR_SREV_9285(ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_11)) -#define AR_SREV_9285_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ - (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ - AR_SREV_REVISION_9285_11))) -#define AR_SREV_9285_12(_ah) \ - (AR_SREV_9285(ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9285_12)) -#define AR_SREV_9285_12_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9285) || \ - (AR_SREV_9285(ah) && ((_ah)->hw_version.macRev >= \ - AR_SREV_REVISION_9285_12))) - -#define AR_SREV_9287(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287)) -#define AR_SREV_9287_10_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9287)) -#define AR_SREV_9287_10(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_10)) -#define AR_SREV_9287_11(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_11)) -#define AR_SREV_9287_11_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_11))) -#define AR_SREV_9287_12(_ah) \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9287_12)) -#define AR_SREV_9287_12_OR_LATER(_ah) \ - (((_ah)->hw_version.macVersion > AR_SREV_VERSION_9287) || \ - (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9287) && \ - ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9287_12))) -#define AR_SREV_9271(_ah) \ - (((_ah))->hw_version.macVersion == AR_SREV_VERSION_9271) -#define AR_SREV_9271_10(_ah) \ - (AR_SREV_9271(_ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_10)) -#define AR_SREV_9271_11(_ah) \ - (AR_SREV_9271(_ah) && \ - ((_ah)->hw_version.macRev == AR_SREV_REVISION_9271_11)) - -#define AR_RADIO_SREV_MAJOR 0xf0 -#define AR_RAD5133_SREV_MAJOR 0xc0 -#define AR_RAD2133_SREV_MAJOR 0xd0 -#define AR_RAD5122_SREV_MAJOR 0xe0 -#define AR_RAD2122_SREV_MAJOR 0xf0 - -#define AR_AHB_MODE 0x4024 -#define AR_AHB_EXACT_WR_EN 0x00000000 -#define AR_AHB_BUF_WR_EN 0x00000001 -#define AR_AHB_EXACT_RD_EN 0x00000000 -#define AR_AHB_CACHELINE_RD_EN 0x00000002 -#define AR_AHB_PREFETCH_RD_EN 0x00000004 -#define AR_AHB_PAGE_SIZE_1K 0x00000000 -#define AR_AHB_PAGE_SIZE_2K 0x00000008 -#define AR_AHB_PAGE_SIZE_4K 0x00000010 -#define AR_AHB_CUSTOM_BURST_EN 0x000000C0 -#define AR_AHB_CUSTOM_BURST_EN_S 6 -#define AR_AHB_CUSTOM_BURST_ASYNC_FIFO_VAL 3 - -#define AR_INTR_RTC_IRQ 0x00000001 -#define AR_INTR_MAC_IRQ 0x00000002 -#define AR_INTR_EEP_PROT_ACCESS 0x00000004 -#define AR_INTR_MAC_AWAKE 0x00020000 -#define AR_INTR_MAC_ASLEEP 0x00040000 -#define AR_INTR_SPURIOUS 0xFFFFFFFF - - -#define AR_INTR_SYNC_CAUSE_CLR 0x4028 - -#define AR_INTR_SYNC_CAUSE 0x4028 - -#define AR_INTR_SYNC_ENABLE 0x402c -#define AR_INTR_SYNC_ENABLE_GPIO 0xFFFC0000 -#define AR_INTR_SYNC_ENABLE_GPIO_S 18 - -enum { - AR_INTR_SYNC_RTC_IRQ = 0x00000001, - AR_INTR_SYNC_MAC_IRQ = 0x00000002, - AR_INTR_SYNC_EEPROM_ILLEGAL_ACCESS = 0x00000004, - AR_INTR_SYNC_APB_TIMEOUT = 0x00000008, - AR_INTR_SYNC_PCI_MODE_CONFLICT = 0x00000010, - AR_INTR_SYNC_HOST1_FATAL = 0x00000020, - AR_INTR_SYNC_HOST1_PERR = 0x00000040, - AR_INTR_SYNC_TRCV_FIFO_PERR = 0x00000080, - AR_INTR_SYNC_RADM_CPL_EP = 0x00000100, - AR_INTR_SYNC_RADM_CPL_DLLP_ABORT = 0x00000200, - AR_INTR_SYNC_RADM_CPL_TLP_ABORT = 0x00000400, - AR_INTR_SYNC_RADM_CPL_ECRC_ERR = 0x00000800, - AR_INTR_SYNC_RADM_CPL_TIMEOUT = 0x00001000, - AR_INTR_SYNC_LOCAL_TIMEOUT = 0x00002000, - AR_INTR_SYNC_PM_ACCESS = 0x00004000, - AR_INTR_SYNC_MAC_AWAKE = 0x00008000, - AR_INTR_SYNC_MAC_ASLEEP = 0x00010000, - AR_INTR_SYNC_MAC_SLEEP_ACCESS = 0x00020000, - AR_INTR_SYNC_ALL = 0x0003FFFF, - - - AR_INTR_SYNC_DEFAULT = (AR_INTR_SYNC_HOST1_FATAL | - AR_INTR_SYNC_HOST1_PERR | - AR_INTR_SYNC_RADM_CPL_EP | - AR_INTR_SYNC_RADM_CPL_DLLP_ABORT | - AR_INTR_SYNC_RADM_CPL_TLP_ABORT | - AR_INTR_SYNC_RADM_CPL_ECRC_ERR | - AR_INTR_SYNC_RADM_CPL_TIMEOUT | - AR_INTR_SYNC_LOCAL_TIMEOUT | - AR_INTR_SYNC_MAC_SLEEP_ACCESS), - - AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, - -}; - -#define AR_INTR_ASYNC_MASK 0x4030 -#define AR_INTR_ASYNC_MASK_GPIO 0xFFFC0000 -#define AR_INTR_ASYNC_MASK_GPIO_S 18 - -#define AR_INTR_SYNC_MASK 0x4034 -#define AR_INTR_SYNC_MASK_GPIO 0xFFFC0000 -#define AR_INTR_SYNC_MASK_GPIO_S 18 - -#define AR_INTR_ASYNC_CAUSE_CLR 0x4038 -#define AR_INTR_ASYNC_CAUSE 0x4038 - -#define AR_INTR_ASYNC_ENABLE 0x403c -#define AR_INTR_ASYNC_ENABLE_GPIO 0xFFFC0000 -#define AR_INTR_ASYNC_ENABLE_GPIO_S 18 - -#define AR_PCIE_SERDES 0x4040 -#define AR_PCIE_SERDES2 0x4044 -#define AR_PCIE_PM_CTRL 0x4014 -#define AR_PCIE_PM_CTRL_ENA 0x00080000 - -#define AR_NUM_GPIO 14 -#define AR928X_NUM_GPIO 10 -#define AR9285_NUM_GPIO 12 -#define AR9287_NUM_GPIO 11 - -#define AR_GPIO_IN_OUT 0x4048 -#define AR_GPIO_IN_VAL 0x0FFFC000 -#define AR_GPIO_IN_VAL_S 14 -#define AR928X_GPIO_IN_VAL 0x000FFC00 -#define AR928X_GPIO_IN_VAL_S 10 -#define AR9285_GPIO_IN_VAL 0x00FFF000 -#define AR9285_GPIO_IN_VAL_S 12 -#define AR9287_GPIO_IN_VAL 0x003FF800 -#define AR9287_GPIO_IN_VAL_S 11 - -#define AR_GPIO_OE_OUT 0x404c -#define AR_GPIO_OE_OUT_DRV 0x3 -#define AR_GPIO_OE_OUT_DRV_NO 0x0 -#define AR_GPIO_OE_OUT_DRV_LOW 0x1 -#define AR_GPIO_OE_OUT_DRV_HI 0x2 -#define AR_GPIO_OE_OUT_DRV_ALL 0x3 - -#define AR_GPIO_INTR_POL 0x4050 -#define AR_GPIO_INTR_POL_VAL 0x00001FFF -#define AR_GPIO_INTR_POL_VAL_S 0 - -#define AR_GPIO_INPUT_EN_VAL 0x4054 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF 0x00000004 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_S 2 -#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_DEF 0x00000008 -#define AR_GPIO_INPUT_EN_VAL_BT_FREQUENCY_S 3 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_DEF 0x00000010 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_S 4 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF 0x00000080 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_DEF_S 7 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB 0x00000400 -#define AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB_S 10 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB 0x00001000 -#define AR_GPIO_INPUT_EN_VAL_BT_ACTIVE_BB_S 12 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB 0x00008000 -#define AR_GPIO_INPUT_EN_VAL_RFSILENT_BB_S 15 -#define AR_GPIO_RTC_RESET_OVERRIDE_ENABLE 0x00010000 -#define AR_GPIO_JTAG_DISABLE 0x00020000 - -#define AR_GPIO_INPUT_MUX1 0x4058 -#define AR_GPIO_INPUT_MUX1_BT_ACTIVE 0x000f0000 -#define AR_GPIO_INPUT_MUX1_BT_ACTIVE_S 16 -#define AR_GPIO_INPUT_MUX1_BT_PRIORITY 0x00000f00 -#define AR_GPIO_INPUT_MUX1_BT_PRIORITY_S 8 - -#define AR_GPIO_INPUT_MUX2 0x405c -#define AR_GPIO_INPUT_MUX2_CLK25 0x0000000f -#define AR_GPIO_INPUT_MUX2_CLK25_S 0 -#define AR_GPIO_INPUT_MUX2_RFSILENT 0x000000f0 -#define AR_GPIO_INPUT_MUX2_RFSILENT_S 4 -#define AR_GPIO_INPUT_MUX2_RTC_RESET 0x00000f00 -#define AR_GPIO_INPUT_MUX2_RTC_RESET_S 8 - -#define AR_GPIO_OUTPUT_MUX1 0x4060 -#define AR_GPIO_OUTPUT_MUX2 0x4064 -#define AR_GPIO_OUTPUT_MUX3 0x4068 - -#define AR_INPUT_STATE 0x406c - -#define AR_EEPROM_STATUS_DATA 0x407c -#define AR_EEPROM_STATUS_DATA_VAL 0x0000ffff -#define AR_EEPROM_STATUS_DATA_VAL_S 0 -#define AR_EEPROM_STATUS_DATA_BUSY 0x00010000 -#define AR_EEPROM_STATUS_DATA_BUSY_ACCESS 0x00020000 -#define AR_EEPROM_STATUS_DATA_PROT_ACCESS 0x00040000 -#define AR_EEPROM_STATUS_DATA_ABSENT_ACCESS 0x00080000 - -#define AR_OBS 0x4080 - -#define AR_GPIO_PDPU 0x4088 - -#define AR_PCIE_MSI 0x4094 -#define AR_PCIE_MSI_ENABLE 0x00000001 - - -#define AR_RTC_9160_PLL_DIV 0x000003ff -#define AR_RTC_9160_PLL_DIV_S 0 -#define AR_RTC_9160_PLL_REFDIV 0x00003C00 -#define AR_RTC_9160_PLL_REFDIV_S 10 -#define AR_RTC_9160_PLL_CLKSEL 0x0000C000 -#define AR_RTC_9160_PLL_CLKSEL_S 14 - -#define AR_RTC_BASE 0x00020000 -#define AR_RTC_RC \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0000) : 0x7000) -#define AR_RTC_RC_M 0x00000003 -#define AR_RTC_RC_MAC_WARM 0x00000001 -#define AR_RTC_RC_MAC_COLD 0x00000002 -#define AR_RTC_RC_COLD_RESET 0x00000004 -#define AR_RTC_RC_WARM_RESET 0x00000008 - -#define AR_RTC_PLL_CONTROL \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0014) : 0x7014) - -#define AR_RTC_PLL_DIV 0x0000001f -#define AR_RTC_PLL_DIV_S 0 -#define AR_RTC_PLL_DIV2 0x00000020 -#define AR_RTC_PLL_REFDIV_5 0x000000c0 -#define AR_RTC_PLL_CLKSEL 0x00000300 -#define AR_RTC_PLL_CLKSEL_S 8 - -#define AR_RTC_RESET \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040) -#define AR_RTC_RESET_EN (0x00000001) - -#define AR_RTC_STATUS \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0044) : 0x7044) - -#define AR_RTC_STATUS_M \ - ((AR_SREV_9100(ah)) ? 0x0000003f : 0x0000000f) - -#define AR_RTC_PM_STATUS_M 0x0000000f - -#define AR_RTC_STATUS_SHUTDOWN 0x00000001 -#define AR_RTC_STATUS_ON 0x00000002 -#define AR_RTC_STATUS_SLEEP 0x00000004 -#define AR_RTC_STATUS_WAKEUP 0x00000008 - -#define AR_RTC_SLEEP_CLK \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0048) : 0x7048) -#define AR_RTC_FORCE_DERIVED_CLK 0x2 - -#define AR_RTC_FORCE_WAKE \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x004c) : 0x704c) -#define AR_RTC_FORCE_WAKE_EN 0x00000001 -#define AR_RTC_FORCE_WAKE_ON_INT 0x00000002 - - -#define AR_RTC_INTR_CAUSE \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0050) : 0x7050) - -#define AR_RTC_INTR_ENABLE \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0054) : 0x7054) - -#define AR_RTC_INTR_MASK \ - ((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0058) : 0x7058) - -/* RTC_DERIVED_* - only for AR9100 */ - -#define AR_RTC_DERIVED_CLK (AR_RTC_BASE + 0x0038) -#define AR_RTC_DERIVED_CLK_PERIOD 0x0000fffe -#define AR_RTC_DERIVED_CLK_PERIOD_S 1 - -#define AR_SEQ_MASK 0x8060 - -#define AR_AN_RF2G1_CH0 0x7810 -#define AR_AN_RF2G1_CH0_OB 0x03800000 -#define AR_AN_RF2G1_CH0_OB_S 23 -#define AR_AN_RF2G1_CH0_DB 0x1C000000 -#define AR_AN_RF2G1_CH0_DB_S 26 - -#define AR_AN_RF5G1_CH0 0x7818 -#define AR_AN_RF5G1_CH0_OB5 0x00070000 -#define AR_AN_RF5G1_CH0_OB5_S 16 -#define AR_AN_RF5G1_CH0_DB5 0x00380000 -#define AR_AN_RF5G1_CH0_DB5_S 19 - -#define AR_AN_RF2G1_CH1 0x7834 -#define AR_AN_RF2G1_CH1_OB 0x03800000 -#define AR_AN_RF2G1_CH1_OB_S 23 -#define AR_AN_RF2G1_CH1_DB 0x1C000000 -#define AR_AN_RF2G1_CH1_DB_S 26 - -#define AR_AN_RF5G1_CH1 0x783C -#define AR_AN_RF5G1_CH1_OB5 0x00070000 -#define AR_AN_RF5G1_CH1_OB5_S 16 -#define AR_AN_RF5G1_CH1_DB5 0x00380000 -#define AR_AN_RF5G1_CH1_DB5_S 19 - -#define AR_AN_TOP1 0x7890 -#define AR_AN_TOP1_DACIPMODE 0x00040000 -#define AR_AN_TOP1_DACIPMODE_S 18 - -#define AR_AN_TOP2 0x7894 -#define AR_AN_TOP2_XPABIAS_LVL 0xC0000000 -#define AR_AN_TOP2_XPABIAS_LVL_S 30 -#define AR_AN_TOP2_LOCALBIAS 0x00200000 -#define AR_AN_TOP2_LOCALBIAS_S 21 -#define AR_AN_TOP2_PWDCLKIND 0x00400000 -#define AR_AN_TOP2_PWDCLKIND_S 22 - -#define AR_AN_SYNTH9 0x7868 -#define AR_AN_SYNTH9_REFDIVA 0xf8000000 -#define AR_AN_SYNTH9_REFDIVA_S 27 - -#define AR9285_AN_RF2G1 0x7820 -#define AR9285_AN_RF2G1_ENPACAL 0x00000800 -#define AR9285_AN_RF2G1_ENPACAL_S 11 -#define AR9285_AN_RF2G1_PDPADRV1 0x02000000 -#define AR9285_AN_RF2G1_PDPADRV1_S 25 -#define AR9285_AN_RF2G1_PDPADRV2 0x01000000 -#define AR9285_AN_RF2G1_PDPADRV2_S 24 -#define AR9285_AN_RF2G1_PDPAOUT 0x00800000 -#define AR9285_AN_RF2G1_PDPAOUT_S 23 - - -#define AR9285_AN_RF2G2 0x7824 -#define AR9285_AN_RF2G2_OFFCAL 0x00001000 -#define AR9285_AN_RF2G2_OFFCAL_S 12 - -#define AR9285_AN_RF2G3 0x7828 -#define AR9285_AN_RF2G3_PDVCCOMP 0x02000000 -#define AR9285_AN_RF2G3_PDVCCOMP_S 25 -#define AR9285_AN_RF2G3_OB_0 0x00E00000 -#define AR9285_AN_RF2G3_OB_0_S 21 -#define AR9285_AN_RF2G3_OB_1 0x001C0000 -#define AR9285_AN_RF2G3_OB_1_S 18 -#define AR9285_AN_RF2G3_OB_2 0x00038000 -#define AR9285_AN_RF2G3_OB_2_S 15 -#define AR9285_AN_RF2G3_OB_3 0x00007000 -#define AR9285_AN_RF2G3_OB_3_S 12 -#define AR9285_AN_RF2G3_OB_4 0x00000E00 -#define AR9285_AN_RF2G3_OB_4_S 9 - -#define AR9285_AN_RF2G3_DB1_0 0x000001C0 -#define AR9285_AN_RF2G3_DB1_0_S 6 -#define AR9285_AN_RF2G3_DB1_1 0x00000038 -#define AR9285_AN_RF2G3_DB1_1_S 3 -#define AR9285_AN_RF2G3_DB1_2 0x00000007 -#define AR9285_AN_RF2G3_DB1_2_S 0 -#define AR9285_AN_RF2G4 0x782C -#define AR9285_AN_RF2G4_DB1_3 0xE0000000 -#define AR9285_AN_RF2G4_DB1_3_S 29 -#define AR9285_AN_RF2G4_DB1_4 0x1C000000 -#define AR9285_AN_RF2G4_DB1_4_S 26 - -#define AR9285_AN_RF2G4_DB2_0 0x03800000 -#define AR9285_AN_RF2G4_DB2_0_S 23 -#define AR9285_AN_RF2G4_DB2_1 0x00700000 -#define AR9285_AN_RF2G4_DB2_1_S 20 -#define AR9285_AN_RF2G4_DB2_2 0x000E0000 -#define AR9285_AN_RF2G4_DB2_2_S 17 -#define AR9285_AN_RF2G4_DB2_3 0x0001C000 -#define AR9285_AN_RF2G4_DB2_3_S 14 -#define AR9285_AN_RF2G4_DB2_4 0x00003800 -#define AR9285_AN_RF2G4_DB2_4_S 11 - -/* AR9271 : 0x7828, 0x782c different setting from AR9285 */ -#define AR9271_AN_RF2G3_OB_cck 0x001C0000 -#define AR9271_AN_RF2G3_OB_cck_S 18 -#define AR9271_AN_RF2G3_OB_psk 0x00038000 -#define AR9271_AN_RF2G3_OB_psk_S 15 -#define AR9271_AN_RF2G3_OB_qam 0x00007000 -#define AR9271_AN_RF2G3_OB_qam_S 12 - -#define AR9271_AN_RF2G3_DB_1 0x00E00000 -#define AR9271_AN_RF2G3_DB_1_S 21 - -#define AR9271_AN_RF2G3_CCOMP 0xFFF -#define AR9271_AN_RF2G3_CCOMP_S 0 - -#define AR9271_AN_RF2G4_DB_2 0xE0000000 -#define AR9271_AN_RF2G4_DB_2_S 29 - -#define AR9285_AN_RF2G6 0x7834 -#define AR9285_AN_RF2G6_CCOMP 0x00007800 -#define AR9285_AN_RF2G6_CCOMP_S 11 -#define AR9285_AN_RF2G6_OFFS 0x03f00000 -#define AR9285_AN_RF2G6_OFFS_S 20 - -#define AR9271_AN_RF2G6_OFFS 0x07f00000 -#define AR9271_AN_RF2G6_OFFS_S 20 - -#define AR9285_AN_RF2G7 0x7838 -#define AR9285_AN_RF2G7_PWDDB 0x00000002 -#define AR9285_AN_RF2G7_PWDDB_S 1 -#define AR9285_AN_RF2G7_PADRVGN2TAB0 0xE0000000 -#define AR9285_AN_RF2G7_PADRVGN2TAB0_S 29 - -#define AR9285_AN_RF2G8 0x783C -#define AR9285_AN_RF2G8_PADRVGN2TAB0 0x0001C000 -#define AR9285_AN_RF2G8_PADRVGN2TAB0_S 14 - - -#define AR9285_AN_RF2G9 0x7840 -#define AR9285_AN_RXTXBB1 0x7854 -#define AR9285_AN_RXTXBB1_PDRXTXBB1 0x00000020 -#define AR9285_AN_RXTXBB1_PDRXTXBB1_S 5 -#define AR9285_AN_RXTXBB1_PDV2I 0x00000080 -#define AR9285_AN_RXTXBB1_PDV2I_S 7 -#define AR9285_AN_RXTXBB1_PDDACIF 0x00000100 -#define AR9285_AN_RXTXBB1_PDDACIF_S 8 -#define AR9285_AN_RXTXBB1_SPARE9 0x00000001 -#define AR9285_AN_RXTXBB1_SPARE9_S 0 - -#define AR9285_AN_TOP2 0x7868 - -#define AR9285_AN_TOP3 0x786c -#define AR9285_AN_TOP3_XPABIAS_LVL 0x0000000C -#define AR9285_AN_TOP3_XPABIAS_LVL_S 2 -#define AR9285_AN_TOP3_PWDDAC 0x00800000 -#define AR9285_AN_TOP3_PWDDAC_S 23 - -#define AR9285_AN_TOP4 0x7870 -#define AR9285_AN_TOP4_DEFAULT 0x10142c00 - -#define AR9287_AN_RF2G3_CH0 0x7808 -#define AR9287_AN_RF2G3_CH1 0x785c -#define AR9287_AN_RF2G3_DB1 0xE0000000 -#define AR9287_AN_RF2G3_DB1_S 29 -#define AR9287_AN_RF2G3_DB2 0x1C000000 -#define AR9287_AN_RF2G3_DB2_S 26 -#define AR9287_AN_RF2G3_OB_CCK 0x03800000 -#define AR9287_AN_RF2G3_OB_CCK_S 23 -#define AR9287_AN_RF2G3_OB_PSK 0x00700000 -#define AR9287_AN_RF2G3_OB_PSK_S 20 -#define AR9287_AN_RF2G3_OB_QAM 0x000E0000 -#define AR9287_AN_RF2G3_OB_QAM_S 17 -#define AR9287_AN_RF2G3_OB_PAL_OFF 0x0001C000 -#define AR9287_AN_RF2G3_OB_PAL_OFF_S 14 - -#define AR9287_AN_TXPC0 0x7898 -#define AR9287_AN_TXPC0_TXPCMODE 0x0000C000 -#define AR9287_AN_TXPC0_TXPCMODE_S 14 -#define AR9287_AN_TXPC0_TXPCMODE_NORMAL 0 -#define AR9287_AN_TXPC0_TXPCMODE_TEST 1 -#define AR9287_AN_TXPC0_TXPCMODE_TEMPSENSE 2 -#define AR9287_AN_TXPC0_TXPCMODE_ATBTEST 3 - -#define AR9287_AN_TOP2 0x78b4 -#define AR9287_AN_TOP2_XPABIAS_LVL 0xC0000000 -#define AR9287_AN_TOP2_XPABIAS_LVL_S 30 - -/* AR9271 specific stuff */ -#define AR9271_RESET_POWER_DOWN_CONTROL 0x50044 -#define AR9271_RADIO_RF_RST 0x20 -#define AR9271_GATE_MAC_CTL 0x4000 - -#define AR_STA_ID0 0x8000 -#define AR_STA_ID1 0x8004 -#define AR_STA_ID1_SADH_MASK 0x0000FFFF -#define AR_STA_ID1_STA_AP 0x00010000 -#define AR_STA_ID1_ADHOC 0x00020000 -#define AR_STA_ID1_PWR_SAV 0x00040000 -#define AR_STA_ID1_KSRCHDIS 0x00080000 -#define AR_STA_ID1_PCF 0x00100000 -#define AR_STA_ID1_USE_DEFANT 0x00200000 -#define AR_STA_ID1_DEFANT_UPDATE 0x00400000 -#define AR_STA_ID1_RTS_USE_DEF 0x00800000 -#define AR_STA_ID1_ACKCTS_6MB 0x01000000 -#define AR_STA_ID1_BASE_RATE_11B 0x02000000 -#define AR_STA_ID1_SECTOR_SELF_GEN 0x04000000 -#define AR_STA_ID1_CRPT_MIC_ENABLE 0x08000000 -#define AR_STA_ID1_KSRCH_MODE 0x10000000 -#define AR_STA_ID1_PRESERVE_SEQNUM 0x20000000 -#define AR_STA_ID1_CBCIV_ENDIAN 0x40000000 -#define AR_STA_ID1_MCAST_KSRCH 0x80000000 - -#define AR_BSS_ID0 0x8008 -#define AR_BSS_ID1 0x800C -#define AR_BSS_ID1_U16 0x0000FFFF -#define AR_BSS_ID1_AID 0x07FF0000 -#define AR_BSS_ID1_AID_S 16 - -#define AR_BCN_RSSI_AVE 0x8010 -#define AR_BCN_RSSI_AVE_MASK 0x00000FFF - -#define AR_TIME_OUT 0x8014 -#define AR_TIME_OUT_ACK 0x00003FFF -#define AR_TIME_OUT_ACK_S 0 -#define AR_TIME_OUT_CTS 0x3FFF0000 -#define AR_TIME_OUT_CTS_S 16 -#define AR_TIME_OUT_ACK_CTS_ASYNC_FIFO_DUR 0x16001D56 - -#define AR_RSSI_THR 0x8018 -#define AR_RSSI_THR_MASK 0x000000FF -#define AR_RSSI_THR_BM_THR 0x0000FF00 -#define AR_RSSI_THR_BM_THR_S 8 -#define AR_RSSI_BCN_WEIGHT 0x1F000000 -#define AR_RSSI_BCN_WEIGHT_S 24 -#define AR_RSSI_BCN_RSSI_RST 0x20000000 - -#define AR_USEC 0x801c -#define AR_USEC_USEC 0x0000007F -#define AR_USEC_TX_LAT 0x007FC000 -#define AR_USEC_TX_LAT_S 14 -#define AR_USEC_RX_LAT 0x1F800000 -#define AR_USEC_RX_LAT_S 23 -#define AR_USEC_ASYNC_FIFO_DUR 0x12e00074 - -#define AR_RESET_TSF 0x8020 -#define AR_RESET_TSF_ONCE 0x01000000 - -#define AR_MAX_CFP_DUR 0x8038 -#define AR_CFP_VAL 0x0000FFFF - -#define AR_RX_FILTER 0x803C - -#define AR_MCAST_FIL0 0x8040 -#define AR_MCAST_FIL1 0x8044 - -#define AR_DIAG_SW 0x8048 -#define AR_DIAG_CACHE_ACK 0x00000001 -#define AR_DIAG_ACK_DIS 0x00000002 -#define AR_DIAG_CTS_DIS 0x00000004 -#define AR_DIAG_ENCRYPT_DIS 0x00000008 -#define AR_DIAG_DECRYPT_DIS 0x00000010 -#define AR_DIAG_RX_DIS 0x00000020 -#define AR_DIAG_LOOP_BACK 0x00000040 -#define AR_DIAG_CORR_FCS 0x00000080 -#define AR_DIAG_CHAN_INFO 0x00000100 -#define AR_DIAG_SCRAM_SEED 0x0001FE00 -#define AR_DIAG_SCRAM_SEED_S 8 -#define AR_DIAG_FRAME_NV0 0x00020000 -#define AR_DIAG_OBS_PT_SEL1 0x000C0000 -#define AR_DIAG_OBS_PT_SEL1_S 18 -#define AR_DIAG_FORCE_RX_CLEAR 0x00100000 -#define AR_DIAG_IGNORE_VIRT_CS 0x00200000 -#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 -#define AR_DIAG_EIFS_CTRL_ENA 0x00800000 -#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 -#define AR_DIAG_RX_ABORT 0x02000000 -#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000 -#define AR_DIAG_OBS_PT_SEL2 0x08000000 -#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000 -#define AR_DIAG_RX_CLEAR_EXT_LOW 0x20000000 - -#define AR_TSF_L32 0x804c -#define AR_TSF_U32 0x8050 - -#define AR_TST_ADDAC 0x8054 -#define AR_DEF_ANTENNA 0x8058 - -#define AR_AES_MUTE_MASK0 0x805c -#define AR_AES_MUTE_MASK0_FC 0x0000FFFF -#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 -#define AR_AES_MUTE_MASK0_QOS_S 16 - -#define AR_AES_MUTE_MASK1 0x8060 -#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF -#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 -#define AR_AES_MUTE_MASK1_FC_MGMT_S 16 - -#define AR_GATED_CLKS 0x8064 -#define AR_GATED_CLKS_TX 0x00000002 -#define AR_GATED_CLKS_RX 0x00000004 -#define AR_GATED_CLKS_REG 0x00000008 - -#define AR_OBS_BUS_CTRL 0x8068 -#define AR_OBS_BUS_SEL_1 0x00040000 -#define AR_OBS_BUS_SEL_2 0x00080000 -#define AR_OBS_BUS_SEL_3 0x000C0000 -#define AR_OBS_BUS_SEL_4 0x08040000 -#define AR_OBS_BUS_SEL_5 0x08080000 - -#define AR_OBS_BUS_1 0x806c -#define AR_OBS_BUS_1_PCU 0x00000001 -#define AR_OBS_BUS_1_RX_END 0x00000002 -#define AR_OBS_BUS_1_RX_WEP 0x00000004 -#define AR_OBS_BUS_1_RX_BEACON 0x00000008 -#define AR_OBS_BUS_1_RX_FILTER 0x00000010 -#define AR_OBS_BUS_1_TX_HCF 0x00000020 -#define AR_OBS_BUS_1_QUIET_TIME 0x00000040 -#define AR_OBS_BUS_1_CHAN_IDLE 0x00000080 -#define AR_OBS_BUS_1_TX_HOLD 0x00000100 -#define AR_OBS_BUS_1_TX_FRAME 0x00000200 -#define AR_OBS_BUS_1_RX_FRAME 0x00000400 -#define AR_OBS_BUS_1_RX_CLEAR 0x00000800 -#define AR_OBS_BUS_1_WEP_STATE 0x0003F000 -#define AR_OBS_BUS_1_WEP_STATE_S 12 -#define AR_OBS_BUS_1_RX_STATE 0x01F00000 -#define AR_OBS_BUS_1_RX_STATE_S 20 -#define AR_OBS_BUS_1_TX_STATE 0x7E000000 -#define AR_OBS_BUS_1_TX_STATE_S 25 - -#define AR_LAST_TSTP 0x8080 -#define AR_NAV 0x8084 -#define AR_RTS_OK 0x8088 -#define AR_RTS_FAIL 0x808c -#define AR_ACK_FAIL 0x8090 -#define AR_FCS_FAIL 0x8094 -#define AR_BEACON_CNT 0x8098 - -#define AR_SLEEP1 0x80d4 -#define AR_SLEEP1_ASSUME_DTIM 0x00080000 -#define AR_SLEEP1_CAB_TIMEOUT 0xFFE00000 -#define AR_SLEEP1_CAB_TIMEOUT_S 21 - -#define AR_SLEEP2 0x80d8 -#define AR_SLEEP2_BEACON_TIMEOUT 0xFFE00000 -#define AR_SLEEP2_BEACON_TIMEOUT_S 21 - -#define AR_BSSMSKL 0x80e0 -#define AR_BSSMSKU 0x80e4 - -#define AR_TPC 0x80e8 -#define AR_TPC_ACK 0x0000003f -#define AR_TPC_ACK_S 0x00 -#define AR_TPC_CTS 0x00003f00 -#define AR_TPC_CTS_S 0x08 -#define AR_TPC_CHIRP 0x003f0000 -#define AR_TPC_CHIRP_S 0x16 - -#define AR_TFCNT 0x80ec -#define AR_RFCNT 0x80f0 -#define AR_RCCNT 0x80f4 -#define AR_CCCNT 0x80f8 - -#define AR_QUIET1 0x80fc -#define AR_QUIET1_NEXT_QUIET_S 0 -#define AR_QUIET1_NEXT_QUIET_M 0x0000ffff -#define AR_QUIET1_QUIET_ENABLE 0x00010000 -#define AR_QUIET1_QUIET_ACK_CTS_ENABLE 0x00020000 -#define AR_QUIET1_QUIET_ACK_CTS_ENABLE_S 17 -#define AR_QUIET2 0x8100 -#define AR_QUIET2_QUIET_PERIOD_S 0 -#define AR_QUIET2_QUIET_PERIOD_M 0x0000ffff -#define AR_QUIET2_QUIET_DUR_S 16 -#define AR_QUIET2_QUIET_DUR 0xffff0000 - -#define AR_TSF_PARM 0x8104 -#define AR_TSF_INCREMENT_M 0x000000ff -#define AR_TSF_INCREMENT_S 0x00 - -#define AR_QOS_NO_ACK 0x8108 -#define AR_QOS_NO_ACK_TWO_BIT 0x0000000f -#define AR_QOS_NO_ACK_TWO_BIT_S 0 -#define AR_QOS_NO_ACK_BIT_OFF 0x00000070 -#define AR_QOS_NO_ACK_BIT_OFF_S 4 -#define AR_QOS_NO_ACK_BYTE_OFF 0x00000180 -#define AR_QOS_NO_ACK_BYTE_OFF_S 7 - -#define AR_PHY_ERR 0x810c - -#define AR_PHY_ERR_DCHIRP 0x00000008 -#define AR_PHY_ERR_RADAR 0x00000020 -#define AR_PHY_ERR_OFDM_TIMING 0x00020000 -#define AR_PHY_ERR_CCK_TIMING 0x02000000 - -#define AR_RXFIFO_CFG 0x8114 - - -#define AR_MIC_QOS_CONTROL 0x8118 -#define AR_MIC_QOS_SELECT 0x811c - -#define AR_PCU_MISC 0x8120 -#define AR_PCU_FORCE_BSSID_MATCH 0x00000001 -#define AR_PCU_MIC_NEW_LOC_ENA 0x00000004 -#define AR_PCU_TX_ADD_TSF 0x00000008 -#define AR_PCU_CCK_SIFS_MODE 0x00000010 -#define AR_PCU_RX_ANT_UPDT 0x00000800 -#define AR_PCU_TXOP_TBTT_LIMIT_ENA 0x00001000 -#define AR_PCU_MISS_BCN_IN_SLEEP 0x00004000 -#define AR_PCU_BUG_12306_FIX_ENA 0x00020000 -#define AR_PCU_FORCE_QUIET_COLL 0x00040000 -#define AR_PCU_TBTT_PROTECT 0x00200000 -#define AR_PCU_CLEAR_VMF 0x01000000 -#define AR_PCU_CLEAR_BA_VALID 0x04000000 - -#define AR_PCU_BT_ANT_PREVENT_RX 0x00100000 -#define AR_PCU_BT_ANT_PREVENT_RX_S 20 - -#define AR_FILT_OFDM 0x8124 -#define AR_FILT_OFDM_COUNT 0x00FFFFFF - -#define AR_FILT_CCK 0x8128 -#define AR_FILT_CCK_COUNT 0x00FFFFFF - -#define AR_PHY_ERR_1 0x812c -#define AR_PHY_ERR_1_COUNT 0x00FFFFFF -#define AR_PHY_ERR_MASK_1 0x8130 - -#define AR_PHY_ERR_2 0x8134 -#define AR_PHY_ERR_2_COUNT 0x00FFFFFF -#define AR_PHY_ERR_MASK_2 0x8138 - -#define AR_PHY_COUNTMAX (3 << 22) -#define AR_MIBCNT_INTRMASK (3 << 22) - -#define AR_TSFOOR_THRESHOLD 0x813c -#define AR_TSFOOR_THRESHOLD_VAL 0x0000FFFF - -#define AR_PHY_ERR_EIFS_MASK 8144 - -#define AR_PHY_ERR_3 0x8168 -#define AR_PHY_ERR_3_COUNT 0x00FFFFFF -#define AR_PHY_ERR_MASK_3 0x816c - -#define AR_BT_COEX_MODE 0x8170 -#define AR_BT_TIME_EXTEND 0x000000ff -#define AR_BT_TIME_EXTEND_S 0 -#define AR_BT_TXSTATE_EXTEND 0x00000100 -#define AR_BT_TXSTATE_EXTEND_S 8 -#define AR_BT_TX_FRAME_EXTEND 0x00000200 -#define AR_BT_TX_FRAME_EXTEND_S 9 -#define AR_BT_MODE 0x00000c00 -#define AR_BT_MODE_S 10 -#define AR_BT_QUIET 0x00001000 -#define AR_BT_QUIET_S 12 -#define AR_BT_QCU_THRESH 0x0001e000 -#define AR_BT_QCU_THRESH_S 13 -#define AR_BT_RX_CLEAR_POLARITY 0x00020000 -#define AR_BT_RX_CLEAR_POLARITY_S 17 -#define AR_BT_PRIORITY_TIME 0x00fc0000 -#define AR_BT_PRIORITY_TIME_S 18 -#define AR_BT_FIRST_SLOT_TIME 0xff000000 -#define AR_BT_FIRST_SLOT_TIME_S 24 - -#define AR_BT_COEX_WEIGHT 0x8174 -#define AR_BT_COEX_WGHT 0xff55 -#define AR_STOMP_ALL_WLAN_WGHT 0xffcc -#define AR_STOMP_LOW_WLAN_WGHT 0xaaa8 -#define AR_STOMP_NONE_WLAN_WGHT 0xaa00 -#define AR_BTCOEX_BT_WGHT 0x0000ffff -#define AR_BTCOEX_BT_WGHT_S 0 -#define AR_BTCOEX_WL_WGHT 0xffff0000 -#define AR_BTCOEX_WL_WGHT_S 16 - -#define AR_BT_COEX_MODE2 0x817c -#define AR_BT_BCN_MISS_THRESH 0x000000ff -#define AR_BT_BCN_MISS_THRESH_S 0 -#define AR_BT_BCN_MISS_CNT 0x0000ff00 -#define AR_BT_BCN_MISS_CNT_S 8 -#define AR_BT_HOLD_RX_CLEAR 0x00010000 -#define AR_BT_HOLD_RX_CLEAR_S 16 -#define AR_BT_DISABLE_BT_ANT 0x00100000 -#define AR_BT_DISABLE_BT_ANT_S 20 - -#define AR_TXSIFS 0x81d0 -#define AR_TXSIFS_TIME 0x000000FF -#define AR_TXSIFS_TX_LATENCY 0x00000F00 -#define AR_TXSIFS_TX_LATENCY_S 8 -#define AR_TXSIFS_ACK_SHIFT 0x00007000 -#define AR_TXSIFS_ACK_SHIFT_S 12 - -#define AR_TXOP_X 0x81ec -#define AR_TXOP_X_VAL 0x000000FF - - -#define AR_TXOP_0_3 0x81f0 -#define AR_TXOP_4_7 0x81f4 -#define AR_TXOP_8_11 0x81f8 -#define AR_TXOP_12_15 0x81fc - -#define AR_NEXT_NDP2_TIMER 0x8180 -#define AR_FIRST_NDP_TIMER 7 -#define AR_NDP2_PERIOD 0x81a0 -#define AR_NDP2_TIMER_MODE 0x81c0 -#define AR_NEXT_TBTT_TIMER 0x8200 -#define AR_NEXT_DMA_BEACON_ALERT 0x8204 -#define AR_NEXT_SWBA 0x8208 -#define AR_NEXT_CFP 0x8208 -#define AR_NEXT_HCF 0x820C -#define AR_NEXT_TIM 0x8210 -#define AR_NEXT_DTIM 0x8214 -#define AR_NEXT_QUIET_TIMER 0x8218 -#define AR_NEXT_NDP_TIMER 0x821C - -#define AR_BEACON_PERIOD 0x8220 -#define AR_DMA_BEACON_PERIOD 0x8224 -#define AR_SWBA_PERIOD 0x8228 -#define AR_HCF_PERIOD 0x822C -#define AR_TIM_PERIOD 0x8230 -#define AR_DTIM_PERIOD 0x8234 -#define AR_QUIET_PERIOD 0x8238 -#define AR_NDP_PERIOD 0x823C - -#define AR_TIMER_MODE 0x8240 -#define AR_TBTT_TIMER_EN 0x00000001 -#define AR_DBA_TIMER_EN 0x00000002 -#define AR_SWBA_TIMER_EN 0x00000004 -#define AR_HCF_TIMER_EN 0x00000008 -#define AR_TIM_TIMER_EN 0x00000010 -#define AR_DTIM_TIMER_EN 0x00000020 -#define AR_QUIET_TIMER_EN 0x00000040 -#define AR_NDP_TIMER_EN 0x00000080 -#define AR_TIMER_OVERFLOW_INDEX 0x00000700 -#define AR_TIMER_OVERFLOW_INDEX_S 8 -#define AR_TIMER_THRESH 0xFFFFF000 -#define AR_TIMER_THRESH_S 12 - -#define AR_SLP32_MODE 0x8244 -#define AR_SLP32_HALF_CLK_LATENCY 0x000FFFFF -#define AR_SLP32_ENA 0x00100000 -#define AR_SLP32_TSF_WRITE_STATUS 0x00200000 - -#define AR_SLP32_WAKE 0x8248 -#define AR_SLP32_WAKE_XTL_TIME 0x0000FFFF - -#define AR_SLP32_INC 0x824c -#define AR_SLP32_TST_INC 0x000FFFFF - -#define AR_SLP_CNT 0x8250 -#define AR_SLP_CYCLE_CNT 0x8254 - -#define AR_SLP_MIB_CTRL 0x8258 -#define AR_SLP_MIB_CLEAR 0x00000001 -#define AR_SLP_MIB_PENDING 0x00000002 - -#define AR_MAC_PCU_LOGIC_ANALYZER 0x8264 -#define AR_MAC_PCU_LOGIC_ANALYZER_DISBUG20768 0x20000000 - - -#define AR_2040_MODE 0x8318 -#define AR_2040_JOINED_RX_CLEAR 0x00000001 - - -#define AR_EXTRCCNT 0x8328 - -#define AR_SELFGEN_MASK 0x832c - -#define AR_PCU_TXBUF_CTRL 0x8340 -#define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF -#define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 -#define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 - -#define AR_PCU_MISC_MODE2 0x8344 -#define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 -#define AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT 0x00000004 - -#define AR_PCU_MISC_MODE2_RESERVED 0x00000038 -#define AR_PCU_MISC_MODE2_ADHOC_MCAST_KEYID_ENABLE 0x00000040 -#define AR_PCU_MISC_MODE2_CFP_IGNORE 0x00000080 -#define AR_PCU_MISC_MODE2_MGMT_QOS 0x0000FF00 -#define AR_PCU_MISC_MODE2_MGMT_QOS_S 8 -#define AR_PCU_MISC_MODE2_ENABLE_LOAD_NAV_BEACON_DURATION 0x00010000 -#define AR_PCU_MISC_MODE2_ENABLE_AGGWEP 0x00020000 -#define AR_PCU_MISC_MODE2_HWWAR1 0x00100000 -#define AR_PCU_MISC_MODE2_HWWAR2 0x02000000 -#define AR_PCU_MISC_MODE2_RESERVED2 0xFFFE0000 - -#define AR_MAC_PCU_ASYNC_FIFO_REG3 0x8358 -#define AR_MAC_PCU_ASYNC_FIFO_REG3_DATAPATH_SEL 0x00000400 -#define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 - - -#define AR_AES_MUTE_MASK0 0x805c -#define AR_AES_MUTE_MASK0_FC 0x0000FFFF -#define AR_AES_MUTE_MASK0_QOS 0xFFFF0000 -#define AR_AES_MUTE_MASK0_QOS_S 16 - -#define AR_AES_MUTE_MASK1 0x8060 -#define AR_AES_MUTE_MASK1_SEQ 0x0000FFFF -#define AR_AES_MUTE_MASK1_SEQ_S 0 -#define AR_AES_MUTE_MASK1_FC_MGMT 0xFFFF0000 -#define AR_AES_MUTE_MASK1_FC_MGMT_S 16 - -#define AR_RATE_DURATION_0 0x8700 -#define AR_RATE_DURATION_31 0x87CC -#define AR_RATE_DURATION_32 0x8780 -#define AR_RATE_DURATION(_n) (AR_RATE_DURATION_0 + ((_n)<<2)) - - -#define AR_KEYTABLE_0 0x8800 -#define AR_KEYTABLE(_n) (AR_KEYTABLE_0 + ((_n)*32)) -#define AR_KEY_CACHE_SIZE 128 -#define AR_RSVD_KEYTABLE_ENTRIES 4 -#define AR_KEY_TYPE 0x00000007 -#define AR_KEYTABLE_TYPE_40 0x00000000 -#define AR_KEYTABLE_TYPE_104 0x00000001 -#define AR_KEYTABLE_TYPE_128 0x00000003 -#define AR_KEYTABLE_TYPE_TKIP 0x00000004 -#define AR_KEYTABLE_TYPE_AES 0x00000005 -#define AR_KEYTABLE_TYPE_CCM 0x00000006 -#define AR_KEYTABLE_TYPE_CLR 0x00000007 -#define AR_KEYTABLE_ANT 0x00000008 -#define AR_KEYTABLE_VALID 0x00008000 -#define AR_KEYTABLE_KEY0(_n) (AR_KEYTABLE(_n) + 0) -#define AR_KEYTABLE_KEY1(_n) (AR_KEYTABLE(_n) + 4) -#define AR_KEYTABLE_KEY2(_n) (AR_KEYTABLE(_n) + 8) -#define AR_KEYTABLE_KEY3(_n) (AR_KEYTABLE(_n) + 12) -#define AR_KEYTABLE_KEY4(_n) (AR_KEYTABLE(_n) + 16) -#define AR_KEYTABLE_TYPE(_n) (AR_KEYTABLE(_n) + 20) -#define AR_KEYTABLE_MAC0(_n) (AR_KEYTABLE(_n) + 24) -#define AR_KEYTABLE_MAC1(_n) (AR_KEYTABLE(_n) + 28) - -#endif diff --git a/drivers/net/wireless/ath/ath9k/virtual.c b/drivers/net/wireless/ath/ath9k/virtual.c deleted file mode 100644 index 19b88f8177fd..000000000000 --- a/drivers/net/wireless/ath/ath9k/virtual.c +++ /dev/null @@ -1,680 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -struct ath9k_vif_iter_data { - int count; - u8 *addr; -}; - -static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath9k_vif_iter_data *iter_data = data; - u8 *nbuf; - - nbuf = krealloc(iter_data->addr, (iter_data->count + 1) * ETH_ALEN, - GFP_ATOMIC); - if (nbuf == NULL) - return; - - memcpy(nbuf + iter_data->count * ETH_ALEN, mac, ETH_ALEN); - iter_data->addr = nbuf; - iter_data->count++; -} - -void ath9k_set_bssid_mask(struct ieee80211_hw *hw) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath9k_vif_iter_data iter_data; - int i, j; - u8 mask[ETH_ALEN]; - - /* - * Add primary MAC address even if it is not in active use since it - * will be configured to the hardware as the starting point and the - * BSSID mask will need to be changed if another address is active. - */ - iter_data.addr = kmalloc(ETH_ALEN, GFP_ATOMIC); - if (iter_data.addr) { - memcpy(iter_data.addr, sc->sc_ah->macaddr, ETH_ALEN); - iter_data.count = 1; - } else - iter_data.count = 0; - - /* Get list of all active MAC addresses */ - spin_lock_bh(&sc->wiphy_lock); - ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter, - &iter_data); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] == NULL) - continue; - ieee80211_iterate_active_interfaces_atomic( - sc->sec_wiphy[i]->hw, ath9k_vif_iter, &iter_data); - } - spin_unlock_bh(&sc->wiphy_lock); - - /* Generate an address mask to cover all active addresses */ - memset(mask, 0, ETH_ALEN); - for (i = 0; i < iter_data.count; i++) { - u8 *a1 = iter_data.addr + i * ETH_ALEN; - for (j = i + 1; j < iter_data.count; j++) { - u8 *a2 = iter_data.addr + j * ETH_ALEN; - mask[0] |= a1[0] ^ a2[0]; - mask[1] |= a1[1] ^ a2[1]; - mask[2] |= a1[2] ^ a2[2]; - mask[3] |= a1[3] ^ a2[3]; - mask[4] |= a1[4] ^ a2[4]; - mask[5] |= a1[5] ^ a2[5]; - } - } - - kfree(iter_data.addr); - - /* Invert the mask and configure hardware */ - sc->bssidmask[0] = ~mask[0]; - sc->bssidmask[1] = ~mask[1]; - sc->bssidmask[2] = ~mask[2]; - sc->bssidmask[3] = ~mask[3]; - sc->bssidmask[4] = ~mask[4]; - sc->bssidmask[5] = ~mask[5]; - - ath9k_hw_setbssidmask(sc); -} - -int ath9k_wiphy_add(struct ath_softc *sc) -{ - int i, error; - struct ath_wiphy *aphy; - struct ieee80211_hw *hw; - u8 addr[ETH_ALEN]; - - hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy), &ath9k_ops); - if (hw == NULL) - return -ENOMEM; - - spin_lock_bh(&sc->wiphy_lock); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] == NULL) - break; - } - - if (i == sc->num_sec_wiphy) { - /* No empty slot available; increase array length */ - struct ath_wiphy **n; - n = krealloc(sc->sec_wiphy, - (sc->num_sec_wiphy + 1) * - sizeof(struct ath_wiphy *), - GFP_ATOMIC); - if (n == NULL) { - spin_unlock_bh(&sc->wiphy_lock); - ieee80211_free_hw(hw); - return -ENOMEM; - } - n[i] = NULL; - sc->sec_wiphy = n; - sc->num_sec_wiphy++; - } - - SET_IEEE80211_DEV(hw, sc->dev); - - aphy = hw->priv; - aphy->sc = sc; - aphy->hw = hw; - sc->sec_wiphy[i] = aphy; - spin_unlock_bh(&sc->wiphy_lock); - - memcpy(addr, sc->sc_ah->macaddr, ETH_ALEN); - addr[0] |= 0x02; /* Locally managed address */ - /* - * XOR virtual wiphy index into the least significant bits to generate - * a different MAC address for each virtual wiphy. - */ - addr[5] ^= i & 0xff; - addr[4] ^= (i & 0xff00) >> 8; - addr[3] ^= (i & 0xff0000) >> 16; - - SET_IEEE80211_PERM_ADDR(hw, addr); - - ath_set_hw_capab(sc, hw); - - error = ieee80211_register_hw(hw); - - if (error == 0) { - /* Make sure wiphy scheduler is started (if enabled) */ - ath9k_wiphy_set_scheduler(sc, sc->wiphy_scheduler_int); - } - - return error; -} - -int ath9k_wiphy_del(struct ath_wiphy *aphy) -{ - struct ath_softc *sc = aphy->sc; - int i; - - spin_lock_bh(&sc->wiphy_lock); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (aphy == sc->sec_wiphy[i]) { - sc->sec_wiphy[i] = NULL; - spin_unlock_bh(&sc->wiphy_lock); - ieee80211_unregister_hw(aphy->hw); - ieee80211_free_hw(aphy->hw); - return 0; - } - } - spin_unlock_bh(&sc->wiphy_lock); - return -ENOENT; -} - -static int ath9k_send_nullfunc(struct ath_wiphy *aphy, - struct ieee80211_vif *vif, const u8 *bssid, - int ps) -{ - struct ath_softc *sc = aphy->sc; - struct ath_tx_control txctl; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - __le16 fc; - struct ieee80211_tx_info *info; - - skb = dev_alloc_skb(24); - if (skb == NULL) - return -ENOMEM; - hdr = (struct ieee80211_hdr *) skb_put(skb, 24); - memset(hdr, 0, 24); - fc = cpu_to_le16(IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | - IEEE80211_FCTL_TODS); - if (ps) - fc |= cpu_to_le16(IEEE80211_FCTL_PM); - hdr->frame_control = fc; - memcpy(hdr->addr1, bssid, ETH_ALEN); - memcpy(hdr->addr2, aphy->hw->wiphy->perm_addr, ETH_ALEN); - memcpy(hdr->addr3, bssid, ETH_ALEN); - - info = IEEE80211_SKB_CB(skb); - memset(info, 0, sizeof(*info)); - info->flags = IEEE80211_TX_CTL_REQ_TX_STATUS; - info->control.vif = vif; - info->control.rates[0].idx = 0; - info->control.rates[0].count = 4; - info->control.rates[1].idx = -1; - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - txctl.txq = &sc->tx.txq[sc->tx.hwq_map[ATH9K_WME_AC_VO]]; - txctl.frame_type = ps ? ATH9K_INT_PAUSE : ATH9K_INT_UNPAUSE; - - if (ath_tx_start(aphy->hw, skb, &txctl) != 0) - goto exit; - - return 0; -exit: - dev_kfree_skb_any(skb); - return -1; -} - -static bool __ath9k_wiphy_pausing(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state == ATH_WIPHY_PAUSING) - return true; - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_PAUSING) - return true; - } - return false; -} - -static bool ath9k_wiphy_pausing(struct ath_softc *sc) -{ - bool ret; - spin_lock_bh(&sc->wiphy_lock); - ret = __ath9k_wiphy_pausing(sc); - spin_unlock_bh(&sc->wiphy_lock); - return ret; -} - -static bool __ath9k_wiphy_scanning(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state == ATH_WIPHY_SCAN) - return true; - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_SCAN) - return true; - } - return false; -} - -bool ath9k_wiphy_scanning(struct ath_softc *sc) -{ - bool ret; - spin_lock_bh(&sc->wiphy_lock); - ret = __ath9k_wiphy_scanning(sc); - spin_unlock_bh(&sc->wiphy_lock); - return ret; -} - -static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy); - -/* caller must hold wiphy_lock */ -static void __ath9k_wiphy_unpause_ch(struct ath_wiphy *aphy) -{ - if (aphy == NULL) - return; - if (aphy->chan_idx != aphy->sc->chan_idx) - return; /* wiphy not on the selected channel */ - __ath9k_wiphy_unpause(aphy); -} - -static void ath9k_wiphy_unpause_channel(struct ath_softc *sc) -{ - int i; - spin_lock_bh(&sc->wiphy_lock); - __ath9k_wiphy_unpause_ch(sc->pri_wiphy); - for (i = 0; i < sc->num_sec_wiphy; i++) - __ath9k_wiphy_unpause_ch(sc->sec_wiphy[i]); - spin_unlock_bh(&sc->wiphy_lock); -} - -void ath9k_wiphy_chan_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, chan_work); - struct ath_wiphy *aphy = sc->next_wiphy; - - if (aphy == NULL) - return; - - /* - * All pending interfaces paused; ready to change - * channels. - */ - - /* Change channels */ - mutex_lock(&sc->mutex); - /* XXX: remove me eventually */ - ath9k_update_ichannel(sc, aphy->hw, - &sc->sc_ah->channels[sc->chan_idx]); - ath_update_chainmask(sc, sc->chan_is_ht); - if (ath_set_channel(sc, aphy->hw, - &sc->sc_ah->channels[sc->chan_idx]) < 0) { - printk(KERN_DEBUG "ath9k: Failed to set channel for new " - "virtual wiphy\n"); - mutex_unlock(&sc->mutex); - return; - } - mutex_unlock(&sc->mutex); - - ath9k_wiphy_unpause_channel(sc); -} - -/* - * ath9k version of ieee80211_tx_status() for TX frames that are generated - * internally in the driver. - */ -void ath9k_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - - if (tx_info_priv && tx_info_priv->frame_type == ATH9K_INT_PAUSE && - aphy->state == ATH_WIPHY_PAUSING) { - if (!(info->flags & IEEE80211_TX_STAT_ACK)) { - printk(KERN_DEBUG "ath9k: %s: no ACK for pause " - "frame\n", wiphy_name(hw->wiphy)); - /* - * The AP did not reply; ignore this to allow us to - * continue. - */ - } - aphy->state = ATH_WIPHY_PAUSED; - if (!ath9k_wiphy_pausing(aphy->sc)) { - /* - * Drop from tasklet to work to allow mutex for channel - * change. - */ - ieee80211_queue_work(aphy->sc->hw, - &aphy->sc->chan_work); - } - } - - kfree(tx_info_priv); - tx_info->rate_driver_data[0] = NULL; - - dev_kfree_skb(skb); -} - -static void ath9k_mark_paused(struct ath_wiphy *aphy) -{ - struct ath_softc *sc = aphy->sc; - aphy->state = ATH_WIPHY_PAUSED; - if (!__ath9k_wiphy_pausing(sc)) - ieee80211_queue_work(sc->hw, &sc->chan_work); -} - -static void ath9k_pause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath_wiphy *aphy = data; - struct ath_vif *avp = (void *) vif->drv_priv; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - if (!vif->bss_conf.assoc) { - ath9k_mark_paused(aphy); - break; - } - /* TODO: could avoid this if already in PS mode */ - if (ath9k_send_nullfunc(aphy, vif, avp->bssid, 1)) { - printk(KERN_DEBUG "%s: failed to send PS nullfunc\n", - __func__); - ath9k_mark_paused(aphy); - } - break; - case NL80211_IFTYPE_AP: - /* Beacon transmission is paused by aphy->state change */ - ath9k_mark_paused(aphy); - break; - default: - break; - } -} - -/* caller must hold wiphy_lock */ -static int __ath9k_wiphy_pause(struct ath_wiphy *aphy) -{ - ieee80211_stop_queues(aphy->hw); - aphy->state = ATH_WIPHY_PAUSING; - /* - * TODO: handle PAUSING->PAUSED for the case where there are multiple - * active vifs (now we do it on the first vif getting ready; should be - * on the last) - */ - ieee80211_iterate_active_interfaces_atomic(aphy->hw, ath9k_pause_iter, - aphy); - return 0; -} - -int ath9k_wiphy_pause(struct ath_wiphy *aphy) -{ - int ret; - spin_lock_bh(&aphy->sc->wiphy_lock); - ret = __ath9k_wiphy_pause(aphy); - spin_unlock_bh(&aphy->sc->wiphy_lock); - return ret; -} - -static void ath9k_unpause_iter(void *data, u8 *mac, struct ieee80211_vif *vif) -{ - struct ath_wiphy *aphy = data; - struct ath_vif *avp = (void *) vif->drv_priv; - - switch (vif->type) { - case NL80211_IFTYPE_STATION: - if (!vif->bss_conf.assoc) - break; - ath9k_send_nullfunc(aphy, vif, avp->bssid, 0); - break; - case NL80211_IFTYPE_AP: - /* Beacon transmission is re-enabled by aphy->state change */ - break; - default: - break; - } -} - -/* caller must hold wiphy_lock */ -static int __ath9k_wiphy_unpause(struct ath_wiphy *aphy) -{ - ieee80211_iterate_active_interfaces_atomic(aphy->hw, - ath9k_unpause_iter, aphy); - aphy->state = ATH_WIPHY_ACTIVE; - ieee80211_wake_queues(aphy->hw); - return 0; -} - -int ath9k_wiphy_unpause(struct ath_wiphy *aphy) -{ - int ret; - spin_lock_bh(&aphy->sc->wiphy_lock); - ret = __ath9k_wiphy_unpause(aphy); - spin_unlock_bh(&aphy->sc->wiphy_lock); - return ret; -} - -static void __ath9k_wiphy_mark_all_paused(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) - sc->pri_wiphy->state = ATH_WIPHY_PAUSED; - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) - sc->sec_wiphy[i]->state = ATH_WIPHY_PAUSED; - } -} - -/* caller must hold wiphy_lock */ -static void __ath9k_wiphy_pause_all(struct ath_softc *sc) -{ - int i; - if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) - __ath9k_wiphy_pause(sc->pri_wiphy); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) - __ath9k_wiphy_pause(sc->sec_wiphy[i]); - } -} - -int ath9k_wiphy_select(struct ath_wiphy *aphy) -{ - struct ath_softc *sc = aphy->sc; - bool now; - - spin_lock_bh(&sc->wiphy_lock); - if (__ath9k_wiphy_scanning(sc)) { - /* - * For now, we are using mac80211 sw scan and it expects to - * have full control over channel changes, so avoid wiphy - * scheduling during a scan. This could be optimized if the - * scanning control were moved into the driver. - */ - spin_unlock_bh(&sc->wiphy_lock); - return -EBUSY; - } - if (__ath9k_wiphy_pausing(sc)) { - if (sc->wiphy_select_failures == 0) - sc->wiphy_select_first_fail = jiffies; - sc->wiphy_select_failures++; - if (time_after(jiffies, sc->wiphy_select_first_fail + HZ / 2)) - { - printk(KERN_DEBUG "ath9k: Previous wiphy select timed " - "out; disable/enable hw to recover\n"); - __ath9k_wiphy_mark_all_paused(sc); - /* - * TODO: this workaround to fix hardware is unlikely to - * be specific to virtual wiphy changes. It can happen - * on normal channel change, too, and as such, this - * should really be made more generic. For example, - * tricker radio disable/enable on GTT interrupt burst - * (say, 10 GTT interrupts received without any TX - * frame being completed) - */ - spin_unlock_bh(&sc->wiphy_lock); - ath_radio_disable(sc); - ath_radio_enable(sc); - ieee80211_queue_work(aphy->sc->hw, - &aphy->sc->chan_work); - return -EBUSY; /* previous select still in progress */ - } - spin_unlock_bh(&sc->wiphy_lock); - return -EBUSY; /* previous select still in progress */ - } - sc->wiphy_select_failures = 0; - - /* Store the new channel */ - sc->chan_idx = aphy->chan_idx; - sc->chan_is_ht = aphy->chan_is_ht; - sc->next_wiphy = aphy; - - __ath9k_wiphy_pause_all(sc); - now = !__ath9k_wiphy_pausing(aphy->sc); - spin_unlock_bh(&sc->wiphy_lock); - - if (now) { - /* Ready to request channel change immediately */ - ieee80211_queue_work(aphy->sc->hw, &aphy->sc->chan_work); - } - - /* - * wiphys will be unpaused in ath9k_tx_status() once channel has been - * changed if any wiphy needs time to become paused. - */ - - return 0; -} - -bool ath9k_wiphy_started(struct ath_softc *sc) -{ - int i; - spin_lock_bh(&sc->wiphy_lock); - if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { - spin_unlock_bh(&sc->wiphy_lock); - return true; - } - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state != ATH_WIPHY_INACTIVE) { - spin_unlock_bh(&sc->wiphy_lock); - return true; - } - } - spin_unlock_bh(&sc->wiphy_lock); - return false; -} - -static void ath9k_wiphy_pause_chan(struct ath_wiphy *aphy, - struct ath_wiphy *selected) -{ - if (selected->state == ATH_WIPHY_SCAN) { - if (aphy == selected) - return; - /* - * Pause all other wiphys for the duration of the scan even if - * they are on the current channel now. - */ - } else if (aphy->chan_idx == selected->chan_idx) - return; - aphy->state = ATH_WIPHY_PAUSED; - ieee80211_stop_queues(aphy->hw); -} - -void ath9k_wiphy_pause_all_forced(struct ath_softc *sc, - struct ath_wiphy *selected) -{ - int i; - spin_lock_bh(&sc->wiphy_lock); - if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) - ath9k_wiphy_pause_chan(sc->pri_wiphy, selected); - for (i = 0; i < sc->num_sec_wiphy; i++) { - if (sc->sec_wiphy[i] && - sc->sec_wiphy[i]->state == ATH_WIPHY_ACTIVE) - ath9k_wiphy_pause_chan(sc->sec_wiphy[i], selected); - } - spin_unlock_bh(&sc->wiphy_lock); -} - -void ath9k_wiphy_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - wiphy_work.work); - struct ath_wiphy *aphy = NULL; - bool first = true; - - spin_lock_bh(&sc->wiphy_lock); - - if (sc->wiphy_scheduler_int == 0) { - /* wiphy scheduler is disabled */ - spin_unlock_bh(&sc->wiphy_lock); - return; - } - -try_again: - sc->wiphy_scheduler_index++; - while (sc->wiphy_scheduler_index <= sc->num_sec_wiphy) { - aphy = sc->sec_wiphy[sc->wiphy_scheduler_index - 1]; - if (aphy && aphy->state != ATH_WIPHY_INACTIVE) - break; - - sc->wiphy_scheduler_index++; - aphy = NULL; - } - if (aphy == NULL) { - sc->wiphy_scheduler_index = 0; - if (sc->pri_wiphy->state == ATH_WIPHY_INACTIVE) { - if (first) { - first = false; - goto try_again; - } - /* No wiphy is ready to be scheduled */ - } else - aphy = sc->pri_wiphy; - } - - spin_unlock_bh(&sc->wiphy_lock); - - if (aphy && - aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN && - ath9k_wiphy_select(aphy)) { - printk(KERN_DEBUG "ath9k: Failed to schedule virtual wiphy " - "change\n"); - } - - ieee80211_queue_delayed_work(sc->hw, - &sc->wiphy_work, - sc->wiphy_scheduler_int); -} - -void ath9k_wiphy_set_scheduler(struct ath_softc *sc, unsigned int msec_int) -{ - cancel_delayed_work_sync(&sc->wiphy_work); - sc->wiphy_scheduler_int = msecs_to_jiffies(msec_int); - if (sc->wiphy_scheduler_int) - ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work, - sc->wiphy_scheduler_int); -} - -/* caller must hold wiphy_lock */ -bool ath9k_all_wiphys_idle(struct ath_softc *sc) -{ - unsigned int i; - if (sc->pri_wiphy->state != ATH_WIPHY_INACTIVE) { - return false; - } - for (i = 0; i < sc->num_sec_wiphy; i++) { - struct ath_wiphy *aphy = sc->sec_wiphy[i]; - if (!aphy) - continue; - if (aphy->state != ATH_WIPHY_INACTIVE) - return false; - } - return true; -} diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c deleted file mode 100644 index 6a04681631d1..000000000000 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ /dev/null @@ -1,2217 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include "ath9k.h" - -#define BITS_PER_BYTE 8 -#define OFDM_PLCP_BITS 22 -#define HT_RC_2_MCS(_rc) ((_rc) & 0x0f) -#define HT_RC_2_STREAMS(_rc) ((((_rc) & 0x78) >> 3) + 1) -#define L_STF 8 -#define L_LTF 8 -#define L_SIG 4 -#define HT_SIG 8 -#define HT_STF 4 -#define HT_LTF(_ns) (4 * (_ns)) -#define SYMBOL_TIME(_ns) ((_ns) << 2) /* ns * 4 us */ -#define SYMBOL_TIME_HALFGI(_ns) (((_ns) * 18 + 4) / 5) /* ns * 3.6 us */ -#define NUM_SYMBOLS_PER_USEC(_usec) (_usec >> 2) -#define NUM_SYMBOLS_PER_USEC_HALFGI(_usec) (((_usec*5)-4)/18) - -#define OFDM_SIFS_TIME 16 - -static u32 bits_per_symbol[][2] = { - /* 20MHz 40MHz */ - { 26, 54 }, /* 0: BPSK */ - { 52, 108 }, /* 1: QPSK 1/2 */ - { 78, 162 }, /* 2: QPSK 3/4 */ - { 104, 216 }, /* 3: 16-QAM 1/2 */ - { 156, 324 }, /* 4: 16-QAM 3/4 */ - { 208, 432 }, /* 5: 64-QAM 2/3 */ - { 234, 486 }, /* 6: 64-QAM 3/4 */ - { 260, 540 }, /* 7: 64-QAM 5/6 */ - { 52, 108 }, /* 8: BPSK */ - { 104, 216 }, /* 9: QPSK 1/2 */ - { 156, 324 }, /* 10: QPSK 3/4 */ - { 208, 432 }, /* 11: 16-QAM 1/2 */ - { 312, 648 }, /* 12: 16-QAM 3/4 */ - { 416, 864 }, /* 13: 64-QAM 2/3 */ - { 468, 972 }, /* 14: 64-QAM 3/4 */ - { 520, 1080 }, /* 15: 64-QAM 5/6 */ -}; - -#define IS_HT_RATE(_rate) ((_rate) & 0x80) - -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head); -static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, - struct ath_txq *txq, - struct list_head *bf_q, - int txok, int sendbar); -static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *head); -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf); -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok); -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok, bool update_rc); - -/*********************/ -/* Aggregation logic */ -/*********************/ - -static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) -{ - struct ath_atx_ac *ac = tid->ac; - - if (tid->paused) - return; - - if (tid->sched) - return; - - tid->sched = true; - list_add_tail(&tid->list, &ac->tid_q); - - if (ac->sched) - return; - - ac->sched = true; - list_add_tail(&ac->list, &txq->axq_acq); -} - -static void ath_tx_pause_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - - spin_lock_bh(&txq->axq_lock); - tid->paused++; - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - - ASSERT(tid->paused > 0); - spin_lock_bh(&txq->axq_lock); - - tid->paused--; - - if (tid->paused > 0) - goto unlock; - - if (list_empty(&tid->buf_q)) - goto unlock; - - ath_tx_queue_tid(txq, tid); - ath_txq_schedule(sc, txq); -unlock: - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = &sc->tx.txq[tid->ac->qnum]; - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - ASSERT(tid->paused > 0); - spin_lock_bh(&txq->axq_lock); - - tid->paused--; - - if (tid->paused > 0) { - spin_unlock_bh(&txq->axq_lock); - return; - } - - while (!list_empty(&tid->buf_q)) { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - ASSERT(!bf_isretried(bf)); - list_move_tail(&bf->list, &bf_head); - ath_tx_send_ht_normal(sc, txq, tid, &bf_head); - } - - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - int seqno) -{ - int index, cindex; - - index = ATH_BA_INDEX(tid->seq_start, seqno); - cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - - tid->tx_buf[cindex] = NULL; - - while (tid->baw_head != tid->baw_tail && !tid->tx_buf[tid->baw_head]) { - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - INCR(tid->baw_head, ATH_TID_MAX_BUFS); - } -} - -static void ath_tx_addto_baw(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf) -{ - int index, cindex; - - if (bf_isretried(bf)) - return; - - index = ATH_BA_INDEX(tid->seq_start, bf->bf_seqno); - cindex = (tid->baw_head + index) & (ATH_TID_MAX_BUFS - 1); - - ASSERT(tid->tx_buf[cindex] == NULL); - tid->tx_buf[cindex] = bf; - - if (index >= ((tid->baw_tail - tid->baw_head) & - (ATH_TID_MAX_BUFS - 1))) { - tid->baw_tail = cindex; - INCR(tid->baw_tail, ATH_TID_MAX_BUFS); - } -} - -/* - * TODO: For frame(s) that are in the retry state, we will reuse the - * sequence number(s) without setting the retry bit. The - * alternative is to give up on these and BAR the receiver's window - * forward. - */ -static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) - -{ - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - for (;;) { - if (list_empty(&tid->buf_q)) - break; - - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - list_move_tail(&bf->list, &bf_head); - - if (bf_isretried(bf)) - ath_tx_update_baw(sc, tid, bf->bf_seqno); - - spin_unlock(&txq->axq_lock); - ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); - spin_lock(&txq->axq_lock); - } - - tid->seq_next = tid->seq_start; - tid->baw_tail = tid->baw_head; -} - -static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf) -{ - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - - bf->bf_state.bf_type |= BUF_RETRY; - bf->bf_retries++; - TX_STAT_INC(txq->axq_qnum, a_retries); - - skb = bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_RETRY); -} - -static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf) -{ - struct ath_buf *tbf; - - spin_lock_bh(&sc->tx.txbuflock); - if (WARN_ON(list_empty(&sc->tx.txbuf))) { - spin_unlock_bh(&sc->tx.txbuflock); - return NULL; - } - tbf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&tbf->list); - spin_unlock_bh(&sc->tx.txbuflock); - - ATH_TXBUF_RESET(tbf); - - tbf->bf_mpdu = bf->bf_mpdu; - tbf->bf_buf_addr = bf->bf_buf_addr; - *(tbf->bf_desc) = *(bf->bf_desc); - tbf->bf_state = bf->bf_state; - tbf->bf_dmacontext = bf->bf_dmacontext; - - return tbf; -} - -static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_buf *bf, struct list_head *bf_q, - int txok) -{ - struct ath_node *an = NULL; - struct sk_buff *skb; - struct ieee80211_sta *sta; - struct ieee80211_hdr *hdr; - struct ath_atx_tid *tid = NULL; - struct ath_buf *bf_next, *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; - struct list_head bf_head, bf_pending; - u16 seq_st = 0, acked_cnt = 0, txfail_cnt = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int isaggr, txfail, txpending, sendbar = 0, needreset = 0, nbad = 0; - bool rc_update = true; - - skb = bf->bf_mpdu; - hdr = (struct ieee80211_hdr *)skb->data; - - rcu_read_lock(); - - sta = ieee80211_find_sta(sc->hw, hdr->addr1); - if (!sta) { - rcu_read_unlock(); - return; - } - - an = (struct ath_node *)sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); - - isaggr = bf_isaggr(bf); - memset(ba, 0, WME_BA_BMP_SIZE >> 3); - - if (isaggr && txok) { - if (ATH_DS_TX_BA(ds)) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), - WME_BA_BMP_SIZE >> 3); - } else { - /* - * AR5416 can become deaf/mute when BA - * issue happens. Chip needs to be reset. - * But AP code may have sychronization issues - * when perform internal reset in this routine. - * Only enable reset in STA mode for now. - */ - if (sc->sc_ah->opmode == NL80211_IFTYPE_STATION) - needreset = 1; - } - } - - INIT_LIST_HEAD(&bf_pending); - INIT_LIST_HEAD(&bf_head); - - nbad = ath_tx_num_badfrms(sc, bf, txok); - while (bf) { - txfail = txpending = 0; - bf_next = bf->bf_next; - - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, bf->bf_seqno))) { - /* transmit completion, subframe is - * acked by block ack */ - acked_cnt++; - } else if (!isaggr && txok) { - /* transmit completion */ - acked_cnt++; - } else { - if (!(tid->state & AGGR_CLEANUP) && - ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) { - if (bf->bf_retries < ATH_MAX_SW_RETRIES) { - ath_tx_set_retry(sc, txq, bf); - txpending = 1; - } else { - bf->bf_state.bf_type |= BUF_XRETRY; - txfail = 1; - sendbar = 1; - txfail_cnt++; - } - } else { - /* - * cleanup in progress, just fail - * the un-acked sub-frames - */ - txfail = 1; - } - } - - if (bf_next == NULL) { - /* - * Make sure the last desc is reclaimed if it - * not a holding desc. - */ - if (!bf_last->bf_stale) - list_move_tail(&bf->list, &bf_head); - else - INIT_LIST_HEAD(&bf_head); - } else { - ASSERT(!list_empty(bf_q)); - list_move_tail(&bf->list, &bf_head); - } - - if (!txpending) { - /* - * complete the acked-ones/xretried ones; update - * block-ack window - */ - spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, bf->bf_seqno); - spin_unlock_bh(&txq->axq_lock); - - if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) { - ath_tx_rc_status(bf, ds, nbad, txok, true); - rc_update = false; - } else { - ath_tx_rc_status(bf, ds, nbad, txok, false); - } - - ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar); - } else { - /* retry the un-acked ones */ - if (bf->bf_next == NULL && bf_last->bf_stale) { - struct ath_buf *tbf; - - tbf = ath_clone_txbuf(sc, bf_last); - /* - * Update tx baw and complete the frame with - * failed status if we run out of tx buf - */ - if (!tbf) { - spin_lock_bh(&txq->axq_lock); - ath_tx_update_baw(sc, tid, - bf->bf_seqno); - spin_unlock_bh(&txq->axq_lock); - - bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ds, nbad, - 0, false); - ath_tx_complete_buf(sc, bf, txq, - &bf_head, 0, 0); - break; - } - - ath9k_hw_cleartxdesc(sc->sc_ah, tbf->bf_desc); - list_add_tail(&tbf->list, &bf_head); - } else { - /* - * Clear descriptor status words for - * software retry - */ - ath9k_hw_cleartxdesc(sc->sc_ah, bf->bf_desc); - } - - /* - * Put this buffer to the temporary pending - * queue to retain ordering - */ - list_splice_tail_init(&bf_head, &bf_pending); - } - - bf = bf_next; - } - - /* prepend un-acked frames to the beginning of the pending frame queue */ - if (!list_empty(&bf_pending)) { - spin_lock_bh(&txq->axq_lock); - list_splice(&bf_pending, &tid->buf_q); - ath_tx_queue_tid(txq, tid); - spin_unlock_bh(&txq->axq_lock); - } - - if (tid->state & AGGR_CLEANUP) { - if (tid->baw_head == tid->baw_tail) { - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_CLEANUP; - - /* send buffered frames as singles */ - ath_tx_flush_tid(sc, tid); - } - rcu_read_unlock(); - return; - } - - rcu_read_unlock(); - - if (needreset) - ath_reset(sc, false); -} - -static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, - struct ath_atx_tid *tid) -{ - const struct ath_rate_table *rate_table = sc->cur_rate_table; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; - struct ath_tx_info_priv *tx_info_priv; - u32 max_4ms_framelen, frmlen; - u16 aggr_limit, legacy = 0; - int i; - - skb = bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; - tx_info_priv = (struct ath_tx_info_priv *)tx_info->rate_driver_data[0]; - - /* - * Find the lowest frame length among the rate series that will have a - * 4ms transmit duration. - * TODO - TXOP limit needs to be considered. - */ - max_4ms_framelen = ATH_AMPDU_LIMIT_MAX; - - for (i = 0; i < 4; i++) { - if (rates[i].count) { - if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { - legacy = 1; - break; - } - - frmlen = rate_table->info[rates[i].idx].max_4ms_framelen; - max_4ms_framelen = min(max_4ms_framelen, frmlen); - } - } - - /* - * limit aggregate size by the minimum rate if rate selected is - * not a probe rate, if rate selected is a probe rate then - * avoid aggregation of this packet. - */ - if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy) - return 0; - - if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED) - aggr_limit = min((max_4ms_framelen * 3) / 8, - (u32)ATH_AMPDU_LIMIT_MAX); - else - aggr_limit = min(max_4ms_framelen, - (u32)ATH_AMPDU_LIMIT_MAX); - - /* - * h/w can accept aggregates upto 16 bit lengths (65535). - * The IE, however can hold upto 65536, which shows up here - * as zero. Ignore 65536 since we are constrained by hw. - */ - if (tid->an->maxampdu) - aggr_limit = min(aggr_limit, tid->an->maxampdu); - - return aggr_limit; -} - -/* - * Returns the number of delimiters to be added to - * meet the minimum required mpdudensity. - */ -static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, - struct ath_buf *bf, u16 frmlen) -{ - const struct ath_rate_table *rt = sc->cur_rate_table; - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - u32 nsymbits, nsymbols; - u16 minlen; - u8 rc, flags, rix; - int width, half_gi, ndelim, mindelim; - - /* Select standard number of delimiters based on frame length alone */ - ndelim = ATH_AGGR_GET_NDELIM(frmlen); - - /* - * If encryption enabled, hardware requires some more padding between - * subframes. - * TODO - this could be improved to be dependent on the rate. - * The hardware can keep up at lower rates, but not higher rates - */ - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) - ndelim += ATH_AGGR_ENCRYPTDELIM; - - /* - * Convert desired mpdu density from microeconds to bytes based - * on highest rate in rate series (i.e. first rate) to determine - * required minimum length for subframe. Take into account - * whether high rate is 20 or 40Mhz and half or full GI. - * - * If there is no mpdu density restriction, no further calculation - * is needed. - */ - - if (tid->an->mpdudensity == 0) - return ndelim; - - rix = tx_info->control.rates[0].idx; - flags = tx_info->control.rates[0].flags; - rc = rt->info[rix].ratecode; - width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; - half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; - - if (half_gi) - nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity); - else - nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity); - - if (nsymbols == 0) - nsymbols = 1; - - nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; - minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; - - if (frmlen < minlen) { - mindelim = (minlen - frmlen) / ATH_AGGR_DELIM_SZ; - ndelim = max(mindelim, ndelim); - } - - return ndelim; -} - -static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc, - struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_q) -{ -#define PADBYTES(_len) ((4 - ((_len) % 4)) % 4) - struct ath_buf *bf, *bf_first, *bf_prev = NULL; - int rl = 0, nframes = 0, ndelim, prev_al = 0; - u16 aggr_limit = 0, al = 0, bpad = 0, - al_delta, h_baw = tid->baw_size / 2; - enum ATH_AGGR_STATUS status = ATH_AGGR_DONE; - - bf_first = list_first_entry(&tid->buf_q, struct ath_buf, list); - - do { - bf = list_first_entry(&tid->buf_q, struct ath_buf, list); - - /* do not step over block-ack window */ - if (!BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno)) { - status = ATH_AGGR_BAW_CLOSED; - break; - } - - if (!rl) { - aggr_limit = ath_lookup_rate(sc, bf, tid); - rl = 1; - } - - /* do not exceed aggregation limit */ - al_delta = ATH_AGGR_DELIM_SZ + bf->bf_frmlen; - - if (nframes && - (aggr_limit < (al + bpad + al_delta + prev_al))) { - status = ATH_AGGR_LIMITED; - break; - } - - /* do not exceed subframe limit */ - if (nframes >= min((int)h_baw, ATH_AMPDU_SUBFRAME_DEFAULT)) { - status = ATH_AGGR_LIMITED; - break; - } - nframes++; - - /* add padding for previous frame to aggregation length */ - al += bpad + al_delta; - - /* - * Get the delimiters needed to meet the MPDU - * density for this node. - */ - ndelim = ath_compute_num_delims(sc, tid, bf_first, bf->bf_frmlen); - bpad = PADBYTES(al_delta) + (ndelim << 2); - - bf->bf_next = NULL; - bf->bf_desc->ds_link = 0; - - /* link buffers of this frame to the aggregate */ - ath_tx_addto_baw(sc, tid, bf); - ath9k_hw_set11n_aggr_middle(sc->sc_ah, bf->bf_desc, ndelim); - list_move_tail(&bf->list, bf_q); - if (bf_prev) { - bf_prev->bf_next = bf; - bf_prev->bf_desc->ds_link = bf->bf_daddr; - } - bf_prev = bf; - - } while (!list_empty(&tid->buf_q)); - - bf_first->bf_al = al; - bf_first->bf_nframes = nframes; - - return status; -#undef PADBYTES -} - -static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid) -{ - struct ath_buf *bf; - enum ATH_AGGR_STATUS status; - struct list_head bf_q; - - do { - if (list_empty(&tid->buf_q)) - return; - - INIT_LIST_HEAD(&bf_q); - - status = ath_tx_form_aggr(sc, txq, tid, &bf_q); - - /* - * no frames picked up to be aggregated; - * block-ack window is not open. - */ - if (list_empty(&bf_q)) - break; - - bf = list_first_entry(&bf_q, struct ath_buf, list); - bf->bf_lastbf = list_entry(bf_q.prev, struct ath_buf, list); - - /* if only one frame, send as non-aggregate */ - if (bf->bf_nframes == 1) { - bf->bf_state.bf_type &= ~BUF_AGGR; - ath9k_hw_clr11n_aggr(sc->sc_ah, bf->bf_desc); - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, &bf_q); - continue; - } - - /* setup first desc of aggregate */ - bf->bf_state.bf_type |= BUF_AGGR; - ath_buf_set_rate(sc, bf); - ath9k_hw_set11n_aggr_first(sc->sc_ah, bf->bf_desc, bf->bf_al); - - /* anchor last desc of aggregate */ - ath9k_hw_set11n_aggr_last(sc->sc_ah, bf->bf_lastbf->bf_desc); - - txq->axq_aggr_depth++; - ath_tx_txqaddbuf(sc, txq, &bf_q); - TX_STAT_INC(txq->axq_qnum, a_aggr); - - } while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH && - status != ATH_AGGR_BAW_CLOSED); -} - -void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, - u16 tid, u16 *ssn) -{ - struct ath_atx_tid *txtid; - struct ath_node *an; - - an = (struct ath_node *)sta->drv_priv; - txtid = ATH_AN_2_TID(an, tid); - txtid->state |= AGGR_ADDBA_PROGRESS; - ath_tx_pause_tid(sc, txtid); - *ssn = txtid->seq_start; -} - -void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) -{ - struct ath_node *an = (struct ath_node *)sta->drv_priv; - struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); - struct ath_txq *txq = &sc->tx.txq[txtid->ac->qnum]; - struct ath_buf *bf; - struct list_head bf_head; - INIT_LIST_HEAD(&bf_head); - - if (txtid->state & AGGR_CLEANUP) - return; - - if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { - txtid->state &= ~AGGR_ADDBA_PROGRESS; - return; - } - - ath_tx_pause_tid(sc, txtid); - - /* drop all software retried frames and mark this TID */ - spin_lock_bh(&txq->axq_lock); - while (!list_empty(&txtid->buf_q)) { - bf = list_first_entry(&txtid->buf_q, struct ath_buf, list); - if (!bf_isretried(bf)) { - /* - * NB: it's based on the assumption that - * software retried frame will always stay - * at the head of software queue. - */ - break; - } - list_move_tail(&bf->list, &bf_head); - ath_tx_update_baw(sc, txtid, bf->bf_seqno); - ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); - } - spin_unlock_bh(&txq->axq_lock); - - if (txtid->baw_head != txtid->baw_tail) { - txtid->state |= AGGR_CLEANUP; - } else { - txtid->state &= ~AGGR_ADDBA_COMPLETE; - ath_tx_flush_tid(sc, txtid); - } -} - -void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) -{ - struct ath_atx_tid *txtid; - struct ath_node *an; - - an = (struct ath_node *)sta->drv_priv; - - if (sc->sc_flags & SC_OP_TXAGGR) { - txtid = ATH_AN_2_TID(an, tid); - txtid->baw_size = - IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; - txtid->state |= AGGR_ADDBA_COMPLETE; - txtid->state &= ~AGGR_ADDBA_PROGRESS; - ath_tx_resume_tid(sc, txtid); - } -} - -bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno) -{ - struct ath_atx_tid *txtid; - - if (!(sc->sc_flags & SC_OP_TXAGGR)) - return false; - - txtid = ATH_AN_2_TID(an, tidno); - - if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) - return true; - return false; -} - -/********************/ -/* Queue Management */ -/********************/ - -static void ath_txq_drain_pending_buffers(struct ath_softc *sc, - struct ath_txq *txq) -{ - struct ath_atx_ac *ac, *ac_tmp; - struct ath_atx_tid *tid, *tid_tmp; - - list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) { - list_del(&ac->list); - ac->sched = false; - list_for_each_entry_safe(tid, tid_tmp, &ac->tid_q, list) { - list_del(&tid->list); - tid->sched = false; - ath_tid_drain(sc, txq, tid); - } - } -} - -struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath9k_tx_queue_info qi; - int qnum; - - memset(&qi, 0, sizeof(qi)); - qi.tqi_subtype = subtype; - qi.tqi_aifs = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmin = ATH9K_TXQ_USEDEFAULT; - qi.tqi_cwmax = ATH9K_TXQ_USEDEFAULT; - qi.tqi_physCompBuf = 0; - - /* - * Enable interrupts only for EOL and DESC conditions. - * We mark tx descriptors to receive a DESC interrupt - * when a tx queue gets deep; otherwise waiting for the - * EOL to reap descriptors. Note that this is done to - * reduce interrupt load and this only defers reaping - * descriptors, never transmitting frames. Aside from - * reducing interrupts this also permits more concurrency. - * The only potential downside is if the tx queue backs - * up in which case the top half of the kernel may backup - * due to a lack of tx descriptors. - * - * The UAPSD queue is an exception, since we take a desc- - * based intr on the EOSP frames. - */ - if (qtype == ATH9K_TX_QUEUE_UAPSD) - qi.tqi_qflags = TXQ_FLAG_TXDESCINT_ENABLE; - else - qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | - TXQ_FLAG_TXDESCINT_ENABLE; - qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); - if (qnum == -1) { - /* - * NB: don't print a message, this happens - * normally on parts with too few tx queues - */ - return NULL; - } - if (qnum >= ARRAY_SIZE(sc->tx.txq)) { - DPRINTF(sc, ATH_DBG_FATAL, - "qnum %u out of range, max %u!\n", - qnum, (unsigned int)ARRAY_SIZE(sc->tx.txq)); - ath9k_hw_releasetxqueue(ah, qnum); - return NULL; - } - if (!ATH_TXQ_SETUP(sc, qnum)) { - struct ath_txq *txq = &sc->tx.txq[qnum]; - - txq->axq_qnum = qnum; - txq->axq_link = NULL; - INIT_LIST_HEAD(&txq->axq_q); - INIT_LIST_HEAD(&txq->axq_acq); - spin_lock_init(&txq->axq_lock); - txq->axq_depth = 0; - txq->axq_aggr_depth = 0; - txq->axq_linkbuf = NULL; - txq->axq_tx_inprogress = false; - sc->tx.txqsetup |= 1<tx.txq[qnum]; -} - -int ath_tx_get_qnum(struct ath_softc *sc, int qtype, int haltype) -{ - int qnum; - - switch (qtype) { - case ATH9K_TX_QUEUE_DATA: - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - DPRINTF(sc, ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return -1; - } - qnum = sc->tx.hwq_map[haltype]; - break; - case ATH9K_TX_QUEUE_BEACON: - qnum = sc->beacon.beaconq; - break; - case ATH9K_TX_QUEUE_CAB: - qnum = sc->beacon.cabq->axq_qnum; - break; - default: - qnum = -1; - } - return qnum; -} - -struct ath_txq *ath_test_get_txq(struct ath_softc *sc, struct sk_buff *skb) -{ - struct ath_txq *txq = NULL; - int qnum; - - qnum = ath_get_hal_qnum(skb_get_queue_mapping(skb), sc); - txq = &sc->tx.txq[qnum]; - - spin_lock_bh(&txq->axq_lock); - - if (txq->axq_depth >= (ATH_TXBUF - 20)) { - DPRINTF(sc, ATH_DBG_XMIT, - "TX queue: %d is full, depth: %d\n", - qnum, txq->axq_depth); - ieee80211_stop_queue(sc->hw, skb_get_queue_mapping(skb)); - txq->stopped = 1; - spin_unlock_bh(&txq->axq_lock); - return NULL; - } - - spin_unlock_bh(&txq->axq_lock); - - return txq; -} - -int ath_txq_update(struct ath_softc *sc, int qnum, - struct ath9k_tx_queue_info *qinfo) -{ - struct ath_hw *ah = sc->sc_ah; - int error = 0; - struct ath9k_tx_queue_info qi; - - if (qnum == sc->beacon.beaconq) { - /* - * XXX: for beacon queue, we just save the parameter. - * It will be picked up by ath_beaconq_config when - * it's necessary. - */ - sc->beacon.beacon_qi = *qinfo; - return 0; - } - - ASSERT(sc->tx.txq[qnum].axq_qnum == qnum); - - ath9k_hw_get_txq_props(ah, qnum, &qi); - qi.tqi_aifs = qinfo->tqi_aifs; - qi.tqi_cwmin = qinfo->tqi_cwmin; - qi.tqi_cwmax = qinfo->tqi_cwmax; - qi.tqi_burstTime = qinfo->tqi_burstTime; - qi.tqi_readyTime = qinfo->tqi_readyTime; - - if (!ath9k_hw_set_txq_props(ah, qnum, &qi)) { - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to update hardware queue %u!\n", qnum); - error = -EIO; - } else { - ath9k_hw_resettxqueue(ah, qnum); - } - - return error; -} - -int ath_cabq_update(struct ath_softc *sc) -{ - struct ath9k_tx_queue_info qi; - int qnum = sc->beacon.cabq->axq_qnum; - - ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi); - /* - * Ensure the readytime % is within the bounds. - */ - if (sc->config.cabqReadytime < ATH9K_READY_TIME_LO_BOUND) - sc->config.cabqReadytime = ATH9K_READY_TIME_LO_BOUND; - else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND) - sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND; - - qi.tqi_readyTime = (sc->beacon_interval * - sc->config.cabqReadytime) / 100; - ath_txq_update(sc, qnum, &qi); - - return 0; -} - -/* - * Drain a given TX queue (could be Beacon or Data) - * - * This assumes output has been stopped and - * we do not need to block ath_tx_tasklet. - */ -void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx) -{ - struct ath_buf *bf, *lastbf; - struct list_head bf_head; - - INIT_LIST_HEAD(&bf_head); - - for (;;) { - spin_lock_bh(&txq->axq_lock); - - if (list_empty(&txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; - spin_unlock_bh(&txq->axq_lock); - break; - } - - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - - if (bf->bf_stale) { - list_del(&bf->list); - spin_unlock_bh(&txq->axq_lock); - - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - continue; - } - - lastbf = bf->bf_lastbf; - if (!retry_tx) - lastbf->bf_desc->ds_txstat.ts_flags = - ATH9K_TX_SW_ABORTED; - - /* remove ath_buf's of the same mpdu from txq */ - list_cut_position(&bf_head, &txq->axq_q, &lastbf->list); - txq->axq_depth--; - - spin_unlock_bh(&txq->axq_lock); - - if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0); - else - ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0); - } - - spin_lock_bh(&txq->axq_lock); - txq->axq_tx_inprogress = false; - spin_unlock_bh(&txq->axq_lock); - - /* flush any pending frames if aggregation is enabled */ - if (sc->sc_flags & SC_OP_TXAGGR) { - if (!retry_tx) { - spin_lock_bh(&txq->axq_lock); - ath_txq_drain_pending_buffers(sc, txq); - spin_unlock_bh(&txq->axq_lock); - } - } -} - -void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_txq *txq; - int i, npend = 0; - - if (sc->sc_flags & SC_OP_INVALID) - return; - - /* Stop beacon queue */ - ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); - - /* Stop data queues */ - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - ath9k_hw_stoptxdma(ah, txq->axq_qnum); - npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); - } - } - - if (npend) { - int r; - - DPRINTF(sc, ATH_DBG_FATAL, "Unable to stop TxDMA. Reset HAL!\n"); - - spin_lock_bh(&sc->sc_resetlock); - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); - if (r) - DPRINTF(sc, ATH_DBG_FATAL, - "Unable to reset hardware; reset status %d\n", - r); - spin_unlock_bh(&sc->sc_resetlock); - } - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) - ath_draintxq(sc, &sc->tx.txq[i], retry_tx); - } -} - -void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) -{ - ath9k_hw_releasetxqueue(sc->sc_ah, txq->axq_qnum); - sc->tx.txqsetup &= ~(1<axq_qnum); -} - -void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) -{ - struct ath_atx_ac *ac; - struct ath_atx_tid *tid; - - if (list_empty(&txq->axq_acq)) - return; - - ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); - list_del(&ac->list); - ac->sched = false; - - do { - if (list_empty(&ac->tid_q)) - return; - - tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list); - list_del(&tid->list); - tid->sched = false; - - if (tid->paused) - continue; - - ath_tx_sched_aggr(sc, txq, tid); - - /* - * add tid to round-robin queue if more frames - * are pending for the tid - */ - if (!list_empty(&tid->buf_q)) - ath_tx_queue_tid(txq, tid); - - break; - } while (!list_empty(&ac->tid_q)); - - if (!list_empty(&ac->tid_q)) { - if (!ac->sched) { - ac->sched = true; - list_add_tail(&ac->list, &txq->axq_acq); - } - } -} - -int ath_tx_setup(struct ath_softc *sc, int haltype) -{ - struct ath_txq *txq; - - if (haltype >= ARRAY_SIZE(sc->tx.hwq_map)) { - DPRINTF(sc, ATH_DBG_FATAL, - "HAL AC %u out of range, max %zu!\n", - haltype, ARRAY_SIZE(sc->tx.hwq_map)); - return 0; - } - txq = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, haltype); - if (txq != NULL) { - sc->tx.hwq_map[haltype] = txq->axq_qnum; - return 1; - } else - return 0; -} - -/***********/ -/* TX, DMA */ -/***********/ - -/* - * Insert a chain of ath_buf (descriptors) on a txq and - * assume the descriptors are already chained together by caller. - */ -static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *head) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf; - - /* - * Insert the frame on the outbound list and - * pass it on to the hardware. - */ - - if (list_empty(head)) - return; - - bf = list_first_entry(head, struct ath_buf, list); - - list_splice_tail_init(head, &txq->axq_q); - txq->axq_depth++; - txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list); - - DPRINTF(sc, ATH_DBG_QUEUE, - "qnum: %d, txq depth: %d\n", txq->axq_qnum, txq->axq_depth); - - if (txq->axq_link == NULL) { - ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr); - DPRINTF(sc, ATH_DBG_XMIT, - "TXDP[%u] = %llx (%p)\n", - txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc); - } else { - *txq->axq_link = bf->bf_daddr; - DPRINTF(sc, ATH_DBG_XMIT, "link[%u] (%p)=%llx (%p)\n", - txq->axq_qnum, txq->axq_link, - ito64(bf->bf_daddr), bf->bf_desc); - } - txq->axq_link = &(bf->bf_lastbf->bf_desc->ds_link); - ath9k_hw_txstart(ah, txq->axq_qnum); -} - -static struct ath_buf *ath_tx_get_buffer(struct ath_softc *sc) -{ - struct ath_buf *bf = NULL; - - spin_lock_bh(&sc->tx.txbuflock); - - if (unlikely(list_empty(&sc->tx.txbuf))) { - spin_unlock_bh(&sc->tx.txbuflock); - return NULL; - } - - bf = list_first_entry(&sc->tx.txbuf, struct ath_buf, list); - list_del(&bf->list); - - spin_unlock_bh(&sc->tx.txbuflock); - - return bf; -} - -static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid, - struct list_head *bf_head, - struct ath_tx_control *txctl) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_state.bf_type |= BUF_AMPDU; - TX_STAT_INC(txctl->txq->axq_qnum, a_queued); - - /* - * Do not queue to h/w when any of the following conditions is true: - * - there are pending frames in software queue - * - the TID is currently paused for ADDBA/BAR request - * - seqno is not within block-ack window - * - h/w queue depth exceeds low water mark - */ - if (!list_empty(&tid->buf_q) || tid->paused || - !BAW_WITHIN(tid->seq_start, tid->baw_size, bf->bf_seqno) || - txctl->txq->axq_depth >= ATH_AGGR_MIN_QDEPTH) { - /* - * Add this frame to software queue for scheduling later - * for aggregation. - */ - list_move_tail(&bf->list, &tid->buf_q); - ath_tx_queue_tid(txctl->txq, tid); - return; - } - - /* Add sub-frame to BAW */ - ath_tx_addto_baw(sc, tid, bf); - - /* Queue to h/w without aggregation */ - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txctl->txq, bf_head); -} - -static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq, - struct ath_atx_tid *tid, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); - bf->bf_state.bf_type &= ~BUF_AMPDU; - - /* update starting sequence number for subsequent ADDBA request */ - INCR(tid->seq_start, IEEE80211_SEQ_MAX); - - bf->bf_nframes = 1; - bf->bf_lastbf = bf; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); - TX_STAT_INC(txq->axq_qnum, queued); -} - -static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq, - struct list_head *bf_head) -{ - struct ath_buf *bf; - - bf = list_first_entry(bf_head, struct ath_buf, list); - - bf->bf_lastbf = bf; - bf->bf_nframes = 1; - ath_buf_set_rate(sc, bf); - ath_tx_txqaddbuf(sc, txq, bf_head); - TX_STAT_INC(txq->axq_qnum, queued); -} - -static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - enum ath9k_pkt_type htype; - __le16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - if (ieee80211_is_beacon(fc)) - htype = ATH9K_PKT_TYPE_BEACON; - else if (ieee80211_is_probe_resp(fc)) - htype = ATH9K_PKT_TYPE_PROBE_RESP; - else if (ieee80211_is_atim(fc)) - htype = ATH9K_PKT_TYPE_ATIM; - else if (ieee80211_is_pspoll(fc)) - htype = ATH9K_PKT_TYPE_PSPOLL; - else - htype = ATH9K_PKT_TYPE_NORMAL; - - return htype; -} - -static int get_hw_crypto_keytype(struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - - if (tx_info->control.hw_key) { - if (tx_info->control.hw_key->alg == ALG_WEP) - return ATH9K_KEY_TYPE_WEP; - else if (tx_info->control.hw_key->alg == ALG_TKIP) - return ATH9K_KEY_TYPE_TKIP; - else if (tx_info->control.hw_key->alg == ALG_CCMP) - return ATH9K_KEY_TYPE_AES; - } - - return ATH9K_KEY_TYPE_CLEAR; -} - -static void assign_aggr_tid_seqno(struct sk_buff *skb, - struct ath_buf *bf) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr; - struct ath_node *an; - struct ath_atx_tid *tid; - __le16 fc; - u8 *qc; - - if (!tx_info->control.sta) - return; - - an = (struct ath_node *)tx_info->control.sta->drv_priv; - hdr = (struct ieee80211_hdr *)skb->data; - fc = hdr->frame_control; - - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - bf->bf_tidno = qc[0] & 0xf; - } - - /* - * For HT capable stations, we save tidno for later use. - * We also override seqno set by upper layer with the one - * in tx aggregation state. - * - * If fragmentation is on, the sequence number is - * not overridden, since it has been - * incremented by the fragmentation routine. - * - * FIXME: check if the fragmentation threshold exceeds - * IEEE80211 max. - */ - tid = ATH_AN_2_TID(an, bf->bf_tidno); - hdr->seq_ctrl = cpu_to_le16(tid->seq_next << - IEEE80211_SEQ_SEQ_SHIFT); - bf->bf_seqno = tid->seq_next; - INCR(tid->seq_next, IEEE80211_SEQ_MAX); -} - -static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb, - struct ath_txq *txq) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - int flags = 0; - - flags |= ATH9K_TXDESC_CLRDMASK; /* needed for crypto errors */ - flags |= ATH9K_TXDESC_INTREQ; - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) - flags |= ATH9K_TXDESC_NOACK; - - return flags; -} - -/* - * rix - rate index - * pktlen - total bytes (delims + data + fcs + pads + pad delims) - * width - 0 for 20 MHz, 1 for 40 MHz - * half_gi - to use 4us v/s 3.6 us for symbol time - */ -static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, - int width, int half_gi, bool shortPreamble) -{ - const struct ath_rate_table *rate_table = sc->cur_rate_table; - u32 nbits, nsymbits, duration, nsymbols; - u8 rc; - int streams, pktlen; - - pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; - rc = rate_table->info[rix].ratecode; - - /* for legacy rates, use old function to compute packet duration */ - if (!IS_HT_RATE(rc)) - return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen, - rix, shortPreamble); - - /* find number of symbols: PLCP + data */ - nbits = (pktlen << 3) + OFDM_PLCP_BITS; - nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; - nsymbols = (nbits + nsymbits - 1) / nsymbits; - - if (!half_gi) - duration = SYMBOL_TIME(nsymbols); - else - duration = SYMBOL_TIME_HALFGI(nsymbols); - - /* addup duration for legacy/ht training and signal fields */ - streams = HT_RC_2_STREAMS(rc); - duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); - - return duration; -} - -static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) -{ - const struct ath_rate_table *rt = sc->cur_rate_table; - struct ath9k_11n_rate_series series[4]; - struct sk_buff *skb; - struct ieee80211_tx_info *tx_info; - struct ieee80211_tx_rate *rates; - struct ieee80211_hdr *hdr; - int i, flags = 0; - u8 rix = 0, ctsrate = 0; - bool is_pspoll; - - memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); - - skb = bf->bf_mpdu; - tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; - hdr = (struct ieee80211_hdr *)skb->data; - is_pspoll = ieee80211_is_pspoll(hdr->frame_control); - - /* - * We check if Short Preamble is needed for the CTS rate by - * checking the BSS's global flag. - * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. - */ - if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) - ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode | - rt->info[tx_info->control.rts_cts_rate_idx].short_preamble; - else - ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode; - - /* - * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. - * Check the first rate in the series to decide whether RTS/CTS - * or CTS-to-self has to be used. - */ - if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - flags = ATH9K_TXDESC_CTSENA; - else if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - flags = ATH9K_TXDESC_RTSENA; - - /* FIXME: Handle aggregation protection */ - if (sc->config.ath_aggr_prot && - (!bf_isaggr(bf) || (bf_isaggr(bf) && bf->bf_al < 8192))) { - flags = ATH9K_TXDESC_RTSENA; - } - - /* For AR5416 - RTS cannot be followed by a frame larger than 8K */ - if (bf_isaggr(bf) && (bf->bf_al > sc->sc_ah->caps.rts_aggr_limit)) - flags &= ~(ATH9K_TXDESC_RTSENA); - - for (i = 0; i < 4; i++) { - if (!rates[i].count || (rates[i].idx < 0)) - continue; - - rix = rates[i].idx; - series[i].Tries = rates[i].count; - series[i].ChSel = sc->tx_chainmask; - - if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - series[i].Rate = rt->info[rix].ratecode | - rt->info[rix].short_preamble; - else - series[i].Rate = rt->info[rix].ratecode; - - if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) - series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; - if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - series[i].RateFlags |= ATH9K_RATESERIES_2040; - if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) - series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; - - series[i].PktDuration = ath_pkt_duration(sc, rix, bf, - (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, - (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), - (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)); - } - - /* set dur_update_en for l-sig computation except for PS-Poll frames */ - ath9k_hw_set11n_ratescenario(sc->sc_ah, bf->bf_desc, - bf->bf_lastbf->bf_desc, - !is_pspoll, ctsrate, - 0, series, 4, flags); - - if (sc->config.ath_aggr_prot && flags) - ath9k_hw_set11n_burstduration(sc->sc_ah, bf->bf_desc, 8192); -} - -static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf, - struct sk_buff *skb, - struct ath_tx_control *txctl) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_tx_info_priv *tx_info_priv; - int hdrlen; - __le16 fc; - - tx_info_priv = kzalloc(sizeof(*tx_info_priv), GFP_ATOMIC); - if (unlikely(!tx_info_priv)) - return -ENOMEM; - tx_info->rate_driver_data[0] = tx_info_priv; - tx_info_priv->aphy = aphy; - tx_info_priv->frame_type = txctl->frame_type; - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - fc = hdr->frame_control; - - ATH_TXBUF_RESET(bf); - - bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); - - if (conf_is_ht(&sc->hw->conf)) - bf->bf_state.bf_type |= BUF_HT; - - bf->bf_flags = setup_tx_flags(sc, skb, txctl->txq); - - bf->bf_keytype = get_hw_crypto_keytype(skb); - if (bf->bf_keytype != ATH9K_KEY_TYPE_CLEAR) { - bf->bf_frmlen += tx_info->control.hw_key->icv_len; - bf->bf_keyix = tx_info->control.hw_key->hw_key_idx; - } else { - bf->bf_keyix = ATH9K_TXKEYIX_INVALID; - } - - if (ieee80211_is_data_qos(fc) && (sc->sc_flags & SC_OP_TXAGGR)) - assign_aggr_tid_seqno(skb, bf); - - bf->bf_mpdu = skb; - - bf->bf_dmacontext = dma_map_single(sc->dev, skb->data, - skb->len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(sc->dev, bf->bf_dmacontext))) { - bf->bf_mpdu = NULL; - kfree(tx_info_priv); - tx_info->rate_driver_data[0] = NULL; - DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error() on TX\n"); - return -ENOMEM; - } - - bf->bf_buf_addr = bf->bf_dmacontext; - - if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) { - bf->bf_isnullfunc = true; - sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED; - } else - bf->bf_isnullfunc = false; - - return 0; -} - -/* FIXME: tx power */ -static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf, - struct ath_tx_control *txctl) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ath_node *an = NULL; - struct list_head bf_head; - struct ath_desc *ds; - struct ath_atx_tid *tid; - struct ath_hw *ah = sc->sc_ah; - int frm_type; - __le16 fc; - - frm_type = get_hw_packet_type(skb); - fc = hdr->frame_control; - - INIT_LIST_HEAD(&bf_head); - list_add_tail(&bf->list, &bf_head); - - ds = bf->bf_desc; - ds->ds_link = 0; - ds->ds_data = bf->bf_buf_addr; - - ath9k_hw_set11n_txdesc(ah, ds, bf->bf_frmlen, frm_type, MAX_RATE_POWER, - bf->bf_keyix, bf->bf_keytype, bf->bf_flags); - - ath9k_hw_filltxdesc(ah, ds, - skb->len, /* segment length */ - true, /* first segment */ - true, /* last segment */ - ds); /* first descriptor */ - - spin_lock_bh(&txctl->txq->axq_lock); - - if (bf_isht(bf) && (sc->sc_flags & SC_OP_TXAGGR) && - tx_info->control.sta) { - an = (struct ath_node *)tx_info->control.sta->drv_priv; - tid = ATH_AN_2_TID(an, bf->bf_tidno); - - if (!ieee80211_is_data_qos(fc)) { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - goto tx_done; - } - - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) { - /* - * Try aggregation if it's a unicast data frame - * and the destination is HT capable. - */ - ath_tx_send_ampdu(sc, tid, &bf_head, txctl); - } else { - /* - * Send this frame as regular when ADDBA - * exchange is neither complete nor pending. - */ - ath_tx_send_ht_normal(sc, txctl->txq, - tid, &bf_head); - } - } else { - ath_tx_send_normal(sc, txctl->txq, &bf_head); - } - -tx_done: - spin_unlock_bh(&txctl->txq->axq_lock); -} - -/* Upon failure caller should free skb */ -int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, - struct ath_tx_control *txctl) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - struct ath_buf *bf; - int r; - - bf = ath_tx_get_buffer(sc); - if (!bf) { - DPRINTF(sc, ATH_DBG_XMIT, "TX buffers are full\n"); - return -1; - } - - r = ath_tx_setup_buffer(hw, bf, skb, txctl); - if (unlikely(r)) { - struct ath_txq *txq = txctl->txq; - - DPRINTF(sc, ATH_DBG_FATAL, "TX mem alloc failure\n"); - - /* upon ath_tx_processq() this TX queue will be resumed, we - * guarantee this will happen by knowing beforehand that - * we will at least have to run TX completionon one buffer - * on the queue */ - spin_lock_bh(&txq->axq_lock); - if (sc->tx.txq[txq->axq_qnum].axq_depth > 1) { - ieee80211_stop_queue(sc->hw, - skb_get_queue_mapping(skb)); - txq->stopped = 1; - } - spin_unlock_bh(&txq->axq_lock); - - spin_lock_bh(&sc->tx.txbuflock); - list_add_tail(&bf->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - - return r; - } - - ath_tx_start_dma(sc, bf, txctl); - - return 0; -} - -void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct ath_wiphy *aphy = hw->priv; - struct ath_softc *sc = aphy->sc; - int hdrlen, padsize; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ath_tx_control txctl; - - memset(&txctl, 0, sizeof(struct ath_tx_control)); - - /* - * As a temporary workaround, assign seq# here; this will likely need - * to be cleaned up to work better with Beacon transmission and virtual - * BSSes. - */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - sc->tx.seq_no += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); - } - - /* Add the padding after the header if this is not already done */ - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - if (hdrlen & 3) { - padsize = hdrlen % 4; - if (skb_headroom(skb) < padsize) { - DPRINTF(sc, ATH_DBG_XMIT, "TX CABQ padding failed\n"); - dev_kfree_skb_any(skb); - return; - } - skb_push(skb, padsize); - memmove(skb->data, skb->data + padsize, hdrlen); - } - - txctl.txq = sc->beacon.cabq; - - DPRINTF(sc, ATH_DBG_XMIT, "transmitting CABQ packet, skb: %p\n", skb); - - if (ath_tx_start(hw, skb, &txctl) != 0) { - DPRINTF(sc, ATH_DBG_XMIT, "CABQ TX failed\n"); - goto exit; - } - - return; -exit: - dev_kfree_skb_any(skb); -} - -/*****************/ -/* TX Completion */ -/*****************/ - -static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, - int tx_flags) -{ - struct ieee80211_hw *hw = sc->hw; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - int hdrlen, padsize; - int frame_type = ATH9K_NOT_INTERNAL; - - DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); - - if (tx_info_priv) { - hw = tx_info_priv->aphy->hw; - frame_type = tx_info_priv->frame_type; - } - - if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK || - tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED) { - kfree(tx_info_priv); - tx_info->rate_driver_data[0] = NULL; - } - - if (tx_flags & ATH_TX_BAR) - tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (!(tx_flags & (ATH_TX_ERROR | ATH_TX_XRETRY))) { - /* Frame was ACKed */ - tx_info->flags |= IEEE80211_TX_STAT_ACK; - } - - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - padsize = hdrlen & 3; - if (padsize && hdrlen >= 24) { - /* - * Remove MAC header padding before giving the frame back to - * mac80211. - */ - memmove(skb->data + padsize, skb->data, hdrlen); - skb_pull(skb, padsize); - } - - if (sc->sc_flags & SC_OP_WAIT_FOR_TX_ACK) { - sc->sc_flags &= ~SC_OP_WAIT_FOR_TX_ACK; - DPRINTF(sc, ATH_DBG_PS, "Going back to sleep after having " - "received TX status (0x%x)\n", - sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | - SC_OP_WAIT_FOR_CAB | - SC_OP_WAIT_FOR_PSPOLL_DATA | - SC_OP_WAIT_FOR_TX_ACK)); - } - - if (frame_type == ATH9K_NOT_INTERNAL) - ieee80211_tx_status(hw, skb); - else - ath9k_tx_status(hw, skb); -} - -static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, - struct ath_txq *txq, - struct list_head *bf_q, - int txok, int sendbar) -{ - struct sk_buff *skb = bf->bf_mpdu; - unsigned long flags; - int tx_flags = 0; - - if (sendbar) - tx_flags = ATH_TX_BAR; - - if (!txok) { - tx_flags |= ATH_TX_ERROR; - - if (bf_isxretried(bf)) - tx_flags |= ATH_TX_XRETRY; - } - - dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE); - ath_tx_complete(sc, skb, tx_flags); - ath_debug_stat_tx(sc, txq, bf); - - /* - * Return the list of ath_buf of this mpdu to free queue - */ - spin_lock_irqsave(&sc->tx.txbuflock, flags); - list_splice_tail_init(bf_q, &sc->tx.txbuf); - spin_unlock_irqrestore(&sc->tx.txbuflock, flags); -} - -static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf, - int txok) -{ - struct ath_buf *bf_last = bf->bf_lastbf; - struct ath_desc *ds = bf_last->bf_desc; - u16 seq_st = 0; - u32 ba[WME_BA_BMP_SIZE >> 5]; - int ba_index; - int nbad = 0; - int isaggr = 0; - - if (ds->ds_txstat.ts_flags == ATH9K_TX_SW_ABORTED) - return 0; - - isaggr = bf_isaggr(bf); - if (isaggr) { - seq_st = ATH_DS_BA_SEQ(ds); - memcpy(ba, ATH_DS_BA_BITMAP(ds), WME_BA_BMP_SIZE >> 3); - } - - while (bf) { - ba_index = ATH_BA_INDEX(seq_st, bf->bf_seqno); - if (!txok || (isaggr && !ATH_BA_ISSET(ba, ba_index))) - nbad++; - - bf = bf->bf_next; - } - - return nbad; -} - -static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, - int nbad, int txok, bool update_rc) -{ - struct sk_buff *skb = bf->bf_mpdu; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); - struct ieee80211_hw *hw = tx_info_priv->aphy->hw; - u8 i, tx_rateindex; - - if (txok) - tx_info->status.ack_signal = ds->ds_txstat.ts_rssi; - - tx_rateindex = ds->ds_txstat.ts_rateindex; - WARN_ON(tx_rateindex >= hw->max_rates); - - tx_info_priv->update_rc = update_rc; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) - tx_info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - - if ((ds->ds_txstat.ts_status & ATH9K_TXERR_FILT) == 0 && - (bf->bf_flags & ATH9K_TXDESC_NOACK) == 0 && update_rc) { - if (ieee80211_is_data(hdr->frame_control)) { - memcpy(&tx_info_priv->tx, &ds->ds_txstat, - sizeof(tx_info_priv->tx)); - tx_info_priv->n_frames = bf->bf_nframes; - tx_info_priv->n_bad_frames = nbad; - } - } - - for (i = tx_rateindex + 1; i < hw->max_rates; i++) - tx_info->status.rates[i].count = 0; - - tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; -} - -static void ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq) -{ - int qnum; - - spin_lock_bh(&txq->axq_lock); - if (txq->stopped && - sc->tx.txq[txq->axq_qnum].axq_depth <= (ATH_TXBUF - 20)) { - qnum = ath_get_mac80211_qnum(txq->axq_qnum, sc); - if (qnum != -1) { - ieee80211_wake_queue(sc->hw, qnum); - txq->stopped = 0; - } - } - spin_unlock_bh(&txq->axq_lock); -} - -static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) -{ - struct ath_hw *ah = sc->sc_ah; - struct ath_buf *bf, *lastbf, *bf_held = NULL; - struct list_head bf_head; - struct ath_desc *ds; - int txok; - int status; - - DPRINTF(sc, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n", - txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum), - txq->axq_link); - - for (;;) { - spin_lock_bh(&txq->axq_lock); - if (list_empty(&txq->axq_q)) { - txq->axq_link = NULL; - txq->axq_linkbuf = NULL; - spin_unlock_bh(&txq->axq_lock); - break; - } - bf = list_first_entry(&txq->axq_q, struct ath_buf, list); - - /* - * There is a race condition that a BH gets scheduled - * after sw writes TxE and before hw re-load the last - * descriptor to get the newly chained one. - * Software must keep the last DONE descriptor as a - * holding descriptor - software does so by marking - * it with the STALE flag. - */ - bf_held = NULL; - if (bf->bf_stale) { - bf_held = bf; - if (list_is_last(&bf_held->list, &txq->axq_q)) { - spin_unlock_bh(&txq->axq_lock); - break; - } else { - bf = list_entry(bf_held->list.next, - struct ath_buf, list); - } - } - - lastbf = bf->bf_lastbf; - ds = lastbf->bf_desc; - - status = ath9k_hw_txprocdesc(ah, ds); - if (status == -EINPROGRESS) { - spin_unlock_bh(&txq->axq_lock); - break; - } - if (bf->bf_desc == txq->axq_lastdsWithCTS) - txq->axq_lastdsWithCTS = NULL; - if (ds == txq->axq_gatingds) - txq->axq_gatingds = NULL; - - if (bf->bf_isnullfunc && - (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) { - if ((sc->sc_flags & SC_OP_PS_ENABLED)) - ath9k_enable_ps(sc); - else - sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED; - } - - /* - * Remove ath_buf's of the same transmit unit from txq, - * however leave the last descriptor back as the holding - * descriptor for hw. - */ - lastbf->bf_stale = true; - INIT_LIST_HEAD(&bf_head); - if (!list_is_singular(&lastbf->list)) - list_cut_position(&bf_head, - &txq->axq_q, lastbf->list.prev); - - txq->axq_depth--; - if (bf_isaggr(bf)) - txq->axq_aggr_depth--; - - txok = !(ds->ds_txstat.ts_status & ATH9K_TXERR_MASK); - txq->axq_tx_inprogress = false; - spin_unlock_bh(&txq->axq_lock); - - if (bf_held) { - spin_lock_bh(&sc->tx.txbuflock); - list_move_tail(&bf_held->list, &sc->tx.txbuf); - spin_unlock_bh(&sc->tx.txbuflock); - } - - if (!bf_isampdu(bf)) { - /* - * This frame is sent out as a single frame. - * Use hardware retry status for this frame. - */ - bf->bf_retries = ds->ds_txstat.ts_longretry; - if (ds->ds_txstat.ts_status & ATH9K_TXERR_XRETRY) - bf->bf_state.bf_type |= BUF_XRETRY; - ath_tx_rc_status(bf, ds, 0, txok, true); - } - - if (bf_isampdu(bf)) - ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok); - else - ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0); - - ath_wake_mac80211_queue(sc, txq); - - spin_lock_bh(&txq->axq_lock); - if (sc->sc_flags & SC_OP_TXAGGR) - ath_txq_schedule(sc, txq); - spin_unlock_bh(&txq->axq_lock); - } -} - -static void ath_tx_complete_poll_work(struct work_struct *work) -{ - struct ath_softc *sc = container_of(work, struct ath_softc, - tx_complete_work.work); - struct ath_txq *txq; - int i; - bool needreset = false; - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - spin_lock_bh(&txq->axq_lock); - if (txq->axq_depth) { - if (txq->axq_tx_inprogress) { - needreset = true; - spin_unlock_bh(&txq->axq_lock); - break; - } else { - txq->axq_tx_inprogress = true; - } - } - spin_unlock_bh(&txq->axq_lock); - } - - if (needreset) { - DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n"); - ath9k_ps_wakeup(sc); - ath_reset(sc, false); - ath9k_ps_restore(sc); - } - - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, - msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT)); -} - - - -void ath_tx_tasklet(struct ath_softc *sc) -{ - int i; - u32 qcumask = ((1 << ATH9K_NUM_TX_QUEUES) - 1); - - ath9k_hw_gettxintrtxqs(sc->sc_ah, &qcumask); - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i) && (qcumask & (1 << i))) - ath_tx_processq(sc, &sc->tx.txq[i]); - } -} - -/*****************/ -/* Init, Cleanup */ -/*****************/ - -int ath_tx_init(struct ath_softc *sc, int nbufs) -{ - int error = 0; - - spin_lock_init(&sc->tx.txbuflock); - - error = ath_descdma_setup(sc, &sc->tx.txdma, &sc->tx.txbuf, - "tx", nbufs, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate tx descriptors: %d\n", error); - goto err; - } - - error = ath_descdma_setup(sc, &sc->beacon.bdma, &sc->beacon.bbuf, - "beacon", ATH_BCBUF, 1); - if (error != 0) { - DPRINTF(sc, ATH_DBG_FATAL, - "Failed to allocate beacon descriptors: %d\n", error); - goto err; - } - - INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work); - -err: - if (error != 0) - ath_tx_cleanup(sc); - - return error; -} - -void ath_tx_cleanup(struct ath_softc *sc) -{ - if (sc->beacon.bdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->beacon.bdma, &sc->beacon.bbuf); - - if (sc->tx.txdma.dd_desc_len != 0) - ath_descdma_cleanup(sc, &sc->tx.txdma, &sc->tx.txbuf); -} - -void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) -{ - struct ath_atx_tid *tid; - struct ath_atx_ac *ac; - int tidno, acno; - - for (tidno = 0, tid = &an->tid[tidno]; - tidno < WME_NUM_TID; - tidno++, tid++) { - tid->an = an; - tid->tidno = tidno; - tid->seq_start = tid->seq_next = 0; - tid->baw_size = WME_MAX_BA; - tid->baw_head = tid->baw_tail = 0; - tid->sched = false; - tid->paused = false; - tid->state &= ~AGGR_CLEANUP; - INIT_LIST_HEAD(&tid->buf_q); - acno = TID_TO_WME_AC(tidno); - tid->ac = &an->ac[acno]; - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_ADDBA_PROGRESS; - } - - for (acno = 0, ac = &an->ac[acno]; - acno < WME_NUM_AC; acno++, ac++) { - ac->sched = false; - INIT_LIST_HEAD(&ac->tid_q); - - switch (acno) { - case WME_AC_BE: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE); - break; - case WME_AC_BK: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BK); - break; - case WME_AC_VI: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VI); - break; - case WME_AC_VO: - ac->qnum = ath_tx_get_qnum(sc, - ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_VO); - break; - } - } -} - -void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) -{ - int i; - struct ath_atx_ac *ac, *ac_tmp; - struct ath_atx_tid *tid, *tid_tmp; - struct ath_txq *txq; - - for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { - if (ATH_TXQ_SETUP(sc, i)) { - txq = &sc->tx.txq[i]; - - spin_lock(&txq->axq_lock); - - list_for_each_entry_safe(ac, - ac_tmp, &txq->axq_acq, list) { - tid = list_first_entry(&ac->tid_q, - struct ath_atx_tid, list); - if (tid && tid->an != an) - continue; - list_del(&ac->list); - ac->sched = false; - - list_for_each_entry_safe(tid, - tid_tmp, &ac->tid_q, list) { - list_del(&tid->list); - tid->sched = false; - ath_tid_drain(sc, txq, tid); - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_CLEANUP; - } - } - - spin_unlock(&txq->axq_lock); - } - } -} diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c deleted file mode 100644 index 487193f1de1a..000000000000 --- a/drivers/net/wireless/ath/main.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include - -#include "ath.h" - -MODULE_AUTHOR("Atheros Communications"); -MODULE_DESCRIPTION("Shared library for Atheros wireless LAN cards."); -MODULE_LICENSE("Dual BSD/GPL"); - -struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, - u32 len, - gfp_t gfp_mask) -{ - struct sk_buff *skb; - u32 off; - - /* - * Cache-line-align. This is important (for the - * 5210 at least) as not doing so causes bogus data - * in rx'd frames. - */ - - /* Note: the kernel can allocate a value greater than - * what we ask it to give us. We really only need 4 KB as that - * is this hardware supports and in fact we need at least 3849 - * as that is the MAX AMSDU size this hardware supports. - * Unfortunately this means we may get 8 KB here from the - * kernel... and that is actually what is observed on some - * systems :( */ - skb = __dev_alloc_skb(len + common->cachelsz - 1, gfp_mask); - if (skb != NULL) { - off = ((unsigned long) skb->data) % common->cachelsz; - if (off != 0) - skb_reserve(skb, common->cachelsz - off); - } else { - printk(KERN_ERR "skbuff alloc of size %u failed\n", len); - return NULL; - } - - return skb; -} -EXPORT_SYMBOL(ath_rxbuf_alloc); diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c deleted file mode 100644 index 077bcc142cde..000000000000 --- a/drivers/net/wireless/ath/regd.c +++ /dev/null @@ -1,590 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include -#include -#include -#include -#include "regd.h" -#include "regd_common.h" - -/* - * This is a set of common rules used by our world regulatory domains. - * We have 12 world regulatory domains. To save space we consolidate - * the regulatory domains in 5 structures by frequency and change - * the flags on our reg_notifier() on a case by case basis. - */ - -/* Only these channels all allow active scan on all world regulatory domains */ -#define ATH9K_2GHZ_CH01_11 REG_RULE(2412-10, 2462+10, 40, 0, 20, 0) - -/* We enable active scan on these a case by case basis by regulatory domain */ -#define ATH9K_2GHZ_CH12_13 REG_RULE(2467-10, 2472+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN) -#define ATH9K_2GHZ_CH14 REG_RULE(2484-10, 2484+10, 40, 0, 20,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM) - -/* We allow IBSS on these on a case by case basis by regulatory domain */ -#define ATH9K_5GHZ_5150_5350 REG_RULE(5150-10, 5350+10, 40, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -#define ATH9K_5GHZ_5470_5850 REG_RULE(5470-10, 5850+10, 40, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) -#define ATH9K_5GHZ_5725_5850 REG_RULE(5725-10, 5850+10, 40, 0, 30,\ - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS) - -#define ATH9K_2GHZ_ALL ATH9K_2GHZ_CH01_11, \ - ATH9K_2GHZ_CH12_13, \ - ATH9K_2GHZ_CH14 - -#define ATH9K_5GHZ_ALL ATH9K_5GHZ_5150_5350, \ - ATH9K_5GHZ_5470_5850 -/* This one skips what we call "mid band" */ -#define ATH9K_5GHZ_NO_MIDBAND ATH9K_5GHZ_5150_5350, \ - ATH9K_5GHZ_5725_5850 - -/* Can be used for: - * 0x60, 0x61, 0x62 */ -static const struct ieee80211_regdomain ath_world_regdom_60_61_62 = { - .n_reg_rules = 5, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_ALL, - ATH9K_5GHZ_ALL, - } -}; - -/* Can be used by 0x63 and 0x65 */ -static const struct ieee80211_regdomain ath_world_regdom_63_65 = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_2GHZ_CH12_13, - ATH9K_5GHZ_NO_MIDBAND, - } -}; - -/* Can be used by 0x64 only */ -static const struct ieee80211_regdomain ath_world_regdom_64 = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_5GHZ_NO_MIDBAND, - } -}; - -/* Can be used by 0x66 and 0x69 */ -static const struct ieee80211_regdomain ath_world_regdom_66_69 = { - .n_reg_rules = 3, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_5GHZ_ALL, - } -}; - -/* Can be used by 0x67, 0x6A and 0x68 */ -static const struct ieee80211_regdomain ath_world_regdom_67_68_6A = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - ATH9K_2GHZ_CH01_11, - ATH9K_2GHZ_CH12_13, - ATH9K_5GHZ_ALL, - } -}; - -static inline bool is_wwr_sku(u16 regd) -{ - return ((regd & WORLD_SKU_MASK) == WORLD_SKU_PREFIX) || - (regd == WORLD); -} - -static u16 ath_regd_get_eepromRD(struct ath_regulatory *reg) -{ - return reg->current_rd & ~WORLDWIDE_ROAMING_FLAG; -} - -bool ath_is_world_regd(struct ath_regulatory *reg) -{ - return is_wwr_sku(ath_regd_get_eepromRD(reg)); -} -EXPORT_SYMBOL(ath_is_world_regd); - -static const struct ieee80211_regdomain *ath_default_world_regdomain(void) -{ - /* this is the most restrictive */ - return &ath_world_regdom_64; -} - -static const struct -ieee80211_regdomain *ath_world_regdomain(struct ath_regulatory *reg) -{ - switch (reg->regpair->regDmnEnum) { - case 0x60: - case 0x61: - case 0x62: - return &ath_world_regdom_60_61_62; - case 0x63: - case 0x65: - return &ath_world_regdom_63_65; - case 0x64: - return &ath_world_regdom_64; - case 0x66: - case 0x69: - return &ath_world_regdom_66_69; - case 0x67: - case 0x68: - case 0x6A: - return &ath_world_regdom_67_68_6A; - default: - WARN_ON(1); - return ath_default_world_regdomain(); - } -} - -/* Frequency is one where radar detection is required */ -static bool ath_is_radar_freq(u16 center_freq) -{ - return (center_freq >= 5260 && center_freq <= 5700); -} - -/* - * N.B: These exception rules do not apply radar freqs. - * - * - We enable adhoc (or beaconing) if allowed by 11d - * - We enable active scan if the channel is allowed by 11d - * - If no country IE has been processed and a we determine we have - * received a beacon on a channel we can enable active scan and - * adhoc (or beaconing). - */ -static void -ath_reg_apply_beaconing_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) -{ - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - const struct ieee80211_reg_rule *reg_rule; - struct ieee80211_channel *ch; - unsigned int i; - u32 bandwidth = 0; - int r; - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - - if (!wiphy->bands[band]) - continue; - - sband = wiphy->bands[band]; - - for (i = 0; i < sband->n_channels; i++) { - - ch = &sband->channels[i]; - - if (ath_is_radar_freq(ch->center_freq) || - (ch->flags & IEEE80211_CHAN_RADAR)) - continue; - - if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) { - r = freq_reg_info(wiphy, - ch->center_freq, - bandwidth, - ®_rule); - if (r) - continue; - /* - * If 11d had a rule for this channel ensure - * we enable adhoc/beaconing if it allows us to - * use it. Note that we would have disabled it - * by applying our static world regdomain by - * default during init, prior to calling our - * regulatory_hint(). - */ - if (!(reg_rule->flags & - NL80211_RRF_NO_IBSS)) - ch->flags &= - ~IEEE80211_CHAN_NO_IBSS; - if (!(reg_rule->flags & - NL80211_RRF_PASSIVE_SCAN)) - ch->flags &= - ~IEEE80211_CHAN_PASSIVE_SCAN; - } else { - if (ch->beacon_found) - ch->flags &= ~(IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN); - } - } - } - -} - -/* Allows active scan scan on Ch 12 and 13 */ -static void -ath_reg_apply_active_scan_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - const struct ieee80211_reg_rule *reg_rule; - u32 bandwidth = 0; - int r; - - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; - - /* - * If no country IE has been received always enable active scan - * on these channels. This is only done for specific regulatory SKUs - */ - if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) { - ch = &sband->channels[11]; /* CH 12 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - ch = &sband->channels[12]; /* CH 13 */ - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - return; - } - - /* - * If a country IE has been recieved check its rule for this - * channel first before enabling active scan. The passive scan - * would have been enforced by the initial processing of our - * custom regulatory domain. - */ - - ch = &sband->channels[11]; /* CH 12 */ - r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); - if (!r) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - } - - ch = &sband->channels[12]; /* CH 13 */ - r = freq_reg_info(wiphy, ch->center_freq, bandwidth, ®_rule); - if (!r) { - if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN)) - if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN) - ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN; - } -} - -/* Always apply Radar/DFS rules on freq range 5260 MHz - 5700 MHz */ -static void ath_reg_apply_radar_flags(struct wiphy *wiphy) -{ - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - unsigned int i; - - if (!wiphy->bands[IEEE80211_BAND_5GHZ]) - return; - - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - if (!ath_is_radar_freq(ch->center_freq)) - continue; - /* We always enable radar detection/DFS on this - * frequency range. Additionally we also apply on - * this frequency range: - * - If STA mode does not yet have DFS supports disable - * active scanning - * - If adhoc mode does not support DFS yet then - * disable adhoc in the frequency. - * - If AP mode does not yet support radar detection/DFS - * do not allow AP mode - */ - if (!(ch->flags & IEEE80211_CHAN_DISABLED)) - ch->flags |= IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS | - IEEE80211_CHAN_PASSIVE_SCAN; - } -} - -static void ath_reg_apply_world_flags(struct wiphy *wiphy, - enum nl80211_reg_initiator initiator, - struct ath_regulatory *reg) -{ - switch (reg->regpair->regDmnEnum) { - case 0x60: - case 0x63: - case 0x66: - case 0x67: - ath_reg_apply_beaconing_flags(wiphy, initiator); - break; - case 0x68: - ath_reg_apply_beaconing_flags(wiphy, initiator); - ath_reg_apply_active_scan_flags(wiphy, initiator); - break; - } - return; -} - -int ath_reg_notifier_apply(struct wiphy *wiphy, - struct regulatory_request *request, - struct ath_regulatory *reg) -{ - /* We always apply this */ - ath_reg_apply_radar_flags(wiphy); - - switch (request->initiator) { - case NL80211_REGDOM_SET_BY_DRIVER: - case NL80211_REGDOM_SET_BY_CORE: - case NL80211_REGDOM_SET_BY_USER: - break; - case NL80211_REGDOM_SET_BY_COUNTRY_IE: - if (ath_is_world_regd(reg)) - ath_reg_apply_world_flags(wiphy, request->initiator, - reg); - break; - } - - return 0; -} -EXPORT_SYMBOL(ath_reg_notifier_apply); - -static bool ath_regd_is_eeprom_valid(struct ath_regulatory *reg) -{ - u16 rd = ath_regd_get_eepromRD(reg); - int i; - - if (rd & COUNTRY_ERD_FLAG) { - /* EEPROM value is a country code */ - u16 cc = rd & ~COUNTRY_ERD_FLAG; - printk(KERN_DEBUG - "ath: EEPROM indicates we should expect " - "a country code\n"); - for (i = 0; i < ARRAY_SIZE(allCountries); i++) - if (allCountries[i].countryCode == cc) - return true; - } else { - /* EEPROM value is a regpair value */ - if (rd != CTRY_DEFAULT) - printk(KERN_DEBUG "ath: EEPROM indicates we " - "should expect a direct regpair map\n"); - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) - if (regDomainPairs[i].regDmnEnum == rd) - return true; - } - printk(KERN_DEBUG - "ath: invalid regulatory domain/country code 0x%x\n", rd); - return false; -} - -/* EEPROM country code to regpair mapping */ -static struct country_code_to_enum_rd* -ath_regd_find_country(u16 countryCode) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].countryCode == countryCode) - return &allCountries[i]; - } - return NULL; -} - -/* EEPROM rd code to regpair mapping */ -static struct country_code_to_enum_rd* -ath_regd_find_country_by_rd(int regdmn) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(allCountries); i++) { - if (allCountries[i].regDmnEnum == regdmn) - return &allCountries[i]; - } - return NULL; -} - -/* Returns the map of the EEPROM set RD to a country code */ -static u16 ath_regd_get_default_country(u16 rd) -{ - if (rd & COUNTRY_ERD_FLAG) { - struct country_code_to_enum_rd *country = NULL; - u16 cc = rd & ~COUNTRY_ERD_FLAG; - - country = ath_regd_find_country(cc); - if (country != NULL) - return cc; - } - - return CTRY_DEFAULT; -} - -static struct reg_dmn_pair_mapping* -ath_get_regpair(int regdmn) -{ - int i; - - if (regdmn == NO_ENUMRD) - return NULL; - for (i = 0; i < ARRAY_SIZE(regDomainPairs); i++) { - if (regDomainPairs[i].regDmnEnum == regdmn) - return ®DomainPairs[i]; - } - return NULL; -} - -static int -ath_regd_init_wiphy(struct ath_regulatory *reg, - struct wiphy *wiphy, - int (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request)) -{ - const struct ieee80211_regdomain *regd; - - wiphy->reg_notifier = reg_notifier; - wiphy->strict_regulatory = true; - - if (ath_is_world_regd(reg)) { - /* - * Anything applied here (prior to wiphy registration) gets - * saved on the wiphy orig_* parameters - */ - regd = ath_world_regdomain(reg); - wiphy->custom_regulatory = true; - wiphy->strict_regulatory = false; - } else { - /* - * This gets applied in the case of the absense of CRDA, - * it's our own custom world regulatory domain, similar to - * cfg80211's but we enable passive scanning. - */ - regd = ath_default_world_regdomain(); - } - wiphy_apply_custom_regulatory(wiphy, regd); - ath_reg_apply_radar_flags(wiphy); - ath_reg_apply_world_flags(wiphy, NL80211_REGDOM_SET_BY_DRIVER, reg); - return 0; -} - -/* - * Some users have reported their EEPROM programmed with - * 0x8000 set, this is not a supported regulatory domain - * but since we have more than one user with it we need - * a solution for them. We default to 0x64, which is the - * default Atheros world regulatory domain. - */ -static void ath_regd_sanitize(struct ath_regulatory *reg) -{ - if (reg->current_rd != COUNTRY_ERD_FLAG) - return; - printk(KERN_DEBUG "ath: EEPROM regdomain sanitized\n"); - reg->current_rd = 0x64; -} - -int -ath_regd_init(struct ath_regulatory *reg, - struct wiphy *wiphy, - int (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request)) -{ - struct country_code_to_enum_rd *country = NULL; - u16 regdmn; - - if (!reg) - return -EINVAL; - - ath_regd_sanitize(reg); - - printk(KERN_DEBUG "ath: EEPROM regdomain: 0x%0x\n", reg->current_rd); - - if (!ath_regd_is_eeprom_valid(reg)) { - printk(KERN_ERR "ath: Invalid EEPROM contents\n"); - return -EINVAL; - } - - regdmn = ath_regd_get_eepromRD(reg); - reg->country_code = ath_regd_get_default_country(regdmn); - - if (reg->country_code == CTRY_DEFAULT && - regdmn == CTRY_DEFAULT) { - printk(KERN_DEBUG "ath: EEPROM indicates default " - "country code should be used\n"); - reg->country_code = CTRY_UNITED_STATES; - } - - if (reg->country_code == CTRY_DEFAULT) { - country = NULL; - } else { - printk(KERN_DEBUG "ath: doing EEPROM country->regdmn " - "map search\n"); - country = ath_regd_find_country(reg->country_code); - if (country == NULL) { - printk(KERN_DEBUG - "ath: no valid country maps found for " - "country code: 0x%0x\n", - reg->country_code); - return -EINVAL; - } else { - regdmn = country->regDmnEnum; - printk(KERN_DEBUG "ath: country maps to " - "regdmn code: 0x%0x\n", - regdmn); - } - } - - reg->regpair = ath_get_regpair(regdmn); - - if (!reg->regpair) { - printk(KERN_DEBUG "ath: " - "No regulatory domain pair found, cannot continue\n"); - return -EINVAL; - } - - if (!country) - country = ath_regd_find_country_by_rd(regdmn); - - if (country) { - reg->alpha2[0] = country->isoName[0]; - reg->alpha2[1] = country->isoName[1]; - } else { - reg->alpha2[0] = '0'; - reg->alpha2[1] = '0'; - } - - printk(KERN_DEBUG "ath: Country alpha2 being used: %c%c\n", - reg->alpha2[0], reg->alpha2[1]); - printk(KERN_DEBUG "ath: Regpair used: 0x%0x\n", - reg->regpair->regDmnEnum); - - ath_regd_init_wiphy(reg, wiphy, reg_notifier); - return 0; -} -EXPORT_SYMBOL(ath_regd_init); - -u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, - enum ieee80211_band band) -{ - if (!reg->regpair || - (reg->country_code == CTRY_DEFAULT && - is_wwr_sku(ath_regd_get_eepromRD(reg)))) { - return SD_NO_CTL; - } - - switch (band) { - case IEEE80211_BAND_2GHZ: - return reg->regpair->reg_2ghz_ctl; - case IEEE80211_BAND_5GHZ: - return reg->regpair->reg_5ghz_ctl; - default: - return NO_CTL; - } -} -EXPORT_SYMBOL(ath_regd_get_band_ctl); diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h deleted file mode 100644 index 21cf5215f6f6..000000000000 --- a/drivers/net/wireless/ath/regd.h +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef REGD_H -#define REGD_H - -#include -#include - -#include "ath.h" - -enum ctl_group { - CTL_FCC = 0x10, - CTL_MKK = 0x40, - CTL_ETSI = 0x30, -}; - -#define NO_CTL 0xff -#define SD_NO_CTL 0xE0 -#define NO_CTL 0xff -#define CTL_11A 0 -#define CTL_11B 1 -#define CTL_11G 2 -#define CTL_2GHT20 5 -#define CTL_5GHT20 6 -#define CTL_2GHT40 7 -#define CTL_5GHT40 8 - -#define CTRY_DEBUG 0x1ff -#define CTRY_DEFAULT 0 - -#define COUNTRY_ERD_FLAG 0x8000 -#define WORLDWIDE_ROAMING_FLAG 0x4000 - -#define MULTI_DOMAIN_MASK 0xFF00 - -#define WORLD_SKU_MASK 0x00F0 -#define WORLD_SKU_PREFIX 0x0060 - -#define CHANNEL_HALF_BW 10 -#define CHANNEL_QUARTER_BW 5 - -struct country_code_to_enum_rd { - u16 countryCode; - u16 regDmnEnum; - const char *isoName; -}; - -enum CountryCode { - CTRY_ALBANIA = 8, - CTRY_ALGERIA = 12, - CTRY_ARGENTINA = 32, - CTRY_ARMENIA = 51, - CTRY_AUSTRALIA = 36, - CTRY_AUSTRIA = 40, - CTRY_AZERBAIJAN = 31, - CTRY_BAHRAIN = 48, - CTRY_BELARUS = 112, - CTRY_BELGIUM = 56, - CTRY_BELIZE = 84, - CTRY_BOLIVIA = 68, - CTRY_BOSNIA_HERZ = 70, - CTRY_BRAZIL = 76, - CTRY_BRUNEI_DARUSSALAM = 96, - CTRY_BULGARIA = 100, - CTRY_CANADA = 124, - CTRY_CHILE = 152, - CTRY_CHINA = 156, - CTRY_COLOMBIA = 170, - CTRY_COSTA_RICA = 188, - CTRY_CROATIA = 191, - CTRY_CYPRUS = 196, - CTRY_CZECH = 203, - CTRY_DENMARK = 208, - CTRY_DOMINICAN_REPUBLIC = 214, - CTRY_ECUADOR = 218, - CTRY_EGYPT = 818, - CTRY_EL_SALVADOR = 222, - CTRY_ESTONIA = 233, - CTRY_FAEROE_ISLANDS = 234, - CTRY_FINLAND = 246, - CTRY_FRANCE = 250, - CTRY_GEORGIA = 268, - CTRY_GERMANY = 276, - CTRY_GREECE = 300, - CTRY_GUATEMALA = 320, - CTRY_HONDURAS = 340, - CTRY_HONG_KONG = 344, - CTRY_HUNGARY = 348, - CTRY_ICELAND = 352, - CTRY_INDIA = 356, - CTRY_INDONESIA = 360, - CTRY_IRAN = 364, - CTRY_IRAQ = 368, - CTRY_IRELAND = 372, - CTRY_ISRAEL = 376, - CTRY_ITALY = 380, - CTRY_JAMAICA = 388, - CTRY_JAPAN = 392, - CTRY_JORDAN = 400, - CTRY_KAZAKHSTAN = 398, - CTRY_KENYA = 404, - CTRY_KOREA_NORTH = 408, - CTRY_KOREA_ROC = 410, - CTRY_KOREA_ROC2 = 411, - CTRY_KOREA_ROC3 = 412, - CTRY_KUWAIT = 414, - CTRY_LATVIA = 428, - CTRY_LEBANON = 422, - CTRY_LIBYA = 434, - CTRY_LIECHTENSTEIN = 438, - CTRY_LITHUANIA = 440, - CTRY_LUXEMBOURG = 442, - CTRY_MACAU = 446, - CTRY_MACEDONIA = 807, - CTRY_MALAYSIA = 458, - CTRY_MALTA = 470, - CTRY_MEXICO = 484, - CTRY_MONACO = 492, - CTRY_MOROCCO = 504, - CTRY_NEPAL = 524, - CTRY_NETHERLANDS = 528, - CTRY_NETHERLANDS_ANTILLES = 530, - CTRY_NEW_ZEALAND = 554, - CTRY_NICARAGUA = 558, - CTRY_NORWAY = 578, - CTRY_OMAN = 512, - CTRY_PAKISTAN = 586, - CTRY_PANAMA = 591, - CTRY_PAPUA_NEW_GUINEA = 598, - CTRY_PARAGUAY = 600, - CTRY_PERU = 604, - CTRY_PHILIPPINES = 608, - CTRY_POLAND = 616, - CTRY_PORTUGAL = 620, - CTRY_PUERTO_RICO = 630, - CTRY_QATAR = 634, - CTRY_ROMANIA = 642, - CTRY_RUSSIA = 643, - CTRY_SAUDI_ARABIA = 682, - CTRY_SERBIA_MONTENEGRO = 891, - CTRY_SINGAPORE = 702, - CTRY_SLOVAKIA = 703, - CTRY_SLOVENIA = 705, - CTRY_SOUTH_AFRICA = 710, - CTRY_SPAIN = 724, - CTRY_SRI_LANKA = 144, - CTRY_SWEDEN = 752, - CTRY_SWITZERLAND = 756, - CTRY_SYRIA = 760, - CTRY_TAIWAN = 158, - CTRY_THAILAND = 764, - CTRY_TRINIDAD_Y_TOBAGO = 780, - CTRY_TUNISIA = 788, - CTRY_TURKEY = 792, - CTRY_UAE = 784, - CTRY_UKRAINE = 804, - CTRY_UNITED_KINGDOM = 826, - CTRY_UNITED_STATES = 840, - CTRY_UNITED_STATES_FCC49 = 842, - CTRY_URUGUAY = 858, - CTRY_UZBEKISTAN = 860, - CTRY_VENEZUELA = 862, - CTRY_VIET_NAM = 704, - CTRY_YEMEN = 887, - CTRY_ZIMBABWE = 716, - CTRY_JAPAN1 = 393, - CTRY_JAPAN2 = 394, - CTRY_JAPAN3 = 395, - CTRY_JAPAN4 = 396, - CTRY_JAPAN5 = 397, - CTRY_JAPAN6 = 4006, - CTRY_JAPAN7 = 4007, - CTRY_JAPAN8 = 4008, - CTRY_JAPAN9 = 4009, - CTRY_JAPAN10 = 4010, - CTRY_JAPAN11 = 4011, - CTRY_JAPAN12 = 4012, - CTRY_JAPAN13 = 4013, - CTRY_JAPAN14 = 4014, - CTRY_JAPAN15 = 4015, - CTRY_JAPAN16 = 4016, - CTRY_JAPAN17 = 4017, - CTRY_JAPAN18 = 4018, - CTRY_JAPAN19 = 4019, - CTRY_JAPAN20 = 4020, - CTRY_JAPAN21 = 4021, - CTRY_JAPAN22 = 4022, - CTRY_JAPAN23 = 4023, - CTRY_JAPAN24 = 4024, - CTRY_JAPAN25 = 4025, - CTRY_JAPAN26 = 4026, - CTRY_JAPAN27 = 4027, - CTRY_JAPAN28 = 4028, - CTRY_JAPAN29 = 4029, - CTRY_JAPAN30 = 4030, - CTRY_JAPAN31 = 4031, - CTRY_JAPAN32 = 4032, - CTRY_JAPAN33 = 4033, - CTRY_JAPAN34 = 4034, - CTRY_JAPAN35 = 4035, - CTRY_JAPAN36 = 4036, - CTRY_JAPAN37 = 4037, - CTRY_JAPAN38 = 4038, - CTRY_JAPAN39 = 4039, - CTRY_JAPAN40 = 4040, - CTRY_JAPAN41 = 4041, - CTRY_JAPAN42 = 4042, - CTRY_JAPAN43 = 4043, - CTRY_JAPAN44 = 4044, - CTRY_JAPAN45 = 4045, - CTRY_JAPAN46 = 4046, - CTRY_JAPAN47 = 4047, - CTRY_JAPAN48 = 4048, - CTRY_JAPAN49 = 4049, - CTRY_JAPAN50 = 4050, - CTRY_JAPAN51 = 4051, - CTRY_JAPAN52 = 4052, - CTRY_JAPAN53 = 4053, - CTRY_JAPAN54 = 4054, - CTRY_JAPAN55 = 4055, - CTRY_JAPAN56 = 4056, - CTRY_JAPAN57 = 4057, - CTRY_JAPAN58 = 4058, - CTRY_JAPAN59 = 4059, - CTRY_AUSTRALIA2 = 5000, - CTRY_CANADA2 = 5001, - CTRY_BELGIUM2 = 5002 -}; - -bool ath_is_world_regd(struct ath_regulatory *reg); -int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy, - int (*reg_notifier)(struct wiphy *wiphy, - struct regulatory_request *request)); -u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, - enum ieee80211_band band); -int ath_reg_notifier_apply(struct wiphy *wiphy, - struct regulatory_request *request, - struct ath_regulatory *reg); - -#endif diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h deleted file mode 100644 index 9847af72208c..000000000000 --- a/drivers/net/wireless/ath/regd_common.h +++ /dev/null @@ -1,467 +0,0 @@ -/* - * Copyright (c) 2008-2009 Atheros Communications Inc. - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef REGD_COMMON_H -#define REGD_COMMON_H - -enum EnumRd { - NO_ENUMRD = 0x00, - NULL1_WORLD = 0x03, - NULL1_ETSIB = 0x07, - NULL1_ETSIC = 0x08, - FCC1_FCCA = 0x10, - FCC1_WORLD = 0x11, - FCC4_FCCA = 0x12, - FCC5_FCCA = 0x13, - FCC6_FCCA = 0x14, - - FCC2_FCCA = 0x20, - FCC2_WORLD = 0x21, - FCC2_ETSIC = 0x22, - FCC6_WORLD = 0x23, - FRANCE_RES = 0x31, - FCC3_FCCA = 0x3A, - FCC3_WORLD = 0x3B, - - ETSI1_WORLD = 0x37, - ETSI3_ETSIA = 0x32, - ETSI2_WORLD = 0x35, - ETSI3_WORLD = 0x36, - ETSI4_WORLD = 0x30, - ETSI4_ETSIC = 0x38, - ETSI5_WORLD = 0x39, - ETSI6_WORLD = 0x34, - ETSI_RESERVED = 0x33, - - MKK1_MKKA = 0x40, - MKK1_MKKB = 0x41, - APL4_WORLD = 0x42, - MKK2_MKKA = 0x43, - APL_RESERVED = 0x44, - APL2_WORLD = 0x45, - APL2_APLC = 0x46, - APL3_WORLD = 0x47, - MKK1_FCCA = 0x48, - APL2_APLD = 0x49, - MKK1_MKKA1 = 0x4A, - MKK1_MKKA2 = 0x4B, - MKK1_MKKC = 0x4C, - - APL3_FCCA = 0x50, - APL1_WORLD = 0x52, - APL1_FCCA = 0x53, - APL1_APLA = 0x54, - APL1_ETSIC = 0x55, - APL2_ETSIC = 0x56, - APL5_WORLD = 0x58, - APL6_WORLD = 0x5B, - APL7_FCCA = 0x5C, - APL8_WORLD = 0x5D, - APL9_WORLD = 0x5E, - - WOR0_WORLD = 0x60, - WOR1_WORLD = 0x61, - WOR2_WORLD = 0x62, - WOR3_WORLD = 0x63, - WOR4_WORLD = 0x64, - WOR5_ETSIC = 0x65, - - WOR01_WORLD = 0x66, - WOR02_WORLD = 0x67, - EU1_WORLD = 0x68, - - WOR9_WORLD = 0x69, - WORA_WORLD = 0x6A, - WORB_WORLD = 0x6B, - - MKK3_MKKB = 0x80, - MKK3_MKKA2 = 0x81, - MKK3_MKKC = 0x82, - - MKK4_MKKB = 0x83, - MKK4_MKKA2 = 0x84, - MKK4_MKKC = 0x85, - - MKK5_MKKB = 0x86, - MKK5_MKKA2 = 0x87, - MKK5_MKKC = 0x88, - - MKK6_MKKB = 0x89, - MKK6_MKKA2 = 0x8A, - MKK6_MKKC = 0x8B, - - MKK7_MKKB = 0x8C, - MKK7_MKKA2 = 0x8D, - MKK7_MKKC = 0x8E, - - MKK8_MKKB = 0x8F, - MKK8_MKKA2 = 0x90, - MKK8_MKKC = 0x91, - - MKK14_MKKA1 = 0x92, - MKK15_MKKA1 = 0x93, - - MKK10_FCCA = 0xD0, - MKK10_MKKA1 = 0xD1, - MKK10_MKKC = 0xD2, - MKK10_MKKA2 = 0xD3, - - MKK11_MKKA = 0xD4, - MKK11_FCCA = 0xD5, - MKK11_MKKA1 = 0xD6, - MKK11_MKKC = 0xD7, - MKK11_MKKA2 = 0xD8, - - MKK12_MKKA = 0xD9, - MKK12_FCCA = 0xDA, - MKK12_MKKA1 = 0xDB, - MKK12_MKKC = 0xDC, - MKK12_MKKA2 = 0xDD, - - MKK13_MKKB = 0xDE, - - MKK3_MKKA = 0xF0, - MKK3_MKKA1 = 0xF1, - MKK3_FCCA = 0xF2, - MKK4_MKKA = 0xF3, - MKK4_MKKA1 = 0xF4, - MKK4_FCCA = 0xF5, - MKK9_MKKA = 0xF6, - MKK10_MKKA = 0xF7, - MKK6_MKKA1 = 0xF8, - MKK6_FCCA = 0xF9, - MKK7_MKKA1 = 0xFA, - MKK7_FCCA = 0xFB, - MKK9_FCCA = 0xFC, - MKK9_MKKA1 = 0xFD, - MKK9_MKKC = 0xFE, - MKK9_MKKA2 = 0xFF, - - WORLD = 0x0199, - DEBUG_REG_DMN = 0x01ff, -}; - -/* Regpair to CTL band mapping */ -static struct reg_dmn_pair_mapping regDomainPairs[] = { - /* regpair, 5 GHz CTL, 2 GHz CTL */ - {NO_ENUMRD, DEBUG_REG_DMN, DEBUG_REG_DMN}, - {NULL1_WORLD, NO_CTL, CTL_ETSI}, - {NULL1_ETSIB, NO_CTL, CTL_ETSI}, - {NULL1_ETSIC, NO_CTL, CTL_ETSI}, - - {FCC2_FCCA, CTL_FCC, CTL_FCC}, - {FCC2_WORLD, CTL_FCC, CTL_ETSI}, - {FCC2_ETSIC, CTL_FCC, CTL_ETSI}, - {FCC3_FCCA, CTL_FCC, CTL_FCC}, - {FCC3_WORLD, CTL_FCC, CTL_ETSI}, - {FCC4_FCCA, CTL_FCC, CTL_FCC}, - {FCC5_FCCA, CTL_FCC, CTL_FCC}, - {FCC6_FCCA, CTL_FCC, CTL_FCC}, - {FCC6_WORLD, CTL_FCC, CTL_ETSI}, - - {ETSI1_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI2_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI3_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI4_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI5_WORLD, CTL_ETSI, CTL_ETSI}, - {ETSI6_WORLD, CTL_ETSI, CTL_ETSI}, - - /* XXX: For ETSI3_ETSIA, Was NO_CTL meant for the 2 GHz band ? */ - {ETSI3_ETSIA, CTL_ETSI, CTL_ETSI}, - {FRANCE_RES, CTL_ETSI, CTL_ETSI}, - - {FCC1_WORLD, CTL_FCC, CTL_ETSI}, - {FCC1_FCCA, CTL_FCC, CTL_FCC}, - {APL1_WORLD, CTL_FCC, CTL_ETSI}, - {APL2_WORLD, CTL_FCC, CTL_ETSI}, - {APL3_WORLD, CTL_FCC, CTL_ETSI}, - {APL4_WORLD, CTL_FCC, CTL_ETSI}, - {APL5_WORLD, CTL_FCC, CTL_ETSI}, - {APL6_WORLD, CTL_ETSI, CTL_ETSI}, - {APL8_WORLD, CTL_ETSI, CTL_ETSI}, - {APL9_WORLD, CTL_ETSI, CTL_ETSI}, - - {APL3_FCCA, CTL_FCC, CTL_FCC}, - {APL1_ETSIC, CTL_FCC, CTL_ETSI}, - {APL2_ETSIC, CTL_FCC, CTL_ETSI}, - {APL2_APLD, CTL_FCC, NO_CTL}, - - {MKK1_MKKA, CTL_MKK, CTL_MKK}, - {MKK1_MKKB, CTL_MKK, CTL_MKK}, - {MKK1_FCCA, CTL_MKK, CTL_FCC}, - {MKK1_MKKA1, CTL_MKK, CTL_MKK}, - {MKK1_MKKA2, CTL_MKK, CTL_MKK}, - {MKK1_MKKC, CTL_MKK, CTL_MKK}, - - {MKK2_MKKA, CTL_MKK, CTL_MKK}, - {MKK3_MKKA, CTL_MKK, CTL_MKK}, - {MKK3_MKKB, CTL_MKK, CTL_MKK}, - {MKK3_MKKA1, CTL_MKK, CTL_MKK}, - {MKK3_MKKA2, CTL_MKK, CTL_MKK}, - {MKK3_MKKC, CTL_MKK, CTL_MKK}, - {MKK3_FCCA, CTL_MKK, CTL_FCC}, - - {MKK4_MKKA, CTL_MKK, CTL_MKK}, - {MKK4_MKKB, CTL_MKK, CTL_MKK}, - {MKK4_MKKA1, CTL_MKK, CTL_MKK}, - {MKK4_MKKA2, CTL_MKK, CTL_MKK}, - {MKK4_MKKC, CTL_MKK, CTL_MKK}, - {MKK4_FCCA, CTL_MKK, CTL_FCC}, - - {MKK5_MKKB, CTL_MKK, CTL_MKK}, - {MKK5_MKKA2, CTL_MKK, CTL_MKK}, - {MKK5_MKKC, CTL_MKK, CTL_MKK}, - - {MKK6_MKKB, CTL_MKK, CTL_MKK}, - {MKK6_MKKA1, CTL_MKK, CTL_MKK}, - {MKK6_MKKA2, CTL_MKK, CTL_MKK}, - {MKK6_MKKC, CTL_MKK, CTL_MKK}, - {MKK6_FCCA, CTL_MKK, CTL_FCC}, - - {MKK7_MKKB, CTL_MKK, CTL_MKK}, - {MKK7_MKKA1, CTL_MKK, CTL_MKK}, - {MKK7_MKKA2, CTL_MKK, CTL_MKK}, - {MKK7_MKKC, CTL_MKK, CTL_MKK}, - {MKK7_FCCA, CTL_MKK, CTL_FCC}, - - {MKK8_MKKB, CTL_MKK, CTL_MKK}, - {MKK8_MKKA2, CTL_MKK, CTL_MKK}, - {MKK8_MKKC, CTL_MKK, CTL_MKK}, - - {MKK9_MKKA, CTL_MKK, CTL_MKK}, - {MKK9_FCCA, CTL_MKK, CTL_FCC}, - {MKK9_MKKA1, CTL_MKK, CTL_MKK}, - {MKK9_MKKA2, CTL_MKK, CTL_MKK}, - {MKK9_MKKC, CTL_MKK, CTL_MKK}, - - {MKK10_MKKA, CTL_MKK, CTL_MKK}, - {MKK10_FCCA, CTL_MKK, CTL_FCC}, - {MKK10_MKKA1, CTL_MKK, CTL_MKK}, - {MKK10_MKKA2, CTL_MKK, CTL_MKK}, - {MKK10_MKKC, CTL_MKK, CTL_MKK}, - - {MKK11_MKKA, CTL_MKK, CTL_MKK}, - {MKK11_FCCA, CTL_MKK, CTL_FCC}, - {MKK11_MKKA1, CTL_MKK, CTL_MKK}, - {MKK11_MKKA2, CTL_MKK, CTL_MKK}, - {MKK11_MKKC, CTL_MKK, CTL_MKK}, - - {MKK12_MKKA, CTL_MKK, CTL_MKK}, - {MKK12_FCCA, CTL_MKK, CTL_FCC}, - {MKK12_MKKA1, CTL_MKK, CTL_MKK}, - {MKK12_MKKA2, CTL_MKK, CTL_MKK}, - {MKK12_MKKC, CTL_MKK, CTL_MKK}, - - {MKK13_MKKB, CTL_MKK, CTL_MKK}, - {MKK14_MKKA1, CTL_MKK, CTL_MKK}, - {MKK15_MKKA1, CTL_MKK, CTL_MKK}, - - {WOR0_WORLD, NO_CTL, NO_CTL}, - {WOR1_WORLD, NO_CTL, NO_CTL}, - {WOR2_WORLD, NO_CTL, NO_CTL}, - {WOR3_WORLD, NO_CTL, NO_CTL}, - {WOR4_WORLD, NO_CTL, NO_CTL}, - {WOR5_ETSIC, NO_CTL, NO_CTL}, - {WOR01_WORLD, NO_CTL, NO_CTL}, - {WOR02_WORLD, NO_CTL, NO_CTL}, - {EU1_WORLD, NO_CTL, NO_CTL}, - {WOR9_WORLD, NO_CTL, NO_CTL}, - {WORA_WORLD, NO_CTL, NO_CTL}, - {WORB_WORLD, NO_CTL, NO_CTL}, -}; - -static struct country_code_to_enum_rd allCountries[] = { - {CTRY_DEBUG, NO_ENUMRD, "DB"}, - {CTRY_DEFAULT, FCC1_FCCA, "CO"}, - {CTRY_ALBANIA, NULL1_WORLD, "AL"}, - {CTRY_ALGERIA, NULL1_WORLD, "DZ"}, - {CTRY_ARGENTINA, APL3_WORLD, "AR"}, - {CTRY_ARMENIA, ETSI4_WORLD, "AM"}, - {CTRY_AUSTRALIA, FCC2_WORLD, "AU"}, - {CTRY_AUSTRALIA2, FCC6_WORLD, "AU"}, - {CTRY_AUSTRIA, ETSI1_WORLD, "AT"}, - {CTRY_AZERBAIJAN, ETSI4_WORLD, "AZ"}, - {CTRY_BAHRAIN, APL6_WORLD, "BH"}, - {CTRY_BELARUS, ETSI1_WORLD, "BY"}, - {CTRY_BELGIUM, ETSI1_WORLD, "BE"}, - {CTRY_BELGIUM2, ETSI4_WORLD, "BL"}, - {CTRY_BELIZE, APL1_ETSIC, "BZ"}, - {CTRY_BOLIVIA, APL1_ETSIC, "BO"}, - {CTRY_BOSNIA_HERZ, ETSI1_WORLD, "BA"}, - {CTRY_BRAZIL, FCC3_WORLD, "BR"}, - {CTRY_BRUNEI_DARUSSALAM, APL1_WORLD, "BN"}, - {CTRY_BULGARIA, ETSI6_WORLD, "BG"}, - {CTRY_CANADA, FCC2_FCCA, "CA"}, - {CTRY_CANADA2, FCC6_FCCA, "CA"}, - {CTRY_CHILE, APL6_WORLD, "CL"}, - {CTRY_CHINA, APL1_WORLD, "CN"}, - {CTRY_COLOMBIA, FCC1_FCCA, "CO"}, - {CTRY_COSTA_RICA, FCC1_WORLD, "CR"}, - {CTRY_CROATIA, ETSI3_WORLD, "HR"}, - {CTRY_CYPRUS, ETSI1_WORLD, "CY"}, - {CTRY_CZECH, ETSI3_WORLD, "CZ"}, - {CTRY_DENMARK, ETSI1_WORLD, "DK"}, - {CTRY_DOMINICAN_REPUBLIC, FCC1_FCCA, "DO"}, - {CTRY_ECUADOR, FCC1_WORLD, "EC"}, - {CTRY_EGYPT, ETSI3_WORLD, "EG"}, - {CTRY_EL_SALVADOR, FCC1_WORLD, "SV"}, - {CTRY_ESTONIA, ETSI1_WORLD, "EE"}, - {CTRY_FINLAND, ETSI1_WORLD, "FI"}, - {CTRY_FRANCE, ETSI1_WORLD, "FR"}, - {CTRY_GEORGIA, ETSI4_WORLD, "GE"}, - {CTRY_GERMANY, ETSI1_WORLD, "DE"}, - {CTRY_GREECE, ETSI1_WORLD, "GR"}, - {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, - {CTRY_HONDURAS, NULL1_WORLD, "HN"}, - {CTRY_HONG_KONG, FCC2_WORLD, "HK"}, - {CTRY_HUNGARY, ETSI1_WORLD, "HU"}, - {CTRY_ICELAND, ETSI1_WORLD, "IS"}, - {CTRY_INDIA, APL6_WORLD, "IN"}, - {CTRY_INDONESIA, APL1_WORLD, "ID"}, - {CTRY_IRAN, APL1_WORLD, "IR"}, - {CTRY_IRELAND, ETSI1_WORLD, "IE"}, - {CTRY_ISRAEL, NULL1_WORLD, "IL"}, - {CTRY_ITALY, ETSI1_WORLD, "IT"}, - {CTRY_JAMAICA, ETSI1_WORLD, "JM"}, - - {CTRY_JAPAN, MKK1_MKKA, "JP"}, - {CTRY_JAPAN1, MKK1_MKKB, "JP"}, - {CTRY_JAPAN2, MKK1_FCCA, "JP"}, - {CTRY_JAPAN3, MKK2_MKKA, "JP"}, - {CTRY_JAPAN4, MKK1_MKKA1, "JP"}, - {CTRY_JAPAN5, MKK1_MKKA2, "JP"}, - {CTRY_JAPAN6, MKK1_MKKC, "JP"}, - {CTRY_JAPAN7, MKK3_MKKB, "JP"}, - {CTRY_JAPAN8, MKK3_MKKA2, "JP"}, - {CTRY_JAPAN9, MKK3_MKKC, "JP"}, - {CTRY_JAPAN10, MKK4_MKKB, "JP"}, - {CTRY_JAPAN11, MKK4_MKKA2, "JP"}, - {CTRY_JAPAN12, MKK4_MKKC, "JP"}, - {CTRY_JAPAN13, MKK5_MKKB, "JP"}, - {CTRY_JAPAN14, MKK5_MKKA2, "JP"}, - {CTRY_JAPAN15, MKK5_MKKC, "JP"}, - {CTRY_JAPAN16, MKK6_MKKB, "JP"}, - {CTRY_JAPAN17, MKK6_MKKA2, "JP"}, - {CTRY_JAPAN18, MKK6_MKKC, "JP"}, - {CTRY_JAPAN19, MKK7_MKKB, "JP"}, - {CTRY_JAPAN20, MKK7_MKKA2, "JP"}, - {CTRY_JAPAN21, MKK7_MKKC, "JP"}, - {CTRY_JAPAN22, MKK8_MKKB, "JP"}, - {CTRY_JAPAN23, MKK8_MKKA2, "JP"}, - {CTRY_JAPAN24, MKK8_MKKC, "JP"}, - {CTRY_JAPAN25, MKK3_MKKA, "JP"}, - {CTRY_JAPAN26, MKK3_MKKA1, "JP"}, - {CTRY_JAPAN27, MKK3_FCCA, "JP"}, - {CTRY_JAPAN28, MKK4_MKKA1, "JP"}, - {CTRY_JAPAN29, MKK4_FCCA, "JP"}, - {CTRY_JAPAN30, MKK6_MKKA1, "JP"}, - {CTRY_JAPAN31, MKK6_FCCA, "JP"}, - {CTRY_JAPAN32, MKK7_MKKA1, "JP"}, - {CTRY_JAPAN33, MKK7_FCCA, "JP"}, - {CTRY_JAPAN34, MKK9_MKKA, "JP"}, - {CTRY_JAPAN35, MKK10_MKKA, "JP"}, - {CTRY_JAPAN36, MKK4_MKKA, "JP"}, - {CTRY_JAPAN37, MKK9_FCCA, "JP"}, - {CTRY_JAPAN38, MKK9_MKKA1, "JP"}, - {CTRY_JAPAN39, MKK9_MKKC, "JP"}, - {CTRY_JAPAN40, MKK9_MKKA2, "JP"}, - {CTRY_JAPAN41, MKK10_FCCA, "JP"}, - {CTRY_JAPAN42, MKK10_MKKA1, "JP"}, - {CTRY_JAPAN43, MKK10_MKKC, "JP"}, - {CTRY_JAPAN44, MKK10_MKKA2, "JP"}, - {CTRY_JAPAN45, MKK11_MKKA, "JP"}, - {CTRY_JAPAN46, MKK11_FCCA, "JP"}, - {CTRY_JAPAN47, MKK11_MKKA1, "JP"}, - {CTRY_JAPAN48, MKK11_MKKC, "JP"}, - {CTRY_JAPAN49, MKK11_MKKA2, "JP"}, - {CTRY_JAPAN50, MKK12_MKKA, "JP"}, - {CTRY_JAPAN51, MKK12_FCCA, "JP"}, - {CTRY_JAPAN52, MKK12_MKKA1, "JP"}, - {CTRY_JAPAN53, MKK12_MKKC, "JP"}, - {CTRY_JAPAN54, MKK12_MKKA2, "JP"}, - {CTRY_JAPAN57, MKK13_MKKB, "JP"}, - {CTRY_JAPAN58, MKK14_MKKA1, "JP"}, - {CTRY_JAPAN59, MKK15_MKKA1, "JP"}, - - {CTRY_JORDAN, ETSI2_WORLD, "JO"}, - {CTRY_KAZAKHSTAN, NULL1_WORLD, "KZ"}, - {CTRY_KOREA_NORTH, APL9_WORLD, "KP"}, - {CTRY_KOREA_ROC, APL9_WORLD, "KR"}, - {CTRY_KOREA_ROC2, APL2_WORLD, "K2"}, - {CTRY_KOREA_ROC3, APL9_WORLD, "K3"}, - {CTRY_KUWAIT, NULL1_WORLD, "KW"}, - {CTRY_LATVIA, ETSI1_WORLD, "LV"}, - {CTRY_LEBANON, NULL1_WORLD, "LB"}, - {CTRY_LIECHTENSTEIN, ETSI1_WORLD, "LI"}, - {CTRY_LITHUANIA, ETSI1_WORLD, "LT"}, - {CTRY_LUXEMBOURG, ETSI1_WORLD, "LU"}, - {CTRY_MACAU, FCC2_WORLD, "MO"}, - {CTRY_MACEDONIA, NULL1_WORLD, "MK"}, - {CTRY_MALAYSIA, APL8_WORLD, "MY"}, - {CTRY_MALTA, ETSI1_WORLD, "MT"}, - {CTRY_MEXICO, FCC1_FCCA, "MX"}, - {CTRY_MONACO, ETSI4_WORLD, "MC"}, - {CTRY_MOROCCO, NULL1_WORLD, "MA"}, - {CTRY_NEPAL, APL1_WORLD, "NP"}, - {CTRY_NETHERLANDS, ETSI1_WORLD, "NL"}, - {CTRY_NETHERLANDS_ANTILLES, ETSI1_WORLD, "AN"}, - {CTRY_NEW_ZEALAND, FCC2_ETSIC, "NZ"}, - {CTRY_NORWAY, ETSI1_WORLD, "NO"}, - {CTRY_OMAN, APL6_WORLD, "OM"}, - {CTRY_PAKISTAN, NULL1_WORLD, "PK"}, - {CTRY_PANAMA, FCC1_FCCA, "PA"}, - {CTRY_PAPUA_NEW_GUINEA, FCC1_WORLD, "PG"}, - {CTRY_PERU, APL1_WORLD, "PE"}, - {CTRY_PHILIPPINES, APL1_WORLD, "PH"}, - {CTRY_POLAND, ETSI1_WORLD, "PL"}, - {CTRY_PORTUGAL, ETSI1_WORLD, "PT"}, - {CTRY_PUERTO_RICO, FCC1_FCCA, "PR"}, - {CTRY_QATAR, NULL1_WORLD, "QA"}, - {CTRY_ROMANIA, NULL1_WORLD, "RO"}, - {CTRY_RUSSIA, NULL1_WORLD, "RU"}, - {CTRY_SAUDI_ARABIA, NULL1_WORLD, "SA"}, - {CTRY_SERBIA_MONTENEGRO, ETSI1_WORLD, "CS"}, - {CTRY_SINGAPORE, APL6_WORLD, "SG"}, - {CTRY_SLOVAKIA, ETSI1_WORLD, "SK"}, - {CTRY_SLOVENIA, ETSI1_WORLD, "SI"}, - {CTRY_SOUTH_AFRICA, FCC3_WORLD, "ZA"}, - {CTRY_SPAIN, ETSI1_WORLD, "ES"}, - {CTRY_SRI_LANKA, FCC3_WORLD, "LK"}, - {CTRY_SWEDEN, ETSI1_WORLD, "SE"}, - {CTRY_SWITZERLAND, ETSI1_WORLD, "CH"}, - {CTRY_SYRIA, NULL1_WORLD, "SY"}, - {CTRY_TAIWAN, APL3_FCCA, "TW"}, - {CTRY_THAILAND, FCC3_WORLD, "TH"}, - {CTRY_TRINIDAD_Y_TOBAGO, ETSI4_WORLD, "TT"}, - {CTRY_TUNISIA, ETSI3_WORLD, "TN"}, - {CTRY_TURKEY, ETSI3_WORLD, "TR"}, - {CTRY_UKRAINE, NULL1_WORLD, "UA"}, - {CTRY_UAE, NULL1_WORLD, "AE"}, - {CTRY_UNITED_KINGDOM, ETSI1_WORLD, "GB"}, - {CTRY_UNITED_STATES, FCC3_FCCA, "US"}, - /* This "PS" is for US public safety actually... to support this we - * would need to assign new special alpha2 to CRDA db as with the world - * regdomain and use another alpha2 */ - {CTRY_UNITED_STATES_FCC49, FCC4_FCCA, "PS"}, - {CTRY_URUGUAY, APL2_WORLD, "UY"}, - {CTRY_UZBEKISTAN, FCC3_FCCA, "UZ"}, - {CTRY_VENEZUELA, APL2_ETSIC, "VE"}, - {CTRY_VIET_NAM, NULL1_WORLD, "VN"}, - {CTRY_YEMEN, NULL1_WORLD, "YE"}, - {CTRY_ZIMBABWE, NULL1_WORLD, "ZW"}, -}; - -#endif diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c deleted file mode 100644 index cce188837d10..000000000000 --- a/drivers/net/wireless/atmel.c +++ /dev/null @@ -1,4553 +0,0 @@ -/*** -*- linux-c -*- ********************************************************** - - Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. - - Copyright 2000-2001 ATMEL Corporation. - Copyright 2003-2004 Simon Kelley. - - This code was developed from version 2.1.1 of the Atmel drivers, - released by Atmel corp. under the GPL in December 2002. It also - includes code from the Linux aironet drivers (C) Benjamin Reed, - and the Linux PCMCIA package, (C) David Hinds and the Linux wireless - extensions, (C) Jean Tourrilhes. - - The firmware module for reading the MAC address of the card comes from - net.russotto.AtmelMACFW, written by Matthew T. Russotto and copyright - by him. net.russotto.AtmelMACFW is used under the GPL license version 2. - This file contains the module in binary form and, under the terms - of the GPL, in source form. The source is located at the end of the file. - - 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 software 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 Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - For all queries about this code, please contact the current author, - Simon Kelley and not Atmel Corporation. - - Credit is due to HP UK and Cambridge Online Systems Ltd for supplying - hardware used during development of this driver. - -******************************************************************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "atmel.h" - -#define DRIVER_MAJOR 0 -#define DRIVER_MINOR 98 - -MODULE_AUTHOR("Simon Kelley"); -MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards."); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("Atmel at76c50x wireless cards"); - -/* The name of the firmware file to be loaded - over-rides any automatic selection */ -static char *firmware = NULL; -module_param(firmware, charp, 0); - -/* table of firmware file names */ -static struct { - AtmelFWType fw_type; - const char *fw_file; - const char *fw_file_ext; -} fw_table[] = { - { ATMEL_FW_TYPE_502, "atmel_at76c502", "bin" }, - { ATMEL_FW_TYPE_502D, "atmel_at76c502d", "bin" }, - { ATMEL_FW_TYPE_502E, "atmel_at76c502e", "bin" }, - { ATMEL_FW_TYPE_502_3COM, "atmel_at76c502_3com", "bin" }, - { ATMEL_FW_TYPE_504, "atmel_at76c504", "bin" }, - { ATMEL_FW_TYPE_504_2958, "atmel_at76c504_2958", "bin" }, - { ATMEL_FW_TYPE_504A_2958, "atmel_at76c504a_2958", "bin" }, - { ATMEL_FW_TYPE_506, "atmel_at76c506", "bin" }, - { ATMEL_FW_TYPE_NONE, NULL, NULL } -}; - -#define MAX_SSID_LENGTH 32 -#define MGMT_JIFFIES (256 * HZ / 100) - -#define MAX_BSS_ENTRIES 64 - -/* registers */ -#define GCR 0x00 /* (SIR0) General Configuration Register */ -#define BSR 0x02 /* (SIR1) Bank Switching Select Register */ -#define AR 0x04 -#define DR 0x08 -#define MR1 0x12 /* Mirror Register 1 */ -#define MR2 0x14 /* Mirror Register 2 */ -#define MR3 0x16 /* Mirror Register 3 */ -#define MR4 0x18 /* Mirror Register 4 */ - -#define GPR1 0x0c -#define GPR2 0x0e -#define GPR3 0x10 -/* - * Constants for the GCR register. - */ -#define GCR_REMAP 0x0400 /* Remap internal SRAM to 0 */ -#define GCR_SWRES 0x0080 /* BIU reset (ARM and PAI are NOT reset) */ -#define GCR_CORES 0x0060 /* Core Reset (ARM and PAI are reset) */ -#define GCR_ENINT 0x0002 /* Enable Interrupts */ -#define GCR_ACKINT 0x0008 /* Acknowledge Interrupts */ - -#define BSS_SRAM 0x0200 /* AMBA module selection --> SRAM */ -#define BSS_IRAM 0x0100 /* AMBA module selection --> IRAM */ -/* - *Constants for the MR registers. - */ -#define MAC_INIT_COMPLETE 0x0001 /* MAC init has been completed */ -#define MAC_BOOT_COMPLETE 0x0010 /* MAC boot has been completed */ -#define MAC_INIT_OK 0x0002 /* MAC boot has been completed */ - -#define MIB_MAX_DATA_BYTES 212 -#define MIB_HEADER_SIZE 4 /* first four fields */ - -struct get_set_mib { - u8 type; - u8 size; - u8 index; - u8 reserved; - u8 data[MIB_MAX_DATA_BYTES]; -}; - -struct rx_desc { - u32 Next; - u16 MsduPos; - u16 MsduSize; - - u8 State; - u8 Status; - u8 Rate; - u8 Rssi; - u8 LinkQuality; - u8 PreambleType; - u16 Duration; - u32 RxTime; -}; - -#define RX_DESC_FLAG_VALID 0x80 -#define RX_DESC_FLAG_CONSUMED 0x40 -#define RX_DESC_FLAG_IDLE 0x00 - -#define RX_STATUS_SUCCESS 0x00 - -#define RX_DESC_MSDU_POS_OFFSET 4 -#define RX_DESC_MSDU_SIZE_OFFSET 6 -#define RX_DESC_FLAGS_OFFSET 8 -#define RX_DESC_STATUS_OFFSET 9 -#define RX_DESC_RSSI_OFFSET 11 -#define RX_DESC_LINK_QUALITY_OFFSET 12 -#define RX_DESC_PREAMBLE_TYPE_OFFSET 13 -#define RX_DESC_DURATION_OFFSET 14 -#define RX_DESC_RX_TIME_OFFSET 16 - -struct tx_desc { - u32 NextDescriptor; - u16 TxStartOfFrame; - u16 TxLength; - - u8 TxState; - u8 TxStatus; - u8 RetryCount; - - u8 TxRate; - - u8 KeyIndex; - u8 ChiperType; - u8 ChipreLength; - u8 Reserved1; - - u8 Reserved; - u8 PacketType; - u16 HostTxLength; -}; - -#define TX_DESC_NEXT_OFFSET 0 -#define TX_DESC_POS_OFFSET 4 -#define TX_DESC_SIZE_OFFSET 6 -#define TX_DESC_FLAGS_OFFSET 8 -#define TX_DESC_STATUS_OFFSET 9 -#define TX_DESC_RETRY_OFFSET 10 -#define TX_DESC_RATE_OFFSET 11 -#define TX_DESC_KEY_INDEX_OFFSET 12 -#define TX_DESC_CIPHER_TYPE_OFFSET 13 -#define TX_DESC_CIPHER_LENGTH_OFFSET 14 -#define TX_DESC_PACKET_TYPE_OFFSET 17 -#define TX_DESC_HOST_LENGTH_OFFSET 18 - -/* - * Host-MAC interface - */ - -#define TX_STATUS_SUCCESS 0x00 - -#define TX_FIRM_OWN 0x80 -#define TX_DONE 0x40 - -#define TX_ERROR 0x01 - -#define TX_PACKET_TYPE_DATA 0x01 -#define TX_PACKET_TYPE_MGMT 0x02 - -#define ISR_EMPTY 0x00 /* no bits set in ISR */ -#define ISR_TxCOMPLETE 0x01 /* packet transmitted */ -#define ISR_RxCOMPLETE 0x02 /* packet received */ -#define ISR_RxFRAMELOST 0x04 /* Rx Frame lost */ -#define ISR_FATAL_ERROR 0x08 /* Fatal error */ -#define ISR_COMMAND_COMPLETE 0x10 /* command completed */ -#define ISR_OUT_OF_RANGE 0x20 /* command completed */ -#define ISR_IBSS_MERGE 0x40 /* (4.1.2.30): IBSS merge */ -#define ISR_GENERIC_IRQ 0x80 - -#define Local_Mib_Type 0x01 -#define Mac_Address_Mib_Type 0x02 -#define Mac_Mib_Type 0x03 -#define Statistics_Mib_Type 0x04 -#define Mac_Mgmt_Mib_Type 0x05 -#define Mac_Wep_Mib_Type 0x06 -#define Phy_Mib_Type 0x07 -#define Multi_Domain_MIB 0x08 - -#define MAC_MGMT_MIB_CUR_BSSID_POS 14 -#define MAC_MIB_FRAG_THRESHOLD_POS 8 -#define MAC_MIB_RTS_THRESHOLD_POS 10 -#define MAC_MIB_SHORT_RETRY_POS 16 -#define MAC_MIB_LONG_RETRY_POS 17 -#define MAC_MIB_SHORT_RETRY_LIMIT_POS 16 -#define MAC_MGMT_MIB_BEACON_PER_POS 0 -#define MAC_MGMT_MIB_STATION_ID_POS 6 -#define MAC_MGMT_MIB_CUR_PRIVACY_POS 11 -#define MAC_MGMT_MIB_CUR_BSSID_POS 14 -#define MAC_MGMT_MIB_PS_MODE_POS 53 -#define MAC_MGMT_MIB_LISTEN_INTERVAL_POS 54 -#define MAC_MGMT_MIB_MULTI_DOMAIN_IMPLEMENTED 56 -#define MAC_MGMT_MIB_MULTI_DOMAIN_ENABLED 57 -#define PHY_MIB_CHANNEL_POS 14 -#define PHY_MIB_RATE_SET_POS 20 -#define PHY_MIB_REG_DOMAIN_POS 26 -#define LOCAL_MIB_AUTO_TX_RATE_POS 3 -#define LOCAL_MIB_SSID_SIZE 5 -#define LOCAL_MIB_TX_PROMISCUOUS_POS 6 -#define LOCAL_MIB_TX_MGMT_RATE_POS 7 -#define LOCAL_MIB_TX_CONTROL_RATE_POS 8 -#define LOCAL_MIB_PREAMBLE_TYPE 9 -#define MAC_ADDR_MIB_MAC_ADDR_POS 0 - -#define CMD_Set_MIB_Vars 0x01 -#define CMD_Get_MIB_Vars 0x02 -#define CMD_Scan 0x03 -#define CMD_Join 0x04 -#define CMD_Start 0x05 -#define CMD_EnableRadio 0x06 -#define CMD_DisableRadio 0x07 -#define CMD_SiteSurvey 0x0B - -#define CMD_STATUS_IDLE 0x00 -#define CMD_STATUS_COMPLETE 0x01 -#define CMD_STATUS_UNKNOWN 0x02 -#define CMD_STATUS_INVALID_PARAMETER 0x03 -#define CMD_STATUS_FUNCTION_NOT_SUPPORTED 0x04 -#define CMD_STATUS_TIME_OUT 0x07 -#define CMD_STATUS_IN_PROGRESS 0x08 -#define CMD_STATUS_REJECTED_RADIO_OFF 0x09 -#define CMD_STATUS_HOST_ERROR 0xFF -#define CMD_STATUS_BUSY 0xFE - -#define CMD_BLOCK_COMMAND_OFFSET 0 -#define CMD_BLOCK_STATUS_OFFSET 1 -#define CMD_BLOCK_PARAMETERS_OFFSET 4 - -#define SCAN_OPTIONS_SITE_SURVEY 0x80 - -#define MGMT_FRAME_BODY_OFFSET 24 -#define MAX_AUTHENTICATION_RETRIES 3 -#define MAX_ASSOCIATION_RETRIES 3 - -#define AUTHENTICATION_RESPONSE_TIME_OUT 1000 - -#define MAX_WIRELESS_BODY 2316 /* mtu is 2312, CRC is 4 */ -#define LOOP_RETRY_LIMIT 500000 - -#define ACTIVE_MODE 1 -#define PS_MODE 2 - -#define MAX_ENCRYPTION_KEYS 4 -#define MAX_ENCRYPTION_KEY_SIZE 40 - -/* - * 802.11 related definitions - */ - -/* - * Regulatory Domains - */ - -#define REG_DOMAIN_FCC 0x10 /* Channels 1-11 USA */ -#define REG_DOMAIN_DOC 0x20 /* Channel 1-11 Canada */ -#define REG_DOMAIN_ETSI 0x30 /* Channel 1-13 Europe (ex Spain/France) */ -#define REG_DOMAIN_SPAIN 0x31 /* Channel 10-11 Spain */ -#define REG_DOMAIN_FRANCE 0x32 /* Channel 10-13 France */ -#define REG_DOMAIN_MKK 0x40 /* Channel 14 Japan */ -#define REG_DOMAIN_MKK1 0x41 /* Channel 1-14 Japan(MKK1) */ -#define REG_DOMAIN_ISRAEL 0x50 /* Channel 3-9 ISRAEL */ - -#define BSS_TYPE_AD_HOC 1 -#define BSS_TYPE_INFRASTRUCTURE 2 - -#define SCAN_TYPE_ACTIVE 0 -#define SCAN_TYPE_PASSIVE 1 - -#define LONG_PREAMBLE 0 -#define SHORT_PREAMBLE 1 -#define AUTO_PREAMBLE 2 - -#define DATA_FRAME_WS_HEADER_SIZE 30 - -/* promiscuous mode control */ -#define PROM_MODE_OFF 0x0 -#define PROM_MODE_UNKNOWN 0x1 -#define PROM_MODE_CRC_FAILED 0x2 -#define PROM_MODE_DUPLICATED 0x4 -#define PROM_MODE_MGMT 0x8 -#define PROM_MODE_CTRL 0x10 -#define PROM_MODE_BAD_PROTOCOL 0x20 - -#define IFACE_INT_STATUS_OFFSET 0 -#define IFACE_INT_MASK_OFFSET 1 -#define IFACE_LOCKOUT_HOST_OFFSET 2 -#define IFACE_LOCKOUT_MAC_OFFSET 3 -#define IFACE_FUNC_CTRL_OFFSET 28 -#define IFACE_MAC_STAT_OFFSET 30 -#define IFACE_GENERIC_INT_TYPE_OFFSET 32 - -#define CIPHER_SUITE_NONE 0 -#define CIPHER_SUITE_WEP_64 1 -#define CIPHER_SUITE_TKIP 2 -#define CIPHER_SUITE_AES 3 -#define CIPHER_SUITE_CCX 4 -#define CIPHER_SUITE_WEP_128 5 - -/* - * IFACE MACROS & definitions - */ - -/* - * FuncCtrl field: - */ -#define FUNC_CTRL_TxENABLE 0x10 -#define FUNC_CTRL_RxENABLE 0x20 -#define FUNC_CTRL_INIT_COMPLETE 0x01 - -/* A stub firmware image which reads the MAC address from NVRAM on the card. - For copyright information and source see the end of this file. */ -static u8 mac_reader[] = { - 0x06, 0x00, 0x00, 0xea, 0x04, 0x00, 0x00, 0xea, 0x03, 0x00, 0x00, 0xea, 0x02, 0x00, 0x00, 0xea, - 0x01, 0x00, 0x00, 0xea, 0x00, 0x00, 0x00, 0xea, 0xff, 0xff, 0xff, 0xea, 0xfe, 0xff, 0xff, 0xea, - 0xd3, 0x00, 0xa0, 0xe3, 0x00, 0xf0, 0x21, 0xe1, 0x0e, 0x04, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, - 0x81, 0x11, 0xa0, 0xe1, 0x00, 0x10, 0x81, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x1c, 0x10, 0x90, 0xe5, - 0x10, 0x10, 0xc1, 0xe3, 0x1c, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, 0x08, 0x10, 0x80, 0xe5, - 0x02, 0x03, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, 0xb0, 0x10, 0xc0, 0xe1, 0xb4, 0x10, 0xc0, 0xe1, - 0xb8, 0x10, 0xc0, 0xe1, 0xbc, 0x10, 0xc0, 0xe1, 0x56, 0xdc, 0xa0, 0xe3, 0x21, 0x00, 0x00, 0xeb, - 0x0a, 0x00, 0xa0, 0xe3, 0x1a, 0x00, 0x00, 0xeb, 0x10, 0x00, 0x00, 0xeb, 0x07, 0x00, 0x00, 0xeb, - 0x02, 0x03, 0xa0, 0xe3, 0x02, 0x14, 0xa0, 0xe3, 0xb4, 0x10, 0xc0, 0xe1, 0x4c, 0x10, 0x9f, 0xe5, - 0xbc, 0x10, 0xc0, 0xe1, 0x10, 0x10, 0xa0, 0xe3, 0xb8, 0x10, 0xc0, 0xe1, 0xfe, 0xff, 0xff, 0xea, - 0x00, 0x40, 0x2d, 0xe9, 0x00, 0x20, 0xa0, 0xe3, 0x02, 0x3c, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, - 0x28, 0x00, 0x9f, 0xe5, 0x37, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, - 0x00, 0x40, 0x2d, 0xe9, 0x12, 0x2e, 0xa0, 0xe3, 0x06, 0x30, 0xa0, 0xe3, 0x00, 0x10, 0xa0, 0xe3, - 0x02, 0x04, 0xa0, 0xe3, 0x2f, 0x00, 0x00, 0xeb, 0x00, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, - 0x00, 0x02, 0x00, 0x02, 0x80, 0x01, 0x90, 0xe0, 0x01, 0x00, 0x00, 0x0a, 0x01, 0x00, 0x50, 0xe2, - 0xfc, 0xff, 0xff, 0xea, 0x1e, 0xff, 0x2f, 0xe1, 0x80, 0x10, 0xa0, 0xe3, 0xf3, 0x06, 0xa0, 0xe3, - 0x00, 0x10, 0x80, 0xe5, 0x00, 0x10, 0xa0, 0xe3, 0x00, 0x10, 0x80, 0xe5, 0x01, 0x10, 0xa0, 0xe3, - 0x04, 0x10, 0x80, 0xe5, 0x00, 0x10, 0x80, 0xe5, 0x0e, 0x34, 0xa0, 0xe3, 0x1c, 0x10, 0x93, 0xe5, - 0x02, 0x1a, 0x81, 0xe3, 0x1c, 0x10, 0x83, 0xe5, 0x58, 0x11, 0x9f, 0xe5, 0x30, 0x10, 0x80, 0xe5, - 0x54, 0x11, 0x9f, 0xe5, 0x34, 0x10, 0x80, 0xe5, 0x38, 0x10, 0x80, 0xe5, 0x3c, 0x10, 0x80, 0xe5, - 0x10, 0x10, 0x90, 0xe5, 0x08, 0x00, 0x90, 0xe5, 0x1e, 0xff, 0x2f, 0xe1, 0xf3, 0x16, 0xa0, 0xe3, - 0x08, 0x00, 0x91, 0xe5, 0x05, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, 0x10, 0x00, 0x91, 0xe5, - 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0xff, 0x00, 0xa0, 0xe3, 0x0c, 0x00, 0x81, 0xe5, - 0x10, 0x00, 0x91, 0xe5, 0x02, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5, - 0x10, 0x00, 0x91, 0xe5, 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x91, 0xe5, - 0xff, 0x00, 0x00, 0xe2, 0x1e, 0xff, 0x2f, 0xe1, 0x30, 0x40, 0x2d, 0xe9, 0x00, 0x50, 0xa0, 0xe1, - 0x03, 0x40, 0xa0, 0xe1, 0xa2, 0x02, 0xa0, 0xe1, 0x08, 0x00, 0x00, 0xe2, 0x03, 0x00, 0x80, 0xe2, - 0xd8, 0x10, 0x9f, 0xe5, 0x00, 0x00, 0xc1, 0xe5, 0x01, 0x20, 0xc1, 0xe5, 0xe2, 0xff, 0xff, 0xeb, - 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x1a, 0x14, 0x00, 0xa0, 0xe3, 0xc4, 0xff, 0xff, 0xeb, - 0x04, 0x20, 0xa0, 0xe1, 0x05, 0x10, 0xa0, 0xe1, 0x02, 0x00, 0xa0, 0xe3, 0x01, 0x00, 0x00, 0xeb, - 0x30, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x70, 0x40, 0x2d, 0xe9, 0xf3, 0x46, 0xa0, 0xe3, - 0x00, 0x30, 0xa0, 0xe3, 0x00, 0x00, 0x50, 0xe3, 0x08, 0x00, 0x00, 0x9a, 0x8c, 0x50, 0x9f, 0xe5, - 0x03, 0x60, 0xd5, 0xe7, 0x0c, 0x60, 0x84, 0xe5, 0x10, 0x60, 0x94, 0xe5, 0x02, 0x00, 0x16, 0xe3, - 0xfc, 0xff, 0xff, 0x0a, 0x01, 0x30, 0x83, 0xe2, 0x00, 0x00, 0x53, 0xe1, 0xf7, 0xff, 0xff, 0x3a, - 0xff, 0x30, 0xa0, 0xe3, 0x0c, 0x30, 0x84, 0xe5, 0x08, 0x00, 0x94, 0xe5, 0x10, 0x00, 0x94, 0xe5, - 0x01, 0x00, 0x10, 0xe3, 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x00, 0x94, 0xe5, 0x00, 0x00, 0xa0, 0xe3, - 0x00, 0x00, 0x52, 0xe3, 0x0b, 0x00, 0x00, 0x9a, 0x10, 0x50, 0x94, 0xe5, 0x02, 0x00, 0x15, 0xe3, - 0xfc, 0xff, 0xff, 0x0a, 0x0c, 0x30, 0x84, 0xe5, 0x10, 0x50, 0x94, 0xe5, 0x01, 0x00, 0x15, 0xe3, - 0xfc, 0xff, 0xff, 0x0a, 0x08, 0x50, 0x94, 0xe5, 0x01, 0x50, 0xc1, 0xe4, 0x01, 0x00, 0x80, 0xe2, - 0x02, 0x00, 0x50, 0xe1, 0xf3, 0xff, 0xff, 0x3a, 0xc8, 0x00, 0xa0, 0xe3, 0x98, 0xff, 0xff, 0xeb, - 0x70, 0x40, 0xbd, 0xe8, 0x1e, 0xff, 0x2f, 0xe1, 0x01, 0x0c, 0x00, 0x02, 0x01, 0x02, 0x00, 0x02, - 0x00, 0x01, 0x00, 0x02 -}; - -struct atmel_private { - void *card; /* Bus dependent stucture varies for PCcard */ - int (*present_callback)(void *); /* And callback which uses it */ - char firmware_id[32]; - AtmelFWType firmware_type; - u8 *firmware; - int firmware_length; - struct timer_list management_timer; - struct net_device *dev; - struct device *sys_dev; - struct iw_statistics wstats; - spinlock_t irqlock, timerlock; /* spinlocks */ - enum { BUS_TYPE_PCCARD, BUS_TYPE_PCI } bus_type; - enum { - CARD_TYPE_PARALLEL_FLASH, - CARD_TYPE_SPI_FLASH, - CARD_TYPE_EEPROM - } card_type; - int do_rx_crc; /* If we need to CRC incoming packets */ - int probe_crc; /* set if we don't yet know */ - int crc_ok_cnt, crc_ko_cnt; /* counters for probing */ - u16 rx_desc_head; - u16 tx_desc_free, tx_desc_head, tx_desc_tail, tx_desc_previous; - u16 tx_free_mem, tx_buff_head, tx_buff_tail; - - u16 frag_seq, frag_len, frag_no; - u8 frag_source[6]; - - u8 wep_is_on, default_key, exclude_unencrypted, encryption_level; - u8 group_cipher_suite, pairwise_cipher_suite; - u8 wep_keys[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE]; - int wep_key_len[MAX_ENCRYPTION_KEYS]; - int use_wpa, radio_on_broken; /* firmware dependent stuff. */ - - u16 host_info_base; - struct host_info_struct { - /* NB this is matched to the hardware, don't change. */ - u8 volatile int_status; - u8 volatile int_mask; - u8 volatile lockout_host; - u8 volatile lockout_mac; - - u16 tx_buff_pos; - u16 tx_buff_size; - u16 tx_desc_pos; - u16 tx_desc_count; - - u16 rx_buff_pos; - u16 rx_buff_size; - u16 rx_desc_pos; - u16 rx_desc_count; - - u16 build_version; - u16 command_pos; - - u16 major_version; - u16 minor_version; - - u16 func_ctrl; - u16 mac_status; - u16 generic_IRQ_type; - u8 reserved[2]; - } host_info; - - enum { - STATION_STATE_SCANNING, - STATION_STATE_JOINNING, - STATION_STATE_AUTHENTICATING, - STATION_STATE_ASSOCIATING, - STATION_STATE_READY, - STATION_STATE_REASSOCIATING, - STATION_STATE_DOWN, - STATION_STATE_MGMT_ERROR - } station_state; - - int operating_mode, power_mode; - time_t last_qual; - int beacons_this_sec; - int channel; - int reg_domain, config_reg_domain; - int tx_rate; - int auto_tx_rate; - int rts_threshold; - int frag_threshold; - int long_retry, short_retry; - int preamble; - int default_beacon_period, beacon_period, listen_interval; - int CurrentAuthentTransactionSeqNum, ExpectedAuthentTransactionSeqNum; - int AuthenticationRequestRetryCnt, AssociationRequestRetryCnt, ReAssociationRequestRetryCnt; - enum { - SITE_SURVEY_IDLE, - SITE_SURVEY_IN_PROGRESS, - SITE_SURVEY_COMPLETED - } site_survey_state; - unsigned long last_survey; - - int station_was_associated, station_is_associated; - int fast_scan; - - struct bss_info { - int channel; - int SSIDsize; - int RSSI; - int UsingWEP; - int preamble; - int beacon_period; - int BSStype; - u8 BSSID[6]; - u8 SSID[MAX_SSID_LENGTH]; - } BSSinfo[MAX_BSS_ENTRIES]; - int BSS_list_entries, current_BSS; - int connect_to_any_BSS; - int SSID_size, new_SSID_size; - u8 CurrentBSSID[6], BSSID[6]; - u8 SSID[MAX_SSID_LENGTH], new_SSID[MAX_SSID_LENGTH]; - u64 last_beacon_timestamp; - u8 rx_buf[MAX_WIRELESS_BODY]; -}; - -static u8 atmel_basic_rates[4] = {0x82, 0x84, 0x0b, 0x16}; - -static const struct { - int reg_domain; - int min, max; - char *name; -} channel_table[] = { { REG_DOMAIN_FCC, 1, 11, "USA" }, - { REG_DOMAIN_DOC, 1, 11, "Canada" }, - { REG_DOMAIN_ETSI, 1, 13, "Europe" }, - { REG_DOMAIN_SPAIN, 10, 11, "Spain" }, - { REG_DOMAIN_FRANCE, 10, 13, "France" }, - { REG_DOMAIN_MKK, 14, 14, "MKK" }, - { REG_DOMAIN_MKK1, 1, 14, "MKK1" }, - { REG_DOMAIN_ISRAEL, 3, 9, "Israel"} }; - -static void build_wpa_mib(struct atmel_private *priv); -static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -static void atmel_copy_to_card(struct net_device *dev, u16 dest, - const unsigned char *src, u16 len); -static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, - u16 src, u16 len); -static void atmel_set_gcr(struct net_device *dev, u16 mask); -static void atmel_clear_gcr(struct net_device *dev, u16 mask); -static int atmel_lock_mac(struct atmel_private *priv); -static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data); -static void atmel_command_irq(struct atmel_private *priv); -static int atmel_validate_channel(struct atmel_private *priv, int channel); -static void atmel_management_frame(struct atmel_private *priv, - struct ieee80211_hdr *header, - u16 frame_len, u8 rssi); -static void atmel_management_timer(u_long a); -static void atmel_send_command(struct atmel_private *priv, int command, - void *cmd, int cmd_size); -static int atmel_send_command_wait(struct atmel_private *priv, int command, - void *cmd, int cmd_size); -static void atmel_transmit_management_frame(struct atmel_private *priv, - struct ieee80211_hdr *header, - u8 *body, int body_len); - -static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index); -static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, - u8 data); -static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, - u16 data); -static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, - u8 *data, int data_len); -static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, - u8 *data, int data_len); -static void atmel_scan(struct atmel_private *priv, int specific_ssid); -static void atmel_join_bss(struct atmel_private *priv, int bss_index); -static void atmel_smooth_qual(struct atmel_private *priv); -static void atmel_writeAR(struct net_device *dev, u16 data); -static int probe_atmel_card(struct net_device *dev); -static int reset_atmel_card(struct net_device *dev); -static void atmel_enter_state(struct atmel_private *priv, int new_state); -int atmel_open (struct net_device *dev); - -static inline u16 atmel_hi(struct atmel_private *priv, u16 offset) -{ - return priv->host_info_base + offset; -} - -static inline u16 atmel_co(struct atmel_private *priv, u16 offset) -{ - return priv->host_info.command_pos + offset; -} - -static inline u16 atmel_rx(struct atmel_private *priv, u16 offset, u16 desc) -{ - return priv->host_info.rx_desc_pos + (sizeof(struct rx_desc) * desc) + offset; -} - -static inline u16 atmel_tx(struct atmel_private *priv, u16 offset, u16 desc) -{ - return priv->host_info.tx_desc_pos + (sizeof(struct tx_desc) * desc) + offset; -} - -static inline u8 atmel_read8(struct net_device *dev, u16 offset) -{ - return inb(dev->base_addr + offset); -} - -static inline void atmel_write8(struct net_device *dev, u16 offset, u8 data) -{ - outb(data, dev->base_addr + offset); -} - -static inline u16 atmel_read16(struct net_device *dev, u16 offset) -{ - return inw(dev->base_addr + offset); -} - -static inline void atmel_write16(struct net_device *dev, u16 offset, u16 data) -{ - outw(data, dev->base_addr + offset); -} - -static inline u8 atmel_rmem8(struct atmel_private *priv, u16 pos) -{ - atmel_writeAR(priv->dev, pos); - return atmel_read8(priv->dev, DR); -} - -static inline void atmel_wmem8(struct atmel_private *priv, u16 pos, u16 data) -{ - atmel_writeAR(priv->dev, pos); - atmel_write8(priv->dev, DR, data); -} - -static inline u16 atmel_rmem16(struct atmel_private *priv, u16 pos) -{ - atmel_writeAR(priv->dev, pos); - return atmel_read16(priv->dev, DR); -} - -static inline void atmel_wmem16(struct atmel_private *priv, u16 pos, u16 data) -{ - atmel_writeAR(priv->dev, pos); - atmel_write16(priv->dev, DR, data); -} - -static const struct iw_handler_def atmel_handler_def; - -static void tx_done_irq(struct atmel_private *priv) -{ - int i; - - for (i = 0; - atmel_rmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head)) == TX_DONE && - i < priv->host_info.tx_desc_count; - i++) { - u8 status = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_STATUS_OFFSET, priv->tx_desc_head)); - u16 msdu_size = atmel_rmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_head)); - u8 type = atmel_rmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_head)); - - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_head), 0); - - priv->tx_free_mem += msdu_size; - priv->tx_desc_free++; - - if (priv->tx_buff_head + msdu_size > (priv->host_info.tx_buff_pos + priv->host_info.tx_buff_size)) - priv->tx_buff_head = 0; - else - priv->tx_buff_head += msdu_size; - - if (priv->tx_desc_head < (priv->host_info.tx_desc_count - 1)) - priv->tx_desc_head++ ; - else - priv->tx_desc_head = 0; - - if (type == TX_PACKET_TYPE_DATA) { - if (status == TX_STATUS_SUCCESS) - priv->dev->stats.tx_packets++; - else - priv->dev->stats.tx_errors++; - netif_wake_queue(priv->dev); - } - } -} - -static u16 find_tx_buff(struct atmel_private *priv, u16 len) -{ - u16 bottom_free = priv->host_info.tx_buff_size - priv->tx_buff_tail; - - if (priv->tx_desc_free == 3 || priv->tx_free_mem < len) - return 0; - - if (bottom_free >= len) - return priv->host_info.tx_buff_pos + priv->tx_buff_tail; - - if (priv->tx_free_mem - bottom_free >= len) { - priv->tx_buff_tail = 0; - return priv->host_info.tx_buff_pos; - } - - return 0; -} - -static void tx_update_descriptor(struct atmel_private *priv, int is_bcast, - u16 len, u16 buff, u8 type) -{ - atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, priv->tx_desc_tail), buff); - atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, priv->tx_desc_tail), len); - if (!priv->use_wpa) - atmel_wmem16(priv, atmel_tx(priv, TX_DESC_HOST_LENGTH_OFFSET, priv->tx_desc_tail), len); - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_PACKET_TYPE_OFFSET, priv->tx_desc_tail), type); - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RATE_OFFSET, priv->tx_desc_tail), priv->tx_rate); - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_RETRY_OFFSET, priv->tx_desc_tail), 0); - if (priv->use_wpa) { - int cipher_type, cipher_length; - if (is_bcast) { - cipher_type = priv->group_cipher_suite; - if (cipher_type == CIPHER_SUITE_WEP_64 || - cipher_type == CIPHER_SUITE_WEP_128) - cipher_length = 8; - else if (cipher_type == CIPHER_SUITE_TKIP) - cipher_length = 12; - else if (priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_64 || - priv->pairwise_cipher_suite == CIPHER_SUITE_WEP_128) { - cipher_type = priv->pairwise_cipher_suite; - cipher_length = 8; - } else { - cipher_type = CIPHER_SUITE_NONE; - cipher_length = 0; - } - } else { - cipher_type = priv->pairwise_cipher_suite; - if (cipher_type == CIPHER_SUITE_WEP_64 || - cipher_type == CIPHER_SUITE_WEP_128) - cipher_length = 8; - else if (cipher_type == CIPHER_SUITE_TKIP) - cipher_length = 12; - else if (priv->group_cipher_suite == CIPHER_SUITE_WEP_64 || - priv->group_cipher_suite == CIPHER_SUITE_WEP_128) { - cipher_type = priv->group_cipher_suite; - cipher_length = 8; - } else { - cipher_type = CIPHER_SUITE_NONE; - cipher_length = 0; - } - } - - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_TYPE_OFFSET, priv->tx_desc_tail), - cipher_type); - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_CIPHER_LENGTH_OFFSET, priv->tx_desc_tail), - cipher_length); - } - atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_tail), 0x80000000L); - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, priv->tx_desc_tail), TX_FIRM_OWN); - if (priv->tx_desc_previous != priv->tx_desc_tail) - atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, priv->tx_desc_previous), 0); - priv->tx_desc_previous = priv->tx_desc_tail; - if (priv->tx_desc_tail < (priv->host_info.tx_desc_count - 1)) - priv->tx_desc_tail++; - else - priv->tx_desc_tail = 0; - priv->tx_desc_free--; - priv->tx_free_mem -= len; -} - -static netdev_tx_t start_tx(struct sk_buff *skb, struct net_device *dev) -{ - static const u8 SNAP_RFC1024[6] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - struct atmel_private *priv = netdev_priv(dev); - struct ieee80211_hdr header; - unsigned long flags; - u16 buff, frame_ctl, len = (ETH_ZLEN < skb->len) ? skb->len : ETH_ZLEN; - - if (priv->card && priv->present_callback && - !(*priv->present_callback)(priv->card)) { - dev->stats.tx_errors++; - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - if (priv->station_state != STATION_STATE_READY) { - dev->stats.tx_errors++; - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - /* first ensure the timer func cannot run */ - spin_lock_bh(&priv->timerlock); - /* then stop the hardware ISR */ - spin_lock_irqsave(&priv->irqlock, flags); - /* nb doing the above in the opposite order will deadlock */ - - /* The Wireless Header is 30 bytes. In the Ethernet packet we "cut" the - 12 first bytes (containing DA/SA) and put them in the appropriate - fields of the Wireless Header. Thus the packet length is then the - initial + 18 (+30-12) */ - - if (!(buff = find_tx_buff(priv, len + 18))) { - dev->stats.tx_dropped++; - spin_unlock_irqrestore(&priv->irqlock, flags); - spin_unlock_bh(&priv->timerlock); - netif_stop_queue(dev); - return NETDEV_TX_BUSY; - } - - frame_ctl = IEEE80211_FTYPE_DATA; - header.duration_id = 0; - header.seq_ctrl = 0; - if (priv->wep_is_on) - frame_ctl |= IEEE80211_FCTL_PROTECTED; - if (priv->operating_mode == IW_MODE_ADHOC) { - skb_copy_from_linear_data(skb, &header.addr1, 6); - memcpy(&header.addr2, dev->dev_addr, 6); - memcpy(&header.addr3, priv->BSSID, 6); - } else { - frame_ctl |= IEEE80211_FCTL_TODS; - memcpy(&header.addr1, priv->CurrentBSSID, 6); - memcpy(&header.addr2, dev->dev_addr, 6); - skb_copy_from_linear_data(skb, &header.addr3, 6); - } - - if (priv->use_wpa) - memcpy(&header.addr4, SNAP_RFC1024, 6); - - header.frame_control = cpu_to_le16(frame_ctl); - /* Copy the wireless header into the card */ - atmel_copy_to_card(dev, buff, (unsigned char *)&header, DATA_FRAME_WS_HEADER_SIZE); - /* Copy the packet sans its 802.3 header addresses which have been replaced */ - atmel_copy_to_card(dev, buff + DATA_FRAME_WS_HEADER_SIZE, skb->data + 12, len - 12); - priv->tx_buff_tail += len - 12 + DATA_FRAME_WS_HEADER_SIZE; - - /* low bit of first byte of destination tells us if broadcast */ - tx_update_descriptor(priv, *(skb->data) & 0x01, len + 18, buff, TX_PACKET_TYPE_DATA); - dev->trans_start = jiffies; - dev->stats.tx_bytes += len; - - spin_unlock_irqrestore(&priv->irqlock, flags); - spin_unlock_bh(&priv->timerlock); - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} - -static void atmel_transmit_management_frame(struct atmel_private *priv, - struct ieee80211_hdr *header, - u8 *body, int body_len) -{ - u16 buff; - int len = MGMT_FRAME_BODY_OFFSET + body_len; - - if (!(buff = find_tx_buff(priv, len))) - return; - - atmel_copy_to_card(priv->dev, buff, (u8 *)header, MGMT_FRAME_BODY_OFFSET); - atmel_copy_to_card(priv->dev, buff + MGMT_FRAME_BODY_OFFSET, body, body_len); - priv->tx_buff_tail += len; - tx_update_descriptor(priv, header->addr1[0] & 0x01, len, buff, TX_PACKET_TYPE_MGMT); -} - -static void fast_rx_path(struct atmel_private *priv, - struct ieee80211_hdr *header, - u16 msdu_size, u16 rx_packet_loc, u32 crc) -{ - /* fast path: unfragmented packet copy directly into skbuf */ - u8 mac4[6]; - struct sk_buff *skb; - unsigned char *skbp; - - /* get the final, mac 4 header field, this tells us encapsulation */ - atmel_copy_to_host(priv->dev, mac4, rx_packet_loc + 24, 6); - msdu_size -= 6; - - if (priv->do_rx_crc) { - crc = crc32_le(crc, mac4, 6); - msdu_size -= 4; - } - - if (!(skb = dev_alloc_skb(msdu_size + 14))) { - priv->dev->stats.rx_dropped++; - return; - } - - skb_reserve(skb, 2); - skbp = skb_put(skb, msdu_size + 12); - atmel_copy_to_host(priv->dev, skbp + 12, rx_packet_loc + 30, msdu_size); - - if (priv->do_rx_crc) { - u32 netcrc; - crc = crc32_le(crc, skbp + 12, msdu_size); - atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + 30 + msdu_size, 4); - if ((crc ^ 0xffffffff) != netcrc) { - priv->dev->stats.rx_crc_errors++; - dev_kfree_skb(skb); - return; - } - } - - memcpy(skbp, header->addr1, 6); /* destination address */ - if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) - memcpy(&skbp[6], header->addr3, 6); - else - memcpy(&skbp[6], header->addr2, 6); /* source address */ - - skb->protocol = eth_type_trans(skb, priv->dev); - skb->ip_summed = CHECKSUM_NONE; - netif_rx(skb); - priv->dev->stats.rx_bytes += 12 + msdu_size; - priv->dev->stats.rx_packets++; -} - -/* Test to see if the packet in card memory at packet_loc has a valid CRC - It doesn't matter that this is slow: it is only used to proble the first few - packets. */ -static int probe_crc(struct atmel_private *priv, u16 packet_loc, u16 msdu_size) -{ - int i = msdu_size - 4; - u32 netcrc, crc = 0xffffffff; - - if (msdu_size < 4) - return 0; - - atmel_copy_to_host(priv->dev, (void *)&netcrc, packet_loc + i, 4); - - atmel_writeAR(priv->dev, packet_loc); - while (i--) { - u8 octet = atmel_read8(priv->dev, DR); - crc = crc32_le(crc, &octet, 1); - } - - return (crc ^ 0xffffffff) == netcrc; -} - -static void frag_rx_path(struct atmel_private *priv, - struct ieee80211_hdr *header, - u16 msdu_size, u16 rx_packet_loc, u32 crc, u16 seq_no, - u8 frag_no, int more_frags) -{ - u8 mac4[6]; - u8 source[6]; - struct sk_buff *skb; - - if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) - memcpy(source, header->addr3, 6); - else - memcpy(source, header->addr2, 6); - - rx_packet_loc += 24; /* skip header */ - - if (priv->do_rx_crc) - msdu_size -= 4; - - if (frag_no == 0) { /* first fragment */ - atmel_copy_to_host(priv->dev, mac4, rx_packet_loc, 6); - msdu_size -= 6; - rx_packet_loc += 6; - - if (priv->do_rx_crc) - crc = crc32_le(crc, mac4, 6); - - priv->frag_seq = seq_no; - priv->frag_no = 1; - priv->frag_len = msdu_size; - memcpy(priv->frag_source, source, 6); - memcpy(&priv->rx_buf[6], source, 6); - memcpy(priv->rx_buf, header->addr1, 6); - - atmel_copy_to_host(priv->dev, &priv->rx_buf[12], rx_packet_loc, msdu_size); - - if (priv->do_rx_crc) { - u32 netcrc; - crc = crc32_le(crc, &priv->rx_buf[12], msdu_size); - atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4); - if ((crc ^ 0xffffffff) != netcrc) { - priv->dev->stats.rx_crc_errors++; - memset(priv->frag_source, 0xff, 6); - } - } - - } else if (priv->frag_no == frag_no && - priv->frag_seq == seq_no && - memcmp(priv->frag_source, source, 6) == 0) { - - atmel_copy_to_host(priv->dev, &priv->rx_buf[12 + priv->frag_len], - rx_packet_loc, msdu_size); - if (priv->do_rx_crc) { - u32 netcrc; - crc = crc32_le(crc, - &priv->rx_buf[12 + priv->frag_len], - msdu_size); - atmel_copy_to_host(priv->dev, (void *)&netcrc, rx_packet_loc + msdu_size, 4); - if ((crc ^ 0xffffffff) != netcrc) { - priv->dev->stats.rx_crc_errors++; - memset(priv->frag_source, 0xff, 6); - more_frags = 1; /* don't send broken assembly */ - } - } - - priv->frag_len += msdu_size; - priv->frag_no++; - - if (!more_frags) { /* last one */ - memset(priv->frag_source, 0xff, 6); - if (!(skb = dev_alloc_skb(priv->frag_len + 14))) { - priv->dev->stats.rx_dropped++; - } else { - skb_reserve(skb, 2); - memcpy(skb_put(skb, priv->frag_len + 12), - priv->rx_buf, - priv->frag_len + 12); - skb->protocol = eth_type_trans(skb, priv->dev); - skb->ip_summed = CHECKSUM_NONE; - netif_rx(skb); - priv->dev->stats.rx_bytes += priv->frag_len + 12; - priv->dev->stats.rx_packets++; - } - } - } else - priv->wstats.discard.fragment++; -} - -static void rx_done_irq(struct atmel_private *priv) -{ - int i; - struct ieee80211_hdr header; - - for (i = 0; - atmel_rmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head)) == RX_DESC_FLAG_VALID && - i < priv->host_info.rx_desc_count; - i++) { - - u16 msdu_size, rx_packet_loc, frame_ctl, seq_control; - u8 status = atmel_rmem8(priv, atmel_rx(priv, RX_DESC_STATUS_OFFSET, priv->rx_desc_head)); - u32 crc = 0xffffffff; - - if (status != RX_STATUS_SUCCESS) { - if (status == 0xc1) /* determined by experiment */ - priv->wstats.discard.nwid++; - else - priv->dev->stats.rx_errors++; - goto next; - } - - msdu_size = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_SIZE_OFFSET, priv->rx_desc_head)); - rx_packet_loc = atmel_rmem16(priv, atmel_rx(priv, RX_DESC_MSDU_POS_OFFSET, priv->rx_desc_head)); - - if (msdu_size < 30) { - priv->dev->stats.rx_errors++; - goto next; - } - - /* Get header as far as end of seq_ctrl */ - atmel_copy_to_host(priv->dev, (char *)&header, rx_packet_loc, 24); - frame_ctl = le16_to_cpu(header.frame_control); - seq_control = le16_to_cpu(header.seq_ctrl); - - /* probe for CRC use here if needed once five packets have - arrived with the same crc status, we assume we know what's - happening and stop probing */ - if (priv->probe_crc) { - if (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED)) { - priv->do_rx_crc = probe_crc(priv, rx_packet_loc, msdu_size); - } else { - priv->do_rx_crc = probe_crc(priv, rx_packet_loc + 24, msdu_size - 24); - } - if (priv->do_rx_crc) { - if (priv->crc_ok_cnt++ > 5) - priv->probe_crc = 0; - } else { - if (priv->crc_ko_cnt++ > 5) - priv->probe_crc = 0; - } - } - - /* don't CRC header when WEP in use */ - if (priv->do_rx_crc && (!priv->wep_is_on || !(frame_ctl & IEEE80211_FCTL_PROTECTED))) { - crc = crc32_le(0xffffffff, (unsigned char *)&header, 24); - } - msdu_size -= 24; /* header */ - - if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) { - int more_fragments = frame_ctl & IEEE80211_FCTL_MOREFRAGS; - u8 packet_fragment_no = seq_control & IEEE80211_SCTL_FRAG; - u16 packet_sequence_no = (seq_control & IEEE80211_SCTL_SEQ) >> 4; - - if (!more_fragments && packet_fragment_no == 0) { - fast_rx_path(priv, &header, msdu_size, rx_packet_loc, crc); - } else { - frag_rx_path(priv, &header, msdu_size, rx_packet_loc, crc, - packet_sequence_no, packet_fragment_no, more_fragments); - } - } - - if ((frame_ctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) { - /* copy rest of packet into buffer */ - atmel_copy_to_host(priv->dev, (unsigned char *)&priv->rx_buf, rx_packet_loc + 24, msdu_size); - - /* we use the same buffer for frag reassembly and control packets */ - memset(priv->frag_source, 0xff, 6); - - if (priv->do_rx_crc) { - /* last 4 octets is crc */ - msdu_size -= 4; - crc = crc32_le(crc, (unsigned char *)&priv->rx_buf, msdu_size); - if ((crc ^ 0xffffffff) != (*((u32 *)&priv->rx_buf[msdu_size]))) { - priv->dev->stats.rx_crc_errors++; - goto next; - } - } - - atmel_management_frame(priv, &header, msdu_size, - atmel_rmem8(priv, atmel_rx(priv, RX_DESC_RSSI_OFFSET, priv->rx_desc_head))); - } - -next: - /* release descriptor */ - atmel_wmem8(priv, atmel_rx(priv, RX_DESC_FLAGS_OFFSET, priv->rx_desc_head), RX_DESC_FLAG_CONSUMED); - - if (priv->rx_desc_head < (priv->host_info.rx_desc_count - 1)) - priv->rx_desc_head++; - else - priv->rx_desc_head = 0; - } -} - -static irqreturn_t service_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *) dev_id; - struct atmel_private *priv = netdev_priv(dev); - u8 isr; - int i = -1; - static u8 irq_order[] = { - ISR_OUT_OF_RANGE, - ISR_RxCOMPLETE, - ISR_TxCOMPLETE, - ISR_RxFRAMELOST, - ISR_FATAL_ERROR, - ISR_COMMAND_COMPLETE, - ISR_IBSS_MERGE, - ISR_GENERIC_IRQ - }; - - if (priv->card && priv->present_callback && - !(*priv->present_callback)(priv->card)) - return IRQ_HANDLED; - - /* In this state upper-level code assumes it can mess with - the card unhampered by interrupts which may change register state. - Note that even though the card shouldn't generate interrupts - the inturrupt line may be shared. This allows card setup - to go on without disabling interrupts for a long time. */ - if (priv->station_state == STATION_STATE_DOWN) - return IRQ_NONE; - - atmel_clear_gcr(dev, GCR_ENINT); /* disable interrupts */ - - while (1) { - if (!atmel_lock_mac(priv)) { - /* failed to contact card */ - printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name); - return IRQ_HANDLED; - } - - isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET)); - atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0); - - if (!isr) { - atmel_set_gcr(dev, GCR_ENINT); /* enable interrupts */ - return i == -1 ? IRQ_NONE : IRQ_HANDLED; - } - - atmel_set_gcr(dev, GCR_ACKINT); /* acknowledge interrupt */ - - for (i = 0; i < ARRAY_SIZE(irq_order); i++) - if (isr & irq_order[i]) - break; - - if (!atmel_lock_mac(priv)) { - /* failed to contact card */ - printk(KERN_ALERT "%s: failed to contact MAC.\n", dev->name); - return IRQ_HANDLED; - } - - isr = atmel_rmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET)); - isr ^= irq_order[i]; - atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_STATUS_OFFSET), isr); - atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0); - - switch (irq_order[i]) { - - case ISR_OUT_OF_RANGE: - if (priv->operating_mode == IW_MODE_INFRA && - priv->station_state == STATION_STATE_READY) { - priv->station_is_associated = 0; - atmel_scan(priv, 1); - } - break; - - case ISR_RxFRAMELOST: - priv->wstats.discard.misc++; - /* fall through */ - case ISR_RxCOMPLETE: - rx_done_irq(priv); - break; - - case ISR_TxCOMPLETE: - tx_done_irq(priv); - break; - - case ISR_FATAL_ERROR: - printk(KERN_ALERT "%s: *** FATAL error interrupt ***\n", dev->name); - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - break; - - case ISR_COMMAND_COMPLETE: - atmel_command_irq(priv); - break; - - case ISR_IBSS_MERGE: - atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, - priv->CurrentBSSID, 6); - /* The WPA stuff cares about the current AP address */ - if (priv->use_wpa) - build_wpa_mib(priv); - break; - case ISR_GENERIC_IRQ: - printk(KERN_INFO "%s: Generic_irq received.\n", dev->name); - break; - } - } -} - -static struct iw_statistics *atmel_get_wireless_stats(struct net_device *dev) -{ - struct atmel_private *priv = netdev_priv(dev); - - /* update the link quality here in case we are seeing no beacons - at all to drive the process */ - atmel_smooth_qual(priv); - - priv->wstats.status = priv->station_state; - - if (priv->operating_mode == IW_MODE_INFRA) { - if (priv->station_state != STATION_STATE_READY) { - priv->wstats.qual.qual = 0; - priv->wstats.qual.level = 0; - priv->wstats.qual.updated = (IW_QUAL_QUAL_INVALID - | IW_QUAL_LEVEL_INVALID); - } - priv->wstats.qual.noise = 0; - priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID; - } else { - /* Quality levels cannot be determined in ad-hoc mode, - because we can 'hear' more that one remote station. */ - priv->wstats.qual.qual = 0; - priv->wstats.qual.level = 0; - priv->wstats.qual.noise = 0; - priv->wstats.qual.updated = IW_QUAL_QUAL_INVALID - | IW_QUAL_LEVEL_INVALID - | IW_QUAL_NOISE_INVALID; - priv->wstats.miss.beacon = 0; - } - - return &priv->wstats; -} - -static int atmel_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > 2312)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -static int atmel_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - - memcpy (dev->dev_addr, addr->sa_data, dev->addr_len); - return atmel_open(dev); -} - -EXPORT_SYMBOL(atmel_open); - -int atmel_open(struct net_device *dev) -{ - struct atmel_private *priv = netdev_priv(dev); - int i, channel, err; - - /* any scheduled timer is no longer needed and might screw things up.. */ - del_timer_sync(&priv->management_timer); - - /* Interrupts will not touch the card once in this state... */ - priv->station_state = STATION_STATE_DOWN; - - if (priv->new_SSID_size) { - memcpy(priv->SSID, priv->new_SSID, priv->new_SSID_size); - priv->SSID_size = priv->new_SSID_size; - priv->new_SSID_size = 0; - } - priv->BSS_list_entries = 0; - - priv->AuthenticationRequestRetryCnt = 0; - priv->AssociationRequestRetryCnt = 0; - priv->ReAssociationRequestRetryCnt = 0; - priv->CurrentAuthentTransactionSeqNum = 0x0001; - priv->ExpectedAuthentTransactionSeqNum = 0x0002; - - priv->site_survey_state = SITE_SURVEY_IDLE; - priv->station_is_associated = 0; - - err = reset_atmel_card(dev); - if (err) - return err; - - if (priv->config_reg_domain) { - priv->reg_domain = priv->config_reg_domain; - atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS, priv->reg_domain); - } else { - priv->reg_domain = atmel_get_mib8(priv, Phy_Mib_Type, PHY_MIB_REG_DOMAIN_POS); - for (i = 0; i < ARRAY_SIZE(channel_table); i++) - if (priv->reg_domain == channel_table[i].reg_domain) - break; - if (i == ARRAY_SIZE(channel_table)) { - priv->reg_domain = REG_DOMAIN_MKK1; - printk(KERN_ALERT "%s: failed to get regulatory domain: assuming MKK1.\n", dev->name); - } - } - - if ((channel = atmel_validate_channel(priv, priv->channel))) - priv->channel = channel; - - /* this moves station_state on.... */ - atmel_scan(priv, 1); - - atmel_set_gcr(priv->dev, GCR_ENINT); /* enable interrupts */ - return 0; -} - -static int atmel_close(struct net_device *dev) -{ - struct atmel_private *priv = netdev_priv(dev); - - /* Send event to userspace that we are disassociating */ - if (priv->station_state == STATION_STATE_READY) { - union iwreq_data wrqu; - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - } - - atmel_enter_state(priv, STATION_STATE_DOWN); - - if (priv->bus_type == BUS_TYPE_PCCARD) - atmel_write16(dev, GCR, 0x0060); - atmel_write16(dev, GCR, 0x0040); - return 0; -} - -static int atmel_validate_channel(struct atmel_private *priv, int channel) -{ - /* check that channel is OK, if so return zero, - else return suitable default channel */ - int i; - - for (i = 0; i < ARRAY_SIZE(channel_table); i++) - if (priv->reg_domain == channel_table[i].reg_domain) { - if (channel >= channel_table[i].min && - channel <= channel_table[i].max) - return 0; - else - return channel_table[i].min; - } - return 0; -} - -static int atmel_proc_output (char *buf, struct atmel_private *priv) -{ - int i; - char *p = buf; - char *s, *r, *c; - - p += sprintf(p, "Driver version:\t\t%d.%d\n", - DRIVER_MAJOR, DRIVER_MINOR); - - if (priv->station_state != STATION_STATE_DOWN) { - p += sprintf(p, "Firmware version:\t%d.%d build %d\n" - "Firmware location:\t", - priv->host_info.major_version, - priv->host_info.minor_version, - priv->host_info.build_version); - - if (priv->card_type != CARD_TYPE_EEPROM) - p += sprintf(p, "on card\n"); - else if (priv->firmware) - p += sprintf(p, "%s loaded by host\n", - priv->firmware_id); - else - p += sprintf(p, "%s loaded by hotplug\n", - priv->firmware_id); - - switch (priv->card_type) { - case CARD_TYPE_PARALLEL_FLASH: - c = "Parallel flash"; - break; - case CARD_TYPE_SPI_FLASH: - c = "SPI flash\n"; - break; - case CARD_TYPE_EEPROM: - c = "EEPROM"; - break; - default: - c = ""; - } - - r = ""; - for (i = 0; i < ARRAY_SIZE(channel_table); i++) - if (priv->reg_domain == channel_table[i].reg_domain) - r = channel_table[i].name; - - p += sprintf(p, "MAC memory type:\t%s\n", c); - p += sprintf(p, "Regulatory domain:\t%s\n", r); - p += sprintf(p, "Host CRC checking:\t%s\n", - priv->do_rx_crc ? "On" : "Off"); - p += sprintf(p, "WPA-capable firmware:\t%s\n", - priv->use_wpa ? "Yes" : "No"); - } - - switch (priv->station_state) { - case STATION_STATE_SCANNING: - s = "Scanning"; - break; - case STATION_STATE_JOINNING: - s = "Joining"; - break; - case STATION_STATE_AUTHENTICATING: - s = "Authenticating"; - break; - case STATION_STATE_ASSOCIATING: - s = "Associating"; - break; - case STATION_STATE_READY: - s = "Ready"; - break; - case STATION_STATE_REASSOCIATING: - s = "Reassociating"; - break; - case STATION_STATE_MGMT_ERROR: - s = "Management error"; - break; - case STATION_STATE_DOWN: - s = "Down"; - break; - default: - s = ""; - } - - p += sprintf(p, "Current state:\t\t%s\n", s); - return p - buf; -} - -static int atmel_read_proc(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - struct atmel_private *priv = data; - int len = atmel_proc_output (page, priv); - if (len <= off+count) - *eof = 1; - *start = page + off; - len -= off; - if (len > count) - len = count; - if (len < 0) - len = 0; - return len; -} - -static const struct net_device_ops atmel_netdev_ops = { - .ndo_open = atmel_open, - .ndo_stop = atmel_close, - .ndo_change_mtu = atmel_change_mtu, - .ndo_set_mac_address = atmel_set_mac_address, - .ndo_start_xmit = start_tx, - .ndo_do_ioctl = atmel_ioctl, - .ndo_validate_addr = eth_validate_addr, -}; - -struct net_device *init_atmel_card(unsigned short irq, unsigned long port, - const AtmelFWType fw_type, - struct device *sys_dev, - int (*card_present)(void *), void *card) -{ - struct proc_dir_entry *ent; - struct net_device *dev; - struct atmel_private *priv; - int rc; - - /* Create the network device object. */ - dev = alloc_etherdev(sizeof(*priv)); - if (!dev) { - printk(KERN_ERR "atmel: Couldn't alloc_etherdev\n"); - return NULL; - } - if (dev_alloc_name(dev, dev->name) < 0) { - printk(KERN_ERR "atmel: Couldn't get name!\n"); - goto err_out_free; - } - - priv = netdev_priv(dev); - priv->dev = dev; - priv->sys_dev = sys_dev; - priv->present_callback = card_present; - priv->card = card; - priv->firmware = NULL; - priv->firmware_id[0] = '\0'; - priv->firmware_type = fw_type; - if (firmware) /* module parameter */ - strcpy(priv->firmware_id, firmware); - priv->bus_type = card_present ? BUS_TYPE_PCCARD : BUS_TYPE_PCI; - priv->station_state = STATION_STATE_DOWN; - priv->do_rx_crc = 0; - /* For PCMCIA cards, some chips need CRC, some don't - so we have to probe. */ - if (priv->bus_type == BUS_TYPE_PCCARD) { - priv->probe_crc = 1; - priv->crc_ok_cnt = priv->crc_ko_cnt = 0; - } else - priv->probe_crc = 0; - priv->last_qual = jiffies; - priv->last_beacon_timestamp = 0; - memset(priv->frag_source, 0xff, sizeof(priv->frag_source)); - memset(priv->BSSID, 0, 6); - priv->CurrentBSSID[0] = 0xFF; /* Initialize to something invalid.... */ - priv->station_was_associated = 0; - - priv->last_survey = jiffies; - priv->preamble = LONG_PREAMBLE; - priv->operating_mode = IW_MODE_INFRA; - priv->connect_to_any_BSS = 0; - priv->config_reg_domain = 0; - priv->reg_domain = 0; - priv->tx_rate = 3; - priv->auto_tx_rate = 1; - priv->channel = 4; - priv->power_mode = 0; - priv->SSID[0] = '\0'; - priv->SSID_size = 0; - priv->new_SSID_size = 0; - priv->frag_threshold = 2346; - priv->rts_threshold = 2347; - priv->short_retry = 7; - priv->long_retry = 4; - - priv->wep_is_on = 0; - priv->default_key = 0; - priv->encryption_level = 0; - priv->exclude_unencrypted = 0; - priv->group_cipher_suite = priv->pairwise_cipher_suite = CIPHER_SUITE_NONE; - priv->use_wpa = 0; - memset(priv->wep_keys, 0, sizeof(priv->wep_keys)); - memset(priv->wep_key_len, 0, sizeof(priv->wep_key_len)); - - priv->default_beacon_period = priv->beacon_period = 100; - priv->listen_interval = 1; - - init_timer(&priv->management_timer); - spin_lock_init(&priv->irqlock); - spin_lock_init(&priv->timerlock); - priv->management_timer.function = atmel_management_timer; - priv->management_timer.data = (unsigned long) dev; - - dev->netdev_ops = &atmel_netdev_ops; - dev->wireless_handlers = &atmel_handler_def; - dev->irq = irq; - dev->base_addr = port; - - SET_NETDEV_DEV(dev, sys_dev); - - if ((rc = request_irq(dev->irq, service_interrupt, IRQF_SHARED, dev->name, dev))) { - printk(KERN_ERR "%s: register interrupt %d failed, rc %d\n", dev->name, irq, rc); - goto err_out_free; - } - - if (!request_region(dev->base_addr, 32, - priv->bus_type == BUS_TYPE_PCCARD ? "atmel_cs" : "atmel_pci")) { - goto err_out_irq; - } - - if (register_netdev(dev)) - goto err_out_res; - - if (!probe_atmel_card(dev)) { - unregister_netdev(dev); - goto err_out_res; - } - - netif_carrier_off(dev); - - ent = create_proc_read_entry ("driver/atmel", 0, NULL, atmel_read_proc, priv); - if (!ent) - printk(KERN_WARNING "atmel: unable to create /proc entry.\n"); - - printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n", - dev->name, DRIVER_MAJOR, DRIVER_MINOR, dev->dev_addr); - - return dev; - -err_out_res: - release_region(dev->base_addr, 32); -err_out_irq: - free_irq(dev->irq, dev); -err_out_free: - free_netdev(dev); - return NULL; -} - -EXPORT_SYMBOL(init_atmel_card); - -void stop_atmel_card(struct net_device *dev) -{ - struct atmel_private *priv = netdev_priv(dev); - - /* put a brick on it... */ - if (priv->bus_type == BUS_TYPE_PCCARD) - atmel_write16(dev, GCR, 0x0060); - atmel_write16(dev, GCR, 0x0040); - - del_timer_sync(&priv->management_timer); - unregister_netdev(dev); - remove_proc_entry("driver/atmel", NULL); - free_irq(dev->irq, dev); - kfree(priv->firmware); - release_region(dev->base_addr, 32); - free_netdev(dev); -} - -EXPORT_SYMBOL(stop_atmel_card); - -static int atmel_set_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - /* Check if we asked for `any' */ - if (dwrq->flags == 0) { - priv->connect_to_any_BSS = 1; - } else { - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - - priv->connect_to_any_BSS = 0; - - /* Check the size of the string */ - if (dwrq->length > MAX_SSID_LENGTH) - return -E2BIG; - if (index != 0) - return -EINVAL; - - memcpy(priv->new_SSID, extra, dwrq->length); - priv->new_SSID_size = dwrq->length; - } - - return -EINPROGRESS; -} - -static int atmel_get_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - /* Get the current SSID */ - if (priv->new_SSID_size != 0) { - memcpy(extra, priv->new_SSID, priv->new_SSID_size); - dwrq->length = priv->new_SSID_size; - } else { - memcpy(extra, priv->SSID, priv->SSID_size); - dwrq->length = priv->SSID_size; - } - - dwrq->flags = !priv->connect_to_any_BSS; /* active */ - - return 0; -} - -static int atmel_get_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - memcpy(awrq->sa_data, priv->CurrentBSSID, 6); - awrq->sa_family = ARPHRD_ETHER; - - return 0; -} - -static int atmel_set_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - /* Basic checking: do we have a key to set ? - * Note : with the new API, it's impossible to get a NULL pointer. - * Therefore, we need to check a key size == 0 instead. - * New version of iwconfig properly set the IW_ENCODE_NOKEY flag - * when no key is present (only change flags), but older versions - * don't do it. - Jean II */ - if (dwrq->length > 0) { - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - int current_index = priv->default_key; - /* Check the size of the key */ - if (dwrq->length > 13) { - return -EINVAL; - } - /* Check the index (none -> use current) */ - if (index < 0 || index >= 4) - index = current_index; - else - priv->default_key = index; - /* Set the length */ - if (dwrq->length > 5) - priv->wep_key_len[index] = 13; - else - if (dwrq->length > 0) - priv->wep_key_len[index] = 5; - else - /* Disable the key */ - priv->wep_key_len[index] = 0; - /* Check if the key is not marked as invalid */ - if (!(dwrq->flags & IW_ENCODE_NOKEY)) { - /* Cleanup */ - memset(priv->wep_keys[index], 0, 13); - /* Copy the key in the driver */ - memcpy(priv->wep_keys[index], extra, dwrq->length); - } - /* WE specify that if a valid key is set, encryption - * should be enabled (user may turn it off later) - * This is also how "iwconfig ethX key on" works */ - if (index == current_index && - priv->wep_key_len[index] > 0) { - priv->wep_is_on = 1; - priv->exclude_unencrypted = 1; - if (priv->wep_key_len[index] > 5) { - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; - priv->encryption_level = 2; - } else { - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; - priv->encryption_level = 1; - } - } - } else { - /* Do we want to just set the transmit key index ? */ - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (index >= 0 && index < 4) { - priv->default_key = index; - } else - /* Don't complain if only change the mode */ - if (!(dwrq->flags & IW_ENCODE_MODE)) - return -EINVAL; - } - /* Read the flags */ - if (dwrq->flags & IW_ENCODE_DISABLED) { - priv->wep_is_on = 0; - priv->encryption_level = 0; - priv->pairwise_cipher_suite = CIPHER_SUITE_NONE; - } else { - priv->wep_is_on = 1; - if (priv->wep_key_len[priv->default_key] > 5) { - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; - priv->encryption_level = 2; - } else { - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; - priv->encryption_level = 1; - } - } - if (dwrq->flags & IW_ENCODE_RESTRICTED) - priv->exclude_unencrypted = 1; - if (dwrq->flags & IW_ENCODE_OPEN) - priv->exclude_unencrypted = 0; - - return -EINPROGRESS; /* Call commit handler */ -} - -static int atmel_get_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - - if (!priv->wep_is_on) - dwrq->flags = IW_ENCODE_DISABLED; - else { - if (priv->exclude_unencrypted) - dwrq->flags = IW_ENCODE_RESTRICTED; - else - dwrq->flags = IW_ENCODE_OPEN; - } - /* Which key do we want ? -1 -> tx index */ - if (index < 0 || index >= 4) - index = priv->default_key; - dwrq->flags |= index + 1; - /* Copy the key to the user buffer */ - dwrq->length = priv->wep_key_len[index]; - if (dwrq->length > 16) { - dwrq->length = 0; - } else { - memset(extra, 0, 16); - memcpy(extra, priv->wep_keys[index], dwrq->length); - } - - return 0; -} - -static int atmel_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, key_len, alg = ext->alg, set_key = 1; - - /* Determine and validate the key index */ - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > 4) - return -EINVAL; - idx--; - } else - idx = priv->default_key; - - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - priv->default_key = idx; - set_key = ext->key_len > 0 ? 1 : 0; - } - - if (set_key) { - /* Set the requested key first */ - switch (alg) { - case IW_ENCODE_ALG_NONE: - priv->wep_is_on = 0; - priv->encryption_level = 0; - priv->pairwise_cipher_suite = CIPHER_SUITE_NONE; - break; - case IW_ENCODE_ALG_WEP: - if (ext->key_len > 5) { - priv->wep_key_len[idx] = 13; - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_128; - priv->encryption_level = 2; - } else if (ext->key_len > 0) { - priv->wep_key_len[idx] = 5; - priv->pairwise_cipher_suite = CIPHER_SUITE_WEP_64; - priv->encryption_level = 1; - } else { - return -EINVAL; - } - priv->wep_is_on = 1; - memset(priv->wep_keys[idx], 0, 13); - key_len = min ((int)ext->key_len, priv->wep_key_len[idx]); - memcpy(priv->wep_keys[idx], ext->key, key_len); - break; - default: - return -EINVAL; - } - } - - return -EINPROGRESS; -} - -static int atmel_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, max_key_len; - - max_key_len = encoding->length - sizeof(*ext); - if (max_key_len < 0) - return -EINVAL; - - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > 4) - return -EINVAL; - idx--; - } else - idx = priv->default_key; - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - if (!priv->wep_is_on) { - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - encoding->flags |= IW_ENCODE_DISABLED; - } else { - if (priv->encryption_level > 0) - ext->alg = IW_ENCODE_ALG_WEP; - else - return -EINVAL; - - ext->key_len = priv->wep_key_len[idx]; - memcpy(ext->key, priv->wep_keys[idx], ext->key_len); - encoding->flags |= IW_ENCODE_ENABLED; - } - - return 0; -} - -static int atmel_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - struct iw_param *param = &wrqu->param; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - case IW_AUTH_PRIVACY_INVOKED: - /* - * atmel does not use these parameters - */ - break; - - case IW_AUTH_DROP_UNENCRYPTED: - priv->exclude_unencrypted = param->value ? 1 : 0; - break; - - case IW_AUTH_80211_AUTH_ALG: { - if (param->value & IW_AUTH_ALG_SHARED_KEY) { - priv->exclude_unencrypted = 1; - } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - priv->exclude_unencrypted = 0; - } else - return -EINVAL; - break; - } - - case IW_AUTH_WPA_ENABLED: - /* Silently accept disable of WPA */ - if (param->value > 0) - return -EOPNOTSUPP; - break; - - default: - return -EOPNOTSUPP; - } - return -EINPROGRESS; -} - -static int atmel_get_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - struct iw_param *param = &wrqu->param; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_DROP_UNENCRYPTED: - param->value = priv->exclude_unencrypted; - break; - - case IW_AUTH_80211_AUTH_ALG: - if (priv->exclude_unencrypted == 1) - param->value = IW_AUTH_ALG_SHARED_KEY; - else - param->value = IW_AUTH_ALG_OPEN_SYSTEM; - break; - - case IW_AUTH_WPA_ENABLED: - param->value = 0; - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - - -static int atmel_get_name(struct net_device *dev, - struct iw_request_info *info, - char *cwrq, - char *extra) -{ - strcpy(cwrq, "IEEE 802.11-DS"); - return 0; -} - -static int atmel_set_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - if (vwrq->fixed == 0) { - priv->tx_rate = 3; - priv->auto_tx_rate = 1; - } else { - priv->auto_tx_rate = 0; - - /* Which type of value ? */ - if ((vwrq->value < 4) && (vwrq->value >= 0)) { - /* Setting by rate index */ - priv->tx_rate = vwrq->value; - } else { - /* Setting by frequency value */ - switch (vwrq->value) { - case 1000000: - priv->tx_rate = 0; - break; - case 2000000: - priv->tx_rate = 1; - break; - case 5500000: - priv->tx_rate = 2; - break; - case 11000000: - priv->tx_rate = 3; - break; - default: - return -EINVAL; - } - } - } - - return -EINPROGRESS; -} - -static int atmel_set_mode(struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - if (*uwrq != IW_MODE_ADHOC && *uwrq != IW_MODE_INFRA) - return -EINVAL; - - priv->operating_mode = *uwrq; - return -EINPROGRESS; -} - -static int atmel_get_mode(struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - *uwrq = priv->operating_mode; - return 0; -} - -static int atmel_get_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - if (priv->auto_tx_rate) { - vwrq->fixed = 0; - vwrq->value = 11000000; - } else { - vwrq->fixed = 1; - switch (priv->tx_rate) { - case 0: - vwrq->value = 1000000; - break; - case 1: - vwrq->value = 2000000; - break; - case 2: - vwrq->value = 5500000; - break; - case 3: - vwrq->value = 11000000; - break; - } - } - return 0; -} - -static int atmel_set_power(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - priv->power_mode = vwrq->disabled ? 0 : 1; - return -EINPROGRESS; -} - -static int atmel_get_power(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - vwrq->disabled = priv->power_mode ? 0 : 1; - vwrq->flags = IW_POWER_ON; - return 0; -} - -static int atmel_set_retry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - if (!vwrq->disabled && (vwrq->flags & IW_RETRY_LIMIT)) { - if (vwrq->flags & IW_RETRY_LONG) - priv->long_retry = vwrq->value; - else if (vwrq->flags & IW_RETRY_SHORT) - priv->short_retry = vwrq->value; - else { - /* No modifier : set both */ - priv->long_retry = vwrq->value; - priv->short_retry = vwrq->value; - } - return -EINPROGRESS; - } - - return -EINVAL; -} - -static int atmel_get_retry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - vwrq->disabled = 0; /* Can't be disabled */ - - /* Note : by default, display the short retry number */ - if (vwrq->flags & IW_RETRY_LONG) { - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - vwrq->value = priv->long_retry; - } else { - vwrq->flags = IW_RETRY_LIMIT; - vwrq->value = priv->short_retry; - if (priv->long_retry != priv->short_retry) - vwrq->flags |= IW_RETRY_SHORT; - } - - return 0; -} - -static int atmel_set_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - int rthr = vwrq->value; - - if (vwrq->disabled) - rthr = 2347; - if ((rthr < 0) || (rthr > 2347)) { - return -EINVAL; - } - priv->rts_threshold = rthr; - - return -EINPROGRESS; /* Call commit handler */ -} - -static int atmel_get_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - vwrq->value = priv->rts_threshold; - vwrq->disabled = (vwrq->value >= 2347); - vwrq->fixed = 1; - - return 0; -} - -static int atmel_set_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - int fthr = vwrq->value; - - if (vwrq->disabled) - fthr = 2346; - if ((fthr < 256) || (fthr > 2346)) { - return -EINVAL; - } - fthr &= ~0x1; /* Get an even value - is it really needed ??? */ - priv->frag_threshold = fthr; - - return -EINPROGRESS; /* Call commit handler */ -} - -static int atmel_get_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - vwrq->value = priv->frag_threshold; - vwrq->disabled = (vwrq->value >= 2346); - vwrq->fixed = 1; - - return 0; -} - -static int atmel_set_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - int rc = -EINPROGRESS; /* Call commit handler */ - - /* If setting by frequency, convert to a channel */ - if (fwrq->e == 1) { - int f = fwrq->m / 100000; - - /* Hack to fall through... */ - fwrq->e = 0; - fwrq->m = ieee80211_freq_to_dsss_chan(f); - } - /* Setting by channel number */ - if ((fwrq->m > 1000) || (fwrq->e > 0)) - rc = -EOPNOTSUPP; - else { - int channel = fwrq->m; - if (atmel_validate_channel(priv, channel) == 0) { - priv->channel = channel; - } else { - rc = -EINVAL; - } - } - return rc; -} - -static int atmel_get_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - - fwrq->m = priv->channel; - fwrq->e = 0; - return 0; -} - -static int atmel_set_scan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - unsigned long flags; - - /* Note : you may have realised that, as this is a SET operation, - * this is privileged and therefore a normal user can't - * perform scanning. - * This is not an error, while the device perform scanning, - * traffic doesn't flow, so it's a perfect DoS... - * Jean II */ - - if (priv->station_state == STATION_STATE_DOWN) - return -EAGAIN; - - /* Timeout old surveys. */ - if (time_after(jiffies, priv->last_survey + 20 * HZ)) - priv->site_survey_state = SITE_SURVEY_IDLE; - priv->last_survey = jiffies; - - /* Initiate a scan command */ - if (priv->site_survey_state == SITE_SURVEY_IN_PROGRESS) - return -EBUSY; - - del_timer_sync(&priv->management_timer); - spin_lock_irqsave(&priv->irqlock, flags); - - priv->site_survey_state = SITE_SURVEY_IN_PROGRESS; - priv->fast_scan = 0; - atmel_scan(priv, 0); - spin_unlock_irqrestore(&priv->irqlock, flags); - - return 0; -} - -static int atmel_get_scan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - int i; - char *current_ev = extra; - struct iw_event iwe; - - if (priv->site_survey_state != SITE_SURVEY_COMPLETED) - return -EAGAIN; - - for (i = 0; i < priv->BSS_list_entries; i++) { - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, priv->BSSinfo[i].BSSID, 6); - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_ADDR_LEN); - - iwe.u.data.length = priv->BSSinfo[i].SSIDsize; - if (iwe.u.data.length > 32) - iwe.u.data.length = 32; - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, priv->BSSinfo[i].SSID); - - iwe.cmd = SIOCGIWMODE; - iwe.u.mode = priv->BSSinfo[i].BSStype; - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_UINT_LEN); - - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = priv->BSSinfo[i].channel; - iwe.u.freq.e = 0; - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_FREQ_LEN); - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.level = priv->BSSinfo[i].RSSI; - iwe.u.qual.qual = iwe.u.qual.level; - /* iwe.u.qual.noise = SOMETHING */ - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_QUAL_LEN); - - - iwe.cmd = SIOCGIWENCODE; - if (priv->BSSinfo[i].UsingWEP) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, NULL); - } - - /* Length of data */ - dwrq->length = (current_ev - extra); - dwrq->flags = 0; - - return 0; -} - -static int atmel_get_range(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - struct iw_range *range = (struct iw_range *) extra; - int k, i, j; - - dwrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - range->min_nwid = 0x0000; - range->max_nwid = 0x0000; - range->num_channels = 0; - for (j = 0; j < ARRAY_SIZE(channel_table); j++) - if (priv->reg_domain == channel_table[j].reg_domain) { - range->num_channels = channel_table[j].max - channel_table[j].min + 1; - break; - } - if (range->num_channels != 0) { - for (k = 0, i = channel_table[j].min; i <= channel_table[j].max; i++) { - range->freq[k].i = i; /* List index */ - - /* Values in MHz -> * 10^5 * 10 */ - range->freq[k].m = (ieee80211_dsss_chan_to_freq(i) * - 100000); - range->freq[k++].e = 1; - } - range->num_frequency = k; - } - - range->max_qual.qual = 100; - range->max_qual.level = 100; - range->max_qual.noise = 0; - range->max_qual.updated = IW_QUAL_NOISE_INVALID; - - range->avg_qual.qual = 50; - range->avg_qual.level = 50; - range->avg_qual.noise = 0; - range->avg_qual.updated = IW_QUAL_NOISE_INVALID; - - range->sensitivity = 0; - - range->bitrate[0] = 1000000; - range->bitrate[1] = 2000000; - range->bitrate[2] = 5500000; - range->bitrate[3] = 11000000; - range->num_bitrates = 4; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = 4; - - range->pmp_flags = IW_POWER_ON; - range->pmt_flags = IW_POWER_ON; - range->pm_capa = 0; - - range->we_version_source = WIRELESS_EXT; - range->we_version_compiled = WIRELESS_EXT; - range->retry_capa = IW_RETRY_LIMIT ; - range->retry_flags = IW_RETRY_LIMIT; - range->r_time_flags = 0; - range->min_retry = 1; - range->max_retry = 65535; - - return 0; -} - -static int atmel_set_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra) -{ - struct atmel_private *priv = netdev_priv(dev); - int i; - static const u8 any[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; - static const u8 off[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - unsigned long flags; - - if (awrq->sa_family != ARPHRD_ETHER) - return -EINVAL; - - if (!memcmp(any, awrq->sa_data, 6) || - !memcmp(off, awrq->sa_data, 6)) { - del_timer_sync(&priv->management_timer); - spin_lock_irqsave(&priv->irqlock, flags); - atmel_scan(priv, 1); - spin_unlock_irqrestore(&priv->irqlock, flags); - return 0; - } - - for (i = 0; i < priv->BSS_list_entries; i++) { - if (memcmp(priv->BSSinfo[i].BSSID, awrq->sa_data, 6) == 0) { - if (!priv->wep_is_on && priv->BSSinfo[i].UsingWEP) { - return -EINVAL; - } else if (priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) { - return -EINVAL; - } else { - del_timer_sync(&priv->management_timer); - spin_lock_irqsave(&priv->irqlock, flags); - atmel_join_bss(priv, i); - spin_unlock_irqrestore(&priv->irqlock, flags); - return 0; - } - } - } - - return -EINVAL; -} - -static int atmel_config_commit(struct net_device *dev, - struct iw_request_info *info, /* NULL */ - void *zwrq, /* NULL */ - char *extra) /* NULL */ -{ - return atmel_open(dev); -} - -static const iw_handler atmel_handler[] = -{ - (iw_handler) atmel_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) atmel_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) atmel_set_freq, /* SIOCSIWFREQ */ - (iw_handler) atmel_get_freq, /* SIOCGIWFREQ */ - (iw_handler) atmel_set_mode, /* SIOCSIWMODE */ - (iw_handler) atmel_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) atmel_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) atmel_set_wap, /* SIOCSIWAP */ - (iw_handler) atmel_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) atmel_set_scan, /* SIOCSIWSCAN */ - (iw_handler) atmel_get_scan, /* SIOCGIWSCAN */ - (iw_handler) atmel_set_essid, /* SIOCSIWESSID */ - (iw_handler) atmel_get_essid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) NULL, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) atmel_set_rate, /* SIOCSIWRATE */ - (iw_handler) atmel_get_rate, /* SIOCGIWRATE */ - (iw_handler) atmel_set_rts, /* SIOCSIWRTS */ - (iw_handler) atmel_get_rts, /* SIOCGIWRTS */ - (iw_handler) atmel_set_frag, /* SIOCSIWFRAG */ - (iw_handler) atmel_get_frag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) atmel_set_retry, /* SIOCSIWRETRY */ - (iw_handler) atmel_get_retry, /* SIOCGIWRETRY */ - (iw_handler) atmel_set_encode, /* SIOCSIWENCODE */ - (iw_handler) atmel_get_encode, /* SIOCGIWENCODE */ - (iw_handler) atmel_set_power, /* SIOCSIWPOWER */ - (iw_handler) atmel_get_power, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCSIWGENIE */ - (iw_handler) NULL, /* SIOCGIWGENIE */ - (iw_handler) atmel_set_auth, /* SIOCSIWAUTH */ - (iw_handler) atmel_get_auth, /* SIOCGIWAUTH */ - (iw_handler) atmel_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) atmel_get_encodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; - -static const iw_handler atmel_private_handler[] = -{ - NULL, /* SIOCIWFIRSTPRIV */ -}; - -typedef struct atmel_priv_ioctl { - char id[32]; - unsigned char __user *data; - unsigned short len; -} atmel_priv_ioctl; - -#define ATMELFWL SIOCIWFIRSTPRIV -#define ATMELIDIFC ATMELFWL + 1 -#define ATMELRD ATMELFWL + 2 -#define ATMELMAGIC 0x51807 -#define REGDOMAINSZ 20 - -static const struct iw_priv_args atmel_private_args[] = { - { - .cmd = ATMELFWL, - .set_args = IW_PRIV_TYPE_BYTE - | IW_PRIV_SIZE_FIXED - | sizeof (atmel_priv_ioctl), - .get_args = IW_PRIV_TYPE_NONE, - .name = "atmelfwl" - }, { - .cmd = ATMELIDIFC, - .set_args = IW_PRIV_TYPE_NONE, - .get_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "atmelidifc" - }, { - .cmd = ATMELRD, - .set_args = IW_PRIV_TYPE_CHAR | REGDOMAINSZ, - .get_args = IW_PRIV_TYPE_NONE, - .name = "regdomain" - }, -}; - -static const struct iw_handler_def atmel_handler_def = { - .num_standard = ARRAY_SIZE(atmel_handler), - .num_private = ARRAY_SIZE(atmel_private_handler), - .num_private_args = ARRAY_SIZE(atmel_private_args), - .standard = (iw_handler *) atmel_handler, - .private = (iw_handler *) atmel_private_handler, - .private_args = (struct iw_priv_args *) atmel_private_args, - .get_wireless_stats = atmel_get_wireless_stats -}; - -static int atmel_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) -{ - int i, rc = 0; - struct atmel_private *priv = netdev_priv(dev); - atmel_priv_ioctl com; - struct iwreq *wrq = (struct iwreq *) rq; - unsigned char *new_firmware; - char domain[REGDOMAINSZ + 1]; - - switch (cmd) { - case ATMELIDIFC: - wrq->u.param.value = ATMELMAGIC; - break; - - case ATMELFWL: - if (copy_from_user(&com, rq->ifr_data, sizeof(com))) { - rc = -EFAULT; - break; - } - - if (!capable(CAP_NET_ADMIN)) { - rc = -EPERM; - break; - } - - if (!(new_firmware = kmalloc(com.len, GFP_KERNEL))) { - rc = -ENOMEM; - break; - } - - if (copy_from_user(new_firmware, com.data, com.len)) { - kfree(new_firmware); - rc = -EFAULT; - break; - } - - kfree(priv->firmware); - - priv->firmware = new_firmware; - priv->firmware_length = com.len; - strncpy(priv->firmware_id, com.id, 31); - priv->firmware_id[31] = '\0'; - break; - - case ATMELRD: - if (copy_from_user(domain, rq->ifr_data, REGDOMAINSZ)) { - rc = -EFAULT; - break; - } - - if (!capable(CAP_NET_ADMIN)) { - rc = -EPERM; - break; - } - - domain[REGDOMAINSZ] = 0; - rc = -EINVAL; - for (i = 0; i < ARRAY_SIZE(channel_table); i++) { - /* strcasecmp doesn't exist in the library */ - char *a = channel_table[i].name; - char *b = domain; - while (*a) { - char c1 = *a++; - char c2 = *b++; - if (tolower(c1) != tolower(c2)) - break; - } - if (!*a && !*b) { - priv->config_reg_domain = channel_table[i].reg_domain; - rc = 0; - } - } - - if (rc == 0 && priv->station_state != STATION_STATE_DOWN) - rc = atmel_open(dev); - break; - - default: - rc = -EOPNOTSUPP; - } - - return rc; -} - -struct auth_body { - __le16 alg; - __le16 trans_seq; - __le16 status; - u8 el_id; - u8 chall_text_len; - u8 chall_text[253]; -}; - -static void atmel_enter_state(struct atmel_private *priv, int new_state) -{ - int old_state = priv->station_state; - - if (new_state == old_state) - return; - - priv->station_state = new_state; - - if (new_state == STATION_STATE_READY) { - netif_start_queue(priv->dev); - netif_carrier_on(priv->dev); - } - - if (old_state == STATION_STATE_READY) { - netif_carrier_off(priv->dev); - if (netif_running(priv->dev)) - netif_stop_queue(priv->dev); - priv->last_beacon_timestamp = 0; - } -} - -static void atmel_scan(struct atmel_private *priv, int specific_ssid) -{ - struct { - u8 BSSID[6]; - u8 SSID[MAX_SSID_LENGTH]; - u8 scan_type; - u8 channel; - __le16 BSS_type; - __le16 min_channel_time; - __le16 max_channel_time; - u8 options; - u8 SSID_size; - } cmd; - - memset(cmd.BSSID, 0xff, 6); - - if (priv->fast_scan) { - cmd.SSID_size = priv->SSID_size; - memcpy(cmd.SSID, priv->SSID, priv->SSID_size); - cmd.min_channel_time = cpu_to_le16(10); - cmd.max_channel_time = cpu_to_le16(50); - } else { - priv->BSS_list_entries = 0; - cmd.SSID_size = 0; - cmd.min_channel_time = cpu_to_le16(10); - cmd.max_channel_time = cpu_to_le16(120); - } - - cmd.options = 0; - - if (!specific_ssid) - cmd.options |= SCAN_OPTIONS_SITE_SURVEY; - - cmd.channel = (priv->channel & 0x7f); - cmd.scan_type = SCAN_TYPE_ACTIVE; - cmd.BSS_type = cpu_to_le16(priv->operating_mode == IW_MODE_ADHOC ? - BSS_TYPE_AD_HOC : BSS_TYPE_INFRASTRUCTURE); - - atmel_send_command(priv, CMD_Scan, &cmd, sizeof(cmd)); - - /* This must come after all hardware access to avoid being messed up - by stuff happening in interrupt context after we leave STATE_DOWN */ - atmel_enter_state(priv, STATION_STATE_SCANNING); -} - -static void join(struct atmel_private *priv, int type) -{ - struct { - u8 BSSID[6]; - u8 SSID[MAX_SSID_LENGTH]; - u8 BSS_type; /* this is a short in a scan command - weird */ - u8 channel; - __le16 timeout; - u8 SSID_size; - u8 reserved; - } cmd; - - cmd.SSID_size = priv->SSID_size; - memcpy(cmd.SSID, priv->SSID, priv->SSID_size); - memcpy(cmd.BSSID, priv->CurrentBSSID, 6); - cmd.channel = (priv->channel & 0x7f); - cmd.BSS_type = type; - cmd.timeout = cpu_to_le16(2000); - - atmel_send_command(priv, CMD_Join, &cmd, sizeof(cmd)); -} - -static void start(struct atmel_private *priv, int type) -{ - struct { - u8 BSSID[6]; - u8 SSID[MAX_SSID_LENGTH]; - u8 BSS_type; - u8 channel; - u8 SSID_size; - u8 reserved[3]; - } cmd; - - cmd.SSID_size = priv->SSID_size; - memcpy(cmd.SSID, priv->SSID, priv->SSID_size); - memcpy(cmd.BSSID, priv->BSSID, 6); - cmd.BSS_type = type; - cmd.channel = (priv->channel & 0x7f); - - atmel_send_command(priv, CMD_Start, &cmd, sizeof(cmd)); -} - -static void handle_beacon_probe(struct atmel_private *priv, u16 capability, - u8 channel) -{ - int rejoin = 0; - int new = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ? - SHORT_PREAMBLE : LONG_PREAMBLE; - - if (priv->preamble != new) { - priv->preamble = new; - rejoin = 1; - atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, new); - } - - if (priv->channel != channel) { - priv->channel = channel; - rejoin = 1; - atmel_set_mib8(priv, Phy_Mib_Type, PHY_MIB_CHANNEL_POS, channel); - } - - if (rejoin) { - priv->station_is_associated = 0; - atmel_enter_state(priv, STATION_STATE_JOINNING); - - if (priv->operating_mode == IW_MODE_INFRA) - join(priv, BSS_TYPE_INFRASTRUCTURE); - else - join(priv, BSS_TYPE_AD_HOC); - } -} - -static void send_authentication_request(struct atmel_private *priv, u16 system, - u8 *challenge, int challenge_len) -{ - struct ieee80211_hdr header; - struct auth_body auth; - - header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH); - header.duration_id = cpu_to_le16(0x8000); - header.seq_ctrl = 0; - memcpy(header.addr1, priv->CurrentBSSID, 6); - memcpy(header.addr2, priv->dev->dev_addr, 6); - memcpy(header.addr3, priv->CurrentBSSID, 6); - - if (priv->wep_is_on && priv->CurrentAuthentTransactionSeqNum != 1) - /* no WEP for authentication frames with TrSeqNo 1 */ - header.frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); - - auth.alg = cpu_to_le16(system); - - auth.status = 0; - auth.trans_seq = cpu_to_le16(priv->CurrentAuthentTransactionSeqNum); - priv->ExpectedAuthentTransactionSeqNum = priv->CurrentAuthentTransactionSeqNum+1; - priv->CurrentAuthentTransactionSeqNum += 2; - - if (challenge_len != 0) { - auth.el_id = 16; /* challenge_text */ - auth.chall_text_len = challenge_len; - memcpy(auth.chall_text, challenge, challenge_len); - atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 8 + challenge_len); - } else { - atmel_transmit_management_frame(priv, &header, (u8 *)&auth, 6); - } -} - -static void send_association_request(struct atmel_private *priv, int is_reassoc) -{ - u8 *ssid_el_p; - int bodysize; - struct ieee80211_hdr header; - struct ass_req_format { - __le16 capability; - __le16 listen_interval; - u8 ap[6]; /* nothing after here directly accessible */ - u8 ssid_el_id; - u8 ssid_len; - u8 ssid[MAX_SSID_LENGTH]; - u8 sup_rates_el_id; - u8 sup_rates_len; - u8 rates[4]; - } body; - - header.frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - (is_reassoc ? IEEE80211_STYPE_REASSOC_REQ : IEEE80211_STYPE_ASSOC_REQ)); - header.duration_id = cpu_to_le16(0x8000); - header.seq_ctrl = 0; - - memcpy(header.addr1, priv->CurrentBSSID, 6); - memcpy(header.addr2, priv->dev->dev_addr, 6); - memcpy(header.addr3, priv->CurrentBSSID, 6); - - body.capability = cpu_to_le16(WLAN_CAPABILITY_ESS); - if (priv->wep_is_on) - body.capability |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY); - if (priv->preamble == SHORT_PREAMBLE) - body.capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - - body.listen_interval = cpu_to_le16(priv->listen_interval * priv->beacon_period); - - /* current AP address - only in reassoc frame */ - if (is_reassoc) { - memcpy(body.ap, priv->CurrentBSSID, 6); - ssid_el_p = (u8 *)&body.ssid_el_id; - bodysize = 18 + priv->SSID_size; - } else { - ssid_el_p = (u8 *)&body.ap[0]; - bodysize = 12 + priv->SSID_size; - } - - ssid_el_p[0] = WLAN_EID_SSID; - ssid_el_p[1] = priv->SSID_size; - memcpy(ssid_el_p + 2, priv->SSID, priv->SSID_size); - ssid_el_p[2 + priv->SSID_size] = WLAN_EID_SUPP_RATES; - ssid_el_p[3 + priv->SSID_size] = 4; /* len of suported rates */ - memcpy(ssid_el_p + 4 + priv->SSID_size, atmel_basic_rates, 4); - - atmel_transmit_management_frame(priv, &header, (void *)&body, bodysize); -} - -static int is_frame_from_current_bss(struct atmel_private *priv, - struct ieee80211_hdr *header) -{ - if (le16_to_cpu(header->frame_control) & IEEE80211_FCTL_FROMDS) - return memcmp(header->addr3, priv->CurrentBSSID, 6) == 0; - else - return memcmp(header->addr2, priv->CurrentBSSID, 6) == 0; -} - -static int retrieve_bss(struct atmel_private *priv) -{ - int i; - int max_rssi = -128; - int max_index = -1; - - if (priv->BSS_list_entries == 0) - return -1; - - if (priv->connect_to_any_BSS) { - /* Select a BSS with the max-RSSI but of the same type and of - the same WEP mode and that it is not marked as 'bad' (i.e. - we had previously failed to connect to this BSS with the - settings that we currently use) */ - priv->current_BSS = 0; - for (i = 0; i < priv->BSS_list_entries; i++) { - if (priv->operating_mode == priv->BSSinfo[i].BSStype && - ((!priv->wep_is_on && !priv->BSSinfo[i].UsingWEP) || - (priv->wep_is_on && priv->BSSinfo[i].UsingWEP)) && - !(priv->BSSinfo[i].channel & 0x80)) { - max_rssi = priv->BSSinfo[i].RSSI; - priv->current_BSS = max_index = i; - } - } - return max_index; - } - - for (i = 0; i < priv->BSS_list_entries; i++) { - if (priv->SSID_size == priv->BSSinfo[i].SSIDsize && - memcmp(priv->SSID, priv->BSSinfo[i].SSID, priv->SSID_size) == 0 && - priv->operating_mode == priv->BSSinfo[i].BSStype && - atmel_validate_channel(priv, priv->BSSinfo[i].channel) == 0) { - if (priv->BSSinfo[i].RSSI >= max_rssi) { - max_rssi = priv->BSSinfo[i].RSSI; - max_index = i; - } - } - } - return max_index; -} - -static void store_bss_info(struct atmel_private *priv, - struct ieee80211_hdr *header, u16 capability, - u16 beacon_period, u8 channel, u8 rssi, u8 ssid_len, - u8 *ssid, int is_beacon) -{ - u8 *bss = capability & WLAN_CAPABILITY_ESS ? header->addr2 : header->addr3; - int i, index; - - for (index = -1, i = 0; i < priv->BSS_list_entries; i++) - if (memcmp(bss, priv->BSSinfo[i].BSSID, 6) == 0) - index = i; - - /* If we process a probe and an entry from this BSS exists - we will update the BSS entry with the info from this BSS. - If we process a beacon we will only update RSSI */ - - if (index == -1) { - if (priv->BSS_list_entries == MAX_BSS_ENTRIES) - return; - index = priv->BSS_list_entries++; - memcpy(priv->BSSinfo[index].BSSID, bss, 6); - priv->BSSinfo[index].RSSI = rssi; - } else { - if (rssi > priv->BSSinfo[index].RSSI) - priv->BSSinfo[index].RSSI = rssi; - if (is_beacon) - return; - } - - priv->BSSinfo[index].channel = channel; - priv->BSSinfo[index].beacon_period = beacon_period; - priv->BSSinfo[index].UsingWEP = capability & WLAN_CAPABILITY_PRIVACY; - memcpy(priv->BSSinfo[index].SSID, ssid, ssid_len); - priv->BSSinfo[index].SSIDsize = ssid_len; - - if (capability & WLAN_CAPABILITY_IBSS) - priv->BSSinfo[index].BSStype = IW_MODE_ADHOC; - else if (capability & WLAN_CAPABILITY_ESS) - priv->BSSinfo[index].BSStype = IW_MODE_INFRA; - - priv->BSSinfo[index].preamble = capability & WLAN_CAPABILITY_SHORT_PREAMBLE ? - SHORT_PREAMBLE : LONG_PREAMBLE; -} - -static void authenticate(struct atmel_private *priv, u16 frame_len) -{ - struct auth_body *auth = (struct auth_body *)priv->rx_buf; - u16 status = le16_to_cpu(auth->status); - u16 trans_seq_no = le16_to_cpu(auth->trans_seq); - u16 system = le16_to_cpu(auth->alg); - - if (status == WLAN_STATUS_SUCCESS && !priv->wep_is_on) { - /* no WEP */ - if (priv->station_was_associated) { - atmel_enter_state(priv, STATION_STATE_REASSOCIATING); - send_association_request(priv, 1); - return; - } else { - atmel_enter_state(priv, STATION_STATE_ASSOCIATING); - send_association_request(priv, 0); - return; - } - } - - if (status == WLAN_STATUS_SUCCESS && priv->wep_is_on) { - int should_associate = 0; - /* WEP */ - if (trans_seq_no != priv->ExpectedAuthentTransactionSeqNum) - return; - - if (system == WLAN_AUTH_OPEN) { - if (trans_seq_no == 0x0002) { - should_associate = 1; - } - } else if (system == WLAN_AUTH_SHARED_KEY) { - if (trans_seq_no == 0x0002 && - auth->el_id == WLAN_EID_CHALLENGE) { - send_authentication_request(priv, system, auth->chall_text, auth->chall_text_len); - return; - } else if (trans_seq_no == 0x0004) { - should_associate = 1; - } - } - - if (should_associate) { - if (priv->station_was_associated) { - atmel_enter_state(priv, STATION_STATE_REASSOCIATING); - send_association_request(priv, 1); - return; - } else { - atmel_enter_state(priv, STATION_STATE_ASSOCIATING); - send_association_request(priv, 0); - return; - } - } - } - - if (status == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG) { - /* Flip back and forth between WEP auth modes until the max - * authentication tries has been exceeded. - */ - if (system == WLAN_AUTH_OPEN) { - priv->CurrentAuthentTransactionSeqNum = 0x001; - priv->exclude_unencrypted = 1; - send_authentication_request(priv, WLAN_AUTH_SHARED_KEY, NULL, 0); - return; - } else if (system == WLAN_AUTH_SHARED_KEY - && priv->wep_is_on) { - priv->CurrentAuthentTransactionSeqNum = 0x001; - priv->exclude_unencrypted = 0; - send_authentication_request(priv, WLAN_AUTH_OPEN, NULL, 0); - return; - } else if (priv->connect_to_any_BSS) { - int bss_index; - - priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80; - - if ((bss_index = retrieve_bss(priv)) != -1) { - atmel_join_bss(priv, bss_index); - return; - } - } - } - - priv->AuthenticationRequestRetryCnt = 0; - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; -} - -static void associate(struct atmel_private *priv, u16 frame_len, u16 subtype) -{ - struct ass_resp_format { - __le16 capability; - __le16 status; - __le16 ass_id; - u8 el_id; - u8 length; - u8 rates[4]; - } *ass_resp = (struct ass_resp_format *)priv->rx_buf; - - u16 status = le16_to_cpu(ass_resp->status); - u16 ass_id = le16_to_cpu(ass_resp->ass_id); - u16 rates_len = ass_resp->length > 4 ? 4 : ass_resp->length; - - union iwreq_data wrqu; - - if (frame_len < 8 + rates_len) - return; - - if (status == WLAN_STATUS_SUCCESS) { - if (subtype == IEEE80211_STYPE_ASSOC_RESP) - priv->AssociationRequestRetryCnt = 0; - else - priv->ReAssociationRequestRetryCnt = 0; - - atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_STATION_ID_POS, ass_id & 0x3fff); - atmel_set_mib(priv, Phy_Mib_Type, - PHY_MIB_RATE_SET_POS, ass_resp->rates, rates_len); - if (priv->power_mode == 0) { - priv->listen_interval = 1; - atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE); - atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1); - } else { - priv->listen_interval = 2; - atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_PS_MODE_POS, PS_MODE); - atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 2); - } - - priv->station_is_associated = 1; - priv->station_was_associated = 1; - atmel_enter_state(priv, STATION_STATE_READY); - - /* Send association event to userspace */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - memcpy(wrqu.ap_addr.sa_data, priv->CurrentBSSID, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - return; - } - - if (subtype == IEEE80211_STYPE_ASSOC_RESP && - status != WLAN_STATUS_ASSOC_DENIED_RATES && - status != WLAN_STATUS_CAPS_UNSUPPORTED && - priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { - mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - priv->AssociationRequestRetryCnt++; - send_association_request(priv, 0); - return; - } - - if (subtype == IEEE80211_STYPE_REASSOC_RESP && - status != WLAN_STATUS_ASSOC_DENIED_RATES && - status != WLAN_STATUS_CAPS_UNSUPPORTED && - priv->AssociationRequestRetryCnt < MAX_ASSOCIATION_RETRIES) { - mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - priv->ReAssociationRequestRetryCnt++; - send_association_request(priv, 1); - return; - } - - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; - - if (priv->connect_to_any_BSS) { - int bss_index; - priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80; - - if ((bss_index = retrieve_bss(priv)) != -1) - atmel_join_bss(priv, bss_index); - } -} - -static void atmel_join_bss(struct atmel_private *priv, int bss_index) -{ - struct bss_info *bss = &priv->BSSinfo[bss_index]; - - memcpy(priv->CurrentBSSID, bss->BSSID, 6); - memcpy(priv->SSID, bss->SSID, priv->SSID_size = bss->SSIDsize); - - /* The WPA stuff cares about the current AP address */ - if (priv->use_wpa) - build_wpa_mib(priv); - - /* When switching to AdHoc turn OFF Power Save if needed */ - - if (bss->BSStype == IW_MODE_ADHOC && - priv->operating_mode != IW_MODE_ADHOC && - priv->power_mode) { - priv->power_mode = 0; - priv->listen_interval = 1; - atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE); - atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, - MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1); - } - - priv->operating_mode = bss->BSStype; - priv->channel = bss->channel & 0x7f; - priv->beacon_period = bss->beacon_period; - - if (priv->preamble != bss->preamble) { - priv->preamble = bss->preamble; - atmel_set_mib8(priv, Local_Mib_Type, - LOCAL_MIB_PREAMBLE_TYPE, bss->preamble); - } - - if (!priv->wep_is_on && bss->UsingWEP) { - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; - return; - } - - if (priv->wep_is_on && !bss->UsingWEP) { - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; - return; - } - - atmel_enter_state(priv, STATION_STATE_JOINNING); - - if (priv->operating_mode == IW_MODE_INFRA) - join(priv, BSS_TYPE_INFRASTRUCTURE); - else - join(priv, BSS_TYPE_AD_HOC); -} - -static void restart_search(struct atmel_private *priv) -{ - int bss_index; - - if (!priv->connect_to_any_BSS) { - atmel_scan(priv, 1); - } else { - priv->BSSinfo[(int)(priv->current_BSS)].channel |= 0x80; - - if ((bss_index = retrieve_bss(priv)) != -1) - atmel_join_bss(priv, bss_index); - else - atmel_scan(priv, 0); - } -} - -static void smooth_rssi(struct atmel_private *priv, u8 rssi) -{ - u8 old = priv->wstats.qual.level; - u8 max_rssi = 42; /* 502-rmfd-revd max by experiment, default for now */ - - switch (priv->firmware_type) { - case ATMEL_FW_TYPE_502E: - max_rssi = 63; /* 502-rmfd-reve max by experiment */ - break; - default: - break; - } - - rssi = rssi * 100 / max_rssi; - if ((rssi + old) % 2) - priv->wstats.qual.level = (rssi + old) / 2 + 1; - else - priv->wstats.qual.level = (rssi + old) / 2; - priv->wstats.qual.updated |= IW_QUAL_LEVEL_UPDATED; - priv->wstats.qual.updated &= ~IW_QUAL_LEVEL_INVALID; -} - -static void atmel_smooth_qual(struct atmel_private *priv) -{ - unsigned long time_diff = (jiffies - priv->last_qual) / HZ; - while (time_diff--) { - priv->last_qual += HZ; - priv->wstats.qual.qual = priv->wstats.qual.qual / 2; - priv->wstats.qual.qual += - priv->beacons_this_sec * priv->beacon_period * (priv->wstats.qual.level + 100) / 4000; - priv->beacons_this_sec = 0; - } - priv->wstats.qual.updated |= IW_QUAL_QUAL_UPDATED; - priv->wstats.qual.updated &= ~IW_QUAL_QUAL_INVALID; -} - -/* deals with incoming management frames. */ -static void atmel_management_frame(struct atmel_private *priv, - struct ieee80211_hdr *header, - u16 frame_len, u8 rssi) -{ - u16 subtype; - - subtype = le16_to_cpu(header->frame_control) & IEEE80211_FCTL_STYPE; - switch (subtype) { - case IEEE80211_STYPE_BEACON: - case IEEE80211_STYPE_PROBE_RESP: - - /* beacon frame has multiple variable-length fields - - never let an engineer loose with a data structure design. */ - { - struct beacon_format { - __le64 timestamp; - __le16 interval; - __le16 capability; - u8 ssid_el_id; - u8 ssid_length; - /* ssid here */ - u8 rates_el_id; - u8 rates_length; - /* rates here */ - u8 ds_el_id; - u8 ds_length; - /* ds here */ - } *beacon = (struct beacon_format *)priv->rx_buf; - - u8 channel, rates_length, ssid_length; - u64 timestamp = le64_to_cpu(beacon->timestamp); - u16 beacon_interval = le16_to_cpu(beacon->interval); - u16 capability = le16_to_cpu(beacon->capability); - u8 *beaconp = priv->rx_buf; - ssid_length = beacon->ssid_length; - /* this blows chunks. */ - if (frame_len < 14 || frame_len < ssid_length + 15) - return; - rates_length = beaconp[beacon->ssid_length + 15]; - if (frame_len < ssid_length + rates_length + 18) - return; - if (ssid_length > MAX_SSID_LENGTH) - return; - channel = beaconp[ssid_length + rates_length + 18]; - - if (priv->station_state == STATION_STATE_READY) { - smooth_rssi(priv, rssi); - if (is_frame_from_current_bss(priv, header)) { - priv->beacons_this_sec++; - atmel_smooth_qual(priv); - if (priv->last_beacon_timestamp) { - /* Note truncate this to 32 bits - kernel can't divide a long long */ - u32 beacon_delay = timestamp - priv->last_beacon_timestamp; - int beacons = beacon_delay / (beacon_interval * 1000); - if (beacons > 1) - priv->wstats.miss.beacon += beacons - 1; - } - priv->last_beacon_timestamp = timestamp; - handle_beacon_probe(priv, capability, channel); - } - } - - if (priv->station_state == STATION_STATE_SCANNING) - store_bss_info(priv, header, capability, - beacon_interval, channel, rssi, - ssid_length, - &beacon->rates_el_id, - subtype == IEEE80211_STYPE_BEACON); - } - break; - - case IEEE80211_STYPE_AUTH: - - if (priv->station_state == STATION_STATE_AUTHENTICATING) - authenticate(priv, frame_len); - - break; - - case IEEE80211_STYPE_ASSOC_RESP: - case IEEE80211_STYPE_REASSOC_RESP: - - if (priv->station_state == STATION_STATE_ASSOCIATING || - priv->station_state == STATION_STATE_REASSOCIATING) - associate(priv, frame_len, subtype); - - break; - - case IEEE80211_STYPE_DISASSOC: - if (priv->station_is_associated && - priv->operating_mode == IW_MODE_INFRA && - is_frame_from_current_bss(priv, header)) { - priv->station_was_associated = 0; - priv->station_is_associated = 0; - - atmel_enter_state(priv, STATION_STATE_JOINNING); - join(priv, BSS_TYPE_INFRASTRUCTURE); - } - - break; - - case IEEE80211_STYPE_DEAUTH: - if (priv->operating_mode == IW_MODE_INFRA && - is_frame_from_current_bss(priv, header)) { - priv->station_was_associated = 0; - - atmel_enter_state(priv, STATION_STATE_JOINNING); - join(priv, BSS_TYPE_INFRASTRUCTURE); - } - - break; - } -} - -/* run when timer expires */ -static void atmel_management_timer(u_long a) -{ - struct net_device *dev = (struct net_device *) a; - struct atmel_private *priv = netdev_priv(dev); - unsigned long flags; - - /* Check if the card has been yanked. */ - if (priv->card && priv->present_callback && - !(*priv->present_callback)(priv->card)) - return; - - spin_lock_irqsave(&priv->irqlock, flags); - - switch (priv->station_state) { - - case STATION_STATE_AUTHENTICATING: - if (priv->AuthenticationRequestRetryCnt >= MAX_AUTHENTICATION_RETRIES) { - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; - priv->AuthenticationRequestRetryCnt = 0; - restart_search(priv); - } else { - int auth = WLAN_AUTH_OPEN; - priv->AuthenticationRequestRetryCnt++; - priv->CurrentAuthentTransactionSeqNum = 0x0001; - mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - if (priv->wep_is_on && priv->exclude_unencrypted) - auth = WLAN_AUTH_SHARED_KEY; - send_authentication_request(priv, auth, NULL, 0); - } - break; - - case STATION_STATE_ASSOCIATING: - if (priv->AssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) { - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; - priv->AssociationRequestRetryCnt = 0; - restart_search(priv); - } else { - priv->AssociationRequestRetryCnt++; - mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - send_association_request(priv, 0); - } - break; - - case STATION_STATE_REASSOCIATING: - if (priv->ReAssociationRequestRetryCnt == MAX_ASSOCIATION_RETRIES) { - atmel_enter_state(priv, STATION_STATE_MGMT_ERROR); - priv->station_is_associated = 0; - priv->ReAssociationRequestRetryCnt = 0; - restart_search(priv); - } else { - priv->ReAssociationRequestRetryCnt++; - mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - send_association_request(priv, 1); - } - break; - - default: - break; - } - - spin_unlock_irqrestore(&priv->irqlock, flags); -} - -static void atmel_command_irq(struct atmel_private *priv) -{ - u8 status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); - u8 command = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET)); - int fast_scan; - union iwreq_data wrqu; - - if (status == CMD_STATUS_IDLE || - status == CMD_STATUS_IN_PROGRESS) - return; - - switch (command) { - case CMD_Start: - if (status == CMD_STATUS_COMPLETE) { - priv->station_was_associated = priv->station_is_associated; - atmel_get_mib(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_BSSID_POS, - (u8 *)priv->CurrentBSSID, 6); - atmel_enter_state(priv, STATION_STATE_READY); - } - break; - - case CMD_Scan: - fast_scan = priv->fast_scan; - priv->fast_scan = 0; - - if (status != CMD_STATUS_COMPLETE) { - atmel_scan(priv, 1); - } else { - int bss_index = retrieve_bss(priv); - int notify_scan_complete = 1; - if (bss_index != -1) { - atmel_join_bss(priv, bss_index); - } else if (priv->operating_mode == IW_MODE_ADHOC && - priv->SSID_size != 0) { - start(priv, BSS_TYPE_AD_HOC); - } else { - priv->fast_scan = !fast_scan; - atmel_scan(priv, 1); - notify_scan_complete = 0; - } - priv->site_survey_state = SITE_SURVEY_COMPLETED; - if (notify_scan_complete) { - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); - } - } - break; - - case CMD_SiteSurvey: - priv->fast_scan = 0; - - if (status != CMD_STATUS_COMPLETE) - return; - - priv->site_survey_state = SITE_SURVEY_COMPLETED; - if (priv->station_is_associated) { - atmel_enter_state(priv, STATION_STATE_READY); - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); - } else { - atmel_scan(priv, 1); - } - break; - - case CMD_Join: - if (status == CMD_STATUS_COMPLETE) { - if (priv->operating_mode == IW_MODE_ADHOC) { - priv->station_was_associated = priv->station_is_associated; - atmel_enter_state(priv, STATION_STATE_READY); - } else { - int auth = WLAN_AUTH_OPEN; - priv->AuthenticationRequestRetryCnt = 0; - atmel_enter_state(priv, STATION_STATE_AUTHENTICATING); - - mod_timer(&priv->management_timer, jiffies + MGMT_JIFFIES); - priv->CurrentAuthentTransactionSeqNum = 0x0001; - if (priv->wep_is_on && priv->exclude_unencrypted) - auth = WLAN_AUTH_SHARED_KEY; - send_authentication_request(priv, auth, NULL, 0); - } - return; - } - - atmel_scan(priv, 1); - } -} - -static int atmel_wakeup_firmware(struct atmel_private *priv) -{ - struct host_info_struct *iface = &priv->host_info; - u16 mr1, mr3; - int i; - - if (priv->card_type == CARD_TYPE_SPI_FLASH) - atmel_set_gcr(priv->dev, GCR_REMAP); - - /* wake up on-board processor */ - atmel_clear_gcr(priv->dev, 0x0040); - atmel_write16(priv->dev, BSR, BSS_SRAM); - - if (priv->card_type == CARD_TYPE_SPI_FLASH) - mdelay(100); - - /* and wait for it */ - for (i = LOOP_RETRY_LIMIT; i; i--) { - mr1 = atmel_read16(priv->dev, MR1); - mr3 = atmel_read16(priv->dev, MR3); - - if (mr3 & MAC_BOOT_COMPLETE) - break; - if (mr1 & MAC_BOOT_COMPLETE && - priv->bus_type == BUS_TYPE_PCCARD) - break; - } - - if (i == 0) { - printk(KERN_ALERT "%s: MAC failed to boot.\n", priv->dev->name); - return -EIO; - } - - if ((priv->host_info_base = atmel_read16(priv->dev, MR2)) == 0xffff) { - printk(KERN_ALERT "%s: card missing.\n", priv->dev->name); - return -ENODEV; - } - - /* now check for completion of MAC initialization through - the FunCtrl field of the IFACE, poll MR1 to detect completion of - MAC initialization, check completion status, set interrupt mask, - enables interrupts and calls Tx and Rx initialization functions */ - - atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), FUNC_CTRL_INIT_COMPLETE); - - for (i = LOOP_RETRY_LIMIT; i; i--) { - mr1 = atmel_read16(priv->dev, MR1); - mr3 = atmel_read16(priv->dev, MR3); - - if (mr3 & MAC_INIT_COMPLETE) - break; - if (mr1 & MAC_INIT_COMPLETE && - priv->bus_type == BUS_TYPE_PCCARD) - break; - } - - if (i == 0) { - printk(KERN_ALERT "%s: MAC failed to initialise.\n", - priv->dev->name); - return -EIO; - } - - /* Check for MAC_INIT_OK only on the register that the MAC_INIT_OK was set */ - if ((mr3 & MAC_INIT_COMPLETE) && - !(atmel_read16(priv->dev, MR3) & MAC_INIT_OK)) { - printk(KERN_ALERT "%s: MAC failed MR3 self-test.\n", priv->dev->name); - return -EIO; - } - if ((mr1 & MAC_INIT_COMPLETE) && - !(atmel_read16(priv->dev, MR1) & MAC_INIT_OK)) { - printk(KERN_ALERT "%s: MAC failed MR1 self-test.\n", priv->dev->name); - return -EIO; - } - - atmel_copy_to_host(priv->dev, (unsigned char *)iface, - priv->host_info_base, sizeof(*iface)); - - iface->tx_buff_pos = le16_to_cpu(iface->tx_buff_pos); - iface->tx_buff_size = le16_to_cpu(iface->tx_buff_size); - iface->tx_desc_pos = le16_to_cpu(iface->tx_desc_pos); - iface->tx_desc_count = le16_to_cpu(iface->tx_desc_count); - iface->rx_buff_pos = le16_to_cpu(iface->rx_buff_pos); - iface->rx_buff_size = le16_to_cpu(iface->rx_buff_size); - iface->rx_desc_pos = le16_to_cpu(iface->rx_desc_pos); - iface->rx_desc_count = le16_to_cpu(iface->rx_desc_count); - iface->build_version = le16_to_cpu(iface->build_version); - iface->command_pos = le16_to_cpu(iface->command_pos); - iface->major_version = le16_to_cpu(iface->major_version); - iface->minor_version = le16_to_cpu(iface->minor_version); - iface->func_ctrl = le16_to_cpu(iface->func_ctrl); - iface->mac_status = le16_to_cpu(iface->mac_status); - - return 0; -} - -/* determine type of memory and MAC address */ -static int probe_atmel_card(struct net_device *dev) -{ - int rc = 0; - struct atmel_private *priv = netdev_priv(dev); - - /* reset pccard */ - if (priv->bus_type == BUS_TYPE_PCCARD) - atmel_write16(dev, GCR, 0x0060); - - atmel_write16(dev, GCR, 0x0040); - mdelay(500); - - if (atmel_read16(dev, MR2) == 0) { - /* No stored firmware so load a small stub which just - tells us the MAC address */ - int i; - priv->card_type = CARD_TYPE_EEPROM; - atmel_write16(dev, BSR, BSS_IRAM); - atmel_copy_to_card(dev, 0, mac_reader, sizeof(mac_reader)); - atmel_set_gcr(dev, GCR_REMAP); - atmel_clear_gcr(priv->dev, 0x0040); - atmel_write16(dev, BSR, BSS_SRAM); - for (i = LOOP_RETRY_LIMIT; i; i--) - if (atmel_read16(dev, MR3) & MAC_BOOT_COMPLETE) - break; - if (i == 0) { - printk(KERN_ALERT "%s: MAC failed to boot MAC address reader.\n", dev->name); - } else { - atmel_copy_to_host(dev, dev->dev_addr, atmel_read16(dev, MR2), 6); - /* got address, now squash it again until the network - interface is opened */ - if (priv->bus_type == BUS_TYPE_PCCARD) - atmel_write16(dev, GCR, 0x0060); - atmel_write16(dev, GCR, 0x0040); - rc = 1; - } - } else if (atmel_read16(dev, MR4) == 0) { - /* Mac address easy in this case. */ - priv->card_type = CARD_TYPE_PARALLEL_FLASH; - atmel_write16(dev, BSR, 1); - atmel_copy_to_host(dev, dev->dev_addr, 0xc000, 6); - atmel_write16(dev, BSR, 0x200); - rc = 1; - } else { - /* Standard firmware in flash, boot it up and ask - for the Mac Address */ - priv->card_type = CARD_TYPE_SPI_FLASH; - if (atmel_wakeup_firmware(priv) == 0) { - atmel_get_mib(priv, Mac_Address_Mib_Type, 0, dev->dev_addr, 6); - - /* got address, now squash it again until the network - interface is opened */ - if (priv->bus_type == BUS_TYPE_PCCARD) - atmel_write16(dev, GCR, 0x0060); - atmel_write16(dev, GCR, 0x0040); - rc = 1; - } - } - - if (rc) { - if (dev->dev_addr[0] == 0xFF) { - u8 default_mac[] = {0x00, 0x04, 0x25, 0x00, 0x00, 0x00}; - printk(KERN_ALERT "%s: *** Invalid MAC address. UPGRADE Firmware ****\n", dev->name); - memcpy(dev->dev_addr, default_mac, 6); - } - } - - return rc; -} - -/* Move the encyption information on the MIB structure. - This routine is for the pre-WPA firmware: later firmware has - a different format MIB and a different routine. */ -static void build_wep_mib(struct atmel_private *priv) -{ - struct { /* NB this is matched to the hardware, don't change. */ - u8 wep_is_on; - u8 default_key; /* 0..3 */ - u8 reserved; - u8 exclude_unencrypted; - - u32 WEPICV_error_count; - u32 WEP_excluded_count; - - u8 wep_keys[MAX_ENCRYPTION_KEYS][13]; - u8 encryption_level; /* 0, 1, 2 */ - u8 reserved2[3]; - } mib; - int i; - - mib.wep_is_on = priv->wep_is_on; - if (priv->wep_is_on) { - if (priv->wep_key_len[priv->default_key] > 5) - mib.encryption_level = 2; - else - mib.encryption_level = 1; - } else { - mib.encryption_level = 0; - } - - mib.default_key = priv->default_key; - mib.exclude_unencrypted = priv->exclude_unencrypted; - - for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) - memcpy(mib.wep_keys[i], priv->wep_keys[i], 13); - - atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib)); -} - -static void build_wpa_mib(struct atmel_private *priv) -{ - /* This is for the later (WPA enabled) firmware. */ - - struct { /* NB this is matched to the hardware, don't change. */ - u8 cipher_default_key_value[MAX_ENCRYPTION_KEYS][MAX_ENCRYPTION_KEY_SIZE]; - u8 receiver_address[6]; - u8 wep_is_on; - u8 default_key; /* 0..3 */ - u8 group_key; - u8 exclude_unencrypted; - u8 encryption_type; - u8 reserved; - - u32 WEPICV_error_count; - u32 WEP_excluded_count; - - u8 key_RSC[4][8]; - } mib; - - int i; - - mib.wep_is_on = priv->wep_is_on; - mib.exclude_unencrypted = priv->exclude_unencrypted; - memcpy(mib.receiver_address, priv->CurrentBSSID, 6); - - /* zero all the keys before adding in valid ones. */ - memset(mib.cipher_default_key_value, 0, sizeof(mib.cipher_default_key_value)); - - if (priv->wep_is_on) { - /* There's a comment in the Atmel code to the effect that this - is only valid when still using WEP, it may need to be set to - something to use WPA */ - memset(mib.key_RSC, 0, sizeof(mib.key_RSC)); - - mib.default_key = mib.group_key = 255; - for (i = 0; i < MAX_ENCRYPTION_KEYS; i++) { - if (priv->wep_key_len[i] > 0) { - memcpy(mib.cipher_default_key_value[i], priv->wep_keys[i], MAX_ENCRYPTION_KEY_SIZE); - if (i == priv->default_key) { - mib.default_key = i; - mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 7; - mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->pairwise_cipher_suite; - } else { - mib.group_key = i; - priv->group_cipher_suite = priv->pairwise_cipher_suite; - mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-1] = 1; - mib.cipher_default_key_value[i][MAX_ENCRYPTION_KEY_SIZE-2] = priv->group_cipher_suite; - } - } - } - if (mib.default_key == 255) - mib.default_key = mib.group_key != 255 ? mib.group_key : 0; - if (mib.group_key == 255) - mib.group_key = mib.default_key; - - } - - atmel_set_mib(priv, Mac_Wep_Mib_Type, 0, (u8 *)&mib, sizeof(mib)); -} - -static int reset_atmel_card(struct net_device *dev) -{ - /* do everything necessary to wake up the hardware, including - waiting for the lightning strike and throwing the knife switch.... - - set all the Mib values which matter in the card to match - their settings in the atmel_private structure. Some of these - can be altered on the fly, but many (WEP, infrastucture or ad-hoc) - can only be changed by tearing down the world and coming back through - here. - - This routine is also responsible for initialising some - hardware-specific fields in the atmel_private structure, - including a copy of the firmware's hostinfo stucture - which is the route into the rest of the firmware datastructures. */ - - struct atmel_private *priv = netdev_priv(dev); - u8 configuration; - int old_state = priv->station_state; - int err = 0; - - /* data to add to the firmware names, in priority order - this implemenents firmware versioning */ - - static char *firmware_modifier[] = { - "-wpa", - "", - NULL - }; - - /* reset pccard */ - if (priv->bus_type == BUS_TYPE_PCCARD) - atmel_write16(priv->dev, GCR, 0x0060); - - /* stop card , disable interrupts */ - atmel_write16(priv->dev, GCR, 0x0040); - - if (priv->card_type == CARD_TYPE_EEPROM) { - /* copy in firmware if needed */ - const struct firmware *fw_entry = NULL; - const unsigned char *fw; - int len = priv->firmware_length; - if (!(fw = priv->firmware)) { - if (priv->firmware_type == ATMEL_FW_TYPE_NONE) { - if (strlen(priv->firmware_id) == 0) { - printk(KERN_INFO - "%s: card type is unknown: assuming at76c502 firmware is OK.\n", - dev->name); - printk(KERN_INFO - "%s: if not, use the firmware= module parameter.\n", - dev->name); - strcpy(priv->firmware_id, "atmel_at76c502.bin"); - } - err = request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev); - if (err != 0) { - printk(KERN_ALERT - "%s: firmware %s is missing, cannot continue.\n", - dev->name, priv->firmware_id); - return err; - } - } else { - int fw_index = 0; - int success = 0; - - /* get firmware filename entry based on firmware type ID */ - while (fw_table[fw_index].fw_type != priv->firmware_type - && fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) - fw_index++; - - /* construct the actual firmware file name */ - if (fw_table[fw_index].fw_type != ATMEL_FW_TYPE_NONE) { - int i; - for (i = 0; firmware_modifier[i]; i++) { - snprintf(priv->firmware_id, 32, "%s%s.%s", fw_table[fw_index].fw_file, - firmware_modifier[i], fw_table[fw_index].fw_file_ext); - priv->firmware_id[31] = '\0'; - if (request_firmware(&fw_entry, priv->firmware_id, priv->sys_dev) == 0) { - success = 1; - break; - } - } - } - if (!success) { - printk(KERN_ALERT - "%s: firmware %s is missing, cannot start.\n", - dev->name, priv->firmware_id); - priv->firmware_id[0] = '\0'; - return -ENOENT; - } - } - - fw = fw_entry->data; - len = fw_entry->size; - } - - if (len <= 0x6000) { - atmel_write16(priv->dev, BSR, BSS_IRAM); - atmel_copy_to_card(priv->dev, 0, fw, len); - atmel_set_gcr(priv->dev, GCR_REMAP); - } else { - /* Remap */ - atmel_set_gcr(priv->dev, GCR_REMAP); - atmel_write16(priv->dev, BSR, BSS_IRAM); - atmel_copy_to_card(priv->dev, 0, fw, 0x6000); - atmel_write16(priv->dev, BSR, 0x2ff); - atmel_copy_to_card(priv->dev, 0x8000, &fw[0x6000], len - 0x6000); - } - - if (fw_entry) - release_firmware(fw_entry); - } - - err = atmel_wakeup_firmware(priv); - if (err != 0) - return err; - - /* Check the version and set the correct flag for wpa stuff, - old and new firmware is incompatible. - The pre-wpa 3com firmware reports major version 5, - the wpa 3com firmware is major version 4 and doesn't need - the 3com broken-ness filter. */ - priv->use_wpa = (priv->host_info.major_version == 4); - priv->radio_on_broken = (priv->host_info.major_version == 5); - - /* unmask all irq sources */ - atmel_wmem8(priv, atmel_hi(priv, IFACE_INT_MASK_OFFSET), 0xff); - - /* int Tx system and enable Tx */ - atmel_wmem8(priv, atmel_tx(priv, TX_DESC_FLAGS_OFFSET, 0), 0); - atmel_wmem32(priv, atmel_tx(priv, TX_DESC_NEXT_OFFSET, 0), 0x80000000L); - atmel_wmem16(priv, atmel_tx(priv, TX_DESC_POS_OFFSET, 0), 0); - atmel_wmem16(priv, atmel_tx(priv, TX_DESC_SIZE_OFFSET, 0), 0); - - priv->tx_desc_free = priv->host_info.tx_desc_count; - priv->tx_desc_head = 0; - priv->tx_desc_tail = 0; - priv->tx_desc_previous = 0; - priv->tx_free_mem = priv->host_info.tx_buff_size; - priv->tx_buff_head = 0; - priv->tx_buff_tail = 0; - - configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); - atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), - configuration | FUNC_CTRL_TxENABLE); - - /* init Rx system and enable */ - priv->rx_desc_head = 0; - - configuration = atmel_rmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET)); - atmel_wmem8(priv, atmel_hi(priv, IFACE_FUNC_CTRL_OFFSET), - configuration | FUNC_CTRL_RxENABLE); - - if (!priv->radio_on_broken) { - if (atmel_send_command_wait(priv, CMD_EnableRadio, NULL, 0) == - CMD_STATUS_REJECTED_RADIO_OFF) { - printk(KERN_INFO "%s: cannot turn the radio on.\n", - dev->name); - return -EIO; - } - } - - /* set up enough MIB values to run. */ - atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_AUTO_TX_RATE_POS, priv->auto_tx_rate); - atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_TX_PROMISCUOUS_POS, PROM_MODE_OFF); - atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_RTS_THRESHOLD_POS, priv->rts_threshold); - atmel_set_mib16(priv, Mac_Mib_Type, MAC_MIB_FRAG_THRESHOLD_POS, priv->frag_threshold); - atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_SHORT_RETRY_POS, priv->short_retry); - atmel_set_mib8(priv, Mac_Mib_Type, MAC_MIB_LONG_RETRY_POS, priv->long_retry); - atmel_set_mib8(priv, Local_Mib_Type, LOCAL_MIB_PREAMBLE_TYPE, priv->preamble); - atmel_set_mib(priv, Mac_Address_Mib_Type, MAC_ADDR_MIB_MAC_ADDR_POS, - priv->dev->dev_addr, 6); - atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_PS_MODE_POS, ACTIVE_MODE); - atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_LISTEN_INTERVAL_POS, 1); - atmel_set_mib16(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_BEACON_PER_POS, priv->default_beacon_period); - atmel_set_mib(priv, Phy_Mib_Type, PHY_MIB_RATE_SET_POS, atmel_basic_rates, 4); - atmel_set_mib8(priv, Mac_Mgmt_Mib_Type, MAC_MGMT_MIB_CUR_PRIVACY_POS, priv->wep_is_on); - if (priv->use_wpa) - build_wpa_mib(priv); - else - build_wep_mib(priv); - - if (old_state == STATION_STATE_READY) { - union iwreq_data wrqu; - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - } - - return 0; -} - -static void atmel_send_command(struct atmel_private *priv, int command, - void *cmd, int cmd_size) -{ - if (cmd) - atmel_copy_to_card(priv->dev, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET), - cmd, cmd_size); - - atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_COMMAND_OFFSET), command); - atmel_wmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET), 0); -} - -static int atmel_send_command_wait(struct atmel_private *priv, int command, - void *cmd, int cmd_size) -{ - int i, status; - - atmel_send_command(priv, command, cmd, cmd_size); - - for (i = 5000; i; i--) { - status = atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_STATUS_OFFSET)); - if (status != CMD_STATUS_IDLE && - status != CMD_STATUS_IN_PROGRESS) - break; - udelay(20); - } - - if (i == 0) { - printk(KERN_ALERT "%s: failed to contact MAC.\n", priv->dev->name); - status = CMD_STATUS_HOST_ERROR; - } else { - if (command != CMD_EnableRadio) - status = CMD_STATUS_COMPLETE; - } - - return status; -} - -static u8 atmel_get_mib8(struct atmel_private *priv, u8 type, u8 index) -{ - struct get_set_mib m; - m.type = type; - m.size = 1; - m.index = index; - - atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + 1); - return atmel_rmem8(priv, atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE)); -} - -static void atmel_set_mib8(struct atmel_private *priv, u8 type, u8 index, u8 data) -{ - struct get_set_mib m; - m.type = type; - m.size = 1; - m.index = index; - m.data[0] = data; - - atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 1); -} - -static void atmel_set_mib16(struct atmel_private *priv, u8 type, u8 index, - u16 data) -{ - struct get_set_mib m; - m.type = type; - m.size = 2; - m.index = index; - m.data[0] = data; - m.data[1] = data >> 8; - - atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + 2); -} - -static void atmel_set_mib(struct atmel_private *priv, u8 type, u8 index, - u8 *data, int data_len) -{ - struct get_set_mib m; - m.type = type; - m.size = data_len; - m.index = index; - - if (data_len > MIB_MAX_DATA_BYTES) - printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name); - - memcpy(m.data, data, data_len); - atmel_send_command_wait(priv, CMD_Set_MIB_Vars, &m, MIB_HEADER_SIZE + data_len); -} - -static void atmel_get_mib(struct atmel_private *priv, u8 type, u8 index, - u8 *data, int data_len) -{ - struct get_set_mib m; - m.type = type; - m.size = data_len; - m.index = index; - - if (data_len > MIB_MAX_DATA_BYTES) - printk(KERN_ALERT "%s: MIB buffer too small.\n", priv->dev->name); - - atmel_send_command_wait(priv, CMD_Get_MIB_Vars, &m, MIB_HEADER_SIZE + data_len); - atmel_copy_to_host(priv->dev, data, - atmel_co(priv, CMD_BLOCK_PARAMETERS_OFFSET + MIB_HEADER_SIZE), data_len); -} - -static void atmel_writeAR(struct net_device *dev, u16 data) -{ - int i; - outw(data, dev->base_addr + AR); - /* Address register appears to need some convincing..... */ - for (i = 0; data != inw(dev->base_addr + AR) && i < 10; i++) - outw(data, dev->base_addr + AR); -} - -static void atmel_copy_to_card(struct net_device *dev, u16 dest, - const unsigned char *src, u16 len) -{ - int i; - atmel_writeAR(dev, dest); - if (dest % 2) { - atmel_write8(dev, DR, *src); - src++; len--; - } - for (i = len; i > 1 ; i -= 2) { - u8 lb = *src++; - u8 hb = *src++; - atmel_write16(dev, DR, lb | (hb << 8)); - } - if (i) - atmel_write8(dev, DR, *src); -} - -static void atmel_copy_to_host(struct net_device *dev, unsigned char *dest, - u16 src, u16 len) -{ - int i; - atmel_writeAR(dev, src); - if (src % 2) { - *dest = atmel_read8(dev, DR); - dest++; len--; - } - for (i = len; i > 1 ; i -= 2) { - u16 hw = atmel_read16(dev, DR); - *dest++ = hw; - *dest++ = hw >> 8; - } - if (i) - *dest = atmel_read8(dev, DR); -} - -static void atmel_set_gcr(struct net_device *dev, u16 mask) -{ - outw(inw(dev->base_addr + GCR) | mask, dev->base_addr + GCR); -} - -static void atmel_clear_gcr(struct net_device *dev, u16 mask) -{ - outw(inw(dev->base_addr + GCR) & ~mask, dev->base_addr + GCR); -} - -static int atmel_lock_mac(struct atmel_private *priv) -{ - int i, j = 20; - retry: - for (i = 5000; i; i--) { - if (!atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) - break; - udelay(20); - } - - if (!i) - return 0; /* timed out */ - - atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 1); - if (atmel_rmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_HOST_OFFSET))) { - atmel_wmem8(priv, atmel_hi(priv, IFACE_LOCKOUT_MAC_OFFSET), 0); - if (!j--) - return 0; /* timed out */ - goto retry; - } - - return 1; -} - -static void atmel_wmem32(struct atmel_private *priv, u16 pos, u32 data) -{ - atmel_writeAR(priv->dev, pos); - atmel_write16(priv->dev, DR, data); /* card is little-endian */ - atmel_write16(priv->dev, DR, data >> 16); -} - -/***************************************************************************/ -/* There follows the source form of the MAC address reading firmware */ -/***************************************************************************/ -#if 0 - -/* Copyright 2003 Matthew T. Russotto */ -/* But derived from the Atmel 76C502 firmware written by Atmel and */ -/* included in "atmel wireless lan drivers" package */ -/** - This file is part of net.russotto.AtmelMACFW, hereto referred to - as AtmelMACFW - - AtmelMACFW is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License version 2 - as published by the Free Software Foundation. - - AtmelMACFW 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 AtmelMACFW; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -****************************************************************************/ -/* This firmware should work on the 76C502 RFMD, RFMD_D, and RFMD_E */ -/* It will probably work on the 76C504 and 76C502 RFMD_3COM */ -/* It only works on SPI EEPROM versions of the card. */ - -/* This firmware initializes the SPI controller and clock, reads the MAC */ -/* address from the EEPROM into SRAM, and puts the SRAM offset of the MAC */ -/* address in MR2, and sets MR3 to 0x10 to indicate it is done */ -/* It also puts a complete copy of the EEPROM in SRAM with the offset in */ -/* MR4, for investigational purposes (maybe we can determine chip type */ -/* from that?) */ - - .org 0 - .set MRBASE, 0x8000000 - .set CPSR_INITIAL, 0xD3 /* IRQ/FIQ disabled, ARM mode, Supervisor state */ - .set CPSR_USER, 0xD1 /* IRQ/FIQ disabled, ARM mode, USER state */ - .set SRAM_BASE, 0x02000000 - .set SP_BASE, 0x0F300000 - .set UNK_BASE, 0x0F000000 /* Some internal device, but which one? */ - .set SPI_CGEN_BASE, 0x0E000000 /* Some internal device, but which one? */ - .set UNK3_BASE, 0x02014000 /* Some internal device, but which one? */ - .set STACK_BASE, 0x5600 - .set SP_SR, 0x10 - .set SP_TDRE, 2 /* status register bit -- TDR empty */ - .set SP_RDRF, 1 /* status register bit -- RDR full */ - .set SP_SWRST, 0x80 - .set SP_SPIEN, 0x1 - .set SP_CR, 0 /* control register */ - .set SP_MR, 4 /* mode register */ - .set SP_RDR, 0x08 /* Read Data Register */ - .set SP_TDR, 0x0C /* Transmit Data Register */ - .set SP_CSR0, 0x30 /* chip select registers */ - .set SP_CSR1, 0x34 - .set SP_CSR2, 0x38 - .set SP_CSR3, 0x3C - .set NVRAM_CMD_RDSR, 5 /* read status register */ - .set NVRAM_CMD_READ, 3 /* read data */ - .set NVRAM_SR_RDY, 1 /* RDY bit. This bit is inverted */ - .set SPI_8CLOCKS, 0xFF /* Writing this to the TDR doesn't do anything to the - serial output, since SO is normally high. But it - does cause 8 clock cycles and thus 8 bits to be - clocked in to the chip. See Atmel's SPI - controller (e.g. AT91M55800) timing and 4K - SPI EEPROM manuals */ - - .set NVRAM_SCRATCH, 0x02000100 /* arbitrary area for scratchpad memory */ - .set NVRAM_IMAGE, 0x02000200 - .set NVRAM_LENGTH, 0x0200 - .set MAC_ADDRESS_MIB, SRAM_BASE - .set MAC_ADDRESS_LENGTH, 6 - .set MAC_BOOT_FLAG, 0x10 - .set MR1, 0 - .set MR2, 4 - .set MR3, 8 - .set MR4, 0xC -RESET_VECTOR: - b RESET_HANDLER -UNDEF_VECTOR: - b HALT1 -SWI_VECTOR: - b HALT1 -IABORT_VECTOR: - b HALT1 -DABORT_VECTOR: -RESERVED_VECTOR: - b HALT1 -IRQ_VECTOR: - b HALT1 -FIQ_VECTOR: - b HALT1 -HALT1: b HALT1 -RESET_HANDLER: - mov r0, #CPSR_INITIAL - msr CPSR_c, r0 /* This is probably unnecessary */ - -/* I'm guessing this is initializing clock generator electronics for SPI */ - ldr r0, =SPI_CGEN_BASE - mov r1, #0 - mov r1, r1, lsl #3 - orr r1, r1, #0 - str r1, [r0] - ldr r1, [r0, #28] - bic r1, r1, #16 - str r1, [r0, #28] - mov r1, #1 - str r1, [r0, #8] - - ldr r0, =MRBASE - mov r1, #0 - strh r1, [r0, #MR1] - strh r1, [r0, #MR2] - strh r1, [r0, #MR3] - strh r1, [r0, #MR4] - - mov sp, #STACK_BASE - bl SP_INIT - mov r0, #10 - bl DELAY9 - bl GET_MAC_ADDR - bl GET_WHOLE_NVRAM - ldr r0, =MRBASE - ldr r1, =MAC_ADDRESS_MIB - strh r1, [r0, #MR2] - ldr r1, =NVRAM_IMAGE - strh r1, [r0, #MR4] - mov r1, #MAC_BOOT_FLAG - strh r1, [r0, #MR3] -HALT2: b HALT2 -.func Get_Whole_NVRAM, GET_WHOLE_NVRAM -GET_WHOLE_NVRAM: - stmdb sp!, {lr} - mov r2, #0 /* 0th bytes of NVRAM */ - mov r3, #NVRAM_LENGTH - mov r1, #0 /* not used in routine */ - ldr r0, =NVRAM_IMAGE - bl NVRAM_XFER - ldmia sp!, {lr} - bx lr -.endfunc - -.func Get_MAC_Addr, GET_MAC_ADDR -GET_MAC_ADDR: - stmdb sp!, {lr} - mov r2, #0x120 /* address of MAC Address within NVRAM */ - mov r3, #MAC_ADDRESS_LENGTH - mov r1, #0 /* not used in routine */ - ldr r0, =MAC_ADDRESS_MIB - bl NVRAM_XFER - ldmia sp!, {lr} - bx lr -.endfunc -.ltorg -.func Delay9, DELAY9 -DELAY9: - adds r0, r0, r0, LSL #3 /* r0 = r0 * 9 */ -DELAYLOOP: - beq DELAY9_done - subs r0, r0, #1 - b DELAYLOOP -DELAY9_done: - bx lr -.endfunc - -.func SP_Init, SP_INIT -SP_INIT: - mov r1, #SP_SWRST - ldr r0, =SP_BASE - str r1, [r0, #SP_CR] /* reset the SPI */ - mov r1, #0 - str r1, [r0, #SP_CR] /* release SPI from reset state */ - mov r1, #SP_SPIEN - str r1, [r0, #SP_MR] /* set the SPI to MASTER mode*/ - str r1, [r0, #SP_CR] /* enable the SPI */ - -/* My guess would be this turns on the SPI clock */ - ldr r3, =SPI_CGEN_BASE - ldr r1, [r3, #28] - orr r1, r1, #0x2000 - str r1, [r3, #28] - - ldr r1, =0x2000c01 - str r1, [r0, #SP_CSR0] - ldr r1, =0x2000201 - str r1, [r0, #SP_CSR1] - str r1, [r0, #SP_CSR2] - str r1, [r0, #SP_CSR3] - ldr r1, [r0, #SP_SR] - ldr r0, [r0, #SP_RDR] - bx lr -.endfunc -.func NVRAM_Init, NVRAM_INIT -NVRAM_INIT: - ldr r1, =SP_BASE - ldr r0, [r1, #SP_RDR] - mov r0, #NVRAM_CMD_RDSR - str r0, [r1, #SP_TDR] -SP_loop1: - ldr r0, [r1, #SP_SR] - tst r0, #SP_TDRE - beq SP_loop1 - - mov r0, #SPI_8CLOCKS - str r0, [r1, #SP_TDR] -SP_loop2: - ldr r0, [r1, #SP_SR] - tst r0, #SP_TDRE - beq SP_loop2 - - ldr r0, [r1, #SP_RDR] -SP_loop3: - ldr r0, [r1, #SP_SR] - tst r0, #SP_RDRF - beq SP_loop3 - - ldr r0, [r1, #SP_RDR] - and r0, r0, #255 - bx lr -.endfunc - -.func NVRAM_Xfer, NVRAM_XFER - /* r0 = dest address */ - /* r1 = not used */ - /* r2 = src address within NVRAM */ - /* r3 = length */ -NVRAM_XFER: - stmdb sp!, {r4, r5, lr} - mov r5, r0 /* save r0 (dest address) */ - mov r4, r3 /* save r3 (length) */ - mov r0, r2, LSR #5 /* SPI memories put A8 in the command field */ - and r0, r0, #8 - add r0, r0, #NVRAM_CMD_READ - ldr r1, =NVRAM_SCRATCH - strb r0, [r1, #0] /* save command in NVRAM_SCRATCH[0] */ - strb r2, [r1, #1] /* save low byte of source address in NVRAM_SCRATCH[1] */ -_local1: - bl NVRAM_INIT - tst r0, #NVRAM_SR_RDY - bne _local1 - mov r0, #20 - bl DELAY9 - mov r2, r4 /* length */ - mov r1, r5 /* dest address */ - mov r0, #2 /* bytes to transfer in command */ - bl NVRAM_XFER2 - ldmia sp!, {r4, r5, lr} - bx lr -.endfunc - -.func NVRAM_Xfer2, NVRAM_XFER2 -NVRAM_XFER2: - stmdb sp!, {r4, r5, r6, lr} - ldr r4, =SP_BASE - mov r3, #0 - cmp r0, #0 - bls _local2 - ldr r5, =NVRAM_SCRATCH -_local4: - ldrb r6, [r5, r3] - str r6, [r4, #SP_TDR] -_local3: - ldr r6, [r4, #SP_SR] - tst r6, #SP_TDRE - beq _local3 - add r3, r3, #1 - cmp r3, r0 /* r0 is # of bytes to send out (command+addr) */ - blo _local4 -_local2: - mov r3, #SPI_8CLOCKS - str r3, [r4, #SP_TDR] - ldr r0, [r4, #SP_RDR] -_local5: - ldr r0, [r4, #SP_SR] - tst r0, #SP_RDRF - beq _local5 - ldr r0, [r4, #SP_RDR] /* what's this byte? It's the byte read while writing the TDR -- nonsense, because the NVRAM doesn't read and write at the same time */ - mov r0, #0 - cmp r2, #0 /* r2 is # of bytes to copy in */ - bls _local6 -_local7: - ldr r5, [r4, #SP_SR] - tst r5, #SP_TDRE - beq _local7 - str r3, [r4, #SP_TDR] /* r3 has SPI_8CLOCKS */ -_local8: - ldr r5, [r4, #SP_SR] - tst r5, #SP_RDRF - beq _local8 - ldr r5, [r4, #SP_RDR] /* but didn't we read this byte above? */ - strb r5, [r1], #1 /* postindexed */ - add r0, r0, #1 - cmp r0, r2 - blo _local7 /* since we don't send another address, the NVRAM must be capable of sequential reads */ -_local6: - mov r0, #200 - bl DELAY9 - ldmia sp!, {r4, r5, r6, lr} - bx lr -#endif diff --git a/drivers/net/wireless/atmel.h b/drivers/net/wireless/atmel.h deleted file mode 100644 index b9b3e5b76544..000000000000 --- a/drivers/net/wireless/atmel.h +++ /dev/null @@ -1,43 +0,0 @@ -/*** -*- linux-c -*- ********************************************************** - - Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. - - Copyright 2005 Dan Williams and Red Hat, Inc. - - 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 software 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 Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -******************************************************************************/ - -#ifndef _ATMEL_H -#define _ATMEL_H - -typedef enum { - ATMEL_FW_TYPE_NONE = 0, - ATMEL_FW_TYPE_502, - ATMEL_FW_TYPE_502D, - ATMEL_FW_TYPE_502E, - ATMEL_FW_TYPE_502_3COM, - ATMEL_FW_TYPE_504, - ATMEL_FW_TYPE_504_2958, - ATMEL_FW_TYPE_504A_2958, - ATMEL_FW_TYPE_506 -} AtmelFWType; - -struct net_device *init_atmel_card(unsigned short, unsigned long, const AtmelFWType, struct device *, - int (*present_func)(void *), void * ); -void stop_atmel_card( struct net_device *); -int atmel_open( struct net_device * ); - -#endif diff --git a/drivers/net/wireless/atmel_cs.c b/drivers/net/wireless/atmel_cs.c deleted file mode 100644 index ddaa859c3491..000000000000 --- a/drivers/net/wireless/atmel_cs.c +++ /dev/null @@ -1,496 +0,0 @@ -/*** -*- linux-c -*- ********************************************************** - - Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. - - Copyright 2000-2001 ATMEL Corporation. - Copyright 2003 Simon Kelley. - - This code was developed from version 2.1.1 of the Atmel drivers, - released by Atmel corp. under the GPL in December 2002. It also - includes code from the Linux aironet drivers (C) Benjamin Reed, - and the Linux PCMCIA package, (C) David Hinds. - - For all queries about this code, please contact the current author, - Simon Kelley and not Atmel Corporation. - - 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 software 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 Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -******************************************************************************/ - -#ifdef __IN_PCMCIA_PACKAGE__ -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "atmel.h" - -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -static char *version = "$Revision: 1.2 $"; -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -MODULE_AUTHOR("Simon Kelley"); -MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards."); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("Atmel at76c50x PCMCIA cards"); - -/*====================================================================*/ - -/* - The event() function is this driver's Card Services event handler. - It will be called by Card Services when an appropriate card status - event is received. The config() and release() entry points are - used to configure or release a socket, in response to card - insertion and ejection events. They are invoked from the atmel_cs - event handler. -*/ - -static int atmel_config(struct pcmcia_device *link); -static void atmel_release(struct pcmcia_device *link); - -/* - The attach() and detach() entry points are used to create and destroy - "instances" of the driver, where each instance represents everything - needed to manage one actual PCMCIA card. -*/ - -static void atmel_detach(struct pcmcia_device *p_dev); - -/* - You'll also need to prototype all the functions that will actually - be used to talk to your device. See 'pcmem_cs' for a good example - of a fully self-sufficient driver; the other drivers rely more or - less on other parts of the kernel. -*/ - -/* - A linked list of "instances" of the atmelnet device. Each actual - PCMCIA card corresponds to one device instance, and is described - by one struct pcmcia_device structure (defined in ds.h). - - You may not want to use a linked list for this -- for example, the - memory card driver uses an array of struct pcmcia_device pointers, where minor - device numbers are used to derive the corresponding array index. -*/ - -/* - A driver needs to provide a dev_node_t structure for each device - on a card. In some cases, there is only one device per card (for - example, ethernet cards, modems). In other cases, there may be - many actual or logical devices (SCSI adapters, memory cards with - multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a struct pcmcia_device - structure. We allocate them in the card's private data structure, - because they generally shouldn't be allocated dynamically. - - In this case, we also provide a flag to indicate if a device is - "stopped" due to a power management event, or card ejection. The - device IO routines can use a flag like this to throttle IO to a - card that is not ready to accept it. -*/ - -typedef struct local_info_t { - dev_node_t node; - struct net_device *eth_dev; -} local_info_t; - -/*====================================================================== - - atmel_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. - - ======================================================================*/ - -static int atmel_probe(struct pcmcia_device *p_dev) -{ - local_info_t *local; - - DEBUG(0, "atmel_attach()\n"); - - /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - p_dev->irq.Handler = NULL; - - /* - General socket configuration defaults can go here. In this - client, we assume very little, and rely on the CIS for almost - everything. In most clients, many details (i.e., number, sizes, - and attributes of IO windows) are fixed by the nature of the - device, and can be hard-wired here. - */ - p_dev->conf.Attributes = 0; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - - /* Allocate space for private device-specific data */ - local = kzalloc(sizeof(local_info_t), GFP_KERNEL); - if (!local) { - printk(KERN_ERR "atmel_cs: no memory for new device\n"); - return -ENOMEM; - } - p_dev->priv = local; - - return atmel_config(p_dev); -} /* atmel_attach */ - -/*====================================================================== - - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. - - ======================================================================*/ - -static void atmel_detach(struct pcmcia_device *link) -{ - DEBUG(0, "atmel_detach(0x%p)\n", link); - - atmel_release(link); - - kfree(link->priv); -} - -/*====================================================================== - - atmel_config() is scheduled to run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - device available to the system. - - ======================================================================*/ - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -/* Call-back function to interrogate PCMCIA-specific information - about the current existance of the card */ -static int card_present(void *arg) -{ - struct pcmcia_device *link = (struct pcmcia_device *)arg; - - if (pcmcia_dev_present(link)) - return 1; - - return 0; -} - -static int atmel_config_check(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) -{ - if (cfg->index == 0) - return -ENODEV; - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - p_dev->conf.Attributes |= CONF_ENABLE_SPKR; - p_dev->conf.Status = CCSR_AUDIO_ENA; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vpp1.present & (1<conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM]/10000; - else if (dflt->vpp1.present & (1<conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM]/10000; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; - } - } - - /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); -} - -static int atmel_config(struct pcmcia_device *link) -{ - local_info_t *dev; - int last_fn, last_ret; - struct pcmcia_device_id *did; - - dev = link->priv; - did = dev_get_drvdata(&handle_to_dev(link)); - - DEBUG(0, "atmel_config(0x%p)\n", link); - - /* - In this loop, we scan the CIS for configuration table entries, - each of which describes a valid card configuration, including - voltage, IO window, memory window, and interrupt settings. - - We make no assumptions about the card to be configured: we use - just the information available in the CIS. In an ideal world, - this would work for any PCMCIA card, but it requires a complete - and accurate CIS. In practice, a driver usually "knows" most of - these things without consulting the CIS, and most client drivers - will only use the CIS to fill in implementation-defined details. - */ - if (pcmcia_loop_config(link, atmel_config_check, NULL)) - goto failed; - - /* - Allocate an interrupt line. Note that this does not assign a - handler to the interrupt, unless the 'Handler' member of the - irq structure is initialized. - */ - if (link->conf.Attributes & CONF_ENABLE_IRQ) - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - - /* - This actually configures the PCMCIA socket -- setting up - the I/O windows and the interrupt mapping, and putting the - card and host interface into "Memory and IO" mode. - */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - - if (link->irq.AssignedIRQ == 0) { - printk(KERN_ALERT - "atmel: cannot assign IRQ: check that CONFIG_ISA is set in kernel config."); - goto cs_failed; - } - - ((local_info_t*)link->priv)->eth_dev = - init_atmel_card(link->irq.AssignedIRQ, - link->io.BasePort1, - did ? did->driver_info : ATMEL_FW_TYPE_NONE, - &handle_to_dev(link), - card_present, - link); - if (!((local_info_t*)link->priv)->eth_dev) - goto cs_failed; - - - /* - At this point, the dev_node_t structure(s) need to be - initialized and arranged in a linked list at link->dev_node. - */ - strcpy(dev->node.dev_name, ((local_info_t*)link->priv)->eth_dev->name ); - dev->node.major = dev->node.minor = 0; - link->dev_node = &dev->node; - - return 0; - - cs_failed: - cs_error(link, last_fn, last_ret); - failed: - atmel_release(link); - return -ENODEV; -} - -/*====================================================================== - - After a card is removed, atmel_release() will unregister the - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. - - ======================================================================*/ - -static void atmel_release(struct pcmcia_device *link) -{ - struct net_device *dev = ((local_info_t*)link->priv)->eth_dev; - - DEBUG(0, "atmel_release(0x%p)\n", link); - - if (dev) - stop_atmel_card(dev); - ((local_info_t*)link->priv)->eth_dev = NULL; - - pcmcia_disable_device(link); -} - -static int atmel_suspend(struct pcmcia_device *link) -{ - local_info_t *local = link->priv; - - netif_device_detach(local->eth_dev); - - return 0; -} - -static int atmel_resume(struct pcmcia_device *link) -{ - local_info_t *local = link->priv; - - atmel_open(local->eth_dev); - netif_device_attach(local->eth_dev); - - return 0; -} - -/*====================================================================*/ -/* We use the driver_info field to store the correct firmware type for a card. */ - -#define PCMCIA_DEVICE_MANF_CARD_INFO(manf, card, info) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_MANF_ID| \ - PCMCIA_DEV_ID_MATCH_CARD_ID, \ - .manf_id = (manf), \ - .card_id = (card), \ - .driver_info = (kernel_ulong_t)(info), } - -#define PCMCIA_DEVICE_PROD_ID12_INFO(v1, v2, vh1, vh2, info) { \ - .match_flags = PCMCIA_DEV_ID_MATCH_PROD_ID1| \ - PCMCIA_DEV_ID_MATCH_PROD_ID2, \ - .prod_id = { (v1), (v2), NULL, NULL }, \ - .prod_id_hash = { (vh1), (vh2), 0, 0 }, \ - .driver_info = (kernel_ulong_t)(info), } - -static struct pcmcia_device_id atmel_ids[] = { - PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0620, ATMEL_FW_TYPE_502_3COM), - PCMCIA_DEVICE_MANF_CARD_INFO(0x0101, 0x0696, ATMEL_FW_TYPE_502_3COM), - PCMCIA_DEVICE_MANF_CARD_INFO(0x01bf, 0x3302, ATMEL_FW_TYPE_502E), - PCMCIA_DEVICE_MANF_CARD_INFO(0xd601, 0x0007, ATMEL_FW_TYPE_502), - PCMCIA_DEVICE_PROD_ID12_INFO("11WAVE", "11WP611AL-E", 0x9eb2da1f, 0xc9a0d3f9, ATMEL_FW_TYPE_502E), - PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR", 0xabda4164, 0x41b37e1f, ATMEL_FW_TYPE_502), - PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_D", 0xabda4164, 0x3675d704, ATMEL_FW_TYPE_502D), - PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C502AR_E", 0xabda4164, 0x4172e792, ATMEL_FW_TYPE_502E), - PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504_R", 0xabda4164, 0x917f3d72, ATMEL_FW_TYPE_504_2958), - PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504", 0xabda4164, 0x5040670a, ATMEL_FW_TYPE_504), - PCMCIA_DEVICE_PROD_ID12_INFO("ATMEL", "AT76C504A", 0xabda4164, 0xe15ed87f, ATMEL_FW_TYPE_504A_2958), - PCMCIA_DEVICE_PROD_ID12_INFO("BT", "Voyager 1020 Laptop Adapter", 0xae49b86a, 0x1e957cd5, ATMEL_FW_TYPE_502), - PCMCIA_DEVICE_PROD_ID12_INFO("CNet", "CNWLC 11Mbps Wireless PC Card V-5", 0xbc477dde, 0x502fae6b, ATMEL_FW_TYPE_502E), - PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN PC Card", 0x5b878724, 0x122f1df6, ATMEL_FW_TYPE_502), - PCMCIA_DEVICE_PROD_ID12_INFO("IEEE 802.11b", "Wireless LAN Card S", 0x5b878724, 0x5fba533a, ATMEL_FW_TYPE_504_2958), - PCMCIA_DEVICE_PROD_ID12_INFO("OEM", "11Mbps Wireless LAN PC Card V-3", 0xfea54c90, 0x1c5b0f68, ATMEL_FW_TYPE_502), - PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W", 0xc4f8b18b, 0x30f38774, ATMEL_FW_TYPE_502D), - PCMCIA_DEVICE_PROD_ID12_INFO("SMC", "2632W-V2", 0xc4f8b18b, 0x172d1377, ATMEL_FW_TYPE_502), - PCMCIA_DEVICE_PROD_ID12_INFO("Wireless", "PC_CARD", 0xa407ecdd, 0x119f6314, ATMEL_FW_TYPE_502D), - PCMCIA_DEVICE_PROD_ID12_INFO("WLAN", "802.11b PC CARD", 0x575c516c, 0xb1f6dbc4, ATMEL_FW_TYPE_502D), - PCMCIA_DEVICE_PROD_ID12_INFO("LG", "LW2100N", 0xb474d43a, 0x6b1fec94, ATMEL_FW_TYPE_502E), - PCMCIA_DEVICE_NULL -}; - -MODULE_DEVICE_TABLE(pcmcia, atmel_ids); - -static struct pcmcia_driver atmel_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "atmel_cs", - }, - .probe = atmel_probe, - .remove = atmel_detach, - .id_table = atmel_ids, - .suspend = atmel_suspend, - .resume = atmel_resume, -}; - -static int atmel_cs_init(void) -{ - return pcmcia_register_driver(&atmel_driver); -} - -static void atmel_cs_cleanup(void) -{ - pcmcia_unregister_driver(&atmel_driver); -} - -/* - 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. - - In addition: - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - 1. Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. The name of the author may not be used to endorse or promote - products derived from this software without specific prior written - permission. - - THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. -*/ - -module_init(atmel_cs_init); -module_exit(atmel_cs_cleanup); diff --git a/drivers/net/wireless/atmel_pci.c b/drivers/net/wireless/atmel_pci.c deleted file mode 100644 index 92f87fbe750f..000000000000 --- a/drivers/net/wireless/atmel_pci.c +++ /dev/null @@ -1,88 +0,0 @@ -/*** -*- linux-c -*- ********************************************************** - - Driver for Atmel at76c502 at76c504 and at76c506 wireless cards. - - Copyright 2004 Simon Kelley. - - 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 software 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 Atmel wireless lan drivers; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -******************************************************************************/ -#include -#include -#include -#include -#include -#include "atmel.h" - -MODULE_AUTHOR("Simon Kelley"); -MODULE_DESCRIPTION("Support for Atmel at76c50x 802.11 wireless ethernet cards."); -MODULE_LICENSE("GPL"); -MODULE_SUPPORTED_DEVICE("Atmel at76c506 PCI wireless cards"); - -static struct pci_device_id card_ids[] = { - { 0x1114, 0x0506, PCI_ANY_ID, PCI_ANY_ID }, - { 0, } -}; - -MODULE_DEVICE_TABLE(pci, card_ids); - -static int atmel_pci_probe(struct pci_dev *, const struct pci_device_id *); -static void atmel_pci_remove(struct pci_dev *); - -static struct pci_driver atmel_driver = { - .name = "atmel", - .id_table = card_ids, - .probe = atmel_pci_probe, - .remove = __devexit_p(atmel_pci_remove), -}; - - -static int __devinit atmel_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *pent) -{ - struct net_device *dev; - - if (pci_enable_device(pdev)) - return -ENODEV; - - pci_set_master(pdev); - - dev = init_atmel_card(pdev->irq, pdev->resource[1].start, - ATMEL_FW_TYPE_506, - &pdev->dev, NULL, NULL); - if (!dev) - return -ENODEV; - - pci_set_drvdata(pdev, dev); - return 0; -} - -static void __devexit atmel_pci_remove(struct pci_dev *pdev) -{ - stop_atmel_card(pci_get_drvdata(pdev)); -} - -static int __init atmel_init_module(void) -{ - return pci_register_driver(&atmel_driver); -} - -static void __exit atmel_cleanup_module(void) -{ - pci_unregister_driver(&atmel_driver); -} - -module_init(atmel_init_module); -module_exit(atmel_cleanup_module); diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig deleted file mode 100644 index 9da5373c3e59..000000000000 --- a/drivers/net/wireless/b43/Kconfig +++ /dev/null @@ -1,148 +0,0 @@ -config B43 - tristate "Broadcom 43xx wireless support (mac80211 stack)" - depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA - select SSB - select FW_LOADER - ---help--- - b43 is a driver for the Broadcom 43xx series wireless devices. - - Check "lspci" for something like - "Broadcom Corporation BCM43XX 802.11 Wireless LAN Controller" - to determine whether you own such a device. - - This driver supports the new BCM43xx IEEE 802.11G devices, but not - the old IEEE 802.11B devices. Old devices are supported by - the b43legacy driver. - Note that this has nothing to do with the standard that your AccessPoint - supports (A, B, G or a combination). - IEEE 802.11G devices can talk to IEEE 802.11B AccessPoints. - - It is safe to include both b43 and b43legacy as the underlying glue - layer will automatically load the correct version for your device. - - This driver uses V4 firmware, which must be installed separately using - b43-fwcutter. - - This driver can be built as a module (recommended) that will be called "b43". - If unsure, say M. - -# Auto-select SSB PCI-HOST support, if possible -config B43_PCI_AUTOSELECT - bool - depends on B43 && SSB_PCIHOST_POSSIBLE - select SSB_PCIHOST - select SSB_B43_PCI_BRIDGE - default y - -# Auto-select SSB PCICORE driver, if possible -config B43_PCICORE_AUTOSELECT - bool - depends on B43 && SSB_DRIVER_PCICORE_POSSIBLE - select SSB_DRIVER_PCICORE - default y - -config B43_PCMCIA - bool "Broadcom 43xx PCMCIA device support" - depends on B43 && SSB_PCMCIAHOST_POSSIBLE - select SSB_PCMCIAHOST - ---help--- - Broadcom 43xx PCMCIA device support. - - Support for 16bit PCMCIA devices. - Please note that most PC-CARD devices are _NOT_ 16bit PCMCIA - devices, but 32bit CardBUS devices. CardBUS devices are supported - out of the box by b43. - - With this config option you can drive b43 cards in - CompactFlash formfactor in a PCMCIA adaptor. - CF b43 cards can sometimes be found in handheld PCs. - - It's safe to select Y here, even if you don't have a B43 PCMCIA device. - - If unsure, say N. - -config B43_SDIO - bool "Broadcom 43xx SDIO device support (EXPERIMENTAL)" - depends on B43 && SSB_SDIOHOST_POSSIBLE && EXPERIMENTAL - select SSB_SDIOHOST - ---help--- - Broadcom 43xx device support for Soft-MAC SDIO devices. - - With this config option you can drive Soft-MAC b43 cards with a - Secure Digital I/O interface. - This includes the WLAN daughter card found on the Nintendo Wii - video game console. - Note that this does not support Broadcom 43xx Full-MAC devices. - - It's safe to select Y here, even if you don't have a B43 SDIO device. - - If unsure, say N. - -#Data transfers to the device via PIO. We want it as a fallback even -# if we can do DMA. -config B43_PIO - bool - depends on B43 - select SSB_BLOCKIO - default y - -config B43_NPHY - bool "Pre IEEE 802.11n support (BROKEN)" - depends on B43 && EXPERIMENTAL && BROKEN - ---help--- - Support for the IEEE 802.11n draft. - - THIS IS BROKEN AND DOES NOT WORK YET. - - SAY N. - -config B43_PHY_LP - bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)" - depends on B43 && EXPERIMENTAL - default y - ---help--- - Support for the LP-PHY. - The LP-PHY is a low-power PHY built into some notebooks - and embedded devices. It supports 802.11a/g - (802.11a support is optional, and currently disabled). - -# This config option automatically enables b43 LEDS support, -# if it's possible. -config B43_LEDS - bool - depends on B43 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43) - default y - -# This config option automatically enables b43 HW-RNG support, -# if the HW-RNG core is enabled. -config B43_HWRNG - bool - depends on B43 && (HW_RANDOM = y || HW_RANDOM = B43) - default y - -config B43_DEBUG - bool "Broadcom 43xx debugging" - depends on B43 - ---help--- - Broadcom 43xx debugging. - - This adds additional runtime sanity checks and statistics to the driver. - These checks and statistics might me expensive and hurt runtime performance - of your system. - This also adds the b43 debugfs interface. - - Do not enable this, unless you are debugging the driver. - - Say N, if you are a distributor or user building a release kernel - for production use. - Only say Y, if you are debugging a problem in the b43 driver sourcecode. - -config B43_FORCE_PIO - bool "Force usage of PIO instead of DMA" - depends on B43 && B43_DEBUG - ---help--- - This will disable DMA and always enable PIO instead. - - Say N! - This is only for debugging the PIO engine code. You do - _NOT_ want to enable this. diff --git a/drivers/net/wireless/b43/Makefile b/drivers/net/wireless/b43/Makefile deleted file mode 100644 index 5e83b6f0a3a0..000000000000 --- a/drivers/net/wireless/b43/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -b43-y += main.o -b43-y += tables.o -b43-$(CONFIG_B43_NPHY) += tables_nphy.o -b43-y += phy_common.o -b43-y += phy_g.o -b43-y += phy_a.o -b43-$(CONFIG_B43_NPHY) += phy_n.o -b43-$(CONFIG_B43_PHY_LP) += phy_lp.o -b43-$(CONFIG_B43_PHY_LP) += tables_lpphy.o -b43-y += sysfs.o -b43-y += xmit.o -b43-y += lo.o -b43-y += wa.o -b43-y += dma.o -b43-y += pio.o -b43-y += rfkill.o -b43-$(CONFIG_B43_LEDS) += leds.o -b43-$(CONFIG_B43_PCMCIA) += pcmcia.o -b43-$(CONFIG_B43_SDIO) += sdio.o -b43-$(CONFIG_B43_DEBUG) += debugfs.o - -obj-$(CONFIG_B43) += b43.o diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h deleted file mode 100644 index 805d28a06ff5..000000000000 --- a/drivers/net/wireless/b43/b43.h +++ /dev/null @@ -1,918 +0,0 @@ -#ifndef B43_H_ -#define B43_H_ - -#include -#include -#include -#include -#include -#include - -#include "debugfs.h" -#include "leds.h" -#include "rfkill.h" -#include "lo.h" -#include "phy_common.h" - - -/* The unique identifier of the firmware that's officially supported by - * this driver version. */ -#define B43_SUPPORTED_FIRMWARE_ID "FW13" - - -#ifdef CONFIG_B43_DEBUG -# define B43_DEBUG 1 -#else -# define B43_DEBUG 0 -#endif - -#define B43_RX_MAX_SSI 60 - -/* MMIO offsets */ -#define B43_MMIO_DMA0_REASON 0x20 -#define B43_MMIO_DMA0_IRQ_MASK 0x24 -#define B43_MMIO_DMA1_REASON 0x28 -#define B43_MMIO_DMA1_IRQ_MASK 0x2C -#define B43_MMIO_DMA2_REASON 0x30 -#define B43_MMIO_DMA2_IRQ_MASK 0x34 -#define B43_MMIO_DMA3_REASON 0x38 -#define B43_MMIO_DMA3_IRQ_MASK 0x3C -#define B43_MMIO_DMA4_REASON 0x40 -#define B43_MMIO_DMA4_IRQ_MASK 0x44 -#define B43_MMIO_DMA5_REASON 0x48 -#define B43_MMIO_DMA5_IRQ_MASK 0x4C -#define B43_MMIO_MACCTL 0x120 /* MAC control */ -#define B43_MMIO_MACCMD 0x124 /* MAC command */ -#define B43_MMIO_GEN_IRQ_REASON 0x128 -#define B43_MMIO_GEN_IRQ_MASK 0x12C -#define B43_MMIO_RAM_CONTROL 0x130 -#define B43_MMIO_RAM_DATA 0x134 -#define B43_MMIO_PS_STATUS 0x140 -#define B43_MMIO_RADIO_HWENABLED_HI 0x158 -#define B43_MMIO_SHM_CONTROL 0x160 -#define B43_MMIO_SHM_DATA 0x164 -#define B43_MMIO_SHM_DATA_UNALIGNED 0x166 -#define B43_MMIO_XMITSTAT_0 0x170 -#define B43_MMIO_XMITSTAT_1 0x174 -#define B43_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ -#define B43_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ -#define B43_MMIO_TSF_CFP_REP 0x188 -#define B43_MMIO_TSF_CFP_START 0x18C -#define B43_MMIO_TSF_CFP_MAXDUR 0x190 - -/* 32-bit DMA */ -#define B43_MMIO_DMA32_BASE0 0x200 -#define B43_MMIO_DMA32_BASE1 0x220 -#define B43_MMIO_DMA32_BASE2 0x240 -#define B43_MMIO_DMA32_BASE3 0x260 -#define B43_MMIO_DMA32_BASE4 0x280 -#define B43_MMIO_DMA32_BASE5 0x2A0 -/* 64-bit DMA */ -#define B43_MMIO_DMA64_BASE0 0x200 -#define B43_MMIO_DMA64_BASE1 0x240 -#define B43_MMIO_DMA64_BASE2 0x280 -#define B43_MMIO_DMA64_BASE3 0x2C0 -#define B43_MMIO_DMA64_BASE4 0x300 -#define B43_MMIO_DMA64_BASE5 0x340 - -/* PIO on core rev < 11 */ -#define B43_MMIO_PIO_BASE0 0x300 -#define B43_MMIO_PIO_BASE1 0x310 -#define B43_MMIO_PIO_BASE2 0x320 -#define B43_MMIO_PIO_BASE3 0x330 -#define B43_MMIO_PIO_BASE4 0x340 -#define B43_MMIO_PIO_BASE5 0x350 -#define B43_MMIO_PIO_BASE6 0x360 -#define B43_MMIO_PIO_BASE7 0x370 -/* PIO on core rev >= 11 */ -#define B43_MMIO_PIO11_BASE0 0x200 -#define B43_MMIO_PIO11_BASE1 0x240 -#define B43_MMIO_PIO11_BASE2 0x280 -#define B43_MMIO_PIO11_BASE3 0x2C0 -#define B43_MMIO_PIO11_BASE4 0x300 -#define B43_MMIO_PIO11_BASE5 0x340 - -#define B43_MMIO_PHY_VER 0x3E0 -#define B43_MMIO_PHY_RADIO 0x3E2 -#define B43_MMIO_PHY0 0x3E6 -#define B43_MMIO_ANTENNA 0x3E8 -#define B43_MMIO_CHANNEL 0x3F0 -#define B43_MMIO_CHANNEL_EXT 0x3F4 -#define B43_MMIO_RADIO_CONTROL 0x3F6 -#define B43_MMIO_RADIO_DATA_HIGH 0x3F8 -#define B43_MMIO_RADIO_DATA_LOW 0x3FA -#define B43_MMIO_PHY_CONTROL 0x3FC -#define B43_MMIO_PHY_DATA 0x3FE -#define B43_MMIO_MACFILTER_CONTROL 0x420 -#define B43_MMIO_MACFILTER_DATA 0x422 -#define B43_MMIO_RCMTA_COUNT 0x43C -#define B43_MMIO_RADIO_HWENABLED_LO 0x49A -#define B43_MMIO_GPIO_CONTROL 0x49C -#define B43_MMIO_GPIO_MASK 0x49E -#define B43_MMIO_TSF_CFP_START_LOW 0x604 -#define B43_MMIO_TSF_CFP_START_HIGH 0x606 -#define B43_MMIO_TSF_CFP_PRETBTT 0x612 -#define B43_MMIO_TSF_0 0x632 /* core rev < 3 only */ -#define B43_MMIO_TSF_1 0x634 /* core rev < 3 only */ -#define B43_MMIO_TSF_2 0x636 /* core rev < 3 only */ -#define B43_MMIO_TSF_3 0x638 /* core rev < 3 only */ -#define B43_MMIO_RNG 0x65A -#define B43_MMIO_IFSSLOT 0x684 /* Interframe slot time */ -#define B43_MMIO_IFSCTL 0x688 /* Interframe space control */ -#define B43_MMIO_IFSCTL_USE_EDCF 0x0004 -#define B43_MMIO_POWERUP_DELAY 0x6A8 -#define B43_MMIO_BTCOEX_CTL 0x6B4 /* Bluetooth Coexistence Control */ -#define B43_MMIO_BTCOEX_STAT 0x6B6 /* Bluetooth Coexistence Status */ -#define B43_MMIO_BTCOEX_TXCTL 0x6B8 /* Bluetooth Coexistence Transmit Control */ - -/* SPROM boardflags_lo values */ -#define B43_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ -#define B43_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */ -#define B43_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */ -#define B43_BFL_RSSI 0x0008 /* software calculates nrssi slope. */ -#define B43_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */ -#define B43_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */ -#define B43_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */ -#define B43_BFL_ENETADM 0x0080 /* has ADMtek switch */ -#define B43_BFL_ENETVLAN 0x0100 /* can do vlan */ -#define B43_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ -#define B43_BFL_NOPCI 0x0400 /* leaves PCI floating */ -#define B43_BFL_FEM 0x0800 /* supports the Front End Module */ -#define B43_BFL_EXTLNA 0x1000 /* has an external LNA */ -#define B43_BFL_HGPA 0x2000 /* had high gain PA */ -#define B43_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ -#define B43_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ - -/* SPROM boardflags_hi values */ -#define B43_BFH_NOPA 0x0001 /* has no PA */ -#define B43_BFH_RSSIINV 0x0002 /* RSSI uses positive slope (not TSSI) */ -#define B43_BFH_PAREF 0x0004 /* uses the PARef LDO */ -#define B43_BFH_3TSWITCH 0x0008 /* uses a triple throw switch shared - * with bluetooth */ -#define B43_BFH_PHASESHIFT 0x0010 /* can support phase shifter */ -#define B43_BFH_BUCKBOOST 0x0020 /* has buck/booster */ -#define B43_BFH_FEM_BT 0x0040 /* has FEM and switch to share antenna - * with bluetooth */ - -/* GPIO register offset, in both ChipCommon and PCI core. */ -#define B43_GPIO_CONTROL 0x6c - -/* SHM Routing */ -enum { - B43_SHM_UCODE, /* Microcode memory */ - B43_SHM_SHARED, /* Shared memory */ - B43_SHM_SCRATCH, /* Scratch memory */ - B43_SHM_HW, /* Internal hardware register */ - B43_SHM_RCMTA, /* Receive match transmitter address (rev >= 5 only) */ -}; -/* SHM Routing modifiers */ -#define B43_SHM_AUTOINC_R 0x0200 /* Auto-increment address on read */ -#define B43_SHM_AUTOINC_W 0x0100 /* Auto-increment address on write */ -#define B43_SHM_AUTOINC_RW (B43_SHM_AUTOINC_R | \ - B43_SHM_AUTOINC_W) - -/* Misc SHM_SHARED offsets */ -#define B43_SHM_SH_WLCOREREV 0x0016 /* 802.11 core revision */ -#define B43_SHM_SH_PCTLWDPOS 0x0008 -#define B43_SHM_SH_RXPADOFF 0x0034 /* RX Padding data offset (PIO only) */ -#define B43_SHM_SH_FWCAPA 0x0042 /* Firmware capabilities (Opensource firmware only) */ -#define B43_SHM_SH_PHYVER 0x0050 /* PHY version */ -#define B43_SHM_SH_PHYTYPE 0x0052 /* PHY type */ -#define B43_SHM_SH_ANTSWAP 0x005C /* Antenna swap threshold */ -#define B43_SHM_SH_HOSTFLO 0x005E /* Hostflags for ucode options (low) */ -#define B43_SHM_SH_HOSTFMI 0x0060 /* Hostflags for ucode options (middle) */ -#define B43_SHM_SH_HOSTFHI 0x0062 /* Hostflags for ucode options (high) */ -#define B43_SHM_SH_RFATT 0x0064 /* Current radio attenuation value */ -#define B43_SHM_SH_RADAR 0x0066 /* Radar register */ -#define B43_SHM_SH_PHYTXNOI 0x006E /* PHY noise directly after TX (lower 8bit only) */ -#define B43_SHM_SH_RFRXSP1 0x0072 /* RF RX SP Register 1 */ -#define B43_SHM_SH_CHAN 0x00A0 /* Current channel (low 8bit only) */ -#define B43_SHM_SH_CHAN_5GHZ 0x0100 /* Bit set, if 5Ghz channel */ -#define B43_SHM_SH_BCMCFIFOID 0x0108 /* Last posted cookie to the bcast/mcast FIFO */ -/* TSSI information */ -#define B43_SHM_SH_TSSI_CCK 0x0058 /* TSSI for last 4 CCK frames (32bit) */ -#define B43_SHM_SH_TSSI_OFDM_A 0x0068 /* TSSI for last 4 OFDM frames (32bit) */ -#define B43_SHM_SH_TSSI_OFDM_G 0x0070 /* TSSI for last 4 OFDM frames (32bit) */ -#define B43_TSSI_MAX 0x7F /* Max value for one TSSI value */ -/* SHM_SHARED TX FIFO variables */ -#define B43_SHM_SH_SIZE01 0x0098 /* TX FIFO size for FIFO 0 (low) and 1 (high) */ -#define B43_SHM_SH_SIZE23 0x009A /* TX FIFO size for FIFO 2 and 3 */ -#define B43_SHM_SH_SIZE45 0x009C /* TX FIFO size for FIFO 4 and 5 */ -#define B43_SHM_SH_SIZE67 0x009E /* TX FIFO size for FIFO 6 and 7 */ -/* SHM_SHARED background noise */ -#define B43_SHM_SH_JSSI0 0x0088 /* Measure JSSI 0 */ -#define B43_SHM_SH_JSSI1 0x008A /* Measure JSSI 1 */ -#define B43_SHM_SH_JSSIAUX 0x008C /* Measure JSSI AUX */ -/* SHM_SHARED crypto engine */ -#define B43_SHM_SH_DEFAULTIV 0x003C /* Default IV location */ -#define B43_SHM_SH_NRRXTRANS 0x003E /* # of soft RX transmitter addresses (max 8) */ -#define B43_SHM_SH_KTP 0x0056 /* Key table pointer */ -#define B43_SHM_SH_TKIPTSCTTAK 0x0318 -#define B43_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block (v4 firmware) */ -#define B43_SHM_SH_PSM 0x05F4 /* PSM transmitter address match block (rev < 5) */ -/* SHM_SHARED WME variables */ -#define B43_SHM_SH_EDCFSTAT 0x000E /* EDCF status */ -#define B43_SHM_SH_TXFCUR 0x0030 /* TXF current index */ -#define B43_SHM_SH_EDCFQ 0x0240 /* EDCF Q info */ -/* SHM_SHARED powersave mode related */ -#define B43_SHM_SH_SLOTT 0x0010 /* Slot time */ -#define B43_SHM_SH_DTIMPER 0x0012 /* DTIM period */ -#define B43_SHM_SH_NOSLPZNATDTIM 0x004C /* NOSLPZNAT DTIM */ -/* SHM_SHARED beacon/AP variables */ -#define B43_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ -#define B43_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ -#define B43_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ -#define B43_SHM_SH_TIMBPOS 0x001E /* TIM B position in beacon */ -#define B43_SHM_SH_DTIMP 0x0012 /* DTIP period */ -#define B43_SHM_SH_MCASTCOOKIE 0x00A8 /* Last bcast/mcast frame ID */ -#define B43_SHM_SH_SFFBLIM 0x0044 /* Short frame fallback retry limit */ -#define B43_SHM_SH_LFFBLIM 0x0046 /* Long frame fallback retry limit */ -#define B43_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word (see PHY TX control) */ -#define B43_SHM_SH_EXTNPHYCTL 0x00B0 /* Extended bytes for beacon PHY control (N) */ -/* SHM_SHARED ACK/CTS control */ -#define B43_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word (see PHY TX control) */ -/* SHM_SHARED probe response variables */ -#define B43_SHM_SH_PRSSID 0x0160 /* Probe Response SSID */ -#define B43_SHM_SH_PRSSIDLEN 0x0048 /* Probe Response SSID length */ -#define B43_SHM_SH_PRTLEN 0x004A /* Probe Response template length */ -#define B43_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */ -#define B43_SHM_SH_PRPHYCTL 0x0188 /* Probe Response PHY TX control word */ -/* SHM_SHARED rate tables */ -#define B43_SHM_SH_OFDMDIRECT 0x01C0 /* Pointer to OFDM direct map */ -#define B43_SHM_SH_OFDMBASIC 0x01E0 /* Pointer to OFDM basic rate map */ -#define B43_SHM_SH_CCKDIRECT 0x0200 /* Pointer to CCK direct map */ -#define B43_SHM_SH_CCKBASIC 0x0220 /* Pointer to CCK basic rate map */ -/* SHM_SHARED microcode soft registers */ -#define B43_SHM_SH_UCODEREV 0x0000 /* Microcode revision */ -#define B43_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ -#define B43_SHM_SH_UCODEDATE 0x0004 /* Microcode date */ -#define B43_SHM_SH_UCODETIME 0x0006 /* Microcode time */ -#define B43_SHM_SH_UCODESTAT 0x0040 /* Microcode debug status code */ -#define B43_SHM_SH_UCODESTAT_INVALID 0 -#define B43_SHM_SH_UCODESTAT_INIT 1 -#define B43_SHM_SH_UCODESTAT_ACTIVE 2 -#define B43_SHM_SH_UCODESTAT_SUSP 3 /* suspended */ -#define B43_SHM_SH_UCODESTAT_SLEEP 4 /* asleep (PS) */ -#define B43_SHM_SH_MAXBFRAMES 0x0080 /* Maximum number of frames in a burst */ -#define B43_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ -#define B43_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ - -/* SHM_SCRATCH offsets */ -#define B43_SHM_SC_MINCONT 0x0003 /* Minimum contention window */ -#define B43_SHM_SC_MAXCONT 0x0004 /* Maximum contention window */ -#define B43_SHM_SC_CURCONT 0x0005 /* Current contention window */ -#define B43_SHM_SC_SRLIMIT 0x0006 /* Short retry count limit */ -#define B43_SHM_SC_LRLIMIT 0x0007 /* Long retry count limit */ -#define B43_SHM_SC_DTIMC 0x0008 /* Current DTIM count */ -#define B43_SHM_SC_BTL0LEN 0x0015 /* Beacon 0 template length */ -#define B43_SHM_SC_BTL1LEN 0x0016 /* Beacon 1 template length */ -#define B43_SHM_SC_SCFB 0x0017 /* Short frame transmit count threshold for rate fallback */ -#define B43_SHM_SC_LCFB 0x0018 /* Long frame transmit count threshold for rate fallback */ - -/* Hardware Radio Enable masks */ -#define B43_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16) -#define B43_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4) - -/* HostFlags. See b43_hf_read/write() */ -#define B43_HF_ANTDIVHELP 0x000000000001ULL /* ucode antenna div helper */ -#define B43_HF_SYMW 0x000000000002ULL /* G-PHY SYM workaround */ -#define B43_HF_RXPULLW 0x000000000004ULL /* RX pullup workaround */ -#define B43_HF_CCKBOOST 0x000000000008ULL /* 4dB CCK power boost (exclusive with OFDM boost) */ -#define B43_HF_BTCOEX 0x000000000010ULL /* Bluetooth coexistance */ -#define B43_HF_GDCW 0x000000000020ULL /* G-PHY DC canceller filter bw workaround */ -#define B43_HF_OFDMPABOOST 0x000000000040ULL /* Enable PA gain boost for OFDM */ -#define B43_HF_ACPR 0x000000000080ULL /* Disable for Japan, channel 14 */ -#define B43_HF_EDCF 0x000000000100ULL /* on if WME and MAC suspended */ -#define B43_HF_TSSIRPSMW 0x000000000200ULL /* TSSI reset PSM ucode workaround */ -#define B43_HF_20IN40IQW 0x000000000200ULL /* 20 in 40 MHz I/Q workaround (rev >= 13 only) */ -#define B43_HF_DSCRQ 0x000000000400ULL /* Disable slow clock request in ucode */ -#define B43_HF_ACIW 0x000000000800ULL /* ACI workaround: shift bits by 2 on PHY CRS */ -#define B43_HF_2060W 0x000000001000ULL /* 2060 radio workaround */ -#define B43_HF_RADARW 0x000000002000ULL /* Radar workaround */ -#define B43_HF_USEDEFKEYS 0x000000004000ULL /* Enable use of default keys */ -#define B43_HF_AFTERBURNER 0x000000008000ULL /* Afterburner enabled */ -#define B43_HF_BT4PRIOCOEX 0x000000010000ULL /* Bluetooth 4-priority coexistance */ -#define B43_HF_FWKUP 0x000000020000ULL /* Fast wake-up ucode */ -#define B43_HF_VCORECALC 0x000000040000ULL /* Force VCO recalculation when powering up synthpu */ -#define B43_HF_PCISCW 0x000000080000ULL /* PCI slow clock workaround */ -#define B43_HF_4318TSSI 0x000000200000ULL /* 4318 TSSI */ -#define B43_HF_FBCMCFIFO 0x000000400000ULL /* Flush bcast/mcast FIFO immediately */ -#define B43_HF_HWPCTL 0x000000800000ULL /* Enable hardwarre power control */ -#define B43_HF_BTCOEXALT 0x000001000000ULL /* Bluetooth coexistance in alternate pins */ -#define B43_HF_TXBTCHECK 0x000002000000ULL /* Bluetooth check during transmission */ -#define B43_HF_SKCFPUP 0x000004000000ULL /* Skip CFP update */ -#define B43_HF_N40W 0x000008000000ULL /* N PHY 40 MHz workaround (rev >= 13 only) */ -#define B43_HF_ANTSEL 0x000020000000ULL /* Antenna selection (for testing antenna div.) */ -#define B43_HF_BT3COEXT 0x000020000000ULL /* Bluetooth 3-wire coexistence (rev >= 13 only) */ -#define B43_HF_BTCANT 0x000040000000ULL /* Bluetooth coexistence (antenna mode) (rev >= 13 only) */ -#define B43_HF_ANTSELEN 0x000100000000ULL /* Antenna selection enabled (rev >= 13 only) */ -#define B43_HF_ANTSELMODE 0x000200000000ULL /* Antenna selection mode (rev >= 13 only) */ -#define B43_HF_MLADVW 0x001000000000ULL /* N PHY ML ADV workaround (rev >= 13 only) */ -#define B43_HF_PR45960W 0x080000000000ULL /* PR 45960 workaround (rev >= 13 only) */ - -/* Firmware capabilities field in SHM (Opensource firmware only) */ -#define B43_FWCAPA_HWCRYPTO 0x0001 -#define B43_FWCAPA_QOS 0x0002 - -/* MacFilter offsets. */ -#define B43_MACFILTER_SELF 0x0000 -#define B43_MACFILTER_BSSID 0x0003 - -/* PowerControl */ -#define B43_PCTL_IN 0xB0 -#define B43_PCTL_OUT 0xB4 -#define B43_PCTL_OUTENABLE 0xB8 -#define B43_PCTL_XTAL_POWERUP 0x40 -#define B43_PCTL_PLL_POWERDOWN 0x80 - -/* PowerControl Clock Modes */ -#define B43_PCTL_CLK_FAST 0x00 -#define B43_PCTL_CLK_SLOW 0x01 -#define B43_PCTL_CLK_DYNAMIC 0x02 - -#define B43_PCTL_FORCE_SLOW 0x0800 -#define B43_PCTL_FORCE_PLL 0x1000 -#define B43_PCTL_DYN_XTAL 0x2000 - -/* PHYVersioning */ -#define B43_PHYTYPE_A 0x00 -#define B43_PHYTYPE_B 0x01 -#define B43_PHYTYPE_G 0x02 -#define B43_PHYTYPE_N 0x04 -#define B43_PHYTYPE_LP 0x05 - -/* PHYRegisters */ -#define B43_PHY_ILT_A_CTRL 0x0072 -#define B43_PHY_ILT_A_DATA1 0x0073 -#define B43_PHY_ILT_A_DATA2 0x0074 -#define B43_PHY_G_LO_CONTROL 0x0810 -#define B43_PHY_ILT_G_CTRL 0x0472 -#define B43_PHY_ILT_G_DATA1 0x0473 -#define B43_PHY_ILT_G_DATA2 0x0474 -#define B43_PHY_A_PCTL 0x007B -#define B43_PHY_G_PCTL 0x0029 -#define B43_PHY_A_CRS 0x0029 -#define B43_PHY_RADIO_BITFIELD 0x0401 -#define B43_PHY_G_CRS 0x0429 -#define B43_PHY_NRSSILT_CTRL 0x0803 -#define B43_PHY_NRSSILT_DATA 0x0804 - -/* RadioRegisters */ -#define B43_RADIOCTL_ID 0x01 - -/* MAC Control bitfield */ -#define B43_MACCTL_ENABLED 0x00000001 /* MAC Enabled */ -#define B43_MACCTL_PSM_RUN 0x00000002 /* Run Microcode */ -#define B43_MACCTL_PSM_JMP0 0x00000004 /* Microcode jump to 0 */ -#define B43_MACCTL_SHM_ENABLED 0x00000100 /* SHM Enabled */ -#define B43_MACCTL_SHM_UPPER 0x00000200 /* SHM Upper */ -#define B43_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */ -#define B43_MACCTL_PSM_DBG 0x00002000 /* Microcode debugging enabled */ -#define B43_MACCTL_GPOUTSMSK 0x0000C000 /* GPOUT Select Mask */ -#define B43_MACCTL_BE 0x00010000 /* Big Endian mode */ -#define B43_MACCTL_INFRA 0x00020000 /* Infrastructure mode */ -#define B43_MACCTL_AP 0x00040000 /* AccessPoint mode */ -#define B43_MACCTL_RADIOLOCK 0x00080000 /* Radio lock */ -#define B43_MACCTL_BEACPROMISC 0x00100000 /* Beacon Promiscuous */ -#define B43_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep frames with bad PLCP */ -#define B43_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */ -#define B43_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */ -#define B43_MACCTL_PROMISC 0x01000000 /* Promiscuous mode */ -#define B43_MACCTL_HWPS 0x02000000 /* Hardware Power Saving */ -#define B43_MACCTL_AWAKE 0x04000000 /* Device is awake */ -#define B43_MACCTL_CLOSEDNET 0x08000000 /* Closed net (no SSID bcast) */ -#define B43_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */ -#define B43_MACCTL_DISCTXSTAT 0x20000000 /* Discard TX status */ -#define B43_MACCTL_DISCPMQ 0x40000000 /* Discard Power Management Queue */ -#define B43_MACCTL_GMODE 0x80000000 /* G Mode */ - -/* MAC Command bitfield */ -#define B43_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */ -#define B43_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */ -#define B43_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */ -#define B43_MACCMD_CCA 0x00000008 /* Clear channel assessment */ -#define B43_MACCMD_BGNOISE 0x00000010 /* Background noise */ - -/* 802.11 core specific TM State Low (SSB_TMSLOW) flags */ -#define B43_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ -#define B43_TMSLOW_PHYCLKSPEED 0x00C00000 /* PHY clock speed mask (N-PHY only) */ -#define B43_TMSLOW_PHYCLKSPEED_40MHZ 0x00000000 /* 40 MHz PHY */ -#define B43_TMSLOW_PHYCLKSPEED_80MHZ 0x00400000 /* 80 MHz PHY */ -#define B43_TMSLOW_PHYCLKSPEED_160MHZ 0x00800000 /* 160 MHz PHY */ -#define B43_TMSLOW_PLLREFSEL 0x00200000 /* PLL Frequency Reference Select (rev >= 5) */ -#define B43_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Control Enable (rev >= 5) */ -#define B43_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */ -#define B43_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */ - -/* 802.11 core specific TM State High (SSB_TMSHIGH) flags */ -#define B43_TMSHIGH_DUALBAND_PHY 0x00080000 /* Dualband PHY available */ -#define B43_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available (rev >= 5) */ -#define B43_TMSHIGH_HAVE_5GHZ_PHY 0x00020000 /* 5 GHz PHY available (rev >= 5) */ -#define B43_TMSHIGH_HAVE_2GHZ_PHY 0x00010000 /* 2.4 GHz PHY available (rev >= 5) */ - -/* Generic-Interrupt reasons. */ -#define B43_IRQ_MAC_SUSPENDED 0x00000001 -#define B43_IRQ_BEACON 0x00000002 -#define B43_IRQ_TBTT_INDI 0x00000004 -#define B43_IRQ_BEACON_TX_OK 0x00000008 -#define B43_IRQ_BEACON_CANCEL 0x00000010 -#define B43_IRQ_ATIM_END 0x00000020 -#define B43_IRQ_PMQ 0x00000040 -#define B43_IRQ_PIO_WORKAROUND 0x00000100 -#define B43_IRQ_MAC_TXERR 0x00000200 -#define B43_IRQ_PHY_TXERR 0x00000800 -#define B43_IRQ_PMEVENT 0x00001000 -#define B43_IRQ_TIMER0 0x00002000 -#define B43_IRQ_TIMER1 0x00004000 -#define B43_IRQ_DMA 0x00008000 -#define B43_IRQ_TXFIFO_FLUSH_OK 0x00010000 -#define B43_IRQ_CCA_MEASURE_OK 0x00020000 -#define B43_IRQ_NOISESAMPLE_OK 0x00040000 -#define B43_IRQ_UCODE_DEBUG 0x08000000 -#define B43_IRQ_RFKILL 0x10000000 -#define B43_IRQ_TX_OK 0x20000000 -#define B43_IRQ_PHY_G_CHANGED 0x40000000 -#define B43_IRQ_TIMEOUT 0x80000000 - -#define B43_IRQ_ALL 0xFFFFFFFF -#define B43_IRQ_MASKTEMPLATE (B43_IRQ_TBTT_INDI | \ - B43_IRQ_ATIM_END | \ - B43_IRQ_PMQ | \ - B43_IRQ_MAC_TXERR | \ - B43_IRQ_PHY_TXERR | \ - B43_IRQ_DMA | \ - B43_IRQ_TXFIFO_FLUSH_OK | \ - B43_IRQ_NOISESAMPLE_OK | \ - B43_IRQ_UCODE_DEBUG | \ - B43_IRQ_RFKILL | \ - B43_IRQ_TX_OK) - -/* The firmware register to fetch the debug-IRQ reason from. */ -#define B43_DEBUGIRQ_REASON_REG 63 -/* Debug-IRQ reasons. */ -#define B43_DEBUGIRQ_PANIC 0 /* The firmware panic'ed */ -#define B43_DEBUGIRQ_DUMP_SHM 1 /* Dump shared SHM */ -#define B43_DEBUGIRQ_DUMP_REGS 2 /* Dump the microcode registers */ -#define B43_DEBUGIRQ_MARKER 3 /* A "marker" was thrown by the firmware. */ -#define B43_DEBUGIRQ_ACK 0xFFFF /* The host writes that to ACK the IRQ */ - -/* The firmware register that contains the "marker" line. */ -#define B43_MARKER_ID_REG 2 -#define B43_MARKER_LINE_REG 3 - -/* The firmware register to fetch the panic reason from. */ -#define B43_FWPANIC_REASON_REG 3 -/* Firmware panic reason codes */ -#define B43_FWPANIC_DIE 0 /* Firmware died. Don't auto-restart it. */ -#define B43_FWPANIC_RESTART 1 /* Firmware died. Schedule a controller reset. */ - -/* The firmware register that contains the watchdog counter. */ -#define B43_WATCHDOG_REG 1 - -/* Device specific rate values. - * The actual values defined here are (rate_in_mbps * 2). - * Some code depends on this. Don't change it. */ -#define B43_CCK_RATE_1MB 0x02 -#define B43_CCK_RATE_2MB 0x04 -#define B43_CCK_RATE_5MB 0x0B -#define B43_CCK_RATE_11MB 0x16 -#define B43_OFDM_RATE_6MB 0x0C -#define B43_OFDM_RATE_9MB 0x12 -#define B43_OFDM_RATE_12MB 0x18 -#define B43_OFDM_RATE_18MB 0x24 -#define B43_OFDM_RATE_24MB 0x30 -#define B43_OFDM_RATE_36MB 0x48 -#define B43_OFDM_RATE_48MB 0x60 -#define B43_OFDM_RATE_54MB 0x6C -/* Convert a b43 rate value to a rate in 100kbps */ -#define B43_RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) - -#define B43_DEFAULT_SHORT_RETRY_LIMIT 7 -#define B43_DEFAULT_LONG_RETRY_LIMIT 4 - -#define B43_PHY_TX_BADNESS_LIMIT 1000 - -/* Max size of a security key */ -#define B43_SEC_KEYSIZE 16 -/* Max number of group keys */ -#define B43_NR_GROUP_KEYS 4 -/* Max number of pairwise keys */ -#define B43_NR_PAIRWISE_KEYS 50 -/* Security algorithms. */ -enum { - B43_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ - B43_SEC_ALGO_WEP40, - B43_SEC_ALGO_TKIP, - B43_SEC_ALGO_AES, - B43_SEC_ALGO_WEP104, - B43_SEC_ALGO_AES_LEGACY, -}; - -struct b43_dmaring; - -/* The firmware file header */ -#define B43_FW_TYPE_UCODE 'u' -#define B43_FW_TYPE_PCM 'p' -#define B43_FW_TYPE_IV 'i' -struct b43_fw_header { - /* File type */ - u8 type; - /* File format version */ - u8 ver; - u8 __padding[2]; - /* Size of the data. For ucode and PCM this is in bytes. - * For IV this is number-of-ivs. */ - __be32 size; -} __attribute__((__packed__)); - -/* Initial Value file format */ -#define B43_IV_OFFSET_MASK 0x7FFF -#define B43_IV_32BIT 0x8000 -struct b43_iv { - __be16 offset_size; - union { - __be16 d16; - __be32 d32; - } data __attribute__((__packed__)); -} __attribute__((__packed__)); - - -/* Data structures for DMA transmission, per 80211 core. */ -struct b43_dma { - struct b43_dmaring *tx_ring_AC_BK; /* Background */ - struct b43_dmaring *tx_ring_AC_BE; /* Best Effort */ - struct b43_dmaring *tx_ring_AC_VI; /* Video */ - struct b43_dmaring *tx_ring_AC_VO; /* Voice */ - struct b43_dmaring *tx_ring_mcast; /* Multicast */ - - struct b43_dmaring *rx_ring; -}; - -struct b43_pio_txqueue; -struct b43_pio_rxqueue; - -/* Data structures for PIO transmission, per 80211 core. */ -struct b43_pio { - struct b43_pio_txqueue *tx_queue_AC_BK; /* Background */ - struct b43_pio_txqueue *tx_queue_AC_BE; /* Best Effort */ - struct b43_pio_txqueue *tx_queue_AC_VI; /* Video */ - struct b43_pio_txqueue *tx_queue_AC_VO; /* Voice */ - struct b43_pio_txqueue *tx_queue_mcast; /* Multicast */ - - struct b43_pio_rxqueue *rx_queue; -}; - -/* Context information for a noise calculation (Link Quality). */ -struct b43_noise_calculation { - bool calculation_running; - u8 nr_samples; - s8 samples[8][4]; -}; - -struct b43_stats { - u8 link_noise; -}; - -struct b43_key { - /* If keyconf is NULL, this key is disabled. - * keyconf is a cookie. Don't derefenrence it outside of the set_key - * path, because b43 doesn't own it. */ - struct ieee80211_key_conf *keyconf; - u8 algorithm; -}; - -/* SHM offsets to the QOS data structures for the 4 different queues. */ -#define B43_QOS_PARAMS(queue) (B43_SHM_SH_EDCFQ + \ - (B43_NR_QOSPARAMS * sizeof(u16) * (queue))) -#define B43_QOS_BACKGROUND B43_QOS_PARAMS(0) -#define B43_QOS_BESTEFFORT B43_QOS_PARAMS(1) -#define B43_QOS_VIDEO B43_QOS_PARAMS(2) -#define B43_QOS_VOICE B43_QOS_PARAMS(3) - -/* QOS parameter hardware data structure offsets. */ -#define B43_NR_QOSPARAMS 16 -enum { - B43_QOSPARAM_TXOP = 0, - B43_QOSPARAM_CWMIN, - B43_QOSPARAM_CWMAX, - B43_QOSPARAM_CWCUR, - B43_QOSPARAM_AIFS, - B43_QOSPARAM_BSLOTS, - B43_QOSPARAM_REGGAP, - B43_QOSPARAM_STATUS, -}; - -/* QOS parameters for a queue. */ -struct b43_qos_params { - /* The QOS parameters */ - struct ieee80211_tx_queue_params p; -}; - -struct b43_wl; - -/* The type of the firmware file. */ -enum b43_firmware_file_type { - B43_FWTYPE_PROPRIETARY, - B43_FWTYPE_OPENSOURCE, - B43_NR_FWTYPES, -}; - -/* Context data for fetching firmware. */ -struct b43_request_fw_context { - /* The device we are requesting the fw for. */ - struct b43_wldev *dev; - /* The type of firmware to request. */ - enum b43_firmware_file_type req_type; - /* Error messages for each firmware type. */ - char errors[B43_NR_FWTYPES][128]; - /* Temporary buffer for storing the firmware name. */ - char fwname[64]; - /* A fatal error occured while requesting. Firmware reqest - * can not continue, as any other reqest will also fail. */ - int fatal_failure; -}; - -/* In-memory representation of a cached microcode file. */ -struct b43_firmware_file { - const char *filename; - const struct firmware *data; - /* Type of the firmware file name. Note that this does only indicate - * the type by the firmware name. NOT the file contents. - * If you want to check for proprietary vs opensource, use (struct b43_firmware)->opensource - * instead! The (struct b43_firmware)->opensource flag is derived from the actual firmware - * binary code, not just the filename. - */ - enum b43_firmware_file_type type; -}; - -/* Pointers to the firmware data and meta information about it. */ -struct b43_firmware { - /* Microcode */ - struct b43_firmware_file ucode; - /* PCM code */ - struct b43_firmware_file pcm; - /* Initial MMIO values for the firmware */ - struct b43_firmware_file initvals; - /* Initial MMIO values for the firmware, band-specific */ - struct b43_firmware_file initvals_band; - - /* Firmware revision */ - u16 rev; - /* Firmware patchlevel */ - u16 patch; - - /* Set to true, if we are using an opensource firmware. - * Use this to check for proprietary vs opensource. */ - bool opensource; - /* Set to true, if the core needs a PCM firmware, but - * we failed to load one. This is always false for - * core rev > 10, as these don't need PCM firmware. */ - bool pcm_request_failed; -}; - -/* Device (802.11 core) initialization status. */ -enum { - B43_STAT_UNINIT = 0, /* Uninitialized. */ - B43_STAT_INITIALIZED = 1, /* Initialized, but not started, yet. */ - B43_STAT_STARTED = 2, /* Up and running. */ -}; -#define b43_status(wldev) atomic_read(&(wldev)->__init_status) -#define b43_set_status(wldev, stat) do { \ - atomic_set(&(wldev)->__init_status, (stat)); \ - smp_wmb(); \ - } while (0) - -/* Data structure for one wireless device (802.11 core) */ -struct b43_wldev { - struct ssb_device *dev; - struct b43_wl *wl; - - /* The device initialization status. - * Use b43_status() to query. */ - atomic_t __init_status; - - bool bad_frames_preempt; /* Use "Bad Frames Preemption" (default off) */ - bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM) */ - bool radio_hw_enable; /* saved state of radio hardware enabled state */ - bool qos_enabled; /* TRUE, if QoS is used. */ - bool hwcrypto_enabled; /* TRUE, if HW crypto acceleration is enabled. */ - bool use_pio; /* TRUE if next init should use PIO */ - - /* PHY/Radio device. */ - struct b43_phy phy; - - union { - /* DMA engines. */ - struct b43_dma dma; - /* PIO engines. */ - struct b43_pio pio; - }; - /* Use b43_using_pio_transfers() to check whether we are using - * DMA or PIO data transfers. */ - bool __using_pio_transfers; - - /* Various statistics about the physical device. */ - struct b43_stats stats; - - /* Reason code of the last interrupt. */ - u32 irq_reason; - u32 dma_reason[6]; - /* The currently active generic-interrupt mask. */ - u32 irq_mask; - - /* Link Quality calculation context. */ - struct b43_noise_calculation noisecalc; - /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ - int mac_suspended; - - /* Periodic tasks */ - struct delayed_work periodic_work; - unsigned int periodic_state; - - struct work_struct restart_work; - - /* encryption/decryption */ - u16 ktp; /* Key table pointer */ - struct b43_key key[B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS]; - - /* Firmware data */ - struct b43_firmware fw; - - /* Devicelist in struct b43_wl (all 802.11 cores) */ - struct list_head list; - - /* Debugging stuff follows. */ -#ifdef CONFIG_B43_DEBUG - struct b43_dfsentry *dfsentry; - unsigned int irq_count; - unsigned int irq_bit_count[32]; - unsigned int tx_count; - unsigned int rx_count; -#endif -}; - -/* Data structure for the WLAN parts (802.11 cores) of the b43 chip. */ -struct b43_wl { - /* Pointer to the active wireless device on this chip */ - struct b43_wldev *current_dev; - /* Pointer to the ieee80211 hardware data structure */ - struct ieee80211_hw *hw; - - /* Global driver mutex. Every operation must run with this mutex locked. */ - struct mutex mutex; - /* Hard-IRQ spinlock. This lock protects things used in the hard-IRQ - * handler, only. This basically is just the IRQ mask register. */ - spinlock_t hardirq_lock; - - /* The number of queues that were registered with the mac80211 subsystem - * initially. This is a backup copy of hw->queues in case hw->queues has - * to be dynamically lowered at runtime (Firmware does not support QoS). - * hw->queues has to be restored to the original value before unregistering - * from the mac80211 subsystem. */ - u16 mac80211_initially_registered_queues; - - /* We can only have one operating interface (802.11 core) - * at a time. General information about this interface follows. - */ - - struct ieee80211_vif *vif; - /* The MAC address of the operating interface. */ - u8 mac_addr[ETH_ALEN]; - /* Current BSSID */ - u8 bssid[ETH_ALEN]; - /* Interface type. (NL80211_IFTYPE_XXX) */ - int if_type; - /* Is the card operating in AP, STA or IBSS mode? */ - bool operating; - /* filter flags */ - unsigned int filter_flags; - /* Stats about the wireless interface */ - struct ieee80211_low_level_stats ieee_stats; - -#ifdef CONFIG_B43_HWRNG - struct hwrng rng; - bool rng_initialized; - char rng_name[30 + 1]; -#endif /* CONFIG_B43_HWRNG */ - - /* List of all wireless devices on this chip */ - struct list_head devlist; - u8 nr_devs; - - bool radiotap_enabled; - bool radio_enabled; - - /* The beacon we are currently using (AP or IBSS mode). */ - struct sk_buff *current_beacon; - bool beacon0_uploaded; - bool beacon1_uploaded; - bool beacon_templates_virgin; /* Never wrote the templates? */ - struct work_struct beacon_update_trigger; - - /* The current QOS parameters for the 4 queues. */ - struct b43_qos_params qos_params[4]; - - /* Work for adjustment of the transmission power. - * This is scheduled when we determine that the actual TX output - * power doesn't match what we want. */ - struct work_struct txpower_adjust_work; - - /* Packet transmit work */ - struct work_struct tx_work; - /* Queue of packets to be transmitted. */ - struct sk_buff_head tx_queue; - - /* The device LEDs. */ - struct b43_leds leds; - - /* Kmalloc'ed scratch space for PIO TX/RX. Protected by wl->mutex. */ - u8 pio_scratchspace[110] __attribute__((__aligned__(8))); - u8 pio_tailspace[4] __attribute__((__aligned__(8))); -}; - -static inline struct b43_wl *hw_to_b43_wl(struct ieee80211_hw *hw) -{ - return hw->priv; -} - -static inline struct b43_wldev *dev_to_b43_wldev(struct device *dev) -{ - struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); - return ssb_get_drvdata(ssb_dev); -} - -/* Is the device operating in a specified mode (NL80211_IFTYPE_XXX). */ -static inline int b43_is_mode(struct b43_wl *wl, int type) -{ - return (wl->operating && wl->if_type == type); -} - -/** - * b43_current_band - Returns the currently used band. - * Returns one of IEEE80211_BAND_2GHZ and IEEE80211_BAND_5GHZ. - */ -static inline enum ieee80211_band b43_current_band(struct b43_wl *wl) -{ - return wl->hw->conf.channel->band; -} - -static inline u16 b43_read16(struct b43_wldev *dev, u16 offset) -{ - return ssb_read16(dev->dev, offset); -} - -static inline void b43_write16(struct b43_wldev *dev, u16 offset, u16 value) -{ - ssb_write16(dev->dev, offset, value); -} - -static inline u32 b43_read32(struct b43_wldev *dev, u16 offset) -{ - return ssb_read32(dev->dev, offset); -} - -static inline void b43_write32(struct b43_wldev *dev, u16 offset, u32 value) -{ - ssb_write32(dev->dev, offset, value); -} - -static inline bool b43_using_pio_transfers(struct b43_wldev *dev) -{ - return dev->__using_pio_transfers; -} - -#ifdef CONFIG_B43_FORCE_PIO -# define B43_PIO_DEFAULT 1 -#else -# define B43_PIO_DEFAULT 0 -#endif - -/* Message printing */ -void b43info(struct b43_wl *wl, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); -void b43err(struct b43_wl *wl, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); -void b43warn(struct b43_wl *wl, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); -void b43dbg(struct b43_wl *wl, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); - - -/* A WARN_ON variant that vanishes when b43 debugging is disabled. - * This _also_ evaluates the arg with debugging disabled. */ -#if B43_DEBUG -# define B43_WARN_ON(x) WARN_ON(x) -#else -static inline bool __b43_warn_on_dummy(bool x) { return x; } -# define B43_WARN_ON(x) __b43_warn_on_dummy(unlikely(!!(x))) -#endif - -/* Convert an integer to a Q5.2 value */ -#define INT_TO_Q52(i) ((i) << 2) -/* Convert a Q5.2 value to an integer (precision loss!) */ -#define Q52_TO_INT(q52) ((q52) >> 2) -/* Macros for printing a value in Q5.2 format */ -#define Q52_FMT "%u.%u" -#define Q52_ARG(q52) Q52_TO_INT(q52), ((((q52) & 0x3) * 100) / 4) - -#endif /* B43_H_ */ diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c deleted file mode 100644 index 80b19a44a407..000000000000 --- a/drivers/net/wireless/b43/debugfs.c +++ /dev/null @@ -1,831 +0,0 @@ -/* - - Broadcom B43 wireless driver - - debugfs driver debugging code - - Copyright (c) 2005-2007 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "b43.h" -#include "main.h" -#include "debugfs.h" -#include "dma.h" -#include "xmit.h" - - -/* The root directory. */ -static struct dentry *rootdir; - -struct b43_debugfs_fops { - ssize_t (*read)(struct b43_wldev *dev, char *buf, size_t bufsize); - int (*write)(struct b43_wldev *dev, const char *buf, size_t count); - struct file_operations fops; - /* Offset of struct b43_dfs_file in struct b43_dfsentry */ - size_t file_struct_offset; -}; - -static inline -struct b43_dfs_file *fops_to_dfs_file(struct b43_wldev *dev, - const struct b43_debugfs_fops *dfops) -{ - void *p; - - p = dev->dfsentry; - p += dfops->file_struct_offset; - - return p; -} - - -#define fappend(fmt, x...) \ - do { \ - if (bufsize - count) \ - count += snprintf(buf + count, \ - bufsize - count, \ - fmt , ##x); \ - else \ - printk(KERN_ERR "b43: fappend overflow\n"); \ - } while (0) - - -/* The biggest address values for SHM access from the debugfs files. */ -#define B43_MAX_SHM_ROUTING 4 -#define B43_MAX_SHM_ADDR 0xFFFF - -static ssize_t shm16read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - unsigned int routing, addr; - u16 val; - - routing = dev->dfsentry->shm16read_routing_next; - addr = dev->dfsentry->shm16read_addr_next; - if ((routing > B43_MAX_SHM_ROUTING) || - (addr > B43_MAX_SHM_ADDR)) - return -EDESTADDRREQ; - - val = b43_shm_read16(dev, routing, addr); - fappend("0x%04X\n", val); - - return count; -} - -static int shm16read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr; - int res; - - res = sscanf(buf, "0x%X 0x%X", &routing, &addr); - if (res != 2) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - - dev->dfsentry->shm16read_routing_next = routing; - dev->dfsentry->shm16read_addr_next = addr; - - return 0; -} - -static int shm16write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr, mask, set; - u16 val; - int res; - - res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", - &routing, &addr, &mask, &set); - if (res != 4) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - if ((mask > 0xFFFF) || (set > 0xFFFF)) - return -E2BIG; - - if (mask == 0) - val = 0; - else - val = b43_shm_read16(dev, routing, addr); - val &= mask; - val |= set; - b43_shm_write16(dev, routing, addr, val); - - return 0; -} - -static ssize_t shm32read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - unsigned int routing, addr; - u32 val; - - routing = dev->dfsentry->shm32read_routing_next; - addr = dev->dfsentry->shm32read_addr_next; - if ((routing > B43_MAX_SHM_ROUTING) || - (addr > B43_MAX_SHM_ADDR)) - return -EDESTADDRREQ; - - val = b43_shm_read32(dev, routing, addr); - fappend("0x%08X\n", val); - - return count; -} - -static int shm32read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr; - int res; - - res = sscanf(buf, "0x%X 0x%X", &routing, &addr); - if (res != 2) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - - dev->dfsentry->shm32read_routing_next = routing; - dev->dfsentry->shm32read_addr_next = addr; - - return 0; -} - -static int shm32write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int routing, addr, mask, set; - u32 val; - int res; - - res = sscanf(buf, "0x%X 0x%X 0x%X 0x%X", - &routing, &addr, &mask, &set); - if (res != 4) - return -EINVAL; - if (routing > B43_MAX_SHM_ROUTING) - return -EADDRNOTAVAIL; - if (addr > B43_MAX_SHM_ADDR) - return -EADDRNOTAVAIL; - if (routing == B43_SHM_SHARED) { - if ((addr % 2) != 0) - return -EADDRNOTAVAIL; - } - if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) - return -E2BIG; - - if (mask == 0) - val = 0; - else - val = b43_shm_read32(dev, routing, addr); - val &= mask; - val |= set; - b43_shm_write32(dev, routing, addr, val); - - return 0; -} - -/* The biggest MMIO address that we allow access to from the debugfs files. */ -#define B43_MAX_MMIO_ACCESS (0xF00 - 1) - -static ssize_t mmio16read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - unsigned int addr; - u16 val; - - addr = dev->dfsentry->mmio16read_next; - if (addr > B43_MAX_MMIO_ACCESS) - return -EDESTADDRREQ; - - val = b43_read16(dev, addr); - fappend("0x%04X\n", val); - - return count; -} - -static int mmio16read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr; - int res; - - res = sscanf(buf, "0x%X", &addr); - if (res != 1) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((addr % 2) != 0) - return -EINVAL; - - dev->dfsentry->mmio16read_next = addr; - - return 0; -} - -static int mmio16write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr, mask, set; - int res; - u16 val; - - res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); - if (res != 3) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((mask > 0xFFFF) || (set > 0xFFFF)) - return -E2BIG; - if ((addr % 2) != 0) - return -EINVAL; - - if (mask == 0) - val = 0; - else - val = b43_read16(dev, addr); - val &= mask; - val |= set; - b43_write16(dev, addr, val); - - return 0; -} - -static ssize_t mmio32read__read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - unsigned int addr; - u32 val; - - addr = dev->dfsentry->mmio32read_next; - if (addr > B43_MAX_MMIO_ACCESS) - return -EDESTADDRREQ; - - val = b43_read32(dev, addr); - fappend("0x%08X\n", val); - - return count; -} - -static int mmio32read__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr; - int res; - - res = sscanf(buf, "0x%X", &addr); - if (res != 1) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((addr % 4) != 0) - return -EINVAL; - - dev->dfsentry->mmio32read_next = addr; - - return 0; -} - -static int mmio32write__write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - unsigned int addr, mask, set; - int res; - u32 val; - - res = sscanf(buf, "0x%X 0x%X 0x%X", &addr, &mask, &set); - if (res != 3) - return -EINVAL; - if (addr > B43_MAX_MMIO_ACCESS) - return -EADDRNOTAVAIL; - if ((mask > 0xFFFFFFFF) || (set > 0xFFFFFFFF)) - return -E2BIG; - if ((addr % 4) != 0) - return -EINVAL; - - if (mask == 0) - val = 0; - else - val = b43_read32(dev, addr); - val &= mask; - val |= set; - b43_write32(dev, addr, val); - - return 0; -} - -static ssize_t txstat_read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - struct b43_txstatus_log *log = &dev->dfsentry->txstatlog; - ssize_t count = 0; - int i, idx; - struct b43_txstatus *stat; - - if (log->end < 0) { - fappend("Nothing transmitted, yet\n"); - goto out; - } - fappend("b43 TX status reports:\n\n" - "index | cookie | seq | phy_stat | frame_count | " - "rts_count | supp_reason | pm_indicated | " - "intermediate | for_ampdu | acked\n" "---\n"); - i = log->end + 1; - idx = 0; - while (1) { - if (i == B43_NR_LOGGED_TXSTATUS) - i = 0; - stat = &(log->log[i]); - if (stat->cookie) { - fappend("%03d | " - "0x%04X | 0x%04X | 0x%02X | " - "0x%X | 0x%X | " - "%u | %u | " - "%u | %u | %u\n", - idx, - stat->cookie, stat->seq, stat->phy_stat, - stat->frame_count, stat->rts_count, - stat->supp_reason, stat->pm_indicated, - stat->intermediate, stat->for_ampdu, - stat->acked); - idx++; - } - if (i == log->end) - break; - i++; - } -out: - - return count; -} - -static int restart_write_file(struct b43_wldev *dev, - const char *buf, size_t count) -{ - int err = 0; - - if (count > 0 && buf[0] == '1') { - b43_controller_restart(dev, "manually restarted"); - } else - err = -EINVAL; - - return err; -} - -static unsigned long calc_expire_secs(unsigned long now, - unsigned long time, - unsigned long expire) -{ - expire = time + expire; - - if (time_after(now, expire)) - return 0; /* expired */ - if (expire < now) { - /* jiffies wrapped */ - expire -= MAX_JIFFY_OFFSET; - now -= MAX_JIFFY_OFFSET; - } - B43_WARN_ON(expire < now); - - return (expire - now) / HZ; -} - -static ssize_t loctls_read_file(struct b43_wldev *dev, - char *buf, size_t bufsize) -{ - ssize_t count = 0; - struct b43_txpower_lo_control *lo; - int i, err = 0; - struct b43_lo_calib *cal; - unsigned long now = jiffies; - struct b43_phy *phy = &dev->phy; - - if (phy->type != B43_PHYTYPE_G) { - fappend("Device is not a G-PHY\n"); - err = -ENODEV; - goto out; - } - lo = phy->g->lo_control; - fappend("-- Local Oscillator calibration data --\n\n"); - fappend("HW-power-control enabled: %d\n", - dev->phy.hardware_power_control); - fappend("TX Bias: 0x%02X, TX Magn: 0x%02X (expire in %lu sec)\n", - lo->tx_bias, lo->tx_magn, - calc_expire_secs(now, lo->txctl_measured_time, - B43_LO_TXCTL_EXPIRE)); - fappend("Power Vector: 0x%08X%08X (expires in %lu sec)\n", - (unsigned int)((lo->power_vector & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(lo->power_vector & 0x00000000FFFFFFFFULL), - calc_expire_secs(now, lo->pwr_vec_read_time, - B43_LO_PWRVEC_EXPIRE)); - - fappend("\nCalibrated settings:\n"); - list_for_each_entry(cal, &lo->calib_list, list) { - bool active; - - active = (b43_compare_bbatt(&cal->bbatt, &phy->g->bbatt) && - b43_compare_rfatt(&cal->rfatt, &phy->g->rfatt)); - fappend("BB(%d), RF(%d,%d) -> I=%d, Q=%d " - "(expires in %lu sec)%s\n", - cal->bbatt.att, - cal->rfatt.att, cal->rfatt.with_padmix, - cal->ctl.i, cal->ctl.q, - calc_expire_secs(now, cal->calib_time, - B43_LO_CALIB_EXPIRE), - active ? " ACTIVE" : ""); - } - - fappend("\nUsed RF attenuation values: Value(WithPadmix flag)\n"); - for (i = 0; i < lo->rfatt_list.len; i++) { - fappend("%u(%d), ", - lo->rfatt_list.list[i].att, - lo->rfatt_list.list[i].with_padmix); - } - fappend("\n"); - fappend("\nUsed Baseband attenuation values:\n"); - for (i = 0; i < lo->bbatt_list.len; i++) { - fappend("%u, ", - lo->bbatt_list.list[i].att); - } - fappend("\n"); - -out: - return err ? err : count; -} - -#undef fappend - -static int b43_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t b43_debugfs_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct b43_wldev *dev; - struct b43_debugfs_fops *dfops; - struct b43_dfs_file *dfile; - ssize_t uninitialized_var(ret); - char *buf; - const size_t bufsize = 1024 * 16; /* 16 kiB buffer */ - const size_t buforder = get_order(bufsize); - int err = 0; - - if (!count) - return 0; - dev = file->private_data; - if (!dev) - return -ENODEV; - - mutex_lock(&dev->wl->mutex); - if (b43_status(dev) < B43_STAT_INITIALIZED) { - err = -ENODEV; - goto out_unlock; - } - - dfops = container_of(file->f_op, struct b43_debugfs_fops, fops); - if (!dfops->read) { - err = -ENOSYS; - goto out_unlock; - } - dfile = fops_to_dfs_file(dev, dfops); - - if (!dfile->buffer) { - buf = (char *)__get_free_pages(GFP_KERNEL, buforder); - if (!buf) { - err = -ENOMEM; - goto out_unlock; - } - memset(buf, 0, bufsize); - ret = dfops->read(dev, buf, bufsize); - if (ret <= 0) { - free_pages((unsigned long)buf, buforder); - err = ret; - goto out_unlock; - } - dfile->data_len = ret; - dfile->buffer = buf; - } - - ret = simple_read_from_buffer(userbuf, count, ppos, - dfile->buffer, - dfile->data_len); - if (*ppos >= dfile->data_len) { - free_pages((unsigned long)dfile->buffer, buforder); - dfile->buffer = NULL; - dfile->data_len = 0; - } -out_unlock: - mutex_unlock(&dev->wl->mutex); - - return err ? err : ret; -} - -static ssize_t b43_debugfs_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct b43_wldev *dev; - struct b43_debugfs_fops *dfops; - char *buf; - int err = 0; - - if (!count) - return 0; - if (count > PAGE_SIZE) - return -E2BIG; - dev = file->private_data; - if (!dev) - return -ENODEV; - - mutex_lock(&dev->wl->mutex); - if (b43_status(dev) < B43_STAT_INITIALIZED) { - err = -ENODEV; - goto out_unlock; - } - - dfops = container_of(file->f_op, struct b43_debugfs_fops, fops); - if (!dfops->write) { - err = -ENOSYS; - goto out_unlock; - } - - buf = (char *)get_zeroed_page(GFP_KERNEL); - if (!buf) { - err = -ENOMEM; - goto out_unlock; - } - if (copy_from_user(buf, userbuf, count)) { - err = -EFAULT; - goto out_freepage; - } - err = dfops->write(dev, buf, count); - if (err) - goto out_freepage; - -out_freepage: - free_page((unsigned long)buf); -out_unlock: - mutex_unlock(&dev->wl->mutex); - - return err ? err : count; -} - - -#define B43_DEBUGFS_FOPS(name, _read, _write) \ - static struct b43_debugfs_fops fops_##name = { \ - .read = _read, \ - .write = _write, \ - .fops = { \ - .open = b43_debugfs_open, \ - .read = b43_debugfs_read, \ - .write = b43_debugfs_write, \ - }, \ - .file_struct_offset = offsetof(struct b43_dfsentry, \ - file_##name), \ - } - -B43_DEBUGFS_FOPS(shm16read, shm16read__read_file, shm16read__write_file); -B43_DEBUGFS_FOPS(shm16write, NULL, shm16write__write_file); -B43_DEBUGFS_FOPS(shm32read, shm32read__read_file, shm32read__write_file); -B43_DEBUGFS_FOPS(shm32write, NULL, shm32write__write_file); -B43_DEBUGFS_FOPS(mmio16read, mmio16read__read_file, mmio16read__write_file); -B43_DEBUGFS_FOPS(mmio16write, NULL, mmio16write__write_file); -B43_DEBUGFS_FOPS(mmio32read, mmio32read__read_file, mmio32read__write_file); -B43_DEBUGFS_FOPS(mmio32write, NULL, mmio32write__write_file); -B43_DEBUGFS_FOPS(txstat, txstat_read_file, NULL); -B43_DEBUGFS_FOPS(restart, NULL, restart_write_file); -B43_DEBUGFS_FOPS(loctls, loctls_read_file, NULL); - - -bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) -{ - bool enabled; - - enabled = (dev->dfsentry && dev->dfsentry->dyn_debug[feature]); - if (unlikely(enabled)) { - /* Force full debugging messages, if the user enabled - * some dynamic debugging feature. */ - b43_modparam_verbose = B43_VERBOSITY_MAX; - } - - return enabled; -} - -static void b43_remove_dynamic_debug(struct b43_wldev *dev) -{ - struct b43_dfsentry *e = dev->dfsentry; - int i; - - for (i = 0; i < __B43_NR_DYNDBG; i++) - debugfs_remove(e->dyn_debug_dentries[i]); -} - -static void b43_add_dynamic_debug(struct b43_wldev *dev) -{ - struct b43_dfsentry *e = dev->dfsentry; - struct dentry *d; - -#define add_dyn_dbg(name, id, initstate) do { \ - e->dyn_debug[id] = (initstate); \ - d = debugfs_create_bool(name, 0600, e->subdir, \ - &(e->dyn_debug[id])); \ - if (!IS_ERR(d)) \ - e->dyn_debug_dentries[id] = d; \ - } while (0) - - add_dyn_dbg("debug_xmitpower", B43_DBG_XMITPOWER, 0); - add_dyn_dbg("debug_dmaoverflow", B43_DBG_DMAOVERFLOW, 0); - add_dyn_dbg("debug_dmaverbose", B43_DBG_DMAVERBOSE, 0); - add_dyn_dbg("debug_pwork_fast", B43_DBG_PWORK_FAST, 0); - add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); - add_dyn_dbg("debug_lo", B43_DBG_LO, 0); - add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); - add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); - add_dyn_dbg("debug_verbose_stats", B43_DBG_VERBOSESTATS, 0); - -#undef add_dyn_dbg -} - -void b43_debugfs_add_device(struct b43_wldev *dev) -{ - struct b43_dfsentry *e; - struct b43_txstatus_log *log; - char devdir[16]; - - B43_WARN_ON(!dev); - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - b43err(dev->wl, "debugfs: add device OOM\n"); - return; - } - e->dev = dev; - log = &e->txstatlog; - log->log = kcalloc(B43_NR_LOGGED_TXSTATUS, - sizeof(struct b43_txstatus), GFP_KERNEL); - if (!log->log) { - b43err(dev->wl, "debugfs: add device txstatus OOM\n"); - kfree(e); - return; - } - log->end = -1; - - dev->dfsentry = e; - - snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy)); - e->subdir = debugfs_create_dir(devdir, rootdir); - if (!e->subdir || IS_ERR(e->subdir)) { - if (e->subdir == ERR_PTR(-ENODEV)) { - b43dbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not " - "enabled in kernel config\n"); - } else { - b43err(dev->wl, "debugfs: cannot create %s directory\n", - devdir); - } - dev->dfsentry = NULL; - kfree(log->log); - kfree(e); - return; - } - - e->mmio16read_next = 0xFFFF; /* invalid address */ - e->mmio32read_next = 0xFFFF; /* invalid address */ - e->shm16read_routing_next = 0xFFFFFFFF; /* invalid routing */ - e->shm16read_addr_next = 0xFFFFFFFF; /* invalid address */ - e->shm32read_routing_next = 0xFFFFFFFF; /* invalid routing */ - e->shm32read_addr_next = 0xFFFFFFFF; /* invalid address */ - -#define ADD_FILE(name, mode) \ - do { \ - struct dentry *d; \ - d = debugfs_create_file(__stringify(name), \ - mode, e->subdir, dev, \ - &fops_##name.fops); \ - e->file_##name.dentry = NULL; \ - if (!IS_ERR(d)) \ - e->file_##name.dentry = d; \ - } while (0) - - - ADD_FILE(shm16read, 0600); - ADD_FILE(shm16write, 0200); - ADD_FILE(shm32read, 0600); - ADD_FILE(shm32write, 0200); - ADD_FILE(mmio16read, 0600); - ADD_FILE(mmio16write, 0200); - ADD_FILE(mmio32read, 0600); - ADD_FILE(mmio32write, 0200); - ADD_FILE(txstat, 0400); - ADD_FILE(restart, 0200); - ADD_FILE(loctls, 0400); - -#undef ADD_FILE - - b43_add_dynamic_debug(dev); -} - -void b43_debugfs_remove_device(struct b43_wldev *dev) -{ - struct b43_dfsentry *e; - - if (!dev) - return; - e = dev->dfsentry; - if (!e) - return; - b43_remove_dynamic_debug(dev); - - debugfs_remove(e->file_shm16read.dentry); - debugfs_remove(e->file_shm16write.dentry); - debugfs_remove(e->file_shm32read.dentry); - debugfs_remove(e->file_shm32write.dentry); - debugfs_remove(e->file_mmio16read.dentry); - debugfs_remove(e->file_mmio16write.dentry); - debugfs_remove(e->file_mmio32read.dentry); - debugfs_remove(e->file_mmio32write.dentry); - debugfs_remove(e->file_txstat.dentry); - debugfs_remove(e->file_restart.dentry); - debugfs_remove(e->file_loctls.dentry); - - debugfs_remove(e->subdir); - kfree(e->txstatlog.log); - kfree(e); -} - -void b43_debugfs_log_txstat(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ - struct b43_dfsentry *e = dev->dfsentry; - struct b43_txstatus_log *log; - struct b43_txstatus *cur; - int i; - - if (!e) - return; - log = &e->txstatlog; - i = log->end + 1; - if (i == B43_NR_LOGGED_TXSTATUS) - i = 0; - log->end = i; - cur = &(log->log[i]); - memcpy(cur, status, sizeof(*cur)); -} - -void b43_debugfs_init(void) -{ - rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(rootdir)) - rootdir = NULL; -} - -void b43_debugfs_exit(void) -{ - debugfs_remove(rootdir); -} diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h deleted file mode 100644 index 822aad8842f4..000000000000 --- a/drivers/net/wireless/b43/debugfs.h +++ /dev/null @@ -1,111 +0,0 @@ -#ifndef B43_DEBUGFS_H_ -#define B43_DEBUGFS_H_ - -struct b43_wldev; -struct b43_txstatus; - -enum b43_dyndbg { /* Dynamic debugging features */ - B43_DBG_XMITPOWER, - B43_DBG_DMAOVERFLOW, - B43_DBG_DMAVERBOSE, - B43_DBG_PWORK_FAST, - B43_DBG_PWORK_STOP, - B43_DBG_LO, - B43_DBG_FIRMWARE, - B43_DBG_KEYS, - B43_DBG_VERBOSESTATS, - __B43_NR_DYNDBG, -}; - -#ifdef CONFIG_B43_DEBUG - -struct dentry; - -#define B43_NR_LOGGED_TXSTATUS 100 - -struct b43_txstatus_log { - /* This structure is protected by wl->mutex */ - - struct b43_txstatus *log; - int end; -}; - -struct b43_dfs_file { - struct dentry *dentry; - char *buffer; - size_t data_len; -}; - -struct b43_dfsentry { - struct b43_wldev *dev; - struct dentry *subdir; - - struct b43_dfs_file file_shm16read; - struct b43_dfs_file file_shm16write; - struct b43_dfs_file file_shm32read; - struct b43_dfs_file file_shm32write; - struct b43_dfs_file file_mmio16read; - struct b43_dfs_file file_mmio16write; - struct b43_dfs_file file_mmio32read; - struct b43_dfs_file file_mmio32write; - struct b43_dfs_file file_txstat; - struct b43_dfs_file file_txpower_g; - struct b43_dfs_file file_restart; - struct b43_dfs_file file_loctls; - - struct b43_txstatus_log txstatlog; - - /* The cached address for the next mmio16read file read */ - u16 mmio16read_next; - /* The cached address for the next mmio32read file read */ - u16 mmio32read_next; - - /* The cached address for the next shm16read file read */ - u32 shm16read_routing_next; - u32 shm16read_addr_next; - /* The cached address for the next shm32read file read */ - u32 shm32read_routing_next; - u32 shm32read_addr_next; - - /* Enabled/Disabled list for the dynamic debugging features. */ - u32 dyn_debug[__B43_NR_DYNDBG]; - /* Dentries for the dynamic debugging entries. */ - struct dentry *dyn_debug_dentries[__B43_NR_DYNDBG]; -}; - -bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature); - -void b43_debugfs_init(void); -void b43_debugfs_exit(void); -void b43_debugfs_add_device(struct b43_wldev *dev); -void b43_debugfs_remove_device(struct b43_wldev *dev); -void b43_debugfs_log_txstat(struct b43_wldev *dev, - const struct b43_txstatus *status); - -#else /* CONFIG_B43_DEBUG */ - -static inline bool b43_debug(struct b43_wldev *dev, enum b43_dyndbg feature) -{ - return 0; -} - -static inline void b43_debugfs_init(void) -{ -} -static inline void b43_debugfs_exit(void) -{ -} -static inline void b43_debugfs_add_device(struct b43_wldev *dev) -{ -} -static inline void b43_debugfs_remove_device(struct b43_wldev *dev) -{ -} -static inline void b43_debugfs_log_txstat(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ -} - -#endif /* CONFIG_B43_DEBUG */ - -#endif /* B43_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c deleted file mode 100644 index 571d475ca321..000000000000 --- a/drivers/net/wireless/b43/dma.c +++ /dev/null @@ -1,1655 +0,0 @@ -/* - - Broadcom B43 wireless driver - - DMA ringbuffer and descriptor allocation/management - - Copyright (c) 2005, 2006 Michael Buesch - - Some code in this file is derived from the b44.c driver - Copyright (C) 2002 David S. Miller - Copyright (C) Pekka Pietikainen - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "dma.h" -#include "main.h" -#include "debugfs.h" -#include "xmit.h" - -#include -#include -#include -#include -#include -#include - - -/* Required number of TX DMA slots per TX frame. - * This currently is 2, because we put the header and the ieee80211 frame - * into separate slots. */ -#define TX_SLOTS_PER_FRAME 2 - - -/* 32bit DMA ops. */ -static -struct b43_dmadesc_generic *op32_idx2desc(struct b43_dmaring *ring, - int slot, - struct b43_dmadesc_meta **meta) -{ - struct b43_dmadesc32 *desc; - - *meta = &(ring->meta[slot]); - desc = ring->descbase; - desc = &(desc[slot]); - - return (struct b43_dmadesc_generic *)desc; -} - -static void op32_fill_descriptor(struct b43_dmaring *ring, - struct b43_dmadesc_generic *desc, - dma_addr_t dmaaddr, u16 bufsize, - int start, int end, int irq) -{ - struct b43_dmadesc32 *descbase = ring->descbase; - int slot; - u32 ctl; - u32 addr; - u32 addrext; - - slot = (int)(&(desc->dma32) - descbase); - B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - - addr = (u32) (dmaaddr & ~SSB_DMA_TRANSLATION_MASK); - addrext = (u32) (dmaaddr & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ssb_dma_translation(ring->dev->dev); - ctl = bufsize & B43_DMA32_DCTL_BYTECNT; - if (slot == ring->nr_slots - 1) - ctl |= B43_DMA32_DCTL_DTABLEEND; - if (start) - ctl |= B43_DMA32_DCTL_FRAMESTART; - if (end) - ctl |= B43_DMA32_DCTL_FRAMEEND; - if (irq) - ctl |= B43_DMA32_DCTL_IRQ; - ctl |= (addrext << B43_DMA32_DCTL_ADDREXT_SHIFT) - & B43_DMA32_DCTL_ADDREXT_MASK; - - desc->dma32.control = cpu_to_le32(ctl); - desc->dma32.address = cpu_to_le32(addr); -} - -static void op32_poke_tx(struct b43_dmaring *ring, int slot) -{ - b43_dma_write(ring, B43_DMA32_TXINDEX, - (u32) (slot * sizeof(struct b43_dmadesc32))); -} - -static void op32_tx_suspend(struct b43_dmaring *ring) -{ - b43_dma_write(ring, B43_DMA32_TXCTL, b43_dma_read(ring, B43_DMA32_TXCTL) - | B43_DMA32_TXSUSPEND); -} - -static void op32_tx_resume(struct b43_dmaring *ring) -{ - b43_dma_write(ring, B43_DMA32_TXCTL, b43_dma_read(ring, B43_DMA32_TXCTL) - & ~B43_DMA32_TXSUSPEND); -} - -static int op32_get_current_rxslot(struct b43_dmaring *ring) -{ - u32 val; - - val = b43_dma_read(ring, B43_DMA32_RXSTATUS); - val &= B43_DMA32_RXDPTR; - - return (val / sizeof(struct b43_dmadesc32)); -} - -static void op32_set_current_rxslot(struct b43_dmaring *ring, int slot) -{ - b43_dma_write(ring, B43_DMA32_RXINDEX, - (u32) (slot * sizeof(struct b43_dmadesc32))); -} - -static const struct b43_dma_ops dma32_ops = { - .idx2desc = op32_idx2desc, - .fill_descriptor = op32_fill_descriptor, - .poke_tx = op32_poke_tx, - .tx_suspend = op32_tx_suspend, - .tx_resume = op32_tx_resume, - .get_current_rxslot = op32_get_current_rxslot, - .set_current_rxslot = op32_set_current_rxslot, -}; - -/* 64bit DMA ops. */ -static -struct b43_dmadesc_generic *op64_idx2desc(struct b43_dmaring *ring, - int slot, - struct b43_dmadesc_meta **meta) -{ - struct b43_dmadesc64 *desc; - - *meta = &(ring->meta[slot]); - desc = ring->descbase; - desc = &(desc[slot]); - - return (struct b43_dmadesc_generic *)desc; -} - -static void op64_fill_descriptor(struct b43_dmaring *ring, - struct b43_dmadesc_generic *desc, - dma_addr_t dmaaddr, u16 bufsize, - int start, int end, int irq) -{ - struct b43_dmadesc64 *descbase = ring->descbase; - int slot; - u32 ctl0 = 0, ctl1 = 0; - u32 addrlo, addrhi; - u32 addrext; - - slot = (int)(&(desc->dma64) - descbase); - B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - - addrlo = (u32) (dmaaddr & 0xFFFFFFFF); - addrhi = (((u64) dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); - addrext = (((u64) dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= (ssb_dma_translation(ring->dev->dev) << 1); - if (slot == ring->nr_slots - 1) - ctl0 |= B43_DMA64_DCTL0_DTABLEEND; - if (start) - ctl0 |= B43_DMA64_DCTL0_FRAMESTART; - if (end) - ctl0 |= B43_DMA64_DCTL0_FRAMEEND; - if (irq) - ctl0 |= B43_DMA64_DCTL0_IRQ; - ctl1 |= bufsize & B43_DMA64_DCTL1_BYTECNT; - ctl1 |= (addrext << B43_DMA64_DCTL1_ADDREXT_SHIFT) - & B43_DMA64_DCTL1_ADDREXT_MASK; - - desc->dma64.control0 = cpu_to_le32(ctl0); - desc->dma64.control1 = cpu_to_le32(ctl1); - desc->dma64.address_low = cpu_to_le32(addrlo); - desc->dma64.address_high = cpu_to_le32(addrhi); -} - -static void op64_poke_tx(struct b43_dmaring *ring, int slot) -{ - b43_dma_write(ring, B43_DMA64_TXINDEX, - (u32) (slot * sizeof(struct b43_dmadesc64))); -} - -static void op64_tx_suspend(struct b43_dmaring *ring) -{ - b43_dma_write(ring, B43_DMA64_TXCTL, b43_dma_read(ring, B43_DMA64_TXCTL) - | B43_DMA64_TXSUSPEND); -} - -static void op64_tx_resume(struct b43_dmaring *ring) -{ - b43_dma_write(ring, B43_DMA64_TXCTL, b43_dma_read(ring, B43_DMA64_TXCTL) - & ~B43_DMA64_TXSUSPEND); -} - -static int op64_get_current_rxslot(struct b43_dmaring *ring) -{ - u32 val; - - val = b43_dma_read(ring, B43_DMA64_RXSTATUS); - val &= B43_DMA64_RXSTATDPTR; - - return (val / sizeof(struct b43_dmadesc64)); -} - -static void op64_set_current_rxslot(struct b43_dmaring *ring, int slot) -{ - b43_dma_write(ring, B43_DMA64_RXINDEX, - (u32) (slot * sizeof(struct b43_dmadesc64))); -} - -static const struct b43_dma_ops dma64_ops = { - .idx2desc = op64_idx2desc, - .fill_descriptor = op64_fill_descriptor, - .poke_tx = op64_poke_tx, - .tx_suspend = op64_tx_suspend, - .tx_resume = op64_tx_resume, - .get_current_rxslot = op64_get_current_rxslot, - .set_current_rxslot = op64_set_current_rxslot, -}; - -static inline int free_slots(struct b43_dmaring *ring) -{ - return (ring->nr_slots - ring->used_slots); -} - -static inline int next_slot(struct b43_dmaring *ring, int slot) -{ - B43_WARN_ON(!(slot >= -1 && slot <= ring->nr_slots - 1)); - if (slot == ring->nr_slots - 1) - return 0; - return slot + 1; -} - -static inline int prev_slot(struct b43_dmaring *ring, int slot) -{ - B43_WARN_ON(!(slot >= 0 && slot <= ring->nr_slots - 1)); - if (slot == 0) - return ring->nr_slots - 1; - return slot - 1; -} - -#ifdef CONFIG_B43_DEBUG -static void update_max_used_slots(struct b43_dmaring *ring, - int current_used_slots) -{ - if (current_used_slots <= ring->max_used_slots) - return; - ring->max_used_slots = current_used_slots; - if (b43_debug(ring->dev, B43_DBG_DMAVERBOSE)) { - b43dbg(ring->dev->wl, - "max_used_slots increased to %d on %s ring %d\n", - ring->max_used_slots, - ring->tx ? "TX" : "RX", ring->index); - } -} -#else -static inline - void update_max_used_slots(struct b43_dmaring *ring, int current_used_slots) -{ -} -#endif /* DEBUG */ - -/* Request a slot for usage. */ -static inline int request_slot(struct b43_dmaring *ring) -{ - int slot; - - B43_WARN_ON(!ring->tx); - B43_WARN_ON(ring->stopped); - B43_WARN_ON(free_slots(ring) == 0); - - slot = next_slot(ring, ring->current_slot); - ring->current_slot = slot; - ring->used_slots++; - - update_max_used_slots(ring, ring->used_slots); - - return slot; -} - -static u16 b43_dmacontroller_base(enum b43_dmatype type, int controller_idx) -{ - static const u16 map64[] = { - B43_MMIO_DMA64_BASE0, - B43_MMIO_DMA64_BASE1, - B43_MMIO_DMA64_BASE2, - B43_MMIO_DMA64_BASE3, - B43_MMIO_DMA64_BASE4, - B43_MMIO_DMA64_BASE5, - }; - static const u16 map32[] = { - B43_MMIO_DMA32_BASE0, - B43_MMIO_DMA32_BASE1, - B43_MMIO_DMA32_BASE2, - B43_MMIO_DMA32_BASE3, - B43_MMIO_DMA32_BASE4, - B43_MMIO_DMA32_BASE5, - }; - - if (type == B43_DMA_64BIT) { - B43_WARN_ON(!(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map64))); - return map64[controller_idx]; - } - B43_WARN_ON(!(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map32))); - return map32[controller_idx]; -} - -static inline - dma_addr_t map_descbuffer(struct b43_dmaring *ring, - unsigned char *buf, size_t len, int tx) -{ - dma_addr_t dmaaddr; - - if (tx) { - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, DMA_TO_DEVICE); - } else { - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, DMA_FROM_DEVICE); - } - - return dmaaddr; -} - -static inline - void unmap_descbuffer(struct b43_dmaring *ring, - dma_addr_t addr, size_t len, int tx) -{ - if (tx) { - ssb_dma_unmap_single(ring->dev->dev, - addr, len, DMA_TO_DEVICE); - } else { - ssb_dma_unmap_single(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); - } -} - -static inline - void sync_descbuffer_for_cpu(struct b43_dmaring *ring, - dma_addr_t addr, size_t len) -{ - B43_WARN_ON(ring->tx); - ssb_dma_sync_single_for_cpu(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); -} - -static inline - void sync_descbuffer_for_device(struct b43_dmaring *ring, - dma_addr_t addr, size_t len) -{ - B43_WARN_ON(ring->tx); - ssb_dma_sync_single_for_device(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); -} - -static inline - void free_descriptor_buffer(struct b43_dmaring *ring, - struct b43_dmadesc_meta *meta) -{ - if (meta->skb) { - dev_kfree_skb_any(meta->skb); - meta->skb = NULL; - } -} - -static int alloc_ringmemory(struct b43_dmaring *ring) -{ - gfp_t flags = GFP_KERNEL; - - /* The specs call for 4K buffers for 30- and 32-bit DMA with 4K - * alignment and 8K buffers for 64-bit DMA with 8K alignment. Testing - * has shown that 4K is sufficient for the latter as long as the buffer - * does not cross an 8K boundary. - * - * For unknown reasons - possibly a hardware error - the BCM4311 rev - * 02, which uses 64-bit DMA, needs the ring buffer in very low memory, - * which accounts for the GFP_DMA flag below. - * - * The flags here must match the flags in free_ringmemory below! - */ - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; - ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, - B43_DMA_RINGMEMSIZE, - &(ring->dmabase), flags); - if (!ring->descbase) { - b43err(ring->dev->wl, "DMA ringmemory allocation failed\n"); - return -ENOMEM; - } - memset(ring->descbase, 0, B43_DMA_RINGMEMSIZE); - - return 0; -} - -static void free_ringmemory(struct b43_dmaring *ring) -{ - gfp_t flags = GFP_KERNEL; - - if (ring->type == B43_DMA_64BIT) - flags |= GFP_DMA; - - ssb_dma_free_consistent(ring->dev->dev, B43_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase, flags); -} - -/* Reset the RX DMA channel */ -static int b43_dmacontroller_rx_reset(struct b43_wldev *dev, u16 mmio_base, - enum b43_dmatype type) -{ - int i; - u32 value; - u16 offset; - - might_sleep(); - - offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXCTL : B43_DMA32_RXCTL; - b43_write32(dev, mmio_base + offset, 0); - for (i = 0; i < 10; i++) { - offset = (type == B43_DMA_64BIT) ? B43_DMA64_RXSTATUS : - B43_DMA32_RXSTATUS; - value = b43_read32(dev, mmio_base + offset); - if (type == B43_DMA_64BIT) { - value &= B43_DMA64_RXSTAT; - if (value == B43_DMA64_RXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= B43_DMA32_RXSTATE; - if (value == B43_DMA32_RXSTAT_DISABLED) { - i = -1; - break; - } - } - msleep(1); - } - if (i != -1) { - b43err(dev->wl, "DMA RX reset timed out\n"); - return -ENODEV; - } - - return 0; -} - -/* Reset the TX DMA channel */ -static int b43_dmacontroller_tx_reset(struct b43_wldev *dev, u16 mmio_base, - enum b43_dmatype type) -{ - int i; - u32 value; - u16 offset; - - might_sleep(); - - for (i = 0; i < 10; i++) { - offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS : - B43_DMA32_TXSTATUS; - value = b43_read32(dev, mmio_base + offset); - if (type == B43_DMA_64BIT) { - value &= B43_DMA64_TXSTAT; - if (value == B43_DMA64_TXSTAT_DISABLED || - value == B43_DMA64_TXSTAT_IDLEWAIT || - value == B43_DMA64_TXSTAT_STOPPED) - break; - } else { - value &= B43_DMA32_TXSTATE; - if (value == B43_DMA32_TXSTAT_DISABLED || - value == B43_DMA32_TXSTAT_IDLEWAIT || - value == B43_DMA32_TXSTAT_STOPPED) - break; - } - msleep(1); - } - offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXCTL : B43_DMA32_TXCTL; - b43_write32(dev, mmio_base + offset, 0); - for (i = 0; i < 10; i++) { - offset = (type == B43_DMA_64BIT) ? B43_DMA64_TXSTATUS : - B43_DMA32_TXSTATUS; - value = b43_read32(dev, mmio_base + offset); - if (type == B43_DMA_64BIT) { - value &= B43_DMA64_TXSTAT; - if (value == B43_DMA64_TXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= B43_DMA32_TXSTATE; - if (value == B43_DMA32_TXSTAT_DISABLED) { - i = -1; - break; - } - } - msleep(1); - } - if (i != -1) { - b43err(dev->wl, "DMA TX reset timed out\n"); - return -ENODEV; - } - /* ensure the reset is completed. */ - msleep(1); - - return 0; -} - -/* Check if a DMA mapping address is invalid. */ -static bool b43_dma_mapping_error(struct b43_dmaring *ring, - dma_addr_t addr, - size_t buffersize, bool dma_to_device) -{ - if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) - return 1; - - switch (ring->type) { - case B43_DMA_30BIT: - if ((u64)addr + buffersize > (1ULL << 30)) - goto address_error; - break; - case B43_DMA_32BIT: - if ((u64)addr + buffersize > (1ULL << 32)) - goto address_error; - break; - case B43_DMA_64BIT: - /* Currently we can't have addresses beyond - * 64bit in the kernel. */ - break; - } - - /* The address is OK. */ - return 0; - -address_error: - /* We can't support this address. Unmap it again. */ - unmap_descbuffer(ring, addr, buffersize, dma_to_device); - - return 1; -} - -static bool b43_rx_buffer_is_poisoned(struct b43_dmaring *ring, struct sk_buff *skb) -{ - unsigned char *f = skb->data + ring->frameoffset; - - return ((f[0] & f[1] & f[2] & f[3] & f[4] & f[5] & f[6] & f[7]) == 0xFF); -} - -static void b43_poison_rx_buffer(struct b43_dmaring *ring, struct sk_buff *skb) -{ - struct b43_rxhdr_fw4 *rxhdr; - unsigned char *frame; - - /* This poisons the RX buffer to detect DMA failures. */ - - rxhdr = (struct b43_rxhdr_fw4 *)(skb->data); - rxhdr->frame_len = 0; - - B43_WARN_ON(ring->rx_buffersize < ring->frameoffset + sizeof(struct b43_plcp_hdr6) + 2); - frame = skb->data + ring->frameoffset; - memset(frame, 0xFF, sizeof(struct b43_plcp_hdr6) + 2 /* padding */); -} - -static int setup_rx_descbuffer(struct b43_dmaring *ring, - struct b43_dmadesc_generic *desc, - struct b43_dmadesc_meta *meta, gfp_t gfp_flags) -{ - dma_addr_t dmaaddr; - struct sk_buff *skb; - - B43_WARN_ON(ring->tx); - - skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); - if (unlikely(!skb)) - return -ENOMEM; - b43_poison_rx_buffer(ring, skb); - dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); - if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { - /* ugh. try to realloc in zone_dma */ - gfp_flags |= GFP_DMA; - - dev_kfree_skb_any(skb); - - skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); - if (unlikely(!skb)) - return -ENOMEM; - b43_poison_rx_buffer(ring, skb); - dmaaddr = map_descbuffer(ring, skb->data, - ring->rx_buffersize, 0); - if (b43_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { - b43err(ring->dev->wl, "RX DMA buffer allocation failed\n"); - dev_kfree_skb_any(skb); - return -EIO; - } - } - - meta->skb = skb; - meta->dmaaddr = dmaaddr; - ring->ops->fill_descriptor(ring, desc, dmaaddr, - ring->rx_buffersize, 0, 0, 0); - - return 0; -} - -/* Allocate the initial descbuffers. - * This is used for an RX ring only. - */ -static int alloc_initial_descbuffers(struct b43_dmaring *ring) -{ - int i, err = -ENOMEM; - struct b43_dmadesc_generic *desc; - struct b43_dmadesc_meta *meta; - - for (i = 0; i < ring->nr_slots; i++) { - desc = ring->ops->idx2desc(ring, i, &meta); - - err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); - if (err) { - b43err(ring->dev->wl, - "Failed to allocate initial descbuffers\n"); - goto err_unwind; - } - } - mb(); - ring->used_slots = ring->nr_slots; - err = 0; - out: - return err; - - err_unwind: - for (i--; i >= 0; i--) { - desc = ring->ops->idx2desc(ring, i, &meta); - - unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); - dev_kfree_skb(meta->skb); - } - goto out; -} - -/* Do initial setup of the DMA controller. - * Reset the controller, write the ring busaddress - * and switch the "enable" bit on. - */ -static int dmacontroller_setup(struct b43_dmaring *ring) -{ - int err = 0; - u32 value; - u32 addrext; - u32 trans = ssb_dma_translation(ring->dev->dev); - - if (ring->tx) { - if (ring->type == B43_DMA_64BIT) { - u64 ringbase = (u64) (ring->dmabase); - - addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = B43_DMA64_TXENABLE; - value |= (addrext << B43_DMA64_TXADDREXT_SHIFT) - & B43_DMA64_TXADDREXT_MASK; - b43_dma_write(ring, B43_DMA64_TXCTL, value); - b43_dma_write(ring, B43_DMA64_TXRINGLO, - (ringbase & 0xFFFFFFFF)); - b43_dma_write(ring, B43_DMA64_TXRINGHI, - ((ringbase >> 32) & - ~SSB_DMA_TRANSLATION_MASK) - | (trans << 1)); - } else { - u32 ringbase = (u32) (ring->dmabase); - - addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = B43_DMA32_TXENABLE; - value |= (addrext << B43_DMA32_TXADDREXT_SHIFT) - & B43_DMA32_TXADDREXT_MASK; - b43_dma_write(ring, B43_DMA32_TXCTL, value); - b43_dma_write(ring, B43_DMA32_TXRING, - (ringbase & ~SSB_DMA_TRANSLATION_MASK) - | trans); - } - } else { - err = alloc_initial_descbuffers(ring); - if (err) - goto out; - if (ring->type == B43_DMA_64BIT) { - u64 ringbase = (u64) (ring->dmabase); - - addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = (ring->frameoffset << B43_DMA64_RXFROFF_SHIFT); - value |= B43_DMA64_RXENABLE; - value |= (addrext << B43_DMA64_RXADDREXT_SHIFT) - & B43_DMA64_RXADDREXT_MASK; - b43_dma_write(ring, B43_DMA64_RXCTL, value); - b43_dma_write(ring, B43_DMA64_RXRINGLO, - (ringbase & 0xFFFFFFFF)); - b43_dma_write(ring, B43_DMA64_RXRINGHI, - ((ringbase >> 32) & - ~SSB_DMA_TRANSLATION_MASK) - | (trans << 1)); - b43_dma_write(ring, B43_DMA64_RXINDEX, ring->nr_slots * - sizeof(struct b43_dmadesc64)); - } else { - u32 ringbase = (u32) (ring->dmabase); - - addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = (ring->frameoffset << B43_DMA32_RXFROFF_SHIFT); - value |= B43_DMA32_RXENABLE; - value |= (addrext << B43_DMA32_RXADDREXT_SHIFT) - & B43_DMA32_RXADDREXT_MASK; - b43_dma_write(ring, B43_DMA32_RXCTL, value); - b43_dma_write(ring, B43_DMA32_RXRING, - (ringbase & ~SSB_DMA_TRANSLATION_MASK) - | trans); - b43_dma_write(ring, B43_DMA32_RXINDEX, ring->nr_slots * - sizeof(struct b43_dmadesc32)); - } - } - -out: - return err; -} - -/* Shutdown the DMA controller. */ -static void dmacontroller_cleanup(struct b43_dmaring *ring) -{ - if (ring->tx) { - b43_dmacontroller_tx_reset(ring->dev, ring->mmio_base, - ring->type); - if (ring->type == B43_DMA_64BIT) { - b43_dma_write(ring, B43_DMA64_TXRINGLO, 0); - b43_dma_write(ring, B43_DMA64_TXRINGHI, 0); - } else - b43_dma_write(ring, B43_DMA32_TXRING, 0); - } else { - b43_dmacontroller_rx_reset(ring->dev, ring->mmio_base, - ring->type); - if (ring->type == B43_DMA_64BIT) { - b43_dma_write(ring, B43_DMA64_RXRINGLO, 0); - b43_dma_write(ring, B43_DMA64_RXRINGHI, 0); - } else - b43_dma_write(ring, B43_DMA32_RXRING, 0); - } -} - -static void free_all_descbuffers(struct b43_dmaring *ring) -{ - struct b43_dmadesc_generic *desc; - struct b43_dmadesc_meta *meta; - int i; - - if (!ring->used_slots) - return; - for (i = 0; i < ring->nr_slots; i++) { - desc = ring->ops->idx2desc(ring, i, &meta); - - if (!meta->skb) { - B43_WARN_ON(!ring->tx); - continue; - } - if (ring->tx) { - unmap_descbuffer(ring, meta->dmaaddr, - meta->skb->len, 1); - } else { - unmap_descbuffer(ring, meta->dmaaddr, - ring->rx_buffersize, 0); - } - free_descriptor_buffer(ring, meta); - } -} - -static u64 supported_dma_mask(struct b43_wldev *dev) -{ - u32 tmp; - u16 mmio_base; - - tmp = b43_read32(dev, SSB_TMSHIGH); - if (tmp & SSB_TMSHIGH_DMA64) - return DMA_BIT_MASK(64); - mmio_base = b43_dmacontroller_base(0, 0); - b43_write32(dev, mmio_base + B43_DMA32_TXCTL, B43_DMA32_TXADDREXT_MASK); - tmp = b43_read32(dev, mmio_base + B43_DMA32_TXCTL); - if (tmp & B43_DMA32_TXADDREXT_MASK) - return DMA_BIT_MASK(32); - - return DMA_BIT_MASK(30); -} - -static enum b43_dmatype dma_mask_to_engine_type(u64 dmamask) -{ - if (dmamask == DMA_BIT_MASK(30)) - return B43_DMA_30BIT; - if (dmamask == DMA_BIT_MASK(32)) - return B43_DMA_32BIT; - if (dmamask == DMA_BIT_MASK(64)) - return B43_DMA_64BIT; - B43_WARN_ON(1); - return B43_DMA_30BIT; -} - -/* Main initialization function. */ -static -struct b43_dmaring *b43_setup_dmaring(struct b43_wldev *dev, - int controller_index, - int for_tx, - enum b43_dmatype type) -{ - struct b43_dmaring *ring; - int err; - dma_addr_t dma_test; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - goto out; - - ring->nr_slots = B43_RXRING_SLOTS; - if (for_tx) - ring->nr_slots = B43_TXRING_SLOTS; - - ring->meta = kcalloc(ring->nr_slots, sizeof(struct b43_dmadesc_meta), - GFP_KERNEL); - if (!ring->meta) - goto err_kfree_ring; - - ring->type = type; - ring->dev = dev; - ring->mmio_base = b43_dmacontroller_base(type, controller_index); - ring->index = controller_index; - if (type == B43_DMA_64BIT) - ring->ops = &dma64_ops; - else - ring->ops = &dma32_ops; - if (for_tx) { - ring->tx = 1; - ring->current_slot = -1; - } else { - if (ring->index == 0) { - ring->rx_buffersize = B43_DMA0_RX_BUFFERSIZE; - ring->frameoffset = B43_DMA0_RX_FRAMEOFFSET; - } else - B43_WARN_ON(1); - } -#ifdef CONFIG_B43_DEBUG - ring->last_injected_overflow = jiffies; -#endif - - if (for_tx) { - /* Assumption: B43_TXRING_SLOTS can be divided by TX_SLOTS_PER_FRAME */ - BUILD_BUG_ON(B43_TXRING_SLOTS % TX_SLOTS_PER_FRAME != 0); - - ring->txhdr_cache = kcalloc(ring->nr_slots / TX_SLOTS_PER_FRAME, - b43_txhdr_size(dev), - GFP_KERNEL); - if (!ring->txhdr_cache) - goto err_kfree_meta; - - /* test for ability to dma to txhdr_cache */ - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); - - if (b43_dma_mapping_error(ring, dma_test, - b43_txhdr_size(dev), 1)) { - /* ugh realloc */ - kfree(ring->txhdr_cache); - ring->txhdr_cache = kcalloc(ring->nr_slots / TX_SLOTS_PER_FRAME, - b43_txhdr_size(dev), - GFP_KERNEL | GFP_DMA); - if (!ring->txhdr_cache) - goto err_kfree_meta; - - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - b43_txhdr_size(dev), - DMA_TO_DEVICE); - - if (b43_dma_mapping_error(ring, dma_test, - b43_txhdr_size(dev), 1)) { - - b43err(dev->wl, - "TXHDR DMA allocation failed\n"); - goto err_kfree_txhdr_cache; - } - } - - ssb_dma_unmap_single(dev->dev, - dma_test, b43_txhdr_size(dev), - DMA_TO_DEVICE); - } - - err = alloc_ringmemory(ring); - if (err) - goto err_kfree_txhdr_cache; - err = dmacontroller_setup(ring); - if (err) - goto err_free_ringmemory; - - out: - return ring; - - err_free_ringmemory: - free_ringmemory(ring); - err_kfree_txhdr_cache: - kfree(ring->txhdr_cache); - err_kfree_meta: - kfree(ring->meta); - err_kfree_ring: - kfree(ring); - ring = NULL; - goto out; -} - -#define divide(a, b) ({ \ - typeof(a) __a = a; \ - do_div(__a, b); \ - __a; \ - }) - -#define modulo(a, b) ({ \ - typeof(a) __a = a; \ - do_div(__a, b); \ - }) - -/* Main cleanup function. */ -static void b43_destroy_dmaring(struct b43_dmaring *ring, - const char *ringname) -{ - if (!ring) - return; - -#ifdef CONFIG_B43_DEBUG - { - /* Print some statistics. */ - u64 failed_packets = ring->nr_failed_tx_packets; - u64 succeed_packets = ring->nr_succeed_tx_packets; - u64 nr_packets = failed_packets + succeed_packets; - u64 permille_failed = 0, average_tries = 0; - - if (nr_packets) - permille_failed = divide(failed_packets * 1000, nr_packets); - if (nr_packets) - average_tries = divide(ring->nr_total_packet_tries * 100, nr_packets); - - b43dbg(ring->dev->wl, "DMA-%u %s: " - "Used slots %d/%d, Failed frames %llu/%llu = %llu.%01llu%%, " - "Average tries %llu.%02llu\n", - (unsigned int)(ring->type), ringname, - ring->max_used_slots, - ring->nr_slots, - (unsigned long long)failed_packets, - (unsigned long long)nr_packets, - (unsigned long long)divide(permille_failed, 10), - (unsigned long long)modulo(permille_failed, 10), - (unsigned long long)divide(average_tries, 100), - (unsigned long long)modulo(average_tries, 100)); - } -#endif /* DEBUG */ - - /* Device IRQs are disabled prior entering this function, - * so no need to take care of concurrency with rx handler stuff. - */ - dmacontroller_cleanup(ring); - free_all_descbuffers(ring); - free_ringmemory(ring); - - kfree(ring->txhdr_cache); - kfree(ring->meta); - kfree(ring); -} - -#define destroy_ring(dma, ring) do { \ - b43_destroy_dmaring((dma)->ring, __stringify(ring)); \ - (dma)->ring = NULL; \ - } while (0) - -void b43_dma_free(struct b43_wldev *dev) -{ - struct b43_dma *dma; - - if (b43_using_pio_transfers(dev)) - return; - dma = &dev->dma; - - destroy_ring(dma, rx_ring); - destroy_ring(dma, tx_ring_AC_BK); - destroy_ring(dma, tx_ring_AC_BE); - destroy_ring(dma, tx_ring_AC_VI); - destroy_ring(dma, tx_ring_AC_VO); - destroy_ring(dma, tx_ring_mcast); -} - -static int b43_dma_set_mask(struct b43_wldev *dev, u64 mask) -{ - u64 orig_mask = mask; - bool fallback = 0; - int err; - - /* Try to set the DMA mask. If it fails, try falling back to a - * lower mask, as we can always also support a lower one. */ - while (1) { - err = ssb_dma_set_mask(dev->dev, mask); - if (!err) - break; - if (mask == DMA_BIT_MASK(64)) { - mask = DMA_BIT_MASK(32); - fallback = 1; - continue; - } - if (mask == DMA_BIT_MASK(32)) { - mask = DMA_BIT_MASK(30); - fallback = 1; - continue; - } - b43err(dev->wl, "The machine/kernel does not support " - "the required %u-bit DMA mask\n", - (unsigned int)dma_mask_to_engine_type(orig_mask)); - return -EOPNOTSUPP; - } - if (fallback) { - b43info(dev->wl, "DMA mask fallback from %u-bit to %u-bit\n", - (unsigned int)dma_mask_to_engine_type(orig_mask), - (unsigned int)dma_mask_to_engine_type(mask)); - } - - return 0; -} - -int b43_dma_init(struct b43_wldev *dev) -{ - struct b43_dma *dma = &dev->dma; - int err; - u64 dmamask; - enum b43_dmatype type; - - dmamask = supported_dma_mask(dev); - type = dma_mask_to_engine_type(dmamask); - err = b43_dma_set_mask(dev, dmamask); - if (err) - return err; - - err = -ENOMEM; - /* setup TX DMA channels. */ - dma->tx_ring_AC_BK = b43_setup_dmaring(dev, 0, 1, type); - if (!dma->tx_ring_AC_BK) - goto out; - - dma->tx_ring_AC_BE = b43_setup_dmaring(dev, 1, 1, type); - if (!dma->tx_ring_AC_BE) - goto err_destroy_bk; - - dma->tx_ring_AC_VI = b43_setup_dmaring(dev, 2, 1, type); - if (!dma->tx_ring_AC_VI) - goto err_destroy_be; - - dma->tx_ring_AC_VO = b43_setup_dmaring(dev, 3, 1, type); - if (!dma->tx_ring_AC_VO) - goto err_destroy_vi; - - dma->tx_ring_mcast = b43_setup_dmaring(dev, 4, 1, type); - if (!dma->tx_ring_mcast) - goto err_destroy_vo; - - /* setup RX DMA channel. */ - dma->rx_ring = b43_setup_dmaring(dev, 0, 0, type); - if (!dma->rx_ring) - goto err_destroy_mcast; - - /* No support for the TX status DMA ring. */ - B43_WARN_ON(dev->dev->id.revision < 5); - - b43dbg(dev->wl, "%u-bit DMA initialized\n", - (unsigned int)type); - err = 0; -out: - return err; - -err_destroy_mcast: - destroy_ring(dma, tx_ring_mcast); -err_destroy_vo: - destroy_ring(dma, tx_ring_AC_VO); -err_destroy_vi: - destroy_ring(dma, tx_ring_AC_VI); -err_destroy_be: - destroy_ring(dma, tx_ring_AC_BE); -err_destroy_bk: - destroy_ring(dma, tx_ring_AC_BK); - return err; -} - -/* Generate a cookie for the TX header. */ -static u16 generate_cookie(struct b43_dmaring *ring, int slot) -{ - u16 cookie; - - /* Use the upper 4 bits of the cookie as - * DMA controller ID and store the slot number - * in the lower 12 bits. - * Note that the cookie must never be 0, as this - * is a special value used in RX path. - * It can also not be 0xFFFF because that is special - * for multicast frames. - */ - cookie = (((u16)ring->index + 1) << 12); - B43_WARN_ON(slot & ~0x0FFF); - cookie |= (u16)slot; - - return cookie; -} - -/* Inspect a cookie and find out to which controller/slot it belongs. */ -static -struct b43_dmaring *parse_cookie(struct b43_wldev *dev, u16 cookie, int *slot) -{ - struct b43_dma *dma = &dev->dma; - struct b43_dmaring *ring = NULL; - - switch (cookie & 0xF000) { - case 0x1000: - ring = dma->tx_ring_AC_BK; - break; - case 0x2000: - ring = dma->tx_ring_AC_BE; - break; - case 0x3000: - ring = dma->tx_ring_AC_VI; - break; - case 0x4000: - ring = dma->tx_ring_AC_VO; - break; - case 0x5000: - ring = dma->tx_ring_mcast; - break; - default: - B43_WARN_ON(1); - } - *slot = (cookie & 0x0FFF); - B43_WARN_ON(!(ring && *slot >= 0 && *slot < ring->nr_slots)); - - return ring; -} - -static int dma_tx_fragment(struct b43_dmaring *ring, - struct sk_buff **in_skb) -{ - struct sk_buff *skb = *in_skb; - const struct b43_dma_ops *ops = ring->ops; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u8 *header; - int slot, old_top_slot, old_used_slots; - int err; - struct b43_dmadesc_generic *desc; - struct b43_dmadesc_meta *meta; - struct b43_dmadesc_meta *meta_hdr; - struct sk_buff *bounce_skb; - u16 cookie; - size_t hdrsize = b43_txhdr_size(ring->dev); - - /* Important note: If the number of used DMA slots per TX frame - * is changed here, the TX_SLOTS_PER_FRAME definition at the top of - * the file has to be updated, too! - */ - - old_top_slot = ring->current_slot; - old_used_slots = ring->used_slots; - - /* Get a slot for the header. */ - slot = request_slot(ring); - desc = ops->idx2desc(ring, slot, &meta_hdr); - memset(meta_hdr, 0, sizeof(*meta_hdr)); - - header = &(ring->txhdr_cache[(slot / TX_SLOTS_PER_FRAME) * hdrsize]); - cookie = generate_cookie(ring, slot); - err = b43_generate_txhdr(ring->dev, header, - skb, info, cookie); - if (unlikely(err)) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - return err; - } - - meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, - hdrsize, 1); - if (b43_dma_mapping_error(ring, meta_hdr->dmaaddr, hdrsize, 1)) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - return -EIO; - } - ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, - hdrsize, 1, 0, 0); - - /* Get a slot for the payload. */ - slot = request_slot(ring); - desc = ops->idx2desc(ring, slot, &meta); - memset(meta, 0, sizeof(*meta)); - - meta->skb = skb; - meta->is_last_fragment = 1; - - meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - /* create a bounce buffer in zone_dma on mapping failure. */ - if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); - if (!bounce_skb) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - err = -ENOMEM; - goto out_unmap_hdr; - } - - memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); - memcpy(bounce_skb->cb, skb->cb, sizeof(skb->cb)); - bounce_skb->dev = skb->dev; - skb_set_queue_mapping(bounce_skb, skb_get_queue_mapping(skb)); - info = IEEE80211_SKB_CB(bounce_skb); - - dev_kfree_skb_any(skb); - skb = bounce_skb; - *in_skb = bounce_skb; - meta->skb = skb; - meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (b43_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - err = -EIO; - goto out_free_bounce; - } - } - - ops->fill_descriptor(ring, desc, meta->dmaaddr, skb->len, 0, 1, 1); - - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - /* Tell the firmware about the cookie of the last - * mcast frame, so it can clear the more-data bit in it. */ - b43_shm_write16(ring->dev, B43_SHM_SHARED, - B43_SHM_SH_MCASTCOOKIE, cookie); - } - /* Now transfer the whole frame. */ - wmb(); - ops->poke_tx(ring, next_slot(ring, slot)); - return 0; - -out_free_bounce: - dev_kfree_skb_any(skb); -out_unmap_hdr: - unmap_descbuffer(ring, meta_hdr->dmaaddr, - hdrsize, 1); - return err; -} - -static inline int should_inject_overflow(struct b43_dmaring *ring) -{ -#ifdef CONFIG_B43_DEBUG - if (unlikely(b43_debug(ring->dev, B43_DBG_DMAOVERFLOW))) { - /* Check if we should inject another ringbuffer overflow - * to test handling of this situation in the stack. */ - unsigned long next_overflow; - - next_overflow = ring->last_injected_overflow + HZ; - if (time_after(jiffies, next_overflow)) { - ring->last_injected_overflow = jiffies; - b43dbg(ring->dev->wl, - "Injecting TX ring overflow on " - "DMA controller %d\n", ring->index); - return 1; - } - } -#endif /* CONFIG_B43_DEBUG */ - return 0; -} - -/* Static mapping of mac80211's queues (priorities) to b43 DMA rings. */ -static struct b43_dmaring *select_ring_by_priority(struct b43_wldev *dev, - u8 queue_prio) -{ - struct b43_dmaring *ring; - - if (dev->qos_enabled) { - /* 0 = highest priority */ - switch (queue_prio) { - default: - B43_WARN_ON(1); - /* fallthrough */ - case 0: - ring = dev->dma.tx_ring_AC_VO; - break; - case 1: - ring = dev->dma.tx_ring_AC_VI; - break; - case 2: - ring = dev->dma.tx_ring_AC_BE; - break; - case 3: - ring = dev->dma.tx_ring_AC_BK; - break; - } - } else - ring = dev->dma.tx_ring_AC_BE; - - return ring; -} - -int b43_dma_tx(struct b43_wldev *dev, struct sk_buff *skb) -{ - struct b43_dmaring *ring; - struct ieee80211_hdr *hdr; - int err = 0; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - hdr = (struct ieee80211_hdr *)skb->data; - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - /* The multicast ring will be sent after the DTIM */ - ring = dev->dma.tx_ring_mcast; - /* Set the more-data bit. Ucode will clear it on - * the last frame for us. */ - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } else { - /* Decide by priority where to put this frame. */ - ring = select_ring_by_priority( - dev, skb_get_queue_mapping(skb)); - } - - B43_WARN_ON(!ring->tx); - - if (unlikely(ring->stopped)) { - /* We get here only because of a bug in mac80211. - * Because of a race, one packet may be queued after - * the queue is stopped, thus we got called when we shouldn't. - * For now, just refuse the transmit. */ - if (b43_debug(dev, B43_DBG_DMAVERBOSE)) - b43err(dev->wl, "Packet after queue stopped\n"); - err = -ENOSPC; - goto out; - } - - if (unlikely(WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME))) { - /* If we get here, we have a real error with the queue - * full, but queues not stopped. */ - b43err(dev->wl, "DMA queue overflow\n"); - err = -ENOSPC; - goto out; - } - - /* Assign the queue number to the ring (if not already done before) - * so TX status handling can use it. The queue to ring mapping is - * static, so we don't need to store it per frame. */ - ring->queue_prio = skb_get_queue_mapping(skb); - - /* dma_tx_fragment might reallocate the skb, so invalidate pointers pointing - * into the skb data or cb now. */ - hdr = NULL; - info = NULL; - err = dma_tx_fragment(ring, &skb); - if (unlikely(err == -ENOKEY)) { - /* Drop this packet, as we don't have the encryption key - * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); - err = 0; - goto out; - } - if (unlikely(err)) { - b43err(dev->wl, "DMA tx mapping failure\n"); - goto out; - } - ring->nr_tx_packets++; - if ((free_slots(ring) < TX_SLOTS_PER_FRAME) || - should_inject_overflow(ring)) { - /* This TX ring is full. */ - ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); - ring->stopped = 1; - if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { - b43dbg(dev->wl, "Stopped TX ring %d\n", ring->index); - } - } -out: - - return err; -} - -void b43_dma_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ - const struct b43_dma_ops *ops; - struct b43_dmaring *ring; - struct b43_dmadesc_generic *desc; - struct b43_dmadesc_meta *meta; - int slot; - bool frame_succeed; - - ring = parse_cookie(dev, status->cookie, &slot); - if (unlikely(!ring)) - return; - - B43_WARN_ON(!ring->tx); - ops = ring->ops; - while (1) { - B43_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - desc = ops->idx2desc(ring, slot, &meta); - - if (meta->skb) - unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, - 1); - else - unmap_descbuffer(ring, meta->dmaaddr, - b43_txhdr_size(dev), 1); - - if (meta->is_last_fragment) { - struct ieee80211_tx_info *info; - - BUG_ON(!meta->skb); - - info = IEEE80211_SKB_CB(meta->skb); - - /* - * Call back to inform the ieee80211 subsystem about - * the status of the transmission. - */ - frame_succeed = b43_fill_txstatus_report(dev, info, status); -#ifdef CONFIG_B43_DEBUG - if (frame_succeed) - ring->nr_succeed_tx_packets++; - else - ring->nr_failed_tx_packets++; - ring->nr_total_packet_tries += status->frame_count; -#endif /* DEBUG */ - ieee80211_tx_status(dev->wl->hw, meta->skb); - - /* skb is freed by ieee80211_tx_status() */ - meta->skb = NULL; - } else { - /* No need to call free_descriptor_buffer here, as - * this is only the txhdr, which is not allocated. - */ - B43_WARN_ON(meta->skb); - } - - /* Everything unmapped and free'd. So it's not used anymore. */ - ring->used_slots--; - - if (meta->is_last_fragment) - break; - slot = next_slot(ring, slot); - } - if (ring->stopped) { - B43_WARN_ON(free_slots(ring) < TX_SLOTS_PER_FRAME); - ieee80211_wake_queue(dev->wl->hw, ring->queue_prio); - ring->stopped = 0; - if (b43_debug(dev, B43_DBG_DMAVERBOSE)) { - b43dbg(dev->wl, "Woke up TX ring %d\n", ring->index); - } - } -} - -void b43_dma_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - const int nr_queues = dev->wl->hw->queues; - struct b43_dmaring *ring; - int i; - - for (i = 0; i < nr_queues; i++) { - ring = select_ring_by_priority(dev, i); - - stats[i].len = ring->used_slots / TX_SLOTS_PER_FRAME; - stats[i].limit = ring->nr_slots / TX_SLOTS_PER_FRAME; - stats[i].count = ring->nr_tx_packets; - } -} - -static void dma_rx(struct b43_dmaring *ring, int *slot) -{ - const struct b43_dma_ops *ops = ring->ops; - struct b43_dmadesc_generic *desc; - struct b43_dmadesc_meta *meta; - struct b43_rxhdr_fw4 *rxhdr; - struct sk_buff *skb; - u16 len; - int err; - dma_addr_t dmaaddr; - - desc = ops->idx2desc(ring, *slot, &meta); - - sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); - skb = meta->skb; - - rxhdr = (struct b43_rxhdr_fw4 *)skb->data; - len = le16_to_cpu(rxhdr->frame_len); - if (len == 0) { - int i = 0; - - do { - udelay(2); - barrier(); - len = le16_to_cpu(rxhdr->frame_len); - } while (len == 0 && i++ < 5); - if (unlikely(len == 0)) { - dmaaddr = meta->dmaaddr; - goto drop_recycle_buffer; - } - } - if (unlikely(b43_rx_buffer_is_poisoned(ring, skb))) { - /* Something went wrong with the DMA. - * The device did not touch the buffer and did not overwrite the poison. */ - b43dbg(ring->dev->wl, "DMA RX: Dropping poisoned buffer.\n"); - dmaaddr = meta->dmaaddr; - goto drop_recycle_buffer; - } - if (unlikely(len > ring->rx_buffersize)) { - /* The data did not fit into one descriptor buffer - * and is split over multiple buffers. - * This should never happen, as we try to allocate buffers - * big enough. So simply ignore this packet. - */ - int cnt = 0; - s32 tmp = len; - - while (1) { - desc = ops->idx2desc(ring, *slot, &meta); - /* recycle the descriptor buffer. */ - b43_poison_rx_buffer(ring, meta->skb); - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - *slot = next_slot(ring, *slot); - cnt++; - tmp -= ring->rx_buffersize; - if (tmp <= 0) - break; - } - b43err(ring->dev->wl, "DMA RX buffer too small " - "(len: %u, buffer: %u, nr-dropped: %d)\n", - len, ring->rx_buffersize, cnt); - goto drop; - } - - dmaaddr = meta->dmaaddr; - err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); - if (unlikely(err)) { - b43dbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer() failed\n"); - goto drop_recycle_buffer; - } - - unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); - skb_put(skb, len + ring->frameoffset); - skb_pull(skb, ring->frameoffset); - - b43_rx(ring->dev, skb, rxhdr); -drop: - return; - -drop_recycle_buffer: - /* Poison and recycle the RX buffer. */ - b43_poison_rx_buffer(ring, skb); - sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize); -} - -void b43_dma_rx(struct b43_dmaring *ring) -{ - const struct b43_dma_ops *ops = ring->ops; - int slot, current_slot; - int used_slots = 0; - - B43_WARN_ON(ring->tx); - current_slot = ops->get_current_rxslot(ring); - B43_WARN_ON(!(current_slot >= 0 && current_slot < ring->nr_slots)); - - slot = ring->current_slot; - for (; slot != current_slot; slot = next_slot(ring, slot)) { - dma_rx(ring, &slot); - update_max_used_slots(ring, ++used_slots); - } - ops->set_current_rxslot(ring, slot); - ring->current_slot = slot; -} - -static void b43_dma_tx_suspend_ring(struct b43_dmaring *ring) -{ - B43_WARN_ON(!ring->tx); - ring->ops->tx_suspend(ring); -} - -static void b43_dma_tx_resume_ring(struct b43_dmaring *ring) -{ - B43_WARN_ON(!ring->tx); - ring->ops->tx_resume(ring); -} - -void b43_dma_tx_suspend(struct b43_wldev *dev) -{ - b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); - b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BK); - b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_BE); - b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VI); - b43_dma_tx_suspend_ring(dev->dma.tx_ring_AC_VO); - b43_dma_tx_suspend_ring(dev->dma.tx_ring_mcast); -} - -void b43_dma_tx_resume(struct b43_wldev *dev) -{ - b43_dma_tx_resume_ring(dev->dma.tx_ring_mcast); - b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VO); - b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_VI); - b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BE); - b43_dma_tx_resume_ring(dev->dma.tx_ring_AC_BK); - b43_power_saving_ctl_bits(dev, 0); -} - -static void direct_fifo_rx(struct b43_wldev *dev, enum b43_dmatype type, - u16 mmio_base, bool enable) -{ - u32 ctl; - - if (type == B43_DMA_64BIT) { - ctl = b43_read32(dev, mmio_base + B43_DMA64_RXCTL); - ctl &= ~B43_DMA64_RXDIRECTFIFO; - if (enable) - ctl |= B43_DMA64_RXDIRECTFIFO; - b43_write32(dev, mmio_base + B43_DMA64_RXCTL, ctl); - } else { - ctl = b43_read32(dev, mmio_base + B43_DMA32_RXCTL); - ctl &= ~B43_DMA32_RXDIRECTFIFO; - if (enable) - ctl |= B43_DMA32_RXDIRECTFIFO; - b43_write32(dev, mmio_base + B43_DMA32_RXCTL, ctl); - } -} - -/* Enable/Disable Direct FIFO Receive Mode (PIO) on a RX engine. - * This is called from PIO code, so DMA structures are not available. */ -void b43_dma_direct_fifo_rx(struct b43_wldev *dev, - unsigned int engine_index, bool enable) -{ - enum b43_dmatype type; - u16 mmio_base; - - type = dma_mask_to_engine_type(supported_dma_mask(dev)); - - mmio_base = b43_dmacontroller_base(type, engine_index); - direct_fifo_rx(dev, type, mmio_base, enable); -} diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h deleted file mode 100644 index f0b0838fb5ba..000000000000 --- a/drivers/net/wireless/b43/dma.h +++ /dev/null @@ -1,290 +0,0 @@ -#ifndef B43_DMA_H_ -#define B43_DMA_H_ - -#include - -#include "b43.h" - - -/* DMA-Interrupt reasons. */ -#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ - | (1 << 14) | (1 << 15)) -#define B43_DMAIRQ_NONFATALMASK (1 << 13) -#define B43_DMAIRQ_RX_DONE (1 << 16) - -/*** 32-bit DMA Engine. ***/ - -/* 32-bit DMA controller registers. */ -#define B43_DMA32_TXCTL 0x00 -#define B43_DMA32_TXENABLE 0x00000001 -#define B43_DMA32_TXSUSPEND 0x00000002 -#define B43_DMA32_TXLOOPBACK 0x00000004 -#define B43_DMA32_TXFLUSH 0x00000010 -#define B43_DMA32_TXADDREXT_MASK 0x00030000 -#define B43_DMA32_TXADDREXT_SHIFT 16 -#define B43_DMA32_TXRING 0x04 -#define B43_DMA32_TXINDEX 0x08 -#define B43_DMA32_TXSTATUS 0x0C -#define B43_DMA32_TXDPTR 0x00000FFF -#define B43_DMA32_TXSTATE 0x0000F000 -#define B43_DMA32_TXSTAT_DISABLED 0x00000000 -#define B43_DMA32_TXSTAT_ACTIVE 0x00001000 -#define B43_DMA32_TXSTAT_IDLEWAIT 0x00002000 -#define B43_DMA32_TXSTAT_STOPPED 0x00003000 -#define B43_DMA32_TXSTAT_SUSP 0x00004000 -#define B43_DMA32_TXERROR 0x000F0000 -#define B43_DMA32_TXERR_NOERR 0x00000000 -#define B43_DMA32_TXERR_PROT 0x00010000 -#define B43_DMA32_TXERR_UNDERRUN 0x00020000 -#define B43_DMA32_TXERR_BUFREAD 0x00030000 -#define B43_DMA32_TXERR_DESCREAD 0x00040000 -#define B43_DMA32_TXACTIVE 0xFFF00000 -#define B43_DMA32_RXCTL 0x10 -#define B43_DMA32_RXENABLE 0x00000001 -#define B43_DMA32_RXFROFF_MASK 0x000000FE -#define B43_DMA32_RXFROFF_SHIFT 1 -#define B43_DMA32_RXDIRECTFIFO 0x00000100 -#define B43_DMA32_RXADDREXT_MASK 0x00030000 -#define B43_DMA32_RXADDREXT_SHIFT 16 -#define B43_DMA32_RXRING 0x14 -#define B43_DMA32_RXINDEX 0x18 -#define B43_DMA32_RXSTATUS 0x1C -#define B43_DMA32_RXDPTR 0x00000FFF -#define B43_DMA32_RXSTATE 0x0000F000 -#define B43_DMA32_RXSTAT_DISABLED 0x00000000 -#define B43_DMA32_RXSTAT_ACTIVE 0x00001000 -#define B43_DMA32_RXSTAT_IDLEWAIT 0x00002000 -#define B43_DMA32_RXSTAT_STOPPED 0x00003000 -#define B43_DMA32_RXERROR 0x000F0000 -#define B43_DMA32_RXERR_NOERR 0x00000000 -#define B43_DMA32_RXERR_PROT 0x00010000 -#define B43_DMA32_RXERR_OVERFLOW 0x00020000 -#define B43_DMA32_RXERR_BUFWRITE 0x00030000 -#define B43_DMA32_RXERR_DESCREAD 0x00040000 -#define B43_DMA32_RXACTIVE 0xFFF00000 - -/* 32-bit DMA descriptor. */ -struct b43_dmadesc32 { - __le32 control; - __le32 address; -} __attribute__ ((__packed__)); -#define B43_DMA32_DCTL_BYTECNT 0x00001FFF -#define B43_DMA32_DCTL_ADDREXT_MASK 0x00030000 -#define B43_DMA32_DCTL_ADDREXT_SHIFT 16 -#define B43_DMA32_DCTL_DTABLEEND 0x10000000 -#define B43_DMA32_DCTL_IRQ 0x20000000 -#define B43_DMA32_DCTL_FRAMEEND 0x40000000 -#define B43_DMA32_DCTL_FRAMESTART 0x80000000 - -/*** 64-bit DMA Engine. ***/ - -/* 64-bit DMA controller registers. */ -#define B43_DMA64_TXCTL 0x00 -#define B43_DMA64_TXENABLE 0x00000001 -#define B43_DMA64_TXSUSPEND 0x00000002 -#define B43_DMA64_TXLOOPBACK 0x00000004 -#define B43_DMA64_TXFLUSH 0x00000010 -#define B43_DMA64_TXADDREXT_MASK 0x00030000 -#define B43_DMA64_TXADDREXT_SHIFT 16 -#define B43_DMA64_TXINDEX 0x04 -#define B43_DMA64_TXRINGLO 0x08 -#define B43_DMA64_TXRINGHI 0x0C -#define B43_DMA64_TXSTATUS 0x10 -#define B43_DMA64_TXSTATDPTR 0x00001FFF -#define B43_DMA64_TXSTAT 0xF0000000 -#define B43_DMA64_TXSTAT_DISABLED 0x00000000 -#define B43_DMA64_TXSTAT_ACTIVE 0x10000000 -#define B43_DMA64_TXSTAT_IDLEWAIT 0x20000000 -#define B43_DMA64_TXSTAT_STOPPED 0x30000000 -#define B43_DMA64_TXSTAT_SUSP 0x40000000 -#define B43_DMA64_TXERROR 0x14 -#define B43_DMA64_TXERRDPTR 0x0001FFFF -#define B43_DMA64_TXERR 0xF0000000 -#define B43_DMA64_TXERR_NOERR 0x00000000 -#define B43_DMA64_TXERR_PROT 0x10000000 -#define B43_DMA64_TXERR_UNDERRUN 0x20000000 -#define B43_DMA64_TXERR_TRANSFER 0x30000000 -#define B43_DMA64_TXERR_DESCREAD 0x40000000 -#define B43_DMA64_TXERR_CORE 0x50000000 -#define B43_DMA64_RXCTL 0x20 -#define B43_DMA64_RXENABLE 0x00000001 -#define B43_DMA64_RXFROFF_MASK 0x000000FE -#define B43_DMA64_RXFROFF_SHIFT 1 -#define B43_DMA64_RXDIRECTFIFO 0x00000100 -#define B43_DMA64_RXADDREXT_MASK 0x00030000 -#define B43_DMA64_RXADDREXT_SHIFT 16 -#define B43_DMA64_RXINDEX 0x24 -#define B43_DMA64_RXRINGLO 0x28 -#define B43_DMA64_RXRINGHI 0x2C -#define B43_DMA64_RXSTATUS 0x30 -#define B43_DMA64_RXSTATDPTR 0x00001FFF -#define B43_DMA64_RXSTAT 0xF0000000 -#define B43_DMA64_RXSTAT_DISABLED 0x00000000 -#define B43_DMA64_RXSTAT_ACTIVE 0x10000000 -#define B43_DMA64_RXSTAT_IDLEWAIT 0x20000000 -#define B43_DMA64_RXSTAT_STOPPED 0x30000000 -#define B43_DMA64_RXSTAT_SUSP 0x40000000 -#define B43_DMA64_RXERROR 0x34 -#define B43_DMA64_RXERRDPTR 0x0001FFFF -#define B43_DMA64_RXERR 0xF0000000 -#define B43_DMA64_RXERR_NOERR 0x00000000 -#define B43_DMA64_RXERR_PROT 0x10000000 -#define B43_DMA64_RXERR_UNDERRUN 0x20000000 -#define B43_DMA64_RXERR_TRANSFER 0x30000000 -#define B43_DMA64_RXERR_DESCREAD 0x40000000 -#define B43_DMA64_RXERR_CORE 0x50000000 - -/* 64-bit DMA descriptor. */ -struct b43_dmadesc64 { - __le32 control0; - __le32 control1; - __le32 address_low; - __le32 address_high; -} __attribute__ ((__packed__)); -#define B43_DMA64_DCTL0_DTABLEEND 0x10000000 -#define B43_DMA64_DCTL0_IRQ 0x20000000 -#define B43_DMA64_DCTL0_FRAMEEND 0x40000000 -#define B43_DMA64_DCTL0_FRAMESTART 0x80000000 -#define B43_DMA64_DCTL1_BYTECNT 0x00001FFF -#define B43_DMA64_DCTL1_ADDREXT_MASK 0x00030000 -#define B43_DMA64_DCTL1_ADDREXT_SHIFT 16 - -struct b43_dmadesc_generic { - union { - struct b43_dmadesc32 dma32; - struct b43_dmadesc64 dma64; - } __attribute__ ((__packed__)); -} __attribute__ ((__packed__)); - -/* Misc DMA constants */ -#define B43_DMA_RINGMEMSIZE PAGE_SIZE -#define B43_DMA0_RX_FRAMEOFFSET 30 - -/* DMA engine tuning knobs */ -#define B43_TXRING_SLOTS 256 -#define B43_RXRING_SLOTS 64 -#define B43_DMA0_RX_BUFFERSIZE IEEE80211_MAX_FRAME_LEN - - -struct sk_buff; -struct b43_private; -struct b43_txstatus; - -struct b43_dmadesc_meta { - /* The kernel DMA-able buffer. */ - struct sk_buff *skb; - /* DMA base bus-address of the descriptor buffer. */ - dma_addr_t dmaaddr; - /* ieee80211 TX status. Only used once per 802.11 frag. */ - bool is_last_fragment; -}; - -struct b43_dmaring; - -/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */ -struct b43_dma_ops { - struct b43_dmadesc_generic *(*idx2desc) (struct b43_dmaring * ring, - int slot, - struct b43_dmadesc_meta ** - meta); - void (*fill_descriptor) (struct b43_dmaring * ring, - struct b43_dmadesc_generic * desc, - dma_addr_t dmaaddr, u16 bufsize, int start, - int end, int irq); - void (*poke_tx) (struct b43_dmaring * ring, int slot); - void (*tx_suspend) (struct b43_dmaring * ring); - void (*tx_resume) (struct b43_dmaring * ring); - int (*get_current_rxslot) (struct b43_dmaring * ring); - void (*set_current_rxslot) (struct b43_dmaring * ring, int slot); -}; - -enum b43_dmatype { - B43_DMA_30BIT = 30, - B43_DMA_32BIT = 32, - B43_DMA_64BIT = 64, -}; - -struct b43_dmaring { - /* Lowlevel DMA ops. */ - const struct b43_dma_ops *ops; - /* Kernel virtual base address of the ring memory. */ - void *descbase; - /* Meta data about all descriptors. */ - struct b43_dmadesc_meta *meta; - /* Cache of TX headers for each TX frame. - * This is to avoid an allocation on each TX. - * This is NULL for an RX ring. - */ - u8 *txhdr_cache; - /* (Unadjusted) DMA base bus-address of the ring memory. */ - dma_addr_t dmabase; - /* Number of descriptor slots in the ring. */ - int nr_slots; - /* Number of used descriptor slots. */ - int used_slots; - /* Currently used slot in the ring. */ - int current_slot; - /* Total number of packets sent. Statistics only. */ - unsigned int nr_tx_packets; - /* Frameoffset in octets. */ - u32 frameoffset; - /* Descriptor buffer size. */ - u16 rx_buffersize; - /* The MMIO base register of the DMA controller. */ - u16 mmio_base; - /* DMA controller index number (0-5). */ - int index; - /* Boolean. Is this a TX ring? */ - bool tx; - /* The type of DMA engine used. */ - enum b43_dmatype type; - /* Boolean. Is this ring stopped at ieee80211 level? */ - bool stopped; - /* The QOS priority assigned to this ring. Only used for TX rings. - * This is the mac80211 "queue" value. */ - u8 queue_prio; - struct b43_wldev *dev; -#ifdef CONFIG_B43_DEBUG - /* Maximum number of used slots. */ - int max_used_slots; - /* Last time we injected a ring overflow. */ - unsigned long last_injected_overflow; - /* Statistics: Number of successfully transmitted packets */ - u64 nr_succeed_tx_packets; - /* Statistics: Number of failed TX packets */ - u64 nr_failed_tx_packets; - /* Statistics: Total number of TX plus all retries. */ - u64 nr_total_packet_tries; -#endif /* CONFIG_B43_DEBUG */ -}; - -static inline u32 b43_dma_read(struct b43_dmaring *ring, u16 offset) -{ - return b43_read32(ring->dev, ring->mmio_base + offset); -} - -static inline void b43_dma_write(struct b43_dmaring *ring, u16 offset, u32 value) -{ - b43_write32(ring->dev, ring->mmio_base + offset, value); -} - -int b43_dma_init(struct b43_wldev *dev); -void b43_dma_free(struct b43_wldev *dev); - -void b43_dma_tx_suspend(struct b43_wldev *dev); -void b43_dma_tx_resume(struct b43_wldev *dev); - -void b43_dma_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats); - -int b43_dma_tx(struct b43_wldev *dev, - struct sk_buff *skb); -void b43_dma_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status); - -void b43_dma_rx(struct b43_dmaring *ring); - -void b43_dma_direct_fifo_rx(struct b43_wldev *dev, - unsigned int engine_index, bool enable); - -#endif /* B43_DMA_H_ */ diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c deleted file mode 100644 index 1e8dba488004..000000000000 --- a/drivers/net/wireless/b43/leds.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - - Broadcom B43 wireless driver - LED control - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005 Stefano Brivio - Copyright (c) 2005-2007 Michael Buesch - Copyright (c) 2005 Danny van Dyk - Copyright (c) 2005 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "leds.h" -#include "rfkill.h" - - -static void b43_led_turn_on(struct b43_wldev *dev, u8 led_index, - bool activelow) -{ - u16 ctl; - - ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); - if (activelow) - ctl &= ~(1 << led_index); - else - ctl |= (1 << led_index); - b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); -} - -static void b43_led_turn_off(struct b43_wldev *dev, u8 led_index, - bool activelow) -{ - u16 ctl; - - ctl = b43_read16(dev, B43_MMIO_GPIO_CONTROL); - if (activelow) - ctl |= (1 << led_index); - else - ctl &= ~(1 << led_index); - b43_write16(dev, B43_MMIO_GPIO_CONTROL, ctl); -} - -static void b43_led_update(struct b43_wldev *dev, - struct b43_led *led) -{ - bool radio_enabled; - bool turn_on; - - if (!led->wl) - return; - - radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); - - /* The led->state read is racy, but we don't care. In case we raced - * with the brightness_set handler, we will be called again soon - * to fixup our state. */ - if (radio_enabled) - turn_on = atomic_read(&led->state) != LED_OFF; - else - turn_on = 0; - if (turn_on == led->hw_state) - return; - led->hw_state = turn_on; - - if (turn_on) - b43_led_turn_on(dev, led->index, led->activelow); - else - b43_led_turn_off(dev, led->index, led->activelow); -} - -static void b43_leds_work(struct work_struct *work) -{ - struct b43_leds *leds = container_of(work, struct b43_leds, work); - struct b43_wl *wl = container_of(leds, struct b43_wl, leds); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) - goto out_unlock; - - b43_led_update(dev, &wl->leds.led_tx); - b43_led_update(dev, &wl->leds.led_rx); - b43_led_update(dev, &wl->leds.led_radio); - b43_led_update(dev, &wl->leds.led_assoc); - -out_unlock: - mutex_unlock(&wl->mutex); -} - -/* Callback from the LED subsystem. */ -static void b43_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct b43_led *led = container_of(led_dev, struct b43_led, led_dev); - struct b43_wl *wl = led->wl; - - if (likely(!wl->leds.stop)) { - atomic_set(&led->state, brightness); - ieee80211_queue_work(wl->hw, &wl->leds.work); - } -} - -static int b43_register_led(struct b43_wldev *dev, struct b43_led *led, - const char *name, const char *default_trigger, - u8 led_index, bool activelow) -{ - int err; - - if (led->wl) - return -EEXIST; - if (!default_trigger) - return -EINVAL; - led->wl = dev->wl; - led->index = led_index; - led->activelow = activelow; - strncpy(led->name, name, sizeof(led->name)); - atomic_set(&led->state, 0); - - led->led_dev.name = led->name; - led->led_dev.default_trigger = default_trigger; - led->led_dev.brightness_set = b43_led_brightness_set; - - err = led_classdev_register(dev->dev->dev, &led->led_dev); - if (err) { - b43warn(dev->wl, "LEDs: Failed to register %s\n", name); - led->wl = NULL; - return err; - } - - return 0; -} - -static void b43_unregister_led(struct b43_led *led) -{ - if (!led->wl) - return; - led_classdev_unregister(&led->led_dev); - led->wl = NULL; -} - -static void b43_map_led(struct b43_wldev *dev, - u8 led_index, - enum b43_led_behaviour behaviour, - bool activelow) -{ - struct ieee80211_hw *hw = dev->wl->hw; - char name[B43_LED_MAX_NAME_LEN + 1]; - - /* Map the b43 specific LED behaviour value to the - * generic LED triggers. */ - switch (behaviour) { - case B43_LED_INACTIVE: - case B43_LED_OFF: - case B43_LED_ON: - break; - case B43_LED_ACTIVITY: - case B43_LED_TRANSFER: - case B43_LED_APTRANSFER: - snprintf(name, sizeof(name), - "b43-%s::tx", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_tx, name, - ieee80211_get_tx_led_name(hw), - led_index, activelow); - snprintf(name, sizeof(name), - "b43-%s::rx", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_rx, name, - ieee80211_get_rx_led_name(hw), - led_index, activelow); - break; - case B43_LED_RADIO_ALL: - case B43_LED_RADIO_A: - case B43_LED_RADIO_B: - case B43_LED_MODE_BG: - snprintf(name, sizeof(name), - "b43-%s::radio", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_radio, name, - ieee80211_get_radio_led_name(hw), - led_index, activelow); - break; - case B43_LED_WEIRD: - case B43_LED_ASSOC: - snprintf(name, sizeof(name), - "b43-%s::assoc", wiphy_name(hw->wiphy)); - b43_register_led(dev, &dev->wl->leds.led_assoc, name, - ieee80211_get_assoc_led_name(hw), - led_index, activelow); - break; - default: - b43warn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n", - behaviour); - break; - } -} - -static void b43_led_get_sprominfo(struct b43_wldev *dev, - unsigned int led_index, - enum b43_led_behaviour *behaviour, - bool *activelow) -{ - struct ssb_bus *bus = dev->dev->bus; - u8 sprom[4]; - - sprom[0] = bus->sprom.gpio0; - sprom[1] = bus->sprom.gpio1; - sprom[2] = bus->sprom.gpio2; - sprom[3] = bus->sprom.gpio3; - - if (sprom[led_index] == 0xFF) { - /* There is no LED information in the SPROM - * for this LED. Hardcode it here. */ - *activelow = 0; - switch (led_index) { - case 0: - *behaviour = B43_LED_ACTIVITY; - *activelow = 1; - if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) - *behaviour = B43_LED_RADIO_ALL; - break; - case 1: - *behaviour = B43_LED_RADIO_B; - if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) - *behaviour = B43_LED_ASSOC; - break; - case 2: - *behaviour = B43_LED_RADIO_A; - break; - case 3: - *behaviour = B43_LED_OFF; - break; - default: - B43_WARN_ON(1); - return; - } - } else { - *behaviour = sprom[led_index] & B43_LED_BEHAVIOUR; - *activelow = !!(sprom[led_index] & B43_LED_ACTIVELOW); - } -} - -void b43_leds_init(struct b43_wldev *dev) -{ - struct b43_led *led; - unsigned int i; - enum b43_led_behaviour behaviour; - bool activelow; - - /* Sync the RF-kill LED state (if we have one) with radio and switch states. */ - led = &dev->wl->leds.led_radio; - if (led->wl) { - if (dev->phy.radio_on && b43_is_hw_radio_enabled(dev)) { - b43_led_turn_on(dev, led->index, led->activelow); - led->hw_state = 1; - atomic_set(&led->state, 1); - } else { - b43_led_turn_off(dev, led->index, led->activelow); - led->hw_state = 0; - atomic_set(&led->state, 0); - } - } - - /* Initialize TX/RX/ASSOC leds */ - led = &dev->wl->leds.led_tx; - if (led->wl) { - b43_led_turn_off(dev, led->index, led->activelow); - led->hw_state = 0; - atomic_set(&led->state, 0); - } - led = &dev->wl->leds.led_rx; - if (led->wl) { - b43_led_turn_off(dev, led->index, led->activelow); - led->hw_state = 0; - atomic_set(&led->state, 0); - } - led = &dev->wl->leds.led_assoc; - if (led->wl) { - b43_led_turn_off(dev, led->index, led->activelow); - led->hw_state = 0; - atomic_set(&led->state, 0); - } - - /* Initialize other LED states. */ - for (i = 0; i < B43_MAX_NR_LEDS; i++) { - b43_led_get_sprominfo(dev, i, &behaviour, &activelow); - switch (behaviour) { - case B43_LED_OFF: - b43_led_turn_off(dev, i, activelow); - break; - case B43_LED_ON: - b43_led_turn_on(dev, i, activelow); - break; - default: - /* Leave others as-is. */ - break; - } - } - - dev->wl->leds.stop = 0; -} - -void b43_leds_exit(struct b43_wldev *dev) -{ - struct b43_leds *leds = &dev->wl->leds; - - b43_led_turn_off(dev, leds->led_tx.index, leds->led_tx.activelow); - b43_led_turn_off(dev, leds->led_rx.index, leds->led_rx.activelow); - b43_led_turn_off(dev, leds->led_assoc.index, leds->led_assoc.activelow); - b43_led_turn_off(dev, leds->led_radio.index, leds->led_radio.activelow); -} - -void b43_leds_stop(struct b43_wldev *dev) -{ - struct b43_leds *leds = &dev->wl->leds; - - leds->stop = 1; - cancel_work_sync(&leds->work); -} - -void b43_leds_register(struct b43_wldev *dev) -{ - unsigned int i; - enum b43_led_behaviour behaviour; - bool activelow; - - INIT_WORK(&dev->wl->leds.work, b43_leds_work); - - /* Register the LEDs to the LED subsystem. */ - for (i = 0; i < B43_MAX_NR_LEDS; i++) { - b43_led_get_sprominfo(dev, i, &behaviour, &activelow); - b43_map_led(dev, i, behaviour, activelow); - } -} - -void b43_leds_unregister(struct b43_wl *wl) -{ - struct b43_leds *leds = &wl->leds; - - b43_unregister_led(&leds->led_tx); - b43_unregister_led(&leds->led_rx); - b43_unregister_led(&leds->led_assoc); - b43_unregister_led(&leds->led_radio); -} diff --git a/drivers/net/wireless/b43/leds.h b/drivers/net/wireless/b43/leds.h deleted file mode 100644 index 32b66d53cdac..000000000000 --- a/drivers/net/wireless/b43/leds.h +++ /dev/null @@ -1,94 +0,0 @@ -#ifndef B43_LEDS_H_ -#define B43_LEDS_H_ - -struct b43_wl; -struct b43_wldev; - -#ifdef CONFIG_B43_LEDS - -#include -#include -#include - - -#define B43_LED_MAX_NAME_LEN 31 - -struct b43_led { - struct b43_wl *wl; - /* The LED class device */ - struct led_classdev led_dev; - /* The index number of the LED. */ - u8 index; - /* If activelow is true, the LED is ON if the - * bit is switched off. */ - bool activelow; - /* The unique name string for this LED device. */ - char name[B43_LED_MAX_NAME_LEN + 1]; - /* The current status of the LED. This is updated locklessly. */ - atomic_t state; - /* The active state in hardware. */ - bool hw_state; -}; - -struct b43_leds { - struct b43_led led_tx; - struct b43_led led_rx; - struct b43_led led_radio; - struct b43_led led_assoc; - - bool stop; - struct work_struct work; -}; - -#define B43_MAX_NR_LEDS 4 - -#define B43_LED_BEHAVIOUR 0x7F -#define B43_LED_ACTIVELOW 0x80 -/* LED behaviour values */ -enum b43_led_behaviour { - B43_LED_OFF, - B43_LED_ON, - B43_LED_ACTIVITY, - B43_LED_RADIO_ALL, - B43_LED_RADIO_A, - B43_LED_RADIO_B, - B43_LED_MODE_BG, - B43_LED_TRANSFER, - B43_LED_APTRANSFER, - B43_LED_WEIRD, //FIXME - B43_LED_ASSOC, - B43_LED_INACTIVE, -}; - -void b43_leds_register(struct b43_wldev *dev); -void b43_leds_unregister(struct b43_wl *wl); -void b43_leds_init(struct b43_wldev *dev); -void b43_leds_exit(struct b43_wldev *dev); -void b43_leds_stop(struct b43_wldev *dev); - - -#else /* CONFIG_B43_LEDS */ -/* LED support disabled */ - -struct b43_leds { - /* empty */ -}; - -static inline void b43_leds_register(struct b43_wldev *dev) -{ -} -static inline void b43_leds_unregister(struct b43_wl *wl) -{ -} -static inline void b43_leds_init(struct b43_wldev *dev) -{ -} -static inline void b43_leds_exit(struct b43_wldev *dev) -{ -} -static inline void b43_leds_stop(struct b43_wldev *dev) -{ -} -#endif /* CONFIG_B43_LEDS */ - -#endif /* B43_LEDS_H_ */ diff --git a/drivers/net/wireless/b43/lo.c b/drivers/net/wireless/b43/lo.c deleted file mode 100644 index 976104f634a1..000000000000 --- a/drivers/net/wireless/b43/lo.c +++ /dev/null @@ -1,1017 +0,0 @@ -/* - - Broadcom B43 wireless driver - - G PHY LO (LocalOscillator) Measuring and Control routines - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005, 2006 Stefano Brivio - Copyright (c) 2005-2007 Michael Buesch - Copyright (c) 2005, 2006 Danny van Dyk - Copyright (c) 2005, 2006 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "lo.h" -#include "phy_g.h" -#include "main.h" - -#include -#include - - -static struct b43_lo_calib *b43_find_lo_calib(struct b43_txpower_lo_control *lo, - const struct b43_bbatt *bbatt, - const struct b43_rfatt *rfatt) -{ - struct b43_lo_calib *c; - - list_for_each_entry(c, &lo->calib_list, list) { - if (!b43_compare_bbatt(&c->bbatt, bbatt)) - continue; - if (!b43_compare_rfatt(&c->rfatt, rfatt)) - continue; - return c; - } - - return NULL; -} - -/* Write the LocalOscillator Control (adjust) value-pair. */ -static void b43_lo_write(struct b43_wldev *dev, struct b43_loctl *control) -{ - struct b43_phy *phy = &dev->phy; - u16 value; - - if (B43_DEBUG) { - if (unlikely(abs(control->i) > 16 || abs(control->q) > 16)) { - b43dbg(dev->wl, "Invalid LO control pair " - "(I: %d, Q: %d)\n", control->i, control->q); - dump_stack(); - return; - } - } - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - - value = (u8) (control->q); - value |= ((u8) (control->i)) << 8; - b43_phy_write(dev, B43_PHY_LO_CTL, value); -} - -static u16 lo_measure_feedthrough(struct b43_wldev *dev, - u16 lna, u16 pga, u16 trsw_rx) -{ - struct b43_phy *phy = &dev->phy; - u16 rfover; - u16 feedthrough; - - if (phy->gmode) { - lna <<= B43_PHY_RFOVERVAL_LNA_SHIFT; - pga <<= B43_PHY_RFOVERVAL_PGA_SHIFT; - - B43_WARN_ON(lna & ~B43_PHY_RFOVERVAL_LNA); - B43_WARN_ON(pga & ~B43_PHY_RFOVERVAL_PGA); -/*FIXME This assertion fails B43_WARN_ON(trsw_rx & ~(B43_PHY_RFOVERVAL_TRSWRX | - B43_PHY_RFOVERVAL_BW)); -*/ - trsw_rx &= (B43_PHY_RFOVERVAL_TRSWRX | B43_PHY_RFOVERVAL_BW); - - /* Construct the RF Override Value */ - rfover = B43_PHY_RFOVERVAL_UNK; - rfover |= pga; - rfover |= lna; - rfover |= trsw_rx; - if ((dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) - && phy->rev > 6) - rfover |= B43_PHY_RFOVERVAL_EXTLNA; - - b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); - b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); - udelay(10); - rfover |= B43_PHY_RFOVERVAL_BW_LBW; - b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); - udelay(10); - rfover |= B43_PHY_RFOVERVAL_BW_LPF; - b43_phy_write(dev, B43_PHY_RFOVERVAL, rfover); - udelay(10); - b43_phy_write(dev, B43_PHY_PGACTL, 0xF300); - } else { - pga |= B43_PHY_PGACTL_UNKNOWN; - b43_phy_write(dev, B43_PHY_PGACTL, pga); - udelay(10); - pga |= B43_PHY_PGACTL_LOWBANDW; - b43_phy_write(dev, B43_PHY_PGACTL, pga); - udelay(10); - pga |= B43_PHY_PGACTL_LPF; - b43_phy_write(dev, B43_PHY_PGACTL, pga); - } - udelay(21); - feedthrough = b43_phy_read(dev, B43_PHY_LO_LEAKAGE); - - /* This is a good place to check if we need to relax a bit, - * as this is the main function called regularly - * in the LO calibration. */ - cond_resched(); - - return feedthrough; -} - -/* TXCTL Register and Value Table. - * Returns the "TXCTL Register". - * "value" is the "TXCTL Value". - * "pad_mix_gain" is the PAD Mixer Gain. - */ -static u16 lo_txctl_register_table(struct b43_wldev *dev, - u16 *value, u16 *pad_mix_gain) -{ - struct b43_phy *phy = &dev->phy; - u16 reg, v, padmix; - - if (phy->type == B43_PHYTYPE_B) { - v = 0x30; - if (phy->radio_rev <= 5) { - reg = 0x43; - padmix = 0; - } else { - reg = 0x52; - padmix = 5; - } - } else { - if (phy->rev >= 2 && phy->radio_rev == 8) { - reg = 0x43; - v = 0x10; - padmix = 2; - } else { - reg = 0x52; - v = 0x30; - padmix = 5; - } - } - if (value) - *value = v; - if (pad_mix_gain) - *pad_mix_gain = padmix; - - return reg; -} - -static void lo_measure_txctl_values(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - u16 reg, mask; - u16 trsw_rx, pga; - u16 radio_pctl_reg; - - static const u8 tx_bias_values[] = { - 0x09, 0x08, 0x0A, 0x01, 0x00, - 0x02, 0x05, 0x04, 0x06, - }; - static const u8 tx_magn_values[] = { - 0x70, 0x40, - }; - - if (!has_loopback_gain(phy)) { - radio_pctl_reg = 6; - trsw_rx = 2; - pga = 0; - } else { - int lb_gain; /* Loopback gain (in dB) */ - - trsw_rx = 0; - lb_gain = gphy->max_lb_gain / 2; - if (lb_gain > 10) { - radio_pctl_reg = 0; - pga = abs(10 - lb_gain) / 6; - pga = clamp_val(pga, 0, 15); - } else { - int cmp_val; - int tmp; - - pga = 0; - cmp_val = 0x24; - if ((phy->rev >= 2) && - (phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) - cmp_val = 0x3C; - tmp = lb_gain; - if ((10 - lb_gain) < cmp_val) - tmp = (10 - lb_gain); - if (tmp < 0) - tmp += 6; - else - tmp += 3; - cmp_val /= 4; - tmp /= 4; - if (tmp >= cmp_val) - radio_pctl_reg = cmp_val; - else - radio_pctl_reg = tmp; - } - } - b43_radio_maskset(dev, 0x43, 0xFFF0, radio_pctl_reg); - b43_gphy_set_baseband_attenuation(dev, 2); - - reg = lo_txctl_register_table(dev, &mask, NULL); - mask = ~mask; - b43_radio_mask(dev, reg, mask); - - if (has_tx_magnification(phy)) { - int i, j; - int feedthrough; - int min_feedth = 0xFFFF; - u8 tx_magn, tx_bias; - - for (i = 0; i < ARRAY_SIZE(tx_magn_values); i++) { - tx_magn = tx_magn_values[i]; - b43_radio_maskset(dev, 0x52, 0xFF0F, tx_magn); - for (j = 0; j < ARRAY_SIZE(tx_bias_values); j++) { - tx_bias = tx_bias_values[j]; - b43_radio_maskset(dev, 0x52, 0xFFF0, tx_bias); - feedthrough = - lo_measure_feedthrough(dev, 0, pga, - trsw_rx); - if (feedthrough < min_feedth) { - lo->tx_bias = tx_bias; - lo->tx_magn = tx_magn; - min_feedth = feedthrough; - } - if (lo->tx_bias == 0) - break; - } - b43_radio_write16(dev, 0x52, - (b43_radio_read16(dev, 0x52) - & 0xFF00) | lo->tx_bias | lo-> - tx_magn); - } - } else { - lo->tx_magn = 0; - lo->tx_bias = 0; - b43_radio_mask(dev, 0x52, 0xFFF0); /* TX bias == 0 */ - } - lo->txctl_measured_time = jiffies; -} - -static void lo_read_power_vector(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - int i; - u64 tmp; - u64 power_vector = 0; - - for (i = 0; i < 8; i += 2) { - tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x310 + i); - power_vector |= (tmp << (i * 8)); - /* Clear the vector on the device. */ - b43_shm_write16(dev, B43_SHM_SHARED, 0x310 + i, 0); - } - if (power_vector) - lo->power_vector = power_vector; - lo->pwr_vec_read_time = jiffies; -} - -/* 802.11/LO/GPHY/MeasuringGains */ -static void lo_measure_gain_values(struct b43_wldev *dev, - s16 max_rx_gain, int use_trsw_rx) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 tmp; - - if (max_rx_gain < 0) - max_rx_gain = 0; - - if (has_loopback_gain(phy)) { - int trsw_rx = 0; - int trsw_rx_gain; - - if (use_trsw_rx) { - trsw_rx_gain = gphy->trsw_rx_gain / 2; - if (max_rx_gain >= trsw_rx_gain) { - trsw_rx_gain = max_rx_gain - trsw_rx_gain; - trsw_rx = 0x20; - } - } else - trsw_rx_gain = max_rx_gain; - if (trsw_rx_gain < 9) { - gphy->lna_lod_gain = 0; - } else { - gphy->lna_lod_gain = 1; - trsw_rx_gain -= 8; - } - trsw_rx_gain = clamp_val(trsw_rx_gain, 0, 0x2D); - gphy->pga_gain = trsw_rx_gain / 3; - if (gphy->pga_gain >= 5) { - gphy->pga_gain -= 5; - gphy->lna_gain = 2; - } else - gphy->lna_gain = 0; - } else { - gphy->lna_gain = 0; - gphy->trsw_rx_gain = 0x20; - if (max_rx_gain >= 0x14) { - gphy->lna_lod_gain = 1; - gphy->pga_gain = 2; - } else if (max_rx_gain >= 0x12) { - gphy->lna_lod_gain = 1; - gphy->pga_gain = 1; - } else if (max_rx_gain >= 0xF) { - gphy->lna_lod_gain = 1; - gphy->pga_gain = 0; - } else { - gphy->lna_lod_gain = 0; - gphy->pga_gain = 0; - } - } - - tmp = b43_radio_read16(dev, 0x7A); - if (gphy->lna_lod_gain == 0) - tmp &= ~0x0008; - else - tmp |= 0x0008; - b43_radio_write16(dev, 0x7A, tmp); -} - -struct lo_g_saved_values { - u8 old_channel; - - /* Core registers */ - u16 reg_3F4; - u16 reg_3E2; - - /* PHY registers */ - u16 phy_lo_mask; - u16 phy_extg_01; - u16 phy_dacctl_hwpctl; - u16 phy_dacctl; - u16 phy_cck_14; - u16 phy_hpwr_tssictl; - u16 phy_analogover; - u16 phy_analogoverval; - u16 phy_rfover; - u16 phy_rfoverval; - u16 phy_classctl; - u16 phy_cck_3E; - u16 phy_crs0; - u16 phy_pgactl; - u16 phy_cck_2A; - u16 phy_syncctl; - u16 phy_cck_30; - u16 phy_cck_06; - - /* Radio registers */ - u16 radio_43; - u16 radio_7A; - u16 radio_52; -}; - -static void lo_measure_setup(struct b43_wldev *dev, - struct lo_g_saved_values *sav) -{ - struct ssb_sprom *sprom = &dev->dev->bus->sprom; - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - u16 tmp; - - if (b43_has_hardware_pctl(dev)) { - sav->phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); - sav->phy_extg_01 = b43_phy_read(dev, B43_PHY_EXTG(0x01)); - sav->phy_dacctl_hwpctl = b43_phy_read(dev, B43_PHY_DACCTL); - sav->phy_cck_14 = b43_phy_read(dev, B43_PHY_CCK(0x14)); - sav->phy_hpwr_tssictl = b43_phy_read(dev, B43_PHY_HPWR_TSSICTL); - - b43_phy_set(dev, B43_PHY_HPWR_TSSICTL, 0x100); - b43_phy_set(dev, B43_PHY_EXTG(0x01), 0x40); - b43_phy_set(dev, B43_PHY_DACCTL, 0x40); - b43_phy_set(dev, B43_PHY_CCK(0x14), 0x200); - } - if (phy->type == B43_PHYTYPE_B && - phy->radio_ver == 0x2050 && phy->radio_rev < 6) { - b43_phy_write(dev, B43_PHY_CCK(0x16), 0x410); - b43_phy_write(dev, B43_PHY_CCK(0x17), 0x820); - } - if (phy->rev >= 2) { - sav->phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); - sav->phy_analogoverval = - b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); - sav->phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER); - sav->phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); - sav->phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL); - sav->phy_cck_3E = b43_phy_read(dev, B43_PHY_CCK(0x3E)); - sav->phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0); - - b43_phy_mask(dev, B43_PHY_CLASSCTL, 0xFFFC); - b43_phy_mask(dev, B43_PHY_CRS0, 0x7FFF); - b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0003); - b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFC); - if (phy->type == B43_PHYTYPE_G) { - if ((phy->rev >= 7) && - (sprom->boardflags_lo & B43_BFL_EXTLNA)) { - b43_phy_write(dev, B43_PHY_RFOVER, 0x933); - } else { - b43_phy_write(dev, B43_PHY_RFOVER, 0x133); - } - } else { - b43_phy_write(dev, B43_PHY_RFOVER, 0); - } - b43_phy_write(dev, B43_PHY_CCK(0x3E), 0); - } - sav->reg_3F4 = b43_read16(dev, 0x3F4); - sav->reg_3E2 = b43_read16(dev, 0x3E2); - sav->radio_43 = b43_radio_read16(dev, 0x43); - sav->radio_7A = b43_radio_read16(dev, 0x7A); - sav->phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL); - sav->phy_cck_2A = b43_phy_read(dev, B43_PHY_CCK(0x2A)); - sav->phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL); - sav->phy_dacctl = b43_phy_read(dev, B43_PHY_DACCTL); - - if (!has_tx_magnification(phy)) { - sav->radio_52 = b43_radio_read16(dev, 0x52); - sav->radio_52 &= 0x00F0; - } - if (phy->type == B43_PHYTYPE_B) { - sav->phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30)); - sav->phy_cck_06 = b43_phy_read(dev, B43_PHY_CCK(0x06)); - b43_phy_write(dev, B43_PHY_CCK(0x30), 0x00FF); - b43_phy_write(dev, B43_PHY_CCK(0x06), 0x3F3F); - } else { - b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) - | 0x8000); - } - b43_write16(dev, 0x3F4, b43_read16(dev, 0x3F4) - & 0xF000); - - tmp = - (phy->type == B43_PHYTYPE_G) ? B43_PHY_LO_MASK : B43_PHY_CCK(0x2E); - b43_phy_write(dev, tmp, 0x007F); - - tmp = sav->phy_syncctl; - b43_phy_write(dev, B43_PHY_SYNCCTL, tmp & 0xFF7F); - tmp = sav->radio_7A; - b43_radio_write16(dev, 0x007A, tmp & 0xFFF0); - - b43_phy_write(dev, B43_PHY_CCK(0x2A), 0x8A3); - if (phy->type == B43_PHYTYPE_G || - (phy->type == B43_PHYTYPE_B && - phy->radio_ver == 0x2050 && phy->radio_rev >= 6)) { - b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1003); - } else - b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x0802); - if (phy->rev >= 2) - b43_dummy_transmission(dev, false, true); - b43_gphy_channel_switch(dev, 6, 0); - b43_radio_read16(dev, 0x51); /* dummy read */ - if (phy->type == B43_PHYTYPE_G) - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0); - - /* Re-measure the txctl values, if needed. */ - if (time_before(lo->txctl_measured_time, - jiffies - B43_LO_TXCTL_EXPIRE)) - lo_measure_txctl_values(dev); - - if (phy->type == B43_PHYTYPE_G && phy->rev >= 3) { - b43_phy_write(dev, B43_PHY_LO_MASK, 0xC078); - } else { - if (phy->type == B43_PHYTYPE_B) - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078); - else - b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); - } -} - -static void lo_measure_restore(struct b43_wldev *dev, - struct lo_g_saved_values *sav) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 tmp; - - if (phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_PGACTL, 0xE300); - tmp = (gphy->pga_gain << 8); - b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA0); - udelay(5); - b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA2); - udelay(2); - b43_phy_write(dev, B43_PHY_RFOVERVAL, tmp | 0xA3); - } else { - tmp = (gphy->pga_gain | 0xEFA0); - b43_phy_write(dev, B43_PHY_PGACTL, tmp); - } - if (phy->type == B43_PHYTYPE_G) { - if (phy->rev >= 3) - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0xC078); - else - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8078); - if (phy->rev >= 2) - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0202); - else - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x0101); - } - b43_write16(dev, 0x3F4, sav->reg_3F4); - b43_phy_write(dev, B43_PHY_PGACTL, sav->phy_pgactl); - b43_phy_write(dev, B43_PHY_CCK(0x2A), sav->phy_cck_2A); - b43_phy_write(dev, B43_PHY_SYNCCTL, sav->phy_syncctl); - b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl); - b43_radio_write16(dev, 0x43, sav->radio_43); - b43_radio_write16(dev, 0x7A, sav->radio_7A); - if (!has_tx_magnification(phy)) { - tmp = sav->radio_52; - b43_radio_maskset(dev, 0x52, 0xFF0F, tmp); - } - b43_write16(dev, 0x3E2, sav->reg_3E2); - if (phy->type == B43_PHYTYPE_B && - phy->radio_ver == 0x2050 && phy->radio_rev <= 5) { - b43_phy_write(dev, B43_PHY_CCK(0x30), sav->phy_cck_30); - b43_phy_write(dev, B43_PHY_CCK(0x06), sav->phy_cck_06); - } - if (phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_ANALOGOVER, sav->phy_analogover); - b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, - sav->phy_analogoverval); - b43_phy_write(dev, B43_PHY_CLASSCTL, sav->phy_classctl); - b43_phy_write(dev, B43_PHY_RFOVER, sav->phy_rfover); - b43_phy_write(dev, B43_PHY_RFOVERVAL, sav->phy_rfoverval); - b43_phy_write(dev, B43_PHY_CCK(0x3E), sav->phy_cck_3E); - b43_phy_write(dev, B43_PHY_CRS0, sav->phy_crs0); - } - if (b43_has_hardware_pctl(dev)) { - tmp = (sav->phy_lo_mask & 0xBFFF); - b43_phy_write(dev, B43_PHY_LO_MASK, tmp); - b43_phy_write(dev, B43_PHY_EXTG(0x01), sav->phy_extg_01); - b43_phy_write(dev, B43_PHY_DACCTL, sav->phy_dacctl_hwpctl); - b43_phy_write(dev, B43_PHY_CCK(0x14), sav->phy_cck_14); - b43_phy_write(dev, B43_PHY_HPWR_TSSICTL, sav->phy_hpwr_tssictl); - } - b43_gphy_channel_switch(dev, sav->old_channel, 1); -} - -struct b43_lo_g_statemachine { - int current_state; - int nr_measured; - int state_val_multiplier; - u16 lowest_feedth; - struct b43_loctl min_loctl; -}; - -/* Loop over each possible value in this state. */ -static int lo_probe_possible_loctls(struct b43_wldev *dev, - struct b43_loctl *probe_loctl, - struct b43_lo_g_statemachine *d) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_loctl test_loctl; - struct b43_loctl orig_loctl; - struct b43_loctl prev_loctl = { - .i = -100, - .q = -100, - }; - int i; - int begin, end; - int found_lower = 0; - u16 feedth; - - static const struct b43_loctl modifiers[] = { - {.i = 1,.q = 1,}, - {.i = 1,.q = 0,}, - {.i = 1,.q = -1,}, - {.i = 0,.q = -1,}, - {.i = -1,.q = -1,}, - {.i = -1,.q = 0,}, - {.i = -1,.q = 1,}, - {.i = 0,.q = 1,}, - }; - - if (d->current_state == 0) { - begin = 1; - end = 8; - } else if (d->current_state % 2 == 0) { - begin = d->current_state - 1; - end = d->current_state + 1; - } else { - begin = d->current_state - 2; - end = d->current_state + 2; - } - if (begin < 1) - begin += 8; - if (end > 8) - end -= 8; - - memcpy(&orig_loctl, probe_loctl, sizeof(struct b43_loctl)); - i = begin; - d->current_state = i; - while (1) { - B43_WARN_ON(!(i >= 1 && i <= 8)); - memcpy(&test_loctl, &orig_loctl, sizeof(struct b43_loctl)); - test_loctl.i += modifiers[i - 1].i * d->state_val_multiplier; - test_loctl.q += modifiers[i - 1].q * d->state_val_multiplier; - if ((test_loctl.i != prev_loctl.i || - test_loctl.q != prev_loctl.q) && - (abs(test_loctl.i) <= 16 && abs(test_loctl.q) <= 16)) { - b43_lo_write(dev, &test_loctl); - feedth = lo_measure_feedthrough(dev, gphy->lna_gain, - gphy->pga_gain, - gphy->trsw_rx_gain); - if (feedth < d->lowest_feedth) { - memcpy(probe_loctl, &test_loctl, - sizeof(struct b43_loctl)); - found_lower = 1; - d->lowest_feedth = feedth; - if ((d->nr_measured < 2) && - !has_loopback_gain(phy)) - break; - } - } - memcpy(&prev_loctl, &test_loctl, sizeof(prev_loctl)); - if (i == end) - break; - if (i == 8) - i = 1; - else - i++; - d->current_state = i; - } - - return found_lower; -} - -static void lo_probe_loctls_statemachine(struct b43_wldev *dev, - struct b43_loctl *loctl, - int *max_rx_gain) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_lo_g_statemachine d; - u16 feedth; - int found_lower; - struct b43_loctl probe_loctl; - int max_repeat = 1, repeat_cnt = 0; - - d.nr_measured = 0; - d.state_val_multiplier = 1; - if (has_loopback_gain(phy)) - d.state_val_multiplier = 3; - - memcpy(&d.min_loctl, loctl, sizeof(struct b43_loctl)); - if (has_loopback_gain(phy)) - max_repeat = 4; - do { - b43_lo_write(dev, &d.min_loctl); - feedth = lo_measure_feedthrough(dev, gphy->lna_gain, - gphy->pga_gain, - gphy->trsw_rx_gain); - if (feedth < 0x258) { - if (feedth >= 0x12C) - *max_rx_gain += 6; - else - *max_rx_gain += 3; - feedth = lo_measure_feedthrough(dev, gphy->lna_gain, - gphy->pga_gain, - gphy->trsw_rx_gain); - } - d.lowest_feedth = feedth; - - d.current_state = 0; - do { - B43_WARN_ON(! - (d.current_state >= 0 - && d.current_state <= 8)); - memcpy(&probe_loctl, &d.min_loctl, - sizeof(struct b43_loctl)); - found_lower = - lo_probe_possible_loctls(dev, &probe_loctl, &d); - if (!found_lower) - break; - if ((probe_loctl.i == d.min_loctl.i) && - (probe_loctl.q == d.min_loctl.q)) - break; - memcpy(&d.min_loctl, &probe_loctl, - sizeof(struct b43_loctl)); - d.nr_measured++; - } while (d.nr_measured < 24); - memcpy(loctl, &d.min_loctl, sizeof(struct b43_loctl)); - - if (has_loopback_gain(phy)) { - if (d.lowest_feedth > 0x1194) - *max_rx_gain -= 6; - else if (d.lowest_feedth < 0x5DC) - *max_rx_gain += 3; - if (repeat_cnt == 0) { - if (d.lowest_feedth <= 0x5DC) { - d.state_val_multiplier = 1; - repeat_cnt++; - } else - d.state_val_multiplier = 2; - } else if (repeat_cnt == 2) - d.state_val_multiplier = 1; - } - lo_measure_gain_values(dev, *max_rx_gain, - has_loopback_gain(phy)); - } while (++repeat_cnt < max_repeat); -} - -static -struct b43_lo_calib *b43_calibrate_lo_setting(struct b43_wldev *dev, - const struct b43_bbatt *bbatt, - const struct b43_rfatt *rfatt) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_loctl loctl = { - .i = 0, - .q = 0, - }; - int max_rx_gain; - struct b43_lo_calib *cal; - struct lo_g_saved_values uninitialized_var(saved_regs); - /* Values from the "TXCTL Register and Value Table" */ - u16 txctl_reg; - u16 txctl_value; - u16 pad_mix_gain; - - saved_regs.old_channel = phy->channel; - b43_mac_suspend(dev); - lo_measure_setup(dev, &saved_regs); - - txctl_reg = lo_txctl_register_table(dev, &txctl_value, &pad_mix_gain); - - b43_radio_maskset(dev, 0x43, 0xFFF0, rfatt->att); - b43_radio_maskset(dev, txctl_reg, ~txctl_value, (rfatt->with_padmix ? txctl_value :0)); - - max_rx_gain = rfatt->att * 2; - max_rx_gain += bbatt->att / 2; - if (rfatt->with_padmix) - max_rx_gain -= pad_mix_gain; - if (has_loopback_gain(phy)) - max_rx_gain += gphy->max_lb_gain; - lo_measure_gain_values(dev, max_rx_gain, - has_loopback_gain(phy)); - - b43_gphy_set_baseband_attenuation(dev, bbatt->att); - lo_probe_loctls_statemachine(dev, &loctl, &max_rx_gain); - - lo_measure_restore(dev, &saved_regs); - b43_mac_enable(dev); - - if (b43_debug(dev, B43_DBG_LO)) { - b43dbg(dev->wl, "LO: Calibrated for BB(%u), RF(%u,%u) " - "=> I=%d Q=%d\n", - bbatt->att, rfatt->att, rfatt->with_padmix, - loctl.i, loctl.q); - } - - cal = kmalloc(sizeof(*cal), GFP_KERNEL); - if (!cal) { - b43warn(dev->wl, "LO calib: out of memory\n"); - return NULL; - } - memcpy(&cal->bbatt, bbatt, sizeof(*bbatt)); - memcpy(&cal->rfatt, rfatt, sizeof(*rfatt)); - memcpy(&cal->ctl, &loctl, sizeof(loctl)); - cal->calib_time = jiffies; - INIT_LIST_HEAD(&cal->list); - - return cal; -} - -/* Get a calibrated LO setting for the given attenuation values. - * Might return a NULL pointer under OOM! */ -static -struct b43_lo_calib *b43_get_calib_lo_settings(struct b43_wldev *dev, - const struct b43_bbatt *bbatt, - const struct b43_rfatt *rfatt) -{ - struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; - struct b43_lo_calib *c; - - c = b43_find_lo_calib(lo, bbatt, rfatt); - if (c) - return c; - /* Not in the list of calibrated LO settings. - * Calibrate it now. */ - c = b43_calibrate_lo_setting(dev, bbatt, rfatt); - if (!c) - return NULL; - list_add(&c->list, &lo->calib_list); - - return c; -} - -void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - int i; - int rf_offset, bb_offset; - const struct b43_rfatt *rfatt; - const struct b43_bbatt *bbatt; - u64 power_vector; - bool table_changed = 0; - - BUILD_BUG_ON(B43_DC_LT_SIZE != 32); - B43_WARN_ON(lo->rfatt_list.len * lo->bbatt_list.len > 64); - - power_vector = lo->power_vector; - if (!update_all && !power_vector) - return; /* Nothing to do. */ - - /* Suspend the MAC now to avoid continuous suspend/enable - * cycles in the loop. */ - b43_mac_suspend(dev); - - for (i = 0; i < B43_DC_LT_SIZE * 2; i++) { - struct b43_lo_calib *cal; - int idx; - u16 val; - - if (!update_all && !(power_vector & (((u64)1ULL) << i))) - continue; - /* Update the table entry for this power_vector bit. - * The table rows are RFatt entries and columns are BBatt. */ - bb_offset = i / lo->rfatt_list.len; - rf_offset = i % lo->rfatt_list.len; - bbatt = &(lo->bbatt_list.list[bb_offset]); - rfatt = &(lo->rfatt_list.list[rf_offset]); - - cal = b43_calibrate_lo_setting(dev, bbatt, rfatt); - if (!cal) { - b43warn(dev->wl, "LO: Could not " - "calibrate DC table entry\n"); - continue; - } - /*FIXME: Is Q really in the low nibble? */ - val = (u8)(cal->ctl.q); - val |= ((u8)(cal->ctl.i)) << 4; - kfree(cal); - - /* Get the index into the hardware DC LT. */ - idx = i / 2; - /* Change the table in memory. */ - if (i % 2) { - /* Change the high byte. */ - lo->dc_lt[idx] = (lo->dc_lt[idx] & 0x00FF) - | ((val & 0x00FF) << 8); - } else { - /* Change the low byte. */ - lo->dc_lt[idx] = (lo->dc_lt[idx] & 0xFF00) - | (val & 0x00FF); - } - table_changed = 1; - } - if (table_changed) { - /* The table changed in memory. Update the hardware table. */ - for (i = 0; i < B43_DC_LT_SIZE; i++) - b43_phy_write(dev, 0x3A0 + i, lo->dc_lt[i]); - } - b43_mac_enable(dev); -} - -/* Fixup the RF attenuation value for the case where we are - * using the PAD mixer. */ -static inline void b43_lo_fixup_rfatt(struct b43_rfatt *rf) -{ - if (!rf->with_padmix) - return; - if ((rf->att != 1) && (rf->att != 2) && (rf->att != 3)) - rf->att = 4; -} - -void b43_lo_g_adjust(struct b43_wldev *dev) -{ - struct b43_phy_g *gphy = dev->phy.g; - struct b43_lo_calib *cal; - struct b43_rfatt rf; - - memcpy(&rf, &gphy->rfatt, sizeof(rf)); - b43_lo_fixup_rfatt(&rf); - - cal = b43_get_calib_lo_settings(dev, &gphy->bbatt, &rf); - if (!cal) - return; - b43_lo_write(dev, &cal->ctl); -} - -void b43_lo_g_adjust_to(struct b43_wldev *dev, - u16 rfatt, u16 bbatt, u16 tx_control) -{ - struct b43_rfatt rf; - struct b43_bbatt bb; - struct b43_lo_calib *cal; - - memset(&rf, 0, sizeof(rf)); - memset(&bb, 0, sizeof(bb)); - rf.att = rfatt; - bb.att = bbatt; - b43_lo_fixup_rfatt(&rf); - cal = b43_get_calib_lo_settings(dev, &bb, &rf); - if (!cal) - return; - b43_lo_write(dev, &cal->ctl); -} - -/* Periodic LO maintanance work */ -void b43_lo_g_maintanance_work(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - unsigned long now; - unsigned long expire; - struct b43_lo_calib *cal, *tmp; - bool current_item_expired = 0; - bool hwpctl; - - if (!lo) - return; - now = jiffies; - hwpctl = b43_has_hardware_pctl(dev); - - if (hwpctl) { - /* Read the power vector and update it, if needed. */ - expire = now - B43_LO_PWRVEC_EXPIRE; - if (time_before(lo->pwr_vec_read_time, expire)) { - lo_read_power_vector(dev); - b43_gphy_dc_lt_init(dev, 0); - } - //FIXME Recalc the whole DC table from time to time? - } - - if (hwpctl) - return; - /* Search for expired LO settings. Remove them. - * Recalibrate the current setting, if expired. */ - expire = now - B43_LO_CALIB_EXPIRE; - list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { - if (!time_before(cal->calib_time, expire)) - continue; - /* This item expired. */ - if (b43_compare_bbatt(&cal->bbatt, &gphy->bbatt) && - b43_compare_rfatt(&cal->rfatt, &gphy->rfatt)) { - B43_WARN_ON(current_item_expired); - current_item_expired = 1; - } - if (b43_debug(dev, B43_DBG_LO)) { - b43dbg(dev->wl, "LO: Item BB(%u), RF(%u,%u), " - "I=%d, Q=%d expired\n", - cal->bbatt.att, cal->rfatt.att, - cal->rfatt.with_padmix, - cal->ctl.i, cal->ctl.q); - } - list_del(&cal->list); - kfree(cal); - } - if (current_item_expired || unlikely(list_empty(&lo->calib_list))) { - /* Recalibrate currently used LO setting. */ - if (b43_debug(dev, B43_DBG_LO)) - b43dbg(dev->wl, "LO: Recalibrating current LO setting\n"); - cal = b43_calibrate_lo_setting(dev, &gphy->bbatt, &gphy->rfatt); - if (cal) { - list_add(&cal->list, &lo->calib_list); - b43_lo_write(dev, &cal->ctl); - } else - b43warn(dev->wl, "Failed to recalibrate current LO setting\n"); - } -} - -void b43_lo_g_cleanup(struct b43_wldev *dev) -{ - struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; - struct b43_lo_calib *cal, *tmp; - - if (!lo) - return; - list_for_each_entry_safe(cal, tmp, &lo->calib_list, list) { - list_del(&cal->list); - kfree(cal); - } -} - -/* LO Initialization */ -void b43_lo_g_init(struct b43_wldev *dev) -{ - if (b43_has_hardware_pctl(dev)) { - lo_read_power_vector(dev); - b43_gphy_dc_lt_init(dev, 1); - } -} diff --git a/drivers/net/wireless/b43/lo.h b/drivers/net/wireless/b43/lo.h deleted file mode 100644 index 3b27e20eff80..000000000000 --- a/drivers/net/wireless/b43/lo.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef B43_LO_H_ -#define B43_LO_H_ - -/* G-PHY Local Oscillator */ - -#include "phy_g.h" - -struct b43_wldev; - -/* Local Oscillator control value-pair. */ -struct b43_loctl { - /* Control values. */ - s8 i; - s8 q; -}; -/* Debugging: Poison value for i and q values. */ -#define B43_LOCTL_POISON 111 - -/* This struct holds calibrated LO settings for a set of - * Baseband and RF attenuation settings. */ -struct b43_lo_calib { - /* The set of attenuation values this set of LO - * control values is calibrated for. */ - struct b43_bbatt bbatt; - struct b43_rfatt rfatt; - /* The set of control values for the LO. */ - struct b43_loctl ctl; - /* The time when these settings were calibrated (in jiffies) */ - unsigned long calib_time; - /* List. */ - struct list_head list; -}; - -/* Size of the DC Lookup Table in 16bit words. */ -#define B43_DC_LT_SIZE 32 - -/* Local Oscillator calibration information */ -struct b43_txpower_lo_control { - /* Lists of RF and BB attenuation values for this device. - * Used for building hardware power control tables. */ - struct b43_rfatt_list rfatt_list; - struct b43_bbatt_list bbatt_list; - - /* The DC Lookup Table is cached in memory here. - * Note that this is only used for Hardware Power Control. */ - u16 dc_lt[B43_DC_LT_SIZE]; - - /* List of calibrated control values (struct b43_lo_calib). */ - struct list_head calib_list; - /* Last time the power vector was read (jiffies). */ - unsigned long pwr_vec_read_time; - /* Last time the txctl values were measured (jiffies). */ - unsigned long txctl_measured_time; - - /* Current TX Bias value */ - u8 tx_bias; - /* Current TX Magnification Value (if used by the device) */ - u8 tx_magn; - - /* Saved device PowerVector */ - u64 power_vector; -}; - -/* Calibration expire timeouts. - * Timeouts must be multiple of 15 seconds. To make sure - * the item really expired when the 15 second timer hits, we - * subtract two additional seconds from the timeout. */ -#define B43_LO_CALIB_EXPIRE (HZ * (30 - 2)) -#define B43_LO_PWRVEC_EXPIRE (HZ * (30 - 2)) -#define B43_LO_TXCTL_EXPIRE (HZ * (180 - 4)) - - -/* Adjust the Local Oscillator to the saved attenuation - * and txctl values. - */ -void b43_lo_g_adjust(struct b43_wldev *dev); -/* Adjust to specific values. */ -void b43_lo_g_adjust_to(struct b43_wldev *dev, - u16 rfatt, u16 bbatt, u16 tx_control); - -void b43_gphy_dc_lt_init(struct b43_wldev *dev, bool update_all); - -void b43_lo_g_maintanance_work(struct b43_wldev *dev); -void b43_lo_g_cleanup(struct b43_wldev *dev); -void b43_lo_g_init(struct b43_wldev *dev); - -#endif /* B43_LO_H_ */ diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c deleted file mode 100644 index d6056347b6bd..000000000000 --- a/drivers/net/wireless/b43/main.c +++ /dev/null @@ -1,5100 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Copyright (c) 2005 Martin Langer - Copyright (c) 2005 Stefano Brivio - Copyright (c) 2005-2009 Michael Buesch - Copyright (c) 2005 Danny van Dyk - Copyright (c) 2005 Andreas Jaggi - - SDIO support - Copyright (c) 2009 Albert Herranz - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "b43.h" -#include "main.h" -#include "debugfs.h" -#include "phy_common.h" -#include "phy_g.h" -#include "phy_n.h" -#include "dma.h" -#include "pio.h" -#include "sysfs.h" -#include "xmit.h" -#include "lo.h" -#include "pcmcia.h" -#include "sdio.h" -#include - -MODULE_DESCRIPTION("Broadcom B43 wireless driver"); -MODULE_AUTHOR("Martin Langer"); -MODULE_AUTHOR("Stefano Brivio"); -MODULE_AUTHOR("Michael Buesch"); -MODULE_AUTHOR("Gábor Stefanik"); -MODULE_LICENSE("GPL"); - -MODULE_FIRMWARE(B43_SUPPORTED_FIRMWARE_ID); - - -static int modparam_bad_frames_preempt; -module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); -MODULE_PARM_DESC(bad_frames_preempt, - "enable(1) / disable(0) Bad Frames Preemption"); - -static char modparam_fwpostfix[16]; -module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); -MODULE_PARM_DESC(fwpostfix, "Postfix for the .fw files to load."); - -static int modparam_hwpctl; -module_param_named(hwpctl, modparam_hwpctl, int, 0444); -MODULE_PARM_DESC(hwpctl, "Enable hardware-side power control (default off)"); - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, int, 0444); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -static int modparam_hwtkip; -module_param_named(hwtkip, modparam_hwtkip, int, 0444); -MODULE_PARM_DESC(hwtkip, "Enable hardware tkip."); - -static int modparam_qos = 1; -module_param_named(qos, modparam_qos, int, 0444); -MODULE_PARM_DESC(qos, "Enable QOS support (default on)"); - -static int modparam_btcoex = 1; -module_param_named(btcoex, modparam_btcoex, int, 0444); -MODULE_PARM_DESC(btcoex, "Enable Bluetooth coexistence (default on)"); - -int b43_modparam_verbose = B43_VERBOSITY_DEFAULT; -module_param_named(verbose, b43_modparam_verbose, int, 0644); -MODULE_PARM_DESC(verbose, "Log message verbosity: 0=error, 1=warn, 2=info(default), 3=debug"); - -int b43_modparam_pio = B43_PIO_DEFAULT; -module_param_named(pio, b43_modparam_pio, int, 0644); -MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO"); - -static const struct ssb_device_id b43_ssb_tbl[] = { - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 5), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 6), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 7), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 9), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 10), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 11), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 13), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 15), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 16), - SSB_DEVTABLE_END -}; - -MODULE_DEVICE_TABLE(ssb, b43_ssb_tbl); - -/* Channel and ratetables are shared for all devices. - * They can't be const, because ieee80211 puts some precalculated - * data in there. This data is the same for all devices, so we don't - * get concurrency issues */ -#define RATETAB_ENT(_rateid, _flags) \ - { \ - .bitrate = B43_RATE_TO_BASE100KBPS(_rateid), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ - } - -/* - * NOTE: When changing this, sync with xmit.c's - * b43_plcp_get_bitrate_idx_* functions! - */ -static struct ieee80211_rate __b43_ratetable[] = { - RATETAB_ENT(B43_CCK_RATE_1MB, 0), - RATETAB_ENT(B43_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(B43_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(B43_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(B43_OFDM_RATE_6MB, 0), - RATETAB_ENT(B43_OFDM_RATE_9MB, 0), - RATETAB_ENT(B43_OFDM_RATE_12MB, 0), - RATETAB_ENT(B43_OFDM_RATE_18MB, 0), - RATETAB_ENT(B43_OFDM_RATE_24MB, 0), - RATETAB_ENT(B43_OFDM_RATE_36MB, 0), - RATETAB_ENT(B43_OFDM_RATE_48MB, 0), - RATETAB_ENT(B43_OFDM_RATE_54MB, 0), -}; - -#define b43_a_ratetable (__b43_ratetable + 4) -#define b43_a_ratetable_size 8 -#define b43_b_ratetable (__b43_ratetable + 0) -#define b43_b_ratetable_size 4 -#define b43_g_ratetable (__b43_ratetable + 0) -#define b43_g_ratetable_size 12 - -#define CHAN4G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} -static struct ieee80211_channel b43_2ghz_chantable[] = { - CHAN4G(1, 2412, 0), - CHAN4G(2, 2417, 0), - CHAN4G(3, 2422, 0), - CHAN4G(4, 2427, 0), - CHAN4G(5, 2432, 0), - CHAN4G(6, 2437, 0), - CHAN4G(7, 2442, 0), - CHAN4G(8, 2447, 0), - CHAN4G(9, 2452, 0), - CHAN4G(10, 2457, 0), - CHAN4G(11, 2462, 0), - CHAN4G(12, 2467, 0), - CHAN4G(13, 2472, 0), - CHAN4G(14, 2484, 0), -}; -#undef CHAN4G - -#define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = 5000 + (5 * (_channel)), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} -static struct ieee80211_channel b43_5ghz_nphy_chantable[] = { - CHAN5G(32, 0), CHAN5G(34, 0), - CHAN5G(36, 0), CHAN5G(38, 0), - CHAN5G(40, 0), CHAN5G(42, 0), - CHAN5G(44, 0), CHAN5G(46, 0), - CHAN5G(48, 0), CHAN5G(50, 0), - CHAN5G(52, 0), CHAN5G(54, 0), - CHAN5G(56, 0), CHAN5G(58, 0), - CHAN5G(60, 0), CHAN5G(62, 0), - CHAN5G(64, 0), CHAN5G(66, 0), - CHAN5G(68, 0), CHAN5G(70, 0), - CHAN5G(72, 0), CHAN5G(74, 0), - CHAN5G(76, 0), CHAN5G(78, 0), - CHAN5G(80, 0), CHAN5G(82, 0), - CHAN5G(84, 0), CHAN5G(86, 0), - CHAN5G(88, 0), CHAN5G(90, 0), - CHAN5G(92, 0), CHAN5G(94, 0), - CHAN5G(96, 0), CHAN5G(98, 0), - CHAN5G(100, 0), CHAN5G(102, 0), - CHAN5G(104, 0), CHAN5G(106, 0), - CHAN5G(108, 0), CHAN5G(110, 0), - CHAN5G(112, 0), CHAN5G(114, 0), - CHAN5G(116, 0), CHAN5G(118, 0), - CHAN5G(120, 0), CHAN5G(122, 0), - CHAN5G(124, 0), CHAN5G(126, 0), - CHAN5G(128, 0), CHAN5G(130, 0), - CHAN5G(132, 0), CHAN5G(134, 0), - CHAN5G(136, 0), CHAN5G(138, 0), - CHAN5G(140, 0), CHAN5G(142, 0), - CHAN5G(144, 0), CHAN5G(145, 0), - CHAN5G(146, 0), CHAN5G(147, 0), - CHAN5G(148, 0), CHAN5G(149, 0), - CHAN5G(150, 0), CHAN5G(151, 0), - CHAN5G(152, 0), CHAN5G(153, 0), - CHAN5G(154, 0), CHAN5G(155, 0), - CHAN5G(156, 0), CHAN5G(157, 0), - CHAN5G(158, 0), CHAN5G(159, 0), - CHAN5G(160, 0), CHAN5G(161, 0), - CHAN5G(162, 0), CHAN5G(163, 0), - CHAN5G(164, 0), CHAN5G(165, 0), - CHAN5G(166, 0), CHAN5G(168, 0), - CHAN5G(170, 0), CHAN5G(172, 0), - CHAN5G(174, 0), CHAN5G(176, 0), - CHAN5G(178, 0), CHAN5G(180, 0), - CHAN5G(182, 0), CHAN5G(184, 0), - CHAN5G(186, 0), CHAN5G(188, 0), - CHAN5G(190, 0), CHAN5G(192, 0), - CHAN5G(194, 0), CHAN5G(196, 0), - CHAN5G(198, 0), CHAN5G(200, 0), - CHAN5G(202, 0), CHAN5G(204, 0), - CHAN5G(206, 0), CHAN5G(208, 0), - CHAN5G(210, 0), CHAN5G(212, 0), - CHAN5G(214, 0), CHAN5G(216, 0), - CHAN5G(218, 0), CHAN5G(220, 0), - CHAN5G(222, 0), CHAN5G(224, 0), - CHAN5G(226, 0), CHAN5G(228, 0), -}; - -static struct ieee80211_channel b43_5ghz_aphy_chantable[] = { - CHAN5G(34, 0), CHAN5G(36, 0), - CHAN5G(38, 0), CHAN5G(40, 0), - CHAN5G(42, 0), CHAN5G(44, 0), - CHAN5G(46, 0), CHAN5G(48, 0), - CHAN5G(52, 0), CHAN5G(56, 0), - CHAN5G(60, 0), CHAN5G(64, 0), - CHAN5G(100, 0), CHAN5G(104, 0), - CHAN5G(108, 0), CHAN5G(112, 0), - CHAN5G(116, 0), CHAN5G(120, 0), - CHAN5G(124, 0), CHAN5G(128, 0), - CHAN5G(132, 0), CHAN5G(136, 0), - CHAN5G(140, 0), CHAN5G(149, 0), - CHAN5G(153, 0), CHAN5G(157, 0), - CHAN5G(161, 0), CHAN5G(165, 0), - CHAN5G(184, 0), CHAN5G(188, 0), - CHAN5G(192, 0), CHAN5G(196, 0), - CHAN5G(200, 0), CHAN5G(204, 0), - CHAN5G(208, 0), CHAN5G(212, 0), - CHAN5G(216, 0), -}; -#undef CHAN5G - -static struct ieee80211_supported_band b43_band_5GHz_nphy = { - .band = IEEE80211_BAND_5GHZ, - .channels = b43_5ghz_nphy_chantable, - .n_channels = ARRAY_SIZE(b43_5ghz_nphy_chantable), - .bitrates = b43_a_ratetable, - .n_bitrates = b43_a_ratetable_size, -}; - -static struct ieee80211_supported_band b43_band_5GHz_aphy = { - .band = IEEE80211_BAND_5GHZ, - .channels = b43_5ghz_aphy_chantable, - .n_channels = ARRAY_SIZE(b43_5ghz_aphy_chantable), - .bitrates = b43_a_ratetable, - .n_bitrates = b43_a_ratetable_size, -}; - -static struct ieee80211_supported_band b43_band_2GHz = { - .band = IEEE80211_BAND_2GHZ, - .channels = b43_2ghz_chantable, - .n_channels = ARRAY_SIZE(b43_2ghz_chantable), - .bitrates = b43_g_ratetable, - .n_bitrates = b43_g_ratetable_size, -}; - -static void b43_wireless_core_exit(struct b43_wldev *dev); -static int b43_wireless_core_init(struct b43_wldev *dev); -static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev); -static int b43_wireless_core_start(struct b43_wldev *dev); - -static int b43_ratelimit(struct b43_wl *wl) -{ - if (!wl || !wl->current_dev) - return 1; - if (b43_status(wl->current_dev) < B43_STAT_STARTED) - return 1; - /* We are up and running. - * Ratelimit the messages to avoid DoS over the net. */ - return net_ratelimit(); -} - -void b43info(struct b43_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (b43_modparam_verbose < B43_VERBOSITY_INFO) - return; - if (!b43_ratelimit(wl)) - return; - va_start(args, fmt); - printk(KERN_INFO "b43-%s: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -void b43err(struct b43_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (b43_modparam_verbose < B43_VERBOSITY_ERROR) - return; - if (!b43_ratelimit(wl)) - return; - va_start(args, fmt); - printk(KERN_ERR "b43-%s ERROR: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -void b43warn(struct b43_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (b43_modparam_verbose < B43_VERBOSITY_WARN) - return; - if (!b43_ratelimit(wl)) - return; - va_start(args, fmt); - printk(KERN_WARNING "b43-%s warning: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -void b43dbg(struct b43_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) - return; - va_start(args, fmt); - printk(KERN_DEBUG "b43-%s debug: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -static void b43_ram_write(struct b43_wldev *dev, u16 offset, u32 val) -{ - u32 macctl; - - B43_WARN_ON(offset % 4 != 0); - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - if (macctl & B43_MACCTL_BE) - val = swab32(val); - - b43_write32(dev, B43_MMIO_RAM_CONTROL, offset); - mmiowb(); - b43_write32(dev, B43_MMIO_RAM_DATA, val); -} - -static inline void b43_shm_control_word(struct b43_wldev *dev, - u16 routing, u16 offset) -{ - u32 control; - - /* "offset" is the WORD offset. */ - control = routing; - control <<= 16; - control |= offset; - b43_write32(dev, B43_MMIO_SHM_CONTROL, control); -} - -u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset) -{ - u32 ret; - - if (routing == B43_SHM_SHARED) { - B43_WARN_ON(offset & 0x0001); - if (offset & 0x0003) { - /* Unaligned access */ - b43_shm_control_word(dev, routing, offset >> 2); - ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); - b43_shm_control_word(dev, routing, (offset >> 2) + 1); - ret |= ((u32)b43_read16(dev, B43_MMIO_SHM_DATA)) << 16; - - goto out; - } - offset >>= 2; - } - b43_shm_control_word(dev, routing, offset); - ret = b43_read32(dev, B43_MMIO_SHM_DATA); -out: - return ret; -} - -u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset) -{ - u16 ret; - - if (routing == B43_SHM_SHARED) { - B43_WARN_ON(offset & 0x0001); - if (offset & 0x0003) { - /* Unaligned access */ - b43_shm_control_word(dev, routing, offset >> 2); - ret = b43_read16(dev, B43_MMIO_SHM_DATA_UNALIGNED); - - goto out; - } - offset >>= 2; - } - b43_shm_control_word(dev, routing, offset); - ret = b43_read16(dev, B43_MMIO_SHM_DATA); -out: - return ret; -} - -void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value) -{ - if (routing == B43_SHM_SHARED) { - B43_WARN_ON(offset & 0x0001); - if (offset & 0x0003) { - /* Unaligned access */ - b43_shm_control_word(dev, routing, offset >> 2); - b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, - value & 0xFFFF); - b43_shm_control_word(dev, routing, (offset >> 2) + 1); - b43_write16(dev, B43_MMIO_SHM_DATA, - (value >> 16) & 0xFFFF); - return; - } - offset >>= 2; - } - b43_shm_control_word(dev, routing, offset); - b43_write32(dev, B43_MMIO_SHM_DATA, value); -} - -void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value) -{ - if (routing == B43_SHM_SHARED) { - B43_WARN_ON(offset & 0x0001); - if (offset & 0x0003) { - /* Unaligned access */ - b43_shm_control_word(dev, routing, offset >> 2); - b43_write16(dev, B43_MMIO_SHM_DATA_UNALIGNED, value); - return; - } - offset >>= 2; - } - b43_shm_control_word(dev, routing, offset); - b43_write16(dev, B43_MMIO_SHM_DATA, value); -} - -/* Read HostFlags */ -u64 b43_hf_read(struct b43_wldev *dev) -{ - u64 ret; - - ret = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI); - ret <<= 16; - ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI); - ret <<= 16; - ret |= b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO); - - return ret; -} - -/* Write HostFlags */ -void b43_hf_write(struct b43_wldev *dev, u64 value) -{ - u16 lo, mi, hi; - - lo = (value & 0x00000000FFFFULL); - mi = (value & 0x0000FFFF0000ULL) >> 16; - hi = (value & 0xFFFF00000000ULL) >> 32; - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO, lo); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFMI, mi); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFHI, hi); -} - -/* Read the firmware capabilities bitmask (Opensource firmware only) */ -static u16 b43_fwcapa_read(struct b43_wldev *dev) -{ - B43_WARN_ON(!dev->fw.opensource); - return b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_FWCAPA); -} - -void b43_tsf_read(struct b43_wldev *dev, u64 *tsf) -{ - u32 low, high; - - B43_WARN_ON(dev->dev->id.revision < 3); - - /* The hardware guarantees us an atomic read, if we - * read the low register first. */ - low = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_LOW); - high = b43_read32(dev, B43_MMIO_REV3PLUS_TSF_HIGH); - - *tsf = high; - *tsf <<= 32; - *tsf |= low; -} - -static void b43_time_lock(struct b43_wldev *dev) -{ - u32 macctl; - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl |= B43_MACCTL_TBTTHOLD; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - /* Commit the write */ - b43_read32(dev, B43_MMIO_MACCTL); -} - -static void b43_time_unlock(struct b43_wldev *dev) -{ - u32 macctl; - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_TBTTHOLD; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - /* Commit the write */ - b43_read32(dev, B43_MMIO_MACCTL); -} - -static void b43_tsf_write_locked(struct b43_wldev *dev, u64 tsf) -{ - u32 low, high; - - B43_WARN_ON(dev->dev->id.revision < 3); - - low = tsf; - high = (tsf >> 32); - /* The hardware guarantees us an atomic write, if we - * write the low register first. */ - b43_write32(dev, B43_MMIO_REV3PLUS_TSF_LOW, low); - mmiowb(); - b43_write32(dev, B43_MMIO_REV3PLUS_TSF_HIGH, high); - mmiowb(); -} - -void b43_tsf_write(struct b43_wldev *dev, u64 tsf) -{ - b43_time_lock(dev); - b43_tsf_write_locked(dev, tsf); - b43_time_unlock(dev); -} - -static -void b43_macfilter_set(struct b43_wldev *dev, u16 offset, const u8 *mac) -{ - static const u8 zero_addr[ETH_ALEN] = { 0 }; - u16 data; - - if (!mac) - mac = zero_addr; - - offset |= 0x0020; - b43_write16(dev, B43_MMIO_MACFILTER_CONTROL, offset); - - data = mac[0]; - data |= mac[1] << 8; - b43_write16(dev, B43_MMIO_MACFILTER_DATA, data); - data = mac[2]; - data |= mac[3] << 8; - b43_write16(dev, B43_MMIO_MACFILTER_DATA, data); - data = mac[4]; - data |= mac[5] << 8; - b43_write16(dev, B43_MMIO_MACFILTER_DATA, data); -} - -static void b43_write_mac_bssid_templates(struct b43_wldev *dev) -{ - const u8 *mac; - const u8 *bssid; - u8 mac_bssid[ETH_ALEN * 2]; - int i; - u32 tmp; - - bssid = dev->wl->bssid; - mac = dev->wl->mac_addr; - - b43_macfilter_set(dev, B43_MACFILTER_BSSID, bssid); - - memcpy(mac_bssid, mac, ETH_ALEN); - memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); - - /* Write our MAC address and BSSID to template ram */ - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) { - tmp = (u32) (mac_bssid[i + 0]); - tmp |= (u32) (mac_bssid[i + 1]) << 8; - tmp |= (u32) (mac_bssid[i + 2]) << 16; - tmp |= (u32) (mac_bssid[i + 3]) << 24; - b43_ram_write(dev, 0x20 + i, tmp); - } -} - -static void b43_upload_card_macaddress(struct b43_wldev *dev) -{ - b43_write_mac_bssid_templates(dev); - b43_macfilter_set(dev, B43_MACFILTER_SELF, dev->wl->mac_addr); -} - -static void b43_set_slot_time(struct b43_wldev *dev, u16 slot_time) -{ - /* slot_time is in usec. */ - /* This test used to exit for all but a G PHY. */ - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) - return; - b43_write16(dev, B43_MMIO_IFSSLOT, 510 + slot_time); - /* Shared memory location 0x0010 is the slot time and should be - * set to slot_time; however, this register is initially 0 and changing - * the value adversely affects the transmit rate for BCM4311 - * devices. Until this behavior is unterstood, delete this step - * - * b43_shm_write16(dev, B43_SHM_SHARED, 0x0010, slot_time); - */ -} - -static void b43_short_slot_timing_enable(struct b43_wldev *dev) -{ - b43_set_slot_time(dev, 9); -} - -static void b43_short_slot_timing_disable(struct b43_wldev *dev) -{ - b43_set_slot_time(dev, 20); -} - -/* DummyTransmission function, as documented on - * http://bcm-v4.sipsolutions.net/802.11/DummyTransmission - */ -void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on) -{ - struct b43_phy *phy = &dev->phy; - unsigned int i, max_loop; - u16 value; - u32 buffer[5] = { - 0x00000000, - 0x00D40000, - 0x00000000, - 0x01000000, - 0x00000000, - }; - - if (ofdm) { - max_loop = 0x1E; - buffer[0] = 0x000201CC; - } else { - max_loop = 0xFA; - buffer[0] = 0x000B846E; - } - - for (i = 0; i < 5; i++) - b43_ram_write(dev, i * 4, buffer[i]); - - b43_write16(dev, 0x0568, 0x0000); - if (dev->dev->id.revision < 11) - b43_write16(dev, 0x07C0, 0x0000); - else - b43_write16(dev, 0x07C0, 0x0100); - value = (ofdm ? 0x41 : 0x40); - b43_write16(dev, 0x050C, value); - if ((phy->type == B43_PHYTYPE_N) || (phy->type == B43_PHYTYPE_LP)) - b43_write16(dev, 0x0514, 0x1A02); - b43_write16(dev, 0x0508, 0x0000); - b43_write16(dev, 0x050A, 0x0000); - b43_write16(dev, 0x054C, 0x0000); - b43_write16(dev, 0x056A, 0x0014); - b43_write16(dev, 0x0568, 0x0826); - b43_write16(dev, 0x0500, 0x0000); - if (!pa_on && (phy->type == B43_PHYTYPE_N)) { - //SPEC TODO - } - - switch (phy->type) { - case B43_PHYTYPE_N: - b43_write16(dev, 0x0502, 0x00D0); - break; - case B43_PHYTYPE_LP: - b43_write16(dev, 0x0502, 0x0050); - break; - default: - b43_write16(dev, 0x0502, 0x0030); - } - - if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) - b43_radio_write16(dev, 0x0051, 0x0017); - for (i = 0x00; i < max_loop; i++) { - value = b43_read16(dev, 0x050E); - if (value & 0x0080) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = b43_read16(dev, 0x050E); - if (value & 0x0400) - break; - udelay(10); - } - for (i = 0x00; i < 0x19; i++) { - value = b43_read16(dev, 0x0690); - if (!(value & 0x0100)) - break; - udelay(10); - } - if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) - b43_radio_write16(dev, 0x0051, 0x0037); -} - -static void key_write(struct b43_wldev *dev, - u8 index, u8 algorithm, const u8 *key) -{ - unsigned int i; - u32 offset; - u16 value; - u16 kidx; - - /* Key index/algo block */ - kidx = b43_kidx_to_fw(dev, index); - value = ((kidx << 4) | algorithm); - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_KEYIDXBLOCK + (kidx * 2), value); - - /* Write the key to the Key Table Pointer offset */ - offset = dev->ktp + (index * B43_SEC_KEYSIZE); - for (i = 0; i < B43_SEC_KEYSIZE; i += 2) { - value = key[i]; - value |= (u16) (key[i + 1]) << 8; - b43_shm_write16(dev, B43_SHM_SHARED, offset + i, value); - } -} - -static void keymac_write(struct b43_wldev *dev, u8 index, const u8 *addr) -{ - u32 addrtmp[2] = { 0, 0, }; - u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; - - if (b43_new_kidx_api(dev)) - pairwise_keys_start = B43_NR_GROUP_KEYS; - - B43_WARN_ON(index < pairwise_keys_start); - /* We have four default TX keys and possibly four default RX keys. - * Physical mac 0 is mapped to physical key 4 or 8, depending - * on the firmware version. - * So we must adjust the index here. - */ - index -= pairwise_keys_start; - B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS); - - if (addr) { - addrtmp[0] = addr[0]; - addrtmp[0] |= ((u32) (addr[1]) << 8); - addrtmp[0] |= ((u32) (addr[2]) << 16); - addrtmp[0] |= ((u32) (addr[3]) << 24); - addrtmp[1] = addr[4]; - addrtmp[1] |= ((u32) (addr[5]) << 8); - } - - /* Receive match transmitter address (RCMTA) mechanism */ - b43_shm_write32(dev, B43_SHM_RCMTA, - (index * 2) + 0, addrtmp[0]); - b43_shm_write16(dev, B43_SHM_RCMTA, - (index * 2) + 1, addrtmp[1]); -} - -/* The ucode will use phase1 key with TEK key to decrypt rx packets. - * When a packet is received, the iv32 is checked. - * - if it doesn't the packet is returned without modification (and software - * decryption can be done). That's what happen when iv16 wrap. - * - if it does, the rc4 key is computed, and decryption is tried. - * Either it will success and B43_RX_MAC_DEC is returned, - * either it fails and B43_RX_MAC_DEC|B43_RX_MAC_DECERR is returned - * and the packet is not usable (it got modified by the ucode). - * So in order to never have B43_RX_MAC_DECERR, we should provide - * a iv32 and phase1key that match. Because we drop packets in case of - * B43_RX_MAC_DECERR, if we have a correct iv32 but a wrong phase1key, all - * packets will be lost without higher layer knowing (ie no resync possible - * until next wrap). - * - * NOTE : this should support 50 key like RCMTA because - * (B43_SHM_SH_KEYIDXBLOCK - B43_SHM_SH_TKIPTSCTTAK)/14 = 50 - */ -static void rx_tkip_phase1_write(struct b43_wldev *dev, u8 index, u32 iv32, - u16 *phase1key) -{ - unsigned int i; - u32 offset; - u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; - - if (!modparam_hwtkip) - return; - - if (b43_new_kidx_api(dev)) - pairwise_keys_start = B43_NR_GROUP_KEYS; - - B43_WARN_ON(index < pairwise_keys_start); - /* We have four default TX keys and possibly four default RX keys. - * Physical mac 0 is mapped to physical key 4 or 8, depending - * on the firmware version. - * So we must adjust the index here. - */ - index -= pairwise_keys_start; - B43_WARN_ON(index >= B43_NR_PAIRWISE_KEYS); - - if (b43_debug(dev, B43_DBG_KEYS)) { - b43dbg(dev->wl, "rx_tkip_phase1_write : idx 0x%x, iv32 0x%x\n", - index, iv32); - } - /* Write the key to the RX tkip shared mem */ - offset = B43_SHM_SH_TKIPTSCTTAK + index * (10 + 4); - for (i = 0; i < 10; i += 2) { - b43_shm_write16(dev, B43_SHM_SHARED, offset + i, - phase1key ? phase1key[i / 2] : 0); - } - b43_shm_write16(dev, B43_SHM_SHARED, offset + i, iv32); - b43_shm_write16(dev, B43_SHM_SHARED, offset + i + 2, iv32 >> 16); -} - -static void b43_op_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_key_conf *keyconf, const u8 *addr, - u32 iv32, u16 *phase1key) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - int index = keyconf->hw_key_idx; - - if (B43_WARN_ON(!modparam_hwtkip)) - return; - - /* This is only called from the RX path through mac80211, where - * our mutex is already locked. */ - B43_WARN_ON(!mutex_is_locked(&wl->mutex)); - dev = wl->current_dev; - B43_WARN_ON(!dev || b43_status(dev) < B43_STAT_INITIALIZED); - - keymac_write(dev, index, NULL); /* First zero out mac to avoid race */ - - rx_tkip_phase1_write(dev, index, iv32, phase1key); - keymac_write(dev, index, addr); -} - -static void do_key_write(struct b43_wldev *dev, - u8 index, u8 algorithm, - const u8 *key, size_t key_len, const u8 *mac_addr) -{ - u8 buf[B43_SEC_KEYSIZE] = { 0, }; - u8 pairwise_keys_start = B43_NR_GROUP_KEYS * 2; - - if (b43_new_kidx_api(dev)) - pairwise_keys_start = B43_NR_GROUP_KEYS; - - B43_WARN_ON(index >= ARRAY_SIZE(dev->key)); - B43_WARN_ON(key_len > B43_SEC_KEYSIZE); - - if (index >= pairwise_keys_start) - keymac_write(dev, index, NULL); /* First zero out mac. */ - if (algorithm == B43_SEC_ALGO_TKIP) { - /* - * We should provide an initial iv32, phase1key pair. - * We could start with iv32=0 and compute the corresponding - * phase1key, but this means calling ieee80211_get_tkip_key - * with a fake skb (or export other tkip function). - * Because we are lazy we hope iv32 won't start with - * 0xffffffff and let's b43_op_update_tkip_key provide a - * correct pair. - */ - rx_tkip_phase1_write(dev, index, 0xffffffff, (u16*)buf); - } else if (index >= pairwise_keys_start) /* clear it */ - rx_tkip_phase1_write(dev, index, 0, NULL); - if (key) - memcpy(buf, key, key_len); - key_write(dev, index, algorithm, buf); - if (index >= pairwise_keys_start) - keymac_write(dev, index, mac_addr); - - dev->key[index].algorithm = algorithm; -} - -static int b43_key_write(struct b43_wldev *dev, - int index, u8 algorithm, - const u8 *key, size_t key_len, - const u8 *mac_addr, - struct ieee80211_key_conf *keyconf) -{ - int i; - int pairwise_keys_start; - - /* For ALG_TKIP the key is encoded as a 256-bit (32 byte) data block: - * - Temporal Encryption Key (128 bits) - * - Temporal Authenticator Tx MIC Key (64 bits) - * - Temporal Authenticator Rx MIC Key (64 bits) - * - * Hardware only store TEK - */ - if (algorithm == B43_SEC_ALGO_TKIP && key_len == 32) - key_len = 16; - if (key_len > B43_SEC_KEYSIZE) - return -EINVAL; - for (i = 0; i < ARRAY_SIZE(dev->key); i++) { - /* Check that we don't already have this key. */ - B43_WARN_ON(dev->key[i].keyconf == keyconf); - } - if (index < 0) { - /* Pairwise key. Get an empty slot for the key. */ - if (b43_new_kidx_api(dev)) - pairwise_keys_start = B43_NR_GROUP_KEYS; - else - pairwise_keys_start = B43_NR_GROUP_KEYS * 2; - for (i = pairwise_keys_start; - i < pairwise_keys_start + B43_NR_PAIRWISE_KEYS; - i++) { - B43_WARN_ON(i >= ARRAY_SIZE(dev->key)); - if (!dev->key[i].keyconf) { - /* found empty */ - index = i; - break; - } - } - if (index < 0) { - b43warn(dev->wl, "Out of hardware key memory\n"); - return -ENOSPC; - } - } else - B43_WARN_ON(index > 3); - - do_key_write(dev, index, algorithm, key, key_len, mac_addr); - if ((index <= 3) && !b43_new_kidx_api(dev)) { - /* Default RX key */ - B43_WARN_ON(mac_addr); - do_key_write(dev, index + 4, algorithm, key, key_len, NULL); - } - keyconf->hw_key_idx = index; - dev->key[index].keyconf = keyconf; - - return 0; -} - -static int b43_key_clear(struct b43_wldev *dev, int index) -{ - if (B43_WARN_ON((index < 0) || (index >= ARRAY_SIZE(dev->key)))) - return -EINVAL; - do_key_write(dev, index, B43_SEC_ALGO_NONE, - NULL, B43_SEC_KEYSIZE, NULL); - if ((index <= 3) && !b43_new_kidx_api(dev)) { - do_key_write(dev, index + 4, B43_SEC_ALGO_NONE, - NULL, B43_SEC_KEYSIZE, NULL); - } - dev->key[index].keyconf = NULL; - - return 0; -} - -static void b43_clear_keys(struct b43_wldev *dev) -{ - int i, count; - - if (b43_new_kidx_api(dev)) - count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS; - else - count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS; - for (i = 0; i < count; i++) - b43_key_clear(dev, i); -} - -static void b43_dump_keymemory(struct b43_wldev *dev) -{ - unsigned int i, index, count, offset, pairwise_keys_start; - u8 mac[ETH_ALEN]; - u16 algo; - u32 rcmta0; - u16 rcmta1; - u64 hf; - struct b43_key *key; - - if (!b43_debug(dev, B43_DBG_KEYS)) - return; - - hf = b43_hf_read(dev); - b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n", - !!(hf & B43_HF_USEDEFKEYS)); - if (b43_new_kidx_api(dev)) { - pairwise_keys_start = B43_NR_GROUP_KEYS; - count = B43_NR_GROUP_KEYS + B43_NR_PAIRWISE_KEYS; - } else { - pairwise_keys_start = B43_NR_GROUP_KEYS * 2; - count = B43_NR_GROUP_KEYS * 2 + B43_NR_PAIRWISE_KEYS; - } - for (index = 0; index < count; index++) { - key = &(dev->key[index]); - printk(KERN_DEBUG "Key slot %02u: %s", - index, (key->keyconf == NULL) ? " " : "*"); - offset = dev->ktp + (index * B43_SEC_KEYSIZE); - for (i = 0; i < B43_SEC_KEYSIZE; i += 2) { - u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i); - printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF)); - } - - algo = b43_shm_read16(dev, B43_SHM_SHARED, - B43_SHM_SH_KEYIDXBLOCK + (index * 2)); - printk(" Algo: %04X/%02X", algo, key->algorithm); - - if (index >= pairwise_keys_start) { - if (key->algorithm == B43_SEC_ALGO_TKIP) { - printk(" TKIP: "); - offset = B43_SHM_SH_TKIPTSCTTAK + (index - 4) * (10 + 4); - for (i = 0; i < 14; i += 2) { - u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i); - printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF)); - } - } - rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, - ((index - pairwise_keys_start) * 2) + 0); - rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, - ((index - pairwise_keys_start) * 2) + 1); - *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); - *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); - printk(" MAC: %pM", mac); - } else - printk(" DEFAULT KEY"); - printk("\n"); - } -} - -void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) -{ - u32 macctl; - u16 ucstat; - bool hwps; - bool awake; - int i; - - B43_WARN_ON((ps_flags & B43_PS_ENABLED) && - (ps_flags & B43_PS_DISABLED)); - B43_WARN_ON((ps_flags & B43_PS_AWAKE) && (ps_flags & B43_PS_ASLEEP)); - - if (ps_flags & B43_PS_ENABLED) { - hwps = 1; - } else if (ps_flags & B43_PS_DISABLED) { - hwps = 0; - } else { - //TODO: If powersave is not off and FIXME is not set and we are not in adhoc - // and thus is not an AP and we are associated, set bit 25 - } - if (ps_flags & B43_PS_AWAKE) { - awake = 1; - } else if (ps_flags & B43_PS_ASLEEP) { - awake = 0; - } else { - //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME, - // or we are associated, or FIXME, or the latest PS-Poll packet sent was - // successful, set bit26 - } - -/* FIXME: For now we force awake-on and hwps-off */ - hwps = 0; - awake = 1; - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - if (hwps) - macctl |= B43_MACCTL_HWPS; - else - macctl &= ~B43_MACCTL_HWPS; - if (awake) - macctl |= B43_MACCTL_AWAKE; - else - macctl &= ~B43_MACCTL_AWAKE; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - /* Commit write */ - b43_read32(dev, B43_MMIO_MACCTL); - if (awake && dev->dev->id.revision >= 5) { - /* Wait for the microcode to wake up. */ - for (i = 0; i < 100; i++) { - ucstat = b43_shm_read16(dev, B43_SHM_SHARED, - B43_SHM_SH_UCODESTAT); - if (ucstat != B43_SHM_SH_UCODESTAT_SLEEP) - break; - udelay(10); - } - } -} - -void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags) -{ - u32 tmslow; - u32 macctl; - - flags |= B43_TMSLOW_PHYCLKEN; - flags |= B43_TMSLOW_PHYRESET; - ssb_device_enable(dev->dev, flags); - msleep(2); /* Wait for the PLL to turn on. */ - - /* Now take the PHY out of Reset again */ - tmslow = ssb_read32(dev->dev, SSB_TMSLOW); - tmslow |= SSB_TMSLOW_FGC; - tmslow &= ~B43_TMSLOW_PHYRESET; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ - msleep(1); - tmslow &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ - msleep(1); - - /* Turn Analog ON, but only if we already know the PHY-type. - * This protects against very early setup where we don't know the - * PHY-type, yet. wireless_core_reset will be called once again later, - * when we know the PHY-type. */ - if (dev->phy.ops) - dev->phy.ops->switch_analog(dev, 1); - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_GMODE; - if (flags & B43_TMSLOW_GMODE) - macctl |= B43_MACCTL_GMODE; - macctl |= B43_MACCTL_IHR_ENABLED; - b43_write32(dev, B43_MMIO_MACCTL, macctl); -} - -static void handle_irq_transmit_status(struct b43_wldev *dev) -{ - u32 v0, v1; - u16 tmp; - struct b43_txstatus stat; - - while (1) { - v0 = b43_read32(dev, B43_MMIO_XMITSTAT_0); - if (!(v0 & 0x00000001)) - break; - v1 = b43_read32(dev, B43_MMIO_XMITSTAT_1); - - stat.cookie = (v0 >> 16); - stat.seq = (v1 & 0x0000FFFF); - stat.phy_stat = ((v1 & 0x00FF0000) >> 16); - tmp = (v0 & 0x0000FFFF); - stat.frame_count = ((tmp & 0xF000) >> 12); - stat.rts_count = ((tmp & 0x0F00) >> 8); - stat.supp_reason = ((tmp & 0x001C) >> 2); - stat.pm_indicated = !!(tmp & 0x0080); - stat.intermediate = !!(tmp & 0x0040); - stat.for_ampdu = !!(tmp & 0x0020); - stat.acked = !!(tmp & 0x0002); - - b43_handle_txstatus(dev, &stat); - } -} - -static void drain_txstatus_queue(struct b43_wldev *dev) -{ - u32 dummy; - - if (dev->dev->id.revision < 5) - return; - /* Read all entries from the microcode TXstatus FIFO - * and throw them away. - */ - while (1) { - dummy = b43_read32(dev, B43_MMIO_XMITSTAT_0); - if (!(dummy & 0x00000001)) - break; - dummy = b43_read32(dev, B43_MMIO_XMITSTAT_1); - } -} - -static u32 b43_jssi_read(struct b43_wldev *dev) -{ - u32 val = 0; - - val = b43_shm_read16(dev, B43_SHM_SHARED, 0x08A); - val <<= 16; - val |= b43_shm_read16(dev, B43_SHM_SHARED, 0x088); - - return val; -} - -static void b43_jssi_write(struct b43_wldev *dev, u32 jssi) -{ - b43_shm_write16(dev, B43_SHM_SHARED, 0x088, (jssi & 0x0000FFFF)); - b43_shm_write16(dev, B43_SHM_SHARED, 0x08A, (jssi & 0xFFFF0000) >> 16); -} - -static void b43_generate_noise_sample(struct b43_wldev *dev) -{ - b43_jssi_write(dev, 0x7F7F7F7F); - b43_write32(dev, B43_MMIO_MACCMD, - b43_read32(dev, B43_MMIO_MACCMD) | B43_MACCMD_BGNOISE); -} - -static void b43_calculate_link_quality(struct b43_wldev *dev) -{ - /* Top half of Link Quality calculation. */ - - if (dev->phy.type != B43_PHYTYPE_G) - return; - if (dev->noisecalc.calculation_running) - return; - dev->noisecalc.calculation_running = 1; - dev->noisecalc.nr_samples = 0; - - b43_generate_noise_sample(dev); -} - -static void handle_irq_noise(struct b43_wldev *dev) -{ - struct b43_phy_g *phy = dev->phy.g; - u16 tmp; - u8 noise[4]; - u8 i, j; - s32 average; - - /* Bottom half of Link Quality calculation. */ - - if (dev->phy.type != B43_PHYTYPE_G) - return; - - /* Possible race condition: It might be possible that the user - * changed to a different channel in the meantime since we - * started the calculation. We ignore that fact, since it's - * not really that much of a problem. The background noise is - * an estimation only anyway. Slightly wrong results will get damped - * by the averaging of the 8 sample rounds. Additionally the - * value is shortlived. So it will be replaced by the next noise - * calculation round soon. */ - - B43_WARN_ON(!dev->noisecalc.calculation_running); - *((__le32 *)noise) = cpu_to_le32(b43_jssi_read(dev)); - if (noise[0] == 0x7F || noise[1] == 0x7F || - noise[2] == 0x7F || noise[3] == 0x7F) - goto generate_new; - - /* Get the noise samples. */ - B43_WARN_ON(dev->noisecalc.nr_samples >= 8); - i = dev->noisecalc.nr_samples; - noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]]; - dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]]; - dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]]; - dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]]; - dev->noisecalc.nr_samples++; - if (dev->noisecalc.nr_samples == 8) { - /* Calculate the Link Quality by the noise samples. */ - average = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 4; j++) - average += dev->noisecalc.samples[i][j]; - } - average /= (8 * 4); - average *= 125; - average += 64; - average /= 128; - tmp = b43_shm_read16(dev, B43_SHM_SHARED, 0x40C); - tmp = (tmp / 128) & 0x1F; - if (tmp >= 8) - average += 2; - else - average -= 25; - if (tmp == 8) - average -= 72; - else - average -= 48; - - dev->stats.link_noise = average; - dev->noisecalc.calculation_running = 0; - return; - } -generate_new: - b43_generate_noise_sample(dev); -} - -static void handle_irq_tbtt_indication(struct b43_wldev *dev) -{ - if (b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) { - ///TODO: PS TBTT - } else { - if (1 /*FIXME: the last PSpoll frame was sent successfully */ ) - b43_power_saving_ctl_bits(dev, 0); - } - if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) - dev->dfq_valid = 1; -} - -static void handle_irq_atim_end(struct b43_wldev *dev) -{ - if (dev->dfq_valid) { - b43_write32(dev, B43_MMIO_MACCMD, - b43_read32(dev, B43_MMIO_MACCMD) - | B43_MACCMD_DFQ_VALID); - dev->dfq_valid = 0; - } -} - -static void handle_irq_pmq(struct b43_wldev *dev) -{ - u32 tmp; - - //TODO: AP mode. - - while (1) { - tmp = b43_read32(dev, B43_MMIO_PS_STATUS); - if (!(tmp & 0x00000008)) - break; - } - /* 16bit write is odd, but correct. */ - b43_write16(dev, B43_MMIO_PS_STATUS, 0x0002); -} - -static void b43_write_template_common(struct b43_wldev *dev, - const u8 *data, u16 size, - u16 ram_offset, - u16 shm_size_offset, u8 rate) -{ - u32 i, tmp; - struct b43_plcp_hdr4 plcp; - - plcp.data = 0; - b43_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); - b43_ram_write(dev, ram_offset, le32_to_cpu(plcp.data)); - ram_offset += sizeof(u32); - /* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet. - * So leave the first two bytes of the next write blank. - */ - tmp = (u32) (data[0]) << 16; - tmp |= (u32) (data[1]) << 24; - b43_ram_write(dev, ram_offset, tmp); - ram_offset += sizeof(u32); - for (i = 2; i < size; i += sizeof(u32)) { - tmp = (u32) (data[i + 0]); - if (i + 1 < size) - tmp |= (u32) (data[i + 1]) << 8; - if (i + 2 < size) - tmp |= (u32) (data[i + 2]) << 16; - if (i + 3 < size) - tmp |= (u32) (data[i + 3]) << 24; - b43_ram_write(dev, ram_offset + i - 2, tmp); - } - b43_shm_write16(dev, B43_SHM_SHARED, shm_size_offset, - size + sizeof(struct b43_plcp_hdr6)); -} - -/* Check if the use of the antenna that ieee80211 told us to - * use is possible. This will fall back to DEFAULT. - * "antenna_nr" is the antenna identifier we got from ieee80211. */ -u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, - u8 antenna_nr) -{ - u8 antenna_mask; - - if (antenna_nr == 0) { - /* Zero means "use default antenna". That's always OK. */ - return 0; - } - - /* Get the mask of available antennas. */ - if (dev->phy.gmode) - antenna_mask = dev->dev->bus->sprom.ant_available_bg; - else - antenna_mask = dev->dev->bus->sprom.ant_available_a; - - if (!(antenna_mask & (1 << (antenna_nr - 1)))) { - /* This antenna is not available. Fall back to default. */ - return 0; - } - - return antenna_nr; -} - -/* Convert a b43 antenna number value to the PHY TX control value. */ -static u16 b43_antenna_to_phyctl(int antenna) -{ - switch (antenna) { - case B43_ANTENNA0: - return B43_TXH_PHY_ANT0; - case B43_ANTENNA1: - return B43_TXH_PHY_ANT1; - case B43_ANTENNA2: - return B43_TXH_PHY_ANT2; - case B43_ANTENNA3: - return B43_TXH_PHY_ANT3; - case B43_ANTENNA_AUTO0: - case B43_ANTENNA_AUTO1: - return B43_TXH_PHY_ANT01AUTO; - } - B43_WARN_ON(1); - return 0; -} - -static void b43_write_beacon_template(struct b43_wldev *dev, - u16 ram_offset, - u16 shm_size_offset) -{ - unsigned int i, len, variable_len; - const struct ieee80211_mgmt *bcn; - const u8 *ie; - bool tim_found = 0; - unsigned int rate; - u16 ctl; - int antenna; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); - - bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); - len = min((size_t) dev->wl->current_beacon->len, - 0x200 - sizeof(struct b43_plcp_hdr6)); - rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; - - b43_write_template_common(dev, (const u8 *)bcn, - len, ram_offset, shm_size_offset, rate); - - /* Write the PHY TX control parameters. */ - antenna = B43_ANTENNA_DEFAULT; - antenna = b43_antenna_to_phyctl(antenna); - ctl = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL); - /* We can't send beacons with short preamble. Would get PHY errors. */ - ctl &= ~B43_TXH_PHY_SHORTPRMBL; - ctl &= ~B43_TXH_PHY_ANT; - ctl &= ~B43_TXH_PHY_ENC; - ctl |= antenna; - if (b43_is_cck_rate(rate)) - ctl |= B43_TXH_PHY_ENC_CCK; - else - ctl |= B43_TXH_PHY_ENC_OFDM; - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl); - - /* Find the position of the TIM and the DTIM_period value - * and write them to SHM. */ - ie = bcn->u.beacon.variable; - variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - for (i = 0; i < variable_len - 2; ) { - uint8_t ie_id, ie_len; - - ie_id = ie[i]; - ie_len = ie[i + 1]; - if (ie_id == 5) { - u16 tim_position; - u16 dtim_period; - /* This is the TIM Information Element */ - - /* Check whether the ie_len is in the beacon data range. */ - if (variable_len < ie_len + 2 + i) - break; - /* A valid TIM is at least 4 bytes long. */ - if (ie_len < 4) - break; - tim_found = 1; - - tim_position = sizeof(struct b43_plcp_hdr6); - tim_position += offsetof(struct ieee80211_mgmt, u.beacon.variable); - tim_position += i; - - dtim_period = ie[i + 3]; - - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_TIMBPOS, tim_position); - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_DTIMPER, dtim_period); - break; - } - i += ie_len + 2; - } - if (!tim_found) { - /* - * If ucode wants to modify TIM do it behind the beacon, this - * will happen, for example, when doing mesh networking. - */ - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_TIMBPOS, - len + sizeof(struct b43_plcp_hdr6)); - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_DTIMPER, 0); - } - b43dbg(dev->wl, "Updated beacon template at 0x%x\n", ram_offset); -} - -static void b43_upload_beacon0(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - - if (wl->beacon0_uploaded) - return; - b43_write_beacon_template(dev, 0x68, 0x18); - wl->beacon0_uploaded = 1; -} - -static void b43_upload_beacon1(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - - if (wl->beacon1_uploaded) - return; - b43_write_beacon_template(dev, 0x468, 0x1A); - wl->beacon1_uploaded = 1; -} - -static void handle_irq_beacon(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - u32 cmd, beacon0_valid, beacon1_valid; - - if (!b43_is_mode(wl, NL80211_IFTYPE_AP) && - !b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) - return; - - /* This is the bottom half of the asynchronous beacon update. */ - - /* Ignore interrupt in the future. */ - dev->irq_mask &= ~B43_IRQ_BEACON; - - cmd = b43_read32(dev, B43_MMIO_MACCMD); - beacon0_valid = (cmd & B43_MACCMD_BEACON0_VALID); - beacon1_valid = (cmd & B43_MACCMD_BEACON1_VALID); - - /* Schedule interrupt manually, if busy. */ - if (beacon0_valid && beacon1_valid) { - b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_BEACON); - dev->irq_mask |= B43_IRQ_BEACON; - return; - } - - if (unlikely(wl->beacon_templates_virgin)) { - /* We never uploaded a beacon before. - * Upload both templates now, but only mark one valid. */ - wl->beacon_templates_virgin = 0; - b43_upload_beacon0(dev); - b43_upload_beacon1(dev); - cmd = b43_read32(dev, B43_MMIO_MACCMD); - cmd |= B43_MACCMD_BEACON0_VALID; - b43_write32(dev, B43_MMIO_MACCMD, cmd); - } else { - if (!beacon0_valid) { - b43_upload_beacon0(dev); - cmd = b43_read32(dev, B43_MMIO_MACCMD); - cmd |= B43_MACCMD_BEACON0_VALID; - b43_write32(dev, B43_MMIO_MACCMD, cmd); - } else if (!beacon1_valid) { - b43_upload_beacon1(dev); - cmd = b43_read32(dev, B43_MMIO_MACCMD); - cmd |= B43_MACCMD_BEACON1_VALID; - b43_write32(dev, B43_MMIO_MACCMD, cmd); - } - } -} - -static void b43_do_beacon_update_trigger_work(struct b43_wldev *dev) -{ - u32 old_irq_mask = dev->irq_mask; - - /* update beacon right away or defer to irq */ - handle_irq_beacon(dev); - if (old_irq_mask != dev->irq_mask) { - /* The handler updated the IRQ mask. */ - B43_WARN_ON(!dev->irq_mask); - if (b43_read32(dev, B43_MMIO_GEN_IRQ_MASK)) { - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); - } else { - /* Device interrupts are currently disabled. That means - * we just ran the hardirq handler and scheduled the - * IRQ thread. The thread will write the IRQ mask when - * it finished, so there's nothing to do here. Writing - * the mask _here_ would incorrectly re-enable IRQs. */ - } - } -} - -static void b43_beacon_update_trigger_work(struct work_struct *work) -{ - struct b43_wl *wl = container_of(work, struct b43_wl, - beacon_update_trigger); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (likely(dev && (b43_status(dev) >= B43_STAT_INITIALIZED))) { - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { - /* wl->mutex is enough. */ - b43_do_beacon_update_trigger_work(dev); - mmiowb(); - } else { - spin_lock_irq(&wl->hardirq_lock); - b43_do_beacon_update_trigger_work(dev); - mmiowb(); - spin_unlock_irq(&wl->hardirq_lock); - } - } - mutex_unlock(&wl->mutex); -} - -/* Asynchronously update the packet templates in template RAM. - * Locking: Requires wl->mutex to be locked. */ -static void b43_update_templates(struct b43_wl *wl) -{ - struct sk_buff *beacon; - - /* This is the top half of the ansynchronous beacon update. - * The bottom half is the beacon IRQ. - * Beacon update must be asynchronous to avoid sending an - * invalid beacon. This can happen for example, if the firmware - * transmits a beacon while we are updating it. */ - - /* We could modify the existing beacon and set the aid bit in - * the TIM field, but that would probably require resizing and - * moving of data within the beacon template. - * Simply request a new beacon and let mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(wl->hw, wl->vif); - if (unlikely(!beacon)) - return; - - if (wl->current_beacon) - dev_kfree_skb_any(wl->current_beacon); - wl->current_beacon = beacon; - wl->beacon0_uploaded = 0; - wl->beacon1_uploaded = 0; - ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); -} - -static void b43_set_beacon_int(struct b43_wldev *dev, u16 beacon_int) -{ - b43_time_lock(dev); - if (dev->dev->id.revision >= 3) { - b43_write32(dev, B43_MMIO_TSF_CFP_REP, (beacon_int << 16)); - b43_write32(dev, B43_MMIO_TSF_CFP_START, (beacon_int << 10)); - } else { - b43_write16(dev, 0x606, (beacon_int >> 6)); - b43_write16(dev, 0x610, beacon_int); - } - b43_time_unlock(dev); - b43dbg(dev->wl, "Set beacon interval to %u\n", beacon_int); -} - -static void b43_handle_firmware_panic(struct b43_wldev *dev) -{ - u16 reason; - - /* Read the register that contains the reason code for the panic. */ - reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_FWPANIC_REASON_REG); - b43err(dev->wl, "Whoopsy, firmware panic! Reason: %u\n", reason); - - switch (reason) { - default: - b43dbg(dev->wl, "The panic reason is unknown.\n"); - /* fallthrough */ - case B43_FWPANIC_DIE: - /* Do not restart the controller or firmware. - * The device is nonfunctional from now on. - * Restarting would result in this panic to trigger again, - * so we avoid that recursion. */ - break; - case B43_FWPANIC_RESTART: - b43_controller_restart(dev, "Microcode panic"); - break; - } -} - -static void handle_irq_ucode_debug(struct b43_wldev *dev) -{ - unsigned int i, cnt; - u16 reason, marker_id, marker_line; - __le16 *buf; - - /* The proprietary firmware doesn't have this IRQ. */ - if (!dev->fw.opensource) - return; - - /* Read the register that contains the reason code for this IRQ. */ - reason = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_DEBUGIRQ_REASON_REG); - - switch (reason) { - case B43_DEBUGIRQ_PANIC: - b43_handle_firmware_panic(dev); - break; - case B43_DEBUGIRQ_DUMP_SHM: - if (!B43_DEBUG) - break; /* Only with driver debugging enabled. */ - buf = kmalloc(4096, GFP_ATOMIC); - if (!buf) { - b43dbg(dev->wl, "SHM-dump: Failed to allocate memory\n"); - goto out; - } - for (i = 0; i < 4096; i += 2) { - u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, i); - buf[i / 2] = cpu_to_le16(tmp); - } - b43info(dev->wl, "Shared memory dump:\n"); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, - 16, 2, buf, 4096, 1); - kfree(buf); - break; - case B43_DEBUGIRQ_DUMP_REGS: - if (!B43_DEBUG) - break; /* Only with driver debugging enabled. */ - b43info(dev->wl, "Microcode register dump:\n"); - for (i = 0, cnt = 0; i < 64; i++) { - u16 tmp = b43_shm_read16(dev, B43_SHM_SCRATCH, i); - if (cnt == 0) - printk(KERN_INFO); - printk("r%02u: 0x%04X ", i, tmp); - cnt++; - if (cnt == 6) { - printk("\n"); - cnt = 0; - } - } - printk("\n"); - break; - case B43_DEBUGIRQ_MARKER: - if (!B43_DEBUG) - break; /* Only with driver debugging enabled. */ - marker_id = b43_shm_read16(dev, B43_SHM_SCRATCH, - B43_MARKER_ID_REG); - marker_line = b43_shm_read16(dev, B43_SHM_SCRATCH, - B43_MARKER_LINE_REG); - b43info(dev->wl, "The firmware just executed the MARKER(%u) " - "at line number %u\n", - marker_id, marker_line); - break; - default: - b43dbg(dev->wl, "Debug-IRQ triggered for unknown reason: %u\n", - reason); - } -out: - /* Acknowledge the debug-IRQ, so the firmware can continue. */ - b43_shm_write16(dev, B43_SHM_SCRATCH, - B43_DEBUGIRQ_REASON_REG, B43_DEBUGIRQ_ACK); -} - -static void b43_do_interrupt_thread(struct b43_wldev *dev) -{ - u32 reason; - u32 dma_reason[ARRAY_SIZE(dev->dma_reason)]; - u32 merged_dma_reason = 0; - int i; - - if (unlikely(b43_status(dev) != B43_STAT_STARTED)) - return; - - reason = dev->irq_reason; - for (i = 0; i < ARRAY_SIZE(dma_reason); i++) { - dma_reason[i] = dev->dma_reason[i]; - merged_dma_reason |= dma_reason[i]; - } - - if (unlikely(reason & B43_IRQ_MAC_TXERR)) - b43err(dev->wl, "MAC transmission error\n"); - - if (unlikely(reason & B43_IRQ_PHY_TXERR)) { - b43err(dev->wl, "PHY transmission error\n"); - rmb(); - if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) { - atomic_set(&dev->phy.txerr_cnt, - B43_PHY_TX_BADNESS_LIMIT); - b43err(dev->wl, "Too many PHY TX errors, " - "restarting the controller\n"); - b43_controller_restart(dev, "PHY TX errors"); - } - } - - if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK | - B43_DMAIRQ_NONFATALMASK))) { - if (merged_dma_reason & B43_DMAIRQ_FATALMASK) { - b43err(dev->wl, "Fatal DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - b43err(dev->wl, "This device does not support DMA " - "on your system. Please use PIO instead.\n"); - /* Fall back to PIO transfers if we get fatal DMA errors! */ - dev->use_pio = 1; - b43_controller_restart(dev, "DMA error"); - return; - } - if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) { - b43err(dev->wl, "DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - } - } - - if (unlikely(reason & B43_IRQ_UCODE_DEBUG)) - handle_irq_ucode_debug(dev); - if (reason & B43_IRQ_TBTT_INDI) - handle_irq_tbtt_indication(dev); - if (reason & B43_IRQ_ATIM_END) - handle_irq_atim_end(dev); - if (reason & B43_IRQ_BEACON) - handle_irq_beacon(dev); - if (reason & B43_IRQ_PMQ) - handle_irq_pmq(dev); - if (reason & B43_IRQ_TXFIFO_FLUSH_OK) - ;/* TODO */ - if (reason & B43_IRQ_NOISESAMPLE_OK) - handle_irq_noise(dev); - - /* Check the DMA reason registers for received data. */ - if (dma_reason[0] & B43_DMAIRQ_RX_DONE) { - if (b43_using_pio_transfers(dev)) - b43_pio_rx(dev->pio.rx_queue); - else - b43_dma_rx(dev->dma.rx_ring); - } - B43_WARN_ON(dma_reason[1] & B43_DMAIRQ_RX_DONE); - B43_WARN_ON(dma_reason[2] & B43_DMAIRQ_RX_DONE); - B43_WARN_ON(dma_reason[3] & B43_DMAIRQ_RX_DONE); - B43_WARN_ON(dma_reason[4] & B43_DMAIRQ_RX_DONE); - B43_WARN_ON(dma_reason[5] & B43_DMAIRQ_RX_DONE); - - if (reason & B43_IRQ_TX_OK) - handle_irq_transmit_status(dev); - - /* Re-enable interrupts on the device by restoring the current interrupt mask. */ - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); - -#if B43_DEBUG - if (b43_debug(dev, B43_DBG_VERBOSESTATS)) { - dev->irq_count++; - for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) { - if (reason & (1 << i)) - dev->irq_bit_count[i]++; - } - } -#endif -} - -/* Interrupt thread handler. Handles device interrupts in thread context. */ -static irqreturn_t b43_interrupt_thread_handler(int irq, void *dev_id) -{ - struct b43_wldev *dev = dev_id; - - mutex_lock(&dev->wl->mutex); - b43_do_interrupt_thread(dev); - mmiowb(); - mutex_unlock(&dev->wl->mutex); - - return IRQ_HANDLED; -} - -static irqreturn_t b43_do_interrupt(struct b43_wldev *dev) -{ - u32 reason; - - /* This code runs under wl->hardirq_lock, but _only_ on non-SDIO busses. - * On SDIO, this runs under wl->mutex. */ - - reason = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); - if (reason == 0xffffffff) /* shared IRQ */ - return IRQ_NONE; - reason &= dev->irq_mask; - if (!reason) - return IRQ_HANDLED; - - dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON) - & 0x0001DC00; - dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON) - & 0x0000DC00; - dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON) - & 0x0000DC00; - dev->dma_reason[3] = b43_read32(dev, B43_MMIO_DMA3_REASON) - & 0x0001DC00; - dev->dma_reason[4] = b43_read32(dev, B43_MMIO_DMA4_REASON) - & 0x0000DC00; -/* Unused ring - dev->dma_reason[5] = b43_read32(dev, B43_MMIO_DMA5_REASON) - & 0x0000DC00; -*/ - - /* ACK the interrupt. */ - b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, reason); - b43_write32(dev, B43_MMIO_DMA0_REASON, dev->dma_reason[0]); - b43_write32(dev, B43_MMIO_DMA1_REASON, dev->dma_reason[1]); - b43_write32(dev, B43_MMIO_DMA2_REASON, dev->dma_reason[2]); - b43_write32(dev, B43_MMIO_DMA3_REASON, dev->dma_reason[3]); - b43_write32(dev, B43_MMIO_DMA4_REASON, dev->dma_reason[4]); -/* Unused ring - b43_write32(dev, B43_MMIO_DMA5_REASON, dev->dma_reason[5]); -*/ - - /* Disable IRQs on the device. The IRQ thread handler will re-enable them. */ - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); - /* Save the reason bitmasks for the IRQ thread handler. */ - dev->irq_reason = reason; - - return IRQ_WAKE_THREAD; -} - -/* Interrupt handler top-half. This runs with interrupts disabled. */ -static irqreturn_t b43_interrupt_handler(int irq, void *dev_id) -{ - struct b43_wldev *dev = dev_id; - irqreturn_t ret; - - if (unlikely(b43_status(dev) < B43_STAT_STARTED)) - return IRQ_NONE; - - spin_lock(&dev->wl->hardirq_lock); - ret = b43_do_interrupt(dev); - mmiowb(); - spin_unlock(&dev->wl->hardirq_lock); - - return ret; -} - -/* SDIO interrupt handler. This runs in process context. */ -static void b43_sdio_interrupt_handler(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - irqreturn_t ret; - - mutex_lock(&wl->mutex); - - ret = b43_do_interrupt(dev); - if (ret == IRQ_WAKE_THREAD) - b43_do_interrupt_thread(dev); - - mutex_unlock(&wl->mutex); -} - -void b43_do_release_fw(struct b43_firmware_file *fw) -{ - release_firmware(fw->data); - fw->data = NULL; - fw->filename = NULL; -} - -static void b43_release_firmware(struct b43_wldev *dev) -{ - b43_do_release_fw(&dev->fw.ucode); - b43_do_release_fw(&dev->fw.pcm); - b43_do_release_fw(&dev->fw.initvals); - b43_do_release_fw(&dev->fw.initvals_band); -} - -static void b43_print_fw_helptext(struct b43_wl *wl, bool error) -{ - const char text[] = - "You must go to " \ - "http://wireless.kernel.org/en/users/Drivers/b43#devicefirmware " \ - "and download the correct firmware for this driver version. " \ - "Please carefully read all instructions on this website.\n"; - - if (error) - b43err(wl, text); - else - b43warn(wl, text); -} - -int b43_do_request_fw(struct b43_request_fw_context *ctx, - const char *name, - struct b43_firmware_file *fw) -{ - const struct firmware *blob; - struct b43_fw_header *hdr; - u32 size; - int err; - - if (!name) { - /* Don't fetch anything. Free possibly cached firmware. */ - /* FIXME: We should probably keep it anyway, to save some headache - * on suspend/resume with multiband devices. */ - b43_do_release_fw(fw); - return 0; - } - if (fw->filename) { - if ((fw->type == ctx->req_type) && - (strcmp(fw->filename, name) == 0)) - return 0; /* Already have this fw. */ - /* Free the cached firmware first. */ - /* FIXME: We should probably do this later after we successfully - * got the new fw. This could reduce headache with multiband devices. - * We could also redesign this to cache the firmware for all possible - * bands all the time. */ - b43_do_release_fw(fw); - } - - switch (ctx->req_type) { - case B43_FWTYPE_PROPRIETARY: - snprintf(ctx->fwname, sizeof(ctx->fwname), - "b43%s/%s.fw", - modparam_fwpostfix, name); - break; - case B43_FWTYPE_OPENSOURCE: - snprintf(ctx->fwname, sizeof(ctx->fwname), - "b43-open%s/%s.fw", - modparam_fwpostfix, name); - break; - default: - B43_WARN_ON(1); - return -ENOSYS; - } - err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); - if (err == -ENOENT) { - snprintf(ctx->errors[ctx->req_type], - sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" not found\n", ctx->fwname); - return err; - } else if (err) { - snprintf(ctx->errors[ctx->req_type], - sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" request failed (err=%d)\n", - ctx->fwname, err); - return err; - } - if (blob->size < sizeof(struct b43_fw_header)) - goto err_format; - hdr = (struct b43_fw_header *)(blob->data); - switch (hdr->type) { - case B43_FW_TYPE_UCODE: - case B43_FW_TYPE_PCM: - size = be32_to_cpu(hdr->size); - if (size != blob->size - sizeof(struct b43_fw_header)) - goto err_format; - /* fallthrough */ - case B43_FW_TYPE_IV: - if (hdr->ver != 1) - goto err_format; - break; - default: - goto err_format; - } - - fw->data = blob; - fw->filename = name; - fw->type = ctx->req_type; - - return 0; - -err_format: - snprintf(ctx->errors[ctx->req_type], - sizeof(ctx->errors[ctx->req_type]), - "Firmware file \"%s\" format error.\n", ctx->fwname); - release_firmware(blob); - - return -EPROTO; -} - -static int b43_try_request_fw(struct b43_request_fw_context *ctx) -{ - struct b43_wldev *dev = ctx->dev; - struct b43_firmware *fw = &ctx->dev->fw; - const u8 rev = ctx->dev->dev->id.revision; - const char *filename; - u32 tmshigh; - int err; - - /* Get microcode */ - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); - if ((rev >= 5) && (rev <= 10)) - filename = "ucode5"; - else if ((rev >= 11) && (rev <= 12)) - filename = "ucode11"; - else if (rev == 13) - filename = "ucode13"; - else if (rev == 14) - filename = "ucode14"; - else if (rev >= 15) - filename = "ucode15"; - else - goto err_no_ucode; - err = b43_do_request_fw(ctx, filename, &fw->ucode); - if (err) - goto err_load; - - /* Get PCM code */ - if ((rev >= 5) && (rev <= 10)) - filename = "pcm5"; - else if (rev >= 11) - filename = NULL; - else - goto err_no_pcm; - fw->pcm_request_failed = 0; - err = b43_do_request_fw(ctx, filename, &fw->pcm); - if (err == -ENOENT) { - /* We did not find a PCM file? Not fatal, but - * core rev <= 10 must do without hwcrypto then. */ - fw->pcm_request_failed = 1; - } else if (err) - goto err_load; - - /* Get initvals */ - switch (dev->phy.type) { - case B43_PHYTYPE_A: - if ((rev >= 5) && (rev <= 10)) { - if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) - filename = "a0g1initvals5"; - else - filename = "a0g0initvals5"; - } else - goto err_no_initvals; - break; - case B43_PHYTYPE_G: - if ((rev >= 5) && (rev <= 10)) - filename = "b0g0initvals5"; - else if (rev >= 13) - filename = "b0g0initvals13"; - else - goto err_no_initvals; - break; - case B43_PHYTYPE_N: - if ((rev >= 11) && (rev <= 12)) - filename = "n0initvals11"; - else - goto err_no_initvals; - break; - case B43_PHYTYPE_LP: - if (rev == 13) - filename = "lp0initvals13"; - else if (rev == 14) - filename = "lp0initvals14"; - else if (rev >= 15) - filename = "lp0initvals15"; - else - goto err_no_initvals; - break; - default: - goto err_no_initvals; - } - err = b43_do_request_fw(ctx, filename, &fw->initvals); - if (err) - goto err_load; - - /* Get bandswitch initvals */ - switch (dev->phy.type) { - case B43_PHYTYPE_A: - if ((rev >= 5) && (rev <= 10)) { - if (tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY) - filename = "a0g1bsinitvals5"; - else - filename = "a0g0bsinitvals5"; - } else if (rev >= 11) - filename = NULL; - else - goto err_no_initvals; - break; - case B43_PHYTYPE_G: - if ((rev >= 5) && (rev <= 10)) - filename = "b0g0bsinitvals5"; - else if (rev >= 11) - filename = NULL; - else - goto err_no_initvals; - break; - case B43_PHYTYPE_N: - if ((rev >= 11) && (rev <= 12)) - filename = "n0bsinitvals11"; - else - goto err_no_initvals; - break; - case B43_PHYTYPE_LP: - if (rev == 13) - filename = "lp0bsinitvals13"; - else if (rev == 14) - filename = "lp0bsinitvals14"; - else if (rev >= 15) - filename = "lp0bsinitvals15"; - else - goto err_no_initvals; - break; - default: - goto err_no_initvals; - } - err = b43_do_request_fw(ctx, filename, &fw->initvals_band); - if (err) - goto err_load; - - return 0; - -err_no_ucode: - err = ctx->fatal_failure = -EOPNOTSUPP; - b43err(dev->wl, "The driver does not know which firmware (ucode) " - "is required for your device (wl-core rev %u)\n", rev); - goto error; - -err_no_pcm: - err = ctx->fatal_failure = -EOPNOTSUPP; - b43err(dev->wl, "The driver does not know which firmware (PCM) " - "is required for your device (wl-core rev %u)\n", rev); - goto error; - -err_no_initvals: - err = ctx->fatal_failure = -EOPNOTSUPP; - b43err(dev->wl, "The driver does not know which firmware (initvals) " - "is required for your device (wl-core rev %u)\n", rev); - goto error; - -err_load: - /* We failed to load this firmware image. The error message - * already is in ctx->errors. Return and let our caller decide - * what to do. */ - goto error; - -error: - b43_release_firmware(dev); - return err; -} - -static int b43_request_firmware(struct b43_wldev *dev) -{ - struct b43_request_fw_context *ctx; - unsigned int i; - int err; - const char *errmsg; - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (!ctx) - return -ENOMEM; - ctx->dev = dev; - - ctx->req_type = B43_FWTYPE_PROPRIETARY; - err = b43_try_request_fw(ctx); - if (!err) - goto out; /* Successfully loaded it. */ - err = ctx->fatal_failure; - if (err) - goto out; - - ctx->req_type = B43_FWTYPE_OPENSOURCE; - err = b43_try_request_fw(ctx); - if (!err) - goto out; /* Successfully loaded it. */ - err = ctx->fatal_failure; - if (err) - goto out; - - /* Could not find a usable firmware. Print the errors. */ - for (i = 0; i < B43_NR_FWTYPES; i++) { - errmsg = ctx->errors[i]; - if (strlen(errmsg)) - b43err(dev->wl, errmsg); - } - b43_print_fw_helptext(dev->wl, 1); - err = -ENOENT; - -out: - kfree(ctx); - return err; -} - -static int b43_upload_microcode(struct b43_wldev *dev) -{ - const size_t hdr_len = sizeof(struct b43_fw_header); - const __be32 *data; - unsigned int i, len; - u16 fwrev, fwpatch, fwdate, fwtime; - u32 tmp, macctl; - int err = 0; - - /* Jump the microcode PSM to offset 0 */ - macctl = b43_read32(dev, B43_MMIO_MACCTL); - B43_WARN_ON(macctl & B43_MACCTL_PSM_RUN); - macctl |= B43_MACCTL_PSM_JMP0; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - /* Zero out all microcode PSM registers and shared memory. */ - for (i = 0; i < 64; i++) - b43_shm_write16(dev, B43_SHM_SCRATCH, i, 0); - for (i = 0; i < 4096; i += 2) - b43_shm_write16(dev, B43_SHM_SHARED, i, 0); - - /* Upload Microcode. */ - data = (__be32 *) (dev->fw.ucode.data->data + hdr_len); - len = (dev->fw.ucode.data->size - hdr_len) / sizeof(__be32); - b43_shm_control_word(dev, B43_SHM_UCODE | B43_SHM_AUTOINC_W, 0x0000); - for (i = 0; i < len; i++) { - b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i])); - udelay(10); - } - - if (dev->fw.pcm.data) { - /* Upload PCM data. */ - data = (__be32 *) (dev->fw.pcm.data->data + hdr_len); - len = (dev->fw.pcm.data->size - hdr_len) / sizeof(__be32); - b43_shm_control_word(dev, B43_SHM_HW, 0x01EA); - b43_write32(dev, B43_MMIO_SHM_DATA, 0x00004000); - /* No need for autoinc bit in SHM_HW */ - b43_shm_control_word(dev, B43_SHM_HW, 0x01EB); - for (i = 0; i < len; i++) { - b43_write32(dev, B43_MMIO_SHM_DATA, be32_to_cpu(data[i])); - udelay(10); - } - } - - b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, B43_IRQ_ALL); - - /* Start the microcode PSM */ - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_PSM_JMP0; - macctl |= B43_MACCTL_PSM_RUN; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - - /* Wait for the microcode to load and respond */ - i = 0; - while (1) { - tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); - if (tmp == B43_IRQ_MAC_SUSPENDED) - break; - i++; - if (i >= 20) { - b43err(dev->wl, "Microcode not responding\n"); - b43_print_fw_helptext(dev->wl, 1); - err = -ENODEV; - goto error; - } - msleep(50); - } - b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); /* dummy read */ - - /* Get and check the revisions. */ - fwrev = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEREV); - fwpatch = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEPATCH); - fwdate = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODEDATE); - fwtime = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_UCODETIME); - - if (fwrev <= 0x128) { - b43err(dev->wl, "YOUR FIRMWARE IS TOO OLD. Firmware from " - "binary drivers older than version 4.x is unsupported. " - "You must upgrade your firmware files.\n"); - b43_print_fw_helptext(dev->wl, 1); - err = -EOPNOTSUPP; - goto error; - } - dev->fw.rev = fwrev; - dev->fw.patch = fwpatch; - dev->fw.opensource = (fwdate == 0xFFFF); - - /* Default to use-all-queues. */ - dev->wl->hw->queues = dev->wl->mac80211_initially_registered_queues; - dev->qos_enabled = !!modparam_qos; - /* Default to firmware/hardware crypto acceleration. */ - dev->hwcrypto_enabled = 1; - - if (dev->fw.opensource) { - u16 fwcapa; - - /* Patchlevel info is encoded in the "time" field. */ - dev->fw.patch = fwtime; - b43info(dev->wl, "Loading OpenSource firmware version %u.%u\n", - dev->fw.rev, dev->fw.patch); - - fwcapa = b43_fwcapa_read(dev); - if (!(fwcapa & B43_FWCAPA_HWCRYPTO) || dev->fw.pcm_request_failed) { - b43info(dev->wl, "Hardware crypto acceleration not supported by firmware\n"); - /* Disable hardware crypto and fall back to software crypto. */ - dev->hwcrypto_enabled = 0; - } - if (!(fwcapa & B43_FWCAPA_QOS)) { - b43info(dev->wl, "QoS not supported by firmware\n"); - /* Disable QoS. Tweak hw->queues to 1. It will be restored before - * ieee80211_unregister to make sure the networking core can - * properly free possible resources. */ - dev->wl->hw->queues = 1; - dev->qos_enabled = 0; - } - } else { - b43info(dev->wl, "Loading firmware version %u.%u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", - fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, fwtime & 0x1F); - if (dev->fw.pcm_request_failed) { - b43warn(dev->wl, "No \"pcm5.fw\" firmware file found. " - "Hardware accelerated cryptography is disabled.\n"); - b43_print_fw_helptext(dev->wl, 0); - } - } - - if (b43_is_old_txhdr_format(dev)) { - /* We're over the deadline, but we keep support for old fw - * until it turns out to be in major conflict with something new. */ - b43warn(dev->wl, "You are using an old firmware image. " - "Support for old firmware will be removed soon " - "(official deadline was July 2008).\n"); - b43_print_fw_helptext(dev->wl, 0); - } - - return 0; - -error: - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_PSM_RUN; - macctl |= B43_MACCTL_PSM_JMP0; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - - return err; -} - -static int b43_write_initvals(struct b43_wldev *dev, - const struct b43_iv *ivals, - size_t count, - size_t array_size) -{ - const struct b43_iv *iv; - u16 offset; - size_t i; - bool bit32; - - BUILD_BUG_ON(sizeof(struct b43_iv) != 6); - iv = ivals; - for (i = 0; i < count; i++) { - if (array_size < sizeof(iv->offset_size)) - goto err_format; - array_size -= sizeof(iv->offset_size); - offset = be16_to_cpu(iv->offset_size); - bit32 = !!(offset & B43_IV_32BIT); - offset &= B43_IV_OFFSET_MASK; - if (offset >= 0x1000) - goto err_format; - if (bit32) { - u32 value; - - if (array_size < sizeof(iv->data.d32)) - goto err_format; - array_size -= sizeof(iv->data.d32); - - value = get_unaligned_be32(&iv->data.d32); - b43_write32(dev, offset, value); - - iv = (const struct b43_iv *)((const uint8_t *)iv + - sizeof(__be16) + - sizeof(__be32)); - } else { - u16 value; - - if (array_size < sizeof(iv->data.d16)) - goto err_format; - array_size -= sizeof(iv->data.d16); - - value = be16_to_cpu(iv->data.d16); - b43_write16(dev, offset, value); - - iv = (const struct b43_iv *)((const uint8_t *)iv + - sizeof(__be16) + - sizeof(__be16)); - } - } - if (array_size) - goto err_format; - - return 0; - -err_format: - b43err(dev->wl, "Initial Values Firmware file-format error.\n"); - b43_print_fw_helptext(dev->wl, 1); - - return -EPROTO; -} - -static int b43_upload_initvals(struct b43_wldev *dev) -{ - const size_t hdr_len = sizeof(struct b43_fw_header); - const struct b43_fw_header *hdr; - struct b43_firmware *fw = &dev->fw; - const struct b43_iv *ivals; - size_t count; - int err; - - hdr = (const struct b43_fw_header *)(fw->initvals.data->data); - ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len); - count = be32_to_cpu(hdr->size); - err = b43_write_initvals(dev, ivals, count, - fw->initvals.data->size - hdr_len); - if (err) - goto out; - if (fw->initvals_band.data) { - hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data); - ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len); - count = be32_to_cpu(hdr->size); - err = b43_write_initvals(dev, ivals, count, - fw->initvals_band.data->size - hdr_len); - if (err) - goto out; - } -out: - - return err; -} - -/* Initialize the GPIOs - * http://bcm-specs.sipsolutions.net/GPIO - */ -static int b43_gpio_init(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; - u32 mask, set; - - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_GPOUTSMSK); - - b43_write16(dev, B43_MMIO_GPIO_MASK, b43_read16(dev, B43_MMIO_GPIO_MASK) - | 0x000F); - - mask = 0x0000001F; - set = 0x0000000F; - if (dev->dev->bus->chip_id == 0x4301) { - mask |= 0x0060; - set |= 0x0060; - } - if (0 /* FIXME: conditional unknown */ ) { - b43_write16(dev, B43_MMIO_GPIO_MASK, - b43_read16(dev, B43_MMIO_GPIO_MASK) - | 0x0100); - mask |= 0x0180; - set |= 0x0180; - } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) { - b43_write16(dev, B43_MMIO_GPIO_MASK, - b43_read16(dev, B43_MMIO_GPIO_MASK) - | 0x0200); - mask |= 0x0200; - set |= 0x0200; - } - if (dev->dev->id.revision >= 2) - mask |= 0x0010; /* FIXME: This is redundant. */ - -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return 0; - ssb_write32(gpiodev, B43_GPIO_CONTROL, - (ssb_read32(gpiodev, B43_GPIO_CONTROL) - & mask) | set); - - return 0; -} - -/* Turn off all GPIO stuff. Call this on module unload, for example. */ -static void b43_gpio_cleanup(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; - -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return; - ssb_write32(gpiodev, B43_GPIO_CONTROL, 0); -} - -/* http://bcm-specs.sipsolutions.net/EnableMac */ -void b43_mac_enable(struct b43_wldev *dev) -{ - if (b43_debug(dev, B43_DBG_FIRMWARE)) { - u16 fwstate; - - fwstate = b43_shm_read16(dev, B43_SHM_SHARED, - B43_SHM_SH_UCODESTAT); - if ((fwstate != B43_SHM_SH_UCODESTAT_SUSP) && - (fwstate != B43_SHM_SH_UCODESTAT_SLEEP)) { - b43err(dev->wl, "b43_mac_enable(): The firmware " - "should be suspended, but current state is %u\n", - fwstate); - } - } - - dev->mac_suspended--; - B43_WARN_ON(dev->mac_suspended < 0); - if (dev->mac_suspended == 0) { - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - | B43_MACCTL_ENABLED); - b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, - B43_IRQ_MAC_SUSPENDED); - /* Commit writes */ - b43_read32(dev, B43_MMIO_MACCTL); - b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); - b43_power_saving_ctl_bits(dev, 0); - } -} - -/* http://bcm-specs.sipsolutions.net/SuspendMAC */ -void b43_mac_suspend(struct b43_wldev *dev) -{ - int i; - u32 tmp; - - might_sleep(); - B43_WARN_ON(dev->mac_suspended < 0); - - if (dev->mac_suspended == 0) { - b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_ENABLED); - /* force pci to flush the write */ - b43_read32(dev, B43_MMIO_MACCTL); - for (i = 35; i; i--) { - tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); - if (tmp & B43_IRQ_MAC_SUSPENDED) - goto out; - udelay(10); - } - /* Hm, it seems this will take some time. Use msleep(). */ - for (i = 40; i; i--) { - tmp = b43_read32(dev, B43_MMIO_GEN_IRQ_REASON); - if (tmp & B43_IRQ_MAC_SUSPENDED) - goto out; - msleep(1); - } - b43err(dev->wl, "MAC suspend failed\n"); - } -out: - dev->mac_suspended++; -} - -static void b43_adjust_opmode(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - u32 ctl; - u16 cfp_pretbtt; - - ctl = b43_read32(dev, B43_MMIO_MACCTL); - /* Reset status to STA infrastructure mode. */ - ctl &= ~B43_MACCTL_AP; - ctl &= ~B43_MACCTL_KEEP_CTL; - ctl &= ~B43_MACCTL_KEEP_BADPLCP; - ctl &= ~B43_MACCTL_KEEP_BAD; - ctl &= ~B43_MACCTL_PROMISC; - ctl &= ~B43_MACCTL_BEACPROMISC; - ctl |= B43_MACCTL_INFRA; - - if (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT)) - ctl |= B43_MACCTL_AP; - else if (b43_is_mode(wl, NL80211_IFTYPE_ADHOC)) - ctl &= ~B43_MACCTL_INFRA; - - if (wl->filter_flags & FIF_CONTROL) - ctl |= B43_MACCTL_KEEP_CTL; - if (wl->filter_flags & FIF_FCSFAIL) - ctl |= B43_MACCTL_KEEP_BAD; - if (wl->filter_flags & FIF_PLCPFAIL) - ctl |= B43_MACCTL_KEEP_BADPLCP; - if (wl->filter_flags & FIF_PROMISC_IN_BSS) - ctl |= B43_MACCTL_PROMISC; - if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC) - ctl |= B43_MACCTL_BEACPROMISC; - - /* Workaround: On old hardware the HW-MAC-address-filter - * doesn't work properly, so always run promisc in filter - * it in software. */ - if (dev->dev->id.revision <= 4) - ctl |= B43_MACCTL_PROMISC; - - b43_write32(dev, B43_MMIO_MACCTL, ctl); - - cfp_pretbtt = 2; - if ((ctl & B43_MACCTL_INFRA) && !(ctl & B43_MACCTL_AP)) { - if (dev->dev->bus->chip_id == 0x4306 && - dev->dev->bus->chip_rev == 3) - cfp_pretbtt = 100; - else - cfp_pretbtt = 50; - } - b43_write16(dev, 0x612, cfp_pretbtt); - - /* FIXME: We don't currently implement the PMQ mechanism, - * so always disable it. If we want to implement PMQ, - * we need to enable it here (clear DISCPMQ) in AP mode. - */ - if (0 /* ctl & B43_MACCTL_AP */) { - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_DISCPMQ); - } else { - b43_write32(dev, B43_MMIO_MACCTL, - b43_read32(dev, B43_MMIO_MACCTL) - | B43_MACCTL_DISCPMQ); - } -} - -static void b43_rate_memory_write(struct b43_wldev *dev, u16 rate, int is_ofdm) -{ - u16 offset; - - if (is_ofdm) { - offset = 0x480; - offset += (b43_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; - } else { - offset = 0x4C0; - offset += (b43_plcp_get_ratecode_cck(rate) & 0x000F) * 2; - } - b43_shm_write16(dev, B43_SHM_SHARED, offset + 0x20, - b43_shm_read16(dev, B43_SHM_SHARED, offset)); -} - -static void b43_rate_memory_init(struct b43_wldev *dev) -{ - switch (dev->phy.type) { - case B43_PHYTYPE_A: - case B43_PHYTYPE_G: - case B43_PHYTYPE_N: - case B43_PHYTYPE_LP: - b43_rate_memory_write(dev, B43_OFDM_RATE_6MB, 1); - b43_rate_memory_write(dev, B43_OFDM_RATE_12MB, 1); - b43_rate_memory_write(dev, B43_OFDM_RATE_18MB, 1); - b43_rate_memory_write(dev, B43_OFDM_RATE_24MB, 1); - b43_rate_memory_write(dev, B43_OFDM_RATE_36MB, 1); - b43_rate_memory_write(dev, B43_OFDM_RATE_48MB, 1); - b43_rate_memory_write(dev, B43_OFDM_RATE_54MB, 1); - if (dev->phy.type == B43_PHYTYPE_A) - break; - /* fallthrough */ - case B43_PHYTYPE_B: - b43_rate_memory_write(dev, B43_CCK_RATE_1MB, 0); - b43_rate_memory_write(dev, B43_CCK_RATE_2MB, 0); - b43_rate_memory_write(dev, B43_CCK_RATE_5MB, 0); - b43_rate_memory_write(dev, B43_CCK_RATE_11MB, 0); - break; - default: - B43_WARN_ON(1); - } -} - -/* Set the default values for the PHY TX Control Words. */ -static void b43_set_phytxctl_defaults(struct b43_wldev *dev) -{ - u16 ctl = 0; - - ctl |= B43_TXH_PHY_ENC_CCK; - ctl |= B43_TXH_PHY_ANT01AUTO; - ctl |= B43_TXH_PHY_TXPWR; - - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_BEACPHYCTL, ctl); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, ctl); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, ctl); -} - -/* Set the TX-Antenna for management frames sent by firmware. */ -static void b43_mgmtframe_txantenna(struct b43_wldev *dev, int antenna) -{ - u16 ant; - u16 tmp; - - ant = b43_antenna_to_phyctl(antenna); - - /* For ACK/CTS */ - tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL); - tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_ACKCTSPHYCTL, tmp); - /* For Probe Resposes */ - tmp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL); - tmp = (tmp & ~B43_TXH_PHY_ANT) | ant; - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRPHYCTL, tmp); -} - -/* This is the opposite of b43_chip_init() */ -static void b43_chip_exit(struct b43_wldev *dev) -{ - b43_phy_exit(dev); - b43_gpio_cleanup(dev); - /* firmware is released later */ -} - -/* Initialize the chip - * http://bcm-specs.sipsolutions.net/ChipInit - */ -static int b43_chip_init(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - int err; - u32 value32, macctl; - u16 value16; - - /* Initialize the MAC control */ - macctl = B43_MACCTL_IHR_ENABLED | B43_MACCTL_SHM_ENABLED; - if (dev->phy.gmode) - macctl |= B43_MACCTL_GMODE; - macctl |= B43_MACCTL_INFRA; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - - err = b43_request_firmware(dev); - if (err) - goto out; - err = b43_upload_microcode(dev); - if (err) - goto out; /* firmware is released later */ - - err = b43_gpio_init(dev); - if (err) - goto out; /* firmware is released later */ - - err = b43_upload_initvals(dev); - if (err) - goto err_gpio_clean; - - /* Turn the Analog on and initialize the PHY. */ - phy->ops->switch_analog(dev, 1); - err = b43_phy_init(dev); - if (err) - goto err_gpio_clean; - - /* Disable Interference Mitigation. */ - if (phy->ops->interf_mitigation) - phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); - - /* Select the antennae */ - if (phy->ops->set_rx_antenna) - phy->ops->set_rx_antenna(dev, B43_ANTENNA_DEFAULT); - b43_mgmtframe_txantenna(dev, B43_ANTENNA_DEFAULT); - - if (phy->type == B43_PHYTYPE_B) { - value16 = b43_read16(dev, 0x005E); - value16 |= 0x0004; - b43_write16(dev, 0x005E, value16); - } - b43_write32(dev, 0x0100, 0x01000000); - if (dev->dev->id.revision < 5) - b43_write32(dev, 0x010C, 0x01000000); - - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_INFRA); - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - | B43_MACCTL_INFRA); - - /* Probe Response Timeout value */ - /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ - b43_shm_write16(dev, B43_SHM_SHARED, 0x0074, 0x0000); - - /* Initially set the wireless operation mode. */ - b43_adjust_opmode(dev); - - if (dev->dev->id.revision < 3) { - b43_write16(dev, 0x060E, 0x0000); - b43_write16(dev, 0x0610, 0x8000); - b43_write16(dev, 0x0604, 0x0000); - b43_write16(dev, 0x0606, 0x0200); - } else { - b43_write32(dev, 0x0188, 0x80000000); - b43_write32(dev, 0x018C, 0x02000000); - } - b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000); - b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00); - b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00); - b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00); - b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00); - b43_write32(dev, B43_MMIO_DMA4_IRQ_MASK, 0x0000DC00); - b43_write32(dev, B43_MMIO_DMA5_IRQ_MASK, 0x0000DC00); - - value32 = ssb_read32(dev->dev, SSB_TMSLOW); - value32 |= 0x00100000; - ssb_write32(dev->dev, SSB_TMSLOW, value32); - - b43_write16(dev, B43_MMIO_POWERUP_DELAY, - dev->dev->bus->chipco.fast_pwrup_delay); - - err = 0; - b43dbg(dev->wl, "Chip initialized\n"); -out: - return err; - -err_gpio_clean: - b43_gpio_cleanup(dev); - return err; -} - -static void b43_periodic_every60sec(struct b43_wldev *dev) -{ - const struct b43_phy_operations *ops = dev->phy.ops; - - if (ops->pwork_60sec) - ops->pwork_60sec(dev); - - /* Force check the TX power emission now. */ - b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME); -} - -static void b43_periodic_every30sec(struct b43_wldev *dev) -{ - /* Update device statistics. */ - b43_calculate_link_quality(dev); -} - -static void b43_periodic_every15sec(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 wdr; - - if (dev->fw.opensource) { - /* Check if the firmware is still alive. - * It will reset the watchdog counter to 0 in its idle loop. */ - wdr = b43_shm_read16(dev, B43_SHM_SCRATCH, B43_WATCHDOG_REG); - if (unlikely(wdr)) { - b43err(dev->wl, "Firmware watchdog: The firmware died!\n"); - b43_controller_restart(dev, "Firmware watchdog"); - return; - } else { - b43_shm_write16(dev, B43_SHM_SCRATCH, - B43_WATCHDOG_REG, 1); - } - } - - if (phy->ops->pwork_15sec) - phy->ops->pwork_15sec(dev); - - atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); - wmb(); - -#if B43_DEBUG - if (b43_debug(dev, B43_DBG_VERBOSESTATS)) { - unsigned int i; - - b43dbg(dev->wl, "Stats: %7u IRQs/sec, %7u TX/sec, %7u RX/sec\n", - dev->irq_count / 15, - dev->tx_count / 15, - dev->rx_count / 15); - dev->irq_count = 0; - dev->tx_count = 0; - dev->rx_count = 0; - for (i = 0; i < ARRAY_SIZE(dev->irq_bit_count); i++) { - if (dev->irq_bit_count[i]) { - b43dbg(dev->wl, "Stats: %7u IRQ-%02u/sec (0x%08X)\n", - dev->irq_bit_count[i] / 15, i, (1 << i)); - dev->irq_bit_count[i] = 0; - } - } - } -#endif -} - -static void do_periodic_work(struct b43_wldev *dev) -{ - unsigned int state; - - state = dev->periodic_state; - if (state % 4 == 0) - b43_periodic_every60sec(dev); - if (state % 2 == 0) - b43_periodic_every30sec(dev); - b43_periodic_every15sec(dev); -} - -/* Periodic work locking policy: - * The whole periodic work handler is protected by - * wl->mutex. If another lock is needed somewhere in the - * pwork callchain, it's aquired in-place, where it's needed. - */ -static void b43_periodic_work_handler(struct work_struct *work) -{ - struct b43_wldev *dev = container_of(work, struct b43_wldev, - periodic_work.work); - struct b43_wl *wl = dev->wl; - unsigned long delay; - - mutex_lock(&wl->mutex); - - if (unlikely(b43_status(dev) != B43_STAT_STARTED)) - goto out; - if (b43_debug(dev, B43_DBG_PWORK_STOP)) - goto out_requeue; - - do_periodic_work(dev); - - dev->periodic_state++; -out_requeue: - if (b43_debug(dev, B43_DBG_PWORK_FAST)) - delay = msecs_to_jiffies(50); - else - delay = round_jiffies_relative(HZ * 15); - ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay); -out: - mutex_unlock(&wl->mutex); -} - -static void b43_periodic_tasks_setup(struct b43_wldev *dev) -{ - struct delayed_work *work = &dev->periodic_work; - - dev->periodic_state = 0; - INIT_DELAYED_WORK(work, b43_periodic_work_handler); - ieee80211_queue_delayed_work(dev->wl->hw, work, 0); -} - -/* Check if communication with the device works correctly. */ -static int b43_validate_chipaccess(struct b43_wldev *dev) -{ - u32 v, backup0, backup4; - - backup0 = b43_shm_read32(dev, B43_SHM_SHARED, 0); - backup4 = b43_shm_read32(dev, B43_SHM_SHARED, 4); - - /* Check for read/write and endianness problems. */ - b43_shm_write32(dev, B43_SHM_SHARED, 0, 0x55AAAA55); - if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0x55AAAA55) - goto error; - b43_shm_write32(dev, B43_SHM_SHARED, 0, 0xAA5555AA); - if (b43_shm_read32(dev, B43_SHM_SHARED, 0) != 0xAA5555AA) - goto error; - - /* Check if unaligned 32bit SHM_SHARED access works properly. - * However, don't bail out on failure, because it's noncritical. */ - b43_shm_write16(dev, B43_SHM_SHARED, 0, 0x1122); - b43_shm_write16(dev, B43_SHM_SHARED, 2, 0x3344); - b43_shm_write16(dev, B43_SHM_SHARED, 4, 0x5566); - b43_shm_write16(dev, B43_SHM_SHARED, 6, 0x7788); - if (b43_shm_read32(dev, B43_SHM_SHARED, 2) != 0x55663344) - b43warn(dev->wl, "Unaligned 32bit SHM read access is broken\n"); - b43_shm_write32(dev, B43_SHM_SHARED, 2, 0xAABBCCDD); - if (b43_shm_read16(dev, B43_SHM_SHARED, 0) != 0x1122 || - b43_shm_read16(dev, B43_SHM_SHARED, 2) != 0xCCDD || - b43_shm_read16(dev, B43_SHM_SHARED, 4) != 0xAABB || - b43_shm_read16(dev, B43_SHM_SHARED, 6) != 0x7788) - b43warn(dev->wl, "Unaligned 32bit SHM write access is broken\n"); - - b43_shm_write32(dev, B43_SHM_SHARED, 0, backup0); - b43_shm_write32(dev, B43_SHM_SHARED, 4, backup4); - - if ((dev->dev->id.revision >= 3) && (dev->dev->id.revision <= 10)) { - /* The 32bit register shadows the two 16bit registers - * with update sideeffects. Validate this. */ - b43_write16(dev, B43_MMIO_TSF_CFP_START, 0xAAAA); - b43_write32(dev, B43_MMIO_TSF_CFP_START, 0xCCCCBBBB); - if (b43_read16(dev, B43_MMIO_TSF_CFP_START_LOW) != 0xBBBB) - goto error; - if (b43_read16(dev, B43_MMIO_TSF_CFP_START_HIGH) != 0xCCCC) - goto error; - } - b43_write32(dev, B43_MMIO_TSF_CFP_START, 0); - - v = b43_read32(dev, B43_MMIO_MACCTL); - v |= B43_MACCTL_GMODE; - if (v != (B43_MACCTL_GMODE | B43_MACCTL_IHR_ENABLED)) - goto error; - - return 0; -error: - b43err(dev->wl, "Failed to validate the chipaccess\n"); - return -ENODEV; -} - -static void b43_security_init(struct b43_wldev *dev) -{ - dev->ktp = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_KTP); - /* KTP is a word address, but we address SHM bytewise. - * So multiply by two. - */ - dev->ktp *= 2; - /* Number of RCMTA address slots */ - b43_write16(dev, B43_MMIO_RCMTA_COUNT, B43_NR_PAIRWISE_KEYS); - /* Clear the key memory. */ - b43_clear_keys(dev); -} - -#ifdef CONFIG_B43_HWRNG -static int b43_rng_read(struct hwrng *rng, u32 *data) -{ - struct b43_wl *wl = (struct b43_wl *)rng->priv; - struct b43_wldev *dev; - int count = -ENODEV; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (likely(dev && b43_status(dev) >= B43_STAT_INITIALIZED)) { - *data = b43_read16(dev, B43_MMIO_RNG); - count = sizeof(u16); - } - mutex_unlock(&wl->mutex); - - return count; -} -#endif /* CONFIG_B43_HWRNG */ - -static void b43_rng_exit(struct b43_wl *wl) -{ -#ifdef CONFIG_B43_HWRNG - if (wl->rng_initialized) - hwrng_unregister(&wl->rng); -#endif /* CONFIG_B43_HWRNG */ -} - -static int b43_rng_init(struct b43_wl *wl) -{ - int err = 0; - -#ifdef CONFIG_B43_HWRNG - snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), - "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); - wl->rng.name = wl->rng_name; - wl->rng.data_read = b43_rng_read; - wl->rng.priv = (unsigned long)wl; - wl->rng_initialized = 1; - err = hwrng_register(&wl->rng); - if (err) { - wl->rng_initialized = 0; - b43err(wl, "Failed to register the random " - "number generator (%d)\n", err); - } -#endif /* CONFIG_B43_HWRNG */ - - return err; -} - -static void b43_tx_work(struct work_struct *work) -{ - struct b43_wl *wl = container_of(work, struct b43_wl, tx_work); - struct b43_wldev *dev; - struct sk_buff *skb; - int err = 0; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (unlikely(!dev || b43_status(dev) < B43_STAT_STARTED)) { - mutex_unlock(&wl->mutex); - return; - } - - while (skb_queue_len(&wl->tx_queue)) { - skb = skb_dequeue(&wl->tx_queue); - - if (b43_using_pio_transfers(dev)) - err = b43_pio_tx(dev, skb); - else - err = b43_dma_tx(dev, skb); - if (unlikely(err)) - dev_kfree_skb(skb); /* Drop it */ - } - -#if B43_DEBUG - dev->tx_count++; -#endif - mutex_unlock(&wl->mutex); -} - -static int b43_op_tx(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - - if (unlikely(skb->len < 2 + 2 + 6)) { - /* Too short, this can't be a valid frame. */ - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - B43_WARN_ON(skb_shinfo(skb)->nr_frags); - - skb_queue_tail(&wl->tx_queue, skb); - ieee80211_queue_work(wl->hw, &wl->tx_work); - - return NETDEV_TX_OK; -} - -static void b43_qos_params_upload(struct b43_wldev *dev, - const struct ieee80211_tx_queue_params *p, - u16 shm_offset) -{ - u16 params[B43_NR_QOSPARAMS]; - int bslots, tmp; - unsigned int i; - - if (!dev->qos_enabled) - return; - - bslots = b43_read16(dev, B43_MMIO_RNG) & p->cw_min; - - memset(¶ms, 0, sizeof(params)); - - params[B43_QOSPARAM_TXOP] = p->txop * 32; - params[B43_QOSPARAM_CWMIN] = p->cw_min; - params[B43_QOSPARAM_CWMAX] = p->cw_max; - params[B43_QOSPARAM_CWCUR] = p->cw_min; - params[B43_QOSPARAM_AIFS] = p->aifs; - params[B43_QOSPARAM_BSLOTS] = bslots; - params[B43_QOSPARAM_REGGAP] = bslots + p->aifs; - - for (i = 0; i < ARRAY_SIZE(params); i++) { - if (i == B43_QOSPARAM_STATUS) { - tmp = b43_shm_read16(dev, B43_SHM_SHARED, - shm_offset + (i * 2)); - /* Mark the parameters as updated. */ - tmp |= 0x100; - b43_shm_write16(dev, B43_SHM_SHARED, - shm_offset + (i * 2), - tmp); - } else { - b43_shm_write16(dev, B43_SHM_SHARED, - shm_offset + (i * 2), - params[i]); - } - } -} - -/* Mapping of mac80211 queue numbers to b43 QoS SHM offsets. */ -static const u16 b43_qos_shm_offsets[] = { - /* [mac80211-queue-nr] = SHM_OFFSET, */ - [0] = B43_QOS_VOICE, - [1] = B43_QOS_VIDEO, - [2] = B43_QOS_BESTEFFORT, - [3] = B43_QOS_BACKGROUND, -}; - -/* Update all QOS parameters in hardware. */ -static void b43_qos_upload_all(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - struct b43_qos_params *params; - unsigned int i; - - if (!dev->qos_enabled) - return; - - BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != - ARRAY_SIZE(wl->qos_params)); - - b43_mac_suspend(dev); - for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { - params = &(wl->qos_params[i]); - b43_qos_params_upload(dev, &(params->p), - b43_qos_shm_offsets[i]); - } - b43_mac_enable(dev); -} - -static void b43_qos_clear(struct b43_wl *wl) -{ - struct b43_qos_params *params; - unsigned int i; - - /* Initialize QoS parameters to sane defaults. */ - - BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != - ARRAY_SIZE(wl->qos_params)); - - for (i = 0; i < ARRAY_SIZE(wl->qos_params); i++) { - params = &(wl->qos_params[i]); - - switch (b43_qos_shm_offsets[i]) { - case B43_QOS_VOICE: - params->p.txop = 0; - params->p.aifs = 2; - params->p.cw_min = 0x0001; - params->p.cw_max = 0x0001; - break; - case B43_QOS_VIDEO: - params->p.txop = 0; - params->p.aifs = 2; - params->p.cw_min = 0x0001; - params->p.cw_max = 0x0001; - break; - case B43_QOS_BESTEFFORT: - params->p.txop = 0; - params->p.aifs = 3; - params->p.cw_min = 0x0001; - params->p.cw_max = 0x03FF; - break; - case B43_QOS_BACKGROUND: - params->p.txop = 0; - params->p.aifs = 7; - params->p.cw_min = 0x0001; - params->p.cw_max = 0x03FF; - break; - default: - B43_WARN_ON(1); - } - } -} - -/* Initialize the core's QOS capabilities */ -static void b43_qos_init(struct b43_wldev *dev) -{ - if (!dev->qos_enabled) { - /* Disable QOS support. */ - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_EDCF); - b43_write16(dev, B43_MMIO_IFSCTL, - b43_read16(dev, B43_MMIO_IFSCTL) - & ~B43_MMIO_IFSCTL_USE_EDCF); - b43dbg(dev->wl, "QoS disabled\n"); - return; - } - - /* Upload the current QOS parameters. */ - b43_qos_upload_all(dev); - - /* Enable QOS support. */ - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_EDCF); - b43_write16(dev, B43_MMIO_IFSCTL, - b43_read16(dev, B43_MMIO_IFSCTL) - | B43_MMIO_IFSCTL_USE_EDCF); - b43dbg(dev->wl, "QoS enabled\n"); -} - -static int b43_op_conf_tx(struct ieee80211_hw *hw, u16 _queue, - const struct ieee80211_tx_queue_params *params) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - unsigned int queue = (unsigned int)_queue; - int err = -ENODEV; - - if (queue >= ARRAY_SIZE(wl->qos_params)) { - /* Queue not available or don't support setting - * params on this queue. Return success to not - * confuse mac80211. */ - return 0; - } - BUILD_BUG_ON(ARRAY_SIZE(b43_qos_shm_offsets) != - ARRAY_SIZE(wl->qos_params)); - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (unlikely(!dev || (b43_status(dev) < B43_STAT_INITIALIZED))) - goto out_unlock; - - memcpy(&(wl->qos_params[queue].p), params, sizeof(*params)); - b43_mac_suspend(dev); - b43_qos_params_upload(dev, &(wl->qos_params[queue].p), - b43_qos_shm_offsets[queue]); - b43_mac_enable(dev); - err = 0; - -out_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - -static int b43_op_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - int err = -ENODEV; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (dev && b43_status(dev) >= B43_STAT_STARTED) { - if (b43_using_pio_transfers(dev)) - b43_pio_get_tx_stats(dev, stats); - else - b43_dma_get_tx_stats(dev, stats); - err = 0; - } - mutex_unlock(&wl->mutex); - - return err; -} - -static int b43_op_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - - mutex_lock(&wl->mutex); - memcpy(stats, &wl->ieee_stats, sizeof(*stats)); - mutex_unlock(&wl->mutex); - - return 0; -} - -static u64 b43_op_get_tsf(struct ieee80211_hw *hw) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - u64 tsf; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - - if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) - b43_tsf_read(dev, &tsf); - else - tsf = 0; - - mutex_unlock(&wl->mutex); - - return tsf; -} - -static void b43_op_set_tsf(struct ieee80211_hw *hw, u64 tsf) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - - if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) - b43_tsf_write(dev, tsf); - - mutex_unlock(&wl->mutex); -} - -static void b43_put_phy_into_reset(struct b43_wldev *dev) -{ - struct ssb_device *sdev = dev->dev; - u32 tmslow; - - tmslow = ssb_read32(sdev, SSB_TMSLOW); - tmslow &= ~B43_TMSLOW_GMODE; - tmslow |= B43_TMSLOW_PHYRESET; - tmslow |= SSB_TMSLOW_FGC; - ssb_write32(sdev, SSB_TMSLOW, tmslow); - msleep(1); - - tmslow = ssb_read32(sdev, SSB_TMSLOW); - tmslow &= ~SSB_TMSLOW_FGC; - tmslow |= B43_TMSLOW_PHYRESET; - ssb_write32(sdev, SSB_TMSLOW, tmslow); - msleep(1); -} - -static const char *band_to_string(enum ieee80211_band band) -{ - switch (band) { - case IEEE80211_BAND_5GHZ: - return "5"; - case IEEE80211_BAND_2GHZ: - return "2.4"; - default: - break; - } - B43_WARN_ON(1); - return ""; -} - -/* Expects wl->mutex locked */ -static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan) -{ - struct b43_wldev *up_dev = NULL; - struct b43_wldev *down_dev; - struct b43_wldev *d; - int err; - bool uninitialized_var(gmode); - int prev_status; - - /* Find a device and PHY which supports the band. */ - list_for_each_entry(d, &wl->devlist, list) { - switch (chan->band) { - case IEEE80211_BAND_5GHZ: - if (d->phy.supports_5ghz) { - up_dev = d; - gmode = 0; - } - break; - case IEEE80211_BAND_2GHZ: - if (d->phy.supports_2ghz) { - up_dev = d; - gmode = 1; - } - break; - default: - B43_WARN_ON(1); - return -EINVAL; - } - if (up_dev) - break; - } - if (!up_dev) { - b43err(wl, "Could not find a device for %s-GHz band operation\n", - band_to_string(chan->band)); - return -ENODEV; - } - if ((up_dev == wl->current_dev) && - (!!wl->current_dev->phy.gmode == !!gmode)) { - /* This device is already running. */ - return 0; - } - b43dbg(wl, "Switching to %s-GHz band\n", - band_to_string(chan->band)); - down_dev = wl->current_dev; - - prev_status = b43_status(down_dev); - /* Shutdown the currently running core. */ - if (prev_status >= B43_STAT_STARTED) - down_dev = b43_wireless_core_stop(down_dev); - if (prev_status >= B43_STAT_INITIALIZED) - b43_wireless_core_exit(down_dev); - - if (down_dev != up_dev) { - /* We switch to a different core, so we put PHY into - * RESET on the old core. */ - b43_put_phy_into_reset(down_dev); - } - - /* Now start the new core. */ - up_dev->phy.gmode = gmode; - if (prev_status >= B43_STAT_INITIALIZED) { - err = b43_wireless_core_init(up_dev); - if (err) { - b43err(wl, "Fatal: Could not initialize device for " - "selected %s-GHz band\n", - band_to_string(chan->band)); - goto init_failure; - } - } - if (prev_status >= B43_STAT_STARTED) { - err = b43_wireless_core_start(up_dev); - if (err) { - b43err(wl, "Fatal: Coult not start device for " - "selected %s-GHz band\n", - band_to_string(chan->band)); - b43_wireless_core_exit(up_dev); - goto init_failure; - } - } - B43_WARN_ON(b43_status(up_dev) != prev_status); - - wl->current_dev = up_dev; - - return 0; -init_failure: - /* Whoops, failed to init the new core. No core is operating now. */ - wl->current_dev = NULL; - return err; -} - -/* Write the short and long frame retry limit values. */ -static void b43_set_retry_limits(struct b43_wldev *dev, - unsigned int short_retry, - unsigned int long_retry) -{ - /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. */ - short_retry = min(short_retry, (unsigned int)0xF); - long_retry = min(long_retry, (unsigned int)0xF); - - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_SRLIMIT, - short_retry); - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_LRLIMIT, - long_retry); -} - -static int b43_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - struct b43_phy *phy; - struct ieee80211_conf *conf = &hw->conf; - int antenna; - int err = 0; - - mutex_lock(&wl->mutex); - - /* Switch the band (if necessary). This might change the active core. */ - err = b43_switch_band(wl, conf->channel); - if (err) - goto out_unlock_mutex; - dev = wl->current_dev; - phy = &dev->phy; - - b43_mac_suspend(dev); - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - b43_set_retry_limits(dev, conf->short_frame_max_tx_count, - conf->long_frame_max_tx_count); - changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; - if (!changed) - goto out_mac_enable; - - /* Switch to the requested channel. - * The firmware takes care of races with the TX handler. */ - if (conf->channel->hw_value != phy->channel) - b43_switch_channel(dev, conf->channel->hw_value); - - dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); - - /* Adjust the desired TX power level. */ - if (conf->power_level != 0) { - if (conf->power_level != phy->desired_txpower) { - phy->desired_txpower = conf->power_level; - b43_phy_txpower_check(dev, B43_TXPWR_IGNORE_TIME | - B43_TXPWR_IGNORE_TSSI); - } - } - - /* Antennas for RX and management frame TX. */ - antenna = B43_ANTENNA_DEFAULT; - b43_mgmtframe_txantenna(dev, antenna); - antenna = B43_ANTENNA_DEFAULT; - if (phy->ops->set_rx_antenna) - phy->ops->set_rx_antenna(dev, antenna); - - if (wl->radio_enabled != phy->radio_on) { - if (wl->radio_enabled) { - b43_software_rfkill(dev, false); - b43info(dev->wl, "Radio turned on by software\n"); - if (!dev->radio_hw_enable) { - b43info(dev->wl, "The hardware RF-kill button " - "still turns the radio physically off. " - "Press the button to turn it on.\n"); - } - } else { - b43_software_rfkill(dev, true); - b43info(dev->wl, "Radio turned off by software\n"); - } - } - -out_mac_enable: - b43_mac_enable(dev); -out_unlock_mutex: - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43_update_basic_rates(struct b43_wldev *dev, u32 brates) -{ - struct ieee80211_supported_band *sband = - dev->wl->hw->wiphy->bands[b43_current_band(dev->wl)]; - struct ieee80211_rate *rate; - int i; - u16 basic, direct, offset, basic_offset, rateptr; - - for (i = 0; i < sband->n_bitrates; i++) { - rate = &sband->bitrates[i]; - - if (b43_is_cck_rate(rate->hw_value)) { - direct = B43_SHM_SH_CCKDIRECT; - basic = B43_SHM_SH_CCKBASIC; - offset = b43_plcp_get_ratecode_cck(rate->hw_value); - offset &= 0xF; - } else { - direct = B43_SHM_SH_OFDMDIRECT; - basic = B43_SHM_SH_OFDMBASIC; - offset = b43_plcp_get_ratecode_ofdm(rate->hw_value); - offset &= 0xF; - } - - rate = ieee80211_get_response_rate(sband, brates, rate->bitrate); - - if (b43_is_cck_rate(rate->hw_value)) { - basic_offset = b43_plcp_get_ratecode_cck(rate->hw_value); - basic_offset &= 0xF; - } else { - basic_offset = b43_plcp_get_ratecode_ofdm(rate->hw_value); - basic_offset &= 0xF; - } - - /* - * Get the pointer that we need to point to - * from the direct map - */ - rateptr = b43_shm_read16(dev, B43_SHM_SHARED, - direct + 2 * basic_offset); - /* and write it to the basic map */ - b43_shm_write16(dev, B43_SHM_SHARED, basic + 2 * offset, - rateptr); - } -} - -static void b43_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, - u32 changed) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - - dev = wl->current_dev; - if (!dev || b43_status(dev) < B43_STAT_STARTED) - goto out_unlock_mutex; - - B43_WARN_ON(wl->vif != vif); - - if (changed & BSS_CHANGED_BSSID) { - if (conf->bssid) - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - else - memset(wl->bssid, 0, ETH_ALEN); - } - - if (b43_status(dev) >= B43_STAT_INITIALIZED) { - if (changed & BSS_CHANGED_BEACON && - (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || - b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) - b43_update_templates(wl); - - if (changed & BSS_CHANGED_BSSID) - b43_write_mac_bssid_templates(dev); - } - - b43_mac_suspend(dev); - - /* Update templates for AP/mesh mode. */ - if (changed & BSS_CHANGED_BEACON_INT && - (b43_is_mode(wl, NL80211_IFTYPE_AP) || - b43_is_mode(wl, NL80211_IFTYPE_MESH_POINT) || - b43_is_mode(wl, NL80211_IFTYPE_ADHOC))) - b43_set_beacon_int(dev, conf->beacon_int); - - if (changed & BSS_CHANGED_BASIC_RATES) - b43_update_basic_rates(dev, conf->basic_rates); - - if (changed & BSS_CHANGED_ERP_SLOT) { - if (conf->use_short_slot) - b43_short_slot_timing_enable(dev); - else - b43_short_slot_timing_disable(dev); - } - - b43_mac_enable(dev); -out_unlock_mutex: - mutex_unlock(&wl->mutex); -} - -static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - u8 algorithm; - u8 index; - int err; - static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - if (modparam_nohwcrypt) - return -ENOSPC; /* User disabled HW-crypto */ - - mutex_lock(&wl->mutex); - - dev = wl->current_dev; - err = -ENODEV; - if (!dev || b43_status(dev) < B43_STAT_INITIALIZED) - goto out_unlock; - - if (dev->fw.pcm_request_failed || !dev->hwcrypto_enabled) { - /* We don't have firmware for the crypto engine. - * Must use software-crypto. */ - err = -EOPNOTSUPP; - goto out_unlock; - } - - err = -EINVAL; - switch (key->alg) { - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - algorithm = B43_SEC_ALGO_WEP40; - else - algorithm = B43_SEC_ALGO_WEP104; - break; - case ALG_TKIP: - algorithm = B43_SEC_ALGO_TKIP; - break; - case ALG_CCMP: - algorithm = B43_SEC_ALGO_AES; - break; - default: - B43_WARN_ON(1); - goto out_unlock; - } - index = (u8) (key->keyidx); - if (index > 3) - goto out_unlock; - - switch (cmd) { - case SET_KEY: - if (algorithm == B43_SEC_ALGO_TKIP && - (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE) || - !modparam_hwtkip)) { - /* We support only pairwise key */ - err = -EOPNOTSUPP; - goto out_unlock; - } - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { - if (WARN_ON(!sta)) { - err = -EOPNOTSUPP; - goto out_unlock; - } - /* Pairwise key with an assigned MAC address. */ - err = b43_key_write(dev, -1, algorithm, - key->key, key->keylen, - sta->addr, key); - } else { - /* Group key */ - err = b43_key_write(dev, index, algorithm, - key->key, key->keylen, NULL, key); - } - if (err) - goto out_unlock; - - if (algorithm == B43_SEC_ALGO_WEP40 || - algorithm == B43_SEC_ALGO_WEP104) { - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_USEDEFKEYS); - } else { - b43_hf_write(dev, - b43_hf_read(dev) & ~B43_HF_USEDEFKEYS); - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - if (algorithm == B43_SEC_ALGO_TKIP) - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - break; - case DISABLE_KEY: { - err = b43_key_clear(dev, key->hw_key_idx); - if (err) - goto out_unlock; - break; - } - default: - B43_WARN_ON(1); - } - -out_unlock: - if (!err) { - b43dbg(wl, "%s hardware based encryption for keyidx: %d, " - "mac: %pM\n", - cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, - sta ? sta->addr : bcast_addr); - b43_dump_keymemory(dev); - } - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed, unsigned int *fflags, - u64 multicast) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (!dev) { - *fflags = 0; - goto out_unlock; - } - - *fflags &= FIF_PROMISC_IN_BSS | - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_BCN_PRBRESP_PROMISC; - - changed &= FIF_PROMISC_IN_BSS | - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_BCN_PRBRESP_PROMISC; - - wl->filter_flags = *fflags; - - if (changed && b43_status(dev) >= B43_STAT_INITIALIZED) - b43_adjust_opmode(dev); - -out_unlock: - mutex_unlock(&wl->mutex); -} - -/* Locking: wl->mutex - * Returns the current dev. This might be different from the passed in dev, - * because the core might be gone away while we unlocked the mutex. */ -static struct b43_wldev * b43_wireless_core_stop(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - struct b43_wldev *orig_dev; - u32 mask; - -redo: - if (!dev || b43_status(dev) < B43_STAT_STARTED) - return dev; - - /* Cancel work. Unlock to avoid deadlocks. */ - mutex_unlock(&wl->mutex); - cancel_delayed_work_sync(&dev->periodic_work); - cancel_work_sync(&wl->tx_work); - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (!dev || b43_status(dev) < B43_STAT_STARTED) { - /* Whoops, aliens ate up the device while we were unlocked. */ - return dev; - } - - /* Disable interrupts on the device. */ - b43_set_status(dev, B43_STAT_INITIALIZED); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { - /* wl->mutex is locked. That is enough. */ - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); - b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ - } else { - spin_lock_irq(&wl->hardirq_lock); - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, 0); - b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); /* Flush */ - spin_unlock_irq(&wl->hardirq_lock); - } - /* Synchronize and free the interrupt handlers. Unlock to avoid deadlocks. */ - orig_dev = dev; - mutex_unlock(&wl->mutex); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { - b43_sdio_free_irq(dev); - } else { - synchronize_irq(dev->dev->irq); - free_irq(dev->dev->irq, dev); - } - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (!dev) - return dev; - if (dev != orig_dev) { - if (b43_status(dev) >= B43_STAT_STARTED) - goto redo; - return dev; - } - mask = b43_read32(dev, B43_MMIO_GEN_IRQ_MASK); - B43_WARN_ON(mask != 0xFFFFFFFF && mask); - - /* Drain the TX queue */ - while (skb_queue_len(&wl->tx_queue)) - dev_kfree_skb(skb_dequeue(&wl->tx_queue)); - - b43_mac_suspend(dev); - b43_leds_exit(dev); - b43dbg(wl, "Wireless interface stopped\n"); - - return dev; -} - -/* Locking: wl->mutex */ -static int b43_wireless_core_start(struct b43_wldev *dev) -{ - int err; - - B43_WARN_ON(b43_status(dev) != B43_STAT_INITIALIZED); - - drain_txstatus_queue(dev); - if (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) { - err = b43_sdio_request_irq(dev, b43_sdio_interrupt_handler); - if (err) { - b43err(dev->wl, "Cannot request SDIO IRQ\n"); - goto out; - } - } else { - err = request_threaded_irq(dev->dev->irq, b43_interrupt_handler, - b43_interrupt_thread_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (err) { - b43err(dev->wl, "Cannot request IRQ-%d\n", dev->dev->irq); - goto out; - } - } - - /* We are ready to run. */ - ieee80211_wake_queues(dev->wl->hw); - b43_set_status(dev, B43_STAT_STARTED); - - /* Start data flow (TX/RX). */ - b43_mac_enable(dev); - b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask); - - /* Start maintainance work */ - b43_periodic_tasks_setup(dev); - - b43_leds_init(dev); - - b43dbg(dev->wl, "Wireless interface started\n"); -out: - return err; -} - -/* Get PHY and RADIO versioning numbers */ -static int b43_phy_versioning(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u32 tmp; - u8 analog_type; - u8 phy_type; - u8 phy_rev; - u16 radio_manuf; - u16 radio_ver; - u16 radio_rev; - int unsupported = 0; - - /* Get PHY versioning */ - tmp = b43_read16(dev, B43_MMIO_PHY_VER); - analog_type = (tmp & B43_PHYVER_ANALOG) >> B43_PHYVER_ANALOG_SHIFT; - phy_type = (tmp & B43_PHYVER_TYPE) >> B43_PHYVER_TYPE_SHIFT; - phy_rev = (tmp & B43_PHYVER_VERSION); - switch (phy_type) { - case B43_PHYTYPE_A: - if (phy_rev >= 4) - unsupported = 1; - break; - case B43_PHYTYPE_B: - if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 - && phy_rev != 7) - unsupported = 1; - break; - case B43_PHYTYPE_G: - if (phy_rev > 9) - unsupported = 1; - break; -#ifdef CONFIG_B43_NPHY - case B43_PHYTYPE_N: - if (phy_rev > 4) - unsupported = 1; - break; -#endif -#ifdef CONFIG_B43_PHY_LP - case B43_PHYTYPE_LP: - if (phy_rev > 2) - unsupported = 1; - break; -#endif - default: - unsupported = 1; - }; - if (unsupported) { - b43err(dev->wl, "FOUND UNSUPPORTED PHY " - "(Analog %u, Type %u, Revision %u)\n", - analog_type, phy_type, phy_rev); - return -EOPNOTSUPP; - } - b43dbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n", - analog_type, phy_type, phy_rev); - - /* Get RADIO versioning */ - if (dev->dev->bus->chip_id == 0x4317) { - if (dev->dev->bus->chip_rev == 0) - tmp = 0x3205017F; - else if (dev->dev->bus->chip_rev == 1) - tmp = 0x4205017F; - else - tmp = 0x5205017F; - } else { - b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID); - tmp = b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); - b43_write16(dev, B43_MMIO_RADIO_CONTROL, B43_RADIOCTL_ID); - tmp |= (u32)b43_read16(dev, B43_MMIO_RADIO_DATA_HIGH) << 16; - } - radio_manuf = (tmp & 0x00000FFF); - radio_ver = (tmp & 0x0FFFF000) >> 12; - radio_rev = (tmp & 0xF0000000) >> 28; - if (radio_manuf != 0x17F /* Broadcom */) - unsupported = 1; - switch (phy_type) { - case B43_PHYTYPE_A: - if (radio_ver != 0x2060) - unsupported = 1; - if (radio_rev != 1) - unsupported = 1; - if (radio_manuf != 0x17F) - unsupported = 1; - break; - case B43_PHYTYPE_B: - if ((radio_ver & 0xFFF0) != 0x2050) - unsupported = 1; - break; - case B43_PHYTYPE_G: - if (radio_ver != 0x2050) - unsupported = 1; - break; - case B43_PHYTYPE_N: - if (radio_ver != 0x2055 && radio_ver != 0x2056) - unsupported = 1; - break; - case B43_PHYTYPE_LP: - if (radio_ver != 0x2062 && radio_ver != 0x2063) - unsupported = 1; - break; - default: - B43_WARN_ON(1); - } - if (unsupported) { - b43err(dev->wl, "FOUND UNSUPPORTED RADIO " - "(Manuf 0x%X, Version 0x%X, Revision %u)\n", - radio_manuf, radio_ver, radio_rev); - return -EOPNOTSUPP; - } - b43dbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X, Revision %u\n", - radio_manuf, radio_ver, radio_rev); - - phy->radio_manuf = radio_manuf; - phy->radio_ver = radio_ver; - phy->radio_rev = radio_rev; - - phy->analog = analog_type; - phy->type = phy_type; - phy->rev = phy_rev; - - return 0; -} - -static void setup_struct_phy_for_init(struct b43_wldev *dev, - struct b43_phy *phy) -{ - phy->hardware_power_control = !!modparam_hwpctl; - phy->next_txpwr_check_time = jiffies; - /* PHY TX errors counter. */ - atomic_set(&phy->txerr_cnt, B43_PHY_TX_BADNESS_LIMIT); - -#if B43_DEBUG - phy->phy_locked = 0; - phy->radio_locked = 0; -#endif -} - -static void setup_struct_wldev_for_init(struct b43_wldev *dev) -{ - dev->dfq_valid = 0; - - /* Assume the radio is enabled. If it's not enabled, the state will - * immediately get fixed on the first periodic work run. */ - dev->radio_hw_enable = 1; - - /* Stats */ - memset(&dev->stats, 0, sizeof(dev->stats)); - - setup_struct_phy_for_init(dev, &dev->phy); - - /* IRQ related flags */ - dev->irq_reason = 0; - memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); - dev->irq_mask = B43_IRQ_MASKTEMPLATE; - if (b43_modparam_verbose < B43_VERBOSITY_DEBUG) - dev->irq_mask &= ~B43_IRQ_PHY_TXERR; - - dev->mac_suspended = 1; - - /* Noise calculation context */ - memset(&dev->noisecalc, 0, sizeof(dev->noisecalc)); -} - -static void b43_bluetooth_coext_enable(struct b43_wldev *dev) -{ - struct ssb_sprom *sprom = &dev->dev->bus->sprom; - u64 hf; - - if (!modparam_btcoex) - return; - if (!(sprom->boardflags_lo & B43_BFL_BTCOEXIST)) - return; - if (dev->phy.type != B43_PHYTYPE_B && !dev->phy.gmode) - return; - - hf = b43_hf_read(dev); - if (sprom->boardflags_lo & B43_BFL_BTCMOD) - hf |= B43_HF_BTCOEXALT; - else - hf |= B43_HF_BTCOEX; - b43_hf_write(dev, hf); -} - -static void b43_bluetooth_coext_disable(struct b43_wldev *dev) -{ - if (!modparam_btcoex) - return; - //TODO -} - -static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev) -{ -#ifdef CONFIG_SSB_DRIVER_PCICORE - struct ssb_bus *bus = dev->dev->bus; - u32 tmp; - - if (bus->pcicore.dev && - bus->pcicore.dev->id.coreid == SSB_DEV_PCI && - bus->pcicore.dev->id.revision <= 5) { - /* IMCFGLO timeouts workaround. */ - tmp = ssb_read32(dev->dev, SSB_IMCFGLO); - switch (bus->bustype) { - case SSB_BUSTYPE_PCI: - case SSB_BUSTYPE_PCMCIA: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x32; - break; - case SSB_BUSTYPE_SSB: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x53; - break; - default: - break; - } - ssb_write32(dev->dev, SSB_IMCFGLO, tmp); - } -#endif /* CONFIG_SSB_DRIVER_PCICORE */ -} - -static void b43_set_synth_pu_delay(struct b43_wldev *dev, bool idle) -{ - u16 pu_delay; - - /* The time value is in microseconds. */ - if (dev->phy.type == B43_PHYTYPE_A) - pu_delay = 3700; - else - pu_delay = 1050; - if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle) - pu_delay = 500; - if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) - pu_delay = max(pu_delay, (u16)2400); - - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SPUWKUP, pu_delay); -} - -/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */ -static void b43_set_pretbtt(struct b43_wldev *dev) -{ - u16 pretbtt; - - /* The time value is in microseconds. */ - if (b43_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) { - pretbtt = 2; - } else { - if (dev->phy.type == B43_PHYTYPE_A) - pretbtt = 120; - else - pretbtt = 250; - } - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRETBTT, pretbtt); - b43_write16(dev, B43_MMIO_TSF_CFP_PRETBTT, pretbtt); -} - -/* Shutdown a wireless core */ -/* Locking: wl->mutex */ -static void b43_wireless_core_exit(struct b43_wldev *dev) -{ - u32 macctl; - - B43_WARN_ON(dev && b43_status(dev) > B43_STAT_INITIALIZED); - if (!dev || b43_status(dev) != B43_STAT_INITIALIZED) - return; - b43_set_status(dev, B43_STAT_UNINIT); - - /* Stop the microcode PSM. */ - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_PSM_RUN; - macctl |= B43_MACCTL_PSM_JMP0; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - - b43_dma_free(dev); - b43_pio_free(dev); - b43_chip_exit(dev); - dev->phy.ops->switch_analog(dev, 0); - if (dev->wl->current_beacon) { - dev_kfree_skb_any(dev->wl->current_beacon); - dev->wl->current_beacon = NULL; - } - - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(dev->dev->bus); -} - -/* Initialize a wireless core */ -static int b43_wireless_core_init(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct ssb_sprom *sprom = &bus->sprom; - struct b43_phy *phy = &dev->phy; - int err; - u64 hf; - u32 tmp; - - B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); - - err = ssb_bus_powerup(bus, 0); - if (err) - goto out; - if (!ssb_device_is_enabled(dev->dev)) { - tmp = phy->gmode ? B43_TMSLOW_GMODE : 0; - b43_wireless_core_reset(dev, tmp); - } - - /* Reset all data structures. */ - setup_struct_wldev_for_init(dev); - phy->ops->prepare_structs(dev); - - /* Enable IRQ routing to this device. */ - ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); - - b43_imcfglo_timeouts_workaround(dev); - b43_bluetooth_coext_disable(dev); - if (phy->ops->prepare_hardware) { - err = phy->ops->prepare_hardware(dev); - if (err) - goto err_busdown; - } - err = b43_chip_init(dev); - if (err) - goto err_busdown; - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_WLCOREREV, dev->dev->id.revision); - hf = b43_hf_read(dev); - if (phy->type == B43_PHYTYPE_G) { - hf |= B43_HF_SYMW; - if (phy->rev == 1) - hf |= B43_HF_GDCW; - if (sprom->boardflags_lo & B43_BFL_PACTRL) - hf |= B43_HF_OFDMPABOOST; - } - if (phy->radio_ver == 0x2050) { - if (phy->radio_rev == 6) - hf |= B43_HF_4318TSSI; - if (phy->radio_rev < 6) - hf |= B43_HF_VCORECALC; - } - if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW) - hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */ -#ifdef CONFIG_SSB_DRIVER_PCICORE - if ((bus->bustype == SSB_BUSTYPE_PCI) && - (bus->pcicore.dev->id.revision <= 10)) - hf |= B43_HF_PCISCW; /* PCI slow clock workaround. */ -#endif - hf &= ~B43_HF_SKCFPUP; - b43_hf_write(dev, hf); - - b43_set_retry_limits(dev, B43_DEFAULT_SHORT_RETRY_LIMIT, - B43_DEFAULT_LONG_RETRY_LIMIT); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_SFFBLIM, 3); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_LFFBLIM, 2); - - /* Disable sending probe responses from firmware. - * Setting the MaxTime to one usec will always trigger - * a timeout, so we never send any probe resp. - * A timeout of zero is infinite. */ - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_PRMAXTIME, 1); - - b43_rate_memory_init(dev); - b43_set_phytxctl_defaults(dev); - - /* Minimum Contention Window */ - if (phy->type == B43_PHYTYPE_B) { - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0x1F); - } else { - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MINCONT, 0xF); - } - /* Maximum Contention Window */ - b43_shm_write16(dev, B43_SHM_SCRATCH, B43_SHM_SC_MAXCONT, 0x3FF); - - if ((dev->dev->bus->bustype == SSB_BUSTYPE_PCMCIA) || - (dev->dev->bus->bustype == SSB_BUSTYPE_SDIO) || - dev->use_pio) { - dev->__using_pio_transfers = 1; - err = b43_pio_init(dev); - } else { - dev->__using_pio_transfers = 0; - err = b43_dma_init(dev); - } - if (err) - goto err_chip_exit; - b43_qos_init(dev); - b43_set_synth_pu_delay(dev, 1); - b43_bluetooth_coext_enable(dev); - - ssb_bus_powerup(bus, !(sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)); - b43_upload_card_macaddress(dev); - b43_security_init(dev); - - ieee80211_wake_queues(dev->wl->hw); - - b43_set_status(dev, B43_STAT_INITIALIZED); - -out: - return err; - -err_chip_exit: - b43_chip_exit(dev); -err_busdown: - ssb_bus_may_powerdown(bus); - B43_WARN_ON(b43_status(dev) != B43_STAT_UNINIT); - return err; -} - -static int b43_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - int err = -EOPNOTSUPP; - - /* TODO: allow WDS/AP devices to coexist */ - - if (conf->type != NL80211_IFTYPE_AP && - conf->type != NL80211_IFTYPE_MESH_POINT && - conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_WDS && - conf->type != NL80211_IFTYPE_ADHOC) - return -EOPNOTSUPP; - - mutex_lock(&wl->mutex); - if (wl->operating) - goto out_mutex_unlock; - - b43dbg(wl, "Adding Interface type %d\n", conf->type); - - dev = wl->current_dev; - wl->operating = 1; - wl->vif = conf->vif; - wl->if_type = conf->type; - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); - - b43_adjust_opmode(dev); - b43_set_pretbtt(dev); - b43_set_synth_pu_delay(dev, 0); - b43_upload_card_macaddress(dev); - - err = 0; - out_mutex_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev = wl->current_dev; - - b43dbg(wl, "Removing Interface type %d\n", conf->type); - - mutex_lock(&wl->mutex); - - B43_WARN_ON(!wl->operating); - B43_WARN_ON(wl->vif != conf->vif); - wl->vif = NULL; - - wl->operating = 0; - - b43_adjust_opmode(dev); - memset(wl->mac_addr, 0, ETH_ALEN); - b43_upload_card_macaddress(dev); - - mutex_unlock(&wl->mutex); -} - -static int b43_op_start(struct ieee80211_hw *hw) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev = wl->current_dev; - int did_init = 0; - int err = 0; - - /* Kill all old instance specific information to make sure - * the card won't use it in the short timeframe between start - * and mac80211 reconfiguring it. */ - memset(wl->bssid, 0, ETH_ALEN); - memset(wl->mac_addr, 0, ETH_ALEN); - wl->filter_flags = 0; - wl->radiotap_enabled = 0; - b43_qos_clear(wl); - wl->beacon0_uploaded = 0; - wl->beacon1_uploaded = 0; - wl->beacon_templates_virgin = 1; - wl->radio_enabled = 1; - - mutex_lock(&wl->mutex); - - if (b43_status(dev) < B43_STAT_INITIALIZED) { - err = b43_wireless_core_init(dev); - if (err) - goto out_mutex_unlock; - did_init = 1; - } - - if (b43_status(dev) < B43_STAT_STARTED) { - err = b43_wireless_core_start(dev); - if (err) { - if (did_init) - b43_wireless_core_exit(dev); - goto out_mutex_unlock; - } - } - - /* XXX: only do if device doesn't support rfkill irq */ - wiphy_rfkill_start_polling(hw->wiphy); - - out_mutex_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43_op_stop(struct ieee80211_hw *hw) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev = wl->current_dev; - - cancel_work_sync(&(wl->beacon_update_trigger)); - - mutex_lock(&wl->mutex); - if (b43_status(dev) >= B43_STAT_STARTED) { - dev = b43_wireless_core_stop(dev); - if (!dev) - goto out_unlock; - } - b43_wireless_core_exit(dev); - wl->radio_enabled = 0; - -out_unlock: - mutex_unlock(&wl->mutex); - - cancel_work_sync(&(wl->txpower_adjust_work)); -} - -static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, bool set) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - - /* FIXME: add locking */ - b43_update_templates(wl); - - return 0; -} - -static void b43_op_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd notify_cmd, - struct ieee80211_sta *sta) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - - B43_WARN_ON(!vif || wl->vif != vif); -} - -static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) { - /* Disable CFP update during scan on other channels. */ - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_SKCFPUP); - } - mutex_unlock(&wl->mutex); -} - -static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (dev && (b43_status(dev) >= B43_STAT_INITIALIZED)) { - /* Re-enable CFP update. */ - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_SKCFPUP); - } - mutex_unlock(&wl->mutex); -} - -static const struct ieee80211_ops b43_hw_ops = { - .tx = b43_op_tx, - .conf_tx = b43_op_conf_tx, - .add_interface = b43_op_add_interface, - .remove_interface = b43_op_remove_interface, - .config = b43_op_config, - .bss_info_changed = b43_op_bss_info_changed, - .configure_filter = b43_op_configure_filter, - .set_key = b43_op_set_key, - .update_tkip_key = b43_op_update_tkip_key, - .get_stats = b43_op_get_stats, - .get_tx_stats = b43_op_get_tx_stats, - .get_tsf = b43_op_get_tsf, - .set_tsf = b43_op_set_tsf, - .start = b43_op_start, - .stop = b43_op_stop, - .set_tim = b43_op_beacon_set_tim, - .sta_notify = b43_op_sta_notify, - .sw_scan_start = b43_op_sw_scan_start_notifier, - .sw_scan_complete = b43_op_sw_scan_complete_notifier, - .rfkill_poll = b43_rfkill_poll, -}; - -/* Hard-reset the chip. Do not call this directly. - * Use b43_controller_restart() - */ -static void b43_chip_reset(struct work_struct *work) -{ - struct b43_wldev *dev = - container_of(work, struct b43_wldev, restart_work); - struct b43_wl *wl = dev->wl; - int err = 0; - int prev_status; - - mutex_lock(&wl->mutex); - - prev_status = b43_status(dev); - /* Bring the device down... */ - if (prev_status >= B43_STAT_STARTED) { - dev = b43_wireless_core_stop(dev); - if (!dev) { - err = -ENODEV; - goto out; - } - } - if (prev_status >= B43_STAT_INITIALIZED) - b43_wireless_core_exit(dev); - - /* ...and up again. */ - if (prev_status >= B43_STAT_INITIALIZED) { - err = b43_wireless_core_init(dev); - if (err) - goto out; - } - if (prev_status >= B43_STAT_STARTED) { - err = b43_wireless_core_start(dev); - if (err) { - b43_wireless_core_exit(dev); - goto out; - } - } -out: - if (err) - wl->current_dev = NULL; /* Failed to init the dev. */ - mutex_unlock(&wl->mutex); - if (err) - b43err(wl, "Controller restart FAILED\n"); - else - b43info(wl, "Controller restarted\n"); -} - -static int b43_setup_bands(struct b43_wldev *dev, - bool have_2ghz_phy, bool have_5ghz_phy) -{ - struct ieee80211_hw *hw = dev->wl->hw; - - if (have_2ghz_phy) - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &b43_band_2GHz; - if (dev->phy.type == B43_PHYTYPE_N) { - if (have_5ghz_phy) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_nphy; - } else { - if (have_5ghz_phy) - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &b43_band_5GHz_aphy; - } - - dev->phy.supports_2ghz = have_2ghz_phy; - dev->phy.supports_5ghz = have_5ghz_phy; - - return 0; -} - -static void b43_wireless_core_detach(struct b43_wldev *dev) -{ - /* We release firmware that late to not be required to re-request - * is all the time when we reinit the core. */ - b43_release_firmware(dev); - b43_phy_free(dev); -} - -static int b43_wireless_core_attach(struct b43_wldev *dev) -{ - struct b43_wl *wl = dev->wl; - struct ssb_bus *bus = dev->dev->bus; - struct pci_dev *pdev = bus->host_pci; - int err; - bool have_2ghz_phy = 0, have_5ghz_phy = 0; - u32 tmp; - - /* Do NOT do any device initialization here. - * Do it in wireless_core_init() instead. - * This function is for gathering basic information about the HW, only. - * Also some structs may be set up here. But most likely you want to have - * that in core_init(), too. - */ - - err = ssb_bus_powerup(bus, 0); - if (err) { - b43err(wl, "Bus powerup failed\n"); - goto out; - } - /* Get the PHY type. */ - if (dev->dev->id.revision >= 5) { - u32 tmshigh; - - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); - have_2ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_2GHZ_PHY); - have_5ghz_phy = !!(tmshigh & B43_TMSHIGH_HAVE_5GHZ_PHY); - } else - B43_WARN_ON(1); - - dev->phy.gmode = have_2ghz_phy; - dev->phy.radio_on = 1; - tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; - b43_wireless_core_reset(dev, tmp); - - err = b43_phy_versioning(dev); - if (err) - goto err_powerdown; - /* Check if this device supports multiband. */ - if (!pdev || - (pdev->device != 0x4312 && - pdev->device != 0x4319 && pdev->device != 0x4324)) { - /* No multiband support. */ - have_2ghz_phy = 0; - have_5ghz_phy = 0; - switch (dev->phy.type) { - case B43_PHYTYPE_A: - have_5ghz_phy = 1; - break; - case B43_PHYTYPE_LP: //FIXME not always! -#if 0 //FIXME enabling 5GHz causes a NULL pointer dereference - have_5ghz_phy = 1; -#endif - case B43_PHYTYPE_G: - case B43_PHYTYPE_N: - have_2ghz_phy = 1; - break; - default: - B43_WARN_ON(1); - } - } - if (dev->phy.type == B43_PHYTYPE_A) { - /* FIXME */ - b43err(wl, "IEEE 802.11a devices are unsupported\n"); - err = -EOPNOTSUPP; - goto err_powerdown; - } - if (1 /* disable A-PHY */) { - /* FIXME: For now we disable the A-PHY on multi-PHY devices. */ - if (dev->phy.type != B43_PHYTYPE_N && - dev->phy.type != B43_PHYTYPE_LP) { - have_2ghz_phy = 1; - have_5ghz_phy = 0; - } - } - - err = b43_phy_allocate(dev); - if (err) - goto err_powerdown; - - dev->phy.gmode = have_2ghz_phy; - tmp = dev->phy.gmode ? B43_TMSLOW_GMODE : 0; - b43_wireless_core_reset(dev, tmp); - - err = b43_validate_chipaccess(dev); - if (err) - goto err_phy_free; - err = b43_setup_bands(dev, have_2ghz_phy, have_5ghz_phy); - if (err) - goto err_phy_free; - - /* Now set some default "current_dev" */ - if (!wl->current_dev) - wl->current_dev = dev; - INIT_WORK(&dev->restart_work, b43_chip_reset); - - dev->phy.ops->switch_analog(dev, 0); - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(bus); - -out: - return err; - -err_phy_free: - b43_phy_free(dev); -err_powerdown: - ssb_bus_may_powerdown(bus); - return err; -} - -static void b43_one_core_detach(struct ssb_device *dev) -{ - struct b43_wldev *wldev; - struct b43_wl *wl; - - /* Do not cancel ieee80211-workqueue based work here. - * See comment in b43_remove(). */ - - wldev = ssb_get_drvdata(dev); - wl = wldev->wl; - b43_debugfs_remove_device(wldev); - b43_wireless_core_detach(wldev); - list_del(&wldev->list); - wl->nr_devs--; - ssb_set_drvdata(dev, NULL); - kfree(wldev); -} - -static int b43_one_core_attach(struct ssb_device *dev, struct b43_wl *wl) -{ - struct b43_wldev *wldev; - struct pci_dev *pdev; - int err = -ENOMEM; - - if (!list_empty(&wl->devlist)) { - /* We are not the first core on this chip. */ - pdev = dev->bus->host_pci; - /* Only special chips support more than one wireless - * core, although some of the other chips have more than - * one wireless core as well. Check for this and - * bail out early. - */ - if (!pdev || - ((pdev->device != 0x4321) && - (pdev->device != 0x4313) && (pdev->device != 0x431A))) { - b43dbg(wl, "Ignoring unconnected 802.11 core\n"); - return -ENODEV; - } - } - - wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); - if (!wldev) - goto out; - - wldev->use_pio = b43_modparam_pio; - wldev->dev = dev; - wldev->wl = wl; - b43_set_status(wldev, B43_STAT_UNINIT); - wldev->bad_frames_preempt = modparam_bad_frames_preempt; - INIT_LIST_HEAD(&wldev->list); - - err = b43_wireless_core_attach(wldev); - if (err) - goto err_kfree_wldev; - - list_add(&wldev->list, &wl->devlist); - wl->nr_devs++; - ssb_set_drvdata(dev, wldev); - b43_debugfs_add_device(wldev); - - out: - return err; - - err_kfree_wldev: - kfree(wldev); - return err; -} - -#define IS_PDEV(pdev, _vendor, _device, _subvendor, _subdevice) ( \ - (pdev->vendor == PCI_VENDOR_ID_##_vendor) && \ - (pdev->device == _device) && \ - (pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \ - (pdev->subsystem_device == _subdevice) ) - -static void b43_sprom_fixup(struct ssb_bus *bus) -{ - struct pci_dev *pdev; - - /* boardflags workarounds */ - if (bus->boardinfo.vendor == SSB_BOARDVENDOR_DELL && - bus->chip_id == 0x4301 && bus->boardinfo.rev == 0x74) - bus->sprom.boardflags_lo |= B43_BFL_BTCOEXIST; - if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && - bus->boardinfo.type == 0x4E && bus->boardinfo.rev > 0x40) - bus->sprom.boardflags_lo |= B43_BFL_PACTRL; - if (bus->bustype == SSB_BUSTYPE_PCI) { - pdev = bus->host_pci; - if (IS_PDEV(pdev, BROADCOM, 0x4318, ASUSTEK, 0x100F) || - IS_PDEV(pdev, BROADCOM, 0x4320, DELL, 0x0003) || - IS_PDEV(pdev, BROADCOM, 0x4320, HP, 0x12f8) || - IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0015) || - IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0014) || - IS_PDEV(pdev, BROADCOM, 0x4320, LINKSYS, 0x0013) || - IS_PDEV(pdev, BROADCOM, 0x4320, MOTOROLA, 0x7010)) - bus->sprom.boardflags_lo &= ~B43_BFL_BTCOEXIST; - } -} - -static void b43_wireless_exit(struct ssb_device *dev, struct b43_wl *wl) -{ - struct ieee80211_hw *hw = wl->hw; - - ssb_set_devtypedata(dev, NULL); - ieee80211_free_hw(hw); -} - -static int b43_wireless_init(struct ssb_device *dev) -{ - struct ssb_sprom *sprom = &dev->bus->sprom; - struct ieee80211_hw *hw; - struct b43_wl *wl; - int err = -ENOMEM; - - b43_sprom_fixup(dev->bus); - - hw = ieee80211_alloc_hw(sizeof(*wl), &b43_hw_ops); - if (!hw) { - b43err(NULL, "Could not allocate ieee80211 device\n"); - goto out; - } - wl = hw_to_b43_wl(hw); - - /* fill hw info */ - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_WDS) | - BIT(NL80211_IFTYPE_ADHOC); - - hw->queues = modparam_qos ? 4 : 1; - wl->mac80211_initially_registered_queues = hw->queues; - hw->max_rates = 2; - SET_IEEE80211_DEV(hw, dev->dev); - if (is_valid_ether_addr(sprom->et1mac)) - SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); - else - SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac); - - /* Initialize struct b43_wl */ - wl->hw = hw; - mutex_init(&wl->mutex); - spin_lock_init(&wl->hardirq_lock); - INIT_LIST_HEAD(&wl->devlist); - INIT_WORK(&wl->beacon_update_trigger, b43_beacon_update_trigger_work); - INIT_WORK(&wl->txpower_adjust_work, b43_phy_txpower_adjust_work); - INIT_WORK(&wl->tx_work, b43_tx_work); - skb_queue_head_init(&wl->tx_queue); - - ssb_set_devtypedata(dev, wl); - b43info(wl, "Broadcom %04X WLAN found (core revision %u)\n", - dev->bus->chip_id, dev->id.revision); - err = 0; -out: - return err; -} - -static int b43_probe(struct ssb_device *dev, const struct ssb_device_id *id) -{ - struct b43_wl *wl; - int err; - int first = 0; - - wl = ssb_get_devtypedata(dev); - if (!wl) { - /* Probing the first core. Must setup common struct b43_wl */ - first = 1; - err = b43_wireless_init(dev); - if (err) - goto out; - wl = ssb_get_devtypedata(dev); - B43_WARN_ON(!wl); - } - err = b43_one_core_attach(dev, wl); - if (err) - goto err_wireless_exit; - - if (first) { - err = ieee80211_register_hw(wl->hw); - if (err) - goto err_one_core_detach; - b43_leds_register(wl->current_dev); - b43_rng_init(wl); - } - - out: - return err; - - err_one_core_detach: - b43_one_core_detach(dev); - err_wireless_exit: - if (first) - b43_wireless_exit(dev, wl); - return err; -} - -static void b43_remove(struct ssb_device *dev) -{ - struct b43_wl *wl = ssb_get_devtypedata(dev); - struct b43_wldev *wldev = ssb_get_drvdata(dev); - - /* We must cancel any work here before unregistering from ieee80211, - * as the ieee80211 unreg will destroy the workqueue. */ - cancel_work_sync(&wldev->restart_work); - - B43_WARN_ON(!wl); - if (wl->current_dev == wldev) { - /* Restore the queues count before unregistering, because firmware detect - * might have modified it. Restoring is important, so the networking - * stack can properly free resources. */ - wl->hw->queues = wl->mac80211_initially_registered_queues; - b43_leds_stop(wldev); - ieee80211_unregister_hw(wl->hw); - } - - b43_one_core_detach(dev); - - if (list_empty(&wl->devlist)) { - b43_rng_exit(wl); - b43_leds_unregister(wl); - /* Last core on the chip unregistered. - * We can destroy common struct b43_wl. - */ - b43_wireless_exit(dev, wl); - } -} - -/* Perform a hardware reset. This can be called from any context. */ -void b43_controller_restart(struct b43_wldev *dev, const char *reason) -{ - /* Must avoid requeueing, if we are in shutdown. */ - if (b43_status(dev) < B43_STAT_INITIALIZED) - return; - b43info(dev->wl, "Controller RESET (%s) ...\n", reason); - ieee80211_queue_work(dev->wl->hw, &dev->restart_work); -} - -static struct ssb_driver b43_ssb_driver = { - .name = KBUILD_MODNAME, - .id_table = b43_ssb_tbl, - .probe = b43_probe, - .remove = b43_remove, -}; - -static void b43_print_driverinfo(void) -{ - const char *feat_pci = "", *feat_pcmcia = "", *feat_nphy = "", - *feat_leds = "", *feat_sdio = ""; - -#ifdef CONFIG_B43_PCI_AUTOSELECT - feat_pci = "P"; -#endif -#ifdef CONFIG_B43_PCMCIA - feat_pcmcia = "M"; -#endif -#ifdef CONFIG_B43_NPHY - feat_nphy = "N"; -#endif -#ifdef CONFIG_B43_LEDS - feat_leds = "L"; -#endif -#ifdef CONFIG_B43_SDIO - feat_sdio = "S"; -#endif - printk(KERN_INFO "Broadcom 43xx driver loaded " - "[ Features: %s%s%s%s%s, Firmware-ID: " - B43_SUPPORTED_FIRMWARE_ID " ]\n", - feat_pci, feat_pcmcia, feat_nphy, - feat_leds, feat_sdio); -} - -static int __init b43_init(void) -{ - int err; - - b43_debugfs_init(); - err = b43_pcmcia_init(); - if (err) - goto err_dfs_exit; - err = b43_sdio_init(); - if (err) - goto err_pcmcia_exit; - err = ssb_driver_register(&b43_ssb_driver); - if (err) - goto err_sdio_exit; - b43_print_driverinfo(); - - return err; - -err_sdio_exit: - b43_sdio_exit(); -err_pcmcia_exit: - b43_pcmcia_exit(); -err_dfs_exit: - b43_debugfs_exit(); - return err; -} - -static void __exit b43_exit(void) -{ - ssb_driver_unregister(&b43_ssb_driver); - b43_sdio_exit(); - b43_pcmcia_exit(); - b43_debugfs_exit(); -} - -module_init(b43_init) -module_exit(b43_exit) diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h deleted file mode 100644 index 40db03678d9f..000000000000 --- a/drivers/net/wireless/b43/main.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef B43_MAIN_H_ -#define B43_MAIN_H_ - -#include "b43.h" - -#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] -#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) -/* Magic helper macro to pad structures. Ignore those above. It's magic. */ -#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) - - -extern int b43_modparam_verbose; - -/* Logmessage verbosity levels. Update the b43_modparam_verbose helptext, if - * you add or remove levels. */ -enum b43_verbosity { - B43_VERBOSITY_ERROR, - B43_VERBOSITY_WARN, - B43_VERBOSITY_INFO, - B43_VERBOSITY_DEBUG, - __B43_VERBOSITY_AFTERLAST, /* keep last */ - - B43_VERBOSITY_MAX = __B43_VERBOSITY_AFTERLAST - 1, -#if B43_DEBUG - B43_VERBOSITY_DEFAULT = B43_VERBOSITY_DEBUG, -#else - B43_VERBOSITY_DEFAULT = B43_VERBOSITY_INFO, -#endif -}; - - -/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ -static inline u8 b43_freq_to_channel_5ghz(int freq) -{ - return ((freq - 5000) / 5); -} -static inline u8 b43_freq_to_channel_2ghz(int freq) -{ - u8 channel; - - if (freq == 2484) - channel = 14; - else - channel = (freq - 2407) / 5; - - return channel; -} - -/* Lightweight function to convert a channel number to a frequency (in Mhz). */ -static inline int b43_channel_to_freq_5ghz(u8 channel) -{ - return (5000 + (5 * channel)); -} -static inline int b43_channel_to_freq_2ghz(u8 channel) -{ - int freq; - - if (channel == 14) - freq = 2484; - else - freq = 2407 + (5 * channel); - - return freq; -} - -static inline int b43_is_cck_rate(int rate) -{ - return (rate == B43_CCK_RATE_1MB || - rate == B43_CCK_RATE_2MB || - rate == B43_CCK_RATE_5MB || rate == B43_CCK_RATE_11MB); -} - -static inline int b43_is_ofdm_rate(int rate) -{ - return !b43_is_cck_rate(rate); -} - -u8 b43_ieee80211_antenna_sanitize(struct b43_wldev *dev, - u8 antenna_nr); - -void b43_tsf_read(struct b43_wldev *dev, u64 * tsf); -void b43_tsf_write(struct b43_wldev *dev, u64 tsf); - -u32 b43_shm_read32(struct b43_wldev *dev, u16 routing, u16 offset); -u16 b43_shm_read16(struct b43_wldev *dev, u16 routing, u16 offset); -void b43_shm_write32(struct b43_wldev *dev, u16 routing, u16 offset, u32 value); -void b43_shm_write16(struct b43_wldev *dev, u16 routing, u16 offset, u16 value); - -u64 b43_hf_read(struct b43_wldev *dev); -void b43_hf_write(struct b43_wldev *dev, u64 value); - -void b43_dummy_transmission(struct b43_wldev *dev, bool ofdm, bool pa_on); - -void b43_wireless_core_reset(struct b43_wldev *dev, u32 flags); - -void b43_controller_restart(struct b43_wldev *dev, const char *reason); - -#define B43_PS_ENABLED (1 << 0) /* Force enable hardware power saving */ -#define B43_PS_DISABLED (1 << 1) /* Force disable hardware power saving */ -#define B43_PS_AWAKE (1 << 2) /* Force device awake */ -#define B43_PS_ASLEEP (1 << 3) /* Force device asleep */ -void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags); - -void b43_mac_suspend(struct b43_wldev *dev); -void b43_mac_enable(struct b43_wldev *dev); - - -struct b43_request_fw_context; -int b43_do_request_fw(struct b43_request_fw_context *ctx, - const char *name, - struct b43_firmware_file *fw); -void b43_do_release_fw(struct b43_firmware_file *fw); - -#endif /* B43_MAIN_H_ */ diff --git a/drivers/net/wireless/b43/pcmcia.c b/drivers/net/wireless/b43/pcmcia.c deleted file mode 100644 index 6c3a74964ab8..000000000000 --- a/drivers/net/wireless/b43/pcmcia.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Copyright (c) 2007 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "pcmcia.h" - -#include - -#include -#include -#include -#include -#include -#include - - -static /*const */ struct pcmcia_device_id b43_pcmcia_tbl[] = { - PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x448), - PCMCIA_DEVICE_MANF_CARD(0x2D0, 0x476), - PCMCIA_DEVICE_NULL, -}; - -MODULE_DEVICE_TABLE(pcmcia, b43_pcmcia_tbl); - -#ifdef CONFIG_PM -static int b43_pcmcia_suspend(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - return ssb_bus_suspend(ssb); -} - -static int b43_pcmcia_resume(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - return ssb_bus_resume(ssb); -} -#else /* CONFIG_PM */ -# define b43_pcmcia_suspend NULL -# define b43_pcmcia_resume NULL -#endif /* CONFIG_PM */ - -static int __devinit b43_pcmcia_probe(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb; - win_req_t win; - memreq_t mem; - tuple_t tuple; - cisparse_t parse; - int err = -ENOMEM; - int res = 0; - unsigned char buf[64]; - - ssb = kzalloc(sizeof(*ssb), GFP_KERNEL); - if (!ssb) - goto out_error; - - err = -ENODEV; - tuple.DesiredTuple = CISTPL_CONFIG; - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - - res = pcmcia_get_first_tuple(dev, &tuple); - if (res != 0) - goto err_kfree_ssb; - res = pcmcia_get_tuple_data(dev, &tuple); - if (res != 0) - goto err_kfree_ssb; - res = pcmcia_parse_tuple(&tuple, &parse); - if (res != 0) - goto err_kfree_ssb; - - dev->conf.ConfigBase = parse.config.base; - dev->conf.Present = parse.config.rmask[0]; - dev->conf.Attributes = CONF_ENABLE_IRQ; - dev->conf.IntType = INT_MEMORY_AND_IO; - - dev->io.BasePort2 = 0; - dev->io.NumPorts2 = 0; - dev->io.Attributes2 = 0; - - win.Attributes = WIN_ADDR_SPACE_MEM | WIN_MEMORY_TYPE_CM | - WIN_ENABLE | WIN_DATA_WIDTH_16 | - WIN_USE_WAIT; - win.Base = 0; - win.Size = SSB_CORE_SIZE; - win.AccessSpeed = 250; - res = pcmcia_request_window(&dev, &win, &dev->win); - if (res != 0) - goto err_kfree_ssb; - - mem.CardOffset = 0; - mem.Page = 0; - res = pcmcia_map_mem_page(dev->win, &mem); - if (res != 0) - goto err_disable; - - dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - dev->irq.Handler = NULL; /* The handler is registered later. */ - dev->irq.Instance = NULL; - res = pcmcia_request_irq(dev, &dev->irq); - if (res != 0) - goto err_disable; - - res = pcmcia_request_configuration(dev, &dev->conf); - if (res != 0) - goto err_disable; - - err = ssb_bus_pcmciabus_register(ssb, dev, win.Base); - if (err) - goto err_disable; - dev->priv = ssb; - - return 0; - -err_disable: - pcmcia_disable_device(dev); -err_kfree_ssb: - kfree(ssb); -out_error: - printk(KERN_ERR "b43-pcmcia: Initialization failed (%d, %d)\n", - res, err); - return err; -} - -static void __devexit b43_pcmcia_remove(struct pcmcia_device *dev) -{ - struct ssb_bus *ssb = dev->priv; - - ssb_bus_unregister(ssb); - pcmcia_disable_device(dev); - kfree(ssb); - dev->priv = NULL; -} - -static struct pcmcia_driver b43_pcmcia_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "b43-pcmcia", - }, - .id_table = b43_pcmcia_tbl, - .probe = b43_pcmcia_probe, - .remove = __devexit_p(b43_pcmcia_remove), - .suspend = b43_pcmcia_suspend, - .resume = b43_pcmcia_resume, -}; - -int b43_pcmcia_init(void) -{ - return pcmcia_register_driver(&b43_pcmcia_driver); -} - -void b43_pcmcia_exit(void) -{ - pcmcia_unregister_driver(&b43_pcmcia_driver); -} diff --git a/drivers/net/wireless/b43/pcmcia.h b/drivers/net/wireless/b43/pcmcia.h deleted file mode 100644 index 85f120a67cbe..000000000000 --- a/drivers/net/wireless/b43/pcmcia.h +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef B43_PCMCIA_H_ -#define B43_PCMCIA_H_ - -#ifdef CONFIG_B43_PCMCIA - -int b43_pcmcia_init(void); -void b43_pcmcia_exit(void); - -#else /* CONFIG_B43_PCMCIA */ - -static inline int b43_pcmcia_init(void) -{ - return 0; -} -static inline void b43_pcmcia_exit(void) -{ -} - -#endif /* CONFIG_B43_PCMCIA */ -#endif /* B43_PCMCIA_H_ */ diff --git a/drivers/net/wireless/b43/phy_a.c b/drivers/net/wireless/b43/phy_a.c deleted file mode 100644 index d90217c3a706..000000000000 --- a/drivers/net/wireless/b43/phy_a.c +++ /dev/null @@ -1,594 +0,0 @@ -/* - - Broadcom B43 wireless driver - IEEE 802.11a PHY driver - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005-2007 Stefano Brivio - Copyright (c) 2005-2008 Michael Buesch - Copyright (c) 2005, 2006 Danny van Dyk - Copyright (c) 2005, 2006 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "phy_a.h" -#include "phy_common.h" -#include "wa.h" -#include "tables.h" -#include "main.h" - - -/* Get the freq, as it has to be written to the device. */ -static inline u16 channel2freq_a(u8 channel) -{ - B43_WARN_ON(channel > 200); - - return (5000 + 5 * channel); -} - -static inline u16 freq_r3A_value(u16 frequency) -{ - u16 value; - - if (frequency < 5091) - value = 0x0040; - else if (frequency < 5321) - value = 0x0000; - else if (frequency < 5806) - value = 0x0080; - else - value = 0x0040; - - return value; -} - -#if 0 -/* This function converts a TSSI value to dBm in Q5.2 */ -static s8 b43_aphy_estimate_power_out(struct b43_wldev *dev, s8 tssi) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_a *aphy = phy->a; - s8 dbm = 0; - s32 tmp; - - tmp = (aphy->tgt_idle_tssi - aphy->cur_idle_tssi + tssi); - tmp += 0x80; - tmp = clamp_val(tmp, 0x00, 0xFF); - dbm = aphy->tssi2dbm[tmp]; - //TODO: There's a FIXME on the specs - - return dbm; -} -#endif - -static void b43_radio_set_tx_iq(struct b43_wldev *dev) -{ - static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; - static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; - u16 tmp = b43_radio_read16(dev, 0x001E); - int i, j; - - for (i = 0; i < 5; i++) { - for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] << 4 | data_low[j])) { - b43_phy_write(dev, 0x0069, - (i - j) << 8 | 0x00C0); - return; - } - } - } -} - -static void aphy_channel_switch(struct b43_wldev *dev, unsigned int channel) -{ - u16 freq, r8, tmp; - - freq = channel2freq_a(channel); - - r8 = b43_radio_read16(dev, 0x0008); - b43_write16(dev, 0x03F0, freq); - b43_radio_write16(dev, 0x0008, r8); - - //TODO: write max channel TX power? to Radio 0x2D - tmp = b43_radio_read16(dev, 0x002E); - tmp &= 0x0080; - //TODO: OR tmp with the Power out estimation for this channel? - b43_radio_write16(dev, 0x002E, tmp); - - if (freq >= 4920 && freq <= 5500) { - /* - * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; - * = (freq * 0.025862069 - */ - r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ - } - b43_radio_write16(dev, 0x0007, (r8 << 4) | r8); - b43_radio_write16(dev, 0x0020, (r8 << 4) | r8); - b43_radio_write16(dev, 0x0021, (r8 << 4) | r8); - b43_radio_maskset(dev, 0x0022, 0x000F, (r8 << 4)); - b43_radio_write16(dev, 0x002A, (r8 << 4)); - b43_radio_write16(dev, 0x002B, (r8 << 4)); - b43_radio_maskset(dev, 0x0008, 0x00F0, (r8 << 4)); - b43_radio_maskset(dev, 0x0029, 0xFF0F, 0x00B0); - b43_radio_write16(dev, 0x0035, 0x00AA); - b43_radio_write16(dev, 0x0036, 0x0085); - b43_radio_maskset(dev, 0x003A, 0xFF20, freq_r3A_value(freq)); - b43_radio_mask(dev, 0x003D, 0x00FF); - b43_radio_maskset(dev, 0x0081, 0xFF7F, 0x0080); - b43_radio_mask(dev, 0x0035, 0xFFEF); - b43_radio_maskset(dev, 0x0035, 0xFFEF, 0x0010); - b43_radio_set_tx_iq(dev); - //TODO: TSSI2dbm workaround -//FIXME b43_phy_xmitpower(dev); -} - -static void b43_radio_init2060(struct b43_wldev *dev) -{ - b43_radio_write16(dev, 0x0004, 0x00C0); - b43_radio_write16(dev, 0x0005, 0x0008); - b43_radio_write16(dev, 0x0009, 0x0040); - b43_radio_write16(dev, 0x0005, 0x00AA); - b43_radio_write16(dev, 0x0032, 0x008F); - b43_radio_write16(dev, 0x0006, 0x008F); - b43_radio_write16(dev, 0x0034, 0x008F); - b43_radio_write16(dev, 0x002C, 0x0007); - b43_radio_write16(dev, 0x0082, 0x0080); - b43_radio_write16(dev, 0x0080, 0x0000); - b43_radio_write16(dev, 0x003F, 0x00DA); - b43_radio_mask(dev, 0x0005, ~0x0008); - b43_radio_mask(dev, 0x0081, ~0x0010); - b43_radio_mask(dev, 0x0081, ~0x0020); - b43_radio_mask(dev, 0x0081, ~0x0020); - msleep(1); /* delay 400usec */ - - b43_radio_maskset(dev, 0x0081, ~0x0020, 0x0010); - msleep(1); /* delay 400usec */ - - b43_radio_maskset(dev, 0x0005, ~0x0008, 0x0008); - b43_radio_mask(dev, 0x0085, ~0x0010); - b43_radio_mask(dev, 0x0005, ~0x0008); - b43_radio_mask(dev, 0x0081, ~0x0040); - b43_radio_maskset(dev, 0x0081, ~0x0040, 0x0040); - b43_radio_write16(dev, 0x0005, - (b43_radio_read16(dev, 0x0081) & ~0x0008) | 0x0008); - b43_phy_write(dev, 0x0063, 0xDDC6); - b43_phy_write(dev, 0x0069, 0x07BE); - b43_phy_write(dev, 0x006A, 0x0000); - - aphy_channel_switch(dev, dev->phy.ops->get_default_chan(dev)); - - msleep(1); -} - -static void b43_phy_rssiagc(struct b43_wldev *dev, u8 enable) -{ - int i; - - if (dev->phy.rev < 3) { - if (enable) - for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { - b43_ofdmtab_write16(dev, - B43_OFDMTAB_LNAHPFGAIN1, i, 0xFFF8); - b43_ofdmtab_write16(dev, - B43_OFDMTAB_WRSSI, i, 0xFFF8); - } - else - for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) { - b43_ofdmtab_write16(dev, - B43_OFDMTAB_LNAHPFGAIN1, i, b43_tab_rssiagc1[i]); - b43_ofdmtab_write16(dev, - B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc1[i]); - } - } else { - if (enable) - for (i = 0; i < B43_TAB_RSSIAGC1_SIZE; i++) - b43_ofdmtab_write16(dev, - B43_OFDMTAB_WRSSI, i, 0x0820); - else - for (i = 0; i < B43_TAB_RSSIAGC2_SIZE; i++) - b43_ofdmtab_write16(dev, - B43_OFDMTAB_WRSSI, i, b43_tab_rssiagc2[i]); - } -} - -static void b43_phy_ww(struct b43_wldev *dev) -{ - u16 b, curr_s, best_s = 0xFFFF; - int i; - - b43_phy_mask(dev, B43_PHY_CRS0, ~B43_PHY_CRS0_EN); - b43_phy_set(dev, B43_PHY_OFDM(0x1B), 0x1000); - b43_phy_maskset(dev, B43_PHY_OFDM(0x82), 0xF0FF, 0x0300); - b43_radio_set(dev, 0x0009, 0x0080); - b43_radio_maskset(dev, 0x0012, 0xFFFC, 0x0002); - b43_wa_initgains(dev); - b43_phy_write(dev, B43_PHY_OFDM(0xBA), 0x3ED5); - b = b43_phy_read(dev, B43_PHY_PWRDOWN); - b43_phy_write(dev, B43_PHY_PWRDOWN, (b & 0xFFF8) | 0x0005); - b43_radio_set(dev, 0x0004, 0x0004); - for (i = 0x10; i <= 0x20; i++) { - b43_radio_write16(dev, 0x0013, i); - curr_s = b43_phy_read(dev, B43_PHY_OTABLEQ) & 0x00FF; - if (!curr_s) { - best_s = 0x0000; - break; - } else if (curr_s >= 0x0080) - curr_s = 0x0100 - curr_s; - if (curr_s < best_s) - best_s = curr_s; - } - b43_phy_write(dev, B43_PHY_PWRDOWN, b); - b43_radio_mask(dev, 0x0004, 0xFFFB); - b43_radio_write16(dev, 0x0013, best_s); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 0xFFEC); - b43_phy_write(dev, B43_PHY_OFDM(0xB7), 0x1E80); - b43_phy_write(dev, B43_PHY_OFDM(0xB6), 0x1C00); - b43_phy_write(dev, B43_PHY_OFDM(0xB5), 0x0EC0); - b43_phy_write(dev, B43_PHY_OFDM(0xB2), 0x00C0); - b43_phy_write(dev, B43_PHY_OFDM(0xB9), 0x1FFF); - b43_phy_maskset(dev, B43_PHY_OFDM(0xBB), 0xF000, 0x0053); - b43_phy_maskset(dev, B43_PHY_OFDM61, 0xFE1F, 0x0120); - b43_phy_maskset(dev, B43_PHY_OFDM(0x13), 0x0FFF, 0x3000); - b43_phy_maskset(dev, B43_PHY_OFDM(0x14), 0x0FFF, 0x3000); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 6, 0x0017); - for (i = 0; i < 6; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, i, 0x000F); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0D, 0x000E); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0E, 0x0011); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0x0F, 0x0013); - b43_phy_write(dev, B43_PHY_OFDM(0x33), 0x5030); - b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN); -} - -static void hardware_pctl_init_aphy(struct b43_wldev *dev) -{ - //TODO -} - -void b43_phy_inita(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy *phy = &dev->phy; - - /* This lowlevel A-PHY init is also called from G-PHY init. - * So we must not access phy->a, if called from G-PHY code. - */ - B43_WARN_ON((phy->type != B43_PHYTYPE_A) && - (phy->type != B43_PHYTYPE_G)); - - might_sleep(); - - if (phy->rev >= 6) { - if (phy->type == B43_PHYTYPE_A) - b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x1000); - if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN) - b43_phy_set(dev, B43_PHY_ENCORE, 0x0010); - else - b43_phy_mask(dev, B43_PHY_ENCORE, ~0x1010); - } - - b43_wa_all(dev); - - if (phy->type == B43_PHYTYPE_A) { - if (phy->gmode && (phy->rev < 3)) - b43_phy_set(dev, 0x0034, 0x0001); - b43_phy_rssiagc(dev, 0); - - b43_phy_set(dev, B43_PHY_CRS0, B43_PHY_CRS0_EN); - - b43_radio_init2060(dev); - - if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && - ((bus->boardinfo.type == SSB_BOARD_BU4306) || - (bus->boardinfo.type == SSB_BOARD_BU4309))) { - ; //TODO: A PHY LO - } - - if (phy->rev >= 3) - b43_phy_ww(dev); - - hardware_pctl_init_aphy(dev); - - //TODO: radar detection - } - - if ((phy->type == B43_PHYTYPE_G) && - (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL)) { - b43_phy_maskset(dev, B43_PHY_OFDM(0x6E), 0xE000, 0x3CF); - } -} - -/* Initialise the TSSI->dBm lookup table */ -static int b43_aphy_init_tssi2dbm_table(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_a *aphy = phy->a; - s16 pab0, pab1, pab2; - - pab0 = (s16) (dev->dev->bus->sprom.pa1b0); - pab1 = (s16) (dev->dev->bus->sprom.pa1b1); - pab2 = (s16) (dev->dev->bus->sprom.pa1b2); - - if (pab0 != 0 && pab1 != 0 && pab2 != 0 && - pab0 != -1 && pab1 != -1 && pab2 != -1) { - /* The pabX values are set in SPROM. Use them. */ - if ((s8) dev->dev->bus->sprom.itssi_a != 0 && - (s8) dev->dev->bus->sprom.itssi_a != -1) - aphy->tgt_idle_tssi = - (s8) (dev->dev->bus->sprom.itssi_a); - else - aphy->tgt_idle_tssi = 62; - aphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, - pab1, pab2); - if (!aphy->tssi2dbm) - return -ENOMEM; - } else { - /* pabX values not set in SPROM, - * but APHY needs a generated table. */ - aphy->tssi2dbm = NULL; - b43err(dev->wl, "Could not generate tssi2dBm " - "table (wrong SPROM info)!\n"); - return -ENODEV; - } - - return 0; -} - -static int b43_aphy_op_allocate(struct b43_wldev *dev) -{ - struct b43_phy_a *aphy; - int err; - - aphy = kzalloc(sizeof(*aphy), GFP_KERNEL); - if (!aphy) - return -ENOMEM; - dev->phy.a = aphy; - - err = b43_aphy_init_tssi2dbm_table(dev); - if (err) - goto err_free_aphy; - - return 0; - -err_free_aphy: - kfree(aphy); - dev->phy.a = NULL; - - return err; -} - -static void b43_aphy_op_prepare_structs(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_a *aphy = phy->a; - const void *tssi2dbm; - int tgt_idle_tssi; - - /* tssi2dbm table is constant, so it is initialized at alloc time. - * Save a copy of the pointer. */ - tssi2dbm = aphy->tssi2dbm; - tgt_idle_tssi = aphy->tgt_idle_tssi; - - /* Zero out the whole PHY structure. */ - memset(aphy, 0, sizeof(*aphy)); - - aphy->tssi2dbm = tssi2dbm; - aphy->tgt_idle_tssi = tgt_idle_tssi; - - //TODO init struct b43_phy_a - -} - -static void b43_aphy_op_free(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_a *aphy = phy->a; - - kfree(aphy->tssi2dbm); - aphy->tssi2dbm = NULL; - - kfree(aphy); - dev->phy.a = NULL; -} - -static int b43_aphy_op_init(struct b43_wldev *dev) -{ - b43_phy_inita(dev); - - return 0; -} - -static inline u16 adjust_phyreg(struct b43_wldev *dev, u16 offset) -{ - /* OFDM registers are base-registers for the A-PHY. */ - if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { - offset &= ~B43_PHYROUTE; - offset |= B43_PHYROUTE_BASE; - } - -#if B43_DEBUG - if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { - /* Ext-G registers are only available on G-PHYs */ - b43err(dev->wl, "Invalid EXT-G PHY access at " - "0x%04X on A-PHY\n", offset); - dump_stack(); - } - if ((offset & B43_PHYROUTE) == B43_PHYROUTE_N_BMODE) { - /* N-BMODE registers are only available on N-PHYs */ - b43err(dev->wl, "Invalid N-BMODE PHY access at " - "0x%04X on A-PHY\n", offset); - dump_stack(); - } -#endif /* B43_DEBUG */ - - return offset; -} - -static u16 b43_aphy_op_read(struct b43_wldev *dev, u16 reg) -{ - reg = adjust_phyreg(dev, reg); - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - return b43_read16(dev, B43_MMIO_PHY_DATA); -} - -static void b43_aphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - reg = adjust_phyreg(dev, reg); - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, value); -} - -static u16 b43_aphy_op_radio_read(struct b43_wldev *dev, u16 reg) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - /* A-PHY needs 0x40 for read access */ - reg |= 0x40; - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); -} - -static void b43_aphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); -} - -static bool b43_aphy_op_supports_hwpctl(struct b43_wldev *dev) -{ - return (dev->phy.rev >= 5); -} - -static void b43_aphy_op_software_rfkill(struct b43_wldev *dev, - bool blocked) -{ - struct b43_phy *phy = &dev->phy; - - if (!blocked) { - if (phy->radio_on) - return; - b43_radio_write16(dev, 0x0004, 0x00C0); - b43_radio_write16(dev, 0x0005, 0x0008); - b43_phy_mask(dev, 0x0010, 0xFFF7); - b43_phy_mask(dev, 0x0011, 0xFFF7); - b43_radio_init2060(dev); - } else { - b43_radio_write16(dev, 0x0004, 0x00FF); - b43_radio_write16(dev, 0x0005, 0x00FB); - b43_phy_set(dev, 0x0010, 0x0008); - b43_phy_set(dev, 0x0011, 0x0008); - } -} - -static int b43_aphy_op_switch_channel(struct b43_wldev *dev, - unsigned int new_channel) -{ - if (new_channel > 200) - return -EINVAL; - aphy_channel_switch(dev, new_channel); - - return 0; -} - -static unsigned int b43_aphy_op_get_default_chan(struct b43_wldev *dev) -{ - return 36; /* Default to channel 36 */ -} - -static void b43_aphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) -{//TODO - struct b43_phy *phy = &dev->phy; - u16 tmp; - int autodiv = 0; - - if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1) - autodiv = 1; - - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP); - - b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT, - (autodiv ? B43_ANTENNA_AUTO1 : antenna) << - B43_PHY_BBANDCFG_RXANT_SHIFT); - - if (autodiv) { - tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); - if (antenna == B43_ANTENNA_AUTO1) - tmp &= ~B43_PHY_ANTDWELL_AUTODIV1; - else - tmp |= B43_PHY_ANTDWELL_AUTODIV1; - b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); - } - if (phy->rev < 3) - b43_phy_maskset(dev, B43_PHY_ANTDWELL, 0xFF00, 0x24); - else { - b43_phy_set(dev, B43_PHY_OFDM61, 0x10); - if (phy->rev == 3) { - b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x1D); - b43_phy_write(dev, B43_PHY_ADIVRELATED, 8); - } else { - b43_phy_write(dev, B43_PHY_CLIPPWRDOWNT, 0x3A); - b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8); - } - } - - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP); -} - -static void b43_aphy_op_adjust_txpower(struct b43_wldev *dev) -{//TODO -} - -static enum b43_txpwr_result b43_aphy_op_recalc_txpower(struct b43_wldev *dev, - bool ignore_tssi) -{//TODO - return B43_TXPWR_RES_DONE; -} - -static void b43_aphy_op_pwork_15sec(struct b43_wldev *dev) -{//TODO -} - -static void b43_aphy_op_pwork_60sec(struct b43_wldev *dev) -{//TODO -} - -const struct b43_phy_operations b43_phyops_a = { - .allocate = b43_aphy_op_allocate, - .free = b43_aphy_op_free, - .prepare_structs = b43_aphy_op_prepare_structs, - .init = b43_aphy_op_init, - .phy_read = b43_aphy_op_read, - .phy_write = b43_aphy_op_write, - .radio_read = b43_aphy_op_radio_read, - .radio_write = b43_aphy_op_radio_write, - .supports_hwpctl = b43_aphy_op_supports_hwpctl, - .software_rfkill = b43_aphy_op_software_rfkill, - .switch_analog = b43_phyop_switch_analog_generic, - .switch_channel = b43_aphy_op_switch_channel, - .get_default_chan = b43_aphy_op_get_default_chan, - .set_rx_antenna = b43_aphy_op_set_rx_antenna, - .recalc_txpower = b43_aphy_op_recalc_txpower, - .adjust_txpower = b43_aphy_op_adjust_txpower, - .pwork_15sec = b43_aphy_op_pwork_15sec, - .pwork_60sec = b43_aphy_op_pwork_60sec, -}; diff --git a/drivers/net/wireless/b43/phy_a.h b/drivers/net/wireless/b43/phy_a.h deleted file mode 100644 index 5cfaab7b16ee..000000000000 --- a/drivers/net/wireless/b43/phy_a.h +++ /dev/null @@ -1,130 +0,0 @@ -#ifndef LINUX_B43_PHY_A_H_ -#define LINUX_B43_PHY_A_H_ - -#include "phy_common.h" - - -/* OFDM (A) PHY Registers */ -#define B43_PHY_VERSION_OFDM B43_PHY_OFDM(0x00) /* Versioning register for A-PHY */ -#define B43_PHY_BBANDCFG B43_PHY_OFDM(0x01) /* Baseband config */ -#define B43_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */ -#define B43_PHY_BBANDCFG_RXANT_SHIFT 7 -#define B43_PHY_PWRDOWN B43_PHY_OFDM(0x03) /* Powerdown */ -#define B43_PHY_CRSTHRES1_R1 B43_PHY_OFDM(0x06) /* CRS Threshold 1 (phy.rev 1 only) */ -#define B43_PHY_LNAHPFCTL B43_PHY_OFDM(0x1C) /* LNA/HPF control */ -#define B43_PHY_LPFGAINCTL B43_PHY_OFDM(0x20) /* LPF Gain control */ -#define B43_PHY_ADIVRELATED B43_PHY_OFDM(0x27) /* FIXME rename */ -#define B43_PHY_CRS0 B43_PHY_OFDM(0x29) -#define B43_PHY_CRS0_EN 0x4000 -#define B43_PHY_PEAK_COUNT B43_PHY_OFDM(0x30) -#define B43_PHY_ANTDWELL B43_PHY_OFDM(0x2B) /* Antenna dwell */ -#define B43_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */ -#define B43_PHY_ENCORE B43_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */ -#define B43_PHY_ENCORE_EN 0x0200 /* Encore enable */ -#define B43_PHY_LMS B43_PHY_OFDM(0x55) -#define B43_PHY_OFDM61 B43_PHY_OFDM(0x61) /* FIXME rename */ -#define B43_PHY_OFDM61_10 0x0010 /* FIXME rename */ -#define B43_PHY_IQBAL B43_PHY_OFDM(0x69) /* I/Q balance */ -#define B43_PHY_BBTXDC_BIAS B43_PHY_OFDM(0x6B) /* Baseband TX DC bias */ -#define B43_PHY_OTABLECTL B43_PHY_OFDM(0x72) /* OFDM table control (see below) */ -#define B43_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */ -#define B43_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */ -#define B43_PHY_OTABLENR_SHIFT 10 -#define B43_PHY_OTABLEI B43_PHY_OFDM(0x73) /* OFDM table data I */ -#define B43_PHY_OTABLEQ B43_PHY_OFDM(0x74) /* OFDM table data Q */ -#define B43_PHY_HPWR_TSSICTL B43_PHY_OFDM(0x78) /* Hardware power TSSI control */ -#define B43_PHY_ADCCTL B43_PHY_OFDM(0x7A) /* ADC control */ -#define B43_PHY_IDLE_TSSI B43_PHY_OFDM(0x7B) -#define B43_PHY_A_TEMP_SENSE B43_PHY_OFDM(0x7C) /* A PHY temperature sense */ -#define B43_PHY_NRSSITHRES B43_PHY_OFDM(0x8A) /* NRSSI threshold */ -#define B43_PHY_ANTWRSETT B43_PHY_OFDM(0x8C) /* Antenna WR settle */ -#define B43_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */ -#define B43_PHY_CLIPPWRDOWNT B43_PHY_OFDM(0x93) /* Clip powerdown threshold */ -#define B43_PHY_OFDM9B B43_PHY_OFDM(0x9B) /* FIXME rename */ -#define B43_PHY_N1P1GAIN B43_PHY_OFDM(0xA0) -#define B43_PHY_P1P2GAIN B43_PHY_OFDM(0xA1) -#define B43_PHY_N1N2GAIN B43_PHY_OFDM(0xA2) -#define B43_PHY_CLIPTHRES B43_PHY_OFDM(0xA3) -#define B43_PHY_CLIPN1P2THRES B43_PHY_OFDM(0xA4) -#define B43_PHY_CCKSHIFTBITS_WA B43_PHY_OFDM(0xA5) /* CCK shiftbits workaround, FIXME rename */ -#define B43_PHY_CCKSHIFTBITS B43_PHY_OFDM(0xA7) /* FIXME rename */ -#define B43_PHY_DIVSRCHIDX B43_PHY_OFDM(0xA8) /* Divider search gain/index */ -#define B43_PHY_CLIPP2THRES B43_PHY_OFDM(0xA9) -#define B43_PHY_CLIPP3THRES B43_PHY_OFDM(0xAA) -#define B43_PHY_DIVP1P2GAIN B43_PHY_OFDM(0xAB) -#define B43_PHY_DIVSRCHGAINBACK B43_PHY_OFDM(0xAD) /* Divider search gain back */ -#define B43_PHY_DIVSRCHGAINCHNG B43_PHY_OFDM(0xAE) /* Divider search gain change */ -#define B43_PHY_CRSTHRES1 B43_PHY_OFDM(0xC0) /* CRS Threshold 1 (phy.rev >= 2 only) */ -#define B43_PHY_CRSTHRES2 B43_PHY_OFDM(0xC1) /* CRS Threshold 2 (phy.rev >= 2 only) */ -#define B43_PHY_TSSIP_LTBASE B43_PHY_OFDM(0x380) /* TSSI power lookup table base */ -#define B43_PHY_DC_LTBASE B43_PHY_OFDM(0x3A0) /* DC lookup table base */ -#define B43_PHY_GAIN_LTBASE B43_PHY_OFDM(0x3C0) /* Gain lookup table base */ - -/*** OFDM table numbers ***/ -#define B43_OFDMTAB(number, offset) (((number) << B43_PHY_OTABLENR_SHIFT) | (offset)) -#define B43_OFDMTAB_AGC1 B43_OFDMTAB(0x00, 0) -#define B43_OFDMTAB_GAIN0 B43_OFDMTAB(0x00, 0) -#define B43_OFDMTAB_GAINX B43_OFDMTAB(0x01, 0) //TODO rename -#define B43_OFDMTAB_GAIN1 B43_OFDMTAB(0x01, 4) -#define B43_OFDMTAB_AGC3 B43_OFDMTAB(0x02, 0) -#define B43_OFDMTAB_GAIN2 B43_OFDMTAB(0x02, 3) -#define B43_OFDMTAB_LNAHPFGAIN1 B43_OFDMTAB(0x03, 0) -#define B43_OFDMTAB_WRSSI B43_OFDMTAB(0x04, 0) -#define B43_OFDMTAB_LNAHPFGAIN2 B43_OFDMTAB(0x04, 0) -#define B43_OFDMTAB_NOISESCALE B43_OFDMTAB(0x05, 0) -#define B43_OFDMTAB_AGC2 B43_OFDMTAB(0x06, 0) -#define B43_OFDMTAB_ROTOR B43_OFDMTAB(0x08, 0) -#define B43_OFDMTAB_ADVRETARD B43_OFDMTAB(0x09, 0) -#define B43_OFDMTAB_DAC B43_OFDMTAB(0x0C, 0) -#define B43_OFDMTAB_DC B43_OFDMTAB(0x0E, 7) -#define B43_OFDMTAB_PWRDYN2 B43_OFDMTAB(0x0E, 12) -#define B43_OFDMTAB_LNAGAIN B43_OFDMTAB(0x0E, 13) -#define B43_OFDMTAB_UNKNOWN_0F B43_OFDMTAB(0x0F, 0) //TODO rename -#define B43_OFDMTAB_UNKNOWN_APHY B43_OFDMTAB(0x0F, 7) //TODO rename -#define B43_OFDMTAB_LPFGAIN B43_OFDMTAB(0x0F, 12) -#define B43_OFDMTAB_RSSI B43_OFDMTAB(0x10, 0) -#define B43_OFDMTAB_UNKNOWN_11 B43_OFDMTAB(0x11, 4) //TODO rename -#define B43_OFDMTAB_AGC1_R1 B43_OFDMTAB(0x13, 0) -#define B43_OFDMTAB_GAINX_R1 B43_OFDMTAB(0x14, 0) //TODO remove! -#define B43_OFDMTAB_MINSIGSQ B43_OFDMTAB(0x14, 0) -#define B43_OFDMTAB_AGC3_R1 B43_OFDMTAB(0x15, 0) -#define B43_OFDMTAB_WRSSI_R1 B43_OFDMTAB(0x15, 4) -#define B43_OFDMTAB_TSSI B43_OFDMTAB(0x15, 0) -#define B43_OFDMTAB_DACRFPABB B43_OFDMTAB(0x16, 0) -#define B43_OFDMTAB_DACOFF B43_OFDMTAB(0x17, 0) -#define B43_OFDMTAB_DCBIAS B43_OFDMTAB(0x18, 0) - -u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset); -void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, - u16 offset, u16 value); -u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset); -void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, - u16 offset, u32 value); - - -struct b43_phy_a { - /* Pointer to the table used to convert a - * TSSI value to dBm-Q5.2 */ - const s8 *tssi2dbm; - /* Target idle TSSI */ - int tgt_idle_tssi; - /* Current idle TSSI */ - int cur_idle_tssi;//FIXME value currently not set - - /* A-PHY TX Power control value. */ - u16 txpwr_offset; - - //TODO lots of missing stuff -}; - -/** - * b43_phy_inita - Lowlevel A-PHY init routine. - * This is _only_ used by the G-PHY code. - */ -void b43_phy_inita(struct b43_wldev *dev); - - -struct b43_phy_operations; -extern const struct b43_phy_operations b43_phyops_a; - -#endif /* LINUX_B43_PHY_A_H_ */ diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c deleted file mode 100644 index 75b26e175e8f..000000000000 --- a/drivers/net/wireless/b43/phy_common.c +++ /dev/null @@ -1,423 +0,0 @@ -/* - - Broadcom B43 wireless driver - Common PHY routines - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005-2007 Stefano Brivio - Copyright (c) 2005-2008 Michael Buesch - Copyright (c) 2005, 2006 Danny van Dyk - Copyright (c) 2005, 2006 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "phy_common.h" -#include "phy_g.h" -#include "phy_a.h" -#include "phy_n.h" -#include "phy_lp.h" -#include "b43.h" -#include "main.h" - - -int b43_phy_allocate(struct b43_wldev *dev) -{ - struct b43_phy *phy = &(dev->phy); - int err; - - phy->ops = NULL; - - switch (phy->type) { - case B43_PHYTYPE_A: - phy->ops = &b43_phyops_a; - break; - case B43_PHYTYPE_G: - phy->ops = &b43_phyops_g; - break; - case B43_PHYTYPE_N: -#ifdef CONFIG_B43_NPHY - phy->ops = &b43_phyops_n; -#endif - break; - case B43_PHYTYPE_LP: -#ifdef CONFIG_B43_PHY_LP - phy->ops = &b43_phyops_lp; -#endif - break; - } - if (B43_WARN_ON(!phy->ops)) - return -ENODEV; - - err = phy->ops->allocate(dev); - if (err) - phy->ops = NULL; - - return err; -} - -void b43_phy_free(struct b43_wldev *dev) -{ - dev->phy.ops->free(dev); - dev->phy.ops = NULL; -} - -int b43_phy_init(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - const struct b43_phy_operations *ops = phy->ops; - int err; - - phy->channel = ops->get_default_chan(dev); - - ops->software_rfkill(dev, false); - err = ops->init(dev); - if (err) { - b43err(dev->wl, "PHY init failed\n"); - goto err_block_rf; - } - /* Make sure to switch hardware and firmware (SHM) to - * the default channel. */ - err = b43_switch_channel(dev, ops->get_default_chan(dev)); - if (err) { - b43err(dev->wl, "PHY init: Channel switch to default failed\n"); - goto err_phy_exit; - } - - return 0; - -err_phy_exit: - if (ops->exit) - ops->exit(dev); -err_block_rf: - ops->software_rfkill(dev, true); - - return err; -} - -void b43_phy_exit(struct b43_wldev *dev) -{ - const struct b43_phy_operations *ops = dev->phy.ops; - - ops->software_rfkill(dev, true); - if (ops->exit) - ops->exit(dev); -} - -bool b43_has_hardware_pctl(struct b43_wldev *dev) -{ - if (!dev->phy.hardware_power_control) - return 0; - if (!dev->phy.ops->supports_hwpctl) - return 0; - return dev->phy.ops->supports_hwpctl(dev); -} - -void b43_radio_lock(struct b43_wldev *dev) -{ - u32 macctl; - -#if B43_DEBUG - B43_WARN_ON(dev->phy.radio_locked); - dev->phy.radio_locked = 1; -#endif - - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl |= B43_MACCTL_RADIOLOCK; - b43_write32(dev, B43_MMIO_MACCTL, macctl); - /* Commit the write and wait for the firmware - * to finish any radio register access. */ - b43_read32(dev, B43_MMIO_MACCTL); - udelay(10); -} - -void b43_radio_unlock(struct b43_wldev *dev) -{ - u32 macctl; - -#if B43_DEBUG - B43_WARN_ON(!dev->phy.radio_locked); - dev->phy.radio_locked = 0; -#endif - - /* Commit any write */ - b43_read16(dev, B43_MMIO_PHY_VER); - /* unlock */ - macctl = b43_read32(dev, B43_MMIO_MACCTL); - macctl &= ~B43_MACCTL_RADIOLOCK; - b43_write32(dev, B43_MMIO_MACCTL, macctl); -} - -void b43_phy_lock(struct b43_wldev *dev) -{ -#if B43_DEBUG - B43_WARN_ON(dev->phy.phy_locked); - dev->phy.phy_locked = 1; -#endif - B43_WARN_ON(dev->dev->id.revision < 3); - - if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) - b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); -} - -void b43_phy_unlock(struct b43_wldev *dev) -{ -#if B43_DEBUG - B43_WARN_ON(!dev->phy.phy_locked); - dev->phy.phy_locked = 0; -#endif - B43_WARN_ON(dev->dev->id.revision < 3); - - if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) - b43_power_saving_ctl_bits(dev, 0); -} - -static inline void assert_mac_suspended(struct b43_wldev *dev) -{ - if (!B43_DEBUG) - return; - if ((b43_status(dev) >= B43_STAT_INITIALIZED) && - (dev->mac_suspended <= 0)) { - b43dbg(dev->wl, "PHY/RADIO register access with " - "enabled MAC.\n"); - dump_stack(); - } -} - -u16 b43_radio_read(struct b43_wldev *dev, u16 reg) -{ - assert_mac_suspended(dev); - return dev->phy.ops->radio_read(dev, reg); -} - -void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - assert_mac_suspended(dev); - dev->phy.ops->radio_write(dev, reg, value); -} - -void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask) -{ - b43_radio_write16(dev, offset, - b43_radio_read16(dev, offset) & mask); -} - -void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set) -{ - b43_radio_write16(dev, offset, - b43_radio_read16(dev, offset) | set); -} - -void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) -{ - b43_radio_write16(dev, offset, - (b43_radio_read16(dev, offset) & mask) | set); -} - -u16 b43_phy_read(struct b43_wldev *dev, u16 reg) -{ - assert_mac_suspended(dev); - return dev->phy.ops->phy_read(dev, reg); -} - -void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - assert_mac_suspended(dev); - dev->phy.ops->phy_write(dev, reg, value); -} - -void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) -{ - assert_mac_suspended(dev); - dev->phy.ops->phy_write(dev, destreg, - dev->phy.ops->phy_read(dev, srcreg)); -} - -void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) -{ - if (dev->phy.ops->phy_maskset) { - assert_mac_suspended(dev); - dev->phy.ops->phy_maskset(dev, offset, mask, 0); - } else { - b43_phy_write(dev, offset, - b43_phy_read(dev, offset) & mask); - } -} - -void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set) -{ - if (dev->phy.ops->phy_maskset) { - assert_mac_suspended(dev); - dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set); - } else { - b43_phy_write(dev, offset, - b43_phy_read(dev, offset) | set); - } -} - -void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) -{ - if (dev->phy.ops->phy_maskset) { - assert_mac_suspended(dev); - dev->phy.ops->phy_maskset(dev, offset, mask, set); - } else { - b43_phy_write(dev, offset, - (b43_phy_read(dev, offset) & mask) | set); - } -} - -int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) -{ - struct b43_phy *phy = &(dev->phy); - u16 channelcookie, savedcookie; - int err; - - if (new_channel == B43_DEFAULT_CHANNEL) - new_channel = phy->ops->get_default_chan(dev); - - /* First we set the channel radio code to prevent the - * firmware from sending ghost packets. - */ - channelcookie = new_channel; - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) - channelcookie |= 0x100; - //FIXME set 40Mhz flag if required - savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); - - /* Now try to switch the PHY hardware channel. */ - err = phy->ops->switch_channel(dev, new_channel); - if (err) - goto err_restore_cookie; - - dev->phy.channel = new_channel; - /* Wait for the radio to tune to the channel and stabilize. */ - msleep(8); - - return 0; - -err_restore_cookie: - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_CHAN, savedcookie); - - return err; -} - -void b43_software_rfkill(struct b43_wldev *dev, bool blocked) -{ - struct b43_phy *phy = &dev->phy; - - b43_mac_suspend(dev); - phy->ops->software_rfkill(dev, blocked); - phy->radio_on = !blocked; - b43_mac_enable(dev); -} - -/** - * b43_phy_txpower_adjust_work - TX power workqueue. - * - * Workqueue for updating the TX power parameters in hardware. - */ -void b43_phy_txpower_adjust_work(struct work_struct *work) -{ - struct b43_wl *wl = container_of(work, struct b43_wl, - txpower_adjust_work); - struct b43_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - - if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED))) - dev->phy.ops->adjust_txpower(dev); - - mutex_unlock(&wl->mutex); -} - -void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) -{ - struct b43_phy *phy = &dev->phy; - unsigned long now = jiffies; - enum b43_txpwr_result result; - - if (!(flags & B43_TXPWR_IGNORE_TIME)) { - /* Check if it's time for a TXpower check. */ - if (time_before(now, phy->next_txpwr_check_time)) - return; /* Not yet */ - } - /* The next check will be needed in two seconds, or later. */ - phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2)); - - if ((dev->dev->bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && - (dev->dev->bus->boardinfo.type == SSB_BOARD_BU4306)) - return; /* No software txpower adjustment needed */ - - result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI)); - if (result == B43_TXPWR_RES_DONE) - return; /* We are done. */ - B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST); - B43_WARN_ON(phy->ops->adjust_txpower == NULL); - - /* We must adjust the transmission power in hardware. - * Schedule b43_phy_txpower_adjust_work(). */ - ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work); -} - -int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) -{ - const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK); - unsigned int a, b, c, d; - unsigned int average; - u32 tmp; - - tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset); - a = tmp & 0xFF; - b = (tmp >> 8) & 0xFF; - c = (tmp >> 16) & 0xFF; - d = (tmp >> 24) & 0xFF; - if (a == 0 || a == B43_TSSI_MAX || - b == 0 || b == B43_TSSI_MAX || - c == 0 || c == B43_TSSI_MAX || - d == 0 || d == B43_TSSI_MAX) - return -ENOENT; - /* The values are OK. Clear them. */ - tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) | - (B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24); - b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp); - - if (is_ofdm) { - a = (a + 32) & 0x3F; - b = (b + 32) & 0x3F; - c = (c + 32) & 0x3F; - d = (d + 32) & 0x3F; - } - - /* Get the average of the values with 0.5 added to each value. */ - average = (a + b + c + d + 2) / 4; - if (is_ofdm) { - /* Adjust for CCK-boost */ - if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTFLO) - & B43_HF_CCKBOOST) - average = (average >= 13) ? (average - 13) : 0; - } - - return average; -} - -void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on) -{ - b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); -} diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h deleted file mode 100644 index 9edd4e8e0c85..000000000000 --- a/drivers/net/wireless/b43/phy_common.h +++ /dev/null @@ -1,422 +0,0 @@ -#ifndef LINUX_B43_PHY_COMMON_H_ -#define LINUX_B43_PHY_COMMON_H_ - -#include - -struct b43_wldev; - - -/* PHY register routing bits */ -#define B43_PHYROUTE 0x0C00 /* PHY register routing bits mask */ -#define B43_PHYROUTE_BASE 0x0000 /* Base registers */ -#define B43_PHYROUTE_OFDM_GPHY 0x0400 /* OFDM register routing for G-PHYs */ -#define B43_PHYROUTE_EXT_GPHY 0x0800 /* Extended G-PHY registers */ -#define B43_PHYROUTE_N_BMODE 0x0C00 /* N-PHY BMODE registers */ - -/* CCK (B-PHY) registers. */ -#define B43_PHY_CCK(reg) ((reg) | B43_PHYROUTE_BASE) -/* N-PHY registers. */ -#define B43_PHY_N(reg) ((reg) | B43_PHYROUTE_BASE) -/* N-PHY BMODE registers. */ -#define B43_PHY_N_BMODE(reg) ((reg) | B43_PHYROUTE_N_BMODE) -/* OFDM (A-PHY) registers. */ -#define B43_PHY_OFDM(reg) ((reg) | B43_PHYROUTE_OFDM_GPHY) -/* Extended G-PHY registers. */ -#define B43_PHY_EXTG(reg) ((reg) | B43_PHYROUTE_EXT_GPHY) - - -/* Masks for the PHY versioning registers. */ -#define B43_PHYVER_ANALOG 0xF000 -#define B43_PHYVER_ANALOG_SHIFT 12 -#define B43_PHYVER_TYPE 0x0F00 -#define B43_PHYVER_TYPE_SHIFT 8 -#define B43_PHYVER_VERSION 0x00FF - -/** - * enum b43_interference_mitigation - Interference Mitigation mode - * - * @B43_INTERFMODE_NONE: Disabled - * @B43_INTERFMODE_NONWLAN: Non-WLAN Interference Mitigation - * @B43_INTERFMODE_MANUALWLAN: WLAN Interference Mitigation - * @B43_INTERFMODE_AUTOWLAN: Automatic WLAN Interference Mitigation - */ -enum b43_interference_mitigation { - B43_INTERFMODE_NONE, - B43_INTERFMODE_NONWLAN, - B43_INTERFMODE_MANUALWLAN, - B43_INTERFMODE_AUTOWLAN, -}; - -/* Antenna identifiers */ -enum { - B43_ANTENNA0 = 0, /* Antenna 0 */ - B43_ANTENNA1 = 1, /* Antenna 1 */ - B43_ANTENNA_AUTO0 = 2, /* Automatic, starting with antenna 0 */ - B43_ANTENNA_AUTO1 = 3, /* Automatic, starting with antenna 1 */ - B43_ANTENNA2 = 4, - B43_ANTENNA3 = 8, - - B43_ANTENNA_AUTO = B43_ANTENNA_AUTO0, - B43_ANTENNA_DEFAULT = B43_ANTENNA_AUTO, -}; - -/** - * enum b43_txpwr_result - Return value for the recalc_txpower PHY op. - * - * @B43_TXPWR_RES_NEED_ADJUST: Values changed. Hardware adjustment is needed. - * @B43_TXPWR_RES_DONE: No more work to do. Everything is done. - */ -enum b43_txpwr_result { - B43_TXPWR_RES_NEED_ADJUST, - B43_TXPWR_RES_DONE, -}; - -/** - * struct b43_phy_operations - Function pointers for PHY ops. - * - * @allocate: Allocate and initialise the PHY data structures. - * Must not be NULL. - * @free: Destroy and free the PHY data structures. - * Must not be NULL. - * - * @prepare_structs: Prepare the PHY data structures. - * The data structures allocated in @allocate are - * initialized here. - * Must not be NULL. - * @prepare_hardware: Prepare the PHY. This is called before b43_chip_init to - * do some early early PHY hardware init. - * Can be NULL, if not required. - * @init: Initialize the PHY. - * Must not be NULL. - * @exit: Shutdown the PHY. - * Can be NULL, if not required. - * - * @phy_read: Read from a PHY register. - * Must not be NULL. - * @phy_write: Write to a PHY register. - * Must not be NULL. - * @phy_maskset: Maskset a PHY register, taking shortcuts. - * If it is NULL, a generic algorithm is used. - * @radio_read: Read from a Radio register. - * Must not be NULL. - * @radio_write: Write to a Radio register. - * Must not be NULL. - * - * @supports_hwpctl: Returns a boolean whether Hardware Power Control - * is supported or not. - * If NULL, hwpctl is assumed to be never supported. - * @software_rfkill: Turn the radio ON or OFF. - * Possible state values are - * RFKILL_STATE_SOFT_BLOCKED or - * RFKILL_STATE_UNBLOCKED - * Must not be NULL. - * @switch_analog: Turn the Analog on/off. - * Must not be NULL. - * @switch_channel: Switch the radio to another channel. - * Must not be NULL. - * @get_default_chan: Just returns the default channel number. - * Must not be NULL. - * @set_rx_antenna: Set the antenna used for RX. - * Can be NULL, if not supported. - * @interf_mitigation: Switch the Interference Mitigation mode. - * Can be NULL, if not supported. - * - * @recalc_txpower: Recalculate the transmission power parameters. - * This callback has to recalculate the TX power settings, - * but does not need to write them to the hardware, yet. - * Returns enum b43_txpwr_result to indicate whether the hardware - * needs to be adjusted. - * If B43_TXPWR_NEED_ADJUST is returned, @adjust_txpower - * will be called later. - * If the parameter "ignore_tssi" is true, the TSSI values should - * be ignored and a recalculation of the power settings should be - * done even if the TSSI values did not change. - * This function may sleep, but should not. - * Must not be NULL. - * @adjust_txpower: Write the previously calculated TX power settings - * (from @recalc_txpower) to the hardware. - * This function may sleep. - * Can be NULL, if (and ONLY if) @recalc_txpower _always_ - * returns B43_TXPWR_RES_DONE. - * - * @pwork_15sec: Periodic work. Called every 15 seconds. - * Can be NULL, if not required. - * @pwork_60sec: Periodic work. Called every 60 seconds. - * Can be NULL, if not required. - */ -struct b43_phy_operations { - /* Initialisation */ - int (*allocate)(struct b43_wldev *dev); - void (*free)(struct b43_wldev *dev); - void (*prepare_structs)(struct b43_wldev *dev); - int (*prepare_hardware)(struct b43_wldev *dev); - int (*init)(struct b43_wldev *dev); - void (*exit)(struct b43_wldev *dev); - - /* Register access */ - u16 (*phy_read)(struct b43_wldev *dev, u16 reg); - void (*phy_write)(struct b43_wldev *dev, u16 reg, u16 value); - void (*phy_maskset)(struct b43_wldev *dev, u16 reg, u16 mask, u16 set); - u16 (*radio_read)(struct b43_wldev *dev, u16 reg); - void (*radio_write)(struct b43_wldev *dev, u16 reg, u16 value); - - /* Radio */ - bool (*supports_hwpctl)(struct b43_wldev *dev); - void (*software_rfkill)(struct b43_wldev *dev, bool blocked); - void (*switch_analog)(struct b43_wldev *dev, bool on); - int (*switch_channel)(struct b43_wldev *dev, unsigned int new_channel); - unsigned int (*get_default_chan)(struct b43_wldev *dev); - void (*set_rx_antenna)(struct b43_wldev *dev, int antenna); - int (*interf_mitigation)(struct b43_wldev *dev, - enum b43_interference_mitigation new_mode); - - /* Transmission power adjustment */ - enum b43_txpwr_result (*recalc_txpower)(struct b43_wldev *dev, - bool ignore_tssi); - void (*adjust_txpower)(struct b43_wldev *dev); - - /* Misc */ - void (*pwork_15sec)(struct b43_wldev *dev); - void (*pwork_60sec)(struct b43_wldev *dev); -}; - -struct b43_phy_a; -struct b43_phy_g; -struct b43_phy_n; -struct b43_phy_lp; - -struct b43_phy { - /* Hardware operation callbacks. */ - const struct b43_phy_operations *ops; - - /* Most hardware context information is stored in the standard- - * specific data structures pointed to by the pointers below. - * Only one of them is valid (the currently enabled PHY). */ -#ifdef CONFIG_B43_DEBUG - /* No union for debug build to force NULL derefs in buggy code. */ - struct { -#else - union { -#endif - /* A-PHY specific information */ - struct b43_phy_a *a; - /* G-PHY specific information */ - struct b43_phy_g *g; - /* N-PHY specific information */ - struct b43_phy_n *n; - /* LP-PHY specific information */ - struct b43_phy_lp *lp; - }; - - /* Band support flags. */ - bool supports_2ghz; - bool supports_5ghz; - - /* GMODE bit enabled? */ - bool gmode; - - /* Analog Type */ - u8 analog; - /* B43_PHYTYPE_ */ - u8 type; - /* PHY revision number. */ - u8 rev; - - /* Radio versioning */ - u16 radio_manuf; /* Radio manufacturer */ - u16 radio_ver; /* Radio version */ - u8 radio_rev; /* Radio revision */ - - /* Software state of the radio */ - bool radio_on; - - /* Desired TX power level (in dBm). - * This is set by the user and adjusted in b43_phy_xmitpower(). */ - int desired_txpower; - - /* Hardware Power Control enabled? */ - bool hardware_power_control; - - /* The time (in absolute jiffies) when the next TX power output - * check is needed. */ - unsigned long next_txpwr_check_time; - - /* current channel */ - unsigned int channel; - - /* PHY TX errors counter. */ - atomic_t txerr_cnt; - -#ifdef CONFIG_B43_DEBUG - /* PHY registers locked (w.r.t. firmware) */ - bool phy_locked; - /* Radio registers locked (w.r.t. firmware) */ - bool radio_locked; -#endif /* B43_DEBUG */ -}; - - -/** - * b43_phy_allocate - Allocate PHY structs - * Allocate the PHY data structures, based on the current dev->phy.type - */ -int b43_phy_allocate(struct b43_wldev *dev); - -/** - * b43_phy_free - Free PHY structs - */ -void b43_phy_free(struct b43_wldev *dev); - -/** - * b43_phy_init - Initialise the PHY - */ -int b43_phy_init(struct b43_wldev *dev); - -/** - * b43_phy_exit - Cleanup PHY - */ -void b43_phy_exit(struct b43_wldev *dev); - -/** - * b43_has_hardware_pctl - Hardware Power Control supported? - * Returns a boolean, whether hardware power control is supported. - */ -bool b43_has_hardware_pctl(struct b43_wldev *dev); - -/** - * b43_phy_read - 16bit PHY register read access - */ -u16 b43_phy_read(struct b43_wldev *dev, u16 reg); - -/** - * b43_phy_write - 16bit PHY register write access - */ -void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value); - -/** - * b43_phy_copy - copy contents of 16bit PHY register to another - */ -void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg); - -/** - * b43_phy_mask - Mask a PHY register with a mask - */ -void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask); - -/** - * b43_phy_set - OR a PHY register with a bitmap - */ -void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set); - -/** - * b43_phy_maskset - Mask and OR a PHY register with a mask and bitmap - */ -void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); - -/** - * b43_radio_read - 16bit Radio register read access - */ -u16 b43_radio_read(struct b43_wldev *dev, u16 reg); -#define b43_radio_read16 b43_radio_read /* DEPRECATED */ - -/** - * b43_radio_write - 16bit Radio register write access - */ -void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value); -#define b43_radio_write16 b43_radio_write /* DEPRECATED */ - -/** - * b43_radio_mask - Mask a 16bit radio register with a mask - */ -void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask); - -/** - * b43_radio_set - OR a 16bit radio register with a bitmap - */ -void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set); - -/** - * b43_radio_maskset - Mask and OR a radio register with a mask and bitmap - */ -void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set); - -/** - * b43_radio_lock - Lock firmware radio register access - */ -void b43_radio_lock(struct b43_wldev *dev); - -/** - * b43_radio_unlock - Unlock firmware radio register access - */ -void b43_radio_unlock(struct b43_wldev *dev); - -/** - * b43_phy_lock - Lock firmware PHY register access - */ -void b43_phy_lock(struct b43_wldev *dev); - -/** - * b43_phy_unlock - Unlock firmware PHY register access - */ -void b43_phy_unlock(struct b43_wldev *dev); - -/** - * b43_switch_channel - Switch to another channel - */ -int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel); -/** - * B43_DEFAULT_CHANNEL - Switch to the default channel. - */ -#define B43_DEFAULT_CHANNEL UINT_MAX - -/** - * b43_software_rfkill - Turn the radio ON or OFF in software. - */ -void b43_software_rfkill(struct b43_wldev *dev, bool blocked); - -/** - * b43_phy_txpower_check - Check TX power output. - * - * Compare the current TX power output to the desired power emission - * and schedule an adjustment in case it mismatches. - * - * @flags: OR'ed enum b43_phy_txpower_check_flags flags. - * See the docs below. - */ -void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags); -/** - * enum b43_phy_txpower_check_flags - Flags for b43_phy_txpower_check() - * - * @B43_TXPWR_IGNORE_TIME: Ignore the schedule time and force-redo - * the check now. - * @B43_TXPWR_IGNORE_TSSI: Redo the recalculation, even if the average - * TSSI did not change. - */ -enum b43_phy_txpower_check_flags { - B43_TXPWR_IGNORE_TIME = (1 << 0), - B43_TXPWR_IGNORE_TSSI = (1 << 1), -}; - -struct work_struct; -void b43_phy_txpower_adjust_work(struct work_struct *work); - -/** - * b43_phy_shm_tssi_read - Read the average of the last 4 TSSI from SHM. - * - * @shm_offset: The SHM address to read the values from. - * - * Returns the average of the 4 TSSI values, or a negative error code. - */ -int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset); - -/** - * b43_phy_switch_analog_generic - Generic PHY operation for switching the Analog. - * - * It does the switching based on the PHY0 core register. - * Do _not_ call this directly. Only use it as a switch_analog callback - * for struct b43_phy_operations. - */ -void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on); - - -#endif /* LINUX_B43_PHY_COMMON_H_ */ diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c deleted file mode 100644 index 382826a8da82..000000000000 --- a/drivers/net/wireless/b43/phy_g.c +++ /dev/null @@ -1,3056 +0,0 @@ -/* - - Broadcom B43 wireless driver - IEEE 802.11g PHY driver - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005-2007 Stefano Brivio - Copyright (c) 2005-2008 Michael Buesch - Copyright (c) 2005, 2006 Danny van Dyk - Copyright (c) 2005, 2006 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "phy_g.h" -#include "phy_common.h" -#include "lo.h" -#include "main.h" - -#include - - -static const s8 b43_tssi2dbm_g_table[] = { - 77, 77, 77, 76, - 76, 76, 75, 75, - 74, 74, 73, 73, - 73, 72, 72, 71, - 71, 70, 70, 69, - 68, 68, 67, 67, - 66, 65, 65, 64, - 63, 63, 62, 61, - 60, 59, 58, 57, - 56, 55, 54, 53, - 52, 50, 49, 47, - 45, 43, 40, 37, - 33, 28, 22, 14, - 5, -7, -20, -20, - -20, -20, -20, -20, - -20, -20, -20, -20, -}; - -static const u8 b43_radio_channel_codes_bg[] = { - 12, 17, 22, 27, - 32, 37, 42, 47, - 52, 57, 62, 67, - 72, 84, -}; - - -static void b43_calc_nrssi_threshold(struct b43_wldev *dev); - - -#define bitrev4(tmp) (bitrev8(tmp) >> 4) - - -/* Get the freq, as it has to be written to the device. */ -static inline u16 channel2freq_bg(u8 channel) -{ - B43_WARN_ON(!(channel >= 1 && channel <= 14)); - - return b43_radio_channel_codes_bg[channel - 1]; -} - -static void generate_rfatt_list(struct b43_wldev *dev, - struct b43_rfatt_list *list) -{ - struct b43_phy *phy = &dev->phy; - - /* APHY.rev < 5 || GPHY.rev < 6 */ - static const struct b43_rfatt rfatt_0[] = { - {.att = 3,.with_padmix = 0,}, - {.att = 1,.with_padmix = 0,}, - {.att = 5,.with_padmix = 0,}, - {.att = 7,.with_padmix = 0,}, - {.att = 9,.with_padmix = 0,}, - {.att = 2,.with_padmix = 0,}, - {.att = 0,.with_padmix = 0,}, - {.att = 4,.with_padmix = 0,}, - {.att = 6,.with_padmix = 0,}, - {.att = 8,.with_padmix = 0,}, - {.att = 1,.with_padmix = 1,}, - {.att = 2,.with_padmix = 1,}, - {.att = 3,.with_padmix = 1,}, - {.att = 4,.with_padmix = 1,}, - }; - /* Radio.rev == 8 && Radio.version == 0x2050 */ - static const struct b43_rfatt rfatt_1[] = { - {.att = 2,.with_padmix = 1,}, - {.att = 4,.with_padmix = 1,}, - {.att = 6,.with_padmix = 1,}, - {.att = 8,.with_padmix = 1,}, - {.att = 10,.with_padmix = 1,}, - {.att = 12,.with_padmix = 1,}, - {.att = 14,.with_padmix = 1,}, - }; - /* Otherwise */ - static const struct b43_rfatt rfatt_2[] = { - {.att = 0,.with_padmix = 1,}, - {.att = 2,.with_padmix = 1,}, - {.att = 4,.with_padmix = 1,}, - {.att = 6,.with_padmix = 1,}, - {.att = 8,.with_padmix = 1,}, - {.att = 9,.with_padmix = 1,}, - {.att = 9,.with_padmix = 1,}, - }; - - if (!b43_has_hardware_pctl(dev)) { - /* Software pctl */ - list->list = rfatt_0; - list->len = ARRAY_SIZE(rfatt_0); - list->min_val = 0; - list->max_val = 9; - return; - } - if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { - /* Hardware pctl */ - list->list = rfatt_1; - list->len = ARRAY_SIZE(rfatt_1); - list->min_val = 0; - list->max_val = 14; - return; - } - /* Hardware pctl */ - list->list = rfatt_2; - list->len = ARRAY_SIZE(rfatt_2); - list->min_val = 0; - list->max_val = 9; -} - -static void generate_bbatt_list(struct b43_wldev *dev, - struct b43_bbatt_list *list) -{ - static const struct b43_bbatt bbatt_0[] = { - {.att = 0,}, - {.att = 1,}, - {.att = 2,}, - {.att = 3,}, - {.att = 4,}, - {.att = 5,}, - {.att = 6,}, - {.att = 7,}, - {.att = 8,}, - }; - - list->list = bbatt_0; - list->len = ARRAY_SIZE(bbatt_0); - list->min_val = 0; - list->max_val = 8; -} - -static void b43_shm_clear_tssi(struct b43_wldev *dev) -{ - b43_shm_write16(dev, B43_SHM_SHARED, 0x0058, 0x7F7F); - b43_shm_write16(dev, B43_SHM_SHARED, 0x005a, 0x7F7F); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0070, 0x7F7F); - b43_shm_write16(dev, B43_SHM_SHARED, 0x0072, 0x7F7F); -} - -/* Synthetic PU workaround */ -static void b43_synth_pu_workaround(struct b43_wldev *dev, u8 channel) -{ - struct b43_phy *phy = &dev->phy; - - might_sleep(); - - if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) { - /* We do not need the workaround. */ - return; - } - - if (channel <= 10) { - b43_write16(dev, B43_MMIO_CHANNEL, - channel2freq_bg(channel + 4)); - } else { - b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(1)); - } - msleep(1); - b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); -} - -/* Set the baseband attenuation value on chip. */ -void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev, - u16 baseband_attenuation) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->analog == 0) { - b43_write16(dev, B43_MMIO_PHY0, (b43_read16(dev, B43_MMIO_PHY0) - & 0xFFF0) | - baseband_attenuation); - } else if (phy->analog > 1) { - b43_phy_maskset(dev, B43_PHY_DACCTL, 0xFFC3, (baseband_attenuation << 2)); - } else { - b43_phy_maskset(dev, B43_PHY_DACCTL, 0xFF87, (baseband_attenuation << 3)); - } -} - -/* Adjust the transmission power output (G-PHY) */ -static void b43_set_txpower_g(struct b43_wldev *dev, - const struct b43_bbatt *bbatt, - const struct b43_rfatt *rfatt, u8 tx_control) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - u16 bb, rf; - u16 tx_bias, tx_magn; - - bb = bbatt->att; - rf = rfatt->att; - tx_bias = lo->tx_bias; - tx_magn = lo->tx_magn; - if (unlikely(tx_bias == 0xFF)) - tx_bias = 0; - - /* Save the values for later. Use memmove, because it's valid - * to pass &gphy->rfatt as rfatt pointer argument. Same for bbatt. */ - gphy->tx_control = tx_control; - memmove(&gphy->rfatt, rfatt, sizeof(*rfatt)); - gphy->rfatt.with_padmix = !!(tx_control & B43_TXCTL_TXMIX); - memmove(&gphy->bbatt, bbatt, sizeof(*bbatt)); - - if (b43_debug(dev, B43_DBG_XMITPOWER)) { - b43dbg(dev->wl, "Tuning TX-power to bbatt(%u), " - "rfatt(%u), tx_control(0x%02X), " - "tx_bias(0x%02X), tx_magn(0x%02X)\n", - bb, rf, tx_control, tx_bias, tx_magn); - } - - b43_gphy_set_baseband_attenuation(dev, bb); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RFATT, rf); - if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { - b43_radio_write16(dev, 0x43, - (rf & 0x000F) | (tx_control & 0x0070)); - } else { - b43_radio_maskset(dev, 0x43, 0xFFF0, (rf & 0x000F)); - b43_radio_maskset(dev, 0x52, ~0x0070, (tx_control & 0x0070)); - } - if (has_tx_magnification(phy)) { - b43_radio_write16(dev, 0x52, tx_magn | tx_bias); - } else { - b43_radio_maskset(dev, 0x52, 0xFFF0, (tx_bias & 0x000F)); - } - b43_lo_g_adjust(dev); -} - -/* GPHY_TSSI_Power_Lookup_Table_Init */ -static void b43_gphy_tssi_power_lt_init(struct b43_wldev *dev) -{ - struct b43_phy_g *gphy = dev->phy.g; - int i; - u16 value; - - for (i = 0; i < 32; i++) - b43_ofdmtab_write16(dev, 0x3C20, i, gphy->tssi2dbm[i]); - for (i = 32; i < 64; i++) - b43_ofdmtab_write16(dev, 0x3C00, i - 32, gphy->tssi2dbm[i]); - for (i = 0; i < 64; i += 2) { - value = (u16) gphy->tssi2dbm[i]; - value |= ((u16) gphy->tssi2dbm[i + 1]) << 8; - b43_phy_write(dev, 0x380 + (i / 2), value); - } -} - -/* GPHY_Gain_Lookup_Table_Init */ -static void b43_gphy_gain_lt_init(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - u16 nr_written = 0; - u16 tmp; - u8 rf, bb; - - for (rf = 0; rf < lo->rfatt_list.len; rf++) { - for (bb = 0; bb < lo->bbatt_list.len; bb++) { - if (nr_written >= 0x40) - return; - tmp = lo->bbatt_list.list[bb].att; - tmp <<= 8; - if (phy->radio_rev == 8) - tmp |= 0x50; - else - tmp |= 0x40; - tmp |= lo->rfatt_list.list[rf].att; - b43_phy_write(dev, 0x3C0 + nr_written, tmp); - nr_written++; - } - } -} - -static void b43_set_all_gains(struct b43_wldev *dev, - s16 first, s16 second, s16 third) -{ - struct b43_phy *phy = &dev->phy; - u16 i; - u16 start = 0x08, end = 0x18; - u16 tmp; - u16 table; - - if (phy->rev <= 1) { - start = 0x10; - end = 0x20; - } - - table = B43_OFDMTAB_GAINX; - if (phy->rev <= 1) - table = B43_OFDMTAB_GAINX_R1; - for (i = 0; i < 4; i++) - b43_ofdmtab_write16(dev, table, i, first); - - for (i = start; i < end; i++) - b43_ofdmtab_write16(dev, table, i, second); - - if (third != -1) { - tmp = ((u16) third << 14) | ((u16) third << 6); - b43_phy_maskset(dev, 0x04A0, 0xBFBF, tmp); - b43_phy_maskset(dev, 0x04A1, 0xBFBF, tmp); - b43_phy_maskset(dev, 0x04A2, 0xBFBF, tmp); - } - b43_dummy_transmission(dev, false, true); -} - -static void b43_set_original_gains(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 i, tmp; - u16 table; - u16 start = 0x0008, end = 0x0018; - - if (phy->rev <= 1) { - start = 0x0010; - end = 0x0020; - } - - table = B43_OFDMTAB_GAINX; - if (phy->rev <= 1) - table = B43_OFDMTAB_GAINX_R1; - for (i = 0; i < 4; i++) { - tmp = (i & 0xFFFC); - tmp |= (i & 0x0001) << 1; - tmp |= (i & 0x0002) >> 1; - - b43_ofdmtab_write16(dev, table, i, tmp); - } - - for (i = start; i < end; i++) - b43_ofdmtab_write16(dev, table, i, i - start); - - b43_phy_maskset(dev, 0x04A0, 0xBFBF, 0x4040); - b43_phy_maskset(dev, 0x04A1, 0xBFBF, 0x4040); - b43_phy_maskset(dev, 0x04A2, 0xBFBF, 0x4000); - b43_dummy_transmission(dev, false, true); -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -static void b43_nrssi_hw_write(struct b43_wldev *dev, u16 offset, s16 val) -{ - b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); - b43_phy_write(dev, B43_PHY_NRSSILT_DATA, (u16) val); -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -static s16 b43_nrssi_hw_read(struct b43_wldev *dev, u16 offset) -{ - u16 val; - - b43_phy_write(dev, B43_PHY_NRSSILT_CTRL, offset); - val = b43_phy_read(dev, B43_PHY_NRSSILT_DATA); - - return (s16) val; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -static void b43_nrssi_hw_update(struct b43_wldev *dev, u16 val) -{ - u16 i; - s16 tmp; - - for (i = 0; i < 64; i++) { - tmp = b43_nrssi_hw_read(dev, i); - tmp -= val; - tmp = clamp_val(tmp, -32, 31); - b43_nrssi_hw_write(dev, i, tmp); - } -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -static void b43_nrssi_mem_update(struct b43_wldev *dev) -{ - struct b43_phy_g *gphy = dev->phy.g; - s16 i, delta; - s32 tmp; - - delta = 0x1F - gphy->nrssi[0]; - for (i = 0; i < 64; i++) { - tmp = (i - delta) * gphy->nrssislope; - tmp /= 0x10000; - tmp += 0x3A; - tmp = clamp_val(tmp, 0, 0x3F); - gphy->nrssi_lt[i] = tmp; - } -} - -static void b43_calc_nrssi_offset(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 backup[20] = { 0 }; - s16 v47F; - u16 i; - u16 saved = 0xFFFF; - - backup[0] = b43_phy_read(dev, 0x0001); - backup[1] = b43_phy_read(dev, 0x0811); - backup[2] = b43_phy_read(dev, 0x0812); - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - backup[3] = b43_phy_read(dev, 0x0814); - backup[4] = b43_phy_read(dev, 0x0815); - } - backup[5] = b43_phy_read(dev, 0x005A); - backup[6] = b43_phy_read(dev, 0x0059); - backup[7] = b43_phy_read(dev, 0x0058); - backup[8] = b43_phy_read(dev, 0x000A); - backup[9] = b43_phy_read(dev, 0x0003); - backup[10] = b43_radio_read16(dev, 0x007A); - backup[11] = b43_radio_read16(dev, 0x0043); - - b43_phy_mask(dev, 0x0429, 0x7FFF); - b43_phy_maskset(dev, 0x0001, 0x3FFF, 0x4000); - b43_phy_set(dev, 0x0811, 0x000C); - b43_phy_maskset(dev, 0x0812, 0xFFF3, 0x0004); - b43_phy_mask(dev, 0x0802, ~(0x1 | 0x2)); - if (phy->rev >= 6) { - backup[12] = b43_phy_read(dev, 0x002E); - backup[13] = b43_phy_read(dev, 0x002F); - backup[14] = b43_phy_read(dev, 0x080F); - backup[15] = b43_phy_read(dev, 0x0810); - backup[16] = b43_phy_read(dev, 0x0801); - backup[17] = b43_phy_read(dev, 0x0060); - backup[18] = b43_phy_read(dev, 0x0014); - backup[19] = b43_phy_read(dev, 0x0478); - - b43_phy_write(dev, 0x002E, 0); - b43_phy_write(dev, 0x002F, 0); - b43_phy_write(dev, 0x080F, 0); - b43_phy_write(dev, 0x0810, 0); - b43_phy_set(dev, 0x0478, 0x0100); - b43_phy_set(dev, 0x0801, 0x0040); - b43_phy_set(dev, 0x0060, 0x0040); - b43_phy_set(dev, 0x0014, 0x0200); - } - b43_radio_set(dev, 0x007A, 0x0070); - b43_radio_set(dev, 0x007A, 0x0080); - udelay(30); - - v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == 31) { - for (i = 7; i >= 4; i--) { - b43_radio_write16(dev, 0x007B, i); - udelay(20); - v47F = - (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F < 31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 4; - } else { - b43_radio_mask(dev, 0x007A, 0x007F); - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - b43_phy_set(dev, 0x0814, 0x0001); - b43_phy_mask(dev, 0x0815, 0xFFFE); - } - b43_phy_set(dev, 0x0811, 0x000C); - b43_phy_set(dev, 0x0812, 0x000C); - b43_phy_set(dev, 0x0811, 0x0030); - b43_phy_set(dev, 0x0812, 0x0030); - b43_phy_write(dev, 0x005A, 0x0480); - b43_phy_write(dev, 0x0059, 0x0810); - b43_phy_write(dev, 0x0058, 0x000D); - if (phy->rev == 0) { - b43_phy_write(dev, 0x0003, 0x0122); - } else { - b43_phy_set(dev, 0x000A, 0x2000); - } - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - b43_phy_set(dev, 0x0814, 0x0004); - b43_phy_mask(dev, 0x0815, 0xFFFB); - } - b43_phy_maskset(dev, 0x0003, 0xFF9F, 0x0040); - b43_radio_set(dev, 0x007A, 0x000F); - b43_set_all_gains(dev, 3, 0, 1); - b43_radio_maskset(dev, 0x0043, 0x00F0, 0x000F); - udelay(30); - v47F = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == -32) { - for (i = 0; i < 4; i++) { - b43_radio_write16(dev, 0x007B, i); - udelay(20); - v47F = - (s16) ((b43_phy_read(dev, 0x047F) >> 8) & - 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F > -31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 3; - } else - saved = 0; - } - b43_radio_write16(dev, 0x007B, saved); - - if (phy->rev >= 6) { - b43_phy_write(dev, 0x002E, backup[12]); - b43_phy_write(dev, 0x002F, backup[13]); - b43_phy_write(dev, 0x080F, backup[14]); - b43_phy_write(dev, 0x0810, backup[15]); - } - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - b43_phy_write(dev, 0x0814, backup[3]); - b43_phy_write(dev, 0x0815, backup[4]); - } - b43_phy_write(dev, 0x005A, backup[5]); - b43_phy_write(dev, 0x0059, backup[6]); - b43_phy_write(dev, 0x0058, backup[7]); - b43_phy_write(dev, 0x000A, backup[8]); - b43_phy_write(dev, 0x0003, backup[9]); - b43_radio_write16(dev, 0x0043, backup[11]); - b43_radio_write16(dev, 0x007A, backup[10]); - b43_phy_write(dev, 0x0802, b43_phy_read(dev, 0x0802) | 0x1 | 0x2); - b43_phy_set(dev, 0x0429, 0x8000); - b43_set_original_gains(dev); - if (phy->rev >= 6) { - b43_phy_write(dev, 0x0801, backup[16]); - b43_phy_write(dev, 0x0060, backup[17]); - b43_phy_write(dev, 0x0014, backup[18]); - b43_phy_write(dev, 0x0478, backup[19]); - } - b43_phy_write(dev, 0x0001, backup[0]); - b43_phy_write(dev, 0x0812, backup[2]); - b43_phy_write(dev, 0x0811, backup[1]); -} - -static void b43_calc_nrssi_slope(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 backup[18] = { 0 }; - u16 tmp; - s16 nrssi0, nrssi1; - - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - - if (phy->radio_rev >= 9) - return; - if (phy->radio_rev == 8) - b43_calc_nrssi_offset(dev); - - b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF); - b43_phy_mask(dev, 0x0802, 0xFFFC); - backup[7] = b43_read16(dev, 0x03E2); - b43_write16(dev, 0x03E2, b43_read16(dev, 0x03E2) | 0x8000); - backup[0] = b43_radio_read16(dev, 0x007A); - backup[1] = b43_radio_read16(dev, 0x0052); - backup[2] = b43_radio_read16(dev, 0x0043); - backup[3] = b43_phy_read(dev, 0x0015); - backup[4] = b43_phy_read(dev, 0x005A); - backup[5] = b43_phy_read(dev, 0x0059); - backup[6] = b43_phy_read(dev, 0x0058); - backup[8] = b43_read16(dev, 0x03E6); - backup[9] = b43_read16(dev, B43_MMIO_CHANNEL_EXT); - if (phy->rev >= 3) { - backup[10] = b43_phy_read(dev, 0x002E); - backup[11] = b43_phy_read(dev, 0x002F); - backup[12] = b43_phy_read(dev, 0x080F); - backup[13] = b43_phy_read(dev, B43_PHY_G_LO_CONTROL); - backup[14] = b43_phy_read(dev, 0x0801); - backup[15] = b43_phy_read(dev, 0x0060); - backup[16] = b43_phy_read(dev, 0x0014); - backup[17] = b43_phy_read(dev, 0x0478); - b43_phy_write(dev, 0x002E, 0); - b43_phy_write(dev, B43_PHY_G_LO_CONTROL, 0); - switch (phy->rev) { - case 4: - case 6: - case 7: - b43_phy_set(dev, 0x0478, 0x0100); - b43_phy_set(dev, 0x0801, 0x0040); - break; - case 3: - case 5: - b43_phy_mask(dev, 0x0801, 0xFFBF); - break; - } - b43_phy_set(dev, 0x0060, 0x0040); - b43_phy_set(dev, 0x0014, 0x0200); - } - b43_radio_set(dev, 0x007A, 0x0070); - b43_set_all_gains(dev, 0, 8, 0); - b43_radio_mask(dev, 0x007A, 0x00F7); - if (phy->rev >= 2) { - b43_phy_maskset(dev, 0x0811, 0xFFCF, 0x0030); - b43_phy_maskset(dev, 0x0812, 0xFFCF, 0x0010); - } - b43_radio_set(dev, 0x007A, 0x0080); - udelay(20); - - nrssi0 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (nrssi0 >= 0x0020) - nrssi0 -= 0x0040; - - b43_radio_mask(dev, 0x007A, 0x007F); - if (phy->rev >= 2) { - b43_phy_maskset(dev, 0x0003, 0xFF9F, 0x0040); - } - - b43_write16(dev, B43_MMIO_CHANNEL_EXT, - b43_read16(dev, B43_MMIO_CHANNEL_EXT) - | 0x2000); - b43_radio_set(dev, 0x007A, 0x000F); - b43_phy_write(dev, 0x0015, 0xF330); - if (phy->rev >= 2) { - b43_phy_maskset(dev, 0x0812, 0xFFCF, 0x0020); - b43_phy_maskset(dev, 0x0811, 0xFFCF, 0x0020); - } - - b43_set_all_gains(dev, 3, 0, 1); - if (phy->radio_rev == 8) { - b43_radio_write16(dev, 0x0043, 0x001F); - } else { - tmp = b43_radio_read16(dev, 0x0052) & 0xFF0F; - b43_radio_write16(dev, 0x0052, tmp | 0x0060); - tmp = b43_radio_read16(dev, 0x0043) & 0xFFF0; - b43_radio_write16(dev, 0x0043, tmp | 0x0009); - } - b43_phy_write(dev, 0x005A, 0x0480); - b43_phy_write(dev, 0x0059, 0x0810); - b43_phy_write(dev, 0x0058, 0x000D); - udelay(20); - nrssi1 = (s16) ((b43_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (nrssi1 >= 0x0020) - nrssi1 -= 0x0040; - if (nrssi0 == nrssi1) - gphy->nrssislope = 0x00010000; - else - gphy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - if (nrssi0 >= -4) { - gphy->nrssi[0] = nrssi1; - gphy->nrssi[1] = nrssi0; - } - if (phy->rev >= 3) { - b43_phy_write(dev, 0x002E, backup[10]); - b43_phy_write(dev, 0x002F, backup[11]); - b43_phy_write(dev, 0x080F, backup[12]); - b43_phy_write(dev, B43_PHY_G_LO_CONTROL, backup[13]); - } - if (phy->rev >= 2) { - b43_phy_mask(dev, 0x0812, 0xFFCF); - b43_phy_mask(dev, 0x0811, 0xFFCF); - } - - b43_radio_write16(dev, 0x007A, backup[0]); - b43_radio_write16(dev, 0x0052, backup[1]); - b43_radio_write16(dev, 0x0043, backup[2]); - b43_write16(dev, 0x03E2, backup[7]); - b43_write16(dev, 0x03E6, backup[8]); - b43_write16(dev, B43_MMIO_CHANNEL_EXT, backup[9]); - b43_phy_write(dev, 0x0015, backup[3]); - b43_phy_write(dev, 0x005A, backup[4]); - b43_phy_write(dev, 0x0059, backup[5]); - b43_phy_write(dev, 0x0058, backup[6]); - b43_synth_pu_workaround(dev, phy->channel); - b43_phy_set(dev, 0x0802, (0x0001 | 0x0002)); - b43_set_original_gains(dev); - b43_phy_set(dev, B43_PHY_G_CRS, 0x8000); - if (phy->rev >= 3) { - b43_phy_write(dev, 0x0801, backup[14]); - b43_phy_write(dev, 0x0060, backup[15]); - b43_phy_write(dev, 0x0014, backup[16]); - b43_phy_write(dev, 0x0478, backup[17]); - } - b43_nrssi_mem_update(dev); - b43_calc_nrssi_threshold(dev); -} - -static void b43_calc_nrssi_threshold(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - s32 a, b; - s16 tmp16; - u16 tmp_u16; - - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - - if (!phy->gmode || - !(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { - tmp16 = b43_nrssi_hw_read(dev, 0x20); - if (tmp16 >= 0x20) - tmp16 -= 0x40; - if (tmp16 < 3) { - b43_phy_maskset(dev, 0x048A, 0xF000, 0x09EB); - } else { - b43_phy_maskset(dev, 0x048A, 0xF000, 0x0AED); - } - } else { - if (gphy->interfmode == B43_INTERFMODE_NONWLAN) { - a = 0xE; - b = 0xA; - } else if (!gphy->aci_wlan_automatic && gphy->aci_enable) { - a = 0x13; - b = 0x12; - } else { - a = 0xE; - b = 0x11; - } - - a = a * (gphy->nrssi[1] - gphy->nrssi[0]); - a += (gphy->nrssi[0] << 6); - if (a < 32) - a += 31; - else - a += 32; - a = a >> 6; - a = clamp_val(a, -31, 31); - - b = b * (gphy->nrssi[1] - gphy->nrssi[0]); - b += (gphy->nrssi[0] << 6); - if (b < 32) - b += 31; - else - b += 32; - b = b >> 6; - b = clamp_val(b, -31, 31); - - tmp_u16 = b43_phy_read(dev, 0x048A) & 0xF000; - tmp_u16 |= ((u32) b & 0x0000003F); - tmp_u16 |= (((u32) a & 0x0000003F) << 6); - b43_phy_write(dev, 0x048A, tmp_u16); - } -} - -/* Stack implementation to save/restore values from the - * interference mitigation code. - * It is save to restore values in random order. - */ -static void _stack_save(u32 *_stackptr, size_t *stackidx, - u8 id, u16 offset, u16 value) -{ - u32 *stackptr = &(_stackptr[*stackidx]); - - B43_WARN_ON(offset & 0xF000); - B43_WARN_ON(id & 0xF0); - *stackptr = offset; - *stackptr |= ((u32) id) << 12; - *stackptr |= ((u32) value) << 16; - (*stackidx)++; - B43_WARN_ON(*stackidx >= B43_INTERFSTACK_SIZE); -} - -static u16 _stack_restore(u32 *stackptr, u8 id, u16 offset) -{ - size_t i; - - B43_WARN_ON(offset & 0xF000); - B43_WARN_ON(id & 0xF0); - for (i = 0; i < B43_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00000FFF) != offset) - continue; - if (((*stackptr & 0x0000F000) >> 12) != id) - continue; - return ((*stackptr & 0xFFFF0000) >> 16); - } - B43_WARN_ON(1); - - return 0; -} - -#define phy_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x1, (offset), \ - b43_phy_read(dev, (offset))); \ - } while (0) -#define phy_stackrestore(offset) \ - do { \ - b43_phy_write(dev, (offset), \ - _stack_restore(stack, 0x1, \ - (offset))); \ - } while (0) -#define radio_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x2, (offset), \ - b43_radio_read16(dev, (offset))); \ - } while (0) -#define radio_stackrestore(offset) \ - do { \ - b43_radio_write16(dev, (offset), \ - _stack_restore(stack, 0x2, \ - (offset))); \ - } while (0) -#define ofdmtab_stacksave(table, offset) \ - do { \ - _stack_save(stack, &stackidx, 0x3, (offset)|(table), \ - b43_ofdmtab_read16(dev, (table), (offset))); \ - } while (0) -#define ofdmtab_stackrestore(table, offset) \ - do { \ - b43_ofdmtab_write16(dev, (table), (offset), \ - _stack_restore(stack, 0x3, \ - (offset)|(table))); \ - } while (0) - -static void -b43_radio_interference_mitigation_enable(struct b43_wldev *dev, int mode) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 tmp, flipped; - size_t stackidx = 0; - u32 *stack = gphy->interfstack; - - switch (mode) { - case B43_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - b43_phy_set(dev, 0x042B, 0x0800); - b43_phy_mask(dev, B43_PHY_G_CRS, ~0x4000); - break; - } - radio_stacksave(0x0078); - tmp = (b43_radio_read16(dev, 0x0078) & 0x001E); - B43_WARN_ON(tmp > 15); - flipped = bitrev4(tmp); - if (flipped < 10 && flipped >= 8) - flipped = 7; - else if (flipped >= 10) - flipped -= 3; - flipped = (bitrev4(flipped) << 1) | 0x0020; - b43_radio_write16(dev, 0x0078, flipped); - - b43_calc_nrssi_threshold(dev); - - phy_stacksave(0x0406); - b43_phy_write(dev, 0x0406, 0x7E28); - - b43_phy_set(dev, 0x042B, 0x0800); - b43_phy_set(dev, B43_PHY_RADIO_BITFIELD, 0x1000); - - phy_stacksave(0x04A0); - b43_phy_maskset(dev, 0x04A0, 0xC0C0, 0x0008); - phy_stacksave(0x04A1); - b43_phy_maskset(dev, 0x04A1, 0xC0C0, 0x0605); - phy_stacksave(0x04A2); - b43_phy_maskset(dev, 0x04A2, 0xC0C0, 0x0204); - phy_stacksave(0x04A8); - b43_phy_maskset(dev, 0x04A8, 0xC0C0, 0x0803); - phy_stacksave(0x04AB); - b43_phy_maskset(dev, 0x04AB, 0xC0C0, 0x0605); - - phy_stacksave(0x04A7); - b43_phy_write(dev, 0x04A7, 0x0002); - phy_stacksave(0x04A3); - b43_phy_write(dev, 0x04A3, 0x287A); - phy_stacksave(0x04A9); - b43_phy_write(dev, 0x04A9, 0x2027); - phy_stacksave(0x0493); - b43_phy_write(dev, 0x0493, 0x32F5); - phy_stacksave(0x04AA); - b43_phy_write(dev, 0x04AA, 0x2027); - phy_stacksave(0x04AC); - b43_phy_write(dev, 0x04AC, 0x32F5); - break; - case B43_INTERFMODE_MANUALWLAN: - if (b43_phy_read(dev, 0x0033) & 0x0800) - break; - - gphy->aci_enable = 1; - - phy_stacksave(B43_PHY_RADIO_BITFIELD); - phy_stacksave(B43_PHY_G_CRS); - if (phy->rev < 2) { - phy_stacksave(0x0406); - } else { - phy_stacksave(0x04C0); - phy_stacksave(0x04C1); - } - phy_stacksave(0x0033); - phy_stacksave(0x04A7); - phy_stacksave(0x04A3); - phy_stacksave(0x04A9); - phy_stacksave(0x04AA); - phy_stacksave(0x04AC); - phy_stacksave(0x0493); - phy_stacksave(0x04A1); - phy_stacksave(0x04A0); - phy_stacksave(0x04A2); - phy_stacksave(0x048A); - phy_stacksave(0x04A8); - phy_stacksave(0x04AB); - if (phy->rev == 2) { - phy_stacksave(0x04AD); - phy_stacksave(0x04AE); - } else if (phy->rev >= 3) { - phy_stacksave(0x04AD); - phy_stacksave(0x0415); - phy_stacksave(0x0416); - phy_stacksave(0x0417); - ofdmtab_stacksave(0x1A00, 0x2); - ofdmtab_stacksave(0x1A00, 0x3); - } - phy_stacksave(0x042B); - phy_stacksave(0x048C); - - b43_phy_mask(dev, B43_PHY_RADIO_BITFIELD, ~0x1000); - b43_phy_maskset(dev, B43_PHY_G_CRS, 0xFFFC, 0x0002); - - b43_phy_write(dev, 0x0033, 0x0800); - b43_phy_write(dev, 0x04A3, 0x2027); - b43_phy_write(dev, 0x04A9, 0x1CA8); - b43_phy_write(dev, 0x0493, 0x287A); - b43_phy_write(dev, 0x04AA, 0x1CA8); - b43_phy_write(dev, 0x04AC, 0x287A); - - b43_phy_maskset(dev, 0x04A0, 0xFFC0, 0x001A); - b43_phy_write(dev, 0x04A7, 0x000D); - - if (phy->rev < 2) { - b43_phy_write(dev, 0x0406, 0xFF0D); - } else if (phy->rev == 2) { - b43_phy_write(dev, 0x04C0, 0xFFFF); - b43_phy_write(dev, 0x04C1, 0x00A9); - } else { - b43_phy_write(dev, 0x04C0, 0x00C1); - b43_phy_write(dev, 0x04C1, 0x0059); - } - - b43_phy_maskset(dev, 0x04A1, 0xC0FF, 0x1800); - b43_phy_maskset(dev, 0x04A1, 0xFFC0, 0x0015); - b43_phy_maskset(dev, 0x04A8, 0xCFFF, 0x1000); - b43_phy_maskset(dev, 0x04A8, 0xF0FF, 0x0A00); - b43_phy_maskset(dev, 0x04AB, 0xCFFF, 0x1000); - b43_phy_maskset(dev, 0x04AB, 0xF0FF, 0x0800); - b43_phy_maskset(dev, 0x04AB, 0xFFCF, 0x0010); - b43_phy_maskset(dev, 0x04AB, 0xFFF0, 0x0005); - b43_phy_maskset(dev, 0x04A8, 0xFFCF, 0x0010); - b43_phy_maskset(dev, 0x04A8, 0xFFF0, 0x0006); - b43_phy_maskset(dev, 0x04A2, 0xF0FF, 0x0800); - b43_phy_maskset(dev, 0x04A0, 0xF0FF, 0x0500); - b43_phy_maskset(dev, 0x04A2, 0xFFF0, 0x000B); - - if (phy->rev >= 3) { - b43_phy_mask(dev, 0x048A, (u16)~0x8000); - b43_phy_maskset(dev, 0x0415, 0x8000, 0x36D8); - b43_phy_maskset(dev, 0x0416, 0x8000, 0x36D8); - b43_phy_maskset(dev, 0x0417, 0xFE00, 0x016D); - } else { - b43_phy_set(dev, 0x048A, 0x1000); - b43_phy_maskset(dev, 0x048A, 0x9FFF, 0x2000); - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ACIW); - } - if (phy->rev >= 2) { - b43_phy_set(dev, 0x042B, 0x0800); - } - b43_phy_maskset(dev, 0x048C, 0xF0FF, 0x0200); - if (phy->rev == 2) { - b43_phy_maskset(dev, 0x04AE, 0xFF00, 0x007F); - b43_phy_maskset(dev, 0x04AD, 0x00FF, 0x1300); - } else if (phy->rev >= 6) { - b43_ofdmtab_write16(dev, 0x1A00, 0x3, 0x007F); - b43_ofdmtab_write16(dev, 0x1A00, 0x2, 0x007F); - b43_phy_mask(dev, 0x04AD, 0x00FF); - } - b43_calc_nrssi_slope(dev); - break; - default: - B43_WARN_ON(1); - } -} - -static void -b43_radio_interference_mitigation_disable(struct b43_wldev *dev, int mode) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u32 *stack = gphy->interfstack; - - switch (mode) { - case B43_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - b43_phy_mask(dev, 0x042B, ~0x0800); - b43_phy_set(dev, B43_PHY_G_CRS, 0x4000); - break; - } - radio_stackrestore(0x0078); - b43_calc_nrssi_threshold(dev); - phy_stackrestore(0x0406); - b43_phy_mask(dev, 0x042B, ~0x0800); - if (!dev->bad_frames_preempt) { - b43_phy_mask(dev, B43_PHY_RADIO_BITFIELD, ~(1 << 11)); - } - b43_phy_set(dev, B43_PHY_G_CRS, 0x4000); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A7); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - break; - case B43_INTERFMODE_MANUALWLAN: - if (!(b43_phy_read(dev, 0x0033) & 0x0800)) - break; - - gphy->aci_enable = 0; - - phy_stackrestore(B43_PHY_RADIO_BITFIELD); - phy_stackrestore(B43_PHY_G_CRS); - phy_stackrestore(0x0033); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A7); - if (phy->rev >= 2) { - phy_stackrestore(0x04C0); - phy_stackrestore(0x04C1); - } else - phy_stackrestore(0x0406); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A8); - if (phy->rev == 2) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x04AE); - } else if (phy->rev >= 3) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x0415); - phy_stackrestore(0x0416); - phy_stackrestore(0x0417); - ofdmtab_stackrestore(0x1A00, 0x2); - ofdmtab_stackrestore(0x1A00, 0x3); - } - phy_stackrestore(0x04A2); - phy_stackrestore(0x048A); - phy_stackrestore(0x042B); - phy_stackrestore(0x048C); - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ACIW); - b43_calc_nrssi_slope(dev); - break; - default: - B43_WARN_ON(1); - } -} - -#undef phy_stacksave -#undef phy_stackrestore -#undef radio_stacksave -#undef radio_stackrestore -#undef ofdmtab_stacksave -#undef ofdmtab_stackrestore - -static u16 b43_radio_core_calibration_value(struct b43_wldev *dev) -{ - u16 reg, index, ret; - - static const u8 rcc_table[] = { - 0x02, 0x03, 0x01, 0x0F, - 0x06, 0x07, 0x05, 0x0F, - 0x0A, 0x0B, 0x09, 0x0F, - 0x0E, 0x0F, 0x0D, 0x0F, - }; - - reg = b43_radio_read16(dev, 0x60); - index = (reg & 0x001E) >> 1; - ret = rcc_table[index] << 1; - ret |= (reg & 0x0001); - ret |= 0x0020; - - return ret; -} - -#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) -static u16 radio2050_rfover_val(struct b43_wldev *dev, - u16 phy_register, unsigned int lpd) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); - - if (!phy->gmode) - return 0; - - if (has_loopback_gain(phy)) { - int max_lb_gain = gphy->max_lb_gain; - u16 extlna; - u16 i; - - if (phy->radio_rev == 8) - max_lb_gain += 0x3E; - else - max_lb_gain += 0x26; - if (max_lb_gain >= 0x46) { - extlna = 0x3000; - max_lb_gain -= 0x46; - } else if (max_lb_gain >= 0x3A) { - extlna = 0x1000; - max_lb_gain -= 0x3A; - } else if (max_lb_gain >= 0x2E) { - extlna = 0x2000; - max_lb_gain -= 0x2E; - } else { - extlna = 0; - max_lb_gain -= 0x10; - } - - for (i = 0; i < 16; i++) { - max_lb_gain -= (i * 6); - if (max_lb_gain < 6) - break; - } - - if ((phy->rev < 7) || - !(sprom->boardflags_lo & B43_BFL_EXTLNA)) { - if (phy_register == B43_PHY_RFOVER) { - return 0x1B3; - } else if (phy_register == B43_PHY_RFOVERVAL) { - extlna |= (i << 8); - switch (lpd) { - case LPD(0, 1, 1): - return 0x0F92; - case LPD(0, 0, 1): - case LPD(1, 0, 1): - return (0x0092 | extlna); - case LPD(1, 0, 0): - return (0x0093 | extlna); - } - B43_WARN_ON(1); - } - B43_WARN_ON(1); - } else { - if (phy_register == B43_PHY_RFOVER) { - return 0x9B3; - } else if (phy_register == B43_PHY_RFOVERVAL) { - if (extlna) - extlna |= 0x8000; - extlna |= (i << 8); - switch (lpd) { - case LPD(0, 1, 1): - return 0x8F92; - case LPD(0, 0, 1): - return (0x8092 | extlna); - case LPD(1, 0, 1): - return (0x2092 | extlna); - case LPD(1, 0, 0): - return (0x2093 | extlna); - } - B43_WARN_ON(1); - } - B43_WARN_ON(1); - } - } else { - if ((phy->rev < 7) || - !(sprom->boardflags_lo & B43_BFL_EXTLNA)) { - if (phy_register == B43_PHY_RFOVER) { - return 0x1B3; - } else if (phy_register == B43_PHY_RFOVERVAL) { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0FB2; - case LPD(0, 0, 1): - return 0x00B2; - case LPD(1, 0, 1): - return 0x30B2; - case LPD(1, 0, 0): - return 0x30B3; - } - B43_WARN_ON(1); - } - B43_WARN_ON(1); - } else { - if (phy_register == B43_PHY_RFOVER) { - return 0x9B3; - } else if (phy_register == B43_PHY_RFOVERVAL) { - switch (lpd) { - case LPD(0, 1, 1): - return 0x8FB2; - case LPD(0, 0, 1): - return 0x80B2; - case LPD(1, 0, 1): - return 0x20B2; - case LPD(1, 0, 0): - return 0x20B3; - } - B43_WARN_ON(1); - } - B43_WARN_ON(1); - } - } - return 0; -} - -struct init2050_saved_values { - /* Core registers */ - u16 reg_3EC; - u16 reg_3E6; - u16 reg_3F4; - /* Radio registers */ - u16 radio_43; - u16 radio_51; - u16 radio_52; - /* PHY registers */ - u16 phy_pgactl; - u16 phy_cck_5A; - u16 phy_cck_59; - u16 phy_cck_58; - u16 phy_cck_30; - u16 phy_rfover; - u16 phy_rfoverval; - u16 phy_analogover; - u16 phy_analogoverval; - u16 phy_crs0; - u16 phy_classctl; - u16 phy_lo_mask; - u16 phy_lo_ctl; - u16 phy_syncctl; -}; - -static u16 b43_radio_init2050(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct init2050_saved_values sav; - u16 rcc; - u16 radio78; - u16 ret; - u16 i, j; - u32 tmp1 = 0, tmp2 = 0; - - memset(&sav, 0, sizeof(sav)); /* get rid of "may be used uninitialized..." */ - - sav.radio_43 = b43_radio_read16(dev, 0x43); - sav.radio_51 = b43_radio_read16(dev, 0x51); - sav.radio_52 = b43_radio_read16(dev, 0x52); - sav.phy_pgactl = b43_phy_read(dev, B43_PHY_PGACTL); - sav.phy_cck_5A = b43_phy_read(dev, B43_PHY_CCK(0x5A)); - sav.phy_cck_59 = b43_phy_read(dev, B43_PHY_CCK(0x59)); - sav.phy_cck_58 = b43_phy_read(dev, B43_PHY_CCK(0x58)); - - if (phy->type == B43_PHYTYPE_B) { - sav.phy_cck_30 = b43_phy_read(dev, B43_PHY_CCK(0x30)); - sav.reg_3EC = b43_read16(dev, 0x3EC); - - b43_phy_write(dev, B43_PHY_CCK(0x30), 0xFF); - b43_write16(dev, 0x3EC, 0x3F3F); - } else if (phy->gmode || phy->rev >= 2) { - sav.phy_rfover = b43_phy_read(dev, B43_PHY_RFOVER); - sav.phy_rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); - sav.phy_analogover = b43_phy_read(dev, B43_PHY_ANALOGOVER); - sav.phy_analogoverval = - b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); - sav.phy_crs0 = b43_phy_read(dev, B43_PHY_CRS0); - sav.phy_classctl = b43_phy_read(dev, B43_PHY_CLASSCTL); - - b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0003); - b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFC); - b43_phy_mask(dev, B43_PHY_CRS0, 0x7FFF); - b43_phy_mask(dev, B43_PHY_CLASSCTL, 0xFFFC); - if (has_loopback_gain(phy)) { - sav.phy_lo_mask = b43_phy_read(dev, B43_PHY_LO_MASK); - sav.phy_lo_ctl = b43_phy_read(dev, B43_PHY_LO_CTL); - - if (phy->rev >= 3) - b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020); - else - b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020); - b43_phy_write(dev, B43_PHY_LO_CTL, 0); - } - - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, - LPD(0, 1, 1))); - b43_phy_write(dev, B43_PHY_RFOVER, - radio2050_rfover_val(dev, B43_PHY_RFOVER, 0)); - } - b43_write16(dev, 0x3E2, b43_read16(dev, 0x3E2) | 0x8000); - - sav.phy_syncctl = b43_phy_read(dev, B43_PHY_SYNCCTL); - b43_phy_mask(dev, B43_PHY_SYNCCTL, 0xFF7F); - sav.reg_3E6 = b43_read16(dev, 0x3E6); - sav.reg_3F4 = b43_read16(dev, 0x3F4); - - if (phy->analog == 0) { - b43_write16(dev, 0x03E6, 0x0122); - } else { - if (phy->analog >= 2) { - b43_phy_maskset(dev, B43_PHY_CCK(0x03), 0xFFBF, 0x40); - } - b43_write16(dev, B43_MMIO_CHANNEL_EXT, - (b43_read16(dev, B43_MMIO_CHANNEL_EXT) | 0x2000)); - } - - rcc = b43_radio_core_calibration_value(dev); - - if (phy->type == B43_PHYTYPE_B) - b43_radio_write16(dev, 0x78, 0x26); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, - LPD(0, 1, 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xBFAF); - b43_phy_write(dev, B43_PHY_CCK(0x2B), 0x1403); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, B43_PHY_RFOVERVAL, - LPD(0, 0, 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xBFA0); - b43_radio_set(dev, 0x51, 0x0004); - if (phy->radio_rev == 8) { - b43_radio_write16(dev, 0x43, 0x1F); - } else { - b43_radio_write16(dev, 0x52, 0); - b43_radio_maskset(dev, 0x43, 0xFFF0, 0x0009); - } - b43_phy_write(dev, B43_PHY_CCK(0x58), 0); - - for (i = 0; i < 16; i++) { - b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0480); - b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); - b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); - udelay(10); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0); - udelay(10); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, 0))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0); - udelay(20); - tmp1 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE); - b43_phy_write(dev, B43_PHY_CCK(0x58), 0); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); - } - udelay(10); - - b43_phy_write(dev, B43_PHY_CCK(0x58), 0); - tmp1++; - tmp1 >>= 9; - - for (i = 0; i < 16; i++) { - radio78 = (bitrev4(i) << 1) | 0x0020; - b43_radio_write16(dev, 0x78, radio78); - udelay(10); - for (j = 0; j < 16; j++) { - b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0D80); - b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); - b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, - 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); - udelay(10); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, - 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xEFB0); - udelay(10); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, - 0))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xFFF0); - udelay(10); - tmp2 += b43_phy_read(dev, B43_PHY_LO_LEAKAGE); - b43_phy_write(dev, B43_PHY_CCK(0x58), 0); - if (phy->gmode || phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_RFOVERVAL, - radio2050_rfover_val(dev, - B43_PHY_RFOVERVAL, - LPD(1, 0, - 1))); - } - b43_phy_write(dev, B43_PHY_PGACTL, 0xAFB0); - } - tmp2++; - tmp2 >>= 8; - if (tmp1 < tmp2) - break; - } - - /* Restore the registers */ - b43_phy_write(dev, B43_PHY_PGACTL, sav.phy_pgactl); - b43_radio_write16(dev, 0x51, sav.radio_51); - b43_radio_write16(dev, 0x52, sav.radio_52); - b43_radio_write16(dev, 0x43, sav.radio_43); - b43_phy_write(dev, B43_PHY_CCK(0x5A), sav.phy_cck_5A); - b43_phy_write(dev, B43_PHY_CCK(0x59), sav.phy_cck_59); - b43_phy_write(dev, B43_PHY_CCK(0x58), sav.phy_cck_58); - b43_write16(dev, 0x3E6, sav.reg_3E6); - if (phy->analog != 0) - b43_write16(dev, 0x3F4, sav.reg_3F4); - b43_phy_write(dev, B43_PHY_SYNCCTL, sav.phy_syncctl); - b43_synth_pu_workaround(dev, phy->channel); - if (phy->type == B43_PHYTYPE_B) { - b43_phy_write(dev, B43_PHY_CCK(0x30), sav.phy_cck_30); - b43_write16(dev, 0x3EC, sav.reg_3EC); - } else if (phy->gmode) { - b43_write16(dev, B43_MMIO_PHY_RADIO, - b43_read16(dev, B43_MMIO_PHY_RADIO) - & 0x7FFF); - b43_phy_write(dev, B43_PHY_RFOVER, sav.phy_rfover); - b43_phy_write(dev, B43_PHY_RFOVERVAL, sav.phy_rfoverval); - b43_phy_write(dev, B43_PHY_ANALOGOVER, sav.phy_analogover); - b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, - sav.phy_analogoverval); - b43_phy_write(dev, B43_PHY_CRS0, sav.phy_crs0); - b43_phy_write(dev, B43_PHY_CLASSCTL, sav.phy_classctl); - if (has_loopback_gain(phy)) { - b43_phy_write(dev, B43_PHY_LO_MASK, sav.phy_lo_mask); - b43_phy_write(dev, B43_PHY_LO_CTL, sav.phy_lo_ctl); - } - } - if (i > 15) - ret = radio78; - else - ret = rcc; - - return ret; -} - -static void b43_phy_initb5(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 offset, value; - u8 old_channel; - - if (phy->analog == 1) { - b43_radio_set(dev, 0x007A, 0x0050); - } - if ((bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM) && - (bus->boardinfo.type != SSB_BOARD_BU4306)) { - value = 0x2120; - for (offset = 0x00A8; offset < 0x00C7; offset++) { - b43_phy_write(dev, offset, value); - value += 0x202; - } - } - b43_phy_maskset(dev, 0x0035, 0xF0FF, 0x0700); - if (phy->radio_ver == 0x2050) - b43_phy_write(dev, 0x0038, 0x0667); - - if (phy->gmode || phy->rev >= 2) { - if (phy->radio_ver == 0x2050) { - b43_radio_set(dev, 0x007A, 0x0020); - b43_radio_set(dev, 0x0051, 0x0004); - } - b43_write16(dev, B43_MMIO_PHY_RADIO, 0x0000); - - b43_phy_set(dev, 0x0802, 0x0100); - b43_phy_set(dev, 0x042B, 0x2000); - - b43_phy_write(dev, 0x001C, 0x186A); - - b43_phy_maskset(dev, 0x0013, 0x00FF, 0x1900); - b43_phy_maskset(dev, 0x0035, 0xFFC0, 0x0064); - b43_phy_maskset(dev, 0x005D, 0xFF80, 0x000A); - } - - if (dev->bad_frames_preempt) { - b43_phy_set(dev, B43_PHY_RADIO_BITFIELD, (1 << 11)); - } - - if (phy->analog == 1) { - b43_phy_write(dev, 0x0026, 0xCE00); - b43_phy_write(dev, 0x0021, 0x3763); - b43_phy_write(dev, 0x0022, 0x1BC3); - b43_phy_write(dev, 0x0023, 0x06F9); - b43_phy_write(dev, 0x0024, 0x037E); - } else - b43_phy_write(dev, 0x0026, 0xCC00); - b43_phy_write(dev, 0x0030, 0x00C6); - b43_write16(dev, 0x03EC, 0x3F22); - - if (phy->analog == 1) - b43_phy_write(dev, 0x0020, 0x3E1C); - else - b43_phy_write(dev, 0x0020, 0x301C); - - if (phy->analog == 0) - b43_write16(dev, 0x03E4, 0x3000); - - old_channel = phy->channel; - /* Force to channel 7, even if not supported. */ - b43_gphy_channel_switch(dev, 7, 0); - - if (phy->radio_ver != 0x2050) { - b43_radio_write16(dev, 0x0075, 0x0080); - b43_radio_write16(dev, 0x0079, 0x0081); - } - - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x0050, 0x0023); - - if (phy->radio_ver == 0x2050) { - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x005A, 0x0070); - } - - b43_radio_write16(dev, 0x005B, 0x007B); - b43_radio_write16(dev, 0x005C, 0x00B0); - - b43_radio_set(dev, 0x007A, 0x0007); - - b43_gphy_channel_switch(dev, old_channel, 0); - - b43_phy_write(dev, 0x0014, 0x0080); - b43_phy_write(dev, 0x0032, 0x00CA); - b43_phy_write(dev, 0x002A, 0x88A3); - - b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control); - - if (phy->radio_ver == 0x2050) - b43_radio_write16(dev, 0x005D, 0x000D); - - b43_write16(dev, 0x03E4, (b43_read16(dev, 0x03E4) & 0xFFC0) | 0x0004); -} - -static void b43_phy_initb6(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 offset, val; - u8 old_channel; - - b43_phy_write(dev, 0x003E, 0x817A); - b43_radio_write16(dev, 0x007A, - (b43_radio_read16(dev, 0x007A) | 0x0058)); - if (phy->radio_rev == 4 || phy->radio_rev == 5) { - b43_radio_write16(dev, 0x51, 0x37); - b43_radio_write16(dev, 0x52, 0x70); - b43_radio_write16(dev, 0x53, 0xB3); - b43_radio_write16(dev, 0x54, 0x9B); - b43_radio_write16(dev, 0x5A, 0x88); - b43_radio_write16(dev, 0x5B, 0x88); - b43_radio_write16(dev, 0x5D, 0x88); - b43_radio_write16(dev, 0x5E, 0x88); - b43_radio_write16(dev, 0x7D, 0x88); - b43_hf_write(dev, b43_hf_read(dev) - | B43_HF_TSSIRPSMW); - } - B43_WARN_ON(phy->radio_rev == 6 || phy->radio_rev == 7); /* We had code for these revs here... */ - if (phy->radio_rev == 8) { - b43_radio_write16(dev, 0x51, 0); - b43_radio_write16(dev, 0x52, 0x40); - b43_radio_write16(dev, 0x53, 0xB7); - b43_radio_write16(dev, 0x54, 0x98); - b43_radio_write16(dev, 0x5A, 0x88); - b43_radio_write16(dev, 0x5B, 0x6B); - b43_radio_write16(dev, 0x5C, 0x0F); - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_ALTIQ) { - b43_radio_write16(dev, 0x5D, 0xFA); - b43_radio_write16(dev, 0x5E, 0xD8); - } else { - b43_radio_write16(dev, 0x5D, 0xF5); - b43_radio_write16(dev, 0x5E, 0xB8); - } - b43_radio_write16(dev, 0x0073, 0x0003); - b43_radio_write16(dev, 0x007D, 0x00A8); - b43_radio_write16(dev, 0x007C, 0x0001); - b43_radio_write16(dev, 0x007E, 0x0008); - } - val = 0x1E1F; - for (offset = 0x0088; offset < 0x0098; offset++) { - b43_phy_write(dev, offset, val); - val -= 0x0202; - } - val = 0x3E3F; - for (offset = 0x0098; offset < 0x00A8; offset++) { - b43_phy_write(dev, offset, val); - val -= 0x0202; - } - val = 0x2120; - for (offset = 0x00A8; offset < 0x00C8; offset++) { - b43_phy_write(dev, offset, (val & 0x3F3F)); - val += 0x0202; - } - if (phy->type == B43_PHYTYPE_G) { - b43_radio_set(dev, 0x007A, 0x0020); - b43_radio_set(dev, 0x0051, 0x0004); - b43_phy_set(dev, 0x0802, 0x0100); - b43_phy_set(dev, 0x042B, 0x2000); - b43_phy_write(dev, 0x5B, 0); - b43_phy_write(dev, 0x5C, 0); - } - - old_channel = phy->channel; - if (old_channel >= 8) - b43_gphy_channel_switch(dev, 1, 0); - else - b43_gphy_channel_switch(dev, 13, 0); - - b43_radio_write16(dev, 0x0050, 0x0020); - b43_radio_write16(dev, 0x0050, 0x0023); - udelay(40); - if (phy->radio_rev < 6 || phy->radio_rev == 8) { - b43_radio_write16(dev, 0x7C, (b43_radio_read16(dev, 0x7C) - | 0x0002)); - b43_radio_write16(dev, 0x50, 0x20); - } - if (phy->radio_rev <= 2) { - b43_radio_write16(dev, 0x7C, 0x20); - b43_radio_write16(dev, 0x5A, 0x70); - b43_radio_write16(dev, 0x5B, 0x7B); - b43_radio_write16(dev, 0x5C, 0xB0); - } - b43_radio_maskset(dev, 0x007A, 0x00F8, 0x0007); - - b43_gphy_channel_switch(dev, old_channel, 0); - - b43_phy_write(dev, 0x0014, 0x0200); - if (phy->radio_rev >= 6) - b43_phy_write(dev, 0x2A, 0x88C2); - else - b43_phy_write(dev, 0x2A, 0x8AC0); - b43_phy_write(dev, 0x0038, 0x0668); - b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, gphy->tx_control); - if (phy->radio_rev <= 5) { - b43_phy_maskset(dev, 0x5D, 0xFF80, 0x0003); - } - if (phy->radio_rev <= 2) - b43_radio_write16(dev, 0x005D, 0x000D); - - if (phy->analog == 4) { - b43_write16(dev, 0x3E4, 9); - b43_phy_mask(dev, 0x61, 0x0FFF); - } else { - b43_phy_maskset(dev, 0x0002, 0xFFC0, 0x0004); - } - if (phy->type == B43_PHYTYPE_B) - B43_WARN_ON(1); - else if (phy->type == B43_PHYTYPE_G) - b43_write16(dev, 0x03E6, 0x0); -} - -static void b43_calc_loopback_gain(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 backup_phy[16] = { 0 }; - u16 backup_radio[3]; - u16 backup_bband; - u16 i, j, loop_i_max; - u16 trsw_rx; - u16 loop1_outer_done, loop1_inner_done; - - backup_phy[0] = b43_phy_read(dev, B43_PHY_CRS0); - backup_phy[1] = b43_phy_read(dev, B43_PHY_CCKBBANDCFG); - backup_phy[2] = b43_phy_read(dev, B43_PHY_RFOVER); - backup_phy[3] = b43_phy_read(dev, B43_PHY_RFOVERVAL); - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - backup_phy[4] = b43_phy_read(dev, B43_PHY_ANALOGOVER); - backup_phy[5] = b43_phy_read(dev, B43_PHY_ANALOGOVERVAL); - } - backup_phy[6] = b43_phy_read(dev, B43_PHY_CCK(0x5A)); - backup_phy[7] = b43_phy_read(dev, B43_PHY_CCK(0x59)); - backup_phy[8] = b43_phy_read(dev, B43_PHY_CCK(0x58)); - backup_phy[9] = b43_phy_read(dev, B43_PHY_CCK(0x0A)); - backup_phy[10] = b43_phy_read(dev, B43_PHY_CCK(0x03)); - backup_phy[11] = b43_phy_read(dev, B43_PHY_LO_MASK); - backup_phy[12] = b43_phy_read(dev, B43_PHY_LO_CTL); - backup_phy[13] = b43_phy_read(dev, B43_PHY_CCK(0x2B)); - backup_phy[14] = b43_phy_read(dev, B43_PHY_PGACTL); - backup_phy[15] = b43_phy_read(dev, B43_PHY_LO_LEAKAGE); - backup_bband = gphy->bbatt.att; - backup_radio[0] = b43_radio_read16(dev, 0x52); - backup_radio[1] = b43_radio_read16(dev, 0x43); - backup_radio[2] = b43_radio_read16(dev, 0x7A); - - b43_phy_mask(dev, B43_PHY_CRS0, 0x3FFF); - b43_phy_set(dev, B43_PHY_CCKBBANDCFG, 0x8000); - b43_phy_set(dev, B43_PHY_RFOVER, 0x0002); - b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xFFFD); - b43_phy_set(dev, B43_PHY_RFOVER, 0x0001); - b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xFFFE); - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0001); - b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFE); - b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0002); - b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFD); - } - b43_phy_set(dev, B43_PHY_RFOVER, 0x000C); - b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x000C); - b43_phy_set(dev, B43_PHY_RFOVER, 0x0030); - b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xFFCF, 0x10); - - b43_phy_write(dev, B43_PHY_CCK(0x5A), 0x0780); - b43_phy_write(dev, B43_PHY_CCK(0x59), 0xC810); - b43_phy_write(dev, B43_PHY_CCK(0x58), 0x000D); - - b43_phy_set(dev, B43_PHY_CCK(0x0A), 0x2000); - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - b43_phy_set(dev, B43_PHY_ANALOGOVER, 0x0004); - b43_phy_mask(dev, B43_PHY_ANALOGOVERVAL, 0xFFFB); - } - b43_phy_maskset(dev, B43_PHY_CCK(0x03), 0xFF9F, 0x40); - - if (phy->radio_rev == 8) { - b43_radio_write16(dev, 0x43, 0x000F); - } else { - b43_radio_write16(dev, 0x52, 0); - b43_radio_maskset(dev, 0x43, 0xFFF0, 0x9); - } - b43_gphy_set_baseband_attenuation(dev, 11); - - if (phy->rev >= 3) - b43_phy_write(dev, B43_PHY_LO_MASK, 0xC020); - else - b43_phy_write(dev, B43_PHY_LO_MASK, 0x8020); - b43_phy_write(dev, B43_PHY_LO_CTL, 0); - - b43_phy_maskset(dev, B43_PHY_CCK(0x2B), 0xFFC0, 0x01); - b43_phy_maskset(dev, B43_PHY_CCK(0x2B), 0xC0FF, 0x800); - - b43_phy_set(dev, B43_PHY_RFOVER, 0x0100); - b43_phy_mask(dev, B43_PHY_RFOVERVAL, 0xCFFF); - - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_EXTLNA) { - if (phy->rev >= 7) { - b43_phy_set(dev, B43_PHY_RFOVER, 0x0800); - b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x8000); - } - } - b43_radio_mask(dev, 0x7A, 0x00F7); - - j = 0; - loop_i_max = (phy->radio_rev == 8) ? 15 : 9; - for (i = 0; i < loop_i_max; i++) { - for (j = 0; j < 16; j++) { - b43_radio_write16(dev, 0x43, i); - b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xF0FF, (j << 8)); - b43_phy_maskset(dev, B43_PHY_PGACTL, 0x0FFF, 0xA000); - b43_phy_set(dev, B43_PHY_PGACTL, 0xF000); - udelay(20); - if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC) - goto exit_loop1; - } - } - exit_loop1: - loop1_outer_done = i; - loop1_inner_done = j; - if (j >= 8) { - b43_phy_set(dev, B43_PHY_RFOVERVAL, 0x30); - trsw_rx = 0x1B; - for (j = j - 8; j < 16; j++) { - b43_phy_maskset(dev, B43_PHY_RFOVERVAL, 0xF0FF, (j << 8)); - b43_phy_maskset(dev, B43_PHY_PGACTL, 0x0FFF, 0xA000); - b43_phy_set(dev, B43_PHY_PGACTL, 0xF000); - udelay(20); - trsw_rx -= 3; - if (b43_phy_read(dev, B43_PHY_LO_LEAKAGE) >= 0xDFC) - goto exit_loop2; - } - } else - trsw_rx = 0x18; - exit_loop2: - - if (phy->rev != 1) { /* Not in specs, but needed to prevent PPC machine check */ - b43_phy_write(dev, B43_PHY_ANALOGOVER, backup_phy[4]); - b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, backup_phy[5]); - } - b43_phy_write(dev, B43_PHY_CCK(0x5A), backup_phy[6]); - b43_phy_write(dev, B43_PHY_CCK(0x59), backup_phy[7]); - b43_phy_write(dev, B43_PHY_CCK(0x58), backup_phy[8]); - b43_phy_write(dev, B43_PHY_CCK(0x0A), backup_phy[9]); - b43_phy_write(dev, B43_PHY_CCK(0x03), backup_phy[10]); - b43_phy_write(dev, B43_PHY_LO_MASK, backup_phy[11]); - b43_phy_write(dev, B43_PHY_LO_CTL, backup_phy[12]); - b43_phy_write(dev, B43_PHY_CCK(0x2B), backup_phy[13]); - b43_phy_write(dev, B43_PHY_PGACTL, backup_phy[14]); - - b43_gphy_set_baseband_attenuation(dev, backup_bband); - - b43_radio_write16(dev, 0x52, backup_radio[0]); - b43_radio_write16(dev, 0x43, backup_radio[1]); - b43_radio_write16(dev, 0x7A, backup_radio[2]); - - b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2] | 0x0003); - udelay(10); - b43_phy_write(dev, B43_PHY_RFOVER, backup_phy[2]); - b43_phy_write(dev, B43_PHY_RFOVERVAL, backup_phy[3]); - b43_phy_write(dev, B43_PHY_CRS0, backup_phy[0]); - b43_phy_write(dev, B43_PHY_CCKBBANDCFG, backup_phy[1]); - - gphy->max_lb_gain = - ((loop1_inner_done * 6) - (loop1_outer_done * 4)) - 11; - gphy->trsw_rx_gain = trsw_rx * 2; -} - -static void b43_hardware_pctl_early_init(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (!b43_has_hardware_pctl(dev)) { - b43_phy_write(dev, 0x047A, 0xC111); - return; - } - - b43_phy_mask(dev, 0x0036, 0xFEFF); - b43_phy_write(dev, 0x002F, 0x0202); - b43_phy_set(dev, 0x047C, 0x0002); - b43_phy_set(dev, 0x047A, 0xF000); - if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) { - b43_phy_maskset(dev, 0x047A, 0xFF0F, 0x0010); - b43_phy_set(dev, 0x005D, 0x8000); - b43_phy_maskset(dev, 0x004E, 0xFFC0, 0x0010); - b43_phy_write(dev, 0x002E, 0xC07F); - b43_phy_set(dev, 0x0036, 0x0400); - } else { - b43_phy_set(dev, 0x0036, 0x0200); - b43_phy_set(dev, 0x0036, 0x0400); - b43_phy_mask(dev, 0x005D, 0x7FFF); - b43_phy_mask(dev, 0x004F, 0xFFFE); - b43_phy_maskset(dev, 0x004E, 0xFFC0, 0x0010); - b43_phy_write(dev, 0x002E, 0xC07F); - b43_phy_maskset(dev, 0x047A, 0xFF0F, 0x0010); - } -} - -/* Hardware power control for G-PHY */ -static void b43_hardware_pctl_init_gphy(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - - if (!b43_has_hardware_pctl(dev)) { - /* No hardware power control */ - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_HWPCTL); - return; - } - - b43_phy_maskset(dev, 0x0036, 0xFFC0, (gphy->tgt_idle_tssi - gphy->cur_idle_tssi)); - b43_phy_maskset(dev, 0x0478, 0xFF00, (gphy->tgt_idle_tssi - gphy->cur_idle_tssi)); - b43_gphy_tssi_power_lt_init(dev); - b43_gphy_gain_lt_init(dev); - b43_phy_mask(dev, 0x0060, 0xFFBF); - b43_phy_write(dev, 0x0014, 0x0000); - - B43_WARN_ON(phy->rev < 6); - b43_phy_set(dev, 0x0478, 0x0800); - b43_phy_mask(dev, 0x0478, 0xFEFF); - b43_phy_mask(dev, 0x0801, 0xFFBF); - - b43_gphy_dc_lt_init(dev, 1); - - /* Enable hardware pctl in firmware. */ - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_HWPCTL); -} - -/* Intialize B/G PHY power control */ -static void b43_phy_init_pctl(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_rfatt old_rfatt; - struct b43_bbatt old_bbatt; - u8 old_tx_control = 0; - - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - - if ((bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM) && - (bus->boardinfo.type == SSB_BOARD_BU4306)) - return; - - b43_phy_write(dev, 0x0028, 0x8018); - - /* This does something with the Analog... */ - b43_write16(dev, B43_MMIO_PHY0, b43_read16(dev, B43_MMIO_PHY0) - & 0xFFDF); - - if (!phy->gmode) - return; - b43_hardware_pctl_early_init(dev); - if (gphy->cur_idle_tssi == 0) { - if (phy->radio_ver == 0x2050 && phy->analog == 0) { - b43_radio_maskset(dev, 0x0076, 0x00F7, 0x0084); - } else { - struct b43_rfatt rfatt; - struct b43_bbatt bbatt; - - memcpy(&old_rfatt, &gphy->rfatt, sizeof(old_rfatt)); - memcpy(&old_bbatt, &gphy->bbatt, sizeof(old_bbatt)); - old_tx_control = gphy->tx_control; - - bbatt.att = 11; - if (phy->radio_rev == 8) { - rfatt.att = 15; - rfatt.with_padmix = 1; - } else { - rfatt.att = 9; - rfatt.with_padmix = 0; - } - b43_set_txpower_g(dev, &bbatt, &rfatt, 0); - } - b43_dummy_transmission(dev, false, true); - gphy->cur_idle_tssi = b43_phy_read(dev, B43_PHY_ITSSI); - if (B43_DEBUG) { - /* Current-Idle-TSSI sanity check. */ - if (abs(gphy->cur_idle_tssi - gphy->tgt_idle_tssi) >= 20) { - b43dbg(dev->wl, - "!WARNING! Idle-TSSI phy->cur_idle_tssi " - "measuring failed. (cur=%d, tgt=%d). Disabling TX power " - "adjustment.\n", gphy->cur_idle_tssi, - gphy->tgt_idle_tssi); - gphy->cur_idle_tssi = 0; - } - } - if (phy->radio_ver == 0x2050 && phy->analog == 0) { - b43_radio_mask(dev, 0x0076, 0xFF7B); - } else { - b43_set_txpower_g(dev, &old_bbatt, - &old_rfatt, old_tx_control); - } - } - b43_hardware_pctl_init_gphy(dev); - b43_shm_clear_tssi(dev); -} - -static void b43_phy_initg(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u16 tmp; - - if (phy->rev == 1) - b43_phy_initb5(dev); - else - b43_phy_initb6(dev); - - if (phy->rev >= 2 || phy->gmode) - b43_phy_inita(dev); - - if (phy->rev >= 2) { - b43_phy_write(dev, B43_PHY_ANALOGOVER, 0); - b43_phy_write(dev, B43_PHY_ANALOGOVERVAL, 0); - } - if (phy->rev == 2) { - b43_phy_write(dev, B43_PHY_RFOVER, 0); - b43_phy_write(dev, B43_PHY_PGACTL, 0xC0); - } - if (phy->rev > 5) { - b43_phy_write(dev, B43_PHY_RFOVER, 0x400); - b43_phy_write(dev, B43_PHY_PGACTL, 0xC0); - } - if (phy->gmode || phy->rev >= 2) { - tmp = b43_phy_read(dev, B43_PHY_VERSION_OFDM); - tmp &= B43_PHYVER_VERSION; - if (tmp == 3 || tmp == 5) { - b43_phy_write(dev, B43_PHY_OFDM(0xC2), 0x1816); - b43_phy_write(dev, B43_PHY_OFDM(0xC3), 0x8006); - } - if (tmp == 5) { - b43_phy_maskset(dev, B43_PHY_OFDM(0xCC), 0x00FF, 0x1F00); - } - } - if ((phy->rev <= 2 && phy->gmode) || phy->rev >= 2) - b43_phy_write(dev, B43_PHY_OFDM(0x7E), 0x78); - if (phy->radio_rev == 8) { - b43_phy_set(dev, B43_PHY_EXTG(0x01), 0x80); - b43_phy_set(dev, B43_PHY_OFDM(0x3E), 0x4); - } - if (has_loopback_gain(phy)) - b43_calc_loopback_gain(dev); - - if (phy->radio_rev != 8) { - if (gphy->initval == 0xFFFF) - gphy->initval = b43_radio_init2050(dev); - else - b43_radio_write16(dev, 0x0078, gphy->initval); - } - b43_lo_g_init(dev); - if (has_tx_magnification(phy)) { - b43_radio_write16(dev, 0x52, - (b43_radio_read16(dev, 0x52) & 0xFF00) - | gphy->lo_control->tx_bias | gphy-> - lo_control->tx_magn); - } else { - b43_radio_maskset(dev, 0x52, 0xFFF0, gphy->lo_control->tx_bias); - } - if (phy->rev >= 6) { - b43_phy_maskset(dev, B43_PHY_CCK(0x36), 0x0FFF, (gphy->lo_control->tx_bias << 12)); - } - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x8075); - else - b43_phy_write(dev, B43_PHY_CCK(0x2E), 0x807F); - if (phy->rev < 2) - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x101); - else - b43_phy_write(dev, B43_PHY_CCK(0x2F), 0x202); - if (phy->gmode || phy->rev >= 2) { - b43_lo_g_adjust(dev); - b43_phy_write(dev, B43_PHY_LO_MASK, 0x8078); - } - - if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) { - /* The specs state to update the NRSSI LT with - * the value 0x7FFFFFFF here. I think that is some weird - * compiler optimization in the original driver. - * Essentially, what we do here is resetting all NRSSI LT - * entries to -32 (see the clamp_val() in nrssi_hw_update()) - */ - b43_nrssi_hw_update(dev, 0xFFFF); //FIXME? - b43_calc_nrssi_threshold(dev); - } else if (phy->gmode || phy->rev >= 2) { - if (gphy->nrssi[0] == -1000) { - B43_WARN_ON(gphy->nrssi[1] != -1000); - b43_calc_nrssi_slope(dev); - } else - b43_calc_nrssi_threshold(dev); - } - if (phy->radio_rev == 8) - b43_phy_write(dev, B43_PHY_EXTG(0x05), 0x3230); - b43_phy_init_pctl(dev); - /* FIXME: The spec says in the following if, the 0 should be replaced - 'if OFDM may not be used in the current locale' - but OFDM is legal everywhere */ - if ((dev->dev->bus->chip_id == 0x4306 - && dev->dev->bus->chip_package == 2) || 0) { - b43_phy_mask(dev, B43_PHY_CRS0, 0xBFFF); - b43_phy_mask(dev, B43_PHY_OFDM(0xC3), 0x7FFF); - } -} - -void b43_gphy_channel_switch(struct b43_wldev *dev, - unsigned int channel, - bool synthetic_pu_workaround) -{ - if (synthetic_pu_workaround) - b43_synth_pu_workaround(dev, channel); - - b43_write16(dev, B43_MMIO_CHANNEL, channel2freq_bg(channel)); - - if (channel == 14) { - if (dev->dev->bus->sprom.country_code == - SSB_SPROM1CCODE_JAPAN) - b43_hf_write(dev, - b43_hf_read(dev) & ~B43_HF_ACPR); - else - b43_hf_write(dev, - b43_hf_read(dev) | B43_HF_ACPR); - b43_write16(dev, B43_MMIO_CHANNEL_EXT, - b43_read16(dev, B43_MMIO_CHANNEL_EXT) - | (1 << 11)); - } else { - b43_write16(dev, B43_MMIO_CHANNEL_EXT, - b43_read16(dev, B43_MMIO_CHANNEL_EXT) - & 0xF7BF); - } -} - -static void default_baseband_attenuation(struct b43_wldev *dev, - struct b43_bbatt *bb) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) - bb->att = 0; - else - bb->att = 2; -} - -static void default_radio_attenuation(struct b43_wldev *dev, - struct b43_rfatt *rf) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy *phy = &dev->phy; - - rf->with_padmix = 0; - - if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && - bus->boardinfo.type == SSB_BOARD_BCM4309G) { - if (bus->boardinfo.rev < 0x43) { - rf->att = 2; - return; - } else if (bus->boardinfo.rev < 0x51) { - rf->att = 3; - return; - } - } - - if (phy->type == B43_PHYTYPE_A) { - rf->att = 0x60; - return; - } - - switch (phy->radio_ver) { - case 0x2053: - switch (phy->radio_rev) { - case 1: - rf->att = 6; - return; - } - break; - case 0x2050: - switch (phy->radio_rev) { - case 0: - rf->att = 5; - return; - case 1: - if (phy->type == B43_PHYTYPE_G) { - if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM - && bus->boardinfo.type == SSB_BOARD_BCM4309G - && bus->boardinfo.rev >= 30) - rf->att = 3; - else if (bus->boardinfo.vendor == - SSB_BOARDVENDOR_BCM - && bus->boardinfo.type == - SSB_BOARD_BU4306) - rf->att = 3; - else - rf->att = 1; - } else { - if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM - && bus->boardinfo.type == SSB_BOARD_BCM4309G - && bus->boardinfo.rev >= 30) - rf->att = 7; - else - rf->att = 6; - } - return; - case 2: - if (phy->type == B43_PHYTYPE_G) { - if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM - && bus->boardinfo.type == SSB_BOARD_BCM4309G - && bus->boardinfo.rev >= 30) - rf->att = 3; - else if (bus->boardinfo.vendor == - SSB_BOARDVENDOR_BCM - && bus->boardinfo.type == - SSB_BOARD_BU4306) - rf->att = 5; - else if (bus->chip_id == 0x4320) - rf->att = 4; - else - rf->att = 3; - } else - rf->att = 6; - return; - case 3: - rf->att = 5; - return; - case 4: - case 5: - rf->att = 1; - return; - case 6: - case 7: - rf->att = 5; - return; - case 8: - rf->att = 0xA; - rf->with_padmix = 1; - return; - case 9: - default: - rf->att = 5; - return; - } - } - rf->att = 5; -} - -static u16 default_tx_control(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->radio_ver != 0x2050) - return 0; - if (phy->radio_rev == 1) - return B43_TXCTL_PA2DB | B43_TXCTL_TXMIX; - if (phy->radio_rev < 6) - return B43_TXCTL_PA2DB; - if (phy->radio_rev == 8) - return B43_TXCTL_TXMIX; - return 0; -} - -static u8 b43_gphy_aci_detect(struct b43_wldev *dev, u8 channel) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - u8 ret = 0; - u16 saved, rssi, temp; - int i, j = 0; - - saved = b43_phy_read(dev, 0x0403); - b43_switch_channel(dev, channel); - b43_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5); - if (gphy->aci_hw_rssi) - rssi = b43_phy_read(dev, 0x048A) & 0x3F; - else - rssi = saved & 0x3F; - /* clamp temp to signed 5bit */ - if (rssi > 32) - rssi -= 64; - for (i = 0; i < 100; i++) { - temp = (b43_phy_read(dev, 0x047F) >> 8) & 0x3F; - if (temp > 32) - temp -= 64; - if (temp < rssi) - j++; - if (j >= 20) - ret = 1; - } - b43_phy_write(dev, 0x0403, saved); - - return ret; -} - -static u8 b43_gphy_aci_scan(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u8 ret[13]; - unsigned int channel = phy->channel; - unsigned int i, j, start, end; - - if (!((phy->type == B43_PHYTYPE_G) && (phy->rev > 0))) - return 0; - - b43_phy_lock(dev); - b43_radio_lock(dev); - b43_phy_mask(dev, 0x0802, 0xFFFC); - b43_phy_mask(dev, B43_PHY_G_CRS, 0x7FFF); - b43_set_all_gains(dev, 3, 8, 1); - - start = (channel - 5 > 0) ? channel - 5 : 1; - end = (channel + 5 < 14) ? channel + 5 : 13; - - for (i = start; i <= end; i++) { - if (abs(channel - i) > 2) - ret[i - 1] = b43_gphy_aci_detect(dev, i); - } - b43_switch_channel(dev, channel); - b43_phy_maskset(dev, 0x0802, 0xFFFC, 0x0003); - b43_phy_mask(dev, 0x0403, 0xFFF8); - b43_phy_set(dev, B43_PHY_G_CRS, 0x8000); - b43_set_original_gains(dev); - for (i = 0; i < 13; i++) { - if (!ret[i]) - continue; - end = (i + 5 < 13) ? i + 5 : 13; - for (j = i; j < end; j++) - ret[j] = 1; - } - b43_radio_unlock(dev); - b43_phy_unlock(dev); - - return ret[channel - 1]; -} - -static s32 b43_tssi2dbm_ad(s32 num, s32 den) -{ - if (num < 0) - return num / den; - else - return (num + den / 2) / den; -} - -static s8 b43_tssi2dbm_entry(s8 entry[], u8 index, - s16 pab0, s16 pab1, s16 pab2) -{ - s32 m1, m2, f = 256, q, delta; - s8 i = 0; - - m1 = b43_tssi2dbm_ad(16 * pab0 + index * pab1, 32); - m2 = max(b43_tssi2dbm_ad(32768 + index * pab2, 256), 1); - do { - if (i > 15) - return -EINVAL; - q = b43_tssi2dbm_ad(f * 4096 - - b43_tssi2dbm_ad(m2 * f, 16) * f, 2048); - delta = abs(q - f); - f = q; - i++; - } while (delta >= 2); - entry[index] = clamp_val(b43_tssi2dbm_ad(m1 * f, 8192), -127, 128); - return 0; -} - -u8 *b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev, - s16 pab0, s16 pab1, s16 pab2) -{ - unsigned int i; - u8 *tab; - int err; - - tab = kmalloc(64, GFP_KERNEL); - if (!tab) { - b43err(dev->wl, "Could not allocate memory " - "for tssi2dbm table\n"); - return NULL; - } - for (i = 0; i < 64; i++) { - err = b43_tssi2dbm_entry(tab, i, pab0, pab1, pab2); - if (err) { - b43err(dev->wl, "Could not generate " - "tssi2dBm table\n"); - kfree(tab); - return NULL; - } - } - - return tab; -} - -/* Initialise the TSSI->dBm lookup table */ -static int b43_gphy_init_tssi2dbm_table(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - s16 pab0, pab1, pab2; - - pab0 = (s16) (dev->dev->bus->sprom.pa0b0); - pab1 = (s16) (dev->dev->bus->sprom.pa0b1); - pab2 = (s16) (dev->dev->bus->sprom.pa0b2); - - B43_WARN_ON((dev->dev->bus->chip_id == 0x4301) && - (phy->radio_ver != 0x2050)); /* Not supported anymore */ - - gphy->dyn_tssi_tbl = 0; - - if (pab0 != 0 && pab1 != 0 && pab2 != 0 && - pab0 != -1 && pab1 != -1 && pab2 != -1) { - /* The pabX values are set in SPROM. Use them. */ - if ((s8) dev->dev->bus->sprom.itssi_bg != 0 && - (s8) dev->dev->bus->sprom.itssi_bg != -1) { - gphy->tgt_idle_tssi = - (s8) (dev->dev->bus->sprom.itssi_bg); - } else - gphy->tgt_idle_tssi = 62; - gphy->tssi2dbm = b43_generate_dyn_tssi2dbm_tab(dev, pab0, - pab1, pab2); - if (!gphy->tssi2dbm) - return -ENOMEM; - gphy->dyn_tssi_tbl = 1; - } else { - /* pabX values not set in SPROM. */ - gphy->tgt_idle_tssi = 52; - gphy->tssi2dbm = b43_tssi2dbm_g_table; - } - - return 0; -} - -static int b43_gphy_op_allocate(struct b43_wldev *dev) -{ - struct b43_phy_g *gphy; - struct b43_txpower_lo_control *lo; - int err; - - gphy = kzalloc(sizeof(*gphy), GFP_KERNEL); - if (!gphy) { - err = -ENOMEM; - goto error; - } - dev->phy.g = gphy; - - lo = kzalloc(sizeof(*lo), GFP_KERNEL); - if (!lo) { - err = -ENOMEM; - goto err_free_gphy; - } - gphy->lo_control = lo; - - err = b43_gphy_init_tssi2dbm_table(dev); - if (err) - goto err_free_lo; - - return 0; - -err_free_lo: - kfree(lo); -err_free_gphy: - kfree(gphy); -error: - return err; -} - -static void b43_gphy_op_prepare_structs(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - const void *tssi2dbm; - int tgt_idle_tssi; - struct b43_txpower_lo_control *lo; - unsigned int i; - - /* tssi2dbm table is constant, so it is initialized at alloc time. - * Save a copy of the pointer. */ - tssi2dbm = gphy->tssi2dbm; - tgt_idle_tssi = gphy->tgt_idle_tssi; - /* Save the LO pointer. */ - lo = gphy->lo_control; - - /* Zero out the whole PHY structure. */ - memset(gphy, 0, sizeof(*gphy)); - - /* Restore pointers. */ - gphy->tssi2dbm = tssi2dbm; - gphy->tgt_idle_tssi = tgt_idle_tssi; - gphy->lo_control = lo; - - memset(gphy->minlowsig, 0xFF, sizeof(gphy->minlowsig)); - - /* NRSSI */ - for (i = 0; i < ARRAY_SIZE(gphy->nrssi); i++) - gphy->nrssi[i] = -1000; - for (i = 0; i < ARRAY_SIZE(gphy->nrssi_lt); i++) - gphy->nrssi_lt[i] = i; - - gphy->lofcal = 0xFFFF; - gphy->initval = 0xFFFF; - - gphy->interfmode = B43_INTERFMODE_NONE; - - /* OFDM-table address caching. */ - gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_UNKNOWN; - - gphy->average_tssi = 0xFF; - - /* Local Osciallator structure */ - lo->tx_bias = 0xFF; - INIT_LIST_HEAD(&lo->calib_list); -} - -static void b43_gphy_op_free(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - - kfree(gphy->lo_control); - - if (gphy->dyn_tssi_tbl) - kfree(gphy->tssi2dbm); - gphy->dyn_tssi_tbl = 0; - gphy->tssi2dbm = NULL; - - kfree(gphy); - dev->phy.g = NULL; -} - -static int b43_gphy_op_prepare_hardware(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - struct b43_txpower_lo_control *lo = gphy->lo_control; - - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - - default_baseband_attenuation(dev, &gphy->bbatt); - default_radio_attenuation(dev, &gphy->rfatt); - gphy->tx_control = (default_tx_control(dev) << 4); - generate_rfatt_list(dev, &lo->rfatt_list); - generate_bbatt_list(dev, &lo->bbatt_list); - - /* Commit previous writes */ - b43_read32(dev, B43_MMIO_MACCTL); - - if (phy->rev == 1) { - /* Workaround: Temporarly disable gmode through the early init - * phase, as the gmode stuff is not needed for phy rev 1 */ - phy->gmode = 0; - b43_wireless_core_reset(dev, 0); - b43_phy_initg(dev); - phy->gmode = 1; - b43_wireless_core_reset(dev, B43_TMSLOW_GMODE); - } - - return 0; -} - -static int b43_gphy_op_init(struct b43_wldev *dev) -{ - b43_phy_initg(dev); - - return 0; -} - -static void b43_gphy_op_exit(struct b43_wldev *dev) -{ - b43_lo_g_cleanup(dev); -} - -static u16 b43_gphy_op_read(struct b43_wldev *dev, u16 reg) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - return b43_read16(dev, B43_MMIO_PHY_DATA); -} - -static void b43_gphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, value); -} - -static u16 b43_gphy_op_radio_read(struct b43_wldev *dev, u16 reg) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - /* G-PHY needs 0x80 for read access. */ - reg |= 0x80; - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); -} - -static void b43_gphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); -} - -static bool b43_gphy_op_supports_hwpctl(struct b43_wldev *dev) -{ - return (dev->phy.rev >= 6); -} - -static void b43_gphy_op_software_rfkill(struct b43_wldev *dev, - bool blocked) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - unsigned int channel; - - might_sleep(); - - if (!blocked) { - /* Turn radio ON */ - if (phy->radio_on) - return; - - b43_phy_write(dev, 0x0015, 0x8000); - b43_phy_write(dev, 0x0015, 0xCC00); - b43_phy_write(dev, 0x0015, (phy->gmode ? 0x00C0 : 0x0000)); - if (gphy->radio_off_context.valid) { - /* Restore the RFover values. */ - b43_phy_write(dev, B43_PHY_RFOVER, - gphy->radio_off_context.rfover); - b43_phy_write(dev, B43_PHY_RFOVERVAL, - gphy->radio_off_context.rfoverval); - gphy->radio_off_context.valid = 0; - } - channel = phy->channel; - b43_gphy_channel_switch(dev, 6, 1); - b43_gphy_channel_switch(dev, channel, 0); - } else { - /* Turn radio OFF */ - u16 rfover, rfoverval; - - rfover = b43_phy_read(dev, B43_PHY_RFOVER); - rfoverval = b43_phy_read(dev, B43_PHY_RFOVERVAL); - gphy->radio_off_context.rfover = rfover; - gphy->radio_off_context.rfoverval = rfoverval; - gphy->radio_off_context.valid = 1; - b43_phy_write(dev, B43_PHY_RFOVER, rfover | 0x008C); - b43_phy_write(dev, B43_PHY_RFOVERVAL, rfoverval & 0xFF73); - } -} - -static int b43_gphy_op_switch_channel(struct b43_wldev *dev, - unsigned int new_channel) -{ - if ((new_channel < 1) || (new_channel > 14)) - return -EINVAL; - b43_gphy_channel_switch(dev, new_channel, 0); - - return 0; -} - -static unsigned int b43_gphy_op_get_default_chan(struct b43_wldev *dev) -{ - return 1; /* Default to channel 1 */ -} - -static void b43_gphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) -{ - struct b43_phy *phy = &dev->phy; - u16 tmp; - int autodiv = 0; - - if (antenna == B43_ANTENNA_AUTO0 || antenna == B43_ANTENNA_AUTO1) - autodiv = 1; - - b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP); - - b43_phy_maskset(dev, B43_PHY_BBANDCFG, ~B43_PHY_BBANDCFG_RXANT, - (autodiv ? B43_ANTENNA_AUTO1 : antenna) << - B43_PHY_BBANDCFG_RXANT_SHIFT); - - if (autodiv) { - tmp = b43_phy_read(dev, B43_PHY_ANTDWELL); - if (antenna == B43_ANTENNA_AUTO1) - tmp &= ~B43_PHY_ANTDWELL_AUTODIV1; - else - tmp |= B43_PHY_ANTDWELL_AUTODIV1; - b43_phy_write(dev, B43_PHY_ANTDWELL, tmp); - } - - tmp = b43_phy_read(dev, B43_PHY_ANTWRSETT); - if (autodiv) - tmp |= B43_PHY_ANTWRSETT_ARXDIV; - else - tmp &= ~B43_PHY_ANTWRSETT_ARXDIV; - b43_phy_write(dev, B43_PHY_ANTWRSETT, tmp); - - if (autodiv) - b43_phy_set(dev, B43_PHY_ANTWRSETT, B43_PHY_ANTWRSETT_ARXDIV); - else { - b43_phy_mask(dev, B43_PHY_ANTWRSETT, - B43_PHY_ANTWRSETT_ARXDIV); - } - - if (phy->rev >= 2) { - b43_phy_set(dev, B43_PHY_OFDM61, B43_PHY_OFDM61_10); - b43_phy_maskset(dev, B43_PHY_DIVSRCHGAINBACK, 0xFF00, 0x15); - - if (phy->rev == 2) - b43_phy_write(dev, B43_PHY_ADIVRELATED, 8); - else - b43_phy_maskset(dev, B43_PHY_ADIVRELATED, 0xFF00, 8); - } - if (phy->rev >= 6) - b43_phy_write(dev, B43_PHY_OFDM9B, 0xDC); - - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP); -} - -static int b43_gphy_op_interf_mitigation(struct b43_wldev *dev, - enum b43_interference_mitigation mode) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - int currentmode; - - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - if ((phy->rev == 0) || (!phy->gmode)) - return -ENODEV; - - gphy->aci_wlan_automatic = 0; - switch (mode) { - case B43_INTERFMODE_AUTOWLAN: - gphy->aci_wlan_automatic = 1; - if (gphy->aci_enable) - mode = B43_INTERFMODE_MANUALWLAN; - else - mode = B43_INTERFMODE_NONE; - break; - case B43_INTERFMODE_NONE: - case B43_INTERFMODE_NONWLAN: - case B43_INTERFMODE_MANUALWLAN: - break; - default: - return -EINVAL; - } - - currentmode = gphy->interfmode; - if (currentmode == mode) - return 0; - if (currentmode != B43_INTERFMODE_NONE) - b43_radio_interference_mitigation_disable(dev, currentmode); - - if (mode == B43_INTERFMODE_NONE) { - gphy->aci_enable = 0; - gphy->aci_hw_rssi = 0; - } else - b43_radio_interference_mitigation_enable(dev, mode); - gphy->interfmode = mode; - - return 0; -} - -/* http://bcm-specs.sipsolutions.net/EstimatePowerOut - * This function converts a TSSI value to dBm in Q5.2 - */ -static s8 b43_gphy_estimate_power_out(struct b43_wldev *dev, s8 tssi) -{ - struct b43_phy_g *gphy = dev->phy.g; - s8 dbm; - s32 tmp; - - tmp = (gphy->tgt_idle_tssi - gphy->cur_idle_tssi + tssi); - tmp = clamp_val(tmp, 0x00, 0x3F); - dbm = gphy->tssi2dbm[tmp]; - - return dbm; -} - -static void b43_put_attenuation_into_ranges(struct b43_wldev *dev, - int *_bbatt, int *_rfatt) -{ - int rfatt = *_rfatt; - int bbatt = *_bbatt; - struct b43_txpower_lo_control *lo = dev->phy.g->lo_control; - - /* Get baseband and radio attenuation values into their permitted ranges. - * Radio attenuation affects power level 4 times as much as baseband. */ - - /* Range constants */ - const int rf_min = lo->rfatt_list.min_val; - const int rf_max = lo->rfatt_list.max_val; - const int bb_min = lo->bbatt_list.min_val; - const int bb_max = lo->bbatt_list.max_val; - - while (1) { - if (rfatt > rf_max && bbatt > bb_max - 4) - break; /* Can not get it into ranges */ - if (rfatt < rf_min && bbatt < bb_min + 4) - break; /* Can not get it into ranges */ - if (bbatt > bb_max && rfatt > rf_max - 1) - break; /* Can not get it into ranges */ - if (bbatt < bb_min && rfatt < rf_min + 1) - break; /* Can not get it into ranges */ - - if (bbatt > bb_max) { - bbatt -= 4; - rfatt += 1; - continue; - } - if (bbatt < bb_min) { - bbatt += 4; - rfatt -= 1; - continue; - } - if (rfatt > rf_max) { - rfatt -= 1; - bbatt += 4; - continue; - } - if (rfatt < rf_min) { - rfatt += 1; - bbatt -= 4; - continue; - } - break; - } - - *_rfatt = clamp_val(rfatt, rf_min, rf_max); - *_bbatt = clamp_val(bbatt, bb_min, bb_max); -} - -static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - int rfatt, bbatt; - u8 tx_control; - - b43_mac_suspend(dev); - - /* Calculate the new attenuation values. */ - bbatt = gphy->bbatt.att; - bbatt += gphy->bbatt_delta; - rfatt = gphy->rfatt.att; - rfatt += gphy->rfatt_delta; - - b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt); - tx_control = gphy->tx_control; - if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) { - if (rfatt <= 1) { - if (tx_control == 0) { - tx_control = - B43_TXCTL_PA2DB | - B43_TXCTL_TXMIX; - rfatt += 2; - bbatt += 2; - } else if (dev->dev->bus->sprom. - boardflags_lo & - B43_BFL_PACTRL) { - bbatt += 4 * (rfatt - 2); - rfatt = 2; - } - } else if (rfatt > 4 && tx_control) { - tx_control = 0; - if (bbatt < 3) { - rfatt -= 3; - bbatt += 2; - } else { - rfatt -= 2; - bbatt -= 2; - } - } - } - /* Save the control values */ - gphy->tx_control = tx_control; - b43_put_attenuation_into_ranges(dev, &bbatt, &rfatt); - gphy->rfatt.att = rfatt; - gphy->bbatt.att = bbatt; - - if (b43_debug(dev, B43_DBG_XMITPOWER)) - b43dbg(dev->wl, "Adjusting TX power\n"); - - /* Adjust the hardware */ - b43_phy_lock(dev); - b43_radio_lock(dev); - b43_set_txpower_g(dev, &gphy->bbatt, &gphy->rfatt, - gphy->tx_control); - b43_radio_unlock(dev); - b43_phy_unlock(dev); - - b43_mac_enable(dev); -} - -static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, - bool ignore_tssi) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - unsigned int average_tssi; - int cck_result, ofdm_result; - int estimated_pwr, desired_pwr, pwr_adjust; - int rfatt_delta, bbatt_delta; - unsigned int max_pwr; - - /* First get the average TSSI */ - cck_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_CCK); - ofdm_result = b43_phy_shm_tssi_read(dev, B43_SHM_SH_TSSI_OFDM_G); - if ((cck_result < 0) && (ofdm_result < 0)) { - /* No TSSI information available */ - if (!ignore_tssi) - goto no_adjustment_needed; - cck_result = 0; - ofdm_result = 0; - } - if (cck_result < 0) - average_tssi = ofdm_result; - else if (ofdm_result < 0) - average_tssi = cck_result; - else - average_tssi = (cck_result + ofdm_result) / 2; - /* Merge the average with the stored value. */ - if (likely(gphy->average_tssi != 0xFF)) - average_tssi = (average_tssi + gphy->average_tssi) / 2; - gphy->average_tssi = average_tssi; - B43_WARN_ON(average_tssi >= B43_TSSI_MAX); - - /* Estimate the TX power emission based on the TSSI */ - estimated_pwr = b43_gphy_estimate_power_out(dev, average_tssi); - - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - max_pwr = dev->dev->bus->sprom.maxpwr_bg; - if (dev->dev->bus->sprom.boardflags_lo & B43_BFL_PACTRL) - max_pwr -= 3; /* minus 0.75 */ - if (unlikely(max_pwr >= INT_TO_Q52(30/*dBm*/))) { - b43warn(dev->wl, - "Invalid max-TX-power value in SPROM.\n"); - max_pwr = INT_TO_Q52(20); /* fake it */ - dev->dev->bus->sprom.maxpwr_bg = max_pwr; - } - - /* Get desired power (in Q5.2) */ - if (phy->desired_txpower < 0) - desired_pwr = INT_TO_Q52(0); - else - desired_pwr = INT_TO_Q52(phy->desired_txpower); - /* And limit it. max_pwr already is Q5.2 */ - desired_pwr = clamp_val(desired_pwr, 0, max_pwr); - if (b43_debug(dev, B43_DBG_XMITPOWER)) { - b43dbg(dev->wl, - "[TX power] current = " Q52_FMT - " dBm, desired = " Q52_FMT - " dBm, max = " Q52_FMT "\n", - Q52_ARG(estimated_pwr), - Q52_ARG(desired_pwr), - Q52_ARG(max_pwr)); - } - - /* Calculate the adjustment delta. */ - pwr_adjust = desired_pwr - estimated_pwr; - if (pwr_adjust == 0) - goto no_adjustment_needed; - - /* RF attenuation delta. */ - rfatt_delta = ((pwr_adjust + 7) / 8); - /* Lower attenuation => Bigger power output. Negate it. */ - rfatt_delta = -rfatt_delta; - - /* Baseband attenuation delta. */ - bbatt_delta = pwr_adjust / 2; - /* Lower attenuation => Bigger power output. Negate it. */ - bbatt_delta = -bbatt_delta; - /* RF att affects power level 4 times as much as - * Baseband attennuation. Subtract it. */ - bbatt_delta -= 4 * rfatt_delta; - -#if B43_DEBUG - if (b43_debug(dev, B43_DBG_XMITPOWER)) { - int dbm = pwr_adjust < 0 ? -pwr_adjust : pwr_adjust; - b43dbg(dev->wl, - "[TX power deltas] %s" Q52_FMT " dBm => " - "bbatt-delta = %d, rfatt-delta = %d\n", - (pwr_adjust < 0 ? "-" : ""), Q52_ARG(dbm), - bbatt_delta, rfatt_delta); - } -#endif /* DEBUG */ - - /* So do we finally need to adjust something in hardware? */ - if ((rfatt_delta == 0) && (bbatt_delta == 0)) - goto no_adjustment_needed; - - /* Save the deltas for later when we adjust the power. */ - gphy->bbatt_delta = bbatt_delta; - gphy->rfatt_delta = rfatt_delta; - - /* We need to adjust the TX power on the device. */ - return B43_TXPWR_RES_NEED_ADJUST; - -no_adjustment_needed: - return B43_TXPWR_RES_DONE; -} - -static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - - b43_mac_suspend(dev); - //TODO: update_aci_moving_average - if (gphy->aci_enable && gphy->aci_wlan_automatic) { - if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { - if (0 /*TODO: bunch of conditions */ ) { - phy->ops->interf_mitigation(dev, - B43_INTERFMODE_MANUALWLAN); - } - } else if (0 /*TODO*/) { - if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) - phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); - } - } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && - phy->rev == 1) { - //TODO: implement rev1 workaround - } - b43_lo_g_maintanance_work(dev); - b43_mac_enable(dev); -} - -static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (!(dev->dev->bus->sprom.boardflags_lo & B43_BFL_RSSI)) - return; - - b43_mac_suspend(dev); - b43_calc_nrssi_slope(dev); - if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 8)) { - u8 old_chan = phy->channel; - - /* VCO Calibration */ - if (old_chan >= 8) - b43_switch_channel(dev, 1); - else - b43_switch_channel(dev, 13); - b43_switch_channel(dev, old_chan); - } - b43_mac_enable(dev); -} - -const struct b43_phy_operations b43_phyops_g = { - .allocate = b43_gphy_op_allocate, - .free = b43_gphy_op_free, - .prepare_structs = b43_gphy_op_prepare_structs, - .prepare_hardware = b43_gphy_op_prepare_hardware, - .init = b43_gphy_op_init, - .exit = b43_gphy_op_exit, - .phy_read = b43_gphy_op_read, - .phy_write = b43_gphy_op_write, - .radio_read = b43_gphy_op_radio_read, - .radio_write = b43_gphy_op_radio_write, - .supports_hwpctl = b43_gphy_op_supports_hwpctl, - .software_rfkill = b43_gphy_op_software_rfkill, - .switch_analog = b43_phyop_switch_analog_generic, - .switch_channel = b43_gphy_op_switch_channel, - .get_default_chan = b43_gphy_op_get_default_chan, - .set_rx_antenna = b43_gphy_op_set_rx_antenna, - .interf_mitigation = b43_gphy_op_interf_mitigation, - .recalc_txpower = b43_gphy_op_recalc_txpower, - .adjust_txpower = b43_gphy_op_adjust_txpower, - .pwork_15sec = b43_gphy_op_pwork_15sec, - .pwork_60sec = b43_gphy_op_pwork_60sec, -}; diff --git a/drivers/net/wireless/b43/phy_g.h b/drivers/net/wireless/b43/phy_g.h deleted file mode 100644 index 8569fdd4c6be..000000000000 --- a/drivers/net/wireless/b43/phy_g.h +++ /dev/null @@ -1,208 +0,0 @@ -#ifndef LINUX_B43_PHY_G_H_ -#define LINUX_B43_PHY_G_H_ - -/* OFDM PHY registers are defined in the A-PHY header. */ -#include "phy_a.h" - -/* CCK (B) PHY Registers */ -#define B43_PHY_VERSION_CCK B43_PHY_CCK(0x00) /* Versioning register for B-PHY */ -#define B43_PHY_CCKBBANDCFG B43_PHY_CCK(0x01) /* Contains antenna 0/1 control bit */ -#define B43_PHY_PGACTL B43_PHY_CCK(0x15) /* PGA control */ -#define B43_PHY_PGACTL_LPF 0x1000 /* Low pass filter (?) */ -#define B43_PHY_PGACTL_LOWBANDW 0x0040 /* Low bandwidth flag */ -#define B43_PHY_PGACTL_UNKNOWN 0xEFA0 -#define B43_PHY_FBCTL1 B43_PHY_CCK(0x18) /* Frequency bandwidth control 1 */ -#define B43_PHY_ITSSI B43_PHY_CCK(0x29) /* Idle TSSI */ -#define B43_PHY_LO_LEAKAGE B43_PHY_CCK(0x2D) /* Measured LO leakage */ -#define B43_PHY_ENERGY B43_PHY_CCK(0x33) /* Energy */ -#define B43_PHY_SYNCCTL B43_PHY_CCK(0x35) -#define B43_PHY_FBCTL2 B43_PHY_CCK(0x38) /* Frequency bandwidth control 2 */ -#define B43_PHY_DACCTL B43_PHY_CCK(0x60) /* DAC control */ -#define B43_PHY_RCCALOVER B43_PHY_CCK(0x78) /* RC calibration override */ - -/* Extended G-PHY Registers */ -#define B43_PHY_CLASSCTL B43_PHY_EXTG(0x02) /* Classify control */ -#define B43_PHY_GTABCTL B43_PHY_EXTG(0x03) /* G-PHY table control (see below) */ -#define B43_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */ -#define B43_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */ -#define B43_PHY_GTABNR_SHIFT 10 -#define B43_PHY_GTABDATA B43_PHY_EXTG(0x04) /* G-PHY table data */ -#define B43_PHY_LO_MASK B43_PHY_EXTG(0x0F) /* Local Oscillator control mask */ -#define B43_PHY_LO_CTL B43_PHY_EXTG(0x10) /* Local Oscillator control */ -#define B43_PHY_RFOVER B43_PHY_EXTG(0x11) /* RF override */ -#define B43_PHY_RFOVERVAL B43_PHY_EXTG(0x12) /* RF override value */ -#define B43_PHY_RFOVERVAL_EXTLNA 0x8000 -#define B43_PHY_RFOVERVAL_LNA 0x7000 -#define B43_PHY_RFOVERVAL_LNA_SHIFT 12 -#define B43_PHY_RFOVERVAL_PGA 0x0F00 -#define B43_PHY_RFOVERVAL_PGA_SHIFT 8 -#define B43_PHY_RFOVERVAL_UNK 0x0010 /* Unknown, always set. */ -#define B43_PHY_RFOVERVAL_TRSWRX 0x00E0 -#define B43_PHY_RFOVERVAL_BW 0x0003 /* Bandwidth flags */ -#define B43_PHY_RFOVERVAL_BW_LPF 0x0001 /* Low Pass Filter */ -#define B43_PHY_RFOVERVAL_BW_LBW 0x0002 /* Low Bandwidth (when set), high when unset */ -#define B43_PHY_ANALOGOVER B43_PHY_EXTG(0x14) /* Analog override */ -#define B43_PHY_ANALOGOVERVAL B43_PHY_EXTG(0x15) /* Analog override value */ - - -/*** G-PHY table numbers */ -#define B43_GTAB(number, offset) (((number) << B43_PHY_GTABNR_SHIFT) | (offset)) -#define B43_GTAB_NRSSI B43_GTAB(0x00, 0) -#define B43_GTAB_TRFEMW B43_GTAB(0x0C, 0x120) -#define B43_GTAB_ORIGTR B43_GTAB(0x2E, 0x298) - -u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset); -void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value); - - -/* Returns the boolean whether "TX Magnification" is enabled. */ -#define has_tx_magnification(phy) \ - (((phy)->rev >= 2) && \ - ((phy)->radio_ver == 0x2050) && \ - ((phy)->radio_rev == 8)) -/* Card uses the loopback gain stuff */ -#define has_loopback_gain(phy) \ - (((phy)->rev > 1) || ((phy)->gmode)) - -/* Radio Attenuation (RF Attenuation) */ -struct b43_rfatt { - u8 att; /* Attenuation value */ - bool with_padmix; /* Flag, PAD Mixer enabled. */ -}; -struct b43_rfatt_list { - /* Attenuation values list */ - const struct b43_rfatt *list; - u8 len; - /* Minimum/Maximum attenuation values */ - u8 min_val; - u8 max_val; -}; - -/* Returns true, if the values are the same. */ -static inline bool b43_compare_rfatt(const struct b43_rfatt *a, - const struct b43_rfatt *b) -{ - return ((a->att == b->att) && - (a->with_padmix == b->with_padmix)); -} - -/* Baseband Attenuation */ -struct b43_bbatt { - u8 att; /* Attenuation value */ -}; -struct b43_bbatt_list { - /* Attenuation values list */ - const struct b43_bbatt *list; - u8 len; - /* Minimum/Maximum attenuation values */ - u8 min_val; - u8 max_val; -}; - -/* Returns true, if the values are the same. */ -static inline bool b43_compare_bbatt(const struct b43_bbatt *a, - const struct b43_bbatt *b) -{ - return (a->att == b->att); -} - -/* tx_control bits. */ -#define B43_TXCTL_PA3DB 0x40 /* PA Gain 3dB */ -#define B43_TXCTL_PA2DB 0x20 /* PA Gain 2dB */ -#define B43_TXCTL_TXMIX 0x10 /* TX Mixer Gain */ - -struct b43_txpower_lo_control; - -struct b43_phy_g { - /* ACI (adjacent channel interference) flags. */ - bool aci_enable; - bool aci_wlan_automatic; - bool aci_hw_rssi; - - /* Radio switched on/off */ - bool radio_on; - struct { - /* Values saved when turning the radio off. - * They are needed when turning it on again. */ - bool valid; - u16 rfover; - u16 rfoverval; - } radio_off_context; - - u16 minlowsig[2]; - u16 minlowsigpos[2]; - - /* Pointer to the table used to convert a - * TSSI value to dBm-Q5.2 */ - const s8 *tssi2dbm; - /* tssi2dbm is kmalloc()ed. Only used for free()ing. */ - bool dyn_tssi_tbl; - /* Target idle TSSI */ - int tgt_idle_tssi; - /* Current idle TSSI */ - int cur_idle_tssi; - /* The current average TSSI. */ - u8 average_tssi; - /* Current TX power level attenuation control values */ - struct b43_bbatt bbatt; - struct b43_rfatt rfatt; - u8 tx_control; /* B43_TXCTL_XXX */ - /* The calculated attenuation deltas that are used later - * when adjusting the actual power output. */ - int bbatt_delta; - int rfatt_delta; - - /* LocalOscillator control values. */ - struct b43_txpower_lo_control *lo_control; - /* Values from b43_calc_loopback_gain() */ - s16 max_lb_gain; /* Maximum Loopback gain in hdB */ - s16 trsw_rx_gain; /* TRSW RX gain in hdB */ - s16 lna_lod_gain; /* LNA lod */ - s16 lna_gain; /* LNA */ - s16 pga_gain; /* PGA */ - - /* Current Interference Mitigation mode */ - int interfmode; - /* Stack of saved values from the Interference Mitigation code. - * Each value in the stack is layed out as follows: - * bit 0-11: offset - * bit 12-15: register ID - * bit 16-32: value - * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT - */ -#define B43_INTERFSTACK_SIZE 26 - u32 interfstack[B43_INTERFSTACK_SIZE]; //FIXME: use a data structure - - /* Saved values from the NRSSI Slope calculation */ - s16 nrssi[2]; - s32 nrssislope; - /* In memory nrssi lookup table. */ - s8 nrssi_lt[64]; - - u16 lofcal; - - u16 initval; //FIXME rename? - - /* The device does address auto increment for the OFDM tables. - * We cache the previously used address here and omit the address - * write on the next table access, if possible. */ - u16 ofdmtab_addr; /* The address currently set in hardware. */ - enum { /* The last data flow direction. */ - B43_OFDMTAB_DIRECTION_UNKNOWN = 0, - B43_OFDMTAB_DIRECTION_READ, - B43_OFDMTAB_DIRECTION_WRITE, - } ofdmtab_addr_direction; -}; - -void b43_gphy_set_baseband_attenuation(struct b43_wldev *dev, - u16 baseband_attenuation); -void b43_gphy_channel_switch(struct b43_wldev *dev, - unsigned int channel, - bool synthetic_pu_workaround); -u8 * b43_generate_dyn_tssi2dbm_tab(struct b43_wldev *dev, - s16 pab0, s16 pab1, s16 pab2); - -struct b43_phy_operations; -extern const struct b43_phy_operations b43_phyops_g; - -#endif /* LINUX_B43_PHY_G_H_ */ diff --git a/drivers/net/wireless/b43/phy_lp.c b/drivers/net/wireless/b43/phy_lp.c deleted file mode 100644 index 1e318d815a5b..000000000000 --- a/drivers/net/wireless/b43/phy_lp.c +++ /dev/null @@ -1,2258 +0,0 @@ -/* - - Broadcom B43 wireless driver - IEEE 802.11a/g LP-PHY driver - - Copyright (c) 2008-2009 Michael Buesch - Copyright (c) 2009 Gábor Stefanik - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "main.h" -#include "phy_lp.h" -#include "phy_common.h" -#include "tables_lpphy.h" - - -static inline u16 channel2freq_lp(u8 channel) -{ - if (channel < 14) - return (2407 + 5 * channel); - else if (channel == 14) - return 2484; - else if (channel < 184) - return (5000 + 5 * channel); - else - return (4000 + 5 * channel); -} - -static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev) -{ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - return 1; - return 36; -} - -static int b43_lpphy_op_allocate(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy; - - lpphy = kzalloc(sizeof(*lpphy), GFP_KERNEL); - if (!lpphy) - return -ENOMEM; - dev->phy.lp = lpphy; - - return 0; -} - -static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_lp *lpphy = phy->lp; - - memset(lpphy, 0, sizeof(*lpphy)); - - //TODO -} - -static void b43_lpphy_op_free(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - - kfree(lpphy); - dev->phy.lp = NULL; -} - -static void lpphy_read_band_sprom(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; - u16 cckpo, maxpwr; - u32 ofdmpo; - int i; - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - lpphy->tx_isolation_med_band = bus->sprom.tri2g; - lpphy->bx_arch = bus->sprom.bxa2g; - lpphy->rx_pwr_offset = bus->sprom.rxpo2g; - lpphy->rssi_vf = bus->sprom.rssismf2g; - lpphy->rssi_vc = bus->sprom.rssismc2g; - lpphy->rssi_gs = bus->sprom.rssisav2g; - lpphy->txpa[0] = bus->sprom.pa0b0; - lpphy->txpa[1] = bus->sprom.pa0b1; - lpphy->txpa[2] = bus->sprom.pa0b2; - maxpwr = bus->sprom.maxpwr_bg; - lpphy->max_tx_pwr_med_band = maxpwr; - cckpo = bus->sprom.cck2gpo; - ofdmpo = bus->sprom.ofdm2gpo; - if (cckpo) { - for (i = 0; i < 4; i++) { - lpphy->tx_max_rate[i] = - maxpwr - (ofdmpo & 0xF) * 2; - ofdmpo >>= 4; - } - ofdmpo = bus->sprom.ofdm2gpo; - for (i = 4; i < 15; i++) { - lpphy->tx_max_rate[i] = - maxpwr - (ofdmpo & 0xF) * 2; - ofdmpo >>= 4; - } - } else { - ofdmpo &= 0xFF; - for (i = 0; i < 4; i++) - lpphy->tx_max_rate[i] = maxpwr; - for (i = 4; i < 15; i++) - lpphy->tx_max_rate[i] = maxpwr - ofdmpo; - } - } else { /* 5GHz */ - lpphy->tx_isolation_low_band = bus->sprom.tri5gl; - lpphy->tx_isolation_med_band = bus->sprom.tri5g; - lpphy->tx_isolation_hi_band = bus->sprom.tri5gh; - lpphy->bx_arch = bus->sprom.bxa5g; - lpphy->rx_pwr_offset = bus->sprom.rxpo5g; - lpphy->rssi_vf = bus->sprom.rssismf5g; - lpphy->rssi_vc = bus->sprom.rssismc5g; - lpphy->rssi_gs = bus->sprom.rssisav5g; - lpphy->txpa[0] = bus->sprom.pa1b0; - lpphy->txpa[1] = bus->sprom.pa1b1; - lpphy->txpa[2] = bus->sprom.pa1b2; - lpphy->txpal[0] = bus->sprom.pa1lob0; - lpphy->txpal[1] = bus->sprom.pa1lob1; - lpphy->txpal[2] = bus->sprom.pa1lob2; - lpphy->txpah[0] = bus->sprom.pa1hib0; - lpphy->txpah[1] = bus->sprom.pa1hib1; - lpphy->txpah[2] = bus->sprom.pa1hib2; - maxpwr = bus->sprom.maxpwr_al; - ofdmpo = bus->sprom.ofdm5glpo; - lpphy->max_tx_pwr_low_band = maxpwr; - for (i = 4; i < 12; i++) { - lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2; - ofdmpo >>= 4; - } - maxpwr = bus->sprom.maxpwr_a; - ofdmpo = bus->sprom.ofdm5gpo; - lpphy->max_tx_pwr_med_band = maxpwr; - for (i = 4; i < 12; i++) { - lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2; - ofdmpo >>= 4; - } - maxpwr = bus->sprom.maxpwr_ah; - ofdmpo = bus->sprom.ofdm5ghpo; - lpphy->max_tx_pwr_hi_band = maxpwr; - for (i = 4; i < 12; i++) { - lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2; - ofdmpo >>= 4; - } - } -} - -static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u16 temp[3]; - u16 isolation; - - B43_WARN_ON(dev->phy.rev >= 2); - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - isolation = lpphy->tx_isolation_med_band; - else if (freq <= 5320) - isolation = lpphy->tx_isolation_low_band; - else if (freq <= 5700) - isolation = lpphy->tx_isolation_med_band; - else - isolation = lpphy->tx_isolation_hi_band; - - temp[0] = ((isolation - 26) / 12) << 12; - temp[1] = temp[0] + 0x1000; - temp[2] = temp[0] + 0x2000; - - b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp); - b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp); -} - -static void lpphy_table_init(struct b43_wldev *dev) -{ - u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev)); - - if (dev->phy.rev < 2) - lpphy_rev0_1_table_init(dev); - else - lpphy_rev2plus_table_init(dev); - - lpphy_init_tx_gain_table(dev); - - if (dev->phy.rev < 2) - lpphy_adjust_gain_table(dev, freq); -} - -static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy_lp *lpphy = dev->phy.lp; - u16 tmp, tmp2; - - b43_phy_mask(dev, B43_LPPHY_AFE_DAC_CTL, 0xF7FF); - b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0); - b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0); - b43_phy_set(dev, B43_LPPHY_AFE_DAC_CTL, 0x0004); - b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x0078); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800); - b43_phy_write(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x0016); - b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_0, 0xFFF8, 0x0004); - b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5400); - b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2400); - b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100); - b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006); - b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00); - b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005); - b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A); - b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3); - b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00); - b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, - 0xFF00, lpphy->rx_pwr_offset); - if ((bus->sprom.boardflags_lo & B43_BFL_FEM) && - ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) || - (bus->sprom.boardflags_hi & B43_BFH_PAREF))) { - ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28); - ssb_pmu_set_ldo_paref(&bus->chipco, true); - if (dev->phy.rev == 0) { - b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, - 0xFFCF, 0x0010); - } - b43_lptab_write(dev, B43_LPTAB16(11, 7), 60); - } else { - ssb_pmu_set_ldo_paref(&bus->chipco, false); - b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT, - 0xFFCF, 0x0020); - b43_lptab_write(dev, B43_LPTAB16(11, 7), 100); - } - tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000; - b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp); - if (bus->sprom.boardflags_hi & B43_BFH_RSSIINV) - b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA); - else - b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA); - b43_lptab_write(dev, B43_LPTAB16(11, 1), 24); - b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL, - 0xFFF9, (lpphy->bx_arch << 1)); - if (dev->phy.rev == 1 && - (bus->sprom.boardflags_hi & B43_BFH_FEM_BT)) { - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00); - } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ || - (bus->boardinfo.type == 0x048A) || ((dev->phy.rev == 0) && - (bus->sprom.boardflags_lo & B43_BFL_FEM))) { - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00); - } else if (dev->phy.rev == 1 || - (bus->sprom.boardflags_lo & B43_BFL_FEM)) { - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300); - } else { - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006); - b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700); - } - if (dev->phy.rev == 1 && (bus->sprom.boardflags_hi & B43_BFH_PAREF)) { - b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1); - b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2); - b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3); - b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4); - } - if ((bus->sprom.boardflags_hi & B43_BFH_FEM_BT) && - (bus->chip_id == 0x5354) && - (bus->chip_package == SSB_CHIPPACK_BCM4712S)) { - b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006); - b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005); - b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF); - //FIXME the Broadcom driver caches & delays this HF write! - b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W); - } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000); - b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040); - b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400); - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00); - b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007); - b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003); - b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020); - b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF); - } else { /* 5GHz */ - b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF); - b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF); - } - if (dev->phy.rev == 1) { - tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH); - tmp2 = (tmp & 0x03E0) >> 5; - tmp2 |= tmp2 << 5; - b43_phy_write(dev, B43_LPPHY_4C3, tmp2); - tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH); - tmp2 = (tmp & 0x1F00) >> 8; - tmp2 |= tmp2 << 5; - b43_phy_write(dev, B43_LPPHY_4C4, tmp2); - tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB); - tmp2 = tmp & 0x00FF; - tmp2 |= tmp << 8; - b43_phy_write(dev, B43_LPPHY_4C5, tmp2); - } -} - -static void lpphy_save_dig_flt_state(struct b43_wldev *dev) -{ - static const u16 addr[] = { - B43_PHY_OFDM(0xC1), - B43_PHY_OFDM(0xC2), - B43_PHY_OFDM(0xC3), - B43_PHY_OFDM(0xC4), - B43_PHY_OFDM(0xC5), - B43_PHY_OFDM(0xC6), - B43_PHY_OFDM(0xC7), - B43_PHY_OFDM(0xC8), - B43_PHY_OFDM(0xCF), - }; - - static const u16 coefs[] = { - 0xDE5E, 0xE832, 0xE331, 0x4D26, - 0x0026, 0x1420, 0x0020, 0xFE08, - 0x0008, - }; - - struct b43_phy_lp *lpphy = dev->phy.lp; - int i; - - for (i = 0; i < ARRAY_SIZE(addr); i++) { - lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]); - b43_phy_write(dev, addr[i], coefs[i]); - } -} - -static void lpphy_restore_dig_flt_state(struct b43_wldev *dev) -{ - static const u16 addr[] = { - B43_PHY_OFDM(0xC1), - B43_PHY_OFDM(0xC2), - B43_PHY_OFDM(0xC3), - B43_PHY_OFDM(0xC4), - B43_PHY_OFDM(0xC5), - B43_PHY_OFDM(0xC6), - B43_PHY_OFDM(0xC7), - B43_PHY_OFDM(0xC8), - B43_PHY_OFDM(0xCF), - }; - - struct b43_phy_lp *lpphy = dev->phy.lp; - int i; - - for (i = 0; i < ARRAY_SIZE(addr); i++) - b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]); -} - -static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy_lp *lpphy = dev->phy.lp; - - b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50); - b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0x8800); - b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0); - b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0); - b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0); - b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0); - b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10); - b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4); - b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200); - b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F); - b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40); - b43_phy_maskset(dev, B43_LPPHY_PREAMBLECONFIRMTO, 0xFF00, 0x2); - b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000); - b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000); - b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1); - if (bus->boardinfo.rev >= 0x18) { - b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC); - b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14); - } else { - b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10); - } - b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4); - b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100); - b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48); - b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0xFF00, 0x46); - b43_phy_maskset(dev, B43_PHY_OFDM(0xE4), 0xFF00, 0x10); - b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9); - b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF); - b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0); - b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300); - b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00); - if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { - b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100); - b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA); - } else { - b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00); - b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD); - } - b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFFE0, 0x1F); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC); - b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0xFF00, 0x19); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0x03FF, 0x3C00); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFC1F, 0x3E0); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC); - b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0x00FF, 0x1900); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800); - b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12); - b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000); - - if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { - b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0); - b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40); - } - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40); - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0xB00); - b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6); - b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00); - b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1); - b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF); - } else /* 5GHz */ - b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40); - - b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0xB3); - b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00); - b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, 0xFF00, lpphy->rx_pwr_offset); - b43_phy_set(dev, B43_LPPHY_RESET_CTL, 0x44); - b43_phy_write(dev, B43_LPPHY_RESET_CTL, 0x80); - b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, 0xA954); - b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1, - 0x2000 | ((u16)lpphy->rssi_gs << 10) | - ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf); - - if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { - b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C); - b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800); - b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400); - } - - lpphy_save_dig_flt_state(dev); -} - -static void lpphy_baseband_init(struct b43_wldev *dev) -{ - lpphy_table_init(dev); - if (dev->phy.rev >= 2) - lpphy_baseband_rev2plus_init(dev); - else - lpphy_baseband_rev0_1_init(dev); -} - -struct b2062_freqdata { - u16 freq; - u8 data[6]; -}; - -/* Initialize the 2062 radio. */ -static void lpphy_2062_init(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; - u32 crystalfreq, tmp, ref; - unsigned int i; - const struct b2062_freqdata *fd = NULL; - - static const struct b2062_freqdata freqdata_tab[] = { - { .freq = 12000, .data[0] = 6, .data[1] = 6, .data[2] = 6, - .data[3] = 6, .data[4] = 10, .data[5] = 6, }, - { .freq = 13000, .data[0] = 4, .data[1] = 4, .data[2] = 4, - .data[3] = 4, .data[4] = 11, .data[5] = 7, }, - { .freq = 14400, .data[0] = 3, .data[1] = 3, .data[2] = 3, - .data[3] = 3, .data[4] = 12, .data[5] = 7, }, - { .freq = 16200, .data[0] = 3, .data[1] = 3, .data[2] = 3, - .data[3] = 3, .data[4] = 13, .data[5] = 8, }, - { .freq = 18000, .data[0] = 2, .data[1] = 2, .data[2] = 2, - .data[3] = 2, .data[4] = 14, .data[5] = 8, }, - { .freq = 19200, .data[0] = 1, .data[1] = 1, .data[2] = 1, - .data[3] = 1, .data[4] = 14, .data[5] = 9, }, - }; - - b2062_upload_init_table(dev); - - b43_radio_write(dev, B2062_N_TX_CTL3, 0); - b43_radio_write(dev, B2062_N_TX_CTL4, 0); - b43_radio_write(dev, B2062_N_TX_CTL5, 0); - b43_radio_write(dev, B2062_N_TX_CTL6, 0); - b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40); - b43_radio_write(dev, B2062_N_PDN_CTL0, 0); - b43_radio_write(dev, B2062_N_CALIB_TS, 0x10); - b43_radio_write(dev, B2062_N_CALIB_TS, 0); - if (dev->phy.rev > 0) { - b43_radio_write(dev, B2062_S_BG_CTL1, - (b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80); - } - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1); - else - b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1); - - /* Get the crystal freq, in Hz. */ - crystalfreq = bus->chipco.pmu.crystalfreq * 1000; - - B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU)); - B43_WARN_ON(crystalfreq == 0); - - if (crystalfreq <= 30000000) { - lpphy->pdiv = 1; - b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB); - } else { - lpphy->pdiv = 2; - b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4); - } - - tmp = (((800000000 * lpphy->pdiv + crystalfreq) / - (2 * crystalfreq)) - 8) & 0xFF; - b43_radio_write(dev, B2062_S_RFPLL_CTL7, tmp); - - tmp = (((100 * crystalfreq + 16000000 * lpphy->pdiv) / - (32000000 * lpphy->pdiv)) - 1) & 0xFF; - b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp); - - tmp = (((2 * crystalfreq + 1000000 * lpphy->pdiv) / - (2000000 * lpphy->pdiv)) - 1) & 0xFF; - b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp); - - ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv); - ref &= 0xFFFF; - for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) { - if (ref < freqdata_tab[i].freq) { - fd = &freqdata_tab[i]; - break; - } - } - if (!fd) - fd = &freqdata_tab[ARRAY_SIZE(freqdata_tab) - 1]; - b43dbg(dev->wl, "b2062: Using crystal tab entry %u kHz.\n", - fd->freq); /* FIXME: Keep this printk until the code is fully debugged. */ - - b43_radio_write(dev, B2062_S_RFPLL_CTL8, - ((u16)(fd->data[1]) << 4) | fd->data[0]); - b43_radio_write(dev, B2062_S_RFPLL_CTL9, - ((u16)(fd->data[3]) << 4) | fd->data[2]); - b43_radio_write(dev, B2062_S_RFPLL_CTL10, fd->data[4]); - b43_radio_write(dev, B2062_S_RFPLL_CTL11, fd->data[5]); -} - -/* Initialize the 2063 radio. */ -static void lpphy_2063_init(struct b43_wldev *dev) -{ - b2063_upload_init_table(dev); - b43_radio_write(dev, B2063_LOGEN_SP5, 0); - b43_radio_set(dev, B2063_COMM8, 0x38); - b43_radio_write(dev, B2063_REG_SP1, 0x56); - b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2); - b43_radio_write(dev, B2063_PA_SP7, 0); - b43_radio_write(dev, B2063_TX_RF_SP6, 0x20); - b43_radio_write(dev, B2063_TX_RF_SP9, 0x40); - if (dev->phy.rev == 2) { - b43_radio_write(dev, B2063_PA_SP3, 0xa0); - b43_radio_write(dev, B2063_PA_SP4, 0xa0); - b43_radio_write(dev, B2063_PA_SP2, 0x18); - } else { - b43_radio_write(dev, B2063_PA_SP3, 0x20); - b43_radio_write(dev, B2063_PA_SP2, 0x20); - } -} - -struct lpphy_stx_table_entry { - u16 phy_offset; - u16 phy_shift; - u16 rf_addr; - u16 rf_shift; - u16 mask; -}; - -static const struct lpphy_stx_table_entry lpphy_stx_table[] = { - { .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, }, - { .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, }, - { .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, }, - { .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, }, - { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, }, - { .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, }, - { .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, }, - { .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, }, - { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, }, - { .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, }, - { .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, }, - { .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, }, - { .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, }, - { .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, }, - { .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, }, - { .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, }, - { .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, }, - { .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, }, - { .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, }, - { .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, }, - { .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, }, - { .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, }, - { .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, }, - { .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, }, - { .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, }, - { .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, }, - { .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, }, - { .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, }, - { .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, }, -}; - -static void lpphy_sync_stx(struct b43_wldev *dev) -{ - const struct lpphy_stx_table_entry *e; - unsigned int i; - u16 tmp; - - for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) { - e = &lpphy_stx_table[i]; - tmp = b43_radio_read(dev, e->rf_addr); - tmp >>= e->rf_shift; - tmp <<= e->phy_shift; - b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset), - ~(e->mask << e->phy_shift), tmp); - } -} - -static void lpphy_radio_init(struct b43_wldev *dev) -{ - /* The radio is attached through the 4wire bus. */ - b43_phy_set(dev, B43_LPPHY_FOURWIRE_CTL, 0x2); - udelay(1); - b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD); - udelay(1); - - if (dev->phy.radio_ver == 0x2062) { - lpphy_2062_init(dev); - } else { - lpphy_2063_init(dev); - lpphy_sync_stx(dev); - b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80); - b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0); - if (dev->dev->bus->chip_id == 0x4325) { - // TODO SSB PMU recalibration - } - } -} - -struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; }; - -static void lpphy_set_rc_cap(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - - u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1; - - if (dev->phy.rev == 1) //FIXME check channel 14! - rc_cap = min_t(u8, rc_cap + 5, 15); - - b43_radio_write(dev, B2062_N_RXBB_CALIB2, - max_t(u8, lpphy->rc_cap - 4, 0x80)); - b43_radio_write(dev, B2062_N_TX_CTL_A, rc_cap | 0x80); - b43_radio_write(dev, B2062_S_RXG_CNT16, - ((lpphy->rc_cap & 0x1F) >> 2) | 0x80); -} - -static u8 lpphy_get_bb_mult(struct b43_wldev *dev) -{ - return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8; -} - -static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult) -{ - b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8); -} - -static void lpphy_set_deaf(struct b43_wldev *dev, bool user) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - - if (user) - lpphy->crs_usr_disable = 1; - else - lpphy->crs_sys_disable = 1; - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80); -} - -static void lpphy_clear_deaf(struct b43_wldev *dev, bool user) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - - if (user) - lpphy->crs_usr_disable = 0; - else - lpphy->crs_sys_disable = 0; - - if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, - 0xFF1F, 0x60); - else - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, - 0xFF1F, 0x20); - } -} - -static void lpphy_disable_crs(struct b43_wldev *dev, bool user) -{ - lpphy_set_deaf(dev, user); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x1); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF); - b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0); - b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1); - b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF); - b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0); - b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF); -} - -static void lpphy_restore_crs(struct b43_wldev *dev, bool user) -{ - lpphy_clear_deaf(dev, user); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00); -} - -struct lpphy_tx_gains { u16 gm, pga, pad, dac; }; - -static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev) -{ - struct lpphy_tx_gains gains; - u16 tmp; - - gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7; - if (dev->phy.rev < 2) { - tmp = b43_phy_read(dev, - B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF; - gains.gm = tmp & 0x0007; - gains.pga = (tmp & 0x0078) >> 3; - gains.pad = (tmp & 0x780) >> 7; - } else { - tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL); - gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF; - gains.gm = tmp & 0xFF; - gains.pga = (tmp >> 8) & 0xFF; - } - - return gains; -} - -static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac) -{ - u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F; - ctl |= dac << 7; - b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl); -} - -static void lpphy_set_tx_gains(struct b43_wldev *dev, - struct lpphy_tx_gains gains) -{ - u16 rf_gain, pa_gain; - - if (dev->phy.rev < 2) { - rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm; - b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, - 0xF800, rf_gain); - } else { - pa_gain = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x1FC0; - pa_gain <<= 2; - b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, - (gains.pga << 8) | gains.gm); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), - 0x8000, gains.pad | pa_gain); - b43_phy_write(dev, B43_PHY_OFDM(0xFC), - (gains.pga << 8) | gains.gm); - b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), - 0x8000, gains.pad | pa_gain); - } - lpphy_set_dac_gain(dev, gains.dac); - if (dev->phy.rev < 2) { - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF, 1 << 8); - } else { - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F, 1 << 7); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF, 1 << 14); - } - b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF, 1 << 6); -} - -static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain) -{ - u16 trsw = gain & 0x1; - u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2); - u16 ext_lna = (gain & 2) >> 1; - - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, - 0xFBFF, ext_lna << 10); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, - 0xF7FF, ext_lna << 11); - b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna); -} - -static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain) -{ - u16 low_gain = gain & 0xFFFF; - u16 high_gain = (gain >> 16) & 0xF; - u16 ext_lna = (gain >> 21) & 0x1; - u16 trsw = ~(gain >> 20) & 0x1; - u16 tmp; - - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, - 0xFDFF, ext_lna << 9); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, - 0xFBFF, ext_lna << 10); - b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain); - b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - tmp = (gain >> 2) & 0x3; - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, - 0xE7FF, tmp<<11); - b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3); - } -} - -static void lpphy_disable_rx_gain_override(struct b43_wldev *dev) -{ - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF); - if (dev->phy.rev >= 2) { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF); - b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7); - } - } else { - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF); - } -} - -static void lpphy_enable_rx_gain_override(struct b43_wldev *dev) -{ - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40); - if (dev->phy.rev >= 2) { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100); - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400); - b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8); - } - } else { - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200); - } -} - -static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain) -{ - if (dev->phy.rev < 2) - lpphy_rev0_1_set_rx_gain(dev, gain); - else - lpphy_rev2plus_set_rx_gain(dev, gain); - lpphy_enable_rx_gain_override(dev); -} - -static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx) -{ - u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx)); - lpphy_set_rx_gain(dev, gain); -} - -static void lpphy_stop_ddfs(struct b43_wldev *dev) -{ - b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD); - b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF); -} - -static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on, - int incr1, int incr2, int scale_idx) -{ - lpphy_stop_ddfs(dev); - b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80); - b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF); - b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1); - b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8); - b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3); - b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4); - b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5); - b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB); - b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2); - b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20); -} - -static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time, - struct lpphy_iq_est *iq_est) -{ - int i; - - b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7); - b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples); - b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time); - b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF); - b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200); - - for (i = 0; i < 500; i++) { - if (!(b43_phy_read(dev, - B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) - break; - msleep(1); - } - - if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) { - b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8); - return false; - } - - iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR); - iq_est->iq_prod <<= 16; - iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR); - - iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR); - iq_est->i_pwr <<= 16; - iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR); - - iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR); - iq_est->q_pwr <<= 16; - iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR); - - b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8); - return true; -} - -static int lpphy_loopback(struct b43_wldev *dev) -{ - struct lpphy_iq_est iq_est; - int i, index = -1; - u32 tmp; - - memset(&iq_est, 0, sizeof(iq_est)); - - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, 0x3); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3); - b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1); - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8); - b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80); - b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80); - for (i = 0; i < 32; i++) { - lpphy_set_rx_gain_by_index(dev, i); - lpphy_run_ddfs(dev, 1, 1, 5, 5, 0); - if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est))) - continue; - tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000; - if ((tmp > 4000) && (tmp < 10000)) { - index = i; - break; - } - } - lpphy_stop_ddfs(dev); - return index; -} - -/* Fixed-point division algorithm using only integer math. */ -static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision) -{ - u32 quotient, remainder; - - if (divisor == 0) - return 0; - - quotient = dividend / divisor; - remainder = dividend % divisor; - - while (precision > 0) { - quotient <<= 1; - if (remainder << 1 >= divisor) { - quotient++; - remainder = (remainder << 1) - divisor; - } - precision--; - } - - if (remainder << 1 >= divisor) - quotient++; - - return quotient; -} - -/* Read the TX power control mode from hardware. */ -static void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u16 ctl; - - ctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD); - switch (ctl & B43_LPPHY_TX_PWR_CTL_CMD_MODE) { - case B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF: - lpphy->txpctl_mode = B43_LPPHY_TXPCTL_OFF; - break; - case B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW: - lpphy->txpctl_mode = B43_LPPHY_TXPCTL_SW; - break; - case B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW: - lpphy->txpctl_mode = B43_LPPHY_TXPCTL_HW; - break; - default: - lpphy->txpctl_mode = B43_LPPHY_TXPCTL_UNKNOWN; - B43_WARN_ON(1); - break; - } -} - -/* Set the TX power control mode in hardware. */ -static void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u16 ctl; - - switch (lpphy->txpctl_mode) { - case B43_LPPHY_TXPCTL_OFF: - ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF; - break; - case B43_LPPHY_TXPCTL_HW: - ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW; - break; - case B43_LPPHY_TXPCTL_SW: - ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW; - break; - default: - ctl = 0; - B43_WARN_ON(1); - } - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, ctl); -} - -static void lpphy_set_tx_power_control(struct b43_wldev *dev, - enum b43_lpphy_txpctl_mode mode) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - enum b43_lpphy_txpctl_mode oldmode; - - lpphy_read_tx_pctl_mode_from_hardware(dev); - oldmode = lpphy->txpctl_mode; - if (oldmode == mode) - return; - lpphy->txpctl_mode = mode; - - if (oldmode == B43_LPPHY_TXPCTL_HW) { - //TODO Update TX Power NPT - //TODO Clear all TX Power offsets - } else { - if (mode == B43_LPPHY_TXPCTL_HW) { - //TODO Recalculate target TX power - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - 0xFF80, lpphy->tssi_idx); - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, - 0x8FFF, ((u16)lpphy->tssi_npt << 16)); - //TODO Set "TSSI Transmit Count" variable to total transmitted frame count - //TODO Disable TX gain override - lpphy->tx_pwr_idx_over = -1; - } - } - if (dev->phy.rev >= 2) { - if (mode == B43_LPPHY_TXPCTL_HW) - b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2); - else - b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD); - } - lpphy_write_tx_pctl_mode_to_hardware(dev); -} - -static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, - unsigned int new_channel); - -static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - struct lpphy_iq_est iq_est; - struct lpphy_tx_gains tx_gains; - static const u32 ideal_pwr_table[21] = { - 0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64, - 0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35, - 0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088, - 0x0004c, 0x0002c, 0x0001a, - }; - bool old_txg_ovr; - u8 old_bbmult; - u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval, - old_rf2_ovr, old_rf2_ovrval, old_phy_ctl; - enum b43_lpphy_txpctl_mode old_txpctl; - u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0; - int loopback, i, j, inner_sum, err; - - memset(&iq_est, 0, sizeof(iq_est)); - - err = b43_lpphy_op_switch_channel(dev, 7); - if (err) { - b43dbg(dev->wl, - "RC calib: Failed to switch to channel 7, error = %d\n", - err); - } - old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40); - old_bbmult = lpphy_get_bb_mult(dev); - if (old_txg_ovr) - tx_gains = lpphy_get_tx_gains(dev); - old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0); - old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0); - old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR); - old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL); - old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2); - old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL); - old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL); - lpphy_read_tx_pctl_mode_from_hardware(dev); - old_txpctl = lpphy->txpctl_mode; - - lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - lpphy_disable_crs(dev, true); - loopback = lpphy_loopback(dev); - if (loopback == -1) - goto finish; - lpphy_set_rx_gain_by_index(dev, loopback); - b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8); - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0); - for (i = 128; i <= 159; i++) { - b43_radio_write(dev, B2062_N_RXBB_CALIB2, i); - inner_sum = 0; - for (j = 5; j <= 25; j++) { - lpphy_run_ddfs(dev, 1, 1, j, j, 0); - if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est))) - goto finish; - mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr; - if (j == 5) - tmp = mean_sq_pwr; - ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1; - normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12); - mean_sq_pwr = ideal_pwr - normal_pwr; - mean_sq_pwr *= mean_sq_pwr; - inner_sum += mean_sq_pwr; - if ((i == 128) || (inner_sum < mean_sq_pwr_min)) { - lpphy->rc_cap = i; - mean_sq_pwr_min = inner_sum; - } - } - } - lpphy_stop_ddfs(dev); - -finish: - lpphy_restore_crs(dev, true); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr); - b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval); - b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval); - b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr); - b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl); - - lpphy_set_bb_mult(dev, old_bbmult); - if (old_txg_ovr) { - /* - * SPEC FIXME: The specs say "get_tx_gains" here, which is - * illogical. According to lwfinger, vendor driver v4.150.10.5 - * has a Set here, while v4.174.64.19 has a Get - regression in - * the vendor driver? This should be tested this once the code - * is testable. - */ - lpphy_set_tx_gains(dev, tx_gains); - } - lpphy_set_tx_power_control(dev, old_txpctl); - if (lpphy->rc_cap) - lpphy_set_rc_cap(dev); -} - -static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; - u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF; - int i; - - b43_radio_write(dev, B2063_RX_BB_SP8, 0x0); - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); - b43_radio_mask(dev, B2063_PLL_SP1, 0xF7); - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); - b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15); - b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70); - b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52); - b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D); - - for (i = 0; i < 10000; i++) { - if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) - break; - msleep(1); - } - - if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) - b43_radio_write(dev, B2063_RX_BB_SP8, tmp); - - tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF; - - b43_radio_write(dev, B2063_TX_BB_SP3, 0x0); - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C); - b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55); - b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76); - - if (crystal_freq == 24000000) { - b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC); - b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0); - } else { - b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13); - b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1); - } - - b43_radio_write(dev, B2063_PA_SP7, 0x7D); - - for (i = 0; i < 10000; i++) { - if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2) - break; - msleep(1); - } - - if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)) - b43_radio_write(dev, B2063_TX_BB_SP3, tmp); - - b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E); -} - -static void lpphy_calibrate_rc(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - - if (dev->phy.rev >= 2) { - lpphy_rev2plus_rc_calib(dev); - } else if (!lpphy->rc_cap) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - lpphy_rev0_1_rc_calib(dev); - } else { - lpphy_set_rc_cap(dev); - } -} - -static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - - lpphy->tx_pwr_idx_over = index; - if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF) - lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW); - - //TODO -} - -static void lpphy_btcoex_override(struct b43_wldev *dev) -{ - b43_write16(dev, B43_MMIO_BTCOEX_CTL, 0x3); - b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF); -} - -static void lpphy_pr41573_workaround(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u32 *saved_tab; - const unsigned int saved_tab_size = 256; - enum b43_lpphy_txpctl_mode txpctl_mode; - s8 tx_pwr_idx_over; - u16 tssi_npt, tssi_idx; - - saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL); - if (!saved_tab) { - b43err(dev->wl, "PR41573 failed. Out of memory!\n"); - return; - } - - lpphy_read_tx_pctl_mode_from_hardware(dev); - txpctl_mode = lpphy->txpctl_mode; - tx_pwr_idx_over = lpphy->tx_pwr_idx_over; - tssi_npt = lpphy->tssi_npt; - tssi_idx = lpphy->tssi_idx; - - if (dev->phy.rev < 2) { - b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140), - saved_tab_size, saved_tab); - } else { - b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140), - saved_tab_size, saved_tab); - } - //TODO - - kfree(saved_tab); -} - -static void lpphy_calibration(struct b43_wldev *dev) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - enum b43_lpphy_txpctl_mode saved_pctl_mode; - - b43_mac_suspend(dev); - - lpphy_btcoex_override(dev); - lpphy_read_tx_pctl_mode_from_hardware(dev); - saved_pctl_mode = lpphy->txpctl_mode; - lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF); - //TODO Perform transmit power table I/Q LO calibration - if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF)) - lpphy_pr41573_workaround(dev); - //TODO If a full calibration has not been performed on this channel yet, perform PAPD TX-power calibration - lpphy_set_tx_power_control(dev, saved_pctl_mode); - //TODO Perform I/Q calibration with a single control value set - - b43_mac_enable(dev); -} - -static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode) -{ - if (mode != TSSI_MUX_EXT) { - b43_radio_set(dev, B2063_PA_SP1, 0x2); - b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000); - b43_radio_write(dev, B2063_PA_CTL10, 0x51); - if (mode == TSSI_MUX_POSTPA) { - b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE); - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7); - } else { - b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1); - b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL, - 0xFFC7, 0x20); - } - } else { - B43_WARN_ON(1); - } -} - -static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev) -{ - u16 tmp; - int i; - - //SPEC TODO Call LP PHY Clear TX Power offsets - for (i = 0; i < 64; i++) { - if (dev->phy.rev >= 2) - b43_lptab_write(dev, B43_LPTAB32(7, i + 1), i); - else - b43_lptab_write(dev, B43_LPTAB32(10, i + 1), i); - } - - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF); - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000); - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F); - if (dev->phy.rev < 2) { - b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF); - b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000); - } else { - b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE); - b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4); - b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10); - b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1); - lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA); - } - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000); - b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF); - b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA); - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, - B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF); - b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF); - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD, - (u16)~B43_LPPHY_TX_PWR_CTL_CMD_MODE, - B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW); - - if (dev->phy.rev < 2) { - b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000); - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF); - } else { - lpphy_set_tx_power_by_index(dev, 0x7F); - } - - b43_dummy_transmission(dev, true, true); - - tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT); - if (tmp & 0x8000) { - b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, - 0xFFC0, (tmp & 0xFF) - 32); - } - - b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF); - - // (SPEC?) TODO Set "Target TX frequency" variable to 0 - // SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8! -} - -static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev) -{ - struct lpphy_tx_gains gains; - - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - gains.gm = 4; - gains.pad = 12; - gains.pga = 12; - gains.dac = 0; - } else { - gains.gm = 7; - gains.pad = 14; - gains.pga = 15; - gains.dac = 0; - } - lpphy_set_tx_gains(dev, gains); - lpphy_set_bb_mult(dev, 150); -} - -/* Initialize TX power control */ -static void lpphy_tx_pctl_init(struct b43_wldev *dev) -{ - if (0/*FIXME HWPCTL capable */) { - lpphy_tx_pctl_init_hw(dev); - } else { /* This device is only software TX power control capable. */ - lpphy_tx_pctl_init_sw(dev); - } -} - -static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - return b43_read16(dev, B43_MMIO_PHY_DATA); -} - -static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, value); -} - -static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask, - u16 set) -{ - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, - (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set); -} - -static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - /* LP-PHY needs a special bit set for read access */ - if (dev->phy.rev < 2) { - if (reg != 0x4001) - reg |= 0x100; - } else - reg |= 0x200; - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); -} - -static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); -} - -static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev, - bool blocked) -{ - //TODO -} - -struct b206x_channel { - u8 channel; - u16 freq; - u8 data[12]; -}; - -static const struct b206x_channel b2062_chantbl[] = { - { .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF, - .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32, - .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, }, - { .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22, - .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11, - .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11, - .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11, - .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11, - .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11, - .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00, - .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77, - .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77, - .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66, - .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66, - .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55, - .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55, - .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44, - .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, }, - { .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44, - .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, - { .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44, - .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77, - .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, }, -}; - -static const struct b206x_channel b2063_chantbl[] = { - { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C, - .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C, - .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C, - .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C, - .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C, - .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C, - .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C, - .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C, - .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C, - .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C, - .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C, - .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C, - .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C, - .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05, - .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x80, .data[11] = 0x70, }, - { .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05, - .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05, - .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, - .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, - .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04, - .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04, - .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03, - .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03, - .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02, - .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60, - .data[10] = 0x20, .data[11] = 0x00, }, - { .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01, - .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, - .data[10] = 0x10, .data[11] = 0x00, }, - { .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01, - .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, - .data[10] = 0x10, .data[11] = 0x00, }, - { .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50, - .data[10] = 0x10, .data[11] = 0x00, }, - { .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00, - .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00, - .data[10] = 0x00, .data[11] = 0x00, }, - { .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0, - .data[10] = 0x50, .data[11] = 0x00, }, - { .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0, - .data[10] = 0x50, .data[11] = 0x00, }, - { .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0, - .data[10] = 0x50, .data[11] = 0x00, }, - { .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, - .data[10] = 0x40, .data[11] = 0x00, }, - { .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, - .data[10] = 0x40, .data[11] = 0x00, }, - { .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0, - .data[10] = 0x40, .data[11] = 0x00, }, - { .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, - .data[10] = 0x40, .data[11] = 0x00, }, - { .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, - .data[10] = 0x40, .data[11] = 0x00, }, - { .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C, - .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08, - .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90, - .data[10] = 0x40, .data[11] = 0x00, }, -}; - -static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - - b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF); - udelay(20); - if (bus->chip_id == 0x5354) { - b43_radio_write(dev, B2062_N_COMM1, 4); - b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4); - } else { - b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0); - } - udelay(5); -} - -static void lpphy_b2062_vco_calib(struct b43_wldev *dev) -{ - b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42); - b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62); - udelay(200); -} - -static int lpphy_b2062_tune(struct b43_wldev *dev, - unsigned int channel) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - struct ssb_bus *bus = dev->dev->bus; - const struct b206x_channel *chandata = NULL; - u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; - u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9; - int i, err = 0; - - for (i = 0; i < ARRAY_SIZE(b2062_chantbl); i++) { - if (b2062_chantbl[i].channel == channel) { - chandata = &b2062_chantbl[i]; - break; - } - } - - if (B43_WARN_ON(!chandata)) - return -EINVAL; - - b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04); - b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]); - b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]); - b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]); - b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]); - b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]); - b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]); - b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]); - b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]); - b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]); - - tmp1 = crystal_freq / 1000; - tmp2 = lpphy->pdiv * 1000; - b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC); - b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07); - lpphy_b2062_reset_pll_bias(dev); - tmp3 = tmp2 * channel2freq_lp(channel); - if (channel2freq_lp(channel) < 4000) - tmp3 *= 2; - tmp4 = 48 * tmp1; - tmp6 = tmp3 / tmp4; - tmp7 = tmp3 % tmp4; - b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6); - tmp5 = tmp7 * 0x100; - tmp6 = tmp5 / tmp4; - tmp7 = tmp5 % tmp4; - b43_radio_write(dev, B2062_S_RFPLL_CTL27, tmp6); - tmp5 = tmp7 * 0x100; - tmp6 = tmp5 / tmp4; - tmp7 = tmp5 % tmp4; - b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6); - tmp5 = tmp7 * 0x100; - tmp6 = tmp5 / tmp4; - tmp7 = tmp5 % tmp4; - b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4)); - tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19); - tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1); - b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16); - b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF); - - lpphy_b2062_vco_calib(dev); - if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) { - b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC); - b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0); - lpphy_b2062_reset_pll_bias(dev); - lpphy_b2062_vco_calib(dev); - if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) - err = -EIO; - } - - b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04); - return err; -} - - -/* This was previously called lpphy_japan_filter */ -static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter! - - if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific? - b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9); - if ((dev->phy.rev == 1) && (lpphy->rc_cap)) - lpphy_set_rc_cap(dev); - } else { - b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F); - } -} - -static void lpphy_b2063_vco_calib(struct b43_wldev *dev) -{ - u16 tmp; - - b43_radio_mask(dev, B2063_PLL_SP1, ~0x40); - tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8; - b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp); - udelay(1); - b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4); - udelay(1); - b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6); - udelay(1); - b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7); - udelay(300); - b43_radio_set(dev, B2063_PLL_SP1, 0x40); -} - -static int lpphy_b2063_tune(struct b43_wldev *dev, - unsigned int channel) -{ - struct ssb_bus *bus = dev->dev->bus; - - static const struct b206x_channel *chandata = NULL; - u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000; - u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count; - u16 old_comm15, scale; - u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6; - int i, div = (crystal_freq <= 26000000 ? 1 : 2); - - for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) { - if (b2063_chantbl[i].channel == channel) { - chandata = &b2063_chantbl[i]; - break; - } - } - - if (B43_WARN_ON(!chandata)) - return -EINVAL; - - b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]); - b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]); - b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]); - b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]); - b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]); - b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]); - b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]); - b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]); - b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]); - b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]); - b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]); - b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]); - - old_comm15 = b43_radio_read(dev, B2063_COMM15); - b43_radio_set(dev, B2063_COMM15, 0x1E); - - if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */ - vco_freq = chandata->freq << 1; - else - vco_freq = chandata->freq << 2; - - freqref = crystal_freq * 3; - val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16); - val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16); - val3 = lpphy_qdiv_roundup(vco_freq, 3, 16); - timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1; - b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2); - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6, - 0xFFF8, timeout >> 2); - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7, - 0xFF9F,timeout << 5); - - timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) + - 999999) / 1000000) + 1; - b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref); - - count = lpphy_qdiv_roundup(val3, val2 + 16, 16); - count *= (timeout + 1) * (timeoutref + 1); - count--; - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7, - 0xF0, count >> 8); - b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF); - - tmp1 = ((val3 * 62500) / freqref) << 4; - tmp2 = ((val3 * 62500) % freqref) << 4; - while (tmp2 >= freqref) { - tmp1++; - tmp2 -= freqref; - } - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4); - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4); - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16); - b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF); - b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF); - - b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9); - b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88); - b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28); - b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63); - - tmp3 = ((41 * (val3 - 3000)) /1200) + 27; - tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16); - - if ((tmp4 + tmp3 - 1) / tmp3 > 60) { - scale = 1; - tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8; - } else { - scale = 0; - tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8; - } - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5); - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6); - - tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16); - tmp6 *= (tmp5 * 8) * (scale + 1); - if (tmp6 > 150) - tmp6 = 0; - - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6); - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5); - - b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4); - if (crystal_freq > 26000000) - b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2); - else - b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD); - - if (val1 == 45) - b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2); - else - b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD); - - b43_radio_set(dev, B2063_PLL_SP2, 0x3); - udelay(1); - b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC); - lpphy_b2063_vco_calib(dev); - b43_radio_write(dev, B2063_COMM15, old_comm15); - - return 0; -} - -static int b43_lpphy_op_switch_channel(struct b43_wldev *dev, - unsigned int new_channel) -{ - struct b43_phy_lp *lpphy = dev->phy.lp; - int err; - - if (dev->phy.radio_ver == 0x2063) { - err = lpphy_b2063_tune(dev, new_channel); - if (err) - return err; - } else { - err = lpphy_b2062_tune(dev, new_channel); - if (err) - return err; - lpphy_set_analog_filter(dev, new_channel); - lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel)); - } - - lpphy->channel = new_channel; - b43_write16(dev, B43_MMIO_CHANNEL, new_channel); - - return 0; -} - -static int b43_lpphy_op_init(struct b43_wldev *dev) -{ - int err; - - lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs? - lpphy_baseband_init(dev); - lpphy_radio_init(dev); - lpphy_calibrate_rc(dev); - err = b43_lpphy_op_switch_channel(dev, 7); - if (err) { - b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n", - err); - } - lpphy_tx_pctl_init(dev); - lpphy_calibration(dev); - //TODO ACI init - - return 0; -} - -static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna) -{ - if (dev->phy.rev >= 2) - return; // rev2+ doesn't support antenna diversity - - if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1)) - return; - - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2); - b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1); -} - -static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev) -{ - //TODO -} - -static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev, - bool ignore_tssi) -{ - //TODO - return B43_TXPWR_RES_DONE; -} - -void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on) -{ - if (on) { - b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8); - } else { - b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007); - b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007); - } -} - -const struct b43_phy_operations b43_phyops_lp = { - .allocate = b43_lpphy_op_allocate, - .free = b43_lpphy_op_free, - .prepare_structs = b43_lpphy_op_prepare_structs, - .init = b43_lpphy_op_init, - .phy_read = b43_lpphy_op_read, - .phy_write = b43_lpphy_op_write, - .phy_maskset = b43_lpphy_op_maskset, - .radio_read = b43_lpphy_op_radio_read, - .radio_write = b43_lpphy_op_radio_write, - .software_rfkill = b43_lpphy_op_software_rfkill, - .switch_analog = b43_lpphy_op_switch_analog, - .switch_channel = b43_lpphy_op_switch_channel, - .get_default_chan = b43_lpphy_op_get_default_chan, - .set_rx_antenna = b43_lpphy_op_set_rx_antenna, - .recalc_txpower = b43_lpphy_op_recalc_txpower, - .adjust_txpower = b43_lpphy_op_adjust_txpower, -}; diff --git a/drivers/net/wireless/b43/phy_lp.h b/drivers/net/wireless/b43/phy_lp.h deleted file mode 100644 index c3232c17b60a..000000000000 --- a/drivers/net/wireless/b43/phy_lp.h +++ /dev/null @@ -1,905 +0,0 @@ -#ifndef LINUX_B43_PHY_LP_H_ -#define LINUX_B43_PHY_LP_H_ - -/* Definitions for the LP-PHY */ - - -/* The CCK PHY register range. */ -#define B43_LPPHY_B_VERSION B43_PHY_CCK(0x00) /* B PHY version */ -#define B43_LPPHY_B_BBCONFIG B43_PHY_CCK(0x01) /* B PHY BBConfig */ -#define B43_LPPHY_B_RX_STAT0 B43_PHY_CCK(0x04) /* B PHY RX Status0 */ -#define B43_LPPHY_B_RX_STAT1 B43_PHY_CCK(0x05) /* B PHY RX Status1 */ -#define B43_LPPHY_B_CRS_THRESH B43_PHY_CCK(0x06) /* B PHY CRS Thresh */ -#define B43_LPPHY_B_TXERROR B43_PHY_CCK(0x07) /* B PHY TxError */ -#define B43_LPPHY_B_CHANNEL B43_PHY_CCK(0x08) /* B PHY Channel */ -#define B43_LPPHY_B_WORKAROUND B43_PHY_CCK(0x09) /* B PHY workaround */ -#define B43_LPPHY_B_TEST B43_PHY_CCK(0x0A) /* B PHY Test */ -#define B43_LPPHY_B_FOURWIRE_ADDR B43_PHY_CCK(0x0B) /* B PHY Fourwire Address */ -#define B43_LPPHY_B_FOURWIRE_DATA_HI B43_PHY_CCK(0x0C) /* B PHY Fourwire Data Hi */ -#define B43_LPPHY_B_FOURWIRE_DATA_LO B43_PHY_CCK(0x0D) /* B PHY Fourwire Data Lo */ -#define B43_LPPHY_B_BIST_STAT B43_PHY_CCK(0x0E) /* B PHY Bist Status */ -#define B43_LPPHY_PA_RAMP_TX_TO B43_PHY_CCK(0x10) /* PA Ramp TX Timeout */ -#define B43_LPPHY_RF_SYNTH_DC_TIMER B43_PHY_CCK(0x11) /* RF Synth DC Timer */ -#define B43_LPPHY_PA_RAMP_TX_TIME_IN B43_PHY_CCK(0x12) /* PA ramp TX Time in */ -#define B43_LPPHY_RX_FILTER_TIME_IN B43_PHY_CCK(0x13) /* RX Filter Time in */ -#define B43_LPPHY_PLL_COEFF_S B43_PHY_CCK(0x18) /* PLL Coefficient(s) */ -#define B43_LPPHY_PLL_OUT B43_PHY_CCK(0x19) /* PLL Out */ -#define B43_LPPHY_RSSI_THRES B43_PHY_CCK(0x20) /* RSSI Threshold */ -#define B43_LPPHY_IQ_THRES_HH B43_PHY_CCK(0x21) /* IQ Threshold HH */ -#define B43_LPPHY_IQ_THRES_H B43_PHY_CCK(0x22) /* IQ Threshold H */ -#define B43_LPPHY_IQ_THRES_L B43_PHY_CCK(0x23) /* IQ Threshold L */ -#define B43_LPPHY_IQ_THRES_LL B43_PHY_CCK(0x24) /* IQ Threshold LL */ -#define B43_LPPHY_AGC_GAIN B43_PHY_CCK(0x25) /* AGC Gain */ -#define B43_LPPHY_LNA_GAIN_RANGE B43_PHY_CCK(0x26) /* LNA Gain Range */ -#define B43_LPPHY_JSSI B43_PHY_CCK(0x27) /* JSSI */ -#define B43_LPPHY_TSSI_CTL B43_PHY_CCK(0x28) /* TSSI Control */ -#define B43_LPPHY_TSSI B43_PHY_CCK(0x29) /* TSSI */ -#define B43_LPPHY_TR_LOSS B43_PHY_CCK(0x2A) /* TR Loss */ -#define B43_LPPHY_LO_LEAKAGE B43_PHY_CCK(0x2B) /* LO Leakage */ -#define B43_LPPHY_LO_RSSIACC B43_PHY_CCK(0x2C) /* LO RSSIAcc */ -#define B43_LPPHY_LO_IQ_MAG_ACC B43_PHY_CCK(0x2D) /* LO IQ Mag Acc */ -#define B43_LPPHY_TX_DCOFFSET1 B43_PHY_CCK(0x2E) /* TX DCOffset1 */ -#define B43_LPPHY_TX_DCOFFSET2 B43_PHY_CCK(0x2F) /* TX DCOffset2 */ -#define B43_LPPHY_SYNCPEAKCNT B43_PHY_CCK(0x30) /* SyncPeakCnt */ -#define B43_LPPHY_SYNCFREQ B43_PHY_CCK(0x31) /* SyncFreq */ -#define B43_LPPHY_SYNCDIVERSITYCTL B43_PHY_CCK(0x32) /* SyncDiversityControl */ -#define B43_LPPHY_PEAKENERGYL B43_PHY_CCK(0x33) /* PeakEnergyL */ -#define B43_LPPHY_PEAKENERGYH B43_PHY_CCK(0x34) /* PeakEnergyH */ -#define B43_LPPHY_SYNCCTL B43_PHY_CCK(0x35) /* SyncControl */ -#define B43_LPPHY_DSSSSTEP B43_PHY_CCK(0x38) /* DsssStep */ -#define B43_LPPHY_DSSSWARMUP B43_PHY_CCK(0x39) /* DsssWarmup */ -#define B43_LPPHY_DSSSSIGPOW B43_PHY_CCK(0x3D) /* DsssSigPow */ -#define B43_LPPHY_SFDDETECTBLOCKTIME B43_PHY_CCK(0x40) /* SfdDetectBlockTIme */ -#define B43_LPPHY_SFDTO B43_PHY_CCK(0x41) /* SFDTimeOut */ -#define B43_LPPHY_SFDCTL B43_PHY_CCK(0x42) /* SFDControl */ -#define B43_LPPHY_RXDBG B43_PHY_CCK(0x43) /* rxDebug */ -#define B43_LPPHY_RX_DELAYCOMP B43_PHY_CCK(0x44) /* RX DelayComp */ -#define B43_LPPHY_CRSDROPOUTTO B43_PHY_CCK(0x45) /* CRSDropoutTimeout */ -#define B43_LPPHY_PSEUDOSHORTTO B43_PHY_CCK(0x46) /* PseudoShortTimeout */ -#define B43_LPPHY_PR3931 B43_PHY_CCK(0x47) /* PR3931 */ -#define B43_LPPHY_DSSSCOEFF1 B43_PHY_CCK(0x48) /* DSSSCoeff1 */ -#define B43_LPPHY_DSSSCOEFF2 B43_PHY_CCK(0x49) /* DSSSCoeff2 */ -#define B43_LPPHY_CCKCOEFF1 B43_PHY_CCK(0x4A) /* CCKCoeff1 */ -#define B43_LPPHY_CCKCOEFF2 B43_PHY_CCK(0x4B) /* CCKCoeff2 */ -#define B43_LPPHY_TRCORR B43_PHY_CCK(0x4C) /* TRCorr */ -#define B43_LPPHY_ANGLESCALE B43_PHY_CCK(0x4D) /* AngleScale */ -#define B43_LPPHY_OPTIONALMODES2 B43_PHY_CCK(0x4F) /* OptionalModes2 */ -#define B43_LPPHY_CCKLMSSTEPSIZE B43_PHY_CCK(0x50) /* CCKLMSStepSize */ -#define B43_LPPHY_DFEBYPASS B43_PHY_CCK(0x51) /* DFEBypass */ -#define B43_LPPHY_CCKSTARTDELAYLONG B43_PHY_CCK(0x52) /* CCKStartDelayLong */ -#define B43_LPPHY_CCKSTARTDELAYSHORT B43_PHY_CCK(0x53) /* CCKStartDelayShort */ -#define B43_LPPHY_PPROCCHDELAY B43_PHY_CCK(0x54) /* PprocChDelay */ -#define B43_LPPHY_PPROCONOFF B43_PHY_CCK(0x55) /* PProcOnOff */ -#define B43_LPPHY_LNAGAINTWOBIT10 B43_PHY_CCK(0x5B) /* LNAGainTwoBit10 */ -#define B43_LPPHY_LNAGAINTWOBIT32 B43_PHY_CCK(0x5C) /* LNAGainTwoBit32 */ -#define B43_LPPHY_OPTIONALMODES B43_PHY_CCK(0x5D) /* OptionalModes */ -#define B43_LPPHY_B_RX_STAT2 B43_PHY_CCK(0x5E) /* B PHY RX Status2 */ -#define B43_LPPHY_B_RX_STAT3 B43_PHY_CCK(0x5F) /* B PHY RX Status3 */ -#define B43_LPPHY_PWDNDACDELAY B43_PHY_CCK(0x63) /* pwdnDacDelay */ -#define B43_LPPHY_FINEDIGIGAIN_CTL B43_PHY_CCK(0x67) /* FineDigiGain Control */ -#define B43_LPPHY_LG2GAINTBLLNA8 B43_PHY_CCK(0x68) /* Lg2GainTblLNA8 */ -#define B43_LPPHY_LG2GAINTBLLNA28 B43_PHY_CCK(0x69) /* Lg2GainTblLNA28 */ -#define B43_LPPHY_GAINTBLLNATRSW B43_PHY_CCK(0x6A) /* GainTblLNATrSw */ -#define B43_LPPHY_PEAKENERGY B43_PHY_CCK(0x6B) /* PeakEnergy */ -#define B43_LPPHY_LG2INITGAIN B43_PHY_CCK(0x6C) /* lg2InitGain */ -#define B43_LPPHY_BLANKCOUNTLNAPGA B43_PHY_CCK(0x6D) /* BlankCountLnaPga */ -#define B43_LPPHY_LNAGAINTWOBIT54 B43_PHY_CCK(0x6E) /* LNAGainTwoBit54 */ -#define B43_LPPHY_LNAGAINTWOBIT76 B43_PHY_CCK(0x6F) /* LNAGainTwoBit76 */ -#define B43_LPPHY_JSSICTL B43_PHY_CCK(0x70) /* JSSIControl */ -#define B43_LPPHY_LG2GAINTBLLNA44 B43_PHY_CCK(0x71) /* Lg2GainTblLNA44 */ -#define B43_LPPHY_LG2GAINTBLLNA62 B43_PHY_CCK(0x72) /* Lg2GainTblLNA62 */ - -/* The OFDM PHY register range. */ -#define B43_LPPHY_VERSION B43_PHY_OFDM(0x00) /* Version */ -#define B43_LPPHY_BBCONFIG B43_PHY_OFDM(0x01) /* BBConfig */ -#define B43_LPPHY_RX_STAT0 B43_PHY_OFDM(0x04) /* RX Status0 */ -#define B43_LPPHY_RX_STAT1 B43_PHY_OFDM(0x05) /* RX Status1 */ -#define B43_LPPHY_TX_ERROR B43_PHY_OFDM(0x07) /* TX Error */ -#define B43_LPPHY_CHANNEL B43_PHY_OFDM(0x08) /* Channel */ -#define B43_LPPHY_WORKAROUND B43_PHY_OFDM(0x09) /* workaround */ -#define B43_LPPHY_FOURWIRE_ADDR B43_PHY_OFDM(0x0B) /* Fourwire Address */ -#define B43_LPPHY_FOURWIREDATAHI B43_PHY_OFDM(0x0C) /* FourwireDataHi */ -#define B43_LPPHY_FOURWIREDATALO B43_PHY_OFDM(0x0D) /* FourwireDataLo */ -#define B43_LPPHY_BISTSTAT0 B43_PHY_OFDM(0x0E) /* BistStatus0 */ -#define B43_LPPHY_BISTSTAT1 B43_PHY_OFDM(0x0F) /* BistStatus1 */ -#define B43_LPPHY_CRSGAIN_CTL B43_PHY_OFDM(0x10) /* crsgain Control */ -#define B43_LPPHY_OFDMPWR_THRESH0 B43_PHY_OFDM(0x11) /* ofdmPower Thresh0 */ -#define B43_LPPHY_OFDMPWR_THRESH1 B43_PHY_OFDM(0x12) /* ofdmPower Thresh1 */ -#define B43_LPPHY_OFDMPWR_THRESH2 B43_PHY_OFDM(0x13) /* ofdmPower Thresh2 */ -#define B43_LPPHY_DSSSPWR_THRESH0 B43_PHY_OFDM(0x14) /* dsssPower Thresh0 */ -#define B43_LPPHY_DSSSPWR_THRESH1 B43_PHY_OFDM(0x15) /* dsssPower Thresh1 */ -#define B43_LPPHY_MINPWR_LEVEL B43_PHY_OFDM(0x16) /* MinPower Level */ -#define B43_LPPHY_OFDMSYNCTHRESH0 B43_PHY_OFDM(0x17) /* ofdmSyncThresh0 */ -#define B43_LPPHY_OFDMSYNCTHRESH1 B43_PHY_OFDM(0x18) /* ofdmSyncThresh1 */ -#define B43_LPPHY_FINEFREQEST B43_PHY_OFDM(0x19) /* FineFreqEst */ -#define B43_LPPHY_IDLEAFTERPKTRXTO B43_PHY_OFDM(0x1A) /* IDLEafterPktRXTimeout */ -#define B43_LPPHY_LTRN_CTL B43_PHY_OFDM(0x1B) /* LTRN Control */ -#define B43_LPPHY_DCOFFSETTRANSIENT B43_PHY_OFDM(0x1C) /* DCOffsetTransient */ -#define B43_LPPHY_PREAMBLEINTO B43_PHY_OFDM(0x1D) /* PreambleInTimeout */ -#define B43_LPPHY_PREAMBLECONFIRMTO B43_PHY_OFDM(0x1E) /* PreambleConfirmTimeout */ -#define B43_LPPHY_CLIPTHRESH B43_PHY_OFDM(0x1F) /* ClipThresh */ -#define B43_LPPHY_CLIPCTRTHRESH B43_PHY_OFDM(0x20) /* ClipCtrThresh */ -#define B43_LPPHY_OFDMSYNCTIMER_CTL B43_PHY_OFDM(0x21) /* ofdmSyncTimer Control */ -#define B43_LPPHY_WAITFORPHYSELTO B43_PHY_OFDM(0x22) /* WaitforPHYSelTimeout */ -#define B43_LPPHY_HIGAINDB B43_PHY_OFDM(0x23) /* HiGainDB */ -#define B43_LPPHY_LOWGAINDB B43_PHY_OFDM(0x24) /* LowGainDB */ -#define B43_LPPHY_VERYLOWGAINDB B43_PHY_OFDM(0x25) /* VeryLowGainDB */ -#define B43_LPPHY_GAINMISMATCH B43_PHY_OFDM(0x26) /* gainMismatch */ -#define B43_LPPHY_GAINDIRECTMISMATCH B43_PHY_OFDM(0x27) /* gaindirectMismatch */ -#define B43_LPPHY_PWR_THRESH0 B43_PHY_OFDM(0x28) /* Power Thresh0 */ -#define B43_LPPHY_PWR_THRESH1 B43_PHY_OFDM(0x29) /* Power Thresh1 */ -#define B43_LPPHY_DETECTOR_DELAY_ADJUST B43_PHY_OFDM(0x2A) /* Detector Delay Adjust */ -#define B43_LPPHY_REDUCED_DETECTOR_DELAY B43_PHY_OFDM(0x2B) /* Reduced Detector Delay */ -#define B43_LPPHY_DATA_TO B43_PHY_OFDM(0x2C) /* data Timeout */ -#define B43_LPPHY_CORRELATOR_DIS_DELAY B43_PHY_OFDM(0x2D) /* correlator Dis Delay */ -#define B43_LPPHY_DIVERSITY_GAINBACK B43_PHY_OFDM(0x2E) /* Diversity GainBack */ -#define B43_LPPHY_DSSS_CONFIRM_CNT B43_PHY_OFDM(0x2F) /* DSSS Confirm Cnt */ -#define B43_LPPHY_DC_BLANK_INT B43_PHY_OFDM(0x30) /* DC Blank Interval */ -#define B43_LPPHY_GAIN_MISMATCH_LIMIT B43_PHY_OFDM(0x31) /* gain Mismatch Limit */ -#define B43_LPPHY_CRS_ED_THRESH B43_PHY_OFDM(0x32) /* crs ed thresh */ -#define B43_LPPHY_PHASE_SHIFT_CTL B43_PHY_OFDM(0x33) /* phase shift Control */ -#define B43_LPPHY_INPUT_PWRDB B43_PHY_OFDM(0x34) /* Input PowerDB */ -#define B43_LPPHY_OFDM_SYNC_CTL B43_PHY_OFDM(0x35) /* ofdm sync Control */ -#define B43_LPPHY_AFE_ADC_CTL_0 B43_PHY_OFDM(0x36) /* Afe ADC Control 0 */ -#define B43_LPPHY_AFE_ADC_CTL_1 B43_PHY_OFDM(0x37) /* Afe ADC Control 1 */ -#define B43_LPPHY_AFE_ADC_CTL_2 B43_PHY_OFDM(0x38) /* Afe ADC Control 2 */ -#define B43_LPPHY_AFE_DAC_CTL B43_PHY_OFDM(0x39) /* Afe DAC Control */ -#define B43_LPPHY_AFE_CTL B43_PHY_OFDM(0x3A) /* Afe Control */ -#define B43_LPPHY_AFE_CTL_OVR B43_PHY_OFDM(0x3B) /* Afe Control Ovr */ -#define B43_LPPHY_AFE_CTL_OVRVAL B43_PHY_OFDM(0x3C) /* Afe Control OvrVal */ -#define B43_LPPHY_AFE_RSSI_CTL_0 B43_PHY_OFDM(0x3D) /* Afe RSSI Control 0 */ -#define B43_LPPHY_AFE_RSSI_CTL_1 B43_PHY_OFDM(0x3E) /* Afe RSSI Control 1 */ -#define B43_LPPHY_AFE_RSSI_SEL B43_PHY_OFDM(0x3F) /* Afe RSSI Sel */ -#define B43_LPPHY_RADAR_THRESH B43_PHY_OFDM(0x40) /* Radar Thresh */ -#define B43_LPPHY_RADAR_BLANK_INT B43_PHY_OFDM(0x41) /* Radar blank Interval */ -#define B43_LPPHY_RADAR_MIN_FM_INT B43_PHY_OFDM(0x42) /* Radar min fm Interval */ -#define B43_LPPHY_RADAR_GAIN_TO B43_PHY_OFDM(0x43) /* Radar gain timeout */ -#define B43_LPPHY_RADAR_PULSE_TO B43_PHY_OFDM(0x44) /* Radar pulse timeout */ -#define B43_LPPHY_RADAR_DETECT_FM_CTL B43_PHY_OFDM(0x45) /* Radar detect FM Control */ -#define B43_LPPHY_RADAR_DETECT_EN B43_PHY_OFDM(0x46) /* Radar detect En */ -#define B43_LPPHY_RADAR_RD_DATA_REG B43_PHY_OFDM(0x47) /* Radar Rd Data Reg */ -#define B43_LPPHY_LP_PHY_CTL B43_PHY_OFDM(0x48) /* LP PHY Control */ -#define B43_LPPHY_CLASSIFIER_CTL B43_PHY_OFDM(0x49) /* classifier Control */ -#define B43_LPPHY_RESET_CTL B43_PHY_OFDM(0x4A) /* reset Control */ -#define B43_LPPHY_CLKEN_CTL B43_PHY_OFDM(0x4B) /* ClkEn Control */ -#define B43_LPPHY_RF_OVERRIDE_0 B43_PHY_OFDM(0x4C) /* RF Override 0 */ -#define B43_LPPHY_RF_OVERRIDE_VAL_0 B43_PHY_OFDM(0x4D) /* RF Override Val 0 */ -#define B43_LPPHY_TR_LOOKUP_1 B43_PHY_OFDM(0x4E) /* TR Lookup 1 */ -#define B43_LPPHY_TR_LOOKUP_2 B43_PHY_OFDM(0x4F) /* TR Lookup 2 */ -#define B43_LPPHY_RSSISELLOOKUP1 B43_PHY_OFDM(0x50) /* RssiSelLookup1 */ -#define B43_LPPHY_IQLO_CAL_CMD B43_PHY_OFDM(0x51) /* iqlo Cal Cmd */ -#define B43_LPPHY_IQLO_CAL_CMD_N_NUM B43_PHY_OFDM(0x52) /* iqlo Cal Cmd N num */ -#define B43_LPPHY_IQLO_CAL_CMD_G_CTL B43_PHY_OFDM(0x53) /* iqlo Cal Cmd G control */ -#define B43_LPPHY_MACINT_DBG_REGISTER B43_PHY_OFDM(0x54) /* macint Debug Register */ -#define B43_LPPHY_TABLE_ADDR B43_PHY_OFDM(0x55) /* Table Address */ -#define B43_LPPHY_TABLEDATALO B43_PHY_OFDM(0x56) /* TabledataLo */ -#define B43_LPPHY_TABLEDATAHI B43_PHY_OFDM(0x57) /* TabledataHi */ -#define B43_LPPHY_PHY_CRS_ENABLE_ADDR B43_PHY_OFDM(0x58) /* phy CRS Enable Address */ -#define B43_LPPHY_IDLETIME_CTL B43_PHY_OFDM(0x59) /* Idletime Control */ -#define B43_LPPHY_IDLETIME_CRS_ON_LO B43_PHY_OFDM(0x5A) /* Idletime CRS On Lo */ -#define B43_LPPHY_IDLETIME_CRS_ON_HI B43_PHY_OFDM(0x5B) /* Idletime CRS On Hi */ -#define B43_LPPHY_IDLETIME_MEAS_TIME_LO B43_PHY_OFDM(0x5C) /* Idletime Meas Time Lo */ -#define B43_LPPHY_IDLETIME_MEAS_TIME_HI B43_PHY_OFDM(0x5D) /* Idletime Meas Time Hi */ -#define B43_LPPHY_RESET_LEN_OFDM_TX_ADDR B43_PHY_OFDM(0x5E) /* Reset len Ofdm TX Address */ -#define B43_LPPHY_RESET_LEN_OFDM_RX_ADDR B43_PHY_OFDM(0x5F) /* Reset len Ofdm RX Address */ -#define B43_LPPHY_REG_CRS_ENABLE B43_PHY_OFDM(0x60) /* reg crs enable */ -#define B43_LPPHY_PLCP_TMT_STR0_CTR_MIN B43_PHY_OFDM(0x61) /* PLCP Tmt Str0 Ctr Min */ -#define B43_LPPHY_PKT_FSM_RESET_LEN_VAL B43_PHY_OFDM(0x62) /* Pkt fsm Reset Len Value */ -#define B43_LPPHY_READSYM2RESET_CTL B43_PHY_OFDM(0x63) /* readsym2reset Control */ -#define B43_LPPHY_DC_FILTER_DELAY1 B43_PHY_OFDM(0x64) /* Dc filter delay1 */ -#define B43_LPPHY_PACKET_RX_ACTIVE_TO B43_PHY_OFDM(0x65) /* packet rx Active timeout */ -#define B43_LPPHY_ED_TOVAL B43_PHY_OFDM(0x66) /* ed timeoutValue */ -#define B43_LPPHY_HOLD_CRS_ON_VAL B43_PHY_OFDM(0x67) /* hold CRS On Value */ -#define B43_LPPHY_OFDM_TX_PHY_CRS_DELAY_VAL B43_PHY_OFDM(0x69) /* ofdm tx phy CRS Delay Value */ -#define B43_LPPHY_CCK_TX_PHY_CRS_DELAY_VAL B43_PHY_OFDM(0x6A) /* cck tx phy CRS Delay Value */ -#define B43_LPPHY_ED_ON_CONFIRM_TIMER_VAL B43_PHY_OFDM(0x6B) /* Ed on confirm Timer Value */ -#define B43_LPPHY_ED_OFFSET_CONFIRM_TIMER_VAL B43_PHY_OFDM(0x6C) /* Ed offset confirm Timer Value */ -#define B43_LPPHY_PHY_CRS_OFFSET_TIMER_VAL B43_PHY_OFDM(0x6D) /* phy CRS offset Timer Value */ -#define B43_LPPHY_ADC_COMPENSATION_CTL B43_PHY_OFDM(0x70) /* ADC Compensation Control */ -#define B43_LPPHY_LOG2_RBPSK_ADDR B43_PHY_OFDM(0x71) /* log2 RBPSK Address */ -#define B43_LPPHY_LOG2_RQPSK_ADDR B43_PHY_OFDM(0x72) /* log2 RQPSK Address */ -#define B43_LPPHY_LOG2_R16QAM_ADDR B43_PHY_OFDM(0x73) /* log2 R16QAM Address */ -#define B43_LPPHY_LOG2_R64QAM_ADDR B43_PHY_OFDM(0x74) /* log2 R64QAM Address */ -#define B43_LPPHY_OFFSET_BPSK_ADDR B43_PHY_OFDM(0x75) /* offset BPSK Address */ -#define B43_LPPHY_OFFSET_QPSK_ADDR B43_PHY_OFDM(0x76) /* offset QPSK Address */ -#define B43_LPPHY_OFFSET_16QAM_ADDR B43_PHY_OFDM(0x77) /* offset 16QAM Address */ -#define B43_LPPHY_OFFSET_64QAM_ADDR B43_PHY_OFDM(0x78) /* offset 64QAM Address */ -#define B43_LPPHY_ALPHA1 B43_PHY_OFDM(0x79) /* Alpha1 */ -#define B43_LPPHY_ALPHA2 B43_PHY_OFDM(0x7A) /* Alpha2 */ -#define B43_LPPHY_BETA1 B43_PHY_OFDM(0x7B) /* Beta1 */ -#define B43_LPPHY_BETA2 B43_PHY_OFDM(0x7C) /* Beta2 */ -#define B43_LPPHY_LOOP_NUM_ADDR B43_PHY_OFDM(0x7D) /* Loop Num Address */ -#define B43_LPPHY_STR_COLLMAX_SMPL_ADDR B43_PHY_OFDM(0x7E) /* Str Collmax Sample Address */ -#define B43_LPPHY_MAX_SMPL_COARSE_FINE_ADDR B43_PHY_OFDM(0x7F) /* Max Sample Coarse/Fine Address */ -#define B43_LPPHY_MAX_SMPL_COARSE_STR0CTR_ADDR B43_PHY_OFDM(0x80) /* Max Sample Coarse/Str0Ctr Address */ -#define B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR B43_PHY_OFDM(0x81) /* IQ Enable Wait Time Address */ -#define B43_LPPHY_IQ_NUM_SMPLS_ADDR B43_PHY_OFDM(0x82) /* IQ Num Samples Address */ -#define B43_LPPHY_IQ_ACC_HI_ADDR B43_PHY_OFDM(0x83) /* IQ Acc Hi Address */ -#define B43_LPPHY_IQ_ACC_LO_ADDR B43_PHY_OFDM(0x84) /* IQ Acc Lo Address */ -#define B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR B43_PHY_OFDM(0x85) /* IQ I PWR Acc Hi Address */ -#define B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR B43_PHY_OFDM(0x86) /* IQ I PWR Acc Lo Address */ -#define B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR B43_PHY_OFDM(0x87) /* IQ Q PWR Acc Hi Address */ -#define B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR B43_PHY_OFDM(0x88) /* IQ Q PWR Acc Lo Address */ -#define B43_LPPHY_MAXNUMSTEPS B43_PHY_OFDM(0x89) /* MaxNumsteps */ -#define B43_LPPHY_ROTORPHASE_ADDR B43_PHY_OFDM(0x8A) /* RotorPhase Address */ -#define B43_LPPHY_ADVANCEDRETARDROTOR_ADDR B43_PHY_OFDM(0x8B) /* AdvancedRetardRotor Address */ -#define B43_LPPHY_RSSIADCDELAY_CTL_ADDR B43_PHY_OFDM(0x8D) /* rssiAdcdelay Control Address */ -#define B43_LPPHY_TSSISTAT_ADDR B43_PHY_OFDM(0x8E) /* tssiStatus Address */ -#define B43_LPPHY_TEMPSENSESTAT_ADDR B43_PHY_OFDM(0x8F) /* tempsenseStatus Address */ -#define B43_LPPHY_TEMPSENSE_CTL_ADDR B43_PHY_OFDM(0x90) /* tempsense Control Address */ -#define B43_LPPHY_WRSSISTAT_ADDR B43_PHY_OFDM(0x91) /* wrssistatus Address */ -#define B43_LPPHY_MUFACTORADDR B43_PHY_OFDM(0x92) /* mufactoraddr */ -#define B43_LPPHY_SCRAMSTATE_ADDR B43_PHY_OFDM(0x93) /* scramstate Address */ -#define B43_LPPHY_TXHOLDOFFADDR B43_PHY_OFDM(0x94) /* txholdoffaddr */ -#define B43_LPPHY_PKTGAINVAL_ADDR B43_PHY_OFDM(0x95) /* pktgainval Address */ -#define B43_LPPHY_COARSEESTIM_ADDR B43_PHY_OFDM(0x96) /* Coarseestim Address */ -#define B43_LPPHY_STATE_TRANSITION_ADDR B43_PHY_OFDM(0x97) /* state Transition Address */ -#define B43_LPPHY_TRN_OFFSET_ADDR B43_PHY_OFDM(0x98) /* TRN offset Address */ -#define B43_LPPHY_NUM_ROTOR_ADDR B43_PHY_OFDM(0x99) /* Num Rotor Address */ -#define B43_LPPHY_VITERBI_OFFSET_ADDR B43_PHY_OFDM(0x9A) /* Viterbi Offset Address */ -#define B43_LPPHY_SMPL_COLLECT_WAIT_ADDR B43_PHY_OFDM(0x9B) /* Sample collect wait Address */ -#define B43_LPPHY_A_PHY_CTL_ADDR B43_PHY_OFDM(0x9C) /* A PHY Control Address */ -#define B43_LPPHY_NUM_PASS_THROUGH_ADDR B43_PHY_OFDM(0x9D) /* Num Pass Through Address */ -#define B43_LPPHY_RX_COMP_COEFF_S B43_PHY_OFDM(0x9E) /* RX Comp coefficient(s) */ -#define B43_LPPHY_CPAROTATEVAL B43_PHY_OFDM(0x9F) /* cpaRotateValue */ -#define B43_LPPHY_SMPL_PLAY_COUNT B43_PHY_OFDM(0xA0) /* Sample play count */ -#define B43_LPPHY_SMPL_PLAY_BUFFER_CTL B43_PHY_OFDM(0xA1) /* Sample play Buffer Control */ -#define B43_LPPHY_FOURWIRE_CTL B43_PHY_OFDM(0xA2) /* fourwire Control */ -#define B43_LPPHY_CPA_TAILCOUNT_VAL B43_PHY_OFDM(0xA3) /* CPA TailCount Value */ -#define B43_LPPHY_TX_PWR_CTL_CMD B43_PHY_OFDM(0xA4) /* TX Power Control Cmd */ -#define B43_LPPHY_TX_PWR_CTL_CMD_MODE 0xE000 /* TX power control mode mask */ -#define B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF 0x0000 /* TX power control is OFF */ -#define B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW 0x8000 /* TX power control is SOFTWARE */ -#define B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW 0xE000 /* TX power control is HARDWARE */ -#define B43_LPPHY_TX_PWR_CTL_NNUM B43_PHY_OFDM(0xA5) /* TX Power Control Nnum */ -#define B43_LPPHY_TX_PWR_CTL_IDLETSSI B43_PHY_OFDM(0xA6) /* TX Power Control IdleTssi */ -#define B43_LPPHY_TX_PWR_CTL_TARGETPWR B43_PHY_OFDM(0xA7) /* TX Power Control TargetPower */ -#define B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT B43_PHY_OFDM(0xA8) /* TX Power Control DeltaPower Limit */ -#define B43_LPPHY_TX_PWR_CTL_BASEINDEX B43_PHY_OFDM(0xA9) /* TX Power Control BaseIndex */ -#define B43_LPPHY_TX_PWR_CTL_PWR_INDEX B43_PHY_OFDM(0xAA) /* TX Power Control Power Index */ -#define B43_LPPHY_TX_PWR_CTL_STAT B43_PHY_OFDM(0xAB) /* TX Power Control Status */ -#define B43_LPPHY_LP_RF_SIGNAL_LUT B43_PHY_OFDM(0xAC) /* LP RF signal LUT */ -#define B43_LPPHY_RX_RADIO_CTL_FILTER_STATE B43_PHY_OFDM(0xAD) /* RX Radio Control Filter State */ -#define B43_LPPHY_RX_RADIO_CTL B43_PHY_OFDM(0xAE) /* RX Radio Control */ -#define B43_LPPHY_NRSSI_STAT_ADDR B43_PHY_OFDM(0xAF) /* NRSSI status Address */ -#define B43_LPPHY_RF_OVERRIDE_2 B43_PHY_OFDM(0xB0) /* RF override 2 */ -#define B43_LPPHY_RF_OVERRIDE_2_VAL B43_PHY_OFDM(0xB1) /* RF override 2 val */ -#define B43_LPPHY_PS_CTL_OVERRIDE_VAL0 B43_PHY_OFDM(0xB2) /* PS Control override val0 */ -#define B43_LPPHY_PS_CTL_OVERRIDE_VAL1 B43_PHY_OFDM(0xB3) /* PS Control override val1 */ -#define B43_LPPHY_PS_CTL_OVERRIDE_VAL2 B43_PHY_OFDM(0xB4) /* PS Control override val2 */ -#define B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL B43_PHY_OFDM(0xB5) /* TX gain Control override val */ -#define B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL B43_PHY_OFDM(0xB6) /* RX gain Control override val */ -#define B43_LPPHY_AFE_DDFS B43_PHY_OFDM(0xB7) /* AFE DDFS */ -#define B43_LPPHY_AFE_DDFS_POINTER_INIT B43_PHY_OFDM(0xB8) /* AFE DDFS pointer init */ -#define B43_LPPHY_AFE_DDFS_INCR_INIT B43_PHY_OFDM(0xB9) /* AFE DDFS incr init */ -#define B43_LPPHY_MRCNOISEREDUCTION B43_PHY_OFDM(0xBA) /* mrcNoiseReduction */ -#define B43_LPPHY_TR_LOOKUP_3 B43_PHY_OFDM(0xBB) /* TR Lookup 3 */ -#define B43_LPPHY_TR_LOOKUP_4 B43_PHY_OFDM(0xBC) /* TR Lookup 4 */ -#define B43_LPPHY_RADAR_FIFO_STAT B43_PHY_OFDM(0xBD) /* Radar FIFO Status */ -#define B43_LPPHY_GPIO_OUTEN B43_PHY_OFDM(0xBE) /* GPIO Out enable */ -#define B43_LPPHY_GPIO_SELECT B43_PHY_OFDM(0xBF) /* GPIO Select */ -#define B43_LPPHY_GPIO_OUT B43_PHY_OFDM(0xC0) /* GPIO Out */ -#define B43_LPPHY_4C3 B43_PHY_OFDM(0xC3) /* unknown, used during BB init */ -#define B43_LPPHY_4C4 B43_PHY_OFDM(0xC4) /* unknown, used during BB init */ -#define B43_LPPHY_4C5 B43_PHY_OFDM(0xC5) /* unknown, used during BB init */ -#define B43_LPPHY_TR_LOOKUP_5 B43_PHY_OFDM(0xC7) /* TR Lookup 5 */ -#define B43_LPPHY_TR_LOOKUP_6 B43_PHY_OFDM(0xC8) /* TR Lookup 6 */ -#define B43_LPPHY_TR_LOOKUP_7 B43_PHY_OFDM(0xC9) /* TR Lookup 7 */ -#define B43_LPPHY_TR_LOOKUP_8 B43_PHY_OFDM(0xCA) /* TR Lookup 8 */ - - - -/* Radio register access decorators. */ -#define B43_LP_RADIO(radio_reg) (radio_reg) -#define B43_LP_NORTH(radio_reg) B43_LP_RADIO(radio_reg) -#define B43_LP_SOUTH(radio_reg) B43_LP_RADIO((radio_reg) | 0x4000) - - -/*** Broadcom 2062 NORTH radio registers ***/ -#define B2062_N_COMM1 B43_LP_NORTH(0x000) /* Common 01 (north) */ -#define B2062_N_COMM2 B43_LP_NORTH(0x002) /* Common 02 (north) */ -#define B2062_N_COMM3 B43_LP_NORTH(0x003) /* Common 03 (north) */ -#define B2062_N_COMM4 B43_LP_NORTH(0x004) /* Common 04 (north) */ -#define B2062_N_COMM5 B43_LP_NORTH(0x005) /* Common 05 (north) */ -#define B2062_N_COMM6 B43_LP_NORTH(0x006) /* Common 06 (north) */ -#define B2062_N_COMM7 B43_LP_NORTH(0x007) /* Common 07 (north) */ -#define B2062_N_COMM8 B43_LP_NORTH(0x008) /* Common 08 (north) */ -#define B2062_N_COMM9 B43_LP_NORTH(0x009) /* Common 09 (north) */ -#define B2062_N_COMM10 B43_LP_NORTH(0x00A) /* Common 10 (north) */ -#define B2062_N_COMM11 B43_LP_NORTH(0x00B) /* Common 11 (north) */ -#define B2062_N_COMM12 B43_LP_NORTH(0x00C) /* Common 12 (north) */ -#define B2062_N_COMM13 B43_LP_NORTH(0x00D) /* Common 13 (north) */ -#define B2062_N_COMM14 B43_LP_NORTH(0x00E) /* Common 14 (north) */ -#define B2062_N_COMM15 B43_LP_NORTH(0x00F) /* Common 15 (north) */ -#define B2062_N_PDN_CTL0 B43_LP_NORTH(0x010) /* PDN Control 0 (north) */ -#define B2062_N_PDN_CTL1 B43_LP_NORTH(0x011) /* PDN Control 1 (north) */ -#define B2062_N_PDN_CTL2 B43_LP_NORTH(0x012) /* PDN Control 2 (north) */ -#define B2062_N_PDN_CTL3 B43_LP_NORTH(0x013) /* PDN Control 3 (north) */ -#define B2062_N_PDN_CTL4 B43_LP_NORTH(0x014) /* PDN Control 4 (north) */ -#define B2062_N_GEN_CTL0 B43_LP_NORTH(0x015) /* GEN Control 0 (north) */ -#define B2062_N_IQ_CALIB B43_LP_NORTH(0x016) /* IQ Calibration (north) */ -#define B2062_N_LGENC B43_LP_NORTH(0x017) /* LGENC (north) */ -#define B2062_N_LGENA_LPF B43_LP_NORTH(0x018) /* LGENA LPF (north) */ -#define B2062_N_LGENA_BIAS0 B43_LP_NORTH(0x019) /* LGENA Bias 0 (north) */ -#define B2062_N_LGNEA_BIAS1 B43_LP_NORTH(0x01A) /* LGNEA Bias 1 (north) */ -#define B2062_N_LGENA_CTL0 B43_LP_NORTH(0x01B) /* LGENA Control 0 (north) */ -#define B2062_N_LGENA_CTL1 B43_LP_NORTH(0x01C) /* LGENA Control 1 (north) */ -#define B2062_N_LGENA_CTL2 B43_LP_NORTH(0x01D) /* LGENA Control 2 (north) */ -#define B2062_N_LGENA_TUNE0 B43_LP_NORTH(0x01E) /* LGENA Tune 0 (north) */ -#define B2062_N_LGENA_TUNE1 B43_LP_NORTH(0x01F) /* LGENA Tune 1 (north) */ -#define B2062_N_LGENA_TUNE2 B43_LP_NORTH(0x020) /* LGENA Tune 2 (north) */ -#define B2062_N_LGENA_TUNE3 B43_LP_NORTH(0x021) /* LGENA Tune 3 (north) */ -#define B2062_N_LGENA_CTL3 B43_LP_NORTH(0x022) /* LGENA Control 3 (north) */ -#define B2062_N_LGENA_CTL4 B43_LP_NORTH(0x023) /* LGENA Control 4 (north) */ -#define B2062_N_LGENA_CTL5 B43_LP_NORTH(0x024) /* LGENA Control 5 (north) */ -#define B2062_N_LGENA_CTL6 B43_LP_NORTH(0x025) /* LGENA Control 6 (north) */ -#define B2062_N_LGENA_CTL7 B43_LP_NORTH(0x026) /* LGENA Control 7 (north) */ -#define B2062_N_RXA_CTL0 B43_LP_NORTH(0x027) /* RXA Control 0 (north) */ -#define B2062_N_RXA_CTL1 B43_LP_NORTH(0x028) /* RXA Control 1 (north) */ -#define B2062_N_RXA_CTL2 B43_LP_NORTH(0x029) /* RXA Control 2 (north) */ -#define B2062_N_RXA_CTL3 B43_LP_NORTH(0x02A) /* RXA Control 3 (north) */ -#define B2062_N_RXA_CTL4 B43_LP_NORTH(0x02B) /* RXA Control 4 (north) */ -#define B2062_N_RXA_CTL5 B43_LP_NORTH(0x02C) /* RXA Control 5 (north) */ -#define B2062_N_RXA_CTL6 B43_LP_NORTH(0x02D) /* RXA Control 6 (north) */ -#define B2062_N_RXA_CTL7 B43_LP_NORTH(0x02E) /* RXA Control 7 (north) */ -#define B2062_N_RXBB_CTL0 B43_LP_NORTH(0x02F) /* RXBB Control 0 (north) */ -#define B2062_N_RXBB_CTL1 B43_LP_NORTH(0x030) /* RXBB Control 1 (north) */ -#define B2062_N_RXBB_CTL2 B43_LP_NORTH(0x031) /* RXBB Control 2 (north) */ -#define B2062_N_RXBB_GAIN0 B43_LP_NORTH(0x032) /* RXBB Gain 0 (north) */ -#define B2062_N_RXBB_GAIN1 B43_LP_NORTH(0x033) /* RXBB Gain 1 (north) */ -#define B2062_N_RXBB_GAIN2 B43_LP_NORTH(0x034) /* RXBB Gain 2 (north) */ -#define B2062_N_RXBB_GAIN3 B43_LP_NORTH(0x035) /* RXBB Gain 3 (north) */ -#define B2062_N_RXBB_RSSI0 B43_LP_NORTH(0x036) /* RXBB RSSI 0 (north) */ -#define B2062_N_RXBB_RSSI1 B43_LP_NORTH(0x037) /* RXBB RSSI 1 (north) */ -#define B2062_N_RXBB_CALIB0 B43_LP_NORTH(0x038) /* RXBB Calibration0 (north) */ -#define B2062_N_RXBB_CALIB1 B43_LP_NORTH(0x039) /* RXBB Calibration1 (north) */ -#define B2062_N_RXBB_CALIB2 B43_LP_NORTH(0x03A) /* RXBB Calibration2 (north) */ -#define B2062_N_RXBB_BIAS0 B43_LP_NORTH(0x03B) /* RXBB Bias 0 (north) */ -#define B2062_N_RXBB_BIAS1 B43_LP_NORTH(0x03C) /* RXBB Bias 1 (north) */ -#define B2062_N_RXBB_BIAS2 B43_LP_NORTH(0x03D) /* RXBB Bias 2 (north) */ -#define B2062_N_RXBB_BIAS3 B43_LP_NORTH(0x03E) /* RXBB Bias 3 (north) */ -#define B2062_N_RXBB_BIAS4 B43_LP_NORTH(0x03F) /* RXBB Bias 4 (north) */ -#define B2062_N_RXBB_BIAS5 B43_LP_NORTH(0x040) /* RXBB Bias 5 (north) */ -#define B2062_N_RXBB_RSSI2 B43_LP_NORTH(0x041) /* RXBB RSSI 2 (north) */ -#define B2062_N_RXBB_RSSI3 B43_LP_NORTH(0x042) /* RXBB RSSI 3 (north) */ -#define B2062_N_RXBB_RSSI4 B43_LP_NORTH(0x043) /* RXBB RSSI 4 (north) */ -#define B2062_N_RXBB_RSSI5 B43_LP_NORTH(0x044) /* RXBB RSSI 5 (north) */ -#define B2062_N_TX_CTL0 B43_LP_NORTH(0x045) /* TX Control 0 (north) */ -#define B2062_N_TX_CTL1 B43_LP_NORTH(0x046) /* TX Control 1 (north) */ -#define B2062_N_TX_CTL2 B43_LP_NORTH(0x047) /* TX Control 2 (north) */ -#define B2062_N_TX_CTL3 B43_LP_NORTH(0x048) /* TX Control 3 (north) */ -#define B2062_N_TX_CTL4 B43_LP_NORTH(0x049) /* TX Control 4 (north) */ -#define B2062_N_TX_CTL5 B43_LP_NORTH(0x04A) /* TX Control 5 (north) */ -#define B2062_N_TX_CTL6 B43_LP_NORTH(0x04B) /* TX Control 6 (north) */ -#define B2062_N_TX_CTL7 B43_LP_NORTH(0x04C) /* TX Control 7 (north) */ -#define B2062_N_TX_CTL8 B43_LP_NORTH(0x04D) /* TX Control 8 (north) */ -#define B2062_N_TX_CTL9 B43_LP_NORTH(0x04E) /* TX Control 9 (north) */ -#define B2062_N_TX_CTL_A B43_LP_NORTH(0x04F) /* TX Control A (north) */ -#define B2062_N_TX_GC2G B43_LP_NORTH(0x050) /* TX GC2G (north) */ -#define B2062_N_TX_GC5G B43_LP_NORTH(0x051) /* TX GC5G (north) */ -#define B2062_N_TX_TUNE B43_LP_NORTH(0x052) /* TX Tune (north) */ -#define B2062_N_TX_PAD B43_LP_NORTH(0x053) /* TX PAD (north) */ -#define B2062_N_TX_PGA B43_LP_NORTH(0x054) /* TX PGA (north) */ -#define B2062_N_TX_PADAUX B43_LP_NORTH(0x055) /* TX PADAUX (north) */ -#define B2062_N_TX_PGAAUX B43_LP_NORTH(0x056) /* TX PGAAUX (north) */ -#define B2062_N_TSSI_CTL0 B43_LP_NORTH(0x057) /* TSSI Control 0 (north) */ -#define B2062_N_TSSI_CTL1 B43_LP_NORTH(0x058) /* TSSI Control 1 (north) */ -#define B2062_N_TSSI_CTL2 B43_LP_NORTH(0x059) /* TSSI Control 2 (north) */ -#define B2062_N_IQ_CALIB_CTL0 B43_LP_NORTH(0x05A) /* IQ Calibration Control 0 (north) */ -#define B2062_N_IQ_CALIB_CTL1 B43_LP_NORTH(0x05B) /* IQ Calibration Control 1 (north) */ -#define B2062_N_IQ_CALIB_CTL2 B43_LP_NORTH(0x05C) /* IQ Calibration Control 2 (north) */ -#define B2062_N_CALIB_TS B43_LP_NORTH(0x05D) /* Calibration TS (north) */ -#define B2062_N_CALIB_CTL0 B43_LP_NORTH(0x05E) /* Calibration Control 0 (north) */ -#define B2062_N_CALIB_CTL1 B43_LP_NORTH(0x05F) /* Calibration Control 1 (north) */ -#define B2062_N_CALIB_CTL2 B43_LP_NORTH(0x060) /* Calibration Control 2 (north) */ -#define B2062_N_CALIB_CTL3 B43_LP_NORTH(0x061) /* Calibration Control 3 (north) */ -#define B2062_N_CALIB_CTL4 B43_LP_NORTH(0x062) /* Calibration Control 4 (north) */ -#define B2062_N_CALIB_DBG0 B43_LP_NORTH(0x063) /* Calibration Debug 0 (north) */ -#define B2062_N_CALIB_DBG1 B43_LP_NORTH(0x064) /* Calibration Debug 1 (north) */ -#define B2062_N_CALIB_DBG2 B43_LP_NORTH(0x065) /* Calibration Debug 2 (north) */ -#define B2062_N_CALIB_DBG3 B43_LP_NORTH(0x066) /* Calibration Debug 3 (north) */ -#define B2062_N_PSENSE_CTL0 B43_LP_NORTH(0x069) /* PSENSE Control 0 (north) */ -#define B2062_N_PSENSE_CTL1 B43_LP_NORTH(0x06A) /* PSENSE Control 1 (north) */ -#define B2062_N_PSENSE_CTL2 B43_LP_NORTH(0x06B) /* PSENSE Control 2 (north) */ -#define B2062_N_TEST_BUF0 B43_LP_NORTH(0x06C) /* TEST BUF0 (north) */ - -/*** Broadcom 2062 SOUTH radio registers ***/ -#define B2062_S_COMM1 B43_LP_SOUTH(0x000) /* Common 01 (south) */ -#define B2062_S_RADIO_ID_CODE B43_LP_SOUTH(0x001) /* Radio ID code (south) */ -#define B2062_S_COMM2 B43_LP_SOUTH(0x002) /* Common 02 (south) */ -#define B2062_S_COMM3 B43_LP_SOUTH(0x003) /* Common 03 (south) */ -#define B2062_S_COMM4 B43_LP_SOUTH(0x004) /* Common 04 (south) */ -#define B2062_S_COMM5 B43_LP_SOUTH(0x005) /* Common 05 (south) */ -#define B2062_S_COMM6 B43_LP_SOUTH(0x006) /* Common 06 (south) */ -#define B2062_S_COMM7 B43_LP_SOUTH(0x007) /* Common 07 (south) */ -#define B2062_S_COMM8 B43_LP_SOUTH(0x008) /* Common 08 (south) */ -#define B2062_S_COMM9 B43_LP_SOUTH(0x009) /* Common 09 (south) */ -#define B2062_S_COMM10 B43_LP_SOUTH(0x00A) /* Common 10 (south) */ -#define B2062_S_COMM11 B43_LP_SOUTH(0x00B) /* Common 11 (south) */ -#define B2062_S_COMM12 B43_LP_SOUTH(0x00C) /* Common 12 (south) */ -#define B2062_S_COMM13 B43_LP_SOUTH(0x00D) /* Common 13 (south) */ -#define B2062_S_COMM14 B43_LP_SOUTH(0x00E) /* Common 14 (south) */ -#define B2062_S_COMM15 B43_LP_SOUTH(0x00F) /* Common 15 (south) */ -#define B2062_S_PDS_CTL0 B43_LP_SOUTH(0x010) /* PDS Control 0 (south) */ -#define B2062_S_PDS_CTL1 B43_LP_SOUTH(0x011) /* PDS Control 1 (south) */ -#define B2062_S_PDS_CTL2 B43_LP_SOUTH(0x012) /* PDS Control 2 (south) */ -#define B2062_S_PDS_CTL3 B43_LP_SOUTH(0x013) /* PDS Control 3 (south) */ -#define B2062_S_BG_CTL0 B43_LP_SOUTH(0x014) /* BG Control 0 (south) */ -#define B2062_S_BG_CTL1 B43_LP_SOUTH(0x015) /* BG Control 1 (south) */ -#define B2062_S_BG_CTL2 B43_LP_SOUTH(0x016) /* BG Control 2 (south) */ -#define B2062_S_LGENG_CTL0 B43_LP_SOUTH(0x017) /* LGENG Control 00 (south) */ -#define B2062_S_LGENG_CTL1 B43_LP_SOUTH(0x018) /* LGENG Control 01 (south) */ -#define B2062_S_LGENG_CTL2 B43_LP_SOUTH(0x019) /* LGENG Control 02 (south) */ -#define B2062_S_LGENG_CTL3 B43_LP_SOUTH(0x01A) /* LGENG Control 03 (south) */ -#define B2062_S_LGENG_CTL4 B43_LP_SOUTH(0x01B) /* LGENG Control 04 (south) */ -#define B2062_S_LGENG_CTL5 B43_LP_SOUTH(0x01C) /* LGENG Control 05 (south) */ -#define B2062_S_LGENG_CTL6 B43_LP_SOUTH(0x01D) /* LGENG Control 06 (south) */ -#define B2062_S_LGENG_CTL7 B43_LP_SOUTH(0x01E) /* LGENG Control 07 (south) */ -#define B2062_S_LGENG_CTL8 B43_LP_SOUTH(0x01F) /* LGENG Control 08 (south) */ -#define B2062_S_LGENG_CTL9 B43_LP_SOUTH(0x020) /* LGENG Control 09 (south) */ -#define B2062_S_LGENG_CTL10 B43_LP_SOUTH(0x021) /* LGENG Control 10 (south) */ -#define B2062_S_LGENG_CTL11 B43_LP_SOUTH(0x022) /* LGENG Control 11 (south) */ -#define B2062_S_REFPLL_CTL0 B43_LP_SOUTH(0x023) /* REFPLL Control 00 (south) */ -#define B2062_S_REFPLL_CTL1 B43_LP_SOUTH(0x024) /* REFPLL Control 01 (south) */ -#define B2062_S_REFPLL_CTL2 B43_LP_SOUTH(0x025) /* REFPLL Control 02 (south) */ -#define B2062_S_REFPLL_CTL3 B43_LP_SOUTH(0x026) /* REFPLL Control 03 (south) */ -#define B2062_S_REFPLL_CTL4 B43_LP_SOUTH(0x027) /* REFPLL Control 04 (south) */ -#define B2062_S_REFPLL_CTL5 B43_LP_SOUTH(0x028) /* REFPLL Control 05 (south) */ -#define B2062_S_REFPLL_CTL6 B43_LP_SOUTH(0x029) /* REFPLL Control 06 (south) */ -#define B2062_S_REFPLL_CTL7 B43_LP_SOUTH(0x02A) /* REFPLL Control 07 (south) */ -#define B2062_S_REFPLL_CTL8 B43_LP_SOUTH(0x02B) /* REFPLL Control 08 (south) */ -#define B2062_S_REFPLL_CTL9 B43_LP_SOUTH(0x02C) /* REFPLL Control 09 (south) */ -#define B2062_S_REFPLL_CTL10 B43_LP_SOUTH(0x02D) /* REFPLL Control 10 (south) */ -#define B2062_S_REFPLL_CTL11 B43_LP_SOUTH(0x02E) /* REFPLL Control 11 (south) */ -#define B2062_S_REFPLL_CTL12 B43_LP_SOUTH(0x02F) /* REFPLL Control 12 (south) */ -#define B2062_S_REFPLL_CTL13 B43_LP_SOUTH(0x030) /* REFPLL Control 13 (south) */ -#define B2062_S_REFPLL_CTL14 B43_LP_SOUTH(0x031) /* REFPLL Control 14 (south) */ -#define B2062_S_REFPLL_CTL15 B43_LP_SOUTH(0x032) /* REFPLL Control 15 (south) */ -#define B2062_S_REFPLL_CTL16 B43_LP_SOUTH(0x033) /* REFPLL Control 16 (south) */ -#define B2062_S_RFPLL_CTL0 B43_LP_SOUTH(0x034) /* RFPLL Control 00 (south) */ -#define B2062_S_RFPLL_CTL1 B43_LP_SOUTH(0x035) /* RFPLL Control 01 (south) */ -#define B2062_S_RFPLL_CTL2 B43_LP_SOUTH(0x036) /* RFPLL Control 02 (south) */ -#define B2062_S_RFPLL_CTL3 B43_LP_SOUTH(0x037) /* RFPLL Control 03 (south) */ -#define B2062_S_RFPLL_CTL4 B43_LP_SOUTH(0x038) /* RFPLL Control 04 (south) */ -#define B2062_S_RFPLL_CTL5 B43_LP_SOUTH(0x039) /* RFPLL Control 05 (south) */ -#define B2062_S_RFPLL_CTL6 B43_LP_SOUTH(0x03A) /* RFPLL Control 06 (south) */ -#define B2062_S_RFPLL_CTL7 B43_LP_SOUTH(0x03B) /* RFPLL Control 07 (south) */ -#define B2062_S_RFPLL_CTL8 B43_LP_SOUTH(0x03C) /* RFPLL Control 08 (south) */ -#define B2062_S_RFPLL_CTL9 B43_LP_SOUTH(0x03D) /* RFPLL Control 09 (south) */ -#define B2062_S_RFPLL_CTL10 B43_LP_SOUTH(0x03E) /* RFPLL Control 10 (south) */ -#define B2062_S_RFPLL_CTL11 B43_LP_SOUTH(0x03F) /* RFPLL Control 11 (south) */ -#define B2062_S_RFPLL_CTL12 B43_LP_SOUTH(0x040) /* RFPLL Control 12 (south) */ -#define B2062_S_RFPLL_CTL13 B43_LP_SOUTH(0x041) /* RFPLL Control 13 (south) */ -#define B2062_S_RFPLL_CTL14 B43_LP_SOUTH(0x042) /* RFPLL Control 14 (south) */ -#define B2062_S_RFPLL_CTL15 B43_LP_SOUTH(0x043) /* RFPLL Control 15 (south) */ -#define B2062_S_RFPLL_CTL16 B43_LP_SOUTH(0x044) /* RFPLL Control 16 (south) */ -#define B2062_S_RFPLL_CTL17 B43_LP_SOUTH(0x045) /* RFPLL Control 17 (south) */ -#define B2062_S_RFPLL_CTL18 B43_LP_SOUTH(0x046) /* RFPLL Control 18 (south) */ -#define B2062_S_RFPLL_CTL19 B43_LP_SOUTH(0x047) /* RFPLL Control 19 (south) */ -#define B2062_S_RFPLL_CTL20 B43_LP_SOUTH(0x048) /* RFPLL Control 20 (south) */ -#define B2062_S_RFPLL_CTL21 B43_LP_SOUTH(0x049) /* RFPLL Control 21 (south) */ -#define B2062_S_RFPLL_CTL22 B43_LP_SOUTH(0x04A) /* RFPLL Control 22 (south) */ -#define B2062_S_RFPLL_CTL23 B43_LP_SOUTH(0x04B) /* RFPLL Control 23 (south) */ -#define B2062_S_RFPLL_CTL24 B43_LP_SOUTH(0x04C) /* RFPLL Control 24 (south) */ -#define B2062_S_RFPLL_CTL25 B43_LP_SOUTH(0x04D) /* RFPLL Control 25 (south) */ -#define B2062_S_RFPLL_CTL26 B43_LP_SOUTH(0x04E) /* RFPLL Control 26 (south) */ -#define B2062_S_RFPLL_CTL27 B43_LP_SOUTH(0x04F) /* RFPLL Control 27 (south) */ -#define B2062_S_RFPLL_CTL28 B43_LP_SOUTH(0x050) /* RFPLL Control 28 (south) */ -#define B2062_S_RFPLL_CTL29 B43_LP_SOUTH(0x051) /* RFPLL Control 29 (south) */ -#define B2062_S_RFPLL_CTL30 B43_LP_SOUTH(0x052) /* RFPLL Control 30 (south) */ -#define B2062_S_RFPLL_CTL31 B43_LP_SOUTH(0x053) /* RFPLL Control 31 (south) */ -#define B2062_S_RFPLL_CTL32 B43_LP_SOUTH(0x054) /* RFPLL Control 32 (south) */ -#define B2062_S_RFPLL_CTL33 B43_LP_SOUTH(0x055) /* RFPLL Control 33 (south) */ -#define B2062_S_RFPLL_CTL34 B43_LP_SOUTH(0x056) /* RFPLL Control 34 (south) */ -#define B2062_S_RXG_CNT0 B43_LP_SOUTH(0x057) /* RXG Counter 00 (south) */ -#define B2062_S_RXG_CNT1 B43_LP_SOUTH(0x058) /* RXG Counter 01 (south) */ -#define B2062_S_RXG_CNT2 B43_LP_SOUTH(0x059) /* RXG Counter 02 (south) */ -#define B2062_S_RXG_CNT3 B43_LP_SOUTH(0x05A) /* RXG Counter 03 (south) */ -#define B2062_S_RXG_CNT4 B43_LP_SOUTH(0x05B) /* RXG Counter 04 (south) */ -#define B2062_S_RXG_CNT5 B43_LP_SOUTH(0x05C) /* RXG Counter 05 (south) */ -#define B2062_S_RXG_CNT6 B43_LP_SOUTH(0x05D) /* RXG Counter 06 (south) */ -#define B2062_S_RXG_CNT7 B43_LP_SOUTH(0x05E) /* RXG Counter 07 (south) */ -#define B2062_S_RXG_CNT8 B43_LP_SOUTH(0x05F) /* RXG Counter 08 (south) */ -#define B2062_S_RXG_CNT9 B43_LP_SOUTH(0x060) /* RXG Counter 09 (south) */ -#define B2062_S_RXG_CNT10 B43_LP_SOUTH(0x061) /* RXG Counter 10 (south) */ -#define B2062_S_RXG_CNT11 B43_LP_SOUTH(0x062) /* RXG Counter 11 (south) */ -#define B2062_S_RXG_CNT12 B43_LP_SOUTH(0x063) /* RXG Counter 12 (south) */ -#define B2062_S_RXG_CNT13 B43_LP_SOUTH(0x064) /* RXG Counter 13 (south) */ -#define B2062_S_RXG_CNT14 B43_LP_SOUTH(0x065) /* RXG Counter 14 (south) */ -#define B2062_S_RXG_CNT15 B43_LP_SOUTH(0x066) /* RXG Counter 15 (south) */ -#define B2062_S_RXG_CNT16 B43_LP_SOUTH(0x067) /* RXG Counter 16 (south) */ -#define B2062_S_RXG_CNT17 B43_LP_SOUTH(0x068) /* RXG Counter 17 (south) */ - - - -/*** Broadcom 2063 radio registers ***/ -#define B2063_RADIO_ID_CODE B43_LP_RADIO(0x001) /* Radio ID code */ -#define B2063_COMM1 B43_LP_RADIO(0x000) /* Common 01 */ -#define B2063_COMM2 B43_LP_RADIO(0x002) /* Common 02 */ -#define B2063_COMM3 B43_LP_RADIO(0x003) /* Common 03 */ -#define B2063_COMM4 B43_LP_RADIO(0x004) /* Common 04 */ -#define B2063_COMM5 B43_LP_RADIO(0x005) /* Common 05 */ -#define B2063_COMM6 B43_LP_RADIO(0x006) /* Common 06 */ -#define B2063_COMM7 B43_LP_RADIO(0x007) /* Common 07 */ -#define B2063_COMM8 B43_LP_RADIO(0x008) /* Common 08 */ -#define B2063_COMM9 B43_LP_RADIO(0x009) /* Common 09 */ -#define B2063_COMM10 B43_LP_RADIO(0x00A) /* Common 10 */ -#define B2063_COMM11 B43_LP_RADIO(0x00B) /* Common 11 */ -#define B2063_COMM12 B43_LP_RADIO(0x00C) /* Common 12 */ -#define B2063_COMM13 B43_LP_RADIO(0x00D) /* Common 13 */ -#define B2063_COMM14 B43_LP_RADIO(0x00E) /* Common 14 */ -#define B2063_COMM15 B43_LP_RADIO(0x00F) /* Common 15 */ -#define B2063_COMM16 B43_LP_RADIO(0x010) /* Common 16 */ -#define B2063_COMM17 B43_LP_RADIO(0x011) /* Common 17 */ -#define B2063_COMM18 B43_LP_RADIO(0x012) /* Common 18 */ -#define B2063_COMM19 B43_LP_RADIO(0x013) /* Common 19 */ -#define B2063_COMM20 B43_LP_RADIO(0x014) /* Common 20 */ -#define B2063_COMM21 B43_LP_RADIO(0x015) /* Common 21 */ -#define B2063_COMM22 B43_LP_RADIO(0x016) /* Common 22 */ -#define B2063_COMM23 B43_LP_RADIO(0x017) /* Common 23 */ -#define B2063_COMM24 B43_LP_RADIO(0x018) /* Common 24 */ -#define B2063_PWR_SWITCH_CTL B43_LP_RADIO(0x019) /* POWER SWITCH Control */ -#define B2063_PLL_SP1 B43_LP_RADIO(0x01A) /* PLL SP 1 */ -#define B2063_PLL_SP2 B43_LP_RADIO(0x01B) /* PLL SP 2 */ -#define B2063_LOGEN_SP1 B43_LP_RADIO(0x01C) /* LOGEN SP 1 */ -#define B2063_LOGEN_SP2 B43_LP_RADIO(0x01D) /* LOGEN SP 2 */ -#define B2063_LOGEN_SP3 B43_LP_RADIO(0x01E) /* LOGEN SP 3 */ -#define B2063_LOGEN_SP4 B43_LP_RADIO(0x01F) /* LOGEN SP 4 */ -#define B2063_LOGEN_SP5 B43_LP_RADIO(0x020) /* LOGEN SP 5 */ -#define B2063_G_RX_SP1 B43_LP_RADIO(0x021) /* G RX SP 1 */ -#define B2063_G_RX_SP2 B43_LP_RADIO(0x022) /* G RX SP 2 */ -#define B2063_G_RX_SP3 B43_LP_RADIO(0x023) /* G RX SP 3 */ -#define B2063_G_RX_SP4 B43_LP_RADIO(0x024) /* G RX SP 4 */ -#define B2063_G_RX_SP5 B43_LP_RADIO(0x025) /* G RX SP 5 */ -#define B2063_G_RX_SP6 B43_LP_RADIO(0x026) /* G RX SP 6 */ -#define B2063_G_RX_SP7 B43_LP_RADIO(0x027) /* G RX SP 7 */ -#define B2063_G_RX_SP8 B43_LP_RADIO(0x028) /* G RX SP 8 */ -#define B2063_G_RX_SP9 B43_LP_RADIO(0x029) /* G RX SP 9 */ -#define B2063_G_RX_SP10 B43_LP_RADIO(0x02A) /* G RX SP 10 */ -#define B2063_G_RX_SP11 B43_LP_RADIO(0x02B) /* G RX SP 11 */ -#define B2063_A_RX_SP1 B43_LP_RADIO(0x02C) /* A RX SP 1 */ -#define B2063_A_RX_SP2 B43_LP_RADIO(0x02D) /* A RX SP 2 */ -#define B2063_A_RX_SP3 B43_LP_RADIO(0x02E) /* A RX SP 3 */ -#define B2063_A_RX_SP4 B43_LP_RADIO(0x02F) /* A RX SP 4 */ -#define B2063_A_RX_SP5 B43_LP_RADIO(0x030) /* A RX SP 5 */ -#define B2063_A_RX_SP6 B43_LP_RADIO(0x031) /* A RX SP 6 */ -#define B2063_A_RX_SP7 B43_LP_RADIO(0x032) /* A RX SP 7 */ -#define B2063_RX_BB_SP1 B43_LP_RADIO(0x033) /* RX BB SP 1 */ -#define B2063_RX_BB_SP2 B43_LP_RADIO(0x034) /* RX BB SP 2 */ -#define B2063_RX_BB_SP3 B43_LP_RADIO(0x035) /* RX BB SP 3 */ -#define B2063_RX_BB_SP4 B43_LP_RADIO(0x036) /* RX BB SP 4 */ -#define B2063_RX_BB_SP5 B43_LP_RADIO(0x037) /* RX BB SP 5 */ -#define B2063_RX_BB_SP6 B43_LP_RADIO(0x038) /* RX BB SP 6 */ -#define B2063_RX_BB_SP7 B43_LP_RADIO(0x039) /* RX BB SP 7 */ -#define B2063_RX_BB_SP8 B43_LP_RADIO(0x03A) /* RX BB SP 8 */ -#define B2063_TX_RF_SP1 B43_LP_RADIO(0x03B) /* TX RF SP 1 */ -#define B2063_TX_RF_SP2 B43_LP_RADIO(0x03C) /* TX RF SP 2 */ -#define B2063_TX_RF_SP3 B43_LP_RADIO(0x03D) /* TX RF SP 3 */ -#define B2063_TX_RF_SP4 B43_LP_RADIO(0x03E) /* TX RF SP 4 */ -#define B2063_TX_RF_SP5 B43_LP_RADIO(0x03F) /* TX RF SP 5 */ -#define B2063_TX_RF_SP6 B43_LP_RADIO(0x040) /* TX RF SP 6 */ -#define B2063_TX_RF_SP7 B43_LP_RADIO(0x041) /* TX RF SP 7 */ -#define B2063_TX_RF_SP8 B43_LP_RADIO(0x042) /* TX RF SP 8 */ -#define B2063_TX_RF_SP9 B43_LP_RADIO(0x043) /* TX RF SP 9 */ -#define B2063_TX_RF_SP10 B43_LP_RADIO(0x044) /* TX RF SP 10 */ -#define B2063_TX_RF_SP11 B43_LP_RADIO(0x045) /* TX RF SP 11 */ -#define B2063_TX_RF_SP12 B43_LP_RADIO(0x046) /* TX RF SP 12 */ -#define B2063_TX_RF_SP13 B43_LP_RADIO(0x047) /* TX RF SP 13 */ -#define B2063_TX_RF_SP14 B43_LP_RADIO(0x048) /* TX RF SP 14 */ -#define B2063_TX_RF_SP15 B43_LP_RADIO(0x049) /* TX RF SP 15 */ -#define B2063_TX_RF_SP16 B43_LP_RADIO(0x04A) /* TX RF SP 16 */ -#define B2063_TX_RF_SP17 B43_LP_RADIO(0x04B) /* TX RF SP 17 */ -#define B2063_PA_SP1 B43_LP_RADIO(0x04C) /* PA SP 1 */ -#define B2063_PA_SP2 B43_LP_RADIO(0x04D) /* PA SP 2 */ -#define B2063_PA_SP3 B43_LP_RADIO(0x04E) /* PA SP 3 */ -#define B2063_PA_SP4 B43_LP_RADIO(0x04F) /* PA SP 4 */ -#define B2063_PA_SP5 B43_LP_RADIO(0x050) /* PA SP 5 */ -#define B2063_PA_SP6 B43_LP_RADIO(0x051) /* PA SP 6 */ -#define B2063_PA_SP7 B43_LP_RADIO(0x052) /* PA SP 7 */ -#define B2063_TX_BB_SP1 B43_LP_RADIO(0x053) /* TX BB SP 1 */ -#define B2063_TX_BB_SP2 B43_LP_RADIO(0x054) /* TX BB SP 2 */ -#define B2063_TX_BB_SP3 B43_LP_RADIO(0x055) /* TX BB SP 3 */ -#define B2063_REG_SP1 B43_LP_RADIO(0x056) /* REG SP 1 */ -#define B2063_BANDGAP_CTL1 B43_LP_RADIO(0x057) /* BANDGAP Control 1 */ -#define B2063_BANDGAP_CTL2 B43_LP_RADIO(0x058) /* BANDGAP Control 2 */ -#define B2063_LPO_CTL1 B43_LP_RADIO(0x059) /* LPO Control 1 */ -#define B2063_RC_CALIB_CTL1 B43_LP_RADIO(0x05A) /* RC Calibration Control 1 */ -#define B2063_RC_CALIB_CTL2 B43_LP_RADIO(0x05B) /* RC Calibration Control 2 */ -#define B2063_RC_CALIB_CTL3 B43_LP_RADIO(0x05C) /* RC Calibration Control 3 */ -#define B2063_RC_CALIB_CTL4 B43_LP_RADIO(0x05D) /* RC Calibration Control 4 */ -#define B2063_RC_CALIB_CTL5 B43_LP_RADIO(0x05E) /* RC Calibration Control 5 */ -#define B2063_RC_CALIB_CTL6 B43_LP_RADIO(0x05F) /* RC Calibration Control 6 */ -#define B2063_RC_CALIB_CTL7 B43_LP_RADIO(0x060) /* RC Calibration Control 7 */ -#define B2063_RC_CALIB_CTL8 B43_LP_RADIO(0x061) /* RC Calibration Control 8 */ -#define B2063_RC_CALIB_CTL9 B43_LP_RADIO(0x062) /* RC Calibration Control 9 */ -#define B2063_RC_CALIB_CTL10 B43_LP_RADIO(0x063) /* RC Calibration Control 10 */ -#define B2063_PLL_JTAG_CALNRST B43_LP_RADIO(0x064) /* PLL JTAG CALNRST */ -#define B2063_PLL_JTAG_IN_PLL1 B43_LP_RADIO(0x065) /* PLL JTAG IN PLL 1 */ -#define B2063_PLL_JTAG_IN_PLL2 B43_LP_RADIO(0x066) /* PLL JTAG IN PLL 2 */ -#define B2063_PLL_JTAG_PLL_CP1 B43_LP_RADIO(0x067) /* PLL JTAG PLL CP 1 */ -#define B2063_PLL_JTAG_PLL_CP2 B43_LP_RADIO(0x068) /* PLL JTAG PLL CP 2 */ -#define B2063_PLL_JTAG_PLL_CP3 B43_LP_RADIO(0x069) /* PLL JTAG PLL CP 3 */ -#define B2063_PLL_JTAG_PLL_CP4 B43_LP_RADIO(0x06A) /* PLL JTAG PLL CP 4 */ -#define B2063_PLL_JTAG_PLL_CTL1 B43_LP_RADIO(0x06B) /* PLL JTAG PLL Control 1 */ -#define B2063_PLL_JTAG_PLL_LF1 B43_LP_RADIO(0x06C) /* PLL JTAG PLL LF 1 */ -#define B2063_PLL_JTAG_PLL_LF2 B43_LP_RADIO(0x06D) /* PLL JTAG PLL LF 2 */ -#define B2063_PLL_JTAG_PLL_LF3 B43_LP_RADIO(0x06E) /* PLL JTAG PLL LF 3 */ -#define B2063_PLL_JTAG_PLL_LF4 B43_LP_RADIO(0x06F) /* PLL JTAG PLL LF 4 */ -#define B2063_PLL_JTAG_PLL_SG1 B43_LP_RADIO(0x070) /* PLL JTAG PLL SG 1 */ -#define B2063_PLL_JTAG_PLL_SG2 B43_LP_RADIO(0x071) /* PLL JTAG PLL SG 2 */ -#define B2063_PLL_JTAG_PLL_SG3 B43_LP_RADIO(0x072) /* PLL JTAG PLL SG 3 */ -#define B2063_PLL_JTAG_PLL_SG4 B43_LP_RADIO(0x073) /* PLL JTAG PLL SG 4 */ -#define B2063_PLL_JTAG_PLL_SG5 B43_LP_RADIO(0x074) /* PLL JTAG PLL SG 5 */ -#define B2063_PLL_JTAG_PLL_VCO1 B43_LP_RADIO(0x075) /* PLL JTAG PLL VCO 1 */ -#define B2063_PLL_JTAG_PLL_VCO2 B43_LP_RADIO(0x076) /* PLL JTAG PLL VCO 2 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB1 B43_LP_RADIO(0x077) /* PLL JTAG PLL VCO Calibration 1 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB2 B43_LP_RADIO(0x078) /* PLL JTAG PLL VCO Calibration 2 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB3 B43_LP_RADIO(0x079) /* PLL JTAG PLL VCO Calibration 3 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB4 B43_LP_RADIO(0x07A) /* PLL JTAG PLL VCO Calibration 4 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB5 B43_LP_RADIO(0x07B) /* PLL JTAG PLL VCO Calibration 5 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB6 B43_LP_RADIO(0x07C) /* PLL JTAG PLL VCO Calibration 6 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB7 B43_LP_RADIO(0x07D) /* PLL JTAG PLL VCO Calibration 7 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB8 B43_LP_RADIO(0x07E) /* PLL JTAG PLL VCO Calibration 8 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB9 B43_LP_RADIO(0x07F) /* PLL JTAG PLL VCO Calibration 9 */ -#define B2063_PLL_JTAG_PLL_VCO_CALIB10 B43_LP_RADIO(0x080) /* PLL JTAG PLL VCO Calibration 10 */ -#define B2063_PLL_JTAG_PLL_XTAL_12 B43_LP_RADIO(0x081) /* PLL JTAG PLL XTAL 1 2 */ -#define B2063_PLL_JTAG_PLL_XTAL3 B43_LP_RADIO(0x082) /* PLL JTAG PLL XTAL 3 */ -#define B2063_LOGEN_ACL1 B43_LP_RADIO(0x083) /* LOGEN ACL 1 */ -#define B2063_LOGEN_ACL2 B43_LP_RADIO(0x084) /* LOGEN ACL 2 */ -#define B2063_LOGEN_ACL3 B43_LP_RADIO(0x085) /* LOGEN ACL 3 */ -#define B2063_LOGEN_ACL4 B43_LP_RADIO(0x086) /* LOGEN ACL 4 */ -#define B2063_LOGEN_ACL5 B43_LP_RADIO(0x087) /* LOGEN ACL 5 */ -#define B2063_LO_CALIB_INPUTS B43_LP_RADIO(0x088) /* LO Calibration INPUTS */ -#define B2063_LO_CALIB_CTL1 B43_LP_RADIO(0x089) /* LO Calibration Control 1 */ -#define B2063_LO_CALIB_CTL2 B43_LP_RADIO(0x08A) /* LO Calibration Control 2 */ -#define B2063_LO_CALIB_CTL3 B43_LP_RADIO(0x08B) /* LO Calibration Control 3 */ -#define B2063_LO_CALIB_WAITCNT B43_LP_RADIO(0x08C) /* LO Calibration WAITCNT */ -#define B2063_LO_CALIB_OVR1 B43_LP_RADIO(0x08D) /* LO Calibration OVR 1 */ -#define B2063_LO_CALIB_OVR2 B43_LP_RADIO(0x08E) /* LO Calibration OVR 2 */ -#define B2063_LO_CALIB_OVAL1 B43_LP_RADIO(0x08F) /* LO Calibration OVAL 1 */ -#define B2063_LO_CALIB_OVAL2 B43_LP_RADIO(0x090) /* LO Calibration OVAL 2 */ -#define B2063_LO_CALIB_OVAL3 B43_LP_RADIO(0x091) /* LO Calibration OVAL 3 */ -#define B2063_LO_CALIB_OVAL4 B43_LP_RADIO(0x092) /* LO Calibration OVAL 4 */ -#define B2063_LO_CALIB_OVAL5 B43_LP_RADIO(0x093) /* LO Calibration OVAL 5 */ -#define B2063_LO_CALIB_OVAL6 B43_LP_RADIO(0x094) /* LO Calibration OVAL 6 */ -#define B2063_LO_CALIB_OVAL7 B43_LP_RADIO(0x095) /* LO Calibration OVAL 7 */ -#define B2063_LO_CALIB_CALVLD1 B43_LP_RADIO(0x096) /* LO Calibration CALVLD 1 */ -#define B2063_LO_CALIB_CALVLD2 B43_LP_RADIO(0x097) /* LO Calibration CALVLD 2 */ -#define B2063_LO_CALIB_CVAL1 B43_LP_RADIO(0x098) /* LO Calibration CVAL 1 */ -#define B2063_LO_CALIB_CVAL2 B43_LP_RADIO(0x099) /* LO Calibration CVAL 2 */ -#define B2063_LO_CALIB_CVAL3 B43_LP_RADIO(0x09A) /* LO Calibration CVAL 3 */ -#define B2063_LO_CALIB_CVAL4 B43_LP_RADIO(0x09B) /* LO Calibration CVAL 4 */ -#define B2063_LO_CALIB_CVAL5 B43_LP_RADIO(0x09C) /* LO Calibration CVAL 5 */ -#define B2063_LO_CALIB_CVAL6 B43_LP_RADIO(0x09D) /* LO Calibration CVAL 6 */ -#define B2063_LO_CALIB_CVAL7 B43_LP_RADIO(0x09E) /* LO Calibration CVAL 7 */ -#define B2063_LOGEN_CALIB_EN B43_LP_RADIO(0x09F) /* LOGEN Calibration EN */ -#define B2063_LOGEN_PEAKDET1 B43_LP_RADIO(0x0A0) /* LOGEN PEAKDET 1 */ -#define B2063_LOGEN_RCCR1 B43_LP_RADIO(0x0A1) /* LOGEN RCCR 1 */ -#define B2063_LOGEN_VCOBUF1 B43_LP_RADIO(0x0A2) /* LOGEN VCOBUF 1 */ -#define B2063_LOGEN_MIXER1 B43_LP_RADIO(0x0A3) /* LOGEN MIXER 1 */ -#define B2063_LOGEN_MIXER2 B43_LP_RADIO(0x0A4) /* LOGEN MIXER 2 */ -#define B2063_LOGEN_BUF1 B43_LP_RADIO(0x0A5) /* LOGEN BUF 1 */ -#define B2063_LOGEN_BUF2 B43_LP_RADIO(0x0A6) /* LOGEN BUF 2 */ -#define B2063_LOGEN_DIV1 B43_LP_RADIO(0x0A7) /* LOGEN DIV 1 */ -#define B2063_LOGEN_DIV2 B43_LP_RADIO(0x0A8) /* LOGEN DIV 2 */ -#define B2063_LOGEN_DIV3 B43_LP_RADIO(0x0A9) /* LOGEN DIV 3 */ -#define B2063_LOGEN_CBUFRX1 B43_LP_RADIO(0x0AA) /* LOGEN CBUFRX 1 */ -#define B2063_LOGEN_CBUFRX2 B43_LP_RADIO(0x0AB) /* LOGEN CBUFRX 2 */ -#define B2063_LOGEN_CBUFTX1 B43_LP_RADIO(0x0AC) /* LOGEN CBUFTX 1 */ -#define B2063_LOGEN_CBUFTX2 B43_LP_RADIO(0x0AD) /* LOGEN CBUFTX 2 */ -#define B2063_LOGEN_IDAC1 B43_LP_RADIO(0x0AE) /* LOGEN IDAC 1 */ -#define B2063_LOGEN_SPARE1 B43_LP_RADIO(0x0AF) /* LOGEN SPARE 1 */ -#define B2063_LOGEN_SPARE2 B43_LP_RADIO(0x0B0) /* LOGEN SPARE 2 */ -#define B2063_LOGEN_SPARE3 B43_LP_RADIO(0x0B1) /* LOGEN SPARE 3 */ -#define B2063_G_RX_1ST1 B43_LP_RADIO(0x0B2) /* G RX 1ST 1 */ -#define B2063_G_RX_1ST2 B43_LP_RADIO(0x0B3) /* G RX 1ST 2 */ -#define B2063_G_RX_1ST3 B43_LP_RADIO(0x0B4) /* G RX 1ST 3 */ -#define B2063_G_RX_2ND1 B43_LP_RADIO(0x0B5) /* G RX 2ND 1 */ -#define B2063_G_RX_2ND2 B43_LP_RADIO(0x0B6) /* G RX 2ND 2 */ -#define B2063_G_RX_2ND3 B43_LP_RADIO(0x0B7) /* G RX 2ND 3 */ -#define B2063_G_RX_2ND4 B43_LP_RADIO(0x0B8) /* G RX 2ND 4 */ -#define B2063_G_RX_2ND5 B43_LP_RADIO(0x0B9) /* G RX 2ND 5 */ -#define B2063_G_RX_2ND6 B43_LP_RADIO(0x0BA) /* G RX 2ND 6 */ -#define B2063_G_RX_2ND7 B43_LP_RADIO(0x0BB) /* G RX 2ND 7 */ -#define B2063_G_RX_2ND8 B43_LP_RADIO(0x0BC) /* G RX 2ND 8 */ -#define B2063_G_RX_PS1 B43_LP_RADIO(0x0BD) /* G RX PS 1 */ -#define B2063_G_RX_PS2 B43_LP_RADIO(0x0BE) /* G RX PS 2 */ -#define B2063_G_RX_PS3 B43_LP_RADIO(0x0BF) /* G RX PS 3 */ -#define B2063_G_RX_PS4 B43_LP_RADIO(0x0C0) /* G RX PS 4 */ -#define B2063_G_RX_PS5 B43_LP_RADIO(0x0C1) /* G RX PS 5 */ -#define B2063_G_RX_MIX1 B43_LP_RADIO(0x0C2) /* G RX MIX 1 */ -#define B2063_G_RX_MIX2 B43_LP_RADIO(0x0C3) /* G RX MIX 2 */ -#define B2063_G_RX_MIX3 B43_LP_RADIO(0x0C4) /* G RX MIX 3 */ -#define B2063_G_RX_MIX4 B43_LP_RADIO(0x0C5) /* G RX MIX 4 */ -#define B2063_G_RX_MIX5 B43_LP_RADIO(0x0C6) /* G RX MIX 5 */ -#define B2063_G_RX_MIX6 B43_LP_RADIO(0x0C7) /* G RX MIX 6 */ -#define B2063_G_RX_MIX7 B43_LP_RADIO(0x0C8) /* G RX MIX 7 */ -#define B2063_G_RX_MIX8 B43_LP_RADIO(0x0C9) /* G RX MIX 8 */ -#define B2063_G_RX_PDET1 B43_LP_RADIO(0x0CA) /* G RX PDET 1 */ -#define B2063_G_RX_SPARES1 B43_LP_RADIO(0x0CB) /* G RX SPARES 1 */ -#define B2063_G_RX_SPARES2 B43_LP_RADIO(0x0CC) /* G RX SPARES 2 */ -#define B2063_G_RX_SPARES3 B43_LP_RADIO(0x0CD) /* G RX SPARES 3 */ -#define B2063_A_RX_1ST1 B43_LP_RADIO(0x0CE) /* A RX 1ST 1 */ -#define B2063_A_RX_1ST2 B43_LP_RADIO(0x0CF) /* A RX 1ST 2 */ -#define B2063_A_RX_1ST3 B43_LP_RADIO(0x0D0) /* A RX 1ST 3 */ -#define B2063_A_RX_1ST4 B43_LP_RADIO(0x0D1) /* A RX 1ST 4 */ -#define B2063_A_RX_1ST5 B43_LP_RADIO(0x0D2) /* A RX 1ST 5 */ -#define B2063_A_RX_2ND1 B43_LP_RADIO(0x0D3) /* A RX 2ND 1 */ -#define B2063_A_RX_2ND2 B43_LP_RADIO(0x0D4) /* A RX 2ND 2 */ -#define B2063_A_RX_2ND3 B43_LP_RADIO(0x0D5) /* A RX 2ND 3 */ -#define B2063_A_RX_2ND4 B43_LP_RADIO(0x0D6) /* A RX 2ND 4 */ -#define B2063_A_RX_2ND5 B43_LP_RADIO(0x0D7) /* A RX 2ND 5 */ -#define B2063_A_RX_2ND6 B43_LP_RADIO(0x0D8) /* A RX 2ND 6 */ -#define B2063_A_RX_2ND7 B43_LP_RADIO(0x0D9) /* A RX 2ND 7 */ -#define B2063_A_RX_PS1 B43_LP_RADIO(0x0DA) /* A RX PS 1 */ -#define B2063_A_RX_PS2 B43_LP_RADIO(0x0DB) /* A RX PS 2 */ -#define B2063_A_RX_PS3 B43_LP_RADIO(0x0DC) /* A RX PS 3 */ -#define B2063_A_RX_PS4 B43_LP_RADIO(0x0DD) /* A RX PS 4 */ -#define B2063_A_RX_PS5 B43_LP_RADIO(0x0DE) /* A RX PS 5 */ -#define B2063_A_RX_PS6 B43_LP_RADIO(0x0DF) /* A RX PS 6 */ -#define B2063_A_RX_MIX1 B43_LP_RADIO(0x0E0) /* A RX MIX 1 */ -#define B2063_A_RX_MIX2 B43_LP_RADIO(0x0E1) /* A RX MIX 2 */ -#define B2063_A_RX_MIX3 B43_LP_RADIO(0x0E2) /* A RX MIX 3 */ -#define B2063_A_RX_MIX4 B43_LP_RADIO(0x0E3) /* A RX MIX 4 */ -#define B2063_A_RX_MIX5 B43_LP_RADIO(0x0E4) /* A RX MIX 5 */ -#define B2063_A_RX_MIX6 B43_LP_RADIO(0x0E5) /* A RX MIX 6 */ -#define B2063_A_RX_MIX7 B43_LP_RADIO(0x0E6) /* A RX MIX 7 */ -#define B2063_A_RX_MIX8 B43_LP_RADIO(0x0E7) /* A RX MIX 8 */ -#define B2063_A_RX_PWRDET1 B43_LP_RADIO(0x0E8) /* A RX PWRDET 1 */ -#define B2063_A_RX_SPARE1 B43_LP_RADIO(0x0E9) /* A RX SPARE 1 */ -#define B2063_A_RX_SPARE2 B43_LP_RADIO(0x0EA) /* A RX SPARE 2 */ -#define B2063_A_RX_SPARE3 B43_LP_RADIO(0x0EB) /* A RX SPARE 3 */ -#define B2063_RX_TIA_CTL1 B43_LP_RADIO(0x0EC) /* RX TIA Control 1 */ -#define B2063_RX_TIA_CTL2 B43_LP_RADIO(0x0ED) /* RX TIA Control 2 */ -#define B2063_RX_TIA_CTL3 B43_LP_RADIO(0x0EE) /* RX TIA Control 3 */ -#define B2063_RX_TIA_CTL4 B43_LP_RADIO(0x0EF) /* RX TIA Control 4 */ -#define B2063_RX_TIA_CTL5 B43_LP_RADIO(0x0F0) /* RX TIA Control 5 */ -#define B2063_RX_TIA_CTL6 B43_LP_RADIO(0x0F1) /* RX TIA Control 6 */ -#define B2063_RX_BB_CTL1 B43_LP_RADIO(0x0F2) /* RX BB Control 1 */ -#define B2063_RX_BB_CTL2 B43_LP_RADIO(0x0F3) /* RX BB Control 2 */ -#define B2063_RX_BB_CTL3 B43_LP_RADIO(0x0F4) /* RX BB Control 3 */ -#define B2063_RX_BB_CTL4 B43_LP_RADIO(0x0F5) /* RX BB Control 4 */ -#define B2063_RX_BB_CTL5 B43_LP_RADIO(0x0F6) /* RX BB Control 5 */ -#define B2063_RX_BB_CTL6 B43_LP_RADIO(0x0F7) /* RX BB Control 6 */ -#define B2063_RX_BB_CTL7 B43_LP_RADIO(0x0F8) /* RX BB Control 7 */ -#define B2063_RX_BB_CTL8 B43_LP_RADIO(0x0F9) /* RX BB Control 8 */ -#define B2063_RX_BB_CTL9 B43_LP_RADIO(0x0FA) /* RX BB Control 9 */ -#define B2063_TX_RF_CTL1 B43_LP_RADIO(0x0FB) /* TX RF Control 1 */ -#define B2063_TX_RF_IDAC_LO_RF_I B43_LP_RADIO(0x0FC) /* TX RF IDAC LO RF I */ -#define B2063_TX_RF_IDAC_LO_RF_Q B43_LP_RADIO(0x0FD) /* TX RF IDAC LO RF Q */ -#define B2063_TX_RF_IDAC_LO_BB_I B43_LP_RADIO(0x0FE) /* TX RF IDAC LO BB I */ -#define B2063_TX_RF_IDAC_LO_BB_Q B43_LP_RADIO(0x0FF) /* TX RF IDAC LO BB Q */ -#define B2063_TX_RF_CTL2 B43_LP_RADIO(0x100) /* TX RF Control 2 */ -#define B2063_TX_RF_CTL3 B43_LP_RADIO(0x101) /* TX RF Control 3 */ -#define B2063_TX_RF_CTL4 B43_LP_RADIO(0x102) /* TX RF Control 4 */ -#define B2063_TX_RF_CTL5 B43_LP_RADIO(0x103) /* TX RF Control 5 */ -#define B2063_TX_RF_CTL6 B43_LP_RADIO(0x104) /* TX RF Control 6 */ -#define B2063_TX_RF_CTL7 B43_LP_RADIO(0x105) /* TX RF Control 7 */ -#define B2063_TX_RF_CTL8 B43_LP_RADIO(0x106) /* TX RF Control 8 */ -#define B2063_TX_RF_CTL9 B43_LP_RADIO(0x107) /* TX RF Control 9 */ -#define B2063_TX_RF_CTL10 B43_LP_RADIO(0x108) /* TX RF Control 10 */ -#define B2063_TX_RF_CTL14 B43_LP_RADIO(0x109) /* TX RF Control 14 */ -#define B2063_TX_RF_CTL15 B43_LP_RADIO(0x10A) /* TX RF Control 15 */ -#define B2063_PA_CTL1 B43_LP_RADIO(0x10B) /* PA Control 1 */ -#define B2063_PA_CTL2 B43_LP_RADIO(0x10C) /* PA Control 2 */ -#define B2063_PA_CTL3 B43_LP_RADIO(0x10D) /* PA Control 3 */ -#define B2063_PA_CTL4 B43_LP_RADIO(0x10E) /* PA Control 4 */ -#define B2063_PA_CTL5 B43_LP_RADIO(0x10F) /* PA Control 5 */ -#define B2063_PA_CTL6 B43_LP_RADIO(0x110) /* PA Control 6 */ -#define B2063_PA_CTL7 B43_LP_RADIO(0x111) /* PA Control 7 */ -#define B2063_PA_CTL8 B43_LP_RADIO(0x112) /* PA Control 8 */ -#define B2063_PA_CTL9 B43_LP_RADIO(0x113) /* PA Control 9 */ -#define B2063_PA_CTL10 B43_LP_RADIO(0x114) /* PA Control 10 */ -#define B2063_PA_CTL11 B43_LP_RADIO(0x115) /* PA Control 11 */ -#define B2063_PA_CTL12 B43_LP_RADIO(0x116) /* PA Control 12 */ -#define B2063_PA_CTL13 B43_LP_RADIO(0x117) /* PA Control 13 */ -#define B2063_TX_BB_CTL1 B43_LP_RADIO(0x118) /* TX BB Control 1 */ -#define B2063_TX_BB_CTL2 B43_LP_RADIO(0x119) /* TX BB Control 2 */ -#define B2063_TX_BB_CTL3 B43_LP_RADIO(0x11A) /* TX BB Control 3 */ -#define B2063_TX_BB_CTL4 B43_LP_RADIO(0x11B) /* TX BB Control 4 */ -#define B2063_GPIO_CTL1 B43_LP_RADIO(0x11C) /* GPIO Control 1 */ -#define B2063_VREG_CTL1 B43_LP_RADIO(0x11D) /* VREG Control 1 */ -#define B2063_AMUX_CTL1 B43_LP_RADIO(0x11E) /* AMUX Control 1 */ -#define B2063_IQ_CALIB_GVAR B43_LP_RADIO(0x11F) /* IQ Calibration GVAR */ -#define B2063_IQ_CALIB_CTL1 B43_LP_RADIO(0x120) /* IQ Calibration Control 1 */ -#define B2063_IQ_CALIB_CTL2 B43_LP_RADIO(0x121) /* IQ Calibration Control 2 */ -#define B2063_TEMPSENSE_CTL1 B43_LP_RADIO(0x122) /* TEMPSENSE Control 1 */ -#define B2063_TEMPSENSE_CTL2 B43_LP_RADIO(0x123) /* TEMPSENSE Control 2 */ -#define B2063_TX_RX_LOOPBACK1 B43_LP_RADIO(0x124) /* TX/RX LOOPBACK 1 */ -#define B2063_TX_RX_LOOPBACK2 B43_LP_RADIO(0x125) /* TX/RX LOOPBACK 2 */ -#define B2063_EXT_TSSI_CTL1 B43_LP_RADIO(0x126) /* EXT TSSI Control 1 */ -#define B2063_EXT_TSSI_CTL2 B43_LP_RADIO(0x127) /* EXT TSSI Control 2 */ -#define B2063_AFE_CTL B43_LP_RADIO(0x128) /* AFE Control */ - - - -enum b43_lpphy_txpctl_mode { - B43_LPPHY_TXPCTL_UNKNOWN = 0, - B43_LPPHY_TXPCTL_OFF, /* TX power control is OFF */ - B43_LPPHY_TXPCTL_SW, /* TX power control is set to Software */ - B43_LPPHY_TXPCTL_HW, /* TX power control is set to Hardware */ -}; - -struct b43_phy_lp { - /* Current TX power control mode. */ - enum b43_lpphy_txpctl_mode txpctl_mode; - - /* Transmit isolation medium band */ - u8 tx_isolation_med_band; - /* Transmit isolation low band */ - u8 tx_isolation_low_band; - /* Transmit isolation high band */ - u8 tx_isolation_hi_band; - - /* Max transmit power medium band */ - u16 max_tx_pwr_med_band; - /* Max transmit power low band */ - u16 max_tx_pwr_low_band; - /* Max transmit power high band */ - u16 max_tx_pwr_hi_band; - - /* FIXME What are these used for? */ - /* FIXME Is 15 the correct array size? */ - u16 tx_max_rate[15]; - u16 tx_max_ratel[15]; - u16 tx_max_rateh[15]; - - /* Transmit power arrays */ - s16 txpa[3], txpal[3], txpah[3]; - - /* Receive power offset */ - u8 rx_pwr_offset; - - /* TSSI transmit count */ - u16 tssi_tx_count; - /* TSSI index */ - u16 tssi_idx; /* FIXME initial value? */ - /* TSSI npt */ - u16 tssi_npt; /* FIXME initial value? */ - - /* Target TX frequency */ - u16 tgt_tx_freq; /* FIXME initial value? */ - - /* Transmit power index override */ - s8 tx_pwr_idx_over; /* FIXME initial value? */ - - /* RSSI vf */ - u8 rssi_vf; - /* RSSI vc */ - u8 rssi_vc; - /* RSSI gs */ - u8 rssi_gs; - - /* RC cap */ - u8 rc_cap; /* FIXME initial value? */ - /* BX arch */ - u8 bx_arch; - - /* Full calibration channel */ - u8 full_calib_chan; /* FIXME initial value? */ - - /* Transmit iqlocal best coeffs */ - bool tx_iqloc_best_coeffs_valid; - u8 tx_iqloc_best_coeffs[11]; - - /* Used for "Save/Restore Dig Filt State" */ - u16 dig_flt_state[9]; - - bool crs_usr_disable, crs_sys_disable; - - unsigned int pdiv; - - /* The channel we are tuned to */ - u8 channel; -}; - -enum tssi_mux_mode { - TSSI_MUX_PREPA, - TSSI_MUX_POSTPA, - TSSI_MUX_EXT, -}; - -struct b43_phy_operations; -extern const struct b43_phy_operations b43_phyops_lp; - -#endif /* LINUX_B43_PHY_LP_H_ */ diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c deleted file mode 100644 index 992318a78077..000000000000 --- a/drivers/net/wireless/b43/phy_n.c +++ /dev/null @@ -1,629 +0,0 @@ -/* - - Broadcom B43 wireless driver - IEEE 802.11n PHY support - - Copyright (c) 2008 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include - -#include "b43.h" -#include "phy_n.h" -#include "tables_nphy.h" - - -void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) -{//TODO -} - -static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev) -{//TODO -} - -static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev, - bool ignore_tssi) -{//TODO - return B43_TXPWR_RES_DONE; -} - -static void b43_chantab_radio_upload(struct b43_wldev *dev, - const struct b43_nphy_channeltab_entry *e) -{ - b43_radio_write16(dev, B2055_PLL_REF, e->radio_pll_ref); - b43_radio_write16(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0); - b43_radio_write16(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1); - b43_radio_write16(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail); - b43_radio_write16(dev, B2055_VCO_CAL1, e->radio_vco_cal1); - b43_radio_write16(dev, B2055_VCO_CAL2, e->radio_vco_cal2); - b43_radio_write16(dev, B2055_PLL_LFC1, e->radio_pll_lfc1); - b43_radio_write16(dev, B2055_PLL_LFR1, e->radio_pll_lfr1); - b43_radio_write16(dev, B2055_PLL_LFC2, e->radio_pll_lfc2); - b43_radio_write16(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf); - b43_radio_write16(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1); - b43_radio_write16(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2); - b43_radio_write16(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune); - b43_radio_write16(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune); - b43_radio_write16(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1); - b43_radio_write16(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn); - b43_radio_write16(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim); - b43_radio_write16(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune); - b43_radio_write16(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune); - b43_radio_write16(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1); - b43_radio_write16(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn); - b43_radio_write16(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim); -} - -static void b43_chantab_phy_upload(struct b43_wldev *dev, - const struct b43_nphy_channeltab_entry *e) -{ - b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a); - b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2); - b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3); - b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4); - b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5); - b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6); -} - -static void b43_nphy_tx_power_fix(struct b43_wldev *dev) -{ - //TODO -} - -/* Tune the hardware to a new channel. */ -static int nphy_channel_switch(struct b43_wldev *dev, unsigned int channel) -{ - const struct b43_nphy_channeltab_entry *tabent; - - tabent = b43_nphy_get_chantabent(dev, channel); - if (!tabent) - return -ESRCH; - - //FIXME enable/disable band select upper20 in RXCTL - if (0 /*FIXME 5Ghz*/) - b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x20); - else - b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, 0x50); - b43_chantab_radio_upload(dev, tabent); - udelay(50); - b43_radio_write16(dev, B2055_VCO_CAL10, 5); - b43_radio_write16(dev, B2055_VCO_CAL10, 45); - b43_radio_write16(dev, B2055_VCO_CAL10, 65); - udelay(300); - if (0 /*FIXME 5Ghz*/) - b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ); - else - b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ); - b43_chantab_phy_upload(dev, tabent); - b43_nphy_tx_power_fix(dev); - - return 0; -} - -static void b43_radio_init2055_pre(struct b43_wldev *dev) -{ - b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, - ~B43_NPHY_RFCTL_CMD_PORFORCE); - b43_phy_set(dev, B43_NPHY_RFCTL_CMD, - B43_NPHY_RFCTL_CMD_CHIP0PU | - B43_NPHY_RFCTL_CMD_OEPORFORCE); - b43_phy_set(dev, B43_NPHY_RFCTL_CMD, - B43_NPHY_RFCTL_CMD_PORFORCE); -} - -static void b43_radio_init2055_post(struct b43_wldev *dev) -{ - struct ssb_sprom *sprom = &(dev->dev->bus->sprom); - struct ssb_boardinfo *binfo = &(dev->dev->bus->boardinfo); - int i; - u16 val; - - b43_radio_mask(dev, B2055_MASTER1, 0xFFF3); - msleep(1); - if ((sprom->revision != 4) || - !(sprom->boardflags_hi & B43_BFH_RSSIINV)) { - if ((binfo->vendor != PCI_VENDOR_ID_BROADCOM) || - (binfo->type != 0x46D) || - (binfo->rev < 0x41)) { - b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); - b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F); - msleep(1); - } - } - b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0x3F, 0x2C); - msleep(1); - b43_radio_write16(dev, B2055_CAL_MISC, 0x3C); - msleep(1); - b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE); - msleep(1); - b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80); - msleep(1); - b43_radio_set(dev, B2055_CAL_MISC, 0x1); - msleep(1); - b43_radio_set(dev, B2055_CAL_MISC, 0x40); - msleep(1); - for (i = 0; i < 100; i++) { - val = b43_radio_read16(dev, B2055_CAL_COUT2); - if (val & 0x80) - break; - udelay(10); - } - msleep(1); - b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F); - msleep(1); - nphy_channel_switch(dev, dev->phy.channel); - b43_radio_write16(dev, B2055_C1_RX_BB_LPF, 0x9); - b43_radio_write16(dev, B2055_C2_RX_BB_LPF, 0x9); - b43_radio_write16(dev, B2055_C1_RX_BB_MIDACHP, 0x83); - b43_radio_write16(dev, B2055_C2_RX_BB_MIDACHP, 0x83); -} - -/* Initialize a Broadcom 2055 N-radio */ -static void b43_radio_init2055(struct b43_wldev *dev) -{ - b43_radio_init2055_pre(dev); - if (b43_status(dev) < B43_STAT_INITIALIZED) - b2055_upload_inittab(dev, 0, 1); - else - b2055_upload_inittab(dev, 0/*FIXME on 5ghz band*/, 0); - b43_radio_init2055_post(dev); -} - -void b43_nphy_radio_turn_on(struct b43_wldev *dev) -{ - b43_radio_init2055(dev); -} - -void b43_nphy_radio_turn_off(struct b43_wldev *dev) -{ - b43_phy_mask(dev, B43_NPHY_RFCTL_CMD, - ~B43_NPHY_RFCTL_CMD_EN); -} - -#define ntab_upload(dev, offset, data) do { \ - unsigned int i; \ - for (i = 0; i < (offset##_SIZE); i++) \ - b43_ntab_write(dev, (offset) + i, (data)[i]); \ - } while (0) - -/* Upload the N-PHY tables. */ -static void b43_nphy_tables_init(struct b43_wldev *dev) -{ - /* Static tables */ - ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); - ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); - ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); - ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn); - ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel); - ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot); - ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt); - ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0); - ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1); - ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0); - ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1); - ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi); - ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest); - ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs); - - /* Volatile tables */ - ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10); - ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11); - ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0); - ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1); - ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0); - ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1); - ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0); - ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1); - ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0); - ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1); - ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0); - ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1); -} - -static void b43_nphy_workarounds(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - unsigned int i; - - b43_phy_set(dev, B43_NPHY_IQFLIP, - B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2); - if (1 /* FIXME band is 2.4GHz */) { - b43_phy_set(dev, B43_NPHY_CLASSCTL, - B43_NPHY_CLASSCTL_CCKEN); - } else { - b43_phy_mask(dev, B43_NPHY_CLASSCTL, - ~B43_NPHY_CLASSCTL_CCKEN); - } - b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8); - b43_phy_write(dev, B43_NPHY_TXFRAMEDELAY, 8); - - /* Fixup some tables */ - b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0xA); - b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0xA); - b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA); - b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA); - b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0); - b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0); - b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB); - b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB); - b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x800); - b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x800); - - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8); - b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301); - - //TODO set RF sequence - - /* Set narrowband clip threshold */ - b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 66); - b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 66); - - /* Set wideband clip 2 threshold */ - b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES, - ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, - 21 << B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES, - ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, - 21 << B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT); - - /* Set Clip 2 detect */ - b43_phy_set(dev, B43_NPHY_C1_CGAINI, - B43_NPHY_C1_CGAINI_CL2DETECT); - b43_phy_set(dev, B43_NPHY_C2_CGAINI, - B43_NPHY_C2_CGAINI_CL2DETECT); - - if (0 /*FIXME*/) { - /* Set dwell lengths */ - b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 43); - b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 43); - b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 9); - b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 9); - - /* Set gain backoff */ - b43_phy_maskset(dev, B43_NPHY_C1_CGAINI, - ~B43_NPHY_C1_CGAINI_GAINBKOFF, - 1 << B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_CGAINI, - ~B43_NPHY_C2_CGAINI_GAINBKOFF, - 1 << B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT); - - /* Set HPVGA2 index */ - b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, - ~B43_NPHY_C1_INITGAIN_HPVGA2, - 6 << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, - ~B43_NPHY_C2_INITGAIN_HPVGA2, - 6 << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT); - - //FIXME verify that the specs really mean to use autoinc here. - for (i = 0; i < 3; i++) - b43_ntab_write(dev, B43_NTAB16(7, 0x106) + i, 0x673); - } - - /* Set minimum gain value */ - b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, - ~B43_NPHY_C1_MINGAIN, - 23 << B43_NPHY_C1_MINGAIN_SHIFT); - b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, - ~B43_NPHY_C2_MINGAIN, - 23 << B43_NPHY_C2_MINGAIN_SHIFT); - - if (phy->rev < 2) { - b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL, - ~B43_NPHY_SCRAM_SIGCTL_SCM); - } - - /* Set phase track alpha and beta */ - b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125); - b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3); - b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105); - b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E); - b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD); - b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); -} - -static void b43_nphy_reset_cca(struct b43_wldev *dev) -{ - u16 bbcfg; - - ssb_write32(dev->dev, SSB_TMSLOW, - ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC); - bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); - b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA); - b43_phy_write(dev, B43_NPHY_BBCFG, - bbcfg & ~B43_NPHY_BBCFG_RSTCCA); - ssb_write32(dev->dev, SSB_TMSLOW, - ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC); -} - -enum b43_nphy_rf_sequence { - B43_RFSEQ_RX2TX, - B43_RFSEQ_TX2RX, - B43_RFSEQ_RESET2RX, - B43_RFSEQ_UPDATE_GAINH, - B43_RFSEQ_UPDATE_GAINL, - B43_RFSEQ_UPDATE_GAINU, -}; - -static void b43_nphy_force_rf_sequence(struct b43_wldev *dev, - enum b43_nphy_rf_sequence seq) -{ - static const u16 trigger[] = { - [B43_RFSEQ_RX2TX] = B43_NPHY_RFSEQTR_RX2TX, - [B43_RFSEQ_TX2RX] = B43_NPHY_RFSEQTR_TX2RX, - [B43_RFSEQ_RESET2RX] = B43_NPHY_RFSEQTR_RST2RX, - [B43_RFSEQ_UPDATE_GAINH] = B43_NPHY_RFSEQTR_UPGH, - [B43_RFSEQ_UPDATE_GAINL] = B43_NPHY_RFSEQTR_UPGL, - [B43_RFSEQ_UPDATE_GAINU] = B43_NPHY_RFSEQTR_UPGU, - }; - int i; - - B43_WARN_ON(seq >= ARRAY_SIZE(trigger)); - - b43_phy_set(dev, B43_NPHY_RFSEQMODE, - B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER); - b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]); - for (i = 0; i < 200; i++) { - if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq])) - goto ok; - msleep(1); - } - b43err(dev->wl, "RF sequence status timeout\n"); -ok: - b43_phy_mask(dev, B43_NPHY_RFSEQMODE, - ~(B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER)); -} - -static void b43_nphy_bphy_init(struct b43_wldev *dev) -{ - unsigned int i; - u16 val; - - val = 0x1E1F; - for (i = 0; i < 14; i++) { - b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val); - val -= 0x202; - } - val = 0x3E3F; - for (i = 0; i < 16; i++) { - b43_phy_write(dev, B43_PHY_N_BMODE(0x97 + i), val); - val -= 0x202; - } - b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); -} - -/* RSSI Calibration */ -static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) -{ - //TODO -} - -int b43_phy_initn(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 tmp; - - //TODO: Spectral management - b43_nphy_tables_init(dev); - - /* Clear all overrides */ - b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); - b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); - b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); - b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); - b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); - b43_phy_mask(dev, B43_NPHY_RFSEQMODE, - ~(B43_NPHY_RFSEQMODE_CAOVER | - B43_NPHY_RFSEQMODE_TROVER)); - b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); - - tmp = (phy->rev < 2) ? 64 : 59; - b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, - ~B43_NPHY_BPHY_CTL3_SCALE, - tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); - - b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); - b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); - - b43_phy_write(dev, B43_NPHY_TXREALFD, 184); - b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200); - b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80); - b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511); - - //TODO MIMO-Config - //TODO Update TX/RX chain - - if (phy->rev < 2) { - b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); - b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); - } - b43_nphy_workarounds(dev); - b43_nphy_reset_cca(dev); - - ssb_write32(dev->dev, SSB_TMSLOW, - ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN); - b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); - b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); - - b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */ - //TODO read core1/2 clip1 thres regs - - if (1 /* FIXME Band is 2.4GHz */) - b43_nphy_bphy_init(dev); - //TODO disable TX power control - //TODO Fix the TX power settings - //TODO Init periodic calibration with reason 3 - b43_nphy_rssi_cal(dev, 2); - b43_nphy_rssi_cal(dev, 0); - b43_nphy_rssi_cal(dev, 1); - //TODO get TX gain - //TODO init superswitch - //TODO calibrate LO - //TODO idle TSSI TX pctl - //TODO TX power control power setup - //TODO table writes - //TODO TX power control coefficients - //TODO enable TX power control - //TODO control antenna selection - //TODO init radar detection - //TODO reset channel if changed - - b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); - return 0; -} - -static int b43_nphy_op_allocate(struct b43_wldev *dev) -{ - struct b43_phy_n *nphy; - - nphy = kzalloc(sizeof(*nphy), GFP_KERNEL); - if (!nphy) - return -ENOMEM; - dev->phy.n = nphy; - - return 0; -} - -static void b43_nphy_op_prepare_structs(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_n *nphy = phy->n; - - memset(nphy, 0, sizeof(*nphy)); - - //TODO init struct b43_phy_n -} - -static void b43_nphy_op_free(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_n *nphy = phy->n; - - kfree(nphy); - phy->n = NULL; -} - -static int b43_nphy_op_init(struct b43_wldev *dev) -{ - return b43_phy_initn(dev); -} - -static inline void check_phyreg(struct b43_wldev *dev, u16 offset) -{ -#if B43_DEBUG - if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) { - /* OFDM registers are onnly available on A/G-PHYs */ - b43err(dev->wl, "Invalid OFDM PHY access at " - "0x%04X on N-PHY\n", offset); - dump_stack(); - } - if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) { - /* Ext-G registers are only available on G-PHYs */ - b43err(dev->wl, "Invalid EXT-G PHY access at " - "0x%04X on N-PHY\n", offset); - dump_stack(); - } -#endif /* B43_DEBUG */ -} - -static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg) -{ - check_phyreg(dev, reg); - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - return b43_read16(dev, B43_MMIO_PHY_DATA); -} - -static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - check_phyreg(dev, reg); - b43_write16(dev, B43_MMIO_PHY_CONTROL, reg); - b43_write16(dev, B43_MMIO_PHY_DATA, value); -} - -static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - /* N-PHY needs 0x100 for read access */ - reg |= 0x100; - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW); -} - -static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value) -{ - /* Register 1 is a 32-bit register. */ - B43_WARN_ON(reg == 1); - - b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg); - b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value); -} - -static void b43_nphy_op_software_rfkill(struct b43_wldev *dev, - bool blocked) -{//TODO -} - -static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on) -{ - b43_phy_write(dev, B43_NPHY_AFECTL_OVER, - on ? 0 : 0x7FFF); -} - -static int b43_nphy_op_switch_channel(struct b43_wldev *dev, - unsigned int new_channel) -{ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if ((new_channel < 1) || (new_channel > 14)) - return -EINVAL; - } else { - if (new_channel > 200) - return -EINVAL; - } - - return nphy_channel_switch(dev, new_channel); -} - -static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev) -{ - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - return 1; - return 36; -} - -const struct b43_phy_operations b43_phyops_n = { - .allocate = b43_nphy_op_allocate, - .free = b43_nphy_op_free, - .prepare_structs = b43_nphy_op_prepare_structs, - .init = b43_nphy_op_init, - .phy_read = b43_nphy_op_read, - .phy_write = b43_nphy_op_write, - .radio_read = b43_nphy_op_radio_read, - .radio_write = b43_nphy_op_radio_write, - .software_rfkill = b43_nphy_op_software_rfkill, - .switch_analog = b43_nphy_op_switch_analog, - .switch_channel = b43_nphy_op_switch_channel, - .get_default_chan = b43_nphy_op_get_default_chan, - .recalc_txpower = b43_nphy_op_recalc_txpower, - .adjust_txpower = b43_nphy_op_adjust_txpower, -}; diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h deleted file mode 100644 index 1749aef4147d..000000000000 --- a/drivers/net/wireless/b43/phy_n.h +++ /dev/null @@ -1,930 +0,0 @@ -#ifndef B43_NPHY_H_ -#define B43_NPHY_H_ - -#include "phy_common.h" - - -/* N-PHY registers. */ - -#define B43_NPHY_BBCFG B43_PHY_N(0x001) /* BB config */ -#define B43_NPHY_BBCFG_RSTCCA 0x4000 /* Reset CCA */ -#define B43_NPHY_BBCFG_RSTRX 0x8000 /* Reset RX */ -#define B43_NPHY_CHANNEL B43_PHY_N(0x005) /* Channel */ -#define B43_NPHY_TXERR B43_PHY_N(0x007) /* TX error */ -#define B43_NPHY_BANDCTL B43_PHY_N(0x009) /* Band control */ -#define B43_NPHY_BANDCTL_5GHZ 0x0001 /* Use the 5GHz band */ -#define B43_NPHY_4WI_ADDR B43_PHY_N(0x00B) /* Four-wire bus address */ -#define B43_NPHY_4WI_DATAHI B43_PHY_N(0x00C) /* Four-wire bus data high */ -#define B43_NPHY_4WI_DATALO B43_PHY_N(0x00D) /* Four-wire bus data low */ -#define B43_NPHY_BIST_STAT0 B43_PHY_N(0x00E) /* Built-in self test status 0 */ -#define B43_NPHY_BIST_STAT1 B43_PHY_N(0x00F) /* Built-in self test status 1 */ - -#define B43_NPHY_C1_DESPWR B43_PHY_N(0x018) /* Core 1 desired power */ -#define B43_NPHY_C1_CCK_DESPWR B43_PHY_N(0x019) /* Core 1 CCK desired power */ -#define B43_NPHY_C1_BCLIPBKOFF B43_PHY_N(0x01A) /* Core 1 barely clip backoff */ -#define B43_NPHY_C1_CCK_BCLIPBKOFF B43_PHY_N(0x01B) /* Core 1 CCK barely clip backoff */ -#define B43_NPHY_C1_CGAINI B43_PHY_N(0x01C) /* Core 1 compute gain info */ -#define B43_NPHY_C1_CGAINI_GAINBKOFF 0x001F /* Gain backoff */ -#define B43_NPHY_C1_CGAINI_GAINBKOFF_SHIFT 0 -#define B43_NPHY_C1_CGAINI_CLIPGBKOFF 0x03E0 /* Clip gain backoff */ -#define B43_NPHY_C1_CGAINI_CLIPGBKOFF_SHIFT 5 -#define B43_NPHY_C1_CGAINI_GAINSTEP 0x1C00 /* Gain step */ -#define B43_NPHY_C1_CGAINI_GAINSTEP_SHIFT 10 -#define B43_NPHY_C1_CGAINI_CL2DETECT 0x2000 /* Clip 2 detect mask */ -#define B43_NPHY_C1_CCK_CGAINI B43_PHY_N(0x01D) /* Core 1 CCK compute gain info */ -#define B43_NPHY_C1_CCK_CGAINI_GAINBKOFF 0x001F /* Gain backoff */ -#define B43_NPHY_C1_CCK_CGAINI_CLIPGBKOFF 0x01E0 /* CCK barely clip gain backoff */ -#define B43_NPHY_C1_MINMAX_GAIN B43_PHY_N(0x01E) /* Core 1 min/max gain */ -#define B43_NPHY_C1_MINGAIN 0x00FF /* Minimum gain */ -#define B43_NPHY_C1_MINGAIN_SHIFT 0 -#define B43_NPHY_C1_MAXGAIN 0xFF00 /* Maximum gain */ -#define B43_NPHY_C1_MAXGAIN_SHIFT 8 -#define B43_NPHY_C1_CCK_MINMAX_GAIN B43_PHY_N(0x01F) /* Core 1 CCK min/max gain */ -#define B43_NPHY_C1_CCK_MINGAIN 0x00FF /* Minimum gain */ -#define B43_NPHY_C1_CCK_MINGAIN_SHIFT 0 -#define B43_NPHY_C1_CCK_MAXGAIN 0xFF00 /* Maximum gain */ -#define B43_NPHY_C1_CCK_MAXGAIN_SHIFT 8 -#define B43_NPHY_C1_INITGAIN B43_PHY_N(0x020) /* Core 1 initial gain code */ -#define B43_NPHY_C1_INITGAIN_EXTLNA 0x0001 /* External LNA index */ -#define B43_NPHY_C1_INITGAIN_LNA 0x0006 /* LNA index */ -#define B43_NPHY_C1_INITGAIN_LNAIDX_SHIFT 1 -#define B43_NPHY_C1_INITGAIN_HPVGA1 0x0078 /* HPVGA1 index */ -#define B43_NPHY_C1_INITGAIN_HPVGA1_SHIFT 3 -#define B43_NPHY_C1_INITGAIN_HPVGA2 0x0F80 /* HPVGA2 index */ -#define B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT 7 -#define B43_NPHY_C1_INITGAIN_TRRX 0x1000 /* TR RX index */ -#define B43_NPHY_C1_INITGAIN_TRTX 0x2000 /* TR TX index */ -#define B43_NPHY_C1_CLIP1_HIGAIN B43_PHY_N(0x021) /* Core 1 clip1 high gain code */ -#define B43_NPHY_C1_CLIP1_MEDGAIN B43_PHY_N(0x022) /* Core 1 clip1 medium gain code */ -#define B43_NPHY_C1_CLIP1_LOGAIN B43_PHY_N(0x023) /* Core 1 clip1 low gain code */ -#define B43_NPHY_C1_CLIP2_GAIN B43_PHY_N(0x024) /* Core 1 clip2 gain code */ -#define B43_NPHY_C1_FILTERGAIN B43_PHY_N(0x025) /* Core 1 filter gain */ -#define B43_NPHY_C1_LPF_QHPF_BW B43_PHY_N(0x026) /* Core 1 LPF Q HP F bandwidth */ -#define B43_NPHY_C1_CLIPWBTHRES B43_PHY_N(0x027) /* Core 1 clip wideband threshold */ -#define B43_NPHY_C1_CLIPWBTHRES_CLIP2 0x003F /* Clip 2 */ -#define B43_NPHY_C1_CLIPWBTHRES_CLIP2_SHIFT 0 -#define B43_NPHY_C1_CLIPWBTHRES_CLIP1 0x0FC0 /* Clip 1 */ -#define B43_NPHY_C1_CLIPWBTHRES_CLIP1_SHIFT 6 -#define B43_NPHY_C1_W1THRES B43_PHY_N(0x028) /* Core 1 W1 threshold */ -#define B43_NPHY_C1_EDTHRES B43_PHY_N(0x029) /* Core 1 ED threshold */ -#define B43_NPHY_C1_SMSIGTHRES B43_PHY_N(0x02A) /* Core 1 small sig threshold */ -#define B43_NPHY_C1_NBCLIPTHRES B43_PHY_N(0x02B) /* Core 1 NB clip threshold */ -#define B43_NPHY_C1_CLIP1THRES B43_PHY_N(0x02C) /* Core 1 clip1 threshold */ -#define B43_NPHY_C1_CLIP2THRES B43_PHY_N(0x02D) /* Core 1 clip2 threshold */ - -#define B43_NPHY_C2_DESPWR B43_PHY_N(0x02E) /* Core 2 desired power */ -#define B43_NPHY_C2_CCK_DESPWR B43_PHY_N(0x02F) /* Core 2 CCK desired power */ -#define B43_NPHY_C2_BCLIPBKOFF B43_PHY_N(0x030) /* Core 2 barely clip backoff */ -#define B43_NPHY_C2_CCK_BCLIPBKOFF B43_PHY_N(0x031) /* Core 2 CCK barely clip backoff */ -#define B43_NPHY_C2_CGAINI B43_PHY_N(0x032) /* Core 2 compute gain info */ -#define B43_NPHY_C2_CGAINI_GAINBKOFF 0x001F /* Gain backoff */ -#define B43_NPHY_C2_CGAINI_GAINBKOFF_SHIFT 0 -#define B43_NPHY_C2_CGAINI_CLIPGBKOFF 0x03E0 /* Clip gain backoff */ -#define B43_NPHY_C2_CGAINI_CLIPGBKOFF_SHIFT 5 -#define B43_NPHY_C2_CGAINI_GAINSTEP 0x1C00 /* Gain step */ -#define B43_NPHY_C2_CGAINI_GAINSTEP_SHIFT 10 -#define B43_NPHY_C2_CGAINI_CL2DETECT 0x2000 /* Clip 2 detect mask */ -#define B43_NPHY_C2_CCK_CGAINI B43_PHY_N(0x033) /* Core 2 CCK compute gain info */ -#define B43_NPHY_C2_CCK_CGAINI_GAINBKOFF 0x001F /* Gain backoff */ -#define B43_NPHY_C2_CCK_CGAINI_CLIPGBKOFF 0x01E0 /* CCK barely clip gain backoff */ -#define B43_NPHY_C2_MINMAX_GAIN B43_PHY_N(0x034) /* Core 2 min/max gain */ -#define B43_NPHY_C2_MINGAIN 0x00FF /* Minimum gain */ -#define B43_NPHY_C2_MINGAIN_SHIFT 0 -#define B43_NPHY_C2_MAXGAIN 0xFF00 /* Maximum gain */ -#define B43_NPHY_C2_MAXGAIN_SHIFT 8 -#define B43_NPHY_C2_CCK_MINMAX_GAIN B43_PHY_N(0x035) /* Core 2 CCK min/max gain */ -#define B43_NPHY_C2_CCK_MINGAIN 0x00FF /* Minimum gain */ -#define B43_NPHY_C2_CCK_MINGAIN_SHIFT 0 -#define B43_NPHY_C2_CCK_MAXGAIN 0xFF00 /* Maximum gain */ -#define B43_NPHY_C2_CCK_MAXGAIN_SHIFT 8 -#define B43_NPHY_C2_INITGAIN B43_PHY_N(0x036) /* Core 2 initial gain code */ -#define B43_NPHY_C2_INITGAIN_EXTLNA 0x0001 /* External LNA index */ -#define B43_NPHY_C2_INITGAIN_LNA 0x0006 /* LNA index */ -#define B43_NPHY_C2_INITGAIN_LNAIDX_SHIFT 1 -#define B43_NPHY_C2_INITGAIN_HPVGA1 0x0078 /* HPVGA1 index */ -#define B43_NPHY_C2_INITGAIN_HPVGA1_SHIFT 3 -#define B43_NPHY_C2_INITGAIN_HPVGA2 0x0F80 /* HPVGA2 index */ -#define B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT 7 -#define B43_NPHY_C2_INITGAIN_TRRX 0x1000 /* TR RX index */ -#define B43_NPHY_C2_INITGAIN_TRTX 0x2000 /* TR TX index */ -#define B43_NPHY_C2_CLIP1_HIGAIN B43_PHY_N(0x037) /* Core 2 clip1 high gain code */ -#define B43_NPHY_C2_CLIP1_MEDGAIN B43_PHY_N(0x038) /* Core 2 clip1 medium gain code */ -#define B43_NPHY_C2_CLIP1_LOGAIN B43_PHY_N(0x039) /* Core 2 clip1 low gain code */ -#define B43_NPHY_C2_CLIP2_GAIN B43_PHY_N(0x03A) /* Core 2 clip2 gain code */ -#define B43_NPHY_C2_FILTERGAIN B43_PHY_N(0x03B) /* Core 2 filter gain */ -#define B43_NPHY_C2_LPF_QHPF_BW B43_PHY_N(0x03C) /* Core 2 LPF Q HP F bandwidth */ -#define B43_NPHY_C2_CLIPWBTHRES B43_PHY_N(0x03D) /* Core 2 clip wideband threshold */ -#define B43_NPHY_C2_CLIPWBTHRES_CLIP2 0x003F /* Clip 2 */ -#define B43_NPHY_C2_CLIPWBTHRES_CLIP2_SHIFT 0 -#define B43_NPHY_C2_CLIPWBTHRES_CLIP1 0x0FC0 /* Clip 1 */ -#define B43_NPHY_C2_CLIPWBTHRES_CLIP1_SHIFT 6 -#define B43_NPHY_C2_W1THRES B43_PHY_N(0x03E) /* Core 2 W1 threshold */ -#define B43_NPHY_C2_EDTHRES B43_PHY_N(0x03F) /* Core 2 ED threshold */ -#define B43_NPHY_C2_SMSIGTHRES B43_PHY_N(0x040) /* Core 2 small sig threshold */ -#define B43_NPHY_C2_NBCLIPTHRES B43_PHY_N(0x041) /* Core 2 NB clip threshold */ -#define B43_NPHY_C2_CLIP1THRES B43_PHY_N(0x042) /* Core 2 clip1 threshold */ -#define B43_NPHY_C2_CLIP2THRES B43_PHY_N(0x043) /* Core 2 clip2 threshold */ - -#define B43_NPHY_CRS_THRES1 B43_PHY_N(0x044) /* CRS threshold 1 */ -#define B43_NPHY_CRS_THRES2 B43_PHY_N(0x045) /* CRS threshold 2 */ -#define B43_NPHY_CRS_THRES3 B43_PHY_N(0x046) /* CRS threshold 3 */ -#define B43_NPHY_CRSCTL B43_PHY_N(0x047) /* CRS control */ -#define B43_NPHY_DCFADDR B43_PHY_N(0x048) /* DC filter address */ -#define B43_NPHY_RXF20_NUM0 B43_PHY_N(0x049) /* RX filter 20 numerator 0 */ -#define B43_NPHY_RXF20_NUM1 B43_PHY_N(0x04A) /* RX filter 20 numerator 1 */ -#define B43_NPHY_RXF20_NUM2 B43_PHY_N(0x04B) /* RX filter 20 numerator 2 */ -#define B43_NPHY_RXF20_DENOM0 B43_PHY_N(0x04C) /* RX filter 20 denominator 0 */ -#define B43_NPHY_RXF20_DENOM1 B43_PHY_N(0x04D) /* RX filter 20 denominator 1 */ -#define B43_NPHY_RXF20_NUM10 B43_PHY_N(0x04E) /* RX filter 20 numerator 10 */ -#define B43_NPHY_RXF20_NUM11 B43_PHY_N(0x04F) /* RX filter 20 numerator 11 */ -#define B43_NPHY_RXF20_NUM12 B43_PHY_N(0x050) /* RX filter 20 numerator 12 */ -#define B43_NPHY_RXF20_DENOM10 B43_PHY_N(0x051) /* RX filter 20 denominator 10 */ -#define B43_NPHY_RXF20_DENOM11 B43_PHY_N(0x052) /* RX filter 20 denominator 11 */ -#define B43_NPHY_RXF40_NUM0 B43_PHY_N(0x053) /* RX filter 40 numerator 0 */ -#define B43_NPHY_RXF40_NUM1 B43_PHY_N(0x054) /* RX filter 40 numerator 1 */ -#define B43_NPHY_RXF40_NUM2 B43_PHY_N(0x055) /* RX filter 40 numerator 2 */ -#define B43_NPHY_RXF40_DENOM0 B43_PHY_N(0x056) /* RX filter 40 denominator 0 */ -#define B43_NPHY_RXF40_DENOM1 B43_PHY_N(0x057) /* RX filter 40 denominator 1 */ -#define B43_NPHY_RXF40_NUM10 B43_PHY_N(0x058) /* RX filter 40 numerator 10 */ -#define B43_NPHY_RXF40_NUM11 B43_PHY_N(0x059) /* RX filter 40 numerator 11 */ -#define B43_NPHY_RXF40_NUM12 B43_PHY_N(0x05A) /* RX filter 40 numerator 12 */ -#define B43_NPHY_RXF40_DENOM10 B43_PHY_N(0x05B) /* RX filter 40 denominator 10 */ -#define B43_NPHY_RXF40_DENOM11 B43_PHY_N(0x05C) /* RX filter 40 denominator 11 */ -#define B43_NPHY_PPROC_RSTLEN B43_PHY_N(0x060) /* Packet processing reset length */ -#define B43_NPHY_INITCARR_DLEN B43_PHY_N(0x061) /* Initial carrier detection length */ -#define B43_NPHY_CLIP1CARR_DLEN B43_PHY_N(0x062) /* Clip1 carrier detection length */ -#define B43_NPHY_CLIP2CARR_DLEN B43_PHY_N(0x063) /* Clip2 carrier detection length */ -#define B43_NPHY_INITGAIN_SLEN B43_PHY_N(0x064) /* Initial gain settle length */ -#define B43_NPHY_CLIP1GAIN_SLEN B43_PHY_N(0x065) /* Clip1 gain settle length */ -#define B43_NPHY_CLIP2GAIN_SLEN B43_PHY_N(0x066) /* Clip2 gain settle length */ -#define B43_NPHY_PACKGAIN_SLEN B43_PHY_N(0x067) /* Packet gain settle length */ -#define B43_NPHY_CARRSRC_TLEN B43_PHY_N(0x068) /* Carrier search timeout length */ -#define B43_NPHY_TISRC_TLEN B43_PHY_N(0x069) /* Timing search timeout length */ -#define B43_NPHY_ENDROP_TLEN B43_PHY_N(0x06A) /* Energy drop timeout length */ -#define B43_NPHY_CLIP1_NBDWELL_LEN B43_PHY_N(0x06B) /* Clip1 NB dwell length */ -#define B43_NPHY_CLIP2_NBDWELL_LEN B43_PHY_N(0x06C) /* Clip2 NB dwell length */ -#define B43_NPHY_W1CLIP1_DWELL_LEN B43_PHY_N(0x06D) /* W1 clip1 dwell length */ -#define B43_NPHY_W1CLIP2_DWELL_LEN B43_PHY_N(0x06E) /* W1 clip2 dwell length */ -#define B43_NPHY_W2CLIP1_DWELL_LEN B43_PHY_N(0x06F) /* W2 clip1 dwell length */ -#define B43_NPHY_PLOAD_CSENSE_EXTLEN B43_PHY_N(0x070) /* Payload carrier sense extension length */ -#define B43_NPHY_EDROP_CSENSE_EXTLEN B43_PHY_N(0x071) /* Energy drop carrier sense extension length */ -#define B43_NPHY_TABLE_ADDR B43_PHY_N(0x072) /* Table address */ -#define B43_NPHY_TABLE_DATALO B43_PHY_N(0x073) /* Table data low */ -#define B43_NPHY_TABLE_DATAHI B43_PHY_N(0x074) /* Table data high */ -#define B43_NPHY_WWISE_LENIDX B43_PHY_N(0x075) /* WWiSE length index */ -#define B43_NPHY_TGNSYNC_LENIDX B43_PHY_N(0x076) /* TGNsync length index */ -#define B43_NPHY_TXMACIF_HOLDOFF B43_PHY_N(0x077) /* TX MAC IF Hold off */ -#define B43_NPHY_RFCTL_CMD B43_PHY_N(0x078) /* RF control (command) */ -#define B43_NPHY_RFCTL_CMD_START 0x0001 /* Start sequence */ -#define B43_NPHY_RFCTL_CMD_RXTX 0x0002 /* RX/TX */ -#define B43_NPHY_RFCTL_CMD_CORESEL 0x0038 /* Core select */ -#define B43_NPHY_RFCTL_CMD_CORESEL_SHIFT 3 -#define B43_NPHY_RFCTL_CMD_PORFORCE 0x0040 /* POR force */ -#define B43_NPHY_RFCTL_CMD_OEPORFORCE 0x0080 /* OE POR force */ -#define B43_NPHY_RFCTL_CMD_RXEN 0x0100 /* RX enable */ -#define B43_NPHY_RFCTL_CMD_TXEN 0x0200 /* TX enable */ -#define B43_NPHY_RFCTL_CMD_CHIP0PU 0x0400 /* Chip0 PU */ -#define B43_NPHY_RFCTL_CMD_EN 0x0800 /* Radio enabled */ -#define B43_NPHY_RFCTL_CMD_SEQENCORE 0xF000 /* Seq en core */ -#define B43_NPHY_RFCTL_CMD_SEQENCORE_SHIFT 12 -#define B43_NPHY_RFCTL_RSSIO1 B43_PHY_N(0x07A) /* RF control (RSSI others 1) */ -#define B43_NPHY_RFCTL_RSSIO1_RXPD 0x0001 /* RX PD */ -#define B43_NPHY_RFCTL_RSSIO1_TXPD 0x0002 /* TX PD */ -#define B43_NPHY_RFCTL_RSSIO1_PAPD 0x0004 /* PA PD */ -#define B43_NPHY_RFCTL_RSSIO1_RSSICTL 0x0030 /* RSSI control */ -#define B43_NPHY_RFCTL_RSSIO1_LPFBW 0x00C0 /* LPF bandwidth */ -#define B43_NPHY_RFCTL_RSSIO1_HPFBWHI 0x0100 /* HPF bandwidth high */ -#define B43_NPHY_RFCTL_RSSIO1_HIQDISCO 0x0200 /* HIQ dis core */ -#define B43_NPHY_RFCTL_RXG1 B43_PHY_N(0x07B) /* RF control (RX gain 1) */ -#define B43_NPHY_RFCTL_TXG1 B43_PHY_N(0x07C) /* RF control (TX gain 1) */ -#define B43_NPHY_RFCTL_RSSIO2 B43_PHY_N(0x07D) /* RF control (RSSI others 2) */ -#define B43_NPHY_RFCTL_RSSIO2_RXPD 0x0001 /* RX PD */ -#define B43_NPHY_RFCTL_RSSIO2_TXPD 0x0002 /* TX PD */ -#define B43_NPHY_RFCTL_RSSIO2_PAPD 0x0004 /* PA PD */ -#define B43_NPHY_RFCTL_RSSIO2_RSSICTL 0x0030 /* RSSI control */ -#define B43_NPHY_RFCTL_RSSIO2_LPFBW 0x00C0 /* LPF bandwidth */ -#define B43_NPHY_RFCTL_RSSIO2_HPFBWHI 0x0100 /* HPF bandwidth high */ -#define B43_NPHY_RFCTL_RSSIO2_HIQDISCO 0x0200 /* HIQ dis core */ -#define B43_NPHY_RFCTL_RXG2 B43_PHY_N(0x07E) /* RF control (RX gain 2) */ -#define B43_NPHY_RFCTL_TXG2 B43_PHY_N(0x07F) /* RF control (TX gain 2) */ -#define B43_NPHY_RFCTL_RSSIO3 B43_PHY_N(0x080) /* RF control (RSSI others 3) */ -#define B43_NPHY_RFCTL_RSSIO3_RXPD 0x0001 /* RX PD */ -#define B43_NPHY_RFCTL_RSSIO3_TXPD 0x0002 /* TX PD */ -#define B43_NPHY_RFCTL_RSSIO3_PAPD 0x0004 /* PA PD */ -#define B43_NPHY_RFCTL_RSSIO3_RSSICTL 0x0030 /* RSSI control */ -#define B43_NPHY_RFCTL_RSSIO3_LPFBW 0x00C0 /* LPF bandwidth */ -#define B43_NPHY_RFCTL_RSSIO3_HPFBWHI 0x0100 /* HPF bandwidth high */ -#define B43_NPHY_RFCTL_RSSIO3_HIQDISCO 0x0200 /* HIQ dis core */ -#define B43_NPHY_RFCTL_RXG3 B43_PHY_N(0x081) /* RF control (RX gain 3) */ -#define B43_NPHY_RFCTL_TXG3 B43_PHY_N(0x082) /* RF control (TX gain 3) */ -#define B43_NPHY_RFCTL_RSSIO4 B43_PHY_N(0x083) /* RF control (RSSI others 4) */ -#define B43_NPHY_RFCTL_RSSIO4_RXPD 0x0001 /* RX PD */ -#define B43_NPHY_RFCTL_RSSIO4_TXPD 0x0002 /* TX PD */ -#define B43_NPHY_RFCTL_RSSIO4_PAPD 0x0004 /* PA PD */ -#define B43_NPHY_RFCTL_RSSIO4_RSSICTL 0x0030 /* RSSI control */ -#define B43_NPHY_RFCTL_RSSIO4_LPFBW 0x00C0 /* LPF bandwidth */ -#define B43_NPHY_RFCTL_RSSIO4_HPFBWHI 0x0100 /* HPF bandwidth high */ -#define B43_NPHY_RFCTL_RSSIO4_HIQDISCO 0x0200 /* HIQ dis core */ -#define B43_NPHY_RFCTL_RXG4 B43_PHY_N(0x084) /* RF control (RX gain 4) */ -#define B43_NPHY_RFCTL_TXG4 B43_PHY_N(0x085) /* RF control (TX gain 4) */ -#define B43_NPHY_C1_TXIQ_COMP_OFF B43_PHY_N(0x087) /* Core 1 TX I/Q comp offset */ -#define B43_NPHY_C2_TXIQ_COMP_OFF B43_PHY_N(0x088) /* Core 2 TX I/Q comp offset */ -#define B43_NPHY_C1_TXCTL B43_PHY_N(0x08B) /* Core 1 TX control */ -#define B43_NPHY_C2_TXCTL B43_PHY_N(0x08C) /* Core 2 TX control */ -#define B43_NPHY_SCRAM_SIGCTL B43_PHY_N(0x090) /* Scram signal control */ -#define B43_NPHY_SCRAM_SIGCTL_INITST 0x007F /* Initial state value */ -#define B43_NPHY_SCRAM_SIGCTL_INITST_SHIFT 0 -#define B43_NPHY_SCRAM_SIGCTL_SCM 0x0080 /* Scram control mode */ -#define B43_NPHY_SCRAM_SIGCTL_SICE 0x0100 /* Scram index control enable */ -#define B43_NPHY_SCRAM_SIGCTL_START 0xFE00 /* Scram start bit */ -#define B43_NPHY_SCRAM_SIGCTL_START_SHIFT 9 -#define B43_NPHY_RFCTL_INTC1 B43_PHY_N(0x091) /* RF control (intc 1) */ -#define B43_NPHY_RFCTL_INTC2 B43_PHY_N(0x092) /* RF control (intc 2) */ -#define B43_NPHY_RFCTL_INTC3 B43_PHY_N(0x093) /* RF control (intc 3) */ -#define B43_NPHY_RFCTL_INTC4 B43_PHY_N(0x094) /* RF control (intc 4) */ -#define B43_NPHY_NRDTO_WWISE B43_PHY_N(0x095) /* # datatones WWiSE */ -#define B43_NPHY_NRDTO_TGNSYNC B43_PHY_N(0x096) /* # datatones TGNsync */ -#define B43_NPHY_SIGFMOD_WWISE B43_PHY_N(0x097) /* Signal field mod WWiSE */ -#define B43_NPHY_LEG_SIGFMOD_11N B43_PHY_N(0x098) /* Legacy signal field mod 11n */ -#define B43_NPHY_HT_SIGFMOD_11N B43_PHY_N(0x099) /* HT signal field mod 11n */ -#define B43_NPHY_C1_RXIQ_COMPA0 B43_PHY_N(0x09A) /* Core 1 RX I/Q comp A0 */ -#define B43_NPHY_C1_RXIQ_COMPB0 B43_PHY_N(0x09B) /* Core 1 RX I/Q comp B0 */ -#define B43_NPHY_C2_RXIQ_COMPA1 B43_PHY_N(0x09C) /* Core 2 RX I/Q comp A1 */ -#define B43_NPHY_C2_RXIQ_COMPB1 B43_PHY_N(0x09D) /* Core 2 RX I/Q comp B1 */ -#define B43_NPHY_RXCTL B43_PHY_N(0x0A0) /* RX control */ -#define B43_NPHY_RXCTL_BSELU20 0x0010 /* Band select upper 20 */ -#define B43_NPHY_RXCTL_RIFSEN 0x0080 /* RIFS enable */ -#define B43_NPHY_RFSEQMODE B43_PHY_N(0x0A1) /* RF seq mode */ -#define B43_NPHY_RFSEQMODE_CAOVER 0x0001 /* Core active override */ -#define B43_NPHY_RFSEQMODE_TROVER 0x0002 /* Trigger override */ -#define B43_NPHY_RFSEQCA B43_PHY_N(0x0A2) /* RF seq core active */ -#define B43_NPHY_RFSEQCA_TXEN 0x000F /* TX enable */ -#define B43_NPHY_RFSEQCA_TXEN_SHIFT 0 -#define B43_NPHY_RFSEQCA_RXEN 0x00F0 /* RX enable */ -#define B43_NPHY_RFSEQCA_RXEN_SHIFT 4 -#define B43_NPHY_RFSEQCA_TXDIS 0x0F00 /* TX disable */ -#define B43_NPHY_RFSEQCA_TXDIS_SHIFT 8 -#define B43_NPHY_RFSEQCA_RXDIS 0xF000 /* RX disable */ -#define B43_NPHY_RFSEQCA_RXDIS_SHIFT 12 -#define B43_NPHY_RFSEQTR B43_PHY_N(0x0A3) /* RF seq trigger */ -#define B43_NPHY_RFSEQTR_RX2TX 0x0001 /* RX2TX */ -#define B43_NPHY_RFSEQTR_TX2RX 0x0002 /* TX2RX */ -#define B43_NPHY_RFSEQTR_UPGH 0x0004 /* Update gain H */ -#define B43_NPHY_RFSEQTR_UPGL 0x0008 /* Update gain L */ -#define B43_NPHY_RFSEQTR_UPGU 0x0010 /* Update gain U */ -#define B43_NPHY_RFSEQTR_RST2RX 0x0020 /* Reset to RX */ -#define B43_NPHY_RFSEQST B43_PHY_N(0x0A4) /* RF seq status. Values same as trigger. */ -#define B43_NPHY_AFECTL_OVER B43_PHY_N(0x0A5) /* AFE control override */ -#define B43_NPHY_AFECTL_C1 B43_PHY_N(0x0A6) /* AFE control core 1 */ -#define B43_NPHY_AFECTL_C2 B43_PHY_N(0x0A7) /* AFE control core 2 */ -#define B43_NPHY_AFECTL_C3 B43_PHY_N(0x0A8) /* AFE control core 3 */ -#define B43_NPHY_AFECTL_C4 B43_PHY_N(0x0A9) /* AFE control core 4 */ -#define B43_NPHY_AFECTL_DACGAIN1 B43_PHY_N(0x0AA) /* AFE control DAC gain 1 */ -#define B43_NPHY_AFECTL_DACGAIN2 B43_PHY_N(0x0AB) /* AFE control DAC gain 2 */ -#define B43_NPHY_AFECTL_DACGAIN3 B43_PHY_N(0x0AC) /* AFE control DAC gain 3 */ -#define B43_NPHY_AFECTL_DACGAIN4 B43_PHY_N(0x0AD) /* AFE control DAC gain 4 */ -#define B43_NPHY_STR_ADDR1 B43_PHY_N(0x0AE) /* STR address 1 */ -#define B43_NPHY_STR_ADDR2 B43_PHY_N(0x0AF) /* STR address 2 */ -#define B43_NPHY_CLASSCTL B43_PHY_N(0x0B0) /* Classifier control */ -#define B43_NPHY_CLASSCTL_CCKEN 0x0001 /* CCK enable */ -#define B43_NPHY_CLASSCTL_OFDMEN 0x0002 /* OFDM enable */ -#define B43_NPHY_CLASSCTL_WAITEDEN 0x0004 /* Waited enable */ -#define B43_NPHY_IQFLIP B43_PHY_N(0x0B1) /* I/Q flip */ -#define B43_NPHY_IQFLIP_ADC1 0x0001 /* ADC1 */ -#define B43_NPHY_IQFLIP_ADC2 0x0010 /* ADC2 */ -#define B43_NPHY_SISO_SNR_THRES B43_PHY_N(0x0B2) /* SISO SNR threshold */ -#define B43_NPHY_SIGMA_N_MULT B43_PHY_N(0x0B3) /* Sigma N multiplier */ -#define B43_NPHY_TXMACDELAY B43_PHY_N(0x0B4) /* TX MAC delay */ -#define B43_NPHY_TXFRAMEDELAY B43_PHY_N(0x0B5) /* TX frame delay */ -#define B43_NPHY_MLPARM B43_PHY_N(0x0B6) /* ML parameters */ -#define B43_NPHY_MLCTL B43_PHY_N(0x0B7) /* ML control */ -#define B43_NPHY_WWISE_20NCYCDAT B43_PHY_N(0x0B8) /* WWiSE 20 N cyc data */ -#define B43_NPHY_WWISE_40NCYCDAT B43_PHY_N(0x0B9) /* WWiSE 40 N cyc data */ -#define B43_NPHY_TGNSYNC_20NCYCDAT B43_PHY_N(0x0BA) /* TGNsync 20 N cyc data */ -#define B43_NPHY_TGNSYNC_40NCYCDAT B43_PHY_N(0x0BB) /* TGNsync 40 N cyc data */ -#define B43_NPHY_INITSWIZP B43_PHY_N(0x0BC) /* Initial swizzle pattern */ -#define B43_NPHY_TXTAILCNT B43_PHY_N(0x0BD) /* TX tail count value */ -#define B43_NPHY_BPHY_CTL1 B43_PHY_N(0x0BE) /* B PHY control 1 */ -#define B43_NPHY_BPHY_CTL2 B43_PHY_N(0x0BF) /* B PHY control 2 */ -#define B43_NPHY_BPHY_CTL2_LUT 0x001F /* LUT index */ -#define B43_NPHY_BPHY_CTL2_LUT_SHIFT 0 -#define B43_NPHY_BPHY_CTL2_MACDEL 0x7FE0 /* MAC delay */ -#define B43_NPHY_BPHY_CTL2_MACDEL_SHIFT 5 -#define B43_NPHY_IQLOCAL_CMD B43_PHY_N(0x0C0) /* I/Q LO cal command */ -#define B43_NPHY_IQLOCAL_CMD_EN 0x8000 -#define B43_NPHY_IQLOCAL_CMDNNUM B43_PHY_N(0x0C1) /* I/Q LO cal command N num */ -#define B43_NPHY_IQLOCAL_CMDGCTL B43_PHY_N(0x0C2) /* I/Q LO cal command G control */ -#define B43_NPHY_SAMP_CMD B43_PHY_N(0x0C3) /* Sample command */ -#define B43_NPHY_SAMP_CMD_STOP 0x0002 /* Stop */ -#define B43_NPHY_SAMP_LOOPCNT B43_PHY_N(0x0C4) /* Sample loop count */ -#define B43_NPHY_SAMP_WAITCNT B43_PHY_N(0x0C5) /* Sample wait count */ -#define B43_NPHY_SAMP_DEPCNT B43_PHY_N(0x0C6) /* Sample depth count */ -#define B43_NPHY_SAMP_STAT B43_PHY_N(0x0C7) /* Sample status */ -#define B43_NPHY_GPIO_LOOEN B43_PHY_N(0x0C8) /* GPIO low out enable */ -#define B43_NPHY_GPIO_HIOEN B43_PHY_N(0x0C9) /* GPIO high out enable */ -#define B43_NPHY_GPIO_SEL B43_PHY_N(0x0CA) /* GPIO select */ -#define B43_NPHY_GPIO_CLKCTL B43_PHY_N(0x0CB) /* GPIO clock control */ -#define B43_NPHY_TXF_20CO_AS0 B43_PHY_N(0x0CC) /* TX filter 20 coeff A stage 0 */ -#define B43_NPHY_TXF_20CO_AS1 B43_PHY_N(0x0CD) /* TX filter 20 coeff A stage 1 */ -#define B43_NPHY_TXF_20CO_AS2 B43_PHY_N(0x0CE) /* TX filter 20 coeff A stage 2 */ -#define B43_NPHY_TXF_20CO_B32S0 B43_PHY_N(0x0CF) /* TX filter 20 coeff B32 stage 0 */ -#define B43_NPHY_TXF_20CO_B1S0 B43_PHY_N(0x0D0) /* TX filter 20 coeff B1 stage 0 */ -#define B43_NPHY_TXF_20CO_B32S1 B43_PHY_N(0x0D1) /* TX filter 20 coeff B32 stage 1 */ -#define B43_NPHY_TXF_20CO_B1S1 B43_PHY_N(0x0D2) /* TX filter 20 coeff B1 stage 1 */ -#define B43_NPHY_TXF_20CO_B32S2 B43_PHY_N(0x0D3) /* TX filter 20 coeff B32 stage 2 */ -#define B43_NPHY_TXF_20CO_B1S2 B43_PHY_N(0x0D4) /* TX filter 20 coeff B1 stage 2 */ -#define B43_NPHY_SIGFLDTOL B43_PHY_N(0x0D5) /* Signal fld tolerance */ -#define B43_NPHY_TXSERFLD B43_PHY_N(0x0D6) /* TX service field */ -#define B43_NPHY_AFESEQ_RX2TX_PUD B43_PHY_N(0x0D7) /* AFE seq RX2TX power up/down delay */ -#define B43_NPHY_AFESEQ_TX2RX_PUD B43_PHY_N(0x0D8) /* AFE seq TX2RX power up/down delay */ -#define B43_NPHY_TGNSYNC_SCRAMI0 B43_PHY_N(0x0D9) /* TGNsync scram init 0 */ -#define B43_NPHY_TGNSYNC_SCRAMI1 B43_PHY_N(0x0DA) /* TGNsync scram init 1 */ -#define B43_NPHY_INITSWIZPATTLEG B43_PHY_N(0x0DB) /* Initial swizzle pattern leg */ -#define B43_NPHY_BPHY_CTL3 B43_PHY_N(0x0DC) /* B PHY control 3 */ -#define B43_NPHY_BPHY_CTL3_SCALE 0x00FF /* Scale */ -#define B43_NPHY_BPHY_CTL3_SCALE_SHIFT 0 -#define B43_NPHY_BPHY_CTL3_FSC 0xFF00 /* Frame start count value */ -#define B43_NPHY_BPHY_CTL3_FSC_SHIFT 8 -#define B43_NPHY_BPHY_CTL4 B43_PHY_N(0x0DD) /* B PHY control 4 */ -#define B43_NPHY_C1_TXBBMULT B43_PHY_N(0x0DE) /* Core 1 TX BB multiplier */ -#define B43_NPHY_C2_TXBBMULT B43_PHY_N(0x0DF) /* Core 2 TX BB multiplier */ -#define B43_NPHY_TXF_40CO_AS0 B43_PHY_N(0x0E1) /* TX filter 40 coeff A stage 0 */ -#define B43_NPHY_TXF_40CO_AS1 B43_PHY_N(0x0E2) /* TX filter 40 coeff A stage 1 */ -#define B43_NPHY_TXF_40CO_AS2 B43_PHY_N(0x0E3) /* TX filter 40 coeff A stage 2 */ -#define B43_NPHY_TXF_40CO_B32S0 B43_PHY_N(0x0E4) /* TX filter 40 coeff B32 stage 0 */ -#define B43_NPHY_TXF_40CO_B1S0 B43_PHY_N(0x0E5) /* TX filter 40 coeff B1 stage 0 */ -#define B43_NPHY_TXF_40CO_B32S1 B43_PHY_N(0x0E6) /* TX filter 40 coeff B32 stage 1 */ -#define B43_NPHY_TXF_40CO_B1S1 B43_PHY_N(0x0E7) /* TX filter 40 coeff B1 stage 1 */ -#define B43_NPHY_TXF_40CO_B32S2 B43_PHY_N(0x0E8) /* TX filter 40 coeff B32 stage 2 */ -#define B43_NPHY_TXF_40CO_B1S2 B43_PHY_N(0x0E9) /* TX filter 40 coeff B1 stage 2 */ -#define B43_NPHY_BIST_STAT2 B43_PHY_N(0x0EA) /* BIST status 2 */ -#define B43_NPHY_BIST_STAT3 B43_PHY_N(0x0EB) /* BIST status 3 */ -#define B43_NPHY_RFCTL_OVER B43_PHY_N(0x0EC) /* RF control override */ -#define B43_NPHY_MIMOCFG B43_PHY_N(0x0ED) /* MIMO config */ -#define B43_NPHY_MIMOCFG_GFMIX 0x0004 /* Greenfield or mixed mode */ -#define B43_NPHY_MIMOCFG_AUTO 0x0100 /* Greenfield/mixed mode auto */ -#define B43_NPHY_RADAR_BLNKCTL B43_PHY_N(0x0EE) /* Radar blank control */ -#define B43_NPHY_A0RADAR_FIFOCTL B43_PHY_N(0x0EF) /* Antenna 0 radar FIFO control */ -#define B43_NPHY_A1RADAR_FIFOCTL B43_PHY_N(0x0F0) /* Antenna 1 radar FIFO control */ -#define B43_NPHY_A0RADAR_FIFODAT B43_PHY_N(0x0F1) /* Antenna 0 radar FIFO data */ -#define B43_NPHY_A1RADAR_FIFODAT B43_PHY_N(0x0F2) /* Antenna 1 radar FIFO data */ -#define B43_NPHY_RADAR_THRES0 B43_PHY_N(0x0F3) /* Radar threshold 0 */ -#define B43_NPHY_RADAR_THRES1 B43_PHY_N(0x0F4) /* Radar threshold 1 */ -#define B43_NPHY_RADAR_THRES0R B43_PHY_N(0x0F5) /* Radar threshold 0R */ -#define B43_NPHY_RADAR_THRES1R B43_PHY_N(0x0F6) /* Radar threshold 1R */ -#define B43_NPHY_CSEN_20IN40_DLEN B43_PHY_N(0x0F7) /* Carrier sense 20 in 40 dwell length */ -#define B43_NPHY_RFCTL_LUT_TRSW_LO1 B43_PHY_N(0x0F8) /* RF control LUT TRSW lower 1 */ -#define B43_NPHY_RFCTL_LUT_TRSW_UP1 B43_PHY_N(0x0F9) /* RF control LUT TRSW upper 1 */ -#define B43_NPHY_RFCTL_LUT_TRSW_LO2 B43_PHY_N(0x0FA) /* RF control LUT TRSW lower 2 */ -#define B43_NPHY_RFCTL_LUT_TRSW_UP2 B43_PHY_N(0x0FB) /* RF control LUT TRSW upper 2 */ -#define B43_NPHY_RFCTL_LUT_TRSW_LO3 B43_PHY_N(0x0FC) /* RF control LUT TRSW lower 3 */ -#define B43_NPHY_RFCTL_LUT_TRSW_UP3 B43_PHY_N(0x0FD) /* RF control LUT TRSW upper 3 */ -#define B43_NPHY_RFCTL_LUT_TRSW_LO4 B43_PHY_N(0x0FE) /* RF control LUT TRSW lower 4 */ -#define B43_NPHY_RFCTL_LUT_TRSW_UP4 B43_PHY_N(0x0FF) /* RF control LUT TRSW upper 4 */ -#define B43_NPHY_RFCTL_LUT_LNAPA1 B43_PHY_N(0x100) /* RF control LUT LNA PA 1 */ -#define B43_NPHY_RFCTL_LUT_LNAPA2 B43_PHY_N(0x101) /* RF control LUT LNA PA 2 */ -#define B43_NPHY_RFCTL_LUT_LNAPA3 B43_PHY_N(0x102) /* RF control LUT LNA PA 3 */ -#define B43_NPHY_RFCTL_LUT_LNAPA4 B43_PHY_N(0x103) /* RF control LUT LNA PA 4 */ -#define B43_NPHY_TGNSYNC_CRCM0 B43_PHY_N(0x104) /* TGNsync CRC mask 0 */ -#define B43_NPHY_TGNSYNC_CRCM1 B43_PHY_N(0x105) /* TGNsync CRC mask 1 */ -#define B43_NPHY_TGNSYNC_CRCM2 B43_PHY_N(0x106) /* TGNsync CRC mask 2 */ -#define B43_NPHY_TGNSYNC_CRCM3 B43_PHY_N(0x107) /* TGNsync CRC mask 3 */ -#define B43_NPHY_TGNSYNC_CRCM4 B43_PHY_N(0x108) /* TGNsync CRC mask 4 */ -#define B43_NPHY_CRCPOLY B43_PHY_N(0x109) /* CRC polynomial */ -#define B43_NPHY_SIGCNT B43_PHY_N(0x10A) /* # sig count */ -#define B43_NPHY_SIGSTARTBIT_CTL B43_PHY_N(0x10B) /* Sig start bit control */ -#define B43_NPHY_CRCPOLY_ORDER B43_PHY_N(0x10C) /* CRC polynomial order */ -#define B43_NPHY_RFCTL_CST0 B43_PHY_N(0x10D) /* RF control core swap table 0 */ -#define B43_NPHY_RFCTL_CST1 B43_PHY_N(0x10E) /* RF control core swap table 1 */ -#define B43_NPHY_RFCTL_CST2O B43_PHY_N(0x10F) /* RF control core swap table 2 + others */ -#define B43_NPHY_BPHY_CTL5 B43_PHY_N(0x111) /* B PHY control 5 */ -#define B43_NPHY_RFSEQ_LPFBW B43_PHY_N(0x112) /* RF seq LPF bandwidth */ -#define B43_NPHY_TSSIBIAS1 B43_PHY_N(0x114) /* TSSI bias val 1 */ -#define B43_NPHY_TSSIBIAS2 B43_PHY_N(0x115) /* TSSI bias val 2 */ -#define B43_NPHY_TSSIBIAS_BIAS 0x00FF /* Bias */ -#define B43_NPHY_TSSIBIAS_BIAS_SHIFT 0 -#define B43_NPHY_TSSIBIAS_VAL 0xFF00 /* Value */ -#define B43_NPHY_TSSIBIAS_VAL_SHIFT 8 -#define B43_NPHY_ESTPWR1 B43_PHY_N(0x118) /* Estimated power 1 */ -#define B43_NPHY_ESTPWR2 B43_PHY_N(0x119) /* Estimated power 2 */ -#define B43_NPHY_ESTPWR_PWR 0x00FF /* Estimated power */ -#define B43_NPHY_ESTPWR_PWR_SHIFT 0 -#define B43_NPHY_ESTPWR_VALID 0x0100 /* Estimated power valid */ -#define B43_NPHY_TSSI_MAXTXFDT B43_PHY_N(0x11C) /* TSSI max TX frame delay time */ -#define B43_NPHY_TSSI_MAXTXFDT_VAL 0x00FF /* max TX frame delay time */ -#define B43_NPHY_TSSI_MAXTXFDT_VAL_SHIFT 0 -#define B43_NPHY_TSSI_MAXTDT B43_PHY_N(0x11D) /* TSSI max TSSI delay time */ -#define B43_NPHY_TSSI_MAXTDT_VAL 0x00FF /* max TSSI delay time */ -#define B43_NPHY_TSSI_MAXTDT_VAL_SHIFT 0 -#define B43_NPHY_ITSSI1 B43_PHY_N(0x11E) /* TSSI idle 1 */ -#define B43_NPHY_ITSSI2 B43_PHY_N(0x11F) /* TSSI idle 2 */ -#define B43_NPHY_ITSSI_VAL 0x00FF /* Idle TSSI */ -#define B43_NPHY_ITSSI_VAL_SHIFT 0 -#define B43_NPHY_TSSIMODE B43_PHY_N(0x122) /* TSSI mode */ -#define B43_NPHY_TSSIMODE_EN 0x0001 /* TSSI enable */ -#define B43_NPHY_TSSIMODE_PDEN 0x0002 /* Power det enable */ -#define B43_NPHY_RXMACIFM B43_PHY_N(0x123) /* RX Macif mode */ -#define B43_NPHY_CRSIT_COCNT_LO B43_PHY_N(0x124) /* CRS idle time CRS-on count (low) */ -#define B43_NPHY_CRSIT_COCNT_HI B43_PHY_N(0x125) /* CRS idle time CRS-on count (high) */ -#define B43_NPHY_CRSIT_MTCNT_LO B43_PHY_N(0x126) /* CRS idle time measure time count (low) */ -#define B43_NPHY_CRSIT_MTCNT_HI B43_PHY_N(0x127) /* CRS idle time measure time count (high) */ -#define B43_NPHY_SAMTWC B43_PHY_N(0x128) /* Sample tail wait count */ -#define B43_NPHY_IQEST_CMD B43_PHY_N(0x129) /* I/Q estimate command */ -#define B43_NPHY_IQEST_CMD_START 0x0001 /* Start */ -#define B43_NPHY_IQEST_CMD_MODE 0x0002 /* Mode */ -#define B43_NPHY_IQEST_WT B43_PHY_N(0x12A) /* I/Q estimate wait time */ -#define B43_NPHY_IQEST_WT_VAL 0x00FF /* Wait time */ -#define B43_NPHY_IQEST_WT_VAL_SHIFT 0 -#define B43_NPHY_IQEST_SAMCNT B43_PHY_N(0x12B) /* I/Q estimate sample count */ -#define B43_NPHY_IQEST_IQACC_LO0 B43_PHY_N(0x12C) /* I/Q estimate I/Q acc lo 0 */ -#define B43_NPHY_IQEST_IQACC_HI0 B43_PHY_N(0x12D) /* I/Q estimate I/Q acc hi 0 */ -#define B43_NPHY_IQEST_IPACC_LO0 B43_PHY_N(0x12E) /* I/Q estimate I power acc lo 0 */ -#define B43_NPHY_IQEST_IPACC_HI0 B43_PHY_N(0x12F) /* I/Q estimate I power acc hi 0 */ -#define B43_NPHY_IQEST_QPACC_LO0 B43_PHY_N(0x130) /* I/Q estimate Q power acc lo 0 */ -#define B43_NPHY_IQEST_QPACC_HI0 B43_PHY_N(0x131) /* I/Q estimate Q power acc hi 0 */ -#define B43_NPHY_IQEST_IQACC_LO1 B43_PHY_N(0x134) /* I/Q estimate I/Q acc lo 1 */ -#define B43_NPHY_IQEST_IQACC_HI1 B43_PHY_N(0x135) /* I/Q estimate I/Q acc hi 1 */ -#define B43_NPHY_IQEST_IPACC_LO1 B43_PHY_N(0x136) /* I/Q estimate I power acc lo 1 */ -#define B43_NPHY_IQEST_IPACC_HI1 B43_PHY_N(0x137) /* I/Q estimate I power acc hi 1 */ -#define B43_NPHY_IQEST_QPACC_LO1 B43_PHY_N(0x138) /* I/Q estimate Q power acc lo 1 */ -#define B43_NPHY_IQEST_QPACC_HI1 B43_PHY_N(0x139) /* I/Q estimate Q power acc hi 1 */ -#define B43_NPHY_MIMO_CRSTXEXT B43_PHY_N(0x13A) /* MIMO PHY CRS TX extension */ -#define B43_NPHY_PWRDET1 B43_PHY_N(0x13B) /* Power det 1 */ -#define B43_NPHY_PWRDET2 B43_PHY_N(0x13C) /* Power det 2 */ -#define B43_NPHY_MAXRSSI_DTIME B43_PHY_N(0x13F) /* RSSI max RSSI delay time */ -#define B43_NPHY_PIL_DW0 B43_PHY_N(0x141) /* Pilot data weight 0 */ -#define B43_NPHY_PIL_DW1 B43_PHY_N(0x142) /* Pilot data weight 1 */ -#define B43_NPHY_PIL_DW2 B43_PHY_N(0x143) /* Pilot data weight 2 */ -#define B43_NPHY_PIL_DW_BPSK 0x000F /* BPSK */ -#define B43_NPHY_PIL_DW_BPSK_SHIFT 0 -#define B43_NPHY_PIL_DW_QPSK 0x00F0 /* QPSK */ -#define B43_NPHY_PIL_DW_QPSK_SHIFT 4 -#define B43_NPHY_PIL_DW_16QAM 0x0F00 /* 16-QAM */ -#define B43_NPHY_PIL_DW_16QAM_SHIFT 8 -#define B43_NPHY_PIL_DW_64QAM 0xF000 /* 64-QAM */ -#define B43_NPHY_PIL_DW_64QAM_SHIFT 12 -#define B43_NPHY_FMDEM_CFG B43_PHY_N(0x144) /* FM demodulation config */ -#define B43_NPHY_PHASETR_A0 B43_PHY_N(0x145) /* Phase track alpha 0 */ -#define B43_NPHY_PHASETR_A1 B43_PHY_N(0x146) /* Phase track alpha 1 */ -#define B43_NPHY_PHASETR_A2 B43_PHY_N(0x147) /* Phase track alpha 2 */ -#define B43_NPHY_PHASETR_B0 B43_PHY_N(0x148) /* Phase track beta 0 */ -#define B43_NPHY_PHASETR_B1 B43_PHY_N(0x149) /* Phase track beta 1 */ -#define B43_NPHY_PHASETR_B2 B43_PHY_N(0x14A) /* Phase track beta 2 */ -#define B43_NPHY_PHASETR_CHG0 B43_PHY_N(0x14B) /* Phase track change 0 */ -#define B43_NPHY_PHASETR_CHG1 B43_PHY_N(0x14C) /* Phase track change 1 */ -#define B43_NPHY_PHASETW_OFF B43_PHY_N(0x14D) /* Phase track offset */ -#define B43_NPHY_RFCTL_DBG B43_PHY_N(0x14E) /* RF control debug */ -#define B43_NPHY_CCK_SHIFTB_REF B43_PHY_N(0x150) /* CCK shiftbits reference var */ -#define B43_NPHY_OVER_DGAIN0 B43_PHY_N(0x152) /* Override digital gain 0 */ -#define B43_NPHY_OVER_DGAIN1 B43_PHY_N(0x153) /* Override digital gain 1 */ -#define B43_NPHY_OVER_DGAIN_FDGV 0x0007 /* Force digital gain value */ -#define B43_NPHY_OVER_DGAIN_FDGV_SHIFT 0 -#define B43_NPHY_OVER_DGAIN_FDGEN 0x0008 /* Force digital gain enable */ -#define B43_NPHY_OVER_DGAIN_CCKDGECV 0xFF00 /* CCK digital gain enable count value */ -#define B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT 8 -#define B43_NPHY_BIST_STAT4 B43_PHY_N(0x156) /* BIST status 4 */ -#define B43_NPHY_RADAR_MAL B43_PHY_N(0x157) /* Radar MA length */ -#define B43_NPHY_RADAR_SRCCTL B43_PHY_N(0x158) /* Radar search control */ -#define B43_NPHY_VLD_DTSIG B43_PHY_N(0x159) /* VLD data tones sig */ -#define B43_NPHY_VLD_DTDAT B43_PHY_N(0x15A) /* VLD data tones data */ -#define B43_NPHY_C1_BPHY_RXIQCA0 B43_PHY_N(0x15B) /* Core 1 B PHY RX I/Q comp A0 */ -#define B43_NPHY_C1_BPHY_RXIQCB0 B43_PHY_N(0x15C) /* Core 1 B PHY RX I/Q comp B0 */ -#define B43_NPHY_C2_BPHY_RXIQCA1 B43_PHY_N(0x15D) /* Core 2 B PHY RX I/Q comp A1 */ -#define B43_NPHY_C2_BPHY_RXIQCB1 B43_PHY_N(0x15E) /* Core 2 B PHY RX I/Q comp B1 */ -#define B43_NPHY_FREQGAIN0 B43_PHY_N(0x160) /* Frequency gain 0 */ -#define B43_NPHY_FREQGAIN1 B43_PHY_N(0x161) /* Frequency gain 1 */ -#define B43_NPHY_FREQGAIN2 B43_PHY_N(0x162) /* Frequency gain 2 */ -#define B43_NPHY_FREQGAIN3 B43_PHY_N(0x163) /* Frequency gain 3 */ -#define B43_NPHY_FREQGAIN4 B43_PHY_N(0x164) /* Frequency gain 4 */ -#define B43_NPHY_FREQGAIN5 B43_PHY_N(0x165) /* Frequency gain 5 */ -#define B43_NPHY_FREQGAIN6 B43_PHY_N(0x166) /* Frequency gain 6 */ -#define B43_NPHY_FREQGAIN7 B43_PHY_N(0x167) /* Frequency gain 7 */ -#define B43_NPHY_FREQGAIN_BYPASS B43_PHY_N(0x168) /* Frequency gain bypass */ -#define B43_NPHY_TRLOSS B43_PHY_N(0x169) /* TR loss value */ -#define B43_NPHY_C1_ADCCLIP B43_PHY_N(0x16A) /* Core 1 ADC clip */ -#define B43_NPHY_C2_ADCCLIP B43_PHY_N(0x16B) /* Core 2 ADC clip */ -#define B43_NPHY_LTRN_OFFGAIN B43_PHY_N(0x16F) /* LTRN offset gain */ -#define B43_NPHY_LTRN_OFF B43_PHY_N(0x170) /* LTRN offset */ -#define B43_NPHY_NRDATAT_WWISE20SIG B43_PHY_N(0x171) /* # data tones WWiSE 20 sig */ -#define B43_NPHY_NRDATAT_WWISE40SIG B43_PHY_N(0x172) /* # data tones WWiSE 40 sig */ -#define B43_NPHY_NRDATAT_TGNSYNC20SIG B43_PHY_N(0x173) /* # data tones TGNsync 20 sig */ -#define B43_NPHY_NRDATAT_TGNSYNC40SIG B43_PHY_N(0x174) /* # data tones TGNsync 40 sig */ -#define B43_NPHY_WWISE_CRCM0 B43_PHY_N(0x175) /* WWiSE CRC mask 0 */ -#define B43_NPHY_WWISE_CRCM1 B43_PHY_N(0x176) /* WWiSE CRC mask 1 */ -#define B43_NPHY_WWISE_CRCM2 B43_PHY_N(0x177) /* WWiSE CRC mask 2 */ -#define B43_NPHY_WWISE_CRCM3 B43_PHY_N(0x178) /* WWiSE CRC mask 3 */ -#define B43_NPHY_WWISE_CRCM4 B43_PHY_N(0x179) /* WWiSE CRC mask 4 */ -#define B43_NPHY_CHANEST_CDDSH B43_PHY_N(0x17A) /* Channel estimate CDD shift */ -#define B43_NPHY_HTAGC_WCNT B43_PHY_N(0x17B) /* HT ADC wait counters */ -#define B43_NPHY_SQPARM B43_PHY_N(0x17C) /* SQ params */ -#define B43_NPHY_MCSDUP6M B43_PHY_N(0x17D) /* MCS dup 6M */ -#define B43_NPHY_NDATAT_DUP40 B43_PHY_N(0x17E) /* # data tones dup 40 */ -#define B43_NPHY_DUP40_TGNSYNC_CYCD B43_PHY_N(0x17F) /* Dup40 TGNsync cycle data */ -#define B43_NPHY_DUP40_GFBL B43_PHY_N(0x180) /* Dup40 GF format BL address */ -#define B43_NPHY_DUP40_BL B43_PHY_N(0x181) /* Dup40 format BL address */ -#define B43_NPHY_LEGDUP_FTA B43_PHY_N(0x182) /* Legacy dup frm table address */ -#define B43_NPHY_PACPROC_DBG B43_PHY_N(0x183) /* Packet processing debug */ -#define B43_NPHY_PIL_CYC1 B43_PHY_N(0x184) /* Pilot cycle counter 1 */ -#define B43_NPHY_PIL_CYC2 B43_PHY_N(0x185) /* Pilot cycle counter 2 */ -#define B43_NPHY_TXF_20CO_S0A1 B43_PHY_N(0x186) /* TX filter 20 coeff stage 0 A1 */ -#define B43_NPHY_TXF_20CO_S0A2 B43_PHY_N(0x187) /* TX filter 20 coeff stage 0 A2 */ -#define B43_NPHY_TXF_20CO_S1A1 B43_PHY_N(0x188) /* TX filter 20 coeff stage 1 A1 */ -#define B43_NPHY_TXF_20CO_S1A2 B43_PHY_N(0x189) /* TX filter 20 coeff stage 1 A2 */ -#define B43_NPHY_TXF_20CO_S2A1 B43_PHY_N(0x18A) /* TX filter 20 coeff stage 2 A1 */ -#define B43_NPHY_TXF_20CO_S2A2 B43_PHY_N(0x18B) /* TX filter 20 coeff stage 2 A2 */ -#define B43_NPHY_TXF_20CO_S0B1 B43_PHY_N(0x18C) /* TX filter 20 coeff stage 0 B1 */ -#define B43_NPHY_TXF_20CO_S0B2 B43_PHY_N(0x18D) /* TX filter 20 coeff stage 0 B2 */ -#define B43_NPHY_TXF_20CO_S0B3 B43_PHY_N(0x18E) /* TX filter 20 coeff stage 0 B3 */ -#define B43_NPHY_TXF_20CO_S1B1 B43_PHY_N(0x18F) /* TX filter 20 coeff stage 1 B1 */ -#define B43_NPHY_TXF_20CO_S1B2 B43_PHY_N(0x190) /* TX filter 20 coeff stage 1 B2 */ -#define B43_NPHY_TXF_20CO_S1B3 B43_PHY_N(0x191) /* TX filter 20 coeff stage 1 B3 */ -#define B43_NPHY_TXF_20CO_S2B1 B43_PHY_N(0x192) /* TX filter 20 coeff stage 2 B1 */ -#define B43_NPHY_TXF_20CO_S2B2 B43_PHY_N(0x193) /* TX filter 20 coeff stage 2 B2 */ -#define B43_NPHY_TXF_20CO_S2B3 B43_PHY_N(0x194) /* TX filter 20 coeff stage 2 B3 */ -#define B43_NPHY_TXF_40CO_S0A1 B43_PHY_N(0x195) /* TX filter 40 coeff stage 0 A1 */ -#define B43_NPHY_TXF_40CO_S0A2 B43_PHY_N(0x196) /* TX filter 40 coeff stage 0 A2 */ -#define B43_NPHY_TXF_40CO_S1A1 B43_PHY_N(0x197) /* TX filter 40 coeff stage 1 A1 */ -#define B43_NPHY_TXF_40CO_S1A2 B43_PHY_N(0x198) /* TX filter 40 coeff stage 1 A2 */ -#define B43_NPHY_TXF_40CO_S2A1 B43_PHY_N(0x199) /* TX filter 40 coeff stage 2 A1 */ -#define B43_NPHY_TXF_40CO_S2A2 B43_PHY_N(0x19A) /* TX filter 40 coeff stage 2 A2 */ -#define B43_NPHY_TXF_40CO_S0B1 B43_PHY_N(0x19B) /* TX filter 40 coeff stage 0 B1 */ -#define B43_NPHY_TXF_40CO_S0B2 B43_PHY_N(0x19C) /* TX filter 40 coeff stage 0 B2 */ -#define B43_NPHY_TXF_40CO_S0B3 B43_PHY_N(0x19D) /* TX filter 40 coeff stage 0 B3 */ -#define B43_NPHY_TXF_40CO_S1B1 B43_PHY_N(0x19E) /* TX filter 40 coeff stage 1 B1 */ -#define B43_NPHY_TXF_40CO_S1B2 B43_PHY_N(0x19F) /* TX filter 40 coeff stage 1 B2 */ -#define B43_NPHY_TXF_40CO_S1B3 B43_PHY_N(0x1A0) /* TX filter 40 coeff stage 1 B3 */ -#define B43_NPHY_TXF_40CO_S2B1 B43_PHY_N(0x1A1) /* TX filter 40 coeff stage 2 B1 */ -#define B43_NPHY_TXF_40CO_S2B2 B43_PHY_N(0x1A2) /* TX filter 40 coeff stage 2 B2 */ -#define B43_NPHY_TXF_40CO_S2B3 B43_PHY_N(0x1A3) /* TX filter 40 coeff stage 2 B3 */ -#define B43_NPHY_RSSIMC_0I_RSSI_X B43_PHY_N(0x1A4) /* RSSI multiplication coefficient 0 I RSSI X */ -#define B43_NPHY_RSSIMC_0I_RSSI_Y B43_PHY_N(0x1A5) /* RSSI multiplication coefficient 0 I RSSI Y */ -#define B43_NPHY_RSSIMC_0I_RSSI_Z B43_PHY_N(0x1A6) /* RSSI multiplication coefficient 0 I RSSI Z */ -#define B43_NPHY_RSSIMC_0I_TBD B43_PHY_N(0x1A7) /* RSSI multiplication coefficient 0 I TBD */ -#define B43_NPHY_RSSIMC_0I_PWRDET B43_PHY_N(0x1A8) /* RSSI multiplication coefficient 0 I power det */ -#define B43_NPHY_RSSIMC_0I_TSSI B43_PHY_N(0x1A9) /* RSSI multiplication coefficient 0 I TSSI */ -#define B43_NPHY_RSSIMC_0Q_RSSI_X B43_PHY_N(0x1AA) /* RSSI multiplication coefficient 0 Q RSSI X */ -#define B43_NPHY_RSSIMC_0Q_RSSI_Y B43_PHY_N(0x1AB) /* RSSI multiplication coefficient 0 Q RSSI Y */ -#define B43_NPHY_RSSIMC_0Q_RSSI_Z B43_PHY_N(0x1AC) /* RSSI multiplication coefficient 0 Q RSSI Z */ -#define B43_NPHY_RSSIMC_0Q_TBD B43_PHY_N(0x1AD) /* RSSI multiplication coefficient 0 Q TBD */ -#define B43_NPHY_RSSIMC_0Q_PWRDET B43_PHY_N(0x1AE) /* RSSI multiplication coefficient 0 Q power det */ -#define B43_NPHY_RSSIMC_0Q_TSSI B43_PHY_N(0x1AF) /* RSSI multiplication coefficient 0 Q TSSI */ -#define B43_NPHY_RSSIMC_1I_RSSI_X B43_PHY_N(0x1B0) /* RSSI multiplication coefficient 1 I RSSI X */ -#define B43_NPHY_RSSIMC_1I_RSSI_Y B43_PHY_N(0x1B1) /* RSSI multiplication coefficient 1 I RSSI Y */ -#define B43_NPHY_RSSIMC_1I_RSSI_Z B43_PHY_N(0x1B2) /* RSSI multiplication coefficient 1 I RSSI Z */ -#define B43_NPHY_RSSIMC_1I_TBD B43_PHY_N(0x1B3) /* RSSI multiplication coefficient 1 I TBD */ -#define B43_NPHY_RSSIMC_1I_PWRDET B43_PHY_N(0x1B4) /* RSSI multiplication coefficient 1 I power det */ -#define B43_NPHY_RSSIMC_1I_TSSI B43_PHY_N(0x1B5) /* RSSI multiplication coefficient 1 I TSSI */ -#define B43_NPHY_RSSIMC_1Q_RSSI_X B43_PHY_N(0x1B6) /* RSSI multiplication coefficient 1 Q RSSI X */ -#define B43_NPHY_RSSIMC_1Q_RSSI_Y B43_PHY_N(0x1B7) /* RSSI multiplication coefficient 1 Q RSSI Y */ -#define B43_NPHY_RSSIMC_1Q_RSSI_Z B43_PHY_N(0x1B8) /* RSSI multiplication coefficient 1 Q RSSI Z */ -#define B43_NPHY_RSSIMC_1Q_TBD B43_PHY_N(0x1B9) /* RSSI multiplication coefficient 1 Q TBD */ -#define B43_NPHY_RSSIMC_1Q_PWRDET B43_PHY_N(0x1BA) /* RSSI multiplication coefficient 1 Q power det */ -#define B43_NPHY_RSSIMC_1Q_TSSI B43_PHY_N(0x1BB) /* RSSI multiplication coefficient 1 Q TSSI */ -#define B43_NPHY_SAMC_WCNT B43_PHY_N(0x1BC) /* Sample collect wait counter */ -#define B43_NPHY_PTHROUGH_CNT B43_PHY_N(0x1BD) /* Pass-through counter */ -#define B43_NPHY_LTRN_OFF_G20L B43_PHY_N(0x1C4) /* LTRN offset gain 20L */ -#define B43_NPHY_LTRN_OFF_20L B43_PHY_N(0x1C5) /* LTRN offset 20L */ -#define B43_NPHY_LTRN_OFF_G20U B43_PHY_N(0x1C6) /* LTRN offset gain 20U */ -#define B43_NPHY_LTRN_OFF_20U B43_PHY_N(0x1C7) /* LTRN offset 20U */ -#define B43_NPHY_DSSSCCK_GAINSL B43_PHY_N(0x1C8) /* DSSS/CCK gain settle length */ -#define B43_NPHY_GPIO_LOOUT B43_PHY_N(0x1C9) /* GPIO low out */ -#define B43_NPHY_GPIO_HIOUT B43_PHY_N(0x1CA) /* GPIO high out */ -#define B43_NPHY_CRS_CHECK B43_PHY_N(0x1CB) /* CRS check */ -#define B43_NPHY_ML_LOGSS_RAT B43_PHY_N(0x1CC) /* ML/logss ratio */ -#define B43_NPHY_DUPSCALE B43_PHY_N(0x1CD) /* Dup scale */ -#define B43_NPHY_BW1A B43_PHY_N(0x1CE) /* BW 1A */ -#define B43_NPHY_BW2 B43_PHY_N(0x1CF) /* BW 2 */ -#define B43_NPHY_BW3 B43_PHY_N(0x1D0) /* BW 3 */ -#define B43_NPHY_BW4 B43_PHY_N(0x1D1) /* BW 4 */ -#define B43_NPHY_BW5 B43_PHY_N(0x1D2) /* BW 5 */ -#define B43_NPHY_BW6 B43_PHY_N(0x1D3) /* BW 6 */ -#define B43_NPHY_COALEN0 B43_PHY_N(0x1D4) /* Coarse length 0 */ -#define B43_NPHY_COALEN1 B43_PHY_N(0x1D5) /* Coarse length 1 */ -#define B43_NPHY_CRSTHRES_1U B43_PHY_N(0x1D6) /* CRS threshold 1 U */ -#define B43_NPHY_CRSTHRES_2U B43_PHY_N(0x1D7) /* CRS threshold 2 U */ -#define B43_NPHY_CRSTHRES_3U B43_PHY_N(0x1D8) /* CRS threshold 3 U */ -#define B43_NPHY_CRSCTL_U B43_PHY_N(0x1D9) /* CRS control U */ -#define B43_NPHY_CRSTHRES_1L B43_PHY_N(0x1DA) /* CRS threshold 1 L */ -#define B43_NPHY_CRSTHRES_2L B43_PHY_N(0x1DB) /* CRS threshold 2 L */ -#define B43_NPHY_CRSTHRES_3L B43_PHY_N(0x1DC) /* CRS threshold 3 L */ -#define B43_NPHY_CRSCTL_L B43_PHY_N(0x1DD) /* CRS control L */ -#define B43_NPHY_STRA_1U B43_PHY_N(0x1DE) /* STR address 1 U */ -#define B43_NPHY_STRA_2U B43_PHY_N(0x1DF) /* STR address 2 U */ -#define B43_NPHY_STRA_1L B43_PHY_N(0x1E0) /* STR address 1 L */ -#define B43_NPHY_STRA_2L B43_PHY_N(0x1E1) /* STR address 2 L */ -#define B43_NPHY_CRSCHECK1 B43_PHY_N(0x1E2) /* CRS check 1 */ -#define B43_NPHY_CRSCHECK2 B43_PHY_N(0x1E3) /* CRS check 2 */ -#define B43_NPHY_CRSCHECK3 B43_PHY_N(0x1E4) /* CRS check 3 */ -#define B43_NPHY_JMPSTP0 B43_PHY_N(0x1E5) /* Jump step 0 */ -#define B43_NPHY_JMPSTP1 B43_PHY_N(0x1E6) /* Jump step 1 */ -#define B43_NPHY_TXPCTL_CMD B43_PHY_N(0x1E7) /* TX power control command */ -#define B43_NPHY_TXPCTL_CMD_INIT 0x007F /* Init */ -#define B43_NPHY_TXPCTL_CMD_INIT_SHIFT 0 -#define B43_NPHY_TXPCTL_CMD_COEFF 0x2000 /* Power control coefficients */ -#define B43_NPHY_TXPCTL_CMD_HWPCTLEN 0x4000 /* Hardware TX power control enable */ -#define B43_NPHY_TXPCTL_CMD_PCTLEN 0x8000 /* TX power control enable */ -#define B43_NPHY_TXPCTL_N B43_PHY_N(0x1E8) /* TX power control N num */ -#define B43_NPHY_TXPCTL_N_TSSID 0x00FF /* N TSSI delay */ -#define B43_NPHY_TXPCTL_N_TSSID_SHIFT 0 -#define B43_NPHY_TXPCTL_N_NPTIL2 0x0700 /* N PT integer log2 */ -#define B43_NPHY_TXPCTL_N_NPTIL2_SHIFT 8 -#define B43_NPHY_TXPCTL_ITSSI B43_PHY_N(0x1E9) /* TX power control idle TSSI */ -#define B43_NPHY_TXPCTL_ITSSI_0 0x003F /* Idle TSSI 0 */ -#define B43_NPHY_TXPCTL_ITSSI_0_SHIFT 0 -#define B43_NPHY_TXPCTL_ITSSI_1 0x3F00 /* Idle TSSI 1 */ -#define B43_NPHY_TXPCTL_ITSSI_1_SHIFT 8 -#define B43_NPHY_TXPCTL_ITSSI_BINF 0x8000 /* Raw TSSI offset bin format */ -#define B43_NPHY_TXPCTL_TPWR B43_PHY_N(0x1EA) /* TX power control target power */ -#define B43_NPHY_TXPCTL_TPWR_0 0x00FF /* Power 0 */ -#define B43_NPHY_TXPCTL_TPWR_0_SHIFT 0 -#define B43_NPHY_TXPCTL_TPWR_1 0xFF00 /* Power 1 */ -#define B43_NPHY_TXPCTL_TPWR_1_SHIFT 8 -#define B43_NPHY_TXPCTL_BIDX B43_PHY_N(0x1EB) /* TX power control base index */ -#define B43_NPHY_TXPCTL_BIDX_0 0x007F /* uC base index 0 */ -#define B43_NPHY_TXPCTL_BIDX_0_SHIFT 0 -#define B43_NPHY_TXPCTL_BIDX_1 0x7F00 /* uC base index 1 */ -#define B43_NPHY_TXPCTL_BIDX_1_SHIFT 8 -#define B43_NPHY_TXPCTL_BIDX_LOAD 0x8000 /* Load base index */ -#define B43_NPHY_TXPCTL_PIDX B43_PHY_N(0x1EC) /* TX power control power index */ -#define B43_NPHY_TXPCTL_PIDX_0 0x007F /* uC power index 0 */ -#define B43_NPHY_TXPCTL_PIDX_0_SHIFT 0 -#define B43_NPHY_TXPCTL_PIDX_1 0x7F00 /* uC power index 1 */ -#define B43_NPHY_TXPCTL_PIDX_1_SHIFT 8 -#define B43_NPHY_C1_TXPCTL_STAT B43_PHY_N(0x1ED) /* Core 1 TX power control status */ -#define B43_NPHY_C2_TXPCTL_STAT B43_PHY_N(0x1EE) /* Core 2 TX power control status */ -#define B43_NPHY_TXPCTL_STAT_EST 0x00FF /* Estimated power */ -#define B43_NPHY_TXPCTL_STAT_EST_SHIFT 0 -#define B43_NPHY_TXPCTL_STAT_BIDX 0x7F00 /* Base index */ -#define B43_NPHY_TXPCTL_STAT_BIDX_SHIFT 8 -#define B43_NPHY_TXPCTL_STAT_ESTVALID 0x8000 /* Estimated power valid */ -#define B43_NPHY_SMALLSGS_LEN B43_PHY_N(0x1EF) /* Small sig gain settle length */ -#define B43_NPHY_PHYSTAT_GAIN0 B43_PHY_N(0x1F0) /* PHY stats gain info 0 */ -#define B43_NPHY_PHYSTAT_GAIN1 B43_PHY_N(0x1F1) /* PHY stats gain info 1 */ -#define B43_NPHY_PHYSTAT_FREQEST B43_PHY_N(0x1F2) /* PHY stats frequency estimate */ -#define B43_NPHY_PHYSTAT_ADVRET B43_PHY_N(0x1F3) /* PHY stats ADV retard */ -#define B43_NPHY_PHYLB_MODE B43_PHY_N(0x1F4) /* PHY loopback mode */ -#define B43_NPHY_TONE_MIDX20_1 B43_PHY_N(0x1F5) /* Tone map index 20/1 */ -#define B43_NPHY_TONE_MIDX20_2 B43_PHY_N(0x1F6) /* Tone map index 20/2 */ -#define B43_NPHY_TONE_MIDX20_3 B43_PHY_N(0x1F7) /* Tone map index 20/3 */ -#define B43_NPHY_TONE_MIDX40_1 B43_PHY_N(0x1F8) /* Tone map index 40/1 */ -#define B43_NPHY_TONE_MIDX40_2 B43_PHY_N(0x1F9) /* Tone map index 40/2 */ -#define B43_NPHY_TONE_MIDX40_3 B43_PHY_N(0x1FA) /* Tone map index 40/3 */ -#define B43_NPHY_TONE_MIDX40_4 B43_PHY_N(0x1FB) /* Tone map index 40/4 */ -#define B43_NPHY_PILTONE_MIDX1 B43_PHY_N(0x1FC) /* Pilot tone map index 1 */ -#define B43_NPHY_PILTONE_MIDX2 B43_PHY_N(0x1FD) /* Pilot tone map index 2 */ -#define B43_NPHY_PILTONE_MIDX3 B43_PHY_N(0x1FE) /* Pilot tone map index 3 */ -#define B43_NPHY_TXRIFS_FRDEL B43_PHY_N(0x1FF) /* TX RIFS frame delay */ -#define B43_NPHY_AFESEQ_RX2TX_PUD_40M B43_PHY_N(0x200) /* AFE seq rx2tx power up/down delay 40M */ -#define B43_NPHY_AFESEQ_TX2RX_PUD_40M B43_PHY_N(0x201) /* AFE seq tx2rx power up/down delay 40M */ -#define B43_NPHY_AFESEQ_RX2TX_PUD_20M B43_PHY_N(0x202) /* AFE seq rx2tx power up/down delay 20M */ -#define B43_NPHY_AFESEQ_TX2RX_PUD_20M B43_PHY_N(0x203) /* AFE seq tx2rx power up/down delay 20M */ -#define B43_NPHY_RX_SIGCTL B43_PHY_N(0x204) /* RX signal control */ -#define B43_NPHY_RXPIL_CYCNT0 B43_PHY_N(0x205) /* RX pilot cycle counter 0 */ -#define B43_NPHY_RXPIL_CYCNT1 B43_PHY_N(0x206) /* RX pilot cycle counter 1 */ -#define B43_NPHY_RXPIL_CYCNT2 B43_PHY_N(0x207) /* RX pilot cycle counter 2 */ -#define B43_NPHY_AFESEQ_RX2TX_PUD_10M B43_PHY_N(0x208) /* AFE seq rx2tx power up/down delay 10M */ -#define B43_NPHY_AFESEQ_TX2RX_PUD_10M B43_PHY_N(0x209) /* AFE seq tx2rx power up/down delay 10M */ -#define B43_NPHY_DSSSCCK_CRSEXTL B43_PHY_N(0x20A) /* DSSS/CCK CRS extension length */ -#define B43_NPHY_ML_LOGSS_RATSLOPE B43_PHY_N(0x20B) /* ML/logss ratio slope */ -#define B43_NPHY_RIFS_SRCTL B43_PHY_N(0x20C) /* RIFS search timeout length */ -#define B43_NPHY_TXREALFD B43_PHY_N(0x20D) /* TX real frame delay */ -#define B43_NPHY_HPANT_SWTHRES B43_PHY_N(0x20E) /* High power antenna switch threshold */ -#define B43_NPHY_EDCRS_ASSTHRES0 B43_PHY_N(0x210) /* ED CRS assert threshold 0 */ -#define B43_NPHY_EDCRS_ASSTHRES1 B43_PHY_N(0x211) /* ED CRS assert threshold 1 */ -#define B43_NPHY_EDCRS_DEASSTHRES0 B43_PHY_N(0x212) /* ED CRS deassert threshold 0 */ -#define B43_NPHY_EDCRS_DEASSTHRES1 B43_PHY_N(0x213) /* ED CRS deassert threshold 1 */ -#define B43_NPHY_STR_WTIME20U B43_PHY_N(0x214) /* STR wait time 20U */ -#define B43_NPHY_STR_WTIME20L B43_PHY_N(0x215) /* STR wait time 20L */ -#define B43_NPHY_TONE_MIDX657M B43_PHY_N(0x216) /* Tone map index 657M */ -#define B43_NPHY_HTSIGTONES B43_PHY_N(0x217) /* HT signal tones */ -#define B43_NPHY_RSSI1 B43_PHY_N(0x219) /* RSSI value 1 */ -#define B43_NPHY_RSSI2 B43_PHY_N(0x21A) /* RSSI value 2 */ -#define B43_NPHY_CHAN_ESTHANG B43_PHY_N(0x21D) /* Channel estimate hang */ -#define B43_NPHY_FINERX2_CGC B43_PHY_N(0x221) /* Fine RX 2 clock gate control */ -#define B43_NPHY_FINERX2_CGC_DECGC 0x0008 /* Decode gated clocks */ -#define B43_NPHY_TXPCTL_INIT B43_PHY_N(0x222) /* TX power controll init */ -#define B43_NPHY_TXPCTL_INIT_PIDXI1 0x00FF /* Power index init 1 */ -#define B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT 0 - - - -/* Broadcom 2055 radio registers */ - -#define B2055_GEN_SPARE 0x00 /* GEN spare */ -#define B2055_SP_PINPD 0x02 /* SP PIN PD */ -#define B2055_C1_SP_RSSI 0x03 /* SP RSSI Core 1 */ -#define B2055_C1_SP_PDMISC 0x04 /* SP PD MISC Core 1 */ -#define B2055_C2_SP_RSSI 0x05 /* SP RSSI Core 2 */ -#define B2055_C2_SP_PDMISC 0x06 /* SP PD MISC Core 2 */ -#define B2055_C1_SP_RXGC1 0x07 /* SP RX GC1 Core 1 */ -#define B2055_C1_SP_RXGC2 0x08 /* SP RX GC2 Core 1 */ -#define B2055_C2_SP_RXGC1 0x09 /* SP RX GC1 Core 2 */ -#define B2055_C2_SP_RXGC2 0x0A /* SP RX GC2 Core 2 */ -#define B2055_C1_SP_LPFBWSEL 0x0B /* SP LPF BW select Core 1 */ -#define B2055_C2_SP_LPFBWSEL 0x0C /* SP LPF BW select Core 2 */ -#define B2055_C1_SP_TXGC1 0x0D /* SP TX GC1 Core 1 */ -#define B2055_C1_SP_TXGC2 0x0E /* SP TX GC2 Core 1 */ -#define B2055_C2_SP_TXGC1 0x0F /* SP TX GC1 Core 2 */ -#define B2055_C2_SP_TXGC2 0x10 /* SP TX GC2 Core 2 */ -#define B2055_MASTER1 0x11 /* Master control 1 */ -#define B2055_MASTER2 0x12 /* Master control 2 */ -#define B2055_PD_LGEN 0x13 /* PD LGEN */ -#define B2055_PD_PLLTS 0x14 /* PD PLL TS */ -#define B2055_C1_PD_LGBUF 0x15 /* PD Core 1 LGBUF */ -#define B2055_C1_PD_TX 0x16 /* PD Core 1 TX */ -#define B2055_C1_PD_RXTX 0x17 /* PD Core 1 RXTX */ -#define B2055_C1_PD_RSSIMISC 0x18 /* PD Core 1 RSSI MISC */ -#define B2055_C2_PD_LGBUF 0x19 /* PD Core 2 LGBUF */ -#define B2055_C2_PD_TX 0x1A /* PD Core 2 TX */ -#define B2055_C2_PD_RXTX 0x1B /* PD Core 2 RXTX */ -#define B2055_C2_PD_RSSIMISC 0x1C /* PD Core 2 RSSI MISC */ -#define B2055_PWRDET_LGEN 0x1D /* PWRDET LGEN */ -#define B2055_C1_PWRDET_LGBUF 0x1E /* PWRDET LGBUF Core 1 */ -#define B2055_C1_PWRDET_RXTX 0x1F /* PWRDET RXTX Core 1 */ -#define B2055_C2_PWRDET_LGBUF 0x20 /* PWRDET LGBUF Core 2 */ -#define B2055_C2_PWRDET_RXTX 0x21 /* PWRDET RXTX Core 2 */ -#define B2055_RRCCAL_CS 0x22 /* RRCCAL Control spare */ -#define B2055_RRCCAL_NOPTSEL 0x23 /* RRCCAL N OPT SEL */ -#define B2055_CAL_MISC 0x24 /* CAL MISC */ -#define B2055_CAL_COUT 0x25 /* CAL Counter out */ -#define B2055_CAL_COUT2 0x26 /* CAL Counter out 2 */ -#define B2055_CAL_CVARCTL 0x27 /* CAL CVAR Control */ -#define B2055_CAL_RVARCTL 0x28 /* CAL RVAR Control */ -#define B2055_CAL_LPOCTL 0x29 /* CAL LPO Control */ -#define B2055_CAL_TS 0x2A /* CAL TS */ -#define B2055_CAL_RCCALRTS 0x2B /* CAL RCCAL READ TS */ -#define B2055_CAL_RCALRTS 0x2C /* CAL RCAL READ TS */ -#define B2055_PADDRV 0x2D /* PAD driver */ -#define B2055_XOCTL1 0x2E /* XO Control 1 */ -#define B2055_XOCTL2 0x2F /* XO Control 2 */ -#define B2055_XOREGUL 0x30 /* XO Regulator */ -#define B2055_XOMISC 0x31 /* XO misc */ -#define B2055_PLL_LFC1 0x32 /* PLL LF C1 */ -#define B2055_PLL_CALVTH 0x33 /* PLL CAL VTH */ -#define B2055_PLL_LFC2 0x34 /* PLL LF C2 */ -#define B2055_PLL_REF 0x35 /* PLL reference */ -#define B2055_PLL_LFR1 0x36 /* PLL LF R1 */ -#define B2055_PLL_PFDCP 0x37 /* PLL PFD CP */ -#define B2055_PLL_IDAC_CPOPAMP 0x38 /* PLL IDAC CPOPAMP */ -#define B2055_PLL_CPREG 0x39 /* PLL CP Regulator */ -#define B2055_PLL_RCAL 0x3A /* PLL RCAL */ -#define B2055_RF_PLLMOD0 0x3B /* RF PLL MOD0 */ -#define B2055_RF_PLLMOD1 0x3C /* RF PLL MOD1 */ -#define B2055_RF_MMDIDAC1 0x3D /* RF MMD IDAC 1 */ -#define B2055_RF_MMDIDAC0 0x3E /* RF MMD IDAC 0 */ -#define B2055_RF_MMDSP 0x3F /* RF MMD spare */ -#define B2055_VCO_CAL1 0x40 /* VCO cal 1 */ -#define B2055_VCO_CAL2 0x41 /* VCO cal 2 */ -#define B2055_VCO_CAL3 0x42 /* VCO cal 3 */ -#define B2055_VCO_CAL4 0x43 /* VCO cal 4 */ -#define B2055_VCO_CAL5 0x44 /* VCO cal 5 */ -#define B2055_VCO_CAL6 0x45 /* VCO cal 6 */ -#define B2055_VCO_CAL7 0x46 /* VCO cal 7 */ -#define B2055_VCO_CAL8 0x47 /* VCO cal 8 */ -#define B2055_VCO_CAL9 0x48 /* VCO cal 9 */ -#define B2055_VCO_CAL10 0x49 /* VCO cal 10 */ -#define B2055_VCO_CAL11 0x4A /* VCO cal 11 */ -#define B2055_VCO_CAL12 0x4B /* VCO cal 12 */ -#define B2055_VCO_CAL13 0x4C /* VCO cal 13 */ -#define B2055_VCO_CAL14 0x4D /* VCO cal 14 */ -#define B2055_VCO_CAL15 0x4E /* VCO cal 15 */ -#define B2055_VCO_CAL16 0x4F /* VCO cal 16 */ -#define B2055_VCO_KVCO 0x50 /* VCO KVCO */ -#define B2055_VCO_CAPTAIL 0x51 /* VCO CAP TAIL */ -#define B2055_VCO_IDACVCO 0x52 /* VCO IDAC VCO */ -#define B2055_VCO_REG 0x53 /* VCO Regulator */ -#define B2055_PLL_RFVTH 0x54 /* PLL RF VTH */ -#define B2055_LGBUF_CENBUF 0x55 /* LGBUF CEN BUF */ -#define B2055_LGEN_TUNE1 0x56 /* LGEN tune 1 */ -#define B2055_LGEN_TUNE2 0x57 /* LGEN tune 2 */ -#define B2055_LGEN_IDAC1 0x58 /* LGEN IDAC 1 */ -#define B2055_LGEN_IDAC2 0x59 /* LGEN IDAC 2 */ -#define B2055_LGEN_BIASC 0x5A /* LGEN BIAS counter */ -#define B2055_LGEN_BIASIDAC 0x5B /* LGEN BIAS IDAC */ -#define B2055_LGEN_RCAL 0x5C /* LGEN RCAL */ -#define B2055_LGEN_DIV 0x5D /* LGEN div */ -#define B2055_LGEN_SPARE2 0x5E /* LGEN spare 2 */ -#define B2055_C1_LGBUF_ATUNE 0x5F /* Core 1 LGBUF A tune */ -#define B2055_C1_LGBUF_GTUNE 0x60 /* Core 1 LGBUF G tune */ -#define B2055_C1_LGBUF_DIV 0x61 /* Core 1 LGBUF div */ -#define B2055_C1_LGBUF_AIDAC 0x62 /* Core 1 LGBUF A IDAC */ -#define B2055_C1_LGBUF_GIDAC 0x63 /* Core 1 LGBUF G IDAC */ -#define B2055_C1_LGBUF_IDACFO 0x64 /* Core 1 LGBUF IDAC filter override */ -#define B2055_C1_LGBUF_SPARE 0x65 /* Core 1 LGBUF spare */ -#define B2055_C1_RX_RFSPC1 0x66 /* Core 1 RX RF SPC1 */ -#define B2055_C1_RX_RFR1 0x67 /* Core 1 RX RF reg 1 */ -#define B2055_C1_RX_RFR2 0x68 /* Core 1 RX RF reg 2 */ -#define B2055_C1_RX_RFRCAL 0x69 /* Core 1 RX RF RCAL */ -#define B2055_C1_RX_BB_BLCMP 0x6A /* Core 1 RX Baseband BUFI LPF CMP */ -#define B2055_C1_RX_BB_LPF 0x6B /* Core 1 RX Baseband LPF */ -#define B2055_C1_RX_BB_MIDACHP 0x6C /* Core 1 RX Baseband MIDAC High-pass */ -#define B2055_C1_RX_BB_VGA1IDAC 0x6D /* Core 1 RX Baseband VGA1 IDAC */ -#define B2055_C1_RX_BB_VGA2IDAC 0x6E /* Core 1 RX Baseband VGA2 IDAC */ -#define B2055_C1_RX_BB_VGA3IDAC 0x6F /* Core 1 RX Baseband VGA3 IDAC */ -#define B2055_C1_RX_BB_BUFOCTL 0x70 /* Core 1 RX Baseband BUFO Control */ -#define B2055_C1_RX_BB_RCCALCTL 0x71 /* Core 1 RX Baseband RCCAL Control */ -#define B2055_C1_RX_BB_RSSICTL1 0x72 /* Core 1 RX Baseband RSSI Control 1 */ -#define B2055_C1_RX_BB_RSSICTL2 0x73 /* Core 1 RX Baseband RSSI Control 2 */ -#define B2055_C1_RX_BB_RSSICTL3 0x74 /* Core 1 RX Baseband RSSI Control 3 */ -#define B2055_C1_RX_BB_RSSICTL4 0x75 /* Core 1 RX Baseband RSSI Control 4 */ -#define B2055_C1_RX_BB_RSSICTL5 0x76 /* Core 1 RX Baseband RSSI Control 5 */ -#define B2055_C1_RX_BB_REG 0x77 /* Core 1 RX Baseband Regulator */ -#define B2055_C1_RX_BB_SPARE1 0x78 /* Core 1 RX Baseband spare 1 */ -#define B2055_C1_RX_TXBBRCAL 0x79 /* Core 1 RX TX BB RCAL */ -#define B2055_C1_TX_RF_SPGA 0x7A /* Core 1 TX RF SGM PGA */ -#define B2055_C1_TX_RF_SPAD 0x7B /* Core 1 TX RF SGM PAD */ -#define B2055_C1_TX_RF_CNTPGA1 0x7C /* Core 1 TX RF counter PGA 1 */ -#define B2055_C1_TX_RF_CNTPAD1 0x7D /* Core 1 TX RF counter PAD 1 */ -#define B2055_C1_TX_RF_PGAIDAC 0x7E /* Core 1 TX RF PGA IDAC */ -#define B2055_C1_TX_PGAPADTN 0x7F /* Core 1 TX PGA PAD TN */ -#define B2055_C1_TX_PADIDAC1 0x80 /* Core 1 TX PAD IDAC 1 */ -#define B2055_C1_TX_PADIDAC2 0x81 /* Core 1 TX PAD IDAC 2 */ -#define B2055_C1_TX_MXBGTRIM 0x82 /* Core 1 TX MX B/G TRIM */ -#define B2055_C1_TX_RF_RCAL 0x83 /* Core 1 TX RF RCAL */ -#define B2055_C1_TX_RF_PADTSSI1 0x84 /* Core 1 TX RF PAD TSSI1 */ -#define B2055_C1_TX_RF_PADTSSI2 0x85 /* Core 1 TX RF PAD TSSI2 */ -#define B2055_C1_TX_RF_SPARE 0x86 /* Core 1 TX RF spare */ -#define B2055_C1_TX_RF_IQCAL1 0x87 /* Core 1 TX RF I/Q CAL 1 */ -#define B2055_C1_TX_RF_IQCAL2 0x88 /* Core 1 TX RF I/Q CAL 2 */ -#define B2055_C1_TXBB_RCCAL 0x89 /* Core 1 TXBB RC CAL Control */ -#define B2055_C1_TXBB_LPF1 0x8A /* Core 1 TXBB LPF 1 */ -#define B2055_C1_TX_VOSCNCL 0x8B /* Core 1 TX VOS CNCL */ -#define B2055_C1_TX_LPF_MXGMIDAC 0x8C /* Core 1 TX LPF MXGM IDAC */ -#define B2055_C1_TX_BB_MXGM 0x8D /* Core 1 TX BB MXGM */ -#define B2055_C2_LGBUF_ATUNE 0x8E /* Core 2 LGBUF A tune */ -#define B2055_C2_LGBUF_GTUNE 0x8F /* Core 2 LGBUF G tune */ -#define B2055_C2_LGBUF_DIV 0x90 /* Core 2 LGBUF div */ -#define B2055_C2_LGBUF_AIDAC 0x91 /* Core 2 LGBUF A IDAC */ -#define B2055_C2_LGBUF_GIDAC 0x92 /* Core 2 LGBUF G IDAC */ -#define B2055_C2_LGBUF_IDACFO 0x93 /* Core 2 LGBUF IDAC filter override */ -#define B2055_C2_LGBUF_SPARE 0x94 /* Core 2 LGBUF spare */ -#define B2055_C2_RX_RFSPC1 0x95 /* Core 2 RX RF SPC1 */ -#define B2055_C2_RX_RFR1 0x96 /* Core 2 RX RF reg 1 */ -#define B2055_C2_RX_RFR2 0x97 /* Core 2 RX RF reg 2 */ -#define B2055_C2_RX_RFRCAL 0x98 /* Core 2 RX RF RCAL */ -#define B2055_C2_RX_BB_BLCMP 0x99 /* Core 2 RX Baseband BUFI LPF CMP */ -#define B2055_C2_RX_BB_LPF 0x9A /* Core 2 RX Baseband LPF */ -#define B2055_C2_RX_BB_MIDACHP 0x9B /* Core 2 RX Baseband MIDAC High-pass */ -#define B2055_C2_RX_BB_VGA1IDAC 0x9C /* Core 2 RX Baseband VGA1 IDAC */ -#define B2055_C2_RX_BB_VGA2IDAC 0x9D /* Core 2 RX Baseband VGA2 IDAC */ -#define B2055_C2_RX_BB_VGA3IDAC 0x9E /* Core 2 RX Baseband VGA3 IDAC */ -#define B2055_C2_RX_BB_BUFOCTL 0x9F /* Core 2 RX Baseband BUFO Control */ -#define B2055_C2_RX_BB_RCCALCTL 0xA0 /* Core 2 RX Baseband RCCAL Control */ -#define B2055_C2_RX_BB_RSSICTL1 0xA1 /* Core 2 RX Baseband RSSI Control 1 */ -#define B2055_C2_RX_BB_RSSICTL2 0xA2 /* Core 2 RX Baseband RSSI Control 2 */ -#define B2055_C2_RX_BB_RSSICTL3 0xA3 /* Core 2 RX Baseband RSSI Control 3 */ -#define B2055_C2_RX_BB_RSSICTL4 0xA4 /* Core 2 RX Baseband RSSI Control 4 */ -#define B2055_C2_RX_BB_RSSICTL5 0xA5 /* Core 2 RX Baseband RSSI Control 5 */ -#define B2055_C2_RX_BB_REG 0xA6 /* Core 2 RX Baseband Regulator */ -#define B2055_C2_RX_BB_SPARE1 0xA7 /* Core 2 RX Baseband spare 1 */ -#define B2055_C2_RX_TXBBRCAL 0xA8 /* Core 2 RX TX BB RCAL */ -#define B2055_C2_TX_RF_SPGA 0xA9 /* Core 2 TX RF SGM PGA */ -#define B2055_C2_TX_RF_SPAD 0xAA /* Core 2 TX RF SGM PAD */ -#define B2055_C2_TX_RF_CNTPGA1 0xAB /* Core 2 TX RF counter PGA 1 */ -#define B2055_C2_TX_RF_CNTPAD1 0xAC /* Core 2 TX RF counter PAD 1 */ -#define B2055_C2_TX_RF_PGAIDAC 0xAD /* Core 2 TX RF PGA IDAC */ -#define B2055_C2_TX_PGAPADTN 0xAE /* Core 2 TX PGA PAD TN */ -#define B2055_C2_TX_PADIDAC1 0xAF /* Core 2 TX PAD IDAC 1 */ -#define B2055_C2_TX_PADIDAC2 0xB0 /* Core 2 TX PAD IDAC 2 */ -#define B2055_C2_TX_MXBGTRIM 0xB1 /* Core 2 TX MX B/G TRIM */ -#define B2055_C2_TX_RF_RCAL 0xB2 /* Core 2 TX RF RCAL */ -#define B2055_C2_TX_RF_PADTSSI1 0xB3 /* Core 2 TX RF PAD TSSI1 */ -#define B2055_C2_TX_RF_PADTSSI2 0xB4 /* Core 2 TX RF PAD TSSI2 */ -#define B2055_C2_TX_RF_SPARE 0xB5 /* Core 2 TX RF spare */ -#define B2055_C2_TX_RF_IQCAL1 0xB6 /* Core 2 TX RF I/Q CAL 1 */ -#define B2055_C2_TX_RF_IQCAL2 0xB7 /* Core 2 TX RF I/Q CAL 2 */ -#define B2055_C2_TXBB_RCCAL 0xB8 /* Core 2 TXBB RC CAL Control */ -#define B2055_C2_TXBB_LPF1 0xB9 /* Core 2 TXBB LPF 1 */ -#define B2055_C2_TX_VOSCNCL 0xBA /* Core 2 TX VOS CNCL */ -#define B2055_C2_TX_LPF_MXGMIDAC 0xBB /* Core 2 TX LPF MXGM IDAC */ -#define B2055_C2_TX_BB_MXGM 0xBC /* Core 2 TX BB MXGM */ -#define B2055_PRG_GCHP21 0xBD /* PRG GC HPVGA23 21 */ -#define B2055_PRG_GCHP22 0xBE /* PRG GC HPVGA23 22 */ -#define B2055_PRG_GCHP23 0xBF /* PRG GC HPVGA23 23 */ -#define B2055_PRG_GCHP24 0xC0 /* PRG GC HPVGA23 24 */ -#define B2055_PRG_GCHP25 0xC1 /* PRG GC HPVGA23 25 */ -#define B2055_PRG_GCHP26 0xC2 /* PRG GC HPVGA23 26 */ -#define B2055_PRG_GCHP27 0xC3 /* PRG GC HPVGA23 27 */ -#define B2055_PRG_GCHP28 0xC4 /* PRG GC HPVGA23 28 */ -#define B2055_PRG_GCHP29 0xC5 /* PRG GC HPVGA23 29 */ -#define B2055_PRG_GCHP30 0xC6 /* PRG GC HPVGA23 30 */ -#define B2055_C1_LNA_GAINBST 0xCD /* Core 1 LNA GAINBST */ -#define B2055_C1_B0NB_RSSIVCM 0xD2 /* Core 1 B0 narrow-band RSSI VCM */ -#define B2055_C1_GENSPARE2 0xD6 /* Core 1 GEN spare 2 */ -#define B2055_C2_LNA_GAINBST 0xD9 /* Core 2 LNA GAINBST */ -#define B2055_C2_B0NB_RSSIVCM 0xDE /* Core 2 B0 narrow-band RSSI VCM */ -#define B2055_C2_GENSPARE2 0xE2 /* Core 2 GEN spare 2 */ - - - -struct b43_wldev; - -struct b43_phy_n { - //TODO lots of missing stuff -}; - - -struct b43_phy_operations; -extern const struct b43_phy_operations b43_phyops_n; - -#endif /* B43_NPHY_H_ */ diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c deleted file mode 100644 index c5cd3bc861be..000000000000 --- a/drivers/net/wireless/b43/pio.c +++ /dev/null @@ -1,828 +0,0 @@ -/* - - Broadcom B43 wireless driver - - PIO data transfer - - Copyright (c) 2005-2008 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "pio.h" -#include "dma.h" -#include "main.h" -#include "xmit.h" - -#include -#include - - -static u16 generate_cookie(struct b43_pio_txqueue *q, - struct b43_pio_txpacket *pack) -{ - u16 cookie; - - /* Use the upper 4 bits of the cookie as - * PIO controller ID and store the packet index number - * in the lower 12 bits. - * Note that the cookie must never be 0, as this - * is a special value used in RX path. - * It can also not be 0xFFFF because that is special - * for multicast frames. - */ - cookie = (((u16)q->index + 1) << 12); - cookie |= pack->index; - - return cookie; -} - -static -struct b43_pio_txqueue *parse_cookie(struct b43_wldev *dev, - u16 cookie, - struct b43_pio_txpacket **pack) -{ - struct b43_pio *pio = &dev->pio; - struct b43_pio_txqueue *q = NULL; - unsigned int pack_index; - - switch (cookie & 0xF000) { - case 0x1000: - q = pio->tx_queue_AC_BK; - break; - case 0x2000: - q = pio->tx_queue_AC_BE; - break; - case 0x3000: - q = pio->tx_queue_AC_VI; - break; - case 0x4000: - q = pio->tx_queue_AC_VO; - break; - case 0x5000: - q = pio->tx_queue_mcast; - break; - } - if (B43_WARN_ON(!q)) - return NULL; - pack_index = (cookie & 0x0FFF); - if (B43_WARN_ON(pack_index >= ARRAY_SIZE(q->packets))) - return NULL; - *pack = &q->packets[pack_index]; - - return q; -} - -static u16 index_to_pioqueue_base(struct b43_wldev *dev, - unsigned int index) -{ - static const u16 bases[] = { - B43_MMIO_PIO_BASE0, - B43_MMIO_PIO_BASE1, - B43_MMIO_PIO_BASE2, - B43_MMIO_PIO_BASE3, - B43_MMIO_PIO_BASE4, - B43_MMIO_PIO_BASE5, - B43_MMIO_PIO_BASE6, - B43_MMIO_PIO_BASE7, - }; - static const u16 bases_rev11[] = { - B43_MMIO_PIO11_BASE0, - B43_MMIO_PIO11_BASE1, - B43_MMIO_PIO11_BASE2, - B43_MMIO_PIO11_BASE3, - B43_MMIO_PIO11_BASE4, - B43_MMIO_PIO11_BASE5, - }; - - if (dev->dev->id.revision >= 11) { - B43_WARN_ON(index >= ARRAY_SIZE(bases_rev11)); - return bases_rev11[index]; - } - B43_WARN_ON(index >= ARRAY_SIZE(bases)); - return bases[index]; -} - -static u16 pio_txqueue_offset(struct b43_wldev *dev) -{ - if (dev->dev->id.revision >= 11) - return 0x18; - return 0; -} - -static u16 pio_rxqueue_offset(struct b43_wldev *dev) -{ - if (dev->dev->id.revision >= 11) - return 0x38; - return 8; -} - -static struct b43_pio_txqueue *b43_setup_pioqueue_tx(struct b43_wldev *dev, - unsigned int index) -{ - struct b43_pio_txqueue *q; - struct b43_pio_txpacket *p; - unsigned int i; - - q = kzalloc(sizeof(*q), GFP_KERNEL); - if (!q) - return NULL; - q->dev = dev; - q->rev = dev->dev->id.revision; - q->mmio_base = index_to_pioqueue_base(dev, index) + - pio_txqueue_offset(dev); - q->index = index; - - q->free_packet_slots = B43_PIO_MAX_NR_TXPACKETS; - if (q->rev >= 8) { - q->buffer_size = 1920; //FIXME this constant is wrong. - } else { - q->buffer_size = b43_piotx_read16(q, B43_PIO_TXQBUFSIZE); - q->buffer_size -= 80; - } - - INIT_LIST_HEAD(&q->packets_list); - for (i = 0; i < ARRAY_SIZE(q->packets); i++) { - p = &(q->packets[i]); - INIT_LIST_HEAD(&p->list); - p->index = i; - p->queue = q; - list_add(&p->list, &q->packets_list); - } - - return q; -} - -static struct b43_pio_rxqueue *b43_setup_pioqueue_rx(struct b43_wldev *dev, - unsigned int index) -{ - struct b43_pio_rxqueue *q; - - q = kzalloc(sizeof(*q), GFP_KERNEL); - if (!q) - return NULL; - q->dev = dev; - q->rev = dev->dev->id.revision; - q->mmio_base = index_to_pioqueue_base(dev, index) + - pio_rxqueue_offset(dev); - - /* Enable Direct FIFO RX (PIO) on the engine. */ - b43_dma_direct_fifo_rx(dev, index, 1); - - return q; -} - -static void b43_pio_cancel_tx_packets(struct b43_pio_txqueue *q) -{ - struct b43_pio_txpacket *pack; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(q->packets); i++) { - pack = &(q->packets[i]); - if (pack->skb) { - dev_kfree_skb_any(pack->skb); - pack->skb = NULL; - } - } -} - -static void b43_destroy_pioqueue_tx(struct b43_pio_txqueue *q, - const char *name) -{ - if (!q) - return; - b43_pio_cancel_tx_packets(q); - kfree(q); -} - -static void b43_destroy_pioqueue_rx(struct b43_pio_rxqueue *q, - const char *name) -{ - if (!q) - return; - kfree(q); -} - -#define destroy_queue_tx(pio, queue) do { \ - b43_destroy_pioqueue_tx((pio)->queue, __stringify(queue)); \ - (pio)->queue = NULL; \ - } while (0) - -#define destroy_queue_rx(pio, queue) do { \ - b43_destroy_pioqueue_rx((pio)->queue, __stringify(queue)); \ - (pio)->queue = NULL; \ - } while (0) - -void b43_pio_free(struct b43_wldev *dev) -{ - struct b43_pio *pio; - - if (!b43_using_pio_transfers(dev)) - return; - pio = &dev->pio; - - destroy_queue_rx(pio, rx_queue); - destroy_queue_tx(pio, tx_queue_mcast); - destroy_queue_tx(pio, tx_queue_AC_VO); - destroy_queue_tx(pio, tx_queue_AC_VI); - destroy_queue_tx(pio, tx_queue_AC_BE); - destroy_queue_tx(pio, tx_queue_AC_BK); -} - -int b43_pio_init(struct b43_wldev *dev) -{ - struct b43_pio *pio = &dev->pio; - int err = -ENOMEM; - - b43_write32(dev, B43_MMIO_MACCTL, b43_read32(dev, B43_MMIO_MACCTL) - & ~B43_MACCTL_BE); - b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_RXPADOFF, 0); - - pio->tx_queue_AC_BK = b43_setup_pioqueue_tx(dev, 0); - if (!pio->tx_queue_AC_BK) - goto out; - - pio->tx_queue_AC_BE = b43_setup_pioqueue_tx(dev, 1); - if (!pio->tx_queue_AC_BE) - goto err_destroy_bk; - - pio->tx_queue_AC_VI = b43_setup_pioqueue_tx(dev, 2); - if (!pio->tx_queue_AC_VI) - goto err_destroy_be; - - pio->tx_queue_AC_VO = b43_setup_pioqueue_tx(dev, 3); - if (!pio->tx_queue_AC_VO) - goto err_destroy_vi; - - pio->tx_queue_mcast = b43_setup_pioqueue_tx(dev, 4); - if (!pio->tx_queue_mcast) - goto err_destroy_vo; - - pio->rx_queue = b43_setup_pioqueue_rx(dev, 0); - if (!pio->rx_queue) - goto err_destroy_mcast; - - b43dbg(dev->wl, "PIO initialized\n"); - err = 0; -out: - return err; - -err_destroy_mcast: - destroy_queue_tx(pio, tx_queue_mcast); -err_destroy_vo: - destroy_queue_tx(pio, tx_queue_AC_VO); -err_destroy_vi: - destroy_queue_tx(pio, tx_queue_AC_VI); -err_destroy_be: - destroy_queue_tx(pio, tx_queue_AC_BE); -err_destroy_bk: - destroy_queue_tx(pio, tx_queue_AC_BK); - return err; -} - -/* Static mapping of mac80211's queues (priorities) to b43 PIO queues. */ -static struct b43_pio_txqueue *select_queue_by_priority(struct b43_wldev *dev, - u8 queue_prio) -{ - struct b43_pio_txqueue *q; - - if (dev->qos_enabled) { - /* 0 = highest priority */ - switch (queue_prio) { - default: - B43_WARN_ON(1); - /* fallthrough */ - case 0: - q = dev->pio.tx_queue_AC_VO; - break; - case 1: - q = dev->pio.tx_queue_AC_VI; - break; - case 2: - q = dev->pio.tx_queue_AC_BE; - break; - case 3: - q = dev->pio.tx_queue_AC_BK; - break; - } - } else - q = dev->pio.tx_queue_AC_BE; - - return q; -} - -static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, - u16 ctl, - const void *_data, - unsigned int data_len) -{ - struct b43_wldev *dev = q->dev; - struct b43_wl *wl = dev->wl; - const u8 *data = _data; - - ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; - b43_piotx_write16(q, B43_PIO_TXCTL, ctl); - - ssb_block_write(dev->dev, data, (data_len & ~1), - q->mmio_base + B43_PIO_TXDATA, - sizeof(u16)); - if (data_len & 1) { - u8 *tail = wl->pio_tailspace; - BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); - - /* Write the last byte. */ - ctl &= ~B43_PIO_TXCTL_WRITEHI; - b43_piotx_write16(q, B43_PIO_TXCTL, ctl); - tail[0] = data[data_len - 1]; - tail[1] = 0; - ssb_block_write(dev->dev, tail, 2, - q->mmio_base + B43_PIO_TXDATA, - sizeof(u16)); - } - - return ctl; -} - -static void pio_tx_frame_2byte_queue(struct b43_pio_txpacket *pack, - const u8 *hdr, unsigned int hdrlen) -{ - struct b43_pio_txqueue *q = pack->queue; - const char *frame = pack->skb->data; - unsigned int frame_len = pack->skb->len; - u16 ctl; - - ctl = b43_piotx_read16(q, B43_PIO_TXCTL); - ctl |= B43_PIO_TXCTL_FREADY; - ctl &= ~B43_PIO_TXCTL_EOF; - - /* Transfer the header data. */ - ctl = tx_write_2byte_queue(q, ctl, hdr, hdrlen); - /* Transfer the frame data. */ - ctl = tx_write_2byte_queue(q, ctl, frame, frame_len); - - ctl |= B43_PIO_TXCTL_EOF; - b43_piotx_write16(q, B43_PIO_TXCTL, ctl); -} - -static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, - u32 ctl, - const void *_data, - unsigned int data_len) -{ - struct b43_wldev *dev = q->dev; - struct b43_wl *wl = dev->wl; - const u8 *data = _data; - - ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 | - B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31; - b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - - ssb_block_write(dev->dev, data, (data_len & ~3), - q->mmio_base + B43_PIO8_TXDATA, - sizeof(u32)); - if (data_len & 3) { - u8 *tail = wl->pio_tailspace; - BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); - - memset(tail, 0, 4); - /* Write the last few bytes. */ - ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | - B43_PIO8_TXCTL_24_31); - switch (data_len & 3) { - case 3: - ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15; - tail[0] = data[data_len - 3]; - tail[1] = data[data_len - 2]; - tail[2] = data[data_len - 1]; - break; - case 2: - ctl |= B43_PIO8_TXCTL_8_15; - tail[0] = data[data_len - 2]; - tail[1] = data[data_len - 1]; - break; - case 1: - tail[0] = data[data_len - 1]; - break; - } - b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - ssb_block_write(dev->dev, tail, 4, - q->mmio_base + B43_PIO8_TXDATA, - sizeof(u32)); - } - - return ctl; -} - -static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack, - const u8 *hdr, unsigned int hdrlen) -{ - struct b43_pio_txqueue *q = pack->queue; - const char *frame = pack->skb->data; - unsigned int frame_len = pack->skb->len; - u32 ctl; - - ctl = b43_piotx_read32(q, B43_PIO8_TXCTL); - ctl |= B43_PIO8_TXCTL_FREADY; - ctl &= ~B43_PIO8_TXCTL_EOF; - - /* Transfer the header data. */ - ctl = tx_write_4byte_queue(q, ctl, hdr, hdrlen); - /* Transfer the frame data. */ - ctl = tx_write_4byte_queue(q, ctl, frame, frame_len); - - ctl |= B43_PIO8_TXCTL_EOF; - b43_piotx_write32(q, B43_PIO_TXCTL, ctl); -} - -static int pio_tx_frame(struct b43_pio_txqueue *q, - struct sk_buff *skb) -{ - struct b43_wldev *dev = q->dev; - struct b43_wl *wl = dev->wl; - struct b43_pio_txpacket *pack; - u16 cookie; - int err; - unsigned int hdrlen; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace; - - B43_WARN_ON(list_empty(&q->packets_list)); - pack = list_entry(q->packets_list.next, - struct b43_pio_txpacket, list); - - cookie = generate_cookie(q, pack); - hdrlen = b43_txhdr_size(dev); - BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr)); - B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen); - err = b43_generate_txhdr(dev, (u8 *)txhdr, skb, - info, cookie); - if (err) - return err; - - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - /* Tell the firmware about the cookie of the last - * mcast frame, so it can clear the more-data bit in it. */ - b43_shm_write16(dev, B43_SHM_SHARED, - B43_SHM_SH_MCASTCOOKIE, cookie); - } - - pack->skb = skb; - if (q->rev >= 8) - pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen); - else - pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen); - - /* Remove it from the list of available packet slots. - * It will be put back when we receive the status report. */ - list_del(&pack->list); - - /* Update the queue statistics. */ - q->buffer_used += roundup(skb->len + hdrlen, 4); - q->free_packet_slots -= 1; - - return 0; -} - -int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb) -{ - struct b43_pio_txqueue *q; - struct ieee80211_hdr *hdr; - unsigned int hdrlen, total_len; - int err = 0; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - hdr = (struct ieee80211_hdr *)skb->data; - - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - /* The multicast queue will be sent after the DTIM. */ - q = dev->pio.tx_queue_mcast; - /* Set the frame More-Data bit. Ucode will clear it - * for us on the last frame. */ - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } else { - /* Decide by priority where to put this frame. */ - q = select_queue_by_priority(dev, skb_get_queue_mapping(skb)); - } - - hdrlen = b43_txhdr_size(dev); - total_len = roundup(skb->len + hdrlen, 4); - - if (unlikely(total_len > q->buffer_size)) { - err = -ENOBUFS; - b43dbg(dev->wl, "PIO: TX packet longer than queue.\n"); - goto out; - } - if (unlikely(q->free_packet_slots == 0)) { - err = -ENOBUFS; - b43warn(dev->wl, "PIO: TX packet overflow.\n"); - goto out; - } - B43_WARN_ON(q->buffer_used > q->buffer_size); - - if (total_len > (q->buffer_size - q->buffer_used)) { - /* Not enough memory on the queue. */ - err = -EBUSY; - ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); - q->stopped = 1; - goto out; - } - - /* Assign the queue number to the ring (if not already done before) - * so TX status handling can use it. The mac80211-queue to b43-queue - * mapping is static, so we don't need to store it per frame. */ - q->queue_prio = skb_get_queue_mapping(skb); - - err = pio_tx_frame(q, skb); - if (unlikely(err == -ENOKEY)) { - /* Drop this packet, as we don't have the encryption key - * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); - err = 0; - goto out; - } - if (unlikely(err)) { - b43err(dev->wl, "PIO transmission failure\n"); - goto out; - } - q->nr_tx_packets++; - - B43_WARN_ON(q->buffer_used > q->buffer_size); - if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || - (q->free_packet_slots == 0)) { - /* The queue is full. */ - ieee80211_stop_queue(dev->wl->hw, skb_get_queue_mapping(skb)); - q->stopped = 1; - } - -out: - return err; -} - -void b43_pio_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ - struct b43_pio_txqueue *q; - struct b43_pio_txpacket *pack = NULL; - unsigned int total_len; - struct ieee80211_tx_info *info; - - q = parse_cookie(dev, status->cookie, &pack); - if (unlikely(!q)) - return; - B43_WARN_ON(!pack); - - info = IEEE80211_SKB_CB(pack->skb); - - b43_fill_txstatus_report(dev, info, status); - - total_len = pack->skb->len + b43_txhdr_size(dev); - total_len = roundup(total_len, 4); - q->buffer_used -= total_len; - q->free_packet_slots += 1; - - ieee80211_tx_status(dev->wl->hw, pack->skb); - pack->skb = NULL; - list_add(&pack->list, &q->packets_list); - - if (q->stopped) { - ieee80211_wake_queue(dev->wl->hw, q->queue_prio); - q->stopped = 0; - } -} - -void b43_pio_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - const int nr_queues = dev->wl->hw->queues; - struct b43_pio_txqueue *q; - int i; - - for (i = 0; i < nr_queues; i++) { - q = select_queue_by_priority(dev, i); - - stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots; - stats[i].limit = B43_PIO_MAX_NR_TXPACKETS; - stats[i].count = q->nr_tx_packets; - } -} - -/* Returns whether we should fetch another frame. */ -static bool pio_rx_frame(struct b43_pio_rxqueue *q) -{ - struct b43_wldev *dev = q->dev; - struct b43_wl *wl = dev->wl; - u16 len; - u32 macstat; - unsigned int i, padding; - struct sk_buff *skb; - const char *err_msg = NULL; - struct b43_rxhdr_fw4 *rxhdr = - (struct b43_rxhdr_fw4 *)wl->pio_scratchspace; - - BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr)); - memset(rxhdr, 0, sizeof(*rxhdr)); - - /* Check if we have data and wait for it to get ready. */ - if (q->rev >= 8) { - u32 ctl; - - ctl = b43_piorx_read32(q, B43_PIO8_RXCTL); - if (!(ctl & B43_PIO8_RXCTL_FRAMERDY)) - return 0; - b43_piorx_write32(q, B43_PIO8_RXCTL, - B43_PIO8_RXCTL_FRAMERDY); - for (i = 0; i < 10; i++) { - ctl = b43_piorx_read32(q, B43_PIO8_RXCTL); - if (ctl & B43_PIO8_RXCTL_DATARDY) - goto data_ready; - udelay(10); - } - } else { - u16 ctl; - - ctl = b43_piorx_read16(q, B43_PIO_RXCTL); - if (!(ctl & B43_PIO_RXCTL_FRAMERDY)) - return 0; - b43_piorx_write16(q, B43_PIO_RXCTL, - B43_PIO_RXCTL_FRAMERDY); - for (i = 0; i < 10; i++) { - ctl = b43_piorx_read16(q, B43_PIO_RXCTL); - if (ctl & B43_PIO_RXCTL_DATARDY) - goto data_ready; - udelay(10); - } - } - b43dbg(q->dev->wl, "PIO RX timed out\n"); - return 1; -data_ready: - - /* Get the preamble (RX header) */ - if (q->rev >= 8) { - ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), - q->mmio_base + B43_PIO8_RXDATA, - sizeof(u32)); - } else { - ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr), - q->mmio_base + B43_PIO_RXDATA, - sizeof(u16)); - } - /* Sanity checks. */ - len = le16_to_cpu(rxhdr->frame_len); - if (unlikely(len > 0x700)) { - err_msg = "len > 0x700"; - goto rx_error; - } - if (unlikely(len == 0)) { - err_msg = "len == 0"; - goto rx_error; - } - - macstat = le32_to_cpu(rxhdr->mac_status); - if (macstat & B43_RX_MAC_FCSERR) { - if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { - /* Drop frames with failed FCS. */ - err_msg = "Frame FCS error"; - goto rx_error; - } - } - - /* We always pad 2 bytes, as that's what upstream code expects - * due to the RX-header being 30 bytes. In case the frame is - * unaligned, we pad another 2 bytes. */ - padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; - skb = dev_alloc_skb(len + padding + 2); - if (unlikely(!skb)) { - err_msg = "Out of memory"; - goto rx_error; - } - skb_reserve(skb, 2); - skb_put(skb, len + padding); - if (q->rev >= 8) { - ssb_block_read(dev->dev, skb->data + padding, (len & ~3), - q->mmio_base + B43_PIO8_RXDATA, - sizeof(u32)); - if (len & 3) { - u8 *tail = wl->pio_tailspace; - BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4); - - /* Read the last few bytes. */ - ssb_block_read(dev->dev, tail, 4, - q->mmio_base + B43_PIO8_RXDATA, - sizeof(u32)); - switch (len & 3) { - case 3: - skb->data[len + padding - 3] = tail[0]; - skb->data[len + padding - 2] = tail[1]; - skb->data[len + padding - 1] = tail[2]; - break; - case 2: - skb->data[len + padding - 2] = tail[0]; - skb->data[len + padding - 1] = tail[1]; - break; - case 1: - skb->data[len + padding - 1] = tail[0]; - break; - } - } - } else { - ssb_block_read(dev->dev, skb->data + padding, (len & ~1), - q->mmio_base + B43_PIO_RXDATA, - sizeof(u16)); - if (len & 1) { - u8 *tail = wl->pio_tailspace; - BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2); - - /* Read the last byte. */ - ssb_block_read(dev->dev, tail, 2, - q->mmio_base + B43_PIO_RXDATA, - sizeof(u16)); - skb->data[len + padding - 1] = tail[0]; - } - } - - b43_rx(q->dev, skb, rxhdr); - - return 1; - -rx_error: - if (err_msg) - b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg); - b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY); - return 1; -} - -void b43_pio_rx(struct b43_pio_rxqueue *q) -{ - unsigned int count = 0; - bool stop; - - while (1) { - stop = (pio_rx_frame(q) == 0); - if (stop) - break; - cond_resched(); - if (WARN_ON_ONCE(++count > 10000)) - break; - } -} - -static void b43_pio_tx_suspend_queue(struct b43_pio_txqueue *q) -{ - if (q->rev >= 8) { - b43_piotx_write32(q, B43_PIO8_TXCTL, - b43_piotx_read32(q, B43_PIO8_TXCTL) - | B43_PIO8_TXCTL_SUSPREQ); - } else { - b43_piotx_write16(q, B43_PIO_TXCTL, - b43_piotx_read16(q, B43_PIO_TXCTL) - | B43_PIO_TXCTL_SUSPREQ); - } -} - -static void b43_pio_tx_resume_queue(struct b43_pio_txqueue *q) -{ - if (q->rev >= 8) { - b43_piotx_write32(q, B43_PIO8_TXCTL, - b43_piotx_read32(q, B43_PIO8_TXCTL) - & ~B43_PIO8_TXCTL_SUSPREQ); - } else { - b43_piotx_write16(q, B43_PIO_TXCTL, - b43_piotx_read16(q, B43_PIO_TXCTL) - & ~B43_PIO_TXCTL_SUSPREQ); - } -} - -void b43_pio_tx_suspend(struct b43_wldev *dev) -{ - b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); - b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BK); - b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_BE); - b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VI); - b43_pio_tx_suspend_queue(dev->pio.tx_queue_AC_VO); - b43_pio_tx_suspend_queue(dev->pio.tx_queue_mcast); -} - -void b43_pio_tx_resume(struct b43_wldev *dev) -{ - b43_pio_tx_resume_queue(dev->pio.tx_queue_mcast); - b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VO); - b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_VI); - b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BE); - b43_pio_tx_resume_queue(dev->pio.tx_queue_AC_BK); - b43_power_saving_ctl_bits(dev, 0); -} diff --git a/drivers/net/wireless/b43/pio.h b/drivers/net/wireless/b43/pio.h deleted file mode 100644 index 7b3c42f93a16..000000000000 --- a/drivers/net/wireless/b43/pio.h +++ /dev/null @@ -1,170 +0,0 @@ -#ifndef B43_PIO_H_ -#define B43_PIO_H_ - -#include "b43.h" - -#include -#include -#include -#include - - -/*** Registers for PIO queues up to revision 7. ***/ -/* TX queue. */ -#define B43_PIO_TXCTL 0x00 -#define B43_PIO_TXCTL_WRITELO 0x0001 -#define B43_PIO_TXCTL_WRITEHI 0x0002 -#define B43_PIO_TXCTL_EOF 0x0004 -#define B43_PIO_TXCTL_FREADY 0x0008 -#define B43_PIO_TXCTL_FLUSHREQ 0x0020 -#define B43_PIO_TXCTL_FLUSHPEND 0x0040 -#define B43_PIO_TXCTL_SUSPREQ 0x0080 -#define B43_PIO_TXCTL_QSUSP 0x0100 -#define B43_PIO_TXCTL_COMMCNT 0xFC00 -#define B43_PIO_TXCTL_COMMCNT_SHIFT 10 -#define B43_PIO_TXDATA 0x02 -#define B43_PIO_TXQBUFSIZE 0x04 -/* RX queue. */ -#define B43_PIO_RXCTL 0x00 -#define B43_PIO_RXCTL_FRAMERDY 0x0001 -#define B43_PIO_RXCTL_DATARDY 0x0002 -#define B43_PIO_RXDATA 0x02 - -/*** Registers for PIO queues revision 8 and later. ***/ -/* TX queue */ -#define B43_PIO8_TXCTL 0x00 -#define B43_PIO8_TXCTL_0_7 0x00000001 -#define B43_PIO8_TXCTL_8_15 0x00000002 -#define B43_PIO8_TXCTL_16_23 0x00000004 -#define B43_PIO8_TXCTL_24_31 0x00000008 -#define B43_PIO8_TXCTL_EOF 0x00000010 -#define B43_PIO8_TXCTL_FREADY 0x00000080 -#define B43_PIO8_TXCTL_SUSPREQ 0x00000100 -#define B43_PIO8_TXCTL_QSUSP 0x00000200 -#define B43_PIO8_TXCTL_FLUSHREQ 0x00000400 -#define B43_PIO8_TXCTL_FLUSHPEND 0x00000800 -#define B43_PIO8_TXDATA 0x04 -/* RX queue */ -#define B43_PIO8_RXCTL 0x00 -#define B43_PIO8_RXCTL_FRAMERDY 0x00000001 -#define B43_PIO8_RXCTL_DATARDY 0x00000002 -#define B43_PIO8_RXDATA 0x04 - - -/* The maximum number of TX-packets the HW can handle. */ -#define B43_PIO_MAX_NR_TXPACKETS 32 - - -struct b43_pio_txpacket { - /* Pointer to the TX queue we belong to. */ - struct b43_pio_txqueue *queue; - /* The TX data packet. */ - struct sk_buff *skb; - /* Index in the (struct b43_pio_txqueue)->packets array. */ - u8 index; - - struct list_head list; -}; - -struct b43_pio_txqueue { - struct b43_wldev *dev; - u16 mmio_base; - - /* The device queue buffer size in bytes. */ - u16 buffer_size; - /* The number of used bytes in the device queue buffer. */ - u16 buffer_used; - /* The number of packets that can still get queued. - * This is decremented on queueing a packet and incremented - * after receiving the transmit status. */ - u16 free_packet_slots; - - /* True, if the mac80211 queue was stopped due to overflow at TX. */ - bool stopped; - /* Our b43 queue index number */ - u8 index; - /* The mac80211 QoS queue priority. */ - u8 queue_prio; - - /* Buffer for TX packet meta data. */ - struct b43_pio_txpacket packets[B43_PIO_MAX_NR_TXPACKETS]; - struct list_head packets_list; - - /* Total number of transmitted packets. */ - unsigned int nr_tx_packets; - - /* Shortcut to the 802.11 core revision. This is to - * avoid horrible pointer dereferencing in the fastpaths. */ - u8 rev; -}; - -struct b43_pio_rxqueue { - struct b43_wldev *dev; - u16 mmio_base; - - /* Shortcut to the 802.11 core revision. This is to - * avoid horrible pointer dereferencing in the fastpaths. */ - u8 rev; -}; - - -static inline u16 b43_piotx_read16(struct b43_pio_txqueue *q, u16 offset) -{ - return b43_read16(q->dev, q->mmio_base + offset); -} - -static inline u32 b43_piotx_read32(struct b43_pio_txqueue *q, u16 offset) -{ - return b43_read32(q->dev, q->mmio_base + offset); -} - -static inline void b43_piotx_write16(struct b43_pio_txqueue *q, - u16 offset, u16 value) -{ - b43_write16(q->dev, q->mmio_base + offset, value); -} - -static inline void b43_piotx_write32(struct b43_pio_txqueue *q, - u16 offset, u32 value) -{ - b43_write32(q->dev, q->mmio_base + offset, value); -} - - -static inline u16 b43_piorx_read16(struct b43_pio_rxqueue *q, u16 offset) -{ - return b43_read16(q->dev, q->mmio_base + offset); -} - -static inline u32 b43_piorx_read32(struct b43_pio_rxqueue *q, u16 offset) -{ - return b43_read32(q->dev, q->mmio_base + offset); -} - -static inline void b43_piorx_write16(struct b43_pio_rxqueue *q, - u16 offset, u16 value) -{ - b43_write16(q->dev, q->mmio_base + offset, value); -} - -static inline void b43_piorx_write32(struct b43_pio_rxqueue *q, - u16 offset, u32 value) -{ - b43_write32(q->dev, q->mmio_base + offset, value); -} - - -int b43_pio_init(struct b43_wldev *dev); -void b43_pio_free(struct b43_wldev *dev); - -int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb); -void b43_pio_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status); -void b43_pio_get_tx_stats(struct b43_wldev *dev, - struct ieee80211_tx_queue_stats *stats); -void b43_pio_rx(struct b43_pio_rxqueue *q); - -void b43_pio_tx_suspend(struct b43_wldev *dev); -void b43_pio_tx_resume(struct b43_wldev *dev); - -#endif /* B43_PIO_H_ */ diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c deleted file mode 100644 index 78016ae21c50..000000000000 --- a/drivers/net/wireless/b43/rfkill.c +++ /dev/null @@ -1,86 +0,0 @@ -/* - - Broadcom B43 wireless driver - RFKILL support - - Copyright (c) 2007 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" - - -/* Returns TRUE, if the radio is enabled in hardware. */ -bool b43_is_hw_radio_enabled(struct b43_wldev *dev) -{ - if (dev->phy.rev >= 3 || dev->phy.type == B43_PHYTYPE_LP) { - if (!(b43_read32(dev, B43_MMIO_RADIO_HWENABLED_HI) - & B43_MMIO_RADIO_HWENABLED_HI_MASK)) - return 1; - } else { - /* To prevent CPU fault on PPC, do not read a register - * unless the interface is started; however, on resume - * for hibernation, this routine is entered early. When - * that happens, unconditionally return TRUE. - */ - if (b43_status(dev) < B43_STAT_STARTED) - return 1; - if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) - & B43_MMIO_RADIO_HWENABLED_LO_MASK) - return 1; - } - return 0; -} - -/* The poll callback for the hardware button. */ -void b43_rfkill_poll(struct ieee80211_hw *hw) -{ - struct b43_wl *wl = hw_to_b43_wl(hw); - struct b43_wldev *dev = wl->current_dev; - struct ssb_bus *bus = dev->dev->bus; - bool enabled; - bool brought_up = false; - - mutex_lock(&wl->mutex); - if (unlikely(b43_status(dev) < B43_STAT_INITIALIZED)) { - if (ssb_bus_powerup(bus, 0)) { - mutex_unlock(&wl->mutex); - return; - } - ssb_device_enable(dev->dev, 0); - brought_up = true; - } - - enabled = b43_is_hw_radio_enabled(dev); - - if (unlikely(enabled != dev->radio_hw_enable)) { - dev->radio_hw_enable = enabled; - b43info(wl, "Radio hardware status changed to %s\n", - enabled ? "ENABLED" : "DISABLED"); - wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); - if (enabled != dev->phy.radio_on) - b43_software_rfkill(dev, !enabled); - } - - if (brought_up) { - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(bus); - } - - mutex_unlock(&wl->mutex); -} diff --git a/drivers/net/wireless/b43/rfkill.h b/drivers/net/wireless/b43/rfkill.h deleted file mode 100644 index f046c3ca0519..000000000000 --- a/drivers/net/wireless/b43/rfkill.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef B43_RFKILL_H_ -#define B43_RFKILL_H_ - -struct ieee80211_hw; -struct b43_wldev; - -void b43_rfkill_poll(struct ieee80211_hw *hw); - -bool b43_is_hw_radio_enabled(struct b43_wldev *dev); - -#endif /* B43_RFKILL_H_ */ diff --git a/drivers/net/wireless/b43/sdio.c b/drivers/net/wireless/b43/sdio.c deleted file mode 100644 index 0d3ac64147a5..000000000000 --- a/drivers/net/wireless/b43/sdio.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Broadcom B43 wireless driver - * - * SDIO over Sonics Silicon Backplane bus glue for b43. - * - * Copyright (C) 2009 Albert Herranz - * Copyright (C) 2009 Michael Buesch - * - * 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. - */ - -#include -#include -#include -#include -#include - -#include "sdio.h" -#include "b43.h" - - -#define HNBU_CHIPID 0x01 /* vendor & device id */ - -#define B43_SDIO_BLOCK_SIZE 64 /* rx fifo max size in bytes */ - - -static const struct b43_sdio_quirk { - u16 vendor; - u16 device; - unsigned int quirks; -} b43_sdio_quirks[] = { - { 0x14E4, 0x4318, SSB_QUIRK_SDIO_READ_AFTER_WRITE32, }, - { }, -}; - - -static unsigned int b43_sdio_get_quirks(u16 vendor, u16 device) -{ - const struct b43_sdio_quirk *q; - - for (q = b43_sdio_quirks; q->quirks; q++) { - if (vendor == q->vendor && device == q->device) - return q->quirks; - } - - return 0; -} - -static void b43_sdio_interrupt_dispatcher(struct sdio_func *func) -{ - struct b43_sdio *sdio = sdio_get_drvdata(func); - struct b43_wldev *dev = sdio->irq_handler_opaque; - - if (unlikely(b43_status(dev) < B43_STAT_STARTED)) - return; - - sdio_release_host(func); - sdio->irq_handler(dev); - sdio_claim_host(func); -} - -int b43_sdio_request_irq(struct b43_wldev *dev, - void (*handler)(struct b43_wldev *dev)) -{ - struct ssb_bus *bus = dev->dev->bus; - struct sdio_func *func = bus->host_sdio; - struct b43_sdio *sdio = sdio_get_drvdata(func); - int err; - - sdio->irq_handler_opaque = dev; - sdio->irq_handler = handler; - sdio_claim_host(func); - err = sdio_claim_irq(func, b43_sdio_interrupt_dispatcher); - sdio_release_host(func); - - return err; -} - -void b43_sdio_free_irq(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct sdio_func *func = bus->host_sdio; - struct b43_sdio *sdio = sdio_get_drvdata(func); - - sdio_claim_host(func); - sdio_release_irq(func); - sdio_release_host(func); - sdio->irq_handler_opaque = NULL; - sdio->irq_handler = NULL; -} - -static int b43_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - struct b43_sdio *sdio; - struct sdio_func_tuple *tuple; - u16 vendor = 0, device = 0; - int error; - - /* Look for the card chip identifier. */ - tuple = func->tuples; - while (tuple) { - switch (tuple->code) { - case 0x80: - switch (tuple->data[0]) { - case HNBU_CHIPID: - if (tuple->size != 5) - break; - vendor = tuple->data[1] | (tuple->data[2]<<8); - device = tuple->data[3] | (tuple->data[4]<<8); - dev_info(&func->dev, "Chip ID %04x:%04x\n", - vendor, device); - break; - default: - break; - } - break; - default: - break; - } - tuple = tuple->next; - } - if (!vendor || !device) { - error = -ENODEV; - goto out; - } - - sdio_claim_host(func); - error = sdio_set_block_size(func, B43_SDIO_BLOCK_SIZE); - if (error) { - dev_err(&func->dev, "failed to set block size to %u bytes," - " error %d\n", B43_SDIO_BLOCK_SIZE, error); - goto err_release_host; - } - error = sdio_enable_func(func); - if (error) { - dev_err(&func->dev, "failed to enable func, error %d\n", error); - goto err_release_host; - } - sdio_release_host(func); - - sdio = kzalloc(sizeof(*sdio), GFP_KERNEL); - if (!sdio) { - error = -ENOMEM; - dev_err(&func->dev, "failed to allocate ssb bus\n"); - goto err_disable_func; - } - error = ssb_bus_sdiobus_register(&sdio->ssb, func, - b43_sdio_get_quirks(vendor, device)); - if (error) { - dev_err(&func->dev, "failed to register ssb sdio bus," - " error %d\n", error); - goto err_free_ssb; - } - sdio_set_drvdata(func, sdio); - - return 0; - -err_free_ssb: - kfree(sdio); -err_disable_func: - sdio_disable_func(func); -err_release_host: - sdio_release_host(func); -out: - return error; -} - -static void b43_sdio_remove(struct sdio_func *func) -{ - struct b43_sdio *sdio = sdio_get_drvdata(func); - - ssb_bus_unregister(&sdio->ssb); - sdio_disable_func(func); - kfree(sdio); - sdio_set_drvdata(func, NULL); -} - -static const struct sdio_device_id b43_sdio_ids[] = { - { SDIO_DEVICE(0x02d0, 0x044b) }, /* Nintendo Wii WLAN daughter card */ - { }, -}; - -static struct sdio_driver b43_sdio_driver = { - .name = "b43-sdio", - .id_table = b43_sdio_ids, - .probe = b43_sdio_probe, - .remove = b43_sdio_remove, -}; - -int b43_sdio_init(void) -{ - return sdio_register_driver(&b43_sdio_driver); -} - -void b43_sdio_exit(void) -{ - sdio_unregister_driver(&b43_sdio_driver); -} diff --git a/drivers/net/wireless/b43/sdio.h b/drivers/net/wireless/b43/sdio.h deleted file mode 100644 index fb633094403a..000000000000 --- a/drivers/net/wireless/b43/sdio.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef B43_SDIO_H_ -#define B43_SDIO_H_ - -#include - -struct b43_wldev; - - -#ifdef CONFIG_B43_SDIO - -struct b43_sdio { - struct ssb_bus ssb; - void *irq_handler_opaque; - void (*irq_handler)(struct b43_wldev *dev); -}; - -int b43_sdio_request_irq(struct b43_wldev *dev, - void (*handler)(struct b43_wldev *dev)); -void b43_sdio_free_irq(struct b43_wldev *dev); - -int b43_sdio_init(void); -void b43_sdio_exit(void); - - -#else /* CONFIG_B43_SDIO */ - - -int b43_sdio_request_irq(struct b43_wldev *dev, - void (*handler)(struct b43_wldev *dev)) -{ - return -ENODEV; -} -void b43_sdio_free_irq(struct b43_wldev *dev) -{ -} -static inline int b43_sdio_init(void) -{ - return 0; -} -static inline void b43_sdio_exit(void) -{ -} - -#endif /* CONFIG_B43_SDIO */ -#endif /* B43_SDIO_H_ */ diff --git a/drivers/net/wireless/b43/sysfs.c b/drivers/net/wireless/b43/sysfs.c deleted file mode 100644 index f1ae4e05a32c..000000000000 --- a/drivers/net/wireless/b43/sysfs.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - - Broadcom B43 wireless driver - - SYSFS support routines - - Copyright (c) 2006 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include - -#include "b43.h" -#include "sysfs.h" -#include "main.h" -#include "phy_common.h" - -#define GENERIC_FILESIZE 64 - -static int get_integer(const char *buf, size_t count) -{ - char tmp[10 + 1] = { 0 }; - int ret = -EINVAL; - - if (count == 0) - goto out; - count = min(count, (size_t) 10); - memcpy(tmp, buf, count); - ret = simple_strtol(tmp, NULL, 10); - out: - return ret; -} - -static ssize_t b43_attr_interfmode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct b43_wldev *wldev = dev_to_b43_wldev(dev); - ssize_t count = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&wldev->wl->mutex); - - if (wldev->phy.type != B43_PHYTYPE_G) { - mutex_unlock(&wldev->wl->mutex); - return -ENOSYS; - } - - switch (wldev->phy.g->interfmode) { - case B43_INTERFMODE_NONE: - count = - snprintf(buf, PAGE_SIZE, - "0 (No Interference Mitigation)\n"); - break; - case B43_INTERFMODE_NONWLAN: - count = - snprintf(buf, PAGE_SIZE, - "1 (Non-WLAN Interference Mitigation)\n"); - break; - case B43_INTERFMODE_MANUALWLAN: - count = - snprintf(buf, PAGE_SIZE, - "2 (WLAN Interference Mitigation)\n"); - break; - default: - B43_WARN_ON(1); - } - - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static ssize_t b43_attr_interfmode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct b43_wldev *wldev = dev_to_b43_wldev(dev); - int err; - int mode; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mode = get_integer(buf, count); - switch (mode) { - case 0: - mode = B43_INTERFMODE_NONE; - break; - case 1: - mode = B43_INTERFMODE_NONWLAN; - break; - case 2: - mode = B43_INTERFMODE_MANUALWLAN; - break; - case 3: - mode = B43_INTERFMODE_AUTOWLAN; - break; - default: - return -EINVAL; - } - - mutex_lock(&wldev->wl->mutex); - - if (wldev->phy.ops->interf_mitigation) { - err = wldev->phy.ops->interf_mitigation(wldev, mode); - if (err) { - b43err(wldev->wl, "Interference Mitigation not " - "supported by device\n"); - } - } else - err = -ENOSYS; - - mmiowb(); - mutex_unlock(&wldev->wl->mutex); - - return err ? err : count; -} - -static DEVICE_ATTR(interference, 0644, - b43_attr_interfmode_show, b43_attr_interfmode_store); - -int b43_sysfs_register(struct b43_wldev *wldev) -{ - struct device *dev = wldev->dev->dev; - - B43_WARN_ON(b43_status(wldev) != B43_STAT_INITIALIZED); - - return device_create_file(dev, &dev_attr_interference); -} - -void b43_sysfs_unregister(struct b43_wldev *wldev) -{ - struct device *dev = wldev->dev->dev; - - device_remove_file(dev, &dev_attr_interference); -} diff --git a/drivers/net/wireless/b43/sysfs.h b/drivers/net/wireless/b43/sysfs.h deleted file mode 100644 index 12bda9ef1a85..000000000000 --- a/drivers/net/wireless/b43/sysfs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef B43_SYSFS_H_ -#define B43_SYSFS_H_ - -struct b43_wldev; - -int b43_sysfs_register(struct b43_wldev *dev); -void b43_sysfs_unregister(struct b43_wldev *dev); - -#endif /* B43_SYSFS_H_ */ diff --git a/drivers/net/wireless/b43/tables.c b/drivers/net/wireless/b43/tables.c deleted file mode 100644 index 1ef9a6463ec6..000000000000 --- a/drivers/net/wireless/b43/tables.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005-2007 Stefano Brivio - Copyright (c) 2006, 2006 Michael Buesch - Copyright (c) 2005 Danny van Dyk - Copyright (c) 2005 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "tables.h" -#include "phy_g.h" - - -const u32 b43_tab_rotor[] = { - 0xFEB93FFD, 0xFEC63FFD, /* 0 */ - 0xFED23FFD, 0xFEDF3FFD, - 0xFEEC3FFE, 0xFEF83FFE, - 0xFF053FFE, 0xFF113FFE, - 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ - 0xFF373FFF, 0xFF443FFF, - 0xFF503FFF, 0xFF5D3FFF, - 0xFF693FFF, 0xFF763FFF, - 0xFF824000, 0xFF8F4000, /* 16 */ - 0xFF9B4000, 0xFFA84000, - 0xFFB54000, 0xFFC14000, - 0xFFCE4000, 0xFFDA4000, - 0xFFE74000, 0xFFF34000, /* 24 */ - 0x00004000, 0x000D4000, - 0x00194000, 0x00264000, - 0x00324000, 0x003F4000, - 0x004B4000, 0x00584000, /* 32 */ - 0x00654000, 0x00714000, - 0x007E4000, 0x008A3FFF, - 0x00973FFF, 0x00A33FFF, - 0x00B03FFF, 0x00BC3FFF, /* 40 */ - 0x00C93FFF, 0x00D63FFF, - 0x00E23FFE, 0x00EF3FFE, - 0x00FB3FFE, 0x01083FFE, - 0x01143FFE, 0x01213FFD, /* 48 */ - 0x012E3FFD, 0x013A3FFD, - 0x01473FFD, -}; - -const u32 b43_tab_retard[] = { - 0xDB93CB87, 0xD666CF64, /* 0 */ - 0xD1FDD358, 0xCDA6D826, - 0xCA38DD9F, 0xC729E2B4, - 0xC469E88E, 0xC26AEE2B, - 0xC0DEF46C, 0xC073FA62, /* 8 */ - 0xC01D00D5, 0xC0760743, - 0xC1560D1E, 0xC2E51369, - 0xC4ED18FF, 0xC7AC1ED7, - 0xCB2823B2, 0xCEFA28D9, /* 16 */ - 0xD2F62D3F, 0xD7BB3197, - 0xDCE53568, 0xE1FE3875, - 0xE7D13B35, 0xED663D35, - 0xF39B3EC4, 0xF98E3FA7, /* 24 */ - 0x00004000, 0x06723FA7, - 0x0C653EC4, 0x129A3D35, - 0x182F3B35, 0x1E023875, - 0x231B3568, 0x28453197, /* 32 */ - 0x2D0A2D3F, 0x310628D9, - 0x34D823B2, 0x38541ED7, - 0x3B1318FF, 0x3D1B1369, - 0x3EAA0D1E, 0x3F8A0743, /* 40 */ - 0x3FE300D5, 0x3F8DFA62, - 0x3F22F46C, 0x3D96EE2B, - 0x3B97E88E, 0x38D7E2B4, - 0x35C8DD9F, 0x325AD826, /* 48 */ - 0x2E03D358, 0x299ACF64, - 0x246DCB87, -}; - -const u16 b43_tab_finefreqa[] = { - 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ - 0x0202, 0x0282, 0x0302, 0x0382, - 0x0402, 0x0482, 0x0502, 0x0582, - 0x05E2, 0x0662, 0x06E2, 0x0762, - 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ - 0x09C2, 0x0A22, 0x0AA2, 0x0B02, - 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, - 0x0D42, 0x0DA2, 0x0E02, 0x0E62, - 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ - 0x1062, 0x10C2, 0x1122, 0x1182, - 0x11E2, 0x1242, 0x12A2, 0x12E2, - 0x1342, 0x13A2, 0x1402, 0x1442, - 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ - 0x15E2, 0x1622, 0x1662, 0x16C1, - 0x1701, 0x1741, 0x1781, 0x17E1, - 0x1821, 0x1861, 0x18A1, 0x18E1, - 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ - 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, - 0x1B01, 0x1B41, 0x1B81, 0x1BA1, - 0x1BE1, 0x1C21, 0x1C41, 0x1C81, - 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ - 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, - 0x1E21, 0x1E61, 0x1E81, 0x1EA1, - 0x1EE1, 0x1F01, 0x1F21, 0x1F41, - 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ - 0x2001, 0x2041, 0x2061, 0x2081, - 0x20A1, 0x20C1, 0x20E1, 0x2101, - 0x2121, 0x2141, 0x2161, 0x2181, - 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ - 0x2221, 0x2241, 0x2261, 0x2281, - 0x22A1, 0x22C1, 0x22C1, 0x22E1, - 0x2301, 0x2321, 0x2341, 0x2361, - 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ - 0x23E1, 0x23E1, 0x2401, 0x2421, - 0x2441, 0x2441, 0x2461, 0x2481, - 0x2481, 0x24A1, 0x24C1, 0x24C1, - 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ - 0x2541, 0x2541, 0x2561, 0x2561, - 0x2581, 0x25A1, 0x25A1, 0x25C1, - 0x25C1, 0x25E1, 0x2601, 0x2601, - 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ - 0x2661, 0x2661, 0x2681, 0x2681, - 0x26A1, 0x26A1, 0x26C1, 0x26C1, - 0x26E1, 0x26E1, 0x2701, 0x2701, - 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ - 0x2760, 0x2760, 0x2780, 0x2780, - 0x2780, 0x27A0, 0x27A0, 0x27C0, - 0x27C0, 0x27E0, 0x27E0, 0x27E0, - 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ - 0x2820, 0x2840, 0x2840, 0x2840, - 0x2860, 0x2860, 0x2880, 0x2880, - 0x2880, 0x28A0, 0x28A0, 0x28A0, - 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ - 0x28E0, 0x28E0, 0x2900, 0x2900, - 0x2900, 0x2920, 0x2920, 0x2920, - 0x2940, 0x2940, 0x2940, 0x2960, - 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ - 0x2980, 0x2980, 0x29A0, 0x29A0, - 0x29A0, 0x29A0, 0x29C0, 0x29C0, - 0x29C0, 0x29E0, 0x29E0, 0x29E0, - 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ - 0x2A00, 0x2A20, 0x2A20, 0x2A20, - 0x2A20, 0x2A40, 0x2A40, 0x2A40, - 0x2A40, 0x2A60, 0x2A60, 0x2A60, -}; - -const u16 b43_tab_finefreqg[] = { - 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ - 0x05A9, 0x0669, 0x0709, 0x0789, - 0x0829, 0x08A9, 0x0929, 0x0989, - 0x0A09, 0x0A69, 0x0AC9, 0x0B29, - 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ - 0x0D09, 0x0D69, 0x0DA9, 0x0E09, - 0x0E69, 0x0EA9, 0x0F09, 0x0F49, - 0x0FA9, 0x0FE9, 0x1029, 0x1089, - 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ - 0x11E9, 0x1229, 0x1289, 0x12C9, - 0x1309, 0x1349, 0x1389, 0x13C9, - 0x1409, 0x1449, 0x14A9, 0x14E9, - 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ - 0x1629, 0x1669, 0x16A9, 0x16E8, - 0x1728, 0x1768, 0x17A8, 0x17E8, - 0x1828, 0x1868, 0x18A8, 0x18E8, - 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ - 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, - 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, - 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, - 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ - 0x1E48, 0x1E88, 0x1EC8, 0x1F08, - 0x1F48, 0x1F88, 0x1FE8, 0x2028, - 0x2068, 0x20A8, 0x2108, 0x2148, - 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ - 0x22C8, 0x2308, 0x2348, 0x23A8, - 0x23E8, 0x2448, 0x24A8, 0x24E8, - 0x2548, 0x25A8, 0x2608, 0x2668, - 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ - 0x2847, 0x28C7, 0x2947, 0x29A7, - 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, - 0x2CA7, 0x2D67, 0x2E47, 0x2F67, - 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ - 0x3806, 0x38A6, 0x3946, 0x39E6, - 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, - 0x3C45, 0x3CA5, 0x3D05, 0x3D85, - 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ - 0x3F45, 0x3FA5, 0x4005, 0x4045, - 0x40A5, 0x40E5, 0x4145, 0x4185, - 0x41E5, 0x4225, 0x4265, 0x42C5, - 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ - 0x4424, 0x4464, 0x44C4, 0x4504, - 0x4544, 0x4584, 0x45C4, 0x4604, - 0x4644, 0x46A4, 0x46E4, 0x4724, - 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ - 0x4864, 0x48A4, 0x48E4, 0x4924, - 0x4964, 0x49A4, 0x49E4, 0x4A24, - 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, - 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ - 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, - 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, - 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, - 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ - 0x5083, 0x50C3, 0x5103, 0x5143, - 0x5183, 0x51E2, 0x5222, 0x5262, - 0x52A2, 0x52E2, 0x5342, 0x5382, - 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ - 0x5502, 0x5542, 0x55A2, 0x55E2, - 0x5642, 0x5682, 0x56E2, 0x5722, - 0x5782, 0x57E1, 0x5841, 0x58A1, - 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ - 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, - 0x5C61, 0x5D01, 0x5D80, 0x5E20, - 0x5EE0, 0x5FA0, 0x6080, 0x61C0, -}; - -const u16 b43_tab_noisea2[] = { - 0x0001, 0x0001, 0x0001, 0xFFFE, - 0xFFFE, 0x3FFF, 0x1000, 0x0393, -}; - -const u16 b43_tab_noisea3[] = { - 0x5E5E, 0x5E5E, 0x5E5E, 0x3F48, - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, -}; - -const u16 b43_tab_noiseg1[] = { - 0x013C, 0x01F5, 0x031A, 0x0631, - 0x0001, 0x0001, 0x0001, 0x0001, -}; - -const u16 b43_tab_noiseg2[] = { - 0x5484, 0x3C40, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, -}; - -const u16 b43_tab_noisescalea2[] = { - 0x6767, 0x6767, 0x6767, 0x6767, /* 0 */ - 0x6767, 0x6767, 0x6767, 0x6767, - 0x6767, 0x6767, 0x6767, 0x6767, - 0x6767, 0x6700, 0x6767, 0x6767, - 0x6767, 0x6767, 0x6767, 0x6767, /* 16 */ - 0x6767, 0x6767, 0x6767, 0x6767, - 0x6767, 0x6767, 0x0067, -}; - -const u16 b43_tab_noisescalea3[] = { - 0x2323, 0x2323, 0x2323, 0x2323, /* 0 */ - 0x2323, 0x2323, 0x2323, 0x2323, - 0x2323, 0x2323, 0x2323, 0x2323, - 0x2323, 0x2300, 0x2323, 0x2323, - 0x2323, 0x2323, 0x2323, 0x2323, /* 16 */ - 0x2323, 0x2323, 0x2323, 0x2323, - 0x2323, 0x2323, 0x0023, -}; - -const u16 b43_tab_noisescaleg1[] = { - 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ - 0x2F2D, 0x2A2A, 0x2527, 0x1F21, - 0x1A1D, 0x1719, 0x1616, 0x1414, - 0x1414, 0x1400, 0x1414, 0x1614, - 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ - 0x2A27, 0x2F2A, 0x332D, 0x3B35, - 0x5140, 0x6C62, 0x0077, -}; - -const u16 b43_tab_noisescaleg2[] = { - 0xD8DD, 0xCBD4, 0xBCC0, 0xB6B7, /* 0 */ - 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, - 0x969B, 0x9195, 0x8F8F, 0x8A8A, - 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, - 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ - 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, - 0xCBC0, 0xD8D4, 0x00DD, -}; - -const u16 b43_tab_noisescaleg3[] = { - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0x00A4, -}; - -const u16 b43_tab_sigmasqr1[] = { - 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ - 0x0067, 0x0063, 0x005E, 0x0059, - 0x0054, 0x0050, 0x004B, 0x0046, - 0x0042, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x0000, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x0042, 0x0046, 0x004B, 0x0050, - 0x0054, 0x0059, 0x005E, 0x0063, - 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ - 0x007A, -}; - -const u16 b43_tab_sigmasqr2[] = { - 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ - 0x00D6, 0x00D4, 0x00D2, 0x00CF, - 0x00CD, 0x00CA, 0x00C7, 0x00C4, - 0x00C1, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x0000, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00C1, 0x00C4, 0x00C7, 0x00CA, - 0x00CD, 0x00CF, 0x00D2, 0x00D4, - 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ - 0x00DE, -}; - -const u16 b43_tab_rssiagc1[] = { - 0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, /* 0 */ - 0xFFF8, 0xFFF9, 0xFFFC, 0xFFFE, - 0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, - 0xFFF8, 0xFFF8, 0xFFF8, 0xFFF8, -}; - -const u16 b43_tab_rssiagc2[] = { - 0x0820, 0x0820, 0x0920, 0x0C38, /* 0 */ - 0x0820, 0x0820, 0x0820, 0x0820, - 0x0820, 0x0820, 0x0920, 0x0A38, - 0x0820, 0x0820, 0x0820, 0x0820, - 0x0820, 0x0820, 0x0920, 0x0A38, /* 16 */ - 0x0820, 0x0820, 0x0820, 0x0820, - 0x0820, 0x0820, 0x0920, 0x0A38, - 0x0820, 0x0820, 0x0820, 0x0820, - 0x0820, 0x0820, 0x0920, 0x0A38, /* 32 */ - 0x0820, 0x0820, 0x0820, 0x0820, - 0x0820, 0x0820, 0x0920, 0x0A38, - 0x0820, 0x0820, 0x0820, 0x0820, -}; - -static inline void assert_sizes(void) -{ - BUILD_BUG_ON(B43_TAB_ROTOR_SIZE != ARRAY_SIZE(b43_tab_rotor)); - BUILD_BUG_ON(B43_TAB_RETARD_SIZE != ARRAY_SIZE(b43_tab_retard)); - BUILD_BUG_ON(B43_TAB_FINEFREQA_SIZE != ARRAY_SIZE(b43_tab_finefreqa)); - BUILD_BUG_ON(B43_TAB_FINEFREQG_SIZE != ARRAY_SIZE(b43_tab_finefreqg)); - BUILD_BUG_ON(B43_TAB_NOISEA2_SIZE != ARRAY_SIZE(b43_tab_noisea2)); - BUILD_BUG_ON(B43_TAB_NOISEA3_SIZE != ARRAY_SIZE(b43_tab_noisea3)); - BUILD_BUG_ON(B43_TAB_NOISEG1_SIZE != ARRAY_SIZE(b43_tab_noiseg1)); - BUILD_BUG_ON(B43_TAB_NOISEG2_SIZE != ARRAY_SIZE(b43_tab_noiseg2)); - BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE != - ARRAY_SIZE(b43_tab_noisescalea2)); - BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE != - ARRAY_SIZE(b43_tab_noisescalea3)); - BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE != - ARRAY_SIZE(b43_tab_noisescaleg1)); - BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE != - ARRAY_SIZE(b43_tab_noisescaleg2)); - BUILD_BUG_ON(B43_TAB_NOISESCALE_SIZE != - ARRAY_SIZE(b43_tab_noisescaleg3)); - BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr1)); - BUILD_BUG_ON(B43_TAB_SIGMASQR_SIZE != ARRAY_SIZE(b43_tab_sigmasqr2)); - BUILD_BUG_ON(B43_TAB_RSSIAGC1_SIZE != ARRAY_SIZE(b43_tab_rssiagc1)); - BUILD_BUG_ON(B43_TAB_RSSIAGC2_SIZE != ARRAY_SIZE(b43_tab_rssiagc2)); -} - -u16 b43_ofdmtab_read16(struct b43_wldev *dev, u16 table, u16 offset) -{ - struct b43_phy_g *gphy = dev->phy.g; - u16 addr; - - addr = table + offset; - if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || - (addr - 1 != gphy->ofdmtab_addr)) { - /* The hardware has a different address in memory. Update it. */ - b43_phy_write(dev, B43_PHY_OTABLECTL, addr); - gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; - } - gphy->ofdmtab_addr = addr; - - return b43_phy_read(dev, B43_PHY_OTABLEI); - - /* Some compiletime assertions... */ - assert_sizes(); -} - -void b43_ofdmtab_write16(struct b43_wldev *dev, u16 table, - u16 offset, u16 value) -{ - struct b43_phy_g *gphy = dev->phy.g; - u16 addr; - - addr = table + offset; - if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || - (addr - 1 != gphy->ofdmtab_addr)) { - /* The hardware has a different address in memory. Update it. */ - b43_phy_write(dev, B43_PHY_OTABLECTL, addr); - gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; - } - gphy->ofdmtab_addr = addr; - b43_phy_write(dev, B43_PHY_OTABLEI, value); -} - -u32 b43_ofdmtab_read32(struct b43_wldev *dev, u16 table, u16 offset) -{ - struct b43_phy_g *gphy = dev->phy.g; - u32 ret; - u16 addr; - - addr = table + offset; - if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_READ) || - (addr - 1 != gphy->ofdmtab_addr)) { - /* The hardware has a different address in memory. Update it. */ - b43_phy_write(dev, B43_PHY_OTABLECTL, addr); - gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_READ; - } - gphy->ofdmtab_addr = addr; - ret = b43_phy_read(dev, B43_PHY_OTABLEQ); - ret <<= 16; - ret |= b43_phy_read(dev, B43_PHY_OTABLEI); - - return ret; -} - -void b43_ofdmtab_write32(struct b43_wldev *dev, u16 table, - u16 offset, u32 value) -{ - struct b43_phy_g *gphy = dev->phy.g; - u16 addr; - - addr = table + offset; - if ((gphy->ofdmtab_addr_direction != B43_OFDMTAB_DIRECTION_WRITE) || - (addr - 1 != gphy->ofdmtab_addr)) { - /* The hardware has a different address in memory. Update it. */ - b43_phy_write(dev, B43_PHY_OTABLECTL, addr); - gphy->ofdmtab_addr_direction = B43_OFDMTAB_DIRECTION_WRITE; - } - gphy->ofdmtab_addr = addr; - - b43_phy_write(dev, B43_PHY_OTABLEI, value); - b43_phy_write(dev, B43_PHY_OTABLEQ, (value >> 16)); -} - -u16 b43_gtab_read(struct b43_wldev *dev, u16 table, u16 offset) -{ - b43_phy_write(dev, B43_PHY_GTABCTL, table + offset); - return b43_phy_read(dev, B43_PHY_GTABDATA); -} - -void b43_gtab_write(struct b43_wldev *dev, u16 table, u16 offset, u16 value) -{ - b43_phy_write(dev, B43_PHY_GTABCTL, table + offset); - b43_phy_write(dev, B43_PHY_GTABDATA, value); -} diff --git a/drivers/net/wireless/b43/tables.h b/drivers/net/wireless/b43/tables.h deleted file mode 100644 index 80e73c7cbac5..000000000000 --- a/drivers/net/wireless/b43/tables.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef B43_TABLES_H_ -#define B43_TABLES_H_ - -#define B43_TAB_ROTOR_SIZE 53 -extern const u32 b43_tab_rotor[]; -#define B43_TAB_RETARD_SIZE 53 -extern const u32 b43_tab_retard[]; -#define B43_TAB_FINEFREQA_SIZE 256 -extern const u16 b43_tab_finefreqa[]; -#define B43_TAB_FINEFREQG_SIZE 256 -extern const u16 b43_tab_finefreqg[]; -#define B43_TAB_NOISEA2_SIZE 8 -extern const u16 b43_tab_noisea2[]; -#define B43_TAB_NOISEA3_SIZE 8 -extern const u16 b43_tab_noisea3[]; -#define B43_TAB_NOISEG1_SIZE 8 -extern const u16 b43_tab_noiseg1[]; -#define B43_TAB_NOISEG2_SIZE 8 -extern const u16 b43_tab_noiseg2[]; -#define B43_TAB_NOISESCALE_SIZE 27 -extern const u16 b43_tab_noisescalea2[]; -extern const u16 b43_tab_noisescalea3[]; -extern const u16 b43_tab_noisescaleg1[]; -extern const u16 b43_tab_noisescaleg2[]; -extern const u16 b43_tab_noisescaleg3[]; -#define B43_TAB_SIGMASQR_SIZE 53 -extern const u16 b43_tab_sigmasqr1[]; -extern const u16 b43_tab_sigmasqr2[]; -#define B43_TAB_RSSIAGC1_SIZE 16 -extern const u16 b43_tab_rssiagc1[]; -#define B43_TAB_RSSIAGC2_SIZE 48 -extern const u16 b43_tab_rssiagc2[]; - -#endif /* B43_TABLES_H_ */ diff --git a/drivers/net/wireless/b43/tables_lpphy.c b/drivers/net/wireless/b43/tables_lpphy.c deleted file mode 100644 index 61027ee84fb5..000000000000 --- a/drivers/net/wireless/b43/tables_lpphy.c +++ /dev/null @@ -1,2457 +0,0 @@ -/* - - Broadcom B43 wireless driver - IEEE 802.11a/g LP-PHY and radio device data tables - - Copyright (c) 2009 Michael Buesch - Copyright (c) 2009 Gábor Stefanik - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "tables_lpphy.h" -#include "phy_common.h" -#include "phy_lp.h" - - -/* Entry of the 2062/2063 radio init table */ -struct b206x_init_tab_entry { - u16 offset; - u16 value_a; - u16 value_g; - u8 flags; -}; -#define B206X_FLAG_A 0x01 /* Flag: Init in A mode */ -#define B206X_FLAG_G 0x02 /* Flag: Init in G mode */ - -static const struct b206x_init_tab_entry b2062_init_tab[] = { - /* { .offset = B2062_N_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = 0x0001, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_N_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_PDN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_N_PDN_CTL1, .value_a = 0x0000, .value_g = 0x00CA, .flags = B206X_FLAG_G, }, - /* { .offset = B2062_N_PDN_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */ - { .offset = B2062_N_PDN_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_N_PDN_CTL4, .value_a = 0x0015, .value_g = 0x002A, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_GEN_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_IQ_CALIB, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - { .offset = B2062_N_LGENC, .value_a = 0x00DB, .value_g = 0x00FF, .flags = B206X_FLAG_A, }, - /* { .offset = B2062_N_LGENA_LPF, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2062_N_LGENA_BIAS0, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */ - /* { .offset = B2062_N_LGNEA_BIAS1, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ - /* { .offset = B2062_N_LGENA_CTL0, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ - /* { .offset = B2062_N_LGENA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_LGENA_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_N_LGENA_TUNE0, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_LGENA_TUNE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_N_LGENA_TUNE2, .value_a = 0x00DD, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_N_LGENA_TUNE3, .value_a = 0x0077, .value_g = 0x00B5, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_N_LGENA_CTL3, .value_a = 0x0000, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_LGENA_CTL4, .value_a = 0x001F, .value_g = 0x001F, .flags = 0, }, */ - /* { .offset = B2062_N_LGENA_CTL5, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ - /* { .offset = B2062_N_LGENA_CTL6, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ - { .offset = B2062_N_LGENA_CTL7, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_RXA_CTL0, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */ - { .offset = B2062_N_RXA_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - /* { .offset = B2062_N_RXA_CTL2, .value_a = 0x0018, .value_g = 0x0018, .flags = 0, }, */ - /* { .offset = B2062_N_RXA_CTL3, .value_a = 0x0027, .value_g = 0x0027, .flags = 0, }, */ - /* { .offset = B2062_N_RXA_CTL4, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */ - /* { .offset = B2062_N_RXA_CTL5, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ - /* { .offset = B2062_N_RXA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_RXA_CTL7, .value_a = 0x0008, .value_g = 0x0008, .flags = 0, }, */ - { .offset = B2062_N_RXBB_CTL0, .value_a = 0x0082, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_RXBB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_GAIN0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_N_RXBB_GAIN1, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_N_RXBB_GAIN2, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_RXBB_GAIN3, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_RSSI0, .value_a = 0x0043, .value_g = 0x0043, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_RSSI1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_CALIB0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_BIAS0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_BIAS1, .value_a = 0x002A, .value_g = 0x002A, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_BIAS2, .value_a = 0x00AA, .value_g = 0x00AA, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_BIAS3, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_BIAS4, .value_a = 0x00AA, .value_g = 0x00AA, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_BIAS5, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_RSSI2, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_RSSI3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_RSSI4, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2062_N_RXBB_RSSI5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL0, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL2, .value_a = 0x0084, .value_g = 0x0084, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_N_TX_CTL4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_N_TX_CTL5, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_TX_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL7, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL8, .value_a = 0x0082, .value_g = 0x0082, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TX_CTL_A, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TX_GC2G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */ - /* { .offset = B2062_N_TX_GC5G, .value_a = 0x00FF, .value_g = 0x00FF, .flags = 0, }, */ - { .offset = B2062_N_TX_TUNE, .value_a = 0x0088, .value_g = 0x001B, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_N_TX_PAD, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2062_N_TX_PGA, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2062_N_TX_PADAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2062_N_TX_PGAAUX, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2062_N_TSSI_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TSSI_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TSSI_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_IQ_CALIB_CTL0, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2062_N_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_N_IQ_CALIB_CTL2, .value_a = 0x0032, .value_g = 0x0032, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_TS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_CTL1, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_CTL2, .value_a = 0x000F, .value_g = 0x000F, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_DBG0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_DBG1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_DBG2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_CALIB_DBG3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_PSENSE_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_PSENSE_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_PSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_N_TEST_BUF0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RADIO_ID_CODE, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_COMM4, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_COMM15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_PDS_CTL0, .value_a = 0x00FF, .value_g = 0x00FF, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_PDS_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_PDS_CTL2, .value_a = 0x008E, .value_g = 0x008E, .flags = 0, }, */ - /* { .offset = B2062_S_PDS_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_BG_CTL0, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ - /* { .offset = B2062_S_BG_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_BG_CTL2, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ - { .offset = B2062_S_LGENG_CTL0, .value_a = 0x00F8, .value_g = 0x00D8, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_LGENG_CTL1, .value_a = 0x003C, .value_g = 0x0024, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_LGENG_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_LGENG_CTL3, .value_a = 0x0041, .value_g = 0x0041, .flags = 0, }, */ - /* { .offset = B2062_S_LGENG_CTL4, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ - /* { .offset = B2062_S_LGENG_CTL5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2062_S_LGENG_CTL6, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */ - /* { .offset = B2062_S_LGENG_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_LGENG_CTL8, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_LGENG_CTL9, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - { .offset = B2062_S_LGENG_CTL10, .value_a = 0x0088, .value_g = 0x0080, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_LGENG_CTL11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL0, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL2, .value_a = 0x00AF, .value_g = 0x00AF, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL3, .value_a = 0x0012, .value_g = 0x0012, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL4, .value_a = 0x000B, .value_g = 0x000B, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL5, .value_a = 0x005F, .value_g = 0x005F, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL7, .value_a = 0x0040, .value_g = 0x0040, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL8, .value_a = 0x0052, .value_g = 0x0052, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL9, .value_a = 0x0026, .value_g = 0x0026, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL10, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL11, .value_a = 0x0036, .value_g = 0x0036, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL12, .value_a = 0x0057, .value_g = 0x0057, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL13, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL14, .value_a = 0x0075, .value_g = 0x0075, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL15, .value_a = 0x00B4, .value_g = 0x00B4, .flags = 0, }, */ - /* { .offset = B2062_S_REFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_RFPLL_CTL0, .value_a = 0x0098, .value_g = 0x0098, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL1, .value_a = 0x0010, .value_g = 0x0010, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_RFPLL_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_RFPLL_CTL5, .value_a = 0x0043, .value_g = 0x0043, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL6, .value_a = 0x0047, .value_g = 0x0047, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL7, .value_a = 0x000C, .value_g = 0x000C, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL8, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL9, .value_a = 0x0011, .value_g = 0x0011, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL10, .value_a = 0x000E, .value_g = 0x000E, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL11, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL12, .value_a = 0x0033, .value_g = 0x0033, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL13, .value_a = 0x000A, .value_g = 0x000A, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL14, .value_a = 0x0006, .value_g = 0x0006, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_RFPLL_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL17, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_RFPLL_CTL18, .value_a = 0x003E, .value_g = 0x003E, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL19, .value_a = 0x0013, .value_g = 0x0013, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_RFPLL_CTL20, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_RFPLL_CTL21, .value_a = 0x0062, .value_g = 0x0062, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL22, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL23, .value_a = 0x0016, .value_g = 0x0016, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL24, .value_a = 0x005C, .value_g = 0x005C, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL25, .value_a = 0x0095, .value_g = 0x0095, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_RFPLL_CTL26, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL27, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL28, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RFPLL_CTL29, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_RFPLL_CTL30, .value_a = 0x00A0, .value_g = 0x00A0, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL31, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_RFPLL_CTL32, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2062_S_RFPLL_CTL33, .value_a = 0x00CC, .value_g = 0x00CC, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2062_S_RFPLL_CTL34, .value_a = 0x0007, .value_g = 0x0007, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2062_S_RXG_CNT0, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT5, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT6, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - { .offset = B2062_S_RXG_CNT8, .value_a = 0x000F, .value_g = 0x000F, .flags = B206X_FLAG_A, }, - /* { .offset = B2062_S_RXG_CNT9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT10, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT11, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT12, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT13, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT14, .value_a = 0x00A0, .value_g = 0x00A0, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT15, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT16, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2062_S_RXG_CNT17, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ -}; - -static const struct b206x_init_tab_entry b2063_init_tab[] = { - { .offset = B2063_COMM1, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - /* { .offset = B2063_COMM2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_COMM10, .value_a = 0x0001, .value_g = 0x0000, .flags = B206X_FLAG_A, }, - /* { .offset = B2063_COMM11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_COMM14, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ - /* { .offset = B2063_COMM15, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */ - { .offset = B2063_COMM16, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM17, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM18, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM19, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM20, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM21, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM22, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM23, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - { .offset = B2063_COMM24, .value_a = 0x0000, .value_g = 0x0000, .flags = B206X_FLAG_G, }, - /* { .offset = B2063_PWR_SWITCH_CTL, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */ - /* { .offset = B2063_PLL_SP1, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */ - /* { .offset = B2063_PLL_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_LOGEN_SP1, .value_a = 0x00e8, .value_g = 0x00d4, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2063_LOGEN_SP2, .value_a = 0x00a7, .value_g = 0x0053, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_LOGEN_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - { .offset = B2063_LOGEN_SP4, .value_a = 0x00f0, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_LOGEN_SP5, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - { .offset = B2063_G_RX_SP1, .value_a = 0x001f, .value_g = 0x005e, .flags = B206X_FLAG_G, }, - { .offset = B2063_G_RX_SP2, .value_a = 0x007f, .value_g = 0x007e, .flags = B206X_FLAG_G, }, - { .offset = B2063_G_RX_SP3, .value_a = 0x0030, .value_g = 0x00f0, .flags = B206X_FLAG_G, }, - /* { .offset = B2063_G_RX_SP4, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */ - /* { .offset = B2063_G_RX_SP5, .value_a = 0x003f, .value_g = 0x003f, .flags = 0, }, */ - /* { .offset = B2063_G_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_G_RX_SP7, .value_a = 0x007f, .value_g = 0x007f, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_G_RX_SP8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_SP9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_G_RX_SP10, .value_a = 0x000c, .value_g = 0x000c, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_G_RX_SP11, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_A_RX_SP1, .value_a = 0x003c, .value_g = 0x003f, .flags = B206X_FLAG_A, }, - { .offset = B2063_A_RX_SP2, .value_a = 0x00fc, .value_g = 0x00fe, .flags = B206X_FLAG_A, }, - /* { .offset = B2063_A_RX_SP3, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - /* { .offset = B2063_A_RX_SP4, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - /* { .offset = B2063_A_RX_SP5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_A_RX_SP7, .value_a = 0x0008, .value_g = 0x0008, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_RX_BB_SP1, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_SP2, .value_a = 0x0022, .value_g = 0x0022, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_SP3, .value_a = 0x00a8, .value_g = 0x00a8, .flags = 0, }, */ - { .offset = B2063_RX_BB_SP4, .value_a = 0x0060, .value_g = 0x0060, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_RX_BB_SP5, .value_a = 0x0011, .value_g = 0x0011, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_SP6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_SP7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_RX_BB_SP8, .value_a = 0x0030, .value_g = 0x0030, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_TX_RF_SP1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP2, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */ - { .offset = B2063_TX_RF_SP3, .value_a = 0x000c, .value_g = 0x000b, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2063_TX_RF_SP4, .value_a = 0x0010, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_TX_RF_SP5, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP6, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP7, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP8, .value_a = 0x0068, .value_g = 0x0068, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP9, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP10, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP11, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP12, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP13, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP14, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP15, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP16, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_SP17, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - { .offset = B2063_PA_SP1, .value_a = 0x003d, .value_g = 0x00fd, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_PA_SP2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */ - /* { .offset = B2063_PA_SP3, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */ - /* { .offset = B2063_PA_SP4, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */ - /* { .offset = B2063_PA_SP5, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */ - /* { .offset = B2063_PA_SP6, .value_a = 0x007f, .value_g = 0x007f, .flags = 0, }, */ - /* { .offset = B2063_PA_SP7, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - { .offset = B2063_TX_BB_SP1, .value_a = 0x0002, .value_g = 0x0002, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_TX_BB_SP2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_BB_SP3, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */ - /* { .offset = B2063_REG_SP1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_BANDGAP_CTL1, .value_a = 0x0056, .value_g = 0x0056, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_BANDGAP_CTL2, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ - /* { .offset = B2063_LPO_CTL1, .value_a = 0x000e, .value_g = 0x000e, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL1, .value_a = 0x007e, .value_g = 0x007e, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL2, .value_a = 0x0015, .value_g = 0x0015, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL3, .value_a = 0x000f, .value_g = 0x000f, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RC_CALIB_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_CALNRST, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_IN_PLL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_IN_PLL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_CP1, .value_a = 0x00cf, .value_g = 0x00cf, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_CP2, .value_a = 0x0059, .value_g = 0x0059, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_CP3, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_CP4, .value_a = 0x0042, .value_g = 0x0042, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_LF1, .value_a = 0x00db, .value_g = 0x00db, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_LF2, .value_a = 0x0094, .value_g = 0x0094, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_LF3, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_LF4, .value_a = 0x0063, .value_g = 0x0063, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_SG1, .value_a = 0x0007, .value_g = 0x0007, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_SG2, .value_a = 0x00d3, .value_g = 0x00d3, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_SG3, .value_a = 0x00b1, .value_g = 0x00b1, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_SG4, .value_a = 0x003b, .value_g = 0x003b, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_SG5, .value_a = 0x0006, .value_g = 0x0006, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO1, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */ - { .offset = B2063_PLL_JTAG_PLL_VCO2, .value_a = 0x00f7, .value_g = 0x00f7, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB3, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB5, .value_a = 0x0009, .value_g = 0x0009, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB6, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB7, .value_a = 0x0016, .value_g = 0x0016, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB8, .value_a = 0x006b, .value_g = 0x006b, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_VCO_CALIB10, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_XTAL_12, .value_a = 0x0004, .value_g = 0x0004, .flags = 0, }, */ - /* { .offset = B2063_PLL_JTAG_PLL_XTAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_ACL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_ACL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_ACL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_ACL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_ACL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_INPUTS, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_WAITCNT, .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVR2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL4, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL5, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL6, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_OVAL7, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CALVLD1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CALVLD2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LO_CALIB_CVAL7, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_CALIB_EN, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_PEAKDET1, .value_a = 0x00ff, .value_g = 0x00ff, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_RCCR1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_VCOBUF1, .value_a = 0x0060, .value_g = 0x0060, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_MIXER1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_MIXER2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_BUF1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_BUF2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_DIV1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_DIV2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_DIV3, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_CBUFRX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_CBUFRX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_CBUFTX1, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_CBUFTX2, .value_a = 0x0066, .value_g = 0x0066, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_IDAC1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_SPARE1, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_LOGEN_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_1ST1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_G_RX_1ST2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND1, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND2, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND5, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND7, .value_a = 0x0035, .value_g = 0x0035, .flags = 0, }, */ - /* { .offset = B2063_G_RX_2ND8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_PS1, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_G_RX_PS2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_PS3, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_G_RX_PS4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_MIX1, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */ - /* { .offset = B2063_G_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_G_RX_MIX3, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2063_G_RX_MIX4, .value_a = 0x0071, .value_g = 0x0071, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_G_RX_MIX5, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */ - /* { .offset = B2063_G_RX_MIX6, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2063_G_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */ - /* { .offset = B2063_G_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2063_G_RX_PDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_SPARES1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_SPARES2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_G_RX_SPARES3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_1ST1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_A_RX_1ST2, .value_a = 0x00f0, .value_g = 0x0030, .flags = B206X_FLAG_A, }, - /* { .offset = B2063_A_RX_1ST3, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - /* { .offset = B2063_A_RX_1ST4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_A_RX_1ST5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND1, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND4, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_2ND7, .value_a = 0x0005, .value_g = 0x0005, .flags = 0, }, */ - /* { .offset = B2063_A_RX_PS1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_PS2, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_A_RX_PS3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_PS4, .value_a = 0x0033, .value_g = 0x0033, .flags = 0, }, */ - /* { .offset = B2063_A_RX_PS5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_A_RX_PS6, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_A_RX_MIX1, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2063_A_RX_MIX2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_MIX3, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */ - { .offset = B2063_A_RX_MIX4, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2063_A_RX_MIX5, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - { .offset = B2063_A_RX_MIX6, .value_a = 0x000f, .value_g = 0x000f, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_A_RX_MIX7, .value_a = 0x0044, .value_g = 0x0044, .flags = 0, }, */ - /* { .offset = B2063_A_RX_MIX8, .value_a = 0x0001, .value_g = 0x0001, .flags = 0, }, */ - /* { .offset = B2063_A_RX_PWRDET1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_SPARE1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_SPARE2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_A_RX_SPARE3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_RX_TIA_CTL1, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_RX_TIA_CTL2, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */ - { .offset = B2063_RX_TIA_CTL3, .value_a = 0x0077, .value_g = 0x0077, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_RX_TIA_CTL4, .value_a = 0x0058, .value_g = 0x0058, .flags = 0, }, */ - /* { .offset = B2063_RX_TIA_CTL5, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RX_TIA_CTL6, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL1, .value_a = 0x0074, .value_g = 0x0074, .flags = 0, }, */ - { .offset = B2063_RX_BB_CTL2, .value_a = 0x0004, .value_g = 0x0004, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_RX_BB_CTL3, .value_a = 0x00a2, .value_g = 0x00a2, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL4, .value_a = 0x00aa, .value_g = 0x00aa, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL5, .value_a = 0x0024, .value_g = 0x0024, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL6, .value_a = 0x00a9, .value_g = 0x00a9, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL7, .value_a = 0x0028, .value_g = 0x0028, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL8, .value_a = 0x0010, .value_g = 0x0010, .flags = 0, }, */ - /* { .offset = B2063_RX_BB_CTL9, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL1, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_IDAC_LO_RF_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_IDAC_LO_RF_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_IDAC_LO_BB_I, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_IDAC_LO_BB_Q, .value_a = 0x0088, .value_g = 0x0088, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL2, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL3, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL4, .value_a = 0x00b8, .value_g = 0x00b8, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL5, .value_a = 0x0080, .value_g = 0x0080, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL6, .value_a = 0x0038, .value_g = 0x0038, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL7, .value_a = 0x0078, .value_g = 0x0078, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL8, .value_a = 0x00c0, .value_g = 0x00c0, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL9, .value_a = 0x0003, .value_g = 0x0003, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL10, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL14, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_RF_CTL15, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_PA_CTL1, .value_a = 0x0000, .value_g = 0x0004, .flags = B206X_FLAG_A, }, - /* { .offset = B2063_PA_CTL2, .value_a = 0x000c, .value_g = 0x000c, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL3, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL4, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL5, .value_a = 0x0096, .value_g = 0x0096, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL6, .value_a = 0x0077, .value_g = 0x0077, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL7, .value_a = 0x005a, .value_g = 0x005a, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL8, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL9, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL10, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL11, .value_a = 0x0070, .value_g = 0x0070, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL12, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_PA_CTL13, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_BB_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_BB_CTL2, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */ - /* { .offset = B2063_TX_BB_CTL3, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2063_TX_BB_CTL4, .value_a = 0x000b, .value_g = 0x000b, .flags = 0, }, */ - /* { .offset = B2063_GPIO_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - { .offset = B2063_VREG_CTL1, .value_a = 0x0003, .value_g = 0x0003, .flags = B206X_FLAG_A | B206X_FLAG_G, }, - /* { .offset = B2063_AMUX_CTL1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_IQ_CALIB_GVAR, .value_a = 0x00b3, .value_g = 0x00b3, .flags = 0, }, */ - /* { .offset = B2063_IQ_CALIB_CTL1, .value_a = 0x0055, .value_g = 0x0055, .flags = 0, }, */ - /* { .offset = B2063_IQ_CALIB_CTL2, .value_a = 0x0030, .value_g = 0x0030, .flags = 0, }, */ - /* { .offset = B2063_TEMPSENSE_CTL1, .value_a = 0x0046, .value_g = 0x0046, .flags = 0, }, */ - /* { .offset = B2063_TEMPSENSE_CTL2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_RX_LOOPBACK1, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_TX_RX_LOOPBACK2, .value_a = 0x0000, .value_g = 0x0000, .flags = 0, }, */ - /* { .offset = B2063_EXT_TSSI_CTL1, .value_a = 0x0021, .value_g = 0x0021, .flags = 0, }, */ - /* { .offset = B2063_EXT_TSSI_CTL2, .value_a = 0x0023, .value_g = 0x0023, .flags = 0, }, */ - /* { .offset = B2063_AFE_CTL , .value_a = 0x0002, .value_g = 0x0002, .flags = 0, }, */ -}; - -void b2062_upload_init_table(struct b43_wldev *dev) -{ - const struct b206x_init_tab_entry *e; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(b2062_init_tab); i++) { - e = &b2062_init_tab[i]; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (!(e->flags & B206X_FLAG_G)) - continue; - b43_radio_write(dev, e->offset, e->value_g); - } else { - if (!(e->flags & B206X_FLAG_A)) - continue; - b43_radio_write(dev, e->offset, e->value_a); - } - } -} - -void b2063_upload_init_table(struct b43_wldev *dev) -{ - const struct b206x_init_tab_entry *e; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(b2063_init_tab); i++) { - e = &b2063_init_tab[i]; - if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) { - if (!(e->flags & B206X_FLAG_G)) - continue; - b43_radio_write(dev, e->offset, e->value_g); - } else { - if (!(e->flags & B206X_FLAG_A)) - continue; - b43_radio_write(dev, e->offset, e->value_a); - } - } -} - -u32 b43_lptab_read(struct b43_wldev *dev, u32 offset) -{ - u32 type, value; - - type = offset & B43_LPTAB_TYPEMASK; - offset &= ~B43_LPTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - switch (type) { - case B43_LPTAB_8BIT: - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - value = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF; - break; - case B43_LPTAB_16BIT: - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - value = b43_phy_read(dev, B43_LPPHY_TABLEDATALO); - break; - case B43_LPTAB_32BIT: - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - value = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI); - value <<= 16; - value |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO); - break; - default: - B43_WARN_ON(1); - value = 0; - } - - return value; -} - -void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, void *_data) -{ - u32 type; - u8 *data = _data; - unsigned int i; - - type = offset & B43_LPTAB_TYPEMASK; - offset &= ~B43_LPTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - - for (i = 0; i < nr_elements; i++) { - switch (type) { - case B43_LPTAB_8BIT: - *data = b43_phy_read(dev, B43_LPPHY_TABLEDATALO) & 0xFF; - data++; - break; - case B43_LPTAB_16BIT: - *((u16 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATALO); - data += 2; - break; - case B43_LPTAB_32BIT: - *((u32 *)data) = b43_phy_read(dev, B43_LPPHY_TABLEDATAHI); - *((u32 *)data) <<= 16; - *((u32 *)data) |= b43_phy_read(dev, B43_LPPHY_TABLEDATALO); - data += 4; - break; - default: - B43_WARN_ON(1); - } - } -} - -void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value) -{ - u32 type; - - type = offset & B43_LPTAB_TYPEMASK; - offset &= ~B43_LPTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - switch (type) { - case B43_LPTAB_8BIT: - B43_WARN_ON(value & ~0xFF); - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); - break; - case B43_LPTAB_16BIT: - B43_WARN_ON(value & ~0xFFFF); - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); - break; - case B43_LPTAB_32BIT: - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16); - b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); - break; - default: - B43_WARN_ON(1); - } -} - -void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, const void *_data) -{ - u32 type, value; - const u8 *data = _data; - unsigned int i; - - type = offset & B43_LPTAB_TYPEMASK; - offset &= ~B43_LPTAB_TYPEMASK; - B43_WARN_ON(offset > 0xFFFF); - - b43_phy_write(dev, B43_LPPHY_TABLE_ADDR, offset); - - for (i = 0; i < nr_elements; i++) { - switch (type) { - case B43_LPTAB_8BIT: - value = *data; - data++; - B43_WARN_ON(value & ~0xFF); - b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); - break; - case B43_LPTAB_16BIT: - value = *((u16 *)data); - data += 2; - B43_WARN_ON(value & ~0xFFFF); - b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); - break; - case B43_LPTAB_32BIT: - value = *((u32 *)data); - data += 4; - b43_phy_write(dev, B43_LPPHY_TABLEDATAHI, value >> 16); - b43_phy_write(dev, B43_LPPHY_TABLEDATALO, value); - break; - default: - B43_WARN_ON(1); - } - } -} - -static const u8 lpphy_min_sig_sq_table[] = { - 0xde, 0xdc, 0xda, 0xd8, 0xd6, 0xd4, 0xd2, 0xcf, 0xcd, - 0xca, 0xc7, 0xc4, 0xc1, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0x00, - 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, - 0xbe, 0xbe, 0xbe, 0xbe, 0xc1, 0xc4, 0xc7, 0xca, 0xcd, - 0xcf, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, -}; - -static const u16 lpphy_rev01_noise_scale_table[] = { - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa400, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, - 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0xa4a4, 0x00a4, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4c00, 0x2d36, - 0x0000, 0x0000, 0x4c00, 0x2d36, -}; - -static const u16 lpphy_rev2plus_noise_scale_table[] = { - 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, - 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, - 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x0000, - 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, - 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, - 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, 0x00a4, - 0x00a4, -}; - -static const u16 lpphy_crs_gain_nft_table[] = { - 0x0366, 0x036a, 0x036f, 0x0364, 0x0367, 0x036d, 0x0374, 0x037f, 0x036f, - 0x037b, 0x038a, 0x0378, 0x0367, 0x036d, 0x0375, 0x0381, 0x0374, 0x0381, - 0x0392, 0x03a9, 0x03c4, 0x03e1, 0x0001, 0x001f, 0x0040, 0x005e, 0x007f, - 0x009e, 0x00bd, 0x00dd, 0x00fd, 0x011d, 0x013d, -}; - -static const u16 lpphy_rev01_filter_control_table[] = { - 0xa0fc, 0x10fc, 0x10db, 0x20b7, 0xff93, 0x10bf, 0x109b, 0x2077, 0xff53, - 0x0127, -}; - -static const u32 lpphy_rev2plus_filter_control_table[] = { - 0x000141fc, 0x000021fc, 0x000021b7, 0x0000416f, 0x0001ff27, 0x0000217f, - 0x00002137, 0x000040ef, 0x0001fea7, 0x0000024f, -}; - -static const u32 lpphy_rev01_ps_control_table[] = { - 0x00010000, 0x000000a0, 0x00040000, 0x00000048, 0x08080101, 0x00000080, - 0x08080101, 0x00000040, 0x08080101, 0x000000c0, 0x08a81501, 0x000000c0, - 0x0fe8fd01, 0x000000c0, 0x08300105, 0x000000c0, 0x08080201, 0x000000c0, - 0x08280205, 0x000000c0, 0xe80802fe, 0x000000c7, 0x28080206, 0x000000c0, - 0x08080202, 0x000000c0, 0x0ba87602, 0x000000c0, 0x1068013d, 0x000000c0, - 0x10280105, 0x000000c0, 0x08880102, 0x000000c0, 0x08280106, 0x000000c0, - 0xe80801fd, 0x000000c7, 0xa8080115, 0x000000c0, -}; - -static const u32 lpphy_rev2plus_ps_control_table[] = { - 0x00e38e08, 0x00e08e38, 0x00000000, 0x00000000, 0x00000000, 0x00002080, - 0x00006180, 0x00003002, 0x00000040, 0x00002042, 0x00180047, 0x00080043, - 0x00000041, 0x000020c1, 0x00046006, 0x00042002, 0x00040000, 0x00002003, - 0x00180006, 0x00080002, -}; - -static const u8 lpphy_pll_fraction_table[] = { - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x80, - 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, -}; - -static const u16 lpphy_iqlo_cal_table[] = { - 0x0200, 0x0300, 0x0400, 0x0600, 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, - 0x1003, 0x1004, 0x1005, 0x1006, 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0200, 0x0300, 0x0400, 0x0600, - 0x0800, 0x0b00, 0x1000, 0x1001, 0x1002, 0x1003, 0x1004, 0x1005, 0x1006, - 0x1007, 0x1707, 0x2007, 0x2d07, 0x4007, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x4000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static const u16 lpphy_rev0_ofdm_cck_gain_table[] = { - 0x0001, 0x0001, 0x0001, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001, - 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075, - 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d, - 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d, -}; - -static const u16 lpphy_rev1_ofdm_cck_gain_table[] = { - 0x5000, 0x6000, 0x7000, 0x0001, 0x1001, 0x2001, 0x3001, 0x4001, 0x5001, - 0x6001, 0x7001, 0x7011, 0x7021, 0x2035, 0x2045, 0x2055, 0x2065, 0x2075, - 0x006d, 0x007d, 0x014d, 0x015d, 0x115d, 0x035d, 0x135d, 0x055d, 0x155d, - 0x0d5d, 0x1d5d, 0x2d5d, 0x555d, 0x655d, 0x755d, -}; - -static const u16 lpphy_gain_delta_table[] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static const u32 lpphy_tx_power_control_table[] = { - 0x00000050, 0x0000004f, 0x0000004e, 0x0000004d, 0x0000004c, 0x0000004b, - 0x0000004a, 0x00000049, 0x00000048, 0x00000047, 0x00000046, 0x00000045, - 0x00000044, 0x00000043, 0x00000042, 0x00000041, 0x00000040, 0x0000003f, - 0x0000003e, 0x0000003d, 0x0000003c, 0x0000003b, 0x0000003a, 0x00000039, - 0x00000038, 0x00000037, 0x00000036, 0x00000035, 0x00000034, 0x00000033, - 0x00000032, 0x00000031, 0x00000030, 0x0000002f, 0x0000002e, 0x0000002d, - 0x0000002c, 0x0000002b, 0x0000002a, 0x00000029, 0x00000028, 0x00000027, - 0x00000026, 0x00000025, 0x00000024, 0x00000023, 0x00000022, 0x00000021, - 0x00000020, 0x0000001f, 0x0000001e, 0x0000001d, 0x0000001c, 0x0000001b, - 0x0000001a, 0x00000019, 0x00000018, 0x00000017, 0x00000016, 0x00000015, - 0x00000014, 0x00000013, 0x00000012, 0x00000011, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x000075a0, 0x000075a0, 0x000075a1, 0x000075a1, 0x000075a2, 0x000075a2, - 0x000075a3, 0x000075a3, 0x000074b0, 0x000074b0, 0x000074b1, 0x000074b1, - 0x000074b2, 0x000074b2, 0x000074b3, 0x000074b3, 0x00006d20, 0x00006d20, - 0x00006d21, 0x00006d21, 0x00006d22, 0x00006d22, 0x00006d23, 0x00006d23, - 0x00004660, 0x00004660, 0x00004661, 0x00004661, 0x00004662, 0x00004662, - 0x00004663, 0x00004663, 0x00003e60, 0x00003e60, 0x00003e61, 0x00003e61, - 0x00003e62, 0x00003e62, 0x00003e63, 0x00003e63, 0x00003660, 0x00003660, - 0x00003661, 0x00003661, 0x00003662, 0x00003662, 0x00003663, 0x00003663, - 0x00002e60, 0x00002e60, 0x00002e61, 0x00002e61, 0x00002e62, 0x00002e62, - 0x00002e63, 0x00002e63, 0x00002660, 0x00002660, 0x00002661, 0x00002661, - 0x00002662, 0x00002662, 0x00002663, 0x00002663, 0x000025e0, 0x000025e0, - 0x000025e1, 0x000025e1, 0x000025e2, 0x000025e2, 0x000025e3, 0x000025e3, - 0x00001de0, 0x00001de0, 0x00001de1, 0x00001de1, 0x00001de2, 0x00001de2, - 0x00001de3, 0x00001de3, 0x00001d60, 0x00001d60, 0x00001d61, 0x00001d61, - 0x00001d62, 0x00001d62, 0x00001d63, 0x00001d63, 0x00001560, 0x00001560, - 0x00001561, 0x00001561, 0x00001562, 0x00001562, 0x00001563, 0x00001563, - 0x00000d60, 0x00000d60, 0x00000d61, 0x00000d61, 0x00000d62, 0x00000d62, - 0x00000d63, 0x00000d63, 0x00000ce0, 0x00000ce0, 0x00000ce1, 0x00000ce1, - 0x00000ce2, 0x00000ce2, 0x00000ce3, 0x00000ce3, 0x00000e10, 0x00000e10, - 0x00000e11, 0x00000e11, 0x00000e12, 0x00000e12, 0x00000e13, 0x00000e13, - 0x00000bf0, 0x00000bf0, 0x00000bf1, 0x00000bf1, 0x00000bf2, 0x00000bf2, - 0x00000bf3, 0x00000bf3, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x04200000, 0x04000000, - 0x04200000, 0x04000000, 0x04200000, 0x04000000, 0x000000ff, 0x000002fc, - 0x0000fa08, 0x00000305, 0x00000206, 0x00000304, 0x0000fb04, 0x0000fcff, - 0x000005fb, 0x0000fd01, 0x00000401, 0x00000006, 0x0000ff03, 0x000007fc, - 0x0000fc08, 0x00000203, 0x0000fffb, 0x00000600, 0x0000fa01, 0x0000fc03, - 0x0000fe06, 0x0000fe00, 0x00000102, 0x000007fd, 0x000004fb, 0x000006ff, - 0x000004fd, 0x0000fdfa, 0x000007fb, 0x0000fdfa, 0x0000fa06, 0x00000500, - 0x0000f902, 0x000007fa, 0x0000fafa, 0x00000500, 0x000007fa, 0x00000700, - 0x00000305, 0x000004ff, 0x00000801, 0x00000503, 0x000005f9, 0x00000404, - 0x0000fb08, 0x000005fd, 0x00000501, 0x00000405, 0x0000fb03, 0x000007fc, - 0x00000403, 0x00000303, 0x00000402, 0x0000faff, 0x0000fe05, 0x000005fd, - 0x0000fe01, 0x000007fa, 0x00000202, 0x00000504, 0x00000102, 0x000008fe, - 0x0000fa04, 0x0000fafc, 0x0000fe08, 0x000000f9, 0x000002fa, 0x000003fe, - 0x00000304, 0x000004f9, 0x00000100, 0x0000fd06, 0x000008fc, 0x00000701, - 0x00000504, 0x0000fdfe, 0x0000fdfc, 0x000003fe, 0x00000704, 0x000002fc, - 0x000004f9, 0x0000fdfd, 0x0000fa07, 0x00000205, 0x000003fd, 0x000005fb, - 0x000004f9, 0x00000804, 0x0000fc06, 0x0000fcf9, 0x00000100, 0x0000fe05, - 0x00000408, 0x0000fb02, 0x00000304, 0x000006fe, 0x000004fa, 0x00000305, - 0x000008fc, 0x00000102, 0x000001fd, 0x000004fc, 0x0000fe03, 0x00000701, - 0x000001fb, 0x000001f9, 0x00000206, 0x000006fd, 0x00000508, 0x00000700, - 0x00000304, 0x000005fe, 0x000005ff, 0x0000fa04, 0x00000303, 0x0000fefb, - 0x000007f9, 0x0000fefc, 0x000004fd, 0x000005fc, 0x0000fffd, 0x0000fc08, - 0x0000fbf9, 0x0000fd07, 0x000008fb, 0x0000fe02, 0x000006fb, 0x00000702, -}; - -static const u32 lpphy_gain_idx_table[] = { - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x10000001, 0x00000000, 0x20000082, 0x00000000, 0x40000104, 0x00000000, - 0x60004207, 0x00000001, 0x7000838a, 0x00000001, 0xd021050d, 0x00000001, - 0xe041c683, 0x00000001, 0x50828805, 0x00000000, 0x80e34288, 0x00000000, - 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, 0x12064711, 0x00000001, - 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010, 0x11630915, 0x00000011, - 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018, 0xf1e50da0, 0x00000018, - 0x22468e21, 0x00000019, 0x4286d023, 0x00000019, 0xa347d0a4, 0x00000019, - 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, 0x0408d329, 0x0000001a, - 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, 0x54aa152c, 0x0000001a, - 0x64ca55ad, 0x0000001a, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x10000001, 0x00000000, 0x20000082, 0x00000000, - 0x40000104, 0x00000000, 0x60004207, 0x00000001, 0x7000838a, 0x00000001, - 0xd021050d, 0x00000001, 0xe041c683, 0x00000001, 0x50828805, 0x00000000, - 0x80e34288, 0x00000000, 0xb144040b, 0x00000000, 0xe1a6058e, 0x00000000, - 0x12064711, 0x00000001, 0xb0a18612, 0x00000010, 0xe1024794, 0x00000010, - 0x11630915, 0x00000011, 0x31c3ca1b, 0x00000011, 0xc1848a9c, 0x00000018, - 0xf1e50da0, 0x00000018, 0x22468e21, 0x00000019, 0x4286d023, 0x00000019, - 0xa347d0a4, 0x00000019, 0xb36811a6, 0x00000019, 0xf3e89227, 0x00000019, - 0x0408d329, 0x0000001a, 0x244953aa, 0x0000001a, 0x346994ab, 0x0000001a, - 0x54aa152c, 0x0000001a, 0x64ca55ad, 0x0000001a, -}; - -static const u16 lpphy_aux_gain_idx_table[] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0001, 0x0002, 0x0004, 0x0016, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0002, 0x0004, 0x0016, -}; - -static const u32 lpphy_gain_value_table[] = { - 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004, - 0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a, - 0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006, - 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, - 0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, - 0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000009, 0x000000f1, - 0x00000000, 0x00000000, -}; - -static const u16 lpphy_gain_table[] = { - 0x0000, 0x0400, 0x0800, 0x0802, 0x0804, 0x0806, 0x0807, 0x0808, 0x080a, - 0x080b, 0x080c, 0x080e, 0x080f, 0x0810, 0x0812, 0x0813, 0x0814, 0x0816, - 0x0817, 0x081a, 0x081b, 0x081f, 0x0820, 0x0824, 0x0830, 0x0834, 0x0837, - 0x083b, 0x083f, 0x0840, 0x0844, 0x0857, 0x085b, 0x085f, 0x08d7, 0x08db, - 0x08df, 0x0957, 0x095b, 0x095f, 0x0b57, 0x0b5b, 0x0b5f, 0x0f5f, 0x135f, - 0x175f, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static const u32 lpphy_a0_gain_idx_table[] = { - 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065, - 0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f, - 0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca, - 0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, - 0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193, - 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a, - 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325, - 0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471, - 0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, - 0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd, - 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28, -}; - -static const u16 lpphy_a0_aux_gain_idx_table[] = { - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0002, 0x0014, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0002, 0x0014, -}; - -static const u32 lpphy_a0_gain_value_table[] = { - 0x00000008, 0x0000000e, 0x00000014, 0x0000001a, 0x000000fb, 0x00000004, - 0x00000008, 0x0000000d, 0x00000001, 0x00000004, 0x00000007, 0x0000000a, - 0x0000000d, 0x00000010, 0x00000012, 0x00000015, 0x00000000, 0x00000006, - 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000012, 0x00000000, - 0x00000000, 0x00000000, 0x00000018, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x0000001e, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000003, 0x00000006, 0x00000009, 0x0000000c, 0x0000000f, - 0x00000012, 0x00000015, 0x00000018, 0x0000001b, 0x0000001e, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x0000000f, 0x000000f7, - 0x00000000, 0x00000000, -}; - -static const u16 lpphy_a0_gain_table[] = { - 0x0000, 0x0002, 0x0004, 0x0006, 0x0007, 0x0008, 0x000a, 0x000b, 0x000c, - 0x000e, 0x000f, 0x0010, 0x0012, 0x0013, 0x0014, 0x0016, 0x0017, 0x001a, - 0x001b, 0x001f, 0x0020, 0x0024, 0x0030, 0x0034, 0x0037, 0x003b, 0x003f, - 0x0040, 0x0044, 0x0057, 0x005b, 0x005f, 0x00d7, 0x00db, 0x00df, 0x0157, - 0x015b, 0x015f, 0x0357, 0x035b, 0x035f, 0x075f, 0x0b5f, 0x0f5f, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, -}; - -static const u16 lpphy_sw_control_table[] = { - 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0128, - 0x0128, 0x0009, 0x0009, 0x0028, 0x0028, 0x0028, 0x0028, 0x0009, 0x0009, - 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0018, 0x0018, 0x0018, - 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0128, 0x0128, 0x0009, 0x0009, - 0x0028, 0x0028, 0x0028, 0x0028, 0x0128, 0x0128, 0x0009, 0x0009, 0x0028, - 0x0028, 0x0028, 0x0028, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, - 0x0009, 0x0009, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, - 0x0018, -}; - -static const u8 lpphy_hf_table[] = { - 0x4b, 0x36, 0x24, 0x18, 0x49, 0x34, 0x23, 0x17, 0x48, - 0x33, 0x23, 0x17, 0x48, 0x33, 0x23, 0x17, -}; - -static const u32 lpphy_papd_eps_table[] = { - 0x00000000, 0x00013ffc, 0x0001dff3, 0x0001bff0, 0x00023fe9, 0x00021fdf, - 0x00028fdf, 0x00033fd2, 0x00039fcb, 0x00043fc7, 0x0004efc2, 0x00055fb5, - 0x0005cfb0, 0x00063fa8, 0x00068fa3, 0x00071f98, 0x0007ef92, 0x00084f8b, - 0x0008df82, 0x00097f77, 0x0009df69, 0x000a3f62, 0x000adf57, 0x000b6f4c, - 0x000bff41, 0x000c9f39, 0x000cff30, 0x000dbf27, 0x000e4f1e, 0x000edf16, - 0x000f7f13, 0x00102f11, 0x00110f10, 0x0011df11, 0x0012ef15, 0x00143f1c, - 0x00158f27, 0x00172f35, 0x00193f47, 0x001baf5f, 0x001e6f7e, 0x0021cfa4, - 0x0025bfd2, 0x002a2008, 0x002fb047, 0x00360090, 0x003d40e0, 0x0045c135, - 0x004fb189, 0x005ae1d7, 0x0067221d, 0x0075025a, 0x007ff291, 0x007ff2bf, - 0x007ff2e3, 0x007ff2ff, 0x007ff315, 0x007ff329, 0x007ff33f, 0x007ff356, - 0x007ff36e, 0x007ff39c, 0x007ff441, 0x007ff506, -}; - -static const u32 lpphy_papd_mult_table[] = { - 0x001111e0, 0x00652051, 0x00606055, 0x005b005a, 0x00555060, 0x00511065, - 0x004c806b, 0x0047d072, 0x00444078, 0x00400080, 0x003ca087, 0x0039408f, - 0x0035e098, 0x0032e0a1, 0x003030aa, 0x002d80b4, 0x002ae0bf, 0x002880ca, - 0x002640d6, 0x002410e3, 0x002220f0, 0x002020ff, 0x001e510e, 0x001ca11e, - 0x001b012f, 0x00199140, 0x00182153, 0x0016c168, 0x0015817d, 0x00145193, - 0x001321ab, 0x001211c5, 0x001111e0, 0x001021fc, 0x000f321a, 0x000e523a, - 0x000d925c, 0x000cd27f, 0x000c12a5, 0x000b62cd, 0x000ac2f8, 0x000a2325, - 0x00099355, 0x00091387, 0x000883bd, 0x000813f5, 0x0007a432, 0x00073471, - 0x0006c4b5, 0x000664fc, 0x00061547, 0x0005b598, 0x000565ec, 0x00051646, - 0x0004d6a5, 0x0004870a, 0x00044775, 0x000407e6, 0x0003d85e, 0x000398dd, - 0x00036963, 0x000339f2, 0x00030a89, 0x0002db28, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev0_nopa_tx_gain_table[] = { - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev0_2ghz_tx_gain_table[] = { - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 10, .pad = 5, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 9, .pad = 5, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 71, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 69, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 67, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 9, .pad = 4, .dac = 0, .bb_mult = 58, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 8, .pad = 4, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 7, .pad = 4, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 67, }, - { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 7, .pad = 3, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 6, .pad = 3, .dac = 0, .bb_mult = 58, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 5, .pad = 3, .dac = 0, .bb_mult = 57, }, - { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 83, }, - { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 81, }, - { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 78, }, - { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 76, }, - { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 74, }, - { .gm = 4, .pga = 4, .pad = 2, .dac = 0, .bb_mult = 72, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev0_5ghz_tx_gain_table[] = { - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev1_nopa_tx_gain_table[] = { - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 152, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 147, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 143, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 139, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 135, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 131, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 128, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 124, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 121, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 117, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 114, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 111, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 107, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 104, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 101, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 99, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 96, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 93, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 90, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 88, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 85, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 83, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 81, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 78, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 76, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 74, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev1_2ghz_tx_gain_table[] = { - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 73, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 71, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 69, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 67, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 73, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 71, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 61, }, - { .gm = 4, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 72, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 70, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 68, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 66, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 64, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 62, }, - { .gm = 4, .pga = 10, .pad = 6, .dac = 0, .bb_mult = 60, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev1_5ghz_tx_gain_table[] = { - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 99, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 96, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 93, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 90, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 88, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 85, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 83, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 81, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 78, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 76, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 74, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 15, .dac = 0, .bb_mult = 55, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 15, .pad = 14, .dac = 0, .bb_mult = 55, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 13, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 72, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 12, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 73, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 11, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 71, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 15, .pad = 10, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 15, .pad = 9, .dac = 0, .bb_mult = 56, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 14, .pad = 9, .dac = 0, .bb_mult = 58, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 9, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 60, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 13, .pad = 8, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 8, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 12, .pad = 7, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 70, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 68, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 66, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 61, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 59, }, - { .gm = 7, .pga = 11, .pad = 7, .dac = 0, .bb_mult = 57, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 69, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 67, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 65, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 63, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 62, }, - { .gm = 7, .pga = 11, .pad = 6, .dac = 0, .bb_mult = 60, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev2_nopa_tx_gain_table[] = { - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 152, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 147, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 143, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 139, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 135, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 131, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 128, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 124, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 121, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 117, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 114, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 111, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 107, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 104, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 101, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 99, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 96, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 93, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 90, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 88, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 85, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 83, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 81, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 78, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 76, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 74, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 72, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 70, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 68, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 66, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 192, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 176, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 171, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 157, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 144, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 140, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 136, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 105, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 91, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 86, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 79, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 248, .pad = 64, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 241, .pad = 62, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 234, .pad = 60, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 227, .pad = 59, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 221, .pad = 57, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 215, .pad = 55, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 208, .pad = 54, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 203, .pad = 52, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 197, .pad = 51, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 191, .pad = 49, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 186, .pad = 48, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 181, .pad = 47, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 175, .pad = 45, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 170, .pad = 44, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 166, .pad = 43, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 161, .pad = 42, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 156, .pad = 40, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 152, .pad = 39, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 148, .pad = 38, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 143, .pad = 37, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 139, .pad = 36, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 135, .pad = 35, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 132, .pad = 34, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 128, .pad = 33, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 124, .pad = 32, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 124, .pad = 31, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 121, .pad = 31, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 121, .pad = 30, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 117, .pad = 30, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 117, .pad = 29, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 114, .pad = 29, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 111, .pad = 29, .dac = 0, .bb_mult = 64, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev2_2ghz_tx_gain_table[] = { - { .gm = 7, .pga = 99, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 96, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 93, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 90, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 88, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 85, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 83, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 81, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 78, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 76, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 74, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 72, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 70, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 68, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 66, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 64, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 62, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 62, .pad = 248, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 60, .pad = 248, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 60, .pad = 241, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 59, .pad = 241, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 59, .pad = 234, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 57, .pad = 234, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 57, .pad = 227, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 55, .pad = 227, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 55, .pad = 221, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 54, .pad = 221, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 54, .pad = 215, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 52, .pad = 215, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 52, .pad = 208, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 51, .pad = 208, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 51, .pad = 203, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 49, .pad = 203, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 49, .pad = 197, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 48, .pad = 197, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 48, .pad = 191, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 47, .pad = 191, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 47, .pad = 186, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 45, .pad = 186, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 45, .pad = 181, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 44, .pad = 181, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 44, .pad = 175, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 43, .pad = 175, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 43, .pad = 170, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 42, .pad = 170, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 42, .pad = 166, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 40, .pad = 166, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 40, .pad = 161, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 39, .pad = 161, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 39, .pad = 156, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 38, .pad = 156, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 38, .pad = 152, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 37, .pad = 152, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 37, .pad = 148, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 36, .pad = 148, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 36, .pad = 143, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 35, .pad = 143, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 35, .pad = 139, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 34, .pad = 139, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 34, .pad = 135, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 33, .pad = 135, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 33, .pad = 132, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 32, .pad = 132, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 32, .pad = 128, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 31, .pad = 128, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 31, .pad = 124, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 30, .pad = 124, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 30, .pad = 121, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 29, .pad = 121, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 29, .pad = 117, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 29, .pad = 114, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 28, .pad = 114, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 28, .pad = 111, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 27, .pad = 111, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 27, .pad = 108, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 26, .pad = 108, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 26, .pad = 104, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 25, .pad = 104, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 25, .pad = 102, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 25, .pad = 99, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 24, .pad = 99, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 24, .pad = 96, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 23, .pad = 96, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 23, .pad = 93, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 23, .pad = 90, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 22, .pad = 90, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 22, .pad = 88, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 21, .pad = 88, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 21, .pad = 85, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 21, .pad = 83, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 20, .pad = 83, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 20, .pad = 81, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 20, .pad = 78, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 19, .pad = 78, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 19, .pad = 76, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 19, .pad = 74, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 18, .pad = 74, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 18, .pad = 72, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 18, .pad = 70, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 17, .pad = 70, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 17, .pad = 68, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 17, .pad = 66, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 16, .pad = 66, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 16, .pad = 64, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 16, .pad = 62, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 62, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 60, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 15, .pad = 59, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 59, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 57, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 55, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 14, .pad = 54, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 54, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, }, - { .gm = 7, .pga = 13, .pad = 52, .dac = 0, .bb_mult = 64, }, -}; - -static struct lpphy_tx_gain_table_entry lpphy_rev2_5ghz_tx_gain_table[] = { - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 152, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 147, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 143, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 139, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 135, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 131, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 128, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 124, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 121, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 117, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 114, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 111, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 107, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 104, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 101, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 99, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 96, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 93, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 90, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 88, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 85, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 83, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 81, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 78, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 76, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 74, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 72, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 70, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 68, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 66, }, - { .gm = 255, .pga = 255, .pad = 255, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 248, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 241, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 234, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 227, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 221, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 215, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 208, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 203, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 197, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 191, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 186, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 181, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 175, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 170, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 166, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 161, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 156, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 152, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 148, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 143, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 139, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 135, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 132, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 128, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 124, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 121, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 117, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 114, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 111, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 108, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 104, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 102, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 99, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 96, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 93, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 90, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 88, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 85, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 83, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 81, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 78, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 76, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 74, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 72, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 70, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 68, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 66, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 64, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 255, .pad = 62, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 248, .pad = 62, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 248, .pad = 60, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 241, .pad = 60, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 241, .pad = 59, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 234, .pad = 59, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 234, .pad = 57, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 227, .pad = 57, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 227, .pad = 55, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 221, .pad = 55, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 221, .pad = 54, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 215, .pad = 54, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 215, .pad = 52, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 208, .pad = 52, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 208, .pad = 51, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 203, .pad = 51, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 203, .pad = 49, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 197, .pad = 49, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 197, .pad = 48, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 191, .pad = 48, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 191, .pad = 47, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 186, .pad = 47, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 186, .pad = 45, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 181, .pad = 45, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 181, .pad = 44, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 175, .pad = 44, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 175, .pad = 43, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 170, .pad = 43, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 170, .pad = 42, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 166, .pad = 42, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 166, .pad = 40, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 161, .pad = 40, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 161, .pad = 39, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 156, .pad = 39, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 156, .pad = 38, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 152, .pad = 38, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 152, .pad = 37, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 148, .pad = 37, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 148, .pad = 36, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 143, .pad = 36, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 143, .pad = 35, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 139, .pad = 35, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 139, .pad = 34, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 135, .pad = 34, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 135, .pad = 33, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 132, .pad = 33, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 132, .pad = 32, .dac = 0, .bb_mult = 64, }, - { .gm = 255, .pga = 128, .pad = 32, .dac = 0, .bb_mult = 64, }, -}; - -void lpphy_rev0_1_table_init(struct b43_wldev *dev) -{ - B43_WARN_ON(dev->phy.rev >= 2); - - b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0), - ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0), - ARRAY_SIZE(lpphy_rev01_noise_scale_table), lpphy_rev01_noise_scale_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0), - ARRAY_SIZE(lpphy_crs_gain_nft_table), lpphy_crs_gain_nft_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(8, 0), - ARRAY_SIZE(lpphy_rev01_filter_control_table), lpphy_rev01_filter_control_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0), - ARRAY_SIZE(lpphy_rev01_ps_control_table), lpphy_rev01_ps_control_table); - b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0), - ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0), - ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table); - if (dev->phy.rev == 0) { - b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), - ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), - ARRAY_SIZE(lpphy_rev0_ofdm_cck_gain_table), lpphy_rev0_ofdm_cck_gain_table); - } else { - b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), - ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), - ARRAY_SIZE(lpphy_rev1_ofdm_cck_gain_table), lpphy_rev1_ofdm_cck_gain_table); -} - b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0), - ARRAY_SIZE(lpphy_gain_delta_table), lpphy_gain_delta_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0), - ARRAY_SIZE(lpphy_tx_power_control_table), lpphy_tx_power_control_table); -} - -void lpphy_rev2plus_table_init(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - int i; - - B43_WARN_ON(dev->phy.rev < 2); - - for (i = 0; i < 704; i++) - b43_lptab_write(dev, B43_LPTAB32(7, i), 0); - - b43_lptab_write_bulk(dev, B43_LPTAB8(2, 0), - ARRAY_SIZE(lpphy_min_sig_sq_table), lpphy_min_sig_sq_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(1, 0), - ARRAY_SIZE(lpphy_rev2plus_noise_scale_table), lpphy_rev2plus_noise_scale_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(11, 0), - ARRAY_SIZE(lpphy_rev2plus_filter_control_table), lpphy_rev2plus_filter_control_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(12, 0), - ARRAY_SIZE(lpphy_rev2plus_ps_control_table), lpphy_rev2plus_ps_control_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0), - ARRAY_SIZE(lpphy_gain_idx_table), lpphy_gain_idx_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0), - ARRAY_SIZE(lpphy_aux_gain_idx_table), lpphy_aux_gain_idx_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(15, 0), - ARRAY_SIZE(lpphy_sw_control_table), lpphy_sw_control_table); - b43_lptab_write_bulk(dev, B43_LPTAB8(16, 0), - ARRAY_SIZE(lpphy_hf_table), lpphy_hf_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0), - ARRAY_SIZE(lpphy_gain_value_table), lpphy_gain_value_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0), - ARRAY_SIZE(lpphy_gain_table), lpphy_gain_table); - b43_lptab_write_bulk(dev, B43_LPTAB8(6, 0), - ARRAY_SIZE(lpphy_pll_fraction_table), lpphy_pll_fraction_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(0, 0), - ARRAY_SIZE(lpphy_iqlo_cal_table), lpphy_iqlo_cal_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(9, 0), - ARRAY_SIZE(lpphy_papd_eps_table), lpphy_papd_eps_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0), - ARRAY_SIZE(lpphy_papd_mult_table), lpphy_papd_mult_table); - - if ((bus->chip_id == 0x4325) && (bus->chip_rev == 0)) { - b43_lptab_write_bulk(dev, B43_LPTAB32(13, 0), - ARRAY_SIZE(lpphy_a0_gain_idx_table), lpphy_a0_gain_idx_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(14, 0), - ARRAY_SIZE(lpphy_a0_aux_gain_idx_table), lpphy_a0_aux_gain_idx_table); - b43_lptab_write_bulk(dev, B43_LPTAB32(17, 0), - ARRAY_SIZE(lpphy_a0_gain_value_table), lpphy_a0_gain_value_table); - b43_lptab_write_bulk(dev, B43_LPTAB16(18, 0), - ARRAY_SIZE(lpphy_a0_gain_table), lpphy_a0_gain_table); - } -} - -static void lpphy_rev0_1_write_gain_table(struct b43_wldev *dev, int offset, - struct lpphy_tx_gain_table_entry data) -{ - u32 tmp; - - B43_WARN_ON(dev->phy.rev >= 2); - - tmp = data.pad << 11; - tmp |= data.pga << 7; - tmp |= data.gm << 4; - tmp |= data.dac; - b43_lptab_write(dev, B43_LPTAB32(10, 0xC0 + offset), tmp); - tmp = data.bb_mult << 20; - b43_lptab_write(dev, B43_LPTAB32(10, 0x140 + offset), tmp); -} - -static void lpphy_rev2plus_write_gain_table(struct b43_wldev *dev, int offset, - struct lpphy_tx_gain_table_entry data) -{ - u32 tmp; - - B43_WARN_ON(dev->phy.rev < 2); - - tmp = data.pad << 16; - tmp |= data.pga << 8; - tmp |= data.gm; - if (dev->phy.rev >= 3) { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) - tmp |= 0x10 << 24; - else - tmp |= 0x70 << 24; - } else { - if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) - tmp |= 0x14 << 24; - else - tmp |= 0x7F << 24; - } - b43_lptab_write(dev, B43_LPTAB32(7, 0xC0 + offset), tmp); - tmp = data.bb_mult << 20; - tmp |= data.dac << 28; - b43_lptab_write(dev, B43_LPTAB32(7, 0x140 + offset), tmp); -} - -void lpphy_write_gain_table(struct b43_wldev *dev, int offset, - struct lpphy_tx_gain_table_entry data) -{ - if (dev->phy.rev >= 2) - lpphy_rev2plus_write_gain_table(dev, offset, data); - else - lpphy_rev0_1_write_gain_table(dev, offset, data); -} - -void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count, - struct lpphy_tx_gain_table_entry *table) -{ - int i; - - for (i = offset; i < count; i++) - lpphy_write_gain_table(dev, i, table[i]); -} - -void lpphy_init_tx_gain_table(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - - switch (dev->phy.rev) { - case 0: - if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) || - (bus->sprom.boardflags_lo & B43_BFL_HGPA)) - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev0_nopa_tx_gain_table); - else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev0_2ghz_tx_gain_table); - else - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev0_5ghz_tx_gain_table); - break; - case 1: - if ((bus->sprom.boardflags_hi & B43_BFH_NOPA) || - (bus->sprom.boardflags_lo & B43_BFL_HGPA)) - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev1_nopa_tx_gain_table); - else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev1_2ghz_tx_gain_table); - else - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev1_5ghz_tx_gain_table); - break; - default: - if (bus->sprom.boardflags_hi & B43_BFH_NOPA) - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev2_nopa_tx_gain_table); - else if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev2_2ghz_tx_gain_table); - else - lpphy_write_gain_table_bulk(dev, 0, 128, - lpphy_rev2_5ghz_tx_gain_table); - } -} diff --git a/drivers/net/wireless/b43/tables_lpphy.h b/drivers/net/wireless/b43/tables_lpphy.h deleted file mode 100644 index 84f1d265f657..000000000000 --- a/drivers/net/wireless/b43/tables_lpphy.h +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef B43_TABLES_LPPHY_H_ -#define B43_TABLES_LPPHY_H_ - - -#define B43_LPTAB_TYPEMASK 0xF0000000 -#define B43_LPTAB_8BIT 0x10000000 -#define B43_LPTAB_16BIT 0x20000000 -#define B43_LPTAB_32BIT 0x30000000 -#define B43_LPTAB8(table, offset) (((table) << 10) | (offset) | B43_LPTAB_8BIT) -#define B43_LPTAB16(table, offset) (((table) << 10) | (offset) | B43_LPTAB_16BIT) -#define B43_LPTAB32(table, offset) (((table) << 10) | (offset) | B43_LPTAB_32BIT) - -/* Table definitions */ -#define B43_LPTAB_TXPWR_R2PLUS B43_LPTAB32(0x07, 0) /* TX power lookup table (rev >= 2) */ -#define B43_LPTAB_TXPWR_R0_1 B43_LPTAB32(0xA0, 0) /* TX power lookup table (rev < 2) */ - -u32 b43_lptab_read(struct b43_wldev *dev, u32 offset); -void b43_lptab_write(struct b43_wldev *dev, u32 offset, u32 value); - -/* Bulk table access. Note that these functions return the bulk data in - * host endianness! The returned data is _not_ a bytearray, but an array - * consisting of nr_elements of the data type. */ -void b43_lptab_read_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, void *data); -void b43_lptab_write_bulk(struct b43_wldev *dev, u32 offset, - unsigned int nr_elements, const void *data); - -void b2062_upload_init_table(struct b43_wldev *dev); -void b2063_upload_init_table(struct b43_wldev *dev); - -struct lpphy_tx_gain_table_entry { - u8 gm, pga, pad, dac, bb_mult; -}; - -void lpphy_write_gain_table(struct b43_wldev *dev, int offset, - struct lpphy_tx_gain_table_entry data); -void lpphy_write_gain_table_bulk(struct b43_wldev *dev, int offset, int count, - struct lpphy_tx_gain_table_entry *table); - -void lpphy_rev0_1_table_init(struct b43_wldev *dev); -void lpphy_rev2plus_table_init(struct b43_wldev *dev); -void lpphy_init_tx_gain_table(struct b43_wldev *dev); - -#endif /* B43_TABLES_LPPHY_H_ */ diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c deleted file mode 100644 index 4e2336315545..000000000000 --- a/drivers/net/wireless/b43/tables_nphy.c +++ /dev/null @@ -1,2476 +0,0 @@ -/* - - Broadcom B43 wireless driver - IEEE 802.11n PHY and radio device data tables - - Copyright (c) 2008 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "tables_nphy.h" -#include "phy_common.h" -#include "phy_n.h" - - -struct b2055_inittab_entry { - /* Value to write if we use the 5GHz band. */ - u16 ghz5; - /* Value to write if we use the 2.4GHz band. */ - u16 ghz2; - /* Flags */ - u8 flags; -#define B2055_INITTAB_ENTRY_OK 0x01 -#define B2055_INITTAB_UPLOAD 0x02 -}; -#define UPLOAD .flags = B2055_INITTAB_ENTRY_OK | B2055_INITTAB_UPLOAD -#define NOUPLOAD .flags = B2055_INITTAB_ENTRY_OK - -static const struct b2055_inittab_entry b2055_inittab [] = { - [B2055_SP_PINPD] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, - [B2055_C1_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, }, - [B2055_C2_SP_RSSI] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_SP_PDMISC] = { .ghz5 = 0x0027, .ghz2 = 0x0027, NOUPLOAD, }, - [B2055_C1_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, }, - [B2055_C1_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, - [B2055_C2_SP_RXGC1] = { .ghz5 = 0x007F, .ghz2 = 0x007F, UPLOAD, }, - [B2055_C2_SP_RXGC2] = { .ghz5 = 0x0007, .ghz2 = 0x0007, UPLOAD, }, - [B2055_C1_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C2_SP_LPFBWSEL] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C1_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, }, - [B2055_C1_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, - [B2055_C2_SP_TXGC1] = { .ghz5 = 0x004F, .ghz2 = 0x004F, UPLOAD, }, - [B2055_C2_SP_TXGC2] = { .ghz5 = 0x0005, .ghz2 = 0x0005, UPLOAD, }, - [B2055_MASTER1] = { .ghz5 = 0x00D0, .ghz2 = 0x00D0, NOUPLOAD, }, - [B2055_MASTER2] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, - [B2055_PD_LGEN] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PD_PLLTS] = { .ghz5 = 0x0040, .ghz2 = 0x0040, NOUPLOAD, }, - [B2055_C1_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_LGBUF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_TX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_RXTX] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_PD_RSSIMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PWRDET_LGEN] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, - [B2055_C1_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_C1_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, - [B2055_C2_PWRDET_LGBUF] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_C2_PWRDET_RXTX] = { .ghz5 = 0x00C0, .ghz2 = 0x00C0, NOUPLOAD, }, - [B2055_RRCCAL_CS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_RRCCAL_NOPTSEL] = { .ghz5 = 0x002C, .ghz2 = 0x002C, NOUPLOAD, }, - [B2055_CAL_MISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_COUT] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_COUT2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_CVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_RVARCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_LPOCTL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_TS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_RCCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_CAL_RCALRTS] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PADDRV] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, - [B2055_XOCTL1] = { .ghz5 = 0x0038, .ghz2 = 0x0038, NOUPLOAD, }, - [B2055_XOCTL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_XOREGUL] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, - [B2055_XOMISC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PLL_LFC1] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_PLL_CALVTH] = { .ghz5 = 0x0087, .ghz2 = 0x0087, NOUPLOAD, }, - [B2055_PLL_LFC2] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, }, - [B2055_PLL_REF] = { .ghz5 = 0x0070, .ghz2 = 0x0070, NOUPLOAD, }, - [B2055_PLL_LFR1] = { .ghz5 = 0x0011, .ghz2 = 0x0011, NOUPLOAD, }, - [B2055_PLL_PFDCP] = { .ghz5 = 0x0018, .ghz2 = 0x0018, UPLOAD, }, - [B2055_PLL_IDAC_CPOPAMP] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_PLL_CPREG] = { .ghz5 = 0x0004, .ghz2 = 0x0004, UPLOAD, }, - [B2055_PLL_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_RF_PLLMOD0] = { .ghz5 = 0x009E, .ghz2 = 0x009E, NOUPLOAD, }, - [B2055_RF_PLLMOD1] = { .ghz5 = 0x0009, .ghz2 = 0x0009, NOUPLOAD, }, - [B2055_RF_MMDIDAC1] = { .ghz5 = 0x00C8, .ghz2 = 0x00C8, UPLOAD, }, - [B2055_RF_MMDIDAC0] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_RF_MMDSP] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL3] = { .ghz5 = 0x0001, .ghz2 = 0x0001, NOUPLOAD, }, - [B2055_VCO_CAL4] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, - [B2055_VCO_CAL5] = { .ghz5 = 0x0096, .ghz2 = 0x0096, NOUPLOAD, }, - [B2055_VCO_CAL6] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, }, - [B2055_VCO_CAL7] = { .ghz5 = 0x003E, .ghz2 = 0x003E, NOUPLOAD, }, - [B2055_VCO_CAL8] = { .ghz5 = 0x0013, .ghz2 = 0x0013, NOUPLOAD, }, - [B2055_VCO_CAL9] = { .ghz5 = 0x0002, .ghz2 = 0x0002, NOUPLOAD, }, - [B2055_VCO_CAL10] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_VCO_CAL11] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_VCO_CAL12] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL13] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL14] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL15] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_CAL16] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_VCO_KVCO] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_VCO_CAPTAIL] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_VCO_IDACVCO] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_VCO_REG] = { .ghz5 = 0x0084, .ghz2 = 0x0084, UPLOAD, }, - [B2055_PLL_RFVTH] = { .ghz5 = 0x00C3, .ghz2 = 0x00C3, NOUPLOAD, }, - [B2055_LGBUF_CENBUF] = { .ghz5 = 0x008F, .ghz2 = 0x008F, NOUPLOAD, }, - [B2055_LGEN_TUNE1] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_LGEN_TUNE2] = { .ghz5 = 0x00FF, .ghz2 = 0x00FF, NOUPLOAD, }, - [B2055_LGEN_IDAC1] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_LGEN_IDAC2] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_LGEN_BIASC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_LGEN_BIASIDAC] = { .ghz5 = 0x00CC, .ghz2 = 0x00CC, NOUPLOAD, }, - [B2055_LGEN_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_LGEN_DIV] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, - [B2055_LGEN_SPARE2] = { .ghz5 = 0x0080, .ghz2 = 0x0080, NOUPLOAD, }, - [B2055_C1_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, }, - [B2055_C1_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, }, - [B2055_C1_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, }, - [B2055_C1_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, }, - [B2055_C1_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C1_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, - [B2055_C1_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C1_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, }, - [B2055_C1_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C1_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C1_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C1_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, }, - [B2055_C1_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, }, - [B2055_C1_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C1_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C1_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C1_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C1_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C1_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, - [B2055_C1_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, }, - [B2055_C1_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C1_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, }, - [B2055_C1_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, }, - [B2055_C1_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C1_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C1_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C1_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C1_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C1_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C1_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, - [B2055_C1_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C1_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, }, - [B2055_C1_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, }, - [B2055_C1_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_LGBUF_ATUNE] = { .ghz5 = 0x00F8, .ghz2 = 0x00F8, NOUPLOAD, }, - [B2055_C2_LGBUF_GTUNE] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_LGBUF_DIV] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_LGBUF_AIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0008, UPLOAD, }, - [B2055_C2_LGBUF_GIDAC] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_LGBUF_IDACFO] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_LGBUF_SPARE] = { .ghz5 = 0x0001, .ghz2 = 0x0001, UPLOAD, }, - [B2055_C2_RX_RFSPC1] = { .ghz5 = 0x008A, .ghz2 = 0x008A, NOUPLOAD, }, - [B2055_C2_RX_RFR1] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C2_RX_RFR2] = { .ghz5 = 0x0083, .ghz2 = 0x0083, NOUPLOAD, }, - [B2055_C2_RX_RFRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C2_RX_BB_BLCMP] = { .ghz5 = 0x00A0, .ghz2 = 0x00A0, NOUPLOAD, }, - [B2055_C2_RX_BB_LPF] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C2_RX_BB_MIDACHP] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C2_RX_BB_VGA1IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_VGA2IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_VGA3IDAC] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_BUFOCTL] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_RX_BB_RCCALCTL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C2_RX_BB_RSSICTL1] = { .ghz5 = 0x006A, .ghz2 = 0x006A, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL2] = { .ghz5 = 0x00AB, .ghz2 = 0x00AB, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL3] = { .ghz5 = 0x0013, .ghz2 = 0x0013, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL4] = { .ghz5 = 0x00C1, .ghz2 = 0x00C1, UPLOAD, }, - [B2055_C2_RX_BB_RSSICTL5] = { .ghz5 = 0x00AA, .ghz2 = 0x00AA, UPLOAD, }, - [B2055_C2_RX_BB_REG] = { .ghz5 = 0x0087, .ghz2 = 0x0087, UPLOAD, }, - [B2055_C2_RX_BB_SPARE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_RX_TXBBRCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C2_TX_RF_SPGA] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C2_TX_RF_SPAD] = { .ghz5 = 0x0007, .ghz2 = 0x0007, NOUPLOAD, }, - [B2055_C2_TX_RF_CNTPGA1] = { .ghz5 = 0x0015, .ghz2 = 0x0015, NOUPLOAD, }, - [B2055_C2_TX_RF_CNTPAD1] = { .ghz5 = 0x0055, .ghz2 = 0x0055, NOUPLOAD, }, - [B2055_C2_TX_RF_PGAIDAC] = { .ghz5 = 0x0097, .ghz2 = 0x0097, UPLOAD, }, - [B2055_C2_TX_PGAPADTN] = { .ghz5 = 0x0008, .ghz2 = 0x0008, NOUPLOAD, }, - [B2055_C2_TX_PADIDAC1] = { .ghz5 = 0x0014, .ghz2 = 0x0014, UPLOAD, }, - [B2055_C2_TX_PADIDAC2] = { .ghz5 = 0x0033, .ghz2 = 0x0033, NOUPLOAD, }, - [B2055_C2_TX_MXBGTRIM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [B2055_C2_TX_RF_RCAL] = { .ghz5 = 0x0006, .ghz2 = 0x0006, NOUPLOAD, }, - [B2055_C2_TX_RF_PADTSSI1] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C2_TX_RF_PADTSSI2] = { .ghz5 = 0x000A, .ghz2 = 0x000A, NOUPLOAD, }, - [B2055_C2_TX_RF_SPARE] = { .ghz5 = 0x0003, .ghz2 = 0x0003, UPLOAD, }, - [B2055_C2_TX_RF_IQCAL1] = { .ghz5 = 0x002A, .ghz2 = 0x002A, NOUPLOAD, }, - [B2055_C2_TX_RF_IQCAL2] = { .ghz5 = 0x00A4, .ghz2 = 0x00A4, NOUPLOAD, }, - [B2055_C2_TXBB_RCCAL] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C2_TXBB_LPF1] = { .ghz5 = 0x0028, .ghz2 = 0x0028, NOUPLOAD, }, - [B2055_C2_TX_VOSCNCL] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_TX_LPF_MXGMIDAC] = { .ghz5 = 0x004A, .ghz2 = 0x004A, NOUPLOAD, }, - [B2055_C2_TX_BB_MXGM] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_PRG_GCHP21] = { .ghz5 = 0x0071, .ghz2 = 0x0071, NOUPLOAD, }, - [B2055_PRG_GCHP22] = { .ghz5 = 0x0072, .ghz2 = 0x0072, NOUPLOAD, }, - [B2055_PRG_GCHP23] = { .ghz5 = 0x0073, .ghz2 = 0x0073, NOUPLOAD, }, - [B2055_PRG_GCHP24] = { .ghz5 = 0x0074, .ghz2 = 0x0074, NOUPLOAD, }, - [B2055_PRG_GCHP25] = { .ghz5 = 0x0075, .ghz2 = 0x0075, NOUPLOAD, }, - [B2055_PRG_GCHP26] = { .ghz5 = 0x0076, .ghz2 = 0x0076, NOUPLOAD, }, - [B2055_PRG_GCHP27] = { .ghz5 = 0x0077, .ghz2 = 0x0077, NOUPLOAD, }, - [B2055_PRG_GCHP28] = { .ghz5 = 0x0078, .ghz2 = 0x0078, NOUPLOAD, }, - [B2055_PRG_GCHP29] = { .ghz5 = 0x0079, .ghz2 = 0x0079, NOUPLOAD, }, - [B2055_PRG_GCHP30] = { .ghz5 = 0x007A, .ghz2 = 0x007A, NOUPLOAD, }, - [0xC7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xC8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xC9] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCE] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xCF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD1] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C1_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [0xD3] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD4] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD5] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C1_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD7] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xD8] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_LNA_GAINBST] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDA] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDB] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDC] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xDD] = { .ghz5 = 0x0018, .ghz2 = 0x0018, NOUPLOAD, }, - [B2055_C2_B0NB_RSSIVCM] = { .ghz5 = 0x0088, .ghz2 = 0x0088, NOUPLOAD, }, - [0xDF] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xE0] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [0xE1] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, - [B2055_C2_GENSPARE2] = { .ghz5 = 0x0000, .ghz2 = 0x0000, NOUPLOAD, }, -}; - - -void b2055_upload_inittab(struct b43_wldev *dev, - bool ghz5, bool ignore_uploadflag) -{ - const struct b2055_inittab_entry *e; - unsigned int i; - u16 value; - - for (i = 0; i < ARRAY_SIZE(b2055_inittab); i++) { - e = &(b2055_inittab[i]); - if (!(e->flags & B2055_INITTAB_ENTRY_OK)) - continue; - if ((e->flags & B2055_INITTAB_UPLOAD) || ignore_uploadflag) { - if (ghz5) - value = e->ghz5; - else - value = e->ghz2; - b43_radio_write16(dev, i, value); - } - } -} - - -#define RADIOREGS(r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, \ - r12, r13, r14, r15, r16, r17, r18, r19, r20, r21) \ - .radio_pll_ref = r0, \ - .radio_rf_pllmod0 = r1, \ - .radio_rf_pllmod1 = r2, \ - .radio_vco_captail = r3, \ - .radio_vco_cal1 = r4, \ - .radio_vco_cal2 = r5, \ - .radio_pll_lfc1 = r6, \ - .radio_pll_lfr1 = r7, \ - .radio_pll_lfc2 = r8, \ - .radio_lgbuf_cenbuf = r9, \ - .radio_lgen_tune1 = r10, \ - .radio_lgen_tune2 = r11, \ - .radio_c1_lgbuf_atune = r12, \ - .radio_c1_lgbuf_gtune = r13, \ - .radio_c1_rx_rfr1 = r14, \ - .radio_c1_tx_pgapadtn = r15, \ - .radio_c1_tx_mxbgtrim = r16, \ - .radio_c2_lgbuf_atune = r17, \ - .radio_c2_lgbuf_gtune = r18, \ - .radio_c2_rx_rfr1 = r19, \ - .radio_c2_tx_pgapadtn = r20, \ - .radio_c2_tx_mxbgtrim = r21 - -#define PHYREGS(r0, r1, r2, r3, r4, r5) \ - .phy_bw1a = r0, \ - .phy_bw2 = r1, \ - .phy_bw3 = r2, \ - .phy_bw4 = r3, \ - .phy_bw5 = r4, \ - .phy_bw6 = r5 - -static const struct b43_nphy_channeltab_entry b43_nphy_channeltab[] = { - { .channel = 184, - .freq = 4920, /* MHz */ - .unk2 = 3280, - RADIOREGS(0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB407, 0xB007, 0xAC07, 0x1402, 0x1502, 0x1602), - }, - { .channel = 186, - .freq = 4930, /* MHz */ - .unk2 = 3287, - RADIOREGS(0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xB807, 0xB407, 0xB007, 0x1302, 0x1402, 0x1502), - }, - { .channel = 188, - .freq = 4940, /* MHz */ - .unk2 = 3293, - RADIOREGS(0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xBC07, 0xB807, 0xB407, 0x1202, 0x1302, 0x1402), - }, - { .channel = 190, - .freq = 4950, /* MHz */ - .unk2 = 3300, - RADIOREGS(0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC007, 0xBC07, 0xB807, 0x1102, 0x1202, 0x1302), - }, - { .channel = 192, - .freq = 4960, /* MHz */ - .unk2 = 3307, - RADIOREGS(0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC407, 0xC007, 0xBC07, 0x0F02, 0x1102, 0x1202), - }, - { .channel = 194, - .freq = 4970, /* MHz */ - .unk2 = 3313, - RADIOREGS(0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xC807, 0xC407, 0xC007, 0x0E02, 0x0F02, 0x1102), - }, - { .channel = 196, - .freq = 4980, /* MHz */ - .unk2 = 3320, - RADIOREGS(0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xCC07, 0xC807, 0xC407, 0x0D02, 0x0E02, 0x0F02), - }, - { .channel = 198, - .freq = 4990, /* MHz */ - .unk2 = 3327, - RADIOREGS(0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD007, 0xCC07, 0xC807, 0x0C02, 0x0D02, 0x0E02), - }, - { .channel = 200, - .freq = 5000, /* MHz */ - .unk2 = 3333, - RADIOREGS(0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD407, 0xD007, 0xCC07, 0x0B02, 0x0C02, 0x0D02), - }, - { .channel = 202, - .freq = 5010, /* MHz */ - .unk2 = 3340, - RADIOREGS(0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xD807, 0xD407, 0xD007, 0x0A02, 0x0B02, 0x0C02), - }, - { .channel = 204, - .freq = 5020, /* MHz */ - .unk2 = 3347, - RADIOREGS(0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xDC07, 0xD807, 0xD407, 0x0902, 0x0A02, 0x0B02), - }, - { .channel = 206, - .freq = 5030, /* MHz */ - .unk2 = 3353, - RADIOREGS(0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE007, 0xDC07, 0xD807, 0x0802, 0x0902, 0x0A02), - }, - { .channel = 208, - .freq = 5040, /* MHz */ - .unk2 = 3360, - RADIOREGS(0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE407, 0xE007, 0xDC07, 0x0702, 0x0802, 0x0902), - }, - { .channel = 210, - .freq = 5050, /* MHz */ - .unk2 = 3367, - RADIOREGS(0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, - 0x8F, 0xFF, 0x00, 0x0F, 0x0F, 0x8F), - PHYREGS(0xE807, 0xE407, 0xE007, 0x0602, 0x0702, 0x0802), - }, - { .channel = 212, - .freq = 5060, /* MHz */ - .unk2 = 3373, - RADIOREGS(0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, - 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xEC07, 0xE807, 0xE407, 0x0502, 0x0602, 0x0702), - }, - { .channel = 214, - .freq = 5070, /* MHz */ - .unk2 = 3380, - RADIOREGS(0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A, - 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, - 0x8E, 0xFF, 0x00, 0x0E, 0x0F, 0x8E), - PHYREGS(0xF007, 0xEC07, 0xE807, 0x0402, 0x0502, 0x0602), - }, - { .channel = 216, - .freq = 5080, /* MHz */ - .unk2 = 3387, - RADIOREGS(0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, - 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF407, 0xF007, 0xEC07, 0x0302, 0x0402, 0x0502), - }, - { .channel = 218, - .freq = 5090, /* MHz */ - .unk2 = 3393, - RADIOREGS(0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, - 0x8D, 0xEE, 0x00, 0x0E, 0x0F, 0x8D), - PHYREGS(0xF807, 0xF407, 0xF007, 0x0202, 0x0302, 0x0402), - }, - { .channel = 220, - .freq = 5100, /* MHz */ - .unk2 = 3400, - RADIOREGS(0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, - 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0xFC07, 0xF807, 0xF407, 0x0102, 0x0202, 0x0302), - }, - { .channel = 222, - .freq = 5110, /* MHz */ - .unk2 = 3407, - RADIOREGS(0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A, - 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, - 0x8D, 0xEE, 0x00, 0x0D, 0x0F, 0x8D), - PHYREGS(0x0008, 0xFC07, 0xF807, 0x0002, 0x0102, 0x0202), - }, - { .channel = 224, - .freq = 5120, /* MHz */ - .unk2 = 3413, - RADIOREGS(0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A, - 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, - 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0408, 0x0008, 0xFC07, 0xFF01, 0x0002, 0x0102), - }, - { .channel = 226, - .freq = 5130, /* MHz */ - .unk2 = 3420, - RADIOREGS(0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A, - 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, - 0x8C, 0xDD, 0x00, 0x0D, 0x0F, 0x8C), - PHYREGS(0x0808, 0x0408, 0x0008, 0xFE01, 0xFF01, 0x0002), - }, - { .channel = 228, - .freq = 5140, /* MHz */ - .unk2 = 3427, - RADIOREGS(0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A, - 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, - 0x8B, 0xDD, 0x00, 0x0C, 0x0E, 0x8B), - PHYREGS(0x0C08, 0x0808, 0x0408, 0xFD01, 0xFE01, 0xFF01), - }, - { .channel = 32, - .freq = 5160, /* MHz */ - .unk2 = 3440, - RADIOREGS(0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, - 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1408, 0x1008, 0x0C08, 0xFB01, 0xFC01, 0xFD01), - }, - { .channel = 34, - .freq = 5170, /* MHz */ - .unk2 = 3447, - RADIOREGS(0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, - 0x8A, 0xCC, 0x00, 0x0B, 0x0D, 0x8A), - PHYREGS(0x1808, 0x1408, 0x1008, 0xFA01, 0xFB01, 0xFC01), - }, - { .channel = 36, - .freq = 5180, /* MHz */ - .unk2 = 3453, - RADIOREGS(0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, - 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x1C08, 0x1808, 0x1408, 0xF901, 0xFA01, 0xFB01), - }, - { .channel = 38, - .freq = 5190, /* MHz */ - .unk2 = 3460, - RADIOREGS(0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A, - 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, - 0x89, 0xCC, 0x00, 0x0B, 0x0C, 0x89), - PHYREGS(0x2008, 0x1C08, 0x1808, 0xF801, 0xF901, 0xFA01), - }, - { .channel = 40, - .freq = 5200, /* MHz */ - .unk2 = 3467, - RADIOREGS(0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, - 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2408, 0x2008, 0x1C08, 0xF701, 0xF801, 0xF901), - }, - { .channel = 42, - .freq = 5210, /* MHz */ - .unk2 = 3473, - RADIOREGS(0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, - 0x89, 0xBB, 0x00, 0x0A, 0x0B, 0x89), - PHYREGS(0x2808, 0x2408, 0x2008, 0xF601, 0xF701, 0xF801), - }, - { .channel = 44, - .freq = 5220, /* MHz */ - .unk2 = 3480, - RADIOREGS(0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, - 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x2C08, 0x2808, 0x2408, 0xF501, 0xF601, 0xF701), - }, - { .channel = 46, - .freq = 5230, /* MHz */ - .unk2 = 3487, - RADIOREGS(0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A, - 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, - 0x88, 0xBB, 0x00, 0x09, 0x0A, 0x88), - PHYREGS(0x3008, 0x2C08, 0x2808, 0xF401, 0xF501, 0xF601), - }, - { .channel = 48, - .freq = 5240, /* MHz */ - .unk2 = 3493, - RADIOREGS(0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, - 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3408, 0x3008, 0x2C08, 0xF301, 0xF401, 0xF501), - }, - { .channel = 50, - .freq = 5250, /* MHz */ - .unk2 = 3500, - RADIOREGS(0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, - 0x87, 0xAA, 0x00, 0x09, 0x0A, 0x87), - PHYREGS(0x3808, 0x3408, 0x3008, 0xF201, 0xF301, 0xF401), - }, - { .channel = 52, - .freq = 5260, /* MHz */ - .unk2 = 3507, - RADIOREGS(0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, - 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x3C08, 0x3808, 0x3408, 0xF101, 0xF201, 0xF301), - }, - { .channel = 54, - .freq = 5270, /* MHz */ - .unk2 = 3513, - RADIOREGS(0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A, - 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, - 0x87, 0xAA, 0x00, 0x08, 0x09, 0x87), - PHYREGS(0x4008, 0x3C08, 0x3808, 0xF001, 0xF101, 0xF201), - }, - { .channel = 56, - .freq = 5280, /* MHz */ - .unk2 = 3520, - RADIOREGS(0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, - 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4408, 0x4008, 0x3C08, 0xF001, 0xF001, 0xF101), - }, - { .channel = 58, - .freq = 5290, /* MHz */ - .unk2 = 3527, - RADIOREGS(0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, - 0x86, 0x99, 0x00, 0x08, 0x08, 0x86), - PHYREGS(0x4808, 0x4408, 0x4008, 0xEF01, 0xF001, 0xF001), - }, - { .channel = 60, - .freq = 5300, /* MHz */ - .unk2 = 3533, - RADIOREGS(0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, - 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x4C08, 0x4808, 0x4408, 0xEE01, 0xEF01, 0xF001), - }, - { .channel = 62, - .freq = 5310, /* MHz */ - .unk2 = 3540, - RADIOREGS(0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A, - 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, - 0x85, 0x99, 0x00, 0x08, 0x07, 0x85), - PHYREGS(0x5008, 0x4C08, 0x4808, 0xED01, 0xEE01, 0xEF01), - }, - { .channel = 64, - .freq = 5320, /* MHz */ - .unk2 = 3547, - RADIOREGS(0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, - 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5408, 0x5008, 0x4C08, 0xEC01, 0xED01, 0xEE01), - }, - { .channel = 66, - .freq = 5330, /* MHz */ - .unk2 = 3553, - RADIOREGS(0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, - 0x84, 0x88, 0x00, 0x07, 0x07, 0x84), - PHYREGS(0x5808, 0x5408, 0x5008, 0xEB01, 0xEC01, 0xED01), - }, - { .channel = 68, - .freq = 5340, /* MHz */ - .unk2 = 3560, - RADIOREGS(0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, - 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x5C08, 0x5808, 0x5408, 0xEA01, 0xEB01, 0xEC01), - }, - { .channel = 70, - .freq = 5350, /* MHz */ - .unk2 = 3567, - RADIOREGS(0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A, - 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, - 0x84, 0x88, 0x00, 0x07, 0x06, 0x84), - PHYREGS(0x6008, 0x5C08, 0x5808, 0xE901, 0xEA01, 0xEB01), - }, - { .channel = 72, - .freq = 5360, /* MHz */ - .unk2 = 3573, - RADIOREGS(0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, - 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6408, 0x6008, 0x5C08, 0xE801, 0xE901, 0xEA01), - }, - { .channel = 74, - .freq = 5370, /* MHz */ - .unk2 = 3580, - RADIOREGS(0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, - 0x83, 0x77, 0x00, 0x06, 0x05, 0x83), - PHYREGS(0x6808, 0x6408, 0x6008, 0xE701, 0xE801, 0xE901), - }, - { .channel = 76, - .freq = 5380, /* MHz */ - .unk2 = 3587, - RADIOREGS(0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, - 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x6C08, 0x6808, 0x6408, 0xE601, 0xE701, 0xE801), - }, - { .channel = 78, - .freq = 5390, /* MHz */ - .unk2 = 3593, - RADIOREGS(0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A, - 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, - 0x82, 0x77, 0x00, 0x06, 0x04, 0x82), - PHYREGS(0x7008, 0x6C08, 0x6808, 0xE501, 0xE601, 0xE701), - }, - { .channel = 80, - .freq = 5400, /* MHz */ - .unk2 = 3600, - RADIOREGS(0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, - 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7408, 0x7008, 0x6C08, 0xE501, 0xE501, 0xE601), - }, - { .channel = 82, - .freq = 5410, /* MHz */ - .unk2 = 3607, - RADIOREGS(0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, - 0x81, 0x66, 0x00, 0x05, 0x04, 0x81), - PHYREGS(0x7808, 0x7408, 0x7008, 0xE401, 0xE501, 0xE501), - }, - { .channel = 84, - .freq = 5420, /* MHz */ - .unk2 = 3613, - RADIOREGS(0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, - 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x7C08, 0x7808, 0x7408, 0xE301, 0xE401, 0xE501), - }, - { .channel = 86, - .freq = 5430, /* MHz */ - .unk2 = 3620, - RADIOREGS(0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A, - 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, - 0x80, 0x66, 0x00, 0x05, 0x03, 0x80), - PHYREGS(0x8008, 0x7C08, 0x7808, 0xE201, 0xE301, 0xE401), - }, - { .channel = 88, - .freq = 5440, /* MHz */ - .unk2 = 3627, - RADIOREGS(0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, - 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8408, 0x8008, 0x7C08, 0xE101, 0xE201, 0xE301), - }, - { .channel = 90, - .freq = 5450, /* MHz */ - .unk2 = 3633, - RADIOREGS(0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, - 0x80, 0x55, 0x00, 0x04, 0x02, 0x80), - PHYREGS(0x8808, 0x8408, 0x8008, 0xE001, 0xE101, 0xE201), - }, - { .channel = 92, - .freq = 5460, /* MHz */ - .unk2 = 3640, - RADIOREGS(0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, - 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x8C08, 0x8808, 0x8408, 0xDF01, 0xE001, 0xE101), - }, - { .channel = 94, - .freq = 5470, /* MHz */ - .unk2 = 3647, - RADIOREGS(0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A, - 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, - 0x80, 0x55, 0x00, 0x04, 0x01, 0x80), - PHYREGS(0x9008, 0x8C08, 0x8808, 0xDE01, 0xDF01, 0xE001), - }, - { .channel = 96, - .freq = 5480, /* MHz */ - .unk2 = 3653, - RADIOREGS(0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9408, 0x9008, 0x8C08, 0xDD01, 0xDE01, 0xDF01), - }, - { .channel = 98, - .freq = 5490, /* MHz */ - .unk2 = 3660, - RADIOREGS(0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9808, 0x9408, 0x9008, 0xDD01, 0xDD01, 0xDE01), - }, - { .channel = 100, - .freq = 5500, /* MHz */ - .unk2 = 3667, - RADIOREGS(0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0x9C08, 0x9808, 0x9408, 0xDC01, 0xDD01, 0xDD01), - }, - { .channel = 102, - .freq = 5510, /* MHz */ - .unk2 = 3673, - RADIOREGS(0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A, - 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, - 0x80, 0x44, 0x00, 0x03, 0x00, 0x80), - PHYREGS(0xA008, 0x9C08, 0x9808, 0xDB01, 0xDC01, 0xDD01), - }, - { .channel = 104, - .freq = 5520, /* MHz */ - .unk2 = 3680, - RADIOREGS(0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA408, 0xA008, 0x9C08, 0xDA01, 0xDB01, 0xDC01), - }, - { .channel = 106, - .freq = 5530, /* MHz */ - .unk2 = 3687, - RADIOREGS(0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xA808, 0xA408, 0xA008, 0xD901, 0xDA01, 0xDB01), - }, - { .channel = 108, - .freq = 5540, /* MHz */ - .unk2 = 3693, - RADIOREGS(0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xAC08, 0xA808, 0xA408, 0xD801, 0xD901, 0xDA01), - }, - { .channel = 110, - .freq = 5550, /* MHz */ - .unk2 = 3700, - RADIOREGS(0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A, - 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, - 0x80, 0x33, 0x00, 0x02, 0x00, 0x80), - PHYREGS(0xB008, 0xAC08, 0xA808, 0xD701, 0xD801, 0xD901), - }, - { .channel = 112, - .freq = 5560, /* MHz */ - .unk2 = 3707, - RADIOREGS(0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB408, 0xB008, 0xAC08, 0xD701, 0xD701, 0xD801), - }, - { .channel = 114, - .freq = 5570, /* MHz */ - .unk2 = 3713, - RADIOREGS(0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xB808, 0xB408, 0xB008, 0xD601, 0xD701, 0xD701), - }, - { .channel = 116, - .freq = 5580, /* MHz */ - .unk2 = 3720, - RADIOREGS(0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xBC08, 0xB808, 0xB408, 0xD501, 0xD601, 0xD701), - }, - { .channel = 118, - .freq = 5590, /* MHz */ - .unk2 = 3727, - RADIOREGS(0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A, - 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, - 0x80, 0x22, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC008, 0xBC08, 0xB808, 0xD401, 0xD501, 0xD601), - }, - { .channel = 120, - .freq = 5600, /* MHz */ - .unk2 = 3733, - RADIOREGS(0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, - 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC408, 0xC008, 0xBC08, 0xD301, 0xD401, 0xD501), - }, - { .channel = 122, - .freq = 5610, /* MHz */ - .unk2 = 3740, - RADIOREGS(0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, - 0x80, 0x11, 0x00, 0x01, 0x00, 0x80), - PHYREGS(0xC808, 0xC408, 0xC008, 0xD201, 0xD301, 0xD401), - }, - { .channel = 124, - .freq = 5620, /* MHz */ - .unk2 = 3747, - RADIOREGS(0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xCC08, 0xC808, 0xC408, 0xD201, 0xD201, 0xD301), - }, - { .channel = 126, - .freq = 5630, /* MHz */ - .unk2 = 3753, - RADIOREGS(0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A, - 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, - 0x80, 0x11, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD008, 0xCC08, 0xC808, 0xD101, 0xD201, 0xD201), - }, - { .channel = 128, - .freq = 5640, /* MHz */ - .unk2 = 3760, - RADIOREGS(0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD408, 0xD008, 0xCC08, 0xD001, 0xD101, 0xD201), - }, - { .channel = 130, - .freq = 5650, /* MHz */ - .unk2 = 3767, - RADIOREGS(0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xD808, 0xD408, 0xD008, 0xCF01, 0xD001, 0xD101), - }, - { .channel = 132, - .freq = 5660, /* MHz */ - .unk2 = 3773, - RADIOREGS(0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xDC08, 0xD808, 0xD408, 0xCE01, 0xCF01, 0xD001), - }, - { .channel = 134, - .freq = 5670, /* MHz */ - .unk2 = 3780, - RADIOREGS(0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE008, 0xDC08, 0xD808, 0xCE01, 0xCE01, 0xCF01), - }, - { .channel = 136, - .freq = 5680, /* MHz */ - .unk2 = 3787, - RADIOREGS(0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE408, 0xE008, 0xDC08, 0xCD01, 0xCE01, 0xCE01), - }, - { .channel = 138, - .freq = 5690, /* MHz */ - .unk2 = 3793, - RADIOREGS(0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xE808, 0xE408, 0xE008, 0xCC01, 0xCD01, 0xCE01), - }, - { .channel = 140, - .freq = 5700, /* MHz */ - .unk2 = 3800, - RADIOREGS(0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xEC08, 0xE808, 0xE408, 0xCB01, 0xCC01, 0xCD01), - }, - { .channel = 142, - .freq = 5710, /* MHz */ - .unk2 = 3807, - RADIOREGS(0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF008, 0xEC08, 0xE808, 0xCA01, 0xCB01, 0xCC01), - }, - { .channel = 144, - .freq = 5720, /* MHz */ - .unk2 = 3813, - RADIOREGS(0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF408, 0xF008, 0xEC08, 0xC901, 0xCA01, 0xCB01), - }, - { .channel = 145, - .freq = 5725, /* MHz */ - .unk2 = 3817, - RADIOREGS(0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF608, 0xF208, 0xEE08, 0xC901, 0xCA01, 0xCB01), - }, - { .channel = 146, - .freq = 5730, /* MHz */ - .unk2 = 3820, - RADIOREGS(0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xF808, 0xF408, 0xF008, 0xC901, 0xC901, 0xCA01), - }, - { .channel = 147, - .freq = 5735, /* MHz */ - .unk2 = 3823, - RADIOREGS(0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFA08, 0xF608, 0xF208, 0xC801, 0xC901, 0xCA01), - }, - { .channel = 148, - .freq = 5740, /* MHz */ - .unk2 = 3827, - RADIOREGS(0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFC08, 0xF808, 0xF408, 0xC801, 0xC901, 0xC901), - }, - { .channel = 149, - .freq = 5745, /* MHz */ - .unk2 = 3830, - RADIOREGS(0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0xFE08, 0xFA08, 0xF608, 0xC801, 0xC801, 0xC901), - }, - { .channel = 150, - .freq = 5750, /* MHz */ - .unk2 = 3833, - RADIOREGS(0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0009, 0xFC08, 0xF808, 0xC701, 0xC801, 0xC901), - }, - { .channel = 151, - .freq = 5755, /* MHz */ - .unk2 = 3837, - RADIOREGS(0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0209, 0xFE08, 0xFA08, 0xC701, 0xC801, 0xC801), - }, - { .channel = 152, - .freq = 5760, /* MHz */ - .unk2 = 3840, - RADIOREGS(0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0409, 0x0009, 0xFC08, 0xC601, 0xC701, 0xC801), - }, - { .channel = 153, - .freq = 5765, /* MHz */ - .unk2 = 3843, - RADIOREGS(0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0609, 0x0209, 0xFE08, 0xC601, 0xC701, 0xC801), - }, - { .channel = 154, - .freq = 5770, /* MHz */ - .unk2 = 3847, - RADIOREGS(0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0809, 0x0409, 0x0009, 0xC601, 0xC601, 0xC701), - }, - { .channel = 155, - .freq = 5775, /* MHz */ - .unk2 = 3850, - RADIOREGS(0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0A09, 0x0609, 0x0209, 0xC501, 0xC601, 0xC701), - }, - { .channel = 156, - .freq = 5780, /* MHz */ - .unk2 = 3853, - RADIOREGS(0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0C09, 0x0809, 0x0409, 0xC501, 0xC601, 0xC601), - }, - { .channel = 157, - .freq = 5785, /* MHz */ - .unk2 = 3857, - RADIOREGS(0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x0E09, 0x0A09, 0x0609, 0xC401, 0xC501, 0xC601), - }, - { .channel = 158, - .freq = 5790, /* MHz */ - .unk2 = 3860, - RADIOREGS(0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1009, 0x0C09, 0x0809, 0xC401, 0xC501, 0xC601), - }, - { .channel = 159, - .freq = 5795, /* MHz */ - .unk2 = 3863, - RADIOREGS(0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1209, 0x0E09, 0x0A09, 0xC401, 0xC401, 0xC501), - }, - { .channel = 160, - .freq = 5800, /* MHz */ - .unk2 = 3867, - RADIOREGS(0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1409, 0x1009, 0x0C09, 0xC301, 0xC401, 0xC501), - }, - { .channel = 161, - .freq = 5805, /* MHz */ - .unk2 = 3870, - RADIOREGS(0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1609, 0x1209, 0x0E09, 0xC301, 0xC401, 0xC401), - }, - { .channel = 162, - .freq = 5810, /* MHz */ - .unk2 = 3873, - RADIOREGS(0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1809, 0x1409, 0x1009, 0xC201, 0xC301, 0xC401), - }, - { .channel = 163, - .freq = 5815, /* MHz */ - .unk2 = 3877, - RADIOREGS(0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1A09, 0x1609, 0x1209, 0xC201, 0xC301, 0xC401), - }, - { .channel = 164, - .freq = 5820, /* MHz */ - .unk2 = 3880, - RADIOREGS(0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1C09, 0x1809, 0x1409, 0xC201, 0xC201, 0xC301), - }, - { .channel = 165, - .freq = 5825, /* MHz */ - .unk2 = 3883, - RADIOREGS(0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x1E09, 0x1A09, 0x1609, 0xC101, 0xC201, 0xC301), - }, - { .channel = 166, - .freq = 5830, /* MHz */ - .unk2 = 3887, - RADIOREGS(0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2009, 0x1C09, 0x1809, 0xC101, 0xC201, 0xC201), - }, - { .channel = 168, - .freq = 5840, /* MHz */ - .unk2 = 3893, - RADIOREGS(0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2409, 0x2009, 0x1C09, 0xC001, 0xC101, 0xC201), - }, - { .channel = 170, - .freq = 5850, /* MHz */ - .unk2 = 3900, - RADIOREGS(0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2809, 0x2409, 0x2009, 0xBF01, 0xC001, 0xC101), - }, - { .channel = 172, - .freq = 5860, /* MHz */ - .unk2 = 3907, - RADIOREGS(0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x2C09, 0x2809, 0x2409, 0xBF01, 0xBF01, 0xC001), - }, - { .channel = 174, - .freq = 5870, /* MHz */ - .unk2 = 3913, - RADIOREGS(0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3009, 0x2C09, 0x2809, 0xBE01, 0xBF01, 0xBF01), - }, - { .channel = 176, - .freq = 5880, /* MHz */ - .unk2 = 3920, - RADIOREGS(0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3409, 0x3009, 0x2C09, 0xBD01, 0xBE01, 0xBF01), - }, - { .channel = 178, - .freq = 5890, /* MHz */ - .unk2 = 3927, - RADIOREGS(0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3809, 0x3409, 0x3009, 0xBC01, 0xBD01, 0xBE01), - }, - { .channel = 180, - .freq = 5900, /* MHz */ - .unk2 = 3933, - RADIOREGS(0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x3C09, 0x3809, 0x3409, 0xBC01, 0xBC01, 0xBD01), - }, - { .channel = 182, - .freq = 5910, /* MHz */ - .unk2 = 3940, - RADIOREGS(0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x80, 0x00, 0x00, 0x00, 0x00, 0x80), - PHYREGS(0x4009, 0x3C09, 0x3809, 0xBB01, 0xBC01, 0xBC01), - }, - { .channel = 1, - .freq = 2412, /* MHz */ - .unk2 = 3216, - RADIOREGS(0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, - 0x80, 0xFF, 0x88, 0x0D, 0x0C, 0x80), - PHYREGS(0xC903, 0xC503, 0xC103, 0x3A04, 0x3F04, 0x4304), - }, - { .channel = 2, - .freq = 2417, /* MHz */ - .unk2 = 3223, - RADIOREGS(0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, - 0x80, 0xFF, 0x88, 0x0C, 0x0B, 0x80), - PHYREGS(0xCB03, 0xC703, 0xC303, 0x3804, 0x3D04, 0x4104), - }, - { .channel = 3, - .freq = 2422, /* MHz */ - .unk2 = 3229, - RADIOREGS(0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, - 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCD03, 0xC903, 0xC503, 0x3604, 0x3A04, 0x3F04), - }, - { .channel = 4, - .freq = 2427, /* MHz */ - .unk2 = 3236, - RADIOREGS(0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, - 0x80, 0xFF, 0x88, 0x0C, 0x0A, 0x80), - PHYREGS(0xCF03, 0xCB03, 0xC703, 0x3404, 0x3804, 0x3D04), - }, - { .channel = 5, - .freq = 2432, /* MHz */ - .unk2 = 3243, - RADIOREGS(0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, - 0x80, 0xFF, 0x88, 0x0C, 0x09, 0x80), - PHYREGS(0xD103, 0xCD03, 0xC903, 0x3104, 0x3604, 0x3A04), - }, - { .channel = 6, - .freq = 2437, /* MHz */ - .unk2 = 3249, - RADIOREGS(0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, - 0x80, 0xFF, 0x88, 0x0B, 0x08, 0x80), - PHYREGS(0xD303, 0xCF03, 0xCB03, 0x2F04, 0x3404, 0x3804), - }, - { .channel = 7, - .freq = 2442, /* MHz */ - .unk2 = 3256, - RADIOREGS(0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, - 0x80, 0xFF, 0x88, 0x0A, 0x07, 0x80), - PHYREGS(0xD503, 0xD103, 0xCD03, 0x2D04, 0x3104, 0x3604), - }, - { .channel = 8, - .freq = 2447, /* MHz */ - .unk2 = 3263, - RADIOREGS(0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, - 0x80, 0xFF, 0x88, 0x0A, 0x06, 0x80), - PHYREGS(0xD703, 0xD303, 0xCF03, 0x2B04, 0x2F04, 0x3404), - }, - { .channel = 9, - .freq = 2452, /* MHz */ - .unk2 = 3269, - RADIOREGS(0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, - 0x80, 0xFF, 0x88, 0x09, 0x06, 0x80), - PHYREGS(0xD903, 0xD503, 0xD103, 0x2904, 0x2D04, 0x3104), - }, - { .channel = 10, - .freq = 2457, /* MHz */ - .unk2 = 3276, - RADIOREGS(0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, - 0x80, 0xFF, 0x88, 0x08, 0x05, 0x80), - PHYREGS(0xDB03, 0xD703, 0xD303, 0x2704, 0x2B04, 0x2F04), - }, - { .channel = 11, - .freq = 2462, /* MHz */ - .unk2 = 3283, - RADIOREGS(0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, - 0x80, 0xFF, 0x88, 0x08, 0x04, 0x80), - PHYREGS(0xDD03, 0xD903, 0xD503, 0x2404, 0x2904, 0x2D04), - }, - { .channel = 12, - .freq = 2467, /* MHz */ - .unk2 = 3289, - RADIOREGS(0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, - 0x80, 0xFF, 0x88, 0x08, 0x03, 0x80), - PHYREGS(0xDF03, 0xDB03, 0xD703, 0x2204, 0x2704, 0x2B04), - }, - { .channel = 13, - .freq = 2472, /* MHz */ - .unk2 = 3296, - RADIOREGS(0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, - 0x80, 0xFF, 0x88, 0x07, 0x03, 0x80), - PHYREGS(0xE103, 0xDD03, 0xD903, 0x2004, 0x2404, 0x2904), - }, - { .channel = 14, - .freq = 2484, /* MHz */ - .unk2 = 3312, - RADIOREGS(0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15, - 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, - 0x80, 0xFF, 0x88, 0x07, 0x01, 0x80), - PHYREGS(0xE603, 0xE203, 0xDE03, 0x1B04, 0x1F04, 0x2404), - }, -}; - -const struct b43_nphy_channeltab_entry * -b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel) -{ - const struct b43_nphy_channeltab_entry *e; - unsigned int i; - - for (i = 0; i < ARRAY_SIZE(b43_nphy_channeltab); i++) { - e = &(b43_nphy_channeltab[i]); - if (e->channel == channel) - return e; - } - - return NULL; -} - - -const u8 b43_ntab_adjustpower0[] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, - 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, - 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, - 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, - 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, - 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, -}; - -const u8 b43_ntab_adjustpower1[] = { - 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, - 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, - 0x04, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, - 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, - 0x08, 0x08, 0x08, 0x08, 0x09, 0x09, 0x09, 0x09, - 0x0A, 0x0A, 0x0A, 0x0A, 0x0B, 0x0B, 0x0B, 0x0B, - 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, - 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F, - 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11, - 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13, - 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15, - 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17, - 0x18, 0x18, 0x18, 0x18, 0x19, 0x19, 0x19, 0x19, - 0x1A, 0x1A, 0x1A, 0x1A, 0x1B, 0x1B, 0x1B, 0x1B, - 0x1C, 0x1C, 0x1C, 0x1C, 0x1D, 0x1D, 0x1D, 0x1D, - 0x1E, 0x1E, 0x1E, 0x1E, 0x1F, 0x1F, 0x1F, 0x1F, -}; - -const u16 b43_ntab_bdi[] = { - 0x0070, 0x0126, 0x012C, 0x0246, 0x048D, 0x04D2, -}; - -const u32 b43_ntab_channelest[] = { - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x44444444, 0x44444444, 0x44444444, 0x44444444, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, - 0x10101010, 0x10101010, 0x10101010, 0x10101010, -}; - -const u8 b43_ntab_estimatepowerlt0[] = { - 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, - 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, - 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, - 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, - 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, - 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, - 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, -}; - -const u8 b43_ntab_estimatepowerlt1[] = { - 0x50, 0x4F, 0x4E, 0x4D, 0x4C, 0x4B, 0x4A, 0x49, - 0x48, 0x47, 0x46, 0x45, 0x44, 0x43, 0x42, 0x41, - 0x40, 0x3F, 0x3E, 0x3D, 0x3C, 0x3B, 0x3A, 0x39, - 0x38, 0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31, - 0x30, 0x2F, 0x2E, 0x2D, 0x2C, 0x2B, 0x2A, 0x29, - 0x28, 0x27, 0x26, 0x25, 0x24, 0x23, 0x22, 0x21, - 0x20, 0x1F, 0x1E, 0x1D, 0x1C, 0x1B, 0x1A, 0x19, - 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, 0x11, -}; - -const u8 b43_ntab_framelookup[] = { - 0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16, - 0x0A, 0x0C, 0x1C, 0x1C, 0x0B, 0x0D, 0x1E, 0x1E, - 0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1A, 0x1A, - 0x0E, 0x10, 0x20, 0x28, 0x0F, 0x11, 0x22, 0x2A, -}; - -const u32 b43_ntab_framestruct[] = { - 0x08004A04, 0x00100000, 0x01000A05, 0x00100020, - 0x09804506, 0x00100030, 0x09804507, 0x00100030, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028, - 0x0980450E, 0x00100038, 0x0980450F, 0x00100038, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000A04, 0x00100000, 0x11008A05, 0x00100020, - 0x1980C506, 0x00100030, 0x21810506, 0x00100030, - 0x21810506, 0x00100030, 0x01800504, 0x00100030, - 0x11808505, 0x00100030, 0x29814507, 0x01100030, - 0x00000A04, 0x00100000, 0x11008A05, 0x00100020, - 0x21810506, 0x00100030, 0x21810506, 0x00100030, - 0x29814507, 0x01100030, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028, - 0x1980C50E, 0x00100038, 0x2181050E, 0x00100038, - 0x2181050E, 0x00100038, 0x0180050C, 0x00100038, - 0x1180850D, 0x00100038, 0x2981450F, 0x01100038, - 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028, - 0x2181050E, 0x00100038, 0x2181050E, 0x00100038, - 0x2981450F, 0x01100038, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x08004A04, 0x00100000, 0x01000A05, 0x00100020, - 0x1980C506, 0x00100030, 0x1980C506, 0x00100030, - 0x11808504, 0x00100030, 0x3981CA05, 0x00100030, - 0x29814507, 0x01100030, 0x00000000, 0x00000000, - 0x10008A04, 0x00100000, 0x3981CA05, 0x00100030, - 0x1980C506, 0x00100030, 0x29814507, 0x01100030, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x08004A0C, 0x00100008, 0x01000A0D, 0x00100028, - 0x1980C50E, 0x00100038, 0x1980C50E, 0x00100038, - 0x1180850C, 0x00100038, 0x3981CA0D, 0x00100038, - 0x2981450F, 0x01100038, 0x00000000, 0x00000000, - 0x10008A0C, 0x00100008, 0x3981CA0D, 0x00100038, - 0x1980C50E, 0x00100038, 0x2981450F, 0x01100038, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x40021404, 0x00100000, 0x02001405, 0x00100040, - 0x0B004A06, 0x01900060, 0x13008A06, 0x01900060, - 0x13008A06, 0x01900060, 0x43020A04, 0x00100060, - 0x1B00CA05, 0x00100060, 0x23010A07, 0x01500060, - 0x40021404, 0x00100000, 0x1A00D405, 0x00100040, - 0x13008A06, 0x01900060, 0x13008A06, 0x01900060, - 0x23010A07, 0x01500060, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x00100010, 0x0200140D, 0x00100050, - 0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070, - 0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070, - 0x1B00CA0D, 0x00100070, 0x23010A0F, 0x01500070, - 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050, - 0x13008A0E, 0x01900070, 0x13008A0E, 0x01900070, - 0x23010A0F, 0x01500070, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50029404, 0x00100000, 0x32019405, 0x00100040, - 0x0B004A06, 0x01900060, 0x0B004A06, 0x01900060, - 0x5B02CA04, 0x00100060, 0x3B01D405, 0x00100060, - 0x23010A07, 0x01500060, 0x00000000, 0x00000000, - 0x5802D404, 0x00100000, 0x3B01D405, 0x00100060, - 0x0B004A06, 0x01900060, 0x23010A07, 0x01500060, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x5002940C, 0x00100010, 0x3201940D, 0x00100050, - 0x0B004A0E, 0x01900070, 0x0B004A0E, 0x01900070, - 0x5B02CA0C, 0x00100070, 0x3B01D40D, 0x00100070, - 0x23010A0F, 0x01500070, 0x00000000, 0x00000000, - 0x5802D40C, 0x00100010, 0x3B01D40D, 0x00100070, - 0x0B004A0E, 0x01900070, 0x23010A0F, 0x01500070, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x40021404, 0x000F4800, 0x62031405, 0x00100040, - 0x53028A06, 0x01900060, 0x53028A07, 0x01900060, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x000F4810, 0x6203140D, 0x00100050, - 0x53028A0E, 0x01900070, 0x53028A0F, 0x01900070, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028, - 0x1980C50E, 0x00100038, 0x2181050E, 0x00100038, - 0x2181050E, 0x00100038, 0x0180050C, 0x00100038, - 0x1180850D, 0x00100038, 0x1181850D, 0x00100038, - 0x2981450F, 0x01100038, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000A0C, 0x00100008, 0x11008A0D, 0x00100028, - 0x2181050E, 0x00100038, 0x2181050E, 0x00100038, - 0x1181850D, 0x00100038, 0x2981450F, 0x01100038, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x08004A04, 0x00100000, 0x01000A05, 0x00100020, - 0x0180C506, 0x00100030, 0x0180C506, 0x00100030, - 0x2180C50C, 0x00100030, 0x49820A0D, 0x0016A130, - 0x41824A0D, 0x0016A130, 0x2981450F, 0x01100030, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x2000CA0C, 0x00100000, 0x49820A0D, 0x0016A130, - 0x1980C50E, 0x00100030, 0x41824A0D, 0x0016A130, - 0x2981450F, 0x01100030, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x00100010, 0x0200140D, 0x00100050, - 0x0B004A0E, 0x01900070, 0x13008A0E, 0x01900070, - 0x13008A0E, 0x01900070, 0x43020A0C, 0x00100070, - 0x1B00CA0D, 0x00100070, 0x1B014A0D, 0x00100070, - 0x23010A0F, 0x01500070, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050, - 0x13008A0E, 0x01900070, 0x13008A0E, 0x01900070, - 0x1B014A0D, 0x00100070, 0x23010A0F, 0x01500070, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x50029404, 0x00100000, 0x32019405, 0x00100040, - 0x03004A06, 0x01900060, 0x03004A06, 0x01900060, - 0x6B030A0C, 0x00100060, 0x4B02140D, 0x0016A160, - 0x4302540D, 0x0016A160, 0x23010A0F, 0x01500060, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x6B03140C, 0x00100060, 0x4B02140D, 0x0016A160, - 0x0B004A0E, 0x01900060, 0x4302540D, 0x0016A160, - 0x23010A0F, 0x01500060, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x40021404, 0x00100000, 0x1A00D405, 0x00100040, - 0x53028A06, 0x01900060, 0x5B02CA06, 0x01900060, - 0x5B02CA06, 0x01900060, 0x43020A04, 0x00100060, - 0x1B00CA05, 0x00100060, 0x53028A07, 0x0190C060, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050, - 0x53028A0E, 0x01900070, 0x5B02CA0E, 0x01900070, - 0x5B02CA0E, 0x01900070, 0x43020A0C, 0x00100070, - 0x1B00CA0D, 0x00100070, 0x53028A0F, 0x0190C070, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x40021404, 0x00100000, 0x1A00D405, 0x00100040, - 0x5B02CA06, 0x01900060, 0x5B02CA06, 0x01900060, - 0x53028A07, 0x0190C060, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x4002140C, 0x00100010, 0x1A00D40D, 0x00100050, - 0x5B02CA0E, 0x01900070, 0x5B02CA0E, 0x01900070, - 0x53028A0F, 0x0190C070, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; - -const u32 b43_ntab_gainctl0[] = { - 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, - 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, - 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, - 0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38, - 0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336, - 0x006B0435, 0x006A0535, 0x00690634, 0x00680734, - 0x00670833, 0x00660933, 0x00650A32, 0x00640B32, - 0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30, - 0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E, - 0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C, - 0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A, - 0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28, - 0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326, - 0x004B0425, 0x004A0525, 0x00490624, 0x00480724, - 0x00470823, 0x00460923, 0x00450A22, 0x00440B22, - 0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20, - 0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E, - 0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C, - 0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A, - 0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18, - 0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316, - 0x002B0415, 0x002A0515, 0x00290614, 0x00280714, - 0x00270813, 0x00260913, 0x00250A12, 0x00240B12, - 0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10, - 0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E, - 0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C, - 0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A, - 0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08, - 0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306, - 0x000B0405, 0x000A0505, 0x00090604, 0x00080704, - 0x00070803, 0x00060903, 0x00050A02, 0x00040B02, - 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, -}; - -const u32 b43_ntab_gainctl1[] = { - 0x007F003F, 0x007E013F, 0x007D023E, 0x007C033E, - 0x007B043D, 0x007A053D, 0x0079063C, 0x0078073C, - 0x0077083B, 0x0076093B, 0x00750A3A, 0x00740B3A, - 0x00730C39, 0x00720D39, 0x00710E38, 0x00700F38, - 0x006F0037, 0x006E0137, 0x006D0236, 0x006C0336, - 0x006B0435, 0x006A0535, 0x00690634, 0x00680734, - 0x00670833, 0x00660933, 0x00650A32, 0x00640B32, - 0x00630C31, 0x00620D31, 0x00610E30, 0x00600F30, - 0x005F002F, 0x005E012F, 0x005D022E, 0x005C032E, - 0x005B042D, 0x005A052D, 0x0059062C, 0x0058072C, - 0x0057082B, 0x0056092B, 0x00550A2A, 0x00540B2A, - 0x00530C29, 0x00520D29, 0x00510E28, 0x00500F28, - 0x004F0027, 0x004E0127, 0x004D0226, 0x004C0326, - 0x004B0425, 0x004A0525, 0x00490624, 0x00480724, - 0x00470823, 0x00460923, 0x00450A22, 0x00440B22, - 0x00430C21, 0x00420D21, 0x00410E20, 0x00400F20, - 0x003F001F, 0x003E011F, 0x003D021E, 0x003C031E, - 0x003B041D, 0x003A051D, 0x0039061C, 0x0038071C, - 0x0037081B, 0x0036091B, 0x00350A1A, 0x00340B1A, - 0x00330C19, 0x00320D19, 0x00310E18, 0x00300F18, - 0x002F0017, 0x002E0117, 0x002D0216, 0x002C0316, - 0x002B0415, 0x002A0515, 0x00290614, 0x00280714, - 0x00270813, 0x00260913, 0x00250A12, 0x00240B12, - 0x00230C11, 0x00220D11, 0x00210E10, 0x00200F10, - 0x001F000F, 0x001E010F, 0x001D020E, 0x001C030E, - 0x001B040D, 0x001A050D, 0x0019060C, 0x0018070C, - 0x0017080B, 0x0016090B, 0x00150A0A, 0x00140B0A, - 0x00130C09, 0x00120D09, 0x00110E08, 0x00100F08, - 0x000F0007, 0x000E0107, 0x000D0206, 0x000C0306, - 0x000B0405, 0x000A0505, 0x00090604, 0x00080704, - 0x00070803, 0x00060903, 0x00050A02, 0x00040B02, - 0x00030C01, 0x00020D01, 0x00010E00, 0x00000F00, -}; - -const u32 b43_ntab_intlevel[] = { - 0x00802070, 0x0671188D, 0x0A60192C, 0x0A300E46, - 0x00C1188D, 0x080024D2, 0x00000070, -}; - -const u32 b43_ntab_iqlt0[] = { - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, -}; - -const u32 b43_ntab_iqlt1[] = { - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, - 0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F, -}; - -const u16 b43_ntab_loftlt0[] = { - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, -}; - -const u16 b43_ntab_loftlt1[] = { - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, 0x0000, 0x0101, 0x0002, 0x0103, - 0x0000, 0x0101, 0x0002, 0x0103, 0x0000, 0x0101, - 0x0002, 0x0103, -}; - -const u8 b43_ntab_mcs[] = { - 0x00, 0x08, 0x0A, 0x10, 0x12, 0x19, 0x1A, 0x1C, - 0x40, 0x48, 0x4A, 0x50, 0x52, 0x59, 0x5A, 0x5C, - 0x80, 0x88, 0x8A, 0x90, 0x92, 0x99, 0x9A, 0x9C, - 0xC0, 0xC8, 0xCA, 0xD0, 0xD2, 0xD9, 0xDA, 0xDC, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x02, 0x04, 0x08, 0x09, 0x0A, 0x0C, - 0x10, 0x11, 0x12, 0x14, 0x18, 0x19, 0x1A, 0x1C, - 0x20, 0x21, 0x22, 0x24, 0x40, 0x41, 0x42, 0x44, - 0x48, 0x49, 0x4A, 0x4C, 0x50, 0x51, 0x52, 0x54, - 0x58, 0x59, 0x5A, 0x5C, 0x60, 0x61, 0x62, 0x64, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; - -const u32 b43_ntab_noisevar10[] = { - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, -}; - -const u32 b43_ntab_noisevar11[] = { - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, - 0x020C020C, 0x0000014D, 0x020C020C, 0x0000014D, -}; - -const u16 b43_ntab_pilot[] = { - 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, 0xFF08, - 0xFF08, 0xFF08, 0x80D5, 0x80D5, 0x80D5, 0x80D5, - 0x80D5, 0x80D5, 0x80D5, 0x80D5, 0xFF0A, 0xFF82, - 0xFFA0, 0xFF28, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, - 0xFF82, 0xFFA0, 0xFF28, 0xFF0A, 0xFFFF, 0xFFFF, - 0xFFFF, 0xFFFF, 0xF83F, 0xFA1F, 0xFA97, 0xFAB5, - 0xF2BD, 0xF0BF, 0xFFFF, 0xFFFF, 0xF017, 0xF815, - 0xF215, 0xF095, 0xF035, 0xF01D, 0xFFFF, 0xFFFF, - 0xFF08, 0xFF02, 0xFF80, 0xFF20, 0xFF08, 0xFF02, - 0xFF80, 0xFF20, 0xF01F, 0xF817, 0xFA15, 0xF295, - 0xF0B5, 0xF03D, 0xFFFF, 0xFFFF, 0xF82A, 0xFA0A, - 0xFA82, 0xFAA0, 0xF2A8, 0xF0AA, 0xFFFF, 0xFFFF, - 0xF002, 0xF800, 0xF200, 0xF080, 0xF020, 0xF008, - 0xFFFF, 0xFFFF, 0xF00A, 0xF802, 0xFA00, 0xF280, - 0xF0A0, 0xF028, 0xFFFF, 0xFFFF, -}; - -const u32 b43_ntab_pilotlt[] = { - 0x76540123, 0x62407351, 0x76543201, 0x76540213, - 0x76540123, 0x76430521, -}; - -const u32 b43_ntab_tdi20a0[] = { - 0x00091226, 0x000A1429, 0x000B56AD, 0x000C58B0, - 0x000D5AB3, 0x000E9CB6, 0x000F9EBA, 0x0000C13D, - 0x00020301, 0x00030504, 0x00040708, 0x0005090B, - 0x00064B8E, 0x00095291, 0x000A5494, 0x000B9718, - 0x000C9927, 0x000D9B2A, 0x000EDD2E, 0x000FDF31, - 0x000101B4, 0x000243B7, 0x000345BB, 0x000447BE, - 0x00058982, 0x00068C05, 0x00099309, 0x000A950C, - 0x000BD78F, 0x000CD992, 0x000DDB96, 0x000F1D99, - 0x00005FA8, 0x0001422C, 0x0002842F, 0x00038632, - 0x00048835, 0x0005CA38, 0x0006CCBC, 0x0009D3BF, - 0x000B1603, 0x000C1806, 0x000D1A0A, 0x000E1C0D, - 0x000F5E10, 0x00008093, 0x00018297, 0x0002C49A, - 0x0003C680, 0x0004C880, 0x00060B00, 0x00070D00, - 0x00000000, 0x00000000, 0x00000000, -}; - -const u32 b43_ntab_tdi20a1[] = { - 0x00014B26, 0x00028D29, 0x000393AD, 0x00049630, - 0x0005D833, 0x0006DA36, 0x00099C3A, 0x000A9E3D, - 0x000BC081, 0x000CC284, 0x000DC488, 0x000F068B, - 0x0000488E, 0x00018B91, 0x0002D214, 0x0003D418, - 0x0004D6A7, 0x000618AA, 0x00071AAE, 0x0009DCB1, - 0x000B1EB4, 0x000C0137, 0x000D033B, 0x000E053E, - 0x000F4702, 0x00008905, 0x00020C09, 0x0003128C, - 0x0004148F, 0x00051712, 0x00065916, 0x00091B19, - 0x000A1D28, 0x000B5F2C, 0x000C41AF, 0x000D43B2, - 0x000E85B5, 0x000F87B8, 0x0000C9BC, 0x00024CBF, - 0x00035303, 0x00045506, 0x0005978A, 0x0006998D, - 0x00095B90, 0x000A5D93, 0x000B9F97, 0x000C821A, - 0x000D8400, 0x000EC600, 0x000FC800, 0x00010A00, - 0x00000000, 0x00000000, 0x00000000, -}; - -const u32 b43_ntab_tdi40a0[] = { - 0x0011A346, 0x00136CCF, 0x0014F5D9, 0x001641E2, - 0x0017CB6B, 0x00195475, 0x001B2383, 0x001CAD0C, - 0x001E7616, 0x0000821F, 0x00020BA8, 0x0003D4B2, - 0x00056447, 0x00072DD0, 0x0008B6DA, 0x000A02E3, - 0x000B8C6C, 0x000D15F6, 0x0011E484, 0x0013AE0D, - 0x00153717, 0x00168320, 0x00180CA9, 0x00199633, - 0x001B6548, 0x001CEED1, 0x001EB7DB, 0x0000C3E4, - 0x00024D6D, 0x000416F7, 0x0005A585, 0x00076F0F, - 0x0008F818, 0x000A4421, 0x000BCDAB, 0x000D9734, - 0x00122649, 0x0013EFD2, 0x001578DC, 0x0016C4E5, - 0x00184E6E, 0x001A17F8, 0x001BA686, 0x001D3010, - 0x001EF999, 0x00010522, 0x00028EAC, 0x00045835, - 0x0005E74A, 0x0007B0D3, 0x00093A5D, 0x000A85E6, - 0x000C0F6F, 0x000DD8F9, 0x00126787, 0x00143111, - 0x0015BA9A, 0x00170623, 0x00188FAD, 0x001A5936, - 0x001BE84B, 0x001DB1D4, 0x001F3B5E, 0x000146E7, - 0x00031070, 0x000499FA, 0x00062888, 0x0007F212, - 0x00097B9B, 0x000AC7A4, 0x000C50AE, 0x000E1A37, - 0x0012A94C, 0x001472D5, 0x0015FC5F, 0x00174868, - 0x0018D171, 0x001A9AFB, 0x001C2989, 0x001DF313, - 0x001F7C9C, 0x000188A5, 0x000351AF, 0x0004DB38, - 0x0006AA4D, 0x000833D7, 0x0009BD60, 0x000B0969, - 0x000C9273, 0x000E5BFC, 0x00132A8A, 0x0014B414, - 0x00163D9D, 0x001789A6, 0x001912B0, 0x001ADC39, - 0x001C6BCE, 0x001E34D8, 0x001FBE61, 0x0001CA6A, - 0x00039374, 0x00051CFD, 0x0006EC0B, 0x00087515, - 0x0009FE9E, 0x000B4AA7, 0x000CD3B1, 0x000E9D3A, - 0x00000000, 0x00000000, -}; - -const u32 b43_ntab_tdi40a1[] = { - 0x001EDB36, 0x000129CA, 0x0002B353, 0x00047CDD, - 0x0005C8E6, 0x000791EF, 0x00091BF9, 0x000AAA07, - 0x000C3391, 0x000DFD1A, 0x00120923, 0x0013D22D, - 0x00155C37, 0x0016EACB, 0x00187454, 0x001A3DDE, - 0x001B89E7, 0x001D12F0, 0x001F1CFA, 0x00016B88, - 0x00033492, 0x0004BE1B, 0x00060A24, 0x0007D32E, - 0x00095D38, 0x000AEC4C, 0x000C7555, 0x000E3EDF, - 0x00124AE8, 0x001413F1, 0x0015A37B, 0x00172C89, - 0x0018B593, 0x001A419C, 0x001BCB25, 0x001D942F, - 0x001F63B9, 0x0001AD4D, 0x00037657, 0x0004C260, - 0x00068BE9, 0x000814F3, 0x0009A47C, 0x000B2D8A, - 0x000CB694, 0x000E429D, 0x00128C26, 0x001455B0, - 0x0015E4BA, 0x00176E4E, 0x0018F758, 0x001A8361, - 0x001C0CEA, 0x001DD674, 0x001FA57D, 0x0001EE8B, - 0x0003B795, 0x0005039E, 0x0006CD27, 0x000856B1, - 0x0009E5C6, 0x000B6F4F, 0x000CF859, 0x000E8462, - 0x00130DEB, 0x00149775, 0x00162603, 0x0017AF8C, - 0x00193896, 0x001AC49F, 0x001C4E28, 0x001E17B2, - 0x0000A6C7, 0x00023050, 0x0003F9DA, 0x00054563, - 0x00070EEC, 0x00089876, 0x000A2704, 0x000BB08D, - 0x000D3A17, 0x001185A0, 0x00134F29, 0x0014D8B3, - 0x001667C8, 0x0017F151, 0x00197ADB, 0x001B0664, - 0x001C8FED, 0x001E5977, 0x0000E805, 0x0002718F, - 0x00043B18, 0x000586A1, 0x0007502B, 0x0008D9B4, - 0x000A68C9, 0x000BF252, 0x000DBBDC, 0x0011C7E5, - 0x001390EE, 0x00151A78, 0x0016A906, 0x00183290, - 0x0019BC19, 0x001B4822, 0x001CD12C, 0x001E9AB5, - 0x00000000, 0x00000000, -}; - -const u32 b43_ntab_tdtrn[] = { - 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6, - 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68, - 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52, - 0x0C380000, 0x12F6FE52, 0xFE36F592, 0xEE680050, - 0x061C061C, 0x0050EE68, 0xF592FE36, 0xFE5212F6, - 0x00000C38, 0xFE5212F6, 0xF592FE36, 0x0050EE68, - 0x061C061C, 0xEE680050, 0xFE36F592, 0x12F6FE52, - 0x0C380000, 0x12F6FE52, 0xFE36F592, 0xEE680050, - 0x05E305E3, 0x004DEF0C, 0xF5F3FE47, 0xFE611246, - 0x00000BC7, 0xFE611246, 0xF5F3FE47, 0x004DEF0C, - 0x05E305E3, 0xEF0C004D, 0xFE47F5F3, 0x1246FE61, - 0x0BC70000, 0x1246FE61, 0xFE47F5F3, 0xEF0C004D, - 0x05E305E3, 0x004DEF0C, 0xF5F3FE47, 0xFE611246, - 0x00000BC7, 0xFE611246, 0xF5F3FE47, 0x004DEF0C, - 0x05E305E3, 0xEF0C004D, 0xFE47F5F3, 0x1246FE61, - 0x0BC70000, 0x1246FE61, 0xFE47F5F3, 0xEF0C004D, - 0xFA58FA58, 0xF895043B, 0xFF4C09C0, 0xFBC6FFA8, - 0xFB84F384, 0x0798F6F9, 0x05760122, 0x058409F6, - 0x0B500000, 0x05B7F542, 0x08860432, 0x06DDFEE7, - 0xFB84F384, 0xF9D90664, 0xF7E8025C, 0x00FFF7BD, - 0x05A805A8, 0xF7BD00FF, 0x025CF7E8, 0x0664F9D9, - 0xF384FB84, 0xFEE706DD, 0x04320886, 0xF54205B7, - 0x00000B50, 0x09F60584, 0x01220576, 0xF6F90798, - 0xF384FB84, 0xFFA8FBC6, 0x09C0FF4C, 0x043BF895, - 0x02D402D4, 0x07DE0270, 0xFC96079C, 0xF90AFE94, - 0xFE00FF2C, 0x02D4065D, 0x092A0096, 0x0014FBB8, - 0xFD2CFD2C, 0x076AFB3C, 0x0096F752, 0xF991FD87, - 0xFB2C0200, 0xFEB8F960, 0x08E0FC96, 0x049802A8, - 0xFD2CFD2C, 0x02A80498, 0xFC9608E0, 0xF960FEB8, - 0x0200FB2C, 0xFD87F991, 0xF7520096, 0xFB3C076A, - 0xFD2CFD2C, 0xFBB80014, 0x0096092A, 0x065D02D4, - 0xFF2CFE00, 0xFE94F90A, 0x079CFC96, 0x027007DE, - 0x02D402D4, 0x027007DE, 0x079CFC96, 0xFE94F90A, - 0xFF2CFE00, 0x065D02D4, 0x0096092A, 0xFBB80014, - 0xFD2CFD2C, 0xFB3C076A, 0xF7520096, 0xFD87F991, - 0x0200FB2C, 0xF960FEB8, 0xFC9608E0, 0x02A80498, - 0xFD2CFD2C, 0x049802A8, 0x08E0FC96, 0xFEB8F960, - 0xFB2C0200, 0xF991FD87, 0x0096F752, 0x076AFB3C, - 0xFD2CFD2C, 0x0014FBB8, 0x092A0096, 0x02D4065D, - 0xFE00FF2C, 0xF90AFE94, 0xFC96079C, 0x07DE0270, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x062A0000, 0xFEFA0759, 0x08B80908, 0xF396FC2D, - 0xF9D6045C, 0xFC4EF608, 0xF748F596, 0x07B207BF, - 0x062A062A, 0xF84EF841, 0xF748F596, 0x03B209F8, - 0xF9D6045C, 0x0C6A03D3, 0x08B80908, 0x0106F8A7, - 0x062A0000, 0xFEFAF8A7, 0x08B8F6F8, 0xF39603D3, - 0xF9D6FBA4, 0xFC4E09F8, 0xF7480A6A, 0x07B2F841, - 0x062AF9D6, 0xF84E07BF, 0xF7480A6A, 0x03B2F608, - 0xF9D6FBA4, 0x0C6AFC2D, 0x08B8F6F8, 0x01060759, - 0x062A0000, 0xFEFA0759, 0x08B80908, 0xF396FC2D, - 0xF9D6045C, 0xFC4EF608, 0xF748F596, 0x07B207BF, - 0x062A062A, 0xF84EF841, 0xF748F596, 0x03B209F8, - 0xF9D6045C, 0x0C6A03D3, 0x08B80908, 0x0106F8A7, - 0x062A0000, 0xFEFAF8A7, 0x08B8F6F8, 0xF39603D3, - 0xF9D6FBA4, 0xFC4E09F8, 0xF7480A6A, 0x07B2F841, - 0x062AF9D6, 0xF84E07BF, 0xF7480A6A, 0x03B2F608, - 0xF9D6FBA4, 0x0C6AFC2D, 0x08B8F6F8, 0x01060759, - 0x061C061C, 0xFF30009D, 0xFFB21141, 0xFD87FB54, - 0xF65DFE59, 0x02EEF99E, 0x0166F03C, 0xFFF809B6, - 0x000008A4, 0x000AF42B, 0x00EFF577, 0xFA840BF2, - 0xFC02FF51, 0x08260F67, 0xFFF0036F, 0x0842F9C3, - 0x00000000, 0x063DF7BE, 0xFC910010, 0xF099F7DA, - 0x00AF03FE, 0xF40E057C, 0x0A89FF11, 0x0BD5FFF6, - 0xF75C0000, 0xF64A0008, 0x0FC4FE9A, 0x0662FD12, - 0x01A709A3, 0x04AC0279, 0xEEBF004E, 0xFF6300D0, - 0xF9E4F9E4, 0x00D0FF63, 0x004EEEBF, 0x027904AC, - 0x09A301A7, 0xFD120662, 0xFE9A0FC4, 0x0008F64A, - 0x0000F75C, 0xFFF60BD5, 0xFF110A89, 0x057CF40E, - 0x03FE00AF, 0xF7DAF099, 0x0010FC91, 0xF7BE063D, - 0x00000000, 0xF9C30842, 0x036FFFF0, 0x0F670826, - 0xFF51FC02, 0x0BF2FA84, 0xF57700EF, 0xF42B000A, - 0x08A40000, 0x09B6FFF8, 0xF03C0166, 0xF99E02EE, - 0xFE59F65D, 0xFB54FD87, 0x1141FFB2, 0x009DFF30, - 0x05E30000, 0xFF060705, 0x085408A0, 0xF425FC59, - 0xFA1D042A, 0xFC78F67A, 0xF7ACF60E, 0x075A0766, - 0x05E305E3, 0xF8A6F89A, 0xF7ACF60E, 0x03880986, - 0xFA1D042A, 0x0BDB03A7, 0x085408A0, 0x00FAF8FB, - 0x05E30000, 0xFF06F8FB, 0x0854F760, 0xF42503A7, - 0xFA1DFBD6, 0xFC780986, 0xF7AC09F2, 0x075AF89A, - 0x05E3FA1D, 0xF8A60766, 0xF7AC09F2, 0x0388F67A, - 0xFA1DFBD6, 0x0BDBFC59, 0x0854F760, 0x00FA0705, - 0x05E30000, 0xFF060705, 0x085408A0, 0xF425FC59, - 0xFA1D042A, 0xFC78F67A, 0xF7ACF60E, 0x075A0766, - 0x05E305E3, 0xF8A6F89A, 0xF7ACF60E, 0x03880986, - 0xFA1D042A, 0x0BDB03A7, 0x085408A0, 0x00FAF8FB, - 0x05E30000, 0xFF06F8FB, 0x0854F760, 0xF42503A7, - 0xFA1DFBD6, 0xFC780986, 0xF7AC09F2, 0x075AF89A, - 0x05E3FA1D, 0xF8A60766, 0xF7AC09F2, 0x0388F67A, - 0xFA1DFBD6, 0x0BDBFC59, 0x0854F760, 0x00FA0705, - 0xFA58FA58, 0xF8F0FE00, 0x0448073D, 0xFDC9FE46, - 0xF9910258, 0x089D0407, 0xFD5CF71A, 0x02AFFDE0, - 0x083E0496, 0xFF5A0740, 0xFF7AFD97, 0x00FE01F1, - 0x0009082E, 0xFA94FF75, 0xFECDF8EA, 0xFFB0F693, - 0xFD2CFA58, 0x0433FF16, 0xFBA405DD, 0xFA610341, - 0x06A606CB, 0x0039FD2D, 0x0677FA97, 0x01FA05E0, - 0xF896003E, 0x075A068B, 0x012CFC3E, 0xFA23F98D, - 0xFC7CFD43, 0xFF90FC0D, 0x01C10982, 0x00C601D6, - 0xFD2CFD2C, 0x01D600C6, 0x098201C1, 0xFC0DFF90, - 0xFD43FC7C, 0xF98DFA23, 0xFC3E012C, 0x068B075A, - 0x003EF896, 0x05E001FA, 0xFA970677, 0xFD2D0039, - 0x06CB06A6, 0x0341FA61, 0x05DDFBA4, 0xFF160433, - 0xFA58FD2C, 0xF693FFB0, 0xF8EAFECD, 0xFF75FA94, - 0x082E0009, 0x01F100FE, 0xFD97FF7A, 0x0740FF5A, - 0x0496083E, 0xFDE002AF, 0xF71AFD5C, 0x0407089D, - 0x0258F991, 0xFE46FDC9, 0x073D0448, 0xFE00F8F0, - 0xFD2CFD2C, 0xFCE00500, 0xFC09FDDC, 0xFE680157, - 0x04C70571, 0xFC3AFF21, 0xFCD70228, 0x056D0277, - 0x0200FE00, 0x0022F927, 0xFE3C032B, 0xFC44FF3C, - 0x03E9FBDB, 0x04570313, 0x04C9FF5C, 0x000D03B8, - 0xFA580000, 0xFBE900D2, 0xF9D0FE0B, 0x0125FDF9, - 0x042501BF, 0x0328FA2B, 0xFFA902F0, 0xFA250157, - 0x0200FE00, 0x03740438, 0xFF0405FD, 0x030CFE52, - 0x0037FB39, 0xFF6904C5, 0x04F8FD23, 0xFD31FC1B, - 0xFD2CFD2C, 0xFC1BFD31, 0xFD2304F8, 0x04C5FF69, - 0xFB390037, 0xFE52030C, 0x05FDFF04, 0x04380374, - 0xFE000200, 0x0157FA25, 0x02F0FFA9, 0xFA2B0328, - 0x01BF0425, 0xFDF90125, 0xFE0BF9D0, 0x00D2FBE9, - 0x0000FA58, 0x03B8000D, 0xFF5C04C9, 0x03130457, - 0xFBDB03E9, 0xFF3CFC44, 0x032BFE3C, 0xF9270022, - 0xFE000200, 0x0277056D, 0x0228FCD7, 0xFF21FC3A, - 0x057104C7, 0x0157FE68, 0xFDDCFC09, 0x0500FCE0, - 0xFD2CFD2C, 0x0500FCE0, 0xFDDCFC09, 0x0157FE68, - 0x057104C7, 0xFF21FC3A, 0x0228FCD7, 0x0277056D, - 0xFE000200, 0xF9270022, 0x032BFE3C, 0xFF3CFC44, - 0xFBDB03E9, 0x03130457, 0xFF5C04C9, 0x03B8000D, - 0x0000FA58, 0x00D2FBE9, 0xFE0BF9D0, 0xFDF90125, - 0x01BF0425, 0xFA2B0328, 0x02F0FFA9, 0x0157FA25, - 0xFE000200, 0x04380374, 0x05FDFF04, 0xFE52030C, - 0xFB390037, 0x04C5FF69, 0xFD2304F8, 0xFC1BFD31, - 0xFD2CFD2C, 0xFD31FC1B, 0x04F8FD23, 0xFF6904C5, - 0x0037FB39, 0x030CFE52, 0xFF0405FD, 0x03740438, - 0x0200FE00, 0xFA250157, 0xFFA902F0, 0x0328FA2B, - 0x042501BF, 0x0125FDF9, 0xF9D0FE0B, 0xFBE900D2, - 0xFA580000, 0x000D03B8, 0x04C9FF5C, 0x04570313, - 0x03E9FBDB, 0xFC44FF3C, 0xFE3C032B, 0x0022F927, - 0x0200FE00, 0x056D0277, 0xFCD70228, 0xFC3AFF21, - 0x04C70571, 0xFE680157, 0xFC09FDDC, 0xFCE00500, - 0x05A80000, 0xFF1006BE, 0x0800084A, 0xF49CFC7E, - 0xFA580400, 0xFC9CF6DA, 0xF800F672, 0x0710071C, - 0x05A805A8, 0xF8F0F8E4, 0xF800F672, 0x03640926, - 0xFA580400, 0x0B640382, 0x0800084A, 0x00F0F942, - 0x05A80000, 0xFF10F942, 0x0800F7B6, 0xF49C0382, - 0xFA58FC00, 0xFC9C0926, 0xF800098E, 0x0710F8E4, - 0x05A8FA58, 0xF8F0071C, 0xF800098E, 0x0364F6DA, - 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE, - 0x05A80000, 0xFF1006BE, 0x0800084A, 0xF49CFC7E, - 0xFA580400, 0xFC9CF6DA, 0xF800F672, 0x0710071C, - 0x05A805A8, 0xF8F0F8E4, 0xF800F672, 0x03640926, - 0xFA580400, 0x0B640382, 0x0800084A, 0x00F0F942, - 0x05A80000, 0xFF10F942, 0x0800F7B6, 0xF49C0382, - 0xFA58FC00, 0xFC9C0926, 0xF800098E, 0x0710F8E4, - 0x05A8FA58, 0xF8F0071C, 0xF800098E, 0x0364F6DA, - 0xFA58FC00, 0x0B64FC7E, 0x0800F7B6, 0x00F006BE, -}; - -const u32 b43_ntab_tmap[] = { - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0xF1111110, 0x11111111, 0x11F11111, 0x00000111, - 0x11000000, 0x1111F111, 0x11111111, 0x111111F1, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x000AA888, - 0x88880000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0xA1111110, 0x11111111, 0x11C11111, 0x00000111, - 0x11000000, 0x1111A111, 0x11111111, 0x111111A1, - 0xA2222220, 0x22222222, 0x22C22222, 0x00000222, - 0x22000000, 0x2222A222, 0x22222222, 0x222222A2, - 0xF1111110, 0x11111111, 0x11F11111, 0x00011111, - 0x11110000, 0x1111F111, 0x11111111, 0x111111F1, - 0xA8AA88A0, 0xA88888A8, 0xA8A8A88A, 0x00088AAA, - 0xAAAA0000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A, - 0xAAA8AAA0, 0x8AAA8AAA, 0xAA8A8A8A, 0x000AAA88, - 0x8AAA0000, 0xAAA8A888, 0x8AA88A8A, 0x8A88A888, - 0x08080A00, 0x0A08080A, 0x080A0A08, 0x00080808, - 0x080A0000, 0x080A0808, 0x080A0808, 0x0A0A0A08, - 0xA0A0A0A0, 0x80A0A080, 0x8080A0A0, 0x00008080, - 0x80A00000, 0x80A080A0, 0xA080A0A0, 0x8080A0A0, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x99999000, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9, - 0x9B99BB90, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00AAA888, - 0x22000000, 0x2222B222, 0x22222222, 0x222222B2, - 0xB2222220, 0x22222222, 0x22D22222, 0x00000222, - 0x11000000, 0x1111A111, 0x11111111, 0x111111A1, - 0xA1111110, 0x11111111, 0x11C11111, 0x00000111, - 0x33000000, 0x3333B333, 0x33333333, 0x333333B3, - 0xB3333330, 0x33333333, 0x33D33333, 0x00000333, - 0x22000000, 0x2222A222, 0x22222222, 0x222222A2, - 0xA2222220, 0x22222222, 0x22C22222, 0x00000222, - 0x99B99B00, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9, - 0x9B99BB99, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x08AAA888, - 0x22222200, 0x2222F222, 0x22222222, 0x222222F2, - 0x22222222, 0x22222222, 0x22F22222, 0x00000222, - 0x11000000, 0x1111F111, 0x11111111, 0x11111111, - 0xF1111111, 0x11111111, 0x11F11111, 0x01111111, - 0xBB9BB900, 0xB9B9BB99, 0xB99BBBBB, 0xBBBB9B9B, - 0xB9BB99BB, 0xB99999B9, 0xB9B9B99B, 0x00000BBB, - 0xAA000000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A, - 0xA8AA88AA, 0xA88888A8, 0xA8A8A88A, 0x0A888AAA, - 0xAA000000, 0xA8A8AA88, 0xA88AAAAA, 0xAAAA8A8A, - 0xA8AA88A0, 0xA88888A8, 0xA8A8A88A, 0x00000AAA, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0xBBBBBB00, 0x999BBBBB, 0x9BB99B9B, 0xB9B9B9BB, - 0xB9B99BBB, 0xB9B9B9BB, 0xB9BB9B99, 0x00000999, - 0x8A000000, 0xAA88A888, 0xA88888AA, 0xA88A8A88, - 0xA88AA88A, 0x88A8AAAA, 0xA8AA8AAA, 0x0888A88A, - 0x0B0B0B00, 0x090B0B0B, 0x0B090B0B, 0x0909090B, - 0x09090B0B, 0x09090B0B, 0x09090B09, 0x00000909, - 0x0A000000, 0x0A080808, 0x080A080A, 0x080A0A08, - 0x080A080A, 0x0808080A, 0x0A0A0A08, 0x0808080A, - 0xB0B0B000, 0x9090B0B0, 0x90B09090, 0xB0B0B090, - 0xB0B090B0, 0x90B0B0B0, 0xB0B09090, 0x00000090, - 0x80000000, 0xA080A080, 0xA08080A0, 0xA0808080, - 0xA080A080, 0x80A0A0A0, 0xA0A080A0, 0x00A0A0A0, - 0x22000000, 0x2222F222, 0x22222222, 0x222222F2, - 0xF2222220, 0x22222222, 0x22F22222, 0x00000222, - 0x11000000, 0x1111F111, 0x11111111, 0x111111F1, - 0xF1111110, 0x11111111, 0x11F11111, 0x00000111, - 0x33000000, 0x3333F333, 0x33333333, 0x333333F3, - 0xF3333330, 0x33333333, 0x33F33333, 0x00000333, - 0x22000000, 0x2222F222, 0x22222222, 0x222222F2, - 0xF2222220, 0x22222222, 0x22F22222, 0x00000222, - 0x99000000, 0x9B9B99BB, 0x9BB99999, 0x9999B9B9, - 0x9B99BB90, 0x9BBBBB9B, 0x9B9B9BB9, 0x00000999, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0x88888000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00AAA888, - 0x88A88A00, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA88, 0x8AAAAA8A, 0x8A8A8AA8, 0x08AAA888, - 0x11000000, 0x1111A111, 0x11111111, 0x111111A1, - 0xA1111110, 0x11111111, 0x11C11111, 0x00000111, - 0x11000000, 0x1111A111, 0x11111111, 0x111111A1, - 0xA1111110, 0x11111111, 0x11C11111, 0x00000111, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0x88000000, 0x8A8A88AA, 0x8AA88888, 0x8888A8A8, - 0x8A88AA80, 0x8AAAAA8A, 0x8A8A8AA8, 0x00000888, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, - 0x00000000, 0x00000000, 0x00000000, 0x00000000, -}; - -static inline void assert_ntab_array_sizes(void) -{ -#undef check -#define check(table, size) \ - BUILD_BUG_ON(ARRAY_SIZE(b43_ntab_##table) != B43_NTAB_##size##_SIZE) - - check(adjustpower0, C0_ADJPLT); - check(adjustpower1, C1_ADJPLT); - check(bdi, BDI); - check(channelest, CHANEST); - check(estimatepowerlt0, C0_ESTPLT); - check(estimatepowerlt1, C1_ESTPLT); - check(framelookup, FRAMELT); - check(framestruct, FRAMESTRUCT); - check(gainctl0, C0_GAINCTL); - check(gainctl1, C1_GAINCTL); - check(intlevel, INTLEVEL); - check(iqlt0, C0_IQLT); - check(iqlt1, C1_IQLT); - check(loftlt0, C0_LOFEEDTH); - check(loftlt1, C1_LOFEEDTH); - check(mcs, MCS); - check(noisevar10, NOISEVAR10); - check(noisevar11, NOISEVAR11); - check(pilot, PILOT); - check(pilotlt, PILOTLT); - check(tdi20a0, TDI20A0); - check(tdi20a1, TDI20A1); - check(tdi40a0, TDI40A0); - check(tdi40a1, TDI40A1); - check(tdtrn, TDTRN); - check(tmap, TMAP); - -#undef check -} - -void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value) -{ - u32 type; - - type = offset & B43_NTAB_TYPEMASK; - offset &= 0xFFFF; - - switch (type) { - case B43_NTAB_8BIT: - B43_WARN_ON(value & ~0xFF); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value); - break; - case B43_NTAB_16BIT: - B43_WARN_ON(value & ~0xFFFF); - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value); - break; - case B43_NTAB_32BIT: - b43_phy_write(dev, B43_NPHY_TABLE_ADDR, offset); - b43_phy_write(dev, B43_NPHY_TABLE_DATAHI, value >> 16); - b43_phy_write(dev, B43_NPHY_TABLE_DATALO, value & 0xFFFF); - break; - default: - B43_WARN_ON(1); - } - - return; - - /* Some compiletime assertions... */ - assert_ntab_array_sizes(); -} diff --git a/drivers/net/wireless/b43/tables_nphy.h b/drivers/net/wireless/b43/tables_nphy.h deleted file mode 100644 index 4d498b053ec7..000000000000 --- a/drivers/net/wireless/b43/tables_nphy.h +++ /dev/null @@ -1,159 +0,0 @@ -#ifndef B43_TABLES_NPHY_H_ -#define B43_TABLES_NPHY_H_ - -#include - - -struct b43_nphy_channeltab_entry { - /* The channel number */ - u8 channel; - /* Radio register values on channelswitch */ - u8 radio_pll_ref; - u8 radio_rf_pllmod0; - u8 radio_rf_pllmod1; - u8 radio_vco_captail; - u8 radio_vco_cal1; - u8 radio_vco_cal2; - u8 radio_pll_lfc1; - u8 radio_pll_lfr1; - u8 radio_pll_lfc2; - u8 radio_lgbuf_cenbuf; - u8 radio_lgen_tune1; - u8 radio_lgen_tune2; - u8 radio_c1_lgbuf_atune; - u8 radio_c1_lgbuf_gtune; - u8 radio_c1_rx_rfr1; - u8 radio_c1_tx_pgapadtn; - u8 radio_c1_tx_mxbgtrim; - u8 radio_c2_lgbuf_atune; - u8 radio_c2_lgbuf_gtune; - u8 radio_c2_rx_rfr1; - u8 radio_c2_tx_pgapadtn; - u8 radio_c2_tx_mxbgtrim; - /* PHY register values on channelswitch */ - u16 phy_bw1a; - u16 phy_bw2; - u16 phy_bw3; - u16 phy_bw4; - u16 phy_bw5; - u16 phy_bw6; - /* The channel frequency in MHz */ - u16 freq; - /* An unknown value */ - u16 unk2; -}; - - -struct b43_wldev; - -/* Upload the default register value table. - * If "ghz5" is true, we upload the 5Ghz table. Otherwise the 2.4Ghz - * table is uploaded. If "ignore_uploadflag" is true, we upload any value - * and ignore the "UPLOAD" flag. */ -void b2055_upload_inittab(struct b43_wldev *dev, - bool ghz5, bool ignore_uploadflag); - - -/* Get the NPHY Channel Switch Table entry for a channel number. - * Returns NULL on failure to find an entry. */ -const struct b43_nphy_channeltab_entry * -b43_nphy_get_chantabent(struct b43_wldev *dev, u8 channel); - - -/* The N-PHY tables. */ - -#define B43_NTAB_TYPEMASK 0xF0000000 -#define B43_NTAB_8BIT 0x10000000 -#define B43_NTAB_16BIT 0x20000000 -#define B43_NTAB_32BIT 0x30000000 -#define B43_NTAB8(table, offset) (((table) << 10) | (offset) | B43_NTAB_8BIT) -#define B43_NTAB16(table, offset) (((table) << 10) | (offset) | B43_NTAB_16BIT) -#define B43_NTAB32(table, offset) (((table) << 10) | (offset) | B43_NTAB_32BIT) - -/* Static N-PHY tables */ -#define B43_NTAB_FRAMESTRUCT B43_NTAB32(0x0A, 0x000) /* Frame Struct Table */ -#define B43_NTAB_FRAMESTRUCT_SIZE 832 -#define B43_NTAB_FRAMELT B43_NTAB8 (0x18, 0x000) /* Frame Lookup Table */ -#define B43_NTAB_FRAMELT_SIZE 32 -#define B43_NTAB_TMAP B43_NTAB32(0x0C, 0x000) /* T Map Table */ -#define B43_NTAB_TMAP_SIZE 448 -#define B43_NTAB_TDTRN B43_NTAB32(0x0E, 0x000) /* TDTRN Table */ -#define B43_NTAB_TDTRN_SIZE 704 -#define B43_NTAB_INTLEVEL B43_NTAB32(0x0D, 0x000) /* Int Level Table */ -#define B43_NTAB_INTLEVEL_SIZE 7 -#define B43_NTAB_PILOT B43_NTAB16(0x0B, 0x000) /* Pilot Table */ -#define B43_NTAB_PILOT_SIZE 88 -#define B43_NTAB_PILOTLT B43_NTAB32(0x14, 0x000) /* Pilot Lookup Table */ -#define B43_NTAB_PILOTLT_SIZE 6 -#define B43_NTAB_TDI20A0 B43_NTAB32(0x13, 0x080) /* TDI Table 20 Antenna 0 */ -#define B43_NTAB_TDI20A0_SIZE 55 -#define B43_NTAB_TDI20A1 B43_NTAB32(0x13, 0x100) /* TDI Table 20 Antenna 1 */ -#define B43_NTAB_TDI20A1_SIZE 55 -#define B43_NTAB_TDI40A0 B43_NTAB32(0x13, 0x280) /* TDI Table 40 Antenna 0 */ -#define B43_NTAB_TDI40A0_SIZE 110 -#define B43_NTAB_TDI40A1 B43_NTAB32(0x13, 0x300) /* TDI Table 40 Antenna 1 */ -#define B43_NTAB_TDI40A1_SIZE 110 -#define B43_NTAB_BDI B43_NTAB16(0x15, 0x000) /* BDI Table */ -#define B43_NTAB_BDI_SIZE 6 -#define B43_NTAB_CHANEST B43_NTAB32(0x16, 0x000) /* Channel Estimate Table */ -#define B43_NTAB_CHANEST_SIZE 96 -#define B43_NTAB_MCS B43_NTAB8 (0x12, 0x000) /* MCS Table */ -#define B43_NTAB_MCS_SIZE 128 - -/* Volatile N-PHY tables */ -#define B43_NTAB_NOISEVAR10 B43_NTAB32(0x10, 0x000) /* Noise Var Table 10 */ -#define B43_NTAB_NOISEVAR10_SIZE 256 -#define B43_NTAB_NOISEVAR11 B43_NTAB32(0x10, 0x080) /* Noise Var Table 11 */ -#define B43_NTAB_NOISEVAR11_SIZE 256 -#define B43_NTAB_C0_ESTPLT B43_NTAB8 (0x1A, 0x000) /* Estimate Power Lookup Table Core 0 */ -#define B43_NTAB_C0_ESTPLT_SIZE 64 -#define B43_NTAB_C1_ESTPLT B43_NTAB8 (0x1B, 0x000) /* Estimate Power Lookup Table Core 1 */ -#define B43_NTAB_C1_ESTPLT_SIZE 64 -#define B43_NTAB_C0_ADJPLT B43_NTAB8 (0x1A, 0x040) /* Adjust Power Lookup Table Core 0 */ -#define B43_NTAB_C0_ADJPLT_SIZE 128 -#define B43_NTAB_C1_ADJPLT B43_NTAB8 (0x1B, 0x040) /* Adjust Power Lookup Table Core 1 */ -#define B43_NTAB_C1_ADJPLT_SIZE 128 -#define B43_NTAB_C0_GAINCTL B43_NTAB32(0x1A, 0x0C0) /* Gain Control Lookup Table Core 0 */ -#define B43_NTAB_C0_GAINCTL_SIZE 128 -#define B43_NTAB_C1_GAINCTL B43_NTAB32(0x1B, 0x0C0) /* Gain Control Lookup Table Core 1 */ -#define B43_NTAB_C1_GAINCTL_SIZE 128 -#define B43_NTAB_C0_IQLT B43_NTAB32(0x1A, 0x140) /* IQ Lookup Table Core 0 */ -#define B43_NTAB_C0_IQLT_SIZE 128 -#define B43_NTAB_C1_IQLT B43_NTAB32(0x1B, 0x140) /* IQ Lookup Table Core 1 */ -#define B43_NTAB_C1_IQLT_SIZE 128 -#define B43_NTAB_C0_LOFEEDTH B43_NTAB16(0x1A, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 0 */ -#define B43_NTAB_C0_LOFEEDTH_SIZE 128 -#define B43_NTAB_C1_LOFEEDTH B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */ -#define B43_NTAB_C1_LOFEEDTH_SIZE 128 - -void b43_ntab_write(struct b43_wldev *dev, u32 offset, u32 value); - -extern const u8 b43_ntab_adjustpower0[]; -extern const u8 b43_ntab_adjustpower1[]; -extern const u16 b43_ntab_bdi[]; -extern const u32 b43_ntab_channelest[]; -extern const u8 b43_ntab_estimatepowerlt0[]; -extern const u8 b43_ntab_estimatepowerlt1[]; -extern const u8 b43_ntab_framelookup[]; -extern const u32 b43_ntab_framestruct[]; -extern const u32 b43_ntab_gainctl0[]; -extern const u32 b43_ntab_gainctl1[]; -extern const u32 b43_ntab_intlevel[]; -extern const u32 b43_ntab_iqlt0[]; -extern const u32 b43_ntab_iqlt1[]; -extern const u16 b43_ntab_loftlt0[]; -extern const u16 b43_ntab_loftlt1[]; -extern const u8 b43_ntab_mcs[]; -extern const u32 b43_ntab_noisevar10[]; -extern const u32 b43_ntab_noisevar11[]; -extern const u16 b43_ntab_pilot[]; -extern const u32 b43_ntab_pilotlt[]; -extern const u32 b43_ntab_tdi20a0[]; -extern const u32 b43_ntab_tdi20a1[]; -extern const u32 b43_ntab_tdi40a0[]; -extern const u32 b43_ntab_tdi40a1[]; -extern const u32 b43_ntab_tdtrn[]; -extern const u32 b43_ntab_tmap[]; - - -#endif /* B43_TABLES_NPHY_H_ */ diff --git a/drivers/net/wireless/b43/wa.c b/drivers/net/wireless/b43/wa.c deleted file mode 100644 index 97c79161c208..000000000000 --- a/drivers/net/wireless/b43/wa.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - - Broadcom B43 wireless driver - - PHY workarounds. - - Copyright (c) 2005-2007 Stefano Brivio - Copyright (c) 2005-2007 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43.h" -#include "main.h" -#include "tables.h" -#include "phy_common.h" -#include "wa.h" - -static void b43_wa_papd(struct b43_wldev *dev) -{ - u16 backup; - - backup = b43_ofdmtab_read16(dev, B43_OFDMTAB_PWRDYN2, 0); - b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, 7); - b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 0, 0); - b43_dummy_transmission(dev, true, true); - b43_ofdmtab_write16(dev, B43_OFDMTAB_PWRDYN2, 0, backup); -} - -static void b43_wa_auxclipthr(struct b43_wldev *dev) -{ - b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x3800); -} - -static void b43_wa_afcdac(struct b43_wldev *dev) -{ - b43_phy_write(dev, 0x0035, 0x03FF); - b43_phy_write(dev, 0x0036, 0x0400); -} - -static void b43_wa_txdc_offset(struct b43_wldev *dev) -{ - b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 0, 0x0051); -} - -void b43_wa_initgains(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - b43_phy_write(dev, B43_PHY_LNAHPFCTL, 0x1FF9); - b43_phy_mask(dev, B43_PHY_LPFGAINCTL, 0xFF0F); - if (phy->rev <= 2) - b43_ofdmtab_write16(dev, B43_OFDMTAB_LPFGAIN, 0, 0x1FBF); - b43_radio_write16(dev, 0x0002, 0x1FBF); - - b43_phy_write(dev, 0x0024, 0x4680); - b43_phy_write(dev, 0x0020, 0x0003); - b43_phy_write(dev, 0x001D, 0x0F40); - b43_phy_write(dev, 0x001F, 0x1C00); - if (phy->rev <= 3) - b43_phy_maskset(dev, 0x002A, 0x00FF, 0x0400); - else if (phy->rev == 5) { - b43_phy_maskset(dev, 0x002A, 0x00FF, 0x1A00); - b43_phy_write(dev, 0x00CC, 0x2121); - } - if (phy->rev >= 3) - b43_phy_write(dev, 0x00BA, 0x3ED5); -} - -static void b43_wa_divider(struct b43_wldev *dev) -{ - b43_phy_mask(dev, 0x002B, ~0x0100); - b43_phy_write(dev, 0x008E, 0x58C1); -} - -static void b43_wa_gt(struct b43_wldev *dev) /* Gain table. */ -{ - if (dev->phy.rev <= 2) { - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 0, 15); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 1, 31); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 2, 42); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 3, 48); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN2, 4, 58); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 0, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 1, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 2, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 3, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 4, 21); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 5, 21); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 6, 25); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 0, 3); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 1, 3); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN1, 2, 7); - } else { - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 0, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 1, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 2, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 3, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 4, 21); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 5, 21); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAIN0, 6, 25); - } -} - -static void b43_wa_rssi_lt(struct b43_wldev *dev) /* RSSI lookup table */ -{ - int i; - - if (0 /* FIXME: For APHY.rev=2 this might be needed */) { - for (i = 0; i < 8; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i + 8); - for (i = 8; i < 16; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i - 8); - } else { - for (i = 0; i < 64; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i); - } -} - -static void b43_wa_analog(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - u16 ofdmrev; - - ofdmrev = b43_phy_read(dev, B43_PHY_VERSION_OFDM) & B43_PHYVER_VERSION; - if (ofdmrev > 2) { - if (phy->type == B43_PHYTYPE_A) - b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1808); - else - b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1000); - } else { - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 3, 0x1044); - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 4, 0x7201); - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 6, 0x0040); - } -} - -static void b43_wa_dac(struct b43_wldev *dev) -{ - if (dev->phy.analog == 1) - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1, - (b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 1) & ~0x0034) | 0x0008); - else - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1, - (b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 1) & ~0x0078) | 0x0010); -} - -static void b43_wa_fft(struct b43_wldev *dev) /* Fine frequency table */ -{ - int i; - - if (dev->phy.type == B43_PHYTYPE_A) - for (i = 0; i < B43_TAB_FINEFREQA_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i, b43_tab_finefreqa[i]); - else - for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i, b43_tab_finefreqg[i]); -} - -static void b43_wa_nft(struct b43_wldev *dev) /* Noise figure table */ -{ - struct b43_phy *phy = &dev->phy; - int i; - - if (phy->type == B43_PHYTYPE_A) { - if (phy->rev == 2) - for (i = 0; i < B43_TAB_NOISEA2_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noisea2[i]); - else - for (i = 0; i < B43_TAB_NOISEA3_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noisea3[i]); - } else { - if (phy->rev == 1) - for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noiseg1[i]); - else - for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i, b43_tab_noiseg2[i]); - } -} - -static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */ -{ - int i; - - for (i = 0; i < B43_TAB_ROTOR_SIZE; i++) - b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]); -} - -static void b43_write_null_nst(struct b43_wldev *dev) -{ - int i; - - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, 0); -} - -static void b43_write_nst(struct b43_wldev *dev, const u16 *nst) -{ - int i; - - for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++) - b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]); -} - -static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */ -{ - struct b43_phy *phy = &dev->phy; - - if (phy->type == B43_PHYTYPE_A) { - if (phy->rev <= 1) - b43_write_null_nst(dev); - else if (phy->rev == 2) - b43_write_nst(dev, b43_tab_noisescalea2); - else if (phy->rev == 3) - b43_write_nst(dev, b43_tab_noisescalea3); - else - b43_write_nst(dev, b43_tab_noisescaleg3); - } else { - if (phy->rev >= 6) { - if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN) - b43_write_nst(dev, b43_tab_noisescaleg3); - else - b43_write_nst(dev, b43_tab_noisescaleg2); - } else { - b43_write_nst(dev, b43_tab_noisescaleg1); - } - } -} - -static void b43_wa_art(struct b43_wldev *dev) /* ADV retard table */ -{ - int i; - - for (i = 0; i < B43_TAB_RETARD_SIZE; i++) - b43_ofdmtab_write32(dev, B43_OFDMTAB_ADVRETARD, - i, b43_tab_retard[i]); -} - -static void b43_wa_txlna_gain(struct b43_wldev *dev) -{ - b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 13, 0x0000); -} - -static void b43_wa_crs_reset(struct b43_wldev *dev) -{ - b43_phy_write(dev, 0x002C, 0x0064); -} - -static void b43_wa_2060txlna_gain(struct b43_wldev *dev) -{ - b43_hf_write(dev, b43_hf_read(dev) | - B43_HF_2060W); -} - -static void b43_wa_lms(struct b43_wldev *dev) -{ - b43_phy_maskset(dev, 0x0055, 0xFFC0, 0x0004); -} - -static void b43_wa_mixedsignal(struct b43_wldev *dev) -{ - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 1, 3); -} - -static void b43_wa_msst(struct b43_wldev *dev) /* Min sigma square table */ -{ - struct b43_phy *phy = &dev->phy; - int i; - const u16 *tab; - - if (phy->type == B43_PHYTYPE_A) { - tab = b43_tab_sigmasqr1; - } else if (phy->type == B43_PHYTYPE_G) { - tab = b43_tab_sigmasqr2; - } else { - B43_WARN_ON(1); - return; - } - - for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) { - b43_ofdmtab_write16(dev, B43_OFDMTAB_MINSIGSQ, - i, tab[i]); - } -} - -static void b43_wa_iqadc(struct b43_wldev *dev) -{ - if (dev->phy.analog == 4) - b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 0, - b43_ofdmtab_read16(dev, B43_OFDMTAB_DAC, 0) & ~0xF000); -} - -static void b43_wa_crs_ed(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->rev == 1) { - b43_phy_write(dev, B43_PHY_CRSTHRES1_R1, 0x4F19); - } else if (phy->rev == 2) { - b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x1861); - b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0271); - b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800); - } else { - b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x0098); - b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0070); - b43_phy_write(dev, B43_PHY_OFDM(0xC9), 0x0080); - b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800); - } -} - -static void b43_wa_crs_thr(struct b43_wldev *dev) -{ - b43_phy_maskset(dev, B43_PHY_CRS0, ~0x03C0, 0xD000); -} - -static void b43_wa_crs_blank(struct b43_wldev *dev) -{ - b43_phy_write(dev, B43_PHY_OFDM(0x2C), 0x005A); -} - -static void b43_wa_cck_shiftbits(struct b43_wldev *dev) -{ - b43_phy_write(dev, B43_PHY_CCKSHIFTBITS, 0x0026); -} - -static void b43_wa_wrssi_offset(struct b43_wldev *dev) -{ - int i; - - if (dev->phy.rev == 1) { - for (i = 0; i < 16; i++) { - b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI_R1, - i, 0x0020); - } - } else { - for (i = 0; i < 32; i++) { - b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI, - i, 0x0820); - } - } -} - -static void b43_wa_txpuoff_rxpuon(struct b43_wldev *dev) -{ - b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 2, 15); - b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 3, 20); -} - -static void b43_wa_altagc(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->rev == 1) { - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 254); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 1, 13); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 2, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 3, 25); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 0, 0x2710); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 1, 0x9B83); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 2, 0x9B83); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 3, 0x0F8D); - b43_phy_write(dev, B43_PHY_LMS, 4); - } else { - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0, 254); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 1, 13); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 2, 19); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25); - } - - b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, (u16)~0xFF00, 0x5700); - b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F); - b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80); - b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300); - b43_radio_set(dev, 0x7A, 0x0008); - b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x000F, 0x0008); - b43_phy_maskset(dev, B43_PHY_P1P2GAIN, ~0x0F00, 0x0600); - b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x0F00, 0x0700); - b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x0F00, 0x0100); - if (phy->rev == 1) { - b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x000F, 0x0007); - } - b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x00FF, 0x001C); - b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x3F00, 0x0200); - b43_phy_maskset(dev, B43_PHY_OFDM(0x96), ~0x00FF, 0x001C); - b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020); - b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200); - b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E); - b43_phy_maskset(dev, B43_PHY_OFDM(0x96), (u16)~0xFF00, 0x1A00); - b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028); - b43_phy_maskset(dev, B43_PHY_OFDM(0x81), (u16)~0xFF00, 0x2C00); - if (phy->rev == 1) { - b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B); - b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002); - } else { - b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x001E); - b43_phy_write(dev, B43_PHY_OFDM(0x1F), 0x287A); - b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004); - if (phy->rev >= 6) { - b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A); - b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, (u16)~0xF000, 0x3000); - } - } - b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874); - b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x1C00); - if (phy->rev == 1) { - b43_phy_maskset(dev, B43_PHY_DIVP1P2GAIN, ~0x0F00, 0x0600); - b43_phy_write(dev, B43_PHY_OFDM(0x8B), 0x005E); - b43_phy_maskset(dev, B43_PHY_ANTWRSETT, ~0x00FF, 0x001E); - b43_phy_write(dev, B43_PHY_OFDM(0x8D), 0x0002); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 0, 0); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 1, 7); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 2, 16); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 3, 28); - } else { - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 0, 0); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 1, 7); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 2, 16); - b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 3, 28); - } - if (phy->rev >= 6) { - b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x0003); - b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x1000); - } - b43_phy_read(dev, B43_PHY_VERSION_OFDM); /* Dummy read */ -} - -static void b43_wa_tr_ltov(struct b43_wldev *dev) /* TR Lookup Table Original Values */ -{ - b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0xC480); -} - -static void b43_wa_cpll_nonpilot(struct b43_wldev *dev) -{ - b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 0, 0); - b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 1, 0); -} - -static void b43_wa_rssi_adc(struct b43_wldev *dev) -{ - if (dev->phy.analog == 4) - b43_phy_write(dev, 0x00DC, 0x7454); -} - -static void b43_wa_boards_a(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - - if (bus->boardinfo.vendor == SSB_BOARDVENDOR_BCM && - bus->boardinfo.type == SSB_BOARD_BU4306 && - bus->boardinfo.rev < 0x30) { - b43_phy_write(dev, 0x0010, 0xE000); - b43_phy_write(dev, 0x0013, 0x0140); - b43_phy_write(dev, 0x0014, 0x0280); - } else { - if (bus->boardinfo.type == SSB_BOARD_MP4318 && - bus->boardinfo.rev < 0x20) { - b43_phy_write(dev, 0x0013, 0x0210); - b43_phy_write(dev, 0x0014, 0x0840); - } else { - b43_phy_write(dev, 0x0013, 0x0140); - b43_phy_write(dev, 0x0014, 0x0280); - } - if (dev->phy.rev <= 4) - b43_phy_write(dev, 0x0010, 0xE000); - else - b43_phy_write(dev, 0x0010, 0x2000); - b43_ofdmtab_write16(dev, B43_OFDMTAB_DC, 1, 0x0039); - b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_APHY, 7, 0x0040); - } -} - -static void b43_wa_boards_g(struct b43_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct b43_phy *phy = &dev->phy; - - if (bus->boardinfo.vendor != SSB_BOARDVENDOR_BCM || - bus->boardinfo.type != SSB_BOARD_BU4306 || - bus->boardinfo.rev != 0x17) { - if (phy->rev < 2) { - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001); - } else { - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001); - if ((bus->sprom.boardflags_lo & B43_BFL_EXTLNA) && - (phy->rev >= 7)) { - b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0021, 0x0001); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0022, 0x0001); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0023, 0x0000); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0000, 0x0000); - b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0003, 0x0002); - } - } - } - if (bus->sprom.boardflags_lo & B43_BFL_FEM) { - b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120); - b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480); - } -} - -void b43_wa_all(struct b43_wldev *dev) -{ - struct b43_phy *phy = &dev->phy; - - if (phy->type == B43_PHYTYPE_A) { - switch (phy->rev) { - case 2: - b43_wa_papd(dev); - b43_wa_auxclipthr(dev); - b43_wa_afcdac(dev); - b43_wa_txdc_offset(dev); - b43_wa_initgains(dev); - b43_wa_divider(dev); - b43_wa_gt(dev); - b43_wa_rssi_lt(dev); - b43_wa_analog(dev); - b43_wa_dac(dev); - b43_wa_fft(dev); - b43_wa_nft(dev); - b43_wa_rt(dev); - b43_wa_nst(dev); - b43_wa_art(dev); - b43_wa_txlna_gain(dev); - b43_wa_crs_reset(dev); - b43_wa_2060txlna_gain(dev); - b43_wa_lms(dev); - break; - case 3: - b43_wa_papd(dev); - b43_wa_mixedsignal(dev); - b43_wa_rssi_lt(dev); - b43_wa_txdc_offset(dev); - b43_wa_initgains(dev); - b43_wa_dac(dev); - b43_wa_nft(dev); - b43_wa_nst(dev); - b43_wa_msst(dev); - b43_wa_analog(dev); - b43_wa_gt(dev); - b43_wa_txpuoff_rxpuon(dev); - b43_wa_txlna_gain(dev); - break; - case 5: - b43_wa_iqadc(dev); - case 6: - b43_wa_papd(dev); - b43_wa_rssi_lt(dev); - b43_wa_txdc_offset(dev); - b43_wa_initgains(dev); - b43_wa_dac(dev); - b43_wa_nft(dev); - b43_wa_nst(dev); - b43_wa_msst(dev); - b43_wa_analog(dev); - b43_wa_gt(dev); - b43_wa_txpuoff_rxpuon(dev); - b43_wa_txlna_gain(dev); - break; - case 7: - b43_wa_iqadc(dev); - b43_wa_papd(dev); - b43_wa_rssi_lt(dev); - b43_wa_txdc_offset(dev); - b43_wa_initgains(dev); - b43_wa_dac(dev); - b43_wa_nft(dev); - b43_wa_nst(dev); - b43_wa_msst(dev); - b43_wa_analog(dev); - b43_wa_gt(dev); - b43_wa_txpuoff_rxpuon(dev); - b43_wa_txlna_gain(dev); - b43_wa_rssi_adc(dev); - default: - B43_WARN_ON(1); - } - b43_wa_boards_a(dev); - } else if (phy->type == B43_PHYTYPE_G) { - switch (phy->rev) { - case 1://XXX review rev1 - b43_wa_crs_ed(dev); - b43_wa_crs_thr(dev); - b43_wa_crs_blank(dev); - b43_wa_cck_shiftbits(dev); - b43_wa_fft(dev); - b43_wa_nft(dev); - b43_wa_rt(dev); - b43_wa_nst(dev); - b43_wa_art(dev); - b43_wa_wrssi_offset(dev); - b43_wa_altagc(dev); - break; - case 2: - case 6: - case 7: - case 8: - case 9: - b43_wa_tr_ltov(dev); - b43_wa_crs_ed(dev); - b43_wa_rssi_lt(dev); - b43_wa_nft(dev); - b43_wa_nst(dev); - b43_wa_msst(dev); - b43_wa_wrssi_offset(dev); - b43_wa_altagc(dev); - b43_wa_analog(dev); - b43_wa_txpuoff_rxpuon(dev); - break; - default: - B43_WARN_ON(1); - } - b43_wa_boards_g(dev); - } else { /* No N PHY support so far, LP PHY is in phy_lp.c */ - B43_WARN_ON(1); - } - - b43_wa_cpll_nonpilot(dev); -} diff --git a/drivers/net/wireless/b43/wa.h b/drivers/net/wireless/b43/wa.h deleted file mode 100644 index e163c5e56e81..000000000000 --- a/drivers/net/wireless/b43/wa.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef B43_WA_H_ -#define B43_WA_H_ - -void b43_wa_initgains(struct b43_wldev *dev); -void b43_wa_all(struct b43_wldev *dev); - -#endif /* B43_WA_H_ */ diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c deleted file mode 100644 index 51d68971f6fa..000000000000 --- a/drivers/net/wireless/b43/xmit.c +++ /dev/null @@ -1,803 +0,0 @@ -/* - - Broadcom B43 wireless driver - - Transmission (TX/RX) related functions. - - Copyright (C) 2005 Martin Langer - Copyright (C) 2005 Stefano Brivio - Copyright (C) 2005, 2006 Michael Buesch - Copyright (C) 2005 Danny van Dyk - Copyright (C) 2005 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "xmit.h" -#include "phy_common.h" -#include "dma.h" -#include "pio.h" - - -/* Extract the bitrate index out of a CCK PLCP header. */ -static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp) -{ - switch (plcp->raw[0]) { - case 0x0A: - return 0; - case 0x14: - return 1; - case 0x37: - return 2; - case 0x6E: - return 3; - } - return -1; -} - -/* Extract the bitrate index out of an OFDM PLCP header. */ -static int b43_plcp_get_bitrate_idx_ofdm(struct b43_plcp_hdr6 *plcp, bool aphy) -{ - int base = aphy ? 0 : 4; - - switch (plcp->raw[0] & 0xF) { - case 0xB: - return base + 0; - case 0xF: - return base + 1; - case 0xA: - return base + 2; - case 0xE: - return base + 3; - case 0x9: - return base + 4; - case 0xD: - return base + 5; - case 0x8: - return base + 6; - case 0xC: - return base + 7; - } - return -1; -} - -u8 b43_plcp_get_ratecode_cck(const u8 bitrate) -{ - switch (bitrate) { - case B43_CCK_RATE_1MB: - return 0x0A; - case B43_CCK_RATE_2MB: - return 0x14; - case B43_CCK_RATE_5MB: - return 0x37; - case B43_CCK_RATE_11MB: - return 0x6E; - } - B43_WARN_ON(1); - return 0; -} - -u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate) -{ - switch (bitrate) { - case B43_OFDM_RATE_6MB: - return 0xB; - case B43_OFDM_RATE_9MB: - return 0xF; - case B43_OFDM_RATE_12MB: - return 0xA; - case B43_OFDM_RATE_18MB: - return 0xE; - case B43_OFDM_RATE_24MB: - return 0x9; - case B43_OFDM_RATE_36MB: - return 0xD; - case B43_OFDM_RATE_48MB: - return 0x8; - case B43_OFDM_RATE_54MB: - return 0xC; - } - B43_WARN_ON(1); - return 0; -} - -void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate) -{ - __u8 *raw = plcp->raw; - - if (b43_is_ofdm_rate(bitrate)) { - u32 d; - - d = b43_plcp_get_ratecode_ofdm(bitrate); - B43_WARN_ON(octets & 0xF000); - d |= (octets << 5); - plcp->data = cpu_to_le32(d); - } else { - u32 plen; - - plen = octets * 16 / bitrate; - if ((octets * 16 % bitrate) > 0) { - plen++; - if ((bitrate == B43_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) { - raw[1] = 0x84; - } else - raw[1] = 0x04; - } else - raw[1] = 0x04; - plcp->data |= cpu_to_le32(plen << 16); - raw[0] = b43_plcp_get_ratecode_cck(bitrate); - } -} - -static u8 b43_calc_fallback_rate(u8 bitrate) -{ - switch (bitrate) { - case B43_CCK_RATE_1MB: - return B43_CCK_RATE_1MB; - case B43_CCK_RATE_2MB: - return B43_CCK_RATE_1MB; - case B43_CCK_RATE_5MB: - return B43_CCK_RATE_2MB; - case B43_CCK_RATE_11MB: - return B43_CCK_RATE_5MB; - case B43_OFDM_RATE_6MB: - return B43_CCK_RATE_5MB; - case B43_OFDM_RATE_9MB: - return B43_OFDM_RATE_6MB; - case B43_OFDM_RATE_12MB: - return B43_OFDM_RATE_9MB; - case B43_OFDM_RATE_18MB: - return B43_OFDM_RATE_12MB; - case B43_OFDM_RATE_24MB: - return B43_OFDM_RATE_18MB; - case B43_OFDM_RATE_36MB: - return B43_OFDM_RATE_24MB; - case B43_OFDM_RATE_48MB: - return B43_OFDM_RATE_36MB; - case B43_OFDM_RATE_54MB: - return B43_OFDM_RATE_48MB; - } - B43_WARN_ON(1); - return 0; -} - -/* Generate a TX data header. */ -int b43_generate_txhdr(struct b43_wldev *dev, - u8 *_txhdr, - struct sk_buff *skb_frag, - struct ieee80211_tx_info *info, - u16 cookie) -{ - const unsigned char *fragment_data = skb_frag->data; - unsigned int fragment_len = skb_frag->len; - struct b43_txhdr *txhdr = (struct b43_txhdr *)_txhdr; - const struct b43_phy *phy = &dev->phy; - const struct ieee80211_hdr *wlhdr = - (const struct ieee80211_hdr *)fragment_data; - int use_encryption = !!info->control.hw_key; - __le16 fctl = wlhdr->frame_control; - struct ieee80211_rate *fbrate; - u8 rate, rate_fb; - int rate_ofdm, rate_fb_ofdm; - unsigned int plcp_fragment_len; - u32 mac_ctl = 0; - u16 phy_ctl = 0; - u8 extra_ft = 0; - struct ieee80211_rate *txrate; - struct ieee80211_tx_rate *rates; - - memset(txhdr, 0, sizeof(*txhdr)); - - txrate = ieee80211_get_tx_rate(dev->wl->hw, info); - rate = txrate ? txrate->hw_value : B43_CCK_RATE_1MB; - rate_ofdm = b43_is_ofdm_rate(rate); - fbrate = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : txrate; - rate_fb = fbrate->hw_value; - rate_fb_ofdm = b43_is_ofdm_rate(rate_fb); - - if (rate_ofdm) - txhdr->phy_rate = b43_plcp_get_ratecode_ofdm(rate); - else - txhdr->phy_rate = b43_plcp_get_ratecode_cck(rate); - txhdr->mac_frame_ctl = wlhdr->frame_control; - memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); - - /* Calculate duration for fallback rate */ - if ((rate_fb == rate) || - (wlhdr->duration_id & cpu_to_le16(0x8000)) || - (wlhdr->duration_id == cpu_to_le16(0))) { - /* If the fallback rate equals the normal rate or the - * dur_id field contains an AID, CFP magic or 0, - * use the original dur_id field. */ - txhdr->dur_fb = wlhdr->duration_id; - } else { - txhdr->dur_fb = ieee80211_generic_frame_duration( - dev->wl->hw, info->control.vif, fragment_len, fbrate); - } - - plcp_fragment_len = fragment_len + FCS_LEN; - if (use_encryption) { - u8 key_idx = info->control.hw_key->hw_key_idx; - struct b43_key *key; - int wlhdr_len; - size_t iv_len; - - B43_WARN_ON(key_idx >= ARRAY_SIZE(dev->key)); - key = &(dev->key[key_idx]); - - if (unlikely(!key->keyconf)) { - /* This key is invalid. This might only happen - * in a short timeframe after machine resume before - * we were able to reconfigure keys. - * Drop this packet completely. Do not transmit it - * unencrypted to avoid leaking information. */ - return -ENOKEY; - } - - /* Hardware appends ICV. */ - plcp_fragment_len += info->control.hw_key->icv_len; - - key_idx = b43_kidx_to_fw(dev, key_idx); - mac_ctl |= (key_idx << B43_TXH_MAC_KEYIDX_SHIFT) & - B43_TXH_MAC_KEYIDX; - mac_ctl |= (key->algorithm << B43_TXH_MAC_KEYALG_SHIFT) & - B43_TXH_MAC_KEYALG; - wlhdr_len = ieee80211_hdrlen(fctl); - if (key->algorithm == B43_SEC_ALGO_TKIP) { - u16 phase1key[5]; - int i; - /* we give the phase1key and iv16 here, the key is stored in - * shm. With that the hardware can do phase 2 and encryption. - */ - ieee80211_get_tkip_key(info->control.hw_key, skb_frag, - IEEE80211_TKIP_P1_KEY, (u8*)phase1key); - /* phase1key is in host endian. Copy to little-endian txhdr->iv. */ - for (i = 0; i < 5; i++) { - txhdr->iv[i * 2 + 0] = phase1key[i]; - txhdr->iv[i * 2 + 1] = phase1key[i] >> 8; - } - /* iv16 */ - memcpy(txhdr->iv + 10, ((u8 *) wlhdr) + wlhdr_len, 3); - } else { - iv_len = min((size_t) info->control.hw_key->iv_len, - ARRAY_SIZE(txhdr->iv)); - memcpy(txhdr->iv, ((u8 *) wlhdr) + wlhdr_len, iv_len); - } - } - if (b43_is_old_txhdr_format(dev)) { - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->old_format.plcp), - plcp_fragment_len, rate); - } else { - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->new_format.plcp), - plcp_fragment_len, rate); - } - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)(&txhdr->plcp_fb), - plcp_fragment_len, rate_fb); - - /* Extra Frame Types */ - if (rate_fb_ofdm) - extra_ft |= B43_TXH_EFT_FB_OFDM; - else - extra_ft |= B43_TXH_EFT_FB_CCK; - - /* Set channel radio code. Note that the micrcode ORs 0x100 to - * this value before comparing it to the value in SHM, if this - * is a 5Ghz packet. - */ - txhdr->chan_radio_code = phy->channel; - - /* PHY TX Control word */ - if (rate_ofdm) - phy_ctl |= B43_TXH_PHY_ENC_OFDM; - else - phy_ctl |= B43_TXH_PHY_ENC_CCK; - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - phy_ctl |= B43_TXH_PHY_SHORTPRMBL; - - switch (b43_ieee80211_antenna_sanitize(dev, info->antenna_sel_tx)) { - case 0: /* Default */ - phy_ctl |= B43_TXH_PHY_ANT01AUTO; - break; - case 1: /* Antenna 0 */ - phy_ctl |= B43_TXH_PHY_ANT0; - break; - case 2: /* Antenna 1 */ - phy_ctl |= B43_TXH_PHY_ANT1; - break; - case 3: /* Antenna 2 */ - phy_ctl |= B43_TXH_PHY_ANT2; - break; - case 4: /* Antenna 3 */ - phy_ctl |= B43_TXH_PHY_ANT3; - break; - default: - B43_WARN_ON(1); - } - - rates = info->control.rates; - /* MAC control */ - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - mac_ctl |= B43_TXH_MAC_ACK; - /* use hardware sequence counter as the non-TID counter */ - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) - mac_ctl |= B43_TXH_MAC_HWSEQ; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - mac_ctl |= B43_TXH_MAC_STMSDU; - if (phy->type == B43_PHYTYPE_A) - mac_ctl |= B43_TXH_MAC_5GHZ; - - /* Overwrite rates[0].count to make the retry calculation - * in the tx status easier. need the actual retry limit to - * detect whether the fallback rate was used. - */ - if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { - rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; - mac_ctl |= B43_TXH_MAC_LONGFRAME; - } else { - rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; - } - - /* Generate the RTS or CTS-to-self frame */ - if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { - unsigned int len; - struct ieee80211_hdr *hdr; - int rts_rate, rts_rate_fb; - int rts_rate_ofdm, rts_rate_fb_ofdm; - struct b43_plcp_hdr6 *plcp; - struct ieee80211_rate *rts_cts_rate; - - rts_cts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info); - - rts_rate = rts_cts_rate ? rts_cts_rate->hw_value : B43_CCK_RATE_1MB; - rts_rate_ofdm = b43_is_ofdm_rate(rts_rate); - rts_rate_fb = b43_calc_fallback_rate(rts_rate); - rts_rate_fb_ofdm = b43_is_ofdm_rate(rts_rate_fb); - - if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - struct ieee80211_cts *cts; - - if (b43_is_old_txhdr_format(dev)) { - cts = (struct ieee80211_cts *) - (txhdr->old_format.rts_frame); - } else { - cts = (struct ieee80211_cts *) - (txhdr->new_format.rts_frame); - } - ieee80211_ctstoself_get(dev->wl->hw, info->control.vif, - fragment_data, fragment_len, - info, cts); - mac_ctl |= B43_TXH_MAC_SENDCTS; - len = sizeof(struct ieee80211_cts); - } else { - struct ieee80211_rts *rts; - - if (b43_is_old_txhdr_format(dev)) { - rts = (struct ieee80211_rts *) - (txhdr->old_format.rts_frame); - } else { - rts = (struct ieee80211_rts *) - (txhdr->new_format.rts_frame); - } - ieee80211_rts_get(dev->wl->hw, info->control.vif, - fragment_data, fragment_len, - info, rts); - mac_ctl |= B43_TXH_MAC_SENDRTS; - len = sizeof(struct ieee80211_rts); - } - len += FCS_LEN; - - /* Generate the PLCP headers for the RTS/CTS frame */ - if (b43_is_old_txhdr_format(dev)) - plcp = &txhdr->old_format.rts_plcp; - else - plcp = &txhdr->new_format.rts_plcp; - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, - len, rts_rate); - plcp = &txhdr->rts_plcp_fb; - b43_generate_plcp_hdr((struct b43_plcp_hdr4 *)plcp, - len, rts_rate_fb); - - if (b43_is_old_txhdr_format(dev)) { - hdr = (struct ieee80211_hdr *) - (&txhdr->old_format.rts_frame); - } else { - hdr = (struct ieee80211_hdr *) - (&txhdr->new_format.rts_frame); - } - txhdr->rts_dur_fb = hdr->duration_id; - - if (rts_rate_ofdm) { - extra_ft |= B43_TXH_EFT_RTS_OFDM; - txhdr->phy_rate_rts = - b43_plcp_get_ratecode_ofdm(rts_rate); - } else { - extra_ft |= B43_TXH_EFT_RTS_CCK; - txhdr->phy_rate_rts = - b43_plcp_get_ratecode_cck(rts_rate); - } - if (rts_rate_fb_ofdm) - extra_ft |= B43_TXH_EFT_RTSFB_OFDM; - else - extra_ft |= B43_TXH_EFT_RTSFB_CCK; - } - - /* Magic cookie */ - if (b43_is_old_txhdr_format(dev)) - txhdr->old_format.cookie = cpu_to_le16(cookie); - else - txhdr->new_format.cookie = cpu_to_le16(cookie); - - /* Apply the bitfields */ - txhdr->mac_ctl = cpu_to_le32(mac_ctl); - txhdr->phy_ctl = cpu_to_le16(phy_ctl); - txhdr->extra_ft = extra_ft; - - return 0; -} - -static s8 b43_rssi_postprocess(struct b43_wldev *dev, - u8 in_rssi, int ofdm, - int adjust_2053, int adjust_2050) -{ - struct b43_phy *phy = &dev->phy; - struct b43_phy_g *gphy = phy->g; - s32 tmp; - - switch (phy->radio_ver) { - case 0x2050: - if (ofdm) { - tmp = in_rssi; - if (tmp > 127) - tmp -= 256; - tmp *= 73; - tmp /= 64; - if (adjust_2050) - tmp += 25; - else - tmp -= 3; - } else { - if (dev->dev->bus->sprom. - boardflags_lo & B43_BFL_RSSI) { - if (in_rssi > 63) - in_rssi = 63; - B43_WARN_ON(phy->type != B43_PHYTYPE_G); - tmp = gphy->nrssi_lt[in_rssi]; - tmp = 31 - tmp; - tmp *= -131; - tmp /= 128; - tmp -= 57; - } else { - tmp = in_rssi; - tmp = 31 - tmp; - tmp *= -149; - tmp /= 128; - tmp -= 68; - } - if (phy->type == B43_PHYTYPE_G && adjust_2050) - tmp += 25; - } - break; - case 0x2060: - if (in_rssi > 127) - tmp = in_rssi - 256; - else - tmp = in_rssi; - break; - default: - tmp = in_rssi; - tmp -= 11; - tmp *= 103; - tmp /= 64; - if (adjust_2053) - tmp -= 109; - else - tmp -= 83; - } - - return (s8) tmp; -} - -//TODO -#if 0 -static s8 b43_rssinoise_postprocess(struct b43_wldev *dev, u8 in_rssi) -{ - struct b43_phy *phy = &dev->phy; - s8 ret; - - if (phy->type == B43_PHYTYPE_A) { - //TODO: Incomplete specs. - ret = 0; - } else - ret = b43_rssi_postprocess(dev, in_rssi, 0, 1, 1); - - return ret; -} -#endif - -void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr) -{ - struct ieee80211_rx_status status; - struct b43_plcp_hdr6 *plcp; - struct ieee80211_hdr *wlhdr; - const struct b43_rxhdr_fw4 *rxhdr = _rxhdr; - __le16 fctl; - u16 phystat0, phystat3, chanstat, mactime; - u32 macstat; - u16 chanid; - u16 phytype; - int padding; - - memset(&status, 0, sizeof(status)); - - /* Get metadata about the frame from the header. */ - phystat0 = le16_to_cpu(rxhdr->phy_status0); - phystat3 = le16_to_cpu(rxhdr->phy_status3); - macstat = le32_to_cpu(rxhdr->mac_status); - mactime = le16_to_cpu(rxhdr->mac_time); - chanstat = le16_to_cpu(rxhdr->channel); - phytype = chanstat & B43_RX_CHAN_PHYTYPE; - - if (unlikely(macstat & B43_RX_MAC_FCSERR)) { - dev->wl->ieee_stats.dot11FCSErrorCount++; - status.flag |= RX_FLAG_FAILED_FCS_CRC; - } - if (unlikely(phystat0 & (B43_RX_PHYST0_PLCPHCF | B43_RX_PHYST0_PLCPFV))) - status.flag |= RX_FLAG_FAILED_PLCP_CRC; - if (phystat0 & B43_RX_PHYST0_SHORTPRMBL) - status.flag |= RX_FLAG_SHORTPRE; - if (macstat & B43_RX_MAC_DECERR) { - /* Decryption with the given key failed. - * Drop the packet. We also won't be able to decrypt it with - * the key in software. */ - goto drop; - } - - /* Skip PLCP and padding */ - padding = (macstat & B43_RX_MAC_PADDING) ? 2 : 0; - if (unlikely(skb->len < (sizeof(struct b43_plcp_hdr6) + padding))) { - b43dbg(dev->wl, "RX: Packet size underrun (1)\n"); - goto drop; - } - plcp = (struct b43_plcp_hdr6 *)(skb->data + padding); - skb_pull(skb, sizeof(struct b43_plcp_hdr6) + padding); - /* The skb contains the Wireless Header + payload data now */ - if (unlikely(skb->len < (2 + 2 + 6 /*minimum hdr */ + FCS_LEN))) { - b43dbg(dev->wl, "RX: Packet size underrun (2)\n"); - goto drop; - } - wlhdr = (struct ieee80211_hdr *)(skb->data); - fctl = wlhdr->frame_control; - - if (macstat & B43_RX_MAC_DEC) { - unsigned int keyidx; - int wlhdr_len; - - keyidx = ((macstat & B43_RX_MAC_KEYIDX) - >> B43_RX_MAC_KEYIDX_SHIFT); - /* We must adjust the key index here. We want the "physical" - * key index, but the ucode passed it slightly different. - */ - keyidx = b43_kidx_to_raw(dev, keyidx); - B43_WARN_ON(keyidx >= ARRAY_SIZE(dev->key)); - - if (dev->key[keyidx].algorithm != B43_SEC_ALGO_NONE) { - wlhdr_len = ieee80211_hdrlen(fctl); - if (unlikely(skb->len < (wlhdr_len + 3))) { - b43dbg(dev->wl, - "RX: Packet size underrun (3)\n"); - goto drop; - } - status.flag |= RX_FLAG_DECRYPTED; - } - } - - /* Link quality statistics */ - status.noise = dev->stats.link_noise; - if ((chanstat & B43_RX_CHAN_PHYTYPE) == B43_PHYTYPE_N) { -// s8 rssi = max(rxhdr->power0, rxhdr->power1); - //TODO: Find out what the rssi value is (dBm or percentage?) - // and also find out what the maximum possible value is. - // Fill status.ssi and status.signal fields. - } else { - status.signal = b43_rssi_postprocess(dev, rxhdr->jssi, - (phystat0 & B43_RX_PHYST0_OFDM), - (phystat0 & B43_RX_PHYST0_GAINCTL), - (phystat3 & B43_RX_PHYST3_TRSTATE)); - status.qual = (rxhdr->jssi * 100) / B43_RX_MAX_SSI; - } - - if (phystat0 & B43_RX_PHYST0_OFDM) - status.rate_idx = b43_plcp_get_bitrate_idx_ofdm(plcp, - phytype == B43_PHYTYPE_A); - else - status.rate_idx = b43_plcp_get_bitrate_idx_cck(plcp); - if (unlikely(status.rate_idx == -1)) { - /* PLCP seems to be corrupted. - * Drop the frame, if we are not interested in corrupted frames. */ - if (!(dev->wl->filter_flags & FIF_PLCPFAIL)) - goto drop; - } - status.antenna = !!(phystat0 & B43_RX_PHYST0_ANT); - - /* - * All frames on monitor interfaces and beacons always need a full - * 64-bit timestamp. Monitor interfaces need it for diagnostic - * purposes and beacons for IBSS merging. - * This code assumes we get to process the packet within 16 bits - * of timestamp, i.e. about 65 milliseconds after the PHY received - * the first symbol. - */ - if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { - u16 low_mactime_now; - - b43_tsf_read(dev, &status.mactime); - low_mactime_now = status.mactime; - status.mactime = status.mactime & ~0xFFFFULL; - status.mactime += mactime; - if (low_mactime_now <= mactime) - status.mactime -= 0x10000; - status.flag |= RX_FLAG_TSFT; - } - - chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT; - switch (chanstat & B43_RX_CHAN_PHYTYPE) { - case B43_PHYTYPE_A: - status.band = IEEE80211_BAND_5GHZ; - B43_WARN_ON(1); - /* FIXME: We don't really know which value the "chanid" contains. - * So the following assignment might be wrong. */ - status.freq = b43_channel_to_freq_5ghz(chanid); - break; - case B43_PHYTYPE_G: - status.band = IEEE80211_BAND_2GHZ; - /* chanid is the radio channel cookie value as used - * to tune the radio. */ - status.freq = chanid + 2400; - break; - case B43_PHYTYPE_N: - case B43_PHYTYPE_LP: - /* chanid is the SHM channel cookie. Which is the plain - * channel number in b43. */ - if (chanstat & B43_RX_CHAN_5GHZ) { - status.band = IEEE80211_BAND_5GHZ; - status.freq = b43_freq_to_channel_5ghz(chanid); - } else { - status.band = IEEE80211_BAND_2GHZ; - status.freq = b43_freq_to_channel_2ghz(chanid); - } - break; - default: - B43_WARN_ON(1); - goto drop; - } - - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - - local_bh_disable(); - ieee80211_rx(dev->wl->hw, skb); - local_bh_enable(); - -#if B43_DEBUG - dev->rx_count++; -#endif - return; -drop: - b43dbg(dev->wl, "RX: Packet dropped\n"); - dev_kfree_skb_any(skb); -} - -void b43_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status) -{ - b43_debugfs_log_txstat(dev, status); - - if (status->intermediate) - return; - if (status->for_ampdu) - return; - if (!status->acked) - dev->wl->ieee_stats.dot11ACKFailureCount++; - if (status->rts_count) { - if (status->rts_count == 0xF) //FIXME - dev->wl->ieee_stats.dot11RTSFailureCount++; - else - dev->wl->ieee_stats.dot11RTSSuccessCount++; - } - - if (b43_using_pio_transfers(dev)) - b43_pio_handle_txstatus(dev, status); - else - b43_dma_handle_txstatus(dev, status); - - b43_phy_txpower_check(dev, 0); -} - -/* Fill out the mac80211 TXstatus report based on the b43-specific - * txstatus report data. This returns a boolean whether the frame was - * successfully transmitted. */ -bool b43_fill_txstatus_report(struct b43_wldev *dev, - struct ieee80211_tx_info *report, - const struct b43_txstatus *status) -{ - bool frame_success = 1; - int retry_limit; - - /* preserve the confiured retry limit before clearing the status - * The xmit function has overwritten the rc's value with the actual - * retry limit done by the hardware */ - retry_limit = report->status.rates[0].count; - ieee80211_tx_info_clear_status(report); - - if (status->acked) { - /* The frame was ACKed. */ - report->flags |= IEEE80211_TX_STAT_ACK; - } else { - /* The frame was not ACKed... */ - if (!(report->flags & IEEE80211_TX_CTL_NO_ACK)) { - /* ...but we expected an ACK. */ - frame_success = 0; - } - } - if (status->frame_count == 0) { - /* The frame was not transmitted at all. */ - report->status.rates[0].count = 0; - } else if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { - /* - * If the short retries (RTS, not data frame) have exceeded - * the limit, the hw will not have tried the selected rate, - * but will have used the fallback rate instead. - * Don't let the rate control count attempts for the selected - * rate in this case, otherwise the statistics will be off. - */ - report->status.rates[0].count = 0; - report->status.rates[1].count = status->frame_count; - } else { - if (status->frame_count > retry_limit) { - report->status.rates[0].count = retry_limit; - report->status.rates[1].count = status->frame_count - - retry_limit; - - } else { - report->status.rates[0].count = status->frame_count; - report->status.rates[1].idx = -1; - } - } - - return frame_success; -} - -/* Stop any TX operation on the device (suspend the hardware queues) */ -void b43_tx_suspend(struct b43_wldev *dev) -{ - if (b43_using_pio_transfers(dev)) - b43_pio_tx_suspend(dev); - else - b43_dma_tx_suspend(dev); -} - -/* Resume any TX operation on the device (resume the hardware queues) */ -void b43_tx_resume(struct b43_wldev *dev) -{ - if (b43_using_pio_transfers(dev)) - b43_pio_tx_resume(dev); - else - b43_dma_tx_resume(dev); -} diff --git a/drivers/net/wireless/b43/xmit.h b/drivers/net/wireless/b43/xmit.h deleted file mode 100644 index 3530de871873..000000000000 --- a/drivers/net/wireless/b43/xmit.h +++ /dev/null @@ -1,335 +0,0 @@ -#ifndef B43_XMIT_H_ -#define B43_XMIT_H_ - -#include "main.h" - -#define _b43_declare_plcp_hdr(size) \ - struct b43_plcp_hdr##size { \ - union { \ - __le32 data; \ - __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) - -/* struct b43_plcp_hdr4 */ -_b43_declare_plcp_hdr(4); -/* struct b43_plcp_hdr6 */ -_b43_declare_plcp_hdr(6); - -#undef _b43_declare_plcp_hdr - -/* TX header for v4 firmware */ -struct b43_txhdr { - __le32 mac_ctl; /* MAC TX control */ - __le16 mac_frame_ctl; /* Copy of the FrameControl field */ - __le16 tx_fes_time_norm; /* TX FES Time Normal */ - __le16 phy_ctl; /* PHY TX control */ - __le16 phy_ctl1; /* PHY TX control word 1 */ - __le16 phy_ctl1_fb; /* PHY TX control word 1 for fallback rates */ - __le16 phy_ctl1_rts; /* PHY TX control word 1 RTS */ - __le16 phy_ctl1_rts_fb; /* PHY TX control word 1 RTS for fallback rates */ - __u8 phy_rate; /* PHY rate */ - __u8 phy_rate_rts; /* PHY rate for RTS/CTS */ - __u8 extra_ft; /* Extra Frame Types */ - __u8 chan_radio_code; /* Channel Radio Code */ - __u8 iv[16]; /* Encryption IV */ - __u8 tx_receiver[6]; /* TX Frame Receiver address */ - __le16 tx_fes_time_fb; /* TX FES Time Fallback */ - struct b43_plcp_hdr6 rts_plcp_fb; /* RTS fallback PLCP header */ - __le16 rts_dur_fb; /* RTS fallback duration */ - struct b43_plcp_hdr6 plcp_fb; /* Fallback PLCP header */ - __le16 dur_fb; /* Fallback duration */ - __le16 mimo_modelen; /* MIMO mode length */ - __le16 mimo_ratelen_fb; /* MIMO fallback rate length */ - __le32 timeout; /* Timeout */ - - union { - /* The new r410 format. */ - struct { - __le16 mimo_antenna; /* MIMO antenna select */ - __le16 preload_size; /* Preload size */ - PAD_BYTES(2); - __le16 cookie; /* TX frame cookie */ - __le16 tx_status; /* TX status */ - struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ - __u8 rts_frame[16]; /* The RTS frame (if used) */ - PAD_BYTES(2); - struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } new_format __attribute__ ((__packed__)); - - /* The old r351 format. */ - struct { - PAD_BYTES(2); - __le16 cookie; /* TX frame cookie */ - __le16 tx_status; /* TX status */ - struct b43_plcp_hdr6 rts_plcp; /* RTS PLCP header */ - __u8 rts_frame[16]; /* The RTS frame (if used) */ - PAD_BYTES(2); - struct b43_plcp_hdr6 plcp; /* Main PLCP header */ - } old_format __attribute__ ((__packed__)); - - } __attribute__ ((__packed__)); -} __attribute__ ((__packed__)); - -/* MAC TX control */ -#define B43_TXH_MAC_USEFBR 0x10000000 /* Use fallback rate for this AMPDU */ -#define B43_TXH_MAC_KEYIDX 0x0FF00000 /* Security key index */ -#define B43_TXH_MAC_KEYIDX_SHIFT 20 -#define B43_TXH_MAC_KEYALG 0x00070000 /* Security key algorithm */ -#define B43_TXH_MAC_KEYALG_SHIFT 16 -#define B43_TXH_MAC_AMIC 0x00008000 /* AMIC */ -#define B43_TXH_MAC_RIFS 0x00004000 /* Use RIFS */ -#define B43_TXH_MAC_LIFETIME 0x00002000 /* Lifetime */ -#define B43_TXH_MAC_FRAMEBURST 0x00001000 /* Frameburst */ -#define B43_TXH_MAC_SENDCTS 0x00000800 /* Send CTS-to-self */ -#define B43_TXH_MAC_AMPDU 0x00000600 /* AMPDU status */ -#define B43_TXH_MAC_AMPDU_MPDU 0x00000000 /* Regular MPDU, not an AMPDU */ -#define B43_TXH_MAC_AMPDU_FIRST 0x00000200 /* First MPDU or AMPDU */ -#define B43_TXH_MAC_AMPDU_INTER 0x00000400 /* Intermediate MPDU or AMPDU */ -#define B43_TXH_MAC_AMPDU_LAST 0x00000600 /* Last (or only) MPDU of AMPDU */ -#define B43_TXH_MAC_40MHZ 0x00000100 /* Use 40 MHz bandwidth */ -#define B43_TXH_MAC_5GHZ 0x00000080 /* 5GHz band */ -#define B43_TXH_MAC_DFCS 0x00000040 /* DFCS */ -#define B43_TXH_MAC_IGNPMQ 0x00000020 /* Ignore PMQ */ -#define B43_TXH_MAC_HWSEQ 0x00000010 /* Use Hardware Sequence Number */ -#define B43_TXH_MAC_STMSDU 0x00000008 /* Start MSDU */ -#define B43_TXH_MAC_SENDRTS 0x00000004 /* Send RTS */ -#define B43_TXH_MAC_LONGFRAME 0x00000002 /* Long frame */ -#define B43_TXH_MAC_ACK 0x00000001 /* Immediate ACK */ - -/* Extra Frame Types */ -#define B43_TXH_EFT_FB 0x03 /* Data frame fallback encoding */ -#define B43_TXH_EFT_FB_CCK 0x00 /* CCK */ -#define B43_TXH_EFT_FB_OFDM 0x01 /* OFDM */ -#define B43_TXH_EFT_FB_EWC 0x02 /* EWC */ -#define B43_TXH_EFT_FB_N 0x03 /* N */ -#define B43_TXH_EFT_RTS 0x0C /* RTS/CTS encoding */ -#define B43_TXH_EFT_RTS_CCK 0x00 /* CCK */ -#define B43_TXH_EFT_RTS_OFDM 0x04 /* OFDM */ -#define B43_TXH_EFT_RTS_EWC 0x08 /* EWC */ -#define B43_TXH_EFT_RTS_N 0x0C /* N */ -#define B43_TXH_EFT_RTSFB 0x30 /* RTS/CTS fallback encoding */ -#define B43_TXH_EFT_RTSFB_CCK 0x00 /* CCK */ -#define B43_TXH_EFT_RTSFB_OFDM 0x10 /* OFDM */ -#define B43_TXH_EFT_RTSFB_EWC 0x20 /* EWC */ -#define B43_TXH_EFT_RTSFB_N 0x30 /* N */ - -/* PHY TX control word */ -#define B43_TXH_PHY_ENC 0x0003 /* Data frame encoding */ -#define B43_TXH_PHY_ENC_CCK 0x0000 /* CCK */ -#define B43_TXH_PHY_ENC_OFDM 0x0001 /* OFDM */ -#define B43_TXH_PHY_ENC_EWC 0x0002 /* EWC */ -#define B43_TXH_PHY_ENC_N 0x0003 /* N */ -#define B43_TXH_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ -#define B43_TXH_PHY_ANT 0x03C0 /* Antenna selection */ -#define B43_TXH_PHY_ANT0 0x0000 /* Use antenna 0 */ -#define B43_TXH_PHY_ANT1 0x0040 /* Use antenna 1 */ -#define B43_TXH_PHY_ANT01AUTO 0x00C0 /* Use antenna 0/1 auto */ -#define B43_TXH_PHY_ANT2 0x0100 /* Use antenna 2 */ -#define B43_TXH_PHY_ANT3 0x0200 /* Use antenna 3 */ -#define B43_TXH_PHY_TXPWR 0xFC00 /* TX power */ -#define B43_TXH_PHY_TXPWR_SHIFT 10 - -/* PHY TX control word 1 */ -#define B43_TXH_PHY1_BW 0x0007 /* Bandwidth */ -#define B43_TXH_PHY1_BW_10 0x0000 /* 10 MHz */ -#define B43_TXH_PHY1_BW_10U 0x0001 /* 10 MHz upper */ -#define B43_TXH_PHY1_BW_20 0x0002 /* 20 MHz */ -#define B43_TXH_PHY1_BW_20U 0x0003 /* 20 MHz upper */ -#define B43_TXH_PHY1_BW_40 0x0004 /* 40 MHz */ -#define B43_TXH_PHY1_BW_40DUP 0x0005 /* 50 MHz duplicate */ -#define B43_TXH_PHY1_MODE 0x0038 /* Mode */ -#define B43_TXH_PHY1_MODE_SISO 0x0000 /* SISO */ -#define B43_TXH_PHY1_MODE_CDD 0x0008 /* CDD */ -#define B43_TXH_PHY1_MODE_STBC 0x0010 /* STBC */ -#define B43_TXH_PHY1_MODE_SDM 0x0018 /* SDM */ -#define B43_TXH_PHY1_CRATE 0x0700 /* Coding rate */ -#define B43_TXH_PHY1_CRATE_1_2 0x0000 /* 1/2 */ -#define B43_TXH_PHY1_CRATE_2_3 0x0100 /* 2/3 */ -#define B43_TXH_PHY1_CRATE_3_4 0x0200 /* 3/4 */ -#define B43_TXH_PHY1_CRATE_4_5 0x0300 /* 4/5 */ -#define B43_TXH_PHY1_CRATE_5_6 0x0400 /* 5/6 */ -#define B43_TXH_PHY1_CRATE_7_8 0x0600 /* 7/8 */ -#define B43_TXH_PHY1_MODUL 0x3800 /* Modulation scheme */ -#define B43_TXH_PHY1_MODUL_BPSK 0x0000 /* BPSK */ -#define B43_TXH_PHY1_MODUL_QPSK 0x0800 /* QPSK */ -#define B43_TXH_PHY1_MODUL_QAM16 0x1000 /* QAM16 */ -#define B43_TXH_PHY1_MODUL_QAM64 0x1800 /* QAM64 */ -#define B43_TXH_PHY1_MODUL_QAM256 0x2000 /* QAM256 */ - - -/* r351 firmware compatibility stuff. */ -static inline -bool b43_is_old_txhdr_format(struct b43_wldev *dev) -{ - return (dev->fw.rev <= 351); -} - -static inline -size_t b43_txhdr_size(struct b43_wldev *dev) -{ - if (b43_is_old_txhdr_format(dev)) - return 100 + sizeof(struct b43_plcp_hdr6); - return 104 + sizeof(struct b43_plcp_hdr6); -} - - -int b43_generate_txhdr(struct b43_wldev *dev, - u8 * txhdr, - struct sk_buff *skb_frag, - struct ieee80211_tx_info *txctl, u16 cookie); - -/* Transmit Status */ -struct b43_txstatus { - u16 cookie; /* The cookie from the txhdr */ - u16 seq; /* Sequence number */ - u8 phy_stat; /* PHY TX status */ - u8 frame_count; /* Frame transmit count */ - u8 rts_count; /* RTS transmit count */ - u8 supp_reason; /* Suppression reason */ - /* flags */ - u8 pm_indicated; /* PM mode indicated to AP */ - u8 intermediate; /* Intermediate status notification (not final) */ - u8 for_ampdu; /* Status is for an AMPDU (afterburner) */ - u8 acked; /* Wireless ACK received */ -}; - -/* txstatus supp_reason values */ -enum { - B43_TXST_SUPP_NONE, /* Not suppressed */ - B43_TXST_SUPP_PMQ, /* Suppressed due to PMQ entry */ - B43_TXST_SUPP_FLUSH, /* Suppressed due to flush request */ - B43_TXST_SUPP_PREV, /* Previous fragment failed */ - B43_TXST_SUPP_CHAN, /* Channel mismatch */ - B43_TXST_SUPP_LIFE, /* Lifetime expired */ - B43_TXST_SUPP_UNDER, /* Buffer underflow */ - B43_TXST_SUPP_ABNACK, /* Afterburner NACK */ -}; - -/* Receive header for v4 firmware. */ -struct b43_rxhdr_fw4 { - __le16 frame_len; /* Frame length */ - PAD_BYTES(2); - __le16 phy_status0; /* PHY RX Status 0 */ - union { - /* RSSI for A/B/G-PHYs */ - struct { - __u8 jssi; /* PHY RX Status 1: JSSI */ - __u8 sig_qual; /* PHY RX Status 1: Signal Quality */ - } __attribute__ ((__packed__)); - - /* RSSI for N-PHYs */ - struct { - __s8 power0; /* PHY RX Status 1: Power 0 */ - __s8 power1; /* PHY RX Status 1: Power 1 */ - } __attribute__ ((__packed__)); - } __attribute__ ((__packed__)); - __le16 phy_status2; /* PHY RX Status 2 */ - __le16 phy_status3; /* PHY RX Status 3 */ - __le32 mac_status; /* MAC RX status */ - __le16 mac_time; - __le16 channel; -} __attribute__ ((__packed__)); - -/* PHY RX Status 0 */ -#define B43_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */ -#define B43_RX_PHYST0_PLCPHCF 0x0200 -#define B43_RX_PHYST0_PLCPFV 0x0100 -#define B43_RX_PHYST0_SHORTPRMBL 0x0080 /* Received with Short Preamble */ -#define B43_RX_PHYST0_LCRS 0x0040 -#define B43_RX_PHYST0_ANT 0x0020 /* Antenna */ -#define B43_RX_PHYST0_UNSRATE 0x0010 -#define B43_RX_PHYST0_CLIP 0x000C -#define B43_RX_PHYST0_CLIP_SHIFT 2 -#define B43_RX_PHYST0_FTYPE 0x0003 /* Frame type */ -#define B43_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */ -#define B43_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */ -#define B43_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */ -#define B43_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */ - -/* PHY RX Status 2 */ -#define B43_RX_PHYST2_LNAG 0xC000 /* LNA Gain */ -#define B43_RX_PHYST2_LNAG_SHIFT 14 -#define B43_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */ -#define B43_RX_PHYST2_PNAG_SHIFT 10 -#define B43_RX_PHYST2_FOFF 0x03FF /* F offset */ - -/* PHY RX Status 3 */ -#define B43_RX_PHYST3_DIGG 0x1800 /* DIG Gain */ -#define B43_RX_PHYST3_DIGG_SHIFT 11 -#define B43_RX_PHYST3_TRSTATE 0x0400 /* TR state */ - -/* MAC RX Status */ -#define B43_RX_MAC_RXST_VALID 0x01000000 /* PHY RXST valid */ -#define B43_RX_MAC_TKIP_MICERR 0x00100000 /* TKIP MIC error */ -#define B43_RX_MAC_TKIP_MICATT 0x00080000 /* TKIP MIC attempted */ -#define B43_RX_MAC_AGGTYPE 0x00060000 /* Aggregation type */ -#define B43_RX_MAC_AGGTYPE_SHIFT 17 -#define B43_RX_MAC_AMSDU 0x00010000 /* A-MSDU mask */ -#define B43_RX_MAC_BEACONSENT 0x00008000 /* Beacon sent flag */ -#define B43_RX_MAC_KEYIDX 0x000007E0 /* Key index */ -#define B43_RX_MAC_KEYIDX_SHIFT 5 -#define B43_RX_MAC_DECERR 0x00000010 /* Decrypt error */ -#define B43_RX_MAC_DEC 0x00000008 /* Decryption attempted */ -#define B43_RX_MAC_PADDING 0x00000004 /* Pad bytes present */ -#define B43_RX_MAC_RESP 0x00000002 /* Response frame transmitted */ -#define B43_RX_MAC_FCSERR 0x00000001 /* FCS error */ - -/* RX channel */ -#define B43_RX_CHAN_40MHZ 0x1000 /* 40 Mhz channel width */ -#define B43_RX_CHAN_5GHZ 0x0800 /* 5 Ghz band */ -#define B43_RX_CHAN_ID 0x07F8 /* Channel ID */ -#define B43_RX_CHAN_ID_SHIFT 3 -#define B43_RX_CHAN_PHYTYPE 0x0007 /* PHY type */ - - -u8 b43_plcp_get_ratecode_cck(const u8 bitrate); -u8 b43_plcp_get_ratecode_ofdm(const u8 bitrate); - -void b43_generate_plcp_hdr(struct b43_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate); - -void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr); - -void b43_handle_txstatus(struct b43_wldev *dev, - const struct b43_txstatus *status); -bool b43_fill_txstatus_report(struct b43_wldev *dev, - struct ieee80211_tx_info *report, - const struct b43_txstatus *status); - -void b43_tx_suspend(struct b43_wldev *dev); -void b43_tx_resume(struct b43_wldev *dev); - - -/* Helper functions for converting the key-table index from "firmware-format" - * to "raw-format" and back. The firmware API changed for this at some revision. - * We need to account for that here. */ -static inline int b43_new_kidx_api(struct b43_wldev *dev) -{ - /* FIXME: Not sure the change was at rev 351 */ - return (dev->fw.rev >= 351); -} -static inline u8 b43_kidx_to_fw(struct b43_wldev *dev, u8 raw_kidx) -{ - u8 firmware_kidx; - if (b43_new_kidx_api(dev)) { - firmware_kidx = raw_kidx; - } else { - if (raw_kidx >= 4) /* Is per STA key? */ - firmware_kidx = raw_kidx - 4; - else - firmware_kidx = raw_kidx; /* TX default key */ - } - return firmware_kidx; -} -static inline u8 b43_kidx_to_raw(struct b43_wldev *dev, u8 firmware_kidx) -{ - u8 raw_kidx; - if (b43_new_kidx_api(dev)) - raw_kidx = firmware_kidx; - else - raw_kidx = firmware_kidx + 4; /* RX default keys or per STA keys */ - return raw_kidx; -} - -#endif /* B43_XMIT_H_ */ diff --git a/drivers/net/wireless/b43legacy/Kconfig b/drivers/net/wireless/b43legacy/Kconfig deleted file mode 100644 index 94a463478053..000000000000 --- a/drivers/net/wireless/b43legacy/Kconfig +++ /dev/null @@ -1,104 +0,0 @@ -config B43LEGACY - tristate "Broadcom 43xx-legacy wireless support (mac80211 stack)" - depends on SSB_POSSIBLE && MAC80211 && WLAN_80211 && HAS_DMA - select SSB - select FW_LOADER - ---help--- - b43legacy is a driver for 802.11b devices from Broadcom (BCM4301 and - BCM4303) and early model 802.11g chips (BCM4306 Ver. 2) used in the - Linksys WPC54G V1 PCMCIA devices. - - Newer 802.11g and 802.11a devices need b43. - - It is safe to include both b43 and b43legacy as the underlying glue - layer will automatically load the correct version for your device. - - This driver uses V3 firmware, which must be installed separately using - b43-fwcutter. - - This driver can be built as a module (recommended) that will be - called "b43legacy". If unsure, say M. - -# Auto-select SSB PCI-HOST support, if possible -config B43LEGACY_PCI_AUTOSELECT - bool - depends on B43LEGACY && SSB_PCIHOST_POSSIBLE - select SSB_PCIHOST - select SSB_B43_PCI_BRIDGE - default y - -# Auto-select SSB PCICORE driver, if possible -config B43LEGACY_PCICORE_AUTOSELECT - bool - depends on B43LEGACY && SSB_DRIVER_PCICORE_POSSIBLE - select SSB_DRIVER_PCICORE - default y - -# LED support -# This config option automatically enables b43legacy LEDS support, -# if it's possible. -config B43LEGACY_LEDS - bool - depends on B43LEGACY && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = B43LEGACY) - default y - -# This config option automatically enables b43 HW-RNG support, -# if the HW-RNG core is enabled. -config B43LEGACY_HWRNG - bool - depends on B43LEGACY && (HW_RANDOM = y || HW_RANDOM = B43LEGACY) - default y - -config B43LEGACY_DEBUG - bool "Broadcom 43xx-legacy debugging" - depends on B43LEGACY - default y - ---help--- - Say Y, because this information will help you get the driver running. - This option generates a minimum of log output. - -config B43LEGACY_DMA - bool - depends on B43LEGACY - -config B43LEGACY_PIO - bool - depends on B43LEGACY - -choice - prompt "Broadcom 43xx-legacy data transfer mode" - depends on B43LEGACY - default B43LEGACY_DMA_AND_PIO_MODE - -config B43LEGACY_DMA_AND_PIO_MODE - bool "DMA + PIO" - select B43LEGACY_DMA - select B43LEGACY_PIO - ---help--- - Include both, Direct Memory Access (DMA) and Programmed I/O (PIO) - data transfer modes. The mode actually used is selectable through - the module parameter "pio". With pio=0 as a module parameter, the - default DMA is used, otherwise PIO is used. - - If unsure, choose this option. - -config B43LEGACY_DMA_MODE - bool "DMA (Direct Memory Access) only" - select B43LEGACY_DMA - ---help--- - Only include Direct Memory Access (DMA). - This reduces the size of the driver module, by omitting the PIO code. - -config B43LEGACY_PIO_MODE - bool "PIO (Programmed I/O) only" - select B43LEGACY_PIO - ---help--- - Only include Programmed I/O (PIO). - This reduces the size of the driver module, by omitting the DMA code. - Please note that PIO transfers are slow (compared to DMA). - - Also note that not all devices of the b43legacy series support PIO. - - You should use PIO only if DMA does not work for you. - -endchoice diff --git a/drivers/net/wireless/b43legacy/Makefile b/drivers/net/wireless/b43legacy/Makefile deleted file mode 100644 index 227a77e84362..000000000000 --- a/drivers/net/wireless/b43legacy/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# b43legacy core -b43legacy-y += main.o -b43legacy-y += ilt.o -b43legacy-y += phy.o -b43legacy-y += radio.o -b43legacy-y += sysfs.o -b43legacy-y += xmit.o -# b43 RFKILL button support -b43legacy-y += rfkill.o -# b43legacy LED support -b43legacy-$(CONFIG_B43LEGACY_LEDS) += leds.o -# b43legacy debugging -b43legacy-$(CONFIG_B43LEGACY_DEBUG) += debugfs.o -# b43legacy DMA and PIO -b43legacy-$(CONFIG_B43LEGACY_DMA) += dma.o -b43legacy-$(CONFIG_B43LEGACY_PIO) += pio.o - -obj-$(CONFIG_B43LEGACY) += b43legacy.o - diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h deleted file mode 100644 index 038baa8869e2..000000000000 --- a/drivers/net/wireless/b43legacy/b43legacy.h +++ /dev/null @@ -1,835 +0,0 @@ -#ifndef B43legacy_H_ -#define B43legacy_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include "debugfs.h" -#include "leds.h" -#include "rfkill.h" -#include "phy.h" - - -/* The unique identifier of the firmware that's officially supported by this - * driver version. */ -#define B43legacy_SUPPORTED_FIRMWARE_ID "FW10" - -#define B43legacy_IRQWAIT_MAX_RETRIES 20 - -#define B43legacy_RX_MAX_SSI 60 /* best guess at max ssi */ - -/* MMIO offsets */ -#define B43legacy_MMIO_DMA0_REASON 0x20 -#define B43legacy_MMIO_DMA0_IRQ_MASK 0x24 -#define B43legacy_MMIO_DMA1_REASON 0x28 -#define B43legacy_MMIO_DMA1_IRQ_MASK 0x2C -#define B43legacy_MMIO_DMA2_REASON 0x30 -#define B43legacy_MMIO_DMA2_IRQ_MASK 0x34 -#define B43legacy_MMIO_DMA3_REASON 0x38 -#define B43legacy_MMIO_DMA3_IRQ_MASK 0x3C -#define B43legacy_MMIO_DMA4_REASON 0x40 -#define B43legacy_MMIO_DMA4_IRQ_MASK 0x44 -#define B43legacy_MMIO_DMA5_REASON 0x48 -#define B43legacy_MMIO_DMA5_IRQ_MASK 0x4C -#define B43legacy_MMIO_MACCTL 0x120 /* MAC control */ -#define B43legacy_MMIO_MACCMD 0x124 /* MAC command */ -#define B43legacy_MMIO_GEN_IRQ_REASON 0x128 -#define B43legacy_MMIO_GEN_IRQ_MASK 0x12C -#define B43legacy_MMIO_RAM_CONTROL 0x130 -#define B43legacy_MMIO_RAM_DATA 0x134 -#define B43legacy_MMIO_PS_STATUS 0x140 -#define B43legacy_MMIO_RADIO_HWENABLED_HI 0x158 -#define B43legacy_MMIO_SHM_CONTROL 0x160 -#define B43legacy_MMIO_SHM_DATA 0x164 -#define B43legacy_MMIO_SHM_DATA_UNALIGNED 0x166 -#define B43legacy_MMIO_XMITSTAT_0 0x170 -#define B43legacy_MMIO_XMITSTAT_1 0x174 -#define B43legacy_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ -#define B43legacy_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ -#define B43legacy_MMIO_TSF_CFP_REP 0x188 -#define B43legacy_MMIO_TSF_CFP_START 0x18C -/* 32-bit DMA */ -#define B43legacy_MMIO_DMA32_BASE0 0x200 -#define B43legacy_MMIO_DMA32_BASE1 0x220 -#define B43legacy_MMIO_DMA32_BASE2 0x240 -#define B43legacy_MMIO_DMA32_BASE3 0x260 -#define B43legacy_MMIO_DMA32_BASE4 0x280 -#define B43legacy_MMIO_DMA32_BASE5 0x2A0 -/* 64-bit DMA */ -#define B43legacy_MMIO_DMA64_BASE0 0x200 -#define B43legacy_MMIO_DMA64_BASE1 0x240 -#define B43legacy_MMIO_DMA64_BASE2 0x280 -#define B43legacy_MMIO_DMA64_BASE3 0x2C0 -#define B43legacy_MMIO_DMA64_BASE4 0x300 -#define B43legacy_MMIO_DMA64_BASE5 0x340 -/* PIO */ -#define B43legacy_MMIO_PIO1_BASE 0x300 -#define B43legacy_MMIO_PIO2_BASE 0x310 -#define B43legacy_MMIO_PIO3_BASE 0x320 -#define B43legacy_MMIO_PIO4_BASE 0x330 - -#define B43legacy_MMIO_PHY_VER 0x3E0 -#define B43legacy_MMIO_PHY_RADIO 0x3E2 -#define B43legacy_MMIO_PHY0 0x3E6 -#define B43legacy_MMIO_ANTENNA 0x3E8 -#define B43legacy_MMIO_CHANNEL 0x3F0 -#define B43legacy_MMIO_CHANNEL_EXT 0x3F4 -#define B43legacy_MMIO_RADIO_CONTROL 0x3F6 -#define B43legacy_MMIO_RADIO_DATA_HIGH 0x3F8 -#define B43legacy_MMIO_RADIO_DATA_LOW 0x3FA -#define B43legacy_MMIO_PHY_CONTROL 0x3FC -#define B43legacy_MMIO_PHY_DATA 0x3FE -#define B43legacy_MMIO_MACFILTER_CONTROL 0x420 -#define B43legacy_MMIO_MACFILTER_DATA 0x422 -#define B43legacy_MMIO_RCMTA_COUNT 0x43C /* Receive Match Transmitter Addr */ -#define B43legacy_MMIO_RADIO_HWENABLED_LO 0x49A -#define B43legacy_MMIO_GPIO_CONTROL 0x49C -#define B43legacy_MMIO_GPIO_MASK 0x49E -#define B43legacy_MMIO_TSF_CFP_PRETBTT 0x612 -#define B43legacy_MMIO_TSF_0 0x632 /* core rev < 3 only */ -#define B43legacy_MMIO_TSF_1 0x634 /* core rev < 3 only */ -#define B43legacy_MMIO_TSF_2 0x636 /* core rev < 3 only */ -#define B43legacy_MMIO_TSF_3 0x638 /* core rev < 3 only */ -#define B43legacy_MMIO_RNG 0x65A -#define B43legacy_MMIO_POWERUP_DELAY 0x6A8 - -/* SPROM boardflags_lo values */ -#define B43legacy_BFL_PACTRL 0x0002 -#define B43legacy_BFL_RSSI 0x0008 -#define B43legacy_BFL_EXTLNA 0x1000 - -/* GPIO register offset, in both ChipCommon and PCI core. */ -#define B43legacy_GPIO_CONTROL 0x6c - -/* SHM Routing */ -#define B43legacy_SHM_SHARED 0x0001 -#define B43legacy_SHM_WIRELESS 0x0002 -#define B43legacy_SHM_HW 0x0004 -#define B43legacy_SHM_UCODE 0x0300 - -/* SHM Routing modifiers */ -#define B43legacy_SHM_AUTOINC_R 0x0200 /* Read Auto-increment */ -#define B43legacy_SHM_AUTOINC_W 0x0100 /* Write Auto-increment */ -#define B43legacy_SHM_AUTOINC_RW (B43legacy_SHM_AUTOINC_R | \ - B43legacy_SHM_AUTOINC_W) - -/* Misc SHM_SHARED offsets */ -#define B43legacy_SHM_SH_WLCOREREV 0x0016 /* 802.11 core revision */ -#define B43legacy_SHM_SH_HOSTFLO 0x005E /* Hostflags ucode opts (low) */ -#define B43legacy_SHM_SH_HOSTFHI 0x0060 /* Hostflags ucode opts (high) */ -/* SHM_SHARED crypto engine */ -#define B43legacy_SHM_SH_KEYIDXBLOCK 0x05D4 /* Key index/algorithm block */ -/* SHM_SHARED beacon/AP variables */ -#define B43legacy_SHM_SH_DTIMP 0x0012 /* DTIM period */ -#define B43legacy_SHM_SH_BTL0 0x0018 /* Beacon template length 0 */ -#define B43legacy_SHM_SH_BTL1 0x001A /* Beacon template length 1 */ -#define B43legacy_SHM_SH_BTSFOFF 0x001C /* Beacon TSF offset */ -#define B43legacy_SHM_SH_TIMPOS 0x001E /* TIM position in beacon */ -#define B43legacy_SHM_SH_BEACPHYCTL 0x0054 /* Beacon PHY TX control word */ -/* SHM_SHARED ACK/CTS control */ -#define B43legacy_SHM_SH_ACKCTSPHYCTL 0x0022 /* ACK/CTS PHY control word */ -/* SHM_SHARED probe response variables */ -#define B43legacy_SHM_SH_PRTLEN 0x004A /* Probe Response template length */ -#define B43legacy_SHM_SH_PRMAXTIME 0x0074 /* Probe Response max time */ -#define B43legacy_SHM_SH_PRPHYCTL 0x0188 /* Probe Resp PHY TX control */ -/* SHM_SHARED rate tables */ -#define B43legacy_SHM_SH_OFDMDIRECT 0x0480 /* Pointer to OFDM direct map */ -#define B43legacy_SHM_SH_OFDMBASIC 0x04A0 /* Pointer to OFDM basic rate map */ -#define B43legacy_SHM_SH_CCKDIRECT 0x04C0 /* Pointer to CCK direct map */ -#define B43legacy_SHM_SH_CCKBASIC 0x04E0 /* Pointer to CCK basic rate map */ -/* SHM_SHARED microcode soft registers */ -#define B43legacy_SHM_SH_UCODEREV 0x0000 /* Microcode revision */ -#define B43legacy_SHM_SH_UCODEPATCH 0x0002 /* Microcode patchlevel */ -#define B43legacy_SHM_SH_UCODEDATE 0x0004 /* Microcode date */ -#define B43legacy_SHM_SH_UCODETIME 0x0006 /* Microcode time */ -#define B43legacy_SHM_SH_SPUWKUP 0x0094 /* pre-wakeup for synth PU in us */ -#define B43legacy_SHM_SH_PRETBTT 0x0096 /* pre-TBTT in us */ - -#define B43legacy_UCODEFLAGS_OFFSET 0x005E - -/* Hardware Radio Enable masks */ -#define B43legacy_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16) -#define B43legacy_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4) - -/* HostFlags. See b43legacy_hf_read/write() */ -#define B43legacy_HF_SYMW 0x00000002 /* G-PHY SYM workaround */ -#define B43legacy_HF_GDCW 0x00000020 /* G-PHY DV cancel filter */ -#define B43legacy_HF_OFDMPABOOST 0x00000040 /* Enable PA boost OFDM */ -#define B43legacy_HF_EDCF 0x00000100 /* on if WME/MAC suspended */ - -/* MacFilter offsets. */ -#define B43legacy_MACFILTER_SELF 0x0000 -#define B43legacy_MACFILTER_BSSID 0x0003 -#define B43legacy_MACFILTER_MAC 0x0010 - -/* PHYVersioning */ -#define B43legacy_PHYTYPE_B 0x01 -#define B43legacy_PHYTYPE_G 0x02 - -/* PHYRegisters */ -#define B43legacy_PHY_G_LO_CONTROL 0x0810 -#define B43legacy_PHY_ILT_G_CTRL 0x0472 -#define B43legacy_PHY_ILT_G_DATA1 0x0473 -#define B43legacy_PHY_ILT_G_DATA2 0x0474 -#define B43legacy_PHY_G_PCTL 0x0029 -#define B43legacy_PHY_RADIO_BITFIELD 0x0401 -#define B43legacy_PHY_G_CRS 0x0429 -#define B43legacy_PHY_NRSSILT_CTRL 0x0803 -#define B43legacy_PHY_NRSSILT_DATA 0x0804 - -/* RadioRegisters */ -#define B43legacy_RADIOCTL_ID 0x01 - -/* MAC Control bitfield */ -#define B43legacy_MACCTL_ENABLED 0x00000001 /* MAC Enabled */ -#define B43legacy_MACCTL_PSM_RUN 0x00000002 /* Run Microcode */ -#define B43legacy_MACCTL_PSM_JMP0 0x00000004 /* Microcode jump to 0 */ -#define B43legacy_MACCTL_SHM_ENABLED 0x00000100 /* SHM Enabled */ -#define B43legacy_MACCTL_IHR_ENABLED 0x00000400 /* IHR Region Enabled */ -#define B43legacy_MACCTL_BE 0x00010000 /* Big Endian mode */ -#define B43legacy_MACCTL_INFRA 0x00020000 /* Infrastructure mode */ -#define B43legacy_MACCTL_AP 0x00040000 /* AccessPoint mode */ -#define B43legacy_MACCTL_RADIOLOCK 0x00080000 /* Radio lock */ -#define B43legacy_MACCTL_BEACPROMISC 0x00100000 /* Beacon Promiscuous */ -#define B43legacy_MACCTL_KEEP_BADPLCP 0x00200000 /* Keep bad PLCP frames */ -#define B43legacy_MACCTL_KEEP_CTL 0x00400000 /* Keep control frames */ -#define B43legacy_MACCTL_KEEP_BAD 0x00800000 /* Keep bad frames (FCS) */ -#define B43legacy_MACCTL_PROMISC 0x01000000 /* Promiscuous mode */ -#define B43legacy_MACCTL_HWPS 0x02000000 /* Hardware Power Saving */ -#define B43legacy_MACCTL_AWAKE 0x04000000 /* Device is awake */ -#define B43legacy_MACCTL_TBTTHOLD 0x10000000 /* TBTT Hold */ -#define B43legacy_MACCTL_GMODE 0x80000000 /* G Mode */ - -/* MAC Command bitfield */ -#define B43legacy_MACCMD_BEACON0_VALID 0x00000001 /* Beacon 0 in template RAM is busy/valid */ -#define B43legacy_MACCMD_BEACON1_VALID 0x00000002 /* Beacon 1 in template RAM is busy/valid */ -#define B43legacy_MACCMD_DFQ_VALID 0x00000004 /* Directed frame queue valid (IBSS PS mode, ATIM) */ -#define B43legacy_MACCMD_CCA 0x00000008 /* Clear channel assessment */ -#define B43legacy_MACCMD_BGNOISE 0x00000010 /* Background noise */ - -/* 802.11 core specific TM State Low flags */ -#define B43legacy_TMSLOW_GMODE 0x20000000 /* G Mode Enable */ -#define B43legacy_TMSLOW_PLLREFSEL 0x00200000 /* PLL Freq Ref Select */ -#define B43legacy_TMSLOW_MACPHYCLKEN 0x00100000 /* MAC PHY Clock Ctrl Enbl */ -#define B43legacy_TMSLOW_PHYRESET 0x00080000 /* PHY Reset */ -#define B43legacy_TMSLOW_PHYCLKEN 0x00040000 /* PHY Clock Enable */ - -/* 802.11 core specific TM State High flags */ -#define B43legacy_TMSHIGH_FCLOCK 0x00040000 /* Fast Clock Available */ -#define B43legacy_TMSHIGH_GPHY 0x00010000 /* G-PHY avail (rev >= 5) */ - -#define B43legacy_UCODEFLAG_AUTODIV 0x0001 - -/* Generic-Interrupt reasons. */ -#define B43legacy_IRQ_MAC_SUSPENDED 0x00000001 -#define B43legacy_IRQ_BEACON 0x00000002 -#define B43legacy_IRQ_TBTT_INDI 0x00000004 /* Target Beacon Transmit Time */ -#define B43legacy_IRQ_BEACON_TX_OK 0x00000008 -#define B43legacy_IRQ_BEACON_CANCEL 0x00000010 -#define B43legacy_IRQ_ATIM_END 0x00000020 -#define B43legacy_IRQ_PMQ 0x00000040 -#define B43legacy_IRQ_PIO_WORKAROUND 0x00000100 -#define B43legacy_IRQ_MAC_TXERR 0x00000200 -#define B43legacy_IRQ_PHY_TXERR 0x00000800 -#define B43legacy_IRQ_PMEVENT 0x00001000 -#define B43legacy_IRQ_TIMER0 0x00002000 -#define B43legacy_IRQ_TIMER1 0x00004000 -#define B43legacy_IRQ_DMA 0x00008000 -#define B43legacy_IRQ_TXFIFO_FLUSH_OK 0x00010000 -#define B43legacy_IRQ_CCA_MEASURE_OK 0x00020000 -#define B43legacy_IRQ_NOISESAMPLE_OK 0x00040000 -#define B43legacy_IRQ_UCODE_DEBUG 0x08000000 -#define B43legacy_IRQ_RFKILL 0x10000000 -#define B43legacy_IRQ_TX_OK 0x20000000 -#define B43legacy_IRQ_PHY_G_CHANGED 0x40000000 -#define B43legacy_IRQ_TIMEOUT 0x80000000 - -#define B43legacy_IRQ_ALL 0xFFFFFFFF -#define B43legacy_IRQ_MASKTEMPLATE (B43legacy_IRQ_MAC_SUSPENDED | \ - B43legacy_IRQ_TBTT_INDI | \ - B43legacy_IRQ_ATIM_END | \ - B43legacy_IRQ_PMQ | \ - B43legacy_IRQ_MAC_TXERR | \ - B43legacy_IRQ_PHY_TXERR | \ - B43legacy_IRQ_DMA | \ - B43legacy_IRQ_TXFIFO_FLUSH_OK | \ - B43legacy_IRQ_NOISESAMPLE_OK | \ - B43legacy_IRQ_UCODE_DEBUG | \ - B43legacy_IRQ_RFKILL | \ - B43legacy_IRQ_TX_OK) - -/* Device specific rate values. - * The actual values defined here are (rate_in_mbps * 2). - * Some code depends on this. Don't change it. */ -#define B43legacy_CCK_RATE_1MB 2 -#define B43legacy_CCK_RATE_2MB 4 -#define B43legacy_CCK_RATE_5MB 11 -#define B43legacy_CCK_RATE_11MB 22 -#define B43legacy_OFDM_RATE_6MB 12 -#define B43legacy_OFDM_RATE_9MB 18 -#define B43legacy_OFDM_RATE_12MB 24 -#define B43legacy_OFDM_RATE_18MB 36 -#define B43legacy_OFDM_RATE_24MB 48 -#define B43legacy_OFDM_RATE_36MB 72 -#define B43legacy_OFDM_RATE_48MB 96 -#define B43legacy_OFDM_RATE_54MB 108 -/* Convert a b43legacy rate value to a rate in 100kbps */ -#define B43legacy_RATE_TO_100KBPS(rate) (((rate) * 10) / 2) - - -#define B43legacy_DEFAULT_SHORT_RETRY_LIMIT 7 -#define B43legacy_DEFAULT_LONG_RETRY_LIMIT 4 - -#define B43legacy_PHY_TX_BADNESS_LIMIT 1000 - -/* Max size of a security key */ -#define B43legacy_SEC_KEYSIZE 16 -/* Security algorithms. */ -enum { - B43legacy_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ - B43legacy_SEC_ALGO_WEP40, - B43legacy_SEC_ALGO_TKIP, - B43legacy_SEC_ALGO_AES, - B43legacy_SEC_ALGO_WEP104, - B43legacy_SEC_ALGO_AES_LEGACY, -}; - -/* Core Information Registers */ -#define B43legacy_CIR_BASE 0xf00 -#define B43legacy_CIR_SBTPSFLAG (B43legacy_CIR_BASE + 0x18) -#define B43legacy_CIR_SBIMSTATE (B43legacy_CIR_BASE + 0x90) -#define B43legacy_CIR_SBINTVEC (B43legacy_CIR_BASE + 0x94) -#define B43legacy_CIR_SBTMSTATELOW (B43legacy_CIR_BASE + 0x98) -#define B43legacy_CIR_SBTMSTATEHIGH (B43legacy_CIR_BASE + 0x9c) -#define B43legacy_CIR_SBIMCONFIGLOW (B43legacy_CIR_BASE + 0xa8) -#define B43legacy_CIR_SB_ID_HI (B43legacy_CIR_BASE + 0xfc) - -/* sbtmstatehigh state flags */ -#define B43legacy_SBTMSTATEHIGH_SERROR 0x00000001 -#define B43legacy_SBTMSTATEHIGH_BUSY 0x00000004 -#define B43legacy_SBTMSTATEHIGH_TIMEOUT 0x00000020 -#define B43legacy_SBTMSTATEHIGH_G_PHY_AVAIL 0x00010000 -#define B43legacy_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000 -#define B43legacy_SBTMSTATEHIGH_DMA64BIT 0x10000000 -#define B43legacy_SBTMSTATEHIGH_GATEDCLK 0x20000000 -#define B43legacy_SBTMSTATEHIGH_BISTFAILED 0x40000000 -#define B43legacy_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000 - -/* sbimstate flags */ -#define B43legacy_SBIMSTATE_IB_ERROR 0x20000 -#define B43legacy_SBIMSTATE_TIMEOUT 0x40000 - -#define PFX KBUILD_MODNAME ": " -#ifdef assert -# undef assert -#endif -#ifdef CONFIG_B43LEGACY_DEBUG -# define B43legacy_WARN_ON(x) WARN_ON(x) -# define B43legacy_BUG_ON(expr) \ - do { \ - if (unlikely((expr))) { \ - printk(KERN_INFO PFX "Test (%s) failed\n", \ - #expr); \ - BUG_ON(expr); \ - } \ - } while (0) -# define B43legacy_DEBUG 1 -#else -/* This will evaluate the argument even if debugging is disabled. */ -static inline bool __b43legacy_warn_on_dummy(bool x) { return x; } -# define B43legacy_WARN_ON(x) __b43legacy_warn_on_dummy(unlikely(!!(x))) -# define B43legacy_BUG_ON(x) do { /* nothing */ } while (0) -# define B43legacy_DEBUG 0 -#endif - - -struct net_device; -struct pci_dev; -struct b43legacy_dmaring; -struct b43legacy_pioqueue; - -/* The firmware file header */ -#define B43legacy_FW_TYPE_UCODE 'u' -#define B43legacy_FW_TYPE_PCM 'p' -#define B43legacy_FW_TYPE_IV 'i' -struct b43legacy_fw_header { - /* File type */ - u8 type; - /* File format version */ - u8 ver; - u8 __padding[2]; - /* Size of the data. For ucode and PCM this is in bytes. - * For IV this is number-of-ivs. */ - __be32 size; -} __attribute__((__packed__)); - -/* Initial Value file format */ -#define B43legacy_IV_OFFSET_MASK 0x7FFF -#define B43legacy_IV_32BIT 0x8000 -struct b43legacy_iv { - __be16 offset_size; - union { - __be16 d16; - __be32 d32; - } data __attribute__((__packed__)); -} __attribute__((__packed__)); - -#define B43legacy_PHYMODE(phytype) (1 << (phytype)) -#define B43legacy_PHYMODE_B B43legacy_PHYMODE \ - ((B43legacy_PHYTYPE_B)) -#define B43legacy_PHYMODE_G B43legacy_PHYMODE \ - ((B43legacy_PHYTYPE_G)) - -/* Value pair to measure the LocalOscillator. */ -struct b43legacy_lopair { - s8 low; - s8 high; - u8 used:1; -}; -#define B43legacy_LO_COUNT (14*4) - -struct b43legacy_phy { - /* Possible PHYMODEs on this PHY */ - u8 possible_phymodes; - /* GMODE bit enabled in MACCTL? */ - bool gmode; - - /* Analog Type */ - u8 analog; - /* B43legacy_PHYTYPE_ */ - u8 type; - /* PHY revision number. */ - u8 rev; - - u16 antenna_diversity; - u16 savedpctlreg; - /* Radio versioning */ - u16 radio_manuf; /* Radio manufacturer */ - u16 radio_ver; /* Radio version */ - u8 calibrated:1; - u8 radio_rev; /* Radio revision */ - - bool dyn_tssi_tbl; /* tssi2dbm is kmalloc()ed. */ - - /* ACI (adjacent channel interference) flags. */ - bool aci_enable; - bool aci_wlan_automatic; - bool aci_hw_rssi; - - /* Radio switched on/off */ - bool radio_on; - struct { - /* Values saved when turning the radio off. - * They are needed when turning it on again. */ - bool valid; - u16 rfover; - u16 rfoverval; - } radio_off_context; - - u16 minlowsig[2]; - u16 minlowsigpos[2]; - - /* LO Measurement Data. - * Use b43legacy_get_lopair() to get a value. - */ - struct b43legacy_lopair *_lo_pairs; - /* TSSI to dBm table in use */ - const s8 *tssi2dbm; - /* idle TSSI value */ - s8 idle_tssi; - /* Target idle TSSI */ - int tgt_idle_tssi; - /* Current idle TSSI */ - int cur_idle_tssi; - - /* LocalOscillator control values. */ - struct b43legacy_txpower_lo_control *lo_control; - /* Values from b43legacy_calc_loopback_gain() */ - s16 max_lb_gain; /* Maximum Loopback gain in hdB */ - s16 trsw_rx_gain; /* TRSW RX gain in hdB */ - s16 lna_lod_gain; /* LNA lod */ - s16 lna_gain; /* LNA */ - s16 pga_gain; /* PGA */ - - /* Desired TX power level (in dBm). This is set by the user and - * adjusted in b43legacy_phy_xmitpower(). */ - u8 power_level; - - /* Values from b43legacy_calc_loopback_gain() */ - u16 loopback_gain[2]; - - /* TX Power control values. */ - /* B/G PHY */ - struct { - /* Current Radio Attenuation for TXpower recalculation. */ - u16 rfatt; - /* Current Baseband Attenuation for TXpower recalculation. */ - u16 bbatt; - /* Current TXpower control value for TXpower recalculation. */ - u16 txctl1; - u16 txctl2; - }; - /* A PHY */ - struct { - u16 txpwr_offset; - }; - - /* Current Interference Mitigation mode */ - int interfmode; - /* Stack of saved values from the Interference Mitigation code. - * Each value in the stack is layed out as follows: - * bit 0-11: offset - * bit 12-15: register ID - * bit 16-32: value - * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT - */ -#define B43legacy_INTERFSTACK_SIZE 26 - u32 interfstack[B43legacy_INTERFSTACK_SIZE]; - - /* Saved values from the NRSSI Slope calculation */ - s16 nrssi[2]; - s32 nrssislope; - /* In memory nrssi lookup table. */ - s8 nrssi_lt[64]; - - /* current channel */ - u8 channel; - - u16 lofcal; - - u16 initval; - - /* PHY TX errors counter. */ - atomic_t txerr_cnt; - -#if B43legacy_DEBUG - /* Manual TX-power control enabled? */ - bool manual_txpower_control; - /* PHY registers locked by b43legacy_phy_lock()? */ - bool phy_locked; -#endif /* B43legacy_DEBUG */ -}; - -/* Data structures for DMA transmission, per 80211 core. */ -struct b43legacy_dma { - struct b43legacy_dmaring *tx_ring0; - struct b43legacy_dmaring *tx_ring1; - struct b43legacy_dmaring *tx_ring2; - struct b43legacy_dmaring *tx_ring3; - struct b43legacy_dmaring *tx_ring4; - struct b43legacy_dmaring *tx_ring5; - - struct b43legacy_dmaring *rx_ring0; - struct b43legacy_dmaring *rx_ring3; /* only on core.rev < 5 */ -}; - -/* Data structures for PIO transmission, per 80211 core. */ -struct b43legacy_pio { - struct b43legacy_pioqueue *queue0; - struct b43legacy_pioqueue *queue1; - struct b43legacy_pioqueue *queue2; - struct b43legacy_pioqueue *queue3; -}; - -/* Context information for a noise calculation (Link Quality). */ -struct b43legacy_noise_calculation { - u8 channel_at_start; - bool calculation_running; - u8 nr_samples; - s8 samples[8][4]; -}; - -struct b43legacy_stats { - u8 link_noise; - /* Store the last TX/RX times here for updating the leds. */ - unsigned long last_tx; - unsigned long last_rx; -}; - -struct b43legacy_key { - void *keyconf; - bool enabled; - u8 algorithm; -}; - -struct b43legacy_wldev; - -/* Data structure for the WLAN parts (802.11 cores) of the b43legacy chip. */ -struct b43legacy_wl { - /* Pointer to the active wireless device on this chip */ - struct b43legacy_wldev *current_dev; - /* Pointer to the ieee80211 hardware data structure */ - struct ieee80211_hw *hw; - - spinlock_t irq_lock; /* locks IRQ */ - struct mutex mutex; /* locks wireless core state */ - spinlock_t leds_lock; /* lock for leds */ - - /* We can only have one operating interface (802.11 core) - * at a time. General information about this interface follows. - */ - - struct ieee80211_vif *vif; - /* MAC address (can be NULL). */ - u8 mac_addr[ETH_ALEN]; - /* Current BSSID (can be NULL). */ - u8 bssid[ETH_ALEN]; - /* Interface type. (IEEE80211_IF_TYPE_XXX) */ - int if_type; - /* Is the card operating in AP, STA or IBSS mode? */ - bool operating; - /* filter flags */ - unsigned int filter_flags; - /* Stats about the wireless interface */ - struct ieee80211_low_level_stats ieee_stats; - -#ifdef CONFIG_B43LEGACY_HWRNG - struct hwrng rng; - u8 rng_initialized; - char rng_name[30 + 1]; -#endif - - /* List of all wireless devices on this chip */ - struct list_head devlist; - u8 nr_devs; - - bool radiotap_enabled; - bool radio_enabled; - - /* The beacon we are currently using (AP or IBSS mode). - * This beacon stuff is protected by the irq_lock. */ - struct sk_buff *current_beacon; - bool beacon0_uploaded; - bool beacon1_uploaded; - bool beacon_templates_virgin; /* Never wrote the templates? */ - struct work_struct beacon_update_trigger; -}; - -/* Pointers to the firmware data and meta information about it. */ -struct b43legacy_firmware { - /* Microcode */ - const struct firmware *ucode; - /* PCM code */ - const struct firmware *pcm; - /* Initial MMIO values for the firmware */ - const struct firmware *initvals; - /* Initial MMIO values for the firmware, band-specific */ - const struct firmware *initvals_band; - /* Firmware revision */ - u16 rev; - /* Firmware patchlevel */ - u16 patch; -}; - -/* Device (802.11 core) initialization status. */ -enum { - B43legacy_STAT_UNINIT = 0, /* Uninitialized. */ - B43legacy_STAT_INITIALIZED = 1, /* Initialized, not yet started. */ - B43legacy_STAT_STARTED = 2, /* Up and running. */ -}; -#define b43legacy_status(wldev) atomic_read(&(wldev)->__init_status) -#define b43legacy_set_status(wldev, stat) do { \ - atomic_set(&(wldev)->__init_status, (stat)); \ - smp_wmb(); \ - } while (0) - -/* *** --- HOW LOCKING WORKS IN B43legacy --- *** - * - * You should always acquire both, wl->mutex and wl->irq_lock unless: - * - You don't need to acquire wl->irq_lock, if the interface is stopped. - * - You don't need to acquire wl->mutex in the IRQ handler, IRQ tasklet - * and packet TX path (and _ONLY_ there.) - */ - -/* Data structure for one wireless device (802.11 core) */ -struct b43legacy_wldev { - struct ssb_device *dev; - struct b43legacy_wl *wl; - - /* The device initialization status. - * Use b43legacy_status() to query. */ - atomic_t __init_status; - /* Saved init status for handling suspend. */ - int suspend_init_status; - - bool __using_pio; /* Using pio rather than dma. */ - bool bad_frames_preempt;/* Use "Bad Frames Preemption". */ - bool dfq_valid; /* Directed frame queue valid (IBSS PS mode, ATIM). */ - bool short_preamble; /* TRUE if using short preamble. */ - bool radio_hw_enable; /* State of radio hardware enable bit. */ - - /* PHY/Radio device. */ - struct b43legacy_phy phy; - union { - /* DMA engines. */ - struct b43legacy_dma dma; - /* PIO engines. */ - struct b43legacy_pio pio; - }; - - /* Various statistics about the physical device. */ - struct b43legacy_stats stats; - - /* The device LEDs. */ - struct b43legacy_led led_tx; - struct b43legacy_led led_rx; - struct b43legacy_led led_assoc; - struct b43legacy_led led_radio; - - /* Reason code of the last interrupt. */ - u32 irq_reason; - u32 dma_reason[6]; - /* The currently active generic-interrupt mask. */ - u32 irq_mask; - /* Link Quality calculation context. */ - struct b43legacy_noise_calculation noisecalc; - /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ - int mac_suspended; - - /* Interrupt Service Routine tasklet (bottom-half) */ - struct tasklet_struct isr_tasklet; - - /* Periodic tasks */ - struct delayed_work periodic_work; - unsigned int periodic_state; - - struct work_struct restart_work; - - /* encryption/decryption */ - u16 ktp; /* Key table pointer */ - u8 max_nr_keys; - struct b43legacy_key key[58]; - - /* Firmware data */ - struct b43legacy_firmware fw; - - /* Devicelist in struct b43legacy_wl (all 802.11 cores) */ - struct list_head list; - - /* Debugging stuff follows. */ -#ifdef CONFIG_B43LEGACY_DEBUG - struct b43legacy_dfsentry *dfsentry; -#endif -}; - - -static inline -struct b43legacy_wl *hw_to_b43legacy_wl(struct ieee80211_hw *hw) -{ - return hw->priv; -} - -/* Helper function, which returns a boolean. - * TRUE, if PIO is used; FALSE, if DMA is used. - */ -#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) -static inline -int b43legacy_using_pio(struct b43legacy_wldev *dev) -{ - return dev->__using_pio; -} -#elif defined(CONFIG_B43LEGACY_DMA) -static inline -int b43legacy_using_pio(struct b43legacy_wldev *dev) -{ - return 0; -} -#elif defined(CONFIG_B43LEGACY_PIO) -static inline -int b43legacy_using_pio(struct b43legacy_wldev *dev) -{ - return 1; -} -#else -# error "Using neither DMA nor PIO? Confused..." -#endif - - -static inline -struct b43legacy_wldev *dev_to_b43legacy_wldev(struct device *dev) -{ - struct ssb_device *ssb_dev = dev_to_ssb_dev(dev); - return ssb_get_drvdata(ssb_dev); -} - -/* Is the device operating in a specified mode (IEEE80211_IF_TYPE_XXX). */ -static inline -int b43legacy_is_mode(struct b43legacy_wl *wl, int type) -{ - return (wl->operating && - wl->if_type == type); -} - -static inline -bool is_bcm_board_vendor(struct b43legacy_wldev *dev) -{ - return (dev->dev->bus->boardinfo.vendor == PCI_VENDOR_ID_BROADCOM); -} - -static inline -u16 b43legacy_read16(struct b43legacy_wldev *dev, u16 offset) -{ - return ssb_read16(dev->dev, offset); -} - -static inline -void b43legacy_write16(struct b43legacy_wldev *dev, u16 offset, u16 value) -{ - ssb_write16(dev->dev, offset, value); -} - -static inline -u32 b43legacy_read32(struct b43legacy_wldev *dev, u16 offset) -{ - return ssb_read32(dev->dev, offset); -} - -static inline -void b43legacy_write32(struct b43legacy_wldev *dev, u16 offset, u32 value) -{ - ssb_write32(dev->dev, offset, value); -} - -static inline -struct b43legacy_lopair *b43legacy_get_lopair(struct b43legacy_phy *phy, - u16 radio_attenuation, - u16 baseband_attenuation) -{ - return phy->_lo_pairs + (radio_attenuation - + 14 * (baseband_attenuation / 2)); -} - - - -/* Message printing */ -void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#if B43legacy_DEBUG -void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...) - __attribute__((format(printf, 2, 3))); -#else /* DEBUG */ -# define b43legacydbg(wl, fmt...) do { /* nothing */ } while (0) -#endif /* DEBUG */ - -/* Macros for printing a value in Q5.2 format */ -#define Q52_FMT "%u.%u" -#define Q52_ARG(q52) ((q52) / 4), (((q52) & 3) * 100 / 4) - -#endif /* B43legacy_H_ */ diff --git a/drivers/net/wireless/b43legacy/debugfs.c b/drivers/net/wireless/b43legacy/debugfs.c deleted file mode 100644 index 1f85ac569fec..000000000000 --- a/drivers/net/wireless/b43legacy/debugfs.c +++ /dev/null @@ -1,505 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - debugfs driver debugging code - - Copyright (c) 2005-2007 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "b43legacy.h" -#include "main.h" -#include "debugfs.h" -#include "dma.h" -#include "pio.h" -#include "xmit.h" - - -/* The root directory. */ -static struct dentry *rootdir; - -struct b43legacy_debugfs_fops { - ssize_t (*read)(struct b43legacy_wldev *dev, char *buf, size_t bufsize); - int (*write)(struct b43legacy_wldev *dev, const char *buf, size_t count); - struct file_operations fops; - /* Offset of struct b43legacy_dfs_file in struct b43legacy_dfsentry */ - size_t file_struct_offset; - /* Take wl->irq_lock before calling read/write? */ - bool take_irqlock; -}; - -static inline -struct b43legacy_dfs_file * fops_to_dfs_file(struct b43legacy_wldev *dev, - const struct b43legacy_debugfs_fops *dfops) -{ - void *p; - - p = dev->dfsentry; - p += dfops->file_struct_offset; - - return p; -} - - -#define fappend(fmt, x...) \ - do { \ - if (bufsize - count) \ - count += snprintf(buf + count, \ - bufsize - count, \ - fmt , ##x); \ - else \ - printk(KERN_ERR "b43legacy: fappend overflow\n"); \ - } while (0) - - -/* wl->irq_lock is locked */ -static ssize_t tsf_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize) -{ - ssize_t count = 0; - u64 tsf; - - b43legacy_tsf_read(dev, &tsf); - fappend("0x%08x%08x\n", - (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(tsf & 0xFFFFFFFFULL)); - - return count; -} - -/* wl->irq_lock is locked */ -static int tsf_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count) -{ - u64 tsf; - - if (sscanf(buf, "%llu", (unsigned long long *)(&tsf)) != 1) - return -EINVAL; - b43legacy_tsf_write(dev, tsf); - - return 0; -} - -/* wl->irq_lock is locked */ -static ssize_t ucode_regs_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize) -{ - ssize_t count = 0; - int i; - - for (i = 0; i < 64; i++) { - fappend("r%d = 0x%04x\n", i, - b43legacy_shm_read16(dev, B43legacy_SHM_WIRELESS, i)); - } - - return count; -} - -/* wl->irq_lock is locked */ -static ssize_t shm_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize) -{ - ssize_t count = 0; - int i; - u16 tmp; - __le16 *le16buf = (__le16 *)buf; - - for (i = 0; i < 0x1000; i++) { - if (bufsize < sizeof(tmp)) - break; - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 2 * i); - le16buf[i] = cpu_to_le16(tmp); - count += sizeof(tmp); - bufsize -= sizeof(tmp); - } - - return count; -} - -static ssize_t txstat_read_file(struct b43legacy_wldev *dev, char *buf, size_t bufsize) -{ - struct b43legacy_txstatus_log *log = &dev->dfsentry->txstatlog; - ssize_t count = 0; - unsigned long flags; - int i, idx; - struct b43legacy_txstatus *stat; - - spin_lock_irqsave(&log->lock, flags); - if (log->end < 0) { - fappend("Nothing transmitted, yet\n"); - goto out_unlock; - } - fappend("b43legacy TX status reports:\n\n" - "index | cookie | seq | phy_stat | frame_count | " - "rts_count | supp_reason | pm_indicated | " - "intermediate | for_ampdu | acked\n" "---\n"); - i = log->end + 1; - idx = 0; - while (1) { - if (i == B43legacy_NR_LOGGED_TXSTATUS) - i = 0; - stat = &(log->log[i]); - if (stat->cookie) { - fappend("%03d | " - "0x%04X | 0x%04X | 0x%02X | " - "0x%X | 0x%X | " - "%u | %u | " - "%u | %u | %u\n", - idx, - stat->cookie, stat->seq, stat->phy_stat, - stat->frame_count, stat->rts_count, - stat->supp_reason, stat->pm_indicated, - stat->intermediate, stat->for_ampdu, - stat->acked); - idx++; - } - if (i == log->end) - break; - i++; - } -out_unlock: - spin_unlock_irqrestore(&log->lock, flags); - - return count; -} - -/* wl->irq_lock is locked */ -static int restart_write_file(struct b43legacy_wldev *dev, const char *buf, size_t count) -{ - int err = 0; - - if (count > 0 && buf[0] == '1') { - b43legacy_controller_restart(dev, "manually restarted"); - } else - err = -EINVAL; - - return err; -} - -#undef fappend - -static int b43legacy_debugfs_open(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t b43legacy_debugfs_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct b43legacy_wldev *dev; - struct b43legacy_debugfs_fops *dfops; - struct b43legacy_dfs_file *dfile; - ssize_t uninitialized_var(ret); - char *buf; - const size_t bufsize = 1024 * 16; /* 16 KiB buffer */ - const size_t buforder = get_order(bufsize); - int err = 0; - - if (!count) - return 0; - dev = file->private_data; - if (!dev) - return -ENODEV; - - mutex_lock(&dev->wl->mutex); - if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { - err = -ENODEV; - goto out_unlock; - } - - dfops = container_of(file->f_op, struct b43legacy_debugfs_fops, fops); - if (!dfops->read) { - err = -ENOSYS; - goto out_unlock; - } - dfile = fops_to_dfs_file(dev, dfops); - - if (!dfile->buffer) { - buf = (char *)__get_free_pages(GFP_KERNEL, buforder); - if (!buf) { - err = -ENOMEM; - goto out_unlock; - } - memset(buf, 0, bufsize); - if (dfops->take_irqlock) { - spin_lock_irq(&dev->wl->irq_lock); - ret = dfops->read(dev, buf, bufsize); - spin_unlock_irq(&dev->wl->irq_lock); - } else - ret = dfops->read(dev, buf, bufsize); - if (ret <= 0) { - free_pages((unsigned long)buf, buforder); - err = ret; - goto out_unlock; - } - dfile->data_len = ret; - dfile->buffer = buf; - } - - ret = simple_read_from_buffer(userbuf, count, ppos, - dfile->buffer, - dfile->data_len); - if (*ppos >= dfile->data_len) { - free_pages((unsigned long)dfile->buffer, buforder); - dfile->buffer = NULL; - dfile->data_len = 0; - } -out_unlock: - mutex_unlock(&dev->wl->mutex); - - return err ? err : ret; -} - -static ssize_t b43legacy_debugfs_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct b43legacy_wldev *dev; - struct b43legacy_debugfs_fops *dfops; - char *buf; - int err = 0; - - if (!count) - return 0; - if (count > PAGE_SIZE) - return -E2BIG; - dev = file->private_data; - if (!dev) - return -ENODEV; - - mutex_lock(&dev->wl->mutex); - if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { - err = -ENODEV; - goto out_unlock; - } - - dfops = container_of(file->f_op, struct b43legacy_debugfs_fops, fops); - if (!dfops->write) { - err = -ENOSYS; - goto out_unlock; - } - - buf = (char *)get_zeroed_page(GFP_KERNEL); - if (!buf) { - err = -ENOMEM; - goto out_unlock; - } - if (copy_from_user(buf, userbuf, count)) { - err = -EFAULT; - goto out_freepage; - } - if (dfops->take_irqlock) { - spin_lock_irq(&dev->wl->irq_lock); - err = dfops->write(dev, buf, count); - spin_unlock_irq(&dev->wl->irq_lock); - } else - err = dfops->write(dev, buf, count); - if (err) - goto out_freepage; - -out_freepage: - free_page((unsigned long)buf); -out_unlock: - mutex_unlock(&dev->wl->mutex); - - return err ? err : count; -} - - -#define B43legacy_DEBUGFS_FOPS(name, _read, _write, _take_irqlock) \ - static struct b43legacy_debugfs_fops fops_##name = { \ - .read = _read, \ - .write = _write, \ - .fops = { \ - .open = b43legacy_debugfs_open, \ - .read = b43legacy_debugfs_read, \ - .write = b43legacy_debugfs_write, \ - }, \ - .file_struct_offset = offsetof(struct b43legacy_dfsentry, \ - file_##name), \ - .take_irqlock = _take_irqlock, \ - } - -B43legacy_DEBUGFS_FOPS(tsf, tsf_read_file, tsf_write_file, 1); -B43legacy_DEBUGFS_FOPS(ucode_regs, ucode_regs_read_file, NULL, 1); -B43legacy_DEBUGFS_FOPS(shm, shm_read_file, NULL, 1); -B43legacy_DEBUGFS_FOPS(txstat, txstat_read_file, NULL, 0); -B43legacy_DEBUGFS_FOPS(restart, NULL, restart_write_file, 1); - - -int b43legacy_debug(struct b43legacy_wldev *dev, enum b43legacy_dyndbg feature) -{ - return !!(dev->dfsentry && dev->dfsentry->dyn_debug[feature]); -} - -static void b43legacy_remove_dynamic_debug(struct b43legacy_wldev *dev) -{ - struct b43legacy_dfsentry *e = dev->dfsentry; - int i; - - for (i = 0; i < __B43legacy_NR_DYNDBG; i++) - debugfs_remove(e->dyn_debug_dentries[i]); -} - -static void b43legacy_add_dynamic_debug(struct b43legacy_wldev *dev) -{ - struct b43legacy_dfsentry *e = dev->dfsentry; - struct dentry *d; - -#define add_dyn_dbg(name, id, initstate) do { \ - e->dyn_debug[id] = (initstate); \ - d = debugfs_create_bool(name, 0600, e->subdir, \ - &(e->dyn_debug[id])); \ - if (!IS_ERR(d)) \ - e->dyn_debug_dentries[id] = d; \ - } while (0) - - add_dyn_dbg("debug_xmitpower", B43legacy_DBG_XMITPOWER, 0); - add_dyn_dbg("debug_dmaoverflow", B43legacy_DBG_DMAOVERFLOW, 0); - add_dyn_dbg("debug_dmaverbose", B43legacy_DBG_DMAVERBOSE, 0); - add_dyn_dbg("debug_pwork_fast", B43legacy_DBG_PWORK_FAST, 0); - add_dyn_dbg("debug_pwork_stop", B43legacy_DBG_PWORK_STOP, 0); - -#undef add_dyn_dbg -} - -void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev) -{ - struct b43legacy_dfsentry *e; - struct b43legacy_txstatus_log *log; - char devdir[16]; - - B43legacy_WARN_ON(!dev); - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - b43legacyerr(dev->wl, "debugfs: add device OOM\n"); - return; - } - e->dev = dev; - log = &e->txstatlog; - log->log = kcalloc(B43legacy_NR_LOGGED_TXSTATUS, - sizeof(struct b43legacy_txstatus), GFP_KERNEL); - if (!log->log) { - b43legacyerr(dev->wl, "debugfs: add device txstatus OOM\n"); - kfree(e); - return; - } - log->end = -1; - spin_lock_init(&log->lock); - - dev->dfsentry = e; - - snprintf(devdir, sizeof(devdir), "%s", wiphy_name(dev->wl->hw->wiphy)); - e->subdir = debugfs_create_dir(devdir, rootdir); - if (!e->subdir || IS_ERR(e->subdir)) { - if (e->subdir == ERR_PTR(-ENODEV)) { - b43legacydbg(dev->wl, "DebugFS (CONFIG_DEBUG_FS) not " - "enabled in kernel config\n"); - } else { - b43legacyerr(dev->wl, "debugfs: cannot create %s directory\n", - devdir); - } - dev->dfsentry = NULL; - kfree(log->log); - kfree(e); - return; - } - -#define ADD_FILE(name, mode) \ - do { \ - struct dentry *d; \ - d = debugfs_create_file(__stringify(name), \ - mode, e->subdir, dev, \ - &fops_##name.fops); \ - e->file_##name.dentry = NULL; \ - if (!IS_ERR(d)) \ - e->file_##name.dentry = d; \ - } while (0) - - - ADD_FILE(tsf, 0600); - ADD_FILE(ucode_regs, 0400); - ADD_FILE(shm, 0400); - ADD_FILE(txstat, 0400); - ADD_FILE(restart, 0200); - -#undef ADD_FILE - - b43legacy_add_dynamic_debug(dev); -} - -void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev) -{ - struct b43legacy_dfsentry *e; - - if (!dev) - return; - e = dev->dfsentry; - if (!e) - return; - b43legacy_remove_dynamic_debug(dev); - - debugfs_remove(e->file_tsf.dentry); - debugfs_remove(e->file_ucode_regs.dentry); - debugfs_remove(e->file_shm.dentry); - debugfs_remove(e->file_txstat.dentry); - debugfs_remove(e->file_restart.dentry); - - debugfs_remove(e->subdir); - kfree(e->txstatlog.log); - kfree(e); -} - -void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) -{ - struct b43legacy_dfsentry *e = dev->dfsentry; - struct b43legacy_txstatus_log *log; - struct b43legacy_txstatus *cur; - int i; - - if (!e) - return; - log = &e->txstatlog; - B43legacy_WARN_ON(!irqs_disabled()); - spin_lock(&log->lock); - i = log->end + 1; - if (i == B43legacy_NR_LOGGED_TXSTATUS) - i = 0; - log->end = i; - cur = &(log->log[i]); - memcpy(cur, status, sizeof(*cur)); - spin_unlock(&log->lock); -} - -void b43legacy_debugfs_init(void) -{ - rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (IS_ERR(rootdir)) - rootdir = NULL; -} - -void b43legacy_debugfs_exit(void) -{ - debugfs_remove(rootdir); -} diff --git a/drivers/net/wireless/b43legacy/debugfs.h b/drivers/net/wireless/b43legacy/debugfs.h deleted file mode 100644 index ae3b0d0fa849..000000000000 --- a/drivers/net/wireless/b43legacy/debugfs.h +++ /dev/null @@ -1,89 +0,0 @@ -#ifndef B43legacy_DEBUGFS_H_ -#define B43legacy_DEBUGFS_H_ - -struct b43legacy_wldev; -struct b43legacy_txstatus; - -enum b43legacy_dyndbg { /* Dynamic debugging features */ - B43legacy_DBG_XMITPOWER, - B43legacy_DBG_DMAOVERFLOW, - B43legacy_DBG_DMAVERBOSE, - B43legacy_DBG_PWORK_FAST, - B43legacy_DBG_PWORK_STOP, - __B43legacy_NR_DYNDBG, -}; - - -#ifdef CONFIG_B43LEGACY_DEBUG - -struct dentry; - -#define B43legacy_NR_LOGGED_TXSTATUS 100 - -struct b43legacy_txstatus_log { - struct b43legacy_txstatus *log; - int end; - spinlock_t lock; /* lock for debugging */ -}; - -struct b43legacy_dfs_file { - struct dentry *dentry; - char *buffer; - size_t data_len; -}; - -struct b43legacy_dfsentry { - struct b43legacy_wldev *dev; - struct dentry *subdir; - - struct b43legacy_dfs_file file_tsf; - struct b43legacy_dfs_file file_ucode_regs; - struct b43legacy_dfs_file file_shm; - struct b43legacy_dfs_file file_txstat; - struct b43legacy_dfs_file file_txpower_g; - struct b43legacy_dfs_file file_restart; - struct b43legacy_dfs_file file_loctls; - - struct b43legacy_txstatus_log txstatlog; - - /* Enabled/Disabled list for the dynamic debugging features. */ - u32 dyn_debug[__B43legacy_NR_DYNDBG]; - /* Dentries for the dynamic debugging entries. */ - struct dentry *dyn_debug_dentries[__B43legacy_NR_DYNDBG]; -}; - -int b43legacy_debug(struct b43legacy_wldev *dev, - enum b43legacy_dyndbg feature); - -void b43legacy_debugfs_init(void); -void b43legacy_debugfs_exit(void); -void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev); -void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev); -void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status); - -#else /* CONFIG_B43LEGACY_DEBUG*/ - -static inline -int b43legacy_debug(struct b43legacy_wldev *dev, - enum b43legacy_dyndbg feature) -{ - return 0; -} - -static inline -void b43legacy_debugfs_init(void) { } -static inline -void b43legacy_debugfs_exit(void) { } -static inline -void b43legacy_debugfs_add_device(struct b43legacy_wldev *dev) { } -static inline -void b43legacy_debugfs_remove_device(struct b43legacy_wldev *dev) { } -static inline -void b43legacy_debugfs_log_txstat(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) - { } - -#endif /* CONFIG_B43LEGACY_DEBUG*/ - -#endif /* B43legacy_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c deleted file mode 100644 index 866403415811..000000000000 --- a/drivers/net/wireless/b43legacy/dma.c +++ /dev/null @@ -1,1696 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - DMA ringbuffer and descriptor allocation/management - - Copyright (c) 2005, 2006 Michael Buesch - - Some code in this file is derived from the b44.c driver - Copyright (C) 2002 David S. Miller - Copyright (C) Pekka Pietikainen - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43legacy.h" -#include "dma.h" -#include "main.h" -#include "debugfs.h" -#include "xmit.h" - -#include -#include -#include -#include -#include - -/* 32bit DMA ops. */ -static -struct b43legacy_dmadesc_generic *op32_idx2desc( - struct b43legacy_dmaring *ring, - int slot, - struct b43legacy_dmadesc_meta **meta) -{ - struct b43legacy_dmadesc32 *desc; - - *meta = &(ring->meta[slot]); - desc = ring->descbase; - desc = &(desc[slot]); - - return (struct b43legacy_dmadesc_generic *)desc; -} - -static void op32_fill_descriptor(struct b43legacy_dmaring *ring, - struct b43legacy_dmadesc_generic *desc, - dma_addr_t dmaaddr, u16 bufsize, - int start, int end, int irq) -{ - struct b43legacy_dmadesc32 *descbase = ring->descbase; - int slot; - u32 ctl; - u32 addr; - u32 addrext; - - slot = (int)(&(desc->dma32) - descbase); - B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - - addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK); - addrext = (u32)(dmaaddr & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - addr |= ssb_dma_translation(ring->dev->dev); - ctl = (bufsize - ring->frameoffset) - & B43legacy_DMA32_DCTL_BYTECNT; - if (slot == ring->nr_slots - 1) - ctl |= B43legacy_DMA32_DCTL_DTABLEEND; - if (start) - ctl |= B43legacy_DMA32_DCTL_FRAMESTART; - if (end) - ctl |= B43legacy_DMA32_DCTL_FRAMEEND; - if (irq) - ctl |= B43legacy_DMA32_DCTL_IRQ; - ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT) - & B43legacy_DMA32_DCTL_ADDREXT_MASK; - - desc->dma32.control = cpu_to_le32(ctl); - desc->dma32.address = cpu_to_le32(addr); -} - -static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot) -{ - b43legacy_dma_write(ring, B43legacy_DMA32_TXINDEX, - (u32)(slot * sizeof(struct b43legacy_dmadesc32))); -} - -static void op32_tx_suspend(struct b43legacy_dmaring *ring) -{ - b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, - b43legacy_dma_read(ring, B43legacy_DMA32_TXCTL) - | B43legacy_DMA32_TXSUSPEND); -} - -static void op32_tx_resume(struct b43legacy_dmaring *ring) -{ - b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, - b43legacy_dma_read(ring, B43legacy_DMA32_TXCTL) - & ~B43legacy_DMA32_TXSUSPEND); -} - -static int op32_get_current_rxslot(struct b43legacy_dmaring *ring) -{ - u32 val; - - val = b43legacy_dma_read(ring, B43legacy_DMA32_RXSTATUS); - val &= B43legacy_DMA32_RXDPTR; - - return (val / sizeof(struct b43legacy_dmadesc32)); -} - -static void op32_set_current_rxslot(struct b43legacy_dmaring *ring, - int slot) -{ - b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, - (u32)(slot * sizeof(struct b43legacy_dmadesc32))); -} - -static const struct b43legacy_dma_ops dma32_ops = { - .idx2desc = op32_idx2desc, - .fill_descriptor = op32_fill_descriptor, - .poke_tx = op32_poke_tx, - .tx_suspend = op32_tx_suspend, - .tx_resume = op32_tx_resume, - .get_current_rxslot = op32_get_current_rxslot, - .set_current_rxslot = op32_set_current_rxslot, -}; - -/* 64bit DMA ops. */ -static -struct b43legacy_dmadesc_generic *op64_idx2desc( - struct b43legacy_dmaring *ring, - int slot, - struct b43legacy_dmadesc_meta - **meta) -{ - struct b43legacy_dmadesc64 *desc; - - *meta = &(ring->meta[slot]); - desc = ring->descbase; - desc = &(desc[slot]); - - return (struct b43legacy_dmadesc_generic *)desc; -} - -static void op64_fill_descriptor(struct b43legacy_dmaring *ring, - struct b43legacy_dmadesc_generic *desc, - dma_addr_t dmaaddr, u16 bufsize, - int start, int end, int irq) -{ - struct b43legacy_dmadesc64 *descbase = ring->descbase; - int slot; - u32 ctl0 = 0; - u32 ctl1 = 0; - u32 addrlo; - u32 addrhi; - u32 addrext; - - slot = (int)(&(desc->dma64) - descbase); - B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - - addrlo = (u32)(dmaaddr & 0xFFFFFFFF); - addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK); - addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - addrhi |= ssb_dma_translation(ring->dev->dev); - if (slot == ring->nr_slots - 1) - ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND; - if (start) - ctl0 |= B43legacy_DMA64_DCTL0_FRAMESTART; - if (end) - ctl0 |= B43legacy_DMA64_DCTL0_FRAMEEND; - if (irq) - ctl0 |= B43legacy_DMA64_DCTL0_IRQ; - ctl1 |= (bufsize - ring->frameoffset) - & B43legacy_DMA64_DCTL1_BYTECNT; - ctl1 |= (addrext << B43legacy_DMA64_DCTL1_ADDREXT_SHIFT) - & B43legacy_DMA64_DCTL1_ADDREXT_MASK; - - desc->dma64.control0 = cpu_to_le32(ctl0); - desc->dma64.control1 = cpu_to_le32(ctl1); - desc->dma64.address_low = cpu_to_le32(addrlo); - desc->dma64.address_high = cpu_to_le32(addrhi); -} - -static void op64_poke_tx(struct b43legacy_dmaring *ring, int slot) -{ - b43legacy_dma_write(ring, B43legacy_DMA64_TXINDEX, - (u32)(slot * sizeof(struct b43legacy_dmadesc64))); -} - -static void op64_tx_suspend(struct b43legacy_dmaring *ring) -{ - b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL, - b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL) - | B43legacy_DMA64_TXSUSPEND); -} - -static void op64_tx_resume(struct b43legacy_dmaring *ring) -{ - b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL, - b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL) - & ~B43legacy_DMA64_TXSUSPEND); -} - -static int op64_get_current_rxslot(struct b43legacy_dmaring *ring) -{ - u32 val; - - val = b43legacy_dma_read(ring, B43legacy_DMA64_RXSTATUS); - val &= B43legacy_DMA64_RXSTATDPTR; - - return (val / sizeof(struct b43legacy_dmadesc64)); -} - -static void op64_set_current_rxslot(struct b43legacy_dmaring *ring, - int slot) -{ - b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX, - (u32)(slot * sizeof(struct b43legacy_dmadesc64))); -} - -static const struct b43legacy_dma_ops dma64_ops = { - .idx2desc = op64_idx2desc, - .fill_descriptor = op64_fill_descriptor, - .poke_tx = op64_poke_tx, - .tx_suspend = op64_tx_suspend, - .tx_resume = op64_tx_resume, - .get_current_rxslot = op64_get_current_rxslot, - .set_current_rxslot = op64_set_current_rxslot, -}; - - -static inline int free_slots(struct b43legacy_dmaring *ring) -{ - return (ring->nr_slots - ring->used_slots); -} - -static inline int next_slot(struct b43legacy_dmaring *ring, int slot) -{ - B43legacy_WARN_ON(!(slot >= -1 && slot <= ring->nr_slots - 1)); - if (slot == ring->nr_slots - 1) - return 0; - return slot + 1; -} - -static inline int prev_slot(struct b43legacy_dmaring *ring, int slot) -{ - B43legacy_WARN_ON(!(slot >= 0 && slot <= ring->nr_slots - 1)); - if (slot == 0) - return ring->nr_slots - 1; - return slot - 1; -} - -#ifdef CONFIG_B43LEGACY_DEBUG -static void update_max_used_slots(struct b43legacy_dmaring *ring, - int current_used_slots) -{ - if (current_used_slots <= ring->max_used_slots) - return; - ring->max_used_slots = current_used_slots; - if (b43legacy_debug(ring->dev, B43legacy_DBG_DMAVERBOSE)) - b43legacydbg(ring->dev->wl, - "max_used_slots increased to %d on %s ring %d\n", - ring->max_used_slots, - ring->tx ? "TX" : "RX", - ring->index); -} -#else -static inline -void update_max_used_slots(struct b43legacy_dmaring *ring, - int current_used_slots) -{ } -#endif /* DEBUG */ - -/* Request a slot for usage. */ -static inline -int request_slot(struct b43legacy_dmaring *ring) -{ - int slot; - - B43legacy_WARN_ON(!ring->tx); - B43legacy_WARN_ON(ring->stopped); - B43legacy_WARN_ON(free_slots(ring) == 0); - - slot = next_slot(ring, ring->current_slot); - ring->current_slot = slot; - ring->used_slots++; - - update_max_used_slots(ring, ring->used_slots); - - return slot; -} - -/* Mac80211-queue to b43legacy-ring mapping */ -static struct b43legacy_dmaring *priority_to_txring( - struct b43legacy_wldev *dev, - int queue_priority) -{ - struct b43legacy_dmaring *ring; - -/*FIXME: For now we always run on TX-ring-1 */ -return dev->dma.tx_ring1; - - /* 0 = highest priority */ - switch (queue_priority) { - default: - B43legacy_WARN_ON(1); - /* fallthrough */ - case 0: - ring = dev->dma.tx_ring3; - break; - case 1: - ring = dev->dma.tx_ring2; - break; - case 2: - ring = dev->dma.tx_ring1; - break; - case 3: - ring = dev->dma.tx_ring0; - break; - case 4: - ring = dev->dma.tx_ring4; - break; - case 5: - ring = dev->dma.tx_ring5; - break; - } - - return ring; -} - -/* Bcm4301-ring to mac80211-queue mapping */ -static inline int txring_to_priority(struct b43legacy_dmaring *ring) -{ - static const u8 idx_to_prio[] = - { 3, 2, 1, 0, 4, 5, }; - -/*FIXME: have only one queue, for now */ -return 0; - - return idx_to_prio[ring->index]; -} - - -static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type, - int controller_idx) -{ - static const u16 map64[] = { - B43legacy_MMIO_DMA64_BASE0, - B43legacy_MMIO_DMA64_BASE1, - B43legacy_MMIO_DMA64_BASE2, - B43legacy_MMIO_DMA64_BASE3, - B43legacy_MMIO_DMA64_BASE4, - B43legacy_MMIO_DMA64_BASE5, - }; - static const u16 map32[] = { - B43legacy_MMIO_DMA32_BASE0, - B43legacy_MMIO_DMA32_BASE1, - B43legacy_MMIO_DMA32_BASE2, - B43legacy_MMIO_DMA32_BASE3, - B43legacy_MMIO_DMA32_BASE4, - B43legacy_MMIO_DMA32_BASE5, - }; - - if (type == B43legacy_DMA_64BIT) { - B43legacy_WARN_ON(!(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map64))); - return map64[controller_idx]; - } - B43legacy_WARN_ON(!(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map32))); - return map32[controller_idx]; -} - -static inline -dma_addr_t map_descbuffer(struct b43legacy_dmaring *ring, - unsigned char *buf, - size_t len, - int tx) -{ - dma_addr_t dmaaddr; - - if (tx) - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, - DMA_TO_DEVICE); - else - dmaaddr = ssb_dma_map_single(ring->dev->dev, - buf, len, - DMA_FROM_DEVICE); - - return dmaaddr; -} - -static inline -void unmap_descbuffer(struct b43legacy_dmaring *ring, - dma_addr_t addr, - size_t len, - int tx) -{ - if (tx) - ssb_dma_unmap_single(ring->dev->dev, - addr, len, - DMA_TO_DEVICE); - else - ssb_dma_unmap_single(ring->dev->dev, - addr, len, - DMA_FROM_DEVICE); -} - -static inline -void sync_descbuffer_for_cpu(struct b43legacy_dmaring *ring, - dma_addr_t addr, - size_t len) -{ - B43legacy_WARN_ON(ring->tx); - - ssb_dma_sync_single_for_cpu(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); -} - -static inline -void sync_descbuffer_for_device(struct b43legacy_dmaring *ring, - dma_addr_t addr, - size_t len) -{ - B43legacy_WARN_ON(ring->tx); - - ssb_dma_sync_single_for_device(ring->dev->dev, - addr, len, DMA_FROM_DEVICE); -} - -static inline -void free_descriptor_buffer(struct b43legacy_dmaring *ring, - struct b43legacy_dmadesc_meta *meta, - int irq_context) -{ - if (meta->skb) { - if (irq_context) - dev_kfree_skb_irq(meta->skb); - else - dev_kfree_skb(meta->skb); - meta->skb = NULL; - } -} - -static int alloc_ringmemory(struct b43legacy_dmaring *ring) -{ - /* GFP flags must match the flags in free_ringmemory()! */ - ring->descbase = ssb_dma_alloc_consistent(ring->dev->dev, - B43legacy_DMA_RINGMEMSIZE, - &(ring->dmabase), - GFP_KERNEL); - if (!ring->descbase) { - b43legacyerr(ring->dev->wl, "DMA ringmemory allocation" - " failed\n"); - return -ENOMEM; - } - memset(ring->descbase, 0, B43legacy_DMA_RINGMEMSIZE); - - return 0; -} - -static void free_ringmemory(struct b43legacy_dmaring *ring) -{ - ssb_dma_free_consistent(ring->dev->dev, B43legacy_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase, GFP_KERNEL); -} - -/* Reset the RX DMA channel */ -static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev, - u16 mmio_base, - enum b43legacy_dmatype type) -{ - int i; - u32 value; - u16 offset; - - might_sleep(); - - offset = (type == B43legacy_DMA_64BIT) ? - B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL; - b43legacy_write32(dev, mmio_base + offset, 0); - for (i = 0; i < 10; i++) { - offset = (type == B43legacy_DMA_64BIT) ? - B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS; - value = b43legacy_read32(dev, mmio_base + offset); - if (type == B43legacy_DMA_64BIT) { - value &= B43legacy_DMA64_RXSTAT; - if (value == B43legacy_DMA64_RXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= B43legacy_DMA32_RXSTATE; - if (value == B43legacy_DMA32_RXSTAT_DISABLED) { - i = -1; - break; - } - } - msleep(1); - } - if (i != -1) { - b43legacyerr(dev->wl, "DMA RX reset timed out\n"); - return -ENODEV; - } - - return 0; -} - -/* Reset the RX DMA channel */ -static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev, - u16 mmio_base, - enum b43legacy_dmatype type) -{ - int i; - u32 value; - u16 offset; - - might_sleep(); - - for (i = 0; i < 10; i++) { - offset = (type == B43legacy_DMA_64BIT) ? - B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS; - value = b43legacy_read32(dev, mmio_base + offset); - if (type == B43legacy_DMA_64BIT) { - value &= B43legacy_DMA64_TXSTAT; - if (value == B43legacy_DMA64_TXSTAT_DISABLED || - value == B43legacy_DMA64_TXSTAT_IDLEWAIT || - value == B43legacy_DMA64_TXSTAT_STOPPED) - break; - } else { - value &= B43legacy_DMA32_TXSTATE; - if (value == B43legacy_DMA32_TXSTAT_DISABLED || - value == B43legacy_DMA32_TXSTAT_IDLEWAIT || - value == B43legacy_DMA32_TXSTAT_STOPPED) - break; - } - msleep(1); - } - offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL : - B43legacy_DMA32_TXCTL; - b43legacy_write32(dev, mmio_base + offset, 0); - for (i = 0; i < 10; i++) { - offset = (type == B43legacy_DMA_64BIT) ? - B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS; - value = b43legacy_read32(dev, mmio_base + offset); - if (type == B43legacy_DMA_64BIT) { - value &= B43legacy_DMA64_TXSTAT; - if (value == B43legacy_DMA64_TXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= B43legacy_DMA32_TXSTATE; - if (value == B43legacy_DMA32_TXSTAT_DISABLED) { - i = -1; - break; - } - } - msleep(1); - } - if (i != -1) { - b43legacyerr(dev->wl, "DMA TX reset timed out\n"); - return -ENODEV; - } - /* ensure the reset is completed. */ - msleep(1); - - return 0; -} - -/* Check if a DMA mapping address is invalid. */ -static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring, - dma_addr_t addr, - size_t buffersize, - bool dma_to_device) -{ - if (unlikely(ssb_dma_mapping_error(ring->dev->dev, addr))) - return 1; - - switch (ring->type) { - case B43legacy_DMA_30BIT: - if ((u64)addr + buffersize > (1ULL << 30)) - goto address_error; - break; - case B43legacy_DMA_32BIT: - if ((u64)addr + buffersize > (1ULL << 32)) - goto address_error; - break; - case B43legacy_DMA_64BIT: - /* Currently we can't have addresses beyond 64 bits in the kernel. */ - break; - } - - /* The address is OK. */ - return 0; - -address_error: - /* We can't support this address. Unmap it again. */ - unmap_descbuffer(ring, addr, buffersize, dma_to_device); - - return 1; -} - -static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, - struct b43legacy_dmadesc_generic *desc, - struct b43legacy_dmadesc_meta *meta, - gfp_t gfp_flags) -{ - struct b43legacy_rxhdr_fw3 *rxhdr; - struct b43legacy_hwtxstatus *txstat; - dma_addr_t dmaaddr; - struct sk_buff *skb; - - B43legacy_WARN_ON(ring->tx); - - skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); - if (unlikely(!skb)) - return -ENOMEM; - dmaaddr = map_descbuffer(ring, skb->data, - ring->rx_buffersize, 0); - if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { - /* ugh. try to realloc in zone_dma */ - gfp_flags |= GFP_DMA; - - dev_kfree_skb_any(skb); - - skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); - if (unlikely(!skb)) - return -ENOMEM; - dmaaddr = map_descbuffer(ring, skb->data, - ring->rx_buffersize, 0); - } - - if (b43legacy_dma_mapping_error(ring, dmaaddr, ring->rx_buffersize, 0)) { - dev_kfree_skb_any(skb); - return -EIO; - } - - meta->skb = skb; - meta->dmaaddr = dmaaddr; - ring->ops->fill_descriptor(ring, desc, dmaaddr, - ring->rx_buffersize, 0, 0, 0); - - rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data); - rxhdr->frame_len = 0; - txstat = (struct b43legacy_hwtxstatus *)(skb->data); - txstat->cookie = 0; - - return 0; -} - -/* Allocate the initial descbuffers. - * This is used for an RX ring only. - */ -static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring) -{ - int i; - int err = -ENOMEM; - struct b43legacy_dmadesc_generic *desc; - struct b43legacy_dmadesc_meta *meta; - - for (i = 0; i < ring->nr_slots; i++) { - desc = ring->ops->idx2desc(ring, i, &meta); - - err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); - if (err) { - b43legacyerr(ring->dev->wl, - "Failed to allocate initial descbuffers\n"); - goto err_unwind; - } - } - mb(); /* all descbuffer setup before next line */ - ring->used_slots = ring->nr_slots; - err = 0; -out: - return err; - -err_unwind: - for (i--; i >= 0; i--) { - desc = ring->ops->idx2desc(ring, i, &meta); - - unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); - dev_kfree_skb(meta->skb); - } - goto out; -} - -/* Do initial setup of the DMA controller. - * Reset the controller, write the ring busaddress - * and switch the "enable" bit on. - */ -static int dmacontroller_setup(struct b43legacy_dmaring *ring) -{ - int err = 0; - u32 value; - u32 addrext; - u32 trans = ssb_dma_translation(ring->dev->dev); - - if (ring->tx) { - if (ring->type == B43legacy_DMA_64BIT) { - u64 ringbase = (u64)(ring->dmabase); - - addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = B43legacy_DMA64_TXENABLE; - value |= (addrext << B43legacy_DMA64_TXADDREXT_SHIFT) - & B43legacy_DMA64_TXADDREXT_MASK; - b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL, - value); - b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, - (ringbase & 0xFFFFFFFF)); - b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, - ((ringbase >> 32) - & ~SSB_DMA_TRANSLATION_MASK) - | trans); - } else { - u32 ringbase = (u32)(ring->dmabase); - - addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = B43legacy_DMA32_TXENABLE; - value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT) - & B43legacy_DMA32_TXADDREXT_MASK; - b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, - value); - b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, - (ringbase & - ~SSB_DMA_TRANSLATION_MASK) - | trans); - } - } else { - err = alloc_initial_descbuffers(ring); - if (err) - goto out; - if (ring->type == B43legacy_DMA_64BIT) { - u64 ringbase = (u64)(ring->dmabase); - - addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = (ring->frameoffset << - B43legacy_DMA64_RXFROFF_SHIFT); - value |= B43legacy_DMA64_RXENABLE; - value |= (addrext << B43legacy_DMA64_RXADDREXT_SHIFT) - & B43legacy_DMA64_RXADDREXT_MASK; - b43legacy_dma_write(ring, B43legacy_DMA64_RXCTL, - value); - b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, - (ringbase & 0xFFFFFFFF)); - b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, - ((ringbase >> 32) & - ~SSB_DMA_TRANSLATION_MASK) | - trans); - b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX, - 200); - } else { - u32 ringbase = (u32)(ring->dmabase); - - addrext = (ringbase & SSB_DMA_TRANSLATION_MASK) - >> SSB_DMA_TRANSLATION_SHIFT; - value = (ring->frameoffset << - B43legacy_DMA32_RXFROFF_SHIFT); - value |= B43legacy_DMA32_RXENABLE; - value |= (addrext << - B43legacy_DMA32_RXADDREXT_SHIFT) - & B43legacy_DMA32_RXADDREXT_MASK; - b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, - value); - b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, - (ringbase & - ~SSB_DMA_TRANSLATION_MASK) - | trans); - b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, - 200); - } - } - -out: - return err; -} - -/* Shutdown the DMA controller. */ -static void dmacontroller_cleanup(struct b43legacy_dmaring *ring) -{ - if (ring->tx) { - b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base, - ring->type); - if (ring->type == B43legacy_DMA_64BIT) { - b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0); - b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0); - } else - b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0); - } else { - b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base, - ring->type); - if (ring->type == B43legacy_DMA_64BIT) { - b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0); - b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0); - } else - b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0); - } -} - -static void free_all_descbuffers(struct b43legacy_dmaring *ring) -{ - struct b43legacy_dmadesc_generic *desc; - struct b43legacy_dmadesc_meta *meta; - int i; - - if (!ring->used_slots) - return; - for (i = 0; i < ring->nr_slots; i++) { - desc = ring->ops->idx2desc(ring, i, &meta); - - if (!meta->skb) { - B43legacy_WARN_ON(!ring->tx); - continue; - } - if (ring->tx) - unmap_descbuffer(ring, meta->dmaaddr, - meta->skb->len, 1); - else - unmap_descbuffer(ring, meta->dmaaddr, - ring->rx_buffersize, 0); - free_descriptor_buffer(ring, meta, 0); - } -} - -static u64 supported_dma_mask(struct b43legacy_wldev *dev) -{ - u32 tmp; - u16 mmio_base; - - tmp = b43legacy_read32(dev, SSB_TMSHIGH); - if (tmp & SSB_TMSHIGH_DMA64) - return DMA_BIT_MASK(64); - mmio_base = b43legacy_dmacontroller_base(0, 0); - b43legacy_write32(dev, - mmio_base + B43legacy_DMA32_TXCTL, - B43legacy_DMA32_TXADDREXT_MASK); - tmp = b43legacy_read32(dev, mmio_base + - B43legacy_DMA32_TXCTL); - if (tmp & B43legacy_DMA32_TXADDREXT_MASK) - return DMA_BIT_MASK(32); - - return DMA_BIT_MASK(30); -} - -static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask) -{ - if (dmamask == DMA_BIT_MASK(30)) - return B43legacy_DMA_30BIT; - if (dmamask == DMA_BIT_MASK(32)) - return B43legacy_DMA_32BIT; - if (dmamask == DMA_BIT_MASK(64)) - return B43legacy_DMA_64BIT; - B43legacy_WARN_ON(1); - return B43legacy_DMA_30BIT; -} - -/* Main initialization function. */ -static -struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev, - int controller_index, - int for_tx, - enum b43legacy_dmatype type) -{ - struct b43legacy_dmaring *ring; - int err; - int nr_slots; - dma_addr_t dma_test; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - goto out; - ring->type = type; - ring->dev = dev; - - nr_slots = B43legacy_RXRING_SLOTS; - if (for_tx) - nr_slots = B43legacy_TXRING_SLOTS; - - ring->meta = kcalloc(nr_slots, sizeof(struct b43legacy_dmadesc_meta), - GFP_KERNEL); - if (!ring->meta) - goto err_kfree_ring; - if (for_tx) { - ring->txhdr_cache = kcalloc(nr_slots, - sizeof(struct b43legacy_txhdr_fw3), - GFP_KERNEL); - if (!ring->txhdr_cache) - goto err_kfree_meta; - - /* test for ability to dma to txhdr_cache */ - dma_test = ssb_dma_map_single(dev->dev, ring->txhdr_cache, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); - - if (b43legacy_dma_mapping_error(ring, dma_test, - sizeof(struct b43legacy_txhdr_fw3), 1)) { - /* ugh realloc */ - kfree(ring->txhdr_cache); - ring->txhdr_cache = kcalloc(nr_slots, - sizeof(struct b43legacy_txhdr_fw3), - GFP_KERNEL | GFP_DMA); - if (!ring->txhdr_cache) - goto err_kfree_meta; - - dma_test = ssb_dma_map_single(dev->dev, - ring->txhdr_cache, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); - - if (b43legacy_dma_mapping_error(ring, dma_test, - sizeof(struct b43legacy_txhdr_fw3), 1)) - goto err_kfree_txhdr_cache; - } - - ssb_dma_unmap_single(dev->dev, dma_test, - sizeof(struct b43legacy_txhdr_fw3), - DMA_TO_DEVICE); - } - - ring->nr_slots = nr_slots; - ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index); - ring->index = controller_index; - if (type == B43legacy_DMA_64BIT) - ring->ops = &dma64_ops; - else - ring->ops = &dma32_ops; - if (for_tx) { - ring->tx = 1; - ring->current_slot = -1; - } else { - if (ring->index == 0) { - ring->rx_buffersize = B43legacy_DMA0_RX_BUFFERSIZE; - ring->frameoffset = B43legacy_DMA0_RX_FRAMEOFFSET; - } else if (ring->index == 3) { - ring->rx_buffersize = B43legacy_DMA3_RX_BUFFERSIZE; - ring->frameoffset = B43legacy_DMA3_RX_FRAMEOFFSET; - } else - B43legacy_WARN_ON(1); - } - spin_lock_init(&ring->lock); -#ifdef CONFIG_B43LEGACY_DEBUG - ring->last_injected_overflow = jiffies; -#endif - - err = alloc_ringmemory(ring); - if (err) - goto err_kfree_txhdr_cache; - err = dmacontroller_setup(ring); - if (err) - goto err_free_ringmemory; - -out: - return ring; - -err_free_ringmemory: - free_ringmemory(ring); -err_kfree_txhdr_cache: - kfree(ring->txhdr_cache); -err_kfree_meta: - kfree(ring->meta); -err_kfree_ring: - kfree(ring); - ring = NULL; - goto out; -} - -/* Main cleanup function. */ -static void b43legacy_destroy_dmaring(struct b43legacy_dmaring *ring) -{ - if (!ring) - return; - - b43legacydbg(ring->dev->wl, "DMA-%u 0x%04X (%s) max used slots:" - " %d/%d\n", (unsigned int)(ring->type), ring->mmio_base, - (ring->tx) ? "TX" : "RX", ring->max_used_slots, - ring->nr_slots); - /* Device IRQs are disabled prior entering this function, - * so no need to take care of concurrency with rx handler stuff. - */ - dmacontroller_cleanup(ring); - free_all_descbuffers(ring); - free_ringmemory(ring); - - kfree(ring->txhdr_cache); - kfree(ring->meta); - kfree(ring); -} - -void b43legacy_dma_free(struct b43legacy_wldev *dev) -{ - struct b43legacy_dma *dma; - - if (b43legacy_using_pio(dev)) - return; - dma = &dev->dma; - - b43legacy_destroy_dmaring(dma->rx_ring3); - dma->rx_ring3 = NULL; - b43legacy_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; - - b43legacy_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; - b43legacy_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; - b43legacy_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; - b43legacy_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; - b43legacy_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; - b43legacy_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; -} - -static int b43legacy_dma_set_mask(struct b43legacy_wldev *dev, u64 mask) -{ - u64 orig_mask = mask; - bool fallback = 0; - int err; - - /* Try to set the DMA mask. If it fails, try falling back to a - * lower mask, as we can always also support a lower one. */ - while (1) { - err = ssb_dma_set_mask(dev->dev, mask); - if (!err) - break; - if (mask == DMA_BIT_MASK(64)) { - mask = DMA_BIT_MASK(32); - fallback = 1; - continue; - } - if (mask == DMA_BIT_MASK(32)) { - mask = DMA_BIT_MASK(30); - fallback = 1; - continue; - } - b43legacyerr(dev->wl, "The machine/kernel does not support " - "the required %u-bit DMA mask\n", - (unsigned int)dma_mask_to_engine_type(orig_mask)); - return -EOPNOTSUPP; - } - if (fallback) { - b43legacyinfo(dev->wl, "DMA mask fallback from %u-bit to %u-" - "bit\n", - (unsigned int)dma_mask_to_engine_type(orig_mask), - (unsigned int)dma_mask_to_engine_type(mask)); - } - - return 0; -} - -int b43legacy_dma_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_dma *dma = &dev->dma; - struct b43legacy_dmaring *ring; - int err; - u64 dmamask; - enum b43legacy_dmatype type; - - dmamask = supported_dma_mask(dev); - type = dma_mask_to_engine_type(dmamask); - err = b43legacy_dma_set_mask(dev, dmamask); - if (err) { -#ifdef CONFIG_B43LEGACY_PIO - b43legacywarn(dev->wl, "DMA for this device not supported. " - "Falling back to PIO\n"); - dev->__using_pio = 1; - return -EAGAIN; -#else - b43legacyerr(dev->wl, "DMA for this device not supported and " - "no PIO support compiled in\n"); - return -EOPNOTSUPP; -#endif - } - - err = -ENOMEM; - /* setup TX DMA channels. */ - ring = b43legacy_setup_dmaring(dev, 0, 1, type); - if (!ring) - goto out; - dma->tx_ring0 = ring; - - ring = b43legacy_setup_dmaring(dev, 1, 1, type); - if (!ring) - goto err_destroy_tx0; - dma->tx_ring1 = ring; - - ring = b43legacy_setup_dmaring(dev, 2, 1, type); - if (!ring) - goto err_destroy_tx1; - dma->tx_ring2 = ring; - - ring = b43legacy_setup_dmaring(dev, 3, 1, type); - if (!ring) - goto err_destroy_tx2; - dma->tx_ring3 = ring; - - ring = b43legacy_setup_dmaring(dev, 4, 1, type); - if (!ring) - goto err_destroy_tx3; - dma->tx_ring4 = ring; - - ring = b43legacy_setup_dmaring(dev, 5, 1, type); - if (!ring) - goto err_destroy_tx4; - dma->tx_ring5 = ring; - - /* setup RX DMA channels. */ - ring = b43legacy_setup_dmaring(dev, 0, 0, type); - if (!ring) - goto err_destroy_tx5; - dma->rx_ring0 = ring; - - if (dev->dev->id.revision < 5) { - ring = b43legacy_setup_dmaring(dev, 3, 0, type); - if (!ring) - goto err_destroy_rx0; - dma->rx_ring3 = ring; - } - - b43legacydbg(dev->wl, "%u-bit DMA initialized\n", (unsigned int)type); - err = 0; -out: - return err; - -err_destroy_rx0: - b43legacy_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; -err_destroy_tx5: - b43legacy_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; -err_destroy_tx4: - b43legacy_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; -err_destroy_tx3: - b43legacy_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; -err_destroy_tx2: - b43legacy_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; -err_destroy_tx1: - b43legacy_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; -err_destroy_tx0: - b43legacy_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; - goto out; -} - -/* Generate a cookie for the TX header. */ -static u16 generate_cookie(struct b43legacy_dmaring *ring, - int slot) -{ - u16 cookie = 0x1000; - - /* Use the upper 4 bits of the cookie as - * DMA controller ID and store the slot number - * in the lower 12 bits. - * Note that the cookie must never be 0, as this - * is a special value used in RX path. - */ - switch (ring->index) { - case 0: - cookie = 0xA000; - break; - case 1: - cookie = 0xB000; - break; - case 2: - cookie = 0xC000; - break; - case 3: - cookie = 0xD000; - break; - case 4: - cookie = 0xE000; - break; - case 5: - cookie = 0xF000; - break; - } - B43legacy_WARN_ON(!(((u16)slot & 0xF000) == 0x0000)); - cookie |= (u16)slot; - - return cookie; -} - -/* Inspect a cookie and find out to which controller/slot it belongs. */ -static -struct b43legacy_dmaring *parse_cookie(struct b43legacy_wldev *dev, - u16 cookie, int *slot) -{ - struct b43legacy_dma *dma = &dev->dma; - struct b43legacy_dmaring *ring = NULL; - - switch (cookie & 0xF000) { - case 0xA000: - ring = dma->tx_ring0; - break; - case 0xB000: - ring = dma->tx_ring1; - break; - case 0xC000: - ring = dma->tx_ring2; - break; - case 0xD000: - ring = dma->tx_ring3; - break; - case 0xE000: - ring = dma->tx_ring4; - break; - case 0xF000: - ring = dma->tx_ring5; - break; - default: - B43legacy_WARN_ON(1); - } - *slot = (cookie & 0x0FFF); - B43legacy_WARN_ON(!(ring && *slot >= 0 && *slot < ring->nr_slots)); - - return ring; -} - -static int dma_tx_fragment(struct b43legacy_dmaring *ring, - struct sk_buff *skb) -{ - const struct b43legacy_dma_ops *ops = ring->ops; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - u8 *header; - int slot, old_top_slot, old_used_slots; - int err; - struct b43legacy_dmadesc_generic *desc; - struct b43legacy_dmadesc_meta *meta; - struct b43legacy_dmadesc_meta *meta_hdr; - struct sk_buff *bounce_skb; - -#define SLOTS_PER_PACKET 2 - B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); - - old_top_slot = ring->current_slot; - old_used_slots = ring->used_slots; - - /* Get a slot for the header. */ - slot = request_slot(ring); - desc = ops->idx2desc(ring, slot, &meta_hdr); - memset(meta_hdr, 0, sizeof(*meta_hdr)); - - header = &(ring->txhdr_cache[slot * sizeof( - struct b43legacy_txhdr_fw3)]); - err = b43legacy_generate_txhdr(ring->dev, header, - skb->data, skb->len, info, - generate_cookie(ring, slot)); - if (unlikely(err)) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - return err; - } - - meta_hdr->dmaaddr = map_descbuffer(ring, (unsigned char *)header, - sizeof(struct b43legacy_txhdr_fw3), 1); - if (b43legacy_dma_mapping_error(ring, meta_hdr->dmaaddr, - sizeof(struct b43legacy_txhdr_fw3), 1)) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - return -EIO; - } - ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, - sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0); - - /* Get a slot for the payload. */ - slot = request_slot(ring); - desc = ops->idx2desc(ring, slot, &meta); - memset(meta, 0, sizeof(*meta)); - - meta->skb = skb; - meta->is_last_fragment = 1; - - meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - /* create a bounce buffer in zone_dma on mapping failure. */ - if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC | GFP_DMA); - if (!bounce_skb) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - err = -ENOMEM; - goto out_unmap_hdr; - } - - memcpy(skb_put(bounce_skb, skb->len), skb->data, skb->len); - dev_kfree_skb_any(skb); - skb = bounce_skb; - meta->skb = skb; - meta->dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (b43legacy_dma_mapping_error(ring, meta->dmaaddr, skb->len, 1)) { - ring->current_slot = old_top_slot; - ring->used_slots = old_used_slots; - err = -EIO; - goto out_free_bounce; - } - } - - ops->fill_descriptor(ring, desc, meta->dmaaddr, - skb->len, 0, 1, 1); - - wmb(); /* previous stuff MUST be done */ - /* Now transfer the whole frame. */ - ops->poke_tx(ring, next_slot(ring, slot)); - return 0; - -out_free_bounce: - dev_kfree_skb_any(skb); -out_unmap_hdr: - unmap_descbuffer(ring, meta_hdr->dmaaddr, - sizeof(struct b43legacy_txhdr_fw3), 1); - return err; -} - -static inline -int should_inject_overflow(struct b43legacy_dmaring *ring) -{ -#ifdef CONFIG_B43LEGACY_DEBUG - if (unlikely(b43legacy_debug(ring->dev, - B43legacy_DBG_DMAOVERFLOW))) { - /* Check if we should inject another ringbuffer overflow - * to test handling of this situation in the stack. */ - unsigned long next_overflow; - - next_overflow = ring->last_injected_overflow + HZ; - if (time_after(jiffies, next_overflow)) { - ring->last_injected_overflow = jiffies; - b43legacydbg(ring->dev->wl, - "Injecting TX ring overflow on " - "DMA controller %d\n", ring->index); - return 1; - } - } -#endif /* CONFIG_B43LEGACY_DEBUG */ - return 0; -} - -int b43legacy_dma_tx(struct b43legacy_wldev *dev, - struct sk_buff *skb) -{ - struct b43legacy_dmaring *ring; - int err = 0; - unsigned long flags; - - ring = priority_to_txring(dev, skb_get_queue_mapping(skb)); - spin_lock_irqsave(&ring->lock, flags); - B43legacy_WARN_ON(!ring->tx); - - if (unlikely(ring->stopped)) { - /* We get here only because of a bug in mac80211. - * Because of a race, one packet may be queued after - * the queue is stopped, thus we got called when we shouldn't. - * For now, just refuse the transmit. */ - if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) - b43legacyerr(dev->wl, "Packet after queue stopped\n"); - err = -ENOSPC; - goto out_unlock; - } - - if (unlikely(WARN_ON(free_slots(ring) < SLOTS_PER_PACKET))) { - /* If we get here, we have a real error with the queue - * full, but queues not stopped. */ - b43legacyerr(dev->wl, "DMA queue overflow\n"); - err = -ENOSPC; - goto out_unlock; - } - - err = dma_tx_fragment(ring, skb); - if (unlikely(err == -ENOKEY)) { - /* Drop this packet, as we don't have the encryption key - * anymore and must not transmit it unencrypted. */ - dev_kfree_skb_any(skb); - err = 0; - goto out_unlock; - } - if (unlikely(err)) { - b43legacyerr(dev->wl, "DMA tx mapping failure\n"); - goto out_unlock; - } - ring->nr_tx_packets++; - if ((free_slots(ring) < SLOTS_PER_PACKET) || - should_inject_overflow(ring)) { - /* This TX ring is full. */ - ieee80211_stop_queue(dev->wl->hw, txring_to_priority(ring)); - ring->stopped = 1; - if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) - b43legacydbg(dev->wl, "Stopped TX ring %d\n", - ring->index); - } -out_unlock: - spin_unlock_irqrestore(&ring->lock, flags); - - return err; -} - -void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) -{ - const struct b43legacy_dma_ops *ops; - struct b43legacy_dmaring *ring; - struct b43legacy_dmadesc_generic *desc; - struct b43legacy_dmadesc_meta *meta; - int retry_limit; - int slot; - - ring = parse_cookie(dev, status->cookie, &slot); - if (unlikely(!ring)) - return; - B43legacy_WARN_ON(!irqs_disabled()); - spin_lock(&ring->lock); - - B43legacy_WARN_ON(!ring->tx); - ops = ring->ops; - while (1) { - B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); - desc = ops->idx2desc(ring, slot, &meta); - - if (meta->skb) - unmap_descbuffer(ring, meta->dmaaddr, - meta->skb->len, 1); - else - unmap_descbuffer(ring, meta->dmaaddr, - sizeof(struct b43legacy_txhdr_fw3), - 1); - - if (meta->is_last_fragment) { - struct ieee80211_tx_info *info; - BUG_ON(!meta->skb); - info = IEEE80211_SKB_CB(meta->skb); - - /* preserve the confiured retry limit before clearing the status - * The xmit function has overwritten the rc's value with the actual - * retry limit done by the hardware */ - retry_limit = info->status.rates[0].count; - ieee80211_tx_info_clear_status(info); - - if (status->acked) - info->flags |= IEEE80211_TX_STAT_ACK; - - if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { - /* - * If the short retries (RTS, not data frame) have exceeded - * the limit, the hw will not have tried the selected rate, - * but will have used the fallback rate instead. - * Don't let the rate control count attempts for the selected - * rate in this case, otherwise the statistics will be off. - */ - info->status.rates[0].count = 0; - info->status.rates[1].count = status->frame_count; - } else { - if (status->frame_count > retry_limit) { - info->status.rates[0].count = retry_limit; - info->status.rates[1].count = status->frame_count - - retry_limit; - - } else { - info->status.rates[0].count = status->frame_count; - info->status.rates[1].idx = -1; - } - } - - /* Call back to inform the ieee80211 subsystem about the - * status of the transmission. - * Some fields of txstat are already filled in dma_tx(). - */ - ieee80211_tx_status_irqsafe(dev->wl->hw, meta->skb); - /* skb is freed by ieee80211_tx_status_irqsafe() */ - meta->skb = NULL; - } else { - /* No need to call free_descriptor_buffer here, as - * this is only the txhdr, which is not allocated. - */ - B43legacy_WARN_ON(meta->skb != NULL); - } - - /* Everything unmapped and free'd. So it's not used anymore. */ - ring->used_slots--; - - if (meta->is_last_fragment) - break; - slot = next_slot(ring, slot); - } - dev->stats.last_tx = jiffies; - if (ring->stopped) { - B43legacy_WARN_ON(free_slots(ring) < SLOTS_PER_PACKET); - ieee80211_wake_queue(dev->wl->hw, txring_to_priority(ring)); - ring->stopped = 0; - if (b43legacy_debug(dev, B43legacy_DBG_DMAVERBOSE)) - b43legacydbg(dev->wl, "Woke up TX ring %d\n", - ring->index); - } - - spin_unlock(&ring->lock); -} - -void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - const int nr_queues = dev->wl->hw->queues; - struct b43legacy_dmaring *ring; - unsigned long flags; - int i; - - for (i = 0; i < nr_queues; i++) { - ring = priority_to_txring(dev, i); - - spin_lock_irqsave(&ring->lock, flags); - stats[i].len = ring->used_slots / SLOTS_PER_PACKET; - stats[i].limit = ring->nr_slots / SLOTS_PER_PACKET; - stats[i].count = ring->nr_tx_packets; - spin_unlock_irqrestore(&ring->lock, flags); - } -} - -static void dma_rx(struct b43legacy_dmaring *ring, - int *slot) -{ - const struct b43legacy_dma_ops *ops = ring->ops; - struct b43legacy_dmadesc_generic *desc; - struct b43legacy_dmadesc_meta *meta; - struct b43legacy_rxhdr_fw3 *rxhdr; - struct sk_buff *skb; - u16 len; - int err; - dma_addr_t dmaaddr; - - desc = ops->idx2desc(ring, *slot, &meta); - - sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); - skb = meta->skb; - - if (ring->index == 3) { - /* We received an xmit status. */ - struct b43legacy_hwtxstatus *hw = - (struct b43legacy_hwtxstatus *)skb->data; - int i = 0; - - while (hw->cookie == 0) { - if (i > 100) - break; - i++; - udelay(2); - barrier(); - } - b43legacy_handle_hwtxstatus(ring->dev, hw); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - - return; - } - rxhdr = (struct b43legacy_rxhdr_fw3 *)skb->data; - len = le16_to_cpu(rxhdr->frame_len); - if (len == 0) { - int i = 0; - - do { - udelay(2); - barrier(); - len = le16_to_cpu(rxhdr->frame_len); - } while (len == 0 && i++ < 5); - if (unlikely(len == 0)) { - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; - } - } - if (unlikely(len > ring->rx_buffersize)) { - /* The data did not fit into one descriptor buffer - * and is split over multiple buffers. - * This should never happen, as we try to allocate buffers - * big enough. So simply ignore this packet. - */ - int cnt = 0; - s32 tmp = len; - - while (1) { - desc = ops->idx2desc(ring, *slot, &meta); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - *slot = next_slot(ring, *slot); - cnt++; - tmp -= ring->rx_buffersize; - if (tmp <= 0) - break; - } - b43legacyerr(ring->dev->wl, "DMA RX buffer too small " - "(len: %u, buffer: %u, nr-dropped: %d)\n", - len, ring->rx_buffersize, cnt); - goto drop; - } - - dmaaddr = meta->dmaaddr; - err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); - if (unlikely(err)) { - b43legacydbg(ring->dev->wl, "DMA RX: setup_rx_descbuffer()" - " failed\n"); - sync_descbuffer_for_device(ring, dmaaddr, - ring->rx_buffersize); - goto drop; - } - - unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); - skb_put(skb, len + ring->frameoffset); - skb_pull(skb, ring->frameoffset); - - b43legacy_rx(ring->dev, skb, rxhdr); -drop: - return; -} - -void b43legacy_dma_rx(struct b43legacy_dmaring *ring) -{ - const struct b43legacy_dma_ops *ops = ring->ops; - int slot; - int current_slot; - int used_slots = 0; - - B43legacy_WARN_ON(ring->tx); - current_slot = ops->get_current_rxslot(ring); - B43legacy_WARN_ON(!(current_slot >= 0 && current_slot < - ring->nr_slots)); - - slot = ring->current_slot; - for (; slot != current_slot; slot = next_slot(ring, slot)) { - dma_rx(ring, &slot); - update_max_used_slots(ring, ++used_slots); - } - ops->set_current_rxslot(ring, slot); - ring->current_slot = slot; -} - -static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring) -{ - unsigned long flags; - - spin_lock_irqsave(&ring->lock, flags); - B43legacy_WARN_ON(!ring->tx); - ring->ops->tx_suspend(ring); - spin_unlock_irqrestore(&ring->lock, flags); -} - -static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring) -{ - unsigned long flags; - - spin_lock_irqsave(&ring->lock, flags); - B43legacy_WARN_ON(!ring->tx); - ring->ops->tx_resume(ring); - spin_unlock_irqrestore(&ring->lock, flags); -} - -void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev) -{ - b43legacy_power_saving_ctl_bits(dev, -1, 1); - b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring0); - b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring1); - b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring2); - b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring3); - b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring4); - b43legacy_dma_tx_suspend_ring(dev->dma.tx_ring5); -} - -void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev) -{ - b43legacy_dma_tx_resume_ring(dev->dma.tx_ring5); - b43legacy_dma_tx_resume_ring(dev->dma.tx_ring4); - b43legacy_dma_tx_resume_ring(dev->dma.tx_ring3); - b43legacy_dma_tx_resume_ring(dev->dma.tx_ring2); - b43legacy_dma_tx_resume_ring(dev->dma.tx_ring1); - b43legacy_dma_tx_resume_ring(dev->dma.tx_ring0); - b43legacy_power_saving_ctl_bits(dev, -1, -1); -} diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h deleted file mode 100644 index 2f186003c31e..000000000000 --- a/drivers/net/wireless/b43legacy/dma.h +++ /dev/null @@ -1,347 +0,0 @@ -#ifndef B43legacy_DMA_H_ -#define B43legacy_DMA_H_ - -#include -#include -#include -#include -#include - -#include "b43legacy.h" - - -/* DMA-Interrupt reasons. */ -#define B43legacy_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ - | (1 << 14) | (1 << 15)) -#define B43legacy_DMAIRQ_NONFATALMASK (1 << 13) -#define B43legacy_DMAIRQ_RX_DONE (1 << 16) - - -/*** 32-bit DMA Engine. ***/ - -/* 32-bit DMA controller registers. */ -#define B43legacy_DMA32_TXCTL 0x00 -#define B43legacy_DMA32_TXENABLE 0x00000001 -#define B43legacy_DMA32_TXSUSPEND 0x00000002 -#define B43legacy_DMA32_TXLOOPBACK 0x00000004 -#define B43legacy_DMA32_TXFLUSH 0x00000010 -#define B43legacy_DMA32_TXADDREXT_MASK 0x00030000 -#define B43legacy_DMA32_TXADDREXT_SHIFT 16 -#define B43legacy_DMA32_TXRING 0x04 -#define B43legacy_DMA32_TXINDEX 0x08 -#define B43legacy_DMA32_TXSTATUS 0x0C -#define B43legacy_DMA32_TXDPTR 0x00000FFF -#define B43legacy_DMA32_TXSTATE 0x0000F000 -#define B43legacy_DMA32_TXSTAT_DISABLED 0x00000000 -#define B43legacy_DMA32_TXSTAT_ACTIVE 0x00001000 -#define B43legacy_DMA32_TXSTAT_IDLEWAIT 0x00002000 -#define B43legacy_DMA32_TXSTAT_STOPPED 0x00003000 -#define B43legacy_DMA32_TXSTAT_SUSP 0x00004000 -#define B43legacy_DMA32_TXERROR 0x000F0000 -#define B43legacy_DMA32_TXERR_NOERR 0x00000000 -#define B43legacy_DMA32_TXERR_PROT 0x00010000 -#define B43legacy_DMA32_TXERR_UNDERRUN 0x00020000 -#define B43legacy_DMA32_TXERR_BUFREAD 0x00030000 -#define B43legacy_DMA32_TXERR_DESCREAD 0x00040000 -#define B43legacy_DMA32_TXACTIVE 0xFFF00000 -#define B43legacy_DMA32_RXCTL 0x10 -#define B43legacy_DMA32_RXENABLE 0x00000001 -#define B43legacy_DMA32_RXFROFF_MASK 0x000000FE -#define B43legacy_DMA32_RXFROFF_SHIFT 1 -#define B43legacy_DMA32_RXDIRECTFIFO 0x00000100 -#define B43legacy_DMA32_RXADDREXT_MASK 0x00030000 -#define B43legacy_DMA32_RXADDREXT_SHIFT 16 -#define B43legacy_DMA32_RXRING 0x14 -#define B43legacy_DMA32_RXINDEX 0x18 -#define B43legacy_DMA32_RXSTATUS 0x1C -#define B43legacy_DMA32_RXDPTR 0x00000FFF -#define B43legacy_DMA32_RXSTATE 0x0000F000 -#define B43legacy_DMA32_RXSTAT_DISABLED 0x00000000 -#define B43legacy_DMA32_RXSTAT_ACTIVE 0x00001000 -#define B43legacy_DMA32_RXSTAT_IDLEWAIT 0x00002000 -#define B43legacy_DMA32_RXSTAT_STOPPED 0x00003000 -#define B43legacy_DMA32_RXERROR 0x000F0000 -#define B43legacy_DMA32_RXERR_NOERR 0x00000000 -#define B43legacy_DMA32_RXERR_PROT 0x00010000 -#define B43legacy_DMA32_RXERR_OVERFLOW 0x00020000 -#define B43legacy_DMA32_RXERR_BUFWRITE 0x00030000 -#define B43legacy_DMA32_RXERR_DESCREAD 0x00040000 -#define B43legacy_DMA32_RXACTIVE 0xFFF00000 - -/* 32-bit DMA descriptor. */ -struct b43legacy_dmadesc32 { - __le32 control; - __le32 address; -} __attribute__((__packed__)); -#define B43legacy_DMA32_DCTL_BYTECNT 0x00001FFF -#define B43legacy_DMA32_DCTL_ADDREXT_MASK 0x00030000 -#define B43legacy_DMA32_DCTL_ADDREXT_SHIFT 16 -#define B43legacy_DMA32_DCTL_DTABLEEND 0x10000000 -#define B43legacy_DMA32_DCTL_IRQ 0x20000000 -#define B43legacy_DMA32_DCTL_FRAMEEND 0x40000000 -#define B43legacy_DMA32_DCTL_FRAMESTART 0x80000000 - - - -/*** 64-bit DMA Engine. ***/ - -/* 64-bit DMA controller registers. */ -#define B43legacy_DMA64_TXCTL 0x00 -#define B43legacy_DMA64_TXENABLE 0x00000001 -#define B43legacy_DMA64_TXSUSPEND 0x00000002 -#define B43legacy_DMA64_TXLOOPBACK 0x00000004 -#define B43legacy_DMA64_TXFLUSH 0x00000010 -#define B43legacy_DMA64_TXADDREXT_MASK 0x00030000 -#define B43legacy_DMA64_TXADDREXT_SHIFT 16 -#define B43legacy_DMA64_TXINDEX 0x04 -#define B43legacy_DMA64_TXRINGLO 0x08 -#define B43legacy_DMA64_TXRINGHI 0x0C -#define B43legacy_DMA64_TXSTATUS 0x10 -#define B43legacy_DMA64_TXSTATDPTR 0x00001FFF -#define B43legacy_DMA64_TXSTAT 0xF0000000 -#define B43legacy_DMA64_TXSTAT_DISABLED 0x00000000 -#define B43legacy_DMA64_TXSTAT_ACTIVE 0x10000000 -#define B43legacy_DMA64_TXSTAT_IDLEWAIT 0x20000000 -#define B43legacy_DMA64_TXSTAT_STOPPED 0x30000000 -#define B43legacy_DMA64_TXSTAT_SUSP 0x40000000 -#define B43legacy_DMA64_TXERROR 0x14 -#define B43legacy_DMA64_TXERRDPTR 0x0001FFFF -#define B43legacy_DMA64_TXERR 0xF0000000 -#define B43legacy_DMA64_TXERR_NOERR 0x00000000 -#define B43legacy_DMA64_TXERR_PROT 0x10000000 -#define B43legacy_DMA64_TXERR_UNDERRUN 0x20000000 -#define B43legacy_DMA64_TXERR_TRANSFER 0x30000000 -#define B43legacy_DMA64_TXERR_DESCREAD 0x40000000 -#define B43legacy_DMA64_TXERR_CORE 0x50000000 -#define B43legacy_DMA64_RXCTL 0x20 -#define B43legacy_DMA64_RXENABLE 0x00000001 -#define B43legacy_DMA64_RXFROFF_MASK 0x000000FE -#define B43legacy_DMA64_RXFROFF_SHIFT 1 -#define B43legacy_DMA64_RXDIRECTFIFO 0x00000100 -#define B43legacy_DMA64_RXADDREXT_MASK 0x00030000 -#define B43legacy_DMA64_RXADDREXT_SHIFT 16 -#define B43legacy_DMA64_RXINDEX 0x24 -#define B43legacy_DMA64_RXRINGLO 0x28 -#define B43legacy_DMA64_RXRINGHI 0x2C -#define B43legacy_DMA64_RXSTATUS 0x30 -#define B43legacy_DMA64_RXSTATDPTR 0x00001FFF -#define B43legacy_DMA64_RXSTAT 0xF0000000 -#define B43legacy_DMA64_RXSTAT_DISABLED 0x00000000 -#define B43legacy_DMA64_RXSTAT_ACTIVE 0x10000000 -#define B43legacy_DMA64_RXSTAT_IDLEWAIT 0x20000000 -#define B43legacy_DMA64_RXSTAT_STOPPED 0x30000000 -#define B43legacy_DMA64_RXSTAT_SUSP 0x40000000 -#define B43legacy_DMA64_RXERROR 0x34 -#define B43legacy_DMA64_RXERRDPTR 0x0001FFFF -#define B43legacy_DMA64_RXERR 0xF0000000 -#define B43legacy_DMA64_RXERR_NOERR 0x00000000 -#define B43legacy_DMA64_RXERR_PROT 0x10000000 -#define B43legacy_DMA64_RXERR_UNDERRUN 0x20000000 -#define B43legacy_DMA64_RXERR_TRANSFER 0x30000000 -#define B43legacy_DMA64_RXERR_DESCREAD 0x40000000 -#define B43legacy_DMA64_RXERR_CORE 0x50000000 - -/* 64-bit DMA descriptor. */ -struct b43legacy_dmadesc64 { - __le32 control0; - __le32 control1; - __le32 address_low; - __le32 address_high; -} __attribute__((__packed__)); -#define B43legacy_DMA64_DCTL0_DTABLEEND 0x10000000 -#define B43legacy_DMA64_DCTL0_IRQ 0x20000000 -#define B43legacy_DMA64_DCTL0_FRAMEEND 0x40000000 -#define B43legacy_DMA64_DCTL0_FRAMESTART 0x80000000 -#define B43legacy_DMA64_DCTL1_BYTECNT 0x00001FFF -#define B43legacy_DMA64_DCTL1_ADDREXT_MASK 0x00030000 -#define B43legacy_DMA64_DCTL1_ADDREXT_SHIFT 16 - - - -struct b43legacy_dmadesc_generic { - union { - struct b43legacy_dmadesc32 dma32; - struct b43legacy_dmadesc64 dma64; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - - -/* Misc DMA constants */ -#define B43legacy_DMA_RINGMEMSIZE PAGE_SIZE -#define B43legacy_DMA0_RX_FRAMEOFFSET 30 -#define B43legacy_DMA3_RX_FRAMEOFFSET 0 - - -/* DMA engine tuning knobs */ -#define B43legacy_TXRING_SLOTS 128 -#define B43legacy_RXRING_SLOTS 64 -#define B43legacy_DMA0_RX_BUFFERSIZE (2304 + 100) -#define B43legacy_DMA3_RX_BUFFERSIZE 16 - - - -#ifdef CONFIG_B43LEGACY_DMA - - -struct sk_buff; -struct b43legacy_private; -struct b43legacy_txstatus; - - -struct b43legacy_dmadesc_meta { - /* The kernel DMA-able buffer. */ - struct sk_buff *skb; - /* DMA base bus-address of the descriptor buffer. */ - dma_addr_t dmaaddr; - /* ieee80211 TX status. Only used once per 802.11 frag. */ - bool is_last_fragment; -}; - -struct b43legacy_dmaring; - -/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */ -struct b43legacy_dma_ops { - struct b43legacy_dmadesc_generic * (*idx2desc) - (struct b43legacy_dmaring *ring, - int slot, - struct b43legacy_dmadesc_meta - **meta); - void (*fill_descriptor)(struct b43legacy_dmaring *ring, - struct b43legacy_dmadesc_generic *desc, - dma_addr_t dmaaddr, u16 bufsize, - int start, int end, int irq); - void (*poke_tx)(struct b43legacy_dmaring *ring, int slot); - void (*tx_suspend)(struct b43legacy_dmaring *ring); - void (*tx_resume)(struct b43legacy_dmaring *ring); - int (*get_current_rxslot)(struct b43legacy_dmaring *ring); - void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot); -}; - -enum b43legacy_dmatype { - B43legacy_DMA_30BIT = 30, - B43legacy_DMA_32BIT = 32, - B43legacy_DMA_64BIT = 64, -}; - -struct b43legacy_dmaring { - /* Lowlevel DMA ops. */ - const struct b43legacy_dma_ops *ops; - /* Kernel virtual base address of the ring memory. */ - void *descbase; - /* Meta data about all descriptors. */ - struct b43legacy_dmadesc_meta *meta; - /* Cache of TX headers for each slot. - * This is to avoid an allocation on each TX. - * This is NULL for an RX ring. - */ - u8 *txhdr_cache; - /* (Unadjusted) DMA base bus-address of the ring memory. */ - dma_addr_t dmabase; - /* Number of descriptor slots in the ring. */ - int nr_slots; - /* Number of used descriptor slots. */ - int used_slots; - /* Currently used slot in the ring. */ - int current_slot; - /* Total number of packets sent. Statistics only. */ - unsigned int nr_tx_packets; - /* Frameoffset in octets. */ - u32 frameoffset; - /* Descriptor buffer size. */ - u16 rx_buffersize; - /* The MMIO base register of the DMA controller. */ - u16 mmio_base; - /* DMA controller index number (0-5). */ - int index; - /* Boolean. Is this a TX ring? */ - bool tx; - /* The type of DMA engine used. */ - enum b43legacy_dmatype type; - /* Boolean. Is this ring stopped at ieee80211 level? */ - bool stopped; - /* Lock, only used for TX. */ - spinlock_t lock; - struct b43legacy_wldev *dev; -#ifdef CONFIG_B43LEGACY_DEBUG - /* Maximum number of used slots. */ - int max_used_slots; - /* Last time we injected a ring overflow. */ - unsigned long last_injected_overflow; -#endif /* CONFIG_B43LEGACY_DEBUG*/ -}; - - -static inline -u32 b43legacy_dma_read(struct b43legacy_dmaring *ring, - u16 offset) -{ - return b43legacy_read32(ring->dev, ring->mmio_base + offset); -} - -static inline -void b43legacy_dma_write(struct b43legacy_dmaring *ring, - u16 offset, u32 value) -{ - b43legacy_write32(ring->dev, ring->mmio_base + offset, value); -} - - -int b43legacy_dma_init(struct b43legacy_wldev *dev); -void b43legacy_dma_free(struct b43legacy_wldev *dev); - -void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev); -void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev); - -void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats); - -int b43legacy_dma_tx(struct b43legacy_wldev *dev, - struct sk_buff *skb); -void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status); - -void b43legacy_dma_rx(struct b43legacy_dmaring *ring); - -#else /* CONFIG_B43LEGACY_DMA */ - - -static inline -int b43legacy_dma_init(struct b43legacy_wldev *dev) -{ - return 0; -} -static inline -void b43legacy_dma_free(struct b43legacy_wldev *dev) -{ -} -static inline -void b43legacy_dma_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ -} -static inline -int b43legacy_dma_tx(struct b43legacy_wldev *dev, - struct sk_buff *skb) -{ - return 0; -} -static inline -void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) -{ -} -static inline -void b43legacy_dma_rx(struct b43legacy_dmaring *ring) -{ -} -static inline -void b43legacy_dma_tx_suspend(struct b43legacy_wldev *dev) -{ -} -static inline -void b43legacy_dma_tx_resume(struct b43legacy_wldev *dev) -{ -} - -#endif /* CONFIG_B43LEGACY_DMA */ -#endif /* B43legacy_DMA_H_ */ diff --git a/drivers/net/wireless/b43legacy/ilt.c b/drivers/net/wireless/b43legacy/ilt.c deleted file mode 100644 index a849078aea69..000000000000 --- a/drivers/net/wireless/b43legacy/ilt.c +++ /dev/null @@ -1,336 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43legacy.h" -#include "ilt.h" -#include "phy.h" - - -/**** Initial Internal Lookup Tables ****/ - -const u32 b43legacy_ilt_rotor[B43legacy_ILT_ROTOR_SIZE] = { - 0xFEB93FFD, 0xFEC63FFD, /* 0 */ - 0xFED23FFD, 0xFEDF3FFD, - 0xFEEC3FFE, 0xFEF83FFE, - 0xFF053FFE, 0xFF113FFE, - 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ - 0xFF373FFF, 0xFF443FFF, - 0xFF503FFF, 0xFF5D3FFF, - 0xFF693FFF, 0xFF763FFF, - 0xFF824000, 0xFF8F4000, /* 16 */ - 0xFF9B4000, 0xFFA84000, - 0xFFB54000, 0xFFC14000, - 0xFFCE4000, 0xFFDA4000, - 0xFFE74000, 0xFFF34000, /* 24 */ - 0x00004000, 0x000D4000, - 0x00194000, 0x00264000, - 0x00324000, 0x003F4000, - 0x004B4000, 0x00584000, /* 32 */ - 0x00654000, 0x00714000, - 0x007E4000, 0x008A3FFF, - 0x00973FFF, 0x00A33FFF, - 0x00B03FFF, 0x00BC3FFF, /* 40 */ - 0x00C93FFF, 0x00D63FFF, - 0x00E23FFE, 0x00EF3FFE, - 0x00FB3FFE, 0x01083FFE, - 0x01143FFE, 0x01213FFD, /* 48 */ - 0x012E3FFD, 0x013A3FFD, - 0x01473FFD, -}; - -const u32 b43legacy_ilt_retard[B43legacy_ILT_RETARD_SIZE] = { - 0xDB93CB87, 0xD666CF64, /* 0 */ - 0xD1FDD358, 0xCDA6D826, - 0xCA38DD9F, 0xC729E2B4, - 0xC469E88E, 0xC26AEE2B, - 0xC0DEF46C, 0xC073FA62, /* 8 */ - 0xC01D00D5, 0xC0760743, - 0xC1560D1E, 0xC2E51369, - 0xC4ED18FF, 0xC7AC1ED7, - 0xCB2823B2, 0xCEFA28D9, /* 16 */ - 0xD2F62D3F, 0xD7BB3197, - 0xDCE53568, 0xE1FE3875, - 0xE7D13B35, 0xED663D35, - 0xF39B3EC4, 0xF98E3FA7, /* 24 */ - 0x00004000, 0x06723FA7, - 0x0C653EC4, 0x129A3D35, - 0x182F3B35, 0x1E023875, - 0x231B3568, 0x28453197, /* 32 */ - 0x2D0A2D3F, 0x310628D9, - 0x34D823B2, 0x38541ED7, - 0x3B1318FF, 0x3D1B1369, - 0x3EAA0D1E, 0x3F8A0743, /* 40 */ - 0x3FE300D5, 0x3F8DFA62, - 0x3F22F46C, 0x3D96EE2B, - 0x3B97E88E, 0x38D7E2B4, - 0x35C8DD9F, 0x325AD826, /* 48 */ - 0x2E03D358, 0x299ACF64, - 0x246DCB87, -}; - -const u16 b43legacy_ilt_finefreqa[B43legacy_ILT_FINEFREQA_SIZE] = { - 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ - 0x0202, 0x0282, 0x0302, 0x0382, - 0x0402, 0x0482, 0x0502, 0x0582, - 0x05E2, 0x0662, 0x06E2, 0x0762, - 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ - 0x09C2, 0x0A22, 0x0AA2, 0x0B02, - 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, - 0x0D42, 0x0DA2, 0x0E02, 0x0E62, - 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ - 0x1062, 0x10C2, 0x1122, 0x1182, - 0x11E2, 0x1242, 0x12A2, 0x12E2, - 0x1342, 0x13A2, 0x1402, 0x1442, - 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ - 0x15E2, 0x1622, 0x1662, 0x16C1, - 0x1701, 0x1741, 0x1781, 0x17E1, - 0x1821, 0x1861, 0x18A1, 0x18E1, - 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ - 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, - 0x1B01, 0x1B41, 0x1B81, 0x1BA1, - 0x1BE1, 0x1C21, 0x1C41, 0x1C81, - 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ - 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, - 0x1E21, 0x1E61, 0x1E81, 0x1EA1, - 0x1EE1, 0x1F01, 0x1F21, 0x1F41, - 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ - 0x2001, 0x2041, 0x2061, 0x2081, - 0x20A1, 0x20C1, 0x20E1, 0x2101, - 0x2121, 0x2141, 0x2161, 0x2181, - 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ - 0x2221, 0x2241, 0x2261, 0x2281, - 0x22A1, 0x22C1, 0x22C1, 0x22E1, - 0x2301, 0x2321, 0x2341, 0x2361, - 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ - 0x23E1, 0x23E1, 0x2401, 0x2421, - 0x2441, 0x2441, 0x2461, 0x2481, - 0x2481, 0x24A1, 0x24C1, 0x24C1, - 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ - 0x2541, 0x2541, 0x2561, 0x2561, - 0x2581, 0x25A1, 0x25A1, 0x25C1, - 0x25C1, 0x25E1, 0x2601, 0x2601, - 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ - 0x2661, 0x2661, 0x2681, 0x2681, - 0x26A1, 0x26A1, 0x26C1, 0x26C1, - 0x26E1, 0x26E1, 0x2701, 0x2701, - 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ - 0x2760, 0x2760, 0x2780, 0x2780, - 0x2780, 0x27A0, 0x27A0, 0x27C0, - 0x27C0, 0x27E0, 0x27E0, 0x27E0, - 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ - 0x2820, 0x2840, 0x2840, 0x2840, - 0x2860, 0x2860, 0x2880, 0x2880, - 0x2880, 0x28A0, 0x28A0, 0x28A0, - 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ - 0x28E0, 0x28E0, 0x2900, 0x2900, - 0x2900, 0x2920, 0x2920, 0x2920, - 0x2940, 0x2940, 0x2940, 0x2960, - 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ - 0x2980, 0x2980, 0x29A0, 0x29A0, - 0x29A0, 0x29A0, 0x29C0, 0x29C0, - 0x29C0, 0x29E0, 0x29E0, 0x29E0, - 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ - 0x2A00, 0x2A20, 0x2A20, 0x2A20, - 0x2A20, 0x2A40, 0x2A40, 0x2A40, - 0x2A40, 0x2A60, 0x2A60, 0x2A60, -}; - -const u16 b43legacy_ilt_finefreqg[B43legacy_ILT_FINEFREQG_SIZE] = { - 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ - 0x05A9, 0x0669, 0x0709, 0x0789, - 0x0829, 0x08A9, 0x0929, 0x0989, - 0x0A09, 0x0A69, 0x0AC9, 0x0B29, - 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ - 0x0D09, 0x0D69, 0x0DA9, 0x0E09, - 0x0E69, 0x0EA9, 0x0F09, 0x0F49, - 0x0FA9, 0x0FE9, 0x1029, 0x1089, - 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ - 0x11E9, 0x1229, 0x1289, 0x12C9, - 0x1309, 0x1349, 0x1389, 0x13C9, - 0x1409, 0x1449, 0x14A9, 0x14E9, - 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ - 0x1629, 0x1669, 0x16A9, 0x16E8, - 0x1728, 0x1768, 0x17A8, 0x17E8, - 0x1828, 0x1868, 0x18A8, 0x18E8, - 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ - 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, - 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, - 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, - 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ - 0x1E48, 0x1E88, 0x1EC8, 0x1F08, - 0x1F48, 0x1F88, 0x1FE8, 0x2028, - 0x2068, 0x20A8, 0x2108, 0x2148, - 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ - 0x22C8, 0x2308, 0x2348, 0x23A8, - 0x23E8, 0x2448, 0x24A8, 0x24E8, - 0x2548, 0x25A8, 0x2608, 0x2668, - 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ - 0x2847, 0x28C7, 0x2947, 0x29A7, - 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, - 0x2CA7, 0x2D67, 0x2E47, 0x2F67, - 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ - 0x3806, 0x38A6, 0x3946, 0x39E6, - 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, - 0x3C45, 0x3CA5, 0x3D05, 0x3D85, - 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ - 0x3F45, 0x3FA5, 0x4005, 0x4045, - 0x40A5, 0x40E5, 0x4145, 0x4185, - 0x41E5, 0x4225, 0x4265, 0x42C5, - 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ - 0x4424, 0x4464, 0x44C4, 0x4504, - 0x4544, 0x4584, 0x45C4, 0x4604, - 0x4644, 0x46A4, 0x46E4, 0x4724, - 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ - 0x4864, 0x48A4, 0x48E4, 0x4924, - 0x4964, 0x49A4, 0x49E4, 0x4A24, - 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, - 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ - 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, - 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, - 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, - 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ - 0x5083, 0x50C3, 0x5103, 0x5143, - 0x5183, 0x51E2, 0x5222, 0x5262, - 0x52A2, 0x52E2, 0x5342, 0x5382, - 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ - 0x5502, 0x5542, 0x55A2, 0x55E2, - 0x5642, 0x5682, 0x56E2, 0x5722, - 0x5782, 0x57E1, 0x5841, 0x58A1, - 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ - 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, - 0x5C61, 0x5D01, 0x5D80, 0x5E20, - 0x5EE0, 0x5FA0, 0x6080, 0x61C0, -}; - -const u16 b43legacy_ilt_noisea2[B43legacy_ILT_NOISEA2_SIZE] = { - 0x0001, 0x0001, 0x0001, 0xFFFE, - 0xFFFE, 0x3FFF, 0x1000, 0x0393, -}; - -const u16 b43legacy_ilt_noisea3[B43legacy_ILT_NOISEA3_SIZE] = { - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, -}; - -const u16 b43legacy_ilt_noiseg1[B43legacy_ILT_NOISEG1_SIZE] = { - 0x013C, 0x01F5, 0x031A, 0x0631, - 0x0001, 0x0001, 0x0001, 0x0001, -}; - -const u16 b43legacy_ilt_noiseg2[B43legacy_ILT_NOISEG2_SIZE] = { - 0x5484, 0x3C40, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, -}; - -const u16 b43legacy_ilt_noisescaleg1[B43legacy_ILT_NOISESCALEG_SIZE] = { - 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ - 0x2F2D, 0x2A2A, 0x2527, 0x1F21, - 0x1A1D, 0x1719, 0x1616, 0x1414, - 0x1414, 0x1400, 0x1414, 0x1614, - 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ - 0x2A27, 0x2F2A, 0x332D, 0x3B35, - 0x5140, 0x6C62, 0x0077, -}; - -const u16 b43legacy_ilt_noisescaleg2[B43legacy_ILT_NOISESCALEG_SIZE] = { - 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */ - 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, - 0x969B, 0x9195, 0x8F8F, 0x8A8A, - 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, - 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ - 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, - 0xCBC0, 0xD8D4, 0x00DD, -}; - -const u16 b43legacy_ilt_noisescaleg3[B43legacy_ILT_NOISESCALEG_SIZE] = { - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0x00A4, -}; - -const u16 b43legacy_ilt_sigmasqr1[B43legacy_ILT_SIGMASQR_SIZE] = { - 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ - 0x0067, 0x0063, 0x005E, 0x0059, - 0x0054, 0x0050, 0x004B, 0x0046, - 0x0042, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x0000, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x0042, 0x0046, 0x004B, 0x0050, - 0x0054, 0x0059, 0x005E, 0x0063, - 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ - 0x007A, -}; - -const u16 b43legacy_ilt_sigmasqr2[B43legacy_ILT_SIGMASQR_SIZE] = { - 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ - 0x00D6, 0x00D4, 0x00D2, 0x00CF, - 0x00CD, 0x00CA, 0x00C7, 0x00C4, - 0x00C1, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x0000, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00C1, 0x00C4, 0x00C7, 0x00CA, - 0x00CD, 0x00CF, 0x00D2, 0x00D4, - 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ - 0x00DE, -}; - -/**** Helper functions to access the device Internal Lookup Tables ****/ - -void b43legacy_ilt_write(struct b43legacy_wldev *dev, u16 offset, u16 val) -{ - b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); - mmiowb(); - b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, val); -} - -void b43legacy_ilt_write32(struct b43legacy_wldev *dev, u16 offset, u32 val) -{ - b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); - mmiowb(); - b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA2, - (val & 0xFFFF0000) >> 16); - b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_DATA1, - val & 0x0000FFFF); -} - -u16 b43legacy_ilt_read(struct b43legacy_wldev *dev, u16 offset) -{ - b43legacy_phy_write(dev, B43legacy_PHY_ILT_G_CTRL, offset); - return b43legacy_phy_read(dev, B43legacy_PHY_ILT_G_DATA1); -} diff --git a/drivers/net/wireless/b43legacy/ilt.h b/drivers/net/wireless/b43legacy/ilt.h deleted file mode 100644 index 48bcf37eccb8..000000000000 --- a/drivers/net/wireless/b43legacy/ilt.h +++ /dev/null @@ -1,34 +0,0 @@ -#ifndef B43legacy_ILT_H_ -#define B43legacy_ILT_H_ - -#define B43legacy_ILT_ROTOR_SIZE 53 -extern const u32 b43legacy_ilt_rotor[B43legacy_ILT_ROTOR_SIZE]; -#define B43legacy_ILT_RETARD_SIZE 53 -extern const u32 b43legacy_ilt_retard[B43legacy_ILT_RETARD_SIZE]; -#define B43legacy_ILT_FINEFREQA_SIZE 256 -extern const u16 b43legacy_ilt_finefreqa[B43legacy_ILT_FINEFREQA_SIZE]; -#define B43legacy_ILT_FINEFREQG_SIZE 256 -extern const u16 b43legacy_ilt_finefreqg[B43legacy_ILT_FINEFREQG_SIZE]; -#define B43legacy_ILT_NOISEA2_SIZE 8 -extern const u16 b43legacy_ilt_noisea2[B43legacy_ILT_NOISEA2_SIZE]; -#define B43legacy_ILT_NOISEA3_SIZE 8 -extern const u16 b43legacy_ilt_noisea3[B43legacy_ILT_NOISEA3_SIZE]; -#define B43legacy_ILT_NOISEG1_SIZE 8 -extern const u16 b43legacy_ilt_noiseg1[B43legacy_ILT_NOISEG1_SIZE]; -#define B43legacy_ILT_NOISEG2_SIZE 8 -extern const u16 b43legacy_ilt_noiseg2[B43legacy_ILT_NOISEG2_SIZE]; -#define B43legacy_ILT_NOISESCALEG_SIZE 27 -extern const u16 b43legacy_ilt_noisescaleg1[B43legacy_ILT_NOISESCALEG_SIZE]; -extern const u16 b43legacy_ilt_noisescaleg2[B43legacy_ILT_NOISESCALEG_SIZE]; -extern const u16 b43legacy_ilt_noisescaleg3[B43legacy_ILT_NOISESCALEG_SIZE]; -#define B43legacy_ILT_SIGMASQR_SIZE 53 -extern const u16 b43legacy_ilt_sigmasqr1[B43legacy_ILT_SIGMASQR_SIZE]; -extern const u16 b43legacy_ilt_sigmasqr2[B43legacy_ILT_SIGMASQR_SIZE]; - - -void b43legacy_ilt_write(struct b43legacy_wldev *dev, u16 offset, u16 val); -void b43legacy_ilt_write32(struct b43legacy_wldev *dev, u16 offset, - u32 val); -u16 b43legacy_ilt_read(struct b43legacy_wldev *dev, u16 offset); - -#endif /* B43legacy_ILT_H_ */ diff --git a/drivers/net/wireless/b43legacy/leds.c b/drivers/net/wireless/b43legacy/leds.c deleted file mode 100644 index 37e9be893560..000000000000 --- a/drivers/net/wireless/b43legacy/leds.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - - Broadcom B43 wireless driver - LED control - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005 Stefano Brivio - Copyright (c) 2005-2007 Michael Buesch - Copyright (c) 2005 Danny van Dyk - Copyright (c) 2005 Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43legacy.h" -#include "leds.h" -#include "rfkill.h" - - -static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index, - bool activelow) -{ - struct b43legacy_wl *wl = dev->wl; - unsigned long flags; - u16 ctl; - - spin_lock_irqsave(&wl->leds_lock, flags); - ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL); - if (activelow) - ctl &= ~(1 << led_index); - else - ctl |= (1 << led_index); - b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl); - spin_unlock_irqrestore(&wl->leds_lock, flags); -} - -static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index, - bool activelow) -{ - struct b43legacy_wl *wl = dev->wl; - unsigned long flags; - u16 ctl; - - spin_lock_irqsave(&wl->leds_lock, flags); - ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL); - if (activelow) - ctl |= (1 << led_index); - else - ctl &= ~(1 << led_index); - b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl); - spin_unlock_irqrestore(&wl->leds_lock, flags); -} - -/* Callback from the LED subsystem. */ -static void b43legacy_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led, - led_dev); - struct b43legacy_wldev *dev = led->dev; - bool radio_enabled; - - /* Checking the radio-enabled status here is slightly racy, - * but we want to avoid the locking overhead and we don't care - * whether the LED has the wrong state for a second. */ - radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable); - - if (brightness == LED_OFF || !radio_enabled) - b43legacy_led_turn_off(dev, led->index, led->activelow); - else - b43legacy_led_turn_on(dev, led->index, led->activelow); -} - -static int b43legacy_register_led(struct b43legacy_wldev *dev, - struct b43legacy_led *led, - const char *name, - const char *default_trigger, - u8 led_index, bool activelow) -{ - int err; - - b43legacy_led_turn_off(dev, led_index, activelow); - if (led->dev) - return -EEXIST; - if (!default_trigger) - return -EINVAL; - led->dev = dev; - led->index = led_index; - led->activelow = activelow; - strncpy(led->name, name, sizeof(led->name)); - - led->led_dev.name = led->name; - led->led_dev.default_trigger = default_trigger; - led->led_dev.brightness_set = b43legacy_led_brightness_set; - - err = led_classdev_register(dev->dev->dev, &led->led_dev); - if (err) { - b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name); - led->dev = NULL; - return err; - } - return 0; -} - -static void b43legacy_unregister_led(struct b43legacy_led *led) -{ - if (!led->dev) - return; - led_classdev_unregister(&led->led_dev); - b43legacy_led_turn_off(led->dev, led->index, led->activelow); - led->dev = NULL; -} - -static void b43legacy_map_led(struct b43legacy_wldev *dev, - u8 led_index, - enum b43legacy_led_behaviour behaviour, - bool activelow) -{ - struct ieee80211_hw *hw = dev->wl->hw; - char name[B43legacy_LED_MAX_NAME_LEN + 1]; - - /* Map the b43 specific LED behaviour value to the - * generic LED triggers. */ - switch (behaviour) { - case B43legacy_LED_INACTIVE: - break; - case B43legacy_LED_OFF: - b43legacy_led_turn_off(dev, led_index, activelow); - break; - case B43legacy_LED_ON: - b43legacy_led_turn_on(dev, led_index, activelow); - break; - case B43legacy_LED_ACTIVITY: - case B43legacy_LED_TRANSFER: - case B43legacy_LED_APTRANSFER: - snprintf(name, sizeof(name), - "b43legacy-%s::tx", wiphy_name(hw->wiphy)); - b43legacy_register_led(dev, &dev->led_tx, name, - ieee80211_get_tx_led_name(hw), - led_index, activelow); - snprintf(name, sizeof(name), - "b43legacy-%s::rx", wiphy_name(hw->wiphy)); - b43legacy_register_led(dev, &dev->led_rx, name, - ieee80211_get_rx_led_name(hw), - led_index, activelow); - break; - case B43legacy_LED_RADIO_ALL: - case B43legacy_LED_RADIO_A: - case B43legacy_LED_RADIO_B: - case B43legacy_LED_MODE_BG: - snprintf(name, sizeof(name), - "b43legacy-%s::radio", wiphy_name(hw->wiphy)); - b43legacy_register_led(dev, &dev->led_radio, name, - ieee80211_get_radio_led_name(hw), - led_index, activelow); - /* Sync the RF-kill LED state with radio and switch states. */ - if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev)) - b43legacy_led_turn_on(dev, led_index, activelow); - break; - case B43legacy_LED_WEIRD: - case B43legacy_LED_ASSOC: - snprintf(name, sizeof(name), - "b43legacy-%s::assoc", wiphy_name(hw->wiphy)); - b43legacy_register_led(dev, &dev->led_assoc, name, - ieee80211_get_assoc_led_name(hw), - led_index, activelow); - break; - default: - b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n", - behaviour); - break; - } -} - -void b43legacy_leds_init(struct b43legacy_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - u8 sprom[4]; - int i; - enum b43legacy_led_behaviour behaviour; - bool activelow; - - sprom[0] = bus->sprom.gpio0; - sprom[1] = bus->sprom.gpio1; - sprom[2] = bus->sprom.gpio2; - sprom[3] = bus->sprom.gpio3; - - for (i = 0; i < 4; i++) { - if (sprom[i] == 0xFF) { - /* There is no LED information in the SPROM - * for this LED. Hardcode it here. */ - activelow = 0; - switch (i) { - case 0: - behaviour = B43legacy_LED_ACTIVITY; - activelow = 1; - if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ) - behaviour = B43legacy_LED_RADIO_ALL; - break; - case 1: - behaviour = B43legacy_LED_RADIO_B; - if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK) - behaviour = B43legacy_LED_ASSOC; - break; - case 2: - behaviour = B43legacy_LED_RADIO_A; - break; - case 3: - behaviour = B43legacy_LED_OFF; - break; - default: - B43legacy_WARN_ON(1); - return; - } - } else { - behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR; - activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW); - } - b43legacy_map_led(dev, i, behaviour, activelow); - } -} - -void b43legacy_leds_exit(struct b43legacy_wldev *dev) -{ - b43legacy_unregister_led(&dev->led_tx); - b43legacy_unregister_led(&dev->led_rx); - b43legacy_unregister_led(&dev->led_assoc); - b43legacy_unregister_led(&dev->led_radio); -} diff --git a/drivers/net/wireless/b43legacy/leds.h b/drivers/net/wireless/b43legacy/leds.h deleted file mode 100644 index 82167a90088f..000000000000 --- a/drivers/net/wireless/b43legacy/leds.h +++ /dev/null @@ -1,63 +0,0 @@ -#ifndef B43legacy_LEDS_H_ -#define B43legacy_LEDS_H_ - -struct b43legacy_wldev; - -#ifdef CONFIG_B43LEGACY_LEDS - -#include -#include - - -#define B43legacy_LED_MAX_NAME_LEN 31 - -struct b43legacy_led { - struct b43legacy_wldev *dev; - /* The LED class device */ - struct led_classdev led_dev; - /* The index number of the LED. */ - u8 index; - /* If activelow is true, the LED is ON if the - * bit is switched off. */ - bool activelow; - /* The unique name string for this LED device. */ - char name[B43legacy_LED_MAX_NAME_LEN + 1]; -}; - -#define B43legacy_LED_BEHAVIOUR 0x7F -#define B43legacy_LED_ACTIVELOW 0x80 -/* LED behaviour values */ -enum b43legacy_led_behaviour { - B43legacy_LED_OFF, - B43legacy_LED_ON, - B43legacy_LED_ACTIVITY, - B43legacy_LED_RADIO_ALL, - B43legacy_LED_RADIO_A, - B43legacy_LED_RADIO_B, - B43legacy_LED_MODE_BG, - B43legacy_LED_TRANSFER, - B43legacy_LED_APTRANSFER, - B43legacy_LED_WEIRD, - B43legacy_LED_ASSOC, - B43legacy_LED_INACTIVE, -}; - -void b43legacy_leds_init(struct b43legacy_wldev *dev); -void b43legacy_leds_exit(struct b43legacy_wldev *dev); - -#else /* CONFIG_B43EGACY_LEDS */ -/* LED support disabled */ - -struct b43legacy_led { - /* empty */ -}; - -static inline void b43legacy_leds_init(struct b43legacy_wldev *dev) -{ -} -static inline void b43legacy_leds_exit(struct b43legacy_wldev *dev) -{ -} -#endif /* CONFIG_B43LEGACY_LEDS */ - -#endif /* B43legacy_LEDS_H_ */ diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c deleted file mode 100644 index c3968fad55e1..000000000000 --- a/drivers/net/wireless/b43legacy/main.c +++ /dev/null @@ -1,4015 +0,0 @@ -/* - * - * Broadcom B43legacy wireless driver - * - * Copyright (c) 2005 Martin Langer - * Copyright (c) 2005-2008 Stefano Brivio - * Copyright (c) 2005, 2006 Michael Buesch - * Copyright (c) 2005 Danny van Dyk - * Copyright (c) 2005 Andreas Jaggi - * Copyright (c) 2007 Larry Finger - * - * Some parts of the code in this file are derived from the ipw2200 - * driver Copyright(c) 2003 - 2004 Intel Corporation. - - * 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; see the file COPYING. If not, write to - * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - * Boston, MA 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "b43legacy.h" -#include "main.h" -#include "debugfs.h" -#include "phy.h" -#include "dma.h" -#include "pio.h" -#include "sysfs.h" -#include "xmit.h" -#include "radio.h" - - -MODULE_DESCRIPTION("Broadcom B43legacy wireless driver"); -MODULE_AUTHOR("Martin Langer"); -MODULE_AUTHOR("Stefano Brivio"); -MODULE_AUTHOR("Michael Buesch"); -MODULE_LICENSE("GPL"); - -MODULE_FIRMWARE(B43legacy_SUPPORTED_FIRMWARE_ID); - -#if defined(CONFIG_B43LEGACY_DMA) && defined(CONFIG_B43LEGACY_PIO) -static int modparam_pio; -module_param_named(pio, modparam_pio, int, 0444); -MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); -#elif defined(CONFIG_B43LEGACY_DMA) -# define modparam_pio 0 -#elif defined(CONFIG_B43LEGACY_PIO) -# define modparam_pio 1 -#endif - -static int modparam_bad_frames_preempt; -module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); -MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames" - " Preemption"); - -static char modparam_fwpostfix[16]; -module_param_string(fwpostfix, modparam_fwpostfix, 16, 0444); -MODULE_PARM_DESC(fwpostfix, "Postfix for the firmware files to load."); - -/* The following table supports BCM4301, BCM4303 and BCM4306/2 devices. */ -static const struct ssb_device_id b43legacy_ssb_tbl[] = { - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 2), - SSB_DEVICE(SSB_VENDOR_BROADCOM, SSB_DEV_80211, 4), - SSB_DEVTABLE_END -}; -MODULE_DEVICE_TABLE(ssb, b43legacy_ssb_tbl); - - -/* Channel and ratetables are shared for all devices. - * They can't be const, because ieee80211 puts some precalculated - * data in there. This data is the same for all devices, so we don't - * get concurrency issues */ -#define RATETAB_ENT(_rateid, _flags) \ - { \ - .bitrate = B43legacy_RATE_TO_100KBPS(_rateid), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ - } -/* - * NOTE: When changing this, sync with xmit.c's - * b43legacy_plcp_get_bitrate_idx_* functions! - */ -static struct ieee80211_rate __b43legacy_ratetable[] = { - RATETAB_ENT(B43legacy_CCK_RATE_1MB, 0), - RATETAB_ENT(B43legacy_CCK_RATE_2MB, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(B43legacy_CCK_RATE_5MB, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(B43legacy_CCK_RATE_11MB, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(B43legacy_OFDM_RATE_6MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_9MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_12MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_18MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_24MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_36MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_48MB, 0), - RATETAB_ENT(B43legacy_OFDM_RATE_54MB, 0), -}; -#define b43legacy_b_ratetable (__b43legacy_ratetable + 0) -#define b43legacy_b_ratetable_size 4 -#define b43legacy_g_ratetable (__b43legacy_ratetable + 0) -#define b43legacy_g_ratetable_size 12 - -#define CHANTAB_ENT(_chanid, _freq) \ - { \ - .center_freq = (_freq), \ - .hw_value = (_chanid), \ - } -static struct ieee80211_channel b43legacy_bg_chantable[] = { - CHANTAB_ENT(1, 2412), - CHANTAB_ENT(2, 2417), - CHANTAB_ENT(3, 2422), - CHANTAB_ENT(4, 2427), - CHANTAB_ENT(5, 2432), - CHANTAB_ENT(6, 2437), - CHANTAB_ENT(7, 2442), - CHANTAB_ENT(8, 2447), - CHANTAB_ENT(9, 2452), - CHANTAB_ENT(10, 2457), - CHANTAB_ENT(11, 2462), - CHANTAB_ENT(12, 2467), - CHANTAB_ENT(13, 2472), - CHANTAB_ENT(14, 2484), -}; - -static struct ieee80211_supported_band b43legacy_band_2GHz_BPHY = { - .channels = b43legacy_bg_chantable, - .n_channels = ARRAY_SIZE(b43legacy_bg_chantable), - .bitrates = b43legacy_b_ratetable, - .n_bitrates = b43legacy_b_ratetable_size, -}; - -static struct ieee80211_supported_band b43legacy_band_2GHz_GPHY = { - .channels = b43legacy_bg_chantable, - .n_channels = ARRAY_SIZE(b43legacy_bg_chantable), - .bitrates = b43legacy_g_ratetable, - .n_bitrates = b43legacy_g_ratetable_size, -}; - -static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev); -static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev); -static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev); -static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev); - - -static int b43legacy_ratelimit(struct b43legacy_wl *wl) -{ - if (!wl || !wl->current_dev) - return 1; - if (b43legacy_status(wl->current_dev) < B43legacy_STAT_STARTED) - return 1; - /* We are up and running. - * Ratelimit the messages to avoid DoS over the net. */ - return net_ratelimit(); -} - -void b43legacyinfo(struct b43legacy_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (!b43legacy_ratelimit(wl)) - return; - va_start(args, fmt); - printk(KERN_INFO "b43legacy-%s: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -void b43legacyerr(struct b43legacy_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (!b43legacy_ratelimit(wl)) - return; - va_start(args, fmt); - printk(KERN_ERR "b43legacy-%s ERROR: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -void b43legacywarn(struct b43legacy_wl *wl, const char *fmt, ...) -{ - va_list args; - - if (!b43legacy_ratelimit(wl)) - return; - va_start(args, fmt); - printk(KERN_WARNING "b43legacy-%s warning: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} - -#if B43legacy_DEBUG -void b43legacydbg(struct b43legacy_wl *wl, const char *fmt, ...) -{ - va_list args; - - va_start(args, fmt); - printk(KERN_DEBUG "b43legacy-%s debug: ", - (wl && wl->hw) ? wiphy_name(wl->hw->wiphy) : "wlan"); - vprintk(fmt, args); - va_end(args); -} -#endif /* DEBUG */ - -static void b43legacy_ram_write(struct b43legacy_wldev *dev, u16 offset, - u32 val) -{ - u32 status; - - B43legacy_WARN_ON(offset % 4 != 0); - - status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - if (status & B43legacy_MACCTL_BE) - val = swab32(val); - - b43legacy_write32(dev, B43legacy_MMIO_RAM_CONTROL, offset); - mmiowb(); - b43legacy_write32(dev, B43legacy_MMIO_RAM_DATA, val); -} - -static inline -void b43legacy_shm_control_word(struct b43legacy_wldev *dev, - u16 routing, u16 offset) -{ - u32 control; - - /* "offset" is the WORD offset. */ - - control = routing; - control <<= 16; - control |= offset; - b43legacy_write32(dev, B43legacy_MMIO_SHM_CONTROL, control); -} - -u32 b43legacy_shm_read32(struct b43legacy_wldev *dev, - u16 routing, u16 offset) -{ - u32 ret; - - if (routing == B43legacy_SHM_SHARED) { - B43legacy_WARN_ON((offset & 0x0001) != 0); - if (offset & 0x0003) { - /* Unaligned access */ - b43legacy_shm_control_word(dev, routing, offset >> 2); - ret = b43legacy_read16(dev, - B43legacy_MMIO_SHM_DATA_UNALIGNED); - ret <<= 16; - b43legacy_shm_control_word(dev, routing, - (offset >> 2) + 1); - ret |= b43legacy_read16(dev, B43legacy_MMIO_SHM_DATA); - - return ret; - } - offset >>= 2; - } - b43legacy_shm_control_word(dev, routing, offset); - ret = b43legacy_read32(dev, B43legacy_MMIO_SHM_DATA); - - return ret; -} - -u16 b43legacy_shm_read16(struct b43legacy_wldev *dev, - u16 routing, u16 offset) -{ - u16 ret; - - if (routing == B43legacy_SHM_SHARED) { - B43legacy_WARN_ON((offset & 0x0001) != 0); - if (offset & 0x0003) { - /* Unaligned access */ - b43legacy_shm_control_word(dev, routing, offset >> 2); - ret = b43legacy_read16(dev, - B43legacy_MMIO_SHM_DATA_UNALIGNED); - - return ret; - } - offset >>= 2; - } - b43legacy_shm_control_word(dev, routing, offset); - ret = b43legacy_read16(dev, B43legacy_MMIO_SHM_DATA); - - return ret; -} - -void b43legacy_shm_write32(struct b43legacy_wldev *dev, - u16 routing, u16 offset, - u32 value) -{ - if (routing == B43legacy_SHM_SHARED) { - B43legacy_WARN_ON((offset & 0x0001) != 0); - if (offset & 0x0003) { - /* Unaligned access */ - b43legacy_shm_control_word(dev, routing, offset >> 2); - mmiowb(); - b43legacy_write16(dev, - B43legacy_MMIO_SHM_DATA_UNALIGNED, - (value >> 16) & 0xffff); - mmiowb(); - b43legacy_shm_control_word(dev, routing, - (offset >> 2) + 1); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA, - value & 0xffff); - return; - } - offset >>= 2; - } - b43legacy_shm_control_word(dev, routing, offset); - mmiowb(); - b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, value); -} - -void b43legacy_shm_write16(struct b43legacy_wldev *dev, u16 routing, u16 offset, - u16 value) -{ - if (routing == B43legacy_SHM_SHARED) { - B43legacy_WARN_ON((offset & 0x0001) != 0); - if (offset & 0x0003) { - /* Unaligned access */ - b43legacy_shm_control_word(dev, routing, offset >> 2); - mmiowb(); - b43legacy_write16(dev, - B43legacy_MMIO_SHM_DATA_UNALIGNED, - value); - return; - } - offset >>= 2; - } - b43legacy_shm_control_word(dev, routing, offset); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_SHM_DATA, value); -} - -/* Read HostFlags */ -u32 b43legacy_hf_read(struct b43legacy_wldev *dev) -{ - u32 ret; - - ret = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_HOSTFHI); - ret <<= 16; - ret |= b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_HOSTFLO); - - return ret; -} - -/* Write HostFlags */ -void b43legacy_hf_write(struct b43legacy_wldev *dev, u32 value) -{ - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_HOSTFLO, - (value & 0x0000FFFF)); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_HOSTFHI, - ((value & 0xFFFF0000) >> 16)); -} - -void b43legacy_tsf_read(struct b43legacy_wldev *dev, u64 *tsf) -{ - /* We need to be careful. As we read the TSF from multiple - * registers, we should take care of register overflows. - * In theory, the whole tsf read process should be atomic. - * We try to be atomic here, by restaring the read process, - * if any of the high registers changed (overflew). - */ - if (dev->dev->id.revision >= 3) { - u32 low; - u32 high; - u32 high2; - - do { - high = b43legacy_read32(dev, - B43legacy_MMIO_REV3PLUS_TSF_HIGH); - low = b43legacy_read32(dev, - B43legacy_MMIO_REV3PLUS_TSF_LOW); - high2 = b43legacy_read32(dev, - B43legacy_MMIO_REV3PLUS_TSF_HIGH); - } while (unlikely(high != high2)); - - *tsf = high; - *tsf <<= 32; - *tsf |= low; - } else { - u64 tmp; - u16 v0; - u16 v1; - u16 v2; - u16 v3; - u16 test1; - u16 test2; - u16 test3; - - do { - v3 = b43legacy_read16(dev, B43legacy_MMIO_TSF_3); - v2 = b43legacy_read16(dev, B43legacy_MMIO_TSF_2); - v1 = b43legacy_read16(dev, B43legacy_MMIO_TSF_1); - v0 = b43legacy_read16(dev, B43legacy_MMIO_TSF_0); - - test3 = b43legacy_read16(dev, B43legacy_MMIO_TSF_3); - test2 = b43legacy_read16(dev, B43legacy_MMIO_TSF_2); - test1 = b43legacy_read16(dev, B43legacy_MMIO_TSF_1); - } while (v3 != test3 || v2 != test2 || v1 != test1); - - *tsf = v3; - *tsf <<= 48; - tmp = v2; - tmp <<= 32; - *tsf |= tmp; - tmp = v1; - tmp <<= 16; - *tsf |= tmp; - *tsf |= v0; - } -} - -static void b43legacy_time_lock(struct b43legacy_wldev *dev) -{ - u32 status; - - status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - status |= B43legacy_MACCTL_TBTTHOLD; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - mmiowb(); -} - -static void b43legacy_time_unlock(struct b43legacy_wldev *dev) -{ - u32 status; - - status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - status &= ~B43legacy_MACCTL_TBTTHOLD; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); -} - -static void b43legacy_tsf_write_locked(struct b43legacy_wldev *dev, u64 tsf) -{ - /* Be careful with the in-progress timer. - * First zero out the low register, so we have a full - * register-overflow duration to complete the operation. - */ - if (dev->dev->id.revision >= 3) { - u32 lo = (tsf & 0x00000000FFFFFFFFULL); - u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; - - b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, 0); - mmiowb(); - b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_HIGH, - hi); - mmiowb(); - b43legacy_write32(dev, B43legacy_MMIO_REV3PLUS_TSF_LOW, - lo); - } else { - u16 v0 = (tsf & 0x000000000000FFFFULL); - u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; - u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; - u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; - - b43legacy_write16(dev, B43legacy_MMIO_TSF_0, 0); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_TSF_3, v3); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_TSF_2, v2); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_TSF_1, v1); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_TSF_0, v0); - } -} - -void b43legacy_tsf_write(struct b43legacy_wldev *dev, u64 tsf) -{ - b43legacy_time_lock(dev); - b43legacy_tsf_write_locked(dev, tsf); - b43legacy_time_unlock(dev); -} - -static -void b43legacy_macfilter_set(struct b43legacy_wldev *dev, - u16 offset, const u8 *mac) -{ - static const u8 zero_addr[ETH_ALEN] = { 0 }; - u16 data; - - if (!mac) - mac = zero_addr; - - offset |= 0x0020; - b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_CONTROL, offset); - - data = mac[0]; - data |= mac[1] << 8; - b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data); - data = mac[2]; - data |= mac[3] << 8; - b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data); - data = mac[4]; - data |= mac[5] << 8; - b43legacy_write16(dev, B43legacy_MMIO_MACFILTER_DATA, data); -} - -static void b43legacy_write_mac_bssid_templates(struct b43legacy_wldev *dev) -{ - static const u8 zero_addr[ETH_ALEN] = { 0 }; - const u8 *mac = dev->wl->mac_addr; - const u8 *bssid = dev->wl->bssid; - u8 mac_bssid[ETH_ALEN * 2]; - int i; - u32 tmp; - - if (!bssid) - bssid = zero_addr; - if (!mac) - mac = zero_addr; - - b43legacy_macfilter_set(dev, B43legacy_MACFILTER_BSSID, bssid); - - memcpy(mac_bssid, mac, ETH_ALEN); - memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); - - /* Write our MAC address and BSSID to template ram */ - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) { - tmp = (u32)(mac_bssid[i + 0]); - tmp |= (u32)(mac_bssid[i + 1]) << 8; - tmp |= (u32)(mac_bssid[i + 2]) << 16; - tmp |= (u32)(mac_bssid[i + 3]) << 24; - b43legacy_ram_write(dev, 0x20 + i, tmp); - b43legacy_ram_write(dev, 0x78 + i, tmp); - b43legacy_ram_write(dev, 0x478 + i, tmp); - } -} - -static void b43legacy_upload_card_macaddress(struct b43legacy_wldev *dev) -{ - b43legacy_write_mac_bssid_templates(dev); - b43legacy_macfilter_set(dev, B43legacy_MACFILTER_SELF, - dev->wl->mac_addr); -} - -static void b43legacy_set_slot_time(struct b43legacy_wldev *dev, - u16 slot_time) -{ - /* slot_time is in usec. */ - if (dev->phy.type != B43legacy_PHYTYPE_G) - return; - b43legacy_write16(dev, 0x684, 510 + slot_time); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0010, - slot_time); -} - -static void b43legacy_short_slot_timing_enable(struct b43legacy_wldev *dev) -{ - b43legacy_set_slot_time(dev, 9); -} - -static void b43legacy_short_slot_timing_disable(struct b43legacy_wldev *dev) -{ - b43legacy_set_slot_time(dev, 20); -} - -/* Synchronize IRQ top- and bottom-half. - * IRQs must be masked before calling this. - * This must not be called with the irq_lock held. - */ -static void b43legacy_synchronize_irq(struct b43legacy_wldev *dev) -{ - synchronize_irq(dev->dev->irq); - tasklet_kill(&dev->isr_tasklet); -} - -/* DummyTransmission function, as documented on - * http://bcm-specs.sipsolutions.net/DummyTransmission - */ -void b43legacy_dummy_transmission(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - unsigned int i; - unsigned int max_loop; - u16 value; - u32 buffer[5] = { - 0x00000000, - 0x00D40000, - 0x00000000, - 0x01000000, - 0x00000000, - }; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - max_loop = 0xFA; - buffer[0] = 0x000B846E; - break; - default: - B43legacy_BUG_ON(1); - return; - } - - for (i = 0; i < 5; i++) - b43legacy_ram_write(dev, i * 4, buffer[i]); - - /* dummy read follows */ - b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - - b43legacy_write16(dev, 0x0568, 0x0000); - b43legacy_write16(dev, 0x07C0, 0x0000); - b43legacy_write16(dev, 0x050C, 0x0000); - b43legacy_write16(dev, 0x0508, 0x0000); - b43legacy_write16(dev, 0x050A, 0x0000); - b43legacy_write16(dev, 0x054C, 0x0000); - b43legacy_write16(dev, 0x056A, 0x0014); - b43legacy_write16(dev, 0x0568, 0x0826); - b43legacy_write16(dev, 0x0500, 0x0000); - b43legacy_write16(dev, 0x0502, 0x0030); - - if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) - b43legacy_radio_write16(dev, 0x0051, 0x0017); - for (i = 0x00; i < max_loop; i++) { - value = b43legacy_read16(dev, 0x050E); - if (value & 0x0080) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = b43legacy_read16(dev, 0x050E); - if (value & 0x0400) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = b43legacy_read16(dev, 0x0690); - if (!(value & 0x0100)) - break; - udelay(10); - } - if (phy->radio_ver == 0x2050 && phy->radio_rev <= 0x5) - b43legacy_radio_write16(dev, 0x0051, 0x0037); -} - -/* Turn the Analog ON/OFF */ -static void b43legacy_switch_analog(struct b43legacy_wldev *dev, int on) -{ - b43legacy_write16(dev, B43legacy_MMIO_PHY0, on ? 0 : 0xF4); -} - -void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags) -{ - u32 tmslow; - u32 macctl; - - flags |= B43legacy_TMSLOW_PHYCLKEN; - flags |= B43legacy_TMSLOW_PHYRESET; - ssb_device_enable(dev->dev, flags); - msleep(2); /* Wait for the PLL to turn on. */ - - /* Now take the PHY out of Reset again */ - tmslow = ssb_read32(dev->dev, SSB_TMSLOW); - tmslow |= SSB_TMSLOW_FGC; - tmslow &= ~B43legacy_TMSLOW_PHYRESET; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ - msleep(1); - tmslow &= ~SSB_TMSLOW_FGC; - ssb_write32(dev->dev, SSB_TMSLOW, tmslow); - ssb_read32(dev->dev, SSB_TMSLOW); /* flush */ - msleep(1); - - /* Turn Analog ON */ - b43legacy_switch_analog(dev, 1); - - macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - macctl &= ~B43legacy_MACCTL_GMODE; - if (flags & B43legacy_TMSLOW_GMODE) { - macctl |= B43legacy_MACCTL_GMODE; - dev->phy.gmode = 1; - } else - dev->phy.gmode = 0; - macctl |= B43legacy_MACCTL_IHR_ENABLED; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); -} - -static void handle_irq_transmit_status(struct b43legacy_wldev *dev) -{ - u32 v0; - u32 v1; - u16 tmp; - struct b43legacy_txstatus stat; - - while (1) { - v0 = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_0); - if (!(v0 & 0x00000001)) - break; - v1 = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_1); - - stat.cookie = (v0 >> 16); - stat.seq = (v1 & 0x0000FFFF); - stat.phy_stat = ((v1 & 0x00FF0000) >> 16); - tmp = (v0 & 0x0000FFFF); - stat.frame_count = ((tmp & 0xF000) >> 12); - stat.rts_count = ((tmp & 0x0F00) >> 8); - stat.supp_reason = ((tmp & 0x001C) >> 2); - stat.pm_indicated = !!(tmp & 0x0080); - stat.intermediate = !!(tmp & 0x0040); - stat.for_ampdu = !!(tmp & 0x0020); - stat.acked = !!(tmp & 0x0002); - - b43legacy_handle_txstatus(dev, &stat); - } -} - -static void drain_txstatus_queue(struct b43legacy_wldev *dev) -{ - u32 dummy; - - if (dev->dev->id.revision < 5) - return; - /* Read all entries from the microcode TXstatus FIFO - * and throw them away. - */ - while (1) { - dummy = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_0); - if (!(dummy & 0x00000001)) - break; - dummy = b43legacy_read32(dev, B43legacy_MMIO_XMITSTAT_1); - } -} - -static u32 b43legacy_jssi_read(struct b43legacy_wldev *dev) -{ - u32 val = 0; - - val = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x40A); - val <<= 16; - val |= b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x408); - - return val; -} - -static void b43legacy_jssi_write(struct b43legacy_wldev *dev, u32 jssi) -{ - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x408, - (jssi & 0x0000FFFF)); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x40A, - (jssi & 0xFFFF0000) >> 16); -} - -static void b43legacy_generate_noise_sample(struct b43legacy_wldev *dev) -{ - b43legacy_jssi_write(dev, 0x7F7F7F7F); - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - b43legacy_read32(dev, B43legacy_MMIO_MACCMD) - | B43legacy_MACCMD_BGNOISE); - B43legacy_WARN_ON(dev->noisecalc.channel_at_start != - dev->phy.channel); -} - -static void b43legacy_calculate_link_quality(struct b43legacy_wldev *dev) -{ - /* Top half of Link Quality calculation. */ - - if (dev->noisecalc.calculation_running) - return; - dev->noisecalc.channel_at_start = dev->phy.channel; - dev->noisecalc.calculation_running = 1; - dev->noisecalc.nr_samples = 0; - - b43legacy_generate_noise_sample(dev); -} - -static void handle_irq_noise(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 tmp; - u8 noise[4]; - u8 i; - u8 j; - s32 average; - - /* Bottom half of Link Quality calculation. */ - - B43legacy_WARN_ON(!dev->noisecalc.calculation_running); - if (dev->noisecalc.channel_at_start != phy->channel) - goto drop_calculation; - *((__le32 *)noise) = cpu_to_le32(b43legacy_jssi_read(dev)); - if (noise[0] == 0x7F || noise[1] == 0x7F || - noise[2] == 0x7F || noise[3] == 0x7F) - goto generate_new; - - /* Get the noise samples. */ - B43legacy_WARN_ON(dev->noisecalc.nr_samples >= 8); - i = dev->noisecalc.nr_samples; - noise[0] = clamp_val(noise[0], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[1] = clamp_val(noise[1], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[2] = clamp_val(noise[2], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - noise[3] = clamp_val(noise[3], 0, ARRAY_SIZE(phy->nrssi_lt) - 1); - dev->noisecalc.samples[i][0] = phy->nrssi_lt[noise[0]]; - dev->noisecalc.samples[i][1] = phy->nrssi_lt[noise[1]]; - dev->noisecalc.samples[i][2] = phy->nrssi_lt[noise[2]]; - dev->noisecalc.samples[i][3] = phy->nrssi_lt[noise[3]]; - dev->noisecalc.nr_samples++; - if (dev->noisecalc.nr_samples == 8) { - /* Calculate the Link Quality by the noise samples. */ - average = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 4; j++) - average += dev->noisecalc.samples[i][j]; - } - average /= (8 * 4); - average *= 125; - average += 64; - average /= 128; - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - 0x40C); - tmp = (tmp / 128) & 0x1F; - if (tmp >= 8) - average += 2; - else - average -= 25; - if (tmp == 8) - average -= 72; - else - average -= 48; - - dev->stats.link_noise = average; -drop_calculation: - dev->noisecalc.calculation_running = 0; - return; - } -generate_new: - b43legacy_generate_noise_sample(dev); -} - -static void handle_irq_tbtt_indication(struct b43legacy_wldev *dev) -{ - if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) { - /* TODO: PS TBTT */ - } else { - if (1/*FIXME: the last PSpoll frame was sent successfully */) - b43legacy_power_saving_ctl_bits(dev, -1, -1); - } - if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) - dev->dfq_valid = 1; -} - -static void handle_irq_atim_end(struct b43legacy_wldev *dev) -{ - if (dev->dfq_valid) { - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, - b43legacy_read32(dev, B43legacy_MMIO_MACCMD) - | B43legacy_MACCMD_DFQ_VALID); - dev->dfq_valid = 0; - } -} - -static void handle_irq_pmq(struct b43legacy_wldev *dev) -{ - u32 tmp; - - /* TODO: AP mode. */ - - while (1) { - tmp = b43legacy_read32(dev, B43legacy_MMIO_PS_STATUS); - if (!(tmp & 0x00000008)) - break; - } - /* 16bit write is odd, but correct. */ - b43legacy_write16(dev, B43legacy_MMIO_PS_STATUS, 0x0002); -} - -static void b43legacy_write_template_common(struct b43legacy_wldev *dev, - const u8 *data, u16 size, - u16 ram_offset, - u16 shm_size_offset, u8 rate) -{ - u32 i; - u32 tmp; - struct b43legacy_plcp_hdr4 plcp; - - plcp.data = 0; - b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate); - b43legacy_ram_write(dev, ram_offset, le32_to_cpu(plcp.data)); - ram_offset += sizeof(u32); - /* The PLCP is 6 bytes long, but we only wrote 4 bytes, yet. - * So leave the first two bytes of the next write blank. - */ - tmp = (u32)(data[0]) << 16; - tmp |= (u32)(data[1]) << 24; - b43legacy_ram_write(dev, ram_offset, tmp); - ram_offset += sizeof(u32); - for (i = 2; i < size; i += sizeof(u32)) { - tmp = (u32)(data[i + 0]); - if (i + 1 < size) - tmp |= (u32)(data[i + 1]) << 8; - if (i + 2 < size) - tmp |= (u32)(data[i + 2]) << 16; - if (i + 3 < size) - tmp |= (u32)(data[i + 3]) << 24; - b43legacy_ram_write(dev, ram_offset + i - 2, tmp); - } - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_size_offset, - size + sizeof(struct b43legacy_plcp_hdr6)); -} - -/* Convert a b43legacy antenna number value to the PHY TX control value. */ -static u16 b43legacy_antenna_to_phyctl(int antenna) -{ - switch (antenna) { - case B43legacy_ANTENNA0: - return B43legacy_TX4_PHY_ANT0; - case B43legacy_ANTENNA1: - return B43legacy_TX4_PHY_ANT1; - } - return B43legacy_TX4_PHY_ANTLAST; -} - -static void b43legacy_write_beacon_template(struct b43legacy_wldev *dev, - u16 ram_offset, - u16 shm_size_offset) -{ - - unsigned int i, len, variable_len; - const struct ieee80211_mgmt *bcn; - const u8 *ie; - bool tim_found = 0; - unsigned int rate; - u16 ctl; - int antenna; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(dev->wl->current_beacon); - - bcn = (const struct ieee80211_mgmt *)(dev->wl->current_beacon->data); - len = min((size_t)dev->wl->current_beacon->len, - 0x200 - sizeof(struct b43legacy_plcp_hdr6)); - rate = ieee80211_get_tx_rate(dev->wl->hw, info)->hw_value; - - b43legacy_write_template_common(dev, (const u8 *)bcn, len, ram_offset, - shm_size_offset, rate); - - /* Write the PHY TX control parameters. */ - antenna = B43legacy_ANTENNA_DEFAULT; - antenna = b43legacy_antenna_to_phyctl(antenna); - ctl = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_BEACPHYCTL); - /* We can't send beacons with short preamble. Would get PHY errors. */ - ctl &= ~B43legacy_TX4_PHY_SHORTPRMBL; - ctl &= ~B43legacy_TX4_PHY_ANT; - ctl &= ~B43legacy_TX4_PHY_ENC; - ctl |= antenna; - ctl |= B43legacy_TX4_PHY_ENC_CCK; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_BEACPHYCTL, ctl); - - /* Find the position of the TIM and the DTIM_period value - * and write them to SHM. */ - ie = bcn->u.beacon.variable; - variable_len = len - offsetof(struct ieee80211_mgmt, u.beacon.variable); - for (i = 0; i < variable_len - 2; ) { - uint8_t ie_id, ie_len; - - ie_id = ie[i]; - ie_len = ie[i + 1]; - if (ie_id == 5) { - u16 tim_position; - u16 dtim_period; - /* This is the TIM Information Element */ - - /* Check whether the ie_len is in the beacon data range. */ - if (variable_len < ie_len + 2 + i) - break; - /* A valid TIM is at least 4 bytes long. */ - if (ie_len < 4) - break; - tim_found = 1; - - tim_position = sizeof(struct b43legacy_plcp_hdr6); - tim_position += offsetof(struct ieee80211_mgmt, - u.beacon.variable); - tim_position += i; - - dtim_period = ie[i + 3]; - - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_TIMPOS, tim_position); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_DTIMP, dtim_period); - break; - } - i += ie_len + 2; - } - if (!tim_found) { - b43legacywarn(dev->wl, "Did not find a valid TIM IE in the " - "beacon template packet. AP or IBSS operation " - "may be broken.\n"); - } else - b43legacydbg(dev->wl, "Updated beacon template\n"); -} - -static void b43legacy_write_probe_resp_plcp(struct b43legacy_wldev *dev, - u16 shm_offset, u16 size, - struct ieee80211_rate *rate) -{ - struct b43legacy_plcp_hdr4 plcp; - u32 tmp; - __le16 dur; - - plcp.data = 0; - b43legacy_generate_plcp_hdr(&plcp, size + FCS_LEN, rate->hw_value); - dur = ieee80211_generic_frame_duration(dev->wl->hw, - dev->wl->vif, - size, - rate); - /* Write PLCP in two parts and timing for packet transfer */ - tmp = le32_to_cpu(plcp.data); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset, - tmp & 0xFFFF); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset + 2, - tmp >> 16); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, shm_offset + 6, - le16_to_cpu(dur)); -} - -/* Instead of using custom probe response template, this function - * just patches custom beacon template by: - * 1) Changing packet type - * 2) Patching duration field - * 3) Stripping TIM - */ -static const u8 *b43legacy_generate_probe_resp(struct b43legacy_wldev *dev, - u16 *dest_size, - struct ieee80211_rate *rate) -{ - const u8 *src_data; - u8 *dest_data; - u16 src_size, elem_size, src_pos, dest_pos; - __le16 dur; - struct ieee80211_hdr *hdr; - size_t ie_start; - - src_size = dev->wl->current_beacon->len; - src_data = (const u8 *)dev->wl->current_beacon->data; - - /* Get the start offset of the variable IEs in the packet. */ - ie_start = offsetof(struct ieee80211_mgmt, u.probe_resp.variable); - B43legacy_WARN_ON(ie_start != offsetof(struct ieee80211_mgmt, - u.beacon.variable)); - - if (B43legacy_WARN_ON(src_size < ie_start)) - return NULL; - - dest_data = kmalloc(src_size, GFP_ATOMIC); - if (unlikely(!dest_data)) - return NULL; - - /* Copy the static data and all Information Elements, except the TIM. */ - memcpy(dest_data, src_data, ie_start); - src_pos = ie_start; - dest_pos = ie_start; - for ( ; src_pos < src_size - 2; src_pos += elem_size) { - elem_size = src_data[src_pos + 1] + 2; - if (src_data[src_pos] == 5) { - /* This is the TIM. */ - continue; - } - memcpy(dest_data + dest_pos, src_data + src_pos, elem_size); - dest_pos += elem_size; - } - *dest_size = dest_pos; - hdr = (struct ieee80211_hdr *)dest_data; - - /* Set the frame control. */ - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_RESP); - dur = ieee80211_generic_frame_duration(dev->wl->hw, - dev->wl->vif, - *dest_size, - rate); - hdr->duration_id = dur; - - return dest_data; -} - -static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev, - u16 ram_offset, - u16 shm_size_offset, - struct ieee80211_rate *rate) -{ - const u8 *probe_resp_data; - u16 size; - - size = dev->wl->current_beacon->len; - probe_resp_data = b43legacy_generate_probe_resp(dev, &size, rate); - if (unlikely(!probe_resp_data)) - return; - - /* Looks like PLCP headers plus packet timings are stored for - * all possible basic rates - */ - b43legacy_write_probe_resp_plcp(dev, 0x31A, size, - &b43legacy_b_ratetable[0]); - b43legacy_write_probe_resp_plcp(dev, 0x32C, size, - &b43legacy_b_ratetable[1]); - b43legacy_write_probe_resp_plcp(dev, 0x33E, size, - &b43legacy_b_ratetable[2]); - b43legacy_write_probe_resp_plcp(dev, 0x350, size, - &b43legacy_b_ratetable[3]); - - size = min((size_t)size, - 0x200 - sizeof(struct b43legacy_plcp_hdr6)); - b43legacy_write_template_common(dev, probe_resp_data, - size, ram_offset, - shm_size_offset, rate->hw_value); - kfree(probe_resp_data); -} - -static void b43legacy_upload_beacon0(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - - if (wl->beacon0_uploaded) - return; - b43legacy_write_beacon_template(dev, 0x68, 0x18); - /* FIXME: Probe resp upload doesn't really belong here, - * but we don't use that feature anyway. */ - b43legacy_write_probe_resp_template(dev, 0x268, 0x4A, - &__b43legacy_ratetable[3]); - wl->beacon0_uploaded = 1; -} - -static void b43legacy_upload_beacon1(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - - if (wl->beacon1_uploaded) - return; - b43legacy_write_beacon_template(dev, 0x468, 0x1A); - wl->beacon1_uploaded = 1; -} - -static void handle_irq_beacon(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - u32 cmd, beacon0_valid, beacon1_valid; - - if (!b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) - return; - - /* This is the bottom half of the asynchronous beacon update. */ - - /* Ignore interrupt in the future. */ - dev->irq_mask &= ~B43legacy_IRQ_BEACON; - - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - beacon0_valid = (cmd & B43legacy_MACCMD_BEACON0_VALID); - beacon1_valid = (cmd & B43legacy_MACCMD_BEACON1_VALID); - - /* Schedule interrupt manually, if busy. */ - if (beacon0_valid && beacon1_valid) { - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, B43legacy_IRQ_BEACON); - dev->irq_mask |= B43legacy_IRQ_BEACON; - return; - } - - if (unlikely(wl->beacon_templates_virgin)) { - /* We never uploaded a beacon before. - * Upload both templates now, but only mark one valid. */ - wl->beacon_templates_virgin = 0; - b43legacy_upload_beacon0(dev); - b43legacy_upload_beacon1(dev); - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - cmd |= B43legacy_MACCMD_BEACON0_VALID; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); - } else { - if (!beacon0_valid) { - b43legacy_upload_beacon0(dev); - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - cmd |= B43legacy_MACCMD_BEACON0_VALID; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); - } else if (!beacon1_valid) { - b43legacy_upload_beacon1(dev); - cmd = b43legacy_read32(dev, B43legacy_MMIO_MACCMD); - cmd |= B43legacy_MACCMD_BEACON1_VALID; - b43legacy_write32(dev, B43legacy_MMIO_MACCMD, cmd); - } - } -} - -static void b43legacy_beacon_update_trigger_work(struct work_struct *work) -{ - struct b43legacy_wl *wl = container_of(work, struct b43legacy_wl, - beacon_update_trigger); - struct b43legacy_wldev *dev; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - if (likely(dev && (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED))) { - spin_lock_irq(&wl->irq_lock); - /* Update beacon right away or defer to IRQ. */ - handle_irq_beacon(dev); - /* The handler might have updated the IRQ mask. */ - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, - dev->irq_mask); - mmiowb(); - spin_unlock_irq(&wl->irq_lock); - } - mutex_unlock(&wl->mutex); -} - -/* Asynchronously update the packet templates in template RAM. - * Locking: Requires wl->irq_lock to be locked. */ -static void b43legacy_update_templates(struct b43legacy_wl *wl) -{ - struct sk_buff *beacon; - /* This is the top half of the ansynchronous beacon update. The bottom - * half is the beacon IRQ. Beacon update must be asynchronous to avoid - * sending an invalid beacon. This can happen for example, if the - * firmware transmits a beacon while we are updating it. */ - - /* We could modify the existing beacon and set the aid bit in the TIM - * field, but that would probably require resizing and moving of data - * within the beacon template. Simply request a new beacon and let - * mac80211 do the hard work. */ - beacon = ieee80211_beacon_get(wl->hw, wl->vif); - if (unlikely(!beacon)) - return; - - if (wl->current_beacon) - dev_kfree_skb_any(wl->current_beacon); - wl->current_beacon = beacon; - wl->beacon0_uploaded = 0; - wl->beacon1_uploaded = 0; - ieee80211_queue_work(wl->hw, &wl->beacon_update_trigger); -} - -static void b43legacy_set_beacon_int(struct b43legacy_wldev *dev, - u16 beacon_int) -{ - b43legacy_time_lock(dev); - if (dev->dev->id.revision >= 3) { - b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_REP, - (beacon_int << 16)); - b43legacy_write32(dev, B43legacy_MMIO_TSF_CFP_START, - (beacon_int << 10)); - } else { - b43legacy_write16(dev, 0x606, (beacon_int >> 6)); - b43legacy_write16(dev, 0x610, beacon_int); - } - b43legacy_time_unlock(dev); - b43legacydbg(dev->wl, "Set beacon interval to %u\n", beacon_int); -} - -static void handle_irq_ucode_debug(struct b43legacy_wldev *dev) -{ -} - -/* Interrupt handler bottom-half */ -static void b43legacy_interrupt_tasklet(struct b43legacy_wldev *dev) -{ - u32 reason; - u32 dma_reason[ARRAY_SIZE(dev->dma_reason)]; - u32 merged_dma_reason = 0; - int i; - unsigned long flags; - - spin_lock_irqsave(&dev->wl->irq_lock, flags); - - B43legacy_WARN_ON(b43legacy_status(dev) < - B43legacy_STAT_INITIALIZED); - - reason = dev->irq_reason; - for (i = 0; i < ARRAY_SIZE(dma_reason); i++) { - dma_reason[i] = dev->dma_reason[i]; - merged_dma_reason |= dma_reason[i]; - } - - if (unlikely(reason & B43legacy_IRQ_MAC_TXERR)) - b43legacyerr(dev->wl, "MAC transmission error\n"); - - if (unlikely(reason & B43legacy_IRQ_PHY_TXERR)) { - b43legacyerr(dev->wl, "PHY transmission error\n"); - rmb(); - if (unlikely(atomic_dec_and_test(&dev->phy.txerr_cnt))) { - b43legacyerr(dev->wl, "Too many PHY TX errors, " - "restarting the controller\n"); - b43legacy_controller_restart(dev, "PHY TX errors"); - } - } - - if (unlikely(merged_dma_reason & (B43legacy_DMAIRQ_FATALMASK | - B43legacy_DMAIRQ_NONFATALMASK))) { - if (merged_dma_reason & B43legacy_DMAIRQ_FATALMASK) { - b43legacyerr(dev->wl, "Fatal DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - b43legacy_controller_restart(dev, "DMA error"); - mmiowb(); - spin_unlock_irqrestore(&dev->wl->irq_lock, flags); - return; - } - if (merged_dma_reason & B43legacy_DMAIRQ_NONFATALMASK) - b43legacyerr(dev->wl, "DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - } - - if (unlikely(reason & B43legacy_IRQ_UCODE_DEBUG)) - handle_irq_ucode_debug(dev); - if (reason & B43legacy_IRQ_TBTT_INDI) - handle_irq_tbtt_indication(dev); - if (reason & B43legacy_IRQ_ATIM_END) - handle_irq_atim_end(dev); - if (reason & B43legacy_IRQ_BEACON) - handle_irq_beacon(dev); - if (reason & B43legacy_IRQ_PMQ) - handle_irq_pmq(dev); - if (reason & B43legacy_IRQ_TXFIFO_FLUSH_OK) - ;/*TODO*/ - if (reason & B43legacy_IRQ_NOISESAMPLE_OK) - handle_irq_noise(dev); - - /* Check the DMA reason registers for received data. */ - if (dma_reason[0] & B43legacy_DMAIRQ_RX_DONE) { - if (b43legacy_using_pio(dev)) - b43legacy_pio_rx(dev->pio.queue0); - else - b43legacy_dma_rx(dev->dma.rx_ring0); - } - B43legacy_WARN_ON(dma_reason[1] & B43legacy_DMAIRQ_RX_DONE); - B43legacy_WARN_ON(dma_reason[2] & B43legacy_DMAIRQ_RX_DONE); - if (dma_reason[3] & B43legacy_DMAIRQ_RX_DONE) { - if (b43legacy_using_pio(dev)) - b43legacy_pio_rx(dev->pio.queue3); - else - b43legacy_dma_rx(dev->dma.rx_ring3); - } - B43legacy_WARN_ON(dma_reason[4] & B43legacy_DMAIRQ_RX_DONE); - B43legacy_WARN_ON(dma_reason[5] & B43legacy_DMAIRQ_RX_DONE); - - if (reason & B43legacy_IRQ_TX_OK) - handle_irq_transmit_status(dev); - - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - mmiowb(); - spin_unlock_irqrestore(&dev->wl->irq_lock, flags); -} - -static void pio_irq_workaround(struct b43legacy_wldev *dev, - u16 base, int queueidx) -{ - u16 rxctl; - - rxctl = b43legacy_read16(dev, base + B43legacy_PIO_RXCTL); - if (rxctl & B43legacy_PIO_RXCTL_DATAAVAILABLE) - dev->dma_reason[queueidx] |= B43legacy_DMAIRQ_RX_DONE; - else - dev->dma_reason[queueidx] &= ~B43legacy_DMAIRQ_RX_DONE; -} - -static void b43legacy_interrupt_ack(struct b43legacy_wldev *dev, u32 reason) -{ - if (b43legacy_using_pio(dev) && - (dev->dev->id.revision < 3) && - (!(reason & B43legacy_IRQ_PIO_WORKAROUND))) { - /* Apply a PIO specific workaround to the dma_reasons */ - pio_irq_workaround(dev, B43legacy_MMIO_PIO1_BASE, 0); - pio_irq_workaround(dev, B43legacy_MMIO_PIO2_BASE, 1); - pio_irq_workaround(dev, B43legacy_MMIO_PIO3_BASE, 2); - pio_irq_workaround(dev, B43legacy_MMIO_PIO4_BASE, 3); - } - - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, reason); - - b43legacy_write32(dev, B43legacy_MMIO_DMA0_REASON, - dev->dma_reason[0]); - b43legacy_write32(dev, B43legacy_MMIO_DMA1_REASON, - dev->dma_reason[1]); - b43legacy_write32(dev, B43legacy_MMIO_DMA2_REASON, - dev->dma_reason[2]); - b43legacy_write32(dev, B43legacy_MMIO_DMA3_REASON, - dev->dma_reason[3]); - b43legacy_write32(dev, B43legacy_MMIO_DMA4_REASON, - dev->dma_reason[4]); - b43legacy_write32(dev, B43legacy_MMIO_DMA5_REASON, - dev->dma_reason[5]); -} - -/* Interrupt handler top-half */ -static irqreturn_t b43legacy_interrupt_handler(int irq, void *dev_id) -{ - irqreturn_t ret = IRQ_NONE; - struct b43legacy_wldev *dev = dev_id; - u32 reason; - - B43legacy_WARN_ON(!dev); - - spin_lock(&dev->wl->irq_lock); - - if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED)) - /* This can only happen on shared IRQ lines. */ - goto out; - reason = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); - if (reason == 0xffffffff) /* shared IRQ */ - goto out; - ret = IRQ_HANDLED; - reason &= dev->irq_mask; - if (!reason) - goto out; - - dev->dma_reason[0] = b43legacy_read32(dev, - B43legacy_MMIO_DMA0_REASON) - & 0x0001DC00; - dev->dma_reason[1] = b43legacy_read32(dev, - B43legacy_MMIO_DMA1_REASON) - & 0x0000DC00; - dev->dma_reason[2] = b43legacy_read32(dev, - B43legacy_MMIO_DMA2_REASON) - & 0x0000DC00; - dev->dma_reason[3] = b43legacy_read32(dev, - B43legacy_MMIO_DMA3_REASON) - & 0x0001DC00; - dev->dma_reason[4] = b43legacy_read32(dev, - B43legacy_MMIO_DMA4_REASON) - & 0x0000DC00; - dev->dma_reason[5] = b43legacy_read32(dev, - B43legacy_MMIO_DMA5_REASON) - & 0x0000DC00; - - b43legacy_interrupt_ack(dev, reason); - /* Disable all IRQs. They are enabled again in the bottom half. */ - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); - /* Save the reason code and call our bottom half. */ - dev->irq_reason = reason; - tasklet_schedule(&dev->isr_tasklet); -out: - mmiowb(); - spin_unlock(&dev->wl->irq_lock); - - return ret; -} - -static void b43legacy_release_firmware(struct b43legacy_wldev *dev) -{ - release_firmware(dev->fw.ucode); - dev->fw.ucode = NULL; - release_firmware(dev->fw.pcm); - dev->fw.pcm = NULL; - release_firmware(dev->fw.initvals); - dev->fw.initvals = NULL; - release_firmware(dev->fw.initvals_band); - dev->fw.initvals_band = NULL; -} - -static void b43legacy_print_fw_helptext(struct b43legacy_wl *wl) -{ - b43legacyerr(wl, "You must go to http://linuxwireless.org/en/users/" - "Drivers/b43#devicefirmware " - "and download the correct firmware (version 3).\n"); -} - -static int do_request_fw(struct b43legacy_wldev *dev, - const char *name, - const struct firmware **fw) -{ - char path[sizeof(modparam_fwpostfix) + 32]; - struct b43legacy_fw_header *hdr; - u32 size; - int err; - - if (!name) - return 0; - - snprintf(path, ARRAY_SIZE(path), - "b43legacy%s/%s.fw", - modparam_fwpostfix, name); - err = request_firmware(fw, path, dev->dev->dev); - if (err) { - b43legacyerr(dev->wl, "Firmware file \"%s\" not found " - "or load failed.\n", path); - return err; - } - if ((*fw)->size < sizeof(struct b43legacy_fw_header)) - goto err_format; - hdr = (struct b43legacy_fw_header *)((*fw)->data); - switch (hdr->type) { - case B43legacy_FW_TYPE_UCODE: - case B43legacy_FW_TYPE_PCM: - size = be32_to_cpu(hdr->size); - if (size != (*fw)->size - sizeof(struct b43legacy_fw_header)) - goto err_format; - /* fallthrough */ - case B43legacy_FW_TYPE_IV: - if (hdr->ver != 1) - goto err_format; - break; - default: - goto err_format; - } - - return err; - -err_format: - b43legacyerr(dev->wl, "Firmware file \"%s\" format error.\n", path); - return -EPROTO; -} - -static int b43legacy_request_firmware(struct b43legacy_wldev *dev) -{ - struct b43legacy_firmware *fw = &dev->fw; - const u8 rev = dev->dev->id.revision; - const char *filename; - u32 tmshigh; - int err; - - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); - if (!fw->ucode) { - if (rev == 2) - filename = "ucode2"; - else if (rev == 4) - filename = "ucode4"; - else - filename = "ucode5"; - err = do_request_fw(dev, filename, &fw->ucode); - if (err) - goto err_load; - } - if (!fw->pcm) { - if (rev < 5) - filename = "pcm4"; - else - filename = "pcm5"; - err = do_request_fw(dev, filename, &fw->pcm); - if (err) - goto err_load; - } - if (!fw->initvals) { - switch (dev->phy.type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - if ((rev >= 5) && (rev <= 10)) - filename = "b0g0initvals5"; - else if (rev == 2 || rev == 4) - filename = "b0g0initvals2"; - else - goto err_no_initvals; - break; - default: - goto err_no_initvals; - } - err = do_request_fw(dev, filename, &fw->initvals); - if (err) - goto err_load; - } - if (!fw->initvals_band) { - switch (dev->phy.type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - if ((rev >= 5) && (rev <= 10)) - filename = "b0g0bsinitvals5"; - else if (rev >= 11) - filename = NULL; - else if (rev == 2 || rev == 4) - filename = NULL; - else - goto err_no_initvals; - break; - default: - goto err_no_initvals; - } - err = do_request_fw(dev, filename, &fw->initvals_band); - if (err) - goto err_load; - } - - return 0; - -err_load: - b43legacy_print_fw_helptext(dev->wl); - goto error; - -err_no_initvals: - err = -ENODEV; - b43legacyerr(dev->wl, "No Initial Values firmware file for PHY %u, " - "core rev %u\n", dev->phy.type, rev); - goto error; - -error: - b43legacy_release_firmware(dev); - return err; -} - -static int b43legacy_upload_microcode(struct b43legacy_wldev *dev) -{ - const size_t hdr_len = sizeof(struct b43legacy_fw_header); - const __be32 *data; - unsigned int i; - unsigned int len; - u16 fwrev; - u16 fwpatch; - u16 fwdate; - u16 fwtime; - u32 tmp, macctl; - int err = 0; - - /* Jump the microcode PSM to offset 0 */ - macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - B43legacy_WARN_ON(macctl & B43legacy_MACCTL_PSM_RUN); - macctl |= B43legacy_MACCTL_PSM_JMP0; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); - /* Zero out all microcode PSM registers and shared memory. */ - for (i = 0; i < 64; i++) - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, i, 0); - for (i = 0; i < 4096; i += 2) - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, i, 0); - - /* Upload Microcode. */ - data = (__be32 *) (dev->fw.ucode->data + hdr_len); - len = (dev->fw.ucode->size - hdr_len) / sizeof(__be32); - b43legacy_shm_control_word(dev, - B43legacy_SHM_UCODE | - B43legacy_SHM_AUTOINC_W, - 0x0000); - for (i = 0; i < len; i++) { - b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, - be32_to_cpu(data[i])); - udelay(10); - } - - if (dev->fw.pcm) { - /* Upload PCM data. */ - data = (__be32 *) (dev->fw.pcm->data + hdr_len); - len = (dev->fw.pcm->size - hdr_len) / sizeof(__be32); - b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EA); - b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, 0x00004000); - /* No need for autoinc bit in SHM_HW */ - b43legacy_shm_control_word(dev, B43legacy_SHM_HW, 0x01EB); - for (i = 0; i < len; i++) { - b43legacy_write32(dev, B43legacy_MMIO_SHM_DATA, - be32_to_cpu(data[i])); - udelay(10); - } - } - - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, - B43legacy_IRQ_ALL); - - /* Start the microcode PSM */ - macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - macctl &= ~B43legacy_MACCTL_PSM_JMP0; - macctl |= B43legacy_MACCTL_PSM_RUN; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); - - /* Wait for the microcode to load and respond */ - i = 0; - while (1) { - tmp = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); - if (tmp == B43legacy_IRQ_MAC_SUSPENDED) - break; - i++; - if (i >= B43legacy_IRQWAIT_MAX_RETRIES) { - b43legacyerr(dev->wl, "Microcode not responding\n"); - b43legacy_print_fw_helptext(dev->wl); - err = -ENODEV; - goto error; - } - msleep_interruptible(50); - if (signal_pending(current)) { - err = -EINTR; - goto error; - } - } - /* dummy read follows */ - b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); - - /* Get and check the revisions. */ - fwrev = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_UCODEREV); - fwpatch = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_UCODEPATCH); - fwdate = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_UCODEDATE); - fwtime = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_UCODETIME); - - if (fwrev > 0x128) { - b43legacyerr(dev->wl, "YOU ARE TRYING TO LOAD V4 FIRMWARE." - " Only firmware from binary drivers version 3.x" - " is supported. You must change your firmware" - " files.\n"); - b43legacy_print_fw_helptext(dev->wl); - err = -EOPNOTSUPP; - goto error; - } - b43legacyinfo(dev->wl, "Loading firmware version 0x%X, patch level %u " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", fwrev, fwpatch, - (fwdate >> 12) & 0xF, (fwdate >> 8) & 0xF, fwdate & 0xFF, - (fwtime >> 11) & 0x1F, (fwtime >> 5) & 0x3F, - fwtime & 0x1F); - - dev->fw.rev = fwrev; - dev->fw.patch = fwpatch; - - return 0; - -error: - macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - macctl &= ~B43legacy_MACCTL_PSM_RUN; - macctl |= B43legacy_MACCTL_PSM_JMP0; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); - - return err; -} - -static int b43legacy_write_initvals(struct b43legacy_wldev *dev, - const struct b43legacy_iv *ivals, - size_t count, - size_t array_size) -{ - const struct b43legacy_iv *iv; - u16 offset; - size_t i; - bool bit32; - - BUILD_BUG_ON(sizeof(struct b43legacy_iv) != 6); - iv = ivals; - for (i = 0; i < count; i++) { - if (array_size < sizeof(iv->offset_size)) - goto err_format; - array_size -= sizeof(iv->offset_size); - offset = be16_to_cpu(iv->offset_size); - bit32 = !!(offset & B43legacy_IV_32BIT); - offset &= B43legacy_IV_OFFSET_MASK; - if (offset >= 0x1000) - goto err_format; - if (bit32) { - u32 value; - - if (array_size < sizeof(iv->data.d32)) - goto err_format; - array_size -= sizeof(iv->data.d32); - - value = get_unaligned_be32(&iv->data.d32); - b43legacy_write32(dev, offset, value); - - iv = (const struct b43legacy_iv *)((const uint8_t *)iv + - sizeof(__be16) + - sizeof(__be32)); - } else { - u16 value; - - if (array_size < sizeof(iv->data.d16)) - goto err_format; - array_size -= sizeof(iv->data.d16); - - value = be16_to_cpu(iv->data.d16); - b43legacy_write16(dev, offset, value); - - iv = (const struct b43legacy_iv *)((const uint8_t *)iv + - sizeof(__be16) + - sizeof(__be16)); - } - } - if (array_size) - goto err_format; - - return 0; - -err_format: - b43legacyerr(dev->wl, "Initial Values Firmware file-format error.\n"); - b43legacy_print_fw_helptext(dev->wl); - - return -EPROTO; -} - -static int b43legacy_upload_initvals(struct b43legacy_wldev *dev) -{ - const size_t hdr_len = sizeof(struct b43legacy_fw_header); - const struct b43legacy_fw_header *hdr; - struct b43legacy_firmware *fw = &dev->fw; - const struct b43legacy_iv *ivals; - size_t count; - int err; - - hdr = (const struct b43legacy_fw_header *)(fw->initvals->data); - ivals = (const struct b43legacy_iv *)(fw->initvals->data + hdr_len); - count = be32_to_cpu(hdr->size); - err = b43legacy_write_initvals(dev, ivals, count, - fw->initvals->size - hdr_len); - if (err) - goto out; - if (fw->initvals_band) { - hdr = (const struct b43legacy_fw_header *) - (fw->initvals_band->data); - ivals = (const struct b43legacy_iv *)(fw->initvals_band->data - + hdr_len); - count = be32_to_cpu(hdr->size); - err = b43legacy_write_initvals(dev, ivals, count, - fw->initvals_band->size - hdr_len); - if (err) - goto out; - } -out: - - return err; -} - -/* Initialize the GPIOs - * http://bcm-specs.sipsolutions.net/GPIO - */ -static int b43legacy_gpio_init(struct b43legacy_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; - u32 mask; - u32 set; - - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, - b43legacy_read32(dev, - B43legacy_MMIO_MACCTL) - & 0xFFFF3FFF); - - b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK, - b43legacy_read16(dev, - B43legacy_MMIO_GPIO_MASK) - | 0x000F); - - mask = 0x0000001F; - set = 0x0000000F; - if (dev->dev->bus->chip_id == 0x4301) { - mask |= 0x0060; - set |= 0x0060; - } - if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) { - b43legacy_write16(dev, B43legacy_MMIO_GPIO_MASK, - b43legacy_read16(dev, - B43legacy_MMIO_GPIO_MASK) - | 0x0200); - mask |= 0x0200; - set |= 0x0200; - } - if (dev->dev->id.revision >= 2) - mask |= 0x0010; /* FIXME: This is redundant. */ - -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return 0; - ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, - (ssb_read32(gpiodev, B43legacy_GPIO_CONTROL) - & mask) | set); - - return 0; -} - -/* Turn off all GPIO stuff. Call this on module unload, for example. */ -static void b43legacy_gpio_cleanup(struct b43legacy_wldev *dev) -{ - struct ssb_bus *bus = dev->dev->bus; - struct ssb_device *gpiodev, *pcidev = NULL; - -#ifdef CONFIG_SSB_DRIVER_PCICORE - pcidev = bus->pcicore.dev; -#endif - gpiodev = bus->chipco.dev ? : pcidev; - if (!gpiodev) - return; - ssb_write32(gpiodev, B43legacy_GPIO_CONTROL, 0); -} - -/* http://bcm-specs.sipsolutions.net/EnableMac */ -void b43legacy_mac_enable(struct b43legacy_wldev *dev) -{ - dev->mac_suspended--; - B43legacy_WARN_ON(dev->mac_suspended < 0); - B43legacy_WARN_ON(irqs_disabled()); - if (dev->mac_suspended == 0) { - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, - b43legacy_read32(dev, - B43legacy_MMIO_MACCTL) - | B43legacy_MACCTL_ENABLED); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, - B43legacy_IRQ_MAC_SUSPENDED); - /* the next two are dummy reads */ - b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); - b43legacy_power_saving_ctl_bits(dev, -1, -1); - - /* Re-enable IRQs. */ - spin_lock_irq(&dev->wl->irq_lock); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, - dev->irq_mask); - spin_unlock_irq(&dev->wl->irq_lock); - } -} - -/* http://bcm-specs.sipsolutions.net/SuspendMAC */ -void b43legacy_mac_suspend(struct b43legacy_wldev *dev) -{ - int i; - u32 tmp; - - might_sleep(); - B43legacy_WARN_ON(irqs_disabled()); - B43legacy_WARN_ON(dev->mac_suspended < 0); - - if (dev->mac_suspended == 0) { - /* Mask IRQs before suspending MAC. Otherwise - * the MAC stays busy and won't suspend. */ - spin_lock_irq(&dev->wl->irq_lock); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); - spin_unlock_irq(&dev->wl->irq_lock); - b43legacy_synchronize_irq(dev); - - b43legacy_power_saving_ctl_bits(dev, -1, 1); - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, - b43legacy_read32(dev, - B43legacy_MMIO_MACCTL) - & ~B43legacy_MACCTL_ENABLED); - b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); - for (i = 40; i; i--) { - tmp = b43legacy_read32(dev, - B43legacy_MMIO_GEN_IRQ_REASON); - if (tmp & B43legacy_IRQ_MAC_SUSPENDED) - goto out; - msleep(1); - } - b43legacyerr(dev->wl, "MAC suspend failed\n"); - } -out: - dev->mac_suspended++; -} - -static void b43legacy_adjust_opmode(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - u32 ctl; - u16 cfp_pretbtt; - - ctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - /* Reset status to STA infrastructure mode. */ - ctl &= ~B43legacy_MACCTL_AP; - ctl &= ~B43legacy_MACCTL_KEEP_CTL; - ctl &= ~B43legacy_MACCTL_KEEP_BADPLCP; - ctl &= ~B43legacy_MACCTL_KEEP_BAD; - ctl &= ~B43legacy_MACCTL_PROMISC; - ctl &= ~B43legacy_MACCTL_BEACPROMISC; - ctl |= B43legacy_MACCTL_INFRA; - - if (b43legacy_is_mode(wl, NL80211_IFTYPE_AP)) - ctl |= B43legacy_MACCTL_AP; - else if (b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC)) - ctl &= ~B43legacy_MACCTL_INFRA; - - if (wl->filter_flags & FIF_CONTROL) - ctl |= B43legacy_MACCTL_KEEP_CTL; - if (wl->filter_flags & FIF_FCSFAIL) - ctl |= B43legacy_MACCTL_KEEP_BAD; - if (wl->filter_flags & FIF_PLCPFAIL) - ctl |= B43legacy_MACCTL_KEEP_BADPLCP; - if (wl->filter_flags & FIF_PROMISC_IN_BSS) - ctl |= B43legacy_MACCTL_PROMISC; - if (wl->filter_flags & FIF_BCN_PRBRESP_PROMISC) - ctl |= B43legacy_MACCTL_BEACPROMISC; - - /* Workaround: On old hardware the HW-MAC-address-filter - * doesn't work properly, so always run promisc in filter - * it in software. */ - if (dev->dev->id.revision <= 4) - ctl |= B43legacy_MACCTL_PROMISC; - - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, ctl); - - cfp_pretbtt = 2; - if ((ctl & B43legacy_MACCTL_INFRA) && - !(ctl & B43legacy_MACCTL_AP)) { - if (dev->dev->bus->chip_id == 0x4306 && - dev->dev->bus->chip_rev == 3) - cfp_pretbtt = 100; - else - cfp_pretbtt = 50; - } - b43legacy_write16(dev, 0x612, cfp_pretbtt); -} - -static void b43legacy_rate_memory_write(struct b43legacy_wldev *dev, - u16 rate, - int is_ofdm) -{ - u16 offset; - - if (is_ofdm) { - offset = 0x480; - offset += (b43legacy_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; - } else { - offset = 0x4C0; - offset += (b43legacy_plcp_get_ratecode_cck(rate) & 0x000F) * 2; - } - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, offset + 0x20, - b43legacy_shm_read16(dev, - B43legacy_SHM_SHARED, offset)); -} - -static void b43legacy_rate_memory_init(struct b43legacy_wldev *dev) -{ - switch (dev->phy.type) { - case B43legacy_PHYTYPE_G: - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_6MB, 1); - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_12MB, 1); - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_18MB, 1); - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_24MB, 1); - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_36MB, 1); - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_48MB, 1); - b43legacy_rate_memory_write(dev, B43legacy_OFDM_RATE_54MB, 1); - /* fallthrough */ - case B43legacy_PHYTYPE_B: - b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_1MB, 0); - b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_2MB, 0); - b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_5MB, 0); - b43legacy_rate_memory_write(dev, B43legacy_CCK_RATE_11MB, 0); - break; - default: - B43legacy_BUG_ON(1); - } -} - -/* Set the TX-Antenna for management frames sent by firmware. */ -static void b43legacy_mgmtframe_txantenna(struct b43legacy_wldev *dev, - int antenna) -{ - u16 ant = 0; - u16 tmp; - - switch (antenna) { - case B43legacy_ANTENNA0: - ant |= B43legacy_TX4_PHY_ANT0; - break; - case B43legacy_ANTENNA1: - ant |= B43legacy_TX4_PHY_ANT1; - break; - case B43legacy_ANTENNA_AUTO: - ant |= B43legacy_TX4_PHY_ANTLAST; - break; - default: - B43legacy_BUG_ON(1); - } - - /* FIXME We also need to set the other flags of the PHY control - * field somewhere. */ - - /* For Beacons */ - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_BEACPHYCTL); - tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_BEACPHYCTL, tmp); - /* For ACK/CTS */ - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_ACKCTSPHYCTL); - tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_ACKCTSPHYCTL, tmp); - /* For Probe Resposes */ - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_PRPHYCTL); - tmp = (tmp & ~B43legacy_TX4_PHY_ANT) | ant; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_PRPHYCTL, tmp); -} - -/* This is the opposite of b43legacy_chip_init() */ -static void b43legacy_chip_exit(struct b43legacy_wldev *dev) -{ - b43legacy_radio_turn_off(dev, 1); - b43legacy_gpio_cleanup(dev); - /* firmware is released later */ -} - -/* Initialize the chip - * http://bcm-specs.sipsolutions.net/ChipInit - */ -static int b43legacy_chip_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - int err; - int tmp; - u32 value32, macctl; - u16 value16; - - /* Initialize the MAC control */ - macctl = B43legacy_MACCTL_IHR_ENABLED | B43legacy_MACCTL_SHM_ENABLED; - if (dev->phy.gmode) - macctl |= B43legacy_MACCTL_GMODE; - macctl |= B43legacy_MACCTL_INFRA; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); - - err = b43legacy_request_firmware(dev); - if (err) - goto out; - err = b43legacy_upload_microcode(dev); - if (err) - goto out; /* firmware is released later */ - - err = b43legacy_gpio_init(dev); - if (err) - goto out; /* firmware is released later */ - - err = b43legacy_upload_initvals(dev); - if (err) - goto err_gpio_clean; - b43legacy_radio_turn_on(dev); - - b43legacy_write16(dev, 0x03E6, 0x0000); - err = b43legacy_phy_init(dev); - if (err) - goto err_radio_off; - - /* Select initial Interference Mitigation. */ - tmp = phy->interfmode; - phy->interfmode = B43legacy_INTERFMODE_NONE; - b43legacy_radio_set_interference_mitigation(dev, tmp); - - b43legacy_phy_set_antenna_diversity(dev); - b43legacy_mgmtframe_txantenna(dev, B43legacy_ANTENNA_DEFAULT); - - if (phy->type == B43legacy_PHYTYPE_B) { - value16 = b43legacy_read16(dev, 0x005E); - value16 |= 0x0004; - b43legacy_write16(dev, 0x005E, value16); - } - b43legacy_write32(dev, 0x0100, 0x01000000); - if (dev->dev->id.revision < 5) - b43legacy_write32(dev, 0x010C, 0x01000000); - - value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - value32 &= ~B43legacy_MACCTL_INFRA; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32); - value32 = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - value32 |= B43legacy_MACCTL_INFRA; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value32); - - if (b43legacy_using_pio(dev)) { - b43legacy_write32(dev, 0x0210, 0x00000100); - b43legacy_write32(dev, 0x0230, 0x00000100); - b43legacy_write32(dev, 0x0250, 0x00000100); - b43legacy_write32(dev, 0x0270, 0x00000100); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0034, - 0x0000); - } - - /* Probe Response Timeout value */ - /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0074, 0x0000); - - /* Initially set the wireless operation mode. */ - b43legacy_adjust_opmode(dev); - - if (dev->dev->id.revision < 3) { - b43legacy_write16(dev, 0x060E, 0x0000); - b43legacy_write16(dev, 0x0610, 0x8000); - b43legacy_write16(dev, 0x0604, 0x0000); - b43legacy_write16(dev, 0x0606, 0x0200); - } else { - b43legacy_write32(dev, 0x0188, 0x80000000); - b43legacy_write32(dev, 0x018C, 0x02000000); - } - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_REASON, 0x00004000); - b43legacy_write32(dev, B43legacy_MMIO_DMA0_IRQ_MASK, 0x0001DC00); - b43legacy_write32(dev, B43legacy_MMIO_DMA1_IRQ_MASK, 0x0000DC00); - b43legacy_write32(dev, B43legacy_MMIO_DMA2_IRQ_MASK, 0x0000DC00); - b43legacy_write32(dev, B43legacy_MMIO_DMA3_IRQ_MASK, 0x0001DC00); - b43legacy_write32(dev, B43legacy_MMIO_DMA4_IRQ_MASK, 0x0000DC00); - b43legacy_write32(dev, B43legacy_MMIO_DMA5_IRQ_MASK, 0x0000DC00); - - value32 = ssb_read32(dev->dev, SSB_TMSLOW); - value32 |= 0x00100000; - ssb_write32(dev->dev, SSB_TMSLOW, value32); - - b43legacy_write16(dev, B43legacy_MMIO_POWERUP_DELAY, - dev->dev->bus->chipco.fast_pwrup_delay); - - /* PHY TX errors counter. */ - atomic_set(&phy->txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT); - - B43legacy_WARN_ON(err != 0); - b43legacydbg(dev->wl, "Chip initialized\n"); -out: - return err; - -err_radio_off: - b43legacy_radio_turn_off(dev, 1); -err_gpio_clean: - b43legacy_gpio_cleanup(dev); - goto out; -} - -static void b43legacy_periodic_every120sec(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - - if (phy->type != B43legacy_PHYTYPE_G || phy->rev < 2) - return; - - b43legacy_mac_suspend(dev); - b43legacy_phy_lo_g_measure(dev); - b43legacy_mac_enable(dev); -} - -static void b43legacy_periodic_every60sec(struct b43legacy_wldev *dev) -{ - b43legacy_phy_lo_mark_all_unused(dev); - if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) { - b43legacy_mac_suspend(dev); - b43legacy_calc_nrssi_slope(dev); - b43legacy_mac_enable(dev); - } -} - -static void b43legacy_periodic_every30sec(struct b43legacy_wldev *dev) -{ - /* Update device statistics. */ - b43legacy_calculate_link_quality(dev); -} - -static void b43legacy_periodic_every15sec(struct b43legacy_wldev *dev) -{ - b43legacy_phy_xmitpower(dev); /* FIXME: unless scanning? */ - - atomic_set(&dev->phy.txerr_cnt, B43legacy_PHY_TX_BADNESS_LIMIT); - wmb(); -} - -static void do_periodic_work(struct b43legacy_wldev *dev) -{ - unsigned int state; - - state = dev->periodic_state; - if (state % 8 == 0) - b43legacy_periodic_every120sec(dev); - if (state % 4 == 0) - b43legacy_periodic_every60sec(dev); - if (state % 2 == 0) - b43legacy_periodic_every30sec(dev); - b43legacy_periodic_every15sec(dev); -} - -/* Periodic work locking policy: - * The whole periodic work handler is protected by - * wl->mutex. If another lock is needed somewhere in the - * pwork callchain, it's aquired in-place, where it's needed. - */ -static void b43legacy_periodic_work_handler(struct work_struct *work) -{ - struct b43legacy_wldev *dev = container_of(work, struct b43legacy_wldev, - periodic_work.work); - struct b43legacy_wl *wl = dev->wl; - unsigned long delay; - - mutex_lock(&wl->mutex); - - if (unlikely(b43legacy_status(dev) != B43legacy_STAT_STARTED)) - goto out; - if (b43legacy_debug(dev, B43legacy_DBG_PWORK_STOP)) - goto out_requeue; - - do_periodic_work(dev); - - dev->periodic_state++; -out_requeue: - if (b43legacy_debug(dev, B43legacy_DBG_PWORK_FAST)) - delay = msecs_to_jiffies(50); - else - delay = round_jiffies_relative(HZ * 15); - ieee80211_queue_delayed_work(wl->hw, &dev->periodic_work, delay); -out: - mutex_unlock(&wl->mutex); -} - -static void b43legacy_periodic_tasks_setup(struct b43legacy_wldev *dev) -{ - struct delayed_work *work = &dev->periodic_work; - - dev->periodic_state = 0; - INIT_DELAYED_WORK(work, b43legacy_periodic_work_handler); - ieee80211_queue_delayed_work(dev->wl->hw, work, 0); -} - -/* Validate access to the chip (SHM) */ -static int b43legacy_validate_chipaccess(struct b43legacy_wldev *dev) -{ - u32 value; - u32 shm_backup; - - shm_backup = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0); - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, 0xAA5555AA); - if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0) != - 0xAA5555AA) - goto error; - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, 0x55AAAA55); - if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 0) != - 0x55AAAA55) - goto error; - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 0, shm_backup); - - value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - if ((value | B43legacy_MACCTL_GMODE) != - (B43legacy_MACCTL_GMODE | B43legacy_MACCTL_IHR_ENABLED)) - goto error; - - value = b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_REASON); - if (value) - goto error; - - return 0; -error: - b43legacyerr(dev->wl, "Failed to validate the chipaccess\n"); - return -ENODEV; -} - -static void b43legacy_security_init(struct b43legacy_wldev *dev) -{ - dev->max_nr_keys = (dev->dev->id.revision >= 5) ? 58 : 20; - B43legacy_WARN_ON(dev->max_nr_keys > ARRAY_SIZE(dev->key)); - dev->ktp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - 0x0056); - /* KTP is a word address, but we address SHM bytewise. - * So multiply by two. - */ - dev->ktp *= 2; - if (dev->dev->id.revision >= 5) - /* Number of RCMTA address slots */ - b43legacy_write16(dev, B43legacy_MMIO_RCMTA_COUNT, - dev->max_nr_keys - 8); -} - -#ifdef CONFIG_B43LEGACY_HWRNG -static int b43legacy_rng_read(struct hwrng *rng, u32 *data) -{ - struct b43legacy_wl *wl = (struct b43legacy_wl *)rng->priv; - unsigned long flags; - - /* Don't take wl->mutex here, as it could deadlock with - * hwrng internal locking. It's not needed to take - * wl->mutex here, anyway. */ - - spin_lock_irqsave(&wl->irq_lock, flags); - *data = b43legacy_read16(wl->current_dev, B43legacy_MMIO_RNG); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - return (sizeof(u16)); -} -#endif - -static void b43legacy_rng_exit(struct b43legacy_wl *wl) -{ -#ifdef CONFIG_B43LEGACY_HWRNG - if (wl->rng_initialized) - hwrng_unregister(&wl->rng); -#endif -} - -static int b43legacy_rng_init(struct b43legacy_wl *wl) -{ - int err = 0; - -#ifdef CONFIG_B43LEGACY_HWRNG - snprintf(wl->rng_name, ARRAY_SIZE(wl->rng_name), - "%s_%s", KBUILD_MODNAME, wiphy_name(wl->hw->wiphy)); - wl->rng.name = wl->rng_name; - wl->rng.data_read = b43legacy_rng_read; - wl->rng.priv = (unsigned long)wl; - wl->rng_initialized = 1; - err = hwrng_register(&wl->rng); - if (err) { - wl->rng_initialized = 0; - b43legacyerr(wl, "Failed to register the random " - "number generator (%d)\n", err); - } - -#endif - return err; -} - -static int b43legacy_op_tx(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - int err = -ENODEV; - unsigned long flags; - - if (unlikely(!dev)) - goto out; - if (unlikely(b43legacy_status(dev) < B43legacy_STAT_STARTED)) - goto out; - /* DMA-TX is done without a global lock. */ - if (b43legacy_using_pio(dev)) { - spin_lock_irqsave(&wl->irq_lock, flags); - err = b43legacy_pio_tx(dev, skb); - spin_unlock_irqrestore(&wl->irq_lock, flags); - } else - err = b43legacy_dma_tx(dev, skb); -out: - if (unlikely(err)) { - /* Drop the packet. */ - dev_kfree_skb_any(skb); - } - return NETDEV_TX_OK; -} - -static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - return 0; -} - -static int b43legacy_op_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - unsigned long flags; - int err = -ENODEV; - - if (!dev) - goto out; - spin_lock_irqsave(&wl->irq_lock, flags); - if (likely(b43legacy_status(dev) >= B43legacy_STAT_STARTED)) { - if (b43legacy_using_pio(dev)) - b43legacy_pio_get_tx_stats(dev, stats); - else - b43legacy_dma_get_tx_stats(dev, stats); - err = 0; - } - spin_unlock_irqrestore(&wl->irq_lock, flags); -out: - return err; -} - -static int b43legacy_op_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - unsigned long flags; - - spin_lock_irqsave(&wl->irq_lock, flags); - memcpy(stats, &wl->ieee_stats, sizeof(*stats)); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - return 0; -} - -static const char *phymode_to_string(unsigned int phymode) -{ - switch (phymode) { - case B43legacy_PHYMODE_B: - return "B"; - case B43legacy_PHYMODE_G: - return "G"; - default: - B43legacy_BUG_ON(1); - } - return ""; -} - -static int find_wldev_for_phymode(struct b43legacy_wl *wl, - unsigned int phymode, - struct b43legacy_wldev **dev, - bool *gmode) -{ - struct b43legacy_wldev *d; - - list_for_each_entry(d, &wl->devlist, list) { - if (d->phy.possible_phymodes & phymode) { - /* Ok, this device supports the PHY-mode. - * Set the gmode bit. */ - *gmode = 1; - *dev = d; - - return 0; - } - } - - return -ESRCH; -} - -static void b43legacy_put_phy_into_reset(struct b43legacy_wldev *dev) -{ - struct ssb_device *sdev = dev->dev; - u32 tmslow; - - tmslow = ssb_read32(sdev, SSB_TMSLOW); - tmslow &= ~B43legacy_TMSLOW_GMODE; - tmslow |= B43legacy_TMSLOW_PHYRESET; - tmslow |= SSB_TMSLOW_FGC; - ssb_write32(sdev, SSB_TMSLOW, tmslow); - msleep(1); - - tmslow = ssb_read32(sdev, SSB_TMSLOW); - tmslow &= ~SSB_TMSLOW_FGC; - tmslow |= B43legacy_TMSLOW_PHYRESET; - ssb_write32(sdev, SSB_TMSLOW, tmslow); - msleep(1); -} - -/* Expects wl->mutex locked */ -static int b43legacy_switch_phymode(struct b43legacy_wl *wl, - unsigned int new_mode) -{ - struct b43legacy_wldev *uninitialized_var(up_dev); - struct b43legacy_wldev *down_dev; - int err; - bool gmode = 0; - int prev_status; - - err = find_wldev_for_phymode(wl, new_mode, &up_dev, &gmode); - if (err) { - b43legacyerr(wl, "Could not find a device for %s-PHY mode\n", - phymode_to_string(new_mode)); - return err; - } - if ((up_dev == wl->current_dev) && - (!!wl->current_dev->phy.gmode == !!gmode)) - /* This device is already running. */ - return 0; - b43legacydbg(wl, "Reconfiguring PHYmode to %s-PHY\n", - phymode_to_string(new_mode)); - down_dev = wl->current_dev; - - prev_status = b43legacy_status(down_dev); - /* Shutdown the currently running core. */ - if (prev_status >= B43legacy_STAT_STARTED) - b43legacy_wireless_core_stop(down_dev); - if (prev_status >= B43legacy_STAT_INITIALIZED) - b43legacy_wireless_core_exit(down_dev); - - if (down_dev != up_dev) - /* We switch to a different core, so we put PHY into - * RESET on the old core. */ - b43legacy_put_phy_into_reset(down_dev); - - /* Now start the new core. */ - up_dev->phy.gmode = gmode; - if (prev_status >= B43legacy_STAT_INITIALIZED) { - err = b43legacy_wireless_core_init(up_dev); - if (err) { - b43legacyerr(wl, "Fatal: Could not initialize device" - " for newly selected %s-PHY mode\n", - phymode_to_string(new_mode)); - goto init_failure; - } - } - if (prev_status >= B43legacy_STAT_STARTED) { - err = b43legacy_wireless_core_start(up_dev); - if (err) { - b43legacyerr(wl, "Fatal: Coult not start device for " - "newly selected %s-PHY mode\n", - phymode_to_string(new_mode)); - b43legacy_wireless_core_exit(up_dev); - goto init_failure; - } - } - B43legacy_WARN_ON(b43legacy_status(up_dev) != prev_status); - - b43legacy_shm_write32(up_dev, B43legacy_SHM_SHARED, 0x003E, 0); - - wl->current_dev = up_dev; - - return 0; -init_failure: - /* Whoops, failed to init the new core. No core is operating now. */ - wl->current_dev = NULL; - return err; -} - -/* Write the short and long frame retry limit values. */ -static void b43legacy_set_retry_limits(struct b43legacy_wldev *dev, - unsigned int short_retry, - unsigned int long_retry) -{ - /* The retry limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. */ - short_retry = min(short_retry, (unsigned int)0xF); - long_retry = min(long_retry, (unsigned int)0xF); - - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0006, short_retry); - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, 0x0007, long_retry); -} - -static int b43legacy_op_dev_config(struct ieee80211_hw *hw, - u32 changed) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev; - struct b43legacy_phy *phy; - struct ieee80211_conf *conf = &hw->conf; - unsigned long flags; - unsigned int new_phymode = 0xFFFF; - int antenna_tx; - int antenna_rx; - int err = 0; - - antenna_tx = B43legacy_ANTENNA_DEFAULT; - antenna_rx = B43legacy_ANTENNA_DEFAULT; - - mutex_lock(&wl->mutex); - dev = wl->current_dev; - phy = &dev->phy; - - if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - b43legacy_set_retry_limits(dev, - conf->short_frame_max_tx_count, - conf->long_frame_max_tx_count); - changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; - if (!changed) - goto out_unlock_mutex; - - /* Switch the PHY mode (if necessary). */ - switch (conf->channel->band) { - case IEEE80211_BAND_2GHZ: - if (phy->type == B43legacy_PHYTYPE_B) - new_phymode = B43legacy_PHYMODE_B; - else - new_phymode = B43legacy_PHYMODE_G; - break; - default: - B43legacy_WARN_ON(1); - } - err = b43legacy_switch_phymode(wl, new_phymode); - if (err) - goto out_unlock_mutex; - - /* Disable IRQs while reconfiguring the device. - * This makes it possible to drop the spinlock throughout - * the reconfiguration process. */ - spin_lock_irqsave(&wl->irq_lock, flags); - if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { - spin_unlock_irqrestore(&wl->irq_lock, flags); - goto out_unlock_mutex; - } - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43legacy_synchronize_irq(dev); - - /* Switch to the requested channel. - * The firmware takes care of races with the TX handler. */ - if (conf->channel->hw_value != phy->channel) - b43legacy_radio_selectchannel(dev, conf->channel->hw_value, 0); - - dev->wl->radiotap_enabled = !!(conf->flags & IEEE80211_CONF_RADIOTAP); - - /* Adjust the desired TX power level. */ - if (conf->power_level != 0) { - if (conf->power_level != phy->power_level) { - phy->power_level = conf->power_level; - b43legacy_phy_xmitpower(dev); - } - } - - /* Antennas for RX and management frame TX. */ - b43legacy_mgmtframe_txantenna(dev, antenna_tx); - - if (wl->radio_enabled != phy->radio_on) { - if (wl->radio_enabled) { - b43legacy_radio_turn_on(dev); - b43legacyinfo(dev->wl, "Radio turned on by software\n"); - if (!dev->radio_hw_enable) - b43legacyinfo(dev->wl, "The hardware RF-kill" - " button still turns the radio" - " physically off. Press the" - " button to turn it on.\n"); - } else { - b43legacy_radio_turn_off(dev, 0); - b43legacyinfo(dev->wl, "Radio turned off by" - " software\n"); - } - } - - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - mmiowb(); - spin_unlock_irqrestore(&wl->irq_lock, flags); -out_unlock_mutex: - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43legacy_update_basic_rates(struct b43legacy_wldev *dev, u32 brates) -{ - struct ieee80211_supported_band *sband = - dev->wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ]; - struct ieee80211_rate *rate; - int i; - u16 basic, direct, offset, basic_offset, rateptr; - - for (i = 0; i < sband->n_bitrates; i++) { - rate = &sband->bitrates[i]; - - if (b43legacy_is_cck_rate(rate->hw_value)) { - direct = B43legacy_SHM_SH_CCKDIRECT; - basic = B43legacy_SHM_SH_CCKBASIC; - offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value); - offset &= 0xF; - } else { - direct = B43legacy_SHM_SH_OFDMDIRECT; - basic = B43legacy_SHM_SH_OFDMBASIC; - offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value); - offset &= 0xF; - } - - rate = ieee80211_get_response_rate(sband, brates, rate->bitrate); - - if (b43legacy_is_cck_rate(rate->hw_value)) { - basic_offset = b43legacy_plcp_get_ratecode_cck(rate->hw_value); - basic_offset &= 0xF; - } else { - basic_offset = b43legacy_plcp_get_ratecode_ofdm(rate->hw_value); - basic_offset &= 0xF; - } - - /* - * Get the pointer that we need to point to - * from the direct map - */ - rateptr = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - direct + 2 * basic_offset); - /* and write it to the basic map */ - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - basic + 2 * offset, rateptr); - } -} - -static void b43legacy_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *conf, - u32 changed) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev; - struct b43legacy_phy *phy; - unsigned long flags; - - mutex_lock(&wl->mutex); - B43legacy_WARN_ON(wl->vif != vif); - - dev = wl->current_dev; - phy = &dev->phy; - - /* Disable IRQs while reconfiguring the device. - * This makes it possible to drop the spinlock throughout - * the reconfiguration process. */ - spin_lock_irqsave(&wl->irq_lock, flags); - if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { - spin_unlock_irqrestore(&wl->irq_lock, flags); - goto out_unlock_mutex; - } - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); - - if (changed & BSS_CHANGED_BSSID) { - b43legacy_synchronize_irq(dev); - - if (conf->bssid) - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - else - memset(wl->bssid, 0, ETH_ALEN); - } - - if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) { - if (changed & BSS_CHANGED_BEACON && - (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) || - b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))) - b43legacy_update_templates(wl); - - if (changed & BSS_CHANGED_BSSID) - b43legacy_write_mac_bssid_templates(dev); - } - spin_unlock_irqrestore(&wl->irq_lock, flags); - - b43legacy_mac_suspend(dev); - - if (changed & BSS_CHANGED_BEACON_INT && - (b43legacy_is_mode(wl, NL80211_IFTYPE_AP) || - b43legacy_is_mode(wl, NL80211_IFTYPE_ADHOC))) - b43legacy_set_beacon_int(dev, conf->beacon_int); - - if (changed & BSS_CHANGED_BASIC_RATES) - b43legacy_update_basic_rates(dev, conf->basic_rates); - - if (changed & BSS_CHANGED_ERP_SLOT) { - if (conf->use_short_slot) - b43legacy_short_slot_timing_enable(dev); - else - b43legacy_short_slot_timing_disable(dev); - } - - b43legacy_mac_enable(dev); - - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - /* XXX: why? */ - mmiowb(); - spin_unlock_irqrestore(&wl->irq_lock, flags); - out_unlock_mutex: - mutex_unlock(&wl->mutex); -} - -static void b43legacy_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed, - unsigned int *fflags,u64 multicast) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - unsigned long flags; - - if (!dev) { - *fflags = 0; - return; - } - - spin_lock_irqsave(&wl->irq_lock, flags); - *fflags &= FIF_PROMISC_IN_BSS | - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_BCN_PRBRESP_PROMISC; - - changed &= FIF_PROMISC_IN_BSS | - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_OTHER_BSS | - FIF_BCN_PRBRESP_PROMISC; - - wl->filter_flags = *fflags; - - if (changed && b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) - b43legacy_adjust_opmode(dev); - spin_unlock_irqrestore(&wl->irq_lock, flags); -} - -/* Locking: wl->mutex */ -static void b43legacy_wireless_core_stop(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - unsigned long flags; - - if (b43legacy_status(dev) < B43legacy_STAT_STARTED) - return; - - /* Disable and sync interrupts. We must do this before than - * setting the status to INITIALIZED, as the interrupt handler - * won't care about IRQs then. */ - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, 0); - b43legacy_read32(dev, B43legacy_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&wl->irq_lock, flags); - b43legacy_synchronize_irq(dev); - - b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); - - mutex_unlock(&wl->mutex); - /* Must unlock as it would otherwise deadlock. No races here. - * Cancel the possibly running self-rearming periodic work. */ - cancel_delayed_work_sync(&dev->periodic_work); - mutex_lock(&wl->mutex); - - ieee80211_stop_queues(wl->hw); /* FIXME this could cause a deadlock */ - - b43legacy_mac_suspend(dev); - free_irq(dev->dev->irq, dev); - b43legacydbg(wl, "Wireless interface stopped\n"); -} - -/* Locking: wl->mutex */ -static int b43legacy_wireless_core_start(struct b43legacy_wldev *dev) -{ - int err; - - B43legacy_WARN_ON(b43legacy_status(dev) != B43legacy_STAT_INITIALIZED); - - drain_txstatus_queue(dev); - err = request_irq(dev->dev->irq, b43legacy_interrupt_handler, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (err) { - b43legacyerr(dev->wl, "Cannot request IRQ-%d\n", - dev->dev->irq); - goto out; - } - /* We are ready to run. */ - ieee80211_wake_queues(dev->wl->hw); - b43legacy_set_status(dev, B43legacy_STAT_STARTED); - - /* Start data flow (TX/RX) */ - b43legacy_mac_enable(dev); - b43legacy_write32(dev, B43legacy_MMIO_GEN_IRQ_MASK, dev->irq_mask); - - /* Start maintenance work */ - b43legacy_periodic_tasks_setup(dev); - - b43legacydbg(dev->wl, "Wireless interface started\n"); -out: - return err; -} - -/* Get PHY and RADIO versioning numbers */ -static int b43legacy_phy_versioning(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u32 tmp; - u8 analog_type; - u8 phy_type; - u8 phy_rev; - u16 radio_manuf; - u16 radio_ver; - u16 radio_rev; - int unsupported = 0; - - /* Get PHY versioning */ - tmp = b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); - analog_type = (tmp & B43legacy_PHYVER_ANALOG) - >> B43legacy_PHYVER_ANALOG_SHIFT; - phy_type = (tmp & B43legacy_PHYVER_TYPE) >> B43legacy_PHYVER_TYPE_SHIFT; - phy_rev = (tmp & B43legacy_PHYVER_VERSION); - switch (phy_type) { - case B43legacy_PHYTYPE_B: - if (phy_rev != 2 && phy_rev != 4 - && phy_rev != 6 && phy_rev != 7) - unsupported = 1; - break; - case B43legacy_PHYTYPE_G: - if (phy_rev > 8) - unsupported = 1; - break; - default: - unsupported = 1; - }; - if (unsupported) { - b43legacyerr(dev->wl, "FOUND UNSUPPORTED PHY " - "(Analog %u, Type %u, Revision %u)\n", - analog_type, phy_type, phy_rev); - return -EOPNOTSUPP; - } - b43legacydbg(dev->wl, "Found PHY: Analog %u, Type %u, Revision %u\n", - analog_type, phy_type, phy_rev); - - - /* Get RADIO versioning */ - if (dev->dev->bus->chip_id == 0x4317) { - if (dev->dev->bus->chip_rev == 0) - tmp = 0x3205017F; - else if (dev->dev->bus->chip_rev == 1) - tmp = 0x4205017F; - else - tmp = 0x5205017F; - } else { - b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, - B43legacy_RADIOCTL_ID); - tmp = b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_HIGH); - tmp <<= 16; - b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, - B43legacy_RADIOCTL_ID); - tmp |= b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_LOW); - } - radio_manuf = (tmp & 0x00000FFF); - radio_ver = (tmp & 0x0FFFF000) >> 12; - radio_rev = (tmp & 0xF0000000) >> 28; - switch (phy_type) { - case B43legacy_PHYTYPE_B: - if ((radio_ver & 0xFFF0) != 0x2050) - unsupported = 1; - break; - case B43legacy_PHYTYPE_G: - if (radio_ver != 0x2050) - unsupported = 1; - break; - default: - B43legacy_BUG_ON(1); - } - if (unsupported) { - b43legacyerr(dev->wl, "FOUND UNSUPPORTED RADIO " - "(Manuf 0x%X, Version 0x%X, Revision %u)\n", - radio_manuf, radio_ver, radio_rev); - return -EOPNOTSUPP; - } - b43legacydbg(dev->wl, "Found Radio: Manuf 0x%X, Version 0x%X," - " Revision %u\n", radio_manuf, radio_ver, radio_rev); - - - phy->radio_manuf = radio_manuf; - phy->radio_ver = radio_ver; - phy->radio_rev = radio_rev; - - phy->analog = analog_type; - phy->type = phy_type; - phy->rev = phy_rev; - - return 0; -} - -static void setup_struct_phy_for_init(struct b43legacy_wldev *dev, - struct b43legacy_phy *phy) -{ - struct b43legacy_lopair *lo; - int i; - - memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); - memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); - - /* Assume the radio is enabled. If it's not enabled, the state will - * immediately get fixed on the first periodic work run. */ - dev->radio_hw_enable = 1; - - phy->savedpctlreg = 0xFFFF; - phy->aci_enable = 0; - phy->aci_wlan_automatic = 0; - phy->aci_hw_rssi = 0; - - lo = phy->_lo_pairs; - if (lo) - memset(lo, 0, sizeof(struct b43legacy_lopair) * - B43legacy_LO_COUNT); - phy->max_lb_gain = 0; - phy->trsw_rx_gain = 0; - - /* Set default attenuation values. */ - phy->bbatt = b43legacy_default_baseband_attenuation(dev); - phy->rfatt = b43legacy_default_radio_attenuation(dev); - phy->txctl1 = b43legacy_default_txctl1(dev); - phy->txpwr_offset = 0; - - /* NRSSI */ - phy->nrssislope = 0; - for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++) - phy->nrssi[i] = -1000; - for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++) - phy->nrssi_lt[i] = i; - - phy->lofcal = 0xFFFF; - phy->initval = 0xFFFF; - - phy->interfmode = B43legacy_INTERFMODE_NONE; - phy->channel = 0xFF; -} - -static void setup_struct_wldev_for_init(struct b43legacy_wldev *dev) -{ - /* Flags */ - dev->dfq_valid = 0; - - /* Stats */ - memset(&dev->stats, 0, sizeof(dev->stats)); - - setup_struct_phy_for_init(dev, &dev->phy); - - /* IRQ related flags */ - dev->irq_reason = 0; - memset(dev->dma_reason, 0, sizeof(dev->dma_reason)); - dev->irq_mask = B43legacy_IRQ_MASKTEMPLATE; - - dev->mac_suspended = 1; - - /* Noise calculation context */ - memset(&dev->noisecalc, 0, sizeof(dev->noisecalc)); -} - -static void b43legacy_imcfglo_timeouts_workaround(struct b43legacy_wldev *dev) -{ -#ifdef CONFIG_SSB_DRIVER_PCICORE - struct ssb_bus *bus = dev->dev->bus; - u32 tmp; - - if (bus->pcicore.dev && - bus->pcicore.dev->id.coreid == SSB_DEV_PCI && - bus->pcicore.dev->id.revision <= 5) { - /* IMCFGLO timeouts workaround. */ - tmp = ssb_read32(dev->dev, SSB_IMCFGLO); - switch (bus->bustype) { - case SSB_BUSTYPE_PCI: - case SSB_BUSTYPE_PCMCIA: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x32; - break; - case SSB_BUSTYPE_SSB: - tmp &= ~SSB_IMCFGLO_REQTO; - tmp &= ~SSB_IMCFGLO_SERTO; - tmp |= 0x53; - break; - default: - break; - } - ssb_write32(dev->dev, SSB_IMCFGLO, tmp); - } -#endif /* CONFIG_SSB_DRIVER_PCICORE */ -} - -static void b43legacy_set_synth_pu_delay(struct b43legacy_wldev *dev, - bool idle) { - u16 pu_delay = 1050; - - if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC) || idle) - pu_delay = 500; - if ((dev->phy.radio_ver == 0x2050) && (dev->phy.radio_rev == 8)) - pu_delay = max(pu_delay, (u16)2400); - - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_SPUWKUP, pu_delay); -} - -/* Set the TSF CFP pre-TargetBeaconTransmissionTime. */ -static void b43legacy_set_pretbtt(struct b43legacy_wldev *dev) -{ - u16 pretbtt; - - /* The time value is in microseconds. */ - if (b43legacy_is_mode(dev->wl, NL80211_IFTYPE_ADHOC)) - pretbtt = 2; - else - pretbtt = 250; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_PRETBTT, pretbtt); - b43legacy_write16(dev, B43legacy_MMIO_TSF_CFP_PRETBTT, pretbtt); -} - -/* Shutdown a wireless core */ -/* Locking: wl->mutex */ -static void b43legacy_wireless_core_exit(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u32 macctl; - - B43legacy_WARN_ON(b43legacy_status(dev) > B43legacy_STAT_INITIALIZED); - if (b43legacy_status(dev) != B43legacy_STAT_INITIALIZED) - return; - b43legacy_set_status(dev, B43legacy_STAT_UNINIT); - - /* Stop the microcode PSM. */ - macctl = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - macctl &= ~B43legacy_MACCTL_PSM_RUN; - macctl |= B43legacy_MACCTL_PSM_JMP0; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, macctl); - - b43legacy_leds_exit(dev); - b43legacy_rng_exit(dev->wl); - b43legacy_pio_free(dev); - b43legacy_dma_free(dev); - b43legacy_chip_exit(dev); - b43legacy_radio_turn_off(dev, 1); - b43legacy_switch_analog(dev, 0); - if (phy->dyn_tssi_tbl) - kfree(phy->tssi2dbm); - kfree(phy->lo_control); - phy->lo_control = NULL; - if (dev->wl->current_beacon) { - dev_kfree_skb_any(dev->wl->current_beacon); - dev->wl->current_beacon = NULL; - } - - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(dev->dev->bus); -} - -static void prepare_phy_data_for_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - int i; - - /* Set default attenuation values. */ - phy->bbatt = b43legacy_default_baseband_attenuation(dev); - phy->rfatt = b43legacy_default_radio_attenuation(dev); - phy->txctl1 = b43legacy_default_txctl1(dev); - phy->txctl2 = 0xFFFF; - phy->txpwr_offset = 0; - - /* NRSSI */ - phy->nrssislope = 0; - for (i = 0; i < ARRAY_SIZE(phy->nrssi); i++) - phy->nrssi[i] = -1000; - for (i = 0; i < ARRAY_SIZE(phy->nrssi_lt); i++) - phy->nrssi_lt[i] = i; - - phy->lofcal = 0xFFFF; - phy->initval = 0xFFFF; - - phy->aci_enable = 0; - phy->aci_wlan_automatic = 0; - phy->aci_hw_rssi = 0; - - phy->antenna_diversity = 0xFFFF; - memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); - memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); - - /* Flags */ - phy->calibrated = 0; - - if (phy->_lo_pairs) - memset(phy->_lo_pairs, 0, - sizeof(struct b43legacy_lopair) * B43legacy_LO_COUNT); - memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain)); -} - -/* Initialize a wireless core */ -static int b43legacy_wireless_core_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - struct ssb_bus *bus = dev->dev->bus; - struct b43legacy_phy *phy = &dev->phy; - struct ssb_sprom *sprom = &dev->dev->bus->sprom; - int err; - u32 hf; - u32 tmp; - - B43legacy_WARN_ON(b43legacy_status(dev) != B43legacy_STAT_UNINIT); - - err = ssb_bus_powerup(bus, 0); - if (err) - goto out; - if (!ssb_device_is_enabled(dev->dev)) { - tmp = phy->gmode ? B43legacy_TMSLOW_GMODE : 0; - b43legacy_wireless_core_reset(dev, tmp); - } - - if ((phy->type == B43legacy_PHYTYPE_B) || - (phy->type == B43legacy_PHYTYPE_G)) { - phy->_lo_pairs = kzalloc(sizeof(struct b43legacy_lopair) - * B43legacy_LO_COUNT, - GFP_KERNEL); - if (!phy->_lo_pairs) - return -ENOMEM; - } - setup_struct_wldev_for_init(dev); - - err = b43legacy_phy_init_tssi2dbm_table(dev); - if (err) - goto err_kfree_lo_control; - - /* Enable IRQ routing to this device. */ - ssb_pcicore_dev_irqvecs_enable(&bus->pcicore, dev->dev); - - b43legacy_imcfglo_timeouts_workaround(dev); - prepare_phy_data_for_init(dev); - b43legacy_phy_calibrate(dev); - err = b43legacy_chip_init(dev); - if (err) - goto err_kfree_tssitbl; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_WLCOREREV, - dev->dev->id.revision); - hf = b43legacy_hf_read(dev); - if (phy->type == B43legacy_PHYTYPE_G) { - hf |= B43legacy_HF_SYMW; - if (phy->rev == 1) - hf |= B43legacy_HF_GDCW; - if (sprom->boardflags_lo & B43legacy_BFL_PACTRL) - hf |= B43legacy_HF_OFDMPABOOST; - } else if (phy->type == B43legacy_PHYTYPE_B) { - hf |= B43legacy_HF_SYMW; - if (phy->rev >= 2 && phy->radio_ver == 0x2050) - hf &= ~B43legacy_HF_GDCW; - } - b43legacy_hf_write(dev, hf); - - b43legacy_set_retry_limits(dev, - B43legacy_DEFAULT_SHORT_RETRY_LIMIT, - B43legacy_DEFAULT_LONG_RETRY_LIMIT); - - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - 0x0044, 3); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - 0x0046, 2); - - /* Disable sending probe responses from firmware. - * Setting the MaxTime to one usec will always trigger - * a timeout, so we never send any probe resp. - * A timeout of zero is infinite. */ - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, - B43legacy_SHM_SH_PRMAXTIME, 1); - - b43legacy_rate_memory_init(dev); - - /* Minimum Contention Window */ - if (phy->type == B43legacy_PHYTYPE_B) - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, - 0x0003, 31); - else - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, - 0x0003, 15); - /* Maximum Contention Window */ - b43legacy_shm_write16(dev, B43legacy_SHM_WIRELESS, - 0x0004, 1023); - - do { - if (b43legacy_using_pio(dev)) - err = b43legacy_pio_init(dev); - else { - err = b43legacy_dma_init(dev); - if (!err) - b43legacy_qos_init(dev); - } - } while (err == -EAGAIN); - if (err) - goto err_chip_exit; - - b43legacy_set_synth_pu_delay(dev, 1); - - ssb_bus_powerup(bus, 1); /* Enable dynamic PCTL */ - b43legacy_upload_card_macaddress(dev); - b43legacy_security_init(dev); - b43legacy_rng_init(wl); - - ieee80211_wake_queues(dev->wl->hw); - b43legacy_set_status(dev, B43legacy_STAT_INITIALIZED); - - b43legacy_leds_init(dev); -out: - return err; - -err_chip_exit: - b43legacy_chip_exit(dev); -err_kfree_tssitbl: - if (phy->dyn_tssi_tbl) - kfree(phy->tssi2dbm); -err_kfree_lo_control: - kfree(phy->lo_control); - phy->lo_control = NULL; - ssb_bus_may_powerdown(bus); - B43legacy_WARN_ON(b43legacy_status(dev) != B43legacy_STAT_UNINIT); - return err; -} - -static int b43legacy_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev; - unsigned long flags; - int err = -EOPNOTSUPP; - - /* TODO: allow WDS/AP devices to coexist */ - - if (conf->type != NL80211_IFTYPE_AP && - conf->type != NL80211_IFTYPE_STATION && - conf->type != NL80211_IFTYPE_WDS && - conf->type != NL80211_IFTYPE_ADHOC) - return -EOPNOTSUPP; - - mutex_lock(&wl->mutex); - if (wl->operating) - goto out_mutex_unlock; - - b43legacydbg(wl, "Adding Interface type %d\n", conf->type); - - dev = wl->current_dev; - wl->operating = 1; - wl->vif = conf->vif; - wl->if_type = conf->type; - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); - - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_adjust_opmode(dev); - b43legacy_set_pretbtt(dev); - b43legacy_set_synth_pu_delay(dev, 0); - b43legacy_upload_card_macaddress(dev); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - err = 0; - out_mutex_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43legacy_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - unsigned long flags; - - b43legacydbg(wl, "Removing Interface type %d\n", conf->type); - - mutex_lock(&wl->mutex); - - B43legacy_WARN_ON(!wl->operating); - B43legacy_WARN_ON(wl->vif != conf->vif); - wl->vif = NULL; - - wl->operating = 0; - - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_adjust_opmode(dev); - memset(wl->mac_addr, 0, ETH_ALEN); - b43legacy_upload_card_macaddress(dev); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - mutex_unlock(&wl->mutex); -} - -static int b43legacy_op_start(struct ieee80211_hw *hw) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - int did_init = 0; - int err = 0; - - /* Kill all old instance specific information to make sure - * the card won't use it in the short timeframe between start - * and mac80211 reconfiguring it. */ - memset(wl->bssid, 0, ETH_ALEN); - memset(wl->mac_addr, 0, ETH_ALEN); - wl->filter_flags = 0; - wl->beacon0_uploaded = 0; - wl->beacon1_uploaded = 0; - wl->beacon_templates_virgin = 1; - wl->radio_enabled = 1; - - mutex_lock(&wl->mutex); - - if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) { - err = b43legacy_wireless_core_init(dev); - if (err) - goto out_mutex_unlock; - did_init = 1; - } - - if (b43legacy_status(dev) < B43legacy_STAT_STARTED) { - err = b43legacy_wireless_core_start(dev); - if (err) { - if (did_init) - b43legacy_wireless_core_exit(dev); - goto out_mutex_unlock; - } - } - - wiphy_rfkill_start_polling(hw->wiphy); - -out_mutex_unlock: - mutex_unlock(&wl->mutex); - - return err; -} - -static void b43legacy_op_stop(struct ieee80211_hw *hw) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - - cancel_work_sync(&(wl->beacon_update_trigger)); - - mutex_lock(&wl->mutex); - if (b43legacy_status(dev) >= B43legacy_STAT_STARTED) - b43legacy_wireless_core_stop(dev); - b43legacy_wireless_core_exit(dev); - wl->radio_enabled = 0; - mutex_unlock(&wl->mutex); -} - -static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, bool set) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - unsigned long flags; - - spin_lock_irqsave(&wl->irq_lock, flags); - b43legacy_update_templates(wl); - spin_unlock_irqrestore(&wl->irq_lock, flags); - - return 0; -} - -static const struct ieee80211_ops b43legacy_hw_ops = { - .tx = b43legacy_op_tx, - .conf_tx = b43legacy_op_conf_tx, - .add_interface = b43legacy_op_add_interface, - .remove_interface = b43legacy_op_remove_interface, - .config = b43legacy_op_dev_config, - .bss_info_changed = b43legacy_op_bss_info_changed, - .configure_filter = b43legacy_op_configure_filter, - .get_stats = b43legacy_op_get_stats, - .get_tx_stats = b43legacy_op_get_tx_stats, - .start = b43legacy_op_start, - .stop = b43legacy_op_stop, - .set_tim = b43legacy_op_beacon_set_tim, - .rfkill_poll = b43legacy_rfkill_poll, -}; - -/* Hard-reset the chip. Do not call this directly. - * Use b43legacy_controller_restart() - */ -static void b43legacy_chip_reset(struct work_struct *work) -{ - struct b43legacy_wldev *dev = - container_of(work, struct b43legacy_wldev, restart_work); - struct b43legacy_wl *wl = dev->wl; - int err = 0; - int prev_status; - - mutex_lock(&wl->mutex); - - prev_status = b43legacy_status(dev); - /* Bring the device down... */ - if (prev_status >= B43legacy_STAT_STARTED) - b43legacy_wireless_core_stop(dev); - if (prev_status >= B43legacy_STAT_INITIALIZED) - b43legacy_wireless_core_exit(dev); - - /* ...and up again. */ - if (prev_status >= B43legacy_STAT_INITIALIZED) { - err = b43legacy_wireless_core_init(dev); - if (err) - goto out; - } - if (prev_status >= B43legacy_STAT_STARTED) { - err = b43legacy_wireless_core_start(dev); - if (err) { - b43legacy_wireless_core_exit(dev); - goto out; - } - } -out: - if (err) - wl->current_dev = NULL; /* Failed to init the dev. */ - mutex_unlock(&wl->mutex); - if (err) - b43legacyerr(wl, "Controller restart FAILED\n"); - else - b43legacyinfo(wl, "Controller restarted\n"); -} - -static int b43legacy_setup_modes(struct b43legacy_wldev *dev, - int have_bphy, - int have_gphy) -{ - struct ieee80211_hw *hw = dev->wl->hw; - struct b43legacy_phy *phy = &dev->phy; - - phy->possible_phymodes = 0; - if (have_bphy) { - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &b43legacy_band_2GHz_BPHY; - phy->possible_phymodes |= B43legacy_PHYMODE_B; - } - - if (have_gphy) { - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &b43legacy_band_2GHz_GPHY; - phy->possible_phymodes |= B43legacy_PHYMODE_G; - } - - return 0; -} - -static void b43legacy_wireless_core_detach(struct b43legacy_wldev *dev) -{ - /* We release firmware that late to not be required to re-request - * is all the time when we reinit the core. */ - b43legacy_release_firmware(dev); -} - -static int b43legacy_wireless_core_attach(struct b43legacy_wldev *dev) -{ - struct b43legacy_wl *wl = dev->wl; - struct ssb_bus *bus = dev->dev->bus; - struct pci_dev *pdev = bus->host_pci; - int err; - int have_bphy = 0; - int have_gphy = 0; - u32 tmp; - - /* Do NOT do any device initialization here. - * Do it in wireless_core_init() instead. - * This function is for gathering basic information about the HW, only. - * Also some structs may be set up here. But most likely you want to - * have that in core_init(), too. - */ - - err = ssb_bus_powerup(bus, 0); - if (err) { - b43legacyerr(wl, "Bus powerup failed\n"); - goto out; - } - /* Get the PHY type. */ - if (dev->dev->id.revision >= 5) { - u32 tmshigh; - - tmshigh = ssb_read32(dev->dev, SSB_TMSHIGH); - have_gphy = !!(tmshigh & B43legacy_TMSHIGH_GPHY); - if (!have_gphy) - have_bphy = 1; - } else if (dev->dev->id.revision == 4) - have_gphy = 1; - else - have_bphy = 1; - - dev->phy.gmode = (have_gphy || have_bphy); - dev->phy.radio_on = 1; - tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; - b43legacy_wireless_core_reset(dev, tmp); - - err = b43legacy_phy_versioning(dev); - if (err) - goto err_powerdown; - /* Check if this device supports multiband. */ - if (!pdev || - (pdev->device != 0x4312 && - pdev->device != 0x4319 && - pdev->device != 0x4324)) { - /* No multiband support. */ - have_bphy = 0; - have_gphy = 0; - switch (dev->phy.type) { - case B43legacy_PHYTYPE_B: - have_bphy = 1; - break; - case B43legacy_PHYTYPE_G: - have_gphy = 1; - break; - default: - B43legacy_BUG_ON(1); - } - } - dev->phy.gmode = (have_gphy || have_bphy); - tmp = dev->phy.gmode ? B43legacy_TMSLOW_GMODE : 0; - b43legacy_wireless_core_reset(dev, tmp); - - err = b43legacy_validate_chipaccess(dev); - if (err) - goto err_powerdown; - err = b43legacy_setup_modes(dev, have_bphy, have_gphy); - if (err) - goto err_powerdown; - - /* Now set some default "current_dev" */ - if (!wl->current_dev) - wl->current_dev = dev; - INIT_WORK(&dev->restart_work, b43legacy_chip_reset); - - b43legacy_radio_turn_off(dev, 1); - b43legacy_switch_analog(dev, 0); - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(bus); - -out: - return err; - -err_powerdown: - ssb_bus_may_powerdown(bus); - return err; -} - -static void b43legacy_one_core_detach(struct ssb_device *dev) -{ - struct b43legacy_wldev *wldev; - struct b43legacy_wl *wl; - - /* Do not cancel ieee80211-workqueue based work here. - * See comment in b43legacy_remove(). */ - - wldev = ssb_get_drvdata(dev); - wl = wldev->wl; - b43legacy_debugfs_remove_device(wldev); - b43legacy_wireless_core_detach(wldev); - list_del(&wldev->list); - wl->nr_devs--; - ssb_set_drvdata(dev, NULL); - kfree(wldev); -} - -static int b43legacy_one_core_attach(struct ssb_device *dev, - struct b43legacy_wl *wl) -{ - struct b43legacy_wldev *wldev; - struct pci_dev *pdev; - int err = -ENOMEM; - - if (!list_empty(&wl->devlist)) { - /* We are not the first core on this chip. */ - pdev = dev->bus->host_pci; - /* Only special chips support more than one wireless - * core, although some of the other chips have more than - * one wireless core as well. Check for this and - * bail out early. - */ - if (!pdev || - ((pdev->device != 0x4321) && - (pdev->device != 0x4313) && - (pdev->device != 0x431A))) { - b43legacydbg(wl, "Ignoring unconnected 802.11 core\n"); - return -ENODEV; - } - } - - wldev = kzalloc(sizeof(*wldev), GFP_KERNEL); - if (!wldev) - goto out; - - wldev->dev = dev; - wldev->wl = wl; - b43legacy_set_status(wldev, B43legacy_STAT_UNINIT); - wldev->bad_frames_preempt = modparam_bad_frames_preempt; - tasklet_init(&wldev->isr_tasklet, - (void (*)(unsigned long))b43legacy_interrupt_tasklet, - (unsigned long)wldev); - if (modparam_pio) - wldev->__using_pio = 1; - INIT_LIST_HEAD(&wldev->list); - - err = b43legacy_wireless_core_attach(wldev); - if (err) - goto err_kfree_wldev; - - list_add(&wldev->list, &wl->devlist); - wl->nr_devs++; - ssb_set_drvdata(dev, wldev); - b43legacy_debugfs_add_device(wldev); -out: - return err; - -err_kfree_wldev: - kfree(wldev); - return err; -} - -static void b43legacy_sprom_fixup(struct ssb_bus *bus) -{ - /* boardflags workarounds */ - if (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE && - bus->boardinfo.type == 0x4E && - bus->boardinfo.rev > 0x40) - bus->sprom.boardflags_lo |= B43legacy_BFL_PACTRL; -} - -static void b43legacy_wireless_exit(struct ssb_device *dev, - struct b43legacy_wl *wl) -{ - struct ieee80211_hw *hw = wl->hw; - - ssb_set_devtypedata(dev, NULL); - ieee80211_free_hw(hw); -} - -static int b43legacy_wireless_init(struct ssb_device *dev) -{ - struct ssb_sprom *sprom = &dev->bus->sprom; - struct ieee80211_hw *hw; - struct b43legacy_wl *wl; - int err = -ENOMEM; - - b43legacy_sprom_fixup(dev->bus); - - hw = ieee80211_alloc_hw(sizeof(*wl), &b43legacy_hw_ops); - if (!hw) { - b43legacyerr(NULL, "Could not allocate ieee80211 device\n"); - goto out; - } - - /* fill hw info */ - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_WDS) | - BIT(NL80211_IFTYPE_ADHOC); - hw->queues = 1; /* FIXME: hardware has more queues */ - hw->max_rates = 2; - SET_IEEE80211_DEV(hw, dev->dev); - if (is_valid_ether_addr(sprom->et1mac)) - SET_IEEE80211_PERM_ADDR(hw, sprom->et1mac); - else - SET_IEEE80211_PERM_ADDR(hw, sprom->il0mac); - - /* Get and initialize struct b43legacy_wl */ - wl = hw_to_b43legacy_wl(hw); - memset(wl, 0, sizeof(*wl)); - wl->hw = hw; - spin_lock_init(&wl->irq_lock); - spin_lock_init(&wl->leds_lock); - mutex_init(&wl->mutex); - INIT_LIST_HEAD(&wl->devlist); - INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); - - ssb_set_devtypedata(dev, wl); - b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); - err = 0; -out: - return err; -} - -static int b43legacy_probe(struct ssb_device *dev, - const struct ssb_device_id *id) -{ - struct b43legacy_wl *wl; - int err; - int first = 0; - - wl = ssb_get_devtypedata(dev); - if (!wl) { - /* Probing the first core - setup common struct b43legacy_wl */ - first = 1; - err = b43legacy_wireless_init(dev); - if (err) - goto out; - wl = ssb_get_devtypedata(dev); - B43legacy_WARN_ON(!wl); - } - err = b43legacy_one_core_attach(dev, wl); - if (err) - goto err_wireless_exit; - - if (first) { - err = ieee80211_register_hw(wl->hw); - if (err) - goto err_one_core_detach; - } - -out: - return err; - -err_one_core_detach: - b43legacy_one_core_detach(dev); -err_wireless_exit: - if (first) - b43legacy_wireless_exit(dev, wl); - return err; -} - -static void b43legacy_remove(struct ssb_device *dev) -{ - struct b43legacy_wl *wl = ssb_get_devtypedata(dev); - struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); - - /* We must cancel any work here before unregistering from ieee80211, - * as the ieee80211 unreg will destroy the workqueue. */ - cancel_work_sync(&wldev->restart_work); - - B43legacy_WARN_ON(!wl); - if (wl->current_dev == wldev) - ieee80211_unregister_hw(wl->hw); - - b43legacy_one_core_detach(dev); - - if (list_empty(&wl->devlist)) - /* Last core on the chip unregistered. - * We can destroy common struct b43legacy_wl. - */ - b43legacy_wireless_exit(dev, wl); -} - -/* Perform a hardware reset. This can be called from any context. */ -void b43legacy_controller_restart(struct b43legacy_wldev *dev, - const char *reason) -{ - /* Must avoid requeueing, if we are in shutdown. */ - if (b43legacy_status(dev) < B43legacy_STAT_INITIALIZED) - return; - b43legacyinfo(dev->wl, "Controller RESET (%s) ...\n", reason); - ieee80211_queue_work(dev->wl->hw, &dev->restart_work); -} - -#ifdef CONFIG_PM - -static int b43legacy_suspend(struct ssb_device *dev, pm_message_t state) -{ - struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); - struct b43legacy_wl *wl = wldev->wl; - - b43legacydbg(wl, "Suspending...\n"); - - mutex_lock(&wl->mutex); - wldev->suspend_init_status = b43legacy_status(wldev); - if (wldev->suspend_init_status >= B43legacy_STAT_STARTED) - b43legacy_wireless_core_stop(wldev); - if (wldev->suspend_init_status >= B43legacy_STAT_INITIALIZED) - b43legacy_wireless_core_exit(wldev); - mutex_unlock(&wl->mutex); - - b43legacydbg(wl, "Device suspended.\n"); - - return 0; -} - -static int b43legacy_resume(struct ssb_device *dev) -{ - struct b43legacy_wldev *wldev = ssb_get_drvdata(dev); - struct b43legacy_wl *wl = wldev->wl; - int err = 0; - - b43legacydbg(wl, "Resuming...\n"); - - mutex_lock(&wl->mutex); - if (wldev->suspend_init_status >= B43legacy_STAT_INITIALIZED) { - err = b43legacy_wireless_core_init(wldev); - if (err) { - b43legacyerr(wl, "Resume failed at core init\n"); - goto out; - } - } - if (wldev->suspend_init_status >= B43legacy_STAT_STARTED) { - err = b43legacy_wireless_core_start(wldev); - if (err) { - b43legacy_wireless_core_exit(wldev); - b43legacyerr(wl, "Resume failed at core start\n"); - goto out; - } - } - - b43legacydbg(wl, "Device resumed.\n"); -out: - mutex_unlock(&wl->mutex); - return err; -} - -#else /* CONFIG_PM */ -# define b43legacy_suspend NULL -# define b43legacy_resume NULL -#endif /* CONFIG_PM */ - -static struct ssb_driver b43legacy_ssb_driver = { - .name = KBUILD_MODNAME, - .id_table = b43legacy_ssb_tbl, - .probe = b43legacy_probe, - .remove = b43legacy_remove, - .suspend = b43legacy_suspend, - .resume = b43legacy_resume, -}; - -static void b43legacy_print_driverinfo(void) -{ - const char *feat_pci = "", *feat_leds = "", *feat_rfkill = "", - *feat_pio = "", *feat_dma = ""; - -#ifdef CONFIG_B43LEGACY_PCI_AUTOSELECT - feat_pci = "P"; -#endif -#ifdef CONFIG_B43LEGACY_LEDS - feat_leds = "L"; -#endif -#ifdef CONFIG_B43LEGACY_RFKILL - feat_rfkill = "R"; -#endif -#ifdef CONFIG_B43LEGACY_PIO - feat_pio = "I"; -#endif -#ifdef CONFIG_B43LEGACY_DMA - feat_dma = "D"; -#endif - printk(KERN_INFO "Broadcom 43xx-legacy driver loaded " - "[ Features: %s%s%s%s%s, Firmware-ID: " - B43legacy_SUPPORTED_FIRMWARE_ID " ]\n", - feat_pci, feat_leds, feat_rfkill, feat_pio, feat_dma); -} - -static int __init b43legacy_init(void) -{ - int err; - - b43legacy_debugfs_init(); - - err = ssb_driver_register(&b43legacy_ssb_driver); - if (err) - goto err_dfs_exit; - - b43legacy_print_driverinfo(); - - return err; - -err_dfs_exit: - b43legacy_debugfs_exit(); - return err; -} - -static void __exit b43legacy_exit(void) -{ - ssb_driver_unregister(&b43legacy_ssb_driver); - b43legacy_debugfs_exit(); -} - -module_init(b43legacy_init) -module_exit(b43legacy_exit) diff --git a/drivers/net/wireless/b43legacy/main.h b/drivers/net/wireless/b43legacy/main.h deleted file mode 100644 index 1f0e2e379b02..000000000000 --- a/drivers/net/wireless/b43legacy/main.h +++ /dev/null @@ -1,127 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Copyright (c) 2005 Martin Langer , - Copyright (c) 2005 Stefano Brivio - Copyright (c) 2005, 2006 Michael Buesch - Copyright (c) 2005 Danny van Dyk - Copyright (c) 2005 Andreas Jaggi - Copyright (c) 2007 Larry Finger - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef B43legacy_MAIN_H_ -#define B43legacy_MAIN_H_ - -#include "b43legacy.h" - - -#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] -#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) -/* Magic helper macro to pad structures. Ignore those above. It's magic. */ -#define PAD_BYTES(nr_bytes) P4D_BYTES(__LINE__ , (nr_bytes)) - - -/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ -static inline -u8 b43legacy_freq_to_channel_bg(int freq) -{ - u8 channel; - - if (freq == 2484) - channel = 14; - else - channel = (freq - 2407) / 5; - - return channel; -} -static inline -u8 b43legacy_freq_to_channel(struct b43legacy_wldev *dev, - int freq) -{ - return b43legacy_freq_to_channel_bg(freq); -} - -/* Lightweight function to convert a channel number to a frequency (in Mhz). */ -static inline -int b43legacy_channel_to_freq_bg(u8 channel) -{ - int freq; - - if (channel == 14) - freq = 2484; - else - freq = 2407 + (5 * channel); - - return freq; -} - -static inline -int b43legacy_channel_to_freq(struct b43legacy_wldev *dev, - u8 channel) -{ - return b43legacy_channel_to_freq_bg(channel); -} - -static inline -int b43legacy_is_cck_rate(int rate) -{ - return (rate == B43legacy_CCK_RATE_1MB || - rate == B43legacy_CCK_RATE_2MB || - rate == B43legacy_CCK_RATE_5MB || - rate == B43legacy_CCK_RATE_11MB); -} - -static inline -int b43legacy_is_ofdm_rate(int rate) -{ - return !b43legacy_is_cck_rate(rate); -} - -void b43legacy_tsf_read(struct b43legacy_wldev *dev, u64 *tsf); -void b43legacy_tsf_write(struct b43legacy_wldev *dev, u64 tsf); - -u32 b43legacy_shm_read32(struct b43legacy_wldev *dev, - u16 routing, u16 offset); -u16 b43legacy_shm_read16(struct b43legacy_wldev *dev, - u16 routing, u16 offset); -void b43legacy_shm_write32(struct b43legacy_wldev *dev, - u16 routing, u16 offset, - u32 value); -void b43legacy_shm_write16(struct b43legacy_wldev *dev, - u16 routing, u16 offset, - u16 value); - -u32 b43legacy_hf_read(struct b43legacy_wldev *dev); -void b43legacy_hf_write(struct b43legacy_wldev *dev, u32 value); - -void b43legacy_dummy_transmission(struct b43legacy_wldev *dev); - -void b43legacy_wireless_core_reset(struct b43legacy_wldev *dev, u32 flags); - -void b43legacy_mac_suspend(struct b43legacy_wldev *dev); -void b43legacy_mac_enable(struct b43legacy_wldev *dev); - -void b43legacy_controller_restart(struct b43legacy_wldev *dev, - const char *reason); - -#endif /* B43legacy_MAIN_H_ */ diff --git a/drivers/net/wireless/b43legacy/phy.c b/drivers/net/wireless/b43legacy/phy.c deleted file mode 100644 index aaf227203a98..000000000000 --- a/drivers/net/wireless/b43legacy/phy.c +++ /dev/null @@ -1,2257 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - Copyright (c) 2007 Larry Finger - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include - -#include "b43legacy.h" -#include "phy.h" -#include "main.h" -#include "radio.h" -#include "ilt.h" - - -static const s8 b43legacy_tssi2dbm_b_table[] = { - 0x4D, 0x4C, 0x4B, 0x4A, - 0x4A, 0x49, 0x48, 0x47, - 0x47, 0x46, 0x45, 0x45, - 0x44, 0x43, 0x42, 0x42, - 0x41, 0x40, 0x3F, 0x3E, - 0x3D, 0x3C, 0x3B, 0x3A, - 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x32, 0x31, - 0x30, 0x2F, 0x2D, 0x2C, - 0x2B, 0x29, 0x28, 0x26, - 0x25, 0x23, 0x21, 0x1F, - 0x1D, 0x1A, 0x17, 0x14, - 0x10, 0x0C, 0x06, 0x00, - -7, -7, -7, -7, - -7, -7, -7, -7, - -7, -7, -7, -7, -}; - -static const s8 b43legacy_tssi2dbm_g_table[] = { - 77, 77, 77, 76, - 76, 76, 75, 75, - 74, 74, 73, 73, - 73, 72, 72, 71, - 71, 70, 70, 69, - 68, 68, 67, 67, - 66, 65, 65, 64, - 63, 63, 62, 61, - 60, 59, 58, 57, - 56, 55, 54, 53, - 52, 50, 49, 47, - 45, 43, 40, 37, - 33, 28, 22, 14, - 5, -7, -20, -20, - -20, -20, -20, -20, - -20, -20, -20, -20, -}; - -static void b43legacy_phy_initg(struct b43legacy_wldev *dev); - - -static inline -void b43legacy_voluntary_preempt(void) -{ - B43legacy_BUG_ON(!(!in_atomic() && !in_irq() && - !in_interrupt() && !irqs_disabled())); -#ifndef CONFIG_PREEMPT - cond_resched(); -#endif /* CONFIG_PREEMPT */ -} - -/* Lock the PHY registers against concurrent access from the microcode. - * This lock is nonrecursive. */ -void b43legacy_phy_lock(struct b43legacy_wldev *dev) -{ -#if B43legacy_DEBUG - B43legacy_WARN_ON(dev->phy.phy_locked); - dev->phy.phy_locked = 1; -#endif - - if (dev->dev->id.revision < 3) { - b43legacy_mac_suspend(dev); - } else { - if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) - b43legacy_power_saving_ctl_bits(dev, -1, 1); - } -} - -void b43legacy_phy_unlock(struct b43legacy_wldev *dev) -{ -#if B43legacy_DEBUG - B43legacy_WARN_ON(!dev->phy.phy_locked); - dev->phy.phy_locked = 0; -#endif - - if (dev->dev->id.revision < 3) { - b43legacy_mac_enable(dev); - } else { - if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) - b43legacy_power_saving_ctl_bits(dev, -1, -1); - } -} - -u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset) -{ - b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset); - return b43legacy_read16(dev, B43legacy_MMIO_PHY_DATA); -} - -void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val) -{ - b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_PHY_DATA, val); -} - -void b43legacy_phy_calibrate(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - - b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */ - if (phy->calibrated) - return; - if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) { - b43legacy_wireless_core_reset(dev, 0); - b43legacy_phy_initg(dev); - b43legacy_wireless_core_reset(dev, B43legacy_TMSLOW_GMODE); - } - phy->calibrated = 1; -} - -/* intialize B PHY power control - * as described in http://bcm-specs.sipsolutions.net/InitPowerControl - */ -static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 saved_batt = 0; - u16 saved_ratt = 0; - u16 saved_txctl1 = 0; - int must_reset_txpower = 0; - - B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B || - phy->type == B43legacy_PHYTYPE_G)); - if (is_bcm_board_vendor(dev) && - (dev->dev->bus->boardinfo.type == 0x0416)) - return; - - b43legacy_phy_write(dev, 0x0028, 0x8018); - b43legacy_write16(dev, 0x03E6, b43legacy_read16(dev, 0x03E6) & 0xFFDF); - - if (phy->type == B43legacy_PHYTYPE_G) { - if (!phy->gmode) - return; - b43legacy_phy_write(dev, 0x047A, 0xC111); - } - if (phy->savedpctlreg != 0xFFFF) - return; -#ifdef CONFIG_B43LEGACY_DEBUG - if (phy->manual_txpower_control) - return; -#endif - - if (phy->type == B43legacy_PHYTYPE_B && - phy->rev >= 2 && - phy->radio_ver == 0x2050) - b43legacy_radio_write16(dev, 0x0076, - b43legacy_radio_read16(dev, 0x0076) - | 0x0084); - else { - saved_batt = phy->bbatt; - saved_ratt = phy->rfatt; - saved_txctl1 = phy->txctl1; - if ((phy->radio_rev >= 6) && (phy->radio_rev <= 8) - && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) - b43legacy_radio_set_txpower_bg(dev, 0xB, 0x1F, 0); - else - b43legacy_radio_set_txpower_bg(dev, 0xB, 9, 0); - must_reset_txpower = 1; - } - b43legacy_dummy_transmission(dev); - - phy->savedpctlreg = b43legacy_phy_read(dev, B43legacy_PHY_G_PCTL); - - if (must_reset_txpower) - b43legacy_radio_set_txpower_bg(dev, saved_batt, saved_ratt, - saved_txctl1); - else - b43legacy_radio_write16(dev, 0x0076, b43legacy_radio_read16(dev, - 0x0076) & 0xFF7B); - b43legacy_radio_clear_tssi(dev); -} - -static void b43legacy_phy_agcsetup(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 offset = 0x0000; - - if (phy->rev == 1) - offset = 0x4C00; - - b43legacy_ilt_write(dev, offset, 0x00FE); - b43legacy_ilt_write(dev, offset + 1, 0x000D); - b43legacy_ilt_write(dev, offset + 2, 0x0013); - b43legacy_ilt_write(dev, offset + 3, 0x0019); - - if (phy->rev == 1) { - b43legacy_ilt_write(dev, 0x1800, 0x2710); - b43legacy_ilt_write(dev, 0x1801, 0x9B83); - b43legacy_ilt_write(dev, 0x1802, 0x9B83); - b43legacy_ilt_write(dev, 0x1803, 0x0F8D); - b43legacy_phy_write(dev, 0x0455, 0x0004); - } - - b43legacy_phy_write(dev, 0x04A5, (b43legacy_phy_read(dev, 0x04A5) - & 0x00FF) | 0x5700); - b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A) - & 0xFF80) | 0x000F); - b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A) - & 0xC07F) | 0x2B80); - b43legacy_phy_write(dev, 0x048C, (b43legacy_phy_read(dev, 0x048C) - & 0xF0FF) | 0x0300); - - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x0008); - - b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0) - & 0xFFF0) | 0x0008); - b43legacy_phy_write(dev, 0x04A1, (b43legacy_phy_read(dev, 0x04A1) - & 0xF0FF) | 0x0600); - b43legacy_phy_write(dev, 0x04A2, (b43legacy_phy_read(dev, 0x04A2) - & 0xF0FF) | 0x0700); - b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0) - & 0xF0FF) | 0x0100); - - if (phy->rev == 1) - b43legacy_phy_write(dev, 0x04A2, - (b43legacy_phy_read(dev, 0x04A2) - & 0xFFF0) | 0x0007); - - b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488) - & 0xFF00) | 0x001C); - b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488) - & 0xC0FF) | 0x0200); - b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496) - & 0xFF00) | 0x001C); - b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489) - & 0xFF00) | 0x0020); - b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489) - & 0xC0FF) | 0x0200); - b43legacy_phy_write(dev, 0x0482, (b43legacy_phy_read(dev, 0x0482) - & 0xFF00) | 0x002E); - b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496) - & 0x00FF) | 0x1A00); - b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481) - & 0xFF00) | 0x0028); - b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481) - & 0x00FF) | 0x2C00); - - if (phy->rev == 1) { - b43legacy_phy_write(dev, 0x0430, 0x092B); - b43legacy_phy_write(dev, 0x041B, - (b43legacy_phy_read(dev, 0x041B) - & 0xFFE1) | 0x0002); - } else { - b43legacy_phy_write(dev, 0x041B, - b43legacy_phy_read(dev, 0x041B) & 0xFFE1); - b43legacy_phy_write(dev, 0x041F, 0x287A); - b43legacy_phy_write(dev, 0x0420, - (b43legacy_phy_read(dev, 0x0420) - & 0xFFF0) | 0x0004); - } - - if (phy->rev > 2) { - b43legacy_phy_write(dev, 0x0422, 0x287A); - b43legacy_phy_write(dev, 0x0420, - (b43legacy_phy_read(dev, 0x0420) - & 0x0FFF) | 0x3000); - } - - b43legacy_phy_write(dev, 0x04A8, (b43legacy_phy_read(dev, 0x04A8) - & 0x8080) | 0x7874); - b43legacy_phy_write(dev, 0x048E, 0x1C00); - - if (phy->rev == 1) { - b43legacy_phy_write(dev, 0x04AB, - (b43legacy_phy_read(dev, 0x04AB) - & 0xF0FF) | 0x0600); - b43legacy_phy_write(dev, 0x048B, 0x005E); - b43legacy_phy_write(dev, 0x048C, - (b43legacy_phy_read(dev, 0x048C) & 0xFF00) - | 0x001E); - b43legacy_phy_write(dev, 0x048D, 0x0002); - } - - b43legacy_ilt_write(dev, offset + 0x0800, 0); - b43legacy_ilt_write(dev, offset + 0x0801, 7); - b43legacy_ilt_write(dev, offset + 0x0802, 16); - b43legacy_ilt_write(dev, offset + 0x0803, 28); - - if (phy->rev >= 6) { - b43legacy_phy_write(dev, 0x0426, - (b43legacy_phy_read(dev, 0x0426) & 0xFFFC)); - b43legacy_phy_write(dev, 0x0426, - (b43legacy_phy_read(dev, 0x0426) & 0xEFFF)); - } -} - -static void b43legacy_phy_setupg(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 i; - - B43legacy_BUG_ON(phy->type != B43legacy_PHYTYPE_G); - if (phy->rev == 1) { - b43legacy_phy_write(dev, 0x0406, 0x4F19); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - (b43legacy_phy_read(dev, - B43legacy_PHY_G_CRS) & 0xFC3F) | 0x0340); - b43legacy_phy_write(dev, 0x042C, 0x005A); - b43legacy_phy_write(dev, 0x0427, 0x001A); - - for (i = 0; i < B43legacy_ILT_FINEFREQG_SIZE; i++) - b43legacy_ilt_write(dev, 0x5800 + i, - b43legacy_ilt_finefreqg[i]); - for (i = 0; i < B43legacy_ILT_NOISEG1_SIZE; i++) - b43legacy_ilt_write(dev, 0x1800 + i, - b43legacy_ilt_noiseg1[i]); - for (i = 0; i < B43legacy_ILT_ROTOR_SIZE; i++) - b43legacy_ilt_write32(dev, 0x2000 + i, - b43legacy_ilt_rotor[i]); - } else { - /* nrssi values are signed 6-bit values. Why 0x7654 here? */ - b43legacy_nrssi_hw_write(dev, 0xBA98, (s16)0x7654); - - if (phy->rev == 2) { - b43legacy_phy_write(dev, 0x04C0, 0x1861); - b43legacy_phy_write(dev, 0x04C1, 0x0271); - } else if (phy->rev > 2) { - b43legacy_phy_write(dev, 0x04C0, 0x0098); - b43legacy_phy_write(dev, 0x04C1, 0x0070); - b43legacy_phy_write(dev, 0x04C9, 0x0080); - } - b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev, - 0x042B) | 0x800); - - for (i = 0; i < 64; i++) - b43legacy_ilt_write(dev, 0x4000 + i, i); - for (i = 0; i < B43legacy_ILT_NOISEG2_SIZE; i++) - b43legacy_ilt_write(dev, 0x1800 + i, - b43legacy_ilt_noiseg2[i]); - } - - if (phy->rev <= 2) - for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++) - b43legacy_ilt_write(dev, 0x1400 + i, - b43legacy_ilt_noisescaleg1[i]); - else if ((phy->rev >= 7) && (b43legacy_phy_read(dev, 0x0449) & 0x0200)) - for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++) - b43legacy_ilt_write(dev, 0x1400 + i, - b43legacy_ilt_noisescaleg3[i]); - else - for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++) - b43legacy_ilt_write(dev, 0x1400 + i, - b43legacy_ilt_noisescaleg2[i]); - - if (phy->rev == 2) - for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++) - b43legacy_ilt_write(dev, 0x5000 + i, - b43legacy_ilt_sigmasqr1[i]); - else if ((phy->rev > 2) && (phy->rev <= 8)) - for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++) - b43legacy_ilt_write(dev, 0x5000 + i, - b43legacy_ilt_sigmasqr2[i]); - - if (phy->rev == 1) { - for (i = 0; i < B43legacy_ILT_RETARD_SIZE; i++) - b43legacy_ilt_write32(dev, 0x2400 + i, - b43legacy_ilt_retard[i]); - for (i = 4; i < 20; i++) - b43legacy_ilt_write(dev, 0x5400 + i, 0x0020); - b43legacy_phy_agcsetup(dev); - - if (is_bcm_board_vendor(dev) && - (dev->dev->bus->boardinfo.type == 0x0416) && - (dev->dev->bus->boardinfo.rev == 0x0017)) - return; - - b43legacy_ilt_write(dev, 0x5001, 0x0002); - b43legacy_ilt_write(dev, 0x5002, 0x0001); - } else { - for (i = 0; i <= 0x20; i++) - b43legacy_ilt_write(dev, 0x1000 + i, 0x0820); - b43legacy_phy_agcsetup(dev); - b43legacy_phy_read(dev, 0x0400); /* dummy read */ - b43legacy_phy_write(dev, 0x0403, 0x1000); - b43legacy_ilt_write(dev, 0x3C02, 0x000F); - b43legacy_ilt_write(dev, 0x3C03, 0x0014); - - if (is_bcm_board_vendor(dev) && - (dev->dev->bus->boardinfo.type == 0x0416) && - (dev->dev->bus->boardinfo.rev == 0x0017)) - return; - - b43legacy_ilt_write(dev, 0x0401, 0x0002); - b43legacy_ilt_write(dev, 0x0402, 0x0001); - } -} - -/* Initialize the APHY portion of a GPHY. */ -static void b43legacy_phy_inita(struct b43legacy_wldev *dev) -{ - - might_sleep(); - - b43legacy_phy_setupg(dev); - if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) - b43legacy_phy_write(dev, 0x046E, 0x03CF); -} - -static void b43legacy_phy_initb2(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 offset; - int val; - - b43legacy_write16(dev, 0x03EC, 0x3F22); - b43legacy_phy_write(dev, 0x0020, 0x301C); - b43legacy_phy_write(dev, 0x0026, 0x0000); - b43legacy_phy_write(dev, 0x0030, 0x00C6); - b43legacy_phy_write(dev, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - b43legacy_phy_write(dev, offset, val); - val -= 0x0202; - } - b43legacy_phy_write(dev, 0x03E4, 0x3000); - b43legacy_radio_selectchannel(dev, phy->channel, 0); - if (phy->radio_ver != 0x2050) { - b43legacy_radio_write16(dev, 0x0075, 0x0080); - b43legacy_radio_write16(dev, 0x0079, 0x0081); - } - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x0050, 0x0023); - if (phy->radio_ver == 0x2050) { - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x005A, 0x0070); - b43legacy_radio_write16(dev, 0x005B, 0x007B); - b43legacy_radio_write16(dev, 0x005C, 0x00B0); - b43legacy_radio_write16(dev, 0x007A, 0x000F); - b43legacy_phy_write(dev, 0x0038, 0x0677); - b43legacy_radio_init2050(dev); - } - b43legacy_phy_write(dev, 0x0014, 0x0080); - b43legacy_phy_write(dev, 0x0032, 0x00CA); - b43legacy_phy_write(dev, 0x0032, 0x00CC); - b43legacy_phy_write(dev, 0x0035, 0x07C2); - b43legacy_phy_lo_b_measure(dev); - b43legacy_phy_write(dev, 0x0026, 0xCC00); - if (phy->radio_ver != 0x2050) - b43legacy_phy_write(dev, 0x0026, 0xCE00); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1000); - b43legacy_phy_write(dev, 0x002A, 0x88A3); - if (phy->radio_ver != 0x2050) - b43legacy_phy_write(dev, 0x002A, 0x88C2); - b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); - b43legacy_phy_init_pctl(dev); -} - -static void b43legacy_phy_initb4(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 offset; - u16 val; - - b43legacy_write16(dev, 0x03EC, 0x3F22); - b43legacy_phy_write(dev, 0x0020, 0x301C); - b43legacy_phy_write(dev, 0x0026, 0x0000); - b43legacy_phy_write(dev, 0x0030, 0x00C6); - b43legacy_phy_write(dev, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - b43legacy_phy_write(dev, offset, val); - val -= 0x0202; - } - b43legacy_phy_write(dev, 0x03E4, 0x3000); - b43legacy_radio_selectchannel(dev, phy->channel, 0); - if (phy->radio_ver != 0x2050) { - b43legacy_radio_write16(dev, 0x0075, 0x0080); - b43legacy_radio_write16(dev, 0x0079, 0x0081); - } - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x0050, 0x0023); - if (phy->radio_ver == 0x2050) { - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x005A, 0x0070); - b43legacy_radio_write16(dev, 0x005B, 0x007B); - b43legacy_radio_write16(dev, 0x005C, 0x00B0); - b43legacy_radio_write16(dev, 0x007A, 0x000F); - b43legacy_phy_write(dev, 0x0038, 0x0677); - b43legacy_radio_init2050(dev); - } - b43legacy_phy_write(dev, 0x0014, 0x0080); - b43legacy_phy_write(dev, 0x0032, 0x00CA); - if (phy->radio_ver == 0x2050) - b43legacy_phy_write(dev, 0x0032, 0x00E0); - b43legacy_phy_write(dev, 0x0035, 0x07C2); - - b43legacy_phy_lo_b_measure(dev); - - b43legacy_phy_write(dev, 0x0026, 0xCC00); - if (phy->radio_ver == 0x2050) - b43legacy_phy_write(dev, 0x0026, 0xCE00); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1100); - b43legacy_phy_write(dev, 0x002A, 0x88A3); - if (phy->radio_ver == 0x2050) - b43legacy_phy_write(dev, 0x002A, 0x88C2); - b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); - if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) { - b43legacy_calc_nrssi_slope(dev); - b43legacy_calc_nrssi_threshold(dev); - } - b43legacy_phy_init_pctl(dev); -} - -static void b43legacy_phy_initb5(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 offset; - u16 value; - u8 old_channel; - - if (phy->analog == 1) - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x0050); - if (!is_bcm_board_vendor(dev) && - (dev->dev->bus->boardinfo.type != 0x0416)) { - value = 0x2120; - for (offset = 0x00A8 ; offset < 0x00C7; offset++) { - b43legacy_phy_write(dev, offset, value); - value += 0x0202; - } - } - b43legacy_phy_write(dev, 0x0035, - (b43legacy_phy_read(dev, 0x0035) & 0xF0FF) - | 0x0700); - if (phy->radio_ver == 0x2050) - b43legacy_phy_write(dev, 0x0038, 0x0667); - - if (phy->gmode) { - if (phy->radio_ver == 0x2050) { - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x0020); - b43legacy_radio_write16(dev, 0x0051, - b43legacy_radio_read16(dev, 0x0051) - | 0x0004); - } - b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, 0x0000); - - b43legacy_phy_write(dev, 0x0802, b43legacy_phy_read(dev, 0x0802) - | 0x0100); - b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev, 0x042B) - | 0x2000); - - b43legacy_phy_write(dev, 0x001C, 0x186A); - - b43legacy_phy_write(dev, 0x0013, (b43legacy_phy_read(dev, - 0x0013) & 0x00FF) | 0x1900); - b43legacy_phy_write(dev, 0x0035, (b43legacy_phy_read(dev, - 0x0035) & 0xFFC0) | 0x0064); - b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev, - 0x005D) & 0xFF80) | 0x000A); - b43legacy_phy_write(dev, 0x5B, 0x0000); - b43legacy_phy_write(dev, 0x5C, 0x0000); - } - - if (dev->bad_frames_preempt) - b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, - b43legacy_phy_read(dev, - B43legacy_PHY_RADIO_BITFIELD) | (1 << 12)); - - if (phy->analog == 1) { - b43legacy_phy_write(dev, 0x0026, 0xCE00); - b43legacy_phy_write(dev, 0x0021, 0x3763); - b43legacy_phy_write(dev, 0x0022, 0x1BC3); - b43legacy_phy_write(dev, 0x0023, 0x06F9); - b43legacy_phy_write(dev, 0x0024, 0x037E); - } else - b43legacy_phy_write(dev, 0x0026, 0xCC00); - b43legacy_phy_write(dev, 0x0030, 0x00C6); - b43legacy_write16(dev, 0x03EC, 0x3F22); - - if (phy->analog == 1) - b43legacy_phy_write(dev, 0x0020, 0x3E1C); - else - b43legacy_phy_write(dev, 0x0020, 0x301C); - - if (phy->analog == 0) - b43legacy_write16(dev, 0x03E4, 0x3000); - - old_channel = (phy->channel == 0xFF) ? 1 : phy->channel; - /* Force to channel 7, even if not supported. */ - b43legacy_radio_selectchannel(dev, 7, 0); - - if (phy->radio_ver != 0x2050) { - b43legacy_radio_write16(dev, 0x0075, 0x0080); - b43legacy_radio_write16(dev, 0x0079, 0x0081); - } - - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x0050, 0x0023); - - if (phy->radio_ver == 0x2050) { - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x005A, 0x0070); - } - - b43legacy_radio_write16(dev, 0x005B, 0x007B); - b43legacy_radio_write16(dev, 0x005C, 0x00B0); - - b43legacy_radio_write16(dev, 0x007A, b43legacy_radio_read16(dev, - 0x007A) | 0x0007); - - b43legacy_radio_selectchannel(dev, old_channel, 0); - - b43legacy_phy_write(dev, 0x0014, 0x0080); - b43legacy_phy_write(dev, 0x0032, 0x00CA); - b43legacy_phy_write(dev, 0x002A, 0x88A3); - - b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); - - if (phy->radio_ver == 0x2050) - b43legacy_radio_write16(dev, 0x005D, 0x000D); - - b43legacy_write16(dev, 0x03E4, (b43legacy_read16(dev, 0x03E4) & - 0xFFC0) | 0x0004); -} - -static void b43legacy_phy_initb6(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 offset; - u16 val; - u8 old_channel; - - b43legacy_phy_write(dev, 0x003E, 0x817A); - b43legacy_radio_write16(dev, 0x007A, - (b43legacy_radio_read16(dev, 0x007A) | 0x0058)); - if (phy->radio_rev == 4 || - phy->radio_rev == 5) { - b43legacy_radio_write16(dev, 0x0051, 0x0037); - b43legacy_radio_write16(dev, 0x0052, 0x0070); - b43legacy_radio_write16(dev, 0x0053, 0x00B3); - b43legacy_radio_write16(dev, 0x0054, 0x009B); - b43legacy_radio_write16(dev, 0x005A, 0x0088); - b43legacy_radio_write16(dev, 0x005B, 0x0088); - b43legacy_radio_write16(dev, 0x005D, 0x0088); - b43legacy_radio_write16(dev, 0x005E, 0x0088); - b43legacy_radio_write16(dev, 0x007D, 0x0088); - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - (b43legacy_shm_read32(dev, - B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET) - | 0x00000200)); - } - if (phy->radio_rev == 8) { - b43legacy_radio_write16(dev, 0x0051, 0x0000); - b43legacy_radio_write16(dev, 0x0052, 0x0040); - b43legacy_radio_write16(dev, 0x0053, 0x00B7); - b43legacy_radio_write16(dev, 0x0054, 0x0098); - b43legacy_radio_write16(dev, 0x005A, 0x0088); - b43legacy_radio_write16(dev, 0x005B, 0x006B); - b43legacy_radio_write16(dev, 0x005C, 0x000F); - if (dev->dev->bus->sprom.boardflags_lo & 0x8000) { - b43legacy_radio_write16(dev, 0x005D, 0x00FA); - b43legacy_radio_write16(dev, 0x005E, 0x00D8); - } else { - b43legacy_radio_write16(dev, 0x005D, 0x00F5); - b43legacy_radio_write16(dev, 0x005E, 0x00B8); - } - b43legacy_radio_write16(dev, 0x0073, 0x0003); - b43legacy_radio_write16(dev, 0x007D, 0x00A8); - b43legacy_radio_write16(dev, 0x007C, 0x0001); - b43legacy_radio_write16(dev, 0x007E, 0x0008); - } - val = 0x1E1F; - for (offset = 0x0088; offset < 0x0098; offset++) { - b43legacy_phy_write(dev, offset, val); - val -= 0x0202; - } - val = 0x3E3F; - for (offset = 0x0098; offset < 0x00A8; offset++) { - b43legacy_phy_write(dev, offset, val); - val -= 0x0202; - } - val = 0x2120; - for (offset = 0x00A8; offset < 0x00C8; offset++) { - b43legacy_phy_write(dev, offset, (val & 0x3F3F)); - val += 0x0202; - } - if (phy->type == B43legacy_PHYTYPE_G) { - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) | - 0x0020); - b43legacy_radio_write16(dev, 0x0051, - b43legacy_radio_read16(dev, 0x0051) | - 0x0004); - b43legacy_phy_write(dev, 0x0802, - b43legacy_phy_read(dev, 0x0802) | 0x0100); - b43legacy_phy_write(dev, 0x042B, - b43legacy_phy_read(dev, 0x042B) | 0x2000); - b43legacy_phy_write(dev, 0x5B, 0x0000); - b43legacy_phy_write(dev, 0x5C, 0x0000); - } - - old_channel = phy->channel; - if (old_channel >= 8) - b43legacy_radio_selectchannel(dev, 1, 0); - else - b43legacy_radio_selectchannel(dev, 13, 0); - - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x0050, 0x0023); - udelay(40); - if (phy->radio_rev < 6 || phy->radio_rev == 8) { - b43legacy_radio_write16(dev, 0x007C, - (b43legacy_radio_read16(dev, 0x007C) - | 0x0002)); - b43legacy_radio_write16(dev, 0x0050, 0x0020); - } - if (phy->radio_rev <= 2) { - b43legacy_radio_write16(dev, 0x0050, 0x0020); - b43legacy_radio_write16(dev, 0x005A, 0x0070); - b43legacy_radio_write16(dev, 0x005B, 0x007B); - b43legacy_radio_write16(dev, 0x005C, 0x00B0); - } - b43legacy_radio_write16(dev, 0x007A, - (b43legacy_radio_read16(dev, - 0x007A) & 0x00F8) | 0x0007); - - b43legacy_radio_selectchannel(dev, old_channel, 0); - - b43legacy_phy_write(dev, 0x0014, 0x0200); - if (phy->radio_rev >= 6) - b43legacy_phy_write(dev, 0x002A, 0x88C2); - else - b43legacy_phy_write(dev, 0x002A, 0x8AC0); - b43legacy_phy_write(dev, 0x0038, 0x0668); - b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); - if (phy->radio_rev == 4 || phy->radio_rev == 5) - b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev, - 0x005D) & 0xFF80) | 0x0003); - if (phy->radio_rev <= 2) - b43legacy_radio_write16(dev, 0x005D, 0x000D); - - if (phy->analog == 4) { - b43legacy_write16(dev, 0x03E4, 0x0009); - b43legacy_phy_write(dev, 0x61, b43legacy_phy_read(dev, 0x61) - & 0xFFF); - } else - b43legacy_phy_write(dev, 0x0002, (b43legacy_phy_read(dev, - 0x0002) & 0xFFC0) | 0x0004); - if (phy->type == B43legacy_PHYTYPE_G) - b43legacy_write16(dev, 0x03E6, 0x0); - if (phy->type == B43legacy_PHYTYPE_B) { - b43legacy_write16(dev, 0x03E6, 0x8140); - b43legacy_phy_write(dev, 0x0016, 0x0410); - b43legacy_phy_write(dev, 0x0017, 0x0820); - b43legacy_phy_write(dev, 0x0062, 0x0007); - b43legacy_radio_init2050(dev); - b43legacy_phy_lo_g_measure(dev); - if (dev->dev->bus->sprom.boardflags_lo & - B43legacy_BFL_RSSI) { - b43legacy_calc_nrssi_slope(dev); - b43legacy_calc_nrssi_threshold(dev); - } - b43legacy_phy_init_pctl(dev); - } -} - -static void b43legacy_calc_loopback_gain(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 backup_phy[15] = {0}; - u16 backup_radio[3]; - u16 backup_bband; - u16 i; - u16 loop1_cnt; - u16 loop1_done; - u16 loop1_omitted; - u16 loop2_done; - - backup_phy[0] = b43legacy_phy_read(dev, 0x0429); - backup_phy[1] = b43legacy_phy_read(dev, 0x0001); - backup_phy[2] = b43legacy_phy_read(dev, 0x0811); - backup_phy[3] = b43legacy_phy_read(dev, 0x0812); - if (phy->rev != 1) { - backup_phy[4] = b43legacy_phy_read(dev, 0x0814); - backup_phy[5] = b43legacy_phy_read(dev, 0x0815); - } - backup_phy[6] = b43legacy_phy_read(dev, 0x005A); - backup_phy[7] = b43legacy_phy_read(dev, 0x0059); - backup_phy[8] = b43legacy_phy_read(dev, 0x0058); - backup_phy[9] = b43legacy_phy_read(dev, 0x000A); - backup_phy[10] = b43legacy_phy_read(dev, 0x0003); - backup_phy[11] = b43legacy_phy_read(dev, 0x080F); - backup_phy[12] = b43legacy_phy_read(dev, 0x0810); - backup_phy[13] = b43legacy_phy_read(dev, 0x002B); - backup_phy[14] = b43legacy_phy_read(dev, 0x0015); - b43legacy_phy_read(dev, 0x002D); /* dummy read */ - backup_bband = phy->bbatt; - backup_radio[0] = b43legacy_radio_read16(dev, 0x0052); - backup_radio[1] = b43legacy_radio_read16(dev, 0x0043); - backup_radio[2] = b43legacy_radio_read16(dev, 0x007A); - - b43legacy_phy_write(dev, 0x0429, - b43legacy_phy_read(dev, 0x0429) & 0x3FFF); - b43legacy_phy_write(dev, 0x0001, - b43legacy_phy_read(dev, 0x0001) & 0x8000); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) | 0x0002); - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) & 0xFFFD); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) | 0x0001); - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) & 0xFFFE); - if (phy->rev != 1) { - b43legacy_phy_write(dev, 0x0814, - b43legacy_phy_read(dev, 0x0814) | 0x0001); - b43legacy_phy_write(dev, 0x0815, - b43legacy_phy_read(dev, 0x0815) & 0xFFFE); - b43legacy_phy_write(dev, 0x0814, - b43legacy_phy_read(dev, 0x0814) | 0x0002); - b43legacy_phy_write(dev, 0x0815, - b43legacy_phy_read(dev, 0x0815) & 0xFFFD); - } - b43legacy_phy_write(dev, 0x0811, b43legacy_phy_read(dev, 0x0811) | - 0x000C); - b43legacy_phy_write(dev, 0x0812, b43legacy_phy_read(dev, 0x0812) | - 0x000C); - - b43legacy_phy_write(dev, 0x0811, (b43legacy_phy_read(dev, 0x0811) - & 0xFFCF) | 0x0030); - b43legacy_phy_write(dev, 0x0812, (b43legacy_phy_read(dev, 0x0812) - & 0xFFCF) | 0x0010); - - b43legacy_phy_write(dev, 0x005A, 0x0780); - b43legacy_phy_write(dev, 0x0059, 0xC810); - b43legacy_phy_write(dev, 0x0058, 0x000D); - if (phy->analog == 0) - b43legacy_phy_write(dev, 0x0003, 0x0122); - else - b43legacy_phy_write(dev, 0x000A, - b43legacy_phy_read(dev, 0x000A) - | 0x2000); - if (phy->rev != 1) { - b43legacy_phy_write(dev, 0x0814, - b43legacy_phy_read(dev, 0x0814) | 0x0004); - b43legacy_phy_write(dev, 0x0815, - b43legacy_phy_read(dev, 0x0815) & 0xFFFB); - } - b43legacy_phy_write(dev, 0x0003, - (b43legacy_phy_read(dev, 0x0003) - & 0xFF9F) | 0x0040); - if (phy->radio_ver == 0x2050 && phy->radio_rev == 2) { - b43legacy_radio_write16(dev, 0x0052, 0x0000); - b43legacy_radio_write16(dev, 0x0043, - (b43legacy_radio_read16(dev, 0x0043) - & 0xFFF0) | 0x0009); - loop1_cnt = 9; - } else if (phy->radio_rev == 8) { - b43legacy_radio_write16(dev, 0x0043, 0x000F); - loop1_cnt = 15; - } else - loop1_cnt = 0; - - b43legacy_phy_set_baseband_attenuation(dev, 11); - - if (phy->rev >= 3) - b43legacy_phy_write(dev, 0x080F, 0xC020); - else - b43legacy_phy_write(dev, 0x080F, 0x8020); - b43legacy_phy_write(dev, 0x0810, 0x0000); - - b43legacy_phy_write(dev, 0x002B, - (b43legacy_phy_read(dev, 0x002B) - & 0xFFC0) | 0x0001); - b43legacy_phy_write(dev, 0x002B, - (b43legacy_phy_read(dev, 0x002B) - & 0xC0FF) | 0x0800); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) | 0x0100); - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) & 0xCFFF); - if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) { - if (phy->rev >= 7) { - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) - | 0x0800); - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) - | 0x8000); - } - } - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - & 0x00F7); - - for (i = 0; i < loop1_cnt; i++) { - b43legacy_radio_write16(dev, 0x0043, loop1_cnt); - b43legacy_phy_write(dev, 0x0812, - (b43legacy_phy_read(dev, 0x0812) - & 0xF0FF) | (i << 8)); - b43legacy_phy_write(dev, 0x0015, - (b43legacy_phy_read(dev, 0x0015) - & 0x0FFF) | 0xA000); - b43legacy_phy_write(dev, 0x0015, - (b43legacy_phy_read(dev, 0x0015) - & 0x0FFF) | 0xF000); - udelay(20); - if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC) - break; - } - loop1_done = i; - loop1_omitted = loop1_cnt - loop1_done; - - loop2_done = 0; - if (loop1_done >= 8) { - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) - | 0x0030); - for (i = loop1_done - 8; i < 16; i++) { - b43legacy_phy_write(dev, 0x0812, - (b43legacy_phy_read(dev, 0x0812) - & 0xF0FF) | (i << 8)); - b43legacy_phy_write(dev, 0x0015, - (b43legacy_phy_read(dev, 0x0015) - & 0x0FFF) | 0xA000); - b43legacy_phy_write(dev, 0x0015, - (b43legacy_phy_read(dev, 0x0015) - & 0x0FFF) | 0xF000); - udelay(20); - if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC) - break; - } - } - - if (phy->rev != 1) { - b43legacy_phy_write(dev, 0x0814, backup_phy[4]); - b43legacy_phy_write(dev, 0x0815, backup_phy[5]); - } - b43legacy_phy_write(dev, 0x005A, backup_phy[6]); - b43legacy_phy_write(dev, 0x0059, backup_phy[7]); - b43legacy_phy_write(dev, 0x0058, backup_phy[8]); - b43legacy_phy_write(dev, 0x000A, backup_phy[9]); - b43legacy_phy_write(dev, 0x0003, backup_phy[10]); - b43legacy_phy_write(dev, 0x080F, backup_phy[11]); - b43legacy_phy_write(dev, 0x0810, backup_phy[12]); - b43legacy_phy_write(dev, 0x002B, backup_phy[13]); - b43legacy_phy_write(dev, 0x0015, backup_phy[14]); - - b43legacy_phy_set_baseband_attenuation(dev, backup_bband); - - b43legacy_radio_write16(dev, 0x0052, backup_radio[0]); - b43legacy_radio_write16(dev, 0x0043, backup_radio[1]); - b43legacy_radio_write16(dev, 0x007A, backup_radio[2]); - - b43legacy_phy_write(dev, 0x0811, backup_phy[2] | 0x0003); - udelay(10); - b43legacy_phy_write(dev, 0x0811, backup_phy[2]); - b43legacy_phy_write(dev, 0x0812, backup_phy[3]); - b43legacy_phy_write(dev, 0x0429, backup_phy[0]); - b43legacy_phy_write(dev, 0x0001, backup_phy[1]); - - phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11; - phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2; -} - -static void b43legacy_phy_initg(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 tmp; - - if (phy->rev == 1) - b43legacy_phy_initb5(dev); - else - b43legacy_phy_initb6(dev); - if (phy->rev >= 2 && phy->gmode) - b43legacy_phy_inita(dev); - - if (phy->rev >= 2) { - b43legacy_phy_write(dev, 0x0814, 0x0000); - b43legacy_phy_write(dev, 0x0815, 0x0000); - } - if (phy->rev == 2) { - b43legacy_phy_write(dev, 0x0811, 0x0000); - b43legacy_phy_write(dev, 0x0015, 0x00C0); - } - if (phy->rev > 5) { - b43legacy_phy_write(dev, 0x0811, 0x0400); - b43legacy_phy_write(dev, 0x0015, 0x00C0); - } - if (phy->gmode) { - tmp = b43legacy_phy_read(dev, 0x0400) & 0xFF; - if (tmp == 3) { - b43legacy_phy_write(dev, 0x04C2, 0x1816); - b43legacy_phy_write(dev, 0x04C3, 0x8606); - } - if (tmp == 4 || tmp == 5) { - b43legacy_phy_write(dev, 0x04C2, 0x1816); - b43legacy_phy_write(dev, 0x04C3, 0x8006); - b43legacy_phy_write(dev, 0x04CC, - (b43legacy_phy_read(dev, - 0x04CC) & 0x00FF) | - 0x1F00); - } - if (phy->rev >= 2) - b43legacy_phy_write(dev, 0x047E, 0x0078); - } - if (phy->radio_rev == 8) { - b43legacy_phy_write(dev, 0x0801, b43legacy_phy_read(dev, 0x0801) - | 0x0080); - b43legacy_phy_write(dev, 0x043E, b43legacy_phy_read(dev, 0x043E) - | 0x0004); - } - if (phy->rev >= 2 && phy->gmode) - b43legacy_calc_loopback_gain(dev); - if (phy->radio_rev != 8) { - if (phy->initval == 0xFFFF) - phy->initval = b43legacy_radio_init2050(dev); - else - b43legacy_radio_write16(dev, 0x0078, phy->initval); - } - if (phy->txctl2 == 0xFFFF) - b43legacy_phy_lo_g_measure(dev); - else { - if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) - b43legacy_radio_write16(dev, 0x0052, - (phy->txctl1 << 4) | - phy->txctl2); - else - b43legacy_radio_write16(dev, 0x0052, - (b43legacy_radio_read16(dev, - 0x0052) & 0xFFF0) | - phy->txctl1); - if (phy->rev >= 6) - b43legacy_phy_write(dev, 0x0036, - (b43legacy_phy_read(dev, 0x0036) - & 0x0FFF) | (phy->txctl2 << 12)); - if (dev->dev->bus->sprom.boardflags_lo & - B43legacy_BFL_PACTRL) - b43legacy_phy_write(dev, 0x002E, 0x8075); - else - b43legacy_phy_write(dev, 0x002E, 0x807F); - if (phy->rev < 2) - b43legacy_phy_write(dev, 0x002F, 0x0101); - else - b43legacy_phy_write(dev, 0x002F, 0x0202); - } - if (phy->gmode) { - b43legacy_phy_lo_adjust(dev, 0); - b43legacy_phy_write(dev, 0x080F, 0x8078); - } - - if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) { - /* The specs state to update the NRSSI LT with - * the value 0x7FFFFFFF here. I think that is some weird - * compiler optimization in the original driver. - * Essentially, what we do here is resetting all NRSSI LT - * entries to -32 (see the clamp_val() in nrssi_hw_update()) - */ - b43legacy_nrssi_hw_update(dev, 0xFFFF); - b43legacy_calc_nrssi_threshold(dev); - } else if (phy->gmode || phy->rev >= 2) { - if (phy->nrssi[0] == -1000) { - B43legacy_WARN_ON(phy->nrssi[1] != -1000); - b43legacy_calc_nrssi_slope(dev); - } else { - B43legacy_WARN_ON(phy->nrssi[1] == -1000); - b43legacy_calc_nrssi_threshold(dev); - } - } - if (phy->radio_rev == 8) - b43legacy_phy_write(dev, 0x0805, 0x3230); - b43legacy_phy_init_pctl(dev); - if (dev->dev->bus->chip_id == 0x4306 - && dev->dev->bus->chip_package == 2) { - b43legacy_phy_write(dev, 0x0429, - b43legacy_phy_read(dev, 0x0429) & 0xBFFF); - b43legacy_phy_write(dev, 0x04C3, - b43legacy_phy_read(dev, 0x04C3) & 0x7FFF); - } -} - -static u16 b43legacy_phy_lo_b_r15_loop(struct b43legacy_wldev *dev) -{ - int i; - u16 ret = 0; - unsigned long flags; - - local_irq_save(flags); - for (i = 0; i < 10; i++) { - b43legacy_phy_write(dev, 0x0015, 0xAFA0); - udelay(1); - b43legacy_phy_write(dev, 0x0015, 0xEFA0); - udelay(10); - b43legacy_phy_write(dev, 0x0015, 0xFFA0); - udelay(40); - ret += b43legacy_phy_read(dev, 0x002C); - } - local_irq_restore(flags); - b43legacy_voluntary_preempt(); - - return ret; -} - -void b43legacy_phy_lo_b_measure(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 regstack[12] = { 0 }; - u16 mls; - u16 fval; - int i; - int j; - - regstack[0] = b43legacy_phy_read(dev, 0x0015); - regstack[1] = b43legacy_radio_read16(dev, 0x0052) & 0xFFF0; - - if (phy->radio_ver == 0x2053) { - regstack[2] = b43legacy_phy_read(dev, 0x000A); - regstack[3] = b43legacy_phy_read(dev, 0x002A); - regstack[4] = b43legacy_phy_read(dev, 0x0035); - regstack[5] = b43legacy_phy_read(dev, 0x0003); - regstack[6] = b43legacy_phy_read(dev, 0x0001); - regstack[7] = b43legacy_phy_read(dev, 0x0030); - - regstack[8] = b43legacy_radio_read16(dev, 0x0043); - regstack[9] = b43legacy_radio_read16(dev, 0x007A); - regstack[10] = b43legacy_read16(dev, 0x03EC); - regstack[11] = b43legacy_radio_read16(dev, 0x0052) & 0x00F0; - - b43legacy_phy_write(dev, 0x0030, 0x00FF); - b43legacy_write16(dev, 0x03EC, 0x3F3F); - b43legacy_phy_write(dev, 0x0035, regstack[4] & 0xFF7F); - b43legacy_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0); - } - b43legacy_phy_write(dev, 0x0015, 0xB000); - b43legacy_phy_write(dev, 0x002B, 0x0004); - - if (phy->radio_ver == 0x2053) { - b43legacy_phy_write(dev, 0x002B, 0x0203); - b43legacy_phy_write(dev, 0x002A, 0x08A3); - } - - phy->minlowsig[0] = 0xFFFF; - - for (i = 0; i < 4; i++) { - b43legacy_radio_write16(dev, 0x0052, regstack[1] | i); - b43legacy_phy_lo_b_r15_loop(dev); - } - for (i = 0; i < 10; i++) { - b43legacy_radio_write16(dev, 0x0052, regstack[1] | i); - mls = b43legacy_phy_lo_b_r15_loop(dev) / 10; - if (mls < phy->minlowsig[0]) { - phy->minlowsig[0] = mls; - phy->minlowsigpos[0] = i; - } - } - b43legacy_radio_write16(dev, 0x0052, regstack[1] - | phy->minlowsigpos[0]); - - phy->minlowsig[1] = 0xFFFF; - - for (i = -4; i < 5; i += 2) { - for (j = -4; j < 5; j += 2) { - if (j < 0) - fval = (0x0100 * i) + j + 0x0100; - else - fval = (0x0100 * i) + j; - b43legacy_phy_write(dev, 0x002F, fval); - mls = b43legacy_phy_lo_b_r15_loop(dev) / 10; - if (mls < phy->minlowsig[1]) { - phy->minlowsig[1] = mls; - phy->minlowsigpos[1] = fval; - } - } - } - phy->minlowsigpos[1] += 0x0101; - - b43legacy_phy_write(dev, 0x002F, phy->minlowsigpos[1]); - if (phy->radio_ver == 0x2053) { - b43legacy_phy_write(dev, 0x000A, regstack[2]); - b43legacy_phy_write(dev, 0x002A, regstack[3]); - b43legacy_phy_write(dev, 0x0035, regstack[4]); - b43legacy_phy_write(dev, 0x0003, regstack[5]); - b43legacy_phy_write(dev, 0x0001, regstack[6]); - b43legacy_phy_write(dev, 0x0030, regstack[7]); - - b43legacy_radio_write16(dev, 0x0043, regstack[8]); - b43legacy_radio_write16(dev, 0x007A, regstack[9]); - - b43legacy_radio_write16(dev, 0x0052, - (b43legacy_radio_read16(dev, 0x0052) - & 0x000F) | regstack[11]); - - b43legacy_write16(dev, 0x03EC, regstack[10]); - } - b43legacy_phy_write(dev, 0x0015, regstack[0]); -} - -static inline -u16 b43legacy_phy_lo_g_deviation_subval(struct b43legacy_wldev *dev, - u16 control) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 ret; - unsigned long flags; - - local_irq_save(flags); - if (phy->gmode) { - b43legacy_phy_write(dev, 0x15, 0xE300); - control <<= 8; - b43legacy_phy_write(dev, 0x0812, control | 0x00B0); - udelay(5); - b43legacy_phy_write(dev, 0x0812, control | 0x00B2); - udelay(2); - b43legacy_phy_write(dev, 0x0812, control | 0x00B3); - udelay(4); - b43legacy_phy_write(dev, 0x0015, 0xF300); - udelay(8); - } else { - b43legacy_phy_write(dev, 0x0015, control | 0xEFA0); - udelay(2); - b43legacy_phy_write(dev, 0x0015, control | 0xEFE0); - udelay(4); - b43legacy_phy_write(dev, 0x0015, control | 0xFFE0); - udelay(8); - } - ret = b43legacy_phy_read(dev, 0x002D); - local_irq_restore(flags); - b43legacy_voluntary_preempt(); - - return ret; -} - -static u32 b43legacy_phy_lo_g_singledeviation(struct b43legacy_wldev *dev, - u16 control) -{ - int i; - u32 ret = 0; - - for (i = 0; i < 8; i++) - ret += b43legacy_phy_lo_g_deviation_subval(dev, control); - - return ret; -} - -/* Write the LocalOscillator CONTROL */ -static inline -void b43legacy_lo_write(struct b43legacy_wldev *dev, - struct b43legacy_lopair *pair) -{ - u16 value; - - value = (u8)(pair->low); - value |= ((u8)(pair->high)) << 8; - -#ifdef CONFIG_B43LEGACY_DEBUG - /* Sanity check. */ - if (pair->low < -8 || pair->low > 8 || - pair->high < -8 || pair->high > 8) { - b43legacydbg(dev->wl, - "WARNING: Writing invalid LOpair " - "(low: %d, high: %d)\n", - pair->low, pair->high); - dump_stack(); - } -#endif - - b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, value); -} - -static inline -struct b43legacy_lopair *b43legacy_find_lopair(struct b43legacy_wldev *dev, - u16 bbatt, - u16 rfatt, - u16 tx) -{ - static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - struct b43legacy_phy *phy = &dev->phy; - - if (bbatt > 6) - bbatt = 6; - B43legacy_WARN_ON(rfatt >= 10); - - if (tx == 3) - return b43legacy_get_lopair(phy, rfatt, bbatt); - return b43legacy_get_lopair(phy, dict[rfatt], bbatt); -} - -static inline -struct b43legacy_lopair *b43legacy_current_lopair(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - - return b43legacy_find_lopair(dev, phy->bbatt, - phy->rfatt, phy->txctl1); -} - -/* Adjust B/G LO */ -void b43legacy_phy_lo_adjust(struct b43legacy_wldev *dev, int fixed) -{ - struct b43legacy_lopair *pair; - - if (fixed) { - /* Use fixed values. Only for initialization. */ - pair = b43legacy_find_lopair(dev, 2, 3, 0); - } else - pair = b43legacy_current_lopair(dev); - b43legacy_lo_write(dev, pair); -} - -static void b43legacy_phy_lo_g_measure_txctl2(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 txctl2 = 0; - u16 i; - u32 smallest; - u32 tmp; - - b43legacy_radio_write16(dev, 0x0052, 0x0000); - udelay(10); - smallest = b43legacy_phy_lo_g_singledeviation(dev, 0); - for (i = 0; i < 16; i++) { - b43legacy_radio_write16(dev, 0x0052, i); - udelay(10); - tmp = b43legacy_phy_lo_g_singledeviation(dev, 0); - if (tmp < smallest) { - smallest = tmp; - txctl2 = i; - } - } - phy->txctl2 = txctl2; -} - -static -void b43legacy_phy_lo_g_state(struct b43legacy_wldev *dev, - const struct b43legacy_lopair *in_pair, - struct b43legacy_lopair *out_pair, - u16 r27) -{ - static const struct b43legacy_lopair transitions[8] = { - { .high = 1, .low = 1, }, - { .high = 1, .low = 0, }, - { .high = 1, .low = -1, }, - { .high = 0, .low = -1, }, - { .high = -1, .low = -1, }, - { .high = -1, .low = 0, }, - { .high = -1, .low = 1, }, - { .high = 0, .low = 1, }, - }; - struct b43legacy_lopair lowest_transition = { - .high = in_pair->high, - .low = in_pair->low, - }; - struct b43legacy_lopair tmp_pair; - struct b43legacy_lopair transition; - int i = 12; - int state = 0; - int found_lower; - int j; - int begin; - int end; - u32 lowest_deviation; - u32 tmp; - - /* Note that in_pair and out_pair can point to the same pair. - * Be careful. */ - - b43legacy_lo_write(dev, &lowest_transition); - lowest_deviation = b43legacy_phy_lo_g_singledeviation(dev, r27); - do { - found_lower = 0; - B43legacy_WARN_ON(!(state >= 0 && state <= 8)); - if (state == 0) { - begin = 1; - end = 8; - } else if (state % 2 == 0) { - begin = state - 1; - end = state + 1; - } else { - begin = state - 2; - end = state + 2; - } - if (begin < 1) - begin += 8; - if (end > 8) - end -= 8; - - j = begin; - tmp_pair.high = lowest_transition.high; - tmp_pair.low = lowest_transition.low; - while (1) { - B43legacy_WARN_ON(!(j >= 1 && j <= 8)); - transition.high = tmp_pair.high + - transitions[j - 1].high; - transition.low = tmp_pair.low + transitions[j - 1].low; - if ((abs(transition.low) < 9) - && (abs(transition.high) < 9)) { - b43legacy_lo_write(dev, &transition); - tmp = b43legacy_phy_lo_g_singledeviation(dev, - r27); - if (tmp < lowest_deviation) { - lowest_deviation = tmp; - state = j; - found_lower = 1; - - lowest_transition.high = - transition.high; - lowest_transition.low = transition.low; - } - } - if (j == end) - break; - if (j == 8) - j = 1; - else - j++; - } - } while (i-- && found_lower); - - out_pair->high = lowest_transition.high; - out_pair->low = lowest_transition.low; -} - -/* Set the baseband attenuation value on chip. */ -void b43legacy_phy_set_baseband_attenuation(struct b43legacy_wldev *dev, - u16 bbatt) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 value; - - if (phy->analog == 0) { - value = (b43legacy_read16(dev, 0x03E6) & 0xFFF0); - value |= (bbatt & 0x000F); - b43legacy_write16(dev, 0x03E6, value); - return; - } - - if (phy->analog > 1) { - value = b43legacy_phy_read(dev, 0x0060) & 0xFFC3; - value |= (bbatt << 2) & 0x003C; - } else { - value = b43legacy_phy_read(dev, 0x0060) & 0xFF87; - value |= (bbatt << 3) & 0x0078; - } - b43legacy_phy_write(dev, 0x0060, value); -} - -/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */ -void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev) -{ - static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; - const int is_initializing = (b43legacy_status(dev) - < B43legacy_STAT_STARTED); - struct b43legacy_phy *phy = &dev->phy; - u16 h; - u16 i; - u16 oldi = 0; - u16 j; - struct b43legacy_lopair control; - struct b43legacy_lopair *tmp_control; - u16 tmp; - u16 regstack[16] = { 0 }; - u8 oldchannel; - - /* XXX: What are these? */ - u8 r27 = 0; - u16 r31; - - oldchannel = phy->channel; - /* Setup */ - if (phy->gmode) { - regstack[0] = b43legacy_phy_read(dev, B43legacy_PHY_G_CRS); - regstack[1] = b43legacy_phy_read(dev, 0x0802); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0] - & 0x7FFF); - b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC); - } - regstack[3] = b43legacy_read16(dev, 0x03E2); - b43legacy_write16(dev, 0x03E2, regstack[3] | 0x8000); - regstack[4] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); - regstack[5] = b43legacy_phy_read(dev, 0x15); - regstack[6] = b43legacy_phy_read(dev, 0x2A); - regstack[7] = b43legacy_phy_read(dev, 0x35); - regstack[8] = b43legacy_phy_read(dev, 0x60); - regstack[9] = b43legacy_radio_read16(dev, 0x43); - regstack[10] = b43legacy_radio_read16(dev, 0x7A); - regstack[11] = b43legacy_radio_read16(dev, 0x52); - if (phy->gmode) { - regstack[12] = b43legacy_phy_read(dev, 0x0811); - regstack[13] = b43legacy_phy_read(dev, 0x0812); - regstack[14] = b43legacy_phy_read(dev, 0x0814); - regstack[15] = b43legacy_phy_read(dev, 0x0815); - } - b43legacy_radio_selectchannel(dev, 6, 0); - if (phy->gmode) { - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0] - & 0x7FFF); - b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC); - b43legacy_dummy_transmission(dev); - } - b43legacy_radio_write16(dev, 0x0043, 0x0006); - - b43legacy_phy_set_baseband_attenuation(dev, 2); - - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x0000); - b43legacy_phy_write(dev, 0x002E, 0x007F); - b43legacy_phy_write(dev, 0x080F, 0x0078); - b43legacy_phy_write(dev, 0x0035, regstack[7] & ~(1 << 7)); - b43legacy_radio_write16(dev, 0x007A, regstack[10] & 0xFFF0); - b43legacy_phy_write(dev, 0x002B, 0x0203); - b43legacy_phy_write(dev, 0x002A, 0x08A3); - if (phy->gmode) { - b43legacy_phy_write(dev, 0x0814, regstack[14] | 0x0003); - b43legacy_phy_write(dev, 0x0815, regstack[15] & 0xFFFC); - b43legacy_phy_write(dev, 0x0811, 0x01B3); - b43legacy_phy_write(dev, 0x0812, 0x00B2); - } - if (is_initializing) - b43legacy_phy_lo_g_measure_txctl2(dev); - b43legacy_phy_write(dev, 0x080F, 0x8078); - - /* Measure */ - control.low = 0; - control.high = 0; - for (h = 0; h < 10; h++) { - /* Loop over each possible RadioAttenuation (0-9) */ - i = pairorder[h]; - if (is_initializing) { - if (i == 3) { - control.low = 0; - control.high = 0; - } else if (((i % 2 == 1) && (oldi % 2 == 1)) || - ((i % 2 == 0) && (oldi % 2 == 0))) { - tmp_control = b43legacy_get_lopair(phy, oldi, - 0); - memcpy(&control, tmp_control, sizeof(control)); - } else { - tmp_control = b43legacy_get_lopair(phy, 3, 0); - memcpy(&control, tmp_control, sizeof(control)); - } - } - /* Loop over each possible BasebandAttenuation/2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp = i * 2 + j; - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = b43legacy_get_lopair(phy, i, - j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - b43legacy_radio_write16(dev, 0x43, i); - b43legacy_radio_write16(dev, 0x52, phy->txctl2); - udelay(10); - b43legacy_voluntary_preempt(); - - b43legacy_phy_set_baseband_attenuation(dev, j * 2); - - tmp = (regstack[10] & 0xFFF0); - if (r31) - tmp |= 0x0008; - b43legacy_radio_write16(dev, 0x007A, tmp); - - tmp_control = b43legacy_get_lopair(phy, i, j * 2); - b43legacy_phy_lo_g_state(dev, &control, tmp_control, - r27); - } - oldi = i; - } - /* Loop over each possible RadioAttenuation (10-13) */ - for (i = 10; i < 14; i++) { - /* Loop over each possible BasebandAttenuation/2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp_control = b43legacy_get_lopair(phy, i - 9, - j * 2); - memcpy(&control, tmp_control, sizeof(control)); - /* FIXME: The next line is wrong, as the - * following if statement can never trigger. */ - tmp = (i - 9) * 2 + j - 5; - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = b43legacy_get_lopair(phy, i - 9, - j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - b43legacy_radio_write16(dev, 0x43, i - 9); - /* FIXME: shouldn't txctl1 be zero in the next line - * and 3 in the loop above? */ - b43legacy_radio_write16(dev, 0x52, - phy->txctl2 - | (3/*txctl1*/ << 4)); - udelay(10); - b43legacy_voluntary_preempt(); - - b43legacy_phy_set_baseband_attenuation(dev, j * 2); - - tmp = (regstack[10] & 0xFFF0); - if (r31) - tmp |= 0x0008; - b43legacy_radio_write16(dev, 0x7A, tmp); - - tmp_control = b43legacy_get_lopair(phy, i, j * 2); - b43legacy_phy_lo_g_state(dev, &control, tmp_control, - r27); - } - } - - /* Restoration */ - if (phy->gmode) { - b43legacy_phy_write(dev, 0x0015, 0xE300); - b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA0); - udelay(5); - b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA2); - udelay(2); - b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA3); - b43legacy_voluntary_preempt(); - } else - b43legacy_phy_write(dev, 0x0015, r27 | 0xEFA0); - b43legacy_phy_lo_adjust(dev, is_initializing); - b43legacy_phy_write(dev, 0x002E, 0x807F); - if (phy->gmode) - b43legacy_phy_write(dev, 0x002F, 0x0202); - else - b43legacy_phy_write(dev, 0x002F, 0x0101); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, regstack[4]); - b43legacy_phy_write(dev, 0x0015, regstack[5]); - b43legacy_phy_write(dev, 0x002A, regstack[6]); - b43legacy_phy_write(dev, 0x0035, regstack[7]); - b43legacy_phy_write(dev, 0x0060, regstack[8]); - b43legacy_radio_write16(dev, 0x0043, regstack[9]); - b43legacy_radio_write16(dev, 0x007A, regstack[10]); - regstack[11] &= 0x00F0; - regstack[11] |= (b43legacy_radio_read16(dev, 0x52) & 0x000F); - b43legacy_radio_write16(dev, 0x52, regstack[11]); - b43legacy_write16(dev, 0x03E2, regstack[3]); - if (phy->gmode) { - b43legacy_phy_write(dev, 0x0811, regstack[12]); - b43legacy_phy_write(dev, 0x0812, regstack[13]); - b43legacy_phy_write(dev, 0x0814, regstack[14]); - b43legacy_phy_write(dev, 0x0815, regstack[15]); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]); - b43legacy_phy_write(dev, 0x0802, regstack[1]); - } - b43legacy_radio_selectchannel(dev, oldchannel, 1); - -#ifdef CONFIG_B43LEGACY_DEBUG - { - /* Sanity check for all lopairs. */ - for (i = 0; i < B43legacy_LO_COUNT; i++) { - tmp_control = phy->_lo_pairs + i; - if (tmp_control->low < -8 || tmp_control->low > 8 || - tmp_control->high < -8 || tmp_control->high > 8) - b43legacywarn(dev->wl, - "WARNING: Invalid LOpair (low: %d, high:" - " %d, index: %d)\n", - tmp_control->low, tmp_control->high, i); - } - } -#endif /* CONFIG_B43LEGACY_DEBUG */ -} - -static -void b43legacy_phy_lo_mark_current_used(struct b43legacy_wldev *dev) -{ - struct b43legacy_lopair *pair; - - pair = b43legacy_current_lopair(dev); - pair->used = 1; -} - -void b43legacy_phy_lo_mark_all_unused(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - struct b43legacy_lopair *pair; - int i; - - for (i = 0; i < B43legacy_LO_COUNT; i++) { - pair = phy->_lo_pairs + i; - pair->used = 0; - } -} - -/* http://bcm-specs.sipsolutions.net/EstimatePowerOut - * This function converts a TSSI value to dBm in Q5.2 - */ -static s8 b43legacy_phy_estimate_power_out(struct b43legacy_wldev *dev, s8 tssi) -{ - struct b43legacy_phy *phy = &dev->phy; - s8 dbm = 0; - s32 tmp; - - tmp = phy->idle_tssi; - tmp += tssi; - tmp -= phy->savedpctlreg; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - tmp = clamp_val(tmp, 0x00, 0x3F); - dbm = phy->tssi2dbm[tmp]; - break; - default: - B43legacy_BUG_ON(1); - } - - return dbm; -} - -/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ -void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 tmp; - u16 txpower; - s8 v0; - s8 v1; - s8 v2; - s8 v3; - s8 average; - int max_pwr; - s16 desired_pwr; - s16 estimated_pwr; - s16 pwr_adjust; - s16 radio_att_delta; - s16 baseband_att_delta; - s16 radio_attenuation; - s16 baseband_attenuation; - - if (phy->savedpctlreg == 0xFFFF) - return; - if ((dev->dev->bus->boardinfo.type == 0x0416) && - is_bcm_board_vendor(dev)) - return; -#ifdef CONFIG_B43LEGACY_DEBUG - if (phy->manual_txpower_control) - return; -#endif - - B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B || - phy->type == B43legacy_PHYTYPE_G)); - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0058); - v0 = (s8)(tmp & 0x00FF); - v1 = (s8)((tmp & 0xFF00) >> 8); - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005A); - v2 = (s8)(tmp & 0x00FF); - v3 = (s8)((tmp & 0xFF00) >> 8); - tmp = 0; - - if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) { - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - 0x0070); - v0 = (s8)(tmp & 0x00FF); - v1 = (s8)((tmp & 0xFF00) >> 8); - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, - 0x0072); - v2 = (s8)(tmp & 0x00FF); - v3 = (s8)((tmp & 0xFF00) >> 8); - if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) - return; - v0 = (v0 + 0x20) & 0x3F; - v1 = (v1 + 0x20) & 0x3F; - v2 = (v2 + 0x20) & 0x3F; - v3 = (v3 + 0x20) & 0x3F; - tmp = 1; - } - b43legacy_radio_clear_tssi(dev); - - average = (v0 + v1 + v2 + v3 + 2) / 4; - - if (tmp && (b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005E) - & 0x8)) - average -= 13; - - estimated_pwr = b43legacy_phy_estimate_power_out(dev, average); - - max_pwr = dev->dev->bus->sprom.maxpwr_bg; - - if ((dev->dev->bus->sprom.boardflags_lo - & B43legacy_BFL_PACTRL) && - (phy->type == B43legacy_PHYTYPE_G)) - max_pwr -= 0x3; - if (unlikely(max_pwr <= 0)) { - b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM." - "\n"); - max_pwr = 74; /* fake it */ - dev->dev->bus->sprom.maxpwr_bg = max_pwr; - } - - /* Use regulatory information to get the maximum power. - * In the absence of such data from mac80211, we will use 20 dBm, which - * is the value for the EU, US, Canada, and most of the world. - * The regulatory maximum is reduced by the antenna gain (from sprom) - * and 1.5 dBm (a safety factor??). The result is in Q5.2 format - * which accounts for the factor of 4 */ -#define REG_MAX_PWR 20 - max_pwr = min(REG_MAX_PWR * 4 - - dev->dev->bus->sprom.antenna_gain.ghz24.a0 - - 0x6, max_pwr); - - /* find the desired power in Q5.2 - power_level is in dBm - * and limit it - max_pwr is already in Q5.2 */ - desired_pwr = clamp_val(phy->power_level << 2, 0, max_pwr); - if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER)) - b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT - " dBm, Desired TX power output: " Q52_FMT - " dBm\n", Q52_ARG(estimated_pwr), - Q52_ARG(desired_pwr)); - /* Check if we need to adjust the current power. The factor of 2 is - * for damping */ - pwr_adjust = (desired_pwr - estimated_pwr) / 2; - /* RF attenuation delta - * The minus sign is because lower attenuation => more power */ - radio_att_delta = -(pwr_adjust + 7) >> 3; - /* Baseband attenuation delta */ - baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); - /* Do we need to adjust anything? */ - if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { - b43legacy_phy_lo_mark_current_used(dev); - return; - } - - /* Calculate the new attenuation values. */ - baseband_attenuation = phy->bbatt; - baseband_attenuation += baseband_att_delta; - radio_attenuation = phy->rfatt; - radio_attenuation += radio_att_delta; - - /* Get baseband and radio attenuation values into permitted ranges. - * baseband 0-11, radio 0-9. - * Radio attenuation affects power level 4 times as much as baseband. - */ - if (radio_attenuation < 0) { - baseband_attenuation -= (4 * -radio_attenuation); - radio_attenuation = 0; - } else if (radio_attenuation > 9) { - baseband_attenuation += (4 * (radio_attenuation - 9)); - radio_attenuation = 9; - } else { - while (baseband_attenuation < 0 && radio_attenuation > 0) { - baseband_attenuation += 4; - radio_attenuation--; - } - while (baseband_attenuation > 11 && radio_attenuation < 9) { - baseband_attenuation -= 4; - radio_attenuation++; - } - } - baseband_attenuation = clamp_val(baseband_attenuation, 0, 11); - - txpower = phy->txctl1; - if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) { - if (radio_attenuation <= 1) { - if (txpower == 0) { - txpower = 3; - radio_attenuation += 2; - baseband_attenuation += 2; - } else if (dev->dev->bus->sprom.boardflags_lo - & B43legacy_BFL_PACTRL) { - baseband_attenuation += 4 * - (radio_attenuation - 2); - radio_attenuation = 2; - } - } else if (radio_attenuation > 4 && txpower != 0) { - txpower = 0; - if (baseband_attenuation < 3) { - radio_attenuation -= 3; - baseband_attenuation += 2; - } else { - radio_attenuation -= 2; - baseband_attenuation -= 2; - } - } - } - /* Save the control values */ - phy->txctl1 = txpower; - baseband_attenuation = clamp_val(baseband_attenuation, 0, 11); - radio_attenuation = clamp_val(radio_attenuation, 0, 9); - phy->rfatt = radio_attenuation; - phy->bbatt = baseband_attenuation; - - /* Adjust the hardware */ - b43legacy_phy_lock(dev); - b43legacy_radio_lock(dev); - b43legacy_radio_set_txpower_bg(dev, baseband_attenuation, - radio_attenuation, txpower); - b43legacy_phy_lo_mark_current_used(dev); - b43legacy_radio_unlock(dev); - b43legacy_phy_unlock(dev); -} - -static inline -s32 b43legacy_tssi2dbm_ad(s32 num, s32 den) -{ - if (num < 0) - return num/den; - else - return (num+den/2)/den; -} - -static inline -s8 b43legacy_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) -{ - s32 m1; - s32 m2; - s32 f = 256; - s32 q; - s32 delta; - s8 i = 0; - - m1 = b43legacy_tssi2dbm_ad(16 * pab0 + index * pab1, 32); - m2 = max(b43legacy_tssi2dbm_ad(32768 + index * pab2, 256), 1); - do { - if (i > 15) - return -EINVAL; - q = b43legacy_tssi2dbm_ad(f * 4096 - - b43legacy_tssi2dbm_ad(m2 * f, 16) * - f, 2048); - delta = abs(q - f); - f = q; - i++; - } while (delta >= 2); - entry[index] = clamp_val(b43legacy_tssi2dbm_ad(m1 * f, 8192), - -127, 128); - return 0; -} - -/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ -int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - s16 pab0; - s16 pab1; - s16 pab2; - u8 idx; - s8 *dyn_tssi2dbm; - - B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B || - phy->type == B43legacy_PHYTYPE_G)); - pab0 = (s16)(dev->dev->bus->sprom.pa0b0); - pab1 = (s16)(dev->dev->bus->sprom.pa0b1); - pab2 = (s16)(dev->dev->bus->sprom.pa0b2); - - if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) { - phy->idle_tssi = 0x34; - phy->tssi2dbm = b43legacy_tssi2dbm_b_table; - return 0; - } - - if (pab0 != 0 && pab1 != 0 && pab2 != 0 && - pab0 != -1 && pab1 != -1 && pab2 != -1) { - /* The pabX values are set in SPROM. Use them. */ - if ((s8)dev->dev->bus->sprom.itssi_bg != 0 && - (s8)dev->dev->bus->sprom.itssi_bg != -1) - phy->idle_tssi = (s8)(dev->dev->bus->sprom. - itssi_bg); - else - phy->idle_tssi = 62; - dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); - if (dyn_tssi2dbm == NULL) { - b43legacyerr(dev->wl, "Could not allocate memory " - "for tssi2dbm table\n"); - return -ENOMEM; - } - for (idx = 0; idx < 64; idx++) - if (b43legacy_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, - pab1, pab2)) { - phy->tssi2dbm = NULL; - b43legacyerr(dev->wl, "Could not generate " - "tssi2dBm table\n"); - kfree(dyn_tssi2dbm); - return -ENODEV; - } - phy->tssi2dbm = dyn_tssi2dbm; - phy->dyn_tssi_tbl = 1; - } else { - /* pabX values not set in SPROM. */ - switch (phy->type) { - case B43legacy_PHYTYPE_B: - phy->idle_tssi = 0x34; - phy->tssi2dbm = b43legacy_tssi2dbm_b_table; - break; - case B43legacy_PHYTYPE_G: - phy->idle_tssi = 0x34; - phy->tssi2dbm = b43legacy_tssi2dbm_g_table; - break; - } - } - - return 0; -} - -int b43legacy_phy_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - int err = -ENODEV; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - switch (phy->rev) { - case 2: - b43legacy_phy_initb2(dev); - err = 0; - break; - case 4: - b43legacy_phy_initb4(dev); - err = 0; - break; - case 5: - b43legacy_phy_initb5(dev); - err = 0; - break; - case 6: - b43legacy_phy_initb6(dev); - err = 0; - break; - } - break; - case B43legacy_PHYTYPE_G: - b43legacy_phy_initg(dev); - err = 0; - break; - } - if (err) - b43legacyerr(dev->wl, "Unknown PHYTYPE found\n"); - - return err; -} - -void b43legacy_phy_set_antenna_diversity(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 antennadiv; - u16 offset; - u16 value; - u32 ucodeflags; - - antennadiv = phy->antenna_diversity; - - if (antennadiv == 0xFFFF) - antennadiv = 3; - B43legacy_WARN_ON(antennadiv > 3); - - ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET); - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - ucodeflags & ~B43legacy_UCODEFLAG_AUTODIV); - - switch (phy->type) { - case B43legacy_PHYTYPE_G: - offset = 0x0400; - - if (antennadiv == 2) - value = (3/*automatic*/ << 7); - else - value = (antennadiv << 7); - b43legacy_phy_write(dev, offset + 1, - (b43legacy_phy_read(dev, offset + 1) - & 0x7E7F) | value); - - if (antennadiv >= 2) { - if (antennadiv == 2) - value = (antennadiv << 7); - else - value = (0/*force0*/ << 7); - b43legacy_phy_write(dev, offset + 0x2B, - (b43legacy_phy_read(dev, - offset + 0x2B) - & 0xFEFF) | value); - } - - if (phy->type == B43legacy_PHYTYPE_G) { - if (antennadiv >= 2) - b43legacy_phy_write(dev, 0x048C, - b43legacy_phy_read(dev, - 0x048C) | 0x2000); - else - b43legacy_phy_write(dev, 0x048C, - b43legacy_phy_read(dev, - 0x048C) & ~0x2000); - if (phy->rev >= 2) { - b43legacy_phy_write(dev, 0x0461, - b43legacy_phy_read(dev, - 0x0461) | 0x0010); - b43legacy_phy_write(dev, 0x04AD, - (b43legacy_phy_read(dev, - 0x04AD) - & 0x00FF) | 0x0015); - if (phy->rev == 2) - b43legacy_phy_write(dev, 0x0427, - 0x0008); - else - b43legacy_phy_write(dev, 0x0427, - (b43legacy_phy_read(dev, 0x0427) - & 0x00FF) | 0x0008); - } else if (phy->rev >= 6) - b43legacy_phy_write(dev, 0x049B, 0x00DC); - } else { - if (phy->rev < 3) - b43legacy_phy_write(dev, 0x002B, - (b43legacy_phy_read(dev, - 0x002B) & 0x00FF) - | 0x0024); - else { - b43legacy_phy_write(dev, 0x0061, - b43legacy_phy_read(dev, - 0x0061) | 0x0010); - if (phy->rev == 3) { - b43legacy_phy_write(dev, 0x0093, - 0x001D); - b43legacy_phy_write(dev, 0x0027, - 0x0008); - } else { - b43legacy_phy_write(dev, 0x0093, - 0x003A); - b43legacy_phy_write(dev, 0x0027, - (b43legacy_phy_read(dev, 0x0027) - & 0x00FF) | 0x0008); - } - } - } - break; - case B43legacy_PHYTYPE_B: - if (dev->dev->id.revision == 2) - value = (3/*automatic*/ << 7); - else - value = (antennadiv << 7); - b43legacy_phy_write(dev, 0x03E2, - (b43legacy_phy_read(dev, 0x03E2) - & 0xFE7F) | value); - break; - default: - B43legacy_WARN_ON(1); - } - - if (antennadiv >= 2) { - ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET); - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - ucodeflags | B43legacy_UCODEFLAG_AUTODIV); - } - - phy->antenna_diversity = antennadiv; -} - -/* Set the PowerSavingControlBits. - * Bitvalues: - * 0 => unset the bit - * 1 => set the bit - * -1 => calculate the bit - */ -void b43legacy_power_saving_ctl_bits(struct b43legacy_wldev *dev, - int bit25, int bit26) -{ - int i; - u32 status; - -/* FIXME: Force 25 to off and 26 to on for now: */ -bit25 = 0; -bit26 = 1; - - if (bit25 == -1) { - /* TODO: If powersave is not off and FIXME is not set and we - * are not in adhoc and thus is not an AP and we arei - * associated, set bit 25 */ - } - if (bit26 == -1) { - /* TODO: If the device is awake or this is an AP, or we are - * scanning, or FIXME, or we are associated, or FIXME, - * or the latest PS-Poll packet sent was successful, - * set bit26 */ - } - status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - if (bit25) - status |= B43legacy_MACCTL_HWPS; - else - status &= ~B43legacy_MACCTL_HWPS; - if (bit26) - status |= B43legacy_MACCTL_AWAKE; - else - status &= ~B43legacy_MACCTL_AWAKE; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - if (bit26 && dev->dev->id.revision >= 5) { - for (i = 0; i < 100; i++) { - if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, - 0x0040) != 4) - break; - udelay(10); - } - } -} diff --git a/drivers/net/wireless/b43legacy/phy.h b/drivers/net/wireless/b43legacy/phy.h deleted file mode 100644 index ecbe409f9a94..000000000000 --- a/drivers/net/wireless/b43legacy/phy.h +++ /dev/null @@ -1,209 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - Copyright (c) 2007 Larry Finger - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef B43legacy_PHY_H_ -#define B43legacy_PHY_H_ - -#include - -enum { - B43legacy_ANTENNA0, /* Antenna 0 */ - B43legacy_ANTENNA1, /* Antenna 0 */ - B43legacy_ANTENNA_AUTO1, /* Automatic, starting with antenna 1 */ - B43legacy_ANTENNA_AUTO0, /* Automatic, starting with antenna 0 */ - - B43legacy_ANTENNA_AUTO = B43legacy_ANTENNA_AUTO0, - B43legacy_ANTENNA_DEFAULT = B43legacy_ANTENNA_AUTO, -}; - -enum { - B43legacy_INTERFMODE_NONE, - B43legacy_INTERFMODE_NONWLAN, - B43legacy_INTERFMODE_MANUALWLAN, - B43legacy_INTERFMODE_AUTOWLAN, -}; - -/*** PHY Registers ***/ - -/* Routing */ -#define B43legacy_PHYROUTE_OFDM_GPHY 0x400 -#define B43legacy_PHYROUTE_EXT_GPHY 0x800 - -/* Base registers. */ -#define B43legacy_PHY_BASE(reg) (reg) -/* OFDM (A) registers of a G-PHY */ -#define B43legacy_PHY_OFDM(reg) ((reg) | B43legacy_PHYROUTE_OFDM_GPHY) -/* Extended G-PHY registers */ -#define B43legacy_PHY_EXTG(reg) ((reg) | B43legacy_PHYROUTE_EXT_GPHY) - - -/* Extended G-PHY Registers */ -#define B43legacy_PHY_CLASSCTL B43legacy_PHY_EXTG(0x02) /* Classify control */ -#define B43legacy_PHY_GTABCTL B43legacy_PHY_EXTG(0x03) /* G-PHY table control (see below) */ -#define B43legacy_PHY_GTABOFF 0x03FF /* G-PHY table offset (see below) */ -#define B43legacy_PHY_GTABNR 0xFC00 /* G-PHY table number (see below) */ -#define B43legacy_PHY_GTABNR_SHIFT 10 -#define B43legacy_PHY_GTABDATA B43legacy_PHY_EXTG(0x04) /* G-PHY table data */ -#define B43legacy_PHY_LO_MASK B43legacy_PHY_EXTG(0x0F) /* Local Oscillator control mask */ -#define B43legacy_PHY_LO_CTL B43legacy_PHY_EXTG(0x10) /* Local Oscillator control */ -#define B43legacy_PHY_RFOVER B43legacy_PHY_EXTG(0x11) /* RF override */ -#define B43legacy_PHY_RFOVERVAL B43legacy_PHY_EXTG(0x12) /* RF override value */ -/*** OFDM table numbers ***/ -#define B43legacy_OFDMTAB(number, offset) \ - (((number) << B43legacy_PHY_OTABLENR_SHIFT) \ - | (offset)) -#define B43legacy_OFDMTAB_AGC1 B43legacy_OFDMTAB(0x00, 0) -#define B43legacy_OFDMTAB_GAIN0 B43legacy_OFDMTAB(0x00, 0) -#define B43legacy_OFDMTAB_GAINX B43legacy_OFDMTAB(0x01, 0) -#define B43legacy_OFDMTAB_GAIN1 B43legacy_OFDMTAB(0x01, 4) -#define B43legacy_OFDMTAB_AGC3 B43legacy_OFDMTAB(0x02, 0) -#define B43legacy_OFDMTAB_GAIN2 B43legacy_OFDMTAB(0x02, 3) -#define B43legacy_OFDMTAB_LNAHPFGAIN1 B43legacy_OFDMTAB(0x03, 0) -#define B43legacy_OFDMTAB_WRSSI B43legacy_OFDMTAB(0x04, 0) -#define B43legacy_OFDMTAB_LNAHPFGAIN2 B43legacy_OFDMTAB(0x04, 0) -#define B43legacy_OFDMTAB_NOISESCALE B43legacy_OFDMTAB(0x05, 0) -#define B43legacy_OFDMTAB_AGC2 B43legacy_OFDMTAB(0x06, 0) -#define B43legacy_OFDMTAB_ROTOR B43legacy_OFDMTAB(0x08, 0) -#define B43legacy_OFDMTAB_ADVRETARD B43legacy_OFDMTAB(0x09, 0) -#define B43legacy_OFDMTAB_DAC B43legacy_OFDMTAB(0x0C, 0) -#define B43legacy_OFDMTAB_DC B43legacy_OFDMTAB(0x0E, 7) -#define B43legacy_OFDMTAB_PWRDYN2 B43legacy_OFDMTAB(0x0E, 12) -#define B43legacy_OFDMTAB_LNAGAIN B43legacy_OFDMTAB(0x0E, 13) - -#define B43legacy_OFDMTAB_LPFGAIN B43legacy_OFDMTAB(0x0F, 12) -#define B43legacy_OFDMTAB_RSSI B43legacy_OFDMTAB(0x10, 0) - -#define B43legacy_OFDMTAB_AGC1_R1 B43legacy_OFDMTAB(0x13, 0) -#define B43legacy_OFDMTAB_GAINX_R1 B43legacy_OFDMTAB(0x14, 0) -#define B43legacy_OFDMTAB_MINSIGSQ B43legacy_OFDMTAB(0x14, 1) -#define B43legacy_OFDMTAB_AGC3_R1 B43legacy_OFDMTAB(0x15, 0) -#define B43legacy_OFDMTAB_WRSSI_R1 B43legacy_OFDMTAB(0x15, 4) -#define B43legacy_OFDMTAB_TSSI B43legacy_OFDMTAB(0x15, 0) -#define B43legacy_OFDMTAB_DACRFPABB B43legacy_OFDMTAB(0x16, 0) -#define B43legacy_OFDMTAB_DACOFF B43legacy_OFDMTAB(0x17, 0) -#define B43legacy_OFDMTAB_DCBIAS B43legacy_OFDMTAB(0x18, 0) - -void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt); - -/* OFDM (A) PHY Registers */ -#define B43legacy_PHY_VERSION_OFDM B43legacy_PHY_OFDM(0x00) /* Versioning register for A-PHY */ -#define B43legacy_PHY_BBANDCFG B43legacy_PHY_OFDM(0x01) /* Baseband config */ -#define B43legacy_PHY_BBANDCFG_RXANT 0x180 /* RX Antenna selection */ -#define B43legacy_PHY_BBANDCFG_RXANT_SHIFT 7 -#define B43legacy_PHY_PWRDOWN B43legacy_PHY_OFDM(0x03) /* Powerdown */ -#define B43legacy_PHY_CRSTHRES1 B43legacy_PHY_OFDM(0x06) /* CRS Threshold 1 */ -#define B43legacy_PHY_LNAHPFCTL B43legacy_PHY_OFDM(0x1C) /* LNA/HPF control */ -#define B43legacy_PHY_ADIVRELATED B43legacy_PHY_OFDM(0x27) /* FIXME rename */ -#define B43legacy_PHY_CRS0 B43legacy_PHY_OFDM(0x29) -#define B43legacy_PHY_ANTDWELL B43legacy_PHY_OFDM(0x2B) /* Antenna dwell */ -#define B43legacy_PHY_ANTDWELL_AUTODIV1 0x0100 /* Automatic RX diversity start antenna */ -#define B43legacy_PHY_ENCORE B43legacy_PHY_OFDM(0x49) /* "Encore" (RangeMax / BroadRange) */ -#define B43legacy_PHY_ENCORE_EN 0x0200 /* Encore enable */ -#define B43legacy_PHY_LMS B43legacy_PHY_OFDM(0x55) -#define B43legacy_PHY_OFDM61 B43legacy_PHY_OFDM(0x61) /* FIXME rename */ -#define B43legacy_PHY_OFDM61_10 0x0010 /* FIXME rename */ -#define B43legacy_PHY_IQBAL B43legacy_PHY_OFDM(0x69) /* I/Q balance */ -#define B43legacy_PHY_OTABLECTL B43legacy_PHY_OFDM(0x72) /* OFDM table control (see below) */ -#define B43legacy_PHY_OTABLEOFF 0x03FF /* OFDM table offset (see below) */ -#define B43legacy_PHY_OTABLENR 0xFC00 /* OFDM table number (see below) */ -#define B43legacy_PHY_OTABLENR_SHIFT 10 -#define B43legacy_PHY_OTABLEI B43legacy_PHY_OFDM(0x73) /* OFDM table data I */ -#define B43legacy_PHY_OTABLEQ B43legacy_PHY_OFDM(0x74) /* OFDM table data Q */ -#define B43legacy_PHY_HPWR_TSSICTL B43legacy_PHY_OFDM(0x78) /* Hardware power TSSI control */ -#define B43legacy_PHY_NRSSITHRES B43legacy_PHY_OFDM(0x8A) /* NRSSI threshold */ -#define B43legacy_PHY_ANTWRSETT B43legacy_PHY_OFDM(0x8C) /* Antenna WR settle */ -#define B43legacy_PHY_ANTWRSETT_ARXDIV 0x2000 /* Automatic RX diversity enabled */ -#define B43legacy_PHY_CLIPPWRDOWNT B43legacy_PHY_OFDM(0x93) /* Clip powerdown threshold */ -#define B43legacy_PHY_OFDM9B B43legacy_PHY_OFDM(0x9B) /* FIXME rename */ -#define B43legacy_PHY_N1P1GAIN B43legacy_PHY_OFDM(0xA0) -#define B43legacy_PHY_P1P2GAIN B43legacy_PHY_OFDM(0xA1) -#define B43legacy_PHY_N1N2GAIN B43legacy_PHY_OFDM(0xA2) -#define B43legacy_PHY_CLIPTHRES B43legacy_PHY_OFDM(0xA3) -#define B43legacy_PHY_CLIPN1P2THRES B43legacy_PHY_OFDM(0xA4) -#define B43legacy_PHY_DIVSRCHIDX B43legacy_PHY_OFDM(0xA8) /* Divider search gain/index */ -#define B43legacy_PHY_CLIPP2THRES B43legacy_PHY_OFDM(0xA9) -#define B43legacy_PHY_CLIPP3THRES B43legacy_PHY_OFDM(0xAA) -#define B43legacy_PHY_DIVP1P2GAIN B43legacy_PHY_OFDM(0xAB) -#define B43legacy_PHY_DIVSRCHGAINBACK B43legacy_PHY_OFDM(0xAD) /* Divider search gain back */ -#define B43legacy_PHY_DIVSRCHGAINCHNG B43legacy_PHY_OFDM(0xAE) /* Divider search gain change */ -#define B43legacy_PHY_CRSTHRES1_R1 B43legacy_PHY_OFDM(0xC0) /* CRS Threshold 1 (rev 1 only) */ -#define B43legacy_PHY_CRSTHRES2_R1 B43legacy_PHY_OFDM(0xC1) /* CRS Threshold 2 (rev 1 only) */ -#define B43legacy_PHY_TSSIP_LTBASE B43legacy_PHY_OFDM(0x380) /* TSSI power lookup table base */ -#define B43legacy_PHY_DC_LTBASE B43legacy_PHY_OFDM(0x3A0) /* DC lookup table base */ -#define B43legacy_PHY_GAIN_LTBASE B43legacy_PHY_OFDM(0x3C0) /* Gain lookup table base */ - -void b43legacy_put_attenuation_into_ranges(int *_bbatt, int *_rfatt); - -/* Masks for the different PHY versioning registers. */ -#define B43legacy_PHYVER_ANALOG 0xF000 -#define B43legacy_PHYVER_ANALOG_SHIFT 12 -#define B43legacy_PHYVER_TYPE 0x0F00 -#define B43legacy_PHYVER_TYPE_SHIFT 8 -#define B43legacy_PHYVER_VERSION 0x00FF - -struct b43legacy_wldev; - -void b43legacy_phy_lock(struct b43legacy_wldev *dev); -void b43legacy_phy_unlock(struct b43legacy_wldev *dev); - -/* Card uses the loopback gain stuff */ -#define has_loopback_gain(phy) \ - (((phy)->rev > 1) || ((phy)->gmode)) - -u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset); -void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val); - -int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev); -int b43legacy_phy_init(struct b43legacy_wldev *dev); - -void b43legacy_set_rx_antenna(struct b43legacy_wldev *dev, int antenna); - -void b43legacy_phy_set_antenna_diversity(struct b43legacy_wldev *dev); -void b43legacy_phy_calibrate(struct b43legacy_wldev *dev); -int b43legacy_phy_connect(struct b43legacy_wldev *dev, int connect); - -void b43legacy_phy_lo_b_measure(struct b43legacy_wldev *dev); -void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev); -void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev); - -/* Adjust the LocalOscillator to the saved values. - * "fixed" is only set to 1 once in initialization. Set to 0 otherwise. - */ -void b43legacy_phy_lo_adjust(struct b43legacy_wldev *dev, int fixed); -void b43legacy_phy_lo_mark_all_unused(struct b43legacy_wldev *dev); - -void b43legacy_phy_set_baseband_attenuation(struct b43legacy_wldev *dev, - u16 baseband_attenuation); - -void b43legacy_power_saving_ctl_bits(struct b43legacy_wldev *dev, - int bit25, int bit26); - -#endif /* B43legacy_PHY_H_ */ diff --git a/drivers/net/wireless/b43legacy/pio.c b/drivers/net/wireless/b43legacy/pio.c deleted file mode 100644 index 51866c9a2769..000000000000 --- a/drivers/net/wireless/b43legacy/pio.c +++ /dev/null @@ -1,707 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - PIO Transmission - - Copyright (c) 2005 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "b43legacy.h" -#include "pio.h" -#include "main.h" -#include "xmit.h" - -#include - - -static void tx_start(struct b43legacy_pioqueue *queue) -{ - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - B43legacy_PIO_TXCTL_INIT); -} - -static void tx_octet(struct b43legacy_pioqueue *queue, - u8 octet) -{ - if (queue->need_workarounds) { - b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, octet); - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - B43legacy_PIO_TXCTL_WRITELO); - } else { - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - B43legacy_PIO_TXCTL_WRITELO); - b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, octet); - } -} - -static u16 tx_get_next_word(const u8 *txhdr, - const u8 *packet, - size_t txhdr_size, - unsigned int *pos) -{ - const u8 *source; - unsigned int i = *pos; - u16 ret; - - if (i < txhdr_size) - source = txhdr; - else { - source = packet; - i -= txhdr_size; - } - ret = le16_to_cpu(*((__le16 *)(source + i))); - *pos += 2; - - return ret; -} - -static void tx_data(struct b43legacy_pioqueue *queue, - u8 *txhdr, - const u8 *packet, - unsigned int octets) -{ - u16 data; - unsigned int i = 0; - - if (queue->need_workarounds) { - data = tx_get_next_word(txhdr, packet, - sizeof(struct b43legacy_txhdr_fw3), &i); - b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, data); - } - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - B43legacy_PIO_TXCTL_WRITELO | - B43legacy_PIO_TXCTL_WRITEHI); - while (i < octets - 1) { - data = tx_get_next_word(txhdr, packet, - sizeof(struct b43legacy_txhdr_fw3), &i); - b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, data); - } - if (octets % 2) - tx_octet(queue, packet[octets - - sizeof(struct b43legacy_txhdr_fw3) - 1]); -} - -static void tx_complete(struct b43legacy_pioqueue *queue, - struct sk_buff *skb) -{ - if (queue->need_workarounds) { - b43legacy_pio_write(queue, B43legacy_PIO_TXDATA, - skb->data[skb->len - 1]); - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - B43legacy_PIO_TXCTL_WRITELO | - B43legacy_PIO_TXCTL_COMPLETE); - } else - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - B43legacy_PIO_TXCTL_COMPLETE); -} - -static u16 generate_cookie(struct b43legacy_pioqueue *queue, - struct b43legacy_pio_txpacket *packet) -{ - u16 cookie = 0x0000; - int packetindex; - - /* We use the upper 4 bits for the PIO - * controller ID and the lower 12 bits - * for the packet index (in the cache). - */ - switch (queue->mmio_base) { - case B43legacy_MMIO_PIO1_BASE: - break; - case B43legacy_MMIO_PIO2_BASE: - cookie = 0x1000; - break; - case B43legacy_MMIO_PIO3_BASE: - cookie = 0x2000; - break; - case B43legacy_MMIO_PIO4_BASE: - cookie = 0x3000; - break; - default: - B43legacy_WARN_ON(1); - } - packetindex = pio_txpacket_getindex(packet); - B43legacy_WARN_ON(!(((u16)packetindex & 0xF000) == 0x0000)); - cookie |= (u16)packetindex; - - return cookie; -} - -static -struct b43legacy_pioqueue *parse_cookie(struct b43legacy_wldev *dev, - u16 cookie, - struct b43legacy_pio_txpacket **packet) -{ - struct b43legacy_pio *pio = &dev->pio; - struct b43legacy_pioqueue *queue = NULL; - int packetindex; - - switch (cookie & 0xF000) { - case 0x0000: - queue = pio->queue0; - break; - case 0x1000: - queue = pio->queue1; - break; - case 0x2000: - queue = pio->queue2; - break; - case 0x3000: - queue = pio->queue3; - break; - default: - B43legacy_WARN_ON(1); - } - packetindex = (cookie & 0x0FFF); - B43legacy_WARN_ON(!(packetindex >= 0 && packetindex - < B43legacy_PIO_MAXTXPACKETS)); - *packet = &(queue->tx_packets_cache[packetindex]); - - return queue; -} - -union txhdr_union { - struct b43legacy_txhdr_fw3 txhdr_fw3; -}; - -static int pio_tx_write_fragment(struct b43legacy_pioqueue *queue, - struct sk_buff *skb, - struct b43legacy_pio_txpacket *packet, - size_t txhdr_size) -{ - union txhdr_union txhdr_data; - u8 *txhdr = NULL; - unsigned int octets; - int err; - - txhdr = (u8 *)(&txhdr_data.txhdr_fw3); - - B43legacy_WARN_ON(skb_shinfo(skb)->nr_frags != 0); - err = b43legacy_generate_txhdr(queue->dev, - txhdr, skb->data, skb->len, - IEEE80211_SKB_CB(skb), - generate_cookie(queue, packet)); - if (err) - return err; - - tx_start(queue); - octets = skb->len + txhdr_size; - if (queue->need_workarounds) - octets--; - tx_data(queue, txhdr, (u8 *)skb->data, octets); - tx_complete(queue, skb); - - return 0; -} - -static void free_txpacket(struct b43legacy_pio_txpacket *packet, - int irq_context) -{ - struct b43legacy_pioqueue *queue = packet->queue; - - if (packet->skb) { - if (irq_context) - dev_kfree_skb_irq(packet->skb); - else - dev_kfree_skb(packet->skb); - } - list_move(&packet->list, &queue->txfree); - queue->nr_txfree++; -} - -static int pio_tx_packet(struct b43legacy_pio_txpacket *packet) -{ - struct b43legacy_pioqueue *queue = packet->queue; - struct sk_buff *skb = packet->skb; - u16 octets; - int err; - - octets = (u16)skb->len + sizeof(struct b43legacy_txhdr_fw3); - if (queue->tx_devq_size < octets) { - b43legacywarn(queue->dev->wl, "PIO queue too small. " - "Dropping packet.\n"); - /* Drop it silently (return success) */ - free_txpacket(packet, 1); - return 0; - } - B43legacy_WARN_ON(queue->tx_devq_packets > - B43legacy_PIO_MAXTXDEVQPACKETS); - B43legacy_WARN_ON(queue->tx_devq_used > queue->tx_devq_size); - /* Check if there is sufficient free space on the device - * TX queue. If not, return and let the TX tasklet - * retry later. - */ - if (queue->tx_devq_packets == B43legacy_PIO_MAXTXDEVQPACKETS) - return -EBUSY; - if (queue->tx_devq_used + octets > queue->tx_devq_size) - return -EBUSY; - /* Now poke the device. */ - err = pio_tx_write_fragment(queue, skb, packet, - sizeof(struct b43legacy_txhdr_fw3)); - if (unlikely(err == -ENOKEY)) { - /* Drop this packet, as we don't have the encryption key - * anymore and must not transmit it unencrypted. */ - free_txpacket(packet, 1); - return 0; - } - - /* Account for the packet size. - * (We must not overflow the device TX queue) - */ - queue->tx_devq_packets++; - queue->tx_devq_used += octets; - - /* Transmission started, everything ok, move the - * packet to the txrunning list. - */ - list_move_tail(&packet->list, &queue->txrunning); - - return 0; -} - -static void tx_tasklet(unsigned long d) -{ - struct b43legacy_pioqueue *queue = (struct b43legacy_pioqueue *)d; - struct b43legacy_wldev *dev = queue->dev; - unsigned long flags; - struct b43legacy_pio_txpacket *packet, *tmp_packet; - int err; - u16 txctl; - - spin_lock_irqsave(&dev->wl->irq_lock, flags); - if (queue->tx_frozen) - goto out_unlock; - txctl = b43legacy_pio_read(queue, B43legacy_PIO_TXCTL); - if (txctl & B43legacy_PIO_TXCTL_SUSPEND) - goto out_unlock; - - list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { - /* Try to transmit the packet. This can fail, if - * the device queue is full. In case of failure, the - * packet is left in the txqueue. - * If transmission succeed, the packet is moved to txrunning. - * If it is impossible to transmit the packet, it - * is dropped. - */ - err = pio_tx_packet(packet); - if (err) - break; - } -out_unlock: - spin_unlock_irqrestore(&dev->wl->irq_lock, flags); -} - -static void setup_txqueues(struct b43legacy_pioqueue *queue) -{ - struct b43legacy_pio_txpacket *packet; - int i; - - queue->nr_txfree = B43legacy_PIO_MAXTXPACKETS; - for (i = 0; i < B43legacy_PIO_MAXTXPACKETS; i++) { - packet = &(queue->tx_packets_cache[i]); - - packet->queue = queue; - INIT_LIST_HEAD(&packet->list); - - list_add(&packet->list, &queue->txfree); - } -} - -static -struct b43legacy_pioqueue *b43legacy_setup_pioqueue(struct b43legacy_wldev *dev, - u16 pio_mmio_base) -{ - struct b43legacy_pioqueue *queue; - u32 value; - u16 qsize; - - queue = kzalloc(sizeof(*queue), GFP_KERNEL); - if (!queue) - goto out; - - queue->dev = dev; - queue->mmio_base = pio_mmio_base; - queue->need_workarounds = (dev->dev->id.revision < 3); - - INIT_LIST_HEAD(&queue->txfree); - INIT_LIST_HEAD(&queue->txqueue); - INIT_LIST_HEAD(&queue->txrunning); - tasklet_init(&queue->txtask, tx_tasklet, - (unsigned long)queue); - - value = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - value &= ~B43legacy_MACCTL_BE; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, value); - - qsize = b43legacy_read16(dev, queue->mmio_base - + B43legacy_PIO_TXQBUFSIZE); - if (qsize == 0) { - b43legacyerr(dev->wl, "This card does not support PIO " - "operation mode. Please use DMA mode " - "(module parameter pio=0).\n"); - goto err_freequeue; - } - if (qsize <= B43legacy_PIO_TXQADJUST) { - b43legacyerr(dev->wl, "PIO tx device-queue too small (%u)\n", - qsize); - goto err_freequeue; - } - qsize -= B43legacy_PIO_TXQADJUST; - queue->tx_devq_size = qsize; - - setup_txqueues(queue); - -out: - return queue; - -err_freequeue: - kfree(queue); - queue = NULL; - goto out; -} - -static void cancel_transfers(struct b43legacy_pioqueue *queue) -{ - struct b43legacy_pio_txpacket *packet, *tmp_packet; - - tasklet_disable(&queue->txtask); - - list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) - free_txpacket(packet, 0); - list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) - free_txpacket(packet, 0); -} - -static void b43legacy_destroy_pioqueue(struct b43legacy_pioqueue *queue) -{ - if (!queue) - return; - - cancel_transfers(queue); - kfree(queue); -} - -void b43legacy_pio_free(struct b43legacy_wldev *dev) -{ - struct b43legacy_pio *pio; - - if (!b43legacy_using_pio(dev)) - return; - pio = &dev->pio; - - b43legacy_destroy_pioqueue(pio->queue3); - pio->queue3 = NULL; - b43legacy_destroy_pioqueue(pio->queue2); - pio->queue2 = NULL; - b43legacy_destroy_pioqueue(pio->queue1); - pio->queue1 = NULL; - b43legacy_destroy_pioqueue(pio->queue0); - pio->queue0 = NULL; -} - -int b43legacy_pio_init(struct b43legacy_wldev *dev) -{ - struct b43legacy_pio *pio = &dev->pio; - struct b43legacy_pioqueue *queue; - int err = -ENOMEM; - - queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO1_BASE); - if (!queue) - goto out; - pio->queue0 = queue; - - queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO2_BASE); - if (!queue) - goto err_destroy0; - pio->queue1 = queue; - - queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO3_BASE); - if (!queue) - goto err_destroy1; - pio->queue2 = queue; - - queue = b43legacy_setup_pioqueue(dev, B43legacy_MMIO_PIO4_BASE); - if (!queue) - goto err_destroy2; - pio->queue3 = queue; - - if (dev->dev->id.revision < 3) - dev->irq_mask |= B43legacy_IRQ_PIO_WORKAROUND; - - b43legacydbg(dev->wl, "PIO initialized\n"); - err = 0; -out: - return err; - -err_destroy2: - b43legacy_destroy_pioqueue(pio->queue2); - pio->queue2 = NULL; -err_destroy1: - b43legacy_destroy_pioqueue(pio->queue1); - pio->queue1 = NULL; -err_destroy0: - b43legacy_destroy_pioqueue(pio->queue0); - pio->queue0 = NULL; - goto out; -} - -int b43legacy_pio_tx(struct b43legacy_wldev *dev, - struct sk_buff *skb) -{ - struct b43legacy_pioqueue *queue = dev->pio.queue1; - struct b43legacy_pio_txpacket *packet; - - B43legacy_WARN_ON(queue->tx_suspended); - B43legacy_WARN_ON(list_empty(&queue->txfree)); - - packet = list_entry(queue->txfree.next, struct b43legacy_pio_txpacket, - list); - packet->skb = skb; - - list_move_tail(&packet->list, &queue->txqueue); - queue->nr_txfree--; - queue->nr_tx_packets++; - B43legacy_WARN_ON(queue->nr_txfree >= B43legacy_PIO_MAXTXPACKETS); - - tasklet_schedule(&queue->txtask); - - return 0; -} - -void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) -{ - struct b43legacy_pioqueue *queue; - struct b43legacy_pio_txpacket *packet; - struct ieee80211_tx_info *info; - int retry_limit; - - queue = parse_cookie(dev, status->cookie, &packet); - B43legacy_WARN_ON(!queue); - - if (!packet->skb) - return; - - queue->tx_devq_packets--; - queue->tx_devq_used -= (packet->skb->len + - sizeof(struct b43legacy_txhdr_fw3)); - - info = IEEE80211_SKB_CB(packet->skb); - - /* preserve the confiured retry limit before clearing the status - * The xmit function has overwritten the rc's value with the actual - * retry limit done by the hardware */ - retry_limit = info->status.rates[0].count; - ieee80211_tx_info_clear_status(info); - - if (status->acked) - info->flags |= IEEE80211_TX_STAT_ACK; - - if (status->rts_count > dev->wl->hw->conf.short_frame_max_tx_count) { - /* - * If the short retries (RTS, not data frame) have exceeded - * the limit, the hw will not have tried the selected rate, - * but will have used the fallback rate instead. - * Don't let the rate control count attempts for the selected - * rate in this case, otherwise the statistics will be off. - */ - info->status.rates[0].count = 0; - info->status.rates[1].count = status->frame_count; - } else { - if (status->frame_count > retry_limit) { - info->status.rates[0].count = retry_limit; - info->status.rates[1].count = status->frame_count - - retry_limit; - - } else { - info->status.rates[0].count = status->frame_count; - info->status.rates[1].idx = -1; - } - } - ieee80211_tx_status_irqsafe(dev->wl->hw, packet->skb); - packet->skb = NULL; - - free_txpacket(packet, 1); - /* If there are packets on the txqueue, poke the tasklet - * to transmit them. - */ - if (!list_empty(&queue->txqueue)) - tasklet_schedule(&queue->txtask); -} - -void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct b43legacy_pio *pio = &dev->pio; - struct b43legacy_pioqueue *queue; - - queue = pio->queue1; - stats[0].len = B43legacy_PIO_MAXTXPACKETS - queue->nr_txfree; - stats[0].limit = B43legacy_PIO_MAXTXPACKETS; - stats[0].count = queue->nr_tx_packets; -} - -static void pio_rx_error(struct b43legacy_pioqueue *queue, - int clear_buffers, - const char *error) -{ - int i; - - b43legacyerr(queue->dev->wl, "PIO RX error: %s\n", error); - b43legacy_pio_write(queue, B43legacy_PIO_RXCTL, - B43legacy_PIO_RXCTL_READY); - if (clear_buffers) { - B43legacy_WARN_ON(queue->mmio_base != B43legacy_MMIO_PIO1_BASE); - for (i = 0; i < 15; i++) { - /* Dummy read. */ - b43legacy_pio_read(queue, B43legacy_PIO_RXDATA); - } - } -} - -void b43legacy_pio_rx(struct b43legacy_pioqueue *queue) -{ - __le16 preamble[21] = { 0 }; - struct b43legacy_rxhdr_fw3 *rxhdr; - u16 tmp; - u16 len; - u16 macstat; - int i; - int preamble_readwords; - struct sk_buff *skb; - - tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXCTL); - if (!(tmp & B43legacy_PIO_RXCTL_DATAAVAILABLE)) - return; - b43legacy_pio_write(queue, B43legacy_PIO_RXCTL, - B43legacy_PIO_RXCTL_DATAAVAILABLE); - - for (i = 0; i < 10; i++) { - tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXCTL); - if (tmp & B43legacy_PIO_RXCTL_READY) - goto data_ready; - udelay(10); - } - b43legacydbg(queue->dev->wl, "PIO RX timed out\n"); - return; -data_ready: - - len = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA); - if (unlikely(len > 0x700)) { - pio_rx_error(queue, 0, "len > 0x700"); - return; - } - if (unlikely(len == 0 && queue->mmio_base != - B43legacy_MMIO_PIO4_BASE)) { - pio_rx_error(queue, 0, "len == 0"); - return; - } - preamble[0] = cpu_to_le16(len); - if (queue->mmio_base == B43legacy_MMIO_PIO4_BASE) - preamble_readwords = 14 / sizeof(u16); - else - preamble_readwords = 18 / sizeof(u16); - for (i = 0; i < preamble_readwords; i++) { - tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA); - preamble[i + 1] = cpu_to_le16(tmp); - } - rxhdr = (struct b43legacy_rxhdr_fw3 *)preamble; - macstat = le16_to_cpu(rxhdr->mac_status); - if (macstat & B43legacy_RX_MAC_FCSERR) { - pio_rx_error(queue, - (queue->mmio_base == B43legacy_MMIO_PIO1_BASE), - "Frame FCS error"); - return; - } - if (queue->mmio_base == B43legacy_MMIO_PIO4_BASE) { - /* We received an xmit status. */ - struct b43legacy_hwtxstatus *hw; - - hw = (struct b43legacy_hwtxstatus *)(preamble + 1); - b43legacy_handle_hwtxstatus(queue->dev, hw); - - return; - } - - skb = dev_alloc_skb(len); - if (unlikely(!skb)) { - pio_rx_error(queue, 1, "OOM"); - return; - } - skb_put(skb, len); - for (i = 0; i < len - 1; i += 2) { - tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA); - *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp); - } - if (len % 2) { - tmp = b43legacy_pio_read(queue, B43legacy_PIO_RXDATA); - skb->data[len - 1] = (tmp & 0x00FF); - } - b43legacy_rx(queue->dev, skb, rxhdr); -} - -void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue *queue) -{ - b43legacy_power_saving_ctl_bits(queue->dev, -1, 1); - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - b43legacy_pio_read(queue, B43legacy_PIO_TXCTL) - | B43legacy_PIO_TXCTL_SUSPEND); -} - -void b43legacy_pio_tx_resume(struct b43legacy_pioqueue *queue) -{ - b43legacy_pio_write(queue, B43legacy_PIO_TXCTL, - b43legacy_pio_read(queue, B43legacy_PIO_TXCTL) - & ~B43legacy_PIO_TXCTL_SUSPEND); - b43legacy_power_saving_ctl_bits(queue->dev, -1, -1); - tasklet_schedule(&queue->txtask); -} - -void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev *dev) -{ - struct b43legacy_pio *pio; - - B43legacy_WARN_ON(!b43legacy_using_pio(dev)); - pio = &dev->pio; - pio->queue0->tx_frozen = 1; - pio->queue1->tx_frozen = 1; - pio->queue2->tx_frozen = 1; - pio->queue3->tx_frozen = 1; -} - -void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev *dev) -{ - struct b43legacy_pio *pio; - - B43legacy_WARN_ON(!b43legacy_using_pio(dev)); - pio = &dev->pio; - pio->queue0->tx_frozen = 0; - pio->queue1->tx_frozen = 0; - pio->queue2->tx_frozen = 0; - pio->queue3->tx_frozen = 0; - if (!list_empty(&pio->queue0->txqueue)) - tasklet_schedule(&pio->queue0->txtask); - if (!list_empty(&pio->queue1->txqueue)) - tasklet_schedule(&pio->queue1->txtask); - if (!list_empty(&pio->queue2->txqueue)) - tasklet_schedule(&pio->queue2->txtask); - if (!list_empty(&pio->queue3->txqueue)) - tasklet_schedule(&pio->queue3->txtask); -} diff --git a/drivers/net/wireless/b43legacy/pio.h b/drivers/net/wireless/b43legacy/pio.h deleted file mode 100644 index 464fec05a06d..000000000000 --- a/drivers/net/wireless/b43legacy/pio.h +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef B43legacy_PIO_H_ -#define B43legacy_PIO_H_ - -#include "b43legacy.h" - -#include -#include -#include - - -#define B43legacy_PIO_TXCTL 0x00 -#define B43legacy_PIO_TXDATA 0x02 -#define B43legacy_PIO_TXQBUFSIZE 0x04 -#define B43legacy_PIO_RXCTL 0x08 -#define B43legacy_PIO_RXDATA 0x0A - -#define B43legacy_PIO_TXCTL_WRITELO (1 << 0) -#define B43legacy_PIO_TXCTL_WRITEHI (1 << 1) -#define B43legacy_PIO_TXCTL_COMPLETE (1 << 2) -#define B43legacy_PIO_TXCTL_INIT (1 << 3) -#define B43legacy_PIO_TXCTL_SUSPEND (1 << 7) - -#define B43legacy_PIO_RXCTL_DATAAVAILABLE (1 << 0) -#define B43legacy_PIO_RXCTL_READY (1 << 1) - -/* PIO constants */ -#define B43legacy_PIO_MAXTXDEVQPACKETS 31 -#define B43legacy_PIO_TXQADJUST 80 - -/* PIO tuning knobs */ -#define B43legacy_PIO_MAXTXPACKETS 256 - - - -#ifdef CONFIG_B43LEGACY_PIO - - -struct b43legacy_pioqueue; -struct b43legacy_xmitstatus; - -struct b43legacy_pio_txpacket { - struct b43legacy_pioqueue *queue; - struct sk_buff *skb; - struct list_head list; -}; - -#define pio_txpacket_getindex(packet) ((int)((packet) - \ - (packet)->queue->tx_packets_cache)) - -struct b43legacy_pioqueue { - struct b43legacy_wldev *dev; - u16 mmio_base; - - bool tx_suspended; - bool tx_frozen; - bool need_workarounds; /* Workarounds needed for core.rev < 3 */ - - /* Adjusted size of the device internal TX buffer. */ - u16 tx_devq_size; - /* Used octets of the device internal TX buffer. */ - u16 tx_devq_used; - /* Used packet slots in the device internal TX buffer. */ - u8 tx_devq_packets; - /* Packets from the txfree list can - * be taken on incoming TX requests. - */ - struct list_head txfree; - unsigned int nr_txfree; - /* Packets on the txqueue are queued, - * but not completely written to the chip, yet. - */ - struct list_head txqueue; - /* Packets on the txrunning queue are completely - * posted to the device. We are waiting for the txstatus. - */ - struct list_head txrunning; - /* Total number or packets sent. - * (This counter can obviously wrap). - */ - unsigned int nr_tx_packets; - struct tasklet_struct txtask; - struct b43legacy_pio_txpacket - tx_packets_cache[B43legacy_PIO_MAXTXPACKETS]; -}; - -static inline -u16 b43legacy_pio_read(struct b43legacy_pioqueue *queue, - u16 offset) -{ - return b43legacy_read16(queue->dev, queue->mmio_base + offset); -} - -static inline -void b43legacy_pio_write(struct b43legacy_pioqueue *queue, - u16 offset, u16 value) -{ - b43legacy_write16(queue->dev, queue->mmio_base + offset, value); - mmiowb(); -} - - -int b43legacy_pio_init(struct b43legacy_wldev *dev); -void b43legacy_pio_free(struct b43legacy_wldev *dev); - -int b43legacy_pio_tx(struct b43legacy_wldev *dev, - struct sk_buff *skb); -void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status); -void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats); -void b43legacy_pio_rx(struct b43legacy_pioqueue *queue); - -/* Suspend TX queue in hardware. */ -void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue *queue); -void b43legacy_pio_tx_resume(struct b43legacy_pioqueue *queue); -/* Suspend (freeze) the TX tasklet (software level). */ -void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev *dev); -void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev *dev); - -#else /* CONFIG_B43LEGACY_PIO */ - -static inline -int b43legacy_pio_init(struct b43legacy_wldev *dev) -{ - return 0; -} -static inline -void b43legacy_pio_free(struct b43legacy_wldev *dev) -{ -} -static inline -int b43legacy_pio_tx(struct b43legacy_wldev *dev, - struct sk_buff *skb) -{ - return 0; -} -static inline -void b43legacy_pio_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) -{ -} -static inline -void b43legacy_pio_get_tx_stats(struct b43legacy_wldev *dev, - struct ieee80211_tx_queue_stats *stats) -{ -} -static inline -void b43legacy_pio_rx(struct b43legacy_pioqueue *queue) -{ -} -static inline -void b43legacy_pio_tx_suspend(struct b43legacy_pioqueue *queue) -{ -} -static inline -void b43legacy_pio_tx_resume(struct b43legacy_pioqueue *queue) -{ -} -static inline -void b43legacy_pio_freeze_txqueues(struct b43legacy_wldev *dev) -{ -} -static inline -void b43legacy_pio_thaw_txqueues(struct b43legacy_wldev *dev) -{ -} - -#endif /* CONFIG_B43LEGACY_PIO */ -#endif /* B43legacy_PIO_H_ */ diff --git a/drivers/net/wireless/b43legacy/radio.c b/drivers/net/wireless/b43legacy/radio.c deleted file mode 100644 index 2df545cfad14..000000000000 --- a/drivers/net/wireless/b43legacy/radio.c +++ /dev/null @@ -1,2162 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - Copyright (c) 2007 Larry Finger - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include - -#include "b43legacy.h" -#include "main.h" -#include "phy.h" -#include "radio.h" -#include "ilt.h" - - -/* Table for b43legacy_radio_calibrationvalue() */ -static const u16 rcc_table[16] = { - 0x0002, 0x0003, 0x0001, 0x000F, - 0x0006, 0x0007, 0x0005, 0x000F, - 0x000A, 0x000B, 0x0009, 0x000F, - 0x000E, 0x000F, 0x000D, 0x000F, -}; - -/* Reverse the bits of a 4bit value. - * Example: 1101 is flipped 1011 - */ -static u16 flip_4bit(u16 value) -{ - u16 flipped = 0x0000; - - B43legacy_BUG_ON(!((value & ~0x000F) == 0x0000)); - - flipped |= (value & 0x0001) << 3; - flipped |= (value & 0x0002) << 1; - flipped |= (value & 0x0004) >> 1; - flipped |= (value & 0x0008) >> 3; - - return flipped; -} - -/* Get the freq, as it has to be written to the device. */ -static inline -u16 channel2freq_bg(u8 channel) -{ - /* Frequencies are given as frequencies_bg[index] + 2.4GHz - * Starting with channel 1 - */ - static const u16 frequencies_bg[14] = { - 12, 17, 22, 27, - 32, 37, 42, 47, - 52, 57, 62, 67, - 72, 84, - }; - - if (unlikely(channel < 1 || channel > 14)) { - printk(KERN_INFO "b43legacy: Channel %d is out of range\n", - channel); - dump_stack(); - return 2412; - } - - return frequencies_bg[channel - 1]; -} - -void b43legacy_radio_lock(struct b43legacy_wldev *dev) -{ - u32 status; - - status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK); - status |= B43legacy_MACCTL_RADIOLOCK; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - mmiowb(); - udelay(10); -} - -void b43legacy_radio_unlock(struct b43legacy_wldev *dev) -{ - u32 status; - - b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */ - status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); - B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK)); - status &= ~B43legacy_MACCTL_RADIOLOCK; - b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); - mmiowb(); -} - -u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset) -{ - struct b43legacy_phy *phy = &dev->phy; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - if (phy->radio_ver == 0x2053) { - if (offset < 0x70) - offset += 0x80; - else if (offset < 0x80) - offset += 0x70; - } else if (phy->radio_ver == 0x2050) - offset |= 0x80; - else - B43legacy_WARN_ON(1); - break; - case B43legacy_PHYTYPE_G: - offset |= 0x80; - break; - default: - B43legacy_BUG_ON(1); - } - - b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset); - return b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_LOW); -} - -void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val) -{ - b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset); - mmiowb(); - b43legacy_write16(dev, B43legacy_MMIO_RADIO_DATA_LOW, val); -} - -static void b43legacy_set_all_gains(struct b43legacy_wldev *dev, - s16 first, s16 second, s16 third) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 i; - u16 start = 0x08; - u16 end = 0x18; - u16 offset = 0x0400; - u16 tmp; - - if (phy->rev <= 1) { - offset = 0x5000; - start = 0x10; - end = 0x20; - } - - for (i = 0; i < 4; i++) - b43legacy_ilt_write(dev, offset + i, first); - - for (i = start; i < end; i++) - b43legacy_ilt_write(dev, offset + i, second); - - if (third != -1) { - tmp = ((u16)third << 14) | ((u16)third << 6); - b43legacy_phy_write(dev, 0x04A0, - (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF) - | tmp); - b43legacy_phy_write(dev, 0x04A1, - (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF) - | tmp); - b43legacy_phy_write(dev, 0x04A2, - (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF) - | tmp); - } - b43legacy_dummy_transmission(dev); -} - -static void b43legacy_set_original_gains(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 i; - u16 tmp; - u16 offset = 0x0400; - u16 start = 0x0008; - u16 end = 0x0018; - - if (phy->rev <= 1) { - offset = 0x5000; - start = 0x0010; - end = 0x0020; - } - - for (i = 0; i < 4; i++) { - tmp = (i & 0xFFFC); - tmp |= (i & 0x0001) << 1; - tmp |= (i & 0x0002) >> 1; - - b43legacy_ilt_write(dev, offset + i, tmp); - } - - for (i = start; i < end; i++) - b43legacy_ilt_write(dev, offset + i, i - start); - - b43legacy_phy_write(dev, 0x04A0, - (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF) - | 0x4040); - b43legacy_phy_write(dev, 0x04A1, - (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF) - | 0x4040); - b43legacy_phy_write(dev, 0x04A2, - (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF) - | 0x4000); - b43legacy_dummy_transmission(dev); -} - -/* Synthetic PU workaround */ -static void b43legacy_synth_pu_workaround(struct b43legacy_wldev *dev, - u8 channel) -{ - struct b43legacy_phy *phy = &dev->phy; - - might_sleep(); - - if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) - /* We do not need the workaround. */ - return; - - if (channel <= 10) - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, - channel2freq_bg(channel + 4)); - else - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, - channel2freq_bg(channel)); - msleep(1); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, - channel2freq_bg(channel)); -} - -u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel) -{ - struct b43legacy_phy *phy = &dev->phy; - u8 ret = 0; - u16 saved; - u16 rssi; - u16 temp; - int i; - int j = 0; - - saved = b43legacy_phy_read(dev, 0x0403); - b43legacy_radio_selectchannel(dev, channel, 0); - b43legacy_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5); - if (phy->aci_hw_rssi) - rssi = b43legacy_phy_read(dev, 0x048A) & 0x3F; - else - rssi = saved & 0x3F; - /* clamp temp to signed 5bit */ - if (rssi > 32) - rssi -= 64; - for (i = 0; i < 100; i++) { - temp = (b43legacy_phy_read(dev, 0x047F) >> 8) & 0x3F; - if (temp > 32) - temp -= 64; - if (temp < rssi) - j++; - if (j >= 20) - ret = 1; - } - b43legacy_phy_write(dev, 0x0403, saved); - - return ret; -} - -u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u8 ret[13]; - unsigned int channel = phy->channel; - unsigned int i; - unsigned int j; - unsigned int start; - unsigned int end; - - if (!((phy->type == B43legacy_PHYTYPE_G) && (phy->rev > 0))) - return 0; - - b43legacy_phy_lock(dev); - b43legacy_radio_lock(dev); - b43legacy_phy_write(dev, 0x0802, - b43legacy_phy_read(dev, 0x0802) & 0xFFFC); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) - & 0x7FFF); - b43legacy_set_all_gains(dev, 3, 8, 1); - - start = (channel - 5 > 0) ? channel - 5 : 1; - end = (channel + 5 < 14) ? channel + 5 : 13; - - for (i = start; i <= end; i++) { - if (abs(channel - i) > 2) - ret[i-1] = b43legacy_radio_aci_detect(dev, i); - } - b43legacy_radio_selectchannel(dev, channel, 0); - b43legacy_phy_write(dev, 0x0802, - (b43legacy_phy_read(dev, 0x0802) & 0xFFFC) - | 0x0003); - b43legacy_phy_write(dev, 0x0403, - b43legacy_phy_read(dev, 0x0403) & 0xFFF8); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) - | 0x8000); - b43legacy_set_original_gains(dev); - for (i = 0; i < 13; i++) { - if (!ret[i]) - continue; - end = (i + 5 < 13) ? i + 5 : 13; - for (j = i; j < end; j++) - ret[j] = 1; - } - b43legacy_radio_unlock(dev); - b43legacy_phy_unlock(dev); - - return ret[channel - 1]; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val) -{ - b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset); - mmiowb(); - b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_DATA, (u16)val); -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -s16 b43legacy_nrssi_hw_read(struct b43legacy_wldev *dev, u16 offset) -{ - u16 val; - - b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset); - val = b43legacy_phy_read(dev, B43legacy_PHY_NRSSILT_DATA); - - return (s16)val; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val) -{ - u16 i; - s16 tmp; - - for (i = 0; i < 64; i++) { - tmp = b43legacy_nrssi_hw_read(dev, i); - tmp -= val; - tmp = clamp_val(tmp, -32, 31); - b43legacy_nrssi_hw_write(dev, i, tmp); - } -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - s16 i; - s16 delta; - s32 tmp; - - delta = 0x1F - phy->nrssi[0]; - for (i = 0; i < 64; i++) { - tmp = (i - delta) * phy->nrssislope; - tmp /= 0x10000; - tmp += 0x3A; - tmp = clamp_val(tmp, 0, 0x3F); - phy->nrssi_lt[i] = tmp; - } -} - -static void b43legacy_calc_nrssi_offset(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 backup[20] = { 0 }; - s16 v47F; - u16 i; - u16 saved = 0xFFFF; - - backup[0] = b43legacy_phy_read(dev, 0x0001); - backup[1] = b43legacy_phy_read(dev, 0x0811); - backup[2] = b43legacy_phy_read(dev, 0x0812); - backup[3] = b43legacy_phy_read(dev, 0x0814); - backup[4] = b43legacy_phy_read(dev, 0x0815); - backup[5] = b43legacy_phy_read(dev, 0x005A); - backup[6] = b43legacy_phy_read(dev, 0x0059); - backup[7] = b43legacy_phy_read(dev, 0x0058); - backup[8] = b43legacy_phy_read(dev, 0x000A); - backup[9] = b43legacy_phy_read(dev, 0x0003); - backup[10] = b43legacy_radio_read16(dev, 0x007A); - backup[11] = b43legacy_radio_read16(dev, 0x0043); - - b43legacy_phy_write(dev, 0x0429, - b43legacy_phy_read(dev, 0x0429) & 0x7FFF); - b43legacy_phy_write(dev, 0x0001, - (b43legacy_phy_read(dev, 0x0001) & 0x3FFF) - | 0x4000); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) | 0x000C); - b43legacy_phy_write(dev, 0x0812, - (b43legacy_phy_read(dev, 0x0812) & 0xFFF3) - | 0x0004); - b43legacy_phy_write(dev, 0x0802, - b43legacy_phy_read(dev, 0x0802) & ~(0x1 | 0x2)); - if (phy->rev >= 6) { - backup[12] = b43legacy_phy_read(dev, 0x002E); - backup[13] = b43legacy_phy_read(dev, 0x002F); - backup[14] = b43legacy_phy_read(dev, 0x080F); - backup[15] = b43legacy_phy_read(dev, 0x0810); - backup[16] = b43legacy_phy_read(dev, 0x0801); - backup[17] = b43legacy_phy_read(dev, 0x0060); - backup[18] = b43legacy_phy_read(dev, 0x0014); - backup[19] = b43legacy_phy_read(dev, 0x0478); - - b43legacy_phy_write(dev, 0x002E, 0); - b43legacy_phy_write(dev, 0x002F, 0); - b43legacy_phy_write(dev, 0x080F, 0); - b43legacy_phy_write(dev, 0x0810, 0); - b43legacy_phy_write(dev, 0x0478, - b43legacy_phy_read(dev, 0x0478) | 0x0100); - b43legacy_phy_write(dev, 0x0801, - b43legacy_phy_read(dev, 0x0801) | 0x0040); - b43legacy_phy_write(dev, 0x0060, - b43legacy_phy_read(dev, 0x0060) | 0x0040); - b43legacy_phy_write(dev, 0x0014, - b43legacy_phy_read(dev, 0x0014) | 0x0200); - } - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) | 0x0070); - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) | 0x0080); - udelay(30); - - v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == 31) { - for (i = 7; i >= 4; i--) { - b43legacy_radio_write16(dev, 0x007B, i); - udelay(20); - v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) - & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F < 31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 4; - } else { - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - & 0x007F); - b43legacy_phy_write(dev, 0x0814, - b43legacy_phy_read(dev, 0x0814) | 0x0001); - b43legacy_phy_write(dev, 0x0815, - b43legacy_phy_read(dev, 0x0815) & 0xFFFE); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) | 0x000C); - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) | 0x000C); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) | 0x0030); - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) | 0x0030); - b43legacy_phy_write(dev, 0x005A, 0x0480); - b43legacy_phy_write(dev, 0x0059, 0x0810); - b43legacy_phy_write(dev, 0x0058, 0x000D); - if (phy->analog == 0) - b43legacy_phy_write(dev, 0x0003, 0x0122); - else - b43legacy_phy_write(dev, 0x000A, - b43legacy_phy_read(dev, 0x000A) - | 0x2000); - b43legacy_phy_write(dev, 0x0814, - b43legacy_phy_read(dev, 0x0814) | 0x0004); - b43legacy_phy_write(dev, 0x0815, - b43legacy_phy_read(dev, 0x0815) & 0xFFFB); - b43legacy_phy_write(dev, 0x0003, - (b43legacy_phy_read(dev, 0x0003) & 0xFF9F) - | 0x0040); - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x000F); - b43legacy_set_all_gains(dev, 3, 0, 1); - b43legacy_radio_write16(dev, 0x0043, - (b43legacy_radio_read16(dev, 0x0043) - & 0x00F0) | 0x000F); - udelay(30); - v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == -32) { - for (i = 0; i < 4; i++) { - b43legacy_radio_write16(dev, 0x007B, i); - udelay(20); - v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> - 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F > -31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 3; - } else - saved = 0; - } - b43legacy_radio_write16(dev, 0x007B, saved); - - if (phy->rev >= 6) { - b43legacy_phy_write(dev, 0x002E, backup[12]); - b43legacy_phy_write(dev, 0x002F, backup[13]); - b43legacy_phy_write(dev, 0x080F, backup[14]); - b43legacy_phy_write(dev, 0x0810, backup[15]); - } - b43legacy_phy_write(dev, 0x0814, backup[3]); - b43legacy_phy_write(dev, 0x0815, backup[4]); - b43legacy_phy_write(dev, 0x005A, backup[5]); - b43legacy_phy_write(dev, 0x0059, backup[6]); - b43legacy_phy_write(dev, 0x0058, backup[7]); - b43legacy_phy_write(dev, 0x000A, backup[8]); - b43legacy_phy_write(dev, 0x0003, backup[9]); - b43legacy_radio_write16(dev, 0x0043, backup[11]); - b43legacy_radio_write16(dev, 0x007A, backup[10]); - b43legacy_phy_write(dev, 0x0802, - b43legacy_phy_read(dev, 0x0802) | 0x1 | 0x2); - b43legacy_phy_write(dev, 0x0429, - b43legacy_phy_read(dev, 0x0429) | 0x8000); - b43legacy_set_original_gains(dev); - if (phy->rev >= 6) { - b43legacy_phy_write(dev, 0x0801, backup[16]); - b43legacy_phy_write(dev, 0x0060, backup[17]); - b43legacy_phy_write(dev, 0x0014, backup[18]); - b43legacy_phy_write(dev, 0x0478, backup[19]); - } - b43legacy_phy_write(dev, 0x0001, backup[0]); - b43legacy_phy_write(dev, 0x0812, backup[2]); - b43legacy_phy_write(dev, 0x0811, backup[1]); -} - -void b43legacy_calc_nrssi_slope(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 backup[18] = { 0 }; - u16 tmp; - s16 nrssi0; - s16 nrssi1; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - backup[0] = b43legacy_radio_read16(dev, 0x007A); - backup[1] = b43legacy_radio_read16(dev, 0x0052); - backup[2] = b43legacy_radio_read16(dev, 0x0043); - backup[3] = b43legacy_phy_read(dev, 0x0030); - backup[4] = b43legacy_phy_read(dev, 0x0026); - backup[5] = b43legacy_phy_read(dev, 0x0015); - backup[6] = b43legacy_phy_read(dev, 0x002A); - backup[7] = b43legacy_phy_read(dev, 0x0020); - backup[8] = b43legacy_phy_read(dev, 0x005A); - backup[9] = b43legacy_phy_read(dev, 0x0059); - backup[10] = b43legacy_phy_read(dev, 0x0058); - backup[11] = b43legacy_read16(dev, 0x03E2); - backup[12] = b43legacy_read16(dev, 0x03E6); - backup[13] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); - - tmp = b43legacy_radio_read16(dev, 0x007A); - tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; - b43legacy_radio_write16(dev, 0x007A, tmp); - b43legacy_phy_write(dev, 0x0030, 0x00FF); - b43legacy_write16(dev, 0x03EC, 0x7F7F); - b43legacy_phy_write(dev, 0x0026, 0x0000); - b43legacy_phy_write(dev, 0x0015, - b43legacy_phy_read(dev, 0x0015) | 0x0020); - b43legacy_phy_write(dev, 0x002A, 0x08A3); - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x0080); - - nrssi0 = (s16)b43legacy_phy_read(dev, 0x0027); - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - & 0x007F); - if (phy->analog >= 2) - b43legacy_write16(dev, 0x03E6, 0x0040); - else if (phy->analog == 0) - b43legacy_write16(dev, 0x03E6, 0x0122); - else - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, - b43legacy_read16(dev, - B43legacy_MMIO_CHANNEL_EXT) & 0x2000); - b43legacy_phy_write(dev, 0x0020, 0x3F3F); - b43legacy_phy_write(dev, 0x0015, 0xF330); - b43legacy_radio_write16(dev, 0x005A, 0x0060); - b43legacy_radio_write16(dev, 0x0043, - b43legacy_radio_read16(dev, 0x0043) - & 0x00F0); - b43legacy_phy_write(dev, 0x005A, 0x0480); - b43legacy_phy_write(dev, 0x0059, 0x0810); - b43legacy_phy_write(dev, 0x0058, 0x000D); - udelay(20); - - nrssi1 = (s16)b43legacy_phy_read(dev, 0x0027); - b43legacy_phy_write(dev, 0x0030, backup[3]); - b43legacy_radio_write16(dev, 0x007A, backup[0]); - b43legacy_write16(dev, 0x03E2, backup[11]); - b43legacy_phy_write(dev, 0x0026, backup[4]); - b43legacy_phy_write(dev, 0x0015, backup[5]); - b43legacy_phy_write(dev, 0x002A, backup[6]); - b43legacy_synth_pu_workaround(dev, phy->channel); - if (phy->analog != 0) - b43legacy_write16(dev, 0x03F4, backup[13]); - - b43legacy_phy_write(dev, 0x0020, backup[7]); - b43legacy_phy_write(dev, 0x005A, backup[8]); - b43legacy_phy_write(dev, 0x0059, backup[9]); - b43legacy_phy_write(dev, 0x0058, backup[10]); - b43legacy_radio_write16(dev, 0x0052, backup[1]); - b43legacy_radio_write16(dev, 0x0043, backup[2]); - - if (nrssi0 == nrssi1) - phy->nrssislope = 0x00010000; - else - phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - - if (nrssi0 <= -4) { - phy->nrssi[0] = nrssi0; - phy->nrssi[1] = nrssi1; - } - break; - case B43legacy_PHYTYPE_G: - if (phy->radio_rev >= 9) - return; - if (phy->radio_rev == 8) - b43legacy_calc_nrssi_offset(dev); - - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) - & 0x7FFF); - b43legacy_phy_write(dev, 0x0802, - b43legacy_phy_read(dev, 0x0802) & 0xFFFC); - backup[7] = b43legacy_read16(dev, 0x03E2); - b43legacy_write16(dev, 0x03E2, - b43legacy_read16(dev, 0x03E2) | 0x8000); - backup[0] = b43legacy_radio_read16(dev, 0x007A); - backup[1] = b43legacy_radio_read16(dev, 0x0052); - backup[2] = b43legacy_radio_read16(dev, 0x0043); - backup[3] = b43legacy_phy_read(dev, 0x0015); - backup[4] = b43legacy_phy_read(dev, 0x005A); - backup[5] = b43legacy_phy_read(dev, 0x0059); - backup[6] = b43legacy_phy_read(dev, 0x0058); - backup[8] = b43legacy_read16(dev, 0x03E6); - backup[9] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); - if (phy->rev >= 3) { - backup[10] = b43legacy_phy_read(dev, 0x002E); - backup[11] = b43legacy_phy_read(dev, 0x002F); - backup[12] = b43legacy_phy_read(dev, 0x080F); - backup[13] = b43legacy_phy_read(dev, - B43legacy_PHY_G_LO_CONTROL); - backup[14] = b43legacy_phy_read(dev, 0x0801); - backup[15] = b43legacy_phy_read(dev, 0x0060); - backup[16] = b43legacy_phy_read(dev, 0x0014); - backup[17] = b43legacy_phy_read(dev, 0x0478); - b43legacy_phy_write(dev, 0x002E, 0); - b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, 0); - switch (phy->rev) { - case 4: case 6: case 7: - b43legacy_phy_write(dev, 0x0478, - b43legacy_phy_read(dev, - 0x0478) | 0x0100); - b43legacy_phy_write(dev, 0x0801, - b43legacy_phy_read(dev, - 0x0801) | 0x0040); - break; - case 3: case 5: - b43legacy_phy_write(dev, 0x0801, - b43legacy_phy_read(dev, - 0x0801) & 0xFFBF); - break; - } - b43legacy_phy_write(dev, 0x0060, - b43legacy_phy_read(dev, 0x0060) - | 0x0040); - b43legacy_phy_write(dev, 0x0014, - b43legacy_phy_read(dev, 0x0014) - | 0x0200); - } - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x0070); - b43legacy_set_all_gains(dev, 0, 8, 0); - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - & 0x00F7); - if (phy->rev >= 2) { - b43legacy_phy_write(dev, 0x0811, - (b43legacy_phy_read(dev, 0x0811) - & 0xFFCF) | 0x0030); - b43legacy_phy_write(dev, 0x0812, - (b43legacy_phy_read(dev, 0x0812) - & 0xFFCF) | 0x0010); - } - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x0080); - udelay(20); - - nrssi0 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (nrssi0 >= 0x0020) - nrssi0 -= 0x0040; - - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - & 0x007F); - if (phy->analog >= 2) - b43legacy_phy_write(dev, 0x0003, - (b43legacy_phy_read(dev, 0x0003) - & 0xFF9F) | 0x0040); - - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, - b43legacy_read16(dev, - B43legacy_MMIO_CHANNEL_EXT) | 0x2000); - b43legacy_radio_write16(dev, 0x007A, - b43legacy_radio_read16(dev, 0x007A) - | 0x000F); - b43legacy_phy_write(dev, 0x0015, 0xF330); - if (phy->rev >= 2) { - b43legacy_phy_write(dev, 0x0812, - (b43legacy_phy_read(dev, 0x0812) - & 0xFFCF) | 0x0020); - b43legacy_phy_write(dev, 0x0811, - (b43legacy_phy_read(dev, 0x0811) - & 0xFFCF) | 0x0020); - } - - b43legacy_set_all_gains(dev, 3, 0, 1); - if (phy->radio_rev == 8) - b43legacy_radio_write16(dev, 0x0043, 0x001F); - else { - tmp = b43legacy_radio_read16(dev, 0x0052) & 0xFF0F; - b43legacy_radio_write16(dev, 0x0052, tmp | 0x0060); - tmp = b43legacy_radio_read16(dev, 0x0043) & 0xFFF0; - b43legacy_radio_write16(dev, 0x0043, tmp | 0x0009); - } - b43legacy_phy_write(dev, 0x005A, 0x0480); - b43legacy_phy_write(dev, 0x0059, 0x0810); - b43legacy_phy_write(dev, 0x0058, 0x000D); - udelay(20); - nrssi1 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); - if (nrssi1 >= 0x0020) - nrssi1 -= 0x0040; - if (nrssi0 == nrssi1) - phy->nrssislope = 0x00010000; - else - phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - if (nrssi0 >= -4) { - phy->nrssi[0] = nrssi1; - phy->nrssi[1] = nrssi0; - } - if (phy->rev >= 3) { - b43legacy_phy_write(dev, 0x002E, backup[10]); - b43legacy_phy_write(dev, 0x002F, backup[11]); - b43legacy_phy_write(dev, 0x080F, backup[12]); - b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, - backup[13]); - } - if (phy->rev >= 2) { - b43legacy_phy_write(dev, 0x0812, - b43legacy_phy_read(dev, 0x0812) - & 0xFFCF); - b43legacy_phy_write(dev, 0x0811, - b43legacy_phy_read(dev, 0x0811) - & 0xFFCF); - } - - b43legacy_radio_write16(dev, 0x007A, backup[0]); - b43legacy_radio_write16(dev, 0x0052, backup[1]); - b43legacy_radio_write16(dev, 0x0043, backup[2]); - b43legacy_write16(dev, 0x03E2, backup[7]); - b43legacy_write16(dev, 0x03E6, backup[8]); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[9]); - b43legacy_phy_write(dev, 0x0015, backup[3]); - b43legacy_phy_write(dev, 0x005A, backup[4]); - b43legacy_phy_write(dev, 0x0059, backup[5]); - b43legacy_phy_write(dev, 0x0058, backup[6]); - b43legacy_synth_pu_workaround(dev, phy->channel); - b43legacy_phy_write(dev, 0x0802, - b43legacy_phy_read(dev, 0x0802) | 0x0003); - b43legacy_set_original_gains(dev); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) - | 0x8000); - if (phy->rev >= 3) { - b43legacy_phy_write(dev, 0x0801, backup[14]); - b43legacy_phy_write(dev, 0x0060, backup[15]); - b43legacy_phy_write(dev, 0x0014, backup[16]); - b43legacy_phy_write(dev, 0x0478, backup[17]); - } - b43legacy_nrssi_mem_update(dev); - b43legacy_calc_nrssi_threshold(dev); - break; - default: - B43legacy_BUG_ON(1); - } -} - -void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - s32 threshold; - s32 a; - s32 b; - s16 tmp16; - u16 tmp_u16; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: { - if (phy->radio_ver != 0x2050) - return; - if (!(dev->dev->bus->sprom.boardflags_lo & - B43legacy_BFL_RSSI)) - return; - - if (phy->radio_rev >= 6) { - threshold = (phy->nrssi[1] - phy->nrssi[0]) * 32; - threshold += 20 * (phy->nrssi[0] + 1); - threshold /= 40; - } else - threshold = phy->nrssi[1] - 5; - - threshold = clamp_val(threshold, 0, 0x3E); - b43legacy_phy_read(dev, 0x0020); /* dummy read */ - b43legacy_phy_write(dev, 0x0020, (((u16)threshold) << 8) - | 0x001C); - - if (phy->radio_rev >= 6) { - b43legacy_phy_write(dev, 0x0087, 0x0E0D); - b43legacy_phy_write(dev, 0x0086, 0x0C0B); - b43legacy_phy_write(dev, 0x0085, 0x0A09); - b43legacy_phy_write(dev, 0x0084, 0x0808); - b43legacy_phy_write(dev, 0x0083, 0x0808); - b43legacy_phy_write(dev, 0x0082, 0x0604); - b43legacy_phy_write(dev, 0x0081, 0x0302); - b43legacy_phy_write(dev, 0x0080, 0x0100); - } - break; - } - case B43legacy_PHYTYPE_G: - if (!phy->gmode || - !(dev->dev->bus->sprom.boardflags_lo & - B43legacy_BFL_RSSI)) { - tmp16 = b43legacy_nrssi_hw_read(dev, 0x20); - if (tmp16 >= 0x20) - tmp16 -= 0x40; - if (tmp16 < 3) - b43legacy_phy_write(dev, 0x048A, - (b43legacy_phy_read(dev, - 0x048A) & 0xF000) | 0x09EB); - else - b43legacy_phy_write(dev, 0x048A, - (b43legacy_phy_read(dev, - 0x048A) & 0xF000) | 0x0AED); - } else { - if (phy->interfmode == - B43legacy_RADIO_INTERFMODE_NONWLAN) { - a = 0xE; - b = 0xA; - } else if (!phy->aci_wlan_automatic && - phy->aci_enable) { - a = 0x13; - b = 0x12; - } else { - a = 0xE; - b = 0x11; - } - - a = a * (phy->nrssi[1] - phy->nrssi[0]); - a += (phy->nrssi[0] << 6); - if (a < 32) - a += 31; - else - a += 32; - a = a >> 6; - a = clamp_val(a, -31, 31); - - b = b * (phy->nrssi[1] - phy->nrssi[0]); - b += (phy->nrssi[0] << 6); - if (b < 32) - b += 31; - else - b += 32; - b = b >> 6; - b = clamp_val(b, -31, 31); - - tmp_u16 = b43legacy_phy_read(dev, 0x048A) & 0xF000; - tmp_u16 |= ((u32)b & 0x0000003F); - tmp_u16 |= (((u32)a & 0x0000003F) << 6); - b43legacy_phy_write(dev, 0x048A, tmp_u16); - } - break; - default: - B43legacy_BUG_ON(1); - } -} - -/* Stack implementation to save/restore values from the - * interference mitigation code. - * It is save to restore values in random order. - */ -static void _stack_save(u32 *_stackptr, size_t *stackidx, - u8 id, u16 offset, u16 value) -{ - u32 *stackptr = &(_stackptr[*stackidx]); - - B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000)); - B43legacy_WARN_ON(!((id & 0xF8) == 0x00)); - *stackptr = offset; - *stackptr |= ((u32)id) << 13; - *stackptr |= ((u32)value) << 16; - (*stackidx)++; - B43legacy_WARN_ON(!(*stackidx < B43legacy_INTERFSTACK_SIZE)); -} - -static u16 _stack_restore(u32 *stackptr, - u8 id, u16 offset) -{ - size_t i; - - B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000)); - B43legacy_WARN_ON(!((id & 0xF8) == 0x00)); - for (i = 0; i < B43legacy_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00001FFF) != offset) - continue; - if (((*stackptr & 0x00007000) >> 13) != id) - continue; - return ((*stackptr & 0xFFFF0000) >> 16); - } - B43legacy_BUG_ON(1); - - return 0; -} - -#define phy_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x1, (offset), \ - b43legacy_phy_read(dev, (offset))); \ - } while (0) -#define phy_stackrestore(offset) \ - do { \ - b43legacy_phy_write(dev, (offset), \ - _stack_restore(stack, 0x1, \ - (offset))); \ - } while (0) -#define radio_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x2, (offset), \ - b43legacy_radio_read16(dev, (offset))); \ - } while (0) -#define radio_stackrestore(offset) \ - do { \ - b43legacy_radio_write16(dev, (offset), \ - _stack_restore(stack, 0x2, \ - (offset))); \ - } while (0) -#define ilt_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x3, (offset), \ - b43legacy_ilt_read(dev, (offset))); \ - } while (0) -#define ilt_stackrestore(offset) \ - do { \ - b43legacy_ilt_write(dev, (offset), \ - _stack_restore(stack, 0x3, \ - (offset))); \ - } while (0) - -static void -b43legacy_radio_interference_mitigation_enable(struct b43legacy_wldev *dev, - int mode) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 tmp; - u16 flipped; - u32 tmp32; - size_t stackidx = 0; - u32 *stack = phy->interfstack; - - switch (mode) { - case B43legacy_RADIO_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - b43legacy_phy_write(dev, 0x042B, - b43legacy_phy_read(dev, 0x042B) - | 0x0800); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, - B43legacy_PHY_G_CRS) & ~0x4000); - break; - } - radio_stacksave(0x0078); - tmp = (b43legacy_radio_read16(dev, 0x0078) & 0x001E); - flipped = flip_4bit(tmp); - if (flipped < 10 && flipped >= 8) - flipped = 7; - else if (flipped >= 10) - flipped -= 3; - flipped = flip_4bit(flipped); - flipped = (flipped << 1) | 0x0020; - b43legacy_radio_write16(dev, 0x0078, flipped); - - b43legacy_calc_nrssi_threshold(dev); - - phy_stacksave(0x0406); - b43legacy_phy_write(dev, 0x0406, 0x7E28); - - b43legacy_phy_write(dev, 0x042B, - b43legacy_phy_read(dev, 0x042B) | 0x0800); - b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, - b43legacy_phy_read(dev, - B43legacy_PHY_RADIO_BITFIELD) | 0x1000); - - phy_stacksave(0x04A0); - b43legacy_phy_write(dev, 0x04A0, - (b43legacy_phy_read(dev, 0x04A0) & 0xC0C0) - | 0x0008); - phy_stacksave(0x04A1); - b43legacy_phy_write(dev, 0x04A1, - (b43legacy_phy_read(dev, 0x04A1) & 0xC0C0) - | 0x0605); - phy_stacksave(0x04A2); - b43legacy_phy_write(dev, 0x04A2, - (b43legacy_phy_read(dev, 0x04A2) & 0xC0C0) - | 0x0204); - phy_stacksave(0x04A8); - b43legacy_phy_write(dev, 0x04A8, - (b43legacy_phy_read(dev, 0x04A8) & 0xC0C0) - | 0x0803); - phy_stacksave(0x04AB); - b43legacy_phy_write(dev, 0x04AB, - (b43legacy_phy_read(dev, 0x04AB) & 0xC0C0) - | 0x0605); - - phy_stacksave(0x04A7); - b43legacy_phy_write(dev, 0x04A7, 0x0002); - phy_stacksave(0x04A3); - b43legacy_phy_write(dev, 0x04A3, 0x287A); - phy_stacksave(0x04A9); - b43legacy_phy_write(dev, 0x04A9, 0x2027); - phy_stacksave(0x0493); - b43legacy_phy_write(dev, 0x0493, 0x32F5); - phy_stacksave(0x04AA); - b43legacy_phy_write(dev, 0x04AA, 0x2027); - phy_stacksave(0x04AC); - b43legacy_phy_write(dev, 0x04AC, 0x32F5); - break; - case B43legacy_RADIO_INTERFMODE_MANUALWLAN: - if (b43legacy_phy_read(dev, 0x0033) & 0x0800) - break; - - phy->aci_enable = 1; - - phy_stacksave(B43legacy_PHY_RADIO_BITFIELD); - phy_stacksave(B43legacy_PHY_G_CRS); - if (phy->rev < 2) - phy_stacksave(0x0406); - else { - phy_stacksave(0x04C0); - phy_stacksave(0x04C1); - } - phy_stacksave(0x0033); - phy_stacksave(0x04A7); - phy_stacksave(0x04A3); - phy_stacksave(0x04A9); - phy_stacksave(0x04AA); - phy_stacksave(0x04AC); - phy_stacksave(0x0493); - phy_stacksave(0x04A1); - phy_stacksave(0x04A0); - phy_stacksave(0x04A2); - phy_stacksave(0x048A); - phy_stacksave(0x04A8); - phy_stacksave(0x04AB); - if (phy->rev == 2) { - phy_stacksave(0x04AD); - phy_stacksave(0x04AE); - } else if (phy->rev >= 3) { - phy_stacksave(0x04AD); - phy_stacksave(0x0415); - phy_stacksave(0x0416); - phy_stacksave(0x0417); - ilt_stacksave(0x1A00 + 0x2); - ilt_stacksave(0x1A00 + 0x3); - } - phy_stacksave(0x042B); - phy_stacksave(0x048C); - - b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, - b43legacy_phy_read(dev, - B43legacy_PHY_RADIO_BITFIELD) & ~0x1000); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - (b43legacy_phy_read(dev, - B43legacy_PHY_G_CRS) - & 0xFFFC) | 0x0002); - - b43legacy_phy_write(dev, 0x0033, 0x0800); - b43legacy_phy_write(dev, 0x04A3, 0x2027); - b43legacy_phy_write(dev, 0x04A9, 0x1CA8); - b43legacy_phy_write(dev, 0x0493, 0x287A); - b43legacy_phy_write(dev, 0x04AA, 0x1CA8); - b43legacy_phy_write(dev, 0x04AC, 0x287A); - - b43legacy_phy_write(dev, 0x04A0, - (b43legacy_phy_read(dev, 0x04A0) - & 0xFFC0) | 0x001A); - b43legacy_phy_write(dev, 0x04A7, 0x000D); - - if (phy->rev < 2) - b43legacy_phy_write(dev, 0x0406, 0xFF0D); - else if (phy->rev == 2) { - b43legacy_phy_write(dev, 0x04C0, 0xFFFF); - b43legacy_phy_write(dev, 0x04C1, 0x00A9); - } else { - b43legacy_phy_write(dev, 0x04C0, 0x00C1); - b43legacy_phy_write(dev, 0x04C1, 0x0059); - } - - b43legacy_phy_write(dev, 0x04A1, - (b43legacy_phy_read(dev, 0x04A1) - & 0xC0FF) | 0x1800); - b43legacy_phy_write(dev, 0x04A1, - (b43legacy_phy_read(dev, 0x04A1) - & 0xFFC0) | 0x0015); - b43legacy_phy_write(dev, 0x04A8, - (b43legacy_phy_read(dev, 0x04A8) - & 0xCFFF) | 0x1000); - b43legacy_phy_write(dev, 0x04A8, - (b43legacy_phy_read(dev, 0x04A8) - & 0xF0FF) | 0x0A00); - b43legacy_phy_write(dev, 0x04AB, - (b43legacy_phy_read(dev, 0x04AB) - & 0xCFFF) | 0x1000); - b43legacy_phy_write(dev, 0x04AB, - (b43legacy_phy_read(dev, 0x04AB) - & 0xF0FF) | 0x0800); - b43legacy_phy_write(dev, 0x04AB, - (b43legacy_phy_read(dev, 0x04AB) - & 0xFFCF) | 0x0010); - b43legacy_phy_write(dev, 0x04AB, - (b43legacy_phy_read(dev, 0x04AB) - & 0xFFF0) | 0x0005); - b43legacy_phy_write(dev, 0x04A8, - (b43legacy_phy_read(dev, 0x04A8) - & 0xFFCF) | 0x0010); - b43legacy_phy_write(dev, 0x04A8, - (b43legacy_phy_read(dev, 0x04A8) - & 0xFFF0) | 0x0006); - b43legacy_phy_write(dev, 0x04A2, - (b43legacy_phy_read(dev, 0x04A2) - & 0xF0FF) | 0x0800); - b43legacy_phy_write(dev, 0x04A0, - (b43legacy_phy_read(dev, 0x04A0) - & 0xF0FF) | 0x0500); - b43legacy_phy_write(dev, 0x04A2, - (b43legacy_phy_read(dev, 0x04A2) - & 0xFFF0) | 0x000B); - - if (phy->rev >= 3) { - b43legacy_phy_write(dev, 0x048A, - b43legacy_phy_read(dev, 0x048A) - & ~0x8000); - b43legacy_phy_write(dev, 0x0415, - (b43legacy_phy_read(dev, 0x0415) - & 0x8000) | 0x36D8); - b43legacy_phy_write(dev, 0x0416, - (b43legacy_phy_read(dev, 0x0416) - & 0x8000) | 0x36D8); - b43legacy_phy_write(dev, 0x0417, - (b43legacy_phy_read(dev, 0x0417) - & 0xFE00) | 0x016D); - } else { - b43legacy_phy_write(dev, 0x048A, - b43legacy_phy_read(dev, 0x048A) - | 0x1000); - b43legacy_phy_write(dev, 0x048A, - (b43legacy_phy_read(dev, 0x048A) - & 0x9FFF) | 0x2000); - tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET); - if (!(tmp32 & 0x800)) { - tmp32 |= 0x800; - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - tmp32); - } - } - if (phy->rev >= 2) - b43legacy_phy_write(dev, 0x042B, - b43legacy_phy_read(dev, 0x042B) - | 0x0800); - b43legacy_phy_write(dev, 0x048C, - (b43legacy_phy_read(dev, 0x048C) - & 0xF0FF) | 0x0200); - if (phy->rev == 2) { - b43legacy_phy_write(dev, 0x04AE, - (b43legacy_phy_read(dev, 0x04AE) - & 0xFF00) | 0x007F); - b43legacy_phy_write(dev, 0x04AD, - (b43legacy_phy_read(dev, 0x04AD) - & 0x00FF) | 0x1300); - } else if (phy->rev >= 6) { - b43legacy_ilt_write(dev, 0x1A00 + 0x3, 0x007F); - b43legacy_ilt_write(dev, 0x1A00 + 0x2, 0x007F); - b43legacy_phy_write(dev, 0x04AD, - b43legacy_phy_read(dev, 0x04AD) - & 0x00FF); - } - b43legacy_calc_nrssi_slope(dev); - break; - default: - B43legacy_BUG_ON(1); - } -} - -static void -b43legacy_radio_interference_mitigation_disable(struct b43legacy_wldev *dev, - int mode) -{ - struct b43legacy_phy *phy = &dev->phy; - u32 tmp32; - u32 *stack = phy->interfstack; - - switch (mode) { - case B43legacy_RADIO_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - b43legacy_phy_write(dev, 0x042B, - b43legacy_phy_read(dev, 0x042B) - & ~0x0800); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, - B43legacy_PHY_G_CRS) | 0x4000); - break; - } - phy_stackrestore(0x0078); - b43legacy_calc_nrssi_threshold(dev); - phy_stackrestore(0x0406); - b43legacy_phy_write(dev, 0x042B, - b43legacy_phy_read(dev, 0x042B) & ~0x0800); - if (!dev->bad_frames_preempt) - b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, - b43legacy_phy_read(dev, - B43legacy_PHY_RADIO_BITFIELD) - & ~(1 << 11)); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) - | 0x4000); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A7); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - break; - case B43legacy_RADIO_INTERFMODE_MANUALWLAN: - if (!(b43legacy_phy_read(dev, 0x0033) & 0x0800)) - break; - - phy->aci_enable = 0; - - phy_stackrestore(B43legacy_PHY_RADIO_BITFIELD); - phy_stackrestore(B43legacy_PHY_G_CRS); - phy_stackrestore(0x0033); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A7); - if (phy->rev >= 2) { - phy_stackrestore(0x04C0); - phy_stackrestore(0x04C1); - } else - phy_stackrestore(0x0406); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A8); - if (phy->rev == 2) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x04AE); - } else if (phy->rev >= 3) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x0415); - phy_stackrestore(0x0416); - phy_stackrestore(0x0417); - ilt_stackrestore(0x1A00 + 0x2); - ilt_stackrestore(0x1A00 + 0x3); - } - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x042B); - phy_stackrestore(0x048C); - tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET); - if (tmp32 & 0x800) { - tmp32 &= ~0x800; - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - tmp32); - } - b43legacy_calc_nrssi_slope(dev); - break; - default: - B43legacy_BUG_ON(1); - } -} - -#undef phy_stacksave -#undef phy_stackrestore -#undef radio_stacksave -#undef radio_stackrestore -#undef ilt_stacksave -#undef ilt_stackrestore - -int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev, - int mode) -{ - struct b43legacy_phy *phy = &dev->phy; - int currentmode; - - if ((phy->type != B43legacy_PHYTYPE_G) || - (phy->rev == 0) || (!phy->gmode)) - return -ENODEV; - - phy->aci_wlan_automatic = 0; - switch (mode) { - case B43legacy_RADIO_INTERFMODE_AUTOWLAN: - phy->aci_wlan_automatic = 1; - if (phy->aci_enable) - mode = B43legacy_RADIO_INTERFMODE_MANUALWLAN; - else - mode = B43legacy_RADIO_INTERFMODE_NONE; - break; - case B43legacy_RADIO_INTERFMODE_NONE: - case B43legacy_RADIO_INTERFMODE_NONWLAN: - case B43legacy_RADIO_INTERFMODE_MANUALWLAN: - break; - default: - return -EINVAL; - } - - currentmode = phy->interfmode; - if (currentmode == mode) - return 0; - if (currentmode != B43legacy_RADIO_INTERFMODE_NONE) - b43legacy_radio_interference_mitigation_disable(dev, - currentmode); - - if (mode == B43legacy_RADIO_INTERFMODE_NONE) { - phy->aci_enable = 0; - phy->aci_hw_rssi = 0; - } else - b43legacy_radio_interference_mitigation_enable(dev, mode); - phy->interfmode = mode; - - return 0; -} - -u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev) -{ - u16 reg; - u16 index; - u16 ret; - - reg = b43legacy_radio_read16(dev, 0x0060); - index = (reg & 0x001E) >> 1; - ret = rcc_table[index] << 1; - ret |= (reg & 0x0001); - ret |= 0x0020; - - return ret; -} - -#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) -static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 loop_or = 0; - u16 adj_loopback_gain = phy->loopback_gain[0]; - u8 loop; - u16 extern_lna_control; - - if (!phy->gmode) - return 0; - if (!has_loopback_gain(phy)) { - if (phy->rev < 7 || !(dev->dev->bus->sprom.boardflags_lo - & B43legacy_BFL_EXTLNA)) { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0FB2; - case LPD(0, 0, 1): - return 0x00B2; - case LPD(1, 0, 1): - return 0x30B2; - case LPD(1, 0, 0): - return 0x30B3; - default: - B43legacy_BUG_ON(1); - } - } else { - switch (lpd) { - case LPD(0, 1, 1): - return 0x8FB2; - case LPD(0, 0, 1): - return 0x80B2; - case LPD(1, 0, 1): - return 0x20B2; - case LPD(1, 0, 0): - return 0x20B3; - default: - B43legacy_BUG_ON(1); - } - } - } else { - if (phy->radio_rev == 8) - adj_loopback_gain += 0x003E; - else - adj_loopback_gain += 0x0026; - if (adj_loopback_gain >= 0x46) { - adj_loopback_gain -= 0x46; - extern_lna_control = 0x3000; - } else if (adj_loopback_gain >= 0x3A) { - adj_loopback_gain -= 0x3A; - extern_lna_control = 0x2000; - } else if (adj_loopback_gain >= 0x2E) { - adj_loopback_gain -= 0x2E; - extern_lna_control = 0x1000; - } else { - adj_loopback_gain -= 0x10; - extern_lna_control = 0x0000; - } - for (loop = 0; loop < 16; loop++) { - u16 tmp = adj_loopback_gain - 6 * loop; - if (tmp < 6) - break; - } - - loop_or = (loop << 8) | extern_lna_control; - if (phy->rev >= 7 && dev->dev->bus->sprom.boardflags_lo - & B43legacy_BFL_EXTLNA) { - if (extern_lna_control) - loop_or |= 0x8000; - switch (lpd) { - case LPD(0, 1, 1): - return 0x8F92; - case LPD(0, 0, 1): - return (0x8092 | loop_or); - case LPD(1, 0, 1): - return (0x2092 | loop_or); - case LPD(1, 0, 0): - return (0x2093 | loop_or); - default: - B43legacy_BUG_ON(1); - } - } else { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0F92; - case LPD(0, 0, 1): - case LPD(1, 0, 1): - return (0x0092 | loop_or); - case LPD(1, 0, 0): - return (0x0093 | loop_or); - default: - B43legacy_BUG_ON(1); - } - } - } - return 0; -} - -u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 backup[21] = { 0 }; - u16 ret; - u16 i; - u16 j; - u32 tmp1 = 0; - u32 tmp2 = 0; - - backup[0] = b43legacy_radio_read16(dev, 0x0043); - backup[14] = b43legacy_radio_read16(dev, 0x0051); - backup[15] = b43legacy_radio_read16(dev, 0x0052); - backup[1] = b43legacy_phy_read(dev, 0x0015); - backup[16] = b43legacy_phy_read(dev, 0x005A); - backup[17] = b43legacy_phy_read(dev, 0x0059); - backup[18] = b43legacy_phy_read(dev, 0x0058); - if (phy->type == B43legacy_PHYTYPE_B) { - backup[2] = b43legacy_phy_read(dev, 0x0030); - backup[3] = b43legacy_read16(dev, 0x03EC); - b43legacy_phy_write(dev, 0x0030, 0x00FF); - b43legacy_write16(dev, 0x03EC, 0x3F3F); - } else { - if (phy->gmode) { - backup[4] = b43legacy_phy_read(dev, 0x0811); - backup[5] = b43legacy_phy_read(dev, 0x0812); - backup[6] = b43legacy_phy_read(dev, 0x0814); - backup[7] = b43legacy_phy_read(dev, 0x0815); - backup[8] = b43legacy_phy_read(dev, - B43legacy_PHY_G_CRS); - backup[9] = b43legacy_phy_read(dev, 0x0802); - b43legacy_phy_write(dev, 0x0814, - (b43legacy_phy_read(dev, 0x0814) - | 0x0003)); - b43legacy_phy_write(dev, 0x0815, - (b43legacy_phy_read(dev, 0x0815) - & 0xFFFC)); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - (b43legacy_phy_read(dev, - B43legacy_PHY_G_CRS) & 0x7FFF)); - b43legacy_phy_write(dev, 0x0802, - (b43legacy_phy_read(dev, 0x0802) - & 0xFFFC)); - if (phy->rev > 1) { /* loopback gain enabled */ - backup[19] = b43legacy_phy_read(dev, 0x080F); - backup[20] = b43legacy_phy_read(dev, 0x0810); - if (phy->rev >= 3) - b43legacy_phy_write(dev, 0x080F, - 0xC020); - else - b43legacy_phy_write(dev, 0x080F, - 0x8020); - b43legacy_phy_write(dev, 0x0810, 0x0000); - } - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(0, 1, 1))); - if (phy->rev < 7 || - !(dev->dev->bus->sprom.boardflags_lo - & B43legacy_BFL_EXTLNA)) - b43legacy_phy_write(dev, 0x0811, 0x01B3); - else - b43legacy_phy_write(dev, 0x0811, 0x09B3); - } - } - b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, - (b43legacy_read16(dev, B43legacy_MMIO_PHY_RADIO) - | 0x8000)); - backup[10] = b43legacy_phy_read(dev, 0x0035); - b43legacy_phy_write(dev, 0x0035, - (b43legacy_phy_read(dev, 0x0035) & 0xFF7F)); - backup[11] = b43legacy_read16(dev, 0x03E6); - backup[12] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); - - /* Initialization */ - if (phy->analog == 0) - b43legacy_write16(dev, 0x03E6, 0x0122); - else { - if (phy->analog >= 2) - b43legacy_phy_write(dev, 0x0003, - (b43legacy_phy_read(dev, 0x0003) - & 0xFFBF) | 0x0040); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, - (b43legacy_read16(dev, - B43legacy_MMIO_CHANNEL_EXT) | 0x2000)); - } - - ret = b43legacy_radio_calibrationvalue(dev); - - if (phy->type == B43legacy_PHYTYPE_B) - b43legacy_radio_write16(dev, 0x0078, 0x0026); - - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(0, 1, 1))); - b43legacy_phy_write(dev, 0x0015, 0xBFAF); - b43legacy_phy_write(dev, 0x002B, 0x1403); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(0, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xBFA0); - b43legacy_radio_write16(dev, 0x0051, - (b43legacy_radio_read16(dev, 0x0051) - | 0x0004)); - if (phy->radio_rev == 8) - b43legacy_radio_write16(dev, 0x0043, 0x001F); - else { - b43legacy_radio_write16(dev, 0x0052, 0x0000); - b43legacy_radio_write16(dev, 0x0043, - (b43legacy_radio_read16(dev, 0x0043) - & 0xFFF0) | 0x0009); - } - b43legacy_phy_write(dev, 0x0058, 0x0000); - - for (i = 0; i < 16; i++) { - b43legacy_phy_write(dev, 0x005A, 0x0480); - b43legacy_phy_write(dev, 0x0059, 0xC810); - b43legacy_phy_write(dev, 0x0058, 0x000D); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xAFB0); - udelay(10); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xEFB0); - udelay(10); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 0))); - b43legacy_phy_write(dev, 0x0015, 0xFFF0); - udelay(20); - tmp1 += b43legacy_phy_read(dev, 0x002D); - b43legacy_phy_write(dev, 0x0058, 0x0000); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xAFB0); - } - - tmp1++; - tmp1 >>= 9; - udelay(10); - b43legacy_phy_write(dev, 0x0058, 0x0000); - - for (i = 0; i < 16; i++) { - b43legacy_radio_write16(dev, 0x0078, (flip_4bit(i) << 1) - | 0x0020); - backup[13] = b43legacy_radio_read16(dev, 0x0078); - udelay(10); - for (j = 0; j < 16; j++) { - b43legacy_phy_write(dev, 0x005A, 0x0D80); - b43legacy_phy_write(dev, 0x0059, 0xC810); - b43legacy_phy_write(dev, 0x0058, 0x000D); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xAFB0); - udelay(10); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xEFB0); - udelay(10); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 0))); - b43legacy_phy_write(dev, 0x0015, 0xFFF0); - udelay(10); - tmp2 += b43legacy_phy_read(dev, 0x002D); - b43legacy_phy_write(dev, 0x0058, 0x0000); - if (phy->gmode) - b43legacy_phy_write(dev, 0x0812, - b43legacy_get_812_value(dev, - LPD(1, 0, 1))); - b43legacy_phy_write(dev, 0x0015, 0xAFB0); - } - tmp2++; - tmp2 >>= 8; - if (tmp1 < tmp2) - break; - } - - /* Restore the registers */ - b43legacy_phy_write(dev, 0x0015, backup[1]); - b43legacy_radio_write16(dev, 0x0051, backup[14]); - b43legacy_radio_write16(dev, 0x0052, backup[15]); - b43legacy_radio_write16(dev, 0x0043, backup[0]); - b43legacy_phy_write(dev, 0x005A, backup[16]); - b43legacy_phy_write(dev, 0x0059, backup[17]); - b43legacy_phy_write(dev, 0x0058, backup[18]); - b43legacy_write16(dev, 0x03E6, backup[11]); - if (phy->analog != 0) - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[12]); - b43legacy_phy_write(dev, 0x0035, backup[10]); - b43legacy_radio_selectchannel(dev, phy->channel, 1); - if (phy->type == B43legacy_PHYTYPE_B) { - b43legacy_phy_write(dev, 0x0030, backup[2]); - b43legacy_write16(dev, 0x03EC, backup[3]); - } else { - if (phy->gmode) { - b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, - (b43legacy_read16(dev, - B43legacy_MMIO_PHY_RADIO) & 0x7FFF)); - b43legacy_phy_write(dev, 0x0811, backup[4]); - b43legacy_phy_write(dev, 0x0812, backup[5]); - b43legacy_phy_write(dev, 0x0814, backup[6]); - b43legacy_phy_write(dev, 0x0815, backup[7]); - b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, - backup[8]); - b43legacy_phy_write(dev, 0x0802, backup[9]); - if (phy->rev > 1) { - b43legacy_phy_write(dev, 0x080F, backup[19]); - b43legacy_phy_write(dev, 0x0810, backup[20]); - } - } - } - if (i >= 15) - ret = backup[13]; - - return ret; -} - -static inline -u16 freq_r3A_value(u16 frequency) -{ - u16 value; - - if (frequency < 5091) - value = 0x0040; - else if (frequency < 5321) - value = 0x0000; - else if (frequency < 5806) - value = 0x0080; - else - value = 0x0040; - - return value; -} - -void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev) -{ - static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; - static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; - u16 tmp = b43legacy_radio_read16(dev, 0x001E); - int i; - int j; - - for (i = 0; i < 5; i++) { - for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] | data_low[j])) { - b43legacy_phy_write(dev, 0x0069, (i - j) << 8 | - 0x00C0); - return; - } - } - } -} - -int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, - u8 channel, - int synthetic_pu_workaround) -{ - struct b43legacy_phy *phy = &dev->phy; - - if (channel == 0xFF) { - switch (phy->type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG; - break; - default: - B43legacy_WARN_ON(1); - } - } - -/* TODO: Check if channel is valid - return -EINVAL if not */ - if (synthetic_pu_workaround) - b43legacy_synth_pu_workaround(dev, channel); - - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, - channel2freq_bg(channel)); - - if (channel == 14) { - if (dev->dev->bus->sprom.country_code == 5) /* JAPAN) */ - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - b43legacy_shm_read32(dev, - B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET) - & ~(1 << 7)); - else - b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET, - b43legacy_shm_read32(dev, - B43legacy_SHM_SHARED, - B43legacy_UCODEFLAGS_OFFSET) - | (1 << 7)); - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, - b43legacy_read16(dev, - B43legacy_MMIO_CHANNEL_EXT) | (1 << 11)); - } else - b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, - b43legacy_read16(dev, - B43legacy_MMIO_CHANNEL_EXT) & 0xF7BF); - - phy->channel = channel; - /*XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states - * that 2000 usecs might suffice. */ - msleep(8); - - return 0; -} - -void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val) -{ - u16 tmp; - - val <<= 8; - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0022) & 0xFCFF; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0022, tmp | val); - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x03A8) & 0xFCFF; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x03A8, tmp | val); - tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0054) & 0xFCFF; - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0054, tmp | val); -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */ -static u16 b43legacy_get_txgain_base_band(u16 txpower) -{ - u16 ret; - - B43legacy_WARN_ON(txpower > 63); - - if (txpower >= 54) - ret = 2; - else if (txpower >= 49) - ret = 4; - else if (txpower >= 44) - ret = 5; - else - ret = 6; - - return ret; -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */ -static u16 b43legacy_get_txgain_freq_power_amp(u16 txpower) -{ - u16 ret; - - B43legacy_WARN_ON(txpower > 63); - - if (txpower >= 32) - ret = 0; - else if (txpower >= 25) - ret = 1; - else if (txpower >= 20) - ret = 2; - else if (txpower >= 12) - ret = 3; - else - ret = 4; - - return ret; -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */ -static u16 b43legacy_get_txgain_dac(u16 txpower) -{ - u16 ret; - - B43legacy_WARN_ON(txpower > 63); - - if (txpower >= 54) - ret = txpower - 53; - else if (txpower >= 49) - ret = txpower - 42; - else if (txpower >= 44) - ret = txpower - 37; - else if (txpower >= 32) - ret = txpower - 32; - else if (txpower >= 25) - ret = txpower - 20; - else if (txpower >= 20) - ret = txpower - 13; - else if (txpower >= 12) - ret = txpower - 8; - else - ret = txpower; - - return ret; -} - -void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 pamp; - u16 base; - u16 dac; - u16 ilt; - - txpower = clamp_val(txpower, 0, 63); - - pamp = b43legacy_get_txgain_freq_power_amp(txpower); - pamp <<= 5; - pamp &= 0x00E0; - b43legacy_phy_write(dev, 0x0019, pamp); - - base = b43legacy_get_txgain_base_band(txpower); - base &= 0x000F; - b43legacy_phy_write(dev, 0x0017, base | 0x0020); - - ilt = b43legacy_ilt_read(dev, 0x3001); - ilt &= 0x0007; - - dac = b43legacy_get_txgain_dac(txpower); - dac <<= 3; - dac |= ilt; - - b43legacy_ilt_write(dev, 0x3001, dac); - - phy->txpwr_offset = txpower; - - /* TODO: FuncPlaceholder (Adjust BB loft cancel) */ -} - -void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev, - u16 baseband_attenuation, - u16 radio_attenuation, - u16 txpower) -{ - struct b43legacy_phy *phy = &dev->phy; - - if (baseband_attenuation == 0xFFFF) - baseband_attenuation = phy->bbatt; - if (radio_attenuation == 0xFFFF) - radio_attenuation = phy->rfatt; - if (txpower == 0xFFFF) - txpower = phy->txctl1; - phy->bbatt = baseband_attenuation; - phy->rfatt = radio_attenuation; - phy->txctl1 = txpower; - - B43legacy_WARN_ON(baseband_attenuation > 11); - if (phy->radio_rev < 6) - B43legacy_WARN_ON(radio_attenuation > 9); - else - B43legacy_WARN_ON(radio_attenuation > 31); - B43legacy_WARN_ON(txpower > 7); - - b43legacy_phy_set_baseband_attenuation(dev, baseband_attenuation); - b43legacy_radio_write16(dev, 0x0043, radio_attenuation); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0064, - radio_attenuation); - if (phy->radio_ver == 0x2050) - b43legacy_radio_write16(dev, 0x0052, - (b43legacy_radio_read16(dev, 0x0052) - & ~0x0070) | ((txpower << 4) & 0x0070)); - /* FIXME: The spec is very weird and unclear here. */ - if (phy->type == B43legacy_PHYTYPE_G) - b43legacy_phy_lo_adjust(dev, 0); -} - -u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - - if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) - return 0; - return 2; -} - -u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - u16 att = 0xFFFF; - - switch (phy->radio_ver) { - case 0x2053: - switch (phy->radio_rev) { - case 1: - att = 6; - break; - } - break; - case 0x2050: - switch (phy->radio_rev) { - case 0: - att = 5; - break; - case 1: - if (phy->type == B43legacy_PHYTYPE_G) { - if (is_bcm_board_vendor(dev) && - dev->dev->bus->boardinfo.type == 0x421 && - dev->dev->bus->boardinfo.rev >= 30) - att = 3; - else if (is_bcm_board_vendor(dev) && - dev->dev->bus->boardinfo.type == 0x416) - att = 3; - else - att = 1; - } else { - if (is_bcm_board_vendor(dev) && - dev->dev->bus->boardinfo.type == 0x421 && - dev->dev->bus->boardinfo.rev >= 30) - att = 7; - else - att = 6; - } - break; - case 2: - if (phy->type == B43legacy_PHYTYPE_G) { - if (is_bcm_board_vendor(dev) && - dev->dev->bus->boardinfo.type == 0x421 && - dev->dev->bus->boardinfo.rev >= 30) - att = 3; - else if (is_bcm_board_vendor(dev) && - dev->dev->bus->boardinfo.type == - 0x416) - att = 5; - else if (dev->dev->bus->chip_id == 0x4320) - att = 4; - else - att = 3; - } else - att = 6; - break; - case 3: - att = 5; - break; - case 4: - case 5: - att = 1; - break; - case 6: - case 7: - att = 5; - break; - case 8: - att = 0x1A; - break; - case 9: - default: - att = 5; - } - } - if (is_bcm_board_vendor(dev) && - dev->dev->bus->boardinfo.type == 0x421) { - if (dev->dev->bus->boardinfo.rev < 0x43) - att = 2; - else if (dev->dev->bus->boardinfo.rev < 0x51) - att = 3; - } - if (att == 0xFFFF) - att = 5; - - return att; -} - -u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - - if (phy->radio_ver != 0x2050) - return 0; - if (phy->radio_rev == 1) - return 3; - if (phy->radio_rev < 6) - return 2; - if (phy->radio_rev == 8) - return 1; - return 0; -} - -void b43legacy_radio_turn_on(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - int err; - u8 channel; - - might_sleep(); - - if (phy->radio_on) - return; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - b43legacy_phy_write(dev, 0x0015, 0x8000); - b43legacy_phy_write(dev, 0x0015, 0xCC00); - b43legacy_phy_write(dev, 0x0015, - (phy->gmode ? 0x00C0 : 0x0000)); - if (phy->radio_off_context.valid) { - /* Restore the RFover values. */ - b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, - phy->radio_off_context.rfover); - b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL, - phy->radio_off_context.rfoverval); - phy->radio_off_context.valid = 0; - } - channel = phy->channel; - err = b43legacy_radio_selectchannel(dev, - B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1); - err |= b43legacy_radio_selectchannel(dev, channel, 0); - B43legacy_WARN_ON(err); - break; - default: - B43legacy_BUG_ON(1); - } - phy->radio_on = 1; -} - -void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force) -{ - struct b43legacy_phy *phy = &dev->phy; - - if (!phy->radio_on && !force) - return; - - if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) { - u16 rfover, rfoverval; - - rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER); - rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL); - if (!force) { - phy->radio_off_context.rfover = rfover; - phy->radio_off_context.rfoverval = rfoverval; - phy->radio_off_context.valid = 1; - } - b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C); - b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL, - rfoverval & 0xFF73); - } else - b43legacy_phy_write(dev, 0x0015, 0xAA00); - phy->radio_on = 0; - b43legacydbg(dev->wl, "Radio initialized\n"); -} - -void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev) -{ - struct b43legacy_phy *phy = &dev->phy; - - switch (phy->type) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0058, - 0x7F7F); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x005a, - 0x7F7F); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0070, - 0x7F7F); - b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0072, - 0x7F7F); - break; - } -} diff --git a/drivers/net/wireless/b43legacy/radio.h b/drivers/net/wireless/b43legacy/radio.h deleted file mode 100644 index ec4de2811c52..000000000000 --- a/drivers/net/wireless/b43legacy/radio.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef B43legacy_RADIO_H_ -#define B43legacy_RADIO_H_ - -#include "b43legacy.h" - - -#define B43legacy_RADIO_DEFAULT_CHANNEL_BG 6 - -/* Force antenna 0. */ -#define B43legacy_RADIO_TXANTENNA_0 0 -/* Force antenna 1. */ -#define B43legacy_RADIO_TXANTENNA_1 1 -/* Use the RX antenna, that was selected for the most recently - * received good PLCP header. - */ -#define B43legacy_RADIO_TXANTENNA_LASTPLCP 3 -#define B43legacy_RADIO_TXANTENNA_DEFAULT B43legacy_RADIO_TXANTENNA_LASTPLCP - -#define B43legacy_RADIO_INTERFMODE_NONE 0 -#define B43legacy_RADIO_INTERFMODE_NONWLAN 1 -#define B43legacy_RADIO_INTERFMODE_MANUALWLAN 2 -#define B43legacy_RADIO_INTERFMODE_AUTOWLAN 3 - - -void b43legacy_radio_lock(struct b43legacy_wldev *dev); -void b43legacy_radio_unlock(struct b43legacy_wldev *dev); - -u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset); -void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val); - -u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev); - -void b43legacy_radio_turn_on(struct b43legacy_wldev *dev); -void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force); - -int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, u8 channel, - int synthetic_pu_workaround); - -void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower); -void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev, - u16 baseband_attenuation, u16 attenuation, - u16 txpower); - -u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev); -u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev); -u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev); - -void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val); - -void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev); - -u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel); -u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev); - -int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev, - int mode); - -void b43legacy_calc_nrssi_slope(struct b43legacy_wldev *dev); -void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev); -s16 b43legacy_nrssi_hw_read(struct b43legacy_wldev *dev, u16 offset); -void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val); -void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val); -void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev); - -void b43legacy_radio_set_tx_iq(struct b43legacy_wldev *dev); -u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev); - -#endif /* B43legacy_RADIO_H_ */ diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c deleted file mode 100644 index d579df72b783..000000000000 --- a/drivers/net/wireless/b43legacy/rfkill.c +++ /dev/null @@ -1,91 +0,0 @@ -/* - - Broadcom B43 wireless driver - RFKILL support - - Copyright (c) 2007 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "radio.h" -#include "b43legacy.h" - - -/* Returns TRUE, if the radio is enabled in hardware. */ -bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) -{ - if (dev->phy.rev >= 3) { - if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) - & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) - return 1; - } else { - /* To prevent CPU fault on PPC, do not read a register - * unless the interface is started; however, on resume - * for hibernation, this routine is entered early. When - * that happens, unconditionally return TRUE. - */ - if (b43legacy_status(dev) < B43legacy_STAT_STARTED) - return 1; - if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO) - & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK) - return 1; - } - return 0; -} - -/* The poll callback for the hardware button. */ -void b43legacy_rfkill_poll(struct ieee80211_hw *hw) -{ - struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); - struct b43legacy_wldev *dev = wl->current_dev; - struct ssb_bus *bus = dev->dev->bus; - bool enabled; - bool brought_up = false; - - mutex_lock(&wl->mutex); - if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { - if (ssb_bus_powerup(bus, 0)) { - mutex_unlock(&wl->mutex); - return; - } - ssb_device_enable(dev->dev, 0); - brought_up = true; - } - - enabled = b43legacy_is_hw_radio_enabled(dev); - - if (unlikely(enabled != dev->radio_hw_enable)) { - dev->radio_hw_enable = enabled; - b43legacyinfo(wl, "Radio hardware status changed to %s\n", - enabled ? "ENABLED" : "DISABLED"); - wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); - if (enabled != dev->phy.radio_on) { - if (enabled) - b43legacy_radio_turn_on(dev); - else - b43legacy_radio_turn_off(dev, 0); - } - } - - if (brought_up) { - ssb_device_disable(dev->dev, 0); - ssb_bus_may_powerdown(bus); - } - - mutex_unlock(&wl->mutex); -} diff --git a/drivers/net/wireless/b43legacy/rfkill.h b/drivers/net/wireless/b43legacy/rfkill.h deleted file mode 100644 index 75585571c544..000000000000 --- a/drivers/net/wireless/b43legacy/rfkill.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef B43legacy_RFKILL_H_ -#define B43legacy_RFKILL_H_ - -struct ieee80211_hw; -struct b43legacy_wldev; - -void b43legacy_rfkill_poll(struct ieee80211_hw *hw); - -bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev); - -#endif /* B43legacy_RFKILL_H_ */ diff --git a/drivers/net/wireless/b43legacy/sysfs.c b/drivers/net/wireless/b43legacy/sysfs.c deleted file mode 100644 index 56c384fa9b1f..000000000000 --- a/drivers/net/wireless/b43legacy/sysfs.c +++ /dev/null @@ -1,238 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - SYSFS support routines - - Copyright (c) 2006 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "sysfs.h" -#include "b43legacy.h" -#include "main.h" -#include "phy.h" -#include "radio.h" - -#include - - -#define GENERIC_FILESIZE 64 - - -static int get_integer(const char *buf, size_t count) -{ - char tmp[10 + 1] = { 0 }; - int ret = -EINVAL; - - if (count == 0) - goto out; - count = min(count, (size_t)10); - memcpy(tmp, buf, count); - ret = simple_strtol(tmp, NULL, 10); -out: - return ret; -} - -static int get_boolean(const char *buf, size_t count) -{ - if (count != 0) { - if (buf[0] == '1') - return 1; - if (buf[0] == '0') - return 0; - if (count >= 4 && memcmp(buf, "true", 4) == 0) - return 1; - if (count >= 5 && memcmp(buf, "false", 5) == 0) - return 0; - if (count >= 3 && memcmp(buf, "yes", 3) == 0) - return 1; - if (count >= 2 && memcmp(buf, "no", 2) == 0) - return 0; - if (count >= 2 && memcmp(buf, "on", 2) == 0) - return 1; - if (count >= 3 && memcmp(buf, "off", 3) == 0) - return 0; - } - return -EINVAL; -} - -static ssize_t b43legacy_attr_interfmode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev); - ssize_t count = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&wldev->wl->mutex); - - switch (wldev->phy.interfmode) { - case B43legacy_INTERFMODE_NONE: - count = snprintf(buf, PAGE_SIZE, "0 (No Interference" - " Mitigation)\n"); - break; - case B43legacy_INTERFMODE_NONWLAN: - count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference" - " Mitigation)\n"); - break; - case B43legacy_INTERFMODE_MANUALWLAN: - count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference" - " Mitigation)\n"); - break; - default: - B43legacy_WARN_ON(1); - } - - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static ssize_t b43legacy_attr_interfmode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev); - unsigned long flags; - int err; - int mode; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mode = get_integer(buf, count); - switch (mode) { - case 0: - mode = B43legacy_INTERFMODE_NONE; - break; - case 1: - mode = B43legacy_INTERFMODE_NONWLAN; - break; - case 2: - mode = B43legacy_INTERFMODE_MANUALWLAN; - break; - case 3: - mode = B43legacy_INTERFMODE_AUTOWLAN; - break; - default: - return -EINVAL; - } - - mutex_lock(&wldev->wl->mutex); - spin_lock_irqsave(&wldev->wl->irq_lock, flags); - - err = b43legacy_radio_set_interference_mitigation(wldev, mode); - if (err) - b43legacyerr(wldev->wl, "Interference Mitigation not " - "supported by device\n"); - mmiowb(); - spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); - mutex_unlock(&wldev->wl->mutex); - - return err ? err : count; -} - -static DEVICE_ATTR(interference, 0644, - b43legacy_attr_interfmode_show, - b43legacy_attr_interfmode_store); - -static ssize_t b43legacy_attr_preamble_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev); - ssize_t count; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&wldev->wl->mutex); - - if (wldev->short_preamble) - count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble" - " enabled)\n"); - else - count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble" - " disabled)\n"); - - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static ssize_t b43legacy_attr_preamble_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct b43legacy_wldev *wldev = dev_to_b43legacy_wldev(dev); - unsigned long flags; - int value; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - value = get_boolean(buf, count); - if (value < 0) - return value; - mutex_lock(&wldev->wl->mutex); - spin_lock_irqsave(&wldev->wl->irq_lock, flags); - - wldev->short_preamble = !!value; - - spin_unlock_irqrestore(&wldev->wl->irq_lock, flags); - mutex_unlock(&wldev->wl->mutex); - - return count; -} - -static DEVICE_ATTR(shortpreamble, 0644, - b43legacy_attr_preamble_show, - b43legacy_attr_preamble_store); - -int b43legacy_sysfs_register(struct b43legacy_wldev *wldev) -{ - struct device *dev = wldev->dev->dev; - int err; - - B43legacy_WARN_ON(b43legacy_status(wldev) != - B43legacy_STAT_INITIALIZED); - - err = device_create_file(dev, &dev_attr_interference); - if (err) - goto out; - err = device_create_file(dev, &dev_attr_shortpreamble); - if (err) - goto err_remove_interfmode; - -out: - return err; -err_remove_interfmode: - device_remove_file(dev, &dev_attr_interference); - goto out; -} - -void b43legacy_sysfs_unregister(struct b43legacy_wldev *wldev) -{ - struct device *dev = wldev->dev->dev; - - device_remove_file(dev, &dev_attr_shortpreamble); - device_remove_file(dev, &dev_attr_interference); -} diff --git a/drivers/net/wireless/b43legacy/sysfs.h b/drivers/net/wireless/b43legacy/sysfs.h deleted file mode 100644 index 417d509803c7..000000000000 --- a/drivers/net/wireless/b43legacy/sysfs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef B43legacy_SYSFS_H_ -#define B43legacy_SYSFS_H_ - -struct b43legacy_wldev; - -int b43legacy_sysfs_register(struct b43legacy_wldev *dev); -void b43legacy_sysfs_unregister(struct b43legacy_wldev *dev); - -#endif /* B43legacy_SYSFS_H_ */ diff --git a/drivers/net/wireless/b43legacy/xmit.c b/drivers/net/wireless/b43legacy/xmit.c deleted file mode 100644 index 103f3c9e7f58..000000000000 --- a/drivers/net/wireless/b43legacy/xmit.c +++ /dev/null @@ -1,681 +0,0 @@ -/* - - Broadcom B43legacy wireless driver - - Transmission (TX/RX) related functions. - - Copyright (C) 2005 Martin Langer - Copyright (C) 2005 Stefano Brivio - Copyright (C) 2005, 2006 Michael Buesch - Copyright (C) 2005 Danny van Dyk - Copyright (C) 2005 Andreas Jaggi - Copyright (C) 2007 Larry Finger - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include - -#include "xmit.h" -#include "phy.h" -#include "dma.h" -#include "pio.h" - - -/* Extract the bitrate out of a CCK PLCP header. */ -static u8 b43legacy_plcp_get_bitrate_idx_cck(struct b43legacy_plcp_hdr6 *plcp) -{ - switch (plcp->raw[0]) { - case 0x0A: - return 0; - case 0x14: - return 1; - case 0x37: - return 2; - case 0x6E: - return 3; - } - B43legacy_BUG_ON(1); - return -1; -} - -/* Extract the bitrate out of an OFDM PLCP header. */ -static u8 b43legacy_plcp_get_bitrate_idx_ofdm(struct b43legacy_plcp_hdr6 *plcp, - bool aphy) -{ - int base = aphy ? 0 : 4; - - switch (plcp->raw[0] & 0xF) { - case 0xB: - return base + 0; - case 0xF: - return base + 1; - case 0xA: - return base + 2; - case 0xE: - return base + 3; - case 0x9: - return base + 4; - case 0xD: - return base + 5; - case 0x8: - return base + 6; - case 0xC: - return base + 7; - } - B43legacy_BUG_ON(1); - return -1; -} - -u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate) -{ - switch (bitrate) { - case B43legacy_CCK_RATE_1MB: - return 0x0A; - case B43legacy_CCK_RATE_2MB: - return 0x14; - case B43legacy_CCK_RATE_5MB: - return 0x37; - case B43legacy_CCK_RATE_11MB: - return 0x6E; - } - B43legacy_BUG_ON(1); - return 0; -} - -u8 b43legacy_plcp_get_ratecode_ofdm(const u8 bitrate) -{ - switch (bitrate) { - case B43legacy_OFDM_RATE_6MB: - return 0xB; - case B43legacy_OFDM_RATE_9MB: - return 0xF; - case B43legacy_OFDM_RATE_12MB: - return 0xA; - case B43legacy_OFDM_RATE_18MB: - return 0xE; - case B43legacy_OFDM_RATE_24MB: - return 0x9; - case B43legacy_OFDM_RATE_36MB: - return 0xD; - case B43legacy_OFDM_RATE_48MB: - return 0x8; - case B43legacy_OFDM_RATE_54MB: - return 0xC; - } - B43legacy_BUG_ON(1); - return 0; -} - -void b43legacy_generate_plcp_hdr(struct b43legacy_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate) -{ - __le32 *data = &(plcp->data); - __u8 *raw = plcp->raw; - - if (b43legacy_is_ofdm_rate(bitrate)) { - u16 d; - - d = b43legacy_plcp_get_ratecode_ofdm(bitrate); - B43legacy_WARN_ON(octets & 0xF000); - d |= (octets << 5); - *data = cpu_to_le32(d); - } else { - u32 plen; - - plen = octets * 16 / bitrate; - if ((octets * 16 % bitrate) > 0) { - plen++; - if ((bitrate == B43legacy_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) - raw[1] = 0x84; - else - raw[1] = 0x04; - } else - raw[1] = 0x04; - *data |= cpu_to_le32(plen << 16); - raw[0] = b43legacy_plcp_get_ratecode_cck(bitrate); - } -} - -static u8 b43legacy_calc_fallback_rate(u8 bitrate) -{ - switch (bitrate) { - case B43legacy_CCK_RATE_1MB: - return B43legacy_CCK_RATE_1MB; - case B43legacy_CCK_RATE_2MB: - return B43legacy_CCK_RATE_1MB; - case B43legacy_CCK_RATE_5MB: - return B43legacy_CCK_RATE_2MB; - case B43legacy_CCK_RATE_11MB: - return B43legacy_CCK_RATE_5MB; - case B43legacy_OFDM_RATE_6MB: - return B43legacy_CCK_RATE_5MB; - case B43legacy_OFDM_RATE_9MB: - return B43legacy_OFDM_RATE_6MB; - case B43legacy_OFDM_RATE_12MB: - return B43legacy_OFDM_RATE_9MB; - case B43legacy_OFDM_RATE_18MB: - return B43legacy_OFDM_RATE_12MB; - case B43legacy_OFDM_RATE_24MB: - return B43legacy_OFDM_RATE_18MB; - case B43legacy_OFDM_RATE_36MB: - return B43legacy_OFDM_RATE_24MB; - case B43legacy_OFDM_RATE_48MB: - return B43legacy_OFDM_RATE_36MB; - case B43legacy_OFDM_RATE_54MB: - return B43legacy_OFDM_RATE_48MB; - } - B43legacy_BUG_ON(1); - return 0; -} - -static int generate_txhdr_fw3(struct b43legacy_wldev *dev, - struct b43legacy_txhdr_fw3 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - struct ieee80211_tx_info *info, - u16 cookie) -{ - const struct ieee80211_hdr *wlhdr; - int use_encryption = !!info->control.hw_key; - u8 rate; - struct ieee80211_rate *rate_fb; - int rate_ofdm; - int rate_fb_ofdm; - unsigned int plcp_fragment_len; - u32 mac_ctl = 0; - u16 phy_ctl = 0; - struct ieee80211_rate *tx_rate; - struct ieee80211_tx_rate *rates; - - wlhdr = (const struct ieee80211_hdr *)fragment_data; - - memset(txhdr, 0, sizeof(*txhdr)); - - tx_rate = ieee80211_get_tx_rate(dev->wl->hw, info); - - rate = tx_rate->hw_value; - rate_ofdm = b43legacy_is_ofdm_rate(rate); - rate_fb = ieee80211_get_alt_retry_rate(dev->wl->hw, info, 0) ? : tx_rate; - rate_fb_ofdm = b43legacy_is_ofdm_rate(rate_fb->hw_value); - - txhdr->mac_frame_ctl = wlhdr->frame_control; - memcpy(txhdr->tx_receiver, wlhdr->addr1, 6); - - /* Calculate duration for fallback rate */ - if ((rate_fb->hw_value == rate) || - (wlhdr->duration_id & cpu_to_le16(0x8000)) || - (wlhdr->duration_id == cpu_to_le16(0))) { - /* If the fallback rate equals the normal rate or the - * dur_id field contains an AID, CFP magic or 0, - * use the original dur_id field. */ - txhdr->dur_fb = wlhdr->duration_id; - } else { - txhdr->dur_fb = ieee80211_generic_frame_duration(dev->wl->hw, - info->control.vif, - fragment_len, - rate_fb); - } - - plcp_fragment_len = fragment_len + FCS_LEN; - if (use_encryption) { - u8 key_idx = info->control.hw_key->hw_key_idx; - struct b43legacy_key *key; - int wlhdr_len; - size_t iv_len; - - B43legacy_WARN_ON(key_idx >= dev->max_nr_keys); - key = &(dev->key[key_idx]); - - if (key->enabled) { - /* Hardware appends ICV. */ - plcp_fragment_len += info->control.hw_key->icv_len; - - key_idx = b43legacy_kidx_to_fw(dev, key_idx); - mac_ctl |= (key_idx << B43legacy_TX4_MAC_KEYIDX_SHIFT) & - B43legacy_TX4_MAC_KEYIDX; - mac_ctl |= (key->algorithm << - B43legacy_TX4_MAC_KEYALG_SHIFT) & - B43legacy_TX4_MAC_KEYALG; - wlhdr_len = ieee80211_hdrlen(wlhdr->frame_control); - iv_len = min((size_t)info->control.hw_key->iv_len, - ARRAY_SIZE(txhdr->iv)); - memcpy(txhdr->iv, ((u8 *)wlhdr) + wlhdr_len, iv_len); - } else { - /* This key is invalid. This might only happen - * in a short timeframe after machine resume before - * we were able to reconfigure keys. - * Drop this packet completely. Do not transmit it - * unencrypted to avoid leaking information. */ - return -ENOKEY; - } - } - b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) - (&txhdr->plcp), plcp_fragment_len, - rate); - b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) - (&txhdr->plcp_fb), plcp_fragment_len, - rate_fb->hw_value); - - /* PHY TX Control word */ - if (rate_ofdm) - phy_ctl |= B43legacy_TX4_PHY_ENC_OFDM; - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - phy_ctl |= B43legacy_TX4_PHY_SHORTPRMBL; - switch (info->antenna_sel_tx) { - case 0: - phy_ctl |= B43legacy_TX4_PHY_ANTLAST; - break; - case 1: - phy_ctl |= B43legacy_TX4_PHY_ANT0; - break; - case 2: - phy_ctl |= B43legacy_TX4_PHY_ANT1; - break; - default: - B43legacy_BUG_ON(1); - } - - /* MAC control */ - rates = info->control.rates; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) - mac_ctl |= B43legacy_TX4_MAC_ACK; - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) - mac_ctl |= B43legacy_TX4_MAC_HWSEQ; - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - mac_ctl |= B43legacy_TX4_MAC_STMSDU; - if (rate_fb_ofdm) - mac_ctl |= B43legacy_TX4_MAC_FALLBACKOFDM; - - /* Overwrite rates[0].count to make the retry calculation - * in the tx status easier. need the actual retry limit to - * detect whether the fallback rate was used. - */ - if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (rates[0].count <= dev->wl->hw->conf.long_frame_max_tx_count)) { - rates[0].count = dev->wl->hw->conf.long_frame_max_tx_count; - mac_ctl |= B43legacy_TX4_MAC_LONGFRAME; - } else { - rates[0].count = dev->wl->hw->conf.short_frame_max_tx_count; - } - - /* Generate the RTS or CTS-to-self frame */ - if ((rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) { - unsigned int len; - struct ieee80211_hdr *hdr; - int rts_rate; - int rts_rate_fb; - int rts_rate_ofdm; - int rts_rate_fb_ofdm; - - rts_rate = ieee80211_get_rts_cts_rate(dev->wl->hw, info)->hw_value; - rts_rate_ofdm = b43legacy_is_ofdm_rate(rts_rate); - rts_rate_fb = b43legacy_calc_fallback_rate(rts_rate); - rts_rate_fb_ofdm = b43legacy_is_ofdm_rate(rts_rate_fb); - if (rts_rate_fb_ofdm) - mac_ctl |= B43legacy_TX4_MAC_CTSFALLBACKOFDM; - - if (rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - ieee80211_ctstoself_get(dev->wl->hw, - info->control.vif, - fragment_data, - fragment_len, info, - (struct ieee80211_cts *) - (txhdr->rts_frame)); - mac_ctl |= B43legacy_TX4_MAC_SENDCTS; - len = sizeof(struct ieee80211_cts); - } else { - ieee80211_rts_get(dev->wl->hw, - info->control.vif, - fragment_data, fragment_len, info, - (struct ieee80211_rts *) - (txhdr->rts_frame)); - mac_ctl |= B43legacy_TX4_MAC_SENDRTS; - len = sizeof(struct ieee80211_rts); - } - len += FCS_LEN; - b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) - (&txhdr->rts_plcp), - len, rts_rate); - b43legacy_generate_plcp_hdr((struct b43legacy_plcp_hdr4 *) - (&txhdr->rts_plcp_fb), - len, rts_rate_fb); - hdr = (struct ieee80211_hdr *)(&txhdr->rts_frame); - txhdr->rts_dur_fb = hdr->duration_id; - } - - /* Magic cookie */ - txhdr->cookie = cpu_to_le16(cookie); - - /* Apply the bitfields */ - txhdr->mac_ctl = cpu_to_le32(mac_ctl); - txhdr->phy_ctl = cpu_to_le16(phy_ctl); - - return 0; -} - -int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, - u8 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - struct ieee80211_tx_info *info, - u16 cookie) -{ - return generate_txhdr_fw3(dev, (struct b43legacy_txhdr_fw3 *)txhdr, - fragment_data, fragment_len, - info, cookie); -} - -static s8 b43legacy_rssi_postprocess(struct b43legacy_wldev *dev, - u8 in_rssi, int ofdm, - int adjust_2053, int adjust_2050) -{ - struct b43legacy_phy *phy = &dev->phy; - s32 tmp; - - switch (phy->radio_ver) { - case 0x2050: - if (ofdm) { - tmp = in_rssi; - if (tmp > 127) - tmp -= 256; - tmp *= 73; - tmp /= 64; - if (adjust_2050) - tmp += 25; - else - tmp -= 3; - } else { - if (dev->dev->bus->sprom.boardflags_lo - & B43legacy_BFL_RSSI) { - if (in_rssi > 63) - in_rssi = 63; - tmp = phy->nrssi_lt[in_rssi]; - tmp = 31 - tmp; - tmp *= -131; - tmp /= 128; - tmp -= 57; - } else { - tmp = in_rssi; - tmp = 31 - tmp; - tmp *= -149; - tmp /= 128; - tmp -= 68; - } - if (phy->type == B43legacy_PHYTYPE_G && - adjust_2050) - tmp += 25; - } - break; - case 0x2060: - if (in_rssi > 127) - tmp = in_rssi - 256; - else - tmp = in_rssi; - break; - default: - tmp = in_rssi; - tmp -= 11; - tmp *= 103; - tmp /= 64; - if (adjust_2053) - tmp -= 109; - else - tmp -= 83; - } - - return (s8)tmp; -} - -void b43legacy_rx(struct b43legacy_wldev *dev, - struct sk_buff *skb, - const void *_rxhdr) -{ - struct ieee80211_rx_status status; - struct b43legacy_plcp_hdr6 *plcp; - struct ieee80211_hdr *wlhdr; - const struct b43legacy_rxhdr_fw3 *rxhdr = _rxhdr; - __le16 fctl; - u16 phystat0; - u16 phystat3; - u16 chanstat; - u16 mactime; - u32 macstat; - u16 chanid; - u8 jssi; - int padding; - - memset(&status, 0, sizeof(status)); - - /* Get metadata about the frame from the header. */ - phystat0 = le16_to_cpu(rxhdr->phy_status0); - phystat3 = le16_to_cpu(rxhdr->phy_status3); - jssi = rxhdr->jssi; - macstat = le16_to_cpu(rxhdr->mac_status); - mactime = le16_to_cpu(rxhdr->mac_time); - chanstat = le16_to_cpu(rxhdr->channel); - - if (macstat & B43legacy_RX_MAC_FCSERR) - dev->wl->ieee_stats.dot11FCSErrorCount++; - - /* Skip PLCP and padding */ - padding = (macstat & B43legacy_RX_MAC_PADDING) ? 2 : 0; - if (unlikely(skb->len < (sizeof(struct b43legacy_plcp_hdr6) + - padding))) { - b43legacydbg(dev->wl, "RX: Packet size underrun (1)\n"); - goto drop; - } - plcp = (struct b43legacy_plcp_hdr6 *)(skb->data + padding); - skb_pull(skb, sizeof(struct b43legacy_plcp_hdr6) + padding); - /* The skb contains the Wireless Header + payload data now */ - if (unlikely(skb->len < (2+2+6/*minimum hdr*/ + FCS_LEN))) { - b43legacydbg(dev->wl, "RX: Packet size underrun (2)\n"); - goto drop; - } - wlhdr = (struct ieee80211_hdr *)(skb->data); - fctl = wlhdr->frame_control; - - if ((macstat & B43legacy_RX_MAC_DEC) && - !(macstat & B43legacy_RX_MAC_DECERR)) { - unsigned int keyidx; - int wlhdr_len; - int iv_len; - int icv_len; - - keyidx = ((macstat & B43legacy_RX_MAC_KEYIDX) - >> B43legacy_RX_MAC_KEYIDX_SHIFT); - /* We must adjust the key index here. We want the "physical" - * key index, but the ucode passed it slightly different. - */ - keyidx = b43legacy_kidx_to_raw(dev, keyidx); - B43legacy_WARN_ON(keyidx >= dev->max_nr_keys); - - if (dev->key[keyidx].algorithm != B43legacy_SEC_ALGO_NONE) { - /* Remove PROTECTED flag to mark it as decrypted. */ - B43legacy_WARN_ON(!ieee80211_has_protected(fctl)); - fctl &= ~cpu_to_le16(IEEE80211_FCTL_PROTECTED); - wlhdr->frame_control = fctl; - - wlhdr_len = ieee80211_hdrlen(fctl); - if (unlikely(skb->len < (wlhdr_len + 3))) { - b43legacydbg(dev->wl, "RX: Packet size" - " underrun3\n"); - goto drop; - } - if (skb->data[wlhdr_len + 3] & (1 << 5)) { - /* The Ext-IV Bit is set in the "KeyID" - * octet of the IV. - */ - iv_len = 8; - icv_len = 8; - } else { - iv_len = 4; - icv_len = 4; - } - if (unlikely(skb->len < (wlhdr_len + iv_len + - icv_len))) { - b43legacydbg(dev->wl, "RX: Packet size" - " underrun4\n"); - goto drop; - } - /* Remove the IV */ - memmove(skb->data + iv_len, skb->data, wlhdr_len); - skb_pull(skb, iv_len); - /* Remove the ICV */ - skb_trim(skb, skb->len - icv_len); - - status.flag |= RX_FLAG_DECRYPTED; - } - } - - status.signal = b43legacy_rssi_postprocess(dev, jssi, - (phystat0 & B43legacy_RX_PHYST0_OFDM), - (phystat0 & B43legacy_RX_PHYST0_GAINCTL), - (phystat3 & B43legacy_RX_PHYST3_TRSTATE)); - status.noise = dev->stats.link_noise; - status.qual = (jssi * 100) / B43legacy_RX_MAX_SSI; - /* change to support A PHY */ - if (phystat0 & B43legacy_RX_PHYST0_OFDM) - status.rate_idx = b43legacy_plcp_get_bitrate_idx_ofdm(plcp, false); - else - status.rate_idx = b43legacy_plcp_get_bitrate_idx_cck(plcp); - status.antenna = !!(phystat0 & B43legacy_RX_PHYST0_ANT); - - /* - * All frames on monitor interfaces and beacons always need a full - * 64-bit timestamp. Monitor interfaces need it for diagnostic - * purposes and beacons for IBSS merging. - * This code assumes we get to process the packet within 16 bits - * of timestamp, i.e. about 65 milliseconds after the PHY received - * the first symbol. - */ - if (ieee80211_is_beacon(fctl) || dev->wl->radiotap_enabled) { - u16 low_mactime_now; - - b43legacy_tsf_read(dev, &status.mactime); - low_mactime_now = status.mactime; - status.mactime = status.mactime & ~0xFFFFULL; - status.mactime += mactime; - if (low_mactime_now <= mactime) - status.mactime -= 0x10000; - status.flag |= RX_FLAG_TSFT; - } - - chanid = (chanstat & B43legacy_RX_CHAN_ID) >> - B43legacy_RX_CHAN_ID_SHIFT; - switch (chanstat & B43legacy_RX_CHAN_PHYTYPE) { - case B43legacy_PHYTYPE_B: - case B43legacy_PHYTYPE_G: - status.band = IEEE80211_BAND_2GHZ; - status.freq = chanid + 2400; - break; - default: - b43legacywarn(dev->wl, "Unexpected value for chanstat (0x%X)\n", - chanstat); - } - - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx_irqsafe(dev->wl->hw, skb); - - return; -drop: - b43legacydbg(dev->wl, "RX: Packet dropped\n"); - dev_kfree_skb_any(skb); -} - -void b43legacy_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status) -{ - b43legacy_debugfs_log_txstat(dev, status); - - if (status->intermediate) - return; - if (status->for_ampdu) - return; - if (!status->acked) - dev->wl->ieee_stats.dot11ACKFailureCount++; - if (status->rts_count) { - if (status->rts_count == 0xF) /* FIXME */ - dev->wl->ieee_stats.dot11RTSFailureCount++; - else - dev->wl->ieee_stats.dot11RTSSuccessCount++; - } - - if (b43legacy_using_pio(dev)) - b43legacy_pio_handle_txstatus(dev, status); - else - b43legacy_dma_handle_txstatus(dev, status); -} - -/* Handle TX status report as received through DMA/PIO queues */ -void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev, - const struct b43legacy_hwtxstatus *hw) -{ - struct b43legacy_txstatus status; - u8 tmp; - - status.cookie = le16_to_cpu(hw->cookie); - status.seq = le16_to_cpu(hw->seq); - status.phy_stat = hw->phy_stat; - tmp = hw->count; - status.frame_count = (tmp >> 4); - status.rts_count = (tmp & 0x0F); - tmp = hw->flags << 1; - status.supp_reason = ((tmp & 0x1C) >> 2); - status.pm_indicated = !!(tmp & 0x80); - status.intermediate = !!(tmp & 0x40); - status.for_ampdu = !!(tmp & 0x20); - status.acked = !!(tmp & 0x02); - - b43legacy_handle_txstatus(dev, &status); -} - -/* Stop any TX operation on the device (suspend the hardware queues) */ -void b43legacy_tx_suspend(struct b43legacy_wldev *dev) -{ - if (b43legacy_using_pio(dev)) - b43legacy_pio_freeze_txqueues(dev); - else - b43legacy_dma_tx_suspend(dev); -} - -/* Resume any TX operation on the device (resume the hardware queues) */ -void b43legacy_tx_resume(struct b43legacy_wldev *dev) -{ - if (b43legacy_using_pio(dev)) - b43legacy_pio_thaw_txqueues(dev); - else - b43legacy_dma_tx_resume(dev); -} - -/* Initialize the QoS parameters */ -void b43legacy_qos_init(struct b43legacy_wldev *dev) -{ - /* FIXME: This function must probably be called from the mac80211 - * config callback. */ -return; - - b43legacy_hf_write(dev, b43legacy_hf_read(dev) | B43legacy_HF_EDCF); - /* FIXME kill magic */ - b43legacy_write16(dev, 0x688, - b43legacy_read16(dev, 0x688) | 0x4); - - - /*TODO: We might need some stack support here to get the values. */ -} diff --git a/drivers/net/wireless/b43legacy/xmit.h b/drivers/net/wireless/b43legacy/xmit.h deleted file mode 100644 index 91633087a20b..000000000000 --- a/drivers/net/wireless/b43legacy/xmit.h +++ /dev/null @@ -1,261 +0,0 @@ -#ifndef B43legacy_XMIT_H_ -#define B43legacy_XMIT_H_ - -#include "main.h" - - -#define _b43legacy_declare_plcp_hdr(size) \ - struct b43legacy_plcp_hdr##size { \ - union { \ - __le32 data; \ - __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) - -/* struct b43legacy_plcp_hdr4 */ -_b43legacy_declare_plcp_hdr(4); -/* struct b43legacy_plcp_hdr6 */ -_b43legacy_declare_plcp_hdr(6); - -#undef _b43legacy_declare_plcp_hdr - - -/* TX header for v3 firmware */ -struct b43legacy_txhdr_fw3 { - __le32 mac_ctl; /* MAC TX control */ - __le16 mac_frame_ctl; /* Copy of the FrameControl */ - __le16 tx_fes_time_norm; /* TX FES Time Normal */ - __le16 phy_ctl; /* PHY TX control */ - __u8 iv[16]; /* Encryption IV */ - __u8 tx_receiver[6]; /* TX Frame Receiver address */ - __le16 tx_fes_time_fb; /* TX FES Time Fallback */ - struct b43legacy_plcp_hdr4 rts_plcp_fb; /* RTS fallback PLCP */ - __le16 rts_dur_fb; /* RTS fallback duration */ - struct b43legacy_plcp_hdr4 plcp_fb; /* Fallback PLCP */ - __le16 dur_fb; /* Fallback duration */ - PAD_BYTES(2); - __le16 cookie; - __le16 unknown_scb_stuff; - struct b43legacy_plcp_hdr6 rts_plcp; /* RTS PLCP */ - __u8 rts_frame[18]; /* The RTS frame (if used) */ - struct b43legacy_plcp_hdr6 plcp; -} __attribute__((__packed__)); - -/* MAC TX control */ -#define B43legacy_TX4_MAC_KEYIDX 0x0FF00000 /* Security key index */ -#define B43legacy_TX4_MAC_KEYIDX_SHIFT 20 -#define B43legacy_TX4_MAC_KEYALG 0x00070000 /* Security key algorithm */ -#define B43legacy_TX4_MAC_KEYALG_SHIFT 16 -#define B43legacy_TX4_MAC_LIFETIME 0x00001000 -#define B43legacy_TX4_MAC_FRAMEBURST 0x00000800 -#define B43legacy_TX4_MAC_SENDCTS 0x00000400 -#define B43legacy_TX4_MAC_AMPDU 0x00000300 -#define B43legacy_TX4_MAC_AMPDU_SHIFT 8 -#define B43legacy_TX4_MAC_CTSFALLBACKOFDM 0x00000200 -#define B43legacy_TX4_MAC_FALLBACKOFDM 0x00000100 -#define B43legacy_TX4_MAC_5GHZ 0x00000080 -#define B43legacy_TX4_MAC_IGNPMQ 0x00000020 -#define B43legacy_TX4_MAC_HWSEQ 0x00000010 /* Use Hardware Seq No */ -#define B43legacy_TX4_MAC_STMSDU 0x00000008 /* Start MSDU */ -#define B43legacy_TX4_MAC_SENDRTS 0x00000004 -#define B43legacy_TX4_MAC_LONGFRAME 0x00000002 -#define B43legacy_TX4_MAC_ACK 0x00000001 - -/* Extra Frame Types */ -#define B43legacy_TX4_EFT_FBOFDM 0x0001 /* Data frame fb rate type */ -#define B43legacy_TX4_EFT_RTSOFDM 0x0004 /* RTS/CTS rate type */ -#define B43legacy_TX4_EFT_RTSFBOFDM 0x0010 /* RTS/CTS fallback rate type */ - -/* PHY TX control word */ -#define B43legacy_TX4_PHY_ENC 0x0003 /* Data frame encoding */ -#define B43legacy_TX4_PHY_ENC_CCK 0x0000 /* CCK */ -#define B43legacy_TX4_PHY_ENC_OFDM 0x0001 /* Data frame rate type */ -#define B43legacy_TX4_PHY_SHORTPRMBL 0x0010 /* Use short preamble */ -#define B43legacy_TX4_PHY_ANT 0x03C0 /* Antenna selection */ -#define B43legacy_TX4_PHY_ANT0 0x0000 /* Use antenna 0 */ -#define B43legacy_TX4_PHY_ANT1 0x0100 /* Use antenna 1 */ -#define B43legacy_TX4_PHY_ANTLAST 0x0300 /* Use last used antenna */ - - - -int b43legacy_generate_txhdr(struct b43legacy_wldev *dev, - u8 *txhdr, - const unsigned char *fragment_data, - unsigned int fragment_len, - struct ieee80211_tx_info *info, - u16 cookie); - - -/* Transmit Status */ -struct b43legacy_txstatus { - u16 cookie; /* The cookie from the txhdr */ - u16 seq; /* Sequence number */ - u8 phy_stat; /* PHY TX status */ - u8 frame_count; /* Frame transmit count */ - u8 rts_count; /* RTS transmit count */ - u8 supp_reason; /* Suppression reason */ - /* flags */ - u8 pm_indicated;/* PM mode indicated to AP */ - u8 intermediate;/* Intermediate status notification */ - u8 for_ampdu; /* Status is for an AMPDU (afterburner) */ - u8 acked; /* Wireless ACK received */ -}; - -/* txstatus supp_reason values */ -enum { - B43legacy_TXST_SUPP_NONE, /* Not suppressed */ - B43legacy_TXST_SUPP_PMQ, /* Suppressed due to PMQ entry */ - B43legacy_TXST_SUPP_FLUSH, /* Suppressed due to flush request */ - B43legacy_TXST_SUPP_PREV, /* Previous fragment failed */ - B43legacy_TXST_SUPP_CHAN, /* Channel mismatch */ - B43legacy_TXST_SUPP_LIFE, /* Lifetime expired */ - B43legacy_TXST_SUPP_UNDER, /* Buffer underflow */ - B43legacy_TXST_SUPP_ABNACK, /* Afterburner NACK */ -}; - -/* Transmit Status as received through DMA/PIO on old chips */ -struct b43legacy_hwtxstatus { - PAD_BYTES(4); - __le16 cookie; - u8 flags; - u8 count; - PAD_BYTES(2); - __le16 seq; - u8 phy_stat; - PAD_BYTES(1); -} __attribute__((__packed__)); - - -/* Receive header for v3 firmware. */ -struct b43legacy_rxhdr_fw3 { - __le16 frame_len; /* Frame length */ - PAD_BYTES(2); - __le16 phy_status0; /* PHY RX Status 0 */ - __u8 jssi; /* PHY RX Status 1: JSSI */ - __u8 sig_qual; /* PHY RX Status 1: Signal Quality */ - PAD_BYTES(2); /* PHY RX Status 2 */ - __le16 phy_status3; /* PHY RX Status 3 */ - __le16 mac_status; /* MAC RX status */ - __le16 mac_time; - __le16 channel; -} __attribute__((__packed__)); - - -/* PHY RX Status 0 */ -#define B43legacy_RX_PHYST0_GAINCTL 0x4000 /* Gain Control */ -#define B43legacy_RX_PHYST0_PLCPHCF 0x0200 -#define B43legacy_RX_PHYST0_PLCPFV 0x0100 -#define B43legacy_RX_PHYST0_SHORTPRMBL 0x0080 /* Recvd with Short Preamble */ -#define B43legacy_RX_PHYST0_LCRS 0x0040 -#define B43legacy_RX_PHYST0_ANT 0x0020 /* Antenna */ -#define B43legacy_RX_PHYST0_UNSRATE 0x0010 -#define B43legacy_RX_PHYST0_CLIP 0x000C -#define B43legacy_RX_PHYST0_CLIP_SHIFT 2 -#define B43legacy_RX_PHYST0_FTYPE 0x0003 /* Frame type */ -#define B43legacy_RX_PHYST0_CCK 0x0000 /* Frame type: CCK */ -#define B43legacy_RX_PHYST0_OFDM 0x0001 /* Frame type: OFDM */ -#define B43legacy_RX_PHYST0_PRE_N 0x0002 /* Pre-standard N-PHY frame */ -#define B43legacy_RX_PHYST0_STD_N 0x0003 /* Standard N-PHY frame */ - -/* PHY RX Status 2 */ -#define B43legacy_RX_PHYST2_LNAG 0xC000 /* LNA Gain */ -#define B43legacy_RX_PHYST2_LNAG_SHIFT 14 -#define B43legacy_RX_PHYST2_PNAG 0x3C00 /* PNA Gain */ -#define B43legacy_RX_PHYST2_PNAG_SHIFT 10 -#define B43legacy_RX_PHYST2_FOFF 0x03FF /* F offset */ - -/* PHY RX Status 3 */ -#define B43legacy_RX_PHYST3_DIGG 0x1800 /* DIG Gain */ -#define B43legacy_RX_PHYST3_DIGG_SHIFT 11 -#define B43legacy_RX_PHYST3_TRSTATE 0x0400 /* TR state */ - -/* MAC RX Status */ -#define B43legacy_RX_MAC_BEACONSENT 0x00008000 /* Beacon send flag */ -#define B43legacy_RX_MAC_KEYIDX 0x000007E0 /* Key index */ -#define B43legacy_RX_MAC_KEYIDX_SHIFT 5 -#define B43legacy_RX_MAC_DECERR 0x00000010 /* Decrypt error */ -#define B43legacy_RX_MAC_DEC 0x00000008 /* Decryption attempted */ -#define B43legacy_RX_MAC_PADDING 0x00000004 /* Pad bytes present */ -#define B43legacy_RX_MAC_RESP 0x00000002 /* Response frame xmitted */ -#define B43legacy_RX_MAC_FCSERR 0x00000001 /* FCS error */ - -/* RX channel */ -#define B43legacy_RX_CHAN_GAIN 0xFC00 /* Gain */ -#define B43legacy_RX_CHAN_GAIN_SHIFT 10 -#define B43legacy_RX_CHAN_ID 0x03FC /* Channel ID */ -#define B43legacy_RX_CHAN_ID_SHIFT 2 -#define B43legacy_RX_CHAN_PHYTYPE 0x0003 /* PHY type */ - - - -u8 b43legacy_plcp_get_ratecode_cck(const u8 bitrate); -u8 b43legacy_plcp_get_ratecode_ofdm(const u8 bitrate); - -void b43legacy_generate_plcp_hdr(struct b43legacy_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate); - -void b43legacy_rx(struct b43legacy_wldev *dev, - struct sk_buff *skb, - const void *_rxhdr); - -void b43legacy_handle_txstatus(struct b43legacy_wldev *dev, - const struct b43legacy_txstatus *status); - -void b43legacy_handle_hwtxstatus(struct b43legacy_wldev *dev, - const struct b43legacy_hwtxstatus *hw); - -void b43legacy_tx_suspend(struct b43legacy_wldev *dev); -void b43legacy_tx_resume(struct b43legacy_wldev *dev); - - -#define B43legacy_NR_QOSPARMS 22 -enum { - B43legacy_QOSPARM_TXOP = 0, - B43legacy_QOSPARM_CWMIN, - B43legacy_QOSPARM_CWMAX, - B43legacy_QOSPARM_CWCUR, - B43legacy_QOSPARM_AIFS, - B43legacy_QOSPARM_BSLOTS, - B43legacy_QOSPARM_REGGAP, - B43legacy_QOSPARM_STATUS, -}; - -void b43legacy_qos_init(struct b43legacy_wldev *dev); - - -/* Helper functions for converting the key-table index from "firmware-format" - * to "raw-format" and back. The firmware API changed for this at some revision. - * We need to account for that here. */ -static inline -int b43legacy_new_kidx_api(struct b43legacy_wldev *dev) -{ - /* FIXME: Not sure the change was at rev 351 */ - return (dev->fw.rev >= 351); -} -static inline -u8 b43legacy_kidx_to_fw(struct b43legacy_wldev *dev, u8 raw_kidx) -{ - u8 firmware_kidx; - if (b43legacy_new_kidx_api(dev)) - firmware_kidx = raw_kidx; - else { - if (raw_kidx >= 4) /* Is per STA key? */ - firmware_kidx = raw_kidx - 4; - else - firmware_kidx = raw_kidx; /* TX default key */ - } - return firmware_kidx; -} -static inline -u8 b43legacy_kidx_to_raw(struct b43legacy_wldev *dev, u8 firmware_kidx) -{ - u8 raw_kidx; - if (b43legacy_new_kidx_api(dev)) - raw_kidx = firmware_kidx; - else - /* RX default keys or per STA keys */ - raw_kidx = firmware_kidx + 4; - return raw_kidx; -} - -#endif /* B43legacy_XMIT_H_ */ diff --git a/drivers/net/wireless/bcm4329/Kconfig b/drivers/net/wireless/bcm4329/Kconfig deleted file mode 100644 index 0315cc135529..000000000000 --- a/drivers/net/wireless/bcm4329/Kconfig +++ /dev/null @@ -1,25 +0,0 @@ -config BCM4329 - tristate "Broadcom 4329 wireless cards support" - depends on WIRELESS_EXT && MMC - ---help--- - This module adds support for wireless adapters based on - Broadcom 4329 chipset. - - This driver uses the kernel's wireless extensions subsystem. - - If you choose to build a module, it'll be called dhd. Say M if - unsure. - -config BCM4329_FW_PATH - depends on BCM4329 - string "Firmware path" - default "/etc/firmware/fw_bcm4329.bin" - ---help--- - Path to the firmware file. - -config BCM4329_NVRAM_PATH - depends on BCM4329 - string "NVRAM path" - default "/etc/firmware/nvram_bcm4329_B23.txt" - ---help--- - Path to the calibration file. diff --git a/drivers/net/wireless/bcm4329/Makefile b/drivers/net/wireless/bcm4329/Makefile deleted file mode 100755 index 26d61b83d6cc..000000000000 --- a/drivers/net/wireless/bcm4329/Makefile +++ /dev/null @@ -1,32 +0,0 @@ -EXTRA_CFLAGS += -Idrivers/net/wireless/bcm4329 -Idrivers/net/wireless/bcm4329/include \ - -DLINUX -DSRCBASE=\"$(BROADCOM_SRC_DIR)\" -DBCMDRIVER -DBCMDONGLEHOST -DDHDTHREAD \ - -DBCMWPA2 -DBCMWAPI_WPI -DUNRELEASEDCHIP -DOEM_ANDROID -DEMBEDDED_PLATFORM \ - -DARP_OFFLOAD_SUPPORT -DPKT_FILTER_SUPPORT -DBCMSDIO -DDHD_GPL -DBCMLXSDMMC \ - -DBCMPLATFORM_BUS -DSDIO_ISR_THREAD -DBDC -DTOE -DDHD_BCMEVENTS -DSHOW_EVENTS \ - -DDHD_SCHED -DDHD_DEBUG -DSDTEST -Wall -Wstrict-prototypes -Werror - - -bcmsdio-objs := bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o \ - bcmsdh_sdmmc_linux.o - -dhd-objs := dhd_common.o dhd_linux.o dhd_linux_sched.o dhd_sdio.o \ - dhd_custom_gpio.o dhd_cdc.o - -shared-objs := aiutils.o bcmutils.o bcmwifi.o hndpmu.o \ - linux_osl.o sbutils.o siutils.o - -wl-objs := wl_iw.o - -bcm4329-objs := $(bcmsdio-objs) $(dhd-objs) $(shared-objs) $(wl-objs) - -obj-$(CONFIG_BCM4329) += bcm4329.o - - - - - - - - - - diff --git a/drivers/net/wireless/bcm4329/aiutils.c b/drivers/net/wireless/bcm4329/aiutils.c deleted file mode 100644 index df48ac0d83d4..000000000000 --- a/drivers/net/wireless/bcm4329/aiutils.c +++ /dev/null @@ -1,686 +0,0 @@ -/* - * Misc utility routines for accessing chip-specific features - * of the SiliconBackplane-based Broadcom chips. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: aiutils.c,v 1.6.4.7.4.6 2010/04/21 20:43:47 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "siutils_priv.h" - -STATIC uint32 -get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st, - uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh); - - -/* EROM parsing */ - -static uint32 -get_erom_ent(si_t *sih, uint32 *eromptr, uint32 mask, uint32 match) -{ - uint32 ent; - uint inv = 0, nom = 0; - - while (TRUE) { - ent = R_REG(si_osh(sih), (uint32 *)(uintptr)(*eromptr)); - *eromptr += sizeof(uint32); - - if (mask == 0) - break; - - if ((ent & ER_VALID) == 0) { - inv++; - continue; - } - - if (ent == (ER_END | ER_VALID)) - break; - - if ((ent & mask) == match) - break; - - nom++; - } - - SI_MSG(("%s: Returning ent 0x%08x\n", __FUNCTION__, ent)); - if (inv + nom) - SI_MSG((" after %d invalid and %d non-matching entries\n", inv, nom)); - return ent; -} - -STATIC uint32 -get_asd(si_t *sih, uint32 *eromptr, uint sp, uint ad, uint st, - uint32 *addrl, uint32 *addrh, uint32 *sizel, uint32 *sizeh) -{ - uint32 asd, sz, szd; - - asd = get_erom_ent(sih, eromptr, ER_VALID, ER_VALID); - if (((asd & ER_TAG1) != ER_ADD) || - (((asd & AD_SP_MASK) >> AD_SP_SHIFT) != sp) || - ((asd & AD_ST_MASK) != st)) { - /* This is not what we want, "push" it back */ - *eromptr -= sizeof(uint32); - return 0; - } - *addrl = asd & AD_ADDR_MASK; - if (asd & AD_AG32) - *addrh = get_erom_ent(sih, eromptr, 0, 0); - else - *addrh = 0; - *sizeh = 0; - sz = asd & AD_SZ_MASK; - if (sz == AD_SZ_SZD) { - szd = get_erom_ent(sih, eromptr, 0, 0); - *sizel = szd & SD_SZ_MASK; - if (szd & SD_SG32) - *sizeh = get_erom_ent(sih, eromptr, 0, 0); - } else - *sizel = AD_SZ_BASE << (sz >> AD_SZ_SHIFT); - - SI_MSG((" SP %d, ad %d: st = %d, 0x%08x_0x%08x @ 0x%08x_0x%08x\n", - sp, ad, st, *sizeh, *sizel, *addrh, *addrl)); - - return asd; -} - -/* parse the enumeration rom to identify all cores */ -void -ai_scan(si_t *sih, void *regs, uint devid) -{ - si_info_t *sii = SI_INFO(sih); - chipcregs_t *cc = (chipcregs_t *)regs; - uint32 erombase, eromptr, eromlim; - - erombase = R_REG(sii->osh, &cc->eromptr); - - switch (BUSTYPE(sih->bustype)) { - case SI_BUS: - eromptr = (uintptr)REG_MAP(erombase, SI_CORE_SIZE); - break; - - case PCI_BUS: - /* Set wrappers address */ - sii->curwrap = (void *)((uintptr)regs + SI_CORE_SIZE); - - /* Now point the window at the erom */ - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, erombase); - eromptr = (uint32)(uintptr)regs; - break; - - case SPI_BUS: - case SDIO_BUS: - eromptr = erombase; - break; - - case PCMCIA_BUS: - default: - SI_ERROR(("Don't know how to do AXI enumertion on bus %d\n", sih->bustype)); - ASSERT(0); - return; - } - eromlim = eromptr + ER_REMAPCONTROL; - - SI_MSG(("ai_scan: regs = 0x%p, erombase = 0x%08x, eromptr = 0x%08x, eromlim = 0x%08x\n", - regs, erombase, eromptr, eromlim)); - while (eromptr < eromlim) { - uint32 cia, cib, base, cid, mfg, crev, nmw, nsw, nmp, nsp; - uint32 mpd, asd, addrl, addrh, sizel, sizeh; - uint i, j, idx; - bool br; - - br = FALSE; - - /* Grok a component */ - cia = get_erom_ent(sih, &eromptr, ER_TAG, ER_CI); - if (cia == (ER_END | ER_VALID)) { - SI_MSG(("Found END of erom after %d cores\n", sii->numcores)); - return; - } - base = eromptr - sizeof(uint32); - cib = get_erom_ent(sih, &eromptr, 0, 0); - - if ((cib & ER_TAG) != ER_CI) { - SI_ERROR(("CIA not followed by CIB\n")); - goto error; - } - - cid = (cia & CIA_CID_MASK) >> CIA_CID_SHIFT; - mfg = (cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT; - crev = (cib & CIB_REV_MASK) >> CIB_REV_SHIFT; - nmw = (cib & CIB_NMW_MASK) >> CIB_NMW_SHIFT; - nsw = (cib & CIB_NSW_MASK) >> CIB_NSW_SHIFT; - nmp = (cib & CIB_NMP_MASK) >> CIB_NMP_SHIFT; - nsp = (cib & CIB_NSP_MASK) >> CIB_NSP_SHIFT; - - SI_MSG(("Found component 0x%04x/0x%4x rev %d at erom addr 0x%08x, with nmw = %d, " - "nsw = %d, nmp = %d & nsp = %d\n", - mfg, cid, crev, base, nmw, nsw, nmp, nsp)); - - if (((mfg == MFGID_ARM) && (cid == DEF_AI_COMP)) || (nsp == 0)) - continue; - if ((nmw + nsw == 0)) { - /* A component which is not a core */ - if (cid == OOB_ROUTER_CORE_ID) { - asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, - &addrl, &addrh, &sizel, &sizeh); - if (asd != 0) { - sii->common_info->oob_router = addrl; - } - } - continue; - } - - idx = sii->numcores; -/* sii->eromptr[idx] = base; */ - sii->common_info->cia[idx] = cia; - sii->common_info->cib[idx] = cib; - sii->common_info->coreid[idx] = cid; - - for (i = 0; i < nmp; i++) { - mpd = get_erom_ent(sih, &eromptr, ER_VALID, ER_VALID); - if ((mpd & ER_TAG) != ER_MP) { - SI_ERROR(("Not enough MP entries for component 0x%x\n", cid)); - goto error; - } - SI_MSG((" Master port %d, mp: %d id: %d\n", i, - (mpd & MPD_MP_MASK) >> MPD_MP_SHIFT, - (mpd & MPD_MUI_MASK) >> MPD_MUI_SHIFT)); - } - - /* First Slave Address Descriptor should be port 0: - * the main register space for the core - */ - asd = get_asd(sih, &eromptr, 0, 0, AD_ST_SLAVE, &addrl, &addrh, &sizel, &sizeh); - if (asd == 0) { - /* Try again to see if it is a bridge */ - asd = get_asd(sih, &eromptr, 0, 0, AD_ST_BRIDGE, &addrl, &addrh, - &sizel, &sizeh); - if (asd != 0) - br = TRUE; - else - if ((addrh != 0) || (sizeh != 0) || (sizel != SI_CORE_SIZE)) { - SI_ERROR(("First Slave ASD for core 0x%04x malformed " - "(0x%08x)\n", cid, asd)); - goto error; - } - } - sii->common_info->coresba[idx] = addrl; - sii->common_info->coresba_size[idx] = sizel; - /* Get any more ASDs in port 0 */ - j = 1; - do { - asd = get_asd(sih, &eromptr, 0, j, AD_ST_SLAVE, &addrl, &addrh, - &sizel, &sizeh); - if ((asd != 0) && (j == 1) && (sizel == SI_CORE_SIZE)) - sii->common_info->coresba2[idx] = addrl; - sii->common_info->coresba2_size[idx] = sizel; - j++; - } while (asd != 0); - - /* Go through the ASDs for other slave ports */ - for (i = 1; i < nsp; i++) { - j = 0; - do { - asd = get_asd(sih, &eromptr, i, j++, AD_ST_SLAVE, &addrl, &addrh, - &sizel, &sizeh); - } while (asd != 0); - if (j == 0) { - SI_ERROR((" SP %d has no address descriptors\n", i)); - goto error; - } - } - - /* Now get master wrappers */ - for (i = 0; i < nmw; i++) { - asd = get_asd(sih, &eromptr, i, 0, AD_ST_MWRAP, &addrl, &addrh, - &sizel, &sizeh); - if (asd == 0) { - SI_ERROR(("Missing descriptor for MW %d\n", i)); - goto error; - } - if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { - SI_ERROR(("Master wrapper %d is not 4KB\n", i)); - goto error; - } - if (i == 0) - sii->common_info->wrapba[idx] = addrl; - } - - /* And finally slave wrappers */ - for (i = 0; i < nsw; i++) { - uint fwp = (nsp == 1) ? 0 : 1; - asd = get_asd(sih, &eromptr, fwp + i, 0, AD_ST_SWRAP, &addrl, &addrh, - &sizel, &sizeh); - if (asd == 0) { - SI_ERROR(("Missing descriptor for SW %d\n", i)); - goto error; - } - if ((sizeh != 0) || (sizel != SI_CORE_SIZE)) { - SI_ERROR(("Slave wrapper %d is not 4KB\n", i)); - goto error; - } - if ((nmw == 0) && (i == 0)) - sii->common_info->wrapba[idx] = addrl; - } - - /* Don't record bridges */ - if (br) - continue; - - /* Done with core */ - sii->numcores++; - } - - SI_ERROR(("Reached end of erom without finding END")); - -error: - sii->numcores = 0; - return; -} - -/* This function changes the logical "focus" to the indicated core. - * Return the current core's virtual address. - */ -void * -ai_setcoreidx(si_t *sih, uint coreidx) -{ - si_info_t *sii = SI_INFO(sih); - uint32 addr = sii->common_info->coresba[coreidx]; - uint32 wrap = sii->common_info->wrapba[coreidx]; - void *regs; - - if (coreidx >= sii->numcores) - return (NULL); - - /* - * If the user has provided an interrupt mask enabled function, - * then assert interrupts are disabled before switching the core. - */ - ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); - - switch (BUSTYPE(sih->bustype)) { - case SI_BUS: - /* map new one */ - if (!sii->common_info->regs[coreidx]) { - sii->common_info->regs[coreidx] = REG_MAP(addr, SI_CORE_SIZE); - ASSERT(GOODREGS(sii->common_info->regs[coreidx])); - } - sii->curmap = regs = sii->common_info->regs[coreidx]; - if (!sii->common_info->wrappers[coreidx]) { - sii->common_info->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); - ASSERT(GOODREGS(sii->common_info->wrappers[coreidx])); - } - sii->curwrap = sii->common_info->wrappers[coreidx]; - break; - - - case SPI_BUS: - case SDIO_BUS: - sii->curmap = regs = (void *)((uintptr)addr); - sii->curwrap = (void *)((uintptr)wrap); - break; - - case PCMCIA_BUS: - default: - ASSERT(0); - regs = NULL; - break; - } - - sii->curmap = regs; - sii->curidx = coreidx; - - return regs; -} - -/* Return the number of address spaces in current core */ -int -ai_numaddrspaces(si_t *sih) -{ - return 2; -} - -/* Return the address of the nth address space in the current core */ -uint32 -ai_addrspace(si_t *sih, uint asidx) -{ - si_info_t *sii; - uint cidx; - - sii = SI_INFO(sih); - cidx = sii->curidx; - - if (asidx == 0) - return sii->common_info->coresba[cidx]; - else if (asidx == 1) - return sii->common_info->coresba2[cidx]; - else { - SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", - __FUNCTION__, asidx)); - return 0; - } -} - -/* Return the size of the nth address space in the current core */ -uint32 -ai_addrspacesize(si_t *sih, uint asidx) -{ - si_info_t *sii; - uint cidx; - - sii = SI_INFO(sih); - cidx = sii->curidx; - - if (asidx == 0) - return sii->common_info->coresba_size[cidx]; - else if (asidx == 1) - return sii->common_info->coresba2_size[cidx]; - else { - SI_ERROR(("%s: Need to parse the erom again to find addr space %d\n", - __FUNCTION__, asidx)); - return 0; - } -} - -uint -ai_flag(si_t *sih) -{ - si_info_t *sii; - aidmp_t *ai; - - sii = SI_INFO(sih); - ai = sii->curwrap; - - return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); -} - -void -ai_setint(si_t *sih, int siflag) -{ -} - -void -ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val) -{ - si_info_t *sii = SI_INFO(sih); - aidmp_t *ai = sii->curwrap; - W_REG(sii->osh, (uint32 *)((uint8 *)ai+offset), val); - return; -} - -uint -ai_corevendor(si_t *sih) -{ - si_info_t *sii; - uint32 cia; - - sii = SI_INFO(sih); - cia = sii->common_info->cia[sii->curidx]; - return ((cia & CIA_MFG_MASK) >> CIA_MFG_SHIFT); -} - -uint -ai_corerev(si_t *sih) -{ - si_info_t *sii; - uint32 cib; - - sii = SI_INFO(sih); - cib = sii->common_info->cib[sii->curidx]; - return ((cib & CIB_REV_MASK) >> CIB_REV_SHIFT); -} - -bool -ai_iscoreup(si_t *sih) -{ - si_info_t *sii; - aidmp_t *ai; - - sii = SI_INFO(sih); - ai = sii->curwrap; - - return (((R_REG(sii->osh, &ai->ioctrl) & (SICF_FGC | SICF_CLOCK_EN)) == SICF_CLOCK_EN) && - ((R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) == 0)); -} - -/* - * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, - * switch back to the original core, and return the new value. - * - * When using the silicon backplane, no fidleing with interrupts or core switches are needed. - * - * Also, when using pci/pcie, we can optimize away the core switching for pci registers - * and (on newer pci cores) chipcommon registers. - */ -uint -ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) -{ - uint origidx = 0; - uint32 *r = NULL; - uint w; - uint intr_val = 0; - bool fast = FALSE; - si_info_t *sii; - - sii = SI_INFO(sih); - - ASSERT(GOODIDX(coreidx)); - ASSERT(regoff < SI_CORE_SIZE); - ASSERT((val & ~mask) == 0); - - if (coreidx >= SI_MAXCORES) - return 0; - - if (BUSTYPE(sih->bustype) == SI_BUS) { - /* If internal bus, we can always get at everything */ - fast = TRUE; - /* map if does not exist */ - if (!sii->common_info->wrappers[coreidx]) { - sii->common_info->regs[coreidx] = - REG_MAP(sii->common_info->coresba[coreidx], SI_CORE_SIZE); - ASSERT(GOODREGS(sii->common_info->regs[coreidx])); - } - r = (uint32 *)((uchar *)sii->common_info->regs[coreidx] + regoff); - } else if (BUSTYPE(sih->bustype) == PCI_BUS) { - /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ - - if ((sii->common_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { - /* Chipc registers are mapped at 12KB */ - - fast = TRUE; - r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); - } else if (sii->pub.buscoreidx == coreidx) { - /* pci registers are at either in the last 2KB of an 8KB window - * or, in pcie and pci rev 13 at 8KB - */ - fast = TRUE; - if (SI_FAST(sii)) - r = (uint32 *)((char *)sii->curmap + - PCI_16KB0_PCIREGS_OFFSET + regoff); - else - r = (uint32 *)((char *)sii->curmap + - ((regoff >= SBCONFIGOFF) ? - PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + - regoff); - } - } - - if (!fast) { - INTR_OFF(sii, intr_val); - - /* save current core index */ - origidx = si_coreidx(&sii->pub); - - /* switch core */ - r = (uint32*) ((uchar*) ai_setcoreidx(&sii->pub, coreidx) + regoff); - } - ASSERT(r != NULL); - - /* mask and set */ - if (mask || val) { - w = (R_REG(sii->osh, r) & ~mask) | val; - W_REG(sii->osh, r, w); - } - - /* readback */ - w = R_REG(sii->osh, r); - - if (!fast) { - /* restore core index */ - if (origidx != coreidx) - ai_setcoreidx(&sii->pub, origidx); - - INTR_RESTORE(sii, intr_val); - } - - return (w); -} - -void -ai_core_disable(si_t *sih, uint32 bits) -{ - si_info_t *sii; - volatile uint32 dummy; - aidmp_t *ai; - - sii = SI_INFO(sih); - - ASSERT(GOODREGS(sii->curwrap)); - ai = sii->curwrap; - - /* if core is already in reset, just return */ - if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) - return; - - W_REG(sii->osh, &ai->ioctrl, bits); - dummy = R_REG(sii->osh, &ai->ioctrl); - OSL_DELAY(10); - - W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); - OSL_DELAY(1); -} - -/* reset and re-enable a core - * inputs: - * bits - core specific bits that are set during and after reset sequence - * resetbits - core specific bits that are set only during reset sequence - */ -void -ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits) -{ - si_info_t *sii; - aidmp_t *ai; - volatile uint32 dummy; - - sii = SI_INFO(sih); - ASSERT(GOODREGS(sii->curwrap)); - ai = sii->curwrap; - - /* - * Must do the disable sequence first to work for arbitrary current core state. - */ - ai_core_disable(sih, (bits | resetbits)); - - /* - * Now do the initialization sequence. - */ - W_REG(sii->osh, &ai->ioctrl, (bits | SICF_FGC | SICF_CLOCK_EN)); - dummy = R_REG(sii->osh, &ai->ioctrl); - W_REG(sii->osh, &ai->resetctrl, 0); - OSL_DELAY(1); - - W_REG(sii->osh, &ai->ioctrl, (bits | SICF_CLOCK_EN)); - dummy = R_REG(sii->osh, &ai->ioctrl); - OSL_DELAY(1); -} - - -void -ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - aidmp_t *ai; - uint32 w; - - sii = SI_INFO(sih); - ASSERT(GOODREGS(sii->curwrap)); - ai = sii->curwrap; - - ASSERT((val & ~mask) == 0); - - if (mask || val) { - w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); - W_REG(sii->osh, &ai->ioctrl, w); - } -} - -uint32 -ai_core_cflags(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - aidmp_t *ai; - uint32 w; - - sii = SI_INFO(sih); - ASSERT(GOODREGS(sii->curwrap)); - ai = sii->curwrap; - - ASSERT((val & ~mask) == 0); - - if (mask || val) { - w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); - W_REG(sii->osh, &ai->ioctrl, w); - } - - return R_REG(sii->osh, &ai->ioctrl); -} - -uint32 -ai_core_sflags(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - aidmp_t *ai; - uint32 w; - - sii = SI_INFO(sih); - ASSERT(GOODREGS(sii->curwrap)); - ai = sii->curwrap; - - ASSERT((val & ~mask) == 0); - ASSERT((mask & ~SISF_CORE_BITS) == 0); - - if (mask || val) { - w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); - W_REG(sii->osh, &ai->iostatus, w); - } - - return R_REG(sii->osh, &ai->iostatus); -} diff --git a/drivers/net/wireless/bcm4329/bcmpcispi.c b/drivers/net/wireless/bcm4329/bcmpcispi.c deleted file mode 100644 index c0a66f1aa3e4..000000000000 --- a/drivers/net/wireless/bcm4329/bcmpcispi.c +++ /dev/null @@ -1,625 +0,0 @@ -/* - * Broadcom SPI over PCI-SPI Host Controller, low-level hardware driver - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmpcispi.c,v 1.22.2.4.4.5 2008/07/09 21:23:30 Exp $ - */ - -#include -#include - -#include /* SDIO Specs */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* to get msglevel bit values */ - -#include -#include -#include -#include /* BRCM PCI-SPI Host Controller Register definitions */ - - -/* ndis_osl.h needs to do a runtime check of the osh to map - * R_REG/W_REG to bus specific access similar to linux_osl.h. - * Until then... - */ -/* linux */ - -#define SPIPCI_RREG R_REG -#define SPIPCI_WREG W_REG - - -#define SPIPCI_ANDREG(osh, r, v) SPIPCI_WREG(osh, (r), (SPIPCI_RREG(osh, r) & (v))) -#define SPIPCI_ORREG(osh, r, v) SPIPCI_WREG(osh, (r), (SPIPCI_RREG(osh, r) | (v))) - - -int bcmpcispi_dump = 0; /* Set to dump complete trace of all SPI bus transactions */ - -typedef struct spih_info_ { - uint bar0; /* BAR0 of PCI Card */ - uint bar1; /* BAR1 of PCI Card */ - osl_t *osh; /* osh handle */ - spih_pciregs_t *pciregs; /* PCI Core Registers */ - spih_regs_t *regs; /* SPI Controller Registers */ - uint8 rev; /* PCI Card Revision ID */ -} spih_info_t; - - -/* Attach to PCI-SPI Host Controller Hardware */ -bool -spi_hw_attach(sdioh_info_t *sd) -{ - osl_t *osh; - spih_info_t *si; - - sd_trace(("%s: enter\n", __FUNCTION__)); - - osh = sd->osh; - - if ((si = (spih_info_t *)MALLOC(osh, sizeof(spih_info_t))) == NULL) { - sd_err(("%s: out of memory, malloced %d bytes\n", __FUNCTION__, MALLOCED(osh))); - return FALSE; - } - - bzero(si, sizeof(spih_info_t)); - - sd->controller = si; - - si->osh = sd->osh; - si->rev = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_REV, 4) & 0xFF; - - if (si->rev < 3) { - sd_err(("Host controller %d not supported, please upgrade to rev >= 3\n", si->rev)); - MFREE(osh, si, sizeof(spih_info_t)); - return (FALSE); - } - - sd_err(("Attaching to Generic PCI SPI Host Controller Rev %d\n", si->rev)); - - /* FPGA Revision < 3 not supported by driver anymore. */ - ASSERT(si->rev >= 3); - - si->bar0 = sd->bar0; - - /* Rev < 10 PciSpiHost has 2 BARs: - * BAR0 = PCI Core Registers - * BAR1 = PciSpiHost Registers (all other cores on backplane) - * - * Rev 10 and up use a different PCI core which only has a single - * BAR0 which contains the PciSpiHost Registers. - */ - if (si->rev < 10) { - si->pciregs = (spih_pciregs_t *)spi_reg_map(osh, - (uintptr)si->bar0, - sizeof(spih_pciregs_t)); - sd_err(("Mapped PCI Core regs to BAR0 at %p\n", si->pciregs)); - - si->bar1 = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_BAR1, 4); - si->regs = (spih_regs_t *)spi_reg_map(osh, - (uintptr)si->bar1, - sizeof(spih_regs_t)); - sd_err(("Mapped SPI Controller regs to BAR1 at %p\n", si->regs)); - } else { - si->regs = (spih_regs_t *)spi_reg_map(osh, - (uintptr)si->bar0, - sizeof(spih_regs_t)); - sd_err(("Mapped SPI Controller regs to BAR0 at %p\n", si->regs)); - si->pciregs = NULL; - } - /* Enable SPI Controller, 16.67MHz SPI Clock */ - SPIPCI_WREG(osh, &si->regs->spih_ctrl, 0x000000d1); - - /* Set extended feature register to defaults */ - SPIPCI_WREG(osh, &si->regs->spih_ext, 0x00000000); - - /* Set GPIO CS# High (de-asserted) */ - SPIPCI_WREG(osh, &si->regs->spih_gpio_data, SPIH_CS); - - /* set GPIO[0] to output for CS# */ - /* set GPIO[1] to output for power control */ - /* set GPIO[2] to input for card detect */ - SPIPCI_WREG(osh, &si->regs->spih_gpio_ctrl, (SPIH_CS | SPIH_SLOT_POWER)); - - /* Clear out the Read FIFO in case there is any stuff left in there from a previous run. */ - while ((SPIPCI_RREG(osh, &si->regs->spih_stat) & SPIH_RFEMPTY) == 0) { - SPIPCI_RREG(osh, &si->regs->spih_data); - } - - /* Wait for power to stabilize to the SDIO Card (100msec was insufficient) */ - OSL_DELAY(250000); - - /* Check card detect on FPGA Revision >= 4 */ - if (si->rev >= 4) { - if (SPIPCI_RREG(osh, &si->regs->spih_gpio_data) & SPIH_CARD_DETECT) { - sd_err(("%s: no card detected in SD slot\n", __FUNCTION__)); - spi_reg_unmap(osh, (uintptr)si->regs, sizeof(spih_regs_t)); - if (si->pciregs) { - spi_reg_unmap(osh, (uintptr)si->pciregs, sizeof(spih_pciregs_t)); - } - MFREE(osh, si, sizeof(spih_info_t)); - return FALSE; - } - } - - /* Interrupts are level sensitive */ - SPIPCI_WREG(osh, &si->regs->spih_int_edge, 0x80000000); - - /* Interrupts are active low. */ - SPIPCI_WREG(osh, &si->regs->spih_int_pol, 0x40000004); - - /* Enable interrupts through PCI Core. */ - if (si->pciregs) { - SPIPCI_WREG(osh, &si->pciregs->ICR, PCI_INT_PROP_EN); - } - - sd_trace(("%s: exit\n", __FUNCTION__)); - return TRUE; -} - -/* Detach and return PCI-SPI Hardware to unconfigured state */ -bool -spi_hw_detach(sdioh_info_t *sd) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - spih_pciregs_t *pciregs = si->pciregs; - - sd_trace(("%s: enter\n", __FUNCTION__)); - - SPIPCI_WREG(osh, ®s->spih_ctrl, 0x00000010); - SPIPCI_WREG(osh, ®s->spih_gpio_ctrl, 0x00000000); /* Disable GPIO for CS# */ - SPIPCI_WREG(osh, ®s->spih_int_mask, 0x00000000); /* Clear Intmask */ - SPIPCI_WREG(osh, ®s->spih_hex_disp, 0x0000DEAF); - SPIPCI_WREG(osh, ®s->spih_int_edge, 0x00000000); - SPIPCI_WREG(osh, ®s->spih_int_pol, 0x00000000); - SPIPCI_WREG(osh, ®s->spih_hex_disp, 0x0000DEAD); - - /* Disable interrupts through PCI Core. */ - if (si->pciregs) { - SPIPCI_WREG(osh, &pciregs->ICR, 0x00000000); - spi_reg_unmap(osh, (uintptr)pciregs, sizeof(spih_pciregs_t)); - } - spi_reg_unmap(osh, (uintptr)regs, sizeof(spih_regs_t)); - - MFREE(osh, si, sizeof(spih_info_t)); - - sd->controller = NULL; - - sd_trace(("%s: exit\n", __FUNCTION__)); - return TRUE; -} - -/* Switch between internal (PCI) and external clock oscillator */ -static bool -sdspi_switch_clock(sdioh_info_t *sd, bool ext_clk) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - - /* Switch to desired clock, and reset the PLL. */ - SPIPCI_WREG(osh, ®s->spih_pll_ctrl, ext_clk ? SPIH_EXT_CLK : 0); - - SPINWAIT(((SPIPCI_RREG(osh, ®s->spih_pll_status) & SPIH_PLL_LOCKED) - != SPIH_PLL_LOCKED), 1000); - if ((SPIPCI_RREG(osh, ®s->spih_pll_status) & SPIH_PLL_LOCKED) != SPIH_PLL_LOCKED) { - sd_err(("%s: timeout waiting for PLL to lock\n", __FUNCTION__)); - return (FALSE); - } - return (TRUE); - -} - -/* Configure PCI-SPI Host Controller's SPI Clock rate as a divisor into the - * base clock rate. The base clock is either the PCI Clock (33MHz) or the - * external clock oscillator at U17 on the PciSpiHost. - */ -bool -spi_start_clock(sdioh_info_t *sd, uint16 div) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - uint32 t, espr, disp; - uint32 disp_xtal_freq; - bool ext_clock = FALSE; - char disp_string[5]; - - if (div > 2048) { - sd_err(("%s: divisor %d too large; using max of 2048\n", __FUNCTION__, div)); - div = 2048; - } else if (div & (div - 1)) { /* Not a power of 2? */ - /* Round up to a power of 2 */ - while ((div + 1) & div) - div |= div >> 1; - div++; - } - - /* For FPGA Rev >= 5, the use of an external clock oscillator is supported. - * If the oscillator is populated, use it to provide the SPI base clock, - * otherwise, default to the PCI clock as the SPI base clock. - */ - if (si->rev >= 5) { - uint32 clk_tick; - /* Enable the External Clock Oscillator as PLL clock source. */ - if (!sdspi_switch_clock(sd, TRUE)) { - sd_err(("%s: error switching to external clock\n", __FUNCTION__)); - } - - /* Check to make sure the external clock is running. If not, then it - * is not populated on the card, so we will default to the PCI clock. - */ - clk_tick = SPIPCI_RREG(osh, ®s->spih_clk_count); - if (clk_tick == SPIPCI_RREG(osh, ®s->spih_clk_count)) { - - /* Switch back to the PCI clock as the clock source. */ - if (!sdspi_switch_clock(sd, FALSE)) { - sd_err(("%s: error switching to external clock\n", __FUNCTION__)); - } - } else { - ext_clock = TRUE; - } - } - - /* Hack to allow hot-swapping oscillators: - * 1. Force PCI clock as clock source, using sd_divisor of 0. - * 2. Swap oscillator - * 3. Set desired sd_divisor (will switch to external oscillator as clock source. - */ - if (div == 0) { - ext_clock = FALSE; - div = 2; - - /* Select PCI clock as the clock source. */ - if (!sdspi_switch_clock(sd, FALSE)) { - sd_err(("%s: error switching to external clock\n", __FUNCTION__)); - } - - sd_err(("%s: Ok to hot-swap oscillators.\n", __FUNCTION__)); - } - - /* If using the external oscillator, read the clock frequency from the controller - * The value read is in units of 10000Hz, and it's not a nice round number because - * it is calculated by the FPGA. So to make up for that, we round it off. - */ - if (ext_clock == TRUE) { - uint32 xtal_freq; - - OSL_DELAY(1000); - xtal_freq = SPIPCI_RREG(osh, ®s->spih_xtal_freq) * 10000; - - sd_info(("%s: Oscillator is %dHz\n", __FUNCTION__, xtal_freq)); - - - disp_xtal_freq = xtal_freq / 10000; - - /* Round it off to a nice number. */ - if ((disp_xtal_freq % 100) > 50) { - disp_xtal_freq += 100; - } - - disp_xtal_freq = (disp_xtal_freq / 100) * 100; - } else { - sd_err(("%s: no external oscillator installed, using PCI clock.\n", __FUNCTION__)); - disp_xtal_freq = 3333; - } - - /* Convert the SPI Clock frequency to BCD format. */ - sprintf(disp_string, "%04d", disp_xtal_freq / div); - - disp = (disp_string[0] - '0') << 12; - disp |= (disp_string[1] - '0') << 8; - disp |= (disp_string[2] - '0') << 4; - disp |= (disp_string[3] - '0'); - - /* Select the correct ESPR register value based on the divisor. */ - switch (div) { - case 1: espr = 0x0; break; - case 2: espr = 0x1; break; - case 4: espr = 0x2; break; - case 8: espr = 0x5; break; - case 16: espr = 0x3; break; - case 32: espr = 0x4; break; - case 64: espr = 0x6; break; - case 128: espr = 0x7; break; - case 256: espr = 0x8; break; - case 512: espr = 0x9; break; - case 1024: espr = 0xa; break; - case 2048: espr = 0xb; break; - default: espr = 0x0; ASSERT(0); break; - } - - t = SPIPCI_RREG(osh, ®s->spih_ctrl); - t &= ~3; - t |= espr & 3; - SPIPCI_WREG(osh, ®s->spih_ctrl, t); - - t = SPIPCI_RREG(osh, ®s->spih_ext); - t &= ~3; - t |= (espr >> 2) & 3; - SPIPCI_WREG(osh, ®s->spih_ext, t); - - SPIPCI_WREG(osh, ®s->spih_hex_disp, disp); - - /* For Rev 8, writing to the PLL_CTRL register resets - * the PLL, and it can re-acquire in 200uS. For - * Rev 7 and older, we use a software delay to allow - * the PLL to re-acquire, which takes more than 2mS. - */ - if (si->rev < 8) { - /* Wait for clock to settle. */ - OSL_DELAY(5000); - } - - sd_info(("%s: SPI_CTRL=0x%08x SPI_EXT=0x%08x\n", - __FUNCTION__, - SPIPCI_RREG(osh, ®s->spih_ctrl), - SPIPCI_RREG(osh, ®s->spih_ext))); - - return TRUE; -} - -/* Configure PCI-SPI Host Controller High-Speed Clocking mode setting */ -bool -spi_controller_highspeed_mode(sdioh_info_t *sd, bool hsmode) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - - if (si->rev >= 10) { - if (hsmode) { - SPIPCI_ORREG(osh, ®s->spih_ext, 0x10); - } else { - SPIPCI_ANDREG(osh, ®s->spih_ext, ~0x10); - } - } - - return TRUE; -} - -/* Disable device interrupt */ -void -spi_devintr_off(sdioh_info_t *sd) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - - sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints)); - if (sd->use_client_ints) { - sd->intmask &= ~SPIH_DEV_INTR; - SPIPCI_WREG(osh, ®s->spih_int_mask, sd->intmask); /* Clear Intmask */ - } -} - -/* Enable device interrupt */ -void -spi_devintr_on(sdioh_info_t *sd) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - - ASSERT(sd->lockcount == 0); - sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints)); - if (sd->use_client_ints) { - if (SPIPCI_RREG(osh, ®s->spih_ctrl) & 0x02) { - /* Ack in case one was pending but is no longer... */ - SPIPCI_WREG(osh, ®s->spih_int_status, SPIH_DEV_INTR); - } - sd->intmask |= SPIH_DEV_INTR; - /* Set device intr in Intmask */ - SPIPCI_WREG(osh, ®s->spih_int_mask, sd->intmask); - } -} - -/* Check to see if an interrupt belongs to the PCI-SPI Host or a SPI Device */ -bool -spi_check_client_intr(sdioh_info_t *sd, int *is_dev_intr) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - bool ours = FALSE; - - uint32 raw_int, cur_int; - ASSERT(sd); - - if (is_dev_intr) - *is_dev_intr = FALSE; - raw_int = SPIPCI_RREG(osh, ®s->spih_int_status); - cur_int = raw_int & sd->intmask; - if (cur_int & SPIH_DEV_INTR) { - if (sd->client_intr_enabled && sd->use_client_ints) { - sd->intrcount++; - ASSERT(sd->intr_handler); - ASSERT(sd->intr_handler_arg); - (sd->intr_handler)(sd->intr_handler_arg); - if (is_dev_intr) - *is_dev_intr = TRUE; - } else { - sd_trace(("%s: Not ready for intr: enabled %d, handler 0x%p\n", - __FUNCTION__, sd->client_intr_enabled, sd->intr_handler)); - } - SPIPCI_WREG(osh, ®s->spih_int_status, SPIH_DEV_INTR); - SPIPCI_RREG(osh, ®s->spih_int_status); - ours = TRUE; - } else if (cur_int & SPIH_CTLR_INTR) { - /* Interrupt is from SPI FIFO... just clear and ack it... */ - sd_trace(("%s: SPI CTLR interrupt: raw_int 0x%08x cur_int 0x%08x\n", - __FUNCTION__, raw_int, cur_int)); - - /* Clear the interrupt in the SPI_STAT register */ - SPIPCI_WREG(osh, ®s->spih_stat, 0x00000080); - - /* Ack the interrupt in the interrupt controller */ - SPIPCI_WREG(osh, ®s->spih_int_status, SPIH_CTLR_INTR); - SPIPCI_RREG(osh, ®s->spih_int_status); - - ours = TRUE; - } else if (cur_int & SPIH_WFIFO_INTR) { - sd_trace(("%s: SPI WR FIFO Empty interrupt: raw_int 0x%08x cur_int 0x%08x\n", - __FUNCTION__, raw_int, cur_int)); - - /* Disable the FIFO Empty Interrupt */ - sd->intmask &= ~SPIH_WFIFO_INTR; - SPIPCI_WREG(osh, ®s->spih_int_mask, sd->intmask); - - sd->local_intrcount++; - sd->got_hcint = TRUE; - ours = TRUE; - } else { - /* Not an error: can share interrupts... */ - sd_trace(("%s: Not my interrupt: raw_int 0x%08x cur_int 0x%08x\n", - __FUNCTION__, raw_int, cur_int)); - ours = FALSE; - } - - return ours; -} - -static void -hexdump(char *pfx, unsigned char *msg, int msglen) -{ - int i, col; - char buf[80]; - - ASSERT(strlen(pfx) + 49 <= sizeof(buf)); - - col = 0; - - for (i = 0; i < msglen; i++, col++) { - if (col % 16 == 0) - strcpy(buf, pfx); - sprintf(buf + strlen(buf), "%02x", msg[i]); - if ((col + 1) % 16 == 0) - printf("%s\n", buf); - else - sprintf(buf + strlen(buf), " "); - } - - if (col % 16 != 0) - printf("%s\n", buf); -} - -/* Send/Receive an SPI Packet */ -void -spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int msglen) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - uint32 count; - uint32 spi_data_out; - uint32 spi_data_in; - bool yield; - - sd_trace(("%s: enter\n", __FUNCTION__)); - - if (bcmpcispi_dump) { - printf("SENDRECV(len=%d)\n", msglen); - hexdump(" OUT: ", msg_out, msglen); - } - -#ifdef BCMSDYIELD - /* Only yield the CPU and wait for interrupt on Rev 8 and newer FPGA images. */ - yield = ((msglen > 500) && (si->rev >= 8)); -#else - yield = FALSE; -#endif /* BCMSDYIELD */ - - ASSERT(msglen % 4 == 0); - - - SPIPCI_ANDREG(osh, ®s->spih_gpio_data, ~SPIH_CS); /* Set GPIO CS# Low (asserted) */ - - for (count = 0; count < (uint32)msglen/4; count++) { - spi_data_out = ((uint32)((uint32 *)msg_out)[count]); - SPIPCI_WREG(osh, ®s->spih_data, spi_data_out); - } - -#ifdef BCMSDYIELD - if (yield) { - /* Ack the interrupt in the interrupt controller */ - SPIPCI_WREG(osh, ®s->spih_int_status, SPIH_WFIFO_INTR); - SPIPCI_RREG(osh, ®s->spih_int_status); - - /* Enable the FIFO Empty Interrupt */ - sd->intmask |= SPIH_WFIFO_INTR; - sd->got_hcint = FALSE; - SPIPCI_WREG(osh, ®s->spih_int_mask, sd->intmask); - - } -#endif /* BCMSDYIELD */ - - /* Wait for write fifo to empty... */ - SPIPCI_ANDREG(osh, ®s->spih_gpio_data, ~0x00000020); /* Set GPIO 5 Low */ - - if (yield) { - ASSERT((SPIPCI_RREG(sd->osh, ®s->spih_stat) & SPIH_WFEMPTY) == 0); - } - - spi_waitbits(sd, yield); - SPIPCI_ORREG(osh, ®s->spih_gpio_data, 0x00000020); /* Set GPIO 5 High (de-asserted) */ - - for (count = 0; count < (uint32)msglen/4; count++) { - spi_data_in = SPIPCI_RREG(osh, ®s->spih_data); - ((uint32 *)msg_in)[count] = spi_data_in; - } - - /* Set GPIO CS# High (de-asserted) */ - SPIPCI_ORREG(osh, ®s->spih_gpio_data, SPIH_CS); - - if (bcmpcispi_dump) { - hexdump(" IN : ", msg_in, msglen); - } -} - -void -spi_spinbits(sdioh_info_t *sd) -{ - spih_info_t *si = (spih_info_t *)sd->controller; - osl_t *osh = si->osh; - spih_regs_t *regs = si->regs; - uint spin_count; /* Spin loop bound check */ - - spin_count = 0; - while ((SPIPCI_RREG(sd->osh, ®s->spih_stat) & SPIH_WFEMPTY) == 0) { - if (spin_count > SPI_SPIN_BOUND) { - ASSERT(FALSE); /* Spin bound exceeded */ - } - spin_count++; - } - spin_count = 0; - /* Wait for SPI Transfer state machine to return to IDLE state. - * The state bits are only implemented in Rev >= 5 FPGA. These - * bits are hardwired to 00 for Rev < 5, so this check doesn't cause - * any problems. - */ - while ((SPIPCI_RREG(osh, ®s->spih_stat) & SPIH_STATE_MASK) != 0) { - if (spin_count > SPI_SPIN_BOUND) { - ASSERT(FALSE); - } - spin_count++; - } -} diff --git a/drivers/net/wireless/bcm4329/bcmsdh.c b/drivers/net/wireless/bcm4329/bcmsdh.c deleted file mode 100644 index 4bf5889e5a68..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdh.c +++ /dev/null @@ -1,652 +0,0 @@ -/* - * BCMSDH interface glue - * implement bcmsdh API for SDIOH driver - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdh.c,v 1.35.2.1.4.8.6.13 2010/04/06 03:26:57 Exp $ - */ -/* ****************** BCMSDH Interface Functions *************************** */ - -#include -#include -#include -#include -#include -#include -#include - -#include /* BRCM API for SDIO clients (such as wl, dhd) */ -#include /* common SDIO/controller interface */ -#include /* BRCM sdio device core */ - -#include /* sdio spec */ - -#define SDIOH_API_ACCESS_RETRY_LIMIT 2 -const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL; - - -struct bcmsdh_info -{ - bool init_success; /* underlying driver successfully attached */ - void *sdioh; /* handler for sdioh */ - uint32 vendevid; /* Target Vendor and Device ID on SD bus */ - osl_t *osh; - bool regfail; /* Save status of last reg_read/reg_write call */ - uint32 sbwad; /* Save backplane window address */ -}; -/* local copy of bcm sd handler */ -bcmsdh_info_t * l_bcmsdh = NULL; - -#if defined(OOB_INTR_ONLY) && defined(HW_OOB) -extern int -sdioh_enable_hw_oob_intr(void *sdioh, bool enable); - -void -bcmsdh_enable_hw_oob_intr(bcmsdh_info_t *sdh, bool enable) -{ - sdioh_enable_hw_oob_intr(sdh->sdioh, enable); -} -#endif - -bcmsdh_info_t * -bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq) -{ - bcmsdh_info_t *bcmsdh; - - if ((bcmsdh = (bcmsdh_info_t *)MALLOC(osh, sizeof(bcmsdh_info_t))) == NULL) { - BCMSDH_ERROR(("bcmsdh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh))); - return NULL; - } - bzero((char *)bcmsdh, sizeof(bcmsdh_info_t)); - - /* save the handler locally */ - l_bcmsdh = bcmsdh; - - if (!(bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq))) { - bcmsdh_detach(osh, bcmsdh); - return NULL; - } - - bcmsdh->osh = osh; - bcmsdh->init_success = TRUE; - - *regsva = (uint32 *)SI_ENUM_BASE; - - /* Report the BAR, to fix if needed */ - bcmsdh->sbwad = SI_ENUM_BASE; - return bcmsdh; -} - -int -bcmsdh_detach(osl_t *osh, void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - if (bcmsdh != NULL) { - if (bcmsdh->sdioh) { - sdioh_detach(osh, bcmsdh->sdioh); - bcmsdh->sdioh = NULL; - } - MFREE(osh, bcmsdh, sizeof(bcmsdh_info_t)); - } - - l_bcmsdh = NULL; - return 0; -} - -int -bcmsdh_iovar_op(void *sdh, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - return sdioh_iovar_op(bcmsdh->sdioh, name, params, plen, arg, len, set); -} - -bool -bcmsdh_intr_query(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - bool on; - - ASSERT(bcmsdh); - status = sdioh_interrupt_query(bcmsdh->sdioh, &on); - if (SDIOH_API_SUCCESS(status)) - return FALSE; - else - return on; -} - -int -bcmsdh_intr_enable(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - ASSERT(bcmsdh); - - status = sdioh_interrupt_set(bcmsdh->sdioh, TRUE); - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - -int -bcmsdh_intr_disable(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - ASSERT(bcmsdh); - - status = sdioh_interrupt_set(bcmsdh->sdioh, FALSE); - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - -int -bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - ASSERT(bcmsdh); - - status = sdioh_interrupt_register(bcmsdh->sdioh, fn, argh); - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - -int -bcmsdh_intr_dereg(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - ASSERT(bcmsdh); - - status = sdioh_interrupt_deregister(bcmsdh->sdioh); - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - -#if defined(DHD_DEBUG) -bool -bcmsdh_intr_pending(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - ASSERT(sdh); - return sdioh_interrupt_pending(bcmsdh->sdioh); -} -#endif - - -int -bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh) -{ - ASSERT(sdh); - - /* don't support yet */ - return BCME_UNSUPPORTED; -} - -uint8 -bcmsdh_cfg_read(void *sdh, uint fnc_num, uint32 addr, int *err) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; -#ifdef SDIOH_API_ACCESS_RETRY_LIMIT - int32 retry = 0; -#endif - uint8 data = 0; - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - -#ifdef SDIOH_API_ACCESS_RETRY_LIMIT - do { - if (retry) /* wait for 1 ms till bus get settled down */ - OSL_DELAY(1000); -#endif - status = sdioh_cfg_read(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data); -#ifdef SDIOH_API_ACCESS_RETRY_LIMIT - } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); -#endif - if (err) - *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); - - BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__, - fnc_num, addr, data)); - - return data; -} - -void -bcmsdh_cfg_write(void *sdh, uint fnc_num, uint32 addr, uint8 data, int *err) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; -#ifdef SDIOH_API_ACCESS_RETRY_LIMIT - int32 retry = 0; -#endif - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - -#ifdef SDIOH_API_ACCESS_RETRY_LIMIT - do { - if (retry) /* wait for 1 ms till bus get settled down */ - OSL_DELAY(1000); -#endif - status = sdioh_cfg_write(bcmsdh->sdioh, fnc_num, addr, (uint8 *)&data); -#ifdef SDIOH_API_ACCESS_RETRY_LIMIT - } while (!SDIOH_API_SUCCESS(status) && (retry++ < SDIOH_API_ACCESS_RETRY_LIMIT)); -#endif - if (err) - *err = SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR; - - BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint8data = 0x%x\n", __FUNCTION__, - fnc_num, addr, data)); -} - -uint32 -bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - uint32 data = 0; - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - - status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_READ, fnc_num, - addr, &data, 4); - - if (err) - *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); - - BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, - fnc_num, addr, data)); - - return data; -} - -void -bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - - status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, fnc_num, - addr, &data, 4); - - if (err) - *err = (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); - - BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, uint32data = 0x%x\n", __FUNCTION__, fnc_num, - addr, data)); -} - - -int -bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - - uint8 *tmp_buf, *tmp_ptr; - uint8 *ptr; - bool ascii = func & ~0xf; - func &= 0x7; - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - ASSERT(cis); - ASSERT(length <= SBSDIO_CIS_SIZE_LIMIT); - - status = sdioh_cis_read(bcmsdh->sdioh, func, cis, length); - - if (ascii) { - /* Move binary bits to tmp and format them into the provided buffer. */ - if ((tmp_buf = (uint8 *)MALLOC(bcmsdh->osh, length)) == NULL) { - BCMSDH_ERROR(("%s: out of memory\n", __FUNCTION__)); - return BCME_NOMEM; - } - bcopy(cis, tmp_buf, length); - for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4); tmp_ptr++) { - ptr += sprintf((char*)ptr, "%.2x ", *tmp_ptr & 0xff); - if ((((tmp_ptr - tmp_buf) + 1) & 0xf) == 0) - ptr += sprintf((char *)ptr, "\n"); - } - MFREE(bcmsdh->osh, tmp_buf, length); - } - - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - - -static int -bcmsdhsdio_set_sbaddr_window(void *sdh, uint32 address) -{ - int err = 0; - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, - (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); - if (!err) - bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, - (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); - if (!err) - bcmsdh_cfg_write(bcmsdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, - (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); - - - return err; -} - -uint32 -bcmsdh_reg_read(void *sdh, uint32 addr, uint size) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - uint32 word = 0; - uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; - - BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, ", __FUNCTION__, addr)); - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - - if (bar0 != bcmsdh->sbwad) { - if (bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0)) - return 0xFFFFFFFF; - - bcmsdh->sbwad = bar0; - } - - addr &= SBSDIO_SB_OFT_ADDR_MASK; - if (size == 4) - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, - SDIOH_READ, SDIO_FUNC_1, addr, &word, size); - - bcmsdh->regfail = !(SDIOH_API_SUCCESS(status)); - - BCMSDH_INFO(("uint32data = 0x%x\n", word)); - - /* if ok, return appropriately masked word */ - if (SDIOH_API_SUCCESS(status)) { - switch (size) { - case sizeof(uint8): - return (word & 0xff); - case sizeof(uint16): - return (word & 0xffff); - case sizeof(uint32): - return word; - default: - bcmsdh->regfail = TRUE; - - } - } - - /* otherwise, bad sdio access or invalid size */ - BCMSDH_ERROR(("%s: error reading addr 0x%04x size %d\n", __FUNCTION__, addr, size)); - return 0xFFFFFFFF; -} - -uint32 -bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; - int err = 0; - - BCMSDH_INFO(("%s:fun = 1, addr = 0x%x, uint%ddata = 0x%x\n", - __FUNCTION__, addr, size*8, data)); - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - ASSERT(bcmsdh->init_success); - - if (bar0 != bcmsdh->sbwad) { - if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))) - return err; - - bcmsdh->sbwad = bar0; - } - - addr &= SBSDIO_SB_OFT_ADDR_MASK; - if (size == 4) - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - status = sdioh_request_word(bcmsdh->sdioh, SDIOH_CMD_TYPE_NORMAL, SDIOH_WRITE, SDIO_FUNC_1, - addr, &data, size); - bcmsdh->regfail = !(SDIOH_API_SUCCESS(status)); - - if (SDIOH_API_SUCCESS(status)) - return 0; - - BCMSDH_ERROR(("%s: error writing 0x%08x to addr 0x%04x size %d\n", - __FUNCTION__, data, addr, size)); - return 0xFFFFFFFF; -} - -bool -bcmsdh_regfail(void *sdh) -{ - return ((bcmsdh_info_t *)sdh)->regfail; -} - -int -bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, - uint8 *buf, uint nbytes, void *pkt, - bcmsdh_cmplt_fn_t complete, void *handle) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - uint incr_fix; - uint width; - uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; - int err = 0; - - ASSERT(bcmsdh); - ASSERT(bcmsdh->init_success); - - BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", - __FUNCTION__, fn, addr, nbytes)); - - /* Async not implemented yet */ - ASSERT(!(flags & SDIO_REQ_ASYNC)); - if (flags & SDIO_REQ_ASYNC) - return BCME_UNSUPPORTED; - - if (bar0 != bcmsdh->sbwad) { - if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))) - return err; - - bcmsdh->sbwad = bar0; - } - - addr &= SBSDIO_SB_OFT_ADDR_MASK; - - incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - if (width == 4) - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix, - SDIOH_READ, fn, addr, width, nbytes, buf, pkt); - - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_SDIO_ERROR); -} - -int -bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, - uint8 *buf, uint nbytes, void *pkt, - bcmsdh_cmplt_fn_t complete, void *handle) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - uint incr_fix; - uint width; - uint bar0 = addr & ~SBSDIO_SB_OFT_ADDR_MASK; - int err = 0; - - ASSERT(bcmsdh); - ASSERT(bcmsdh->init_success); - - BCMSDH_INFO(("%s:fun = %d, addr = 0x%x, size = %d\n", - __FUNCTION__, fn, addr, nbytes)); - - /* Async not implemented yet */ - ASSERT(!(flags & SDIO_REQ_ASYNC)); - if (flags & SDIO_REQ_ASYNC) - return BCME_UNSUPPORTED; - - if (bar0 != bcmsdh->sbwad) { - if ((err = bcmsdhsdio_set_sbaddr_window(bcmsdh, bar0))) - return err; - - bcmsdh->sbwad = bar0; - } - - addr &= SBSDIO_SB_OFT_ADDR_MASK; - - incr_fix = (flags & SDIO_REQ_FIXED) ? SDIOH_DATA_FIX : SDIOH_DATA_INC; - width = (flags & SDIO_REQ_4BYTE) ? 4 : 2; - if (width == 4) - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, incr_fix, - SDIOH_WRITE, fn, addr, width, nbytes, buf, pkt); - - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - -int -bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - SDIOH_API_RC status; - - ASSERT(bcmsdh); - ASSERT(bcmsdh->init_success); - ASSERT((addr & SBSDIO_SBWINDOW_MASK) == 0); - - addr &= SBSDIO_SB_OFT_ADDR_MASK; - addr |= SBSDIO_SB_ACCESS_2_4B_FLAG; - - status = sdioh_request_buffer(bcmsdh->sdioh, SDIOH_DATA_PIO, SDIOH_DATA_INC, - (rw ? SDIOH_WRITE : SDIOH_READ), SDIO_FUNC_1, - addr, 4, nbytes, buf, NULL); - - return (SDIOH_API_SUCCESS(status) ? 0 : BCME_ERROR); -} - -int -bcmsdh_abort(void *sdh, uint fn) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - return sdioh_abort(bcmsdh->sdioh, fn); -} - -int -bcmsdh_start(void *sdh, int stage) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - return sdioh_start(bcmsdh->sdioh, stage); -} - -int -bcmsdh_stop(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - return sdioh_stop(bcmsdh->sdioh); -} - - -int -bcmsdh_query_device(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - bcmsdh->vendevid = (VENDOR_BROADCOM << 16) | 0; - return (bcmsdh->vendevid); -} - -uint -bcmsdh_query_iofnum(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - return (sdioh_query_iofnum(bcmsdh->sdioh)); -} - -int -bcmsdh_reset(bcmsdh_info_t *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - return sdioh_sdio_reset(bcmsdh->sdioh); -} - -void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh) -{ - ASSERT(sdh); - return sdh->sdioh; -} - -/* Function to pass device-status bits to DHD. */ -uint32 -bcmsdh_get_dstatus(void *sdh) -{ - return 0; -} -uint32 -bcmsdh_cur_sbwad(void *sdh) -{ - bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - - if (!bcmsdh) - bcmsdh = l_bcmsdh; - - return (bcmsdh->sbwad); -} - -void -bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev) -{ - return; -} diff --git a/drivers/net/wireless/bcm4329/bcmsdh_linux.c b/drivers/net/wireless/bcm4329/bcmsdh_linux.c deleted file mode 100644 index 79d610bf6b45..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdh_linux.c +++ /dev/null @@ -1,691 +0,0 @@ -/* - * SDIO access interface for drivers - linux specific (pci only) - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdh_linux.c,v 1.42.10.10.2.12 2010/03/10 03:09:48 Exp $ - */ - -/** - * @file bcmsdh_linux.c - */ - -#define __UNDEF_NO_VERSION__ - -#include -#include - -#include -#include - -#include -#include -#include -#include - -#if defined(OOB_INTR_ONLY) -#include -extern void dhdsdio_isr(void * args); -#include -#include -#include -#endif /* defined(OOB_INTR_ONLY) */ -#if defined(CONFIG_MACH_SANDGATE2G) || defined(CONFIG_MACH_LOGICPD_PXA270) -#if !defined(BCMPLATFORM_BUS) -#define BCMPLATFORM_BUS -#endif /* !defined(BCMPLATFORM_BUS) */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) -#include -#endif /* KERNEL_VERSION(2, 6, 19) */ -#endif /* CONFIG_MACH_SANDGATE2G || CONFIG_MACH_LOGICPD_PXA270 */ - -/** - * SDIO Host Controller info - */ -typedef struct bcmsdh_hc bcmsdh_hc_t; - -struct bcmsdh_hc { - bcmsdh_hc_t *next; -#ifdef BCMPLATFORM_BUS - struct device *dev; /* platform device handle */ -#else - struct pci_dev *dev; /* pci device handle */ -#endif /* BCMPLATFORM_BUS */ - osl_t *osh; - void *regs; /* SDIO Host Controller address */ - bcmsdh_info_t *sdh; /* SDIO Host Controller handle */ - void *ch; - unsigned int oob_irq; - unsigned long oob_flags; /* OOB Host specifiction as edge and etc */ -}; -static bcmsdh_hc_t *sdhcinfo = NULL; - -/* driver info, initialized when bcmsdh_register is called */ -static bcmsdh_driver_t drvinfo = {NULL, NULL}; - -/* debugging macros */ -#define SDLX_MSG(x) - -/** - * Checks to see if vendor and device IDs match a supported SDIO Host Controller. - */ -bool -bcmsdh_chipmatch(uint16 vendor, uint16 device) -{ - /* Add other vendors and devices as required */ - -#ifdef BCMSDIOH_STD - /* Check for Arasan host controller */ - if (vendor == VENDOR_SI_IMAGE) { - return (TRUE); - } - /* Check for BRCM 27XX Standard host controller */ - if (device == BCM27XX_SDIOH_ID && vendor == VENDOR_BROADCOM) { - return (TRUE); - } - /* Check for BRCM Standard host controller */ - if (device == SDIOH_FPGA_ID && vendor == VENDOR_BROADCOM) { - return (TRUE); - } - /* Check for TI PCIxx21 Standard host controller */ - if (device == PCIXX21_SDIOH_ID && vendor == VENDOR_TI) { - return (TRUE); - } - if (device == PCIXX21_SDIOH0_ID && vendor == VENDOR_TI) { - return (TRUE); - } - /* Ricoh R5C822 Standard SDIO Host */ - if (device == R5C822_SDIOH_ID && vendor == VENDOR_RICOH) { - return (TRUE); - } - /* JMicron Standard SDIO Host */ - if (device == JMICRON_SDIOH_ID && vendor == VENDOR_JMICRON) { - return (TRUE); - } - -#endif /* BCMSDIOH_STD */ -#ifdef BCMSDIOH_SPI - /* This is the PciSpiHost. */ - if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) { - printf("Found PCI SPI Host Controller\n"); - return (TRUE); - } - -#endif /* BCMSDIOH_SPI */ - - return (FALSE); -} - -#if defined(BCMPLATFORM_BUS) -#if defined(BCMLXSDMMC) -/* forward declarations */ -int bcmsdh_probe(struct device *dev); -int bcmsdh_remove(struct device *dev); - -EXPORT_SYMBOL(bcmsdh_probe); -EXPORT_SYMBOL(bcmsdh_remove); - -#else -/* forward declarations */ -static int __devinit bcmsdh_probe(struct device *dev); -static int __devexit bcmsdh_remove(struct device *dev); -#endif /* BCMLXSDMMC */ - -#ifndef BCMLXSDMMC -static struct device_driver bcmsdh_driver = { - .name = "pxa2xx-mci", - .bus = &platform_bus_type, - .probe = bcmsdh_probe, - .remove = bcmsdh_remove, - .suspend = NULL, - .resume = NULL, - }; -#endif /* BCMLXSDMMC */ - -#ifndef BCMLXSDMMC -static -#endif /* BCMLXSDMMC */ -int bcmsdh_probe(struct device *dev) -{ - osl_t *osh = NULL; - bcmsdh_hc_t *sdhc = NULL; - ulong regs = 0; - bcmsdh_info_t *sdh = NULL; -#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) - struct platform_device *pdev; - struct resource *r; -#endif /* BCMLXSDMMC */ - int irq = 0; - uint32 vendevid; - unsigned long irq_flags = 0; - -#if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) - pdev = to_platform_device(dev); - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - irq = platform_get_irq(pdev, 0); - if (!r || irq == NO_IRQ) - return -ENXIO; -#endif /* BCMLXSDMMC */ - -#if defined(OOB_INTR_ONLY) - irq_flags = IRQF_TRIGGER_FALLING; - irq = dhd_customer_oob_irq_map(&irq_flags); - if (irq < 0) { - SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__)); - return 1; - } -#endif /* defined(OOB_INTR_ONLY) */ - /* allocate SDIO Host Controller state info */ - if (!(osh = osl_attach(dev, PCI_BUS, FALSE))) { - SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); - goto err; - } - if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) { - SDLX_MSG(("%s: out of memory, allocated %d bytes\n", - __FUNCTION__, - MALLOCED(osh))); - goto err; - } - bzero(sdhc, sizeof(bcmsdh_hc_t)); - sdhc->osh = osh; - - sdhc->dev = (void *)dev; - -#ifdef BCMLXSDMMC - if (!(sdh = bcmsdh_attach(osh, (void *)0, - (void **)®s, irq))) { - SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); - goto err; - } -#else - if (!(sdh = bcmsdh_attach(osh, (void *)r->start, - (void **)®s, irq))) { - SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); - goto err; - } -#endif /* BCMLXSDMMC */ - sdhc->sdh = sdh; - sdhc->oob_irq = irq; - sdhc->oob_flags = irq_flags; - - /* chain SDIO Host Controller info together */ - sdhc->next = sdhcinfo; - sdhcinfo = sdhc; - /* Read the vendor/device ID from the CIS */ - vendevid = bcmsdh_query_device(sdh); - - /* try to attach to the target device */ - if (!(sdhc->ch = drvinfo.attach((vendevid >> 16), - (vendevid & 0xFFFF), 0, 0, 0, 0, - (void *)regs, NULL, sdh))) { - SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); - goto err; - } - - return 0; - - /* error handling */ -err: - if (sdhc) { - if (sdhc->sdh) - bcmsdh_detach(sdhc->osh, sdhc->sdh); - MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); - } - if (osh) - osl_detach(osh); - return -ENODEV; -} - -#ifndef BCMLXSDMMC -static -#endif /* BCMLXSDMMC */ -int bcmsdh_remove(struct device *dev) -{ - bcmsdh_hc_t *sdhc, *prev; - osl_t *osh; - - sdhc = sdhcinfo; - drvinfo.detach(sdhc->ch); - bcmsdh_detach(sdhc->osh, sdhc->sdh); - /* find the SDIO Host Controller state for this pdev and take it out from the list */ - for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { - if (sdhc->dev == (void *)dev) { - if (prev) - prev->next = sdhc->next; - else - sdhcinfo = NULL; - break; - } - prev = sdhc; - } - if (!sdhc) { - SDLX_MSG(("%s: failed\n", __FUNCTION__)); - return 0; - } - - - /* release SDIO Host Controller info */ - osh = sdhc->osh; - MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); - osl_detach(osh); - -#if !defined(BCMLXSDMMC) - dev_set_drvdata(dev, NULL); -#endif /* !defined(BCMLXSDMMC) */ - - return 0; -} - -#else /* BCMPLATFORM_BUS */ - -#if !defined(BCMLXSDMMC) -/* forward declarations for PCI probe and remove functions. */ -static int __devinit bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void __devexit bcmsdh_pci_remove(struct pci_dev *pdev); - -/** - * pci id table - */ -static struct pci_device_id bcmsdh_pci_devid[] __devinitdata = { - { vendor: PCI_ANY_ID, - device: PCI_ANY_ID, - subvendor: PCI_ANY_ID, - subdevice: PCI_ANY_ID, - class: 0, - class_mask: 0, - driver_data: 0, - }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, bcmsdh_pci_devid); - -/** - * SDIO Host Controller pci driver info - */ -static struct pci_driver bcmsdh_pci_driver = { - node: {}, - name: "bcmsdh", - id_table: bcmsdh_pci_devid, - probe: bcmsdh_pci_probe, - remove: bcmsdh_pci_remove, -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) - save_state: NULL, -#endif - suspend: NULL, - resume: NULL, - }; - - -extern uint sd_pci_slot; /* Force detection to a particular PCI */ - /* slot only . Allows for having multiple */ - /* WL devices at once in a PC */ - /* Only one instance of dhd will be */ - /* useable at a time */ - /* Upper word is bus number, */ - /* lower word is slot number */ - /* Default value of 0xFFFFffff turns this */ - /* off */ -module_param(sd_pci_slot, uint, 0); - - -/** - * Detect supported SDIO Host Controller and attach if found. - * - * Determine if the device described by pdev is a supported SDIO Host - * Controller. If so, attach to it and attach to the target device. - */ -static int __devinit -bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - osl_t *osh = NULL; - bcmsdh_hc_t *sdhc = NULL; - ulong regs; - bcmsdh_info_t *sdh = NULL; - int rc; - - if (sd_pci_slot != 0xFFFFffff) { - if (pdev->bus->number != (sd_pci_slot>>16) || - PCI_SLOT(pdev->devfn) != (sd_pci_slot&0xffff)) { - SDLX_MSG(("%s: %s: bus %X, slot %X, vend %X, dev %X\n", - __FUNCTION__, - bcmsdh_chipmatch(pdev->vendor, pdev->device) - ?"Found compatible SDIOHC" - :"Probing unknown device", - pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, - pdev->device)); - return -ENODEV; - } - SDLX_MSG(("%s: %s: bus %X, slot %X, vendor %X, device %X (good PCI location)\n", - __FUNCTION__, - bcmsdh_chipmatch(pdev->vendor, pdev->device) - ?"Using compatible SDIOHC" - :"WARNING, forced use of unkown device", - pdev->bus->number, PCI_SLOT(pdev->devfn), pdev->vendor, pdev->device)); - } - - if ((pdev->vendor == VENDOR_TI) && ((pdev->device == PCIXX21_FLASHMEDIA_ID) || - (pdev->device == PCIXX21_FLASHMEDIA0_ID))) { - uint32 config_reg; - - SDLX_MSG(("%s: Disabling TI FlashMedia Controller.\n", __FUNCTION__)); - if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) { - SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); - goto err; - } - - config_reg = OSL_PCI_READ_CONFIG(osh, 0x4c, 4); - - /* - * Set MMC_SD_DIS bit in FlashMedia Controller. - * Disbling the SD/MMC Controller in the FlashMedia Controller - * allows the Standard SD Host Controller to take over control - * of the SD Slot. - */ - config_reg |= 0x02; - OSL_PCI_WRITE_CONFIG(osh, 0x4c, 4, config_reg); - osl_detach(osh); - } - /* match this pci device with what we support */ - /* we can't solely rely on this to believe it is our SDIO Host Controller! */ - if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) { - return -ENODEV; - } - - /* this is a pci device we might support */ - SDLX_MSG(("%s: Found possible SDIO Host Controller: bus %d slot %d func %d irq %d\n", - __FUNCTION__, - pdev->bus->number, PCI_SLOT(pdev->devfn), - PCI_FUNC(pdev->devfn), pdev->irq)); - - /* use bcmsdh_query_device() to get the vendor ID of the target device so - * it will eventually appear in the Broadcom string on the console - */ - - /* allocate SDIO Host Controller state info */ - if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) { - SDLX_MSG(("%s: osl_attach failed\n", __FUNCTION__)); - goto err; - } - if (!(sdhc = MALLOC(osh, sizeof(bcmsdh_hc_t)))) { - SDLX_MSG(("%s: out of memory, allocated %d bytes\n", - __FUNCTION__, - MALLOCED(osh))); - goto err; - } - bzero(sdhc, sizeof(bcmsdh_hc_t)); - sdhc->osh = osh; - - sdhc->dev = pdev; - - /* map to address where host can access */ - pci_set_master(pdev); - rc = pci_enable_device(pdev); - if (rc) { - SDLX_MSG(("%s: Cannot enble PCI device\n", __FUNCTION__)); - goto err; - } - if (!(sdh = bcmsdh_attach(osh, (void *)(uintptr)pci_resource_start(pdev, 0), - (void **)®s, pdev->irq))) { - SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__)); - goto err; - } - - sdhc->sdh = sdh; - - /* try to attach to the target device */ - if (!(sdhc->ch = drvinfo.attach(VENDOR_BROADCOM, /* pdev->vendor, */ - bcmsdh_query_device(sdh) & 0xFFFF, 0, 0, 0, 0, - (void *)regs, NULL, sdh))) { - SDLX_MSG(("%s: device attach failed\n", __FUNCTION__)); - goto err; - } - - /* chain SDIO Host Controller info together */ - sdhc->next = sdhcinfo; - sdhcinfo = sdhc; - - return 0; - - /* error handling */ -err: - if (sdhc->sdh) - bcmsdh_detach(sdhc->osh, sdhc->sdh); - if (sdhc) - MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); - if (osh) - osl_detach(osh); - return -ENODEV; -} - - -/** - * Detach from target devices and SDIO Host Controller - */ -static void __devexit -bcmsdh_pci_remove(struct pci_dev *pdev) -{ - bcmsdh_hc_t *sdhc, *prev; - osl_t *osh; - - /* find the SDIO Host Controller state for this pdev and take it out from the list */ - for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { - if (sdhc->dev == pdev) { - if (prev) - prev->next = sdhc->next; - else - sdhcinfo = NULL; - break; - } - prev = sdhc; - } - if (!sdhc) - return; - - drvinfo.detach(sdhc->ch); - - bcmsdh_detach(sdhc->osh, sdhc->sdh); - - /* release SDIO Host Controller info */ - osh = sdhc->osh; - MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); - osl_detach(osh); -} -#endif /* BCMLXSDMMC */ -#endif /* BCMPLATFORM_BUS */ - -extern int sdio_function_init(void); - -int -bcmsdh_register(bcmsdh_driver_t *driver) -{ - int error = 0; - - drvinfo = *driver; - -#if defined(BCMPLATFORM_BUS) -#if defined(BCMLXSDMMC) - SDLX_MSG(("Linux Kernel SDIO/MMC Driver\n")); - error = sdio_function_init(); -#else - SDLX_MSG(("Intel PXA270 SDIO Driver\n")); - error = driver_register(&bcmsdh_driver); -#endif /* defined(BCMLXSDMMC) */ - return error; -#endif /* defined(BCMPLATFORM_BUS) */ - -#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) - if (!(error = pci_module_init(&bcmsdh_pci_driver))) - return 0; -#else - if (!(error = pci_register_driver(&bcmsdh_pci_driver))) - return 0; -#endif - - SDLX_MSG(("%s: pci_module_init failed 0x%x\n", __FUNCTION__, error)); -#endif /* BCMPLATFORM_BUS */ - - return error; -} - -extern void sdio_function_cleanup(void); - -void -bcmsdh_unregister(void) -{ -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) - if (bcmsdh_pci_driver.node.next) -#endif - -#if defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) - driver_unregister(&bcmsdh_driver); -#endif -#if defined(BCMLXSDMMC) - sdio_function_cleanup(); -#endif /* BCMLXSDMMC */ -#if !defined(BCMPLATFORM_BUS) && !defined(BCMLXSDMMC) - pci_unregister_driver(&bcmsdh_pci_driver); -#endif /* BCMPLATFORM_BUS */ -} - -#if defined(OOB_INTR_ONLY) -static irqreturn_t wlan_oob_irq(int irq, void *dev_id) -{ - dhd_pub_t *dhdp; - - dhdp = (dhd_pub_t *)dev_get_drvdata(sdhcinfo->dev); - - if (dhdp == NULL) { - disable_irq(sdhcinfo->oob_irq); - SDLX_MSG(("Out of band GPIO interrupt fired way too early\n")); - return IRQ_HANDLED; - } - - WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25); - - dhdsdio_isr((void *)dhdp->bus); - - return IRQ_HANDLED; -} - -int bcmsdh_register_oob_intr(void * dhdp) -{ - int error = 0; - - SDLX_MSG(("%s Enter\n", __FUNCTION__)); - - dev_set_drvdata(sdhcinfo->dev, dhdp); - - - /* Refer to customer Host IRQ docs about proper irqflags definition */ - error = request_irq(sdhcinfo->oob_irq, wlan_oob_irq, sdhcinfo->oob_flags, - "bcmsdh_sdmmc", NULL); - - if (error) - return -ENODEV; - - set_irq_wake(sdhcinfo->oob_irq, 1); - - return 0; -} - -void bcmsdh_unregister_oob_intr(void) -{ - SDLX_MSG(("%s: Enter\n", __FUNCTION__)); - - set_irq_wake(sdhcinfo->oob_irq, 0); - disable_irq(sdhcinfo->oob_irq); /* just in case.. */ - free_irq(sdhcinfo->oob_irq, NULL); -} - -void bcmsdh_oob_intr_set(bool enable) -{ - if (enable) - enable_irq(sdhcinfo->oob_irq); - else - disable_irq(sdhcinfo->oob_irq); -} -#endif /* defined(OOB_INTR_ONLY) */ -/* Module parameters specific to each host-controller driver */ - -extern uint sd_msglevel; /* Debug message level */ -module_param(sd_msglevel, uint, 0); - -extern uint sd_power; /* 0 = SD Power OFF, 1 = SD Power ON. */ -module_param(sd_power, uint, 0); - -extern uint sd_clock; /* SD Clock Control, 0 = SD Clock OFF, 1 = SD Clock ON */ -module_param(sd_clock, uint, 0); - -extern uint sd_divisor; /* Divisor (-1 means external clock) */ -module_param(sd_divisor, uint, 0); - -extern uint sd_sdmode; /* Default is SD4, 0=SPI, 1=SD1, 2=SD4 */ -module_param(sd_sdmode, uint, 0); - -extern uint sd_hiok; /* Ok to use hi-speed mode */ -module_param(sd_hiok, uint, 0); - -extern uint sd_f2_blocksize; -module_param(sd_f2_blocksize, int, 0); - - -#ifdef BCMSDH_MODULE -EXPORT_SYMBOL(bcmsdh_attach); -EXPORT_SYMBOL(bcmsdh_detach); -EXPORT_SYMBOL(bcmsdh_intr_query); -EXPORT_SYMBOL(bcmsdh_intr_enable); -EXPORT_SYMBOL(bcmsdh_intr_disable); -EXPORT_SYMBOL(bcmsdh_intr_reg); -EXPORT_SYMBOL(bcmsdh_intr_dereg); - -#if defined(DHD_DEBUG) -EXPORT_SYMBOL(bcmsdh_intr_pending); -#endif - -EXPORT_SYMBOL(bcmsdh_devremove_reg); -EXPORT_SYMBOL(bcmsdh_cfg_read); -EXPORT_SYMBOL(bcmsdh_cfg_write); -EXPORT_SYMBOL(bcmsdh_cis_read); -EXPORT_SYMBOL(bcmsdh_reg_read); -EXPORT_SYMBOL(bcmsdh_reg_write); -EXPORT_SYMBOL(bcmsdh_regfail); -EXPORT_SYMBOL(bcmsdh_send_buf); -EXPORT_SYMBOL(bcmsdh_recv_buf); - -EXPORT_SYMBOL(bcmsdh_rwdata); -EXPORT_SYMBOL(bcmsdh_abort); -EXPORT_SYMBOL(bcmsdh_query_device); -EXPORT_SYMBOL(bcmsdh_query_iofnum); -EXPORT_SYMBOL(bcmsdh_iovar_op); -EXPORT_SYMBOL(bcmsdh_register); -EXPORT_SYMBOL(bcmsdh_unregister); -EXPORT_SYMBOL(bcmsdh_chipmatch); -EXPORT_SYMBOL(bcmsdh_reset); - -EXPORT_SYMBOL(bcmsdh_get_dstatus); -EXPORT_SYMBOL(bcmsdh_cfg_read_word); -EXPORT_SYMBOL(bcmsdh_cfg_write_word); -EXPORT_SYMBOL(bcmsdh_cur_sbwad); -EXPORT_SYMBOL(bcmsdh_chipinfo); - -#endif /* BCMSDH_MODULE */ diff --git a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c deleted file mode 100644 index 6581614c0ebf..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc.c +++ /dev/null @@ -1,1299 +0,0 @@ -/* - * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdh_sdmmc.c,v 1.1.2.5.6.29 2010/03/19 17:16:08 Exp $ - */ -#include - -#include -#include -#include -#include -#include /* SDIO Device and Protocol Specs */ -#include /* SDIO Host Controller Specification */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* ioctl/iovars */ - -#include -#include -#include - -#include -#include - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) -#include -extern volatile bool dhd_mmc_suspend; -#endif -#include "bcmsdh_sdmmc.h" - -#ifndef BCMSDH_MODULE -extern int sdio_function_init(void); -extern void sdio_function_cleanup(void); -#endif /* BCMSDH_MODULE */ - -#if !defined(OOB_INTR_ONLY) -static void IRQHandler(struct sdio_func *func); -static void IRQHandlerF2(struct sdio_func *func); -#endif -static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr); -extern int sdio_reset_comm(struct mmc_card *card); - -extern PBCMSDH_SDMMC_INSTANCE gInstance; - -uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ -uint sd_f2_blocksize = 512; /* Default blocksize */ - -uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */ - -uint sd_power = 1; /* Default to SD Slot powered ON */ -uint sd_clock = 1; /* Default to SD Clock turned ON */ -uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */ -uint sd_msglevel = 0x01; -uint sd_use_dma = TRUE; -DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); -DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); -DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); -DHD_PM_RESUME_WAIT_INIT(sdioh_request_buffer_wait); - -#define DMA_ALIGN_MASK 0x03 - -int sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data); - -static int -sdioh_sdmmc_card_enablefuncs(sdioh_info_t *sd) -{ - int err_ret; - uint32 fbraddr; - uint8 func; - - sd_trace(("%s\n", __FUNCTION__)); - - /* Get the Card's common CIS address */ - sd->com_cis_ptr = sdioh_sdmmc_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0); - sd->func_cis_ptr[0] = sd->com_cis_ptr; - sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); - - /* Get the Card's function CIS (for each function) */ - for (fbraddr = SDIOD_FBR_STARTADDR, func = 1; - func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { - sd->func_cis_ptr[func] = sdioh_sdmmc_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr); - sd_info(("%s: Function %d CIS Ptr = 0x%x\n", - __FUNCTION__, func, sd->func_cis_ptr[func])); - } - - sd->func_cis_ptr[0] = sd->com_cis_ptr; - sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); - - /* Enable Function 1 */ - sdio_claim_host(gInstance->func[1]); - err_ret = sdio_enable_func(gInstance->func[1]); - sdio_release_host(gInstance->func[1]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to enable F1 Err: 0x%08x", err_ret)); - } - - return FALSE; -} - -/* - * Public entry points & extern's - */ -extern sdioh_info_t * -sdioh_attach(osl_t *osh, void *bar0, uint irq) -{ - sdioh_info_t *sd; - int err_ret; - - sd_trace(("%s\n", __FUNCTION__)); - - if (gInstance == NULL) { - sd_err(("%s: SDIO Device not present\n", __FUNCTION__)); - return NULL; - } - - if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) { - sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh))); - return NULL; - } - bzero((char *)sd, sizeof(sdioh_info_t)); - sd->osh = osh; - if (sdioh_sdmmc_osinit(sd) != 0) { - sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __FUNCTION__)); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return NULL; - } - - sd->num_funcs = 2; - sd->sd_blockmode = TRUE; - sd->use_client_ints = TRUE; - sd->client_block_size[0] = 64; - - gInstance->sd = sd; - - /* Claim host controller */ - sdio_claim_host(gInstance->func[1]); - - sd->client_block_size[1] = 64; - err_ret = sdio_set_block_size(gInstance->func[1], 64); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n")); - } - - /* Release host controller F1 */ - sdio_release_host(gInstance->func[1]); - - if (gInstance->func[2]) { - /* Claim host controller F2 */ - sdio_claim_host(gInstance->func[2]); - - sd->client_block_size[2] = sd_f2_blocksize; - err_ret = sdio_set_block_size(gInstance->func[2], sd_f2_blocksize); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to set F2 blocksize to %d\n", - sd_f2_blocksize)); - } - - /* Release host controller F2 */ - sdio_release_host(gInstance->func[2]); - } - - sdioh_sdmmc_card_enablefuncs(sd); - - sd_trace(("%s: Done\n", __FUNCTION__)); - return sd; -} - - -extern SDIOH_API_RC -sdioh_detach(osl_t *osh, sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - - if (sd) { - - /* Disable Function 2 */ - sdio_claim_host(gInstance->func[2]); - sdio_disable_func(gInstance->func[2]); - sdio_release_host(gInstance->func[2]); - - /* Disable Function 1 */ - sdio_claim_host(gInstance->func[1]); - sdio_disable_func(gInstance->func[1]); - sdio_release_host(gInstance->func[1]); - - /* deregister irq */ - sdioh_sdmmc_osfree(sd); - - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - } - return SDIOH_API_RC_SUCCESS; -} - -#if defined(OOB_INTR_ONLY) && defined(HW_OOB) - -extern SDIOH_API_RC -sdioh_enable_func_intr(void) -{ - uint8 reg; - int err; - - if (gInstance->func[0]) { - sdio_claim_host(gInstance->func[0]); - - reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err); - if (err) { - sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); - sdio_release_host(gInstance->func[0]); - return SDIOH_API_RC_FAIL; - } - - /* Enable F1 and F2 interrupts, set master enable */ - reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN | INTR_CTL_MASTER_EN); - - sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err); - sdio_release_host(gInstance->func[0]); - - if (err) { - sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); - return SDIOH_API_RC_FAIL; - } - } - - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_disable_func_intr(void) -{ - uint8 reg; - int err; - - if (gInstance->func[0]) { - sdio_claim_host(gInstance->func[0]); - reg = sdio_readb(gInstance->func[0], SDIOD_CCCR_INTEN, &err); - if (err) { - sd_err(("%s: error for read SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); - sdio_release_host(gInstance->func[0]); - return SDIOH_API_RC_FAIL; - } - - reg &= ~(INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); - /* Disable master interrupt with the last function interrupt */ - if (!(reg & 0xFE)) - reg = 0; - sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err); - - sdio_release_host(gInstance->func[0]); - if (err) { - sd_err(("%s: error for write SDIO_CCCR_IENx : 0x%x\n", __FUNCTION__, err)); - return SDIOH_API_RC_FAIL; - } - } - return SDIOH_API_RC_SUCCESS; -} -#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ - -/* Configure callback to client when we recieve client interrupt */ -extern SDIOH_API_RC -sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - if (fn == NULL) { - sd_err(("%s: interrupt handler is NULL, not registering\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } -#if !defined(OOB_INTR_ONLY) - sd->intr_handler = fn; - sd->intr_handler_arg = argh; - sd->intr_handler_valid = TRUE; - - /* register and unmask irq */ - if (gInstance->func[2]) { - sdio_claim_host(gInstance->func[2]); - sdio_claim_irq(gInstance->func[2], IRQHandlerF2); - sdio_release_host(gInstance->func[2]); - } - - if (gInstance->func[1]) { - sdio_claim_host(gInstance->func[1]); - sdio_claim_irq(gInstance->func[1], IRQHandler); - sdio_release_host(gInstance->func[1]); - } -#elif defined(HW_OOB) - sdioh_enable_func_intr(); -#endif /* defined(OOB_INTR_ONLY) */ - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_deregister(sdioh_info_t *sd) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - -#if !defined(OOB_INTR_ONLY) - if (gInstance->func[1]) { - /* register and unmask irq */ - sdio_claim_host(gInstance->func[1]); - sdio_release_irq(gInstance->func[1]); - sdio_release_host(gInstance->func[1]); - } - - if (gInstance->func[2]) { - /* Claim host controller F2 */ - sdio_claim_host(gInstance->func[2]); - sdio_release_irq(gInstance->func[2]); - /* Release host controller F2 */ - sdio_release_host(gInstance->func[2]); - } - - sd->intr_handler_valid = FALSE; - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; -#elif defined(HW_OOB) - sdioh_disable_func_intr(); -#endif /* !defined(OOB_INTR_ONLY) */ - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - *onoff = sd->client_intr_enabled; - return SDIOH_API_RC_SUCCESS; -} - -#if defined(DHD_DEBUG) -extern bool -sdioh_interrupt_pending(sdioh_info_t *sd) -{ - return (0); -} -#endif - -uint -sdioh_query_iofnum(sdioh_info_t *sd) -{ - return sd->num_funcs; -} - -/* IOVar table */ -enum { - IOV_MSGLEVEL = 1, - IOV_BLOCKMODE, - IOV_BLOCKSIZE, - IOV_DMA, - IOV_USEINTS, - IOV_NUMINTS, - IOV_NUMLOCALINTS, - IOV_HOSTREG, - IOV_DEVREG, - IOV_DIVISOR, - IOV_SDMODE, - IOV_HISPEED, - IOV_HCIREGS, - IOV_POWER, - IOV_CLOCK, - IOV_RXCHAIN -}; - -const bcm_iovar_t sdioh_iovars[] = { - {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, - {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 }, - {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ - {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 }, - {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, - {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, - {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, - {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, - {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, - {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, - {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}, - {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0 }, - {"sd_rxchain", IOV_RXCHAIN, 0, IOVT_BOOL, 0 }, - {NULL, 0, 0, 0, 0 } -}; - -int -sdioh_iovar_op(sdioh_info_t *si, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - const bcm_iovar_t *vi = NULL; - int bcmerror = 0; - int val_size; - int32 int_val = 0; - bool bool_val; - uint32 actionid; - - ASSERT(name); - ASSERT(len >= 0); - - /* Get must have return space; Set does not take qualifiers */ - ASSERT(set || (arg && len)); - ASSERT(!set || (!params && !plen)); - - sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name)); - - if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) { - bcmerror = BCME_UNSUPPORTED; - goto exit; - } - - if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0) - goto exit; - - /* Set up params so get and set can share the convenience variables */ - if (params == NULL) { - params = arg; - plen = len; - } - - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - val_size = sizeof(int); - - if (plen >= (int)sizeof(int_val)) - bcopy(params, &int_val, sizeof(int_val)); - - bool_val = (int_val != 0) ? TRUE : FALSE; - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - switch (actionid) { - case IOV_GVAL(IOV_MSGLEVEL): - int_val = (int32)sd_msglevel; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_MSGLEVEL): - sd_msglevel = int_val; - break; - - case IOV_GVAL(IOV_BLOCKMODE): - int_val = (int32)si->sd_blockmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_BLOCKMODE): - si->sd_blockmode = (bool)int_val; - /* Haven't figured out how to make non-block mode with DMA */ - break; - - case IOV_GVAL(IOV_BLOCKSIZE): - if ((uint32)int_val > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - int_val = (int32)si->client_block_size[int_val]; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_BLOCKSIZE): - { - uint func = ((uint32)int_val >> 16); - uint blksize = (uint16)int_val; - uint maxsize; - - if (func > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - - switch (func) { - case 0: maxsize = 32; break; - case 1: maxsize = BLOCK_SIZE_4318; break; - case 2: maxsize = BLOCK_SIZE_4328; break; - default: maxsize = 0; - } - if (blksize > maxsize) { - bcmerror = BCME_BADARG; - break; - } - if (!blksize) { - blksize = maxsize; - } - - /* Now set it */ - si->client_block_size[func] = blksize; - - break; - } - - case IOV_GVAL(IOV_RXCHAIN): - int_val = FALSE; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_DMA): - int_val = (int32)si->sd_use_dma; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DMA): - si->sd_use_dma = (bool)int_val; - break; - - case IOV_GVAL(IOV_USEINTS): - int_val = (int32)si->use_client_ints; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_USEINTS): - si->use_client_ints = (bool)int_val; - if (si->use_client_ints) - si->intmask |= CLIENT_INTR; - else - si->intmask &= ~CLIENT_INTR; - - break; - - case IOV_GVAL(IOV_DIVISOR): - int_val = (uint32)sd_divisor; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DIVISOR): - sd_divisor = int_val; - break; - - case IOV_GVAL(IOV_POWER): - int_val = (uint32)sd_power; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_POWER): - sd_power = int_val; - break; - - case IOV_GVAL(IOV_CLOCK): - int_val = (uint32)sd_clock; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_CLOCK): - sd_clock = int_val; - break; - - case IOV_GVAL(IOV_SDMODE): - int_val = (uint32)sd_sdmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SDMODE): - sd_sdmode = int_val; - break; - - case IOV_GVAL(IOV_HISPEED): - int_val = (uint32)sd_hiok; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_HISPEED): - sd_hiok = int_val; - break; - - case IOV_GVAL(IOV_NUMINTS): - int_val = (int32)si->intrcount; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_NUMLOCALINTS): - int_val = (int32)0; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_HOSTREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - - if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { - sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset)); - bcmerror = BCME_BADARG; - break; - } - - sd_trace(("%s: rreg%d at offset %d\n", __FUNCTION__, - (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), - sd_ptr->offset)); - if (sd_ptr->offset & 1) - int_val = 8; /* sdioh_sdmmc_rreg8(si, sd_ptr->offset); */ - else if (sd_ptr->offset & 2) - int_val = 16; /* sdioh_sdmmc_rreg16(si, sd_ptr->offset); */ - else - int_val = 32; /* sdioh_sdmmc_rreg(si, sd_ptr->offset); */ - - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_HOSTREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - - if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { - sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset)); - bcmerror = BCME_BADARG; - break; - } - - sd_trace(("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value, - (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), - sd_ptr->offset)); - break; - } - - case IOV_GVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data = 0; - - if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - - int_val = (int)data; - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data = (uint8)sd_ptr->value; - - if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - break; - } - - default: - bcmerror = BCME_UNSUPPORTED; - break; - } -exit: - - return bcmerror; -} - -#if defined(OOB_INTR_ONLY) && defined(HW_OOB) - -SDIOH_API_RC -sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable) -{ - SDIOH_API_RC status; - uint8 data; - - if (enable) - data = 3; /* enable hw oob interrupt */ - else - data = 4; /* disable hw oob interrupt */ - - status = sdioh_request_byte(sd, SDIOH_WRITE, 0, 0xf2, &data); - return status; -} -#endif /* defined(OOB_INTR_ONLY) && defined(HW_OOB) */ - -extern SDIOH_API_RC -sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - SDIOH_API_RC status; - /* No lock needed since sdioh_request_byte does locking */ - status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - /* No lock needed since sdioh_request_byte does locking */ - SDIOH_API_RC status; - status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); - return status; -} - -static int -sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr) -{ - /* read 24 bits and return valid 17 bit addr */ - int i; - uint32 scratch, regdata; - uint8 *ptr = (uint8 *)&scratch; - for (i = 0; i < 3; i++) { - if ((sdioh_sdmmc_card_regread (sd, 0, regaddr, 1, ®data)) != SUCCESS) - sd_err(("%s: Can't read!\n", __FUNCTION__)); - - *ptr++ = (uint8) regdata; - regaddr++; - } - - /* Only the lower 17-bits are valid */ - scratch = ltoh32(scratch); - scratch &= 0x0001FFFF; - return (scratch); -} - -extern SDIOH_API_RC -sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) -{ - uint32 count; - int offset; - uint32 foo; - uint8 *cis = cisd; - - sd_trace(("%s: Func = %d\n", __FUNCTION__, func)); - - if (!sd->func_cis_ptr[func]) { - bzero(cis, length); - sd_err(("%s: no func_cis_ptr[%d]\n", __FUNCTION__, func)); - return SDIOH_API_RC_FAIL; - } - - sd_err(("%s: func_cis_ptr[%d]=0x%04x\n", __FUNCTION__, func, sd->func_cis_ptr[func])); - - for (count = 0; count < length; count++) { - offset = sd->func_cis_ptr[func] + count; - if (sdioh_sdmmc_card_regread (sd, 0, offset, 1, &foo) < 0) { - sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } - - *cis = (uint8)(foo & 0xff); - cis++; - } - - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) -{ - int err_ret; - - sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); - - DHD_PM_RESUME_WAIT(sdioh_request_byte_wait); - DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); - if(rw) { /* CMD52 Write */ - if (func == 0) { - /* Can only directly write to some F0 registers. Handle F2 enable - * as a special case. - */ - if (regaddr == SDIOD_CCCR_IOEN) { - if (gInstance->func[2]) { - sdio_claim_host(gInstance->func[2]); - if (*byte & SDIO_FUNC_ENABLE_2) { - /* Enable Function 2 */ - err_ret = sdio_enable_func(gInstance->func[2]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: enable F2 failed:%d", - err_ret)); - } - } else { - /* Disable Function 2 */ - err_ret = sdio_disable_func(gInstance->func[2]); - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Disab F2 failed:%d", - err_ret)); - } - } - sdio_release_host(gInstance->func[2]); - } - } -#if defined(MMC_SDIO_ABORT) - /* to allow abort command through F1 */ - else if (regaddr == SDIOD_CCCR_IOABORT) { - sdio_claim_host(gInstance->func[func]); - /* - * this sdio_f0_writeb() can be replaced with another api - * depending upon MMC driver change. - * As of this time, this is temporaray one - */ - sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); - } -#endif /* MMC_SDIO_ABORT */ - else if (regaddr < 0xF0) { - sd_err(("bcmsdh_sdmmc: F0 Wr:0x%02x: write disallowed\n", regaddr)); - } else { - /* Claim host controller, perform F0 write, and release */ - sdio_claim_host(gInstance->func[func]); - sdio_f0_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); - } - } else { - /* Claim host controller, perform Fn write, and release */ - sdio_claim_host(gInstance->func[func]); - sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); - sdio_release_host(gInstance->func[func]); - } - } else { /* CMD52 Read */ - /* Claim host controller, perform Fn read, and release */ - sdio_claim_host(gInstance->func[func]); - - if (func == 0) { - *byte = sdio_f0_readb(gInstance->func[func], regaddr, &err_ret); - } else { - *byte = sdio_readb(gInstance->func[func], regaddr, &err_ret); - } - - sdio_release_host(gInstance->func[func]); - } - - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", - rw ? "Write" : "Read", func, regaddr, *byte, err_ret)); - } - - return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); -} - -extern SDIOH_API_RC -sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, - uint32 *word, uint nbytes) -{ - int err_ret = SDIOH_API_RC_FAIL; - - if (func == 0) { - sd_err(("%s: Only CMD52 allowed to F0.\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } - - sd_info(("%s: cmd_type=%d, rw=%d, func=%d, addr=0x%05x, nbytes=%d\n", - __FUNCTION__, cmd_type, rw, func, addr, nbytes)); - - DHD_PM_RESUME_WAIT(sdioh_request_word_wait); - DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); - /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); - - if(rw) { /* CMD52 Write */ - if (nbytes == 4) { - sdio_writel(gInstance->func[func], *word, addr, &err_ret); - } else if (nbytes == 2) { - sdio_writew(gInstance->func[func], (*word & 0xFFFF), addr, &err_ret); - } else { - sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes)); - } - } else { /* CMD52 Read */ - if (nbytes == 4) { - *word = sdio_readl(gInstance->func[func], addr, &err_ret); - } else if (nbytes == 2) { - *word = sdio_readw(gInstance->func[func], addr, &err_ret) & 0xFFFF; - } else { - sd_err(("%s: Invalid nbytes: %d\n", __FUNCTION__, nbytes)); - } - } - - /* Release host controller */ - sdio_release_host(gInstance->func[func]); - - if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", - rw ? "Write" : "Read", err_ret)); - } - - return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); -} - -static SDIOH_API_RC -sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, - uint addr, void *pkt) -{ - bool fifo = (fix_inc == SDIOH_DATA_FIX); - uint32 SGCount = 0; - int err_ret = 0; - - void *pnext; - - sd_trace(("%s: Enter\n", __FUNCTION__)); - - ASSERT(pkt); - DHD_PM_RESUME_WAIT(sdioh_request_packet_wait); - DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); - - /* Claim host controller */ - sdio_claim_host(gInstance->func[func]); - for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) { - uint pkt_len = PKTLEN(sd->osh, pnext); - pkt_len += 3; - pkt_len &= 0xFFFFFFFC; - -#ifdef CONFIG_MMC_MSM7X00A - if ((pkt_len % 64) == 32) { - sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); - pkt_len += 32; - } -#endif /* CONFIG_MMC_MSM7X00A */ - /* Make sure the packet is aligned properly. If it isn't, then this - * is the fault of sdioh_request_buffer() which is supposed to give - * us something we can work with. - */ - ASSERT(((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) == 0); - - if ((write) && (!fifo)) { - err_ret = sdio_memcpy_toio(gInstance->func[func], addr, - ((uint8*)PKTDATA(sd->osh, pnext)), - pkt_len); - } else if (write) { - err_ret = sdio_memcpy_toio(gInstance->func[func], addr, - ((uint8*)PKTDATA(sd->osh, pnext)), - pkt_len); - } else if (fifo) { - err_ret = sdio_readsb(gInstance->func[func], - ((uint8*)PKTDATA(sd->osh, pnext)), - addr, - pkt_len); - } else { - err_ret = sdio_memcpy_fromio(gInstance->func[func], - ((uint8*)PKTDATA(sd->osh, pnext)), - addr, - pkt_len); - } - - if (err_ret) { - sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n", - __FUNCTION__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len, err_ret)); - } else { - sd_trace(("%s: %s xfr'd %p[%d], addr=0x%05x, len=%d\n", - __FUNCTION__, - (write) ? "TX" : "RX", - pnext, SGCount, addr, pkt_len)); - } - - if (!fifo) { - addr += pkt_len; - } - SGCount ++; - - } - - /* Release host controller */ - sdio_release_host(gInstance->func[func]); - - sd_trace(("%s: Exit\n", __FUNCTION__)); - return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); -} - - -/* - * This function takes a buffer or packet, and fixes everything up so that in the - * end, a DMA-able packet is created. - * - * A buffer does not have an associated packet pointer, and may or may not be aligned. - * A packet may consist of a single packet, or a packet chain. If it is a packet chain, - * then all the packets in the chain must be properly aligned. If the packet data is not - * aligned, then there may only be one packet, and in this case, it is copied to a new - * aligned packet. - * - */ -extern SDIOH_API_RC -sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, uint func, - uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) -{ - SDIOH_API_RC Status; - void *mypkt = NULL; - - sd_trace(("%s: Enter\n", __FUNCTION__)); - - DHD_PM_RESUME_WAIT(sdioh_request_buffer_wait); - DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); - /* Case 1: we don't have a packet. */ - if (pkt == NULL) { - sd_data(("%s: Creating new %s Packet, len=%d\n", - __FUNCTION__, write ? "TX" : "RX", buflen_u)); -#ifdef DHD_USE_STATIC_BUF - if (!(mypkt = PKTGET_STATIC(sd->osh, buflen_u, write ? TRUE : FALSE))) { -#else - if (!(mypkt = PKTGET(sd->osh, buflen_u, write ? TRUE : FALSE))) { -#endif /* DHD_USE_STATIC_BUF */ - sd_err(("%s: PKTGET failed: len %d\n", - __FUNCTION__, buflen_u)); - return SDIOH_API_RC_FAIL; - } - - /* For a write, copy the buffer data into the packet. */ - if (write) { - bcopy(buffer, PKTDATA(sd->osh, mypkt), buflen_u); - } - - Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt); - - /* For a read, copy the packet data back to the buffer. */ - if (!write) { - bcopy(PKTDATA(sd->osh, mypkt), buffer, buflen_u); - } -#ifdef DHD_USE_STATIC_BUF - PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); -#else - PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); -#endif /* DHD_USE_STATIC_BUF */ - } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { - /* Case 2: We have a packet, but it is unaligned. */ - - /* In this case, we cannot have a chain. */ - ASSERT(PKTNEXT(sd->osh, pkt) == NULL); - - sd_data(("%s: Creating aligned %s Packet, len=%d\n", - __FUNCTION__, write ? "TX" : "RX", PKTLEN(sd->osh, pkt))); -#ifdef DHD_USE_STATIC_BUF - if (!(mypkt = PKTGET_STATIC(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { -#else - if (!(mypkt = PKTGET(sd->osh, PKTLEN(sd->osh, pkt), write ? TRUE : FALSE))) { -#endif /* DHD_USE_STATIC_BUF */ - sd_err(("%s: PKTGET failed: len %d\n", - __FUNCTION__, PKTLEN(sd->osh, pkt))); - return SDIOH_API_RC_FAIL; - } - - /* For a write, copy the buffer data into the packet. */ - if (write) { - bcopy(PKTDATA(sd->osh, pkt), - PKTDATA(sd->osh, mypkt), - PKTLEN(sd->osh, pkt)); - } - - Status = sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt); - - /* For a read, copy the packet data back to the buffer. */ - if (!write) { - bcopy(PKTDATA(sd->osh, mypkt), - PKTDATA(sd->osh, pkt), - PKTLEN(sd->osh, mypkt)); - } -#ifdef DHD_USE_STATIC_BUF - PKTFREE_STATIC(sd->osh, mypkt, write ? TRUE : FALSE); -#else - PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); -#endif /* DHD_USE_STATIC_BUF */ - } else { /* case 3: We have a packet and it is aligned. */ - sd_data(("%s: Aligned %s Packet, direct DMA\n", - __FUNCTION__, write ? "Tx" : "Rx")); - Status = sdioh_request_packet(sd, fix_inc, write, func, addr, pkt); - } - - return (Status); -} - -extern int -sdioh_abort(sdioh_info_t *sd, uint func) -{ - sd_trace(("%s: Enter\n", __FUNCTION__)); - -#if defined(MMC_SDIO_ABORT) - /* issue abort cmd52 command through F1 */ - sdioh_request_byte(sd, SD_IO_OP_WRITE, SDIO_FUNC_0, SDIOD_CCCR_IOABORT, (uint8 *)&func); -#endif /* defined(MMC_SDIO_ABORT) */ - - sd_trace(("%s: Exit\n", __FUNCTION__)); - return SDIOH_API_RC_SUCCESS; -} - -/* Reset and re-initialize the device */ -int sdioh_sdio_reset(sdioh_info_t *si) -{ - sd_trace(("%s: Enter\n", __FUNCTION__)); - sd_trace(("%s: Exit\n", __FUNCTION__)); - return SDIOH_API_RC_SUCCESS; -} - -/* Disable device interrupt */ -void -sdioh_sdmmc_devintr_off(sdioh_info_t *sd) -{ - sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints)); - sd->intmask &= ~CLIENT_INTR; -} - -/* Enable device interrupt */ -void -sdioh_sdmmc_devintr_on(sdioh_info_t *sd) -{ - sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints)); - sd->intmask |= CLIENT_INTR; -} - -/* Read client card reg */ -int -sdioh_sdmmc_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) -{ - - if ((func == 0) || (regsize == 1)) { - uint8 temp = 0; - - sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp); - *data = temp; - *data &= 0xff; - sd_data(("%s: byte read data=0x%02x\n", - __FUNCTION__, *data)); - } else { - sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, data, regsize); - if (regsize == 2) - *data &= 0xffff; - - sd_data(("%s: word read data=0x%08x\n", - __FUNCTION__, *data)); - } - - return SUCCESS; -} - -#if !defined(OOB_INTR_ONLY) -/* bcmsdh_sdmmc interrupt handler */ -static void IRQHandler(struct sdio_func *func) -{ - sdioh_info_t *sd; - - sd_trace(("bcmsdh_sdmmc: ***IRQHandler\n")); - sd = gInstance->sd; - - ASSERT(sd != NULL); - sdio_release_host(gInstance->func[0]); - - if (sd->use_client_ints) { - sd->intrcount++; - ASSERT(sd->intr_handler); - ASSERT(sd->intr_handler_arg); - (sd->intr_handler)(sd->intr_handler_arg); - } else { - sd_err(("bcmsdh_sdmmc: ***IRQHandler\n")); - - sd_err(("%s: Not ready for intr: enabled %d, handler %p\n", - __FUNCTION__, sd->client_intr_enabled, sd->intr_handler)); - } - - sdio_claim_host(gInstance->func[0]); -} - -/* bcmsdh_sdmmc interrupt handler for F2 (dummy handler) */ -static void IRQHandlerF2(struct sdio_func *func) -{ - sdioh_info_t *sd; - - sd_trace(("bcmsdh_sdmmc: ***IRQHandlerF2\n")); - - sd = gInstance->sd; - - ASSERT(sd != NULL); -} -#endif /* !defined(OOB_INTR_ONLY) */ - -#ifdef NOTUSED -/* Write client card reg */ -static int -sdioh_sdmmc_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data) -{ - - if ((func == 0) || (regsize == 1)) { - uint8 temp; - - temp = data & 0xff; - sdioh_request_byte(sd, SDIOH_READ, func, regaddr, &temp); - sd_data(("%s: byte write data=0x%02x\n", - __FUNCTION__, data)); - } else { - if (regsize == 2) - data &= 0xffff; - - sdioh_request_word(sd, 0, SDIOH_READ, func, regaddr, &data, regsize); - - sd_data(("%s: word write data=0x%08x\n", - __FUNCTION__, data)); - } - - return SUCCESS; -} -#endif /* NOTUSED */ - -int -sdioh_start(sdioh_info_t *si, int stage) -{ - int ret; - sdioh_info_t *sd = gInstance->sd; - - /* Need to do this stages as we can't enable the interrupt till - downloading of the firmware is complete, other wise polling - sdio access will come in way - */ - if (gInstance->func[0]) { - if (stage == 0) { - /* Since the power to the chip is killed, we will have - re enumerate the device again. Set the block size - and enable the fucntion 1 for in preparation for - downloading the code - */ - /* sdio_reset_comm() - has been fixed in latest kernel/msm.git for Linux - 2.6.27. The implementation prior to that is buggy, and needs broadcom's - patch for it - */ - if ((ret = sdio_reset_comm(gInstance->func[0]->card))) - sd_err(("%s Failed, error = %d\n", __FUNCTION__, ret)); - else { - sd->num_funcs = 2; - sd->sd_blockmode = TRUE; - sd->use_client_ints = TRUE; - sd->client_block_size[0] = 64; - - /* Claim host controller */ - sdio_claim_host(gInstance->func[1]); - - sd->client_block_size[1] = 64; - if (sdio_set_block_size(gInstance->func[1], 64)) { - sd_err(("bcmsdh_sdmmc: Failed to set F1 blocksize\n")); - } - - /* Release host controller F1 */ - sdio_release_host(gInstance->func[1]); - - if (gInstance->func[2]) { - /* Claim host controller F2 */ - sdio_claim_host(gInstance->func[2]); - - sd->client_block_size[2] = sd_f2_blocksize; - if (sdio_set_block_size(gInstance->func[2], - sd_f2_blocksize)) { - sd_err(("bcmsdh_sdmmc: Failed to set F2 " - "blocksize to %d\n", sd_f2_blocksize)); - } - - /* Release host controller F2 */ - sdio_release_host(gInstance->func[2]); - } - - sdioh_sdmmc_card_enablefuncs(sd); - } - } else { -#if !defined(OOB_INTR_ONLY) - sdio_claim_host(gInstance->func[0]); - sdio_claim_irq(gInstance->func[2], IRQHandlerF2); - sdio_claim_irq(gInstance->func[1], IRQHandler); - sdio_release_host(gInstance->func[0]); -#else /* defined(OOB_INTR_ONLY) */ -#if defined(HW_OOB) - sdioh_enable_func_intr(); -#endif - bcmsdh_oob_intr_set(TRUE); -#endif /* !defined(OOB_INTR_ONLY) */ - } - } - else - sd_err(("%s Failed\n", __FUNCTION__)); - - return (0); -} - -int -sdioh_stop(sdioh_info_t *si) -{ - /* MSM7201A Android sdio stack has bug with interrupt - So internaly within SDIO stack they are polling - which cause issue when device is turned off. So - unregister interrupt with SDIO stack to stop the - polling - */ - if (gInstance->func[0]) { -#if !defined(OOB_INTR_ONLY) - sdio_claim_host(gInstance->func[0]); - sdio_release_irq(gInstance->func[1]); - sdio_release_irq(gInstance->func[2]); - sdio_release_host(gInstance->func[0]); -#else /* defined(OOB_INTR_ONLY) */ -#if defined(HW_OOB) - sdioh_disable_func_intr(); -#endif - bcmsdh_oob_intr_set(FALSE); -#endif /* !defined(OOB_INTR_ONLY) */ - } - else - sd_err(("%s Failed\n", __FUNCTION__)); - return (0); -} diff --git a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c deleted file mode 100644 index 5260b482a8df..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdh_sdmmc_linux.c +++ /dev/null @@ -1,261 +0,0 @@ -/* - * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdh_sdmmc_linux.c,v 1.1.2.5.6.15 2010/04/14 21:11:46 Exp $ - */ - -#include -#include -#include /* SDIO Specs */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* to get msglevel bit values */ - -#include /* request_irq() */ - -#include -#include -#include -#include -#include - -#if !defined(SDIO_VENDOR_ID_BROADCOM) -#define SDIO_VENDOR_ID_BROADCOM 0x02d0 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4325) -#define SDIO_DEVICE_ID_BROADCOM_4325 0x0000 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4325) */ -#if !defined(SDIO_DEVICE_ID_BROADCOM_4329) -#define SDIO_DEVICE_ID_BROADCOM_4329 0x4329 -#endif /* !defined(SDIO_DEVICE_ID_BROADCOM_4329) */ - -#include - -#include - -extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); -extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); - -int sdio_function_init(void); -void sdio_function_cleanup(void); - -#define DESCRIPTION "bcmsdh_sdmmc Driver" -#define AUTHOR "Broadcom Corporation" - -/* module param defaults */ -static int clockoverride = 0; - -module_param(clockoverride, int, 0644); -MODULE_PARM_DESC(clockoverride, "SDIO card clock override"); - -PBCMSDH_SDMMC_INSTANCE gInstance; - -/* Maximum number of bcmsdh_sdmmc devices supported by driver */ -#define BCMSDH_SDMMC_MAX_DEVICES 1 - -extern int bcmsdh_probe(struct device *dev); -extern int bcmsdh_remove(struct device *dev); -struct device sdmmc_dev; - -static int bcmsdh_sdmmc_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - int ret = 0; - static struct sdio_func sdio_func_0; - sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__)); - sd_trace(("sdio_bcmsdh: func->class=%x\n", func->class)); - sd_trace(("sdio_vendor: 0x%04x\n", func->vendor)); - sd_trace(("sdio_device: 0x%04x\n", func->device)); - sd_trace(("Function#: 0x%04x\n", func->num)); - - if (func->num == 1) { - sdio_func_0.num = 0; - sdio_func_0.card = func->card; - gInstance->func[0] = &sdio_func_0; - if(func->device == 0x4) { /* 4318 */ - gInstance->func[2] = NULL; - sd_trace(("NIC found, calling bcmsdh_probe...\n")); - ret = bcmsdh_probe(&sdmmc_dev); - } - } - - gInstance->func[func->num] = func; - - if (func->num == 2) { - sd_trace(("F2 found, calling bcmsdh_probe...\n")); - ret = bcmsdh_probe(&sdmmc_dev); - } - - return ret; -} - -static void bcmsdh_sdmmc_remove(struct sdio_func *func) -{ - sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__)); - sd_info(("sdio_bcmsdh: func->class=%x\n", func->class)); - sd_info(("sdio_vendor: 0x%04x\n", func->vendor)); - sd_info(("sdio_device: 0x%04x\n", func->device)); - sd_info(("Function#: 0x%04x\n", func->num)); - - if (func->num == 2) { - sd_trace(("F2 found, calling bcmsdh_probe...\n")); - bcmsdh_remove(&sdmmc_dev); - } -} - -/* devices we support, null terminated */ -static const struct sdio_device_id bcmsdh_sdmmc_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4325) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_BROADCOM, SDIO_DEVICE_ID_BROADCOM_4329) }, - { /* end: all zeroes */ }, -}; - -MODULE_DEVICE_TABLE(sdio, bcmsdh_sdmmc_ids); - -static struct sdio_driver bcmsdh_sdmmc_driver = { - .probe = bcmsdh_sdmmc_probe, - .remove = bcmsdh_sdmmc_remove, - .name = "bcmsdh_sdmmc", - .id_table = bcmsdh_sdmmc_ids, - }; - -struct sdos_info { - sdioh_info_t *sd; - spinlock_t lock; -}; - - -int -sdioh_sdmmc_osinit(sdioh_info_t *sd) -{ - struct sdos_info *sdos; - - sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info)); - sd->sdos_info = (void*)sdos; - if (sdos == NULL) - return BCME_NOMEM; - - sdos->sd = sd; - spin_lock_init(&sdos->lock); - return BCME_OK; -} - -void -sdioh_sdmmc_osfree(sdioh_info_t *sd) -{ - struct sdos_info *sdos; - ASSERT(sd && sd->sdos_info); - - sdos = (struct sdos_info *)sd->sdos_info; - MFREE(sd->osh, sdos, sizeof(struct sdos_info)); -} - -/* Interrupt enable/disable */ -SDIOH_API_RC -sdioh_interrupt_set(sdioh_info_t *sd, bool enable) -{ - ulong flags; - struct sdos_info *sdos; - - sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling")); - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - -#if !defined(OOB_INTR_ONLY) - if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { - sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } -#endif /* !defined(OOB_INTR_ONLY) */ - - /* Ensure atomicity for enable/disable calls */ - spin_lock_irqsave(&sdos->lock, flags); - - sd->client_intr_enabled = enable; - if (enable) { - sdioh_sdmmc_devintr_on(sd); - } else { - sdioh_sdmmc_devintr_off(sd); - } - - spin_unlock_irqrestore(&sdos->lock, flags); - - return SDIOH_API_RC_SUCCESS; -} - - -#ifdef BCMSDH_MODULE -static int __init -bcmsdh_module_init(void) -{ - int error = 0; - sdio_function_init(); - return error; -} - -static void __exit -bcmsdh_module_cleanup(void) -{ - sdio_function_cleanup(); -} - -module_init(bcmsdh_module_init); -module_exit(bcmsdh_module_cleanup); - -MODULE_LICENSE("GPL v2"); -MODULE_DESCRIPTION(DESCRIPTION); -MODULE_AUTHOR(AUTHOR); - -#endif /* BCMSDH_MODULE */ -/* - * module init -*/ -int sdio_function_init(void) -{ - int error = 0; - sd_trace(("bcmsdh_sdmmc: %s Enter\n", __FUNCTION__)); - - gInstance = kzalloc(sizeof(BCMSDH_SDMMC_INSTANCE), GFP_KERNEL); - if (!gInstance) - return -ENOMEM; - - bzero(&sdmmc_dev, sizeof(sdmmc_dev)); - error = sdio_register_driver(&bcmsdh_sdmmc_driver); - - return error; -} - -/* - * module cleanup -*/ -extern int bcmsdh_remove(struct device *dev); -void sdio_function_cleanup(void) -{ - sd_trace(("%s Enter\n", __FUNCTION__)); - - - sdio_unregister_driver(&bcmsdh_sdmmc_driver); - - if (gInstance) - kfree(gInstance); -} diff --git a/drivers/net/wireless/bcm4329/bcmsdspi.c b/drivers/net/wireless/bcm4329/bcmsdspi.c deleted file mode 100644 index 636539be5ea5..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdspi.c +++ /dev/null @@ -1,1596 +0,0 @@ -/* - * Broadcom BCMSDH to SPI Protocol Conversion Layer - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdspi.c,v 1.14.4.2.4.4.6.5 2010/03/10 03:09:48 Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#include /* SDIO Device and Protocol Specs */ -#include /* SDIO Host Controller Specification */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* ioctl/iovars */ - -#include - - -#include -#include - -#include - -#define SD_PAGE 4096 - -/* Globals */ - -uint sd_msglevel = SDH_ERROR_VAL; -uint sd_hiok = FALSE; /* Use hi-speed mode if available? */ -uint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */ -uint sd_f2_blocksize = 512; /* Default blocksize */ - -uint sd_divisor = 2; /* Default 33MHz/2 = 16MHz for dongle */ -uint sd_power = 1; /* Default to SD Slot powered ON */ -uint sd_clock = 1; /* Default to SD Clock turned ON */ -uint sd_crc = 0; /* Default to SPI CRC Check turned OFF */ -uint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */ - -uint sd_toctl = 7; - -/* Prototypes */ -static bool sdspi_start_power(sdioh_info_t *sd); -static int sdspi_set_highspeed_mode(sdioh_info_t *sd, bool HSMode); -static int sdspi_card_enablefuncs(sdioh_info_t *sd); -static void sdspi_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count); -static int sdspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd, uint32 arg, - uint32 *data, uint32 datalen); -static int sdspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, - int regsize, uint32 *data); -static int sdspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, - int regsize, uint32 data); -static int sdspi_driver_init(sdioh_info_t *sd); -static bool sdspi_reset(sdioh_info_t *sd, bool host_reset, bool client_reset); -static int sdspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, - uint32 addr, int nbytes, uint32 *data); -static int sdspi_abort(sdioh_info_t *sd, uint func); - -static int set_client_block_size(sdioh_info_t *sd, int func, int blocksize); - -static uint8 sdspi_crc7(unsigned char* p, uint32 len); -static uint16 sdspi_crc16(unsigned char* p, uint32 len); -static int sdspi_crc_onoff(sdioh_info_t *sd, bool use_crc); - -/* - * Public entry points & extern's - */ -extern sdioh_info_t * -sdioh_attach(osl_t *osh, void *bar0, uint irq) -{ - sdioh_info_t *sd; - - sd_trace(("%s\n", __FUNCTION__)); - if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) { - sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh))); - return NULL; - } - bzero((char *)sd, sizeof(sdioh_info_t)); - sd->osh = osh; - - if (spi_osinit(sd) != 0) { - sd_err(("%s: spi_osinit() failed\n", __FUNCTION__)); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return NULL; - } - - sd->bar0 = (uintptr)bar0; - sd->irq = irq; - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; - sd->intr_handler_valid = FALSE; - - /* Set defaults */ - sd->sd_blockmode = FALSE; - sd->use_client_ints = TRUE; - sd->sd_use_dma = FALSE; /* DMA Not supported */ - - /* Haven't figured out how to make bytemode work with dma */ - if (!sd->sd_blockmode) - sd->sd_use_dma = 0; - - if (!spi_hw_attach(sd)) { - sd_err(("%s: spi_hw_attach() failed\n", __FUNCTION__)); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return NULL; - } - - if (sdspi_driver_init(sd) != SUCCESS) { - if (sdspi_driver_init(sd) != SUCCESS) { - sd_err(("%s:sdspi_driver_init() failed()\n", __FUNCTION__)); - spi_hw_detach(sd); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - } - - if (spi_register_irq(sd, irq) != SUCCESS) { - sd_err(("%s: spi_register_irq() failed for irq = %d\n", __FUNCTION__, irq)); - spi_hw_detach(sd); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - - sd_trace(("%s: Done\n", __FUNCTION__)); - return sd; -} - -extern SDIOH_API_RC -sdioh_detach(osl_t *osh, sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - - if (sd) { - if (sd->card_init_done) - sdspi_reset(sd, 1, 1); - - sd_info(("%s: detaching from hardware\n", __FUNCTION__)); - spi_free_irq(sd->irq, sd); - spi_hw_detach(sd); - spi_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - } - - return SDIOH_API_RC_SUCCESS; -} - -/* Configure callback to client when we recieve client interrupt */ -extern SDIOH_API_RC -sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - - sd->intr_handler = fn; - sd->intr_handler_arg = argh; - sd->intr_handler_valid = TRUE; - - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_deregister(sdioh_info_t *sd) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - - sd->intr_handler_valid = FALSE; - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; - - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - - *onoff = sd->client_intr_enabled; - - return SDIOH_API_RC_SUCCESS; -} - -#if defined(DHD_DEBUG) -extern bool -sdioh_interrupt_pending(sdioh_info_t *sd) -{ - return 0; -} -#endif - -uint -sdioh_query_iofnum(sdioh_info_t *sd) -{ - return sd->num_funcs; -} - -/* IOVar table */ -enum { - IOV_MSGLEVEL = 1, - IOV_BLOCKMODE, - IOV_BLOCKSIZE, - IOV_DMA, - IOV_USEINTS, - IOV_NUMINTS, - IOV_NUMLOCALINTS, - IOV_HOSTREG, - IOV_DEVREG, - IOV_DIVISOR, - IOV_SDMODE, - IOV_HISPEED, - IOV_HCIREGS, - IOV_POWER, - IOV_CLOCK, - IOV_CRC -}; - -const bcm_iovar_t sdioh_iovars[] = { - {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, - {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 }, - {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ - {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 }, - {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, - {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, - {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, - {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, - {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, - {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, - {"sd_crc", IOV_CRC, 0, IOVT_UINT32, 0 }, - {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}, - {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}, - {NULL, 0, 0, 0, 0 } -}; - -int -sdioh_iovar_op(sdioh_info_t *si, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - const bcm_iovar_t *vi = NULL; - int bcmerror = 0; - int val_size; - int32 int_val = 0; - bool bool_val; - uint32 actionid; - - ASSERT(name); - ASSERT(len >= 0); - - /* Get must have return space; Set does not take qualifiers */ - ASSERT(set || (arg && len)); - ASSERT(!set || (!params && !plen)); - - sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name)); - - if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) { - bcmerror = BCME_UNSUPPORTED; - goto exit; - } - - if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0) - goto exit; - - /* Set up params so get and set can share the convenience variables */ - if (params == NULL) { - params = arg; - plen = len; - } - - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - val_size = sizeof(int); - - if (plen >= (int)sizeof(int_val)) - bcopy(params, &int_val, sizeof(int_val)); - - bool_val = (int_val != 0) ? TRUE : FALSE; - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - switch (actionid) { - case IOV_GVAL(IOV_MSGLEVEL): - int_val = (int32)sd_msglevel; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_MSGLEVEL): - sd_msglevel = int_val; - break; - - case IOV_GVAL(IOV_BLOCKMODE): - int_val = (int32)si->sd_blockmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_BLOCKMODE): - si->sd_blockmode = (bool)int_val; - /* Haven't figured out how to make non-block mode with DMA */ - if (!si->sd_blockmode) - si->sd_use_dma = 0; - break; - - case IOV_GVAL(IOV_BLOCKSIZE): - if ((uint32)int_val > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - int_val = (int32)si->client_block_size[int_val]; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_BLOCKSIZE): - { - uint func = ((uint32)int_val >> 16); - uint blksize = (uint16)int_val; - uint maxsize; - - if (func > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - - switch (func) { - case 0: maxsize = 32; break; - case 1: maxsize = BLOCK_SIZE_4318; break; - case 2: maxsize = BLOCK_SIZE_4328; break; - default: maxsize = 0; - } - if (blksize > maxsize) { - bcmerror = BCME_BADARG; - break; - } - if (!blksize) { - blksize = maxsize; - } - - /* Now set it */ - spi_lock(si); - bcmerror = set_client_block_size(si, func, blksize); - spi_unlock(si); - break; - } - - case IOV_GVAL(IOV_DMA): - int_val = (int32)si->sd_use_dma; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DMA): - si->sd_use_dma = (bool)int_val; - break; - - case IOV_GVAL(IOV_USEINTS): - int_val = (int32)si->use_client_ints; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_USEINTS): - break; - - case IOV_GVAL(IOV_DIVISOR): - int_val = (uint32)sd_divisor; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DIVISOR): - sd_divisor = int_val; - if (!spi_start_clock(si, (uint16)sd_divisor)) { - sd_err(("set clock failed!\n")); - bcmerror = BCME_ERROR; - } - break; - - case IOV_GVAL(IOV_POWER): - int_val = (uint32)sd_power; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_POWER): - sd_power = int_val; - break; - - case IOV_GVAL(IOV_CLOCK): - int_val = (uint32)sd_clock; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_CLOCK): - sd_clock = int_val; - break; - - case IOV_GVAL(IOV_CRC): - int_val = (uint32)sd_crc; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_CRC): - /* Apply new setting, but don't change sd_crc until - * after the CRC-mode is selected in the device. This - * is required because the software must generate a - * correct CRC for the CMD59 in order to be able to - * turn OFF the CRC. - */ - sdspi_crc_onoff(si, int_val ? 1 : 0); - sd_crc = int_val; - break; - - case IOV_GVAL(IOV_SDMODE): - int_val = (uint32)sd_sdmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SDMODE): - sd_sdmode = int_val; - break; - - case IOV_GVAL(IOV_HISPEED): - int_val = (uint32)sd_hiok; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_HISPEED): - sd_hiok = int_val; - - if (!sdspi_set_highspeed_mode(si, (bool)sd_hiok)) { - sd_err(("Failed changing highspeed mode to %d.\n", sd_hiok)); - bcmerror = BCME_ERROR; - return ERROR; - } - break; - - case IOV_GVAL(IOV_NUMINTS): - int_val = (int32)si->intrcount; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_NUMLOCALINTS): - int_val = (int32)si->local_intrcount; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_HOSTREG): - { - break; - } - - case IOV_SVAL(IOV_HOSTREG): - { - sd_err(("IOV_HOSTREG unsupported\n")); - break; - } - - case IOV_GVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data; - - if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - - int_val = (int)data; - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data = (uint8)sd_ptr->value; - - if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - break; - } - - - default: - bcmerror = BCME_UNSUPPORTED; - break; - } -exit: - - return bcmerror; -} - -extern SDIOH_API_RC -sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - SDIOH_API_RC status; - /* No lock needed since sdioh_request_byte does locking */ - status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - /* No lock needed since sdioh_request_byte does locking */ - SDIOH_API_RC status; - status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) -{ - uint32 count; - int offset; - uint32 foo; - uint8 *cis = cisd; - - sd_trace(("%s: Func = %d\n", __FUNCTION__, func)); - - if (!sd->func_cis_ptr[func]) { - bzero(cis, length); - return SDIOH_API_RC_FAIL; - } - - spi_lock(sd); - *cis = 0; - for (count = 0; count < length; count++) { - offset = sd->func_cis_ptr[func] + count; - if (sdspi_card_regread (sd, 0, offset, 1, &foo) < 0) { - sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__)); - spi_unlock(sd); - return SDIOH_API_RC_FAIL; - } - *cis = (uint8)(foo & 0xff); - cis++; - } - spi_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) -{ - int status; - uint32 cmd_arg; - uint32 rsp5; - - spi_lock(sd); - - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, rw == SDIOH_READ ? 0 : 1); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, rw == SDIOH_READ ? 0 : *byte); - - sd_trace(("%s: rw=%d, func=%d, regaddr=0x%08x\n", __FUNCTION__, rw, func, regaddr)); - - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, - SDIOH_CMD_52, cmd_arg, NULL, 0)) != SUCCESS) { - spi_unlock(sd); - return status; - } - - sdspi_cmd_getrsp(sd, &rsp5, 1); - if (rsp5 != 0x00) { - sd_err(("%s: rsp5 flags is 0x%x func=%d\n", - __FUNCTION__, rsp5, func)); - /* ASSERT(0); */ - spi_unlock(sd); - return SDIOH_API_RC_FAIL; - } - - if (rw == SDIOH_READ) - *byte = sd->card_rsp_data >> 24; - - spi_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, - uint32 *word, uint nbytes) -{ - int status; - - spi_lock(sd); - - if (rw == SDIOH_READ) - status = sdspi_card_regread(sd, func, addr, nbytes, word); - else - status = sdspi_card_regwrite(sd, func, addr, nbytes, *word); - - spi_unlock(sd); - return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); -} - -extern SDIOH_API_RC -sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func, - uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) -{ - int len; - int buflen = (int)buflen_u; - bool fifo = (fix_inc == SDIOH_DATA_FIX); - - spi_lock(sd); - - ASSERT(reg_width == 4); - ASSERT(buflen_u < (1 << 30)); - ASSERT(sd->client_block_size[func]); - - sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n", - __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W', - buflen_u, sd->r_cnt, sd->t_cnt, pkt)); - - /* Break buffer down into blocksize chunks: - * Bytemode: 1 block at a time. - */ - while (buflen > 0) { - if (sd->sd_blockmode) { - /* Max xfer is Page size */ - len = MIN(SD_PAGE, buflen); - - /* Round down to a block boundry */ - if (buflen > sd->client_block_size[func]) - len = (len/sd->client_block_size[func]) * - sd->client_block_size[func]; - } else { - /* Byte mode: One block at a time */ - len = MIN(sd->client_block_size[func], buflen); - } - - if (sdspi_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) { - spi_unlock(sd); - return SDIOH_API_RC_FAIL; - } - buffer += len; - buflen -= len; - if (!fifo) - addr += len; - } - spi_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -static int -sdspi_abort(sdioh_info_t *sd, uint func) -{ - uint8 spi_databuf[] = { 0x74, 0x80, 0x00, 0x0C, 0xFF, 0x95, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - uint8 spi_rspbuf[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - int err = 0; - - sd_err(("Sending SPI Abort to F%d\n", func)); - spi_databuf[4] = func & 0x7; - /* write to function 0, addr 6 (IOABORT) func # in 3 LSBs. */ - spi_sendrecv(sd, spi_databuf, spi_rspbuf, sizeof(spi_databuf)); - - return err; -} - -extern int -sdioh_abort(sdioh_info_t *sd, uint fnum) -{ - int ret; - - spi_lock(sd); - ret = sdspi_abort(sd, fnum); - spi_unlock(sd); - - return ret; -} - -int -sdioh_start(sdioh_info_t *sd, int stage) -{ - return SUCCESS; -} - -int -sdioh_stop(sdioh_info_t *sd) -{ - return SUCCESS; -} - - -/* - * Private/Static work routines - */ -static bool -sdspi_reset(sdioh_info_t *sd, bool host_reset, bool client_reset) -{ - if (!sd) - return TRUE; - - spi_lock(sd); - /* Reset client card */ - if (client_reset && (sd->adapter_slot != -1)) { - if (sdspi_card_regwrite(sd, 0, SDIOD_CCCR_IOABORT, 1, 0x8) != SUCCESS) - sd_err(("%s: Cannot write to card reg 0x%x\n", - __FUNCTION__, SDIOD_CCCR_IOABORT)); - else - sd->card_rca = 0; - } - - /* The host reset is a NOP in the sd-spi case. */ - if (host_reset) { - sd->sd_mode = SDIOH_MODE_SPI; - } - spi_unlock(sd); - return TRUE; -} - -static int -sdspi_host_init(sdioh_info_t *sd) -{ - sdspi_reset(sd, 1, 0); - - /* Default power on mode is SD1 */ - sd->sd_mode = SDIOH_MODE_SPI; - sd->polled_mode = TRUE; - sd->host_init_done = TRUE; - sd->card_init_done = FALSE; - sd->adapter_slot = 1; - - return (SUCCESS); -} - -#define CMD0_RETRIES 3 -#define CMD5_RETRIES 10 - -static int -get_ocr(sdioh_info_t *sd, uint32 *cmd_arg, uint32 *cmd_rsp) -{ - uint32 rsp5; - int retries, status; - - /* First issue a CMD0 to get the card into SPI mode. */ - for (retries = 0; retries <= CMD0_RETRIES; retries++) { - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, - SDIOH_CMD_0, *cmd_arg, NULL, 0)) != SUCCESS) { - sd_err(("%s: No response to CMD0\n", __FUNCTION__)); - continue; - } - - sdspi_cmd_getrsp(sd, &rsp5, 1); - - if (GFIELD(rsp5, SPI_RSP_ILL_CMD)) { - printf("%s: Card already initialized (continuing)\n", __FUNCTION__); - break; - } - - if (GFIELD(rsp5, SPI_RSP_IDLE)) { - printf("%s: Card in SPI mode\n", __FUNCTION__); - break; - } - } - - if (retries > CMD0_RETRIES) { - sd_err(("%s: Too many retries for CMD0\n", __FUNCTION__)); - return ERROR; - } - - /* Get the Card's Operation Condition. */ - /* Occasionally the board takes a while to become ready. */ - for (retries = 0; retries <= CMD5_RETRIES; retries++) { - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, - SDIOH_CMD_5, *cmd_arg, NULL, 0)) != SUCCESS) { - sd_err(("%s: No response to CMD5\n", __FUNCTION__)); - continue; - } - - printf("CMD5 response data was: 0x%08x\n", sd->card_rsp_data); - - if (GFIELD(sd->card_rsp_data, RSP4_CARD_READY)) { - printf("%s: Card ready\n", __FUNCTION__); - break; - } - } - - if (retries > CMD5_RETRIES) { - sd_err(("%s: Too many retries for CMD5\n", __FUNCTION__)); - return ERROR; - } - - *cmd_rsp = sd->card_rsp_data; - - sdspi_crc_onoff(sd, sd_crc ? 1 : 0); - - return (SUCCESS); -} - -static int -sdspi_crc_onoff(sdioh_info_t *sd, bool use_crc) -{ - uint32 args; - int status; - - args = use_crc ? 1 : 0; - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, - SDIOH_CMD_59, args, NULL, 0)) != SUCCESS) { - sd_err(("%s: No response to CMD59\n", __FUNCTION__)); - } - - sd_info(("CMD59 response data was: 0x%08x\n", sd->card_rsp_data)); - - sd_err(("SD-SPI CRC turned %s\n", use_crc ? "ON" : "OFF")); - return (SUCCESS); -} - -static int -sdspi_client_init(sdioh_info_t *sd) -{ - uint8 fn_ints; - - sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot)); - - /* Start at ~400KHz clock rate for initialization */ - if (!spi_start_clock(sd, 128)) { - sd_err(("spi_start_clock failed\n")); - return ERROR; - } - - if (!sdspi_start_power(sd)) { - sd_err(("sdspi_start_power failed\n")); - return ERROR; - } - - if (sd->num_funcs == 0) { - sd_err(("%s: No IO funcs!\n", __FUNCTION__)); - return ERROR; - } - - sdspi_card_enablefuncs(sd); - - set_client_block_size(sd, 1, BLOCK_SIZE_4318); - fn_ints = INTR_CTL_FUNC1_EN; - - if (sd->num_funcs >= 2) { - set_client_block_size(sd, 2, sd_f2_blocksize /* BLOCK_SIZE_4328 */); - fn_ints |= INTR_CTL_FUNC2_EN; - } - - /* Enable/Disable Client interrupts */ - /* Turn on here but disable at host controller */ - if (sdspi_card_regwrite(sd, 0, SDIOD_CCCR_INTEN, 1, - (fn_ints | INTR_CTL_MASTER_EN)) != SUCCESS) { - sd_err(("%s: Could not enable ints in CCCR\n", __FUNCTION__)); - return ERROR; - } - - /* Switch to High-speed clocking mode if both host and device support it */ - sdspi_set_highspeed_mode(sd, (bool)sd_hiok); - - /* After configuring for High-Speed mode, set the desired clock rate. */ - if (!spi_start_clock(sd, (uint16)sd_divisor)) { - sd_err(("spi_start_clock failed\n")); - return ERROR; - } - - sd->card_init_done = TRUE; - - return SUCCESS; -} - -static int -sdspi_set_highspeed_mode(sdioh_info_t *sd, bool HSMode) -{ - uint32 regdata; - int status; - bool hsmode; - - if (HSMode == TRUE) { - - sd_err(("Attempting to enable High-Speed mode.\n")); - - if ((status = sdspi_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, ®data)) != SUCCESS) { - return status; - } - if (regdata & SDIO_SPEED_SHS) { - sd_err(("Device supports High-Speed mode.\n")); - - regdata |= SDIO_SPEED_EHS; - - sd_err(("Writing %08x to Card at %08x\n", - regdata, SDIOD_CCCR_SPEED_CONTROL)); - if ((status = sdspi_card_regwrite(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, regdata)) != BCME_OK) { - return status; - } - - hsmode = 1; - - sd_err(("High-speed clocking mode enabled.\n")); - } - else { - sd_err(("Device does not support High-Speed Mode.\n")); - hsmode = 0; - } - } else { - if ((status = sdspi_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, ®data)) != SUCCESS) { - return status; - } - - regdata = ~SDIO_SPEED_EHS; - - sd_err(("Writing %08x to Card at %08x\n", - regdata, SDIOD_CCCR_SPEED_CONTROL)); - if ((status = sdspi_card_regwrite(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, regdata)) != BCME_OK) { - return status; - } - - sd_err(("Low-speed clocking mode enabled.\n")); - hsmode = 0; - } - - spi_controller_highspeed_mode(sd, hsmode); - - return TRUE; -} - -bool -sdspi_start_power(sdioh_info_t *sd) -{ - uint32 cmd_arg; - uint32 cmd_rsp; - - sd_trace(("%s\n", __FUNCTION__)); - - /* Get the Card's Operation Condition. Occasionally the board - * takes a while to become ready - */ - - cmd_arg = 0; - if (get_ocr(sd, &cmd_arg, &cmd_rsp) != SUCCESS) { - sd_err(("%s: Failed to get OCR; bailing\n", __FUNCTION__)); - return FALSE; - } - - sd_err(("mem_present = %d\n", GFIELD(cmd_rsp, RSP4_MEM_PRESENT))); - sd_err(("num_funcs = %d\n", GFIELD(cmd_rsp, RSP4_NUM_FUNCS))); - sd_err(("card_ready = %d\n", GFIELD(cmd_rsp, RSP4_CARD_READY))); - sd_err(("OCR = 0x%x\n", GFIELD(cmd_rsp, RSP4_IO_OCR))); - - /* Verify that the card supports I/O mode */ - if (GFIELD(cmd_rsp, RSP4_NUM_FUNCS) == 0) { - sd_err(("%s: Card does not support I/O\n", __FUNCTION__)); - return ERROR; - } - - sd->num_funcs = GFIELD(cmd_rsp, RSP4_NUM_FUNCS); - - /* Examine voltage: Arasan only supports 3.3 volts, - * so look for 3.2-3.3 Volts and also 3.3-3.4 volts. - */ - - if ((GFIELD(cmd_rsp, RSP4_IO_OCR) & (0x3 << 20)) == 0) { - sd_err(("This client does not support 3.3 volts!\n")); - return ERROR; - } - - - return TRUE; -} - -static int -sdspi_driver_init(sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - - if ((sdspi_host_init(sd)) != SUCCESS) { - return ERROR; - } - - if (sdspi_client_init(sd) != SUCCESS) { - return ERROR; - } - - return SUCCESS; -} - -static int -sdspi_card_enablefuncs(sdioh_info_t *sd) -{ - int status; - uint32 regdata; - uint32 regaddr, fbraddr; - uint8 func; - uint8 *ptr; - - sd_trace(("%s\n", __FUNCTION__)); - /* Get the Card's common CIS address */ - ptr = (uint8 *) &sd->com_cis_ptr; - for (regaddr = SDIOD_CCCR_CISPTR_0; regaddr <= SDIOD_CCCR_CISPTR_2; regaddr++) { - if ((status = sdspi_card_regread (sd, 0, regaddr, 1, ®data)) != SUCCESS) - return status; - - *ptr++ = (uint8) regdata; - } - - /* Only the lower 17-bits are valid */ - sd->com_cis_ptr &= 0x0001FFFF; - sd->func_cis_ptr[0] = sd->com_cis_ptr; - sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); - - /* Get the Card's function CIS (for each function) */ - for (fbraddr = SDIOD_FBR_STARTADDR, func = 1; - func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { - ptr = (uint8 *) &sd->func_cis_ptr[func]; - for (regaddr = SDIOD_FBR_CISPTR_0; regaddr <= SDIOD_FBR_CISPTR_2; regaddr++) { - if ((status = sdspi_card_regread (sd, 0, regaddr + fbraddr, 1, ®data)) - != SUCCESS) - return status; - - *ptr++ = (uint8) regdata; - } - - /* Only the lower 17-bits are valid */ - sd->func_cis_ptr[func] &= 0x0001FFFF; - sd_info(("%s: Function %d CIS Ptr = 0x%x\n", - __FUNCTION__, func, sd->func_cis_ptr[func])); - } - - sd_info(("%s: write ESCI bit\n", __FUNCTION__)); - /* Enable continuous SPI interrupt (ESCI bit) */ - sdspi_card_regwrite(sd, 0, SDIOD_CCCR_BICTRL, 1, 0x60); - - sd_info(("%s: enable f1\n", __FUNCTION__)); - /* Enable function 1 on the card */ - regdata = SDIO_FUNC_ENABLE_1; - if ((status = sdspi_card_regwrite(sd, 0, SDIOD_CCCR_IOEN, 1, regdata)) != SUCCESS) - return status; - - sd_info(("%s: done\n", __FUNCTION__)); - return SUCCESS; -} - -/* Read client card reg */ -static int -sdspi_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) -{ - int status; - uint32 cmd_arg; - uint32 rsp5; - - cmd_arg = 0; - - if ((func == 0) || (regsize == 1)) { - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_READ); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, 0); - - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg, NULL, 0)) - != SUCCESS) - return status; - - sdspi_cmd_getrsp(sd, &rsp5, 1); - - if (rsp5 != 0x00) - sd_err(("%s: rsp5 flags is 0x%x\t %d\n", - __FUNCTION__, rsp5, func)); - - *data = sd->card_rsp_data >> 24; - } else { - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, regsize); - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); - cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_READ); - - sd->data_xfer_count = regsize; - - /* sdspi_cmd_issue() returns with the command complete bit - * in the ISR already cleared - */ - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_53, cmd_arg, NULL, 0)) - != SUCCESS) - return status; - - sdspi_cmd_getrsp(sd, &rsp5, 1); - - if (rsp5 != 0x00) - sd_err(("%s: rsp5 flags is 0x%x\t %d\n", - __FUNCTION__, rsp5, func)); - - *data = sd->card_rsp_data; - if (regsize == 2) { - *data &= 0xffff; - } - - sd_info(("%s: CMD53 func %d, addr 0x%x, size %d, data 0x%08x\n", - __FUNCTION__, func, regaddr, regsize, *data)); - - - } - - return SUCCESS; -} - -/* write a client register */ -static int -sdspi_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data) -{ - int status; - uint32 cmd_arg, rsp5, flags; - - cmd_arg = 0; - - if ((func == 0) || (regsize == 1)) { - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_WRITE); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, data & 0xff); - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_52, cmd_arg, NULL, 0)) - != SUCCESS) - return status; - - sdspi_cmd_getrsp(sd, &rsp5, 1); - flags = GFIELD(rsp5, RSP5_FLAGS); - if (flags && (flags != 0x10)) - sd_err(("%s: rsp5.rsp5.flags = 0x%x, expecting 0x10\n", - __FUNCTION__, flags)); - } - else { - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, regsize); - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); - cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_WRITE); - - sd->data_xfer_count = regsize; - sd->cmd53_wr_data = data; - - sd_info(("%s: CMD53 func %d, addr 0x%x, size %d, data 0x%08x\n", - __FUNCTION__, func, regaddr, regsize, data)); - - /* sdspi_cmd_issue() returns with the command complete bit - * in the ISR already cleared - */ - if ((status = sdspi_cmd_issue(sd, sd->sd_use_dma, SDIOH_CMD_53, cmd_arg, NULL, 0)) - != SUCCESS) - return status; - - sdspi_cmd_getrsp(sd, &rsp5, 1); - - if (rsp5 != 0x00) - sd_err(("%s: rsp5 flags = 0x%x, expecting 0x00\n", - __FUNCTION__, rsp5)); - - } - return SUCCESS; -} - -void -sdspi_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count /* num 32 bit words */) -{ - *rsp_buffer = sd->card_response; -} - -int max_errors = 0; - -#define SPI_MAX_PKT_LEN 768 -uint8 spi_databuf[SPI_MAX_PKT_LEN]; -uint8 spi_rspbuf[SPI_MAX_PKT_LEN]; - -/* datalen is used for CMD53 length only (0 for sd->data_xfer_count) */ -static int -sdspi_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd, uint32 arg, - uint32 *data, uint32 datalen) -{ - uint32 cmd_reg; - uint32 cmd_arg = arg; - uint8 cmd_crc = 0x95; /* correct CRC for CMD0 and don't care for others. */ - uint16 dat_crc; - uint8 cmd52data = 0; - uint32 i, j; - uint32 spi_datalen = 0; - uint32 spi_pre_cmd_pad = 0; - uint32 spi_max_response_pad = 128; - - cmd_reg = 0; - cmd_reg = SFIELD(cmd_reg, SPI_DIR, 1); - cmd_reg = SFIELD(cmd_reg, SPI_CMD_INDEX, cmd); - - if (GFIELD(cmd_arg, CMD52_RW_FLAG) == 1) { /* Same for CMD52 and CMD53 */ - cmd_reg = SFIELD(cmd_reg, SPI_RW, 1); - } - - switch (cmd) { - case SDIOH_CMD_59: /* CRC_ON_OFF (SPI Mode Only) - Response R1 */ - cmd52data = arg & 0x1; - case SDIOH_CMD_0: /* Set Card to Idle State - No Response */ - case SDIOH_CMD_5: /* Send Operation condition - Response R4 */ - sd_trace(("%s: CMD%d\n", __FUNCTION__, cmd)); - spi_datalen = 44; - spi_pre_cmd_pad = 12; - spi_max_response_pad = 28; - break; - - case SDIOH_CMD_3: /* Ask card to send RCA - Response R6 */ - case SDIOH_CMD_7: /* Select card - Response R1 */ - case SDIOH_CMD_15: /* Set card to inactive state - Response None */ - sd_err(("%s: CMD%d is invalid for SPI Mode.\n", __FUNCTION__, cmd)); - return ERROR; - break; - - case SDIOH_CMD_52: /* IO R/W Direct (single byte) - Response R5 */ - cmd52data = GFIELD(cmd_arg, CMD52_DATA); - cmd_arg = arg; - cmd_reg = SFIELD(cmd_reg, SPI_FUNC, GFIELD(cmd_arg, CMD52_FUNCTION)); - cmd_reg = SFIELD(cmd_reg, SPI_ADDR, GFIELD(cmd_arg, CMD52_REG_ADDR)); - /* Display trace for byte write */ - if (GFIELD(cmd_arg, CMD52_RW_FLAG) == 1) { - sd_trace(("%s: CMD52: Wr F:%d @0x%04x=%02x\n", - __FUNCTION__, - GFIELD(cmd_arg, CMD52_FUNCTION), - GFIELD(cmd_arg, CMD52_REG_ADDR), - cmd52data)); - } - - spi_datalen = 32; - spi_max_response_pad = 28; - - break; - case SDIOH_CMD_53: /* IO R/W Extended (multiple bytes/blocks) */ - cmd_arg = arg; - cmd_reg = SFIELD(cmd_reg, SPI_FUNC, GFIELD(cmd_arg, CMD53_FUNCTION)); - cmd_reg = SFIELD(cmd_reg, SPI_ADDR, GFIELD(cmd_arg, CMD53_REG_ADDR)); - cmd_reg = SFIELD(cmd_reg, SPI_BLKMODE, 0); - cmd_reg = SFIELD(cmd_reg, SPI_OPCODE, GFIELD(cmd_arg, CMD53_OP_CODE)); - cmd_reg = SFIELD(cmd_reg, SPI_STUFF0, (sd->data_xfer_count>>8)); - cmd52data = (uint8)sd->data_xfer_count; - - /* Set upper bit in byte count if necessary, but don't set it for 512 bytes. */ - if ((sd->data_xfer_count > 255) && (sd->data_xfer_count < 512)) { - cmd_reg |= 1; - } - - if (GFIELD(cmd_reg, SPI_RW) == 1) { /* Write */ - spi_max_response_pad = 32; - spi_datalen = (sd->data_xfer_count + spi_max_response_pad) & 0xFFFC; - } else { /* Read */ - - spi_max_response_pad = 32; - spi_datalen = (sd->data_xfer_count + spi_max_response_pad) & 0xFFFC; - } - sd_trace(("%s: CMD53: %s F:%d @0x%04x len=0x%02x\n", - __FUNCTION__, - (GFIELD(cmd_reg, SPI_RW) == 1 ? "Wr" : "Rd"), - GFIELD(cmd_arg, CMD53_FUNCTION), - GFIELD(cmd_arg, CMD53_REG_ADDR), - cmd52data)); - break; - - default: - sd_err(("%s: Unknown command %d\n", __FUNCTION__, cmd)); - return ERROR; - } - - /* Set up and issue the SDIO command */ - memset(spi_databuf, SDSPI_IDLE_PAD, spi_datalen); - spi_databuf[spi_pre_cmd_pad + 0] = (cmd_reg & 0xFF000000) >> 24; - spi_databuf[spi_pre_cmd_pad + 1] = (cmd_reg & 0x00FF0000) >> 16; - spi_databuf[spi_pre_cmd_pad + 2] = (cmd_reg & 0x0000FF00) >> 8; - spi_databuf[spi_pre_cmd_pad + 3] = (cmd_reg & 0x000000FF); - spi_databuf[spi_pre_cmd_pad + 4] = cmd52data; - - /* Generate CRC7 for command, if CRC is enabled, otherwise, a - * default CRC7 of 0x95, which is correct for CMD0, is used. - */ - if (sd_crc) { - cmd_crc = sdspi_crc7(&spi_databuf[spi_pre_cmd_pad], 5); - } - spi_databuf[spi_pre_cmd_pad + 5] = cmd_crc; -#define SPI_STOP_TRAN 0xFD - - /* for CMD53 Write, put the data into the output buffer */ - if ((cmd == SDIOH_CMD_53) && (GFIELD(cmd_arg, CMD53_RW_FLAG) == 1)) { - if (datalen != 0) { - spi_databuf[spi_pre_cmd_pad + 9] = SDSPI_IDLE_PAD; - spi_databuf[spi_pre_cmd_pad + 10] = SDSPI_START_BLOCK; - - for (i = 0; i < sd->data_xfer_count; i++) { - spi_databuf[i + 11 + spi_pre_cmd_pad] = ((uint8 *)data)[i]; - } - if (sd_crc) { - dat_crc = sdspi_crc16(&spi_databuf[spi_pre_cmd_pad+11], i); - } else { - dat_crc = 0xAAAA; - } - spi_databuf[i + 11 + spi_pre_cmd_pad] = (dat_crc >> 8) & 0xFF; - spi_databuf[i + 12 + spi_pre_cmd_pad] = dat_crc & 0xFF; - } else if (sd->data_xfer_count == 2) { - spi_databuf[spi_pre_cmd_pad + 9] = SDSPI_IDLE_PAD; - spi_databuf[spi_pre_cmd_pad + 10] = SDSPI_START_BLOCK; - spi_databuf[spi_pre_cmd_pad + 11] = sd->cmd53_wr_data & 0xFF; - spi_databuf[spi_pre_cmd_pad + 12] = (sd->cmd53_wr_data & 0x0000FF00) >> 8; - if (sd_crc) { - dat_crc = sdspi_crc16(&spi_databuf[spi_pre_cmd_pad+11], 2); - } else { - dat_crc = 0x22AA; - } - spi_databuf[spi_pre_cmd_pad + 13] = (dat_crc >> 8) & 0xFF; - spi_databuf[spi_pre_cmd_pad + 14] = (dat_crc & 0xFF); - } else if (sd->data_xfer_count == 4) { - spi_databuf[spi_pre_cmd_pad + 9] = SDSPI_IDLE_PAD; - spi_databuf[spi_pre_cmd_pad + 10] = SDSPI_START_BLOCK; - spi_databuf[spi_pre_cmd_pad + 11] = sd->cmd53_wr_data & 0xFF; - spi_databuf[spi_pre_cmd_pad + 12] = (sd->cmd53_wr_data & 0x0000FF00) >> 8; - spi_databuf[spi_pre_cmd_pad + 13] = (sd->cmd53_wr_data & 0x00FF0000) >> 16; - spi_databuf[spi_pre_cmd_pad + 14] = (sd->cmd53_wr_data & 0xFF000000) >> 24; - if (sd_crc) { - dat_crc = sdspi_crc16(&spi_databuf[spi_pre_cmd_pad+11], 4); - } else { - dat_crc = 0x44AA; - } - spi_databuf[spi_pre_cmd_pad + 15] = (dat_crc >> 8) & 0xFF; - spi_databuf[spi_pre_cmd_pad + 16] = (dat_crc & 0xFF); - } else { - printf("CMD53 Write: size %d unsupported\n", sd->data_xfer_count); - } - } - - spi_sendrecv(sd, spi_databuf, spi_rspbuf, spi_datalen); - - for (i = spi_pre_cmd_pad + SDSPI_COMMAND_LEN; i < spi_max_response_pad; i++) { - if ((spi_rspbuf[i] & SDSPI_START_BIT_MASK) == 0) { - break; - } - } - - if (i == spi_max_response_pad) { - sd_err(("%s: Did not get a response for CMD%d\n", __FUNCTION__, cmd)); - return ERROR; - } - - /* Extract the response. */ - sd->card_response = spi_rspbuf[i]; - - /* for CMD53 Read, find the start of the response data... */ - if ((cmd == SDIOH_CMD_53) && (GFIELD(cmd_arg, CMD52_RW_FLAG) == 0)) { - for (; i < spi_max_response_pad; i++) { - if (spi_rspbuf[i] == SDSPI_START_BLOCK) { - break; - } - } - - if (i == spi_max_response_pad) { - printf("Did not get a start of data phase for CMD%d\n", cmd); - max_errors++; - sdspi_abort(sd, GFIELD(cmd_arg, CMD53_FUNCTION)); - } - sd->card_rsp_data = spi_rspbuf[i+1]; - sd->card_rsp_data |= spi_rspbuf[i+2] << 8; - sd->card_rsp_data |= spi_rspbuf[i+3] << 16; - sd->card_rsp_data |= spi_rspbuf[i+4] << 24; - - if (datalen != 0) { - i++; - for (j = 0; j < sd->data_xfer_count; j++) { - ((uint8 *)data)[j] = spi_rspbuf[i+j]; - } - if (sd_crc) { - uint16 recv_crc; - - recv_crc = spi_rspbuf[i+j] << 8 | spi_rspbuf[i+j+1]; - dat_crc = sdspi_crc16((uint8 *)data, datalen); - if (dat_crc != recv_crc) { - sd_err(("%s: Incorrect data CRC: expected 0x%04x, " - "received 0x%04x\n", - __FUNCTION__, dat_crc, recv_crc)); - } - } - } - return SUCCESS; - } - - sd->card_rsp_data = spi_rspbuf[i+4]; - sd->card_rsp_data |= spi_rspbuf[i+3] << 8; - sd->card_rsp_data |= spi_rspbuf[i+2] << 16; - sd->card_rsp_data |= spi_rspbuf[i+1] << 24; - - /* Display trace for byte read */ - if ((cmd == SDIOH_CMD_52) && (GFIELD(cmd_arg, CMD52_RW_FLAG) == 0)) { - sd_trace(("%s: CMD52: Rd F:%d @0x%04x=%02x\n", - __FUNCTION__, - GFIELD(cmd_arg, CMD53_FUNCTION), - GFIELD(cmd_arg, CMD53_REG_ADDR), - sd->card_rsp_data >> 24)); - } - - return SUCCESS; -} - -/* - * On entry: if single-block or non-block, buffer size <= block size. - * If multi-block, buffer size is unlimited. - * Question is how to handle the left-overs in either single- or multi-block. - * I think the caller should break the buffer up so this routine will always - * use block size == buffer size to handle the end piece of the buffer - */ - -static int -sdspi_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int nbytes, uint32 *data) -{ - int status; - uint32 cmd_arg; - uint32 rsp5; - int num_blocks, blocksize; - bool local_blockmode, local_dma; - bool read = rw == SDIOH_READ ? 1 : 0; - - ASSERT(nbytes); - - cmd_arg = 0; - sd_data(("%s: %s 53 func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", - __FUNCTION__, read ? "Rd" : "Wr", func, fifo ? "FIXED" : "INCR", - addr, nbytes, sd->r_cnt, sd->t_cnt)); - - if (read) sd->r_cnt++; else sd->t_cnt++; - - local_blockmode = sd->sd_blockmode; - local_dma = sd->sd_use_dma; - - /* Don't bother with block mode on small xfers */ - if (nbytes < sd->client_block_size[func]) { - sd_info(("setting local blockmode to false: nbytes (%d) != block_size (%d)\n", - nbytes, sd->client_block_size[func])); - local_blockmode = FALSE; - local_dma = FALSE; - } - - if (local_blockmode) { - blocksize = MIN(sd->client_block_size[func], nbytes); - num_blocks = nbytes/blocksize; - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, num_blocks); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 1); - } else { - num_blocks = 1; - blocksize = nbytes; - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, nbytes); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); - } - - if (fifo) - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 0); - else - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); - - cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, addr); - if (read) - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_READ); - else - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_WRITE); - - sd->data_xfer_count = nbytes; - if ((func == 2) && (fifo == 1)) { - sd_data(("%s: %s 53 func %d, %s, addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", - __FUNCTION__, read ? "Rd" : "Wr", func, fifo ? "FIXED" : "INCR", - addr, nbytes, sd->r_cnt, sd->t_cnt)); - } - - /* sdspi_cmd_issue() returns with the command complete bit - * in the ISR already cleared - */ - if ((status = sdspi_cmd_issue(sd, local_dma, - SDIOH_CMD_53, cmd_arg, - data, nbytes)) != SUCCESS) { - sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__, (read ? "read" : "write"))); - return status; - } - - sdspi_cmd_getrsp(sd, &rsp5, 1); - - if (rsp5 != 0x00) { - sd_err(("%s: rsp5 flags = 0x%x, expecting 0x00\n", - __FUNCTION__, rsp5)); - return ERROR; - } - - return SUCCESS; -} - -static int -set_client_block_size(sdioh_info_t *sd, int func, int block_size) -{ - int base; - int err = 0; - - sd_err(("%s: Setting block size %d, func %d\n", __FUNCTION__, block_size, func)); - sd->client_block_size[func] = block_size; - - /* Set the block size in the SDIO Card register */ - base = func * SDIOD_FBR_SIZE; - err = sdspi_card_regwrite(sd, 0, base + SDIOD_CCCR_BLKSIZE_0, 1, block_size & 0xff); - if (!err) { - err = sdspi_card_regwrite(sd, 0, base + SDIOD_CCCR_BLKSIZE_1, 1, - (block_size >> 8) & 0xff); - } - - /* - * Do not set the block size in the SDIO Host register; that - * is func dependent and will get done on an individual - * transaction basis. - */ - - return (err ? BCME_SDIO_ERROR : 0); -} - -/* Reset and re-initialize the device */ -int -sdioh_sdio_reset(sdioh_info_t *si) -{ - si->card_init_done = FALSE; - return sdspi_client_init(si); -} - -#define CRC7_POLYNOM 0x09 -#define CRC7_CRCHIGHBIT 0x40 - -static uint8 sdspi_crc7(unsigned char* p, uint32 len) -{ - uint8 c, j, bit, crc = 0; - uint32 i; - - for (i = 0; i < len; i++) { - c = *p++; - for (j = 0x80; j; j >>= 1) { - bit = crc & CRC7_CRCHIGHBIT; - crc <<= 1; - if (c & j) bit ^= CRC7_CRCHIGHBIT; - if (bit) crc ^= CRC7_POLYNOM; - } - } - - /* Convert the CRC7 to an 8-bit SD CRC */ - crc = (crc << 1) | 1; - - return (crc); -} - -#define CRC16_POLYNOM 0x1021 -#define CRC16_CRCHIGHBIT 0x8000 - -static uint16 sdspi_crc16(unsigned char* p, uint32 len) -{ - uint32 i; - uint16 j, c, bit; - uint16 crc = 0; - - for (i = 0; i < len; i++) { - c = *p++; - for (j = 0x80; j; j >>= 1) { - bit = crc & CRC16_CRCHIGHBIT; - crc <<= 1; - if (c & j) bit ^= CRC16_CRCHIGHBIT; - if (bit) crc ^= CRC16_POLYNOM; - } - } - - return (crc); -} diff --git a/drivers/net/wireless/bcm4329/bcmsdspi_linux.c b/drivers/net/wireless/bcm4329/bcmsdspi_linux.c deleted file mode 100644 index e2e0ca6abe46..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdspi_linux.c +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Broadcom SPI Host Controller Driver - Linux Per-port - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdspi_linux.c,v 1.7.2.1.4.3 2008/06/30 21:09:36 Exp $ - */ - -#include -#include -#include - -#include /* SDIO Specs */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* to get msglevel bit values */ - -#include /* request_irq(), free_irq() */ - -#include -#include - -extern uint sd_crc; -module_param(sd_crc, uint, 0); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define KERNEL26 -#endif - -struct sdos_info { - sdioh_info_t *sd; - spinlock_t lock; - wait_queue_head_t intr_wait_queue; -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define BLOCKABLE() (!in_atomic()) -#else -#define BLOCKABLE() (!in_interrupt()) -#endif - -/* Interrupt handler */ -static irqreturn_t -sdspi_isr(int irq, void *dev_id -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -, struct pt_regs *ptregs -#endif -) -{ - sdioh_info_t *sd; - struct sdos_info *sdos; - bool ours; - - sd = (sdioh_info_t *)dev_id; - sd->local_intrcount++; - - if (!sd->card_init_done) { - sd_err(("%s: Hey Bogus intr...not even initted: irq %d\n", __FUNCTION__, irq)); - return IRQ_RETVAL(FALSE); - } else { - ours = spi_check_client_intr(sd, NULL); - - /* For local interrupts, wake the waiting process */ - if (ours && sd->got_hcint) { - sdos = (struct sdos_info *)sd->sdos_info; - wake_up_interruptible(&sdos->intr_wait_queue); - } - - return IRQ_RETVAL(ours); - } -} - -/* Register with Linux for interrupts */ -int -spi_register_irq(sdioh_info_t *sd, uint irq) -{ - sd_trace(("Entering %s: irq == %d\n", __FUNCTION__, irq)); - if (request_irq(irq, sdspi_isr, IRQF_SHARED, "bcmsdspi", sd) < 0) { - sd_err(("%s: request_irq() failed\n", __FUNCTION__)); - return ERROR; - } - return SUCCESS; -} - -/* Free Linux irq */ -void -spi_free_irq(uint irq, sdioh_info_t *sd) -{ - free_irq(irq, sd); -} - -/* Map Host controller registers */ - -uint32 * -spi_reg_map(osl_t *osh, uintptr addr, int size) -{ - return (uint32 *)REG_MAP(addr, size); -} - -void -spi_reg_unmap(osl_t *osh, uintptr addr, int size) -{ - REG_UNMAP((void*)(uintptr)addr); -} - -int -spi_osinit(sdioh_info_t *sd) -{ - struct sdos_info *sdos; - - sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info)); - sd->sdos_info = (void*)sdos; - if (sdos == NULL) - return BCME_NOMEM; - - sdos->sd = sd; - spin_lock_init(&sdos->lock); - init_waitqueue_head(&sdos->intr_wait_queue); - return BCME_OK; -} - -void -spi_osfree(sdioh_info_t *sd) -{ - struct sdos_info *sdos; - ASSERT(sd && sd->sdos_info); - - sdos = (struct sdos_info *)sd->sdos_info; - MFREE(sd->osh, sdos, sizeof(struct sdos_info)); -} - -/* Interrupt enable/disable */ -SDIOH_API_RC -sdioh_interrupt_set(sdioh_info_t *sd, bool enable) -{ - ulong flags; - struct sdos_info *sdos; - - sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling")); - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - - if (!(sd->host_init_done && sd->card_init_done)) { - sd_err(("%s: Card & Host are not initted - bailing\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } - - if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { - sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } - - /* Ensure atomicity for enable/disable calls */ - spin_lock_irqsave(&sdos->lock, flags); - - sd->client_intr_enabled = enable; - if (enable && !sd->lockcount) - spi_devintr_on(sd); - else - spi_devintr_off(sd); - - spin_unlock_irqrestore(&sdos->lock, flags); - - return SDIOH_API_RC_SUCCESS; -} - -/* Protect against reentrancy (disable device interrupts while executing) */ -void -spi_lock(sdioh_info_t *sd) -{ - ulong flags; - struct sdos_info *sdos; - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - - sd_trace(("%s: %d\n", __FUNCTION__, sd->lockcount)); - - spin_lock_irqsave(&sdos->lock, flags); - if (sd->lockcount) { - sd_err(("%s: Already locked!\n", __FUNCTION__)); - ASSERT(sd->lockcount == 0); - } - spi_devintr_off(sd); - sd->lockcount++; - spin_unlock_irqrestore(&sdos->lock, flags); -} - -/* Enable client interrupt */ -void -spi_unlock(sdioh_info_t *sd) -{ - ulong flags; - struct sdos_info *sdos; - - sd_trace(("%s: %d, %d\n", __FUNCTION__, sd->lockcount, sd->client_intr_enabled)); - ASSERT(sd->lockcount > 0); - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - - spin_lock_irqsave(&sdos->lock, flags); - if (--sd->lockcount == 0 && sd->client_intr_enabled) { - spi_devintr_on(sd); - } - spin_unlock_irqrestore(&sdos->lock, flags); -} - -void spi_waitbits(sdioh_info_t *sd, bool yield) -{ - struct sdos_info *sdos; - - sdos = (struct sdos_info *)sd->sdos_info; - -#ifndef BCMSDYIELD - ASSERT(!yield); -#endif - sd_trace(("%s: yield %d canblock %d\n", - __FUNCTION__, yield, BLOCKABLE())); - - /* Clear the "interrupt happened" flag and last intrstatus */ - sd->got_hcint = FALSE; - -#ifdef BCMSDYIELD - if (yield && BLOCKABLE()) { - /* Wait for the indication, the interrupt will be masked when the ISR fires. */ - wait_event_interruptible(sdos->intr_wait_queue, (sd->got_hcint)); - } else -#endif /* BCMSDYIELD */ - { - spi_spinbits(sd); - } - -} diff --git a/drivers/net/wireless/bcm4329/bcmsdstd.c b/drivers/net/wireless/bcm4329/bcmsdstd.c deleted file mode 100644 index 0b1b575d9629..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdstd.c +++ /dev/null @@ -1,3130 +0,0 @@ -/* - * 'Standard' SDIO HOST CONTROLLER driver - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdstd.c,v 1.64.4.1.4.4.2.17 2010/03/10 03:09:48 Exp $ - */ - -#include - -#include -#include -#include -#include -#include -#include /* SDIO Device and Protocol Specs */ -#include /* SDIO Host Controller Specification */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* ioctl/iovars */ -#include - - -#define SD_PAGE_BITS 12 -#define SD_PAGE (1 << SD_PAGE_BITS) - -#include - -/* Globals */ -uint sd_msglevel = SDH_ERROR_VAL; -uint sd_hiok = TRUE; /* Use hi-speed mode if available? */ -uint sd_sdmode = SDIOH_MODE_SD4; /* Use SD4 mode by default */ -uint sd_f2_blocksize = 64; /* Default blocksize */ - -#ifdef BCMSDYIELD -bool sd_yieldcpu = TRUE; /* Allow CPU yielding for buffer requests */ -uint sd_minyield = 0; /* Minimum xfer size to allow CPU yield */ -bool sd_forcerb = FALSE; /* Force sync readback in intrs_on/off */ -#endif - -uint sd_divisor = 2; /* Default 48MHz/2 = 24MHz */ - -uint sd_power = 1; /* Default to SD Slot powered ON */ -uint sd_clock = 1; /* Default to SD Clock turned ON */ -uint sd_pci_slot = 0xFFFFffff; /* Used to force selection of a particular PCI slot */ -uint8 sd_dma_mode = DMA_MODE_SDMA; /* Default to SDMA for now */ - -uint sd_toctl = 7; - -static bool trap_errs = FALSE; - -static const char *dma_mode_description[] = { "PIO", "SDMA", "ADMA1", "32b ADMA2", "64b ADMA2" }; - -/* Prototypes */ -static bool sdstd_start_clock(sdioh_info_t *sd, uint16 divisor); -static bool sdstd_start_power(sdioh_info_t *sd); -static bool sdstd_bus_width(sdioh_info_t *sd, int width); -static int sdstd_set_highspeed_mode(sdioh_info_t *sd, bool HSMode); -static int sdstd_set_dma_mode(sdioh_info_t *sd, int8 dma_mode); -static int sdstd_card_enablefuncs(sdioh_info_t *sd); -static void sdstd_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count); -static int sdstd_cmd_issue(sdioh_info_t *sd, bool use_dma, uint32 cmd, uint32 arg); -static int sdstd_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, - int regsize, uint32 *data); -static int sdstd_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, - int regsize, uint32 data); -static int sdstd_driver_init(sdioh_info_t *sd); -static bool sdstd_reset(sdioh_info_t *sd, bool host_reset, bool client_reset); -static int sdstd_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, - uint32 addr, int nbytes, uint32 *data); -static int sdstd_abort(sdioh_info_t *sd, uint func); -static int sdstd_check_errs(sdioh_info_t *sdioh_info, uint32 cmd, uint32 arg); -static int set_client_block_size(sdioh_info_t *sd, int func, int blocksize); -static void sd_map_dma(sdioh_info_t * sd); -static void sd_unmap_dma(sdioh_info_t * sd); -static void sd_clear_adma_dscr_buf(sdioh_info_t *sd); -static void sd_fill_dma_data_buf(sdioh_info_t *sd, uint8 data); -static void sd_create_adma_descriptor(sdioh_info_t *sd, - uint32 index, uint32 addr_phys, - uint16 length, uint16 flags); -static void sd_dump_adma_dscr(sdioh_info_t *sd); -static void sdstd_dumpregs(sdioh_info_t *sd); - - -/* - * Private register access routines. - */ - -/* 16 bit PCI regs */ - -extern uint16 sdstd_rreg16(sdioh_info_t *sd, uint reg); -uint16 -sdstd_rreg16(sdioh_info_t *sd, uint reg) -{ - - volatile uint16 data = *(volatile uint16 *)(sd->mem_space + reg); - sd_ctrl(("16: R Reg 0x%02x, Data 0x%x\n", reg, data)); - return data; -} - -extern void sdstd_wreg16(sdioh_info_t *sd, uint reg, uint16 data); -void -sdstd_wreg16(sdioh_info_t *sd, uint reg, uint16 data) -{ - *(volatile uint16 *)(sd->mem_space + reg) = (volatile uint16) data; - sd_ctrl(("16: W Reg 0x%02x, Data 0x%x\n", reg, data)); -} - -static void -sdstd_or_reg16(sdioh_info_t *sd, uint reg, uint16 val) -{ - volatile uint16 data = *(volatile uint16 *)(sd->mem_space + reg); - sd_ctrl(("16: OR Reg 0x%02x, Val 0x%x\n", reg, val)); - data |= val; - *(volatile uint16 *)(sd->mem_space + reg) = (volatile uint16)data; - -} -static void -sdstd_mod_reg16(sdioh_info_t *sd, uint reg, int16 mask, uint16 val) -{ - - volatile uint16 data = *(volatile uint16 *)(sd->mem_space + reg); - sd_ctrl(("16: MOD Reg 0x%02x, Mask 0x%x, Val 0x%x\n", reg, mask, val)); - data &= ~mask; - data |= (val & mask); - *(volatile uint16 *)(sd->mem_space + reg) = (volatile uint16)data; -} - - -/* 32 bit PCI regs */ -static uint32 -sdstd_rreg(sdioh_info_t *sd, uint reg) -{ - volatile uint32 data = *(volatile uint32 *)(sd->mem_space + reg); - sd_ctrl(("32: R Reg 0x%02x, Data 0x%x\n", reg, data)); - return data; -} -static inline void -sdstd_wreg(sdioh_info_t *sd, uint reg, uint32 data) -{ - *(volatile uint32 *)(sd->mem_space + reg) = (volatile uint32)data; - sd_ctrl(("32: W Reg 0x%02x, Data 0x%x\n", reg, data)); - -} - -/* 8 bit PCI regs */ -static inline void -sdstd_wreg8(sdioh_info_t *sd, uint reg, uint8 data) -{ - *(volatile uint8 *)(sd->mem_space + reg) = (volatile uint8)data; - sd_ctrl(("08: W Reg 0x%02x, Data 0x%x\n", reg, data)); -} -static uint8 -sdstd_rreg8(sdioh_info_t *sd, uint reg) -{ - volatile uint8 data = *(volatile uint8 *)(sd->mem_space + reg); - sd_ctrl(("08: R Reg 0x%02x, Data 0x%x\n", reg, data)); - return data; -} - -/* - * Private work routines - */ - -sdioh_info_t *glob_sd; - -/* - * Public entry points & extern's - */ -extern sdioh_info_t * -sdioh_attach(osl_t *osh, void *bar0, uint irq) -{ - sdioh_info_t *sd; - - sd_trace(("%s\n", __FUNCTION__)); - if ((sd = (sdioh_info_t *)MALLOC(osh, sizeof(sdioh_info_t))) == NULL) { - sd_err(("sdioh_attach: out of memory, malloced %d bytes\n", MALLOCED(osh))); - return NULL; - } - bzero((char *)sd, sizeof(sdioh_info_t)); - glob_sd = sd; - sd->osh = osh; - if (sdstd_osinit(sd) != 0) { - sd_err(("%s:sdstd_osinit() failed\n", __FUNCTION__)); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return NULL; - } - sd->mem_space = (volatile char *)sdstd_reg_map(osh, (uintptr)bar0, SDIOH_REG_WINSZ); - sd_init_dma(sd); - sd->irq = irq; - if (sd->mem_space == NULL) { - sd_err(("%s:ioremap() failed\n", __FUNCTION__)); - sdstd_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return NULL; - } - sd_info(("%s:sd->mem_space = %p\n", __FUNCTION__, sd->mem_space)); - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; - sd->intr_handler_valid = FALSE; - - /* Set defaults */ - sd->sd_blockmode = TRUE; - sd->use_client_ints = TRUE; - sd->sd_dma_mode = sd_dma_mode; - - if (!sd->sd_blockmode) - sd->sd_dma_mode = DMA_MODE_NONE; - - if (sdstd_driver_init(sd) != SUCCESS) { - /* If host CPU was reset without resetting SD bus or - SD device, the device will still have its RCA but - driver no longer knows what it is (since driver has been restarted). - go through once to clear the RCA and a gain reassign it. - */ - sd_info(("driver_init failed - Reset RCA and try again\n")); - if (sdstd_driver_init(sd) != SUCCESS) { - sd_err(("%s:driver_init() failed()\n", __FUNCTION__)); - if (sd->mem_space) { - sdstd_reg_unmap(osh, (uintptr)sd->mem_space, SDIOH_REG_WINSZ); - sd->mem_space = NULL; - } - sdstd_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - } - - OSL_DMADDRWIDTH(osh, 32); - - /* Always map DMA buffers, so we can switch between DMA modes. */ - sd_map_dma(sd); - - if (sdstd_register_irq(sd, irq) != SUCCESS) { - sd_err(("%s: sdstd_register_irq() failed for irq = %d\n", __FUNCTION__, irq)); - sdstd_free_irq(sd->irq, sd); - if (sd->mem_space) { - sdstd_reg_unmap(osh, (uintptr)sd->mem_space, SDIOH_REG_WINSZ); - sd->mem_space = NULL; - } - - sdstd_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - return (NULL); - } - - sd_trace(("%s: Done\n", __FUNCTION__)); - return sd; -} - -extern SDIOH_API_RC -sdioh_detach(osl_t *osh, sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - if (sd) { - sd_unmap_dma(sd); - sdstd_wreg16(sd, SD_IntrSignalEnable, 0); - sd_trace(("%s: freeing irq %d\n", __FUNCTION__, sd->irq)); - sdstd_free_irq(sd->irq, sd); - if (sd->card_init_done) - sdstd_reset(sd, 1, 1); - if (sd->mem_space) { - sdstd_reg_unmap(osh, (uintptr)sd->mem_space, SDIOH_REG_WINSZ); - sd->mem_space = NULL; - } - - sdstd_osfree(sd); - MFREE(sd->osh, sd, sizeof(sdioh_info_t)); - } - return SDIOH_API_RC_SUCCESS; -} - -/* Configure callback to client when we recieve client interrupt */ -extern SDIOH_API_RC -sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - sd->intr_handler = fn; - sd->intr_handler_arg = argh; - sd->intr_handler_valid = TRUE; - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_deregister(sdioh_info_t *sd) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - sd->intr_handler_valid = FALSE; - sd->intr_handler = NULL; - sd->intr_handler_arg = NULL; - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_interrupt_query(sdioh_info_t *sd, bool *onoff) -{ - sd_trace(("%s: Entering\n", __FUNCTION__)); - *onoff = sd->client_intr_enabled; - return SDIOH_API_RC_SUCCESS; -} - -#if defined(DHD_DEBUG) -extern bool -sdioh_interrupt_pending(sdioh_info_t *sd) -{ - uint16 intrstatus; - intrstatus = sdstd_rreg16(sd, SD_IntrStatus); - return !!(intrstatus & CLIENT_INTR); -} -#endif - -uint -sdioh_query_iofnum(sdioh_info_t *sd) -{ - return sd->num_funcs; -} - -/* IOVar table */ -enum { - IOV_MSGLEVEL = 1, - IOV_BLOCKMODE, - IOV_BLOCKSIZE, - IOV_DMA, - IOV_USEINTS, - IOV_NUMINTS, - IOV_NUMLOCALINTS, - IOV_HOSTREG, - IOV_DEVREG, - IOV_DIVISOR, - IOV_SDMODE, - IOV_HISPEED, - IOV_HCIREGS, - IOV_POWER, - IOV_YIELDCPU, - IOV_MINYIELD, - IOV_FORCERB, - IOV_CLOCK -}; - -const bcm_iovar_t sdioh_iovars[] = { - {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, - {"sd_blockmode", IOV_BLOCKMODE, 0, IOVT_BOOL, 0 }, - {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ - {"sd_dma", IOV_DMA, 0, IOVT_UINT32, 0 }, -#ifdef BCMSDYIELD - {"sd_yieldcpu", IOV_YIELDCPU, 0, IOVT_BOOL, 0 }, - {"sd_minyield", IOV_MINYIELD, 0, IOVT_UINT32, 0 }, - {"sd_forcerb", IOV_FORCERB, 0, IOVT_BOOL, 0 }, -#endif - {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, - {"sd_numints", IOV_NUMINTS, 0, IOVT_UINT32, 0 }, - {"sd_numlocalints", IOV_NUMLOCALINTS, 0, IOVT_UINT32, 0 }, - {"sd_hostreg", IOV_HOSTREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_devreg", IOV_DEVREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_divisor", IOV_DIVISOR, 0, IOVT_UINT32, 0 }, - {"sd_power", IOV_POWER, 0, IOVT_UINT32, 0 }, - {"sd_clock", IOV_CLOCK, 0, IOVT_UINT32, 0 }, - {"sd_mode", IOV_SDMODE, 0, IOVT_UINT32, 100}, - {"sd_highspeed", IOV_HISPEED, 0, IOVT_UINT32, 0}, - {NULL, 0, 0, 0, 0 } -}; - -int -sdioh_iovar_op(sdioh_info_t *si, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - const bcm_iovar_t *vi = NULL; - int bcmerror = 0; - int val_size; - int32 int_val = 0; - bool bool_val; - uint32 actionid; - - ASSERT(name); - ASSERT(len >= 0); - - /* Get must have return space; Set does not take qualifiers */ - ASSERT(set || (arg && len)); - ASSERT(!set || (!params && !plen)); - - sd_trace(("%s: Enter (%s %s)\n", __FUNCTION__, (set ? "set" : "get"), name)); - - if ((vi = bcm_iovar_lookup(sdioh_iovars, name)) == NULL) { - bcmerror = BCME_UNSUPPORTED; - goto exit; - } - - if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, set)) != 0) - goto exit; - - /* Set up params so get and set can share the convenience variables */ - if (params == NULL) { - params = arg; - plen = len; - } - - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - val_size = sizeof(int); - - if (plen >= (int)sizeof(int_val)) - bcopy(params, &int_val, sizeof(int_val)); - - bool_val = (int_val != 0) ? TRUE : FALSE; - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - switch (actionid) { - case IOV_GVAL(IOV_MSGLEVEL): - int_val = (int32)sd_msglevel; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_MSGLEVEL): - sd_msglevel = int_val; - break; - - case IOV_GVAL(IOV_BLOCKMODE): - int_val = (int32)si->sd_blockmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_BLOCKMODE): - si->sd_blockmode = (bool)int_val; - /* Haven't figured out how to make non-block mode with DMA */ - if (!si->sd_blockmode) - si->sd_dma_mode = DMA_MODE_NONE; - break; - -#ifdef BCMSDYIELD - case IOV_GVAL(IOV_YIELDCPU): - int_val = sd_yieldcpu; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_YIELDCPU): - sd_yieldcpu = (bool)int_val; - break; - - case IOV_GVAL(IOV_MINYIELD): - int_val = sd_minyield; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_MINYIELD): - sd_minyield = (bool)int_val; - break; - - case IOV_GVAL(IOV_FORCERB): - int_val = sd_forcerb; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_FORCERB): - sd_forcerb = (bool)int_val; - break; -#endif /* BCMSDYIELD */ - - case IOV_GVAL(IOV_BLOCKSIZE): - if ((uint32)int_val > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - int_val = (int32)si->client_block_size[int_val]; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_BLOCKSIZE): - { - uint func = ((uint32)int_val >> 16); - uint blksize = (uint16)int_val; - uint maxsize; - - if (func > si->num_funcs) { - bcmerror = BCME_BADARG; - break; - } - - switch (func) { - case 0: maxsize = 32; break; - case 1: maxsize = BLOCK_SIZE_4318; break; - case 2: maxsize = BLOCK_SIZE_4328; break; - default: maxsize = 0; - } - if (blksize > maxsize) { - bcmerror = BCME_BADARG; - break; - } - if (!blksize) { - blksize = maxsize; - } - - /* Now set it */ - sdstd_lock(si); - bcmerror = set_client_block_size(si, func, blksize); - sdstd_unlock(si); - break; - } - - case IOV_GVAL(IOV_DMA): - int_val = (int32)si->sd_dma_mode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DMA): - si->sd_dma_mode = (char)int_val; - sdstd_set_dma_mode(si, si->sd_dma_mode); - break; - - case IOV_GVAL(IOV_USEINTS): - int_val = (int32)si->use_client_ints; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_USEINTS): - si->use_client_ints = (bool)int_val; - if (si->use_client_ints) - si->intmask |= CLIENT_INTR; - else - si->intmask &= ~CLIENT_INTR; - break; - - case IOV_GVAL(IOV_DIVISOR): - int_val = (uint32)sd_divisor; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DIVISOR): - sd_divisor = int_val; - if (!sdstd_start_clock(si, (uint16)sd_divisor)) { - sd_err(("set clock failed!\n")); - bcmerror = BCME_ERROR; - } - break; - - case IOV_GVAL(IOV_POWER): - int_val = (uint32)sd_power; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_POWER): - sd_power = int_val; - if (sd_power == 1) { - if (sdstd_driver_init(si) != SUCCESS) { - sd_err(("set SD Slot power failed!\n")); - bcmerror = BCME_ERROR; - } else { - sd_err(("SD Slot Powered ON.\n")); - } - } else { - uint8 pwr = 0; - - pwr = SFIELD(pwr, PWR_BUS_EN, 0); - sdstd_wreg8(si, SD_PwrCntrl, pwr); /* Set Voltage level */ - sd_err(("SD Slot Powered OFF.\n")); - } - break; - - case IOV_GVAL(IOV_CLOCK): - int_val = (uint32)sd_clock; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_CLOCK): - sd_clock = int_val; - if (sd_clock == 1) { - sd_info(("SD Clock turned ON.\n")); - if (!sdstd_start_clock(si, (uint16)sd_divisor)) { - sd_err(("sdstd_start_clock failed\n")); - bcmerror = BCME_ERROR; - } - } else { - /* turn off HC clock */ - sdstd_wreg16(si, SD_ClockCntrl, - sdstd_rreg16(si, SD_ClockCntrl) & ~((uint16)0x4)); - - sd_info(("SD Clock turned OFF.\n")); - } - break; - - case IOV_GVAL(IOV_SDMODE): - int_val = (uint32)sd_sdmode; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SDMODE): - sd_sdmode = int_val; - - if (!sdstd_bus_width(si, sd_sdmode)) { - sd_err(("sdstd_bus_width failed\n")); - bcmerror = BCME_ERROR; - } - break; - - case IOV_GVAL(IOV_HISPEED): - int_val = (uint32)sd_hiok; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_HISPEED): - sd_hiok = int_val; - bcmerror = sdstd_set_highspeed_mode(si, (bool)sd_hiok); - break; - - case IOV_GVAL(IOV_NUMINTS): - int_val = (int32)si->intrcount; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_NUMLOCALINTS): - int_val = (int32)si->local_intrcount; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_HOSTREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - - if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { - sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset)); - bcmerror = BCME_BADARG; - break; - } - - sd_trace(("%s: rreg%d at offset %d\n", __FUNCTION__, - (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), - sd_ptr->offset)); - if (sd_ptr->offset & 1) - int_val = sdstd_rreg8(si, sd_ptr->offset); - else if (sd_ptr->offset & 2) - int_val = sdstd_rreg16(si, sd_ptr->offset); - else - int_val = sdstd_rreg(si, sd_ptr->offset); - - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_HOSTREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - - if (sd_ptr->offset < SD_SysAddr || sd_ptr->offset > SD_MaxCurCap) { - sd_err(("%s: bad offset 0x%x\n", __FUNCTION__, sd_ptr->offset)); - bcmerror = BCME_BADARG; - break; - } - - sd_trace(("%s: wreg%d value 0x%08x at offset %d\n", __FUNCTION__, sd_ptr->value, - (sd_ptr->offset & 1) ? 8 : ((sd_ptr->offset & 2) ? 16 : 32), - sd_ptr->offset)); - if (sd_ptr->offset & 1) - sdstd_wreg8(si, sd_ptr->offset, (uint8)sd_ptr->value); - else if (sd_ptr->offset & 2) - sdstd_wreg16(si, sd_ptr->offset, (uint16)sd_ptr->value); - else - sdstd_wreg(si, sd_ptr->offset, (uint32)sd_ptr->value); - - break; - } - - case IOV_GVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data; - - if (sdioh_cfg_read(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - - int_val = (int)data; - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_DEVREG): - { - sdreg_t *sd_ptr = (sdreg_t *)params; - uint8 data = (uint8)sd_ptr->value; - - if (sdioh_cfg_write(si, sd_ptr->func, sd_ptr->offset, &data)) { - bcmerror = BCME_SDIO_ERROR; - break; - } - break; - } - - - default: - bcmerror = BCME_UNSUPPORTED; - break; - } -exit: - - return bcmerror; -} - -extern SDIOH_API_RC -sdioh_cfg_read(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - SDIOH_API_RC status; - /* No lock needed since sdioh_request_byte does locking */ - status = sdioh_request_byte(sd, SDIOH_READ, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cfg_write(sdioh_info_t *sd, uint fnc_num, uint32 addr, uint8 *data) -{ - /* No lock needed since sdioh_request_byte does locking */ - SDIOH_API_RC status; - status = sdioh_request_byte(sd, SDIOH_WRITE, fnc_num, addr, data); - return status; -} - -extern SDIOH_API_RC -sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) -{ - uint32 count; - int offset; - uint32 foo; - uint8 *cis = cisd; - - sd_trace(("%s: Func = %d\n", __FUNCTION__, func)); - - if (!sd->func_cis_ptr[func]) { - bzero(cis, length); - return SDIOH_API_RC_FAIL; - } - - sdstd_lock(sd); - *cis = 0; - for (count = 0; count < length; count++) { - offset = sd->func_cis_ptr[func] + count; - if (sdstd_card_regread(sd, 0, offset, 1, &foo)) { - sd_err(("%s: regread failed: Can't read CIS\n", __FUNCTION__)); - sdstd_unlock(sd); - return SDIOH_API_RC_FAIL; - } - *cis = (uint8)(foo & 0xff); - cis++; - } - sdstd_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) -{ - int status; - uint32 cmd_arg; - uint32 rsp5; - - sdstd_lock(sd); - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, rw == SDIOH_READ ? 0 : 1); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, rw == SDIOH_READ ? 0 : *byte); - - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_52, cmd_arg)) != SUCCESS) { - sdstd_unlock(sd); - return status; - } - - sdstd_cmd_getrsp(sd, &rsp5, 1); - if (sdstd_rreg16 (sd, SD_ErrorIntrStatus) != 0) { - sd_err(("%s: 1: ErrorintrStatus 0x%x\n", - __FUNCTION__, sdstd_rreg16(sd, SD_ErrorIntrStatus))); - } - if (GFIELD(rsp5, RSP5_FLAGS) != 0x10) - sd_err(("%s: rsp5 flags is 0x%x\t %d\n", - __FUNCTION__, GFIELD(rsp5, RSP5_FLAGS), func)); - - if (GFIELD(rsp5, RSP5_STUFF)) - sd_err(("%s: rsp5 stuff is 0x%x: should be 0\n", - __FUNCTION__, GFIELD(rsp5, RSP5_STUFF))); - - if (rw == SDIOH_READ) - *byte = GFIELD(rsp5, RSP5_DATA); - - sdstd_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -extern SDIOH_API_RC -sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint addr, - uint32 *word, uint nbytes) -{ - int status; - bool swap = FALSE; - - sdstd_lock(sd); - - if (rw == SDIOH_READ) { - status = sdstd_card_regread(sd, func, addr, nbytes, word); - if (swap) - *word = BCMSWAP32(*word); - } else { - if (swap) - *word = BCMSWAP32(*word); - status = sdstd_card_regwrite(sd, func, addr, nbytes, *word); - } - - sdstd_unlock(sd); - return (status == SUCCESS ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); -} - -extern SDIOH_API_RC -sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint rw, uint func, - uint addr, uint reg_width, uint buflen_u, uint8 *buffer, void *pkt) -{ - int len; - int buflen = (int)buflen_u; - bool fifo = (fix_inc == SDIOH_DATA_FIX); - uint8 *localbuf = NULL, *tmpbuf = NULL; - uint tmplen = 0; - bool local_blockmode = sd->sd_blockmode; - - sdstd_lock(sd); - - ASSERT(reg_width == 4); - ASSERT(buflen_u < (1 << 30)); - ASSERT(sd->client_block_size[func]); - - sd_data(("%s: %c len %d r_cnt %d t_cnt %d, pkt @0x%p\n", - __FUNCTION__, rw == SDIOH_READ ? 'R' : 'W', - buflen_u, sd->r_cnt, sd->t_cnt, pkt)); - - /* Break buffer down into blocksize chunks: - * Bytemode: 1 block at a time. - * Blockmode: Multiples of blocksizes at a time w/ max of SD_PAGE. - * Both: leftovers are handled last (will be sent via bytemode). - */ - while (buflen > 0) { - if (local_blockmode) { - /* Max xfer is Page size */ - len = MIN(SD_PAGE, buflen); - - /* Round down to a block boundry */ - if (buflen > sd->client_block_size[func]) - len = (len/sd->client_block_size[func]) * - sd->client_block_size[func]; - if ((func == SDIO_FUNC_1) && ((len % 4) == 3) && (rw == SDIOH_WRITE)) { - tmplen = len; - sd_err(("%s: Rounding up buffer to mod4 length.\n", __FUNCTION__)); - len++; - tmpbuf = buffer; - if ((localbuf = (uint8 *)MALLOC(sd->osh, len)) == NULL) { - sd_err(("out of memory, malloced %d bytes\n", - MALLOCED(sd->osh))); - sdstd_unlock(sd); - return SDIOH_API_RC_FAIL; - } - bcopy(buffer, localbuf, len); - buffer = localbuf; - } - } else { - /* Byte mode: One block at a time */ - len = MIN(sd->client_block_size[func], buflen); - } - - if (sdstd_card_buf(sd, rw, func, fifo, addr, len, (uint32 *)buffer) != SUCCESS) { - sdstd_unlock(sd); - return SDIOH_API_RC_FAIL; - } - - if (local_blockmode) { - if ((func == SDIO_FUNC_1) && ((tmplen % 4) == 3) && (rw == SDIOH_WRITE)) { - if (localbuf) - MFREE(sd->osh, localbuf, len); - len--; - buffer = tmpbuf; - sd_err(("%s: Restoring back buffer ptr and len.\n", __FUNCTION__)); - } - } - - buffer += len; - buflen -= len; - if (!fifo) - addr += len; - } - sdstd_unlock(sd); - return SDIOH_API_RC_SUCCESS; -} - -static -int sdstd_abort(sdioh_info_t *sd, uint func) -{ - int err = 0; - int retries; - - uint16 cmd_reg; - uint32 cmd_arg; - uint32 rsp5; - uint8 rflags; - - uint16 int_reg = 0; - uint16 plain_intstatus; - - /* Argument is write to F0 (CCCR) IOAbort with function number */ - cmd_arg = 0; - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, SDIO_FUNC_0); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, SDIOD_CCCR_IOABORT); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SD_IO_OP_WRITE); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, func); - - /* Command is CMD52 write */ - cmd_reg = 0; - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_48_BUSY); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_ABORT); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, SDIOH_CMD_52); - - if (sd->sd_mode == SDIOH_MODE_SPI) { - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 0); - } - - /* Wait for CMD_INHIBIT to go away as per spec section 3.6.1.1 */ - retries = RETRIES_SMALL; - while (GFIELD(sdstd_rreg(sd, SD_PresentState), PRES_CMD_INHIBIT)) { - if (retries == RETRIES_SMALL) - sd_err(("%s: Waiting for Command Inhibit, state 0x%08x\n", - __FUNCTION__, sdstd_rreg(sd, SD_PresentState))); - if (!--retries) { - sd_err(("%s: Command Inhibit timeout, state 0x%08x\n", - __FUNCTION__, sdstd_rreg(sd, SD_PresentState))); - if (trap_errs) - ASSERT(0); - err = BCME_SDIO_ERROR; - goto done; - } - } - - /* Clear errors from any previous commands */ - if ((plain_intstatus = sdstd_rreg16(sd, SD_ErrorIntrStatus)) != 0) { - sd_err(("abort: clearing errstat 0x%04x\n", plain_intstatus)); - sdstd_wreg16(sd, SD_ErrorIntrStatus, plain_intstatus); - } - plain_intstatus = sdstd_rreg16(sd, SD_IntrStatus); - if (plain_intstatus & ~(SFIELD(0, INTSTAT_CARD_INT, 1))) { - sd_err(("abort: intstatus 0x%04x\n", plain_intstatus)); - if (GFIELD(plain_intstatus, INTSTAT_CMD_COMPLETE)) { - sd_err(("SDSTD_ABORT: CMD COMPLETE SET BEFORE COMMAND GIVEN!!!\n")); - } - if (GFIELD(plain_intstatus, INTSTAT_CARD_REMOVAL)) { - sd_err(("SDSTD_ABORT: INTSTAT_CARD_REMOVAL\n")); - err = BCME_NODEVICE; - goto done; - } - } - - /* Issue the command */ - sdstd_wreg(sd, SD_Arg0, cmd_arg); - sdstd_wreg16(sd, SD_Command, cmd_reg); - - /* In interrupt mode return, expect later CMD_COMPLETE interrupt */ - if (!sd->polled_mode) - return err; - - /* Otherwise, wait for the command to complete */ - retries = RETRIES_LARGE; - do { - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - } while (--retries && - (GFIELD(int_reg, INTSTAT_ERROR_INT) == 0) && - (GFIELD(int_reg, INTSTAT_CMD_COMPLETE) == 0)); - - /* If command completion fails, do a cmd reset and note the error */ - if (!retries) { - sd_err(("%s: CMD_COMPLETE timeout: intr 0x%04x err 0x%04x state 0x%08x\n", - __FUNCTION__, int_reg, - sdstd_rreg16(sd, SD_ErrorIntrStatus), - sdstd_rreg(sd, SD_PresentState))); - - sdstd_wreg8(sd, SD_SoftwareReset, SFIELD(0, SW_RESET_CMD, 1)); - retries = RETRIES_LARGE; - do { - sd_trace(("%s: waiting for CMD line reset\n", __FUNCTION__)); - } while ((GFIELD(sdstd_rreg8(sd, SD_SoftwareReset), - SW_RESET_CMD)) && retries--); - - if (!retries) { - sd_err(("%s: Timeout waiting for CMD line reset\n", __FUNCTION__)); - } - - if (trap_errs) - ASSERT(0); - - err = BCME_SDIO_ERROR; - } - - /* Clear Command Complete interrupt */ - int_reg = SFIELD(0, INTSTAT_CMD_COMPLETE, 1); - sdstd_wreg16(sd, SD_IntrStatus, int_reg); - - /* Check for Errors */ - if ((plain_intstatus = sdstd_rreg16 (sd, SD_ErrorIntrStatus)) != 0) { - sd_err(("%s: ErrorintrStatus: 0x%x, " - "(intrstatus = 0x%x, present state 0x%x) clearing\n", - __FUNCTION__, plain_intstatus, - sdstd_rreg16(sd, SD_IntrStatus), - sdstd_rreg(sd, SD_PresentState))); - - sdstd_wreg16(sd, SD_ErrorIntrStatus, plain_intstatus); - - sdstd_wreg8(sd, SD_SoftwareReset, SFIELD(0, SW_RESET_DAT, 1)); - retries = RETRIES_LARGE; - do { - sd_trace(("%s: waiting for DAT line reset\n", __FUNCTION__)); - } while ((GFIELD(sdstd_rreg8(sd, SD_SoftwareReset), - SW_RESET_DAT)) && retries--); - - if (!retries) { - sd_err(("%s: Timeout waiting for DAT line reset\n", __FUNCTION__)); - } - - if (trap_errs) - ASSERT(0); - - /* ABORT is dataless, only cmd errs count */ - if (plain_intstatus & ERRINT_CMD_ERRS) - err = BCME_SDIO_ERROR; - } - - /* If command failed don't bother looking at response */ - if (err) - goto done; - - /* Otherwise, check the response */ - sdstd_cmd_getrsp(sd, &rsp5, 1); - rflags = GFIELD(rsp5, RSP5_FLAGS); - - if (rflags & SD_RSP_R5_ERRBITS) { - sd_err(("%s: R5 flags include errbits: 0x%02x\n", __FUNCTION__, rflags)); - - /* The CRC error flag applies to the previous command */ - if (rflags & (SD_RSP_R5_ERRBITS & ~SD_RSP_R5_COM_CRC_ERROR)) { - err = BCME_SDIO_ERROR; - goto done; - } - } - - if (((rflags & (SD_RSP_R5_IO_CURRENTSTATE0 | SD_RSP_R5_IO_CURRENTSTATE1)) != 0x10) && - ((rflags & (SD_RSP_R5_IO_CURRENTSTATE0 | SD_RSP_R5_IO_CURRENTSTATE1)) != 0x20)) { - sd_err(("%s: R5 flags has bad state: 0x%02x\n", __FUNCTION__, rflags)); - err = BCME_SDIO_ERROR; - goto done; - } - - if (GFIELD(rsp5, RSP5_STUFF)) { - sd_err(("%s: rsp5 stuff is 0x%x: should be 0\n", - __FUNCTION__, GFIELD(rsp5, RSP5_STUFF))); - err = BCME_SDIO_ERROR; - goto done; - } - -done: - if (err == BCME_NODEVICE) - return err; - - sdstd_wreg8(sd, SD_SoftwareReset, - SFIELD(SFIELD(0, SW_RESET_DAT, 1), SW_RESET_CMD, 1)); - - retries = RETRIES_LARGE; - do { - rflags = sdstd_rreg8(sd, SD_SoftwareReset); - if (!GFIELD(rflags, SW_RESET_DAT) && !GFIELD(rflags, SW_RESET_CMD)) - break; - } while (--retries); - - if (!retries) { - sd_err(("%s: Timeout waiting for DAT/CMD reset: 0x%02x\n", - __FUNCTION__, rflags)); - err = BCME_SDIO_ERROR; - } - - return err; -} - -extern int -sdioh_abort(sdioh_info_t *sd, uint fnum) -{ - int ret; - - sdstd_lock(sd); - ret = sdstd_abort(sd, fnum); - sdstd_unlock(sd); - - return ret; -} - -int -sdioh_start(sdioh_info_t *sd, int stage) -{ - return SUCCESS; -} - -int -sdioh_stop(sdioh_info_t *sd) -{ - return SUCCESS; -} - -static int -sdstd_check_errs(sdioh_info_t *sdioh_info, uint32 cmd, uint32 arg) -{ - uint16 regval; - uint retries; - uint function = 0; - - /* If no errors, we're done */ - if ((regval = sdstd_rreg16(sdioh_info, SD_ErrorIntrStatus)) == 0) - return SUCCESS; - - sd_info(("%s: ErrorIntrStatus 0x%04x (clearing), IntrStatus 0x%04x PresentState 0x%08x\n", - __FUNCTION__, regval, sdstd_rreg16(sdioh_info, SD_IntrStatus), - sdstd_rreg(sdioh_info, SD_PresentState))); - sdstd_wreg16(sdioh_info, SD_ErrorIntrStatus, regval); - - /* On command error, issue CMD reset */ - if (regval & ERRINT_CMD_ERRS) { - sd_trace(("%s: issuing CMD reset\n", __FUNCTION__)); - sdstd_wreg8(sdioh_info, SD_SoftwareReset, SFIELD(0, SW_RESET_CMD, 1)); - for (retries = RETRIES_LARGE; retries; retries--) - if (!(GFIELD(sdstd_rreg8(sdioh_info, SD_SoftwareReset), SW_RESET_CMD))) - break; - if (!retries) { - sd_err(("%s: Timeout waiting for CMD line reset\n", __FUNCTION__)); - } - } - - /* On data error, issue DAT reset */ - if (regval & ERRINT_DATA_ERRS) { - sd_trace(("%s: issuing DAT reset\n", __FUNCTION__)); - sdstd_wreg8(sdioh_info, SD_SoftwareReset, SFIELD(0, SW_RESET_DAT, 1)); - for (retries = RETRIES_LARGE; retries; retries--) - if (!(GFIELD(sdstd_rreg8(sdioh_info, SD_SoftwareReset), SW_RESET_DAT))) - break; - if (!retries) { - sd_err(("%s: Timeout waiting for DAT line reset\n", __FUNCTION__)); - } - } - - /* For an IO command (CMD52 or CMD53) issue an abort to the appropriate function */ - if (cmd == SDIOH_CMD_53) - function = GFIELD(arg, CMD53_FUNCTION); - else if (cmd == SDIOH_CMD_52) - function = GFIELD(arg, CMD52_FUNCTION); - if (function) { - sd_trace(("%s: requesting abort for function %d after cmd %d\n", - __FUNCTION__, function, cmd)); - sdstd_abort(sdioh_info, function); - } - - if (trap_errs) - ASSERT(0); - - return ERROR; -} - - - -/* - * Private/Static work routines - */ -static bool -sdstd_reset(sdioh_info_t *sd, bool host_reset, bool client_reset) -{ - int retries = RETRIES_LARGE; - uchar regval; - - if (!sd) - return TRUE; - - sdstd_lock(sd); - /* Reset client card */ - if (client_reset && (sd->adapter_slot != -1)) { - if (sdstd_card_regwrite(sd, 0, SDIOD_CCCR_IOABORT, 1, 0x8) != SUCCESS) - sd_err(("%s: Cannot write to card reg 0x%x\n", - __FUNCTION__, SDIOD_CCCR_IOABORT)); - else - sd->card_rca = 0; - } - - /* Reset host controller */ - if (host_reset) { - regval = SFIELD(0, SW_RESET_ALL, 1); - sdstd_wreg8(sd, SD_SoftwareReset, regval); - do { - sd_trace(("%s: waiting for reset\n", __FUNCTION__)); - } while ((sdstd_rreg8(sd, SD_SoftwareReset) & regval) && retries--); - - if (!retries) { - sd_err(("%s: Timeout waiting for host reset\n", __FUNCTION__)); - sdstd_unlock(sd); - return (FALSE); - } - - /* A reset should reset bus back to 1 bit mode */ - sd->sd_mode = SDIOH_MODE_SD1; - sdstd_set_dma_mode(sd, sd->sd_dma_mode); - } - sdstd_unlock(sd); - return TRUE; -} - -/* Disable device interrupt */ -void -sdstd_devintr_off(sdioh_info_t *sd) -{ - sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints)); - if (sd->use_client_ints) { - sd->intmask &= ~CLIENT_INTR; - sdstd_wreg16(sd, SD_IntrSignalEnable, sd->intmask); - sdstd_rreg16(sd, SD_IntrSignalEnable); /* Sync readback */ - } -} - -/* Enable device interrupt */ -void -sdstd_devintr_on(sdioh_info_t *sd) -{ - ASSERT(sd->lockcount == 0); - sd_trace(("%s: %d\n", __FUNCTION__, sd->use_client_ints)); - if (sd->use_client_ints) { - uint16 status = sdstd_rreg16(sd, SD_IntrStatusEnable); - sdstd_wreg16(sd, SD_IntrStatusEnable, SFIELD(status, INTSTAT_CARD_INT, 0)); - sdstd_wreg16(sd, SD_IntrStatusEnable, status); - - sd->intmask |= CLIENT_INTR; - sdstd_wreg16(sd, SD_IntrSignalEnable, sd->intmask); - sdstd_rreg16(sd, SD_IntrSignalEnable); /* Sync readback */ - } -} - -#ifdef BCMSDYIELD -/* Enable/disable other interrupts */ -void -sdstd_intrs_on(sdioh_info_t *sd, uint16 norm, uint16 err) -{ - if (err) { - norm = SFIELD(norm, INTSTAT_ERROR_INT, 1); - sdstd_wreg16(sd, SD_ErrorIntrSignalEnable, err); - } - - sd->intmask |= norm; - sdstd_wreg16(sd, SD_IntrSignalEnable, sd->intmask); - if (sd_forcerb) - sdstd_rreg16(sd, SD_IntrSignalEnable); /* Sync readback */ -} - -void -sdstd_intrs_off(sdioh_info_t *sd, uint16 norm, uint16 err) -{ - if (err) { - norm = SFIELD(norm, INTSTAT_ERROR_INT, 1); - sdstd_wreg16(sd, SD_ErrorIntrSignalEnable, 0); - } - - sd->intmask &= ~norm; - sdstd_wreg16(sd, SD_IntrSignalEnable, sd->intmask); - if (sd_forcerb) - sdstd_rreg16(sd, SD_IntrSignalEnable); /* Sync readback */ -} -#endif /* BCMSDYIELD */ - -static int -sdstd_host_init(sdioh_info_t *sd) -{ - int num_slots, full_slot; - uint8 reg8; - - uint32 card_ins; - int slot, first_bar = 0; - bool detect_slots = FALSE; - uint bar; - - /* Check for Arasan ID */ - if ((OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) & 0xFFFF) == VENDOR_SI_IMAGE) { - sd_info(("%s: Found Arasan Standard SDIO Host Controller\n", __FUNCTION__)); - sd->controller_type = SDIOH_TYPE_ARASAN_HDK; - detect_slots = TRUE; - } else if ((OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) & 0xFFFF) == VENDOR_BROADCOM) { - sd_info(("%s: Found Broadcom 27xx Standard SDIO Host Controller\n", __FUNCTION__)); - sd->controller_type = SDIOH_TYPE_BCM27XX; - detect_slots = FALSE; - } else if ((OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) & 0xFFFF) == VENDOR_TI) { - sd_info(("%s: Found TI PCIxx21 Standard SDIO Host Controller\n", __FUNCTION__)); - sd->controller_type = SDIOH_TYPE_TI_PCIXX21; - detect_slots = TRUE; - } else if ((OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) & 0xFFFF) == VENDOR_RICOH) { - sd_info(("%s: Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter\n", - __FUNCTION__)); - sd->controller_type = SDIOH_TYPE_RICOH_R5C822; - detect_slots = TRUE; - } else if ((OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) & 0xFFFF) == VENDOR_JMICRON) { - sd_info(("%s: JMicron Standard SDIO Host Controller\n", - __FUNCTION__)); - sd->controller_type = SDIOH_TYPE_JMICRON; - detect_slots = TRUE; - } else { - return ERROR; - } - - /* - * Determine num of slots - * Search each slot - */ - - first_bar = OSL_PCI_READ_CONFIG(sd->osh, SD_SlotInfo, 4) & 0x7; - num_slots = (OSL_PCI_READ_CONFIG(sd->osh, SD_SlotInfo, 4) & 0xff) >> 4; - num_slots &= 7; - num_slots++; /* map bits to num slots according to spec */ - - if (OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_VID, 4) == - ((SDIOH_FPGA_ID << 16) | VENDOR_BROADCOM)) { - sd_err(("%s: Found Broadcom Standard SDIO Host Controller FPGA\n", __FUNCTION__)); - /* Set BAR0 Window to SDIOSTH core */ - OSL_PCI_WRITE_CONFIG(sd->osh, PCI_BAR0_WIN, 4, 0x18001000); - - /* Set defaults particular to this controller. */ - detect_slots = TRUE; - num_slots = 1; - first_bar = 0; - - /* Controller supports ADMA2, so turn it on here. */ - sd->sd_dma_mode = DMA_MODE_ADMA2; - } - - /* Map in each slot on the board and query it to see if a - * card is inserted. Use the first populated slot found. - */ - if (sd->mem_space) { - sdstd_reg_unmap(sd->osh, (uintptr)sd->mem_space, SDIOH_REG_WINSZ); - sd->mem_space = NULL; - } - - full_slot = -1; - - for (slot = 0; slot < num_slots; slot++) { - bar = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_BAR0 + (4*(slot + first_bar)), 4); - sd->mem_space = (volatile char *)sdstd_reg_map(sd->osh, - (uintptr)bar, SDIOH_REG_WINSZ); - - sd->adapter_slot = -1; - - if (detect_slots) { - card_ins = GFIELD(sdstd_rreg(sd, SD_PresentState), PRES_CARD_PRESENT); - } else { - card_ins = TRUE; - } - - if (card_ins) { - sd_info(("%s: SDIO slot %d: Full\n", __FUNCTION__, slot)); - if (full_slot < 0) - full_slot = slot; - } else { - sd_info(("%s: SDIO slot %d: Empty\n", __FUNCTION__, slot)); - } - - if (sd->mem_space) { - sdstd_reg_unmap(sd->osh, (uintptr)sd->mem_space, SDIOH_REG_WINSZ); - sd->mem_space = NULL; - } - } - - if (full_slot < 0) { - sd_err(("No slots on SDIO controller are populated\n")); - return -1; - } - - bar = OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_BAR0 + (4*(full_slot + first_bar)), 4); - sd->mem_space = (volatile char *)sdstd_reg_map(sd->osh, (uintptr)bar, SDIOH_REG_WINSZ); - - sd_err(("Using slot %d at BAR%d [0x%08x] mem_space 0x%p\n", - full_slot, - (full_slot + first_bar), - OSL_PCI_READ_CONFIG(sd->osh, PCI_CFG_BAR0 + (4*(full_slot + first_bar)), 4), - sd->mem_space)); - - - sd->adapter_slot = full_slot; - - sd->version = sdstd_rreg16(sd, SD_HostControllerVersion) & 0xFF; - switch (sd->version) { - case 0: - sd_err(("Host Controller version 1.0, Vendor Revision: 0x%02x\n", - sdstd_rreg16(sd, SD_HostControllerVersion) >> 8)); - break; - case 1: - case 2: - sd_err(("Host Controller version 2.0, Vendor Revision: 0x%02x\n", - sdstd_rreg16(sd, SD_HostControllerVersion) >> 8)); - break; - default: - sd_err(("%s: Host Controller version 0x%02x not supported.\n", - __FUNCTION__, sd->version)); - break; - } - - sd->caps = sdstd_rreg(sd, SD_Capabilities); /* Cache this for later use */ - sd->curr_caps = sdstd_rreg(sd, SD_MaxCurCap); - - sdstd_set_dma_mode(sd, sd->sd_dma_mode); - - - sdstd_reset(sd, 1, 0); - - /* Read SD4/SD1 mode */ - if ((reg8 = sdstd_rreg8(sd, SD_HostCntrl))) { - if (reg8 & SD4_MODE) { - sd_err(("%s: Host cntrlr already in 4 bit mode: 0x%x\n", - __FUNCTION__, reg8)); - } - } - - /* Default power on mode is SD1 */ - sd->sd_mode = SDIOH_MODE_SD1; - sd->polled_mode = TRUE; - sd->host_init_done = TRUE; - sd->card_init_done = FALSE; - sd->adapter_slot = full_slot; - - return (SUCCESS); -} -#define CMD5_RETRIES 200 -static int -get_ocr(sdioh_info_t *sd, uint32 *cmd_arg, uint32 *cmd_rsp) -{ - int retries, status; - - /* Get the Card's Operation Condition. Occasionally the board - * takes a while to become ready - */ - retries = CMD5_RETRIES; - do { - *cmd_rsp = 0; - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_5, *cmd_arg)) - != SUCCESS) { - sd_err(("%s: CMD5 failed\n", __FUNCTION__)); - return status; - } - sdstd_cmd_getrsp(sd, cmd_rsp, 1); - if (!GFIELD(*cmd_rsp, RSP4_CARD_READY)) - sd_trace(("%s: Waiting for card to become ready\n", __FUNCTION__)); - } while ((!GFIELD(*cmd_rsp, RSP4_CARD_READY)) && --retries); - if (!retries) - return ERROR; - - return (SUCCESS); -} - -static int -sdstd_client_init(sdioh_info_t *sd) -{ - uint32 cmd_arg, cmd_rsp; - int status; - uint8 fn_ints; - - - sd_trace(("%s: Powering up slot %d\n", __FUNCTION__, sd->adapter_slot)); - - /* Clear any pending ints */ - sdstd_wreg16(sd, SD_IntrStatus, 0x1ff); - sdstd_wreg16(sd, SD_ErrorIntrStatus, 0x0fff); - - /* Enable both Normal and Error Status. This does not enable - * interrupts, it only enables the status bits to - * become 'live' - */ - sdstd_wreg16(sd, SD_IntrStatusEnable, 0x1ff); - sdstd_wreg16(sd, SD_ErrorIntrStatusEnable, 0xffff); - - sdstd_wreg16(sd, SD_IntrSignalEnable, 0); /* Disable ints for now. */ - - /* Start at ~400KHz clock rate for initialization */ - if (!sdstd_start_clock(sd, 128)) { - sd_err(("sdstd_start_clock failed\n")); - return ERROR; - } - if (!sdstd_start_power(sd)) { - sd_err(("sdstd_start_power failed\n")); - return ERROR; - } - - if (sd->num_funcs == 0) { - sd_err(("%s: No IO funcs!\n", __FUNCTION__)); - return ERROR; - } - - /* In SPI mode, issue CMD0 first */ - if (sd->sd_mode == SDIOH_MODE_SPI) { - cmd_arg = 0; - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_0, cmd_arg)) - != SUCCESS) { - sd_err(("BCMSDIOH: cardinit: CMD0 failed!\n")); - return status; - } - } - - if (sd->sd_mode != SDIOH_MODE_SPI) { - uint16 rsp6_status; - - /* Card is operational. Ask it to send an RCA */ - cmd_arg = 0; - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_3, cmd_arg)) - != SUCCESS) { - sd_err(("%s: CMD3 failed!\n", __FUNCTION__)); - return status; - } - - /* Verify the card status returned with the cmd response */ - sdstd_cmd_getrsp(sd, &cmd_rsp, 1); - rsp6_status = GFIELD(cmd_rsp, RSP6_STATUS); - if (GFIELD(rsp6_status, RSP6STAT_COM_CRC_ERROR) || - GFIELD(rsp6_status, RSP6STAT_ILLEGAL_CMD) || - GFIELD(rsp6_status, RSP6STAT_ERROR)) { - sd_err(("%s: CMD3 response error. Response = 0x%x!\n", - __FUNCTION__, rsp6_status)); - return ERROR; - } - - /* Save the Card's RCA */ - sd->card_rca = GFIELD(cmd_rsp, RSP6_IO_RCA); - sd_info(("RCA is 0x%x\n", sd->card_rca)); - - if (rsp6_status) - sd_err(("raw status is 0x%x\n", rsp6_status)); - - /* Select the card */ - cmd_arg = SFIELD(0, CMD7_RCA, sd->card_rca); - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_7, cmd_arg)) - != SUCCESS) { - sd_err(("%s: CMD7 failed!\n", __FUNCTION__)); - return status; - } - sdstd_cmd_getrsp(sd, &cmd_rsp, 1); - if (cmd_rsp != SDIOH_CMD7_EXP_STATUS) { - sd_err(("%s: CMD7 response error. Response = 0x%x!\n", - __FUNCTION__, cmd_rsp)); - return ERROR; - } - } - - sdstd_card_enablefuncs(sd); - - if (!sdstd_bus_width(sd, sd_sdmode)) { - sd_err(("sdstd_bus_width failed\n")); - return ERROR; - } - - set_client_block_size(sd, 1, BLOCK_SIZE_4318); - fn_ints = INTR_CTL_FUNC1_EN; - - if (sd->num_funcs >= 2) { - set_client_block_size(sd, 2, sd_f2_blocksize /* BLOCK_SIZE_4328 */); - fn_ints |= INTR_CTL_FUNC2_EN; - } - - /* Enable/Disable Client interrupts */ - /* Turn on here but disable at host controller? */ - if (sdstd_card_regwrite(sd, 0, SDIOD_CCCR_INTEN, 1, - (fn_ints | INTR_CTL_MASTER_EN)) != SUCCESS) { - sd_err(("%s: Could not enable ints in CCCR\n", __FUNCTION__)); - return ERROR; - } - - /* Switch to High-speed clocking mode if both host and device support it */ - sdstd_set_highspeed_mode(sd, (bool)sd_hiok); - - /* After configuring for High-Speed mode, set the desired clock rate. */ - if (!sdstd_start_clock(sd, (uint16)sd_divisor)) { - sd_err(("sdstd_start_clock failed\n")); - return ERROR; - } - - sd->card_init_done = TRUE; - - return SUCCESS; -} - -static int -sdstd_set_highspeed_mode(sdioh_info_t *sd, bool HSMode) -{ - uint32 regdata; - int status; - uint8 reg8; - - reg8 = sdstd_rreg8(sd, SD_HostCntrl); - - - if (HSMode == TRUE) { - if (sd_hiok && (GFIELD(sd->caps, CAP_HIGHSPEED)) == 0) { - sd_err(("Host Controller does not support hi-speed mode.\n")); - return BCME_ERROR; - } - - sd_info(("Attempting to enable High-Speed mode.\n")); - - if ((status = sdstd_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, ®data)) != SUCCESS) { - return BCME_SDIO_ERROR; - } - if (regdata & SDIO_SPEED_SHS) { - sd_info(("Device supports High-Speed mode.\n")); - - regdata |= SDIO_SPEED_EHS; - - sd_info(("Writing %08x to Card at %08x\n", - regdata, SDIOD_CCCR_SPEED_CONTROL)); - if ((status = sdstd_card_regwrite(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, regdata)) != BCME_OK) { - return BCME_SDIO_ERROR; - } - - if ((status = sdstd_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, ®data)) != BCME_OK) { - return BCME_SDIO_ERROR; - } - - sd_info(("Read %08x to Card at %08x\n", regdata, SDIOD_CCCR_SPEED_CONTROL)); - - reg8 = SFIELD(reg8, HOST_HI_SPEED_EN, 1); - - sd_err(("High-speed clocking mode enabled.\n")); - } - else { - sd_err(("Device does not support High-Speed Mode.\n")); - reg8 = SFIELD(reg8, HOST_HI_SPEED_EN, 0); - } - } else { - /* Force off device bit */ - if ((status = sdstd_card_regread(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, ®data)) != BCME_OK) { - return status; - } - if (regdata & SDIO_SPEED_EHS) { - regdata &= ~SDIO_SPEED_EHS; - if ((status = sdstd_card_regwrite(sd, 0, SDIOD_CCCR_SPEED_CONTROL, - 1, regdata)) != BCME_OK) { - return status; - } - } - - sd_err(("High-speed clocking mode disabled.\n")); - reg8 = SFIELD(reg8, HOST_HI_SPEED_EN, 0); - } - - sdstd_wreg8(sd, SD_HostCntrl, reg8); - - return BCME_OK; -} - -/* Select DMA Mode: - * If dma_mode == DMA_MODE_AUTO, pick the "best" mode. - * Otherwise, pick the selected mode if supported. - * If not supported, use PIO mode. - */ -static int -sdstd_set_dma_mode(sdioh_info_t *sd, int8 dma_mode) -{ - uint8 reg8, dma_sel_bits = SDIOH_SDMA_MODE; - int8 prev_dma_mode = sd->sd_dma_mode; - - switch (prev_dma_mode) { - case DMA_MODE_AUTO: - sd_dma(("%s: Selecting best DMA mode supported by controller.\n", - __FUNCTION__)); - if (GFIELD(sd->caps, CAP_ADMA2)) { - sd->sd_dma_mode = DMA_MODE_ADMA2; - dma_sel_bits = SDIOH_ADMA2_MODE; - } else if (GFIELD(sd->caps, CAP_ADMA1)) { - sd->sd_dma_mode = DMA_MODE_ADMA1; - dma_sel_bits = SDIOH_ADMA1_MODE; - } else if (GFIELD(sd->caps, CAP_DMA)) { - sd->sd_dma_mode = DMA_MODE_SDMA; - } else { - sd->sd_dma_mode = DMA_MODE_NONE; - } - break; - case DMA_MODE_NONE: - sd->sd_dma_mode = DMA_MODE_NONE; - break; - case DMA_MODE_SDMA: - if (GFIELD(sd->caps, CAP_DMA)) { - sd->sd_dma_mode = DMA_MODE_SDMA; - } else { - sd_err(("%s: SDMA not supported by controller.\n", __FUNCTION__)); - sd->sd_dma_mode = DMA_MODE_NONE; - } - break; - case DMA_MODE_ADMA1: - if (GFIELD(sd->caps, CAP_ADMA1)) { - sd->sd_dma_mode = DMA_MODE_ADMA1; - dma_sel_bits = SDIOH_ADMA1_MODE; - } else { - sd_err(("%s: ADMA1 not supported by controller.\n", __FUNCTION__)); - sd->sd_dma_mode = DMA_MODE_NONE; - } - break; - case DMA_MODE_ADMA2: - if (GFIELD(sd->caps, CAP_ADMA2)) { - sd->sd_dma_mode = DMA_MODE_ADMA2; - dma_sel_bits = SDIOH_ADMA2_MODE; - } else { - sd_err(("%s: ADMA2 not supported by controller.\n", __FUNCTION__)); - sd->sd_dma_mode = DMA_MODE_NONE; - } - break; - case DMA_MODE_ADMA2_64: - sd_err(("%s: 64b ADMA2 not supported by driver.\n", __FUNCTION__)); - sd->sd_dma_mode = DMA_MODE_NONE; - break; - default: - sd_err(("%s: Unsupported DMA Mode %d requested.\n", __FUNCTION__, - prev_dma_mode)); - sd->sd_dma_mode = DMA_MODE_NONE; - break; - } - - /* clear SysAddr, only used for SDMA */ - sdstd_wreg(sd, SD_SysAddr, 0); - - sd_err(("%s: %s mode selected.\n", __FUNCTION__, dma_mode_description[sd->sd_dma_mode])); - - reg8 = sdstd_rreg8(sd, SD_HostCntrl); - reg8 = SFIELD(reg8, HOST_DMA_SEL, dma_sel_bits); - sdstd_wreg8(sd, SD_HostCntrl, reg8); - sd_dma(("%s: SD_HostCntrl=0x%02x\n", __FUNCTION__, reg8)); - - return BCME_OK; -} - - -bool -sdstd_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor) -{ - uint rc, count; - uint16 divisor; - - /* turn off HC clock */ - sdstd_wreg16(sd, SD_ClockCntrl, - sdstd_rreg16(sd, SD_ClockCntrl) & ~((uint16)0x4)); /* Disable the HC clock */ - - /* Set divisor */ - - divisor = (new_sd_divisor >> 1) << 8; - - sd_info(("Clock control is 0x%x\n", sdstd_rreg16(sd, SD_ClockCntrl))); - sdstd_mod_reg16(sd, SD_ClockCntrl, 0xff00, divisor); - sd_info(("%s: Using clock divisor of %d (regval 0x%04x)\n", __FUNCTION__, - new_sd_divisor, divisor)); - - sd_info(("Primary Clock Freq = %d MHz\n", GFIELD(sd->caps, CAP_TO_CLKFREQ))); - - if (GFIELD(sd->caps, CAP_TO_CLKFREQ) == 50) { - sd_info(("%s: Resulting SDIO clock is %d %s\n", __FUNCTION__, - ((50 % new_sd_divisor) ? (50000 / new_sd_divisor) : (50 / new_sd_divisor)), - ((50 % new_sd_divisor) ? "KHz" : "MHz"))); - } else if (GFIELD(sd->caps, CAP_TO_CLKFREQ) == 48) { - sd_info(("%s: Resulting SDIO clock is %d %s\n", __FUNCTION__, - ((48 % new_sd_divisor) ? (48000 / new_sd_divisor) : (48 / new_sd_divisor)), - ((48 % new_sd_divisor) ? "KHz" : "MHz"))); - } else if (GFIELD(sd->caps, CAP_TO_CLKFREQ) == 33) { - sd_info(("%s: Resulting SDIO clock is %d %s\n", __FUNCTION__, - ((33 % new_sd_divisor) ? (33000 / new_sd_divisor) : (33 / new_sd_divisor)), - ((33 % new_sd_divisor) ? "KHz" : "MHz"))); - - } else if (sd->controller_type == SDIOH_TYPE_BCM27XX) { - } else { - sd_err(("Need to determine divisor for %d MHz clocks\n", - GFIELD(sd->caps, CAP_TO_CLKFREQ))); - sd_err(("Consult SD Host Controller Spec: Clock Control Register\n")); - return (FALSE); - } - - sdstd_or_reg16(sd, SD_ClockCntrl, 0x1); /* Enable the clock */ - - /* Wait for clock to stabilize */ - rc = (sdstd_rreg16(sd, SD_ClockCntrl) & 2); - count = 0; - while (!rc) { - OSL_DELAY(1); - sd_info(("Waiting for clock to become stable 0x%x\n", rc)); - rc = (sdstd_rreg16(sd, SD_ClockCntrl) & 2); - count++; - if (count > 10000) { - sd_err(("%s:Clocks failed to stabilize after %u attempts", - __FUNCTION__, count)); - return (FALSE); - } - } - /* Turn on clock */ - sdstd_or_reg16(sd, SD_ClockCntrl, 0x4); - - /* Set timeout control (adjust default value based on divisor). - * Disabling timeout interrupts during setting is advised by host spec. - */ - { - uint16 regdata; - uint toval; - - toval = sd_toctl; - divisor = new_sd_divisor; - - while (toval && !(divisor & 1)) { - toval -= 1; - divisor >>= 1; - } - - regdata = sdstd_rreg16(sd, SD_ErrorIntrStatusEnable); - sdstd_wreg16(sd, SD_ErrorIntrStatusEnable, (regdata & ~ERRINT_DATA_TIMEOUT_BIT)); - sdstd_wreg8(sd, SD_TimeoutCntrl, (uint8)toval); - sdstd_wreg16(sd, SD_ErrorIntrStatusEnable, regdata); - } - - OSL_DELAY(2); - - sd_info(("Final Clock control is 0x%x\n", sdstd_rreg16(sd, SD_ClockCntrl))); - - return TRUE; -} - -bool -sdstd_start_power(sdioh_info_t *sd) -{ - char *s; - uint32 cmd_arg; - uint32 cmd_rsp; - uint8 pwr = 0; - int volts; - - volts = 0; - s = NULL; - if (GFIELD(sd->caps, CAP_VOLT_1_8)) { - volts = 5; - s = "1.8"; - } - if (GFIELD(sd->caps, CAP_VOLT_3_0)) { - volts = 6; - s = "3.0"; - } - if (GFIELD(sd->caps, CAP_VOLT_3_3)) { - volts = 7; - s = "3.3"; - } - - pwr = SFIELD(pwr, PWR_VOLTS, volts); - pwr = SFIELD(pwr, PWR_BUS_EN, 1); - sdstd_wreg8(sd, SD_PwrCntrl, pwr); /* Set Voltage level */ - sd_info(("Setting Bus Power to %s Volts\n", s)); - - /* Wait for power to stabilize, Dongle takes longer than NIC. */ - OSL_DELAY(250000); - - /* Get the Card's Operation Condition. Occasionally the board - * takes a while to become ready - */ - cmd_arg = 0; - cmd_rsp = 0; - if (get_ocr(sd, &cmd_arg, &cmd_rsp) != SUCCESS) { - sd_err(("%s: Failed to get OCR bailing\n", __FUNCTION__)); - sdstd_reset(sd, 0, 1); - return FALSE; - } - - sd_info(("mem_present = %d\n", GFIELD(cmd_rsp, RSP4_MEM_PRESENT))); - sd_info(("num_funcs = %d\n", GFIELD(cmd_rsp, RSP4_NUM_FUNCS))); - sd_info(("card_ready = %d\n", GFIELD(cmd_rsp, RSP4_CARD_READY))); - sd_info(("OCR = 0x%x\n", GFIELD(cmd_rsp, RSP4_IO_OCR))); - - /* Verify that the card supports I/O mode */ - if (GFIELD(cmd_rsp, RSP4_NUM_FUNCS) == 0) { - sd_err(("%s: Card does not support I/O\n", __FUNCTION__)); - return ERROR; - } - sd->num_funcs = GFIELD(cmd_rsp, RSP4_NUM_FUNCS); - - /* Examine voltage: Arasan only supports 3.3 volts, - * so look for 3.2-3.3 Volts and also 3.3-3.4 volts. - */ - - if ((GFIELD(cmd_rsp, RSP4_IO_OCR) & (0x3 << 20)) == 0) { - sd_err(("This client does not support 3.3 volts!\n")); - return ERROR; - } - sd_info(("Leaving bus power at 3.3 Volts\n")); - - cmd_arg = SFIELD(0, CMD5_OCR, 0xfff000); - cmd_rsp = 0; - get_ocr(sd, &cmd_arg, &cmd_rsp); - sd_info(("OCR = 0x%x\n", GFIELD(cmd_rsp, RSP4_IO_OCR))); - return TRUE; -} - -bool -sdstd_bus_width(sdioh_info_t *sd, int new_mode) -{ - uint32 regdata; - int status; - uint8 reg8; - - sd_trace(("%s\n", __FUNCTION__)); - if (sd->sd_mode == new_mode) { - sd_info(("%s: Already at width %d\n", __FUNCTION__, new_mode)); - /* Could exit, but continue just in case... */ - } - - /* Set client side via reg 0x7 in CCCR */ - if ((status = sdstd_card_regread (sd, 0, SDIOD_CCCR_BICTRL, 1, ®data)) != SUCCESS) - return (bool)status; - regdata &= ~BUS_SD_DATA_WIDTH_MASK; - if (new_mode == SDIOH_MODE_SD4) { - sd_info(("Changing to SD4 Mode\n")); - regdata |= SD4_MODE; - } else if (new_mode == SDIOH_MODE_SD1) { - sd_info(("Changing to SD1 Mode\n")); - } else { - sd_err(("SPI Mode not supported by Standard Host Controller\n")); - } - - if ((status = sdstd_card_regwrite (sd, 0, SDIOD_CCCR_BICTRL, 1, regdata)) != SUCCESS) - return (bool)status; - - /* Set host side via Host reg */ - reg8 = sdstd_rreg8(sd, SD_HostCntrl) & ~SD4_MODE; - if (new_mode == SDIOH_MODE_SD4) - reg8 |= SD4_MODE; - sdstd_wreg8(sd, SD_HostCntrl, reg8); - - sd->sd_mode = new_mode; - - return TRUE; -} - -static int -sdstd_driver_init(sdioh_info_t *sd) -{ - sd_trace(("%s\n", __FUNCTION__)); - if ((sdstd_host_init(sd)) != SUCCESS) { - return ERROR; - } - - if (sdstd_client_init(sd) != SUCCESS) { - return ERROR; - } - - return SUCCESS; -} - -static int -sdstd_get_cisaddr(sdioh_info_t *sd, uint32 regaddr) -{ - /* read 24 bits and return valid 17 bit addr */ - int i; - uint32 scratch, regdata; - uint8 *ptr = (uint8 *)&scratch; - for (i = 0; i < 3; i++) { - if ((sdstd_card_regread (sd, 0, regaddr, 1, ®data)) != SUCCESS) - sd_err(("%s: Can't read!\n", __FUNCTION__)); - - *ptr++ = (uint8) regdata; - regaddr++; - } - /* Only the lower 17-bits are valid */ - scratch = ltoh32(scratch); - scratch &= 0x0001FFFF; - return (scratch); -} - -static int -sdstd_card_enablefuncs(sdioh_info_t *sd) -{ - int status; - uint32 regdata; - uint32 fbraddr; - uint8 func; - - sd_trace(("%s\n", __FUNCTION__)); - - /* Get the Card's common CIS address */ - sd->com_cis_ptr = sdstd_get_cisaddr(sd, SDIOD_CCCR_CISPTR_0); - sd->func_cis_ptr[0] = sd->com_cis_ptr; - sd_info(("%s: Card's Common CIS Ptr = 0x%x\n", __FUNCTION__, sd->com_cis_ptr)); - - /* Get the Card's function CIS (for each function) */ - for (fbraddr = SDIOD_FBR_STARTADDR, func = 1; - func <= sd->num_funcs; func++, fbraddr += SDIOD_FBR_SIZE) { - sd->func_cis_ptr[func] = sdstd_get_cisaddr(sd, SDIOD_FBR_CISPTR_0 + fbraddr); - sd_info(("%s: Function %d CIS Ptr = 0x%x\n", - __FUNCTION__, func, sd->func_cis_ptr[func])); - } - - /* Enable function 1 on the card */ - regdata = SDIO_FUNC_ENABLE_1; - if ((status = sdstd_card_regwrite(sd, 0, SDIOD_CCCR_IOEN, 1, regdata)) != SUCCESS) - return status; - - return SUCCESS; -} - -/* Read client card reg */ -static int -sdstd_card_regread(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 *data) -{ - int status; - uint32 cmd_arg; - uint32 rsp5; - - - cmd_arg = 0; - - if ((func == 0) || (regsize == 1)) { - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_READ); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, 0); - - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_52, cmd_arg)) - != SUCCESS) - return status; - - sdstd_cmd_getrsp(sd, &rsp5, 1); - if (sdstd_rreg16(sd, SD_ErrorIntrStatus) != 0) { - sd_err(("%s: 1: ErrorintrStatus 0x%x\n", - __FUNCTION__, sdstd_rreg16(sd, SD_ErrorIntrStatus))); - } - - if (GFIELD(rsp5, RSP5_FLAGS) != 0x10) - sd_err(("%s: rsp5 flags is 0x%x\t %d\n", - __FUNCTION__, GFIELD(rsp5, RSP5_FLAGS), func)); - - if (GFIELD(rsp5, RSP5_STUFF)) - sd_err(("%s: rsp5 stuff is 0x%x: should be 0\n", - __FUNCTION__, GFIELD(rsp5, RSP5_STUFF))); - *data = GFIELD(rsp5, RSP5_DATA); - } else { - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, regsize); - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); - cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_READ); - - sd->data_xfer_count = regsize; - - /* sdstd_cmd_issue() returns with the command complete bit - * in the ISR already cleared - */ - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_53, cmd_arg)) - != SUCCESS) - return status; - - sdstd_cmd_getrsp(sd, &rsp5, 1); - - if (GFIELD(rsp5, RSP5_FLAGS) != 0x10) - sd_err(("%s: rsp5 flags is 0x%x\t %d\n", - __FUNCTION__, GFIELD(rsp5, RSP5_FLAGS), func)); - - if (GFIELD(rsp5, RSP5_STUFF)) - sd_err(("%s: rsp5 stuff is 0x%x: should be 0\n", - __FUNCTION__, GFIELD(rsp5, RSP5_STUFF))); - - if (sd->polled_mode) { - volatile uint16 int_reg; - int retries = RETRIES_LARGE; - - /* Wait for Read Buffer to become ready */ - do { - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - } while (--retries && (GFIELD(int_reg, INTSTAT_BUF_READ_READY) == 0)); - - if (!retries) { - sd_err(("%s: Timeout on Buf_Read_Ready: " - "intStat: 0x%x errint: 0x%x PresentState 0x%x\n", - __FUNCTION__, int_reg, - sdstd_rreg16(sd, SD_ErrorIntrStatus), - sdstd_rreg(sd, SD_PresentState))); - sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg); - return (ERROR); - } - - /* Have Buffer Ready, so clear it and read the data */ - sdstd_wreg16(sd, SD_IntrStatus, SFIELD(0, INTSTAT_BUF_READ_READY, 1)); - if (regsize == 2) - *data = sdstd_rreg16(sd, SD_BufferDataPort0); - else - *data = sdstd_rreg(sd, SD_BufferDataPort0); - - /* Check Status. - * After the data is read, the Transfer Complete bit should be on - */ - retries = RETRIES_LARGE; - do { - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - } while (--retries && (GFIELD(int_reg, INTSTAT_XFER_COMPLETE) == 0)); - - /* Check for any errors from the data phase */ - if (sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg)) - return ERROR; - - if (!retries) { - sd_err(("%s: Timeout on xfer complete: " - "intr 0x%04x err 0x%04x state 0x%08x\n", - __FUNCTION__, int_reg, - sdstd_rreg16(sd, SD_ErrorIntrStatus), - sdstd_rreg(sd, SD_PresentState))); - return (ERROR); - } - - sdstd_wreg16(sd, SD_IntrStatus, SFIELD(0, INTSTAT_XFER_COMPLETE, 1)); - } - } - if (sd->polled_mode) { - if (regsize == 2) - *data &= 0xffff; - } - return SUCCESS; -} - -bool -check_client_intr(sdioh_info_t *sd) -{ - uint16 raw_int, cur_int, old_int; - - raw_int = sdstd_rreg16(sd, SD_IntrStatus); - cur_int = raw_int & sd->intmask; - - if (!cur_int) { - /* Not an error -- might share interrupts... */ - return FALSE; - } - - if (GFIELD(cur_int, INTSTAT_CARD_INT)) { - old_int = sdstd_rreg16(sd, SD_IntrStatusEnable); - sdstd_wreg16(sd, SD_IntrStatusEnable, SFIELD(old_int, INTSTAT_CARD_INT, 0)); - - if (sd->client_intr_enabled && sd->use_client_ints) { - sd->intrcount++; - ASSERT(sd->intr_handler); - ASSERT(sd->intr_handler_arg); - (sd->intr_handler)(sd->intr_handler_arg); - } else { - sd_err(("%s: Not ready for intr: enabled %d, handler %p\n", - __FUNCTION__, sd->client_intr_enabled, sd->intr_handler)); - } - sdstd_wreg16(sd, SD_IntrStatusEnable, old_int); - } else { - /* Local interrupt: disable, set flag, and save intrstatus */ - sdstd_wreg16(sd, SD_IntrSignalEnable, 0); - sdstd_wreg16(sd, SD_ErrorIntrSignalEnable, 0); - sd->local_intrcount++; - sd->got_hcint = TRUE; - sd->last_intrstatus = cur_int; - } - - return TRUE; -} - -void -sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err) -{ - uint16 int_reg, err_reg; - int retries = RETRIES_LARGE; - - do { - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - err_reg = sdstd_rreg16(sd, SD_ErrorIntrStatus); - } while (--retries && !(int_reg & norm) && !(err_reg & err)); - - norm |= sd->intmask; - if (err_reg & err) - norm = SFIELD(norm, INTSTAT_ERROR_INT, 1); - sd->last_intrstatus = int_reg & norm; -} - -/* write a client register */ -static int -sdstd_card_regwrite(sdioh_info_t *sd, int func, uint32 regaddr, int regsize, uint32 data) -{ - int status; - uint32 cmd_arg, rsp5, flags; - - cmd_arg = 0; - - if ((func == 0) || (regsize == 1)) { - cmd_arg = SFIELD(cmd_arg, CMD52_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD52_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD52_RW_FLAG, SDIOH_XFER_TYPE_WRITE); - cmd_arg = SFIELD(cmd_arg, CMD52_RAW, 0); - cmd_arg = SFIELD(cmd_arg, CMD52_DATA, data & 0xff); - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_52, cmd_arg)) - != SUCCESS) - return status; - - sdstd_cmd_getrsp(sd, &rsp5, 1); - flags = GFIELD(rsp5, RSP5_FLAGS); - if (flags && (flags != 0x10)) - sd_err(("%s: rsp5.rsp5.flags = 0x%x, expecting 0x10\n", - __FUNCTION__, flags)); - } - else { - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, regsize); - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); - cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, regaddr); - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_WRITE); - - sd->data_xfer_count = regsize; - - /* sdstd_cmd_issue() returns with the command complete bit - * in the ISR already cleared - */ - if ((status = sdstd_cmd_issue(sd, USE_DMA(sd), SDIOH_CMD_53, cmd_arg)) - != SUCCESS) - return status; - - sdstd_cmd_getrsp(sd, &rsp5, 1); - - if (GFIELD(rsp5, RSP5_FLAGS) != 0x10) - sd_err(("%s: rsp5 flags = 0x%x, expecting 0x10\n", - __FUNCTION__, GFIELD(rsp5, RSP5_FLAGS))); - if (GFIELD(rsp5, RSP5_STUFF)) - sd_err(("%s: rsp5 stuff is 0x%x: expecting 0\n", - __FUNCTION__, GFIELD(rsp5, RSP5_STUFF))); - - if (sd->polled_mode) { - uint16 int_reg; - int retries = RETRIES_LARGE; - - /* Wait for Write Buffer to become ready */ - do { - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - } while (--retries && (GFIELD(int_reg, INTSTAT_BUF_WRITE_READY) == 0)); - - if (!retries) { - sd_err(("%s: Timeout on Buf_Write_Ready: intStat: 0x%x " - "errint: 0x%x PresentState 0x%x\n", - __FUNCTION__, int_reg, - sdstd_rreg16(sd, SD_ErrorIntrStatus), - sdstd_rreg(sd, SD_PresentState))); - sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg); - return (ERROR); - } - /* Clear Write Buf Ready bit */ - int_reg = 0; - int_reg = SFIELD(int_reg, INTSTAT_BUF_WRITE_READY, 1); - sdstd_wreg16(sd, SD_IntrStatus, int_reg); - - /* At this point we have Buffer Ready, so write the data */ - if (regsize == 2) - sdstd_wreg16(sd, SD_BufferDataPort0, (uint16) data); - else - sdstd_wreg(sd, SD_BufferDataPort0, data); - - /* Wait for Transfer Complete */ - retries = RETRIES_LARGE; - do { - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - } while (--retries && (GFIELD(int_reg, INTSTAT_XFER_COMPLETE) == 0)); - - /* Check for any errors from the data phase */ - if (sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg)) - return ERROR; - - if (retries == 0) { - sd_err(("%s: Timeout for xfer complete; State = 0x%x, " - "intr state=0x%x, Errintstatus 0x%x rcnt %d, tcnt %d\n", - __FUNCTION__, sdstd_rreg(sd, SD_PresentState), - int_reg, sdstd_rreg16(sd, SD_ErrorIntrStatus), - sd->r_cnt, sd->t_cnt)); - } - /* Clear the status bits */ - sdstd_wreg16(sd, SD_IntrStatus, SFIELD(int_reg, INTSTAT_CARD_INT, 0)); - } - } - return SUCCESS; -} - -void -sdstd_cmd_getrsp(sdioh_info_t *sd, uint32 *rsp_buffer, int count /* num 32 bit words */) -{ - int rsp_count; - int respaddr = SD_Response0; - - if (count > 4) - count = 4; - - for (rsp_count = 0; rsp_count < count; rsp_count++) { - *rsp_buffer++ = sdstd_rreg(sd, respaddr); - respaddr += 4; - } -} - -static int -sdstd_cmd_issue(sdioh_info_t *sdioh_info, bool use_dma, uint32 cmd, uint32 arg) -{ - uint16 cmd_reg; - int retries; - uint32 cmd_arg; - uint16 xfer_reg = 0; - - - if ((sdioh_info->sd_mode == SDIOH_MODE_SPI) && - ((cmd == SDIOH_CMD_3) || (cmd == SDIOH_CMD_7) || (cmd == SDIOH_CMD_15))) { - sd_err(("%s: Cmd %d is not for SPI\n", __FUNCTION__, cmd)); - return ERROR; - } - - retries = RETRIES_SMALL; - while ((GFIELD(sdstd_rreg(sdioh_info, SD_PresentState), PRES_CMD_INHIBIT)) && --retries) { - if (retries == RETRIES_SMALL) - sd_err(("%s: Waiting for Command Inhibit cmd = %d 0x%x\n", - __FUNCTION__, cmd, sdstd_rreg(sdioh_info, SD_PresentState))); - } - if (!retries) { - sd_err(("%s: Command Inhibit timeout\n", __FUNCTION__)); - if (trap_errs) - ASSERT(0); - return ERROR; - } - - - cmd_reg = 0; - switch (cmd) { - case SDIOH_CMD_0: /* Set Card to Idle State - No Response */ - sd_data(("%s: CMD%d\n", __FUNCTION__, cmd)); - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_NONE); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - break; - - case SDIOH_CMD_3: /* Ask card to send RCA - Response R6 */ - sd_data(("%s: CMD%d\n", __FUNCTION__, cmd)); - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_48); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - break; - - case SDIOH_CMD_5: /* Send Operation condition - Response R4 */ - sd_data(("%s: CMD%d\n", __FUNCTION__, cmd)); - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_48); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - break; - - case SDIOH_CMD_7: /* Select card - Response R1 */ - sd_data(("%s: CMD%d\n", __FUNCTION__, cmd)); - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_48); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - break; - - case SDIOH_CMD_15: /* Set card to inactive state - Response None */ - sd_data(("%s: CMD%d\n", __FUNCTION__, cmd)); - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_NONE); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - break; - - case SDIOH_CMD_52: /* IO R/W Direct (single byte) - Response R5 */ - - sd_data(("%s: CMD52 func(%d) addr(0x%x) %s data(0x%x)\n", - __FUNCTION__, - GFIELD(arg, CMD52_FUNCTION), - GFIELD(arg, CMD52_REG_ADDR), - GFIELD(arg, CMD52_RW_FLAG) ? "W" : "R", - GFIELD(arg, CMD52_DATA))); - - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_48); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - break; - - case SDIOH_CMD_53: /* IO R/W Extended (multiple bytes/blocks) */ - - sd_data(("%s: CMD53 func(%d) addr(0x%x) %s mode(%s) cnt(%d), %s\n", - __FUNCTION__, - GFIELD(arg, CMD53_FUNCTION), - GFIELD(arg, CMD53_REG_ADDR), - GFIELD(arg, CMD53_RW_FLAG) ? "W" : "R", - GFIELD(arg, CMD53_BLK_MODE) ? "Block" : "Byte", - GFIELD(arg, CMD53_BYTE_BLK_CNT), - GFIELD(arg, CMD53_OP_CODE) ? "Incrementing addr" : "Single addr")); - - cmd_arg = arg; - xfer_reg = 0; - - cmd_reg = SFIELD(cmd_reg, CMD_RESP_TYPE, RESP_TYPE_48); - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_DATA_EN, 1); - cmd_reg = SFIELD(cmd_reg, CMD_TYPE, CMD_TYPE_NORMAL); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX, cmd); - - use_dma = USE_DMA(sdioh_info) && GFIELD(cmd_arg, CMD53_BLK_MODE); - - if (GFIELD(cmd_arg, CMD53_BLK_MODE)) { - uint16 blocksize; - uint16 blockcount; - int func; - - ASSERT(sdioh_info->sd_blockmode); - - func = GFIELD(cmd_arg, CMD53_FUNCTION); - blocksize = MIN((int)sdioh_info->data_xfer_count, - sdioh_info->client_block_size[func]); - blockcount = GFIELD(cmd_arg, CMD53_BYTE_BLK_CNT); - - /* data_xfer_cnt is already setup so that for multiblock mode, - * it is the entire buffer length. For non-block or single block, - * it is < 64 bytes - */ - if (use_dma) { - switch (sdioh_info->sd_dma_mode) { - case DMA_MODE_SDMA: - sd_dma(("%s: SDMA: SysAddr reg was 0x%x now 0x%x\n", - __FUNCTION__, sdstd_rreg(sdioh_info, SD_SysAddr), - (uint32)sdioh_info->dma_phys)); - sdstd_wreg(sdioh_info, SD_SysAddr, sdioh_info->dma_phys); - break; - case DMA_MODE_ADMA1: - case DMA_MODE_ADMA2: - sd_dma(("%s: ADMA: Using ADMA\n", __FUNCTION__)); - sd_create_adma_descriptor(sdioh_info, 0, - sdioh_info->dma_phys, blockcount*blocksize, - ADMA2_ATTRIBUTE_VALID | ADMA2_ATTRIBUTE_END | - ADMA2_ATTRIBUTE_INT | ADMA2_ATTRIBUTE_ACT_TRAN); - /* Dump descriptor if DMA debugging is enabled. */ - if (sd_msglevel & SDH_DMA_VAL) { - sd_dump_adma_dscr(sdioh_info); - } - - sdstd_wreg(sdioh_info, SD_ADMA_SysAddr, - sdioh_info->adma2_dscr_phys); - break; - default: - sd_err(("%s: unsupported DMA mode %d.\n", - __FUNCTION__, sdioh_info->sd_dma_mode)); - break; - } - } - - sd_trace(("%s: Setting block count %d, block size %d bytes\n", - __FUNCTION__, blockcount, blocksize)); - sdstd_wreg16(sdioh_info, SD_BlockSize, blocksize); - sdstd_wreg16(sdioh_info, SD_BlockCount, blockcount); - - xfer_reg = SFIELD(xfer_reg, XFER_DMA_ENABLE, use_dma); - - if (sdioh_info->client_block_size[func] != blocksize) - set_client_block_size(sdioh_info, 1, blocksize); - - if (blockcount > 1) { - xfer_reg = SFIELD(xfer_reg, XFER_MULTI_BLOCK, 1); - xfer_reg = SFIELD(xfer_reg, XFER_BLK_COUNT_EN, 1); - xfer_reg = SFIELD(xfer_reg, XFER_CMD_12_EN, 0); - } else { - xfer_reg = SFIELD(xfer_reg, XFER_MULTI_BLOCK, 0); - xfer_reg = SFIELD(xfer_reg, XFER_BLK_COUNT_EN, 0); - xfer_reg = SFIELD(xfer_reg, XFER_CMD_12_EN, 0); - } - - if (GFIELD(cmd_arg, CMD53_RW_FLAG) == SDIOH_XFER_TYPE_READ) - xfer_reg = SFIELD(xfer_reg, XFER_DATA_DIRECTION, 1); - else - xfer_reg = SFIELD(xfer_reg, XFER_DATA_DIRECTION, 0); - - retries = RETRIES_SMALL; - while (GFIELD(sdstd_rreg(sdioh_info, SD_PresentState), - PRES_DAT_INHIBIT) && --retries) - sd_err(("%s: Waiting for Data Inhibit cmd = %d\n", - __FUNCTION__, cmd)); - if (!retries) { - sd_err(("%s: Data Inhibit timeout\n", __FUNCTION__)); - if (trap_errs) - ASSERT(0); - return ERROR; - } - sdstd_wreg16(sdioh_info, SD_TransferMode, xfer_reg); - - } else { /* Non block mode */ - uint16 bytes = GFIELD(cmd_arg, CMD53_BYTE_BLK_CNT); - /* The byte/block count field only has 9 bits, - * so, to do a 512-byte bytemode transfer, this - * field will contain 0, but we need to tell the - * controller we're transferring 512 bytes. - */ - if (bytes == 0) bytes = 512; - - if (use_dma) - sdstd_wreg(sdioh_info, SD_SysAddr, sdioh_info->dma_phys); - - /* PCI: Transfer Mode register 0x0c */ - xfer_reg = SFIELD(xfer_reg, XFER_DMA_ENABLE, bytes <= 4 ? 0 : use_dma); - xfer_reg = SFIELD(xfer_reg, XFER_CMD_12_EN, 0); - if (GFIELD(cmd_arg, CMD53_RW_FLAG) == SDIOH_XFER_TYPE_READ) - xfer_reg = SFIELD(xfer_reg, XFER_DATA_DIRECTION, 1); - else - xfer_reg = SFIELD(xfer_reg, XFER_DATA_DIRECTION, 0); - /* See table 2-8 Host Controller spec ver 1.00 */ - xfer_reg = SFIELD(xfer_reg, XFER_BLK_COUNT_EN, 0); /* Dont care */ - xfer_reg = SFIELD(xfer_reg, XFER_MULTI_BLOCK, 0); - - sdstd_wreg16(sdioh_info, SD_BlockSize, bytes); - - sdstd_wreg16(sdioh_info, SD_BlockCount, 1); - - retries = RETRIES_SMALL; - while (GFIELD(sdstd_rreg(sdioh_info, SD_PresentState), - PRES_DAT_INHIBIT) && --retries) - sd_err(("%s: Waiting for Data Inhibit cmd = %d\n", - __FUNCTION__, cmd)); - if (!retries) { - sd_err(("%s: Data Inhibit timeout\n", __FUNCTION__)); - if (trap_errs) - ASSERT(0); - return ERROR; - } - sdstd_wreg16(sdioh_info, SD_TransferMode, xfer_reg); - } - break; - - default: - sd_err(("%s: Unknown command\n", __FUNCTION__)); - return ERROR; - } - - if (sdioh_info->sd_mode == SDIOH_MODE_SPI) { - cmd_reg = SFIELD(cmd_reg, CMD_CRC_EN, 0); - cmd_reg = SFIELD(cmd_reg, CMD_INDEX_EN, 0); - } - - /* Setup and issue the SDIO command */ - sdstd_wreg(sdioh_info, SD_Arg0, arg); - sdstd_wreg16(sdioh_info, SD_Command, cmd_reg); - - /* If we are in polled mode, wait for the command to complete. - * In interrupt mode, return immediately. The calling function will - * know that the command has completed when the CMDATDONE interrupt - * is asserted - */ - if (sdioh_info->polled_mode) { - uint16 int_reg = 0; - int retries = RETRIES_LARGE; - - do { - int_reg = sdstd_rreg16(sdioh_info, SD_IntrStatus); - } while (--retries && - (GFIELD(int_reg, INTSTAT_ERROR_INT) == 0) && - (GFIELD(int_reg, INTSTAT_CMD_COMPLETE) == 0)); - - if (!retries) { - sd_err(("%s: CMD_COMPLETE timeout: intrStatus: 0x%x " - "error stat 0x%x state 0x%x\n", - __FUNCTION__, int_reg, - sdstd_rreg16(sdioh_info, SD_ErrorIntrStatus), - sdstd_rreg(sdioh_info, SD_PresentState))); - - /* Attempt to reset CMD line when we get a CMD timeout */ - sdstd_wreg8(sdioh_info, SD_SoftwareReset, SFIELD(0, SW_RESET_CMD, 1)); - retries = RETRIES_LARGE; - do { - sd_trace(("%s: waiting for CMD line reset\n", __FUNCTION__)); - } while ((GFIELD(sdstd_rreg8(sdioh_info, SD_SoftwareReset), - SW_RESET_CMD)) && retries--); - - if (!retries) { - sd_err(("%s: Timeout waiting for CMD line reset\n", __FUNCTION__)); - } - - if (trap_errs) - ASSERT(0); - return (ERROR); - } - - /* Clear Command Complete interrupt */ - int_reg = SFIELD(0, INTSTAT_CMD_COMPLETE, 1); - sdstd_wreg16(sdioh_info, SD_IntrStatus, int_reg); - - /* Check for Errors */ - if (sdstd_check_errs(sdioh_info, cmd, arg)) { - if (trap_errs) - ASSERT(0); - return ERROR; - } - } - return SUCCESS; -} - - -static int -sdstd_card_buf(sdioh_info_t *sd, int rw, int func, bool fifo, uint32 addr, int nbytes, uint32 *data) -{ - int status; - uint32 cmd_arg; - uint32 rsp5; - uint16 int_reg, int_bit; - uint flags; - int num_blocks, blocksize; - bool local_blockmode, local_dma; - bool read = rw == SDIOH_READ ? 1 : 0; - bool yield = FALSE; - - ASSERT(nbytes); - - cmd_arg = 0; - - sd_data(("%s: %s 53 addr 0x%x, len %d bytes, r_cnt %d t_cnt %d\n", - __FUNCTION__, read ? "Rd" : "Wr", addr, nbytes, sd->r_cnt, sd->t_cnt)); - - if (read) sd->r_cnt++; else sd->t_cnt++; - - local_blockmode = sd->sd_blockmode; - local_dma = USE_DMA(sd); - - /* Don't bother with block mode on small xfers */ - if (nbytes < sd->client_block_size[func]) { - sd_data(("setting local blockmode to false: nbytes (%d) != block_size (%d)\n", - nbytes, sd->client_block_size[func])); - local_blockmode = FALSE; - local_dma = FALSE; - } - - if (local_blockmode) { - blocksize = MIN(sd->client_block_size[func], nbytes); - num_blocks = nbytes/blocksize; - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, num_blocks); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 1); - } else { - num_blocks = 1; - blocksize = nbytes; - cmd_arg = SFIELD(cmd_arg, CMD53_BYTE_BLK_CNT, nbytes); - cmd_arg = SFIELD(cmd_arg, CMD53_BLK_MODE, 0); - } - - if (local_dma && !read) { - bcopy(data, sd->dma_buf, nbytes); - sd_sync_dma(sd, read, nbytes); - } - - if (fifo) - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 0); - else - cmd_arg = SFIELD(cmd_arg, CMD53_OP_CODE, 1); - - cmd_arg = SFIELD(cmd_arg, CMD53_FUNCTION, func); - cmd_arg = SFIELD(cmd_arg, CMD53_REG_ADDR, addr); - if (read) - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_READ); - else - cmd_arg = SFIELD(cmd_arg, CMD53_RW_FLAG, SDIOH_XFER_TYPE_WRITE); - - sd->data_xfer_count = nbytes; - - /* sdstd_cmd_issue() returns with the command complete bit - * in the ISR already cleared - */ - if ((status = sdstd_cmd_issue(sd, local_dma, SDIOH_CMD_53, cmd_arg)) != SUCCESS) { - sd_err(("%s: cmd_issue failed for %s\n", __FUNCTION__, (read ? "read" : "write"))); - return status; - } - - sdstd_cmd_getrsp(sd, &rsp5, 1); - - if ((flags = GFIELD(rsp5, RSP5_FLAGS)) != 0x10) { - sd_err(("%s: Rsp5: nbytes %d, dma %d blockmode %d, read %d " - "numblocks %d, blocksize %d\n", - __FUNCTION__, nbytes, local_dma, local_dma, read, num_blocks, blocksize)); - - if (flags & 1) - sd_err(("%s: rsp5: Command not accepted: arg out of range 0x%x, " - "bytes %d dma %d\n", - __FUNCTION__, flags, GFIELD(cmd_arg, CMD53_BYTE_BLK_CNT), - GFIELD(cmd_arg, CMD53_BLK_MODE))); - if (flags & 0x8) - sd_err(("%s: Rsp5: General Error\n", __FUNCTION__)); - - sd_err(("%s: rsp5 flags = 0x%x, expecting 0x10 returning error\n", - __FUNCTION__, flags)); - if (trap_errs) - ASSERT(0); - return ERROR; - } - - if (GFIELD(rsp5, RSP5_STUFF)) - sd_err(("%s: rsp5 stuff is 0x%x: expecting 0\n", - __FUNCTION__, GFIELD(rsp5, RSP5_STUFF))); - -#ifdef BCMSDYIELD - yield = sd_yieldcpu && ((uint)nbytes >= sd_minyield); -#endif - - if (!local_dma) { - int bytes, i; - uint32 tmp; - for (i = 0; i < num_blocks; i++) { - int words; - - /* Decide which status bit we're waiting for */ - if (read) - int_bit = SFIELD(0, INTSTAT_BUF_READ_READY, 1); - else - int_bit = SFIELD(0, INTSTAT_BUF_WRITE_READY, 1); - - /* If not on, wait for it (or for xfer error) */ - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - if (!(int_reg & int_bit)) - int_reg = sdstd_waitbits(sd, int_bit, ERRINT_TRANSFER_ERRS, yield); - - /* Confirm we got the bit w/o error */ - if (!(int_reg & int_bit) || GFIELD(int_reg, INTSTAT_ERROR_INT)) { - sd_err(("%s: Error or timeout for Buf_%s_Ready: intStat: 0x%x " - "errint: 0x%x PresentState 0x%x\n", - __FUNCTION__, read ? "Read" : "Write", int_reg, - sdstd_rreg16(sd, SD_ErrorIntrStatus), - sdstd_rreg(sd, SD_PresentState))); - sdstd_dumpregs(sd); - sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg); - return (ERROR); - } - - /* Clear Buf Ready bit */ - sdstd_wreg16(sd, SD_IntrStatus, int_bit); - - /* At this point we have Buffer Ready, write the data 4 bytes at a time */ - for (words = blocksize/4; words; words--) { - if (read) - *data = sdstd_rreg(sd, SD_BufferDataPort0); - else - sdstd_wreg(sd, SD_BufferDataPort0, *data); - data++; - } - - /* Handle < 4 bytes. wlc_pio.c currently (as of 12/20/05) truncates buflen - * to be evenly divisable by 4. However dongle passes arbitrary lengths, - * so handle it here - */ - bytes = blocksize % 4; - - /* If no leftover bytes, go to next block */ - if (!bytes) - continue; - - switch (bytes) { - case 1: - /* R/W 8 bits */ - if (read) - *(data++) = (uint32)(sdstd_rreg8(sd, SD_BufferDataPort0)); - else - sdstd_wreg8(sd, SD_BufferDataPort0, - (uint8)(*(data++) & 0xff)); - break; - case 2: - /* R/W 16 bits */ - if (read) - *(data++) = (uint32)sdstd_rreg16(sd, SD_BufferDataPort0); - else - sdstd_wreg16(sd, SD_BufferDataPort0, (uint16)(*(data++))); - break; - case 3: - /* R/W 24 bits: - * SD_BufferDataPort0[0-15] | SD_BufferDataPort1[16-23] - */ - if (read) { - tmp = (uint32)sdstd_rreg16(sd, SD_BufferDataPort0); - tmp |= ((uint32)(sdstd_rreg8(sd, - SD_BufferDataPort1)) << 16); - *(data++) = tmp; - } else { - tmp = *(data++); - sdstd_wreg16(sd, SD_BufferDataPort0, (uint16)tmp & 0xffff); - sdstd_wreg8(sd, SD_BufferDataPort1, - (uint8)((tmp >> 16) & 0xff)); - } - break; - default: - sd_err(("%s: Unexpected bytes leftover %d\n", - __FUNCTION__, bytes)); - ASSERT(0); - break; - } - } - } /* End PIO processing */ - - /* Wait for Transfer Complete or Transfer Error */ - int_bit = SFIELD(0, INTSTAT_XFER_COMPLETE, 1); - - /* If not on, wait for it (or for xfer error) */ - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - if (!(int_reg & int_bit)) - int_reg = sdstd_waitbits(sd, int_bit, ERRINT_TRANSFER_ERRS, yield); - - /* Check for any errors from the data phase */ - if (sdstd_check_errs(sd, SDIOH_CMD_53, cmd_arg)) - return ERROR; - - /* May have gotten a software timeout if not blocking? */ - int_reg = sdstd_rreg16(sd, SD_IntrStatus); - if (!(int_reg & int_bit)) { - sd_err(("%s: Error or Timeout for xfer complete; %s, dma %d, State 0x%08x, " - "intr 0x%04x, Err 0x%04x, len = %d, rcnt %d, tcnt %d\n", - __FUNCTION__, read ? "R" : "W", local_dma, - sdstd_rreg(sd, SD_PresentState), int_reg, - sdstd_rreg16(sd, SD_ErrorIntrStatus), nbytes, - sd->r_cnt, sd->t_cnt)); - sdstd_dumpregs(sd); - return ERROR; - } - - /* Clear the status bits */ - int_reg = int_bit; - if (local_dma) { - /* DMA Complete */ - /* Reads in particular don't have DMA_COMPLETE set */ - int_reg = SFIELD(int_reg, INTSTAT_DMA_INT, 1); - } - sdstd_wreg16(sd, SD_IntrStatus, int_reg); - - /* Fetch data */ - if (local_dma && read) { - sd_sync_dma(sd, read, nbytes); - bcopy(sd->dma_buf, data, nbytes); - } - return SUCCESS; -} - -static int -set_client_block_size(sdioh_info_t *sd, int func, int block_size) -{ - int base; - int err = 0; - - - sd_err(("%s: Setting block size %d, func %d\n", __FUNCTION__, block_size, func)); - sd->client_block_size[func] = block_size; - - /* Set the block size in the SDIO Card register */ - base = func * SDIOD_FBR_SIZE; - err = sdstd_card_regwrite(sd, 0, base+SDIOD_CCCR_BLKSIZE_0, 1, block_size & 0xff); - if (!err) { - err = sdstd_card_regwrite(sd, 0, base+SDIOD_CCCR_BLKSIZE_1, 1, - (block_size >> 8) & 0xff); - } - - /* Do not set the block size in the SDIO Host register, that - * is func dependent and will get done on an individual - * transaction basis - */ - - return (err ? BCME_SDIO_ERROR : 0); -} - -/* Reset and re-initialize the device */ -int sdioh_sdio_reset(sdioh_info_t *si) -{ - uint8 hreg; - - /* Reset the attached device (use slower clock for safety) */ - sdstd_start_clock(si, 128); - sdstd_reset(si, 0, 1); - - /* Reset portions of the host state accordingly */ - hreg = sdstd_rreg8(si, SD_HostCntrl); - hreg = SFIELD(hreg, HOST_HI_SPEED_EN, 0); - hreg = SFIELD(hreg, HOST_DATA_WIDTH, 0); - si->sd_mode = SDIOH_MODE_SD1; - - /* Reinitialize the card */ - si->card_init_done = FALSE; - return sdstd_client_init(si); -} - - -static void -sd_map_dma(sdioh_info_t * sd) -{ - - void *va; - - if ((va = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE, - &sd->dma_start_phys, 0x12, 12)) == NULL) { - sd->sd_dma_mode = DMA_MODE_NONE; - sd->dma_start_buf = 0; - sd->dma_buf = (void *)0; - sd->dma_phys = 0; - sd->alloced_dma_size = SD_PAGE; - sd_err(("%s: DMA_ALLOC failed. Disabling DMA support.\n", __FUNCTION__)); - } else { - sd->dma_start_buf = va; - sd->dma_buf = (void *)ROUNDUP((uintptr)va, SD_PAGE); - sd->dma_phys = ROUNDUP((sd->dma_start_phys), SD_PAGE); - sd->alloced_dma_size = SD_PAGE; - sd_err(("%s: Mapped DMA Buffer %dbytes @virt/phys: %p/0x%lx\n", - __FUNCTION__, sd->alloced_dma_size, sd->dma_buf, sd->dma_phys)); - sd_fill_dma_data_buf(sd, 0xA5); - } - - if ((va = DMA_ALLOC_CONSISTENT(sd->osh, SD_PAGE, - &sd->adma2_dscr_start_phys, 0x12, 12)) == NULL) { - sd->sd_dma_mode = DMA_MODE_NONE; - sd->adma2_dscr_start_buf = 0; - sd->adma2_dscr_buf = (void *)0; - sd->adma2_dscr_phys = 0; - sd->alloced_adma2_dscr_size = 0; - sd_err(("%s: DMA_ALLOC failed for descriptor buffer. " - "Disabling DMA support.\n", __FUNCTION__)); - } else { - sd->adma2_dscr_start_buf = va; - sd->adma2_dscr_buf = (void *)ROUNDUP((uintptr)va, SD_PAGE); - sd->adma2_dscr_phys = ROUNDUP((sd->adma2_dscr_start_phys), SD_PAGE); - sd->alloced_adma2_dscr_size = SD_PAGE; - } - - sd_err(("%s: Mapped ADMA2 Descriptor Buffer %dbytes @virt/phys: %p/0x%lx\n", - __FUNCTION__, sd->alloced_adma2_dscr_size, sd->adma2_dscr_buf, - sd->adma2_dscr_phys)); - sd_clear_adma_dscr_buf(sd); -} - -static void -sd_unmap_dma(sdioh_info_t * sd) -{ - if (sd->dma_start_buf) { - DMA_FREE_CONSISTENT(sd->osh, sd->dma_start_buf, sd->alloced_dma_size, - sd->dma_start_phys, 0x12); - } - - if (sd->adma2_dscr_start_buf) { - DMA_FREE_CONSISTENT(sd->osh, sd->adma2_dscr_start_buf, sd->alloced_adma2_dscr_size, - sd->adma2_dscr_start_phys, 0x12); - } -} - -static void sd_clear_adma_dscr_buf(sdioh_info_t *sd) -{ - bzero((char *)sd->adma2_dscr_buf, SD_PAGE); - sd_dump_adma_dscr(sd); -} - -static void sd_fill_dma_data_buf(sdioh_info_t *sd, uint8 data) -{ - memset((char *)sd->dma_buf, data, SD_PAGE); -} - - -static void sd_create_adma_descriptor(sdioh_info_t *sd, uint32 index, - uint32 addr_phys, uint16 length, uint16 flags) -{ - adma2_dscr_32b_t *adma2_dscr_table; - adma1_dscr_t *adma1_dscr_table; - - adma2_dscr_table = sd->adma2_dscr_buf; - adma1_dscr_table = sd->adma2_dscr_buf; - - switch (sd->sd_dma_mode) { - case DMA_MODE_ADMA2: - sd_dma(("%s: creating ADMA2 descriptor for index %d\n", - __FUNCTION__, index)); - - adma2_dscr_table[index].phys_addr = addr_phys; - adma2_dscr_table[index].len_attr = length << 16; - adma2_dscr_table[index].len_attr |= flags; - break; - case DMA_MODE_ADMA1: - /* ADMA1 requires two descriptors, one for len - * and the other for data transfer - */ - index <<= 1; - - sd_dma(("%s: creating ADMA1 descriptor for index %d\n", - __FUNCTION__, index)); - - adma1_dscr_table[index].phys_addr_attr = length << 12; - adma1_dscr_table[index].phys_addr_attr |= (ADMA1_ATTRIBUTE_ACT_SET | - ADMA2_ATTRIBUTE_VALID); - adma1_dscr_table[index+1].phys_addr_attr = addr_phys & 0xFFFFF000; - adma1_dscr_table[index+1].phys_addr_attr |= (flags & 0x3f); - break; - default: - sd_err(("%s: cannot create ADMA descriptor for DMA mode %d\n", - __FUNCTION__, sd->sd_dma_mode)); - break; - } -} - - -static void sd_dump_adma_dscr(sdioh_info_t *sd) -{ - adma2_dscr_32b_t *adma2_dscr_table; - adma1_dscr_t *adma1_dscr_table; - uint32 i = 0; - uint16 flags; - char flags_str[32]; - - ASSERT(sd->adma2_dscr_buf != NULL); - - adma2_dscr_table = sd->adma2_dscr_buf; - adma1_dscr_table = sd->adma2_dscr_buf; - - switch (sd->sd_dma_mode) { - case DMA_MODE_ADMA2: - sd_err(("ADMA2 Descriptor Table (%dbytes) @virt/phys: %p/0x%lx\n", - SD_PAGE, sd->adma2_dscr_buf, sd->adma2_dscr_phys)); - sd_err((" #[Descr VA ] Buffer PA | Len | Flags (5:4 2 1 0)" - " |\n")); - while (adma2_dscr_table->len_attr & ADMA2_ATTRIBUTE_VALID) { - flags = adma2_dscr_table->len_attr & 0xFFFF; - sprintf(flags_str, "%s%s%s%s", - ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_LINK) ? "LINK " : - ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_TRAN) ? "TRAN " : - ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_NOP) ? "NOP " : "RSV ", - (flags & ADMA2_ATTRIBUTE_INT ? "INT " : " "), - (flags & ADMA2_ATTRIBUTE_END ? "END " : " "), - (flags & ADMA2_ATTRIBUTE_VALID ? "VALID" : "")); - sd_err(("%2d[0x%p]: 0x%08x | 0x%04x | 0x%04x (%s) |\n", - i, adma2_dscr_table, adma2_dscr_table->phys_addr, - adma2_dscr_table->len_attr >> 16, flags, flags_str)); - i++; - - /* Follow LINK descriptors or skip to next. */ - if ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_LINK) { - adma2_dscr_table = phys_to_virt( - adma2_dscr_table->phys_addr); - } else { - adma2_dscr_table++; - } - - } - break; - case DMA_MODE_ADMA1: - sd_err(("ADMA1 Descriptor Table (%dbytes) @virt/phys: %p/0x%lx\n", - SD_PAGE, sd->adma2_dscr_buf, sd->adma2_dscr_phys)); - sd_err((" #[Descr VA ] Buffer PA | Flags (5:4 2 1 0) |\n")); - - for (i = 0; adma1_dscr_table->phys_addr_attr & ADMA2_ATTRIBUTE_VALID; i++) { - flags = adma1_dscr_table->phys_addr_attr & 0x3F; - sprintf(flags_str, "%s%s%s%s", - ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_LINK) ? "LINK " : - ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_TRAN) ? "TRAN " : - ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_NOP) ? "NOP " : "SET ", - (flags & ADMA2_ATTRIBUTE_INT ? "INT " : " "), - (flags & ADMA2_ATTRIBUTE_END ? "END " : " "), - (flags & ADMA2_ATTRIBUTE_VALID ? "VALID" : "")); - sd_err(("%2d[0x%p]: 0x%08x | 0x%04x | (%s) |\n", - i, adma1_dscr_table, - adma1_dscr_table->phys_addr_attr & 0xFFFFF000, - flags, flags_str)); - - /* Follow LINK descriptors or skip to next. */ - if ((flags & ADMA2_ATTRIBUTE_ACT_LINK) == - ADMA2_ATTRIBUTE_ACT_LINK) { - adma1_dscr_table = phys_to_virt( - adma1_dscr_table->phys_addr_attr & 0xFFFFF000); - } else { - adma1_dscr_table++; - } - } - break; - default: - sd_err(("Unknown DMA Descriptor Table Format.\n")); - break; - } -} - -static void sdstd_dumpregs(sdioh_info_t *sd) -{ - sd_err(("IntrStatus: 0x%04x ErrorIntrStatus 0x%04x\n", - sdstd_rreg16(sd, SD_IntrStatus), - sdstd_rreg16(sd, SD_ErrorIntrStatus))); - sd_err(("IntrStatusEnable: 0x%04x ErrorIntrStatusEnable 0x%04x\n", - sdstd_rreg16(sd, SD_IntrStatusEnable), - sdstd_rreg16(sd, SD_ErrorIntrStatusEnable))); - sd_err(("IntrSignalEnable: 0x%04x ErrorIntrSignalEnable 0x%04x\n", - sdstd_rreg16(sd, SD_IntrSignalEnable), - sdstd_rreg16(sd, SD_ErrorIntrSignalEnable))); -} diff --git a/drivers/net/wireless/bcm4329/bcmsdstd_linux.c b/drivers/net/wireless/bcm4329/bcmsdstd_linux.c deleted file mode 100644 index ad6d6603fccd..000000000000 --- a/drivers/net/wireless/bcm4329/bcmsdstd_linux.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * 'Standard' SDIO HOST CONTROLLER driver - linux portion - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdstd_linux.c,v 1.11.18.2 2008/05/28 18:36:56 Exp $ - */ - -#include -#include -#include -#include /* SDIO Specs */ -#include /* bcmsdh to/from specific controller APIs */ -#include /* to get msglevel bit values */ - -#include /* request_irq() */ - -#include - -struct sdos_info { - sdioh_info_t *sd; - spinlock_t lock; - wait_queue_head_t intr_wait_queue; -}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define BLOCKABLE() (!in_atomic()) -#else -#define BLOCKABLE() (!in_interrupt()) -#endif - -/* Interrupt handler */ -static irqreturn_t -sdstd_isr(int irq, void *dev_id -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20) -, struct pt_regs *ptregs -#endif -) -{ - sdioh_info_t *sd; - struct sdos_info *sdos; - bool ours; - - sd = (sdioh_info_t *)dev_id; - - if (!sd->card_init_done) { - sd_err(("%s: Hey Bogus intr...not even initted: irq %d\n", __FUNCTION__, irq)); - return IRQ_RETVAL(FALSE); - } else { - ours = check_client_intr(sd); - - /* For local interrupts, wake the waiting process */ - if (ours && sd->got_hcint) { - sd_trace(("INTR->WAKE\n")); - sdos = (struct sdos_info *)sd->sdos_info; - wake_up_interruptible(&sdos->intr_wait_queue); - } - return IRQ_RETVAL(ours); - } -} - -/* Register with Linux for interrupts */ -int -sdstd_register_irq(sdioh_info_t *sd, uint irq) -{ - sd_trace(("Entering %s: irq == %d\n", __FUNCTION__, irq)); - if (request_irq(irq, sdstd_isr, IRQF_SHARED, "bcmsdstd", sd) < 0) { - sd_err(("%s: request_irq() failed\n", __FUNCTION__)); - return ERROR; - } - return SUCCESS; -} - -/* Free Linux irq */ -void -sdstd_free_irq(uint irq, sdioh_info_t *sd) -{ - free_irq(irq, sd); -} - -/* Map Host controller registers */ - -uint32 * -sdstd_reg_map(osl_t *osh, int32 addr, int size) -{ - return (uint32 *)REG_MAP(addr, size); -} - -void -sdstd_reg_unmap(osl_t *osh, int32 addr, int size) -{ - REG_UNMAP((void*)(uintptr)addr); -} - -int -sdstd_osinit(sdioh_info_t *sd) -{ - struct sdos_info *sdos; - - sdos = (struct sdos_info*)MALLOC(sd->osh, sizeof(struct sdos_info)); - sd->sdos_info = (void*)sdos; - if (sdos == NULL) - return BCME_NOMEM; - - sdos->sd = sd; - spin_lock_init(&sdos->lock); - init_waitqueue_head(&sdos->intr_wait_queue); - return BCME_OK; -} - -void -sdstd_osfree(sdioh_info_t *sd) -{ - struct sdos_info *sdos; - ASSERT(sd && sd->sdos_info); - - sdos = (struct sdos_info *)sd->sdos_info; - MFREE(sd->osh, sdos, sizeof(struct sdos_info)); -} - -/* Interrupt enable/disable */ -SDIOH_API_RC -sdioh_interrupt_set(sdioh_info_t *sd, bool enable) -{ - ulong flags; - struct sdos_info *sdos; - - sd_trace(("%s: %s\n", __FUNCTION__, enable ? "Enabling" : "Disabling")); - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - - if (!(sd->host_init_done && sd->card_init_done)) { - sd_err(("%s: Card & Host are not initted - bailing\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } - - if (enable && !(sd->intr_handler && sd->intr_handler_arg)) { - sd_err(("%s: no handler registered, will not enable\n", __FUNCTION__)); - return SDIOH_API_RC_FAIL; - } - - /* Ensure atomicity for enable/disable calls */ - spin_lock_irqsave(&sdos->lock, flags); - - sd->client_intr_enabled = enable; - if (enable && !sd->lockcount) - sdstd_devintr_on(sd); - else - sdstd_devintr_off(sd); - - spin_unlock_irqrestore(&sdos->lock, flags); - - return SDIOH_API_RC_SUCCESS; -} - -/* Protect against reentrancy (disable device interrupts while executing) */ -void -sdstd_lock(sdioh_info_t *sd) -{ - ulong flags; - struct sdos_info *sdos; - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - - sd_trace(("%s: %d\n", __FUNCTION__, sd->lockcount)); - - spin_lock_irqsave(&sdos->lock, flags); - if (sd->lockcount) { - sd_err(("%s: Already locked!\n", __FUNCTION__)); - ASSERT(sd->lockcount == 0); - } - sdstd_devintr_off(sd); - sd->lockcount++; - spin_unlock_irqrestore(&sdos->lock, flags); -} - -/* Enable client interrupt */ -void -sdstd_unlock(sdioh_info_t *sd) -{ - ulong flags; - struct sdos_info *sdos; - - sd_trace(("%s: %d, %d\n", __FUNCTION__, sd->lockcount, sd->client_intr_enabled)); - ASSERT(sd->lockcount > 0); - - sdos = (struct sdos_info *)sd->sdos_info; - ASSERT(sdos); - - spin_lock_irqsave(&sdos->lock, flags); - if (--sd->lockcount == 0 && sd->client_intr_enabled) { - sdstd_devintr_on(sd); - } - spin_unlock_irqrestore(&sdos->lock, flags); -} - -uint16 -sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield) -{ - struct sdos_info *sdos; - - sdos = (struct sdos_info *)sd->sdos_info; - -#ifndef BCMSDYIELD - ASSERT(!yield); -#endif - sd_trace(("%s: int 0x%02x err 0x%02x yield %d canblock %d\n", - __FUNCTION__, norm, err, yield, BLOCKABLE())); - - /* Clear the "interrupt happened" flag and last intrstatus */ - sd->got_hcint = FALSE; - sd->last_intrstatus = 0; - -#ifdef BCMSDYIELD - if (yield && BLOCKABLE()) { - /* Enable interrupts, wait for the indication, then disable */ - sdstd_intrs_on(sd, norm, err); - wait_event_interruptible(sdos->intr_wait_queue, (sd->got_hcint)); - sdstd_intrs_off(sd, norm, err); - } else -#endif /* BCMSDYIELD */ - { - sdstd_spinbits(sd, norm, err); - } - - sd_trace(("%s: last_intrstatus 0x%04x\n", __FUNCTION__, sd->last_intrstatus)); - - return sd->last_intrstatus; -} diff --git a/drivers/net/wireless/bcm4329/bcmutils.c b/drivers/net/wireless/bcm4329/bcmutils.c deleted file mode 100644 index 43c04ee92f38..000000000000 --- a/drivers/net/wireless/bcm4329/bcmutils.c +++ /dev/null @@ -1,1838 +0,0 @@ -/* - * Driver O/S-independent utility routines - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.c,v 1.210.4.5.2.4.6.19 2010/04/26 06:05:25 Exp $ - */ - -#include -#include -#include -#include -#ifdef BCMDRIVER -#include -#include -#else -#include -#include -/* This case for external supplicant use */ -#if defined(BCMEXTSUP) -#include -#endif - -#endif /* BCMDRIVER */ -#include -#include -#include -#include -#include -#include -#include - - -#ifdef BCMDRIVER - - -/* copy a pkt buffer chain into a buffer */ -uint -pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf) -{ - uint n, ret = 0; - - if (len < 0) - len = 4096; /* "infinite" */ - - /* skip 'offset' bytes */ - for (; p && offset; p = PKTNEXT(osh, p)) { - if (offset < (uint)PKTLEN(osh, p)) - break; - offset -= PKTLEN(osh, p); - } - - if (!p) - return 0; - - /* copy the data */ - for (; p && len; p = PKTNEXT(osh, p)) { - n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); - bcopy(PKTDATA(osh, p) + offset, buf, n); - buf += n; - len -= n; - ret += n; - offset = 0; - } - - return ret; -} - -/* copy a buffer into a pkt buffer chain */ -uint -pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf) -{ - uint n, ret = 0; - - /* skip 'offset' bytes */ - for (; p && offset; p = PKTNEXT(osh, p)) { - if (offset < (uint)PKTLEN(osh, p)) - break; - offset -= PKTLEN(osh, p); - } - - if (!p) - return 0; - - /* copy the data */ - for (; p && len; p = PKTNEXT(osh, p)) { - n = MIN((uint)PKTLEN(osh, p) - offset, (uint)len); - bcopy(buf, PKTDATA(osh, p) + offset, n); - buf += n; - len -= n; - ret += n; - offset = 0; - } - - return ret; -} - - - -/* return total length of buffer chain */ -uint -pkttotlen(osl_t *osh, void *p) -{ - uint total; - - total = 0; - for (; p; p = PKTNEXT(osh, p)) - total += PKTLEN(osh, p); - return (total); -} - -/* return the last buffer of chained pkt */ -void * -pktlast(osl_t *osh, void *p) -{ - for (; PKTNEXT(osh, p); p = PKTNEXT(osh, p)) - ; - - return (p); -} - -/* count segments of a chained packet */ -uint -pktsegcnt(osl_t *osh, void *p) -{ - uint cnt; - - for (cnt = 0; p; p = PKTNEXT(osh, p)) - cnt++; - - return cnt; -} - - -/* - * osl multiple-precedence packet queue - * hi_prec is always >= the number of the highest non-empty precedence - */ -void * -pktq_penq(struct pktq *pq, int prec, void *p) -{ - struct pktq_prec *q; - - ASSERT(prec >= 0 && prec < pq->num_prec); - ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ - - ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); - - q = &pq->q[prec]; - - if (q->head) - PKTSETLINK(q->tail, p); - else - q->head = p; - - q->tail = p; - q->len++; - - pq->len++; - - if (pq->hi_prec < prec) - pq->hi_prec = (uint8)prec; - - return p; -} - -void * -pktq_penq_head(struct pktq *pq, int prec, void *p) -{ - struct pktq_prec *q; - - ASSERT(prec >= 0 && prec < pq->num_prec); - ASSERT(PKTLINK(p) == NULL); /* queueing chains not allowed */ - - ASSERT(!pktq_full(pq)); - ASSERT(!pktq_pfull(pq, prec)); - - q = &pq->q[prec]; - - if (q->head == NULL) - q->tail = p; - - PKTSETLINK(p, q->head); - q->head = p; - q->len++; - - pq->len++; - - if (pq->hi_prec < prec) - pq->hi_prec = (uint8)prec; - - return p; -} - -void * -pktq_pdeq(struct pktq *pq, int prec) -{ - struct pktq_prec *q; - void *p; - - ASSERT(prec >= 0 && prec < pq->num_prec); - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - return NULL; - - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; - - q->len--; - - pq->len--; - - PKTSETLINK(p, NULL); - - return p; -} - -void * -pktq_pdeq_tail(struct pktq *pq, int prec) -{ - struct pktq_prec *q; - void *p, *prev; - - ASSERT(prec >= 0 && prec < pq->num_prec); - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - return NULL; - - for (prev = NULL; p != q->tail; p = PKTLINK(p)) - prev = p; - - if (prev) - PKTSETLINK(prev, NULL); - else - q->head = NULL; - - q->tail = prev; - q->len--; - - pq->len--; - - return p; -} - -void -pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir) -{ - struct pktq_prec *q; - void *p; - - q = &pq->q[prec]; - p = q->head; - while (p) { - q->head = PKTLINK(p); - PKTSETLINK(p, NULL); - PKTFREE(osh, p, dir); - q->len--; - pq->len--; - p = q->head; - } - ASSERT(q->len == 0); - q->tail = NULL; -} - -bool -pktq_pdel(struct pktq *pq, void *pktbuf, int prec) -{ - struct pktq_prec *q; - void *p; - - ASSERT(prec >= 0 && prec < pq->num_prec); - - if (!pktbuf) - return FALSE; - - q = &pq->q[prec]; - - if (q->head == pktbuf) { - if ((q->head = PKTLINK(pktbuf)) == NULL) - q->tail = NULL; - } else { - for (p = q->head; p && PKTLINK(p) != pktbuf; p = PKTLINK(p)) - ; - if (p == NULL) - return FALSE; - - PKTSETLINK(p, PKTLINK(pktbuf)); - if (q->tail == pktbuf) - q->tail = p; - } - - q->len--; - pq->len--; - PKTSETLINK(pktbuf, NULL); - return TRUE; -} - -void -pktq_init(struct pktq *pq, int num_prec, int max_len) -{ - int prec; - - ASSERT(num_prec > 0 && num_prec <= PKTQ_MAX_PREC); - - /* pq is variable size; only zero out what's requested */ - bzero(pq, OFFSETOF(struct pktq, q) + (sizeof(struct pktq_prec) * num_prec)); - - pq->num_prec = (uint16)num_prec; - - pq->max = (uint16)max_len; - - for (prec = 0; prec < num_prec; prec++) - pq->q[prec].max = pq->max; -} - -void * -pktq_deq(struct pktq *pq, int *prec_out) -{ - struct pktq_prec *q; - void *p; - int prec; - - if (pq->len == 0) - return NULL; - - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) - pq->hi_prec--; - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - return NULL; - - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; - - q->len--; - - pq->len--; - - if (prec_out) - *prec_out = prec; - - PKTSETLINK(p, NULL); - - return p; -} - -void * -pktq_deq_tail(struct pktq *pq, int *prec_out) -{ - struct pktq_prec *q; - void *p, *prev; - int prec; - - if (pq->len == 0) - return NULL; - - for (prec = 0; prec < pq->hi_prec; prec++) - if (pq->q[prec].head) - break; - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - return NULL; - - for (prev = NULL; p != q->tail; p = PKTLINK(p)) - prev = p; - - if (prev) - PKTSETLINK(prev, NULL); - else - q->head = NULL; - - q->tail = prev; - q->len--; - - pq->len--; - - if (prec_out) - *prec_out = prec; - - PKTSETLINK(p, NULL); - - return p; -} - -void * -pktq_peek(struct pktq *pq, int *prec_out) -{ - int prec; - - if (pq->len == 0) - return NULL; - - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) - pq->hi_prec--; - - if (prec_out) - *prec_out = prec; - - return (pq->q[prec].head); -} - -void * -pktq_peek_tail(struct pktq *pq, int *prec_out) -{ - int prec; - - if (pq->len == 0) - return NULL; - - for (prec = 0; prec < pq->hi_prec; prec++) - if (pq->q[prec].head) - break; - - if (prec_out) - *prec_out = prec; - - return (pq->q[prec].tail); -} - -void -pktq_flush(osl_t *osh, struct pktq *pq, bool dir) -{ - int prec; - for (prec = 0; prec < pq->num_prec; prec++) - pktq_pflush(osh, pq, prec, dir); - ASSERT(pq->len == 0); -} - -/* Return sum of lengths of a specific set of precedences */ -int -pktq_mlen(struct pktq *pq, uint prec_bmp) -{ - int prec, len; - - len = 0; - - for (prec = 0; prec <= pq->hi_prec; prec++) - if (prec_bmp & (1 << prec)) - len += pq->q[prec].len; - - return len; -} - -/* Priority dequeue from a specific set of precedences */ -void * -pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) -{ - struct pktq_prec *q; - void *p; - int prec; - - if (pq->len == 0) - return NULL; - - while ((prec = pq->hi_prec) > 0 && pq->q[prec].head == NULL) - pq->hi_prec--; - - while ((prec_bmp & (1 << prec)) == 0 || pq->q[prec].head == NULL) - if (prec-- == 0) - return NULL; - - q = &pq->q[prec]; - - if ((p = q->head) == NULL) - return NULL; - - if ((q->head = PKTLINK(p)) == NULL) - q->tail = NULL; - - q->len--; - - if (prec_out) - *prec_out = prec; - - pq->len--; - - PKTSETLINK(p, NULL); - - return p; -} -#endif /* BCMDRIVER */ - - - -const unsigned char bcm_ctype[] = { - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ - _BCM_C, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C|_BCM_S, _BCM_C, - _BCM_C, /* 8-15 */ - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 16-23 */ - _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 24-31 */ - _BCM_S|_BCM_SP,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 32-39 */ - _BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 40-47 */ - _BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D,_BCM_D, /* 48-55 */ - _BCM_D,_BCM_D,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 56-63 */ - _BCM_P, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, _BCM_U|_BCM_X, - _BCM_U|_BCM_X, _BCM_U, /* 64-71 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 72-79 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U,_BCM_U, /* 80-87 */ - _BCM_U,_BCM_U,_BCM_U,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_P, /* 88-95 */ - _BCM_P, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, _BCM_L|_BCM_X, - _BCM_L|_BCM_X, _BCM_L, /* 96-103 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 104-111 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L,_BCM_L, /* 112-119 */ - _BCM_L,_BCM_L,_BCM_L,_BCM_P,_BCM_P,_BCM_P,_BCM_P,_BCM_C, /* 120-127 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 128-143 */ - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 144-159 */ - _BCM_S|_BCM_SP, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, - _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 160-175 */ - _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, - _BCM_P, _BCM_P, _BCM_P, _BCM_P, _BCM_P, /* 176-191 */ - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, /* 192-207 */ - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_P, _BCM_U, _BCM_U, _BCM_U, - _BCM_U, _BCM_U, _BCM_U, _BCM_U, _BCM_L, /* 208-223 */ - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, /* 224-239 */ - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_P, _BCM_L, _BCM_L, _BCM_L, - _BCM_L, _BCM_L, _BCM_L, _BCM_L, _BCM_L /* 240-255 */ -}; - -ulong -bcm_strtoul(char *cp, char **endp, uint base) -{ - ulong result, last_result = 0, value; - bool minus; - - minus = FALSE; - - while (bcm_isspace(*cp)) - cp++; - - if (cp[0] == '+') - cp++; - else if (cp[0] == '-') { - minus = TRUE; - cp++; - } - - if (base == 0) { - if (cp[0] == '0') { - if ((cp[1] == 'x') || (cp[1] == 'X')) { - base = 16; - cp = &cp[2]; - } else { - base = 8; - cp = &cp[1]; - } - } else - base = 10; - } else if (base == 16 && (cp[0] == '0') && ((cp[1] == 'x') || (cp[1] == 'X'))) { - cp = &cp[2]; - } - - result = 0; - - while (bcm_isxdigit(*cp) && - (value = bcm_isdigit(*cp) ? *cp-'0' : bcm_toupper(*cp)-'A'+10) < base) { - result = result*base + value; - /* Detected overflow */ - if (result < last_result && !minus) - return (ulong)-1; - last_result = result; - cp++; - } - - if (minus) - result = (ulong)(-(long)result); - - if (endp) - *endp = (char *)cp; - - return (result); -} - -int -bcm_atoi(char *s) -{ - return (int)bcm_strtoul(s, NULL, 10); -} - -/* return pointer to location of substring 'needle' in 'haystack' */ -char* -bcmstrstr(char *haystack, char *needle) -{ - int len, nlen; - int i; - - if ((haystack == NULL) || (needle == NULL)) - return (haystack); - - nlen = strlen(needle); - len = strlen(haystack) - nlen + 1; - - for (i = 0; i < len; i++) - if (memcmp(needle, &haystack[i], nlen) == 0) - return (&haystack[i]); - return (NULL); -} - -char* -bcmstrcat(char *dest, const char *src) -{ - char *p; - - p = dest + strlen(dest); - - while ((*p++ = *src++) != '\0') - ; - - return (dest); -} - -char* -bcmstrncat(char *dest, const char *src, uint size) -{ - char *endp; - char *p; - - p = dest + strlen(dest); - endp = p + size; - - while (p != endp && (*p++ = *src++) != '\0') - ; - - return (dest); -} - - -/**************************************************************************** -* Function: bcmstrtok -* -* Purpose: -* Tokenizes a string. This function is conceptually similiar to ANSI C strtok(), -* but allows strToken() to be used by different strings or callers at the same -* time. Each call modifies '*string' by substituting a NULL character for the -* first delimiter that is encountered, and updates 'string' to point to the char -* after the delimiter. Leading delimiters are skipped. -* -* Parameters: -* string (mod) Ptr to string ptr, updated by token. -* delimiters (in) Set of delimiter characters. -* tokdelim (out) Character that delimits the returned token. (May -* be set to NULL if token delimiter is not required). -* -* Returns: Pointer to the next token found. NULL when no more tokens are found. -***************************************************************************** -*/ -char * -bcmstrtok(char **string, const char *delimiters, char *tokdelim) -{ - unsigned char *str; - unsigned long map[8]; - int count; - char *nextoken; - - if (tokdelim != NULL) { - /* Prime the token delimiter */ - *tokdelim = '\0'; - } - - /* Clear control map */ - for (count = 0; count < 8; count++) { - map[count] = 0; - } - - /* Set bits in delimiter table */ - do { - map[*delimiters >> 5] |= (1 << (*delimiters & 31)); - } - while (*delimiters++); - - str = (unsigned char*)*string; - - /* Find beginning of token (skip over leading delimiters). Note that - * there is no token iff this loop sets str to point to the terminal - * null (*str == '\0') - */ - while (((map[*str >> 5] & (1 << (*str & 31))) && *str) || (*str == ' ')) { - str++; - } - - nextoken = (char*)str; - - /* Find the end of the token. If it is not the end of the string, - * put a null there. - */ - for (; *str; str++) { - if (map[*str >> 5] & (1 << (*str & 31))) { - if (tokdelim != NULL) { - *tokdelim = *str; - } - - *str++ = '\0'; - break; - } - } - - *string = (char*)str; - - /* Determine if a token has been found. */ - if (nextoken == (char *) str) { - return NULL; - } - else { - return nextoken; - } -} - - -#define xToLower(C) \ - ((C >= 'A' && C <= 'Z') ? (char)((int)C - (int)'A' + (int)'a') : C) - - -/**************************************************************************** -* Function: bcmstricmp -* -* Purpose: Compare to strings case insensitively. -* -* Parameters: s1 (in) First string to compare. -* s2 (in) Second string to compare. -* -* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if -* t1 > t2, when ignoring case sensitivity. -***************************************************************************** -*/ -int -bcmstricmp(const char *s1, const char *s2) -{ - char dc, sc; - - while (*s2 && *s1) { - dc = xToLower(*s1); - sc = xToLower(*s2); - if (dc < sc) return -1; - if (dc > sc) return 1; - s1++; - s2++; - } - - if (*s1 && !*s2) return 1; - if (!*s1 && *s2) return -1; - return 0; -} - - -/**************************************************************************** -* Function: bcmstrnicmp -* -* Purpose: Compare to strings case insensitively, upto a max of 'cnt' -* characters. -* -* Parameters: s1 (in) First string to compare. -* s2 (in) Second string to compare. -* cnt (in) Max characters to compare. -* -* Returns: Return 0 if the two strings are equal, -1 if t1 < t2 and 1 if -* t1 > t2, when ignoring case sensitivity. -***************************************************************************** -*/ -int -bcmstrnicmp(const char* s1, const char* s2, int cnt) -{ - char dc, sc; - - while (*s2 && *s1 && cnt) { - dc = xToLower(*s1); - sc = xToLower(*s2); - if (dc < sc) return -1; - if (dc > sc) return 1; - s1++; - s2++; - cnt--; - } - - if (!cnt) return 0; - if (*s1 && !*s2) return 1; - if (!*s1 && *s2) return -1; - return 0; -} - -/* parse a xx:xx:xx:xx:xx:xx format ethernet address */ -int -bcm_ether_atoe(char *p, struct ether_addr *ea) -{ - int i = 0; - - for (;;) { - ea->octet[i++] = (char) bcm_strtoul(p, &p, 16); - if (!*p++ || i == 6) - break; - } - - return (i == 6); -} - - -#if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) -/* registry routine buffer preparation utility functions: - * parameter order is like strncpy, but returns count - * of bytes copied. Minimum bytes copied is null char(1)/wchar(2) - */ -ulong -wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen) -{ - ulong copyct = 1; - ushort i; - - if (abuflen == 0) - return 0; - - /* wbuflen is in bytes */ - wbuflen /= sizeof(ushort); - - for (i = 0; i < wbuflen; ++i) { - if (--abuflen == 0) - break; - *abuf++ = (char) *wbuf++; - ++copyct; - } - *abuf = '\0'; - - return copyct; -} -#endif /* CONFIG_USBRNDIS_RETAIL || NDIS_MINIPORT_DRIVER */ - -char * -bcm_ether_ntoa(const struct ether_addr *ea, char *buf) -{ - static const char template[] = "%02x:%02x:%02x:%02x:%02x:%02x"; - snprintf(buf, 18, template, - ea->octet[0]&0xff, ea->octet[1]&0xff, ea->octet[2]&0xff, - ea->octet[3]&0xff, ea->octet[4]&0xff, ea->octet[5]&0xff); - return (buf); -} - -char * -bcm_ip_ntoa(struct ipv4_addr *ia, char *buf) -{ - snprintf(buf, 16, "%d.%d.%d.%d", - ia->addr[0], ia->addr[1], ia->addr[2], ia->addr[3]); - return (buf); -} - -#ifdef BCMDRIVER - -void -bcm_mdelay(uint ms) -{ - uint i; - - for (i = 0; i < ms; i++) { - OSL_DELAY(1000); - } -} - - - - - - -#if defined(DHD_DEBUG) -/* pretty hex print a pkt buffer chain */ -void -prpkt(const char *msg, osl_t *osh, void *p0) -{ - void *p; - - if (msg && (msg[0] != '\0')) - printf("%s:\n", msg); - - for (p = p0; p; p = PKTNEXT(osh, p)) - prhex(NULL, PKTDATA(osh, p), PKTLEN(osh, p)); -} -#endif - -/* Takes an Ethernet frame and sets out-of-bound PKTPRIO. - * Also updates the inplace vlan tag if requested. - * For debugging, it returns an indication of what it did. - */ -uint -pktsetprio(void *pkt, bool update_vtag) -{ - struct ether_header *eh; - struct ethervlan_header *evh; - uint8 *pktdata; - int priority = 0; - int rc = 0; - - pktdata = (uint8 *) PKTDATA(NULL, pkt); - ASSERT(ISALIGNED((uintptr)pktdata, sizeof(uint16))); - - eh = (struct ether_header *) pktdata; - - if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { - uint16 vlan_tag; - int vlan_prio, dscp_prio = 0; - - evh = (struct ethervlan_header *)eh; - - vlan_tag = ntoh16(evh->vlan_tag); - vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; - - if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) { - uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); - uint8 tos_tc = IP_TOS(ip_body); - dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); - } - - /* DSCP priority gets precedence over 802.1P (vlan tag) */ - if (dscp_prio != 0) { - priority = dscp_prio; - rc |= PKTPRIO_VDSCP; - } else { - priority = vlan_prio; - rc |= PKTPRIO_VLAN; - } - /* - * If the DSCP priority is not the same as the VLAN priority, - * then overwrite the priority field in the vlan tag, with the - * DSCP priority value. This is required for Linux APs because - * the VLAN driver on Linux, overwrites the skb->priority field - * with the priority value in the vlan tag - */ - if (update_vtag && (priority != vlan_prio)) { - vlan_tag &= ~(VLAN_PRI_MASK << VLAN_PRI_SHIFT); - vlan_tag |= (uint16)priority << VLAN_PRI_SHIFT; - evh->vlan_tag = hton16(vlan_tag); - rc |= PKTPRIO_UPD; - } - } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { - uint8 *ip_body = pktdata + sizeof(struct ether_header); - uint8 tos_tc = IP_TOS(ip_body); - priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); - rc |= PKTPRIO_DSCP; - } - - ASSERT(priority >= 0 && priority <= MAXPRIO); - PKTSETPRIO(pkt, priority); - return (rc | priority); -} - -static char bcm_undeferrstr[BCME_STRLEN]; - -static const char *bcmerrorstrtable[] = BCMERRSTRINGTABLE; - -/* Convert the error codes into related error strings */ -const char * -bcmerrorstr(int bcmerror) -{ - /* check if someone added a bcmerror code but forgot to add errorstring */ - ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(bcmerrorstrtable) - 1)); - - if (bcmerror > 0 || bcmerror < BCME_LAST) { - snprintf(bcm_undeferrstr, BCME_STRLEN, "Undefined error %d", bcmerror); - return bcm_undeferrstr; - } - - ASSERT(strlen(bcmerrorstrtable[-bcmerror]) < BCME_STRLEN); - - return bcmerrorstrtable[-bcmerror]; -} - - - -/* iovar table lookup */ -const bcm_iovar_t* -bcm_iovar_lookup(const bcm_iovar_t *table, const char *name) -{ - const bcm_iovar_t *vi; - const char *lookup_name; - - /* skip any ':' delimited option prefixes */ - lookup_name = strrchr(name, ':'); - if (lookup_name != NULL) - lookup_name++; - else - lookup_name = name; - - ASSERT(table != NULL); - - for (vi = table; vi->name; vi++) { - if (!strcmp(vi->name, lookup_name)) - return vi; - } - /* ran to end of table */ - - return NULL; /* var name not found */ -} - -int -bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) -{ - int bcmerror = 0; - - /* length check on io buf */ - switch (vi->type) { - case IOVT_BOOL: - case IOVT_INT8: - case IOVT_INT16: - case IOVT_INT32: - case IOVT_UINT8: - case IOVT_UINT16: - case IOVT_UINT32: - /* all integers are int32 sized args at the ioctl interface */ - if (len < (int)sizeof(int)) { - bcmerror = BCME_BUFTOOSHORT; - } - break; - - case IOVT_BUFFER: - /* buffer must meet minimum length requirement */ - if (len < vi->minlen) { - bcmerror = BCME_BUFTOOSHORT; - } - break; - - case IOVT_VOID: - if (!set) { - /* Cannot return nil... */ - bcmerror = BCME_UNSUPPORTED; - } else if (len) { - /* Set is an action w/o parameters */ - bcmerror = BCME_BUFTOOLONG; - } - break; - - default: - /* unknown type for length check in iovar info */ - ASSERT(0); - bcmerror = BCME_UNSUPPORTED; - } - - return bcmerror; -} - -#endif /* BCMDRIVER */ - -/******************************************************************************* - * crc8 - * - * Computes a crc8 over the input data using the polynomial: - * - * x^8 + x^7 +x^6 + x^4 + x^2 + 1 - * - * The caller provides the initial value (either CRC8_INIT_VALUE - * or the previous returned value) to allow for processing of - * discontiguous blocks of data. When generating the CRC the - * caller is responsible for complementing the final return value - * and inserting it into the byte stream. When checking, a final - * return value of CRC8_GOOD_VALUE indicates a valid CRC. - * - * Reference: Dallas Semiconductor Application Note 27 - * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", - * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., - * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt - * - * **************************************************************************** - */ - -STATIC const uint8 crc8_table[256] = { - 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, - 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, - 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, - 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, - 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, - 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, - 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, - 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, - 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, - 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, - 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, - 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, - 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, - 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, - 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, - 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, - 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, - 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, - 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, - 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, - 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, - 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, - 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, - 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, - 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, - 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, - 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, - 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, - 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, - 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, - 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, - 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F -}; - -#define CRC_INNER_LOOP(n, c, x) \ - (c) = ((c) >> 8) ^ crc##n##_table[((c) ^ (x)) & 0xff] - -uint8 -hndcrc8( - uint8 *pdata, /* pointer to array of data to process */ - uint nbytes, /* number of input data bytes to process */ - uint8 crc /* either CRC8_INIT_VALUE or previous return value */ -) -{ - /* hard code the crc loop instead of using CRC_INNER_LOOP macro - * to avoid the undefined and unnecessary (uint8 >> 8) operation. - */ - while (nbytes-- > 0) - crc = crc8_table[(crc ^ *pdata++) & 0xff]; - - return crc; -} - -/******************************************************************************* - * crc16 - * - * Computes a crc16 over the input data using the polynomial: - * - * x^16 + x^12 +x^5 + 1 - * - * The caller provides the initial value (either CRC16_INIT_VALUE - * or the previous returned value) to allow for processing of - * discontiguous blocks of data. When generating the CRC the - * caller is responsible for complementing the final return value - * and inserting it into the byte stream. When checking, a final - * return value of CRC16_GOOD_VALUE indicates a valid CRC. - * - * Reference: Dallas Semiconductor Application Note 27 - * Williams, Ross N., "A Painless Guide to CRC Error Detection Algorithms", - * ver 3, Aug 1993, ross@guest.adelaide.edu.au, Rocksoft Pty Ltd., - * ftp://ftp.rocksoft.com/clients/rocksoft/papers/crc_v3.txt - * - * **************************************************************************** - */ - -static const uint16 crc16_table[256] = { - 0x0000, 0x1189, 0x2312, 0x329B, 0x4624, 0x57AD, 0x6536, 0x74BF, - 0x8C48, 0x9DC1, 0xAF5A, 0xBED3, 0xCA6C, 0xDBE5, 0xE97E, 0xF8F7, - 0x1081, 0x0108, 0x3393, 0x221A, 0x56A5, 0x472C, 0x75B7, 0x643E, - 0x9CC9, 0x8D40, 0xBFDB, 0xAE52, 0xDAED, 0xCB64, 0xF9FF, 0xE876, - 0x2102, 0x308B, 0x0210, 0x1399, 0x6726, 0x76AF, 0x4434, 0x55BD, - 0xAD4A, 0xBCC3, 0x8E58, 0x9FD1, 0xEB6E, 0xFAE7, 0xC87C, 0xD9F5, - 0x3183, 0x200A, 0x1291, 0x0318, 0x77A7, 0x662E, 0x54B5, 0x453C, - 0xBDCB, 0xAC42, 0x9ED9, 0x8F50, 0xFBEF, 0xEA66, 0xD8FD, 0xC974, - 0x4204, 0x538D, 0x6116, 0x709F, 0x0420, 0x15A9, 0x2732, 0x36BB, - 0xCE4C, 0xDFC5, 0xED5E, 0xFCD7, 0x8868, 0x99E1, 0xAB7A, 0xBAF3, - 0x5285, 0x430C, 0x7197, 0x601E, 0x14A1, 0x0528, 0x37B3, 0x263A, - 0xDECD, 0xCF44, 0xFDDF, 0xEC56, 0x98E9, 0x8960, 0xBBFB, 0xAA72, - 0x6306, 0x728F, 0x4014, 0x519D, 0x2522, 0x34AB, 0x0630, 0x17B9, - 0xEF4E, 0xFEC7, 0xCC5C, 0xDDD5, 0xA96A, 0xB8E3, 0x8A78, 0x9BF1, - 0x7387, 0x620E, 0x5095, 0x411C, 0x35A3, 0x242A, 0x16B1, 0x0738, - 0xFFCF, 0xEE46, 0xDCDD, 0xCD54, 0xB9EB, 0xA862, 0x9AF9, 0x8B70, - 0x8408, 0x9581, 0xA71A, 0xB693, 0xC22C, 0xD3A5, 0xE13E, 0xF0B7, - 0x0840, 0x19C9, 0x2B52, 0x3ADB, 0x4E64, 0x5FED, 0x6D76, 0x7CFF, - 0x9489, 0x8500, 0xB79B, 0xA612, 0xD2AD, 0xC324, 0xF1BF, 0xE036, - 0x18C1, 0x0948, 0x3BD3, 0x2A5A, 0x5EE5, 0x4F6C, 0x7DF7, 0x6C7E, - 0xA50A, 0xB483, 0x8618, 0x9791, 0xE32E, 0xF2A7, 0xC03C, 0xD1B5, - 0x2942, 0x38CB, 0x0A50, 0x1BD9, 0x6F66, 0x7EEF, 0x4C74, 0x5DFD, - 0xB58B, 0xA402, 0x9699, 0x8710, 0xF3AF, 0xE226, 0xD0BD, 0xC134, - 0x39C3, 0x284A, 0x1AD1, 0x0B58, 0x7FE7, 0x6E6E, 0x5CF5, 0x4D7C, - 0xC60C, 0xD785, 0xE51E, 0xF497, 0x8028, 0x91A1, 0xA33A, 0xB2B3, - 0x4A44, 0x5BCD, 0x6956, 0x78DF, 0x0C60, 0x1DE9, 0x2F72, 0x3EFB, - 0xD68D, 0xC704, 0xF59F, 0xE416, 0x90A9, 0x8120, 0xB3BB, 0xA232, - 0x5AC5, 0x4B4C, 0x79D7, 0x685E, 0x1CE1, 0x0D68, 0x3FF3, 0x2E7A, - 0xE70E, 0xF687, 0xC41C, 0xD595, 0xA12A, 0xB0A3, 0x8238, 0x93B1, - 0x6B46, 0x7ACF, 0x4854, 0x59DD, 0x2D62, 0x3CEB, 0x0E70, 0x1FF9, - 0xF78F, 0xE606, 0xD49D, 0xC514, 0xB1AB, 0xA022, 0x92B9, 0x8330, - 0x7BC7, 0x6A4E, 0x58D5, 0x495C, 0x3DE3, 0x2C6A, 0x1EF1, 0x0F78 -}; - -uint16 -hndcrc16( - uint8 *pdata, /* pointer to array of data to process */ - uint nbytes, /* number of input data bytes to process */ - uint16 crc /* either CRC16_INIT_VALUE or previous return value */ -) -{ - while (nbytes-- > 0) - CRC_INNER_LOOP(16, crc, *pdata++); - return crc; -} - -STATIC const uint32 crc32_table[256] = { - 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, - 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, - 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, - 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, - 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, - 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, - 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, - 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, - 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, - 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, - 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, - 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, - 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, - 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, - 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, - 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, - 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, - 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, - 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, - 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, - 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, - 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, - 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, - 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, - 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, - 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, - 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, - 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, - 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, - 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, - 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, - 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, - 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, - 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, - 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, - 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, - 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, - 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, - 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, - 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, - 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, - 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, - 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, - 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, - 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, - 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, - 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, - 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, - 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, - 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, - 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, - 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, - 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, - 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, - 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, - 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, - 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, - 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, - 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, - 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, - 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, - 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, - 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, - 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D -}; - -uint32 -hndcrc32( - uint8 *pdata, /* pointer to array of data to process */ - uint nbytes, /* number of input data bytes to process */ - uint32 crc /* either CRC32_INIT_VALUE or previous return value */ -) -{ - uint8 *pend; -#ifdef __mips__ - uint8 tmp[4]; - ulong *tptr = (ulong *)tmp; - - /* in case the beginning of the buffer isn't aligned */ - pend = (uint8 *)((uint)(pdata + 3) & 0xfffffffc); - nbytes -= (pend - pdata); - while (pdata < pend) - CRC_INNER_LOOP(32, crc, *pdata++); - - /* handle bulk of data as 32-bit words */ - pend = pdata + (nbytes & 0xfffffffc); - while (pdata < pend) { - *tptr = *(ulong *)pdata; - pdata += sizeof(ulong *); - CRC_INNER_LOOP(32, crc, tmp[0]); - CRC_INNER_LOOP(32, crc, tmp[1]); - CRC_INNER_LOOP(32, crc, tmp[2]); - CRC_INNER_LOOP(32, crc, tmp[3]); - } - - /* 1-3 bytes at end of buffer */ - pend = pdata + (nbytes & 0x03); - while (pdata < pend) - CRC_INNER_LOOP(32, crc, *pdata++); -#else - pend = pdata + nbytes; - while (pdata < pend) - CRC_INNER_LOOP(32, crc, *pdata++); -#endif /* __mips__ */ - - return crc; -} - -#ifdef notdef -#define CLEN 1499 /* CRC Length */ -#define CBUFSIZ (CLEN+4) -#define CNBUFS 5 /* # of bufs */ - -void testcrc32(void) -{ - uint j, k, l; - uint8 *buf; - uint len[CNBUFS]; - uint32 crcr; - uint32 crc32tv[CNBUFS] = - {0xd2cb1faa, 0xd385c8fa, 0xf5b4f3f3, 0x55789e20, 0x00343110}; - - ASSERT((buf = MALLOC(CBUFSIZ*CNBUFS)) != NULL); - - /* step through all possible alignments */ - for (l = 0; l <= 4; l++) { - for (j = 0; j < CNBUFS; j++) { - len[j] = CLEN; - for (k = 0; k < len[j]; k++) - *(buf + j*CBUFSIZ + (k+l)) = (j+k) & 0xff; - } - - for (j = 0; j < CNBUFS; j++) { - crcr = crc32(buf + j*CBUFSIZ + l, len[j], CRC32_INIT_VALUE); - ASSERT(crcr == crc32tv[j]); - } - } - - MFREE(buf, CBUFSIZ*CNBUFS); - return; -} -#endif /* notdef */ - -/* - * Advance from the current 1-byte tag/1-byte length/variable-length value - * triple, to the next, returning a pointer to the next. - * If the current or next TLV is invalid (does not fit in given buffer length), - * NULL is returned. - * *buflen is not modified if the TLV elt parameter is invalid, or is decremented - * by the TLV parameter's length if it is valid. - */ -bcm_tlv_t * -bcm_next_tlv(bcm_tlv_t *elt, int *buflen) -{ - int len; - - /* validate current elt */ - if (!bcm_valid_tlv(elt, *buflen)) - return NULL; - - /* advance to next elt */ - len = elt->len; - elt = (bcm_tlv_t*)(elt->data + len); - *buflen -= (2 + len); - - /* validate next elt */ - if (!bcm_valid_tlv(elt, *buflen)) - return NULL; - - return elt; -} - -/* - * Traverse a string of 1-byte tag/1-byte length/variable-length value - * triples, returning a pointer to the substring whose first element - * matches tag - */ -bcm_tlv_t * -bcm_parse_tlvs(void *buf, int buflen, uint key) -{ - bcm_tlv_t *elt; - int totlen; - - elt = (bcm_tlv_t*)buf; - totlen = buflen; - - /* find tagged parameter */ - while (totlen >= 2) { - int len = elt->len; - - /* validate remaining totlen */ - if ((elt->id == key) && (totlen >= (len + 2))) - return (elt); - - elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); - totlen -= (len + 2); - } - - return NULL; -} - -/* - * Traverse a string of 1-byte tag/1-byte length/variable-length value - * triples, returning a pointer to the substring whose first element - * matches tag. Stop parsing when we see an element whose ID is greater - * than the target key. - */ -bcm_tlv_t * -bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) -{ - bcm_tlv_t *elt; - int totlen; - - elt = (bcm_tlv_t*)buf; - totlen = buflen; - - /* find tagged parameter */ - while (totlen >= 2) { - uint id = elt->id; - int len = elt->len; - - /* Punt if we start seeing IDs > than target key */ - if (id > key) - return (NULL); - - /* validate remaining totlen */ - if ((id == key) && (totlen >= (len + 2))) - return (elt); - - elt = (bcm_tlv_t*)((uint8*)elt + (len + 2)); - totlen -= (len + 2); - } - return NULL; -} - -#if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ - defined(DHD_DEBUG) -int -bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) -{ - int i; - char* p = buf; - char hexstr[16]; - int slen = 0; - uint32 bit; - const char* name; - - if (len < 2 || !buf) - return 0; - - buf[0] = '\0'; - len -= 1; - - for (i = 0; flags != 0; i++) { - bit = bd[i].bit; - name = bd[i].name; - if (bit == 0 && flags) { - /* print any unnamed bits */ - sprintf(hexstr, "0x%X", flags); - name = hexstr; - flags = 0; /* exit loop */ - } else if ((flags & bit) == 0) - continue; - slen += strlen(name); - if (len < slen) - break; - if (p != buf) p += sprintf(p, " "); /* btwn flag space */ - strcat(p, name); - p += strlen(name); - flags &= ~bit; - len -= slen; - slen = 1; /* account for btwn flag space */ - } - - /* indicate the str was too short */ - if (flags != 0) { - if (len == 0) - p--; /* overwrite last char */ - p += sprintf(p, ">"); - } - - return (int)(p - buf); -} - -/* print bytes formatted as hex to a string. return the resulting string length */ -int -bcm_format_hex(char *str, const void *bytes, int len) -{ - int i; - char *p = str; - const uint8 *src = (const uint8*)bytes; - - for (i = 0; i < len; i++) { - p += sprintf(p, "%02X", *src); - src++; - } - return (int)(p - str); -} - -/* pretty hex print a contiguous buffer */ -void -prhex(const char *msg, uchar *buf, uint nbytes) -{ - char line[128], *p; - uint i; - - if (msg && (msg[0] != '\0')) - printf("%s:\n", msg); - - p = line; - for (i = 0; i < nbytes; i++) { - if (i % 16 == 0) { - p += sprintf(p, " %04d: ", i); /* line prefix */ - } - p += sprintf(p, "%02x ", buf[i]); - if (i % 16 == 15) { - printf("%s\n", line); /* flush line */ - p = line; - } - } - - /* flush last partial line */ - if (p != line) - printf("%s\n", line); -} -#endif - - -/* Produce a human-readable string for boardrev */ -char * -bcm_brev_str(uint32 brev, char *buf) -{ - if (brev < 0x100) - snprintf(buf, 8, "%d.%d", (brev & 0xf0) >> 4, brev & 0xf); - else - snprintf(buf, 8, "%c%03x", ((brev & 0xf000) == 0x1000) ? 'P' : 'A', brev & 0xfff); - - return (buf); -} - -#define BUFSIZE_TODUMP_ATONCE 512 /* Buffer size */ - -/* dump large strings to console */ -void -printbig(char *buf) -{ - uint len, max_len; - char c; - - len = strlen(buf); - - max_len = BUFSIZE_TODUMP_ATONCE; - - while (len > max_len) { - c = buf[max_len]; - buf[max_len] = '\0'; - printf("%s", buf); - buf[max_len] = c; - - buf += max_len; - len -= max_len; - } - /* print the remaining string */ - printf("%s\n", buf); - return; -} - -/* routine to dump fields in a fileddesc structure */ -uint -bcmdumpfields(bcmutl_rdreg_rtn read_rtn, void *arg0, uint arg1, struct fielddesc *fielddesc_array, - char *buf, uint32 bufsize) -{ - uint filled_len; - int len; - struct fielddesc *cur_ptr; - - filled_len = 0; - cur_ptr = fielddesc_array; - - while (bufsize > 1) { - if (cur_ptr->nameandfmt == NULL) - break; - len = snprintf(buf, bufsize, cur_ptr->nameandfmt, - read_rtn(arg0, arg1, cur_ptr->offset)); - /* check for snprintf overflow or error */ - if (len < 0 || (uint32)len >= bufsize) - len = bufsize - 1; - buf += len; - bufsize -= len; - filled_len += len; - cur_ptr++; - } - return filled_len; -} - -uint -bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) -{ - uint len; - - len = strlen(name) + 1; - - if ((len + datalen) > buflen) - return 0; - - strncpy(buf, name, buflen); - - /* append data onto the end of the name string */ - memcpy(&buf[len], data, datalen); - len += datalen; - - return len; -} - -/* Quarter dBm units to mW - * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 - * Table is offset so the last entry is largest mW value that fits in - * a uint16. - */ - -#define QDBM_OFFSET 153 /* Offset for first entry */ -#define QDBM_TABLE_LEN 40 /* Table size */ - -/* Smallest mW value that will round up to the first table entry, QDBM_OFFSET. - * Value is ( mW(QDBM_OFFSET - 1) + mW(QDBM_OFFSET) ) / 2 - */ -#define QDBM_TABLE_LOW_BOUND 6493 /* Low bound */ - -/* Largest mW value that will round down to the last table entry, - * QDBM_OFFSET + QDBM_TABLE_LEN-1. - * Value is ( mW(QDBM_OFFSET + QDBM_TABLE_LEN - 1) + mW(QDBM_OFFSET + QDBM_TABLE_LEN) ) / 2. - */ -#define QDBM_TABLE_HIGH_BOUND 64938 /* High bound */ - -static const uint16 nqdBm_to_mW_map[QDBM_TABLE_LEN] = { -/* qdBm: +0 +1 +2 +3 +4 +5 +6 +7 */ -/* 153: */ 6683, 7079, 7499, 7943, 8414, 8913, 9441, 10000, -/* 161: */ 10593, 11220, 11885, 12589, 13335, 14125, 14962, 15849, -/* 169: */ 16788, 17783, 18836, 19953, 21135, 22387, 23714, 25119, -/* 177: */ 26607, 28184, 29854, 31623, 33497, 35481, 37584, 39811, -/* 185: */ 42170, 44668, 47315, 50119, 53088, 56234, 59566, 63096 -}; - -uint16 -bcm_qdbm_to_mw(uint8 qdbm) -{ - uint factor = 1; - int idx = qdbm - QDBM_OFFSET; - - if (idx >= QDBM_TABLE_LEN) { - /* clamp to max uint16 mW value */ - return 0xFFFF; - } - - /* scale the qdBm index up to the range of the table 0-40 - * where an offset of 40 qdBm equals a factor of 10 mW. - */ - while (idx < 0) { - idx += 40; - factor *= 10; - } - - /* return the mW value scaled down to the correct factor of 10, - * adding in factor/2 to get proper rounding. - */ - return ((nqdBm_to_mW_map[idx] + factor/2) / factor); -} - -uint8 -bcm_mw_to_qdbm(uint16 mw) -{ - uint8 qdbm; - int offset; - uint mw_uint = mw; - uint boundary; - - /* handle boundary case */ - if (mw_uint <= 1) - return 0; - - offset = QDBM_OFFSET; - - /* move mw into the range of the table */ - while (mw_uint < QDBM_TABLE_LOW_BOUND) { - mw_uint *= 10; - offset -= 40; - } - - for (qdbm = 0; qdbm < QDBM_TABLE_LEN-1; qdbm++) { - boundary = nqdBm_to_mW_map[qdbm] + (nqdBm_to_mW_map[qdbm+1] - - nqdBm_to_mW_map[qdbm])/2; - if (mw_uint < boundary) break; - } - - qdbm += (uint8)offset; - - return (qdbm); -} - - -uint -bcm_bitcount(uint8 *bitmap, uint length) -{ - uint bitcount = 0, i; - uint8 tmp; - for (i = 0; i < length; i++) { - tmp = bitmap[i]; - while (tmp) { - bitcount++; - tmp &= (tmp - 1); - } - } - return bitcount; -} - -#ifdef BCMDRIVER - -/* Initialization of bcmstrbuf structure */ -void -bcm_binit(struct bcmstrbuf *b, char *buf, uint size) -{ - b->origsize = b->size = size; - b->origbuf = b->buf = buf; -} - -/* Buffer sprintf wrapper to guard against buffer overflow */ -int -bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...) -{ - va_list ap; - int r; - - va_start(ap, fmt); - r = vsnprintf(b->buf, b->size, fmt, ap); - - /* Non Ansi C99 compliant returns -1, - * Ansi compliant return r >= b->size, - * bcmstdlib returns 0, handle all - */ - if ((r == -1) || (r >= (int)b->size) || (r == 0)) { - b->size = 0; - } else { - b->size -= r; - b->buf += r; - } - - va_end(ap); - - return r; -} - -void -bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount) -{ - int i; - - for (i = 0; i < num_bytes; i++) { - num[i] += amount; - if (num[i] >= amount) - break; - amount = 1; - } -} - -int -bcm_cmp_bytes(uchar *arg1, uchar *arg2, uint8 nbytes) -{ - int i; - - for (i = nbytes - 1; i >= 0; i--) { - if (arg1[i] != arg2[i]) - return (arg1[i] - arg2[i]); - } - return 0; -} - -void -bcm_print_bytes(char *name, const uchar *data, int len) -{ - int i; - int per_line = 0; - - printf("%s: %d \n", name ? name : "", len); - for (i = 0; i < len; i++) { - printf("%02x ", *data++); - per_line++; - if (per_line == 16) { - per_line = 0; - printf("\n"); - } - } - printf("\n"); -} - -/* - * buffer length needed for wlc_format_ssid - * 32 SSID chars, max of 4 chars for each SSID char "\xFF", plus NULL. - */ - -#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ - defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) -int -bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len) -{ - uint i, c; - char *p = buf; - char *endp = buf + SSID_FMT_BUF_LEN; - - if (ssid_len > DOT11_MAX_SSID_LEN) ssid_len = DOT11_MAX_SSID_LEN; - - for (i = 0; i < ssid_len; i++) { - c = (uint)ssid[i]; - if (c == '\\') { - *p++ = '\\'; - *p++ = '\\'; - } else if (bcm_isprint((uchar)c)) { - *p++ = (char)c; - } else { - p += snprintf(p, (endp - p), "\\x%02X", c); - } - } - *p = '\0'; - ASSERT(p < endp); - - return (int)(p - buf); -} -#endif - -#endif /* BCMDRIVER */ diff --git a/drivers/net/wireless/bcm4329/bcmwifi.c b/drivers/net/wireless/bcm4329/bcmwifi.c deleted file mode 100644 index 803acf842a29..000000000000 --- a/drivers/net/wireless/bcm4329/bcmwifi.c +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Misc utility routines used by kernel or app-level. - * Contents are wifi-specific, used by any kernel or app-level - * software that might want wifi things as it grows. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmwifi.c,v 1.18.24.2.4.1 2009/09/25 00:32:01 Exp $ - */ - - -#include - -#ifdef BCMDRIVER -#include -#include -#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) -#define tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) -#else -#include -#include -#include -#endif -#include - -#if defined(WIN32) && (defined(BCMDLL) || defined(WLMDLL)) -#include -#endif - - - - - -char * -wf_chspec_ntoa(chanspec_t chspec, char *buf) -{ - const char *band, *bw, *sb; - uint channel; - - band = ""; - bw = ""; - sb = ""; - channel = CHSPEC_CHANNEL(chspec); - - if ((CHSPEC_IS2G(chspec) && channel > CH_MAX_2G_CHANNEL) || - (CHSPEC_IS5G(chspec) && channel <= CH_MAX_2G_CHANNEL)) - band = (CHSPEC_IS2G(chspec)) ? "b" : "a"; - if (CHSPEC_IS40(chspec)) { - if (CHSPEC_SB_UPPER(chspec)) { - sb = "u"; - channel += CH_10MHZ_APART; - } else { - sb = "l"; - channel -= CH_10MHZ_APART; - } - } else if (CHSPEC_IS10(chspec)) { - bw = "n"; - } - - - snprintf(buf, 6, "%d%s%s%s", channel, band, bw, sb); - return (buf); -} - - -chanspec_t -wf_chspec_aton(char *a) -{ - char *endp = NULL; - uint channel, band, bw, ctl_sb; - char c; - - channel = strtoul(a, &endp, 10); - - - if (endp == a) - return 0; - - if (channel > MAXCHANNEL) - return 0; - - band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); - bw = WL_CHANSPEC_BW_20; - ctl_sb = WL_CHANSPEC_CTL_SB_NONE; - - a = endp; - - c = tolower(a[0]); - if (c == '\0') - goto done; - - - if (c == 'a' || c == 'b') { - band = (c == 'a') ? WL_CHANSPEC_BAND_5G : WL_CHANSPEC_BAND_2G; - a++; - c = tolower(a[0]); - if (c == '\0') - goto done; - } - - - if (c == 'n') { - bw = WL_CHANSPEC_BW_10; - } else if (c == 'l') { - bw = WL_CHANSPEC_BW_40; - ctl_sb = WL_CHANSPEC_CTL_SB_LOWER; - - if (channel <= (MAXCHANNEL - CH_20MHZ_APART)) - channel += CH_10MHZ_APART; - else - return 0; - } else if (c == 'u') { - bw = WL_CHANSPEC_BW_40; - ctl_sb = WL_CHANSPEC_CTL_SB_UPPER; - - if (channel > CH_20MHZ_APART) - channel -= CH_10MHZ_APART; - else - return 0; - } else { - return 0; - } - -done: - return (channel | band | bw | ctl_sb); -} - - -int -wf_mhz2channel(uint freq, uint start_factor) -{ - int ch = -1; - uint base; - int offset; - - - if (start_factor == 0) { - if (freq >= 2400 && freq <= 2500) - start_factor = WF_CHAN_FACTOR_2_4_G; - else if (freq >= 5000 && freq <= 6000) - start_factor = WF_CHAN_FACTOR_5_G; - } - - if (freq == 2484 && start_factor == WF_CHAN_FACTOR_2_4_G) - return 14; - - base = start_factor / 2; - - - if ((freq < base) || (freq > base + 1000)) - return -1; - - offset = freq - base; - ch = offset / 5; - - - if (offset != (ch * 5)) - return -1; - - - if (start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 13)) - return -1; - - return ch; -} - - -int -wf_channel2mhz(uint ch, uint start_factor) -{ - int freq; - - if ((start_factor == WF_CHAN_FACTOR_2_4_G && (ch < 1 || ch > 14)) || - (ch <= 200)) - freq = -1; - if ((start_factor == WF_CHAN_FACTOR_2_4_G) && (ch == 14)) - freq = 2484; - else - freq = ch * 5 + start_factor / 2; - - return freq; -} diff --git a/drivers/net/wireless/bcm4329/dhd.h b/drivers/net/wireless/bcm4329/dhd.h deleted file mode 100644 index 1c5f8dd796f4..000000000000 --- a/drivers/net/wireless/bcm4329/dhd.h +++ /dev/null @@ -1,521 +0,0 @@ -/* - * Header file describing the internal (inter-module) DHD interfaces. - * - * Provides type definitions and function prototypes used to link the - * DHD OS, bus, and protocol modules. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd.h,v 1.32.4.7.2.4.14.44 2010/06/03 21:27:48 Exp $ - */ - -/**************** - * Common types * - */ - -#ifndef _dhd_h_ -#define _dhd_h_ - -#if defined(LINUX) -#if defined(CHROMIUMOS_COMPAT_WIRELESS) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) -#include -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -/* The kernel threading is sdio-specific */ -#else /* LINUX */ -#define ENOMEM 1 -#define EFAULT 2 -#define EINVAL 3 -#define EIO 4 -#define ETIMEDOUT 5 -#define ERESTARTSYS 6 -#endif /* LINUX */ - -#include - - -/* Forward decls */ -struct dhd_bus; -struct dhd_prot; -struct dhd_info; - -/* The level of bus communication with the dongle */ -enum dhd_bus_state { - DHD_BUS_DOWN, /* Not ready for frame transfers */ - DHD_BUS_LOAD, /* Download access only (CPU reset) */ - DHD_BUS_DATA /* Ready for frame transfers */ -}; - -enum dhd_bus_wake_state { - WAKE_LOCK_OFF, - WAKE_LOCK_PRIV, - WAKE_LOCK_DPC, - WAKE_LOCK_IOCTL, - WAKE_LOCK_DOWNLOAD, - WAKE_LOCK_TMOUT, - WAKE_LOCK_WATCHDOG, - WAKE_LOCK_LINK_DOWN_TMOUT, - WAKE_LOCK_SOFTAP_SET, - WAKE_LOCK_SOFTAP_STOP, - WAKE_LOCK_SOFTAP_START, - WAKE_LOCK_MAX -}; -enum dhd_prealloc_index { - DHD_PREALLOC_PROT = 0, - DHD_PREALLOC_RXBUF, - DHD_PREALLOC_DATABUF, - DHD_PREALLOC_OSL_BUF -}; -#ifdef DHD_USE_STATIC_BUF -extern void * dhd_os_prealloc(int section, unsigned long size); -#endif -/* Common structure for module and instance linkage */ -typedef struct dhd_pub { - /* Linkage ponters */ - osl_t *osh; /* OSL handle */ - struct dhd_bus *bus; /* Bus module handle */ - struct dhd_prot *prot; /* Protocol module handle */ - struct dhd_info *info; /* Info module handle */ - - /* Internal dhd items */ - bool up; /* Driver up/down (to OS) */ - bool txoff; /* Transmit flow-controlled */ - bool dongle_reset; /* TRUE = DEVRESET put dongle into reset */ - enum dhd_bus_state busstate; - uint hdrlen; /* Total DHD header length (proto + bus) */ - uint maxctl; /* Max size rxctl request from proto to bus */ - uint rxsz; /* Rx buffer size bus module should use */ - uint8 wme_dp; /* wme discard priority */ - - /* Dongle media info */ - bool iswl; /* Dongle-resident driver is wl */ - ulong drv_version; /* Version of dongle-resident driver */ - struct ether_addr mac; /* MAC address obtained from dongle */ - dngl_stats_t dstats; /* Stats for dongle-based data */ - - /* Additional stats for the bus level */ - ulong tx_packets; /* Data packets sent to dongle */ - ulong tx_multicast; /* Multicast data packets sent to dongle */ - ulong tx_errors; /* Errors in sending data to dongle */ - ulong tx_ctlpkts; /* Control packets sent to dongle */ - ulong tx_ctlerrs; /* Errors sending control frames to dongle */ - ulong rx_packets; /* Packets sent up the network interface */ - ulong rx_multicast; /* Multicast packets sent up the network interface */ - ulong rx_errors; /* Errors processing rx data packets */ - ulong rx_ctlpkts; /* Control frames processed from dongle */ - ulong rx_ctlerrs; /* Errors in processing rx control frames */ - ulong rx_dropped; /* Packets dropped locally (no memory) */ - ulong rx_flushed; /* Packets flushed due to unscheduled sendup thread */ - ulong wd_dpc_sched; /* Number of times dhd dpc scheduled by watchdog timer */ - - ulong rx_readahead_cnt; /* Number of packets where header read-ahead was used. */ - ulong tx_realloc; /* Number of tx packets we had to realloc for headroom */ - ulong fc_packets; /* Number of flow control pkts recvd */ - - /* Last error return */ - int bcmerror; - uint tickcnt; - - /* Last error from dongle */ - int dongle_error; - - /* Pkt filter defination */ - char * pktfilter[100]; - int pktfilter_count; - - uint8 country_code[WLC_CNTRY_BUF_SZ]; - char eventmask[WL_EVENTING_MASK_LEN]; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - struct wake_lock wakelock[WAKE_LOCK_MAX]; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ - struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ -#endif -} dhd_pub_t; - - - #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) - - #define DHD_PM_RESUME_WAIT_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); - #define _DHD_PM_RESUME_WAIT(a, b) do {\ - int retry = 0; \ - while (dhd_mmc_suspend && retry++ != b) { \ - wait_event_timeout(a, FALSE, HZ/100); \ - } \ - } while (0) - #define DHD_PM_RESUME_WAIT(a) _DHD_PM_RESUME_WAIT(a, 30) - #define DHD_PM_RESUME_WAIT_FOREVER(a) _DHD_PM_RESUME_WAIT(a, ~0) - #define DHD_PM_RESUME_RETURN_ERROR(a) do { if (dhd_mmc_suspend) return a; } while (0) - #define DHD_PM_RESUME_RETURN do { if (dhd_mmc_suspend) return; } while (0) - - #define DHD_SPINWAIT_SLEEP_INIT(a) DECLARE_WAIT_QUEUE_HEAD(a); - #define SPINWAIT_SLEEP(a, exp, us) do { \ - uint countdown = (us) + 9999; \ - while ((exp) && (countdown >= 10000)) { \ - wait_event_timeout(a, FALSE, HZ/100); \ - countdown -= 10000; \ - } \ - } while (0) - - #else - - #define DHD_PM_RESUME_WAIT_INIT(a) - #define DHD_PM_RESUME_WAIT(a) - #define DHD_PM_RESUME_WAIT_FOREVER(a) - #define DHD_PM_RESUME_RETURN_ERROR(a) - #define DHD_PM_RESUME_RETURN - - #define DHD_SPINWAIT_SLEEP_INIT(a) - #define SPINWAIT_SLEEP(a, exp, us) do { \ - uint countdown = (us) + 9; \ - while ((exp) && (countdown >= 10)) { \ - OSL_DELAY(10); \ - countdown -= 10; \ - } \ - } while (0) - - #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ -#define DHD_IF_VIF 0x01 /* Virtual IF (Hidden from user) */ - -inline static void MUTEX_LOCK_INIT(dhd_pub_t * dhdp) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_init(&dhdp->wl_start_stop_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_LOCK(dhd_pub_t * dhdp) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_lock(&dhdp->wl_start_stop_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_UNLOCK(dhd_pub_t * dhdp) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_unlock(&dhdp->wl_start_stop_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_init(&dhdp->wl_softap_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_LOCK_SOFTAP_SET(dhd_pub_t * dhdp) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_lock(&dhdp->wl_softap_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_unlock(&dhdp->wl_softap_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 -extern struct mutex g_wl_ss_scan_lock; /* lock/unlock for Scan/Cache settings */ -#endif - -inline static void MUTEX_LOCK_WL_SCAN_SET_INIT(void) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_init(&g_wl_ss_scan_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_LOCK_WL_SCAN_SET(void) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_lock(&g_wl_ss_scan_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void MUTEX_UNLOCK_WL_SCAN_SET(void) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - mutex_unlock(&g_wl_ss_scan_lock); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -inline static void WAKE_LOCK_INIT(dhd_pub_t * dhdp, int index, char * y) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - wake_lock_init(&dhdp->wakelock[index], WAKE_LOCK_SUSPEND, y); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -} - -inline static void WAKE_LOCK(dhd_pub_t * dhdp, int index) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - wake_lock(&dhdp->wakelock[index]); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -} - -inline static void WAKE_UNLOCK(dhd_pub_t * dhdp, int index) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - wake_unlock(&dhdp->wakelock[index]); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -} - -inline static void WAKE_LOCK_TIMEOUT(dhd_pub_t * dhdp, int index, long time) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - wake_lock_timeout(&dhdp->wakelock[index], time); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -} - -inline static void WAKE_LOCK_DESTROY(dhd_pub_t * dhdp, int index) -{ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) - wake_lock_destroy(&dhdp->wakelock[index]); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ -} - - -typedef struct dhd_if_event { - uint8 ifidx; - uint8 action; - uint8 flags; - uint8 bssidx; -} dhd_if_event_t; - -/* - * Exported from dhd OS modules (dhd_linux/dhd_ndis) - */ - -/* To allow osl_attach/detach calls from os-independent modules */ -osl_t *dhd_osl_attach(void *pdev, uint bustype); -void dhd_osl_detach(osl_t *osh); - -/* Indication from bus module regarding presence/insertion of dongle. - * Return dhd_pub_t pointer, used as handle to OS module in later calls. - * Returned structure should have bus and prot pointers filled in. - * bus_hdrlen specifies required headroom for bus module header. - */ -extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen); -extern int dhd_net_attach(dhd_pub_t *dhdp, int idx); - -/* Indication from bus module regarding removal/absence of dongle */ -extern void dhd_detach(dhd_pub_t *dhdp); - -/* Indication from bus module to change flow-control state */ -extern void dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool on); - -extern bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec); - -/* Receive frame for delivery to OS. Callee disposes of rxp. */ -extern void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *rxp, int numpkt); - -/* Return pointer to interface name */ -extern char *dhd_ifname(dhd_pub_t *dhdp, int idx); - -/* Request scheduling of the bus dpc */ -extern void dhd_sched_dpc(dhd_pub_t *dhdp); - -/* Notify tx completion */ -extern void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success); - -/* Query ioctl */ -extern int dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); - -/* OS independent layer functions */ -extern int dhd_os_proto_block(dhd_pub_t * pub); -extern int dhd_os_proto_unblock(dhd_pub_t * pub); -extern int dhd_os_ioctl_resp_wait(dhd_pub_t * pub, uint * condition, bool * pending); -extern int dhd_os_ioctl_resp_wake(dhd_pub_t * pub); -extern unsigned int dhd_os_get_ioctl_resp_timeout(void); -extern void dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec); -extern void * dhd_os_open_image(char * filename); -extern int dhd_os_get_image_block(char * buf, int len, void * image); -extern void dhd_os_close_image(void * image); -extern void dhd_os_wd_timer(void *bus, uint wdtick); -extern void dhd_os_sdlock(dhd_pub_t * pub); -extern void dhd_os_sdunlock(dhd_pub_t * pub); -extern void dhd_os_sdlock_txq(dhd_pub_t * pub); -extern void dhd_os_sdunlock_txq(dhd_pub_t * pub); -extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); -extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); -extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); -extern void dhd_customer_gpio_wlan_ctrl(int onoff); -extern int dhd_custom_get_mac_address(unsigned char *buf); -extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); -extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); -extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); -#ifdef DHD_DEBUG -extern int write_to_file(dhd_pub_t *dhd, uint8 *buf, int size); -#endif /* DHD_DEBUG */ -#if defined(OOB_INTR_ONLY) -extern int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr); -#endif /* defined(OOB_INTR_ONLY) */ -extern void dhd_os_sdtxlock(dhd_pub_t * pub); -extern void dhd_os_sdtxunlock(dhd_pub_t * pub); - -int setScheduler(struct task_struct *p, int policy, struct sched_param *param); - -typedef struct { - uint32 limit; /* Expiration time (usec) */ - uint32 increment; /* Current expiration increment (usec) */ - uint32 elapsed; /* Current elapsed time (usec) */ - uint32 tick; /* O/S tick time (usec) */ -} dhd_timeout_t; - -extern void dhd_timeout_start(dhd_timeout_t *tmo, uint usec); -extern int dhd_timeout_expired(dhd_timeout_t *tmo); - -extern int dhd_ifname2idx(struct dhd_info *dhd, char *name); -extern uint8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx); -extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata, - wl_event_msg_t *, void **data_ptr); -extern void wl_event_to_host_order(wl_event_msg_t * evt); - -extern void dhd_common_init(void); - -extern int dhd_add_if(struct dhd_info *dhd, int ifidx, void *handle, - char *name, uint8 *mac_addr, uint32 flags, uint8 bssidx); -extern void dhd_del_if(struct dhd_info *dhd, int ifidx); - -extern void dhd_vif_add(struct dhd_info *dhd, int ifidx, char * name); -extern void dhd_vif_del(struct dhd_info *dhd, int ifidx); - -extern void dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx); -extern void dhd_vif_sendup(struct dhd_info *dhd, int ifidx, uchar *cp, int len); - - -/* Send packet to dongle via data channel */ -extern int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pkt); - -/* Send event to host */ -extern void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data); -extern int dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag); -extern uint dhd_bus_status(dhd_pub_t *dhdp); -extern int dhd_bus_start(dhd_pub_t *dhdp); - -extern void print_buf(void *pbuf, int len, int bytes_per_line); - - -typedef enum cust_gpio_modes { - WLAN_RESET_ON, - WLAN_RESET_OFF, - WLAN_POWER_ON, - WLAN_POWER_OFF -} cust_gpio_modes_t; -extern int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); -extern int wl_iw_send_priv_event(struct net_device *dev, char *flag); -/* - * Insmod parameters for debug/test - */ - -/* Watchdog timer interval */ -extern uint dhd_watchdog_ms; - -#if defined(DHD_DEBUG) -/* Console output poll interval */ -extern uint dhd_console_ms; -#endif /* defined(DHD_DEBUG) */ - -/* Use interrupts */ -extern uint dhd_intr; - -/* Use polling */ -extern uint dhd_poll; - -/* ARP offload agent mode */ -extern uint dhd_arp_mode; - -/* ARP offload enable */ -extern uint dhd_arp_enable; - -/* Pkt filte enable control */ -extern uint dhd_pkt_filter_enable; - -/* Pkt filter init setup */ -extern uint dhd_pkt_filter_init; - -/* Pkt filter mode control */ -extern uint dhd_master_mode; - -/* Roaming mode control */ -extern uint dhd_roam; - -/* Roaming mode control */ -extern uint dhd_radio_up; - -/* Initial idletime ticks (may be -1 for immediate idle, 0 for no idle) */ -extern int dhd_idletime; -#define DHD_IDLETIME_TICKS 1 - -/* SDIO Drive Strength */ -extern uint dhd_sdiod_drive_strength; - -/* Override to force tx queueing all the time */ -extern uint dhd_force_tx_queueing; - -#ifdef SDTEST -/* Echo packet generator (SDIO), pkts/s */ -extern uint dhd_pktgen; - -/* Echo packet len (0 => sawtooth, max 1800) */ -extern uint dhd_pktgen_len; -#define MAX_PKTGEN_LEN 1800 -#endif - - -/* optionally set by a module_param_string() */ -#define MOD_PARAM_PATHLEN 2048 -extern char fw_path[MOD_PARAM_PATHLEN]; -extern char nv_path[MOD_PARAM_PATHLEN]; - -/* For supporting multiple interfaces */ -#define DHD_MAX_IFS 16 -#define DHD_DEL_IF -0xe -#define DHD_BAD_IF -0xf - -#ifdef APSTA_PINGTEST -#define MAX_GUEST 8 -#endif - -extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar); -extern void dhd_wait_event_wakeup(dhd_pub_t*dhd); - -#endif /* _dhd_h_ */ diff --git a/drivers/net/wireless/bcm4329/dhd_bus.h b/drivers/net/wireless/bcm4329/dhd_bus.h deleted file mode 100644 index 9e29fb955444..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_bus.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Header file describing the internal (inter-module) DHD interfaces. - * - * Provides type definitions and function prototypes used to link the - * DHD OS, bus, and protocol modules. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_bus.h,v 1.4.6.3.2.3.6.6 2010/05/17 18:18:13 Exp $ - */ - -#ifndef _dhd_bus_h_ -#define _dhd_bus_h_ - -/* - * Exported from dhd bus module (dhd_usb, dhd_sdio) - */ - -/* Indicate (dis)interest in finding dongles. */ -extern int dhd_bus_register(void); -extern void dhd_bus_unregister(void); - -/* Download firmware image and nvram image */ -extern bool dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, - char *fw_path, char *nv_path); - -/* Stop bus module: clear pending frames, disable data flow */ -extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex); - -/* Initialize bus module: prepare for communication w/dongle */ -extern int dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex); - -/* Send a data frame to the dongle. Callee disposes of txp. */ -extern int dhd_bus_txdata(struct dhd_bus *bus, void *txp); - -/* Send/receive a control message to/from the dongle. - * Expects caller to enforce a single outstanding transaction. - */ -extern int dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen); -extern int dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen); - -/* Watchdog timer function */ -extern bool dhd_bus_watchdog(dhd_pub_t *dhd); - -#ifdef DHD_DEBUG -/* Device console input function */ -extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen); -#endif - -/* Deferred processing for the bus, return TRUE requests reschedule */ -extern bool dhd_bus_dpc(struct dhd_bus *bus); -extern void dhd_bus_isr(bool * InterruptRecognized, bool * QueueMiniportHandleInterrupt, void *arg); - - -/* Check for and handle local prot-specific iovar commands */ -extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, - void *params, int plen, void *arg, int len, bool set); - -/* Add bus dump output to a buffer */ -extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); - -/* Clear any bus counters */ -extern void dhd_bus_clearcounts(dhd_pub_t *dhdp); - -/* return the dongle chipid */ -extern uint dhd_bus_chip(struct dhd_bus *bus); - -/* Set user-specified nvram parameters. */ -extern void dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params); - -extern void *dhd_bus_pub(struct dhd_bus *bus); -extern void *dhd_bus_txq(struct dhd_bus *bus); -extern uint dhd_bus_hdrlen(struct dhd_bus *bus); - -#endif /* _dhd_bus_h_ */ diff --git a/drivers/net/wireless/bcm4329/dhd_cdc.c b/drivers/net/wireless/bcm4329/dhd_cdc.c deleted file mode 100644 index e98af39c48a4..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_cdc.c +++ /dev/null @@ -1,548 +0,0 @@ -/* - * DHD Protocol Module for CDC and BDC. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_cdc.c,v 1.22.4.2.4.7.2.41 2010/06/23 19:58:18 Exp $ - * - * BDC is like CDC, except it includes a header for data packets to convey - * packet priority over the bus, and flags (e.g. to indicate checksum status - * for dongle offload). - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#ifdef CUSTOMER_HW2 -int wifi_get_mac_addr(unsigned char *buf); -#endif - -extern int dhd_preinit_ioctls(dhd_pub_t *dhd); - - -/* Packet alignment for most efficient SDIO (can change based on platform) */ -#ifndef DHD_SDALIGN -#define DHD_SDALIGN 32 -#endif -#if !ISPOWEROF2(DHD_SDALIGN) -#error DHD_SDALIGN is not a power of 2! -#endif - -#define RETRIES 2 /* # of retries to retrieve matching ioctl response */ -#define BUS_HEADER_LEN (16+DHD_SDALIGN) /* Must be atleast SDPCM_RESERVE - * defined in dhd_sdio.c (amount of header tha might be added) - * plus any space that might be needed for alignment padding. - */ -#define ROUND_UP_MARGIN 2048 /* Biggest SDIO block size possible for - * round off at the end of buffer - */ - -typedef struct dhd_prot { - uint16 reqid; - uint8 pending; - uint32 lastcmd; - uint8 bus_header[BUS_HEADER_LEN]; - cdc_ioctl_t msg; - unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN]; -} dhd_prot_t; - -static int -dhdcdc_msg(dhd_pub_t *dhd) -{ - dhd_prot_t *prot = dhd->prot; - int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t); - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* NOTE : cdc->msg.len holds the desired length of the buffer to be - * returned. Only up to CDC_MAX_MSG_SIZE of this buffer area - * is actually sent to the dongle - */ - if (len > CDC_MAX_MSG_SIZE) - len = CDC_MAX_MSG_SIZE; - - /* Send request */ - return dhd_bus_txctl(dhd->bus, (uchar*)&prot->msg, len); -} - -static int -dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len) -{ - int ret; - dhd_prot_t *prot = dhd->prot; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - do { - ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, len+sizeof(cdc_ioctl_t)); - if (ret < 0) - break; - } while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id); - - return ret; -} - -int -dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) -{ - dhd_prot_t *prot = dhd->prot; - cdc_ioctl_t *msg = &prot->msg; - void *info; - int ret = 0, retries = 0; - uint32 id, flags = 0; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len)); - - - /* Respond "bcmerror" and "bcmerrorstr" with local cache */ - if (cmd == WLC_GET_VAR && buf) - { - if (!strcmp((char *)buf, "bcmerrorstr")) - { - strncpy((char *)buf, bcmerrorstr(dhd->dongle_error), BCME_STRLEN); - goto done; - } - else if (!strcmp((char *)buf, "bcmerror")) - { - *(int *)buf = dhd->dongle_error; - goto done; - } - } - - memset(msg, 0, sizeof(cdc_ioctl_t)); - - msg->cmd = htol32(cmd); - msg->len = htol32(len); - msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT); - CDC_SET_IF_IDX(msg, ifidx); - msg->flags = htol32(msg->flags); - - if (buf) - memcpy(prot->buf, buf, len); - - if ((ret = dhdcdc_msg(dhd)) < 0) { - DHD_ERROR(("dhdcdc_query_ioctl: dhdcdc_msg failed w/status %d\n", ret)); - goto done; - } - -retry: - /* wait for interrupt and get first fragment */ - if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0) - goto done; - - flags = ltoh32(msg->flags); - id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT; - - if ((id < prot->reqid) && (++retries < RETRIES)) - goto retry; - if (id != prot->reqid) { - DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n", - dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid)); - ret = -EINVAL; - goto done; - } - - /* Check info buffer */ - info = (void*)&msg[1]; - - /* Copy info buffer */ - if (buf) - { - if (ret < (int)len) - len = ret; - memcpy(buf, info, len); - } - - /* Check the ERROR flag */ - if (flags & CDCF_IOC_ERROR) - { - ret = ltoh32(msg->status); - /* Cache error from dongle */ - dhd->dongle_error = ret; - } - -done: - return ret; -} - -int -dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len) -{ - dhd_prot_t *prot = dhd->prot; - cdc_ioctl_t *msg = &prot->msg; - int ret = 0; - uint32 flags, id; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - DHD_CTL(("%s: cmd %d len %d\n", __FUNCTION__, cmd, len)); - - memset(msg, 0, sizeof(cdc_ioctl_t)); - - msg->cmd = htol32(cmd); - msg->len = htol32(len); - msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET; - CDC_SET_IF_IDX(msg, ifidx); - msg->flags = htol32(msg->flags); - - if (buf) - memcpy(prot->buf, buf, len); - - if ((ret = dhdcdc_msg(dhd)) < 0) - goto done; - - if ((ret = dhdcdc_cmplt(dhd, prot->reqid, len)) < 0) - goto done; - - flags = ltoh32(msg->flags); - id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT; - - if (id != prot->reqid) { - DHD_ERROR(("%s: %s: unexpected request id %d (expected %d)\n", - dhd_ifname(dhd, ifidx), __FUNCTION__, id, prot->reqid)); - ret = -EINVAL; - goto done; - } - - /* Check the ERROR flag */ - if (flags & CDCF_IOC_ERROR) - { - ret = ltoh32(msg->status); - /* Cache error from dongle */ - dhd->dongle_error = ret; - } - -done: - return ret; -} - -extern int dhd_bus_interface(struct dhd_bus *bus, uint arg, void* arg2); -int -dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len) -{ - dhd_prot_t *prot = dhd->prot; - int ret = -1; - - if (dhd->busstate == DHD_BUS_DOWN) { - DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); - return ret; - } - dhd_os_proto_block(dhd); - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - ASSERT(len <= WLC_IOCTL_MAXLEN); - - if (len > WLC_IOCTL_MAXLEN) - goto done; - - if (prot->pending == TRUE) { - DHD_TRACE(("CDC packet is pending!!!! cmd=0x%x (%lu) lastcmd=0x%x (%lu)\n", - ioc->cmd, (unsigned long)ioc->cmd, prot->lastcmd, - (unsigned long)prot->lastcmd)); - if ((ioc->cmd == WLC_SET_VAR) || (ioc->cmd == WLC_GET_VAR)) { - DHD_TRACE(("iovar cmd=%s\n", (char*)buf)); - } - goto done; - } - - prot->pending = TRUE; - prot->lastcmd = ioc->cmd; - if (ioc->set) - ret = dhdcdc_set_ioctl(dhd, ifidx, ioc->cmd, buf, len); - else { - ret = dhdcdc_query_ioctl(dhd, ifidx, ioc->cmd, buf, len); - if (ret > 0) - ioc->used = ret - sizeof(cdc_ioctl_t); - } - - /* Too many programs assume ioctl() returns 0 on success */ - if (ret >= 0) - ret = 0; - else { - cdc_ioctl_t *msg = &prot->msg; - ioc->needed = ltoh32(msg->len); /* len == needed when set/query fails from dongle */ - } - - /* Intercept the wme_dp ioctl here */ - if ((!ret) && (ioc->cmd == WLC_SET_VAR) && (!strcmp(buf, "wme_dp"))) { - int slen, val = 0; - - slen = strlen("wme_dp") + 1; - if (len >= (int)(slen + sizeof(int))) - bcopy(((char *)buf + slen), &val, sizeof(int)); - dhd->wme_dp = (uint8) ltoh32(val); - } - - prot->pending = FALSE; - -done: - dhd_os_proto_unblock(dhd); - - return ret; -} - -int -dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - return BCME_UNSUPPORTED; -} - -void -dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) -{ - bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); -} - -#ifdef APSTA_PINGTEST -extern struct ether_addr guest_eas[MAX_GUEST]; -#endif - -void -dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) -{ -#ifdef BDC - struct bdc_header *h; -#ifdef APSTA_PINGTEST - struct ether_header *eh; - int i; -#ifdef DHD_DEBUG - char eabuf1[ETHER_ADDR_STR_LEN]; - char eabuf2[ETHER_ADDR_STR_LEN]; -#endif /* DHD_DEBUG */ -#endif /* APSTA_PINGTEST */ -#endif /* BDC */ - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - -#ifdef BDC - /* Push BDC header used to convey priority for buses that don't */ - -#ifdef APSTA_PINGTEST - eh = (struct ether_header *)PKTDATA(dhd->osh, pktbuf); -#endif - - PKTPUSH(dhd->osh, pktbuf, BDC_HEADER_LEN); - - h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); - - h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); - if (PKTSUMNEEDED(pktbuf)) - h->flags |= BDC_FLAG_SUM_NEEDED; - - - h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK); - h->flags2 = 0; -#ifdef APSTA_PINGTEST - for (i = 0; i < MAX_GUEST; ++i) { - if (!ETHER_ISNULLADDR(eh->ether_dhost) && - bcmp(eh->ether_dhost, guest_eas[i].octet, ETHER_ADDR_LEN) == 0) { - DHD_TRACE(("send on if 1; sa %s, da %s\n", - bcm_ether_ntoa((struct ether_addr *)(eh->ether_shost), eabuf1), - bcm_ether_ntoa((struct ether_addr *)(eh->ether_dhost), eabuf2))); - /* assume all guest STAs are on interface 1 */ - h->flags2 = 1; - break; - } - } -#endif /* APSTA_PINGTEST */ - h->rssi = 0; -#endif /* BDC */ - BDC_SET_IF_IDX(h, ifidx); -} - - -bool -dhd_proto_fcinfo(dhd_pub_t *dhd, void *pktbuf, uint8 *fcbits) -{ -#ifdef BDC - struct bdc_header *h; - - if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) { - DHD_ERROR(("%s: rx data too short (%d < %d)\n", - __FUNCTION__, PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN)); - return BCME_ERROR; - } - - h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); - - *fcbits = h->priority >> BDC_PRIORITY_FC_SHIFT; - if ((h->flags2 & BDC_FLAG2_FC_FLAG) == BDC_FLAG2_FC_FLAG) - return TRUE; -#endif - return FALSE; -} - - -int -dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf) -{ -#ifdef BDC - struct bdc_header *h; -#endif - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - -#ifdef BDC - /* Pop BDC header used to convey priority for buses that don't */ - - if (PKTLEN(dhd->osh, pktbuf) < BDC_HEADER_LEN) { - DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__, - PKTLEN(dhd->osh, pktbuf), BDC_HEADER_LEN)); - return BCME_ERROR; - } - - h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); - - if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) { - DHD_ERROR(("%s: rx data ifnum out of range (%d)\n", - __FUNCTION__, *ifidx)); - return BCME_ERROR; - } - - if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) { - DHD_ERROR(("%s: non-BDC packet received, flags 0x%x\n", - dhd_ifname(dhd, *ifidx), h->flags)); - return BCME_ERROR; - } - - if (h->flags & BDC_FLAG_SUM_GOOD) { - DHD_INFO(("%s: BDC packet received with good rx-csum, flags 0x%x\n", - dhd_ifname(dhd, *ifidx), h->flags)); - PKTSETSUMGOOD(pktbuf, TRUE); - } - - PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK)); - - PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); -#endif /* BDC */ - - return 0; -} - -int -dhd_prot_attach(dhd_pub_t *dhd) -{ - dhd_prot_t *cdc; - -#ifndef DHD_USE_STATIC_BUF - if (!(cdc = (dhd_prot_t *)MALLOC(dhd->osh, sizeof(dhd_prot_t)))) { - DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); - goto fail; - } -#else - if (!(cdc = (dhd_prot_t *)dhd_os_prealloc(DHD_PREALLOC_PROT, sizeof(dhd_prot_t)))) { - DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); - goto fail; - } -#endif /* DHD_USE_STATIC_BUF */ - memset(cdc, 0, sizeof(dhd_prot_t)); - - /* ensure that the msg buf directly follows the cdc msg struct */ - if ((uintptr)(&cdc->msg + 1) != (uintptr)cdc->buf) { - DHD_ERROR(("dhd_prot_t is not correctly defined\n")); - goto fail; - } - - dhd->prot = cdc; -#ifdef BDC - dhd->hdrlen += BDC_HEADER_LEN; -#endif - dhd->maxctl = WLC_IOCTL_MAXLEN + sizeof(cdc_ioctl_t) + ROUND_UP_MARGIN; - return 0; - -fail: -#ifndef DHD_USE_STATIC_BUF - if (cdc != NULL) - MFREE(dhd->osh, cdc, sizeof(dhd_prot_t)); -#endif - return BCME_NOMEM; -} - -/* ~NOTE~ What if another thread is waiting on the semaphore? Holding it? */ -void -dhd_prot_detach(dhd_pub_t *dhd) -{ -#ifndef DHD_USE_STATIC_BUF - MFREE(dhd->osh, dhd->prot, sizeof(dhd_prot_t)); -#endif - dhd->prot = NULL; -} - -void -dhd_prot_dstats(dhd_pub_t *dhd) -{ - /* No stats from dongle added yet, copy bus stats */ - dhd->dstats.tx_packets = dhd->tx_packets; - dhd->dstats.tx_errors = dhd->tx_errors; - dhd->dstats.rx_packets = dhd->rx_packets; - dhd->dstats.rx_errors = dhd->rx_errors; - dhd->dstats.rx_dropped = dhd->rx_dropped; - dhd->dstats.multicast = dhd->rx_multicast; - return; -} - -int -dhd_prot_init(dhd_pub_t *dhd) -{ - int ret = 0; - char buf[128]; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - dhd_os_proto_block(dhd); - - /* Get the device MAC address */ - strcpy(buf, "cur_etheraddr"); - ret = dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf)); - if (ret < 0) { - dhd_os_proto_unblock(dhd); - return ret; - } - memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN); - - dhd_os_proto_unblock(dhd); - -#ifdef EMBEDDED_PLATFORM - ret = dhd_preinit_ioctls(dhd); -#endif /* EMBEDDED_PLATFORM */ - - /* Always assumes wl for now */ - dhd->iswl = TRUE; - - return ret; -} - -void -dhd_prot_stop(dhd_pub_t *dhd) -{ - /* Nothing to do for CDC */ -} diff --git a/drivers/net/wireless/bcm4329/dhd_common.c b/drivers/net/wireless/bcm4329/dhd_common.c deleted file mode 100644 index 2fe30bdfdde5..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_common.c +++ /dev/null @@ -1,1979 +0,0 @@ -/* - * Broadcom Dongle Host Driver (DHD), common DHD core. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_common.c,v 1.5.6.8.2.6.6.65 2010/07/07 00:05:07 Exp $ - */ -#include -#include - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - - -#include - -int dhd_msg_level; - - -#if defined(CSCAN) -#include -#endif - -char fw_path[MOD_PARAM_PATHLEN]; -char nv_path[MOD_PARAM_PATHLEN]; - -/* Last connection success/failure status */ -uint32 dhd_conn_event; -uint32 dhd_conn_status; -uint32 dhd_conn_reason; - -#define htod32(i) i -#define htod16(i) i -#define dtoh32(i) i -#define dtoh16(i) i - -extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); -extern void dhd_ind_scan_confirm(void *h, bool status); -extern int dhd_wl_ioctl(dhd_pub_t *dhd, uint cmd, char *buf, uint buflen); -void dhd_iscan_lock(void); -void dhd_iscan_unlock(void); - -/* Packet alignment for most efficient SDIO (can change based on platform) */ -#ifndef DHD_SDALIGN -#define DHD_SDALIGN 32 -#endif -#if !ISPOWEROF2(DHD_SDALIGN) -#error DHD_SDALIGN is not a power of 2! -#endif - -#ifdef DHD_DEBUG -const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " - __DATE__ " at " __TIME__; -#else -const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR; -#endif - -void dhd_set_timer(void *bus, uint wdtick); - -/* IOVar table */ -enum { - IOV_VERSION = 1, - IOV_MSGLEVEL, - IOV_BCMERRORSTR, - IOV_BCMERROR, - IOV_WDTICK, - IOV_DUMP, -#ifdef DHD_DEBUG - IOV_CONS, - IOV_DCONSOLE_POLL, -#endif - IOV_CLEARCOUNTS, - IOV_LOGDUMP, - IOV_LOGCAL, - IOV_LOGSTAMP, - IOV_GPIOOB, - IOV_IOCTLTIMEOUT, - IOV_LAST -}; - -const bcm_iovar_t dhd_iovars[] = { - {"version", IOV_VERSION, 0, IOVT_BUFFER, sizeof(dhd_version) }, -#ifdef DHD_DEBUG - {"msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, -#endif /* DHD_DEBUG */ - {"bcmerrorstr", IOV_BCMERRORSTR, 0, IOVT_BUFFER, BCME_STRLEN }, - {"bcmerror", IOV_BCMERROR, 0, IOVT_INT8, 0 }, - {"wdtick", IOV_WDTICK, 0, IOVT_UINT32, 0 }, - {"dump", IOV_DUMP, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, -#ifdef DHD_DEBUG - {"dconpoll", IOV_DCONSOLE_POLL, 0, IOVT_UINT32, 0 }, - {"cons", IOV_CONS, 0, IOVT_BUFFER, 0 }, -#endif - {"clearcounts", IOV_CLEARCOUNTS, 0, IOVT_VOID, 0 }, - {"gpioob", IOV_GPIOOB, 0, IOVT_UINT32, 0 }, - {"ioctl_timeout", IOV_IOCTLTIMEOUT, 0, IOVT_UINT32, 0 }, - {NULL, 0, 0, 0, 0 } -}; - -void -dhd_common_init(void) -{ - /* Init global variables at run-time, not as part of the declaration. - * This is required to support init/de-init of the driver. Initialization - * of globals as part of the declaration results in non-deterministic - * behaviour since the value of the globals may be different on the - * first time that the driver is initialized vs subsequent initializations. - */ - dhd_msg_level = DHD_ERROR_VAL; -#ifdef CONFIG_BCM4329_FW_PATH - strncpy(fw_path, CONFIG_BCM4329_FW_PATH, MOD_PARAM_PATHLEN-1); -#else - fw_path[0] = '\0'; -#endif -#ifdef CONFIG_BCM4329_NVRAM_PATH - strncpy(nv_path, CONFIG_BCM4329_NVRAM_PATH, MOD_PARAM_PATHLEN-1); -#else - nv_path[0] = '\0'; -#endif -} - -static int -dhd_dump(dhd_pub_t *dhdp, char *buf, int buflen) -{ - char eabuf[ETHER_ADDR_STR_LEN]; - - struct bcmstrbuf b; - struct bcmstrbuf *strbuf = &b; - - bcm_binit(strbuf, buf, buflen); - - /* Base DHD info */ - bcm_bprintf(strbuf, "%s\n", dhd_version); - bcm_bprintf(strbuf, "\n"); - bcm_bprintf(strbuf, "pub.up %d pub.txoff %d pub.busstate %d\n", - dhdp->up, dhdp->txoff, dhdp->busstate); - bcm_bprintf(strbuf, "pub.hdrlen %d pub.maxctl %d pub.rxsz %d\n", - dhdp->hdrlen, dhdp->maxctl, dhdp->rxsz); - bcm_bprintf(strbuf, "pub.iswl %d pub.drv_version %ld pub.mac %s\n", - dhdp->iswl, dhdp->drv_version, bcm_ether_ntoa(&dhdp->mac, eabuf)); - bcm_bprintf(strbuf, "pub.bcmerror %d tickcnt %d\n", dhdp->bcmerror, dhdp->tickcnt); - - bcm_bprintf(strbuf, "dongle stats:\n"); - bcm_bprintf(strbuf, "tx_packets %ld tx_bytes %ld tx_errors %ld tx_dropped %ld\n", - dhdp->dstats.tx_packets, dhdp->dstats.tx_bytes, - dhdp->dstats.tx_errors, dhdp->dstats.tx_dropped); - bcm_bprintf(strbuf, "rx_packets %ld rx_bytes %ld rx_errors %ld rx_dropped %ld\n", - dhdp->dstats.rx_packets, dhdp->dstats.rx_bytes, - dhdp->dstats.rx_errors, dhdp->dstats.rx_dropped); - bcm_bprintf(strbuf, "multicast %ld\n", dhdp->dstats.multicast); - - bcm_bprintf(strbuf, "bus stats:\n"); - bcm_bprintf(strbuf, "tx_packets %ld tx_multicast %ld tx_errors %ld\n", - dhdp->tx_packets, dhdp->tx_multicast, dhdp->tx_errors); - bcm_bprintf(strbuf, "tx_ctlpkts %ld tx_ctlerrs %ld\n", - dhdp->tx_ctlpkts, dhdp->tx_ctlerrs); - bcm_bprintf(strbuf, "rx_packets %ld rx_multicast %ld rx_errors %ld \n", - dhdp->rx_packets, dhdp->rx_multicast, dhdp->rx_errors); - bcm_bprintf(strbuf, "rx_ctlpkts %ld rx_ctlerrs %ld rx_dropped %ld rx_flushed %ld\n", - dhdp->rx_ctlpkts, dhdp->rx_ctlerrs, dhdp->rx_dropped, dhdp->rx_flushed); - bcm_bprintf(strbuf, "rx_readahead_cnt %ld tx_realloc %ld fc_packets %ld\n", - dhdp->rx_readahead_cnt, dhdp->tx_realloc, dhdp->fc_packets); - bcm_bprintf(strbuf, "wd_dpc_sched %ld\n", dhdp->wd_dpc_sched); - bcm_bprintf(strbuf, "\n"); - - /* Add any prot info */ - dhd_prot_dump(dhdp, strbuf); - bcm_bprintf(strbuf, "\n"); - - /* Add any bus info */ - dhd_bus_dump(dhdp, strbuf); - - return (!strbuf->size ? BCME_BUFTOOSHORT : 0); -} - -static int -dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const char *name, - void *params, int plen, void *arg, int len, int val_size) -{ - int bcmerror = 0; - int32 int_val = 0; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0) - goto exit; - - if (plen >= (int)sizeof(int_val)) - bcopy(params, &int_val, sizeof(int_val)); - - switch (actionid) { - case IOV_GVAL(IOV_VERSION): - /* Need to have checked buffer length */ - strncpy((char*)arg, dhd_version, len); - break; - - case IOV_GVAL(IOV_MSGLEVEL): - int_val = (int32)dhd_msg_level; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_MSGLEVEL): - dhd_msg_level = int_val; - break; - - - case IOV_GVAL(IOV_BCMERRORSTR): - strncpy((char *)arg, bcmerrorstr(dhd_pub->bcmerror), BCME_STRLEN); - ((char *)arg)[BCME_STRLEN - 1] = 0x00; - break; - - case IOV_GVAL(IOV_BCMERROR): - int_val = (int32)dhd_pub->bcmerror; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_WDTICK): - int_val = (int32)dhd_watchdog_ms; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_WDTICK): - if (!dhd_pub->up) { - bcmerror = BCME_NOTUP; - break; - } - dhd_os_wd_timer(dhd_pub, (uint)int_val); - break; - - case IOV_GVAL(IOV_DUMP): - bcmerror = dhd_dump(dhd_pub, arg, len); - break; - -#ifdef DHD_DEBUG - case IOV_GVAL(IOV_DCONSOLE_POLL): - int_val = (int32)dhd_console_ms; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_DCONSOLE_POLL): - dhd_console_ms = (uint)int_val; - break; - - case IOV_SVAL(IOV_CONS): - if (len > 0) - bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1); - break; -#endif - - case IOV_SVAL(IOV_CLEARCOUNTS): - dhd_pub->tx_packets = dhd_pub->rx_packets = 0; - dhd_pub->tx_errors = dhd_pub->rx_errors = 0; - dhd_pub->tx_ctlpkts = dhd_pub->rx_ctlpkts = 0; - dhd_pub->tx_ctlerrs = dhd_pub->rx_ctlerrs = 0; - dhd_pub->rx_dropped = 0; - dhd_pub->rx_readahead_cnt = 0; - dhd_pub->tx_realloc = 0; - dhd_pub->wd_dpc_sched = 0; - memset(&dhd_pub->dstats, 0, sizeof(dhd_pub->dstats)); - dhd_bus_clearcounts(dhd_pub); - break; - - - case IOV_GVAL(IOV_IOCTLTIMEOUT): { - int_val = (int32)dhd_os_get_ioctl_resp_timeout(); - bcopy(&int_val, arg, sizeof(int_val)); - break; - } - - case IOV_SVAL(IOV_IOCTLTIMEOUT): { - if (int_val <= 0) - bcmerror = BCME_BADARG; - else - dhd_os_set_ioctl_resp_timeout((unsigned int)int_val); - break; - } - - - default: - bcmerror = BCME_UNSUPPORTED; - break; - } - -exit: - return bcmerror; -} - -/* Store the status of a connection attempt for later retrieval by an iovar */ -void -dhd_store_conn_status(uint32 event, uint32 status, uint32 reason) -{ - /* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID - * because an encryption/rsn mismatch results in both events, and - * the important information is in the WLC_E_PRUNE. - */ - if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL && - dhd_conn_event == WLC_E_PRUNE)) { - dhd_conn_event = event; - dhd_conn_status = status; - dhd_conn_reason = reason; - } -} - -bool -dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) -{ - void *p; - int eprec = -1; /* precedence to evict from */ - bool discard_oldest; - - /* Fast case, precedence queue is not full and we are also not - * exceeding total queue length - */ - if (!pktq_pfull(q, prec) && !pktq_full(q)) { - pktq_penq(q, prec, pkt); - return TRUE; - } - - /* Determine precedence from which to evict packet, if any */ - if (pktq_pfull(q, prec)) - eprec = prec; - else if (pktq_full(q)) { - p = pktq_peek_tail(q, &eprec); - ASSERT(p); - if (eprec > prec) - return FALSE; - } - - /* Evict if needed */ - if (eprec >= 0) { - /* Detect queueing to unconfigured precedence */ - ASSERT(!pktq_pempty(q, eprec)); - discard_oldest = AC_BITMAP_TST(dhdp->wme_dp, eprec); - if (eprec == prec && !discard_oldest) - return FALSE; /* refuse newer (incoming) packet */ - /* Evict packet according to discard policy */ - p = discard_oldest ? pktq_pdeq(q, eprec) : pktq_pdeq_tail(q, eprec); - if (p == NULL) { - DHD_ERROR(("%s: pktq_penq() failed, oldest %d.", - __FUNCTION__, discard_oldest)); - ASSERT(p); - } - - PKTFREE(dhdp->osh, p, TRUE); - } - - /* Enqueue */ - p = pktq_penq(q, prec, pkt); - if (p == NULL) { - DHD_ERROR(("%s: pktq_penq() failed.", __FUNCTION__)); - ASSERT(p); - } - - return TRUE; -} - -static int -dhd_iovar_op(dhd_pub_t *dhd_pub, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - int bcmerror = 0; - int val_size; - const bcm_iovar_t *vi = NULL; - uint32 actionid; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - ASSERT(name); - ASSERT(len >= 0); - - /* Get MUST have return space */ - ASSERT(set || (arg && len)); - - /* Set does NOT take qualifiers */ - ASSERT(!set || (!params && !plen)); - - if ((vi = bcm_iovar_lookup(dhd_iovars, name)) == NULL) { - bcmerror = BCME_UNSUPPORTED; - goto exit; - } - - DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__, - name, (set ? "set" : "get"), len, plen)); - - /* set up 'params' pointer in case this is a set command so that - * the convenience int and bool code can be common to set and get - */ - if (params == NULL) { - params = arg; - plen = len; - } - - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - /* all other types are integer sized */ - val_size = sizeof(int); - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - bcmerror = dhd_doiovar(dhd_pub, vi, actionid, name, params, plen, arg, len, val_size); - -exit: - return bcmerror; -} - -int -dhd_ioctl(dhd_pub_t *dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen) -{ - int bcmerror = 0; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (!buf) return BCME_BADARG; - - switch (ioc->cmd) { - case DHD_GET_MAGIC: - if (buflen < sizeof(int)) - bcmerror = BCME_BUFTOOSHORT; - else - *(int*)buf = DHD_IOCTL_MAGIC; - break; - - case DHD_GET_VERSION: - if (buflen < sizeof(int)) - bcmerror = -BCME_BUFTOOSHORT; - else - *(int*)buf = DHD_IOCTL_VERSION; - break; - - case DHD_GET_VAR: - case DHD_SET_VAR: { - char *arg; - uint arglen; - - /* scan past the name to any arguments */ - for (arg = buf, arglen = buflen; *arg && arglen; arg++, arglen--); - - if (*arg) { - bcmerror = BCME_BUFTOOSHORT; - break; - } - - /* account for the NUL terminator */ - arg++, arglen--; - - /* call with the appropriate arguments */ - if (ioc->cmd == DHD_GET_VAR) - bcmerror = dhd_iovar_op(dhd_pub, buf, arg, arglen, - buf, buflen, IOV_GET); - else - bcmerror = dhd_iovar_op(dhd_pub, buf, NULL, 0, arg, arglen, IOV_SET); - if (bcmerror != BCME_UNSUPPORTED) - break; - - /* not in generic table, try protocol module */ - if (ioc->cmd == DHD_GET_VAR) - bcmerror = dhd_prot_iovar_op(dhd_pub, buf, arg, - arglen, buf, buflen, IOV_GET); - else - bcmerror = dhd_prot_iovar_op(dhd_pub, buf, - NULL, 0, arg, arglen, IOV_SET); - if (bcmerror != BCME_UNSUPPORTED) - break; - - /* if still not found, try bus module */ - if (ioc->cmd == DHD_GET_VAR) - bcmerror = dhd_bus_iovar_op(dhd_pub, buf, - arg, arglen, buf, buflen, IOV_GET); - else - bcmerror = dhd_bus_iovar_op(dhd_pub, buf, - NULL, 0, arg, arglen, IOV_SET); - - break; - } - - default: - bcmerror = BCME_UNSUPPORTED; - } - - return bcmerror; -} - -#ifdef APSTA_PINGTEST -struct ether_addr guest_eas[MAX_GUEST]; -#endif - -#ifdef SHOW_EVENTS -static void -wl_show_host_event(wl_event_msg_t *event, void *event_data) -{ - uint i, status, reason; - bool group = FALSE, flush_txq = FALSE, link = FALSE; - char *auth_str, *event_name; - uchar *buf; - char err_msg[256], eabuf[ETHER_ADDR_STR_LEN]; - static struct {uint event; char *event_name;} event_names[] = { - {WLC_E_SET_SSID, "SET_SSID"}, - {WLC_E_JOIN, "JOIN"}, - {WLC_E_START, "START"}, - {WLC_E_AUTH, "AUTH"}, - {WLC_E_AUTH_IND, "AUTH_IND"}, - {WLC_E_DEAUTH, "DEAUTH"}, - {WLC_E_DEAUTH_IND, "DEAUTH_IND"}, - {WLC_E_ASSOC, "ASSOC"}, - {WLC_E_ASSOC_IND, "ASSOC_IND"}, - {WLC_E_REASSOC, "REASSOC"}, - {WLC_E_REASSOC_IND, "REASSOC_IND"}, - {WLC_E_DISASSOC, "DISASSOC"}, - {WLC_E_DISASSOC_IND, "DISASSOC_IND"}, - {WLC_E_QUIET_START, "START_QUIET"}, - {WLC_E_QUIET_END, "END_QUIET"}, - {WLC_E_BEACON_RX, "BEACON_RX"}, - {WLC_E_LINK, "LINK"}, - {WLC_E_MIC_ERROR, "MIC_ERROR"}, - {WLC_E_NDIS_LINK, "NDIS_LINK"}, - {WLC_E_ROAM, "ROAM"}, - {WLC_E_TXFAIL, "TXFAIL"}, - {WLC_E_PMKID_CACHE, "PMKID_CACHE"}, - {WLC_E_RETROGRADE_TSF, "RETROGRADE_TSF"}, - {WLC_E_PRUNE, "PRUNE"}, - {WLC_E_AUTOAUTH, "AUTOAUTH"}, - {WLC_E_EAPOL_MSG, "EAPOL_MSG"}, - {WLC_E_SCAN_COMPLETE, "SCAN_COMPLETE"}, - {WLC_E_ADDTS_IND, "ADDTS_IND"}, - {WLC_E_DELTS_IND, "DELTS_IND"}, - {WLC_E_BCNSENT_IND, "BCNSENT_IND"}, - {WLC_E_BCNRX_MSG, "BCNRX_MSG"}, - {WLC_E_BCNLOST_MSG, "BCNLOST_MSG"}, - {WLC_E_ROAM_PREP, "ROAM_PREP"}, - {WLC_E_PFN_NET_FOUND, "PNO_NET_FOUND"}, - {WLC_E_PFN_NET_LOST, "PNO_NET_LOST"}, - {WLC_E_RESET_COMPLETE, "RESET_COMPLETE"}, - {WLC_E_JOIN_START, "JOIN_START"}, - {WLC_E_ROAM_START, "ROAM_START"}, - {WLC_E_ASSOC_START, "ASSOC_START"}, - {WLC_E_IBSS_ASSOC, "IBSS_ASSOC"}, - {WLC_E_RADIO, "RADIO"}, - {WLC_E_PSM_WATCHDOG, "PSM_WATCHDOG"}, - {WLC_E_PROBREQ_MSG, "PROBREQ_MSG"}, - {WLC_E_SCAN_CONFIRM_IND, "SCAN_CONFIRM_IND"}, - {WLC_E_PSK_SUP, "PSK_SUP"}, - {WLC_E_COUNTRY_CODE_CHANGED, "COUNTRY_CODE_CHANGED"}, - {WLC_E_EXCEEDED_MEDIUM_TIME, "EXCEEDED_MEDIUM_TIME"}, - {WLC_E_ICV_ERROR, "ICV_ERROR"}, - {WLC_E_UNICAST_DECODE_ERROR, "UNICAST_DECODE_ERROR"}, - {WLC_E_MULTICAST_DECODE_ERROR, "MULTICAST_DECODE_ERROR"}, - {WLC_E_TRACE, "TRACE"}, - {WLC_E_ACTION_FRAME, "ACTION FRAME"}, - {WLC_E_ACTION_FRAME_COMPLETE, "ACTION FRAME TX COMPLETE"}, - {WLC_E_IF, "IF"}, - {WLC_E_RSSI, "RSSI"}, - {WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"} - }; - uint event_type, flags, auth_type, datalen; - event_type = ntoh32(event->event_type); - flags = ntoh16(event->flags); - status = ntoh32(event->status); - reason = ntoh32(event->reason); - auth_type = ntoh32(event->auth_type); - datalen = ntoh32(event->datalen); - /* debug dump of event messages */ - sprintf(eabuf, "%02x:%02x:%02x:%02x:%02x:%02x", - (uchar)event->addr.octet[0]&0xff, - (uchar)event->addr.octet[1]&0xff, - (uchar)event->addr.octet[2]&0xff, - (uchar)event->addr.octet[3]&0xff, - (uchar)event->addr.octet[4]&0xff, - (uchar)event->addr.octet[5]&0xff); - - event_name = "UNKNOWN"; - for (i = 0; i < ARRAYSIZE(event_names); i++) { - if (event_names[i].event == event_type) - event_name = event_names[i].event_name; - } - - DHD_EVENT(("EVENT: %s, event ID = %d\n", event_name, event_type)); - - if (flags & WLC_EVENT_MSG_LINK) - link = TRUE; - if (flags & WLC_EVENT_MSG_GROUP) - group = TRUE; - if (flags & WLC_EVENT_MSG_FLUSHTXQ) - flush_txq = TRUE; - - switch (event_type) { - case WLC_E_START: - case WLC_E_DEAUTH: - case WLC_E_DISASSOC: - DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); - break; - - case WLC_E_ASSOC_IND: - case WLC_E_REASSOC_IND: -#ifdef APSTA_PINGTEST - { - int i; - for (i = 0; i < MAX_GUEST; ++i) - if (ETHER_ISNULLADDR(&guest_eas[i])) - break; - if (i < MAX_GUEST) - bcopy(event->addr.octet, guest_eas[i].octet, ETHER_ADDR_LEN); - } -#endif /* APSTA_PINGTEST */ - DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); - break; - - case WLC_E_ASSOC: - case WLC_E_REASSOC: - if (status == WLC_E_STATUS_SUCCESS) { - DHD_EVENT(("MACEVENT: %s, MAC %s, SUCCESS\n", event_name, eabuf)); - } else if (status == WLC_E_STATUS_TIMEOUT) { - DHD_EVENT(("MACEVENT: %s, MAC %s, TIMEOUT\n", event_name, eabuf)); - } else if (status == WLC_E_STATUS_FAIL) { - DHD_EVENT(("MACEVENT: %s, MAC %s, FAILURE, reason %d\n", - event_name, eabuf, (int)reason)); - } else { - DHD_EVENT(("MACEVENT: %s, MAC %s, unexpected status %d\n", - event_name, eabuf, (int)status)); - } - break; - - case WLC_E_DEAUTH_IND: - case WLC_E_DISASSOC_IND: -#ifdef APSTA_PINGTEST - { - int i; - for (i = 0; i < MAX_GUEST; ++i) { - if (bcmp(guest_eas[i].octet, event->addr.octet, - ETHER_ADDR_LEN) == 0) { - bzero(guest_eas[i].octet, ETHER_ADDR_LEN); - break; - } - } - } -#endif /* APSTA_PINGTEST */ - DHD_EVENT(("MACEVENT: %s, MAC %s, reason %d\n", event_name, eabuf, (int)reason)); - break; - - case WLC_E_AUTH: - case WLC_E_AUTH_IND: - if (auth_type == DOT11_OPEN_SYSTEM) - auth_str = "Open System"; - else if (auth_type == DOT11_SHARED_KEY) - auth_str = "Shared Key"; - else { - sprintf(err_msg, "AUTH unknown: %d", (int)auth_type); - auth_str = err_msg; - } - if (event_type == WLC_E_AUTH_IND) { - DHD_EVENT(("MACEVENT: %s, MAC %s, %s\n", event_name, eabuf, auth_str)); - } else if (status == WLC_E_STATUS_SUCCESS) { - DHD_EVENT(("MACEVENT: %s, MAC %s, %s, SUCCESS\n", - event_name, eabuf, auth_str)); - } else if (status == WLC_E_STATUS_TIMEOUT) { - DHD_EVENT(("MACEVENT: %s, MAC %s, %s, TIMEOUT\n", - event_name, eabuf, auth_str)); - } else if (status == WLC_E_STATUS_FAIL) { - DHD_EVENT(("MACEVENT: %s, MAC %s, %s, FAILURE, reason %d\n", - event_name, eabuf, auth_str, (int)reason)); - } - - break; - - case WLC_E_JOIN: - case WLC_E_ROAM: - case WLC_E_SET_SSID: - if (status == WLC_E_STATUS_SUCCESS) { - DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); - } else if (status == WLC_E_STATUS_FAIL) { - DHD_EVENT(("MACEVENT: %s, failed\n", event_name)); - } else if (status == WLC_E_STATUS_NO_NETWORKS) { - DHD_EVENT(("MACEVENT: %s, no networks found\n", event_name)); - } else { - DHD_EVENT(("MACEVENT: %s, unexpected status %d\n", - event_name, (int)status)); - } - break; - - case WLC_E_BEACON_RX: - if (status == WLC_E_STATUS_SUCCESS) { - DHD_EVENT(("MACEVENT: %s, SUCCESS\n", event_name)); - } else if (status == WLC_E_STATUS_FAIL) { - DHD_EVENT(("MACEVENT: %s, FAIL\n", event_name)); - } else { - DHD_EVENT(("MACEVENT: %s, status %d\n", event_name, status)); - } - break; - - case WLC_E_LINK: - DHD_EVENT(("MACEVENT: %s %s\n", event_name, link?"UP":"DOWN")); - break; - - case WLC_E_MIC_ERROR: - DHD_EVENT(("MACEVENT: %s, MAC %s, Group %d, Flush %d\n", - event_name, eabuf, group, flush_txq)); - break; - - case WLC_E_ICV_ERROR: - case WLC_E_UNICAST_DECODE_ERROR: - case WLC_E_MULTICAST_DECODE_ERROR: - DHD_EVENT(("MACEVENT: %s, MAC %s\n", - event_name, eabuf)); - break; - - case WLC_E_TXFAIL: - DHD_EVENT(("MACEVENT: %s, RA %s\n", event_name, eabuf)); - break; - - case WLC_E_SCAN_COMPLETE: - case WLC_E_PMKID_CACHE: - DHD_EVENT(("MACEVENT: %s\n", event_name)); - break; - - case WLC_E_PFN_NET_FOUND: - case WLC_E_PFN_NET_LOST: - case WLC_E_PFN_SCAN_COMPLETE: - DHD_EVENT(("PNOEVENT: %s\n", event_name)); - break; - - case WLC_E_PSK_SUP: - case WLC_E_PRUNE: - DHD_EVENT(("MACEVENT: %s, status %d, reason %d\n", - event_name, (int)status, (int)reason)); - break; - - case WLC_E_TRACE: - { - static uint32 seqnum_prev = 0; - msgtrace_hdr_t hdr; - uint32 nblost; - char *s, *p; - - buf = (uchar *) event_data; - memcpy(&hdr, buf, MSGTRACE_HDRLEN); - - if (hdr.version != MSGTRACE_VERSION) { - printf("\nMACEVENT: %s [unsupported version --> " - "dhd version:%d dongle version:%d]\n", - event_name, MSGTRACE_VERSION, hdr.version); - /* Reset datalen to avoid display below */ - datalen = 0; - break; - } - - /* There are 2 bytes available at the end of data */ - buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0'; - - if (ntoh32(hdr.discarded_bytes) || ntoh32(hdr.discarded_printf)) { - printf("\nWLC_E_TRACE: [Discarded traces in dongle -->" - "discarded_bytes %d discarded_printf %d]\n", - ntoh32(hdr.discarded_bytes), ntoh32(hdr.discarded_printf)); - } - - nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1; - if (nblost > 0) { - printf("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n", - ntoh32(hdr.seqnum), nblost); - } - seqnum_prev = ntoh32(hdr.seqnum); - - /* Display the trace buffer. Advance from \n to \n to avoid display big - * printf (issue with Linux printk ) - */ - p = (char *)&buf[MSGTRACE_HDRLEN]; - while ((s = strstr(p, "\n")) != NULL) { - *s = '\0'; - printf("%s\n", p); - p = s + 1; - } - printf("%s\n", p); - - /* Reset datalen to avoid display below */ - datalen = 0; - } - break; - - - case WLC_E_RSSI: - DHD_EVENT(("MACEVENT: %s %d\n", event_name, ntoh32(*((int *)event_data)))); - break; - - default: - DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", - event_name, event_type, eabuf, (int)status, (int)reason, - (int)auth_type)); - break; - } - - /* show any appended data */ - if (datalen) { - buf = (uchar *) event_data; - DHD_EVENT((" data (%d) : ", datalen)); - for (i = 0; i < datalen; i++) - DHD_EVENT((" 0x%02x ", *buf++)); - DHD_EVENT(("\n")); - } -} -#endif /* SHOW_EVENTS */ - -int -wl_host_event(struct dhd_info *dhd, int *ifidx, void *pktdata, - wl_event_msg_t *event, void **data_ptr) -{ - /* check whether packet is a BRCM event pkt */ - bcm_event_t *pvt_data = (bcm_event_t *)pktdata; - char *event_data; - uint32 type, status; - uint16 flags; - int evlen; - - if (bcmp(BRCM_OUI, &pvt_data->bcm_hdr.oui[0], DOT11_OUI_LEN)) { - DHD_ERROR(("%s: mismatched OUI, bailing\n", __FUNCTION__)); - return (BCME_ERROR); - } - - /* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */ - if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) != BCMILCP_BCM_SUBTYPE_EVENT) { - DHD_ERROR(("%s: mismatched subtype, bailing\n", __FUNCTION__)); - return (BCME_ERROR); - } - - *data_ptr = &pvt_data[1]; - event_data = *data_ptr; - - /* memcpy since BRCM event pkt may be unaligned. */ - memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t)); - - type = ntoh32_ua((void *)&event->event_type); - flags = ntoh16_ua((void *)&event->flags); - status = ntoh32_ua((void *)&event->status); - evlen = ntoh32_ua((void *)&event->datalen) + sizeof(bcm_event_t); - - switch (type) { - case WLC_E_IF: - { - dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; - DHD_TRACE(("%s: if event\n", __FUNCTION__)); - - if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) - { - if (ifevent->action == WLC_E_IF_ADD) - dhd_add_if(dhd, ifevent->ifidx, - NULL, event->ifname, - pvt_data->eth.ether_dhost, - ifevent->flags, ifevent->bssidx); - else - dhd_del_if(dhd, ifevent->ifidx); - } else { - DHD_ERROR(("%s: Invalid ifidx %d for %s\n", - __FUNCTION__, ifevent->ifidx, event->ifname)); - } - } - /* send up the if event: btamp user needs it */ - *ifidx = dhd_ifname2idx(dhd, event->ifname); - /* push up to external supp/auth */ - dhd_event(dhd, (char *)pvt_data, evlen, *ifidx); - break; - - -#ifdef P2P - case WLC_E_NDIS_LINK: - break; -#endif - /* fall through */ - /* These are what external supplicant/authenticator wants */ - case WLC_E_LINK: - case WLC_E_ASSOC_IND: - case WLC_E_REASSOC_IND: - case WLC_E_DISASSOC_IND: - case WLC_E_MIC_ERROR: - default: - /* Fall through: this should get _everything_ */ - - *ifidx = dhd_ifname2idx(dhd, event->ifname); - /* push up to external supp/auth */ - dhd_event(dhd, (char *)pvt_data, evlen, *ifidx); - DHD_TRACE(("%s: MAC event %d, flags %x, status %x\n", - __FUNCTION__, type, flags, status)); - - /* put it back to WLC_E_NDIS_LINK */ - if (type == WLC_E_NDIS_LINK) { - uint32 temp; - - temp = ntoh32_ua((void *)&event->event_type); - DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp)); - - temp = ntoh32(WLC_E_NDIS_LINK); - memcpy((void *)(&pvt_data->event.event_type), &temp, - sizeof(pvt_data->event.event_type)); - } - break; - } - -#ifdef SHOW_EVENTS - wl_show_host_event(event, event_data); -#endif /* SHOW_EVENTS */ - - return (BCME_OK); -} - - -void -wl_event_to_host_order(wl_event_msg_t *evt) -{ - /* Event struct members passed from dongle to host are stored in network - * byte order. Convert all members to host-order. - */ - evt->event_type = ntoh32(evt->event_type); - evt->flags = ntoh16(evt->flags); - evt->status = ntoh32(evt->status); - evt->reason = ntoh32(evt->reason); - evt->auth_type = ntoh32(evt->auth_type); - evt->datalen = ntoh32(evt->datalen); - evt->version = ntoh16(evt->version); -} - -void print_buf(void *pbuf, int len, int bytes_per_line) -{ - int i, j = 0; - unsigned char *buf = pbuf; - - if (bytes_per_line == 0) { - bytes_per_line = len; - } - - for (i = 0; i < len; i++) { - printf("%2.2x", *buf++); - j++; - if (j == bytes_per_line) { - printf("\n"); - j = 0; - } else { - printf(":"); - } - } - printf("\n"); -} - -#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) - -/* Convert user's input in hex pattern to byte-size mask */ -static int -wl_pattern_atoh(char *src, char *dst) -{ - int i; - if (strncmp(src, "0x", 2) != 0 && - strncmp(src, "0X", 2) != 0) { - DHD_ERROR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - DHD_ERROR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - strncpy(num, src, 2); - num[2] = '\0'; - dst[i] = (uint8)strtoul(num, NULL, 16); - src += 2; - } - return i; -} - -void -dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode) -{ - char *argv[8]; - int i = 0; - const char *str; - int buf_len; - int str_len; - char *arg_save = 0, *arg_org = 0; - int rc; - char buf[128]; - wl_pkt_filter_enable_t enable_parm; - wl_pkt_filter_enable_t * pkt_filterp; - - if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { - DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); - goto fail; - } - arg_org = arg_save; - memcpy(arg_save, arg, strlen(arg) + 1); - - argv[i] = bcmstrtok(&arg_save, " ", 0); - - i = 0; - if (NULL == argv[i]) { - DHD_ERROR(("No args provided\n")); - goto fail; - } - - str = "pkt_filter_enable"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[str_len] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (wl_pkt_filter_enable_t *)(buf + str_len + 1); - - /* Parse packet filter id. */ - enable_parm.id = htod32(strtoul(argv[i], NULL, 0)); - - /* Parse enable/disable value. */ - enable_parm.enable = htod32(enable); - - buf_len += sizeof(enable_parm); - memcpy((char *)pkt_filterp, - &enable_parm, - sizeof(enable_parm)); - - /* Enable/disable the specified filter. */ - rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len); - rc = rc >= 0 ? 0 : rc; - if (rc) - DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", - __FUNCTION__, arg, rc)); - else - DHD_TRACE(("%s: successfully added pktfilter %s\n", - __FUNCTION__, arg)); - - /* Contorl the master mode */ - bcm_mkiovar("pkt_filter_mode", (char *)&master_mode, 4, buf, sizeof(buf)); - rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf)); - rc = rc >= 0 ? 0 : rc; - if (rc) - DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", - __FUNCTION__, arg, rc)); - -fail: - if (arg_org) - MFREE(dhd->osh, arg_org, strlen(arg) + 1); -} - -void -dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg) -{ - const char *str; - wl_pkt_filter_t pkt_filter; - wl_pkt_filter_t *pkt_filterp; - int buf_len; - int str_len; - int rc; - uint32 mask_size; - uint32 pattern_size; - char *argv[8], * buf = 0; - int i = 0; - char *arg_save = 0, *arg_org = 0; -#define BUF_SIZE 2048 - - if (!(arg_save = MALLOC(dhd->osh, strlen(arg) + 1))) { - DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); - goto fail; - } - - arg_org = arg_save; - - if (!(buf = MALLOC(dhd->osh, BUF_SIZE))) { - DHD_ERROR(("%s: kmalloc failed\n", __FUNCTION__)); - goto fail; - } - - memcpy(arg_save, arg, strlen(arg) + 1); - - if (strlen(arg) > BUF_SIZE) { - DHD_ERROR(("Not enough buffer %d < %d\n", (int)strlen(arg), (int)sizeof(buf))); - goto fail; - } - - argv[i] = bcmstrtok(&arg_save, " ", 0); - while (argv[i++]) - argv[i] = bcmstrtok(&arg_save, " ", 0); - - i = 0; - if (NULL == argv[i]) { - DHD_ERROR(("No args provided\n")); - goto fail; - } - - str = "pkt_filter_add"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[ str_len ] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1); - - /* Parse packet filter id. */ - pkt_filter.id = htod32(strtoul(argv[i], NULL, 0)); - - if (NULL == argv[++i]) { - DHD_ERROR(("Polarity not provided\n")); - goto fail; - } - - /* Parse filter polarity. */ - pkt_filter.negate_match = htod32(strtoul(argv[i], NULL, 0)); - - if (NULL == argv[++i]) { - DHD_ERROR(("Filter type not provided\n")); - goto fail; - } - - /* Parse filter type. */ - pkt_filter.type = htod32(strtoul(argv[i], NULL, 0)); - - if (NULL == argv[++i]) { - DHD_ERROR(("Offset not provided\n")); - goto fail; - } - - /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = htod32(strtoul(argv[i], NULL, 0)); - - if (NULL == argv[++i]) { - DHD_ERROR(("Bitmask not provided\n")); - goto fail; - } - - /* Parse pattern filter mask. */ - mask_size = - htod32(wl_pattern_atoh(argv[i], (char *) pkt_filterp->u.pattern.mask_and_pattern)); - - if (NULL == argv[++i]) { - DHD_ERROR(("Pattern not provided\n")); - goto fail; - } - - /* Parse pattern filter pattern. */ - pattern_size = - htod32(wl_pattern_atoh(argv[i], - (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size])); - - if (mask_size != pattern_size) { - DHD_ERROR(("Mask and pattern not the same size\n")); - goto fail; - } - - pkt_filter.u.pattern.size_bytes = mask_size; - buf_len += WL_PKT_FILTER_FIXED_LEN; - buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); - - /* Keep-alive attributes are set in local variable (keep_alive_pkt), and - ** then memcpy'ed into buffer (keep_alive_pktp) since there is no - ** guarantee that the buffer is properly aligned. - */ - memcpy((char *)pkt_filterp, - &pkt_filter, - WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - - rc = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, buf_len); - rc = rc >= 0 ? 0 : rc; - - if (rc) - DHD_TRACE(("%s: failed to add pktfilter %s, retcode = %d\n", - __FUNCTION__, arg, rc)); - else - DHD_TRACE(("%s: successfully added pktfilter %s\n", - __FUNCTION__, arg)); - -fail: - if (arg_org) - MFREE(dhd->osh, arg_org, strlen(arg) + 1); - - if (buf) - MFREE(dhd->osh, buf, BUF_SIZE); -} - -void -dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode) -{ - char iovbuf[32]; - int retcode; - - bcm_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf)); - retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - retcode = retcode >= 0 ? 0 : retcode; - if (retcode) - DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n", - __FUNCTION__, arp_mode, retcode)); - else - DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n", - __FUNCTION__, arp_mode)); -} - -void -dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable) -{ - char iovbuf[32]; - int retcode; - - bcm_mkiovar("arpoe", (char *)&arp_enable, 4, iovbuf, sizeof(iovbuf)); - retcode = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - retcode = retcode >= 0 ? 0 : retcode; - if (retcode) - DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n", - __FUNCTION__, arp_enable, retcode)); - else - DHD_TRACE(("%s: successfully enabed ARP offload to %d\n", - __FUNCTION__, arp_enable)); -} - -int -dhd_preinit_ioctls(dhd_pub_t *dhd) -{ - char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - uint up = 0; - char buf[128], *ptr; - uint power_mode = PM_FAST; - uint32 dongle_align = DHD_SDALIGN; - uint32 glom = 0; - uint bcn_timeout = 3; - int scan_assoc_time = 40; - int scan_unassoc_time = 80; -#ifdef GET_CUSTOM_MAC_ENABLE - int ret = 0; - struct ether_addr ea_addr; -#endif /* GET_CUSTOM_MAC_ENABLE */ - - dhd_os_proto_block(dhd); - -#ifdef GET_CUSTOM_MAC_ENABLE - /* Read MAC address from external customer place - ** NOTE that default mac address has to be present in otp or nvram file to bring up - ** firmware but unique per board mac address maybe provided by customer code - */ - ret = dhd_custom_get_mac_address(ea_addr.octet); - if (!ret) { - bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf)); - ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf)); - if (ret < 0) { - DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret)); - } - else - memcpy(dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN); - } -#endif /* GET_CUSTOM_MAC_ENABLE */ - - memset(dhd->country_code, 0, sizeof(dhd->country_code)); - strncpy(dhd->country_code,"JP", 2); //set max numbers of radio channels - - /* Set Country code */ - if (dhd->country_code[0] != 0) { - if (dhdcdc_set_ioctl(dhd, 0, WLC_SET_COUNTRY, - dhd->country_code, sizeof(dhd->country_code)) < 0) { - DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__)); - } - } - - /* query for 'ver' to get version info from firmware */ - memset(buf, 0, sizeof(buf)); - ptr = buf; - bcm_mkiovar("ver", 0, 0, buf, sizeof(buf)); - dhdcdc_query_ioctl(dhd, 0, WLC_GET_VAR, buf, sizeof(buf)); - bcmstrtok(&ptr, "\n", 0); - /* Print fw version info */ - DHD_ERROR(("Firmware version = %s\n", buf)); - - /* Set PowerSave mode */ - dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode)); - - /* Match Host and Dongle rx alignment */ - bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - - /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - - /* Setup timeout if Beacons are lost and roam is off to report link down */ - bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - - /* Enable/Disable build-in roaming to allowed ext supplicant to take of romaing */ - bcm_mkiovar("roam_off", (char *)&dhd_roam, 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - - /* Force STA UP */ - if (dhd_radio_up) - dhdcdc_set_ioctl(dhd, 0, WLC_UP, (char *)&up, sizeof(up)); - - /* Setup event_msgs */ - bcm_mkiovar("event_msgs", dhd->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); - - dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time, - sizeof(scan_assoc_time)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time, - sizeof(scan_unassoc_time)); - -#ifdef ARP_OFFLOAD_SUPPORT - /* Set and enable ARP offload feature */ - if (dhd_arp_enable) - dhd_arp_offload_set(dhd, dhd_arp_mode); - dhd_arp_offload_enable(dhd, dhd_arp_enable); -#endif /* ARP_OFFLOAD_SUPPORT */ - -#ifdef PKT_FILTER_SUPPORT - { - int i; - /* Set up pkt filter */ - if (dhd_pkt_filter_enable) { - for (i = 0; i < dhd->pktfilter_count; i++) { - dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); - dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], - dhd_pkt_filter_init, dhd_master_mode); - } - } - } -#endif /* PKT_FILTER_SUPPORT */ - - dhd_os_proto_unblock(dhd); - - return 0; -} - -#ifdef SIMPLE_ISCAN - -uint iscan_thread_id; -iscan_buf_t * iscan_chain = 0; - -iscan_buf_t * -dhd_iscan_allocate_buf(dhd_pub_t *dhd, iscan_buf_t **iscanbuf) -{ - iscan_buf_t *iscanbuf_alloc = 0; - iscan_buf_t *iscanbuf_head; - - dhd_iscan_lock(); - - iscanbuf_alloc = (iscan_buf_t*)MALLOC(dhd->osh, sizeof(iscan_buf_t)); - if (iscanbuf_alloc == NULL) - goto fail; - - iscanbuf_alloc->next = NULL; - iscanbuf_head = *iscanbuf; - - DHD_ISCAN(("%s: addr of allocated node = 0x%X, addr of iscanbuf_head \ - = 0x%X dhd = 0x%X\n", __FUNCTION__, iscanbuf_alloc, - iscanbuf_head, dhd)); - - if (iscanbuf_head == NULL) { - *iscanbuf = iscanbuf_alloc; - DHD_ISCAN(("%s: Head is allocated\n", __FUNCTION__)); - goto fail; - } - - while (iscanbuf_head->next) - iscanbuf_head = iscanbuf_head->next; - - iscanbuf_head->next = iscanbuf_alloc; - -fail: - dhd_iscan_unlock(); - return iscanbuf_alloc; -} - -void -dhd_iscan_free_buf(void *dhdp, iscan_buf_t *iscan_delete) -{ - iscan_buf_t *iscanbuf_free = 0; - iscan_buf_t *iscanbuf_prv = 0; - iscan_buf_t *iscanbuf_cur = iscan_chain; - dhd_pub_t *dhd = dhd_bus_pub(dhdp); - - dhd_iscan_lock(); - /* If iscan_delete is null then delete the entire - * chain or else delete specific one provided - */ - if (!iscan_delete) { - while (iscanbuf_cur) { - iscanbuf_free = iscanbuf_cur; - iscanbuf_cur = iscanbuf_cur->next; - iscanbuf_free->next = 0; - MFREE(dhd->osh, iscanbuf_free, sizeof(iscan_buf_t)); - } - iscan_chain = 0; - } else { - while (iscanbuf_cur) { - if (iscanbuf_cur == iscan_delete) - break; - iscanbuf_prv = iscanbuf_cur; - iscanbuf_cur = iscanbuf_cur->next; - } - if (iscanbuf_prv) - iscanbuf_prv->next = iscan_delete->next; - - iscan_delete->next = 0; - MFREE(dhd->osh, iscan_delete, sizeof(iscan_buf_t)); - - if (!iscanbuf_prv) - iscan_chain = 0; - } - dhd_iscan_unlock(); -} - -iscan_buf_t * -dhd_iscan_result_buf(void) -{ - return iscan_chain; -} - - - -/* -* print scan cache -* print partial iscan_skip list differently -*/ -int -dhd_iscan_print_cache(iscan_buf_t *iscan_skip) -{ - int i = 0, l = 0; - iscan_buf_t *iscan_cur; - wl_iscan_results_t *list; - wl_scan_results_t *results; - wl_bss_info_t UNALIGNED *bi; - - dhd_iscan_lock(); - - iscan_cur = dhd_iscan_result_buf(); - - while (iscan_cur) { - list = (wl_iscan_results_t *)iscan_cur->iscan_buf; - if (!list) - break; - - results = (wl_scan_results_t *)&list->results; - if (!results) - break; - - if (results->version != WL_BSS_INFO_VERSION) { - DHD_ISCAN(("%s: results->version %d != WL_BSS_INFO_VERSION\n", - __FUNCTION__, results->version)); - goto done; - } - - bi = results->bss_info; - for (i = 0; i < results->count; i++) { - if (!bi) - break; - - DHD_ISCAN(("%s[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", - iscan_cur != iscan_skip?"BSS":"bss", l, i, - bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], - bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); - - bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); - } - iscan_cur = iscan_cur->next; - l++; - } - -done: - dhd_iscan_unlock(); - return 0; -} - -/* -* delete disappeared AP from specific scan cache but skip partial list in iscan_skip -*/ -int -dhd_iscan_delete_bss(void *dhdp, void *addr, iscan_buf_t *iscan_skip) -{ - int i = 0, j = 0, l = 0; - iscan_buf_t *iscan_cur; - wl_iscan_results_t *list; - wl_scan_results_t *results; - wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next; - - uchar *s_addr = addr; - - dhd_iscan_lock(); - DHD_ISCAN(("%s: BSS to remove %X:%X:%X:%X:%X:%X\n", - __FUNCTION__, s_addr[0], s_addr[1], s_addr[2], - s_addr[3], s_addr[4], s_addr[5])); - - iscan_cur = dhd_iscan_result_buf(); - - while (iscan_cur) { - if (iscan_cur != iscan_skip) { - list = (wl_iscan_results_t *)iscan_cur->iscan_buf; - if (!list) - break; - - results = (wl_scan_results_t *)&list->results; - if (!results) - break; - - if (results->version != WL_BSS_INFO_VERSION) { - DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n", - __FUNCTION__, results->version)); - goto done; - } - - bi = results->bss_info; - for (i = 0; i < results->count; i++) { - if (!bi) - break; - - if (!memcmp(bi->BSSID.octet, addr, ETHER_ADDR_LEN)) { - DHD_ISCAN(("%s: Del BSS[%2.2d:%2.2d] %X:%X:%X:%X:%X:%X\n", \ - __FUNCTION__, l, i, bi->BSSID.octet[0], \ - bi->BSSID.octet[1], bi->BSSID.octet[2], \ - bi->BSSID.octet[3], bi->BSSID.octet[4], \ - bi->BSSID.octet[5])); - - bi_new = bi; - bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); -/* - if(bi && bi_new) { - bcopy(bi, bi_new, results->buflen - - dtoh32(bi_new->length)); - results->buflen -= dtoh32(bi_new->length); - } -*/ - results->buflen -= dtoh32(bi_new->length); - results->count--; - - for (j = i; j < results->count; j++) { - if (bi && bi_new) { - DHD_ISCAN(("%s: Moved up BSS[%2.2d:%2.2d] \ - %X:%X:%X:%X:%X:%X\n", - __FUNCTION__, l, j, bi->BSSID.octet[0], - bi->BSSID.octet[1], bi->BSSID.octet[2], - bi->BSSID.octet[3], bi->BSSID.octet[4], - bi->BSSID.octet[5])); - - bi_next = (wl_bss_info_t *)((uintptr)bi + - dtoh32(bi->length)); - bcopy(bi, bi_new, dtoh32(bi->length)); - bi_new = (wl_bss_info_t *)((uintptr)bi_new + - dtoh32(bi_new->length)); - bi = bi_next; - } - } - - if (results->count == 0) { - /* Prune now empty partial scan list */ - dhd_iscan_free_buf(dhdp, iscan_cur); - goto done; - } - break; - } - bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); - } - } - iscan_cur = iscan_cur->next; - l++; - } - -done: - dhd_iscan_unlock(); - return 0; -} - -int -dhd_iscan_remove_duplicates(void * dhdp, iscan_buf_t *iscan_cur) -{ - int i = 0; - wl_iscan_results_t *list; - wl_scan_results_t *results; - wl_bss_info_t UNALIGNED *bi, *bi_new, *bi_next; - - dhd_iscan_lock(); - - DHD_ISCAN(("%s: Scan cache before delete\n", - __FUNCTION__)); - dhd_iscan_print_cache(iscan_cur); - - if (!iscan_cur) - goto done; - - list = (wl_iscan_results_t *)iscan_cur->iscan_buf; - if (!list) - goto done; - - results = (wl_scan_results_t *)&list->results; - if (!results) - goto done; - - if (results->version != WL_BSS_INFO_VERSION) { - DHD_ERROR(("%s: results->version %d != WL_BSS_INFO_VERSION\n", - __FUNCTION__, results->version)); - goto done; - } - - bi = results->bss_info; - for (i = 0; i < results->count; i++) { - if (!bi) - break; - - DHD_ISCAN(("%s: Find dups for BSS[%2.2d] %X:%X:%X:%X:%X:%X\n", - __FUNCTION__, i, bi->BSSID.octet[0], bi->BSSID.octet[1], bi->BSSID.octet[2], - bi->BSSID.octet[3], bi->BSSID.octet[4], bi->BSSID.octet[5])); - - dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur); - - bi = (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)); - } - -done: - DHD_ISCAN(("%s: Scan cache after delete\n", __FUNCTION__)); - dhd_iscan_print_cache(iscan_cur); - dhd_iscan_unlock(); - return 0; -} - -void -dhd_iscan_ind_scan_confirm(void *dhdp, bool status) -{ - - dhd_ind_scan_confirm(dhdp, status); -} - -int -dhd_iscan_request(void * dhdp, uint16 action) -{ - int rc; - wl_iscan_params_t params; - dhd_pub_t *dhd = dhd_bus_pub(dhdp); - char buf[WLC_IOCTL_SMLEN]; - - - memset(¶ms, 0, sizeof(wl_iscan_params_t)); - memcpy(¶ms.params.bssid, ðer_bcast, ETHER_ADDR_LEN); - - params.params.bss_type = DOT11_BSSTYPE_ANY; - params.params.scan_type = DOT11_SCANTYPE_ACTIVE; - - params.params.nprobes = htod32(-1); - params.params.active_time = htod32(-1); - params.params.passive_time = htod32(-1); - params.params.home_time = htod32(-1); - params.params.channel_num = htod32(0); - - params.version = htod32(ISCAN_REQ_VERSION); - params.action = htod16(action); - params.scan_duration = htod16(0); - - bcm_mkiovar("iscan", (char *)¶ms, sizeof(wl_iscan_params_t), buf, WLC_IOCTL_SMLEN); - rc = dhd_wl_ioctl(dhdp, WLC_SET_VAR, buf, WLC_IOCTL_SMLEN); - - return rc; -} - -static int -dhd_iscan_get_partial_result(void *dhdp, uint *scan_count) -{ - wl_iscan_results_t *list_buf; - wl_iscan_results_t list; - wl_scan_results_t *results; - iscan_buf_t *iscan_cur; - int status = -1; - dhd_pub_t *dhd = dhd_bus_pub(dhdp); - int rc; - - - iscan_cur = dhd_iscan_allocate_buf(dhd, &iscan_chain); - if (!iscan_cur) { - DHD_ERROR(("%s: Failed to allocate node\n", __FUNCTION__)); - dhd_iscan_free_buf(dhdp, 0); - dhd_iscan_request(dhdp, WL_SCAN_ACTION_ABORT); - goto fail; - } - - dhd_iscan_lock(); - - memset(iscan_cur->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); - list_buf = (wl_iscan_results_t*)iscan_cur->iscan_buf; - results = &list_buf->results; - results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; - results->version = 0; - results->count = 0; - - memset(&list, 0, sizeof(list)); - list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); - bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE, - iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); - rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN); - - results->buflen = dtoh32(results->buflen); - results->version = dtoh32(results->version); - *scan_count = results->count = dtoh32(results->count); - status = dtoh32(list_buf->status); - - dhd_iscan_unlock(); - - if (!(*scan_count)) - dhd_iscan_free_buf(dhdp, iscan_cur); - else - dhd_iscan_remove_duplicates(dhdp, iscan_cur); - - -fail: - return status; -} - -#endif - -/* Android ComboSCAN support */ -#if defined(CSCAN) - -/* - * data parsing from ComboScan tlv list -*/ -int -wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, const char token, \ - int input_size, int *bytes_left) -{ - char* str = *list_str; - uint16 short_temp; - uint32 int_temp; - - if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { - DHD_ERROR(("%s error paramters\n", __FUNCTION__)); - return -1; - } - - /* Clean all dest bytes */ - memset(dst, 0, dst_size); - while (*bytes_left > 0) { - - if (str[0] != token) { - DHD_TRACE(("%s NOT Type=%d get=%d left_parse=%d \n", __FUNCTION__, \ - token, str[0], *bytes_left)); - return -1; - } - - *bytes_left -= 1; - str += 1; - - if (input_size == 1) { - memcpy(dst, str, input_size); - } - else if (input_size == 2) { - memcpy(dst, (char *)htod16(memcpy(&short_temp, str, input_size)), \ - input_size); - } - else if (input_size == 4) { - memcpy(dst, (char *)htod32(memcpy(&int_temp, str, input_size)), \ - input_size); - } - - *bytes_left -= input_size; - str += input_size; - *list_str = str; - return 1; - } - return 1; -} - -/* - * channel list parsing from cscan tlv list -*/ -int -wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, \ - int channel_num, int *bytes_left) -{ - char* str = *list_str; - int idx = 0; - - if ((list_str == NULL) || (*list_str == NULL) ||(bytes_left == NULL) || (*bytes_left < 0)) { - DHD_ERROR(("%s error paramters\n", __FUNCTION__)); - return -1; - } - - while (*bytes_left > 0) { - - if (str[0] != CSCAN_TLV_TYPE_CHANNEL_IE) { - *list_str = str; - DHD_TRACE(("End channel=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); - return idx; - } - /* Get proper CSCAN_TLV_TYPE_CHANNEL_IE */ - *bytes_left -= 1; - str += 1; - - if (str[0] == 0) { - /* All channels */ - channel_list[idx] = 0x0; - } - else { - channel_list[idx] = (uint16)str[0]; - DHD_TRACE(("%s channel=%d \n", __FUNCTION__, channel_list[idx])); - } - *bytes_left -= 1; - str += 1; - - if (idx++ > 255) { - DHD_ERROR(("%s Too many channels \n", __FUNCTION__)); - return -1; - } - } - - *list_str = str; - return idx; -} - -/* - * SSIDs list parsing from cscan tlv list - */ -int -wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left) -{ - char* str = *list_str; - int idx = 0; - - if ((list_str == NULL) || (*list_str == NULL) || (*bytes_left < 0)) { - DHD_ERROR(("%s error paramters\n", __FUNCTION__)); - return -1; - } - - while (*bytes_left > 0) { - - if (str[0] != CSCAN_TLV_TYPE_SSID_IE) { - *list_str = str; - DHD_TRACE(("nssid=%d left_parse=%d %d\n", idx, *bytes_left, str[0])); - return idx; - } - - /* Get proper CSCAN_TLV_TYPE_SSID_IE */ - *bytes_left -= 1; - str += 1; - - if (str[0] == 0) { - /* Broadcast SSID */ - ssid[idx].SSID_len = 0; - memset((char*)ssid[idx].SSID, 0x0, DOT11_MAX_SSID_LEN); - *bytes_left -= 1; - str += 1; - - DHD_TRACE(("BROADCAST SCAN left=%d\n", *bytes_left)); - } - else if (str[0] <= DOT11_MAX_SSID_LEN) { - /* Get proper SSID size */ - ssid[idx].SSID_len = str[0]; - *bytes_left -= 1; - str += 1; - - /* Get SSID */ - if (ssid[idx].SSID_len > *bytes_left) { - DHD_ERROR(("%s out of memory range len=%d but left=%d\n", \ - __FUNCTION__, ssid[idx].SSID_len, *bytes_left)); - return -1; - } - - memcpy((char*)ssid[idx].SSID, str, ssid[idx].SSID_len); - - *bytes_left -= ssid[idx].SSID_len; - str += ssid[idx].SSID_len; - - DHD_TRACE(("%s :size=%d left=%d\n", (char*)ssid[idx].SSID, \ - ssid[idx].SSID_len, *bytes_left)); - } - else { - DHD_ERROR(("### SSID size more that %d\n", str[0])); - return -1; - } - - if (idx++ > max) { - DHD_ERROR(("%s number of SSIDs more that %d\n", __FUNCTION__, idx)); - return -1; - } - } - - *list_str = str; - return idx; -} - -/* Parse a comma-separated list from list_str into ssid array, starting - * at index idx. Max specifies size of the ssid array. Parses ssids - * and returns updated idx; if idx >= max not all fit, the excess have - * not been copied. Returns -1 on empty string, or on ssid too long. - */ -int -wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max) -{ - char* str, *ptr; - - if ((list_str == NULL) || (*list_str == NULL)) - return -1; - - for (str = *list_str; str != NULL; str = ptr) { - - /* check for next TAG */ - if (!strncmp(str, GET_CHANNEL, strlen(GET_CHANNEL))) { - *list_str = str + strlen(GET_CHANNEL); - return idx; - } - - if ((ptr = strchr(str, ',')) != NULL) { - *ptr++ = '\0'; - } - - if (strlen(str) > DOT11_MAX_SSID_LEN) { - DHD_ERROR(("ssid <%s> exceeds %d\n", str, DOT11_MAX_SSID_LEN)); - return -1; - } - - if (strlen(str) == 0) - ssid[idx].SSID_len = 0; - - if (idx < max) { - strcpy((char*)ssid[idx].SSID, str); - ssid[idx].SSID_len = strlen(str); - } - idx++; - } - return idx; -} - -/* - * Parse channel list from iwpriv CSCAN - */ -int -wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num) -{ - int num; - int val; - char* str; - char* endptr = NULL; - - if ((list_str == NULL)||(*list_str == NULL)) - return -1; - - str = *list_str; - num = 0; - while (strncmp(str, GET_NPROBE, strlen(GET_NPROBE))) { - val = (int)strtoul(str, &endptr, 0); - if (endptr == str) { - printf("could not parse channel number starting at" - " substring \"%s\" in list:\n%s\n", - str, *list_str); - return -1; - } - str = endptr + strspn(endptr, " ,"); - - if (num == channel_num) { - DHD_ERROR(("too many channels (more than %d) in channel list:\n%s\n", - channel_num, *list_str)); - return -1; - } - - channel_list[num++] = (uint16)val; - } - *list_str = str; - return num; -} - -#endif diff --git a/drivers/net/wireless/bcm4329/dhd_custom_gpio.c b/drivers/net/wireless/bcm4329/dhd_custom_gpio.c deleted file mode 100644 index f2b7adbed0d3..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_custom_gpio.c +++ /dev/null @@ -1,186 +0,0 @@ -/* -* Customer code to add GPIO control during WLAN start/stop -* Copyright (C) 1999-2010, Broadcom Corporation -* -* Unless you and Broadcom execute a separate written software license -* agreement governing use of this software, this software is licensed to you -* under the terms of the GNU General Public License version 2 (the "GPL"), -* available at http://www.broadcom.com/licenses/GPLv2.php, with the -* following added to such license: -* -* As a special exception, the copyright holders of this software give you -* permission to link this software with independent modules, and to copy and -* distribute the resulting executable under terms of your choice, provided that -* you also meet, for each linked independent module, the terms and conditions of -* the license of that module. An independent module is a module which is not -* derived from this software. The special exception does not apply to any -* modifications of the software. -* -* Notwithstanding the above, under no circumstances may you combine this -* software in any way with any other Broadcom software provided under a license -* other than the GPL, without Broadcom's express prior written consent. -* -* $Id: dhd_custom_gpio.c,v 1.1.4.7 2010/06/03 21:27:48 Exp $ -*/ - - -#include -#include -#include -#include - -#include -#include - -#include -#include - -#define WL_ERROR(x) printf x -#define WL_TRACE(x) - -#ifdef CUSTOMER_HW -extern void bcm_wlan_power_off(int); -extern void bcm_wlan_power_on(int); -#endif /* CUSTOMER_HW */ -#ifdef CUSTOMER_HW2 -int wifi_set_carddetect(int on); -int wifi_set_power(int on, unsigned long msec); -int wifi_get_irq_number(unsigned long *irq_flags_ptr); -#endif - -#if defined(CONFIG_WIFI_CONTROL_FUNC) -int wifi_set_power(int on, unsigned long msec); -int wifi_set_reset(int on, unsigned long msec); -#endif - -#if defined(OOB_INTR_ONLY) - -#if defined(BCMLXSDMMC) -extern int sdioh_mmc_irq(int irq); -#endif /* (BCMLXSDMMC) */ - -#ifdef CUSTOMER_HW3 -#include -#endif - -/* Customer specific Host GPIO defintion */ -static int dhd_oob_gpio_num = -1; /* GG 19 */ - -module_param(dhd_oob_gpio_num, int, 0644); -MODULE_PARM_DESC(dhd_oob_gpio_num, "DHD oob gpio number"); - -int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr) -{ - int host_oob_irq = 0; - -#ifdef CUSTOMER_HW2 - host_oob_irq = wifi_get_irq_number(irq_flags_ptr); - -#else /* for NOT CUSTOMER_HW2 */ -#if defined(CUSTOM_OOB_GPIO_NUM) - if (dhd_oob_gpio_num < 0) { - dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM; - } -#endif - *irq_flags_ptr = IRQF_TRIGGER_FALLING; - if (dhd_oob_gpio_num < 0) { - WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n", - __FUNCTION__)); - return (dhd_oob_gpio_num); - } - - WL_ERROR(("%s: customer specific Host GPIO number is (%d)\n", - __FUNCTION__, dhd_oob_gpio_num)); - -#if defined CUSTOMER_HW - host_oob_irq = MSM_GPIO_TO_INT(dhd_oob_gpio_num); -#elif defined CUSTOMER_HW3 - gpio_request(dhd_oob_gpio_num, "oob irq"); - host_oob_irq = gpio_to_irq(dhd_oob_gpio_num); - gpio_direction_input(dhd_oob_gpio_num); -#endif /* CUSTOMER_HW */ -#endif /* CUSTOMER_HW2 */ - - return (host_oob_irq); -} -#endif /* defined(OOB_INTR_ONLY) */ - -/* Customer function to control hw specific wlan gpios */ -void -dhd_customer_gpio_wlan_ctrl(int onoff) -{ - switch (onoff) { - case WLAN_RESET_OFF: - WL_TRACE(("%s: call customer specific GPIO to insert WLAN RESET\n", - __FUNCTION__)); -#ifdef CUSTOMER_HW - bcm_wlan_power_off(2); -#endif /* CUSTOMER_HW */ -#ifdef CUSTOMER_HW2 - wifi_set_power(0, 0); -#endif -#if defined(CONFIG_WIFI_CONTROL_FUNC) - wifi_set_power(0, 0); - wifi_set_reset(0, 0); -#endif - WL_ERROR(("=========== WLAN placed in RESET ========\n")); - break; - - case WLAN_RESET_ON: - WL_TRACE(("%s: callc customer specific GPIO to remove WLAN RESET\n", - __FUNCTION__)); -#ifdef CUSTOMER_HW - bcm_wlan_power_on(2); -#endif /* CUSTOMER_HW */ -#ifdef CUSTOMER_HW2 - wifi_set_power(1, 0); -#endif -#if defined(CONFIG_WIFI_CONTROL_FUNC) - wifi_set_power(1, 0); - wifi_set_reset(1, 0); -#endif - WL_ERROR(("=========== WLAN going back to live ========\n")); - break; - - case WLAN_POWER_OFF: - WL_TRACE(("%s: call customer specific GPIO to turn off WL_REG_ON\n", - __FUNCTION__)); -#ifdef CUSTOMER_HW - bcm_wlan_power_off(1); -#endif /* CUSTOMER_HW */ - break; - - case WLAN_POWER_ON: - WL_TRACE(("%s: call customer specific GPIO to turn on WL_REG_ON\n", - __FUNCTION__)); -#ifdef CUSTOMER_HW - bcm_wlan_power_on(1); -#endif /* CUSTOMER_HW */ - /* Lets customer power to get stable */ - OSL_DELAY(500); - break; - } -} - -#ifdef GET_CUSTOM_MAC_ENABLE -/* Function to get custom MAC address */ -int -dhd_custom_get_mac_address(unsigned char *buf) -{ - WL_TRACE(("%s Enter\n", __FUNCTION__)); - if (!buf) - return -EINVAL; - - /* Customer access to MAC address stored outside of DHD driver */ - -#ifdef EXAMPLE_GET_MAC - /* EXAMPLE code */ - { - struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}}; - bcopy((char *)&ea_example, buf, sizeof(struct ether_addr)); - } -#endif /* EXAMPLE_GET_MAC */ - - return 0; -} -#endif /* GET_CUSTOM_MAC_ENABLE */ diff --git a/drivers/net/wireless/bcm4329/dhd_dbg.h b/drivers/net/wireless/bcm4329/dhd_dbg.h deleted file mode 100644 index 9f09ce7fcc04..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_dbg.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Debug/trace/assert driver definitions for Dongle Host Driver. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_dbg.h,v 1.5.6.2.4.2.14.10 2010/05/21 21:49:38 Exp $ - */ - -#ifndef _dhd_dbg_ -#define _dhd_dbg_ - -#if 0 || (defined DHD_DEBUG) - -#define DHD_ERROR(args) do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \ - printf args;} while (0) -#define DHD_TRACE(args) do {if (dhd_msg_level & DHD_TRACE_VAL) printf args;} while (0) -#define DHD_INFO(args) do {if (dhd_msg_level & DHD_INFO_VAL) printf args;} while (0) -#define DHD_DATA(args) do {if (dhd_msg_level & DHD_DATA_VAL) printf args;} while (0) -#define DHD_CTL(args) do {if (dhd_msg_level & DHD_CTL_VAL) printf args;} while (0) -#define DHD_TIMER(args) do {if (dhd_msg_level & DHD_TIMER_VAL) printf args;} while (0) -#define DHD_HDRS(args) do {if (dhd_msg_level & DHD_HDRS_VAL) printf args;} while (0) -#define DHD_BYTES(args) do {if (dhd_msg_level & DHD_BYTES_VAL) printf args;} while (0) -#define DHD_INTR(args) do {if (dhd_msg_level & DHD_INTR_VAL) printf args;} while (0) -#define DHD_GLOM(args) do {if (dhd_msg_level & DHD_GLOM_VAL) printf args;} while (0) -#define DHD_EVENT(args) do {if (dhd_msg_level & DHD_EVENT_VAL) printf args;} while (0) -#define DHD_BTA(args) do {if (dhd_msg_level & DHD_BTA_VAL) printf args;} while (0) -#define DHD_ISCAN(args) do {if (dhd_msg_level & DHD_ISCAN_VAL) printf args;} while (0) - -#define DHD_ERROR_ON() (dhd_msg_level & DHD_ERROR_VAL) -#define DHD_TRACE_ON() (dhd_msg_level & DHD_TRACE_VAL) -#define DHD_INFO_ON() (dhd_msg_level & DHD_INFO_VAL) -#define DHD_DATA_ON() (dhd_msg_level & DHD_DATA_VAL) -#define DHD_CTL_ON() (dhd_msg_level & DHD_CTL_VAL) -#define DHD_TIMER_ON() (dhd_msg_level & DHD_TIMER_VAL) -#define DHD_HDRS_ON() (dhd_msg_level & DHD_HDRS_VAL) -#define DHD_BYTES_ON() (dhd_msg_level & DHD_BYTES_VAL) -#define DHD_INTR_ON() (dhd_msg_level & DHD_INTR_VAL) -#define DHD_GLOM_ON() (dhd_msg_level & DHD_GLOM_VAL) -#define DHD_EVENT_ON() (dhd_msg_level & DHD_EVENT_VAL) -#define DHD_BTA_ON() (dhd_msg_level & DHD_BTA_VAL) -#define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL) - -#else /* (defined BCMDBG) || (defined DHD_DEBUG) */ - -#define DHD_ERROR(args) do {if (net_ratelimit()) printf args;} while (0) -#define DHD_TRACE(args) -#define DHD_INFO(args) -#define DHD_DATA(args) -#define DHD_CTL(args) -#define DHD_TIMER(args) -#define DHD_HDRS(args) -#define DHD_BYTES(args) -#define DHD_INTR(args) -#define DHD_GLOM(args) -#define DHD_EVENT(args) -#define DHD_BTA(args) -#define DHD_ISCAN(args) - -#define DHD_ERROR_ON() 0 -#define DHD_TRACE_ON() 0 -#define DHD_INFO_ON() 0 -#define DHD_DATA_ON() 0 -#define DHD_CTL_ON() 0 -#define DHD_TIMER_ON() 0 -#define DHD_HDRS_ON() 0 -#define DHD_BYTES_ON() 0 -#define DHD_INTR_ON() 0 -#define DHD_GLOM_ON() 0 -#define DHD_EVENT_ON() 0 -#define DHD_BTA_ON() 0 -#define DHD_ISCAN_ON() 0 -#endif - -#define DHD_LOG(args) - -#define DHD_NONE(args) -extern int dhd_msg_level; - -/* Defines msg bits */ -#include - -#endif /* _dhd_dbg_ */ diff --git a/drivers/net/wireless/bcm4329/dhd_linux.c b/drivers/net/wireless/bcm4329/dhd_linux.c deleted file mode 100644 index e610b4b0d7ea..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_linux.c +++ /dev/null @@ -1,2891 +0,0 @@ -/* - * Broadcom Dongle Host Driver (DHD), Linux-specific network interface - * Basically selected code segments from usb-cdc.c and usb-rndis.c - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_linux.c,v 1.65.4.9.2.12.2.89 2010/07/21 18:07:11 Exp $ - */ - - -#ifdef CONFIG_WIFI_CONTROL_FUNC -#include -#endif -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#if defined(CONFIG_WIFI_CONTROL_FUNC) -#include - -struct semaphore wifi_control_sem; - -struct dhd_bus *g_bus; - -static struct wifi_platform_data *wifi_control_data = NULL; -//static struct resource *wifi_irqres = NULL; -#if 0 -int wifi_get_irq_number(unsigned long *irq_flags_ptr) -{ - if (wifi_irqres) { - *irq_flags_ptr = wifi_irqres->flags & IRQF_TRIGGER_MASK; - return (int)wifi_irqres->start; - } -#ifdef CUSTOM_OOB_GPIO_NUM - return CUSTOM_OOB_GPIO_NUM; -#else - return -1; -#endif -} -#endif - -int wifi_set_carddetect(int on) -{ - printk("%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_carddetect) { - wifi_control_data->set_carddetect(on); - } - return 0; -} - -int wifi_set_power(int on, unsigned long msec) -{ - printk("%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_power) { - wifi_control_data->set_power(on); - } - if (msec) - mdelay(msec); - return 0; -} - -int wifi_set_reset(int on, unsigned long msec) -{ - printk("%s = %d\n", __FUNCTION__, on); - if (wifi_control_data && wifi_control_data->set_reset) { - wifi_control_data->set_reset(on); - } - if (msec) - mdelay(msec); - return 0; -} -static int wifi_probe(struct platform_device *pdev) -{ - struct wifi_platform_data *wifi_ctrl = - (struct wifi_platform_data *)(pdev->dev.platform_data); - - printk("## %s\n", __FUNCTION__); -// wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq"); - wifi_control_data = wifi_ctrl; - - wifi_set_power(1, 0); /* Power On */ - wifi_set_reset(1, 0); - wifi_set_carddetect(1); /* CardDetect (0->1) */ - - up(&wifi_control_sem); - return 0; -} - -static int wifi_remove(struct platform_device *pdev) -{ - struct wifi_platform_data *wifi_ctrl = - (struct wifi_platform_data *)(pdev->dev.platform_data); - - printk("## %s\n", __FUNCTION__); - wifi_control_data = wifi_ctrl; - - wifi_set_power(0, 0); - wifi_set_reset(0, 0); - wifi_set_carddetect(0); /* CardDetect (1->0) */ - - up(&wifi_control_sem); - return 0; -} -static int wifi_suspend(struct platform_device *pdev, pm_message_t state) -{ - DHD_TRACE(("##> %s\n", __FUNCTION__)); - return 0; -} -static int wifi_resume(struct platform_device *pdev) -{ - DHD_TRACE(("##> %s\n", __FUNCTION__)); - return 0; -} - -static struct platform_driver wifi_device = { - .probe = wifi_probe, - .remove = wifi_remove, - .suspend = wifi_suspend, - .resume = wifi_resume, - .driver = { - .name = "bcm4329_wlan", - } -}; - -int wifi_add_dev(void) -{ - DHD_TRACE(("## Calling platform_driver_register\n")); - return platform_driver_register(&wifi_device); -} - -void wifi_del_dev(void) -{ - DHD_TRACE(("## Unregister platform_driver_register\n")); - platform_driver_unregister(&wifi_device); -} -#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) -#include -volatile bool dhd_mmc_suspend = FALSE; -DECLARE_WAIT_QUEUE_HEAD(dhd_dpc_wait); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ - -#if defined(OOB_INTR_ONLY) -extern void dhd_enable_oob_intr(struct dhd_bus *bus, bool enable); -#endif /* defined(OOB_INTR_ONLY) */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -MODULE_LICENSE("GPL v2"); -#endif /* LinuxVer */ - -#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) -const char * -print_tainted() -{ - return ""; -} -#endif /* LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15) */ - -/* Linux wireless extension support */ -#if defined(CONFIG_WIRELESS_EXT) -#include -#endif /* defined(CONFIG_WIRELESS_EXT) */ - -#if defined(CONFIG_HAS_EARLYSUSPEND) -#include -extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); -extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); -extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ - -/* Interface control information */ -typedef struct dhd_if { - struct dhd_info *info; /* back pointer to dhd_info */ - /* OS/stack specifics */ - struct net_device *net; - struct net_device_stats stats; - int idx; /* iface idx in dongle */ - int state; /* interface state */ - uint subunit; /* subunit */ - uint8 mac_addr[ETHER_ADDR_LEN]; /* assigned MAC address */ - bool attached; /* Delayed attachment when unset */ - bool txflowcontrol; /* Per interface flow control indicator */ - char name[IFNAMSIZ+1]; /* linux interface name */ -} dhd_if_t; - -/* Local private structure (extension of pub) */ -typedef struct dhd_info { -#if defined(CONFIG_WIRELESS_EXT) - wl_iw_t iw; /* wireless extensions state (must be first) */ -#endif /* defined(CONFIG_WIRELESS_EXT) */ - - dhd_pub_t pub; - - /* OS/stack specifics */ - dhd_if_t *iflist[DHD_MAX_IFS]; - - struct semaphore proto_sem; - wait_queue_head_t ioctl_resp_wait; - struct timer_list timer; - bool wd_timer_valid; - struct tasklet_struct tasklet; - spinlock_t sdlock; - spinlock_t txqlock; - /* Thread based operation */ - bool threads_only; - struct semaphore sdsem; - long watchdog_pid; - struct semaphore watchdog_sem; - struct completion watchdog_exited; - long dpc_pid; - struct semaphore dpc_sem; - struct completion dpc_exited; - - /* Thread to issue ioctl for multicast */ - long sysioc_pid; - struct semaphore sysioc_sem; - struct completion sysioc_exited; - bool set_multicast; - bool set_macaddress; - struct ether_addr macvalue; - wait_queue_head_t ctrl_wait; - atomic_t pend_8021x_cnt; - -#ifdef CONFIG_HAS_EARLYSUSPEND - struct early_suspend early_suspend; -#endif /* CONFIG_HAS_EARLYSUSPEND */ -} dhd_info_t; - -/* Definitions to provide path to the firmware and nvram - * example nvram_path[MOD_PARAM_PATHLEN]="/projects/wlan/nvram.txt" - */ -char firmware_path[MOD_PARAM_PATHLEN]; -char nvram_path[MOD_PARAM_PATHLEN]; - -extern int wl_control_wl_start(struct net_device *dev); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) -struct semaphore dhd_registration_sem; -#define DHD_REGISTRATION_TIMEOUT 10000 /* msec : allowed time to finished dhd registration */ -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -/* load firmware and/or nvram values from the filesystem */ -module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0); -module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); - -/* Error bits */ -module_param(dhd_msg_level, int, 0); - -/* Spawn a thread for system ioctls (set mac, set mcast) */ -uint dhd_sysioc = TRUE; -module_param(dhd_sysioc, uint, 0); - -/* Watchdog interval */ -uint dhd_watchdog_ms = 10; -module_param(dhd_watchdog_ms, uint, 0); - -#ifdef DHD_DEBUG -/* Console poll interval */ -uint dhd_console_ms = 0; -module_param(dhd_console_ms, uint, 0); -#endif /* DHD_DEBUG */ - -/* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */ -uint dhd_arp_mode = 0xb; -module_param(dhd_arp_mode, uint, 0); - -/* ARP offload enable */ -uint dhd_arp_enable = TRUE; -module_param(dhd_arp_enable, uint, 0); - -/* Global Pkt filter enable control */ -uint dhd_pkt_filter_enable = TRUE; -module_param(dhd_pkt_filter_enable, uint, 0); - -/* Pkt filter init setup */ -uint dhd_pkt_filter_init = 0; -module_param(dhd_pkt_filter_init, uint, 0); - -/* Pkt filter mode control */ -uint dhd_master_mode = TRUE; -module_param(dhd_master_mode, uint, 1); - -/* Watchdog thread priority, -1 to use kernel timer */ -int dhd_watchdog_prio = 97; -module_param(dhd_watchdog_prio, int, 0); - -/* DPC thread priority, -1 to use tasklet */ -int dhd_dpc_prio = 98; -module_param(dhd_dpc_prio, int, 0); - -/* DPC thread priority, -1 to use tasklet */ -extern int dhd_dongle_memsize; -module_param(dhd_dongle_memsize, int, 0); - -/* Contorl fw roaming */ -#ifdef CUSTOMER_HW2 -uint dhd_roam = 0; -#else -uint dhd_roam = 1; -#endif - -/* Control radio state */ -uint dhd_radio_up = 1; - -/* Network inteface name */ -char iface_name[IFNAMSIZ]; -module_param_string(iface_name, iface_name, IFNAMSIZ, 0); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define DAEMONIZE(a) daemonize(a); \ - allow_signal(SIGKILL); \ - allow_signal(SIGTERM); -#else /* Linux 2.4 (w/o preemption patch) */ -#define RAISE_RX_SOFTIRQ() \ - cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) -#define DAEMONIZE(a) daemonize(); \ - do { if (a) \ - strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ - } while (0); -#endif /* LINUX_VERSION_CODE */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define BLOCKABLE() (!in_atomic()) -#else -#define BLOCKABLE() (!in_interrupt()) -#endif - -/* The following are specific to the SDIO dongle */ - -/* IOCTL response timeout */ -int dhd_ioctl_timeout_msec = IOCTL_RESP_TIMEOUT; - -/* Idle timeout for backplane clock */ -int dhd_idletime = DHD_IDLETIME_TICKS; -module_param(dhd_idletime, int, 0); - -/* Use polling */ -uint dhd_poll = FALSE; -module_param(dhd_poll, uint, 0); - - -/* Use interrupts */ -uint dhd_intr = TRUE; -module_param(dhd_intr, uint, 0); - -/* SDIO Drive Strength (in milliamps) */ -uint dhd_sdiod_drive_strength = 6; -module_param(dhd_sdiod_drive_strength, uint, 0); - -/* Tx/Rx bounds */ -extern uint dhd_txbound; -extern uint dhd_rxbound; -module_param(dhd_txbound, uint, 0); -module_param(dhd_rxbound, uint, 0); - -/* Deferred transmits */ -extern uint dhd_deferred_tx; -module_param(dhd_deferred_tx, uint, 0); - - - -#ifdef SDTEST -/* Echo packet generator (pkts/s) */ -uint dhd_pktgen = 0; -module_param(dhd_pktgen, uint, 0); - -/* Echo packet len (0 => sawtooth, max 2040) */ -uint dhd_pktgen_len = 0; -module_param(dhd_pktgen_len, uint, 0); -#endif - - -/* Version string to report */ -#ifdef DHD_DEBUG -#define DHD_COMPILED "\nCompiled in " SRCBASE -#else -#define DHD_COMPILED -#endif - -static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR -#ifdef DHD_DEBUG -"\nCompiled in " SRCBASE " on " __DATE__ " at " __TIME__ -#endif -; - - -#if defined(CONFIG_WIRELESS_EXT) -struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); -#endif /* defined(CONFIG_WIRELESS_EXT) */ - -static void dhd_dpc(ulong data); -/* forward decl */ -extern int dhd_wait_pend8021x(struct net_device *dev); - -#ifdef TOE -#ifndef BDC -#error TOE requires BDC -#endif /* !BDC */ -static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol); -static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol); -#endif /* TOE */ - -static int dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, - wl_event_msg_t *event_ptr, void **data_ptr); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) && 1 -static int dhd_sleep_pm_callback(struct notifier_block *nfb, unsigned long action, void *ignored) -{ - switch (action) - { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - dhd_mmc_suspend = TRUE; - return NOTIFY_OK; - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - dhd_mmc_suspend = FALSE; - return NOTIFY_OK; - } - return 0; -} - -static struct notifier_block dhd_sleep_pm_notifier = { - .notifier_call = dhd_sleep_pm_callback, - .priority = 0 -}; -extern int register_pm_notifier(struct notifier_block *nb); -extern int unregister_pm_notifier(struct notifier_block *nb); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ - /* && defined(DHD_GPL) */ - - -#if defined(CONFIG_HAS_EARLYSUSPEND) - -int dhd_set_suspend(int value, dhd_pub_t *dhd) -{ - int power_mode = PM_MAX; - /* wl_pkt_filter_enable_t enable_parm; */ - char iovbuf[32]; - int bcn_li_dtim = 3; -#ifdef CUSTOMER_HW2 - uint roamvar = 1; -#endif /* CUSTOMER_HW2 */ - int i; - -#define htod32(i) i - - if (dhd && dhd->up) { - dhd_os_proto_block(dhd); - if (value) { - - /* Kernel suspended */ - dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, - (char *)&power_mode, sizeof(power_mode)); - - /* Enable packet filter, only allow unicast packet to send up */ - if (dhd_pkt_filter_enable) { - for (i = 0; i < dhd->pktfilter_count; i++) { - dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); - dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], - 1, dhd_master_mode); - } - } - - /* set bcn_li_dtim */ - bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, - 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); -#ifdef CUSTOMER_HW2 - /* Disable build-in roaming to allowed ext supplicant to take of romaing */ - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); -#endif /* CUSTOMER_HW2 */ - } else { - - /* Kernel resumed */ - power_mode = PM_FAST; - dhdcdc_set_ioctl(dhd, 0, WLC_SET_PM, (char *)&power_mode, - sizeof(power_mode)); - - /* disable pkt filter */ - if (dhd_pkt_filter_enable) { - for (i = 0; i < dhd->pktfilter_count; i++) { - dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); - dhd_pktfilter_offload_enable(dhd, dhd->pktfilter[i], - 0, dhd_master_mode); - } - } - - /* set bcn_li_dtim */ - bcn_li_dtim = 0; - bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, - 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); -#ifdef CUSTOMER_HW2 - roamvar = 0; - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, iovbuf, sizeof(iovbuf)); -#endif /* CUSTOMER_HW2 */ - } - dhd_os_proto_unblock(dhd); - } - - return 0; -} - -static void dhd_early_suspend(struct early_suspend *h) -{ - struct dhd_info *dhdp; - dhdp = container_of(h, struct dhd_info, early_suspend); - - DHD_TRACE(("%s: enter\n", __FUNCTION__)); - - dhd_set_suspend(1, &dhdp->pub); -} - -static void dhd_late_resume(struct early_suspend *h) -{ - struct dhd_info *dhdp; - dhdp = container_of(h, struct dhd_info, early_suspend); - - DHD_TRACE(("%s: enter\n", __FUNCTION__)); - - dhd_set_suspend(0, &dhdp->pub); -} -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ - -/* - * Generalized timeout mechanism. Uses spin sleep with exponential back-off until - * the sleep time reaches one jiffy, then switches over to task delay. Usage: - * - * dhd_timeout_start(&tmo, usec); - * while (!dhd_timeout_expired(&tmo)) - * if (poll_something()) - * break; - * if (dhd_timeout_expired(&tmo)) - * fatal(); - */ - -void -dhd_timeout_start(dhd_timeout_t *tmo, uint usec) -{ - tmo->limit = usec; - tmo->increment = 0; - tmo->elapsed = 0; - tmo->tick = 1000000 / HZ; -} - -int -dhd_timeout_expired(dhd_timeout_t *tmo) -{ - /* Does nothing the first call */ - if (tmo->increment == 0) { - tmo->increment = 1; - return 0; - } - - if (tmo->elapsed >= tmo->limit) - return 1; - - /* Add the delay that's about to take place */ - tmo->elapsed += tmo->increment; - - if (tmo->increment < tmo->tick) { - OSL_DELAY(tmo->increment); - tmo->increment *= 2; - if (tmo->increment > tmo->tick) - tmo->increment = tmo->tick; - } else { - wait_queue_head_t delay_wait; - DECLARE_WAITQUEUE(wait, current); - int pending; - init_waitqueue_head(&delay_wait); - add_wait_queue(&delay_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(1); - pending = signal_pending(current); - remove_wait_queue(&delay_wait, &wait); - set_current_state(TASK_RUNNING); - if (pending) - return 1; /* Interrupted */ - } - - return 0; -} - -static int -dhd_net2idx(dhd_info_t *dhd, struct net_device *net) -{ - int i = 0; - - ASSERT(dhd); - while (i < DHD_MAX_IFS) { - if (dhd->iflist[i] && (dhd->iflist[i]->net == net)) - return i; - i++; - } - - return DHD_BAD_IF; -} - -int -dhd_ifname2idx(dhd_info_t *dhd, char *name) -{ - int i = DHD_MAX_IFS; - - ASSERT(dhd); - - if (name == NULL || *name == '\0') - return 0; - - while (--i > 0) - if (dhd->iflist[i] && !strncmp(dhd->iflist[i]->name, name, IFNAMSIZ)) - break; - - DHD_TRACE(("%s: return idx %d for \"%s\"\n", __FUNCTION__, i, name)); - - return i; /* default - the primary interface */ -} - -char * -dhd_ifname(dhd_pub_t *dhdp, int ifidx) -{ - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - - ASSERT(dhd); - - if (ifidx < 0 || ifidx >= DHD_MAX_IFS) { - DHD_ERROR(("%s: ifidx %d out of range\n", __FUNCTION__, ifidx)); - return ""; - } - - if (dhd->iflist[ifidx] == NULL) { - DHD_ERROR(("%s: null i/f %d\n", __FUNCTION__, ifidx)); - return ""; - } - - if (dhd->iflist[ifidx]->net) - return dhd->iflist[ifidx]->net->name; - - return ""; -} - -static void -_dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) -{ - struct net_device *dev; - struct dev_mc_list *mclist; - uint32 allmulti, cnt; - - wl_ioctl_t ioc; - char *buf, *bufp; - uint buflen; - int ret; - - ASSERT(dhd && dhd->iflist[ifidx]); - dev = dhd->iflist[ifidx]->net; - mclist = dev->mc_list; - cnt = dev->mc_count; - - /* Determine initial value of allmulti flag */ - allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; - - /* Send down the multicast list first. */ - - - buflen = sizeof("mcast_list") + sizeof(cnt) + (cnt * ETHER_ADDR_LEN); - if (!(bufp = buf = MALLOC(dhd->pub.osh, buflen))) { - DHD_ERROR(("%s: out of memory for mcast_list, cnt %d\n", - dhd_ifname(&dhd->pub, ifidx), cnt)); - return; - } - - strcpy(bufp, "mcast_list"); - bufp += strlen("mcast_list") + 1; - - cnt = htol32(cnt); - memcpy(bufp, &cnt, sizeof(cnt)); - bufp += sizeof(cnt); - - for (cnt = 0; mclist && (cnt < dev->mc_count); cnt++, mclist = mclist->next) { - memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); - bufp += ETHER_ADDR_LEN; - } - - memset(&ioc, 0, sizeof(ioc)); - ioc.cmd = WLC_SET_VAR; - ioc.buf = buf; - ioc.len = buflen; - ioc.set = TRUE; - - ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); - if (ret < 0) { - DHD_ERROR(("%s: set mcast_list failed, cnt %d\n", - dhd_ifname(&dhd->pub, ifidx), cnt)); - allmulti = cnt ? TRUE : allmulti; - } - - MFREE(dhd->pub.osh, buf, buflen); - - /* Now send the allmulti setting. This is based on the setting in the - * net_device flags, but might be modified above to be turned on if we - * were trying to set some addresses and dongle rejected it... - */ - - buflen = sizeof("allmulti") + sizeof(allmulti); - if (!(buf = MALLOC(dhd->pub.osh, buflen))) { - DHD_ERROR(("%s: out of memory for allmulti\n", dhd_ifname(&dhd->pub, ifidx))); - return; - } - allmulti = htol32(allmulti); - - if (!bcm_mkiovar("allmulti", (void*)&allmulti, sizeof(allmulti), buf, buflen)) { - DHD_ERROR(("%s: mkiovar failed for allmulti, datalen %d buflen %u\n", - dhd_ifname(&dhd->pub, ifidx), (int)sizeof(allmulti), buflen)); - MFREE(dhd->pub.osh, buf, buflen); - return; - } - - - memset(&ioc, 0, sizeof(ioc)); - ioc.cmd = WLC_SET_VAR; - ioc.buf = buf; - ioc.len = buflen; - ioc.set = TRUE; - - ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); - if (ret < 0) { - DHD_ERROR(("%s: set allmulti %d failed\n", - dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti))); - } - - MFREE(dhd->pub.osh, buf, buflen); - - /* Finally, pick up the PROMISC flag as well, like the NIC driver does */ - - allmulti = (dev->flags & IFF_PROMISC) ? TRUE : FALSE; - allmulti = htol32(allmulti); - - memset(&ioc, 0, sizeof(ioc)); - ioc.cmd = WLC_SET_PROMISC; - ioc.buf = &allmulti; - ioc.len = sizeof(allmulti); - ioc.set = TRUE; - - ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); - if (ret < 0) { - DHD_ERROR(("%s: set promisc %d failed\n", - dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti))); - } -} - -static int -_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr) -{ - char buf[32]; - wl_ioctl_t ioc; - int ret; - - DHD_TRACE(("%s enter\n", __FUNCTION__)); - if (!bcm_mkiovar("cur_etheraddr", (char*)addr, ETHER_ADDR_LEN, buf, 32)) { - DHD_ERROR(("%s: mkiovar failed for cur_etheraddr\n", dhd_ifname(&dhd->pub, ifidx))); - return -1; - } - memset(&ioc, 0, sizeof(ioc)); - ioc.cmd = WLC_SET_VAR; - ioc.buf = buf; - ioc.len = 32; - ioc.set = TRUE; - - ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len); - if (ret < 0) { - DHD_ERROR(("%s: set cur_etheraddr failed\n", dhd_ifname(&dhd->pub, ifidx))); - } else { - memcpy(dhd->iflist[ifidx]->net->dev_addr, addr, ETHER_ADDR_LEN); - } - - return ret; -} - -#ifdef SOFTAP -extern struct net_device *ap_net_dev; -#endif - -static void -dhd_op_if(dhd_if_t *ifp) -{ - dhd_info_t *dhd; - int ret = 0, err = 0; - - ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */ - - dhd = ifp->info; - - DHD_TRACE(("%s: idx %d, state %d\n", __FUNCTION__, ifp->idx, ifp->state)); - - switch (ifp->state) { - case WLC_E_IF_ADD: - /* - * Delete the existing interface before overwriting it - * in case we missed the WLC_E_IF_DEL event. - */ - if (ifp->net != NULL) { - DHD_ERROR(("%s: ERROR: netdev:%s already exists, try free & unregister \n", - __FUNCTION__, ifp->net->name)); - netif_stop_queue(ifp->net); - unregister_netdev(ifp->net); - free_netdev(ifp->net); - } - /* Allocate etherdev, including space for private structure */ - if (!(ifp->net = alloc_etherdev(sizeof(dhd)))) { - DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); - ret = -ENOMEM; - } - if (ret == 0) { - strcpy(ifp->net->name, ifp->name); - memcpy(netdev_priv(ifp->net), &dhd, sizeof(dhd)); - if ((err = dhd_net_attach(&dhd->pub, ifp->idx)) != 0) { - DHD_ERROR(("%s: dhd_net_attach failed, err %d\n", - __FUNCTION__, err)); - ret = -EOPNOTSUPP; - } else { -#ifdef SOFTAP - /* semaphore that the soft AP CODE waits on */ - extern struct semaphore ap_eth_sema; - - /* save ptr to wl0.1 netdev for use in wl_iw.c */ - ap_net_dev = ifp->net; - /* signal to the SOFTAP 'sleeper' thread, wl0.1 is ready */ - up(&ap_eth_sema); -#endif - DHD_TRACE(("\n ==== pid:%x, net_device for if:%s created ===\n\n", - current->pid, ifp->net->name)); - ifp->state = 0; - } - } - break; - case WLC_E_IF_DEL: - if (ifp->net != NULL) { - DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n", __FUNCTION__)); - netif_stop_queue(ifp->net); - unregister_netdev(ifp->net); - ret = DHD_DEL_IF; /* Make sure the free_netdev() is called */ - } - break; - default: - DHD_ERROR(("%s: bad op %d\n", __FUNCTION__, ifp->state)); - ASSERT(!ifp->state); - break; - } - - if (ret < 0) { - if (ifp->net) { - free_netdev(ifp->net); - } - dhd->iflist[ifp->idx] = NULL; - MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); -#ifdef SOFTAP - if (ifp->net == ap_net_dev) - ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */ -#endif /* SOFTAP */ - } -} - -static int -_dhd_sysioc_thread(void *data) -{ - dhd_info_t *dhd = (dhd_info_t *)data; - int i; -#ifdef SOFTAP - bool in_ap = FALSE; -#endif - - DAEMONIZE("dhd_sysioc"); - - while (down_interruptible(&dhd->sysioc_sem) == 0) { - for (i = 0; i < DHD_MAX_IFS; i++) { - if (dhd->iflist[i]) { -#ifdef SOFTAP - in_ap = (ap_net_dev != NULL); -#endif /* SOFTAP */ - if (dhd->iflist[i]->state) - dhd_op_if(dhd->iflist[i]); -#ifdef SOFTAP - if (dhd->iflist[i] == NULL) { - DHD_TRACE(("\n\n %s: interface %d just been removed," - "!\n\n", __FUNCTION__, i)); - continue; - } - - if (in_ap && dhd->set_macaddress) { - DHD_TRACE(("attempt to set MAC for %s in AP Mode," - "blocked. \n", dhd->iflist[i]->net->name)); - dhd->set_macaddress = FALSE; - continue; - } - - if (in_ap && dhd->set_multicast) { - DHD_TRACE(("attempt to set MULTICAST list for %s" - "in AP Mode, blocked. \n", dhd->iflist[i]->net->name)); - dhd->set_multicast = FALSE; - continue; - } -#endif /* SOFTAP */ - if (dhd->set_multicast) { - dhd->set_multicast = FALSE; - _dhd_set_multicast_list(dhd, i); - } - if (dhd->set_macaddress) { - dhd->set_macaddress = FALSE; - _dhd_set_mac_address(dhd, i, &dhd->macvalue); - } - } - } - } - complete_and_exit(&dhd->sysioc_exited, 0); -} - -static int -dhd_set_mac_address(struct net_device *dev, void *addr) -{ - int ret = 0; - - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - struct sockaddr *sa = (struct sockaddr *)addr; - int ifidx; - - ifidx = dhd_net2idx(dhd, dev); - if (ifidx == DHD_BAD_IF) - return -1; - - ASSERT(dhd->sysioc_pid >= 0); - memcpy(&dhd->macvalue, sa->sa_data, ETHER_ADDR_LEN); - dhd->set_macaddress = TRUE; - up(&dhd->sysioc_sem); - - return ret; -} - -static void -dhd_set_multicast_list(struct net_device *dev) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ifidx; - - ifidx = dhd_net2idx(dhd, dev); - if (ifidx == DHD_BAD_IF) - return; - - ASSERT(dhd->sysioc_pid >= 0); - dhd->set_multicast = TRUE; - up(&dhd->sysioc_sem); -} - -int -dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) -{ - int ret; - dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); - - /* Reject if down */ - if (!dhdp->up || (dhdp->busstate == DHD_BUS_DOWN)) { - return -ENODEV; - } - - /* Update multicast statistic */ - if (PKTLEN(dhdp->osh, pktbuf) >= ETHER_ADDR_LEN) { - uint8 *pktdata = (uint8 *)PKTDATA(dhdp->osh, pktbuf); - struct ether_header *eh = (struct ether_header *)pktdata; - - if (ETHER_ISMULTI(eh->ether_dhost)) - dhdp->tx_multicast++; - if (ntoh16(eh->ether_type) == ETHER_TYPE_802_1X) - atomic_inc(&dhd->pend_8021x_cnt); - } - - /* Look into the packet and update the packet priority */ - if ((PKTPRIO(pktbuf) == 0)) - pktsetprio(pktbuf, FALSE); - - /* If the protocol uses a data header, apply it */ - dhd_prot_hdrpush(dhdp, ifidx, pktbuf); - - /* Use bus module to send data frame */ -#ifdef BCMDBUS - ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */); -#else - WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25); - ret = dhd_bus_txdata(dhdp->bus, pktbuf); -#endif /* BCMDBUS */ - - return ret; -} - -static int -dhd_start_xmit(struct sk_buff *skb, struct net_device *net) -{ - int ret; - void *pktbuf; - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - int ifidx; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Reject if down */ - if (!dhd->pub.up || (dhd->pub.busstate == DHD_BUS_DOWN)) { - DHD_ERROR(("%s: xmit rejected pub.up=%d busstate=%d \n", - __FUNCTION__, dhd->pub.up, dhd->pub.busstate)); - netif_stop_queue(net); - /* Send Event when bus down detected during data session */ - if (dhd->pub.busstate == DHD_BUS_DOWN) { - DHD_ERROR(("%s: Event RELOAD send up\n", __FUNCTION__)); - wl_iw_send_priv_event(net, "RELOAD"); - } - return -ENODEV; - } - - ifidx = dhd_net2idx(dhd, net); - if (ifidx == DHD_BAD_IF) { - DHD_ERROR(("%s: bad ifidx %d\n", __FUNCTION__, ifidx)); - netif_stop_queue(net); - return -ENODEV; - } - - /* Make sure there's enough room for any header */ - if (skb_headroom(skb) < dhd->pub.hdrlen) { - struct sk_buff *skb2; - - DHD_INFO(("%s: insufficient headroom\n", - dhd_ifname(&dhd->pub, ifidx))); - dhd->pub.tx_realloc++; - skb2 = skb_realloc_headroom(skb, dhd->pub.hdrlen); - dev_kfree_skb(skb); - if ((skb = skb2) == NULL) { - DHD_ERROR(("%s: skb_realloc_headroom failed\n", - dhd_ifname(&dhd->pub, ifidx))); - ret = -ENOMEM; - goto done; - } - } - - /* Convert to packet */ - if (!(pktbuf = PKTFRMNATIVE(dhd->pub.osh, skb))) { - DHD_ERROR(("%s: PKTFRMNATIVE failed\n", - dhd_ifname(&dhd->pub, ifidx))); - dev_kfree_skb_any(skb); - ret = -ENOMEM; - goto done; - } - - ret = dhd_sendpkt(&dhd->pub, ifidx, pktbuf); - - -done: - if (ret) - dhd->pub.dstats.tx_dropped++; - else - dhd->pub.tx_packets++; - - /* Return ok: we always eat the packet */ - return 0; -} - -void -dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state) -{ - struct net_device *net; - dhd_info_t *dhd = dhdp->info; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - dhdp->txoff = state; - ASSERT(dhd && dhd->iflist[ifidx]); - net = dhd->iflist[ifidx]->net; - if (state == ON) - netif_stop_queue(net); - else - netif_wake_queue(net); -} - -void -dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt) -{ - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - struct sk_buff *skb; - uchar *eth; - uint len; - void * data, *pnext, *save_pktbuf; - int i; - dhd_if_t *ifp; - wl_event_msg_t event; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - save_pktbuf = pktbuf; - - for (i = 0; pktbuf && i < numpkt; i++, pktbuf = pnext) { - - pnext = PKTNEXT(dhdp->osh, pktbuf); - PKTSETNEXT(wl->sh.osh, pktbuf, NULL); - - - skb = PKTTONATIVE(dhdp->osh, pktbuf); - - /* Get the protocol, maintain skb around eth_type_trans() - * The main reason for this hack is for the limitation of - * Linux 2.4 where 'eth_type_trans' uses the 'net->hard_header_len' - * to perform skb_pull inside vs ETH_HLEN. Since to avoid - * coping of the packet coming from the network stack to add - * BDC, Hardware header etc, during network interface registration - * we set the 'net->hard_header_len' to ETH_HLEN + extra space required - * for BDC, Hardware header etc. and not just the ETH_HLEN - */ - eth = skb->data; - len = skb->len; - - ifp = dhd->iflist[ifidx]; - if (ifp == NULL) - ifp = dhd->iflist[0]; - - ASSERT(ifp); - skb->dev = ifp->net; - skb->protocol = eth_type_trans(skb, skb->dev); - - if (skb->pkt_type == PACKET_MULTICAST) { - dhd->pub.rx_multicast++; - } - - skb->data = eth; - skb->len = len; - - /* Strip header, count, deliver upward */ - skb_pull(skb, ETH_HLEN); - - /* Process special event packets and then discard them */ - if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) - dhd_wl_host_event(dhd, &ifidx, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) - skb->mac_header, -#else - skb->mac.raw, -#endif - &event, - &data); - - ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]); - if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state) - ifp = dhd->iflist[ifidx]; - - if (ifp->net) - ifp->net->last_rx = jiffies; - - dhdp->dstats.rx_bytes += skb->len; - dhdp->rx_packets++; /* Local count */ - - if (in_interrupt()) { - netif_rx(skb); - } else { - /* If the receive is not processed inside an ISR, - * the softirqd must be woken explicitly to service - * the NET_RX_SOFTIRQ. In 2.6 kernels, this is handled - * by netif_rx_ni(), but in earlier kernels, we need - * to do it manually. - */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) - netif_rx_ni(skb); -#else - ulong flags; - netif_rx(skb); - local_irq_save(flags); - RAISE_RX_SOFTIRQ(); - local_irq_restore(flags); -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ - } - } -} - -void -dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx) -{ - /* Linux version has nothing to do */ - return; -} - -void -dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) -{ - uint ifidx; - dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); - struct ether_header *eh; - uint16 type; - - dhd_prot_hdrpull(dhdp, &ifidx, txp); - - eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); - type = ntoh16(eh->ether_type); - - if (type == ETHER_TYPE_802_1X) - atomic_dec(&dhd->pend_8021x_cnt); - -} - -static struct net_device_stats * -dhd_get_stats(struct net_device *net) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - dhd_if_t *ifp; - int ifidx; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - ifidx = dhd_net2idx(dhd, net); - if (ifidx == DHD_BAD_IF) - return NULL; - - ifp = dhd->iflist[ifidx]; - ASSERT(dhd && ifp); - - if (dhd->pub.up) { - /* Use the protocol to get dongle stats */ - dhd_prot_dstats(&dhd->pub); - } - - /* Copy dongle stats to net device stats */ - ifp->stats.rx_packets = dhd->pub.dstats.rx_packets; - ifp->stats.tx_packets = dhd->pub.dstats.tx_packets; - ifp->stats.rx_bytes = dhd->pub.dstats.rx_bytes; - ifp->stats.tx_bytes = dhd->pub.dstats.tx_bytes; - ifp->stats.rx_errors = dhd->pub.dstats.rx_errors; - ifp->stats.tx_errors = dhd->pub.dstats.tx_errors; - ifp->stats.rx_dropped = dhd->pub.dstats.rx_dropped; - ifp->stats.tx_dropped = dhd->pub.dstats.tx_dropped; - ifp->stats.multicast = dhd->pub.dstats.multicast; - - return &ifp->stats; -} - -static int -dhd_watchdog_thread(void *data) -{ - dhd_info_t *dhd = (dhd_info_t *)data; - WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_WATCHDOG, "dhd_watchdog_thread"); - - /* This thread doesn't need any user-level access, - * so get rid of all our resources - */ -#ifdef DHD_SCHED - if (dhd_watchdog_prio > 0) { - struct sched_param param; - param.sched_priority = (dhd_watchdog_prio < MAX_RT_PRIO)? - dhd_watchdog_prio:(MAX_RT_PRIO-1); - setScheduler(current, SCHED_FIFO, ¶m); - } -#endif /* DHD_SCHED */ - - DAEMONIZE("dhd_watchdog"); - - /* Run until signal received */ - while (1) { - if (down_interruptible (&dhd->watchdog_sem) == 0) { - if (dhd->pub.dongle_reset == FALSE) { - WAKE_LOCK(&dhd->pub, WAKE_LOCK_WATCHDOG); - /* Call the bus module watchdog */ - dhd_bus_watchdog(&dhd->pub); - WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_WATCHDOG); - } - /* Count the tick for reference */ - dhd->pub.tickcnt++; - - /* Reschedule the watchdog */ - if (dhd->wd_timer_valid) { - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); - } - } - else - break; - } - - WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG); - complete_and_exit(&dhd->watchdog_exited, 0); -} - -static void -dhd_watchdog(ulong data) -{ - dhd_info_t *dhd = (dhd_info_t *)data; - - if (dhd->watchdog_pid >= 0) { - up(&dhd->watchdog_sem); - return; - } - - /* Call the bus module watchdog */ - dhd_bus_watchdog(&dhd->pub); - - /* Count the tick for reference */ - dhd->pub.tickcnt++; - - /* Reschedule the watchdog */ - if (dhd->wd_timer_valid) - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); -} - -static int -dhd_dpc_thread(void *data) -{ - dhd_info_t *dhd = (dhd_info_t *)data; - - WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_DPC, "dhd_dpc_thread"); - /* This thread doesn't need any user-level access, - * so get rid of all our resources - */ -#ifdef DHD_SCHED - if (dhd_dpc_prio > 0) - { - struct sched_param param; - param.sched_priority = (dhd_dpc_prio < MAX_RT_PRIO)?dhd_dpc_prio:(MAX_RT_PRIO-1); - setScheduler(current, SCHED_FIFO, ¶m); - } -#endif /* DHD_SCHED */ - - DAEMONIZE("dhd_dpc"); - - /* Run until signal received */ - while (1) { - if (down_interruptible(&dhd->dpc_sem) == 0) { - /* Call bus dpc unless it indicated down (then clean stop) */ - if (dhd->pub.busstate != DHD_BUS_DOWN) { - WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC); - if (dhd_bus_dpc(dhd->pub.bus)) { - up(&dhd->dpc_sem); - WAKE_LOCK_TIMEOUT(&dhd->pub, WAKE_LOCK_TMOUT, 25); - } - WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_DPC); - } else { - dhd_bus_stop(dhd->pub.bus, TRUE); - } - } - else - break; - } - - WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_DPC); - - complete_and_exit(&dhd->dpc_exited, 0); -} - -static void -dhd_dpc(ulong data) -{ - dhd_info_t *dhd; - - dhd = (dhd_info_t *)data; - - /* Call bus dpc unless it indicated down (then clean stop) */ - if (dhd->pub.busstate != DHD_BUS_DOWN) { - if (dhd_bus_dpc(dhd->pub.bus)) - tasklet_schedule(&dhd->tasklet); - } else { - dhd_bus_stop(dhd->pub.bus, TRUE); - } -} - -void -dhd_sched_dpc(dhd_pub_t *dhdp) -{ - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - - if (dhd->dpc_pid >= 0) { - up(&dhd->dpc_sem); - return; - } - - tasklet_schedule(&dhd->tasklet); -} - -#ifdef TOE -/* Retrieve current toe component enables, which are kept as a bitmap in toe_ol iovar */ -static int -dhd_toe_get(dhd_info_t *dhd, int ifidx, uint32 *toe_ol) -{ - wl_ioctl_t ioc; - char buf[32]; - int ret; - - memset(&ioc, 0, sizeof(ioc)); - - ioc.cmd = WLC_GET_VAR; - ioc.buf = buf; - ioc.len = (uint)sizeof(buf); - ioc.set = FALSE; - - strcpy(buf, "toe_ol"); - if ((ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { - /* Check for older dongle image that doesn't support toe_ol */ - if (ret == -EIO) { - DHD_ERROR(("%s: toe not supported by device\n", - dhd_ifname(&dhd->pub, ifidx))); - return -EOPNOTSUPP; - } - - DHD_INFO(("%s: could not get toe_ol: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret)); - return ret; - } - - memcpy(toe_ol, buf, sizeof(uint32)); - return 0; -} - -/* Set current toe component enables in toe_ol iovar, and set toe global enable iovar */ -static int -dhd_toe_set(dhd_info_t *dhd, int ifidx, uint32 toe_ol) -{ - wl_ioctl_t ioc; - char buf[32]; - int toe, ret; - - memset(&ioc, 0, sizeof(ioc)); - - ioc.cmd = WLC_SET_VAR; - ioc.buf = buf; - ioc.len = (uint)sizeof(buf); - ioc.set = TRUE; - - /* Set toe_ol as requested */ - - strcpy(buf, "toe_ol"); - memcpy(&buf[sizeof("toe_ol")], &toe_ol, sizeof(uint32)); - - if ((ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { - DHD_ERROR(("%s: could not set toe_ol: ret=%d\n", - dhd_ifname(&dhd->pub, ifidx), ret)); - return ret; - } - - /* Enable toe globally only if any components are enabled. */ - - toe = (toe_ol != 0); - - strcpy(buf, "toe"); - memcpy(&buf[sizeof("toe")], &toe, sizeof(uint32)); - - if ((ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len)) < 0) { - DHD_ERROR(("%s: could not set toe: ret=%d\n", dhd_ifname(&dhd->pub, ifidx), ret)); - return ret; - } - - return 0; -} -#endif /* TOE */ - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) -static void dhd_ethtool_get_drvinfo(struct net_device *net, - struct ethtool_drvinfo *info) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - - sprintf(info->driver, "wl"); - sprintf(info->version, "%lu", dhd->pub.drv_version); -} - -struct ethtool_ops dhd_ethtool_ops = { - .get_drvinfo = dhd_ethtool_get_drvinfo -}; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ - - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) -static int -dhd_ethtool(dhd_info_t *dhd, void *uaddr) -{ - struct ethtool_drvinfo info; - char drvname[sizeof(info.driver)]; - uint32 cmd; -#ifdef TOE - struct ethtool_value edata; - uint32 toe_cmpnt, csum_dir; - int ret; -#endif - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* all ethtool calls start with a cmd word */ - if (copy_from_user(&cmd, uaddr, sizeof (uint32))) - return -EFAULT; - - switch (cmd) { - case ETHTOOL_GDRVINFO: - /* Copy out any request driver name */ - if (copy_from_user(&info, uaddr, sizeof(info))) - return -EFAULT; - strncpy(drvname, info.driver, sizeof(info.driver)); - drvname[sizeof(info.driver)-1] = '\0'; - - /* clear struct for return */ - memset(&info, 0, sizeof(info)); - info.cmd = cmd; - - /* if dhd requested, identify ourselves */ - if (strcmp(drvname, "?dhd") == 0) { - sprintf(info.driver, "dhd"); - strcpy(info.version, EPI_VERSION_STR); - } - - /* otherwise, require dongle to be up */ - else if (!dhd->pub.up) { - DHD_ERROR(("%s: dongle is not up\n", __FUNCTION__)); - return -ENODEV; - } - - /* finally, report dongle driver type */ - else if (dhd->pub.iswl) - sprintf(info.driver, "wl"); - else - sprintf(info.driver, "xx"); - - sprintf(info.version, "%lu", dhd->pub.drv_version); - if (copy_to_user(uaddr, &info, sizeof(info))) - return -EFAULT; - DHD_CTL(("%s: given %*s, returning %s\n", __FUNCTION__, - (int)sizeof(drvname), drvname, info.driver)); - break; - -#ifdef TOE - /* Get toe offload components from dongle */ - case ETHTOOL_GRXCSUM: - case ETHTOOL_GTXCSUM: - if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0) - return ret; - - csum_dir = (cmd == ETHTOOL_GTXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; - - edata.cmd = cmd; - edata.data = (toe_cmpnt & csum_dir) ? 1 : 0; - - if (copy_to_user(uaddr, &edata, sizeof(edata))) - return -EFAULT; - break; - - /* Set toe offload components in dongle */ - case ETHTOOL_SRXCSUM: - case ETHTOOL_STXCSUM: - if (copy_from_user(&edata, uaddr, sizeof(edata))) - return -EFAULT; - - /* Read the current settings, update and write back */ - if ((ret = dhd_toe_get(dhd, 0, &toe_cmpnt)) < 0) - return ret; - - csum_dir = (cmd == ETHTOOL_STXCSUM) ? TOE_TX_CSUM_OL : TOE_RX_CSUM_OL; - - if (edata.data != 0) - toe_cmpnt |= csum_dir; - else - toe_cmpnt &= ~csum_dir; - - if ((ret = dhd_toe_set(dhd, 0, toe_cmpnt)) < 0) - return ret; - - /* If setting TX checksum mode, tell Linux the new mode */ - if (cmd == ETHTOOL_STXCSUM) { - if (edata.data) - dhd->iflist[0]->net->features |= NETIF_F_IP_CSUM; - else - dhd->iflist[0]->net->features &= ~NETIF_F_IP_CSUM; - } - - break; -#endif /* TOE */ - - default: - return -EOPNOTSUPP; - } - - return 0; -} -#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ - -static int -dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - dhd_ioctl_t ioc; - int bcmerror = 0; - int buflen = 0; - void *buf = NULL; - uint driver = 0; - int ifidx; - bool is_set_key_cmd; - - ifidx = dhd_net2idx(dhd, net); - DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); - - if (ifidx == DHD_BAD_IF) - return -1; - -#if defined(CONFIG_WIRELESS_EXT) - /* linux wireless extensions */ - if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { - /* may recurse, do NOT lock */ - return wl_iw_ioctl(net, ifr, cmd); - } -#endif /* defined(CONFIG_WIRELESS_EXT) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) - if (cmd == SIOCETHTOOL) - return (dhd_ethtool(dhd, (void*)ifr->ifr_data)); -#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ - - if (cmd != SIOCDEVPRIVATE) - return -EOPNOTSUPP; - - memset(&ioc, 0, sizeof(ioc)); - - /* Copy the ioc control structure part of ioctl request */ - if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) { - bcmerror = -BCME_BADADDR; - goto done; - } - - /* Copy out any buffer passed */ - if (ioc.buf) { - buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN); - /* optimization for direct ioctl calls from kernel */ - /* - if (segment_eq(get_fs(), KERNEL_DS)) { - buf = ioc.buf; - } else { - */ - { - if (!(buf = (char*)MALLOC(dhd->pub.osh, buflen))) { - bcmerror = -BCME_NOMEM; - goto done; - } - if (copy_from_user(buf, ioc.buf, buflen)) { - bcmerror = -BCME_BADADDR; - goto done; - } - } - } - - /* To differentiate between wl and dhd read 4 more byes */ - if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t), - sizeof(uint)) != 0)) { - bcmerror = -BCME_BADADDR; - goto done; - } - - if (!capable(CAP_NET_ADMIN)) { - bcmerror = -BCME_EPERM; - goto done; - } - - /* check for local dhd ioctl and handle it */ - if (driver == DHD_IOCTL_MAGIC) { - bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen); - if (bcmerror) - dhd->pub.bcmerror = bcmerror; - goto done; - } - - /* send to dongle (must be up, and wl) */ - if ( - (dhd->pub.busstate != DHD_BUS_DATA)) { - DHD_ERROR(("%s DONGLE_DOWN,__FUNCTION__\n", __FUNCTION__)); - bcmerror = BCME_DONGLE_DOWN; - goto done; - } - - if (!dhd->pub.iswl) { - bcmerror = BCME_DONGLE_DOWN; - goto done; - } - - /* Intercept WLC_SET_KEY IOCTL - serialize M4 send and set key IOCTL to - * prevent M4 encryption. - */ - is_set_key_cmd = ((ioc.cmd == WLC_SET_KEY) || - ((ioc.cmd == WLC_SET_VAR) && - !(strncmp("wsec_key", ioc.buf, 9))) || - ((ioc.cmd == WLC_SET_VAR) && - !(strncmp("bsscfg:wsec_key", ioc.buf, 15)))); - if (is_set_key_cmd) { - dhd_wait_pend8021x(net); - } - WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_IOCTL, "dhd_ioctl_entry"); - WAKE_LOCK(&dhd->pub, WAKE_LOCK_IOCTL); - - bcmerror = dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); - - WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_IOCTL); - WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_IOCTL); - if (bcmerror == -ETIMEDOUT) { - DHD_ERROR(("%s: Event RELOAD send up\n", __FUNCTION__)); - wl_iw_send_priv_event(net, "RELOAD"); - } -done: - if (!bcmerror && buf && ioc.buf) { - if (copy_to_user(ioc.buf, buf, buflen)) - bcmerror = -EFAULT; - } - - if (buf) - MFREE(dhd->pub.osh, buf, buflen); - - return OSL_ERROR(bcmerror); -} - -static int -dhd_stop(struct net_device *net) -{ -#if !defined(IGNORE_ETH0_DOWN) - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - if (dhd->pub.up == 0) { - return 0; - } - - /* Set state and stop OS transmissions */ - dhd->pub.up = 0; - netif_stop_queue(net); -#else - DHD_ERROR(("BYPASS %s:due to BRCM compilation : under investigation ...\n", __FUNCTION__)); -#endif /* !defined(IGNORE_ETH0_DOWN) */ - - OLD_MOD_DEC_USE_COUNT; - return 0; -} - -static int -dhd_open(struct net_device *net) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); -#ifdef TOE - uint32 toe_ol; -#endif - int ifidx = dhd_net2idx(dhd, net); - int32 ret = 0; - - DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); - - /* Force start if ifconfig_up gets called before START command */ - wl_control_wl_start(net); - - if (ifidx == 0) { /* do it only for primary eth0 */ - - atomic_set(&dhd->pend_8021x_cnt, 0); - - memcpy(net->dev_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); - -#ifdef TOE - /* Get current TOE mode from dongle */ - if (dhd_toe_get(dhd, ifidx, &toe_ol) >= 0 && (toe_ol & TOE_TX_CSUM_OL) != 0) - dhd->iflist[ifidx]->net->features |= NETIF_F_IP_CSUM; - else - dhd->iflist[ifidx]->net->features &= ~NETIF_F_IP_CSUM; -#endif - } - /* Allow transmit calls */ - netif_start_queue(net); - dhd->pub.up = 1; - - - OLD_MOD_INC_USE_COUNT; - return ret; -} - -osl_t * -dhd_osl_attach(void *pdev, uint bustype) -{ - return osl_attach(pdev, bustype, TRUE); -} - -void -dhd_osl_detach(osl_t *osh) -{ - if (MALLOCED(osh)) { - DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh))); - } - osl_detach(osh); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - up(&dhd_registration_sem); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ -} - -int -dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, - uint8 *mac_addr, uint32 flags, uint8 bssidx) -{ - dhd_if_t *ifp; - - DHD_TRACE(("%s: idx %d, handle->%p\n", __FUNCTION__, ifidx, handle)); - - ASSERT(dhd && (ifidx < DHD_MAX_IFS)); - - ifp = dhd->iflist[ifidx]; - if (!ifp && !(ifp = MALLOC(dhd->pub.osh, sizeof(dhd_if_t)))) { - DHD_ERROR(("%s: OOM - dhd_if_t\n", __FUNCTION__)); - return -ENOMEM; - } - - memset(ifp, 0, sizeof(dhd_if_t)); - ifp->info = dhd; - dhd->iflist[ifidx] = ifp; - strncpy(ifp->name, name, IFNAMSIZ); - ifp->name[IFNAMSIZ] = '\0'; - if (mac_addr != NULL) - memcpy(&ifp->mac_addr, mac_addr, ETHER_ADDR_LEN); - - if (handle == NULL) { - ifp->state = WLC_E_IF_ADD; - ifp->idx = ifidx; - ASSERT(dhd->sysioc_pid >= 0); - up(&dhd->sysioc_sem); - } else - ifp->net = (struct net_device *)handle; - - return 0; -} - -void -dhd_del_if(dhd_info_t *dhd, int ifidx) -{ - dhd_if_t *ifp; - - DHD_TRACE(("%s: idx %d\n", __FUNCTION__, ifidx)); - - ASSERT(dhd && ifidx && (ifidx < DHD_MAX_IFS)); - ifp = dhd->iflist[ifidx]; - if (!ifp) { - DHD_ERROR(("%s: Null interface\n", __FUNCTION__)); - return; - } - - ifp->state = WLC_E_IF_DEL; - ifp->idx = ifidx; - ASSERT(dhd->sysioc_pid >= 0); - up(&dhd->sysioc_sem); -} - -dhd_pub_t * -dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) -{ - dhd_info_t *dhd = NULL; - struct net_device *net; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - /* updates firmware nvram path if it was provided as module paramters */ - if ((firmware_path != NULL) && (firmware_path[0] != '\0')) - strcpy(fw_path, firmware_path); - if ((nvram_path != NULL) && (nvram_path[0] != '\0')) - strcpy(nv_path, nvram_path); - - /* Allocate etherdev, including space for private structure */ - if (!(net = alloc_etherdev(sizeof(dhd)))) { - DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); - goto fail; - } - - /* Allocate primary dhd_info */ - if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { - DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__)); - goto fail; - } - - memset(dhd, 0, sizeof(dhd_info_t)); - - /* - * Save the dhd_info into the priv - */ - memcpy(netdev_priv(net), &dhd, sizeof(dhd)); - dhd->pub.osh = osh; - - /* Set network interface name if it was provided as module parameter */ - if (iface_name[0]) { - int len; - char ch; - strncpy(net->name, iface_name, IFNAMSIZ); - net->name[IFNAMSIZ - 1] = 0; - len = strlen(net->name); - ch = net->name[len - 1]; - if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2)) - strcat(net->name, "%d"); - } - - /* we rename the netdevice interface name wlan0 */ - dev_alloc_name(net, "wlan%d"); - - if (dhd_add_if(dhd, 0, (void *)net, net->name, NULL, 0, 0) == DHD_BAD_IF) - goto fail; - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) - net->open = NULL; -#else - net->netdev_ops = NULL; -#endif - init_MUTEX(&dhd->proto_sem); - /* Initialize other structure content */ - init_waitqueue_head(&dhd->ioctl_resp_wait); - init_waitqueue_head(&dhd->ctrl_wait); - - /* Initialize the spinlocks */ - spin_lock_init(&dhd->sdlock); - spin_lock_init(&dhd->txqlock); - - /* Link to info module */ - dhd->pub.info = dhd; - - /* Link to bus module */ - dhd->pub.bus = bus; - dhd->pub.hdrlen = bus_hdrlen; - - /* Attach and link in the protocol */ - if (dhd_prot_attach(&dhd->pub) != 0) { - DHD_ERROR(("dhd_prot_attach failed\n")); - goto fail; - } -#if defined(CONFIG_WIRELESS_EXT) - /* Attach and link in the iw */ - if (wl_iw_attach(net, (void *)&dhd->pub) != 0) { - DHD_ERROR(("wl_iw_attach failed\n")); - goto fail; - } -#endif /* defined(CONFIG_WIRELESS_EXT) */ - - - /* Set up the watchdog timer */ - init_timer(&dhd->timer); - dhd->timer.data = (ulong)dhd; - dhd->timer.function = dhd_watchdog; - - /* Initialize thread based operation and lock */ - init_MUTEX(&dhd->sdsem); - if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0)) { - dhd->threads_only = TRUE; - } - else { - dhd->threads_only = FALSE; - } - - if (dhd_dpc_prio >= 0) { - /* Initialize watchdog thread */ - sema_init(&dhd->watchdog_sem, 0); - init_completion(&dhd->watchdog_exited); - dhd->watchdog_pid = kernel_thread(dhd_watchdog_thread, dhd, 0); - } else { - dhd->watchdog_pid = -1; - } - - /* Set up the bottom half handler */ - if (dhd_dpc_prio >= 0) { - /* Initialize DPC thread */ - sema_init(&dhd->dpc_sem, 0); - init_completion(&dhd->dpc_exited); - dhd->dpc_pid = kernel_thread(dhd_dpc_thread, dhd, 0); - } else { - tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); - dhd->dpc_pid = -1; - } - - if (dhd_sysioc) { - sema_init(&dhd->sysioc_sem, 0); - init_completion(&dhd->sysioc_exited); - dhd->sysioc_pid = kernel_thread(_dhd_sysioc_thread, dhd, 0); - } else { - dhd->sysioc_pid = -1; - } - - /* - * Save the dhd_info into the priv - */ - memcpy(netdev_priv(net), &dhd, sizeof(dhd)); - -#if defined(CONFIG_WIFI_CONTROL_FUNC) - g_bus = bus; -#endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) && 1 - register_pm_notifier(&dhd_sleep_pm_notifier); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ - /* && defined(DHD_GPL) */ - /* Init lock suspend to prevent kernel going to suspend */ - WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_TMOUT, "dhd_wake_lock"); - WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_LINK_DOWN_TMOUT, "dhd_wake_lock_link_dw_event"); - -#ifdef CONFIG_HAS_EARLYSUSPEND - dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20; - dhd->early_suspend.suspend = dhd_early_suspend; - dhd->early_suspend.resume = dhd_late_resume; - register_early_suspend(&dhd->early_suspend); -#endif - - return &dhd->pub; - -fail: - if (net) - free_netdev(net); - if (dhd) - dhd_detach(&dhd->pub); - - return NULL; -} - - -int -dhd_bus_start(dhd_pub_t *dhdp) -{ - int ret = -1; - dhd_info_t *dhd = (dhd_info_t*)dhdp->info; -#ifdef EMBEDDED_PLATFORM - char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ -#endif /* EMBEDDED_PLATFORM */ - - ASSERT(dhd); - - DHD_TRACE(("%s: \n", __FUNCTION__)); - - /* try to download image and nvram to the dongle */ - if (dhd->pub.busstate == DHD_BUS_DOWN) { - WAKE_LOCK_INIT(dhdp, WAKE_LOCK_DOWNLOAD, "dhd_bus_start"); - WAKE_LOCK(dhdp, WAKE_LOCK_DOWNLOAD); - if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, - fw_path, nv_path))) { - DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n", - __FUNCTION__, fw_path, nv_path)); - WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD); - WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD); - return -1; - } - - WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD); - WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD); - } - - /* Start the watchdog timer */ - dhd->pub.tickcnt = 0; - dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); - - /* Bring up the bus */ - if ((ret = dhd_bus_init(&dhd->pub, TRUE)) != 0) { - DHD_ERROR(("%s, dhd_bus_init failed %d\n", __FUNCTION__, ret)); - return ret; - } -#if defined(OOB_INTR_ONLY) - /* Host registration for OOB interrupt */ - if (bcmsdh_register_oob_intr(dhdp)) { - del_timer(&dhd->timer); - dhd->wd_timer_valid = FALSE; - DHD_ERROR(("%s Host failed to resgister for OOB\n", __FUNCTION__)); - return -ENODEV; - } - - /* Enable oob at firmware */ - dhd_enable_oob_intr(dhd->pub.bus, TRUE); -#endif /* defined(OOB_INTR_ONLY) */ - - /* If bus is not ready, can't come up */ - if (dhd->pub.busstate != DHD_BUS_DATA) { - del_timer(&dhd->timer); - dhd->wd_timer_valid = FALSE; - DHD_ERROR(("%s failed bus is not ready\n", __FUNCTION__)); - return -ENODEV; - } - -#ifdef EMBEDDED_PLATFORM - bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); - dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf)); - bcopy(iovbuf, dhdp->eventmask, WL_EVENTING_MASK_LEN); - - setbit(dhdp->eventmask, WLC_E_SET_SSID); - setbit(dhdp->eventmask, WLC_E_PRUNE); - setbit(dhdp->eventmask, WLC_E_AUTH); - setbit(dhdp->eventmask, WLC_E_REASSOC); - setbit(dhdp->eventmask, WLC_E_REASSOC_IND); - setbit(dhdp->eventmask, WLC_E_DEAUTH_IND); - setbit(dhdp->eventmask, WLC_E_DISASSOC_IND); - setbit(dhdp->eventmask, WLC_E_DISASSOC); - setbit(dhdp->eventmask, WLC_E_JOIN); - setbit(dhdp->eventmask, WLC_E_ASSOC_IND); - setbit(dhdp->eventmask, WLC_E_PSK_SUP); - setbit(dhdp->eventmask, WLC_E_LINK); - setbit(dhdp->eventmask, WLC_E_NDIS_LINK); - setbit(dhdp->eventmask, WLC_E_MIC_ERROR); - setbit(dhdp->eventmask, WLC_E_PMKID_CACHE); - setbit(dhdp->eventmask, WLC_E_TXFAIL); - setbit(dhdp->eventmask, WLC_E_JOIN_START); - setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE); - - dhdp->pktfilter_count = 1; - /* Setup filter to allow only unicast */ - dhdp->pktfilter[0] = "100 0 0 0 0x01 0x00"; -#endif /* EMBEDDED_PLATFORM */ - - /* Bus is ready, do any protocol initialization */ - if ((ret = dhd_prot_init(&dhd->pub)) < 0) - return ret; - - return 0; -} - -int -dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, int set) -{ - char buf[strlen(name) + 1 + cmd_len]; - int len = sizeof(buf); - wl_ioctl_t ioc; - int ret; - - len = bcm_mkiovar(name, cmd_buf, cmd_len, buf, len); - - memset(&ioc, 0, sizeof(ioc)); - - ioc.cmd = set? WLC_SET_VAR : WLC_GET_VAR; - ioc.buf = buf; - ioc.len = len; - ioc.set = set; - - ret = dhd_prot_ioctl(pub, ifidx, &ioc, ioc.buf, ioc.len); - if (!set && ret >= 0) - memcpy(cmd_buf, buf, cmd_len); - - return ret; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) -static struct net_device_ops dhd_ops_pri = { - .ndo_open = dhd_open, - .ndo_stop = dhd_stop, - .ndo_get_stats = dhd_get_stats, - .ndo_do_ioctl = dhd_ioctl_entry, - .ndo_start_xmit = dhd_start_xmit, - .ndo_set_mac_address = dhd_set_mac_address, - .ndo_set_multicast_list = dhd_set_multicast_list -}; - -static struct net_device_ops dhd_ops_virt = { - .ndo_get_stats = dhd_get_stats, - .ndo_do_ioctl = dhd_ioctl_entry, - .ndo_start_xmit = dhd_start_xmit, - .ndo_set_mac_address = dhd_set_mac_address, - .ndo_set_multicast_list = dhd_set_multicast_list -}; -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) */ -int -dhd_net_attach(dhd_pub_t *dhdp, int ifidx) -{ - dhd_info_t *dhd = (dhd_info_t *)dhdp->info; - struct net_device *net; - uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 }; - - DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); - - ASSERT(dhd && dhd->iflist[ifidx]); - - net = dhd->iflist[ifidx]->net; - ASSERT(net); - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) - ASSERT(!net->open); - net->get_stats = dhd_get_stats; - net->do_ioctl = dhd_ioctl_entry; - net->hard_start_xmit = dhd_start_xmit; - net->set_mac_address = dhd_set_mac_address; - net->set_multicast_list = dhd_set_multicast_list; - net->open = net->stop = NULL; -#else - ASSERT(!net->netdev_ops); - net->netdev_ops = &dhd_ops_virt; -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) - net->open = dhd_open; - net->stop = dhd_stop; -#else - net->netdev_ops = &dhd_ops_pri; -#endif - - /* - * We have to use the primary MAC for virtual interfaces - */ - if (ifidx != 0) { - /* for virtual interfaces use the primary MAC */ - memcpy(temp_addr, dhd->pub.mac.octet, ETHER_ADDR_LEN); - - } - - if (ifidx == 1) { - DHD_TRACE(("%s ACCESS POINT MAC: \n", __FUNCTION__)); - /* ACCESSPOINT INTERFACE CASE */ - temp_addr[0] |= 0X02; /* set bit 2 , - Locally Administered address */ - - } - net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) - net->ethtool_ops = &dhd_ethtool_ops; -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */ - -#if defined(CONFIG_WIRELESS_EXT) -#if WIRELESS_EXT < 19 - net->get_wireless_stats = dhd_get_wireless_stats; -#endif /* WIRELESS_EXT < 19 */ -#if WIRELESS_EXT > 12 - net->wireless_handlers = (struct iw_handler_def *)&wl_iw_handler_def; -#endif /* WIRELESS_EXT > 12 */ -#endif /* defined(CONFIG_WIRELESS_EXT) */ - - - dhd->pub.rxsz = net->mtu + net->hard_header_len + dhd->pub.hdrlen; - - memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); - - if (register_netdev(net) != 0) { - DHD_ERROR(("%s: couldn't register the net device\n", __FUNCTION__)); - goto fail; - } - - printf("%s: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n", net->name, - dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2], - dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]); - -#if defined(CONFIG_WIRELESS_EXT) && !defined(CSCAN) -#ifdef SOFTAP - if (ifidx == 0) - /* Don't call for SOFTAP Interface in SOFTAP MODE */ - wl_iw_iscan_set_scan_broadcast_prep(net, 1); -#else - wl_iw_iscan_set_scan_broadcast_prep(net, 1); -#endif /* SOFTAP */ -#endif /* CONFIG_WIRELESS_EXT */ - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - up(&dhd_registration_sem); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ - return 0; - -fail: -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - net->open = NULL; -#else - net->netdev_ops = NULL; -#endif - return BCME_ERROR; -} - -void -dhd_bus_detach(dhd_pub_t *dhdp) -{ - dhd_info_t *dhd; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (dhdp) { - dhd = (dhd_info_t *)dhdp->info; - if (dhd) { - /* Stop the protocol module */ - dhd_prot_stop(&dhd->pub); - - /* Stop the bus module */ - dhd_bus_stop(dhd->pub.bus, TRUE); -#if defined(OOB_INTR_ONLY) - bcmsdh_unregister_oob_intr(); -#endif /* defined(OOB_INTR_ONLY) */ - - /* Clear the watchdog timer */ - del_timer(&dhd->timer); - dhd->wd_timer_valid = FALSE; - } - } -} - -void -dhd_detach(dhd_pub_t *dhdp) -{ - dhd_info_t *dhd; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (dhdp) { - dhd = (dhd_info_t *)dhdp->info; - if (dhd) { - dhd_if_t *ifp; - int i; - -#if defined(CONFIG_HAS_EARLYSUSPEND) - unregister_early_suspend(&dhd->early_suspend); -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ - - for (i = 1; i < DHD_MAX_IFS; i++) - if (dhd->iflist[i]) - dhd_del_if(dhd, i); - - ifp = dhd->iflist[0]; - ASSERT(ifp); -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)) - if (ifp->net->open) { -#else - if (ifp->net->netdev_ops == &dhd_ops_pri) { -#endif - dhd_stop(ifp->net); - unregister_netdev(ifp->net); - } - - - if (dhd->watchdog_pid >= 0) - { - KILL_PROC(dhd->watchdog_pid, SIGTERM); - wait_for_completion(&dhd->watchdog_exited); - } - - if (dhd->dpc_pid >= 0) - { - KILL_PROC(dhd->dpc_pid, SIGTERM); - wait_for_completion(&dhd->dpc_exited); - } - else - tasklet_kill(&dhd->tasklet); - - if (dhd->sysioc_pid >= 0) { - KILL_PROC(dhd->sysioc_pid, SIGTERM); - wait_for_completion(&dhd->sysioc_exited); - } - - dhd_bus_detach(dhdp); - - if (dhdp->prot) - dhd_prot_detach(dhdp); - -#if defined(CONFIG_WIRELESS_EXT) - /* Attach and link in the iw */ - wl_iw_detach(); -#endif - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) && 1 - unregister_pm_notifier(&dhd_sleep_pm_notifier); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ - /* && defined(DHD_GPL) */ - WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT); - WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT); - free_netdev(ifp->net); - MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); - MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); - } -} -} -static void __exit -dhd_module_cleanup(void) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - dhd_bus_unregister(); -#if defined(CONFIG_WIFI_CONTROL_FUNC) - wifi_del_dev(); -#endif - /* Call customer gpio to turn off power with WL_REG_ON signal */ - dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); -} - - -static int __init -dhd_module_init(void) -{ - int error; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Sanity check on the module parameters */ - do { - /* Both watchdog and DPC as tasklets are ok */ - if ((dhd_watchdog_prio < 0) && (dhd_dpc_prio < 0)) - break; - - /* If both watchdog and DPC are threads, TX must be deferred */ - if ((dhd_watchdog_prio >= 0) && (dhd_dpc_prio >= 0) && dhd_deferred_tx) - break; - - DHD_ERROR(("Invalid module parameters.\n")); - return -EINVAL; - } while (0); - /* Call customer gpio to turn on power with WL_REG_ON signal */ - dhd_customer_gpio_wlan_ctrl(WLAN_POWER_ON); - -#if defined(CONFIG_WIFI_CONTROL_FUNC) - sema_init(&wifi_control_sem, 0); - - error = wifi_add_dev(); - if (error) { - DHD_ERROR(("%s: platform_driver_register failed\n", __FUNCTION__)); - goto faild; - } - - /* Waiting callback after platform_driver_register is done or exit with error */ - if (down_timeout(&wifi_control_sem, msecs_to_jiffies(1000)) != 0) { - printk("%s: platform_driver_register timeout\n", __FUNCTION__); - /* renove device */ - wifi_del_dev(); - goto faild; - } -#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - sema_init(&dhd_registration_sem, 0); -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ - - error = dhd_bus_register(); - - if (!error) - printf("\n%s\n", dhd_version); - else { - DHD_ERROR(("%s: sdio_register_driver failed\n", __FUNCTION__)); - goto faild; - } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - /* - * Wait till MMC sdio_register_driver callback called and made driver attach. - * It's needed to make sync up exit from dhd insmod and - * Kernel MMC sdio device callback registration - */ - if (down_timeout(&dhd_registration_sem, msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT)) != 0) { - error = -EINVAL; - DHD_ERROR(("%s: sdio_register_driver timeout\n", __FUNCTION__)); - dhd_bus_unregister(); - } -#endif - return error; - -faild: - /* turn off power and exit */ - dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF); - return -EINVAL; -} - -module_init(dhd_module_init); -module_exit(dhd_module_cleanup); - -/* - * OS specific functions required to implement DHD driver in OS independent way - */ -int -dhd_os_proto_block(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - if (dhd) { - down(&dhd->proto_sem); - return 1; - } - return 0; -} - -int -dhd_os_proto_unblock(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - if (dhd) { - up(&dhd->proto_sem); - return 1; - } - - return 0; -} - -unsigned int -dhd_os_get_ioctl_resp_timeout(void) -{ - return ((unsigned int)dhd_ioctl_timeout_msec); -} - -void -dhd_os_set_ioctl_resp_timeout(unsigned int timeout_msec) -{ - dhd_ioctl_timeout_msec = (int)timeout_msec; -} - -int -dhd_os_ioctl_resp_wait(dhd_pub_t *pub, uint *condition, bool *pending) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - DECLARE_WAITQUEUE(wait, current); - int timeout = dhd_ioctl_timeout_msec; - - /* Convert timeout in millsecond to jiffies */ - timeout = timeout * HZ / 1000; - - /* Wait until control frame is available */ - add_wait_queue(&dhd->ioctl_resp_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - while (!(*condition) && (!signal_pending(current) && timeout)) - timeout = schedule_timeout(timeout); - - if (signal_pending(current)) - *pending = TRUE; - - set_current_state(TASK_RUNNING); - remove_wait_queue(&dhd->ioctl_resp_wait, &wait); - - return timeout; -} - -int -dhd_os_ioctl_resp_wake(dhd_pub_t *pub) -{ - dhd_info_t *dhd = (dhd_info_t *)(pub->info); - - if (waitqueue_active(&dhd->ioctl_resp_wait)) { - wake_up_interruptible(&dhd->ioctl_resp_wait); - } - - return 0; -} - -void -dhd_os_wd_timer(void *bus, uint wdtick) -{ - dhd_pub_t *pub = bus; - static uint save_dhd_watchdog_ms = 0; - dhd_info_t *dhd = (dhd_info_t *)pub->info; - - /* don't start the wd until fw is loaded */ - if (pub->busstate == DHD_BUS_DOWN) - return; - - /* Totally stop the timer */ - if (!wdtick && dhd->wd_timer_valid == TRUE) { - del_timer(&dhd->timer); - dhd->wd_timer_valid = FALSE; - save_dhd_watchdog_ms = wdtick; - return; - } - - if (wdtick) { - dhd_watchdog_ms = (uint) wdtick; - if (save_dhd_watchdog_ms != dhd_watchdog_ms) { - - if (dhd->wd_timer_valid == TRUE) - /* Stop timer and restart at new value */ - del_timer(&dhd->timer); - - /* Create timer again when watchdog period is - dynamically changed or in the first instance - */ - dhd->timer.expires = jiffies + dhd_watchdog_ms * HZ / 1000; - add_timer(&dhd->timer); - } else { - /* Re arm the timer, at last watchdog period */ - mod_timer(&dhd->timer, jiffies + dhd_watchdog_ms * HZ / 1000); - } - - dhd->wd_timer_valid = TRUE; - save_dhd_watchdog_ms = wdtick; - } -} - -void * -dhd_os_open_image(char *filename) -{ - struct file *fp; - - - fp = filp_open(filename, O_RDONLY, 0); - /* - * 2.6.11 (FC4) supports filp_open() but later revs don't? - * Alternative: - * fp = open_namei(AT_FDCWD, filename, O_RD, 0); - * ??? - */ - if (IS_ERR(fp)) - fp = NULL; - - return fp; -} - -int -dhd_os_get_image_block(char *buf, int len, void *image) -{ - struct file *fp = (struct file *)image; - int rdlen; - - - if (!image) - return 0; - - rdlen = kernel_read(fp, fp->f_pos, buf, len); - if (rdlen > 0) - fp->f_pos += rdlen; - - return rdlen; -} - -void -dhd_os_close_image(void *image) -{ - if (image) - filp_close((struct file *)image, NULL); -} - - -void -dhd_os_sdlock(dhd_pub_t *pub) -{ - dhd_info_t *dhd; - - dhd = (dhd_info_t *)(pub->info); - - if (dhd->threads_only) - down(&dhd->sdsem); - else - spin_lock_bh(&dhd->sdlock); -} - -void -dhd_os_sdunlock(dhd_pub_t *pub) -{ - dhd_info_t *dhd; - - dhd = (dhd_info_t *)(pub->info); - - if (dhd->threads_only) - up(&dhd->sdsem); - else - spin_unlock_bh(&dhd->sdlock); -} - -void -dhd_os_sdlock_txq(dhd_pub_t *pub) -{ - dhd_info_t *dhd; - - dhd = (dhd_info_t *)(pub->info); - spin_lock_bh(&dhd->txqlock); -} - -void -dhd_os_sdunlock_txq(dhd_pub_t *pub) -{ - dhd_info_t *dhd; - - dhd = (dhd_info_t *)(pub->info); - spin_unlock_bh(&dhd->txqlock); -} -void -dhd_os_sdlock_rxq(dhd_pub_t *pub) -{ -} -void -dhd_os_sdunlock_rxq(dhd_pub_t *pub) -{ -} - -void -dhd_os_sdtxlock(dhd_pub_t *pub) -{ - dhd_os_sdlock(pub); -} - -void -dhd_os_sdtxunlock(dhd_pub_t *pub) -{ - dhd_os_sdunlock(pub); -} - -#ifdef DHD_USE_STATIC_BUF -void * dhd_os_prealloc(int section, unsigned long size) -{ -#if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) - void *alloc_ptr = NULL; - if (wifi_control_data && wifi_control_data->mem_prealloc) - { - alloc_ptr = wifi_control_data->mem_prealloc(section, size); - if (alloc_ptr) - { - DHD_INFO(("success alloc section %d\n", section)); - bzero(alloc_ptr, size); - return alloc_ptr; - } - } - - DHD_ERROR(("can't alloc section %d\n", section)); - return 0; -#else -return MALLOC(0, size); -#endif /* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */ -} -#endif /* DHD_USE_STATIC_BUF */ -#if defined(CONFIG_WIRELESS_EXT) -struct iw_statistics * -dhd_get_wireless_stats(struct net_device *dev) -{ - int res = 0; - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - - res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats); - - if (res == 0) - return &dhd->iw.wstats; - else - return NULL; -} -#endif /* defined(CONFIG_WIRELESS_EXT) */ - -static int -dhd_wl_host_event(dhd_info_t *dhd, int *ifidx, void *pktdata, - wl_event_msg_t *event, void **data) -{ - int bcmerror = 0; - - ASSERT(dhd != NULL); - - bcmerror = wl_host_event(dhd, ifidx, pktdata, event, data); - if (bcmerror != BCME_OK) - return (bcmerror); - -#if defined(CONFIG_WIRELESS_EXT) - ASSERT(dhd->iflist[*ifidx] != NULL); - ASSERT(dhd->iflist[*ifidx]->net != NULL); - - if (dhd->iflist[*ifidx]->net) - wl_iw_event(dhd->iflist[*ifidx]->net, event, *data); -#endif /* defined(CONFIG_WIRELESS_EXT) */ - - - return (bcmerror); -} - -/* send up locally generated event */ -void -dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data) -{ - switch (ntoh32(event->event_type)) { - default: - break; - } -} - -void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) -{ -#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) - struct dhd_info *dhdinfo = dhd->info; - dhd_os_sdunlock(dhd); - wait_event_interruptible_timeout(dhdinfo->ctrl_wait, (*lockvar == FALSE), HZ * 2); - dhd_os_sdlock(dhd); -#endif - return; -} - -void dhd_wait_event_wakeup(dhd_pub_t *dhd) -{ -#if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) - struct dhd_info *dhdinfo = dhd->info; - if (waitqueue_active(&dhdinfo->ctrl_wait)) - wake_up_interruptible(&dhdinfo->ctrl_wait); -#endif - return; -} -int -dhd_dev_reset(struct net_device *dev, uint8 flag) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - - /* Turning off watchdog */ - if (flag) - dhd_os_wd_timer(&dhd->pub, 0); - - dhd_bus_devreset(&dhd->pub, flag); - - /* Turning on watchdog back */ - if (!flag) - dhd_os_wd_timer(&dhd->pub, dhd_watchdog_ms); - DHD_ERROR(("%s: WLAN OFF DONE\n", __FUNCTION__)); - - return 1; -} - -void -dhd_dev_init_ioctl(struct net_device *dev) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - - dhd_preinit_ioctls(&dhd->pub); -} - -static int -dhd_get_pend_8021x_cnt(dhd_info_t *dhd) -{ - return (atomic_read(&dhd->pend_8021x_cnt)); -} - -#define MAX_WAIT_FOR_8021X_TX 10 - -int -dhd_wait_pend8021x(struct net_device *dev) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int timeout = 10 * HZ / 1000; - int ntimes = MAX_WAIT_FOR_8021X_TX; - int pend = dhd_get_pend_8021x_cnt(dhd); - - while (ntimes && pend) { - if (pend) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(timeout); - set_current_state(TASK_RUNNING); - ntimes--; - } - pend = dhd_get_pend_8021x_cnt(dhd); - } - return pend; -} - -#ifdef DHD_DEBUG -int -write_to_file(dhd_pub_t *dhd, uint8 *buf, int size) -{ - int ret = 0; - struct file *fp; - mm_segment_t old_fs; - loff_t pos = 0; - - /* change to KERNEL_DS address limit */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - - /* open file to write */ - fp = filp_open("/tmp/mem_dump", O_WRONLY|O_CREAT, 0640); - if (!fp) { - printf("%s: open file error\n", __FUNCTION__); - ret = -1; - goto exit; - } - - /* Write buf to file */ - fp->f_op->write(fp, buf, size, &pos); - -exit: - /* free buf before return */ - MFREE(dhd->osh, buf, size); - /* close file before return */ - if (fp) - filp_close(fp, current->files); - /* restore previous address limit */ - set_fs(old_fs); - - return ret; -} -#endif /* DHD_DEBUG */ diff --git a/drivers/net/wireless/bcm4329/dhd_linux_sched.c b/drivers/net/wireless/bcm4329/dhd_linux_sched.c deleted file mode 100644 index 480b416657ee..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_linux_sched.c +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Expose some of the kernel scheduler routines - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_linux_sched.c,v 1.1.34.1.6.1 2009/01/16 01:17:40 Exp $ - */ -#include -#include -#include -#include - -int setScheduler(struct task_struct *p, int policy, struct sched_param *param) -{ - int rc = 0; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) - rc = sched_setscheduler(p, policy, param); -#endif /* LinuxVer */ - return rc; -} diff --git a/drivers/net/wireless/bcm4329/dhd_proto.h b/drivers/net/wireless/bcm4329/dhd_proto.h deleted file mode 100644 index 382785a1ff6b..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_proto.h +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Header file describing the internal (inter-module) DHD interfaces. - * - * Provides type definitions and function prototypes used to link the - * DHD OS, bus, and protocol modules. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_proto.h,v 1.2.82.1.4.1.16.7 2010/05/10 12:54:59 Exp $ - */ - -#ifndef _dhd_proto_h_ -#define _dhd_proto_h_ - -#include -#include - -#ifndef IOCTL_RESP_TIMEOUT -#define IOCTL_RESP_TIMEOUT 2000 /* In milli second */ -#endif - -#ifndef IOCTL_CHIP_ACTIVE_TIMEOUT -#define IOCTL_CHIP_ACTIVE_TIMEOUT 10 /* In milli second */ -#endif - -/* - * Exported from the dhd protocol module (dhd_cdc, dhd_rndis) - */ - -/* Linkage, sets prot link and updates hdrlen in pub */ -extern int dhd_prot_attach(dhd_pub_t *dhdp); - -/* Unlink, frees allocated protocol memory (including dhd_prot) */ -extern void dhd_prot_detach(dhd_pub_t *dhdp); - -/* Initialize protocol: sync w/dongle state. - * Sets dongle media info (iswl, drv_version, mac address). - */ -extern int dhd_prot_init(dhd_pub_t *dhdp); - -/* Stop protocol: sync w/dongle state. */ -extern void dhd_prot_stop(dhd_pub_t *dhdp); - -extern bool dhd_proto_fcinfo(dhd_pub_t *dhd, void *pktbuf, uint8 *fcbits); - -/* Add any protocol-specific data header. - * Caller must reserve prot_hdrlen prepend space. - */ -extern void dhd_prot_hdrpush(dhd_pub_t *, int ifidx, void *txp); - -/* Remove any protocol-specific data header. */ -extern int dhd_prot_hdrpull(dhd_pub_t *, int *ifidx, void *rxp); - -/* Use protocol to issue ioctl to dongle */ -extern int dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len); - -/* Check for and handle local prot-specific iovar commands */ -extern int dhd_prot_iovar_op(dhd_pub_t *dhdp, const char *name, - void *params, int plen, void *arg, int len, bool set); - -/* Add prot dump output to a buffer */ -extern void dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf); - -/* Update local copy of dongle statistics */ -extern void dhd_prot_dstats(dhd_pub_t *dhdp); - -extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen); - -extern int dhd_preinit_ioctls(dhd_pub_t *dhd); - -/******************************** - * For version-string expansion * - */ -#if defined(BDC) -#define DHD_PROTOCOL "bdc" -#elif defined(CDC) -#define DHD_PROTOCOL "cdc" -#elif defined(RNDIS) -#define DHD_PROTOCOL "rndis" -#else -#define DHD_PROTOCOL "unknown" -#endif /* proto */ - -#endif /* _dhd_proto_h_ */ diff --git a/drivers/net/wireless/bcm4329/dhd_sdio.c b/drivers/net/wireless/bcm4329/dhd_sdio.c deleted file mode 100644 index 127260a5ae92..000000000000 --- a/drivers/net/wireless/bcm4329/dhd_sdio.c +++ /dev/null @@ -1,5866 +0,0 @@ -/* - * DHD Bus Module for SDIO - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhd_sdio.c,v 1.157.2.27.2.33.2.126 2010/06/15 23:38:39 Exp $ - */ - -#include -#include -#include - -#ifdef BCMEMBEDIMAGE -#include BCMEMBEDIMAGE -#endif /* BCMEMBEDIMAGE */ - -#include -#include -#include -#include - -#include -#include -#include -#ifdef DHD_DEBUG -#include -#include -#endif /* DHD_DEBUG */ -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#ifndef DHDSDIO_MEM_DUMP_FNAME -#define DHDSDIO_MEM_DUMP_FNAME "mem_dump" -#endif - -#define QLEN 256 /* bulk rx and tx queue lengths */ -#define FCHI (QLEN - 10) -#define FCLOW (FCHI / 2) -#define PRIOMASK 7 - -#define TXRETRIES 2 /* # of retries for tx frames */ - -#if defined(CONFIG_MACH_SANDGATE2G) -#define DHD_RXBOUND 250 /* Default for max rx frames in one scheduling */ -#else -#define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ -#endif /* defined(CONFIG_MACH_SANDGATE2G) */ - -#define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ - -#define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ - -#define MEMBLOCK 2048 /* Block size used for downloading of dongle image */ -#define MAX_DATA_BUF (32 * 1024) /* Must be large enough to hold biggest possible glom */ - -/* Packet alignment for most efficient SDIO (can change based on platform) */ -#ifndef DHD_SDALIGN -#define DHD_SDALIGN 32 -#endif -#if !ISPOWEROF2(DHD_SDALIGN) -#error DHD_SDALIGN is not a power of 2! -#endif - -#ifndef DHD_FIRSTREAD -#define DHD_FIRSTREAD 32 -#endif -#if !ISPOWEROF2(DHD_FIRSTREAD) -#error DHD_FIRSTREAD is not a power of 2! -#endif - -/* Total length of frame header for dongle protocol */ -#define SDPCM_HDRLEN (SDPCM_FRAMETAG_LEN + SDPCM_SWHEADER_LEN) -#ifdef SDTEST -#define SDPCM_RESERVE (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN) -#else -#define SDPCM_RESERVE (SDPCM_HDRLEN + DHD_SDALIGN) -#endif - -/* Space for header read, limit for data packets */ -#ifndef MAX_HDR_READ -#define MAX_HDR_READ 32 -#endif -#if !ISPOWEROF2(MAX_HDR_READ) -#error MAX_HDR_READ is not a power of 2! -#endif - -#define MAX_RX_DATASZ 2048 - -/* Maximum milliseconds to wait for F2 to come up */ -#define DHD_WAIT_F2RDY 3000 - -/* Bump up limit on waiting for HT to account for first startup; - * if the image is doing a CRC calculation before programming the PMU - * for HT availability, it could take a couple hundred ms more, so - * max out at a half second (500000us). - */ -#if (PMU_MAX_TRANSITION_DLY <= 500000) -#undef PMU_MAX_TRANSITION_DLY -#define PMU_MAX_TRANSITION_DLY 500000 -#endif - -/* Value for ChipClockCSR during initial setup */ -#define DHD_INIT_CLKCTL1 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ) -#define DHD_INIT_CLKCTL2 (SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP) - -/* Flags for SDH calls */ -#define F2SYNC (SDIO_REQ_4BYTE | SDIO_REQ_FIXED) - -/* Packet free applicable unconditionally for sdio and sdspi. Conditional if - * bufpool was present for gspi bus. - */ -#define PKTFREE2() if ((bus->bus != SPI_BUS) || bus->usebufpool) \ - PKTFREE(bus->dhd->osh, pkt, FALSE); -DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep); -extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len); - -#ifdef DHD_DEBUG -/* Device console log buffer state */ -typedef struct dhd_console { - uint count; /* Poll interval msec counter */ - uint log_addr; /* Log struct address (fixed) */ - hndrte_log_t log; /* Log struct (host copy) */ - uint bufsize; /* Size of log buffer */ - uint8 *buf; /* Log buffer (host copy) */ - uint last; /* Last buffer read index */ -} dhd_console_t; -#endif /* DHD_DEBUG */ - -/* Private data for SDIO bus interaction */ -typedef struct dhd_bus { - dhd_pub_t *dhd; - - bcmsdh_info_t *sdh; /* Handle for BCMSDH calls */ - si_t *sih; /* Handle for SI calls */ - char *vars; /* Variables (from CIS and/or other) */ - uint varsz; /* Size of variables buffer */ - uint32 sbaddr; /* Current SB window pointer (-1, invalid) */ - - sdpcmd_regs_t *regs; /* Registers for SDIO core */ - uint sdpcmrev; /* SDIO core revision */ - uint armrev; /* CPU core revision */ - uint ramrev; /* SOCRAM core revision */ - uint32 ramsize; /* Size of RAM in SOCRAM (bytes) */ - uint32 orig_ramsize; /* Size of RAM in SOCRAM (bytes) */ - - uint32 bus; /* gSPI or SDIO bus */ - uint32 hostintmask; /* Copy of Host Interrupt Mask */ - uint32 intstatus; /* Intstatus bits (events) pending */ - bool dpc_sched; /* Indicates DPC schedule (intrpt rcvd) */ - bool fcstate; /* State of dongle flow-control */ - - uint16 cl_devid; /* cached devid for dhdsdio_probe_attach() */ - char *fw_path; /* module_param: path to firmware image */ - char *nv_path; /* module_param: path to nvram vars file */ - const char *nvram_params; /* user specified nvram params. */ - - uint blocksize; /* Block size of SDIO transfers */ - uint roundup; /* Max roundup limit */ - - struct pktq txq; /* Queue length used for flow-control */ - uint8 flowcontrol; /* per prio flow control bitmask */ - uint8 tx_seq; /* Transmit sequence number (next) */ - uint8 tx_max; /* Maximum transmit sequence allowed */ - - uint8 hdrbuf[MAX_HDR_READ + DHD_SDALIGN]; - uint8 *rxhdr; /* Header of current rx frame (in hdrbuf) */ - uint16 nextlen; /* Next Read Len from last header */ - uint8 rx_seq; /* Receive sequence number (expected) */ - bool rxskip; /* Skip receive (awaiting NAK ACK) */ - - void *glomd; /* Packet containing glomming descriptor */ - void *glom; /* Packet chain for glommed superframe */ - uint glomerr; /* Glom packet read errors */ - - uint8 *rxbuf; /* Buffer for receiving control packets */ - uint rxblen; /* Allocated length of rxbuf */ - uint8 *rxctl; /* Aligned pointer into rxbuf */ - uint8 *databuf; /* Buffer for receiving big glom packet */ - uint8 *dataptr; /* Aligned pointer into databuf */ - uint rxlen; /* Length of valid data in buffer */ - - uint8 sdpcm_ver; /* Bus protocol reported by dongle */ - - bool intr; /* Use interrupts */ - bool poll; /* Use polling */ - bool ipend; /* Device interrupt is pending */ - bool intdis; /* Interrupts disabled by isr */ - uint intrcount; /* Count of device interrupt callbacks */ - uint lastintrs; /* Count as of last watchdog timer */ - uint spurious; /* Count of spurious interrupts */ - uint pollrate; /* Ticks between device polls */ - uint polltick; /* Tick counter */ - uint pollcnt; /* Count of active polls */ - -#ifdef DHD_DEBUG - dhd_console_t console; /* Console output polling support */ - uint console_addr; /* Console address from shared struct */ -#endif /* DHD_DEBUG */ - - uint regfails; /* Count of R_REG/W_REG failures */ - - uint clkstate; /* State of sd and backplane clock(s) */ - bool activity; /* Activity flag for clock down */ - int32 idletime; /* Control for activity timeout */ - int32 idlecount; /* Activity timeout counter */ - int32 idleclock; /* How to set bus driver when idle */ - int32 sd_divisor; /* Speed control to bus driver */ - int32 sd_mode; /* Mode control to bus driver */ - int32 sd_rxchain; /* If bcmsdh api accepts PKT chains */ - bool use_rxchain; /* If dhd should use PKT chains */ - bool sleeping; /* Is SDIO bus sleeping? */ - bool rxflow_mode; /* Rx flow control mode */ - bool rxflow; /* Is rx flow control on */ - uint prev_rxlim_hit; /* Is prev rx limit exceeded (per dpc schedule) */ - bool alp_only; /* Don't use HT clock (ALP only) */ - /* Field to decide if rx of control frames happen in rxbuf or lb-pool */ - bool usebufpool; - -#ifdef SDTEST - /* external loopback */ - bool ext_loop; - uint8 loopid; - - /* pktgen configuration */ - uint pktgen_freq; /* Ticks between bursts */ - uint pktgen_count; /* Packets to send each burst */ - uint pktgen_print; /* Bursts between count displays */ - uint pktgen_total; /* Stop after this many */ - uint pktgen_minlen; /* Minimum packet data len */ - uint pktgen_maxlen; /* Maximum packet data len */ - uint pktgen_mode; /* Configured mode: tx, rx, or echo */ - uint pktgen_stop; /* Number of tx failures causing stop */ - - /* active pktgen fields */ - uint pktgen_tick; /* Tick counter for bursts */ - uint pktgen_ptick; /* Burst counter for printing */ - uint pktgen_sent; /* Number of test packets generated */ - uint pktgen_rcvd; /* Number of test packets received */ - uint pktgen_fail; /* Number of failed send attempts */ - uint16 pktgen_len; /* Length of next packet to send */ -#endif /* SDTEST */ - - /* Some additional counters */ - uint tx_sderrs; /* Count of tx attempts with sd errors */ - uint fcqueued; /* Tx packets that got queued */ - uint rxrtx; /* Count of rtx requests (NAK to dongle) */ - uint rx_toolong; /* Receive frames too long to receive */ - uint rxc_errors; /* SDIO errors when reading control frames */ - uint rx_hdrfail; /* SDIO errors on header reads */ - uint rx_badhdr; /* Bad received headers (roosync?) */ - uint rx_badseq; /* Mismatched rx sequence number */ - uint fc_rcvd; /* Number of flow-control events received */ - uint fc_xoff; /* Number which turned on flow-control */ - uint fc_xon; /* Number which turned off flow-control */ - uint rxglomfail; /* Failed deglom attempts */ - uint rxglomframes; /* Number of glom frames (superframes) */ - uint rxglompkts; /* Number of packets from glom frames */ - uint f2rxhdrs; /* Number of header reads */ - uint f2rxdata; /* Number of frame data reads */ - uint f2txdata; /* Number of f2 frame writes */ - uint f1regdata; /* Number of f1 register accesses */ - - uint8 *ctrl_frame_buf; - uint32 ctrl_frame_len; - bool ctrl_frame_stat; -} dhd_bus_t; - -/* clkstate */ -#define CLK_NONE 0 -#define CLK_SDONLY 1 -#define CLK_PENDING 2 /* Not used yet */ -#define CLK_AVAIL 3 - -#define DHD_NOPMU(dhd) (FALSE) - -#ifdef DHD_DEBUG -static int qcount[NUMPRIO]; -static int tx_packets[NUMPRIO]; -#endif /* DHD_DEBUG */ - -/* Deferred transmit */ -const uint dhd_deferred_tx = 1; - -extern uint dhd_watchdog_ms; -extern void dhd_os_wd_timer(void *bus, uint wdtick); - -/* Tx/Rx bounds */ -uint dhd_txbound; -uint dhd_rxbound; -uint dhd_txminmax; - -/* override the RAM size if possible */ -#define DONGLE_MIN_MEMSIZE (128 *1024) -int dhd_dongle_memsize; - -static bool dhd_doflow; -static bool dhd_alignctl; - -static bool sd1idle; - -static bool retrydata; -#define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) - -static const uint watermark = 8; -static const uint firstread = DHD_FIRSTREAD; - -#define HDATLEN (firstread - (SDPCM_HDRLEN)) - -/* Retry count for register access failures */ -static const uint retry_limit = 2; - -/* Force even SD lengths (some host controllers mess up on odd bytes) */ -static bool forcealign; - -#define ALIGNMENT 4 - -#if defined(OOB_INTR_ONLY) && defined(HW_OOB) -extern void bcmsdh_enable_hw_oob_intr(void *sdh, bool enable); -#endif - -#if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) -#error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD -#endif /* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */ -#define PKTALIGN(osh, p, len, align) \ - do { \ - uint datalign; \ - datalign = (uintptr)PKTDATA((osh), (p)); \ - datalign = ROUNDUP(datalign, (align)) - datalign; \ - ASSERT(datalign < (align)); \ - ASSERT(PKTLEN((osh), (p)) >= ((len) + datalign)); \ - if (datalign) \ - PKTPULL((osh), (p), datalign); \ - PKTSETLEN((osh), (p), (len)); \ - } while (0) - -/* Limit on rounding up frames */ -static const uint max_roundup = 512; - -/* Try doing readahead */ -static bool dhd_readahead; - - -/* To check if there's window offered */ -#define DATAOK(bus) \ - (((uint8)(bus->tx_max - bus->tx_seq) != 0) && \ - (((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0)) - -/* Macros to get register read/write status */ -/* NOTE: these assume a local dhdsdio_bus_t *bus! */ -#define R_SDREG(regvar, regaddr, retryvar) \ -do { \ - retryvar = 0; \ - do { \ - regvar = R_REG(bus->dhd->osh, regaddr); \ - } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \ - if (retryvar) { \ - bus->regfails += (retryvar-1); \ - if (retryvar > retry_limit) { \ - DHD_ERROR(("%s: FAILED" #regvar "READ, LINE %d\n", \ - __FUNCTION__, __LINE__)); \ - regvar = 0; \ - } \ - } \ -} while (0) - -#define W_SDREG(regval, regaddr, retryvar) \ -do { \ - retryvar = 0; \ - do { \ - W_REG(bus->dhd->osh, regaddr, regval); \ - } while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \ - if (retryvar) { \ - bus->regfails += (retryvar-1); \ - if (retryvar > retry_limit) \ - DHD_ERROR(("%s: FAILED REGISTER WRITE, LINE %d\n", \ - __FUNCTION__, __LINE__)); \ - } \ -} while (0) - - -#define DHD_BUS SDIO_BUS - -#define PKT_AVAILABLE() (intstatus & I_HMB_FRAME_IND) - -#define HOSTINTMASK (I_HMB_SW_MASK | I_CHIPACTIVE) - -#define GSPI_PR55150_BAILOUT - - -#ifdef SDTEST -static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq); -static void dhdsdio_sdtest_set(dhd_bus_t *bus, bool start); -#endif - -#ifdef DHD_DEBUG -static int dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size); -static int dhdsdio_mem_dump(dhd_bus_t *bus); -#endif /* DHD_DEBUG */ -static int dhdsdio_download_state(dhd_bus_t *bus, bool enter); - -static void dhdsdio_release(dhd_bus_t *bus, osl_t *osh); -static void dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh); -static void dhdsdio_disconnect(void *ptr); -static bool dhdsdio_chipmatch(uint16 chipid); -static bool dhdsdio_probe_attach(dhd_bus_t *bus, osl_t *osh, void *sdh, - void * regsva, uint16 devid); -static bool dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh); -static bool dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh); -static void dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh); - -static uint process_nvram_vars(char *varbuf, uint len); - -static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size); -static int dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, - uint8 *buf, uint nbytes, - void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); -static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, - uint8 *buf, uint nbytes, - void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); - -static bool dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh); -static int _dhdsdio_download_firmware(struct dhd_bus *bus); - -static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path); -static int dhdsdio_download_nvram(struct dhd_bus *bus); -#ifdef BCMEMBEDIMAGE -static int dhdsdio_download_code_array(struct dhd_bus *bus); -#endif - - -static void -dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) -{ - int32 min_size = DONGLE_MIN_MEMSIZE; - /* Restrict the memsize to user specified limit */ - DHD_ERROR(("user: Restrict the dongle ram size to %d, min accepted %d\n", - dhd_dongle_memsize, min_size)); - if ((dhd_dongle_memsize > min_size) && - (dhd_dongle_memsize < (int32)bus->orig_ramsize)) - bus->ramsize = dhd_dongle_memsize; -} - -static int -dhdsdio_set_siaddr_window(dhd_bus_t *bus, uint32 address) -{ - int err = 0; - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRLOW, - (address >> 8) & SBSDIO_SBADDRLOW_MASK, &err); - if (!err) - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRMID, - (address >> 16) & SBSDIO_SBADDRMID_MASK, &err); - if (!err) - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SBADDRHIGH, - (address >> 24) & SBSDIO_SBADDRHIGH_MASK, &err); - return err; -} - - -/* Turn backplane clock on or off */ -static int -dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) -{ - int err; - uint8 clkctl, clkreq, devctl; - bcmsdh_info_t *sdh; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - -#if defined(OOB_INTR_ONLY) - pendok = FALSE; -#endif - clkctl = 0; - sdh = bus->sdh; - - - if (on) { - /* Request HT Avail */ - clkreq = bus->alp_only ? SBSDIO_ALP_AVAIL_REQ : SBSDIO_HT_AVAIL_REQ; - - if ((bus->sih->chip == BCM4329_CHIP_ID) && (bus->sih->chiprev == 0)) - clkreq |= SBSDIO_FORCE_ALP; - - - - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); - if (err) { - DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); - return BCME_ERROR; - } - - if (pendok && - ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) { - uint32 dummy, retries; - R_SDREG(dummy, &bus->regs->clockctlstatus, retries); - } - - /* Check current status */ - clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (err) { - DHD_ERROR(("%s: HT Avail read error: %d\n", __FUNCTION__, err)); - return BCME_ERROR; - } - - /* Go to pending and await interrupt if appropriate */ - if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { - /* Allow only clock-available interrupt */ - devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); - if (err) { - DHD_ERROR(("%s: Devctl access error setting CA: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - - devctl |= SBSDIO_DEVCTL_CA_INT_ONLY; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); - DHD_INFO(("CLKCTL: set PENDING\n")); - bus->clkstate = CLK_PENDING; - - return BCME_OK; - } else if (bus->clkstate == CLK_PENDING) { - /* Cancel CA-only interrupt filter */ - devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); - devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); - } - - /* Otherwise, wait here (polling) for HT Avail */ - if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { - SPINWAIT_SLEEP(sdioh_spinwait_sleep, - ((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, &err)), - !SBSDIO_CLKAV(clkctl, bus->alp_only)), PMU_MAX_TRANSITION_DLY); - } - if (err) { - DHD_ERROR(("%s: HT Avail request error: %d\n", __FUNCTION__, err)); - return BCME_ERROR; - } - if (!SBSDIO_CLKAV(clkctl, bus->alp_only)) { - DHD_ERROR(("%s: HT Avail timeout (%d): clkctl 0x%02x\n", - __FUNCTION__, PMU_MAX_TRANSITION_DLY, clkctl)); - return BCME_ERROR; - } - - - /* Mark clock available */ - bus->clkstate = CLK_AVAIL; - DHD_INFO(("CLKCTL: turned ON\n")); - -#if defined(DHD_DEBUG) - if (bus->alp_only == TRUE) { -#if !defined(BCMLXSDMMC) - if (!SBSDIO_ALPONLY(clkctl)) { - DHD_ERROR(("%s: HT Clock, when ALP Only\n", __FUNCTION__)); - } -#endif /* !defined(BCMLXSDMMC) */ - } else { - if (SBSDIO_ALPONLY(clkctl)) { - DHD_ERROR(("%s: HT Clock should be on.\n", __FUNCTION__)); - } - } -#endif /* defined (DHD_DEBUG) */ - - bus->activity = TRUE; - } else { - clkreq = 0; - - if (bus->clkstate == CLK_PENDING) { - /* Cancel CA-only interrupt filter */ - devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); - devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); - } - - bus->clkstate = CLK_SDONLY; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkreq, &err); - DHD_INFO(("CLKCTL: turned OFF\n")); - if (err) { - DHD_ERROR(("%s: Failed access turning clock off: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - } - return BCME_OK; -} - -/* Change idle/active SD state */ -static int -dhdsdio_sdclk(dhd_bus_t *bus, bool on) -{ - int err; - int32 iovalue; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (on) { - if (bus->idleclock == DHD_IDLE_STOP) { - /* Turn on clock and restore mode */ - iovalue = 1; - err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, - &iovalue, sizeof(iovalue), TRUE); - if (err) { - DHD_ERROR(("%s: error enabling sd_clock: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - - iovalue = bus->sd_mode; - err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, - &iovalue, sizeof(iovalue), TRUE); - if (err) { - DHD_ERROR(("%s: error changing sd_mode: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - } else if (bus->idleclock != DHD_IDLE_ACTIVE) { - /* Restore clock speed */ - iovalue = bus->sd_divisor; - err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, - &iovalue, sizeof(iovalue), TRUE); - if (err) { - DHD_ERROR(("%s: error restoring sd_divisor: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - } - bus->clkstate = CLK_SDONLY; - } else { - /* Stop or slow the SD clock itself */ - if ((bus->sd_divisor == -1) || (bus->sd_mode == -1)) { - DHD_TRACE(("%s: can't idle clock, divisor %d mode %d\n", - __FUNCTION__, bus->sd_divisor, bus->sd_mode)); - return BCME_ERROR; - } - if (bus->idleclock == DHD_IDLE_STOP) { - if (sd1idle) { - /* Change to SD1 mode and turn off clock */ - iovalue = 1; - err = bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, - &iovalue, sizeof(iovalue), TRUE); - if (err) { - DHD_ERROR(("%s: error changing sd_clock: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - } - - iovalue = 0; - err = bcmsdh_iovar_op(bus->sdh, "sd_clock", NULL, 0, - &iovalue, sizeof(iovalue), TRUE); - if (err) { - DHD_ERROR(("%s: error disabling sd_clock: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - } else if (bus->idleclock != DHD_IDLE_ACTIVE) { - /* Set divisor to idle value */ - iovalue = bus->idleclock; - err = bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, - &iovalue, sizeof(iovalue), TRUE); - if (err) { - DHD_ERROR(("%s: error changing sd_divisor: %d\n", - __FUNCTION__, err)); - return BCME_ERROR; - } - } - bus->clkstate = CLK_NONE; - } - - return BCME_OK; -} - -/* Transition SD and backplane clock readiness */ -static int -dhdsdio_clkctl(dhd_bus_t *bus, uint target, bool pendok) -{ -#ifdef DHD_DEBUG - uint oldstate = bus->clkstate; -#endif /* DHD_DEBUG */ - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Early exit if we're already there */ - if (bus->clkstate == target) { - if (target == CLK_AVAIL) { - dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); - bus->activity = TRUE; - } - return BCME_OK; - } - - switch (target) { - case CLK_AVAIL: - /* Make sure SD clock is available */ - if (bus->clkstate == CLK_NONE) - dhdsdio_sdclk(bus, TRUE); - /* Now request HT Avail on the backplane */ - dhdsdio_htclk(bus, TRUE, pendok); - dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); - bus->activity = TRUE; - break; - - case CLK_SDONLY: - /* Remove HT request, or bring up SD clock */ - if (bus->clkstate == CLK_NONE) - dhdsdio_sdclk(bus, TRUE); - else if (bus->clkstate == CLK_AVAIL) - dhdsdio_htclk(bus, FALSE, FALSE); - else - DHD_ERROR(("dhdsdio_clkctl: request for %d -> %d\n", - bus->clkstate, target)); - dhd_os_wd_timer(bus->dhd, dhd_watchdog_ms); - break; - - case CLK_NONE: - /* Make sure to remove HT request */ - if (bus->clkstate == CLK_AVAIL) - dhdsdio_htclk(bus, FALSE, FALSE); - /* Now remove the SD clock */ - dhdsdio_sdclk(bus, FALSE); - dhd_os_wd_timer(bus->dhd, 0); - break; - } -#ifdef DHD_DEBUG - DHD_INFO(("dhdsdio_clkctl: %d -> %d\n", oldstate, bus->clkstate)); -#endif /* DHD_DEBUG */ - - return BCME_OK; -} - -int -dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) -{ - bcmsdh_info_t *sdh = bus->sdh; - sdpcmd_regs_t *regs = bus->regs; - uint retries = 0; - - DHD_INFO(("dhdsdio_bussleep: request %s (currently %s)\n", - (sleep ? "SLEEP" : "WAKE"), - (bus->sleeping ? "SLEEP" : "WAKE"))); - - /* Done if we're already in the requested state */ - if (sleep == bus->sleeping) - return BCME_OK; - - /* Going to sleep: set the alarm and turn off the lights... */ - if (sleep) { - /* Don't sleep if something is pending */ - if (bus->dpc_sched || bus->rxskip || pktq_len(&bus->txq)) - return BCME_BUSY; - - - /* Disable SDIO interrupts (no longer interested) */ - bcmsdh_intr_disable(bus->sdh); - - /* Make sure the controller has the bus up */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - /* Tell device to start using OOB wakeup */ - W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); - if (retries > retry_limit) - DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n")); - - /* Turn off our contribution to the HT clock request */ - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - SBSDIO_FORCE_HW_CLKREQ_OFF, NULL); - - /* Isolate the bus */ - if (bus->sih->chip != BCM4329_CHIP_ID && bus->sih->chip != BCM4319_CHIP_ID) { - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, - SBSDIO_DEVCTL_PADS_ISO, NULL); - } - - /* Change state */ - bus->sleeping = TRUE; - - } else { - /* Waking up: bus power up is ok, set local state */ - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - 0, NULL); - - /* Force pad isolation off if possible (in case power never toggled) */ - if ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev >= 10)) - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, 0, NULL); - - - /* Make sure the controller has the bus up */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - /* Send misc interrupt to indicate OOB not needed */ - W_SDREG(0, ®s->tosbmailboxdata, retries); - if (retries <= retry_limit) - W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); - - if (retries > retry_limit) - DHD_ERROR(("CANNOT SIGNAL CHIP TO CLEAR OOB!!\n")); - - /* Make sure we have SD bus access */ - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); - - /* Change state */ - bus->sleeping = FALSE; - - /* Enable interrupts again */ - if (bus->intr && (bus->dhd->busstate == DHD_BUS_DATA)) { - bus->intdis = FALSE; - bcmsdh_intr_enable(bus->sdh); - } - } - - return BCME_OK; -} -#if defined(OOB_INTR_ONLY) -void -dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) -{ -#if defined(HW_OOB) - bcmsdh_enable_hw_oob_intr(bus->sdh, enable); -#else - sdpcmd_regs_t *regs = bus->regs; - uint retries = 0; - - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - if (enable == TRUE) { - - /* Tell device to start using OOB wakeup */ - W_SDREG(SMB_USE_OOB, ®s->tosbmailbox, retries); - if (retries > retry_limit) - DHD_ERROR(("CANNOT SIGNAL CHIP, WILL NOT WAKE UP!!\n")); - - } else { - /* Send misc interrupt to indicate OOB not needed */ - W_SDREG(0, ®s->tosbmailboxdata, retries); - if (retries <= retry_limit) - W_SDREG(SMB_DEV_INT, ®s->tosbmailbox, retries); - } - - /* Turn off our contribution to the HT clock request */ - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); -#endif /* !defined(HW_OOB) */ -} -#endif /* defined(OOB_INTR_ONLY) */ - -#define BUS_WAKE(bus) \ - do { \ - if ((bus)->sleeping) \ - dhdsdio_bussleep((bus), FALSE); \ - } while (0); - - -/* Writes a HW/SW header into the packet and sends it. */ -/* Assumes: (a) header space already there, (b) caller holds lock */ -static int -dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt) -{ - int ret; - osl_t *osh; - uint8 *frame; - uint16 len, pad = 0; - uint32 swheader; - uint retries = 0; - bcmsdh_info_t *sdh; - void *new; - int i; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - sdh = bus->sdh; - osh = bus->dhd->osh; - - if (bus->dhd->dongle_reset) { - ret = BCME_NOTREADY; - goto done; - } - - frame = (uint8*)PKTDATA(osh, pkt); - - /* Add alignment padding, allocate new packet if needed */ - if ((pad = ((uintptr)frame % DHD_SDALIGN))) { - if (PKTHEADROOM(osh, pkt) < pad) { - DHD_INFO(("%s: insufficient headroom %d for %d pad\n", - __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad)); - bus->dhd->tx_realloc++; - new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE); - if (!new) { - DHD_ERROR(("%s: couldn't allocate new %d-byte packet\n", - __FUNCTION__, PKTLEN(osh, pkt) + DHD_SDALIGN)); - ret = BCME_NOMEM; - goto done; - } - - PKTALIGN(osh, new, PKTLEN(osh, pkt), DHD_SDALIGN); - bcopy(PKTDATA(osh, pkt), PKTDATA(osh, new), PKTLEN(osh, pkt)); - if (free_pkt) - PKTFREE(osh, pkt, TRUE); - /* free the pkt if canned one is not used */ - free_pkt = TRUE; - pkt = new; - frame = (uint8*)PKTDATA(osh, pkt); - ASSERT(((uintptr)frame % DHD_SDALIGN) == 0); - pad = 0; - } else { - PKTPUSH(osh, pkt, pad); - frame = (uint8*)PKTDATA(osh, pkt); - - ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt)); - bzero(frame, pad + SDPCM_HDRLEN); - } - } - ASSERT(pad < DHD_SDALIGN); - - /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ - len = (uint16)PKTLEN(osh, pkt); - *(uint16*)frame = htol16(len); - *(((uint16*)frame) + 1) = htol16(~len); - - /* Software tag: channel, sequence number, data offset */ - swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | - (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); - htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN); - htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); - -#ifdef DHD_DEBUG - tx_packets[PKTPRIO(pkt)]++; - if (DHD_BYTES_ON() && - (((DHD_CTL_ON() && (chan == SDPCM_CONTROL_CHANNEL)) || - (DHD_DATA_ON() && (chan != SDPCM_CONTROL_CHANNEL))))) { - prhex("Tx Frame", frame, len); - } else if (DHD_HDRS_ON()) { - prhex("TxHdr", frame, MIN(len, 16)); - } -#endif - - /* Raise len to next SDIO block to eliminate tail command */ - if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { - uint16 pad = bus->blocksize - (len % bus->blocksize); - if ((pad <= bus->roundup) && (pad < bus->blocksize)) -#ifdef NOTUSED - if (pad <= PKTTAILROOM(osh, pkt)) -#endif /* NOTUSED */ - len += pad; - } else if (len % DHD_SDALIGN) { - len += DHD_SDALIGN - (len % DHD_SDALIGN); - } - - /* Some controllers have trouble with odd bytes -- round to even */ - if (forcealign && (len & (ALIGNMENT - 1))) { -#ifdef NOTUSED - if (PKTTAILROOM(osh, pkt)) -#endif - len = ROUNDUP(len, ALIGNMENT); -#ifdef NOTUSED - else - DHD_ERROR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len)); -#endif - } - - do { - ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - frame, len, pkt, NULL, NULL); - bus->f2txdata++; - ASSERT(ret != BCME_PENDING); - - if (ret < 0) { - /* On failure, abort the command and terminate the frame */ - DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", - __FUNCTION__, ret)); - bus->tx_sderrs++; - - bcmsdh_abort(sdh, SDIO_FUNC_2); - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, - SFC_WF_TERM, NULL); - bus->f1regdata++; - - for (i = 0; i < 3; i++) { - uint8 hi, lo; - hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCLO, NULL); - bus->f1regdata += 2; - if ((hi == 0) && (lo == 0)) - break; - } - - } - if (ret == 0) { - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; - } - } while ((ret < 0) && retrydata && retries++ < TXRETRIES); - -done: - /* restore pkt buffer pointer before calling tx complete routine */ - PKTPULL(osh, pkt, SDPCM_HDRLEN + pad); - dhd_os_sdunlock(bus->dhd); - dhd_txcomplete(bus->dhd, pkt, ret != 0); - dhd_os_sdlock(bus->dhd); - - if (free_pkt) - PKTFREE(osh, pkt, TRUE); - - return ret; -} - -int -dhd_bus_txdata(struct dhd_bus *bus, void *pkt) -{ - int ret = BCME_ERROR; - osl_t *osh; - uint datalen, prec; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - osh = bus->dhd->osh; - datalen = PKTLEN(osh, pkt); - -#ifdef SDTEST - /* Push the test header if doing loopback */ - if (bus->ext_loop) { - uint8* data; - PKTPUSH(osh, pkt, SDPCM_TEST_HDRLEN); - data = PKTDATA(osh, pkt); - *data++ = SDPCM_TEST_ECHOREQ; - *data++ = (uint8)bus->loopid++; - *data++ = (datalen >> 0); - *data++ = (datalen >> 8); - datalen += SDPCM_TEST_HDRLEN; - } -#endif /* SDTEST */ - - /* Add space for the header */ - PKTPUSH(osh, pkt, SDPCM_HDRLEN); - ASSERT(ISALIGNED((uintptr)PKTDATA(osh, pkt), 2)); - - prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK)); - - - /* Check for existing queue, current flow-control, pending event, or pending clock */ - if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched || - (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) || - (bus->clkstate != CLK_AVAIL)) { - DHD_TRACE(("%s: deferring pktq len %d\n", __FUNCTION__, - pktq_len(&bus->txq))); - bus->fcqueued++; - - /* Priority based enq */ - dhd_os_sdlock_txq(bus->dhd); - if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == FALSE) { - PKTPULL(osh, pkt, SDPCM_HDRLEN); - dhd_txcomplete(bus->dhd, pkt, FALSE); - PKTFREE(osh, pkt, TRUE); - DHD_ERROR(("%s: out of bus->txq !!!\n", __FUNCTION__)); - ret = BCME_NORESOURCE; - } else { - ret = BCME_OK; - } - dhd_os_sdunlock_txq(bus->dhd); - - if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow) - dhd_txflowcontrol(bus->dhd, 0, ON); - -#ifdef DHD_DEBUG - if (pktq_plen(&bus->txq, prec) > qcount[prec]) - qcount[prec] = pktq_plen(&bus->txq, prec); -#endif - /* Schedule DPC if needed to send queued packet(s) */ - if (dhd_deferred_tx && !bus->dpc_sched) { - bus->dpc_sched = TRUE; - dhd_sched_dpc(bus->dhd); - } - } else { - /* Lock: we're about to use shared data/code (and SDIO) */ - dhd_os_sdlock(bus->dhd); - - /* Otherwise, send it now */ - BUS_WAKE(bus); - /* Make sure back plane ht clk is on, no pending allowed */ - dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); - -#ifndef SDTEST - DHD_TRACE(("%s: calling txpkt\n", __FUNCTION__)); - ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE); -#else - ret = dhdsdio_txpkt(bus, pkt, - (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE); -#endif - if (ret) - bus->dhd->tx_errors++; - else - bus->dhd->dstats.tx_bytes += datalen; - - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { - bus->activity = FALSE; - dhdsdio_clkctl(bus, CLK_NONE, TRUE); - } - - dhd_os_sdunlock(bus->dhd); - } - - - return ret; -} - -static uint -dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) -{ - void *pkt; - uint32 intstatus = 0; - uint retries = 0; - int ret = 0, prec_out; - uint cnt = 0; - uint datalen; - uint8 tx_prec_map; - - dhd_pub_t *dhd = bus->dhd; - sdpcmd_regs_t *regs = bus->regs; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - tx_prec_map = ~bus->flowcontrol; - - /* Send frames until the limit or some other event */ - for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) { - dhd_os_sdlock_txq(bus->dhd); - if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { - dhd_os_sdunlock_txq(bus->dhd); - break; - } - dhd_os_sdunlock_txq(bus->dhd); - datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN; - -#ifndef SDTEST - ret = dhdsdio_txpkt(bus, pkt, SDPCM_DATA_CHANNEL, TRUE); -#else - ret = dhdsdio_txpkt(bus, pkt, - (bus->ext_loop ? SDPCM_TEST_CHANNEL : SDPCM_DATA_CHANNEL), TRUE); -#endif - if (ret) - bus->dhd->tx_errors++; - else - bus->dhd->dstats.tx_bytes += datalen; - - /* In poll mode, need to check for other events */ - if (!bus->intr && cnt) - { - /* Check device status, signal pending interrupt */ - R_SDREG(intstatus, ®s->intstatus, retries); - bus->f2txdata++; - if (bcmsdh_regfail(bus->sdh)) - break; - if (intstatus & bus->hostintmask) - bus->ipend = TRUE; - } - } - - /* Deflow-control stack if needed */ - if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) && - dhd->txoff && (pktq_len(&bus->txq) < FCLOW)) - dhd_txflowcontrol(dhd, 0, OFF); - - return cnt; -} - -int -dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) -{ - uint8 *frame; - uint16 len; - uint32 swheader; - uint retries = 0; - bcmsdh_info_t *sdh = bus->sdh; - uint8 doff = 0; - int ret = -1; - int i; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (bus->dhd->dongle_reset) - return -EIO; - - /* Back the pointer to make a room for bus header */ - frame = msg - SDPCM_HDRLEN; - len = (msglen += SDPCM_HDRLEN); - - /* Add alignment padding (optional for ctl frames) */ - if (dhd_alignctl) { - if ((doff = ((uintptr)frame % DHD_SDALIGN))) { - frame -= doff; - len += doff; - msglen += doff; - bzero(frame, doff + SDPCM_HDRLEN); - } - ASSERT(doff < DHD_SDALIGN); - } - doff += SDPCM_HDRLEN; - - /* Round send length to next SDIO block */ - if (bus->roundup && bus->blocksize && (len > bus->blocksize)) { - uint16 pad = bus->blocksize - (len % bus->blocksize); - if ((pad <= bus->roundup) && (pad < bus->blocksize)) - len += pad; - } else if (len % DHD_SDALIGN) { - len += DHD_SDALIGN - (len % DHD_SDALIGN); - } - - /* Satisfy length-alignment requirements */ - if (forcealign && (len & (ALIGNMENT - 1))) - len = ROUNDUP(len, ALIGNMENT); - - ASSERT(ISALIGNED((uintptr)frame, 2)); - - - /* Need to lock here to protect txseq and SDIO tx calls */ - dhd_os_sdlock(bus->dhd); - - BUS_WAKE(bus); - - /* Make sure backplane clock is on */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - /* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */ - *(uint16*)frame = htol16((uint16)msglen); - *(((uint16*)frame) + 1) = htol16(~msglen); - - /* Software tag: channel, sequence number, data offset */ - swheader = ((SDPCM_CONTROL_CHANNEL << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) - | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); - htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN); - htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader)); - - if (!DATAOK(bus)) { - DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n", - __FUNCTION__, bus->tx_max, bus->tx_seq)); - bus->ctrl_frame_stat = TRUE; - /* Send from dpc */ - bus->ctrl_frame_buf = frame; - bus->ctrl_frame_len = len; - - dhd_wait_for_event(bus->dhd, &bus->ctrl_frame_stat); - - if (bus->ctrl_frame_stat == FALSE) { - DHD_INFO(("%s: ctrl_frame_stat == FALSE\n", __FUNCTION__)); - ret = 0; - } else { - DHD_INFO(("%s: ctrl_frame_stat == TRUE\n", __FUNCTION__)); - ret = -1; - } - } - - if (ret == -1) { -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() && DHD_CTL_ON()) { - prhex("Tx Frame", frame, len); - } else if (DHD_HDRS_ON()) { - prhex("TxHdr", frame, MIN(len, 16)); - } -#endif - - do { - bus->ctrl_frame_stat = FALSE; - ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - frame, len, NULL, NULL, NULL); - - ASSERT(ret != BCME_PENDING); - - if (ret < 0) { - /* On failure, abort the command and terminate the frame */ - DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", - __FUNCTION__, ret)); - bus->tx_sderrs++; - - bcmsdh_abort(sdh, SDIO_FUNC_2); - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, - SFC_WF_TERM, NULL); - bus->f1regdata++; - - for (i = 0; i < 3; i++) { - uint8 hi, lo; - hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCLO, NULL); - bus->f1regdata += 2; - if ((hi == 0) && (lo == 0)) - break; - } - - } - if (ret == 0) { - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; - } - } while ((ret < 0) && retries++ < TXRETRIES); - } - - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { - bus->activity = FALSE; - dhdsdio_clkctl(bus, CLK_NONE, TRUE); - } - - dhd_os_sdunlock(bus->dhd); - - if (ret) - bus->dhd->tx_ctlerrs++; - else - bus->dhd->tx_ctlpkts++; - - return ret ? -EIO : 0; -} - -int -dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) -{ - int timeleft; - uint rxlen = 0; - bool pending; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (bus->dhd->dongle_reset) - return -EIO; - - /* Wait until control frame is available */ - timeleft = dhd_os_ioctl_resp_wait(bus->dhd, &bus->rxlen, &pending); - - dhd_os_sdlock(bus->dhd); - rxlen = bus->rxlen; - bcopy(bus->rxctl, msg, MIN(msglen, rxlen)); - bus->rxlen = 0; - dhd_os_sdunlock(bus->dhd); - - if (rxlen) { - DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", - __FUNCTION__, rxlen, msglen)); - } else if (timeleft == 0) { - DHD_ERROR(("%s: resumed on timeout\n", __FUNCTION__)); -#ifdef DHD_DEBUG - dhd_os_sdlock(bus->dhd); - dhdsdio_checkdied(bus, NULL, 0); - dhd_os_sdunlock(bus->dhd); -#endif /* DHD_DEBUG */ - } else if (pending == TRUE) { - DHD_CTL(("%s: cancelled\n", __FUNCTION__)); - return -ERESTARTSYS; - } else { - DHD_CTL(("%s: resumed for unknown reason?\n", __FUNCTION__)); -#ifdef DHD_DEBUG - dhd_os_sdlock(bus->dhd); - dhdsdio_checkdied(bus, NULL, 0); - dhd_os_sdunlock(bus->dhd); -#endif /* DHD_DEBUG */ - } - - if (rxlen) - bus->dhd->rx_ctlpkts++; - else - bus->dhd->rx_ctlerrs++; - - return rxlen ? (int)rxlen : -ETIMEDOUT; -} - -/* IOVar table */ -enum { - IOV_INTR = 1, - IOV_POLLRATE, - IOV_SDREG, - IOV_SBREG, - IOV_SDCIS, - IOV_MEMBYTES, - IOV_MEMSIZE, -#ifdef DHD_DEBUG - IOV_CHECKDIED, -#endif - IOV_DOWNLOAD, - IOV_FORCEEVEN, - IOV_SDIOD_DRIVE, - IOV_READAHEAD, - IOV_SDRXCHAIN, - IOV_ALIGNCTL, - IOV_SDALIGN, - IOV_DEVRESET, - IOV_CPU, -#ifdef SDTEST - IOV_PKTGEN, - IOV_EXTLOOP, -#endif /* SDTEST */ - IOV_SPROM, - IOV_TXBOUND, - IOV_RXBOUND, - IOV_TXMINMAX, - IOV_IDLETIME, - IOV_IDLECLOCK, - IOV_SD1IDLE, - IOV_SLEEP, - IOV_VARS -}; - -const bcm_iovar_t dhdsdio_iovars[] = { - {"intr", IOV_INTR, 0, IOVT_BOOL, 0 }, - {"sleep", IOV_SLEEP, 0, IOVT_BOOL, 0 }, - {"pollrate", IOV_POLLRATE, 0, IOVT_UINT32, 0 }, - {"idletime", IOV_IDLETIME, 0, IOVT_INT32, 0 }, - {"idleclock", IOV_IDLECLOCK, 0, IOVT_INT32, 0 }, - {"sd1idle", IOV_SD1IDLE, 0, IOVT_BOOL, 0 }, - {"membytes", IOV_MEMBYTES, 0, IOVT_BUFFER, 2 * sizeof(int) }, - {"memsize", IOV_MEMSIZE, 0, IOVT_UINT32, 0 }, - {"download", IOV_DOWNLOAD, 0, IOVT_BOOL, 0 }, - {"vars", IOV_VARS, 0, IOVT_BUFFER, 0 }, - {"sdiod_drive", IOV_SDIOD_DRIVE, 0, IOVT_UINT32, 0 }, - {"readahead", IOV_READAHEAD, 0, IOVT_BOOL, 0 }, - {"sdrxchain", IOV_SDRXCHAIN, 0, IOVT_BOOL, 0 }, - {"alignctl", IOV_ALIGNCTL, 0, IOVT_BOOL, 0 }, - {"sdalign", IOV_SDALIGN, 0, IOVT_BOOL, 0 }, - {"devreset", IOV_DEVRESET, 0, IOVT_BOOL, 0 }, -#ifdef DHD_DEBUG - {"sdreg", IOV_SDREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sbreg", IOV_SBREG, 0, IOVT_BUFFER, sizeof(sdreg_t) }, - {"sd_cis", IOV_SDCIS, 0, IOVT_BUFFER, DHD_IOCTL_MAXLEN }, - {"forcealign", IOV_FORCEEVEN, 0, IOVT_BOOL, 0 }, - {"txbound", IOV_TXBOUND, 0, IOVT_UINT32, 0 }, - {"rxbound", IOV_RXBOUND, 0, IOVT_UINT32, 0 }, - {"txminmax", IOV_TXMINMAX, 0, IOVT_UINT32, 0 }, - {"cpu", IOV_CPU, 0, IOVT_BOOL, 0 }, -#ifdef DHD_DEBUG - {"checkdied", IOV_CHECKDIED, 0, IOVT_BUFFER, 0 }, -#endif /* DHD_DEBUG */ -#endif /* DHD_DEBUG */ -#ifdef SDTEST - {"extloop", IOV_EXTLOOP, 0, IOVT_BOOL, 0 }, - {"pktgen", IOV_PKTGEN, 0, IOVT_BUFFER, sizeof(dhd_pktgen_t) }, -#endif /* SDTEST */ - - {NULL, 0, 0, 0, 0 } -}; - -static void -dhd_dump_pct(struct bcmstrbuf *strbuf, char *desc, uint num, uint div) -{ - uint q1, q2; - - if (!div) { - bcm_bprintf(strbuf, "%s N/A", desc); - } else { - q1 = num / div; - q2 = (100 * (num - (q1 * div))) / div; - bcm_bprintf(strbuf, "%s %d.%02d", desc, q1, q2); - } -} - -void -dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) -{ - dhd_bus_t *bus = dhdp->bus; - - bcm_bprintf(strbuf, "Bus SDIO structure:\n"); - bcm_bprintf(strbuf, "hostintmask 0x%08x intstatus 0x%08x sdpcm_ver %d\n", - bus->hostintmask, bus->intstatus, bus->sdpcm_ver); - bcm_bprintf(strbuf, "fcstate %d qlen %d tx_seq %d, max %d, rxskip %d rxlen %d rx_seq %d\n", - bus->fcstate, pktq_len(&bus->txq), bus->tx_seq, bus->tx_max, bus->rxskip, - bus->rxlen, bus->rx_seq); - bcm_bprintf(strbuf, "intr %d intrcount %d lastintrs %d spurious %d\n", - bus->intr, bus->intrcount, bus->lastintrs, bus->spurious); - bcm_bprintf(strbuf, "pollrate %d pollcnt %d regfails %d\n", - bus->pollrate, bus->pollcnt, bus->regfails); - - bcm_bprintf(strbuf, "\nAdditional counters:\n"); - bcm_bprintf(strbuf, "tx_sderrs %d fcqueued %d rxrtx %d rx_toolong %d rxc_errors %d\n", - bus->tx_sderrs, bus->fcqueued, bus->rxrtx, bus->rx_toolong, - bus->rxc_errors); - bcm_bprintf(strbuf, "rx_hdrfail %d badhdr %d badseq %d\n", - bus->rx_hdrfail, bus->rx_badhdr, bus->rx_badseq); - bcm_bprintf(strbuf, "fc_rcvd %d, fc_xoff %d, fc_xon %d\n", - bus->fc_rcvd, bus->fc_xoff, bus->fc_xon); - bcm_bprintf(strbuf, "rxglomfail %d, rxglomframes %d, rxglompkts %d\n", - bus->rxglomfail, bus->rxglomframes, bus->rxglompkts); - bcm_bprintf(strbuf, "f2rx (hdrs/data) %d (%d/%d), f2tx %d f1regs %d\n", - (bus->f2rxhdrs + bus->f2rxdata), bus->f2rxhdrs, bus->f2rxdata, - bus->f2txdata, bus->f1regdata); - { - dhd_dump_pct(strbuf, "\nRx: pkts/f2rd", bus->dhd->rx_packets, - (bus->f2rxhdrs + bus->f2rxdata)); - dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->rx_packets, bus->f1regdata); - dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->rx_packets, - (bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); - dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->rx_packets, bus->intrcount); - bcm_bprintf(strbuf, "\n"); - - dhd_dump_pct(strbuf, "Rx: glom pct", (100 * bus->rxglompkts), - bus->dhd->rx_packets); - dhd_dump_pct(strbuf, ", pkts/glom", bus->rxglompkts, bus->rxglomframes); - bcm_bprintf(strbuf, "\n"); - - dhd_dump_pct(strbuf, "Tx: pkts/f2wr", bus->dhd->tx_packets, bus->f2txdata); - dhd_dump_pct(strbuf, ", pkts/f1sd", bus->dhd->tx_packets, bus->f1regdata); - dhd_dump_pct(strbuf, ", pkts/sd", bus->dhd->tx_packets, - (bus->f2txdata + bus->f1regdata)); - dhd_dump_pct(strbuf, ", pkts/int", bus->dhd->tx_packets, bus->intrcount); - bcm_bprintf(strbuf, "\n"); - - dhd_dump_pct(strbuf, "Total: pkts/f2rw", - (bus->dhd->tx_packets + bus->dhd->rx_packets), - (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata)); - dhd_dump_pct(strbuf, ", pkts/f1sd", - (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->f1regdata); - dhd_dump_pct(strbuf, ", pkts/sd", - (bus->dhd->tx_packets + bus->dhd->rx_packets), - (bus->f2txdata + bus->f2rxhdrs + bus->f2rxdata + bus->f1regdata)); - dhd_dump_pct(strbuf, ", pkts/int", - (bus->dhd->tx_packets + bus->dhd->rx_packets), bus->intrcount); - bcm_bprintf(strbuf, "\n\n"); - } - -#ifdef SDTEST - if (bus->pktgen_count) { - bcm_bprintf(strbuf, "pktgen config and count:\n"); - bcm_bprintf(strbuf, "freq %d count %d print %d total %d min %d len %d\n", - bus->pktgen_freq, bus->pktgen_count, bus->pktgen_print, - bus->pktgen_total, bus->pktgen_minlen, bus->pktgen_maxlen); - bcm_bprintf(strbuf, "send attempts %d rcvd %d fail %d\n", - bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail); - } -#endif /* SDTEST */ -#ifdef DHD_DEBUG - bcm_bprintf(strbuf, "dpc_sched %d host interrupt%spending\n", - bus->dpc_sched, (bcmsdh_intr_pending(bus->sdh) ? " " : " not ")); - bcm_bprintf(strbuf, "blocksize %d roundup %d\n", bus->blocksize, bus->roundup); -#endif /* DHD_DEBUG */ - bcm_bprintf(strbuf, "clkstate %d activity %d idletime %d idlecount %d sleeping %d\n", - bus->clkstate, bus->activity, bus->idletime, bus->idlecount, bus->sleeping); -} - -void -dhd_bus_clearcounts(dhd_pub_t *dhdp) -{ - dhd_bus_t *bus = (dhd_bus_t *)dhdp->bus; - - bus->intrcount = bus->lastintrs = bus->spurious = bus->regfails = 0; - bus->rxrtx = bus->rx_toolong = bus->rxc_errors = 0; - bus->rx_hdrfail = bus->rx_badhdr = bus->rx_badseq = 0; - bus->tx_sderrs = bus->fc_rcvd = bus->fc_xoff = bus->fc_xon = 0; - bus->rxglomfail = bus->rxglomframes = bus->rxglompkts = 0; - bus->f2rxhdrs = bus->f2rxdata = bus->f2txdata = bus->f1regdata = 0; -} - -#ifdef SDTEST -static int -dhdsdio_pktgen_get(dhd_bus_t *bus, uint8 *arg) -{ - dhd_pktgen_t pktgen; - - pktgen.version = DHD_PKTGEN_VERSION; - pktgen.freq = bus->pktgen_freq; - pktgen.count = bus->pktgen_count; - pktgen.print = bus->pktgen_print; - pktgen.total = bus->pktgen_total; - pktgen.minlen = bus->pktgen_minlen; - pktgen.maxlen = bus->pktgen_maxlen; - pktgen.numsent = bus->pktgen_sent; - pktgen.numrcvd = bus->pktgen_rcvd; - pktgen.numfail = bus->pktgen_fail; - pktgen.mode = bus->pktgen_mode; - pktgen.stop = bus->pktgen_stop; - - bcopy(&pktgen, arg, sizeof(pktgen)); - - return 0; -} - -static int -dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg) -{ - dhd_pktgen_t pktgen; - uint oldcnt, oldmode; - - bcopy(arg, &pktgen, sizeof(pktgen)); - if (pktgen.version != DHD_PKTGEN_VERSION) - return BCME_BADARG; - - oldcnt = bus->pktgen_count; - oldmode = bus->pktgen_mode; - - bus->pktgen_freq = pktgen.freq; - bus->pktgen_count = pktgen.count; - bus->pktgen_print = pktgen.print; - bus->pktgen_total = pktgen.total; - bus->pktgen_minlen = pktgen.minlen; - bus->pktgen_maxlen = pktgen.maxlen; - bus->pktgen_mode = pktgen.mode; - bus->pktgen_stop = pktgen.stop; - - bus->pktgen_tick = bus->pktgen_ptick = 0; - bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen); - bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen); - - /* Clear counts for a new pktgen (mode change, or was stopped) */ - if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) - bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0; - - return 0; -} -#endif /* SDTEST */ - -static int -dhdsdio_membytes(dhd_bus_t *bus, bool write, uint32 address, uint8 *data, uint size) -{ - int bcmerror = 0; - uint32 sdaddr; - uint dsize; - - /* Determine initial transfer parameters */ - sdaddr = address & SBSDIO_SB_OFT_ADDR_MASK; - if ((sdaddr + size) & SBSDIO_SBWINDOW_MASK) - dsize = (SBSDIO_SB_OFT_ADDR_LIMIT - sdaddr); - else - dsize = size; - - /* Set the backplane window to include the start address */ - if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { - DHD_ERROR(("%s: window change failed\n", __FUNCTION__)); - goto xfer_done; - } - - /* Do the transfer(s) */ - while (size) { - DHD_INFO(("%s: %s %d bytes at offset 0x%08x in window 0x%08x\n", - __FUNCTION__, (write ? "write" : "read"), dsize, sdaddr, - (address & SBSDIO_SBWINDOW_MASK))); - if ((bcmerror = bcmsdh_rwdata(bus->sdh, write, sdaddr, data, dsize))) { - DHD_ERROR(("%s: membytes transfer failed\n", __FUNCTION__)); - break; - } - - /* Adjust for next transfer (if any) */ - if ((size -= dsize)) { - data += dsize; - address += dsize; - if ((bcmerror = dhdsdio_set_siaddr_window(bus, address))) { - DHD_ERROR(("%s: window change failed\n", __FUNCTION__)); - break; - } - sdaddr = 0; - dsize = MIN(SBSDIO_SB_OFT_ADDR_LIMIT, size); - } - } - -xfer_done: - /* Return the window to backplane enumeration space for core access */ - if (dhdsdio_set_siaddr_window(bus, bcmsdh_cur_sbwad(bus->sdh))) { - DHD_ERROR(("%s: FAILED to set window back to 0x%x\n", __FUNCTION__, - bcmsdh_cur_sbwad(bus->sdh))); - } - - return bcmerror; -} - -#ifdef DHD_DEBUG -static int -dhdsdio_readshared(dhd_bus_t *bus, sdpcm_shared_t *sh) -{ - uint32 addr; - int rv; - - /* Read last word in memory to determine address of sdpcm_shared structure */ - if ((rv = dhdsdio_membytes(bus, FALSE, bus->ramsize - 4, (uint8 *)&addr, 4)) < 0) - return rv; - - addr = ltoh32(addr); - - DHD_INFO(("sdpcm_shared address 0x%08X\n", addr)); - - /* - * Check if addr is valid. - * NVRAM length at the end of memory should have been overwritten. - */ - if (addr == 0 || ((~addr >> 16) & 0xffff) == (addr & 0xffff)) { - DHD_ERROR(("%s: address (0x%08x) of sdpcm_shared invalid\n", __FUNCTION__, addr)); - return BCME_ERROR; - } - - /* Read hndrte_shared structure */ - if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)sh, sizeof(sdpcm_shared_t))) < 0) - return rv; - - /* Endianness */ - sh->flags = ltoh32(sh->flags); - sh->trap_addr = ltoh32(sh->trap_addr); - sh->assert_exp_addr = ltoh32(sh->assert_exp_addr); - sh->assert_file_addr = ltoh32(sh->assert_file_addr); - sh->assert_line = ltoh32(sh->assert_line); - sh->console_addr = ltoh32(sh->console_addr); - sh->msgtrace_addr = ltoh32(sh->msgtrace_addr); - - if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) { - DHD_ERROR(("%s: sdpcm_shared version %d in dhd " - "is different than sdpcm_shared version %d in dongle\n", - __FUNCTION__, SDPCM_SHARED_VERSION, - sh->flags & SDPCM_SHARED_VERSION_MASK)); - return BCME_ERROR; - } - - return BCME_OK; -} - -static int -dhdsdio_checkdied(dhd_bus_t *bus, uint8 *data, uint size) -{ - int bcmerror = 0; - uint msize = 512; - char *mbuffer = NULL; - uint maxstrlen = 256; - char *str = NULL; - trap_t tr; - sdpcm_shared_t sdpcm_shared; - struct bcmstrbuf strbuf; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (data == NULL) { - /* - * Called after a rx ctrl timeout. "data" is NULL. - * allocate memory to trace the trap or assert. - */ - size = msize; - mbuffer = data = MALLOC(bus->dhd->osh, msize); - if (mbuffer == NULL) { - DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, msize)); - bcmerror = BCME_NOMEM; - goto done; - } - } - - if ((str = MALLOC(bus->dhd->osh, maxstrlen)) == NULL) { - DHD_ERROR(("%s: MALLOC(%d) failed \n", __FUNCTION__, maxstrlen)); - bcmerror = BCME_NOMEM; - goto done; - } - - if ((bcmerror = dhdsdio_readshared(bus, &sdpcm_shared)) < 0) - goto done; - - bcm_binit(&strbuf, data, size); - - bcm_bprintf(&strbuf, "msgtrace address : 0x%08X\nconsole address : 0x%08X\n", - sdpcm_shared.msgtrace_addr, sdpcm_shared.console_addr); - - if ((sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) == 0) { - /* NOTE: Misspelled assert is intentional - DO NOT FIX. - * (Avoids conflict with real asserts for programmatic parsing of output.) - */ - bcm_bprintf(&strbuf, "Assrt not built in dongle\n"); - } - - if ((sdpcm_shared.flags & (SDPCM_SHARED_ASSERT|SDPCM_SHARED_TRAP)) == 0) { - /* NOTE: Misspelled assert is intentional - DO NOT FIX. - * (Avoids conflict with real asserts for programmatic parsing of output.) - */ - bcm_bprintf(&strbuf, "No trap%s in dongle", - (sdpcm_shared.flags & SDPCM_SHARED_ASSERT_BUILT) - ?"/assrt" :""); - } else { - if (sdpcm_shared.flags & SDPCM_SHARED_ASSERT) { - /* Download assert */ - bcm_bprintf(&strbuf, "Dongle assert"); - if (sdpcm_shared.assert_exp_addr != 0) { - str[0] = '\0'; - if ((bcmerror = dhdsdio_membytes(bus, FALSE, - sdpcm_shared.assert_exp_addr, - (uint8 *)str, maxstrlen)) < 0) - goto done; - - str[maxstrlen - 1] = '\0'; - bcm_bprintf(&strbuf, " expr \"%s\"", str); - } - - if (sdpcm_shared.assert_file_addr != 0) { - str[0] = '\0'; - if ((bcmerror = dhdsdio_membytes(bus, FALSE, - sdpcm_shared.assert_file_addr, - (uint8 *)str, maxstrlen)) < 0) - goto done; - - str[maxstrlen - 1] = '\0'; - bcm_bprintf(&strbuf, " file \"%s\"", str); - } - - bcm_bprintf(&strbuf, " line %d ", sdpcm_shared.assert_line); - } - - if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { - if ((bcmerror = dhdsdio_membytes(bus, FALSE, - sdpcm_shared.trap_addr, - (uint8*)&tr, sizeof(trap_t))) < 0) - goto done; - - bcm_bprintf(&strbuf, - "Dongle trap type 0x%x @ epc 0x%x, cpsr 0x%x, spsr 0x%x, sp 0x%x," - "lp 0x%x, rpc 0x%x Trap offset 0x%x, " - "r0 0x%x, r1 0x%x, r2 0x%x, r3 0x%x, r4 0x%x, r5 0x%x, r6 0x%x, r7 0x%x\n", - tr.type, tr.epc, tr.cpsr, tr.spsr, tr.r13, tr.r14, tr.pc, - sdpcm_shared.trap_addr, - tr.r0, tr.r1, tr.r2, tr.r3, tr.r4, tr.r5, tr.r6, tr.r7); - } - } - - if (sdpcm_shared.flags & (SDPCM_SHARED_ASSERT | SDPCM_SHARED_TRAP)) { - DHD_ERROR(("%s: %s\n", __FUNCTION__, strbuf.origbuf)); - } - -#ifdef DHD_DEBUG - if (sdpcm_shared.flags & SDPCM_SHARED_TRAP) { - /* Mem dump to a file on device */ - dhdsdio_mem_dump(bus); - } -#endif /* DHD_DEBUG */ - -done: - if (mbuffer) - MFREE(bus->dhd->osh, mbuffer, msize); - if (str) - MFREE(bus->dhd->osh, str, maxstrlen); - - return bcmerror; -} - -static int -dhdsdio_mem_dump(dhd_bus_t *bus) -{ - int ret = 0; - int size; /* Full mem size */ - int start = 0; /* Start address */ - int read_size = 0; /* Read size of each iteration */ - uint8 *buf = NULL, *databuf = NULL; - - /* Get full mem size */ - size = bus->ramsize; - buf = MALLOC(bus->dhd->osh, size); - if (!buf) { - printf("%s: Out of memory (%d bytes)\n", __FUNCTION__, size); - return -1; - } - - /* Read mem content */ - printf("Dump dongle memory"); - databuf = buf; - while (size) - { - read_size = MIN(MEMBLOCK, size); - if ((ret = dhdsdio_membytes(bus, FALSE, start, databuf, read_size))) - { - printf("%s: Error membytes %d\n", __FUNCTION__, ret); - if (buf) { - MFREE(bus->dhd->osh, buf, size); - } - return -1; - } - printf("."); - - /* Decrement size and increment start address */ - size -= read_size; - start += read_size; - databuf += read_size; - } - printf("Done\n"); - - /* free buf before return !!! */ - if (write_to_file(bus->dhd, buf, bus->ramsize)) - { - printf("%s: Error writing to files\n", __FUNCTION__); - return -1; - } - - /* buf free handled in write_to_file, not here */ - return 0; -} - -#define CONSOLE_LINE_MAX 192 - -static int -dhdsdio_readconsole(dhd_bus_t *bus) -{ - dhd_console_t *c = &bus->console; - uint8 line[CONSOLE_LINE_MAX], ch; - uint32 n, idx, addr; - int rv; - - /* Don't do anything until FWREADY updates console address */ - if (bus->console_addr == 0) - return 0; - - /* Read console log struct */ - addr = bus->console_addr + OFFSETOF(hndrte_cons_t, log); - if ((rv = dhdsdio_membytes(bus, FALSE, addr, (uint8 *)&c->log, sizeof(c->log))) < 0) - return rv; - - /* Allocate console buffer (one time only) */ - if (c->buf == NULL) { - c->bufsize = ltoh32(c->log.buf_size); - if ((c->buf = MALLOC(bus->dhd->osh, c->bufsize)) == NULL) - return BCME_NOMEM; - } - - idx = ltoh32(c->log.idx); - - /* Protect against corrupt value */ - if (idx > c->bufsize) - return BCME_ERROR; - - /* Skip reading the console buffer if the index pointer has not moved */ - if (idx == c->last) - return BCME_OK; - - /* Read the console buffer */ - addr = ltoh32(c->log.buf); - if ((rv = dhdsdio_membytes(bus, FALSE, addr, c->buf, c->bufsize)) < 0) - return rv; - - while (c->last != idx) { - for (n = 0; n < CONSOLE_LINE_MAX - 2; n++) { - if (c->last == idx) { - /* This would output a partial line. Instead, back up - * the buffer pointer and output this line next time around. - */ - if (c->last >= n) - c->last -= n; - else - c->last = c->bufsize - n; - goto break2; - } - ch = c->buf[c->last]; - c->last = (c->last + 1) % c->bufsize; - if (ch == '\n') - break; - line[n] = ch; - } - - if (n > 0) { - if (line[n - 1] == '\r') - n--; - line[n] = 0; - printf("CONSOLE: %s\n", line); - } - } -break2: - - return BCME_OK; -} -#endif /* DHD_DEBUG */ - -int -dhdsdio_downloadvars(dhd_bus_t *bus, void *arg, int len) -{ - int bcmerror = BCME_OK; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Basic sanity checks */ - if (bus->dhd->up) { - bcmerror = BCME_NOTDOWN; - goto err; - } - if (!len) { - bcmerror = BCME_BUFTOOSHORT; - goto err; - } - - /* Free the old ones and replace with passed variables */ - if (bus->vars) - MFREE(bus->dhd->osh, bus->vars, bus->varsz); - - bus->vars = MALLOC(bus->dhd->osh, len); - bus->varsz = bus->vars ? len : 0; - if (bus->vars == NULL) { - bcmerror = BCME_NOMEM; - goto err; - } - - /* Copy the passed variables, which should include the terminating double-null */ - bcopy(arg, bus->vars, bus->varsz); -err: - return bcmerror; -} - -static int -dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const char *name, - void *params, int plen, void *arg, int len, int val_size) -{ - int bcmerror = 0; - int32 int_val = 0; - bool bool_val = 0; - - DHD_TRACE(("%s: Enter, action %d name %s params %p plen %d arg %p len %d val_size %d\n", - __FUNCTION__, actionid, name, params, plen, arg, len, val_size)); - - if ((bcmerror = bcm_iovar_lencheck(vi, arg, len, IOV_ISSET(actionid))) != 0) - goto exit; - - if (plen >= (int)sizeof(int_val)) - bcopy(params, &int_val, sizeof(int_val)); - - bool_val = (int_val != 0) ? TRUE : FALSE; - - - /* Some ioctls use the bus */ - dhd_os_sdlock(bus->dhd); - - /* Check if dongle is in reset. If so, only allow DEVRESET iovars */ - if (bus->dhd->dongle_reset && !(actionid == IOV_SVAL(IOV_DEVRESET) || - actionid == IOV_GVAL(IOV_DEVRESET))) { - bcmerror = BCME_NOTREADY; - goto exit; - } - - /* Handle sleep stuff before any clock mucking */ - if (vi->varid == IOV_SLEEP) { - if (IOV_ISSET(actionid)) { - bcmerror = dhdsdio_bussleep(bus, bool_val); - } else { - int_val = (int32)bus->sleeping; - bcopy(&int_val, arg, val_size); - } - goto exit; - } - - /* Request clock to allow SDIO accesses */ - if (!bus->dhd->dongle_reset) { - BUS_WAKE(bus); - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - } - - switch (actionid) { - case IOV_GVAL(IOV_INTR): - int_val = (int32)bus->intr; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_INTR): - bus->intr = bool_val; - bus->intdis = FALSE; - if (bus->dhd->up) { - if (bus->intr) { - DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__)); - bcmsdh_intr_enable(bus->sdh); - } else { - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - bcmsdh_intr_disable(bus->sdh); - } - } - break; - - case IOV_GVAL(IOV_POLLRATE): - int_val = (int32)bus->pollrate; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_POLLRATE): - bus->pollrate = (uint)int_val; - bus->poll = (bus->pollrate != 0); - break; - - case IOV_GVAL(IOV_IDLETIME): - int_val = bus->idletime; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_IDLETIME): - if ((int_val < 0) && (int_val != DHD_IDLE_IMMEDIATE)) { - bcmerror = BCME_BADARG; - } else { - bus->idletime = int_val; - } - break; - - case IOV_GVAL(IOV_IDLECLOCK): - int_val = (int32)bus->idleclock; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_IDLECLOCK): - bus->idleclock = int_val; - break; - - case IOV_GVAL(IOV_SD1IDLE): - int_val = (int32)sd1idle; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SD1IDLE): - sd1idle = bool_val; - break; - - - case IOV_SVAL(IOV_MEMBYTES): - case IOV_GVAL(IOV_MEMBYTES): - { - uint32 address; - uint size, dsize; - uint8 *data; - - bool set = (actionid == IOV_SVAL(IOV_MEMBYTES)); - - ASSERT(plen >= 2*sizeof(int)); - - address = (uint32)int_val; - bcopy((char *)params + sizeof(int_val), &int_val, sizeof(int_val)); - size = (uint)int_val; - - /* Do some validation */ - dsize = set ? plen - (2 * sizeof(int)) : len; - if (dsize < size) { - DHD_ERROR(("%s: error on %s membytes, addr 0x%08x size %d dsize %d\n", - __FUNCTION__, (set ? "set" : "get"), address, size, dsize)); - bcmerror = BCME_BADARG; - break; - } - - DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__, - (set ? "write" : "read"), size, address)); - - /* If we know about SOCRAM, check for a fit */ - if ((bus->orig_ramsize) && - ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) { - DHD_ERROR(("%s: ramsize 0x%08x doesn't have %d bytes at 0x%08x\n", - __FUNCTION__, bus->orig_ramsize, size, address)); - bcmerror = BCME_BADARG; - break; - } - - /* Generate the actual data pointer */ - data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg; - - /* Call to do the transfer */ - bcmerror = dhdsdio_membytes(bus, set, address, data, size); - - break; - } - - case IOV_GVAL(IOV_MEMSIZE): - int_val = (int32)bus->ramsize; - bcopy(&int_val, arg, val_size); - break; - - case IOV_GVAL(IOV_SDIOD_DRIVE): - int_val = (int32)dhd_sdiod_drive_strength; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SDIOD_DRIVE): - dhd_sdiod_drive_strength = int_val; - si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh, dhd_sdiod_drive_strength); - break; - - case IOV_SVAL(IOV_DOWNLOAD): - bcmerror = dhdsdio_download_state(bus, bool_val); - break; - - case IOV_SVAL(IOV_VARS): - bcmerror = dhdsdio_downloadvars(bus, arg, len); - break; - - case IOV_GVAL(IOV_READAHEAD): - int_val = (int32)dhd_readahead; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_READAHEAD): - if (bool_val && !dhd_readahead) - bus->nextlen = 0; - dhd_readahead = bool_val; - break; - - case IOV_GVAL(IOV_SDRXCHAIN): - int_val = (int32)bus->use_rxchain; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_SDRXCHAIN): - if (bool_val && !bus->sd_rxchain) - bcmerror = BCME_UNSUPPORTED; - else - bus->use_rxchain = bool_val; - break; - case IOV_GVAL(IOV_ALIGNCTL): - int_val = (int32)dhd_alignctl; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_ALIGNCTL): - dhd_alignctl = bool_val; - break; - - case IOV_GVAL(IOV_SDALIGN): - int_val = DHD_SDALIGN; - bcopy(&int_val, arg, val_size); - break; - -#ifdef DHD_DEBUG - case IOV_GVAL(IOV_VARS): - if (bus->varsz < (uint)len) - bcopy(bus->vars, arg, bus->varsz); - else - bcmerror = BCME_BUFTOOSHORT; - break; -#endif /* DHD_DEBUG */ - -#ifdef DHD_DEBUG - case IOV_GVAL(IOV_SDREG): - { - sdreg_t *sd_ptr; - uint32 addr, size; - - sd_ptr = (sdreg_t *)params; - - addr = (uintptr)bus->regs + sd_ptr->offset; - size = sd_ptr->func; - int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); - if (bcmsdh_regfail(bus->sdh)) - bcmerror = BCME_SDIO_ERROR; - bcopy(&int_val, arg, sizeof(int32)); - break; - } - - case IOV_SVAL(IOV_SDREG): - { - sdreg_t *sd_ptr; - uint32 addr, size; - - sd_ptr = (sdreg_t *)params; - - addr = (uintptr)bus->regs + sd_ptr->offset; - size = sd_ptr->func; - bcmsdh_reg_write(bus->sdh, addr, size, sd_ptr->value); - if (bcmsdh_regfail(bus->sdh)) - bcmerror = BCME_SDIO_ERROR; - break; - } - - /* Same as above, but offset is not backplane (not SDIO core) */ - case IOV_GVAL(IOV_SBREG): - { - sdreg_t sdreg; - uint32 addr, size; - - bcopy(params, &sdreg, sizeof(sdreg)); - - addr = SI_ENUM_BASE + sdreg.offset; - size = sdreg.func; - int_val = (int32)bcmsdh_reg_read(bus->sdh, addr, size); - if (bcmsdh_regfail(bus->sdh)) - bcmerror = BCME_SDIO_ERROR; - bcopy(&int_val, arg, sizeof(int32)); - break; - } - - case IOV_SVAL(IOV_SBREG): - { - sdreg_t sdreg; - uint32 addr, size; - - bcopy(params, &sdreg, sizeof(sdreg)); - - addr = SI_ENUM_BASE + sdreg.offset; - size = sdreg.func; - bcmsdh_reg_write(bus->sdh, addr, size, sdreg.value); - if (bcmsdh_regfail(bus->sdh)) - bcmerror = BCME_SDIO_ERROR; - break; - } - - case IOV_GVAL(IOV_SDCIS): - { - *(char *)arg = 0; - - bcmstrcat(arg, "\nFunc 0\n"); - bcmsdh_cis_read(bus->sdh, 0x10, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); - bcmstrcat(arg, "\nFunc 1\n"); - bcmsdh_cis_read(bus->sdh, 0x11, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); - bcmstrcat(arg, "\nFunc 2\n"); - bcmsdh_cis_read(bus->sdh, 0x12, (uint8 *)arg + strlen(arg), SBSDIO_CIS_SIZE_LIMIT); - break; - } - - case IOV_GVAL(IOV_FORCEEVEN): - int_val = (int32)forcealign; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_FORCEEVEN): - forcealign = bool_val; - break; - - case IOV_GVAL(IOV_TXBOUND): - int_val = (int32)dhd_txbound; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_TXBOUND): - dhd_txbound = (uint)int_val; - break; - - case IOV_GVAL(IOV_RXBOUND): - int_val = (int32)dhd_rxbound; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_RXBOUND): - dhd_rxbound = (uint)int_val; - break; - - case IOV_GVAL(IOV_TXMINMAX): - int_val = (int32)dhd_txminmax; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_TXMINMAX): - dhd_txminmax = (uint)int_val; - break; - - - -#endif /* DHD_DEBUG */ - - -#ifdef SDTEST - case IOV_GVAL(IOV_EXTLOOP): - int_val = (int32)bus->ext_loop; - bcopy(&int_val, arg, val_size); - break; - - case IOV_SVAL(IOV_EXTLOOP): - bus->ext_loop = bool_val; - break; - - case IOV_GVAL(IOV_PKTGEN): - bcmerror = dhdsdio_pktgen_get(bus, arg); - break; - - case IOV_SVAL(IOV_PKTGEN): - bcmerror = dhdsdio_pktgen_set(bus, arg); - break; -#endif /* SDTEST */ - - - case IOV_SVAL(IOV_DEVRESET): - DHD_TRACE(("%s: Called set IOV_DEVRESET=%d dongle_reset=%d busstate=%d\n", - __FUNCTION__, bool_val, bus->dhd->dongle_reset, - bus->dhd->busstate)); - - ASSERT(bus->dhd->osh); - /* ASSERT(bus->cl_devid); */ - - dhd_bus_devreset(bus->dhd, (uint8)bool_val); - - break; - - case IOV_GVAL(IOV_DEVRESET): - DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__)); - - /* Get its status */ - int_val = (bool) bus->dhd->dongle_reset; - bcopy(&int_val, arg, val_size); - - break; - - default: - bcmerror = BCME_UNSUPPORTED; - break; - } - -exit: - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { - bus->activity = FALSE; - dhdsdio_clkctl(bus, CLK_NONE, TRUE); - } - - dhd_os_sdunlock(bus->dhd); - - if (actionid == IOV_SVAL(IOV_DEVRESET) && bool_val == FALSE) - dhd_preinit_ioctls((dhd_pub_t *) bus->dhd); - - return bcmerror; -} - -static int -dhdsdio_write_vars(dhd_bus_t *bus) -{ - int bcmerror = 0; - uint32 varsize; - uint32 varaddr; - uint8 *vbuffer; - uint32 varsizew; -#ifdef DHD_DEBUG - char *nvram_ularray; -#endif /* DHD_DEBUG */ - - /* Even if there are no vars are to be written, we still need to set the ramsize. */ - varsize = bus->varsz ? ROUNDUP(bus->varsz, 4) : 0; - varaddr = (bus->ramsize - 4) - varsize; - - if (bus->vars) { - vbuffer = (uint8 *)MALLOC(bus->dhd->osh, varsize); - if (!vbuffer) - return BCME_NOMEM; - - bzero(vbuffer, varsize); - bcopy(bus->vars, vbuffer, bus->varsz); - - /* Write the vars list */ - bcmerror = dhdsdio_membytes(bus, TRUE, varaddr, vbuffer, varsize); -#ifdef DHD_DEBUG - /* Verify NVRAM bytes */ - DHD_INFO(("Compare NVRAM dl & ul; varsize=%d\n", varsize)); - nvram_ularray = (char*)MALLOC(bus->dhd->osh, varsize); - if (!nvram_ularray) - return BCME_NOMEM; - - /* Upload image to verify downloaded contents. */ - memset(nvram_ularray, 0xaa, varsize); - - /* Read the vars list to temp buffer for comparison */ - bcmerror = dhdsdio_membytes(bus, FALSE, varaddr, nvram_ularray, varsize); - if (bcmerror) { - DHD_ERROR(("%s: error %d on reading %d nvram bytes at 0x%08x\n", - __FUNCTION__, bcmerror, varsize, varaddr)); - } - /* Compare the org NVRAM with the one read from RAM */ - if (memcmp(vbuffer, nvram_ularray, varsize)) { - DHD_ERROR(("%s: Downloaded NVRAM image is corrupted.\n", __FUNCTION__)); - } else - DHD_ERROR(("%s: Download, Upload and compare of NVRAM succeeded.\n", - __FUNCTION__)); - - MFREE(bus->dhd->osh, nvram_ularray, varsize); -#endif /* DHD_DEBUG */ - - MFREE(bus->dhd->osh, vbuffer, varsize); - } - - /* adjust to the user specified RAM */ - DHD_INFO(("Physical memory size: %d, usable memory size: %d\n", - bus->orig_ramsize, bus->ramsize)); - DHD_INFO(("Vars are at %d, orig varsize is %d\n", - varaddr, varsize)); - varsize = ((bus->orig_ramsize - 4) - varaddr); - - /* - * Determine the length token: - * Varsize, converted to words, in lower 16-bits, checksum in upper 16-bits. - */ - if (bcmerror) { - varsizew = 0; - } else { - varsizew = varsize / 4; - varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF); - varsizew = htol32(varsizew); - } - - DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize, varsizew)); - - /* Write the length token to the last word */ - bcmerror = dhdsdio_membytes(bus, TRUE, (bus->orig_ramsize - 4), - (uint8*)&varsizew, 4); - - return bcmerror; -} - -static int -dhdsdio_download_state(dhd_bus_t *bus, bool enter) -{ - uint retries; - int bcmerror = 0; - - /* To enter download state, disable ARM and reset SOCRAM. - * To exit download state, simply reset ARM (default is RAM boot). - */ - if (enter) { - - bus->alp_only = TRUE; - - if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && - !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - - si_core_disable(bus->sih, 0); - if (bcmsdh_regfail(bus->sdh)) { - bcmerror = BCME_SDIO_ERROR; - goto fail; - } - - if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - - si_core_reset(bus->sih, 0, 0); - if (bcmsdh_regfail(bus->sdh)) { - DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__)); - bcmerror = BCME_SDIO_ERROR; - goto fail; - } - - /* Clear the top bit of memory */ - if (bus->ramsize) { - uint32 zeros = 0; - dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4); - } - } else { - if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - - if (!si_iscoreup(bus->sih)) { - DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - - if ((bcmerror = dhdsdio_write_vars(bus))) { - DHD_ERROR(("%s: no vars written to RAM\n", __FUNCTION__)); - bcmerror = 0; - } - - if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && - !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { - DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); - - - if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && - !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - - si_core_reset(bus->sih, 0, 0); - if (bcmsdh_regfail(bus->sdh)) { - DHD_ERROR(("%s: Failure trying to reset ARM core?\n", __FUNCTION__)); - bcmerror = BCME_SDIO_ERROR; - goto fail; - } - - /* Allow HT Clock now that the ARM is running. */ - bus->alp_only = FALSE; - - bus->dhd->busstate = DHD_BUS_LOAD; - } - -fail: - /* Always return to SDIOD core */ - if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) - si_setcore(bus->sih, SDIOD_CORE_ID, 0); - - return bcmerror; -} - -int -dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, - void *params, int plen, void *arg, int len, bool set) -{ - dhd_bus_t *bus = dhdp->bus; - const bcm_iovar_t *vi = NULL; - int bcmerror = 0; - int val_size; - uint32 actionid; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - ASSERT(name); - ASSERT(len >= 0); - - /* Get MUST have return space */ - ASSERT(set || (arg && len)); - - /* Set does NOT take qualifiers */ - ASSERT(!set || (!params && !plen)); - - /* Look up var locally; if not found pass to host driver */ - if ((vi = bcm_iovar_lookup(dhdsdio_iovars, name)) == NULL) { - dhd_os_sdlock(bus->dhd); - - BUS_WAKE(bus); - - /* Turn on clock in case SD command needs backplane */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - bcmerror = bcmsdh_iovar_op(bus->sdh, name, params, plen, arg, len, set); - - /* Check for bus configuration changes of interest */ - - /* If it was divisor change, read the new one */ - if (set && strcmp(name, "sd_divisor") == 0) { - if (bcmsdh_iovar_op(bus->sdh, "sd_divisor", NULL, 0, - &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) { - bus->sd_divisor = -1; - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name)); - } else { - DHD_INFO(("%s: noted %s update, value now %d\n", - __FUNCTION__, name, bus->sd_divisor)); - } - } - /* If it was a mode change, read the new one */ - if (set && strcmp(name, "sd_mode") == 0) { - if (bcmsdh_iovar_op(bus->sdh, "sd_mode", NULL, 0, - &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) { - bus->sd_mode = -1; - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, name)); - } else { - DHD_INFO(("%s: noted %s update, value now %d\n", - __FUNCTION__, name, bus->sd_mode)); - } - } - /* Similar check for blocksize change */ - if (set && strcmp(name, "sd_blocksize") == 0) { - int32 fnum = 2; - if (bcmsdh_iovar_op(bus->sdh, "sd_blocksize", &fnum, sizeof(int32), - &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { - bus->blocksize = 0; - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); - } else { - DHD_INFO(("%s: noted %s update, value now %d\n", - __FUNCTION__, "sd_blocksize", bus->blocksize)); - } - } - bus->roundup = MIN(max_roundup, bus->blocksize); - - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { - bus->activity = FALSE; - dhdsdio_clkctl(bus, CLK_NONE, TRUE); - } - - dhd_os_sdunlock(bus->dhd); - goto exit; - } - - DHD_CTL(("%s: %s %s, len %d plen %d\n", __FUNCTION__, - name, (set ? "set" : "get"), len, plen)); - - /* set up 'params' pointer in case this is a set command so that - * the convenience int and bool code can be common to set and get - */ - if (params == NULL) { - params = arg; - plen = len; - } - - if (vi->type == IOVT_VOID) - val_size = 0; - else if (vi->type == IOVT_BUFFER) - val_size = len; - else - /* all other types are integer sized */ - val_size = sizeof(int); - - actionid = set ? IOV_SVAL(vi->varid) : IOV_GVAL(vi->varid); - bcmerror = dhdsdio_doiovar(bus, vi, actionid, name, params, plen, arg, len, val_size); - -exit: - return bcmerror; -} - -void -dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) -{ - osl_t *osh = bus->dhd->osh; - uint32 local_hostintmask; - uint8 saveclk; - uint retries; - int err; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (enforce_mutex) - dhd_os_sdlock(bus->dhd); - - BUS_WAKE(bus); - - /* Enable clock for device interrupts */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - /* Disable and clear interrupts at the chip level also */ - W_SDREG(0, &bus->regs->hostintmask, retries); - local_hostintmask = bus->hostintmask; - bus->hostintmask = 0; - - /* Change our idea of bus state */ - bus->dhd->busstate = DHD_BUS_DOWN; - - /* Force clocks on backplane to be sure F2 interrupt propagates */ - saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (!err) { - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - (saveclk | SBSDIO_FORCE_HT), &err); - } - if (err) { - DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); - } - - /* Turn off the bus (F2), free any pending packets */ - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - bcmsdh_intr_disable(bus->sdh); - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); - - /* Clear any pending interrupts now that F2 is disabled */ - W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); - - /* Turn off the backplane clock (only) */ - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); - - /* Clear the data packet queues */ - pktq_flush(osh, &bus->txq, TRUE); - - /* Clear any held glomming stuff */ - if (bus->glomd) - PKTFREE(osh, bus->glomd, FALSE); - - if (bus->glom) - PKTFREE(osh, bus->glom, FALSE); - - bus->glom = bus->glomd = NULL; - - /* Clear rx control and wake any waiters */ - bus->rxlen = 0; - dhd_os_ioctl_resp_wake(bus->dhd); - - /* Reset some F2 state stuff */ - bus->rxskip = FALSE; - bus->tx_seq = bus->rx_seq = 0; - - if (enforce_mutex) - dhd_os_sdunlock(bus->dhd); -} - -int -dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) -{ - dhd_bus_t *bus = dhdp->bus; - dhd_timeout_t tmo; - uint retries = 0; - uint8 ready, enable; - int err, ret = 0; - uint8 saveclk; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - ASSERT(bus->dhd); - if (!bus->dhd) - return 0; - - if (enforce_mutex) - dhd_os_sdlock(bus->dhd); - - /* Make sure backplane clock is on, needed to generate F2 interrupt */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - if (bus->clkstate != CLK_AVAIL) - goto exit; - - - /* Force clocks on backplane to be sure F2 interrupt propagates */ - saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (!err) { - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - (saveclk | SBSDIO_FORCE_HT), &err); - } - if (err) { - DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); - goto exit; - } - - /* Enable function 2 (frame transfers) */ - W_SDREG((SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT), - &bus->regs->tosbmailboxdata, retries); - enable = (SDIO_FUNC_ENABLE_1 | SDIO_FUNC_ENABLE_2); - - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); - - /* Give the dongle some time to do its thing and set IOR2 */ - dhd_timeout_start(&tmo, DHD_WAIT_F2RDY * 1000); - - ready = 0; - while (ready != enable && !dhd_timeout_expired(&tmo)) - ready = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IORDY, NULL); - - - DHD_INFO(("%s: enable 0x%02x, ready 0x%02x (waited %uus)\n", - __FUNCTION__, enable, ready, tmo.elapsed)); - - - /* If F2 successfully enabled, set core and enable interrupts */ - if (ready == enable) { - /* Make sure we're talking to the core. */ - if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0))) - bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0); - - /* Set up the interrupt mask and enable interrupts */ - bus->hostintmask = HOSTINTMASK; - W_SDREG(bus->hostintmask, &bus->regs->hostintmask, retries); - - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); - - /* Set bus state according to enable result */ - dhdp->busstate = DHD_BUS_DATA; - - /* bcmsdh_intr_unmask(bus->sdh); */ - - bus->intdis = FALSE; - if (bus->intr) { - DHD_INTR(("%s: enable SDIO device interrupts\n", __FUNCTION__)); - bcmsdh_intr_enable(bus->sdh); - } else { - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - bcmsdh_intr_disable(bus->sdh); - } - - } - - - else { - /* Disable F2 again */ - enable = SDIO_FUNC_ENABLE_1; - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, enable, NULL); - } - - /* Restore previous clock setting */ - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, saveclk, &err); - - - /* If we didn't come up, turn off backplane clock */ - if (dhdp->busstate != DHD_BUS_DATA) - dhdsdio_clkctl(bus, CLK_NONE, FALSE); - -exit: - if (enforce_mutex) - dhd_os_sdunlock(bus->dhd); - - return ret; -} - -static void -dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx) -{ - bcmsdh_info_t *sdh = bus->sdh; - sdpcmd_regs_t *regs = bus->regs; - uint retries = 0; - uint16 lastrbc; - uint8 hi, lo; - int err; - - DHD_ERROR(("%s: %sterminate frame%s\n", __FUNCTION__, - (abort ? "abort command, " : ""), (rtx ? ", send NAK" : ""))); - - if (abort) { - bcmsdh_abort(sdh, SDIO_FUNC_2); - } - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); - bus->f1regdata++; - - /* Wait until the packet has been flushed (device/FIFO stable) */ - for (lastrbc = retries = 0xffff; retries > 0; retries--) { - hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL); - lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL); - bus->f1regdata += 2; - - if ((hi == 0) && (lo == 0)) - break; - - if ((hi > (lastrbc >> 8)) && (lo > (lastrbc & 0x00ff))) { - DHD_ERROR(("%s: count growing: last 0x%04x now 0x%04x\n", - __FUNCTION__, lastrbc, ((hi << 8) + lo))); - } - lastrbc = (hi << 8) + lo; - } - - if (!retries) { - DHD_ERROR(("%s: count never zeroed: last 0x%04x\n", __FUNCTION__, lastrbc)); - } else { - DHD_INFO(("%s: flush took %d iterations\n", __FUNCTION__, (0xffff - retries))); - } - - if (rtx) { - bus->rxrtx++; - W_SDREG(SMB_NAK, ®s->tosbmailbox, retries); - bus->f1regdata++; - if (retries <= retry_limit) { - bus->rxskip = TRUE; - } - } - - /* Clear partial in any case */ - bus->nextlen = 0; - - /* If we can't reach the device, signal failure */ - if (err || bcmsdh_regfail(sdh)) - bus->dhd->busstate = DHD_BUS_DOWN; -} - -static void -dhdsdio_read_control(dhd_bus_t *bus, uint8 *hdr, uint len, uint doff) -{ - bcmsdh_info_t *sdh = bus->sdh; - uint rdlen, pad; - - int sdret; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Control data already received in aligned rxctl */ - if ((bus->bus == SPI_BUS) && (!bus->usebufpool)) - goto gotpkt; - - ASSERT(bus->rxbuf); - /* Set rxctl for frame (w/optional alignment) */ - bus->rxctl = bus->rxbuf; - if (dhd_alignctl) { - bus->rxctl += firstread; - if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN))) - bus->rxctl += (DHD_SDALIGN - pad); - bus->rxctl -= firstread; - } - ASSERT(bus->rxctl >= bus->rxbuf); - - /* Copy the already-read portion over */ - bcopy(hdr, bus->rxctl, firstread); - if (len <= firstread) - goto gotpkt; - - /* Copy the full data pkt in gSPI case and process ioctl. */ - if (bus->bus == SPI_BUS) { - bcopy(hdr, bus->rxctl, len); - goto gotpkt; - } - - /* Raise rdlen to next SDIO block to avoid tail command */ - rdlen = len - firstread; - if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { - pad = bus->blocksize - (rdlen % bus->blocksize); - if ((pad <= bus->roundup) && (pad < bus->blocksize) && - ((len + pad) < bus->dhd->maxctl)) - rdlen += pad; - } else if (rdlen % DHD_SDALIGN) { - rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); - } - - /* Satisfy length-alignment requirements */ - if (forcealign && (rdlen & (ALIGNMENT - 1))) - rdlen = ROUNDUP(rdlen, ALIGNMENT); - - /* Drop if the read is too big or it exceeds our maximum */ - if ((rdlen + firstread) > bus->dhd->maxctl) { - DHD_ERROR(("%s: %d-byte control read exceeds %d-byte buffer\n", - __FUNCTION__, rdlen, bus->dhd->maxctl)); - bus->dhd->rx_errors++; - dhdsdio_rxfail(bus, FALSE, FALSE); - goto done; - } - - if ((len - doff) > bus->dhd->maxctl) { - DHD_ERROR(("%s: %d-byte ctl frame (%d-byte ctl data) exceeds %d-byte limit\n", - __FUNCTION__, len, (len - doff), bus->dhd->maxctl)); - bus->dhd->rx_errors++; bus->rx_toolong++; - dhdsdio_rxfail(bus, FALSE, FALSE); - goto done; - } - - - /* Read remainder of frame body into the rxctl buffer */ - sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - (bus->rxctl + firstread), rdlen, NULL, NULL, NULL); - bus->f2rxdata++; - ASSERT(sdret != BCME_PENDING); - - /* Control frame failures need retransmission */ - if (sdret < 0) { - DHD_ERROR(("%s: read %d control bytes failed: %d\n", __FUNCTION__, rdlen, sdret)); - bus->rxc_errors++; /* dhd.rx_ctlerrs is higher level */ - dhdsdio_rxfail(bus, TRUE, TRUE); - goto done; - } - -gotpkt: - -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() && DHD_CTL_ON()) { - prhex("RxCtrl", bus->rxctl, len); - } -#endif - - /* Point to valid data and indicate its length */ - bus->rxctl += doff; - bus->rxlen = len - doff; - -done: - /* Awake any waiters */ - dhd_os_ioctl_resp_wake(bus->dhd); -} - -static uint8 -dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) -{ - uint16 dlen, totlen; - uint8 *dptr, num = 0; - - uint16 sublen, check; - void *pfirst, *plast, *pnext, *save_pfirst; - osl_t *osh = bus->dhd->osh; - - int errcode; - uint8 chan, seq, doff, sfdoff; - uint8 txmax; - - int ifidx = 0; - bool usechain = bus->use_rxchain; - - /* If packets, issue read(s) and send up packet chain */ - /* Return sequence numbers consumed? */ - - DHD_TRACE(("dhdsdio_rxglom: start: glomd %p glom %p\n", bus->glomd, bus->glom)); - - /* If there's a descriptor, generate the packet chain */ - if (bus->glomd) { - dhd_os_sdlock_rxq(bus->dhd); - - pfirst = plast = pnext = NULL; - dlen = (uint16)PKTLEN(osh, bus->glomd); - dptr = PKTDATA(osh, bus->glomd); - if (!dlen || (dlen & 1)) { - DHD_ERROR(("%s: bad glomd len (%d), ignore descriptor\n", - __FUNCTION__, dlen)); - dlen = 0; - } - - for (totlen = num = 0; dlen; num++) { - /* Get (and move past) next length */ - sublen = ltoh16_ua(dptr); - dlen -= sizeof(uint16); - dptr += sizeof(uint16); - if ((sublen < SDPCM_HDRLEN) || - ((num == 0) && (sublen < (2 * SDPCM_HDRLEN)))) { - DHD_ERROR(("%s: descriptor len %d bad: %d\n", - __FUNCTION__, num, sublen)); - pnext = NULL; - break; - } - if (sublen % DHD_SDALIGN) { - DHD_ERROR(("%s: sublen %d not a multiple of %d\n", - __FUNCTION__, sublen, DHD_SDALIGN)); - usechain = FALSE; - } - totlen += sublen; - - /* For last frame, adjust read len so total is a block multiple */ - if (!dlen) { - sublen += (ROUNDUP(totlen, bus->blocksize) - totlen); - totlen = ROUNDUP(totlen, bus->blocksize); - } - - /* Allocate/chain packet for next subframe */ - if ((pnext = PKTGET(osh, sublen + DHD_SDALIGN, FALSE)) == NULL) { - DHD_ERROR(("%s: PKTGET failed, num %d len %d\n", - __FUNCTION__, num, sublen)); - break; - } - ASSERT(!PKTLINK(pnext)); - if (!pfirst) { - ASSERT(!plast); - pfirst = plast = pnext; - } else { - ASSERT(plast); - PKTSETNEXT(osh, plast, pnext); - plast = pnext; - } - - /* Adhere to start alignment requirements */ - PKTALIGN(osh, pnext, sublen, DHD_SDALIGN); - } - - /* If all allocations succeeded, save packet chain in bus structure */ - if (pnext) { - DHD_GLOM(("%s: allocated %d-byte packet chain for %d subframes\n", - __FUNCTION__, totlen, num)); - if (DHD_GLOM_ON() && bus->nextlen) { - if (totlen != bus->nextlen) { - DHD_GLOM(("%s: glomdesc mismatch: nextlen %d glomdesc %d " - "rxseq %d\n", __FUNCTION__, bus->nextlen, - totlen, rxseq)); - } - } - bus->glom = pfirst; - pfirst = pnext = NULL; - } else { - if (pfirst) - PKTFREE(osh, pfirst, FALSE); - bus->glom = NULL; - num = 0; - } - - /* Done with descriptor packet */ - PKTFREE(osh, bus->glomd, FALSE); - bus->glomd = NULL; - bus->nextlen = 0; - - dhd_os_sdunlock_rxq(bus->dhd); - } - - /* Ok -- either we just generated a packet chain, or had one from before */ - if (bus->glom) { - if (DHD_GLOM_ON()) { - DHD_GLOM(("%s: attempt superframe read, packet chain:\n", __FUNCTION__)); - for (pnext = bus->glom; pnext; pnext = PKTNEXT(osh, pnext)) { - DHD_GLOM((" %p: %p len 0x%04x (%d)\n", - pnext, (uint8*)PKTDATA(osh, pnext), - PKTLEN(osh, pnext), PKTLEN(osh, pnext))); - } - } - - pfirst = bus->glom; - dlen = (uint16)pkttotlen(osh, pfirst); - - /* Do an SDIO read for the superframe. Configurable iovar to - * read directly into the chained packet, or allocate a large - * packet and and copy into the chain. - */ - if (usechain) { - errcode = dhd_bcmsdh_recv_buf(bus, - bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2, - F2SYNC, (uint8*)PKTDATA(osh, pfirst), - dlen, pfirst, NULL, NULL); - } else if (bus->dataptr) { - errcode = dhd_bcmsdh_recv_buf(bus, - bcmsdh_cur_sbwad(bus->sdh), SDIO_FUNC_2, - F2SYNC, bus->dataptr, - dlen, NULL, NULL, NULL); - sublen = (uint16)pktfrombuf(osh, pfirst, 0, dlen, bus->dataptr); - if (sublen != dlen) { - DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n", - __FUNCTION__, dlen, sublen)); - errcode = -1; - } - pnext = NULL; - } else { - DHD_ERROR(("COULDN'T ALLOC %d-BYTE GLOM, FORCE FAILURE\n", dlen)); - errcode = -1; - } - bus->f2rxdata++; - ASSERT(errcode != BCME_PENDING); - - /* On failure, kill the superframe, allow a couple retries */ - if (errcode < 0) { - DHD_ERROR(("%s: glom read of %d bytes failed: %d\n", - __FUNCTION__, dlen, errcode)); - bus->dhd->rx_errors++; - - if (bus->glomerr++ < 3) { - dhdsdio_rxfail(bus, TRUE, TRUE); - } else { - bus->glomerr = 0; - dhdsdio_rxfail(bus, TRUE, FALSE); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE(osh, bus->glom, FALSE); - dhd_os_sdunlock_rxq(bus->dhd); - bus->rxglomfail++; - bus->glom = NULL; - } - return 0; - } - -#ifdef DHD_DEBUG - if (DHD_GLOM_ON()) { - prhex("SUPERFRAME", PKTDATA(osh, pfirst), - MIN(PKTLEN(osh, pfirst), 48)); - } -#endif - - - /* Validate the superframe header */ - dptr = (uint8 *)PKTDATA(osh, pfirst); - sublen = ltoh16_ua(dptr); - check = ltoh16_ua(dptr + sizeof(uint16)); - - chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); - seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); - bus->nextlen = dptr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; - if ((bus->nextlen << 4) > MAX_RX_DATASZ) { - DHD_INFO(("%s: got frame w/nextlen too large (%d) seq %d\n", - __FUNCTION__, bus->nextlen, seq)); - bus->nextlen = 0; - } - doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); - txmax = SDPCM_WINDOW_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); - - errcode = 0; - if ((uint16)~(sublen^check)) { - DHD_ERROR(("%s (superframe): HW hdr error: len/check 0x%04x/0x%04x\n", - __FUNCTION__, sublen, check)); - errcode = -1; - } else if (ROUNDUP(sublen, bus->blocksize) != dlen) { - DHD_ERROR(("%s (superframe): len 0x%04x, rounded 0x%04x, expect 0x%04x\n", - __FUNCTION__, sublen, ROUNDUP(sublen, bus->blocksize), dlen)); - errcode = -1; - } else if (SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]) != SDPCM_GLOM_CHANNEL) { - DHD_ERROR(("%s (superframe): bad channel %d\n", __FUNCTION__, - SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]))); - errcode = -1; - } else if (SDPCM_GLOMDESC(&dptr[SDPCM_FRAMETAG_LEN])) { - DHD_ERROR(("%s (superframe): got second descriptor?\n", __FUNCTION__)); - errcode = -1; - } else if ((doff < SDPCM_HDRLEN) || - (doff > (PKTLEN(osh, pfirst) - SDPCM_HDRLEN))) { - DHD_ERROR(("%s (superframe): Bad data offset %d: HW %d pkt %d min %d\n", - __FUNCTION__, doff, sublen, PKTLEN(osh, pfirst), SDPCM_HDRLEN)); - errcode = -1; - } - - /* Check sequence number of superframe SW header */ - if (rxseq != seq) { - DHD_INFO(("%s: (superframe) rx_seq %d, expected %d\n", - __FUNCTION__, seq, rxseq)); - bus->rx_badseq++; - rxseq = seq; - } - - /* Check window for sanity */ - if ((uint8)(txmax - bus->tx_seq) > 0x40) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", - __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq + 2; - } - bus->tx_max = txmax; - - /* Remove superframe header, remember offset */ - PKTPULL(osh, pfirst, doff); - sfdoff = doff; - - /* Validate all the subframe headers */ - for (num = 0, pnext = pfirst; pnext && !errcode; - num++, pnext = PKTNEXT(osh, pnext)) { - dptr = (uint8 *)PKTDATA(osh, pnext); - dlen = (uint16)PKTLEN(osh, pnext); - sublen = ltoh16_ua(dptr); - check = ltoh16_ua(dptr + sizeof(uint16)); - chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); - doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); -#ifdef DHD_DEBUG - if (DHD_GLOM_ON()) { - prhex("subframe", dptr, 32); - } -#endif - - if ((uint16)~(sublen^check)) { - DHD_ERROR(("%s (subframe %d): HW hdr error: " - "len/check 0x%04x/0x%04x\n", - __FUNCTION__, num, sublen, check)); - errcode = -1; - } else if ((sublen > dlen) || (sublen < SDPCM_HDRLEN)) { - DHD_ERROR(("%s (subframe %d): length mismatch: " - "len 0x%04x, expect 0x%04x\n", - __FUNCTION__, num, sublen, dlen)); - errcode = -1; - } else if ((chan != SDPCM_DATA_CHANNEL) && - (chan != SDPCM_EVENT_CHANNEL)) { - DHD_ERROR(("%s (subframe %d): bad channel %d\n", - __FUNCTION__, num, chan)); - errcode = -1; - } else if ((doff < SDPCM_HDRLEN) || (doff > sublen)) { - DHD_ERROR(("%s (subframe %d): Bad data offset %d: HW %d min %d\n", - __FUNCTION__, num, doff, sublen, SDPCM_HDRLEN)); - errcode = -1; - } - } - - if (errcode) { - /* Terminate frame on error, request a couple retries */ - if (bus->glomerr++ < 3) { - /* Restore superframe header space */ - PKTPUSH(osh, pfirst, sfdoff); - dhdsdio_rxfail(bus, TRUE, TRUE); - } else { - bus->glomerr = 0; - dhdsdio_rxfail(bus, TRUE, FALSE); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE(osh, bus->glom, FALSE); - dhd_os_sdunlock_rxq(bus->dhd); - bus->rxglomfail++; - bus->glom = NULL; - } - bus->nextlen = 0; - return 0; - } - - /* Basic SD framing looks ok - process each packet (header) */ - save_pfirst = pfirst; - bus->glom = NULL; - plast = NULL; - - dhd_os_sdlock_rxq(bus->dhd); - for (num = 0; pfirst; rxseq++, pfirst = pnext) { - pnext = PKTNEXT(osh, pfirst); - PKTSETNEXT(osh, pfirst, NULL); - - dptr = (uint8 *)PKTDATA(osh, pfirst); - sublen = ltoh16_ua(dptr); - chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]); - seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]); - doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]); - - DHD_GLOM(("%s: Get subframe %d, %p(%p/%d), sublen %d chan %d seq %d\n", - __FUNCTION__, num, pfirst, PKTDATA(osh, pfirst), - PKTLEN(osh, pfirst), sublen, chan, seq)); - - ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL)); - - if (rxseq != seq) { - DHD_GLOM(("%s: rx_seq %d, expected %d\n", - __FUNCTION__, seq, rxseq)); - bus->rx_badseq++; - rxseq = seq; - } - -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() && DHD_DATA_ON()) { - prhex("Rx Subframe Data", dptr, dlen); - } -#endif - - PKTSETLEN(osh, pfirst, sublen); - PKTPULL(osh, pfirst, doff); - - if (PKTLEN(osh, pfirst) == 0) { - PKTFREE(bus->dhd->osh, pfirst, FALSE); - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } else { - ASSERT(save_pfirst == pfirst); - save_pfirst = pnext; - } - continue; - } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst) != 0) { - DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__)); - bus->dhd->rx_errors++; - PKTFREE(osh, pfirst, FALSE); - if (plast) { - PKTSETNEXT(osh, plast, pnext); - } else { - ASSERT(save_pfirst == pfirst); - save_pfirst = pnext; - } - continue; - } - - /* this packet will go up, link back into chain and count it */ - PKTSETNEXT(osh, pfirst, pnext); - plast = pfirst; - num++; - -#ifdef DHD_DEBUG - if (DHD_GLOM_ON()) { - DHD_GLOM(("%s subframe %d to stack, %p(%p/%d) nxt/lnk %p/%p\n", - __FUNCTION__, num, pfirst, - PKTDATA(osh, pfirst), PKTLEN(osh, pfirst), - PKTNEXT(osh, pfirst), PKTLINK(pfirst))); - prhex("", (uint8 *)PKTDATA(osh, pfirst), - MIN(PKTLEN(osh, pfirst), 32)); - } -#endif /* DHD_DEBUG */ - } - dhd_os_sdunlock_rxq(bus->dhd); - if (num) { - dhd_os_sdunlock(bus->dhd); - dhd_rx_frame(bus->dhd, ifidx, save_pfirst, num); - dhd_os_sdlock(bus->dhd); - } - - bus->rxglomframes++; - bus->rxglompkts += num; - } - return num; -} - -/* Return TRUE if there may be more frames to read */ -static uint -dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) -{ - osl_t *osh = bus->dhd->osh; - bcmsdh_info_t *sdh = bus->sdh; - - uint16 len, check; /* Extracted hardware header fields */ - uint8 chan, seq, doff; /* Extracted software header fields */ - uint8 fcbits; /* Extracted fcbits from software header */ - uint8 delta; - - void *pkt; /* Packet for event or data frames */ - uint16 pad; /* Number of pad bytes to read */ - uint16 rdlen; /* Total number of bytes to read */ - uint8 rxseq; /* Next sequence number to expect */ - uint rxleft = 0; /* Remaining number of frames allowed */ - int sdret; /* Return code from bcmsdh calls */ - uint8 txmax; /* Maximum tx sequence offered */ - bool len_consistent; /* Result of comparing readahead len and len from hw-hdr */ - uint8 *rxbuf; - int ifidx = 0; - uint rxcount = 0; /* Total frames read */ - -#if defined(DHD_DEBUG) || defined(SDTEST) - bool sdtest = FALSE; /* To limit message spew from test mode */ -#endif - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - ASSERT(maxframes); - -#ifdef SDTEST - /* Allow pktgen to override maxframes */ - if (bus->pktgen_count && (bus->pktgen_mode == DHD_PKTGEN_RECV)) { - maxframes = bus->pktgen_count; - sdtest = TRUE; - } -#endif - - /* Not finished unless we encounter no more frames indication */ - *finished = FALSE; - - - for (rxseq = bus->rx_seq, rxleft = maxframes; - !bus->rxskip && rxleft && bus->dhd->busstate != DHD_BUS_DOWN; - rxseq++, rxleft--) { - - /* Handle glomming separately */ - if (bus->glom || bus->glomd) { - uint8 cnt; - DHD_GLOM(("%s: calling rxglom: glomd %p, glom %p\n", - __FUNCTION__, bus->glomd, bus->glom)); - cnt = dhdsdio_rxglom(bus, rxseq); - DHD_GLOM(("%s: rxglom returned %d\n", __FUNCTION__, cnt)); - rxseq += cnt - 1; - rxleft = (rxleft > cnt) ? (rxleft - cnt) : 1; - continue; - } - - /* Try doing single read if we can */ - if (dhd_readahead && bus->nextlen) { - uint16 nextlen = bus->nextlen; - bus->nextlen = 0; - - if (bus->bus == SPI_BUS) { - rdlen = len = nextlen; - } - else { - rdlen = len = nextlen << 4; - - /* Pad read to blocksize for efficiency */ - if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { - pad = bus->blocksize - (rdlen % bus->blocksize); - if ((pad <= bus->roundup) && (pad < bus->blocksize) && - ((rdlen + pad + firstread) < MAX_RX_DATASZ)) - rdlen += pad; - } else if (rdlen % DHD_SDALIGN) { - rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); - } - } - - /* We use bus->rxctl buffer in WinXP for initial control pkt receives. - * Later we use buffer-poll for data as well as control packets. - * This is required becuase dhd receives full frame in gSPI unlike SDIO. - * After the frame is received we have to distinguish whether it is data - * or non-data frame. - */ - /* Allocate a packet buffer */ - dhd_os_sdlock_rxq(bus->dhd); - if (!(pkt = PKTGET(osh, rdlen + DHD_SDALIGN, FALSE))) { - if (bus->bus == SPI_BUS) { - bus->usebufpool = FALSE; - bus->rxctl = bus->rxbuf; - if (dhd_alignctl) { - bus->rxctl += firstread; - if ((pad = ((uintptr)bus->rxctl % DHD_SDALIGN))) - bus->rxctl += (DHD_SDALIGN - pad); - bus->rxctl -= firstread; - } - ASSERT(bus->rxctl >= bus->rxbuf); - rxbuf = bus->rxctl; - /* Read the entire frame */ - sdret = dhd_bcmsdh_recv_buf(bus, - bcmsdh_cur_sbwad(sdh), - SDIO_FUNC_2, - F2SYNC, rxbuf, rdlen, - NULL, NULL, NULL); - bus->f2rxdata++; - ASSERT(sdret != BCME_PENDING); - - - /* Control frame failures need retransmission */ - if (sdret < 0) { - DHD_ERROR(("%s: read %d control bytes failed: %d\n", - __FUNCTION__, rdlen, sdret)); - /* dhd.rx_ctlerrs is higher level */ - bus->rxc_errors++; - dhd_os_sdunlock_rxq(bus->dhd); - dhdsdio_rxfail(bus, TRUE, - (bus->bus == SPI_BUS) ? FALSE : TRUE); - continue; - } - } else { - /* Give up on data, request rtx of events */ - DHD_ERROR(("%s (nextlen): PKTGET failed: len %d rdlen %d " - "expected rxseq %d\n", - __FUNCTION__, len, rdlen, rxseq)); - /* Just go try again w/normal header read */ - dhd_os_sdunlock_rxq(bus->dhd); - continue; - } - } else { - if (bus->bus == SPI_BUS) - bus->usebufpool = TRUE; - - ASSERT(!PKTLINK(pkt)); - PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN); - rxbuf = (uint8 *)PKTDATA(osh, pkt); - /* Read the entire frame */ - sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), - SDIO_FUNC_2, - F2SYNC, rxbuf, rdlen, - pkt, NULL, NULL); - bus->f2rxdata++; - ASSERT(sdret != BCME_PENDING); - - if (sdret < 0) { - DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n", - __FUNCTION__, rdlen, sdret)); - PKTFREE(bus->dhd->osh, pkt, FALSE); - bus->dhd->rx_errors++; - dhd_os_sdunlock_rxq(bus->dhd); - /* Force retry w/normal header read. Don't attemp NAK for - * gSPI - */ - dhdsdio_rxfail(bus, TRUE, - (bus->bus == SPI_BUS) ? FALSE : TRUE); - continue; - } - } - dhd_os_sdunlock_rxq(bus->dhd); - - /* Now check the header */ - bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN); - - /* Extract hardware header fields */ - len = ltoh16_ua(bus->rxhdr); - check = ltoh16_ua(bus->rxhdr + sizeof(uint16)); - - /* All zeros means readahead info was bad */ - if (!(len|check)) { - DHD_INFO(("%s (nextlen): read zeros in HW header???\n", - __FUNCTION__)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE2(); - dhd_os_sdunlock_rxq(bus->dhd); - GSPI_PR55150_BAILOUT; - continue; - } - - /* Validate check bytes */ - if ((uint16)~(len^check)) { - DHD_ERROR(("%s (nextlen): HW hdr error: nextlen/len/check" - " 0x%04x/0x%04x/0x%04x\n", __FUNCTION__, nextlen, - len, check)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE2(); - dhd_os_sdunlock_rxq(bus->dhd); - bus->rx_badhdr++; - dhdsdio_rxfail(bus, FALSE, FALSE); - GSPI_PR55150_BAILOUT; - continue; - } - - /* Validate frame length */ - if (len < SDPCM_HDRLEN) { - DHD_ERROR(("%s (nextlen): HW hdr length invalid: %d\n", - __FUNCTION__, len)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE2(); - dhd_os_sdunlock_rxq(bus->dhd); - GSPI_PR55150_BAILOUT; - continue; - } - - /* Check for consistency with readahead info */ - len_consistent = (nextlen != (ROUNDUP(len, 16) >> 4)); - if (len_consistent) { - /* Mismatch, force retry w/normal header (may be >4K) */ - DHD_ERROR(("%s (nextlen): mismatch, nextlen %d len %d rnd %d; " - "expected rxseq %d\n", - __FUNCTION__, nextlen, len, ROUNDUP(len, 16), rxseq)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE2(); - dhd_os_sdunlock_rxq(bus->dhd); - dhdsdio_rxfail(bus, TRUE, (bus->bus == SPI_BUS) ? FALSE : TRUE); - GSPI_PR55150_BAILOUT; - continue; - } - - - /* Extract software header fields */ - chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - - bus->nextlen = - bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; - if ((bus->nextlen << 4) > MAX_RX_DATASZ) { - DHD_INFO(("%s (nextlen): got frame w/nextlen too large" - " (%d), seq %d\n", __FUNCTION__, bus->nextlen, - seq)); - bus->nextlen = 0; - } - - bus->dhd->rx_readahead_cnt ++; - /* Handle Flow Control */ - fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - - delta = 0; - if (~bus->flowcontrol & fcbits) { - bus->fc_xoff++; - delta = 1; - } - if (bus->flowcontrol & ~fcbits) { - bus->fc_xon++; - delta = 1; - } - - if (delta) { - bus->fc_rcvd++; - bus->flowcontrol = fcbits; - } - - /* Check and update sequence number */ - if (rxseq != seq) { - DHD_INFO(("%s (nextlen): rx_seq %d, expected %d\n", - __FUNCTION__, seq, rxseq)); - bus->rx_badseq++; - rxseq = seq; - } - - /* Check window for sanity */ - if ((uint8)(txmax - bus->tx_seq) > 0x40) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", - __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq + 2; - } - bus->tx_max = txmax; - -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() && DHD_DATA_ON()) { - prhex("Rx Data", rxbuf, len); - } else if (DHD_HDRS_ON()) { - prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); - } -#endif - - if (chan == SDPCM_CONTROL_CHANNEL) { - if (bus->bus == SPI_BUS) { - dhdsdio_read_control(bus, rxbuf, len, doff); - if (bus->usebufpool) { - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE(bus->dhd->osh, pkt, FALSE); - dhd_os_sdunlock_rxq(bus->dhd); - } - continue; - } else { - DHD_ERROR(("%s (nextlen): readahead on control" - " packet %d?\n", __FUNCTION__, seq)); - /* Force retry w/normal header read */ - bus->nextlen = 0; - dhdsdio_rxfail(bus, FALSE, TRUE); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE2(); - dhd_os_sdunlock_rxq(bus->dhd); - continue; - } - } - - if ((bus->bus == SPI_BUS) && !bus->usebufpool) { - DHD_ERROR(("Received %d bytes on %d channel. Running out of " - "rx pktbuf's or not yet malloced.\n", len, chan)); - continue; - } - - /* Validate data offset */ - if ((doff < SDPCM_HDRLEN) || (doff > len)) { - DHD_ERROR(("%s (nextlen): bad data offset %d: HW len %d min %d\n", - __FUNCTION__, doff, len, SDPCM_HDRLEN)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE2(); - dhd_os_sdunlock_rxq(bus->dhd); - ASSERT(0); - dhdsdio_rxfail(bus, FALSE, FALSE); - continue; - } - - /* All done with this one -- now deliver the packet */ - goto deliver; - } - /* gSPI frames should not be handled in fractions */ - if (bus->bus == SPI_BUS) { - break; - } - - /* Read frame header (hardware and software) */ - sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - bus->rxhdr, firstread, NULL, NULL, NULL); - bus->f2rxhdrs++; - ASSERT(sdret != BCME_PENDING); - - if (sdret < 0) { - DHD_ERROR(("%s: RXHEADER FAILED: %d\n", __FUNCTION__, sdret)); - bus->rx_hdrfail++; - dhdsdio_rxfail(bus, TRUE, TRUE); - continue; - } - -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() || DHD_HDRS_ON()) { - prhex("RxHdr", bus->rxhdr, SDPCM_HDRLEN); - } -#endif - - /* Extract hardware header fields */ - len = ltoh16_ua(bus->rxhdr); - check = ltoh16_ua(bus->rxhdr + sizeof(uint16)); - - /* All zeros means no more frames */ - if (!(len|check)) { - *finished = TRUE; - break; - } - - /* Validate check bytes */ - if ((uint16)~(len^check)) { - DHD_ERROR(("%s: HW hdr error: len/check 0x%04x/0x%04x\n", - __FUNCTION__, len, check)); - bus->rx_badhdr++; - dhdsdio_rxfail(bus, FALSE, FALSE); - continue; - } - - /* Validate frame length */ - if (len < SDPCM_HDRLEN) { - DHD_ERROR(("%s: HW hdr length invalid: %d\n", __FUNCTION__, len)); - continue; - } - - /* Extract software header fields */ - chan = SDPCM_PACKET_CHANNEL(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - seq = SDPCM_PACKET_SEQUENCE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - doff = SDPCM_DOFFSET_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - txmax = SDPCM_WINDOW_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - - /* Validate data offset */ - if ((doff < SDPCM_HDRLEN) || (doff > len)) { - DHD_ERROR(("%s: Bad data offset %d: HW len %d, min %d seq %d\n", - __FUNCTION__, doff, len, SDPCM_HDRLEN, seq)); - bus->rx_badhdr++; - ASSERT(0); - dhdsdio_rxfail(bus, FALSE, FALSE); - continue; - } - - /* Save the readahead length if there is one */ - bus->nextlen = bus->rxhdr[SDPCM_FRAMETAG_LEN + SDPCM_NEXTLEN_OFFSET]; - if ((bus->nextlen << 4) > MAX_RX_DATASZ) { - DHD_INFO(("%s (nextlen): got frame w/nextlen too large (%d), seq %d\n", - __FUNCTION__, bus->nextlen, seq)); - bus->nextlen = 0; - } - - /* Handle Flow Control */ - fcbits = SDPCM_FCMASK_VALUE(&bus->rxhdr[SDPCM_FRAMETAG_LEN]); - - delta = 0; - if (~bus->flowcontrol & fcbits) { - bus->fc_xoff++; - delta = 1; - } - if (bus->flowcontrol & ~fcbits) { - bus->fc_xon++; - delta = 1; - } - - if (delta) { - bus->fc_rcvd++; - bus->flowcontrol = fcbits; - } - - /* Check and update sequence number */ - if (rxseq != seq) { - DHD_INFO(("%s: rx_seq %d, expected %d\n", __FUNCTION__, seq, rxseq)); - bus->rx_badseq++; - rxseq = seq; - } - - /* Check window for sanity */ - if ((uint8)(txmax - bus->tx_seq) > 0x40) { - DHD_ERROR(("%s: got unlikely tx max %d with tx_seq %d\n", - __FUNCTION__, txmax, bus->tx_seq)); - txmax = bus->tx_seq + 2; - } - bus->tx_max = txmax; - - /* Call a separate function for control frames */ - if (chan == SDPCM_CONTROL_CHANNEL) { - dhdsdio_read_control(bus, bus->rxhdr, len, doff); - continue; - } - - ASSERT((chan == SDPCM_DATA_CHANNEL) || (chan == SDPCM_EVENT_CHANNEL) || - (chan == SDPCM_TEST_CHANNEL) || (chan == SDPCM_GLOM_CHANNEL)); - - /* Length to read */ - rdlen = (len > firstread) ? (len - firstread) : 0; - - /* May pad read to blocksize for efficiency */ - if (bus->roundup && bus->blocksize && (rdlen > bus->blocksize)) { - pad = bus->blocksize - (rdlen % bus->blocksize); - if ((pad <= bus->roundup) && (pad < bus->blocksize) && - ((rdlen + pad + firstread) < MAX_RX_DATASZ)) - rdlen += pad; - } else if (rdlen % DHD_SDALIGN) { - rdlen += DHD_SDALIGN - (rdlen % DHD_SDALIGN); - } - - /* Satisfy length-alignment requirements */ - if (forcealign && (rdlen & (ALIGNMENT - 1))) - rdlen = ROUNDUP(rdlen, ALIGNMENT); - - if ((rdlen + firstread) > MAX_RX_DATASZ) { - /* Too long -- skip this frame */ - DHD_ERROR(("%s: too long: len %d rdlen %d\n", __FUNCTION__, len, rdlen)); - bus->dhd->rx_errors++; bus->rx_toolong++; - dhdsdio_rxfail(bus, FALSE, FALSE); - continue; - } - - dhd_os_sdlock_rxq(bus->dhd); - if (!(pkt = PKTGET(osh, (rdlen + firstread + DHD_SDALIGN), FALSE))) { - /* Give up on data, request rtx of events */ - DHD_ERROR(("%s: PKTGET failed: rdlen %d chan %d\n", - __FUNCTION__, rdlen, chan)); - bus->dhd->rx_dropped++; - dhd_os_sdunlock_rxq(bus->dhd); - dhdsdio_rxfail(bus, FALSE, RETRYCHAN(chan)); - continue; - } - dhd_os_sdunlock_rxq(bus->dhd); - - ASSERT(!PKTLINK(pkt)); - - /* Leave room for what we already read, and align remainder */ - ASSERT(firstread < (PKTLEN(osh, pkt))); - PKTPULL(osh, pkt, firstread); - PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN); - - /* Read the remaining frame data */ - sdret = dhd_bcmsdh_recv_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - ((uint8 *)PKTDATA(osh, pkt)), rdlen, pkt, NULL, NULL); - bus->f2rxdata++; - ASSERT(sdret != BCME_PENDING); - - if (sdret < 0) { - DHD_ERROR(("%s: read %d %s bytes failed: %d\n", __FUNCTION__, rdlen, - ((chan == SDPCM_EVENT_CHANNEL) ? "event" : - ((chan == SDPCM_DATA_CHANNEL) ? "data" : "test")), sdret)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE(bus->dhd->osh, pkt, FALSE); - dhd_os_sdunlock_rxq(bus->dhd); - bus->dhd->rx_errors++; - dhdsdio_rxfail(bus, TRUE, RETRYCHAN(chan)); - continue; - } - - /* Copy the already-read portion */ - PKTPUSH(osh, pkt, firstread); - bcopy(bus->rxhdr, PKTDATA(osh, pkt), firstread); - -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() && DHD_DATA_ON()) { - prhex("Rx Data", PKTDATA(osh, pkt), len); - } -#endif - -deliver: - /* Save superframe descriptor and allocate packet frame */ - if (chan == SDPCM_GLOM_CHANNEL) { - if (SDPCM_GLOMDESC(&bus->rxhdr[SDPCM_FRAMETAG_LEN])) { - DHD_GLOM(("%s: got glom descriptor, %d bytes:\n", - __FUNCTION__, len)); -#ifdef DHD_DEBUG - if (DHD_GLOM_ON()) { - prhex("Glom Data", PKTDATA(osh, pkt), len); - } -#endif - PKTSETLEN(osh, pkt, len); - ASSERT(doff == SDPCM_HDRLEN); - PKTPULL(osh, pkt, SDPCM_HDRLEN); - bus->glomd = pkt; - } else { - DHD_ERROR(("%s: glom superframe w/o descriptor!\n", __FUNCTION__)); - dhdsdio_rxfail(bus, FALSE, FALSE); - } - continue; - } - - /* Fill in packet len and prio, deliver upward */ - PKTSETLEN(osh, pkt, len); - PKTPULL(osh, pkt, doff); - -#ifdef SDTEST - /* Test channel packets are processed separately */ - if (chan == SDPCM_TEST_CHANNEL) { - dhdsdio_testrcv(bus, pkt, seq); - continue; - } -#endif /* SDTEST */ - - if (PKTLEN(osh, pkt) == 0) { - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE(bus->dhd->osh, pkt, FALSE); - dhd_os_sdunlock_rxq(bus->dhd); - continue; - } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) { - DHD_ERROR(("%s: rx protocol error\n", __FUNCTION__)); - dhd_os_sdlock_rxq(bus->dhd); - PKTFREE(bus->dhd->osh, pkt, FALSE); - dhd_os_sdunlock_rxq(bus->dhd); - bus->dhd->rx_errors++; - continue; - } - - - /* Unlock during rx call */ - dhd_os_sdunlock(bus->dhd); - dhd_rx_frame(bus->dhd, ifidx, pkt, 1); - dhd_os_sdlock(bus->dhd); - } - rxcount = maxframes - rxleft; -#ifdef DHD_DEBUG - /* Message if we hit the limit */ - if (!rxleft && !sdtest) - DHD_DATA(("%s: hit rx limit of %d frames\n", __FUNCTION__, maxframes)); - else -#endif /* DHD_DEBUG */ - DHD_DATA(("%s: processed %d frames\n", __FUNCTION__, rxcount)); - /* Back off rxseq if awaiting rtx, update rx_seq */ - if (bus->rxskip) - rxseq--; - bus->rx_seq = rxseq; - - return rxcount; -} - -static uint32 -dhdsdio_hostmail(dhd_bus_t *bus) -{ - sdpcmd_regs_t *regs = bus->regs; - uint32 intstatus = 0; - uint32 hmb_data; - uint8 fcbits; - uint retries = 0; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Read mailbox data and ack that we did so */ - R_SDREG(hmb_data, ®s->tohostmailboxdata, retries); - if (retries <= retry_limit) - W_SDREG(SMB_INT_ACK, ®s->tosbmailbox, retries); - bus->f1regdata += 2; - - /* Dongle recomposed rx frames, accept them again */ - if (hmb_data & HMB_DATA_NAKHANDLED) { - DHD_INFO(("Dongle reports NAK handled, expect rtx of %d\n", bus->rx_seq)); - if (!bus->rxskip) { - DHD_ERROR(("%s: unexpected NAKHANDLED!\n", __FUNCTION__)); - } - bus->rxskip = FALSE; - intstatus |= I_HMB_FRAME_IND; - } - - /* - * DEVREADY does not occur with gSPI. - */ - if (hmb_data & (HMB_DATA_DEVREADY | HMB_DATA_FWREADY)) { - bus->sdpcm_ver = (hmb_data & HMB_DATA_VERSION_MASK) >> HMB_DATA_VERSION_SHIFT; - if (bus->sdpcm_ver != SDPCM_PROT_VERSION) - DHD_ERROR(("Version mismatch, dongle reports %d, expecting %d\n", - bus->sdpcm_ver, SDPCM_PROT_VERSION)); - else - DHD_INFO(("Dongle ready, protocol version %d\n", bus->sdpcm_ver)); - } - - /* - * Flow Control has been moved into the RX headers and this out of band - * method isn't used any more. Leae this here for possibly remaining backward - * compatible with older dongles - */ - if (hmb_data & HMB_DATA_FC) { - fcbits = (hmb_data & HMB_DATA_FCDATA_MASK) >> HMB_DATA_FCDATA_SHIFT; - - if (fcbits & ~bus->flowcontrol) - bus->fc_xoff++; - if (bus->flowcontrol & ~fcbits) - bus->fc_xon++; - - bus->fc_rcvd++; - bus->flowcontrol = fcbits; - } - - /* Shouldn't be any others */ - if (hmb_data & ~(HMB_DATA_DEVREADY | - HMB_DATA_NAKHANDLED | - HMB_DATA_FC | - HMB_DATA_FWREADY | - HMB_DATA_FCDATA_MASK | - HMB_DATA_VERSION_MASK)) { - DHD_ERROR(("Unknown mailbox data content: 0x%02x\n", hmb_data)); - } - - return intstatus; -} - -bool -dhdsdio_dpc(dhd_bus_t *bus) -{ - bcmsdh_info_t *sdh = bus->sdh; - sdpcmd_regs_t *regs = bus->regs; - uint32 intstatus, newstatus = 0; - uint retries = 0; - uint rxlimit = dhd_rxbound; /* Rx frames to read before resched */ - uint txlimit = dhd_txbound; /* Tx frames to send before resched */ - uint framecnt = 0; /* Temporary counter of tx/rx frames */ - bool rxdone = TRUE; /* Flag for no more read data */ - bool resched = FALSE; /* Flag indicating resched wanted */ - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - /* Start with leftover status bits */ - intstatus = bus->intstatus; - - dhd_os_sdlock(bus->dhd); - - /* If waiting for HTAVAIL, check status */ - if (bus->clkstate == CLK_PENDING) { - int err; - uint8 clkctl, devctl = 0; - -#ifdef DHD_DEBUG - /* Check for inconsistent device control */ - devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); - if (err) { - DHD_ERROR(("%s: error reading DEVCTL: %d\n", __FUNCTION__, err)); - bus->dhd->busstate = DHD_BUS_DOWN; - } else { - ASSERT(devctl & SBSDIO_DEVCTL_CA_INT_ONLY); - } -#endif /* DHD_DEBUG */ - - /* Read CSR, if clock on switch to AVAIL, else ignore */ - clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (err) { - DHD_ERROR(("%s: error reading CSR: %d\n", __FUNCTION__, err)); - bus->dhd->busstate = DHD_BUS_DOWN; - } - - DHD_INFO(("DPC: PENDING, devctl 0x%02x clkctl 0x%02x\n", devctl, clkctl)); - - if (SBSDIO_HTAV(clkctl)) { - devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); - if (err) { - DHD_ERROR(("%s: error reading DEVCTL: %d\n", - __FUNCTION__, err)); - bus->dhd->busstate = DHD_BUS_DOWN; - } - devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); - if (err) { - DHD_ERROR(("%s: error writing DEVCTL: %d\n", - __FUNCTION__, err)); - bus->dhd->busstate = DHD_BUS_DOWN; - } - bus->clkstate = CLK_AVAIL; - } else { - goto clkwait; - } - } - - BUS_WAKE(bus); - - /* Make sure backplane clock is on */ - dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); - if (bus->clkstate == CLK_PENDING) - goto clkwait; - - /* Pending interrupt indicates new device status */ - if (bus->ipend) { - bus->ipend = FALSE; - R_SDREG(newstatus, ®s->intstatus, retries); - bus->f1regdata++; - if (bcmsdh_regfail(bus->sdh)) - newstatus = 0; - newstatus &= bus->hostintmask; - bus->fcstate = !!(newstatus & I_HMB_FC_STATE); - if (newstatus) { - W_SDREG(newstatus, ®s->intstatus, retries); - bus->f1regdata++; - } - } - - /* Merge new bits with previous */ - intstatus |= newstatus; - bus->intstatus = 0; - - /* Handle flow-control change: read new state in case our ack - * crossed another change interrupt. If change still set, assume - * FC ON for safety, let next loop through do the debounce. - */ - if (intstatus & I_HMB_FC_CHANGE) { - intstatus &= ~I_HMB_FC_CHANGE; - W_SDREG(I_HMB_FC_CHANGE, ®s->intstatus, retries); - R_SDREG(newstatus, ®s->intstatus, retries); - bus->f1regdata += 2; - bus->fcstate = !!(newstatus & (I_HMB_FC_STATE | I_HMB_FC_CHANGE)); - intstatus |= (newstatus & bus->hostintmask); - } - - /* Handle host mailbox indication */ - if (intstatus & I_HMB_HOST_INT) { - intstatus &= ~I_HMB_HOST_INT; - intstatus |= dhdsdio_hostmail(bus); - } - - /* Generally don't ask for these, can get CRC errors... */ - if (intstatus & I_WR_OOSYNC) { - DHD_ERROR(("Dongle reports WR_OOSYNC\n")); - intstatus &= ~I_WR_OOSYNC; - } - - if (intstatus & I_RD_OOSYNC) { - DHD_ERROR(("Dongle reports RD_OOSYNC\n")); - intstatus &= ~I_RD_OOSYNC; - } - - if (intstatus & I_SBINT) { - DHD_ERROR(("Dongle reports SBINT\n")); - intstatus &= ~I_SBINT; - } - - /* Would be active due to wake-wlan in gSPI */ - if (intstatus & I_CHIPACTIVE) { - DHD_INFO(("Dongle reports CHIPACTIVE\n")); - intstatus &= ~I_CHIPACTIVE; - } - - /* Ignore frame indications if rxskip is set */ - if (bus->rxskip) - intstatus &= ~I_HMB_FRAME_IND; - - /* On frame indication, read available frames */ - if (PKT_AVAILABLE()) { - framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone); - if (rxdone || bus->rxskip) - intstatus &= ~I_HMB_FRAME_IND; - rxlimit -= MIN(framecnt, rxlimit); - } - - /* Keep still-pending events for next scheduling */ - bus->intstatus = intstatus; - -clkwait: - /* Re-enable interrupts to detect new device events (mailbox, rx frame) - * or clock availability. (Allows tx loop to check ipend if desired.) - * (Unless register access seems hosed, as we may not be able to ACK...) - */ - if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) { - DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n", - __FUNCTION__, rxdone, framecnt)); - bus->intdis = FALSE; - bcmsdh_intr_enable(sdh); - } - - if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { - int ret, i; - - ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, - NULL, NULL, NULL); - ASSERT(ret != BCME_PENDING); - - if (ret < 0) { - /* On failure, abort the command and terminate the frame */ - DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", - __FUNCTION__, ret)); - bus->tx_sderrs++; - - bcmsdh_abort(sdh, SDIO_FUNC_2); - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, - SFC_WF_TERM, NULL); - bus->f1regdata++; - - for (i = 0; i < 3; i++) { - uint8 hi, lo; - hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCLO, NULL); - bus->f1regdata += 2; - if ((hi == 0) && (lo == 0)) - break; - } - - } - if (ret == 0) { - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; - } - - printf("Return_dpc value is : %d\n", ret); - bus->ctrl_frame_stat = FALSE; - dhd_wait_event_wakeup(bus->dhd); - } - /* Send queued frames (limit 1 if rx may still be pending) */ - else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && - pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) { - framecnt = rxdone ? txlimit : MIN(txlimit, dhd_txminmax); - framecnt = dhdsdio_sendfromq(bus, framecnt); - txlimit -= framecnt; - } - - /* Resched if events or tx frames are pending, else await next interrupt */ - /* On failed register access, all bets are off: no resched or interrupts */ - if ((bus->dhd->busstate == DHD_BUS_DOWN) || bcmsdh_regfail(sdh)) { - DHD_ERROR(("%s: failed backplane access over SDIO, halting operation %d \n", - __FUNCTION__, bcmsdh_regfail(sdh))); - bus->dhd->busstate = DHD_BUS_DOWN; - bus->intstatus = 0; - } else if (bus->clkstate == CLK_PENDING) { - DHD_INFO(("%s: rescheduled due to CLK_PENDING awaiting \ - I_CHIPACTIVE interrupt", __FUNCTION__)); - resched = TRUE; - } else if (bus->intstatus || bus->ipend || - (!bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) || - PKT_AVAILABLE()) { /* Read multiple frames */ - resched = TRUE; - } - - - bus->dpc_sched = resched; - - /* If we're done for now, turn off clock request. */ - if ((bus->clkstate != CLK_PENDING) && bus->idletime == DHD_IDLE_IMMEDIATE) { - bus->activity = FALSE; - dhdsdio_clkctl(bus, CLK_NONE, FALSE); - } - - dhd_os_sdunlock(bus->dhd); - - return resched; -} - -bool -dhd_bus_dpc(struct dhd_bus *bus) -{ - bool resched; - - /* Call the DPC directly. */ - DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); - resched = dhdsdio_dpc(bus); - - return resched; -} - -void -dhdsdio_isr(void *arg) -{ - dhd_bus_t *bus = (dhd_bus_t*)arg; - bcmsdh_info_t *sdh; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (!bus) { - DHD_ERROR(("%s : bus is null pointer , exit \n", __FUNCTION__)); - return; - } - sdh = bus->sdh; - - if (bus->dhd->busstate == DHD_BUS_DOWN) { - DHD_ERROR(("%s : bus is down. we have nothing to do\n", __FUNCTION__)); - return; - } - /* Count the interrupt call */ - bus->intrcount++; - bus->ipend = TRUE; - - /* Shouldn't get this interrupt if we're sleeping? */ - if (bus->sleeping) { - DHD_ERROR(("INTERRUPT WHILE SLEEPING??\n")); - return; - } - - /* Disable additional interrupts (is this needed now)? */ - if (bus->intr) { - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - } else { - DHD_ERROR(("dhdsdio_isr() w/o interrupt configured!\n")); - } - - bcmsdh_intr_disable(sdh); - bus->intdis = TRUE; - -#if defined(SDIO_ISR_THREAD) - DHD_TRACE(("Calling dhdsdio_dpc() from %s\n", __FUNCTION__)); - while (dhdsdio_dpc(bus)); -#else - bus->dpc_sched = TRUE; - dhd_sched_dpc(bus->dhd); -#endif - - -} - -#ifdef SDTEST -static void -dhdsdio_pktgen_init(dhd_bus_t *bus) -{ - /* Default to specified length, or full range */ - if (dhd_pktgen_len) { - bus->pktgen_maxlen = MIN(dhd_pktgen_len, MAX_PKTGEN_LEN); - bus->pktgen_minlen = bus->pktgen_maxlen; - } else { - bus->pktgen_maxlen = MAX_PKTGEN_LEN; - bus->pktgen_minlen = 0; - } - bus->pktgen_len = (uint16)bus->pktgen_minlen; - - /* Default to per-watchdog burst with 10s print time */ - bus->pktgen_freq = 1; - bus->pktgen_print = 10000 / dhd_watchdog_ms; - bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000; - - /* Default to echo mode */ - bus->pktgen_mode = DHD_PKTGEN_ECHO; - bus->pktgen_stop = 1; -} - -static void -dhdsdio_pktgen(dhd_bus_t *bus) -{ - void *pkt; - uint8 *data; - uint pktcount; - uint fillbyte; - osl_t *osh = bus->dhd->osh; - uint16 len; - - /* Display current count if appropriate */ - if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) { - bus->pktgen_ptick = 0; - printf("%s: send attempts %d rcvd %d\n", - __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd); - } - - /* For recv mode, just make sure dongle has started sending */ - if (bus->pktgen_mode == DHD_PKTGEN_RECV) { - if (!bus->pktgen_rcvd) - dhdsdio_sdtest_set(bus, TRUE); - return; - } - - /* Otherwise, generate or request the specified number of packets */ - for (pktcount = 0; pktcount < bus->pktgen_count; pktcount++) { - /* Stop if total has been reached */ - if (bus->pktgen_total && (bus->pktgen_sent >= bus->pktgen_total)) { - bus->pktgen_count = 0; - break; - } - - /* Allocate an appropriate-sized packet */ - len = bus->pktgen_len; - if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN), - TRUE))) {; - DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__)); - break; - } - PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN); - data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; - - /* Write test header cmd and extra based on mode */ - switch (bus->pktgen_mode) { - case DHD_PKTGEN_ECHO: - *data++ = SDPCM_TEST_ECHOREQ; - *data++ = (uint8)bus->pktgen_sent; - break; - - case DHD_PKTGEN_SEND: - *data++ = SDPCM_TEST_DISCARD; - *data++ = (uint8)bus->pktgen_sent; - break; - - case DHD_PKTGEN_RXBURST: - *data++ = SDPCM_TEST_BURST; - *data++ = (uint8)bus->pktgen_count; - break; - - default: - DHD_ERROR(("Unrecognized pktgen mode %d\n", bus->pktgen_mode)); - PKTFREE(osh, pkt, TRUE); - bus->pktgen_count = 0; - return; - } - - /* Write test header length field */ - *data++ = (len >> 0); - *data++ = (len >> 8); - - /* Then fill in the remainder -- N/A for burst, but who cares... */ - for (fillbyte = 0; fillbyte < len; fillbyte++) - *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent); - -#ifdef DHD_DEBUG - if (DHD_BYTES_ON() && DHD_DATA_ON()) { - data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; - prhex("dhdsdio_pktgen: Tx Data", data, PKTLEN(osh, pkt) - SDPCM_HDRLEN); - } -#endif - - /* Send it */ - if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE)) { - bus->pktgen_fail++; - if (bus->pktgen_stop && bus->pktgen_stop == bus->pktgen_fail) - bus->pktgen_count = 0; - } - bus->pktgen_sent++; - - /* Bump length if not fixed, wrap at max */ - if (++bus->pktgen_len > bus->pktgen_maxlen) - bus->pktgen_len = (uint16)bus->pktgen_minlen; - - /* Special case for burst mode: just send one request! */ - if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) - break; - } -} - -static void -dhdsdio_sdtest_set(dhd_bus_t *bus, bool start) -{ - void *pkt; - uint8 *data; - osl_t *osh = bus->dhd->osh; - - /* Allocate the packet */ - if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN, TRUE))) { - DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__)); - return; - } - PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN); - data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; - - /* Fill in the test header */ - *data++ = SDPCM_TEST_SEND; - *data++ = start; - *data++ = (bus->pktgen_maxlen >> 0); - *data++ = (bus->pktgen_maxlen >> 8); - - /* Send it */ - if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE)) - bus->pktgen_fail++; -} - - -static void -dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq) -{ - osl_t *osh = bus->dhd->osh; - uint8 *data; - uint pktlen; - - uint8 cmd; - uint8 extra; - uint16 len; - uint16 offset; - - /* Check for min length */ - if ((pktlen = PKTLEN(osh, pkt)) < SDPCM_TEST_HDRLEN) { - DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n", pktlen)); - PKTFREE(osh, pkt, FALSE); - return; - } - - /* Extract header fields */ - data = PKTDATA(osh, pkt); - cmd = *data++; - extra = *data++; - len = *data++; len += *data++ << 8; - - /* Check length for relevant commands */ - if (cmd == SDPCM_TEST_DISCARD || cmd == SDPCM_TEST_ECHOREQ || cmd == SDPCM_TEST_ECHORSP) { - if (pktlen != len + SDPCM_TEST_HDRLEN) { - DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, pktlen %d seq %d" - " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len)); - PKTFREE(osh, pkt, FALSE); - return; - } - } - - /* Process as per command */ - switch (cmd) { - case SDPCM_TEST_ECHOREQ: - /* Rx->Tx turnaround ok (even on NDIS w/current implementation) */ - *(uint8 *)(PKTDATA(osh, pkt)) = SDPCM_TEST_ECHORSP; - if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE) == 0) { - bus->pktgen_sent++; - } else { - bus->pktgen_fail++; - PKTFREE(osh, pkt, FALSE); - } - bus->pktgen_rcvd++; - break; - - case SDPCM_TEST_ECHORSP: - if (bus->ext_loop) { - PKTFREE(osh, pkt, FALSE); - bus->pktgen_rcvd++; - break; - } - - for (offset = 0; offset < len; offset++, data++) { - if (*data != SDPCM_TEST_FILL(offset, extra)) { - DHD_ERROR(("dhdsdio_testrcv: echo data mismatch: " - "offset %d (len %d) expect 0x%02x rcvd 0x%02x\n", - offset, len, SDPCM_TEST_FILL(offset, extra), *data)); - break; - } - } - PKTFREE(osh, pkt, FALSE); - bus->pktgen_rcvd++; - break; - - case SDPCM_TEST_DISCARD: - PKTFREE(osh, pkt, FALSE); - bus->pktgen_rcvd++; - break; - - case SDPCM_TEST_BURST: - case SDPCM_TEST_SEND: - default: - DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, pktlen %d seq %d" - " cmd %d extra %d len %d\n", pktlen, seq, cmd, extra, len)); - PKTFREE(osh, pkt, FALSE); - break; - } - - /* For recv mode, stop at limie (and tell dongle to stop sending) */ - if (bus->pktgen_mode == DHD_PKTGEN_RECV) { - if (bus->pktgen_total && (bus->pktgen_rcvd >= bus->pktgen_total)) { - bus->pktgen_count = 0; - dhdsdio_sdtest_set(bus, FALSE); - } - } -} -#endif /* SDTEST */ - -extern bool -dhd_bus_watchdog(dhd_pub_t *dhdp) -{ - dhd_bus_t *bus; - - DHD_TIMER(("%s: Enter\n", __FUNCTION__)); - - bus = dhdp->bus; - - if (bus->dhd->dongle_reset) - return FALSE; - - /* Ignore the timer if simulating bus down */ - if (bus->sleeping) - return FALSE; - - dhd_os_sdlock(bus->dhd); - - /* Poll period: check device if appropriate. */ - if (bus->poll && (++bus->polltick >= bus->pollrate)) { - uint32 intstatus = 0; - - /* Reset poll tick */ - bus->polltick = 0; - - /* Check device if no interrupts */ - if (!bus->intr || (bus->intrcount == bus->lastintrs)) { - - if (!bus->dpc_sched) { - uint8 devpend; - devpend = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_0, - SDIOD_CCCR_INTPEND, NULL); - intstatus = devpend & (INTR_STATUS_FUNC1 | INTR_STATUS_FUNC2); - } - - /* If there is something, make like the ISR and schedule the DPC */ - if (intstatus) { - bus->pollcnt++; - bus->ipend = TRUE; - if (bus->intr) { - bcmsdh_intr_disable(bus->sdh); - } - bus->dpc_sched = TRUE; - dhd_sched_dpc(bus->dhd); - - } - } - - /* Update interrupt tracking */ - bus->lastintrs = bus->intrcount; - } - -#ifdef DHD_DEBUG - /* Poll for console output periodically */ - if (dhdp->busstate == DHD_BUS_DATA && dhd_console_ms != 0) { - bus->console.count += dhd_watchdog_ms; - if (bus->console.count >= dhd_console_ms) { - bus->console.count -= dhd_console_ms; - /* Make sure backplane clock is on */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - if (dhdsdio_readconsole(bus) < 0) - dhd_console_ms = 0; /* On error, stop trying */ - } - } -#endif /* DHD_DEBUG */ - -#ifdef SDTEST - /* Generate packets if configured */ - if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) { - /* Make sure backplane clock is on */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - bus->pktgen_tick = 0; - dhdsdio_pktgen(bus); - } -#endif - - /* On idle timeout clear activity flag and/or turn off clock */ - if ((bus->idletime > 0) && (bus->clkstate == CLK_AVAIL)) { - if (++bus->idlecount >= bus->idletime) { - bus->idlecount = 0; - if (bus->activity) { - bus->activity = FALSE; - dhd_os_wd_timer(bus->dhd,dhd_watchdog_ms); - } else { - dhdsdio_clkctl(bus, CLK_NONE, FALSE); - } - } - } - - dhd_os_sdunlock(bus->dhd); - - return bus->ipend; -} - -#ifdef DHD_DEBUG -extern int -dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen) -{ - dhd_bus_t *bus = dhdp->bus; - uint32 addr, val; - int rv; - void *pkt; - - /* Address could be zero if CONSOLE := 0 in dongle Makefile */ - if (bus->console_addr == 0) - return BCME_UNSUPPORTED; - - /* Exclusive bus access */ - dhd_os_sdlock(bus->dhd); - - /* Don't allow input if dongle is in reset */ - if (bus->dhd->dongle_reset) { - dhd_os_sdunlock(bus->dhd); - return BCME_NOTREADY; - } - - /* Request clock to allow SDIO accesses */ - BUS_WAKE(bus); - /* No pend allowed since txpkt is called later, ht clk has to be on */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - /* Zero cbuf_index */ - addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf_idx); - val = htol32(0); - if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0) - goto done; - - /* Write message into cbuf */ - addr = bus->console_addr + OFFSETOF(hndrte_cons_t, cbuf); - if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)msg, msglen)) < 0) - goto done; - - /* Write length into vcons_in */ - addr = bus->console_addr + OFFSETOF(hndrte_cons_t, vcons_in); - val = htol32(msglen); - if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0) - goto done; - - /* Bump dongle by sending an empty event pkt. - * sdpcm_sendup (RX) checks for virtual console input. - */ - if (((pkt = PKTGET(bus->dhd->osh, 4 + SDPCM_RESERVE, TRUE)) != NULL) && - bus->clkstate == CLK_AVAIL) - dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, TRUE); - -done: - if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched) { - bus->activity = FALSE; - dhdsdio_clkctl(bus, CLK_NONE, TRUE); - } - - dhd_os_sdunlock(bus->dhd); - - return rv; -} -#endif /* DHD_DEBUG */ - -#ifdef DHD_DEBUG -static void -dhd_dump_cis(uint fn, uint8 *cis) -{ - uint byte, tag, tdata; - DHD_INFO(("Function %d CIS:\n", fn)); - - for (tdata = byte = 0; byte < SBSDIO_CIS_SIZE_LIMIT; byte++) { - if ((byte % 16) == 0) - DHD_INFO((" ")); - DHD_INFO(("%02x ", cis[byte])); - if ((byte % 16) == 15) - DHD_INFO(("\n")); - if (!tdata--) { - tag = cis[byte]; - if (tag == 0xff) - break; - else if (!tag) - tdata = 0; - else if ((byte + 1) < SBSDIO_CIS_SIZE_LIMIT) - tdata = cis[byte + 1] + 1; - else - DHD_INFO(("]")); - } - } - if ((byte % 16) != 15) - DHD_INFO(("\n")); -} -#endif /* DHD_DEBUG */ - -static bool -dhdsdio_chipmatch(uint16 chipid) -{ - if (chipid == BCM4325_CHIP_ID) - return TRUE; - if (chipid == BCM4329_CHIP_ID) - return TRUE; - if (chipid == BCM4315_CHIP_ID) - return TRUE; - if (chipid == BCM4319_CHIP_ID) - return TRUE; - return FALSE; -} - -static void * -dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, - uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh) -{ - int ret; - dhd_bus_t *bus; - - /* Init global variables at run-time, not as part of the declaration. - * This is required to support init/de-init of the driver. Initialization - * of globals as part of the declaration results in non-deterministic - * behavior since the value of the globals may be different on the - * first time that the driver is initialized vs subsequent initializations. - */ - dhd_txbound = DHD_TXBOUND; - dhd_rxbound = DHD_RXBOUND; - dhd_alignctl = TRUE; - sd1idle = TRUE; - dhd_readahead = TRUE; - retrydata = FALSE; - dhd_doflow = FALSE; - dhd_dongle_memsize = 0; - dhd_txminmax = DHD_TXMINMAX; - - forcealign = TRUE; - - - dhd_common_init(); - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - DHD_INFO(("%s: venid 0x%04x devid 0x%04x\n", __FUNCTION__, venid, devid)); - - /* We make assumptions about address window mappings */ - ASSERT((uintptr)regsva == SI_ENUM_BASE); - - /* BCMSDH passes venid and devid based on CIS parsing -- but low-power start - * means early parse could fail, so here we should get either an ID - * we recognize OR (-1) indicating we must request power first. - */ - /* Check the Vendor ID */ - switch (venid) { - case 0x0000: - case VENDOR_BROADCOM: - break; - default: - DHD_ERROR(("%s: unknown vendor: 0x%04x\n", - __FUNCTION__, venid)); - return NULL; - } - - /* Check the Device ID and make sure it's one that we support */ - switch (devid) { - case BCM4325_D11DUAL_ID: /* 4325 802.11a/g id */ - case BCM4325_D11G_ID: /* 4325 802.11g 2.4Ghz band id */ - case BCM4325_D11A_ID: /* 4325 802.11a 5Ghz band id */ - DHD_INFO(("%s: found 4325 Dongle\n", __FUNCTION__)); - break; - case BCM4329_D11NDUAL_ID: /* 4329 802.11n dualband device */ - case BCM4329_D11N2G_ID: /* 4329 802.11n 2.4G device */ - case BCM4329_D11N5G_ID: /* 4329 802.11n 5G device */ - case 0x4329: - DHD_INFO(("%s: found 4329 Dongle\n", __FUNCTION__)); - break; - case BCM4315_D11DUAL_ID: /* 4315 802.11a/g id */ - case BCM4315_D11G_ID: /* 4315 802.11g id */ - case BCM4315_D11A_ID: /* 4315 802.11a id */ - DHD_INFO(("%s: found 4315 Dongle\n", __FUNCTION__)); - break; - case BCM4319_D11N_ID: /* 4319 802.11n id */ - case BCM4319_D11N2G_ID: /* 4319 802.11n2g id */ - case BCM4319_D11N5G_ID: /* 4319 802.11n5g id */ - DHD_INFO(("%s: found 4319 Dongle\n", __FUNCTION__)); - break; - case 0: - DHD_INFO(("%s: allow device id 0, will check chip internals\n", - __FUNCTION__)); - break; - - default: - DHD_ERROR(("%s: skipping 0x%04x/0x%04x, not a dongle\n", - __FUNCTION__, venid, devid)); - return NULL; - } - - if (osh == NULL) { - /* Ask the OS interface part for an OSL handle */ - if (!(osh = dhd_osl_attach(sdh, DHD_BUS))) { - DHD_ERROR(("%s: osl_attach failed!\n", __FUNCTION__)); - return NULL; - } - } - - /* Allocate private bus interface state */ - if (!(bus = MALLOC(osh, sizeof(dhd_bus_t)))) { - DHD_ERROR(("%s: MALLOC of dhd_bus_t failed\n", __FUNCTION__)); - goto fail; - } - bzero(bus, sizeof(dhd_bus_t)); - bus->sdh = sdh; - bus->cl_devid = (uint16)devid; - bus->bus = DHD_BUS; - bus->tx_seq = SDPCM_SEQUENCE_WRAP - 1; - bus->usebufpool = FALSE; /* Use bufpool if allocated, else use locally malloced rxbuf */ - - /* attempt to attach to the dongle */ - if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) { - DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __FUNCTION__)); - goto fail; - } - - /* Attach to the dhd/OS/network interface */ - if (!(bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE))) { - DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__)); - goto fail; - } - - /* Allocate buffers */ - if (!(dhdsdio_probe_malloc(bus, osh, sdh))) { - DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__)); - goto fail; - } - - if (!(dhdsdio_probe_init(bus, osh, sdh))) { - DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __FUNCTION__)); - goto fail; - } - - /* Register interrupt callback, but mask it (not operational yet). */ - DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__)); - bcmsdh_intr_disable(sdh); - if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) { - DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n", - __FUNCTION__, ret)); - goto fail; - } - DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__)); - - DHD_INFO(("%s: completed!!\n", __FUNCTION__)); - - - /* if firmware path present try to download and bring up bus */ - if ((ret = dhd_bus_start(bus->dhd)) != 0) { - DHD_ERROR(("%s: failed\n", __FUNCTION__)); - goto fail; - if (ret == BCME_NOTUP) { - DHD_ERROR(("%s: dongle is not responding\n", __FUNCTION__)); - goto fail; - } - } - /* Ok, have the per-port tell the stack we're open for business */ - if (dhd_net_attach(bus->dhd, 0) != 0) { - DHD_ERROR(("%s: Net attach failed!!\n", __FUNCTION__)); - goto fail; - } - - return bus; - -fail: - dhdsdio_release(bus, osh); - return NULL; -} - - -static bool -dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, - uint16 devid) -{ - uint8 clkctl = 0; - int err = 0; - - bus->alp_only = TRUE; - - /* Return the window to backplane enumeration space for core access */ - if (dhdsdio_set_siaddr_window(bus, SI_ENUM_BASE)) { - DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __FUNCTION__)); - } - -#ifdef DHD_DEBUG - printf("F1 signature read @0x18000000=0x%4x\n", - bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4)); - - -#endif /* DHD_DEBUG */ - - - /* Force PLL off until si_attach() programs PLL control regs */ - - - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, DHD_INIT_CLKCTL1, &err); - if (!err) - clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - - if (err || ((clkctl & ~SBSDIO_AVBITS) != DHD_INIT_CLKCTL1)) { - DHD_ERROR(("dhdsdio_probe: ChipClkCSR access: err %d wrote 0x%02x read 0x%02x\n", - err, DHD_INIT_CLKCTL1, clkctl)); - goto fail; - } - - -#ifdef DHD_DEBUG - if (DHD_INFO_ON()) { - uint fn, numfn; - uint8 *cis[SDIOD_MAX_IOFUNCS]; - int err = 0; - - numfn = bcmsdh_query_iofnum(sdh); - ASSERT(numfn <= SDIOD_MAX_IOFUNCS); - - /* Make sure ALP is available before trying to read CIS */ - SPINWAIT(((clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, NULL)), - !SBSDIO_ALPAV(clkctl)), PMU_MAX_TRANSITION_DLY); - - /* Now request ALP be put on the bus */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - DHD_INIT_CLKCTL2, &err); - OSL_DELAY(65); - - for (fn = 0; fn <= numfn; fn++) { - if (!(cis[fn] = MALLOC(osh, SBSDIO_CIS_SIZE_LIMIT))) { - DHD_INFO(("dhdsdio_probe: fn %d cis malloc failed\n", fn)); - break; - } - bzero(cis[fn], SBSDIO_CIS_SIZE_LIMIT); - - if ((err = bcmsdh_cis_read(sdh, fn, cis[fn], SBSDIO_CIS_SIZE_LIMIT))) { - DHD_INFO(("dhdsdio_probe: fn %d cis read err %d\n", fn, err)); - MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); - break; - } - dhd_dump_cis(fn, cis[fn]); - } - - while (fn-- > 0) { - ASSERT(cis[fn]); - MFREE(osh, cis[fn], SBSDIO_CIS_SIZE_LIMIT); - } - - if (err) { - DHD_ERROR(("dhdsdio_probe: failure reading or parsing CIS\n")); - goto fail; - } - } -#endif /* DHD_DEBUG */ - - /* si_attach() will provide an SI handle and scan the backplane */ - if (!(bus->sih = si_attach((uint)devid, osh, regsva, DHD_BUS, sdh, - &bus->vars, &bus->varsz))) { - DHD_ERROR(("%s: si_attach failed!\n", __FUNCTION__)); - goto fail; - } - - bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); - - if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { - DHD_ERROR(("%s: unsupported chip: 0x%04x\n", - __FUNCTION__, bus->sih->chip)); - goto fail; - } - - si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength); - - - /* Get info on the ARM and SOCRAM cores... */ - if (!DHD_NOPMU(bus)) { - if ((si_setcore(bus->sih, ARM7S_CORE_ID, 0)) || - (si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { - bus->armrev = si_corerev(bus->sih); - } else { - DHD_ERROR(("%s: failed to find ARM core!\n", __FUNCTION__)); - goto fail; - } - if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { - DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__)); - goto fail; - } - bus->ramsize = bus->orig_ramsize; - if (dhd_dongle_memsize) - dhd_dongle_setmemsize(bus, dhd_dongle_memsize); - - DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n", - bus->ramsize, bus->orig_ramsize)); - } - - /* ...but normally deal with the SDPCMDEV core */ - if (!(bus->regs = si_setcore(bus->sih, PCMCIA_CORE_ID, 0)) && - !(bus->regs = si_setcore(bus->sih, SDIOD_CORE_ID, 0))) { - DHD_ERROR(("%s: failed to find SDIODEV core!\n", __FUNCTION__)); - goto fail; - } - bus->sdpcmrev = si_corerev(bus->sih); - - /* Set core control so an SDIO reset does a backplane reset */ - OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN); - - pktq_init(&bus->txq, (PRIOMASK + 1), QLEN); - - /* Locate an appropriately-aligned portion of hdrbuf */ - bus->rxhdr = (uint8 *)ROUNDUP((uintptr)&bus->hdrbuf[0], DHD_SDALIGN); - - /* Set the poll and/or interrupt flags */ - bus->intr = (bool)dhd_intr; - if ((bus->poll = (bool)dhd_poll)) - bus->pollrate = 1; - - return TRUE; - -fail: - return FALSE; -} - -static bool -dhdsdio_probe_malloc(dhd_bus_t *bus, osl_t *osh, void *sdh) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - -#ifndef DHD_USE_STATIC_BUF - if (bus->dhd->maxctl) { - bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; - if (!(bus->rxbuf = MALLOC(osh, bus->rxblen))) { - DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n", - __FUNCTION__, bus->rxblen)); - goto fail; - } - } - - /* Allocate buffer to receive glomed packet */ - if (!(bus->databuf = MALLOC(osh, MAX_DATA_BUF))) { - DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n", - __FUNCTION__, MAX_DATA_BUF)); - /* release rxbuf which was already located as above */ - if (!bus->rxblen) MFREE(osh, bus->rxbuf, bus->rxblen); - goto fail; - } -#else - if (bus->dhd->maxctl) { - bus->rxblen = ROUNDUP((bus->dhd->maxctl + SDPCM_HDRLEN), ALIGNMENT) + DHD_SDALIGN; - if (!(bus->rxbuf = dhd_os_prealloc(DHD_PREALLOC_RXBUF, bus->rxblen))) { - DHD_ERROR(("%s: MALLOC of %d-byte rxbuf failed\n", - __FUNCTION__, bus->rxblen)); - goto fail; - } - } - /* Allocate buffer to receive glomed packet */ - if (!(bus->databuf = dhd_os_prealloc(DHD_PREALLOC_DATABUF, MAX_DATA_BUF))) { - DHD_ERROR(("%s: MALLOC of %d-byte databuf failed\n", - __FUNCTION__, MAX_DATA_BUF)); - goto fail; - } -#endif /* DHD_USE_STATIC_BUF */ - - /* Align the buffer */ - if ((uintptr)bus->databuf % DHD_SDALIGN) - bus->dataptr = bus->databuf + (DHD_SDALIGN - ((uintptr)bus->databuf % DHD_SDALIGN)); - else - bus->dataptr = bus->databuf; - - return TRUE; - -fail: - return FALSE; -} - - -static bool -dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh) -{ - int32 fnum; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - -#ifdef SDTEST - dhdsdio_pktgen_init(bus); -#endif /* SDTEST */ - - /* Disable F2 to clear any intermediate frame state on the dongle */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); - - bus->dhd->busstate = DHD_BUS_DOWN; - bus->sleeping = FALSE; - bus->rxflow = FALSE; - bus->prev_rxlim_hit = 0; - - - /* Done with backplane-dependent accesses, can drop clock... */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, 0, NULL); - - /* ...and initialize clock/power states */ - bus->clkstate = CLK_SDONLY; - bus->idletime = (int32)dhd_idletime; - bus->idleclock = DHD_IDLE_ACTIVE; - - /* Query the SD clock speed */ - if (bcmsdh_iovar_op(sdh, "sd_divisor", NULL, 0, - &bus->sd_divisor, sizeof(int32), FALSE) != BCME_OK) { - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_divisor")); - bus->sd_divisor = -1; - } else { - DHD_INFO(("%s: Initial value for %s is %d\n", - __FUNCTION__, "sd_divisor", bus->sd_divisor)); - } - - /* Query the SD bus mode */ - if (bcmsdh_iovar_op(sdh, "sd_mode", NULL, 0, - &bus->sd_mode, sizeof(int32), FALSE) != BCME_OK) { - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_mode")); - bus->sd_mode = -1; - } else { - DHD_INFO(("%s: Initial value for %s is %d\n", - __FUNCTION__, "sd_mode", bus->sd_mode)); - } - - /* Query the F2 block size, set roundup accordingly */ - fnum = 2; - if (bcmsdh_iovar_op(sdh, "sd_blocksize", &fnum, sizeof(int32), - &bus->blocksize, sizeof(int32), FALSE) != BCME_OK) { - bus->blocksize = 0; - DHD_ERROR(("%s: fail on %s get\n", __FUNCTION__, "sd_blocksize")); - } else { - DHD_INFO(("%s: Initial value for %s is %d\n", - __FUNCTION__, "sd_blocksize", bus->blocksize)); - } - bus->roundup = MIN(max_roundup, bus->blocksize); - - /* Query if bus module supports packet chaining, default to use if supported */ - if (bcmsdh_iovar_op(sdh, "sd_rxchain", NULL, 0, - &bus->sd_rxchain, sizeof(int32), FALSE) != BCME_OK) { - bus->sd_rxchain = FALSE; - } else { - DHD_INFO(("%s: bus module (through bcmsdh API) %s chaining\n", - __FUNCTION__, (bus->sd_rxchain ? "supports" : "does not support"))); - } - bus->use_rxchain = (bool)bus->sd_rxchain; - - return TRUE; -} - -bool -dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh, - char *fw_path, char *nv_path) -{ - bool ret; - bus->fw_path = fw_path; - bus->nv_path = nv_path; - - ret = dhdsdio_download_firmware(bus, osh, bus->sdh); - - - return ret; -} - -static bool -dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh) -{ - bool ret; - - /* Download the firmware */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - - ret = _dhdsdio_download_firmware(bus) == 0; - - dhdsdio_clkctl(bus, CLK_SDONLY, FALSE); - - return ret; -} - -/* Detach and free everything */ -static void -dhdsdio_release(dhd_bus_t *bus, osl_t *osh) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (bus) { - ASSERT(osh); - - - /* De-register interrupt handler */ - bcmsdh_intr_disable(bus->sdh); - bcmsdh_intr_dereg(bus->sdh); - - if (bus->dhd) { - - dhdsdio_release_dongle(bus, osh); - - dhd_detach(bus->dhd); - bus->dhd = NULL; - } - - dhdsdio_release_malloc(bus, osh); - - - MFREE(osh, bus, sizeof(dhd_bus_t)); - } - - if (osh) - dhd_osl_detach(osh); - - DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); -} - -static void -dhdsdio_release_malloc(dhd_bus_t *bus, osl_t *osh) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (bus->dhd && bus->dhd->dongle_reset) - return; - - if (bus->rxbuf) { -#ifndef DHD_USE_STATIC_BUF - MFREE(osh, bus->rxbuf, bus->rxblen); -#endif - bus->rxctl = bus->rxbuf = NULL; - bus->rxlen = 0; - } - - if (bus->databuf) { -#ifndef DHD_USE_STATIC_BUF - MFREE(osh, bus->databuf, MAX_DATA_BUF); -#endif - bus->databuf = NULL; - } -} - - -static void -dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (bus->dhd && bus->dhd->dongle_reset) - return; - - if (bus->sih) { - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); -#if !defined(BCMLXSDMMC) - si_watchdog(bus->sih, 4); -#endif /* !defined(BCMLXSDMMC) */ - dhdsdio_clkctl(bus, CLK_NONE, FALSE); - si_detach(bus->sih); - if (bus->vars && bus->varsz) - MFREE(osh, bus->vars, bus->varsz); - bus->vars = NULL; - } - - DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); -} - -static void -dhdsdio_disconnect(void *ptr) -{ - dhd_bus_t *bus = (dhd_bus_t *)ptr; - - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - if (bus) { - ASSERT(bus->dhd); - dhdsdio_release(bus, bus->dhd->osh); - } - - DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); -} - - -/* Register/Unregister functions are called by the main DHD entry - * point (e.g. module insertion) to link with the bus driver, in - * order to look for or await the device. - */ - -static bcmsdh_driver_t dhd_sdio = { - dhdsdio_probe, - dhdsdio_disconnect -}; - -int -dhd_bus_register(void) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - return bcmsdh_register(&dhd_sdio); -} - -void -dhd_bus_unregister(void) -{ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - - bcmsdh_unregister(); -} - -#ifdef BCMEMBEDIMAGE -static int -dhdsdio_download_code_array(struct dhd_bus *bus) -{ - int bcmerror = -1; - int offset = 0; - - DHD_INFO(("%s: download embedded firmware...\n", __FUNCTION__)); - - /* Download image */ - while ((offset + MEMBLOCK) < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, TRUE, offset, dlarray + offset, MEMBLOCK); - if (bcmerror) { - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto err; - } - - offset += MEMBLOCK; - } - - if (offset < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, TRUE, offset, - dlarray + offset, sizeof(dlarray) - offset); - if (bcmerror) { - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); - goto err; - } - } - -#ifdef DHD_DEBUG - /* Upload and compare the downloaded code */ - { - unsigned char *ularray; - - ularray = MALLOC(bus->dhd->osh, bus->ramsize); - /* Upload image to verify downloaded contents. */ - offset = 0; - memset(ularray, 0xaa, bus->ramsize); - while ((offset + MEMBLOCK) < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, FALSE, offset, ularray + offset, MEMBLOCK); - if (bcmerror) { - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto err; - } - - offset += MEMBLOCK; - } - - if (offset < sizeof(dlarray)) { - bcmerror = dhdsdio_membytes(bus, FALSE, offset, - ularray + offset, sizeof(dlarray) - offset); - if (bcmerror) { - DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset)); - goto err; - } - } - - if (memcmp(dlarray, ularray, sizeof(dlarray))) { - DHD_ERROR(("%s: Downloaded image is corrupted.\n", __FUNCTION__)); - ASSERT(0); - goto err; - } else - DHD_ERROR(("%s: Download, Upload and compare succeeded.\n", __FUNCTION__)); - - MFREE(bus->dhd->osh, ularray, bus->ramsize); - } -#endif /* DHD_DEBUG */ - -err: - return bcmerror; -} -#endif /* BCMEMBEDIMAGE */ - -static int -dhdsdio_download_code_file(struct dhd_bus *bus, char *fw_path) -{ - int bcmerror = -1; - int offset = 0; - uint len; - void *image = NULL; - uint8 *memblock = NULL, *memptr; - - DHD_INFO(("%s: download firmware %s\n", __FUNCTION__, fw_path)); - - image = dhd_os_open_image(fw_path); - if (image == NULL) - goto err; - - memptr = memblock = MALLOC(bus->dhd->osh, MEMBLOCK + DHD_SDALIGN); - if (memblock == NULL) { - DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__, MEMBLOCK)); - goto err; - } - if ((uint32)(uintptr)memblock % DHD_SDALIGN) - memptr += (DHD_SDALIGN - ((uint32)(uintptr)memblock % DHD_SDALIGN)); - - /* Download image */ - while ((len = dhd_os_get_image_block((char*)memptr, MEMBLOCK, image))) { - bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len); - if (bcmerror) { - DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", - __FUNCTION__, bcmerror, MEMBLOCK, offset)); - goto err; - } - - offset += MEMBLOCK; - } - -err: - if (memblock) - MFREE(bus->dhd->osh, memblock, MEMBLOCK + DHD_SDALIGN); - - if (image) - dhd_os_close_image(image); - - return bcmerror; -} - -/* - * ProcessVars:Takes a buffer of "=\n" lines read from a file and ending in a NUL. - * Removes carriage returns, empty lines, comment lines, and converts newlines to NULs. - * Shortens buffer as needed and pads with NULs. End of buffer is marked by two NULs. -*/ - -static uint -process_nvram_vars(char *varbuf, uint len) -{ - char *dp; - bool findNewline; - int column; - uint buf_len, n; - - dp = varbuf; - - findNewline = FALSE; - column = 0; - - for (n = 0; n < len; n++) { - if (varbuf[n] == 0) - break; - if (varbuf[n] == '\r') - continue; - if (findNewline && varbuf[n] != '\n') - continue; - findNewline = FALSE; - if (varbuf[n] == '#') { - findNewline = TRUE; - continue; - } - if (varbuf[n] == '\n') { - if (column == 0) - continue; - *dp++ = 0; - column = 0; - continue; - } - *dp++ = varbuf[n]; - column++; - } - buf_len = dp - varbuf; - - while (dp < varbuf + n) - *dp++ = 0; - - return buf_len; -} - -/* - EXAMPLE: nvram_array - nvram_arry format: - name=value - Use carriage return at the end of each assignment, and an empty string with - carriage return at the end of array. - - For example: - unsigned char nvram_array[] = {"name1=value1\n", "name2=value2\n", "\n"}; - Hex values start with 0x, and mac addr format: xx:xx:xx:xx:xx:xx. - - Search "EXAMPLE: nvram_array" to see how the array is activated. -*/ - -void -dhd_bus_set_nvram_params(struct dhd_bus * bus, const char *nvram_params) -{ - bus->nvram_params = nvram_params; -} - -static int -dhdsdio_download_nvram(struct dhd_bus *bus) -{ - int bcmerror = -1; - uint len; - void * image = NULL; - char * memblock = NULL; - char *bufp; - char *nv_path; - bool nvram_file_exists; - - nv_path = bus->nv_path; - - nvram_file_exists = ((nv_path != NULL) && (nv_path[0] != '\0')); - if (!nvram_file_exists && (bus->nvram_params == NULL)) - return (0); - - if (nvram_file_exists) { - image = dhd_os_open_image(nv_path); - if (image == NULL) - goto err; - } - - memblock = MALLOC(bus->dhd->osh, MEMBLOCK); - if (memblock == NULL) { - DHD_ERROR(("%s: Failed to allocate memory %d bytes\n", - __FUNCTION__, MEMBLOCK)); - goto err; - } - - /* Download variables */ - if (nvram_file_exists) { - len = dhd_os_get_image_block(memblock, MEMBLOCK, image); - } - else { - len = strlen(bus->nvram_params); - ASSERT(len <= MEMBLOCK); - if (len > MEMBLOCK) - len = MEMBLOCK; - memcpy(memblock, bus->nvram_params, len); - } - - if (len > 0 && len < MEMBLOCK) { - bufp = (char *)memblock; - bufp[len] = 0; - len = process_nvram_vars(bufp, len); - bufp += len; - *bufp++ = 0; - if (len) - bcmerror = dhdsdio_downloadvars(bus, memblock, len + 1); - if (bcmerror) { - DHD_ERROR(("%s: error downloading vars: %d\n", - __FUNCTION__, bcmerror)); - } - } - else { - DHD_ERROR(("%s: error reading nvram file: %d\n", - __FUNCTION__, len)); - bcmerror = BCME_SDIO_ERROR; - } - -err: - if (memblock) - MFREE(bus->dhd->osh, memblock, MEMBLOCK); - - if (image) - dhd_os_close_image(image); - - return bcmerror; -} - -static int -_dhdsdio_download_firmware(struct dhd_bus *bus) -{ - int bcmerror = -1; - - bool embed = FALSE; /* download embedded firmware */ - bool dlok = FALSE; /* download firmware succeeded */ - - /* Out immediately if no image to download */ - if ((bus->fw_path == NULL) || (bus->fw_path[0] == '\0')) { -#ifdef BCMEMBEDIMAGE - embed = TRUE; -#else - return bcmerror; -#endif - } - - /* Keep arm in reset */ - if (dhdsdio_download_state(bus, TRUE)) { - DHD_ERROR(("%s: error placing ARM core in reset\n", __FUNCTION__)); - goto err; - } - - /* External image takes precedence if specified */ - if ((bus->fw_path != NULL) && (bus->fw_path[0] != '\0')) { - if (dhdsdio_download_code_file(bus, bus->fw_path)) { - DHD_ERROR(("%s: dongle image file download failed\n", __FUNCTION__)); -#ifdef BCMEMBEDIMAGE - embed = TRUE; -#else - goto err; -#endif - } - else { - embed = FALSE; - dlok = TRUE; - } - } -#ifdef BCMEMBEDIMAGE - if (embed) { - if (dhdsdio_download_code_array(bus)) { - DHD_ERROR(("%s: dongle image array download failed\n", __FUNCTION__)); - goto err; - } - else { - dlok = TRUE; - } - } -#endif - if (!dlok) { - DHD_ERROR(("%s: dongle image download failed\n", __FUNCTION__)); - goto err; - } - - /* EXAMPLE: nvram_array */ - /* If a valid nvram_arry is specified as above, it can be passed down to dongle */ - /* dhd_bus_set_nvram_params(bus, (char *)&nvram_array); */ - - /* External nvram takes precedence if specified */ - if (dhdsdio_download_nvram(bus)) { - DHD_ERROR(("%s: dongle nvram file download failed\n", __FUNCTION__)); - } - - /* Take arm out of reset */ - if (dhdsdio_download_state(bus, FALSE)) { - DHD_ERROR(("%s: error getting out of ARM core reset\n", __FUNCTION__)); - goto err; - } - - bcmerror = 0; - -err: - return bcmerror; -} - -static int -dhd_bcmsdh_recv_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, - void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) -{ - int status; - - /* 4329: GSPI check */ - status = bcmsdh_recv_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle); - return status; -} - -static int -dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, - void *pkt, bcmsdh_cmplt_fn_t complete, void *handle) -{ - return (bcmsdh_send_buf(bus->sdh, addr, fn, flags, buf, nbytes, pkt, complete, handle)); -} - -uint -dhd_bus_chip(struct dhd_bus *bus) -{ - ASSERT(bus->sih != NULL); - return bus->sih->chip; -} - -void * -dhd_bus_pub(struct dhd_bus *bus) -{ - return bus->dhd; -} - -void * -dhd_bus_txq(struct dhd_bus *bus) -{ - return &bus->txq; -} - -uint -dhd_bus_hdrlen(struct dhd_bus *bus) -{ - return SDPCM_HDRLEN; -} - -int -dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag) -{ - int bcmerror = 0; - dhd_bus_t *bus; - - bus = dhdp->bus; - - if (flag == TRUE) { - if (!bus->dhd->dongle_reset) { -#if !defined(IGNORE_ETH0_DOWN) - /* Force flow control as protection when stop come before ifconfig_down */ - dhd_txflowcontrol(bus->dhd, 0, ON); -#endif /* !defined(IGNORE_ETH0_DOWN) */ - /* save country settinng if was pre-setup with priv ioctl */ - dhd_os_proto_block(dhdp); - dhdcdc_query_ioctl(bus->dhd, 0, WLC_GET_COUNTRY, - bus->dhd->country_code, sizeof(bus->dhd->country_code)); - dhd_os_proto_unblock(dhdp); - /* Expect app to have torn down any connection before calling */ - /* Stop the bus, disable F2 */ - dhd_bus_stop(bus, FALSE); - - /* Clean tx/rx buffer pointers, detach from the dongle */ - dhdsdio_release_dongle(bus, bus->dhd->osh); - - bus->dhd->dongle_reset = TRUE; - bus->dhd->up = FALSE; - - DHD_TRACE(("%s: WLAN OFF DONE\n", __FUNCTION__)); - /* App can now remove power from device */ - } else - bcmerror = BCME_SDIO_ERROR; - } else { - /* App must have restored power to device before calling */ - - DHD_TRACE(("\n\n%s: == WLAN ON ==\n", __FUNCTION__)); - - if (bus->dhd->dongle_reset) { - /* Turn on WLAN */ - /* Reset SD client */ - bcmsdh_reset(bus->sdh); - - /* Attempt to re-attach & download */ - if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh, - (uint32 *)SI_ENUM_BASE, - bus->cl_devid)) { - /* Attempt to download binary to the dongle */ - if (dhdsdio_probe_init(bus, bus->dhd->osh, bus->sdh) && - dhdsdio_download_firmware(bus, bus->dhd->osh, bus->sdh)) { - - /* Re-init bus, enable F2 transfer */ - dhd_bus_init((dhd_pub_t *) bus->dhd, FALSE); - -#if defined(OOB_INTR_ONLY) - dhd_enable_oob_intr(bus, TRUE); -#endif /* defined(OOB_INTR_ONLY) */ - - bus->dhd->dongle_reset = FALSE; - bus->dhd->up = TRUE; - -#if !defined(IGNORE_ETH0_DOWN) - /* Restore flow control */ - dhd_txflowcontrol(bus->dhd, 0, OFF); -#endif - - DHD_TRACE(("%s: WLAN ON DONE\n", __FUNCTION__)); - } else - bcmerror = BCME_SDIO_ERROR; - } else - bcmerror = BCME_SDIO_ERROR; - } else { - bcmerror = BCME_NOTDOWN; - DHD_ERROR(("%s: Set DEVRESET=FALSE invoked when device is on\n", - __FUNCTION__)); - bcmerror = BCME_SDIO_ERROR; - } - } - return bcmerror; -} diff --git a/drivers/net/wireless/bcm4329/dngl_stats.h b/drivers/net/wireless/bcm4329/dngl_stats.h deleted file mode 100644 index e5db54e7edfe..000000000000 --- a/drivers/net/wireless/bcm4329/dngl_stats.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Common stats definitions for clients of dongle - * ports - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dngl_stats.h,v 1.2.140.3 2008/05/26 16:52:08 Exp $ - */ - -#ifndef _dngl_stats_h_ -#define _dngl_stats_h_ - -typedef struct { - unsigned long rx_packets; /* total packets received */ - unsigned long tx_packets; /* total packets transmitted */ - unsigned long rx_bytes; /* total bytes received */ - unsigned long tx_bytes; /* total bytes transmitted */ - unsigned long rx_errors; /* bad packets received */ - unsigned long tx_errors; /* packet transmit problems */ - unsigned long rx_dropped; /* packets dropped by dongle */ - unsigned long tx_dropped; /* packets dropped by dongle */ - unsigned long multicast; /* multicast packets received */ -} dngl_stats_t; - -#endif /* _dngl_stats_h_ */ diff --git a/drivers/net/wireless/bcm4329/hndpmu.c b/drivers/net/wireless/bcm4329/hndpmu.c deleted file mode 100644 index 307347a43bde..000000000000 --- a/drivers/net/wireless/bcm4329/hndpmu.c +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Misc utility routines for accessing PMU corerev specific features - * of the SiliconBackplane-based Broadcom chips. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: hndpmu.c,v 1.95.2.17.4.11.2.63 2010/07/21 13:55:09 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* debug/trace */ -#define PMU_ERROR(args) - -#define PMU_MSG(args) - - -/* SDIO Pad drive strength to select value mappings */ -typedef struct { - uint8 strength; /* Pad Drive Strength in mA */ - uint8 sel; /* Chip-specific select value */ -} sdiod_drive_str_t; - -/* SDIO Drive Strength to sel value table for PMU Rev 1 */ -static const sdiod_drive_str_t sdiod_drive_strength_tab1[] = { - {4, 0x2}, - {2, 0x3}, - {1, 0x0}, - {0, 0x0} }; - -/* SDIO Drive Strength to sel value table for PMU Rev 2, 3 */ -static const sdiod_drive_str_t sdiod_drive_strength_tab2[] = { - {12, 0x7}, - {10, 0x6}, - {8, 0x5}, - {6, 0x4}, - {4, 0x2}, - {2, 0x1}, - {0, 0x0} }; - -#define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) - -void -si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength) -{ - chipcregs_t *cc; - uint origidx, intr_val = 0; - sdiod_drive_str_t *str_tab = NULL; - uint32 str_mask = 0; - uint32 str_shift = 0; - - if (!(sih->cccaps & CC_CAP_PMU)) { - return; - } - - /* Remember original core before switch to chipc */ - cc = (chipcregs_t *) si_switch_core(sih, CC_CORE_ID, &origidx, &intr_val); - - switch (SDIOD_DRVSTR_KEY(sih->chip, sih->pmurev)) { - case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 1): - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab1; - str_mask = 0x30000000; - str_shift = 28; - break; - case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 2): - case SDIOD_DRVSTR_KEY(BCM4325_CHIP_ID, 3): - case SDIOD_DRVSTR_KEY(BCM4315_CHIP_ID, 4): - str_tab = (sdiod_drive_str_t *)&sdiod_drive_strength_tab2; - str_mask = 0x00003800; - str_shift = 11; - break; - - default: - PMU_MSG(("No SDIO Drive strength init done for chip %x rev %d pmurev %d\n", - sih->chip, sih->chiprev, sih->pmurev)); - - break; - } - - if (str_tab != NULL) { - uint32 drivestrength_sel = 0; - uint32 cc_data_temp; - int i; - - for (i = 0; str_tab[i].strength != 0; i ++) { - if (drivestrength >= str_tab[i].strength) { - drivestrength_sel = str_tab[i].sel; - break; - } - } - - W_REG(osh, &cc->chipcontrol_addr, 1); - cc_data_temp = R_REG(osh, &cc->chipcontrol_data); - cc_data_temp &= ~str_mask; - drivestrength_sel <<= str_shift; - cc_data_temp |= drivestrength_sel; - W_REG(osh, &cc->chipcontrol_data, cc_data_temp); - - PMU_MSG(("SDIO: %dmA drive strength selected, set to 0x%08x\n", - drivestrength, cc_data_temp)); - } - - /* Return to original core */ - si_restore_core(sih, origidx, intr_val); -} diff --git a/drivers/net/wireless/bcm4329/include/Makefile b/drivers/net/wireless/bcm4329/include/Makefile deleted file mode 100644 index 439ead14a0e6..000000000000 --- a/drivers/net/wireless/bcm4329/include/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# include/Makefile -# -# Copyright 2005, Broadcom, Inc. -# -# $Id: Makefile,v 13.5 2005/02/17 19:11:31 Exp $ -# - -SRCBASE = .. - -TARGETS = epivers.h - - -all release: - bash epivers.sh - -clean: - rm -rf ${TARGETS} *.prev - - -.PHONY: all release clean diff --git a/drivers/net/wireless/bcm4329/include/aidmp.h b/drivers/net/wireless/bcm4329/include/aidmp.h deleted file mode 100644 index a927e5dae586..000000000000 --- a/drivers/net/wireless/bcm4329/include/aidmp.h +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Broadcom AMBA Interconnect definitions. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: aidmp.h,v 13.2.10.1 2008/05/07 20:32:12 Exp $ - */ - - -#ifndef _AIDMP_H -#define _AIDMP_H - - -#define MFGID_ARM 0x43b -#define MFGID_BRCM 0x4bf -#define MFGID_MIPS 0x4a7 - - -#define CC_SIM 0 -#define CC_EROM 1 -#define CC_CORESIGHT 9 -#define CC_VERIF 0xb -#define CC_OPTIMO 0xd -#define CC_GEN 0xe -#define CC_PRIMECELL 0xf - - -#define ER_EROMENTRY 0x000 -#define ER_REMAPCONTROL 0xe00 -#define ER_REMAPSELECT 0xe04 -#define ER_MASTERSELECT 0xe10 -#define ER_ITCR 0xf00 -#define ER_ITIP 0xf04 - - -#define ER_TAG 0xe -#define ER_TAG1 0x6 -#define ER_VALID 1 -#define ER_CI 0 -#define ER_MP 2 -#define ER_ADD 4 -#define ER_END 0xe -#define ER_BAD 0xffffffff - - -#define CIA_MFG_MASK 0xfff00000 -#define CIA_MFG_SHIFT 20 -#define CIA_CID_MASK 0x000fff00 -#define CIA_CID_SHIFT 8 -#define CIA_CCL_MASK 0x000000f0 -#define CIA_CCL_SHIFT 4 - - -#define CIB_REV_MASK 0xff000000 -#define CIB_REV_SHIFT 24 -#define CIB_NSW_MASK 0x00f80000 -#define CIB_NSW_SHIFT 19 -#define CIB_NMW_MASK 0x0007c000 -#define CIB_NMW_SHIFT 14 -#define CIB_NSP_MASK 0x00003e00 -#define CIB_NSP_SHIFT 9 -#define CIB_NMP_MASK 0x000001f0 -#define CIB_NMP_SHIFT 4 - - -#define MPD_MUI_MASK 0x0000ff00 -#define MPD_MUI_SHIFT 8 -#define MPD_MP_MASK 0x000000f0 -#define MPD_MP_SHIFT 4 - - -#define AD_ADDR_MASK 0xfffff000 -#define AD_SP_MASK 0x00000f00 -#define AD_SP_SHIFT 8 -#define AD_ST_MASK 0x000000c0 -#define AD_ST_SHIFT 6 -#define AD_ST_SLAVE 0x00000000 -#define AD_ST_BRIDGE 0x00000040 -#define AD_ST_SWRAP 0x00000080 -#define AD_ST_MWRAP 0x000000c0 -#define AD_SZ_MASK 0x00000030 -#define AD_SZ_SHIFT 4 -#define AD_SZ_4K 0x00000000 -#define AD_SZ_8K 0x00000010 -#define AD_SZ_16K 0x00000020 -#define AD_SZ_SZD 0x00000030 -#define AD_AG32 0x00000008 -#define AD_ADDR_ALIGN 0x00000fff -#define AD_SZ_BASE 0x00001000 - - -#define SD_SZ_MASK 0xfffff000 -#define SD_SG32 0x00000008 -#define SD_SZ_ALIGN 0x00000fff - - -#ifndef _LANGUAGE_ASSEMBLY - -typedef volatile struct _aidmp { - uint32 oobselina30; - uint32 oobselina74; - uint32 PAD[6]; - uint32 oobselinb30; - uint32 oobselinb74; - uint32 PAD[6]; - uint32 oobselinc30; - uint32 oobselinc74; - uint32 PAD[6]; - uint32 oobselind30; - uint32 oobselind74; - uint32 PAD[38]; - uint32 oobselouta30; - uint32 oobselouta74; - uint32 PAD[6]; - uint32 oobseloutb30; - uint32 oobseloutb74; - uint32 PAD[6]; - uint32 oobseloutc30; - uint32 oobseloutc74; - uint32 PAD[6]; - uint32 oobseloutd30; - uint32 oobseloutd74; - uint32 PAD[38]; - uint32 oobsynca; - uint32 oobseloutaen; - uint32 PAD[6]; - uint32 oobsyncb; - uint32 oobseloutben; - uint32 PAD[6]; - uint32 oobsyncc; - uint32 oobseloutcen; - uint32 PAD[6]; - uint32 oobsyncd; - uint32 oobseloutden; - uint32 PAD[38]; - uint32 oobaextwidth; - uint32 oobainwidth; - uint32 oobaoutwidth; - uint32 PAD[5]; - uint32 oobbextwidth; - uint32 oobbinwidth; - uint32 oobboutwidth; - uint32 PAD[5]; - uint32 oobcextwidth; - uint32 oobcinwidth; - uint32 oobcoutwidth; - uint32 PAD[5]; - uint32 oobdextwidth; - uint32 oobdinwidth; - uint32 oobdoutwidth; - uint32 PAD[37]; - uint32 ioctrlset; - uint32 ioctrlclear; - uint32 ioctrl; - uint32 PAD[61]; - uint32 iostatus; - uint32 PAD[127]; - uint32 ioctrlwidth; - uint32 iostatuswidth; - uint32 PAD[62]; - uint32 resetctrl; - uint32 resetstatus; - uint32 resetreadid; - uint32 resetwriteid; - uint32 PAD[60]; - uint32 errlogctrl; - uint32 errlogdone; - uint32 errlogstatus; - uint32 errlogaddrlo; - uint32 errlogaddrhi; - uint32 errlogid; - uint32 errloguser; - uint32 errlogflags; - uint32 PAD[56]; - uint32 intstatus; - uint32 PAD[127]; - uint32 config; - uint32 PAD[63]; - uint32 itcr; - uint32 PAD[3]; - uint32 itipooba; - uint32 itipoobb; - uint32 itipoobc; - uint32 itipoobd; - uint32 PAD[4]; - uint32 itipoobaout; - uint32 itipoobbout; - uint32 itipoobcout; - uint32 itipoobdout; - uint32 PAD[4]; - uint32 itopooba; - uint32 itopoobb; - uint32 itopoobc; - uint32 itopoobd; - uint32 PAD[4]; - uint32 itopoobain; - uint32 itopoobbin; - uint32 itopoobcin; - uint32 itopoobdin; - uint32 PAD[4]; - uint32 itopreset; - uint32 PAD[15]; - uint32 peripherialid4; - uint32 peripherialid5; - uint32 peripherialid6; - uint32 peripherialid7; - uint32 peripherialid0; - uint32 peripherialid1; - uint32 peripherialid2; - uint32 peripherialid3; - uint32 componentid0; - uint32 componentid1; - uint32 componentid2; - uint32 componentid3; -} aidmp_t; - -#endif - - -#define OOB_BUSCONFIG 0x020 -#define OOB_STATUSA 0x100 -#define OOB_STATUSB 0x104 -#define OOB_STATUSC 0x108 -#define OOB_STATUSD 0x10c -#define OOB_ENABLEA0 0x200 -#define OOB_ENABLEA1 0x204 -#define OOB_ENABLEA2 0x208 -#define OOB_ENABLEA3 0x20c -#define OOB_ENABLEB0 0x280 -#define OOB_ENABLEB1 0x284 -#define OOB_ENABLEB2 0x288 -#define OOB_ENABLEB3 0x28c -#define OOB_ENABLEC0 0x300 -#define OOB_ENABLEC1 0x304 -#define OOB_ENABLEC2 0x308 -#define OOB_ENABLEC3 0x30c -#define OOB_ENABLED0 0x380 -#define OOB_ENABLED1 0x384 -#define OOB_ENABLED2 0x388 -#define OOB_ENABLED3 0x38c -#define OOB_ITCR 0xf00 -#define OOB_ITIPOOBA 0xf10 -#define OOB_ITIPOOBB 0xf14 -#define OOB_ITIPOOBC 0xf18 -#define OOB_ITIPOOBD 0xf1c -#define OOB_ITOPOOBA 0xf30 -#define OOB_ITOPOOBB 0xf34 -#define OOB_ITOPOOBC 0xf38 -#define OOB_ITOPOOBD 0xf3c - - -#define AI_OOBSELINA30 0x000 -#define AI_OOBSELINA74 0x004 -#define AI_OOBSELINB30 0x020 -#define AI_OOBSELINB74 0x024 -#define AI_OOBSELINC30 0x040 -#define AI_OOBSELINC74 0x044 -#define AI_OOBSELIND30 0x060 -#define AI_OOBSELIND74 0x064 -#define AI_OOBSELOUTA30 0x100 -#define AI_OOBSELOUTA74 0x104 -#define AI_OOBSELOUTB30 0x120 -#define AI_OOBSELOUTB74 0x124 -#define AI_OOBSELOUTC30 0x140 -#define AI_OOBSELOUTC74 0x144 -#define AI_OOBSELOUTD30 0x160 -#define AI_OOBSELOUTD74 0x164 -#define AI_OOBSYNCA 0x200 -#define AI_OOBSELOUTAEN 0x204 -#define AI_OOBSYNCB 0x220 -#define AI_OOBSELOUTBEN 0x224 -#define AI_OOBSYNCC 0x240 -#define AI_OOBSELOUTCEN 0x244 -#define AI_OOBSYNCD 0x260 -#define AI_OOBSELOUTDEN 0x264 -#define AI_OOBAEXTWIDTH 0x300 -#define AI_OOBAINWIDTH 0x304 -#define AI_OOBAOUTWIDTH 0x308 -#define AI_OOBBEXTWIDTH 0x320 -#define AI_OOBBINWIDTH 0x324 -#define AI_OOBBOUTWIDTH 0x328 -#define AI_OOBCEXTWIDTH 0x340 -#define AI_OOBCINWIDTH 0x344 -#define AI_OOBCOUTWIDTH 0x348 -#define AI_OOBDEXTWIDTH 0x360 -#define AI_OOBDINWIDTH 0x364 -#define AI_OOBDOUTWIDTH 0x368 -#define AI_IOCTRLSET 0x400 -#define AI_IOCTRLCLEAR 0x404 -#define AI_IOCTRL 0x408 -#define AI_IOSTATUS 0x500 -#define AI_IOCTRLWIDTH 0x700 -#define AI_IOSTATUSWIDTH 0x704 -#define AI_RESETCTRL 0x800 -#define AI_RESETSTATUS 0x804 -#define AI_RESETREADID 0x808 -#define AI_RESETWRITEID 0x80c -#define AI_ERRLOGCTRL 0xa00 -#define AI_ERRLOGDONE 0xa04 -#define AI_ERRLOGSTATUS 0xa08 -#define AI_ERRLOGADDRLO 0xa0c -#define AI_ERRLOGADDRHI 0xa10 -#define AI_ERRLOGID 0xa14 -#define AI_ERRLOGUSER 0xa18 -#define AI_ERRLOGFLAGS 0xa1c -#define AI_INTSTATUS 0xa00 -#define AI_CONFIG 0xe00 -#define AI_ITCR 0xf00 -#define AI_ITIPOOBA 0xf10 -#define AI_ITIPOOBB 0xf14 -#define AI_ITIPOOBC 0xf18 -#define AI_ITIPOOBD 0xf1c -#define AI_ITIPOOBAOUT 0xf30 -#define AI_ITIPOOBBOUT 0xf34 -#define AI_ITIPOOBCOUT 0xf38 -#define AI_ITIPOOBDOUT 0xf3c -#define AI_ITOPOOBA 0xf50 -#define AI_ITOPOOBB 0xf54 -#define AI_ITOPOOBC 0xf58 -#define AI_ITOPOOBD 0xf5c -#define AI_ITOPOOBAIN 0xf70 -#define AI_ITOPOOBBIN 0xf74 -#define AI_ITOPOOBCIN 0xf78 -#define AI_ITOPOOBDIN 0xf7c -#define AI_ITOPRESET 0xf90 -#define AI_PERIPHERIALID4 0xfd0 -#define AI_PERIPHERIALID5 0xfd4 -#define AI_PERIPHERIALID6 0xfd8 -#define AI_PERIPHERIALID7 0xfdc -#define AI_PERIPHERIALID0 0xfe0 -#define AI_PERIPHERIALID1 0xfe4 -#define AI_PERIPHERIALID2 0xfe8 -#define AI_PERIPHERIALID3 0xfec -#define AI_COMPONENTID0 0xff0 -#define AI_COMPONENTID1 0xff4 -#define AI_COMPONENTID2 0xff8 -#define AI_COMPONENTID3 0xffc - - -#define AIRC_RESET 1 - - -#define AICFG_OOB 0x00000020 -#define AICFG_IOS 0x00000010 -#define AICFG_IOC 0x00000008 -#define AICFG_TO 0x00000004 -#define AICFG_ERRL 0x00000002 -#define AICFG_RST 0x00000001 - -#endif diff --git a/drivers/net/wireless/bcm4329/include/bcmcdc.h b/drivers/net/wireless/bcm4329/include/bcmcdc.h deleted file mode 100644 index c2a860beab24..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmcdc.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * CDC network driver ioctl/indication encoding - * Broadcom 802.11abg Networking Device Driver - * - * Definitions subject to change without notice. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmcdc.h,v 13.14.16.3.16.4 2009/04/12 16:58:45 Exp $ - */ -#include - -typedef struct cdc_ioctl { - uint32 cmd; /* ioctl command value */ - uint32 len; /* lower 16: output buflen; upper 16: input buflen (excludes header) */ - uint32 flags; /* flag defns given below */ - uint32 status; /* status code returned from the device */ -} cdc_ioctl_t; - -/* Max valid buffer size that can be sent to the dongle */ -#define CDC_MAX_MSG_SIZE ETHER_MAX_LEN - -/* len field is divided into input and output buffer lengths */ -#define CDCL_IOC_OUTLEN_MASK 0x0000FFFF /* maximum or expected response length, */ - /* excluding IOCTL header */ -#define CDCL_IOC_OUTLEN_SHIFT 0 -#define CDCL_IOC_INLEN_MASK 0xFFFF0000 /* input buffer length, excluding IOCTL header */ -#define CDCL_IOC_INLEN_SHIFT 16 - -/* CDC flag definitions */ -#define CDCF_IOC_ERROR 0x01 /* 0=success, 1=ioctl cmd failed */ -#define CDCF_IOC_SET 0x02 /* 0=get, 1=set cmd */ -#define CDCF_IOC_IF_MASK 0xF000 /* I/F index */ -#define CDCF_IOC_IF_SHIFT 12 -#define CDCF_IOC_ID_MASK 0xFFFF0000 /* used to uniquely id an ioctl req/resp pairing */ -#define CDCF_IOC_ID_SHIFT 16 /* # of bits of shift for ID Mask */ - -#define CDC_IOC_IF_IDX(flags) (((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT) -#define CDC_IOC_ID(flags) (((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT) - -#define CDC_GET_IF_IDX(hdr) \ - ((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)) -#define CDC_SET_IF_IDX(hdr, idx) \ - ((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | ((idx) << CDCF_IOC_IF_SHIFT))) - -/* - * BDC header - * - * The BDC header is used on data packets to convey priority across USB. - */ - -#define BDC_HEADER_LEN 4 - -#define BDC_PROTO_VER 1 /* Protocol version */ - -#define BDC_FLAG_VER_MASK 0xf0 /* Protocol version mask */ -#define BDC_FLAG_VER_SHIFT 4 /* Protocol version shift */ - -#define BDC_FLAG__UNUSED 0x03 /* Unassigned */ -#define BDC_FLAG_SUM_GOOD 0x04 /* Dongle has verified good RX checksums */ -#define BDC_FLAG_SUM_NEEDED 0x08 /* Dongle needs to do TX checksums */ - -#define BDC_PRIORITY_MASK 0x7 - -#define BDC_FLAG2_FC_FLAG 0x10 /* flag to indicate if pkt contains */ - /* FLOW CONTROL info only */ -#define BDC_PRIORITY_FC_SHIFT 4 /* flow control info shift */ - -#define BDC_FLAG2_IF_MASK 0x0f /* APSTA: interface on which the packet was received */ -#define BDC_FLAG2_IF_SHIFT 0 - -#define BDC_GET_IF_IDX(hdr) \ - ((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT)) -#define BDC_SET_IF_IDX(hdr, idx) \ - ((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | ((idx) << BDC_FLAG2_IF_SHIFT))) - -struct bdc_header { - uint8 flags; /* Flags */ - uint8 priority; /* 802.1d Priority 0:2 bits, 4:7 flow control info for usb */ - uint8 flags2; - uint8 rssi; -}; diff --git a/drivers/net/wireless/bcm4329/include/bcmdefs.h b/drivers/net/wireless/bcm4329/include/bcmdefs.h deleted file mode 100644 index e3c6876f86fa..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmdefs.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Misc system wide definitions - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmdefs.h,v 13.38.4.10.2.7.6.11 2010/02/01 05:51:55 Exp $ - */ - - -#ifndef _bcmdefs_h_ -#define _bcmdefs_h_ - -#define STATIC static - - -#define SI_BUS 0 -#define PCI_BUS 1 -#define PCMCIA_BUS 2 -#define SDIO_BUS 3 -#define JTAG_BUS 4 -#define USB_BUS 5 -#define SPI_BUS 6 - - -#ifdef BCMBUSTYPE -#define BUSTYPE(bus) (BCMBUSTYPE) -#else -#define BUSTYPE(bus) (bus) -#endif - - -#ifdef BCMCHIPTYPE -#define CHIPTYPE(bus) (BCMCHIPTYPE) -#else -#define CHIPTYPE(bus) (bus) -#endif - - - -#if defined(BCMSPROMBUS) -#define SPROMBUS (BCMSPROMBUS) -#elif defined(SI_PCMCIA_SROM) -#define SPROMBUS (PCMCIA_BUS) -#else -#define SPROMBUS (PCI_BUS) -#endif - - -#ifdef BCMCHIPID -#define CHIPID(chip) (BCMCHIPID) -#else -#define CHIPID(chip) (chip) -#endif - - -#define DMADDR_MASK_32 0x0 -#define DMADDR_MASK_30 0xc0000000 -#define DMADDR_MASK_0 0xffffffff - -#define DMADDRWIDTH_30 30 -#define DMADDRWIDTH_32 32 -#define DMADDRWIDTH_63 63 -#define DMADDRWIDTH_64 64 - - -#define BCMEXTRAHDROOM 164 - - -#define BCMDONGLEHDRSZ 12 -#define BCMDONGLEPADSZ 16 - -#define BCMDONGLEOVERHEAD (BCMDONGLEHDRSZ + BCMDONGLEPADSZ) - - - -#define BITFIELD_MASK(width) \ - (((unsigned)1 << (width)) - 1) -#define GFIELD(val, field) \ - (((val) >> field ## _S) & field ## _M) -#define SFIELD(val, field, bits) \ - (((val) & (~(field ## _M << field ## _S))) | \ - ((unsigned)(bits) << field ## _S)) - - -#ifdef BCMSMALL -#undef BCMSPACE -#define bcmspace FALSE -#else -#define BCMSPACE -#define bcmspace TRUE -#endif - - -#define MAXSZ_NVRAM_VARS 4096 - -#define LOCATOR_EXTERN static - -#endif diff --git a/drivers/net/wireless/bcm4329/include/bcmdevs.h b/drivers/net/wireless/bcm4329/include/bcmdevs.h deleted file mode 100644 index 14853f17795c..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmdevs.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Broadcom device-specific manifest constants. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmdevs.h,v 13.172.4.5.4.10.2.36 2010/05/25 08:33:44 Exp $ - */ - - -#ifndef _BCMDEVS_H -#define _BCMDEVS_H - - -#define VENDOR_EPIGRAM 0xfeda -#define VENDOR_BROADCOM 0x14e4 -#define VENDOR_SI_IMAGE 0x1095 -#define VENDOR_TI 0x104c -#define VENDOR_RICOH 0x1180 -#define VENDOR_JMICRON 0x197b - - -#define VENDOR_BROADCOM_PCMCIA 0x02d0 - - -#define VENDOR_BROADCOM_SDIO 0x00BF - - -#define BCM_DNGL_VID 0xa5c -#define BCM_DNGL_BL_PID_4320 0xbd11 -#define BCM_DNGL_BL_PID_4328 0xbd12 -#define BCM_DNGL_BL_PID_4322 0xbd13 -#define BCM_DNGL_BL_PID_4325 0xbd14 -#define BCM_DNGL_BL_PID_4315 0xbd15 -#define BCM_DNGL_BL_PID_4319 0xbd16 -#define BCM_DNGL_BDC_PID 0xbdc - -#define BCM4325_D11DUAL_ID 0x431b -#define BCM4325_D11G_ID 0x431c -#define BCM4325_D11A_ID 0x431d -#define BCM4329_D11NDUAL_ID 0x432e -#define BCM4329_D11N2G_ID 0x432f -#define BCM4329_D11N5G_ID 0x4330 -#define BCM4336_D11N_ID 0x4343 -#define BCM4315_D11DUAL_ID 0x4334 -#define BCM4315_D11G_ID 0x4335 -#define BCM4315_D11A_ID 0x4336 -#define BCM4319_D11N_ID 0x4337 -#define BCM4319_D11N2G_ID 0x4338 -#define BCM4319_D11N5G_ID 0x4339 - - -#define SDIOH_FPGA_ID 0x43f2 -#define SPIH_FPGA_ID 0x43f5 -#define BCM4710_DEVICE_ID 0x4710 -#define BCM27XX_SDIOH_ID 0x2702 -#define PCIXX21_FLASHMEDIA0_ID 0x8033 -#define PCIXX21_SDIOH0_ID 0x8034 -#define PCIXX21_FLASHMEDIA_ID 0x803b -#define PCIXX21_SDIOH_ID 0x803c -#define R5C822_SDIOH_ID 0x0822 -#define JMICRON_SDIOH_ID 0x2381 - - -#define BCM4306_CHIP_ID 0x4306 -#define BCM4311_CHIP_ID 0x4311 -#define BCM4312_CHIP_ID 0x4312 -#define BCM4315_CHIP_ID 0x4315 -#define BCM4318_CHIP_ID 0x4318 -#define BCM4319_CHIP_ID 0x4319 -#define BCM4320_CHIP_ID 0x4320 -#define BCM4321_CHIP_ID 0x4321 -#define BCM4322_CHIP_ID 0x4322 -#define BCM4325_CHIP_ID 0x4325 -#define BCM4328_CHIP_ID 0x4328 -#define BCM4329_CHIP_ID 0x4329 -#define BCM4336_CHIP_ID 0x4336 -#define BCM4402_CHIP_ID 0x4402 -#define BCM4704_CHIP_ID 0x4704 -#define BCM4710_CHIP_ID 0x4710 -#define BCM4712_CHIP_ID 0x4712 -#define BCM4785_CHIP_ID 0x4785 -#define BCM5350_CHIP_ID 0x5350 -#define BCM5352_CHIP_ID 0x5352 -#define BCM5354_CHIP_ID 0x5354 -#define BCM5365_CHIP_ID 0x5365 - - - -#define BCM4303_PKG_ID 2 -#define BCM4309_PKG_ID 1 -#define BCM4712LARGE_PKG_ID 0 -#define BCM4712SMALL_PKG_ID 1 -#define BCM4712MID_PKG_ID 2 -#define BCM4328USBD11G_PKG_ID 2 -#define BCM4328USBDUAL_PKG_ID 3 -#define BCM4328SDIOD11G_PKG_ID 4 -#define BCM4328SDIODUAL_PKG_ID 5 -#define BCM4329_289PIN_PKG_ID 0 -#define BCM4329_182PIN_PKG_ID 1 -#define BCM5354E_PKG_ID 1 -#define HDLSIM5350_PKG_ID 1 -#define HDLSIM_PKG_ID 14 -#define HWSIM_PKG_ID 15 - - -#endif diff --git a/drivers/net/wireless/bcm4329/include/bcmendian.h b/drivers/net/wireless/bcm4329/include/bcmendian.h deleted file mode 100644 index ae468383aa74..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmendian.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Byte order utilities - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmendian.h,v 1.31.302.1.16.1 2009/02/03 18:34:31 Exp $ - * - * This file by default provides proper behavior on little-endian architectures. - * On big-endian architectures, IL_BIGENDIAN should be defined. - */ - - -#ifndef _BCMENDIAN_H_ -#define _BCMENDIAN_H_ - -#include - - -#define BCMSWAP16(val) \ - ((uint16)((((uint16)(val) & (uint16)0x00ffU) << 8) | \ - (((uint16)(val) & (uint16)0xff00U) >> 8))) - - -#define BCMSWAP32(val) \ - ((uint32)((((uint32)(val) & (uint32)0x000000ffU) << 24) | \ - (((uint32)(val) & (uint32)0x0000ff00U) << 8) | \ - (((uint32)(val) & (uint32)0x00ff0000U) >> 8) | \ - (((uint32)(val) & (uint32)0xff000000U) >> 24))) - - -#define BCMSWAP32BY16(val) \ - ((uint32)((((uint32)(val) & (uint32)0x0000ffffU) << 16) | \ - (((uint32)(val) & (uint32)0xffff0000U) >> 16))) - - -static INLINE uint16 -bcmswap16(uint16 val) -{ - return BCMSWAP16(val); -} - -static INLINE uint32 -bcmswap32(uint32 val) -{ - return BCMSWAP32(val); -} - -static INLINE uint32 -bcmswap32by16(uint32 val) -{ - return BCMSWAP32BY16(val); -} - - - - -static INLINE void -bcmswap16_buf(uint16 *buf, uint len) -{ - len = len / 2; - - while (len--) { - *buf = bcmswap16(*buf); - buf++; - } -} - -#ifndef hton16 -#ifndef IL_BIGENDIAN -#define HTON16(i) BCMSWAP16(i) -#define HTON32(i) BCMSWAP32(i) -#define hton16(i) bcmswap16(i) -#define hton32(i) bcmswap32(i) -#define ntoh16(i) bcmswap16(i) -#define ntoh32(i) bcmswap32(i) -#define HTOL16(i) (i) -#define HTOL32(i) (i) -#define ltoh16(i) (i) -#define ltoh32(i) (i) -#define htol16(i) (i) -#define htol32(i) (i) -#else -#define HTON16(i) (i) -#define HTON32(i) (i) -#define hton16(i) (i) -#define hton32(i) (i) -#define ntoh16(i) (i) -#define ntoh32(i) (i) -#define HTOL16(i) BCMSWAP16(i) -#define HTOL32(i) BCMSWAP32(i) -#define ltoh16(i) bcmswap16(i) -#define ltoh32(i) bcmswap32(i) -#define htol16(i) bcmswap16(i) -#define htol32(i) bcmswap32(i) -#endif -#endif - -#ifndef IL_BIGENDIAN -#define ltoh16_buf(buf, i) -#define htol16_buf(buf, i) -#else -#define ltoh16_buf(buf, i) bcmswap16_buf((uint16 *)buf, i) -#define htol16_buf(buf, i) bcmswap16_buf((uint16 *)buf, i) -#endif - - -static INLINE void -htol16_ua_store(uint16 val, uint8 *bytes) -{ - bytes[0] = val & 0xff; - bytes[1] = val >> 8; -} - - -static INLINE void -htol32_ua_store(uint32 val, uint8 *bytes) -{ - bytes[0] = val & 0xff; - bytes[1] = (val >> 8) & 0xff; - bytes[2] = (val >> 16) & 0xff; - bytes[3] = val >> 24; -} - - -static INLINE void -hton16_ua_store(uint16 val, uint8 *bytes) -{ - bytes[0] = val >> 8; - bytes[1] = val & 0xff; -} - - -static INLINE void -hton32_ua_store(uint32 val, uint8 *bytes) -{ - bytes[0] = val >> 24; - bytes[1] = (val >> 16) & 0xff; - bytes[2] = (val >> 8) & 0xff; - bytes[3] = val & 0xff; -} - -#define _LTOH16_UA(cp) ((cp)[0] | ((cp)[1] << 8)) -#define _LTOH32_UA(cp) ((cp)[0] | ((cp)[1] << 8) | ((cp)[2] << 16) | ((cp)[3] << 24)) -#define _NTOH16_UA(cp) (((cp)[0] << 8) | (cp)[1]) -#define _NTOH32_UA(cp) (((cp)[0] << 24) | ((cp)[1] << 16) | ((cp)[2] << 8) | (cp)[3]) - - -static INLINE uint16 -ltoh16_ua(const void *bytes) -{ - return _LTOH16_UA((const uint8 *)bytes); -} - - -static INLINE uint32 -ltoh32_ua(const void *bytes) -{ - return _LTOH32_UA((const uint8 *)bytes); -} - - -static INLINE uint16 -ntoh16_ua(const void *bytes) -{ - return _NTOH16_UA((const uint8 *)bytes); -} - - -static INLINE uint32 -ntoh32_ua(const void *bytes) -{ - return _NTOH32_UA((const uint8 *)bytes); -} - -#define ltoh_ua(ptr) \ - (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)ptr : \ - sizeof(*(ptr)) == sizeof(uint16) ? _LTOH16_UA((const uint8 *)ptr) : \ - sizeof(*(ptr)) == sizeof(uint32) ? _LTOH32_UA((const uint8 *)ptr) : \ - 0xfeedf00d) - -#define ntoh_ua(ptr) \ - (sizeof(*(ptr)) == sizeof(uint8) ? *(const uint8 *)ptr : \ - sizeof(*(ptr)) == sizeof(uint16) ? _NTOH16_UA((const uint8 *)ptr) : \ - sizeof(*(ptr)) == sizeof(uint32) ? _NTOH32_UA((const uint8 *)ptr) : \ - 0xfeedf00d) - -#endif diff --git a/drivers/net/wireless/bcm4329/include/bcmpcispi.h b/drivers/net/wireless/bcm4329/include/bcmpcispi.h deleted file mode 100644 index 7d98fb7cbdc8..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmpcispi.h +++ /dev/null @@ -1,205 +0,0 @@ -/* - * Broadcom PCI-SPI Host Controller Register Definitions - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmpcispi.h,v 13.11.8.3 2008/07/09 21:23:29 Exp $ - */ - -/* cpp contortions to concatenate w/arg prescan */ -#ifndef PAD -#define _PADLINE(line) pad ## line -#define _XSTR(line) _PADLINE(line) -#define PAD _XSTR(__LINE__) -#endif /* PAD */ - -/* -+---------------------------------------------------------------------------+ -| | -| 7 6 5 4 3 2 1 0 | -| 0x0000 SPI_CTRL SPIE SPE 0 MSTR CPOL CPHA SPR1 SPR0 | -| 0x0004 SPI_STAT SPIF WCOL ST1 ST0 WFFUL WFEMP RFFUL RFEMP | -| 0x0008 SPI_DATA Bits 31:0, data to send out on MOSI | -| 0x000C SPI_EXT ICNT1 ICNT0 BSWAP *HSMODE ESPR1 ESPR0 | -| 0x0020 GPIO_OE 0=input, 1=output PWR_OE CS_OE | -| 0x0024 GPIO_DATA CARD:1=missing, 0=present CARD PWR_DAT CS_DAT | -| 0x0040 INT_EDGE 0=level, 1=edge DEV_E SPI_E | -| 0x0044 INT_POL 1=active high, 0=active low DEV_P SPI_P | -| 0x0048 INTMASK DEV SPI | -| 0x004C INTSTATUS DEV SPI | -| 0x0060 HEXDISP Reset value: 0x14e443f5. In hexdisp mode, value | -| shows on the Raggedstone1 4-digit 7-segment display. | -| 0x0064 CURRENT_MA Low 16 bits indicate card current consumption in mA | -| 0x006C DISP_SEL Display mode (0=hexdisp, 1=current) DSP | -| 0x00C0 PLL_CTL bit31=ext_clk, remainder unused. | -| 0x00C4 PLL_STAT LOCK | -| 0x00C8 CLK_FREQ | -| 0x00CC CLK_CNT | -| | -| *Notes: HSMODE is not implemented, never set this bit! | -| BSWAP is available in rev >= 8 | -| | -+---------------------------------------------------------------------------+ -*/ - -typedef volatile struct { - uint32 spih_ctrl; /* 0x00 SPI Control Register */ - uint32 spih_stat; /* 0x04 SPI Status Register */ - uint32 spih_data; /* 0x08 SPI Data Register, 32-bits wide */ - uint32 spih_ext; /* 0x0C SPI Extension Register */ - uint32 PAD[4]; /* 0x10-0x1F PADDING */ - - uint32 spih_gpio_ctrl; /* 0x20 SPI GPIO Control Register */ - uint32 spih_gpio_data; /* 0x24 SPI GPIO Data Register */ - uint32 PAD[6]; /* 0x28-0x3F PADDING */ - - uint32 spih_int_edge; /* 0x40 SPI Interrupt Edge Register (0=Level, 1=Edge) */ - uint32 spih_int_pol; /* 0x44 SPI Interrupt Polarity Register (0=Active Low, */ - /* 1=Active High) */ - uint32 spih_int_mask; /* 0x48 SPI Interrupt Mask */ - uint32 spih_int_status; /* 0x4C SPI Interrupt Status */ - uint32 PAD[4]; /* 0x50-0x5F PADDING */ - - uint32 spih_hex_disp; /* 0x60 SPI 4-digit hex display value */ - uint32 spih_current_ma; /* 0x64 SPI SD card current consumption in mA */ - uint32 PAD[1]; /* 0x68 PADDING */ - uint32 spih_disp_sel; /* 0x6c SPI 4-digit hex display mode select (1=current) */ - uint32 PAD[4]; /* 0x70-0x7F PADDING */ - uint32 PAD[8]; /* 0x80-0x9F PADDING */ - uint32 PAD[8]; /* 0xA0-0xBF PADDING */ - uint32 spih_pll_ctrl; /* 0xC0 PLL Control Register */ - uint32 spih_pll_status; /* 0xC4 PLL Status Register */ - uint32 spih_xtal_freq; /* 0xC8 External Clock Frequency in units of 10000Hz */ - uint32 spih_clk_count; /* 0xCC External Clock Count Register */ - -} spih_regs_t; - -typedef volatile struct { - uint32 cfg_space[0x40]; /* 0x000-0x0FF PCI Configuration Space (Read Only) */ - uint32 P_IMG_CTRL0; /* 0x100 PCI Image0 Control Register */ - - uint32 P_BA0; /* 0x104 32 R/W PCI Image0 Base Address register */ - uint32 P_AM0; /* 0x108 32 R/W PCI Image0 Address Mask register */ - uint32 P_TA0; /* 0x10C 32 R/W PCI Image0 Translation Address register */ - uint32 P_IMG_CTRL1; /* 0x110 32 R/W PCI Image1 Control register */ - uint32 P_BA1; /* 0x114 32 R/W PCI Image1 Base Address register */ - uint32 P_AM1; /* 0x118 32 R/W PCI Image1 Address Mask register */ - uint32 P_TA1; /* 0x11C 32 R/W PCI Image1 Translation Address register */ - uint32 P_IMG_CTRL2; /* 0x120 32 R/W PCI Image2 Control register */ - uint32 P_BA2; /* 0x124 32 R/W PCI Image2 Base Address register */ - uint32 P_AM2; /* 0x128 32 R/W PCI Image2 Address Mask register */ - uint32 P_TA2; /* 0x12C 32 R/W PCI Image2 Translation Address register */ - uint32 P_IMG_CTRL3; /* 0x130 32 R/W PCI Image3 Control register */ - uint32 P_BA3; /* 0x134 32 R/W PCI Image3 Base Address register */ - uint32 P_AM3; /* 0x138 32 R/W PCI Image3 Address Mask register */ - uint32 P_TA3; /* 0x13C 32 R/W PCI Image3 Translation Address register */ - uint32 P_IMG_CTRL4; /* 0x140 32 R/W PCI Image4 Control register */ - uint32 P_BA4; /* 0x144 32 R/W PCI Image4 Base Address register */ - uint32 P_AM4; /* 0x148 32 R/W PCI Image4 Address Mask register */ - uint32 P_TA4; /* 0x14C 32 R/W PCI Image4 Translation Address register */ - uint32 P_IMG_CTRL5; /* 0x150 32 R/W PCI Image5 Control register */ - uint32 P_BA5; /* 0x154 32 R/W PCI Image5 Base Address register */ - uint32 P_AM5; /* 0x158 32 R/W PCI Image5 Address Mask register */ - uint32 P_TA5; /* 0x15C 32 R/W PCI Image5 Translation Address register */ - uint32 P_ERR_CS; /* 0x160 32 R/W PCI Error Control and Status register */ - uint32 P_ERR_ADDR; /* 0x164 32 R PCI Erroneous Address register */ - uint32 P_ERR_DATA; /* 0x168 32 R PCI Erroneous Data register */ - - uint32 PAD[5]; /* 0x16C-0x17F PADDING */ - - uint32 WB_CONF_SPC_BAR; /* 0x180 32 R WISHBONE Configuration Space Base Address */ - uint32 W_IMG_CTRL1; /* 0x184 32 R/W WISHBONE Image1 Control register */ - uint32 W_BA1; /* 0x188 32 R/W WISHBONE Image1 Base Address register */ - uint32 W_AM1; /* 0x18C 32 R/W WISHBONE Image1 Address Mask register */ - uint32 W_TA1; /* 0x190 32 R/W WISHBONE Image1 Translation Address reg */ - uint32 W_IMG_CTRL2; /* 0x194 32 R/W WISHBONE Image2 Control register */ - uint32 W_BA2; /* 0x198 32 R/W WISHBONE Image2 Base Address register */ - uint32 W_AM2; /* 0x19C 32 R/W WISHBONE Image2 Address Mask register */ - uint32 W_TA2; /* 0x1A0 32 R/W WISHBONE Image2 Translation Address reg */ - uint32 W_IMG_CTRL3; /* 0x1A4 32 R/W WISHBONE Image3 Control register */ - uint32 W_BA3; /* 0x1A8 32 R/W WISHBONE Image3 Base Address register */ - uint32 W_AM3; /* 0x1AC 32 R/W WISHBONE Image3 Address Mask register */ - uint32 W_TA3; /* 0x1B0 32 R/W WISHBONE Image3 Translation Address reg */ - uint32 W_IMG_CTRL4; /* 0x1B4 32 R/W WISHBONE Image4 Control register */ - uint32 W_BA4; /* 0x1B8 32 R/W WISHBONE Image4 Base Address register */ - uint32 W_AM4; /* 0x1BC 32 R/W WISHBONE Image4 Address Mask register */ - uint32 W_TA4; /* 0x1C0 32 R/W WISHBONE Image4 Translation Address reg */ - uint32 W_IMG_CTRL5; /* 0x1C4 32 R/W WISHBONE Image5 Control register */ - uint32 W_BA5; /* 0x1C8 32 R/W WISHBONE Image5 Base Address register */ - uint32 W_AM5; /* 0x1CC 32 R/W WISHBONE Image5 Address Mask register */ - uint32 W_TA5; /* 0x1D0 32 R/W WISHBONE Image5 Translation Address reg */ - uint32 W_ERR_CS; /* 0x1D4 32 R/W WISHBONE Error Control and Status reg */ - uint32 W_ERR_ADDR; /* 0x1D8 32 R WISHBONE Erroneous Address register */ - uint32 W_ERR_DATA; /* 0x1DC 32 R WISHBONE Erroneous Data register */ - uint32 CNF_ADDR; /* 0x1E0 32 R/W Configuration Cycle register */ - uint32 CNF_DATA; /* 0x1E4 32 R/W Configuration Cycle Generation Data reg */ - - uint32 INT_ACK; /* 0x1E8 32 R Interrupt Acknowledge register */ - uint32 ICR; /* 0x1EC 32 R/W Interrupt Control register */ - uint32 ISR; /* 0x1F0 32 R/W Interrupt Status register */ -} spih_pciregs_t; - -/* - * PCI Core interrupt enable and status bit definitions. - */ - -/* PCI Core ICR Register bit definitions */ -#define PCI_INT_PROP_EN (1 << 0) /* Interrupt Propagation Enable */ -#define PCI_WB_ERR_INT_EN (1 << 1) /* Wishbone Error Interrupt Enable */ -#define PCI_PCI_ERR_INT_EN (1 << 2) /* PCI Error Interrupt Enable */ -#define PCI_PAR_ERR_INT_EN (1 << 3) /* Parity Error Interrupt Enable */ -#define PCI_SYS_ERR_INT_EN (1 << 4) /* System Error Interrupt Enable */ -#define PCI_SOFTWARE_RESET (1U << 31) /* Software reset of the PCI Core. */ - - -/* PCI Core ISR Register bit definitions */ -#define PCI_INT_PROP_ST (1 << 0) /* Interrupt Propagation Status */ -#define PCI_WB_ERR_INT_ST (1 << 1) /* Wishbone Error Interrupt Status */ -#define PCI_PCI_ERR_INT_ST (1 << 2) /* PCI Error Interrupt Status */ -#define PCI_PAR_ERR_INT_ST (1 << 3) /* Parity Error Interrupt Status */ -#define PCI_SYS_ERR_INT_ST (1 << 4) /* System Error Interrupt Status */ - - -/* Registers on the Wishbone bus */ -#define SPIH_CTLR_INTR (1 << 0) /* SPI Host Controller Core Interrupt */ -#define SPIH_DEV_INTR (1 << 1) /* SPI Device Interrupt */ -#define SPIH_WFIFO_INTR (1 << 2) /* SPI Tx FIFO Empty Intr (FPGA Rev >= 8) */ - -/* GPIO Bit definitions */ -#define SPIH_CS (1 << 0) /* SPI Chip Select (active low) */ -#define SPIH_SLOT_POWER (1 << 1) /* SD Card Slot Power Enable */ -#define SPIH_CARD_DETECT (1 << 2) /* SD Card Detect */ - -/* SPI Status Register Bit definitions */ -#define SPIH_STATE_MASK 0x30 /* SPI Transfer State Machine state mask */ -#define SPIH_STATE_SHIFT 4 /* SPI Transfer State Machine state shift */ -#define SPIH_WFFULL (1 << 3) /* SPI Write FIFO Full */ -#define SPIH_WFEMPTY (1 << 2) /* SPI Write FIFO Empty */ -#define SPIH_RFFULL (1 << 1) /* SPI Read FIFO Full */ -#define SPIH_RFEMPTY (1 << 0) /* SPI Read FIFO Empty */ - -#define SPIH_EXT_CLK (1U << 31) /* Use External Clock as PLL Clock source. */ - -#define SPIH_PLL_NO_CLK (1 << 1) /* Set to 1 if the PLL's input clock is lost. */ -#define SPIH_PLL_LOCKED (1 << 3) /* Set to 1 when the PLL is locked. */ - -/* Spin bit loop bound check */ -#define SPI_SPIN_BOUND 0xf4240 /* 1 million */ diff --git a/drivers/net/wireless/bcm4329/include/bcmperf.h b/drivers/net/wireless/bcm4329/include/bcmperf.h deleted file mode 100644 index 2a78784e85d3..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmperf.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Performance counters software interface. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmperf.h,v 13.5 2007/09/14 22:00:59 Exp $ - */ -/* essai */ -#ifndef _BCMPERF_H_ -#define _BCMPERF_H_ -/* get cache hits and misses */ -#define BCMPERF_ENABLE_INSTRCOUNT() -#define BCMPERF_ENABLE_ICACHE_MISS() -#define BCMPERF_ENABLE_ICACHE_HIT() -#define BCMPERF_GETICACHE_MISS(x) ((x) = 0) -#define BCMPERF_GETICACHE_HIT(x) ((x) = 0) -#define BCMPERF_GETINSTRCOUNT(x) ((x) = 0) -#endif /* _BCMPERF_H_ */ diff --git a/drivers/net/wireless/bcm4329/include/bcmsdbus.h b/drivers/net/wireless/bcm4329/include/bcmsdbus.h deleted file mode 100644 index b7b67bc66248..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmsdbus.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Definitions for API from sdio common code (bcmsdh) to individual - * host controller drivers. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdbus.h,v 13.11.14.2.6.6 2009/10/27 17:20:28 Exp $ - */ - -#ifndef _sdio_api_h_ -#define _sdio_api_h_ - - -#define SDIOH_API_RC_SUCCESS (0x00) -#define SDIOH_API_RC_FAIL (0x01) -#define SDIOH_API_SUCCESS(status) (status == 0) - -#define SDIOH_READ 0 /* Read request */ -#define SDIOH_WRITE 1 /* Write request */ - -#define SDIOH_DATA_FIX 0 /* Fixed addressing */ -#define SDIOH_DATA_INC 1 /* Incremental addressing */ - -#define SDIOH_CMD_TYPE_NORMAL 0 /* Normal command */ -#define SDIOH_CMD_TYPE_APPEND 1 /* Append command */ -#define SDIOH_CMD_TYPE_CUTTHRU 2 /* Cut-through command */ - -#define SDIOH_DATA_PIO 0 /* PIO mode */ -#define SDIOH_DATA_DMA 1 /* DMA mode */ - - -typedef int SDIOH_API_RC; - -/* SDio Host structure */ -typedef struct sdioh_info sdioh_info_t; - -/* callback function, taking one arg */ -typedef void (*sdioh_cb_fn_t)(void *); - -/* attach, return handler on success, NULL if failed. - * The handler shall be provided by all subsequent calls. No local cache - * cfghdl points to the starting address of pci device mapped memory - */ -extern sdioh_info_t * sdioh_attach(osl_t *osh, void *cfghdl, uint irq); -extern SDIOH_API_RC sdioh_detach(osl_t *osh, sdioh_info_t *si); -extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si, sdioh_cb_fn_t fn, void *argh); -extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si); - -/* query whether SD interrupt is enabled or not */ -extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff); - -/* enable or disable SD interrupt */ -extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable); - -#if defined(DHD_DEBUG) -extern bool sdioh_interrupt_pending(sdioh_info_t *si); -#endif - -/* read or write one byte using cmd52 */ -extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc, uint addr, uint8 *byte); - -/* read or write 2/4 bytes using cmd53 */ -extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type, uint rw, uint fnc, - uint addr, uint32 *word, uint nbyte); - -/* read or write any buffer using cmd53 */ -extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma, uint fix_inc, - uint rw, uint fnc_num, uint32 addr, uint regwidth, uint32 buflen, uint8 *buffer, - void *pkt); - -/* get cis data */ -extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, uint8 *cis, uint32 length); - -extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data); -extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, uint32 addr, uint8 *data); - -/* query number of io functions */ -extern uint sdioh_query_iofnum(sdioh_info_t *si); - -/* handle iovars */ -extern int sdioh_iovar_op(sdioh_info_t *si, const char *name, - void *params, int plen, void *arg, int len, bool set); - -/* Issue abort to the specified function and clear controller as needed */ -extern int sdioh_abort(sdioh_info_t *si, uint fnc); - -/* Start and Stop SDIO without re-enumerating the SD card. */ -extern int sdioh_start(sdioh_info_t *si, int stage); -extern int sdioh_stop(sdioh_info_t *si); - -/* Reset and re-initialize the device */ -extern int sdioh_sdio_reset(sdioh_info_t *si); - -/* Helper function */ -void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); - - - -#endif /* _sdio_api_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/bcmsdh.h b/drivers/net/wireless/bcm4329/include/bcmsdh.h deleted file mode 100644 index f5dee5c58445..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmsdh.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * SDIO host client driver interface of Broadcom HNBU - * export functions to client drivers - * abstract OS and BUS specific details of SDIO - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdh.h,v 13.35.14.7.6.8 2009/10/14 04:22:25 Exp $ - */ - -#ifndef _bcmsdh_h_ -#define _bcmsdh_h_ - -#define BCMSDH_ERROR_VAL 0x0001 /* Error */ -#define BCMSDH_INFO_VAL 0x0002 /* Info */ -extern const uint bcmsdh_msglevel; - -#define BCMSDH_ERROR(x) -#define BCMSDH_INFO(x) - -/* forward declarations */ -typedef struct bcmsdh_info bcmsdh_info_t; -typedef void (*bcmsdh_cb_fn_t)(void *); - -/* Attach and build an interface to the underlying SD host driver. - * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. - * - Returns the bcmsdh handle and virtual address base for register access. - * The returned handle should be used in all subsequent calls, but the bcmsh - * implementation may maintain a single "default" handle (e.g. the first or - * most recent one) to enable single-instance implementations to pass NULL. - */ -extern bcmsdh_info_t *bcmsdh_attach(osl_t *osh, void *cfghdl, void **regsva, uint irq); - -/* Detach - freeup resources allocated in attach */ -extern int bcmsdh_detach(osl_t *osh, void *sdh); - -/* Query if SD device interrupts are enabled */ -extern bool bcmsdh_intr_query(void *sdh); - -/* Enable/disable SD interrupt */ -extern int bcmsdh_intr_enable(void *sdh); -extern int bcmsdh_intr_disable(void *sdh); - -/* Register/deregister device interrupt handler. */ -extern int bcmsdh_intr_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); -extern int bcmsdh_intr_dereg(void *sdh); - -#if defined(DHD_DEBUG) -/* Query pending interrupt status from the host controller */ -extern bool bcmsdh_intr_pending(void *sdh); -#endif - -#ifdef BCMLXSDMMC -extern int bcmsdh_claim_host_and_lock(void *sdh); -extern int bcmsdh_release_host_and_unlock(void *sdh); -#endif /* BCMLXSDMMC */ - -/* Register a callback to be called if and when bcmsdh detects - * device removal. No-op in the case of non-removable/hardwired devices. - */ -extern int bcmsdh_devremove_reg(void *sdh, bcmsdh_cb_fn_t fn, void *argh); - -/* Access SDIO address space (e.g. CCCR) using CMD52 (single-byte interface). - * fn: function number - * addr: unmodified SDIO-space address - * data: data byte to write - * err: pointer to error code (or NULL) - */ -extern uint8 bcmsdh_cfg_read(void *sdh, uint func, uint32 addr, int *err); -extern void bcmsdh_cfg_write(void *sdh, uint func, uint32 addr, uint8 data, int *err); - -/* Read/Write 4bytes from/to cfg space */ -extern uint32 bcmsdh_cfg_read_word(void *sdh, uint fnc_num, uint32 addr, int *err); -extern void bcmsdh_cfg_write_word(void *sdh, uint fnc_num, uint32 addr, uint32 data, int *err); - -/* Read CIS content for specified function. - * fn: function whose CIS is being requested (0 is common CIS) - * cis: pointer to memory location to place results - * length: number of bytes to read - * Internally, this routine uses the values from the cis base regs (0x9-0xB) - * to form an SDIO-space address to read the data from. - */ -extern int bcmsdh_cis_read(void *sdh, uint func, uint8 *cis, uint length); - -/* Synchronous access to device (client) core registers via CMD53 to F1. - * addr: backplane address (i.e. >= regsva from attach) - * size: register width in bytes (2 or 4) - * data: data for register write - */ -extern uint32 bcmsdh_reg_read(void *sdh, uint32 addr, uint size); -extern uint32 bcmsdh_reg_write(void *sdh, uint32 addr, uint size, uint32 data); - -/* Indicate if last reg read/write failed */ -extern bool bcmsdh_regfail(void *sdh); - -/* Buffer transfer to/from device (client) core via cmd53. - * fn: function number - * addr: backplane address (i.e. >= regsva from attach) - * flags: backplane width, address increment, sync/async - * buf: pointer to memory data buffer - * nbytes: number of bytes to transfer to/from buf - * pkt: pointer to packet associated with buf (if any) - * complete: callback function for command completion (async only) - * handle: handle for completion callback (first arg in callback) - * Returns 0 or error code. - * NOTE: Async operation is not currently supported. - */ -typedef void (*bcmsdh_cmplt_fn_t)(void *handle, int status, bool sync_waiting); -extern int bcmsdh_send_buf(void *sdh, uint32 addr, uint fn, uint flags, - uint8 *buf, uint nbytes, void *pkt, - bcmsdh_cmplt_fn_t complete, void *handle); -extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, - uint8 *buf, uint nbytes, void *pkt, - bcmsdh_cmplt_fn_t complete, void *handle); - -/* Flags bits */ -#define SDIO_REQ_4BYTE 0x1 /* Four-byte target (backplane) width (vs. two-byte) */ -#define SDIO_REQ_FIXED 0x2 /* Fixed address (FIFO) (vs. incrementing address) */ -#define SDIO_REQ_ASYNC 0x4 /* Async request (vs. sync request) */ - -/* Pending (non-error) return code */ -#define BCME_PENDING 1 - -/* Read/write to memory block (F1, no FIFO) via CMD53 (sync only). - * rw: read or write (0/1) - * addr: direct SDIO address - * buf: pointer to memory data buffer - * nbytes: number of bytes to transfer to/from buf - * Returns 0 or error code. - */ -extern int bcmsdh_rwdata(void *sdh, uint rw, uint32 addr, uint8 *buf, uint nbytes); - -/* Issue an abort to the specified function */ -extern int bcmsdh_abort(void *sdh, uint fn); - -/* Start SDIO Host Controller communication */ -extern int bcmsdh_start(void *sdh, int stage); - -/* Stop SDIO Host Controller communication */ -extern int bcmsdh_stop(void *sdh); - -/* Returns the "Device ID" of target device on the SDIO bus. */ -extern int bcmsdh_query_device(void *sdh); - -/* Returns the number of IO functions reported by the device */ -extern uint bcmsdh_query_iofnum(void *sdh); - -/* Miscellaneous knob tweaker. */ -extern int bcmsdh_iovar_op(void *sdh, const char *name, - void *params, int plen, void *arg, int len, bool set); - -/* Reset and reinitialize the device */ -extern int bcmsdh_reset(bcmsdh_info_t *sdh); - -/* helper functions */ - -extern void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh); - -/* callback functions */ -typedef struct { - /* attach to device */ - void *(*attach)(uint16 vend_id, uint16 dev_id, uint16 bus, uint16 slot, - uint16 func, uint bustype, void * regsva, osl_t * osh, - void * param); - /* detach from device */ - void (*detach)(void *ch); -} bcmsdh_driver_t; - -/* platform specific/high level functions */ -extern int bcmsdh_register(bcmsdh_driver_t *driver); -extern void bcmsdh_unregister(void); -extern bool bcmsdh_chipmatch(uint16 vendor, uint16 device); -extern void bcmsdh_device_remove(void * sdh); - -#if defined(OOB_INTR_ONLY) -extern int bcmsdh_register_oob_intr(void * dhdp); -extern void bcmsdh_unregister_oob_intr(void); -extern void bcmsdh_oob_intr_set(bool enable); -#endif /* defined(OOB_INTR_ONLY) */ -/* Function to pass device-status bits to DHD. */ -extern uint32 bcmsdh_get_dstatus(void *sdh); - -/* Function to return current window addr */ -extern uint32 bcmsdh_cur_sbwad(void *sdh); - -/* Function to pass chipid and rev to lower layers for controlling pr's */ -extern void bcmsdh_chipinfo(void *sdh, uint32 chip, uint32 chiprev); - - -#endif /* _bcmsdh_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcm4329/include/bcmsdh_sdmmc.h deleted file mode 100644 index 6ec5874b6187..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmsdh_sdmmc.h +++ /dev/null @@ -1,122 +0,0 @@ -/* - * BCMSDH Function Driver for the native SDIO/MMC driver in the Linux Kernel - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdh_sdmmc.h,v 13.1.2.1.8.7 2009/10/27 18:22:52 Exp $ - */ - -#ifndef __BCMSDH_SDMMC_H__ -#define __BCMSDH_SDMMC_H__ - -#define sd_err(x) -#define sd_trace(x) -#define sd_info(x) -#define sd_debug(x) -#define sd_data(x) -#define sd_ctrl(x) - -#define sd_sync_dma(sd, read, nbytes) -#define sd_init_dma(sd) -#define sd_ack_intr(sd) -#define sd_wakeup(sd); - -/* Allocate/init/free per-OS private data */ -extern int sdioh_sdmmc_osinit(sdioh_info_t *sd); -extern void sdioh_sdmmc_osfree(sdioh_info_t *sd); - -#define sd_log(x) - -#define SDIOH_ASSERT(exp) \ - do { if (!(exp)) \ - printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ - } while (0) - -#define BLOCK_SIZE_4318 64 -#define BLOCK_SIZE_4328 512 - -/* internal return code */ -#define SUCCESS 0 -#define ERROR 1 - -/* private bus modes */ -#define SDIOH_MODE_SD4 2 -#define CLIENT_INTR 0x100 /* Get rid of this! */ - -struct sdioh_info { - osl_t *osh; /* osh handler */ - bool client_intr_enabled; /* interrupt connnected flag */ - bool intr_handler_valid; /* client driver interrupt handler valid */ - sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ - void *intr_handler_arg; /* argument to call interrupt handler */ - uint16 intmask; /* Current active interrupts */ - void *sdos_info; /* Pointer to per-OS private data */ - - uint irq; /* Client irq */ - int intrcount; /* Client interrupts */ - - bool sd_use_dma; /* DMA on CMD53 */ - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ - /* Must be on for sd_multiblock to be effective */ - bool use_client_ints; /* If this is false, make sure to restore */ - int sd_mode; /* SD1/SD4/SPI */ - int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ - uint8 num_funcs; /* Supported funcs on client */ - uint32 com_cis_ptr; - uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; - uint max_dma_len; - uint max_dma_descriptors; /* DMA Descriptors supported by this controller. */ -// SDDMA_DESCRIPTOR SGList[32]; /* Scatter/Gather DMA List */ -}; - -/************************************************************ - * Internal interfaces: per-port references into bcmsdh_sdmmc.c - */ - -/* Global message bits */ -extern uint sd_msglevel; - -/* OS-independent interrupt handler */ -extern bool check_client_intr(sdioh_info_t *sd); - -/* Core interrupt enable/disable of device interrupts */ -extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd); -extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd); - - -/************************************************************** - * Internal interfaces: bcmsdh_sdmmc.c references to per-port code - */ - -/* Register mapping routines */ -extern uint32 *sdioh_sdmmc_reg_map(osl_t *osh, int32 addr, int size); -extern void sdioh_sdmmc_reg_unmap(osl_t *osh, int32 addr, int size); - -/* Interrupt (de)registration routines */ -extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq); -extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd); - -typedef struct _BCMSDH_SDMMC_INSTANCE { - sdioh_info_t *sd; - struct sdio_func *func[SDIOD_MAX_IOFUNCS]; -} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE; - -#endif /* __BCMSDH_SDMMC_H__ */ diff --git a/drivers/net/wireless/bcm4329/include/bcmsdpcm.h b/drivers/net/wireless/bcm4329/include/bcmsdpcm.h deleted file mode 100644 index 77aca4500ad8..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmsdpcm.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Broadcom SDIO/PCMCIA - * Software-specific definitions shared between device and host side - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdpcm.h,v 1.1.2.4 2010/07/02 01:15:46 Exp $ - */ - -#ifndef _bcmsdpcm_h_ -#define _bcmsdpcm_h_ - -/* - * Software allocation of To SB Mailbox resources - */ - -/* intstatus bits */ -#define I_SMB_NAK I_SMB_SW0 /* To SB Mailbox Frame NAK */ -#define I_SMB_INT_ACK I_SMB_SW1 /* To SB Mailbox Host Interrupt ACK */ -#define I_SMB_USE_OOB I_SMB_SW2 /* To SB Mailbox Use OOB Wakeup */ -#define I_SMB_DEV_INT I_SMB_SW3 /* To SB Mailbox Miscellaneous Interrupt */ - -/* tosbmailbox bits corresponding to intstatus bits */ -#define SMB_NAK (1 << 0) /* To SB Mailbox Frame NAK */ -#define SMB_INT_ACK (1 << 1) /* To SB Mailbox Host Interrupt ACK */ -#define SMB_USE_OOB (1 << 2) /* To SB Mailbox Use OOB Wakeup */ -#define SMB_DEV_INT (1 << 3) /* To SB Mailbox Miscellaneous Interrupt */ -#define SMB_MASK 0x0000000f /* To SB Mailbox Mask */ - -/* tosbmailboxdata */ -#define SMB_DATA_VERSION_MASK 0x00ff0000 /* host protocol version (sent with F2 enable) */ -#define SMB_DATA_VERSION_SHIFT 16 /* host protocol version (sent with F2 enable) */ - -/* - * Software allocation of To Host Mailbox resources - */ - -/* intstatus bits */ -#define I_HMB_FC_STATE I_HMB_SW0 /* To Host Mailbox Flow Control State */ -#define I_HMB_FC_CHANGE I_HMB_SW1 /* To Host Mailbox Flow Control State Changed */ -#define I_HMB_FRAME_IND I_HMB_SW2 /* To Host Mailbox Frame Indication */ -#define I_HMB_HOST_INT I_HMB_SW3 /* To Host Mailbox Miscellaneous Interrupt */ - -/* tohostmailbox bits corresponding to intstatus bits */ -#define HMB_FC_ON (1 << 0) /* To Host Mailbox Flow Control State */ -#define HMB_FC_CHANGE (1 << 1) /* To Host Mailbox Flow Control State Changed */ -#define HMB_FRAME_IND (1 << 2) /* To Host Mailbox Frame Indication */ -#define HMB_HOST_INT (1 << 3) /* To Host Mailbox Miscellaneous Interrupt */ -#define HMB_MASK 0x0000000f /* To Host Mailbox Mask */ - -/* tohostmailboxdata */ -#define HMB_DATA_NAKHANDLED 1 /* we're ready to retransmit NAK'd frame to host */ -#define HMB_DATA_DEVREADY 2 /* we're ready to to talk to host after enable */ -#define HMB_DATA_FC 4 /* per prio flowcontrol update flag to host */ -#define HMB_DATA_FWREADY 8 /* firmware is ready for protocol activity */ - -#define HMB_DATA_FCDATA_MASK 0xff000000 /* per prio flowcontrol data */ -#define HMB_DATA_FCDATA_SHIFT 24 /* per prio flowcontrol data */ - -#define HMB_DATA_VERSION_MASK 0x00ff0000 /* device protocol version (with devready) */ -#define HMB_DATA_VERSION_SHIFT 16 /* device protocol version (with devready) */ - -/* - * Software-defined protocol header - */ - -/* Current protocol version */ -#define SDPCM_PROT_VERSION 4 - -/* SW frame header */ -#define SDPCM_SEQUENCE_MASK 0x000000ff /* Sequence Number Mask */ -#define SDPCM_PACKET_SEQUENCE(p) (((uint8 *)p)[0] & 0xff) /* p starts w/SW Header */ - -#define SDPCM_CHANNEL_MASK 0x00000f00 /* Channel Number Mask */ -#define SDPCM_CHANNEL_SHIFT 8 /* Channel Number Shift */ -#define SDPCM_PACKET_CHANNEL(p) (((uint8 *)p)[1] & 0x0f) /* p starts w/SW Header */ - -#define SDPCM_FLAGS_MASK 0x0000f000 /* Mask of flag bits */ -#define SDPCM_FLAGS_SHIFT 12 /* Flag bits shift */ -#define SDPCM_PACKET_FLAGS(p) ((((uint8 *)p)[1] & 0xf0) >> 4) /* p starts w/SW Header */ - -/* Next Read Len: lookahead length of next frame, in 16-byte units (rounded up) */ -#define SDPCM_NEXTLEN_MASK 0x00ff0000 /* Next Read Len Mask */ -#define SDPCM_NEXTLEN_SHIFT 16 /* Next Read Len Shift */ -#define SDPCM_NEXTLEN_VALUE(p) ((((uint8 *)p)[2] & 0xff) << 4) /* p starts w/SW Header */ -#define SDPCM_NEXTLEN_OFFSET 2 - -/* Data Offset from SOF (HW Tag, SW Tag, Pad) */ -#define SDPCM_DOFFSET_OFFSET 3 /* Data Offset */ -#define SDPCM_DOFFSET_VALUE(p) (((uint8 *)p)[SDPCM_DOFFSET_OFFSET] & 0xff) -#define SDPCM_DOFFSET_MASK 0xff000000 -#define SDPCM_DOFFSET_SHIFT 24 - -#define SDPCM_FCMASK_OFFSET 4 /* Flow control */ -#define SDPCM_FCMASK_VALUE(p) (((uint8 *)p)[SDPCM_FCMASK_OFFSET ] & 0xff) -#define SDPCM_WINDOW_OFFSET 5 /* Credit based fc */ -#define SDPCM_WINDOW_VALUE(p) (((uint8 *)p)[SDPCM_WINDOW_OFFSET] & 0xff) -#define SDPCM_VERSION_OFFSET 6 /* Version # */ -#define SDPCM_VERSION_VALUE(p) (((uint8 *)p)[SDPCM_VERSION_OFFSET] & 0xff) -#define SDPCM_UNUSED_OFFSET 7 /* Spare */ -#define SDPCM_UNUSED_VALUE(p) (((uint8 *)p)[SDPCM_UNUSED_OFFSET] & 0xff) - -#define SDPCM_SWHEADER_LEN 8 /* SW header is 64 bits */ - -/* logical channel numbers */ -#define SDPCM_CONTROL_CHANNEL 0 /* Control Request/Response Channel Id */ -#define SDPCM_EVENT_CHANNEL 1 /* Asyc Event Indication Channel Id */ -#define SDPCM_DATA_CHANNEL 2 /* Data Xmit/Recv Channel Id */ -#define SDPCM_GLOM_CHANNEL 3 /* For coalesced packets (superframes) */ -#define SDPCM_TEST_CHANNEL 15 /* Reserved for test/debug packets */ -#define SDPCM_MAX_CHANNEL 15 - -#define SDPCM_SEQUENCE_WRAP 256 /* wrap-around val for eight-bit frame seq number */ - -#define SDPCM_FLAG_RESVD0 0x01 -#define SDPCM_FLAG_RESVD1 0x02 -#define SDPCM_FLAG_GSPI_TXENAB 0x04 -#define SDPCM_FLAG_GLOMDESC 0x08 /* Superframe descriptor mask */ - -/* For GLOM_CHANNEL frames, use a flag to indicate descriptor frame */ -#define SDPCM_GLOMDESC_FLAG (SDPCM_FLAG_GLOMDESC << SDPCM_FLAGS_SHIFT) - -#define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) - -/* For TEST_CHANNEL packets, define another 4-byte header */ -#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); - * Semantics of Ext byte depend on command. - * Len is current or requested frame length, not - * including test header; sent little-endian. - */ -#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ -#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ -#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ -#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count */ -#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off */ - -/* Handy macro for filling in datagen packets with a pattern */ -#define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) - -/* - * Software counters (first part matches hardware counters) - */ - -typedef volatile struct { - uint32 cmd52rd; /* Cmd52RdCount, SDIO: cmd52 reads */ - uint32 cmd52wr; /* Cmd52WrCount, SDIO: cmd52 writes */ - uint32 cmd53rd; /* Cmd53RdCount, SDIO: cmd53 reads */ - uint32 cmd53wr; /* Cmd53WrCount, SDIO: cmd53 writes */ - uint32 abort; /* AbortCount, SDIO: aborts */ - uint32 datacrcerror; /* DataCrcErrorCount, SDIO: frames w/CRC error */ - uint32 rdoutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Rd Frm out of sync */ - uint32 wroutofsync; /* RdOutOfSyncCount, SDIO/PCMCIA: Wr Frm out of sync */ - uint32 writebusy; /* WriteBusyCount, SDIO: device asserted "busy" */ - uint32 readwait; /* ReadWaitCount, SDIO: no data ready for a read cmd */ - uint32 readterm; /* ReadTermCount, SDIO: read frame termination cmds */ - uint32 writeterm; /* WriteTermCount, SDIO: write frames termination cmds */ - uint32 rxdescuflo; /* receive descriptor underflows */ - uint32 rxfifooflo; /* receive fifo overflows */ - uint32 txfifouflo; /* transmit fifo underflows */ - uint32 runt; /* runt (too short) frames recv'd from bus */ - uint32 badlen; /* frame's rxh len does not match its hw tag len */ - uint32 badcksum; /* frame's hw tag chksum doesn't agree with len value */ - uint32 seqbreak; /* break in sequence # space from one rx frame to the next */ - uint32 rxfcrc; /* frame rx header indicates crc error */ - uint32 rxfwoos; /* frame rx header indicates write out of sync */ - uint32 rxfwft; /* frame rx header indicates write frame termination */ - uint32 rxfabort; /* frame rx header indicates frame aborted */ - uint32 woosint; /* write out of sync interrupt */ - uint32 roosint; /* read out of sync interrupt */ - uint32 rftermint; /* read frame terminate interrupt */ - uint32 wftermint; /* write frame terminate interrupt */ -} sdpcmd_cnt_t; - -/* - * Register Access Macros - */ - -#define SDIODREV_IS(var, val) ((var) == (val)) -#define SDIODREV_GE(var, val) ((var) >= (val)) -#define SDIODREV_GT(var, val) ((var) > (val)) -#define SDIODREV_LT(var, val) ((var) < (val)) -#define SDIODREV_LE(var, val) ((var) <= (val)) - -#define SDIODDMAREG32(h, dir, chnl) \ - ((dir) == DMA_TX ? \ - (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].xmt) : \ - (void *)(uintptr)&((h)->regs->dma.sdiod32.dma32regs[chnl].rcv)) - -#define SDIODDMAREG64(h, dir, chnl) \ - ((dir) == DMA_TX ? \ - (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].xmt) : \ - (void *)(uintptr)&((h)->regs->dma.sdiod64.dma64regs[chnl].rcv)) - -#define SDIODDMAREG(h, dir, chnl) \ - (SDIODREV_LT((h)->corerev, 1) ? \ - SDIODDMAREG32((h), (dir), (chnl)) : \ - SDIODDMAREG64((h), (dir), (chnl))) - -#define PCMDDMAREG(h, dir, chnl) \ - ((dir) == DMA_TX ? \ - (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.xmt) : \ - (void *)(uintptr)&((h)->regs->dma.pcm32.dmaregs.rcv)) - -#define SDPCMDMAREG(h, dir, chnl, coreid) \ - ((coreid) == SDIOD_CORE_ID ? \ - SDIODDMAREG(h, dir, chnl) : \ - PCMDDMAREG(h, dir, chnl)) - -#define SDIODFIFOREG(h, corerev) \ - (SDIODREV_LT((corerev), 1) ? \ - ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod32.dmafifo)) : \ - ((dma32diag_t *)(uintptr)&((h)->regs->dma.sdiod64.dmafifo))) - -#define PCMDFIFOREG(h) \ - ((dma32diag_t *)(uintptr)&((h)->regs->dma.pcm32.dmafifo)) - -#define SDPCMFIFOREG(h, coreid, corerev) \ - ((coreid) == SDIOD_CORE_ID ? \ - SDIODFIFOREG(h, corerev) : \ - PCMDFIFOREG(h)) - -/* - * Shared structure between dongle and the host - * The structure contains pointers to trap or assert information shared with the host - */ -#define SDPCM_SHARED_VERSION 0x0002 -#define SDPCM_SHARED_VERSION_MASK 0x00FF -#define SDPCM_SHARED_ASSERT_BUILT 0x0100 -#define SDPCM_SHARED_ASSERT 0x0200 -#define SDPCM_SHARED_TRAP 0x0400 - -typedef struct { - uint32 flags; - uint32 trap_addr; - uint32 assert_exp_addr; - uint32 assert_file_addr; - uint32 assert_line; - uint32 console_addr; /* Address of hndrte_cons_t */ - uint32 msgtrace_addr; - uint8 tag[32]; -} sdpcm_shared_t; - -extern sdpcm_shared_t sdpcm_shared; - -#endif /* _bcmsdpcm_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/bcmsdspi.h b/drivers/net/wireless/bcm4329/include/bcmsdspi.h deleted file mode 100644 index eaae10d8bf19..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmsdspi.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * SD-SPI Protocol Conversion - BCMSDH->SPI Translation Layer - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdspi.h,v 13.8.10.2 2008/06/30 21:09:40 Exp $ - */ - -/* global msglevel for debug messages - bitvals come from sdiovar.h */ - -#define sd_err(x) -#define sd_trace(x) -#define sd_info(x) -#define sd_debug(x) -#define sd_data(x) -#define sd_ctrl(x) - -#define sd_log(x) - -#define SDIOH_ASSERT(exp) \ - do { if (!(exp)) \ - printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ - } while (0) - -#define BLOCK_SIZE_4318 64 -#define BLOCK_SIZE_4328 512 - -/* internal return code */ -#define SUCCESS 0 -#undef ERROR -#define ERROR 1 - -/* private bus modes */ -#define SDIOH_MODE_SPI 0 - -#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ -#define USE_MULTIBLOCK 0x4 - -struct sdioh_info { - uint cfg_bar; /* pci cfg address for bar */ - uint32 caps; /* cached value of capabilities reg */ - uint bar0; /* BAR0 for PCI Device */ - osl_t *osh; /* osh handler */ - void *controller; /* Pointer to SPI Controller's private data struct */ - - uint lockcount; /* nest count of sdspi_lock() calls */ - bool client_intr_enabled; /* interrupt connnected flag */ - bool intr_handler_valid; /* client driver interrupt handler valid */ - sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ - void *intr_handler_arg; /* argument to call interrupt handler */ - bool initialized; /* card initialized */ - uint32 target_dev; /* Target device ID */ - uint32 intmask; /* Current active interrupts */ - void *sdos_info; /* Pointer to per-OS private data */ - - uint32 controller_type; /* Host controller type */ - uint8 version; /* Host Controller Spec Compliance Version */ - uint irq; /* Client irq */ - uint32 intrcount; /* Client interrupts */ - uint32 local_intrcount; /* Controller interrupts */ - bool host_init_done; /* Controller initted */ - bool card_init_done; /* Client SDIO interface initted */ - bool polled_mode; /* polling for command completion */ - - bool sd_use_dma; /* DMA on CMD53 */ - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ - /* Must be on for sd_multiblock to be effective */ - bool use_client_ints; /* If this is false, make sure to restore */ - bool got_hcint; /* Host Controller interrupt. */ - /* polling hack in wl_linux.c:wl_timer() */ - int adapter_slot; /* Maybe dealing with multiple slots/controllers */ - int sd_mode; /* SD1/SD4/SPI */ - int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ - uint32 data_xfer_count; /* Current register transfer size */ - uint32 cmd53_wr_data; /* Used to pass CMD53 write data */ - uint32 card_response; /* Used to pass back response status byte */ - uint32 card_rsp_data; /* Used to pass back response data word */ - uint16 card_rca; /* Current Address */ - uint8 num_funcs; /* Supported funcs on client */ - uint32 com_cis_ptr; - uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; - void *dma_buf; - ulong dma_phys; - int r_cnt; /* rx count */ - int t_cnt; /* tx_count */ -}; - -/************************************************************ - * Internal interfaces: per-port references into bcmsdspi.c - */ - -/* Global message bits */ -extern uint sd_msglevel; - -/************************************************************** - * Internal interfaces: bcmsdspi.c references to per-port code - */ - -/* Register mapping routines */ -extern uint32 *spi_reg_map(osl_t *osh, uintptr addr, int size); -extern void spi_reg_unmap(osl_t *osh, uintptr addr, int size); - -/* Interrupt (de)registration routines */ -extern int spi_register_irq(sdioh_info_t *sd, uint irq); -extern void spi_free_irq(uint irq, sdioh_info_t *sd); - -/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ -extern void spi_lock(sdioh_info_t *sd); -extern void spi_unlock(sdioh_info_t *sd); - -/* Allocate/init/free per-OS private data */ -extern int spi_osinit(sdioh_info_t *sd); -extern void spi_osfree(sdioh_info_t *sd); diff --git a/drivers/net/wireless/bcm4329/include/bcmsdstd.h b/drivers/net/wireless/bcm4329/include/bcmsdstd.h deleted file mode 100644 index 974b3d41698d..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmsdstd.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * 'Standard' SDIO HOST CONTROLLER driver - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmsdstd.h,v 13.16.18.1.16.3 2009/12/10 01:09:23 Exp $ - */ - -/* global msglevel for debug messages - bitvals come from sdiovar.h */ - -#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0) -#define sd_trace(x) -#define sd_info(x) -#define sd_debug(x) -#define sd_data(x) -#define sd_ctrl(x) -#define sd_dma(x) - -#define sd_sync_dma(sd, read, nbytes) -#define sd_init_dma(sd) -#define sd_ack_intr(sd) -#define sd_wakeup(sd); -/* Allocate/init/free per-OS private data */ -extern int sdstd_osinit(sdioh_info_t *sd); -extern void sdstd_osfree(sdioh_info_t *sd); - -#define sd_log(x) - -#define SDIOH_ASSERT(exp) \ - do { if (!(exp)) \ - printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ - } while (0) - -#define BLOCK_SIZE_4318 64 -#define BLOCK_SIZE_4328 512 - -/* internal return code */ -#define SUCCESS 0 -#define ERROR 1 - -/* private bus modes */ -#define SDIOH_MODE_SPI 0 -#define SDIOH_MODE_SD1 1 -#define SDIOH_MODE_SD4 2 - -#define MAX_SLOTS 6 /* For PCI: Only 6 BAR entries => 6 slots */ -#define SDIOH_REG_WINSZ 0x100 /* Number of registers in Standard Host Controller */ - -#define SDIOH_TYPE_ARASAN_HDK 1 -#define SDIOH_TYPE_BCM27XX 2 -#define SDIOH_TYPE_TI_PCIXX21 4 /* TI PCIxx21 Standard Host Controller */ -#define SDIOH_TYPE_RICOH_R5C822 5 /* Ricoh Co Ltd R5C822 SD/SDIO/MMC/MS/MSPro Host Adapter */ -#define SDIOH_TYPE_JMICRON 6 /* JMicron Standard SDIO Host Controller */ - -/* For linux, allow yielding for dongle */ -#define BCMSDYIELD - -/* Expected card status value for CMD7 */ -#define SDIOH_CMD7_EXP_STATUS 0x00001E00 - -#define RETRIES_LARGE 100000 -#define RETRIES_SMALL 100 - - -#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ -#define USE_MULTIBLOCK 0x4 - -#define USE_FIFO 0x8 /* Fifo vs non-fifo */ - -#define CLIENT_INTR 0x100 /* Get rid of this! */ - - -struct sdioh_info { - uint cfg_bar; /* pci cfg address for bar */ - uint32 caps; /* cached value of capabilities reg */ - uint32 curr_caps; /* max current capabilities reg */ - - osl_t *osh; /* osh handler */ - volatile char *mem_space; /* pci device memory va */ - uint lockcount; /* nest count of sdstd_lock() calls */ - bool client_intr_enabled; /* interrupt connnected flag */ - bool intr_handler_valid; /* client driver interrupt handler valid */ - sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ - void *intr_handler_arg; /* argument to call interrupt handler */ - bool initialized; /* card initialized */ - uint target_dev; /* Target device ID */ - uint16 intmask; /* Current active interrupts */ - void *sdos_info; /* Pointer to per-OS private data */ - - uint32 controller_type; /* Host controller type */ - uint8 version; /* Host Controller Spec Compliance Version */ - uint irq; /* Client irq */ - int intrcount; /* Client interrupts */ - int local_intrcount; /* Controller interrupts */ - bool host_init_done; /* Controller initted */ - bool card_init_done; /* Client SDIO interface initted */ - bool polled_mode; /* polling for command completion */ - - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ - /* Must be on for sd_multiblock to be effective */ - bool use_client_ints; /* If this is false, make sure to restore */ - /* polling hack in wl_linux.c:wl_timer() */ - int adapter_slot; /* Maybe dealing with multiple slots/controllers */ - int sd_mode; /* SD1/SD4/SPI */ - int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ - uint32 data_xfer_count; /* Current transfer */ - uint16 card_rca; /* Current Address */ - int8 sd_dma_mode; /* DMA Mode (PIO, SDMA, ... ADMA2) on CMD53 */ - uint8 num_funcs; /* Supported funcs on client */ - uint32 com_cis_ptr; - uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; - void *dma_buf; /* DMA Buffer virtual address */ - ulong dma_phys; /* DMA Buffer physical address */ - void *adma2_dscr_buf; /* ADMA2 Descriptor Buffer virtual address */ - ulong adma2_dscr_phys; /* ADMA2 Descriptor Buffer physical address */ - - /* adjustments needed to make the dma align properly */ - void *dma_start_buf; - ulong dma_start_phys; - uint alloced_dma_size; - void *adma2_dscr_start_buf; - ulong adma2_dscr_start_phys; - uint alloced_adma2_dscr_size; - - int r_cnt; /* rx count */ - int t_cnt; /* tx_count */ - bool got_hcint; /* local interrupt flag */ - uint16 last_intrstatus; /* to cache intrstatus */ -}; - -#define DMA_MODE_NONE 0 -#define DMA_MODE_SDMA 1 -#define DMA_MODE_ADMA1 2 -#define DMA_MODE_ADMA2 3 -#define DMA_MODE_ADMA2_64 4 -#define DMA_MODE_AUTO -1 - -#define USE_DMA(sd) ((bool)((sd->sd_dma_mode > 0) ? TRUE : FALSE)) - -/* SDIO Host Control Register DMA Mode Definitions */ -#define SDIOH_SDMA_MODE 0 -#define SDIOH_ADMA1_MODE 1 -#define SDIOH_ADMA2_MODE 2 -#define SDIOH_ADMA2_64_MODE 3 - -#define ADMA2_ATTRIBUTE_VALID (1 << 0) /* ADMA Descriptor line valid */ -#define ADMA2_ATTRIBUTE_END (1 << 1) /* End of Descriptor */ -#define ADMA2_ATTRIBUTE_INT (1 << 2) /* Interrupt when line is done */ -#define ADMA2_ATTRIBUTE_ACT_NOP (0 << 4) /* Skip current line, go to next. */ -#define ADMA2_ATTRIBUTE_ACT_RSV (1 << 4) /* Same as NOP */ -#define ADMA1_ATTRIBUTE_ACT_SET (1 << 4) /* ADMA1 Only - set transfer length */ -#define ADMA2_ATTRIBUTE_ACT_TRAN (2 << 4) /* Transfer Data of one descriptor line. */ -#define ADMA2_ATTRIBUTE_ACT_LINK (3 << 4) /* Link Descriptor */ - -/* ADMA2 Descriptor Table Entry for 32-bit Address */ -typedef struct adma2_dscr_32b { - uint32 len_attr; - uint32 phys_addr; -} adma2_dscr_32b_t; - -/* ADMA1 Descriptor Table Entry */ -typedef struct adma1_dscr { - uint32 phys_addr_attr; -} adma1_dscr_t; - -/************************************************************ - * Internal interfaces: per-port references into bcmsdstd.c - */ - -/* Global message bits */ -extern uint sd_msglevel; - -/* OS-independent interrupt handler */ -extern bool check_client_intr(sdioh_info_t *sd); - -/* Core interrupt enable/disable of device interrupts */ -extern void sdstd_devintr_on(sdioh_info_t *sd); -extern void sdstd_devintr_off(sdioh_info_t *sd); - -/* Enable/disable interrupts for local controller events */ -extern void sdstd_intrs_on(sdioh_info_t *sd, uint16 norm, uint16 err); -extern void sdstd_intrs_off(sdioh_info_t *sd, uint16 norm, uint16 err); - -/* Wait for specified interrupt and error bits to be set */ -extern void sdstd_spinbits(sdioh_info_t *sd, uint16 norm, uint16 err); - - -/************************************************************** - * Internal interfaces: bcmsdstd.c references to per-port code - */ - -/* Register mapping routines */ -extern uint32 *sdstd_reg_map(osl_t *osh, int32 addr, int size); -extern void sdstd_reg_unmap(osl_t *osh, int32 addr, int size); - -/* Interrupt (de)registration routines */ -extern int sdstd_register_irq(sdioh_info_t *sd, uint irq); -extern void sdstd_free_irq(uint irq, sdioh_info_t *sd); - -/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ -extern void sdstd_lock(sdioh_info_t *sd); -extern void sdstd_unlock(sdioh_info_t *sd); - -/* OS-specific wait-for-interrupt-or-status */ -extern uint16 sdstd_waitbits(sdioh_info_t *sd, uint16 norm, uint16 err, bool yield); diff --git a/drivers/net/wireless/bcm4329/include/bcmspi.h b/drivers/net/wireless/bcm4329/include/bcmspi.h deleted file mode 100644 index 2e2bc935716f..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmspi.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Broadcom SPI Low-Level Hardware Driver API - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmspi.h,v 13.3.10.2 2008/06/30 21:09:40 Exp $ - */ - -extern void spi_devintr_off(sdioh_info_t *sd); -extern void spi_devintr_on(sdioh_info_t *sd); -extern bool spi_start_clock(sdioh_info_t *sd, uint16 new_sd_divisor); -extern bool spi_controller_highspeed_mode(sdioh_info_t *sd, bool hsmode); -extern bool spi_check_client_intr(sdioh_info_t *sd, int *is_dev_intr); -extern bool spi_hw_attach(sdioh_info_t *sd); -extern bool spi_hw_detach(sdioh_info_t *sd); -extern void spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int msglen); -extern void spi_spinbits(sdioh_info_t *sd); -extern void spi_waitbits(sdioh_info_t *sd, bool yield); diff --git a/drivers/net/wireless/bcm4329/include/bcmutils.h b/drivers/net/wireless/bcm4329/include/bcmutils.h deleted file mode 100644 index f85ed351d663..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmutils.h +++ /dev/null @@ -1,637 +0,0 @@ -/* - * Misc useful os-independent macros and functions. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.h,v 13.184.4.6.2.1.18.25 2010/04/26 06:05:24 Exp $ - */ - - -#ifndef _bcmutils_h_ -#define _bcmutils_h_ - -#ifdef __cplusplus -extern "C" { -#endif - - -#define _BCM_U 0x01 -#define _BCM_L 0x02 -#define _BCM_D 0x04 -#define _BCM_C 0x08 -#define _BCM_P 0x10 -#define _BCM_S 0x20 -#define _BCM_X 0x40 -#define _BCM_SP 0x80 - -extern const unsigned char bcm_ctype[]; -#define bcm_ismask(x) (bcm_ctype[(int)(unsigned char)(x)]) - -#define bcm_isalnum(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L|_BCM_D)) != 0) -#define bcm_isalpha(c) ((bcm_ismask(c)&(_BCM_U|_BCM_L)) != 0) -#define bcm_iscntrl(c) ((bcm_ismask(c)&(_BCM_C)) != 0) -#define bcm_isdigit(c) ((bcm_ismask(c)&(_BCM_D)) != 0) -#define bcm_isgraph(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D)) != 0) -#define bcm_islower(c) ((bcm_ismask(c)&(_BCM_L)) != 0) -#define bcm_isprint(c) ((bcm_ismask(c)&(_BCM_P|_BCM_U|_BCM_L|_BCM_D|_BCM_SP)) != 0) -#define bcm_ispunct(c) ((bcm_ismask(c)&(_BCM_P)) != 0) -#define bcm_isspace(c) ((bcm_ismask(c)&(_BCM_S)) != 0) -#define bcm_isupper(c) ((bcm_ismask(c)&(_BCM_U)) != 0) -#define bcm_isxdigit(c) ((bcm_ismask(c)&(_BCM_D|_BCM_X)) != 0) -#define bcm_tolower(c) (bcm_isupper((c)) ? ((c) + 'a' - 'A') : (c)) -#define bcm_toupper(c) (bcm_islower((c)) ? ((c) + 'A' - 'a') : (c)) - - - -struct bcmstrbuf { - char *buf; - unsigned int size; - char *origbuf; - unsigned int origsize; -}; - - -#ifdef BCMDRIVER -#include - -#define GPIO_PIN_NOTDEFINED 0x20 - - -#define SPINWAIT(exp, us) { \ - uint countdown = (us) + 9; \ - while ((exp) && (countdown >= 10)) {\ - OSL_DELAY(10); \ - countdown -= 10; \ - } \ -} - - - -#ifndef PKTQ_LEN_DEFAULT -#define PKTQ_LEN_DEFAULT 128 -#endif -#ifndef PKTQ_MAX_PREC -#define PKTQ_MAX_PREC 16 -#endif - -typedef struct pktq_prec { - void *head; - void *tail; - uint16 len; - uint16 max; -} pktq_prec_t; - - - -struct pktq { - uint16 num_prec; - uint16 hi_prec; - uint16 max; - uint16 len; - - struct pktq_prec q[PKTQ_MAX_PREC]; -}; - - -struct spktq { - uint16 num_prec; - uint16 hi_prec; - uint16 max; - uint16 len; - - struct pktq_prec q[1]; -}; - -#define PKTQ_PREC_ITER(pq, prec) for (prec = (pq)->num_prec - 1; prec >= 0; prec--) - - - - -struct ether_addr; - -extern int ether_isbcast(const void *ea); -extern int ether_isnulladdr(const void *ea); - - - -#define pktq_psetmax(pq, prec, _max) ((pq)->q[prec].max = (_max)) -#define pktq_plen(pq, prec) ((pq)->q[prec].len) -#define pktq_pavail(pq, prec) ((pq)->q[prec].max - (pq)->q[prec].len) -#define pktq_pfull(pq, prec) ((pq)->q[prec].len >= (pq)->q[prec].max) -#define pktq_pempty(pq, prec) ((pq)->q[prec].len == 0) - -#define pktq_ppeek(pq, prec) ((pq)->q[prec].head) -#define pktq_ppeek_tail(pq, prec) ((pq)->q[prec].tail) - -extern void *pktq_penq(struct pktq *pq, int prec, void *p); -extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); -extern void *pktq_pdeq(struct pktq *pq, int prec); -extern void *pktq_pdeq_tail(struct pktq *pq, int prec); - -extern bool pktq_pdel(struct pktq *pq, void *p, int prec); - - -extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir); - -extern void pktq_flush(osl_t *osh, struct pktq *pq, bool dir); - - - -extern int pktq_mlen(struct pktq *pq, uint prec_bmp); -extern void *pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out); - - - -#define pktq_len(pq) ((int)(pq)->len) -#define pktq_max(pq) ((int)(pq)->max) -#define pktq_avail(pq) ((int)((pq)->max - (pq)->len)) -#define pktq_full(pq) ((pq)->len >= (pq)->max) -#define pktq_empty(pq) ((pq)->len == 0) - - -#define pktenq(pq, p) pktq_penq(((struct pktq *)pq), 0, (p)) -#define pktenq_head(pq, p) pktq_penq_head(((struct pktq *)pq), 0, (p)) -#define pktdeq(pq) pktq_pdeq(((struct pktq *)pq), 0) -#define pktdeq_tail(pq) pktq_pdeq_tail(((struct pktq *)pq), 0) -#define pktqinit(pq, len) pktq_init(((struct pktq *)pq), 1, len) - -extern void pktq_init(struct pktq *pq, int num_prec, int max_len); - -extern void *pktq_deq(struct pktq *pq, int *prec_out); -extern void *pktq_deq_tail(struct pktq *pq, int *prec_out); -extern void *pktq_peek(struct pktq *pq, int *prec_out); -extern void *pktq_peek_tail(struct pktq *pq, int *prec_out); - - - -extern uint pktcopy(osl_t *osh, void *p, uint offset, int len, uchar *buf); -extern uint pktfrombuf(osl_t *osh, void *p, uint offset, int len, uchar *buf); -extern uint pkttotlen(osl_t *osh, void *p); -extern void *pktlast(osl_t *osh, void *p); -extern uint pktsegcnt(osl_t *osh, void *p); - - -extern uint pktsetprio(void *pkt, bool update_vtag); -#define PKTPRIO_VDSCP 0x100 -#define PKTPRIO_VLAN 0x200 -#define PKTPRIO_UPD 0x400 -#define PKTPRIO_DSCP 0x800 - - -extern int bcm_atoi(char *s); -extern ulong bcm_strtoul(char *cp, char **endp, uint base); -extern char *bcmstrstr(char *haystack, char *needle); -extern char *bcmstrcat(char *dest, const char *src); -extern char *bcmstrncat(char *dest, const char *src, uint size); -extern ulong wchar2ascii(char *abuf, ushort *wbuf, ushort wbuflen, ulong abuflen); -char* bcmstrtok(char **string, const char *delimiters, char *tokdelim); -int bcmstricmp(const char *s1, const char *s2); -int bcmstrnicmp(const char* s1, const char* s2, int cnt); - - - -extern char *bcm_ether_ntoa(const struct ether_addr *ea, char *buf); -extern int bcm_ether_atoe(char *p, struct ether_addr *ea); - - -struct ipv4_addr; -extern char *bcm_ip_ntoa(struct ipv4_addr *ia, char *buf); - - -extern void bcm_mdelay(uint ms); - -extern char *getvar(char *vars, const char *name); -extern int getintvar(char *vars, const char *name); -extern uint getgpiopin(char *vars, char *pin_name, uint def_pin); -#define bcm_perf_enable() -#define bcmstats(fmt) -#define bcmlog(fmt, a1, a2) -#define bcmdumplog(buf, size) *buf = '\0' -#define bcmdumplogent(buf, idx) -1 - -#define bcmtslog(tstamp, fmt, a1, a2) -#define bcmprinttslogs() -#define bcmprinttstamp(us) - - - - -typedef struct bcm_iovar { - const char *name; - uint16 varid; - uint16 flags; - uint16 type; - uint16 minlen; -} bcm_iovar_t; - - - - -#define IOV_GET 0 -#define IOV_SET 1 - - -#define IOV_GVAL(id) ((id)*2) -#define IOV_SVAL(id) (((id)*2)+IOV_SET) -#define IOV_ISSET(actionid) ((actionid & IOV_SET) == IOV_SET) - - - -extern const bcm_iovar_t *bcm_iovar_lookup(const bcm_iovar_t *table, const char *name); -extern int bcm_iovar_lencheck(const bcm_iovar_t *table, void *arg, int len, bool set); - -#endif - - -#define IOVT_VOID 0 -#define IOVT_BOOL 1 -#define IOVT_INT8 2 -#define IOVT_UINT8 3 -#define IOVT_INT16 4 -#define IOVT_UINT16 5 -#define IOVT_INT32 6 -#define IOVT_UINT32 7 -#define IOVT_BUFFER 8 -#define BCM_IOVT_VALID(type) (((unsigned int)(type)) <= IOVT_BUFFER) - - -#define BCM_IOV_TYPE_INIT { \ - "void", \ - "bool", \ - "int8", \ - "uint8", \ - "int16", \ - "uint16", \ - "int32", \ - "uint32", \ - "buffer", \ - "" } - -#define BCM_IOVT_IS_INT(type) (\ - (type == IOVT_BOOL) || \ - (type == IOVT_INT8) || \ - (type == IOVT_UINT8) || \ - (type == IOVT_INT16) || \ - (type == IOVT_UINT16) || \ - (type == IOVT_INT32) || \ - (type == IOVT_UINT32)) - - - -#define BCME_STRLEN 64 -#define VALID_BCMERROR(e) ((e <= 0) && (e >= BCME_LAST)) - - - - -#define BCME_OK 0 -#define BCME_ERROR -1 -#define BCME_BADARG -2 -#define BCME_BADOPTION -3 -#define BCME_NOTUP -4 -#define BCME_NOTDOWN -5 -#define BCME_NOTAP -6 -#define BCME_NOTSTA -7 -#define BCME_BADKEYIDX -8 -#define BCME_RADIOOFF -9 -#define BCME_NOTBANDLOCKED -10 -#define BCME_NOCLK -11 -#define BCME_BADRATESET -12 -#define BCME_BADBAND -13 -#define BCME_BUFTOOSHORT -14 -#define BCME_BUFTOOLONG -15 -#define BCME_BUSY -16 -#define BCME_NOTASSOCIATED -17 -#define BCME_BADSSIDLEN -18 -#define BCME_OUTOFRANGECHAN -19 -#define BCME_BADCHAN -20 -#define BCME_BADADDR -21 -#define BCME_NORESOURCE -22 -#define BCME_UNSUPPORTED -23 -#define BCME_BADLEN -24 -#define BCME_NOTREADY -25 -#define BCME_EPERM -26 -#define BCME_NOMEM -27 -#define BCME_ASSOCIATED -28 -#define BCME_RANGE -29 -#define BCME_NOTFOUND -30 -#define BCME_WME_NOT_ENABLED -31 -#define BCME_TSPEC_NOTFOUND -32 -#define BCME_ACM_NOTSUPPORTED -33 -#define BCME_NOT_WME_ASSOCIATION -34 -#define BCME_SDIO_ERROR -35 -#define BCME_DONGLE_DOWN -36 -#define BCME_VERSION -37 -#define BCME_TXFAIL -38 -#define BCME_RXFAIL -39 -#define BCME_NODEVICE -40 -#define BCME_UNFINISHED -41 -#define BCME_LAST BCME_UNFINISHED - - -#define BCMERRSTRINGTABLE { \ - "OK", \ - "Undefined error", \ - "Bad Argument", \ - "Bad Option", \ - "Not up", \ - "Not down", \ - "Not AP", \ - "Not STA", \ - "Bad Key Index", \ - "Radio Off", \ - "Not band locked", \ - "No clock", \ - "Bad Rate valueset", \ - "Bad Band", \ - "Buffer too short", \ - "Buffer too long", \ - "Busy", \ - "Not Associated", \ - "Bad SSID len", \ - "Out of Range Channel", \ - "Bad Channel", \ - "Bad Address", \ - "Not Enough Resources", \ - "Unsupported", \ - "Bad length", \ - "Not Ready", \ - "Not Permitted", \ - "No Memory", \ - "Associated", \ - "Not In Range", \ - "Not Found", \ - "WME Not Enabled", \ - "TSPEC Not Found", \ - "ACM Not Supported", \ - "Not WME Association", \ - "SDIO Bus Error", \ - "Dongle Not Accessible", \ - "Incorrect version", \ - "TX Failure", \ - "RX Failure", \ - "Device Not Present", \ - "Command not finished", \ -} - -#ifndef ABS -#define ABS(a) (((a) < 0)?-(a):(a)) -#endif - -#ifndef MIN -#define MIN(a, b) (((a) < (b))?(a):(b)) -#endif - -#ifndef MAX -#define MAX(a, b) (((a) > (b))?(a):(b)) -#endif - -#define CEIL(x, y) (((x) + ((y)-1)) / (y)) -#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y)) -#define ISALIGNED(a, x) (((a) & ((x)-1)) == 0) -#define ALIGN_ADDR(addr, boundary) (void *)(((uintptr)(addr) + (boundary) - 1) \ - & ~((boundary) - 1)) -#define ISPOWEROF2(x) ((((x)-1)&(x)) == 0) -#define VALID_MASK(mask) !((mask) & ((mask) + 1)) -#ifndef OFFSETOF -#define OFFSETOF(type, member) ((uint)(uintptr)&((type *)0)->member) -#endif -#ifndef ARRAYSIZE -#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - - -#ifndef setbit -#ifndef NBBY -#define NBBY 8 -#endif -#define setbit(a, i) (((uint8 *)a)[(i)/NBBY] |= 1<<((i)%NBBY)) -#define clrbit(a, i) (((uint8 *)a)[(i)/NBBY] &= ~(1<<((i)%NBBY))) -#define isset(a, i) (((const uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) -#define isclr(a, i) ((((const uint8 *)a)[(i)/NBBY] & (1<<((i)%NBBY))) == 0) -#endif - -#define NBITS(type) (sizeof(type) * 8) -#define NBITVAL(nbits) (1 << (nbits)) -#define MAXBITVAL(nbits) ((1 << (nbits)) - 1) -#define NBITMASK(nbits) MAXBITVAL(nbits) -#define MAXNBVAL(nbyte) MAXBITVAL((nbyte) * 8) - - -#define MUX(pred, true, false) ((pred) ? (true) : (false)) - - -#define MODDEC(x, bound) MUX((x) == 0, (bound) - 1, (x) - 1) -#define MODINC(x, bound) MUX((x) == (bound) - 1, 0, (x) + 1) - - -#define MODDEC_POW2(x, bound) (((x) - 1) & ((bound) - 1)) -#define MODINC_POW2(x, bound) (((x) + 1) & ((bound) - 1)) - - -#define MODADD(x, y, bound) \ - MUX((x) + (y) >= (bound), (x) + (y) - (bound), (x) + (y)) -#define MODSUB(x, y, bound) \ - MUX(((int)(x)) - ((int)(y)) < 0, (x) - (y) + (bound), (x) - (y)) - - -#define MODADD_POW2(x, y, bound) (((x) + (y)) & ((bound) - 1)) -#define MODSUB_POW2(x, y, bound) (((x) - (y)) & ((bound) - 1)) - - -#define CRC8_INIT_VALUE 0xff -#define CRC8_GOOD_VALUE 0x9f -#define CRC16_INIT_VALUE 0xffff -#define CRC16_GOOD_VALUE 0xf0b8 -#define CRC32_INIT_VALUE 0xffffffff -#define CRC32_GOOD_VALUE 0xdebb20e3 - - -typedef struct bcm_bit_desc { - uint32 bit; - const char* name; -} bcm_bit_desc_t; - - -typedef struct bcm_tlv { - uint8 id; - uint8 len; - uint8 data[1]; -} bcm_tlv_t; - - -#define bcm_valid_tlv(elt, buflen) ((buflen) >= 2 && (int)(buflen) >= (int)(2 + (elt)->len)) - - -#define ETHER_ADDR_STR_LEN 18 - - -#ifdef IL_BIGENDIAN -static INLINE uint32 -load32_ua(uint8 *a) -{ - return ((a[0] << 24) | (a[1] << 16) | (a[2] << 8) | a[3]); -} - -static INLINE void -store32_ua(uint8 *a, uint32 v) -{ - a[0] = (v >> 24) & 0xff; - a[1] = (v >> 16) & 0xff; - a[2] = (v >> 8) & 0xff; - a[3] = v & 0xff; -} - -static INLINE uint16 -load16_ua(uint8 *a) -{ - return ((a[0] << 8) | a[1]); -} - -static INLINE void -store16_ua(uint8 *a, uint16 v) -{ - a[0] = (v >> 8) & 0xff; - a[1] = v & 0xff; -} - -#else - -static INLINE uint32 -load32_ua(uint8 *a) -{ - return ((a[3] << 24) | (a[2] << 16) | (a[1] << 8) | a[0]); -} - -static INLINE void -store32_ua(uint8 *a, uint32 v) -{ - a[3] = (v >> 24) & 0xff; - a[2] = (v >> 16) & 0xff; - a[1] = (v >> 8) & 0xff; - a[0] = v & 0xff; -} - -static INLINE uint16 -load16_ua(uint8 *a) -{ - return ((a[1] << 8) | a[0]); -} - -static INLINE void -store16_ua(uint8 *a, uint16 v) -{ - a[1] = (v >> 8) & 0xff; - a[0] = v & 0xff; -} - -#endif - - - -static INLINE void -xor_128bit_block(const uint8 *src1, const uint8 *src2, uint8 *dst) -{ - if ( -#ifdef __i386__ - 1 || -#endif - (((uintptr)src1 | (uintptr)src2 | (uintptr)dst) & 3) == 0) { - - - ((uint32 *)dst)[0] = ((uint32 *)src1)[0] ^ ((uint32 *)src2)[0]; - ((uint32 *)dst)[1] = ((uint32 *)src1)[1] ^ ((uint32 *)src2)[1]; - ((uint32 *)dst)[2] = ((uint32 *)src1)[2] ^ ((uint32 *)src2)[2]; - ((uint32 *)dst)[3] = ((uint32 *)src1)[3] ^ ((uint32 *)src2)[3]; - } else { - - int k; - for (k = 0; k < 16; k++) - dst[k] = src1[k] ^ src2[k]; - } -} - - - -extern uint8 hndcrc8(uint8 *p, uint nbytes, uint8 crc); -extern uint16 hndcrc16(uint8 *p, uint nbytes, uint16 crc); -extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); - -#if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ - defined(WLMSG_ASSOC) -extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); -extern int bcm_format_hex(char *str, const void *bytes, int len); -extern void prhex(const char *msg, uchar *buf, uint len); -#endif -extern char *bcm_brev_str(uint32 brev, char *buf); -extern void printbig(char *buf); - - -extern bcm_tlv_t *bcm_next_tlv(bcm_tlv_t *elt, int *buflen); -extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); -extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); - - -extern const char *bcmerrorstr(int bcmerror); - - -typedef uint32 mbool; -#define mboolset(mb, bit) ((mb) |= (bit)) -#define mboolclr(mb, bit) ((mb) &= ~(bit)) -#define mboolisset(mb, bit) (((mb) & (bit)) != 0) -#define mboolmaskset(mb, mask, val) ((mb) = (((mb) & ~(mask)) | (val))) - - -extern uint16 bcm_qdbm_to_mw(uint8 qdbm); -extern uint8 bcm_mw_to_qdbm(uint16 mw); - - -struct fielddesc { - const char *nameandfmt; - uint32 offset; - uint32 len; -}; - -extern void bcm_binit(struct bcmstrbuf *b, char *buf, uint size); -extern int bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...); -extern void bcm_inc_bytes(uchar *num, int num_bytes, uint8 amount); -extern int bcm_cmp_bytes(uchar *arg1, uchar *arg2, uint8 nbytes); -extern void bcm_print_bytes(char *name, const uchar *cdata, int len); - -typedef uint32 (*bcmutl_rdreg_rtn)(void *arg0, uint arg1, uint32 offset); -extern uint bcmdumpfields(bcmutl_rdreg_rtn func_ptr, void *arg0, uint arg1, struct fielddesc *str, - char *buf, uint32 bufsize); - -extern uint bcm_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); -extern uint bcm_bitcount(uint8 *bitmap, uint bytelength); - -#if defined(WLTINYDUMP) || defined(WLMSG_INFORM) || defined(WLMSG_ASSOC) || \ - defined(WLMSG_PRPKT) || defined(WLMSG_WSEC) -extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); -#endif - - -#define SSID_FMT_BUF_LEN ((4 * DOT11_MAX_SSID_LEN) + 1) - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/drivers/net/wireless/bcm4329/include/bcmwifi.h b/drivers/net/wireless/bcm4329/include/bcmwifi.h deleted file mode 100644 index 038aedcdb3c8..000000000000 --- a/drivers/net/wireless/bcm4329/include/bcmwifi.h +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Misc utility routines for WL and Apps - * This header file housing the define and function prototype use by - * both the wl driver, tools & Apps. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmwifi.h,v 1.15.30.4 2010/03/10 20:10:52 Exp $ - */ - - -#ifndef _bcmwifi_h_ -#define _bcmwifi_h_ - - - -typedef uint16 chanspec_t; - - -#define CH_UPPER_SB 0x01 -#define CH_LOWER_SB 0x02 -#define CH_EWA_VALID 0x04 -#define CH_20MHZ_APART 4 -#define CH_10MHZ_APART 2 -#define CH_5MHZ_APART 1 -#define CH_MAX_2G_CHANNEL 14 -#define WLC_MAX_2G_CHANNEL CH_MAX_2G_CHANNEL -#define MAXCHANNEL 224 - -#define WL_CHANSPEC_CHAN_MASK 0x00ff -#define WL_CHANSPEC_CHAN_SHIFT 0 - -#define WL_CHANSPEC_CTL_SB_MASK 0x0300 -#define WL_CHANSPEC_CTL_SB_SHIFT 8 -#define WL_CHANSPEC_CTL_SB_LOWER 0x0100 -#define WL_CHANSPEC_CTL_SB_UPPER 0x0200 -#define WL_CHANSPEC_CTL_SB_NONE 0x0300 - -#define WL_CHANSPEC_BW_MASK 0x0C00 -#define WL_CHANSPEC_BW_SHIFT 10 -#define WL_CHANSPEC_BW_10 0x0400 -#define WL_CHANSPEC_BW_20 0x0800 -#define WL_CHANSPEC_BW_40 0x0C00 - -#define WL_CHANSPEC_BAND_MASK 0xf000 -#define WL_CHANSPEC_BAND_SHIFT 12 -#define WL_CHANSPEC_BAND_5G 0x1000 -#define WL_CHANSPEC_BAND_2G 0x2000 -#define INVCHANSPEC 255 - - -#define WF_CHAN_FACTOR_2_4_G 4814 -#define WF_CHAN_FACTOR_5_G 10000 -#define WF_CHAN_FACTOR_4_G 8000 - - -#define LOWER_20_SB(channel) ((channel > CH_10MHZ_APART) ? (channel - CH_10MHZ_APART) : 0) -#define UPPER_20_SB(channel) ((channel < (MAXCHANNEL - CH_10MHZ_APART)) ? \ - (channel + CH_10MHZ_APART) : 0) -#define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) -#define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ - WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ - WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G)) -#define NEXT_20MHZ_CHAN(channel) ((channel < (MAXCHANNEL - CH_20MHZ_APART)) ? \ - (channel + CH_20MHZ_APART) : 0) -#define CH40MHZ_CHSPEC(channel, ctlsb) (chanspec_t) \ - ((channel) | (ctlsb) | WL_CHANSPEC_BW_40 | \ - ((channel) <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : \ - WL_CHANSPEC_BAND_5G)) -#define CHSPEC_CHANNEL(chspec) ((uint8)(chspec & WL_CHANSPEC_CHAN_MASK)) -#define CHSPEC_BAND(chspec) (chspec & WL_CHANSPEC_BAND_MASK) - -#ifdef WL20MHZ_ONLY - -#define CHSPEC_CTL_SB(chspec) WL_CHANSPEC_CTL_SB_NONE -#define CHSPEC_BW(chspec) WL_CHANSPEC_BW_20 -#define CHSPEC_IS10(chspec) 0 -#define CHSPEC_IS20(chspec) 1 -#ifndef CHSPEC_IS40 -#define CHSPEC_IS40(chspec) 0 -#endif - -#else - -#define CHSPEC_CTL_SB(chspec) (chspec & WL_CHANSPEC_CTL_SB_MASK) -#define CHSPEC_BW(chspec) (chspec & WL_CHANSPEC_BW_MASK) -#define CHSPEC_IS10(chspec) ((chspec & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_10) -#define CHSPEC_IS20(chspec) ((chspec & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_20) -#ifndef CHSPEC_IS40 -#define CHSPEC_IS40(chspec) (((chspec) & WL_CHANSPEC_BW_MASK) == WL_CHANSPEC_BW_40) -#endif - -#endif - -#define CHSPEC_IS5G(chspec) ((chspec & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_5G) -#define CHSPEC_IS2G(chspec) ((chspec & WL_CHANSPEC_BAND_MASK) == WL_CHANSPEC_BAND_2G) -#define CHSPEC_SB_NONE(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_NONE) -#define CHSPEC_SB_UPPER(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_UPPER) -#define CHSPEC_SB_LOWER(chspec) ((chspec & WL_CHANSPEC_CTL_SB_MASK) == WL_CHANSPEC_CTL_SB_LOWER) -#define CHSPEC_CTL_CHAN(chspec) ((CHSPEC_SB_LOWER(chspec)) ? \ - (LOWER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK))) : \ - (UPPER_20_SB(((chspec) & WL_CHANSPEC_CHAN_MASK)))) - -#define CHSPEC2WLC_BAND(chspec) (CHSPEC_IS5G((chspec))? WLC_BAND_5G: WLC_BAND_2G) - -#define CHANSPEC_STR_LEN 8 - - -#define WLC_MAXRATE 108 -#define WLC_RATE_1M 2 -#define WLC_RATE_2M 4 -#define WLC_RATE_5M5 11 -#define WLC_RATE_11M 22 -#define WLC_RATE_6M 12 -#define WLC_RATE_9M 18 -#define WLC_RATE_12M 24 -#define WLC_RATE_18M 36 -#define WLC_RATE_24M 48 -#define WLC_RATE_36M 72 -#define WLC_RATE_48M 96 -#define WLC_RATE_54M 108 - -#define WLC_2G_25MHZ_OFFSET 5 - - -extern char * wf_chspec_ntoa(chanspec_t chspec, char *buf); - - -extern chanspec_t wf_chspec_aton(char *a); - - -extern int wf_mhz2channel(uint freq, uint start_factor); - - -extern int wf_channel2mhz(uint channel, uint start_factor); - -#endif diff --git a/drivers/net/wireless/bcm4329/include/dhdioctl.h b/drivers/net/wireless/bcm4329/include/dhdioctl.h deleted file mode 100644 index 980a14301003..000000000000 --- a/drivers/net/wireless/bcm4329/include/dhdioctl.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Definitions for ioctls to access DHD iovars. - * Based on wlioctl.h (for Broadcom 802.11abg driver). - * (Moves towards generic ioctls for BCM drivers/iovars.) - * - * Definitions subject to change without notice. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: dhdioctl.h,v 13.7.8.1.4.1.16.5 2010/05/21 21:49:38 Exp $ - */ - -#ifndef _dhdioctl_h_ -#define _dhdioctl_h_ - -#include - - -/* require default structure packing */ -#define BWL_DEFAULT_PACKING -#include - - -/* Linux network driver ioctl encoding */ -typedef struct dhd_ioctl { - uint cmd; /* common ioctl definition */ - void *buf; /* pointer to user buffer */ - uint len; /* length of user buffer */ - bool set; /* get or set request (optional) */ - uint used; /* bytes read or written (optional) */ - uint needed; /* bytes needed (optional) */ - uint driver; /* to identify target driver */ -} dhd_ioctl_t; - -/* per-driver magic numbers */ -#define DHD_IOCTL_MAGIC 0x00444944 - -/* bump this number if you change the ioctl interface */ -#define DHD_IOCTL_VERSION 1 - -#define DHD_IOCTL_MAXLEN 8192 /* max length ioctl buffer required */ -#define DHD_IOCTL_SMLEN 256 /* "small" length ioctl buffer required */ - -/* common ioctl definitions */ -#define DHD_GET_MAGIC 0 -#define DHD_GET_VERSION 1 -#define DHD_GET_VAR 2 -#define DHD_SET_VAR 3 - -/* message levels */ -#define DHD_ERROR_VAL 0x0001 -#define DHD_TRACE_VAL 0x0002 -#define DHD_INFO_VAL 0x0004 -#define DHD_DATA_VAL 0x0008 -#define DHD_CTL_VAL 0x0010 -#define DHD_TIMER_VAL 0x0020 -#define DHD_HDRS_VAL 0x0040 -#define DHD_BYTES_VAL 0x0080 -#define DHD_INTR_VAL 0x0100 -#define DHD_LOG_VAL 0x0200 -#define DHD_GLOM_VAL 0x0400 -#define DHD_EVENT_VAL 0x0800 -#define DHD_BTA_VAL 0x1000 -#define DHD_ISCAN_VAL 0x2000 - -#ifdef SDTEST -/* For pktgen iovar */ -typedef struct dhd_pktgen { - uint version; /* To allow structure change tracking */ - uint freq; /* Max ticks between tx/rx attempts */ - uint count; /* Test packets to send/rcv each attempt */ - uint print; /* Print counts every attempts */ - uint total; /* Total packets (or bursts) */ - uint minlen; /* Minimum length of packets to send */ - uint maxlen; /* Maximum length of packets to send */ - uint numsent; /* Count of test packets sent */ - uint numrcvd; /* Count of test packets received */ - uint numfail; /* Count of test send failures */ - uint mode; /* Test mode (type of test packets) */ - uint stop; /* Stop after this many tx failures */ -} dhd_pktgen_t; - -/* Version in case structure changes */ -#define DHD_PKTGEN_VERSION 2 - -/* Type of test packets to use */ -#define DHD_PKTGEN_ECHO 1 /* Send echo requests */ -#define DHD_PKTGEN_SEND 2 /* Send discard packets */ -#define DHD_PKTGEN_RXBURST 3 /* Request dongle send N packets */ -#define DHD_PKTGEN_RECV 4 /* Continuous rx from continuous tx dongle */ -#endif /* SDTEST */ - -/* Enter idle immediately (no timeout) */ -#define DHD_IDLE_IMMEDIATE (-1) - -/* Values for idleclock iovar: other values are the sd_divisor to use when idle */ -#define DHD_IDLE_ACTIVE 0 /* Do not request any SD clock change when idle */ -#define DHD_IDLE_STOP (-1) /* Request SD clock be stopped (and use SD1 mode) */ - - -/* require default structure packing */ -#include - - -#endif /* _dhdioctl_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/epivers.h b/drivers/net/wireless/bcm4329/include/epivers.h deleted file mode 100644 index 114c735fb381..000000000000 --- a/drivers/net/wireless/bcm4329/include/epivers.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: epivers.h.in,v 13.25 2005/10/28 18:35:33 Exp $ - * -*/ - - -#ifndef _epivers_h_ -#define _epivers_h_ - -#define EPI_MAJOR_VERSION 4 - -#define EPI_MINOR_VERSION 218 - -#define EPI_RC_NUMBER 245 - -#define EPI_INCREMENTAL_NUMBER 0 - -#define EPI_BUILD_NUMBER 0 - -#define EPI_VERSION 4, 218, 245, 0 - -#define EPI_VERSION_NUM 0x04daf500 - - -#define EPI_VERSION_STR "4.218.245.0" -#define EPI_ROUTER_VERSION_STR "4.219.245.0" - -#endif diff --git a/drivers/net/wireless/bcm4329/include/hndpmu.h b/drivers/net/wireless/bcm4329/include/hndpmu.h deleted file mode 100644 index e829b3df2d0b..000000000000 --- a/drivers/net/wireless/bcm4329/include/hndpmu.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * HND SiliconBackplane PMU support. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: hndpmu.h,v 13.14.4.3.4.3.8.7 2010/04/09 13:20:51 Exp $ - */ - -#ifndef _hndpmu_h_ -#define _hndpmu_h_ - - -extern void si_pmu_otp_power(si_t *sih, osl_t *osh, bool on); -extern void si_sdiod_drive_strength_init(si_t *sih, osl_t *osh, uint32 drivestrength); - -#endif /* _hndpmu_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/hndrte_armtrap.h b/drivers/net/wireless/bcm4329/include/hndrte_armtrap.h deleted file mode 100644 index ca3281b6d901..000000000000 --- a/drivers/net/wireless/bcm4329/include/hndrte_armtrap.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * HNDRTE arm trap handling. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: hndrte_armtrap.h,v 13.3.196.2 2010/07/15 19:06:11 Exp $ - */ - -#ifndef _hndrte_armtrap_h -#define _hndrte_armtrap_h - - -/* ARM trap handling */ - -/* Trap types defined by ARM (see arminc.h) */ - -/* Trap locations in lo memory */ -#define TRAP_STRIDE 4 -#define FIRST_TRAP TR_RST -#define LAST_TRAP (TR_FIQ * TRAP_STRIDE) - -#if defined(__ARM_ARCH_4T__) -#define MAX_TRAP_TYPE (TR_FIQ + 1) -#elif defined(__ARM_ARCH_7M__) -#define MAX_TRAP_TYPE (TR_ISR + ARMCM3_NUMINTS) -#endif /* __ARM_ARCH_7M__ */ - -/* The trap structure is defined here as offsets for assembly */ -#define TR_TYPE 0x00 -#define TR_EPC 0x04 -#define TR_CPSR 0x08 -#define TR_SPSR 0x0c -#define TR_REGS 0x10 -#define TR_REG(n) (TR_REGS + (n) * 4) -#define TR_SP TR_REG(13) -#define TR_LR TR_REG(14) -#define TR_PC TR_REG(15) - -#define TRAP_T_SIZE 80 - -#ifndef _LANGUAGE_ASSEMBLY - -#include - -typedef struct _trap_struct { - uint32 type; - uint32 epc; - uint32 cpsr; - uint32 spsr; - uint32 r0; - uint32 r1; - uint32 r2; - uint32 r3; - uint32 r4; - uint32 r5; - uint32 r6; - uint32 r7; - uint32 r8; - uint32 r9; - uint32 r10; - uint32 r11; - uint32 r12; - uint32 r13; - uint32 r14; - uint32 pc; -} trap_t; - -#endif /* !_LANGUAGE_ASSEMBLY */ - -#endif /* _hndrte_armtrap_h */ diff --git a/drivers/net/wireless/bcm4329/include/hndrte_cons.h b/drivers/net/wireless/bcm4329/include/hndrte_cons.h deleted file mode 100644 index a42417478a16..000000000000 --- a/drivers/net/wireless/bcm4329/include/hndrte_cons.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Console support for hndrte. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: hndrte_cons.h,v 13.1.2.4 2010/07/15 19:06:11 Exp $ - */ - -#include - -#define CBUF_LEN (128) - -#define LOG_BUF_LEN 1024 - -typedef struct { - uint32 buf; /* Can't be pointer on (64-bit) hosts */ - uint buf_size; - uint idx; - char *_buf_compat; /* Redundant pointer for backward compat. */ -} hndrte_log_t; - -typedef struct { - /* Virtual UART - * When there is no UART (e.g. Quickturn), the host should write a complete - * input line directly into cbuf and then write the length into vcons_in. - * This may also be used when there is a real UART (at risk of conflicting with - * the real UART). vcons_out is currently unused. - */ - volatile uint vcons_in; - volatile uint vcons_out; - - /* Output (logging) buffer - * Console output is written to a ring buffer log_buf at index log_idx. - * The host may read the output when it sees log_idx advance. - * Output will be lost if the output wraps around faster than the host polls. - */ - hndrte_log_t log; - - /* Console input line buffer - * Characters are read one at a time into cbuf until is received, then - * the buffer is processed as a command line. Also used for virtual UART. - */ - uint cbuf_idx; - char cbuf[CBUF_LEN]; -} hndrte_cons_t; diff --git a/drivers/net/wireless/bcm4329/include/hndsoc.h b/drivers/net/wireless/bcm4329/include/hndsoc.h deleted file mode 100644 index 35424175f55e..000000000000 --- a/drivers/net/wireless/bcm4329/include/hndsoc.h +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Broadcom HND chip & on-chip-interconnect-related definitions. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: hndsoc.h,v 13.3.10.3 2008/08/06 03:43:25 Exp $ - */ - -#ifndef _HNDSOC_H -#define _HNDSOC_H - -/* Include the soci specific files */ -#include -#include - -/* - * SOC Interconnect Address Map. - * All regions may not exist on all chips. - */ -#define SI_SDRAM_BASE 0x00000000 /* Physical SDRAM */ -#define SI_PCI_MEM 0x08000000 /* Host Mode sb2pcitranslation0 (64 MB) */ -#define SI_PCI_MEM_SZ (64 * 1024 * 1024) -#define SI_PCI_CFG 0x0c000000 /* Host Mode sb2pcitranslation1 (64 MB) */ -#define SI_SDRAM_SWAPPED 0x10000000 /* Byteswapped Physical SDRAM */ - -#define SI_ENUM_BASE 0x18000000 /* Enumeration space base */ -#define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ -#ifndef SI_MAXCORES -#define SI_MAXCORES 16 /* Max cores (this is arbitrary, for software - * convenience and could be changed if we - * make any larger chips - */ -#endif - -#define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ - -#define SI_FLASH2 0x1c000000 /* Flash Region 2 (region 1 shadowed here) */ -#define SI_FLASH2_SZ 0x02000000 /* Size of Flash Region 2 */ -#define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ -#define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ -#define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ -#define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ -#define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ -#define SI_ARM7S_SRAM2 0x80000000 /* ARM7TDMI-S SRAM Region 2 */ -#define SI_ARM_FLASH1 0xffff0000 /* ARM Flash Region 1 */ -#define SI_ARM_FLASH1_SZ 0x00010000 /* ARM Size of Flash Region 1 */ - -#define SI_PCI_DMA 0x40000000 /* Client Mode sb2pcitranslation2 (1 GB) */ -#define SI_PCI_DMA2 0x80000000 /* Client Mode sb2pcitranslation2 (1 GB) */ -#define SI_PCI_DMA_SZ 0x40000000 /* Client Mode sb2pcitranslation2 size in bytes */ -#define SI_PCIE_DMA_L32 0x00000000 /* PCIE Client Mode sb2pcitranslation2 - * (2 ZettaBytes), low 32 bits - */ -#define SI_PCIE_DMA_H32 0x80000000 /* PCIE Client Mode sb2pcitranslation2 - * (2 ZettaBytes), high 32 bits - */ - -/* core codes */ -#define NODEV_CORE_ID 0x700 /* Invalid coreid */ -#define CC_CORE_ID 0x800 /* chipcommon core */ -#define ILINE20_CORE_ID 0x801 /* iline20 core */ -#define SRAM_CORE_ID 0x802 /* sram core */ -#define SDRAM_CORE_ID 0x803 /* sdram core */ -#define PCI_CORE_ID 0x804 /* pci core */ -#define MIPS_CORE_ID 0x805 /* mips core */ -#define ENET_CORE_ID 0x806 /* enet mac core */ -#define CODEC_CORE_ID 0x807 /* v90 codec core */ -#define USB_CORE_ID 0x808 /* usb 1.1 host/device core */ -#define ADSL_CORE_ID 0x809 /* ADSL core */ -#define ILINE100_CORE_ID 0x80a /* iline100 core */ -#define IPSEC_CORE_ID 0x80b /* ipsec core */ -#define UTOPIA_CORE_ID 0x80c /* utopia core */ -#define PCMCIA_CORE_ID 0x80d /* pcmcia core */ -#define SOCRAM_CORE_ID 0x80e /* internal memory core */ -#define MEMC_CORE_ID 0x80f /* memc sdram core */ -#define OFDM_CORE_ID 0x810 /* OFDM phy core */ -#define EXTIF_CORE_ID 0x811 /* external interface core */ -#define D11_CORE_ID 0x812 /* 802.11 MAC core */ -#define APHY_CORE_ID 0x813 /* 802.11a phy core */ -#define BPHY_CORE_ID 0x814 /* 802.11b phy core */ -#define GPHY_CORE_ID 0x815 /* 802.11g phy core */ -#define MIPS33_CORE_ID 0x816 /* mips3302 core */ -#define USB11H_CORE_ID 0x817 /* usb 1.1 host core */ -#define USB11D_CORE_ID 0x818 /* usb 1.1 device core */ -#define USB20H_CORE_ID 0x819 /* usb 2.0 host core */ -#define USB20D_CORE_ID 0x81a /* usb 2.0 device core */ -#define SDIOH_CORE_ID 0x81b /* sdio host core */ -#define ROBO_CORE_ID 0x81c /* roboswitch core */ -#define ATA100_CORE_ID 0x81d /* parallel ATA core */ -#define SATAXOR_CORE_ID 0x81e /* serial ATA & XOR DMA core */ -#define GIGETH_CORE_ID 0x81f /* gigabit ethernet core */ -#define PCIE_CORE_ID 0x820 /* pci express core */ -#define NPHY_CORE_ID 0x821 /* 802.11n 2x2 phy core */ -#define SRAMC_CORE_ID 0x822 /* SRAM controller core */ -#define MINIMAC_CORE_ID 0x823 /* MINI MAC/phy core */ -#define ARM11_CORE_ID 0x824 /* ARM 1176 core */ -#define ARM7S_CORE_ID 0x825 /* ARM7tdmi-s core */ -#define LPPHY_CORE_ID 0x826 /* 802.11a/b/g phy core */ -#define PMU_CORE_ID 0x827 /* PMU core */ -#define SSNPHY_CORE_ID 0x828 /* 802.11n single-stream phy core */ -#define SDIOD_CORE_ID 0x829 /* SDIO device core */ -#define ARMCM3_CORE_ID 0x82a /* ARM Cortex M3 core */ -#define QNPHY_CORE_ID 0x82b /* 802.11n 4x4 phy core */ -#define MIPS74K_CORE_ID 0x82c /* mips 74k core */ -#define GMAC_CORE_ID 0x82d /* Gigabit MAC core */ -#define DMEMC_CORE_ID 0x82e /* DDR1/2 memory controller core */ -#define PCIERC_CORE_ID 0x82f /* PCIE Root Complex core */ -#define OCP_CORE_ID 0x830 /* OCP2OCP bridge core */ -#define SC_CORE_ID 0x831 /* shared common core */ -#define AHB_CORE_ID 0x832 /* OCP2AHB bridge core */ -#define SPIH_CORE_ID 0x833 /* SPI host core */ -#define I2S_CORE_ID 0x834 /* I2S core */ -#define OOB_ROUTER_CORE_ID 0x367 /* OOB router core ID */ -#define DEF_AI_COMP 0xfff /* Default component, in ai chips it maps all - * unused address ranges - */ - -/* There are TWO constants on all HND chips: SI_ENUM_BASE above, - * and chipcommon being the first core: - */ -#define SI_CC_IDX 0 - -/* SOC Interconnect types (aka chip types) */ -#define SOCI_SB 0 -#define SOCI_AI 1 - -/* Common core control flags */ -#define SICF_BIST_EN 0x8000 -#define SICF_PME_EN 0x4000 -#define SICF_CORE_BITS 0x3ffc -#define SICF_FGC 0x0002 -#define SICF_CLOCK_EN 0x0001 - -/* Common core status flags */ -#define SISF_BIST_DONE 0x8000 -#define SISF_BIST_ERROR 0x4000 -#define SISF_GATED_CLK 0x2000 -#define SISF_DMA64 0x1000 -#define SISF_CORE_BITS 0x0fff - -/* A register that is common to all cores to - * communicate w/PMU regarding clock control. - */ -#define SI_CLK_CTL_ST 0x1e0 /* clock control and status */ - -/* clk_ctl_st register */ -#define CCS_FORCEALP 0x00000001 /* force ALP request */ -#define CCS_FORCEHT 0x00000002 /* force HT request */ -#define CCS_FORCEILP 0x00000004 /* force ILP request */ -#define CCS_ALPAREQ 0x00000008 /* ALP Avail Request */ -#define CCS_HTAREQ 0x00000010 /* HT Avail Request */ -#define CCS_FORCEHWREQOFF 0x00000020 /* Force HW Clock Request Off */ -#define CCS_ALPAVAIL 0x00010000 /* ALP is available */ -#define CCS_HTAVAIL 0x00020000 /* HT is available */ -#define CCS0_HTAVAIL 0x00010000 /* HT avail in chipc and pcmcia on 4328a0 */ -#define CCS0_ALPAVAIL 0x00020000 /* ALP avail in chipc and pcmcia on 4328a0 */ - -/* Not really related to SOC Interconnect, but a couple of software - * conventions for the use the flash space: - */ - -/* Minumum amount of flash we support */ -#define FLASH_MIN 0x00020000 /* Minimum flash size */ - -/* A boot/binary may have an embedded block that describes its size */ -#define BISZ_OFFSET 0x3e0 /* At this offset into the binary */ -#define BISZ_MAGIC 0x4249535a /* Marked with this value: 'BISZ' */ -#define BISZ_MAGIC_IDX 0 /* Word 0: magic */ -#define BISZ_TXTST_IDX 1 /* 1: text start */ -#define BISZ_TXTEND_IDX 2 /* 2: text end */ -#define BISZ_DATAST_IDX 3 /* 3: data start */ -#define BISZ_DATAEND_IDX 4 /* 4: data end */ -#define BISZ_BSSST_IDX 5 /* 5: bss start */ -#define BISZ_BSSEND_IDX 6 /* 6: bss end */ -#define BISZ_SIZE 7 /* descriptor size in 32-bit intergers */ - -#endif /* _HNDSOC_H */ diff --git a/drivers/net/wireless/bcm4329/include/linux_osl.h b/drivers/net/wireless/bcm4329/include/linux_osl.h deleted file mode 100644 index b059c2adb17d..000000000000 --- a/drivers/net/wireless/bcm4329/include/linux_osl.h +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Linux OS Independent Layer - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: linux_osl.h,v 13.131.30.8 2010/04/26 05:42:18 Exp $ - */ - - -#ifndef _linux_osl_h_ -#define _linux_osl_h_ - -#include - - -#include - - -#ifdef __GNUC__ -#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) -#if GCC_VERSION > 30100 -#define ASSERT(exp) do {} while (0) -#else - -#define ASSERT(exp) -#endif -#endif - - -#define OSL_DELAY(usec) osl_delay(usec) -extern void osl_delay(uint usec); - - - -#define OSL_PCMCIA_READ_ATTR(osh, offset, buf, size) \ - osl_pcmcia_read_attr((osh), (offset), (buf), (size)) -#define OSL_PCMCIA_WRITE_ATTR(osh, offset, buf, size) \ - osl_pcmcia_write_attr((osh), (offset), (buf), (size)) -extern void osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size); -extern void osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size); - - -#define OSL_PCI_READ_CONFIG(osh, offset, size) \ - osl_pci_read_config((osh), (offset), (size)) -#define OSL_PCI_WRITE_CONFIG(osh, offset, size, val) \ - osl_pci_write_config((osh), (offset), (size), (val)) -extern uint32 osl_pci_read_config(osl_t *osh, uint offset, uint size); -extern void osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val); - - -#define OSL_PCI_BUS(osh) osl_pci_bus(osh) -#define OSL_PCI_SLOT(osh) osl_pci_slot(osh) -extern uint osl_pci_bus(osl_t *osh); -extern uint osl_pci_slot(osl_t *osh); - - -typedef struct { - bool pkttag; - uint pktalloced; - bool mmbus; - pktfree_cb_fn_t tx_fn; - void *tx_ctx; -} osl_pubinfo_t; - - -extern osl_t *osl_attach(void *pdev, uint bustype, bool pkttag); -extern void osl_detach(osl_t *osh); - -#define PKTFREESETCB(osh, _tx_fn, _tx_ctx) \ - do { \ - ((osl_pubinfo_t*)osh)->tx_fn = _tx_fn; \ - ((osl_pubinfo_t*)osh)->tx_ctx = _tx_ctx; \ - } while (0) - - -#define BUS_SWAP32(v) (v) - - -#define MALLOC(osh, size) osl_malloc((osh), (size)) -#define MFREE(osh, addr, size) osl_mfree((osh), (addr), (size)) -#define MALLOCED(osh) osl_malloced((osh)) - - -#define MALLOC_FAILED(osh) osl_malloc_failed((osh)) - -extern void *osl_malloc(osl_t *osh, uint size); -extern void osl_mfree(osl_t *osh, void *addr, uint size); -extern uint osl_malloced(osl_t *osh); -extern uint osl_malloc_failed(osl_t *osh); - - -#define DMA_CONSISTENT_ALIGN PAGE_SIZE -#define DMA_ALLOC_CONSISTENT(osh, size, pap, dmah, alignbits) \ - osl_dma_alloc_consistent((osh), (size), (pap)) -#define DMA_FREE_CONSISTENT(osh, va, size, pa, dmah) \ - osl_dma_free_consistent((osh), (void*)(va), (size), (pa)) -extern void *osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap); -extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); - - -#define DMA_TX 1 -#define DMA_RX 2 - - -#define DMA_MAP(osh, va, size, direction, p, dmah) \ - osl_dma_map((osh), (va), (size), (direction)) -#define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ - osl_dma_unmap((osh), (pa), (size), (direction)) -extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); -extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); - - -#define OSL_DMADDRWIDTH(osh, addrwidth) do {} while (0) - - -#include -#define OSL_WRITE_REG(osh, r, v) (bcmsdh_reg_write(NULL, (uintptr)(r), sizeof(*(r)), (v))) -#define OSL_READ_REG(osh, r) (bcmsdh_reg_read(NULL, (uintptr)(r), sizeof(*(r)))) - -#define SELECT_BUS_WRITE(osh, mmap_op, bus_op) if (((osl_pubinfo_t*)(osh))->mmbus) \ - mmap_op else bus_op -#define SELECT_BUS_READ(osh, mmap_op, bus_op) (((osl_pubinfo_t*)(osh))->mmbus) ? \ - mmap_op : bus_op - - - - -#ifndef printf -#define printf(fmt, args...) printk(fmt, ## args) -#endif -#include -#include - - -#ifndef IL_BIGENDIAN -#define R_REG(osh, r) (\ - SELECT_BUS_READ(osh, sizeof(*(r)) == sizeof(uint8) ? readb((volatile uint8*)(r)) : \ - sizeof(*(r)) == sizeof(uint16) ? readw((volatile uint16*)(r)) : \ - readl((volatile uint32*)(r)), OSL_READ_REG(osh, r)) \ -) -#define W_REG(osh, r, v) do { \ - SELECT_BUS_WRITE(osh, \ - switch (sizeof(*(r))) { \ - case sizeof(uint8): writeb((uint8)(v), (volatile uint8*)(r)); break; \ - case sizeof(uint16): writew((uint16)(v), (volatile uint16*)(r)); break; \ - case sizeof(uint32): writel((uint32)(v), (volatile uint32*)(r)); break; \ - }, \ - (OSL_WRITE_REG(osh, r, v))); \ - } while (0) -#else -#define R_REG(osh, r) (\ - SELECT_BUS_READ(osh, \ - ({ \ - __typeof(*(r)) __osl_v; \ - switch (sizeof(*(r))) { \ - case sizeof(uint8): __osl_v = \ - readb((volatile uint8*)((uintptr)(r)^3)); break; \ - case sizeof(uint16): __osl_v = \ - readw((volatile uint16*)((uintptr)(r)^2)); break; \ - case sizeof(uint32): __osl_v = \ - readl((volatile uint32*)(r)); break; \ - } \ - __osl_v; \ - }), \ - OSL_READ_REG(osh, r)) \ -) -#define W_REG(osh, r, v) do { \ - SELECT_BUS_WRITE(osh, \ - switch (sizeof(*(r))) { \ - case sizeof(uint8): writeb((uint8)(v), \ - (volatile uint8*)((uintptr)(r)^3)); break; \ - case sizeof(uint16): writew((uint16)(v), \ - (volatile uint16*)((uintptr)(r)^2)); break; \ - case sizeof(uint32): writel((uint32)(v), \ - (volatile uint32*)(r)); break; \ - }, \ - (OSL_WRITE_REG(osh, r, v))); \ - } while (0) -#endif - -#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) -#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) - - -#define bcopy(src, dst, len) memcpy((dst), (src), (len)) -#define bcmp(b1, b2, len) memcmp((b1), (b2), (len)) -#define bzero(b, len) memset((b), '\0', (len)) - - -#define OSL_UNCACHED(va) ((void*)va) - - -#if defined(__i386__) -#define OSL_GETCYCLES(x) rdtscl((x)) -#else -#define OSL_GETCYCLES(x) ((x) = 0) -#endif - - -#define BUSPROBE(val, addr) ({ (val) = R_REG(NULL, (addr)); 0; }) - - -#if !defined(CONFIG_MMC_MSM7X00A) -#define REG_MAP(pa, size) ioremap_nocache((unsigned long)(pa), (unsigned long)(size)) -#else -#define REG_MAP(pa, size) (void *)(0) -#endif -#define REG_UNMAP(va) iounmap((va)) - - -#define R_SM(r) *(r) -#define W_SM(r, v) (*(r) = (v)) -#define BZERO_SM(r, len) memset((r), '\0', (len)) - - -#define PKTGET(osh, len, send) osl_pktget((osh), (len)) -#define PKTFREE(osh, skb, send) osl_pktfree((osh), (skb), (send)) -#ifdef DHD_USE_STATIC_BUF -#define PKTGET_STATIC(osh, len, send) osl_pktget_static((osh), (len)) -#define PKTFREE_STATIC(osh, skb, send) osl_pktfree_static((osh), (skb), (send)) -#endif -#define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) -#define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) -#define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) -#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) -#define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) -#define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) -#define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) -#define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) -#define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) -#define PKTDUP(osh, skb) osl_pktdup((osh), (skb)) -#define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) -#define PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced -#define PKTSETPOOL(osh, skb, x, y) do {} while (0) -#define PKTPOOL(osh, skb) FALSE -#define PKTPOOLLEN(osh, pktp) (0) -#define PKTPOOLAVAIL(osh, pktp) (0) -#define PKTPOOLADD(osh, pktp, p) BCME_ERROR -#define PKTPOOLGET(osh, pktp) NULL -#define PKTLIST_DUMP(osh, buf) - -extern void *osl_pktget(osl_t *osh, uint len); -extern void osl_pktfree(osl_t *osh, void *skb, bool send); -extern void *osl_pktget_static(osl_t *osh, uint len); -extern void osl_pktfree_static(osl_t *osh, void *skb, bool send); -extern void *osl_pktdup(osl_t *osh, void *skb); - - - -static INLINE void * -osl_pkt_frmnative(osl_pubinfo_t *osh, struct sk_buff *skb) -{ - struct sk_buff *nskb; - - if (osh->pkttag) - bzero((void*)skb->cb, OSL_PKTTAG_SZ); - - - for (nskb = skb; nskb; nskb = nskb->next) { - osh->pktalloced++; - } - - return (void *)skb; -} -#define PKTFRMNATIVE(osh, skb) osl_pkt_frmnative(((osl_pubinfo_t *)osh), (struct sk_buff*)(skb)) - - -static INLINE struct sk_buff * -osl_pkt_tonative(osl_pubinfo_t *osh, void *pkt) -{ - struct sk_buff *nskb; - - if (osh->pkttag) - bzero(((struct sk_buff*)pkt)->cb, OSL_PKTTAG_SZ); - - - for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { - osh->pktalloced--; - } - - return (struct sk_buff *)pkt; -} -#define PKTTONATIVE(osh, pkt) osl_pkt_tonative((osl_pubinfo_t *)(osh), (pkt)) - -#define PKTLINK(skb) (((struct sk_buff*)(skb))->prev) -#define PKTSETLINK(skb, x) (((struct sk_buff*)(skb))->prev = (struct sk_buff*)(x)) -#define PKTPRIO(skb) (((struct sk_buff*)(skb))->priority) -#define PKTSETPRIO(skb, x) (((struct sk_buff*)(skb))->priority = (x)) -#define PKTSUMNEEDED(skb) (((struct sk_buff*)(skb))->ip_summed == CHECKSUM_HW) -#define PKTSETSUMGOOD(skb, x) (((struct sk_buff*)(skb))->ip_summed = \ - ((x) ? CHECKSUM_UNNECESSARY : CHECKSUM_NONE)) - -#define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) - - -#define OSL_ERROR(bcmerror) osl_error(bcmerror) -extern int osl_error(int bcmerror); - - -#define PKTBUFSZ 2048 - - -#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) -#endif diff --git a/drivers/net/wireless/bcm4329/include/linuxver.h b/drivers/net/wireless/bcm4329/include/linuxver.h deleted file mode 100644 index 6ee5c5872f61..000000000000 --- a/drivers/net/wireless/bcm4329/include/linuxver.h +++ /dev/null @@ -1,462 +0,0 @@ -/* - * Linux-specific abstractions to gain some independence from linux kernel versions. - * Pave over some 2.2 versus 2.4 versus 2.6 kernel differences. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: linuxver.h,v 13.38.8.1.8.6 2010/04/29 05:00:46 Exp $ - */ - - -#ifndef _linuxver_h_ -#define _linuxver_h_ - -#include -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) -#include -#else -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) -#include -#else -#include -#endif -#endif -#include - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 0)) - -#ifdef __UNDEF_NO_VERSION__ -#undef __NO_VERSION__ -#else -#define __NO_VERSION__ -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 5, 0) -#define module_param(_name_, _type_, _perm_) MODULE_PARM(_name_, "i") -#define module_param_string(_name_, _string_, _size_, _perm_) \ - MODULE_PARM(_string_, "c" __MODULE_STRING(_size_)) -#endif - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 9)) -#include -#else -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) -#undef IP_TOS -#endif -#include - -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 5, 41)) -#include -#else -#include -#ifndef work_struct -#define work_struct tq_struct -#endif -#ifndef INIT_WORK -#define INIT_WORK(_work, _func, _data) INIT_TQUEUE((_work), (_func), (_data)) -#endif -#ifndef schedule_work -#define schedule_work(_work) schedule_task((_work)) -#endif -#ifndef flush_scheduled_work -#define flush_scheduled_work() flush_scheduled_tasks() -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -#define MY_INIT_WORK(_work, _func, _data) INIT_WORK(_work, _func) -#else -#define MY_INIT_WORK(_work, _func, _data) INIT_WORK(_work, _func, _data) -typedef void (*work_func_t)(void *work); -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) - -#ifndef IRQ_NONE -typedef void irqreturn_t; -#define IRQ_NONE -#define IRQ_HANDLED -#define IRQ_RETVAL(x) -#endif -#else -typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 18) -#define IRQF_SHARED SA_SHIRQ -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 17) -#ifdef CONFIG_NET_RADIO -#define CONFIG_WIRELESS_EXT -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 67) -#ifndef SANDGATE2G -#define MOD_INC_USE_COUNT -#endif -#endif - - -#ifndef __exit -#define __exit -#endif -#ifndef __devexit -#define __devexit -#endif -#ifndef __devinit -#define __devinit __init -#endif -#ifndef __devinitdata -#define __devinitdata -#endif -#ifndef __devexit_p -#define __devexit_p(x) x -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 0)) - -#define pci_get_drvdata(dev) (dev)->sysdata -#define pci_set_drvdata(dev, value) (dev)->sysdata = (value) - - - -struct pci_device_id { - unsigned int vendor, device; - unsigned int subvendor, subdevice; - unsigned int class, class_mask; - unsigned long driver_data; -}; - -struct pci_driver { - struct list_head node; - char *name; - const struct pci_device_id *id_table; - int (*probe)(struct pci_dev *dev, - const struct pci_device_id *id); - void (*remove)(struct pci_dev *dev); - void (*suspend)(struct pci_dev *dev); - void (*resume)(struct pci_dev *dev); -}; - -#define MODULE_DEVICE_TABLE(type, name) -#define PCI_ANY_ID (~0) - - -#define pci_module_init pci_register_driver -extern int pci_register_driver(struct pci_driver *drv); -extern void pci_unregister_driver(struct pci_driver *drv); - -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 18)) -#define pci_module_init pci_register_driver -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 2, 18)) -#ifdef MODULE -#define module_init(x) int init_module(void) { return x(); } -#define module_exit(x) void cleanup_module(void) { x(); } -#else -#define module_init(x) __initcall(x); -#define module_exit(x) __exitcall(x); -#endif -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 48)) -#define list_for_each(pos, head) \ - for (pos = (head)->next; pos != (head); pos = pos->next) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 13)) -#define pci_resource_start(dev, bar) ((dev)->base_address[(bar)]) -#elif (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 44)) -#define pci_resource_start(dev, bar) ((dev)->resource[(bar)].start) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 23)) -#define pci_enable_device(dev) do { } while (0) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 14)) -#define net_device device -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 42)) - - - -#ifndef PCI_DMA_TODEVICE -#define PCI_DMA_TODEVICE 1 -#define PCI_DMA_FROMDEVICE 2 -#endif - -typedef u32 dma_addr_t; - - -static inline int get_order(unsigned long size) -{ - int order; - - size = (size-1) >> (PAGE_SHIFT-1); - order = -1; - do { - size >>= 1; - order++; - } while (size); - return order; -} - -static inline void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, - dma_addr_t *dma_handle) -{ - void *ret; - int gfp = GFP_ATOMIC | GFP_DMA; - - ret = (void *)__get_free_pages(gfp, get_order(size)); - - if (ret != NULL) { - memset(ret, 0, size); - *dma_handle = virt_to_bus(ret); - } - return ret; -} -static inline void pci_free_consistent(struct pci_dev *hwdev, size_t size, - void *vaddr, dma_addr_t dma_handle) -{ - free_pages((unsigned long)vaddr, get_order(size)); -} -#define pci_map_single(cookie, address, size, dir) virt_to_bus(address) -#define pci_unmap_single(cookie, address, size, dir) - -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 3, 43)) - -#define dev_kfree_skb_any(a) dev_kfree_skb(a) -#define netif_down(dev) do { (dev)->start = 0; } while (0) - - -#ifndef _COMPAT_NETDEVICE_H - - - -#define dev_kfree_skb_irq(a) dev_kfree_skb(a) -#define netif_wake_queue(dev) \ - do { clear_bit(0, &(dev)->tbusy); mark_bh(NET_BH); } while (0) -#define netif_stop_queue(dev) set_bit(0, &(dev)->tbusy) - -static inline void netif_start_queue(struct net_device *dev) -{ - dev->tbusy = 0; - dev->interrupt = 0; - dev->start = 1; -} - -#define netif_queue_stopped(dev) (dev)->tbusy -#define netif_running(dev) (dev)->start - -#endif - -#define netif_device_attach(dev) netif_start_queue(dev) -#define netif_device_detach(dev) netif_stop_queue(dev) - - -#define tasklet_struct tq_struct -static inline void tasklet_schedule(struct tasklet_struct *tasklet) -{ - queue_task(tasklet, &tq_immediate); - mark_bh(IMMEDIATE_BH); -} - -static inline void tasklet_init(struct tasklet_struct *tasklet, - void (*func)(unsigned long), - unsigned long data) -{ - tasklet->next = NULL; - tasklet->sync = 0; - tasklet->routine = (void (*)(void *))func; - tasklet->data = (void *)data; -} -#define tasklet_kill(tasklet) { do {} while (0); } - - -#define del_timer_sync(timer) del_timer(timer) - -#else - -#define netif_down(dev) - -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 3)) - - -#define PREPARE_TQUEUE(_tq, _routine, _data) \ - do { \ - (_tq)->routine = _routine; \ - (_tq)->data = _data; \ - } while (0) - - -#define INIT_TQUEUE(_tq, _routine, _data) \ - do { \ - INIT_LIST_HEAD(&(_tq)->list); \ - (_tq)->sync = 0; \ - PREPARE_TQUEUE((_tq), (_routine), (_data)); \ - } while (0) - -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 6)) - - - -static inline int -pci_save_state(struct pci_dev *dev, u32 *buffer) -{ - int i; - if (buffer) { - for (i = 0; i < 16; i++) - pci_read_config_dword(dev, i * 4, &buffer[i]); - } - return 0; -} - -static inline int -pci_restore_state(struct pci_dev *dev, u32 *buffer) -{ - int i; - - if (buffer) { - for (i = 0; i < 16; i++) - pci_write_config_dword(dev, i * 4, buffer[i]); - } - - else { - for (i = 0; i < 6; i ++) - pci_write_config_dword(dev, - PCI_BASE_ADDRESS_0 + (i * 4), - pci_resource_start(dev, i)); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, dev->irq); - } - return 0; -} - -#endif - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 4, 19)) -#define read_c0_count() read_32bit_cp0_register(CP0_COUNT) -#endif - - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)) -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) do {} while (0) -#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -#else -#define OLD_MOD_INC_USE_COUNT do {} while (0) -#define OLD_MOD_DEC_USE_COUNT do {} while (0) -#endif -#else -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) do {} while (0) -#endif -#ifndef MOD_INC_USE_COUNT -#define MOD_INC_USE_COUNT do {} while (0) -#endif -#ifndef MOD_DEC_USE_COUNT -#define MOD_DEC_USE_COUNT do {} while (0) -#endif -#define OLD_MOD_INC_USE_COUNT MOD_INC_USE_COUNT -#define OLD_MOD_DEC_USE_COUNT MOD_DEC_USE_COUNT -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) do {} while (0) -#endif - -#ifndef HAVE_FREE_NETDEV -#define free_netdev(dev) kfree(dev) -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) - -#define af_packet_priv data -#endif - - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 11) -#define DRV_SUSPEND_STATE_TYPE pm_message_t -#else -#define DRV_SUSPEND_STATE_TYPE uint32 -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19) -#define CHECKSUM_HW CHECKSUM_PARTIAL -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) -#define KILL_PROC(nr, sig) \ -{ \ -struct task_struct *tsk; \ -struct pid *pid; \ -pid = find_get_pid((pid_t)nr); \ -tsk = pid_task(pid, PIDTYPE_PID); \ -if (tsk) send_sig(sig, tsk, 1); \ -} -#else -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \ - KERNEL_VERSION(2, 6, 30)) -#define KILL_PROC(pid, sig) \ -{ \ - struct task_struct *tsk; \ - tsk = find_task_by_vpid(pid); \ - if (tsk) send_sig(sig, tsk, 1); \ -} -#else -#define KILL_PROC(pid, sig) \ -{ \ - kill_proc(pid, sig, 1); \ -} -#endif -#endif - -#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0)) -#define netdev_priv(dev) dev->priv -#endif - -#endif diff --git a/drivers/net/wireless/bcm4329/include/miniopt.h b/drivers/net/wireless/bcm4329/include/miniopt.h deleted file mode 100644 index 3667fb1e215b..000000000000 --- a/drivers/net/wireless/bcm4329/include/miniopt.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Command line options parser. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: miniopt.h,v 1.1.6.2 2009/01/14 23:52:48 Exp $ - */ - - -#ifndef MINI_OPT_H -#define MINI_OPT_H - -#ifdef __cplusplus -extern "C" { -#endif - -/* ---- Include Files ---------------------------------------------------- */ -/* ---- Constants and Types ---------------------------------------------- */ - -#define MINIOPT_MAXKEY 128 /* Max options */ -typedef struct miniopt { - - /* These are persistent after miniopt_init() */ - const char* name; /* name for prompt in error strings */ - const char* flags; /* option chars that take no args */ - bool longflags; /* long options may be flags */ - bool opt_end; /* at end of options (passed a "--") */ - - /* These are per-call to miniopt() */ - - int consumed; /* number of argv entries cosumed in - * the most recent call to miniopt() - */ - bool positional; - bool good_int; /* 'val' member is the result of a sucessful - * strtol conversion of the option value - */ - char opt; - char key[MINIOPT_MAXKEY]; - char* valstr; /* positional param, or value for the option, - * or null if the option had - * no accompanying value - */ - uint uval; /* strtol translation of valstr */ - int val; /* strtol translation of valstr */ -} miniopt_t; - -void miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags); -int miniopt(miniopt_t *t, char **argv); - - -/* ---- Variable Externs ------------------------------------------------- */ -/* ---- Function Prototypes ---------------------------------------------- */ - - -#ifdef __cplusplus - } -#endif - -#endif /* MINI_OPT_H */ diff --git a/drivers/net/wireless/bcm4329/include/msgtrace.h b/drivers/net/wireless/bcm4329/include/msgtrace.h deleted file mode 100644 index 1479086dba3e..000000000000 --- a/drivers/net/wireless/bcm4329/include/msgtrace.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Trace messages sent over HBUS - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: msgtrace.h,v 1.1.2.4 2009/01/27 04:09:40 Exp $ - */ - -#ifndef _MSGTRACE_H -#define _MSGTRACE_H - -#ifndef _TYPEDEFS_H_ -#include -#endif - - -/* This marks the start of a packed structure section. */ -#include - -#define MSGTRACE_VERSION 1 - -/* Message trace header */ -typedef BWL_PRE_PACKED_STRUCT struct msgtrace_hdr { - uint8 version; - uint8 spare; - uint16 len; /* Len of the trace */ - uint32 seqnum; /* Sequence number of message. Useful if the messsage has been lost - * because of DMA error or a bus reset (ex: SDIO Func2) - */ - uint32 discarded_bytes; /* Number of discarded bytes because of trace overflow */ - uint32 discarded_printf; /* Number of discarded printf because of trace overflow */ -} BWL_POST_PACKED_STRUCT msgtrace_hdr_t; - -#define MSGTRACE_HDRLEN sizeof(msgtrace_hdr_t) - -/* The hbus driver generates traces when sending a trace message. This causes endless traces. - * This flag must be set to TRUE in any hbus traces. The flag is reset in the function msgtrace_put. - * This prevents endless traces but generates hasardous lost of traces only in bus device code. - * It is recommendat to set this flag in macro SD_TRACE but not in SD_ERROR for avoiding missing - * hbus error traces. hbus error trace should not generates endless traces. - */ -extern bool msgtrace_hbus_trace; - -typedef void (*msgtrace_func_send_t)(void *hdl1, void *hdl2, uint8 *hdr, - uint16 hdrlen, uint8 *buf, uint16 buflen); - -extern void msgtrace_sent(void); -extern void msgtrace_put(char *buf, int count); -extern void msgtrace_init(void *hdl1, void *hdl2, msgtrace_func_send_t func_send); - -/* This marks the end of a packed structure section. */ -#include - -#endif /* _MSGTRACE_H */ diff --git a/drivers/net/wireless/bcm4329/include/osl.h b/drivers/net/wireless/bcm4329/include/osl.h deleted file mode 100644 index 5599e536eeea..000000000000 --- a/drivers/net/wireless/bcm4329/include/osl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * OS Abstraction Layer - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: osl.h,v 13.37.32.1 2008/11/20 00:51:15 Exp $ - */ - - -#ifndef _osl_h_ -#define _osl_h_ - - -typedef struct osl_info osl_t; -typedef struct osl_dmainfo osldma_t; - -#define OSL_PKTTAG_SZ 32 - - -typedef void (*pktfree_cb_fn_t)(void *ctx, void *pkt, unsigned int status); - -#include - - - - -#define SET_REG(osh, r, mask, val) W_REG((osh), (r), ((R_REG((osh), r) & ~(mask)) | (val))) - -#ifndef AND_REG -#define AND_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) & (v)) -#endif - -#ifndef OR_REG -#define OR_REG(osh, r, v) W_REG(osh, (r), R_REG(osh, r) | (v)) -#endif - - -#endif diff --git a/drivers/net/wireless/bcm4329/include/packed_section_end.h b/drivers/net/wireless/bcm4329/include/packed_section_end.h deleted file mode 100644 index 5b61c18fcd08..000000000000 --- a/drivers/net/wireless/bcm4329/include/packed_section_end.h +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Declare directives for structure packing. No padding will be provided - * between the members of packed structures, and therefore, there is no - * guarantee that structure members will be aligned. - * - * Declaring packed structures is compiler specific. In order to handle all - * cases, packed structures should be delared as: - * - * #include - * - * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { - * some_struct_members; - * } BWL_POST_PACKED_STRUCT foobar_t; - * - * #include - * - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: packed_section_end.h,v 1.1.6.3 2008/12/10 00:27:54 Exp $ - */ - - - - -#ifdef BWL_PACKED_SECTION - #undef BWL_PACKED_SECTION -#else - #error "BWL_PACKED_SECTION is NOT defined!" -#endif - - - - - -#undef BWL_PRE_PACKED_STRUCT -#undef BWL_POST_PACKED_STRUCT diff --git a/drivers/net/wireless/bcm4329/include/packed_section_start.h b/drivers/net/wireless/bcm4329/include/packed_section_start.h deleted file mode 100644 index cb93aa64079a..000000000000 --- a/drivers/net/wireless/bcm4329/include/packed_section_start.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Declare directives for structure packing. No padding will be provided - * between the members of packed structures, and therefore, there is no - * guarantee that structure members will be aligned. - * - * Declaring packed structures is compiler specific. In order to handle all - * cases, packed structures should be delared as: - * - * #include - * - * typedef BWL_PRE_PACKED_STRUCT struct foobar_t { - * some_struct_members; - * } BWL_POST_PACKED_STRUCT foobar_t; - * - * #include - * - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: packed_section_start.h,v 1.1.6.3 2008/12/10 00:27:54 Exp $ - */ - - - - -#ifdef BWL_PACKED_SECTION - #error "BWL_PACKED_SECTION is already defined!" -#else - #define BWL_PACKED_SECTION -#endif - - - - - -#if defined(__GNUC__) - #define BWL_PRE_PACKED_STRUCT - #define BWL_POST_PACKED_STRUCT __attribute__((packed)) -#elif defined(__CC_ARM) - #define BWL_PRE_PACKED_STRUCT __packed - #define BWL_POST_PACKED_STRUCT -#else - #error "Unknown compiler!" -#endif diff --git a/drivers/net/wireless/bcm4329/include/pcicfg.h b/drivers/net/wireless/bcm4329/include/pcicfg.h deleted file mode 100644 index 898962c942a8..000000000000 --- a/drivers/net/wireless/bcm4329/include/pcicfg.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * pcicfg.h: PCI configuration constants and structures. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: pcicfg.h,v 1.41.12.3 2008/06/26 22:49:41 Exp $ - */ - - -#ifndef _h_pcicfg_ -#define _h_pcicfg_ - - -#define PCI_CFG_VID 0 -#define PCI_CFG_CMD 4 -#define PCI_CFG_REV 8 -#define PCI_CFG_BAR0 0x10 -#define PCI_CFG_BAR1 0x14 -#define PCI_BAR0_WIN 0x80 -#define PCI_INT_STATUS 0x90 -#define PCI_INT_MASK 0x94 - -#define PCIE_EXTCFG_OFFSET 0x100 -#define PCI_BAR0_PCIREGS_OFFSET (6 * 1024) -#define PCI_BAR0_PCISBR_OFFSET (4 * 1024) - -#define PCI_BAR0_WINSZ (16 * 1024) - - -#define PCI_16KB0_PCIREGS_OFFSET (8 * 1024) -#define PCI_16KB0_CCREGS_OFFSET (12 * 1024) -#define PCI_16KBB0_WINSZ (16 * 1024) - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/802.11.h b/drivers/net/wireless/bcm4329/include/proto/802.11.h deleted file mode 100644 index fd26317361da..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/802.11.h +++ /dev/null @@ -1,1433 +0,0 @@ -/* - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * Fundamental types and constants relating to 802.11 - * - * $Id: 802.11.h,v 9.219.4.1.4.5.6.11 2010/02/09 13:23:26 Exp $ - */ - - -#ifndef _802_11_H_ -#define _802_11_H_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - -#ifndef _NET_ETHERNET_H_ -#include -#endif - -#include - - -#include - - -#define DOT11_TU_TO_US 1024 - - -#define DOT11_A3_HDR_LEN 24 -#define DOT11_A4_HDR_LEN 30 -#define DOT11_MAC_HDR_LEN DOT11_A3_HDR_LEN -#define DOT11_FCS_LEN 4 -#define DOT11_ICV_LEN 4 -#define DOT11_ICV_AES_LEN 8 -#define DOT11_QOS_LEN 2 -#define DOT11_HTC_LEN 4 - -#define DOT11_KEY_INDEX_SHIFT 6 -#define DOT11_IV_LEN 4 -#define DOT11_IV_TKIP_LEN 8 -#define DOT11_IV_AES_OCB_LEN 4 -#define DOT11_IV_AES_CCM_LEN 8 -#define DOT11_IV_MAX_LEN 8 - - -#define DOT11_MAX_MPDU_BODY_LEN 2304 - -#define DOT11_MAX_MPDU_LEN (DOT11_A4_HDR_LEN + \ - DOT11_QOS_LEN + \ - DOT11_IV_AES_CCM_LEN + \ - DOT11_MAX_MPDU_BODY_LEN + \ - DOT11_ICV_LEN + \ - DOT11_FCS_LEN) - -#define DOT11_MAX_SSID_LEN 32 - - -#define DOT11_DEFAULT_RTS_LEN 2347 -#define DOT11_MAX_RTS_LEN 2347 - - -#define DOT11_MIN_FRAG_LEN 256 -#define DOT11_MAX_FRAG_LEN 2346 -#define DOT11_DEFAULT_FRAG_LEN 2346 - - -#define DOT11_MIN_BEACON_PERIOD 1 -#define DOT11_MAX_BEACON_PERIOD 0xFFFF - - -#define DOT11_MIN_DTIM_PERIOD 1 -#define DOT11_MAX_DTIM_PERIOD 0xFF - - -#define DOT11_LLC_SNAP_HDR_LEN 8 -#define DOT11_OUI_LEN 3 -BWL_PRE_PACKED_STRUCT struct dot11_llc_snap_header { - uint8 dsap; - uint8 ssap; - uint8 ctl; - uint8 oui[DOT11_OUI_LEN]; - uint16 type; -} BWL_POST_PACKED_STRUCT; - - -#define RFC1042_HDR_LEN (ETHER_HDR_LEN + DOT11_LLC_SNAP_HDR_LEN) - - - -BWL_PRE_PACKED_STRUCT struct dot11_header { - uint16 fc; - uint16 durid; - struct ether_addr a1; - struct ether_addr a2; - struct ether_addr a3; - uint16 seq; - struct ether_addr a4; -} BWL_POST_PACKED_STRUCT; - - - -BWL_PRE_PACKED_STRUCT struct dot11_rts_frame { - uint16 fc; - uint16 durid; - struct ether_addr ra; - struct ether_addr ta; -} BWL_POST_PACKED_STRUCT; -#define DOT11_RTS_LEN 16 - -BWL_PRE_PACKED_STRUCT struct dot11_cts_frame { - uint16 fc; - uint16 durid; - struct ether_addr ra; -} BWL_POST_PACKED_STRUCT; -#define DOT11_CTS_LEN 10 - -BWL_PRE_PACKED_STRUCT struct dot11_ack_frame { - uint16 fc; - uint16 durid; - struct ether_addr ra; -} BWL_POST_PACKED_STRUCT; -#define DOT11_ACK_LEN 10 - -BWL_PRE_PACKED_STRUCT struct dot11_ps_poll_frame { - uint16 fc; - uint16 durid; - struct ether_addr bssid; - struct ether_addr ta; -} BWL_POST_PACKED_STRUCT; -#define DOT11_PS_POLL_LEN 16 - -BWL_PRE_PACKED_STRUCT struct dot11_cf_end_frame { - uint16 fc; - uint16 durid; - struct ether_addr ra; - struct ether_addr bssid; -} BWL_POST_PACKED_STRUCT; -#define DOT11_CS_END_LEN 16 - -BWL_PRE_PACKED_STRUCT struct dot11_action_wifi_vendor_specific { - uint8 category; - uint8 OUI[3]; - uint8 type; - uint8 subtype; - uint8 data[1040]; - struct dot11_action_wifi_vendor_specific* next_node; -} BWL_POST_PACKED_STRUCT; - -typedef struct dot11_action_wifi_vendor_specific dot11_action_wifi_vendor_specific_t; - -#define DOT11_BA_CTL_POLICY_NORMAL 0x0000 -#define DOT11_BA_CTL_POLICY_NOACK 0x0001 -#define DOT11_BA_CTL_POLICY_MASK 0x0001 - -#define DOT11_BA_CTL_MTID 0x0002 -#define DOT11_BA_CTL_COMPRESSED 0x0004 - -#define DOT11_BA_CTL_NUMMSDU_MASK 0x0FC0 -#define DOT11_BA_CTL_NUMMSDU_SHIFT 6 - -#define DOT11_BA_CTL_TID_MASK 0xF000 -#define DOT11_BA_CTL_TID_SHIFT 12 - - -BWL_PRE_PACKED_STRUCT struct dot11_ctl_header { - uint16 fc; - uint16 durid; - struct ether_addr ra; - struct ether_addr ta; -} BWL_POST_PACKED_STRUCT; -#define DOT11_CTL_HDR_LEN 16 - - -BWL_PRE_PACKED_STRUCT struct dot11_bar { - uint16 bar_control; - uint16 seqnum; -} BWL_POST_PACKED_STRUCT; -#define DOT11_BAR_LEN 4 - -#define DOT11_BA_BITMAP_LEN 128 -#define DOT11_BA_CMP_BITMAP_LEN 8 - -BWL_PRE_PACKED_STRUCT struct dot11_ba { - uint16 ba_control; - uint16 seqnum; - uint8 bitmap[DOT11_BA_BITMAP_LEN]; -} BWL_POST_PACKED_STRUCT; -#define DOT11_BA_LEN 4 - - -BWL_PRE_PACKED_STRUCT struct dot11_management_header { - uint16 fc; - uint16 durid; - struct ether_addr da; - struct ether_addr sa; - struct ether_addr bssid; - uint16 seq; -} BWL_POST_PACKED_STRUCT; -#define DOT11_MGMT_HDR_LEN 24 - - - -BWL_PRE_PACKED_STRUCT struct dot11_bcn_prb { - uint32 timestamp[2]; - uint16 beacon_interval; - uint16 capability; -} BWL_POST_PACKED_STRUCT; -#define DOT11_BCN_PRB_LEN 12 - -BWL_PRE_PACKED_STRUCT struct dot11_auth { - uint16 alg; - uint16 seq; - uint16 status; -} BWL_POST_PACKED_STRUCT; -#define DOT11_AUTH_FIXED_LEN 6 - -BWL_PRE_PACKED_STRUCT struct dot11_assoc_req { - uint16 capability; - uint16 listen; -} BWL_POST_PACKED_STRUCT; -#define DOT11_ASSOC_REQ_FIXED_LEN 4 - -BWL_PRE_PACKED_STRUCT struct dot11_reassoc_req { - uint16 capability; - uint16 listen; - struct ether_addr ap; -} BWL_POST_PACKED_STRUCT; -#define DOT11_REASSOC_REQ_FIXED_LEN 10 - -BWL_PRE_PACKED_STRUCT struct dot11_assoc_resp { - uint16 capability; - uint16 status; - uint16 aid; -} BWL_POST_PACKED_STRUCT; -#define DOT11_ASSOC_RESP_FIXED_LEN 6 - -BWL_PRE_PACKED_STRUCT struct dot11_action_measure { - uint8 category; - uint8 action; - uint8 token; - uint8 data[1]; -} BWL_POST_PACKED_STRUCT; -#define DOT11_ACTION_MEASURE_LEN 3 - -BWL_PRE_PACKED_STRUCT struct dot11_action_ht_ch_width { - uint8 category; - uint8 action; - uint8 ch_width; -} BWL_POST_PACKED_STRUCT; - -BWL_PRE_PACKED_STRUCT struct dot11_action_ht_mimops { - uint8 category; - uint8 action; - uint8 control; -} BWL_POST_PACKED_STRUCT; - -#define SM_PWRSAVE_ENABLE 1 -#define SM_PWRSAVE_MODE 2 - - -BWL_PRE_PACKED_STRUCT struct dot11_power_cnst { - uint8 id; - uint8 len; - uint8 power; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_power_cnst dot11_power_cnst_t; - -BWL_PRE_PACKED_STRUCT struct dot11_power_cap { - uint8 min; - uint8 max; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_power_cap dot11_power_cap_t; - -BWL_PRE_PACKED_STRUCT struct dot11_tpc_rep { - uint8 id; - uint8 len; - uint8 tx_pwr; - uint8 margin; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_tpc_rep dot11_tpc_rep_t; -#define DOT11_MNG_IE_TPC_REPORT_LEN 2 - -BWL_PRE_PACKED_STRUCT struct dot11_supp_channels { - uint8 id; - uint8 len; - uint8 first_channel; - uint8 num_channels; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_supp_channels dot11_supp_channels_t; - - -BWL_PRE_PACKED_STRUCT struct dot11_extch { - uint8 id; - uint8 len; - uint8 extch; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_extch dot11_extch_ie_t; - -BWL_PRE_PACKED_STRUCT struct dot11_brcm_extch { - uint8 id; - uint8 len; - uint8 oui[3]; - uint8 type; - uint8 extch; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_brcm_extch dot11_brcm_extch_ie_t; - -#define BRCM_EXTCH_IE_LEN 5 -#define BRCM_EXTCH_IE_TYPE 53 -#define DOT11_EXTCH_IE_LEN 1 -#define DOT11_EXT_CH_MASK 0x03 -#define DOT11_EXT_CH_UPPER 0x01 -#define DOT11_EXT_CH_LOWER 0x03 -#define DOT11_EXT_CH_NONE 0x00 - -BWL_PRE_PACKED_STRUCT struct dot11_action_frmhdr { - uint8 category; - uint8 action; - uint8 data[1]; -} BWL_POST_PACKED_STRUCT; -#define DOT11_ACTION_FRMHDR_LEN 2 - - -BWL_PRE_PACKED_STRUCT struct dot11_channel_switch { - uint8 id; - uint8 len; - uint8 mode; - uint8 channel; - uint8 count; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_channel_switch dot11_chan_switch_ie_t; - -#define DOT11_SWITCH_IE_LEN 3 - -#define DOT11_CSA_MODE_ADVISORY 0 -#define DOT11_CSA_MODE_NO_TX 1 - -BWL_PRE_PACKED_STRUCT struct dot11_action_switch_channel { - uint8 category; - uint8 action; - dot11_chan_switch_ie_t chan_switch_ie; - dot11_brcm_extch_ie_t extch_ie; -} BWL_POST_PACKED_STRUCT; - -BWL_PRE_PACKED_STRUCT struct dot11_csa_body { - uint8 mode; - uint8 reg; - uint8 channel; - uint8 count; -} BWL_POST_PACKED_STRUCT; - - -BWL_PRE_PACKED_STRUCT struct dot11_ext_csa { - uint8 id; - uint8 len; - struct dot11_csa_body b; -} BWL_POST_PACKED_STRUCT; - -BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { - uint8 category; - uint8 action; - struct dot11_csa_body b; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_ext_csa dot11_ext_csa_ie_t; -#define DOT11_EXT_CSA_IE_LEN 4 - -BWL_PRE_PACKED_STRUCT struct dot11_action_ext_csa { - uint8 category; - uint8 action; - dot11_ext_csa_ie_t chan_switch_ie; -} BWL_POST_PACKED_STRUCT; - -BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { - uint8 id; - uint8 len; - uint8 info; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_obss_coex dot11_obss_coex_t; -#define DOT11_OBSS_COEXINFO_LEN 1 - -#define DOT11_OBSS_COEX_INFO_REQ 0x01 -#define DOT11_OBSS_COEX_40MHZ_INTOLERANT 0x02 -#define DOT11_OBSS_COEX_20MHZ_WIDTH_REQ 0x04 - -BWL_PRE_PACKED_STRUCT struct dot11_obss_chanlist { - uint8 id; - uint8 len; - uint8 regclass; - uint8 chanlist[1]; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_obss_chanlist dot11_obss_chanlist_t; -#define DOT11_OBSS_CHANLIST_FIXED_LEN 1 - -BWL_PRE_PACKED_STRUCT struct dot11_extcap_ie { - uint8 id; - uint8 len; - uint8 cap; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_extcap_ie dot11_extcap_ie_t; -#define DOT11_EXTCAP_LEN 1 - - - -#define DOT11_MEASURE_TYPE_BASIC 0 -#define DOT11_MEASURE_TYPE_CCA 1 -#define DOT11_MEASURE_TYPE_RPI 2 - - -#define DOT11_MEASURE_MODE_ENABLE (1<<1) -#define DOT11_MEASURE_MODE_REQUEST (1<<2) -#define DOT11_MEASURE_MODE_REPORT (1<<3) - -#define DOT11_MEASURE_MODE_LATE (1<<0) -#define DOT11_MEASURE_MODE_INCAPABLE (1<<1) -#define DOT11_MEASURE_MODE_REFUSED (1<<2) - -#define DOT11_MEASURE_BASIC_MAP_BSS ((uint8)(1<<0)) -#define DOT11_MEASURE_BASIC_MAP_OFDM ((uint8)(1<<1)) -#define DOT11_MEASURE_BASIC_MAP_UKNOWN ((uint8)(1<<2)) -#define DOT11_MEASURE_BASIC_MAP_RADAR ((uint8)(1<<3)) -#define DOT11_MEASURE_BASIC_MAP_UNMEAS ((uint8)(1<<4)) - -BWL_PRE_PACKED_STRUCT struct dot11_meas_req { - uint8 id; - uint8 len; - uint8 token; - uint8 mode; - uint8 type; - uint8 channel; - uint8 start_time[8]; - uint16 duration; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_meas_req dot11_meas_req_t; -#define DOT11_MNG_IE_MREQ_LEN 14 - -#define DOT11_MNG_IE_MREQ_FIXED_LEN 3 - -BWL_PRE_PACKED_STRUCT struct dot11_meas_rep { - uint8 id; - uint8 len; - uint8 token; - uint8 mode; - uint8 type; - BWL_PRE_PACKED_STRUCT union - { - BWL_PRE_PACKED_STRUCT struct { - uint8 channel; - uint8 start_time[8]; - uint16 duration; - uint8 map; - } BWL_POST_PACKED_STRUCT basic; - uint8 data[1]; - } BWL_POST_PACKED_STRUCT rep; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_meas_rep dot11_meas_rep_t; - - -#define DOT11_MNG_IE_MREP_FIXED_LEN 3 - -BWL_PRE_PACKED_STRUCT struct dot11_meas_rep_basic { - uint8 channel; - uint8 start_time[8]; - uint16 duration; - uint8 map; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_meas_rep_basic dot11_meas_rep_basic_t; -#define DOT11_MEASURE_BASIC_REP_LEN 12 - -BWL_PRE_PACKED_STRUCT struct dot11_quiet { - uint8 id; - uint8 len; - uint8 count; - uint8 period; - uint16 duration; - uint16 offset; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_quiet dot11_quiet_t; - -BWL_PRE_PACKED_STRUCT struct chan_map_tuple { - uint8 channel; - uint8 map; -} BWL_POST_PACKED_STRUCT; -typedef struct chan_map_tuple chan_map_tuple_t; - -BWL_PRE_PACKED_STRUCT struct dot11_ibss_dfs { - uint8 id; - uint8 len; - uint8 eaddr[ETHER_ADDR_LEN]; - uint8 interval; - chan_map_tuple_t map[1]; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; - - -#define WME_OUI "\x00\x50\xf2" -#define WME_VER 1 -#define WME_TYPE 2 -#define WME_SUBTYPE_IE 0 -#define WME_SUBTYPE_PARAM_IE 1 -#define WME_SUBTYPE_TSPEC 2 - - -#define AC_BE 0 -#define AC_BK 1 -#define AC_VI 2 -#define AC_VO 3 -#define AC_COUNT 4 - -typedef uint8 ac_bitmap_t; - -#define AC_BITMAP_NONE 0x0 -#define AC_BITMAP_ALL 0xf -#define AC_BITMAP_TST(ab, ac) (((ab) & (1 << (ac))) != 0) -#define AC_BITMAP_SET(ab, ac) (((ab) |= (1 << (ac)))) -#define AC_BITMAP_RESET(ab, ac) (((ab) &= ~(1 << (ac)))) - - -BWL_PRE_PACKED_STRUCT struct wme_ie { - uint8 oui[3]; - uint8 type; - uint8 subtype; - uint8 version; - uint8 qosinfo; -} BWL_POST_PACKED_STRUCT; -typedef struct wme_ie wme_ie_t; -#define WME_IE_LEN 7 - -BWL_PRE_PACKED_STRUCT struct edcf_acparam { - uint8 ACI; - uint8 ECW; - uint16 TXOP; -} BWL_POST_PACKED_STRUCT; -typedef struct edcf_acparam edcf_acparam_t; - - -BWL_PRE_PACKED_STRUCT struct wme_param_ie { - uint8 oui[3]; - uint8 type; - uint8 subtype; - uint8 version; - uint8 qosinfo; - uint8 rsvd; - edcf_acparam_t acparam[AC_COUNT]; -} BWL_POST_PACKED_STRUCT; -typedef struct wme_param_ie wme_param_ie_t; -#define WME_PARAM_IE_LEN 24 - - -#define WME_QI_AP_APSD_MASK 0x80 -#define WME_QI_AP_APSD_SHIFT 7 -#define WME_QI_AP_COUNT_MASK 0x0f -#define WME_QI_AP_COUNT_SHIFT 0 - - -#define WME_QI_STA_MAXSPLEN_MASK 0x60 -#define WME_QI_STA_MAXSPLEN_SHIFT 5 -#define WME_QI_STA_APSD_ALL_MASK 0xf -#define WME_QI_STA_APSD_ALL_SHIFT 0 -#define WME_QI_STA_APSD_BE_MASK 0x8 -#define WME_QI_STA_APSD_BE_SHIFT 3 -#define WME_QI_STA_APSD_BK_MASK 0x4 -#define WME_QI_STA_APSD_BK_SHIFT 2 -#define WME_QI_STA_APSD_VI_MASK 0x2 -#define WME_QI_STA_APSD_VI_SHIFT 1 -#define WME_QI_STA_APSD_VO_MASK 0x1 -#define WME_QI_STA_APSD_VO_SHIFT 0 - - -#define EDCF_AIFSN_MIN 1 -#define EDCF_AIFSN_MAX 15 -#define EDCF_AIFSN_MASK 0x0f -#define EDCF_ACM_MASK 0x10 -#define EDCF_ACI_MASK 0x60 -#define EDCF_ACI_SHIFT 5 -#define EDCF_AIFSN_SHIFT 12 - - -#define EDCF_ECW_MIN 0 -#define EDCF_ECW_MAX 15 -#define EDCF_ECW2CW(exp) ((1 << (exp)) - 1) -#define EDCF_ECWMIN_MASK 0x0f -#define EDCF_ECWMAX_MASK 0xf0 -#define EDCF_ECWMAX_SHIFT 4 - - -#define EDCF_TXOP_MIN 0 -#define EDCF_TXOP_MAX 65535 -#define EDCF_TXOP2USEC(txop) ((txop) << 5) - - -#define NON_EDCF_AC_BE_ACI_STA 0x02 - - -#define EDCF_AC_BE_ACI_STA 0x03 -#define EDCF_AC_BE_ECW_STA 0xA4 -#define EDCF_AC_BE_TXOP_STA 0x0000 -#define EDCF_AC_BK_ACI_STA 0x27 -#define EDCF_AC_BK_ECW_STA 0xA4 -#define EDCF_AC_BK_TXOP_STA 0x0000 -#define EDCF_AC_VI_ACI_STA 0x42 -#define EDCF_AC_VI_ECW_STA 0x43 -#define EDCF_AC_VI_TXOP_STA 0x005e -#define EDCF_AC_VO_ACI_STA 0x62 -#define EDCF_AC_VO_ECW_STA 0x32 -#define EDCF_AC_VO_TXOP_STA 0x002f - - -#define EDCF_AC_BE_ACI_AP 0x03 -#define EDCF_AC_BE_ECW_AP 0x64 -#define EDCF_AC_BE_TXOP_AP 0x0000 -#define EDCF_AC_BK_ACI_AP 0x27 -#define EDCF_AC_BK_ECW_AP 0xA4 -#define EDCF_AC_BK_TXOP_AP 0x0000 -#define EDCF_AC_VI_ACI_AP 0x41 -#define EDCF_AC_VI_ECW_AP 0x43 -#define EDCF_AC_VI_TXOP_AP 0x005e -#define EDCF_AC_VO_ACI_AP 0x61 -#define EDCF_AC_VO_ECW_AP 0x32 -#define EDCF_AC_VO_TXOP_AP 0x002f - - -BWL_PRE_PACKED_STRUCT struct edca_param_ie { - uint8 qosinfo; - uint8 rsvd; - edcf_acparam_t acparam[AC_COUNT]; -} BWL_POST_PACKED_STRUCT; -typedef struct edca_param_ie edca_param_ie_t; -#define EDCA_PARAM_IE_LEN 18 - - -BWL_PRE_PACKED_STRUCT struct qos_cap_ie { - uint8 qosinfo; -} BWL_POST_PACKED_STRUCT; -typedef struct qos_cap_ie qos_cap_ie_t; - -BWL_PRE_PACKED_STRUCT struct dot11_qbss_load_ie { - uint8 id; - uint8 length; - uint16 station_count; - uint8 channel_utilization; - uint16 aac; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_qbss_load_ie dot11_qbss_load_ie_t; - - -#define FIXED_MSDU_SIZE 0x8000 -#define MSDU_SIZE_MASK 0x7fff - - - -#define INTEGER_SHIFT 13 -#define FRACTION_MASK 0x1FFF - - -BWL_PRE_PACKED_STRUCT struct dot11_management_notification { - uint8 category; - uint8 action; - uint8 token; - uint8 status; - uint8 data[1]; -} BWL_POST_PACKED_STRUCT; -#define DOT11_MGMT_NOTIFICATION_LEN 4 - - -#define WME_ADDTS_REQUEST 0 -#define WME_ADDTS_RESPONSE 1 -#define WME_DELTS_REQUEST 2 - - -#define WME_ADMISSION_ACCEPTED 0 -#define WME_INVALID_PARAMETERS 1 -#define WME_ADMISSION_REFUSED 3 - - -#define BCN_PRB_SSID(body) ((char*)(body) + DOT11_BCN_PRB_LEN) - - -#define DOT11_OPEN_SYSTEM 0 -#define DOT11_SHARED_KEY 1 - -#define DOT11_OPEN_SHARED 2 -#define DOT11_CHALLENGE_LEN 128 - - -#define FC_PVER_MASK 0x3 -#define FC_PVER_SHIFT 0 -#define FC_TYPE_MASK 0xC -#define FC_TYPE_SHIFT 2 -#define FC_SUBTYPE_MASK 0xF0 -#define FC_SUBTYPE_SHIFT 4 -#define FC_TODS 0x100 -#define FC_TODS_SHIFT 8 -#define FC_FROMDS 0x200 -#define FC_FROMDS_SHIFT 9 -#define FC_MOREFRAG 0x400 -#define FC_MOREFRAG_SHIFT 10 -#define FC_RETRY 0x800 -#define FC_RETRY_SHIFT 11 -#define FC_PM 0x1000 -#define FC_PM_SHIFT 12 -#define FC_MOREDATA 0x2000 -#define FC_MOREDATA_SHIFT 13 -#define FC_WEP 0x4000 -#define FC_WEP_SHIFT 14 -#define FC_ORDER 0x8000 -#define FC_ORDER_SHIFT 15 - - -#define SEQNUM_SHIFT 4 -#define SEQNUM_MAX 0x1000 -#define FRAGNUM_MASK 0xF - - - - -#define FC_TYPE_MNG 0 -#define FC_TYPE_CTL 1 -#define FC_TYPE_DATA 2 - - -#define FC_SUBTYPE_ASSOC_REQ 0 -#define FC_SUBTYPE_ASSOC_RESP 1 -#define FC_SUBTYPE_REASSOC_REQ 2 -#define FC_SUBTYPE_REASSOC_RESP 3 -#define FC_SUBTYPE_PROBE_REQ 4 -#define FC_SUBTYPE_PROBE_RESP 5 -#define FC_SUBTYPE_BEACON 8 -#define FC_SUBTYPE_ATIM 9 -#define FC_SUBTYPE_DISASSOC 10 -#define FC_SUBTYPE_AUTH 11 -#define FC_SUBTYPE_DEAUTH 12 -#define FC_SUBTYPE_ACTION 13 -#define FC_SUBTYPE_ACTION_NOACK 14 - - -#define FC_SUBTYPE_CTL_WRAPPER 7 -#define FC_SUBTYPE_BLOCKACK_REQ 8 -#define FC_SUBTYPE_BLOCKACK 9 -#define FC_SUBTYPE_PS_POLL 10 -#define FC_SUBTYPE_RTS 11 -#define FC_SUBTYPE_CTS 12 -#define FC_SUBTYPE_ACK 13 -#define FC_SUBTYPE_CF_END 14 -#define FC_SUBTYPE_CF_END_ACK 15 - - -#define FC_SUBTYPE_DATA 0 -#define FC_SUBTYPE_DATA_CF_ACK 1 -#define FC_SUBTYPE_DATA_CF_POLL 2 -#define FC_SUBTYPE_DATA_CF_ACK_POLL 3 -#define FC_SUBTYPE_NULL 4 -#define FC_SUBTYPE_CF_ACK 5 -#define FC_SUBTYPE_CF_POLL 6 -#define FC_SUBTYPE_CF_ACK_POLL 7 -#define FC_SUBTYPE_QOS_DATA 8 -#define FC_SUBTYPE_QOS_DATA_CF_ACK 9 -#define FC_SUBTYPE_QOS_DATA_CF_POLL 10 -#define FC_SUBTYPE_QOS_DATA_CF_ACK_POLL 11 -#define FC_SUBTYPE_QOS_NULL 12 -#define FC_SUBTYPE_QOS_CF_POLL 14 -#define FC_SUBTYPE_QOS_CF_ACK_POLL 15 - - -#define FC_SUBTYPE_ANY_QOS(s) (((s) & 8) != 0) -#define FC_SUBTYPE_ANY_NULL(s) (((s) & 4) != 0) -#define FC_SUBTYPE_ANY_CF_POLL(s) (((s) & 2) != 0) -#define FC_SUBTYPE_ANY_CF_ACK(s) (((s) & 1) != 0) - - -#define FC_KIND_MASK (FC_TYPE_MASK | FC_SUBTYPE_MASK) - -#define FC_KIND(t, s) (((t) << FC_TYPE_SHIFT) | ((s) << FC_SUBTYPE_SHIFT)) - -#define FC_SUBTYPE(fc) (((fc) & FC_SUBTYPE_MASK) >> FC_SUBTYPE_SHIFT) -#define FC_TYPE(fc) (((fc) & FC_TYPE_MASK) >> FC_TYPE_SHIFT) - -#define FC_ASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_REQ) -#define FC_ASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ASSOC_RESP) -#define FC_REASSOC_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_REQ) -#define FC_REASSOC_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_REASSOC_RESP) -#define FC_PROBE_REQ FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_REQ) -#define FC_PROBE_RESP FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_PROBE_RESP) -#define FC_BEACON FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_BEACON) -#define FC_DISASSOC FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DISASSOC) -#define FC_AUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_AUTH) -#define FC_DEAUTH FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_DEAUTH) -#define FC_ACTION FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION) -#define FC_ACTION_NOACK FC_KIND(FC_TYPE_MNG, FC_SUBTYPE_ACTION_NOACK) - -#define FC_CTL_WRAPPER FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTL_WRAPPER) -#define FC_BLOCKACK_REQ FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK_REQ) -#define FC_BLOCKACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_BLOCKACK) -#define FC_PS_POLL FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_PS_POLL) -#define FC_RTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_RTS) -#define FC_CTS FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CTS) -#define FC_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_ACK) -#define FC_CF_END FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END) -#define FC_CF_END_ACK FC_KIND(FC_TYPE_CTL, FC_SUBTYPE_CF_END_ACK) - -#define FC_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA) -#define FC_NULL_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_NULL) -#define FC_DATA_CF_ACK FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_DATA_CF_ACK) -#define FC_QOS_DATA FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_DATA) -#define FC_QOS_NULL FC_KIND(FC_TYPE_DATA, FC_SUBTYPE_QOS_NULL) - - - - -#define QOS_PRIO_SHIFT 0 -#define QOS_PRIO_MASK 0x0007 -#define QOS_PRIO(qos) (((qos) & QOS_PRIO_MASK) >> QOS_PRIO_SHIFT) - - -#define QOS_TID_SHIFT 0 -#define QOS_TID_MASK 0x000f -#define QOS_TID(qos) (((qos) & QOS_TID_MASK) >> QOS_TID_SHIFT) - - -#define QOS_EOSP_SHIFT 4 -#define QOS_EOSP_MASK 0x0010 -#define QOS_EOSP(qos) (((qos) & QOS_EOSP_MASK) >> QOS_EOSP_SHIFT) - - -#define QOS_ACK_NORMAL_ACK 0 -#define QOS_ACK_NO_ACK 1 -#define QOS_ACK_NO_EXP_ACK 2 -#define QOS_ACK_BLOCK_ACK 3 -#define QOS_ACK_SHIFT 5 -#define QOS_ACK_MASK 0x0060 -#define QOS_ACK(qos) (((qos) & QOS_ACK_MASK) >> QOS_ACK_SHIFT) - - -#define QOS_AMSDU_SHIFT 7 -#define QOS_AMSDU_MASK 0x0080 - - - - - - -#define DOT11_MNG_AUTH_ALGO_LEN 2 -#define DOT11_MNG_AUTH_SEQ_LEN 2 -#define DOT11_MNG_BEACON_INT_LEN 2 -#define DOT11_MNG_CAP_LEN 2 -#define DOT11_MNG_AP_ADDR_LEN 6 -#define DOT11_MNG_LISTEN_INT_LEN 2 -#define DOT11_MNG_REASON_LEN 2 -#define DOT11_MNG_AID_LEN 2 -#define DOT11_MNG_STATUS_LEN 2 -#define DOT11_MNG_TIMESTAMP_LEN 8 - - -#define DOT11_AID_MASK 0x3fff - - -#define DOT11_RC_RESERVED 0 -#define DOT11_RC_UNSPECIFIED 1 -#define DOT11_RC_AUTH_INVAL 2 -#define DOT11_RC_DEAUTH_LEAVING 3 -#define DOT11_RC_INACTIVITY 4 -#define DOT11_RC_BUSY 5 -#define DOT11_RC_INVAL_CLASS_2 6 -#define DOT11_RC_INVAL_CLASS_3 7 -#define DOT11_RC_DISASSOC_LEAVING 8 -#define DOT11_RC_NOT_AUTH 9 -#define DOT11_RC_BAD_PC 10 -#define DOT11_RC_BAD_CHANNELS 11 - - - -#define DOT11_RC_UNSPECIFIED_QOS 32 -#define DOT11_RC_INSUFFCIENT_BW 33 -#define DOT11_RC_EXCESSIVE_FRAMES 34 -#define DOT11_RC_TX_OUTSIDE_TXOP 35 -#define DOT11_RC_LEAVING_QBSS 36 -#define DOT11_RC_BAD_MECHANISM 37 -#define DOT11_RC_SETUP_NEEDED 38 -#define DOT11_RC_TIMEOUT 39 - -#define DOT11_RC_MAX 23 - - -#define DOT11_SC_SUCCESS 0 -#define DOT11_SC_FAILURE 1 -#define DOT11_SC_CAP_MISMATCH 10 -#define DOT11_SC_REASSOC_FAIL 11 -#define DOT11_SC_ASSOC_FAIL 12 -#define DOT11_SC_AUTH_MISMATCH 13 -#define DOT11_SC_AUTH_SEQ 14 -#define DOT11_SC_AUTH_CHALLENGE_FAIL 15 -#define DOT11_SC_AUTH_TIMEOUT 16 -#define DOT11_SC_ASSOC_BUSY_FAIL 17 -#define DOT11_SC_ASSOC_RATE_MISMATCH 18 -#define DOT11_SC_ASSOC_SHORT_REQUIRED 19 -#define DOT11_SC_ASSOC_PBCC_REQUIRED 20 -#define DOT11_SC_ASSOC_AGILITY_REQUIRED 21 -#define DOT11_SC_ASSOC_SPECTRUM_REQUIRED 22 -#define DOT11_SC_ASSOC_BAD_POWER_CAP 23 -#define DOT11_SC_ASSOC_BAD_SUP_CHANNELS 24 -#define DOT11_SC_ASSOC_SHORTSLOT_REQUIRED 25 -#define DOT11_SC_ASSOC_ERPBCC_REQUIRED 26 -#define DOT11_SC_ASSOC_DSSOFDM_REQUIRED 27 - -#define DOT11_SC_DECLINED 37 -#define DOT11_SC_INVALID_PARAMS 38 - - -#define DOT11_MNG_DS_PARAM_LEN 1 -#define DOT11_MNG_IBSS_PARAM_LEN 2 - - -#define DOT11_MNG_TIM_FIXED_LEN 3 -#define DOT11_MNG_TIM_DTIM_COUNT 0 -#define DOT11_MNG_TIM_DTIM_PERIOD 1 -#define DOT11_MNG_TIM_BITMAP_CTL 2 -#define DOT11_MNG_TIM_PVB 3 - - -#define TLV_TAG_OFF 0 -#define TLV_LEN_OFF 1 -#define TLV_HDR_LEN 2 -#define TLV_BODY_OFF 2 - - -#define DOT11_MNG_SSID_ID 0 -#define DOT11_MNG_RATES_ID 1 -#define DOT11_MNG_FH_PARMS_ID 2 -#define DOT11_MNG_DS_PARMS_ID 3 -#define DOT11_MNG_CF_PARMS_ID 4 -#define DOT11_MNG_TIM_ID 5 -#define DOT11_MNG_IBSS_PARMS_ID 6 -#define DOT11_MNG_COUNTRY_ID 7 -#define DOT11_MNG_HOPPING_PARMS_ID 8 -#define DOT11_MNG_HOPPING_TABLE_ID 9 -#define DOT11_MNG_REQUEST_ID 10 -#define DOT11_MNG_QBSS_LOAD_ID 11 -#define DOT11_MNG_EDCA_PARAM_ID 12 -#define DOT11_MNG_CHALLENGE_ID 16 -#define DOT11_MNG_PWR_CONSTRAINT_ID 32 -#define DOT11_MNG_PWR_CAP_ID 33 -#define DOT11_MNG_TPC_REQUEST_ID 34 -#define DOT11_MNG_TPC_REPORT_ID 35 -#define DOT11_MNG_SUPP_CHANNELS_ID 36 -#define DOT11_MNG_CHANNEL_SWITCH_ID 37 -#define DOT11_MNG_MEASURE_REQUEST_ID 38 -#define DOT11_MNG_MEASURE_REPORT_ID 39 -#define DOT11_MNG_QUIET_ID 40 -#define DOT11_MNG_IBSS_DFS_ID 41 -#define DOT11_MNG_ERP_ID 42 -#define DOT11_MNG_TS_DELAY_ID 43 -#define DOT11_MNG_HT_CAP 45 -#define DOT11_MNG_QOS_CAP_ID 46 -#define DOT11_MNG_NONERP_ID 47 -#define DOT11_MNG_RSN_ID 48 -#define DOT11_MNG_EXT_RATES_ID 50 -#define DOT11_MNG_REGCLASS_ID 59 -#define DOT11_MNG_EXT_CSA_ID 60 -#define DOT11_MNG_HT_ADD 61 -#define DOT11_MNG_EXT_CHANNEL_OFFSET 62 -#define DOT11_MNG_WAPI_ID 68 -#define DOT11_MNG_HT_BSS_COEXINFO_ID 72 -#define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 -#define DOT11_MNG_HT_OBSS_ID 74 -#define DOT11_MNG_EXT_CAP 127 -#define DOT11_MNG_WPA_ID 221 -#define DOT11_MNG_PROPR_ID 221 - - -#define DOT11_RATE_BASIC 0x80 -#define DOT11_RATE_MASK 0x7F - - -#define DOT11_MNG_ERP_LEN 1 -#define DOT11_MNG_NONERP_PRESENT 0x01 -#define DOT11_MNG_USE_PROTECTION 0x02 -#define DOT11_MNG_BARKER_PREAMBLE 0x04 - -#define DOT11_MGN_TS_DELAY_LEN 4 -#define TS_DELAY_FIELD_SIZE 4 - - -#define DOT11_CAP_ESS 0x0001 -#define DOT11_CAP_IBSS 0x0002 -#define DOT11_CAP_POLLABLE 0x0004 -#define DOT11_CAP_POLL_RQ 0x0008 -#define DOT11_CAP_PRIVACY 0x0010 -#define DOT11_CAP_SHORT 0x0020 -#define DOT11_CAP_PBCC 0x0040 -#define DOT11_CAP_AGILITY 0x0080 -#define DOT11_CAP_SPECTRUM 0x0100 -#define DOT11_CAP_SHORTSLOT 0x0400 -#define DOT11_CAP_CCK_OFDM 0x2000 - - -#define DOT11_OBSS_COEX_MNG_SUPPORT 0x01 - - -#define DOT11_ACTION_HDR_LEN 2 -#define DOT11_ACTION_CAT_ERR_MASK 0x80 -#define DOT11_ACTION_CAT_MASK 0x7F -#define DOT11_ACTION_CAT_SPECT_MNG 0 -#define DOT11_ACTION_CAT_BLOCKACK 3 -#define DOT11_ACTION_CAT_PUBLIC 4 -#define DOT11_ACTION_CAT_HT 7 -#define DOT11_ACTION_CAT_VS 127 -#define DOT11_ACTION_NOTIFICATION 0x11 - -#define DOT11_ACTION_ID_M_REQ 0 -#define DOT11_ACTION_ID_M_REP 1 -#define DOT11_ACTION_ID_TPC_REQ 2 -#define DOT11_ACTION_ID_TPC_REP 3 -#define DOT11_ACTION_ID_CHANNEL_SWITCH 4 -#define DOT11_ACTION_ID_EXT_CSA 5 - - -#define DOT11_ACTION_ID_HT_CH_WIDTH 0 -#define DOT11_ACTION_ID_HT_MIMO_PS 1 - - -#define DOT11_PUB_ACTION_BSS_COEX_MNG 0 -#define DOT11_PUB_ACTION_CHANNEL_SWITCH 4 - - -#define DOT11_BA_ACTION_ADDBA_REQ 0 -#define DOT11_BA_ACTION_ADDBA_RESP 1 -#define DOT11_BA_ACTION_DELBA 2 - - -#define DOT11_ADDBA_PARAM_AMSDU_SUP 0x0001 -#define DOT11_ADDBA_PARAM_POLICY_MASK 0x0002 -#define DOT11_ADDBA_PARAM_POLICY_SHIFT 1 -#define DOT11_ADDBA_PARAM_TID_MASK 0x003c -#define DOT11_ADDBA_PARAM_TID_SHIFT 2 -#define DOT11_ADDBA_PARAM_BSIZE_MASK 0xffc0 -#define DOT11_ADDBA_PARAM_BSIZE_SHIFT 6 - -#define DOT11_ADDBA_POLICY_DELAYED 0 -#define DOT11_ADDBA_POLICY_IMMEDIATE 1 - -BWL_PRE_PACKED_STRUCT struct dot11_addba_req { - uint8 category; - uint8 action; - uint8 token; - uint16 addba_param_set; - uint16 timeout; - uint16 start_seqnum; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_addba_req dot11_addba_req_t; -#define DOT11_ADDBA_REQ_LEN 9 - -BWL_PRE_PACKED_STRUCT struct dot11_addba_resp { - uint8 category; - uint8 action; - uint8 token; - uint16 status; - uint16 addba_param_set; - uint16 timeout; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_addba_resp dot11_addba_resp_t; -#define DOT11_ADDBA_RESP_LEN 9 - - -#define DOT11_DELBA_PARAM_INIT_MASK 0x0800 -#define DOT11_DELBA_PARAM_INIT_SHIFT 11 -#define DOT11_DELBA_PARAM_TID_MASK 0xf000 -#define DOT11_DELBA_PARAM_TID_SHIFT 12 - -BWL_PRE_PACKED_STRUCT struct dot11_delba { - uint8 category; - uint8 action; - uint16 delba_param_set; - uint16 reason; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_delba dot11_delba_t; -#define DOT11_DELBA_LEN 6 - - -#define DOT11_BSSTYPE_INFRASTRUCTURE 0 -#define DOT11_BSSTYPE_INDEPENDENT 1 -#define DOT11_BSSTYPE_ANY 2 -#define DOT11_SCANTYPE_ACTIVE 0 -#define DOT11_SCANTYPE_PASSIVE 1 - - -#define PREN_PREAMBLE 24 -#define PREN_MM_EXT 8 -#define PREN_PREAMBLE_EXT 4 - - -#define NPHY_RIFS_TIME 2 - - -#define APHY_SLOT_TIME 9 -#define APHY_SIFS_TIME 16 -#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) -#define APHY_PREAMBLE_TIME 16 -#define APHY_SIGNAL_TIME 4 -#define APHY_SYMBOL_TIME 4 -#define APHY_SERVICE_NBITS 16 -#define APHY_TAIL_NBITS 6 -#define APHY_CWMIN 15 - - -#define BPHY_SLOT_TIME 20 -#define BPHY_SIFS_TIME 10 -#define BPHY_DIFS_TIME 50 -#define BPHY_PLCP_TIME 192 -#define BPHY_PLCP_SHORT_TIME 96 -#define BPHY_CWMIN 31 - - -#define DOT11_OFDM_SIGNAL_EXTENSION 6 - -#define PHY_CWMAX 1023 - -#define DOT11_MAXNUMFRAGS 16 - - -typedef struct d11cnt { - uint32 txfrag; - uint32 txmulti; - uint32 txfail; - uint32 txretry; - uint32 txretrie; - uint32 rxdup; - uint32 txrts; - uint32 txnocts; - uint32 txnoack; - uint32 rxfrag; - uint32 rxmulti; - uint32 rxcrc; - uint32 txfrmsnt; - uint32 rxundec; -} d11cnt_t; - - -#define BRCM_PROP_OUI "\x00\x90\x4C" - - - - -BWL_PRE_PACKED_STRUCT struct brcm_prop_ie_s { - uint8 id; - uint8 len; - uint8 oui[3]; - uint8 type; - uint16 cap; -} BWL_POST_PACKED_STRUCT; -typedef struct brcm_prop_ie_s brcm_prop_ie_t; - -#define BRCM_PROP_IE_LEN 6 - -#define DPT_IE_TYPE 2 - - -#define BRCM_OUI "\x00\x10\x18" - - -BWL_PRE_PACKED_STRUCT struct brcm_ie { - uint8 id; - uint8 len; - uint8 oui[3]; - uint8 ver; - uint8 assoc; - uint8 flags; - uint8 flags1; - uint16 amsdu_mtu_pref; -} BWL_POST_PACKED_STRUCT; -typedef struct brcm_ie brcm_ie_t; -#define BRCM_IE_LEN 11 -#define BRCM_IE_VER 2 -#define BRCM_IE_LEGACY_AES_VER 1 - - -#ifdef WLAFTERBURNER -#define BRF_ABCAP 0x1 -#define BRF_ABRQRD 0x2 -#define BRF_ABCOUNTER_MASK 0xf0 -#define BRF_ABCOUNTER_SHIFT 4 -#endif -#define BRF_LZWDS 0x4 -#define BRF_BLOCKACK 0x8 - - -#define BRF1_AMSDU 0x1 -#define BRF1_WMEPS 0x4 -#define BRF1_PSOFIX 0x8 - -#ifdef WLAFTERBURNER -#define AB_WDS_TIMEOUT_MAX 15 -#define AB_WDS_TIMEOUT_MIN 1 -#endif - -#define AB_GUARDCOUNT 10 - -#define MCSSET_LEN 16 -#define MAX_MCS_NUM (128) - -BWL_PRE_PACKED_STRUCT struct ht_cap_ie { - uint16 cap; - uint8 params; - uint8 supp_mcs[MCSSET_LEN]; - uint16 ext_htcap; - uint32 txbf_cap; - uint8 as_cap; -} BWL_POST_PACKED_STRUCT; -typedef struct ht_cap_ie ht_cap_ie_t; - - - -BWL_PRE_PACKED_STRUCT struct ht_prop_cap_ie { - uint8 id; - uint8 len; - uint8 oui[3]; - uint8 type; - ht_cap_ie_t cap_ie; -} BWL_POST_PACKED_STRUCT; -typedef struct ht_prop_cap_ie ht_prop_cap_ie_t; -#define HT_PROP_IE_OVERHEAD 4 -#define HT_CAP_IE_LEN 26 -#define HT_CAP_IE_TYPE 51 - -#define HT_CAP_LDPC_CODING 0x0001 -#define HT_CAP_40MHZ 0x0002 -#define HT_CAP_MIMO_PS_MASK 0x000C -#define HT_CAP_MIMO_PS_SHIFT 0x0002 -#define HT_CAP_MIMO_PS_OFF 0x0003 -#define HT_CAP_MIMO_PS_RTS 0x0001 -#define HT_CAP_MIMO_PS_ON 0x0000 -#define HT_CAP_GF 0x0010 -#define HT_CAP_SHORT_GI_20 0x0020 -#define HT_CAP_SHORT_GI_40 0x0040 -#define HT_CAP_TX_STBC 0x0080 -#define HT_CAP_RX_STBC_MASK 0x0300 -#define HT_CAP_RX_STBC_SHIFT 8 -#define HT_CAP_DELAYED_BA 0x0400 -#define HT_CAP_MAX_AMSDU 0x0800 -#define HT_CAP_DSSS_CCK 0x1000 -#define HT_CAP_PSMP 0x2000 -#define HT_CAP_40MHZ_INTOLERANT 0x4000 -#define HT_CAP_LSIG_TXOP 0x8000 - -#define HT_CAP_RX_STBC_NO 0x0 -#define HT_CAP_RX_STBC_ONE_STREAM 0x1 -#define HT_CAP_RX_STBC_TWO_STREAM 0x2 -#define HT_CAP_RX_STBC_THREE_STREAM 0x3 - -#define HT_MAX_AMSDU 7935 -#define HT_MIN_AMSDU 3835 - -#define HT_PARAMS_RX_FACTOR_MASK 0x03 -#define HT_PARAMS_DENSITY_MASK 0x1C -#define HT_PARAMS_DENSITY_SHIFT 2 - - -#define AMPDU_MAX_MPDU_DENSITY 7 -#define AMPDU_RX_FACTOR_64K 3 -#define AMPDU_RX_FACTOR_BASE 8*1024 -#define AMPDU_DELIMITER_LEN 4 - -#define HT_CAP_EXT_PCO 0x0001 -#define HT_CAP_EXT_PCO_TTIME_MASK 0x0006 -#define HT_CAP_EXT_PCO_TTIME_SHIFT 1 -#define HT_CAP_EXT_MCS_FEEDBACK_MASK 0x0300 -#define HT_CAP_EXT_MCS_FEEDBACK_SHIFT 8 -#define HT_CAP_EXT_HTC 0x0400 -#define HT_CAP_EXT_RD_RESP 0x0800 - -BWL_PRE_PACKED_STRUCT struct ht_add_ie { - uint8 ctl_ch; - uint8 byte1; - uint16 opmode; - uint16 misc_bits; - uint8 basic_mcs[MCSSET_LEN]; -} BWL_POST_PACKED_STRUCT; -typedef struct ht_add_ie ht_add_ie_t; - - - -BWL_PRE_PACKED_STRUCT struct ht_prop_add_ie { - uint8 id; - uint8 len; - uint8 oui[3]; - uint8 type; - ht_add_ie_t add_ie; -} BWL_POST_PACKED_STRUCT; -typedef struct ht_prop_add_ie ht_prop_add_ie_t; - -#define HT_ADD_IE_LEN 22 -#define HT_ADD_IE_TYPE 52 - - -#define HT_BW_ANY 0x04 -#define HT_RIFS_PERMITTED 0x08 - - -#define HT_OPMODE_MASK 0x0003 -#define HT_OPMODE_SHIFT 0 -#define HT_OPMODE_PURE 0x0000 -#define HT_OPMODE_OPTIONAL 0x0001 -#define HT_OPMODE_HT20IN40 0x0002 -#define HT_OPMODE_MIXED 0x0003 -#define HT_OPMODE_NONGF 0x0004 -#define DOT11N_TXBURST 0x0008 -#define DOT11N_OBSS_NONHT 0x0010 - - -#define HT_BASIC_STBC_MCS 0x007f -#define HT_DUAL_STBC_PROT 0x0080 -#define HT_SECOND_BCN 0x0100 -#define HT_LSIG_TXOP 0x0200 -#define HT_PCO_ACTIVE 0x0400 -#define HT_PCO_PHASE 0x0800 -#define HT_DUALCTS_PROTECTION 0x0080 - - -#define DOT11N_2G_TXBURST_LIMIT 6160 -#define DOT11N_5G_TXBURST_LIMIT 3080 - - -#define GET_HT_OPMODE(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ - >> HT_OPMODE_SHIFT) -#define HT_MIXEDMODE_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ - == HT_OPMODE_MIXED) -#define HT_HT20_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ - == HT_OPMODE_HT20IN40) -#define HT_OPTIONAL_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_MASK) \ - == HT_OPMODE_OPTIONAL) -#define HT_USE_PROTECTION(add_ie) (HT_HT20_PRESENT((add_ie)) || \ - HT_MIXEDMODE_PRESENT((add_ie))) -#define HT_NONGF_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & HT_OPMODE_NONGF) \ - == HT_OPMODE_NONGF) -#define DOT11N_TXBURST_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_TXBURST) \ - == DOT11N_TXBURST) -#define DOT11N_OBSS_NONHT_PRESENT(add_ie) ((ltoh16_ua(&add_ie->opmode) & DOT11N_OBSS_NONHT) \ - == DOT11N_OBSS_NONHT) - -BWL_PRE_PACKED_STRUCT struct obss_params { - uint16 passive_dwell; - uint16 active_dwell; - uint16 bss_widthscan_interval; - uint16 passive_total; - uint16 active_total; - uint16 chanwidth_transition_dly; - uint16 activity_threshold; -} BWL_POST_PACKED_STRUCT; -typedef struct obss_params obss_params_t; - -BWL_PRE_PACKED_STRUCT struct dot11_obss_ie { - uint8 id; - uint8 len; - obss_params_t obss_params; -} BWL_POST_PACKED_STRUCT; -typedef struct dot11_obss_ie dot11_obss_ie_t; -#define DOT11_OBSS_SCAN_IE_LEN sizeof(obss_params_t) - - -BWL_PRE_PACKED_STRUCT struct vndr_ie { - uchar id; - uchar len; - uchar oui [3]; - uchar data [1]; -} BWL_POST_PACKED_STRUCT; -typedef struct vndr_ie vndr_ie_t; - -#define VNDR_IE_HDR_LEN 2 -#define VNDR_IE_MIN_LEN 3 -#define VNDR_IE_MAX_LEN 256 - - -#define WPA_VERSION 1 -#define WPA_OUI "\x00\x50\xF2" - -#define WPA2_VERSION 1 -#define WPA2_VERSION_LEN 2 -#define WPA2_OUI "\x00\x0F\xAC" - -#define WPA_OUI_LEN 3 - - -#define RSN_AKM_NONE 0 -#define RSN_AKM_UNSPECIFIED 1 -#define RSN_AKM_PSK 2 - - -#define DOT11_MAX_DEFAULT_KEYS 4 -#define DOT11_MAX_KEY_SIZE 32 -#define DOT11_MAX_IV_SIZE 16 -#define DOT11_EXT_IV_FLAG (1<<5) -#define DOT11_WPA_KEY_RSC_LEN 8 - -#define WEP1_KEY_SIZE 5 -#define WEP1_KEY_HEX_SIZE 10 -#define WEP128_KEY_SIZE 13 -#define WEP128_KEY_HEX_SIZE 26 -#define TKIP_MIC_SIZE 8 -#define TKIP_EOM_SIZE 7 -#define TKIP_EOM_FLAG 0x5a -#define TKIP_KEY_SIZE 32 -#define TKIP_MIC_AUTH_TX 16 -#define TKIP_MIC_AUTH_RX 24 -#define TKIP_MIC_SUP_RX TKIP_MIC_AUTH_TX -#define TKIP_MIC_SUP_TX TKIP_MIC_AUTH_RX -#define AES_KEY_SIZE 16 -#define AES_MIC_SIZE 8 - -#define SMS4_KEY_LEN 16 -#define SMS4_WPI_CBC_MAC_LEN 16 - - -#include - - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/802.11e.h b/drivers/net/wireless/bcm4329/include/proto/802.11e.h deleted file mode 100644 index 1dd6f45b1ed8..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/802.11e.h +++ /dev/null @@ -1,131 +0,0 @@ -/* - * 802.11e protocol header file - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: 802.11e.h,v 1.5.56.1 2008/11/20 00:51:18 Exp $ - */ - -#ifndef _802_11e_H_ -#define _802_11e_H_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - -/* This marks the start of a packed structure section. */ -#include - - -/* WME Traffic Specification (TSPEC) element */ -#define WME_TSPEC_HDR_LEN 2 /* WME TSPEC header length */ -#define WME_TSPEC_BODY_OFF 2 /* WME TSPEC body offset */ - -#define WME_CATEGORY_CODE_OFFSET 0 /* WME Category code offset */ -#define WME_ACTION_CODE_OFFSET 1 /* WME Action code offset */ -#define WME_TOKEN_CODE_OFFSET 2 /* WME Token code offset */ -#define WME_STATUS_CODE_OFFSET 3 /* WME Status code offset */ - -BWL_PRE_PACKED_STRUCT struct tsinfo { - uint8 octets[3]; -} BWL_POST_PACKED_STRUCT; - -typedef struct tsinfo tsinfo_t; - -/* 802.11e TSPEC IE */ -typedef BWL_PRE_PACKED_STRUCT struct tspec { - uint8 oui[DOT11_OUI_LEN]; /* WME_OUI */ - uint8 type; /* WME_TYPE */ - uint8 subtype; /* WME_SUBTYPE_TSPEC */ - uint8 version; /* WME_VERSION */ - tsinfo_t tsinfo; /* TS Info bit field */ - uint16 nom_msdu_size; /* (Nominal or fixed) MSDU Size (bytes) */ - uint16 max_msdu_size; /* Maximum MSDU Size (bytes) */ - uint32 min_srv_interval; /* Minimum Service Interval (us) */ - uint32 max_srv_interval; /* Maximum Service Interval (us) */ - uint32 inactivity_interval; /* Inactivity Interval (us) */ - uint32 suspension_interval; /* Suspension Interval (us) */ - uint32 srv_start_time; /* Service Start Time (us) */ - uint32 min_data_rate; /* Minimum Data Rate (bps) */ - uint32 mean_data_rate; /* Mean Data Rate (bps) */ - uint32 peak_data_rate; /* Peak Data Rate (bps) */ - uint32 max_burst_size; /* Maximum Burst Size (bytes) */ - uint32 delay_bound; /* Delay Bound (us) */ - uint32 min_phy_rate; /* Minimum PHY Rate (bps) */ - uint16 surplus_bw; /* Surplus Bandwidth Allowance (range 1.0-8.0) */ - uint16 medium_time; /* Medium Time (32 us/s periods) */ -} BWL_POST_PACKED_STRUCT tspec_t; - -#define WME_TSPEC_LEN (sizeof(tspec_t)) /* not including 2-bytes of header */ - -/* ts_info */ -/* 802.1D priority is duplicated - bits 13-11 AND bits 3-1 */ -#define TS_INFO_TID_SHIFT 1 /* TS info. TID shift */ -#define TS_INFO_TID_MASK (0xf << TS_INFO_TID_SHIFT) /* TS info. TID mask */ -#define TS_INFO_CONTENTION_SHIFT 7 /* TS info. contention shift */ -#define TS_INFO_CONTENTION_MASK (0x1 << TS_INFO_CONTENTION_SHIFT) /* TS info. contention mask */ -#define TS_INFO_DIRECTION_SHIFT 5 /* TS info. direction shift */ -#define TS_INFO_DIRECTION_MASK (0x3 << TS_INFO_DIRECTION_SHIFT) /* TS info. direction mask */ -#define TS_INFO_PSB_SHIFT 2 /* TS info. PSB bit Shift */ -#define TS_INFO_PSB_MASK (1 << TS_INFO_PSB_SHIFT) /* TS info. PSB mask */ -#define TS_INFO_UPLINK (0 << TS_INFO_DIRECTION_SHIFT) /* TS info. uplink */ -#define TS_INFO_DOWNLINK (1 << TS_INFO_DIRECTION_SHIFT) /* TS info. downlink */ -#define TS_INFO_BIDIRECTIONAL (3 << TS_INFO_DIRECTION_SHIFT) /* TS info. bidirectional */ -#define TS_INFO_USER_PRIO_SHIFT 3 /* TS info. user priority shift */ -/* TS info. user priority mask */ -#define TS_INFO_USER_PRIO_MASK (0x7 << TS_INFO_USER_PRIO_SHIFT) - -/* Macro to get/set bit(s) field in TSINFO */ -#define WLC_CAC_GET_TID(pt) ((((pt).octets[0]) & TS_INFO_TID_MASK) >> TS_INFO_TID_SHIFT) -#define WLC_CAC_GET_DIR(pt) ((((pt).octets[0]) & \ - TS_INFO_DIRECTION_MASK) >> TS_INFO_DIRECTION_SHIFT) -#define WLC_CAC_GET_PSB(pt) ((((pt).octets[1]) & TS_INFO_PSB_MASK) >> TS_INFO_PSB_SHIFT) -#define WLC_CAC_GET_USER_PRIO(pt) ((((pt).octets[1]) & \ - TS_INFO_USER_PRIO_MASK) >> TS_INFO_USER_PRIO_SHIFT) - -#define WLC_CAC_SET_TID(pt, id) ((((pt).octets[0]) & (~TS_INFO_TID_MASK)) | \ - ((id) << TS_INFO_TID_SHIFT)) -#define WLC_CAC_SET_USER_PRIO(pt, prio) ((((pt).octets[0]) & (~TS_INFO_USER_PRIO_MASK)) | \ - ((prio) << TS_INFO_USER_PRIO_SHIFT)) - -/* 802.11e QBSS Load IE */ -#define QBSS_LOAD_IE_LEN 5 /* QBSS Load IE length */ -#define QBSS_LOAD_AAC_OFF 3 /* AAC offset in IE */ - -#define CAC_ADDTS_RESP_TIMEOUT 300 /* default ADDTS response timeout in ms */ - -/* 802.11e ADDTS status code */ -#define DOT11E_STATUS_ADMISSION_ACCEPTED 0 /* TSPEC Admission accepted status */ -#define DOT11E_STATUS_ADDTS_INVALID_PARAM 1 /* TSPEC invalid parameter status */ -#define DOT11E_STATUS_ADDTS_REFUSED_NSBW 3 /* ADDTS refused (non-sufficient BW) */ -#define DOT11E_STATUS_ADDTS_REFUSED_AWHILE 47 /* ADDTS refused but could retry later */ - -/* 802.11e DELTS status code */ -#define DOT11E_STATUS_QSTA_LEAVE_QBSS 36 /* STA leave QBSS */ -#define DOT11E_STATUS_END_TS 37 /* END TS */ -#define DOT11E_STATUS_UNKNOWN_TS 38 /* UNKNOWN TS */ -#define DOT11E_STATUS_QSTA_REQ_TIMEOUT 39 /* STA ADDTS request timeout */ - - -/* This marks the end of a packed structure section. */ -#include - -#endif /* _802_11e_CAC_H_ */ diff --git a/drivers/net/wireless/bcm4329/include/proto/802.1d.h b/drivers/net/wireless/bcm4329/include/proto/802.1d.h deleted file mode 100644 index 45c728bc2976..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/802.1d.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * Fundamental types and constants relating to 802.1D - * - * $Id: 802.1d.h,v 9.3 2007/04/10 21:33:06 Exp $ - */ - - -#ifndef _802_1_D_ -#define _802_1_D_ - - -#define PRIO_8021D_NONE 2 -#define PRIO_8021D_BK 1 -#define PRIO_8021D_BE 0 -#define PRIO_8021D_EE 3 -#define PRIO_8021D_CL 4 -#define PRIO_8021D_VI 5 -#define PRIO_8021D_VO 6 -#define PRIO_8021D_NC 7 -#define MAXPRIO 7 -#define NUMPRIO (MAXPRIO + 1) - -#define ALLPRIO -1 - - -#define PRIO2PREC(prio) \ - (((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? ((prio^2)) : (prio)) - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/bcmeth.h b/drivers/net/wireless/bcm4329/include/proto/bcmeth.h deleted file mode 100644 index fdb5a2a5648f..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/bcmeth.h +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Broadcom Ethernettype protocol definitions - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: bcmeth.h,v 9.9.46.1 2008/11/20 00:51:20 Exp $ - */ - - - - -#ifndef _BCMETH_H_ -#define _BCMETH_H_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - - -#include - - - - - - - -#define BCMILCP_SUBTYPE_RATE 1 -#define BCMILCP_SUBTYPE_LINK 2 -#define BCMILCP_SUBTYPE_CSA 3 -#define BCMILCP_SUBTYPE_LARQ 4 -#define BCMILCP_SUBTYPE_VENDOR 5 -#define BCMILCP_SUBTYPE_FLH 17 - -#define BCMILCP_SUBTYPE_VENDOR_LONG 32769 -#define BCMILCP_SUBTYPE_CERT 32770 -#define BCMILCP_SUBTYPE_SES 32771 - - -#define BCMILCP_BCM_SUBTYPE_RESERVED 0 -#define BCMILCP_BCM_SUBTYPE_EVENT 1 -#define BCMILCP_BCM_SUBTYPE_SES 2 - - -#define BCMILCP_BCM_SUBTYPE_DPT 4 - -#define BCMILCP_BCM_SUBTYPEHDR_MINLENGTH 8 -#define BCMILCP_BCM_SUBTYPEHDR_VERSION 0 - - -typedef BWL_PRE_PACKED_STRUCT struct bcmeth_hdr -{ - uint16 subtype; - uint16 length; - uint8 version; - uint8 oui[3]; - - uint16 usr_subtype; -} BWL_POST_PACKED_STRUCT bcmeth_hdr_t; - - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/bcmevent.h b/drivers/net/wireless/bcm4329/include/proto/bcmevent.h deleted file mode 100644 index 46c04d379227..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/bcmevent.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * Broadcom Event protocol definitions - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * - * Dependencies: proto/bcmeth.h - * - * $Id: bcmevent.h,v 9.34.4.1.20.16 2009/09/25 23:52:38 Exp $ - * - */ - - - - -#ifndef _BCMEVENT_H_ -#define _BCMEVENT_H_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - - -#include - -#define BCM_EVENT_MSG_VERSION 1 -#define BCM_MSG_IFNAME_MAX 16 - - -#define WLC_EVENT_MSG_LINK 0x01 -#define WLC_EVENT_MSG_FLUSHTXQ 0x02 -#define WLC_EVENT_MSG_GROUP 0x04 - - -typedef BWL_PRE_PACKED_STRUCT struct -{ - uint16 version; - uint16 flags; - uint32 event_type; - uint32 status; - uint32 reason; - uint32 auth_type; - uint32 datalen; - struct ether_addr addr; - char ifname[BCM_MSG_IFNAME_MAX]; -} BWL_POST_PACKED_STRUCT wl_event_msg_t; - - -typedef BWL_PRE_PACKED_STRUCT struct bcm_event { - struct ether_header eth; - bcmeth_hdr_t bcm_hdr; - wl_event_msg_t event; - -} BWL_POST_PACKED_STRUCT bcm_event_t; - -#define BCM_MSG_LEN (sizeof(bcm_event_t) - sizeof(bcmeth_hdr_t) - sizeof(struct ether_header)) - - -#define WLC_E_SET_SSID 0 -#define WLC_E_JOIN 1 -#define WLC_E_START 2 -#define WLC_E_AUTH 3 -#define WLC_E_AUTH_IND 4 -#define WLC_E_DEAUTH 5 -#define WLC_E_DEAUTH_IND 6 -#define WLC_E_ASSOC 7 -#define WLC_E_ASSOC_IND 8 -#define WLC_E_REASSOC 9 -#define WLC_E_REASSOC_IND 10 -#define WLC_E_DISASSOC 11 -#define WLC_E_DISASSOC_IND 12 -#define WLC_E_QUIET_START 13 -#define WLC_E_QUIET_END 14 -#define WLC_E_BEACON_RX 15 -#define WLC_E_LINK 16 -#define WLC_E_MIC_ERROR 17 -#define WLC_E_NDIS_LINK 18 -#define WLC_E_ROAM 19 -#define WLC_E_TXFAIL 20 -#define WLC_E_PMKID_CACHE 21 -#define WLC_E_RETROGRADE_TSF 22 -#define WLC_E_PRUNE 23 -#define WLC_E_AUTOAUTH 24 -#define WLC_E_EAPOL_MSG 25 -#define WLC_E_SCAN_COMPLETE 26 -#define WLC_E_ADDTS_IND 27 -#define WLC_E_DELTS_IND 28 -#define WLC_E_BCNSENT_IND 29 -#define WLC_E_BCNRX_MSG 30 -#define WLC_E_BCNLOST_MSG 31 -#define WLC_E_ROAM_PREP 32 -#define WLC_E_PFN_NET_FOUND 33 -#define WLC_E_PFN_NET_LOST 34 -#define WLC_E_RESET_COMPLETE 35 -#define WLC_E_JOIN_START 36 -#define WLC_E_ROAM_START 37 -#define WLC_E_ASSOC_START 38 -#define WLC_E_IBSS_ASSOC 39 -#define WLC_E_RADIO 40 -#define WLC_E_PSM_WATCHDOG 41 -#define WLC_E_PROBREQ_MSG 44 -#define WLC_E_SCAN_CONFIRM_IND 45 -#define WLC_E_PSK_SUP 46 -#define WLC_E_COUNTRY_CODE_CHANGED 47 -#define WLC_E_EXCEEDED_MEDIUM_TIME 48 -#define WLC_E_ICV_ERROR 49 -#define WLC_E_UNICAST_DECODE_ERROR 50 -#define WLC_E_MULTICAST_DECODE_ERROR 51 -#define WLC_E_TRACE 52 -#define WLC_E_IF 54 -#define WLC_E_RSSI 56 -#define WLC_E_PFN_SCAN_COMPLETE 57 -#define WLC_E_ACTION_FRAME 58 -#define WLC_E_ACTION_FRAME_COMPLETE 59 - -#define WLC_E_ESCAN_RESULT 69 -#define WLC_E_WAKE_EVENT 70 -#define WLC_E_LAST 71 - - - - -#define WLC_E_STATUS_SUCCESS 0 -#define WLC_E_STATUS_FAIL 1 -#define WLC_E_STATUS_TIMEOUT 2 -#define WLC_E_STATUS_NO_NETWORKS 3 -#define WLC_E_STATUS_ABORT 4 -#define WLC_E_STATUS_NO_ACK 5 -#define WLC_E_STATUS_UNSOLICITED 6 -#define WLC_E_STATUS_ATTEMPT 7 -#define WLC_E_STATUS_PARTIAL 8 -#define WLC_E_STATUS_NEWSCAN 9 -#define WLC_E_STATUS_NEWASSOC 10 -#define WLC_E_STATUS_11HQUIET 11 -#define WLC_E_STATUS_SUPPRESS 12 -#define WLC_E_STATUS_NOCHANS 13 -#define WLC_E_STATUS_CCXFASTRM 14 -#define WLC_E_STATUS_CS_ABORT 15 - - -#define WLC_E_REASON_INITIAL_ASSOC 0 -#define WLC_E_REASON_LOW_RSSI 1 -#define WLC_E_REASON_DEAUTH 2 -#define WLC_E_REASON_DISASSOC 3 -#define WLC_E_REASON_BCNS_LOST 4 -#define WLC_E_REASON_FAST_ROAM_FAILED 5 -#define WLC_E_REASON_DIRECTED_ROAM 6 -#define WLC_E_REASON_TSPEC_REJECTED 7 -#define WLC_E_REASON_BETTER_AP 8 - - -#define WLC_E_PRUNE_ENCR_MISMATCH 1 -#define WLC_E_PRUNE_BCAST_BSSID 2 -#define WLC_E_PRUNE_MAC_DENY 3 -#define WLC_E_PRUNE_MAC_NA 4 -#define WLC_E_PRUNE_REG_PASSV 5 -#define WLC_E_PRUNE_SPCT_MGMT 6 -#define WLC_E_PRUNE_RADAR 7 -#define WLC_E_RSN_MISMATCH 8 -#define WLC_E_PRUNE_NO_COMMON_RATES 9 -#define WLC_E_PRUNE_BASIC_RATES 10 -#define WLC_E_PRUNE_CIPHER_NA 12 -#define WLC_E_PRUNE_KNOWN_STA 13 -#define WLC_E_PRUNE_WDS_PEER 15 -#define WLC_E_PRUNE_QBSS_LOAD 16 -#define WLC_E_PRUNE_HOME_AP 17 - - -#define WLC_E_SUP_OTHER 0 -#define WLC_E_SUP_DECRYPT_KEY_DATA 1 -#define WLC_E_SUP_BAD_UCAST_WEP128 2 -#define WLC_E_SUP_BAD_UCAST_WEP40 3 -#define WLC_E_SUP_UNSUP_KEY_LEN 4 -#define WLC_E_SUP_PW_KEY_CIPHER 5 -#define WLC_E_SUP_MSG3_TOO_MANY_IE 6 -#define WLC_E_SUP_MSG3_IE_MISMATCH 7 -#define WLC_E_SUP_NO_INSTALL_FLAG 8 -#define WLC_E_SUP_MSG3_NO_GTK 9 -#define WLC_E_SUP_GRP_KEY_CIPHER 10 -#define WLC_E_SUP_GRP_MSG1_NO_GTK 11 -#define WLC_E_SUP_GTK_DECRYPT_FAIL 12 -#define WLC_E_SUP_SEND_FAIL 13 -#define WLC_E_SUP_DEAUTH 14 -#define WLC_E_SUP_WPA_PSK_TMO 15 - - -#define WLC_E_IF_ADD 1 -#define WLC_E_IF_DEL 2 - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/bcmip.h b/drivers/net/wireless/bcm4329/include/proto/bcmip.h deleted file mode 100644 index 9d2fd6fba484..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/bcmip.h +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * Fundamental constants relating to IP Protocol - * - * $Id: bcmip.h,v 9.16.186.4 2009/01/27 04:25:25 Exp $ - */ - - -#ifndef _bcmip_h_ -#define _bcmip_h_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - - -#include - - - -#define IP_VER_OFFSET 0x0 -#define IP_VER_MASK 0xf0 -#define IP_VER_SHIFT 4 -#define IP_VER_4 4 -#define IP_VER_6 6 - -#define IP_VER(ip_body) \ - ((((uint8 *)(ip_body))[IP_VER_OFFSET] & IP_VER_MASK) >> IP_VER_SHIFT) - -#define IP_PROT_ICMP 0x1 -#define IP_PROT_TCP 0x6 -#define IP_PROT_UDP 0x11 - - -#define IPV4_VER_HL_OFFSET 0 -#define IPV4_TOS_OFFSET 1 -#define IPV4_PKTLEN_OFFSET 2 -#define IPV4_PKTFLAG_OFFSET 6 -#define IPV4_PROT_OFFSET 9 -#define IPV4_CHKSUM_OFFSET 10 -#define IPV4_SRC_IP_OFFSET 12 -#define IPV4_DEST_IP_OFFSET 16 -#define IPV4_OPTIONS_OFFSET 20 - - -#define IPV4_VER_MASK 0xf0 -#define IPV4_VER_SHIFT 4 - -#define IPV4_HLEN_MASK 0x0f -#define IPV4_HLEN(ipv4_body) (4 * (((uint8 *)(ipv4_body))[IPV4_VER_HL_OFFSET] & IPV4_HLEN_MASK)) - -#define IPV4_ADDR_LEN 4 - -#define IPV4_ADDR_NULL(a) ((((uint8 *)(a))[0] | ((uint8 *)(a))[1] | \ - ((uint8 *)(a))[2] | ((uint8 *)(a))[3]) == 0) - -#define IPV4_ADDR_BCAST(a) ((((uint8 *)(a))[0] & ((uint8 *)(a))[1] & \ - ((uint8 *)(a))[2] & ((uint8 *)(a))[3]) == 0xff) - -#define IPV4_TOS_DSCP_MASK 0xfc -#define IPV4_TOS_DSCP_SHIFT 2 - -#define IPV4_TOS(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_TOS_OFFSET]) - -#define IPV4_TOS_PREC_MASK 0xe0 -#define IPV4_TOS_PREC_SHIFT 5 - -#define IPV4_TOS_LOWDELAY 0x10 -#define IPV4_TOS_THROUGHPUT 0x8 -#define IPV4_TOS_RELIABILITY 0x4 - -#define IPV4_PROT(ipv4_body) (((uint8 *)(ipv4_body))[IPV4_PROT_OFFSET]) - -#define IPV4_FRAG_RESV 0x8000 -#define IPV4_FRAG_DONT 0x4000 -#define IPV4_FRAG_MORE 0x2000 -#define IPV4_FRAG_OFFSET_MASK 0x1fff - -#define IPV4_ADDR_STR_LEN 16 - - -BWL_PRE_PACKED_STRUCT struct ipv4_addr { - uint8 addr[IPV4_ADDR_LEN]; -} BWL_POST_PACKED_STRUCT; - -BWL_PRE_PACKED_STRUCT struct ipv4_hdr { - uint8 version_ihl; - uint8 tos; - uint16 tot_len; - uint16 id; - uint16 frag; - uint8 ttl; - uint8 prot; - uint16 hdr_chksum; - uint8 src_ip[IPV4_ADDR_LEN]; - uint8 dst_ip[IPV4_ADDR_LEN]; -} BWL_POST_PACKED_STRUCT; - - -#define IPV6_PAYLOAD_LEN_OFFSET 4 -#define IPV6_NEXT_HDR_OFFSET 6 -#define IPV6_HOP_LIMIT_OFFSET 7 -#define IPV6_SRC_IP_OFFSET 8 -#define IPV6_DEST_IP_OFFSET 24 - - -#define IPV6_TRAFFIC_CLASS(ipv6_body) \ - (((((uint8 *)(ipv6_body))[0] & 0x0f) << 4) | \ - ((((uint8 *)(ipv6_body))[1] & 0xf0) >> 4)) - -#define IPV6_FLOW_LABEL(ipv6_body) \ - (((((uint8 *)(ipv6_body))[1] & 0x0f) << 16) | \ - (((uint8 *)(ipv6_body))[2] << 8) | \ - (((uint8 *)(ipv6_body))[3])) - -#define IPV6_PAYLOAD_LEN(ipv6_body) \ - ((((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 0] << 8) | \ - ((uint8 *)(ipv6_body))[IPV6_PAYLOAD_LEN_OFFSET + 1]) - -#define IPV6_NEXT_HDR(ipv6_body) \ - (((uint8 *)(ipv6_body))[IPV6_NEXT_HDR_OFFSET]) - -#define IPV6_PROT(ipv6_body) IPV6_NEXT_HDR(ipv6_body) - -#define IPV6_ADDR_LEN 16 - - -#ifndef IP_TOS -#define IP_TOS(ip_body) \ - (IP_VER(ip_body) == IP_VER_4 ? IPV4_TOS(ip_body) : \ - IP_VER(ip_body) == IP_VER_6 ? IPV6_TRAFFIC_CLASS(ip_body) : 0) -#endif - - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/eapol.h b/drivers/net/wireless/bcm4329/include/proto/eapol.h deleted file mode 100644 index 95e76ff18c6b..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/eapol.h +++ /dev/null @@ -1,172 +0,0 @@ -/* - * 802.1x EAPOL definitions - * - * See - * IEEE Std 802.1X-2001 - * IEEE 802.1X RADIUS Usage Guidelines - * - * Copyright (C) 2002 Broadcom Corporation - * - * $Id: eapol.h,v 9.18.260.1.2.1.6.6 2009/04/08 05:00:08 Exp $ - */ - -#ifndef _eapol_h_ -#define _eapol_h_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - -/* This marks the start of a packed structure section. */ -#include - -#define AKW_BLOCK_LEN 8 /* The only def we need here */ - -/* EAPOL for 802.3/Ethernet */ -typedef struct { - struct ether_header eth; /* 802.3/Ethernet header */ - unsigned char version; /* EAPOL protocol version */ - unsigned char type; /* EAPOL type */ - unsigned short length; /* Length of body */ - unsigned char body[1]; /* Body (optional) */ -} eapol_header_t; - -#define EAPOL_HEADER_LEN 18 - -/* EAPOL version */ -#define WPA2_EAPOL_VERSION 2 -#define WPA_EAPOL_VERSION 1 -#define LEAP_EAPOL_VERSION 1 -#define SES_EAPOL_VERSION 1 - -/* EAPOL types */ -#define EAP_PACKET 0 -#define EAPOL_START 1 -#define EAPOL_LOGOFF 2 -#define EAPOL_KEY 3 -#define EAPOL_ASF 4 - -/* EAPOL-Key types */ -#define EAPOL_RC4_KEY 1 -#define EAPOL_WPA2_KEY 2 /* 802.11i/WPA2 */ -#define EAPOL_WPA_KEY 254 /* WPA */ - -/* RC4 EAPOL-Key header field sizes */ -#define EAPOL_KEY_REPLAY_LEN 8 -#define EAPOL_KEY_IV_LEN 16 -#define EAPOL_KEY_SIG_LEN 16 - -/* RC4 EAPOL-Key */ -typedef BWL_PRE_PACKED_STRUCT struct { - unsigned char type; /* Key Descriptor Type */ - unsigned short length; /* Key Length (unaligned) */ - unsigned char replay[EAPOL_KEY_REPLAY_LEN]; /* Replay Counter */ - unsigned char iv[EAPOL_KEY_IV_LEN]; /* Key IV */ - unsigned char index; /* Key Flags & Index */ - unsigned char signature[EAPOL_KEY_SIG_LEN]; /* Key Signature */ - unsigned char key[1]; /* Key (optional) */ -} BWL_POST_PACKED_STRUCT eapol_key_header_t; - -#define EAPOL_KEY_HEADER_LEN 44 - -/* RC4 EAPOL-Key flags */ -#define EAPOL_KEY_FLAGS_MASK 0x80 -#define EAPOL_KEY_BROADCAST 0 -#define EAPOL_KEY_UNICAST 0x80 - -/* RC4 EAPOL-Key index */ -#define EAPOL_KEY_INDEX_MASK 0x7f - -/* WPA/802.11i/WPA2 EAPOL-Key header field sizes */ -#define EAPOL_WPA_KEY_REPLAY_LEN 8 -#define EAPOL_WPA_KEY_NONCE_LEN 32 -#define EAPOL_WPA_KEY_IV_LEN 16 -#define EAPOL_WPA_KEY_ID_LEN 8 -#define EAPOL_WPA_KEY_RSC_LEN 8 -#define EAPOL_WPA_KEY_MIC_LEN 16 -#define EAPOL_WPA_KEY_DATA_LEN (EAPOL_WPA_MAX_KEY_SIZE + AKW_BLOCK_LEN) -#define EAPOL_WPA_MAX_KEY_SIZE 32 - -/* WPA EAPOL-Key */ -typedef BWL_PRE_PACKED_STRUCT struct { - unsigned char type; /* Key Descriptor Type */ - unsigned short key_info; /* Key Information (unaligned) */ - unsigned short key_len; /* Key Length (unaligned) */ - unsigned char replay[EAPOL_WPA_KEY_REPLAY_LEN]; /* Replay Counter */ - unsigned char nonce[EAPOL_WPA_KEY_NONCE_LEN]; /* Nonce */ - unsigned char iv[EAPOL_WPA_KEY_IV_LEN]; /* Key IV */ - unsigned char rsc[EAPOL_WPA_KEY_RSC_LEN]; /* Key RSC */ - unsigned char id[EAPOL_WPA_KEY_ID_LEN]; /* WPA:Key ID, 802.11i/WPA2: Reserved */ - unsigned char mic[EAPOL_WPA_KEY_MIC_LEN]; /* Key MIC */ - unsigned short data_len; /* Key Data Length */ - unsigned char data[EAPOL_WPA_KEY_DATA_LEN]; /* Key data */ -} BWL_POST_PACKED_STRUCT eapol_wpa_key_header_t; - -#define EAPOL_WPA_KEY_LEN 95 - -/* WPA/802.11i/WPA2 KEY KEY_INFO bits */ -#define WPA_KEY_DESC_V1 0x01 -#define WPA_KEY_DESC_V2 0x02 -#define WPA_KEY_PAIRWISE 0x08 -#define WPA_KEY_INSTALL 0x40 -#define WPA_KEY_ACK 0x80 -#define WPA_KEY_MIC 0x100 -#define WPA_KEY_SECURE 0x200 -#define WPA_KEY_ERROR 0x400 -#define WPA_KEY_REQ 0x800 - -/* WPA-only KEY KEY_INFO bits */ -#define WPA_KEY_INDEX_0 0x00 -#define WPA_KEY_INDEX_1 0x10 -#define WPA_KEY_INDEX_2 0x20 -#define WPA_KEY_INDEX_3 0x30 -#define WPA_KEY_INDEX_MASK 0x30 -#define WPA_KEY_INDEX_SHIFT 0x04 - -/* 802.11i/WPA2-only KEY KEY_INFO bits */ -#define WPA_KEY_ENCRYPTED_DATA 0x1000 - -/* Key Data encapsulation */ -typedef BWL_PRE_PACKED_STRUCT struct { - uint8 type; - uint8 length; - uint8 oui[3]; - uint8 subtype; - uint8 data[1]; -} BWL_POST_PACKED_STRUCT eapol_wpa2_encap_data_t; - -#define EAPOL_WPA2_ENCAP_DATA_HDR_LEN 6 - -#define WPA2_KEY_DATA_SUBTYPE_GTK 1 -#define WPA2_KEY_DATA_SUBTYPE_STAKEY 2 -#define WPA2_KEY_DATA_SUBTYPE_MAC 3 -#define WPA2_KEY_DATA_SUBTYPE_PMKID 4 - -/* GTK encapsulation */ -typedef BWL_PRE_PACKED_STRUCT struct { - uint8 flags; - uint8 reserved; - uint8 gtk[EAPOL_WPA_MAX_KEY_SIZE]; -} BWL_POST_PACKED_STRUCT eapol_wpa2_key_gtk_encap_t; - -#define EAPOL_WPA2_KEY_GTK_ENCAP_HDR_LEN 2 - -#define WPA2_GTK_INDEX_MASK 0x03 -#define WPA2_GTK_INDEX_SHIFT 0x00 - -#define WPA2_GTK_TRANSMIT 0x04 - -/* STAKey encapsulation */ -typedef BWL_PRE_PACKED_STRUCT struct { - uint8 reserved[2]; - uint8 mac[ETHER_ADDR_LEN]; - uint8 stakey[EAPOL_WPA_MAX_KEY_SIZE]; -} BWL_POST_PACKED_STRUCT eapol_wpa2_key_stakey_encap_t; - -#define WPA2_KEY_DATA_PAD 0xdd - - -/* This marks the end of a packed structure section. */ -#include - -#endif /* _eapol_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/proto/ethernet.h b/drivers/net/wireless/bcm4329/include/proto/ethernet.h deleted file mode 100644 index 9ad2ea0c70fd..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/ethernet.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * From FreeBSD 2.2.7: Fundamental constants relating to ethernet. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: ethernet.h,v 9.45.56.5 2010/02/22 22:04:36 Exp $ - */ - - -#ifndef _NET_ETHERNET_H_ -#define _NET_ETHERNET_H_ - -#ifndef _TYPEDEFS_H_ -#include "typedefs.h" -#endif - - -#include - - - -#define ETHER_ADDR_LEN 6 - - -#define ETHER_TYPE_LEN 2 - - -#define ETHER_CRC_LEN 4 - - -#define ETHER_HDR_LEN (ETHER_ADDR_LEN * 2 + ETHER_TYPE_LEN) - - -#define ETHER_MIN_LEN 64 - - -#define ETHER_MIN_DATA 46 - - -#define ETHER_MAX_LEN 1518 - - -#define ETHER_MAX_DATA 1500 - - -#define ETHER_TYPE_MIN 0x0600 -#define ETHER_TYPE_IP 0x0800 -#define ETHER_TYPE_ARP 0x0806 -#define ETHER_TYPE_8021Q 0x8100 -#define ETHER_TYPE_BRCM 0x886c -#define ETHER_TYPE_802_1X 0x888e -#define ETHER_TYPE_WAI 0x88b4 -#ifdef BCMWPA2 -#define ETHER_TYPE_802_1X_PREAUTH 0x88c7 -#endif - - -#define ETHER_BRCM_SUBTYPE_LEN 4 -#define ETHER_BRCM_CRAM 1 - - -#define ETHER_DEST_OFFSET (0 * ETHER_ADDR_LEN) -#define ETHER_SRC_OFFSET (1 * ETHER_ADDR_LEN) -#define ETHER_TYPE_OFFSET (2 * ETHER_ADDR_LEN) - - -#define ETHER_IS_VALID_LEN(foo) \ - ((foo) >= ETHER_MIN_LEN && (foo) <= ETHER_MAX_LEN) - - -#ifndef __INCif_etherh - -BWL_PRE_PACKED_STRUCT struct ether_header { - uint8 ether_dhost[ETHER_ADDR_LEN]; - uint8 ether_shost[ETHER_ADDR_LEN]; - uint16 ether_type; -} BWL_POST_PACKED_STRUCT; - - -BWL_PRE_PACKED_STRUCT struct ether_addr { - uint8 octet[ETHER_ADDR_LEN]; -} BWL_POST_PACKED_STRUCT; -#endif - - -#define ETHER_SET_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] | 2)) -#define ETHER_IS_LOCALADDR(ea) (((uint8 *)(ea))[0] & 2) -#define ETHER_CLR_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & 0xd)) -#define ETHER_TOGGLE_LOCALADDR(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] ^ 2)) - - -#define ETHER_SET_UNICAST(ea) (((uint8 *)(ea))[0] = (((uint8 *)(ea))[0] & ~1)) - - -#define ETHER_ISMULTI(ea) (((const uint8 *)(ea))[0] & 1) - - - -#define ether_cmp(a, b) (!(((short*)a)[0] == ((short*)b)[0]) | \ - !(((short*)a)[1] == ((short*)b)[1]) | \ - !(((short*)a)[2] == ((short*)b)[2])) - - -#define ether_copy(s, d) { \ - ((short*)d)[0] = ((short*)s)[0]; \ - ((short*)d)[1] = ((short*)s)[1]; \ - ((short*)d)[2] = ((short*)s)[2]; } - - -static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; -static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; - -#define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ - ((uint8 *)(ea))[1] & \ - ((uint8 *)(ea))[2] & \ - ((uint8 *)(ea))[3] & \ - ((uint8 *)(ea))[4] & \ - ((uint8 *)(ea))[5]) == 0xff) -#define ETHER_ISNULLADDR(ea) ((((uint8 *)(ea))[0] | \ - ((uint8 *)(ea))[1] | \ - ((uint8 *)(ea))[2] | \ - ((uint8 *)(ea))[3] | \ - ((uint8 *)(ea))[4] | \ - ((uint8 *)(ea))[5]) == 0) - - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/sdspi.h b/drivers/net/wireless/bcm4329/include/proto/sdspi.h deleted file mode 100644 index 7739e68a2440..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/sdspi.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SD-SPI Protocol Standard - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sdspi.h,v 9.1.20.1 2008/05/06 22:59:19 Exp $ - */ - -#define SPI_START_M BITFIELD_MASK(1) /* Bit [31] - Start Bit */ -#define SPI_START_S 31 -#define SPI_DIR_M BITFIELD_MASK(1) /* Bit [30] - Direction */ -#define SPI_DIR_S 30 -#define SPI_CMD_INDEX_M BITFIELD_MASK(6) /* Bits [29:24] - Command number */ -#define SPI_CMD_INDEX_S 24 -#define SPI_RW_M BITFIELD_MASK(1) /* Bit [23] - Read=0, Write=1 */ -#define SPI_RW_S 23 -#define SPI_FUNC_M BITFIELD_MASK(3) /* Bits [22:20] - Function Number */ -#define SPI_FUNC_S 20 -#define SPI_RAW_M BITFIELD_MASK(1) /* Bit [19] - Read After Wr */ -#define SPI_RAW_S 19 -#define SPI_STUFF_M BITFIELD_MASK(1) /* Bit [18] - Stuff bit */ -#define SPI_STUFF_S 18 -#define SPI_BLKMODE_M BITFIELD_MASK(1) /* Bit [19] - Blockmode 1=blk */ -#define SPI_BLKMODE_S 19 -#define SPI_OPCODE_M BITFIELD_MASK(1) /* Bit [18] - OP Code */ -#define SPI_OPCODE_S 18 -#define SPI_ADDR_M BITFIELD_MASK(17) /* Bits [17:1] - Address */ -#define SPI_ADDR_S 1 -#define SPI_STUFF0_M BITFIELD_MASK(1) /* Bit [0] - Stuff bit */ -#define SPI_STUFF0_S 0 - -#define SPI_RSP_START_M BITFIELD_MASK(1) /* Bit [7] - Start Bit (always 0) */ -#define SPI_RSP_START_S 7 -#define SPI_RSP_PARAM_ERR_M BITFIELD_MASK(1) /* Bit [6] - Parameter Error */ -#define SPI_RSP_PARAM_ERR_S 6 -#define SPI_RSP_RFU5_M BITFIELD_MASK(1) /* Bit [5] - RFU (Always 0) */ -#define SPI_RSP_RFU5_S 5 -#define SPI_RSP_FUNC_ERR_M BITFIELD_MASK(1) /* Bit [4] - Function number error */ -#define SPI_RSP_FUNC_ERR_S 4 -#define SPI_RSP_CRC_ERR_M BITFIELD_MASK(1) /* Bit [3] - COM CRC Error */ -#define SPI_RSP_CRC_ERR_S 3 -#define SPI_RSP_ILL_CMD_M BITFIELD_MASK(1) /* Bit [2] - Illegal Command error */ -#define SPI_RSP_ILL_CMD_S 2 -#define SPI_RSP_RFU1_M BITFIELD_MASK(1) /* Bit [1] - RFU (Always 0) */ -#define SPI_RSP_RFU1_S 1 -#define SPI_RSP_IDLE_M BITFIELD_MASK(1) /* Bit [0] - In idle state */ -#define SPI_RSP_IDLE_S 0 - -/* SD-SPI Protocol Definitions */ -#define SDSPI_COMMAND_LEN 6 /* Number of bytes in an SD command */ -#define SDSPI_START_BLOCK 0xFE /* SD Start Block Token */ -#define SDSPI_IDLE_PAD 0xFF /* SD-SPI idle value for MOSI */ -#define SDSPI_START_BIT_MASK 0x80 diff --git a/drivers/net/wireless/bcm4329/include/proto/vlan.h b/drivers/net/wireless/bcm4329/include/proto/vlan.h deleted file mode 100644 index 670bc44c6bd6..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/vlan.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 802.1Q VLAN protocol definitions - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: vlan.h,v 9.4.196.2 2008/12/07 21:19:20 Exp $ - */ - - -#ifndef _vlan_h_ -#define _vlan_h_ - -#ifndef _TYPEDEFS_H_ -#include -#endif - - -#include - -#define VLAN_VID_MASK 0xfff -#define VLAN_CFI_SHIFT 12 -#define VLAN_PRI_SHIFT 13 - -#define VLAN_PRI_MASK 7 - -#define VLAN_TAG_LEN 4 -#define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) - -#define VLAN_TPID 0x8100 - -struct ethervlan_header { - uint8 ether_dhost[ETHER_ADDR_LEN]; - uint8 ether_shost[ETHER_ADDR_LEN]; - uint16 vlan_type; - uint16 vlan_tag; - uint16 ether_type; -}; - -#define ETHERVLAN_HDR_LEN (ETHER_HDR_LEN + VLAN_TAG_LEN) - - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/proto/wpa.h b/drivers/net/wireless/bcm4329/include/proto/wpa.h deleted file mode 100644 index f5d0cd539777..000000000000 --- a/drivers/net/wireless/bcm4329/include/proto/wpa.h +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Fundamental types and constants relating to WPA - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: wpa.h,v 1.16.166.1.20.1 2008/11/20 00:51:31 Exp $ - */ - - -#ifndef _proto_wpa_h_ -#define _proto_wpa_h_ - -#include -#include - - - -#include - - - - -#define DOT11_RC_INVALID_WPA_IE 13 -#define DOT11_RC_MIC_FAILURE 14 -#define DOT11_RC_4WH_TIMEOUT 15 -#define DOT11_RC_GTK_UPDATE_TIMEOUT 16 -#define DOT11_RC_WPA_IE_MISMATCH 17 -#define DOT11_RC_INVALID_MC_CIPHER 18 -#define DOT11_RC_INVALID_UC_CIPHER 19 -#define DOT11_RC_INVALID_AKMP 20 -#define DOT11_RC_BAD_WPA_VERSION 21 -#define DOT11_RC_INVALID_WPA_CAP 22 -#define DOT11_RC_8021X_AUTH_FAIL 23 - -#define WPA2_PMKID_LEN 16 - - -typedef BWL_PRE_PACKED_STRUCT struct -{ - uint8 tag; - uint8 length; - uint8 oui[3]; - uint8 oui_type; - BWL_PRE_PACKED_STRUCT struct { - uint8 low; - uint8 high; - } BWL_POST_PACKED_STRUCT version; -} BWL_POST_PACKED_STRUCT wpa_ie_fixed_t; -#define WPA_IE_OUITYPE_LEN 4 -#define WPA_IE_FIXED_LEN 8 -#define WPA_IE_TAG_FIXED_LEN 6 - -typedef BWL_PRE_PACKED_STRUCT struct { - uint8 tag; - uint8 length; - BWL_PRE_PACKED_STRUCT struct { - uint8 low; - uint8 high; - } BWL_POST_PACKED_STRUCT version; -} BWL_POST_PACKED_STRUCT wpa_rsn_ie_fixed_t; -#define WPA_RSN_IE_FIXED_LEN 4 -#define WPA_RSN_IE_TAG_FIXED_LEN 2 -typedef uint8 wpa_pmkid_t[WPA2_PMKID_LEN]; - - -typedef BWL_PRE_PACKED_STRUCT struct -{ - uint8 oui[3]; - uint8 type; -} BWL_POST_PACKED_STRUCT wpa_suite_t, wpa_suite_mcast_t; -#define WPA_SUITE_LEN 4 - - -typedef BWL_PRE_PACKED_STRUCT struct -{ - BWL_PRE_PACKED_STRUCT struct { - uint8 low; - uint8 high; - } BWL_POST_PACKED_STRUCT count; - wpa_suite_t list[1]; -} BWL_POST_PACKED_STRUCT wpa_suite_ucast_t, wpa_suite_auth_key_mgmt_t; -#define WPA_IE_SUITE_COUNT_LEN 2 -typedef BWL_PRE_PACKED_STRUCT struct -{ - BWL_PRE_PACKED_STRUCT struct { - uint8 low; - uint8 high; - } BWL_POST_PACKED_STRUCT count; - wpa_pmkid_t list[1]; -} BWL_POST_PACKED_STRUCT wpa_pmkid_list_t; - - -#define WPA_CIPHER_NONE 0 -#define WPA_CIPHER_WEP_40 1 -#define WPA_CIPHER_TKIP 2 -#define WPA_CIPHER_AES_OCB 3 -#define WPA_CIPHER_AES_CCM 4 -#define WPA_CIPHER_WEP_104 5 - -#define IS_WPA_CIPHER(cipher) ((cipher) == WPA_CIPHER_NONE || \ - (cipher) == WPA_CIPHER_WEP_40 || \ - (cipher) == WPA_CIPHER_WEP_104 || \ - (cipher) == WPA_CIPHER_TKIP || \ - (cipher) == WPA_CIPHER_AES_OCB || \ - (cipher) == WPA_CIPHER_AES_CCM) - - -#define WPA_TKIP_CM_DETECT 60 -#define WPA_TKIP_CM_BLOCK 60 - - -#define RSN_CAP_LEN 2 - - -#define RSN_CAP_PREAUTH 0x0001 -#define RSN_CAP_NOPAIRWISE 0x0002 -#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C -#define RSN_CAP_PTK_REPLAY_CNTR_SHIFT 2 -#define RSN_CAP_GTK_REPLAY_CNTR_MASK 0x0030 -#define RSN_CAP_GTK_REPLAY_CNTR_SHIFT 4 -#define RSN_CAP_1_REPLAY_CNTR 0 -#define RSN_CAP_2_REPLAY_CNTRS 1 -#define RSN_CAP_4_REPLAY_CNTRS 2 -#define RSN_CAP_16_REPLAY_CNTRS 3 - - -#define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS -#define WPA_CAP_16_REPLAY_CNTRS RSN_CAP_16_REPLAY_CNTRS -#define WPA_CAP_REPLAY_CNTR_SHIFT RSN_CAP_PTK_REPLAY_CNTR_SHIFT -#define WPA_CAP_REPLAY_CNTR_MASK RSN_CAP_PTK_REPLAY_CNTR_MASK - - -#define WPA_CAP_LEN RSN_CAP_LEN - -#define WPA_CAP_WPA2_PREAUTH RSN_CAP_PREAUTH - - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/sbchipc.h b/drivers/net/wireless/bcm4329/include/sbchipc.h deleted file mode 100644 index 05b3fd872973..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbchipc.h +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * SiliconBackplane Chipcommon core hardware definitions. - * - * The chipcommon core provides chip identification, SB control, - * jtag, 0/1/2 uarts, clock frequency control, a watchdog interrupt timer, - * gpio interface, extbus, and support for serial and parallel flashes. - * - * $Id: sbchipc.h,v 13.103.2.5.4.5.2.9 2009/07/03 14:23:21 Exp $ - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - */ - - -#ifndef _SBCHIPC_H -#define _SBCHIPC_H - -#ifndef _LANGUAGE_ASSEMBLY - - -#ifndef PAD -#define _PADLINE(line) pad ## line -#define _XSTR(line) _PADLINE(line) -#define PAD _XSTR(__LINE__) -#endif - -typedef volatile struct { - uint32 chipid; - uint32 capabilities; - uint32 corecontrol; - uint32 bist; - - - uint32 otpstatus; - uint32 otpcontrol; - uint32 otpprog; - uint32 PAD; - - - uint32 intstatus; - uint32 intmask; - uint32 chipcontrol; - uint32 chipstatus; - - - uint32 jtagcmd; - uint32 jtagir; - uint32 jtagdr; - uint32 jtagctrl; - - - uint32 flashcontrol; - uint32 flashaddress; - uint32 flashdata; - uint32 PAD[1]; - - - uint32 broadcastaddress; - uint32 broadcastdata; - - - uint32 gpiopullup; - uint32 gpiopulldown; - uint32 gpioin; - uint32 gpioout; - uint32 gpioouten; - uint32 gpiocontrol; - uint32 gpiointpolarity; - uint32 gpiointmask; - - - uint32 gpioevent; - uint32 gpioeventintmask; - - - uint32 watchdog; - - - uint32 gpioeventintpolarity; - - - uint32 gpiotimerval; - uint32 gpiotimeroutmask; - - - uint32 clockcontrol_n; - uint32 clockcontrol_sb; - uint32 clockcontrol_pci; - uint32 clockcontrol_m2; - uint32 clockcontrol_m3; - uint32 clkdiv; - uint32 PAD[2]; - - - uint32 pll_on_delay; - uint32 fref_sel_delay; - uint32 slow_clk_ctl; - uint32 PAD[1]; - - - uint32 system_clk_ctl; - uint32 clkstatestretch; - uint32 PAD[13]; - - - uint32 eromptr; - - - uint32 pcmcia_config; - uint32 pcmcia_memwait; - uint32 pcmcia_attrwait; - uint32 pcmcia_iowait; - uint32 ide_config; - uint32 ide_memwait; - uint32 ide_attrwait; - uint32 ide_iowait; - uint32 prog_config; - uint32 prog_waitcount; - uint32 flash_config; - uint32 flash_waitcount; - uint32 PAD[4]; - uint32 PAD[40]; - - - - uint32 clk_ctl_st; - uint32 hw_war; - uint32 PAD[70]; - - - uint8 uart0data; - uint8 uart0imr; - uint8 uart0fcr; - uint8 uart0lcr; - uint8 uart0mcr; - uint8 uart0lsr; - uint8 uart0msr; - uint8 uart0scratch; - uint8 PAD[248]; - - uint8 uart1data; - uint8 uart1imr; - uint8 uart1fcr; - uint8 uart1lcr; - uint8 uart1mcr; - uint8 uart1lsr; - uint8 uart1msr; - uint8 uart1scratch; - uint32 PAD[126]; - - - uint32 pmucontrol; - uint32 pmucapabilities; - uint32 pmustatus; - uint32 res_state; - uint32 res_pending; - uint32 pmutimer; - uint32 min_res_mask; - uint32 max_res_mask; - uint32 res_table_sel; - uint32 res_dep_mask; - uint32 res_updn_timer; - uint32 res_timer; - uint32 clkstretch; - uint32 pmuwatchdog; - uint32 gpiosel; - uint32 gpioenable; - uint32 res_req_timer_sel; - uint32 res_req_timer; - uint32 res_req_mask; - uint32 PAD; - uint32 chipcontrol_addr; - uint32 chipcontrol_data; - uint32 regcontrol_addr; - uint32 regcontrol_data; - uint32 pllcontrol_addr; - uint32 pllcontrol_data; - uint32 PAD[102]; - uint16 otp[768]; -} chipcregs_t; - -#endif - -#define CC_CHIPID 0 -#define CC_CAPABILITIES 4 -#define CC_OTPST 0x10 -#define CC_CHIPST 0x2c -#define CC_JTAGCMD 0x30 -#define CC_JTAGIR 0x34 -#define CC_JTAGDR 0x38 -#define CC_JTAGCTRL 0x3c -#define CC_WATCHDOG 0x80 -#define CC_CLKC_N 0x90 -#define CC_CLKC_M0 0x94 -#define CC_CLKC_M1 0x98 -#define CC_CLKC_M2 0x9c -#define CC_CLKC_M3 0xa0 -#define CC_CLKDIV 0xa4 -#define CC_SYS_CLK_CTL 0xc0 -#define CC_CLK_CTL_ST SI_CLK_CTL_ST -#define CC_EROMPTR 0xfc -#define PMU_CTL 0x600 -#define PMU_CAP 0x604 -#define PMU_ST 0x608 -#define PMU_RES_STATE 0x60c -#define PMU_TIMER 0x614 -#define PMU_MIN_RES_MASK 0x618 -#define PMU_MAX_RES_MASK 0x61c -#define PMU_REG_CONTROL_ADDR 0x658 -#define PMU_REG_CONTROL_DATA 0x65C -#define PMU_PLL_CONTROL_ADDR 0x660 -#define PMU_PLL_CONTROL_DATA 0x664 -#define CC_OTP 0x800 - - -#define CID_ID_MASK 0x0000ffff -#define CID_REV_MASK 0x000f0000 -#define CID_REV_SHIFT 16 -#define CID_PKG_MASK 0x00f00000 -#define CID_PKG_SHIFT 20 -#define CID_CC_MASK 0x0f000000 -#define CID_CC_SHIFT 24 -#define CID_TYPE_MASK 0xf0000000 -#define CID_TYPE_SHIFT 28 - - -#define CC_CAP_UARTS_MASK 0x00000003 -#define CC_CAP_MIPSEB 0x00000004 -#define CC_CAP_UCLKSEL 0x00000018 -#define CC_CAP_UINTCLK 0x00000008 -#define CC_CAP_UARTGPIO 0x00000020 -#define CC_CAP_EXTBUS_MASK 0x000000c0 -#define CC_CAP_EXTBUS_NONE 0x00000000 -#define CC_CAP_EXTBUS_FULL 0x00000040 -#define CC_CAP_EXTBUS_PROG 0x00000080 -#define CC_CAP_FLASH_MASK 0x00000700 -#define CC_CAP_PLL_MASK 0x00038000 -#define CC_CAP_PWR_CTL 0x00040000 -#define CC_CAP_OTPSIZE 0x00380000 -#define CC_CAP_OTPSIZE_SHIFT 19 -#define CC_CAP_OTPSIZE_BASE 5 -#define CC_CAP_JTAGP 0x00400000 -#define CC_CAP_ROM 0x00800000 -#define CC_CAP_BKPLN64 0x08000000 -#define CC_CAP_PMU 0x10000000 -#define CC_CAP_ECI 0x20000000 - - -#define PLL_NONE 0x00000000 -#define PLL_TYPE1 0x00010000 -#define PLL_TYPE2 0x00020000 -#define PLL_TYPE3 0x00030000 -#define PLL_TYPE4 0x00008000 -#define PLL_TYPE5 0x00018000 -#define PLL_TYPE6 0x00028000 -#define PLL_TYPE7 0x00038000 - - -#define ILP_CLOCK 32000 - - -#define ALP_CLOCK 20000000 - - -#define HT_CLOCK 80000000 - - -#define CC_UARTCLKO 0x00000001 -#define CC_SE 0x00000002 -#define CC_UARTCLKEN 0x00000008 - - -#define CHIPCTRL_4321A0_DEFAULT 0x3a4 -#define CHIPCTRL_4321A1_DEFAULT 0x0a4 -#define CHIPCTRL_4321_PLL_DOWN 0x800000 - - -#define OTPS_OL_MASK 0x000000ff -#define OTPS_OL_MFG 0x00000001 -#define OTPS_OL_OR1 0x00000002 -#define OTPS_OL_OR2 0x00000004 -#define OTPS_OL_GU 0x00000008 -#define OTPS_GUP_MASK 0x00000f00 -#define OTPS_GUP_SHIFT 8 -#define OTPS_GUP_HW 0x00000100 -#define OTPS_GUP_SW 0x00000200 -#define OTPS_GUP_CI 0x00000400 -#define OTPS_GUP_FUSE 0x00000800 -#define OTPS_READY 0x00001000 -#define OTPS_RV(x) (1 << (16 + (x))) -#define OTPS_RV_MASK 0x0fff0000 - - -#define OTPC_PROGSEL 0x00000001 -#define OTPC_PCOUNT_MASK 0x0000000e -#define OTPC_PCOUNT_SHIFT 1 -#define OTPC_VSEL_MASK 0x000000f0 -#define OTPC_VSEL_SHIFT 4 -#define OTPC_TMM_MASK 0x00000700 -#define OTPC_TMM_SHIFT 8 -#define OTPC_ODM 0x00000800 -#define OTPC_PROGEN 0x80000000 - - -#define OTPP_COL_MASK 0x000000ff -#define OTPP_COL_SHIFT 0 -#define OTPP_ROW_MASK 0x0000ff00 -#define OTPP_ROW_SHIFT 8 -#define OTPP_OC_MASK 0x0f000000 -#define OTPP_OC_SHIFT 24 -#define OTPP_READERR 0x10000000 -#define OTPP_VALUE_MASK 0x20000000 -#define OTPP_VALUE_SHIFT 29 -#define OTPP_START_BUSY 0x80000000 - - -#define OTPPOC_READ 0 -#define OTPPOC_BIT_PROG 1 -#define OTPPOC_VERIFY 3 -#define OTPPOC_INIT 4 -#define OTPPOC_SET 5 -#define OTPPOC_RESET 6 -#define OTPPOC_OCST 7 -#define OTPPOC_ROW_LOCK 8 -#define OTPPOC_PRESCN_TEST 9 - - -#define JCMD_START 0x80000000 -#define JCMD_BUSY 0x80000000 -#define JCMD_STATE_MASK 0x60000000 -#define JCMD_STATE_TLR 0x00000000 -#define JCMD_STATE_PIR 0x20000000 -#define JCMD_STATE_PDR 0x40000000 -#define JCMD_STATE_RTI 0x60000000 -#define JCMD0_ACC_MASK 0x0000f000 -#define JCMD0_ACC_IRDR 0x00000000 -#define JCMD0_ACC_DR 0x00001000 -#define JCMD0_ACC_IR 0x00002000 -#define JCMD0_ACC_RESET 0x00003000 -#define JCMD0_ACC_IRPDR 0x00004000 -#define JCMD0_ACC_PDR 0x00005000 -#define JCMD0_IRW_MASK 0x00000f00 -#define JCMD_ACC_MASK 0x000f0000 -#define JCMD_ACC_IRDR 0x00000000 -#define JCMD_ACC_DR 0x00010000 -#define JCMD_ACC_IR 0x00020000 -#define JCMD_ACC_RESET 0x00030000 -#define JCMD_ACC_IRPDR 0x00040000 -#define JCMD_ACC_PDR 0x00050000 -#define JCMD_ACC_PIR 0x00060000 -#define JCMD_ACC_IRDR_I 0x00070000 -#define JCMD_ACC_DR_I 0x00080000 -#define JCMD_IRW_MASK 0x00001f00 -#define JCMD_IRW_SHIFT 8 -#define JCMD_DRW_MASK 0x0000003f - - -#define JCTRL_FORCE_CLK 4 -#define JCTRL_EXT_EN 2 -#define JCTRL_EN 1 - - -#define CLKD_SFLASH 0x0f000000 -#define CLKD_SFLASH_SHIFT 24 -#define CLKD_OTP 0x000f0000 -#define CLKD_OTP_SHIFT 16 -#define CLKD_JTAG 0x00000f00 -#define CLKD_JTAG_SHIFT 8 -#define CLKD_UART 0x000000ff - - -#define CI_GPIO 0x00000001 -#define CI_EI 0x00000002 -#define CI_TEMP 0x00000004 -#define CI_SIRQ 0x00000008 -#define CI_ECI 0x00000010 -#define CI_PMU 0x00000020 -#define CI_UART 0x00000040 -#define CI_WDRESET 0x80000000 - - -#define SCC_SS_MASK 0x00000007 -#define SCC_SS_LPO 0x00000000 -#define SCC_SS_XTAL 0x00000001 -#define SCC_SS_PCI 0x00000002 -#define SCC_LF 0x00000200 -#define SCC_LP 0x00000400 -#define SCC_FS 0x00000800 -#define SCC_IP 0x00001000 -#define SCC_XC 0x00002000 -#define SCC_XP 0x00004000 -#define SCC_CD_MASK 0xffff0000 -#define SCC_CD_SHIFT 16 - - -#define SYCC_IE 0x00000001 -#define SYCC_AE 0x00000002 -#define SYCC_FP 0x00000004 -#define SYCC_AR 0x00000008 -#define SYCC_HR 0x00000010 -#define SYCC_CD_MASK 0xffff0000 -#define SYCC_CD_SHIFT 16 - - -#define CF_EN 0x00000001 -#define CF_EM_MASK 0x0000000e -#define CF_EM_SHIFT 1 -#define CF_EM_FLASH 0 -#define CF_EM_SYNC 2 -#define CF_EM_PCMCIA 4 -#define CF_DS 0x00000010 -#define CF_BS 0x00000020 -#define CF_CD_MASK 0x000000c0 -#define CF_CD_SHIFT 6 -#define CF_CD_DIV2 0x00000000 -#define CF_CD_DIV3 0x00000040 -#define CF_CD_DIV4 0x00000080 -#define CF_CE 0x00000100 -#define CF_SB 0x00000200 - - -#define PM_W0_MASK 0x0000003f -#define PM_W1_MASK 0x00001f00 -#define PM_W1_SHIFT 8 -#define PM_W2_MASK 0x001f0000 -#define PM_W2_SHIFT 16 -#define PM_W3_MASK 0x1f000000 -#define PM_W3_SHIFT 24 - - -#define PA_W0_MASK 0x0000003f -#define PA_W1_MASK 0x00001f00 -#define PA_W1_SHIFT 8 -#define PA_W2_MASK 0x001f0000 -#define PA_W2_SHIFT 16 -#define PA_W3_MASK 0x1f000000 -#define PA_W3_SHIFT 24 - - -#define PI_W0_MASK 0x0000003f -#define PI_W1_MASK 0x00001f00 -#define PI_W1_SHIFT 8 -#define PI_W2_MASK 0x001f0000 -#define PI_W2_SHIFT 16 -#define PI_W3_MASK 0x1f000000 -#define PI_W3_SHIFT 24 - - -#define PW_W0_MASK 0x0000001f -#define PW_W1_MASK 0x00001f00 -#define PW_W1_SHIFT 8 -#define PW_W2_MASK 0x001f0000 -#define PW_W2_SHIFT 16 -#define PW_W3_MASK 0x1f000000 -#define PW_W3_SHIFT 24 - -#define PW_W0 0x0000000c -#define PW_W1 0x00000a00 -#define PW_W2 0x00020000 -#define PW_W3 0x01000000 - - -#define FW_W0_MASK 0x0000003f -#define FW_W1_MASK 0x00001f00 -#define FW_W1_SHIFT 8 -#define FW_W2_MASK 0x001f0000 -#define FW_W2_SHIFT 16 -#define FW_W3_MASK 0x1f000000 -#define FW_W3_SHIFT 24 - - -#define WATCHDOG_CLOCK 48000000 -#define WATCHDOG_CLOCK_5354 32000 - - -#define PCTL_ILP_DIV_MASK 0xffff0000 -#define PCTL_ILP_DIV_SHIFT 16 -#define PCTL_PLL_PLLCTL_UPD 0x00000400 -#define PCTL_NOILP_ON_WAIT 0x00000200 -#define PCTL_HT_REQ_EN 0x00000100 -#define PCTL_ALP_REQ_EN 0x00000080 -#define PCTL_XTALFREQ_MASK 0x0000007c -#define PCTL_XTALFREQ_SHIFT 2 -#define PCTL_ILP_DIV_EN 0x00000002 -#define PCTL_LPO_SEL 0x00000001 - - -#define CSTRETCH_HT 0xffff0000 -#define CSTRETCH_ALP 0x0000ffff - - -#define GPIO_ONTIME_SHIFT 16 - - -#define CN_N1_MASK 0x3f -#define CN_N2_MASK 0x3f00 -#define CN_N2_SHIFT 8 -#define CN_PLLC_MASK 0xf0000 -#define CN_PLLC_SHIFT 16 - - -#define CC_M1_MASK 0x3f -#define CC_M2_MASK 0x3f00 -#define CC_M2_SHIFT 8 -#define CC_M3_MASK 0x3f0000 -#define CC_M3_SHIFT 16 -#define CC_MC_MASK 0x1f000000 -#define CC_MC_SHIFT 24 - - -#define CC_F6_2 0x02 -#define CC_F6_3 0x03 -#define CC_F6_4 0x05 -#define CC_F6_5 0x09 -#define CC_F6_6 0x11 -#define CC_F6_7 0x21 - -#define CC_F5_BIAS 5 - -#define CC_MC_BYPASS 0x08 -#define CC_MC_M1 0x04 -#define CC_MC_M1M2 0x02 -#define CC_MC_M1M2M3 0x01 -#define CC_MC_M1M3 0x11 - - -#define CC_T2_BIAS 2 -#define CC_T2M2_BIAS 3 - -#define CC_T2MC_M1BYP 1 -#define CC_T2MC_M2BYP 2 -#define CC_T2MC_M3BYP 4 - - -#define CC_T6_MMASK 1 -#define CC_T6_M0 120000000 -#define CC_T6_M1 100000000 -#define SB2MIPS_T6(sb) (2 * (sb)) - - -#define CC_CLOCK_BASE1 24000000 -#define CC_CLOCK_BASE2 12500000 - - -#define CLKC_5350_N 0x0311 -#define CLKC_5350_M 0x04020009 - - -#define FLASH_NONE 0x000 -#define SFLASH_ST 0x100 -#define SFLASH_AT 0x200 -#define PFLASH 0x700 - - -#define CC_CFG_EN 0x0001 -#define CC_CFG_EM_MASK 0x000e -#define CC_CFG_EM_ASYNC 0x0000 -#define CC_CFG_EM_SYNC 0x0002 -#define CC_CFG_EM_PCMCIA 0x0004 -#define CC_CFG_EM_IDE 0x0006 -#define CC_CFG_DS 0x0010 -#define CC_CFG_CD_MASK 0x00e0 -#define CC_CFG_CE 0x0100 -#define CC_CFG_SB 0x0200 -#define CC_CFG_IS 0x0400 - - -#define CC_EB_BASE 0x1a000000 -#define CC_EB_PCMCIA_MEM 0x1a000000 -#define CC_EB_PCMCIA_IO 0x1a200000 -#define CC_EB_PCMCIA_CFG 0x1a400000 -#define CC_EB_IDE 0x1a800000 -#define CC_EB_PCMCIA1_MEM 0x1a800000 -#define CC_EB_PCMCIA1_IO 0x1aa00000 -#define CC_EB_PCMCIA1_CFG 0x1ac00000 -#define CC_EB_PROGIF 0x1b000000 - - - -#define SFLASH_OPCODE 0x000000ff -#define SFLASH_ACTION 0x00000700 -#define SFLASH_CS_ACTIVE 0x00001000 -#define SFLASH_START 0x80000000 -#define SFLASH_BUSY SFLASH_START - - -#define SFLASH_ACT_OPONLY 0x0000 -#define SFLASH_ACT_OP1D 0x0100 -#define SFLASH_ACT_OP3A 0x0200 -#define SFLASH_ACT_OP3A1D 0x0300 -#define SFLASH_ACT_OP3A4D 0x0400 -#define SFLASH_ACT_OP3A4X4D 0x0500 -#define SFLASH_ACT_OP3A1X4D 0x0700 - - -#define SFLASH_ST_WREN 0x0006 -#define SFLASH_ST_WRDIS 0x0004 -#define SFLASH_ST_RDSR 0x0105 -#define SFLASH_ST_WRSR 0x0101 -#define SFLASH_ST_READ 0x0303 -#define SFLASH_ST_PP 0x0302 -#define SFLASH_ST_SE 0x02d8 -#define SFLASH_ST_BE 0x00c7 -#define SFLASH_ST_DP 0x00b9 -#define SFLASH_ST_RES 0x03ab -#define SFLASH_ST_CSA 0x1000 - - -#define SFLASH_ST_WIP 0x01 -#define SFLASH_ST_WEL 0x02 -#define SFLASH_ST_BP_MASK 0x1c -#define SFLASH_ST_BP_SHIFT 2 -#define SFLASH_ST_SRWD 0x80 - - -#define SFLASH_AT_READ 0x07e8 -#define SFLASH_AT_PAGE_READ 0x07d2 -#define SFLASH_AT_BUF1_READ -#define SFLASH_AT_BUF2_READ -#define SFLASH_AT_STATUS 0x01d7 -#define SFLASH_AT_BUF1_WRITE 0x0384 -#define SFLASH_AT_BUF2_WRITE 0x0387 -#define SFLASH_AT_BUF1_ERASE_PROGRAM 0x0283 -#define SFLASH_AT_BUF2_ERASE_PROGRAM 0x0286 -#define SFLASH_AT_BUF1_PROGRAM 0x0288 -#define SFLASH_AT_BUF2_PROGRAM 0x0289 -#define SFLASH_AT_PAGE_ERASE 0x0281 -#define SFLASH_AT_BLOCK_ERASE 0x0250 -#define SFLASH_AT_BUF1_WRITE_ERASE_PROGRAM 0x0382 -#define SFLASH_AT_BUF2_WRITE_ERASE_PROGRAM 0x0385 -#define SFLASH_AT_BUF1_LOAD 0x0253 -#define SFLASH_AT_BUF2_LOAD 0x0255 -#define SFLASH_AT_BUF1_COMPARE 0x0260 -#define SFLASH_AT_BUF2_COMPARE 0x0261 -#define SFLASH_AT_BUF1_REPROGRAM 0x0258 -#define SFLASH_AT_BUF2_REPROGRAM 0x0259 - - -#define SFLASH_AT_READY 0x80 -#define SFLASH_AT_MISMATCH 0x40 -#define SFLASH_AT_ID_MASK 0x38 -#define SFLASH_AT_ID_SHIFT 3 - - - -#define UART_RX 0 -#define UART_TX 0 -#define UART_DLL 0 -#define UART_IER 1 -#define UART_DLM 1 -#define UART_IIR 2 -#define UART_FCR 2 -#define UART_LCR 3 -#define UART_MCR 4 -#define UART_LSR 5 -#define UART_MSR 6 -#define UART_SCR 7 -#define UART_LCR_DLAB 0x80 -#define UART_LCR_WLEN8 0x03 -#define UART_MCR_OUT2 0x08 -#define UART_MCR_LOOP 0x10 -#define UART_LSR_RX_FIFO 0x80 -#define UART_LSR_TDHR 0x40 -#define UART_LSR_THRE 0x20 -#define UART_LSR_BREAK 0x10 -#define UART_LSR_FRAMING 0x08 -#define UART_LSR_PARITY 0x04 -#define UART_LSR_OVERRUN 0x02 -#define UART_LSR_RXRDY 0x01 -#define UART_FCR_FIFO_ENABLE 1 - - -#define UART_IIR_FIFO_MASK 0xc0 -#define UART_IIR_INT_MASK 0xf -#define UART_IIR_MDM_CHG 0x0 -#define UART_IIR_NOINT 0x1 -#define UART_IIR_THRE 0x2 -#define UART_IIR_RCVD_DATA 0x4 -#define UART_IIR_RCVR_STATUS 0x6 -#define UART_IIR_CHAR_TIME 0xc - - -#define UART_IER_EDSSI 8 -#define UART_IER_ELSI 4 -#define UART_IER_ETBEI 2 -#define UART_IER_ERBFI 1 - - -#define PST_INTPEND 0x0040 -#define PST_SBCLKST 0x0030 -#define PST_SBCLKST_ILP 0x0010 -#define PST_SBCLKST_ALP 0x0020 -#define PST_SBCLKST_HT 0x0030 -#define PST_ALPAVAIL 0x0008 -#define PST_HTAVAIL 0x0004 -#define PST_RESINIT 0x0003 - - -#define PCAP_REV_MASK 0x000000ff -#define PCAP_RC_MASK 0x00001f00 -#define PCAP_RC_SHIFT 8 -#define PCAP_TC_MASK 0x0001e000 -#define PCAP_TC_SHIFT 13 -#define PCAP_PC_MASK 0x001e0000 -#define PCAP_PC_SHIFT 17 -#define PCAP_VC_MASK 0x01e00000 -#define PCAP_VC_SHIFT 21 -#define PCAP_CC_MASK 0x1e000000 -#define PCAP_CC_SHIFT 25 -#define PCAP5_PC_MASK 0x003e0000 -#define PCAP5_PC_SHIFT 17 -#define PCAP5_VC_MASK 0x07c00000 -#define PCAP5_VC_SHIFT 22 -#define PCAP5_CC_MASK 0xf8000000 -#define PCAP5_CC_SHIFT 27 - - - -#define PRRT_TIME_MASK 0x03ff -#define PRRT_INTEN 0x0400 -#define PRRT_REQ_ACTIVE 0x0800 -#define PRRT_ALP_REQ 0x1000 -#define PRRT_HT_REQ 0x2000 - - -#define PMURES_BIT(bit) (1 << (bit)) - - -#define PMURES_MAX_RESNUM 30 - - - - -#define PMU0_PLL0_PLLCTL0 0 -#define PMU0_PLL0_PC0_PDIV_MASK 1 -#define PMU0_PLL0_PC0_PDIV_FREQ 25000 -#define PMU0_PLL0_PC0_DIV_ARM_MASK 0x00000038 -#define PMU0_PLL0_PC0_DIV_ARM_SHIFT 3 -#define PMU0_PLL0_PC0_DIV_ARM_BASE 8 - - -#define PMU0_PLL0_PC0_DIV_ARM_110MHZ 0 -#define PMU0_PLL0_PC0_DIV_ARM_97_7MHZ 1 -#define PMU0_PLL0_PC0_DIV_ARM_88MHZ 2 -#define PMU0_PLL0_PC0_DIV_ARM_80MHZ 3 -#define PMU0_PLL0_PC0_DIV_ARM_73_3MHZ 4 -#define PMU0_PLL0_PC0_DIV_ARM_67_7MHZ 5 -#define PMU0_PLL0_PC0_DIV_ARM_62_9MHZ 6 -#define PMU0_PLL0_PC0_DIV_ARM_58_6MHZ 7 - - -#define PMU0_PLL0_PLLCTL1 1 -#define PMU0_PLL0_PC1_WILD_INT_MASK 0xf0000000 -#define PMU0_PLL0_PC1_WILD_INT_SHIFT 28 -#define PMU0_PLL0_PC1_WILD_FRAC_MASK 0x0fffff00 -#define PMU0_PLL0_PC1_WILD_FRAC_SHIFT 8 -#define PMU0_PLL0_PC1_STOP_MOD 0x00000040 - - -#define PMU0_PLL0_PLLCTL2 2 -#define PMU0_PLL0_PC2_WILD_INT_MASK 0xf -#define PMU0_PLL0_PC2_WILD_INT_SHIFT 4 - - -#define RES4328_EXT_SWITCHER_PWM 0 -#define RES4328_BB_SWITCHER_PWM 1 -#define RES4328_BB_SWITCHER_BURST 2 -#define RES4328_BB_EXT_SWITCHER_BURST 3 -#define RES4328_ILP_REQUEST 4 -#define RES4328_RADIO_SWITCHER_PWM 5 -#define RES4328_RADIO_SWITCHER_BURST 6 -#define RES4328_ROM_SWITCH 7 -#define RES4328_PA_REF_LDO 8 -#define RES4328_RADIO_LDO 9 -#define RES4328_AFE_LDO 10 -#define RES4328_PLL_LDO 11 -#define RES4328_BG_FILTBYP 12 -#define RES4328_TX_FILTBYP 13 -#define RES4328_RX_FILTBYP 14 -#define RES4328_XTAL_PU 15 -#define RES4328_XTAL_EN 16 -#define RES4328_BB_PLL_FILTBYP 17 -#define RES4328_RF_PLL_FILTBYP 18 -#define RES4328_BB_PLL_PU 19 - -#define RES5354_EXT_SWITCHER_PWM 0 -#define RES5354_BB_SWITCHER_PWM 1 -#define RES5354_BB_SWITCHER_BURST 2 -#define RES5354_BB_EXT_SWITCHER_BURST 3 -#define RES5354_ILP_REQUEST 4 -#define RES5354_RADIO_SWITCHER_PWM 5 -#define RES5354_RADIO_SWITCHER_BURST 6 -#define RES5354_ROM_SWITCH 7 -#define RES5354_PA_REF_LDO 8 -#define RES5354_RADIO_LDO 9 -#define RES5354_AFE_LDO 10 -#define RES5354_PLL_LDO 11 -#define RES5354_BG_FILTBYP 12 -#define RES5354_TX_FILTBYP 13 -#define RES5354_RX_FILTBYP 14 -#define RES5354_XTAL_PU 15 -#define RES5354_XTAL_EN 16 -#define RES5354_BB_PLL_FILTBYP 17 -#define RES5354_RF_PLL_FILTBYP 18 -#define RES5354_BB_PLL_PU 19 - - - -#define DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT 8 -#define DOT11MAC_880MHZ_CLK_DIVISOR_MASK (0xFF << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) -#define DOT11MAC_880MHZ_CLK_DIVISOR_VAL (0xE << DOT11MAC_880MHZ_CLK_DIVISOR_SHIFT) - - -#define PMU2_PHY_PLL_PLLCTL 4 -#define PMU2_SI_PLL_PLLCTL 10 - - -#define RES4325_BUCK_BOOST_BURST 0 -#define RES4325_CBUCK_BURST 1 -#define RES4325_CBUCK_PWM 2 -#define RES4325_CLDO_CBUCK_BURST 3 -#define RES4325_CLDO_CBUCK_PWM 4 -#define RES4325_BUCK_BOOST_PWM 5 -#define RES4325_ILP_REQUEST 6 -#define RES4325_ABUCK_BURST 7 -#define RES4325_ABUCK_PWM 8 -#define RES4325_LNLDO1_PU 9 -#define RES4325_OTP_PU 10 -#define RES4325_LNLDO3_PU 11 -#define RES4325_LNLDO4_PU 12 -#define RES4325_XTAL_PU 13 -#define RES4325_ALP_AVAIL 14 -#define RES4325_RX_PWRSW_PU 15 -#define RES4325_TX_PWRSW_PU 16 -#define RES4325_RFPLL_PWRSW_PU 17 -#define RES4325_LOGEN_PWRSW_PU 18 -#define RES4325_AFE_PWRSW_PU 19 -#define RES4325_BBPLL_PWRSW_PU 20 -#define RES4325_HT_AVAIL 21 - - -#define RES4325B0_CBUCK_LPOM 1 -#define RES4325B0_CBUCK_BURST 2 -#define RES4325B0_CBUCK_PWM 3 -#define RES4325B0_CLDO_PU 4 - - -#define RES4325C1_OTP_PWRSW_PU 10 -#define RES4325C1_LNLDO2_PU 12 - - -#define CST4325_SPROM_OTP_SEL_MASK 0x00000003 -#define CST4325_DEFCIS_SEL 0 -#define CST4325_SPROM_SEL 1 -#define CST4325_OTP_SEL 2 -#define CST4325_OTP_PWRDN 3 -#define CST4325_SDIO_USB_MODE_MASK 0x00000004 -#define CST4325_SDIO_USB_MODE_SHIFT 2 -#define CST4325_RCAL_VALID_MASK 0x00000008 -#define CST4325_RCAL_VALID_SHIFT 3 -#define CST4325_RCAL_VALUE_MASK 0x000001f0 -#define CST4325_RCAL_VALUE_SHIFT 4 -#define CST4325_PMUTOP_2B_MASK 0x00000200 -#define CST4325_PMUTOP_2B_SHIFT 9 - -#define RES4329_RESERVED0 0 -#define RES4329_CBUCK_LPOM 1 -#define RES4329_CBUCK_BURST 2 -#define RES4329_CBUCK_PWM 3 -#define RES4329_CLDO_PU 4 -#define RES4329_PALDO_PU 5 -#define RES4329_ILP_REQUEST 6 -#define RES4329_RESERVED7 7 -#define RES4329_RESERVED8 8 -#define RES4329_LNLDO1_PU 9 -#define RES4329_OTP_PU 10 -#define RES4329_RESERVED11 11 -#define RES4329_LNLDO2_PU 12 -#define RES4329_XTAL_PU 13 -#define RES4329_ALP_AVAIL 14 -#define RES4329_RX_PWRSW_PU 15 -#define RES4329_TX_PWRSW_PU 16 -#define RES4329_RFPLL_PWRSW_PU 17 -#define RES4329_LOGEN_PWRSW_PU 18 -#define RES4329_AFE_PWRSW_PU 19 -#define RES4329_BBPLL_PWRSW_PU 20 -#define RES4329_HT_AVAIL 21 - -#define CST4329_SPROM_OTP_SEL_MASK 0x00000003 -#define CST4329_DEFCIS_SEL 0 -#define CST4329_SPROM_SEL 1 -#define CST4329_OTP_SEL 2 -#define CST4329_OTP_PWRDN 3 -#define CST4329_SPI_SDIO_MODE_MASK 0x00000004 -#define CST4329_SPI_SDIO_MODE_SHIFT 2 - - -#define RES4312_SWITCHER_BURST 0 -#define RES4312_SWITCHER_PWM 1 -#define RES4312_PA_REF_LDO 2 -#define RES4312_CORE_LDO_BURST 3 -#define RES4312_CORE_LDO_PWM 4 -#define RES4312_RADIO_LDO 5 -#define RES4312_ILP_REQUEST 6 -#define RES4312_BG_FILTBYP 7 -#define RES4312_TX_FILTBYP 8 -#define RES4312_RX_FILTBYP 9 -#define RES4312_XTAL_PU 10 -#define RES4312_ALP_AVAIL 11 -#define RES4312_BB_PLL_FILTBYP 12 -#define RES4312_RF_PLL_FILTBYP 13 -#define RES4312_HT_AVAIL 14 - -#define RES4322_RF_LDO 0 -#define RES4322_ILP_REQUEST 1 -#define RES4322_XTAL_PU 2 -#define RES4322_ALP_AVAIL 3 -#define RES4322_SI_PLL_ON 4 -#define RES4322_HT_SI_AVAIL 5 -#define RES4322_PHY_PLL_ON 6 -#define RES4322_HT_PHY_AVAIL 7 -#define RES4322_OTP_PU 8 - - -#define CST4322_XTAL_FREQ_20_40MHZ 0x00000020 -#define CST4322_SPROM_OTP_SEL_MASK 0x000000c0 -#define CST4322_SPROM_OTP_SEL_SHIFT 6 -#define CST4322_NO_SPROM_OTP 0 -#define CST4322_SPROM_PRESENT 1 -#define CST4322_OTP_PRESENT 2 -#define CST4322_PCI_OR_USB 0x00000100 -#define CST4322_BOOT_MASK 0x00000600 -#define CST4322_BOOT_SHIFT 9 -#define CST4322_BOOT_FROM_SRAM 0 -#define CST4322_BOOT_FROM_ROM 1 -#define CST4322_BOOT_FROM_FLASH 2 -#define CST4322_BOOT_FROM_INVALID 3 -#define CST4322_ILP_DIV_EN 0x00000800 -#define CST4322_FLASH_TYPE_MASK 0x00001000 -#define CST4322_FLASH_TYPE_SHIFT 12 -#define CST4322_FLASH_TYPE_SHIFT_ST 0 -#define CST4322_FLASH_TYPE_SHIFT_ATMEL 1 -#define CST4322_ARM_TAP_SEL 0x00002000 -#define CST4322_RES_INIT_MODE_MASK 0x0000c000 -#define CST4322_RES_INIT_MODE_SHIFT 14 -#define CST4322_RES_INIT_MODE_ILPAVAIL 0 -#define CST4322_RES_INIT_MODE_ILPREQ 1 -#define CST4322_RES_INIT_MODE_ALPAVAIL 2 -#define CST4322_RES_INIT_MODE_HTAVAIL 3 -#define CST4322_PCIPLLCLK_GATING 0x00010000 -#define CST4322_CLK_SWITCH_PCI_TO_ALP 0x00020000 -#define CST4322_PCI_CARDBUS_MODE 0x00040000 - -#define RES4315_CBUCK_LPOM 1 -#define RES4315_CBUCK_BURST 2 -#define RES4315_CBUCK_PWM 3 -#define RES4315_CLDO_PU 4 -#define RES4315_PALDO_PU 5 -#define RES4315_ILP_REQUEST 6 -#define RES4315_LNLDO1_PU 9 -#define RES4315_OTP_PU 10 -#define RES4315_LNLDO2_PU 12 -#define RES4315_XTAL_PU 13 -#define RES4315_ALP_AVAIL 14 -#define RES4315_RX_PWRSW_PU 15 -#define RES4315_TX_PWRSW_PU 16 -#define RES4315_RFPLL_PWRSW_PU 17 -#define RES4315_LOGEN_PWRSW_PU 18 -#define RES4315_AFE_PWRSW_PU 19 -#define RES4315_BBPLL_PWRSW_PU 20 -#define RES4315_HT_AVAIL 21 - -#define CST4315_SPROM_OTP_SEL_MASK 0x00000003 -#define CST4315_DEFCIS_SEL 0x00000000 -#define CST4315_SPROM_SEL 0x00000001 -#define CST4315_OTP_SEL 0x00000002 -#define CST4315_OTP_PWRDN 0x00000003 -#define CST4315_SDIO_MODE 0x00000004 -#define CST4315_RCAL_VALID 0x00000008 -#define CST4315_RCAL_VALUE_MASK 0x000001f0 -#define CST4315_RCAL_VALUE_SHIFT 4 -#define CST4315_PALDO_EXTPNP 0x00000200 -#define CST4315_CBUCK_MODE_MASK 0x00000c00 -#define CST4315_CBUCK_MODE_BURST 0x00000400 -#define CST4315_CBUCK_MODE_LPBURST 0x00000c00 - - -#define PMU_MAX_TRANSITION_DLY 15000 - - -#define PMURES_UP_TRANSITION 2 - - - - - -#define ECI_BW_20 0x0 -#define ECI_BW_25 0x1 -#define ECI_BW_30 0x2 -#define ECI_BW_35 0x3 -#define ECI_BW_40 0x4 -#define ECI_BW_45 0x5 -#define ECI_BW_50 0x6 -#define ECI_BW_ALL 0x7 - - -#define WLAN_NUM_ANT1 TXANT_0 -#define WLAN_NUM_ANT2 TXANT_1 - -#endif diff --git a/drivers/net/wireless/bcm4329/include/sbconfig.h b/drivers/net/wireless/bcm4329/include/sbconfig.h deleted file mode 100644 index da18ccbe9ab8..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbconfig.h +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Broadcom SiliconBackplane hardware register definitions. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbconfig.h,v 13.67.30.1 2008/05/07 20:17:27 Exp $ - */ - - -#ifndef _SBCONFIG_H -#define _SBCONFIG_H - - -#ifndef PAD -#define _PADLINE(line) pad ## line -#define _XSTR(line) _PADLINE(line) -#define PAD _XSTR(__LINE__) -#endif - - -#define SB_BUS_SIZE 0x10000 -#define SB_BUS_BASE(b) (SI_ENUM_BASE + (b) * SB_BUS_SIZE) -#define SB_BUS_MAXCORES (SB_BUS_SIZE / SI_CORE_SIZE) - - -#define SBCONFIGOFF 0xf00 -#define SBCONFIGSIZE 256 - -#define SBIPSFLAG 0x08 -#define SBTPSFLAG 0x18 -#define SBTMERRLOGA 0x48 -#define SBTMERRLOG 0x50 -#define SBADMATCH3 0x60 -#define SBADMATCH2 0x68 -#define SBADMATCH1 0x70 -#define SBIMSTATE 0x90 -#define SBINTVEC 0x94 -#define SBTMSTATELOW 0x98 -#define SBTMSTATEHIGH 0x9c -#define SBBWA0 0xa0 -#define SBIMCONFIGLOW 0xa8 -#define SBIMCONFIGHIGH 0xac -#define SBADMATCH0 0xb0 -#define SBTMCONFIGLOW 0xb8 -#define SBTMCONFIGHIGH 0xbc -#define SBBCONFIG 0xc0 -#define SBBSTATE 0xc8 -#define SBACTCNFG 0xd8 -#define SBFLAGST 0xe8 -#define SBIDLOW 0xf8 -#define SBIDHIGH 0xfc - - - -#define SBIMERRLOGA 0xea8 -#define SBIMERRLOG 0xeb0 -#define SBTMPORTCONNID0 0xed8 -#define SBTMPORTLOCK0 0xef8 - -#ifndef _LANGUAGE_ASSEMBLY - -typedef volatile struct _sbconfig { - uint32 PAD[2]; - uint32 sbipsflag; - uint32 PAD[3]; - uint32 sbtpsflag; - uint32 PAD[11]; - uint32 sbtmerrloga; - uint32 PAD; - uint32 sbtmerrlog; - uint32 PAD[3]; - uint32 sbadmatch3; - uint32 PAD; - uint32 sbadmatch2; - uint32 PAD; - uint32 sbadmatch1; - uint32 PAD[7]; - uint32 sbimstate; - uint32 sbintvec; - uint32 sbtmstatelow; - uint32 sbtmstatehigh; - uint32 sbbwa0; - uint32 PAD; - uint32 sbimconfiglow; - uint32 sbimconfighigh; - uint32 sbadmatch0; - uint32 PAD; - uint32 sbtmconfiglow; - uint32 sbtmconfighigh; - uint32 sbbconfig; - uint32 PAD; - uint32 sbbstate; - uint32 PAD[3]; - uint32 sbactcnfg; - uint32 PAD[3]; - uint32 sbflagst; - uint32 PAD[3]; - uint32 sbidlow; - uint32 sbidhigh; -} sbconfig_t; - -#endif - - -#define SBIPS_INT1_MASK 0x3f -#define SBIPS_INT1_SHIFT 0 -#define SBIPS_INT2_MASK 0x3f00 -#define SBIPS_INT2_SHIFT 8 -#define SBIPS_INT3_MASK 0x3f0000 -#define SBIPS_INT3_SHIFT 16 -#define SBIPS_INT4_MASK 0x3f000000 -#define SBIPS_INT4_SHIFT 24 - - -#define SBTPS_NUM0_MASK 0x3f -#define SBTPS_F0EN0 0x40 - - -#define SBTMEL_CM 0x00000007 -#define SBTMEL_CI 0x0000ff00 -#define SBTMEL_EC 0x0f000000 -#define SBTMEL_ME 0x80000000 - - -#define SBIM_PC 0xf -#define SBIM_AP_MASK 0x30 -#define SBIM_AP_BOTH 0x00 -#define SBIM_AP_TS 0x10 -#define SBIM_AP_TK 0x20 -#define SBIM_AP_RSV 0x30 -#define SBIM_IBE 0x20000 -#define SBIM_TO 0x40000 -#define SBIM_BY 0x01800000 -#define SBIM_RJ 0x02000000 - - -#define SBTML_RESET 0x0001 -#define SBTML_REJ_MASK 0x0006 -#define SBTML_REJ 0x0002 -#define SBTML_TMPREJ 0x0004 - -#define SBTML_SICF_SHIFT 16 - - -#define SBTMH_SERR 0x0001 -#define SBTMH_INT 0x0002 -#define SBTMH_BUSY 0x0004 -#define SBTMH_TO 0x0020 - -#define SBTMH_SISF_SHIFT 16 - - -#define SBBWA_TAB0_MASK 0xffff -#define SBBWA_TAB1_MASK 0xffff -#define SBBWA_TAB1_SHIFT 16 - - -#define SBIMCL_STO_MASK 0x7 -#define SBIMCL_RTO_MASK 0x70 -#define SBIMCL_RTO_SHIFT 4 -#define SBIMCL_CID_MASK 0xff0000 -#define SBIMCL_CID_SHIFT 16 - - -#define SBIMCH_IEM_MASK 0xc -#define SBIMCH_TEM_MASK 0x30 -#define SBIMCH_TEM_SHIFT 4 -#define SBIMCH_BEM_MASK 0xc0 -#define SBIMCH_BEM_SHIFT 6 - - -#define SBAM_TYPE_MASK 0x3 -#define SBAM_AD64 0x4 -#define SBAM_ADINT0_MASK 0xf8 -#define SBAM_ADINT0_SHIFT 3 -#define SBAM_ADINT1_MASK 0x1f8 -#define SBAM_ADINT1_SHIFT 3 -#define SBAM_ADINT2_MASK 0x1f8 -#define SBAM_ADINT2_SHIFT 3 -#define SBAM_ADEN 0x400 -#define SBAM_ADNEG 0x800 -#define SBAM_BASE0_MASK 0xffffff00 -#define SBAM_BASE0_SHIFT 8 -#define SBAM_BASE1_MASK 0xfffff000 -#define SBAM_BASE1_SHIFT 12 -#define SBAM_BASE2_MASK 0xffff0000 -#define SBAM_BASE2_SHIFT 16 - - -#define SBTMCL_CD_MASK 0xff -#define SBTMCL_CO_MASK 0xf800 -#define SBTMCL_CO_SHIFT 11 -#define SBTMCL_IF_MASK 0xfc0000 -#define SBTMCL_IF_SHIFT 18 -#define SBTMCL_IM_MASK 0x3000000 -#define SBTMCL_IM_SHIFT 24 - - -#define SBTMCH_BM_MASK 0x3 -#define SBTMCH_RM_MASK 0x3 -#define SBTMCH_RM_SHIFT 2 -#define SBTMCH_SM_MASK 0x30 -#define SBTMCH_SM_SHIFT 4 -#define SBTMCH_EM_MASK 0x300 -#define SBTMCH_EM_SHIFT 8 -#define SBTMCH_IM_MASK 0xc00 -#define SBTMCH_IM_SHIFT 10 - - -#define SBBC_LAT_MASK 0x3 -#define SBBC_MAX0_MASK 0xf0000 -#define SBBC_MAX0_SHIFT 16 -#define SBBC_MAX1_MASK 0xf00000 -#define SBBC_MAX1_SHIFT 20 - - -#define SBBS_SRD 0x1 -#define SBBS_HRD 0x2 - - -#define SBIDL_CS_MASK 0x3 -#define SBIDL_AR_MASK 0x38 -#define SBIDL_AR_SHIFT 3 -#define SBIDL_SYNCH 0x40 -#define SBIDL_INIT 0x80 -#define SBIDL_MINLAT_MASK 0xf00 -#define SBIDL_MINLAT_SHIFT 8 -#define SBIDL_MAXLAT 0xf000 -#define SBIDL_MAXLAT_SHIFT 12 -#define SBIDL_FIRST 0x10000 -#define SBIDL_CW_MASK 0xc0000 -#define SBIDL_CW_SHIFT 18 -#define SBIDL_TP_MASK 0xf00000 -#define SBIDL_TP_SHIFT 20 -#define SBIDL_IP_MASK 0xf000000 -#define SBIDL_IP_SHIFT 24 -#define SBIDL_RV_MASK 0xf0000000 -#define SBIDL_RV_SHIFT 28 -#define SBIDL_RV_2_2 0x00000000 -#define SBIDL_RV_2_3 0x10000000 - - -#define SBIDH_RC_MASK 0x000f -#define SBIDH_RCE_MASK 0x7000 -#define SBIDH_RCE_SHIFT 8 -#define SBCOREREV(sbidh) \ - ((((sbidh) & SBIDH_RCE_MASK) >> SBIDH_RCE_SHIFT) | ((sbidh) & SBIDH_RC_MASK)) -#define SBIDH_CC_MASK 0x8ff0 -#define SBIDH_CC_SHIFT 4 -#define SBIDH_VC_MASK 0xffff0000 -#define SBIDH_VC_SHIFT 16 - -#define SB_COMMIT 0xfd8 - - -#define SB_VEND_BCM 0x4243 - -#endif diff --git a/drivers/net/wireless/bcm4329/include/sbhnddma.h b/drivers/net/wireless/bcm4329/include/sbhnddma.h deleted file mode 100644 index 7681395f5b3b..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbhnddma.h +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Generic Broadcom Home Networking Division (HND) DMA engine HW interface - * This supports the following chips: BCM42xx, 44xx, 47xx . - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbhnddma.h,v 13.11.250.5.16.1 2009/07/21 14:04:51 Exp $ - */ - - -#ifndef _sbhnddma_h_ -#define _sbhnddma_h_ - - - - - - - -typedef volatile struct { - uint32 control; - uint32 addr; - uint32 ptr; - uint32 status; -} dma32regs_t; - -typedef volatile struct { - dma32regs_t xmt; - dma32regs_t rcv; -} dma32regp_t; - -typedef volatile struct { - uint32 fifoaddr; - uint32 fifodatalow; - uint32 fifodatahigh; - uint32 pad; -} dma32diag_t; - - -typedef volatile struct { - uint32 ctrl; - uint32 addr; -} dma32dd_t; - - -#define D32RINGALIGN_BITS 12 -#define D32MAXRINGSZ (1 << D32RINGALIGN_BITS) -#define D32RINGALIGN (1 << D32RINGALIGN_BITS) -#define D32MAXDD (D32MAXRINGSZ / sizeof (dma32dd_t)) - - -#define XC_XE ((uint32)1 << 0) -#define XC_SE ((uint32)1 << 1) -#define XC_LE ((uint32)1 << 2) -#define XC_FL ((uint32)1 << 4) -#define XC_PD ((uint32)1 << 11) -#define XC_AE ((uint32)3 << 16) -#define XC_AE_SHIFT 16 - - -#define XP_LD_MASK 0xfff - - -#define XS_CD_MASK 0x0fff -#define XS_XS_MASK 0xf000 -#define XS_XS_SHIFT 12 -#define XS_XS_DISABLED 0x0000 -#define XS_XS_ACTIVE 0x1000 -#define XS_XS_IDLE 0x2000 -#define XS_XS_STOPPED 0x3000 -#define XS_XS_SUSP 0x4000 -#define XS_XE_MASK 0xf0000 -#define XS_XE_SHIFT 16 -#define XS_XE_NOERR 0x00000 -#define XS_XE_DPE 0x10000 -#define XS_XE_DFU 0x20000 -#define XS_XE_BEBR 0x30000 -#define XS_XE_BEDA 0x40000 -#define XS_AD_MASK 0xfff00000 -#define XS_AD_SHIFT 20 - - -#define RC_RE ((uint32)1 << 0) -#define RC_RO_MASK 0xfe -#define RC_RO_SHIFT 1 -#define RC_FM ((uint32)1 << 8) -#define RC_SH ((uint32)1 << 9) -#define RC_OC ((uint32)1 << 10) -#define RC_PD ((uint32)1 << 11) -#define RC_AE ((uint32)3 << 16) -#define RC_AE_SHIFT 16 - - -#define RP_LD_MASK 0xfff - - -#define RS_CD_MASK 0x0fff -#define RS_RS_MASK 0xf000 -#define RS_RS_SHIFT 12 -#define RS_RS_DISABLED 0x0000 -#define RS_RS_ACTIVE 0x1000 -#define RS_RS_IDLE 0x2000 -#define RS_RS_STOPPED 0x3000 -#define RS_RE_MASK 0xf0000 -#define RS_RE_SHIFT 16 -#define RS_RE_NOERR 0x00000 -#define RS_RE_DPE 0x10000 -#define RS_RE_DFO 0x20000 -#define RS_RE_BEBW 0x30000 -#define RS_RE_BEDA 0x40000 -#define RS_AD_MASK 0xfff00000 -#define RS_AD_SHIFT 20 - - -#define FA_OFF_MASK 0xffff -#define FA_SEL_MASK 0xf0000 -#define FA_SEL_SHIFT 16 -#define FA_SEL_XDD 0x00000 -#define FA_SEL_XDP 0x10000 -#define FA_SEL_RDD 0x40000 -#define FA_SEL_RDP 0x50000 -#define FA_SEL_XFD 0x80000 -#define FA_SEL_XFP 0x90000 -#define FA_SEL_RFD 0xc0000 -#define FA_SEL_RFP 0xd0000 -#define FA_SEL_RSD 0xe0000 -#define FA_SEL_RSP 0xf0000 - - -#define CTRL_BC_MASK 0x1fff -#define CTRL_AE ((uint32)3 << 16) -#define CTRL_AE_SHIFT 16 -#define CTRL_EOT ((uint32)1 << 28) -#define CTRL_IOC ((uint32)1 << 29) -#define CTRL_EOF ((uint32)1 << 30) -#define CTRL_SOF ((uint32)1 << 31) - - -#define CTRL_CORE_MASK 0x0ff00000 - - - - -typedef volatile struct { - uint32 control; - uint32 ptr; - uint32 addrlow; - uint32 addrhigh; - uint32 status0; - uint32 status1; -} dma64regs_t; - -typedef volatile struct { - dma64regs_t tx; - dma64regs_t rx; -} dma64regp_t; - -typedef volatile struct { - uint32 fifoaddr; - uint32 fifodatalow; - uint32 fifodatahigh; - uint32 pad; -} dma64diag_t; - - -typedef volatile struct { - uint32 ctrl1; - uint32 ctrl2; - uint32 addrlow; - uint32 addrhigh; -} dma64dd_t; - - -#define D64RINGALIGN_BITS 13 -#define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) -#define D64RINGALIGN (1 << D64RINGALIGN_BITS) -#define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) - - -#define D64_XC_XE 0x00000001 -#define D64_XC_SE 0x00000002 -#define D64_XC_LE 0x00000004 -#define D64_XC_FL 0x00000010 -#define D64_XC_PD 0x00000800 -#define D64_XC_AE 0x00030000 -#define D64_XC_AE_SHIFT 16 - - -#define D64_XP_LD_MASK 0x00000fff - - -#define D64_XS0_CD_MASK 0x00001fff -#define D64_XS0_XS_MASK 0xf0000000 -#define D64_XS0_XS_SHIFT 28 -#define D64_XS0_XS_DISABLED 0x00000000 -#define D64_XS0_XS_ACTIVE 0x10000000 -#define D64_XS0_XS_IDLE 0x20000000 -#define D64_XS0_XS_STOPPED 0x30000000 -#define D64_XS0_XS_SUSP 0x40000000 - -#define D64_XS1_AD_MASK 0x0001ffff -#define D64_XS1_XE_MASK 0xf0000000 -#define D64_XS1_XE_SHIFT 28 -#define D64_XS1_XE_NOERR 0x00000000 -#define D64_XS1_XE_DPE 0x10000000 -#define D64_XS1_XE_DFU 0x20000000 -#define D64_XS1_XE_DTE 0x30000000 -#define D64_XS1_XE_DESRE 0x40000000 -#define D64_XS1_XE_COREE 0x50000000 - - -#define D64_RC_RE 0x00000001 -#define D64_RC_RO_MASK 0x000000fe -#define D64_RC_RO_SHIFT 1 -#define D64_RC_FM 0x00000100 -#define D64_RC_SH 0x00000200 -#define D64_RC_OC 0x00000400 -#define D64_RC_PD 0x00000800 -#define D64_RC_AE 0x00030000 -#define D64_RC_AE_SHIFT 16 - - -#define D64_RP_LD_MASK 0x00000fff - - -#define D64_RS0_CD_MASK 0x00001fff -#define D64_RS0_RS_MASK 0xf0000000 -#define D64_RS0_RS_SHIFT 28 -#define D64_RS0_RS_DISABLED 0x00000000 -#define D64_RS0_RS_ACTIVE 0x10000000 -#define D64_RS0_RS_IDLE 0x20000000 -#define D64_RS0_RS_STOPPED 0x30000000 -#define D64_RS0_RS_SUSP 0x40000000 - -#define D64_RS1_AD_MASK 0x0001ffff -#define D64_RS1_RE_MASK 0xf0000000 -#define D64_RS1_RE_SHIFT 28 -#define D64_RS1_RE_NOERR 0x00000000 -#define D64_RS1_RE_DPO 0x10000000 -#define D64_RS1_RE_DFU 0x20000000 -#define D64_RS1_RE_DTE 0x30000000 -#define D64_RS1_RE_DESRE 0x40000000 -#define D64_RS1_RE_COREE 0x50000000 - - -#define D64_FA_OFF_MASK 0xffff -#define D64_FA_SEL_MASK 0xf0000 -#define D64_FA_SEL_SHIFT 16 -#define D64_FA_SEL_XDD 0x00000 -#define D64_FA_SEL_XDP 0x10000 -#define D64_FA_SEL_RDD 0x40000 -#define D64_FA_SEL_RDP 0x50000 -#define D64_FA_SEL_XFD 0x80000 -#define D64_FA_SEL_XFP 0x90000 -#define D64_FA_SEL_RFD 0xc0000 -#define D64_FA_SEL_RFP 0xd0000 -#define D64_FA_SEL_RSD 0xe0000 -#define D64_FA_SEL_RSP 0xf0000 - - -#define D64_CTRL1_EOT ((uint32)1 << 28) -#define D64_CTRL1_IOC ((uint32)1 << 29) -#define D64_CTRL1_EOF ((uint32)1 << 30) -#define D64_CTRL1_SOF ((uint32)1 << 31) - - -#define D64_CTRL2_BC_MASK 0x00007fff -#define D64_CTRL2_AE 0x00030000 -#define D64_CTRL2_AE_SHIFT 16 -#define D64_CTRL2_PARITY 0x00040000 - - -#define D64_CTRL_CORE_MASK 0x0ff00000 - - -#endif diff --git a/drivers/net/wireless/bcm4329/include/sbpcmcia.h b/drivers/net/wireless/bcm4329/include/sbpcmcia.h deleted file mode 100644 index d6d80334258a..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbpcmcia.h +++ /dev/null @@ -1,109 +0,0 @@ -/* - * BCM43XX Sonics SiliconBackplane PCMCIA core hardware definitions. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbpcmcia.h,v 13.31.4.1.2.3.8.7 2009/06/22 05:14:24 Exp $ - */ - - -#ifndef _SBPCMCIA_H -#define _SBPCMCIA_H - - - - -#define PCMCIA_FCR (0x700 / 2) - -#define FCR0_OFF 0 -#define FCR1_OFF (0x40 / 2) -#define FCR2_OFF (0x80 / 2) -#define FCR3_OFF (0xc0 / 2) - -#define PCMCIA_FCR0 (0x700 / 2) -#define PCMCIA_FCR1 (0x740 / 2) -#define PCMCIA_FCR2 (0x780 / 2) -#define PCMCIA_FCR3 (0x7c0 / 2) - - - -#define PCMCIA_COR 0 - -#define COR_RST 0x80 -#define COR_LEV 0x40 -#define COR_IRQEN 0x04 -#define COR_BLREN 0x01 -#define COR_FUNEN 0x01 - - -#define PCICIA_FCSR (2 / 2) -#define PCICIA_PRR (4 / 2) -#define PCICIA_SCR (6 / 2) -#define PCICIA_ESR (8 / 2) - - -#define PCM_MEMOFF 0x0000 -#define F0_MEMOFF 0x1000 -#define F1_MEMOFF 0x2000 -#define F2_MEMOFF 0x3000 -#define F3_MEMOFF 0x4000 - - -#define MEM_ADDR0 (0x728 / 2) -#define MEM_ADDR1 (0x72a / 2) -#define MEM_ADDR2 (0x72c / 2) - - -#define PCMCIA_ADDR0 (0x072e / 2) -#define PCMCIA_ADDR1 (0x0730 / 2) -#define PCMCIA_ADDR2 (0x0732 / 2) - -#define MEM_SEG (0x0734 / 2) -#define SROM_CS (0x0736 / 2) -#define SROM_DATAL (0x0738 / 2) -#define SROM_DATAH (0x073a / 2) -#define SROM_ADDRL (0x073c / 2) -#define SROM_ADDRH (0x073e / 2) -#define SROM_INFO2 (0x0772 / 2) -#define SROM_INFO (0x07be / 2) - - -#define SROM_IDLE 0 -#define SROM_WRITE 1 -#define SROM_READ 2 -#define SROM_WEN 4 -#define SROM_WDS 7 -#define SROM_DONE 8 - - -#define SRI_SZ_MASK 0x03 -#define SRI_BLANK 0x04 -#define SRI_OTP 0x80 - - - -#define SBTML_INT_ACK 0x40000 -#define SBTML_INT_EN 0x20000 - - -#define SBTMH_INT_STATUS 0x40000 - -#endif diff --git a/drivers/net/wireless/bcm4329/include/sbsdio.h b/drivers/net/wireless/bcm4329/include/sbsdio.h deleted file mode 100644 index 75aaf4d88f7d..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbsdio.h +++ /dev/null @@ -1,166 +0,0 @@ -/* - * SDIO device core hardware definitions. - * sdio is a portion of the pcmcia core in core rev 3 - rev 8 - * - * SDIO core support 1bit, 4 bit SDIO mode as well as SPI mode. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbsdio.h,v 13.29.4.1.22.3 2009/03/11 20:26:57 Exp $ - */ - -#ifndef _SBSDIO_H -#define _SBSDIO_H - -#define SBSDIO_NUM_FUNCTION 3 /* as of sdiod rev 0, supports 3 functions */ - -/* function 1 miscellaneous registers */ -#define SBSDIO_SPROM_CS 0x10000 /* sprom command and status */ -#define SBSDIO_SPROM_INFO 0x10001 /* sprom info register */ -#define SBSDIO_SPROM_DATA_LOW 0x10002 /* sprom indirect access data byte 0 */ -#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* sprom indirect access data byte 1 */ -#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* sprom indirect access addr byte 0 */ -#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* sprom indirect access addr byte 0 */ -#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu (gpio) output */ -#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu (gpio) enable */ -#define SBSDIO_WATERMARK 0x10008 /* rev < 7, watermark for sdio device */ -#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */ - -/* registers introduced in rev 8, some content (mask/bits) defs in sbsdpcmdev.h */ -#define SBSDIO_FUNC1_SBADDRLOW 0x1000A /* SB Address Window Low (b15) */ -#define SBSDIO_FUNC1_SBADDRMID 0x1000B /* SB Address Window Mid (b23:b16) */ -#define SBSDIO_FUNC1_SBADDRHIGH 0x1000C /* SB Address Window High (b31:b24) */ -#define SBSDIO_FUNC1_FRAMECTRL 0x1000D /* Frame Control (frame term/abort) */ -#define SBSDIO_FUNC1_CHIPCLKCSR 0x1000E /* ChipClockCSR (ALP/HT ctl/status) */ -#define SBSDIO_FUNC1_SDIOPULLUP 0x1000F /* SdioPullUp (on cmd, d0-d2) */ -#define SBSDIO_FUNC1_WFRAMEBCLO 0x10019 /* Write Frame Byte Count Low */ -#define SBSDIO_FUNC1_WFRAMEBCHI 0x1001A /* Write Frame Byte Count High */ -#define SBSDIO_FUNC1_RFRAMEBCLO 0x1001B /* Read Frame Byte Count Low */ -#define SBSDIO_FUNC1_RFRAMEBCHI 0x1001C /* Read Frame Byte Count High */ - -#define SBSDIO_FUNC1_MISC_REG_START 0x10000 /* f1 misc register start */ -#define SBSDIO_FUNC1_MISC_REG_LIMIT 0x1001C /* f1 misc register end */ - -/* SBSDIO_SPROM_CS */ -#define SBSDIO_SPROM_IDLE 0 -#define SBSDIO_SPROM_WRITE 1 -#define SBSDIO_SPROM_READ 2 -#define SBSDIO_SPROM_WEN 4 -#define SBSDIO_SPROM_WDS 7 -#define SBSDIO_SPROM_DONE 8 - -/* SBSDIO_SPROM_INFO */ -#define SROM_SZ_MASK 0x03 /* SROM size, 1: 4k, 2: 16k */ -#define SROM_BLANK 0x04 /* depreciated in corerev 6 */ -#define SROM_OTP 0x80 /* OTP present */ - -/* SBSDIO_CHIP_CTRL */ -#define SBSDIO_CHIP_CTRL_XTAL 0x01 /* or'd with onchip xtal_pu, - * 1: power on oscillator - * (for 4318 only) - */ -/* SBSDIO_WATERMARK */ -#define SBSDIO_WATERMARK_MASK 0x7f /* number of words - 1 for sd device - * to wait before sending data to host - */ - -/* SBSDIO_DEVICE_CTL */ -#define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when - * receiving CMD53 - */ -#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 /* 1: assertion of sdio interrupt is - * synchronous to the sdio clock - */ -#define SBSDIO_DEVCTL_CA_INT_ONLY 0x04 /* 1: mask all interrupts to host - * except the chipActive (rev 8) - */ -#define SBSDIO_DEVCTL_PADS_ISO 0x08 /* 1: isolate internal sdio signals, put - * external pads in tri-state; requires - * sdio bus power cycle to clear (rev 9) - */ -#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */ -#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ -#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ -#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ - - -/* SBSDIO_FUNC1_CHIPCLKCSR */ -#define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */ -#define SBSDIO_FORCE_HT 0x02 /* Force HT request to backplane */ -#define SBSDIO_FORCE_ILP 0x04 /* Force ILP request to backplane */ -#define SBSDIO_ALP_AVAIL_REQ 0x08 /* Make ALP ready (power up xtal) */ -#define SBSDIO_HT_AVAIL_REQ 0x10 /* Make HT ready (power up PLL) */ -#define SBSDIO_FORCE_HW_CLKREQ_OFF 0x20 /* Squelch clock requests from HW */ -#define SBSDIO_ALP_AVAIL 0x40 /* Status: ALP is ready */ -#define SBSDIO_HT_AVAIL 0x80 /* Status: HT is ready */ -/* In rev8, actual avail bits followed original docs */ -#define SBSDIO_Rev8_HT_AVAIL 0x40 -#define SBSDIO_Rev8_ALP_AVAIL 0x80 - -#define SBSDIO_AVBITS (SBSDIO_HT_AVAIL | SBSDIO_ALP_AVAIL) -#define SBSDIO_ALPAV(regval) ((regval) & SBSDIO_AVBITS) -#define SBSDIO_HTAV(regval) (((regval) & SBSDIO_AVBITS) == SBSDIO_AVBITS) -#define SBSDIO_ALPONLY(regval) (SBSDIO_ALPAV(regval) && !SBSDIO_HTAV(regval)) -#define SBSDIO_CLKAV(regval, alponly) (SBSDIO_ALPAV(regval) && \ - (alponly ? 1 : SBSDIO_HTAV(regval))) - -/* SBSDIO_FUNC1_SDIOPULLUP */ -#define SBSDIO_PULLUP_D0 0x01 /* Enable D0/MISO pullup */ -#define SBSDIO_PULLUP_D1 0x02 /* Enable D1/INT# pullup */ -#define SBSDIO_PULLUP_D2 0x04 /* Enable D2 pullup */ -#define SBSDIO_PULLUP_CMD 0x08 /* Enable CMD/MOSI pullup */ -#define SBSDIO_PULLUP_ALL 0x0f /* All valid bits */ - -/* function 1 OCP space */ -#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF /* sb offset addr is <= 15 bits, 32k */ -#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 -#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 /* with b15, maps to 32-bit SB access */ - -/* some duplication with sbsdpcmdev.h here */ -/* valid bits in SBSDIO_FUNC1_SBADDRxxx regs */ -#define SBSDIO_SBADDRLOW_MASK 0x80 /* Valid bits in SBADDRLOW */ -#define SBSDIO_SBADDRMID_MASK 0xff /* Valid bits in SBADDRMID */ -#define SBSDIO_SBADDRHIGH_MASK 0xffU /* Valid bits in SBADDRHIGH */ -#define SBSDIO_SBWINDOW_MASK 0xffff8000 /* Address bits from SBADDR regs */ - -/* direct(mapped) cis space */ -#define SBSDIO_CIS_BASE_COMMON 0x1000 /* MAPPED common CIS address */ -#define SBSDIO_CIS_SIZE_LIMIT 0x200 /* maximum bytes in one CIS */ -#define SBSDIO_OTP_CIS_SIZE_LIMIT 0x078 /* maximum bytes OTP CIS */ - -#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF /* cis offset addr is < 17 bits */ - -#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 /* manfid tuple length, include tuple, - * link bytes - */ - -/* indirect cis access (in sprom) */ -#define SBSDIO_SPROM_CIS_OFFSET 0x8 /* 8 control bytes first, CIS starts from - * 8th byte - */ - -#define SBSDIO_BYTEMODE_DATALEN_MAX 64 /* sdio byte mode: maximum length of one - * data comamnd - */ - -#define SBSDIO_CORE_ADDR_MASK 0x1FFFF /* sdio core function one address mask */ - -#endif /* _SBSDIO_H */ diff --git a/drivers/net/wireless/bcm4329/include/sbsdpcmdev.h b/drivers/net/wireless/bcm4329/include/sbsdpcmdev.h deleted file mode 100644 index 7c7c7e4de0f6..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbsdpcmdev.h +++ /dev/null @@ -1,288 +0,0 @@ -/* - * Broadcom SiliconBackplane SDIO/PCMCIA hardware-specific device core support - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbsdpcmdev.h,v 13.29.4.1.4.6.6.2 2008/12/31 21:16:51 Exp $ - */ - -#ifndef _sbsdpcmdev_h_ -#define _sbsdpcmdev_h_ - -/* cpp contortions to concatenate w/arg prescan */ -#ifndef PAD -#define _PADLINE(line) pad ## line -#define _XSTR(line) _PADLINE(line) -#define PAD _XSTR(__LINE__) -#endif /* PAD */ - - -typedef volatile struct { - dma64regs_t xmt; /* dma tx */ - uint32 PAD[2]; - dma64regs_t rcv; /* dma rx */ - uint32 PAD[2]; -} dma64p_t; - -/* dma64 sdiod corerev >= 1 */ -typedef volatile struct { - dma64p_t dma64regs[2]; - dma64diag_t dmafifo; /* DMA Diagnostic Regs, 0x280-0x28c */ - uint32 PAD[92]; -} sdiodma64_t; - -/* dma32 sdiod corerev == 0 */ -typedef volatile struct { - dma32regp_t dma32regs[2]; /* dma tx & rx, 0x200-0x23c */ - dma32diag_t dmafifo; /* DMA Diagnostic Regs, 0x240-0x24c */ - uint32 PAD[108]; -} sdiodma32_t; - -/* dma32 regs for pcmcia core */ -typedef volatile struct { - dma32regp_t dmaregs; /* DMA Regs, 0x200-0x21c, rev8 */ - dma32diag_t dmafifo; /* DMA Diagnostic Regs, 0x220-0x22c */ - uint32 PAD[116]; -} pcmdma32_t; - -/* core registers */ -typedef volatile struct { - uint32 corecontrol; /* CoreControl, 0x000, rev8 */ - uint32 corestatus; /* CoreStatus, 0x004, rev8 */ - uint32 PAD[1]; - uint32 biststatus; /* BistStatus, 0x00c, rev8 */ - - /* PCMCIA access */ - uint16 pcmciamesportaladdr; /* PcmciaMesPortalAddr, 0x010, rev8 */ - uint16 PAD[1]; - uint16 pcmciamesportalmask; /* PcmciaMesPortalMask, 0x014, rev8 */ - uint16 PAD[1]; - uint16 pcmciawrframebc; /* PcmciaWrFrameBC, 0x018, rev8 */ - uint16 PAD[1]; - uint16 pcmciaunderflowtimer; /* PcmciaUnderflowTimer, 0x01c, rev8 */ - uint16 PAD[1]; - - /* interrupt */ - uint32 intstatus; /* IntStatus, 0x020, rev8 */ - uint32 hostintmask; /* IntHostMask, 0x024, rev8 */ - uint32 intmask; /* IntSbMask, 0x028, rev8 */ - uint32 sbintstatus; /* SBIntStatus, 0x02c, rev8 */ - uint32 sbintmask; /* SBIntMask, 0x030, rev8 */ - uint32 PAD[3]; - uint32 tosbmailbox; /* ToSBMailbox, 0x040, rev8 */ - uint32 tohostmailbox; /* ToHostMailbox, 0x044, rev8 */ - uint32 tosbmailboxdata; /* ToSbMailboxData, 0x048, rev8 */ - uint32 tohostmailboxdata; /* ToHostMailboxData, 0x04c, rev8 */ - - /* synchronized access to registers in SDIO clock domain */ - uint32 sdioaccess; /* SdioAccess, 0x050, rev8 */ - uint32 PAD[3]; - - /* PCMCIA frame control */ - uint8 pcmciaframectrl; /* pcmciaFrameCtrl, 0x060, rev8 */ - uint8 PAD[3]; - uint8 pcmciawatermark; /* pcmciaWaterMark, 0x064, rev8 */ - uint8 PAD[155]; - - /* interrupt batching control */ - uint32 intrcvlazy; /* IntRcvLazy, 0x100, rev8 */ - uint32 PAD[3]; - - /* counters */ - uint32 cmd52rd; /* Cmd52RdCount, 0x110, rev8, SDIO: cmd52 reads */ - uint32 cmd52wr; /* Cmd52WrCount, 0x114, rev8, SDIO: cmd52 writes */ - uint32 cmd53rd; /* Cmd53RdCount, 0x118, rev8, SDIO: cmd53 reads */ - uint32 cmd53wr; /* Cmd53WrCount, 0x11c, rev8, SDIO: cmd53 writes */ - uint32 abort; /* AbortCount, 0x120, rev8, SDIO: aborts */ - uint32 datacrcerror; /* DataCrcErrorCount, 0x124, rev8, SDIO: frames w/bad CRC */ - uint32 rdoutofsync; /* RdOutOfSyncCount, 0x128, rev8, SDIO/PCMCIA: Rd Frm OOS */ - uint32 wroutofsync; /* RdOutOfSyncCount, 0x12c, rev8, SDIO/PCMCIA: Wr Frm OOS */ - uint32 writebusy; /* WriteBusyCount, 0x130, rev8, SDIO: dev asserted "busy" */ - uint32 readwait; /* ReadWaitCount, 0x134, rev8, SDIO: read: no data avail */ - uint32 readterm; /* ReadTermCount, 0x138, rev8, SDIO: rd frm terminates */ - uint32 writeterm; /* WriteTermCount, 0x13c, rev8, SDIO: wr frm terminates */ - uint32 PAD[40]; - uint32 clockctlstatus; /* ClockCtlStatus, 0x1e0, rev8 */ - uint32 PAD[7]; - - /* DMA engines */ - volatile union { - pcmdma32_t pcm32; - sdiodma32_t sdiod32; - sdiodma64_t sdiod64; - } dma; - - /* SDIO/PCMCIA CIS region */ - char cis[512]; /* 512 byte CIS, 0x400-0x5ff, rev6 */ - - /* PCMCIA function control registers */ - char pcmciafcr[256]; /* PCMCIA FCR, 0x600-6ff, rev6 */ - uint16 PAD[55]; - - /* PCMCIA backplane access */ - uint16 backplanecsr; /* BackplaneCSR, 0x76E, rev6 */ - uint16 backplaneaddr0; /* BackplaneAddr0, 0x770, rev6 */ - uint16 backplaneaddr1; /* BackplaneAddr1, 0x772, rev6 */ - uint16 backplaneaddr2; /* BackplaneAddr2, 0x774, rev6 */ - uint16 backplaneaddr3; /* BackplaneAddr3, 0x776, rev6 */ - uint16 backplanedata0; /* BackplaneData0, 0x778, rev6 */ - uint16 backplanedata1; /* BackplaneData1, 0x77a, rev6 */ - uint16 backplanedata2; /* BackplaneData2, 0x77c, rev6 */ - uint16 backplanedata3; /* BackplaneData3, 0x77e, rev6 */ - uint16 PAD[31]; - - /* sprom "size" & "blank" info */ - uint16 spromstatus; /* SPROMStatus, 0x7BE, rev2 */ - uint32 PAD[464]; - - /* Sonics SiliconBackplane registers */ - sbconfig_t sbconfig; /* SbConfig Regs, 0xf00-0xfff, rev8 */ -} sdpcmd_regs_t; - -/* corecontrol */ -#define CC_CISRDY (1 << 0) /* CIS Ready */ -#define CC_BPRESEN (1 << 1) /* CCCR RES signal causes backplane reset */ -#define CC_F2RDY (1 << 2) /* set CCCR IOR2 bit */ -#define CC_CLRPADSISO (1 << 3) /* clear SDIO pads isolation bit (rev 11) */ - -/* corestatus */ -#define CS_PCMCIAMODE (1 << 0) /* Device Mode; 0=SDIO, 1=PCMCIA */ -#define CS_SMARTDEV (1 << 1) /* 1=smartDev enabled */ -#define CS_F2ENABLED (1 << 2) /* 1=host has enabled the device */ - -#define PCMCIA_MES_PA_MASK 0x7fff /* PCMCIA Message Portal Address Mask */ -#define PCMCIA_MES_PM_MASK 0x7fff /* PCMCIA Message Portal Mask Mask */ -#define PCMCIA_WFBC_MASK 0xffff /* PCMCIA Write Frame Byte Count Mask */ -#define PCMCIA_UT_MASK 0x07ff /* PCMCIA Underflow Timer Mask */ - -/* intstatus */ -#define I_SMB_SW0 (1 << 0) /* To SB Mail S/W interrupt 0 */ -#define I_SMB_SW1 (1 << 1) /* To SB Mail S/W interrupt 1 */ -#define I_SMB_SW2 (1 << 2) /* To SB Mail S/W interrupt 2 */ -#define I_SMB_SW3 (1 << 3) /* To SB Mail S/W interrupt 3 */ -#define I_SMB_SW_MASK 0x0000000f /* To SB Mail S/W interrupts mask */ -#define I_SMB_SW_SHIFT 0 /* To SB Mail S/W interrupts shift */ -#define I_HMB_SW0 (1 << 4) /* To Host Mail S/W interrupt 0 */ -#define I_HMB_SW1 (1 << 5) /* To Host Mail S/W interrupt 1 */ -#define I_HMB_SW2 (1 << 6) /* To Host Mail S/W interrupt 2 */ -#define I_HMB_SW3 (1 << 7) /* To Host Mail S/W interrupt 3 */ -#define I_HMB_SW_MASK 0x000000f0 /* To Host Mail S/W interrupts mask */ -#define I_HMB_SW_SHIFT 4 /* To Host Mail S/W interrupts shift */ -#define I_WR_OOSYNC (1 << 8) /* Write Frame Out Of Sync */ -#define I_RD_OOSYNC (1 << 9) /* Read Frame Out Of Sync */ -#define I_PC (1 << 10) /* descriptor error */ -#define I_PD (1 << 11) /* data error */ -#define I_DE (1 << 12) /* Descriptor protocol Error */ -#define I_RU (1 << 13) /* Receive descriptor Underflow */ -#define I_RO (1 << 14) /* Receive fifo Overflow */ -#define I_XU (1 << 15) /* Transmit fifo Underflow */ -#define I_RI (1 << 16) /* Receive Interrupt */ -#define I_BUSPWR (1 << 17) /* SDIO Bus Power Change (rev 9) */ -#define I_XI (1 << 24) /* Transmit Interrupt */ -#define I_RF_TERM (1 << 25) /* Read Frame Terminate */ -#define I_WF_TERM (1 << 26) /* Write Frame Terminate */ -#define I_PCMCIA_XU (1 << 27) /* PCMCIA Transmit FIFO Underflow */ -#define I_SBINT (1 << 28) /* sbintstatus Interrupt */ -#define I_CHIPACTIVE (1 << 29) /* chip transitioned from doze to active state */ -#define I_SRESET (1 << 30) /* CCCR RES interrupt */ -#define I_IOE2 (1U << 31) /* CCCR IOE2 Bit Changed */ -#define I_ERRORS (I_PC | I_PD | I_DE | I_RU | I_RO | I_XU) /* DMA Errors */ -#define I_DMA (I_RI | I_XI | I_ERRORS) - -/* sbintstatus */ -#define I_SB_SERR (1 << 8) /* Backplane SError (write) */ -#define I_SB_RESPERR (1 << 9) /* Backplane Response Error (read) */ -#define I_SB_SPROMERR (1 << 10) /* Error accessing the sprom */ - -/* sdioaccess */ -#define SDA_DATA_MASK 0x000000ff /* Read/Write Data Mask */ -#define SDA_ADDR_MASK 0x000fff00 /* Read/Write Address Mask */ -#define SDA_ADDR_SHIFT 8 /* Read/Write Address Shift */ -#define SDA_WRITE 0x01000000 /* Write bit */ -#define SDA_READ 0x00000000 /* Write bit cleared for Read */ -#define SDA_BUSY 0x80000000 /* Busy bit */ - -/* sdioaccess-accessible register address spaces */ -#define SDA_CCCR_SPACE 0x000 /* sdioAccess CCCR register space */ -#define SDA_F1_FBR_SPACE 0x100 /* sdioAccess F1 FBR register space */ -#define SDA_F2_FBR_SPACE 0x200 /* sdioAccess F2 FBR register space */ -#define SDA_F1_REG_SPACE 0x300 /* sdioAccess F1 core-specific register space */ - -/* SDA_F1_REG_SPACE sdioaccess-accessible F1 reg space register offsets */ -#define SDA_CHIPCONTROLDATA 0x006 /* ChipControlData */ -#define SDA_CHIPCONTROLENAB 0x007 /* ChipControlEnable */ -#define SDA_F2WATERMARK 0x008 /* Function 2 Watermark */ -#define SDA_DEVICECONTROL 0x009 /* DeviceControl */ -#define SDA_SBADDRLOW 0x00a /* SbAddrLow */ -#define SDA_SBADDRMID 0x00b /* SbAddrMid */ -#define SDA_SBADDRHIGH 0x00c /* SbAddrHigh */ -#define SDA_FRAMECTRL 0x00d /* FrameCtrl */ -#define SDA_CHIPCLOCKCSR 0x00e /* ChipClockCSR */ -#define SDA_SDIOPULLUP 0x00f /* SdioPullUp */ -#define SDA_SDIOWRFRAMEBCLOW 0x019 /* SdioWrFrameBCLow */ -#define SDA_SDIOWRFRAMEBCHIGH 0x01a /* SdioWrFrameBCHigh */ -#define SDA_SDIORDFRAMEBCLOW 0x01b /* SdioRdFrameBCLow */ -#define SDA_SDIORDFRAMEBCHIGH 0x01c /* SdioRdFrameBCHigh */ - -/* SDA_F2WATERMARK */ -#define SDA_F2WATERMARK_MASK 0x7f /* F2Watermark Mask */ - -/* SDA_SBADDRLOW */ -#define SDA_SBADDRLOW_MASK 0x80 /* SbAddrLow Mask */ - -/* SDA_SBADDRMID */ -#define SDA_SBADDRMID_MASK 0xff /* SbAddrMid Mask */ - -/* SDA_SBADDRHIGH */ -#define SDA_SBADDRHIGH_MASK 0xff /* SbAddrHigh Mask */ - -/* SDA_FRAMECTRL */ -#define SFC_RF_TERM (1 << 0) /* Read Frame Terminate */ -#define SFC_WF_TERM (1 << 1) /* Write Frame Terminate */ -#define SFC_CRC4WOOS (1 << 2) /* HW reports CRC error for write out of sync */ -#define SFC_ABORTALL (1 << 3) /* Abort cancels all in-progress frames */ - -/* pcmciaframectrl */ -#define PFC_RF_TERM (1 << 0) /* Read Frame Terminate */ -#define PFC_WF_TERM (1 << 1) /* Write Frame Terminate */ - -/* intrcvlazy */ -#define IRL_TO_MASK 0x00ffffff /* timeout */ -#define IRL_FC_MASK 0xff000000 /* frame count */ -#define IRL_FC_SHIFT 24 /* frame count */ - -/* rx header */ -typedef volatile struct { - uint16 len; - uint16 flags; -} sdpcmd_rxh_t; - -/* rx header flags */ -#define RXF_CRC 0x0001 /* CRC error detected */ -#define RXF_WOOS 0x0002 /* write frame out of sync */ -#define RXF_WF_TERM 0x0004 /* write frame terminated */ -#define RXF_ABORT 0x0008 /* write frame aborted */ -#define RXF_DISCARD (RXF_CRC | RXF_WOOS | RXF_WF_TERM | RXF_ABORT) /* bad frame */ - -/* HW frame tag */ -#define SDPCM_FRAMETAG_LEN 4 /* HW frametag: 2 bytes len, 2 bytes check val */ - -#endif /* _sbsdpcmdev_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/sbsocram.h b/drivers/net/wireless/bcm4329/include/sbsocram.h deleted file mode 100644 index 5ede0b66d97f..000000000000 --- a/drivers/net/wireless/bcm4329/include/sbsocram.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * BCM47XX Sonics SiliconBackplane embedded ram core - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbsocram.h,v 13.9.162.2 2008/12/12 14:13:27 Exp $ - */ - - -#ifndef _SBSOCRAM_H -#define _SBSOCRAM_H - -#ifndef _LANGUAGE_ASSEMBLY - - -#ifndef PAD -#define _PADLINE(line) pad ## line -#define _XSTR(line) _PADLINE(line) -#define PAD _XSTR(__LINE__) -#endif - - -typedef volatile struct sbsocramregs { - uint32 coreinfo; - uint32 bwalloc; - uint32 extracoreinfo; - uint32 biststat; - uint32 bankidx; - uint32 standbyctrl; - - uint32 errlogstatus; - uint32 errlogaddr; - - uint32 cambankidx; - uint32 cambankstandbyctrl; - uint32 cambankpatchctrl; - uint32 cambankpatchtblbaseaddr; - uint32 cambankcmdreg; - uint32 cambankdatareg; - uint32 cambankmaskreg; - uint32 PAD[17]; - uint32 extmemconfig; - uint32 extmemparitycsr; - uint32 extmemparityerrdata; - uint32 extmemparityerrcnt; - uint32 extmemwrctrlandsize; - uint32 PAD[84]; - uint32 workaround; - uint32 pwrctl; -} sbsocramregs_t; - -#endif - - -#define SR_COREINFO 0x00 -#define SR_BWALLOC 0x04 -#define SR_BISTSTAT 0x0c -#define SR_BANKINDEX 0x10 -#define SR_BANKSTBYCTL 0x14 -#define SR_PWRCTL 0x1e8 - - -#define SRCI_PT_MASK 0x00070000 -#define SRCI_PT_SHIFT 16 - -#define SRCI_PT_OCP_OCP 0 -#define SRCI_PT_AXI_OCP 1 -#define SRCI_PT_ARM7AHB_OCP 2 -#define SRCI_PT_CM3AHB_OCP 3 -#define SRCI_PT_AXI_AXI 4 -#define SRCI_PT_AHB_AXI 5 - -#define SRCI_LSS_MASK 0x00f00000 -#define SRCI_LSS_SHIFT 20 -#define SRCI_LRS_MASK 0x0f000000 -#define SRCI_LRS_SHIFT 24 - - -#define SRCI_MS0_MASK 0xf -#define SR_MS0_BASE 16 - - -#define SRCI_ROMNB_MASK 0xf000 -#define SRCI_ROMNB_SHIFT 12 -#define SRCI_ROMBSZ_MASK 0xf00 -#define SRCI_ROMBSZ_SHIFT 8 -#define SRCI_SRNB_MASK 0xf0 -#define SRCI_SRNB_SHIFT 4 -#define SRCI_SRBSZ_MASK 0xf -#define SRCI_SRBSZ_SHIFT 0 - -#define SR_BSZ_BASE 14 - - -#define SRSC_SBYOVR_MASK 0x80000000 -#define SRSC_SBYOVR_SHIFT 31 -#define SRSC_SBYOVRVAL_MASK 0x60000000 -#define SRSC_SBYOVRVAL_SHIFT 29 -#define SRSC_SBYEN_MASK 0x01000000 -#define SRSC_SBYEN_SHIFT 24 - - -#define SRPC_PMU_STBYDIS_MASK 0x00000010 -#define SRPC_PMU_STBYDIS_SHIFT 4 -#define SRPC_STBYOVRVAL_MASK 0x00000008 -#define SRPC_STBYOVRVAL_SHIFT 3 -#define SRPC_STBYOVR_MASK 0x00000007 -#define SRPC_STBYOVR_SHIFT 0 - - -#define SRECC_NUM_BANKS_MASK 0x000000F0 -#define SRECC_NUM_BANKS_SHIFT 4 -#define SRECC_BANKSIZE_MASK 0x0000000F -#define SRECC_BANKSIZE_SHIFT 0 - -#define SRECC_BANKSIZE(value) (1 << (value)) - - -#define SRCBPC_PATCHENABLE 0x80000000 - -#define SRP_ADDRESS 0x0001FFFC -#define SRP_VALID 0x8000 - - -#define SRCMD_WRITE 0x00020000 -#define SRCMD_READ 0x00010000 -#define SRCMD_DONE 0x80000000 - -#define SRCMD_DONE_DLY 1000 - - -#endif diff --git a/drivers/net/wireless/bcm4329/include/sdio.h b/drivers/net/wireless/bcm4329/include/sdio.h deleted file mode 100644 index 280cb845fb04..000000000000 --- a/drivers/net/wireless/bcm4329/include/sdio.h +++ /dev/null @@ -1,566 +0,0 @@ -/* - * SDIO spec header file - * Protocol and standard (common) device definitions - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sdio.h,v 13.24.4.1.4.1.16.1 2009/08/12 01:08:02 Exp $ - */ - -#ifndef _SDIO_H -#define _SDIO_H - - -/* CCCR structure for function 0 */ -typedef volatile struct { - uint8 cccr_sdio_rev; /* RO, cccr and sdio revision */ - uint8 sd_rev; /* RO, sd spec revision */ - uint8 io_en; /* I/O enable */ - uint8 io_rdy; /* I/O ready reg */ - uint8 intr_ctl; /* Master and per function interrupt enable control */ - uint8 intr_status; /* RO, interrupt pending status */ - uint8 io_abort; /* read/write abort or reset all functions */ - uint8 bus_inter; /* bus interface control */ - uint8 capability; /* RO, card capability */ - - uint8 cis_base_low; /* 0x9 RO, common CIS base address, LSB */ - uint8 cis_base_mid; - uint8 cis_base_high; /* 0xB RO, common CIS base address, MSB */ - - /* suspend/resume registers */ - uint8 bus_suspend; /* 0xC */ - uint8 func_select; /* 0xD */ - uint8 exec_flag; /* 0xE */ - uint8 ready_flag; /* 0xF */ - - uint8 fn0_blk_size[2]; /* 0x10(LSB), 0x11(MSB) */ - - uint8 power_control; /* 0x12 (SDIO version 1.10) */ - - uint8 speed_control; /* 0x13 */ -} sdio_regs_t; - -/* SDIO Device CCCR offsets */ -#define SDIOD_CCCR_REV 0x00 -#define SDIOD_CCCR_SDREV 0x01 -#define SDIOD_CCCR_IOEN 0x02 -#define SDIOD_CCCR_IORDY 0x03 -#define SDIOD_CCCR_INTEN 0x04 -#define SDIOD_CCCR_INTPEND 0x05 -#define SDIOD_CCCR_IOABORT 0x06 -#define SDIOD_CCCR_BICTRL 0x07 -#define SDIOD_CCCR_CAPABLITIES 0x08 -#define SDIOD_CCCR_CISPTR_0 0x09 -#define SDIOD_CCCR_CISPTR_1 0x0A -#define SDIOD_CCCR_CISPTR_2 0x0B -#define SDIOD_CCCR_BUSSUSP 0x0C -#define SDIOD_CCCR_FUNCSEL 0x0D -#define SDIOD_CCCR_EXECFLAGS 0x0E -#define SDIOD_CCCR_RDYFLAGS 0x0F -#define SDIOD_CCCR_BLKSIZE_0 0x10 -#define SDIOD_CCCR_BLKSIZE_1 0x11 -#define SDIOD_CCCR_POWER_CONTROL 0x12 -#define SDIOD_CCCR_SPEED_CONTROL 0x13 - -/* Broadcom extensions (corerev >= 1) */ -#define SDIOD_CCCR_BRCM_SEPINT 0xf2 - -/* cccr_sdio_rev */ -#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */ -#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */ - -/* sd_rev */ -#define SD_REV_PHY_MASK 0x0f /* SD format version number */ - -/* io_en */ -#define SDIO_FUNC_ENABLE_1 0x02 /* function 1 I/O enable */ -#define SDIO_FUNC_ENABLE_2 0x04 /* function 2 I/O enable */ - -/* io_rdys */ -#define SDIO_FUNC_READY_1 0x02 /* function 1 I/O ready */ -#define SDIO_FUNC_READY_2 0x04 /* function 2 I/O ready */ - -/* intr_ctl */ -#define INTR_CTL_MASTER_EN 0x1 /* interrupt enable master */ -#define INTR_CTL_FUNC1_EN 0x2 /* interrupt enable for function 1 */ -#define INTR_CTL_FUNC2_EN 0x4 /* interrupt enable for function 2 */ - -/* intr_status */ -#define INTR_STATUS_FUNC1 0x2 /* interrupt pending for function 1 */ -#define INTR_STATUS_FUNC2 0x4 /* interrupt pending for function 2 */ - -/* io_abort */ -#define IO_ABORT_RESET_ALL 0x08 /* I/O card reset */ -#define IO_ABORT_FUNC_MASK 0x07 /* abort selction: function x */ - -/* bus_inter */ -#define BUS_CARD_DETECT_DIS 0x80 /* Card Detect disable */ -#define BUS_SPI_CONT_INTR_CAP 0x40 /* support continuous SPI interrupt */ -#define BUS_SPI_CONT_INTR_EN 0x20 /* continuous SPI interrupt enable */ -#define BUS_SD_DATA_WIDTH_MASK 0x03 /* bus width mask */ -#define BUS_SD_DATA_WIDTH_4BIT 0x02 /* bus width 4-bit mode */ -#define BUS_SD_DATA_WIDTH_1BIT 0x00 /* bus width 1-bit mode */ - -/* capability */ -#define SDIO_CAP_4BLS 0x80 /* 4-bit support for low speed card */ -#define SDIO_CAP_LSC 0x40 /* low speed card */ -#define SDIO_CAP_E4MI 0x20 /* enable interrupt between block of data in 4-bit mode */ -#define SDIO_CAP_S4MI 0x10 /* support interrupt between block of data in 4-bit mode */ -#define SDIO_CAP_SBS 0x08 /* support suspend/resume */ -#define SDIO_CAP_SRW 0x04 /* support read wait */ -#define SDIO_CAP_SMB 0x02 /* support multi-block transfer */ -#define SDIO_CAP_SDC 0x01 /* Support Direct commands during multi-byte transfer */ - -/* power_control */ -#define SDIO_POWER_SMPC 0x01 /* supports master power control (RO) */ -#define SDIO_POWER_EMPC 0x02 /* enable master power control (allow > 200mA) (RW) */ - -/* speed_control (control device entry into high-speed clocking mode) */ -#define SDIO_SPEED_SHS 0x01 /* supports high-speed [clocking] mode (RO) */ -#define SDIO_SPEED_EHS 0x02 /* enable high-speed [clocking] mode (RW) */ - -/* brcm sepint */ -#define SDIO_SEPINT_MASK 0x01 /* route sdpcmdev intr onto separate pad (chip-specific) */ -#define SDIO_SEPINT_OE 0x02 /* 1 asserts output enable for above pad */ -#define SDIO_SEPINT_ACT_HI 0x04 /* use active high interrupt level instead of active low */ - -/* FBR structure for function 1-7, FBR addresses and register offsets */ -typedef volatile struct { - uint8 devctr; /* device interface, CSA control */ - uint8 ext_dev; /* extended standard I/O device type code */ - uint8 pwr_sel; /* power selection support */ - uint8 PAD[6]; /* reserved */ - - uint8 cis_low; /* CIS LSB */ - uint8 cis_mid; - uint8 cis_high; /* CIS MSB */ - uint8 csa_low; /* code storage area, LSB */ - uint8 csa_mid; - uint8 csa_high; /* code storage area, MSB */ - uint8 csa_dat_win; /* data access window to function */ - - uint8 fnx_blk_size[2]; /* block size, little endian */ -} sdio_fbr_t; - -/* Maximum number of I/O funcs */ -#define SDIOD_MAX_IOFUNCS 7 - -/* SDIO Device FBR Start Address */ -#define SDIOD_FBR_STARTADDR 0x100 - -/* SDIO Device FBR Size */ -#define SDIOD_FBR_SIZE 0x100 - -/* Macro to calculate FBR register base */ -#define SDIOD_FBR_BASE(n) ((n) * 0x100) - -/* Function register offsets */ -#define SDIOD_FBR_DEVCTR 0x00 /* basic info for function */ -#define SDIOD_FBR_EXT_DEV 0x01 /* extended I/O device code */ -#define SDIOD_FBR_PWR_SEL 0x02 /* power selection bits */ - -/* SDIO Function CIS ptr offset */ -#define SDIOD_FBR_CISPTR_0 0x09 -#define SDIOD_FBR_CISPTR_1 0x0A -#define SDIOD_FBR_CISPTR_2 0x0B - -/* Code Storage Area pointer */ -#define SDIOD_FBR_CSA_ADDR_0 0x0C -#define SDIOD_FBR_CSA_ADDR_1 0x0D -#define SDIOD_FBR_CSA_ADDR_2 0x0E -#define SDIOD_FBR_CSA_DATA 0x0F - -/* SDIO Function I/O Block Size */ -#define SDIOD_FBR_BLKSIZE_0 0x10 -#define SDIOD_FBR_BLKSIZE_1 0x11 - -/* devctr */ -#define SDIOD_FBR_DEVCTR_DIC 0x0f /* device interface code */ -#define SDIOD_FBR_DECVTR_CSA 0x40 /* CSA support flag */ -#define SDIOD_FBR_DEVCTR_CSA_EN 0x80 /* CSA enabled */ -/* interface codes */ -#define SDIOD_DIC_NONE 0 /* SDIO standard interface is not supported */ -#define SDIOD_DIC_UART 1 -#define SDIOD_DIC_BLUETOOTH_A 2 -#define SDIOD_DIC_BLUETOOTH_B 3 -#define SDIOD_DIC_GPS 4 -#define SDIOD_DIC_CAMERA 5 -#define SDIOD_DIC_PHS 6 -#define SDIOD_DIC_WLAN 7 -#define SDIOD_DIC_EXT 0xf /* extended device interface, read ext_dev register */ - -/* pwr_sel */ -#define SDIOD_PWR_SEL_SPS 0x01 /* supports power selection */ -#define SDIOD_PWR_SEL_EPS 0x02 /* enable power selection (low-current mode) */ - -/* misc defines */ -#define SDIO_FUNC_0 0 -#define SDIO_FUNC_1 1 -#define SDIO_FUNC_2 2 -#define SDIO_FUNC_3 3 -#define SDIO_FUNC_4 4 -#define SDIO_FUNC_5 5 -#define SDIO_FUNC_6 6 -#define SDIO_FUNC_7 7 - -#define SD_CARD_TYPE_UNKNOWN 0 /* bad type or unrecognized */ -#define SD_CARD_TYPE_IO 1 /* IO only card */ -#define SD_CARD_TYPE_MEMORY 2 /* memory only card */ -#define SD_CARD_TYPE_COMBO 3 /* IO and memory combo card */ - -#define SDIO_MAX_BLOCK_SIZE 2048 /* maximum block size for block mode operation */ -#define SDIO_MIN_BLOCK_SIZE 1 /* minimum block size for block mode operation */ - -/* Card registers: status bit position */ -#define CARDREG_STATUS_BIT_OUTOFRANGE 31 -#define CARDREG_STATUS_BIT_COMCRCERROR 23 -#define CARDREG_STATUS_BIT_ILLEGALCOMMAND 22 -#define CARDREG_STATUS_BIT_ERROR 19 -#define CARDREG_STATUS_BIT_IOCURRENTSTATE3 12 -#define CARDREG_STATUS_BIT_IOCURRENTSTATE2 11 -#define CARDREG_STATUS_BIT_IOCURRENTSTATE1 10 -#define CARDREG_STATUS_BIT_IOCURRENTSTATE0 9 -#define CARDREG_STATUS_BIT_FUN_NUM_ERROR 4 - - - -#define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */ -#define SD_CMD_SEND_OPCOND 1 -#define SD_CMD_MMC_SET_RCA 3 -#define SD_CMD_IO_SEND_OP_COND 5 /* mandatory for SDIO */ -#define SD_CMD_SELECT_DESELECT_CARD 7 -#define SD_CMD_SEND_CSD 9 -#define SD_CMD_SEND_CID 10 -#define SD_CMD_STOP_TRANSMISSION 12 -#define SD_CMD_SEND_STATUS 13 -#define SD_CMD_GO_INACTIVE_STATE 15 -#define SD_CMD_SET_BLOCKLEN 16 -#define SD_CMD_READ_SINGLE_BLOCK 17 -#define SD_CMD_READ_MULTIPLE_BLOCK 18 -#define SD_CMD_WRITE_BLOCK 24 -#define SD_CMD_WRITE_MULTIPLE_BLOCK 25 -#define SD_CMD_PROGRAM_CSD 27 -#define SD_CMD_SET_WRITE_PROT 28 -#define SD_CMD_CLR_WRITE_PROT 29 -#define SD_CMD_SEND_WRITE_PROT 30 -#define SD_CMD_ERASE_WR_BLK_START 32 -#define SD_CMD_ERASE_WR_BLK_END 33 -#define SD_CMD_ERASE 38 -#define SD_CMD_LOCK_UNLOCK 42 -#define SD_CMD_IO_RW_DIRECT 52 /* mandatory for SDIO */ -#define SD_CMD_IO_RW_EXTENDED 53 /* mandatory for SDIO */ -#define SD_CMD_APP_CMD 55 -#define SD_CMD_GEN_CMD 56 -#define SD_CMD_READ_OCR 58 -#define SD_CMD_CRC_ON_OFF 59 /* mandatory for SDIO */ -#define SD_ACMD_SD_STATUS 13 -#define SD_ACMD_SEND_NUM_WR_BLOCKS 22 -#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT 23 -#define SD_ACMD_SD_SEND_OP_COND 41 -#define SD_ACMD_SET_CLR_CARD_DETECT 42 -#define SD_ACMD_SEND_SCR 51 - -/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */ -#define SD_IO_OP_READ 0 /* Read_Write: Read */ -#define SD_IO_OP_WRITE 1 /* Read_Write: Write */ -#define SD_IO_RW_NORMAL 0 /* no RAW */ -#define SD_IO_RW_RAW 1 /* RAW */ -#define SD_IO_BYTE_MODE 0 /* Byte Mode */ -#define SD_IO_BLOCK_MODE 1 /* BlockMode */ -#define SD_IO_FIXED_ADDRESS 0 /* fix Address */ -#define SD_IO_INCREMENT_ADDRESS 1 /* IncrementAddress */ - -/* build SD_CMD_IO_RW_DIRECT Argument */ -#define SDIO_IO_RW_DIRECT_ARG(rw, raw, func, addr, data) \ - ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((raw) & 1) << 27) | \ - (((addr) & 0x1FFFF) << 9) | ((data) & 0xFF)) - -/* build SD_CMD_IO_RW_EXTENDED Argument */ -#define SDIO_IO_RW_EXTENDED_ARG(rw, blk, func, addr, inc_addr, count) \ - ((((rw) & 1) << 31) | (((func) & 0x7) << 28) | (((blk) & 1) << 27) | \ - (((inc_addr) & 1) << 26) | (((addr) & 0x1FFFF) << 9) | ((count) & 0x1FF)) - -/* SDIO response parameters */ -#define SD_RSP_NO_NONE 0 -#define SD_RSP_NO_1 1 -#define SD_RSP_NO_2 2 -#define SD_RSP_NO_3 3 -#define SD_RSP_NO_4 4 -#define SD_RSP_NO_5 5 -#define SD_RSP_NO_6 6 - - /* Modified R6 response (to CMD3) */ -#define SD_RSP_MR6_COM_CRC_ERROR 0x8000 -#define SD_RSP_MR6_ILLEGAL_COMMAND 0x4000 -#define SD_RSP_MR6_ERROR 0x2000 - - /* Modified R1 in R4 Response (to CMD5) */ -#define SD_RSP_MR1_SBIT 0x80 -#define SD_RSP_MR1_PARAMETER_ERROR 0x40 -#define SD_RSP_MR1_RFU5 0x20 -#define SD_RSP_MR1_FUNC_NUM_ERROR 0x10 -#define SD_RSP_MR1_COM_CRC_ERROR 0x08 -#define SD_RSP_MR1_ILLEGAL_COMMAND 0x04 -#define SD_RSP_MR1_RFU1 0x02 -#define SD_RSP_MR1_IDLE_STATE 0x01 - - /* R5 response (to CMD52 and CMD53) */ -#define SD_RSP_R5_COM_CRC_ERROR 0x80 -#define SD_RSP_R5_ILLEGAL_COMMAND 0x40 -#define SD_RSP_R5_IO_CURRENTSTATE1 0x20 -#define SD_RSP_R5_IO_CURRENTSTATE0 0x10 -#define SD_RSP_R5_ERROR 0x08 -#define SD_RSP_R5_RFU 0x04 -#define SD_RSP_R5_FUNC_NUM_ERROR 0x02 -#define SD_RSP_R5_OUT_OF_RANGE 0x01 - -#define SD_RSP_R5_ERRBITS 0xCB - - -/* ------------------------------------------------ - * SDIO Commands and responses - * - * I/O only commands are: - * CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53 - * ------------------------------------------------ - */ - -/* SDIO Commands */ -#define SDIOH_CMD_0 0 -#define SDIOH_CMD_3 3 -#define SDIOH_CMD_5 5 -#define SDIOH_CMD_7 7 -#define SDIOH_CMD_15 15 -#define SDIOH_CMD_52 52 -#define SDIOH_CMD_53 53 -#define SDIOH_CMD_59 59 - -/* SDIO Command Responses */ -#define SDIOH_RSP_NONE 0 -#define SDIOH_RSP_R1 1 -#define SDIOH_RSP_R2 2 -#define SDIOH_RSP_R3 3 -#define SDIOH_RSP_R4 4 -#define SDIOH_RSP_R5 5 -#define SDIOH_RSP_R6 6 - -/* - * SDIO Response Error flags - */ -#define SDIOH_RSP5_ERROR_FLAGS 0xCB - -/* ------------------------------------------------ - * SDIO Command structures. I/O only commands are: - * - * CMD0, CMD3, CMD5, CMD7, CMD15, CMD52, CMD53 - * ------------------------------------------------ - */ - -#define CMD5_OCR_M BITFIELD_MASK(24) -#define CMD5_OCR_S 0 - -#define CMD7_RCA_M BITFIELD_MASK(16) -#define CMD7_RCA_S 16 - -#define CMD_15_RCA_M BITFIELD_MASK(16) -#define CMD_15_RCA_S 16 - -#define CMD52_DATA_M BITFIELD_MASK(8) /* Bits [7:0] - Write Data/Stuff bits of CMD52 - */ -#define CMD52_DATA_S 0 -#define CMD52_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */ -#define CMD52_REG_ADDR_S 9 -#define CMD52_RAW_M BITFIELD_MASK(1) /* Bit 27 - Read after Write flag */ -#define CMD52_RAW_S 27 -#define CMD52_FUNCTION_M BITFIELD_MASK(3) /* Bits [30:28] - Function number */ -#define CMD52_FUNCTION_S 28 -#define CMD52_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */ -#define CMD52_RW_FLAG_S 31 - - -#define CMD53_BYTE_BLK_CNT_M BITFIELD_MASK(9) /* Bits [8:0] - Byte/Block Count of CMD53 */ -#define CMD53_BYTE_BLK_CNT_S 0 -#define CMD53_REG_ADDR_M BITFIELD_MASK(17) /* Bits [25:9] - register address */ -#define CMD53_REG_ADDR_S 9 -#define CMD53_OP_CODE_M BITFIELD_MASK(1) /* Bit 26 - R/W Operation Code */ -#define CMD53_OP_CODE_S 26 -#define CMD53_BLK_MODE_M BITFIELD_MASK(1) /* Bit 27 - Block Mode */ -#define CMD53_BLK_MODE_S 27 -#define CMD53_FUNCTION_M BITFIELD_MASK(3) /* Bits [30:28] - Function number */ -#define CMD53_FUNCTION_S 28 -#define CMD53_RW_FLAG_M BITFIELD_MASK(1) /* Bit 31 - R/W flag */ -#define CMD53_RW_FLAG_S 31 - -/* ------------------------------------------------------ - * SDIO Command Response structures for SD1 and SD4 modes - * ----------------------------------------------------- - */ -#define RSP4_IO_OCR_M BITFIELD_MASK(24) /* Bits [23:0] - Card's OCR Bits [23:0] */ -#define RSP4_IO_OCR_S 0 -#define RSP4_STUFF_M BITFIELD_MASK(3) /* Bits [26:24] - Stuff bits */ -#define RSP4_STUFF_S 24 -#define RSP4_MEM_PRESENT_M BITFIELD_MASK(1) /* Bit 27 - Memory present */ -#define RSP4_MEM_PRESENT_S 27 -#define RSP4_NUM_FUNCS_M BITFIELD_MASK(3) /* Bits [30:28] - Number of I/O funcs */ -#define RSP4_NUM_FUNCS_S 28 -#define RSP4_CARD_READY_M BITFIELD_MASK(1) /* Bit 31 - SDIO card ready */ -#define RSP4_CARD_READY_S 31 - -#define RSP6_STATUS_M BITFIELD_MASK(16) /* Bits [15:0] - Card status bits [19,22,23,12:0] - */ -#define RSP6_STATUS_S 0 -#define RSP6_IO_RCA_M BITFIELD_MASK(16) /* Bits [31:16] - RCA bits[31-16] */ -#define RSP6_IO_RCA_S 16 - -#define RSP1_AKE_SEQ_ERROR_M BITFIELD_MASK(1) /* Bit 3 - Authentication seq error */ -#define RSP1_AKE_SEQ_ERROR_S 3 -#define RSP1_APP_CMD_M BITFIELD_MASK(1) /* Bit 5 - Card expects ACMD */ -#define RSP1_APP_CMD_S 5 -#define RSP1_READY_FOR_DATA_M BITFIELD_MASK(1) /* Bit 8 - Ready for data (buff empty) */ -#define RSP1_READY_FOR_DATA_S 8 -#define RSP1_CURR_STATE_M BITFIELD_MASK(4) /* Bits [12:9] - State of card - * when Cmd was received - */ -#define RSP1_CURR_STATE_S 9 -#define RSP1_EARSE_RESET_M BITFIELD_MASK(1) /* Bit 13 - Erase seq cleared */ -#define RSP1_EARSE_RESET_S 13 -#define RSP1_CARD_ECC_DISABLE_M BITFIELD_MASK(1) /* Bit 14 - Card ECC disabled */ -#define RSP1_CARD_ECC_DISABLE_S 14 -#define RSP1_WP_ERASE_SKIP_M BITFIELD_MASK(1) /* Bit 15 - Partial blocks erased due to W/P */ -#define RSP1_WP_ERASE_SKIP_S 15 -#define RSP1_CID_CSD_OVERW_M BITFIELD_MASK(1) /* Bit 16 - Illegal write to CID or R/O bits - * of CSD - */ -#define RSP1_CID_CSD_OVERW_S 16 -#define RSP1_ERROR_M BITFIELD_MASK(1) /* Bit 19 - General/Unknown error */ -#define RSP1_ERROR_S 19 -#define RSP1_CC_ERROR_M BITFIELD_MASK(1) /* Bit 20 - Internal Card Control error */ -#define RSP1_CC_ERROR_S 20 -#define RSP1_CARD_ECC_FAILED_M BITFIELD_MASK(1) /* Bit 21 - Card internal ECC failed - * to correct data - */ -#define RSP1_CARD_ECC_FAILED_S 21 -#define RSP1_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 22 - Cmd not legal for the card state */ -#define RSP1_ILLEGAL_CMD_S 22 -#define RSP1_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 23 - CRC check of previous command failed - */ -#define RSP1_COM_CRC_ERROR_S 23 -#define RSP1_LOCK_UNLOCK_FAIL_M BITFIELD_MASK(1) /* Bit 24 - Card lock-unlock Cmd Seq error */ -#define RSP1_LOCK_UNLOCK_FAIL_S 24 -#define RSP1_CARD_LOCKED_M BITFIELD_MASK(1) /* Bit 25 - Card locked by the host */ -#define RSP1_CARD_LOCKED_S 25 -#define RSP1_WP_VIOLATION_M BITFIELD_MASK(1) /* Bit 26 - Attempt to program - * write-protected blocks - */ -#define RSP1_WP_VIOLATION_S 26 -#define RSP1_ERASE_PARAM_M BITFIELD_MASK(1) /* Bit 27 - Invalid erase blocks */ -#define RSP1_ERASE_PARAM_S 27 -#define RSP1_ERASE_SEQ_ERR_M BITFIELD_MASK(1) /* Bit 28 - Erase Cmd seq error */ -#define RSP1_ERASE_SEQ_ERR_S 28 -#define RSP1_BLK_LEN_ERR_M BITFIELD_MASK(1) /* Bit 29 - Block length error */ -#define RSP1_BLK_LEN_ERR_S 29 -#define RSP1_ADDR_ERR_M BITFIELD_MASK(1) /* Bit 30 - Misaligned address */ -#define RSP1_ADDR_ERR_S 30 -#define RSP1_OUT_OF_RANGE_M BITFIELD_MASK(1) /* Bit 31 - Cmd arg was out of range */ -#define RSP1_OUT_OF_RANGE_S 31 - - -#define RSP5_DATA_M BITFIELD_MASK(8) /* Bits [0:7] - data */ -#define RSP5_DATA_S 0 -#define RSP5_FLAGS_M BITFIELD_MASK(8) /* Bit [15:8] - Rsp flags */ -#define RSP5_FLAGS_S 8 -#define RSP5_STUFF_M BITFIELD_MASK(16) /* Bits [31:16] - Stuff bits */ -#define RSP5_STUFF_S 16 - -/* ---------------------------------------------- - * SDIO Command Response structures for SPI mode - * ---------------------------------------------- - */ -#define SPIRSP4_IO_OCR_M BITFIELD_MASK(16) /* Bits [15:0] - Card's OCR Bits [23:8] */ -#define SPIRSP4_IO_OCR_S 0 -#define SPIRSP4_STUFF_M BITFIELD_MASK(3) /* Bits [18:16] - Stuff bits */ -#define SPIRSP4_STUFF_S 16 -#define SPIRSP4_MEM_PRESENT_M BITFIELD_MASK(1) /* Bit 19 - Memory present */ -#define SPIRSP4_MEM_PRESENT_S 19 -#define SPIRSP4_NUM_FUNCS_M BITFIELD_MASK(3) /* Bits [22:20] - Number of I/O funcs */ -#define SPIRSP4_NUM_FUNCS_S 20 -#define SPIRSP4_CARD_READY_M BITFIELD_MASK(1) /* Bit 23 - SDIO card ready */ -#define SPIRSP4_CARD_READY_S 23 -#define SPIRSP4_IDLE_STATE_M BITFIELD_MASK(1) /* Bit 24 - idle state */ -#define SPIRSP4_IDLE_STATE_S 24 -#define SPIRSP4_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 26 - Illegal Cmd error */ -#define SPIRSP4_ILLEGAL_CMD_S 26 -#define SPIRSP4_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 27 - COM CRC error */ -#define SPIRSP4_COM_CRC_ERROR_S 27 -#define SPIRSP4_FUNC_NUM_ERROR_M BITFIELD_MASK(1) /* Bit 28 - Function number error - */ -#define SPIRSP4_FUNC_NUM_ERROR_S 28 -#define SPIRSP4_PARAM_ERROR_M BITFIELD_MASK(1) /* Bit 30 - Parameter Error Bit */ -#define SPIRSP4_PARAM_ERROR_S 30 -#define SPIRSP4_START_BIT_M BITFIELD_MASK(1) /* Bit 31 - Start Bit */ -#define SPIRSP4_START_BIT_S 31 - -#define SPIRSP5_DATA_M BITFIELD_MASK(8) /* Bits [23:16] - R/W Data */ -#define SPIRSP5_DATA_S 16 -#define SPIRSP5_IDLE_STATE_M BITFIELD_MASK(1) /* Bit 24 - Idle state */ -#define SPIRSP5_IDLE_STATE_S 24 -#define SPIRSP5_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 26 - Illegal Cmd error */ -#define SPIRSP5_ILLEGAL_CMD_S 26 -#define SPIRSP5_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 27 - COM CRC error */ -#define SPIRSP5_COM_CRC_ERROR_S 27 -#define SPIRSP5_FUNC_NUM_ERROR_M BITFIELD_MASK(1) /* Bit 28 - Function number error - */ -#define SPIRSP5_FUNC_NUM_ERROR_S 28 -#define SPIRSP5_PARAM_ERROR_M BITFIELD_MASK(1) /* Bit 30 - Parameter Error Bit */ -#define SPIRSP5_PARAM_ERROR_S 30 -#define SPIRSP5_START_BIT_M BITFIELD_MASK(1) /* Bit 31 - Start Bit */ -#define SPIRSP5_START_BIT_S 31 - -/* RSP6 card status format; Pg 68 Physical Layer spec v 1.10 */ -#define RSP6STAT_AKE_SEQ_ERROR_M BITFIELD_MASK(1) /* Bit 3 - Authentication seq error - */ -#define RSP6STAT_AKE_SEQ_ERROR_S 3 -#define RSP6STAT_APP_CMD_M BITFIELD_MASK(1) /* Bit 5 - Card expects ACMD */ -#define RSP6STAT_APP_CMD_S 5 -#define RSP6STAT_READY_FOR_DATA_M BITFIELD_MASK(1) /* Bit 8 - Ready for data - * (buff empty) - */ -#define RSP6STAT_READY_FOR_DATA_S 8 -#define RSP6STAT_CURR_STATE_M BITFIELD_MASK(4) /* Bits [12:9] - Card state at - * Cmd reception - */ -#define RSP6STAT_CURR_STATE_S 9 -#define RSP6STAT_ERROR_M BITFIELD_MASK(1) /* Bit 13 - General/Unknown error Bit 19 - */ -#define RSP6STAT_ERROR_S 13 -#define RSP6STAT_ILLEGAL_CMD_M BITFIELD_MASK(1) /* Bit 14 - Illegal cmd for - * card state Bit 22 - */ -#define RSP6STAT_ILLEGAL_CMD_S 14 -#define RSP6STAT_COM_CRC_ERROR_M BITFIELD_MASK(1) /* Bit 15 - CRC previous command - * failed Bit 23 - */ -#define RSP6STAT_COM_CRC_ERROR_S 15 - -#define SDIOH_XFER_TYPE_READ SD_IO_OP_READ -#define SDIOH_XFER_TYPE_WRITE SD_IO_OP_WRITE - -#endif /* _SDIO_H */ diff --git a/drivers/net/wireless/bcm4329/include/sdioh.h b/drivers/net/wireless/bcm4329/include/sdioh.h deleted file mode 100644 index 8123452eac2b..000000000000 --- a/drivers/net/wireless/bcm4329/include/sdioh.h +++ /dev/null @@ -1,299 +0,0 @@ -/* - * SDIO Host Controller Spec header file - * Register map and definitions for the Standard Host Controller - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sdioh.h,v 13.13.18.1.16.3 2009/12/08 22:34:21 Exp $ - */ - -#ifndef _SDIOH_H -#define _SDIOH_H - -#define SD_SysAddr 0x000 -#define SD_BlockSize 0x004 -#define SD_BlockCount 0x006 -#define SD_Arg0 0x008 -#define SD_Arg1 0x00A -#define SD_TransferMode 0x00C -#define SD_Command 0x00E -#define SD_Response0 0x010 -#define SD_Response1 0x012 -#define SD_Response2 0x014 -#define SD_Response3 0x016 -#define SD_Response4 0x018 -#define SD_Response5 0x01A -#define SD_Response6 0x01C -#define SD_Response7 0x01E -#define SD_BufferDataPort0 0x020 -#define SD_BufferDataPort1 0x022 -#define SD_PresentState 0x024 -#define SD_HostCntrl 0x028 -#define SD_PwrCntrl 0x029 -#define SD_BlockGapCntrl 0x02A -#define SD_WakeupCntrl 0x02B -#define SD_ClockCntrl 0x02C -#define SD_TimeoutCntrl 0x02E -#define SD_SoftwareReset 0x02F -#define SD_IntrStatus 0x030 -#define SD_ErrorIntrStatus 0x032 -#define SD_IntrStatusEnable 0x034 -#define SD_ErrorIntrStatusEnable 0x036 -#define SD_IntrSignalEnable 0x038 -#define SD_ErrorIntrSignalEnable 0x03A -#define SD_CMD12ErrorStatus 0x03C -#define SD_Capabilities 0x040 -#define SD_Capabilities_Reserved 0x044 -#define SD_MaxCurCap 0x048 -#define SD_MaxCurCap_Reserved 0x04C -#define SD_ADMA_SysAddr 0x58 -#define SD_SlotInterruptStatus 0x0FC -#define SD_HostControllerVersion 0x0FE - -/* SD specific registers in PCI config space */ -#define SD_SlotInfo 0x40 - -/* SD_Capabilities reg (0x040) */ -#define CAP_TO_CLKFREQ_M BITFIELD_MASK(6) -#define CAP_TO_CLKFREQ_S 0 -#define CAP_TO_CLKUNIT_M BITFIELD_MASK(1) -#define CAP_TO_CLKUNIT_S 7 -#define CAP_BASECLK_M BITFIELD_MASK(6) -#define CAP_BASECLK_S 8 -#define CAP_MAXBLOCK_M BITFIELD_MASK(2) -#define CAP_MAXBLOCK_S 16 -#define CAP_ADMA2_M BITFIELD_MASK(1) -#define CAP_ADMA2_S 19 -#define CAP_ADMA1_M BITFIELD_MASK(1) -#define CAP_ADMA1_S 20 -#define CAP_HIGHSPEED_M BITFIELD_MASK(1) -#define CAP_HIGHSPEED_S 21 -#define CAP_DMA_M BITFIELD_MASK(1) -#define CAP_DMA_S 22 -#define CAP_SUSPEND_M BITFIELD_MASK(1) -#define CAP_SUSPEND_S 23 -#define CAP_VOLT_3_3_M BITFIELD_MASK(1) -#define CAP_VOLT_3_3_S 24 -#define CAP_VOLT_3_0_M BITFIELD_MASK(1) -#define CAP_VOLT_3_0_S 25 -#define CAP_VOLT_1_8_M BITFIELD_MASK(1) -#define CAP_VOLT_1_8_S 26 -#define CAP_64BIT_HOST_M BITFIELD_MASK(1) -#define CAP_64BIT_HOST_S 28 - -/* SD_MaxCurCap reg (0x048) */ -#define CAP_CURR_3_3_M BITFIELD_MASK(8) -#define CAP_CURR_3_3_S 0 -#define CAP_CURR_3_0_M BITFIELD_MASK(8) -#define CAP_CURR_3_0_S 8 -#define CAP_CURR_1_8_M BITFIELD_MASK(8) -#define CAP_CURR_1_8_S 16 - -/* SD_SysAddr: Offset 0x0000, Size 4 bytes */ - -/* SD_BlockSize: Offset 0x004, Size 2 bytes */ -#define BLKSZ_BLKSZ_M BITFIELD_MASK(12) -#define BLKSZ_BLKSZ_S 0 -#define BLKSZ_BNDRY_M BITFIELD_MASK(3) -#define BLKSZ_BNDRY_S 12 - -/* SD_BlockCount: Offset 0x006, size 2 bytes */ - -/* SD_Arg0: Offset 0x008, size = 4 bytes */ -/* SD_TransferMode Offset 0x00C, size = 2 bytes */ -#define XFER_DMA_ENABLE_M BITFIELD_MASK(1) -#define XFER_DMA_ENABLE_S 0 -#define XFER_BLK_COUNT_EN_M BITFIELD_MASK(1) -#define XFER_BLK_COUNT_EN_S 1 -#define XFER_CMD_12_EN_M BITFIELD_MASK(1) -#define XFER_CMD_12_EN_S 2 -#define XFER_DATA_DIRECTION_M BITFIELD_MASK(1) -#define XFER_DATA_DIRECTION_S 4 -#define XFER_MULTI_BLOCK_M BITFIELD_MASK(1) -#define XFER_MULTI_BLOCK_S 5 - -/* SD_Command: Offset 0x00E, size = 2 bytes */ -/* resp_type field */ -#define RESP_TYPE_NONE 0 -#define RESP_TYPE_136 1 -#define RESP_TYPE_48 2 -#define RESP_TYPE_48_BUSY 3 -/* type field */ -#define CMD_TYPE_NORMAL 0 -#define CMD_TYPE_SUSPEND 1 -#define CMD_TYPE_RESUME 2 -#define CMD_TYPE_ABORT 3 - -#define CMD_RESP_TYPE_M BITFIELD_MASK(2) /* Bits [0-1] - Response type */ -#define CMD_RESP_TYPE_S 0 -#define CMD_CRC_EN_M BITFIELD_MASK(1) /* Bit 3 - CRC enable */ -#define CMD_CRC_EN_S 3 -#define CMD_INDEX_EN_M BITFIELD_MASK(1) /* Bit 4 - Enable index checking */ -#define CMD_INDEX_EN_S 4 -#define CMD_DATA_EN_M BITFIELD_MASK(1) /* Bit 5 - Using DAT line */ -#define CMD_DATA_EN_S 5 -#define CMD_TYPE_M BITFIELD_MASK(2) /* Bit [6-7] - Normal, abort, resume, etc - */ -#define CMD_TYPE_S 6 -#define CMD_INDEX_M BITFIELD_MASK(6) /* Bits [8-13] - Command number */ -#define CMD_INDEX_S 8 - -/* SD_BufferDataPort0 : Offset 0x020, size = 2 or 4 bytes */ -/* SD_BufferDataPort1 : Offset 0x022, size = 2 bytes */ -/* SD_PresentState : Offset 0x024, size = 4 bytes */ -#define PRES_CMD_INHIBIT_M BITFIELD_MASK(1) /* Bit 0 May use CMD */ -#define PRES_CMD_INHIBIT_S 0 -#define PRES_DAT_INHIBIT_M BITFIELD_MASK(1) /* Bit 1 May use DAT */ -#define PRES_DAT_INHIBIT_S 1 -#define PRES_DAT_BUSY_M BITFIELD_MASK(1) /* Bit 2 DAT is busy */ -#define PRES_DAT_BUSY_S 2 -#define PRES_PRESENT_RSVD_M BITFIELD_MASK(5) /* Bit [3-7] rsvd */ -#define PRES_PRESENT_RSVD_S 3 -#define PRES_WRITE_ACTIVE_M BITFIELD_MASK(1) /* Bit 8 Write is active */ -#define PRES_WRITE_ACTIVE_S 8 -#define PRES_READ_ACTIVE_M BITFIELD_MASK(1) /* Bit 9 Read is active */ -#define PRES_READ_ACTIVE_S 9 -#define PRES_WRITE_DATA_RDY_M BITFIELD_MASK(1) /* Bit 10 Write buf is avail */ -#define PRES_WRITE_DATA_RDY_S 10 -#define PRES_READ_DATA_RDY_M BITFIELD_MASK(1) /* Bit 11 Read buf data avail */ -#define PRES_READ_DATA_RDY_S 11 -#define PRES_CARD_PRESENT_M BITFIELD_MASK(1) /* Bit 16 Card present - debounced */ -#define PRES_CARD_PRESENT_S 16 -#define PRES_CARD_STABLE_M BITFIELD_MASK(1) /* Bit 17 Debugging */ -#define PRES_CARD_STABLE_S 17 -#define PRES_CARD_PRESENT_RAW_M BITFIELD_MASK(1) /* Bit 18 Not debounced */ -#define PRES_CARD_PRESENT_RAW_S 18 -#define PRES_WRITE_ENABLED_M BITFIELD_MASK(1) /* Bit 19 Write protected? */ -#define PRES_WRITE_ENABLED_S 19 -#define PRES_DAT_SIGNAL_M BITFIELD_MASK(4) /* Bit [20-23] Debugging */ -#define PRES_DAT_SIGNAL_S 20 -#define PRES_CMD_SIGNAL_M BITFIELD_MASK(1) /* Bit 24 Debugging */ -#define PRES_CMD_SIGNAL_S 24 - -/* SD_HostCntrl: Offset 0x028, size = 1 bytes */ -#define HOST_LED_M BITFIELD_MASK(1) /* Bit 0 LED On/Off */ -#define HOST_LED_S 0 -#define HOST_DATA_WIDTH_M BITFIELD_MASK(1) /* Bit 1 4 bit enable */ -#define HOST_DATA_WIDTH_S 1 -#define HOST_HI_SPEED_EN_M BITFIELD_MASK(1) /* Bit 2 High speed vs low speed */ -#define HOST_DMA_SEL_S 3 -#define HOST_DMA_SEL_M BITFIELD_MASK(2) /* Bit 4:3 DMA Select */ -#define HOST_HI_SPEED_EN_S 2 - -/* misc defines */ -#define SD1_MODE 0x1 /* SD Host Cntrlr Spec */ -#define SD4_MODE 0x2 /* SD Host Cntrlr Spec */ - -/* SD_PwrCntrl: Offset 0x029, size = 1 bytes */ -#define PWR_BUS_EN_M BITFIELD_MASK(1) /* Bit 0 Power the bus */ -#define PWR_BUS_EN_S 0 -#define PWR_VOLTS_M BITFIELD_MASK(3) /* Bit [1-3] Voltage Select */ -#define PWR_VOLTS_S 1 - -/* SD_SoftwareReset: Offset 0x02F, size = 1 byte */ -#define SW_RESET_ALL_M BITFIELD_MASK(1) /* Bit 0 Reset All */ -#define SW_RESET_ALL_S 0 -#define SW_RESET_CMD_M BITFIELD_MASK(1) /* Bit 1 CMD Line Reset */ -#define SW_RESET_CMD_S 1 -#define SW_RESET_DAT_M BITFIELD_MASK(1) /* Bit 2 DAT Line Reset */ -#define SW_RESET_DAT_S 2 - -/* SD_IntrStatus: Offset 0x030, size = 2 bytes */ -/* Defs also serve SD_IntrStatusEnable and SD_IntrSignalEnable */ -#define INTSTAT_CMD_COMPLETE_M BITFIELD_MASK(1) /* Bit 0 */ -#define INTSTAT_CMD_COMPLETE_S 0 -#define INTSTAT_XFER_COMPLETE_M BITFIELD_MASK(1) -#define INTSTAT_XFER_COMPLETE_S 1 -#define INTSTAT_BLOCK_GAP_EVENT_M BITFIELD_MASK(1) -#define INTSTAT_BLOCK_GAP_EVENT_S 2 -#define INTSTAT_DMA_INT_M BITFIELD_MASK(1) -#define INTSTAT_DMA_INT_S 3 -#define INTSTAT_BUF_WRITE_READY_M BITFIELD_MASK(1) -#define INTSTAT_BUF_WRITE_READY_S 4 -#define INTSTAT_BUF_READ_READY_M BITFIELD_MASK(1) -#define INTSTAT_BUF_READ_READY_S 5 -#define INTSTAT_CARD_INSERTION_M BITFIELD_MASK(1) -#define INTSTAT_CARD_INSERTION_S 6 -#define INTSTAT_CARD_REMOVAL_M BITFIELD_MASK(1) -#define INTSTAT_CARD_REMOVAL_S 7 -#define INTSTAT_CARD_INT_M BITFIELD_MASK(1) -#define INTSTAT_CARD_INT_S 8 -#define INTSTAT_ERROR_INT_M BITFIELD_MASK(1) /* Bit 15 */ -#define INTSTAT_ERROR_INT_S 15 - -/* SD_ErrorIntrStatus: Offset 0x032, size = 2 bytes */ -/* Defs also serve SD_ErrorIntrStatusEnable and SD_ErrorIntrSignalEnable */ -#define ERRINT_CMD_TIMEOUT_M BITFIELD_MASK(1) -#define ERRINT_CMD_TIMEOUT_S 0 -#define ERRINT_CMD_CRC_M BITFIELD_MASK(1) -#define ERRINT_CMD_CRC_S 1 -#define ERRINT_CMD_ENDBIT_M BITFIELD_MASK(1) -#define ERRINT_CMD_ENDBIT_S 2 -#define ERRINT_CMD_INDEX_M BITFIELD_MASK(1) -#define ERRINT_CMD_INDEX_S 3 -#define ERRINT_DATA_TIMEOUT_M BITFIELD_MASK(1) -#define ERRINT_DATA_TIMEOUT_S 4 -#define ERRINT_DATA_CRC_M BITFIELD_MASK(1) -#define ERRINT_DATA_CRC_S 5 -#define ERRINT_DATA_ENDBIT_M BITFIELD_MASK(1) -#define ERRINT_DATA_ENDBIT_S 6 -#define ERRINT_CURRENT_LIMIT_M BITFIELD_MASK(1) -#define ERRINT_CURRENT_LIMIT_S 7 -#define ERRINT_AUTO_CMD12_M BITFIELD_MASK(1) -#define ERRINT_AUTO_CMD12_S 8 -#define ERRINT_VENDOR_M BITFIELD_MASK(4) -#define ERRINT_VENDOR_S 12 - -/* Also provide definitions in "normal" form to allow combined masks */ -#define ERRINT_CMD_TIMEOUT_BIT 0x0001 -#define ERRINT_CMD_CRC_BIT 0x0002 -#define ERRINT_CMD_ENDBIT_BIT 0x0004 -#define ERRINT_CMD_INDEX_BIT 0x0008 -#define ERRINT_DATA_TIMEOUT_BIT 0x0010 -#define ERRINT_DATA_CRC_BIT 0x0020 -#define ERRINT_DATA_ENDBIT_BIT 0x0040 -#define ERRINT_CURRENT_LIMIT_BIT 0x0080 -#define ERRINT_AUTO_CMD12_BIT 0x0100 - -/* Masks to select CMD vs. DATA errors */ -#define ERRINT_CMD_ERRS (ERRINT_CMD_TIMEOUT_BIT | ERRINT_CMD_CRC_BIT |\ - ERRINT_CMD_ENDBIT_BIT | ERRINT_CMD_INDEX_BIT) -#define ERRINT_DATA_ERRS (ERRINT_DATA_TIMEOUT_BIT | ERRINT_DATA_CRC_BIT |\ - ERRINT_DATA_ENDBIT_BIT) -#define ERRINT_TRANSFER_ERRS (ERRINT_CMD_ERRS | ERRINT_DATA_ERRS) - -/* SD_WakeupCntr_BlockGapCntrl : Offset 0x02A , size = bytes */ -/* SD_ClockCntrl : Offset 0x02C , size = bytes */ -/* SD_SoftwareReset_TimeoutCntrl : Offset 0x02E , size = bytes */ -/* SD_IntrStatus : Offset 0x030 , size = bytes */ -/* SD_ErrorIntrStatus : Offset 0x032 , size = bytes */ -/* SD_IntrStatusEnable : Offset 0x034 , size = bytes */ -/* SD_ErrorIntrStatusEnable : Offset 0x036 , size = bytes */ -/* SD_IntrSignalEnable : Offset 0x038 , size = bytes */ -/* SD_ErrorIntrSignalEnable : Offset 0x03A , size = bytes */ -/* SD_CMD12ErrorStatus : Offset 0x03C , size = bytes */ -/* SD_Capabilities : Offset 0x040 , size = bytes */ -/* SD_MaxCurCap : Offset 0x048 , size = bytes */ -/* SD_MaxCurCap_Reserved: Offset 0x04C , size = bytes */ -/* SD_SlotInterruptStatus: Offset 0x0FC , size = bytes */ -/* SD_HostControllerVersion : Offset 0x0FE , size = bytes */ - -#endif /* _SDIOH_H */ diff --git a/drivers/net/wireless/bcm4329/include/sdiovar.h b/drivers/net/wireless/bcm4329/include/sdiovar.h deleted file mode 100644 index 0179d4cb96db..000000000000 --- a/drivers/net/wireless/bcm4329/include/sdiovar.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Structure used by apps whose drivers access SDIO drivers. - * Pulled out separately so dhdu and wlu can both use it. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sdiovar.h,v 13.5.14.2.16.2 2009/12/08 22:34:21 Exp $ - */ - -#ifndef _sdiovar_h_ -#define _sdiovar_h_ - -#include - -/* require default structure packing */ -#define BWL_DEFAULT_PACKING -#include - -typedef struct sdreg { - int func; - int offset; - int value; -} sdreg_t; - -/* Common msglevel constants */ -#define SDH_ERROR_VAL 0x0001 /* Error */ -#define SDH_TRACE_VAL 0x0002 /* Trace */ -#define SDH_INFO_VAL 0x0004 /* Info */ -#define SDH_DEBUG_VAL 0x0008 /* Debug */ -#define SDH_DATA_VAL 0x0010 /* Data */ -#define SDH_CTRL_VAL 0x0020 /* Control Regs */ -#define SDH_LOG_VAL 0x0040 /* Enable bcmlog */ -#define SDH_DMA_VAL 0x0080 /* DMA */ - -#define NUM_PREV_TRANSACTIONS 16 - - -#include - -#endif /* _sdiovar_h_ */ diff --git a/drivers/net/wireless/bcm4329/include/siutils.h b/drivers/net/wireless/bcm4329/include/siutils.h deleted file mode 100644 index cb9f1407b73b..000000000000 --- a/drivers/net/wireless/bcm4329/include/siutils.h +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Misc utility routines for accessing the SOC Interconnects - * of Broadcom HNBU chips. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: siutils.h,v 13.197.4.2.4.3.8.16 2010/06/23 21:36:05 Exp $ - */ - - -#ifndef _siutils_h_ -#define _siutils_h_ - - -struct si_pub { - uint socitype; - - uint bustype; - uint buscoretype; - uint buscorerev; - uint buscoreidx; - int ccrev; - uint32 cccaps; - int pmurev; - uint32 pmucaps; - uint boardtype; - uint boardvendor; - uint boardflags; - uint chip; - uint chiprev; - uint chippkg; - uint32 chipst; - bool issim; - uint socirev; - bool pci_pr32414; -}; - -#if defined(WLC_HIGH) && !defined(WLC_LOW) -typedef struct si_pub si_t; -#else -typedef const struct si_pub si_t; -#endif - - -#define SI_OSH NULL - - -#define XTAL 0x1 -#define PLL 0x2 - - -#define CLK_FAST 0 -#define CLK_DYNAMIC 2 - - -#define GPIO_DRV_PRIORITY 0 -#define GPIO_APP_PRIORITY 1 -#define GPIO_HI_PRIORITY 2 - - -#define GPIO_PULLUP 0 -#define GPIO_PULLDN 1 - - -#define GPIO_REGEVT 0 -#define GPIO_REGEVT_INTMSK 1 -#define GPIO_REGEVT_INTPOL 2 - - -#define SI_DEVPATH_BUFSZ 16 - - -#define SI_DOATTACH 1 -#define SI_PCIDOWN 2 -#define SI_PCIUP 3 - -#define ISSIM_ENAB(sih) 0 - - -#if defined(BCMPMUCTL) -#define PMUCTL_ENAB(sih) (BCMPMUCTL) -#else -#define PMUCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PMU) -#endif - - -#if defined(BCMPMUCTL) && BCMPMUCTL -#define CCCTL_ENAB(sih) (0) -#define CCPLL_ENAB(sih) (0) -#else -#define CCCTL_ENAB(sih) ((sih)->cccaps & CC_CAP_PWR_CTL) -#define CCPLL_ENAB(sih) ((sih)->cccaps & CC_CAP_PLL_MASK) -#endif - -typedef void (*gpio_handler_t)(uint32 stat, void *arg); - - - -extern si_t *si_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, - void *sdh, char **vars, uint *varsz); -extern si_t *si_kattach(osl_t *osh); -extern void si_detach(si_t *sih); -extern bool si_pci_war16165(si_t *sih); - -extern uint si_corelist(si_t *sih, uint coreid[]); -extern uint si_coreid(si_t *sih); -extern uint si_flag(si_t *sih); -extern uint si_intflag(si_t *sih); -extern uint si_coreidx(si_t *sih); -extern uint si_coreunit(si_t *sih); -extern uint si_corevendor(si_t *sih); -extern uint si_corerev(si_t *sih); -extern void *si_osh(si_t *sih); -extern void si_setosh(si_t *sih, osl_t *osh); -extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); -extern void *si_coreregs(si_t *sih); -extern void si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val); -extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); -extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); -extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); -extern bool si_iscoreup(si_t *sih); -extern uint si_findcoreidx(si_t *sih, uint coreid, uint coreunit); -extern void *si_setcoreidx(si_t *sih, uint coreidx); -extern void *si_setcore(si_t *sih, uint coreid, uint coreunit); -extern void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val); -extern void si_restore_core(si_t *sih, uint coreid, uint intr_val); -extern int si_numaddrspaces(si_t *sih); -extern uint32 si_addrspace(si_t *sih, uint asidx); -extern uint32 si_addrspacesize(si_t *sih, uint asidx); -extern int si_corebist(si_t *sih); -extern void si_core_reset(si_t *sih, uint32 bits, uint32 resetbits); -extern void si_core_tofixup(si_t *sih); -extern void si_core_disable(si_t *sih, uint32 bits); -extern uint32 si_clock_rate(uint32 pll_type, uint32 n, uint32 m); -extern uint32 si_clock(si_t *sih); -extern void si_clock_pmu_spuravoid(si_t *sih, bool spuravoid); -extern uint32 si_alp_clock(si_t *sih); -extern uint32 si_ilp_clock(si_t *sih); -extern void si_pci_setup(si_t *sih, uint coremask); -extern void si_pcmcia_init(si_t *sih); -extern void si_setint(si_t *sih, int siflag); -extern bool si_backplane64(si_t *sih); -extern void si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, - void *intrsenabled_fn, void *intr_arg); -extern void si_deregister_intr_callback(si_t *sih); -extern void si_clkctl_init(si_t *sih); -extern uint16 si_clkctl_fast_pwrup_delay(si_t *sih); -extern bool si_clkctl_cc(si_t *sih, uint mode); -extern int si_clkctl_xtal(si_t *sih, uint what, bool on); -extern uint32 si_gpiotimerval(si_t *sih, uint32 mask, uint32 val); -extern bool si_backplane64(si_t *sih); -extern void si_btcgpiowar(si_t *sih); -extern bool si_deviceremoved(si_t *sih); -extern uint32 si_socram_size(si_t *sih); - -extern void si_watchdog(si_t *sih, uint ticks); -extern void si_watchdog_ms(si_t *sih, uint32 ms); -extern void *si_gpiosetcore(si_t *sih); -extern uint32 si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority); -extern uint32 si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority); -extern uint32 si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority); -extern uint32 si_gpioin(si_t *sih); -extern uint32 si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority); -extern uint32 si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority); -extern uint32 si_gpioled(si_t *sih, uint32 mask, uint32 val); -extern uint32 si_gpioreserve(si_t *sih, uint32 gpio_num, uint8 priority); -extern uint32 si_gpiorelease(si_t *sih, uint32 gpio_num, uint8 priority); -extern uint32 si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val); -extern uint32 si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val); -extern uint32 si_gpio_int_enable(si_t *sih, bool enable); - - -extern void *si_gpio_handler_register(si_t *sih, uint32 e, bool lev, gpio_handler_t cb, void *arg); -extern void si_gpio_handler_unregister(si_t *sih, void* gpioh); -extern void si_gpio_handler_process(si_t *sih); - - -extern bool si_pci_pmecap(si_t *sih); -struct osl_info; -extern bool si_pci_fastpmecap(struct osl_info *osh); -extern bool si_pci_pmeclr(si_t *sih); -extern void si_pci_pmeen(si_t *sih); -extern uint si_pcie_readreg(void *sih, uint addrtype, uint offset); - -extern void si_sdio_init(si_t *sih); - -extern uint16 si_d11_devid(si_t *sih); -extern int si_corepciid(si_t *sih, uint func, uint16 *pcivendor, uint16 *pcidevice, - uint8 *pciclass, uint8 *pcisubclass, uint8 *pciprogif, uint8 *pciheader); - -#define si_eci_init(sih) (0) -#define si_eci_notify_bt(sih, type, val, interrupt) (0) - - - -extern int si_devpath(si_t *sih, char *path, int size); - -extern char *si_getdevpathvar(si_t *sih, const char *name); -extern int si_getdevpathintvar(si_t *sih, const char *name); - - -extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val); -extern void si_war42780_clkreq(si_t *sih, bool clkreq); -extern void si_pci_sleep(si_t *sih); -extern void si_pci_down(si_t *sih); -extern void si_pci_up(si_t *sih); -extern void si_pcie_war_ovr_disable(si_t *sih); -extern void si_pcie_extendL1timer(si_t *sih, bool extend); -extern int si_pci_fixcfg(si_t *sih); - - - - - - - -#endif diff --git a/drivers/net/wireless/bcm4329/include/trxhdr.h b/drivers/net/wireless/bcm4329/include/trxhdr.h deleted file mode 100644 index 8f5eed9410eb..000000000000 --- a/drivers/net/wireless/bcm4329/include/trxhdr.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * TRX image file header format. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: trxhdr.h,v 13.11.310.1 2008/08/17 12:58:58 Exp $ - */ - -#include - -#define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 /* Version 1 */ -#define TRX_MAX_LEN 0x3A0000 /* Max length */ -#define TRX_NO_HEADER 1 /* Do not write TRX header */ -#define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ -#define TRX_MAX_OFFSET 3 /* Max number of individual files */ -#define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ - -struct trx_header { - uint32 magic; /* "HDR0" */ - uint32 len; /* Length of file including header */ - uint32 crc32; /* 32-bit CRC from flag_version to end of file */ - uint32 flag_version; /* 0:15 flags, 16:31 version */ - uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ -}; - -/* Compatibility */ -typedef struct trx_header TRXHDR, *PTRXHDR; diff --git a/drivers/net/wireless/bcm4329/include/typedefs.h b/drivers/net/wireless/bcm4329/include/typedefs.h deleted file mode 100644 index 4d9dd761ed64..000000000000 --- a/drivers/net/wireless/bcm4329/include/typedefs.h +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: typedefs.h,v 1.85.34.1.2.5 2009/01/27 04:09:40 Exp $ - */ - - -#ifndef _TYPEDEFS_H_ -#define _TYPEDEFS_H_ - -#ifdef SITE_TYPEDEFS - - - -#include "site_typedefs.h" - -#else - - - -#ifdef __cplusplus - -#define TYPEDEF_BOOL -#ifndef FALSE -#define FALSE false -#endif -#ifndef TRUE -#define TRUE true -#endif - -#else - - -#endif - -#if defined(__x86_64__) -#define TYPEDEF_UINTPTR -typedef unsigned long long int uintptr; -#endif - - - - -#if defined(TARGETOS_nucleus) - -#include - - -#define TYPEDEF_FLOAT_T -#endif - -#if defined(_NEED_SIZE_T_) -typedef long unsigned int size_t; -#endif - -#ifdef __DJGPP__ -typedef long unsigned int size_t; -#endif - - - - - -#define TYPEDEF_UINT -#ifndef TARGETENV_android -#define TYPEDEF_USHORT -#define TYPEDEF_ULONG -#endif -#ifdef __KERNEL__ -#include -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 19)) -#define TYPEDEF_BOOL -#endif -#endif - - - - - -#if defined(__GNUC__) && defined(__STRICT_ANSI__) -#define TYPEDEF_INT64 -#define TYPEDEF_UINT64 -#endif - - -#if defined(__ICL) - -#define TYPEDEF_INT64 - -#if defined(__STDC__) -#define TYPEDEF_UINT64 -#endif - -#endif - -#if !defined(__DJGPP__) && !defined(TARGETOS_nucleus) - - -#if defined(__KERNEL__) - -#include - -#else - - -#include - -#endif - -#endif - - - - -#define USE_TYPEDEF_DEFAULTS - -#endif - - - - -#ifdef USE_TYPEDEF_DEFAULTS -#undef USE_TYPEDEF_DEFAULTS - -#ifndef TYPEDEF_BOOL -typedef unsigned char bool; -#endif - - - -#ifndef TYPEDEF_UCHAR -typedef unsigned char uchar; -#endif - -#ifndef TYPEDEF_USHORT -typedef unsigned short ushort; -#endif - -#ifndef TYPEDEF_UINT -typedef unsigned int uint; -#endif - -#ifndef TYPEDEF_ULONG -typedef unsigned long ulong; -#endif - - - -#ifndef TYPEDEF_UINT8 -typedef unsigned char uint8; -#endif - -#ifndef TYPEDEF_UINT16 -typedef unsigned short uint16; -#endif - -#ifndef TYPEDEF_UINT32 -typedef unsigned int uint32; -#endif - -#ifndef TYPEDEF_UINT64 -typedef unsigned long long uint64; -#endif - -#ifndef TYPEDEF_UINTPTR -typedef unsigned int uintptr; -#endif - -#ifndef TYPEDEF_INT8 -typedef signed char int8; -#endif - -#ifndef TYPEDEF_INT16 -typedef signed short int16; -#endif - -#ifndef TYPEDEF_INT32 -typedef signed int int32; -#endif - -#ifndef TYPEDEF_INT64 -typedef signed long long int64; -#endif - - - -#ifndef TYPEDEF_FLOAT32 -typedef float float32; -#endif - -#ifndef TYPEDEF_FLOAT64 -typedef double float64; -#endif - - - -#ifndef TYPEDEF_FLOAT_T - -#if defined(FLOAT32) -typedef float32 float_t; -#else -typedef float64 float_t; -#endif - -#endif - - - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef NULL -#define NULL 0 -#endif - -#ifndef OFF -#define OFF 0 -#endif - -#ifndef ON -#define ON 1 -#endif - -#define AUTO (-1) - - - -#ifndef PTRSZ -#define PTRSZ sizeof(char*) -#endif - - - -#if defined(__GNUC__) - #define BWL_COMPILER_GNU -#elif defined(__CC_ARM) - #define BWL_COMPILER_ARMCC -#else - #error "Unknown compiler!" -#endif - - -#ifndef INLINE - #if defined(BWL_COMPILER_MICROSOFT) - #define INLINE __inline - #elif defined(BWL_COMPILER_GNU) - #define INLINE __inline__ - #elif defined(BWL_COMPILER_ARMCC) - #define INLINE __inline - #else - #define INLINE - #endif -#endif - -#undef TYPEDEF_BOOL -#undef TYPEDEF_UCHAR -#undef TYPEDEF_USHORT -#undef TYPEDEF_UINT -#undef TYPEDEF_ULONG -#undef TYPEDEF_UINT8 -#undef TYPEDEF_UINT16 -#undef TYPEDEF_UINT32 -#undef TYPEDEF_UINT64 -#undef TYPEDEF_UINTPTR -#undef TYPEDEF_INT8 -#undef TYPEDEF_INT16 -#undef TYPEDEF_INT32 -#undef TYPEDEF_INT64 -#undef TYPEDEF_FLOAT32 -#undef TYPEDEF_FLOAT64 -#undef TYPEDEF_FLOAT_T - -#endif - - -#define UNUSED_PARAMETER(x) (void)(x) - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/include/wlioctl.h b/drivers/net/wireless/bcm4329/include/wlioctl.h deleted file mode 100644 index d346945dec94..000000000000 --- a/drivers/net/wireless/bcm4329/include/wlioctl.h +++ /dev/null @@ -1,1661 +0,0 @@ -/* - * Custom OID/ioctl definitions for - * Broadcom 802.11abg Networking Device Driver - * - * Definitions subject to change without notice. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: wlioctl.h,v 1.601.4.15.2.14.2.61 2010/05/04 20:26:25 Exp $ - */ - - -#ifndef _wlioctl_h_ -#define _wlioctl_h_ - -#include -#include -#include -#include -#include -#include - - - -#define ACTION_FRAME_SIZE 1040 - -typedef struct wl_action_frame { - struct ether_addr da; - uint16 len; - uint32 packetId; - uint8 data[ACTION_FRAME_SIZE]; -} wl_action_frame_t; - -#define WL_WIFI_ACTION_FRAME_SIZE sizeof(struct wl_action_frame) - - -#define BWL_DEFAULT_PACKING -#include - -#define RWL_ACTION_WIFI_CATEGORY 127 -#define RWL_WIFI_OUI_BYTE1 0x90 -#define RWL_WIFI_OUI_BYTE2 0x4C -#define RWL_WIFI_OUI_BYTE3 0x0F -#define RWL_WIFI_ACTION_FRAME_SIZE sizeof(struct dot11_action_wifi_vendor_specific) -#define RWL_WIFI_DEFAULT 0x00 -#define RWL_WIFI_FIND_MY_PEER 0x09 -#define RWL_WIFI_FOUND_PEER 0x0A -#define RWL_ACTION_WIFI_FRAG_TYPE 0x55 - -typedef struct ssid_info -{ - uint8 ssid_len; - uint8 ssid[32]; -} ssid_info_t; - -typedef struct cnt_rx -{ - uint32 cnt_rxundec; - uint32 cnt_rxframe; -} cnt_rx_t; - - - -#define RWL_REF_MAC_ADDRESS_OFFSET 17 -#define RWL_DUT_MAC_ADDRESS_OFFSET 23 -#define RWL_WIFI_CLIENT_CHANNEL_OFFSET 50 -#define RWL_WIFI_SERVER_CHANNEL_OFFSET 51 - - - - - -#define WL_BSS_INFO_VERSION 108 - - -typedef struct wl_bss_info { - uint32 version; - uint32 length; - struct ether_addr BSSID; - uint16 beacon_period; - uint16 capability; - uint8 SSID_len; - uint8 SSID[32]; - struct { - uint count; - uint8 rates[16]; - } rateset; - chanspec_t chanspec; - uint16 atim_window; - uint8 dtim_period; - int16 RSSI; - int8 phy_noise; - - uint8 n_cap; - uint32 nbss_cap; - uint8 ctl_ch; - uint32 reserved32[1]; - uint8 flags; - uint8 reserved[3]; - uint8 basic_mcs[MCSSET_LEN]; - - uint16 ie_offset; - uint32 ie_length; - - -} wl_bss_info_t; - -typedef struct wlc_ssid { - uint32 SSID_len; - uchar SSID[32]; -} wlc_ssid_t; - - -#define WL_BSSTYPE_INFRA 1 -#define WL_BSSTYPE_INDEP 0 -#define WL_BSSTYPE_ANY 2 - - -#define WL_SCANFLAGS_PASSIVE 0x01 -#define WL_SCANFLAGS_PROHIBITED 0x04 - -typedef struct wl_scan_params { - wlc_ssid_t ssid; - struct ether_addr bssid; - int8 bss_type; - int8 scan_type; - int32 nprobes; - int32 active_time; - int32 passive_time; - int32 home_time; - int32 channel_num; - uint16 channel_list[1]; -} wl_scan_params_t; - -#define WL_SCAN_PARAMS_FIXED_SIZE 64 - - -#define WL_SCAN_PARAMS_COUNT_MASK 0x0000ffff -#define WL_SCAN_PARAMS_NSSID_SHIFT 16 - -#define WL_SCAN_ACTION_START 1 -#define WL_SCAN_ACTION_CONTINUE 2 -#define WL_SCAN_ACTION_ABORT 3 - -#define ISCAN_REQ_VERSION 1 - - -typedef struct wl_iscan_params { - uint32 version; - uint16 action; - uint16 scan_duration; - wl_scan_params_t params; -} wl_iscan_params_t; - -#define WL_ISCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_iscan_params_t, params) + sizeof(wlc_ssid_t)) - -typedef struct wl_scan_results { - uint32 buflen; - uint32 version; - uint32 count; - wl_bss_info_t bss_info[1]; -} wl_scan_results_t; - -#define WL_SCAN_RESULTS_FIXED_SIZE 12 - - -#define WL_SCAN_RESULTS_SUCCESS 0 -#define WL_SCAN_RESULTS_PARTIAL 1 -#define WL_SCAN_RESULTS_PENDING 2 -#define WL_SCAN_RESULTS_ABORTED 3 -#define WL_SCAN_RESULTS_NO_MEM 4 - -#define ESCAN_REQ_VERSION 1 - -typedef struct wl_escan_params { - uint32 version; - uint16 action; - uint16 sync_id; - wl_scan_params_t params; -} wl_escan_params_t; - -#define WL_ESCAN_PARAMS_FIXED_SIZE (OFFSETOF(wl_escan_params_t, params) + sizeof(wlc_ssid_t)) - -typedef struct wl_escan_result { - uint32 buflen; - uint32 version; - uint16 sync_id; - uint16 bss_count; - wl_bss_info_t bss_info[1]; -} wl_escan_result_t; - -#define WL_ESCAN_RESULTS_FIXED_SIZE (sizeof(wl_escan_result_t) - sizeof(wl_bss_info_t)) - - -typedef struct wl_iscan_results { - uint32 status; - wl_scan_results_t results; -} wl_iscan_results_t; - -#define WL_ISCAN_RESULTS_FIXED_SIZE \ - (WL_SCAN_RESULTS_FIXED_SIZE + OFFSETOF(wl_iscan_results_t, results)) - -#define WL_NUMRATES 16 -typedef struct wl_rateset { - uint32 count; - uint8 rates[WL_NUMRATES]; -} wl_rateset_t; - - -typedef struct wl_uint32_list { - - uint32 count; - - uint32 element[1]; -} wl_uint32_list_t; - - -typedef struct wl_assoc_params { - struct ether_addr bssid; - uint16 bssid_cnt; - int32 chanspec_num; - chanspec_t chanspec_list[1]; -} wl_assoc_params_t; -#define WL_ASSOC_PARAMS_FIXED_SIZE (sizeof(wl_assoc_params_t) - sizeof(chanspec_t)) - - -typedef wl_assoc_params_t wl_reassoc_params_t; -#define WL_REASSOC_PARAMS_FIXED_SIZE WL_ASSOC_PARAMS_FIXED_SIZE - - -typedef struct wl_join_params { - wlc_ssid_t ssid; - wl_assoc_params_t params; -} wl_join_params_t; -#define WL_JOIN_PARAMS_FIXED_SIZE (sizeof(wl_join_params_t) - sizeof(chanspec_t)) - -#define WLC_CNTRY_BUF_SZ 4 - - -typedef enum sup_auth_status { - - WLC_SUP_DISCONNECTED = 0, - WLC_SUP_CONNECTING, - WLC_SUP_IDREQUIRED, - WLC_SUP_AUTHENTICATING, - WLC_SUP_AUTHENTICATED, - WLC_SUP_KEYXCHANGE, - WLC_SUP_KEYED, - WLC_SUP_TIMEOUT, - WLC_SUP_LAST_BASIC_STATE, - - - WLC_SUP_KEYXCHANGE_WAIT_M1 = WLC_SUP_AUTHENTICATED, - - WLC_SUP_KEYXCHANGE_PREP_M2 = WLC_SUP_KEYXCHANGE, - - WLC_SUP_KEYXCHANGE_WAIT_M3 = WLC_SUP_LAST_BASIC_STATE, - - WLC_SUP_KEYXCHANGE_PREP_M4, - WLC_SUP_KEYXCHANGE_WAIT_G1, - WLC_SUP_KEYXCHANGE_PREP_G2 -} sup_auth_status_t; - - -#define CRYPTO_ALGO_OFF 0 -#define CRYPTO_ALGO_WEP1 1 -#define CRYPTO_ALGO_TKIP 2 -#define CRYPTO_ALGO_WEP128 3 -#define CRYPTO_ALGO_AES_CCM 4 -#define CRYPTO_ALGO_AES_OCB_MSDU 5 -#define CRYPTO_ALGO_AES_OCB_MPDU 6 -#define CRYPTO_ALGO_NALG 7 -#define CRYPTO_ALGO_SMS4 11 - -#define WSEC_GEN_MIC_ERROR 0x0001 -#define WSEC_GEN_REPLAY 0x0002 -#define WSEC_GEN_ICV_ERROR 0x0004 - -#define WL_SOFT_KEY (1 << 0) -#define WL_PRIMARY_KEY (1 << 1) -#define WL_KF_RES_4 (1 << 4) -#define WL_KF_RES_5 (1 << 5) -#define WL_IBSS_PEER_GROUP_KEY (1 << 6) - -typedef struct wl_wsec_key { - uint32 index; - uint32 len; - uint8 data[DOT11_MAX_KEY_SIZE]; - uint32 pad_1[18]; - uint32 algo; - uint32 flags; - uint32 pad_2[2]; - int pad_3; - int iv_initialized; - int pad_4; - - struct { - uint32 hi; - uint16 lo; - } rxiv; - uint32 pad_5[2]; - struct ether_addr ea; -} wl_wsec_key_t; - -#define WSEC_MIN_PSK_LEN 8 -#define WSEC_MAX_PSK_LEN 64 - - -#define WSEC_PASSPHRASE (1<<0) - - -typedef struct { - ushort key_len; - ushort flags; - uint8 key[WSEC_MAX_PSK_LEN]; -} wsec_pmk_t; - - -#define WEP_ENABLED 0x0001 -#define TKIP_ENABLED 0x0002 -#define AES_ENABLED 0x0004 -#define WSEC_SWFLAG 0x0008 -#define SES_OW_ENABLED 0x0040 -#define SMS4_ENABLED 0x0100 - - -#define WPA_AUTH_DISABLED 0x0000 -#define WPA_AUTH_NONE 0x0001 -#define WPA_AUTH_UNSPECIFIED 0x0002 -#define WPA_AUTH_PSK 0x0004 - -#define WPA2_AUTH_UNSPECIFIED 0x0040 -#define WPA2_AUTH_PSK 0x0080 -#define BRCM_AUTH_PSK 0x0100 -#define BRCM_AUTH_DPT 0x0200 -#define WPA_AUTH_WAPI 0x0400 - -#define WPA_AUTH_PFN_ANY 0xffffffff - - -#define MAXPMKID 16 - -typedef struct _pmkid { - struct ether_addr BSSID; - uint8 PMKID[WPA2_PMKID_LEN]; -} pmkid_t; - -typedef struct _pmkid_list { - uint32 npmkid; - pmkid_t pmkid[1]; -} pmkid_list_t; - -typedef struct _pmkid_cand { - struct ether_addr BSSID; - uint8 preauth; -} pmkid_cand_t; - -typedef struct _pmkid_cand_list { - uint32 npmkid_cand; - pmkid_cand_t pmkid_cand[1]; -} pmkid_cand_list_t; - - - - -typedef struct { - uint32 val; - struct ether_addr ea; -} scb_val_t; - - - -typedef struct channel_info { - int hw_channel; - int target_channel; - int scan_channel; -} channel_info_t; - - -struct maclist { - uint count; - struct ether_addr ea[1]; -}; - - -typedef struct get_pktcnt { - uint rx_good_pkt; - uint rx_bad_pkt; - uint tx_good_pkt; - uint tx_bad_pkt; - uint rx_ocast_good_pkt; -} get_pktcnt_t; - - -typedef struct wl_ioctl { - uint cmd; - void *buf; - uint len; - uint8 set; - uint used; - uint needed; -} wl_ioctl_t; - - - -#define WLC_IOCTL_MAGIC 0x14e46c77 - - -#define WLC_IOCTL_VERSION 1 - -#define WLC_IOCTL_MAXLEN 8192 -#define WLC_IOCTL_SMLEN 256 -#define WLC_IOCTL_MEDLEN 1536 - - - -#define WLC_GET_MAGIC 0 -#define WLC_GET_VERSION 1 -#define WLC_UP 2 -#define WLC_DOWN 3 -#define WLC_GET_LOOP 4 -#define WLC_SET_LOOP 5 -#define WLC_DUMP 6 -#define WLC_GET_MSGLEVEL 7 -#define WLC_SET_MSGLEVEL 8 -#define WLC_GET_PROMISC 9 -#define WLC_SET_PROMISC 10 - -#define WLC_GET_RATE 12 - -#define WLC_GET_INSTANCE 14 - - - - -#define WLC_GET_INFRA 19 -#define WLC_SET_INFRA 20 -#define WLC_GET_AUTH 21 -#define WLC_SET_AUTH 22 -#define WLC_GET_BSSID 23 -#define WLC_SET_BSSID 24 -#define WLC_GET_SSID 25 -#define WLC_SET_SSID 26 -#define WLC_RESTART 27 - -#define WLC_GET_CHANNEL 29 -#define WLC_SET_CHANNEL 30 -#define WLC_GET_SRL 31 -#define WLC_SET_SRL 32 -#define WLC_GET_LRL 33 -#define WLC_SET_LRL 34 -#define WLC_GET_PLCPHDR 35 -#define WLC_SET_PLCPHDR 36 -#define WLC_GET_RADIO 37 -#define WLC_SET_RADIO 38 -#define WLC_GET_PHYTYPE 39 -#define WLC_DUMP_RATE 40 -#define WLC_SET_RATE_PARAMS 41 - - -#define WLC_GET_KEY 44 -#define WLC_SET_KEY 45 -#define WLC_GET_REGULATORY 46 -#define WLC_SET_REGULATORY 47 -#define WLC_GET_PASSIVE_SCAN 48 -#define WLC_SET_PASSIVE_SCAN 49 -#define WLC_SCAN 50 -#define WLC_SCAN_RESULTS 51 -#define WLC_DISASSOC 52 -#define WLC_REASSOC 53 -#define WLC_GET_ROAM_TRIGGER 54 -#define WLC_SET_ROAM_TRIGGER 55 -#define WLC_GET_ROAM_DELTA 56 -#define WLC_SET_ROAM_DELTA 57 -#define WLC_GET_ROAM_SCAN_PERIOD 58 -#define WLC_SET_ROAM_SCAN_PERIOD 59 -#define WLC_EVM 60 -#define WLC_GET_TXANT 61 -#define WLC_SET_TXANT 62 -#define WLC_GET_ANTDIV 63 -#define WLC_SET_ANTDIV 64 - - -#define WLC_GET_CLOSED 67 -#define WLC_SET_CLOSED 68 -#define WLC_GET_MACLIST 69 -#define WLC_SET_MACLIST 70 -#define WLC_GET_RATESET 71 -#define WLC_SET_RATESET 72 - -#define WLC_LONGTRAIN 74 -#define WLC_GET_BCNPRD 75 -#define WLC_SET_BCNPRD 76 -#define WLC_GET_DTIMPRD 77 -#define WLC_SET_DTIMPRD 78 -#define WLC_GET_SROM 79 -#define WLC_SET_SROM 80 -#define WLC_GET_WEP_RESTRICT 81 -#define WLC_SET_WEP_RESTRICT 82 -#define WLC_GET_COUNTRY 83 -#define WLC_SET_COUNTRY 84 -#define WLC_GET_PM 85 -#define WLC_SET_PM 86 -#define WLC_GET_WAKE 87 -#define WLC_SET_WAKE 88 - -#define WLC_GET_FORCELINK 90 -#define WLC_SET_FORCELINK 91 -#define WLC_FREQ_ACCURACY 92 -#define WLC_CARRIER_SUPPRESS 93 -#define WLC_GET_PHYREG 94 -#define WLC_SET_PHYREG 95 -#define WLC_GET_RADIOREG 96 -#define WLC_SET_RADIOREG 97 -#define WLC_GET_REVINFO 98 -#define WLC_GET_UCANTDIV 99 -#define WLC_SET_UCANTDIV 100 -#define WLC_R_REG 101 -#define WLC_W_REG 102 - - -#define WLC_GET_MACMODE 105 -#define WLC_SET_MACMODE 106 -#define WLC_GET_MONITOR 107 -#define WLC_SET_MONITOR 108 -#define WLC_GET_GMODE 109 -#define WLC_SET_GMODE 110 -#define WLC_GET_LEGACY_ERP 111 -#define WLC_SET_LEGACY_ERP 112 -#define WLC_GET_RX_ANT 113 -#define WLC_GET_CURR_RATESET 114 -#define WLC_GET_SCANSUPPRESS 115 -#define WLC_SET_SCANSUPPRESS 116 -#define WLC_GET_AP 117 -#define WLC_SET_AP 118 -#define WLC_GET_EAP_RESTRICT 119 -#define WLC_SET_EAP_RESTRICT 120 -#define WLC_SCB_AUTHORIZE 121 -#define WLC_SCB_DEAUTHORIZE 122 -#define WLC_GET_WDSLIST 123 -#define WLC_SET_WDSLIST 124 -#define WLC_GET_ATIM 125 -#define WLC_SET_ATIM 126 -#define WLC_GET_RSSI 127 -#define WLC_GET_PHYANTDIV 128 -#define WLC_SET_PHYANTDIV 129 -#define WLC_AP_RX_ONLY 130 -#define WLC_GET_TX_PATH_PWR 131 -#define WLC_SET_TX_PATH_PWR 132 -#define WLC_GET_WSEC 133 -#define WLC_SET_WSEC 134 -#define WLC_GET_PHY_NOISE 135 -#define WLC_GET_BSS_INFO 136 -#define WLC_GET_PKTCNTS 137 -#define WLC_GET_LAZYWDS 138 -#define WLC_SET_LAZYWDS 139 -#define WLC_GET_BANDLIST 140 -#define WLC_GET_BAND 141 -#define WLC_SET_BAND 142 -#define WLC_SCB_DEAUTHENTICATE 143 -#define WLC_GET_SHORTSLOT 144 -#define WLC_GET_SHORTSLOT_OVERRIDE 145 -#define WLC_SET_SHORTSLOT_OVERRIDE 146 -#define WLC_GET_SHORTSLOT_RESTRICT 147 -#define WLC_SET_SHORTSLOT_RESTRICT 148 -#define WLC_GET_GMODE_PROTECTION 149 -#define WLC_GET_GMODE_PROTECTION_OVERRIDE 150 -#define WLC_SET_GMODE_PROTECTION_OVERRIDE 151 -#define WLC_UPGRADE 152 - - -#define WLC_GET_IGNORE_BCNS 155 -#define WLC_SET_IGNORE_BCNS 156 -#define WLC_GET_SCB_TIMEOUT 157 -#define WLC_SET_SCB_TIMEOUT 158 -#define WLC_GET_ASSOCLIST 159 -#define WLC_GET_CLK 160 -#define WLC_SET_CLK 161 -#define WLC_GET_UP 162 -#define WLC_OUT 163 -#define WLC_GET_WPA_AUTH 164 -#define WLC_SET_WPA_AUTH 165 -#define WLC_GET_UCFLAGS 166 -#define WLC_SET_UCFLAGS 167 -#define WLC_GET_PWRIDX 168 -#define WLC_SET_PWRIDX 169 -#define WLC_GET_TSSI 170 -#define WLC_GET_SUP_RATESET_OVERRIDE 171 -#define WLC_SET_SUP_RATESET_OVERRIDE 172 - - - - - -#define WLC_GET_PROTECTION_CONTROL 178 -#define WLC_SET_PROTECTION_CONTROL 179 -#define WLC_GET_PHYLIST 180 -#define WLC_ENCRYPT_STRENGTH 181 -#define WLC_DECRYPT_STATUS 182 -#define WLC_GET_KEY_SEQ 183 -#define WLC_GET_SCAN_CHANNEL_TIME 184 -#define WLC_SET_SCAN_CHANNEL_TIME 185 -#define WLC_GET_SCAN_UNASSOC_TIME 186 -#define WLC_SET_SCAN_UNASSOC_TIME 187 -#define WLC_GET_SCAN_HOME_TIME 188 -#define WLC_SET_SCAN_HOME_TIME 189 -#define WLC_GET_SCAN_NPROBES 190 -#define WLC_SET_SCAN_NPROBES 191 -#define WLC_GET_PRB_RESP_TIMEOUT 192 -#define WLC_SET_PRB_RESP_TIMEOUT 193 -#define WLC_GET_ATTEN 194 -#define WLC_SET_ATTEN 195 -#define WLC_GET_SHMEM 196 -#define WLC_SET_SHMEM 197 - - -#define WLC_SET_WSEC_TEST 200 -#define WLC_SCB_DEAUTHENTICATE_FOR_REASON 201 -#define WLC_TKIP_COUNTERMEASURES 202 -#define WLC_GET_PIOMODE 203 -#define WLC_SET_PIOMODE 204 -#define WLC_SET_ASSOC_PREFER 205 -#define WLC_GET_ASSOC_PREFER 206 -#define WLC_SET_ROAM_PREFER 207 -#define WLC_GET_ROAM_PREFER 208 -#define WLC_SET_LED 209 -#define WLC_GET_LED 210 -#define WLC_GET_INTERFERENCE_MODE 211 -#define WLC_SET_INTERFERENCE_MODE 212 -#define WLC_GET_CHANNEL_QA 213 -#define WLC_START_CHANNEL_QA 214 -#define WLC_GET_CHANNEL_SEL 215 -#define WLC_START_CHANNEL_SEL 216 -#define WLC_GET_VALID_CHANNELS 217 -#define WLC_GET_FAKEFRAG 218 -#define WLC_SET_FAKEFRAG 219 -#define WLC_GET_PWROUT_PERCENTAGE 220 -#define WLC_SET_PWROUT_PERCENTAGE 221 -#define WLC_SET_BAD_FRAME_PREEMPT 222 -#define WLC_GET_BAD_FRAME_PREEMPT 223 -#define WLC_SET_LEAP_LIST 224 -#define WLC_GET_LEAP_LIST 225 -#define WLC_GET_CWMIN 226 -#define WLC_SET_CWMIN 227 -#define WLC_GET_CWMAX 228 -#define WLC_SET_CWMAX 229 -#define WLC_GET_WET 230 -#define WLC_SET_WET 231 -#define WLC_GET_PUB 232 - - -#define WLC_GET_KEY_PRIMARY 235 -#define WLC_SET_KEY_PRIMARY 236 - -#define WLC_GET_ACI_ARGS 238 -#define WLC_SET_ACI_ARGS 239 -#define WLC_UNSET_CALLBACK 240 -#define WLC_SET_CALLBACK 241 -#define WLC_GET_RADAR 242 -#define WLC_SET_RADAR 243 -#define WLC_SET_SPECT_MANAGMENT 244 -#define WLC_GET_SPECT_MANAGMENT 245 -#define WLC_WDS_GET_REMOTE_HWADDR 246 -#define WLC_WDS_GET_WPA_SUP 247 -#define WLC_SET_CS_SCAN_TIMER 248 -#define WLC_GET_CS_SCAN_TIMER 249 -#define WLC_MEASURE_REQUEST 250 -#define WLC_INIT 251 -#define WLC_SEND_QUIET 252 -#define WLC_KEEPALIVE 253 -#define WLC_SEND_PWR_CONSTRAINT 254 -#define WLC_UPGRADE_STATUS 255 -#define WLC_CURRENT_PWR 256 -#define WLC_GET_SCAN_PASSIVE_TIME 257 -#define WLC_SET_SCAN_PASSIVE_TIME 258 -#define WLC_LEGACY_LINK_BEHAVIOR 259 -#define WLC_GET_CHANNELS_IN_COUNTRY 260 -#define WLC_GET_COUNTRY_LIST 261 -#define WLC_GET_VAR 262 -#define WLC_SET_VAR 263 -#define WLC_NVRAM_GET 264 -#define WLC_NVRAM_SET 265 -#define WLC_NVRAM_DUMP 266 -#define WLC_REBOOT 267 -#define WLC_SET_WSEC_PMK 268 -#define WLC_GET_AUTH_MODE 269 -#define WLC_SET_AUTH_MODE 270 -#define WLC_GET_WAKEENTRY 271 -#define WLC_SET_WAKEENTRY 272 -#define WLC_NDCONFIG_ITEM 273 -#define WLC_NVOTPW 274 -#define WLC_OTPW 275 -#define WLC_IOV_BLOCK_GET 276 -#define WLC_IOV_MODULES_GET 277 -#define WLC_SOFT_RESET 278 -#define WLC_GET_ALLOW_MODE 279 -#define WLC_SET_ALLOW_MODE 280 -#define WLC_GET_DESIRED_BSSID 281 -#define WLC_SET_DESIRED_BSSID 282 -#define WLC_DISASSOC_MYAP 283 -#define WLC_GET_NBANDS 284 -#define WLC_GET_BANDSTATES 285 -#define WLC_GET_WLC_BSS_INFO 286 -#define WLC_GET_ASSOC_INFO 287 -#define WLC_GET_OID_PHY 288 -#define WLC_SET_OID_PHY 289 -#define WLC_SET_ASSOC_TIME 290 -#define WLC_GET_DESIRED_SSID 291 -#define WLC_GET_CHANSPEC 292 -#define WLC_GET_ASSOC_STATE 293 -#define WLC_SET_PHY_STATE 294 -#define WLC_GET_SCAN_PENDING 295 -#define WLC_GET_SCANREQ_PENDING 296 -#define WLC_GET_PREV_ROAM_REASON 297 -#define WLC_SET_PREV_ROAM_REASON 298 -#define WLC_GET_BANDSTATES_PI 299 -#define WLC_GET_PHY_STATE 300 -#define WLC_GET_BSS_WPA_RSN 301 -#define WLC_GET_BSS_WPA2_RSN 302 -#define WLC_GET_BSS_BCN_TS 303 -#define WLC_GET_INT_DISASSOC 304 -#define WLC_SET_NUM_PEERS 305 -#define WLC_GET_NUM_BSS 306 -#define WLC_LAST 307 - - - -#define WL_RADIO_SW_DISABLE (1<<0) -#define WL_RADIO_HW_DISABLE (1<<1) -#define WL_RADIO_MPC_DISABLE (1<<2) -#define WL_RADIO_COUNTRY_DISABLE (1<<3) - - -#define WL_TXPWR_OVERRIDE (1U<<31) - -#define WL_PHY_PAVARS_LEN 6 - - -#define WL_DIAG_INTERRUPT 1 -#define WL_DIAG_LOOPBACK 2 -#define WL_DIAG_MEMORY 3 -#define WL_DIAG_LED 4 -#define WL_DIAG_REG 5 -#define WL_DIAG_SROM 6 -#define WL_DIAG_DMA 7 - -#define WL_DIAGERR_SUCCESS 0 -#define WL_DIAGERR_FAIL_TO_RUN 1 -#define WL_DIAGERR_NOT_SUPPORTED 2 -#define WL_DIAGERR_INTERRUPT_FAIL 3 -#define WL_DIAGERR_LOOPBACK_FAIL 4 -#define WL_DIAGERR_SROM_FAIL 5 -#define WL_DIAGERR_SROM_BADCRC 6 -#define WL_DIAGERR_REG_FAIL 7 -#define WL_DIAGERR_MEMORY_FAIL 8 -#define WL_DIAGERR_NOMEM 9 -#define WL_DIAGERR_DMA_FAIL 10 - -#define WL_DIAGERR_MEMORY_TIMEOUT 11 -#define WL_DIAGERR_MEMORY_BADPATTERN 12 - - -#define WLC_BAND_AUTO 0 -#define WLC_BAND_5G 1 -#define WLC_BAND_2G 2 -#define WLC_BAND_ALL 3 - - -#define WL_CHAN_FREQ_RANGE_2G 0 -#define WL_CHAN_FREQ_RANGE_5GL 1 -#define WL_CHAN_FREQ_RANGE_5GM 2 -#define WL_CHAN_FREQ_RANGE_5GH 3 - - -#define WLC_PHY_TYPE_A 0 -#define WLC_PHY_TYPE_B 1 -#define WLC_PHY_TYPE_G 2 -#define WLC_PHY_TYPE_N 4 -#define WLC_PHY_TYPE_LP 5 -#define WLC_PHY_TYPE_SSN 6 -#define WLC_PHY_TYPE_NULL 0xf - - -#define WLC_MACMODE_DISABLED 0 -#define WLC_MACMODE_DENY 1 -#define WLC_MACMODE_ALLOW 2 - - -#define GMODE_LEGACY_B 0 -#define GMODE_AUTO 1 -#define GMODE_ONLY 2 -#define GMODE_B_DEFERRED 3 -#define GMODE_PERFORMANCE 4 -#define GMODE_LRS 5 -#define GMODE_MAX 6 - - -#define WLC_PLCP_AUTO -1 -#define WLC_PLCP_SHORT 0 -#define WLC_PLCP_LONG 1 - - -#define WLC_PROTECTION_AUTO -1 -#define WLC_PROTECTION_OFF 0 -#define WLC_PROTECTION_ON 1 -#define WLC_PROTECTION_MMHDR_ONLY 2 -#define WLC_PROTECTION_CTS_ONLY 3 - - -#define WLC_PROTECTION_CTL_OFF 0 -#define WLC_PROTECTION_CTL_LOCAL 1 -#define WLC_PROTECTION_CTL_OVERLAP 2 - - -#define WLC_N_PROTECTION_OFF 0 -#define WLC_N_PROTECTION_OPTIONAL 1 -#define WLC_N_PROTECTION_20IN40 2 -#define WLC_N_PROTECTION_MIXEDMODE 3 - - -#define WLC_N_PREAMBLE_MIXEDMODE 0 -#define WLC_N_PREAMBLE_GF 1 - - -#define WLC_N_BW_20ALL 0 -#define WLC_N_BW_40ALL 1 -#define WLC_N_BW_20IN2G_40IN5G 2 - - -#define WLC_N_TXRX_CHAIN0 0 -#define WLC_N_TXRX_CHAIN1 1 - - -#define WLC_N_SGI_20 0x01 -#define WLC_N_SGI_40 0x02 - - -#define PM_OFF 0 -#define PM_MAX 1 -#define PM_FAST 2 - - -#define INTERFERE_NONE 0 -#define NON_WLAN 1 -#define WLAN_MANUAL 2 -#define WLAN_AUTO 3 -#define AUTO_ACTIVE (1 << 7) - -typedef struct wl_aci_args { - int enter_aci_thresh; - int exit_aci_thresh; - int usec_spin; - int glitch_delay; - uint16 nphy_adcpwr_enter_thresh; - uint16 nphy_adcpwr_exit_thresh; - uint16 nphy_repeat_ctr; - uint16 nphy_num_samples; - uint16 nphy_undetect_window_sz; - uint16 nphy_b_energy_lo_aci; - uint16 nphy_b_energy_md_aci; - uint16 nphy_b_energy_hi_aci; -} wl_aci_args_t; - -#define WL_ACI_ARGS_LEGACY_LENGTH 16 - - - -#define WL_ERROR_VAL 0x00000001 -#define WL_TRACE_VAL 0x00000002 -#define WL_PRHDRS_VAL 0x00000004 -#define WL_PRPKT_VAL 0x00000008 -#define WL_INFORM_VAL 0x00000010 -#define WL_TMP_VAL 0x00000020 -#define WL_OID_VAL 0x00000040 -#define WL_RATE_VAL 0x00000080 -#define WL_ASSOC_VAL 0x00000100 -#define WL_PRUSR_VAL 0x00000200 -#define WL_PS_VAL 0x00000400 -#define WL_TXPWR_VAL 0x00000800 -#define WL_PORT_VAL 0x00001000 -#define WL_DUAL_VAL 0x00002000 -#define WL_WSEC_VAL 0x00004000 -#define WL_WSEC_DUMP_VAL 0x00008000 -#define WL_LOG_VAL 0x00010000 -#define WL_NRSSI_VAL 0x00020000 -#define WL_LOFT_VAL 0x00040000 -#define WL_REGULATORY_VAL 0x00080000 -#define WL_PHYCAL_VAL 0x00100000 -#define WL_RADAR_VAL 0x00200000 -#define WL_MPC_VAL 0x00400000 -#define WL_APSTA_VAL 0x00800000 -#define WL_DFS_VAL 0x01000000 -#define WL_BA_VAL 0x02000000 -#define WL_MBSS_VAL 0x04000000 -#define WL_CAC_VAL 0x08000000 -#define WL_AMSDU_VAL 0x10000000 -#define WL_AMPDU_VAL 0x20000000 -#define WL_FFPLD_VAL 0x40000000 - - -#define WL_DPT_VAL 0x00000001 -#define WL_SCAN_VAL 0x00000002 -#define WL_WOWL_VAL 0x00000004 -#define WL_COEX_VAL 0x00000008 -#define WL_RTDC_VAL 0x00000010 -#define WL_BTA_VAL 0x00000040 - - -#define WL_LED_NUMGPIO 16 - - -#define WL_LED_OFF 0 -#define WL_LED_ON 1 -#define WL_LED_ACTIVITY 2 -#define WL_LED_RADIO 3 -#define WL_LED_ARADIO 4 -#define WL_LED_BRADIO 5 -#define WL_LED_BGMODE 6 -#define WL_LED_WI1 7 -#define WL_LED_WI2 8 -#define WL_LED_WI3 9 -#define WL_LED_ASSOC 10 -#define WL_LED_INACTIVE 11 -#define WL_LED_ASSOCACT 12 -#define WL_LED_NUMBEHAVIOR 13 - - -#define WL_LED_BEH_MASK 0x7f -#define WL_LED_AL_MASK 0x80 - - -#define WL_NUMCHANNELS 64 -#define WL_NUMCHANSPECS 100 - - -#define WL_WDS_WPA_ROLE_AUTH 0 -#define WL_WDS_WPA_ROLE_SUP 1 -#define WL_WDS_WPA_ROLE_AUTO 255 - - -#define WL_EVENTING_MASK_LEN 16 - - -#define VNDR_IE_CMD_LEN 4 - - -#define VNDR_IE_BEACON_FLAG 0x1 -#define VNDR_IE_PRBRSP_FLAG 0x2 -#define VNDR_IE_ASSOCRSP_FLAG 0x4 -#define VNDR_IE_AUTHRSP_FLAG 0x8 -#define VNDR_IE_PRBREQ_FLAG 0x10 -#define VNDR_IE_ASSOCREQ_FLAG 0x20 -#define VNDR_IE_CUSTOM_FLAG 0x100 - -#define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) - -typedef struct { - uint32 pktflag; - vndr_ie_t vndr_ie_data; -} vndr_ie_info_t; - -typedef struct { - int iecount; - vndr_ie_info_t vndr_ie_list[1]; -} vndr_ie_buf_t; - -typedef struct { - char cmd[VNDR_IE_CMD_LEN]; - vndr_ie_buf_t vndr_ie_buffer; -} vndr_ie_setbuf_t; - - - - -#define WL_JOIN_PREF_RSSI 1 -#define WL_JOIN_PREF_WPA 2 -#define WL_JOIN_PREF_BAND 3 - - -#define WLJP_BAND_ASSOC_PREF 255 - - -#define WL_WPA_ACP_MCS_ANY "\x00\x00\x00\x00" - -struct tsinfo_arg { - uint8 octets[3]; -}; - - -#define NFIFO 6 - -#define WL_CNT_T_VERSION 5 -#define WL_CNT_EXT_T_VERSION 1 - -typedef struct { - uint16 version; - uint16 length; - - - uint32 txframe; - uint32 txbyte; - uint32 txretrans; - uint32 txerror; - uint32 txctl; - uint32 txprshort; - uint32 txserr; - uint32 txnobuf; - uint32 txnoassoc; - uint32 txrunt; - uint32 txchit; - uint32 txcmiss; - - - uint32 txuflo; - uint32 txphyerr; - uint32 txphycrs; - - - uint32 rxframe; - uint32 rxbyte; - uint32 rxerror; - uint32 rxctl; - uint32 rxnobuf; - uint32 rxnondata; - uint32 rxbadds; - uint32 rxbadcm; - uint32 rxfragerr; - uint32 rxrunt; - uint32 rxgiant; - uint32 rxnoscb; - uint32 rxbadproto; - uint32 rxbadsrcmac; - uint32 rxbadda; - uint32 rxfilter; - - - uint32 rxoflo; - uint32 rxuflo[NFIFO]; - - uint32 d11cnt_txrts_off; - uint32 d11cnt_rxcrc_off; - uint32 d11cnt_txnocts_off; - - - uint32 dmade; - uint32 dmada; - uint32 dmape; - uint32 reset; - uint32 tbtt; - uint32 txdmawar; - uint32 pkt_callback_reg_fail; - - - uint32 txallfrm; - uint32 txrtsfrm; - uint32 txctsfrm; - uint32 txackfrm; - uint32 txdnlfrm; - uint32 txbcnfrm; - uint32 txfunfl[8]; - uint32 txtplunfl; - uint32 txphyerror; - uint32 rxfrmtoolong; - uint32 rxfrmtooshrt; - uint32 rxinvmachdr; - uint32 rxbadfcs; - uint32 rxbadplcp; - uint32 rxcrsglitch; - uint32 rxstrt; - uint32 rxdfrmucastmbss; - uint32 rxmfrmucastmbss; - uint32 rxcfrmucast; - uint32 rxrtsucast; - uint32 rxctsucast; - uint32 rxackucast; - uint32 rxdfrmocast; - uint32 rxmfrmocast; - uint32 rxcfrmocast; - uint32 rxrtsocast; - uint32 rxctsocast; - uint32 rxdfrmmcast; - uint32 rxmfrmmcast; - uint32 rxcfrmmcast; - uint32 rxbeaconmbss; - uint32 rxdfrmucastobss; - uint32 rxbeaconobss; - uint32 rxrsptmout; - uint32 bcntxcancl; - uint32 rxf0ovfl; - uint32 rxf1ovfl; - uint32 rxf2ovfl; - uint32 txsfovfl; - uint32 pmqovfl; - uint32 rxcgprqfrm; - uint32 rxcgprsqovfl; - uint32 txcgprsfail; - uint32 txcgprssuc; - uint32 prs_timeout; - uint32 rxnack; - uint32 frmscons; - uint32 txnack; - uint32 txglitch_nack; - uint32 txburst; - - - uint32 txfrag; - uint32 txmulti; - uint32 txfail; - uint32 txretry; - uint32 txretrie; - uint32 rxdup; - uint32 txrts; - uint32 txnocts; - uint32 txnoack; - uint32 rxfrag; - uint32 rxmulti; - uint32 rxcrc; - uint32 txfrmsnt; - uint32 rxundec; - - - uint32 tkipmicfaill; - uint32 tkipcntrmsr; - uint32 tkipreplay; - uint32 ccmpfmterr; - uint32 ccmpreplay; - uint32 ccmpundec; - uint32 fourwayfail; - uint32 wepundec; - uint32 wepicverr; - uint32 decsuccess; - uint32 tkipicverr; - uint32 wepexcluded; - - uint32 txchanrej; - uint32 psmwds; - uint32 phywatchdog; - - - uint32 prq_entries_handled; - uint32 prq_undirected_entries; - uint32 prq_bad_entries; - uint32 atim_suppress_count; - uint32 bcn_template_not_ready; - uint32 bcn_template_not_ready_done; - uint32 late_tbtt_dpc; - - - uint32 rx1mbps; - uint32 rx2mbps; - uint32 rx5mbps5; - uint32 rx6mbps; - uint32 rx9mbps; - uint32 rx11mbps; - uint32 rx12mbps; - uint32 rx18mbps; - uint32 rx24mbps; - uint32 rx36mbps; - uint32 rx48mbps; - uint32 rx54mbps; - uint32 rx108mbps; - uint32 rx162mbps; - uint32 rx216mbps; - uint32 rx270mbps; - uint32 rx324mbps; - uint32 rx378mbps; - uint32 rx432mbps; - uint32 rx486mbps; - uint32 rx540mbps; - - uint32 pktengrxducast; - uint32 pktengrxdmcast; -} wl_cnt_t; - -typedef struct { - uint16 version; - uint16 length; - - uint32 rxampdu_sgi; - uint32 rxampdu_stbc; - uint32 rxmpdu_sgi; - uint32 rxmpdu_stbc; - uint32 rxmcs0_40M; - uint32 rxmcs1_40M; - uint32 rxmcs2_40M; - uint32 rxmcs3_40M; - uint32 rxmcs4_40M; - uint32 rxmcs5_40M; - uint32 rxmcs6_40M; - uint32 rxmcs7_40M; - uint32 rxmcs32_40M; - - uint32 txfrmsnt_20Mlo; - uint32 txfrmsnt_20Mup; - uint32 txfrmsnt_40M; - - uint32 rx_20ul; -} wl_cnt_ext_t; - -#define WL_RXDIV_STATS_T_VERSION 1 -typedef struct { - uint16 version; - uint16 length; - - uint32 rxant[4]; -} wl_rxdiv_stats_t; - -#define WL_DELTA_STATS_T_VERSION 1 - -typedef struct { - uint16 version; - uint16 length; - - - uint32 txframe; - uint32 txbyte; - uint32 txretrans; - uint32 txfail; - - - uint32 rxframe; - uint32 rxbyte; - - - uint32 rx1mbps; - uint32 rx2mbps; - uint32 rx5mbps5; - uint32 rx6mbps; - uint32 rx9mbps; - uint32 rx11mbps; - uint32 rx12mbps; - uint32 rx18mbps; - uint32 rx24mbps; - uint32 rx36mbps; - uint32 rx48mbps; - uint32 rx54mbps; - uint32 rx108mbps; - uint32 rx162mbps; - uint32 rx216mbps; - uint32 rx270mbps; - uint32 rx324mbps; - uint32 rx378mbps; - uint32 rx432mbps; - uint32 rx486mbps; - uint32 rx540mbps; -} wl_delta_stats_t; - -#define WL_WME_CNT_VERSION 1 - -typedef struct { - uint32 packets; - uint32 bytes; -} wl_traffic_stats_t; - -typedef struct { - uint16 version; - uint16 length; - - wl_traffic_stats_t tx[AC_COUNT]; - wl_traffic_stats_t tx_failed[AC_COUNT]; - wl_traffic_stats_t rx[AC_COUNT]; - wl_traffic_stats_t rx_failed[AC_COUNT]; - - wl_traffic_stats_t forward[AC_COUNT]; - - wl_traffic_stats_t tx_expired[AC_COUNT]; - -} wl_wme_cnt_t; - - - -#define WLC_ROAM_TRIGGER_DEFAULT 0 -#define WLC_ROAM_TRIGGER_BANDWIDTH 1 -#define WLC_ROAM_TRIGGER_DISTANCE 2 -#define WLC_ROAM_TRIGGER_MAX_VALUE 2 - - -enum { - PFN_LIST_ORDER, - PFN_RSSI -}; - -enum { - DISABLE, - ENABLE -}; - -#define SORT_CRITERIA_BIT 0 -#define AUTO_NET_SWITCH_BIT 1 -#define ENABLE_BKGRD_SCAN_BIT 2 -#define IMMEDIATE_SCAN_BIT 3 -#define AUTO_CONNECT_BIT 4 - -#define SORT_CRITERIA_MASK 0x01 -#define AUTO_NET_SWITCH_MASK 0x02 -#define ENABLE_BKGRD_SCAN_MASK 0x04 -#define IMMEDIATE_SCAN_MASK 0x08 -#define AUTO_CONNECT_MASK 0x10 - -#define PFN_VERSION 1 - - -typedef struct wl_pfn_param { - int32 version; - int32 scan_freq; - int32 lost_network_timeout; - int16 flags; - int16 rssi_margin; -} wl_pfn_param_t; - -typedef struct wl_pfn { - wlc_ssid_t ssid; - int32 bss_type; - int32 infra; - int32 auth; - uint32 wpa_auth; - int32 wsec; -#ifdef WLPFN_AUTO_CONNECT - union { - wl_wsec_key_t sec_key; - wsec_pmk_t wpa_sec_key; - } pfn_security; -#endif -} wl_pfn_t; - - -#define TOE_TX_CSUM_OL 0x00000001 -#define TOE_RX_CSUM_OL 0x00000002 - - -#define TOE_ERRTEST_TX_CSUM 0x00000001 -#define TOE_ERRTEST_RX_CSUM 0x00000002 -#define TOE_ERRTEST_RX_CSUM2 0x00000004 - -struct toe_ol_stats_t { - - uint32 tx_summed; - - - uint32 tx_iph_fill; - uint32 tx_tcp_fill; - uint32 tx_udp_fill; - uint32 tx_icmp_fill; - - - uint32 rx_iph_good; - uint32 rx_iph_bad; - uint32 rx_tcp_good; - uint32 rx_tcp_bad; - uint32 rx_udp_good; - uint32 rx_udp_bad; - uint32 rx_icmp_good; - uint32 rx_icmp_bad; - - - uint32 tx_tcp_errinj; - uint32 tx_udp_errinj; - uint32 tx_icmp_errinj; - - - uint32 rx_tcp_errinj; - uint32 rx_udp_errinj; - uint32 rx_icmp_errinj; -}; - - -#define ARP_OL_AGENT 0x00000001 -#define ARP_OL_SNOOP 0x00000002 -#define ARP_OL_HOST_AUTO_REPLY 0x00000004 -#define ARP_OL_PEER_AUTO_REPLY 0x00000008 - - -#define ARP_ERRTEST_REPLY_PEER 0x1 -#define ARP_ERRTEST_REPLY_HOST 0x2 - -#define ARP_MULTIHOMING_MAX 8 - - -struct arp_ol_stats_t { - uint32 host_ip_entries; - uint32 host_ip_overflow; - - uint32 arp_table_entries; - uint32 arp_table_overflow; - - uint32 host_request; - uint32 host_reply; - uint32 host_service; - - uint32 peer_request; - uint32 peer_request_drop; - uint32 peer_reply; - uint32 peer_reply_drop; - uint32 peer_service; -}; - - - - - -typedef struct wl_keep_alive_pkt { - uint32 period_msec; - uint16 len_bytes; - uint8 data[1]; -} wl_keep_alive_pkt_t; - -#define WL_KEEP_ALIVE_FIXED_LEN OFFSETOF(wl_keep_alive_pkt_t, data) - - - - - -typedef enum wl_pkt_filter_type { - WL_PKT_FILTER_TYPE_PATTERN_MATCH -} wl_pkt_filter_type_t; - -#define WL_PKT_FILTER_TYPE wl_pkt_filter_type_t - - -typedef struct wl_pkt_filter_pattern { - uint32 offset; - uint32 size_bytes; - uint8 mask_and_pattern[1]; -} wl_pkt_filter_pattern_t; - - -typedef struct wl_pkt_filter { - uint32 id; - uint32 type; - uint32 negate_match; - union { - wl_pkt_filter_pattern_t pattern; - } u; -} wl_pkt_filter_t; - -#define WL_PKT_FILTER_FIXED_LEN OFFSETOF(wl_pkt_filter_t, u) -#define WL_PKT_FILTER_PATTERN_FIXED_LEN OFFSETOF(wl_pkt_filter_pattern_t, mask_and_pattern) - - -typedef struct wl_pkt_filter_enable { - uint32 id; - uint32 enable; -} wl_pkt_filter_enable_t; - - -typedef struct wl_pkt_filter_list { - uint32 num; - wl_pkt_filter_t filter[1]; -} wl_pkt_filter_list_t; - -#define WL_PKT_FILTER_LIST_FIXED_LEN OFFSETOF(wl_pkt_filter_list_t, filter) - - -typedef struct wl_pkt_filter_stats { - uint32 num_pkts_matched; - uint32 num_pkts_forwarded; - uint32 num_pkts_discarded; -} wl_pkt_filter_stats_t; - - -typedef struct wl_seq_cmd_ioctl { - uint32 cmd; - uint32 len; -} wl_seq_cmd_ioctl_t; - -#define WL_SEQ_CMD_ALIGN_BYTES 4 - - -#define WL_SEQ_CMDS_GET_IOCTL_FILTER(cmd) \ - (((cmd) == WLC_GET_MAGIC) || \ - ((cmd) == WLC_GET_VERSION) || \ - ((cmd) == WLC_GET_AP) || \ - ((cmd) == WLC_GET_INSTANCE)) - - - -#define WL_PKTENG_PER_TX_START 0x01 -#define WL_PKTENG_PER_TX_STOP 0x02 -#define WL_PKTENG_PER_RX_START 0x04 -#define WL_PKTENG_PER_RX_WITH_ACK_START 0x05 -#define WL_PKTENG_PER_TX_WITH_ACK_START 0x06 -#define WL_PKTENG_PER_RX_STOP 0x08 -#define WL_PKTENG_PER_MASK 0xff - -#define WL_PKTENG_SYNCHRONOUS 0x100 - -typedef struct wl_pkteng { - uint32 flags; - uint32 delay; - uint32 nframes; - uint32 length; - uint8 seqno; - struct ether_addr dest; - struct ether_addr src; -} wl_pkteng_t; - -#define NUM_80211b_RATES 4 -#define NUM_80211ag_RATES 8 -#define NUM_80211n_RATES 32 -#define NUM_80211_RATES (NUM_80211b_RATES+NUM_80211ag_RATES+NUM_80211n_RATES) -typedef struct wl_pkteng_stats { - uint32 lostfrmcnt; - int32 rssi; - int32 snr; - uint16 rxpktcnt[NUM_80211_RATES+1]; -} wl_pkteng_stats_t; - -#define WL_WOWL_MAGIC (1 << 0) -#define WL_WOWL_NET (1 << 1) -#define WL_WOWL_DIS (1 << 2) -#define WL_WOWL_RETR (1 << 3) -#define WL_WOWL_BCN (1 << 4) -#define WL_WOWL_TST (1 << 5) -#define WL_WOWL_BCAST (1 << 15) - -#define MAGIC_PKT_MINLEN 102 - -typedef struct { - uint masksize; - uint offset; - uint patternoffset; - uint patternsize; - - -} wl_wowl_pattern_t; - -typedef struct { - uint count; - wl_wowl_pattern_t pattern[1]; -} wl_wowl_pattern_list_t; - -typedef struct { - uint8 pci_wakeind; - uint16 ucode_wakeind; -} wl_wowl_wakeind_t; - - -typedef struct wl_txrate_class { - uint8 init_rate; - uint8 min_rate; - uint8 max_rate; -} wl_txrate_class_t; - - - - -#define WLC_OBSS_SCAN_PASSIVE_DWELL_DEFAULT 100 -#define WLC_OBSS_SCAN_PASSIVE_DWELL_MIN 5 -#define WLC_OBSS_SCAN_PASSIVE_DWELL_MAX 1000 -#define WLC_OBSS_SCAN_ACTIVE_DWELL_DEFAULT 20 -#define WLC_OBSS_SCAN_ACTIVE_DWELL_MIN 10 -#define WLC_OBSS_SCAN_ACTIVE_DWELL_MAX 1000 -#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_DEFAULT 300 -#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MIN 10 -#define WLC_OBSS_SCAN_WIDTHSCAN_INTERVAL_MAX 900 -#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_DEFAULT 5 -#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MIN 5 -#define WLC_OBSS_SCAN_CHANWIDTH_TRANSITION_DLY_MAX 100 -#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_DEFAULT 200 -#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MIN 200 -#define WLC_OBSS_SCAN_PASSIVE_TOTAL_PER_CHANNEL_MAX 10000 -#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_DEFAULT 20 -#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MIN 20 -#define WLC_OBSS_SCAN_ACTIVE_TOTAL_PER_CHANNEL_MAX 10000 -#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_DEFAULT 25 -#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MIN 0 -#define WLC_OBSS_SCAN_ACTIVITY_THRESHOLD_MAX 100 - - -typedef struct wl_obss_scan_arg { - int16 passive_dwell; - int16 active_dwell; - int16 bss_widthscan_interval; - int16 passive_total; - int16 active_total; - int16 chanwidth_transition_delay; - int16 activity_threshold; -} wl_obss_scan_arg_t; -#define WL_OBSS_SCAN_PARAM_LEN sizeof(wl_obss_scan_arg_t) -#define WL_MIN_NUM_OBSS_SCAN_ARG 7 - -#define WL_COEX_INFO_MASK 0x07 -#define WL_COEX_INFO_REQ 0x01 -#define WL_COEX_40MHZ_INTOLERANT 0x02 -#define WL_COEX_WIDTH20 0x04 - -typedef struct wl_action_obss_coex_req { - uint8 info; - uint8 num; - uint8 ch_list[1]; -} wl_action_obss_coex_req_t; - - -#define MAX_RSSI_LEVELS 8 - - -typedef struct wl_rssi_event { - - uint32 rate_limit_msec; - - uint8 num_rssi_levels; - - int8 rssi_levels[MAX_RSSI_LEVELS]; -} wl_rssi_event_t; - - - -#define WLFEATURE_DISABLE_11N 0x00000001 -#define WLFEATURE_DISABLE_11N_STBC_TX 0x00000002 -#define WLFEATURE_DISABLE_11N_STBC_RX 0x00000004 -#define WLFEATURE_DISABLE_11N_SGI_TX 0x00000008 -#define WLFEATURE_DISABLE_11N_SGI_RX 0x00000010 -#define WLFEATURE_DISABLE_11N_AMPDU_TX 0x00000020 -#define WLFEATURE_DISABLE_11N_AMPDU_RX 0x00000040 -#define WLFEATURE_DISABLE_11N_GF 0x00000080 - - - -#include - - -#include - - -typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_hdr { - struct ether_addr staAddr; - uint16 ieLen; -} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_hdr_t; - -typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_data { - sta_prbreq_wps_ie_hdr_t hdr; - uint8 ieData[1]; -} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_data_t; - -typedef BWL_PRE_PACKED_STRUCT struct sta_prbreq_wps_ie_list { - uint32 totLen; - uint8 ieDataList[1]; -} BWL_POST_PACKED_STRUCT sta_prbreq_wps_ie_list_t; - - -#include - -#endif diff --git a/drivers/net/wireless/bcm4329/linux_osl.c b/drivers/net/wireless/bcm4329/linux_osl.c deleted file mode 100644 index 242af39e0caa..000000000000 --- a/drivers/net/wireless/bcm4329/linux_osl.c +++ /dev/null @@ -1,620 +0,0 @@ -/* - * Linux OS Independent Layer - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: linux_osl.c,v 1.125.12.3.8.7 2010/05/04 21:10:04 Exp $ - */ - - -#define LINUX_OSL -#if defined(CHROMIUMOS_COMPAT_WIRELESS) -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#include - -#define PCI_CFG_RETRY 10 - -#define OS_HANDLE_MAGIC 0x1234abcd -#define BCM_MEM_FILENAME_LEN 24 - -#ifdef DHD_USE_STATIC_BUF -#define MAX_STATIC_BUF_NUM 16 -#define STATIC_BUF_SIZE (PAGE_SIZE*2) -#define STATIC_BUF_TOTAL_LEN (MAX_STATIC_BUF_NUM*STATIC_BUF_SIZE) -typedef struct bcm_static_buf { - struct semaphore static_sem; - unsigned char *buf_ptr; - unsigned char buf_use[MAX_STATIC_BUF_NUM]; -} bcm_static_buf_t; - -static bcm_static_buf_t *bcm_static_buf = 0; - -#define MAX_STATIC_PKT_NUM 8 -typedef struct bcm_static_pkt { - struct sk_buff *skb_4k[MAX_STATIC_PKT_NUM]; - struct sk_buff *skb_8k[MAX_STATIC_PKT_NUM]; - struct semaphore osl_pkt_sem; - unsigned char pkt_use[MAX_STATIC_PKT_NUM*2]; -} bcm_static_pkt_t; -static bcm_static_pkt_t *bcm_static_skb = 0; - -#endif -typedef struct bcm_mem_link { - struct bcm_mem_link *prev; - struct bcm_mem_link *next; - uint size; - int line; - char file[BCM_MEM_FILENAME_LEN]; -} bcm_mem_link_t; - -struct osl_info { - osl_pubinfo_t pub; - uint magic; - void *pdev; - uint malloced; - uint failed; - uint bustype; - bcm_mem_link_t *dbgmem_list; -}; - -static int16 linuxbcmerrormap[] = -{ 0, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -E2BIG, - -E2BIG, - -EBUSY, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EFAULT, - -ENOMEM, - -EOPNOTSUPP, - -EMSGSIZE, - -EINVAL, - -EPERM, - -ENOMEM, - -EINVAL, - -ERANGE, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EINVAL, - -EIO, - -ENODEV, - -EINVAL, - -EIO, - -EIO, - -EINVAL, - -EINVAL, - - - -#if BCME_LAST != -41 -#error "You need to add a OS error translation in the linuxbcmerrormap \ - for new error code defined in bcmutils.h" -#endif -}; - - -int -osl_error(int bcmerror) -{ - if (bcmerror > 0) - bcmerror = 0; - else if (bcmerror < BCME_LAST) - bcmerror = BCME_ERROR; - - - return linuxbcmerrormap[-bcmerror]; -} - -void * dhd_os_prealloc(int section, unsigned long size); -osl_t * -osl_attach(void *pdev, uint bustype, bool pkttag) -{ - osl_t *osh; - - osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); - ASSERT(osh); - - bzero(osh, sizeof(osl_t)); - - - ASSERT(ABS(BCME_LAST) == (ARRAYSIZE(linuxbcmerrormap) - 1)); - - osh->magic = OS_HANDLE_MAGIC; - osh->malloced = 0; - osh->failed = 0; - osh->dbgmem_list = NULL; - osh->pdev = pdev; - osh->pub.pkttag = pkttag; - osh->bustype = bustype; - - switch (bustype) { - case PCI_BUS: - case SI_BUS: - case PCMCIA_BUS: - osh->pub.mmbus = TRUE; - break; - case JTAG_BUS: - case SDIO_BUS: - case USB_BUS: - case SPI_BUS: - osh->pub.mmbus = FALSE; - break; - default: - ASSERT(FALSE); - break; - } - -#ifdef DHD_USE_STATIC_BUF - - - if (!bcm_static_buf) { - if (!(bcm_static_buf = (bcm_static_buf_t *)dhd_os_prealloc(3, STATIC_BUF_SIZE+ - STATIC_BUF_TOTAL_LEN))) { - printk("can not alloc static buf!\n"); - } - else - printk("alloc static buf at %x!\n", (unsigned int)bcm_static_buf); - - - init_MUTEX(&bcm_static_buf->static_sem); - - - bcm_static_buf->buf_ptr = (unsigned char *)bcm_static_buf + STATIC_BUF_SIZE; - - } - - if (!bcm_static_skb) - { - int i; - void *skb_buff_ptr = 0; - bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); - skb_buff_ptr = dhd_os_prealloc(4, 0); - - bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)*16); - for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++) - bcm_static_skb->pkt_use[i] = 0; - - init_MUTEX(&bcm_static_skb->osl_pkt_sem); - } -#endif - return osh; -} - -void -osl_detach(osl_t *osh) -{ - if (osh == NULL) - return; - -#ifdef DHD_USE_STATIC_BUF - if (bcm_static_buf) { - bcm_static_buf = 0; - } - if (bcm_static_skb) { - bcm_static_skb = 0; - } -#endif - ASSERT(osh->magic == OS_HANDLE_MAGIC); - kfree(osh); -} - - -void* -osl_pktget(osl_t *osh, uint len) -{ - struct sk_buff *skb; - - if ((skb = dev_alloc_skb(len))) { - skb_put(skb, len); - skb->priority = 0; - - - osh->pub.pktalloced++; - } - - return ((void*) skb); -} - - -void -osl_pktfree(osl_t *osh, void *p, bool send) -{ - struct sk_buff *skb, *nskb; - - skb = (struct sk_buff*) p; - - if (send && osh->pub.tx_fn) - osh->pub.tx_fn(osh->pub.tx_ctx, p, 0); - - - while (skb) { - nskb = skb->next; - skb->next = NULL; - - - if (skb->destructor) { - - dev_kfree_skb_any(skb); - } else { - - dev_kfree_skb(skb); - } - - osh->pub.pktalloced--; - - skb = nskb; - } -} - -#ifdef DHD_USE_STATIC_BUF -void* -osl_pktget_static(osl_t *osh, uint len) -{ - int i = 0; - struct sk_buff *skb; - - - if (len > (PAGE_SIZE*2)) - { - printk("Do we really need this big skb??\n"); - return osl_pktget(osh, len); - } - - - down(&bcm_static_skb->osl_pkt_sem); - if (len <= PAGE_SIZE) - { - - for (i = 0; i < MAX_STATIC_PKT_NUM; i++) - { - if (bcm_static_skb->pkt_use[i] == 0) - break; - } - - if (i != MAX_STATIC_PKT_NUM) - { - bcm_static_skb->pkt_use[i] = 1; - up(&bcm_static_skb->osl_pkt_sem); - - skb = bcm_static_skb->skb_4k[i]; - skb->tail = skb->data + len; - skb->len = len; - - return skb; - } - } - - - for (i = 0; i < MAX_STATIC_PKT_NUM; i++) - { - if (bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] == 0) - break; - } - - if (i != MAX_STATIC_PKT_NUM) - { - bcm_static_skb->pkt_use[i+MAX_STATIC_PKT_NUM] = 1; - up(&bcm_static_skb->osl_pkt_sem); - skb = bcm_static_skb->skb_8k[i]; - skb->tail = skb->data + len; - skb->len = len; - - return skb; - } - - - - up(&bcm_static_skb->osl_pkt_sem); - printk("all static pkt in use!\n"); - return osl_pktget(osh, len); -} - - -void -osl_pktfree_static(osl_t *osh, void *p, bool send) -{ - int i; - - for (i = 0; i < MAX_STATIC_PKT_NUM*2; i++) - { - if (p == bcm_static_skb->skb_4k[i]) - { - down(&bcm_static_skb->osl_pkt_sem); - bcm_static_skb->pkt_use[i] = 0; - up(&bcm_static_skb->osl_pkt_sem); - - - return; - } - } - return osl_pktfree(osh, p, send); -} -#endif -uint32 -osl_pci_read_config(osl_t *osh, uint offset, uint size) -{ - uint val = 0; - uint retry = PCI_CFG_RETRY; - - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - - - ASSERT(size == 4); - - do { - pci_read_config_dword(osh->pdev, offset, &val); - if (val != 0xffffffff) - break; - } while (retry--); - - - return (val); -} - -void -osl_pci_write_config(osl_t *osh, uint offset, uint size, uint val) -{ - uint retry = PCI_CFG_RETRY; - - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - - - ASSERT(size == 4); - - do { - pci_write_config_dword(osh->pdev, offset, val); - if (offset != PCI_BAR0_WIN) - break; - if (osl_pci_read_config(osh, offset, size) == val) - break; - } while (retry--); - -} - - -uint -osl_pci_bus(osl_t *osh) -{ - ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); - - return ((struct pci_dev *)osh->pdev)->bus->number; -} - - -uint -osl_pci_slot(osl_t *osh) -{ - ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); - - return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); -} - -static void -osl_pcmcia_attr(osl_t *osh, uint offset, char *buf, int size, bool write) -{ -} - -void -osl_pcmcia_read_attr(osl_t *osh, uint offset, void *buf, int size) -{ - osl_pcmcia_attr(osh, offset, (char *) buf, size, FALSE); -} - -void -osl_pcmcia_write_attr(osl_t *osh, uint offset, void *buf, int size) -{ - osl_pcmcia_attr(osh, offset, (char *) buf, size, TRUE); -} - - - -void* -osl_malloc(osl_t *osh, uint size) -{ - void *addr; - - - if (osh) - ASSERT(osh->magic == OS_HANDLE_MAGIC); - -#ifdef DHD_USE_STATIC_BUF - if (bcm_static_buf) - { - int i = 0; - if ((size >= PAGE_SIZE)&&(size <= STATIC_BUF_SIZE)) - { - down(&bcm_static_buf->static_sem); - - for (i = 0; i < MAX_STATIC_BUF_NUM; i++) - { - if (bcm_static_buf->buf_use[i] == 0) - break; - } - - if (i == MAX_STATIC_BUF_NUM) - { - up(&bcm_static_buf->static_sem); - printk("all static buff in use!\n"); - goto original; - } - - bcm_static_buf->buf_use[i] = 1; - up(&bcm_static_buf->static_sem); - - bzero(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i, size); - if (osh) - osh->malloced += size; - - return ((void *)(bcm_static_buf->buf_ptr+STATIC_BUF_SIZE*i)); - } - } -original: -#endif - - if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { - if (osh) - osh->failed++; - return (NULL); - } - if (osh) - osh->malloced += size; - - return (addr); -} - -void -osl_mfree(osl_t *osh, void *addr, uint size) -{ -#ifdef DHD_USE_STATIC_BUF - if (bcm_static_buf) - { - if ((addr > (void *)bcm_static_buf) && ((unsigned char *)addr - <= ((unsigned char *)bcm_static_buf + STATIC_BUF_TOTAL_LEN))) - { - int buf_idx = 0; - - buf_idx = ((unsigned char *)addr - bcm_static_buf->buf_ptr)/STATIC_BUF_SIZE; - - down(&bcm_static_buf->static_sem); - bcm_static_buf->buf_use[buf_idx] = 0; - up(&bcm_static_buf->static_sem); - - if (osh) { - ASSERT(osh->magic == OS_HANDLE_MAGIC); - osh->malloced -= size; - } - return; - } - } -#endif - if (osh) { - ASSERT(osh->magic == OS_HANDLE_MAGIC); - osh->malloced -= size; - } - kfree(addr); -} - -uint -osl_malloced(osl_t *osh) -{ - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - return (osh->malloced); -} - -uint -osl_malloc_failed(osl_t *osh) -{ - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - return (osh->failed); -} - -void* -osl_dma_alloc_consistent(osl_t *osh, uint size, ulong *pap) -{ - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - - return (pci_alloc_consistent(osh->pdev, size, (dma_addr_t*)pap)); -} - -void -osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) -{ - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - - pci_free_consistent(osh->pdev, size, va, (dma_addr_t)pa); -} - -uint -osl_dma_map(osl_t *osh, void *va, uint size, int direction) -{ - int dir; - - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; - return (pci_map_single(osh->pdev, va, size, dir)); -} - -void -osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction) -{ - int dir; - - ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); - dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; - pci_unmap_single(osh->pdev, (uint32)pa, size, dir); -} - - -void -osl_delay(uint usec) -{ - uint d; - - while (usec > 0) { - d = MIN(usec, 1000); - udelay(d); - usec -= d; - } -} - - - -void * -osl_pktdup(osl_t *osh, void *skb) -{ - void * p; - - if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) - return NULL; - - - if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); - - - osh->pub.pktalloced++; - return (p); -} diff --git a/drivers/net/wireless/bcm4329/miniopt.c b/drivers/net/wireless/bcm4329/miniopt.c deleted file mode 100644 index 6a184a75f06b..000000000000 --- a/drivers/net/wireless/bcm4329/miniopt.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * Description. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * $Id: miniopt.c,v 1.1.6.4 2009/09/25 00:32:01 Exp $ - */ - -/* ---- Include Files ---------------------------------------------------- */ - -#include -#include -#include -#include -#include "miniopt.h" - - -/* ---- Public Variables ------------------------------------------------- */ -/* ---- Private Constants and Types -------------------------------------- */ - - - -/* ---- Private Variables ------------------------------------------------ */ -/* ---- Private Function Prototypes -------------------------------------- */ -/* ---- Functions -------------------------------------------------------- */ - -/* ----------------------------------------------------------------------- */ -void -miniopt_init(miniopt_t *t, const char* name, const char* flags, bool longflags) -{ - static const char *null_flags = ""; - - memset(t, 0, sizeof(miniopt_t)); - t->name = name; - if (flags == NULL) - t->flags = null_flags; - else - t->flags = flags; - t->longflags = longflags; -} - - -/* ----------------------------------------------------------------------- */ -int -miniopt(miniopt_t *t, char **argv) -{ - int keylen; - char *p, *eq, *valstr, *endptr = NULL; - int err = 0; - - t->consumed = 0; - t->positional = FALSE; - memset(t->key, 0, MINIOPT_MAXKEY); - t->opt = '\0'; - t->valstr = NULL; - t->good_int = FALSE; - valstr = NULL; - - if (*argv == NULL) { - err = -1; - goto exit; - } - - p = *argv++; - t->consumed++; - - if (!t->opt_end && !strcmp(p, "--")) { - t->opt_end = TRUE; - if (*argv == NULL) { - err = -1; - goto exit; - } - p = *argv++; - t->consumed++; - } - - if (t->opt_end) { - t->positional = TRUE; - valstr = p; - } - else if (!strncmp(p, "--", 2)) { - eq = strchr(p, '='); - if (eq == NULL && !t->longflags) { - fprintf(stderr, - "%s: missing \" = \" in long param \"%s\"\n", t->name, p); - err = 1; - goto exit; - } - keylen = eq ? (eq - (p + 2)) : (int)strlen(p) - 2; - if (keylen > 63) keylen = 63; - memcpy(t->key, p + 2, keylen); - - if (eq) { - valstr = eq + 1; - if (*valstr == '\0') { - fprintf(stderr, - "%s: missing value after \" = \" in long param \"%s\"\n", - t->name, p); - err = 1; - goto exit; - } - } - } - else if (!strncmp(p, "-", 1)) { - t->opt = p[1]; - if (strlen(p) > 2) { - fprintf(stderr, - "%s: only single char options, error on param \"%s\"\n", - t->name, p); - err = 1; - goto exit; - } - if (strchr(t->flags, t->opt)) { - /* this is a flag option, no value expected */ - valstr = NULL; - } else { - if (*argv == NULL) { - fprintf(stderr, - "%s: missing value parameter after \"%s\"\n", t->name, p); - err = 1; - goto exit; - } - valstr = *argv; - argv++; - t->consumed++; - } - } else { - t->positional = TRUE; - valstr = p; - } - - /* parse valstr as int just in case */ - if (valstr) { - t->uval = (uint)strtoul(valstr, &endptr, 0); - t->val = (int)t->uval; - t->good_int = (*endptr == '\0'); - } - - t->valstr = valstr; - -exit: - if (err == 1) - t->opt = '?'; - - return err; -} diff --git a/drivers/net/wireless/bcm4329/sbutils.c b/drivers/net/wireless/bcm4329/sbutils.c deleted file mode 100644 index 46cd51010b78..000000000000 --- a/drivers/net/wireless/bcm4329/sbutils.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * Misc utility routines for accessing chip-specific features - * of the SiliconBackplane-based Broadcom chips. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: sbutils.c,v 1.662.4.10.2.7.4.2 2010/04/19 05:48:48 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "siutils_priv.h" - -/* local prototypes */ -static uint _sb_coreidx(si_info_t *sii, uint32 sba); -static uint _sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, - uint ncores); -static uint32 _sb_coresba(si_info_t *sii); -static void *_sb_setcoreidx(si_info_t *sii, uint coreidx); - -#define SET_SBREG(sii, r, mask, val) \ - W_SBREG((sii), (r), ((R_SBREG((sii), (r)) & ~(mask)) | (val))) -#define REGS2SB(va) (sbconfig_t*) ((int8*)(va) + SBCONFIGOFF) - -/* sonicsrev */ -#define SONICS_2_2 (SBIDL_RV_2_2 >> SBIDL_RV_SHIFT) -#define SONICS_2_3 (SBIDL_RV_2_3 >> SBIDL_RV_SHIFT) - -#define R_SBREG(sii, sbr) sb_read_sbreg((sii), (sbr)) -#define W_SBREG(sii, sbr, v) sb_write_sbreg((sii), (sbr), (v)) -#define AND_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) & (v))) -#define OR_SBREG(sii, sbr, v) W_SBREG((sii), (sbr), (R_SBREG((sii), (sbr)) | (v))) - -static uint32 -sb_read_sbreg(si_info_t *sii, volatile uint32 *sbr) -{ - uint8 tmp; - uint32 val, intr_val = 0; - - - /* - * compact flash only has 11 bits address, while we needs 12 bits address. - * MEM_SEG will be OR'd with other 11 bits address in hardware, - * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). - * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special - */ - if (PCMCIA(sii)) { - INTR_OFF(sii, intr_val); - tmp = 1; - OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); - sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ - } - - val = R_REG(sii->osh, sbr); - - if (PCMCIA(sii)) { - tmp = 0; - OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); - INTR_RESTORE(sii, intr_val); - } - - return (val); -} - -static void -sb_write_sbreg(si_info_t *sii, volatile uint32 *sbr, uint32 v) -{ - uint8 tmp; - volatile uint32 dummy; - uint32 intr_val = 0; - - - /* - * compact flash only has 11 bits address, while we needs 12 bits address. - * MEM_SEG will be OR'd with other 11 bits address in hardware, - * so we program MEM_SEG with 12th bit when necessary(access sb regsiters). - * For normal PCMCIA bus(CFTable_regwinsz > 2k), do nothing special - */ - if (PCMCIA(sii)) { - INTR_OFF(sii, intr_val); - tmp = 1; - OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); - sbr = (volatile uint32 *)((uintptr)sbr & ~(1 << 11)); /* mask out bit 11 */ - } - - if (BUSTYPE(sii->pub.bustype) == PCMCIA_BUS) { -#ifdef IL_BIGENDIAN - dummy = R_REG(sii->osh, sbr); - W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); - dummy = R_REG(sii->osh, sbr); - W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); -#else - dummy = R_REG(sii->osh, sbr); - W_REG(sii->osh, (volatile uint16 *)sbr, (uint16)(v & 0xffff)); - dummy = R_REG(sii->osh, sbr); - W_REG(sii->osh, ((volatile uint16 *)sbr + 1), (uint16)((v >> 16) & 0xffff)); -#endif /* IL_BIGENDIAN */ - } else - W_REG(sii->osh, sbr, v); - - if (PCMCIA(sii)) { - tmp = 0; - OSL_PCMCIA_WRITE_ATTR(sii->osh, MEM_SEG, &tmp, 1); - INTR_RESTORE(sii, intr_val); - } -} - -uint -sb_coreid(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_CC_MASK) >> SBIDH_CC_SHIFT); -} - -uint -sb_flag(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - return R_SBREG(sii, &sb->sbtpsflag) & SBTPS_NUM0_MASK; -} - -void -sb_setint(si_t *sih, int siflag) -{ - si_info_t *sii; - sbconfig_t *sb; - uint32 vec; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - if (siflag == -1) - vec = 0; - else - vec = 1 << siflag; - W_SBREG(sii, &sb->sbintvec, vec); -} - -/* return core index of the core with address 'sba' */ -static uint -_sb_coreidx(si_info_t *sii, uint32 sba) -{ - uint i; - - for (i = 0; i < sii->numcores; i ++) - if (sba == sii->common_info->coresba[i]) - return i; - return BADIDX; -} - -/* return core address of the current core */ -static uint32 -_sb_coresba(si_info_t *sii) -{ - uint32 sbaddr; - - - switch (BUSTYPE(sii->pub.bustype)) { - case SI_BUS: { - sbconfig_t *sb = REGS2SB(sii->curmap); - sbaddr = sb_base(R_SBREG(sii, &sb->sbadmatch0)); - break; - } - - case PCI_BUS: - sbaddr = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - break; - - case PCMCIA_BUS: { - uint8 tmp = 0; - OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1); - sbaddr = (uint32)tmp << 12; - OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1); - sbaddr |= (uint32)tmp << 16; - OSL_PCMCIA_READ_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1); - sbaddr |= (uint32)tmp << 24; - break; - } - - case SPI_BUS: - case SDIO_BUS: - sbaddr = (uint32)(uintptr)sii->curmap; - break; - - - default: - sbaddr = BADCOREADDR; - break; - } - - return sbaddr; -} - -uint -sb_corevendor(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - return ((R_SBREG(sii, &sb->sbidhigh) & SBIDH_VC_MASK) >> SBIDH_VC_SHIFT); -} - -uint -sb_corerev(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - uint sbidh; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - sbidh = R_SBREG(sii, &sb->sbidhigh); - - return (SBCOREREV(sbidh)); -} - -/* set core-specific control flags */ -void -sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - sbconfig_t *sb; - uint32 w; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - ASSERT((val & ~mask) == 0); - - /* mask and set */ - w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) | - (val << SBTML_SICF_SHIFT); - W_SBREG(sii, &sb->sbtmstatelow, w); -} - -/* set/clear core-specific control flags */ -uint32 -sb_core_cflags(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - sbconfig_t *sb; - uint32 w; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - ASSERT((val & ~mask) == 0); - - /* mask and set */ - if (mask || val) { - w = (R_SBREG(sii, &sb->sbtmstatelow) & ~(mask << SBTML_SICF_SHIFT)) | - (val << SBTML_SICF_SHIFT); - W_SBREG(sii, &sb->sbtmstatelow, w); - } - - /* return the new value - * for write operation, the following readback ensures the completion of write opration. - */ - return (R_SBREG(sii, &sb->sbtmstatelow) >> SBTML_SICF_SHIFT); -} - -/* set/clear core-specific status flags */ -uint32 -sb_core_sflags(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - sbconfig_t *sb; - uint32 w; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - ASSERT((val & ~mask) == 0); - ASSERT((mask & ~SISF_CORE_BITS) == 0); - - /* mask and set */ - if (mask || val) { - w = (R_SBREG(sii, &sb->sbtmstatehigh) & ~(mask << SBTMH_SISF_SHIFT)) | - (val << SBTMH_SISF_SHIFT); - W_SBREG(sii, &sb->sbtmstatehigh, w); - } - - /* return the new value */ - return (R_SBREG(sii, &sb->sbtmstatehigh) >> SBTMH_SISF_SHIFT); -} - -bool -sb_iscoreup(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - return ((R_SBREG(sii, &sb->sbtmstatelow) & - (SBTML_RESET | SBTML_REJ_MASK | (SICF_CLOCK_EN << SBTML_SICF_SHIFT))) == - (SICF_CLOCK_EN << SBTML_SICF_SHIFT)); -} - -/* - * Switch to 'coreidx', issue a single arbitrary 32bit register mask&set operation, - * switch back to the original core, and return the new value. - * - * When using the silicon backplane, no fidleing with interrupts or core switches are needed. - * - * Also, when using pci/pcie, we can optimize away the core switching for pci registers - * and (on newer pci cores) chipcommon registers. - */ -uint -sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) -{ - uint origidx = 0; - uint32 *r = NULL; - uint w; - uint intr_val = 0; - bool fast = FALSE; - si_info_t *sii; - - sii = SI_INFO(sih); - - ASSERT(GOODIDX(coreidx)); - ASSERT(regoff < SI_CORE_SIZE); - ASSERT((val & ~mask) == 0); - - if (coreidx >= SI_MAXCORES) - return 0; - - if (BUSTYPE(sii->pub.bustype) == SI_BUS) { - /* If internal bus, we can always get at everything */ - fast = TRUE; - /* map if does not exist */ - if (!sii->common_info->regs[coreidx]) { - sii->common_info->regs[coreidx] = - REG_MAP(sii->common_info->coresba[coreidx], SI_CORE_SIZE); - ASSERT(GOODREGS(sii->common_info->regs[coreidx])); - } - r = (uint32 *)((uchar *)sii->common_info->regs[coreidx] + regoff); - } else if (BUSTYPE(sii->pub.bustype) == PCI_BUS) { - /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ - - if ((sii->common_info->coreid[coreidx] == CC_CORE_ID) && SI_FAST(sii)) { - /* Chipc registers are mapped at 12KB */ - - fast = TRUE; - r = (uint32 *)((char *)sii->curmap + PCI_16KB0_CCREGS_OFFSET + regoff); - } else if (sii->pub.buscoreidx == coreidx) { - /* pci registers are at either in the last 2KB of an 8KB window - * or, in pcie and pci rev 13 at 8KB - */ - fast = TRUE; - if (SI_FAST(sii)) - r = (uint32 *)((char *)sii->curmap + - PCI_16KB0_PCIREGS_OFFSET + regoff); - else - r = (uint32 *)((char *)sii->curmap + - ((regoff >= SBCONFIGOFF) ? - PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + - regoff); - } - } - - if (!fast) { - INTR_OFF(sii, intr_val); - - /* save current core index */ - origidx = si_coreidx(&sii->pub); - - /* switch core */ - r = (uint32*) ((uchar*)sb_setcoreidx(&sii->pub, coreidx) + regoff); - } - ASSERT(r != NULL); - - /* mask and set */ - if (mask || val) { - if (regoff >= SBCONFIGOFF) { - w = (R_SBREG(sii, r) & ~mask) | val; - W_SBREG(sii, r, w); - } else { - w = (R_REG(sii->osh, r) & ~mask) | val; - W_REG(sii->osh, r, w); - } - } - - /* readback */ - if (regoff >= SBCONFIGOFF) - w = R_SBREG(sii, r); - else { - if ((CHIPID(sii->pub.chip) == BCM5354_CHIP_ID) && - (coreidx == SI_CC_IDX) && - (regoff == OFFSETOF(chipcregs_t, watchdog))) { - w = val; - } else - w = R_REG(sii->osh, r); - } - - if (!fast) { - /* restore core index */ - if (origidx != coreidx) - sb_setcoreidx(&sii->pub, origidx); - - INTR_RESTORE(sii, intr_val); - } - - return (w); -} - -/* Scan the enumeration space to find all cores starting from the given - * bus 'sbba'. Append coreid and other info to the lists in 'si'. 'sba' - * is the default core address at chip POR time and 'regs' is the virtual - * address that the default core is mapped at. 'ncores' is the number of - * cores expected on bus 'sbba'. It returns the total number of cores - * starting from bus 'sbba', inclusive. - */ -#define SB_MAXBUSES 2 -static uint -_sb_scan(si_info_t *sii, uint32 sba, void *regs, uint bus, uint32 sbba, uint numcores) -{ - uint next; - uint ncc = 0; - uint i; - - if (bus >= SB_MAXBUSES) { - SI_ERROR(("_sb_scan: bus 0x%08x at level %d is too deep to scan\n", sbba, bus)); - return 0; - } - SI_MSG(("_sb_scan: scan bus 0x%08x assume %u cores\n", sbba, numcores)); - - /* Scan all cores on the bus starting from core 0. - * Core addresses must be contiguous on each bus. - */ - for (i = 0, next = sii->numcores; i < numcores && next < SB_BUS_MAXCORES; i++, next++) { - sii->common_info->coresba[next] = sbba + (i * SI_CORE_SIZE); - - /* keep and reuse the initial register mapping */ - if ((BUSTYPE(sii->pub.bustype) == SI_BUS) && - (sii->common_info->coresba[next] == sba)) { - SI_MSG(("_sb_scan: reuse mapped regs %p for core %u\n", regs, next)); - sii->common_info->regs[next] = regs; - } - - /* change core to 'next' and read its coreid */ - sii->curmap = _sb_setcoreidx(sii, next); - sii->curidx = next; - - sii->common_info->coreid[next] = sb_coreid(&sii->pub); - - /* core specific processing... */ - /* chipc provides # cores */ - if (sii->common_info->coreid[next] == CC_CORE_ID) { - chipcregs_t *cc = (chipcregs_t *)sii->curmap; - uint32 ccrev = sb_corerev(&sii->pub); - - /* determine numcores - this is the total # cores in the chip */ - if (((ccrev == 4) || (ccrev >= 6))) - numcores = (R_REG(sii->osh, &cc->chipid) & CID_CC_MASK) >> - CID_CC_SHIFT; - else { - /* Older chips */ - uint chip = sii->pub.chip; - - if (chip == BCM4306_CHIP_ID) /* < 4306c0 */ - numcores = 6; - else if (chip == BCM4704_CHIP_ID) - numcores = 9; - else if (chip == BCM5365_CHIP_ID) - numcores = 7; - else { - SI_ERROR(("sb_chip2numcores: unsupported chip 0x%x\n", - chip)); - ASSERT(0); - numcores = 1; - } - } - SI_MSG(("_sb_scan: there are %u cores in the chip %s\n", numcores, - sii->pub.issim ? "QT" : "")); - } - /* scan bridged SB(s) and add results to the end of the list */ - else if (sii->common_info->coreid[next] == OCP_CORE_ID) { - sbconfig_t *sb = REGS2SB(sii->curmap); - uint32 nsbba = R_SBREG(sii, &sb->sbadmatch1); - uint nsbcc; - - sii->numcores = next + 1; - - if ((nsbba & 0xfff00000) != SI_ENUM_BASE) - continue; - nsbba &= 0xfffff000; - if (_sb_coreidx(sii, nsbba) != BADIDX) - continue; - - nsbcc = (R_SBREG(sii, &sb->sbtmstatehigh) & 0x000f0000) >> 16; - nsbcc = _sb_scan(sii, sba, regs, bus + 1, nsbba, nsbcc); - if (sbba == SI_ENUM_BASE) - numcores -= nsbcc; - ncc += nsbcc; - } - } - - SI_MSG(("_sb_scan: found %u cores on bus 0x%08x\n", i, sbba)); - - sii->numcores = i + ncc; - return sii->numcores; -} - -/* scan the sb enumerated space to identify all cores */ -void -sb_scan(si_t *sih, void *regs, uint devid) -{ - si_info_t *sii; - uint32 origsba; - - sii = SI_INFO(sih); - - /* Save the current core info and validate it later till we know - * for sure what is good and what is bad. - */ - origsba = _sb_coresba(sii); - - /* scan all SB(s) starting from SI_ENUM_BASE */ - sii->numcores = _sb_scan(sii, origsba, regs, 0, SI_ENUM_BASE, 1); -} - -/* - * This function changes logical "focus" to the indicated core; - * must be called with interrupts off. - * Moreover, callers should keep interrupts off during switching out of and back to d11 core - */ -void * -sb_setcoreidx(si_t *sih, uint coreidx) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - if (coreidx >= sii->numcores) - return (NULL); - - /* - * If the user has provided an interrupt mask enabled function, - * then assert interrupts are disabled before switching the core. - */ - ASSERT((sii->intrsenabled_fn == NULL) || !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); - - sii->curmap = _sb_setcoreidx(sii, coreidx); - sii->curidx = coreidx; - - return (sii->curmap); -} - -/* This function changes the logical "focus" to the indicated core. - * Return the current core's virtual address. - */ -static void * -_sb_setcoreidx(si_info_t *sii, uint coreidx) -{ - uint32 sbaddr = sii->common_info->coresba[coreidx]; - void *regs; - - switch (BUSTYPE(sii->pub.bustype)) { - case SI_BUS: - /* map new one */ - if (!sii->common_info->regs[coreidx]) { - sii->common_info->regs[coreidx] = REG_MAP(sbaddr, SI_CORE_SIZE); - ASSERT(GOODREGS(sii->common_info->regs[coreidx])); - } - regs = sii->common_info->regs[coreidx]; - break; - - case PCI_BUS: - /* point bar0 window */ - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, sbaddr); - regs = sii->curmap; - break; - - case PCMCIA_BUS: { - uint8 tmp = (sbaddr >> 12) & 0x0f; - OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR0, &tmp, 1); - tmp = (sbaddr >> 16) & 0xff; - OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR1, &tmp, 1); - tmp = (sbaddr >> 24) & 0xff; - OSL_PCMCIA_WRITE_ATTR(sii->osh, PCMCIA_ADDR2, &tmp, 1); - regs = sii->curmap; - break; - } - case SPI_BUS: - case SDIO_BUS: - /* map new one */ - if (!sii->common_info->regs[coreidx]) { - sii->common_info->regs[coreidx] = (void *)(uintptr)sbaddr; - ASSERT(GOODREGS(sii->common_info->regs[coreidx])); - } - regs = sii->common_info->regs[coreidx]; - break; - - - default: - ASSERT(0); - regs = NULL; - break; - } - - return regs; -} - -/* Return the address of sbadmatch0/1/2/3 register */ -static volatile uint32 * -sb_admatch(si_info_t *sii, uint asidx) -{ - sbconfig_t *sb; - volatile uint32 *addrm; - - sb = REGS2SB(sii->curmap); - - switch (asidx) { - case 0: - addrm = &sb->sbadmatch0; - break; - - case 1: - addrm = &sb->sbadmatch1; - break; - - case 2: - addrm = &sb->sbadmatch2; - break; - - case 3: - addrm = &sb->sbadmatch3; - break; - - default: - SI_ERROR(("%s: Address space index (%d) out of range\n", __FUNCTION__, asidx)); - return 0; - } - - return (addrm); -} - -/* Return the number of address spaces in current core */ -int -sb_numaddrspaces(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - - sii = SI_INFO(sih); - sb = REGS2SB(sii->curmap); - - /* + 1 because of enumeration space */ - return ((R_SBREG(sii, &sb->sbidlow) & SBIDL_AR_MASK) >> SBIDL_AR_SHIFT) + 1; -} - -/* Return the address of the nth address space in the current core */ -uint32 -sb_addrspace(si_t *sih, uint asidx) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - return (sb_base(R_SBREG(sii, sb_admatch(sii, asidx)))); -} - -/* Return the size of the nth address space in the current core */ -uint32 -sb_addrspacesize(si_t *sih, uint asidx) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - return (sb_size(R_SBREG(sii, sb_admatch(sii, asidx)))); -} - - -/* do buffered registers update */ -void -sb_commit(si_t *sih) -{ - si_info_t *sii; - uint origidx; - uint intr_val = 0; - - sii = SI_INFO(sih); - - origidx = sii->curidx; - ASSERT(GOODIDX(origidx)); - - INTR_OFF(sii, intr_val); - - /* switch over to chipcommon core if there is one, else use pci */ - if (sii->pub.ccrev != NOREV) { - chipcregs_t *ccregs = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); - - /* do the buffer registers update */ - W_REG(sii->osh, &ccregs->broadcastaddress, SB_COMMIT); - W_REG(sii->osh, &ccregs->broadcastdata, 0x0); - } else - ASSERT(0); - - /* restore core index */ - sb_setcoreidx(sih, origidx); - INTR_RESTORE(sii, intr_val); -} - -void -sb_core_disable(si_t *sih, uint32 bits) -{ - si_info_t *sii; - volatile uint32 dummy; - sbconfig_t *sb; - - sii = SI_INFO(sih); - - ASSERT(GOODREGS(sii->curmap)); - sb = REGS2SB(sii->curmap); - - /* if core is already in reset, just return */ - if (R_SBREG(sii, &sb->sbtmstatelow) & SBTML_RESET) - return; - - /* if clocks are not enabled, put into reset and return */ - if ((R_SBREG(sii, &sb->sbtmstatelow) & (SICF_CLOCK_EN << SBTML_SICF_SHIFT)) == 0) - goto disable; - - /* set target reject and spin until busy is clear (preserve core-specific bits) */ - OR_SBREG(sii, &sb->sbtmstatelow, SBTML_REJ); - dummy = R_SBREG(sii, &sb->sbtmstatelow); - OSL_DELAY(1); - SPINWAIT((R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY), 100000); - if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_BUSY) - SI_ERROR(("%s: target state still busy\n", __FUNCTION__)); - - if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) { - OR_SBREG(sii, &sb->sbimstate, SBIM_RJ); - dummy = R_SBREG(sii, &sb->sbimstate); - OSL_DELAY(1); - SPINWAIT((R_SBREG(sii, &sb->sbimstate) & SBIM_BY), 100000); - } - - /* set reset and reject while enabling the clocks */ - W_SBREG(sii, &sb->sbtmstatelow, - (((bits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | - SBTML_REJ | SBTML_RESET)); - dummy = R_SBREG(sii, &sb->sbtmstatelow); - OSL_DELAY(10); - - /* don't forget to clear the initiator reject bit */ - if (R_SBREG(sii, &sb->sbidlow) & SBIDL_INIT) - AND_SBREG(sii, &sb->sbimstate, ~SBIM_RJ); - -disable: - /* leave reset and reject asserted */ - W_SBREG(sii, &sb->sbtmstatelow, ((bits << SBTML_SICF_SHIFT) | SBTML_REJ | SBTML_RESET)); - OSL_DELAY(1); -} - -/* reset and re-enable a core - * inputs: - * bits - core specific bits that are set during and after reset sequence - * resetbits - core specific bits that are set only during reset sequence - */ -void -sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits) -{ - si_info_t *sii; - sbconfig_t *sb; - volatile uint32 dummy; - - sii = SI_INFO(sih); - ASSERT(GOODREGS(sii->curmap)); - sb = REGS2SB(sii->curmap); - - /* - * Must do the disable sequence first to work for arbitrary current core state. - */ - sb_core_disable(sih, (bits | resetbits)); - - /* - * Now do the initialization sequence. - */ - - /* set reset while enabling the clock and forcing them on throughout the core */ - W_SBREG(sii, &sb->sbtmstatelow, - (((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT) | - SBTML_RESET)); - dummy = R_SBREG(sii, &sb->sbtmstatelow); - OSL_DELAY(1); - - if (R_SBREG(sii, &sb->sbtmstatehigh) & SBTMH_SERR) { - W_SBREG(sii, &sb->sbtmstatehigh, 0); - } - if ((dummy = R_SBREG(sii, &sb->sbimstate)) & (SBIM_IBE | SBIM_TO)) { - AND_SBREG(sii, &sb->sbimstate, ~(SBIM_IBE | SBIM_TO)); - } - - /* clear reset and allow it to propagate throughout the core */ - W_SBREG(sii, &sb->sbtmstatelow, - ((bits | resetbits | SICF_FGC | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)); - dummy = R_SBREG(sii, &sb->sbtmstatelow); - OSL_DELAY(1); - - /* leave clock enabled */ - W_SBREG(sii, &sb->sbtmstatelow, ((bits | SICF_CLOCK_EN) << SBTML_SICF_SHIFT)); - dummy = R_SBREG(sii, &sb->sbtmstatelow); - OSL_DELAY(1); -} - -void -sb_core_tofixup(si_t *sih) -{ - si_info_t *sii; - sbconfig_t *sb; - - sii = SI_INFO(sih); - - if ((BUSTYPE(sii->pub.bustype) != PCI_BUS) || PCIE(sii) || - (PCI(sii) && (sii->pub.buscorerev >= 5))) - return; - - ASSERT(GOODREGS(sii->curmap)); - sb = REGS2SB(sii->curmap); - - if (BUSTYPE(sii->pub.bustype) == SI_BUS) { - SET_SBREG(sii, &sb->sbimconfiglow, - SBIMCL_RTO_MASK | SBIMCL_STO_MASK, - (0x5 << SBIMCL_RTO_SHIFT) | 0x3); - } else { - if (sb_coreid(sih) == PCI_CORE_ID) { - SET_SBREG(sii, &sb->sbimconfiglow, - SBIMCL_RTO_MASK | SBIMCL_STO_MASK, - (0x3 << SBIMCL_RTO_SHIFT) | 0x2); - } else { - SET_SBREG(sii, &sb->sbimconfiglow, (SBIMCL_RTO_MASK | SBIMCL_STO_MASK), 0); - } - } - - sb_commit(sih); -} - -/* - * Set the initiator timeout for the "master core". - * The master core is defined to be the core in control - * of the chip and so it issues accesses to non-memory - * locations (Because of dma *any* core can access memeory). - * - * The routine uses the bus to decide who is the master: - * SI_BUS => mips - * JTAG_BUS => chipc - * PCI_BUS => pci or pcie - * PCMCIA_BUS => pcmcia - * SDIO_BUS => pcmcia - * - * This routine exists so callers can disable initiator - * timeouts so accesses to very slow devices like otp - * won't cause an abort. The routine allows arbitrary - * settings of the service and request timeouts, though. - * - * Returns the timeout state before changing it or -1 - * on error. - */ - -#define TO_MASK (SBIMCL_RTO_MASK | SBIMCL_STO_MASK) - -uint32 -sb_set_initiator_to(si_t *sih, uint32 to, uint idx) -{ - si_info_t *sii; - uint origidx; - uint intr_val = 0; - uint32 tmp, ret = 0xffffffff; - sbconfig_t *sb; - - sii = SI_INFO(sih); - - if ((to & ~TO_MASK) != 0) - return ret; - - /* Figure out the master core */ - if (idx == BADIDX) { - switch (BUSTYPE(sii->pub.bustype)) { - case PCI_BUS: - idx = sii->pub.buscoreidx; - break; - case JTAG_BUS: - idx = SI_CC_IDX; - break; - case PCMCIA_BUS: - case SDIO_BUS: - idx = si_findcoreidx(sih, PCMCIA_CORE_ID, 0); - break; - case SI_BUS: - idx = si_findcoreidx(sih, MIPS33_CORE_ID, 0); - break; - default: - ASSERT(0); - } - if (idx == BADIDX) - return ret; - } - - INTR_OFF(sii, intr_val); - origidx = si_coreidx(sih); - - sb = REGS2SB(sb_setcoreidx(sih, idx)); - - tmp = R_SBREG(sii, &sb->sbimconfiglow); - ret = tmp & TO_MASK; - W_SBREG(sii, &sb->sbimconfiglow, (tmp & ~TO_MASK) | to); - - sb_commit(sih); - sb_setcoreidx(sih, origidx); - INTR_RESTORE(sii, intr_val); - return ret; -} - -uint32 -sb_base(uint32 admatch) -{ - uint32 base; - uint type; - - type = admatch & SBAM_TYPE_MASK; - ASSERT(type < 3); - - base = 0; - - if (type == 0) { - base = admatch & SBAM_BASE0_MASK; - } else if (type == 1) { - ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ - base = admatch & SBAM_BASE1_MASK; - } else if (type == 2) { - ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ - base = admatch & SBAM_BASE2_MASK; - } - - return (base); -} - -uint32 -sb_size(uint32 admatch) -{ - uint32 size; - uint type; - - type = admatch & SBAM_TYPE_MASK; - ASSERT(type < 3); - - size = 0; - - if (type == 0) { - size = 1 << (((admatch & SBAM_ADINT0_MASK) >> SBAM_ADINT0_SHIFT) + 1); - } else if (type == 1) { - ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ - size = 1 << (((admatch & SBAM_ADINT1_MASK) >> SBAM_ADINT1_SHIFT) + 1); - } else if (type == 2) { - ASSERT(!(admatch & SBAM_ADNEG)); /* neg not supported */ - size = 1 << (((admatch & SBAM_ADINT2_MASK) >> SBAM_ADINT2_SHIFT) + 1); - } - - return (size); -} diff --git a/drivers/net/wireless/bcm4329/siutils.c b/drivers/net/wireless/bcm4329/siutils.c deleted file mode 100644 index 1814db0f9dd6..000000000000 --- a/drivers/net/wireless/bcm4329/siutils.c +++ /dev/null @@ -1,1527 +0,0 @@ -/* - * Misc utility routines for accessing chip-specific features - * of the SiliconBackplane-based Broadcom chips. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: siutils.c,v 1.662.4.4.4.16.4.28 2010/06/23 21:37:54 Exp $ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "siutils_priv.h" - -/* local prototypes */ -static si_info_t *si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, - uint bustype, void *sdh, char **vars, uint *varsz); -static bool si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh); -static bool si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, - uint *origidx, void *regs); - - -/* global variable to indicate reservation/release of gpio's */ -static uint32 si_gpioreservation = 0; -static void *common_info_alloced = NULL; - -/* global flag to prevent shared resources from being initialized multiple times in si_attach() */ - -/* - * Allocate a si handle. - * devid - pci device id (used to determine chip#) - * osh - opaque OS handle - * regs - virtual address of initial core registers - * bustype - pci/pcmcia/sb/sdio/etc - * vars - pointer to a pointer area for "environment" variables - * varsz - pointer to int to return the size of the vars - */ -si_t * -si_attach(uint devid, osl_t *osh, void *regs, - uint bustype, void *sdh, char **vars, uint *varsz) -{ - si_info_t *sii; - - /* alloc si_info_t */ - if ((sii = MALLOC(osh, sizeof (si_info_t))) == NULL) { - SI_ERROR(("si_attach: malloc failed! malloced %d bytes\n", MALLOCED(osh))); - return (NULL); - } - - if (si_doattach(sii, devid, osh, regs, bustype, sdh, vars, varsz) == NULL) { - if (NULL != sii->common_info) - MFREE(osh, sii->common_info, sizeof(si_common_info_t)); - MFREE(osh, sii, sizeof(si_info_t)); - return (NULL); - } - sii->vars = vars ? *vars : NULL; - sii->varsz = varsz ? *varsz : 0; - - return (si_t *)sii; -} - -/* global kernel resource */ -static si_info_t ksii; - -static uint32 wd_msticks; /* watchdog timer ticks normalized to ms */ - -/* generic kernel variant of si_attach() */ -si_t * -si_kattach(osl_t *osh) -{ - static bool ksii_attached = FALSE; - - if (!ksii_attached) { - void *regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); - - if (si_doattach(&ksii, BCM4710_DEVICE_ID, osh, regs, - SI_BUS, NULL, - osh != SI_OSH ? &ksii.vars : NULL, - osh != SI_OSH ? &ksii.varsz : NULL) == NULL) { - if (NULL != ksii.common_info) - MFREE(osh, ksii.common_info, sizeof(si_common_info_t)); - SI_ERROR(("si_kattach: si_doattach failed\n")); - REG_UNMAP(regs); - return NULL; - } - REG_UNMAP(regs); - - /* save ticks normalized to ms for si_watchdog_ms() */ - if (PMUCTL_ENAB(&ksii.pub)) { - /* based on 32KHz ILP clock */ - wd_msticks = 32; - } else { - wd_msticks = ALP_CLOCK / 1000; - } - - ksii_attached = TRUE; - SI_MSG(("si_kattach done. ccrev = %d, wd_msticks = %d\n", - ksii.pub.ccrev, wd_msticks)); - } - - return &ksii.pub; -} - - -static bool -si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh) -{ - /* need to set memseg flag for CF card first before any sb registers access */ - if (BUSTYPE(bustype) == PCMCIA_BUS) - sii->memseg = TRUE; - - - if (BUSTYPE(bustype) == SDIO_BUS) { - int err; - uint8 clkset; - - /* Try forcing SDIO core to do ALPAvail request only */ - clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_ALP_AVAIL_REQ; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, clkset, &err); - if (!err) { - uint8 clkval; - - /* If register supported, wait for ALPAvail and then force ALP */ - clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, NULL); - if ((clkval & ~SBSDIO_AVBITS) == clkset) { - SPINWAIT(((clkval = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_CHIPCLKCSR, NULL)), !SBSDIO_ALPAV(clkval)), - PMU_MAX_TRANSITION_DLY); - if (!SBSDIO_ALPAV(clkval)) { - SI_ERROR(("timeout on ALPAV wait, clkval 0x%02x\n", - clkval)); - return FALSE; - } - clkset = SBSDIO_FORCE_HW_CLKREQ_OFF | SBSDIO_FORCE_ALP; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - clkset, &err); - OSL_DELAY(65); - } - } - - /* Also, disable the extra SDIO pull-ups */ - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SDIOPULLUP, 0, NULL); - } - - - return TRUE; -} - -static bool -si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin, - uint *origidx, void *regs) -{ - bool pci, pcie; - uint i; - uint pciidx, pcieidx, pcirev, pcierev; - - cc = si_setcoreidx(&sii->pub, SI_CC_IDX); - ASSERT((uintptr)cc); - - /* get chipcommon rev */ - sii->pub.ccrev = (int)si_corerev(&sii->pub); - - /* get chipcommon chipstatus */ - if (sii->pub.ccrev >= 11) - sii->pub.chipst = R_REG(sii->osh, &cc->chipstatus); - - /* get chipcommon capabilites */ - sii->pub.cccaps = R_REG(sii->osh, &cc->capabilities); - - /* get pmu rev and caps */ - if (sii->pub.cccaps & CC_CAP_PMU) { - sii->pub.pmucaps = R_REG(sii->osh, &cc->pmucapabilities); - sii->pub.pmurev = sii->pub.pmucaps & PCAP_REV_MASK; - } - - SI_MSG(("Chipc: rev %d, caps 0x%x, chipst 0x%x pmurev %d, pmucaps 0x%x\n", - sii->pub.ccrev, sii->pub.cccaps, sii->pub.chipst, sii->pub.pmurev, - sii->pub.pmucaps)); - - /* figure out bus/orignal core idx */ - sii->pub.buscoretype = NODEV_CORE_ID; - sii->pub.buscorerev = NOREV; - sii->pub.buscoreidx = BADIDX; - - pci = pcie = FALSE; - pcirev = pcierev = NOREV; - pciidx = pcieidx = BADIDX; - - for (i = 0; i < sii->numcores; i++) { - uint cid, crev; - - si_setcoreidx(&sii->pub, i); - cid = si_coreid(&sii->pub); - crev = si_corerev(&sii->pub); - - /* Display cores found */ - SI_MSG(("CORE[%d]: id 0x%x rev %d base 0x%x regs 0x%p\n", - i, cid, crev, sii->common_info->coresba[i], sii->common_info->regs[i])); - - if (BUSTYPE(bustype) == PCI_BUS) { - if (cid == PCI_CORE_ID) { - pciidx = i; - pcirev = crev; - pci = TRUE; - } else if (cid == PCIE_CORE_ID) { - pcieidx = i; - pcierev = crev; - pcie = TRUE; - } - } else if ((BUSTYPE(bustype) == PCMCIA_BUS) && - (cid == PCMCIA_CORE_ID)) { - sii->pub.buscorerev = crev; - sii->pub.buscoretype = cid; - sii->pub.buscoreidx = i; - } - else if (((BUSTYPE(bustype) == SDIO_BUS) || - (BUSTYPE(bustype) == SPI_BUS)) && - ((cid == PCMCIA_CORE_ID) || - (cid == SDIOD_CORE_ID))) { - sii->pub.buscorerev = crev; - sii->pub.buscoretype = cid; - sii->pub.buscoreidx = i; - } - - /* find the core idx before entering this func. */ - if ((savewin && (savewin == sii->common_info->coresba[i])) || - (regs == sii->common_info->regs[i])) - *origidx = i; - } - - - SI_MSG(("Buscore id/type/rev %d/0x%x/%d\n", sii->pub.buscoreidx, sii->pub.buscoretype, - sii->pub.buscorerev)); - - if (BUSTYPE(sii->pub.bustype) == SI_BUS && (CHIPID(sii->pub.chip) == BCM4712_CHIP_ID) && - (sii->pub.chippkg != BCM4712LARGE_PKG_ID) && (sii->pub.chiprev <= 3)) - OR_REG(sii->osh, &cc->slow_clk_ctl, SCC_SS_XTAL); - - - /* Make sure any on-chip ARM is off (in case strapping is wrong), or downloaded code was - * already running. - */ - if ((BUSTYPE(bustype) == SDIO_BUS) || (BUSTYPE(bustype) == SPI_BUS)) { - if (si_setcore(&sii->pub, ARM7S_CORE_ID, 0) || - si_setcore(&sii->pub, ARMCM3_CORE_ID, 0)) - si_core_disable(&sii->pub, 0); - } - - /* return to the original core */ - si_setcoreidx(&sii->pub, *origidx); - - return TRUE; -} - - - -static si_info_t * -si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, - uint bustype, void *sdh, char **vars, uint *varsz) -{ - struct si_pub *sih = &sii->pub; - uint32 w, savewin; - chipcregs_t *cc; - char *pvars = NULL; - uint origidx; - - ASSERT(GOODREGS(regs)); - - bzero((uchar*)sii, sizeof(si_info_t)); - - - { - if (NULL == (common_info_alloced = (void *)MALLOC(osh, sizeof(si_common_info_t)))) { - SI_ERROR(("si_doattach: malloc failed! malloced %dbytes\n", MALLOCED(osh))); - return (NULL); - } - bzero((uchar*)(common_info_alloced), sizeof(si_common_info_t)); - } - sii->common_info = (si_common_info_t *)common_info_alloced; - sii->common_info->attach_count++; - - savewin = 0; - - sih->buscoreidx = BADIDX; - - sii->curmap = regs; - sii->sdh = sdh; - sii->osh = osh; - - - /* find Chipcommon address */ - if (bustype == PCI_BUS) { - savewin = OSL_PCI_READ_CONFIG(sii->osh, PCI_BAR0_WIN, sizeof(uint32)); - if (!GOODCOREADDR(savewin, SI_ENUM_BASE)) - savewin = SI_ENUM_BASE; - OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, 4, SI_ENUM_BASE); - cc = (chipcregs_t *)regs; - } else - if ((bustype == SDIO_BUS) || (bustype == SPI_BUS)) { - cc = (chipcregs_t *)sii->curmap; - } else { - cc = (chipcregs_t *)REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); - } - - sih->bustype = bustype; - if (bustype != BUSTYPE(bustype)) { - SI_ERROR(("si_doattach: bus type %d does not match configured bus type %d\n", - bustype, BUSTYPE(bustype))); - return NULL; - } - - /* bus/core/clk setup for register access */ - if (!si_buscore_prep(sii, bustype, devid, sdh)) { - SI_ERROR(("si_doattach: si_core_clk_prep failed %d\n", bustype)); - return NULL; - } - - /* ChipID recognition. - * We assume we can read chipid at offset 0 from the regs arg. - * If we add other chiptypes (or if we need to support old sdio hosts w/o chipcommon), - * some way of recognizing them needs to be added here. - */ - w = R_REG(osh, &cc->chipid); - sih->socitype = (w & CID_TYPE_MASK) >> CID_TYPE_SHIFT; - /* Might as wll fill in chip id rev & pkg */ - sih->chip = w & CID_ID_MASK; - sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT; - sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT; - if ((CHIPID(sih->chip) == BCM4329_CHIP_ID) && (sih->chippkg != BCM4329_289PIN_PKG_ID)) - sih->chippkg = BCM4329_182PIN_PKG_ID; - sih->issim = IS_SIM(sih->chippkg); - - /* scan for cores */ - if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { - SI_MSG(("Found chip type SB (0x%08x)\n", w)); - sb_scan(&sii->pub, regs, devid); - } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { - SI_MSG(("Found chip type AI (0x%08x)\n", w)); - /* pass chipc address instead of original core base */ - ai_scan(&sii->pub, (void *)cc, devid); - } else { - SI_ERROR(("Found chip of unkown type (0x%08x)\n", w)); - return NULL; - } - /* no cores found, bail out */ - if (sii->numcores == 0) { - SI_ERROR(("si_doattach: could not find any cores\n")); - return NULL; - } - /* bus/core/clk setup */ - origidx = SI_CC_IDX; - if (!si_buscore_setup(sii, cc, bustype, savewin, &origidx, regs)) { - SI_ERROR(("si_doattach: si_buscore_setup failed\n")); - return NULL; - } - - pvars = NULL; - - - - if (sii->pub.ccrev >= 20) { - cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); - W_REG(osh, &cc->gpiopullup, 0); - W_REG(osh, &cc->gpiopulldown, 0); - si_setcoreidx(sih, origidx); - } - - /* Skip PMU initialization from the Dongle Host. - * Firmware will take care of it when it comes up. - */ - - - - return (sii); -} - -/* may be called with core in reset */ -void -si_detach(si_t *sih) -{ - si_info_t *sii; - uint idx; - - sii = SI_INFO(sih); - - if (sii == NULL) - return; - - if (BUSTYPE(sih->bustype) == SI_BUS) - for (idx = 0; idx < SI_MAXCORES; idx++) - if (sii->common_info->regs[idx]) { - REG_UNMAP(sii->common_info->regs[idx]); - sii->common_info->regs[idx] = NULL; - } - - - if (1 == sii->common_info->attach_count--) { - MFREE(sii->osh, sii->common_info, sizeof(si_common_info_t)); - common_info_alloced = NULL; - } - -#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) - if (sii != &ksii) -#endif /* !BCMBUSTYPE || (BCMBUSTYPE == SI_BUS) */ - MFREE(sii->osh, sii, sizeof(si_info_t)); -} - -void * -si_osh(si_t *sih) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - return sii->osh; -} - -void -si_setosh(si_t *sih, osl_t *osh) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - if (sii->osh != NULL) { - SI_ERROR(("osh is already set....\n")); - ASSERT(!sii->osh); - } - sii->osh = osh; -} - -/* register driver interrupt disabling and restoring callback functions */ -void -si_register_intr_callback(si_t *sih, void *intrsoff_fn, void *intrsrestore_fn, - void *intrsenabled_fn, void *intr_arg) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - sii->intr_arg = intr_arg; - sii->intrsoff_fn = (si_intrsoff_t)intrsoff_fn; - sii->intrsrestore_fn = (si_intrsrestore_t)intrsrestore_fn; - sii->intrsenabled_fn = (si_intrsenabled_t)intrsenabled_fn; - /* save current core id. when this function called, the current core - * must be the core which provides driver functions(il, et, wl, etc.) - */ - sii->dev_coreid = sii->common_info->coreid[sii->curidx]; -} - -void -si_deregister_intr_callback(si_t *sih) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - sii->intrsoff_fn = NULL; -} - -uint -si_intflag(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - if (CHIPTYPE(sih->socitype) == SOCI_SB) { - sbconfig_t *ccsbr = (sbconfig_t *)((uintptr)((ulong) - (sii->common_info->coresba[SI_CC_IDX]) + SBCONFIGOFF)); - return R_REG(sii->osh, &ccsbr->sbflagst); - } else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return R_REG(sii->osh, ((uint32 *)(uintptr) - (sii->common_info->oob_router + OOB_STATUSA))); - else { - ASSERT(0); - return 0; - } -} - -uint -si_flag(si_t *sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_flag(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_flag(sih); - else { - ASSERT(0); - return 0; - } -} - -void -si_setint(si_t *sih, int siflag) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - sb_setint(sih, siflag); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - ai_setint(sih, siflag); - else - ASSERT(0); -} - -uint -si_coreid(si_t *sih) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - return sii->common_info->coreid[sii->curidx]; -} - -uint -si_coreidx(si_t *sih) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - return sii->curidx; -} - -/* return the core-type instantiation # of the current core */ -uint -si_coreunit(si_t *sih) -{ - si_info_t *sii; - uint idx; - uint coreid; - uint coreunit; - uint i; - - sii = SI_INFO(sih); - coreunit = 0; - - idx = sii->curidx; - - ASSERT(GOODREGS(sii->curmap)); - coreid = si_coreid(sih); - - /* count the cores of our type */ - for (i = 0; i < idx; i++) - if (sii->common_info->coreid[i] == coreid) - coreunit++; - - return (coreunit); -} - -uint -si_corevendor(si_t *sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_corevendor(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_corevendor(sih); - else { - ASSERT(0); - return 0; - } -} - -bool -si_backplane64(si_t *sih) -{ - return ((sih->cccaps & CC_CAP_BKPLN64) != 0); -} - -uint -si_corerev(si_t *sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_corerev(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_corerev(sih); - else { - ASSERT(0); - return 0; - } -} - -/* return index of coreid or BADIDX if not found */ -uint -si_findcoreidx(si_t *sih, uint coreid, uint coreunit) -{ - si_info_t *sii; - uint found; - uint i; - - sii = SI_INFO(sih); - - found = 0; - - for (i = 0; i < sii->numcores; i++) - if (sii->common_info->coreid[i] == coreid) { - if (found == coreunit) - return (i); - found++; - } - - return (BADIDX); -} - -/* return list of found cores */ -uint -si_corelist(si_t *sih, uint coreid[]) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - bcopy((uchar*)sii->common_info->coreid, (uchar*)coreid, (sii->numcores * sizeof(uint))); - return (sii->numcores); -} - -/* return current register mapping */ -void * -si_coreregs(si_t *sih) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - ASSERT(GOODREGS(sii->curmap)); - - return (sii->curmap); -} - -/* - * This function changes logical "focus" to the indicated core; - * must be called with interrupts off. - * Moreover, callers should keep interrupts off during switching out of and back to d11 core - */ -void * -si_setcore(si_t *sih, uint coreid, uint coreunit) -{ - uint idx; - - idx = si_findcoreidx(sih, coreid, coreunit); - if (!GOODIDX(idx)) - return (NULL); - - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_setcoreidx(sih, idx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_setcoreidx(sih, idx); - else { - ASSERT(0); - return NULL; - } -} - -void * -si_setcoreidx(si_t *sih, uint coreidx) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_setcoreidx(sih, coreidx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_setcoreidx(sih, coreidx); - else { - ASSERT(0); - return NULL; - } -} - -/* Turn off interrupt as required by sb_setcore, before switch core */ -void *si_switch_core(si_t *sih, uint coreid, uint *origidx, uint *intr_val) -{ - void *cc; - si_info_t *sii; - - sii = SI_INFO(sih); - - INTR_OFF(sii, *intr_val); - *origidx = sii->curidx; - cc = si_setcore(sih, coreid, 0); - ASSERT(cc != NULL); - - return cc; -} - -/* restore coreidx and restore interrupt */ -void si_restore_core(si_t *sih, uint coreid, uint intr_val) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - si_setcoreidx(sih, coreid); - INTR_RESTORE(sii, intr_val); -} - -int -si_numaddrspaces(si_t *sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_numaddrspaces(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_numaddrspaces(sih); - else { - ASSERT(0); - return 0; - } -} - -uint32 -si_addrspace(si_t *sih, uint asidx) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_addrspace(sih, asidx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_addrspace(sih, asidx); - else { - ASSERT(0); - return 0; - } -} - -uint32 -si_addrspacesize(si_t *sih, uint asidx) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_addrspacesize(sih, asidx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_addrspacesize(sih, asidx); - else { - ASSERT(0); - return 0; - } -} - -uint32 -si_core_cflags(si_t *sih, uint32 mask, uint32 val) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_core_cflags(sih, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_core_cflags(sih, mask, val); - else { - ASSERT(0); - return 0; - } -} - -void -si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - sb_core_cflags_wo(sih, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - ai_core_cflags_wo(sih, mask, val); - else - ASSERT(0); -} - -uint32 -si_core_sflags(si_t *sih, uint32 mask, uint32 val) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_core_sflags(sih, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_core_sflags(sih, mask, val); - else { - ASSERT(0); - return 0; - } -} - -bool -si_iscoreup(si_t *sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_iscoreup(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_iscoreup(sih); - else { - ASSERT(0); - return FALSE; - } -} - -void -si_write_wrapperreg(si_t *sih, uint32 offset, uint32 val) -{ - /* only for 4319, no requirement for SOCI_SB */ - if (CHIPTYPE(sih->socitype) == SOCI_AI) { - ai_write_wrap_reg(sih, offset, val); - } - else - return; - - return; -} - -uint -si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - return sb_corereg(sih, coreidx, regoff, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - return ai_corereg(sih, coreidx, regoff, mask, val); - else { - ASSERT(0); - return 0; - } -} - -void -si_core_disable(si_t *sih, uint32 bits) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - sb_core_disable(sih, bits); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - ai_core_disable(sih, bits); -} - -void -si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - sb_core_reset(sih, bits, resetbits); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) - ai_core_reset(sih, bits, resetbits); -} - -void -si_core_tofixup(si_t *sih) -{ - if (CHIPTYPE(sih->socitype) == SOCI_SB) - sb_core_tofixup(sih); -} - -/* Run bist on current core. Caller needs to take care of core-specific bist hazards */ -int -si_corebist(si_t *sih) -{ - uint32 cflags; - int result = 0; - - /* Read core control flags */ - cflags = si_core_cflags(sih, 0, 0); - - /* Set bist & fgc */ - si_core_cflags(sih, 0, (SICF_BIST_EN | SICF_FGC)); - - /* Wait for bist done */ - SPINWAIT(((si_core_sflags(sih, 0, 0) & SISF_BIST_DONE) == 0), 100000); - - if (si_core_sflags(sih, 0, 0) & SISF_BIST_ERROR) - result = BCME_ERROR; - - /* Reset core control flags */ - si_core_cflags(sih, 0xffff, cflags); - - return result; -} - -static uint32 -factor6(uint32 x) -{ - switch (x) { - case CC_F6_2: return 2; - case CC_F6_3: return 3; - case CC_F6_4: return 4; - case CC_F6_5: return 5; - case CC_F6_6: return 6; - case CC_F6_7: return 7; - default: return 0; - } -} - -/* calculate the speed the SI would run at given a set of clockcontrol values */ -uint32 -si_clock_rate(uint32 pll_type, uint32 n, uint32 m) -{ - uint32 n1, n2, clock, m1, m2, m3, mc; - - n1 = n & CN_N1_MASK; - n2 = (n & CN_N2_MASK) >> CN_N2_SHIFT; - - if (pll_type == PLL_TYPE6) { - if (m & CC_T6_MMASK) - return CC_T6_M1; - else - return CC_T6_M0; - } else if ((pll_type == PLL_TYPE1) || - (pll_type == PLL_TYPE3) || - (pll_type == PLL_TYPE4) || - (pll_type == PLL_TYPE7)) { - n1 = factor6(n1); - n2 += CC_F5_BIAS; - } else if (pll_type == PLL_TYPE2) { - n1 += CC_T2_BIAS; - n2 += CC_T2_BIAS; - ASSERT((n1 >= 2) && (n1 <= 7)); - ASSERT((n2 >= 5) && (n2 <= 23)); - } else if (pll_type == PLL_TYPE5) { - return (100000000); - } else - ASSERT(0); - /* PLL types 3 and 7 use BASE2 (25Mhz) */ - if ((pll_type == PLL_TYPE3) || - (pll_type == PLL_TYPE7)) { - clock = CC_CLOCK_BASE2 * n1 * n2; - } else - clock = CC_CLOCK_BASE1 * n1 * n2; - - if (clock == 0) - return 0; - - m1 = m & CC_M1_MASK; - m2 = (m & CC_M2_MASK) >> CC_M2_SHIFT; - m3 = (m & CC_M3_MASK) >> CC_M3_SHIFT; - mc = (m & CC_MC_MASK) >> CC_MC_SHIFT; - - if ((pll_type == PLL_TYPE1) || - (pll_type == PLL_TYPE3) || - (pll_type == PLL_TYPE4) || - (pll_type == PLL_TYPE7)) { - m1 = factor6(m1); - if ((pll_type == PLL_TYPE1) || (pll_type == PLL_TYPE3)) - m2 += CC_F5_BIAS; - else - m2 = factor6(m2); - m3 = factor6(m3); - - switch (mc) { - case CC_MC_BYPASS: return (clock); - case CC_MC_M1: return (clock / m1); - case CC_MC_M1M2: return (clock / (m1 * m2)); - case CC_MC_M1M2M3: return (clock / (m1 * m2 * m3)); - case CC_MC_M1M3: return (clock / (m1 * m3)); - default: return (0); - } - } else { - ASSERT(pll_type == PLL_TYPE2); - - m1 += CC_T2_BIAS; - m2 += CC_T2M2_BIAS; - m3 += CC_T2_BIAS; - ASSERT((m1 >= 2) && (m1 <= 7)); - ASSERT((m2 >= 3) && (m2 <= 10)); - ASSERT((m3 >= 2) && (m3 <= 7)); - - if ((mc & CC_T2MC_M1BYP) == 0) - clock /= m1; - if ((mc & CC_T2MC_M2BYP) == 0) - clock /= m2; - if ((mc & CC_T2MC_M3BYP) == 0) - clock /= m3; - - return (clock); - } -} - - -/* set chip watchdog reset timer to fire in 'ticks' */ -void -si_watchdog(si_t *sih, uint ticks) -{ - if (PMUCTL_ENAB(sih)) { - - if ((sih->chip == BCM4319_CHIP_ID) && (sih->chiprev == 0) && (ticks != 0)) { - si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); - si_setcore(sih, USB20D_CORE_ID, 0); - si_core_disable(sih, 1); - si_setcore(sih, CC_CORE_ID, 0); - } - - if (ticks == 1) - ticks = 2; - si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, pmuwatchdog), ~0, ticks); - } else { - /* instant NMI */ - si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, watchdog), ~0, ticks); - } -} - -#if !defined(BCMBUSTYPE) || (BCMBUSTYPE == SI_BUS) -/* trigger watchdog reset after ms milliseconds */ -void -si_watchdog_ms(si_t *sih, uint32 ms) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - si_watchdog(sih, wd_msticks * ms); -} -#endif - - - -/* initialize the sdio core */ -void -si_sdio_init(si_t *sih) -{ - si_info_t *sii = SI_INFO(sih); - - if (((sih->buscoretype == PCMCIA_CORE_ID) && (sih->buscorerev >= 8)) || - (sih->buscoretype == SDIOD_CORE_ID)) { - uint idx; - sdpcmd_regs_t *sdpregs; - - /* get the current core index */ - idx = sii->curidx; - ASSERT(idx == si_findcoreidx(sih, D11_CORE_ID, 0)); - - /* switch to sdio core */ - if (!(sdpregs = (sdpcmd_regs_t *)si_setcore(sih, PCMCIA_CORE_ID, 0))) - sdpregs = (sdpcmd_regs_t *)si_setcore(sih, SDIOD_CORE_ID, 0); - ASSERT(sdpregs); - - SI_MSG(("si_sdio_init: For PCMCIA/SDIO Corerev %d, enable ints from core %d " - "through SD core %d (%p)\n", - sih->buscorerev, idx, sii->curidx, sdpregs)); - - /* enable backplane error and core interrupts */ - W_REG(sii->osh, &sdpregs->hostintmask, I_SBINT); - W_REG(sii->osh, &sdpregs->sbintmask, (I_SB_SERR | I_SB_RESPERR | (1 << idx))); - - /* switch back to previous core */ - si_setcoreidx(sih, idx); - } - - /* enable interrupts */ - bcmsdh_intr_enable(sii->sdh); - -} - - -/* change logical "focus" to the gpio core for optimized access */ -void * -si_gpiosetcore(si_t *sih) -{ - return (si_setcoreidx(sih, SI_CC_IDX)); -} - -/* mask&set gpiocontrol bits */ -uint32 -si_gpiocontrol(si_t *sih, uint32 mask, uint32 val, uint8 priority) -{ - uint regoff; - - regoff = 0; - - /* gpios could be shared on router platforms - * ignore reservation if it's high priority (e.g., test apps) - */ - if ((priority != GPIO_HI_PRIORITY) && - (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { - mask = priority ? (si_gpioreservation & mask) : - ((si_gpioreservation | mask) & ~(si_gpioreservation)); - val &= mask; - } - - regoff = OFFSETOF(chipcregs_t, gpiocontrol); - return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -} - -/* mask&set gpio output enable bits */ -uint32 -si_gpioouten(si_t *sih, uint32 mask, uint32 val, uint8 priority) -{ - uint regoff; - - regoff = 0; - - /* gpios could be shared on router platforms - * ignore reservation if it's high priority (e.g., test apps) - */ - if ((priority != GPIO_HI_PRIORITY) && - (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { - mask = priority ? (si_gpioreservation & mask) : - ((si_gpioreservation | mask) & ~(si_gpioreservation)); - val &= mask; - } - - regoff = OFFSETOF(chipcregs_t, gpioouten); - return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -} - -/* mask&set gpio output bits */ -uint32 -si_gpioout(si_t *sih, uint32 mask, uint32 val, uint8 priority) -{ - uint regoff; - - regoff = 0; - - /* gpios could be shared on router platforms - * ignore reservation if it's high priority (e.g., test apps) - */ - if ((priority != GPIO_HI_PRIORITY) && - (BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { - mask = priority ? (si_gpioreservation & mask) : - ((si_gpioreservation | mask) & ~(si_gpioreservation)); - val &= mask; - } - - regoff = OFFSETOF(chipcregs_t, gpioout); - return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -} - -/* reserve one gpio */ -uint32 -si_gpioreserve(si_t *sih, uint32 gpio_bitmask, uint8 priority) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - /* only cores on SI_BUS share GPIO's and only applcation users need to - * reserve/release GPIO - */ - if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { - ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); - return -1; - } - /* make sure only one bit is set */ - if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { - ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); - return -1; - } - - /* already reserved */ - if (si_gpioreservation & gpio_bitmask) - return -1; - /* set reservation */ - si_gpioreservation |= gpio_bitmask; - - return si_gpioreservation; -} - -/* release one gpio */ -/* - * releasing the gpio doesn't change the current value on the GPIO last write value - * persists till some one overwrites it - */ - -uint32 -si_gpiorelease(si_t *sih, uint32 gpio_bitmask, uint8 priority) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - /* only cores on SI_BUS share GPIO's and only applcation users need to - * reserve/release GPIO - */ - if ((BUSTYPE(sih->bustype) != SI_BUS) || (!priority)) { - ASSERT((BUSTYPE(sih->bustype) == SI_BUS) && (priority)); - return -1; - } - /* make sure only one bit is set */ - if ((!gpio_bitmask) || ((gpio_bitmask) & (gpio_bitmask - 1))) { - ASSERT((gpio_bitmask) && !((gpio_bitmask) & (gpio_bitmask - 1))); - return -1; - } - - /* already released */ - if (!(si_gpioreservation & gpio_bitmask)) - return -1; - - /* clear reservation */ - si_gpioreservation &= ~gpio_bitmask; - - return si_gpioreservation; -} - -/* return the current gpioin register value */ -uint32 -si_gpioin(si_t *sih) -{ - si_info_t *sii; - uint regoff; - - sii = SI_INFO(sih); - regoff = 0; - - regoff = OFFSETOF(chipcregs_t, gpioin); - return (si_corereg(sih, SI_CC_IDX, regoff, 0, 0)); -} - -/* mask&set gpio interrupt polarity bits */ -uint32 -si_gpiointpolarity(si_t *sih, uint32 mask, uint32 val, uint8 priority) -{ - si_info_t *sii; - uint regoff; - - sii = SI_INFO(sih); - regoff = 0; - - /* gpios could be shared on router platforms */ - if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { - mask = priority ? (si_gpioreservation & mask) : - ((si_gpioreservation | mask) & ~(si_gpioreservation)); - val &= mask; - } - - regoff = OFFSETOF(chipcregs_t, gpiointpolarity); - return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -} - -/* mask&set gpio interrupt mask bits */ -uint32 -si_gpiointmask(si_t *sih, uint32 mask, uint32 val, uint8 priority) -{ - si_info_t *sii; - uint regoff; - - sii = SI_INFO(sih); - regoff = 0; - - /* gpios could be shared on router platforms */ - if ((BUSTYPE(sih->bustype) == SI_BUS) && (val || mask)) { - mask = priority ? (si_gpioreservation & mask) : - ((si_gpioreservation | mask) & ~(si_gpioreservation)); - val &= mask; - } - - regoff = OFFSETOF(chipcregs_t, gpiointmask); - return (si_corereg(sih, SI_CC_IDX, regoff, mask, val)); -} - -/* assign the gpio to an led */ -uint32 -si_gpioled(si_t *sih, uint32 mask, uint32 val) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - if (sih->ccrev < 16) - return -1; - - /* gpio led powersave reg */ - return (si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, gpiotimeroutmask), mask, val)); -} - -/* mask&set gpio timer val */ -uint32 -si_gpiotimerval(si_t *sih, uint32 mask, uint32 gpiotimerval) -{ - si_info_t *sii; - - sii = SI_INFO(sih); - - if (sih->ccrev < 16) - return -1; - - return (si_corereg(sih, SI_CC_IDX, - OFFSETOF(chipcregs_t, gpiotimerval), mask, gpiotimerval)); -} - -uint32 -si_gpiopull(si_t *sih, bool updown, uint32 mask, uint32 val) -{ - si_info_t *sii; - uint offs; - - sii = SI_INFO(sih); - if (sih->ccrev < 20) - return -1; - - offs = (updown ? OFFSETOF(chipcregs_t, gpiopulldown) : OFFSETOF(chipcregs_t, gpiopullup)); - return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); -} - -uint32 -si_gpioevent(si_t *sih, uint regtype, uint32 mask, uint32 val) -{ - si_info_t *sii; - uint offs; - - sii = SI_INFO(sih); - if (sih->ccrev < 11) - return -1; - - if (regtype == GPIO_REGEVT) - offs = OFFSETOF(chipcregs_t, gpioevent); - else if (regtype == GPIO_REGEVT_INTMSK) - offs = OFFSETOF(chipcregs_t, gpioeventintmask); - else if (regtype == GPIO_REGEVT_INTPOL) - offs = OFFSETOF(chipcregs_t, gpioeventintpolarity); - else - return -1; - - return (si_corereg(sih, SI_CC_IDX, offs, mask, val)); -} - -void * -si_gpio_handler_register(si_t *sih, uint32 event, - bool level, gpio_handler_t cb, void *arg) -{ - si_info_t *sii; - gpioh_item_t *gi; - - ASSERT(event); - ASSERT(cb != NULL); - - sii = SI_INFO(sih); - if (sih->ccrev < 11) - return NULL; - - if ((gi = MALLOC(sii->osh, sizeof(gpioh_item_t))) == NULL) - return NULL; - - bzero(gi, sizeof(gpioh_item_t)); - gi->event = event; - gi->handler = cb; - gi->arg = arg; - gi->level = level; - - gi->next = sii->gpioh_head; - sii->gpioh_head = gi; - - return (void *)(gi); -} - -void -si_gpio_handler_unregister(si_t *sih, void *gpioh) -{ - si_info_t *sii; - gpioh_item_t *p, *n; - - sii = SI_INFO(sih); - if (sih->ccrev < 11) - return; - - ASSERT(sii->gpioh_head != NULL); - if ((void*)sii->gpioh_head == gpioh) { - sii->gpioh_head = sii->gpioh_head->next; - MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); - return; - } else { - p = sii->gpioh_head; - n = p->next; - while (n) { - if ((void*)n == gpioh) { - p->next = n->next; - MFREE(sii->osh, gpioh, sizeof(gpioh_item_t)); - return; - } - p = n; - n = n->next; - } - } - - ASSERT(0); /* Not found in list */ -} - -void -si_gpio_handler_process(si_t *sih) -{ - si_info_t *sii; - gpioh_item_t *h; - uint32 status; - uint32 level = si_gpioin(sih); - uint32 edge = si_gpioevent(sih, GPIO_REGEVT, 0, 0); - - sii = SI_INFO(sih); - for (h = sii->gpioh_head; h != NULL; h = h->next) { - if (h->handler) { - status = (h->level ? level : edge); - - if (status & h->event) - h->handler(status, h->arg); - } - } - - si_gpioevent(sih, GPIO_REGEVT, edge, edge); /* clear edge-trigger status */ -} - -uint32 -si_gpio_int_enable(si_t *sih, bool enable) -{ - si_info_t *sii; - uint offs; - - sii = SI_INFO(sih); - if (sih->ccrev < 11) - return -1; - - offs = OFFSETOF(chipcregs_t, intmask); - return (si_corereg(sih, SI_CC_IDX, offs, CI_GPIO, (enable ? CI_GPIO : 0))); -} - - -/* Return the RAM size of the SOCRAM core */ -uint32 -si_socram_size(si_t *sih) -{ - si_info_t *sii; - uint origidx; - uint intr_val = 0; - - sbsocramregs_t *regs; - bool wasup; - uint corerev; - uint32 coreinfo; - uint memsize = 0; - - sii = SI_INFO(sih); - - /* Block ints and save current core */ - INTR_OFF(sii, intr_val); - origidx = si_coreidx(sih); - - /* Switch to SOCRAM core */ - if (!(regs = si_setcore(sih, SOCRAM_CORE_ID, 0))) - goto done; - - /* Get info for determining size */ - if (!(wasup = si_iscoreup(sih))) - si_core_reset(sih, 0, 0); - corerev = si_corerev(sih); - coreinfo = R_REG(sii->osh, ®s->coreinfo); - - /* Calculate size from coreinfo based on rev */ - if (corerev == 0) - memsize = 1 << (16 + (coreinfo & SRCI_MS0_MASK)); - else if (corerev < 3) { - memsize = 1 << (SR_BSZ_BASE + (coreinfo & SRCI_SRBSZ_MASK)); - memsize *= (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; - } else { - uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT; - uint bsz = (coreinfo & SRCI_SRBSZ_MASK); - uint lss = (coreinfo & SRCI_LSS_MASK) >> SRCI_LSS_SHIFT; - if (lss != 0) - nb --; - memsize = nb * (1 << (bsz + SR_BSZ_BASE)); - if (lss != 0) - memsize += (1 << ((lss - 1) + SR_BSZ_BASE)); - } - - /* Return to previous state and core */ - if (!wasup) - si_core_disable(sih, 0); - si_setcoreidx(sih, origidx); - -done: - INTR_RESTORE(sii, intr_val); - - return memsize; -} - - -void -si_btcgpiowar(si_t *sih) -{ - si_info_t *sii; - uint origidx; - uint intr_val = 0; - chipcregs_t *cc; - - sii = SI_INFO(sih); - - /* Make sure that there is ChipCommon core present && - * UART_TX is strapped to 1 - */ - if (!(sih->cccaps & CC_CAP_UARTGPIO)) - return; - - /* si_corereg cannot be used as we have to guarantee 8-bit read/writes */ - INTR_OFF(sii, intr_val); - - origidx = si_coreidx(sih); - - cc = (chipcregs_t *)si_setcore(sih, CC_CORE_ID, 0); - ASSERT(cc != NULL); - - W_REG(sii->osh, &cc->uart0mcr, R_REG(sii->osh, &cc->uart0mcr) | 0x04); - - /* restore the original index */ - si_setcoreidx(sih, origidx); - - INTR_RESTORE(sii, intr_val); -} - -/* check if the device is removed */ -bool -si_deviceremoved(si_t *sih) -{ - uint32 w; - si_info_t *sii; - - sii = SI_INFO(sih); - - switch (BUSTYPE(sih->bustype)) { - case PCI_BUS: - ASSERT(sii->osh != NULL); - w = OSL_PCI_READ_CONFIG(sii->osh, PCI_CFG_VID, sizeof(uint32)); - if ((w & 0xFFFF) != VENDOR_BROADCOM) - return TRUE; - else - return FALSE; - default: - return FALSE; - } - return FALSE; -} diff --git a/drivers/net/wireless/bcm4329/siutils_priv.h b/drivers/net/wireless/bcm4329/siutils_priv.h deleted file mode 100644 index e8ad7e50958a..000000000000 --- a/drivers/net/wireless/bcm4329/siutils_priv.h +++ /dev/null @@ -1,213 +0,0 @@ -/* - * Include file private to the SOC Interconnect support files. - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: siutils_priv.h,v 1.3.10.5.4.2 2009/09/22 13:28:16 Exp $ - */ - -#ifndef _siutils_priv_h_ -#define _siutils_priv_h_ - -/* debug/trace */ -#define SI_ERROR(args) - -#define SI_MSG(args) - -#define IS_SIM(chippkg) ((chippkg == HDLSIM_PKG_ID) || (chippkg == HWSIM_PKG_ID)) - -typedef uint32 (*si_intrsoff_t)(void *intr_arg); -typedef void (*si_intrsrestore_t)(void *intr_arg, uint32 arg); -typedef bool (*si_intrsenabled_t)(void *intr_arg); - -typedef struct gpioh_item { - void *arg; - bool level; - gpio_handler_t handler; - uint32 event; - struct gpioh_item *next; -} gpioh_item_t; - -/* misc si info needed by some of the routines */ -typedef struct si_common_info { - void *regs[SI_MAXCORES]; /* other regs va */ - void *regs2[SI_MAXCORES]; /* va of each core second register set (usbh20) */ - uint coreid[SI_MAXCORES]; /* id of each core */ - uint32 cia[SI_MAXCORES]; /* erom cia entry for each core */ - uint32 cib[SI_MAXCORES]; /* erom cia entry for each core */ - uint32 coresba_size[SI_MAXCORES]; /* backplane address space size */ - uint32 coresba2_size[SI_MAXCORES]; /* second address space size */ - uint32 coresba[SI_MAXCORES]; /* backplane address of each core */ - uint32 coresba2[SI_MAXCORES]; /* address of each core second register set (usbh20) */ - void *wrappers[SI_MAXCORES]; /* other cores wrapper va */ - uint32 wrapba[SI_MAXCORES]; /* address of controlling wrapper */ - uint32 oob_router; /* oob router registers for axi */ - uint8 attach_count; -} si_common_info_t; - -typedef struct si_info { - struct si_pub pub; /* back plane public state (must be first field) */ - - void *osh; /* osl os handle */ - void *sdh; /* bcmsdh handle */ - void *pch; /* PCI/E core handle */ - uint dev_coreid; /* the core provides driver functions */ - void *intr_arg; /* interrupt callback function arg */ - si_intrsoff_t intrsoff_fn; /* turns chip interrupts off */ - si_intrsrestore_t intrsrestore_fn; /* restore chip interrupts */ - si_intrsenabled_t intrsenabled_fn; /* check if interrupts are enabled */ - - - gpioh_item_t *gpioh_head; /* GPIO event handlers list */ - - bool memseg; /* flag to toggle MEM_SEG register */ - - char *vars; - uint varsz; - - void *curmap; /* current regs va */ - - uint curidx; /* current core index */ - uint numcores; /* # discovered cores */ - void *curwrap; /* current wrapper va */ - si_common_info_t *common_info; /* Common information for all the cores in a chip */ -} si_info_t; - -#define SI_INFO(sih) (si_info_t *)(uintptr)sih - -#define GOODCOREADDR(x, b) (((x) >= (b)) && ((x) < ((b) + SI_MAXCORES * SI_CORE_SIZE)) && \ - ISALIGNED((x), SI_CORE_SIZE)) -#define GOODREGS(regs) ((regs) != NULL && ISALIGNED((uintptr)(regs), SI_CORE_SIZE)) -#define BADCOREADDR 0 -#define GOODIDX(idx) (((uint)idx) < SI_MAXCORES) -#define BADIDX (SI_MAXCORES + 1) -#define NOREV -1 /* Invalid rev */ - -#define PCI(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ - ((si)->pub.buscoretype == PCI_CORE_ID)) -#define PCIE(si) ((BUSTYPE((si)->pub.bustype) == PCI_BUS) && \ - ((si)->pub.buscoretype == PCIE_CORE_ID)) -#define PCMCIA(si) ((BUSTYPE((si)->pub.bustype) == PCMCIA_BUS) && ((si)->memseg == TRUE)) - -/* Newer chips can access PCI/PCIE and CC core without requiring to change - * PCI BAR0 WIN - */ -#define SI_FAST(si) (((si)->pub.buscoretype == PCIE_CORE_ID) || \ - (((si)->pub.buscoretype == PCI_CORE_ID) && (si)->pub.buscorerev >= 13)) - -#define PCIEREGS(si) (((char *)((si)->curmap) + PCI_16KB0_PCIREGS_OFFSET)) -#define CCREGS_FAST(si) (((char *)((si)->curmap) + PCI_16KB0_CCREGS_OFFSET)) - -/* - * Macros to disable/restore function core(D11, ENET, ILINE20, etc) interrupts before/ - * after core switching to avoid invalid register accesss inside ISR. - */ -#define INTR_OFF(si, intr_val) \ - if ((si)->intrsoff_fn && (si)->common_info->coreid[(si)->curidx] == (si)->dev_coreid) { \ - intr_val = (*(si)->intrsoff_fn)((si)->intr_arg); } -#define INTR_RESTORE(si, intr_val) \ - if ((si)->intrsrestore_fn && (si)->common_info->coreid[(si)->curidx] == (si)->dev_coreid) {\ - (*(si)->intrsrestore_fn)((si)->intr_arg, intr_val); } - -/* dynamic clock control defines */ -#define LPOMINFREQ 25000 /* low power oscillator min */ -#define LPOMAXFREQ 43000 /* low power oscillator max */ -#define XTALMINFREQ 19800000 /* 20 MHz - 1% */ -#define XTALMAXFREQ 20200000 /* 20 MHz + 1% */ -#define PCIMINFREQ 25000000 /* 25 MHz */ -#define PCIMAXFREQ 34000000 /* 33 MHz + fudge */ - -#define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ -#define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ - -#define PCI_FORCEHT(si) \ - (((PCIE(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ - ((PCI(si) || PCIE(si)) && (si->pub.chip == BCM4321_CHIP_ID))) - -/* GPIO Based LED powersave defines */ -#define DEFAULT_GPIO_ONTIME 10 /* Default: 10% on */ -#define DEFAULT_GPIO_OFFTIME 90 /* Default: 10% on */ - -#ifndef DEFAULT_GPIOTIMERVAL -#define DEFAULT_GPIOTIMERVAL ((DEFAULT_GPIO_ONTIME << GPIO_ONTIME_SHIFT) | DEFAULT_GPIO_OFFTIME) -#endif - -/* Silicon Backplane externs */ -extern void sb_scan(si_t *sih, void *regs, uint devid); -extern uint sb_coreid(si_t *sih); -extern uint sb_flag(si_t *sih); -extern void sb_setint(si_t *sih, int siflag); -extern uint sb_corevendor(si_t *sih); -extern uint sb_corerev(si_t *sih); -extern uint sb_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); -extern bool sb_iscoreup(si_t *sih); -extern void *sb_setcoreidx(si_t *sih, uint coreidx); -extern uint32 sb_core_cflags(si_t *sih, uint32 mask, uint32 val); -extern void sb_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); -extern uint32 sb_core_sflags(si_t *sih, uint32 mask, uint32 val); -extern void sb_commit(si_t *sih); -extern uint32 sb_base(uint32 admatch); -extern uint32 sb_size(uint32 admatch); -extern void sb_core_reset(si_t *sih, uint32 bits, uint32 resetbits); -extern void sb_core_tofixup(si_t *sih); -extern void sb_core_disable(si_t *sih, uint32 bits); -extern uint32 sb_addrspace(si_t *sih, uint asidx); -extern uint32 sb_addrspacesize(si_t *sih, uint asidx); -extern int sb_numaddrspaces(si_t *sih); - -extern uint32 sb_set_initiator_to(si_t *sih, uint32 to, uint idx); - - - -/* Wake-on-wireless-LAN (WOWL) */ -extern bool sb_pci_pmecap(si_t *sih); -struct osl_info; -extern bool sb_pci_fastpmecap(struct osl_info *osh); -extern bool sb_pci_pmeclr(si_t *sih); -extern void sb_pci_pmeen(si_t *sih); -extern uint sb_pcie_readreg(void *sih, uint addrtype, uint offset); - -/* AMBA Interconnect exported externs */ -extern si_t *ai_attach(uint pcidev, osl_t *osh, void *regs, uint bustype, - void *sdh, char **vars, uint *varsz); -extern si_t *ai_kattach(osl_t *osh); -extern void ai_scan(si_t *sih, void *regs, uint devid); - -extern uint ai_flag(si_t *sih); -extern void ai_setint(si_t *sih, int siflag); -extern uint ai_coreidx(si_t *sih); -extern uint ai_corevendor(si_t *sih); -extern uint ai_corerev(si_t *sih); -extern bool ai_iscoreup(si_t *sih); -extern void *ai_setcoreidx(si_t *sih, uint coreidx); -extern uint32 ai_core_cflags(si_t *sih, uint32 mask, uint32 val); -extern void ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); -extern uint32 ai_core_sflags(si_t *sih, uint32 mask, uint32 val); -extern uint ai_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); -extern void ai_core_reset(si_t *sih, uint32 bits, uint32 resetbits); -extern void ai_core_disable(si_t *sih, uint32 bits); -extern int ai_numaddrspaces(si_t *sih); -extern uint32 ai_addrspace(si_t *sih, uint asidx); -extern uint32 ai_addrspacesize(si_t *sih, uint asidx); -extern void ai_write_wrap_reg(si_t *sih, uint32 offset, uint32 val); - - -#endif /* _siutils_priv_h_ */ diff --git a/drivers/net/wireless/bcm4329/wl_cfg80211.c b/drivers/net/wireless/bcm4329/wl_cfg80211.c deleted file mode 100644 index 81491cb97746..000000000000 --- a/drivers/net/wireless/bcm4329/wl_cfg80211.c +++ /dev/null @@ -1,4491 +0,0 @@ -/* - * Linux Cfg80211 support - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: wl_cfg80211.c,v 1.1.2.28 2010/05/04 21:43:38 Exp $ - */ - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -static struct sdio_func *cfg80211_sdio_func = NULL; -static struct wl_dev *wl_cfg80211_dev = NULL; - -#ifdef WL_CFG80211_BACKTRACE -uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO | WL_DBG_DBG; -#else -uint32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO; -#endif - -#define WL_4329_FW_FILE "brcm/fw_4329.bin" -#define WL_4329_NVRAM_FILE "brcm/nvram_4329.txt" - -/* -** cfg80211_ops api/callback list -*/ -static int32 wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, - enum nl80211_iftype type, uint32 *flags, struct vif_params *params); -static int32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid); -static int32 wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request); -static int32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed); -static int32 wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params); -static int32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev); -static int32 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - uint8 *mac, struct station_info *sinfo); -static int32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, - struct net_device *dev, bool enabled, int32 timeout); -static int32 wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, - struct net_device *dev, const uint8 *addr, - const struct cfg80211_bitrate_mask *mask); -static int wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme); -static int32 wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - uint16 reason_code); -static int32 wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, int32 dbm); -static int32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm); -static int32 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx); -static int32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr, struct key_params *params); -static int32 wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr); -static int32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr, void *cookie, - void (*callback)(void *cookie, struct key_params *params)); -static int32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, - struct net_device *dev, uint8 key_idx); -static int32 wl_cfg80211_resume(struct wiphy *wiphy); -static int32 wl_cfg80211_suspend(struct wiphy *wiphy); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) -static int32 wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_pmksa *pmksa); -static int32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_pmksa *pmksa); -static int32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); -#endif -/* -** event & event Q handlers for cfg80211 interfaces -*/ -static int32 wl_create_event_handler(struct wl_priv *wl); -static void wl_destroy_event_handler(struct wl_priv *wl); -static int32 wl_event_handler(void *data); -static void wl_init_eq(struct wl_priv *wl); -static void wl_flush_eq(struct wl_priv *wl); -static void wl_lock_eq(struct wl_priv *wl); -static void wl_unlock_eq(struct wl_priv *wl); -static void wl_init_eq_lock(struct wl_priv *wl); -static void wl_init_eloop_handler(struct wl_event_loop *el); -static struct wl_event_q *wl_deq_event(struct wl_priv *wl); -static int32 wl_enq_event(struct wl_priv *wl, uint32 type, const wl_event_msg_t *msg, void *data); -static void wl_put_event(struct wl_event_q *e); -static void wl_wakeup_event(struct wl_priv *wl); -static int32 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data); -static int32 wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data); -static int32 wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data); -static int32 wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data); -static int32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data); -static int32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data); - -/* -** register/deregister sdio function -*/ -static struct sdio_func *wl_sdio_func(void); -static void wl_clear_sdio_func(void); - -/* -** ioctl utilites -*/ -static int32 wl_dev_bufvar_get(struct net_device *dev, int8 *name, int8 *buf, int32 buf_len); -static __used int32 wl_dev_bufvar_set(struct net_device *dev, int8 *name, int8 *buf, int32 len); -static int32 wl_dev_intvar_set(struct net_device *dev, int8 *name, int32 val); -static int32 wl_dev_intvar_get(struct net_device *dev, int8 *name, int32 *retval); -static int32 wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len); - - -/* -** cfg80211 set_wiphy_params utilities -*/ -static int32 wl_set_frag(struct net_device *dev, uint32 frag_threshold); -static int32 wl_set_rts(struct net_device *dev, uint32 frag_threshold); -static int32 wl_set_retry(struct net_device *dev, uint32 retry, bool l); - -/* -** wl profile utilities -*/ -static int32 wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, int32 item); -static void * wl_read_prof(struct wl_priv *wl, int32 item); -static void wl_init_prof(struct wl_profile *prof); - - -/* -** cfg80211 connect utilites -*/ -static int32 wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme); -static int32 wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme); -static int32 wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme); -static int32 wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme); -static int32 wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme); -static int32 wl_get_assoc_ies(struct wl_priv *wl); - - -/* -** information element utilities -*/ -static void wl_rst_ie(struct wl_priv *wl); -static int32 wl_add_ie(struct wl_priv *wl, uint8 t, uint8 l, uint8 *v); -static int32 wl_mrg_ie(struct wl_priv *wl, uint8 *ie_stream, uint16 ie_size); -static int32 wl_cp_ie(struct wl_priv *wl, uint8 *dst, uint16 dst_size); -static uint32 wl_get_ielen(struct wl_priv *wl); - - -static int32 wl_mode_to_nl80211_iftype(int32 mode); - -static struct wireless_dev *wl_alloc_wdev(int32 sizeof_iface, struct device *dev); -static void wl_free_wdev(struct wl_priv *wl); - -static int32 wl_inform_bss(struct wl_priv *wl); -static int32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); -static int32 wl_update_bss_info(struct wl_priv *wl); - -static int32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr, struct key_params *params); - - -/* -** key indianess swap utilities -*/ -static void swap_key_from_BE(struct wl_wsec_key *key); -static void swap_key_to_BE(struct wl_wsec_key *key); - - -/* -** wl_priv memory init/deinit utilities -*/ -static int32 wl_init_priv_mem(struct wl_priv *wl); -static void wl_deinit_priv_mem(struct wl_priv *wl); - -static void wl_delay(uint32 ms); - -/* -** store/restore cfg80211 instance data -*/ -static void wl_set_drvdata(struct wl_dev *dev, void *data); -static void *wl_get_drvdata(struct wl_dev *dev); - -/* -** ibss mode utilities -*/ -static bool wl_is_ibssmode(struct wl_priv *wl); -static bool wl_is_ibssstarter(struct wl_priv *wl); - -/* -** dongle up/down , default configuration utilities -*/ -static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e); -static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e); -static void wl_link_up(struct wl_priv *wl); -static void wl_link_down(struct wl_priv *wl); -static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype); -static int32 __wl_cfg80211_up(struct wl_priv *wl); -static int32 __wl_cfg80211_down(struct wl_priv *wl); -static int32 wl_dongle_probecap(struct wl_priv *wl); -static void wl_init_conf(struct wl_conf *conf); - -/* -** dongle configuration utilities -*/ -#ifndef EMBEDDED_PLATFORM -static int32 wl_dongle_mode(struct net_device *ndev, int32 iftype); -static int32 wl_dongle_country(struct net_device *ndev, uint8 ccode); -static int32 wl_dongle_up(struct net_device *ndev, uint32 up); -static int32 wl_dongle_power(struct net_device *ndev, uint32 power_mode); -static int32 wl_dongle_glom(struct net_device *ndev, uint32 glom, uint32 dongle_align); -static int32 wl_dongle_roam(struct net_device *ndev, uint32 roamvar, uint32 bcn_timeout); -static int32 wl_dongle_eventmsg(struct net_device *ndev); -static int32 wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time, - int32 scan_unassoc_time); -static int32 wl_dongle_offload(struct net_device *ndev, int32 arpoe, int32 arp_ol); -static int32 wl_pattern_atoh(int8 *src, int8 *dst); -static int32 wl_dongle_filter(struct net_device *ndev, uint32 filter_mode); -static int32 wl_update_wiphybands(struct wl_priv *wl); -#endif /* !EMBEDDED_PLATFORM */ -static int32 wl_config_dongle(struct wl_priv *wl, bool need_lock); - -/* -** iscan handler -*/ -static void wl_iscan_timer(ulong data); -static void wl_term_iscan(struct wl_priv *wl); -static int32 wl_init_iscan(struct wl_priv *wl); -static int32 wl_iscan_thread(void *data); -static int32 wl_dev_iovar_setbuf(struct net_device *dev, int8 *iovar, void *param, - int32 paramlen, void *bufptr, int32 buflen); -static int32 wl_dev_iovar_getbuf(struct net_device *dev, int8 *iovar, void *param, - int32 paramlen, void *bufptr, int32 buflen); -static int32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action); -static int32 wl_do_iscan(struct wl_priv *wl); -static int32 wl_wakeup_iscan(struct wl_iscan_ctrl *iscan); -static int32 wl_invoke_iscan(struct wl_priv *wl); -static int32 wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status, - struct wl_scan_results **bss_list); -static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted); -static void wl_init_iscan_eloop(struct wl_iscan_eloop *el); -static int32 wl_iscan_done(struct wl_priv *wl); -static int32 wl_iscan_pending(struct wl_priv *wl); -static int32 wl_iscan_inprogress(struct wl_priv *wl); -static int32 wl_iscan_aborted(struct wl_priv *wl); - -/* -** fw/nvram downloading handler -*/ -static void wl_init_fw(struct wl_fw_ctrl *fw); - -/* -* find most significant bit set -*/ -static __used uint32 wl_find_msb(uint16 bit16); - -/* -* update pmklist to dongle -*/ -static __used int32 wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, - int32 err); - - -#define WL_PRIV_GET() \ - ({ \ - struct wl_iface *ci; \ - if (unlikely(!(wl_cfg80211_dev && (ci = wl_get_drvdata(wl_cfg80211_dev))))) { \ - WL_ERR(("wl_cfg80211_dev is unavailable\n")); \ - BUG(); \ - } \ - ci_to_wl(ci); \ - }) - -#define CHECK_SYS_UP() \ - do { \ - struct wl_priv *wl = wiphy_to_wl(wiphy); \ - if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) { \ - WL_INFO(("device is not ready : status (%d)\n", (int)wl->status)); \ - return -EIO; \ - } \ - } while (0) - - -extern int dhd_wait_pend8021x(struct net_device *dev); - -#if (WL_DBG_LEVEL > 0) -#define WL_DBG_ESTR_MAX 32 -static int8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = { -"SET_SSID", "JOIN", "START", "AUTH", "AUTH_IND", -"DEAUTH", "DEAUTH_IND", "ASSOC", "ASSOC_IND", "REASSOC", -"REASSOC_IND", "DISASSOC", "DISASSOC_IND", "QUIET_START", "QUIET_END", -"BEACON_RX", "LINK", "MIC_ERROR", "NDIS_LINK", "ROAM", -"TXFAIL", "PMKID_CACHE", "RETROGRADE_TSF", "PRUNE", "AUTOAUTH", -"EAPOL_MSG", "SCAN_COMPLETE", "ADDTS_IND", "DELTS_IND", "BCNSENT_IND", -"BCNRX_MSG", "BCNLOST_MSG", "ROAM_PREP", "PFN_NET_FOUND", "PFN_NET_LOST", -"RESET_COMPLETE", "JOIN_START", "ROAM_START", "ASSOC_START", "IBSS_ASSOC", -"RADIO", "PSM_WATCHDOG", -"PROBREQ_MSG", -"SCAN_CONFIRM_IND", "PSK_SUP", "COUNTRY_CODE_CHANGED", "EXCEEDED_MEDIUM_TIME", "ICV_ERROR", -"UNICAST_DECODE_ERROR", "MULTICAST_DECODE_ERROR", "TRACE", -"IF", -"RSSI", "PFN_SCAN_COMPLETE", "ACTION_FRAME", "ACTION_FRAME_COMPLETE", -}; -#endif /* WL_DBG_LEVEL */ - -#define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -#define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = 5000 + (5 * (_channel)), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -#define RATE_TO_BASE100KBPS(rate) (((rate) * 10) / 2) -#define RATETAB_ENT(_rateid, _flags) \ - { \ - .bitrate = RATE_TO_BASE100KBPS(_rateid), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ - } - -static struct ieee80211_rate __wl_rates[] = { - RATETAB_ENT(WLC_RATE_1M, 0), - RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(WLC_RATE_6M, 0), - RATETAB_ENT(WLC_RATE_9M, 0), - RATETAB_ENT(WLC_RATE_12M, 0), - RATETAB_ENT(WLC_RATE_18M, 0), - RATETAB_ENT(WLC_RATE_24M, 0), - RATETAB_ENT(WLC_RATE_36M, 0), - RATETAB_ENT(WLC_RATE_48M, 0), - RATETAB_ENT(WLC_RATE_54M, 0), -}; - -#define wl_a_rates (__wl_rates + 4) -#define wl_a_rates_size 8 -#define wl_g_rates (__wl_rates + 0) -#define wl_g_rates_size 12 - -static struct ieee80211_channel __wl_2ghz_channels[] = { - CHAN2G(1, 2412, 0), - CHAN2G(2, 2417, 0), - CHAN2G(3, 2422, 0), - CHAN2G(4, 2427, 0), - CHAN2G(5, 2432, 0), - CHAN2G(6, 2437, 0), - CHAN2G(7, 2442, 0), - CHAN2G(8, 2447, 0), - CHAN2G(9, 2452, 0), - CHAN2G(10, 2457, 0), - CHAN2G(11, 2462, 0), - CHAN2G(12, 2467, 0), - CHAN2G(13, 2472, 0), - CHAN2G(14, 2484, 0), -}; - -static struct ieee80211_channel __wl_5ghz_a_channels[] = { - CHAN5G(34, 0), CHAN5G(36, 0), - CHAN5G(38, 0), CHAN5G(40, 0), - CHAN5G(42, 0), CHAN5G(44, 0), - CHAN5G(46, 0), CHAN5G(48, 0), - CHAN5G(52, 0), CHAN5G(56, 0), - CHAN5G(60, 0), CHAN5G(64, 0), - CHAN5G(100, 0), CHAN5G(104, 0), - CHAN5G(108, 0), CHAN5G(112, 0), - CHAN5G(116, 0), CHAN5G(120, 0), - CHAN5G(124, 0), CHAN5G(128, 0), - CHAN5G(132, 0), CHAN5G(136, 0), - CHAN5G(140, 0), CHAN5G(149, 0), - CHAN5G(153, 0), CHAN5G(157, 0), - CHAN5G(161, 0), CHAN5G(165, 0), - CHAN5G(184, 0), CHAN5G(188, 0), - CHAN5G(192, 0), CHAN5G(196, 0), - CHAN5G(200, 0), CHAN5G(204, 0), - CHAN5G(208, 0), CHAN5G(212, 0), - CHAN5G(216, 0), -}; - -static struct ieee80211_channel __wl_5ghz_n_channels[] = { - CHAN5G(32, 0), CHAN5G(34, 0), - CHAN5G(36, 0), CHAN5G(38, 0), - CHAN5G(40, 0), CHAN5G(42, 0), - CHAN5G(44, 0), CHAN5G(46, 0), - CHAN5G(48, 0), CHAN5G(50, 0), - CHAN5G(52, 0), CHAN5G(54, 0), - CHAN5G(56, 0), CHAN5G(58, 0), - CHAN5G(60, 0), CHAN5G(62, 0), - CHAN5G(64, 0), CHAN5G(66, 0), - CHAN5G(68, 0), CHAN5G(70, 0), - CHAN5G(72, 0), CHAN5G(74, 0), - CHAN5G(76, 0), CHAN5G(78, 0), - CHAN5G(80, 0), CHAN5G(82, 0), - CHAN5G(84, 0), CHAN5G(86, 0), - CHAN5G(88, 0), CHAN5G(90, 0), - CHAN5G(92, 0), CHAN5G(94, 0), - CHAN5G(96, 0), CHAN5G(98, 0), - CHAN5G(100, 0), CHAN5G(102, 0), - CHAN5G(104, 0), CHAN5G(106, 0), - CHAN5G(108, 0), CHAN5G(110, 0), - CHAN5G(112, 0), CHAN5G(114, 0), - CHAN5G(116, 0), CHAN5G(118, 0), - CHAN5G(120, 0), CHAN5G(122, 0), - CHAN5G(124, 0), CHAN5G(126, 0), - CHAN5G(128, 0), CHAN5G(130, 0), - CHAN5G(132, 0), CHAN5G(134, 0), - CHAN5G(136, 0), CHAN5G(138, 0), - CHAN5G(140, 0), CHAN5G(142, 0), - CHAN5G(144, 0), CHAN5G(145, 0), - CHAN5G(146, 0), CHAN5G(147, 0), - CHAN5G(148, 0), CHAN5G(149, 0), - CHAN5G(150, 0), CHAN5G(151, 0), - CHAN5G(152, 0), CHAN5G(153, 0), - CHAN5G(154, 0), CHAN5G(155, 0), - CHAN5G(156, 0), CHAN5G(157, 0), - CHAN5G(158, 0), CHAN5G(159, 0), - CHAN5G(160, 0), CHAN5G(161, 0), - CHAN5G(162, 0), CHAN5G(163, 0), - CHAN5G(164, 0), CHAN5G(165, 0), - CHAN5G(166, 0), CHAN5G(168, 0), - CHAN5G(170, 0), CHAN5G(172, 0), - CHAN5G(174, 0), CHAN5G(176, 0), - CHAN5G(178, 0), CHAN5G(180, 0), - CHAN5G(182, 0), CHAN5G(184, 0), - CHAN5G(186, 0), CHAN5G(188, 0), - CHAN5G(190, 0), CHAN5G(192, 0), - CHAN5G(194, 0), CHAN5G(196, 0), - CHAN5G(198, 0), CHAN5G(200, 0), - CHAN5G(202, 0), CHAN5G(204, 0), - CHAN5G(206, 0), CHAN5G(208, 0), - CHAN5G(210, 0), CHAN5G(212, 0), - CHAN5G(214, 0), CHAN5G(216, 0), - CHAN5G(218, 0), CHAN5G(220, 0), - CHAN5G(222, 0), CHAN5G(224, 0), - CHAN5G(226, 0), CHAN5G(228, 0), -}; - -static struct ieee80211_supported_band __wl_band_2ghz = { - .band = IEEE80211_BAND_2GHZ, - .channels = __wl_2ghz_channels, - .n_channels = ARRAY_SIZE(__wl_2ghz_channels), - .bitrates = wl_g_rates, - .n_bitrates = wl_g_rates_size, -}; - -static struct ieee80211_supported_band __wl_band_5ghz_a = { - .band = IEEE80211_BAND_5GHZ, - .channels = __wl_5ghz_a_channels, - .n_channels = ARRAY_SIZE(__wl_5ghz_a_channels), - .bitrates = wl_a_rates, - .n_bitrates = wl_a_rates_size, -}; - -static struct ieee80211_supported_band __wl_band_5ghz_n = { - .band = IEEE80211_BAND_5GHZ, - .channels = __wl_5ghz_n_channels, - .n_channels = ARRAY_SIZE(__wl_5ghz_n_channels), - .bitrates = wl_a_rates, - .n_bitrates = wl_a_rates_size, -}; - -static const uint32 __wl_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, - WLAN_CIPHER_SUITE_AES_CMAC, -}; - -static void -swap_key_from_BE(struct wl_wsec_key *key) -{ - key->index = htod32(key->index); - key->len = htod32(key->len); - key->algo = htod32(key->algo); - key->flags = htod32(key->flags); - key->rxiv.hi = htod32(key->rxiv.hi); - key->rxiv.lo = htod16(key->rxiv.lo); - key->iv_initialized = htod32(key->iv_initialized); -} - -static void -swap_key_to_BE(struct wl_wsec_key *key) -{ - key->index = dtoh32(key->index); - key->len = dtoh32(key->len); - key->algo = dtoh32(key->algo); - key->flags = dtoh32(key->flags); - key->rxiv.hi = dtoh32(key->rxiv.hi); - key->rxiv.lo = dtoh16(key->rxiv.lo); - key->iv_initialized = dtoh32(key->iv_initialized); -} - -static int32 -wl_dev_ioctl(struct net_device *dev, uint32 cmd, void *arg, uint32 len) -{ - struct ifreq ifr; - struct wl_ioctl ioc; - mm_segment_t fs; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In : cmd (%d)\n", cmd)); -#endif - memset(&ioc, 0, sizeof(ioc)); - ioc.cmd = cmd; - ioc.buf = arg; - ioc.len = len; - strcpy(ifr.ifr_name, dev->name); - ifr.ifr_data = (caddr_t) &ioc; - - - fs = get_fs(); - set_fs(get_ds()); - err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); - set_fs(fs); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, - enum nl80211_iftype type, uint32 *flags, struct vif_params *params) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct wireless_dev *wdev; - int32 infra = 0; - int32 ap = 0; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - switch (type) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_WDS: - WL_ERR(("type (%d) : currently we do not support this type\n", type)); - return -EOPNOTSUPP; - case NL80211_IFTYPE_ADHOC: - wl->conf->mode = WL_MODE_IBSS; - break; - case NL80211_IFTYPE_STATION: - wl->conf->mode = WL_MODE_BSS; - infra = 1; - break; - default: - return -EINVAL; - } - infra = htod32(infra); - ap = htod32(ap); - wdev = ndev->ieee80211_ptr; - wdev->iftype = type; - WL_DBG(("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra)); - if (unlikely((err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra)))) || - unlikely((err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap))))) { - WL_ERR(("Error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - /* -EINPROGRESS: Call commit handler */ - return -EINPROGRESS; -} - -static void -wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid) -{ - memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); - params->bss_type = DOT11_BSSTYPE_ANY; - params->scan_type = 0; - params->nprobes = -1; - params->active_time = -1; - params->passive_time = -1; - params->home_time = -1; - params->channel_num = 0; - - params->nprobes = htod32(params->nprobes); - params->active_time = htod32(params->active_time); - params->passive_time = htod32(params->passive_time); - params->home_time = htod32(params->home_time); - if (ssid && ssid->SSID_len) - memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t)); - -} - -static int32 -wl_dev_iovar_setbuf(struct net_device *dev, int8 *iovar, void *param, - int32 paramlen, void *bufptr, int32 buflen) -{ - int32 iolen; - - iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); - BUG_ON(unlikely(!iolen)); - - return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen); -} - -static int32 -wl_dev_iovar_getbuf(struct net_device *dev, int8 *iovar, void *param, - int32 paramlen, void *bufptr, int32 buflen) -{ - int32 iolen; - - iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); - BUG_ON(unlikely(!iolen)); - - return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen); -} - -static int32 -wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, uint16 action) -{ - int32 params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); - struct wl_iscan_params *params; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (ssid && ssid->SSID_len) - params_size += sizeof(struct wlc_ssid); - params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL); - if (unlikely(!params)) - return -ENOMEM; - memset(params, 0, params_size); - BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN)); - - wl_iscan_prep(¶ms->params, ssid); - - params->version = htod32(ISCAN_REQ_VERSION); - params->action = htod16(action); - params->scan_duration = htod16(0); - - /* params_size += OFFSETOF(wl_iscan_params_t, params); */ - if (unlikely((err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size, - iscan->ioctl_buf, WLC_IOCTL_SMLEN)))) { - if (err == -EBUSY) { - WL_INFO(("system busy : iscan canceled\n")); - } else { - WL_ERR(("error (%d)\n", err)); - } - } - kfree(params); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - - -static int32 -wl_do_iscan(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); - struct wlc_ssid ssid; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - /* Broadcast scan by default */ - memset(&ssid, 0, sizeof(ssid)); - - iscan->state = WL_ISCAN_STATE_SCANING; - - if (wl->active_scan) { - int32 passive_scan = 0; - /* make it active scan */ - if (unlikely((err = wl_dev_ioctl(wl_to_ndev(wl), WLC_SET_PASSIVE_SCAN, - &passive_scan, sizeof(passive_scan))))) { - WL_DBG(("error (%d)\n", err)); - return err; - } - } - wl->iscan_kickstart = TRUE; - wl_run_iscan(iscan, &ssid, WL_SCAN_ACTION_START); - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - iscan->timer_on = 1; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - - -static int32 -__wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid) -{ - struct wl_priv *wl = ndev_to_wl(ndev); - struct cfg80211_ssid *ssids; - struct wl_scan_req *sr = wl_to_sr(wl); - uint32 n_ssids; - bool iscan_req; - bool spec_scan; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) { - WL_ERR(("Scanning already : status (%d)\n", (int)wl->status)); - return -EAGAIN; - } - if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) { - WL_ERR(("Scanning being aborted : status (%d)\n", (int)wl->status)); - return -EAGAIN; - } - - iscan_req = FALSE; - spec_scan = FALSE; - if (request) { /* scan bss */ - ssids = request->ssids; - n_ssids = min(request->n_ssids, WL_NUM_SCAN_MAX); - if (wl->iscan_on && n_ssids && !ssids->ssid_len) { /* for specific scan, - * ssids->ssid_len has - * non-zero(ssid string) length. - * Otherwise this is 0. - * we do not iscan for - * specific scan request - */ - iscan_req = TRUE; - } - } else { /* scan in ibss */ - /* we don't do iscan in ibss */ - ssids = this_ssid; - n_ssids = 1; - } - wl->scan_request = request; - set_bit(WL_STATUS_SCANNING, &wl->status); - if (iscan_req) { - if (likely(!(err = wl_do_iscan(wl)))) - return err; - else - goto scan_out; - } else { - WL_DBG(("n_ssid (%d), ssid \"%s\", ssid_len (%d)\n", - n_ssids, ssids->ssid, ssids->ssid_len)); - memset(&sr->ssid, 0, sizeof(sr->ssid)); - if (n_ssids) { - sr->ssid.SSID_len = MIN(sizeof(sr->ssid.SSID), ssids->ssid_len); - if (sr->ssid.SSID_len) { - memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len); - sr->ssid.SSID_len = htod32(sr->ssid.SSID_len); - WL_DBG(("Specific scan ssid=\"%s\" len=%d\n", sr->ssid.SSID, - sr->ssid.SSID_len)); - spec_scan = TRUE; - } else { - WL_DBG(("Broadcast scan\n")); - } - } else { - /* broadcast scan */ - WL_DBG(("Broadcast scan\n")); - } - WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len)); - if (wl->active_scan) { - int32 pssive_scan = 0; - /* make it active scan */ - if (unlikely((err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN, - &pssive_scan, sizeof(pssive_scan))))) { - WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err)); - goto scan_out; - } - } - if ((err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid, sizeof(sr->ssid)))) { - if (err == -EBUSY) { - WL_INFO(("system busy : scan for \"%s\" canceled\n", - sr->ssid.SSID)); - } else { - WL_ERR(("WLC_SCAN error (%d)\n", err)); - } - goto scan_out; - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return 0; - -scan_out: - clear_bit(WL_STATUS_SCANNING, &wl->status); - wl->scan_request = NULL; - return err; -} - - -static int32 -wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request) -{ - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - if (unlikely((err = __wl_cfg80211_scan(wiphy, ndev, request, NULL)))) { - WL_DBG(("scan error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_dev_intvar_set(struct net_device *dev, int8 *name, int32 val) -{ - int8 buf[WLC_IOCTL_SMLEN]; - uint32 len; - int32 err = 0; - - val = htod32(val); - len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf)); - BUG_ON(unlikely(!len)); - - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len)))) { - WL_ERR(("error (%d)\n", err)); - } - - return err; -} - -static int32 -wl_dev_intvar_get(struct net_device *dev, int8 *name, int32 *retval) -{ - union { - int8 buf[WLC_IOCTL_SMLEN]; - int32 val; - } var; - uint32 len; - uint32 data_null; - int32 err = 0; - - len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf)); - BUG_ON(unlikely(!len)); - if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len)))) { - WL_ERR(("error (%d)\n", err)); - } - *retval = dtoh32(var.val); - - return err; -} - -static int32 -wl_set_rts(struct net_device *dev, uint32 rts_threshold) -{ - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely((err = wl_dev_intvar_set(dev, "rtsthresh", rts_threshold)))) { - WL_ERR(("Error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_set_frag(struct net_device *dev, uint32 frag_threshold) -{ - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely((err = wl_dev_intvar_set(dev, "fragthresh", frag_threshold)))) { - WL_ERR(("Error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_set_retry(struct net_device *dev, uint32 retry, bool l) -{ - int32 err = 0; - uint32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - retry = htod32(retry); - if (unlikely((err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry))))) { - WL_ERR(("cmd (%d) , error (%d)\n", cmd, err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, uint32 changed) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct net_device *ndev = wl_to_ndev(wl); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - if (changed & WIPHY_PARAM_RTS_THRESHOLD && - (wl->conf->rts_threshold != wiphy->rts_threshold)) { - wl->conf->rts_threshold = wiphy->rts_threshold; - if (!(err = wl_set_rts(ndev, wl->conf->rts_threshold))) { - return err; - } - } - if (changed & WIPHY_PARAM_FRAG_THRESHOLD && - (wl->conf->frag_threshold != wiphy->frag_threshold)) { - wl->conf->frag_threshold = wiphy->frag_threshold; - if (!(err = wl_set_frag(ndev, wl->conf->frag_threshold))) { - return err; - } - } - if (changed & WIPHY_PARAM_RETRY_LONG && (wl->conf->retry_long != wiphy->retry_long)) { - wl->conf->retry_long = wiphy->retry_long; - if (!(err = wl_set_retry(ndev, wl->conf->retry_long, TRUE))) { - return err; - } - } - if (changed & WIPHY_PARAM_RETRY_SHORT && (wl->conf->retry_short != wiphy->retry_short)) { - wl->conf->retry_short = wiphy->retry_short; - if (!(err = wl_set_retry(ndev, wl->conf->retry_short, FALSE))) { - return err; - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct cfg80211_bss *bss; - struct ieee80211_channel *chan; - struct wl_join_params join_params; - struct cfg80211_ssid ssid; - int32 scan_retry = 0; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In \n")); -#endif - CHECK_SYS_UP(); - if (params->bssid) { - WL_ERR(("Invalid bssid\n")); - return -EOPNOTSUPP; - } - bss = cfg80211_get_ibss(wiphy, NULL, params->ssid, params->ssid_len); - if (!bss) { - memcpy(ssid.ssid, params->ssid, params->ssid_len); - ssid.ssid_len = params->ssid_len; - do { - if (unlikely(__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) == -EBUSY)) { - wl_delay(150); - } else { - break; - } - } while (++scan_retry < WL_SCAN_RETRY_MAX); - rtnl_unlock(); /* to allow scan_inform to paropagate to cfg80211 plane */ - schedule_timeout_interruptible(4 * HZ); /* wait 4 secons till scan done.... */ - rtnl_lock(); - bss = cfg80211_get_ibss(wiphy, NULL, - params->ssid, params->ssid_len); - } - if (bss) { - wl->ibss_starter = FALSE; - WL_DBG(("Found IBSS\n")); - } else { - wl->ibss_starter = TRUE; - } - if ((chan = params->channel)) { - wl->channel = ieee80211_frequency_to_channel(chan->center_freq); - } - /* - ** Join with specific BSSID and cached SSID - ** If SSID is zero join based on BSSID only - */ - memset(&join_params, 0, sizeof(join_params)); - memcpy((void *)join_params.ssid.SSID, (void *)params->ssid, params->ssid_len); - join_params.ssid.SSID_len = htod32(params->ssid_len); - if (params->bssid) - memcpy(&join_params.params.bssid, params->bssid, ETHER_ADDR_LEN); - else - memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN); - - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params))))) { - WL_ERR(("Error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - wl_link_down(wl); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = ndev_to_wl(dev); - struct wl_security *sec; - int32 val = 0; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) - val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; - else if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2) - val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; - else - val = WPA_AUTH_DISABLED; - WL_DBG(("setting wpa_auth to 0x%0x\n", val)); - if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) { - WL_ERR(("set wpa_auth failed (%d)\n", err)); - return err; - } - sec = wl_read_prof(wl, WL_PROF_SEC); - sec->wpa_versions = sme->crypto.wpa_versions; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = ndev_to_wl(dev); - struct wl_security *sec; - int32 val = 0; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - switch (sme->auth_type) { - case NL80211_AUTHTYPE_OPEN_SYSTEM: - val = 0; - WL_DBG(("open system\n")); - break; - case NL80211_AUTHTYPE_SHARED_KEY: - val = 1; - WL_DBG(("shared key\n")); - break; - case NL80211_AUTHTYPE_AUTOMATIC: - val = 2; - WL_DBG(("automatic\n")); - break; - case NL80211_AUTHTYPE_NETWORK_EAP: - WL_DBG(("network eap\n")); - default : - val = 2; - WL_ERR(("invalid auth type (%d)\n", sme->auth_type)); - break; - } - - if (unlikely((err = wl_dev_intvar_set(dev, "auth", val)))) { - WL_ERR(("set auth failed (%d)\n", err)); - return err; - } - sec = wl_read_prof(wl, WL_PROF_SEC); - sec->auth_type = sme->auth_type; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - - -static int32 -wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = ndev_to_wl(dev); - struct wl_security *sec; - int32 pval = 0; - int32 gval = 0; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (sme->crypto.n_ciphers_pairwise) { - switch (sme->crypto.ciphers_pairwise[0]) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - pval = WEP_ENABLED; - break; - case WLAN_CIPHER_SUITE_TKIP: - pval = TKIP_ENABLED; - break; - case WLAN_CIPHER_SUITE_CCMP: - pval = AES_ENABLED; - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - pval = AES_ENABLED; - break; - default: - WL_ERR(("invalid cipher pairwise (%d)\n", - sme->crypto.ciphers_pairwise[0])); - return -EINVAL; - } - } - if (sme->crypto.cipher_group) { - switch (sme->crypto.cipher_group) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - gval = WEP_ENABLED; - break; - case WLAN_CIPHER_SUITE_TKIP: - gval = TKIP_ENABLED; - break; - case WLAN_CIPHER_SUITE_CCMP: - gval = AES_ENABLED; - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - gval = AES_ENABLED; - break; - default: - WL_ERR(("invalid cipher group (%d)\n", sme->crypto.cipher_group)); - return -EINVAL; - } - } - - WL_DBG(("pval (%d) gval (%d)\n", pval, gval)); - if (unlikely((err = wl_dev_intvar_set(dev, "wsec", pval|gval)))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - - sec = wl_read_prof(wl, WL_PROF_SEC); - sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; - sec->cipher_group = sme->crypto.cipher_group; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = ndev_to_wl(dev); - struct wl_security *sec; - int32 val = 0; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - - if (sme->crypto.n_akm_suites) { - if (unlikely((err = wl_dev_intvar_get(dev, "wpa_auth", &val)))) { - WL_ERR(("could not get wpa_auth (%d)\n", err)); - return err; - } - if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { - switch (sme->crypto.akm_suites[0]) { - case WLAN_AKM_SUITE_8021X: - val = WPA_AUTH_UNSPECIFIED; - break; - case WLAN_AKM_SUITE_PSK: - val = WPA_AUTH_PSK; - break; - default : - WL_ERR(("invalid cipher group (%d)\n", - sme->crypto.cipher_group)); - return -EINVAL; - } - } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { - switch (sme->crypto.akm_suites[0]) { - case WLAN_AKM_SUITE_8021X: - val = WPA2_AUTH_UNSPECIFIED; - break; - case WLAN_AKM_SUITE_PSK: - val = WPA2_AUTH_PSK; - break; - default : - WL_ERR(("invalid cipher group (%d)\n", - sme->crypto.cipher_group)); - return -EINVAL; - } - } - - WL_DBG(("setting wpa_auth to %d\n", val)); - if (unlikely((err = wl_dev_intvar_set(dev, "wpa_auth", val)))) { - WL_ERR(("could not set wpa_auth (%d)\n", err)); - return err; - } - } - sec = wl_read_prof(wl, WL_PROF_SEC); - sec->wpa_auth = sme->crypto.akm_suites[0]; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_set_set_sharedkey(struct net_device *dev, struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = ndev_to_wl(dev); - struct wl_security *sec; - struct wl_wsec_key key; - int32 val; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - WL_DBG(("key len (%d)\n", sme->key_len)); - if (sme->key_len) { - sec = wl_read_prof(wl, WL_PROF_SEC); - WL_DBG(("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, - sec->cipher_pairwise)); - if (!(sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) && - (sec->cipher_pairwise & (WLAN_CIPHER_SUITE_WEP40 | - WLAN_CIPHER_SUITE_WEP104))) { - memset(&key, 0, sizeof(key)); - key.len = (uint32)sme->key_len; - key.index = (uint32)sme->key_idx; - if (unlikely(key.len > sizeof(key.data))) { - WL_ERR(("Too long key length (%u)\n", key.len)); - return -EINVAL; - } - memcpy(key.data, sme->key, key.len); - key.flags = WL_PRIMARY_KEY; - switch (sec->cipher_pairwise) { - case WLAN_CIPHER_SUITE_WEP40: - key.algo = CRYPTO_ALGO_WEP1; - break; - case WLAN_CIPHER_SUITE_WEP104: - key.algo = CRYPTO_ALGO_WEP128; - break; - default : - WL_ERR(("Invalid algorithm (%d)\n", - sme->crypto.ciphers_pairwise[0])); - return -EINVAL; - } - /* Set the new key/index */ - WL_DBG(("key length (%d) key index (%d) algo (%d)\n", key.len, - key.index, key.algo)); - WL_DBG(("key \"%s\"\n", key.data)); - swap_key_from_BE(&key); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) { - WL_ERR(("WLC_SET_KEY error (%d)\n", err)); - return err; - } - if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { - WL_DBG(("set auth_type to shared key\n")); - val = 1; /* shared key */ - if (unlikely((err = wl_dev_intvar_set(dev, "auth", val)))) { - WL_ERR(("set auth failed (%d)\n", err)); - return err; - } - } - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct ieee80211_channel *chan = sme->channel; - struct wlc_ssid ssid; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In \n")); -#endif - CHECK_SYS_UP(); - if (unlikely(!sme->ssid)) { - WL_ERR(("Invalid ssid\n")); - return -EOPNOTSUPP; - } - if (chan) { - wl->channel = ieee80211_frequency_to_channel(chan->center_freq); - WL_DBG(("channel (%d), center_req (%d) \n", wl->channel, chan->center_freq)); - } - WL_DBG(("ie (%p), ie_len (%d)\n", sme->ie, sme->ie_len)); - if (unlikely((err = wl_set_wpa_version(dev, sme)))) { - return err; - } - if (unlikely((err = wl_set_auth_type(dev, sme)))) { - return err; - } - if (unlikely((err = wl_set_set_cipher(dev, sme)))) { - return err; - } - if (unlikely((err = wl_set_key_mgmt(dev, sme)))) { - return err; - } - if (unlikely((err = wl_set_set_sharedkey(dev, sme)))) { - return err; - } - wl_update_prof(wl, NULL, sme->bssid, WL_PROF_BSSID); - /* - ** Join with specific BSSID and cached SSID - ** If SSID is zero join based on BSSID only - */ - memset(&ssid, 0, sizeof(ssid)); - ssid.SSID_len = MIN(sizeof(ssid.SSID), sme->ssid_len); - memcpy(ssid.SSID, sme->ssid, ssid.SSID_len); - ssid.SSID_len = htod32(ssid.SSID_len); - wl_update_prof(wl, NULL, &ssid, WL_PROF_SSID); - if (ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { - WL_DBG(("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len)); - } - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(ssid))))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - set_bit(WL_STATUS_CONNECTING, &wl->status); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - uint16 reason_code) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - scb_val_t scbval; - bool act = FALSE; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - WL_DBG(("Reason %d\n", reason_code)); - CHECK_SYS_UP(); - if (likely((act = *(bool *)wl_read_prof(wl, WL_PROF_ACT)))) { - scbval.val = reason_code; - memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN); - scbval.val = htod32(scbval.val); - if (unlikely((err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval, - sizeof(scb_val_t))))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, int32 dbm) -{ - - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct net_device *ndev = wl_to_ndev(wl); - uint16 txpwrmw; - int32 err = 0; - int32 disable = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - switch (type) { - case TX_POWER_AUTOMATIC: - break; - case TX_POWER_LIMITED: - if (dbm < 0) { - WL_ERR(("TX_POWER_LIMITTED - dbm is negative\n")); - return -EINVAL; - } - break; - case TX_POWER_FIXED: - if (dbm < 0) { - WL_ERR(("TX_POWER_FIXED - dbm is negative..\n")); - return -EINVAL; - } - break; - } - /* Make sure radio is off or on as far as software is concerned */ - disable = WL_RADIO_SW_DISABLE << 16; - disable = htod32(disable); - if (unlikely((err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable))))) { - WL_ERR(("WLC_SET_RADIO error (%d)\n", err)); - return err; - } - - if (dbm > 0xffff) - txpwrmw = 0xffff; - else - txpwrmw = (uint16)dbm; - if (unlikely((err = wl_dev_intvar_set(ndev, "qtxpower", - (int32)(bcm_mw_to_qdbm(txpwrmw)))))) { - WL_ERR(("qtxpower error (%d)\n", err)); - return err; - } - wl->conf->tx_power = dbm; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_get_tx_power(struct wiphy *wiphy, int32 *dbm) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct net_device *ndev = wl_to_ndev(wl); - int32 txpwrdbm; - uint8 result; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - if (unlikely((err = wl_dev_intvar_get(ndev, "qtxpower", &txpwrdbm)))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE); - *dbm = (int32)bcm_qdbm_to_mw(result); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, uint8 key_idx) -{ - uint32 index; - int32 wsec; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - WL_DBG(("key index (%d)\n", key_idx)); - CHECK_SYS_UP(); - - if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) { - WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); - return err; - } - wsec = dtoh32(wsec); - if (wsec & WEP_ENABLED) { - /* Just select a new current key */ - index = (uint32)key_idx; - index = htod32(index); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, - &index, sizeof(index))))) { - WL_ERR(("error (%d)\n", err)); - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr, struct key_params *params) -{ - struct wl_wsec_key key; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - memset(&key, 0, sizeof(key)); - key.index = (uint32)key_idx; - /* Instead of bcast for ea address for default wep keys, driver needs it to be Null */ - if (!ETHER_ISMULTI(mac_addr)) - memcpy((char *)&key.ea, (void *)mac_addr, ETHER_ADDR_LEN); - key.len = (uint32)params->key_len; - /* check for key index change */ - if (key.len == 0) { - /* key delete */ - swap_key_from_BE(&key); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) { - WL_ERR(("key delete error (%d)\n", err)); - return err; - } - } else { - if (key.len > sizeof(key.data)) { - WL_ERR(("Invalid key length (%d)\n", key.len)); - return -EINVAL; - } - - WL_DBG(("Setting the key index %d\n", key.index)); - memcpy(key.data, params->key, key.len); - - if (params->cipher == WLAN_CIPHER_SUITE_TKIP) { - uint8 keybuf[8]; - memcpy(keybuf, &key.data[24], sizeof(keybuf)); - memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); - memcpy(&key.data[16], keybuf, sizeof(keybuf)); - } - - /* if IW_ENCODE_EXT_RX_SEQ_VALID set */ - if (params->seq && params->seq_len == 6) { - /* rx iv */ - uint8 *ivptr; - ivptr = (uint8 *)params->seq; - key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | - (ivptr[3] << 8) | ivptr[2]; - key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; - key.iv_initialized = TRUE; - } - - switch (params->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - key.algo = CRYPTO_ALGO_WEP1; - WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n")); - break; - case WLAN_CIPHER_SUITE_WEP104: - key.algo = CRYPTO_ALGO_WEP128; - WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n")); - break; - case WLAN_CIPHER_SUITE_TKIP: - key.algo = CRYPTO_ALGO_TKIP; - WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - key.algo = CRYPTO_ALGO_AES_CCM; - WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); - break; - case WLAN_CIPHER_SUITE_CCMP: - key.algo = CRYPTO_ALGO_AES_CCM; - WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); - break; - default: - WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); - return -EINVAL; - } - swap_key_from_BE(&key); - - dhd_wait_pend8021x(dev); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) { - WL_ERR(("WLC_SET_KEY error (%d)\n", err)); - return err; - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr, struct key_params *params) -{ - struct wl_wsec_key key; - int32 val; - int32 wsec; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - WL_DBG(("key index (%d)\n", key_idx)); - CHECK_SYS_UP(); - - if (mac_addr) - return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params); - memset(&key, 0, sizeof(key)); - - key.len = (uint32)params->key_len; - key.index = (uint32)key_idx; - - if (unlikely(key.len > sizeof(key.data))) { - WL_ERR(("Too long key length (%u)\n", key.len)); - return -EINVAL; - } - memcpy(key.data, params->key, key.len); - - key.flags = WL_PRIMARY_KEY; - switch (params->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - key.algo = CRYPTO_ALGO_WEP1; - WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n")); - break; - case WLAN_CIPHER_SUITE_WEP104: - key.algo = CRYPTO_ALGO_WEP128; - WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n")); - break; - case WLAN_CIPHER_SUITE_TKIP: - key.algo = CRYPTO_ALGO_TKIP; - WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); - break; - case WLAN_CIPHER_SUITE_AES_CMAC: - key.algo = CRYPTO_ALGO_AES_CCM; - WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); - break; - case WLAN_CIPHER_SUITE_CCMP: - key.algo = CRYPTO_ALGO_AES_CCM; - WL_DBG(("WLAN_CIPHER_SUITE_CCMP\n")); - break; - default: - WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); - return -EINVAL; - } - - /* Set the new key/index */ - swap_key_from_BE(&key); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) { - WL_ERR(("WLC_SET_KEY error (%d)\n", err)); - return err; - } - - val = WEP_ENABLED; - if (unlikely((err = wl_dev_intvar_get(dev, "wsec", &wsec)))) { - WL_ERR(("get wsec error (%d)\n", err)); - return err; - } - wsec &= ~(WEP_ENABLED); - wsec |= val; - if (unlikely((err = wl_dev_intvar_set(dev, "wsec", wsec)))) { - WL_ERR(("set wsec error (%d)\n", err)); - return err; - } - - val = 1; /* assume shared key. otherwise 0 */ - val = htod32(val); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))) { - WL_ERR(("WLC_SET_AUTH error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr) -{ - struct wl_wsec_key key; - int32 err = 0; - int32 val; - int32 wsec; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - memset(&key, 0, sizeof(key)); - - key.index = (uint32)key_idx; - key.flags = WL_PRIMARY_KEY; - key.algo = CRYPTO_ALGO_OFF; - - WL_DBG(("key index (%d)\n", key_idx)); - /* Set the new key/index */ - swap_key_from_BE(&key); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_KEY, &key, sizeof(key))))) { - if (err == -EINVAL) { - if (key.index >= DOT11_MAX_DEFAULT_KEYS) { - /* we ignore this key index in this case */ - WL_DBG(("invalid key index (%d)\n", key_idx)); - } - } else { - WL_ERR(("WLC_SET_KEY error (%d)\n", err)); - } - return err; - } - - val = 0; - if (unlikely((err = wl_dev_intvar_get(dev, "wsec", &wsec)))) { - WL_ERR(("get wsec error (%d)\n", err)); - return err; - } - wsec &= ~(WEP_ENABLED); - wsec |= val; - if (unlikely((err = wl_dev_intvar_set(dev, "wsec", wsec)))) { - WL_ERR(("set wsec error (%d)\n", err)); - return err; - } - - val = 0; /* assume open key. otherwise 1 */ - val = htod32(val); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val))))) { - WL_ERR(("WLC_SET_AUTH error (%d)\n", err)); - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, - uint8 key_idx, const uint8 *mac_addr, void *cookie, - void (*callback)(void *cookie, struct key_params *params)) -{ - struct key_params params; - struct wl_wsec_key key; - struct wl_priv *wl = wiphy_to_wl(wiphy); - struct wl_security *sec; - int32 wsec; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - WL_DBG(("key index (%d)\n", key_idx)); - CHECK_SYS_UP(); - - memset(&key, 0, sizeof(key)); - key.index = key_idx; - swap_key_to_BE(&key); - memset(¶ms, 0, sizeof(params)); - params.key_len = (uint8)MIN(DOT11_MAX_KEY_SIZE, key.len); - memcpy(params.key, key.data, params.key_len); - - if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec)))) { - WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); - return err; - } - wsec = dtoh32(wsec); - switch (wsec) { - case WEP_ENABLED: - sec = wl_read_prof(wl, WL_PROF_SEC); - if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { - params.cipher = WLAN_CIPHER_SUITE_WEP40; - WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n")); - } else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) { - params.cipher = WLAN_CIPHER_SUITE_WEP104; - WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n")); - } - break; - case TKIP_ENABLED: - params.cipher = WLAN_CIPHER_SUITE_TKIP; - WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n")); - break; - case AES_ENABLED: - params.cipher = WLAN_CIPHER_SUITE_AES_CMAC; - WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n")); - break; - default: - WL_ERR(("Invalid algo (0x%x)\n", wsec)); - return -EINVAL; - } - - callback(cookie, ¶ms); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, - struct net_device *dev, uint8 key_idx) -{ - WL_INFO(("Not supported\n")); - CHECK_SYS_UP(); - return -EOPNOTSUPP; -} - -static int32 -wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - uint8 *mac, struct station_info *sinfo) - -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - scb_val_t scb_val; - int rssi; - int32 rate; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - if (unlikely(memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) { - WL_ERR(("Wrong Mac address\n")); - return -ENOENT; - } - - /* Report the current tx rate */ - if ((err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) { - WL_ERR(("Could not get rate (%d)\n", err)); - } else { - rate = dtoh32(rate); - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = rate * 5; - WL_DBG(("Rate %d Mbps\n", (rate/2))); - } - - if (test_bit(WL_STATUS_CONNECTED, &wl->status)) { - scb_val.val = 0; - if (unlikely(err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) { - WL_ERR(("Could not get rssi (%d)\n", err)); - return err; - } - rssi = dtoh32(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_DBG(("RSSI %d dBm\n", rssi)); - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, - bool enabled, int32 timeout) -{ - int32 pm; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - pm = enabled ? PM_FAST : PM_OFF; - pm = htod32(pm); - WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm))))) { - if (err == -ENODEV) { - WL_DBG(("net_device is not ready yet\n")); - } else { - WL_ERR(("error (%d)\n", err)); - } - return err; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static __used uint32 -wl_find_msb(uint16 bit16) -{ - uint32 ret = 0; - - if (bit16 & 0xff00) { - ret += 8; - bit16 >>= 8; - } - - if (bit16 & 0xf0) { - ret += 4; - bit16 >>= 4; - } - - if (bit16 & 0xc) { - ret += 2; - bit16 >>= 2; - } - - if (bit16 & 2) - ret += bit16 & 2; - else if (bit16) - ret += bit16; - - return ret; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) -static int32 -wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, - const uint8 *addr, const struct cfg80211_bitrate_mask *mask) -{ - struct wl_rateset rateset; - int32 rate; - int32 val; - int32 err_bg; - int32 err_a; - uint32 legacy; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - /* addr param is always NULL. ignore it */ - /* Get current rateset */ - if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, - sizeof(rateset))))) { - WL_ERR(("could not get current rateset (%d)\n", err)); - return err; - } - - rateset.count = dtoh32(rateset.count); - - if (!(legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy))) - legacy = wl_find_msb(mask->control[IEEE80211_BAND_5GHZ].legacy); - - val = wl_g_rates[legacy-1].bitrate * 100000; - - if (val < rateset.count) { - /* Select rate by rateset index */ - rate = rateset.rates[val] & 0x7f; - } else { - /* Specified rate in bps */ - rate = val / 500000; - } - - WL_DBG(("rate %d mbps\n", (rate/2))); - - /* - * - * Set rate override, - * Since the is a/b/g-blind, both a/bg_rate are enforced. - */ - err_bg = wl_dev_intvar_set(dev, "bg_rate", rate); - err_a = wl_dev_intvar_set(dev, "a_rate", rate); - if (unlikely(err_bg && err_a)) { - WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a)); - return (err_bg | err_a); - } - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} -#else -static int32 -wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev, - const uint8 *addr, const struct cfg80211_bitrate_mask *mask) -{ - struct wl_rateset rateset; - int32 rate; - int32 val; - int32 err_bg; - int32 err_a; - int32 err = 0; - int i; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - /* addr param is always NULL. ignore it */ - /* Get current rateset */ - if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, - sizeof(rateset))))) { - WL_ERR(("could not get current rateset (%d)\n", err)); - return err; - } - - rateset.count = dtoh32(rateset.count); - - if (mask->fixed || mask->maxrate) { - val = mask->fixed ? (mask->fixed * 1000) : (mask->maxrate * 1000); - if (val < rateset.count) { - /* Select rate by rateset index */ - rate = rateset.rates[val] & 0x7f; - } else { - /* Specified rate in bps */ - rate = val / 500000; - } - } else { - /* Select maximum rate */ - rate = rateset.rates[rateset.count - 1] & 0x7f; - } - - if (mask->fixed) { - /* - Set rate override, - Since the is a/b/g-blind, both a/bg_rate are enforced. - */ - err_bg = wl_dev_intvar_set(dev, "bg_rate", rate); - err_a = wl_dev_intvar_set(dev, "a_rate", rate); - if (unlikely(err_bg && err_a)) { - WL_ERR(("could not set fixed rate (%d) (%d)\n", err_bg, err_a)); - return (err_bg | err_a); - } - } else { - /* - clear rate override - Since the is a/b/g-blind, both a/bg_rate are enforced. - */ - /* 0 is for clearing rate override */ - err_bg = wl_dev_intvar_set(dev, "bg_rate", 0); - /* 0 is for clearing rate override */ - err_a = wl_dev_intvar_set(dev, "a_rate", 0); - - if (unlikely(err_bg && err_a)) { - WL_ERR(("could not set max rate (%d) (%d)\n", err_bg, err_a)); - return (err_bg | err_a); - } - - /* Remove rates above selected rate */ - for (i = 0; i < rateset.count; i++) - if ((rateset.rates[i] & 0x7f) > rate) - break; - rateset.count = htod32(i); - - /* Set current rateset */ - if (unlikely((err = wl_dev_ioctl(dev, WLC_SET_RATESET, &rateset, - sizeof(rateset))))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */ - -static int32 -wl_cfg80211_resume(struct wiphy *wiphy) -{ - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - wl_invoke_iscan(wiphy_to_wl(wiphy)); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_suspend(struct wiphy *wiphy) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - - set_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - wl_term_iscan(wl); - if (wl->scan_request) { - cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means abort */ - wl->scan_request = NULL; - } - clear_bit(WL_STATUS_SCANNING, &wl->status); - clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static __used int32 -wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list, int32 err) -{ - int8 eabuf[ETHER_ADDR_STR_LEN]; - int i, j; - - memset(eabuf, 0, ETHER_ADDR_STR_LEN); - - WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid)); - for (i = 0; i < pmk_list->pmkids.npmkid; i++) { - WL_DBG(("PMKID[%d]: %s =\n", i, - bcm_ether_ntoa(&pmk_list->pmkids.pmkid[i].BSSID, - eabuf))); - for (j = 0; j < WPA2_PMKID_LEN; j++) { - WL_DBG(("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j])); - } - } - if (likely(!err)) { - err = wl_dev_bufvar_set(dev, "pmkid_info", (char *)pmk_list, - sizeof(*pmk_list)); - } - - return err; -} - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) -static int32 -wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_pmksa *pmksa) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - int8 eabuf[ETHER_ADDR_STR_LEN]; - int32 err = 0; - int i; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - - CHECK_SYS_UP(); - memset(eabuf, 0, ETHER_ADDR_STR_LEN); - for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++) - if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, - ETHER_ADDR_LEN)) - break; - if (i < WL_NUM_PMKIDS_MAX) { - memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid, ETHER_ADDR_LEN); - memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid, WPA2_PMKID_LEN); - if (i == wl->pmk_list->pmkids.npmkid) - wl->pmk_list->pmkids.npmkid++; - } else { - err = -EINVAL; - } - WL_DBG(("set_pmksa,IW_PMKSA_ADD - PMKID: %s =\n", - bcm_ether_ntoa(&wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID, - eabuf))); - for (i = 0; i < WPA2_PMKID_LEN; i++) { - WL_DBG(("%02x\n", - wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].PMKID[i])); - } - - err = wl_update_pmklist(dev, wl->pmk_list, err); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_pmksa *pmksa) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - int8 eabuf[ETHER_ADDR_STR_LEN]; - struct _pmkid_list pmkid; - int32 err = 0; - int i; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - - CHECK_SYS_UP(); - memset(eabuf, 0, ETHER_ADDR_STR_LEN); - memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN); - memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN); - - WL_DBG(("del_pmksa,IW_PMKSA_REMOVE - PMKID: %s =\n", - bcm_ether_ntoa(&pmkid.pmkid[0].BSSID, eabuf))); - for (i = 0; i < WPA2_PMKID_LEN; i++) { - WL_DBG(("%02x\n", pmkid.pmkid[0].PMKID[i])); - } - - for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++) - if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN)) - break; - - if ((wl->pmk_list->pmkids.npmkid > 0) && (i < wl->pmk_list->pmkids.npmkid)) { - memset(&wl->pmk_list->pmkids.pmkid[i], 0, sizeof(pmkid_t)); - for (; i < (wl->pmk_list->pmkids.npmkid - 1); i++) { - memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, - &wl->pmk_list->pmkids.pmkid[i+1].BSSID, ETHER_ADDR_LEN); - memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, - &wl->pmk_list->pmkids.pmkid[i+1].PMKID, WPA2_PMKID_LEN); - } - wl->pmk_list->pmkids.npmkid--; - } - else { - err = -EINVAL; - } - - err = wl_update_pmklist(dev, wl->pmk_list, err); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; - -} - -static int32 -wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) -{ - struct wl_priv *wl = wiphy_to_wl(wiphy); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - CHECK_SYS_UP(); - memset(wl->pmk_list, 0, sizeof(*wl->pmk_list)); - err = wl_update_pmklist(dev, wl->pmk_list, err); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; - -} -#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) */ - -static struct cfg80211_ops wl_cfg80211_ops = { - .change_virtual_intf = wl_cfg80211_change_iface, - .scan = wl_cfg80211_scan, - .set_wiphy_params = wl_cfg80211_set_wiphy_params, - .join_ibss = wl_cfg80211_join_ibss, - .leave_ibss = wl_cfg80211_leave_ibss, - .get_station = wl_cfg80211_get_station, - .set_tx_power = wl_cfg80211_set_tx_power, - .get_tx_power = wl_cfg80211_get_tx_power, - .add_key = wl_cfg80211_add_key, - .del_key = wl_cfg80211_del_key, - .get_key = wl_cfg80211_get_key, - .set_default_key = wl_cfg80211_config_default_key, - .set_default_mgmt_key = wl_cfg80211_config_default_mgmt_key, - .set_power_mgmt = wl_cfg80211_set_power_mgmt, - .set_bitrate_mask = wl_cfg80211_set_bitrate_mask, - .connect = wl_cfg80211_connect, - .disconnect = wl_cfg80211_disconnect, - .suspend = wl_cfg80211_suspend, - .resume = wl_cfg80211_resume, -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) - .set_pmksa = wl_cfg80211_set_pmksa, - .del_pmksa = wl_cfg80211_del_pmksa, - .flush_pmksa = wl_cfg80211_flush_pmksa -#endif -}; - -static int32 -wl_mode_to_nl80211_iftype(int32 mode) -{ - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - switch (mode) { - case WL_MODE_BSS: - return NL80211_IFTYPE_STATION; - case WL_MODE_IBSS: - return NL80211_IFTYPE_ADHOC; - default: - return NL80211_IFTYPE_UNSPECIFIED; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static struct wireless_dev * -wl_alloc_wdev(int32 sizeof_iface, struct device *dev) -{ - struct wireless_dev *wdev; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); - if (unlikely(!wdev)) { - WL_ERR(("Could not allocate wireless device\n")); - return ERR_PTR(-ENOMEM); - } - wdev->wiphy = wiphy_new(&wl_cfg80211_ops, sizeof(struct wl_priv) + sizeof_iface); - if (unlikely(!wdev->wiphy)) { - WL_ERR(("Couldn not allocate wiphy device\n")); - err = -ENOMEM; - goto wiphy_new_out; - } - set_wiphy_dev(wdev->wiphy, dev); - wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) - wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; -#endif - wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION)| BIT(NL80211_IFTYPE_ADHOC); - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set it as 11a by default. - ** This will be updated with - ** 11n phy tables in "ifconfig up" - ** if phy has 11n capability - */ - wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - wdev->wiphy->cipher_suites = __wl_cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites); -#ifndef WL_POWERSAVE_DISABLED -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) - wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT; /* enable power - * save mode by default - */ -#else - wdev->wiphy->ps_default = TRUE; /* enable power save mode by default */ -#endif -#else -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) - wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; -#else - wdev->wiphy->ps_default = FALSE; -#endif -#endif /* !WL_POWERSAVE_DISABLED */ - if (unlikely(((err = wiphy_register(wdev->wiphy)) < 0))) { - WL_ERR(("Couldn not register wiphy device (%d)\n", err)); - goto wiphy_register_out; - } - return wdev; - -wiphy_register_out: - wiphy_free(wdev->wiphy); - -wiphy_new_out: - kfree(wdev); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return ERR_PTR(err); -} - -static void -wl_free_wdev(struct wl_priv *wl) -{ - struct wireless_dev *wdev = wl_to_wdev(wl); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely(!wdev)) { - WL_ERR(("wdev is invalid\n")); - return; - } - wiphy_unregister(wdev->wiphy); - wiphy_free(wdev->wiphy); - kfree(wdev); - wl_to_wdev(wl) = NULL; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif -} - -static int32 -wl_inform_bss(struct wl_priv *wl) -{ - struct wl_scan_results *bss_list; - struct wl_bss_info *bi = NULL; /* must be initialized */ - int32 err = 0; - int i; - - - bss_list = wl->bss_list; - if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) { - WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version)); - return -EOPNOTSUPP; - } - WL_DBG(("scanned AP count (%d)\n", bss_list->count)); - bi = next_bss(bss_list, bi); - for_each_bss(bss_list, bi, i) { - if (unlikely(err = wl_inform_single_bss(wl, bi))) - break; - } - return err; -} - -static int32 -wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) -{ - struct wiphy *wiphy = wl_to_wiphy(wl); - struct ieee80211_mgmt *mgmt; - struct ieee80211_channel *channel; - struct ieee80211_supported_band *band; - struct wl_cfg80211_bss_info *notif_bss_info; - struct wl_scan_req *sr = wl_to_sr(wl); - uint32 signal; - uint32 freq; - int32 err = 0; - - if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { - WL_DBG(("Beacon size is larger than allocated buffer. Discard it!!\n")); - return err; - } - notif_bss_info = kzalloc(sizeof(*notif_bss_info) + sizeof(*mgmt) - sizeof(uint8) + - WL_BSS_INFO_MAX, GFP_KERNEL); - if (unlikely(!notif_bss_info)) { - WL_ERR(("notif_bss_info alloc failed\n")); - return -ENOMEM; - } - mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf; - notif_bss_info->channel = CHSPEC_CHANNEL(bi->chanspec); - if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - else - band = wiphy->bands[IEEE80211_BAND_5GHZ]; - notif_bss_info->rssi = bi->RSSI; - memcpy(mgmt->bssid, &bi->BSSID, ETHER_ADDR_LEN); - if (!memcmp(bi->SSID, sr->ssid.SSID, bi->SSID_len)) { - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_PROBE_RESP); - } - mgmt->u.probe_resp.timestamp = 0; - mgmt->u.probe_resp.beacon_int = cpu_to_le16(bi->beacon_period); - mgmt->u.probe_resp.capab_info = cpu_to_le16(bi->capability); - wl_rst_ie(wl); - wl_add_ie(wl, WLAN_EID_SSID, bi->SSID_len, bi->SSID); - wl_add_ie(wl, WLAN_EID_SUPP_RATES, bi->rateset.count, bi->rateset.rates); - wl_mrg_ie(wl, ((uint8 *)bi) + bi->ie_offset, bi->ie_length); - wl_cp_ie(wl, mgmt->u.probe_resp.variable, WL_BSS_INFO_MAX - - offsetof(struct wl_cfg80211_bss_info, frame_buf)); - notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, u.probe_resp.variable) + - wl_get_ielen(wl); - freq = ieee80211_channel_to_frequency(notif_bss_info->channel); - channel = ieee80211_get_channel(wiphy, freq); - - WL_DBG(("SSID : \"%s\", rssi (%d), capability : 0x04%x\n", bi->SSID, notif_bss_info->rssi, - mgmt->u.probe_resp.capab_info)); - - signal = notif_bss_info->rssi * 100; - if (unlikely(!cfg80211_inform_bss_frame(wiphy, channel, mgmt, - le16_to_cpu(notif_bss_info->frame_len), signal, GFP_KERNEL))) { - WL_ERR(("cfg80211_inform_bss_frame error\n")); - kfree(notif_bss_info); - return -EINVAL; - } - kfree(notif_bss_info); - - return err; -} - -static bool -wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e) -{ - uint32 event = ntoh32(e->event_type); - uint16 flags = ntoh16(e->flags); - - if (event == WLC_E_JOIN || event == WLC_E_ASSOC_IND || event == WLC_E_REASSOC_IND) { - return TRUE; - } else if (event == WLC_E_LINK) { - if (flags & WLC_EVENT_MSG_LINK) { - if (wl_is_ibssmode(wl)) { - if (wl_is_ibssstarter(wl)) { - } - } else { - - } - } - } - - return FALSE; -} - -static bool -wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e) -{ - uint32 event = ntoh32(e->event_type); - uint16 flags = ntoh16(e->flags); - - if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) { - return TRUE; - } else if (event == WLC_E_LINK) { - if (!(flags & WLC_EVENT_MSG_LINK)) { - return TRUE; - } - } - - return FALSE; -} - -static int32 -wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data) -{ - bool act; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (wl_is_linkup(wl, e)) { - wl_link_up(wl); - if (wl_is_ibssmode(wl)) { - cfg80211_ibss_joined(ndev, (int8 *)&e->addr, GFP_KERNEL); - WL_DBG(("joined in IBSS network\n")); - } else { - wl_bss_connect_done(wl, ndev, e, data); - WL_DBG(("joined in BSS network \"%s\"\n", - ((struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID))->SSID)); - } - act = TRUE; - wl_update_prof(wl, e, &act, WL_PROF_ACT); - } else if (wl_is_linkdown(wl, e)) { - cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); - clear_bit(WL_STATUS_CONNECTED, &wl->status); - wl_link_down(wl); - wl_init_prof(wl->profile); - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_notify_roaming_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data) -{ - bool act; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl_bss_roaming_done(wl, ndev, e, data); - act = TRUE; - wl_update_prof(wl, e, &act, WL_PROF_ACT); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static __used int32 -wl_dev_bufvar_set(struct net_device *dev, int8 *name, int8 *buf, int32 len) -{ - struct wl_priv *wl = ndev_to_wl(dev); - uint32 buflen; - - buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX); - BUG_ON(unlikely(!buflen)); - - return (wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen)); -} - -static int32 -wl_dev_bufvar_get(struct net_device *dev, int8 *name, int8 *buf, int32 buf_len) -{ - struct wl_priv *wl = ndev_to_wl(dev); - uint32 len; - int32 err = 0; - - len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX); - BUG_ON(unlikely(!len)); - if (unlikely((err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf, - WL_IOCTL_LEN_MAX)))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - memcpy(buf, wl->ioctl_buf, buf_len); - - return err; -} - -static int32 -wl_get_assoc_ies(struct wl_priv *wl) -{ - struct net_device *ndev = wl_to_ndev(wl); - struct wl_assoc_ielen *assoc_info; - struct wl_connect_info *conn_info = wl_to_conn(wl); - uint32 req_len; - uint32 resp_len; - int32 err = 0; - - if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_info", wl->extra_buf, - WL_ASSOC_INFO_MAX))) { - WL_ERR(("could not get assoc info (%d)\n", err)); - return err; - } - assoc_info = (struct wl_assoc_ielen *)wl->extra_buf; - req_len = assoc_info->req_len; - resp_len = assoc_info->resp_len; - if (req_len) { - if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf, - WL_ASSOC_INFO_MAX))) { - WL_ERR(("could not get assoc req (%d)\n", err)); - return err; - } - conn_info->req_ie_len = req_len; - conn_info->req_ie = kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL); - } else { - conn_info->req_ie_len = 0; - conn_info->req_ie = NULL; - } - if (resp_len) { - if (unlikely(err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf, - WL_ASSOC_INFO_MAX))) { - WL_ERR(("could not get assoc resp (%d)\n", err)); - return err; - } - conn_info->resp_ie_len = resp_len; - conn_info->resp_ie = kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL); - } else { - conn_info->resp_ie_len = 0; - conn_info->resp_ie = NULL; - } - WL_DBG(("req len (%d) resp len (%d)\n", conn_info->req_ie_len, conn_info->resp_ie_len)); - - return err; -} - -static int32 -wl_update_bss_info(struct wl_priv *wl) -{ - struct cfg80211_bss *bss; - struct wl_bss_info *bi; - struct wlc_ssid *ssid; - int32 err = 0; - - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (wl_is_ibssmode(wl)) - return err; - - ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID); - bss = cfg80211_get_bss(wl_to_wiphy(wl), NULL, (int8 *)&wl->bssid, ssid->SSID, - ssid->SSID_len, WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); - - rtnl_lock(); - if (unlikely(!bss)) { - WL_DBG(("Could not find the AP\n")); - *(uint32*)wl->extra_buf = htod32(WL_EXTRA_BUF_MAX); - if (unlikely(err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO, wl->extra_buf, - WL_EXTRA_BUF_MAX))) { - WL_ERR(("Could not get bss info %d\n", err)); - goto update_bss_info_out; - } - bi = (struct wl_bss_info *)(wl->extra_buf + 4); - if (unlikely(memcmp(&bi->BSSID, &wl->bssid, ETHER_ADDR_LEN))) { - err = -EIO; - goto update_bss_info_out; - } - if (unlikely((err = wl_inform_single_bss(wl, bi)))) - goto update_bss_info_out; - } else { - WL_DBG(("Found the AP in the list - BSSID %02x:%02x:%02x:%02x:%02x:%02x\n", - bss->bssid[0], bss->bssid[1], bss->bssid[2], bss->bssid[3], - bss->bssid[4], bss->bssid[5])); - cfg80211_put_bss(bss); - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - -update_bss_info_out: - rtnl_unlock(); - return err; -} - -static int32 -wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data) -{ - struct wl_connect_info *conn_info = wl_to_conn(wl); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl_get_assoc_ies(wl); - memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN); - wl_update_bss_info(wl); - cfg80211_roamed(ndev, - (uint8 *)&wl->bssid, - conn_info->req_ie, conn_info->req_ie_len, - conn_info->resp_ie, conn_info->resp_ie_len, - GFP_KERNEL); - WL_DBG(("Report roaming result\n")); - - set_bit(WL_STATUS_CONNECTED, &wl->status); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data) -{ - struct wl_connect_info *conn_info = wl_to_conn(wl); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl_get_assoc_ies(wl); - memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN); - wl_update_bss_info(wl); - if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) { - cfg80211_connect_result(ndev, - (uint8 *)&wl->bssid, - conn_info->req_ie, conn_info->req_ie_len, - conn_info->resp_ie, conn_info->resp_ie_len, - WLAN_STATUS_SUCCESS, - GFP_KERNEL); - WL_DBG(("Report connect result\n")); - } else { - cfg80211_roamed(ndev, - (uint8 *)&wl->bssid, - conn_info->req_ie, conn_info->req_ie_len, - conn_info->resp_ie, conn_info->resp_ie_len, - GFP_KERNEL); - WL_DBG(("Report roaming result\n")); - } - set_bit(WL_STATUS_CONNECTED, &wl->status); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data) -{ - uint16 flags = ntoh16(e->flags); - enum nl80211_key_type key_type; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - - rtnl_lock(); - if (flags & WLC_EVENT_MSG_GROUP) - key_type = NL80211_KEYTYPE_GROUP; - else - key_type = NL80211_KEYTYPE_PAIRWISE; - - cfg80211_michael_mic_failure(ndev, (uint8 *)&e->addr, key_type, -1, NULL, GFP_KERNEL); - rtnl_unlock(); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return 0; -} - -static int32 -wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void* data) -{ - struct channel_info channel_inform; - struct wl_scan_results *bss_list; - uint32 len = WL_SCAN_BUF_MAX; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - - if (wl->iscan_on && wl->iscan_kickstart) - return wl_wakeup_iscan(wl_to_iscan(wl)); - - if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) { - WL_ERR(("Scan complete while device not scanning\n")); - return -EINVAL; - } - if (unlikely(!wl->scan_request)) { - } - rtnl_lock(); - if (unlikely((err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform, - sizeof(channel_inform))))) { - WL_ERR(("scan busy (%d)\n", err)); - goto scan_done_out; - } - channel_inform.scan_channel = dtoh32(channel_inform.scan_channel); - if (unlikely(channel_inform.scan_channel)) { - - WL_DBG(("channel_inform.scan_channel (%d)\n", channel_inform.scan_channel)); - } - wl->bss_list = wl->scan_results; - bss_list = wl->bss_list; - memset(bss_list, 0, len); - bss_list->buflen = htod32(len); - if (unlikely((err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len)))) { - WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err)); - err = -EINVAL; - goto scan_done_out; - } - bss_list->buflen = dtoh32(bss_list->buflen); - bss_list->version = dtoh32(bss_list->version); - bss_list->count = dtoh32(bss_list->count); - - if ((err = wl_inform_bss(wl))) { - goto scan_done_out; - } - -scan_done_out : - if (wl->scan_request) { - cfg80211_scan_done(wl->scan_request, FALSE); - wl->scan_request = NULL; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - rtnl_unlock(); - return err; -} - -static void -wl_init_conf(struct wl_conf *conf) -{ - conf->mode = (uint32)-1; - conf->frag_threshold = (uint32)-1; - conf->rts_threshold = (uint32)-1; - conf->retry_short = (uint32)-1; - conf->retry_long = (uint32)-1; - conf->tx_power = -1; -} - -static void -wl_init_prof(struct wl_profile *prof) -{ - memset(prof, 0, sizeof(*prof)); -} - -static void -wl_init_eloop_handler(struct wl_event_loop *el) -{ - memset(el, 0, sizeof(*el)); - el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status; - el->handler[WLC_E_JOIN] = wl_notify_connect_status; - el->handler[WLC_E_LINK] = wl_notify_connect_status; - el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status; - el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status; - el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status; - el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status; - el->handler[WLC_E_ROAM] = wl_notify_roaming_status; - el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status; -} - -static int32 -wl_init_priv_mem(struct wl_priv *wl) -{ - wl->scan_results = (void *)kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); - if (unlikely(!wl->scan_results)) { - WL_ERR(("Scan results alloc failed\n")); - goto init_priv_mem_out; - } - wl->conf = (void *)kzalloc(sizeof(*wl->conf), GFP_KERNEL); - if (unlikely(!wl->conf)) { - WL_ERR(("wl_conf alloc failed\n")); - goto init_priv_mem_out; - } - wl->profile = (void *)kzalloc(sizeof(*wl->profile), GFP_KERNEL); - if (unlikely(!wl->profile)) { - WL_ERR(("wl_profile alloc failed\n")); - goto init_priv_mem_out; - } - wl->bss_info = (void *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (unlikely(!wl->bss_info)) { - WL_ERR(("Bss information alloc failed\n")); - goto init_priv_mem_out; - } - wl->scan_req_int = (void *)kzalloc(sizeof(*wl->scan_req_int), GFP_KERNEL); - if (unlikely(!wl->scan_req_int)) { - WL_ERR(("Scan req alloc failed\n")); - goto init_priv_mem_out; - } - wl->ioctl_buf = (void *)kzalloc(WL_IOCTL_LEN_MAX, GFP_KERNEL); - if (unlikely(!wl->ioctl_buf)) { - WL_ERR(("Ioctl buf alloc failed\n")); - goto init_priv_mem_out; - } - wl->extra_buf = (void *)kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); - if (unlikely(!wl->extra_buf)) { - WL_ERR(("Extra buf alloc failed\n")); - goto init_priv_mem_out; - } - wl->iscan = (void *)kzalloc(sizeof(*wl->iscan), GFP_KERNEL); - if (unlikely(!wl->iscan)) { - WL_ERR(("Iscan buf alloc failed\n")); - goto init_priv_mem_out; - } - wl->fw = (void *)kzalloc(sizeof(*wl->fw), GFP_KERNEL); - if (unlikely(!wl->fw)) { - WL_ERR(("fw object alloc failed\n")); - goto init_priv_mem_out; - } - wl->pmk_list = (void *)kzalloc(sizeof(*wl->pmk_list), GFP_KERNEL); - if (unlikely(!wl->pmk_list)) { - WL_ERR(("pmk list alloc failed\n")); - goto init_priv_mem_out; - } - - return 0; - -init_priv_mem_out: - wl_deinit_priv_mem(wl); - - return -ENOMEM; -} - -static void -wl_deinit_priv_mem(struct wl_priv *wl) -{ - if (wl->scan_results) { - kfree(wl->scan_results); - wl->scan_results = NULL; - } - if (wl->bss_info) { - kfree(wl->bss_info); - wl->bss_info = NULL; - } - if (wl->conf) { - kfree(wl->conf); - wl->conf = NULL; - } - if (wl->profile) { - kfree(wl->profile); - wl->profile = NULL; - } - if (wl->scan_req_int) { - kfree(wl->scan_req_int); - wl->scan_req_int = NULL; - } - if (wl->ioctl_buf) { - kfree(wl->ioctl_buf); - wl->ioctl_buf = NULL; - } - if (wl->extra_buf) { - kfree(wl->extra_buf); - wl->extra_buf = NULL; - } - if (wl->iscan) { - kfree(wl->iscan); - wl->iscan = NULL; - } - if (wl->fw) { - kfree(wl->fw); - wl->fw = NULL; - } - if (wl->pmk_list) { - kfree(wl->pmk_list); - wl->pmk_list = NULL; - } -} - - -static int32 -wl_create_event_handler(struct wl_priv *wl) -{ - sema_init(&wl->event_sync, 0); - init_completion(&wl->event_exit); - if (unlikely(((wl->event_pid = kernel_thread(wl_event_handler, wl, 0)) < 0))) { - WL_ERR(("failed to create event thread\n")); - return -ENOMEM; - } - WL_DBG(("pid %d\n", wl->event_pid)); - return 0; -} - -static void -wl_destroy_event_handler(struct wl_priv *wl) -{ - if (wl->event_pid >= 0) { - KILL_PROC(wl->event_pid, SIGTERM); - wait_for_completion(&wl->event_exit); - } -} - -static void -wl_term_iscan(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); - - if (wl->iscan_on && iscan->pid >= 0) { - iscan->state = WL_ISCAN_STATE_IDLE; - KILL_PROC(iscan->pid, SIGTERM); - wait_for_completion(&iscan->exited); - iscan->pid = -1; - } -} - -static void -wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted) -{ - struct wl_priv *wl = iscan_to_wl(iscan); - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) { - WL_ERR(("Scan complete while device not scanning\n")); - return; - } - if (likely(wl->scan_request)) { - cfg80211_scan_done(wl->scan_request, aborted); - wl->scan_request = NULL; - } - wl->iscan_kickstart = FALSE; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif -} - -static int32 -wl_wakeup_iscan(struct wl_iscan_ctrl *iscan) -{ - if (likely(iscan->state != WL_ISCAN_STATE_IDLE)) { - WL_DBG(("wake up iscan\n")); - up(&iscan->sync); - return 0; - } - - return -EIO; -} - -static int32 -wl_get_iscan_results(struct wl_iscan_ctrl *iscan, uint32 *status, struct wl_scan_results **bss_list) -{ - struct wl_iscan_results list; - struct wl_scan_results *results; - struct wl_iscan_results *list_buf; - int32 err = 0; - - memset(iscan->scan_buf, 0, WL_ISCAN_BUF_MAX); - list_buf = (struct wl_iscan_results *)iscan->scan_buf; - results = &list_buf->results; - results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; - results->version = 0; - results->count = 0; - - memset(&list, 0, sizeof(list)); - list.results.buflen = htod32(WL_ISCAN_BUF_MAX); - if (unlikely((err = wl_dev_iovar_getbuf( - iscan->dev, - "iscanresults", - &list, - WL_ISCAN_RESULTS_FIXED_SIZE, - iscan->scan_buf, - WL_ISCAN_BUF_MAX)))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - results->buflen = dtoh32(results->buflen); - results->version = dtoh32(results->version); - results->count = dtoh32(results->count); - WL_DBG(("results->count = %d\n", results->count)); - WL_DBG(("results->buflen = %d\n", results->buflen)); - *status = dtoh32(list_buf->status); - *bss_list = results; - - return err; -} - -static int32 -wl_iscan_done(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl->iscan; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - iscan->state = WL_ISCAN_STATE_IDLE; - rtnl_lock(); - wl_inform_bss(wl); - wl_notify_iscan_complete(iscan, FALSE); - rtnl_unlock(); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_iscan_pending(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl->iscan; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - /* Reschedule the timer */ - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - iscan->timer_on = 1; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_iscan_inprogress(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl->iscan; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - rtnl_lock(); - wl_inform_bss(wl); - wl_run_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); - rtnl_unlock(); - /* Reschedule the timer */ - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - iscan->timer_on = 1; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_iscan_aborted(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl->iscan; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - iscan->state = WL_ISCAN_STATE_IDLE; - rtnl_lock(); - wl_notify_iscan_complete(iscan, TRUE); - rtnl_unlock(); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_iscan_thread(void *data) -{ - struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; - struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; - struct wl_priv *wl = iscan_to_wl(iscan); - struct wl_iscan_eloop *el = &iscan->el; - uint32 status; - int err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - sched_setscheduler(current, SCHED_FIFO, ¶m); - status = WL_SCAN_RESULTS_PARTIAL; - while (likely(!down_interruptible(&iscan->sync))) { - if (iscan->timer_on) { - del_timer_sync(&iscan->timer); - iscan->timer_on = 0; - } - rtnl_lock(); - if (unlikely((err = wl_get_iscan_results(iscan, &status, &wl->bss_list)))) { - status = WL_SCAN_RESULTS_ABORTED; - WL_ERR(("Abort iscan\n")); - } - rtnl_unlock(); - el->handler[status](wl); - } - if (iscan->timer_on) { - del_timer_sync(&iscan->timer); - iscan->timer_on = 0; - } - complete_and_exit(&iscan->exited, 0); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return 0; -} - -static void -wl_iscan_timer(ulong data) -{ - struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; - - if (iscan) { - iscan->timer_on = 0; - WL_DBG(("timer expired\n")); - wl_wakeup_iscan(iscan); - } -} - -static int32 -wl_invoke_iscan(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); - int err = 0; - - if (wl->iscan_on && iscan->pid < 0) { - iscan->state = WL_ISCAN_STATE_IDLE; - sema_init(&iscan->sync, 0); - init_completion(&iscan->exited); - iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0); - if (unlikely(iscan->pid < 0)) { - WL_ERR(("Could not create iscan thread\n")); - return -ENOMEM; - } - } - - return err; -} - -static void -wl_init_iscan_eloop(struct wl_iscan_eloop *el) -{ - memset(el, 0, sizeof(*el)); - el->handler[WL_SCAN_RESULTS_SUCCESS] = wl_iscan_done; - el->handler[WL_SCAN_RESULTS_PARTIAL] = wl_iscan_inprogress; - el->handler[WL_SCAN_RESULTS_PENDING] = wl_iscan_pending; - el->handler[WL_SCAN_RESULTS_ABORTED] = wl_iscan_aborted; - el->handler[WL_SCAN_RESULTS_NO_MEM] = wl_iscan_aborted; -} - -static int32 -wl_init_iscan(struct wl_priv *wl) -{ - struct wl_iscan_ctrl *iscan = wl_to_iscan(wl); - int err = 0; - - if (wl->iscan_on) { - iscan->dev = wl_to_ndev(wl); - iscan->state = WL_ISCAN_STATE_IDLE; - wl_init_iscan_eloop(&iscan->el); - iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; - init_timer(&iscan->timer); - iscan->timer.data = (ulong)iscan; - iscan->timer.function = wl_iscan_timer; - sema_init(&iscan->sync, 0); - init_completion(&iscan->exited); - iscan->pid = kernel_thread(wl_iscan_thread, iscan, 0); - if (unlikely(iscan->pid < 0)) { - WL_ERR(("Could not create iscan thread\n")); - return -ENOMEM; - } - iscan->data = wl; - } - - return err; -} - -static void -wl_init_fw(struct wl_fw_ctrl *fw) -{ - fw->status = 0; /* init fw loading status. 0 means nothing was loaded yet */ -} - -static int32 -wl_init_priv(struct wl_priv *wl) -{ - struct wiphy *wiphy = wl_to_wiphy(wl); - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl->scan_request = NULL; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) || \ - defined(CHROMIUMOS_COMPAT_WIRELESS) - wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT); -#else - wl->pwr_save = wiphy->ps_default; -#endif -#ifndef WL_ISCAN_DISABLED - wl->iscan_on = TRUE; /* iscan on & off switch. we enable iscan per default */ -#else - wl->iscan_on = FALSE; -#endif /* WL_ISCAN_DISABLED */ -#ifndef WL_ROAM_DISABLED - wl->roam_on = TRUE; /* roam on & off switch. we enable roam per default */ -#else - wl->roam_on = FALSE; -#endif /* WL_ROAM_DISABLED */ - - wl->iscan_kickstart = FALSE; - wl->active_scan = TRUE; /* we do active scan for specific scan per default */ - wl->dongle_up = FALSE; /* dongle is not up yet */ - wl_init_eq(wl); - if (unlikely((err = wl_init_priv_mem(wl)))) - return err; - if (unlikely(wl_create_event_handler(wl))) - return -ENOMEM; - wl_init_eloop_handler(&wl->el); - mutex_init(&wl->usr_sync); - if (unlikely((err = wl_init_iscan(wl)))) - return err; - wl_init_fw(wl->fw); - wl_init_conf(wl->conf); - wl_init_prof(wl->profile); - wl_link_down(wl); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static void -wl_deinit_priv(struct wl_priv *wl) -{ -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl_destroy_event_handler(wl); - wl->dongle_up = FALSE; /* dongle down */ - wl_flush_eq(wl); - wl_link_down(wl); - wl_term_iscan(wl); - wl_deinit_priv_mem(wl); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif -} - -int32 -wl_cfg80211_attach(struct net_device *ndev, void *data) -{ - struct wireless_dev *wdev; - struct wl_priv *wl; - struct wl_iface *ci; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely(!ndev)) { - WL_ERR(("ndev is invaild\n")); - return -ENODEV; - } - wl_cfg80211_dev = kzalloc(sizeof(struct wl_dev), GFP_KERNEL); - if (unlikely(!wl_cfg80211_dev)) { - WL_ERR(("wl_cfg80211_dev is invalid\n")); - return -ENOMEM; - } - WL_DBG(("func %p\n", wl_sdio_func())); -#ifndef WL_CFG80211_LOCALTEST - wdev = wl_alloc_wdev(sizeof(struct wl_iface), &wl_sdio_func()->dev); -#else - wdev = wl_alloc_wdev(sizeof(struct wl_iface), NULL); -#endif - if (unlikely(IS_ERR(wdev))) - return -ENOMEM; - - wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); - wl = wdev_to_wl(wdev); - wl->wdev = wdev; - wl->pub = data; - ci = (struct wl_iface *)wl_to_ci(wl); - ci->wl = wl; - ndev->ieee80211_ptr = wdev; - SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); - wdev->netdev = ndev; - if (unlikely((err = wl_init_priv(wl)))) { - WL_ERR(("Failed to init iwm_priv (%d)\n", err)); - goto cfg80211_attach_out; - } - wl_set_drvdata(wl_cfg80211_dev, ci); - set_bit(WL_STATUS_READY, &wl->status); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; - -cfg80211_attach_out: - wl_free_wdev(wl); - return err; -} - -void -wl_cfg80211_detach(void) -{ - struct wl_priv *wl; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl = WL_PRIV_GET(); - - wl_deinit_priv(wl); - wl_free_wdev(wl); - wl_set_drvdata(wl_cfg80211_dev, NULL); - kfree(wl_cfg80211_dev); - wl_cfg80211_dev = NULL; - wl_clear_sdio_func(); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif -} - -static void -wl_wakeup_event(struct wl_priv *wl) -{ - up(&wl->event_sync); -} - -static int32 -wl_event_handler(void *data) -{ - struct wl_priv *wl = (struct wl_priv *)data; - struct sched_param param = { .sched_priority = MAX_RT_PRIO-1 }; - struct wl_event_q *e; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - sched_setscheduler(current, SCHED_FIFO, ¶m); - while (likely(!down_interruptible(&wl->event_sync))) { - if (unlikely(!(e = wl_deq_event(wl)))) { - WL_ERR(("eqeue empty..\n")); - BUG(); - } - WL_DBG(("event type (%d)\n", e->etype)); - if (wl->el.handler[e->etype]) { - wl->el.handler[e->etype](wl, wl_to_ndev(wl), &e->emsg, e->edata); - } else { - WL_DBG(("Unknown Event (%d): ignoring\n", e->etype)); - } - wl_put_event(e); - } - complete_and_exit(&wl->event_exit, 0); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif -} - -void -wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void* data) -{ - uint32 event_type = ntoh32(e->event_type); - struct wl_priv *wl = ndev_to_wl(ndev); -#if (WL_DBG_LEVEL > 0) - int8 *estr = (event_type <= sizeof(wl_dbg_estr)/WL_DBG_ESTR_MAX-1) ? - wl_dbg_estr[event_type] : (int8 *)"Unknown"; -#endif /* (WL_DBG_LEVEL > 0) */ - WL_DBG(("event_type (%d):""WLC_E_""%s\n", event_type, estr)); - if (likely(!wl_enq_event(wl, event_type, e, data))) - wl_wakeup_event(wl); -} - -static void -wl_init_eq(struct wl_priv *wl) -{ - wl_init_eq_lock(wl); - INIT_LIST_HEAD(&wl->eq_list); -} - -static void -wl_flush_eq(struct wl_priv *wl) -{ - struct wl_event_q *e; - - wl_lock_eq(wl); - while (!list_empty(&wl->eq_list)) { - e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list); - list_del(&e->eq_list); - kfree(e); - } - wl_unlock_eq(wl); -} - -/* -* retrieve first queued event from head -*/ - -static struct wl_event_q * -wl_deq_event(struct wl_priv *wl) -{ - struct wl_event_q *e = NULL; - - wl_lock_eq(wl); - if (likely(!list_empty(&wl->eq_list))) { - e = list_first_entry(&wl->eq_list, struct wl_event_q, eq_list); - list_del(&e->eq_list); - } - wl_unlock_eq(wl); - - return e; -} - -/* -** push event to tail of the queue -*/ - -static int32 -wl_enq_event(struct wl_priv *wl, uint32 event, const wl_event_msg_t *msg, void *data) -{ - struct wl_event_q *e; - int32 err = 0; - - if (unlikely(!(e = kzalloc(sizeof(struct wl_event_q), GFP_KERNEL)))) { - WL_ERR(("event alloc failed\n")); - return -ENOMEM; - } - - e->etype = event; - memcpy(&e->emsg, msg, sizeof(wl_event_msg_t)); - if (data) { - } - wl_lock_eq(wl); - list_add_tail(&e->eq_list, &wl->eq_list); - wl_unlock_eq(wl); - - return err; -} - -static void -wl_put_event(struct wl_event_q *e) -{ - kfree(e); -} - -void -wl_cfg80211_sdio_func(void *func) -{ - cfg80211_sdio_func = (struct sdio_func *)func; -} - -static void -wl_clear_sdio_func(void) -{ - cfg80211_sdio_func = NULL; -} - - -static struct sdio_func * -wl_sdio_func(void) -{ - return cfg80211_sdio_func; -} - -static int32 -wl_dongle_mode(struct net_device *ndev, int32 iftype) -{ - int32 infra = 0; - int32 ap = 0; - int32 err = 0; - - switch (iftype) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_WDS: - WL_ERR(("type (%d) : currently we do not support this mode\n", iftype)); - err = -EINVAL; - return err; - case NL80211_IFTYPE_ADHOC: - break; - case NL80211_IFTYPE_STATION: - infra = 1; - break; - default: - err = -EINVAL; - WL_ERR(("invalid type (%d)\n", iftype)); - return err; - } - infra = htod32(infra); - ap = htod32(ap); - WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra))) || - unlikely(err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap)))) { - WL_ERR(("WLC_SET_INFRA error (%d)\n", err)); - return err; - } - - return -EINPROGRESS; -} - -#ifndef EMBEDDED_PLATFORM -static int32 -wl_dongle_country(struct net_device *ndev, uint8 ccode) -{ - - int32 err = 0; - - - return err; -} - -static int32 -wl_dongle_up(struct net_device *ndev, uint32 up) -{ - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely(err = wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up)))) { - WL_ERR(("WLC_UP error (%d)\n", err)); - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return err; -} - -static int32 -wl_dongle_power(struct net_device *ndev, uint32 power_mode) -{ - int32 err = 0; - - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode)))) { - WL_ERR(("WLC_SET_PM error (%d)\n", err)); - } - return err; -} - -static int32 -wl_dongle_glom(struct net_device *ndev, uint32 glom, uint32 dongle_align) -{ - int8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - int32 err = 0; - - /* Match Host and Dongle rx alignment */ - bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - WL_ERR(("txglomalign error (%d)\n", err)); - goto dongle_glom_out; - } - /* disable glom option per default */ - bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - WL_ERR(("txglom error (%d)\n", err)); - goto dongle_glom_out; - } -dongle_glom_out : - return err; -} - -static int32 -wl_dongle_roam(struct net_device *ndev, uint32 roamvar, uint32 bcn_timeout) -{ - int8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - int32 err = 0; - - /* Setup timeout if Beacons are lost and roam is off to report link down */ - if (roamvar) { - bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - WL_ERR(("bcn_timeout error (%d)\n", err)); - goto dongle_rom_out; - } - } - /* Enable/Disable built-in roaming to allow supplicant to take care of roaming */ - bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - WL_ERR(("roam_off error (%d)\n", err)); - goto dongle_rom_out; - } -dongle_rom_out : - return err; -} - -static int32 -wl_dongle_eventmsg(struct net_device *ndev) -{ - - int8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - int8 eventmask[WL_EVENTING_MASK_LEN]; - int32 err = 0; - - /* Setup event_msgs */ - bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf)))) { - WL_ERR(("Get event_msgs error (%d)\n", err)); - goto dongle_eventmsg_out; - } - memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN); - - setbit(eventmask, WLC_E_SET_SSID); - setbit(eventmask, WLC_E_PRUNE); - setbit(eventmask, WLC_E_AUTH); - setbit(eventmask, WLC_E_REASSOC); - setbit(eventmask, WLC_E_REASSOC_IND); - setbit(eventmask, WLC_E_DEAUTH_IND); - setbit(eventmask, WLC_E_DISASSOC_IND); - setbit(eventmask, WLC_E_DISASSOC); - setbit(eventmask, WLC_E_JOIN); - setbit(eventmask, WLC_E_ASSOC_IND); - setbit(eventmask, WLC_E_PSK_SUP); - setbit(eventmask, WLC_E_LINK); - setbit(eventmask, WLC_E_NDIS_LINK); - setbit(eventmask, WLC_E_MIC_ERROR); - setbit(eventmask, WLC_E_PMKID_CACHE); - setbit(eventmask, WLC_E_TXFAIL); - setbit(eventmask, WLC_E_JOIN_START); - setbit(eventmask, WLC_E_SCAN_COMPLETE); - - bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); - if (unlikely(err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - WL_ERR(("Set event_msgs error (%d)\n", err)); - goto dongle_eventmsg_out; - } - -dongle_eventmsg_out : - return err; -} - -static int32 -wl_dongle_scantime(struct net_device *ndev, int32 scan_assoc_time, int32 scan_unassoc_time) -{ - int32 err = 0; - - if ((err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time, - sizeof(scan_assoc_time)))) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan assoc time is not supported\n")); - } else { - WL_ERR(("Scan assoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - if ((err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time, - sizeof(scan_unassoc_time)))) { - if (err == -EOPNOTSUPP) { - WL_INFO(("Scan unassoc time is not supported\n")); - } else { - WL_ERR(("Scan unassoc time error (%d)\n", err)); - } - goto dongle_scantime_out; - } - -dongle_scantime_out : - return err; -} - -static int32 -wl_dongle_offload(struct net_device *ndev, int32 arpoe, int32 arp_ol) -{ - int8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - int32 err = 0; - - /* Set ARP offload */ - bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf)); - if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - if (err == -EOPNOTSUPP) { - WL_INFO(("arpoe is not supported\n")); - } else { - WL_ERR(("arpoe error (%d)\n", err)); - } - goto dongle_offload_out; - } - bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf)); - if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - if (err == -EOPNOTSUPP) { - WL_INFO(("arp_ol is not supported\n")); - } else { - WL_ERR(("arp_ol error (%d)\n", err)); - } - goto dongle_offload_out; - } - -dongle_offload_out : - return err; -} - -static int32 -wl_pattern_atoh(int8 *src, int8 *dst) -{ -#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) - int i; - if (strncmp(src, "0x", 2) != 0 && - strncmp(src, "0X", 2) != 0) { - WL_ERR(("Mask invalid format. Needs to start with 0x\n")); - return -1; - } - src = src + 2; /* Skip past 0x */ - if (strlen(src) % 2 != 0) { - WL_ERR(("Mask invalid format. Needs to be of even length\n")); - return -1; - } - for (i = 0; *src != '\0'; i++) { - char num[3]; - strncpy(num, src, 2); - num[2] = '\0'; - dst[i] = (uint8)strtoul(num, NULL, 16); - src += 2; - } - return i; -} - -static int32 -wl_dongle_filter(struct net_device *ndev, uint32 filter_mode) -{ - int8 iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - const int8 *str; - struct wl_pkt_filter pkt_filter; - struct wl_pkt_filter *pkt_filterp; - int32 buf_len; - int32 str_len; - uint32 mask_size; - uint32 pattern_size; - int8 buf[256]; - int32 err = 0; - -/* add a default packet filter pattern */ - str = "pkt_filter_add"; - str_len = strlen(str); - strncpy(buf, str, str_len); - buf[ str_len ] = '\0'; - buf_len = str_len + 1; - - pkt_filterp = (struct wl_pkt_filter *) (buf + str_len + 1); - - /* Parse packet filter id. */ - pkt_filter.id = htod32(100); - - /* Parse filter polarity. */ - pkt_filter.negate_match = htod32(0); - - /* Parse filter type. */ - pkt_filter.type = htod32(0); - - /* Parse pattern filter offset. */ - pkt_filter.u.pattern.offset = htod32(0); - - /* Parse pattern filter mask. */ - mask_size = htod32(wl_pattern_atoh("0xff", - (char *) pkt_filterp->u.pattern.mask_and_pattern)); - - /* Parse pattern filter pattern. */ - pattern_size = htod32(wl_pattern_atoh("0x00", - (char *) &pkt_filterp->u.pattern.mask_and_pattern[mask_size])); - - if (mask_size != pattern_size) { - WL_ERR(("Mask and pattern not the same size\n")); - err = -EINVAL; - goto dongle_filter_out; - } - - pkt_filter.u.pattern.size_bytes = mask_size; - buf_len += WL_PKT_FILTER_FIXED_LEN; - buf_len += (WL_PKT_FILTER_PATTERN_FIXED_LEN + 2 * mask_size); - - /* Keep-alive attributes are set in local variable (keep_alive_pkt), and - ** then memcpy'ed into buffer (keep_alive_pktp) since there is no - ** guarantee that the buffer is properly aligned. - */ - memcpy((char *)pkt_filterp, &pkt_filter, - WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN); - - if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len))) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter not supported\n")); - } else { - WL_ERR(("filter (%d)\n", err)); - } - goto dongle_filter_out; - } - - /* set mode to allow pattern */ - bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf)); - if ((err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf)))) { - if (err == -EOPNOTSUPP) { - WL_INFO(("filter_mode not supported\n")); - } else { - WL_ERR(("filter_mode (%d)\n", err)); - } - goto dongle_filter_out; - } - -dongle_filter_out : - return err; -} -#endif /* !EMBEDDED_PLATFORM */ - -int32 -wl_config_dongle(struct wl_priv *wl, bool need_lock) -{ -#ifndef DHD_SDALIGN -#define DHD_SDALIGN 32 -#endif - struct net_device *ndev; - struct wireless_dev *wdev; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (wl->dongle_up) - return err; - - - ndev = wl_to_ndev(wl); - wdev = ndev->ieee80211_ptr; - if (need_lock) - rtnl_lock(); - -#ifndef EMBEDDED_PLATFORM - if (unlikely((err = wl_dongle_up(ndev, 0)))) - goto default_conf_out; - if (unlikely((err = wl_dongle_country(ndev, 0)))) - goto default_conf_out; - if (unlikely((err = wl_dongle_power(ndev, PM_FAST)))) - goto default_conf_out; - if (unlikely((err = wl_dongle_glom(ndev, 0, DHD_SDALIGN)))) - goto default_conf_out; - if (unlikely((err = wl_dongle_roam(ndev, (wl->roam_on ? 0 : 1), 3)))) - goto default_conf_out; - if (unlikely((err = wl_dongle_eventmsg(ndev)))) - goto default_conf_out; - - wl_dongle_scantime(ndev, 40, 80); - wl_dongle_offload(ndev, 1, 0xf); - wl_dongle_filter(ndev, 1); -#endif /* !EMBEDDED_PLATFORM */ - - err = wl_dongle_mode(ndev, wdev->iftype); - if (unlikely(err && err != -EINPROGRESS)) - goto default_conf_out; - if (unlikely((err = wl_dongle_probecap(wl)))) - goto default_conf_out; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - /* -EINPROGRESS: Call commit handler */ - -default_conf_out : - if (need_lock) - rtnl_unlock(); - - wl->dongle_up = TRUE; - - return err; - -} - -static int32 -wl_update_wiphybands(struct wl_priv *wl) -{ - struct wiphy *wiphy; - int32 phy_list; - int8 phy; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - if (unlikely(err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_PHYLIST, &phy_list, - sizeof(phy_list)))) { - WL_ERR(("error (%d)\n", err)); - return err; - } - - phy = ((char *)&phy_list)[1]; - WL_DBG(("%c phy\n", phy)); - if (phy == 'n' || phy == 'a') { - wiphy = wl_to_wiphy(wl); - wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -__wl_cfg80211_up(struct wl_priv *wl) -{ - int32 err = 0; - - if (unlikely(err = wl_config_dongle(wl, FALSE))) - return err; - - wl_invoke_iscan(wl); - set_bit(WL_STATUS_READY, &wl->status); - return err; -} - -static int32 -__wl_cfg80211_down(struct wl_priv *wl) -{ - int32 err = 0; - - /* Check if cfg80211 interface is already down */ - if (!test_bit(WL_STATUS_READY, &wl->status)) - return err; /* it is even not ready */ - - set_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - wl_term_iscan(wl); - if (wl->scan_request) { - cfg80211_scan_done(wl->scan_request, TRUE); /* TRUE means abort */ - wl->scan_request = NULL; - } - clear_bit(WL_STATUS_READY, &wl->status); - clear_bit(WL_STATUS_SCANNING, &wl->status); - clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status); - clear_bit(WL_STATUS_CONNECTED, &wl->status); - - return err; -} - -int32 -wl_cfg80211_up(void) -{ - struct wl_priv *wl; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl = WL_PRIV_GET(); - mutex_lock(&wl->usr_sync); - err = __wl_cfg80211_up(wl); - mutex_unlock(&wl->usr_sync); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -int32 -wl_cfg80211_down(void) -{ - struct wl_priv *wl; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl = WL_PRIV_GET(); - mutex_lock(&wl->usr_sync); - err = __wl_cfg80211_down(wl); - mutex_unlock(&wl->usr_sync); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - - return err; -} - -static int32 -wl_dongle_probecap(struct wl_priv *wl) -{ - int32 err = 0; - - if (unlikely((err = wl_update_wiphybands(wl)))) - return err; - - return err; -} - -static void * -wl_read_prof(struct wl_priv *wl, int32 item) -{ - switch (item) { - case WL_PROF_SEC: - return &wl->profile->sec; - case WL_PROF_ACT: - return &wl->profile->active; - case WL_PROF_BSSID: - return &wl->profile->bssid; - case WL_PROF_SSID: - return &wl->profile->ssid; - } - WL_ERR(("invalid item (%d)\n", item)); - return NULL; -} - -static int32 -wl_update_prof(struct wl_priv *wl, const wl_event_msg_t *e, void *data, int32 item) -{ - int32 err = 0; - struct wlc_ssid *ssid; - - switch (item) { - case WL_PROF_SSID: - ssid = (wlc_ssid_t *)data; - memset(wl->profile->ssid.SSID, 0, sizeof(wl->profile->ssid.SSID)); - memcpy(wl->profile->ssid.SSID, ssid->SSID, ssid->SSID_len); - wl->profile->ssid.SSID_len = ssid->SSID_len; - break; - case WL_PROF_BSSID: - if (data) - memcpy(wl->profile->bssid, data, ETHER_ADDR_LEN); - else - memset(wl->profile->bssid, 0, ETHER_ADDR_LEN); - break; - case WL_PROF_SEC: - memcpy(&wl->profile->sec, data, sizeof(wl->profile->sec)); - break; - case WL_PROF_ACT: - wl->profile->active = *(bool *)data; - break; - default : - WL_ERR(("unsupported item (%d)\n", item)); - err = -EOPNOTSUPP; - break; - } - - return err; -} - -void -wl_cfg80211_dbg_level(uint32 level) -{ - wl_dbg_level = level; -} - -static bool -wl_is_ibssmode(struct wl_priv *wl) -{ - return (wl->conf->mode == WL_MODE_IBSS); -} - -static bool -wl_is_ibssstarter(struct wl_priv *wl) -{ - return wl->ibss_starter; -} - -static void -wl_rst_ie(struct wl_priv *wl) -{ - struct wl_ie *ie = wl_to_ie(wl); - - ie->offset = 0; -} - -static int32 -wl_add_ie(struct wl_priv *wl, uint8 t, uint8 l, uint8 *v) -{ - struct wl_ie *ie = wl_to_ie(wl); - int32 err = 0; - - if (unlikely(ie->offset + l + 2 > WL_TLV_INFO_MAX)) { - WL_ERR(("ei crosses buffer boundary\n")); - return -ENOSPC; - } - ie->buf[ie->offset] = t; - ie->buf[ie->offset+1] = l; - memcpy(&ie->buf[ie->offset+2], v, l); - ie->offset += l+2; - - return err; -} - -static int32 -wl_mrg_ie(struct wl_priv *wl, uint8 *ie_stream, uint16 ie_size) -{ - struct wl_ie *ie = wl_to_ie(wl); - int32 err = 0; - - if (unlikely(ie->offset + ie_size > WL_TLV_INFO_MAX)) { - WL_ERR(("ei_stream crosses buffer boundary\n")); - return -ENOSPC; - } - memcpy(&ie->buf[ie->offset], ie_stream, ie_size); - ie->offset += ie_size; - - return err; -} - -static int32 -wl_cp_ie(struct wl_priv *wl, uint8 *dst, uint16 dst_size) -{ - struct wl_ie *ie = wl_to_ie(wl); - int32 err = 0; - - if (unlikely(ie->offset > dst_size)) { - WL_ERR(("dst_size is not enough\n")); - return -ENOSPC; - } - memcpy(dst, &ie->buf[0], ie->offset); - - return err; -} - -static uint32 -wl_get_ielen(struct wl_priv *wl) -{ - struct wl_ie *ie = wl_to_ie(wl); - - return ie->offset; -} - -static void -wl_link_up(struct wl_priv *wl) -{ - wl->link_up = TRUE; -} - -static void -wl_link_down(struct wl_priv *wl) -{ - struct wl_connect_info *conn_info = wl_to_conn(wl); - - wl->link_up = FALSE; - if (conn_info->req_ie) { - kfree(conn_info->req_ie); - conn_info->req_ie = NULL; - } - conn_info->req_ie_len = 0; - if (conn_info->resp_ie) { - kfree(conn_info->resp_ie); - conn_info->resp_ie = NULL; - } - conn_info->resp_ie_len = 0; -} - -static void -wl_lock_eq(struct wl_priv *wl) -{ - spin_lock_irq(&wl->eq_lock); -} - -static void -wl_unlock_eq(struct wl_priv *wl) -{ - spin_unlock_irq(&wl->eq_lock); -} - -static void -wl_init_eq_lock(struct wl_priv *wl) -{ - spin_lock_init(&wl->eq_lock); -} - -static void -wl_delay(uint32 ms) -{ - if (ms < 1000 / HZ) { - cond_resched(); - mdelay(ms); - } else { - msleep(ms); - } -} - -static void -wl_set_drvdata(struct wl_dev *dev, void *data) -{ - dev->driver_data = data; -} - -static void * -wl_get_drvdata(struct wl_dev *dev) -{ - return dev->driver_data; -} - -int32 -wl_cfg80211_read_fw(int8 *buf, uint32 size) -{ - const struct firmware *fw_entry; - struct wl_priv *wl; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In : size (%d)\n", size)); -#endif - wl = WL_PRIV_GET(); - - fw_entry = wl->fw->fw_entry; - - if (fw_entry->size < wl->fw->ptr + size) { - size = fw_entry->size - wl->fw->ptr; - } - memcpy(buf, &fw_entry->data[wl->fw->ptr], size); - wl->fw->ptr += size; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out : size (%d)\n", size)); -#endif - return size; -} - -void -wl_cfg80211_release_fw(void) -{ - struct wl_priv *wl; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl = WL_PRIV_GET(); - release_firmware(wl->fw->fw_entry); - wl->fw->ptr = 0; -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif -} - -void * -wl_cfg80211_request_fw(int8 *file_name) -{ - struct wl_priv *wl; - const struct firmware *fw_entry = NULL; - int32 err = 0; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - WL_DBG(("file name : \"%s\"\n", file_name)); - wl = WL_PRIV_GET(); - - if (!test_bit(WL_FW_LOADING_DONE, &wl->fw->status)) { - if (unlikely(err = request_firmware(&wl->fw->fw_entry, file_name, - &wl_sdio_func()->dev))) { - WL_ERR(("Could not download fw (%d)\n", err)); - goto req_fw_out; - } - set_bit(WL_FW_LOADING_DONE, &wl->fw->status); - fw_entry = wl->fw->fw_entry; - if (fw_entry) { - WL_DBG(("fw size (%d), data (%p)\n", fw_entry->size, fw_entry->data)); - } - } else if (!test_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status)) { - if (unlikely(err = request_firmware(&wl->fw->fw_entry, file_name, - &wl_sdio_func()->dev))) { - WL_ERR(("Could not download nvram (%d)\n", err)); - goto req_fw_out; - } - set_bit(WL_NVRAM_LOADING_DONE, &wl->fw->status); - fw_entry = wl->fw->fw_entry; - if (fw_entry) { - WL_DBG(("nvram size (%d), data (%p)\n", fw_entry->size, fw_entry->data)); - } - } else { - WL_DBG(("Downloading already done. Nothing to do more\n")); - err = -EPERM; - } -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - -req_fw_out: - if (unlikely(err)) { - return NULL; - } - wl->fw->ptr = 0; - return (void *)fw_entry->data; -} - -int8 * -wl_cfg80211_get_fwname(void) -{ - struct wl_priv *wl; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl = WL_PRIV_GET(); - strcpy(wl->fw->fw_name, WL_4329_FW_FILE); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return wl->fw->fw_name; -} - -int8 * -wl_cfg80211_get_nvramname(void) -{ - struct wl_priv *wl; - -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("In\n")); -#endif - wl = WL_PRIV_GET(); - strcpy(wl->fw->nvram_name, WL_4329_NVRAM_FILE); -#ifdef WL_CFG80211_BACKTRACE - WL_DBG(("Out\n")); -#endif - return wl->fw->nvram_name; -} diff --git a/drivers/net/wireless/bcm4329/wl_cfg80211.h b/drivers/net/wireless/bcm4329/wl_cfg80211.h deleted file mode 100644 index 27226992796d..000000000000 --- a/drivers/net/wireless/bcm4329/wl_cfg80211.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Linux Cfg80211 support - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: wl_cfg80211.h,v 1.1.2.19 2010/05/04 21:21:00 Exp $ - */ - -#ifndef _wl_cfg80211_h_ -#define _wl_cfg80211_h_ - -#include -#include -#include -#include -#include -#include - -struct wl_conf; -struct wl_iface; -struct wl_priv; -struct wl_security; -struct wl_ibss; - -#if defined(IL_BIGENDIAN) -#include -#define htod32(i) (bcmswap32(i)) -#define htod16(i) (bcmswap16(i)) -#define dtoh32(i) (bcmswap32(i)) -#define dtoh16(i) (bcmswap16(i)) -#define htodchanspec(i) htod16(i) -#define dtohchanspec(i) dtoh16(i) -#else -#define htod32(i) i -#define htod16(i) i -#define dtoh32(i) i -#define dtoh16(i) i -#define htodchanspec(i) i -#define dtohchanspec(i) i -#endif - -#define WL_DBG_NONE 0 -#define WL_DBG_DBG (1 << 2) -#define WL_DBG_INFO (1 << 1) -#define WL_DBG_ERR (1 << 0) -#define WL_DBG_MASK ((WL_DBG_DBG | WL_DBG_INFO | WL_DBG_ERR) << 1) - -#define WL_DBG_LEVEL 1 /* 0 invalidates all debug messages. default is 1 */ -#define WL_ERR(args) \ - do { \ - if (wl_dbg_level & WL_DBG_ERR) { \ - if (net_ratelimit()) { \ - printk("ERROR @%s : ", __FUNCTION__); \ - printk args; \ - } \ - } \ - } while (0) -#define WL_INFO(args) \ - do { \ - if (wl_dbg_level & WL_DBG_INFO) { \ - if (net_ratelimit()) { \ - printk("INFO @%s : ", __FUNCTION__); \ - printk args; \ - } \ - } \ - } while (0) -#if (WL_DBG_LEVEL > 0) -#define WL_DBG(args) \ - do { \ - if (wl_dbg_level & WL_DBG_DBG) { \ - printk("DEBUG @%s :", __FUNCTION__); \ - printk args; \ - } \ - } while (0) -#else /* !(WL_DBG_LEVEL > 0) */ -#define WL_DBG(args) -#endif /* (WL_DBG_LEVEL > 0) */ - -#define WL_SCAN_RETRY_MAX 3 /* used for ibss scan */ -#define WL_NUM_SCAN_MAX 1 -#define WL_NUM_PMKIDS_MAX MAXPMKID /* will be used for 2.6.33 kernel - * or later - */ -#define WL_SCAN_BUF_MAX (1024 * 8) -#define WL_TLV_INFO_MAX 1024 -#define WL_BSS_INFO_MAX 2048 -#define WL_ASSOC_INFO_MAX 512 /* - * needs to grab assoc info from dongle to - * report it to cfg80211 through "connect" - * event - */ -#define WL_IOCTL_LEN_MAX 1024 -#define WL_EXTRA_BUF_MAX 2048 -#define WL_ISCAN_BUF_MAX 2048 /* the buf lengh can be WLC_IOCTL_MAXLEN (8K) - * to reduce iteration - */ -#define WL_ISCAN_TIMER_INTERVAL_MS 3000 -#define WL_SCAN_ERSULTS_LAST (WL_SCAN_RESULTS_NO_MEM+1) -#define WL_AP_MAX 256 /* virtually unlimitted as long - * as kernel memory allows - */ -#define WL_FILE_NAME_MAX 256 - -/* dongle status */ -enum wl_status { - WL_STATUS_READY, - WL_STATUS_SCANNING, - WL_STATUS_SCAN_ABORTING, - WL_STATUS_CONNECTING, - WL_STATUS_CONNECTED -}; - -/* wi-fi mode */ -enum wl_mode { - WL_MODE_BSS, - WL_MODE_IBSS, - WL_MODE_AP -}; - -/* dongle profile list */ -enum wl_prof_list { - WL_PROF_MODE, - WL_PROF_SSID, - WL_PROF_SEC, - WL_PROF_IBSS, - WL_PROF_BAND, - WL_PROF_BSSID, - WL_PROF_ACT -}; - -/* dongle iscan state */ -enum wl_iscan_state { - WL_ISCAN_STATE_IDLE, - WL_ISCAN_STATE_SCANING -}; - -/* fw downloading status */ -enum wl_fw_status { - WL_FW_LOADING_DONE, - WL_NVRAM_LOADING_DONE -}; - -/* dongle configuration */ -struct wl_conf { - uint32 mode; /* adhoc , infrastructure or ap */ - uint32 frag_threshold; - uint32 rts_threshold; - uint32 retry_short; - uint32 retry_long; - int32 tx_power; - struct ieee80211_channel channel; -}; - -/* cfg80211 main event loop */ -struct wl_event_loop { - int32 (*handler[WLC_E_LAST])(struct wl_priv *wl, struct net_device *ndev, - const wl_event_msg_t *e, void *data); -}; - -/* representing interface of cfg80211 plane */ -struct wl_iface { - struct wl_priv *wl; -}; - -struct wl_dev { - void *driver_data; /* to store cfg80211 object information */ -}; - -/* bss inform structure for cfg80211 interface */ -struct wl_cfg80211_bss_info { - uint16 band; - uint16 channel; - int16 rssi; - uint16 frame_len; - uint8 frame_buf[1]; -}; - -/* basic structure of scan request */ -struct wl_scan_req { - struct wlc_ssid ssid; -}; - -/* basic structure of information element */ -struct wl_ie { - uint16 offset; - uint8 buf[WL_TLV_INFO_MAX]; -}; - -/* event queue for cfg80211 main event */ -struct wl_event_q { - struct list_head eq_list; - uint32 etype; - wl_event_msg_t emsg; - int8 edata[1]; -}; - -/* security information with currently associated ap */ -struct wl_security { - uint32 wpa_versions; - uint32 auth_type; - uint32 cipher_pairwise; - uint32 cipher_group; - uint32 wpa_auth; -}; - -/* ibss information for currently joined ibss network */ -struct wl_ibss { - uint8 beacon_interval; /* in millisecond */ - uint8 atim; /* in millisecond */ - int8 join_only; - uint8 band; - uint8 channel; -}; - -/* dongle profile */ -struct wl_profile { - uint32 mode; - struct wlc_ssid ssid; - uint8 bssid[ETHER_ADDR_LEN]; - struct wl_security sec; - struct wl_ibss ibss; - int32 band; - bool active; -}; - -/* dongle iscan event loop */ -struct wl_iscan_eloop { - int32 (*handler[WL_SCAN_ERSULTS_LAST])(struct wl_priv *wl); -}; - -/* dongle iscan controller */ -struct wl_iscan_ctrl { - struct net_device *dev; - struct timer_list timer; - uint32 timer_ms; - uint32 timer_on; - int32 state; - int32 pid; - struct semaphore sync; - struct completion exited; - struct wl_iscan_eloop el; - void *data; - int8 ioctl_buf[WLC_IOCTL_SMLEN]; - int8 scan_buf[WL_ISCAN_BUF_MAX]; -}; - -/* association inform */ -struct wl_connect_info { - uint8 *req_ie; - int32 req_ie_len; - uint8 *resp_ie; - int32 resp_ie_len; -}; - -/* firmware /nvram downloading controller */ -struct wl_fw_ctrl { - const struct firmware *fw_entry; - ulong status; - uint32 ptr; - int8 fw_name[WL_FILE_NAME_MAX]; - int8 nvram_name[WL_FILE_NAME_MAX]; -}; - -/* assoc ie length */ -struct wl_assoc_ielen { - uint32 req_len; - uint32 resp_len; -}; - -/* wpa2 pmk list */ -struct wl_pmk_list { - pmkid_list_t pmkids; - pmkid_t foo[MAXPMKID-1]; -}; - - -/* dongle private data of cfg80211 interface */ -struct wl_priv { - struct wireless_dev *wdev; /* representing wl cfg80211 device */ - struct wl_conf *conf; /* dongle configuration */ - struct cfg80211_scan_request *scan_request; /* scan request object */ - struct wl_event_loop el; /* main event loop */ - struct list_head eq_list; /* used for event queue */ - spinlock_t eq_lock; /* for event queue synchronization */ - struct mutex usr_sync; /* maily for dongle up/down synchronization */ - struct wl_scan_results *bss_list; /* bss_list holding scanned ap information */ - struct wl_scan_results *scan_results; - struct wl_scan_req *scan_req_int; /* scan request object for internal purpose */ - struct wl_cfg80211_bss_info *bss_info; /* bss information for cfg80211 layer */ - struct wl_ie ie; /* information element object for internal purpose */ - struct ether_addr bssid; /* bssid of currently engaged network */ - struct semaphore event_sync; /* for synchronization of main event thread */ - struct completion event_exit; - struct wl_profile *profile; /* holding dongle profile */ - struct wl_iscan_ctrl *iscan; /* iscan controller */ - struct wl_connect_info conn_info; /* association information container */ - struct wl_fw_ctrl *fw; /* control firwmare / nvram paramter downloading */ - struct wl_pmk_list *pmk_list; /* wpa2 pmk list */ - int32 event_pid; /* pid of main event handler thread */ - ulong status; /* current dongle status */ - void * pub; - uint32 channel; /* current channel */ - bool iscan_on; /* iscan on/off switch */ - bool iscan_kickstart; /* indicate iscan already started */ - bool active_scan; /* current scan mode */ - bool ibss_starter; /* indicates this sta is ibss starter */ - bool link_up; /* link/connection up flag */ - bool pwr_save; /* indicate whether dongle to support power save mode */ - bool dongle_up; /* indicate whether dongle up or not */ - bool roam_on; /* on/off switch for dongle self-roaming */ - bool scan_tried; /* indicates if first scan attempted */ - uint8 *ioctl_buf; /* ioctl buffer */ - uint8 *extra_buf; /* maily to grab assoc information */ - uint8 ci[0] __attribute__((__aligned__(NETDEV_ALIGN))); -}; - -#define wl_to_dev(w) (wiphy_dev(wl->wdev->wiphy)) -#define wl_to_wiphy(w) (w->wdev->wiphy) -#define wiphy_to_wl(w) ((struct wl_priv *)(wiphy_priv(w))) -#define wl_to_wdev(w) (w->wdev) -#define wdev_to_wl(w) ((struct wl_priv *)(wdev_priv(w))) -#define wl_to_ndev(w) (w->wdev->netdev) -#define ndev_to_wl(n) (wdev_to_wl(n->ieee80211_ptr)) -#define ci_to_wl(c) (ci->wl) -#define wl_to_ci(w) (&w->ci) -#define wl_to_sr(w) (w->scan_req_int) -#define wl_to_ie(w) (&w->ie) -#define iscan_to_wl(i) ((struct wl_priv *)(i->data)) -#define wl_to_iscan(w) (w->iscan) -#define wl_to_conn(w) (&w->conn_info) - -inline static struct wl_bss_info * next_bss(struct wl_scan_results *list, - struct wl_bss_info *bss) { - return (bss = bss ? - (struct wl_bss_info *)((uintptr)bss + dtoh32(bss->length)) : list->bss_info); -} -#define for_each_bss(list, bss, __i) \ - for (__i = 0; __i < list->count && __i < WL_AP_MAX; __i++, bss = next_bss(list, bss)) - -extern int32 wl_cfg80211_attach(struct net_device *ndev, void *data); -extern void wl_cfg80211_detach(void); -/* event handler from dongle */ -extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void* data); -extern void wl_cfg80211_sdio_func(void *func); /* set sdio function info */ -extern int32 wl_cfg80211_up(void); /* dongle up */ -extern int32 wl_cfg80211_down(void); /* dongle down */ -extern void wl_cfg80211_dbg_level(uint32 level); /* set dongle debugging level */ -extern void * wl_cfg80211_request_fw(int8 *file_name); /* request fw /nvram downloading */ -extern int32 wl_cfg80211_read_fw(int8 *buf, uint32 size); /* read fw image */ -extern void wl_cfg80211_release_fw(void); /* release fw */ -extern int8 * wl_cfg80211_get_fwname(void); /* get firmware name for the dongle */ -extern int8 * wl_cfg80211_get_nvramname(void); /* get nvram name for the dongle */ - -#endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcm4329/wl_iw.c b/drivers/net/wireless/bcm4329/wl_iw.c deleted file mode 100644 index d817dccf89ad..000000000000 --- a/drivers/net/wireless/bcm4329/wl_iw.c +++ /dev/null @@ -1,7552 +0,0 @@ -/* - * Linux Wireless Extensions support - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: wl_iw.c,v 1.51.4.9.2.6.4.124 2010/07/27 20:46:02 Exp $ - */ - -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -typedef void wlc_info_t; -typedef void wl_info_t; -typedef const struct si_pub si_t; -#include - -#include -#include -#include -#define WL_ERROR(x) printf x -#define WL_TRACE(x) -#define WL_ASSOC(x) -#define WL_INFORM(x) -#define WL_WSEC(x) -#define WL_SCAN(x) - -#include - - - -#ifndef IW_ENCODE_ALG_SM4 -#define IW_ENCODE_ALG_SM4 0x20 -#endif - -#ifndef IW_AUTH_WAPI_ENABLED -#define IW_AUTH_WAPI_ENABLED 0x20 -#endif - -#ifndef IW_AUTH_WAPI_VERSION_1 -#define IW_AUTH_WAPI_VERSION_1 0x00000008 -#endif - -#ifndef IW_AUTH_CIPHER_SMS4 -#define IW_AUTH_CIPHER_SMS4 0x00000020 -#endif - -#ifndef IW_AUTH_KEY_MGMT_WAPI_PSK -#define IW_AUTH_KEY_MGMT_WAPI_PSK 4 -#endif - -#ifndef IW_AUTH_KEY_MGMT_WAPI_CERT -#define IW_AUTH_KEY_MGMT_WAPI_CERT 8 -#endif - - -#define IW_WSEC_ENABLED(wsec) ((wsec) & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED | SMS4_ENABLED)) - -#include - -#define WL_IW_USE_ISCAN 1 -#define ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS 1 - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 - struct mutex g_wl_ss_scan_lock; -#endif - -#if defined(SOFTAP) -#define WL_SOFTAP(x) printk x -static struct net_device *priv_dev; -static bool ap_cfg_running = FALSE; -static bool ap_fw_loaded = FALSE; -struct net_device *ap_net_dev = NULL; -struct semaphore ap_eth_sema; -static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap); -static int wl_iw_softap_deassoc_stations(struct net_device *dev); -#endif - -#define WL_IW_IOCTL_CALL(func_call) \ - do { \ - func_call; \ - } while (0) - -static int g_onoff = G_WLAN_SET_ON; - -extern bool wl_iw_conn_status_str(uint32 event_type, uint32 status, - uint32 reason, char* stringBuf, uint buflen); -#include -extern void dhd_customer_gpio_wlan_ctrl(int onoff); -extern uint dhd_dev_reset(struct net_device *dev, uint8 flag); -extern void dhd_dev_init_ioctl(struct net_device *dev); -int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val); - -uint wl_msg_level = WL_ERROR_VAL; - -#define MAX_WLIW_IOCTL_LEN 1024 - - -#if defined(IL_BIGENDIAN) -#include -#define htod32(i) (bcmswap32(i)) -#define htod16(i) (bcmswap16(i)) -#define dtoh32(i) (bcmswap32(i)) -#define dtoh16(i) (bcmswap16(i)) -#define htodchanspec(i) htod16(i) -#define dtohchanspec(i) dtoh16(i) -#else -#define htod32(i) i -#define htod16(i) i -#define dtoh32(i) i -#define dtoh16(i) i -#define htodchanspec(i) i -#define dtohchanspec(i) i -#endif - -#ifdef CONFIG_WIRELESS_EXT - -extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev); -extern int dhd_wait_pend8021x(struct net_device *dev); -#endif - -#if WIRELESS_EXT < 19 -#define IW_IOCTL_IDX(cmd) ((cmd) - SIOCIWFIRST) -#define IW_EVENT_IDX(cmd) ((cmd) - IWEVFIRST) -#endif - -static void *g_scan = NULL; -static volatile uint g_scan_specified_ssid; -static wlc_ssid_t g_specific_ssid; - -static wlc_ssid_t g_ssid; - -static wl_iw_ss_cache_ctrl_t g_ss_cache_ctrl; -static volatile uint g_first_broadcast_scan; - - - - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) -#define DAEMONIZE(a) daemonize(a); \ - allow_signal(SIGKILL); \ - allow_signal(SIGTERM); -#else -#define RAISE_RX_SOFTIRQ() \ - cpu_raise_softirq(smp_processor_id(), NET_RX_SOFTIRQ) -#define DAEMONIZE(a) daemonize(); \ - do { if (a) \ - strncpy(current->comm, a, MIN(sizeof(current->comm), (strlen(a) + 1))); \ - } while (0); -#endif - -#if defined(WL_IW_USE_ISCAN) -#if !defined(CSCAN) -static void wl_iw_free_ss_cache(void); -static int wl_iw_run_ss_cache_timer(int kick_off); -#endif -int wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag); -static int dev_wlc_bufvar_set(struct net_device *dev, char *name, char *buf, int len); -#define ISCAN_STATE_IDLE 0 -#define ISCAN_STATE_SCANING 1 - - -#define WLC_IW_ISCAN_MAXLEN 2048 -typedef struct iscan_buf { - struct iscan_buf * next; - char iscan_buf[WLC_IW_ISCAN_MAXLEN]; -} iscan_buf_t; - -typedef struct iscan_info { - struct net_device *dev; - struct timer_list timer; - uint32 timer_ms; - uint32 timer_on; - int iscan_state; - iscan_buf_t * list_hdr; - iscan_buf_t * list_cur; - - - long sysioc_pid; - struct semaphore sysioc_sem; - struct completion sysioc_exited; - - uint32 scan_flag; -#if defined CSCAN - char ioctlbuf[WLC_IOCTL_MEDLEN]; -#else - char ioctlbuf[WLC_IOCTL_SMLEN]; -#endif - - wl_iscan_params_t *iscan_ex_params_p; - int iscan_ex_param_size; -} iscan_info_t; -#define COEX_DHCP 1 -static void wl_iw_bt_flag_set(struct net_device *dev, bool set); -static void wl_iw_bt_release(void); - -typedef enum bt_coex_status { - BT_DHCP_IDLE = 0, - BT_DHCP_START, - BT_DHCP_OPPORTUNITY_WINDOW, - BT_DHCP_FLAG_FORCE_TIMEOUT -} coex_status_t; -#define BT_DHCP_OPPORTUNITY_WINDOW_TIEM 2500 -#define BT_DHCP_FLAG_FORCE_TIME 5500 - -typedef struct bt_info { - struct net_device *dev; - struct timer_list timer; - uint32 timer_ms; - uint32 timer_on; - int bt_state; - - - long bt_pid; - struct semaphore bt_sem; - struct completion bt_exited; -} bt_info_t; - -bt_info_t *g_bt = NULL; -static void wl_iw_bt_timerfunc(ulong data); -iscan_info_t *g_iscan = NULL; -static void wl_iw_timerfunc(ulong data); -static void wl_iw_set_event_mask(struct net_device *dev); -static int -wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action); -#endif -static int -wl_iw_set_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -); -static int -wl_iw_get_scan( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -); - -static uint -wl_iw_get_scan_prep( - wl_scan_results_t *list, - struct iw_request_info *info, - char *extra, - short max_size -); - - -static void swap_key_from_BE( - wl_wsec_key_t *key -) -{ - key->index = htod32(key->index); - key->len = htod32(key->len); - key->algo = htod32(key->algo); - key->flags = htod32(key->flags); - key->rxiv.hi = htod32(key->rxiv.hi); - key->rxiv.lo = htod16(key->rxiv.lo); - key->iv_initialized = htod32(key->iv_initialized); -} - -static void swap_key_to_BE( - wl_wsec_key_t *key -) -{ - key->index = dtoh32(key->index); - key->len = dtoh32(key->len); - key->algo = dtoh32(key->algo); - key->flags = dtoh32(key->flags); - key->rxiv.hi = dtoh32(key->rxiv.hi); - key->rxiv.lo = dtoh16(key->rxiv.lo); - key->iv_initialized = dtoh32(key->iv_initialized); -} - -static int -dev_wlc_ioctl( - struct net_device *dev, - int cmd, - void *arg, - int len -) -{ - struct ifreq ifr; - wl_ioctl_t ioc; - mm_segment_t fs; - int ret = -EINVAL; - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return ret; - } - - WL_INFORM(("\n%s, PID:%x: send Local IOCTL -> dhd: cmd:0x%x, buf:%p, len:%d ,\n", - __FUNCTION__, current->pid, cmd, arg, len)); - - if (g_onoff == G_WLAN_SET_ON) { - memset(&ioc, 0, sizeof(ioc)); - ioc.cmd = cmd; - ioc.buf = arg; - ioc.len = len; - - strcpy(ifr.ifr_name, dev->name); - ifr.ifr_data = (caddr_t) &ioc; - - - ret = dev_open(dev); - if (ret) { - WL_ERROR(("%s: Error dev_open: %d\n", __func__, ret)); - return ret; - } - - fs = get_fs(); - set_fs(get_ds()); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - ret = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE); -#else - ret = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE); -#endif - set_fs(fs); - } - else { - WL_TRACE(("%s: call after driver stop : ignored\n", __FUNCTION__)); - } - return ret; -} - - -static int -dev_wlc_intvar_get_reg( - struct net_device *dev, - char *name, - uint reg, - int *retval) -{ - union { - char buf[WLC_IOCTL_SMLEN]; - int val; - } var; - int error; - - uint len; - len = bcm_mkiovar(name, (char *)(®), sizeof(reg), (char *)(&var), sizeof(var.buf)); - ASSERT(len); - error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len); - - *retval = dtoh32(var.val); - return (error); -} - - -static int -dev_wlc_intvar_set_reg( - struct net_device *dev, - char *name, - char *addr, - char * val) -{ - char reg_addr[8]; - - memset(reg_addr, 0, sizeof(reg_addr)); - memcpy((char *)®_addr[0], (char *)addr, 4); - memcpy((char *)®_addr[4], (char *)val, 4); - - return (dev_wlc_bufvar_set(dev, name, (char *)®_addr[0], sizeof(reg_addr))); -} - - - - -static int -dev_wlc_intvar_set( - struct net_device *dev, - char *name, - int val) -{ - char buf[WLC_IOCTL_SMLEN]; - uint len; - - val = htod32(val); - len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf)); - ASSERT(len); - - return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len)); -} - -#if defined(WL_IW_USE_ISCAN) -static int -dev_iw_iovar_setbuf( - struct net_device *dev, - char *iovar, - void *param, - int paramlen, - void *bufptr, - int buflen) -{ - int iolen; - - iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); - ASSERT(iolen); - - if (iolen == 0) - return 0; - - return (dev_wlc_ioctl(dev, WLC_SET_VAR, bufptr, iolen)); -} - -static int -dev_iw_iovar_getbuf( - struct net_device *dev, - char *iovar, - void *param, - int paramlen, - void *bufptr, - int buflen) -{ - int iolen; - - iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen); - ASSERT(iolen); - - return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen)); -} -#endif - - -#if WIRELESS_EXT > 17 -static int -dev_wlc_bufvar_set( - struct net_device *dev, - char *name, - char *buf, int len) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - char ioctlbuf[MAX_WLIW_IOCTL_LEN]; -#else - static char ioctlbuf[MAX_WLIW_IOCTL_LEN]; -#endif - uint buflen; - - buflen = bcm_mkiovar(name, buf, len, ioctlbuf, sizeof(ioctlbuf)); - ASSERT(buflen); - - return (dev_wlc_ioctl(dev, WLC_SET_VAR, ioctlbuf, buflen)); -} -#endif - - -static int -dev_wlc_bufvar_get( - struct net_device *dev, - char *name, - char *buf, int buflen) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - char ioctlbuf[MAX_WLIW_IOCTL_LEN]; -#else - static char ioctlbuf[MAX_WLIW_IOCTL_LEN]; -#endif - int error; - uint len; - - len = bcm_mkiovar(name, NULL, 0, ioctlbuf, sizeof(ioctlbuf)); - ASSERT(len); - error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf, MAX_WLIW_IOCTL_LEN); - if (!error) - bcopy(ioctlbuf, buf, buflen); - - return (error); -} - - - -static int -dev_wlc_intvar_get( - struct net_device *dev, - char *name, - int *retval) -{ - union { - char buf[WLC_IOCTL_SMLEN]; - int val; - } var; - int error; - - uint len; - uint data_null; - - len = bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var), sizeof(var.buf)); - ASSERT(len); - error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len); - - *retval = dtoh32(var.val); - - return (error); -} - - -#if WIRELESS_EXT > 12 -static int -wl_iw_set_active_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int as = 0; - int error = 0; - char *p = extra; - -#if defined(WL_IW_USE_ISCAN) - if (g_iscan->iscan_state == ISCAN_STATE_IDLE) -#endif - error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as)); -#if defined(WL_IW_USE_ISCAN) - else - g_iscan->scan_flag = as; -#endif - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - return error; -} - -static int -wl_iw_set_passive_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int ps = 1; - int error = 0; - char *p = extra; - -#if defined(WL_IW_USE_ISCAN) - if (g_iscan->iscan_state == ISCAN_STATE_IDLE) { -#endif - - - if (g_scan_specified_ssid == 0) { - error = dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &ps, sizeof(ps)); - } -#if defined(WL_IW_USE_ISCAN) - } - else - g_iscan->scan_flag = ps; -#endif - - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - return error; -} - -static int -wl_iw_get_macaddr( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error; - char buf[128]; - struct ether_addr *id; - char *p = extra; - - - strcpy(buf, "cur_etheraddr"); - error = dev_wlc_ioctl(dev, WLC_GET_VAR, buf, sizeof(buf)); - id = (struct ether_addr *) buf; - p += snprintf(p, MAX_WX_STRING, "Macaddr = %02X:%02X:%02X:%02X:%02X:%02X\n", - id->octet[0], id->octet[1], id->octet[2], - id->octet[3], id->octet[4], id->octet[5]); - wrqu->data.length = p - extra + 1; - - return error; -} - - - -static int -wl_iw_set_country( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - char country_code[WLC_CNTRY_BUF_SZ]; - int error = 0; - char *p = extra; - int country_offset; - int country_code_size; - - memset(country_code, 0, sizeof(country_code)); - - - country_offset = strcspn(extra, " "); - country_code_size = strlen(extra) - country_offset; - - - if (country_offset != 0) { - strncpy(country_code, extra + country_offset +1, - MIN(country_code_size, sizeof(country_code))); - - - if ((error = dev_wlc_ioctl(dev, WLC_SET_COUNTRY, - &country_code, sizeof(country_code))) >= 0) { - p += snprintf(p, MAX_WX_STRING, "OK"); - WL_TRACE(("%s: set country %s OK\n", __FUNCTION__, country_code)); - goto exit; - } - } - - WL_ERROR(("%s: set country %s failed code %d\n", __FUNCTION__, country_code, error)); - p += snprintf(p, MAX_WX_STRING, "FAIL"); - -exit: - wrqu->data.length = p - extra + 1; - return error; -} - -#ifdef CUSTOMER_HW2 -static int -wl_iw_set_power_mode( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = 0; - char *p = extra; - static int pm = PM_FAST; - int pm_local = PM_OFF; - char powermode_val = 0; - - strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1); - - if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - - WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); - - dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)); - dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); - } - else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { - - WL_TRACE(("%s: DHCP session done\n", __FUNCTION__)); - - - dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); - } - else { - WL_ERROR(("Unkwown yet power setting, ignored\n")); - } - - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return error; -} -#endif -static int -wl_iw_set_btcoex_dhcp( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = 0; - char *p = extra; -#ifndef CUSTOMER_HW2 - static int pm = PM_FAST; - int pm_local = PM_OFF; -#endif - char powermode_val = 0; - char buf_reg66va_dhcp_on[8] = { 66, 00, 00, 00, 0x10, 0x27, 0x00, 0x00 }; - char buf_reg41va_dhcp_on[8] = { 41, 00, 00, 00, 0x33, 0x00, 0x00, 0x00 }; - char buf_reg68va_dhcp_on[8] = { 68, 00, 00, 00, 0x90, 0x01, 0x00, 0x00 }; - - uint32 regaddr; - static uint32 saved_reg66; - static uint32 saved_reg41; - static uint32 saved_reg68; - static bool saved_status = FALSE; - - char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; -#ifndef CUSTOMER_HW2 - uint32 temp1, temp2; -#endif - - -#ifdef CUSTOMER_HW2 - strncpy((char *)&powermode_val, extra + strlen("BTCOEXMODE") +1, 1); -#else - strncpy((char *)&powermode_val, extra + strlen("POWERMODE") +1, 1); -#endif - - if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - - WL_TRACE(("%s: DHCP session starts\n", __FUNCTION__)); - - - if ((saved_status == FALSE) && -#ifndef CUSTOMER_HW2 - (!dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm))) && -#endif - (!dev_wlc_intvar_get_reg(dev, "btc_params", 66, &saved_reg66)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 41, &saved_reg41)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 68, &saved_reg68))) { - saved_status = TRUE; - WL_TRACE(("Saved 0x%x 0x%x 0x%x\n", \ - saved_reg66, saved_reg41, saved_reg68)); - - -#ifndef CUSTOMER_HW2 - dev_wlc_ioctl(dev, WLC_SET_PM, &pm_local, sizeof(pm_local)); -#endif - - - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg66va_dhcp_on[0], \ - sizeof(buf_reg66va_dhcp_on)); - - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg41va_dhcp_on[0], \ - sizeof(buf_reg41va_dhcp_on)); - - dev_wlc_bufvar_set(dev, "btc_params", \ - (char *)&buf_reg68va_dhcp_on[0], \ - sizeof(buf_reg68va_dhcp_on)); - -#ifndef CUSTOMER_HW2 - if ((!dev_wlc_intvar_get_reg(dev, "btc_params", 12, &temp1)) && - (!dev_wlc_intvar_get_reg(dev, "btc_params", 13, &temp2))) - { - if ((temp1 != 0) && (temp2 != 0)) { -#endif - g_bt->bt_state = BT_DHCP_START; - g_bt->timer_on = 1; - mod_timer(&g_bt->timer, g_bt->timer.expires); - WL_TRACE(("%s enable BT DHCP Timer\n", \ - __FUNCTION__)); -#ifndef CUSTOMER_HW2 - } - } -#endif - } - else if (saved_status == TRUE) { - WL_ERROR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__)); - } - } -#ifdef CUSTOMER_HW2 - else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { -#else - else if (strnicmp((char *)&powermode_val, "0", strlen("0")) == 0) { -#endif - - WL_TRACE(("%s: DHCP session done\n", __FUNCTION__)); - - -#ifndef CUSTOMER_HW2 - dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)); -#endif - - - WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); - if (g_bt->timer_on) { - g_bt->timer_on = 0; - del_timer_sync(&g_bt->timer); - } - - - dev_wlc_bufvar_set(dev, "btc_flags", \ - (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); - - - if (saved_status) { - regaddr = 66; - dev_wlc_intvar_set_reg(dev, "btc_params", \ - (char *)®addr, (char *)&saved_reg66); - regaddr = 41; - dev_wlc_intvar_set_reg(dev, "btc_params", \ - (char *)®addr, (char *)&saved_reg41); - regaddr = 68; - dev_wlc_intvar_set_reg(dev, "btc_params", \ - (char *)®addr, (char *)&saved_reg68); - } - saved_status = FALSE; - - } - else { - WL_ERROR(("Unkwown yet power setting, ignored\n")); - } - - p += snprintf(p, MAX_WX_STRING, "OK"); - - wrqu->data.length = p - extra + 1; - - return error; -} - -int -wl_format_ssid(char* ssid_buf, uint8* ssid, int ssid_len) -{ - int i, c; - char *p = ssid_buf; - - if (ssid_len > 32) ssid_len = 32; - - for (i = 0; i < ssid_len; i++) { - c = (int)ssid[i]; - if (c == '\\') { - *p++ = '\\'; - *p++ = '\\'; - } else if (isprint((uchar)c)) { - *p++ = (char)c; - } else { - p += sprintf(p, "\\x%02X", c); - } - } - *p = '\0'; - - return p - ssid_buf; -} - -static int -wl_iw_get_link_speed( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = 0; - char *p = extra; - static int link_speed; - - - if (g_onoff == G_WLAN_SET_ON) { - error = dev_wlc_ioctl(dev, WLC_GET_RATE, &link_speed, sizeof(link_speed)); - link_speed *= 500000; - } - - p += snprintf(p, MAX_WX_STRING, "LinkSpeed %d", link_speed/1000000); - - wrqu->data.length = p - extra + 1; - - return error; -} - - -static int -wl_iw_get_band( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = -1; - char *p = extra; - static int band; - - if (g_onoff == G_WLAN_SET_ON) { - error = dev_wlc_ioctl(dev, WLC_GET_BAND, &band, sizeof(band)); - - p += snprintf(p, MAX_WX_STRING, "Band %d", band); - - wrqu->data.length = p - extra + 1; - } - return error; -} - - -static int -wl_iw_set_band( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error = -1; - char *p = extra; - char band; - - if (g_onoff == G_WLAN_SET_ON) { - - band = *(extra + strlen(BAND_SET_CMD) + 1) - '0'; - - if ((band == WLC_BAND_AUTO) || (band == WLC_BAND_5G) || (band == WLC_BAND_2G)) { - - - if ((error = dev_wlc_ioctl(dev, WLC_SET_BAND, - &band, sizeof(band))) >= 0) { - p += snprintf(p, MAX_WX_STRING, "OK"); - WL_TRACE(("%s: set band %d OK\n", __FUNCTION__, band)); - goto exit; - } - else WL_ERROR(("%s: set band %d failed code %d\n", __FUNCTION__, \ - band, error)); - } - else WL_ERROR(("%s Incorrect band setting, ignored\n", __FUNCTION__)); - } - - p += snprintf(p, MAX_WX_STRING, "FAIL"); - -exit: - wrqu->data.length = p - extra + 1; - return error; -} - - -static int -wl_iw_get_rssi( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - static int rssi = 0; - static wlc_ssid_t ssid = {0}; - int error = 0; - char *p = extra; - static char ssidbuf[SSID_FMT_BUF_LEN]; - scb_val_t scb_val; - - bzero(&scb_val, sizeof(scb_val_t)); - - if (g_onoff == G_WLAN_SET_ON) { - error = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)); - rssi = dtoh32(scb_val.val); - - error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)); - - ssid.SSID_len = dtoh32(ssid.SSID_len); - } - - wl_format_ssid(ssidbuf, ssid.SSID, dtoh32(ssid.SSID_len)); - p += snprintf(p, MAX_WX_STRING, "%s rssi %d ", ssidbuf, rssi); - wrqu->data.length = p - extra + 1; - - return error; -} - -int -wl_iw_send_priv_event( - struct net_device *dev, - char *flag -) -{ - union iwreq_data wrqu; - char extra[IW_CUSTOM_MAX + 1]; - int cmd; - - cmd = IWEVCUSTOM; - memset(&wrqu, 0, sizeof(wrqu)); - if (strlen(flag) > sizeof(extra)) - return -1; - - strcpy(extra, flag); - wrqu.data.length = strlen(extra); - wireless_send_event(dev, cmd, &wrqu, extra); - WL_TRACE(("Send IWEVCUSTOM Event as %s\n", extra)); - - return 0; -} - - -int -wl_control_wl_start(struct net_device *dev) -{ - int ret = 0; - wl_iw_t *iw; - - WL_ERROR(("Enter %s \n", __FUNCTION__)); - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return -1; - } - - iw = *(wl_iw_t **)netdev_priv(dev); - MUTEX_LOCK(iw->pub); - - if (g_onoff == G_WLAN_SET_OFF) { - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON); - -#if defined(BCMLXSDMMC) - sdioh_start(NULL, 0); -#endif - - dhd_dev_reset(dev, 0); - -#if defined(BCMLXSDMMC) - sdioh_start(NULL, 1); -#endif - - dhd_dev_init_ioctl(dev); - - g_onoff = G_WLAN_SET_ON; - } - WL_ERROR(("Exited %s \n", __FUNCTION__)); - - MUTEX_UNLOCK(iw->pub); - return ret; -} -static int -wl_iw_control_wl_off( - struct net_device *dev, - struct iw_request_info *info -) -{ - int ret = 0; - wl_iw_t *iw; - - WL_ERROR(("Enter %s\n", __FUNCTION__)); - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return -1; - } - - iw = *(wl_iw_t **)netdev_priv(dev); - MUTEX_LOCK(iw->pub); - -#ifdef SOFTAP - ap_cfg_running = FALSE; - -#endif - - if (g_onoff == G_WLAN_SET_ON) { - g_onoff = G_WLAN_SET_OFF; - -#if defined(WL_IW_USE_ISCAN) - g_iscan->iscan_state = ISCAN_STATE_IDLE; -#endif - - dhd_dev_reset(dev, 1); - -#if defined(WL_IW_USE_ISCAN) -#if !defined(CSCAN) - - wl_iw_free_ss_cache(); - wl_iw_run_ss_cache_timer(0); - - g_ss_cache_ctrl.m_link_down = 1; -#endif - memset(g_scan, 0, G_SCAN_RESULTS); - g_scan_specified_ssid = 0; - - g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE; -#endif - -#if defined(BCMLXSDMMC) - sdioh_stop(NULL); -#endif - - dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); - - wl_iw_send_priv_event(dev, "STOP"); - - } - - MUTEX_UNLOCK(iw->pub); - - WL_TRACE(("Exited %s\n", __FUNCTION__)); - - return ret; -} - -static int -wl_iw_control_wl_on( - struct net_device *dev, - struct iw_request_info *info -) -{ - int ret = 0; - - WL_TRACE(("Enter %s \n", __FUNCTION__)); - - ret = wl_control_wl_start(dev); - - wl_iw_send_priv_event(dev, "START"); - -#if !defined(CSCAN) -#ifdef SOFTAP - if (!ap_fw_loaded) { - wl_iw_iscan_set_scan_broadcast_prep(dev, 0); - } -#else - wl_iw_iscan_set_scan_broadcast_prep(dev, 0); -#endif -#endif - - WL_TRACE(("Exited %s \n", __FUNCTION__)); - - return ret; -} - -#ifdef SOFTAP -static struct ap_profile my_ap; -static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap); -static int get_assoc_sta_list(struct net_device *dev, char *buf, int len); -static int set_ap_mac_list(struct net_device *dev, char *buf); - -#define PTYPE_STRING 0 -#define PTYPE_INTDEC 1 -#define PTYPE_INTHEX 2 -#define PTYPE_STR_HEX 3 -int get_parmeter_from_string( - char **str_ptr, const char *token, int param_type, void *dst, int param_max_len); - -#endif - -int hex2num(char c) -{ - if (c >= '0' && c <= '9') - return c - '0'; - if (c >= 'a' && c <= 'f') - return c - 'a' + 10; - if (c >= 'A' && c <= 'F') - return c - 'A' + 10; - return -1; -} - -int hex2byte(const char *hex) -{ - int a, b; - a = hex2num(*hex++); - if (a < 0) - return -1; - b = hex2num(*hex++); - if (b < 0) - return -1; - return (a << 4) | b; -} - - - -int hstr_2_buf(const char *txt, u8 *buf, int len) -{ - int i; - - for (i = 0; i < len; i++) { - int a, b; - - a = hex2num(*txt++); - if (a < 0) - return -1; - b = hex2num(*txt++); - if (b < 0) - return -1; - *buf++ = (a << 4) | b; - } - - return 0; -} - -#ifdef SOFTAP -int init_ap_profile_from_string(char *param_str, struct ap_profile *ap_cfg) -{ - char *str_ptr = param_str; - char sub_cmd[16]; - int ret = 0; - - memset(sub_cmd, 0, sizeof(sub_cmd)); - memset(ap_cfg, 0, sizeof(struct ap_profile)); - - - if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=", - PTYPE_STRING, sub_cmd, SSID_LEN) != 0) { - return -1; - } - if (strncmp(sub_cmd, "AP_CFG", 6)) { - WL_ERROR(("ERROR: sub_cmd:%s != 'AP_CFG'!\n", sub_cmd)); - return -1; - } - - - - ret = get_parmeter_from_string(&str_ptr, "SSID=", PTYPE_STRING, ap_cfg->ssid, SSID_LEN); - - ret |= get_parmeter_from_string(&str_ptr, "SEC=", PTYPE_STRING, ap_cfg->sec, SEC_LEN); - - ret |= get_parmeter_from_string(&str_ptr, "KEY=", PTYPE_STRING, ap_cfg->key, KEY_LEN); - - ret |= get_parmeter_from_string(&str_ptr, "CHANNEL=", PTYPE_INTDEC, &ap_cfg->channel, 5); - - ret |= get_parmeter_from_string(&str_ptr, "PREAMBLE=", PTYPE_INTDEC, &ap_cfg->preamble, 5); - - ret |= get_parmeter_from_string(&str_ptr, "MAX_SCB=", PTYPE_INTDEC, &ap_cfg->max_scb, 5); - - return ret; -} -#endif - - - -#ifdef SOFTAP -static int iwpriv_set_ap_config(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - int res = 0; - char *extra = NULL; - struct ap_profile *ap_cfg = &my_ap; - - WL_TRACE(("> Got IWPRIV SET_AP IOCTL: info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n", - info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length)); - - - if (wrqu->data.length != 0) { - - char *str_ptr; - - if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL))) - return -ENOMEM; - - if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) { - kfree(extra); - return -EFAULT; - } - - extra[wrqu->data.length] = 0; - WL_SOFTAP((" Got str param in iw_point:\n %s\n", extra)); - - memset(ap_cfg, 0, sizeof(struct ap_profile)); - - - - str_ptr = extra; - - if ((res = init_ap_profile_from_string(extra, ap_cfg)) < 0) { - WL_ERROR(("%s failed to parse %d\n", __FUNCTION__, res)); - kfree(extra); - return -1; - } - - } else { - - WL_ERROR(("IWPRIV argument len = 0 \n")); - return -1; - } - - if ((res = set_ap_cfg(dev, ap_cfg)) < 0) - WL_ERROR(("%s failed to set_ap_cfg %d\n", __FUNCTION__, res)); - - kfree(extra); - - return res; -} -#endif - - - -#ifdef SOFTAP -static int iwpriv_get_assoc_list(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *p_iwrq, - char *extra) -{ - int i, ret = 0; - char mac_buf[256]; - struct maclist *sta_maclist = (struct maclist *)mac_buf; - - char mac_lst[256]; - char *p_mac_str; - - WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d, \ - iwp.len:%p, iwp.flags:%x \n", __FUNCTION__, info->cmd, info->flags, \ - extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags)); - - WL_SOFTAP(("extra:%s\n", extra)); - print_buf((u8 *)p_iwrq, 16, 0); - - memset(sta_maclist, 0, sizeof(mac_buf)); - - sta_maclist->count = 8; - - WL_TRACE((" net device:%s, buf_sz:%d\n", dev->name, sizeof(mac_buf))); - get_assoc_sta_list(dev, mac_buf, 256); - WL_TRACE((" got %d stations\n", sta_maclist->count)); - - - memset(mac_lst, 0, sizeof(mac_lst)); - p_mac_str = mac_lst; - - for (i = 0; i < 8; i++) { - struct ether_addr * id = &sta_maclist->ea[i]; - - WL_SOFTAP(("dhd_drv>> sta_mac[%d] :", i)); - print_buf((unsigned char *)&sta_maclist->ea[i], 6, 0); - - - p_mac_str += snprintf(p_mac_str, MAX_WX_STRING, - "Mac[%d]=%02X:%02X:%02X:%02X:%02X:%02X\n", i, - id->octet[0], id->octet[1], id->octet[2], - id->octet[3], id->octet[4], id->octet[5]); - - } - - p_iwrq->data.length = strlen(mac_lst); - - WL_TRACE(("u.pointer:%p\n", p_iwrq->data.pointer)); - WL_TRACE(("resulting str:\n%s \n len:%d\n\n", mac_lst, p_iwrq->data.length)); - - if (p_iwrq->data.length) { - if (copy_to_user(p_iwrq->data.pointer, mac_lst, p_iwrq->data.length)) { - WL_ERROR(("%s: Can't copy to user\n", __FUNCTION__)); - return -EFAULT; - } - } - - WL_ERROR(("Exited %s \n", __FUNCTION__)); - return ret; -} -#endif - - -#ifdef SOFTAP -static int iwpriv_set_mac_filters(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - - int i, ret = -1; - char * extra = NULL; - u8 macfilt[8][6]; - int mac_cnt = 0; - char sub_cmd[16]; - - WL_TRACE((">>> Got IWPRIV SET_MAC_FILTER IOCTL: info->cmd:%x, \ - info->flags:%x, u.data:%p, u.len:%d\n", - info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length)); - - if (wrqu->data.length != 0) { - - char *str_ptr; - - if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL))) - return -ENOMEM; - - if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) { - kfree(extra); - return -EFAULT; - } - - extra[wrqu->data.length] = 0; - WL_SOFTAP((" Got parameter string in iw_point:\n %s \n", extra)); - - memset(macfilt, 0, sizeof(macfilt)); - memset(sub_cmd, 0, sizeof(sub_cmd)); - - - str_ptr = extra; - - - if (get_parmeter_from_string(&str_ptr, "ASCII_CMD=", PTYPE_STRING, sub_cmd, 15) != 0) { - goto exit_proc; - } - -#define MAC_FILT_MAX 8 - - if (strncmp(sub_cmd, "MAC_FLT_W", strlen("MAC_FLT_W"))) { - WL_ERROR(("ERROR: sub_cmd:%s != 'MAC_FLT_W'!\n", sub_cmd)); - goto exit_proc; - } - - if (get_parmeter_from_string(&str_ptr, "MAC_CNT=", - PTYPE_INTDEC, &mac_cnt, 4) != 0) { - WL_ERROR(("ERROR: MAC_CNT param is missing \n")); - goto exit_proc; - } - - if (mac_cnt > MAC_FILT_MAX) { - WL_ERROR(("ERROR: number of MAC filters > MAX\n")); - goto exit_proc; - } - - for (i=0; i< mac_cnt; i++) - if (get_parmeter_from_string(&str_ptr, "MAC=", - PTYPE_STR_HEX, macfilt[i], 12) != 0) { - WL_ERROR(("ERROR: MAC_filter[%d] is missing !\n", i)); - goto exit_proc; - } - - for (i = 0; i < mac_cnt; i++) { - WL_SOFTAP(("mac_filt[%d]:", i)); - print_buf(macfilt[i], 6, 0); - } - - - wrqu->data.pointer = NULL; - wrqu->data.length = 0; - ret = 0; - - } else { - - WL_ERROR(("IWPRIV argument len is 0\n")); - return -1; - } - - exit_proc: - kfree(extra); - return ret; -} -#endif - -#endif - -#if WIRELESS_EXT < 13 -struct iw_request_info -{ - __u16 cmd; - __u16 flags; -}; - -typedef int (*iw_handler)(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra); -#endif - -static int -wl_iw_config_commit( - struct net_device *dev, - struct iw_request_info *info, - void *zwrq, - char *extra -) -{ - wlc_ssid_t ssid; - int error; - struct sockaddr bssid; - - WL_TRACE(("%s: SIOCSIWCOMMIT\n", dev->name)); - - if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) - return error; - - ssid.SSID_len = dtoh32(ssid.SSID_len); - - if (!ssid.SSID_len) - return 0; - - bzero(&bssid, sizeof(struct sockaddr)); - if ((error = dev_wlc_ioctl(dev, WLC_REASSOC, &bssid, ETHER_ADDR_LEN))) { - WL_ERROR(("%s: WLC_REASSOC to %s failed \n", __FUNCTION__, ssid.SSID)); - return error; - } - - return 0; -} - -static int -wl_iw_get_name( - struct net_device *dev, - struct iw_request_info *info, - char *cwrq, - char *extra -) -{ - WL_TRACE(("%s: SIOCGIWNAME\n", dev->name)); - - strcpy(cwrq, "IEEE 802.11-DS"); - - return 0; -} - -static int -wl_iw_set_freq( - struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra -) -{ - int error, chan; - uint sf = 0; - - WL_TRACE(("\n %s %s: SIOCSIWFREQ\n", __FUNCTION__, dev->name)); - -#if defined(SOFTAP) - if (ap_cfg_running) { - WL_TRACE(("%s:>> not executed, 'SOFT_AP is active' \n", __FUNCTION__)); - return 0; - } -#endif - - - if (fwrq->e == 0 && fwrq->m < MAXCHANNEL) { - chan = fwrq->m; - } - - - else { - - if (fwrq->e >= 6) { - fwrq->e -= 6; - while (fwrq->e--) - fwrq->m *= 10; - } else if (fwrq->e < 6) { - while (fwrq->e++ < 6) - fwrq->m /= 10; - } - - if (fwrq->m > 4000 && fwrq->m < 5000) - sf = WF_CHAN_FACTOR_4_G; - - chan = wf_mhz2channel(fwrq->m, sf); - } - chan = htod32(chan); - - if ((error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan)))) - return error; - - - return -EINPROGRESS; -} - -static int -wl_iw_get_freq( - struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, - char *extra -) -{ - channel_info_t ci; - int error; - - WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name)); - - if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) - return error; - - - fwrq->m = dtoh32(ci.hw_channel); - fwrq->e = dtoh32(0); - return 0; -} - -static int -wl_iw_set_mode( - struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra -) -{ - int infra = 0, ap = 0, error = 0; - - WL_TRACE(("%s: SIOCSIWMODE\n", dev->name)); - - switch (*uwrq) { - case IW_MODE_MASTER: - infra = ap = 1; - break; - case IW_MODE_ADHOC: - case IW_MODE_AUTO: - break; - case IW_MODE_INFRA: - infra = 1; - break; - default: - return -EINVAL; - } - infra = htod32(infra); - ap = htod32(ap); - - if ((error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra))) || - (error = dev_wlc_ioctl(dev, WLC_SET_AP, &ap, sizeof(ap)))) - return error; - - - return -EINPROGRESS; -} - -static int -wl_iw_get_mode( - struct net_device *dev, - struct iw_request_info *info, - __u32 *uwrq, - char *extra -) -{ - int error, infra = 0, ap = 0; - - WL_TRACE(("%s: SIOCGIWMODE\n", dev->name)); - - if ((error = dev_wlc_ioctl(dev, WLC_GET_INFRA, &infra, sizeof(infra))) || - (error = dev_wlc_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap)))) - return error; - - infra = dtoh32(infra); - ap = dtoh32(ap); - *uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC; - - return 0; -} - -static int -wl_iw_get_range( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - struct iw_range *range = (struct iw_range *) extra; - wl_uint32_list_t *list; - wl_rateset_t rateset; - int8 *channels; - int error, i, k; - uint sf, ch; - - int phytype; - int bw_cap = 0, sgi_tx = 0, nmode = 0; - channel_info_t ci; - uint8 nrate_list2copy = 0; - uint16 nrate_list[4][8] = { {13, 26, 39, 52, 78, 104, 117, 130}, - {14, 29, 43, 58, 87, 116, 130, 144}, - {27, 54, 81, 108, 162, 216, 243, 270}, - {30, 60, 90, 120, 180, 240, 270, 300}}; - - WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); - - if (!extra) - return -EINVAL; - - channels = kmalloc((MAXCHANNEL+1)*4, GFP_KERNEL); - if (!channels) { - WL_ERROR(("Could not alloc channels\n")); - return -ENOMEM; - } - list = (wl_uint32_list_t *)channels; - - dwrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(range)); - - - range->min_nwid = range->max_nwid = 0; - - - list->count = htod32(MAXCHANNEL); - if ((error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels, (MAXCHANNEL+1)*4))) { - kfree(channels); - return error; - } - for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) { - range->freq[i].i = dtoh32(list->element[i]); - - ch = dtoh32(list->element[i]); - if (ch <= CH_MAX_2G_CHANNEL) - sf = WF_CHAN_FACTOR_2_4_G; - else - sf = WF_CHAN_FACTOR_5_G; - - range->freq[i].m = wf_channel2mhz(ch, sf); - range->freq[i].e = 6; - } - range->num_frequency = range->num_channels = i; - - - range->max_qual.qual = 5; - - range->max_qual.level = 0x100 - 200; - - range->max_qual.noise = 0x100 - 200; - - range->sensitivity = 65535; - -#if WIRELESS_EXT > 11 - - range->avg_qual.qual = 3; - - range->avg_qual.level = 0x100 + WL_IW_RSSI_GOOD; - - range->avg_qual.noise = 0x100 - 75; -#endif - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) { - kfree(channels); - return error; - } - rateset.count = dtoh32(rateset.count); - range->num_bitrates = rateset.count; - for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) - range->bitrate[i] = (rateset.rates[i]& 0x7f) * 500000; - dev_wlc_intvar_get(dev, "nmode", &nmode); - dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)); - - if (nmode == 1 && phytype == WLC_PHY_TYPE_SSN) { - dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap); - dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx); - dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)); - ci.hw_channel = dtoh32(ci.hw_channel); - - if (bw_cap == 0 || - (bw_cap == 2 && ci.hw_channel <= 14)) { - if (sgi_tx == 0) - nrate_list2copy = 0; - else - nrate_list2copy = 1; - } - if (bw_cap == 1 || - (bw_cap == 2 && ci.hw_channel >= 36)) { - if (sgi_tx == 0) - nrate_list2copy = 2; - else - nrate_list2copy = 3; - } - range->num_bitrates += 8; - for (k = 0; i < range->num_bitrates; k++, i++) { - - range->bitrate[i] = (nrate_list[nrate_list2copy][k]) * 500000; - } - } - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &i, sizeof(i)))) { - kfree(channels); - return error; - } - i = dtoh32(i); - if (i == WLC_PHY_TYPE_A) - range->throughput = 24000000; - else - range->throughput = 1500000; - - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS; - range->num_encoding_sizes = 4; - range->encoding_size[0] = WEP1_KEY_SIZE; - range->encoding_size[1] = WEP128_KEY_SIZE; -#if WIRELESS_EXT > 17 - range->encoding_size[2] = TKIP_KEY_SIZE; -#else - range->encoding_size[2] = 0; -#endif - range->encoding_size[3] = AES_KEY_SIZE; - - - range->min_pmp = 0; - range->max_pmp = 0; - range->min_pmt = 0; - range->max_pmt = 0; - range->pmp_flags = 0; - range->pm_capa = 0; - - - range->num_txpower = 2; - range->txpower[0] = 1; - range->txpower[1] = 255; - range->txpower_capa = IW_TXPOW_MWATT; - -#if WIRELESS_EXT > 10 - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 19; - - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->r_time_flags = 0; - - range->min_retry = 1; - range->max_retry = 255; - - range->min_r_time = 0; - range->max_r_time = 0; -#endif - -#if WIRELESS_EXT > 17 - range->enc_capa = IW_ENC_CAPA_WPA; - range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; - range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; -#ifdef BCMWPA2 - range->enc_capa |= IW_ENC_CAPA_WPA2; -#endif - - - IW_EVENT_CAPA_SET_KERNEL(range->event_capa); - - IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWAP); - IW_EVENT_CAPA_SET(range->event_capa, SIOCGIWSCAN); - IW_EVENT_CAPA_SET(range->event_capa, IWEVTXDROP); - IW_EVENT_CAPA_SET(range->event_capa, IWEVMICHAELMICFAILURE); -#ifdef BCMWPA2 - IW_EVENT_CAPA_SET(range->event_capa, IWEVPMKIDCAND); -#endif -#endif - - kfree(channels); - - return 0; -} - -static int -rssi_to_qual(int rssi) -{ - if (rssi <= WL_IW_RSSI_NO_SIGNAL) - return 0; - else if (rssi <= WL_IW_RSSI_VERY_LOW) - return 1; - else if (rssi <= WL_IW_RSSI_LOW) - return 2; - else if (rssi <= WL_IW_RSSI_GOOD) - return 3; - else if (rssi <= WL_IW_RSSI_VERY_GOOD) - return 4; - else - return 5; -} - -static int -wl_iw_set_spy( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - struct sockaddr *addr = (struct sockaddr *) extra; - int i; - - WL_TRACE(("%s: SIOCSIWSPY\n", dev->name)); - - if (!extra) - return -EINVAL; - - iw->spy_num = MIN(ARRAYSIZE(iw->spy_addr), dwrq->length); - for (i = 0; i < iw->spy_num; i++) - memcpy(&iw->spy_addr[i], addr[i].sa_data, ETHER_ADDR_LEN); - memset(iw->spy_qual, 0, sizeof(iw->spy_qual)); - - return 0; -} - -static int -wl_iw_get_spy( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - struct sockaddr *addr = (struct sockaddr *) extra; - struct iw_quality *qual = (struct iw_quality *) &addr[iw->spy_num]; - int i; - - WL_TRACE(("%s: SIOCGIWSPY\n", dev->name)); - - if (!extra) - return -EINVAL; - - dwrq->length = iw->spy_num; - for (i = 0; i < iw->spy_num; i++) { - memcpy(addr[i].sa_data, &iw->spy_addr[i], ETHER_ADDR_LEN); - addr[i].sa_family = AF_UNIX; - memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality)); - iw->spy_qual[i].updated = 0; - } - - return 0; -} - -static int -wl_iw_set_wap( - struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra -) -{ - int error = -EINVAL; - wl_join_params_t join_params; - - WL_TRACE(("%s: SIOCSIWAP\n", dev->name)); - - if (awrq->sa_family != ARPHRD_ETHER) { - WL_ERROR(("Invalid Header...sa_family\n")); - return -EINVAL; - } - - - if (ETHER_ISBCAST(awrq->sa_data) || ETHER_ISNULLADDR(awrq->sa_data)) { - scb_val_t scbval; - - bzero(&scbval, sizeof(scb_val_t)); - - (void) dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); - return 0; - } - - - - memset(&join_params, 0, sizeof(join_params)); - - memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len); - join_params.ssid.SSID_len = htod32(g_ssid.SSID_len); - memcpy(&join_params.params.bssid, awrq->sa_data, ETHER_ADDR_LEN); - - if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &join_params, sizeof(join_params)))) { - WL_ERROR(("Invalid ioctl data.\n")); - return error; - } - - - memset(&g_ssid, 0, sizeof(g_ssid)); - return 0; -} - -static int -wl_iw_get_wap( - struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra -) -{ - WL_TRACE(("%s: SIOCGIWAP\n", dev->name)); - - awrq->sa_family = ARPHRD_ETHER; - memset(awrq->sa_data, 0, ETHER_ADDR_LEN); - - - (void) dev_wlc_ioctl(dev, WLC_GET_BSSID, awrq->sa_data, ETHER_ADDR_LEN); - - return 0; -} - -#if WIRELESS_EXT > 17 -static int -wl_iw_mlme( - struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, - char *extra -) -{ - struct iw_mlme *mlme; - scb_val_t scbval; - int error = -EINVAL; - - WL_TRACE(("%s: SIOCSIWMLME DISASSOC/DEAUTH\n", dev->name)); - - mlme = (struct iw_mlme *)extra; - if (mlme == NULL) { - WL_ERROR(("Invalid ioctl data.\n")); - return error; - } - - scbval.val = mlme->reason_code; - bcopy(&mlme->addr.sa_data, &scbval.ea, ETHER_ADDR_LEN); - - if (mlme->cmd == IW_MLME_DISASSOC) { - scbval.val = htod32(scbval.val); - error = dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval, sizeof(scb_val_t)); - } - else if (mlme->cmd == IW_MLME_DEAUTH) { - scbval.val = htod32(scbval.val); - error = dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, - sizeof(scb_val_t)); - } - else { - WL_ERROR(("Invalid ioctl data.\n")); - return error; - } - - return error; -} -#endif - -static int -wl_iw_get_aplist( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_scan_results_t *list; - struct sockaddr *addr = (struct sockaddr *) extra; - struct iw_quality qual[IW_MAX_AP]; - wl_bss_info_t *bi = NULL; - int error, i; - uint buflen = dwrq->length; - - WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); - - if (!extra) - return -EINVAL; - - - list = kmalloc(buflen, GFP_KERNEL); - if (!list) - return -ENOMEM; - memset(list, 0, buflen); - list->buflen = htod32(buflen); - if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen))) { - WL_ERROR(("%d: Scan results error %d\n", __LINE__, error)); - kfree(list); - return error; - } - list->buflen = dtoh32(list->buflen); - list->version = dtoh32(list->version); - list->count = dtoh32(list->count); - if (list->version != WL_BSS_INFO_VERSION) { - WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \ - __FUNCTION__, list->version)); - kfree(list); - return -EINVAL; - } - - for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; - ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + - buflen)); - - - if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) - continue; - - - memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); - addr[dwrq->length].sa_family = ARPHRD_ETHER; - qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); - qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); - qual[dwrq->length].noise = 0x100 + bi->phy_noise; - - -#if WIRELESS_EXT > 18 - qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; -#else - qual[dwrq->length].updated = 7; -#endif - - dwrq->length++; - } - - kfree(list); - - if (dwrq->length) { - memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); - - dwrq->flags = 1; - } - - return 0; -} - -#ifdef WL_IW_USE_ISCAN -static int -wl_iw_iscan_get_aplist( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_scan_results_t *list; - iscan_buf_t * buf; - iscan_info_t *iscan = g_iscan; - - struct sockaddr *addr = (struct sockaddr *) extra; - struct iw_quality qual[IW_MAX_AP]; - wl_bss_info_t *bi = NULL; - int i; - - WL_TRACE(("%s: SIOCGIWAPLIST\n", dev->name)); - - if (!extra) - return -EINVAL; - - if ((!iscan) || (iscan->sysioc_pid < 0)) { - return wl_iw_get_aplist(dev, info, dwrq, extra); - } - - buf = iscan->list_hdr; - - while (buf) { - list = &((wl_iscan_results_t*)buf->iscan_buf)->results; - if (list->version != WL_BSS_INFO_VERSION) { - WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \ - __FUNCTION__, list->version)); - return -EINVAL; - } - - bi = NULL; - for (i = 0, dwrq->length = 0; i < list->count && dwrq->length < IW_MAX_AP; i++) { - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) - : list->bss_info; - ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + - WLC_IW_ISCAN_MAXLEN)); - - - if (!(dtoh16(bi->capability) & DOT11_CAP_ESS)) - continue; - - - memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETHER_ADDR_LEN); - addr[dwrq->length].sa_family = ARPHRD_ETHER; - qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI)); - qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI); - qual[dwrq->length].noise = 0x100 + bi->phy_noise; - - -#if WIRELESS_EXT > 18 - qual[dwrq->length].updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; -#else - qual[dwrq->length].updated = 7; -#endif - - dwrq->length++; - } - buf = buf->next; - } - if (dwrq->length) { - memcpy(&addr[dwrq->length], qual, sizeof(struct iw_quality) * dwrq->length); - - dwrq->flags = 1; - } - - return 0; -} - -static int -wl_iw_iscan_prep(wl_scan_params_t *params, wlc_ssid_t *ssid) -{ - int err = 0; - - memcpy(¶ms->bssid, ðer_bcast, ETHER_ADDR_LEN); - params->bss_type = DOT11_BSSTYPE_ANY; - params->scan_type = 0; - params->nprobes = -1; - params->active_time = -1; - params->passive_time = -1; - params->home_time = -1; - params->channel_num = 0; - - params->nprobes = htod32(params->nprobes); - params->active_time = htod32(params->active_time); - params->passive_time = htod32(params->passive_time); - params->home_time = htod32(params->home_time); - if (ssid && ssid->SSID_len) - memcpy(¶ms->ssid, ssid, sizeof(wlc_ssid_t)); - - return err; -} - -static int -wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action) -{ - int err = 0; - - iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); - iscan->iscan_ex_params_p->action = htod16(action); - iscan->iscan_ex_params_p->scan_duration = htod16(0); - - WL_SCAN(("%s : nprobes=%d\n", __FUNCTION__, iscan->iscan_ex_params_p->params.nprobes)); - WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time)); - WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time)); - WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time)); - WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type)); - WL_SCAN(("bss_type=%d\n", iscan->iscan_ex_params_p->params.bss_type)); - - - (void) dev_iw_iovar_setbuf(iscan->dev, "iscan", iscan->iscan_ex_params_p, \ - iscan->iscan_ex_param_size, iscan->ioctlbuf, sizeof(iscan->ioctlbuf)); - - return err; -} - -static void -wl_iw_timerfunc(ulong data) -{ - iscan_info_t *iscan = (iscan_info_t *)data; - if (iscan) { - iscan->timer_on = 0; - if (iscan->iscan_state != ISCAN_STATE_IDLE) { - WL_TRACE(("timer trigger\n")); - up(&iscan->sysioc_sem); - } - } -} -static void wl_iw_set_event_mask(struct net_device *dev) -{ - char eventmask[WL_EVENTING_MASK_LEN]; - char iovbuf[WL_EVENTING_MASK_LEN + 12]; - - dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf)); - bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN); - setbit(eventmask, WLC_E_SCAN_COMPLETE); - dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN, - iovbuf, sizeof(iovbuf)); -} - -static uint32 -wl_iw_iscan_get(iscan_info_t *iscan) -{ - iscan_buf_t * buf; - iscan_buf_t * ptr; - wl_iscan_results_t * list_buf; - wl_iscan_results_t list; - wl_scan_results_t *results; - uint32 status; - - - MUTEX_LOCK_WL_SCAN_SET(); - if (iscan->list_cur) { - buf = iscan->list_cur; - iscan->list_cur = buf->next; - } - else { - buf = kmalloc(sizeof(iscan_buf_t), GFP_KERNEL); - if (!buf) { - WL_ERROR(("%s can't alloc iscan_buf_t : going to abort currect iscan\n", \ - __FUNCTION__)); - MUTEX_UNLOCK_WL_SCAN_SET(); - return WL_SCAN_RESULTS_NO_MEM; - } - buf->next = NULL; - if (!iscan->list_hdr) - iscan->list_hdr = buf; - else { - ptr = iscan->list_hdr; - while (ptr->next) { - ptr = ptr->next; - } - ptr->next = buf; - } - } - memset(buf->iscan_buf, 0, WLC_IW_ISCAN_MAXLEN); - list_buf = (wl_iscan_results_t*)buf->iscan_buf; - results = &list_buf->results; - results->buflen = WL_ISCAN_RESULTS_FIXED_SIZE; - results->version = 0; - results->count = 0; - - memset(&list, 0, sizeof(list)); - list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN); - (void) dev_iw_iovar_getbuf( - iscan->dev, - "iscanresults", - &list, - WL_ISCAN_RESULTS_FIXED_SIZE, - buf->iscan_buf, - WLC_IW_ISCAN_MAXLEN); - results->buflen = dtoh32(results->buflen); - results->version = dtoh32(results->version); - results->count = dtoh32(results->count); - WL_TRACE(("results->count = %d\n", results->count)); - - WL_TRACE(("results->buflen = %d\n", results->buflen)); - status = dtoh32(list_buf->status); - MUTEX_UNLOCK_WL_SCAN_SET(); - return status; -} - -static void wl_iw_force_specific_scan(iscan_info_t *iscan) -{ - WL_TRACE(("%s force Specific SCAN for %s\n", __FUNCTION__, g_specific_ssid.SSID)); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_lock(); -#endif - - (void) dev_wlc_ioctl(iscan->dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_unlock(); -#endif -} -static void wl_iw_send_scan_complete(iscan_info_t *iscan) -{ -#ifndef SANDGATE2G - union iwreq_data wrqu; - - memset(&wrqu, 0, sizeof(wrqu)); - - - wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL); -#if !defined(CSCAN) - if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) - g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_READY; -#endif - WL_TRACE(("Send Event ISCAN complete\n")); -#endif -} -static int -_iscan_sysioc_thread(void *data) -{ - uint32 status; - iscan_info_t *iscan = (iscan_info_t *)data; - static bool iscan_pass_abort = FALSE; - DAEMONIZE("iscan_sysioc"); - - status = WL_SCAN_RESULTS_PARTIAL; - while (down_interruptible(&iscan->sysioc_sem) == 0) { - -#if defined(SOFTAP) - - if (ap_cfg_running) { - WL_TRACE(("%s skipping SCAN ops in AP mode !!!\n", __FUNCTION__)); - continue; - } -#endif - if (iscan->timer_on) { - del_timer(&iscan->timer); - iscan->timer_on = 0; - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_lock(); -#endif - status = wl_iw_iscan_get(iscan); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_unlock(); -#endif - if (g_scan_specified_ssid && (iscan_pass_abort == TRUE)) { - WL_TRACE(("%s Get results from specific scan status=%d\n", __FUNCTION__, status)); - wl_iw_send_scan_complete(iscan); - iscan_pass_abort = FALSE; - status = -1; - } - - switch (status) { - case WL_SCAN_RESULTS_PARTIAL: - WL_TRACE(("iscanresults incomplete\n")); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_lock(); -#endif - - wl_iw_iscan(iscan, NULL, WL_SCAN_ACTION_CONTINUE); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_unlock(); -#endif - - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - iscan->timer_on = 1; - break; - case WL_SCAN_RESULTS_SUCCESS: - WL_TRACE(("iscanresults complete\n")); - iscan->iscan_state = ISCAN_STATE_IDLE; - wl_iw_send_scan_complete(iscan); - break; - case WL_SCAN_RESULTS_PENDING: - WL_TRACE(("iscanresults pending\n")); - - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - iscan->timer_on = 1; - break; - case WL_SCAN_RESULTS_ABORTED: - WL_TRACE(("iscanresults aborted\n")); - iscan->iscan_state = ISCAN_STATE_IDLE; - if (g_scan_specified_ssid == 0) - wl_iw_send_scan_complete(iscan); - else { - iscan_pass_abort = TRUE; - wl_iw_force_specific_scan(iscan); - } - break; - case WL_SCAN_RESULTS_NO_MEM: - WL_TRACE(("iscanresults can't alloc memory: skip\n")); - iscan->iscan_state = ISCAN_STATE_IDLE; - break; - default: - WL_TRACE(("iscanresults returned unknown status %d\n", status)); - break; - } - } - - if (iscan->timer_on) { - del_timer(&iscan->timer); - iscan->timer_on = 0; - } - complete_and_exit(&iscan->sysioc_exited, 0); -} -#endif - -#if !defined(CSCAN) - -static void -wl_iw_set_ss_cache_timer_flag(void) -{ - g_ss_cache_ctrl.m_timer_expired = 1; - WL_TRACE(("%s called\n", __FUNCTION__)); -} - -static int -wl_iw_init_ss_cache_ctrl(void) -{ - WL_TRACE(("%s :\n", __FUNCTION__)); - g_ss_cache_ctrl.m_prev_scan_mode = 0; - g_ss_cache_ctrl.m_cons_br_scan_cnt = 0; - g_ss_cache_ctrl.m_cache_head = NULL; - g_ss_cache_ctrl.m_link_down = 0; - g_ss_cache_ctrl.m_timer_expired = 0; - memset(g_ss_cache_ctrl.m_active_bssid, 0, ETHER_ADDR_LEN); - - g_ss_cache_ctrl.m_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL); - if (!g_ss_cache_ctrl.m_timer) { - return -ENOMEM; - } - g_ss_cache_ctrl.m_timer->function = (void *)wl_iw_set_ss_cache_timer_flag; - init_timer(g_ss_cache_ctrl.m_timer); - - return 0; -} - - - -static void -wl_iw_free_ss_cache(void) -{ - wl_iw_ss_cache_t *node, *cur; - wl_iw_ss_cache_t **spec_scan_head; - - WL_TRACE(("%s called\n", __FUNCTION__)); - - MUTEX_LOCK_WL_SCAN_SET(); - spec_scan_head = &g_ss_cache_ctrl.m_cache_head; - node = *spec_scan_head; - - for (;node;) { - WL_TRACE(("%s : SSID - %s\n", __FUNCTION__, node->bss_info->SSID)); - cur = node; - node = cur->next; - kfree(cur); - } - *spec_scan_head = NULL; - MUTEX_UNLOCK_WL_SCAN_SET(); -} - - - -static int -wl_iw_run_ss_cache_timer(int kick_off) -{ - struct timer_list **timer; - - timer = &g_ss_cache_ctrl.m_timer; - - if (*timer) { - if (kick_off) { - (*timer)->expires = jiffies + 30000 * HZ / 1000; - add_timer(*timer); - WL_TRACE(("%s : timer starts \n", __FUNCTION__)); - } else { - del_timer_sync(*timer); - WL_TRACE(("%s : timer stops \n", __FUNCTION__)); - } - } - - return 0; -} - - -void -wl_iw_release_ss_cache_ctrl(void) -{ - WL_TRACE(("%s :\n", __FUNCTION__)); - wl_iw_free_ss_cache(); - wl_iw_run_ss_cache_timer(0); - if (g_ss_cache_ctrl.m_timer) { - kfree(g_ss_cache_ctrl.m_timer); - } -} - - - -static void -wl_iw_reset_ss_cache(void) -{ - wl_iw_ss_cache_t *node, *prev, *cur; - wl_iw_ss_cache_t **spec_scan_head; - - MUTEX_LOCK_WL_SCAN_SET(); - spec_scan_head = &g_ss_cache_ctrl.m_cache_head; - node = *spec_scan_head; - prev = node; - - for (;node;) { - WL_TRACE(("%s : node SSID %s \n", __FUNCTION__, node->bss_info->SSID)); - if (!node->dirty) { - cur = node; - if (cur == *spec_scan_head) { - *spec_scan_head = cur->next; - prev = *spec_scan_head; - } - else { - prev->next = cur->next; - } - node = cur->next; - - WL_TRACE(("%s : Del node : SSID %s\n", __FUNCTION__, cur->bss_info->SSID)); - kfree(cur); - continue; - } - - node->dirty = 0; - prev = node; - node = node->next; - } - MUTEX_UNLOCK_WL_SCAN_SET(); -} - - -static int -wl_iw_add_bss_to_ss_cache(wl_scan_results_t *ss_list) -{ - - wl_iw_ss_cache_t *node, *prev, *leaf; - wl_iw_ss_cache_t **spec_scan_head; - wl_bss_info_t *bi = NULL; - int i; - - - if (!ss_list->count) { - return 0; - } - - MUTEX_LOCK_WL_SCAN_SET(); - spec_scan_head = &g_ss_cache_ctrl.m_cache_head; - for (i = 0; i < ss_list->count; i++) { - - node = *spec_scan_head; - prev = node; - - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info; - - WL_TRACE(("%s : find %d with specific SSID %s\n", __FUNCTION__, i, bi->SSID)); - for (;node;) { - if (!memcmp(&node->bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) { - - WL_TRACE(("dirty marked : SSID %s\n", bi->SSID)); - node->dirty = 1; - break; - } - prev = node; - node = node->next; - } - - if (node) { - continue; - } - leaf = kmalloc(bi->length + WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN, GFP_KERNEL); - if (!leaf) { - MUTEX_UNLOCK_WL_SCAN_SET(); - return -ENOMEM; - } - - memcpy(leaf->bss_info, bi, bi->length); - leaf->next = NULL; - leaf->dirty = 1; - leaf->count = 1; - leaf->version = ss_list->version; - - if (!prev) { - *spec_scan_head = leaf; - } - else { - prev->next = leaf; - } - } - MUTEX_UNLOCK_WL_SCAN_SET(); - return 0; - -} - - -static int -wl_iw_merge_scan_cache(struct iw_request_info *info, char *extra, uint buflen_from_user, -__u16 *merged_len) -{ - wl_iw_ss_cache_t *node; - wl_scan_results_t *list_merge; - - MUTEX_LOCK_WL_SCAN_SET(); - node = g_ss_cache_ctrl.m_cache_head; - for (;node;) { - list_merge = (wl_scan_results_t *)node; - WL_TRACE(("%s: Cached Specific APs list=%d\n", __FUNCTION__, list_merge->count)); - if (buflen_from_user - *merged_len > 0) { - *merged_len += (__u16) wl_iw_get_scan_prep(list_merge, info, - extra + *merged_len, buflen_from_user - *merged_len); - } - else { - WL_TRACE(("%s: exit with break\n", __FUNCTION__)); - break; - } - node = node->next; - } - MUTEX_UNLOCK_WL_SCAN_SET(); - return 0; -} - - -static int -wl_iw_delete_bss_from_ss_cache(void *addr) -{ - - wl_iw_ss_cache_t *node, *prev; - wl_iw_ss_cache_t **spec_scan_head; - - MUTEX_LOCK_WL_SCAN_SET(); - spec_scan_head = &g_ss_cache_ctrl.m_cache_head; - node = *spec_scan_head; - prev = node; - for (;node;) { - if (!memcmp(&node->bss_info->BSSID, addr, ETHER_ADDR_LEN)) { - if (node == *spec_scan_head) { - *spec_scan_head = node->next; - } - else { - prev->next = node->next; - } - - WL_TRACE(("%s : Del node : %s\n", __FUNCTION__, node->bss_info->SSID)); - kfree(node); - break; - } - - prev = node; - node = node->next; - } - - memset(addr, 0, ETHER_ADDR_LEN); - MUTEX_UNLOCK_WL_SCAN_SET(); - return 0; - -} - -#endif - - -static int -wl_iw_set_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int error; - WL_TRACE(("\n:%s dev:%s: SIOCSIWSCAN : SCAN\n", __FUNCTION__, dev->name)); - - -#if defined(CSCAN) - WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__)); - return -EINVAL; -#endif - -#if defined(SOFTAP) - - if (ap_cfg_running) { - WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); - return 0; - } -#endif - - - if (g_onoff == G_WLAN_SET_OFF) - return 0; - - - memset(&g_specific_ssid, 0, sizeof(g_specific_ssid)); -#ifndef WL_IW_USE_ISCAN - - g_scan_specified_ssid = 0; -#endif - -#if WIRELESS_EXT > 17 - - if (wrqu->data.length == sizeof(struct iw_scan_req)) { - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct iw_scan_req *req = (struct iw_scan_req *)extra; - if (g_first_broadcast_scan != BROADCAST_SCAN_FIRST_RESULT_CONSUMED) { - - WL_TRACE(("%s Ignoring SC %s first BC is not done = %d\n", \ - __FUNCTION__, req->essid, \ - g_first_broadcast_scan)); - return -EBUSY; - } - if (g_scan_specified_ssid) { - WL_TRACE(("%s Specific SCAN is not done ignore scan for = %s \n", \ - __FUNCTION__, req->essid)); - - return -EBUSY; - } - else { - g_specific_ssid.SSID_len = MIN(sizeof(g_specific_ssid.SSID), \ - req->essid_len); - memcpy(g_specific_ssid.SSID, req->essid, g_specific_ssid.SSID_len); - g_specific_ssid.SSID_len = htod32(g_specific_ssid.SSID_len); - g_scan_specified_ssid = 1; - WL_TRACE(("### Specific scan ssid=%s len=%d\n", \ - g_specific_ssid.SSID, g_specific_ssid.SSID_len)); - } - } - } -#endif - - if ((error = dev_wlc_ioctl(dev, WLC_SCAN, &g_specific_ssid, sizeof(g_specific_ssid)))) { - WL_TRACE(("#### Set SCAN for %s failed with %d\n", g_specific_ssid.SSID, error)); - - g_scan_specified_ssid = 0; - return -EBUSY; - } - - return 0; -} - -#ifdef WL_IW_USE_ISCAN -int -wl_iw_iscan_set_scan_broadcast_prep(struct net_device *dev, uint flag) -{ - wlc_ssid_t ssid; - iscan_info_t *iscan = g_iscan; - -#if !defined(CSCAN) - - if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_IDLE) { - g_first_broadcast_scan = BROADCAST_SCAN_FIRST_STARTED; - WL_TRACE(("%s: First Brodcast scan was forced\n", __FUNCTION__)); - } - else if (g_first_broadcast_scan == BROADCAST_SCAN_FIRST_STARTED) { - WL_TRACE(("%s: ignore ISCAN request first BS is not done yet\n", __FUNCTION__)); - return 0; - } -#endif - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - if (flag) - rtnl_lock(); -#endif - - dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &iscan->scan_flag, sizeof(iscan->scan_flag)); - wl_iw_set_event_mask(dev); - - WL_TRACE(("+++: Set Broadcast ISCAN\n")); - - memset(&ssid, 0, sizeof(ssid)); - - iscan->list_cur = iscan->list_hdr; - iscan->iscan_state = ISCAN_STATE_SCANING; - - memset(&iscan->iscan_ex_params_p->params, 0, iscan->iscan_ex_param_size); - wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, &ssid); - wl_iw_iscan(iscan, &ssid, WL_SCAN_ACTION_START); - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - if (flag) - rtnl_unlock(); -#endif - - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - - iscan->timer_on = 1; - - return 0; -} -static int -wl_iw_iscan_set_scan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - wlc_ssid_t ssid; - iscan_info_t *iscan = g_iscan; - - WL_TRACE(("%s: SIOCSIWSCAN : ISCAN\n", dev->name)); - -#if defined(CSCAN) - WL_ERROR(("%s: Scan from SIOCGIWSCAN not supported\n", __FUNCTION__)); - return -EINVAL; -#endif - - -#if defined(SOFTAP) - if (ap_cfg_running) { - WL_TRACE(("\n>%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); - return 0; - } -#endif - - if (g_onoff == G_WLAN_SET_OFF) { - WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); - return 0; - } - - - if ((!iscan) || (iscan->sysioc_pid < 0)) { - WL_TRACE(("%s use backup if iscan thread is not successful\n", \ - __FUNCTION__)); - return wl_iw_set_scan(dev, info, wrqu, extra); - } - - if (g_scan_specified_ssid) { - WL_TRACE(("%s Specific SCAN already running ignoring BC scan\n", \ - __FUNCTION__)); - return EBUSY; - } - - - memset(&ssid, 0, sizeof(ssid)); - -#if WIRELESS_EXT > 17 - - if (wrqu->data.length == sizeof(struct iw_scan_req)) { - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - int as = 0; - struct iw_scan_req *req = (struct iw_scan_req *)extra; -#if !defined(CSCAN) - if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_CONSUMED) { - - WL_TRACE(("%s First ISCAN in progress : ignoring SC = %s\n", \ - __FUNCTION__, req->essid)); - return -EBUSY; - } -#endif - ssid.SSID_len = MIN(sizeof(ssid.SSID), req->essid_len); - memcpy(ssid.SSID, req->essid, ssid.SSID_len); - ssid.SSID_len = htod32(ssid.SSID_len); - dev_wlc_ioctl(dev, WLC_SET_PASSIVE_SCAN, &as, sizeof(as)); - wl_iw_set_event_mask(dev); - return wl_iw_set_scan(dev, info, wrqu, extra); - } - else { - g_scan_specified_ssid = 0; - - if (iscan->iscan_state == ISCAN_STATE_SCANING) { - WL_TRACE(("%s ISCAN already in progress \n", __FUNCTION__)); - return 0; - } - } - } -#endif - - wl_iw_iscan_set_scan_broadcast_prep(dev, 0); - - return 0; -} -#endif - -#if WIRELESS_EXT > 17 -static bool -ie_is_wpa_ie(uint8 **wpaie, uint8 **tlvs, int *tlvs_len) -{ - - - uint8 *ie = *wpaie; - - - if ((ie[1] >= 6) && - !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x01"), 4)) { - return TRUE; - } - - - ie += ie[1] + 2; - - *tlvs_len -= (int)(ie - *tlvs); - - *tlvs = ie; - return FALSE; -} - -static bool -ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len) -{ - - - uint8 *ie = *wpsie; - - - if ((ie[1] >= 4) && - !bcmp((const void *)&ie[2], (const void *)(WPA_OUI "\x04"), 4)) { - return TRUE; - } - - - ie += ie[1] + 2; - - *tlvs_len -= (int)(ie - *tlvs); - - *tlvs = ie; - return FALSE; -} -#endif - -static inline int _wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, - size_t len, int uppercase) -{ - size_t i; - char *pos = buf, *end = buf + buf_size; - int ret; - if (buf_size == 0) - return 0; - for (i = 0; i < len; i++) { - ret = snprintf(pos, end - pos, uppercase ? "%02X" : "%02x", - data[i]); - if (ret < 0 || ret >= end - pos) { - end[-1] = '\0'; - return pos - buf; - } - pos += ret; - } - end[-1] = '\0'; - return pos - buf; -} - - -int wpa_snprintf_hex(char *buf, size_t buf_size, const u8 *data, size_t len) -{ - return _wpa_snprintf_hex(buf, buf_size, data, len, 0); -} - -static int -wl_iw_handle_scanresults_ies(char **event_p, char *end, - struct iw_request_info *info, wl_bss_info_t *bi) -{ -#if WIRELESS_EXT > 17 - struct iw_event iwe; - char *event; - char *buf; - int custom_event_len; - - event = *event_p; - if (bi->ie_length) { - - bcm_tlv_t *ie; - uint8 *ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - int ptr_len = bi->ie_length; - -#ifdef BCMWPA2 - if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_RSN_ID))) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - } - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); -#endif - - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { - - if (ie_is_wps_ie(((uint8 **)&ie), &ptr, &ptr_len)) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - break; - } - } - - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - ptr_len = bi->ie_length; - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { - if (ie_is_wpa_ie(((uint8 **)&ie), &ptr, &ptr_len)) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); - break; - } - } - - ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); - ptr_len = bi->ie_length; - - while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WAPI_ID))) { - WL_TRACE(("%s: found a WAPI IE...\n", __FUNCTION__)); -#ifdef WAPI_IE_USE_GENIE - iwe.cmd = IWEVGENIE; - iwe.u.data.length = ie->len + 2; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); -#else - iwe.cmd = IWEVCUSTOM; - custom_event_len = strlen("wapi_ie=") + 2*(ie->len + 2); - iwe.u.data.length = custom_event_len; - - buf = kmalloc(custom_event_len+1, GFP_KERNEL); - if (buf == NULL) - { - WL_ERROR(("malloc(%d) returned NULL...\n", custom_event_len)); - break; - } - - memcpy(buf, "wapi_ie=", 8); - wpa_snprintf_hex(buf + 8, 2+1, &(ie->id), 1); - wpa_snprintf_hex(buf + 10, 2+1, &(ie->len), 1); - wpa_snprintf_hex(buf + 12, 2*ie->len+1, ie->data, ie->len); - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, buf); -#endif - break; - } - *event_p = event; - } -#endif - - return 0; -} - -static uint -wl_iw_get_scan_prep( - wl_scan_results_t *list, - struct iw_request_info *info, - char *extra, - short max_size) -{ - int i, j; - struct iw_event iwe; - wl_bss_info_t *bi = NULL; - char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value; - int ret = 0; - - ASSERT(list); - - - - for (i = 0; i < list->count && i < IW_MAX_AP; i++) - { - if (list->version != WL_BSS_INFO_VERSION) { - WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \ - __FUNCTION__, list->version)); - return ret; - } - - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; - - WL_TRACE(("%s : %s\n", __FUNCTION__, bi->SSID)); - - - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); - - iwe.u.data.length = dtoh32(bi->SSID_len); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); - - - if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { - iwe.cmd = SIOCGIWMODE; - if (dtoh16(bi->capability) & DOT11_CAP_ESS) - iwe.u.mode = IW_MODE_INFRA; - else - iwe.u.mode = IW_MODE_ADHOC; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); - } - - - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), - CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); - iwe.u.freq.e = 6; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); - - - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); - iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); - iwe.u.qual.noise = 0x100 + bi->phy_noise; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); - - - wl_iw_handle_scanresults_ies(&event, end, info, bi); - - - iwe.cmd = SIOCGIWENCODE; - if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); - - - if (bi->rateset.count) { - if (((event -extra) + IW_EV_LCP_LEN) <= (uintptr)end) { - value = event + IW_EV_LCP_LEN; - iwe.cmd = SIOCGIWRATE; - - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { - iwe.u.bitrate.value = - (bi->rateset.rates[j] & 0x7f) * 500000; - value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, - IW_EV_PARAM_LEN); - } - event = value; - } - } - } - - if ((ret = (event - extra)) < 0) { - WL_ERROR(("==> Wrong size\n")); - ret = 0; - } - WL_TRACE(("%s: size=%d bytes prepared \n", __FUNCTION__, (unsigned int)(event - extra))); - return (uint)ret; -} - -static int -wl_iw_get_scan( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - channel_info_t ci; - wl_scan_results_t *list_merge; - wl_scan_results_t *list = (wl_scan_results_t *) g_scan; - int error; - uint buflen_from_user = dwrq->length; - uint len = G_SCAN_RESULTS; - __u16 len_ret = 0; -#if !defined(CSCAN) - __u16 merged_len = 0; -#endif -#if defined(WL_IW_USE_ISCAN) - iscan_info_t *iscan = g_iscan; - iscan_buf_t * p_buf; -#if !defined(CSCAN) - uint32 counter = 0; -#endif -#endif - - WL_TRACE(("%s: buflen_from_user %d: \n", dev->name, buflen_from_user)); - - if (!extra) { - WL_TRACE(("%s: wl_iw_get_scan return -EINVAL\n", dev->name)); - return -EINVAL; - } - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) - return error; - ci.scan_channel = dtoh32(ci.scan_channel); - if (ci.scan_channel) - return -EAGAIN; - -#if !defined(CSCAN) - if (g_ss_cache_ctrl.m_timer_expired) { - wl_iw_free_ss_cache(); - g_ss_cache_ctrl.m_timer_expired ^= 1; - } - if ((!g_scan_specified_ssid && g_ss_cache_ctrl.m_prev_scan_mode) || - g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) { - g_ss_cache_ctrl.m_cons_br_scan_cnt = 0; - - wl_iw_reset_ss_cache(); - } - g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid; - if (g_scan_specified_ssid) { - g_ss_cache_ctrl.m_cons_br_scan_cnt = 0; - } - else { - g_ss_cache_ctrl.m_cons_br_scan_cnt++; - } -#endif - - - - if (g_scan_specified_ssid) { - - list = kmalloc(len, GFP_KERNEL); - if (!list) { - WL_TRACE(("%s: wl_iw_get_scan return -ENOMEM\n", dev->name)); - g_scan_specified_ssid = 0; - return -ENOMEM; - } - } - - memset(list, 0, len); - list->buflen = htod32(len); - if ((error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len))) { - WL_TRACE(("%s: %s : Scan_results ERROR %d\n", dev->name, __FUNCTION__, len)); - dwrq->length = len; - if (g_scan_specified_ssid) - kfree(list); - return 0; - } - list->buflen = dtoh32(list->buflen); - list->version = dtoh32(list->version); - list->count = dtoh32(list->count); - - - if (list->version != WL_BSS_INFO_VERSION) { - WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \ - __FUNCTION__, list->version)); - if (g_scan_specified_ssid) { - g_scan_specified_ssid = 0; - kfree(list); - } - return -EINVAL; - } - -#if !defined(CSCAN) - if (g_scan_specified_ssid) { - - wl_iw_add_bss_to_ss_cache(list); - kfree(list); - } -#endif - -#if !defined(CSCAN) - MUTEX_LOCK_WL_SCAN_SET(); -#if defined(WL_IW_USE_ISCAN) - if (g_scan_specified_ssid) - WL_TRACE(("%s: Specified scan APs from scan=%d\n", __FUNCTION__, list->count)); - p_buf = iscan->list_hdr; - - while (p_buf != iscan->list_cur) { - list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; - WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); - counter += list_merge->count; - if (list_merge->count > 0) - len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, - extra+len_ret, buflen_from_user -len_ret); - p_buf = p_buf->next; - } - WL_TRACE(("%s merged with total Bcast APs=%d\n", __FUNCTION__, counter)); -#else - list_merge = (wl_scan_results_t *) g_scan; - len_ret = (__u16) wl_iw_get_scan_prep(list_merge, info, extra, buflen_from_user); -#endif - MUTEX_UNLOCK_WL_SCAN_SET(); - if (g_ss_cache_ctrl.m_link_down) { - - wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid); - } - - wl_iw_merge_scan_cache(info, extra+len_ret, buflen_from_user-len_ret, &merged_len); - len_ret += merged_len; - wl_iw_run_ss_cache_timer(0); - wl_iw_run_ss_cache_timer(1); -#else - - - if (g_scan_specified_ssid) { - WL_TRACE(("%s: Specified scan APs in the list =%d\n", __FUNCTION__, list->count)); - len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user); - kfree(list); - -#if defined(WL_IW_USE_ISCAN) - p_buf = iscan->list_hdr; - - while (p_buf != iscan->list_cur) { - list_merge = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; - WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); - if (list_merge->count > 0) - len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, - extra+len_ret, buflen_from_user -len_ret); - p_buf = p_buf->next; - } -#else - list_merge = (wl_scan_results_t *) g_scan; - WL_TRACE(("%s: Bcast APs list=%d\n", __FUNCTION__, list_merge->count)); - if (list_merge->count > 0) - len_ret += (__u16) wl_iw_get_scan_prep(list_merge, info, extra+len_ret, - buflen_from_user -len_ret); -#endif - } - else { - list = (wl_scan_results_t *) g_scan; - len_ret = (__u16) wl_iw_get_scan_prep(list, info, extra, buflen_from_user); - } -#endif - -#if defined(WL_IW_USE_ISCAN) - - g_scan_specified_ssid = 0; -#endif - - if ((len_ret + WE_ADD_EVENT_FIX) < buflen_from_user) - len = len_ret; - - dwrq->length = len; - dwrq->flags = 0; - - WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, list->count)); - return 0; -} - -#if defined(WL_IW_USE_ISCAN) -static int -wl_iw_iscan_get_scan( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_scan_results_t *list; - struct iw_event iwe; - wl_bss_info_t *bi = NULL; - int ii, j; - int apcnt; - char *event = extra, *end = extra + dwrq->length, *value; - iscan_info_t *iscan = g_iscan; - iscan_buf_t * p_buf; - uint32 counter = 0; -#if !defined(CSCAN) - __u16 merged_len = 0; - uint buflen_from_user = dwrq->length; -#endif - - WL_TRACE(("%s %s buflen_from_user %d:\n", dev->name, __FUNCTION__, dwrq->length)); - -#if defined(SOFTAP) - if (ap_cfg_running) { - WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); - return -EINVAL; - } -#endif - - if (!extra) { - WL_TRACE(("%s: INVALID SIOCGIWSCAN GET bad parameter\n", dev->name)); - return -EINVAL; - } - -#if !defined(CSCAN) - if (g_first_broadcast_scan < BROADCAST_SCAN_FIRST_RESULT_READY) { - WL_TRACE(("%s %s: first ISCAN results are NOT ready yet \n", \ - dev->name, __FUNCTION__)); - return -EAGAIN; - } -#endif - - if ((!iscan) || (iscan->sysioc_pid < 0)) { - WL_TRACE(("%ssysioc_pid\n", __FUNCTION__)); - return wl_iw_get_scan(dev, info, dwrq, extra); - } - - - -#if !defined(CSCAN) - if (g_ss_cache_ctrl.m_timer_expired) { - wl_iw_free_ss_cache(); - g_ss_cache_ctrl.m_timer_expired ^= 1; - } - if (g_scan_specified_ssid) { - return wl_iw_get_scan(dev, info, dwrq, extra); - } - else { - if (g_ss_cache_ctrl.m_link_down) { - - wl_iw_delete_bss_from_ss_cache(g_ss_cache_ctrl.m_active_bssid); - } - if (g_ss_cache_ctrl.m_prev_scan_mode || g_ss_cache_ctrl.m_cons_br_scan_cnt > 4) { - g_ss_cache_ctrl.m_cons_br_scan_cnt = 0; - - wl_iw_reset_ss_cache(); - } - g_ss_cache_ctrl.m_prev_scan_mode = g_scan_specified_ssid; - g_ss_cache_ctrl.m_cons_br_scan_cnt++; - } -#endif - - WL_TRACE(("%s: SIOCGIWSCAN GET broadcast results\n", dev->name)); - apcnt = 0; - p_buf = iscan->list_hdr; - - while (p_buf != iscan->list_cur) { - list = &((wl_iscan_results_t*)p_buf->iscan_buf)->results; - - counter += list->count; - - if (list->version != WL_BSS_INFO_VERSION) { - WL_ERROR(("%s : list->version %d != WL_BSS_INFO_VERSION\n", \ - __FUNCTION__, list->version)); - return -EINVAL; - } - - bi = NULL; - for (ii = 0; ii < list->count && apcnt < IW_MAX_AP; apcnt++, ii++) { - bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : list->bss_info; - ASSERT(((uintptr)bi + dtoh32(bi->length)) <= ((uintptr)list + - WLC_IW_ISCAN_MAXLEN)); - - - if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN + - IW_EV_QUAL_LEN >= end) - return -E2BIG; - - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, &bi->BSSID, ETHER_ADDR_LEN); - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_ADDR_LEN); - - - iwe.u.data.length = dtoh32(bi->SSID_len); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID); - - - if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) { - iwe.cmd = SIOCGIWMODE; - if (dtoh16(bi->capability) & DOT11_CAP_ESS) - iwe.u.mode = IW_MODE_INFRA; - else - iwe.u.mode = IW_MODE_ADHOC; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_UINT_LEN); - } - - - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec), - CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL ? - WF_CHAN_FACTOR_2_4_G : WF_CHAN_FACTOR_5_G); - iwe.u.freq.e = 6; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_FREQ_LEN); - - - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI)); - iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI); - iwe.u.qual.noise = 0x100 + bi->phy_noise; - event = IWE_STREAM_ADD_EVENT(info, event, end, &iwe, IW_EV_QUAL_LEN); - - - wl_iw_handle_scanresults_ies(&event, end, info, bi); - - - iwe.cmd = SIOCGIWENCODE; - if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)event); - - - if (bi->rateset.count) { - if (event + IW_MAX_BITRATES*IW_EV_PARAM_LEN >= end) - return -E2BIG; - - value = event + IW_EV_LCP_LEN; - iwe.cmd = SIOCGIWRATE; - - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - for (j = 0; j < bi->rateset.count && j < IW_MAX_BITRATES; j++) { - iwe.u.bitrate.value = (bi->rateset.rates[j] & 0x7f) * 500000; - value = IWE_STREAM_ADD_VALUE(info, event, value, end, &iwe, - IW_EV_PARAM_LEN); - } - event = value; - } - } - p_buf = p_buf->next; - } - - dwrq->length = event - extra; - dwrq->flags = 0; - -#if !defined(CSCAN) - - wl_iw_merge_scan_cache(info, event, buflen_from_user - dwrq->length, &merged_len); - dwrq->length += merged_len; - wl_iw_run_ss_cache_timer(0); - wl_iw_run_ss_cache_timer(1); - - g_first_broadcast_scan = BROADCAST_SCAN_FIRST_RESULT_CONSUMED; -#endif - - WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter)); - - - if (!dwrq->length) - return -EAGAIN; - - return 0; -} -#endif - -static int -wl_iw_set_essid( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - int error; - - WL_TRACE(("%s: SIOCSIWESSID\n", dev->name)); - - - - memset(&g_ssid, 0, sizeof(g_ssid)); - - CHECK_EXTRA_FOR_NULL(extra); - - if (dwrq->length && extra) { -#if WIRELESS_EXT > 20 - g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length); -#else - g_ssid.SSID_len = MIN(sizeof(g_ssid.SSID), dwrq->length-1); -#endif - memcpy(g_ssid.SSID, extra, g_ssid.SSID_len); - } else { - - g_ssid.SSID_len = 0; - } - g_ssid.SSID_len = htod32(g_ssid.SSID_len); - if ((error = dev_wlc_ioctl(dev, WLC_SET_SSID, &g_ssid, sizeof(g_ssid)))) - return error; - - if (g_ssid.SSID_len) { - WL_TRACE(("%s: join SSID=%s\n", __FUNCTION__, g_ssid.SSID)); - } - return 0; -} - -static int -wl_iw_get_essid( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wlc_ssid_t ssid; - int error; - - WL_TRACE(("%s: SIOCGIWESSID\n", dev->name)); - - if (!extra) - return -EINVAL; - - if ((error = dev_wlc_ioctl(dev, WLC_GET_SSID, &ssid, sizeof(ssid)))) { - WL_ERROR(("Error getting the SSID\n")); - return error; - } - - ssid.SSID_len = dtoh32(ssid.SSID_len); - - - memcpy(extra, ssid.SSID, ssid.SSID_len); - - dwrq->length = ssid.SSID_len; - - dwrq->flags = 1; - - return 0; -} - -static int -wl_iw_set_nick( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - - WL_TRACE(("%s: SIOCSIWNICKN\n", dev->name)); - - if (!extra) - return -EINVAL; - - - if (dwrq->length > sizeof(iw->nickname)) - return -E2BIG; - - memcpy(iw->nickname, extra, dwrq->length); - iw->nickname[dwrq->length - 1] = '\0'; - - return 0; -} - -static int -wl_iw_get_nick( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - - WL_TRACE(("%s: SIOCGIWNICKN\n", dev->name)); - - if (!extra) - return -EINVAL; - - strcpy(extra, iw->nickname); - dwrq->length = strlen(extra) + 1; - - return 0; -} - -static int wl_iw_set_rate( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - wl_rateset_t rateset; - int error, rate, i, error_bg, error_a; - - WL_TRACE(("%s: SIOCSIWRATE\n", dev->name)); - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_CURR_RATESET, &rateset, sizeof(rateset)))) - return error; - - rateset.count = dtoh32(rateset.count); - - if (vwrq->value < 0) { - - rate = rateset.rates[rateset.count - 1] & 0x7f; - } else if (vwrq->value < rateset.count) { - - rate = rateset.rates[vwrq->value] & 0x7f; - } else { - - rate = vwrq->value / 500000; - } - - if (vwrq->fixed) { - - error_bg = dev_wlc_intvar_set(dev, "bg_rate", rate); - error_a = dev_wlc_intvar_set(dev, "a_rate", rate); - - if (error_bg && error_a) - return (error_bg | error_a); - } else { - - - error_bg = dev_wlc_intvar_set(dev, "bg_rate", 0); - - error_a = dev_wlc_intvar_set(dev, "a_rate", 0); - - if (error_bg && error_a) - return (error_bg | error_a); - - - for (i = 0; i < rateset.count; i++) - if ((rateset.rates[i] & 0x7f) > rate) - break; - rateset.count = htod32(i); - - - if ((error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset, sizeof(rateset)))) - return error; - } - - return 0; -} - -static int wl_iw_get_rate( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, rate; - - WL_TRACE(("%s: SIOCGIWRATE\n", dev->name)); - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate)))) - return error; - rate = dtoh32(rate); - vwrq->value = rate * 500000; - - return 0; -} - -static int -wl_iw_set_rts( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, rts; - - WL_TRACE(("%s: SIOCSIWRTS\n", dev->name)); - - if (vwrq->disabled) - rts = DOT11_DEFAULT_RTS_LEN; - else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_RTS_LEN) - return -EINVAL; - else - rts = vwrq->value; - - if ((error = dev_wlc_intvar_set(dev, "rtsthresh", rts))) - return error; - - return 0; -} - -static int -wl_iw_get_rts( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, rts; - - WL_TRACE(("%s: SIOCGIWRTS\n", dev->name)); - - if ((error = dev_wlc_intvar_get(dev, "rtsthresh", &rts))) - return error; - - vwrq->value = rts; - vwrq->disabled = (rts >= DOT11_DEFAULT_RTS_LEN); - vwrq->fixed = 1; - - return 0; -} - -static int -wl_iw_set_frag( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, frag; - - WL_TRACE(("%s: SIOCSIWFRAG\n", dev->name)); - - if (vwrq->disabled) - frag = DOT11_DEFAULT_FRAG_LEN; - else if (vwrq->value < 0 || vwrq->value > DOT11_DEFAULT_FRAG_LEN) - return -EINVAL; - else - frag = vwrq->value; - - if ((error = dev_wlc_intvar_set(dev, "fragthresh", frag))) - return error; - - return 0; -} - -static int -wl_iw_get_frag( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, fragthreshold; - - WL_TRACE(("%s: SIOCGIWFRAG\n", dev->name)); - - if ((error = dev_wlc_intvar_get(dev, "fragthresh", &fragthreshold))) - return error; - - vwrq->value = fragthreshold; - vwrq->disabled = (fragthreshold >= DOT11_DEFAULT_FRAG_LEN); - vwrq->fixed = 1; - - return 0; -} - -static int -wl_iw_set_txpow( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, disable; - uint16 txpwrmw; - WL_TRACE(("%s: SIOCSIWTXPOW\n", dev->name)); - - - disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0; - disable += WL_RADIO_SW_DISABLE << 16; - - disable = htod32(disable); - if ((error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable)))) - return error; - - - if (disable & WL_RADIO_SW_DISABLE) - return 0; - - - if (!(vwrq->flags & IW_TXPOW_MWATT)) - return -EINVAL; - - - if (vwrq->value < 0) - return 0; - - if (vwrq->value > 0xffff) txpwrmw = 0xffff; - else txpwrmw = (uint16)vwrq->value; - - - error = dev_wlc_intvar_set(dev, "qtxpower", (int)(bcm_mw_to_qdbm(txpwrmw))); - return error; -} - -static int -wl_iw_get_txpow( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, disable, txpwrdbm; - uint8 result; - - WL_TRACE(("%s: SIOCGIWTXPOW\n", dev->name)); - - if ((error = dev_wlc_ioctl(dev, WLC_GET_RADIO, &disable, sizeof(disable))) || - (error = dev_wlc_intvar_get(dev, "qtxpower", &txpwrdbm))) - return error; - - disable = dtoh32(disable); - result = (uint8)(txpwrdbm & ~WL_TXPWR_OVERRIDE); - vwrq->value = (int32)bcm_qdbm_to_mw(result); - vwrq->fixed = 0; - vwrq->disabled = (disable & (WL_RADIO_SW_DISABLE | WL_RADIO_HW_DISABLE)) ? 1 : 0; - vwrq->flags = IW_TXPOW_MWATT; - - return 0; -} - -#if WIRELESS_EXT > 10 -static int -wl_iw_set_retry( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, lrl, srl; - - WL_TRACE(("%s: SIOCSIWRETRY\n", dev->name)); - - - if (vwrq->disabled || (vwrq->flags & IW_RETRY_LIFETIME)) - return -EINVAL; - - - if (vwrq->flags & IW_RETRY_LIMIT) { - - -#if WIRELESS_EXT > 20 - if ((vwrq->flags & IW_RETRY_LONG) ||(vwrq->flags & IW_RETRY_MAX) || - !((vwrq->flags & IW_RETRY_SHORT) || (vwrq->flags & IW_RETRY_MIN))) { -#else - if ((vwrq->flags & IW_RETRY_MAX) || !(vwrq->flags & IW_RETRY_MIN)) { -#endif - lrl = htod32(vwrq->value); - if ((error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl, sizeof(lrl)))) - return error; - } - - -#if WIRELESS_EXT > 20 - if ((vwrq->flags & IW_RETRY_SHORT) ||(vwrq->flags & IW_RETRY_MIN) || - !((vwrq->flags & IW_RETRY_LONG) || (vwrq->flags & IW_RETRY_MAX))) { -#else - if ((vwrq->flags & IW_RETRY_MIN) || !(vwrq->flags & IW_RETRY_MAX)) { -#endif - srl = htod32(vwrq->value); - if ((error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl, sizeof(srl)))) - return error; - } - } - return 0; -} - -static int -wl_iw_get_retry( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, lrl, srl; - - WL_TRACE(("%s: SIOCGIWRETRY\n", dev->name)); - - vwrq->disabled = 0; - - - if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) - return -EINVAL; - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_LRL, &lrl, sizeof(lrl))) || - (error = dev_wlc_ioctl(dev, WLC_GET_SRL, &srl, sizeof(srl)))) - return error; - - lrl = dtoh32(lrl); - srl = dtoh32(srl); - - - if (vwrq->flags & IW_RETRY_MAX) { - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - vwrq->value = lrl; - } else { - vwrq->flags = IW_RETRY_LIMIT; - vwrq->value = srl; - if (srl != lrl) - vwrq->flags |= IW_RETRY_MIN; - } - - return 0; -} -#endif - -static int -wl_iw_set_encode( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_wsec_key_t key; - int error, val, wsec; - - WL_TRACE(("%s: SIOCSIWENCODE\n", dev->name)); - - memset(&key, 0, sizeof(key)); - - if ((dwrq->flags & IW_ENCODE_INDEX) == 0) { - - for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) { - val = htod32(key.index); - if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)))) - return error; - val = dtoh32(val); - if (val) - break; - } - - if (key.index == DOT11_MAX_DEFAULT_KEYS) - key.index = 0; - } else { - key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if (key.index >= DOT11_MAX_DEFAULT_KEYS) - return -EINVAL; - } - - - if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) { - - val = htod32(key.index); - if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val, sizeof(val)))) - return error; - } else { - key.len = dwrq->length; - - if (dwrq->length > sizeof(key.data)) - return -EINVAL; - - memcpy(key.data, extra, dwrq->length); - - key.flags = WL_PRIMARY_KEY; - switch (key.len) { - case WEP1_KEY_SIZE: - key.algo = CRYPTO_ALGO_WEP1; - break; - case WEP128_KEY_SIZE: - key.algo = CRYPTO_ALGO_WEP128; - break; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14) - case TKIP_KEY_SIZE: - key.algo = CRYPTO_ALGO_TKIP; - break; -#endif - case AES_KEY_SIZE: - key.algo = CRYPTO_ALGO_AES_CCM; - break; - default: - return -EINVAL; - } - - - swap_key_from_BE(&key); - if ((error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)))) - return error; - } - - - val = (dwrq->flags & IW_ENCODE_DISABLED) ? 0 : WEP_ENABLED; - - if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec))) - return error; - - wsec &= ~(WEP_ENABLED); - wsec |= val; - - if ((error = dev_wlc_intvar_set(dev, "wsec", wsec))) - return error; - - - val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0; - val = htod32(val); - if ((error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val)))) - return error; - - return 0; -} - -static int -wl_iw_get_encode( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_wsec_key_t key; - int error, val, wsec, auth; - - WL_TRACE(("%s: SIOCGIWENCODE\n", dev->name)); - - - bzero(&key, sizeof(wl_wsec_key_t)); - - if ((dwrq->flags & IW_ENCODE_INDEX) == 0) { - - for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS; key.index++) { - val = key.index; - if ((error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val, sizeof(val)))) - return error; - val = dtoh32(val); - if (val) - break; - } - } else - key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - - if (key.index >= DOT11_MAX_DEFAULT_KEYS) - key.index = 0; - - - - if ((error = dev_wlc_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec))) || - (error = dev_wlc_ioctl(dev, WLC_GET_AUTH, &auth, sizeof(auth)))) - return error; - - swap_key_to_BE(&key); - - wsec = dtoh32(wsec); - auth = dtoh32(auth); - - dwrq->length = MIN(DOT11_MAX_KEY_SIZE, key.len); - - - dwrq->flags = key.index + 1; - if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED))) { - - dwrq->flags |= IW_ENCODE_DISABLED; - } - if (auth) { - - dwrq->flags |= IW_ENCODE_RESTRICTED; - } - - - if (dwrq->length && extra) - memcpy(extra, key.data, dwrq->length); - - return 0; -} - -static int -wl_iw_set_power( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, pm; - - WL_TRACE(("%s: SIOCSIWPOWER\n", dev->name)); - - pm = vwrq->disabled ? PM_OFF : PM_MAX; - - pm = htod32(pm); - if ((error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm)))) - return error; - - return 0; -} - -static int -wl_iw_get_power( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error, pm; - - WL_TRACE(("%s: SIOCGIWPOWER\n", dev->name)); - - if ((error = dev_wlc_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm)))) - return error; - - pm = dtoh32(pm); - vwrq->disabled = pm ? 0 : 1; - vwrq->flags = IW_POWER_ALL_R; - - return 0; -} - -#if WIRELESS_EXT > 17 -static int -wl_iw_set_wpaie( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *iwp, - char *extra -) -{ - uchar buf[WLC_IOCTL_SMLEN] = {0}; - uchar *p = buf; - int wapi_ie_size; - - WL_TRACE(("%s: SIOCSIWGENIE\n", dev->name)); - - CHECK_EXTRA_FOR_NULL(extra); - - if (extra[0] == DOT11_MNG_WAPI_ID) - { - wapi_ie_size = iwp->length; - memcpy(p, extra, iwp->length); - dev_wlc_bufvar_set(dev, "wapiie", buf, wapi_ie_size); - } - else - dev_wlc_bufvar_set(dev, "wpaie", extra, iwp->length); - - return 0; -} - -static int -wl_iw_get_wpaie( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *iwp, - char *extra -) -{ - WL_TRACE(("%s: SIOCGIWGENIE\n", dev->name)); - iwp->length = 64; - dev_wlc_bufvar_get(dev, "wpaie", extra, iwp->length); - return 0; -} - -static int -wl_iw_set_encodeext( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra -) -{ - wl_wsec_key_t key; - int error; - struct iw_encode_ext *iwe; - - WL_TRACE(("%s: SIOCSIWENCODEEXT\n", dev->name)); - - CHECK_EXTRA_FOR_NULL(extra); - - memset(&key, 0, sizeof(key)); - iwe = (struct iw_encode_ext *)extra; - - - if (dwrq->flags & IW_ENCODE_DISABLED) { - - } - - - key.index = 0; - if (dwrq->flags & IW_ENCODE_INDEX) - key.index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - - key.len = iwe->key_len; - - - if (!ETHER_ISMULTI(iwe->addr.sa_data)) - bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea, ETHER_ADDR_LEN); - - - if (key.len == 0) { - if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - WL_WSEC(("Changing the the primary Key to %d\n", key.index)); - - key.index = htod32(key.index); - error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, - &key.index, sizeof(key.index)); - if (error) - return error; - } - - else { - swap_key_from_BE(&key); - dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); - } - } - else { - if (iwe->key_len > sizeof(key.data)) - return -EINVAL; - - WL_WSEC(("Setting the key index %d\n", key.index)); - if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - WL_WSEC(("key is a Primary Key\n")); - key.flags = WL_PRIMARY_KEY; - } - - bcopy((void *)iwe->key, key.data, iwe->key_len); - - if (iwe->alg == IW_ENCODE_ALG_TKIP) { - uint8 keybuf[8]; - bcopy(&key.data[24], keybuf, sizeof(keybuf)); - bcopy(&key.data[16], &key.data[24], sizeof(keybuf)); - bcopy(keybuf, &key.data[16], sizeof(keybuf)); - } - - - if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) { - uchar *ivptr; - ivptr = (uchar *)iwe->rx_seq; - key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) | - (ivptr[3] << 8) | ivptr[2]; - key.rxiv.lo = (ivptr[1] << 8) | ivptr[0]; - key.iv_initialized = TRUE; - } - - switch (iwe->alg) { - case IW_ENCODE_ALG_NONE: - key.algo = CRYPTO_ALGO_OFF; - break; - case IW_ENCODE_ALG_WEP: - if (iwe->key_len == WEP1_KEY_SIZE) - key.algo = CRYPTO_ALGO_WEP1; - else - key.algo = CRYPTO_ALGO_WEP128; - break; - case IW_ENCODE_ALG_TKIP: - key.algo = CRYPTO_ALGO_TKIP; - break; - case IW_ENCODE_ALG_CCMP: - key.algo = CRYPTO_ALGO_AES_CCM; - break; - case IW_ENCODE_ALG_SM4: - key.algo = CRYPTO_ALGO_SMS4; - if (iwe->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - key.flags &= ~WL_PRIMARY_KEY; - } - break; - default: - break; - } - swap_key_from_BE(&key); - - dhd_wait_pend8021x(dev); - - error = dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); - if (error) - return error; - } - return 0; -} - -#if WIRELESS_EXT > 17 -#ifdef BCMWPA2 -struct { - pmkid_list_t pmkids; - pmkid_t foo[MAXPMKID-1]; -} pmkid_list; - -static int -wl_iw_set_pmksa( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - struct iw_pmksa *iwpmksa; - uint i; - int ret = 0; - char eabuf[ETHER_ADDR_STR_LEN]; - - WL_WSEC(("%s: SIOCSIWPMKSA\n", dev->name)); - - CHECK_EXTRA_FOR_NULL(extra); - - iwpmksa = (struct iw_pmksa *)extra; - bzero((char *)eabuf, ETHER_ADDR_STR_LEN); - - if (iwpmksa->cmd == IW_PMKSA_FLUSH) { - WL_WSEC(("wl_iw_set_pmksa - IW_PMKSA_FLUSH\n")); - bzero((char *)&pmkid_list, sizeof(pmkid_list)); - } - - else if (iwpmksa->cmd == IW_PMKSA_REMOVE) { - { - pmkid_list_t pmkid, *pmkidptr; - uint j; - pmkidptr = &pmkid; - - bcopy(&iwpmksa->bssid.sa_data[0], &pmkidptr->pmkid[0].BSSID, \ - ETHER_ADDR_LEN); - bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID, WPA2_PMKID_LEN); - - WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_REMOVE - PMKID: %s = ", - bcm_ether_ntoa(&pmkidptr->pmkid[0].BSSID, - eabuf))); - for (j = 0; j < WPA2_PMKID_LEN; j++) - WL_WSEC(("%02x ", pmkidptr->pmkid[0].PMKID[j])); - WL_WSEC(("\n")); - } - - for (i = 0; i < pmkid_list.pmkids.npmkid; i++) - if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID, - ETHER_ADDR_LEN)) - break; - - if ((pmkid_list.pmkids.npmkid > 0) && (i < pmkid_list.pmkids.npmkid)) { - bzero(&pmkid_list.pmkids.pmkid[i], sizeof(pmkid_t)); - for (; i < (pmkid_list.pmkids.npmkid - 1); i++) { - bcopy(&pmkid_list.pmkids.pmkid[i+1].BSSID, - &pmkid_list.pmkids.pmkid[i].BSSID, - ETHER_ADDR_LEN); - bcopy(&pmkid_list.pmkids.pmkid[i+1].PMKID, - &pmkid_list.pmkids.pmkid[i].PMKID, - WPA2_PMKID_LEN); - } - pmkid_list.pmkids.npmkid--; - } - else - ret = -EINVAL; - } - - else if (iwpmksa->cmd == IW_PMKSA_ADD) { - for (i = 0; i < pmkid_list.pmkids.npmkid; i++) - if (!bcmp(&iwpmksa->bssid.sa_data[0], &pmkid_list.pmkids.pmkid[i].BSSID, - ETHER_ADDR_LEN)) - break; - if (i < MAXPMKID) { - bcopy(&iwpmksa->bssid.sa_data[0], - &pmkid_list.pmkids.pmkid[i].BSSID, - ETHER_ADDR_LEN); - bcopy(&iwpmksa->pmkid[0], &pmkid_list.pmkids.pmkid[i].PMKID, - WPA2_PMKID_LEN); - if (i == pmkid_list.pmkids.npmkid) - pmkid_list.pmkids.npmkid++; - } - else - ret = -EINVAL; - { - uint j; - uint k; - k = pmkid_list.pmkids.npmkid; - WL_WSEC(("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %s = ", - bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[k].BSSID, - eabuf))); - for (j = 0; j < WPA2_PMKID_LEN; j++) - WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[k].PMKID[j])); - WL_WSEC(("\n")); - } - } - WL_WSEC(("PRINTING pmkid LIST - No of elements %d\n", pmkid_list.pmkids.npmkid)); - for (i = 0; i < pmkid_list.pmkids.npmkid; i++) { - uint j; - WL_WSEC(("PMKID[%d]: %s = ", i, - bcm_ether_ntoa(&pmkid_list.pmkids.pmkid[i].BSSID, - eabuf))); - for (j = 0; j < WPA2_PMKID_LEN; j++) - WL_WSEC(("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j])); - WL_WSEC(("\n")); - } - WL_WSEC(("\n")); - - if (!ret) - ret = dev_wlc_bufvar_set(dev, "pmkid_info", (char *)&pmkid_list, \ - sizeof(pmkid_list)); - return ret; -} -#endif -#endif - -static int -wl_iw_get_encodeext( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - WL_TRACE(("%s: SIOCGIWENCODEEXT\n", dev->name)); - return 0; -} - -static int -wl_iw_set_wpaauth( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error = 0; - int paramid; - int paramval; - int val = 0; - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - - WL_TRACE(("%s: SIOCSIWAUTH\n", dev->name)); - -#if defined(SOFTAP) - if (ap_cfg_running) { - WL_TRACE(("%s: Not executed, reason -'SOFTAP is active'\n", __FUNCTION__)); - return 0; - } -#endif - - paramid = vwrq->flags & IW_AUTH_INDEX; - paramval = vwrq->value; - - WL_TRACE(("%s: SIOCSIWAUTH, paramid = 0x%0x, paramval = 0x%0x\n", - dev->name, paramid, paramval)); - - switch (paramid) { - case IW_AUTH_WPA_VERSION: - - if (paramval & IW_AUTH_WPA_VERSION_DISABLED) - val = WPA_AUTH_DISABLED; - else if (paramval & (IW_AUTH_WPA_VERSION_WPA)) - val = WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED; -#ifdef BCMWPA2 - else if (paramval & IW_AUTH_WPA_VERSION_WPA2) - val = WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED; -#endif - else if (paramval & IW_AUTH_WAPI_VERSION_1) - val = WPA_AUTH_WAPI; - WL_INFORM(("%s: %d: setting wpa_auth to 0x%0x\n", __FUNCTION__, __LINE__, val)); - if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) - return error; - break; - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - - - if (paramval & (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104)) - val = WEP_ENABLED; - if (paramval & IW_AUTH_CIPHER_TKIP) - val = TKIP_ENABLED; - if (paramval & IW_AUTH_CIPHER_CCMP) - val = AES_ENABLED; - if (paramval & IW_AUTH_CIPHER_SMS4) - val = SMS4_ENABLED; - - if (paramid == IW_AUTH_CIPHER_PAIRWISE) { - iw->pwsec = val; - val |= iw->gwsec; - } - else { - iw->gwsec = val; - val |= iw->pwsec; - } - - if (iw->privacy_invoked && !val) { - WL_WSEC(("%s: %s: 'Privacy invoked' TRUE but clearing wsec, assuming " - "we're a WPS enrollee\n", dev->name, __FUNCTION__)); - if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { - WL_WSEC(("Failed to set iovar is_WPS_enrollee\n")); - return error; - } - } else if (val) { - if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { - WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n")); - return error; - } - } - - if ((error = dev_wlc_intvar_set(dev, "wsec", val))) - return error; - - break; - - case IW_AUTH_KEY_MGMT: - if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) - return error; - - if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { - if (paramval & IW_AUTH_KEY_MGMT_PSK) - val = WPA_AUTH_PSK; - else - val = WPA_AUTH_UNSPECIFIED; - } -#ifdef BCMWPA2 - else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { - if (paramval & IW_AUTH_KEY_MGMT_PSK) - val = WPA2_AUTH_PSK; - else - val = WPA2_AUTH_UNSPECIFIED; - } -#endif - if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT)) - val = WPA_AUTH_WAPI; - WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); - if ((error = dev_wlc_intvar_set(dev, "wpa_auth", val))) - return error; - - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - dev_wlc_bufvar_set(dev, "tkip_countermeasures", (char *)¶mval, 1); - break; - - case IW_AUTH_80211_AUTH_ALG: - - WL_INFORM(("Setting the D11auth %d\n", paramval)); - if (paramval == IW_AUTH_ALG_OPEN_SYSTEM) - val = 0; - else if (paramval == IW_AUTH_ALG_SHARED_KEY) - val = 1; - else if (paramval == (IW_AUTH_ALG_OPEN_SYSTEM | IW_AUTH_ALG_SHARED_KEY)) - val = 2; - else - error = 1; - if (!error && (error = dev_wlc_intvar_set(dev, "auth", val))) - return error; - break; - - case IW_AUTH_WPA_ENABLED: - if (paramval == 0) { - iw->pwsec = 0; - iw->gwsec = 0; - if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) - return error; - if (val & (TKIP_ENABLED | AES_ENABLED)) { - val &= ~(TKIP_ENABLED | AES_ENABLED); - dev_wlc_intvar_set(dev, "wsec", val); - } - val = 0; - WL_INFORM(("%s: %d: setting wpa_auth to %d\n", __FUNCTION__, __LINE__, val)); - dev_wlc_intvar_set(dev, "wpa_auth", 0); - return error; - } - - - break; - - case IW_AUTH_DROP_UNENCRYPTED: - dev_wlc_bufvar_set(dev, "wsec_restrict", (char *)¶mval, 1); - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - dev_wlc_bufvar_set(dev, "rx_unencrypted_eapol", (char *)¶mval, 1); - break; - -#if WIRELESS_EXT > 17 - case IW_AUTH_ROAMING_CONTROL: - WL_INFORM(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); - - break; - case IW_AUTH_PRIVACY_INVOKED: { - int wsec; - - if (paramval == 0) { - iw->privacy_invoked = FALSE; - if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { - WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n")); - return error; - } - } else { - iw->privacy_invoked = TRUE; - if ((error = dev_wlc_intvar_get(dev, "wsec", &wsec))) - return error; - - if (!(IW_WSEC_ENABLED(wsec))) { - - - if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", TRUE))) { - WL_WSEC(("Failed to set iovar is_WPS_enrollee\n")); - return error; - } - } else { - if ((error = dev_wlc_intvar_set(dev, "is_WPS_enrollee", FALSE))) { - WL_WSEC(("Failed to clear iovar is_WPS_enrollee\n")); - return error; - } - } - } - break; - } -#endif - case IW_AUTH_WAPI_ENABLED: - if ((error = dev_wlc_intvar_get(dev, "wsec", &val))) - return error; - if (paramval) { - val |= SMS4_ENABLED; - if ((error = dev_wlc_intvar_set(dev, "wsec", val))) { - WL_ERROR(("%s: setting wsec to 0x%0x returned error %d\n", - __FUNCTION__, val, error)); - return error; - } - if ((error = dev_wlc_intvar_set(dev, "wpa_auth", WPA_AUTH_WAPI))) { - WL_ERROR(("%s: setting wpa_auth(WPA_AUTH_WAPI) returned %d\n", - __FUNCTION__, error)); - return error; - } - } - - break; - default: - break; - } - return 0; -} -#ifdef BCMWPA2 -#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK) || ((_val) & WPA2_AUTH_PSK)) -#else -#define VAL_PSK(_val) (((_val) & WPA_AUTH_PSK)) -#endif - -static int -wl_iw_get_wpaauth( - struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, - char *extra -) -{ - int error; - int paramid; - int paramval = 0; - int val; - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - - WL_TRACE(("%s: SIOCGIWAUTH\n", dev->name)); - - paramid = vwrq->flags & IW_AUTH_INDEX; - - switch (paramid) { - case IW_AUTH_WPA_VERSION: - - if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) - return error; - if (val & (WPA_AUTH_NONE | WPA_AUTH_DISABLED)) - paramval = IW_AUTH_WPA_VERSION_DISABLED; - else if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) - paramval = IW_AUTH_WPA_VERSION_WPA; -#ifdef BCMWPA2 - else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) - paramval = IW_AUTH_WPA_VERSION_WPA2; -#endif - break; - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - if (paramid == IW_AUTH_CIPHER_PAIRWISE) - val = iw->pwsec; - else - val = iw->gwsec; - - paramval = 0; - if (val) { - if (val & WEP_ENABLED) - paramval |= (IW_AUTH_CIPHER_WEP40 | IW_AUTH_CIPHER_WEP104); - if (val & TKIP_ENABLED) - paramval |= (IW_AUTH_CIPHER_TKIP); - if (val & AES_ENABLED) - paramval |= (IW_AUTH_CIPHER_CCMP); - } - else - paramval = IW_AUTH_CIPHER_NONE; - break; - case IW_AUTH_KEY_MGMT: - - if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) - return error; - if (VAL_PSK(val)) - paramval = IW_AUTH_KEY_MGMT_PSK; - else - paramval = IW_AUTH_KEY_MGMT_802_1X; - - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - dev_wlc_bufvar_get(dev, "tkip_countermeasures", (char *)¶mval, 1); - break; - - case IW_AUTH_DROP_UNENCRYPTED: - dev_wlc_bufvar_get(dev, "wsec_restrict", (char *)¶mval, 1); - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - dev_wlc_bufvar_get(dev, "rx_unencrypted_eapol", (char *)¶mval, 1); - break; - - case IW_AUTH_80211_AUTH_ALG: - - if ((error = dev_wlc_intvar_get(dev, "auth", &val))) - return error; - if (!val) - paramval = IW_AUTH_ALG_OPEN_SYSTEM; - else - paramval = IW_AUTH_ALG_SHARED_KEY; - break; - case IW_AUTH_WPA_ENABLED: - if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) - return error; - if (val) - paramval = TRUE; - else - paramval = FALSE; - break; -#if WIRELESS_EXT > 17 - case IW_AUTH_ROAMING_CONTROL: - WL_ERROR(("%s: IW_AUTH_ROAMING_CONTROL\n", __FUNCTION__)); - - break; - case IW_AUTH_PRIVACY_INVOKED: - paramval = iw->privacy_invoked; - break; - -#endif - } - vwrq->value = paramval; - return 0; -} -#endif - - -#ifdef SOFTAP - -static int ap_macmode = MACLIST_MODE_DISABLED; -static struct mflist ap_black_list; -static int -wl_iw_parse_wep(char *keystr, wl_wsec_key_t *key) -{ - char hex[] = "XX"; - unsigned char *data = key->data; - - switch (strlen(keystr)) { - case 5: - case 13: - case 16: - key->len = strlen(keystr); - memcpy(data, keystr, key->len + 1); - break; - case 12: - case 28: - case 34: - case 66: - - if (!strnicmp(keystr, "0x", 2)) - keystr += 2; - else - return -1; - - case 10: - case 26: - case 32: - case 64: - key->len = strlen(keystr) / 2; - while (*keystr) { - strncpy(hex, keystr, 2); - *data++ = (char) bcm_strtoul(hex, NULL, 16); - keystr += 2; - } - break; - default: - return -1; - } - - switch (key->len) { - case 5: - key->algo = CRYPTO_ALGO_WEP1; - break; - case 13: - key->algo = CRYPTO_ALGO_WEP128; - break; - case 16: - - key->algo = CRYPTO_ALGO_AES_CCM; - break; - case 32: - key->algo = CRYPTO_ALGO_TKIP; - break; - default: - return -1; - } - - - key->flags |= WL_PRIMARY_KEY; - - return 0; -} - -#ifdef EXT_WPA_CRYPTO -#define SHA1HashSize 20 -extern void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, \ - int iterations, u8 *buf, size_t buflen); - -#else - -#define SHA1HashSize 20 -int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len, \ - int iterations, u8 *buf, size_t buflen) -{ - WL_ERROR(("WARNING: %s is not implemented !!!\n", __FUNCTION__)); - return -1; -} - -#endif - - -int dev_iw_write_cfg1_bss_var(struct net_device *dev, int val) -{ - struct { - int cfg; - int val; - } bss_setbuf; - - int bss_set_res; - char smbuf[WLC_IOCTL_SMLEN]; - memset(smbuf, 0, sizeof(smbuf)); - - bss_setbuf.cfg = 1; - bss_setbuf.val = val; - - bss_set_res = dev_iw_iovar_setbuf(dev, "bss", - &bss_setbuf, sizeof(bss_setbuf), smbuf, sizeof(smbuf)); - WL_TRACE(("%s: bss_set_result:%d set with %d\n", __FUNCTION__, bss_set_res, val)); - - return bss_set_res; -} - - -int dev_iw_read_cfg1_bss_var(struct net_device *dev, int *val) -{ - int bsscfg_idx = 1; - int bss_set_res; - char smbuf[WLC_IOCTL_SMLEN]; - memset(smbuf, 0, sizeof(smbuf)); - - bss_set_res = dev_iw_iovar_getbuf(dev, "bss", \ - &bsscfg_idx, sizeof(bsscfg_idx), smbuf, sizeof(smbuf)); - *val = *(int*)smbuf; - *val = dtoh32(*val); - WL_TRACE(("%s: status=%d bss_get_result=%d\n", __FUNCTION__, bss_set_res, *val)); - return bss_set_res; -} - - - -#ifndef AP_ONLY -static int wl_bssiovar_mkbuf( - const char *iovar, - int bssidx, - void *param, - int paramlen, - void *bufptr, - int buflen, - int *perr) -{ - const char *prefix = "bsscfg:"; - int8* p; - uint prefixlen; - uint namelen; - uint iolen; - - prefixlen = strlen(prefix); - namelen = strlen(iovar) + 1; - iolen = prefixlen + namelen + sizeof(int) + paramlen; - - - if (buflen < 0 || iolen > (uint)buflen) { - *perr = BCME_BUFTOOSHORT; - return 0; - } - - p = (int8*)bufptr; - - - memcpy(p, prefix, prefixlen); - p += prefixlen; - - - memcpy(p, iovar, namelen); - p += namelen; - - - bssidx = htod32(bssidx); - memcpy(p, &bssidx, sizeof(int32)); - p += sizeof(int32); - - - if (paramlen) - memcpy(p, param, paramlen); - - *perr = 0; - return iolen; -} -#endif - - - - -int get_user_params(char *user_params, struct iw_point *dwrq) -{ - int ret = 0; - - if (copy_from_user(user_params, dwrq->pointer, dwrq->length)) { - WL_ERROR(("\n%s: no user params: uptr:%p, ulen:%d\n", - __FUNCTION__, dwrq->pointer, dwrq->length)); - return -EFAULT; - } - - WL_TRACE(("\n%s: iwpriv user params:%s\n", __FUNCTION__, user_params)); - - return ret; -} - - -#define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base)) - - -#if defined(CSCAN) - - - -static int -wl_iw_combined_scan_set(struct net_device *dev, wlc_ssid_t* ssids_local, int nssid, int nchan) -{ - int params_size = WL_SCAN_PARAMS_FIXED_SIZE + WL_NUMCHANNELS * sizeof(uint16); - int err = 0; - char *p; - int i; - iscan_info_t *iscan = g_iscan; - - WL_ERROR(("%s nssid=%d nchan=%d\n", __FUNCTION__, nssid, nchan)); - - if ((!dev) && (!g_iscan) && (!iscan->iscan_ex_params_p)) { - WL_ERROR(("%s error exit\n", __FUNCTION__)); - err = -1; - } - - params_size += WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); - - - if (nssid > 0) { - i = OFFSETOF(wl_scan_params_t, channel_list) + nchan * sizeof(uint16); - i = ROUNDUP(i, sizeof(uint32)); - if (i + nssid * sizeof(wlc_ssid_t) > params_size) { - printf("additional ssids exceed params_size\n"); - err = -1; - goto exit; - } - - p = ((char*)&iscan->iscan_ex_params_p->params) + i; - memcpy(p, ssids_local, nssid * sizeof(wlc_ssid_t)); - p += nssid * sizeof(wlc_ssid_t); - } else { - p = (char*)iscan->iscan_ex_params_p->params.channel_list + nchan * sizeof(uint16); - } - - - iscan->iscan_ex_params_p->params.channel_num = \ - htod32((nssid << WL_SCAN_PARAMS_NSSID_SHIFT) | \ - (nchan & WL_SCAN_PARAMS_COUNT_MASK)); - - nssid = \ - (uint)((iscan->iscan_ex_params_p->params.channel_num >> WL_SCAN_PARAMS_NSSID_SHIFT) & \ - WL_SCAN_PARAMS_COUNT_MASK); - - - params_size = (int) (p - (char*)iscan->iscan_ex_params_p + nssid * sizeof(wlc_ssid_t)); - iscan->iscan_ex_param_size = params_size; - - iscan->list_cur = iscan->list_hdr; - iscan->iscan_state = ISCAN_STATE_SCANING; - wl_iw_set_event_mask(dev); - mod_timer(&iscan->timer, jiffies + iscan->timer_ms*HZ/1000); - - iscan->timer_on = 1; - -#ifdef SCAN_DUMP - { - int i; - WL_SCAN(("\n### List of SSIDs to scan ###\n")); - for (i = 0; i < nssid; i++) { - if (!ssids_local[i].SSID_len) - WL_SCAN(("%d: Broadcast scan\n", i)); - else - WL_SCAN(("%d: scan for %s size =%d\n", i, \ - ssids_local[i].SSID, ssids_local[i].SSID_len)); - } - WL_SCAN(("### List of channels to scan ###\n")); - for (i = 0; i < nchan; i++) - { - WL_SCAN(("%d ", iscan->iscan_ex_params_p->params.channel_list[i])); - } - WL_SCAN(("\nnprobes=%d\n", iscan->iscan_ex_params_p->params.nprobes)); - WL_SCAN(("active_time=%d\n", iscan->iscan_ex_params_p->params.active_time)); - WL_SCAN(("passive_time=%d\n", iscan->iscan_ex_params_p->params.passive_time)); - WL_SCAN(("home_time=%d\n", iscan->iscan_ex_params_p->params.home_time)); - WL_SCAN(("scan_type=%d\n", iscan->iscan_ex_params_p->params.scan_type)); - WL_SCAN(("\n###################\n")); - } -#endif - - if (params_size > WLC_IOCTL_MEDLEN) { - WL_ERROR(("Set ISCAN for %s due to params_size=%d \n", \ - __FUNCTION__, params_size)); - err = -1; - } - - if ((err = dev_iw_iovar_setbuf(dev, "iscan", iscan->iscan_ex_params_p, \ - iscan->iscan_ex_param_size, \ - iscan->ioctlbuf, sizeof(iscan->ioctlbuf)))) { - WL_TRACE(("Set ISCAN for %s failed with %d\n", __FUNCTION__, err)); - err = -1; - } - -exit: - - return err; -} - - -static int iwpriv_set_cscan(struct net_device *dev, struct iw_request_info *info, \ - union iwreq_data *wrqu, char *ext) -{ - int res = 0; - char *extra = NULL; - iscan_info_t *iscan = g_iscan; - wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX]; - int nssid = 0; - int nchan = 0; - - WL_TRACE(("\%s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n", - __FUNCTION__, info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length)); - - if (g_onoff == G_WLAN_SET_OFF) { - WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); - return -1; - } - - if (wrqu->data.length != 0) { - - char *str_ptr; - - if (!iscan->iscan_ex_params_p) { - return -EFAULT; - } - - if (!(extra = kmalloc(wrqu->data.length+1, GFP_KERNEL))) - return -ENOMEM; - - if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) { - kfree(extra); - return -EFAULT; - } - - extra[wrqu->data.length] = 0; - WL_ERROR(("Got str param in iw_point:\n %s\n", extra)); - - str_ptr = extra; - - - if (strncmp(str_ptr, GET_SSID, strlen(GET_SSID))) { - WL_ERROR(("%s Error: extracting SSID='' string\n", __FUNCTION__)); - goto exit_proc; - } - str_ptr += strlen(GET_SSID); - nssid = wl_iw_parse_ssid_list(&str_ptr, ssids_local, nssid, \ - WL_SCAN_PARAMS_SSID_MAX); - if (nssid == -1) { - WL_ERROR(("%s wrong ssid list", __FUNCTION__)); - return -1; - } - - memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size); - ASSERT(iscan->iscan_ex_param_size < WLC_IOCTL_MAXLEN); - - - wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL); - iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); - iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START); - iscan->iscan_ex_params_p->scan_duration = htod16(0); - - - if ((nchan = wl_iw_parse_channel_list(&str_ptr, \ - &iscan->iscan_ex_params_p->params.channel_list[0], \ - WL_NUMCHANNELS)) == -1) { - WL_ERROR(("%s missing channel list\n", __FUNCTION__)); - return -1; - } - - - get_parmeter_from_string(&str_ptr, \ - GET_NPROBE, PTYPE_INTDEC, \ - &iscan->iscan_ex_params_p->params.nprobes, 2); - - get_parmeter_from_string(&str_ptr, GET_ACTIVE_ASSOC_DWELL, PTYPE_INTDEC, \ - &iscan->iscan_ex_params_p->params.active_time, 4); - - get_parmeter_from_string(&str_ptr, GET_PASSIVE_ASSOC_DWELL, PTYPE_INTDEC, \ - &iscan->iscan_ex_params_p->params.passive_time, 4); - - get_parmeter_from_string(&str_ptr, GET_HOME_DWELL, PTYPE_INTDEC, \ - &iscan->iscan_ex_params_p->params.home_time, 4); - - get_parmeter_from_string(&str_ptr, GET_SCAN_TYPE, PTYPE_INTDEC, \ - &iscan->iscan_ex_params_p->params.scan_type, 1); - - - res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan); - - } else { - - WL_ERROR(("IWPRIV argument len = 0 \n")); - return -1; - } - -exit_proc: - - kfree(extra); - - return res; -} - - -static int -wl_iw_set_cscan( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra -) -{ - int res = -1; - iscan_info_t *iscan = g_iscan; - wlc_ssid_t ssids_local[WL_SCAN_PARAMS_SSID_MAX]; - int nssid = 0; - int nchan = 0; - cscan_tlv_t *cscan_tlv_temp; - char type; - char *str_ptr; - int tlv_size_left; -#ifdef TLV_DEBUG - int i; - char tlv_in_example[] = { 'C', 'S', 'C', 'A', 'N', ' ', \ - 0x53, 0x01, 0x00, 0x00, - 'S', - 0x00, - 'S', - 0x04, - 'B', 'R', 'C', 'M', - 'C', - 0x06, - 'P', - 0x94, - 0x11, - 'T', - 0x01 - }; -#endif - - WL_TRACE(("\n### %s: info->cmd:%x, info->flags:%x, u.data=0x%p, u.len=%d\n", - __FUNCTION__, info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length)); - - if (g_onoff == G_WLAN_SET_OFF) { - WL_TRACE(("%s: driver is not up yet after START\n", __FUNCTION__)); - return -1; - } - - if (wrqu->data.length < (strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))) { - WL_ERROR(("%s aggument=%d less %d\n", __FUNCTION__, \ - wrqu->data.length, strlen(CSCAN_COMMAND) + sizeof(cscan_tlv_t))); - return -1; - } - -#ifdef TLV_DEBUG - memcpy(extra, tlv_in_example, sizeof(tlv_in_example)); - wrqu->data.length = sizeof(tlv_in_example); - for (i = 0; i < wrqu->data.length; i++) - printf("%02X ", extra[i]); - printf("\n"); -#endif - - str_ptr = extra; - str_ptr += strlen(CSCAN_COMMAND); - tlv_size_left = wrqu->data.length - strlen(CSCAN_COMMAND); - - cscan_tlv_temp = (cscan_tlv_t *)str_ptr; - memset(ssids_local, 0, sizeof(ssids_local)); - - if ((cscan_tlv_temp->prefix == CSCAN_TLV_PREFIX) && \ - (cscan_tlv_temp->version == CSCAN_TLV_VERSION) && \ - (cscan_tlv_temp->subver == CSCAN_TLV_SUBVERSION)) - { - str_ptr += sizeof(cscan_tlv_t); - tlv_size_left -= sizeof(cscan_tlv_t); - - - if ((nssid = wl_iw_parse_ssid_list_tlv(&str_ptr, ssids_local, \ - WL_SCAN_PARAMS_SSID_MAX, &tlv_size_left)) <= 0) { - WL_ERROR(("SSID is not presented or corrupted ret=%d\n", nssid)); - goto exit_proc; - } - else { - - memset(iscan->iscan_ex_params_p, 0, iscan->iscan_ex_param_size); - - - wl_iw_iscan_prep(&iscan->iscan_ex_params_p->params, NULL); - iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION); - iscan->iscan_ex_params_p->action = htod16(WL_SCAN_ACTION_START); - iscan->iscan_ex_params_p->scan_duration = htod16(0); - - - while (tlv_size_left > 0) - { - type = str_ptr[0]; - switch (type) { - case CSCAN_TLV_TYPE_CHANNEL_IE: - - if ((nchan = wl_iw_parse_channel_list_tlv(&str_ptr, \ - &iscan->iscan_ex_params_p->params.channel_list[0], \ - WL_NUMCHANNELS, &tlv_size_left)) == -1) { - WL_ERROR(("%s missing channel list\n", \ - __FUNCTION__)); - goto exit_proc; - } - break; - case CSCAN_TLV_TYPE_NPROBE_IE: - if ((res = wl_iw_parse_data_tlv(&str_ptr, \ - &iscan->iscan_ex_params_p->params.nprobes, \ - sizeof(iscan->iscan_ex_params_p->params.nprobes), \ - type, sizeof(char), &tlv_size_left)) == -1) { - WL_ERROR(("%s return %d\n", \ - __FUNCTION__, res)); - goto exit_proc; - } - break; - case CSCAN_TLV_TYPE_ACTIVE_IE: - if ((res = wl_iw_parse_data_tlv(&str_ptr, \ - &iscan->iscan_ex_params_p->params.active_time, \ - sizeof(iscan->iscan_ex_params_p->params.active_time), \ - type, sizeof(short), &tlv_size_left)) == -1) { - WL_ERROR(("%s return %d\n", \ - __FUNCTION__, res)); - goto exit_proc; - } - break; - case CSCAN_TLV_TYPE_PASSIVE_IE: - if ((res = wl_iw_parse_data_tlv(&str_ptr, \ - &iscan->iscan_ex_params_p->params.passive_time, \ - sizeof(iscan->iscan_ex_params_p->params.passive_time), \ - type, sizeof(short), &tlv_size_left)) == -1) { - WL_ERROR(("%s return %d\n", \ - __FUNCTION__, res)); - goto exit_proc; - } - break; - case CSCAN_TLV_TYPE_HOME_IE: - if ((res = wl_iw_parse_data_tlv(&str_ptr, \ - &iscan->iscan_ex_params_p->params.home_time, \ - sizeof(iscan->iscan_ex_params_p->params.home_time), \ - type, sizeof(short), &tlv_size_left)) == -1) { - WL_ERROR(("%s return %d\n", \ - __FUNCTION__, res)); - goto exit_proc; - } - break; - case CSCAN_TLV_TYPE_STYPE_IE: - if ((res = wl_iw_parse_data_tlv(&str_ptr, \ - &iscan->iscan_ex_params_p->params.scan_type, \ - sizeof(iscan->iscan_ex_params_p->params.scan_type), \ - type, sizeof(char), &tlv_size_left)) == -1) { - WL_ERROR(("%s return %d\n", \ - __FUNCTION__, res)); - goto exit_proc; - } - break; - - default : - WL_ERROR(("%s get unkwown type %X\n", \ - __FUNCTION__, type)); - goto exit_proc; - break; - } - } - } - } - else { - WL_ERROR(("%s get wrong TLV command\n", __FUNCTION__)); - goto exit_proc; - } - - - res = wl_iw_combined_scan_set(dev, ssids_local, nssid, nchan); - -exit_proc: - return res; -} - -#endif - - - -#ifdef SOFTAP -#ifndef AP_ONLY - - -static int thr_wait_for_2nd_eth_dev(void *data) -{ - int ret = 0; - - DAEMONIZE("wl0_eth_wthread"); - - WL_TRACE(("\n>%s threda started:, PID:%x\n", __FUNCTION__, current->pid)); - - if (down_timeout(&ap_eth_sema, msecs_to_jiffies(5000)) != 0) { - WL_ERROR(("\n%s: sap_eth_sema timeout \n", __FUNCTION__)); - ret = -1; - goto fail; - } - - if (!ap_net_dev) { - WL_ERROR((" ap_net_dev is null !!!")); - ret = -1; - goto fail; - } - - WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n", - __FUNCTION__, ap_net_dev->name)); - - ap_cfg_running = TRUE; - - bcm_mdelay(500); - - - wl_iw_send_priv_event(priv_dev, "AP_SET_CFG_OK"); - -fail: - - WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__)); - - return ret; -} -#endif -#ifndef AP_ONLY -static int last_auto_channel = 6; -#endif -static int get_softap_auto_channel(struct net_device *dev, struct ap_profile *ap) -{ - int chosen = 0; - wl_uint32_list_t request; - int rescan = 0; - int retry = 0; - int updown = 0; - int ret = 0; - wlc_ssid_t null_ssid; - int res = 0; -#ifndef AP_ONLY - int iolen = 0; - int mkvar_err = 0; - int bsscfg_index = 1; - char buf[WLC_IOCTL_SMLEN]; -#endif - WL_SOFTAP(("Enter %s\n", __FUNCTION__)); - -#ifndef AP_ONLY - if (ap_cfg_running) { - ap->channel = last_auto_channel; - return res; - } -#endif - memset(&null_ssid, 0, sizeof(wlc_ssid_t)); - res |= dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)); -#ifdef AP_ONLY - res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &null_ssid, sizeof(null_ssid)); -#else - iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&null_ssid), \ - null_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); - ASSERT(iolen); - res |= dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen); -#endif - auto_channel_retry: - request.count = htod32(0); - ret = dev_wlc_ioctl(dev, WLC_START_CHANNEL_SEL, &request, sizeof(request)); - if (ret < 0) { - WL_ERROR(("can't start auto channel scan\n")); - goto fail; - } - - get_channel_retry: - bcm_mdelay(500); - - ret = dev_wlc_ioctl(dev, WLC_GET_CHANNEL_SEL, &chosen, sizeof(chosen)); - if (ret < 0 || dtoh32(chosen) == 0) { - if (retry++ < 3) - goto get_channel_retry; - else { - WL_ERROR(("can't get auto channel sel, err = %d, \ - chosen = %d\n", ret, chosen)); - goto fail; - } - } - if ((chosen == 1) && (!rescan++)) - goto auto_channel_retry; - WL_SOFTAP(("Set auto channel = %d\n", chosen)); - ap->channel = chosen; - if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown))) < 0) { - WL_ERROR(("%s fail to set up err =%d\n", __FUNCTION__, res)); - goto fail; - } -#ifndef AP_ONLY - if (!res) - last_auto_channel = ap->channel; -#endif - -fail : - return res; -} - - -static int set_ap_cfg(struct net_device *dev, struct ap_profile *ap) -{ - int updown = 0; - int channel = 0; - - wlc_ssid_t ap_ssid; - int max_assoc = 8; - - int res = 0; - int apsta_var = 0; -#ifndef AP_ONLY - int mpc = 0; - int iolen = 0; - int mkvar_err = 0; - int bsscfg_index = 1; - char buf[WLC_IOCTL_SMLEN]; -#endif - wl_iw_t *iw; - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return -1; - } - - WL_SOFTAP(("wl_iw: set ap profile:\n")); - WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); - WL_SOFTAP((" security = '%s'\n", ap->sec)); - if (ap->key[0] != '\0') - WL_SOFTAP((" key = '%s'\n", ap->key)); - WL_SOFTAP((" channel = %d\n", ap->channel)); - WL_SOFTAP((" max scb = %d\n", ap->max_scb)); - - iw = *(wl_iw_t **)netdev_priv(dev); - MUTEX_LOCK_SOFTAP_SET(iw->pub); - WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_SOFTAP_SET, "SoftAP_SET"); - WAKE_LOCK(iw->pub, WAKE_LOCK_SOFTAP_SET); - -#ifdef AP_ONLY - if (ap_cfg_running) { - wl_iw_softap_deassoc_stations(dev); - ap_cfg_running = FALSE; - } -#endif - - - if (ap_cfg_running == FALSE) { - -#ifndef AP_ONLY - - - sema_init(&ap_eth_sema, 0); - - mpc = 0; - if ((res = dev_wlc_intvar_set(dev, "mpc", mpc))) { - WL_ERROR(("%s fail to set mpc\n", __FUNCTION__)); - goto fail; - } -#endif - - updown = 0; - if ((res = dev_wlc_ioctl(dev, WLC_DOWN, &updown, sizeof(updown)))) { - WL_ERROR(("%s fail to set updown\n", __FUNCTION__)); - goto fail; - } - -#ifdef AP_ONLY - - apsta_var = 0; - if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) { - WL_ERROR(("%s fail to set apsta_var 0\n", __FUNCTION__)); - goto fail; - } - apsta_var = 1; - if ((res = dev_wlc_ioctl(dev, WLC_SET_AP, &apsta_var, sizeof(apsta_var)))) { - WL_ERROR(("%s fail to set apsta_var 1\n", __FUNCTION__)); - goto fail; - } - res = dev_wlc_ioctl(dev, WLC_GET_AP, &apsta_var, sizeof(apsta_var)); -#else - - apsta_var = 1; - iolen = wl_bssiovar_mkbuf("apsta", - bsscfg_index, &apsta_var, sizeof(apsta_var)+4, - buf, sizeof(buf), &mkvar_err); - ASSERT(iolen); - if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) < 0) { - WL_ERROR(("%s fail to set apsta \n", __FUNCTION__)); - goto fail; - } - WL_TRACE(("\n>in %s: apsta set result: %d \n", __FUNCTION__, res)); -#endif - - updown = 1; - if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown))) < 0) { - WL_ERROR(("%s fail to set apsta \n", __FUNCTION__)); - goto fail; - } - - } else { - - if (!ap_net_dev) { - WL_ERROR(("%s: ap_net_dev is null\n", __FUNCTION__)); - goto fail; - } - - res = wl_iw_softap_deassoc_stations(ap_net_dev); - - - if ((res = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) { - WL_ERROR(("%s fail to set bss down\n", __FUNCTION__)); - goto fail; - } - } - - - if ((ap->channel == 0) && (get_softap_auto_channel(dev, ap) < 0)) { - ap->channel = 1; - WL_ERROR(("%s auto channel failed, pick up channel=%d\n", \ - __FUNCTION__, ap->channel)); - - } - - channel = ap->channel; - if ((res = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel)))) { - WL_ERROR(("%s fail to set channel\n", __FUNCTION__)); - goto fail; - } - - if (ap_cfg_running == FALSE) { - updown = 0; - if ((res = dev_wlc_ioctl(dev, WLC_UP, &updown, sizeof(updown)))) { - WL_ERROR(("%s fail to set up\n", __FUNCTION__)); - goto fail; - } - } - - max_assoc = ap->max_scb; - if ((res = dev_wlc_intvar_set(dev, "maxassoc", max_assoc))) { - WL_ERROR(("%s fail to set maxassoc\n", __FUNCTION__)); - goto fail; - } - - ap_ssid.SSID_len = strlen(ap->ssid); - strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len); - - -#ifdef AP_ONLY - if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) { - WL_ERROR(("ERROR:%d in:%s, wl_iw_set_ap_security is skipped\n", \ - res, __FUNCTION__)); - goto fail; - } - wl_iw_send_priv_event(dev, "ASCII_CMD=AP_BSS_START"); - ap_cfg_running = TRUE; -#else - - iolen = wl_bssiovar_mkbuf("ssid", bsscfg_index, (char *)(&ap_ssid), - ap_ssid.SSID_len+4, buf, sizeof(buf), &mkvar_err); - ASSERT(iolen); - if ((res = dev_wlc_ioctl(dev, WLC_SET_VAR, buf, iolen)) != 0) { - WL_ERROR(("ERROR:%d in:%s, Security & BSS reconfiguration is skipped\n", \ - res, __FUNCTION__)); - goto fail; - } - if (ap_cfg_running == FALSE) { - - kernel_thread(thr_wait_for_2nd_eth_dev, 0, 0); - } else { - - - if (ap_net_dev == NULL) { - WL_ERROR(("%s ERROR: ap_net_dev is NULL !!!\n", __FUNCTION__)); - goto fail; - } - - WL_ERROR(("%s: %s Configure security & restart AP bss \n", \ - __FUNCTION__, ap_net_dev->name)); - - - if ((res = wl_iw_set_ap_security(ap_net_dev, &my_ap)) < 0) { - WL_ERROR(("%s fail to set security : %d\n", __FUNCTION__, res)); - goto fail; - } - - - if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) { - WL_ERROR(("%s fail to set bss up\n", __FUNCTION__)); - goto fail; - } - } -#endif -fail: - WAKE_UNLOCK(iw->pub, WAKE_LOCK_SOFTAP_SET); - WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_SOFTAP_SET); - MUTEX_UNLOCK_SOFTAP_SET(iw->pub); - - WL_SOFTAP(("%s exit with %d\n", __FUNCTION__, res)); - return res; -} -#endif - - - -static int wl_iw_set_ap_security(struct net_device *dev, struct ap_profile *ap) -{ - int wsec = 0; - int wpa_auth = 0; - int res = 0; - int i; - char *ptr; -#ifdef AP_ONLY - int mpc = 0; - wlc_ssid_t ap_ssid; -#endif - wl_wsec_key_t key; - - WL_SOFTAP(("\nsetting SOFTAP security mode:\n")); - WL_SOFTAP(("wl_iw: set ap profile:\n")); - WL_SOFTAP((" ssid = '%s'\n", ap->ssid)); - WL_SOFTAP((" security = '%s'\n", ap->sec)); - if (ap->key[0] != '\0') - WL_SOFTAP((" key = '%s'\n", ap->key)); - WL_SOFTAP((" channel = %d\n", ap->channel)); - WL_SOFTAP((" max scb = %d\n", ap->max_scb)); - - - if (strnicmp(ap->sec, "open", strlen("open")) == 0) { - - - wsec = 0; - res = dev_wlc_intvar_set(dev, "wsec", wsec); - wpa_auth = WPA_AUTH_DISABLED; - res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth); - - WL_SOFTAP(("=====================\n")); - WL_SOFTAP((" wsec & wpa_auth set 'OPEN', result:&d %d\n", res)); - WL_SOFTAP(("=====================\n")); - - } else if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) { - - - memset(&key, 0, sizeof(key)); - - wsec = WEP_ENABLED; - res = dev_wlc_intvar_set(dev, "wsec", wsec); - - key.index = 0; - if (wl_iw_parse_wep(ap->key, &key)) { - WL_SOFTAP(("wep key parse err!\n")); - return -1; - } - - key.index = htod32(key.index); - key.len = htod32(key.len); - key.algo = htod32(key.algo); - key.flags = htod32(key.flags); - - res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); - - wpa_auth = WPA_AUTH_DISABLED; - res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth); - - WL_SOFTAP(("=====================\n")); - WL_SOFTAP((" wsec & auth set 'WEP', result:&d %d\n", res)); - WL_SOFTAP(("=====================\n")); - - } else if (strnicmp(ap->sec, "wpa2-psk", strlen("wpa2-psk")) == 0) { - - - - wsec_pmk_t psk; - size_t key_len; - - wsec = AES_ENABLED; - dev_wlc_intvar_set(dev, "wsec", wsec); - - key_len = strlen(ap->key); - if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) { - WL_SOFTAP(("passphrase must be between %d and %d characters long\n", - WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN)); - return -1; - } - - - if (key_len < WSEC_MAX_PSK_LEN) { - unsigned char output[2*SHA1HashSize]; - char key_str_buf[WSEC_MAX_PSK_LEN+1]; - - - memset(output, 0, sizeof(output)); - pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32); - - ptr = key_str_buf; - for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) { - - sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], \ - (uint)output[i*4+1], (uint)output[i*4+2], \ - (uint)output[i*4+3]); - ptr += 8; - } - WL_SOFTAP(("%s: passphase = %s\n", __FUNCTION__, key_str_buf)); - - psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN); - memcpy(psk.key, key_str_buf, psk.key_len); - } else { - psk.key_len = htod16((ushort) key_len); - memcpy(psk.key, ap->key, key_len); - } - psk.flags = htod16(WSEC_PASSPHRASE); - dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk)); - - wpa_auth = WPA2_AUTH_PSK; - dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth); - - } else if (strnicmp(ap->sec, "wpa-psk", strlen("wpa-psk")) == 0) { - - - wsec_pmk_t psk; - size_t key_len; - - wsec = TKIP_ENABLED; - res = dev_wlc_intvar_set(dev, "wsec", wsec); - - key_len = strlen(ap->key); - if (key_len < WSEC_MIN_PSK_LEN || key_len > WSEC_MAX_PSK_LEN) { - WL_SOFTAP(("passphrase must be between %d and %d characters long\n", - WSEC_MIN_PSK_LEN, WSEC_MAX_PSK_LEN)); - return -1; - } - - - if (key_len < WSEC_MAX_PSK_LEN) { - unsigned char output[2*SHA1HashSize]; - char key_str_buf[WSEC_MAX_PSK_LEN+1]; - - WL_SOFTAP(("%s: do passhash...\n", __FUNCTION__)); - - pbkdf2_sha1(ap->key, ap->ssid, strlen(ap->ssid), 4096, output, 32); - - ptr = key_str_buf; - for (i = 0; i < (WSEC_MAX_PSK_LEN/8); i++) { - WL_SOFTAP(("[%02d]: %08x\n", i, *((unsigned int*)&output[i*4]))); - - sprintf(ptr, "%02x%02x%02x%02x", (uint)output[i*4], \ - (uint)output[i*4+1], (uint)output[i*4+2], \ - (uint)output[i*4+3]); - ptr += 8; - } - printk("%s: passphase = %s\n", __FUNCTION__, key_str_buf); - - psk.key_len = htod16((ushort)WSEC_MAX_PSK_LEN); - memcpy(psk.key, key_str_buf, psk.key_len); - } else { - psk.key_len = htod16((ushort) key_len); - memcpy(psk.key, ap->key, key_len); - } - - psk.flags = htod16(WSEC_PASSPHRASE); - res |= dev_wlc_ioctl(dev, WLC_SET_WSEC_PMK, &psk, sizeof(psk)); - - wpa_auth = WPA_AUTH_PSK; - res |= dev_wlc_intvar_set(dev, "wpa_auth", wpa_auth); - - WL_SOFTAP((" wsec & auth set 'wpa-psk' (TKIP), result:&d %d\n", res)); - } - -#ifdef AP_ONLY - ap_ssid.SSID_len = strlen(ap->ssid); - strncpy(ap_ssid.SSID, ap->ssid, ap_ssid.SSID_len); - res |= dev_wlc_ioctl(dev, WLC_SET_SSID, &ap_ssid, sizeof(ap_ssid)); - mpc = 0; - res |= dev_wlc_intvar_set(dev, "mpc", mpc); - if (strnicmp(ap->sec, "wep", strlen("wep")) == 0) { - res |= dev_wlc_ioctl(dev, WLC_SET_KEY, &key, sizeof(key)); - } -#endif - return res; -} - - - -int get_parmeter_from_string( - char **str_ptr, const char *token, - int param_type, void *dst, int param_max_len) -{ - char int_str[7] = "0"; - int parm_str_len; - char *param_str_begin; - char *param_str_end; - char *orig_str = *str_ptr; - - if ((*str_ptr) && !strncmp(*str_ptr, token, strlen(token))) { - - strsep(str_ptr, "=,"); - param_str_begin = *str_ptr; - strsep(str_ptr, "=,"); - - if (*str_ptr == NULL) { - - parm_str_len = strlen(param_str_begin); - } else { - param_str_end = *str_ptr-1; - parm_str_len = param_str_end - param_str_begin; - } - - WL_TRACE((" 'token:%s', len:%d, ", token, parm_str_len)); - - if (parm_str_len > param_max_len) { - WL_ERROR((" WARNING: extracted param len:%d is > MAX:%d\n", - parm_str_len, param_max_len)); - - parm_str_len = param_max_len; - } - - switch (param_type) { - - case PTYPE_INTDEC: { - - int *pdst_int = dst; - char *eptr; - if (parm_str_len > sizeof(int_str)) - parm_str_len = sizeof(int_str); - - memcpy(int_str, param_str_begin, parm_str_len); - - *pdst_int = simple_strtoul(int_str, &eptr, 10); - - WL_TRACE((" written as integer:%d\n", *pdst_int)); - } - break; - case PTYPE_STR_HEX: { - u8 *buf = dst; - - param_max_len = param_max_len >> 1; - hstr_2_buf(param_str_begin, buf, param_max_len); - print_buf(buf, param_max_len, 0); - } - break; - default: - - memcpy(dst, param_str_begin, parm_str_len); - *((char *)dst + parm_str_len) = 0; - WL_ERROR((" written as a string:%s\n", (char *)dst)); - break; - - } - - return 0; - } else { - WL_ERROR(("\n %s: ERROR: can't find token:%s in str:%s \n", - __FUNCTION__, token, orig_str)); - - return -1; - } -} - - -static int wl_iw_softap_deassoc_stations(struct net_device *dev) -{ - int i; - int res = 0; - - char mac_buf[128] = {0}; - struct maclist *assoc_maclist = (struct maclist *) mac_buf; - - memset(assoc_maclist, 0, sizeof(mac_buf)); - assoc_maclist->count = 8; - - res = dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 128); - if (res != 0) { - - WL_SOFTAP((" Error:%d in :%s, Couldn't get ASSOC List\n", res, __FUNCTION__)); - return res; - } - - if (assoc_maclist->count) - for (i = 0; i < assoc_maclist->count; i++) { - scb_val_t scbval; - scbval.val = htod32(1); - - bcopy(&assoc_maclist->ea[i], &scbval.ea, ETHER_ADDR_LEN); - - WL_SOFTAP(("deauth STA:%d \n", i)); - res |= dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, - &scbval, sizeof(scb_val_t)); - - } else WL_SOFTAP((" STA ASSOC list is empty\n")); - - - if (res != 0) - WL_SOFTAP((" Error:%d in :%s\n", res, __FUNCTION__)); - else if (assoc_maclist->count) { - - bcm_mdelay(200); - } - return res; -} - - - -static int iwpriv_softap_stop(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - int res = 0; - wl_iw_t *iw; - - WL_SOFTAP(("got iwpriv AP_BSS_STOP \n")); - - if ((!dev) && (!ap_net_dev)) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return res; - } - - iw = *(wl_iw_t **)netdev_priv(dev); - MUTEX_LOCK_SOFTAP_SET(iw->pub); - WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_SOFTAP_STOP, "SoftAP_STOP"); - WAKE_LOCK(iw->pub, WAKE_LOCK_SOFTAP_STOP); - - if ((ap_cfg_running == TRUE)) { -#ifdef AP_ONLY - wl_iw_softap_deassoc_stations(dev); -#else - wl_iw_softap_deassoc_stations(ap_net_dev); - - if ((res = dev_iw_write_cfg1_bss_var(dev, 2)) < 0) - WL_ERROR(("%s failed to del BSS err = %d", __FUNCTION__, res)); -#endif - - - bcm_mdelay(100); - - wrqu->data.length = 0; - ap_cfg_running = FALSE; - } - else - WL_ERROR(("%s: was called when SoftAP is OFF : move on\n", __FUNCTION__)); - - WAKE_UNLOCK(iw->pub, WAKE_LOCK_SOFTAP_STOP); - WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_SOFTAP_STOP); - MUTEX_UNLOCK_SOFTAP_SET(iw->pub); - - WL_SOFTAP(("%s Done with %d\n", __FUNCTION__, res)); - return res; -} - - - -static int iwpriv_fw_reload(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - - int ret = -1; - char extra[256]; - char *fwstr = fw_path ; - - WL_SOFTAP(("current firmware_path[]=%s\n", fwstr)); - - WL_TRACE((">Got FW_RELOAD cmd:" - "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d, \ - fw_path:%p, len:%d \n", - info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length, fwstr, strlen(fwstr))); - - - if ((wrqu->data.length > 4) && (wrqu->data.length < sizeof(extra))) { - - char *str_ptr; - - if (copy_from_user(extra, wrqu->data.pointer, wrqu->data.length)) { - ret = -EFAULT; - goto exit_proc; - } - - - extra[wrqu->data.length] = 8; - str_ptr = extra; - - if (get_parmeter_from_string(&str_ptr, "FW_PATH=", PTYPE_STRING, fwstr, 255) != 0) { - WL_ERROR(("Error: extracting FW_PATH='' string\n")); - goto exit_proc; - } - - if (strstr(fwstr, "apsta") != NULL) { - WL_SOFTAP(("GOT APSTA FIRMWARE\n")); - ap_fw_loaded = TRUE; - } else { - WL_SOFTAP(("GOT STA FIRMWARE\n")); - ap_fw_loaded = FALSE; - } - - WL_SOFTAP(("SET firmware_path[]=%s , str_p:%p\n", fwstr, fwstr)); - ret = 0; - } else { - WL_ERROR(("Error: ivalid param len:%d\n", wrqu->data.length)); - } - -exit_proc: - return ret; -} -#ifdef SOFTAP - -static int iwpriv_wpasupp_loop_tst(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *ext) -{ - int res = 0; - char *params = NULL; - - WL_TRACE((">Got IWPRIV wp_supp loopback cmd test:" - "info->cmd:%x, info->flags:%x, u.data:%p, u.len:%d\n", - info->cmd, info->flags, - wrqu->data.pointer, wrqu->data.length)); - - if (wrqu->data.length != 0) { - - if (!(params = kmalloc(wrqu->data.length+1, GFP_KERNEL))) - return -ENOMEM; - - - if (copy_from_user(params, wrqu->data.pointer, wrqu->data.length)) { - kfree(params); - return -EFAULT; - } - - params[wrqu->data.length] = 0; - WL_SOFTAP(("\n>> copied from user:\n %s\n", params)); - } else { - WL_ERROR(("ERROR param length is 0\n")); - return -EFAULT; - } - - - res = wl_iw_send_priv_event(dev, params); - kfree(params); - - return res; -} -#endif - - -static int - iwpriv_en_ap_bss( - struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - int res = 0; - wl_iw_t *iw; - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return -1; - } - - WL_TRACE(("%s: rcvd IWPRIV IOCTL: for dev:%s\n", __FUNCTION__, dev->name)); - - iw = *(wl_iw_t **)netdev_priv(dev); - MUTEX_LOCK_SOFTAP_SET(iw->pub); - WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_SOFTAP_START, "SoftAP_START"); - WAKE_LOCK(iw->pub, WAKE_LOCK_SOFTAP_START); - - -#ifndef AP_ONLY - if ((res = wl_iw_set_ap_security(dev, &my_ap)) != 0) { - WL_ERROR((" %s ERROR setting SOFTAP security in :%d\n", __FUNCTION__, res)); - } - else { - - if ((res = dev_iw_write_cfg1_bss_var(dev, 1)) < 0) - WL_ERROR(("%s fail to set bss up err=%d\n", __FUNCTION__, res)); - else - - bcm_mdelay(100); - } - -#endif - - WL_SOFTAP(("%s done with res %d \n", __FUNCTION__, res)); - WAKE_UNLOCK(iw->pub, WAKE_LOCK_SOFTAP_START); - WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_SOFTAP_START); - MUTEX_UNLOCK_SOFTAP_SET(iw->pub); - return res; -} - -static int -get_assoc_sta_list(struct net_device *dev, char *buf, int len) -{ - - WL_TRACE(("calling dev_wlc_ioctl(dev:%p, cmd:%d, buf:%p, len:%d)\n", - dev, WLC_GET_ASSOCLIST, buf, len)); - - dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, buf, len); - - return 0; -} - - -static int -set_ap_mac_list(struct net_device *dev, char *buf) -{ - struct mac_list_set *mac_list_set = (struct mac_list_set *)buf; - struct maclist *white_maclist = (struct maclist *)&mac_list_set->white_list; - struct maclist *black_maclist = (struct maclist *)&mac_list_set->black_list; - int mac_mode = mac_list_set->mode; - int length; - int i; - - ap_macmode = mac_mode; - if (mac_mode == MACLIST_MODE_DISABLED) { - - bzero(&ap_black_list, sizeof(struct mflist)); - - - dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); - } else { - scb_val_t scbval; - char mac_buf[256] = {0}; - struct maclist *assoc_maclist = (struct maclist *) mac_buf; - - mac_mode = MACLIST_MODE_ALLOW; - - dev_wlc_ioctl(dev, WLC_SET_MACMODE, &mac_mode, sizeof(mac_mode)); - - - length = sizeof(white_maclist->count)+white_maclist->count*ETHER_ADDR_LEN; - dev_wlc_ioctl(dev, WLC_SET_MACLIST, white_maclist, length); - WL_SOFTAP(("White List, length %d:\n", length)); - for (i = 0; i < white_maclist->count; i++) - WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, white_maclist->ea[i].octet[0], white_maclist->ea[i].octet[1], \ - white_maclist->ea[i].octet[2], \ - white_maclist->ea[i].octet[3], white_maclist->ea[i].octet[4], \ - white_maclist->ea[i].octet[5])); - - - bcopy(black_maclist, &ap_black_list, sizeof(ap_black_list)); - - WL_SOFTAP(("Black List, size %d:\n", sizeof(ap_black_list))); - for (i = 0; i < ap_black_list.count; i++) - WL_SOFTAP(("mac %d: %02X:%02X:%02X:%02X:%02X:%02X\n", - i, ap_black_list.ea[i].octet[0], ap_black_list.ea[i].octet[1], \ - ap_black_list.ea[i].octet[2], \ - ap_black_list.ea[i].octet[3], \ - ap_black_list.ea[i].octet[4], ap_black_list.ea[i].octet[5])); - - - dev_wlc_ioctl(dev, WLC_GET_ASSOCLIST, assoc_maclist, 256); - if (assoc_maclist->count) { - int j; - for (i = 0; i < assoc_maclist->count; i++) { - for (j = 0; j < white_maclist->count; j++) { - if (!bcmp(&assoc_maclist->ea[i], &white_maclist->ea[j], \ - ETHER_ADDR_LEN)) { - WL_SOFTAP(("match allow, let it be\n")); - break; - } - } - if (j == white_maclist->count) { - WL_SOFTAP(("match black, deauth it\n")); - scbval.val = htod32(1); - bcopy(&assoc_maclist->ea[i], &scbval.ea, \ - ETHER_ADDR_LEN); - dev_wlc_ioctl(dev, \ - WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, - sizeof(scb_val_t)); - } - } - } - } - return 0; -} -#endif - - -#ifdef SOFTAP -int set_macfilt_from_string(struct mflist *pmflist, char **param_str) -{ - return 0; -} -#endif - - -#ifdef SOFTAP -#define PARAM_OFFSET PROFILE_OFFSET - -int wl_iw_process_private_ascii_cmd( - struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *dwrq, - char *cmd_str) -{ - int ret = 0; - char *sub_cmd = cmd_str + PROFILE_OFFSET + strlen("ASCII_CMD="); - - WL_SOFTAP(("\n %s: ASCII_CMD: offs_0:%s, offset_32:\n'%s'\n", - __FUNCTION__, cmd_str, cmd_str + PROFILE_OFFSET)); - - if (strnicmp(sub_cmd, "AP_CFG", strlen("AP_CFG")) == 0) { - - WL_SOFTAP((" AP_CFG \n")); - - - if (init_ap_profile_from_string(cmd_str+PROFILE_OFFSET, &my_ap) != 0) { - WL_ERROR(("ERROR: SoftAP CFG prams !\n")); - ret = -1; - } else { - ret = set_ap_cfg(dev, &my_ap); - } - - } else if (strnicmp(sub_cmd, "AP_BSS_START", strlen("AP_BSS_START")) == 0) { - - WL_SOFTAP(("\n SOFTAP - ENABLE BSS \n")); - - - WL_SOFTAP(("\n!!! got 'WL_AP_EN_BSS' from WPA supplicant, dev:%s\n", dev->name)); - -#ifndef AP_ONLY - if (ap_net_dev == NULL) { - printf("\n ERROR: SOFTAP net_dev* is NULL !!!\n"); - } else { - - if ((ret = iwpriv_en_ap_bss(ap_net_dev, info, dwrq, cmd_str)) < 0) - WL_ERROR(("%s line %d fail to set bss up\n", \ - __FUNCTION__, __LINE__)); - } -#else - if ((ret = iwpriv_en_ap_bss(dev, info, dwrq, cmd_str)) < 0) - WL_ERROR(("%s line %d fail to set bss up\n", \ - __FUNCTION__, __LINE__)); -#endif - } else if (strnicmp(sub_cmd, "ASSOC_LST", strlen("ASSOC_LST")) == 0) { - - - - } else if (strnicmp(sub_cmd, "AP_BSS_STOP", strlen("AP_BSS_STOP")) == 0) { - - WL_SOFTAP((" \n temp DOWN SOFTAP\n")); -#ifndef AP_ONLY - if ((ret = dev_iw_write_cfg1_bss_var(dev, 0)) < 0) { - WL_ERROR(("%s line %d fail to set bss down\n", \ - __FUNCTION__, __LINE__)); - } -#endif - } - - return ret; - -} -#endif -static int wl_iw_set_priv( - struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *ext -) -{ - int ret = 0; - char * extra; - - wl_iw_t *iw = *(wl_iw_t **)netdev_priv(dev); - if (!(extra = kmalloc(dwrq->length, GFP_KERNEL))) - return -ENOMEM; - - if (copy_from_user(extra, dwrq->pointer, dwrq->length)) { - kfree(extra); - return -EFAULT; - } - - WL_TRACE(("%s: SIOCSIWPRIV request %s, info->cmd:%x, info->flags:%d\n dwrq->length:%d\n", - dev->name, extra, info->cmd, info->flags, dwrq->length)); - - - if (dwrq->length && extra) { - WAKE_LOCK_INIT(iw->pub, WAKE_LOCK_PRIV, "wl_iw_set_priv"); - WAKE_LOCK(iw->pub, WAKE_LOCK_PRIV); - - if (g_onoff == G_WLAN_SET_OFF) { - if (strnicmp(extra, "START", strlen("START")) != 0) { - WL_ERROR(("%s First IOCTL after stop is NOT START \n", \ - __FUNCTION__)); - WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV); - WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV); - kfree(extra); - return -EFAULT; - } else { - wl_iw_control_wl_on(dev, info); - WL_TRACE(("%s, Received regular START command\n", __FUNCTION__)); - } - } - - if (strnicmp(extra, "SCAN-ACTIVE", strlen("SCAN-ACTIVE")) == 0) { -#ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS - WL_TRACE(("%s: active scan setting suppressed\n", dev->name)); -#else - ret = wl_iw_set_active_scan(dev, info, (union iwreq_data *)dwrq, extra); -#endif - } - else if (strnicmp(extra, "SCAN-PASSIVE", strlen("SCAN-PASSIVE")) == 0) -#ifdef ENABLE_ACTIVE_PASSIVE_SCAN_SUPPRESS - WL_TRACE(("%s: passive scan setting suppressed\n", dev->name)); -#else - ret = wl_iw_set_passive_scan(dev, info, (union iwreq_data *)dwrq, extra); -#endif - else if (strnicmp(extra, "RSSI", strlen("RSSI")) == 0) - ret = wl_iw_get_rssi(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "LINKSPEED", strlen("LINKSPEED")) == 0) - ret = wl_iw_get_link_speed(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "MACADDR", strlen("MACADDR")) == 0) - ret = wl_iw_get_macaddr(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "COUNTRY", strlen("COUNTRY")) == 0) - ret = wl_iw_set_country(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "STOP", strlen("STOP")) == 0) - ret = wl_iw_control_wl_off(dev, info); - else if (strnicmp(extra, BAND_GET_CMD, strlen(BAND_GET_CMD)) == 0) - ret = wl_iw_get_band(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, BAND_SET_CMD, strlen(BAND_SET_CMD)) == 0) - ret = wl_iw_set_band(dev, info, (union iwreq_data *)dwrq, extra); -#if defined(CSCAN) - - else if (strnicmp(extra, CSCAN_COMMAND, strlen(CSCAN_COMMAND)) == 0) - ret = wl_iw_set_cscan(dev, info, (union iwreq_data *)dwrq, extra); -#endif -#ifdef CUSTOMER_HW2 - else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) - ret = wl_iw_set_power_mode(dev, info, (union iwreq_data *)dwrq, extra); - else if (strnicmp(extra, "BTCOEXMODE", strlen("BTCOEXMODE")) == 0) - ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); -#else - else if (strnicmp(extra, "POWERMODE", strlen("POWERMODE")) == 0) - ret = wl_iw_set_btcoex_dhcp(dev, info, (union iwreq_data *)dwrq, extra); -#endif -#ifdef SOFTAP - else if (strnicmp(extra, "ASCII_CMD", strlen("ASCII_CMD")) == 0) { - - wl_iw_process_private_ascii_cmd(dev, info, (union iwreq_data *)dwrq, extra); - } - else if (strnicmp(extra, "AP_MAC_LIST_SET", strlen("AP_MAC_LIST_SET")) == 0) { - WL_SOFTAP(("penguin, set AP_MAC_LIST_SET\n")); - set_ap_mac_list(dev, (extra + PROFILE_OFFSET)); - } -#endif - else { - WL_TRACE(("Unkown PRIVATE command %s\n", extra)); - snprintf(extra, MAX_WX_STRING, "OK"); - dwrq->length = strlen("OK") + 1; - WL_ERROR(("Unkown PRIVATE command, ignored\n")); - } - WAKE_UNLOCK(iw->pub, WAKE_LOCK_PRIV); - WAKE_LOCK_DESTROY(iw->pub, WAKE_LOCK_PRIV); - } - - if (extra) { - if (copy_to_user(dwrq->pointer, extra, dwrq->length)) { - kfree(extra); - return -EFAULT; - } - - kfree(extra); - } - - return ret; -} - -static const iw_handler wl_iw_handler[] = -{ - (iw_handler) wl_iw_config_commit, - (iw_handler) wl_iw_get_name, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_set_freq, - (iw_handler) wl_iw_get_freq, - (iw_handler) wl_iw_set_mode, - (iw_handler) wl_iw_get_mode, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_get_range, - (iw_handler) wl_iw_set_priv, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_set_spy, - (iw_handler) wl_iw_get_spy, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_set_wap, - (iw_handler) wl_iw_get_wap, -#if WIRELESS_EXT > 17 - (iw_handler) wl_iw_mlme, -#else - (iw_handler) NULL, -#endif -#if defined(WL_IW_USE_ISCAN) - (iw_handler) wl_iw_iscan_get_aplist, -#else - (iw_handler) wl_iw_get_aplist, -#endif -#if WIRELESS_EXT > 13 -#if defined(WL_IW_USE_ISCAN) - (iw_handler) wl_iw_iscan_set_scan, - (iw_handler) wl_iw_iscan_get_scan, -#else - (iw_handler) wl_iw_set_scan, - (iw_handler) wl_iw_get_scan, -#endif -#else - (iw_handler) NULL, - (iw_handler) NULL, -#endif - (iw_handler) wl_iw_set_essid, - (iw_handler) wl_iw_get_essid, - (iw_handler) wl_iw_set_nick, - (iw_handler) wl_iw_get_nick, - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_set_rate, - (iw_handler) wl_iw_get_rate, - (iw_handler) wl_iw_set_rts, - (iw_handler) wl_iw_get_rts, - (iw_handler) wl_iw_set_frag, - (iw_handler) wl_iw_get_frag, - (iw_handler) wl_iw_set_txpow, - (iw_handler) wl_iw_get_txpow, -#if WIRELESS_EXT > 10 - (iw_handler) wl_iw_set_retry, - (iw_handler) wl_iw_get_retry, -#endif - (iw_handler) wl_iw_set_encode, - (iw_handler) wl_iw_get_encode, - (iw_handler) wl_iw_set_power, - (iw_handler) wl_iw_get_power, -#if WIRELESS_EXT > 17 - (iw_handler) NULL, - (iw_handler) NULL, - (iw_handler) wl_iw_set_wpaie, - (iw_handler) wl_iw_get_wpaie, - (iw_handler) wl_iw_set_wpaauth, - (iw_handler) wl_iw_get_wpaauth, - (iw_handler) wl_iw_set_encodeext, - (iw_handler) wl_iw_get_encodeext, -#ifdef BCMWPA2 - (iw_handler) wl_iw_set_pmksa, -#endif -#endif -}; - -#if WIRELESS_EXT > 12 -static const iw_handler wl_iw_priv_handler[] = { - NULL, - (iw_handler)wl_iw_set_active_scan, - NULL, - (iw_handler)wl_iw_get_rssi, - NULL, - (iw_handler)wl_iw_set_passive_scan, - NULL, - (iw_handler)wl_iw_get_link_speed, - NULL, - (iw_handler)wl_iw_get_macaddr, - NULL, - (iw_handler)wl_iw_control_wl_off, - NULL, - (iw_handler)wl_iw_control_wl_on, -#ifdef SOFTAP - - - NULL, - (iw_handler)iwpriv_set_ap_config, - - - - NULL, - (iw_handler)iwpriv_get_assoc_list, - - - NULL, - (iw_handler)iwpriv_set_mac_filters, - - - NULL, - (iw_handler)iwpriv_en_ap_bss, - - - NULL, - (iw_handler)iwpriv_wpasupp_loop_tst, - - NULL, - (iw_handler)iwpriv_softap_stop, - - NULL, - (iw_handler)iwpriv_fw_reload, -#endif -#if defined(CSCAN) - - NULL, - (iw_handler)iwpriv_set_cscan -#endif -}; - -static const struct iw_priv_args wl_iw_priv_args[] = -{ - { - WL_IW_SET_ACTIVE_SCAN, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "SCAN-ACTIVE" - }, - { - WL_IW_GET_RSSI, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "RSSI" - }, - { - WL_IW_SET_PASSIVE_SCAN, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "SCAN-PASSIVE" - }, - { - WL_IW_GET_LINK_SPEED, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "LINKSPEED" - }, - { - WL_IW_GET_CURR_MACADDR, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "Macaddr" - }, - { - WL_IW_SET_STOP, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "STOP" - }, - { - WL_IW_SET_START, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "START" - }, - -#ifdef SOFTAP - - - { - WL_SET_AP_CFG, - IW_PRIV_TYPE_CHAR | 256, - 0, - "AP_SET_CFG" - }, - - { - WL_AP_STA_LIST, - 0, - IW_PRIV_TYPE_CHAR | 0, - "AP_GET_STA_LIST" - }, - - { - WL_AP_MAC_FLTR, - IW_PRIV_TYPE_CHAR | 256, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, - "AP_SET_MAC_FLTR" - }, - - { - WL_AP_BSS_START, - 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - "AP_BSS_START" - }, - - { - AP_LPB_CMD, - IW_PRIV_TYPE_CHAR | 256, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, - "AP_LPB_CMD" - }, - - { - WL_AP_STOP, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, - "AP_BSS_STOP" - }, - { - WL_FW_RELOAD, - IW_PRIV_TYPE_CHAR | 256, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 0, - "WL_FW_RELOAD" - }, -#endif -#if defined(CSCAN) - { - WL_COMBO_SCAN, - IW_PRIV_TYPE_CHAR | 1024, - 0, - "CSCAN" - }, -#endif - }; - -const struct iw_handler_def wl_iw_handler_def = -{ - .num_standard = ARRAYSIZE(wl_iw_handler), - .standard = (iw_handler *) wl_iw_handler, - .num_private = ARRAYSIZE(wl_iw_priv_handler), - .num_private_args = ARRAY_SIZE(wl_iw_priv_args), - .private = (iw_handler *)wl_iw_priv_handler, - .private_args = (void *) wl_iw_priv_args, - -#if WIRELESS_EXT >= 19 - get_wireless_stats: dhd_get_wireless_stats, -#endif - }; -#endif - - - -int wl_iw_ioctl( - struct net_device *dev, - struct ifreq *rq, - int cmd -) -{ - struct iwreq *wrq = (struct iwreq *) rq; - struct iw_request_info info; - iw_handler handler; - char *extra = NULL; - int token_size = 1, max_tokens = 0, ret = 0; - - WL_TRACE(("\n%s, cmd:%x alled via dhd->do_ioctl()entry point\n", __FUNCTION__, cmd)); - if (cmd < SIOCIWFIRST || - IW_IOCTL_IDX(cmd) >= ARRAYSIZE(wl_iw_handler) || - !(handler = wl_iw_handler[IW_IOCTL_IDX(cmd)])) { - WL_ERROR(("%s: error in cmd=%x : not supported\n", __FUNCTION__, cmd)); - return -EOPNOTSUPP; - } - - switch (cmd) { - - case SIOCSIWESSID: - case SIOCGIWESSID: - case SIOCSIWNICKN: - case SIOCGIWNICKN: - max_tokens = IW_ESSID_MAX_SIZE + 1; - break; - - case SIOCSIWENCODE: - case SIOCGIWENCODE: -#if WIRELESS_EXT > 17 - case SIOCSIWENCODEEXT: - case SIOCGIWENCODEEXT: -#endif - max_tokens = wrq->u.data.length; - break; - - case SIOCGIWRANGE: - - max_tokens = sizeof(struct iw_range) + 500; - break; - - case SIOCGIWAPLIST: - token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality); - max_tokens = IW_MAX_AP; - break; - -#if WIRELESS_EXT > 13 - case SIOCGIWSCAN: -#if defined(WL_IW_USE_ISCAN) - if (g_iscan) - max_tokens = wrq->u.data.length; - else -#endif - max_tokens = IW_SCAN_MAX_DATA; - break; -#endif - - case SIOCSIWSPY: - token_size = sizeof(struct sockaddr); - max_tokens = IW_MAX_SPY; - break; - - case SIOCGIWSPY: - token_size = sizeof(struct sockaddr) + sizeof(struct iw_quality); - max_tokens = IW_MAX_SPY; - break; - -#if WIRELESS_EXT > 17 - case SIOCSIWPMKSA: - case SIOCSIWGENIE: -#endif - case SIOCSIWPRIV: - max_tokens = wrq->u.data.length; - break; - } - - if (max_tokens && wrq->u.data.pointer) { - if (wrq->u.data.length > max_tokens) { - WL_ERROR(("%s: error in cmd=%x wrq->u.data.length=%d > max_tokens=%d\n", \ - __FUNCTION__, cmd, wrq->u.data.length, max_tokens)); - return -E2BIG; - } - if (!(extra = kmalloc(max_tokens * token_size, GFP_KERNEL))) - return -ENOMEM; - - if (copy_from_user(extra, wrq->u.data.pointer, wrq->u.data.length * token_size)) { - kfree(extra); - return -EFAULT; - } - } - - info.cmd = cmd; - info.flags = 0; - - ret = handler(dev, &info, &wrq->u, extra); - - if (extra) { - if (copy_to_user(wrq->u.data.pointer, extra, wrq->u.data.length * token_size)) { - kfree(extra); - return -EFAULT; - } - - kfree(extra); - } - - return ret; -} - - -bool -wl_iw_conn_status_str(uint32 event_type, uint32 status, uint32 reason, - char* stringBuf, uint buflen) -{ - typedef struct conn_fail_event_map_t { - uint32 inEvent; - uint32 inStatus; - uint32 inReason; - const char* outName; - const char* outCause; - } conn_fail_event_map_t; - - -# define WL_IW_DONT_CARE 9999 - const conn_fail_event_map_t event_map [] = { - - - {WLC_E_SET_SSID, WLC_E_STATUS_SUCCESS, WL_IW_DONT_CARE, - "Conn", "Success"}, - {WLC_E_SET_SSID, WLC_E_STATUS_NO_NETWORKS, WL_IW_DONT_CARE, - "Conn", "NoNetworks"}, - {WLC_E_SET_SSID, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, - "Conn", "ConfigMismatch"}, - {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_PRUNE_ENCR_MISMATCH, - "Conn", "EncrypMismatch"}, - {WLC_E_PRUNE, WL_IW_DONT_CARE, WLC_E_RSN_MISMATCH, - "Conn", "RsnMismatch"}, - {WLC_E_AUTH, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE, - "Conn", "AuthTimeout"}, - {WLC_E_AUTH, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, - "Conn", "AuthFail"}, - {WLC_E_AUTH, WLC_E_STATUS_NO_ACK, WL_IW_DONT_CARE, - "Conn", "AuthNoAck"}, - {WLC_E_REASSOC, WLC_E_STATUS_FAIL, WL_IW_DONT_CARE, - "Conn", "ReassocFail"}, - {WLC_E_REASSOC, WLC_E_STATUS_TIMEOUT, WL_IW_DONT_CARE, - "Conn", "ReassocTimeout"}, - {WLC_E_REASSOC, WLC_E_STATUS_ABORT, WL_IW_DONT_CARE, - "Conn", "ReassocAbort"}, - {WLC_E_PSK_SUP, WLC_SUP_KEYED, WL_IW_DONT_CARE, - "Sup", "ConnSuccess"}, - {WLC_E_PSK_SUP, WL_IW_DONT_CARE, WL_IW_DONT_CARE, - "Sup", "WpaHandshakeFail"}, - {WLC_E_DEAUTH_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE, - "Conn", "Deauth"}, - {WLC_E_DISASSOC_IND, WL_IW_DONT_CARE, WL_IW_DONT_CARE, - "Conn", "DisassocInd"}, - {WLC_E_DISASSOC, WL_IW_DONT_CARE, WL_IW_DONT_CARE, - "Conn", "Disassoc"} - }; - - const char* name = ""; - const char* cause = NULL; - int i; - - - for (i = 0; i < sizeof(event_map)/sizeof(event_map[0]); i++) { - const conn_fail_event_map_t* row = &event_map[i]; - if (row->inEvent == event_type && - (row->inStatus == status || row->inStatus == WL_IW_DONT_CARE) && - (row->inReason == reason || row->inReason == WL_IW_DONT_CARE)) { - name = row->outName; - cause = row->outCause; - break; - } - } - - - if (cause) { - memset(stringBuf, 0, buflen); - snprintf(stringBuf, buflen, "%s %s %02d %02d", - name, cause, status, reason); - WL_INFORM(("Connection status: %s\n", stringBuf)); - return TRUE; - } else { - return FALSE; - } -} - -#if WIRELESS_EXT > 14 - -static bool -wl_iw_check_conn_fail(wl_event_msg_t *e, char* stringBuf, uint buflen) -{ - uint32 event = ntoh32(e->event_type); - uint32 status = ntoh32(e->status); - uint32 reason = ntoh32(e->reason); - - if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) { - return TRUE; - } - else - return FALSE; -} -#endif - -#ifndef IW_CUSTOM_MAX -#define IW_CUSTOM_MAX 256 -#endif - -void -wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data) -{ -#if WIRELESS_EXT > 13 - union iwreq_data wrqu; - char extra[IW_CUSTOM_MAX + 1]; - int cmd = 0; - uint32 event_type = ntoh32(e->event_type); - uint16 flags = ntoh16(e->flags); - uint32 datalen = ntoh32(e->datalen); - uint32 status = ntoh32(e->status); - wl_iw_t *iw; - uint32 toto; - - memset(&wrqu, 0, sizeof(wrqu)); - memset(extra, 0, sizeof(extra)); - iw = 0; - - if (!dev) { - WL_ERROR(("%s: dev is null\n", __FUNCTION__)); - return; - } - - iw = *(wl_iw_t **)netdev_priv(dev); - - WL_TRACE(("%s: dev=%s event=%d \n", __FUNCTION__, dev->name, event_type)); - - - switch (event_type) { -#if defined(SOFTAP) - case WLC_E_PRUNE: - if (ap_cfg_running) { - char *macaddr = (char *)&e->addr; - WL_SOFTAP(("PRUNE received, %02X:%02X:%02X:%02X:%02X:%02X!\n", - macaddr[0], macaddr[1], macaddr[2], macaddr[3], \ - macaddr[4], macaddr[5])); - - - if (ap_macmode) - { - int i; - for (i = 0; i < ap_black_list.count; i++) { - if (!bcmp(macaddr, &ap_black_list.ea[i], \ - sizeof(struct ether_addr))) { - WL_SOFTAP(("mac in black list, ignore it\n")); - break; - } - } - - if (i == ap_black_list.count) { - - char mac_buf[32] = {0}; - sprintf(mac_buf, "STA_BLOCK %02X:%02X:%02X:%02X:%02X:%02X", - macaddr[0], macaddr[1], macaddr[2], - macaddr[3], macaddr[4], macaddr[5]); - wl_iw_send_priv_event(priv_dev, mac_buf); - } - } - } - break; -#endif - case WLC_E_TXFAIL: - cmd = IWEVTXDROP; - memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - break; -#if WIRELESS_EXT > 14 - case WLC_E_JOIN: - case WLC_E_ASSOC_IND: - case WLC_E_REASSOC_IND: -#if defined(SOFTAP) - WL_SOFTAP(("STA connect received %d\n", event_type)); - if (ap_cfg_running) { - wl_iw_send_priv_event(priv_dev, "STA_JOIN"); - return; - } -#endif - memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - cmd = IWEVREGISTERED; - break; - case WLC_E_DEAUTH_IND: - case WLC_E_DISASSOC_IND: -#if defined(SOFTAP) - WL_SOFTAP(("STA disconnect received %d\n", event_type)); - if (ap_cfg_running) { - wl_iw_send_priv_event(priv_dev, "STA_LEAVE"); - return; - } -#endif - cmd = SIOCGIWAP; - bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - bzero(&extra, ETHER_ADDR_LEN); - break; - case WLC_E_LINK: - case WLC_E_NDIS_LINK: - cmd = SIOCGIWAP; - if (!(flags & WLC_EVENT_MSG_LINK)) { - - -#ifdef SOFTAP -#ifdef AP_ONLY - if (ap_cfg_running) { -#else - if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) { -#endif - - WL_SOFTAP(("AP DOWN %d\n", event_type)); - wl_iw_send_priv_event(priv_dev, "AP_DOWN"); - } else { - WL_TRACE(("STA_Link Down\n")); - g_ss_cache_ctrl.m_link_down = 1; - } -#else - g_ss_cache_ctrl.m_link_down = 1; -#endif - WL_TRACE(("Link Down\n")); - - bzero(wrqu.addr.sa_data, ETHER_ADDR_LEN); - bzero(&extra, ETHER_ADDR_LEN); - WAKE_LOCK_TIMEOUT(iw->pub, WAKE_LOCK_LINK_DOWN_TMOUT, 20 * HZ); - } - else { - - memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN); - g_ss_cache_ctrl.m_link_down = 0; - - memcpy(g_ss_cache_ctrl.m_active_bssid, &e->addr, ETHER_ADDR_LEN); -#ifdef SOFTAP - -#ifdef AP_ONLY - if (ap_cfg_running) { -#else - if (ap_cfg_running && !strncmp(dev->name, "wl0.1", 5)) { -#endif - - WL_SOFTAP(("AP UP %d\n", event_type)); - wl_iw_send_priv_event(priv_dev, "AP_UP"); - } else { - WL_TRACE(("STA_LINK_UP\n")); - } -#else -#endif - WL_TRACE(("Link UP\n")); - - } - wrqu.addr.sa_family = ARPHRD_ETHER; - break; - case WLC_E_ACTION_FRAME: - cmd = IWEVCUSTOM; - if (datalen + 1 <= sizeof(extra)) { - wrqu.data.length = datalen + 1; - extra[0] = WLC_E_ACTION_FRAME; - memcpy(&extra[1], data, datalen); - WL_TRACE(("WLC_E_ACTION_FRAME len %d \n", wrqu.data.length)); - } - break; - - case WLC_E_ACTION_FRAME_COMPLETE: - cmd = IWEVCUSTOM; - memcpy(&toto, data, 4); - if (sizeof(status) + 1 <= sizeof(extra)) { - wrqu.data.length = sizeof(status) + 1; - extra[0] = WLC_E_ACTION_FRAME_COMPLETE; - memcpy(&extra[1], &status, sizeof(status)); - printf("wl_iw_event status %d PacketId %d \n", status, toto); - printf("WLC_E_ACTION_FRAME_COMPLETE len %d \n", wrqu.data.length); - } - break; -#endif -#if WIRELESS_EXT > 17 - case WLC_E_MIC_ERROR: { - struct iw_michaelmicfailure *micerrevt = (struct iw_michaelmicfailure *)&extra; - cmd = IWEVMICHAELMICFAILURE; - wrqu.data.length = sizeof(struct iw_michaelmicfailure); - if (flags & WLC_EVENT_MSG_GROUP) - micerrevt->flags |= IW_MICFAILURE_GROUP; - else - micerrevt->flags |= IW_MICFAILURE_PAIRWISE; - memcpy(micerrevt->src_addr.sa_data, &e->addr, ETHER_ADDR_LEN); - micerrevt->src_addr.sa_family = ARPHRD_ETHER; - - break; - } -#ifdef BCMWPA2 - case WLC_E_PMKID_CACHE: { - if (data) - { - struct iw_pmkid_cand *iwpmkidcand = (struct iw_pmkid_cand *)&extra; - pmkid_cand_list_t *pmkcandlist; - pmkid_cand_t *pmkidcand; - int count; - - cmd = IWEVPMKIDCAND; - pmkcandlist = data; - count = ntoh32_ua((uint8 *)&pmkcandlist->npmkid_cand); - ASSERT(count >= 0); - wrqu.data.length = sizeof(struct iw_pmkid_cand); - pmkidcand = pmkcandlist->pmkid_cand; - while (count) { - bzero(iwpmkidcand, sizeof(struct iw_pmkid_cand)); - if (pmkidcand->preauth) - iwpmkidcand->flags |= IW_PMKID_CAND_PREAUTH; - bcopy(&pmkidcand->BSSID, &iwpmkidcand->bssid.sa_data, - ETHER_ADDR_LEN); -#ifndef SANDGATE2G - wireless_send_event(dev, cmd, &wrqu, extra); -#endif - pmkidcand++; - count--; - } - } - return; - } -#endif -#endif - - case WLC_E_SCAN_COMPLETE: -#if defined(WL_IW_USE_ISCAN) - if ((g_iscan) && (g_iscan->sysioc_pid >= 0) && - (g_iscan->iscan_state != ISCAN_STATE_IDLE)) - { - up(&g_iscan->sysioc_sem); - } else { - cmd = SIOCGIWSCAN; - wrqu.data.length = strlen(extra); - WL_TRACE(("Event WLC_E_SCAN_COMPLETE from specific scan %d\n", \ - g_iscan->iscan_state)); - } -#else - cmd = SIOCGIWSCAN; - wrqu.data.length = strlen(extra); - WL_TRACE(("Event WLC_E_SCAN_COMPLETE\n")); -#endif - break; - - default: - - WL_TRACE(("Unknown Event %d: ignoring\n", event_type)); - break; - } -#ifndef SANDGATE2G - if (cmd) { - if (cmd == SIOCGIWSCAN) - wireless_send_event(dev, cmd, &wrqu, NULL); - else - wireless_send_event(dev, cmd, &wrqu, extra); - } -#endif - -#if WIRELESS_EXT > 14 - - memset(extra, 0, sizeof(extra)); - if (wl_iw_check_conn_fail(e, extra, sizeof(extra))) { - cmd = IWEVCUSTOM; - wrqu.data.length = strlen(extra); -#ifndef SANDGATE2G - wireless_send_event(dev, cmd, &wrqu, extra); -#endif - } -#endif - -#endif -} - -int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats) -{ - int res = 0; - wl_cnt_t cnt; - int phy_noise; - int rssi; - scb_val_t scb_val; - - phy_noise = 0; - if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) - goto done; - - phy_noise = dtoh32(phy_noise); - WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise)); - - bzero(&scb_val, sizeof(scb_val_t)); - if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) - goto done; - - rssi = dtoh32(scb_val.val); - WL_TRACE(("wl_iw_get_wireless_stats rssi=%d\n", rssi)); - if (rssi <= WL_IW_RSSI_NO_SIGNAL) - wstats->qual.qual = 0; - else if (rssi <= WL_IW_RSSI_VERY_LOW) - wstats->qual.qual = 1; - else if (rssi <= WL_IW_RSSI_LOW) - wstats->qual.qual = 2; - else if (rssi <= WL_IW_RSSI_GOOD) - wstats->qual.qual = 3; - else if (rssi <= WL_IW_RSSI_VERY_GOOD) - wstats->qual.qual = 4; - else - wstats->qual.qual = 5; - - - wstats->qual.level = 0x100 + rssi; - wstats->qual.noise = 0x100 + phy_noise; -#if WIRELESS_EXT > 18 - wstats->qual.updated |= (IW_QUAL_ALL_UPDATED | IW_QUAL_DBM); -#else - wstats->qual.updated |= 7; -#endif - -#if WIRELESS_EXT > 11 - WL_TRACE(("wl_iw_get_wireless_stats counters=%d\n", (int)sizeof(wl_cnt_t))); - - memset(&cnt, 0, sizeof(wl_cnt_t)); - res = dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t)); - if (res) - { - WL_ERROR(("wl_iw_get_wireless_stats counters failed error=%d\n", res)); - goto done; - } - - cnt.version = dtoh16(cnt.version); - if (cnt.version != WL_CNT_T_VERSION) { - WL_TRACE(("\tIncorrect version of counters struct: expected %d; got %d\n", - WL_CNT_T_VERSION, cnt.version)); - goto done; - } - - wstats->discard.nwid = 0; - wstats->discard.code = dtoh32(cnt.rxundec); - wstats->discard.fragment = dtoh32(cnt.rxfragerr); - wstats->discard.retries = dtoh32(cnt.txfail); - wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant); - wstats->miss.beacon = 0; - - WL_TRACE(("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n", - dtoh32(cnt.txframe), dtoh32(cnt.txbyte))); - WL_TRACE(("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n", dtoh32(cnt.rxfrmtoolong))); - WL_TRACE(("wl_iw_get_wireless_stats counters rxbadplcp=%d\n", dtoh32(cnt.rxbadplcp))); - WL_TRACE(("wl_iw_get_wireless_stats counters rxundec=%d\n", dtoh32(cnt.rxundec))); - WL_TRACE(("wl_iw_get_wireless_stats counters rxfragerr=%d\n", dtoh32(cnt.rxfragerr))); - WL_TRACE(("wl_iw_get_wireless_stats counters txfail=%d\n", dtoh32(cnt.txfail))); - WL_TRACE(("wl_iw_get_wireless_stats counters rxrunt=%d\n", dtoh32(cnt.rxrunt))); - WL_TRACE(("wl_iw_get_wireless_stats counters rxgiant=%d\n", dtoh32(cnt.rxgiant))); - -#endif - -done: - return res; -} -static void -wl_iw_bt_flag_set( - struct net_device *dev, - bool set) -{ - char buf_flag7_dhcp_on[8] = { 7, 00, 00, 00, 0x1, 0x0, 0x00, 0x00 }; - char buf_flag7_default[8] = { 7, 00, 00, 00, 0x0, 0x00, 0x00, 0x00}; - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_lock(); -#endif - - if (set == TRUE) { - - dev_wlc_bufvar_set(dev, "btc_flags", \ - (char *)&buf_flag7_dhcp_on[0], sizeof(buf_flag7_dhcp_on)); - } - else { - - dev_wlc_bufvar_set(dev, "btc_flags", \ - (char *)&buf_flag7_default[0], sizeof(buf_flag7_default)); - } - -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - rtnl_unlock(); -#endif -} - -static void -wl_iw_bt_timerfunc(ulong data) -{ - bt_info_t *bt_local = (bt_info_t *)data; - bt_local->timer_on = 0; - WL_TRACE(("%s\n", __FUNCTION__)); - - up(&bt_local->bt_sem); -} - -static int -_bt_dhcp_sysioc_thread(void *data) -{ - DAEMONIZE("dhcp_sysioc"); - - while (down_interruptible(&g_bt->bt_sem) == 0) { - if (g_bt->timer_on) { - del_timer(&g_bt->timer); - g_bt->timer_on = 0; - } - - switch (g_bt->bt_state) { - case BT_DHCP_START: - - g_bt->bt_state = BT_DHCP_OPPORTUNITY_WINDOW; - mod_timer(&g_bt->timer, jiffies + \ - BT_DHCP_OPPORTUNITY_WINDOW_TIEM*HZ/1000); - g_bt->timer_on = 1; - break; - case BT_DHCP_OPPORTUNITY_WINDOW: - - WL_TRACE(("%s waiting for %d msec expired, force bt flag\n", \ - __FUNCTION__, BT_DHCP_OPPORTUNITY_WINDOW_TIEM)); - if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, TRUE); - g_bt->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; - mod_timer(&g_bt->timer, jiffies + BT_DHCP_FLAG_FORCE_TIME*HZ/1000); - g_bt->timer_on = 1; - break; - case BT_DHCP_FLAG_FORCE_TIMEOUT: - - WL_TRACE(("%s waiting for %d msec expired remove bt flag\n", \ - __FUNCTION__, BT_DHCP_FLAG_FORCE_TIME)); - - if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE); - g_bt->bt_state = BT_DHCP_IDLE; - g_bt->timer_on = 0; - break; - default: - WL_ERROR(("%s error g_status=%d !!!\n", __FUNCTION__, \ - g_bt->bt_state)); - if (g_bt->dev) wl_iw_bt_flag_set(g_bt->dev, FALSE); - g_bt->bt_state = BT_DHCP_IDLE; - g_bt->timer_on = 0; - break; - } - } - - if (g_bt->timer_on) { - del_timer(&g_bt->timer); - g_bt->timer_on = 0; - } - complete_and_exit(&g_bt->bt_exited, 0); -} - -static void -wl_iw_bt_release(void) -{ - bt_info_t *bt_local = g_bt; - - if (!bt_local) { - return; - } - - if (bt_local->bt_pid >= 0) { - KILL_PROC(bt_local->bt_pid, SIGTERM); - wait_for_completion(&bt_local->bt_exited); - } - kfree(bt_local); - g_bt = NULL; -} - -static int -wl_iw_bt_init(struct net_device *dev) -{ - bt_info_t *bt_dhcp = NULL; - - bt_dhcp = kmalloc(sizeof(bt_info_t), GFP_KERNEL); - if (!bt_dhcp) - return -ENOMEM; - - memset(bt_dhcp, 0, sizeof(bt_info_t)); - bt_dhcp->bt_pid = -1; - g_bt = bt_dhcp; - bt_dhcp->dev = dev; - bt_dhcp->bt_state = BT_DHCP_IDLE; - - - bt_dhcp->timer_ms = 10; - init_timer(&bt_dhcp->timer); - bt_dhcp->timer.data = (ulong)bt_dhcp; - bt_dhcp->timer.function = wl_iw_bt_timerfunc; - - sema_init(&bt_dhcp->bt_sem, 0); - init_completion(&bt_dhcp->bt_exited); - bt_dhcp->bt_pid = kernel_thread(_bt_dhcp_sysioc_thread, bt_dhcp, 0); - if (bt_dhcp->bt_pid < 0) { - WL_ERROR(("Failed in %s\n", __FUNCTION__)); - return -ENOMEM; - } - - return 0; -} - -int wl_iw_attach(struct net_device *dev, void * dhdp) -{ - int params_size; - wl_iw_t *iw; -#if defined(WL_IW_USE_ISCAN) - iscan_info_t *iscan = NULL; - - if (!dev) - return 0; - - -#ifdef CSCAN - params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)) + - (WL_NUMCHANNELS * sizeof(uint16)) + WL_SCAN_PARAMS_SSID_MAX * sizeof(wlc_ssid_t); -#else - params_size = (WL_SCAN_PARAMS_FIXED_SIZE + OFFSETOF(wl_iscan_params_t, params)); -#endif - iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL); - - if (!iscan) - return -ENOMEM; - memset(iscan, 0, sizeof(iscan_info_t)); - - - iscan->iscan_ex_params_p = (wl_iscan_params_t*)kmalloc(params_size, GFP_KERNEL); - if (!iscan->iscan_ex_params_p) - return -ENOMEM; - iscan->iscan_ex_param_size = params_size; - iscan->sysioc_pid = -1; - - g_iscan = iscan; - iscan->dev = dev; - iscan->iscan_state = ISCAN_STATE_IDLE; - - g_first_broadcast_scan = BROADCAST_SCAN_FIRST_IDLE; - g_iscan->scan_flag = 0; - - - iscan->timer_ms = 3000; - init_timer(&iscan->timer); - iscan->timer.data = (ulong)iscan; - iscan->timer.function = wl_iw_timerfunc; - - sema_init(&iscan->sysioc_sem, 0); - init_completion(&iscan->sysioc_exited); - iscan->sysioc_pid = kernel_thread(_iscan_sysioc_thread, iscan, 0); - if (iscan->sysioc_pid < 0) - return -ENOMEM; -#endif - - iw = *(wl_iw_t **)netdev_priv(dev); - iw->pub = (dhd_pub_t *)dhdp; - MUTEX_LOCK_INIT(iw->pub); - MUTEX_LOCK_WL_SCAN_SET_INIT(); -#ifdef SOFTAP - priv_dev = dev; - MUTEX_LOCK_SOFTAP_SET_INIT(iw->pub); -#endif - g_scan = NULL; - - - g_scan = (void *)kmalloc(G_SCAN_RESULTS, GFP_KERNEL); - if (!g_scan) - return -ENOMEM; - - memset(g_scan, 0, G_SCAN_RESULTS); - g_scan_specified_ssid = 0; - -#if !defined(CSCAN) - - wl_iw_init_ss_cache_ctrl(); -#endif - - wl_iw_bt_init(dev); - - - return 0; -} - -void wl_iw_detach(void) -{ -#if defined(WL_IW_USE_ISCAN) - iscan_buf_t *buf; - iscan_info_t *iscan = g_iscan; - - if (!iscan) - return; - if (iscan->sysioc_pid >= 0) { - KILL_PROC(iscan->sysioc_pid, SIGTERM); - wait_for_completion(&iscan->sysioc_exited); - } - MUTEX_LOCK_WL_SCAN_SET(); - while (iscan->list_hdr) { - buf = iscan->list_hdr->next; - kfree(iscan->list_hdr); - iscan->list_hdr = buf; - } - MUTEX_UNLOCK_WL_SCAN_SET(); - kfree(iscan->iscan_ex_params_p); - kfree(iscan); - g_iscan = NULL; -#endif - - if (g_scan) - kfree(g_scan); - - g_scan = NULL; -#if !defined(CSCAN) - wl_iw_release_ss_cache_ctrl(); -#endif - wl_iw_bt_release(); - -#ifdef SOFTAP - if (ap_cfg_running) { - WL_TRACE(("\n%s AP is going down\n", __FUNCTION__)); - - wl_iw_send_priv_event(priv_dev, "AP_DOWN"); - } -#endif - -} diff --git a/drivers/net/wireless/bcm4329/wl_iw.h b/drivers/net/wireless/bcm4329/wl_iw.h deleted file mode 100644 index 6375e94bae96..000000000000 --- a/drivers/net/wireless/bcm4329/wl_iw.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Linux Wireless Extensions support - * - * Copyright (C) 1999-2010, Broadcom Corporation - * - * Unless you and Broadcom execute a separate written software license - * agreement governing use of this software, this software is licensed to you - * under the terms of the GNU General Public License version 2 (the "GPL"), - * available at http://www.broadcom.com/licenses/GPLv2.php, with the - * following added to such license: - * - * As a special exception, the copyright holders of this software give you - * permission to link this software with independent modules, and to copy and - * distribute the resulting executable under terms of your choice, provided that - * you also meet, for each linked independent module, the terms and conditions of - * the license of that module. An independent module is a module which is not - * derived from this software. The special exception does not apply to any - * modifications of the software. - * - * Notwithstanding the above, under no circumstances may you combine this - * software in any way with any other Broadcom software provided under a license - * other than the GPL, without Broadcom's express prior written consent. - * - * $Id: wl_iw.h,v 1.5.34.1.6.24 2010/07/27 20:46:02 Exp $ - */ - - -#ifndef _wl_iw_h_ -#define _wl_iw_h_ - -#include - -#include -#include -#include - -#define WL_SCAN_PARAMS_SSID_MAX 10 -#define GET_SSID "SSID=" -#define GET_CHANNEL "CH=" -#define GET_NPROBE "NPROBE=" -#define GET_ACTIVE_ASSOC_DWELL "ACTIVE=" -#define GET_PASSIVE_ASSOC_DWELL "PASSIVE=" -#define GET_HOME_DWELL "HOME=" -#define GET_SCAN_TYPE "TYPE=" - -#define BAND_GET_CMD "BANDGET" -#define BAND_SET_CMD "BANDSET" - -#define SOFTAP 1 - - -#define WL_IW_RSSI_MINVAL -200 -#define WL_IW_RSSI_NO_SIGNAL -91 -#define WL_IW_RSSI_VERY_LOW -80 -#define WL_IW_RSSI_LOW -70 -#define WL_IW_RSSI_GOOD -68 -#define WL_IW_RSSI_VERY_GOOD -58 -#define WL_IW_RSSI_EXCELLENT -57 -#define WL_IW_RSSI_INVALID 0 -#define MAX_WX_STRING 80 -#define isprint(c) bcm_isprint(c) -#define WL_IW_SET_ACTIVE_SCAN (SIOCIWFIRSTPRIV+1) -#define WL_IW_GET_RSSI (SIOCIWFIRSTPRIV+3) -#define WL_IW_SET_PASSIVE_SCAN (SIOCIWFIRSTPRIV+5) -#define WL_IW_GET_LINK_SPEED (SIOCIWFIRSTPRIV+7) -#define WL_IW_GET_CURR_MACADDR (SIOCIWFIRSTPRIV+9) -#define WL_IW_SET_STOP (SIOCIWFIRSTPRIV+11) -#define WL_IW_SET_START (SIOCIWFIRSTPRIV+13) - - -#define WL_SET_AP_CFG (SIOCIWFIRSTPRIV+15) -#define WL_AP_STA_LIST (SIOCIWFIRSTPRIV+17) -#define WL_AP_MAC_FLTR (SIOCIWFIRSTPRIV+19) -#define WL_AP_BSS_START (SIOCIWFIRSTPRIV+21) -#define AP_LPB_CMD (SIOCIWFIRSTPRIV+23) -#define WL_AP_STOP (SIOCIWFIRSTPRIV+25) -#define WL_FW_RELOAD (SIOCIWFIRSTPRIV+27) -#define WL_COMBO_SCAN (SIOCIWFIRSTPRIV+29) -#define WL_AP_SPARE3 (SIOCIWFIRSTPRIV+31) -#define G_SCAN_RESULTS 8*1024 -#define WE_ADD_EVENT_FIX 0x80 -#define G_WLAN_SET_ON 0 -#define G_WLAN_SET_OFF 1 - -#define CHECK_EXTRA_FOR_NULL(extra) \ -if (!extra) { \ - WL_ERROR(("%s: error : extra is null pointer\n", __FUNCTION__)); \ - return -EINVAL; \ -} - -typedef struct wl_iw { - char nickname[IW_ESSID_MAX_SIZE]; - - struct iw_statistics wstats; - - int spy_num; - uint32 pwsec; - uint32 gwsec; - bool privacy_invoked; - - struct ether_addr spy_addr[IW_MAX_SPY]; - struct iw_quality spy_qual[IW_MAX_SPY]; - void *wlinfo; - dhd_pub_t * pub; -} wl_iw_t; - -int wl_control_wl_start(struct net_device *dev); -#define WLC_IW_SS_CACHE_MAXLEN 512 -#define WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN 32 -#define WLC_IW_BSS_INFO_MAXLEN \ - (WLC_IW_SS_CACHE_MAXLEN - WLC_IW_SS_CACHE_CTRL_FIELD_MAXLEN) - -typedef struct wl_iw_ss_cache { - struct wl_iw_ss_cache *next; - uint32 buflen; - uint32 version; - uint32 count; - int dirty; - wl_bss_info_t bss_info[1]; -} wl_iw_ss_cache_t; - -typedef struct wl_iw_ss_cache_ctrl { - wl_iw_ss_cache_t *m_cache_head; - int m_link_down; - int m_timer_expired; - char m_active_bssid[ETHER_ADDR_LEN]; - uint m_prev_scan_mode; - uint m_cons_br_scan_cnt; - struct timer_list *m_timer; -} wl_iw_ss_cache_ctrl_t; -typedef enum broadcast_first_scan { - BROADCAST_SCAN_FIRST_IDLE = 0, - BROADCAST_SCAN_FIRST_STARTED, - BROADCAST_SCAN_FIRST_RESULT_READY, - BROADCAST_SCAN_FIRST_RESULT_CONSUMED -} broadcast_first_scan_t; -#ifdef SOFTAP -#define SSID_LEN 33 -#define SEC_LEN 16 -#define KEY_LEN 65 -#define PROFILE_OFFSET 32 -struct ap_profile { - uint8 ssid[SSID_LEN]; - uint8 sec[SEC_LEN]; - uint8 key[KEY_LEN]; - uint32 channel; - uint32 preamble; - uint32 max_scb; -}; - - -#define MACLIST_MODE_DISABLED 0 -#define MACLIST_MODE_ENABLED 1 -#define MACLIST_MODE_ALLOW 2 -struct mflist { - uint count; - struct ether_addr ea[16]; -}; -struct mac_list_set { - uint32 mode; - struct mflist white_list; - struct mflist black_list; -}; -#endif - -#if WIRELESS_EXT > 12 -#include -extern const struct iw_handler_def wl_iw_handler_def; -#endif - -extern int wl_iw_ioctl(struct net_device *dev, struct ifreq *rq, int cmd); -extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data); -extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats); -int wl_iw_attach(struct net_device *dev, void * dhdp); -void wl_iw_detach(void); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) -#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ - iwe_stream_add_event(info, stream, ends, iwe, extra) -#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \ - iwe_stream_add_value(info, event, value, ends, iwe, event_len) -#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \ - iwe_stream_add_point(info, stream, ends, iwe, extra) -#else -#define IWE_STREAM_ADD_EVENT(info, stream, ends, iwe, extra) \ - iwe_stream_add_event(stream, ends, iwe, extra) -#define IWE_STREAM_ADD_VALUE(info, event, value, ends, iwe, event_len) \ - iwe_stream_add_value(event, value, ends, iwe, event_len) -#define IWE_STREAM_ADD_POINT(info, stream, ends, iwe, extra) \ - iwe_stream_add_point(stream, ends, iwe, extra) -#endif - -#if defined(CSCAN) - -typedef struct cscan_tlv { - char prefix; - char version; - char subver; - char reserved; -} cscan_tlv_t; - -#define CSCAN_COMMAND "CSCAN " -#define CSCAN_TLV_PREFIX 'S' -#define CSCAN_TLV_VERSION 1 -#define CSCAN_TLV_SUBVERSION 0 -#define CSCAN_TLV_TYPE_SSID_IE 'S' -#define CSCAN_TLV_TYPE_CHANNEL_IE 'C' -#define CSCAN_TLV_TYPE_NPROBE_IE 'N' -#define CSCAN_TLV_TYPE_ACTIVE_IE 'A' -#define CSCAN_TLV_TYPE_PASSIVE_IE 'P' -#define CSCAN_TLV_TYPE_HOME_IE 'H' -#define CSCAN_TLV_TYPE_STYPE_IE 'T' - -extern int wl_iw_parse_channel_list_tlv(char** list_str, uint16* channel_list, \ - int channel_num, int *bytes_left); - -extern int wl_iw_parse_data_tlv(char** list_str, void *dst, int dst_size, \ - const char token, int input_size, int *bytes_left); - -extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, \ - int max, int *bytes_left); - -extern int wl_iw_parse_ssid_list(char** list_str, wlc_ssid_t* ssid, int idx, int max); - -extern int wl_iw_parse_channel_list(char** list_str, uint16* channel_list, int channel_num); - -#endif - -#endif diff --git a/drivers/net/wireless/hostap/Kconfig b/drivers/net/wireless/hostap/Kconfig deleted file mode 100644 index c15db2293515..000000000000 --- a/drivers/net/wireless/hostap/Kconfig +++ /dev/null @@ -1,97 +0,0 @@ -config HOSTAP - tristate "IEEE 802.11 for Host AP (Prism2/2.5/3 and WEP/TKIP/CCMP)" - depends on WLAN_80211 - select WIRELESS_EXT - select CRYPTO - select CRYPTO_ARC4 - select CRYPTO_ECB - select CRYPTO_AES - select CRYPTO_MICHAEL_MIC - select CRYPTO_ECB - select CRC32 - select LIB80211 - select LIB80211_CRYPT_WEP - select LIB80211_CRYPT_TKIP - select LIB80211_CRYPT_CCMP - ---help--- - Shared driver code for IEEE 802.11b wireless cards based on - Intersil Prism2/2.5/3 chipset. This driver supports so called - Host AP mode that allows the card to act as an IEEE 802.11 - access point. - - See for more information about the - Host AP driver configuration and tools. This site includes - information and tools (hostapd and wpa_supplicant) for WPA/WPA2 - support. - - This option includes the base Host AP driver code that is shared by - different hardware models. You will also need to enable support for - PLX/PCI/CS version of the driver to actually use the driver. - - The driver can be compiled as a module and it will be called - hostap. - -config HOSTAP_FIRMWARE - bool "Support downloading firmware images with Host AP driver" - depends on HOSTAP - ---help--- - Configure Host AP driver to include support for firmware image - download. This option by itself only enables downloading to the - volatile memory, i.e. the card RAM. This option is required to - support cards that don't have firmware in flash, such as D-Link - DWL-520 rev E and D-Link DWL-650 rev P. - - Firmware image downloading needs a user space tool, prism2_srec. - It is available from http://hostap.epitest.fi/. - -config HOSTAP_FIRMWARE_NVRAM - bool "Support for non-volatile firmware download" - depends on HOSTAP_FIRMWARE - ---help--- - Allow Host AP driver to write firmware images to the non-volatile - card memory, i.e. flash memory that survives power cycling. - Enable this option if you want to be able to change card firmware - permanently. - - Firmware image downloading needs a user space tool, prism2_srec. - It is available from http://hostap.epitest.fi/. - -config HOSTAP_PLX - tristate "Host AP driver for Prism2/2.5/3 in PLX9052 PCI adaptors" - depends on PCI && HOSTAP - ---help--- - Host AP driver's version for Prism2/2.5/3 PC Cards in PLX9052 based - PCI adaptors. - - "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this - driver and its help text includes more information about the Host AP - driver. - - The driver can be compiled as a module and will be named - hostap_plx. - -config HOSTAP_PCI - tristate "Host AP driver for Prism2.5 PCI adaptors" - depends on PCI && HOSTAP - ---help--- - Host AP driver's version for Prism2.5 PCI adaptors. - - "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this - driver and its help text includes more information about the Host AP - driver. - - The driver can be compiled as a module and will be named - hostap_pci. - -config HOSTAP_CS - tristate "Host AP driver for Prism2/2.5/3 PC Cards" - depends on PCMCIA && HOSTAP - ---help--- - Host AP driver's version for Prism2/2.5/3 PC Cards. - - "Host AP support for Prism2/2.5/3 IEEE 802.11b" is required for this - driver and its help text includes more information about the Host AP - driver. - - The driver can be compiled as a module and will be named - hostap_cs. diff --git a/drivers/net/wireless/hostap/Makefile b/drivers/net/wireless/hostap/Makefile deleted file mode 100644 index b8e41a702c00..000000000000 --- a/drivers/net/wireless/hostap/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -hostap-y := hostap_80211_rx.o hostap_80211_tx.o hostap_ap.o hostap_info.o \ - hostap_ioctl.o hostap_main.o hostap_proc.o -obj-$(CONFIG_HOSTAP) += hostap.o - -obj-$(CONFIG_HOSTAP_CS) += hostap_cs.o -obj-$(CONFIG_HOSTAP_PLX) += hostap_plx.o -obj-$(CONFIG_HOSTAP_PCI) += hostap_pci.o diff --git a/drivers/net/wireless/hostap/hostap.h b/drivers/net/wireless/hostap/hostap.h deleted file mode 100644 index ce8721fbc10e..000000000000 --- a/drivers/net/wireless/hostap/hostap.h +++ /dev/null @@ -1,95 +0,0 @@ -#ifndef HOSTAP_H -#define HOSTAP_H - -#include -#include - -#include "hostap_wlan.h" -#include "hostap_ap.h" - -static const long freq_list[] = { 2412, 2417, 2422, 2427, 2432, 2437, 2442, - 2447, 2452, 2457, 2462, 2467, 2472, 2484 }; -#define FREQ_COUNT ARRAY_SIZE(freq_list) - -/* hostap.c */ - -extern struct proc_dir_entry *hostap_proc; - -u16 hostap_tx_callback_register(local_info_t *local, - void (*func)(struct sk_buff *, int ok, void *), - void *data); -int hostap_tx_callback_unregister(local_info_t *local, u16 idx); -int hostap_set_word(struct net_device *dev, int rid, u16 val); -int hostap_set_string(struct net_device *dev, int rid, const char *val); -u16 hostap_get_porttype(local_info_t *local); -int hostap_set_encryption(local_info_t *local); -int hostap_set_antsel(local_info_t *local); -int hostap_set_roaming(local_info_t *local); -int hostap_set_auth_algs(local_info_t *local); -void hostap_dump_rx_header(const char *name, - const struct hfa384x_rx_frame *rx); -void hostap_dump_tx_header(const char *name, - const struct hfa384x_tx_frame *tx); -extern const struct header_ops hostap_80211_ops; -int hostap_80211_get_hdrlen(__le16 fc); -struct net_device_stats *hostap_get_stats(struct net_device *dev); -void hostap_setup_dev(struct net_device *dev, local_info_t *local, - int type); -void hostap_set_multicast_list_queue(struct work_struct *work); -int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked); -int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked); -void hostap_cleanup(local_info_t *local); -void hostap_cleanup_handler(void *data); -struct net_device * hostap_add_interface(struct local_info *local, - int type, int rtnl_locked, - const char *prefix, const char *name); -void hostap_remove_interface(struct net_device *dev, int rtnl_locked, - int remove_from_list); -int prism2_update_comms_qual(struct net_device *dev); -int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype, - u8 *body, size_t bodylen); -int prism2_sta_deauth(local_info_t *local, u16 reason); -int prism2_wds_add(local_info_t *local, u8 *remote_addr, - int rtnl_locked); -int prism2_wds_del(local_info_t *local, u8 *remote_addr, - int rtnl_locked, int do_not_remove); - - -/* hostap_ap.c */ - -int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac); -int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac); -void ap_control_flush_macs(struct mac_restrictions *mac_restrictions); -int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac); -void ap_control_kickall(struct ap_data *ap); -void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, - struct lib80211_crypt_data ***crypt); -int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], - struct iw_quality qual[], int buf_size, - int aplist); -int prism2_ap_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *buffer); -int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param); - - -/* hostap_proc.c */ - -void hostap_init_proc(local_info_t *local); -void hostap_remove_proc(local_info_t *local); - - -/* hostap_info.c */ - -void hostap_info_init(local_info_t *local); -void hostap_info_process(local_info_t *local, struct sk_buff *skb); - - -/* hostap_ioctl.c */ - -extern const struct iw_handler_def hostap_iw_handler_def; -extern const struct ethtool_ops prism2_ethtool_ops; - -int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd); - - -#endif /* HOSTAP_H */ diff --git a/drivers/net/wireless/hostap/hostap_80211.h b/drivers/net/wireless/hostap/hostap_80211.h deleted file mode 100644 index 7f9d8d976aa8..000000000000 --- a/drivers/net/wireless/hostap/hostap_80211.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef HOSTAP_80211_H -#define HOSTAP_80211_H - -#include -#include -#include - -struct hostap_ieee80211_mgmt { - __le16 frame_control; - __le16 duration; - u8 da[6]; - u8 sa[6]; - u8 bssid[6]; - __le16 seq_ctrl; - union { - struct { - __le16 auth_alg; - __le16 auth_transaction; - __le16 status_code; - /* possibly followed by Challenge text */ - u8 variable[0]; - } __attribute__ ((packed)) auth; - struct { - __le16 reason_code; - } __attribute__ ((packed)) deauth; - struct { - __le16 capab_info; - __le16 listen_interval; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_req; - struct { - __le16 capab_info; - __le16 status_code; - __le16 aid; - /* followed by Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) assoc_resp, reassoc_resp; - struct { - __le16 capab_info; - __le16 listen_interval; - u8 current_ap[6]; - /* followed by SSID and Supported rates */ - u8 variable[0]; - } __attribute__ ((packed)) reassoc_req; - struct { - __le16 reason_code; - } __attribute__ ((packed)) disassoc; - struct { - } __attribute__ ((packed)) probe_req; - struct { - u8 timestamp[8]; - __le16 beacon_int; - __le16 capab_info; - /* followed by some of SSID, Supported rates, - * FH Params, DS Params, CF Params, IBSS Params, TIM */ - u8 variable[0]; - } __attribute__ ((packed)) beacon, probe_resp; - } u; -} __attribute__ ((packed)); - - -#define IEEE80211_MGMT_HDR_LEN 24 -#define IEEE80211_DATA_HDR3_LEN 24 -#define IEEE80211_DATA_HDR4_LEN 30 - - -struct hostap_80211_rx_status { - u32 mac_time; - u8 signal; - u8 noise; - u16 rate; /* in 100 kbps */ -}; - -/* prism2_rx_80211 'type' argument */ -enum { - PRISM2_RX_MONITOR, PRISM2_RX_MGMT, PRISM2_RX_NON_ASSOC, - PRISM2_RX_NULLFUNC_ACK -}; - -int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats, int type); -void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats); -void hostap_dump_rx_80211(const char *name, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats); - -void hostap_dump_tx_80211(const char *name, struct sk_buff *skb); -netdev_tx_t hostap_data_start_xmit(struct sk_buff *skb, - struct net_device *dev); -netdev_tx_t hostap_mgmt_start_xmit(struct sk_buff *skb, - struct net_device *dev); -netdev_tx_t hostap_master_start_xmit(struct sk_buff *skb, - struct net_device *dev); - -#endif /* HOSTAP_80211_H */ diff --git a/drivers/net/wireless/hostap/hostap_80211_rx.c b/drivers/net/wireless/hostap/hostap_80211_rx.c deleted file mode 100644 index 3816df96a663..000000000000 --- a/drivers/net/wireless/hostap/hostap_80211_rx.c +++ /dev/null @@ -1,1116 +0,0 @@ -#include -#include -#include - -#include "hostap_80211.h" -#include "hostap.h" -#include "hostap_ap.h" - -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -/* No encapsulation header if EtherType < 0x600 (=length) */ - -void hostap_dump_rx_80211(const char *name, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct ieee80211_hdr *hdr; - u16 fc; - - hdr = (struct ieee80211_hdr *) skb->data; - - printk(KERN_DEBUG "%s: RX signal=%d noise=%d rate=%d len=%d " - "jiffies=%ld\n", - name, rx_stats->signal, rx_stats->noise, rx_stats->rate, - skb->len, jiffies); - - if (skb->len < 2) - return; - - fc = le16_to_cpu(hdr->frame_control); - printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s", - fc, (fc & IEEE80211_FCTL_FTYPE) >> 2, - (fc & IEEE80211_FCTL_STYPE) >> 4, - fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "", - fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : ""); - - if (skb->len < IEEE80211_DATA_HDR3_LEN) { - printk("\n"); - return; - } - - printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id), - le16_to_cpu(hdr->seq_ctrl)); - - printk(KERN_DEBUG " A1=%pM", hdr->addr1); - printk(" A2=%pM", hdr->addr2); - printk(" A3=%pM", hdr->addr3); - if (skb->len >= 30) - printk(" A4=%pM", hdr->addr4); - printk("\n"); -} - - -/* Send RX frame to netif with 802.11 (and possible prism) header. - * Called from hardware or software IRQ context. */ -int prism2_rx_80211(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats, int type) -{ - struct hostap_interface *iface; - local_info_t *local; - int hdrlen, phdrlen, head_need, tail_need; - u16 fc; - int prism_header, ret; - struct ieee80211_hdr *fhdr; - - iface = netdev_priv(dev); - local = iface->local; - - if (dev->type == ARPHRD_IEEE80211_PRISM) { - if (local->monitor_type == PRISM2_MONITOR_PRISM) { - prism_header = 1; - phdrlen = sizeof(struct linux_wlan_ng_prism_hdr); - } else { /* local->monitor_type == PRISM2_MONITOR_CAPHDR */ - prism_header = 2; - phdrlen = sizeof(struct linux_wlan_ng_cap_hdr); - } - } else if (dev->type == ARPHRD_IEEE80211_RADIOTAP) { - prism_header = 3; - phdrlen = sizeof(struct hostap_radiotap_rx); - } else { - prism_header = 0; - phdrlen = 0; - } - - fhdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(fhdr->frame_control); - - if (type == PRISM2_RX_MGMT && (fc & IEEE80211_FCTL_VERS)) { - printk(KERN_DEBUG "%s: dropped management frame with header " - "version %d\n", dev->name, fc & IEEE80211_FCTL_VERS); - dev_kfree_skb_any(skb); - return 0; - } - - hdrlen = hostap_80211_get_hdrlen(fhdr->frame_control); - - /* check if there is enough room for extra data; if not, expand skb - * buffer to be large enough for the changes */ - head_need = phdrlen; - tail_need = 0; -#ifdef PRISM2_ADD_BOGUS_CRC - tail_need += 4; -#endif /* PRISM2_ADD_BOGUS_CRC */ - - head_need -= skb_headroom(skb); - tail_need -= skb_tailroom(skb); - - if (head_need > 0 || tail_need > 0) { - if (pskb_expand_head(skb, head_need > 0 ? head_need : 0, - tail_need > 0 ? tail_need : 0, - GFP_ATOMIC)) { - printk(KERN_DEBUG "%s: prism2_rx_80211 failed to " - "reallocate skb buffer\n", dev->name); - dev_kfree_skb_any(skb); - return 0; - } - } - - /* We now have an skb with enough head and tail room, so just insert - * the extra data */ - -#ifdef PRISM2_ADD_BOGUS_CRC - memset(skb_put(skb, 4), 0xff, 4); /* Prism2 strips CRC */ -#endif /* PRISM2_ADD_BOGUS_CRC */ - - if (prism_header == 1) { - struct linux_wlan_ng_prism_hdr *hdr; - hdr = (struct linux_wlan_ng_prism_hdr *) - skb_push(skb, phdrlen); - memset(hdr, 0, phdrlen); - hdr->msgcode = LWNG_CAP_DID_BASE; - hdr->msglen = sizeof(*hdr); - memcpy(hdr->devname, dev->name, sizeof(hdr->devname)); -#define LWNG_SETVAL(f,i,s,l,d) \ -hdr->f.did = LWNG_CAP_DID_BASE | (i << 12); \ -hdr->f.status = s; hdr->f.len = l; hdr->f.data = d - LWNG_SETVAL(hosttime, 1, 0, 4, jiffies); - LWNG_SETVAL(mactime, 2, 0, 4, rx_stats->mac_time); - LWNG_SETVAL(channel, 3, 1 /* no value */, 4, 0); - LWNG_SETVAL(rssi, 4, 1 /* no value */, 4, 0); - LWNG_SETVAL(sq, 5, 1 /* no value */, 4, 0); - LWNG_SETVAL(signal, 6, 0, 4, rx_stats->signal); - LWNG_SETVAL(noise, 7, 0, 4, rx_stats->noise); - LWNG_SETVAL(rate, 8, 0, 4, rx_stats->rate / 5); - LWNG_SETVAL(istx, 9, 0, 4, 0); - LWNG_SETVAL(frmlen, 10, 0, 4, skb->len - phdrlen); -#undef LWNG_SETVAL - } else if (prism_header == 2) { - struct linux_wlan_ng_cap_hdr *hdr; - hdr = (struct linux_wlan_ng_cap_hdr *) - skb_push(skb, phdrlen); - memset(hdr, 0, phdrlen); - hdr->version = htonl(LWNG_CAPHDR_VERSION); - hdr->length = htonl(phdrlen); - hdr->mactime = __cpu_to_be64(rx_stats->mac_time); - hdr->hosttime = __cpu_to_be64(jiffies); - hdr->phytype = htonl(4); /* dss_dot11_b */ - hdr->channel = htonl(local->channel); - hdr->datarate = htonl(rx_stats->rate); - hdr->antenna = htonl(0); /* unknown */ - hdr->priority = htonl(0); /* unknown */ - hdr->ssi_type = htonl(3); /* raw */ - hdr->ssi_signal = htonl(rx_stats->signal); - hdr->ssi_noise = htonl(rx_stats->noise); - hdr->preamble = htonl(0); /* unknown */ - hdr->encoding = htonl(1); /* cck */ - } else if (prism_header == 3) { - struct hostap_radiotap_rx *hdr; - hdr = (struct hostap_radiotap_rx *)skb_push(skb, phdrlen); - memset(hdr, 0, phdrlen); - hdr->hdr.it_len = cpu_to_le16(phdrlen); - hdr->hdr.it_present = - cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE)); - hdr->tsft = cpu_to_le64(rx_stats->mac_time); - hdr->chan_freq = cpu_to_le16(freq_list[local->channel - 1]); - hdr->chan_flags = cpu_to_le16(IEEE80211_CHAN_CCK | - IEEE80211_CHAN_2GHZ); - hdr->rate = rx_stats->rate / 5; - hdr->dbm_antsignal = rx_stats->signal; - hdr->dbm_antnoise = rx_stats->noise; - } - - ret = skb->len - phdrlen; - skb->dev = dev; - skb_reset_mac_header(skb); - skb_pull(skb, hdrlen); - if (prism_header) - skb_pull(skb, phdrlen); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = cpu_to_be16(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); - - return ret; -} - - -/* Called only as a tasklet (software IRQ) */ -static void monitor_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - int len; - - len = prism2_rx_80211(dev, skb, rx_stats, PRISM2_RX_MONITOR); - dev->stats.rx_packets++; - dev->stats.rx_bytes += len; -} - - -/* Called only as a tasklet (software IRQ) */ -static struct prism2_frag_entry * -prism2_frag_cache_find(local_info_t *local, unsigned int seq, - unsigned int frag, u8 *src, u8 *dst) -{ - struct prism2_frag_entry *entry; - int i; - - for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) { - entry = &local->frag_cache[i]; - if (entry->skb != NULL && - time_after(jiffies, entry->first_frag_time + 2 * HZ)) { - printk(KERN_DEBUG "%s: expiring fragment cache entry " - "seq=%u last_frag=%u\n", - local->dev->name, entry->seq, entry->last_frag); - dev_kfree_skb(entry->skb); - entry->skb = NULL; - } - - if (entry->skb != NULL && entry->seq == seq && - (entry->last_frag + 1 == frag || frag == -1) && - memcmp(entry->src_addr, src, ETH_ALEN) == 0 && - memcmp(entry->dst_addr, dst, ETH_ALEN) == 0) - return entry; - } - - return NULL; -} - - -/* Called only as a tasklet (software IRQ) */ -static struct sk_buff * -prism2_frag_cache_get(local_info_t *local, struct ieee80211_hdr *hdr) -{ - struct sk_buff *skb = NULL; - u16 sc; - unsigned int frag, seq; - struct prism2_frag_entry *entry; - - sc = le16_to_cpu(hdr->seq_ctrl); - frag = sc & IEEE80211_SCTL_FRAG; - seq = (sc & IEEE80211_SCTL_SEQ) >> 4; - - if (frag == 0) { - /* Reserve enough space to fit maximum frame length */ - skb = dev_alloc_skb(local->dev->mtu + - sizeof(struct ieee80211_hdr) + - 8 /* LLC */ + - 2 /* alignment */ + - 8 /* WEP */ + ETH_ALEN /* WDS */); - if (skb == NULL) - return NULL; - - entry = &local->frag_cache[local->frag_next_idx]; - local->frag_next_idx++; - if (local->frag_next_idx >= PRISM2_FRAG_CACHE_LEN) - local->frag_next_idx = 0; - - if (entry->skb != NULL) - dev_kfree_skb(entry->skb); - - entry->first_frag_time = jiffies; - entry->seq = seq; - entry->last_frag = frag; - entry->skb = skb; - memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); - memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); - } else { - /* received a fragment of a frame for which the head fragment - * should have already been received */ - entry = prism2_frag_cache_find(local, seq, frag, hdr->addr2, - hdr->addr1); - if (entry != NULL) { - entry->last_frag = frag; - skb = entry->skb; - } - } - - return skb; -} - - -/* Called only as a tasklet (software IRQ) */ -static int prism2_frag_cache_invalidate(local_info_t *local, - struct ieee80211_hdr *hdr) -{ - u16 sc; - unsigned int seq; - struct prism2_frag_entry *entry; - - sc = le16_to_cpu(hdr->seq_ctrl); - seq = (sc & IEEE80211_SCTL_SEQ) >> 4; - - entry = prism2_frag_cache_find(local, seq, -1, hdr->addr2, hdr->addr1); - - if (entry == NULL) { - printk(KERN_DEBUG "%s: could not invalidate fragment cache " - "entry (seq=%u)\n", - local->dev->name, seq); - return -1; - } - - entry->skb = NULL; - return 0; -} - - -static struct hostap_bss_info *__hostap_get_bss(local_info_t *local, u8 *bssid, - u8 *ssid, size_t ssid_len) -{ - struct list_head *ptr; - struct hostap_bss_info *bss; - - list_for_each(ptr, &local->bss_list) { - bss = list_entry(ptr, struct hostap_bss_info, list); - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0 && - (ssid == NULL || - (ssid_len == bss->ssid_len && - memcmp(ssid, bss->ssid, ssid_len) == 0))) { - list_move(&bss->list, &local->bss_list); - return bss; - } - } - - return NULL; -} - - -static struct hostap_bss_info *__hostap_add_bss(local_info_t *local, u8 *bssid, - u8 *ssid, size_t ssid_len) -{ - struct hostap_bss_info *bss; - - if (local->num_bss_info >= HOSTAP_MAX_BSS_COUNT) { - bss = list_entry(local->bss_list.prev, - struct hostap_bss_info, list); - list_del(&bss->list); - local->num_bss_info--; - } else { - bss = (struct hostap_bss_info *) - kmalloc(sizeof(*bss), GFP_ATOMIC); - if (bss == NULL) - return NULL; - } - - memset(bss, 0, sizeof(*bss)); - memcpy(bss->bssid, bssid, ETH_ALEN); - memcpy(bss->ssid, ssid, ssid_len); - bss->ssid_len = ssid_len; - local->num_bss_info++; - list_add(&bss->list, &local->bss_list); - return bss; -} - - -static void __hostap_expire_bss(local_info_t *local) -{ - struct hostap_bss_info *bss; - - while (local->num_bss_info > 0) { - bss = list_entry(local->bss_list.prev, - struct hostap_bss_info, list); - if (!time_after(jiffies, bss->last_update + 60 * HZ)) - break; - - list_del(&bss->list); - local->num_bss_info--; - kfree(bss); - } -} - - -/* Both IEEE 802.11 Beacon and Probe Response frames have similar structure, so - * the same routine can be used to parse both of them. */ -static void hostap_rx_sta_beacon(local_info_t *local, struct sk_buff *skb, - int stype) -{ - struct hostap_ieee80211_mgmt *mgmt; - int left, chan = 0; - u8 *pos; - u8 *ssid = NULL, *wpa = NULL, *rsn = NULL; - size_t ssid_len = 0, wpa_len = 0, rsn_len = 0; - struct hostap_bss_info *bss; - - if (skb->len < IEEE80211_MGMT_HDR_LEN + sizeof(mgmt->u.beacon)) - return; - - mgmt = (struct hostap_ieee80211_mgmt *) skb->data; - pos = mgmt->u.beacon.variable; - left = skb->len - (pos - skb->data); - - while (left >= 2) { - if (2 + pos[1] > left) - return; /* parse failed */ - switch (*pos) { - case WLAN_EID_SSID: - ssid = pos + 2; - ssid_len = pos[1]; - break; - case WLAN_EID_GENERIC: - if (pos[1] >= 4 && - pos[2] == 0x00 && pos[3] == 0x50 && - pos[4] == 0xf2 && pos[5] == 1) { - wpa = pos; - wpa_len = pos[1] + 2; - } - break; - case WLAN_EID_RSN: - rsn = pos; - rsn_len = pos[1] + 2; - break; - case WLAN_EID_DS_PARAMS: - if (pos[1] >= 1) - chan = pos[2]; - break; - } - left -= 2 + pos[1]; - pos += 2 + pos[1]; - } - - if (wpa_len > MAX_WPA_IE_LEN) - wpa_len = MAX_WPA_IE_LEN; - if (rsn_len > MAX_WPA_IE_LEN) - rsn_len = MAX_WPA_IE_LEN; - if (ssid_len > sizeof(bss->ssid)) - ssid_len = sizeof(bss->ssid); - - spin_lock(&local->lock); - bss = __hostap_get_bss(local, mgmt->bssid, ssid, ssid_len); - if (bss == NULL) - bss = __hostap_add_bss(local, mgmt->bssid, ssid, ssid_len); - if (bss) { - bss->last_update = jiffies; - bss->count++; - bss->capab_info = le16_to_cpu(mgmt->u.beacon.capab_info); - if (wpa) { - memcpy(bss->wpa_ie, wpa, wpa_len); - bss->wpa_ie_len = wpa_len; - } else - bss->wpa_ie_len = 0; - if (rsn) { - memcpy(bss->rsn_ie, rsn, rsn_len); - bss->rsn_ie_len = rsn_len; - } else - bss->rsn_ie_len = 0; - bss->chan = chan; - } - __hostap_expire_bss(local); - spin_unlock(&local->lock); -} - - -static int -hostap_rx_frame_mgmt(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats, u16 type, - u16 stype) -{ - if (local->iw_mode == IW_MODE_MASTER) - hostap_update_sta_ps(local, (struct ieee80211_hdr *) skb->data); - - if (local->hostapd && type == IEEE80211_FTYPE_MGMT) { - if (stype == IEEE80211_STYPE_BEACON && - local->iw_mode == IW_MODE_MASTER) { - struct sk_buff *skb2; - /* Process beacon frames also in kernel driver to - * update STA(AP) table statistics */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) - hostap_rx(skb2->dev, skb2, rx_stats); - } - - /* send management frames to the user space daemon for - * processing */ - local->apdevstats.rx_packets++; - local->apdevstats.rx_bytes += skb->len; - if (local->apdev == NULL) - return -1; - prism2_rx_80211(local->apdev, skb, rx_stats, PRISM2_RX_MGMT); - return 0; - } - - if (local->iw_mode == IW_MODE_MASTER) { - if (type != IEEE80211_FTYPE_MGMT && - type != IEEE80211_FTYPE_CTL) { - printk(KERN_DEBUG "%s: unknown management frame " - "(type=0x%02x, stype=0x%02x) dropped\n", - skb->dev->name, type >> 2, stype >> 4); - return -1; - } - - hostap_rx(skb->dev, skb, rx_stats); - return 0; - } else if (type == IEEE80211_FTYPE_MGMT && - (stype == IEEE80211_STYPE_BEACON || - stype == IEEE80211_STYPE_PROBE_RESP)) { - hostap_rx_sta_beacon(local, skb, stype); - return -1; - } else if (type == IEEE80211_FTYPE_MGMT && - (stype == IEEE80211_STYPE_ASSOC_RESP || - stype == IEEE80211_STYPE_REASSOC_RESP)) { - /* Ignore (Re)AssocResp silently since these are not currently - * needed but are still received when WPA/RSN mode is enabled. - */ - return -1; - } else { - printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: dropped unhandled" - " management frame in non-Host AP mode (type=%d:%d)\n", - skb->dev->name, type >> 2, stype >> 4); - return -1; - } -} - - -/* Called only as a tasklet (software IRQ) */ -static struct net_device *prism2_rx_get_wds(local_info_t *local, - u8 *addr) -{ - struct hostap_interface *iface = NULL; - struct list_head *ptr; - - read_lock_bh(&local->iface_lock); - list_for_each(ptr, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - if (iface->type == HOSTAP_INTERFACE_WDS && - memcmp(iface->u.wds.remote_addr, addr, ETH_ALEN) == 0) - break; - iface = NULL; - } - read_unlock_bh(&local->iface_lock); - - return iface ? iface->dev : NULL; -} - - -static int -hostap_rx_frame_wds(local_info_t *local, struct ieee80211_hdr *hdr, u16 fc, - struct net_device **wds) -{ - /* FIX: is this really supposed to accept WDS frames only in Master - * mode? What about Repeater or Managed with WDS frames? */ - if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) != - (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS) && - (local->iw_mode != IW_MODE_MASTER || !(fc & IEEE80211_FCTL_TODS))) - return 0; /* not a WDS frame */ - - /* Possible WDS frame: either IEEE 802.11 compliant (if FromDS) - * or own non-standard frame with 4th address after payload */ - if (memcmp(hdr->addr1, local->dev->dev_addr, ETH_ALEN) != 0 && - (hdr->addr1[0] != 0xff || hdr->addr1[1] != 0xff || - hdr->addr1[2] != 0xff || hdr->addr1[3] != 0xff || - hdr->addr1[4] != 0xff || hdr->addr1[5] != 0xff)) { - /* RA (or BSSID) is not ours - drop */ - PDEBUG(DEBUG_EXTRA2, "%s: received WDS frame with " - "not own or broadcast %s=%pM\n", - local->dev->name, - fc & IEEE80211_FCTL_FROMDS ? "RA" : "BSSID", - hdr->addr1); - return -1; - } - - /* check if the frame came from a registered WDS connection */ - *wds = prism2_rx_get_wds(local, hdr->addr2); - if (*wds == NULL && fc & IEEE80211_FCTL_FROMDS && - (local->iw_mode != IW_MODE_INFRA || - !(local->wds_type & HOSTAP_WDS_AP_CLIENT) || - memcmp(hdr->addr2, local->bssid, ETH_ALEN) != 0)) { - /* require that WDS link has been registered with TA or the - * frame is from current AP when using 'AP client mode' */ - PDEBUG(DEBUG_EXTRA, "%s: received WDS[4 addr] frame " - "from unknown TA=%pM\n", - local->dev->name, hdr->addr2); - if (local->ap && local->ap->autom_ap_wds) - hostap_wds_link_oper(local, hdr->addr2, WDS_ADD); - return -1; - } - - if (*wds && !(fc & IEEE80211_FCTL_FROMDS) && local->ap && - hostap_is_sta_assoc(local->ap, hdr->addr2)) { - /* STA is actually associated with us even though it has a - * registered WDS link. Assume it is in 'AP client' mode. - * Since this is a 3-addr frame, assume it is not (bogus) WDS - * frame and process it like any normal ToDS frame from - * associated STA. */ - *wds = NULL; - } - - return 0; -} - - -static int hostap_is_eapol_frame(local_info_t *local, struct sk_buff *skb) -{ - struct net_device *dev = local->dev; - u16 fc, ethertype; - struct ieee80211_hdr *hdr; - u8 *pos; - - if (skb->len < 24) - return 0; - - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - - /* check that the frame is unicast frame to us */ - if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0 && - memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { - /* ToDS frame with own addr BSSID and DA */ - } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { - /* FromDS frame with own addr as DA */ - } else - return 0; - - if (skb->len < 24 + 8) - return 0; - - /* check for port access entity Ethernet type */ - pos = skb->data + 24; - ethertype = (pos[6] << 8) | pos[7]; - if (ethertype == ETH_P_PAE) - return 1; - - return 0; -} - - -/* Called only as a tasklet (software IRQ) */ -static int -hostap_rx_frame_decrypt(local_info_t *local, struct sk_buff *skb, - struct lib80211_crypt_data *crypt) -{ - struct ieee80211_hdr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) - return 0; - - hdr = (struct ieee80211_hdr *) skb->data; - hdrlen = hostap_80211_get_hdrlen(hdr->frame_control); - - if (local->tkip_countermeasures && - strcmp(crypt->ops->name, "TKIP") == 0) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " - "received packet from %pM\n", - local->dev->name, hdr->addr2); - } - return -1; - } - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - printk(KERN_DEBUG "%s: decryption failed (SA=%pM) res=%d\n", - local->dev->name, hdr->addr2, res); - local->comm_tallies.rx_discards_wep_undecryptable++; - return -1; - } - - return res; -} - - -/* Called only as a tasklet (software IRQ) */ -static int -hostap_rx_frame_decrypt_msdu(local_info_t *local, struct sk_buff *skb, - int keyidx, struct lib80211_crypt_data *crypt) -{ - struct ieee80211_hdr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) - return 0; - - hdr = (struct ieee80211_hdr *) skb->data; - hdrlen = hostap_80211_get_hdrlen(hdr->frame_control); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" - " (SA=%pM keyidx=%d)\n", - local->dev->name, hdr->addr2, keyidx); - return -1; - } - - return 0; -} - - -/* All received frames are sent to this function. @skb contains the frame in - * IEEE 802.11 format, i.e., in the format it was sent over air. - * This function is called only as a tasklet (software IRQ). */ -void hostap_80211_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct hostap_interface *iface; - local_info_t *local; - struct ieee80211_hdr *hdr; - size_t hdrlen; - u16 fc, type, stype, sc; - struct net_device *wds = NULL; - unsigned int frag; - u8 *payload; - struct sk_buff *skb2 = NULL; - u16 ethertype; - int frame_authorized = 0; - int from_assoc_ap = 0; - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - struct lib80211_crypt_data *crypt = NULL; - void *sta = NULL; - int keyidx = 0; - - iface = netdev_priv(dev); - local = iface->local; - iface->stats.rx_packets++; - iface->stats.rx_bytes += skb->len; - - /* dev is the master radio device; change this to be the default - * virtual interface (this may be changed to WDS device below) */ - dev = local->ddev; - iface = netdev_priv(dev); - - hdr = (struct ieee80211_hdr *) skb->data; - - if (skb->len < 10) - goto rx_dropped; - - fc = le16_to_cpu(hdr->frame_control); - type = fc & IEEE80211_FCTL_FTYPE; - stype = fc & IEEE80211_FCTL_STYPE; - sc = le16_to_cpu(hdr->seq_ctrl); - frag = sc & IEEE80211_SCTL_FRAG; - hdrlen = hostap_80211_get_hdrlen(hdr->frame_control); - - /* Put this code here so that we avoid duplicating it in all - * Rx paths. - Jean II */ -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ - /* If spy monitoring on */ - if (iface->spy_data.spy_number > 0) { - struct iw_quality wstats; - wstats.level = rx_stats->signal; - wstats.noise = rx_stats->noise; - wstats.updated = IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_UPDATED - | IW_QUAL_QUAL_INVALID | IW_QUAL_DBM; - /* Update spy records */ - wireless_spy_update(dev, hdr->addr2, &wstats); - } -#endif /* IW_WIRELESS_SPY */ - hostap_update_rx_stats(local->ap, hdr, rx_stats); - - if (local->iw_mode == IW_MODE_MONITOR) { - monitor_rx(dev, skb, rx_stats); - return; - } - - if (local->host_decrypt) { - int idx = 0; - if (skb->len >= hdrlen + 3) - idx = skb->data[hdrlen + 3] >> 6; - crypt = local->crypt_info.crypt[idx]; - sta = NULL; - - /* Use station specific key to override default keys if the - * receiver address is a unicast address ("individual RA"). If - * bcrx_sta_key parameter is set, station specific key is used - * even with broad/multicast targets (this is against IEEE - * 802.11, but makes it easier to use different keys with - * stations that do not support WEP key mapping). */ - - if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) - (void) hostap_handle_sta_crypto(local, hdr, &crypt, - &sta); - - /* allow NULL decrypt to indicate an station specific override - * for default encryption */ - if (crypt && (crypt->ops == NULL || - crypt->ops->decrypt_mpdu == NULL)) - crypt = NULL; - - if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) { -#if 0 - /* This seems to be triggered by some (multicast?) - * frames from other than current BSS, so just drop the - * frames silently instead of filling system log with - * these reports. */ - printk(KERN_DEBUG "%s: WEP decryption failed (not set)" - " (SA=%pM)\n", - local->dev->name, hdr->addr2); -#endif - local->comm_tallies.rx_discards_wep_undecryptable++; - goto rx_dropped; - } - } - - if (type != IEEE80211_FTYPE_DATA) { - if (type == IEEE80211_FTYPE_MGMT && - stype == IEEE80211_STYPE_AUTH && - fc & IEEE80211_FCTL_PROTECTED && local->host_decrypt && - (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0) - { - printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " - "from %pM\n", dev->name, hdr->addr2); - /* TODO: could inform hostapd about this so that it - * could send auth failure report */ - goto rx_dropped; - } - - if (hostap_rx_frame_mgmt(local, skb, rx_stats, type, stype)) - goto rx_dropped; - else - goto rx_exit; - } - - /* Data frame - extract src/dst addresses */ - if (skb->len < IEEE80211_DATA_HDR3_LEN) - goto rx_dropped; - - switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_FROMDS: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - break; - case IEEE80211_FCTL_TODS: - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - if (skb->len < IEEE80211_DATA_HDR4_LEN) - goto rx_dropped; - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - break; - case 0: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - break; - } - - if (hostap_rx_frame_wds(local, hdr, fc, &wds)) - goto rx_dropped; - if (wds) - skb->dev = dev = wds; - - if (local->iw_mode == IW_MODE_MASTER && !wds && - (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && - local->stadev && - memcmp(hdr->addr2, local->assoc_ap_addr, ETH_ALEN) == 0) { - /* Frame from BSSID of the AP for which we are a client */ - skb->dev = dev = local->stadev; - from_assoc_ap = 1; - } - - if ((local->iw_mode == IW_MODE_MASTER || - local->iw_mode == IW_MODE_REPEAT) && - !from_assoc_ap) { - switch (hostap_handle_sta_rx(local, dev, skb, rx_stats, - wds != NULL)) { - case AP_RX_CONTINUE_NOT_AUTHORIZED: - frame_authorized = 0; - break; - case AP_RX_CONTINUE: - frame_authorized = 1; - break; - case AP_RX_DROP: - goto rx_dropped; - case AP_RX_EXIT: - goto rx_exit; - } - } - - /* Nullfunc frames may have PS-bit set, so they must be passed to - * hostap_handle_sta_rx() before being dropped here. */ - if (stype != IEEE80211_STYPE_DATA && - stype != IEEE80211_STYPE_DATA_CFACK && - stype != IEEE80211_STYPE_DATA_CFPOLL && - stype != IEEE80211_STYPE_DATA_CFACKPOLL) { - if (stype != IEEE80211_STYPE_NULLFUNC) - printk(KERN_DEBUG "%s: RX: dropped data frame " - "with no data (type=0x%02x, subtype=0x%02x)\n", - dev->name, type >> 2, stype >> 4); - goto rx_dropped; - } - - /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ - - if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && - (keyidx = hostap_rx_frame_decrypt(local, skb, crypt)) < 0) - goto rx_dropped; - hdr = (struct ieee80211_hdr *) skb->data; - - /* skb: hdr + (possibly fragmented) plaintext payload */ - - if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && - (frag != 0 || (fc & IEEE80211_FCTL_MOREFRAGS))) { - int flen; - struct sk_buff *frag_skb = - prism2_frag_cache_get(local, hdr); - if (!frag_skb) { - printk(KERN_DEBUG "%s: Rx cannot get skb from " - "fragment cache (morefrag=%d seq=%u frag=%u)\n", - dev->name, (fc & IEEE80211_FCTL_MOREFRAGS) != 0, - (sc & IEEE80211_SCTL_SEQ) >> 4, frag); - goto rx_dropped; - } - - flen = skb->len; - if (frag != 0) - flen -= hdrlen; - - if (frag_skb->tail + flen > frag_skb->end) { - printk(KERN_WARNING "%s: host decrypted and " - "reassembled frame did not fit skb\n", - dev->name); - prism2_frag_cache_invalidate(local, hdr); - goto rx_dropped; - } - - if (frag == 0) { - /* copy first fragment (including full headers) into - * beginning of the fragment cache skb */ - skb_copy_from_linear_data(skb, skb_put(frag_skb, flen), - flen); - } else { - /* append frame payload to the end of the fragment - * cache skb */ - skb_copy_from_linear_data_offset(skb, hdrlen, - skb_put(frag_skb, - flen), flen); - } - dev_kfree_skb(skb); - skb = NULL; - - if (fc & IEEE80211_FCTL_MOREFRAGS) { - /* more fragments expected - leave the skb in fragment - * cache for now; it will be delivered to upper layers - * after all fragments have been received */ - goto rx_exit; - } - - /* this was the last fragment and the frame will be - * delivered, so remove skb from fragment cache */ - skb = frag_skb; - hdr = (struct ieee80211_hdr *) skb->data; - prism2_frag_cache_invalidate(local, hdr); - } - - /* skb: hdr + (possible reassembled) full MSDU payload; possibly still - * encrypted/authenticated */ - - if (local->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && - hostap_rx_frame_decrypt_msdu(local, skb, keyidx, crypt)) - goto rx_dropped; - - hdr = (struct ieee80211_hdr *) skb->data; - if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !local->open_wep) { - if (local->ieee_802_1x && - hostap_is_eapol_frame(local, skb)) { - /* pass unencrypted EAPOL frames even if encryption is - * configured */ - PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X - passing " - "unencrypted EAPOL frame\n", local->dev->name); - } else { - printk(KERN_DEBUG "%s: encryption configured, but RX " - "frame not encrypted (SA=%pM)\n", - local->dev->name, hdr->addr2); - goto rx_dropped; - } - } - - if (local->drop_unencrypted && !(fc & IEEE80211_FCTL_PROTECTED) && - !hostap_is_eapol_frame(local, skb)) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: dropped unencrypted RX data " - "frame from %pM (drop_unencrypted=1)\n", - dev->name, hdr->addr2); - } - goto rx_dropped; - } - - /* skb: hdr + (possible reassembled) full plaintext payload */ - - payload = skb->data + hdrlen; - ethertype = (payload[6] << 8) | payload[7]; - - /* If IEEE 802.1X is used, check whether the port is authorized to send - * the received frame. */ - if (local->ieee_802_1x && local->iw_mode == IW_MODE_MASTER) { - if (ethertype == ETH_P_PAE) { - PDEBUG(DEBUG_EXTRA2, "%s: RX: IEEE 802.1X frame\n", - dev->name); - if (local->hostapd && local->apdev) { - /* Send IEEE 802.1X frames to the user - * space daemon for processing */ - prism2_rx_80211(local->apdev, skb, rx_stats, - PRISM2_RX_MGMT); - local->apdevstats.rx_packets++; - local->apdevstats.rx_bytes += skb->len; - goto rx_exit; - } - } else if (!frame_authorized) { - printk(KERN_DEBUG "%s: dropped frame from " - "unauthorized port (IEEE 802.1X): " - "ethertype=0x%04x\n", - dev->name, ethertype); - goto rx_dropped; - } - } - - /* convert hdr + possible LLC headers into Ethernet header */ - if (skb->len - hdrlen >= 8 && - ((memcmp(payload, rfc1042_header, 6) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - memcmp(payload, bridge_tunnel_header, 6) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ - skb_pull(skb, hdrlen + 6); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } else { - __be16 len; - /* Leave Ethernet header part of hdr and full payload */ - skb_pull(skb, hdrlen); - len = htons(skb->len); - memcpy(skb_push(skb, 2), &len, 2); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } - - if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS) && - skb->len >= ETH_HLEN + ETH_ALEN) { - /* Non-standard frame: get addr4 from its bogus location after - * the payload */ - skb_copy_from_linear_data_offset(skb, skb->len - ETH_ALEN, - skb->data + ETH_ALEN, - ETH_ALEN); - skb_trim(skb, skb->len - ETH_ALEN); - } - - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - - if (local->iw_mode == IW_MODE_MASTER && !wds && - local->ap->bridge_packets) { - if (dst[0] & 0x01) { - /* copy multicast frame both to the higher layers and - * to the wireless media */ - local->ap->bridged_multicast++; - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - printk(KERN_DEBUG "%s: skb_clone failed for " - "multicast frame\n", dev->name); - } else if (hostap_is_sta_authorized(local->ap, dst)) { - /* send frame directly to the associated STA using - * wireless media and not passing to higher layers */ - local->ap->bridged_unicast++; - skb2 = skb; - skb = NULL; - } - } - - if (skb2 != NULL) { - /* send to wireless media */ - skb2->dev = dev; - skb2->protocol = cpu_to_be16(ETH_P_802_3); - skb_reset_mac_header(skb2); - skb_reset_network_header(skb2); - /* skb2->network_header += ETH_HLEN; */ - dev_queue_xmit(skb2); - } - - if (skb) { - skb->protocol = eth_type_trans(skb, dev); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); - } - - rx_exit: - if (sta) - hostap_handle_sta_release(sta); - return; - - rx_dropped: - dev_kfree_skb(skb); - - dev->stats.rx_dropped++; - goto rx_exit; -} - - -EXPORT_SYMBOL(hostap_80211_rx); diff --git a/drivers/net/wireless/hostap/hostap_80211_tx.c b/drivers/net/wireless/hostap/hostap_80211_tx.c deleted file mode 100644 index 90108b698f11..000000000000 --- a/drivers/net/wireless/hostap/hostap_80211_tx.c +++ /dev/null @@ -1,550 +0,0 @@ -#include "hostap_80211.h" -#include "hostap_common.h" -#include "hostap_wlan.h" -#include "hostap.h" -#include "hostap_ap.h" - -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char rfc1042_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char bridge_tunnel_header[] = -{ 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -/* No encapsulation header if EtherType < 0x600 (=length) */ - -void hostap_dump_tx_80211(const char *name, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - u16 fc; - - hdr = (struct ieee80211_hdr *) skb->data; - - printk(KERN_DEBUG "%s: TX len=%d jiffies=%ld\n", - name, skb->len, jiffies); - - if (skb->len < 2) - return; - - fc = le16_to_cpu(hdr->frame_control); - printk(KERN_DEBUG " FC=0x%04x (type=%d:%d)%s%s", - fc, (fc & IEEE80211_FCTL_FTYPE) >> 2, - (fc & IEEE80211_FCTL_STYPE) >> 4, - fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "", - fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : ""); - - if (skb->len < IEEE80211_DATA_HDR3_LEN) { - printk("\n"); - return; - } - - printk(" dur=0x%04x seq=0x%04x\n", le16_to_cpu(hdr->duration_id), - le16_to_cpu(hdr->seq_ctrl)); - - printk(KERN_DEBUG " A1=%pM", hdr->addr1); - printk(" A2=%pM", hdr->addr2); - printk(" A3=%pM", hdr->addr3); - if (skb->len >= 30) - printk(" A4=%pM", hdr->addr4); - printk("\n"); -} - - -/* hard_start_xmit function for data interfaces (wlan#, wlan#wds#, wlan#sta) - * Convert Ethernet header into a suitable IEEE 802.11 header depending on - * device configuration. */ -netdev_tx_t hostap_data_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - int need_headroom, need_tailroom = 0; - struct ieee80211_hdr hdr; - u16 fc, ethertype = 0; - enum { - WDS_NO = 0, WDS_OWN_FRAME, WDS_COMPLIANT_FRAME - } use_wds = WDS_NO; - u8 *encaps_data; - int hdr_len, encaps_len, skip_header_bytes; - int to_assoc_ap = 0; - struct hostap_skb_tx_data *meta; - - iface = netdev_priv(dev); - local = iface->local; - - if (skb->len < ETH_HLEN) { - printk(KERN_DEBUG "%s: hostap_data_start_xmit: short skb " - "(len=%d)\n", dev->name, skb->len); - kfree_skb(skb); - return NETDEV_TX_OK; - } - - if (local->ddev != dev) { - use_wds = (local->iw_mode == IW_MODE_MASTER && - !(local->wds_type & HOSTAP_WDS_STANDARD_FRAME)) ? - WDS_OWN_FRAME : WDS_COMPLIANT_FRAME; - if (dev == local->stadev) { - to_assoc_ap = 1; - use_wds = WDS_NO; - } else if (dev == local->apdev) { - printk(KERN_DEBUG "%s: prism2_tx: trying to use " - "AP device with Ethernet net dev\n", dev->name); - kfree_skb(skb); - return NETDEV_TX_OK; - } - } else { - if (local->iw_mode == IW_MODE_REPEAT) { - printk(KERN_DEBUG "%s: prism2_tx: trying to use " - "non-WDS link in Repeater mode\n", dev->name); - kfree_skb(skb); - return NETDEV_TX_OK; - } else if (local->iw_mode == IW_MODE_INFRA && - (local->wds_type & HOSTAP_WDS_AP_CLIENT) && - memcmp(skb->data + ETH_ALEN, dev->dev_addr, - ETH_ALEN) != 0) { - /* AP client mode: send frames with foreign src addr - * using 4-addr WDS frames */ - use_wds = WDS_COMPLIANT_FRAME; - } - } - - /* Incoming skb->data: dst_addr[6], src_addr[6], proto[2], payload - * ==> - * Prism2 TX frame with 802.11 header: - * txdesc (address order depending on used mode; includes dst_addr and - * src_addr), possible encapsulation (RFC1042/Bridge-Tunnel; - * proto[2], payload {, possible addr4[6]} */ - - ethertype = (skb->data[12] << 8) | skb->data[13]; - - memset(&hdr, 0, sizeof(hdr)); - - /* Length of data after IEEE 802.11 header */ - encaps_data = NULL; - encaps_len = 0; - skip_header_bytes = ETH_HLEN; - if (ethertype == ETH_P_AARP || ethertype == ETH_P_IPX) { - encaps_data = bridge_tunnel_header; - encaps_len = sizeof(bridge_tunnel_header); - skip_header_bytes -= 2; - } else if (ethertype >= 0x600) { - encaps_data = rfc1042_header; - encaps_len = sizeof(rfc1042_header); - skip_header_bytes -= 2; - } - - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; - hdr_len = IEEE80211_DATA_HDR3_LEN; - - if (use_wds != WDS_NO) { - /* Note! Prism2 station firmware has problems with sending real - * 802.11 frames with four addresses; until these problems can - * be fixed or worked around, 4-addr frames needed for WDS are - * using incompatible format: FromDS flag is not set and the - * fourth address is added after the frame payload; it is - * assumed, that the receiving station knows how to handle this - * frame format */ - - if (use_wds == WDS_COMPLIANT_FRAME) { - fc |= IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS; - /* From&To DS: Addr1 = RA, Addr2 = TA, Addr3 = DA, - * Addr4 = SA */ - skb_copy_from_linear_data_offset(skb, ETH_ALEN, - &hdr.addr4, ETH_ALEN); - hdr_len += ETH_ALEN; - } else { - /* bogus 4-addr format to workaround Prism2 station - * f/w bug */ - fc |= IEEE80211_FCTL_TODS; - /* From DS: Addr1 = DA (used as RA), - * Addr2 = BSSID (used as TA), Addr3 = SA (used as DA), - */ - - /* SA from skb->data + ETH_ALEN will be added after - * frame payload; use hdr.addr4 as a temporary buffer - */ - skb_copy_from_linear_data_offset(skb, ETH_ALEN, - &hdr.addr4, ETH_ALEN); - need_tailroom += ETH_ALEN; - } - - /* send broadcast and multicast frames to broadcast RA, if - * configured; otherwise, use unicast RA of the WDS link */ - if ((local->wds_type & HOSTAP_WDS_BROADCAST_RA) && - skb->data[0] & 0x01) - memset(&hdr.addr1, 0xff, ETH_ALEN); - else if (iface->type == HOSTAP_INTERFACE_WDS) - memcpy(&hdr.addr1, iface->u.wds.remote_addr, - ETH_ALEN); - else - memcpy(&hdr.addr1, local->bssid, ETH_ALEN); - memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN); - skb_copy_from_linear_data(skb, &hdr.addr3, ETH_ALEN); - } else if (local->iw_mode == IW_MODE_MASTER && !to_assoc_ap) { - fc |= IEEE80211_FCTL_FROMDS; - /* From DS: Addr1 = DA, Addr2 = BSSID, Addr3 = SA */ - skb_copy_from_linear_data(skb, &hdr.addr1, ETH_ALEN); - memcpy(&hdr.addr2, dev->dev_addr, ETH_ALEN); - skb_copy_from_linear_data_offset(skb, ETH_ALEN, &hdr.addr3, - ETH_ALEN); - } else if (local->iw_mode == IW_MODE_INFRA || to_assoc_ap) { - fc |= IEEE80211_FCTL_TODS; - /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ - memcpy(&hdr.addr1, to_assoc_ap ? - local->assoc_ap_addr : local->bssid, ETH_ALEN); - skb_copy_from_linear_data_offset(skb, ETH_ALEN, &hdr.addr2, - ETH_ALEN); - skb_copy_from_linear_data(skb, &hdr.addr3, ETH_ALEN); - } else if (local->iw_mode == IW_MODE_ADHOC) { - /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ - skb_copy_from_linear_data(skb, &hdr.addr1, ETH_ALEN); - skb_copy_from_linear_data_offset(skb, ETH_ALEN, &hdr.addr2, - ETH_ALEN); - memcpy(&hdr.addr3, local->bssid, ETH_ALEN); - } - - hdr.frame_control = cpu_to_le16(fc); - - skb_pull(skb, skip_header_bytes); - need_headroom = local->func->need_tx_headroom + hdr_len + encaps_len; - if (skb_tailroom(skb) < need_tailroom) { - skb = skb_unshare(skb, GFP_ATOMIC); - if (skb == NULL) { - iface->stats.tx_dropped++; - return NETDEV_TX_OK; - } - if (pskb_expand_head(skb, need_headroom, need_tailroom, - GFP_ATOMIC)) { - kfree_skb(skb); - iface->stats.tx_dropped++; - return NETDEV_TX_OK; - } - } else if (skb_headroom(skb) < need_headroom) { - struct sk_buff *tmp = skb; - skb = skb_realloc_headroom(skb, need_headroom); - kfree_skb(tmp); - if (skb == NULL) { - iface->stats.tx_dropped++; - return NETDEV_TX_OK; - } - } else { - skb = skb_unshare(skb, GFP_ATOMIC); - if (skb == NULL) { - iface->stats.tx_dropped++; - return NETDEV_TX_OK; - } - } - - if (encaps_data) - memcpy(skb_push(skb, encaps_len), encaps_data, encaps_len); - memcpy(skb_push(skb, hdr_len), &hdr, hdr_len); - if (use_wds == WDS_OWN_FRAME) { - memcpy(skb_put(skb, ETH_ALEN), &hdr.addr4, ETH_ALEN); - } - - iface->stats.tx_packets++; - iface->stats.tx_bytes += skb->len; - - skb_reset_mac_header(skb); - meta = (struct hostap_skb_tx_data *) skb->cb; - memset(meta, 0, sizeof(*meta)); - meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; - if (use_wds) - meta->flags |= HOSTAP_TX_FLAGS_WDS; - meta->ethertype = ethertype; - meta->iface = iface; - - /* Send IEEE 802.11 encapsulated frame using the master radio device */ - skb->dev = local->dev; - dev_queue_xmit(skb); - return NETDEV_TX_OK; -} - - -/* hard_start_xmit function for hostapd wlan#ap interfaces */ -netdev_tx_t hostap_mgmt_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hostap_skb_tx_data *meta; - struct ieee80211_hdr *hdr; - u16 fc; - - iface = netdev_priv(dev); - local = iface->local; - - if (skb->len < 10) { - printk(KERN_DEBUG "%s: hostap_mgmt_start_xmit: short skb " - "(len=%d)\n", dev->name, skb->len); - kfree_skb(skb); - return NETDEV_TX_OK; - } - - iface->stats.tx_packets++; - iface->stats.tx_bytes += skb->len; - - meta = (struct hostap_skb_tx_data *) skb->cb; - memset(meta, 0, sizeof(*meta)); - meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; - meta->iface = iface; - - if (skb->len >= IEEE80211_DATA_HDR3_LEN + sizeof(rfc1042_header) + 2) { - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - if (ieee80211_is_data(hdr->frame_control) && - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DATA) { - u8 *pos = &skb->data[IEEE80211_DATA_HDR3_LEN + - sizeof(rfc1042_header)]; - meta->ethertype = (pos[0] << 8) | pos[1]; - } - } - - /* Send IEEE 802.11 encapsulated frame using the master radio device */ - skb->dev = local->dev; - dev_queue_xmit(skb); - return NETDEV_TX_OK; -} - - -/* Called only from software IRQ */ -static struct sk_buff * hostap_tx_encrypt(struct sk_buff *skb, - struct lib80211_crypt_data *crypt) -{ - struct hostap_interface *iface; - local_info_t *local; - struct ieee80211_hdr *hdr; - int prefix_len, postfix_len, hdr_len, res; - - iface = netdev_priv(skb->dev); - local = iface->local; - - if (skb->len < IEEE80211_DATA_HDR3_LEN) { - kfree_skb(skb); - return NULL; - } - - if (local->tkip_countermeasures && - strcmp(crypt->ops->name, "TKIP") == 0) { - hdr = (struct ieee80211_hdr *) skb->data; - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: TKIP countermeasures: dropped " - "TX packet to %pM\n", - local->dev->name, hdr->addr1); - } - kfree_skb(skb); - return NULL; - } - - skb = skb_unshare(skb, GFP_ATOMIC); - if (skb == NULL) - return NULL; - - prefix_len = crypt->ops->extra_mpdu_prefix_len + - crypt->ops->extra_msdu_prefix_len; - postfix_len = crypt->ops->extra_mpdu_postfix_len + - crypt->ops->extra_msdu_postfix_len; - if ((skb_headroom(skb) < prefix_len || - skb_tailroom(skb) < postfix_len) && - pskb_expand_head(skb, prefix_len, postfix_len, GFP_ATOMIC)) { - kfree_skb(skb); - return NULL; - } - - hdr = (struct ieee80211_hdr *) skb->data; - hdr_len = hostap_80211_get_hdrlen(hdr->frame_control); - - /* Host-based IEEE 802.11 fragmentation for TX is not yet supported, so - * call both MSDU and MPDU encryption functions from here. */ - atomic_inc(&crypt->refcnt); - res = 0; - if (crypt->ops->encrypt_msdu) - res = crypt->ops->encrypt_msdu(skb, hdr_len, crypt->priv); - if (res == 0 && crypt->ops->encrypt_mpdu) - res = crypt->ops->encrypt_mpdu(skb, hdr_len, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - kfree_skb(skb); - return NULL; - } - - return skb; -} - - -/* hard_start_xmit function for master radio interface wifi#. - * AP processing (TX rate control, power save buffering, etc.). - * Use hardware TX function to send the frame. */ -netdev_tx_t hostap_master_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - netdev_tx_t ret = NETDEV_TX_BUSY; - u16 fc; - struct hostap_tx_data tx; - ap_tx_ret tx_ret; - struct hostap_skb_tx_data *meta; - int no_encrypt = 0; - struct ieee80211_hdr *hdr; - - iface = netdev_priv(dev); - local = iface->local; - - tx.skb = skb; - tx.sta_ptr = NULL; - - meta = (struct hostap_skb_tx_data *) skb->cb; - if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) { - printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, " - "expected 0x%08x)\n", - dev->name, meta->magic, HOSTAP_SKB_TX_DATA_MAGIC); - ret = NETDEV_TX_OK; - iface->stats.tx_dropped++; - goto fail; - } - - if (local->host_encrypt) { - /* Set crypt to default algorithm and key; will be replaced in - * AP code if STA has own alg/key */ - tx.crypt = local->crypt_info.crypt[local->crypt_info.tx_keyidx]; - tx.host_encrypt = 1; - } else { - tx.crypt = NULL; - tx.host_encrypt = 0; - } - - if (skb->len < 24) { - printk(KERN_DEBUG "%s: hostap_master_start_xmit: short skb " - "(len=%d)\n", dev->name, skb->len); - ret = NETDEV_TX_OK; - iface->stats.tx_dropped++; - goto fail; - } - - /* FIX (?): - * Wi-Fi 802.11b test plan suggests that AP should ignore power save - * bit in authentication and (re)association frames and assume tha - * STA remains awake for the response. */ - tx_ret = hostap_handle_sta_tx(local, &tx); - skb = tx.skb; - meta = (struct hostap_skb_tx_data *) skb->cb; - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - switch (tx_ret) { - case AP_TX_CONTINUE: - break; - case AP_TX_CONTINUE_NOT_AUTHORIZED: - if (local->ieee_802_1x && - ieee80211_is_data(hdr->frame_control) && - meta->ethertype != ETH_P_PAE && - !(meta->flags & HOSTAP_TX_FLAGS_WDS)) { - printk(KERN_DEBUG "%s: dropped frame to unauthorized " - "port (IEEE 802.1X): ethertype=0x%04x\n", - dev->name, meta->ethertype); - hostap_dump_tx_80211(dev->name, skb); - - ret = NETDEV_TX_OK; /* drop packet */ - iface->stats.tx_dropped++; - goto fail; - } - break; - case AP_TX_DROP: - ret = NETDEV_TX_OK; /* drop packet */ - iface->stats.tx_dropped++; - goto fail; - case AP_TX_RETRY: - goto fail; - case AP_TX_BUFFERED: - /* do not free skb here, it will be freed when the - * buffered frame is sent/timed out */ - ret = NETDEV_TX_OK; - goto tx_exit; - } - - /* Request TX callback if protocol version is 2 in 802.11 header; - * this version 2 is a special case used between hostapd and kernel - * driver */ - if (((fc & IEEE80211_FCTL_VERS) == BIT(1)) && - local->ap && local->ap->tx_callback_idx && meta->tx_cb_idx == 0) { - meta->tx_cb_idx = local->ap->tx_callback_idx; - - /* remove special version from the frame header */ - fc &= ~IEEE80211_FCTL_VERS; - hdr->frame_control = cpu_to_le16(fc); - } - - if (!ieee80211_is_data(hdr->frame_control)) { - no_encrypt = 1; - tx.crypt = NULL; - } - - if (local->ieee_802_1x && meta->ethertype == ETH_P_PAE && tx.crypt && - !(fc & IEEE80211_FCTL_PROTECTED)) { - no_encrypt = 1; - PDEBUG(DEBUG_EXTRA2, "%s: TX: IEEE 802.1X - passing " - "unencrypted EAPOL frame\n", dev->name); - tx.crypt = NULL; /* no encryption for IEEE 802.1X frames */ - } - - if (tx.crypt && (!tx.crypt->ops || !tx.crypt->ops->encrypt_mpdu)) - tx.crypt = NULL; - else if ((tx.crypt || - local->crypt_info.crypt[local->crypt_info.tx_keyidx]) && - !no_encrypt) { - /* Add ISWEP flag both for firmware and host based encryption - */ - fc |= IEEE80211_FCTL_PROTECTED; - hdr->frame_control = cpu_to_le16(fc); - } else if (local->drop_unencrypted && - ieee80211_is_data(hdr->frame_control) && - meta->ethertype != ETH_P_PAE) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: dropped unencrypted TX data " - "frame (drop_unencrypted=1)\n", dev->name); - } - iface->stats.tx_dropped++; - ret = NETDEV_TX_OK; - goto fail; - } - - if (tx.crypt) { - skb = hostap_tx_encrypt(skb, tx.crypt); - if (skb == NULL) { - printk(KERN_DEBUG "%s: TX - encryption failed\n", - dev->name); - ret = NETDEV_TX_OK; - goto fail; - } - meta = (struct hostap_skb_tx_data *) skb->cb; - if (meta->magic != HOSTAP_SKB_TX_DATA_MAGIC) { - printk(KERN_DEBUG "%s: invalid skb->cb magic (0x%08x, " - "expected 0x%08x) after hostap_tx_encrypt\n", - dev->name, meta->magic, - HOSTAP_SKB_TX_DATA_MAGIC); - ret = NETDEV_TX_OK; - iface->stats.tx_dropped++; - goto fail; - } - } - - if (local->func->tx == NULL || local->func->tx(skb, dev)) { - ret = NETDEV_TX_OK; - iface->stats.tx_dropped++; - } else { - ret = NETDEV_TX_OK; - iface->stats.tx_packets++; - iface->stats.tx_bytes += skb->len; - } - - fail: - if (ret == NETDEV_TX_OK && skb) - dev_kfree_skb(skb); - tx_exit: - if (tx.sta_ptr) - hostap_handle_sta_release(tx.sta_ptr); - return ret; -} - - -EXPORT_SYMBOL(hostap_master_start_xmit); diff --git a/drivers/net/wireless/hostap/hostap_ap.c b/drivers/net/wireless/hostap/hostap_ap.c deleted file mode 100644 index a2a203c90ba3..000000000000 --- a/drivers/net/wireless/hostap/hostap_ap.c +++ /dev/null @@ -1,3271 +0,0 @@ -/* - * Intersil Prism2 driver with Host AP (software access point) support - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2005, Jouni Malinen - * - * This file is to be included into hostap.c when S/W AP functionality is - * compiled. - * - * AP: FIX: - * - if unicast Class 2 (assoc,reassoc,disassoc) frame received from - * unauthenticated STA, send deauth. frame (8802.11: 5.5) - * - if unicast Class 3 (data with to/from DS,deauth,pspoll) frame received - * from authenticated, but unassoc STA, send disassoc frame (8802.11: 5.5) - * - if unicast Class 3 received from unauthenticated STA, send deauth. frame - * (8802.11: 5.5) - */ - -#include -#include -#include -#include - -#include "hostap_wlan.h" -#include "hostap.h" -#include "hostap_ap.h" - -static int other_ap_policy[MAX_PARM_DEVICES] = { AP_OTHER_AP_SKIP_ALL, - DEF_INTS }; -module_param_array(other_ap_policy, int, NULL, 0444); -MODULE_PARM_DESC(other_ap_policy, "Other AP beacon monitoring policy (0-3)"); - -static int ap_max_inactivity[MAX_PARM_DEVICES] = { AP_MAX_INACTIVITY_SEC, - DEF_INTS }; -module_param_array(ap_max_inactivity, int, NULL, 0444); -MODULE_PARM_DESC(ap_max_inactivity, "AP timeout (in seconds) for station " - "inactivity"); - -static int ap_bridge_packets[MAX_PARM_DEVICES] = { 1, DEF_INTS }; -module_param_array(ap_bridge_packets, int, NULL, 0444); -MODULE_PARM_DESC(ap_bridge_packets, "Bridge packets directly between " - "stations"); - -static int autom_ap_wds[MAX_PARM_DEVICES] = { 0, DEF_INTS }; -module_param_array(autom_ap_wds, int, NULL, 0444); -MODULE_PARM_DESC(autom_ap_wds, "Add WDS connections to other APs " - "automatically"); - - -static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta); -static void hostap_event_expired_sta(struct net_device *dev, - struct sta_info *sta); -static void handle_add_proc_queue(struct work_struct *work); - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static void handle_wds_oper_queue(struct work_struct *work); -static void prism2_send_mgmt(struct net_device *dev, - u16 type_subtype, char *body, - int body_len, u8 *addr, u16 tx_cb_idx); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -#ifndef PRISM2_NO_PROCFS_DEBUG -static int ap_debug_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ap_data *ap = (struct ap_data *) data; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "BridgedUnicastFrames=%u\n", ap->bridged_unicast); - p += sprintf(p, "BridgedMulticastFrames=%u\n", ap->bridged_multicast); - p += sprintf(p, "max_inactivity=%u\n", ap->max_inactivity / HZ); - p += sprintf(p, "bridge_packets=%u\n", ap->bridge_packets); - p += sprintf(p, "nullfunc_ack=%u\n", ap->nullfunc_ack); - p += sprintf(p, "autom_ap_wds=%u\n", ap->autom_ap_wds); - p += sprintf(p, "auth_algs=%u\n", ap->local->auth_algs); - p += sprintf(p, "tx_drop_nonassoc=%u\n", ap->tx_drop_nonassoc); - - return (p - page); -} -#endif /* PRISM2_NO_PROCFS_DEBUG */ - - -static void ap_sta_hash_add(struct ap_data *ap, struct sta_info *sta) -{ - sta->hnext = ap->sta_hash[STA_HASH(sta->addr)]; - ap->sta_hash[STA_HASH(sta->addr)] = sta; -} - -static void ap_sta_hash_del(struct ap_data *ap, struct sta_info *sta) -{ - struct sta_info *s; - - s = ap->sta_hash[STA_HASH(sta->addr)]; - if (s == NULL) return; - if (memcmp(s->addr, sta->addr, ETH_ALEN) == 0) { - ap->sta_hash[STA_HASH(sta->addr)] = s->hnext; - return; - } - - while (s->hnext != NULL && memcmp(s->hnext->addr, sta->addr, ETH_ALEN) - != 0) - s = s->hnext; - if (s->hnext != NULL) - s->hnext = s->hnext->hnext; - else - printk("AP: could not remove STA %pM from hash table\n", - sta->addr); -} - -static void ap_free_sta(struct ap_data *ap, struct sta_info *sta) -{ - if (sta->ap && sta->local) - hostap_event_expired_sta(sta->local->dev, sta); - - if (ap->proc != NULL) { - char name[20]; - sprintf(name, "%pM", sta->addr); - remove_proc_entry(name, ap->proc); - } - - if (sta->crypt) { - sta->crypt->ops->deinit(sta->crypt->priv); - kfree(sta->crypt); - sta->crypt = NULL; - } - - skb_queue_purge(&sta->tx_buf); - - ap->num_sta--; -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (sta->aid > 0) - ap->sta_aid[sta->aid - 1] = NULL; - - if (!sta->ap && sta->u.sta.challenge) - kfree(sta->u.sta.challenge); - del_timer(&sta->timer); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - kfree(sta); -} - - -static void hostap_set_tim(local_info_t *local, int aid, int set) -{ - if (local->func->set_tim) - local->func->set_tim(local->dev, aid, set); -} - - -static void hostap_event_new_sta(struct net_device *dev, struct sta_info *sta) -{ - union iwreq_data wrqu; - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, IWEVREGISTERED, &wrqu, NULL); -} - - -static void hostap_event_expired_sta(struct net_device *dev, - struct sta_info *sta) -{ - union iwreq_data wrqu; - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.addr.sa_data, sta->addr, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, IWEVEXPIRED, &wrqu, NULL); -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - -static void ap_handle_timer(unsigned long data) -{ - struct sta_info *sta = (struct sta_info *) data; - local_info_t *local; - struct ap_data *ap; - unsigned long next_time = 0; - int was_assoc; - - if (sta == NULL || sta->local == NULL || sta->local->ap == NULL) { - PDEBUG(DEBUG_AP, "ap_handle_timer() called with NULL data\n"); - return; - } - - local = sta->local; - ap = local->ap; - was_assoc = sta->flags & WLAN_STA_ASSOC; - - if (atomic_read(&sta->users) != 0) - next_time = jiffies + HZ; - else if ((sta->flags & WLAN_STA_PERM) && !(sta->flags & WLAN_STA_AUTH)) - next_time = jiffies + ap->max_inactivity; - - if (time_before(jiffies, sta->last_rx + ap->max_inactivity)) { - /* station activity detected; reset timeout state */ - sta->timeout_next = STA_NULLFUNC; - next_time = sta->last_rx + ap->max_inactivity; - } else if (sta->timeout_next == STA_DISASSOC && - !(sta->flags & WLAN_STA_PENDING_POLL)) { - /* STA ACKed data nullfunc frame poll */ - sta->timeout_next = STA_NULLFUNC; - next_time = jiffies + ap->max_inactivity; - } - - if (next_time) { - sta->timer.expires = next_time; - add_timer(&sta->timer); - return; - } - - if (sta->ap) - sta->timeout_next = STA_DEAUTH; - - if (sta->timeout_next == STA_DEAUTH && !(sta->flags & WLAN_STA_PERM)) { - spin_lock(&ap->sta_table_lock); - ap_sta_hash_del(ap, sta); - list_del(&sta->list); - spin_unlock(&ap->sta_table_lock); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - } else if (sta->timeout_next == STA_DISASSOC) - sta->flags &= ~WLAN_STA_ASSOC; - - if (was_assoc && !(sta->flags & WLAN_STA_ASSOC) && !sta->ap) - hostap_event_expired_sta(local->dev, sta); - - if (sta->timeout_next == STA_DEAUTH && sta->aid > 0 && - !skb_queue_empty(&sta->tx_buf)) { - hostap_set_tim(local, sta->aid, 0); - sta->flags &= ~WLAN_STA_TIM; - } - - if (sta->ap) { - if (ap->autom_ap_wds) { - PDEBUG(DEBUG_AP, "%s: removing automatic WDS " - "connection to AP %pM\n", - local->dev->name, sta->addr); - hostap_wds_link_oper(local, sta->addr, WDS_DEL); - } - } else if (sta->timeout_next == STA_NULLFUNC) { - /* send data frame to poll STA and check whether this frame - * is ACKed */ - /* FIX: IEEE80211_STYPE_NULLFUNC would be more appropriate, but - * it is apparently not retried so TX Exc events are not - * received for it */ - sta->flags |= WLAN_STA_PENDING_POLL; - prism2_send_mgmt(local->dev, IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_DATA, NULL, 0, - sta->addr, ap->tx_callback_poll); - } else { - int deauth = sta->timeout_next == STA_DEAUTH; - __le16 resp; - PDEBUG(DEBUG_AP, "%s: sending %s info to STA %pM" - "(last=%lu, jiffies=%lu)\n", - local->dev->name, - deauth ? "deauthentication" : "disassociation", - sta->addr, sta->last_rx, jiffies); - - resp = cpu_to_le16(deauth ? WLAN_REASON_PREV_AUTH_NOT_VALID : - WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY); - prism2_send_mgmt(local->dev, IEEE80211_FTYPE_MGMT | - (deauth ? IEEE80211_STYPE_DEAUTH : - IEEE80211_STYPE_DISASSOC), - (char *) &resp, 2, sta->addr, 0); - } - - if (sta->timeout_next == STA_DEAUTH) { - if (sta->flags & WLAN_STA_PERM) { - PDEBUG(DEBUG_AP, "%s: STA %pM" - " would have been removed, " - "but it has 'perm' flag\n", - local->dev->name, sta->addr); - } else - ap_free_sta(ap, sta); - return; - } - - if (sta->timeout_next == STA_NULLFUNC) { - sta->timeout_next = STA_DISASSOC; - sta->timer.expires = jiffies + AP_DISASSOC_DELAY; - } else { - sta->timeout_next = STA_DEAUTH; - sta->timer.expires = jiffies + AP_DEAUTH_DELAY; - } - - add_timer(&sta->timer); -} - - -void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap, - int resend) -{ - u8 addr[ETH_ALEN]; - __le16 resp; - int i; - - PDEBUG(DEBUG_AP, "%s: Deauthenticate all stations\n", dev->name); - memset(addr, 0xff, ETH_ALEN); - - resp = cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - - /* deauth message sent; try to resend it few times; the message is - * broadcast, so it may be delayed until next DTIM; there is not much - * else we can do at this point since the driver is going to be shut - * down */ - for (i = 0; i < 5; i++) { - prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_DEAUTH, - (char *) &resp, 2, addr, 0); - - if (!resend || ap->num_sta <= 0) - return; - - mdelay(50); - } -} - - -static int ap_control_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ap_data *ap = (struct ap_data *) data; - char *policy_txt; - struct mac_entry *entry; - - if (off != 0) { - *eof = 1; - return 0; - } - - switch (ap->mac_restrictions.policy) { - case MAC_POLICY_OPEN: - policy_txt = "open"; - break; - case MAC_POLICY_ALLOW: - policy_txt = "allow"; - break; - case MAC_POLICY_DENY: - policy_txt = "deny"; - break; - default: - policy_txt = "unknown"; - break; - }; - p += sprintf(p, "MAC policy: %s\n", policy_txt); - p += sprintf(p, "MAC entries: %u\n", ap->mac_restrictions.entries); - p += sprintf(p, "MAC list:\n"); - spin_lock_bh(&ap->mac_restrictions.lock); - list_for_each_entry(entry, &ap->mac_restrictions.mac_list, list) { - if (p - page > PAGE_SIZE - 80) { - p += sprintf(p, "All entries did not fit one page.\n"); - break; - } - - p += sprintf(p, "%pM\n", entry->addr); - } - spin_unlock_bh(&ap->mac_restrictions.lock); - - return (p - page); -} - - -int ap_control_add_mac(struct mac_restrictions *mac_restrictions, u8 *mac) -{ - struct mac_entry *entry; - - entry = kmalloc(sizeof(struct mac_entry), GFP_KERNEL); - if (entry == NULL) - return -1; - - memcpy(entry->addr, mac, ETH_ALEN); - - spin_lock_bh(&mac_restrictions->lock); - list_add_tail(&entry->list, &mac_restrictions->mac_list); - mac_restrictions->entries++; - spin_unlock_bh(&mac_restrictions->lock); - - return 0; -} - - -int ap_control_del_mac(struct mac_restrictions *mac_restrictions, u8 *mac) -{ - struct list_head *ptr; - struct mac_entry *entry; - - spin_lock_bh(&mac_restrictions->lock); - for (ptr = mac_restrictions->mac_list.next; - ptr != &mac_restrictions->mac_list; ptr = ptr->next) { - entry = list_entry(ptr, struct mac_entry, list); - - if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { - list_del(ptr); - kfree(entry); - mac_restrictions->entries--; - spin_unlock_bh(&mac_restrictions->lock); - return 0; - } - } - spin_unlock_bh(&mac_restrictions->lock); - return -1; -} - - -static int ap_control_mac_deny(struct mac_restrictions *mac_restrictions, - u8 *mac) -{ - struct mac_entry *entry; - int found = 0; - - if (mac_restrictions->policy == MAC_POLICY_OPEN) - return 0; - - spin_lock_bh(&mac_restrictions->lock); - list_for_each_entry(entry, &mac_restrictions->mac_list, list) { - if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { - found = 1; - break; - } - } - spin_unlock_bh(&mac_restrictions->lock); - - if (mac_restrictions->policy == MAC_POLICY_ALLOW) - return !found; - else - return found; -} - - -void ap_control_flush_macs(struct mac_restrictions *mac_restrictions) -{ - struct list_head *ptr, *n; - struct mac_entry *entry; - - if (mac_restrictions->entries == 0) - return; - - spin_lock_bh(&mac_restrictions->lock); - for (ptr = mac_restrictions->mac_list.next, n = ptr->next; - ptr != &mac_restrictions->mac_list; - ptr = n, n = ptr->next) { - entry = list_entry(ptr, struct mac_entry, list); - list_del(ptr); - kfree(entry); - } - mac_restrictions->entries = 0; - spin_unlock_bh(&mac_restrictions->lock); -} - - -int ap_control_kick_mac(struct ap_data *ap, struct net_device *dev, u8 *mac) -{ - struct sta_info *sta; - __le16 resp; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, mac); - if (sta) { - ap_sta_hash_del(ap, sta); - list_del(&sta->list); - } - spin_unlock_bh(&ap->sta_table_lock); - - if (!sta) - return -EINVAL; - - resp = cpu_to_le16(WLAN_REASON_PREV_AUTH_NOT_VALID); - prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_DEAUTH, - (char *) &resp, 2, sta->addr, 0); - - if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap) - hostap_event_expired_sta(dev, sta); - - ap_free_sta(ap, sta); - - return 0; -} - -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -void ap_control_kickall(struct ap_data *ap) -{ - struct list_head *ptr, *n; - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - for (ptr = ap->sta_list.next, n = ptr->next; ptr != &ap->sta_list; - ptr = n, n = ptr->next) { - sta = list_entry(ptr, struct sta_info, list); - ap_sta_hash_del(ap, sta); - list_del(&sta->list); - if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) - hostap_event_expired_sta(sta->local->dev, sta); - ap_free_sta(ap, sta); - } - spin_unlock_bh(&ap->sta_table_lock); -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - -#define PROC_LIMIT (PAGE_SIZE - 80) - -static int prism2_ap_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct ap_data *ap = (struct ap_data *) data; - struct sta_info *sta; - int i; - - if (off > PROC_LIMIT) { - *eof = 1; - return 0; - } - - p += sprintf(p, "# BSSID CHAN SIGNAL NOISE RATE SSID FLAGS\n"); - spin_lock_bh(&ap->sta_table_lock); - list_for_each_entry(sta, &ap->sta_list, list) { - if (!sta->ap) - continue; - - p += sprintf(p, "%pM %d %d %d %d '", - sta->addr, - sta->u.ap.channel, sta->last_rx_signal, - sta->last_rx_silence, sta->last_rx_rate); - for (i = 0; i < sta->u.ap.ssid_len; i++) - p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 && - sta->u.ap.ssid[i] < 127) ? - "%c" : "<%02x>"), - sta->u.ap.ssid[i]); - p += sprintf(p, "'"); - if (sta->capability & WLAN_CAPABILITY_ESS) - p += sprintf(p, " [ESS]"); - if (sta->capability & WLAN_CAPABILITY_IBSS) - p += sprintf(p, " [IBSS]"); - if (sta->capability & WLAN_CAPABILITY_PRIVACY) - p += sprintf(p, " [WEP]"); - p += sprintf(p, "\n"); - - if ((p - page) > PROC_LIMIT) { - printk(KERN_DEBUG "hostap: ap proc did not fit\n"); - break; - } - } - spin_unlock_bh(&ap->sta_table_lock); - - if ((p - page) <= off) { - *eof = 1; - return 0; - } - - *start = page + off; - - return (p - page - off); -} -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver) -{ - if (!ap) - return; - - if (sta_fw_ver == PRISM2_FW_VER(0,8,0)) { - PDEBUG(DEBUG_AP, "Using data::nullfunc ACK workaround - " - "firmware upgrade recommended\n"); - ap->nullfunc_ack = 1; - } else - ap->nullfunc_ack = 0; - - if (sta_fw_ver == PRISM2_FW_VER(1,4,2)) { - printk(KERN_WARNING "%s: Warning: secondary station firmware " - "version 1.4.2 does not seem to work in Host AP mode\n", - ap->local->dev->name); - } -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_ap_tx_cb(struct sk_buff *skb, int ok, void *data) -{ - struct ap_data *ap = data; - struct ieee80211_hdr *hdr; - - if (!ap->local->hostapd || !ap->local->apdev) { - dev_kfree_skb(skb); - return; - } - - /* Pass the TX callback frame to the hostapd; use 802.11 header version - * 1 to indicate failure (no ACK) and 2 success (frame ACKed) */ - - hdr = (struct ieee80211_hdr *) skb->data; - hdr->frame_control &= cpu_to_le16(~IEEE80211_FCTL_VERS); - hdr->frame_control |= cpu_to_le16(ok ? BIT(1) : BIT(0)); - - skb->dev = ap->local->apdev; - skb_pull(skb, hostap_80211_get_hdrlen(hdr->frame_control)); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = cpu_to_be16(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -/* Called only as a tasklet (software IRQ) */ -static void hostap_ap_tx_cb_auth(struct sk_buff *skb, int ok, void *data) -{ - struct ap_data *ap = data; - struct net_device *dev = ap->local->dev; - struct ieee80211_hdr *hdr; - u16 auth_alg, auth_transaction, status; - __le16 *pos; - struct sta_info *sta = NULL; - char *txt = NULL; - - if (ap->local->hostapd) { - dev_kfree_skb(skb); - return; - } - - hdr = (struct ieee80211_hdr *) skb->data; - if (!ieee80211_is_auth(hdr->frame_control) || - skb->len < IEEE80211_MGMT_HDR_LEN + 6) { - printk(KERN_DEBUG "%s: hostap_ap_tx_cb_auth received invalid " - "frame\n", dev->name); - dev_kfree_skb(skb); - return; - } - - pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN); - auth_alg = le16_to_cpu(*pos++); - auth_transaction = le16_to_cpu(*pos++); - status = le16_to_cpu(*pos++); - - if (!ok) { - txt = "frame was not ACKed"; - goto done; - } - - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, hdr->addr1); - if (sta) - atomic_inc(&sta->users); - spin_unlock(&ap->sta_table_lock); - - if (!sta) { - txt = "STA not found"; - goto done; - } - - if (status == WLAN_STATUS_SUCCESS && - ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 2) || - (auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 4))) { - txt = "STA authenticated"; - sta->flags |= WLAN_STA_AUTH; - sta->last_auth = jiffies; - } else if (status != WLAN_STATUS_SUCCESS) - txt = "authentication failed"; - - done: - if (sta) - atomic_dec(&sta->users); - if (txt) { - PDEBUG(DEBUG_AP, "%s: %pM auth_cb - alg=%d " - "trans#=%d status=%d - %s\n", - dev->name, hdr->addr1, - auth_alg, auth_transaction, status, txt); - } - dev_kfree_skb(skb); -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_ap_tx_cb_assoc(struct sk_buff *skb, int ok, void *data) -{ - struct ap_data *ap = data; - struct net_device *dev = ap->local->dev; - struct ieee80211_hdr *hdr; - u16 fc, status; - __le16 *pos; - struct sta_info *sta = NULL; - char *txt = NULL; - - if (ap->local->hostapd) { - dev_kfree_skb(skb); - return; - } - - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - if ((!ieee80211_is_assoc_resp(hdr->frame_control) && - !ieee80211_is_reassoc_resp(hdr->frame_control)) || - skb->len < IEEE80211_MGMT_HDR_LEN + 4) { - printk(KERN_DEBUG "%s: hostap_ap_tx_cb_assoc received invalid " - "frame\n", dev->name); - dev_kfree_skb(skb); - return; - } - - if (!ok) { - txt = "frame was not ACKed"; - goto done; - } - - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, hdr->addr1); - if (sta) - atomic_inc(&sta->users); - spin_unlock(&ap->sta_table_lock); - - if (!sta) { - txt = "STA not found"; - goto done; - } - - pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN); - pos++; - status = le16_to_cpu(*pos++); - if (status == WLAN_STATUS_SUCCESS) { - if (!(sta->flags & WLAN_STA_ASSOC)) - hostap_event_new_sta(dev, sta); - txt = "STA associated"; - sta->flags |= WLAN_STA_ASSOC; - sta->last_assoc = jiffies; - } else - txt = "association failed"; - - done: - if (sta) - atomic_dec(&sta->users); - if (txt) { - PDEBUG(DEBUG_AP, "%s: %pM assoc_cb - %s\n", - dev->name, hdr->addr1, txt); - } - dev_kfree_skb(skb); -} - -/* Called only as a tasklet (software IRQ); TX callback for poll frames used - * in verifying whether the STA is still present. */ -static void hostap_ap_tx_cb_poll(struct sk_buff *skb, int ok, void *data) -{ - struct ap_data *ap = data; - struct ieee80211_hdr *hdr; - struct sta_info *sta; - - if (skb->len < 24) - goto fail; - hdr = (struct ieee80211_hdr *) skb->data; - if (ok) { - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, hdr->addr1); - if (sta) - sta->flags &= ~WLAN_STA_PENDING_POLL; - spin_unlock(&ap->sta_table_lock); - } else { - PDEBUG(DEBUG_AP, - "%s: STA %pM did not ACK activity poll frame\n", - ap->local->dev->name, hdr->addr1); - } - - fail: - dev_kfree_skb(skb); -} -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -void hostap_init_data(local_info_t *local) -{ - struct ap_data *ap = local->ap; - - if (ap == NULL) { - printk(KERN_WARNING "hostap_init_data: ap == NULL\n"); - return; - } - memset(ap, 0, sizeof(struct ap_data)); - ap->local = local; - - ap->ap_policy = GET_INT_PARM(other_ap_policy, local->card_idx); - ap->bridge_packets = GET_INT_PARM(ap_bridge_packets, local->card_idx); - ap->max_inactivity = - GET_INT_PARM(ap_max_inactivity, local->card_idx) * HZ; - ap->autom_ap_wds = GET_INT_PARM(autom_ap_wds, local->card_idx); - - spin_lock_init(&ap->sta_table_lock); - INIT_LIST_HEAD(&ap->sta_list); - - /* Initialize task queue structure for AP management */ - INIT_WORK(&local->ap->add_sta_proc_queue, handle_add_proc_queue); - - ap->tx_callback_idx = - hostap_tx_callback_register(local, hostap_ap_tx_cb, ap); - if (ap->tx_callback_idx == 0) - printk(KERN_WARNING "%s: failed to register TX callback for " - "AP\n", local->dev->name); -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - INIT_WORK(&local->ap->wds_oper_queue, handle_wds_oper_queue); - - ap->tx_callback_auth = - hostap_tx_callback_register(local, hostap_ap_tx_cb_auth, ap); - ap->tx_callback_assoc = - hostap_tx_callback_register(local, hostap_ap_tx_cb_assoc, ap); - ap->tx_callback_poll = - hostap_tx_callback_register(local, hostap_ap_tx_cb_poll, ap); - if (ap->tx_callback_auth == 0 || ap->tx_callback_assoc == 0 || - ap->tx_callback_poll == 0) - printk(KERN_WARNING "%s: failed to register TX callback for " - "AP\n", local->dev->name); - - spin_lock_init(&ap->mac_restrictions.lock); - INIT_LIST_HEAD(&ap->mac_restrictions.mac_list); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - ap->initialized = 1; -} - - -void hostap_init_ap_proc(local_info_t *local) -{ - struct ap_data *ap = local->ap; - - ap->proc = local->proc; - if (ap->proc == NULL) - return; - -#ifndef PRISM2_NO_PROCFS_DEBUG - create_proc_read_entry("ap_debug", 0, ap->proc, - ap_debug_proc_read, ap); -#endif /* PRISM2_NO_PROCFS_DEBUG */ - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - create_proc_read_entry("ap_control", 0, ap->proc, - ap_control_proc_read, ap); - create_proc_read_entry("ap", 0, ap->proc, - prism2_ap_proc_read, ap); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - -} - - -void hostap_free_data(struct ap_data *ap) -{ - struct sta_info *n, *sta; - - if (ap == NULL || !ap->initialized) { - printk(KERN_DEBUG "hostap_free_data: ap has not yet been " - "initialized - skip resource freeing\n"); - return; - } - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (ap->crypt) - ap->crypt->deinit(ap->crypt_priv); - ap->crypt = ap->crypt_priv = NULL; -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - list_for_each_entry_safe(sta, n, &ap->sta_list, list) { - ap_sta_hash_del(ap, sta); - list_del(&sta->list); - if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) - hostap_event_expired_sta(sta->local->dev, sta); - ap_free_sta(ap, sta); - } - -#ifndef PRISM2_NO_PROCFS_DEBUG - if (ap->proc != NULL) { - remove_proc_entry("ap_debug", ap->proc); - } -#endif /* PRISM2_NO_PROCFS_DEBUG */ - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (ap->proc != NULL) { - remove_proc_entry("ap", ap->proc); - remove_proc_entry("ap_control", ap->proc); - } - ap_control_flush_macs(&ap->mac_restrictions); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - ap->initialized = 0; -} - - -/* caller should have mutex for AP STA list handling */ -static struct sta_info* ap_get_sta(struct ap_data *ap, u8 *sta) -{ - struct sta_info *s; - - s = ap->sta_hash[STA_HASH(sta)]; - while (s != NULL && memcmp(s->addr, sta, ETH_ALEN) != 0) - s = s->hnext; - return s; -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - -/* Called from timer handler and from scheduled AP queue handlers */ -static void prism2_send_mgmt(struct net_device *dev, - u16 type_subtype, char *body, - int body_len, u8 *addr, u16 tx_cb_idx) -{ - struct hostap_interface *iface; - local_info_t *local; - struct ieee80211_hdr *hdr; - u16 fc; - struct sk_buff *skb; - struct hostap_skb_tx_data *meta; - int hdrlen; - - iface = netdev_priv(dev); - local = iface->local; - dev = local->dev; /* always use master radio device */ - iface = netdev_priv(dev); - - if (!(dev->flags & IFF_UP)) { - PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt - device is not UP - " - "cannot send frame\n", dev->name); - return; - } - - skb = dev_alloc_skb(sizeof(*hdr) + body_len); - if (skb == NULL) { - PDEBUG(DEBUG_AP, "%s: prism2_send_mgmt failed to allocate " - "skb\n", dev->name); - return; - } - - fc = type_subtype; - hdrlen = hostap_80211_get_hdrlen(cpu_to_le16(type_subtype)); - hdr = (struct ieee80211_hdr *) skb_put(skb, hdrlen); - if (body) - memcpy(skb_put(skb, body_len), body, body_len); - - memset(hdr, 0, hdrlen); - - /* FIX: ctrl::ack sending used special HFA384X_TX_CTRL_802_11 - * tx_control instead of using local->tx_control */ - - - memcpy(hdr->addr1, addr, ETH_ALEN); /* DA / RA */ - if (ieee80211_is_data(hdr->frame_control)) { - fc |= IEEE80211_FCTL_FROMDS; - memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* BSSID */ - memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* SA */ - } else if (ieee80211_is_ctl(hdr->frame_control)) { - /* control:ACK does not have addr2 or addr3 */ - memset(hdr->addr2, 0, ETH_ALEN); - memset(hdr->addr3, 0, ETH_ALEN); - } else { - memcpy(hdr->addr2, dev->dev_addr, ETH_ALEN); /* SA */ - memcpy(hdr->addr3, dev->dev_addr, ETH_ALEN); /* BSSID */ - } - - hdr->frame_control = cpu_to_le16(fc); - - meta = (struct hostap_skb_tx_data *) skb->cb; - memset(meta, 0, sizeof(*meta)); - meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; - meta->iface = iface; - meta->tx_cb_idx = tx_cb_idx; - - skb->dev = dev; - skb_reset_mac_header(skb); - skb_reset_network_header(skb); - dev_queue_xmit(skb); -} -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -static int prism2_sta_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - struct sta_info *sta = (struct sta_info *) data; - int i; - - /* FIX: possible race condition.. the STA data could have just expired, - * but proc entry was still here so that the read could have started; - * some locking should be done here.. */ - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "%s=%pM\nusers=%d\naid=%d\n" - "flags=0x%04x%s%s%s%s%s%s%s\n" - "capability=0x%02x\nlisten_interval=%d\nsupported_rates=", - sta->ap ? "AP" : "STA", - sta->addr, atomic_read(&sta->users), sta->aid, - sta->flags, - sta->flags & WLAN_STA_AUTH ? " AUTH" : "", - sta->flags & WLAN_STA_ASSOC ? " ASSOC" : "", - sta->flags & WLAN_STA_PS ? " PS" : "", - sta->flags & WLAN_STA_TIM ? " TIM" : "", - sta->flags & WLAN_STA_PERM ? " PERM" : "", - sta->flags & WLAN_STA_AUTHORIZED ? " AUTHORIZED" : "", - sta->flags & WLAN_STA_PENDING_POLL ? " POLL" : "", - sta->capability, sta->listen_interval); - /* supported_rates: 500 kbit/s units with msb ignored */ - for (i = 0; i < sizeof(sta->supported_rates); i++) - if (sta->supported_rates[i] != 0) - p += sprintf(p, "%d%sMbps ", - (sta->supported_rates[i] & 0x7f) / 2, - sta->supported_rates[i] & 1 ? ".5" : ""); - p += sprintf(p, "\njiffies=%lu\nlast_auth=%lu\nlast_assoc=%lu\n" - "last_rx=%lu\nlast_tx=%lu\nrx_packets=%lu\n" - "tx_packets=%lu\n" - "rx_bytes=%lu\ntx_bytes=%lu\nbuffer_count=%d\n" - "last_rx: silence=%d dBm signal=%d dBm rate=%d%s Mbps\n" - "tx_rate=%d\ntx[1M]=%d\ntx[2M]=%d\ntx[5.5M]=%d\n" - "tx[11M]=%d\n" - "rx[1M]=%d\nrx[2M]=%d\nrx[5.5M]=%d\nrx[11M]=%d\n", - jiffies, sta->last_auth, sta->last_assoc, sta->last_rx, - sta->last_tx, - sta->rx_packets, sta->tx_packets, sta->rx_bytes, - sta->tx_bytes, skb_queue_len(&sta->tx_buf), - sta->last_rx_silence, - sta->last_rx_signal, sta->last_rx_rate / 10, - sta->last_rx_rate % 10 ? ".5" : "", - sta->tx_rate, sta->tx_count[0], sta->tx_count[1], - sta->tx_count[2], sta->tx_count[3], sta->rx_count[0], - sta->rx_count[1], sta->rx_count[2], sta->rx_count[3]); - if (sta->crypt && sta->crypt->ops && sta->crypt->ops->print_stats) - p = sta->crypt->ops->print_stats(p, sta->crypt->priv); -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (sta->ap) { - if (sta->u.ap.channel >= 0) - p += sprintf(p, "channel=%d\n", sta->u.ap.channel); - p += sprintf(p, "ssid="); - for (i = 0; i < sta->u.ap.ssid_len; i++) - p += sprintf(p, ((sta->u.ap.ssid[i] >= 32 && - sta->u.ap.ssid[i] < 127) ? - "%c" : "<%02x>"), - sta->u.ap.ssid[i]); - p += sprintf(p, "\n"); - } -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - return (p - page); -} - - -static void handle_add_proc_queue(struct work_struct *work) -{ - struct ap_data *ap = container_of(work, struct ap_data, - add_sta_proc_queue); - struct sta_info *sta; - char name[20]; - struct add_sta_proc_data *entry, *prev; - - entry = ap->add_sta_proc_entries; - ap->add_sta_proc_entries = NULL; - - while (entry) { - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, entry->addr); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&ap->sta_table_lock); - - if (sta) { - sprintf(name, "%pM", sta->addr); - sta->proc = create_proc_read_entry( - name, 0, ap->proc, - prism2_sta_proc_read, sta); - - atomic_dec(&sta->users); - } - - prev = entry; - entry = entry->next; - kfree(prev); - } -} - - -static struct sta_info * ap_add_sta(struct ap_data *ap, u8 *addr) -{ - struct sta_info *sta; - - sta = kzalloc(sizeof(struct sta_info), GFP_ATOMIC); - if (sta == NULL) { - PDEBUG(DEBUG_AP, "AP: kmalloc failed\n"); - return NULL; - } - - /* initialize STA info data */ - sta->local = ap->local; - skb_queue_head_init(&sta->tx_buf); - memcpy(sta->addr, addr, ETH_ALEN); - - atomic_inc(&sta->users); - spin_lock_bh(&ap->sta_table_lock); - list_add(&sta->list, &ap->sta_list); - ap->num_sta++; - ap_sta_hash_add(ap, sta); - spin_unlock_bh(&ap->sta_table_lock); - - if (ap->proc) { - struct add_sta_proc_data *entry; - /* schedule a non-interrupt context process to add a procfs - * entry for the STA since procfs code use GFP_KERNEL */ - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (entry) { - memcpy(entry->addr, sta->addr, ETH_ALEN); - entry->next = ap->add_sta_proc_entries; - ap->add_sta_proc_entries = entry; - schedule_work(&ap->add_sta_proc_queue); - } else - printk(KERN_DEBUG "Failed to add STA proc data\n"); - } - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - init_timer(&sta->timer); - sta->timer.expires = jiffies + ap->max_inactivity; - sta->timer.data = (unsigned long) sta; - sta->timer.function = ap_handle_timer; - if (!ap->local->hostapd) - add_timer(&sta->timer); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - return sta; -} - - -static int ap_tx_rate_ok(int rateidx, struct sta_info *sta, - local_info_t *local) -{ - if (rateidx > sta->tx_max_rate || - !(sta->tx_supp_rates & (1 << rateidx))) - return 0; - - if (local->tx_rate_control != 0 && - !(local->tx_rate_control & (1 << rateidx))) - return 0; - - return 1; -} - - -static void prism2_check_tx_rates(struct sta_info *sta) -{ - int i; - - sta->tx_supp_rates = 0; - for (i = 0; i < sizeof(sta->supported_rates); i++) { - if ((sta->supported_rates[i] & 0x7f) == 2) - sta->tx_supp_rates |= WLAN_RATE_1M; - if ((sta->supported_rates[i] & 0x7f) == 4) - sta->tx_supp_rates |= WLAN_RATE_2M; - if ((sta->supported_rates[i] & 0x7f) == 11) - sta->tx_supp_rates |= WLAN_RATE_5M5; - if ((sta->supported_rates[i] & 0x7f) == 22) - sta->tx_supp_rates |= WLAN_RATE_11M; - } - sta->tx_max_rate = sta->tx_rate = sta->tx_rate_idx = 0; - if (sta->tx_supp_rates & WLAN_RATE_1M) { - sta->tx_max_rate = 0; - if (ap_tx_rate_ok(0, sta, sta->local)) { - sta->tx_rate = 10; - sta->tx_rate_idx = 0; - } - } - if (sta->tx_supp_rates & WLAN_RATE_2M) { - sta->tx_max_rate = 1; - if (ap_tx_rate_ok(1, sta, sta->local)) { - sta->tx_rate = 20; - sta->tx_rate_idx = 1; - } - } - if (sta->tx_supp_rates & WLAN_RATE_5M5) { - sta->tx_max_rate = 2; - if (ap_tx_rate_ok(2, sta, sta->local)) { - sta->tx_rate = 55; - sta->tx_rate_idx = 2; - } - } - if (sta->tx_supp_rates & WLAN_RATE_11M) { - sta->tx_max_rate = 3; - if (ap_tx_rate_ok(3, sta, sta->local)) { - sta->tx_rate = 110; - sta->tx_rate_idx = 3; - } - } -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - -static void ap_crypt_init(struct ap_data *ap) -{ - ap->crypt = lib80211_get_crypto_ops("WEP"); - - if (ap->crypt) { - if (ap->crypt->init) { - ap->crypt_priv = ap->crypt->init(0); - if (ap->crypt_priv == NULL) - ap->crypt = NULL; - else { - u8 key[WEP_KEY_LEN]; - get_random_bytes(key, WEP_KEY_LEN); - ap->crypt->set_key(key, WEP_KEY_LEN, NULL, - ap->crypt_priv); - } - } - } - - if (ap->crypt == NULL) { - printk(KERN_WARNING "AP could not initialize WEP: load module " - "lib80211_crypt_wep.ko\n"); - } -} - - -/* Generate challenge data for shared key authentication. IEEE 802.11 specifies - * that WEP algorithm is used for generating challange. This should be unique, - * but otherwise there is not really need for randomness etc. Initialize WEP - * with pseudo random key and then use increasing IV to get unique challenge - * streams. - * - * Called only as a scheduled task for pending AP frames. - */ -static char * ap_auth_make_challenge(struct ap_data *ap) -{ - char *tmpbuf; - struct sk_buff *skb; - - if (ap->crypt == NULL) { - ap_crypt_init(ap); - if (ap->crypt == NULL) - return NULL; - } - - tmpbuf = kmalloc(WLAN_AUTH_CHALLENGE_LEN, GFP_ATOMIC); - if (tmpbuf == NULL) { - PDEBUG(DEBUG_AP, "AP: kmalloc failed for challenge\n"); - return NULL; - } - - skb = dev_alloc_skb(WLAN_AUTH_CHALLENGE_LEN + - ap->crypt->extra_mpdu_prefix_len + - ap->crypt->extra_mpdu_postfix_len); - if (skb == NULL) { - kfree(tmpbuf); - return NULL; - } - - skb_reserve(skb, ap->crypt->extra_mpdu_prefix_len); - memset(skb_put(skb, WLAN_AUTH_CHALLENGE_LEN), 0, - WLAN_AUTH_CHALLENGE_LEN); - if (ap->crypt->encrypt_mpdu(skb, 0, ap->crypt_priv)) { - dev_kfree_skb(skb); - kfree(tmpbuf); - return NULL; - } - - skb_copy_from_linear_data_offset(skb, ap->crypt->extra_mpdu_prefix_len, - tmpbuf, WLAN_AUTH_CHALLENGE_LEN); - dev_kfree_skb(skb); - - return tmpbuf; -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void handle_authen(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct net_device *dev = local->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - size_t hdrlen; - struct ap_data *ap = local->ap; - char body[8 + WLAN_AUTH_CHALLENGE_LEN], *challenge = NULL; - int len, olen; - u16 auth_alg, auth_transaction, status_code; - __le16 *pos; - u16 resp = WLAN_STATUS_SUCCESS; - struct sta_info *sta = NULL; - struct lib80211_crypt_data *crypt; - char *txt = ""; - - len = skb->len - IEEE80211_MGMT_HDR_LEN; - - hdrlen = hostap_80211_get_hdrlen(hdr->frame_control); - - if (len < 6) { - PDEBUG(DEBUG_AP, "%s: handle_authen - too short payload " - "(len=%d) from %pM\n", dev->name, len, hdr->addr2); - return; - } - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&local->ap->sta_table_lock); - - if (sta && sta->crypt) - crypt = sta->crypt; - else { - int idx = 0; - if (skb->len >= hdrlen + 3) - idx = skb->data[hdrlen + 3] >> 6; - crypt = local->crypt_info.crypt[idx]; - } - - pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN); - auth_alg = __le16_to_cpu(*pos); - pos++; - auth_transaction = __le16_to_cpu(*pos); - pos++; - status_code = __le16_to_cpu(*pos); - pos++; - - if (memcmp(dev->dev_addr, hdr->addr2, ETH_ALEN) == 0 || - ap_control_mac_deny(&ap->mac_restrictions, hdr->addr2)) { - txt = "authentication denied"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (((local->auth_algs & PRISM2_AUTH_OPEN) && - auth_alg == WLAN_AUTH_OPEN) || - ((local->auth_algs & PRISM2_AUTH_SHARED_KEY) && - crypt && auth_alg == WLAN_AUTH_SHARED_KEY)) { - } else { - txt = "unsupported algorithm"; - resp = WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG; - goto fail; - } - - if (len >= 8) { - u8 *u = (u8 *) pos; - if (*u == WLAN_EID_CHALLENGE) { - if (*(u + 1) != WLAN_AUTH_CHALLENGE_LEN) { - txt = "invalid challenge len"; - resp = WLAN_STATUS_CHALLENGE_FAIL; - goto fail; - } - if (len - 8 < WLAN_AUTH_CHALLENGE_LEN) { - txt = "challenge underflow"; - resp = WLAN_STATUS_CHALLENGE_FAIL; - goto fail; - } - challenge = (char *) (u + 2); - } - } - - if (sta && sta->ap) { - if (time_after(jiffies, sta->u.ap.last_beacon + - (10 * sta->listen_interval * HZ) / 1024)) { - PDEBUG(DEBUG_AP, "%s: no beacons received for a while," - " assuming AP %pM is now STA\n", - dev->name, sta->addr); - sta->ap = 0; - sta->flags = 0; - sta->u.sta.challenge = NULL; - } else { - txt = "AP trying to authenticate?"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - } - - if ((auth_alg == WLAN_AUTH_OPEN && auth_transaction == 1) || - (auth_alg == WLAN_AUTH_SHARED_KEY && - (auth_transaction == 1 || - (auth_transaction == 3 && sta != NULL && - sta->u.sta.challenge != NULL)))) { - } else { - txt = "unknown authentication transaction number"; - resp = WLAN_STATUS_UNKNOWN_AUTH_TRANSACTION; - goto fail; - } - - if (sta == NULL) { - txt = "new STA"; - - if (local->ap->num_sta >= MAX_STA_COUNT) { - /* FIX: might try to remove some old STAs first? */ - txt = "no more room for new STAs"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - sta = ap_add_sta(local->ap, hdr->addr2); - if (sta == NULL) { - txt = "ap_add_sta failed"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - } - - switch (auth_alg) { - case WLAN_AUTH_OPEN: - txt = "authOK"; - /* IEEE 802.11 standard is not completely clear about - * whether STA is considered authenticated after - * authentication OK frame has been send or after it - * has been ACKed. In order to reduce interoperability - * issues, mark the STA authenticated before ACK. */ - sta->flags |= WLAN_STA_AUTH; - break; - - case WLAN_AUTH_SHARED_KEY: - if (auth_transaction == 1) { - if (sta->u.sta.challenge == NULL) { - sta->u.sta.challenge = - ap_auth_make_challenge(local->ap); - if (sta->u.sta.challenge == NULL) { - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - } - } else { - if (sta->u.sta.challenge == NULL || - challenge == NULL || - memcmp(sta->u.sta.challenge, challenge, - WLAN_AUTH_CHALLENGE_LEN) != 0 || - !ieee80211_has_protected(hdr->frame_control)) { - txt = "challenge response incorrect"; - resp = WLAN_STATUS_CHALLENGE_FAIL; - goto fail; - } - - txt = "challenge OK - authOK"; - /* IEEE 802.11 standard is not completely clear about - * whether STA is considered authenticated after - * authentication OK frame has been send or after it - * has been ACKed. In order to reduce interoperability - * issues, mark the STA authenticated before ACK. */ - sta->flags |= WLAN_STA_AUTH; - kfree(sta->u.sta.challenge); - sta->u.sta.challenge = NULL; - } - break; - } - - fail: - pos = (__le16 *) body; - *pos = cpu_to_le16(auth_alg); - pos++; - *pos = cpu_to_le16(auth_transaction + 1); - pos++; - *pos = cpu_to_le16(resp); /* status_code */ - pos++; - olen = 6; - - if (resp == WLAN_STATUS_SUCCESS && sta != NULL && - sta->u.sta.challenge != NULL && - auth_alg == WLAN_AUTH_SHARED_KEY && auth_transaction == 1) { - u8 *tmp = (u8 *) pos; - *tmp++ = WLAN_EID_CHALLENGE; - *tmp++ = WLAN_AUTH_CHALLENGE_LEN; - pos++; - memcpy(pos, sta->u.sta.challenge, WLAN_AUTH_CHALLENGE_LEN); - olen += 2 + WLAN_AUTH_CHALLENGE_LEN; - } - - prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_AUTH, - body, olen, hdr->addr2, ap->tx_callback_auth); - - if (sta) { - sta->last_rx = jiffies; - atomic_dec(&sta->users); - } - - if (resp) { - PDEBUG(DEBUG_AP, "%s: %pM auth (alg=%d " - "trans#=%d stat=%d len=%d fc=%04x) ==> %d (%s)\n", - dev->name, hdr->addr2, - auth_alg, auth_transaction, status_code, len, - le16_to_cpu(hdr->frame_control), resp, txt); - } -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void handle_assoc(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats, int reassoc) -{ - struct net_device *dev = local->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - char body[12], *p, *lpos; - int len, left; - __le16 *pos; - u16 resp = WLAN_STATUS_SUCCESS; - struct sta_info *sta = NULL; - int send_deauth = 0; - char *txt = ""; - u8 prev_ap[ETH_ALEN]; - - left = len = skb->len - IEEE80211_MGMT_HDR_LEN; - - if (len < (reassoc ? 10 : 4)) { - PDEBUG(DEBUG_AP, "%s: handle_assoc - too short payload " - "(len=%d, reassoc=%d) from %pM\n", - dev->name, len, reassoc, hdr->addr2); - return; - } - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta == NULL || (sta->flags & WLAN_STA_AUTH) == 0) { - spin_unlock_bh(&local->ap->sta_table_lock); - txt = "trying to associate before authentication"; - send_deauth = 1; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - sta = NULL; /* do not decrement sta->users */ - goto fail; - } - atomic_inc(&sta->users); - spin_unlock_bh(&local->ap->sta_table_lock); - - pos = (__le16 *) (skb->data + IEEE80211_MGMT_HDR_LEN); - sta->capability = __le16_to_cpu(*pos); - pos++; left -= 2; - sta->listen_interval = __le16_to_cpu(*pos); - pos++; left -= 2; - - if (reassoc) { - memcpy(prev_ap, pos, ETH_ALEN); - pos++; pos++; pos++; left -= 6; - } else - memset(prev_ap, 0, ETH_ALEN); - - if (left >= 2) { - unsigned int ileft; - unsigned char *u = (unsigned char *) pos; - - if (*u == WLAN_EID_SSID) { - u++; left--; - ileft = *u; - u++; left--; - - if (ileft > left || ileft > MAX_SSID_LEN) { - txt = "SSID overflow"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - if (ileft != strlen(local->essid) || - memcmp(local->essid, u, ileft) != 0) { - txt = "not our SSID"; - resp = WLAN_STATUS_ASSOC_DENIED_UNSPEC; - goto fail; - } - - u += ileft; - left -= ileft; - } - - if (left >= 2 && *u == WLAN_EID_SUPP_RATES) { - u++; left--; - ileft = *u; - u++; left--; - - if (ileft > left || ileft == 0 || - ileft > WLAN_SUPP_RATES_MAX) { - txt = "SUPP_RATES len error"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - memset(sta->supported_rates, 0, - sizeof(sta->supported_rates)); - memcpy(sta->supported_rates, u, ileft); - prism2_check_tx_rates(sta); - - u += ileft; - left -= ileft; - } - - if (left > 0) { - PDEBUG(DEBUG_AP, "%s: assoc from %pM" - " with extra data (%d bytes) [", - dev->name, hdr->addr2, left); - while (left > 0) { - PDEBUG2(DEBUG_AP, "<%02x>", *u); - u++; left--; - } - PDEBUG2(DEBUG_AP, "]\n"); - } - } else { - txt = "frame underflow"; - resp = WLAN_STATUS_UNSPECIFIED_FAILURE; - goto fail; - } - - /* get a unique AID */ - if (sta->aid > 0) - txt = "OK, old AID"; - else { - spin_lock_bh(&local->ap->sta_table_lock); - for (sta->aid = 1; sta->aid <= MAX_AID_TABLE_SIZE; sta->aid++) - if (local->ap->sta_aid[sta->aid - 1] == NULL) - break; - if (sta->aid > MAX_AID_TABLE_SIZE) { - sta->aid = 0; - spin_unlock_bh(&local->ap->sta_table_lock); - resp = WLAN_STATUS_AP_UNABLE_TO_HANDLE_NEW_STA; - txt = "no room for more AIDs"; - } else { - local->ap->sta_aid[sta->aid - 1] = sta; - spin_unlock_bh(&local->ap->sta_table_lock); - txt = "OK, new AID"; - } - } - - fail: - pos = (__le16 *) body; - - if (send_deauth) { - *pos = cpu_to_le16(WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH); - pos++; - } else { - /* FIX: CF-Pollable and CF-PollReq should be set to match the - * values in beacons/probe responses */ - /* FIX: how about privacy and WEP? */ - /* capability */ - *pos = cpu_to_le16(WLAN_CAPABILITY_ESS); - pos++; - - /* status_code */ - *pos = cpu_to_le16(resp); - pos++; - - *pos = cpu_to_le16((sta && sta->aid > 0 ? sta->aid : 0) | - BIT(14) | BIT(15)); /* AID */ - pos++; - - /* Supported rates (Information element) */ - p = (char *) pos; - *p++ = WLAN_EID_SUPP_RATES; - lpos = p; - *p++ = 0; /* len */ - if (local->tx_rate_control & WLAN_RATE_1M) { - *p++ = local->basic_rates & WLAN_RATE_1M ? 0x82 : 0x02; - (*lpos)++; - } - if (local->tx_rate_control & WLAN_RATE_2M) { - *p++ = local->basic_rates & WLAN_RATE_2M ? 0x84 : 0x04; - (*lpos)++; - } - if (local->tx_rate_control & WLAN_RATE_5M5) { - *p++ = local->basic_rates & WLAN_RATE_5M5 ? - 0x8b : 0x0b; - (*lpos)++; - } - if (local->tx_rate_control & WLAN_RATE_11M) { - *p++ = local->basic_rates & WLAN_RATE_11M ? - 0x96 : 0x16; - (*lpos)++; - } - pos = (__le16 *) p; - } - - prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | - (send_deauth ? IEEE80211_STYPE_DEAUTH : - (reassoc ? IEEE80211_STYPE_REASSOC_RESP : - IEEE80211_STYPE_ASSOC_RESP)), - body, (u8 *) pos - (u8 *) body, - hdr->addr2, - send_deauth ? 0 : local->ap->tx_callback_assoc); - - if (sta) { - if (resp == WLAN_STATUS_SUCCESS) { - sta->last_rx = jiffies; - /* STA will be marked associated from TX callback, if - * AssocResp is ACKed */ - } - atomic_dec(&sta->users); - } - -#if 0 - PDEBUG(DEBUG_AP, "%s: %pM %sassoc (len=%d " - "prev_ap=%pM) => %d(%d) (%s)\n", - dev->name, - hdr->addr2, - reassoc ? "re" : "", len, - prev_ap, - resp, send_deauth, txt); -#endif -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void handle_deauth(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct net_device *dev = local->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - char *body = (char *) (skb->data + IEEE80211_MGMT_HDR_LEN); - int len; - u16 reason_code; - __le16 *pos; - struct sta_info *sta = NULL; - - len = skb->len - IEEE80211_MGMT_HDR_LEN; - - if (len < 2) { - printk("handle_deauth - too short payload (len=%d)\n", len); - return; - } - - pos = (__le16 *) body; - reason_code = le16_to_cpu(*pos); - - PDEBUG(DEBUG_AP, "%s: deauthentication: %pM len=%d, " - "reason_code=%d\n", dev->name, hdr->addr2, - len, reason_code); - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta != NULL) { - if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap) - hostap_event_expired_sta(local->dev, sta); - sta->flags &= ~(WLAN_STA_AUTH | WLAN_STA_ASSOC); - } - spin_unlock_bh(&local->ap->sta_table_lock); - if (sta == NULL) { - printk("%s: deauthentication from %pM, " - "reason_code=%d, but STA not authenticated\n", dev->name, - hdr->addr2, reason_code); - } -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void handle_disassoc(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct net_device *dev = local->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - char *body = skb->data + IEEE80211_MGMT_HDR_LEN; - int len; - u16 reason_code; - __le16 *pos; - struct sta_info *sta = NULL; - - len = skb->len - IEEE80211_MGMT_HDR_LEN; - - if (len < 2) { - printk("handle_disassoc - too short payload (len=%d)\n", len); - return; - } - - pos = (__le16 *) body; - reason_code = le16_to_cpu(*pos); - - PDEBUG(DEBUG_AP, "%s: disassociation: %pM len=%d, " - "reason_code=%d\n", dev->name, hdr->addr2, - len, reason_code); - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta != NULL) { - if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap) - hostap_event_expired_sta(local->dev, sta); - sta->flags &= ~WLAN_STA_ASSOC; - } - spin_unlock_bh(&local->ap->sta_table_lock); - if (sta == NULL) { - printk("%s: disassociation from %pM, " - "reason_code=%d, but STA not authenticated\n", - dev->name, hdr->addr2, reason_code); - } -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void ap_handle_data_nullfunc(local_info_t *local, - struct ieee80211_hdr *hdr) -{ - struct net_device *dev = local->dev; - - /* some STA f/w's seem to require control::ACK frame for - * data::nullfunc, but at least Prism2 station f/w version 0.8.0 does - * not send this.. - * send control::ACK for the data::nullfunc */ - - printk(KERN_DEBUG "Sending control::ACK for data::nullfunc\n"); - prism2_send_mgmt(dev, IEEE80211_FTYPE_CTL | IEEE80211_STYPE_ACK, - NULL, 0, hdr->addr2, 0); -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void ap_handle_dropped_data(local_info_t *local, - struct ieee80211_hdr *hdr) -{ - struct net_device *dev = local->dev; - struct sta_info *sta; - __le16 reason; - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&local->ap->sta_table_lock); - - if (sta != NULL && (sta->flags & WLAN_STA_ASSOC)) { - PDEBUG(DEBUG_AP, "ap_handle_dropped_data: STA is now okay?\n"); - atomic_dec(&sta->users); - return; - } - - reason = cpu_to_le16(WLAN_REASON_CLASS3_FRAME_FROM_NONASSOC_STA); - prism2_send_mgmt(dev, IEEE80211_FTYPE_MGMT | - ((sta == NULL || !(sta->flags & WLAN_STA_ASSOC)) ? - IEEE80211_STYPE_DEAUTH : IEEE80211_STYPE_DISASSOC), - (char *) &reason, sizeof(reason), hdr->addr2, 0); - - if (sta) - atomic_dec(&sta->users); -} - -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -/* Called only as a scheduled task for pending AP frames. */ -static void pspoll_send_buffered(local_info_t *local, struct sta_info *sta, - struct sk_buff *skb) -{ - struct hostap_skb_tx_data *meta; - - if (!(sta->flags & WLAN_STA_PS)) { - /* Station has moved to non-PS mode, so send all buffered - * frames using normal device queue. */ - dev_queue_xmit(skb); - return; - } - - /* add a flag for hostap_handle_sta_tx() to know that this skb should - * be passed through even though STA is using PS */ - meta = (struct hostap_skb_tx_data *) skb->cb; - meta->flags |= HOSTAP_TX_FLAGS_BUFFERED_FRAME; - if (!skb_queue_empty(&sta->tx_buf)) { - /* indicate to STA that more frames follow */ - meta->flags |= HOSTAP_TX_FLAGS_ADD_MOREDATA; - } - dev_queue_xmit(skb); -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void handle_pspoll(local_info_t *local, - struct ieee80211_hdr *hdr, - struct hostap_80211_rx_status *rx_stats) -{ - struct net_device *dev = local->dev; - struct sta_info *sta; - u16 aid; - struct sk_buff *skb; - - PDEBUG(DEBUG_PS2, "handle_pspoll: BSSID=%pM, TA=%pM PWRMGT=%d\n", - hdr->addr1, hdr->addr2, !!ieee80211_has_pm(hdr->frame_control)); - - if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, - "handle_pspoll - addr1(BSSID)=%pM not own MAC\n", - hdr->addr1); - return; - } - - aid = le16_to_cpu(hdr->duration_id); - if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) { - PDEBUG(DEBUG_PS, " PSPOLL and AID[15:14] not set\n"); - return; - } - aid &= ~(BIT(15) | BIT(14)); - if (aid == 0 || aid > MAX_AID_TABLE_SIZE) { - PDEBUG(DEBUG_PS, " invalid aid=%d\n", aid); - return; - } - PDEBUG(DEBUG_PS2, " aid=%d\n", aid); - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&local->ap->sta_table_lock); - - if (sta == NULL) { - PDEBUG(DEBUG_PS, " STA not found\n"); - return; - } - if (sta->aid != aid) { - PDEBUG(DEBUG_PS, " received aid=%i does not match with " - "assoc.aid=%d\n", aid, sta->aid); - return; - } - - /* FIX: todo: - * - add timeout for buffering (clear aid in TIM vector if buffer timed - * out (expiry time must be longer than ListenInterval for - * the corresponding STA; "8802-11: 11.2.1.9 AP aging function" - * - what to do, if buffered, pspolled, and sent frame is not ACKed by - * sta; store buffer for later use and leave TIM aid bit set? use - * TX event to check whether frame was ACKed? - */ - - while ((skb = skb_dequeue(&sta->tx_buf)) != NULL) { - /* send buffered frame .. */ - PDEBUG(DEBUG_PS2, "Sending buffered frame to STA after PS POLL" - " (buffer_count=%d)\n", skb_queue_len(&sta->tx_buf)); - - pspoll_send_buffered(local, sta, skb); - - if (sta->flags & WLAN_STA_PS) { - /* send only one buffered packet per PS Poll */ - /* FIX: should ignore further PS Polls until the - * buffered packet that was just sent is acknowledged - * (Tx or TxExc event) */ - break; - } - } - - if (skb_queue_empty(&sta->tx_buf)) { - /* try to clear aid from TIM */ - if (!(sta->flags & WLAN_STA_TIM)) - PDEBUG(DEBUG_PS2, "Re-unsetting TIM for aid %d\n", - aid); - hostap_set_tim(local, aid, 0); - sta->flags &= ~WLAN_STA_TIM; - } - - atomic_dec(&sta->users); -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - -static void handle_wds_oper_queue(struct work_struct *work) -{ - struct ap_data *ap = container_of(work, struct ap_data, - wds_oper_queue); - local_info_t *local = ap->local; - struct wds_oper_data *entry, *prev; - - spin_lock_bh(&local->lock); - entry = local->ap->wds_oper_entries; - local->ap->wds_oper_entries = NULL; - spin_unlock_bh(&local->lock); - - while (entry) { - PDEBUG(DEBUG_AP, "%s: %s automatic WDS connection " - "to AP %pM\n", - local->dev->name, - entry->type == WDS_ADD ? "adding" : "removing", - entry->addr); - if (entry->type == WDS_ADD) - prism2_wds_add(local, entry->addr, 0); - else if (entry->type == WDS_DEL) - prism2_wds_del(local, entry->addr, 0, 1); - - prev = entry; - entry = entry->next; - kfree(prev); - } -} - - -/* Called only as a scheduled task for pending AP frames. */ -static void handle_beacon(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - char *body = skb->data + IEEE80211_MGMT_HDR_LEN; - int len, left; - u16 beacon_int, capability; - __le16 *pos; - char *ssid = NULL; - unsigned char *supp_rates = NULL; - int ssid_len = 0, supp_rates_len = 0; - struct sta_info *sta = NULL; - int new_sta = 0, channel = -1; - - len = skb->len - IEEE80211_MGMT_HDR_LEN; - - if (len < 8 + 2 + 2) { - printk(KERN_DEBUG "handle_beacon - too short payload " - "(len=%d)\n", len); - return; - } - - pos = (__le16 *) body; - left = len; - - /* Timestamp (8 octets) */ - pos += 4; left -= 8; - /* Beacon interval (2 octets) */ - beacon_int = le16_to_cpu(*pos); - pos++; left -= 2; - /* Capability information (2 octets) */ - capability = le16_to_cpu(*pos); - pos++; left -= 2; - - if (local->ap->ap_policy != AP_OTHER_AP_EVEN_IBSS && - capability & WLAN_CAPABILITY_IBSS) - return; - - if (left >= 2) { - unsigned int ileft; - unsigned char *u = (unsigned char *) pos; - - if (*u == WLAN_EID_SSID) { - u++; left--; - ileft = *u; - u++; left--; - - if (ileft > left || ileft > MAX_SSID_LEN) { - PDEBUG(DEBUG_AP, "SSID: overflow\n"); - return; - } - - if (local->ap->ap_policy == AP_OTHER_AP_SAME_SSID && - (ileft != strlen(local->essid) || - memcmp(local->essid, u, ileft) != 0)) { - /* not our SSID */ - return; - } - - ssid = u; - ssid_len = ileft; - - u += ileft; - left -= ileft; - } - - if (*u == WLAN_EID_SUPP_RATES) { - u++; left--; - ileft = *u; - u++; left--; - - if (ileft > left || ileft == 0 || ileft > 8) { - PDEBUG(DEBUG_AP, " - SUPP_RATES len error\n"); - return; - } - - supp_rates = u; - supp_rates_len = ileft; - - u += ileft; - left -= ileft; - } - - if (*u == WLAN_EID_DS_PARAMS) { - u++; left--; - ileft = *u; - u++; left--; - - if (ileft > left || ileft != 1) { - PDEBUG(DEBUG_AP, " - DS_PARAMS len error\n"); - return; - } - - channel = *u; - - u += ileft; - left -= ileft; - } - } - - spin_lock_bh(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta != NULL) - atomic_inc(&sta->users); - spin_unlock_bh(&local->ap->sta_table_lock); - - if (sta == NULL) { - /* add new AP */ - new_sta = 1; - sta = ap_add_sta(local->ap, hdr->addr2); - if (sta == NULL) { - printk(KERN_INFO "prism2: kmalloc failed for AP " - "data structure\n"); - return; - } - hostap_event_new_sta(local->dev, sta); - - /* mark APs authentication and associated for pseudo ad-hoc - * style communication */ - sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; - - if (local->ap->autom_ap_wds) { - hostap_wds_link_oper(local, sta->addr, WDS_ADD); - } - } - - sta->ap = 1; - if (ssid) { - sta->u.ap.ssid_len = ssid_len; - memcpy(sta->u.ap.ssid, ssid, ssid_len); - sta->u.ap.ssid[ssid_len] = '\0'; - } else { - sta->u.ap.ssid_len = 0; - sta->u.ap.ssid[0] = '\0'; - } - sta->u.ap.channel = channel; - sta->rx_packets++; - sta->rx_bytes += len; - sta->u.ap.last_beacon = sta->last_rx = jiffies; - sta->capability = capability; - sta->listen_interval = beacon_int; - - atomic_dec(&sta->users); - - if (new_sta) { - memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); - memcpy(sta->supported_rates, supp_rates, supp_rates_len); - prism2_check_tx_rates(sta); - } -} - -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -/* Called only as a tasklet. */ -static void handle_ap_item(local_info_t *local, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - struct net_device *dev = local->dev; -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - u16 fc, type, stype; - struct ieee80211_hdr *hdr; - - /* FIX: should give skb->len to handler functions and check that the - * buffer is long enough */ - hdr = (struct ieee80211_hdr *) skb->data; - fc = le16_to_cpu(hdr->frame_control); - type = fc & IEEE80211_FCTL_FTYPE; - stype = fc & IEEE80211_FCTL_STYPE; - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (!local->hostapd && type == IEEE80211_FTYPE_DATA) { - PDEBUG(DEBUG_AP, "handle_ap_item - data frame\n"); - - if (!(fc & IEEE80211_FCTL_TODS) || - (fc & IEEE80211_FCTL_FROMDS)) { - if (stype == IEEE80211_STYPE_NULLFUNC) { - /* no ToDS nullfunc seems to be used to check - * AP association; so send reject message to - * speed up re-association */ - ap_handle_dropped_data(local, hdr); - goto done; - } - PDEBUG(DEBUG_AP, " not ToDS frame (fc=0x%04x)\n", - fc); - goto done; - } - - if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, "handle_ap_item - addr1(BSSID)=%pM" - " not own MAC\n", hdr->addr1); - goto done; - } - - if (local->ap->nullfunc_ack && - stype == IEEE80211_STYPE_NULLFUNC) - ap_handle_data_nullfunc(local, hdr); - else - ap_handle_dropped_data(local, hdr); - goto done; - } - - if (type == IEEE80211_FTYPE_MGMT && stype == IEEE80211_STYPE_BEACON) { - handle_beacon(local, skb, rx_stats); - goto done; - } -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - if (type == IEEE80211_FTYPE_CTL && stype == IEEE80211_STYPE_PSPOLL) { - handle_pspoll(local, hdr, rx_stats); - goto done; - } - - if (local->hostapd) { - PDEBUG(DEBUG_AP, "Unknown frame in AP queue: type=0x%02x " - "subtype=0x%02x\n", type, stype); - goto done; - } - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (type != IEEE80211_FTYPE_MGMT) { - PDEBUG(DEBUG_AP, "handle_ap_item - not a management frame?\n"); - goto done; - } - - if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, "handle_ap_item - addr1(DA)=%pM" - " not own MAC\n", hdr->addr1); - goto done; - } - - if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN)) { - PDEBUG(DEBUG_AP, "handle_ap_item - addr3(BSSID)=%pM" - " not own MAC\n", hdr->addr3); - goto done; - } - - switch (stype) { - case IEEE80211_STYPE_ASSOC_REQ: - handle_assoc(local, skb, rx_stats, 0); - break; - case IEEE80211_STYPE_ASSOC_RESP: - PDEBUG(DEBUG_AP, "==> ASSOC RESP (ignored)\n"); - break; - case IEEE80211_STYPE_REASSOC_REQ: - handle_assoc(local, skb, rx_stats, 1); - break; - case IEEE80211_STYPE_REASSOC_RESP: - PDEBUG(DEBUG_AP, "==> REASSOC RESP (ignored)\n"); - break; - case IEEE80211_STYPE_ATIM: - PDEBUG(DEBUG_AP, "==> ATIM (ignored)\n"); - break; - case IEEE80211_STYPE_DISASSOC: - handle_disassoc(local, skb, rx_stats); - break; - case IEEE80211_STYPE_AUTH: - handle_authen(local, skb, rx_stats); - break; - case IEEE80211_STYPE_DEAUTH: - handle_deauth(local, skb, rx_stats); - break; - default: - PDEBUG(DEBUG_AP, "Unknown mgmt frame subtype 0x%02x\n", - stype >> 4); - break; - } -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - done: - dev_kfree_skb(skb); -} - - -/* Called only as a tasklet (software IRQ) */ -void hostap_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats) -{ - struct hostap_interface *iface; - local_info_t *local; - struct ieee80211_hdr *hdr; - - iface = netdev_priv(dev); - local = iface->local; - - if (skb->len < 16) - goto drop; - - dev->stats.rx_packets++; - - hdr = (struct ieee80211_hdr *) skb->data; - - if (local->ap->ap_policy == AP_OTHER_AP_SKIP_ALL && - ieee80211_is_beacon(hdr->frame_control)) - goto drop; - - skb->protocol = cpu_to_be16(ETH_P_HOSTAP); - handle_ap_item(local, skb, rx_stats); - return; - - drop: - dev_kfree_skb(skb); -} - - -/* Called only as a tasklet (software IRQ) */ -static void schedule_packet_send(local_info_t *local, struct sta_info *sta) -{ - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - struct hostap_80211_rx_status rx_stats; - - if (skb_queue_empty(&sta->tx_buf)) - return; - - skb = dev_alloc_skb(16); - if (skb == NULL) { - printk(KERN_DEBUG "%s: schedule_packet_send: skb alloc " - "failed\n", local->dev->name); - return; - } - - hdr = (struct ieee80211_hdr *) skb_put(skb, 16); - - /* Generate a fake pspoll frame to start packet delivery */ - hdr->frame_control = cpu_to_le16( - IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); - memcpy(hdr->addr1, local->dev->dev_addr, ETH_ALEN); - memcpy(hdr->addr2, sta->addr, ETH_ALEN); - hdr->duration_id = cpu_to_le16(sta->aid | BIT(15) | BIT(14)); - - PDEBUG(DEBUG_PS2, - "%s: Scheduling buffered packet delivery for STA %pM\n", - local->dev->name, sta->addr); - - skb->dev = local->dev; - - memset(&rx_stats, 0, sizeof(rx_stats)); - hostap_rx(local->dev, skb, &rx_stats); -} - - -int prism2_ap_get_sta_qual(local_info_t *local, struct sockaddr addr[], - struct iw_quality qual[], int buf_size, - int aplist) -{ - struct ap_data *ap = local->ap; - struct list_head *ptr; - int count = 0; - - spin_lock_bh(&ap->sta_table_lock); - - for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list; - ptr = ptr->next) { - struct sta_info *sta = (struct sta_info *) ptr; - - if (aplist && !sta->ap) - continue; - addr[count].sa_family = ARPHRD_ETHER; - memcpy(addr[count].sa_data, sta->addr, ETH_ALEN); - if (sta->last_rx_silence == 0) - qual[count].qual = sta->last_rx_signal < 27 ? - 0 : (sta->last_rx_signal - 27) * 92 / 127; - else - qual[count].qual = sta->last_rx_signal - - sta->last_rx_silence - 35; - qual[count].level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); - qual[count].noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); - qual[count].updated = sta->last_rx_updated; - - sta->last_rx_updated = IW_QUAL_DBM; - - count++; - if (count >= buf_size) - break; - } - spin_unlock_bh(&ap->sta_table_lock); - - return count; -} - - -/* Translate our list of Access Points & Stations to a card independant - * format that the Wireless Tools will understand - Jean II */ -int prism2_ap_translate_scan(struct net_device *dev, - struct iw_request_info *info, char *buffer) -{ - struct hostap_interface *iface; - local_info_t *local; - struct ap_data *ap; - struct list_head *ptr; - struct iw_event iwe; - char *current_ev = buffer; - char *end_buf = buffer + IW_SCAN_MAX_DATA; -#if !defined(PRISM2_NO_KERNEL_IEEE80211_MGMT) - char buf[64]; -#endif - - iface = netdev_priv(dev); - local = iface->local; - ap = local->ap; - - spin_lock_bh(&ap->sta_table_lock); - - for (ptr = ap->sta_list.next; ptr != NULL && ptr != &ap->sta_list; - ptr = ptr->next) { - struct sta_info *sta = (struct sta_info *) ptr; - - /* First entry *MUST* be the AP MAC address */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, sta->addr, ETH_ALEN); - iwe.len = IW_EV_ADDR_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); - - /* Use the mode to indicate if it's a station or - * an Access Point */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - if (sta->ap) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_INFRA; - iwe.len = IW_EV_UINT_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); - - /* Some quality */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - if (sta->last_rx_silence == 0) - iwe.u.qual.qual = sta->last_rx_signal < 27 ? - 0 : (sta->last_rx_signal - 27) * 92 / 127; - else - iwe.u.qual.qual = sta->last_rx_signal - - sta->last_rx_silence - 35; - iwe.u.qual.level = HFA384X_LEVEL_TO_dBm(sta->last_rx_signal); - iwe.u.qual.noise = HFA384X_LEVEL_TO_dBm(sta->last_rx_silence); - iwe.u.qual.updated = sta->last_rx_updated; - iwe.len = IW_EV_QUAL_LEN; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (sta->ap) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = sta->u.ap.ssid_len; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, - sta->u.ap.ssid); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (sta->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = - IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, - sta->u.ap.ssid); - - if (sta->u.ap.channel > 0 && - sta->u.ap.channel <= FREQ_COUNT) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = freq_list[sta->u.ap.channel - 1] - * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event( - info, current_ev, end_buf, &iwe, - IW_EV_FREQ_LEN); - } - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "beacon_interval=%d", - sta->listen_interval); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, buf); - } -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - sta->last_rx_updated = IW_QUAL_DBM; - - /* To be continued, we should make good use of IWEVCUSTOM */ - } - - spin_unlock_bh(&ap->sta_table_lock); - - return current_ev - buffer; -} - - -static int prism2_hostapd_add_sta(struct ap_data *ap, - struct prism2_hostapd_param *param) -{ - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, param->sta_addr); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&ap->sta_table_lock); - - if (sta == NULL) { - sta = ap_add_sta(ap, param->sta_addr); - if (sta == NULL) - return -1; - } - - if (!(sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) - hostap_event_new_sta(sta->local->dev, sta); - - sta->flags |= WLAN_STA_AUTH | WLAN_STA_ASSOC; - sta->last_rx = jiffies; - sta->aid = param->u.add_sta.aid; - sta->capability = param->u.add_sta.capability; - sta->tx_supp_rates = param->u.add_sta.tx_supp_rates; - if (sta->tx_supp_rates & WLAN_RATE_1M) - sta->supported_rates[0] = 2; - if (sta->tx_supp_rates & WLAN_RATE_2M) - sta->supported_rates[1] = 4; - if (sta->tx_supp_rates & WLAN_RATE_5M5) - sta->supported_rates[2] = 11; - if (sta->tx_supp_rates & WLAN_RATE_11M) - sta->supported_rates[3] = 22; - prism2_check_tx_rates(sta); - atomic_dec(&sta->users); - return 0; -} - - -static int prism2_hostapd_remove_sta(struct ap_data *ap, - struct prism2_hostapd_param *param) -{ - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, param->sta_addr); - if (sta) { - ap_sta_hash_del(ap, sta); - list_del(&sta->list); - } - spin_unlock_bh(&ap->sta_table_lock); - - if (!sta) - return -ENOENT; - - if ((sta->flags & WLAN_STA_ASSOC) && !sta->ap && sta->local) - hostap_event_expired_sta(sta->local->dev, sta); - ap_free_sta(ap, sta); - - return 0; -} - - -static int prism2_hostapd_get_info_sta(struct ap_data *ap, - struct prism2_hostapd_param *param) -{ - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, param->sta_addr); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&ap->sta_table_lock); - - if (!sta) - return -ENOENT; - - param->u.get_info_sta.inactive_sec = (jiffies - sta->last_rx) / HZ; - - atomic_dec(&sta->users); - - return 1; -} - - -static int prism2_hostapd_set_flags_sta(struct ap_data *ap, - struct prism2_hostapd_param *param) -{ - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, param->sta_addr); - if (sta) { - sta->flags |= param->u.set_flags_sta.flags_or; - sta->flags &= param->u.set_flags_sta.flags_and; - } - spin_unlock_bh(&ap->sta_table_lock); - - if (!sta) - return -ENOENT; - - return 0; -} - - -static int prism2_hostapd_sta_clear_stats(struct ap_data *ap, - struct prism2_hostapd_param *param) -{ - struct sta_info *sta; - int rate; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, param->sta_addr); - if (sta) { - sta->rx_packets = sta->tx_packets = 0; - sta->rx_bytes = sta->tx_bytes = 0; - for (rate = 0; rate < WLAN_RATE_COUNT; rate++) { - sta->tx_count[rate] = 0; - sta->rx_count[rate] = 0; - } - } - spin_unlock_bh(&ap->sta_table_lock); - - if (!sta) - return -ENOENT; - - return 0; -} - - -int prism2_hostapd(struct ap_data *ap, struct prism2_hostapd_param *param) -{ - switch (param->cmd) { - case PRISM2_HOSTAPD_FLUSH: - ap_control_kickall(ap); - return 0; - case PRISM2_HOSTAPD_ADD_STA: - return prism2_hostapd_add_sta(ap, param); - case PRISM2_HOSTAPD_REMOVE_STA: - return prism2_hostapd_remove_sta(ap, param); - case PRISM2_HOSTAPD_GET_INFO_STA: - return prism2_hostapd_get_info_sta(ap, param); - case PRISM2_HOSTAPD_SET_FLAGS_STA: - return prism2_hostapd_set_flags_sta(ap, param); - case PRISM2_HOSTAPD_STA_CLEAR_STATS: - return prism2_hostapd_sta_clear_stats(ap, param); - default: - printk(KERN_WARNING "prism2_hostapd: unknown cmd=%d\n", - param->cmd); - return -EOPNOTSUPP; - } -} - - -/* Update station info for host-based TX rate control and return current - * TX rate */ -static int ap_update_sta_tx_rate(struct sta_info *sta, struct net_device *dev) -{ - int ret = sta->tx_rate; - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - sta->tx_count[sta->tx_rate_idx]++; - sta->tx_since_last_failure++; - sta->tx_consecutive_exc = 0; - if (sta->tx_since_last_failure >= WLAN_RATE_UPDATE_COUNT && - sta->tx_rate_idx < sta->tx_max_rate) { - /* use next higher rate */ - int old_rate, new_rate; - old_rate = new_rate = sta->tx_rate_idx; - while (new_rate < sta->tx_max_rate) { - new_rate++; - if (ap_tx_rate_ok(new_rate, sta, local)) { - sta->tx_rate_idx = new_rate; - break; - } - } - if (old_rate != sta->tx_rate_idx) { - switch (sta->tx_rate_idx) { - case 0: sta->tx_rate = 10; break; - case 1: sta->tx_rate = 20; break; - case 2: sta->tx_rate = 55; break; - case 3: sta->tx_rate = 110; break; - default: sta->tx_rate = 0; break; - } - PDEBUG(DEBUG_AP, "%s: STA %pM TX rate raised to %d\n", - dev->name, sta->addr, sta->tx_rate); - } - sta->tx_since_last_failure = 0; - } - - return ret; -} - - -/* Called only from software IRQ. Called for each TX frame prior possible - * encryption and transmit. */ -ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx) -{ - struct sta_info *sta = NULL; - struct sk_buff *skb = tx->skb; - int set_tim, ret; - struct ieee80211_hdr *hdr; - struct hostap_skb_tx_data *meta; - - meta = (struct hostap_skb_tx_data *) skb->cb; - ret = AP_TX_CONTINUE; - if (local->ap == NULL || skb->len < 10 || - meta->iface->type == HOSTAP_INTERFACE_STA) - goto out; - - hdr = (struct ieee80211_hdr *) skb->data; - - if (hdr->addr1[0] & 0x01) { - /* broadcast/multicast frame - no AP related processing */ - if (local->ap->num_sta <= 0) - ret = AP_TX_DROP; - goto out; - } - - /* unicast packet - check whether destination STA is associated */ - spin_lock(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr1); - if (sta) - atomic_inc(&sta->users); - spin_unlock(&local->ap->sta_table_lock); - - if (local->iw_mode == IW_MODE_MASTER && sta == NULL && - !(meta->flags & HOSTAP_TX_FLAGS_WDS) && - meta->iface->type != HOSTAP_INTERFACE_MASTER && - meta->iface->type != HOSTAP_INTERFACE_AP) { -#if 0 - /* This can happen, e.g., when wlan0 is added to a bridge and - * bridging code does not know which port is the correct target - * for a unicast frame. In this case, the packet is send to all - * ports of the bridge. Since this is a valid scenario, do not - * print out any errors here. */ - if (net_ratelimit()) { - printk(KERN_DEBUG "AP: drop packet to non-associated " - "STA %pM\n", hdr->addr1); - } -#endif - local->ap->tx_drop_nonassoc++; - ret = AP_TX_DROP; - goto out; - } - - if (sta == NULL) - goto out; - - if (!(sta->flags & WLAN_STA_AUTHORIZED)) - ret = AP_TX_CONTINUE_NOT_AUTHORIZED; - - /* Set tx_rate if using host-based TX rate control */ - if (!local->fw_tx_rate_control) - local->ap->last_tx_rate = meta->rate = - ap_update_sta_tx_rate(sta, local->dev); - - if (local->iw_mode != IW_MODE_MASTER) - goto out; - - if (!(sta->flags & WLAN_STA_PS)) - goto out; - - if (meta->flags & HOSTAP_TX_FLAGS_ADD_MOREDATA) { - /* indicate to STA that more frames follow */ - hdr->frame_control |= - cpu_to_le16(IEEE80211_FCTL_MOREDATA); - } - - if (meta->flags & HOSTAP_TX_FLAGS_BUFFERED_FRAME) { - /* packet was already buffered and now send due to - * PS poll, so do not rebuffer it */ - goto out; - } - - if (skb_queue_len(&sta->tx_buf) >= STA_MAX_TX_BUFFER) { - PDEBUG(DEBUG_PS, "%s: No more space in STA (%pM)'s" - "PS mode buffer\n", - local->dev->name, sta->addr); - /* Make sure that TIM is set for the station (it might not be - * after AP wlan hw reset). */ - /* FIX: should fix hw reset to restore bits based on STA - * buffer state.. */ - hostap_set_tim(local, sta->aid, 1); - sta->flags |= WLAN_STA_TIM; - ret = AP_TX_DROP; - goto out; - } - - /* STA in PS mode, buffer frame for later delivery */ - set_tim = skb_queue_empty(&sta->tx_buf); - skb_queue_tail(&sta->tx_buf, skb); - /* FIX: could save RX time to skb and expire buffered frames after - * some time if STA does not poll for them */ - - if (set_tim) { - if (sta->flags & WLAN_STA_TIM) - PDEBUG(DEBUG_PS2, "Re-setting TIM for aid %d\n", - sta->aid); - hostap_set_tim(local, sta->aid, 1); - sta->flags |= WLAN_STA_TIM; - } - - ret = AP_TX_BUFFERED; - - out: - if (sta != NULL) { - if (ret == AP_TX_CONTINUE || - ret == AP_TX_CONTINUE_NOT_AUTHORIZED) { - sta->tx_packets++; - sta->tx_bytes += skb->len; - sta->last_tx = jiffies; - } - - if ((ret == AP_TX_CONTINUE || - ret == AP_TX_CONTINUE_NOT_AUTHORIZED) && - sta->crypt && tx->host_encrypt) { - tx->crypt = sta->crypt; - tx->sta_ptr = sta; /* hostap_handle_sta_release() will - * be called to release sta info - * later */ - } else - atomic_dec(&sta->users); - } - - return ret; -} - - -void hostap_handle_sta_release(void *ptr) -{ - struct sta_info *sta = ptr; - atomic_dec(&sta->users); -} - - -/* Called only as a tasklet (software IRQ) */ -void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb) -{ - struct sta_info *sta; - struct ieee80211_hdr *hdr; - struct hostap_skb_tx_data *meta; - - hdr = (struct ieee80211_hdr *) skb->data; - meta = (struct hostap_skb_tx_data *) skb->cb; - - spin_lock(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr1); - if (!sta) { - spin_unlock(&local->ap->sta_table_lock); - PDEBUG(DEBUG_AP, "%s: Could not find STA %pM" - " for this TX error (@%lu)\n", - local->dev->name, hdr->addr1, jiffies); - return; - } - - sta->tx_since_last_failure = 0; - sta->tx_consecutive_exc++; - - if (sta->tx_consecutive_exc >= WLAN_RATE_DECREASE_THRESHOLD && - sta->tx_rate_idx > 0 && meta->rate <= sta->tx_rate) { - /* use next lower rate */ - int old, rate; - old = rate = sta->tx_rate_idx; - while (rate > 0) { - rate--; - if (ap_tx_rate_ok(rate, sta, local)) { - sta->tx_rate_idx = rate; - break; - } - } - if (old != sta->tx_rate_idx) { - switch (sta->tx_rate_idx) { - case 0: sta->tx_rate = 10; break; - case 1: sta->tx_rate = 20; break; - case 2: sta->tx_rate = 55; break; - case 3: sta->tx_rate = 110; break; - default: sta->tx_rate = 0; break; - } - PDEBUG(DEBUG_AP, - "%s: STA %pM TX rate lowered to %d\n", - local->dev->name, sta->addr, sta->tx_rate); - } - sta->tx_consecutive_exc = 0; - } - spin_unlock(&local->ap->sta_table_lock); -} - - -static void hostap_update_sta_ps2(local_info_t *local, struct sta_info *sta, - int pwrmgt, int type, int stype) -{ - if (pwrmgt && !(sta->flags & WLAN_STA_PS)) { - sta->flags |= WLAN_STA_PS; - PDEBUG(DEBUG_PS2, "STA %pM changed to use PS " - "mode (type=0x%02X, stype=0x%02X)\n", - sta->addr, type >> 2, stype >> 4); - } else if (!pwrmgt && (sta->flags & WLAN_STA_PS)) { - sta->flags &= ~WLAN_STA_PS; - PDEBUG(DEBUG_PS2, "STA %pM changed to not use " - "PS mode (type=0x%02X, stype=0x%02X)\n", - sta->addr, type >> 2, stype >> 4); - if (type != IEEE80211_FTYPE_CTL || - stype != IEEE80211_STYPE_PSPOLL) - schedule_packet_send(local, sta); - } -} - - -/* Called only as a tasklet (software IRQ). Called for each RX frame to update - * STA power saving state. pwrmgt is a flag from 802.11 frame_control field. */ -int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr) -{ - struct sta_info *sta; - u16 fc; - - spin_lock(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta) - atomic_inc(&sta->users); - spin_unlock(&local->ap->sta_table_lock); - - if (!sta) - return -1; - - fc = le16_to_cpu(hdr->frame_control); - hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM, - fc & IEEE80211_FCTL_FTYPE, - fc & IEEE80211_FCTL_STYPE); - - atomic_dec(&sta->users); - return 0; -} - - -/* Called only as a tasklet (software IRQ). Called for each RX frame after - * getting RX header and payload from hardware. */ -ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, - struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats, - int wds) -{ - int ret; - struct sta_info *sta; - u16 fc, type, stype; - struct ieee80211_hdr *hdr; - - if (local->ap == NULL) - return AP_RX_CONTINUE; - - hdr = (struct ieee80211_hdr *) skb->data; - - fc = le16_to_cpu(hdr->frame_control); - type = fc & IEEE80211_FCTL_FTYPE; - stype = fc & IEEE80211_FCTL_STYPE; - - spin_lock(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta) - atomic_inc(&sta->users); - spin_unlock(&local->ap->sta_table_lock); - - if (sta && !(sta->flags & WLAN_STA_AUTHORIZED)) - ret = AP_RX_CONTINUE_NOT_AUTHORIZED; - else - ret = AP_RX_CONTINUE; - - - if (fc & IEEE80211_FCTL_TODS) { - if (!wds && (sta == NULL || !(sta->flags & WLAN_STA_ASSOC))) { - if (local->hostapd) { - prism2_rx_80211(local->apdev, skb, rx_stats, - PRISM2_RX_NON_ASSOC); -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - } else { - printk(KERN_DEBUG "%s: dropped received packet" - " from non-associated STA %pM" - " (type=0x%02x, subtype=0x%02x)\n", - dev->name, hdr->addr2, - type >> 2, stype >> 4); - hostap_rx(dev, skb, rx_stats); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - } - ret = AP_RX_EXIT; - goto out; - } - } else if (fc & IEEE80211_FCTL_FROMDS) { - if (!wds) { - /* FromDS frame - not for us; probably - * broadcast/multicast in another BSS - drop */ - if (memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { - printk(KERN_DEBUG "Odd.. FromDS packet " - "received with own BSSID\n"); - hostap_dump_rx_80211(dev->name, skb, rx_stats); - } - ret = AP_RX_DROP; - goto out; - } - } else if (stype == IEEE80211_STYPE_NULLFUNC && sta == NULL && - memcmp(hdr->addr1, dev->dev_addr, ETH_ALEN) == 0) { - - if (local->hostapd) { - prism2_rx_80211(local->apdev, skb, rx_stats, - PRISM2_RX_NON_ASSOC); -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - } else { - /* At least Lucent f/w seems to send data::nullfunc - * frames with no ToDS flag when the current AP returns - * after being unavailable for some time. Speed up - * re-association by informing the station about it not - * being associated. */ - printk(KERN_DEBUG "%s: rejected received nullfunc frame" - " without ToDS from not associated STA %pM\n", - dev->name, hdr->addr2); - hostap_rx(dev, skb, rx_stats); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - } - ret = AP_RX_EXIT; - goto out; - } else if (stype == IEEE80211_STYPE_NULLFUNC) { - /* At least Lucent cards seem to send periodic nullfunc - * frames with ToDS. Let these through to update SQ - * stats and PS state. Nullfunc frames do not contain - * any data and they will be dropped below. */ - } else { - /* If BSSID (Addr3) is foreign, this frame is a normal - * broadcast frame from an IBSS network. Drop it silently. - * If BSSID is own, report the dropping of this frame. */ - if (memcmp(hdr->addr3, dev->dev_addr, ETH_ALEN) == 0) { - printk(KERN_DEBUG "%s: dropped received packet from %pM" - " with no ToDS flag " - "(type=0x%02x, subtype=0x%02x)\n", dev->name, - hdr->addr2, type >> 2, stype >> 4); - hostap_dump_rx_80211(dev->name, skb, rx_stats); - } - ret = AP_RX_DROP; - goto out; - } - - if (sta) { - hostap_update_sta_ps2(local, sta, fc & IEEE80211_FCTL_PM, - type, stype); - - sta->rx_packets++; - sta->rx_bytes += skb->len; - sta->last_rx = jiffies; - } - - if (local->ap->nullfunc_ack && stype == IEEE80211_STYPE_NULLFUNC && - fc & IEEE80211_FCTL_TODS) { - if (local->hostapd) { - prism2_rx_80211(local->apdev, skb, rx_stats, - PRISM2_RX_NULLFUNC_ACK); -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - } else { - /* some STA f/w's seem to require control::ACK frame - * for data::nullfunc, but Prism2 f/w 0.8.0 (at least - * from Compaq) does not send this.. Try to generate - * ACK for these frames from the host driver to make - * power saving work with, e.g., Lucent WaveLAN f/w */ - hostap_rx(dev, skb, rx_stats); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - } - ret = AP_RX_EXIT; - goto out; - } - - out: - if (sta) - atomic_dec(&sta->users); - - return ret; -} - - -/* Called only as a tasklet (software IRQ) */ -int hostap_handle_sta_crypto(local_info_t *local, - struct ieee80211_hdr *hdr, - struct lib80211_crypt_data **crypt, - void **sta_ptr) -{ - struct sta_info *sta; - - spin_lock(&local->ap->sta_table_lock); - sta = ap_get_sta(local->ap, hdr->addr2); - if (sta) - atomic_inc(&sta->users); - spin_unlock(&local->ap->sta_table_lock); - - if (!sta) - return -1; - - if (sta->crypt) { - *crypt = sta->crypt; - *sta_ptr = sta; - /* hostap_handle_sta_release() will be called to release STA - * info */ - } else - atomic_dec(&sta->users); - - return 0; -} - - -/* Called only as a tasklet (software IRQ) */ -int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr) -{ - struct sta_info *sta; - int ret = 0; - - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, sta_addr); - if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap) - ret = 1; - spin_unlock(&ap->sta_table_lock); - - return ret; -} - - -/* Called only as a tasklet (software IRQ) */ -int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr) -{ - struct sta_info *sta; - int ret = 0; - - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, sta_addr); - if (sta != NULL && (sta->flags & WLAN_STA_ASSOC) && !sta->ap && - ((sta->flags & WLAN_STA_AUTHORIZED) || - ap->local->ieee_802_1x == 0)) - ret = 1; - spin_unlock(&ap->sta_table_lock); - - return ret; -} - - -/* Called only as a tasklet (software IRQ) */ -int hostap_add_sta(struct ap_data *ap, u8 *sta_addr) -{ - struct sta_info *sta; - int ret = 1; - - if (!ap) - return -1; - - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, sta_addr); - if (sta) - ret = 0; - spin_unlock(&ap->sta_table_lock); - - if (ret == 1) { - sta = ap_add_sta(ap, sta_addr); - if (!sta) - return -1; - sta->flags = WLAN_STA_AUTH | WLAN_STA_ASSOC; - sta->ap = 1; - memset(sta->supported_rates, 0, sizeof(sta->supported_rates)); - /* No way of knowing which rates are supported since we did not - * get supported rates element from beacon/assoc req. Assume - * that remote end supports all 802.11b rates. */ - sta->supported_rates[0] = 0x82; - sta->supported_rates[1] = 0x84; - sta->supported_rates[2] = 0x0b; - sta->supported_rates[3] = 0x16; - sta->tx_supp_rates = WLAN_RATE_1M | WLAN_RATE_2M | - WLAN_RATE_5M5 | WLAN_RATE_11M; - sta->tx_rate = 110; - sta->tx_max_rate = sta->tx_rate_idx = 3; - } - - return ret; -} - - -/* Called only as a tasklet (software IRQ) */ -int hostap_update_rx_stats(struct ap_data *ap, - struct ieee80211_hdr *hdr, - struct hostap_80211_rx_status *rx_stats) -{ - struct sta_info *sta; - - if (!ap) - return -1; - - spin_lock(&ap->sta_table_lock); - sta = ap_get_sta(ap, hdr->addr2); - if (sta) { - sta->last_rx_silence = rx_stats->noise; - sta->last_rx_signal = rx_stats->signal; - sta->last_rx_rate = rx_stats->rate; - sta->last_rx_updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - if (rx_stats->rate == 10) - sta->rx_count[0]++; - else if (rx_stats->rate == 20) - sta->rx_count[1]++; - else if (rx_stats->rate == 55) - sta->rx_count[2]++; - else if (rx_stats->rate == 110) - sta->rx_count[3]++; - } - spin_unlock(&ap->sta_table_lock); - - return sta ? 0 : -1; -} - - -void hostap_update_rates(local_info_t *local) -{ - struct sta_info *sta; - struct ap_data *ap = local->ap; - - if (!ap) - return; - - spin_lock_bh(&ap->sta_table_lock); - list_for_each_entry(sta, &ap->sta_list, list) { - prism2_check_tx_rates(sta); - } - spin_unlock_bh(&ap->sta_table_lock); -} - - -void * ap_crypt_get_ptrs(struct ap_data *ap, u8 *addr, int permanent, - struct lib80211_crypt_data ***crypt) -{ - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - sta = ap_get_sta(ap, addr); - if (sta) - atomic_inc(&sta->users); - spin_unlock_bh(&ap->sta_table_lock); - - if (!sta && permanent) - sta = ap_add_sta(ap, addr); - - if (!sta) - return NULL; - - if (permanent) - sta->flags |= WLAN_STA_PERM; - - *crypt = &sta->crypt; - - return sta; -} - - -void hostap_add_wds_links(local_info_t *local) -{ - struct ap_data *ap = local->ap; - struct sta_info *sta; - - spin_lock_bh(&ap->sta_table_lock); - list_for_each_entry(sta, &ap->sta_list, list) { - if (sta->ap) - hostap_wds_link_oper(local, sta->addr, WDS_ADD); - } - spin_unlock_bh(&ap->sta_table_lock); - - schedule_work(&local->ap->wds_oper_queue); -} - - -void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type) -{ - struct wds_oper_data *entry; - - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) - return; - memcpy(entry->addr, addr, ETH_ALEN); - entry->type = type; - spin_lock_bh(&local->lock); - entry->next = local->ap->wds_oper_entries; - local->ap->wds_oper_entries = entry; - spin_unlock_bh(&local->lock); - - schedule_work(&local->ap->wds_oper_queue); -} - - -EXPORT_SYMBOL(hostap_init_data); -EXPORT_SYMBOL(hostap_init_ap_proc); -EXPORT_SYMBOL(hostap_free_data); -EXPORT_SYMBOL(hostap_check_sta_fw_version); -EXPORT_SYMBOL(hostap_handle_sta_tx_exc); -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ diff --git a/drivers/net/wireless/hostap/hostap_ap.h b/drivers/net/wireless/hostap/hostap_ap.h deleted file mode 100644 index 655ceeba9612..000000000000 --- a/drivers/net/wireless/hostap/hostap_ap.h +++ /dev/null @@ -1,263 +0,0 @@ -#ifndef HOSTAP_AP_H -#define HOSTAP_AP_H - -#include "hostap_80211.h" - -/* AP data structures for STAs */ - -/* maximum number of frames to buffer per STA */ -#define STA_MAX_TX_BUFFER 32 - -/* STA flags */ -#define WLAN_STA_AUTH BIT(0) -#define WLAN_STA_ASSOC BIT(1) -#define WLAN_STA_PS BIT(2) -#define WLAN_STA_TIM BIT(3) /* TIM bit is on for PS stations */ -#define WLAN_STA_PERM BIT(4) /* permanent; do not remove entry on expiration */ -#define WLAN_STA_AUTHORIZED BIT(5) /* If 802.1X is used, this flag is - * controlling whether STA is authorized to - * send and receive non-IEEE 802.1X frames - */ -#define WLAN_STA_PENDING_POLL BIT(6) /* pending activity poll not ACKed */ - -#define WLAN_RATE_1M BIT(0) -#define WLAN_RATE_2M BIT(1) -#define WLAN_RATE_5M5 BIT(2) -#define WLAN_RATE_11M BIT(3) -#define WLAN_RATE_COUNT 4 - -/* Maximum size of Supported Rates info element. IEEE 802.11 has a limit of 8, - * but some pre-standard IEEE 802.11g products use longer elements. */ -#define WLAN_SUPP_RATES_MAX 32 - -/* Try to increase TX rate after # successfully sent consecutive packets */ -#define WLAN_RATE_UPDATE_COUNT 50 - -/* Decrease TX rate after # consecutive dropped packets */ -#define WLAN_RATE_DECREASE_THRESHOLD 2 - -struct sta_info { - struct list_head list; - struct sta_info *hnext; /* next entry in hash table list */ - atomic_t users; /* number of users (do not remove if > 0) */ - struct proc_dir_entry *proc; - - u8 addr[6]; - u16 aid; /* STA's unique AID (1 .. 2007) or 0 if not yet assigned */ - u32 flags; - u16 capability; - u16 listen_interval; /* or beacon_int for APs */ - u8 supported_rates[WLAN_SUPP_RATES_MAX]; - - unsigned long last_auth; - unsigned long last_assoc; - unsigned long last_rx; - unsigned long last_tx; - unsigned long rx_packets, tx_packets; - unsigned long rx_bytes, tx_bytes; - struct sk_buff_head tx_buf; - /* FIX: timeout buffers with an expiry time somehow derived from - * listen_interval */ - - s8 last_rx_silence; /* Noise in dBm */ - s8 last_rx_signal; /* Signal strength in dBm */ - u8 last_rx_rate; /* TX rate in 0.1 Mbps */ - u8 last_rx_updated; /* IWSPY's struct iw_quality::updated */ - - u8 tx_supp_rates; /* bit field of supported TX rates */ - u8 tx_rate; /* current TX rate (in 0.1 Mbps) */ - u8 tx_rate_idx; /* current TX rate (WLAN_RATE_*) */ - u8 tx_max_rate; /* max TX rate (WLAN_RATE_*) */ - u32 tx_count[WLAN_RATE_COUNT]; /* number of frames sent (per rate) */ - u32 rx_count[WLAN_RATE_COUNT]; /* number of frames received (per rate) - */ - u32 tx_since_last_failure; - u32 tx_consecutive_exc; - - struct lib80211_crypt_data *crypt; - - int ap; /* whether this station is an AP */ - - local_info_t *local; - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - union { - struct { - char *challenge; /* shared key authentication - * challenge */ - } sta; - struct { - int ssid_len; - unsigned char ssid[MAX_SSID_LEN + 1]; /* AP's ssid */ - int channel; - unsigned long last_beacon; /* last RX beacon time */ - } ap; - } u; - - struct timer_list timer; - enum { STA_NULLFUNC = 0, STA_DISASSOC, STA_DEAUTH } timeout_next; -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -}; - - -#define MAX_STA_COUNT 1024 - -/* Maximum number of AIDs to use for STAs; must be 2007 or lower - * (8802.11 limitation) */ -#define MAX_AID_TABLE_SIZE 128 - -#define STA_HASH_SIZE 256 -#define STA_HASH(sta) (sta[5]) - - -/* Default value for maximum station inactivity. After AP_MAX_INACTIVITY_SEC - * has passed since last received frame from the station, a nullfunc data - * frame is sent to the station. If this frame is not acknowledged and no other - * frames have been received, the station will be disassociated after - * AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after - * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with - * max inactivity timer. */ -#define AP_MAX_INACTIVITY_SEC (5 * 60) -#define AP_DISASSOC_DELAY (HZ) -#define AP_DEAUTH_DELAY (HZ) - -/* ap_policy: whether to accept frames to/from other APs/IBSS */ -typedef enum { - AP_OTHER_AP_SKIP_ALL = 0, - AP_OTHER_AP_SAME_SSID = 1, - AP_OTHER_AP_ALL = 2, - AP_OTHER_AP_EVEN_IBSS = 3 -} ap_policy_enum; - -#define PRISM2_AUTH_OPEN BIT(0) -#define PRISM2_AUTH_SHARED_KEY BIT(1) - - -/* MAC address-based restrictions */ -struct mac_entry { - struct list_head list; - u8 addr[6]; -}; - -struct mac_restrictions { - enum { MAC_POLICY_OPEN = 0, MAC_POLICY_ALLOW, MAC_POLICY_DENY } policy; - unsigned int entries; - struct list_head mac_list; - spinlock_t lock; -}; - - -struct add_sta_proc_data { - u8 addr[ETH_ALEN]; - struct add_sta_proc_data *next; -}; - - -typedef enum { WDS_ADD, WDS_DEL } wds_oper_type; -struct wds_oper_data { - wds_oper_type type; - u8 addr[ETH_ALEN]; - struct wds_oper_data *next; -}; - - -struct ap_data { - int initialized; /* whether ap_data has been initialized */ - local_info_t *local; - int bridge_packets; /* send packet to associated STAs directly to the - * wireless media instead of higher layers in the - * kernel */ - unsigned int bridged_unicast; /* number of unicast frames bridged on - * wireless media */ - unsigned int bridged_multicast; /* number of non-unicast frames - * bridged on wireless media */ - unsigned int tx_drop_nonassoc; /* number of unicast TX packets dropped - * because they were to an address that - * was not associated */ - int nullfunc_ack; /* use workaround for nullfunc frame ACKs */ - - spinlock_t sta_table_lock; - int num_sta; /* number of entries in sta_list */ - struct list_head sta_list; /* STA info list head */ - struct sta_info *sta_hash[STA_HASH_SIZE]; - - struct proc_dir_entry *proc; - - ap_policy_enum ap_policy; - unsigned int max_inactivity; - int autom_ap_wds; - - struct mac_restrictions mac_restrictions; /* MAC-based auth */ - int last_tx_rate; - - struct work_struct add_sta_proc_queue; - struct add_sta_proc_data *add_sta_proc_entries; - - struct work_struct wds_oper_queue; - struct wds_oper_data *wds_oper_entries; - - u16 tx_callback_idx; - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - /* pointers to STA info; based on allocated AID or NULL if AID free - * AID is in the range 1-2007, so sta_aid[0] corresponders to AID 1 - * and so on - */ - struct sta_info *sta_aid[MAX_AID_TABLE_SIZE]; - - u16 tx_callback_auth, tx_callback_assoc, tx_callback_poll; - - /* WEP operations for generating challenges to be used with shared key - * authentication */ - struct lib80211_crypto_ops *crypt; - void *crypt_priv; -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ -}; - - -void hostap_rx(struct net_device *dev, struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats); -void hostap_init_data(local_info_t *local); -void hostap_init_ap_proc(local_info_t *local); -void hostap_free_data(struct ap_data *ap); -void hostap_check_sta_fw_version(struct ap_data *ap, int sta_fw_ver); - -typedef enum { - AP_TX_CONTINUE, AP_TX_DROP, AP_TX_RETRY, AP_TX_BUFFERED, - AP_TX_CONTINUE_NOT_AUTHORIZED -} ap_tx_ret; -struct hostap_tx_data { - struct sk_buff *skb; - int host_encrypt; - struct lib80211_crypt_data *crypt; - void *sta_ptr; -}; -ap_tx_ret hostap_handle_sta_tx(local_info_t *local, struct hostap_tx_data *tx); -void hostap_handle_sta_release(void *ptr); -void hostap_handle_sta_tx_exc(local_info_t *local, struct sk_buff *skb); -int hostap_update_sta_ps(local_info_t *local, struct ieee80211_hdr *hdr); -typedef enum { - AP_RX_CONTINUE, AP_RX_DROP, AP_RX_EXIT, AP_RX_CONTINUE_NOT_AUTHORIZED -} ap_rx_ret; -ap_rx_ret hostap_handle_sta_rx(local_info_t *local, struct net_device *dev, - struct sk_buff *skb, - struct hostap_80211_rx_status *rx_stats, - int wds); -int hostap_handle_sta_crypto(local_info_t *local, struct ieee80211_hdr *hdr, - struct lib80211_crypt_data **crypt, - void **sta_ptr); -int hostap_is_sta_assoc(struct ap_data *ap, u8 *sta_addr); -int hostap_is_sta_authorized(struct ap_data *ap, u8 *sta_addr); -int hostap_add_sta(struct ap_data *ap, u8 *sta_addr); -int hostap_update_rx_stats(struct ap_data *ap, struct ieee80211_hdr *hdr, - struct hostap_80211_rx_status *rx_stats); -void hostap_update_rates(local_info_t *local); -void hostap_add_wds_links(local_info_t *local); -void hostap_wds_link_oper(local_info_t *local, u8 *addr, wds_oper_type type); - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -void hostap_deauth_all_stas(struct net_device *dev, struct ap_data *ap, - int resend); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - -#endif /* HOSTAP_AP_H */ diff --git a/drivers/net/wireless/hostap/hostap_common.h b/drivers/net/wireless/hostap/hostap_common.h deleted file mode 100644 index 90b64b092007..000000000000 --- a/drivers/net/wireless/hostap/hostap_common.h +++ /dev/null @@ -1,419 +0,0 @@ -#ifndef HOSTAP_COMMON_H -#define HOSTAP_COMMON_H - -#include -#include - -/* IEEE 802.11 defines */ - -/* HFA384X Configuration RIDs */ -#define HFA384X_RID_CNFPORTTYPE 0xFC00 -#define HFA384X_RID_CNFOWNMACADDR 0xFC01 -#define HFA384X_RID_CNFDESIREDSSID 0xFC02 -#define HFA384X_RID_CNFOWNCHANNEL 0xFC03 -#define HFA384X_RID_CNFOWNSSID 0xFC04 -#define HFA384X_RID_CNFOWNATIMWINDOW 0xFC05 -#define HFA384X_RID_CNFSYSTEMSCALE 0xFC06 -#define HFA384X_RID_CNFMAXDATALEN 0xFC07 -#define HFA384X_RID_CNFWDSADDRESS 0xFC08 -#define HFA384X_RID_CNFPMENABLED 0xFC09 -#define HFA384X_RID_CNFPMEPS 0xFC0A -#define HFA384X_RID_CNFMULTICASTRECEIVE 0xFC0B -#define HFA384X_RID_CNFMAXSLEEPDURATION 0xFC0C -#define HFA384X_RID_CNFPMHOLDOVERDURATION 0xFC0D -#define HFA384X_RID_CNFOWNNAME 0xFC0E -#define HFA384X_RID_CNFOWNDTIMPERIOD 0xFC10 -#define HFA384X_RID_CNFWDSADDRESS1 0xFC11 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS2 0xFC12 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS3 0xFC13 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS4 0xFC14 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS5 0xFC15 /* AP f/w only */ -#define HFA384X_RID_CNFWDSADDRESS6 0xFC16 /* AP f/w only */ -#define HFA384X_RID_CNFMULTICASTPMBUFFERING 0xFC17 /* AP f/w only */ -#define HFA384X_RID_UNKNOWN1 0xFC20 -#define HFA384X_RID_UNKNOWN2 0xFC21 -#define HFA384X_RID_CNFWEPDEFAULTKEYID 0xFC23 -#define HFA384X_RID_CNFDEFAULTKEY0 0xFC24 -#define HFA384X_RID_CNFDEFAULTKEY1 0xFC25 -#define HFA384X_RID_CNFDEFAULTKEY2 0xFC26 -#define HFA384X_RID_CNFDEFAULTKEY3 0xFC27 -#define HFA384X_RID_CNFWEPFLAGS 0xFC28 -#define HFA384X_RID_CNFWEPKEYMAPPINGTABLE 0xFC29 -#define HFA384X_RID_CNFAUTHENTICATION 0xFC2A -#define HFA384X_RID_CNFMAXASSOCSTA 0xFC2B /* AP f/w only */ -#define HFA384X_RID_CNFTXCONTROL 0xFC2C -#define HFA384X_RID_CNFROAMINGMODE 0xFC2D -#define HFA384X_RID_CNFHOSTAUTHENTICATION 0xFC2E /* AP f/w only */ -#define HFA384X_RID_CNFRCVCRCERROR 0xFC30 -#define HFA384X_RID_CNFMMLIFE 0xFC31 -#define HFA384X_RID_CNFALTRETRYCOUNT 0xFC32 -#define HFA384X_RID_CNFBEACONINT 0xFC33 -#define HFA384X_RID_CNFAPPCFINFO 0xFC34 /* AP f/w only */ -#define HFA384X_RID_CNFSTAPCFINFO 0xFC35 -#define HFA384X_RID_CNFPRIORITYQUSAGE 0xFC37 -#define HFA384X_RID_CNFTIMCTRL 0xFC40 -#define HFA384X_RID_UNKNOWN3 0xFC41 /* added in STA f/w 0.7.x */ -#define HFA384X_RID_CNFTHIRTY2TALLY 0xFC42 /* added in STA f/w 0.8.0 */ -#define HFA384X_RID_CNFENHSECURITY 0xFC43 /* AP f/w or STA f/w >= 1.6.3 */ -#define HFA384X_RID_CNFDBMADJUST 0xFC46 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_GENERICELEMENT 0xFC48 /* added in STA f/w 1.7.0; - * write only */ -#define HFA384X_RID_PROPAGATIONDELAY 0xFC49 /* added in STA f/w 1.7.6 */ -#define HFA384X_RID_GROUPADDRESSES 0xFC80 -#define HFA384X_RID_CREATEIBSS 0xFC81 -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD 0xFC82 -#define HFA384X_RID_RTSTHRESHOLD 0xFC83 -#define HFA384X_RID_TXRATECONTROL 0xFC84 -#define HFA384X_RID_PROMISCUOUSMODE 0xFC85 -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD0 0xFC90 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD1 0xFC91 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD2 0xFC92 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD3 0xFC93 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD4 0xFC94 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD5 0xFC95 /* AP f/w only */ -#define HFA384X_RID_FRAGMENTATIONTHRESHOLD6 0xFC96 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD0 0xFC97 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD1 0xFC98 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD2 0xFC99 /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD3 0xFC9A /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD4 0xFC9B /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD5 0xFC9C /* AP f/w only */ -#define HFA384X_RID_RTSTHRESHOLD6 0xFC9D /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL0 0xFC9E /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL1 0xFC9F /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL2 0xFCA0 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL3 0xFCA1 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL4 0xFCA2 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL5 0xFCA3 /* AP f/w only */ -#define HFA384X_RID_TXRATECONTROL6 0xFCA4 /* AP f/w only */ -#define HFA384X_RID_CNFSHORTPREAMBLE 0xFCB0 -#define HFA384X_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1 -#define HFA384X_RID_CNFAUTHENTICATIONRSPTO 0xFCB2 -#define HFA384X_RID_CNFBASICRATES 0xFCB3 -#define HFA384X_RID_CNFSUPPORTEDRATES 0xFCB4 -#define HFA384X_RID_CNFFALLBACKCTRL 0xFCB5 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_WEPKEYDISABLE 0xFCB6 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_WEPKEYMAPINDEX 0xFCB7 /* ? */ -#define HFA384X_RID_BROADCASTKEYID 0xFCB8 /* ? */ -#define HFA384X_RID_ENTSECFLAGEYID 0xFCB9 /* ? */ -#define HFA384X_RID_CNFPASSIVESCANCTRL 0xFCBA /* added in STA f/w 1.5.0 */ -#define HFA384X_RID_SSNHANDLINGMODE 0xFCBB /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_MDCCONTROL 0xFCBC /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_MDCCOUNTRY 0xFCBD /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_TXPOWERMAX 0xFCBE /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_CNFLFOENABLED 0xFCBF /* added in STA f/w 1.6.3 */ -#define HFA384X_RID_CAPINFO 0xFCC0 /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_LISTENINTERVAL 0xFCC1 /* added in STA f/w 1.7.0 */ -#define HFA384X_RID_SW_ANT_DIV 0xFCC2 /* added in STA f/w 1.7.0; Prism3 */ -#define HFA384X_RID_LED_CTRL 0xFCC4 /* added in STA f/w 1.7.6 */ -#define HFA384X_RID_HFODELAY 0xFCC5 /* added in STA f/w 1.7.6 */ -#define HFA384X_RID_DISALLOWEDBSSID 0xFCC6 /* added in STA f/w 1.8.0 */ -#define HFA384X_RID_TICKTIME 0xFCE0 -#define HFA384X_RID_SCANREQUEST 0xFCE1 -#define HFA384X_RID_JOINREQUEST 0xFCE2 -#define HFA384X_RID_AUTHENTICATESTATION 0xFCE3 /* AP f/w only */ -#define HFA384X_RID_CHANNELINFOREQUEST 0xFCE4 /* AP f/w only */ -#define HFA384X_RID_HOSTSCAN 0xFCE5 /* added in STA f/w 1.3.1 */ - -/* HFA384X Information RIDs */ -#define HFA384X_RID_MAXLOADTIME 0xFD00 -#define HFA384X_RID_DOWNLOADBUFFER 0xFD01 -#define HFA384X_RID_PRIID 0xFD02 -#define HFA384X_RID_PRISUPRANGE 0xFD03 -#define HFA384X_RID_CFIACTRANGES 0xFD04 -#define HFA384X_RID_NICSERNUM 0xFD0A -#define HFA384X_RID_NICID 0xFD0B -#define HFA384X_RID_MFISUPRANGE 0xFD0C -#define HFA384X_RID_CFISUPRANGE 0xFD0D -#define HFA384X_RID_CHANNELLIST 0xFD10 -#define HFA384X_RID_REGULATORYDOMAINS 0xFD11 -#define HFA384X_RID_TEMPTYPE 0xFD12 -#define HFA384X_RID_CIS 0xFD13 -#define HFA384X_RID_STAID 0xFD20 -#define HFA384X_RID_STASUPRANGE 0xFD21 -#define HFA384X_RID_MFIACTRANGES 0xFD22 -#define HFA384X_RID_CFIACTRANGES2 0xFD23 -#define HFA384X_RID_PRODUCTNAME 0xFD24 /* added in STA f/w 1.3.1; - * only Prism2.5(?) */ -#define HFA384X_RID_PORTSTATUS 0xFD40 -#define HFA384X_RID_CURRENTSSID 0xFD41 -#define HFA384X_RID_CURRENTBSSID 0xFD42 -#define HFA384X_RID_COMMSQUALITY 0xFD43 -#define HFA384X_RID_CURRENTTXRATE 0xFD44 -#define HFA384X_RID_CURRENTBEACONINTERVAL 0xFD45 -#define HFA384X_RID_CURRENTSCALETHRESHOLDS 0xFD46 -#define HFA384X_RID_PROTOCOLRSPTIME 0xFD47 -#define HFA384X_RID_SHORTRETRYLIMIT 0xFD48 -#define HFA384X_RID_LONGRETRYLIMIT 0xFD49 -#define HFA384X_RID_MAXTRANSMITLIFETIME 0xFD4A -#define HFA384X_RID_MAXRECEIVELIFETIME 0xFD4B -#define HFA384X_RID_CFPOLLABLE 0xFD4C -#define HFA384X_RID_AUTHENTICATIONALGORITHMS 0xFD4D -#define HFA384X_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F -#define HFA384X_RID_DBMCOMMSQUALITY 0xFD51 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_CURRENTTXRATE1 0xFD80 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE2 0xFD81 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE3 0xFD82 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE4 0xFD83 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE5 0xFD84 /* AP f/w only */ -#define HFA384X_RID_CURRENTTXRATE6 0xFD85 /* AP f/w only */ -#define HFA384X_RID_OWNMACADDR 0xFD86 /* AP f/w only */ -#define HFA384X_RID_SCANRESULTSTABLE 0xFD88 /* added in STA f/w 0.8.3 */ -#define HFA384X_RID_HOSTSCANRESULTS 0xFD89 /* added in STA f/w 1.3.1 */ -#define HFA384X_RID_AUTHENTICATIONUSED 0xFD8A /* added in STA f/w 1.3.4 */ -#define HFA384X_RID_CNFFAASWITCHCTRL 0xFD8B /* added in STA f/w 1.6.3 */ -#define HFA384X_RID_ASSOCIATIONFAILURE 0xFD8D /* added in STA f/w 1.8.0 */ -#define HFA384X_RID_PHYTYPE 0xFDC0 -#define HFA384X_RID_CURRENTCHANNEL 0xFDC1 -#define HFA384X_RID_CURRENTPOWERSTATE 0xFDC2 -#define HFA384X_RID_CCAMODE 0xFDC3 -#define HFA384X_RID_SUPPORTEDDATARATES 0xFDC6 -#define HFA384X_RID_LFO_VOLT_REG_TEST_RES 0xFDC7 /* added in STA f/w 1.7.1 */ -#define HFA384X_RID_BUILDSEQ 0xFFFE -#define HFA384X_RID_FWID 0xFFFF - - -struct hfa384x_comp_ident -{ - __le16 id; - __le16 variant; - __le16 major; - __le16 minor; -} __attribute__ ((packed)); - -#define HFA384X_COMP_ID_PRI 0x15 -#define HFA384X_COMP_ID_STA 0x1f -#define HFA384X_COMP_ID_FW_AP 0x14b - -struct hfa384x_sup_range -{ - __le16 role; - __le16 id; - __le16 variant; - __le16 bottom; - __le16 top; -} __attribute__ ((packed)); - - -struct hfa384x_build_id -{ - __le16 pri_seq; - __le16 sec_seq; -} __attribute__ ((packed)); - -/* FD01 - Download Buffer */ -struct hfa384x_rid_download_buffer -{ - __le16 page; - __le16 offset; - __le16 length; -} __attribute__ ((packed)); - -/* BSS connection quality (RID FD43 range, RID FD51 dBm-normalized) */ -struct hfa384x_comms_quality { - __le16 comm_qual; /* 0 .. 92 */ - __le16 signal_level; /* 27 .. 154 */ - __le16 noise_level; /* 27 .. 154 */ -} __attribute__ ((packed)); - - -/* netdevice private ioctls (used, e.g., with iwpriv from user space) */ - -/* New wireless extensions API - SET/GET convention (even ioctl numbers are - * root only) - */ -#define PRISM2_IOCTL_PRISM2_PARAM (SIOCIWFIRSTPRIV + 0) -#define PRISM2_IOCTL_GET_PRISM2_PARAM (SIOCIWFIRSTPRIV + 1) -#define PRISM2_IOCTL_WRITEMIF (SIOCIWFIRSTPRIV + 2) -#define PRISM2_IOCTL_READMIF (SIOCIWFIRSTPRIV + 3) -#define PRISM2_IOCTL_MONITOR (SIOCIWFIRSTPRIV + 4) -#define PRISM2_IOCTL_RESET (SIOCIWFIRSTPRIV + 6) -#define PRISM2_IOCTL_INQUIRE (SIOCIWFIRSTPRIV + 8) -#define PRISM2_IOCTL_WDS_ADD (SIOCIWFIRSTPRIV + 10) -#define PRISM2_IOCTL_WDS_DEL (SIOCIWFIRSTPRIV + 12) -#define PRISM2_IOCTL_SET_RID_WORD (SIOCIWFIRSTPRIV + 14) -#define PRISM2_IOCTL_MACCMD (SIOCIWFIRSTPRIV + 16) -#define PRISM2_IOCTL_ADDMAC (SIOCIWFIRSTPRIV + 18) -#define PRISM2_IOCTL_DELMAC (SIOCIWFIRSTPRIV + 20) -#define PRISM2_IOCTL_KICKMAC (SIOCIWFIRSTPRIV + 22) - -/* following are not in SIOCGIWPRIV list; check permission in the driver code - */ -#define PRISM2_IOCTL_DOWNLOAD (SIOCDEVPRIVATE + 13) -#define PRISM2_IOCTL_HOSTAPD (SIOCDEVPRIVATE + 14) - - -/* PRISM2_IOCTL_PRISM2_PARAM ioctl() subtypes: */ -enum { - /* PRISM2_PARAM_PTYPE = 1, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_TXRATECTRL = 2, - PRISM2_PARAM_BEACON_INT = 3, - PRISM2_PARAM_PSEUDO_IBSS = 4, - PRISM2_PARAM_ALC = 5, - /* PRISM2_PARAM_TXPOWER = 6, */ /* REMOVED 2003-10-22 */ - PRISM2_PARAM_DUMP = 7, - PRISM2_PARAM_OTHER_AP_POLICY = 8, - PRISM2_PARAM_AP_MAX_INACTIVITY = 9, - PRISM2_PARAM_AP_BRIDGE_PACKETS = 10, - PRISM2_PARAM_DTIM_PERIOD = 11, - PRISM2_PARAM_AP_NULLFUNC_ACK = 12, - PRISM2_PARAM_MAX_WDS = 13, - PRISM2_PARAM_AP_AUTOM_AP_WDS = 14, - PRISM2_PARAM_AP_AUTH_ALGS = 15, - PRISM2_PARAM_MONITOR_ALLOW_FCSERR = 16, - PRISM2_PARAM_HOST_ENCRYPT = 17, - PRISM2_PARAM_HOST_DECRYPT = 18, - /* PRISM2_PARAM_BUS_MASTER_THRESHOLD_RX = 19, REMOVED 2005-08-14 */ - /* PRISM2_PARAM_BUS_MASTER_THRESHOLD_TX = 20, REMOVED 2005-08-14 */ - PRISM2_PARAM_HOST_ROAMING = 21, - PRISM2_PARAM_BCRX_STA_KEY = 22, - PRISM2_PARAM_IEEE_802_1X = 23, - PRISM2_PARAM_ANTSEL_TX = 24, - PRISM2_PARAM_ANTSEL_RX = 25, - PRISM2_PARAM_MONITOR_TYPE = 26, - PRISM2_PARAM_WDS_TYPE = 27, - PRISM2_PARAM_HOSTSCAN = 28, - PRISM2_PARAM_AP_SCAN = 29, - PRISM2_PARAM_ENH_SEC = 30, - PRISM2_PARAM_IO_DEBUG = 31, - PRISM2_PARAM_BASIC_RATES = 32, - PRISM2_PARAM_OPER_RATES = 33, - PRISM2_PARAM_HOSTAPD = 34, - PRISM2_PARAM_HOSTAPD_STA = 35, - PRISM2_PARAM_WPA = 36, - PRISM2_PARAM_PRIVACY_INVOKED = 37, - PRISM2_PARAM_TKIP_COUNTERMEASURES = 38, - PRISM2_PARAM_DROP_UNENCRYPTED = 39, - PRISM2_PARAM_SCAN_CHANNEL_MASK = 40, -}; - -enum { HOSTAP_ANTSEL_DO_NOT_TOUCH = 0, HOSTAP_ANTSEL_DIVERSITY = 1, - HOSTAP_ANTSEL_LOW = 2, HOSTAP_ANTSEL_HIGH = 3 }; - - -/* PRISM2_IOCTL_MACCMD ioctl() subcommands: */ -enum { AP_MAC_CMD_POLICY_OPEN = 0, AP_MAC_CMD_POLICY_ALLOW = 1, - AP_MAC_CMD_POLICY_DENY = 2, AP_MAC_CMD_FLUSH = 3, - AP_MAC_CMD_KICKALL = 4 }; - - -/* PRISM2_IOCTL_DOWNLOAD ioctl() dl_cmd: */ -enum { - PRISM2_DOWNLOAD_VOLATILE = 1 /* RAM */, - /* Note! Old versions of prism2_srec have a fatal error in CRC-16 - * calculation, which will corrupt all non-volatile downloads. - * PRISM2_DOWNLOAD_NON_VOLATILE used to be 2, but it is now 3 to - * prevent use of old versions of prism2_srec for non-volatile - * download. */ - PRISM2_DOWNLOAD_NON_VOLATILE = 3 /* FLASH */, - PRISM2_DOWNLOAD_VOLATILE_GENESIS = 4 /* RAM in Genesis mode */, - /* Persistent versions of volatile download commands (keep firmware - * data in memory and automatically re-download after hw_reset */ - PRISM2_DOWNLOAD_VOLATILE_PERSISTENT = 5, - PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT = 6, -}; - -struct prism2_download_param { - u32 dl_cmd; - u32 start_addr; - u32 num_areas; - struct prism2_download_area { - u32 addr; /* wlan card address */ - u32 len; - void __user *ptr; /* pointer to data in user space */ - } data[0]; -}; - -#define PRISM2_MAX_DOWNLOAD_AREA_LEN 131072 -#define PRISM2_MAX_DOWNLOAD_LEN 262144 - - -/* PRISM2_IOCTL_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_HOSTAPD_FLUSH = 1, - PRISM2_HOSTAPD_ADD_STA = 2, - PRISM2_HOSTAPD_REMOVE_STA = 3, - PRISM2_HOSTAPD_GET_INFO_STA = 4, - /* REMOVED: PRISM2_HOSTAPD_RESET_TXEXC_STA = 5, */ - PRISM2_SET_ENCRYPTION = 6, - PRISM2_GET_ENCRYPTION = 7, - PRISM2_HOSTAPD_SET_FLAGS_STA = 8, - PRISM2_HOSTAPD_GET_RID = 9, - PRISM2_HOSTAPD_SET_RID = 10, - PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR = 11, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, - PRISM2_HOSTAPD_STA_CLEAR_STATS = 15, -}; - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_RID_HDR_LEN \ -offsetof(struct prism2_hostapd_param, u.rid.data) -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ -offsetof(struct prism2_hostapd_param, u.generic_elem.data) - -/* Maximum length for algorithm names (-1 for nul termination) used in ioctl() - */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u16 aid; - u16 capability; - u8 tx_supp_rates; - } add_sta; - struct { - u32 inactive_sec; - } get_info_sta; - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u32 flags_and; - u32 flags_or; - } set_flags_sta; - struct { - u16 rid; - u16 len; - u8 data[0]; - } rid; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - -#define HOSTAP_CRYPT_FLAG_SET_TX_KEY BIT(0) -#define HOSTAP_CRYPT_FLAG_PERMANENT BIT(1) - -#define HOSTAP_CRYPT_ERR_UNKNOWN_ALG 2 -#define HOSTAP_CRYPT_ERR_UNKNOWN_ADDR 3 -#define HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED 4 -#define HOSTAP_CRYPT_ERR_KEY_SET_FAILED 5 -#define HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED 6 -#define HOSTAP_CRYPT_ERR_CARD_CONF_FAILED 7 - - -#endif /* HOSTAP_COMMON_H */ diff --git a/drivers/net/wireless/hostap/hostap_config.h b/drivers/net/wireless/hostap/hostap_config.h deleted file mode 100644 index 30acd39d76a2..000000000000 --- a/drivers/net/wireless/hostap/hostap_config.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef HOSTAP_CONFIG_H -#define HOSTAP_CONFIG_H - -/* In the previous versions of Host AP driver, support for user space version - * of IEEE 802.11 management (hostapd) used to be disabled in the default - * configuration. From now on, support for hostapd is always included and it is - * possible to disable kernel driver version of IEEE 802.11 management with a - * separate define, PRISM2_NO_KERNEL_IEEE80211_MGMT. */ -/* #define PRISM2_NO_KERNEL_IEEE80211_MGMT */ - -/* Maximum number of events handler per one interrupt */ -#define PRISM2_MAX_INTERRUPT_EVENTS 20 - -/* Include code for downloading firmware images into volatile RAM. */ -#define PRISM2_DOWNLOAD_SUPPORT - -/* Allow kernel configuration to enable download support. */ -#if !defined(PRISM2_DOWNLOAD_SUPPORT) && defined(CONFIG_HOSTAP_FIRMWARE) -#define PRISM2_DOWNLOAD_SUPPORT -#endif - -/* Allow kernel configuration to enable non-volatile download support. */ -#ifdef CONFIG_HOSTAP_FIRMWARE_NVRAM -#define PRISM2_NON_VOLATILE_DOWNLOAD -#endif - -/* Save low-level I/O for debugging. This should not be enabled in normal use. - */ -/* #define PRISM2_IO_DEBUG */ - -/* Following defines can be used to remove unneeded parts of the driver, e.g., - * to limit the size of the kernel module. Definitions can be added here in - * hostap_config.h or they can be added to make command with EXTRA_CFLAGS, - * e.g., - * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"' - */ - -/* Do not include debug messages into the driver */ -/* #define PRISM2_NO_DEBUG */ - -/* Do not include /proc/net/prism2/wlan#/{registers,debug} */ -/* #define PRISM2_NO_PROCFS_DEBUG */ - -/* Do not include station functionality (i.e., allow only Master (Host AP) mode - */ -/* #define PRISM2_NO_STATION_MODES */ - -#endif /* HOSTAP_CONFIG_H */ diff --git a/drivers/net/wireless/hostap/hostap_cs.c b/drivers/net/wireless/hostap/hostap_cs.c deleted file mode 100644 index b4ff1dc1d72d..000000000000 --- a/drivers/net/wireless/hostap/hostap_cs.c +++ /dev/null @@ -1,913 +0,0 @@ -#define PRISM2_PCCARD - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include - -#include "hostap_wlan.h" - - -static dev_info_t dev_info = "hostap_cs"; - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " - "cards (PC Card)."); -MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PC Card)"); -MODULE_LICENSE("GPL"); - - -static int ignore_cis_vcc; -module_param(ignore_cis_vcc, int, 0444); -MODULE_PARM_DESC(ignore_cis_vcc, "Ignore broken CIS VCC entry"); - - -/* struct local_info::hw_priv */ -struct hostap_cs_priv { - dev_node_t node; - struct pcmcia_device *link; - int sandisk_connectplus; -}; - - -#ifdef PRISM2_IO_DEBUG - -static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); - outb(v, dev->base_addr + a); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - u8 v; - - iface = netdev_priv(dev); - local = iface->local; - spin_lock_irqsave(&local->lock, flags); - v = inb(dev->base_addr + a); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); - spin_unlock_irqrestore(&local->lock, flags); - return v; -} - -static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); - outw(v, dev->base_addr + a); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - u16 v; - - iface = netdev_priv(dev); - local = iface->local; - spin_lock_irqsave(&local->lock, flags); - v = inw(dev->base_addr + a); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); - spin_unlock_irqrestore(&local->lock, flags); - return v; -} - -static inline void hfa384x_outsw_debug(struct net_device *dev, int a, - u8 *buf, int wc) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc); - outsw(dev->base_addr + a, buf, wc); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline void hfa384x_insw_debug(struct net_device *dev, int a, - u8 *buf, int wc) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc); - insw(dev->base_addr + a, buf, wc); - spin_unlock_irqrestore(&local->lock, flags); -} - -#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) -#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) -#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) -#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) -#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc)) -#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc)) - -#else /* PRISM2_IO_DEBUG */ - -#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a)) -#define HFA384X_INB(a) inb(dev->base_addr + (a)) -#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a)) -#define HFA384X_INW(a) inw(dev->base_addr + (a)) -#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc) -#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc) - -#endif /* PRISM2_IO_DEBUG */ - - -static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, - int len) -{ - u16 d_off; - u16 *pos; - - d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; - pos = (u16 *) buf; - - if (len / 2) - HFA384X_INSW(d_off, buf, len / 2); - pos += len / 2; - - if (len & 1) - *((char *) pos) = HFA384X_INB(d_off); - - return 0; -} - - -static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) -{ - u16 d_off; - u16 *pos; - - d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; - pos = (u16 *) buf; - - if (len / 2) - HFA384X_OUTSW(d_off, buf, len / 2); - pos += len / 2; - - if (len & 1) - HFA384X_OUTB(*((char *) pos), d_off); - - return 0; -} - - -/* FIX: This might change at some point.. */ -#include "hostap_hw.c" - - - -static void prism2_detach(struct pcmcia_device *p_dev); -static void prism2_release(u_long arg); -static int prism2_config(struct pcmcia_device *link); - - -static int prism2_pccard_card_present(local_info_t *local) -{ - struct hostap_cs_priv *hw_priv = local->hw_priv; - if (hw_priv != NULL && hw_priv->link != NULL && pcmcia_dev_present(hw_priv->link)) - return 1; - return 0; -} - - -/* - * SanDisk CompactFlash WLAN Flashcard - Product Manual v1.0 - * Document No. 20-10-00058, January 2004 - * http://www.sandisk.com/pdf/industrial/ProdManualCFWLANv1.0.pdf - */ -#define SANDISK_WLAN_ACTIVATION_OFF 0x40 -#define SANDISK_HCR_OFF 0x42 - - -static void sandisk_set_iobase(local_info_t *local) -{ - int res; - conf_reg_t reg; - struct hostap_cs_priv *hw_priv = local->hw_priv; - - reg.Function = 0; - reg.Action = CS_WRITE; - reg.Offset = 0x10; /* 0x3f0 IO base 1 */ - reg.Value = hw_priv->link->io.BasePort1 & 0x00ff; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 0 -" - " res=%d\n", res); - } - udelay(10); - - reg.Function = 0; - reg.Action = CS_WRITE; - reg.Offset = 0x12; /* 0x3f2 IO base 2 */ - reg.Value = (hw_priv->link->io.BasePort1 & 0xff00) >> 8; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "Prism3 SanDisk - failed to set I/O base 1 -" - " res=%d\n", res); - } -} - - -static void sandisk_write_hcr(local_info_t *local, int hcr) -{ - struct net_device *dev = local->dev; - int i; - - HFA384X_OUTB(0x80, SANDISK_WLAN_ACTIVATION_OFF); - udelay(50); - for (i = 0; i < 10; i++) { - HFA384X_OUTB(hcr, SANDISK_HCR_OFF); - } - udelay(55); - HFA384X_OUTB(0x45, SANDISK_WLAN_ACTIVATION_OFF); -} - - -static int sandisk_enable_wireless(struct net_device *dev) -{ - int res, ret = 0; - conf_reg_t reg; - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - tuple_t tuple; - cisparse_t *parse = NULL; - u_char buf[64]; - struct hostap_cs_priv *hw_priv = local->hw_priv; - - if (hw_priv->link->io.NumPorts1 < 0x42) { - /* Not enough ports to be SanDisk multi-function card */ - ret = -ENODEV; - goto done; - } - - parse = kmalloc(sizeof(cisparse_t), GFP_KERNEL); - if (parse == NULL) { - ret = -ENOMEM; - goto done; - } - - tuple.Attributes = TUPLE_RETURN_COMMON; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - - if (hw_priv->link->manf_id != 0xd601 || hw_priv->link->card_id != 0x0101) { - /* No SanDisk manfid found */ - ret = -ENODEV; - goto done; - } - - tuple.DesiredTuple = CISTPL_LONGLINK_MFC; - if (pcmcia_get_first_tuple(hw_priv->link, &tuple) || - pcmcia_get_tuple_data(hw_priv->link, &tuple) || - pcmcia_parse_tuple(&tuple, parse) || - parse->longlink_mfc.nfn < 2) { - /* No multi-function links found */ - ret = -ENODEV; - goto done; - } - - printk(KERN_DEBUG "%s: Multi-function SanDisk ConnectPlus detected" - " - using vendor-specific initialization\n", dev->name); - hw_priv->sandisk_connectplus = 1; - - reg.Function = 0; - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; - reg.Value = COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", - dev->name, res); - goto done; - } - mdelay(5); - - reg.Function = 0; - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; - /* - * Do not enable interrupts here to avoid some bogus events. Interrupts - * will be enabled during the first cor_sreset call. - */ - reg.Value = COR_LEVEL_REQ | 0x8 | COR_ADDR_DECODE | COR_FUNC_ENA; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "%s: SanDisk - COR sreset failed (%d)\n", - dev->name, res); - goto done; - } - mdelay(5); - - sandisk_set_iobase(local); - - HFA384X_OUTB(0xc5, SANDISK_WLAN_ACTIVATION_OFF); - udelay(10); - HFA384X_OUTB(0x4b, SANDISK_WLAN_ACTIVATION_OFF); - udelay(10); - -done: - kfree(parse); - return ret; -} - - -static void prism2_pccard_cor_sreset(local_info_t *local) -{ - int res; - conf_reg_t reg; - struct hostap_cs_priv *hw_priv = local->hw_priv; - - if (!prism2_pccard_card_present(local)) - return; - - reg.Function = 0; - reg.Action = CS_READ; - reg.Offset = CISREG_COR; - reg.Value = 0; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 1 (%d)\n", - res); - return; - } - printk(KERN_DEBUG "prism2_pccard_cor_sreset: original COR %02x\n", - reg.Value); - - reg.Action = CS_WRITE; - reg.Value |= COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 2 (%d)\n", - res); - return; - } - - mdelay(hw_priv->sandisk_connectplus ? 5 : 2); - - reg.Value &= ~COR_SOFT_RESET; - if (hw_priv->sandisk_connectplus) - reg.Value |= COR_IREQ_ENA; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_cor_sreset failed 3 (%d)\n", - res); - return; - } - - mdelay(hw_priv->sandisk_connectplus ? 5 : 2); - - if (hw_priv->sandisk_connectplus) - sandisk_set_iobase(local); -} - - -static void prism2_pccard_genesis_reset(local_info_t *local, int hcr) -{ - int res; - conf_reg_t reg; - int old_cor; - struct hostap_cs_priv *hw_priv = local->hw_priv; - - if (!prism2_pccard_card_present(local)) - return; - - if (hw_priv->sandisk_connectplus) { - sandisk_write_hcr(local, hcr); - return; - } - - reg.Function = 0; - reg.Action = CS_READ; - reg.Offset = CISREG_COR; - reg.Value = 0; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 1 " - "(%d)\n", res); - return; - } - printk(KERN_DEBUG "prism2_pccard_genesis_sreset: original COR %02x\n", - reg.Value); - old_cor = reg.Value; - - reg.Action = CS_WRITE; - reg.Value |= COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 2 " - "(%d)\n", res); - return; - } - - mdelay(10); - - /* Setup Genesis mode */ - reg.Action = CS_WRITE; - reg.Value = hcr; - reg.Offset = CISREG_CCSR; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 3 " - "(%d)\n", res); - return; - } - mdelay(10); - - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; - reg.Value = old_cor & ~COR_SOFT_RESET; - res = pcmcia_access_configuration_register(hw_priv->link, - ®); - if (res != 0) { - printk(KERN_DEBUG "prism2_pccard_genesis_sreset failed 4 " - "(%d)\n", res); - return; - } - - mdelay(10); -} - - -static struct prism2_helper_functions prism2_pccard_funcs = -{ - .card_present = prism2_pccard_card_present, - .cor_sreset = prism2_pccard_cor_sreset, - .genesis_reset = prism2_pccard_genesis_reset, - .hw_type = HOSTAP_HW_PCCARD, -}; - - -/* allocate local data and register with CardServices - * initialize dev_link structure, but do not configure the card yet */ -static int hostap_cs_probe(struct pcmcia_device *p_dev) -{ - int ret; - - PDEBUG(DEBUG_HW, "%s: setting Vcc=33 (constant)\n", dev_info); - p_dev->conf.IntType = INT_MEMORY_AND_IO; - - ret = prism2_config(p_dev); - if (ret) { - PDEBUG(DEBUG_EXTRA, "prism2_config() failed\n"); - } - - return ret; -} - - -static void prism2_detach(struct pcmcia_device *link) -{ - PDEBUG(DEBUG_FLOW, "prism2_detach\n"); - - prism2_release((u_long)link); - - /* release net devices */ - if (link->priv) { - struct hostap_cs_priv *hw_priv; - struct net_device *dev; - struct hostap_interface *iface; - dev = link->priv; - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - prism2_free_local_data(dev); - kfree(hw_priv); - } -} - - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - - -/* run after a CARD_INSERTION event is received to configure the PCMCIA - * socket and make the device available to the system */ - -static int prism2_config_check(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) -{ - if (cfg->index == 0) - return -ENODEV; - - PDEBUG(DEBUG_EXTRA, "Checking CFTABLE_ENTRY 0x%02X " - "(default 0x%02X)\n", cfg->index, dflt->index); - - /* Does this card need audio output? */ - if (cfg->flags & CISTPL_CFTABLE_AUDIO) { - p_dev->conf.Attributes |= CONF_ENABLE_SPKR; - p_dev->conf.Status = CCSR_AUDIO_ENA; - } - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / - 10000 && !ignore_cis_vcc) { - PDEBUG(DEBUG_EXTRA, " Vcc mismatch - skipping" - " this entry\n"); - return -ENODEV; - } - } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / - 10000 && !ignore_cis_vcc) { - PDEBUG(DEBUG_EXTRA, " Vcc (default) mismatch " - "- skipping this entry\n"); - return -ENODEV; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; - else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1 || dflt->irq.IRQInfo1) - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - else if (!(p_dev->conf.Attributes & CONF_ENABLE_IRQ)) { - /* At least Compaq WL200 does not have IRQInfo1 set, - * but it does not work without interrupts.. */ - printk(KERN_WARNING "Config has no IRQ info, but trying to " - "enable IRQ anyway..\n"); - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - } - - /* IO window settings */ - PDEBUG(DEBUG_EXTRA, "IO window settings: cfg->io.nwin=%d " - "dflt->io.nwin=%d\n", - cfg->io.nwin, dflt->io.nwin); - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - PDEBUG(DEBUG_EXTRA, "io->flags = 0x%04X, " - "io.base=0x%04x, len=%d\n", io->flags, - io->win[0].base, io->win[0].len); - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & - CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; - } - } - - /* This reserves IO space but doesn't actually enable it */ - return pcmcia_request_io(p_dev, &p_dev->io); -} - -static int prism2_config(struct pcmcia_device *link) -{ - struct net_device *dev; - struct hostap_interface *iface; - local_info_t *local; - int ret = 1; - int last_fn, last_ret; - struct hostap_cs_priv *hw_priv; - unsigned long flags; - - PDEBUG(DEBUG_FLOW, "prism2_config()\n"); - - hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); - if (hw_priv == NULL) { - ret = -ENOMEM; - goto failed; - } - - /* Look for an appropriate configuration table entry in the CIS */ - last_ret = pcmcia_loop_config(link, prism2_config_check, NULL); - if (last_ret) { - if (!ignore_cis_vcc) - printk(KERN_ERR "GetNextTuple(): No matching " - "CIS configuration. Maybe you need the " - "ignore_cis_vcc=1 parameter.\n"); - cs_error(link, RequestIO, last_ret); - goto failed; - } - - /* Need to allocate net_device before requesting IRQ handler */ - dev = prism2_init_local_data(&prism2_pccard_funcs, 0, - &handle_to_dev(link)); - if (dev == NULL) - goto failed; - link->priv = dev; - - iface = netdev_priv(dev); - local = iface->local; - local->hw_priv = hw_priv; - hw_priv->link = link; - strcpy(hw_priv->node.dev_name, dev->name); - link->dev_node = &hw_priv->node; - - /* - * Make sure the IRQ handler cannot proceed until at least - * dev->base_addr is initialized. - */ - spin_lock_irqsave(&local->irq_init_lock, flags); - - /* - * Allocate an interrupt line. Note that this does not assign a - * handler to the interrupt, unless the 'Handler' member of the - * irq structure is initialized. - */ - if (link->conf.Attributes & CONF_ENABLE_IRQ) { - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | - IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = prism2_interrupt; - link->irq.Instance = dev; - CS_CHECK(RequestIRQ, - pcmcia_request_irq(link, &link->irq)); - } - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping, and putting the - * card and host interface into "Memory and IO" mode. - */ - CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link, &link->conf)); - - dev->irq = link->irq.AssignedIRQ; - dev->base_addr = link->io.BasePort1; - - spin_unlock_irqrestore(&local->irq_init_lock, flags); - - /* Finally, report what we've done */ - printk(KERN_INFO "%s: index 0x%02x: ", - dev_info, link->conf.ConfigIndex); - if (link->conf.Vpp) - printk(", Vpp %d.%d", link->conf.Vpp / 10, - link->conf.Vpp % 10); - if (link->conf.Attributes & CONF_ENABLE_IRQ) - printk(", irq %d", link->irq.AssignedIRQ); - if (link->io.NumPorts1) - printk(", io 0x%04x-0x%04x", link->io.BasePort1, - link->io.BasePort1+link->io.NumPorts1-1); - if (link->io.NumPorts2) - printk(" & 0x%04x-0x%04x", link->io.BasePort2, - link->io.BasePort2+link->io.NumPorts2-1); - printk("\n"); - - local->shutdown = 0; - - sandisk_enable_wireless(dev); - - ret = prism2_hw_config(dev, 1); - if (!ret) { - ret = hostap_hw_ready(dev); - if (ret == 0 && local->ddev) - strcpy(hw_priv->node.dev_name, local->ddev->name); - } - return ret; - - cs_failed: - spin_unlock_irqrestore(&local->irq_init_lock, flags); - cs_error(link, last_fn, last_ret); - - failed: - kfree(hw_priv); - prism2_release((u_long)link); - return ret; -} - - -static void prism2_release(u_long arg) -{ - struct pcmcia_device *link = (struct pcmcia_device *)arg; - - PDEBUG(DEBUG_FLOW, "prism2_release\n"); - - if (link->priv) { - struct net_device *dev = link->priv; - struct hostap_interface *iface; - - iface = netdev_priv(dev); - prism2_hw_shutdown(dev, 0); - iface->local->shutdown = 1; - } - - pcmcia_disable_device(link); - PDEBUG(DEBUG_FLOW, "release - done\n"); -} - -static int hostap_cs_suspend(struct pcmcia_device *link) -{ - struct net_device *dev = (struct net_device *) link->priv; - int dev_open = 0; - struct hostap_interface *iface = NULL; - - if (!dev) - return -ENODEV; - - iface = netdev_priv(dev); - - PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_SUSPEND\n", dev_info); - if (iface && iface->local) - dev_open = iface->local->num_dev_open > 0; - if (dev_open) { - netif_stop_queue(dev); - netif_device_detach(dev); - } - prism2_suspend(dev); - - return 0; -} - -static int hostap_cs_resume(struct pcmcia_device *link) -{ - struct net_device *dev = (struct net_device *) link->priv; - int dev_open = 0; - struct hostap_interface *iface = NULL; - - if (!dev) - return -ENODEV; - - iface = netdev_priv(dev); - - PDEBUG(DEBUG_EXTRA, "%s: CS_EVENT_PM_RESUME\n", dev_info); - - if (iface && iface->local) - dev_open = iface->local->num_dev_open > 0; - - prism2_hw_shutdown(dev, 1); - prism2_hw_config(dev, dev_open ? 0 : 1); - if (dev_open) { - netif_device_attach(dev); - netif_start_queue(dev); - } - - return 0; -} - -static struct pcmcia_device_id hostap_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), - PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), - PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x3301), - PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x030b), - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0x02d2, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x0001), - PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), -/* PCMCIA_DEVICE_MANF_CARD(0xc00f, 0x0000), conflict with pcnet_cs */ - PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0010), - PCMCIA_DEVICE_MANF_CARD(0x0126, 0x0002), - PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0xd601, 0x0005, "ADLINK 345 CF", - 0x2d858104), - PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "INTERSIL", - 0x74c5e40d), - PCMCIA_DEVICE_MANF_CARD_PROD_ID1(0x0156, 0x0002, "Intersil", - 0x4b801a17), - PCMCIA_MFC_DEVICE_PROD_ID12(0, "SanDisk", "ConnectPlus", - 0x7a954bd9, 0x74be00c6), - PCMCIA_DEVICE_PROD_ID123( - "Intersil", "PRISM 2_5 PCMCIA ADAPTER", "ISL37300P", - 0x4b801a17, 0x6345a0bf, 0xc9049a39), - /* D-Link DWL-650 Rev. P1; manfid 0x000b, 0x7110 */ - PCMCIA_DEVICE_PROD_ID123( - "D-Link", "DWL-650 Wireless PC Card RevP", "ISL37101P-10", - 0x1a424a1c, 0x6ea57632, 0xdd97a26b), - PCMCIA_DEVICE_PROD_ID123( - "Addtron", "AWP-100 Wireless PCMCIA", "Version 01.02", - 0xe6ec52ce, 0x08649af2, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID123( - "D", "Link DWL-650 11Mbps WLAN Card", "Version 01.02", - 0x71b18589, 0xb6f1b0ab, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID123( - "Instant Wireless ", " Network PC CARD", "Version 01.02", - 0x11d901af, 0x6e9bd926, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID123( - "SMC", "SMC2632W", "Version 01.02", - 0xc4f8b18b, 0x474a1f2a, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", - 0x2decece3, 0x82067c18), - PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", - 0x54f7c49c, 0x15a75e5b), - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", - 0x74c5e40d, 0xdb472a18), - PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", - 0x0733cc81, 0x0c52f395), - PCMCIA_DEVICE_PROD_ID12( - "ZoomAir 11Mbps High", "Rate wireless Networking", - 0x273fe3db, 0x32a1eaee), - PCMCIA_DEVICE_PROD_ID123( - "Pretec", "CompactWLAN Card 802.11b", "2.5", - 0x1cadd3e5, 0xe697636c, 0x7a5bfcf1), - PCMCIA_DEVICE_PROD_ID123( - "U.S. Robotics", "IEEE 802.11b PC-CARD", "Version 01.02", - 0xc7b8df9d, 0x1700d087, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID123( - "Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", - "Ver. 1.00", - 0x5cd01705, 0x4271660f, 0x9d08ee12), - PCMCIA_DEVICE_PROD_ID123( - "corega", "WL PCCL-11", "ISL37300P", - 0xa21501a, 0x59868926, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID123( - "The Linksys Group, Inc.", "Wireless Network CF Card", "ISL37300P", - 0xa5f472c2, 0x9c05598d, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID123( - "Wireless LAN" , "11Mbps PC Card", "Version 01.02", - 0x4b8870ff, 0x70e946d1, 0x4b74baa0), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, hostap_cs_ids); - - -static struct pcmcia_driver hostap_driver = { - .drv = { - .name = "hostap_cs", - }, - .probe = hostap_cs_probe, - .remove = prism2_detach, - .owner = THIS_MODULE, - .id_table = hostap_cs_ids, - .suspend = hostap_cs_suspend, - .resume = hostap_cs_resume, -}; - -static int __init init_prism2_pccard(void) -{ - return pcmcia_register_driver(&hostap_driver); -} - -static void __exit exit_prism2_pccard(void) -{ - pcmcia_unregister_driver(&hostap_driver); -} - - -module_init(init_prism2_pccard); -module_exit(exit_prism2_pccard); diff --git a/drivers/net/wireless/hostap/hostap_download.c b/drivers/net/wireless/hostap/hostap_download.c deleted file mode 100644 index 89d3849abfe0..000000000000 --- a/drivers/net/wireless/hostap/hostap_download.c +++ /dev/null @@ -1,762 +0,0 @@ -static int prism2_enable_aux_port(struct net_device *dev, int enable) -{ - u16 val, reg; - int i, tries; - unsigned long flags; - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->no_pri) { - if (enable) { - PDEBUG(DEBUG_EXTRA2, "%s: no PRI f/w - assuming Aux " - "port is already enabled\n", dev->name); - } - return 0; - } - - spin_lock_irqsave(&local->cmdlock, flags); - - /* wait until busy bit is clear */ - tries = HFA384X_CMD_BUSY_TIMEOUT; - while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { - tries--; - udelay(1); - } - if (tries == 0) { - reg = HFA384X_INW(HFA384X_CMD_OFF); - spin_unlock_irqrestore(&local->cmdlock, flags); - printk("%s: prism2_enable_aux_port - timeout - reg=0x%04x\n", - dev->name, reg); - return -ETIMEDOUT; - } - - val = HFA384X_INW(HFA384X_CONTROL_OFF); - - if (enable) { - HFA384X_OUTW(HFA384X_AUX_MAGIC0, HFA384X_PARAM0_OFF); - HFA384X_OUTW(HFA384X_AUX_MAGIC1, HFA384X_PARAM1_OFF); - HFA384X_OUTW(HFA384X_AUX_MAGIC2, HFA384X_PARAM2_OFF); - - if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_DISABLED) - printk("prism2_enable_aux_port: was not disabled!?\n"); - val &= ~HFA384X_AUX_PORT_MASK; - val |= HFA384X_AUX_PORT_ENABLE; - } else { - HFA384X_OUTW(0, HFA384X_PARAM0_OFF); - HFA384X_OUTW(0, HFA384X_PARAM1_OFF); - HFA384X_OUTW(0, HFA384X_PARAM2_OFF); - - if ((val & HFA384X_AUX_PORT_MASK) != HFA384X_AUX_PORT_ENABLED) - printk("prism2_enable_aux_port: was not enabled!?\n"); - val &= ~HFA384X_AUX_PORT_MASK; - val |= HFA384X_AUX_PORT_DISABLE; - } - HFA384X_OUTW(val, HFA384X_CONTROL_OFF); - - udelay(5); - - i = 10000; - while (i > 0) { - val = HFA384X_INW(HFA384X_CONTROL_OFF); - val &= HFA384X_AUX_PORT_MASK; - - if ((enable && val == HFA384X_AUX_PORT_ENABLED) || - (!enable && val == HFA384X_AUX_PORT_DISABLED)) - break; - - udelay(10); - i--; - } - - spin_unlock_irqrestore(&local->cmdlock, flags); - - if (i == 0) { - printk("prism2_enable_aux_port(%d) timed out\n", - enable); - return -ETIMEDOUT; - } - - return 0; -} - - -static int hfa384x_from_aux(struct net_device *dev, unsigned int addr, int len, - void *buf) -{ - u16 page, offset; - if (addr & 1 || len & 1) - return -1; - - page = addr >> 7; - offset = addr & 0x7f; - - HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF); - HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF); - - udelay(5); - -#ifdef PRISM2_PCI - { - __le16 *pos = (__le16 *) buf; - while (len > 0) { - *pos++ = HFA384X_INW_DATA(HFA384X_AUXDATA_OFF); - len -= 2; - } - } -#else /* PRISM2_PCI */ - HFA384X_INSW(HFA384X_AUXDATA_OFF, buf, len / 2); -#endif /* PRISM2_PCI */ - - return 0; -} - - -static int hfa384x_to_aux(struct net_device *dev, unsigned int addr, int len, - void *buf) -{ - u16 page, offset; - if (addr & 1 || len & 1) - return -1; - - page = addr >> 7; - offset = addr & 0x7f; - - HFA384X_OUTW(page, HFA384X_AUXPAGE_OFF); - HFA384X_OUTW(offset, HFA384X_AUXOFFSET_OFF); - - udelay(5); - -#ifdef PRISM2_PCI - { - __le16 *pos = (__le16 *) buf; - while (len > 0) { - HFA384X_OUTW_DATA(*pos++, HFA384X_AUXDATA_OFF); - len -= 2; - } - } -#else /* PRISM2_PCI */ - HFA384X_OUTSW(HFA384X_AUXDATA_OFF, buf, len / 2); -#endif /* PRISM2_PCI */ - - return 0; -} - - -static int prism2_pda_ok(u8 *buf) -{ - __le16 *pda = (__le16 *) buf; - int pos; - u16 len, pdr; - - if (buf[0] == 0xff && buf[1] == 0x00 && buf[2] == 0xff && - buf[3] == 0x00) - return 0; - - pos = 0; - while (pos + 1 < PRISM2_PDA_SIZE / 2) { - len = le16_to_cpu(pda[pos]); - pdr = le16_to_cpu(pda[pos + 1]); - if (len == 0 || pos + len > PRISM2_PDA_SIZE / 2) - return 0; - - if (pdr == 0x0000 && len == 2) { - /* PDA end found */ - return 1; - } - - pos += len + 1; - } - - return 0; -} - - -static int prism2_download_aux_dump(struct net_device *dev, - unsigned int addr, int len, u8 *buf) -{ - int res; - - prism2_enable_aux_port(dev, 1); - res = hfa384x_from_aux(dev, addr, len, buf); - prism2_enable_aux_port(dev, 0); - if (res) - return -1; - - return 0; -} - - -static u8 * prism2_read_pda(struct net_device *dev) -{ - u8 *buf; - int res, i, found = 0; -#define NUM_PDA_ADDRS 4 - unsigned int pda_addr[NUM_PDA_ADDRS] = { - 0x7f0000 /* others than HFA3841 */, - 0x3f0000 /* HFA3841 */, - 0x390000 /* apparently used in older cards */, - 0x7f0002 /* Intel PRO/Wireless 2011B (PCI) */, - }; - - buf = kmalloc(PRISM2_PDA_SIZE, GFP_KERNEL); - if (buf == NULL) - return NULL; - - /* Note: wlan card should be in initial state (just after init cmd) - * and no other operations should be performed concurrently. */ - - prism2_enable_aux_port(dev, 1); - - for (i = 0; i < NUM_PDA_ADDRS; i++) { - PDEBUG(DEBUG_EXTRA2, "%s: trying to read PDA from 0x%08x", - dev->name, pda_addr[i]); - res = hfa384x_from_aux(dev, pda_addr[i], PRISM2_PDA_SIZE, buf); - if (res) - continue; - if (res == 0 && prism2_pda_ok(buf)) { - PDEBUG2(DEBUG_EXTRA2, ": OK\n"); - found = 1; - break; - } else { - PDEBUG2(DEBUG_EXTRA2, ": failed\n"); - } - } - - prism2_enable_aux_port(dev, 0); - - if (!found) { - printk(KERN_DEBUG "%s: valid PDA not found\n", dev->name); - kfree(buf); - buf = NULL; - } - - return buf; -} - - -static int prism2_download_volatile(local_info_t *local, - struct prism2_download_data *param) -{ - struct net_device *dev = local->dev; - int ret = 0, i; - u16 param0, param1; - - if (local->hw_downloading) { - printk(KERN_WARNING "%s: Already downloading - aborting new " - "request\n", dev->name); - return -1; - } - - local->hw_downloading = 1; - if (local->pri_only) { - hfa384x_disable_interrupts(dev); - } else { - prism2_hw_shutdown(dev, 0); - - if (prism2_hw_init(dev, 0)) { - printk(KERN_WARNING "%s: Could not initialize card for" - " download\n", dev->name); - ret = -1; - goto out; - } - } - - if (prism2_enable_aux_port(dev, 1)) { - printk(KERN_WARNING "%s: Could not enable AUX port\n", - dev->name); - ret = -1; - goto out; - } - - param0 = param->start_addr & 0xffff; - param1 = param->start_addr >> 16; - - HFA384X_OUTW(0, HFA384X_PARAM2_OFF); - HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); - if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | - (HFA384X_PROGMODE_ENABLE_VOLATILE << 8), - param0)) { - printk(KERN_WARNING "%s: Download command execution failed\n", - dev->name); - ret = -1; - goto out; - } - - for (i = 0; i < param->num_areas; i++) { - PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n", - dev->name, param->data[i].len, param->data[i].addr); - if (hfa384x_to_aux(dev, param->data[i].addr, - param->data[i].len, param->data[i].data)) { - printk(KERN_WARNING "%s: RAM download at 0x%08x " - "(len=%d) failed\n", dev->name, - param->data[i].addr, param->data[i].len); - ret = -1; - goto out; - } - } - - HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); - HFA384X_OUTW(0, HFA384X_PARAM2_OFF); - if (hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_DOWNLOAD | - (HFA384X_PROGMODE_DISABLE << 8), param0)) { - printk(KERN_WARNING "%s: Download command execution failed\n", - dev->name); - ret = -1; - goto out; - } - /* ProgMode disable causes the hardware to restart itself from the - * given starting address. Give hw some time and ACK command just in - * case restart did not happen. */ - mdelay(5); - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); - - if (prism2_enable_aux_port(dev, 0)) { - printk(KERN_DEBUG "%s: Disabling AUX port failed\n", - dev->name); - /* continue anyway.. restart should have taken care of this */ - } - - mdelay(5); - local->hw_downloading = 0; - if (prism2_hw_config(dev, 2)) { - printk(KERN_WARNING "%s: Card configuration after RAM " - "download failed\n", dev->name); - ret = -1; - goto out; - } - - out: - local->hw_downloading = 0; - return ret; -} - - -static int prism2_enable_genesis(local_info_t *local, int hcr) -{ - struct net_device *dev = local->dev; - u8 initseq[4] = { 0x00, 0xe1, 0xa1, 0xff }; - u8 readbuf[4]; - - printk(KERN_DEBUG "%s: test Genesis mode with HCR 0x%02x\n", - dev->name, hcr); - local->func->cor_sreset(local); - hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq); - local->func->genesis_reset(local, hcr); - - /* Readback test */ - hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf); - hfa384x_to_aux(dev, 0x7e0038, sizeof(initseq), initseq); - hfa384x_from_aux(dev, 0x7e0038, sizeof(readbuf), readbuf); - - if (memcmp(initseq, readbuf, sizeof(initseq)) == 0) { - printk(KERN_DEBUG "Readback test succeeded, HCR 0x%02x\n", - hcr); - return 0; - } else { - printk(KERN_DEBUG "Readback test failed, HCR 0x%02x " - "write %02x %02x %02x %02x read %02x %02x %02x %02x\n", - hcr, initseq[0], initseq[1], initseq[2], initseq[3], - readbuf[0], readbuf[1], readbuf[2], readbuf[3]); - return 1; - } -} - - -static int prism2_get_ram_size(local_info_t *local) -{ - int ret; - - /* Try to enable genesis mode; 0x1F for x8 SRAM or 0x0F for x16 SRAM */ - if (prism2_enable_genesis(local, 0x1f) == 0) - ret = 8; - else if (prism2_enable_genesis(local, 0x0f) == 0) - ret = 16; - else - ret = -1; - - /* Disable genesis mode */ - local->func->genesis_reset(local, ret == 16 ? 0x07 : 0x17); - - return ret; -} - - -static int prism2_download_genesis(local_info_t *local, - struct prism2_download_data *param) -{ - struct net_device *dev = local->dev; - int ram16 = 0, i; - int ret = 0; - - if (local->hw_downloading) { - printk(KERN_WARNING "%s: Already downloading - aborting new " - "request\n", dev->name); - return -EBUSY; - } - - if (!local->func->genesis_reset || !local->func->cor_sreset) { - printk(KERN_INFO "%s: Genesis mode downloading not supported " - "with this hwmodel\n", dev->name); - return -EOPNOTSUPP; - } - - local->hw_downloading = 1; - - if (prism2_enable_aux_port(dev, 1)) { - printk(KERN_DEBUG "%s: failed to enable AUX port\n", - dev->name); - ret = -EIO; - goto out; - } - - if (local->sram_type == -1) { - /* 0x1F for x8 SRAM or 0x0F for x16 SRAM */ - if (prism2_enable_genesis(local, 0x1f) == 0) { - ram16 = 0; - PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x8 " - "SRAM\n", dev->name); - } else if (prism2_enable_genesis(local, 0x0f) == 0) { - ram16 = 1; - PDEBUG(DEBUG_EXTRA2, "%s: Genesis mode OK using x16 " - "SRAM\n", dev->name); - } else { - printk(KERN_DEBUG "%s: Could not initiate genesis " - "mode\n", dev->name); - ret = -EIO; - goto out; - } - } else { - if (prism2_enable_genesis(local, local->sram_type == 8 ? - 0x1f : 0x0f)) { - printk(KERN_DEBUG "%s: Failed to set Genesis " - "mode (sram_type=%d)\n", dev->name, - local->sram_type); - ret = -EIO; - goto out; - } - ram16 = local->sram_type != 8; - } - - for (i = 0; i < param->num_areas; i++) { - PDEBUG(DEBUG_EXTRA2, "%s: Writing %d bytes at 0x%08x\n", - dev->name, param->data[i].len, param->data[i].addr); - if (hfa384x_to_aux(dev, param->data[i].addr, - param->data[i].len, param->data[i].data)) { - printk(KERN_WARNING "%s: RAM download at 0x%08x " - "(len=%d) failed\n", dev->name, - param->data[i].addr, param->data[i].len); - ret = -EIO; - goto out; - } - } - - PDEBUG(DEBUG_EXTRA2, "Disable genesis mode\n"); - local->func->genesis_reset(local, ram16 ? 0x07 : 0x17); - if (prism2_enable_aux_port(dev, 0)) { - printk(KERN_DEBUG "%s: Failed to disable AUX port\n", - dev->name); - } - - mdelay(5); - local->hw_downloading = 0; - - PDEBUG(DEBUG_EXTRA2, "Trying to initialize card\n"); - /* - * Make sure the INIT command does not generate a command completion - * event by disabling interrupts. - */ - hfa384x_disable_interrupts(dev); - if (prism2_hw_init(dev, 1)) { - printk(KERN_DEBUG "%s: Initialization after genesis mode " - "download failed\n", dev->name); - ret = -EIO; - goto out; - } - - PDEBUG(DEBUG_EXTRA2, "Card initialized - running PRI only\n"); - if (prism2_hw_init2(dev, 1)) { - printk(KERN_DEBUG "%s: Initialization(2) after genesis mode " - "download failed\n", dev->name); - ret = -EIO; - goto out; - } - - out: - local->hw_downloading = 0; - return ret; -} - - -#ifdef PRISM2_NON_VOLATILE_DOWNLOAD -/* Note! Non-volatile downloading functionality has not yet been tested - * thoroughly and it may corrupt flash image and effectively kill the card that - * is being updated. You have been warned. */ - -static inline int prism2_download_block(struct net_device *dev, - u32 addr, u8 *data, - u32 bufaddr, int rest_len) -{ - u16 param0, param1; - int block_len; - - block_len = rest_len < 4096 ? rest_len : 4096; - - param0 = addr & 0xffff; - param1 = addr >> 16; - - HFA384X_OUTW(block_len, HFA384X_PARAM2_OFF); - HFA384X_OUTW(param1, HFA384X_PARAM1_OFF); - - if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | - (HFA384X_PROGMODE_ENABLE_NON_VOLATILE << 8), - param0)) { - printk(KERN_WARNING "%s: Flash download command execution " - "failed\n", dev->name); - return -1; - } - - if (hfa384x_to_aux(dev, bufaddr, block_len, data)) { - printk(KERN_WARNING "%s: flash download at 0x%08x " - "(len=%d) failed\n", dev->name, addr, block_len); - return -1; - } - - HFA384X_OUTW(0, HFA384X_PARAM2_OFF); - HFA384X_OUTW(0, HFA384X_PARAM1_OFF); - if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | - (HFA384X_PROGMODE_PROGRAM_NON_VOLATILE << 8), - 0)) { - printk(KERN_WARNING "%s: Flash write command execution " - "failed\n", dev->name); - return -1; - } - - return block_len; -} - - -static int prism2_download_nonvolatile(local_info_t *local, - struct prism2_download_data *dl) -{ - struct net_device *dev = local->dev; - int ret = 0, i; - struct { - __le16 page; - __le16 offset; - __le16 len; - } dlbuffer; - u32 bufaddr; - - if (local->hw_downloading) { - printk(KERN_WARNING "%s: Already downloading - aborting new " - "request\n", dev->name); - return -1; - } - - ret = local->func->get_rid(dev, HFA384X_RID_DOWNLOADBUFFER, - &dlbuffer, 6, 0); - - if (ret < 0) { - printk(KERN_WARNING "%s: Could not read download buffer " - "parameters\n", dev->name); - goto out; - } - - printk(KERN_DEBUG "Download buffer: %d bytes at 0x%04x:0x%04x\n", - le16_to_cpu(dlbuffer.len), - le16_to_cpu(dlbuffer.page), - le16_to_cpu(dlbuffer.offset)); - - bufaddr = (le16_to_cpu(dlbuffer.page) << 7) + le16_to_cpu(dlbuffer.offset); - - local->hw_downloading = 1; - - if (!local->pri_only) { - prism2_hw_shutdown(dev, 0); - - if (prism2_hw_init(dev, 0)) { - printk(KERN_WARNING "%s: Could not initialize card for" - " download\n", dev->name); - ret = -1; - goto out; - } - } - - hfa384x_disable_interrupts(dev); - - if (prism2_enable_aux_port(dev, 1)) { - printk(KERN_WARNING "%s: Could not enable AUX port\n", - dev->name); - ret = -1; - goto out; - } - - printk(KERN_DEBUG "%s: starting flash download\n", dev->name); - for (i = 0; i < dl->num_areas; i++) { - int rest_len = dl->data[i].len; - int data_off = 0; - - while (rest_len > 0) { - int block_len; - - block_len = prism2_download_block( - dev, dl->data[i].addr + data_off, - dl->data[i].data + data_off, bufaddr, - rest_len); - - if (block_len < 0) { - ret = -1; - goto out; - } - - rest_len -= block_len; - data_off += block_len; - } - } - - HFA384X_OUTW(0, HFA384X_PARAM1_OFF); - HFA384X_OUTW(0, HFA384X_PARAM2_OFF); - if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_DOWNLOAD | - (HFA384X_PROGMODE_DISABLE << 8), 0)) { - printk(KERN_WARNING "%s: Download command execution failed\n", - dev->name); - ret = -1; - goto out; - } - - if (prism2_enable_aux_port(dev, 0)) { - printk(KERN_DEBUG "%s: Disabling AUX port failed\n", - dev->name); - /* continue anyway.. restart should have taken care of this */ - } - - mdelay(5); - - local->func->hw_reset(dev); - local->hw_downloading = 0; - if (prism2_hw_config(dev, 2)) { - printk(KERN_WARNING "%s: Card configuration after flash " - "download failed\n", dev->name); - ret = -1; - } else { - printk(KERN_INFO "%s: Card initialized successfully after " - "flash download\n", dev->name); - } - - out: - local->hw_downloading = 0; - return ret; -} -#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */ - - -static void prism2_download_free_data(struct prism2_download_data *dl) -{ - int i; - - if (dl == NULL) - return; - - for (i = 0; i < dl->num_areas; i++) - kfree(dl->data[i].data); - kfree(dl); -} - - -static int prism2_download(local_info_t *local, - struct prism2_download_param *param) -{ - int ret = 0; - int i; - u32 total_len = 0; - struct prism2_download_data *dl = NULL; - - printk(KERN_DEBUG "prism2_download: dl_cmd=%d start_addr=0x%08x " - "num_areas=%d\n", - param->dl_cmd, param->start_addr, param->num_areas); - - if (param->num_areas > 100) { - ret = -EINVAL; - goto out; - } - - dl = kzalloc(sizeof(*dl) + param->num_areas * - sizeof(struct prism2_download_data_area), GFP_KERNEL); - if (dl == NULL) { - ret = -ENOMEM; - goto out; - } - dl->dl_cmd = param->dl_cmd; - dl->start_addr = param->start_addr; - dl->num_areas = param->num_areas; - for (i = 0; i < param->num_areas; i++) { - PDEBUG(DEBUG_EXTRA2, - " area %d: addr=0x%08x len=%d ptr=0x%p\n", - i, param->data[i].addr, param->data[i].len, - param->data[i].ptr); - - dl->data[i].addr = param->data[i].addr; - dl->data[i].len = param->data[i].len; - - total_len += param->data[i].len; - if (param->data[i].len > PRISM2_MAX_DOWNLOAD_AREA_LEN || - total_len > PRISM2_MAX_DOWNLOAD_LEN) { - ret = -E2BIG; - goto out; - } - - dl->data[i].data = kmalloc(dl->data[i].len, GFP_KERNEL); - if (dl->data[i].data == NULL) { - ret = -ENOMEM; - goto out; - } - - if (copy_from_user(dl->data[i].data, param->data[i].ptr, - param->data[i].len)) { - ret = -EFAULT; - goto out; - } - } - - switch (param->dl_cmd) { - case PRISM2_DOWNLOAD_VOLATILE: - case PRISM2_DOWNLOAD_VOLATILE_PERSISTENT: - ret = prism2_download_volatile(local, dl); - break; - case PRISM2_DOWNLOAD_VOLATILE_GENESIS: - case PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT: - ret = prism2_download_genesis(local, dl); - break; - case PRISM2_DOWNLOAD_NON_VOLATILE: -#ifdef PRISM2_NON_VOLATILE_DOWNLOAD - ret = prism2_download_nonvolatile(local, dl); -#else /* PRISM2_NON_VOLATILE_DOWNLOAD */ - printk(KERN_INFO "%s: non-volatile downloading not enabled\n", - local->dev->name); - ret = -EOPNOTSUPP; -#endif /* PRISM2_NON_VOLATILE_DOWNLOAD */ - break; - default: - printk(KERN_DEBUG "%s: unsupported download command %d\n", - local->dev->name, param->dl_cmd); - ret = -EINVAL; - break; - }; - - out: - if (ret == 0 && dl && - param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_GENESIS_PERSISTENT) { - prism2_download_free_data(local->dl_pri); - local->dl_pri = dl; - } else if (ret == 0 && dl && - param->dl_cmd == PRISM2_DOWNLOAD_VOLATILE_PERSISTENT) { - prism2_download_free_data(local->dl_sec); - local->dl_sec = dl; - } else - prism2_download_free_data(dl); - - return ret; -} diff --git a/drivers/net/wireless/hostap/hostap_hw.c b/drivers/net/wireless/hostap/hostap_hw.c deleted file mode 100644 index 2f999fc94f60..000000000000 --- a/drivers/net/wireless/hostap/hostap_hw.c +++ /dev/null @@ -1,3418 +0,0 @@ -/* - * Host AP (software wireless LAN access point) driver for - * Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - * - * FIX: - * - there is currently no way of associating TX packets to correct wds device - * when TX Exc/OK event occurs, so all tx_packets and some - * tx_errors/tx_dropped are added to the main netdevice; using sw_support - * field in txdesc might be used to fix this (using Alloc event to increment - * tx_packets would need some further info in txfid table) - * - * Buffer Access Path (BAP) usage: - * Prism2 cards have two separate BAPs for accessing the card memory. These - * should allow concurrent access to two different frames and the driver - * previously used BAP0 for sending data and BAP1 for receiving data. - * However, there seems to be number of issues with concurrent access and at - * least one know hardware bug in using BAP0 and BAP1 concurrently with PCI - * Prism2.5. Therefore, the driver now only uses BAP0 for moving data between - * host and card memories. BAP0 accesses are protected with local->baplock - * (spin_lock_bh) to prevent concurrent use. - */ - - - -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hostap_80211.h" -#include "hostap.h" -#include "hostap_ap.h" - - -/* #define final_version */ - -static int mtu = 1500; -module_param(mtu, int, 0444); -MODULE_PARM_DESC(mtu, "Maximum transfer unit"); - -static int channel[MAX_PARM_DEVICES] = { 3, DEF_INTS }; -module_param_array(channel, int, NULL, 0444); -MODULE_PARM_DESC(channel, "Initial channel"); - -static char essid[33] = "test"; -module_param_string(essid, essid, sizeof(essid), 0444); -MODULE_PARM_DESC(essid, "Host AP's ESSID"); - -static int iw_mode[MAX_PARM_DEVICES] = { IW_MODE_MASTER, DEF_INTS }; -module_param_array(iw_mode, int, NULL, 0444); -MODULE_PARM_DESC(iw_mode, "Initial operation mode"); - -static int beacon_int[MAX_PARM_DEVICES] = { 100, DEF_INTS }; -module_param_array(beacon_int, int, NULL, 0444); -MODULE_PARM_DESC(beacon_int, "Beacon interval (1 = 1024 usec)"); - -static int dtim_period[MAX_PARM_DEVICES] = { 1, DEF_INTS }; -module_param_array(dtim_period, int, NULL, 0444); -MODULE_PARM_DESC(dtim_period, "DTIM period"); - -static char dev_template[16] = "wlan%d"; -module_param_string(dev_template, dev_template, sizeof(dev_template), 0444); -MODULE_PARM_DESC(dev_template, "Prefix for network device name (default: " - "wlan%d)"); - -#ifdef final_version -#define EXTRA_EVENTS_WTERR 0 -#else -/* check WTERR events (Wait Time-out) in development versions */ -#define EXTRA_EVENTS_WTERR HFA384X_EV_WTERR -#endif - -/* Events that will be using BAP0 */ -#define HFA384X_BAP0_EVENTS \ - (HFA384X_EV_TXEXC | HFA384X_EV_RX | HFA384X_EV_INFO | HFA384X_EV_TX) - -/* event mask, i.e., events that will result in an interrupt */ -#define HFA384X_EVENT_MASK \ - (HFA384X_BAP0_EVENTS | HFA384X_EV_ALLOC | HFA384X_EV_INFDROP | \ - HFA384X_EV_CMD | HFA384X_EV_TICK | \ - EXTRA_EVENTS_WTERR) - -/* Default TX control flags: use 802.11 headers and request interrupt for - * failed transmits. Frames that request ACK callback, will add - * _TX_OK flag and _ALT_RTRY flag may be used to select different retry policy. - */ -#define HFA384X_TX_CTRL_FLAGS \ - (HFA384X_TX_CTRL_802_11 | HFA384X_TX_CTRL_TX_EX) - - -/* ca. 1 usec */ -#define HFA384X_CMD_BUSY_TIMEOUT 5000 -#define HFA384X_BAP_BUSY_TIMEOUT 50000 - -/* ca. 10 usec */ -#define HFA384X_CMD_COMPL_TIMEOUT 20000 -#define HFA384X_DL_COMPL_TIMEOUT 1000000 - -/* Wait times for initialization; yield to other processes to avoid busy - * waiting for long time. */ -#define HFA384X_INIT_TIMEOUT (HZ / 2) /* 500 ms */ -#define HFA384X_ALLOC_COMPL_TIMEOUT (HZ / 20) /* 50 ms */ - - -static void prism2_hw_reset(struct net_device *dev); -static void prism2_check_sta_fw_version(local_info_t *local); - -#ifdef PRISM2_DOWNLOAD_SUPPORT -/* hostap_download.c */ -static int prism2_download_aux_dump(struct net_device *dev, - unsigned int addr, int len, u8 *buf); -static u8 * prism2_read_pda(struct net_device *dev); -static int prism2_download(local_info_t *local, - struct prism2_download_param *param); -static void prism2_download_free_data(struct prism2_download_data *dl); -static int prism2_download_volatile(local_info_t *local, - struct prism2_download_data *param); -static int prism2_download_genesis(local_info_t *local, - struct prism2_download_data *param); -static int prism2_get_ram_size(local_info_t *local); -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - - - - -#ifndef final_version -/* magic value written to SWSUPPORT0 reg. for detecting whether card is still - * present */ -#define HFA384X_MAGIC 0x8A32 -#endif - - -static u16 hfa384x_read_reg(struct net_device *dev, u16 reg) -{ - return HFA384X_INW(reg); -} - - -static void hfa384x_read_regs(struct net_device *dev, - struct hfa384x_regs *regs) -{ - regs->cmd = HFA384X_INW(HFA384X_CMD_OFF); - regs->evstat = HFA384X_INW(HFA384X_EVSTAT_OFF); - regs->offset0 = HFA384X_INW(HFA384X_OFFSET0_OFF); - regs->offset1 = HFA384X_INW(HFA384X_OFFSET1_OFF); - regs->swsupport0 = HFA384X_INW(HFA384X_SWSUPPORT0_OFF); -} - - -/** - * __hostap_cmd_queue_free - Free Prism2 command queue entry (private) - * @local: pointer to private Host AP driver data - * @entry: Prism2 command queue entry to be freed - * @del_req: request the entry to be removed - * - * Internal helper function for freeing Prism2 command queue entries. - * Caller must have acquired local->cmdlock before calling this function. - */ -static inline void __hostap_cmd_queue_free(local_info_t *local, - struct hostap_cmd_queue *entry, - int del_req) -{ - if (del_req) { - entry->del_req = 1; - if (!list_empty(&entry->list)) { - list_del_init(&entry->list); - local->cmd_queue_len--; - } - } - - if (atomic_dec_and_test(&entry->usecnt) && entry->del_req) - kfree(entry); -} - - -/** - * hostap_cmd_queue_free - Free Prism2 command queue entry - * @local: pointer to private Host AP driver data - * @entry: Prism2 command queue entry to be freed - * @del_req: request the entry to be removed - * - * Free a Prism2 command queue entry. - */ -static inline void hostap_cmd_queue_free(local_info_t *local, - struct hostap_cmd_queue *entry, - int del_req) -{ - unsigned long flags; - - spin_lock_irqsave(&local->cmdlock, flags); - __hostap_cmd_queue_free(local, entry, del_req); - spin_unlock_irqrestore(&local->cmdlock, flags); -} - - -/** - * prism2_clear_cmd_queue - Free all pending Prism2 command queue entries - * @local: pointer to private Host AP driver data - */ -static void prism2_clear_cmd_queue(local_info_t *local) -{ - struct list_head *ptr, *n; - unsigned long flags; - struct hostap_cmd_queue *entry; - - spin_lock_irqsave(&local->cmdlock, flags); - list_for_each_safe(ptr, n, &local->cmd_queue) { - entry = list_entry(ptr, struct hostap_cmd_queue, list); - atomic_inc(&entry->usecnt); - printk(KERN_DEBUG "%s: removed pending cmd_queue entry " - "(type=%d, cmd=0x%04x, param0=0x%04x)\n", - local->dev->name, entry->type, entry->cmd, - entry->param0); - __hostap_cmd_queue_free(local, entry, 1); - } - if (local->cmd_queue_len) { - /* This should not happen; print debug message and clear - * queue length. */ - printk(KERN_DEBUG "%s: cmd_queue_len (%d) not zero after " - "flush\n", local->dev->name, local->cmd_queue_len); - local->cmd_queue_len = 0; - } - spin_unlock_irqrestore(&local->cmdlock, flags); -} - - -/** - * hfa384x_cmd_issue - Issue a Prism2 command to the hardware - * @dev: pointer to net_device - * @entry: Prism2 command queue entry to be issued - */ -static int hfa384x_cmd_issue(struct net_device *dev, - struct hostap_cmd_queue *entry) -{ - struct hostap_interface *iface; - local_info_t *local; - int tries; - u16 reg; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->card_present && !local->func->card_present(local)) - return -ENODEV; - - if (entry->issued) { - printk(KERN_DEBUG "%s: driver bug - re-issuing command @%p\n", - dev->name, entry); - } - - /* wait until busy bit is clear; this should always be clear since the - * commands are serialized */ - tries = HFA384X_CMD_BUSY_TIMEOUT; - while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { - tries--; - udelay(1); - } -#ifndef final_version - if (tries != HFA384X_CMD_BUSY_TIMEOUT) { - prism2_io_debug_error(dev, 1); - printk(KERN_DEBUG "%s: hfa384x_cmd_issue: cmd reg was busy " - "for %d usec\n", dev->name, - HFA384X_CMD_BUSY_TIMEOUT - tries); - } -#endif - if (tries == 0) { - reg = HFA384X_INW(HFA384X_CMD_OFF); - prism2_io_debug_error(dev, 2); - printk(KERN_DEBUG "%s: hfa384x_cmd_issue - timeout - " - "reg=0x%04x\n", dev->name, reg); - return -ETIMEDOUT; - } - - /* write command */ - spin_lock_irqsave(&local->cmdlock, flags); - HFA384X_OUTW(entry->param0, HFA384X_PARAM0_OFF); - HFA384X_OUTW(entry->param1, HFA384X_PARAM1_OFF); - HFA384X_OUTW(entry->cmd, HFA384X_CMD_OFF); - entry->issued = 1; - spin_unlock_irqrestore(&local->cmdlock, flags); - - return 0; -} - - -/** - * hfa384x_cmd - Issue a Prism2 command and wait (sleep) for completion - * @dev: pointer to net_device - * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) - * @param0: value for Param0 register - * @param1: value for Param1 register (pointer; %NULL if not used) - * @resp0: pointer for Resp0 data or %NULL if Resp0 is not needed - * - * Issue given command (possibly after waiting in command queue) and sleep - * until the command is completed (or timed out or interrupted). This can be - * called only from user process context. - */ -static int hfa384x_cmd(struct net_device *dev, u16 cmd, u16 param0, - u16 *param1, u16 *resp0) -{ - struct hostap_interface *iface; - local_info_t *local; - int err, res, issue, issued = 0; - unsigned long flags; - struct hostap_cmd_queue *entry; - DECLARE_WAITQUEUE(wait, current); - - iface = netdev_priv(dev); - local = iface->local; - - if (in_interrupt()) { - printk(KERN_DEBUG "%s: hfa384x_cmd called from interrupt " - "context\n", dev->name); - return -1; - } - - if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN) { - printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n", - dev->name); - return -1; - } - - if (signal_pending(current)) - return -EINTR; - - entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (entry == NULL) { - printk(KERN_DEBUG "%s: hfa384x_cmd - kmalloc failed\n", - dev->name); - return -ENOMEM; - } - atomic_set(&entry->usecnt, 1); - entry->type = CMD_SLEEP; - entry->cmd = cmd; - entry->param0 = param0; - if (param1) - entry->param1 = *param1; - init_waitqueue_head(&entry->compl); - - /* prepare to wait for command completion event, but do not sleep yet - */ - add_wait_queue(&entry->compl, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - spin_lock_irqsave(&local->cmdlock, flags); - issue = list_empty(&local->cmd_queue); - if (issue) - entry->issuing = 1; - list_add_tail(&entry->list, &local->cmd_queue); - local->cmd_queue_len++; - spin_unlock_irqrestore(&local->cmdlock, flags); - - err = 0; - if (!issue) - goto wait_completion; - - if (signal_pending(current)) - err = -EINTR; - - if (!err) { - if (hfa384x_cmd_issue(dev, entry)) - err = -ETIMEDOUT; - else - issued = 1; - } - - wait_completion: - if (!err && entry->type != CMD_COMPLETED) { - /* sleep until command is completed or timed out */ - res = schedule_timeout(2 * HZ); - } else - res = -1; - - if (!err && signal_pending(current)) - err = -EINTR; - - if (err && issued) { - /* the command was issued, so a CmdCompl event should occur - * soon; however, there's a pending signal and - * schedule_timeout() would be interrupted; wait a short period - * of time to avoid removing entry from the list before - * CmdCompl event */ - udelay(300); - } - - set_current_state(TASK_RUNNING); - remove_wait_queue(&entry->compl, &wait); - - /* If entry->list is still in the list, it must be removed - * first and in this case prism2_cmd_ev() does not yet have - * local reference to it, and the data can be kfree()'d - * here. If the command completion event is still generated, - * it will be assigned to next (possibly) pending command, but - * the driver will reset the card anyway due to timeout - * - * If the entry is not in the list prism2_cmd_ev() has a local - * reference to it, but keeps cmdlock as long as the data is - * needed, so the data can be kfree()'d here. */ - - /* FIX: if the entry->list is in the list, it has not been completed - * yet, so removing it here is somewhat wrong.. this could cause - * references to freed memory and next list_del() causing NULL pointer - * dereference.. it would probably be better to leave the entry in the - * list and the list should be emptied during hw reset */ - - spin_lock_irqsave(&local->cmdlock, flags); - if (!list_empty(&entry->list)) { - printk(KERN_DEBUG "%s: hfa384x_cmd: entry still in list? " - "(entry=%p, type=%d, res=%d)\n", dev->name, entry, - entry->type, res); - list_del_init(&entry->list); - local->cmd_queue_len--; - } - spin_unlock_irqrestore(&local->cmdlock, flags); - - if (err) { - printk(KERN_DEBUG "%s: hfa384x_cmd: interrupted; err=%d\n", - dev->name, err); - res = err; - goto done; - } - - if (entry->type != CMD_COMPLETED) { - u16 reg = HFA384X_INW(HFA384X_EVSTAT_OFF); - printk(KERN_DEBUG "%s: hfa384x_cmd: command was not " - "completed (res=%d, entry=%p, type=%d, cmd=0x%04x, " - "param0=0x%04x, EVSTAT=%04x INTEN=%04x)\n", dev->name, - res, entry, entry->type, entry->cmd, entry->param0, reg, - HFA384X_INW(HFA384X_INTEN_OFF)); - if (reg & HFA384X_EV_CMD) { - /* Command completion event is pending, but the - * interrupt was not delivered - probably an issue - * with pcmcia-cs configuration. */ - printk(KERN_WARNING "%s: interrupt delivery does not " - "seem to work\n", dev->name); - } - prism2_io_debug_error(dev, 3); - res = -ETIMEDOUT; - goto done; - } - - if (resp0 != NULL) - *resp0 = entry->resp0; -#ifndef final_version - if (entry->res) { - printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x, " - "resp0=0x%04x\n", - dev->name, cmd, entry->res, entry->resp0); - } -#endif /* final_version */ - - res = entry->res; - done: - hostap_cmd_queue_free(local, entry, 1); - return res; -} - - -/** - * hfa384x_cmd_callback - Issue a Prism2 command; callback when completed - * @dev: pointer to net_device - * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) - * @param0: value for Param0 register - * @callback: command completion callback function (%NULL = no callback) - * @context: context data to be given to the callback function - * - * Issue given command (possibly after waiting in command queue) and use - * callback function to indicate command completion. This can be called both - * from user and interrupt context. The callback function will be called in - * hardware IRQ context. It can be %NULL, when no function is called when - * command is completed. - */ -static int hfa384x_cmd_callback(struct net_device *dev, u16 cmd, u16 param0, - void (*callback)(struct net_device *dev, - long context, u16 resp0, - u16 status), - long context) -{ - struct hostap_interface *iface; - local_info_t *local; - int issue, ret; - unsigned long flags; - struct hostap_cmd_queue *entry; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->cmd_queue_len >= HOSTAP_CMD_QUEUE_MAX_LEN + 2) { - printk(KERN_DEBUG "%s: hfa384x_cmd: cmd_queue full\n", - dev->name); - return -1; - } - - entry = kzalloc(sizeof(*entry), GFP_ATOMIC); - if (entry == NULL) { - printk(KERN_DEBUG "%s: hfa384x_cmd_callback - kmalloc " - "failed\n", dev->name); - return -ENOMEM; - } - atomic_set(&entry->usecnt, 1); - entry->type = CMD_CALLBACK; - entry->cmd = cmd; - entry->param0 = param0; - entry->callback = callback; - entry->context = context; - - spin_lock_irqsave(&local->cmdlock, flags); - issue = list_empty(&local->cmd_queue); - if (issue) - entry->issuing = 1; - list_add_tail(&entry->list, &local->cmd_queue); - local->cmd_queue_len++; - spin_unlock_irqrestore(&local->cmdlock, flags); - - if (issue && hfa384x_cmd_issue(dev, entry)) - ret = -ETIMEDOUT; - else - ret = 0; - - hostap_cmd_queue_free(local, entry, ret); - - return ret; -} - - -/** - * __hfa384x_cmd_no_wait - Issue a Prism2 command (private) - * @dev: pointer to net_device - * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) - * @param0: value for Param0 register - * @io_debug_num: I/O debug error number - * - * Shared helper function for hfa384x_cmd_wait() and hfa384x_cmd_no_wait(). - */ -static int __hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd, u16 param0, - int io_debug_num) -{ - int tries; - u16 reg; - - /* wait until busy bit is clear; this should always be clear since the - * commands are serialized */ - tries = HFA384X_CMD_BUSY_TIMEOUT; - while (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY && tries > 0) { - tries--; - udelay(1); - } - if (tries == 0) { - reg = HFA384X_INW(HFA384X_CMD_OFF); - prism2_io_debug_error(dev, io_debug_num); - printk(KERN_DEBUG "%s: __hfa384x_cmd_no_wait(%d) - timeout - " - "reg=0x%04x\n", dev->name, io_debug_num, reg); - return -ETIMEDOUT; - } - - /* write command */ - HFA384X_OUTW(param0, HFA384X_PARAM0_OFF); - HFA384X_OUTW(cmd, HFA384X_CMD_OFF); - - return 0; -} - - -/** - * hfa384x_cmd_wait - Issue a Prism2 command and busy wait for completion - * @dev: pointer to net_device - * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) - * @param0: value for Param0 register - */ -static int hfa384x_cmd_wait(struct net_device *dev, u16 cmd, u16 param0) -{ - int res, tries; - u16 reg; - - res = __hfa384x_cmd_no_wait(dev, cmd, param0, 4); - if (res) - return res; - - /* wait for command completion */ - if ((cmd & HFA384X_CMDCODE_MASK) == HFA384X_CMDCODE_DOWNLOAD) - tries = HFA384X_DL_COMPL_TIMEOUT; - else - tries = HFA384X_CMD_COMPL_TIMEOUT; - - while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) && - tries > 0) { - tries--; - udelay(10); - } - if (tries == 0) { - reg = HFA384X_INW(HFA384X_EVSTAT_OFF); - prism2_io_debug_error(dev, 5); - printk(KERN_DEBUG "%s: hfa384x_cmd_wait - timeout2 - " - "reg=0x%04x\n", dev->name, reg); - return -ETIMEDOUT; - } - - res = (HFA384X_INW(HFA384X_STATUS_OFF) & - (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | BIT(9) | - BIT(8))) >> 8; -#ifndef final_version - if (res) { - printk(KERN_DEBUG "%s: CMD=0x%04x => res=0x%02x\n", - dev->name, cmd, res); - } -#endif - - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); - - return res; -} - - -/** - * hfa384x_cmd_no_wait - Issue a Prism2 command; do not wait for completion - * @dev: pointer to net_device - * @cmd: Prism2 command code (HFA384X_CMD_CODE_*) - * @param0: value for Param0 register - */ -static inline int hfa384x_cmd_no_wait(struct net_device *dev, u16 cmd, - u16 param0) -{ - return __hfa384x_cmd_no_wait(dev, cmd, param0, 6); -} - - -/** - * prism2_cmd_ev - Prism2 command completion event handler - * @dev: pointer to net_device - * - * Interrupt handler for command completion events. Called by the main - * interrupt handler in hardware IRQ context. Read Resp0 and status registers - * from the hardware and ACK the event. Depending on the issued command type - * either wake up the sleeping process that is waiting for command completion - * or call the callback function. Issue the next command, if one is pending. - */ -static void prism2_cmd_ev(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hostap_cmd_queue *entry = NULL; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock(&local->cmdlock); - if (!list_empty(&local->cmd_queue)) { - entry = list_entry(local->cmd_queue.next, - struct hostap_cmd_queue, list); - atomic_inc(&entry->usecnt); - list_del_init(&entry->list); - local->cmd_queue_len--; - - if (!entry->issued) { - printk(KERN_DEBUG "%s: Command completion event, but " - "cmd not issued\n", dev->name); - __hostap_cmd_queue_free(local, entry, 1); - entry = NULL; - } - } - spin_unlock(&local->cmdlock); - - if (!entry) { - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); - printk(KERN_DEBUG "%s: Command completion event, but no " - "pending commands\n", dev->name); - return; - } - - entry->resp0 = HFA384X_INW(HFA384X_RESP0_OFF); - entry->res = (HFA384X_INW(HFA384X_STATUS_OFF) & - (BIT(14) | BIT(13) | BIT(12) | BIT(11) | BIT(10) | - BIT(9) | BIT(8))) >> 8; - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); - - /* TODO: rest of the CmdEv handling could be moved to tasklet */ - if (entry->type == CMD_SLEEP) { - entry->type = CMD_COMPLETED; - wake_up_interruptible(&entry->compl); - } else if (entry->type == CMD_CALLBACK) { - if (entry->callback) - entry->callback(dev, entry->context, entry->resp0, - entry->res); - } else { - printk(KERN_DEBUG "%s: Invalid command completion type %d\n", - dev->name, entry->type); - } - hostap_cmd_queue_free(local, entry, 1); - - /* issue next command, if pending */ - entry = NULL; - spin_lock(&local->cmdlock); - if (!list_empty(&local->cmd_queue)) { - entry = list_entry(local->cmd_queue.next, - struct hostap_cmd_queue, list); - if (entry->issuing) { - /* hfa384x_cmd() has already started issuing this - * command, so do not start here */ - entry = NULL; - } - if (entry) - atomic_inc(&entry->usecnt); - } - spin_unlock(&local->cmdlock); - - if (entry) { - /* issue next command; if command issuing fails, remove the - * entry from cmd_queue */ - int res = hfa384x_cmd_issue(dev, entry); - spin_lock(&local->cmdlock); - __hostap_cmd_queue_free(local, entry, res); - spin_unlock(&local->cmdlock); - } -} - - -static int hfa384x_wait_offset(struct net_device *dev, u16 o_off) -{ - int tries = HFA384X_BAP_BUSY_TIMEOUT; - int res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; - - while (res && tries > 0) { - tries--; - udelay(1); - res = HFA384X_INW(o_off) & HFA384X_OFFSET_BUSY; - } - return res; -} - - -/* Offset must be even */ -static int hfa384x_setup_bap(struct net_device *dev, u16 bap, u16 id, - int offset) -{ - u16 o_off, s_off; - int ret = 0; - - if (offset % 2 || bap > 1) - return -EINVAL; - - if (bap == BAP1) { - o_off = HFA384X_OFFSET1_OFF; - s_off = HFA384X_SELECT1_OFF; - } else { - o_off = HFA384X_OFFSET0_OFF; - s_off = HFA384X_SELECT0_OFF; - } - - if (hfa384x_wait_offset(dev, o_off)) { - prism2_io_debug_error(dev, 7); - printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout before\n", - dev->name); - ret = -ETIMEDOUT; - goto out; - } - - HFA384X_OUTW(id, s_off); - HFA384X_OUTW(offset, o_off); - - if (hfa384x_wait_offset(dev, o_off)) { - prism2_io_debug_error(dev, 8); - printk(KERN_DEBUG "%s: hfa384x_setup_bap - timeout after\n", - dev->name); - ret = -ETIMEDOUT; - goto out; - } -#ifndef final_version - if (HFA384X_INW(o_off) & HFA384X_OFFSET_ERR) { - prism2_io_debug_error(dev, 9); - printk(KERN_DEBUG "%s: hfa384x_setup_bap - offset error " - "(%d,0x04%x,%d); reg=0x%04x\n", - dev->name, bap, id, offset, HFA384X_INW(o_off)); - ret = -EINVAL; - } -#endif - - out: - return ret; -} - - -static int hfa384x_get_rid(struct net_device *dev, u16 rid, void *buf, int len, - int exact_len) -{ - struct hostap_interface *iface; - local_info_t *local; - int res, rlen = 0; - struct hfa384x_rid_hdr rec; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->no_pri) { - printk(KERN_DEBUG "%s: cannot get RID %04x (len=%d) - no PRI " - "f/w\n", dev->name, rid, len); - return -ENOTTY; /* Well.. not really correct, but return - * something unique enough.. */ - } - - if ((local->func->card_present && !local->func->card_present(local)) || - local->hw_downloading) - return -ENODEV; - - res = mutex_lock_interruptible(&local->rid_bap_mtx); - if (res) - return res; - - res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS, rid, NULL, NULL); - if (res) { - printk(KERN_DEBUG "%s: hfa384x_get_rid: CMDCODE_ACCESS failed " - "(res=%d, rid=%04x, len=%d)\n", - dev->name, res, rid, len); - mutex_unlock(&local->rid_bap_mtx); - return res; - } - - spin_lock_bh(&local->baplock); - - res = hfa384x_setup_bap(dev, BAP0, rid, 0); - if (!res) - res = hfa384x_from_bap(dev, BAP0, &rec, sizeof(rec)); - - if (le16_to_cpu(rec.len) == 0) { - /* RID not available */ - res = -ENODATA; - } - - rlen = (le16_to_cpu(rec.len) - 1) * 2; - if (!res && exact_len && rlen != len) { - printk(KERN_DEBUG "%s: hfa384x_get_rid - RID len mismatch: " - "rid=0x%04x, len=%d (expected %d)\n", - dev->name, rid, rlen, len); - res = -ENODATA; - } - - if (!res) - res = hfa384x_from_bap(dev, BAP0, buf, len); - - spin_unlock_bh(&local->baplock); - mutex_unlock(&local->rid_bap_mtx); - - if (res) { - if (res != -ENODATA) - printk(KERN_DEBUG "%s: hfa384x_get_rid (rid=%04x, " - "len=%d) - failed - res=%d\n", dev->name, rid, - len, res); - if (res == -ETIMEDOUT) - prism2_hw_reset(dev); - return res; - } - - return rlen; -} - - -static int hfa384x_set_rid(struct net_device *dev, u16 rid, void *buf, int len) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hfa384x_rid_hdr rec; - int res; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->no_pri) { - printk(KERN_DEBUG "%s: cannot set RID %04x (len=%d) - no PRI " - "f/w\n", dev->name, rid, len); - return -ENOTTY; /* Well.. not really correct, but return - * something unique enough.. */ - } - - if ((local->func->card_present && !local->func->card_present(local)) || - local->hw_downloading) - return -ENODEV; - - rec.rid = cpu_to_le16(rid); - /* RID len in words and +1 for rec.rid */ - rec.len = cpu_to_le16(len / 2 + len % 2 + 1); - - res = mutex_lock_interruptible(&local->rid_bap_mtx); - if (res) - return res; - - spin_lock_bh(&local->baplock); - res = hfa384x_setup_bap(dev, BAP0, rid, 0); - if (!res) - res = hfa384x_to_bap(dev, BAP0, &rec, sizeof(rec)); - if (!res) - res = hfa384x_to_bap(dev, BAP0, buf, len); - spin_unlock_bh(&local->baplock); - - if (res) { - printk(KERN_DEBUG "%s: hfa384x_set_rid (rid=%04x, len=%d) - " - "failed - res=%d\n", dev->name, rid, len, res); - mutex_unlock(&local->rid_bap_mtx); - return res; - } - - res = hfa384x_cmd(dev, HFA384X_CMDCODE_ACCESS_WRITE, rid, NULL, NULL); - mutex_unlock(&local->rid_bap_mtx); - - if (res) { - printk(KERN_DEBUG "%s: hfa384x_set_rid: CMDCODE_ACCESS_WRITE " - "failed (res=%d, rid=%04x, len=%d)\n", - dev->name, res, rid, len); - - if (res == -ETIMEDOUT) - prism2_hw_reset(dev); - } - - return res; -} - - -static void hfa384x_disable_interrupts(struct net_device *dev) -{ - /* disable interrupts and clear event status */ - HFA384X_OUTW(0, HFA384X_INTEN_OFF); - HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); -} - - -static void hfa384x_enable_interrupts(struct net_device *dev) -{ - /* ack pending events and enable interrupts from selected events */ - HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); - HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF); -} - - -static void hfa384x_events_no_bap0(struct net_device *dev) -{ - HFA384X_OUTW(HFA384X_EVENT_MASK & ~HFA384X_BAP0_EVENTS, - HFA384X_INTEN_OFF); -} - - -static void hfa384x_events_all(struct net_device *dev) -{ - HFA384X_OUTW(HFA384X_EVENT_MASK, HFA384X_INTEN_OFF); -} - - -static void hfa384x_events_only_cmd(struct net_device *dev) -{ - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_INTEN_OFF); -} - - -static u16 hfa384x_allocate_fid(struct net_device *dev, int len) -{ - u16 fid; - unsigned long delay; - - /* FIX: this could be replace with hfa384x_cmd() if the Alloc event - * below would be handled like CmdCompl event (sleep here, wake up from - * interrupt handler */ - if (hfa384x_cmd_wait(dev, HFA384X_CMDCODE_ALLOC, len)) { - printk(KERN_DEBUG "%s: cannot allocate fid, len=%d\n", - dev->name, len); - return 0xffff; - } - - delay = jiffies + HFA384X_ALLOC_COMPL_TIMEOUT; - while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC) && - time_before(jiffies, delay)) - yield(); - if (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_ALLOC)) { - printk("%s: fid allocate, len=%d - timeout\n", dev->name, len); - return 0xffff; - } - - fid = HFA384X_INW(HFA384X_ALLOCFID_OFF); - HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF); - - return fid; -} - - -static int prism2_reset_port(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - int res; - - iface = netdev_priv(dev); - local = iface->local; - - if (!local->dev_enabled) - return 0; - - res = hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0, - NULL, NULL); - if (res) - printk(KERN_DEBUG "%s: reset port failed to disable port\n", - dev->name); - else { - res = hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0, - NULL, NULL); - if (res) - printk(KERN_DEBUG "%s: reset port failed to enable " - "port\n", dev->name); - } - - /* It looks like at least some STA firmware versions reset - * fragmentation threshold back to 2346 after enable command. Restore - * the configured value, if it differs from this default. */ - if (local->fragm_threshold != 2346 && - hostap_set_word(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, - local->fragm_threshold)) { - printk(KERN_DEBUG "%s: failed to restore fragmentation " - "threshold (%d) after Port0 enable\n", - dev->name, local->fragm_threshold); - } - - /* Some firmwares lose antenna selection settings on reset */ - (void) hostap_set_antsel(local); - - return res; -} - - -static int prism2_get_version_info(struct net_device *dev, u16 rid, - const char *txt) -{ - struct hfa384x_comp_ident comp; - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->no_pri) { - /* PRI f/w not yet available - cannot read RIDs */ - return -1; - } - if (hfa384x_get_rid(dev, rid, &comp, sizeof(comp), 1) < 0) { - printk(KERN_DEBUG "Could not get RID for component %s\n", txt); - return -1; - } - - printk(KERN_INFO "%s: %s: id=0x%02x v%d.%d.%d\n", dev->name, txt, - __le16_to_cpu(comp.id), __le16_to_cpu(comp.major), - __le16_to_cpu(comp.minor), __le16_to_cpu(comp.variant)); - return 0; -} - - -static int prism2_setup_rids(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 tmp; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - hostap_set_word(dev, HFA384X_RID_TICKTIME, 2000); - - if (!local->fw_ap) { - u16 tmp1 = hostap_get_porttype(local); - ret = hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, tmp1); - if (ret) { - printk("%s: Port type setting to %d failed\n", - dev->name, tmp1); - goto fail; - } - } - - /* Setting SSID to empty string seems to kill the card in Host AP mode - */ - if (local->iw_mode != IW_MODE_MASTER || local->essid[0] != '\0') { - ret = hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, - local->essid); - if (ret) { - printk("%s: AP own SSID setting failed\n", dev->name); - goto fail; - } - } - - ret = hostap_set_word(dev, HFA384X_RID_CNFMAXDATALEN, - PRISM2_DATA_MAXLEN); - if (ret) { - printk("%s: MAC data length setting to %d failed\n", - dev->name, PRISM2_DATA_MAXLEN); - goto fail; - } - - if (hfa384x_get_rid(dev, HFA384X_RID_CHANNELLIST, &tmp, 2, 1) < 0) { - printk("%s: Channel list read failed\n", dev->name); - ret = -EINVAL; - goto fail; - } - local->channel_mask = le16_to_cpu(tmp); - - if (local->channel < 1 || local->channel > 14 || - !(local->channel_mask & (1 << (local->channel - 1)))) { - printk(KERN_WARNING "%s: Channel setting out of range " - "(%d)!\n", dev->name, local->channel); - ret = -EBUSY; - goto fail; - } - - ret = hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel); - if (ret) { - printk("%s: Channel setting to %d failed\n", - dev->name, local->channel); - goto fail; - } - - ret = hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, - local->beacon_int); - if (ret) { - printk("%s: Beacon interval setting to %d failed\n", - dev->name, local->beacon_int); - /* this may fail with Symbol/Lucent firmware */ - if (ret == -ETIMEDOUT) - goto fail; - } - - ret = hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, - local->dtim_period); - if (ret) { - printk("%s: DTIM period setting to %d failed\n", - dev->name, local->dtim_period); - /* this may fail with Symbol/Lucent firmware */ - if (ret == -ETIMEDOUT) - goto fail; - } - - ret = hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, - local->is_promisc); - if (ret) - printk(KERN_INFO "%s: Setting promiscuous mode (%d) failed\n", - dev->name, local->is_promisc); - - if (!local->fw_ap) { - ret = hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, - local->essid); - if (ret) { - printk("%s: Desired SSID setting failed\n", dev->name); - goto fail; - } - } - - /* Setup TXRateControl, defaults to allow use of 1, 2, 5.5, and - * 11 Mbps in automatic TX rate fallback and 1 and 2 Mbps as basic - * rates */ - if (local->tx_rate_control == 0) { - local->tx_rate_control = - HFA384X_RATES_1MBPS | - HFA384X_RATES_2MBPS | - HFA384X_RATES_5MBPS | - HFA384X_RATES_11MBPS; - } - if (local->basic_rates == 0) - local->basic_rates = HFA384X_RATES_1MBPS | HFA384X_RATES_2MBPS; - - if (!local->fw_ap) { - ret = hostap_set_word(dev, HFA384X_RID_TXRATECONTROL, - local->tx_rate_control); - if (ret) { - printk("%s: TXRateControl setting to %d failed\n", - dev->name, local->tx_rate_control); - goto fail; - } - - ret = hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES, - local->tx_rate_control); - if (ret) { - printk("%s: cnfSupportedRates setting to %d failed\n", - dev->name, local->tx_rate_control); - } - - ret = hostap_set_word(dev, HFA384X_RID_CNFBASICRATES, - local->basic_rates); - if (ret) { - printk("%s: cnfBasicRates setting to %d failed\n", - dev->name, local->basic_rates); - } - - ret = hostap_set_word(dev, HFA384X_RID_CREATEIBSS, 1); - if (ret) { - printk("%s: Create IBSS setting to 1 failed\n", - dev->name); - } - } - - if (local->name_set) - (void) hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, - local->name); - - if (hostap_set_encryption(local)) { - printk(KERN_INFO "%s: could not configure encryption\n", - dev->name); - } - - (void) hostap_set_antsel(local); - - if (hostap_set_roaming(local)) { - printk(KERN_INFO "%s: could not set host roaming\n", - dev->name); - } - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,6,3) && - hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY, local->enh_sec)) - printk(KERN_INFO "%s: cnfEnhSecurity setting to 0x%x failed\n", - dev->name, local->enh_sec); - - /* 32-bit tallies were added in STA f/w 0.8.0, but they were apparently - * not working correctly (last seven counters report bogus values). - * This has been fixed in 0.8.2, so enable 32-bit tallies only - * beginning with that firmware version. Another bug fix for 32-bit - * tallies in 1.4.0; should 16-bit tallies be used for some other - * versions, too? */ - if (local->sta_fw_ver >= PRISM2_FW_VER(0,8,2)) { - if (hostap_set_word(dev, HFA384X_RID_CNFTHIRTY2TALLY, 1)) { - printk(KERN_INFO "%s: cnfThirty2Tally setting " - "failed\n", dev->name); - local->tallies32 = 0; - } else - local->tallies32 = 1; - } else - local->tallies32 = 0; - - hostap_set_auth_algs(local); - - if (hostap_set_word(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, - local->fragm_threshold)) { - printk(KERN_INFO "%s: setting FragmentationThreshold to %d " - "failed\n", dev->name, local->fragm_threshold); - } - - if (hostap_set_word(dev, HFA384X_RID_RTSTHRESHOLD, - local->rts_threshold)) { - printk(KERN_INFO "%s: setting RTSThreshold to %d failed\n", - dev->name, local->rts_threshold); - } - - if (local->manual_retry_count >= 0 && - hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT, - local->manual_retry_count)) { - printk(KERN_INFO "%s: setting cnfAltRetryCount to %d failed\n", - dev->name, local->manual_retry_count); - } - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1) && - hfa384x_get_rid(dev, HFA384X_RID_CNFDBMADJUST, &tmp, 2, 1) == 2) { - local->rssi_to_dBm = le16_to_cpu(tmp); - } - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,7,0) && local->wpa && - hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1)) { - printk(KERN_INFO "%s: setting ssnHandlingMode to 1 failed\n", - dev->name); - } - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,7,0) && local->generic_elem && - hfa384x_set_rid(dev, HFA384X_RID_GENERICELEMENT, - local->generic_elem, local->generic_elem_len)) { - printk(KERN_INFO "%s: setting genericElement failed\n", - dev->name); - } - - fail: - return ret; -} - - -static int prism2_hw_init(struct net_device *dev, int initial) -{ - struct hostap_interface *iface; - local_info_t *local; - int ret, first = 1; - unsigned long start, delay; - - PDEBUG(DEBUG_FLOW, "prism2_hw_init()\n"); - - iface = netdev_priv(dev); - local = iface->local; - - clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits); - - init: - /* initialize HFA 384x */ - ret = hfa384x_cmd_no_wait(dev, HFA384X_CMDCODE_INIT, 0); - if (ret) { - printk(KERN_INFO "%s: first command failed - assuming card " - "does not have primary firmware\n", dev_info); - } - - if (first && (HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD)) { - /* EvStat has Cmd bit set in some cases, so retry once if no - * wait was needed */ - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); - printk(KERN_DEBUG "%s: init command completed too quickly - " - "retrying\n", dev->name); - first = 0; - goto init; - } - - start = jiffies; - delay = jiffies + HFA384X_INIT_TIMEOUT; - while (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD) && - time_before(jiffies, delay)) - yield(); - if (!(HFA384X_INW(HFA384X_EVSTAT_OFF) & HFA384X_EV_CMD)) { - printk(KERN_DEBUG "%s: assuming no Primary image in " - "flash - card initialization not completed\n", - dev_info); - local->no_pri = 1; -#ifdef PRISM2_DOWNLOAD_SUPPORT - if (local->sram_type == -1) - local->sram_type = prism2_get_ram_size(local); -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - return 1; - } - local->no_pri = 0; - printk(KERN_DEBUG "prism2_hw_init: initialized in %lu ms\n", - (jiffies - start) * 1000 / HZ); - HFA384X_OUTW(HFA384X_EV_CMD, HFA384X_EVACK_OFF); - return 0; -} - - -static int prism2_hw_init2(struct net_device *dev, int initial) -{ - struct hostap_interface *iface; - local_info_t *local; - int i; - - iface = netdev_priv(dev); - local = iface->local; - -#ifdef PRISM2_DOWNLOAD_SUPPORT - kfree(local->pda); - if (local->no_pri) - local->pda = NULL; - else - local->pda = prism2_read_pda(dev); -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - - hfa384x_disable_interrupts(dev); - -#ifndef final_version - HFA384X_OUTW(HFA384X_MAGIC, HFA384X_SWSUPPORT0_OFF); - if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) { - printk("SWSUPPORT0 write/read failed: %04X != %04X\n", - HFA384X_INW(HFA384X_SWSUPPORT0_OFF), HFA384X_MAGIC); - goto failed; - } -#endif - - if (initial || local->pri_only) { - hfa384x_events_only_cmd(dev); - /* get card version information */ - if (prism2_get_version_info(dev, HFA384X_RID_NICID, "NIC") || - prism2_get_version_info(dev, HFA384X_RID_PRIID, "PRI")) { - hfa384x_disable_interrupts(dev); - goto failed; - } - - if (prism2_get_version_info(dev, HFA384X_RID_STAID, "STA")) { - printk(KERN_DEBUG "%s: Failed to read STA f/w version " - "- only Primary f/w present\n", dev->name); - local->pri_only = 1; - return 0; - } - local->pri_only = 0; - hfa384x_disable_interrupts(dev); - } - - /* FIX: could convert allocate_fid to use sleeping CmdCompl wait and - * enable interrupts before this. This would also require some sort of - * sleeping AllocEv waiting */ - - /* allocate TX FIDs */ - local->txfid_len = PRISM2_TXFID_LEN; - for (i = 0; i < PRISM2_TXFID_COUNT; i++) { - local->txfid[i] = hfa384x_allocate_fid(dev, local->txfid_len); - if (local->txfid[i] == 0xffff && local->txfid_len > 1600) { - local->txfid[i] = hfa384x_allocate_fid(dev, 1600); - if (local->txfid[i] != 0xffff) { - printk(KERN_DEBUG "%s: Using shorter TX FID " - "(1600 bytes)\n", dev->name); - local->txfid_len = 1600; - } - } - if (local->txfid[i] == 0xffff) - goto failed; - local->intransmitfid[i] = PRISM2_TXFID_EMPTY; - } - - hfa384x_events_only_cmd(dev); - - if (initial) { - struct list_head *ptr; - prism2_check_sta_fw_version(local); - - if (hfa384x_get_rid(dev, HFA384X_RID_CNFOWNMACADDR, - dev->dev_addr, 6, 1) < 0) { - printk("%s: could not get own MAC address\n", - dev->name); - } - list_for_each(ptr, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - memcpy(iface->dev->dev_addr, dev->dev_addr, ETH_ALEN); - } - } else if (local->fw_ap) - prism2_check_sta_fw_version(local); - - prism2_setup_rids(dev); - - /* MAC is now configured, but port 0 is not yet enabled */ - return 0; - - failed: - if (!local->no_pri) - printk(KERN_WARNING "%s: Initialization failed\n", dev_info); - return 1; -} - - -static int prism2_hw_enable(struct net_device *dev, int initial) -{ - struct hostap_interface *iface; - local_info_t *local; - int was_resetting; - - iface = netdev_priv(dev); - local = iface->local; - was_resetting = local->hw_resetting; - - if (hfa384x_cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, NULL)) { - printk("%s: MAC port 0 enabling failed\n", dev->name); - return 1; - } - - local->hw_ready = 1; - local->hw_reset_tries = 0; - local->hw_resetting = 0; - hfa384x_enable_interrupts(dev); - - /* at least D-Link DWL-650 seems to require additional port reset - * before it starts acting as an AP, so reset port automatically - * here just in case */ - if (initial && prism2_reset_port(dev)) { - printk("%s: MAC port 0 reseting failed\n", dev->name); - return 1; - } - - if (was_resetting && netif_queue_stopped(dev)) { - /* If hw_reset() was called during pending transmit, netif - * queue was stopped. Wake it up now since the wlan card has - * been resetted. */ - netif_wake_queue(dev); - } - - return 0; -} - - -static int prism2_hw_config(struct net_device *dev, int initial) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->hw_downloading) - return 1; - - if (prism2_hw_init(dev, initial)) { - return local->no_pri ? 0 : 1; - } - - if (prism2_hw_init2(dev, initial)) - return 1; - - /* Enable firmware if secondary image is loaded and at least one of the - * netdevices is up. */ - if (!local->pri_only && - (initial == 0 || (initial == 2 && local->num_dev_open > 0))) { - if (!local->dev_enabled) - prism2_callback(local, PRISM2_CALLBACK_ENABLE); - local->dev_enabled = 1; - return prism2_hw_enable(dev, initial); - } - - return 0; -} - - -static void prism2_hw_shutdown(struct net_device *dev, int no_disable) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - /* Allow only command completion events during disable */ - hfa384x_events_only_cmd(dev); - - local->hw_ready = 0; - if (local->dev_enabled) - prism2_callback(local, PRISM2_CALLBACK_DISABLE); - local->dev_enabled = 0; - - if (local->func->card_present && !local->func->card_present(local)) { - printk(KERN_DEBUG "%s: card already removed or not configured " - "during shutdown\n", dev->name); - return; - } - - if ((no_disable & HOSTAP_HW_NO_DISABLE) == 0 && - hfa384x_cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, NULL)) - printk(KERN_WARNING "%s: Shutdown failed\n", dev_info); - - hfa384x_disable_interrupts(dev); - - if (no_disable & HOSTAP_HW_ENABLE_CMDCOMPL) - hfa384x_events_only_cmd(dev); - else - prism2_clear_cmd_queue(local); -} - - -static void prism2_hw_reset(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - -#if 0 - static long last_reset = 0; - - /* do not reset card more than once per second to avoid ending up in a - * busy loop reseting the card */ - if (time_before_eq(jiffies, last_reset + HZ)) - return; - last_reset = jiffies; -#endif - - iface = netdev_priv(dev); - local = iface->local; - - if (in_interrupt()) { - printk(KERN_DEBUG "%s: driver bug - prism2_hw_reset() called " - "in interrupt context\n", dev->name); - return; - } - - if (local->hw_downloading) - return; - - if (local->hw_resetting) { - printk(KERN_WARNING "%s: %s: already resetting card - " - "ignoring reset request\n", dev_info, dev->name); - return; - } - - local->hw_reset_tries++; - if (local->hw_reset_tries > 10) { - printk(KERN_WARNING "%s: too many reset tries, skipping\n", - dev->name); - return; - } - - printk(KERN_WARNING "%s: %s: resetting card\n", dev_info, dev->name); - hfa384x_disable_interrupts(dev); - local->hw_resetting = 1; - if (local->func->cor_sreset) { - /* Host system seems to hang in some cases with high traffic - * load or shared interrupts during COR sreset. Disable shared - * interrupts during reset to avoid these crashes. COS sreset - * takes quite a long time, so it is unfortunate that this - * seems to be needed. Anyway, I do not know of any better way - * of avoiding the crash. */ - disable_irq(dev->irq); - local->func->cor_sreset(local); - enable_irq(dev->irq); - } - prism2_hw_shutdown(dev, 1); - prism2_hw_config(dev, 0); - local->hw_resetting = 0; - -#ifdef PRISM2_DOWNLOAD_SUPPORT - if (local->dl_pri) { - printk(KERN_DEBUG "%s: persistent download of primary " - "firmware\n", dev->name); - if (prism2_download_genesis(local, local->dl_pri) < 0) - printk(KERN_WARNING "%s: download (PRI) failed\n", - dev->name); - } - - if (local->dl_sec) { - printk(KERN_DEBUG "%s: persistent download of secondary " - "firmware\n", dev->name); - if (prism2_download_volatile(local, local->dl_sec) < 0) - printk(KERN_WARNING "%s: download (SEC) failed\n", - dev->name); - } -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - - /* TODO: restore beacon TIM bits for STAs that have buffered frames */ -} - - -static void prism2_schedule_reset(local_info_t *local) -{ - schedule_work(&local->reset_queue); -} - - -/* Called only as scheduled task after noticing card timeout in interrupt - * context */ -static void handle_reset_queue(struct work_struct *work) -{ - local_info_t *local = container_of(work, local_info_t, reset_queue); - - printk(KERN_DEBUG "%s: scheduled card reset\n", local->dev->name); - prism2_hw_reset(local->dev); - - if (netif_queue_stopped(local->dev)) { - int i; - - for (i = 0; i < PRISM2_TXFID_COUNT; i++) - if (local->intransmitfid[i] == PRISM2_TXFID_EMPTY) { - PDEBUG(DEBUG_EXTRA, "prism2_tx_timeout: " - "wake up queue\n"); - netif_wake_queue(local->dev); - break; - } - } -} - - -static int prism2_get_txfid_idx(local_info_t *local) -{ - int idx, end; - unsigned long flags; - - spin_lock_irqsave(&local->txfidlock, flags); - end = idx = local->next_txfid; - do { - if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) { - local->intransmitfid[idx] = PRISM2_TXFID_RESERVED; - spin_unlock_irqrestore(&local->txfidlock, flags); - return idx; - } - idx++; - if (idx >= PRISM2_TXFID_COUNT) - idx = 0; - } while (idx != end); - spin_unlock_irqrestore(&local->txfidlock, flags); - - PDEBUG(DEBUG_EXTRA2, "prism2_get_txfid_idx: no room in txfid buf: " - "packet dropped\n"); - local->dev->stats.tx_dropped++; - - return -1; -} - - -/* Called only from hardware IRQ */ -static void prism2_transmit_cb(struct net_device *dev, long context, - u16 resp0, u16 res) -{ - struct hostap_interface *iface; - local_info_t *local; - int idx = (int) context; - - iface = netdev_priv(dev); - local = iface->local; - - if (res) { - printk(KERN_DEBUG "%s: prism2_transmit_cb - res=0x%02x\n", - dev->name, res); - return; - } - - if (idx < 0 || idx >= PRISM2_TXFID_COUNT) { - printk(KERN_DEBUG "%s: prism2_transmit_cb called with invalid " - "idx=%d\n", dev->name, idx); - return; - } - - if (!test_and_clear_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) { - printk(KERN_DEBUG "%s: driver bug: prism2_transmit_cb called " - "with no pending transmit\n", dev->name); - } - - if (netif_queue_stopped(dev)) { - /* ready for next TX, so wake up queue that was stopped in - * prism2_transmit() */ - netif_wake_queue(dev); - } - - spin_lock(&local->txfidlock); - - /* With reclaim, Resp0 contains new txfid for transmit; the old txfid - * will be automatically allocated for the next TX frame */ - local->intransmitfid[idx] = resp0; - - PDEBUG(DEBUG_FID, "%s: prism2_transmit_cb: txfid[%d]=0x%04x, " - "resp0=0x%04x, transmit_txfid=0x%04x\n", - dev->name, idx, local->txfid[idx], - resp0, local->intransmitfid[local->next_txfid]); - - idx++; - if (idx >= PRISM2_TXFID_COUNT) - idx = 0; - local->next_txfid = idx; - - /* check if all TX buffers are occupied */ - do { - if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) { - spin_unlock(&local->txfidlock); - return; - } - idx++; - if (idx >= PRISM2_TXFID_COUNT) - idx = 0; - } while (idx != local->next_txfid); - spin_unlock(&local->txfidlock); - - /* no empty TX buffers, stop queue */ - netif_stop_queue(dev); -} - - -/* Called only from software IRQ if PCI bus master is not used (with bus master - * this can be called both from software and hardware IRQ) */ -static int prism2_transmit(struct net_device *dev, int idx) -{ - struct hostap_interface *iface; - local_info_t *local; - int res; - - iface = netdev_priv(dev); - local = iface->local; - - /* The driver tries to stop netif queue so that there would not be - * more than one attempt to transmit frames going on; check that this - * is really the case */ - - if (test_and_set_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) { - printk(KERN_DEBUG "%s: driver bug - prism2_transmit() called " - "when previous TX was pending\n", dev->name); - return -1; - } - - /* stop the queue for the time that transmit is pending */ - netif_stop_queue(dev); - - /* transmit packet */ - res = hfa384x_cmd_callback( - dev, - HFA384X_CMDCODE_TRANSMIT | HFA384X_CMD_TX_RECLAIM, - local->txfid[idx], - prism2_transmit_cb, (long) idx); - - if (res) { - printk(KERN_DEBUG "%s: prism2_transmit: CMDCODE_TRANSMIT " - "failed (res=%d)\n", dev->name, res); - dev->stats.tx_dropped++; - netif_wake_queue(dev); - return -1; - } - dev->trans_start = jiffies; - - /* Since we did not wait for command completion, the card continues - * to process on the background and we will finish handling when - * command completion event is handled (prism2_cmd_ev() function) */ - - return 0; -} - - -/* Send IEEE 802.11 frame (convert the header into Prism2 TX descriptor and - * send the payload with this descriptor) */ -/* Called only from software IRQ */ -static int prism2_tx_80211(struct sk_buff *skb, struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hfa384x_tx_frame txdesc; - struct hostap_skb_tx_data *meta; - int hdr_len, data_len, idx, res, ret = -1; - u16 tx_control, fc; - - iface = netdev_priv(dev); - local = iface->local; - - meta = (struct hostap_skb_tx_data *) skb->cb; - - prism2_callback(local, PRISM2_CALLBACK_TX_START); - - if ((local->func->card_present && !local->func->card_present(local)) || - !local->hw_ready || local->hw_downloading || local->pri_only) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: prism2_tx_80211: hw not ready -" - " skipping\n", dev->name); - } - goto fail; - } - - memset(&txdesc, 0, sizeof(txdesc)); - - /* skb->data starts with txdesc->frame_control */ - hdr_len = 24; - skb_copy_from_linear_data(skb, &txdesc.frame_control, hdr_len); - fc = le16_to_cpu(txdesc.frame_control); - if (ieee80211_is_data(txdesc.frame_control) && - ieee80211_has_a4(txdesc.frame_control) && - skb->len >= 30) { - /* Addr4 */ - skb_copy_from_linear_data_offset(skb, hdr_len, txdesc.addr4, - ETH_ALEN); - hdr_len += ETH_ALEN; - } - - tx_control = local->tx_control; - if (meta->tx_cb_idx) { - tx_control |= HFA384X_TX_CTRL_TX_OK; - txdesc.sw_support = cpu_to_le32(meta->tx_cb_idx); - } - txdesc.tx_control = cpu_to_le16(tx_control); - txdesc.tx_rate = meta->rate; - - data_len = skb->len - hdr_len; - txdesc.data_len = cpu_to_le16(data_len); - txdesc.len = cpu_to_be16(data_len); - - idx = prism2_get_txfid_idx(local); - if (idx < 0) - goto fail; - - if (local->frame_dump & PRISM2_DUMP_TX_HDR) - hostap_dump_tx_header(dev->name, &txdesc); - - spin_lock(&local->baplock); - res = hfa384x_setup_bap(dev, BAP0, local->txfid[idx], 0); - - if (!res) - res = hfa384x_to_bap(dev, BAP0, &txdesc, sizeof(txdesc)); - if (!res) - res = hfa384x_to_bap(dev, BAP0, skb->data + hdr_len, - skb->len - hdr_len); - spin_unlock(&local->baplock); - - if (!res) - res = prism2_transmit(dev, idx); - if (res) { - printk(KERN_DEBUG "%s: prism2_tx_80211 - to BAP0 failed\n", - dev->name); - local->intransmitfid[idx] = PRISM2_TXFID_EMPTY; - schedule_work(&local->reset_queue); - goto fail; - } - - ret = 0; - -fail: - prism2_callback(local, PRISM2_CALLBACK_TX_END); - return ret; -} - - -/* Some SMP systems have reported number of odd errors with hostap_pci. fid - * register has changed values between consecutive reads for an unknown reason. - * This should really not happen, so more debugging is needed. This test - * version is a big slower, but it will detect most of such register changes - * and will try to get the correct fid eventually. */ -#define EXTRA_FID_READ_TESTS - -static u16 prism2_read_fid_reg(struct net_device *dev, u16 reg) -{ -#ifdef EXTRA_FID_READ_TESTS - u16 val, val2, val3; - int i; - - for (i = 0; i < 10; i++) { - val = HFA384X_INW(reg); - val2 = HFA384X_INW(reg); - val3 = HFA384X_INW(reg); - - if (val == val2 && val == val3) - return val; - - printk(KERN_DEBUG "%s: detected fid change (try=%d, reg=%04x):" - " %04x %04x %04x\n", - dev->name, i, reg, val, val2, val3); - if ((val == val2 || val == val3) && val != 0) - return val; - if (val2 == val3 && val2 != 0) - return val2; - } - printk(KERN_WARNING "%s: Uhhuh.. could not read good fid from reg " - "%04x (%04x %04x %04x)\n", dev->name, reg, val, val2, val3); - return val; -#else /* EXTRA_FID_READ_TESTS */ - return HFA384X_INW(reg); -#endif /* EXTRA_FID_READ_TESTS */ -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_rx(local_info_t *local) -{ - struct net_device *dev = local->dev; - int res, rx_pending = 0; - u16 len, hdr_len, rxfid, status, macport; - struct hfa384x_rx_frame rxdesc; - struct sk_buff *skb = NULL; - - prism2_callback(local, PRISM2_CALLBACK_RX_START); - - rxfid = prism2_read_fid_reg(dev, HFA384X_RXFID_OFF); -#ifndef final_version - if (rxfid == 0) { - rxfid = HFA384X_INW(HFA384X_RXFID_OFF); - printk(KERN_DEBUG "prism2_rx: rxfid=0 (next 0x%04x)\n", - rxfid); - if (rxfid == 0) { - schedule_work(&local->reset_queue); - goto rx_dropped; - } - /* try to continue with the new rxfid value */ - } -#endif - - spin_lock(&local->baplock); - res = hfa384x_setup_bap(dev, BAP0, rxfid, 0); - if (!res) - res = hfa384x_from_bap(dev, BAP0, &rxdesc, sizeof(rxdesc)); - - if (res) { - spin_unlock(&local->baplock); - printk(KERN_DEBUG "%s: copy from BAP0 failed %d\n", dev->name, - res); - if (res == -ETIMEDOUT) { - schedule_work(&local->reset_queue); - } - goto rx_dropped; - } - - len = le16_to_cpu(rxdesc.data_len); - hdr_len = sizeof(rxdesc); - status = le16_to_cpu(rxdesc.status); - macport = (status >> 8) & 0x07; - - /* Drop frames with too large reported payload length. Monitor mode - * seems to sometimes pass frames (e.g., ctrl::ack) with signed and - * negative value, so allow also values 65522 .. 65534 (-14 .. -2) for - * macport 7 */ - if (len > PRISM2_DATA_MAXLEN + 8 /* WEP */) { - if (macport == 7 && local->iw_mode == IW_MODE_MONITOR) { - if (len >= (u16) -14) { - hdr_len -= 65535 - len; - hdr_len--; - } - len = 0; - } else { - spin_unlock(&local->baplock); - printk(KERN_DEBUG "%s: Received frame with invalid " - "length 0x%04x\n", dev->name, len); - hostap_dump_rx_header(dev->name, &rxdesc); - goto rx_dropped; - } - } - - skb = dev_alloc_skb(len + hdr_len); - if (!skb) { - spin_unlock(&local->baplock); - printk(KERN_DEBUG "%s: RX failed to allocate skb\n", - dev->name); - goto rx_dropped; - } - skb->dev = dev; - memcpy(skb_put(skb, hdr_len), &rxdesc, hdr_len); - - if (len > 0) - res = hfa384x_from_bap(dev, BAP0, skb_put(skb, len), len); - spin_unlock(&local->baplock); - if (res) { - printk(KERN_DEBUG "%s: RX failed to read " - "frame data\n", dev->name); - goto rx_dropped; - } - - skb_queue_tail(&local->rx_list, skb); - tasklet_schedule(&local->rx_tasklet); - - rx_exit: - prism2_callback(local, PRISM2_CALLBACK_RX_END); - if (!rx_pending) { - HFA384X_OUTW(HFA384X_EV_RX, HFA384X_EVACK_OFF); - } - - return; - - rx_dropped: - dev->stats.rx_dropped++; - if (skb) - dev_kfree_skb(skb); - goto rx_exit; -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_rx_skb(local_info_t *local, struct sk_buff *skb) -{ - struct hfa384x_rx_frame *rxdesc; - struct net_device *dev = skb->dev; - struct hostap_80211_rx_status stats; - int hdrlen, rx_hdrlen; - - rx_hdrlen = sizeof(*rxdesc); - if (skb->len < sizeof(*rxdesc)) { - /* Allow monitor mode to receive shorter frames */ - if (local->iw_mode == IW_MODE_MONITOR && - skb->len >= sizeof(*rxdesc) - 30) { - rx_hdrlen = skb->len; - } else { - dev_kfree_skb(skb); - return; - } - } - - rxdesc = (struct hfa384x_rx_frame *) skb->data; - - if (local->frame_dump & PRISM2_DUMP_RX_HDR && - skb->len >= sizeof(*rxdesc)) - hostap_dump_rx_header(dev->name, rxdesc); - - if (le16_to_cpu(rxdesc->status) & HFA384X_RX_STATUS_FCSERR && - (!local->monitor_allow_fcserr || - local->iw_mode != IW_MODE_MONITOR)) - goto drop; - - if (skb->len > PRISM2_DATA_MAXLEN) { - printk(KERN_DEBUG "%s: RX: len(%d) > MAX(%d)\n", - dev->name, skb->len, PRISM2_DATA_MAXLEN); - goto drop; - } - - stats.mac_time = le32_to_cpu(rxdesc->time); - stats.signal = rxdesc->signal - local->rssi_to_dBm; - stats.noise = rxdesc->silence - local->rssi_to_dBm; - stats.rate = rxdesc->rate; - - /* Convert Prism2 RX structure into IEEE 802.11 header */ - hdrlen = hostap_80211_get_hdrlen(rxdesc->frame_control); - if (hdrlen > rx_hdrlen) - hdrlen = rx_hdrlen; - - memmove(skb_pull(skb, rx_hdrlen - hdrlen), - &rxdesc->frame_control, hdrlen); - - hostap_80211_rx(dev, skb, &stats); - return; - - drop: - dev_kfree_skb(skb); -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_rx_tasklet(unsigned long data) -{ - local_info_t *local = (local_info_t *) data; - struct sk_buff *skb; - - while ((skb = skb_dequeue(&local->rx_list)) != NULL) - hostap_rx_skb(local, skb); -} - - -/* Called only from hardware IRQ */ -static void prism2_alloc_ev(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - int idx; - u16 fid; - - iface = netdev_priv(dev); - local = iface->local; - - fid = prism2_read_fid_reg(dev, HFA384X_ALLOCFID_OFF); - - PDEBUG(DEBUG_FID, "FID: interrupt: ALLOC - fid=0x%04x\n", fid); - - spin_lock(&local->txfidlock); - idx = local->next_alloc; - - do { - if (local->txfid[idx] == fid) { - PDEBUG(DEBUG_FID, "FID: found matching txfid[%d]\n", - idx); - -#ifndef final_version - if (local->intransmitfid[idx] == PRISM2_TXFID_EMPTY) - printk("Already released txfid found at idx " - "%d\n", idx); - if (local->intransmitfid[idx] == PRISM2_TXFID_RESERVED) - printk("Already reserved txfid found at idx " - "%d\n", idx); -#endif - local->intransmitfid[idx] = PRISM2_TXFID_EMPTY; - idx++; - local->next_alloc = idx >= PRISM2_TXFID_COUNT ? 0 : - idx; - - if (!test_bit(HOSTAP_BITS_TRANSMIT, &local->bits) && - netif_queue_stopped(dev)) - netif_wake_queue(dev); - - spin_unlock(&local->txfidlock); - return; - } - - idx++; - if (idx >= PRISM2_TXFID_COUNT) - idx = 0; - } while (idx != local->next_alloc); - - printk(KERN_WARNING "%s: could not find matching txfid (0x%04x, new " - "read 0x%04x) for alloc event\n", dev->name, fid, - HFA384X_INW(HFA384X_ALLOCFID_OFF)); - printk(KERN_DEBUG "TXFIDs:"); - for (idx = 0; idx < PRISM2_TXFID_COUNT; idx++) - printk(" %04x[%04x]", local->txfid[idx], - local->intransmitfid[idx]); - printk("\n"); - spin_unlock(&local->txfidlock); - - /* FIX: should probably schedule reset; reference to one txfid was lost - * completely.. Bad things will happen if we run out of txfids - * Actually, this will cause netdev watchdog to notice TX timeout and - * then card reset after all txfids have been leaked. */ -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_tx_callback(local_info_t *local, - struct hfa384x_tx_frame *txdesc, int ok, - char *payload) -{ - u16 sw_support, hdrlen, len; - struct sk_buff *skb; - struct hostap_tx_callback_info *cb; - - /* Make sure that frame was from us. */ - if (memcmp(txdesc->addr2, local->dev->dev_addr, ETH_ALEN)) { - printk(KERN_DEBUG "%s: TX callback - foreign frame\n", - local->dev->name); - return; - } - - sw_support = le32_to_cpu(txdesc->sw_support); - - spin_lock(&local->lock); - cb = local->tx_callback; - while (cb != NULL && cb->idx != sw_support) - cb = cb->next; - spin_unlock(&local->lock); - - if (cb == NULL) { - printk(KERN_DEBUG "%s: could not find TX callback (idx %d)\n", - local->dev->name, sw_support); - return; - } - - hdrlen = hostap_80211_get_hdrlen(txdesc->frame_control); - len = le16_to_cpu(txdesc->data_len); - skb = dev_alloc_skb(hdrlen + len); - if (skb == NULL) { - printk(KERN_DEBUG "%s: hostap_tx_callback failed to allocate " - "skb\n", local->dev->name); - return; - } - - memcpy(skb_put(skb, hdrlen), (void *) &txdesc->frame_control, hdrlen); - if (payload) - memcpy(skb_put(skb, len), payload, len); - - skb->dev = local->dev; - skb_reset_mac_header(skb); - - cb->func(skb, ok, cb->data); -} - - -/* Called only as a tasklet (software IRQ) */ -static int hostap_tx_compl_read(local_info_t *local, int error, - struct hfa384x_tx_frame *txdesc, - char **payload) -{ - u16 fid, len; - int res, ret = 0; - struct net_device *dev = local->dev; - - fid = prism2_read_fid_reg(dev, HFA384X_TXCOMPLFID_OFF); - - PDEBUG(DEBUG_FID, "interrupt: TX (err=%d) - fid=0x%04x\n", fid, error); - - spin_lock(&local->baplock); - res = hfa384x_setup_bap(dev, BAP0, fid, 0); - if (!res) - res = hfa384x_from_bap(dev, BAP0, txdesc, sizeof(*txdesc)); - if (res) { - PDEBUG(DEBUG_EXTRA, "%s: TX (err=%d) - fid=0x%04x - could not " - "read txdesc\n", dev->name, error, fid); - if (res == -ETIMEDOUT) { - schedule_work(&local->reset_queue); - } - ret = -1; - goto fail; - } - if (txdesc->sw_support) { - len = le16_to_cpu(txdesc->data_len); - if (len < PRISM2_DATA_MAXLEN) { - *payload = kmalloc(len, GFP_ATOMIC); - if (*payload == NULL || - hfa384x_from_bap(dev, BAP0, *payload, len)) { - PDEBUG(DEBUG_EXTRA, "%s: could not read TX " - "frame payload\n", dev->name); - kfree(*payload); - *payload = NULL; - ret = -1; - goto fail; - } - } - } - - fail: - spin_unlock(&local->baplock); - - return ret; -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_tx_ev(local_info_t *local) -{ - struct net_device *dev = local->dev; - char *payload = NULL; - struct hfa384x_tx_frame txdesc; - - if (hostap_tx_compl_read(local, 0, &txdesc, &payload)) - goto fail; - - if (local->frame_dump & PRISM2_DUMP_TX_HDR) { - PDEBUG(DEBUG_EXTRA, "%s: TX - status=0x%04x " - "retry_count=%d tx_rate=%d seq_ctrl=%d " - "duration_id=%d\n", - dev->name, le16_to_cpu(txdesc.status), - txdesc.retry_count, txdesc.tx_rate, - le16_to_cpu(txdesc.seq_ctrl), - le16_to_cpu(txdesc.duration_id)); - } - - if (txdesc.sw_support) - hostap_tx_callback(local, &txdesc, 1, payload); - kfree(payload); - - fail: - HFA384X_OUTW(HFA384X_EV_TX, HFA384X_EVACK_OFF); -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_sta_tx_exc_tasklet(unsigned long data) -{ - local_info_t *local = (local_info_t *) data; - struct sk_buff *skb; - - while ((skb = skb_dequeue(&local->sta_tx_exc_list)) != NULL) { - struct hfa384x_tx_frame *txdesc = - (struct hfa384x_tx_frame *) skb->data; - - if (skb->len >= sizeof(*txdesc)) { - /* Convert Prism2 RX structure into IEEE 802.11 header - */ - int hdrlen = hostap_80211_get_hdrlen(txdesc->frame_control); - memmove(skb_pull(skb, sizeof(*txdesc) - hdrlen), - &txdesc->frame_control, hdrlen); - - hostap_handle_sta_tx_exc(local, skb); - } - dev_kfree_skb(skb); - } -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_txexc(local_info_t *local) -{ - struct net_device *dev = local->dev; - u16 status, fc; - int show_dump, res; - char *payload = NULL; - struct hfa384x_tx_frame txdesc; - - show_dump = local->frame_dump & PRISM2_DUMP_TXEXC_HDR; - dev->stats.tx_errors++; - - res = hostap_tx_compl_read(local, 1, &txdesc, &payload); - HFA384X_OUTW(HFA384X_EV_TXEXC, HFA384X_EVACK_OFF); - if (res) - return; - - status = le16_to_cpu(txdesc.status); - - /* We produce a TXDROP event only for retry or lifetime - * exceeded, because that's the only status that really mean - * that this particular node went away. - * Other errors means that *we* screwed up. - Jean II */ - if (status & (HFA384X_TX_STATUS_RETRYERR | HFA384X_TX_STATUS_AGEDERR)) - { - union iwreq_data wrqu; - - /* Copy 802.11 dest address. */ - memcpy(wrqu.addr.sa_data, txdesc.addr1, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); - } else - show_dump = 1; - - if (local->iw_mode == IW_MODE_MASTER || - local->iw_mode == IW_MODE_REPEAT || - local->wds_type & HOSTAP_WDS_AP_CLIENT) { - struct sk_buff *skb; - skb = dev_alloc_skb(sizeof(txdesc)); - if (skb) { - memcpy(skb_put(skb, sizeof(txdesc)), &txdesc, - sizeof(txdesc)); - skb_queue_tail(&local->sta_tx_exc_list, skb); - tasklet_schedule(&local->sta_tx_exc_tasklet); - } - } - - if (txdesc.sw_support) - hostap_tx_callback(local, &txdesc, 0, payload); - kfree(payload); - - if (!show_dump) - return; - - PDEBUG(DEBUG_EXTRA, "%s: TXEXC - status=0x%04x (%s%s%s%s)" - " tx_control=%04x\n", - dev->name, status, - status & HFA384X_TX_STATUS_RETRYERR ? "[RetryErr]" : "", - status & HFA384X_TX_STATUS_AGEDERR ? "[AgedErr]" : "", - status & HFA384X_TX_STATUS_DISCON ? "[Discon]" : "", - status & HFA384X_TX_STATUS_FORMERR ? "[FormErr]" : "", - le16_to_cpu(txdesc.tx_control)); - - fc = le16_to_cpu(txdesc.frame_control); - PDEBUG(DEBUG_EXTRA, " retry_count=%d tx_rate=%d fc=0x%04x " - "(%s%s%s::%d%s%s)\n", - txdesc.retry_count, txdesc.tx_rate, fc, - ieee80211_is_mgmt(txdesc.frame_control) ? "Mgmt" : "", - ieee80211_is_ctl(txdesc.frame_control) ? "Ctrl" : "", - ieee80211_is_data(txdesc.frame_control) ? "Data" : "", - (fc & IEEE80211_FCTL_STYPE) >> 4, - ieee80211_has_tods(txdesc.frame_control) ? " ToDS" : "", - ieee80211_has_fromds(txdesc.frame_control) ? " FromDS" : ""); - PDEBUG(DEBUG_EXTRA, " A1=%pM A2=%pM A3=%pM A4=%pM\n", - txdesc.addr1, txdesc.addr2, - txdesc.addr3, txdesc.addr4); -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_info_tasklet(unsigned long data) -{ - local_info_t *local = (local_info_t *) data; - struct sk_buff *skb; - - while ((skb = skb_dequeue(&local->info_list)) != NULL) { - hostap_info_process(local, skb); - dev_kfree_skb(skb); - } -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info(local_info_t *local) -{ - struct net_device *dev = local->dev; - u16 fid; - int res, left; - struct hfa384x_info_frame info; - struct sk_buff *skb; - - fid = HFA384X_INW(HFA384X_INFOFID_OFF); - - spin_lock(&local->baplock); - res = hfa384x_setup_bap(dev, BAP0, fid, 0); - if (!res) - res = hfa384x_from_bap(dev, BAP0, &info, sizeof(info)); - if (res) { - spin_unlock(&local->baplock); - printk(KERN_DEBUG "Could not get info frame (fid=0x%04x)\n", - fid); - if (res == -ETIMEDOUT) { - schedule_work(&local->reset_queue); - } - goto out; - } - - left = (le16_to_cpu(info.len) - 1) * 2; - - if (info.len & cpu_to_le16(0x8000) || info.len == 0 || left > 2060) { - /* data register seems to give 0x8000 in some error cases even - * though busy bit is not set in offset register; - * in addition, length must be at least 1 due to type field */ - spin_unlock(&local->baplock); - printk(KERN_DEBUG "%s: Received info frame with invalid " - "length 0x%04x (type 0x%04x)\n", dev->name, - le16_to_cpu(info.len), le16_to_cpu(info.type)); - goto out; - } - - skb = dev_alloc_skb(sizeof(info) + left); - if (skb == NULL) { - spin_unlock(&local->baplock); - printk(KERN_DEBUG "%s: Could not allocate skb for info " - "frame\n", dev->name); - goto out; - } - - memcpy(skb_put(skb, sizeof(info)), &info, sizeof(info)); - if (left > 0 && hfa384x_from_bap(dev, BAP0, skb_put(skb, left), left)) - { - spin_unlock(&local->baplock); - printk(KERN_WARNING "%s: Info frame read failed (fid=0x%04x, " - "len=0x%04x, type=0x%04x\n", dev->name, fid, - le16_to_cpu(info.len), le16_to_cpu(info.type)); - dev_kfree_skb(skb); - goto out; - } - spin_unlock(&local->baplock); - - skb_queue_tail(&local->info_list, skb); - tasklet_schedule(&local->info_tasklet); - - out: - HFA384X_OUTW(HFA384X_EV_INFO, HFA384X_EVACK_OFF); -} - - -/* Called only as a tasklet (software IRQ) */ -static void hostap_bap_tasklet(unsigned long data) -{ - local_info_t *local = (local_info_t *) data; - struct net_device *dev = local->dev; - u16 ev; - int frames = 30; - - if (local->func->card_present && !local->func->card_present(local)) - return; - - set_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits); - - /* Process all pending BAP events without generating new interrupts - * for them */ - while (frames-- > 0) { - ev = HFA384X_INW(HFA384X_EVSTAT_OFF); - if (ev == 0xffff || !(ev & HFA384X_BAP0_EVENTS)) - break; - if (ev & HFA384X_EV_RX) - prism2_rx(local); - if (ev & HFA384X_EV_INFO) - prism2_info(local); - if (ev & HFA384X_EV_TX) - prism2_tx_ev(local); - if (ev & HFA384X_EV_TXEXC) - prism2_txexc(local); - } - - set_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits); - clear_bit(HOSTAP_BITS_BAP_TASKLET, &local->bits); - - /* Enable interrupts for new BAP events */ - hfa384x_events_all(dev); - clear_bit(HOSTAP_BITS_BAP_TASKLET2, &local->bits); -} - - -/* Called only from hardware IRQ */ -static void prism2_infdrop(struct net_device *dev) -{ - static unsigned long last_inquire = 0; - - PDEBUG(DEBUG_EXTRA, "%s: INFDROP event\n", dev->name); - - /* some firmware versions seem to get stuck with - * full CommTallies in high traffic load cases; every - * packet will then cause INFDROP event and CommTallies - * info frame will not be sent automatically. Try to - * get out of this state by inquiring CommTallies. */ - if (!last_inquire || time_after(jiffies, last_inquire + HZ)) { - hfa384x_cmd_callback(dev, HFA384X_CMDCODE_INQUIRE, - HFA384X_INFO_COMMTALLIES, NULL, 0); - last_inquire = jiffies; - } -} - - -/* Called only from hardware IRQ */ -static void prism2_ev_tick(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - u16 evstat, inten; - static int prev_stuck = 0; - - iface = netdev_priv(dev); - local = iface->local; - - if (time_after(jiffies, local->last_tick_timer + 5 * HZ) && - local->last_tick_timer) { - evstat = HFA384X_INW(HFA384X_EVSTAT_OFF); - inten = HFA384X_INW(HFA384X_INTEN_OFF); - if (!prev_stuck) { - printk(KERN_INFO "%s: SW TICK stuck? " - "bits=0x%lx EvStat=%04x IntEn=%04x\n", - dev->name, local->bits, evstat, inten); - } - local->sw_tick_stuck++; - if ((evstat & HFA384X_BAP0_EVENTS) && - (inten & HFA384X_BAP0_EVENTS)) { - printk(KERN_INFO "%s: trying to recover from IRQ " - "hang\n", dev->name); - hfa384x_events_no_bap0(dev); - } - prev_stuck = 1; - } else - prev_stuck = 0; -} - - -/* Called only from hardware IRQ */ -static void prism2_check_magic(local_info_t *local) -{ - /* at least PCI Prism2.5 with bus mastering seems to sometimes - * return 0x0000 in SWSUPPORT0 for unknown reason, but re-reading the - * register once or twice seems to get the correct value.. PCI cards - * cannot anyway be removed during normal operation, so there is not - * really any need for this verification with them. */ - -#ifndef PRISM2_PCI -#ifndef final_version - static unsigned long last_magic_err = 0; - struct net_device *dev = local->dev; - - if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != HFA384X_MAGIC) { - if (!local->hw_ready) - return; - HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); - if (time_after(jiffies, last_magic_err + 10 * HZ)) { - printk("%s: Interrupt, but SWSUPPORT0 does not match: " - "%04X != %04X - card removed?\n", dev->name, - HFA384X_INW(HFA384X_SWSUPPORT0_OFF), - HFA384X_MAGIC); - last_magic_err = jiffies; - } else if (net_ratelimit()) { - printk(KERN_DEBUG "%s: interrupt - SWSUPPORT0=%04x " - "MAGIC=%04x\n", dev->name, - HFA384X_INW(HFA384X_SWSUPPORT0_OFF), - HFA384X_MAGIC); - } - if (HFA384X_INW(HFA384X_SWSUPPORT0_OFF) != 0xffff) - schedule_work(&local->reset_queue); - return; - } -#endif /* final_version */ -#endif /* !PRISM2_PCI */ -} - - -/* Called only from hardware IRQ */ -static irqreturn_t prism2_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct hostap_interface *iface; - local_info_t *local; - int events = 0; - u16 ev; - - iface = netdev_priv(dev); - local = iface->local; - - /* Detect early interrupt before driver is fully configued */ - spin_lock(&local->irq_init_lock); - if (!dev->base_addr) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: Interrupt, but dev not configured\n", - dev->name); - } - spin_unlock(&local->irq_init_lock); - return IRQ_HANDLED; - } - spin_unlock(&local->irq_init_lock); - - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 0); - - if (local->func->card_present && !local->func->card_present(local)) { - if (net_ratelimit()) { - printk(KERN_DEBUG "%s: Interrupt, but dev not OK\n", - dev->name); - } - return IRQ_HANDLED; - } - - prism2_check_magic(local); - - for (;;) { - ev = HFA384X_INW(HFA384X_EVSTAT_OFF); - if (ev == 0xffff) { - if (local->shutdown) - return IRQ_HANDLED; - HFA384X_OUTW(0xffff, HFA384X_EVACK_OFF); - printk(KERN_DEBUG "%s: prism2_interrupt: ev=0xffff\n", - dev->name); - return IRQ_HANDLED; - } - - ev &= HFA384X_INW(HFA384X_INTEN_OFF); - if (ev == 0) - break; - - if (ev & HFA384X_EV_CMD) { - prism2_cmd_ev(dev); - } - - /* Above events are needed even before hw is ready, but other - * events should be skipped during initialization. This may - * change for AllocEv if allocate_fid is implemented without - * busy waiting. */ - if (!local->hw_ready || local->hw_resetting || - !local->dev_enabled) { - ev = HFA384X_INW(HFA384X_EVSTAT_OFF); - if (ev & HFA384X_EV_CMD) - goto next_event; - if ((ev & HFA384X_EVENT_MASK) == 0) - return IRQ_HANDLED; - if (local->dev_enabled && (ev & ~HFA384X_EV_TICK) && - net_ratelimit()) { - printk(KERN_DEBUG "%s: prism2_interrupt: hw " - "not ready; skipping events 0x%04x " - "(IntEn=0x%04x)%s%s%s\n", - dev->name, ev, - HFA384X_INW(HFA384X_INTEN_OFF), - !local->hw_ready ? " (!hw_ready)" : "", - local->hw_resetting ? - " (hw_resetting)" : "", - !local->dev_enabled ? - " (!dev_enabled)" : ""); - } - HFA384X_OUTW(ev, HFA384X_EVACK_OFF); - return IRQ_HANDLED; - } - - if (ev & HFA384X_EV_TICK) { - prism2_ev_tick(dev); - HFA384X_OUTW(HFA384X_EV_TICK, HFA384X_EVACK_OFF); - } - - if (ev & HFA384X_EV_ALLOC) { - prism2_alloc_ev(dev); - HFA384X_OUTW(HFA384X_EV_ALLOC, HFA384X_EVACK_OFF); - } - - /* Reading data from the card is quite time consuming, so do it - * in tasklets. TX, TXEXC, RX, and INFO events will be ACKed - * and unmasked after needed data has been read completely. */ - if (ev & HFA384X_BAP0_EVENTS) { - hfa384x_events_no_bap0(dev); - tasklet_schedule(&local->bap_tasklet); - } - -#ifndef final_version - if (ev & HFA384X_EV_WTERR) { - PDEBUG(DEBUG_EXTRA, "%s: WTERR event\n", dev->name); - HFA384X_OUTW(HFA384X_EV_WTERR, HFA384X_EVACK_OFF); - } -#endif /* final_version */ - - if (ev & HFA384X_EV_INFDROP) { - prism2_infdrop(dev); - HFA384X_OUTW(HFA384X_EV_INFDROP, HFA384X_EVACK_OFF); - } - - next_event: - events++; - if (events >= PRISM2_MAX_INTERRUPT_EVENTS) { - PDEBUG(DEBUG_EXTRA, "prism2_interrupt: >%d events " - "(EvStat=0x%04x)\n", - PRISM2_MAX_INTERRUPT_EVENTS, - HFA384X_INW(HFA384X_EVSTAT_OFF)); - break; - } - } - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INTERRUPT, 0, 1); - return IRQ_RETVAL(events); -} - - -static void prism2_check_sta_fw_version(local_info_t *local) -{ - struct hfa384x_comp_ident comp; - int id, variant, major, minor; - - if (hfa384x_get_rid(local->dev, HFA384X_RID_STAID, - &comp, sizeof(comp), 1) < 0) - return; - - local->fw_ap = 0; - id = le16_to_cpu(comp.id); - if (id != HFA384X_COMP_ID_STA) { - if (id == HFA384X_COMP_ID_FW_AP) - local->fw_ap = 1; - return; - } - - major = __le16_to_cpu(comp.major); - minor = __le16_to_cpu(comp.minor); - variant = __le16_to_cpu(comp.variant); - local->sta_fw_ver = PRISM2_FW_VER(major, minor, variant); - - /* Station firmware versions before 1.4.x seem to have a bug in - * firmware-based WEP encryption when using Host AP mode, so use - * host_encrypt as a default for them. Firmware version 1.4.9 is the - * first one that has been seen to produce correct encryption, but the - * bug might be fixed before that (although, at least 1.4.2 is broken). - */ - local->fw_encrypt_ok = local->sta_fw_ver >= PRISM2_FW_VER(1,4,9); - - if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt && - !local->fw_encrypt_ok) { - printk(KERN_DEBUG "%s: defaulting to host-based encryption as " - "a workaround for firmware bug in Host AP mode WEP\n", - local->dev->name); - local->host_encrypt = 1; - } - - /* IEEE 802.11 standard compliant WDS frames (4 addresses) were broken - * in station firmware versions before 1.5.x. With these versions, the - * driver uses a workaround with bogus frame format (4th address after - * the payload). This is not compatible with other AP devices. Since - * the firmware bug is fixed in the latest station firmware versions, - * automatically enable standard compliant mode for cards using station - * firmware version 1.5.0 or newer. */ - if (local->sta_fw_ver >= PRISM2_FW_VER(1,5,0)) - local->wds_type |= HOSTAP_WDS_STANDARD_FRAME; - else { - printk(KERN_DEBUG "%s: defaulting to bogus WDS frame as a " - "workaround for firmware bug in Host AP mode WDS\n", - local->dev->name); - } - - hostap_check_sta_fw_version(local->ap, local->sta_fw_ver); -} - - -static void hostap_passive_scan(unsigned long data) -{ - local_info_t *local = (local_info_t *) data; - struct net_device *dev = local->dev; - u16 chan; - - if (local->passive_scan_interval <= 0) - return; - - if (local->passive_scan_state == PASSIVE_SCAN_LISTEN) { - int max_tries = 16; - - /* Even though host system does not really know when the WLAN - * MAC is sending frames, try to avoid changing channels for - * passive scanning when a host-generated frame is being - * transmitted */ - if (test_bit(HOSTAP_BITS_TRANSMIT, &local->bits)) { - printk(KERN_DEBUG "%s: passive scan detected pending " - "TX - delaying\n", dev->name); - local->passive_scan_timer.expires = jiffies + HZ / 10; - add_timer(&local->passive_scan_timer); - return; - } - - do { - local->passive_scan_channel++; - if (local->passive_scan_channel > 14) - local->passive_scan_channel = 1; - max_tries--; - } while (!(local->channel_mask & - (1 << (local->passive_scan_channel - 1))) && - max_tries > 0); - - if (max_tries == 0) { - printk(KERN_INFO "%s: no allowed passive scan channels" - " found\n", dev->name); - return; - } - - printk(KERN_DEBUG "%s: passive scan channel %d\n", - dev->name, local->passive_scan_channel); - chan = local->passive_scan_channel; - local->passive_scan_state = PASSIVE_SCAN_WAIT; - local->passive_scan_timer.expires = jiffies + HZ / 10; - } else { - chan = local->channel; - local->passive_scan_state = PASSIVE_SCAN_LISTEN; - local->passive_scan_timer.expires = jiffies + - local->passive_scan_interval * HZ; - } - - if (hfa384x_cmd_callback(dev, HFA384X_CMDCODE_TEST | - (HFA384X_TEST_CHANGE_CHANNEL << 8), - chan, NULL, 0)) - printk(KERN_ERR "%s: passive scan channel set %d " - "failed\n", dev->name, chan); - - add_timer(&local->passive_scan_timer); -} - - -/* Called only as a scheduled task when communications quality values should - * be updated. */ -static void handle_comms_qual_update(struct work_struct *work) -{ - local_info_t *local = - container_of(work, local_info_t, comms_qual_update); - prism2_update_comms_qual(local->dev); -} - - -/* Software watchdog - called as a timer. Hardware interrupt (Tick event) is - * used to monitor that local->last_tick_timer is being updated. If not, - * interrupt busy-loop is assumed and driver tries to recover by masking out - * some events. */ -static void hostap_tick_timer(unsigned long data) -{ - static unsigned long last_inquire = 0; - local_info_t *local = (local_info_t *) data; - local->last_tick_timer = jiffies; - - /* Inquire CommTallies every 10 seconds to keep the statistics updated - * more often during low load and when using 32-bit tallies. */ - if ((!last_inquire || time_after(jiffies, last_inquire + 10 * HZ)) && - !local->hw_downloading && local->hw_ready && - !local->hw_resetting && local->dev_enabled) { - hfa384x_cmd_callback(local->dev, HFA384X_CMDCODE_INQUIRE, - HFA384X_INFO_COMMTALLIES, NULL, 0); - last_inquire = jiffies; - } - - if ((local->last_comms_qual_update == 0 || - time_after(jiffies, local->last_comms_qual_update + 10 * HZ)) && - (local->iw_mode == IW_MODE_INFRA || - local->iw_mode == IW_MODE_ADHOC)) { - schedule_work(&local->comms_qual_update); - } - - local->tick_timer.expires = jiffies + 2 * HZ; - add_timer(&local->tick_timer); -} - - -#ifndef PRISM2_NO_PROCFS_DEBUG -static int prism2_registers_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - - if (off != 0) { - *eof = 1; - return 0; - } - -#define SHOW_REG(n) \ -p += sprintf(p, #n "=%04x\n", hfa384x_read_reg(local->dev, HFA384X_##n##_OFF)) - - SHOW_REG(CMD); - SHOW_REG(PARAM0); - SHOW_REG(PARAM1); - SHOW_REG(PARAM2); - SHOW_REG(STATUS); - SHOW_REG(RESP0); - SHOW_REG(RESP1); - SHOW_REG(RESP2); - SHOW_REG(INFOFID); - SHOW_REG(CONTROL); - SHOW_REG(SELECT0); - SHOW_REG(SELECT1); - SHOW_REG(OFFSET0); - SHOW_REG(OFFSET1); - SHOW_REG(RXFID); - SHOW_REG(ALLOCFID); - SHOW_REG(TXCOMPLFID); - SHOW_REG(SWSUPPORT0); - SHOW_REG(SWSUPPORT1); - SHOW_REG(SWSUPPORT2); - SHOW_REG(EVSTAT); - SHOW_REG(INTEN); - SHOW_REG(EVACK); - /* Do not read data registers, because they change the state of the - * MAC (offset += 2) */ - /* SHOW_REG(DATA0); */ - /* SHOW_REG(DATA1); */ - SHOW_REG(AUXPAGE); - SHOW_REG(AUXOFFSET); - /* SHOW_REG(AUXDATA); */ -#ifdef PRISM2_PCI - SHOW_REG(PCICOR); - SHOW_REG(PCIHCR); - SHOW_REG(PCI_M0_ADDRH); - SHOW_REG(PCI_M0_ADDRL); - SHOW_REG(PCI_M0_LEN); - SHOW_REG(PCI_M0_CTL); - SHOW_REG(PCI_STATUS); - SHOW_REG(PCI_M1_ADDRH); - SHOW_REG(PCI_M1_ADDRL); - SHOW_REG(PCI_M1_LEN); - SHOW_REG(PCI_M1_CTL); -#endif /* PRISM2_PCI */ - - return (p - page); -} -#endif /* PRISM2_NO_PROCFS_DEBUG */ - - -struct set_tim_data { - struct list_head list; - int aid; - int set; -}; - -static int prism2_set_tim(struct net_device *dev, int aid, int set) -{ - struct list_head *ptr; - struct set_tim_data *new_entry; - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - new_entry = kzalloc(sizeof(*new_entry), GFP_ATOMIC); - if (new_entry == NULL) { - printk(KERN_DEBUG "%s: prism2_set_tim: kmalloc failed\n", - local->dev->name); - return -ENOMEM; - } - new_entry->aid = aid; - new_entry->set = set; - - spin_lock_bh(&local->set_tim_lock); - list_for_each(ptr, &local->set_tim_list) { - struct set_tim_data *entry = - list_entry(ptr, struct set_tim_data, list); - if (entry->aid == aid) { - PDEBUG(DEBUG_PS2, "%s: prism2_set_tim: aid=%d " - "set=%d ==> %d\n", - local->dev->name, aid, entry->set, set); - entry->set = set; - kfree(new_entry); - new_entry = NULL; - break; - } - } - if (new_entry) - list_add_tail(&new_entry->list, &local->set_tim_list); - spin_unlock_bh(&local->set_tim_lock); - - schedule_work(&local->set_tim_queue); - - return 0; -} - - -static void handle_set_tim_queue(struct work_struct *work) -{ - local_info_t *local = container_of(work, local_info_t, set_tim_queue); - struct set_tim_data *entry; - u16 val; - - for (;;) { - entry = NULL; - spin_lock_bh(&local->set_tim_lock); - if (!list_empty(&local->set_tim_list)) { - entry = list_entry(local->set_tim_list.next, - struct set_tim_data, list); - list_del(&entry->list); - } - spin_unlock_bh(&local->set_tim_lock); - if (!entry) - break; - - PDEBUG(DEBUG_PS2, "%s: handle_set_tim_queue: aid=%d set=%d\n", - local->dev->name, entry->aid, entry->set); - - val = entry->aid; - if (entry->set) - val |= 0x8000; - if (hostap_set_word(local->dev, HFA384X_RID_CNFTIMCTRL, val)) { - printk(KERN_DEBUG "%s: set_tim failed (aid=%d " - "set=%d)\n", - local->dev->name, entry->aid, entry->set); - } - - kfree(entry); - } -} - - -static void prism2_clear_set_tim_queue(local_info_t *local) -{ - struct list_head *ptr, *n; - - list_for_each_safe(ptr, n, &local->set_tim_list) { - struct set_tim_data *entry; - entry = list_entry(ptr, struct set_tim_data, list); - list_del(&entry->list); - kfree(entry); - } -} - - -/* - * HostAP uses two layers of net devices, where the inner - * layer gets called all the time from the outer layer. - * This is a natural nesting, which needs a split lock type. - */ -static struct lock_class_key hostap_netdev_xmit_lock_key; -static struct lock_class_key hostap_netdev_addr_lock_key; - -static void prism2_set_lockdep_class_one(struct net_device *dev, - struct netdev_queue *txq, - void *_unused) -{ - lockdep_set_class(&txq->_xmit_lock, - &hostap_netdev_xmit_lock_key); -} - -static void prism2_set_lockdep_class(struct net_device *dev) -{ - lockdep_set_class(&dev->addr_list_lock, - &hostap_netdev_addr_lock_key); - netdev_for_each_tx_queue(dev, prism2_set_lockdep_class_one, NULL); -} - -static struct net_device * -prism2_init_local_data(struct prism2_helper_functions *funcs, int card_idx, - struct device *sdev) -{ - struct net_device *dev; - struct hostap_interface *iface; - struct local_info *local; - int len, i, ret; - - if (funcs == NULL) - return NULL; - - len = strlen(dev_template); - if (len >= IFNAMSIZ || strstr(dev_template, "%d") == NULL) { - printk(KERN_WARNING "hostap: Invalid dev_template='%s'\n", - dev_template); - return NULL; - } - - len = sizeof(struct hostap_interface) + - 3 + sizeof(struct local_info) + - 3 + sizeof(struct ap_data); - - dev = alloc_etherdev(len); - if (dev == NULL) - return NULL; - - iface = netdev_priv(dev); - local = (struct local_info *) ((((long) (iface + 1)) + 3) & ~3); - local->ap = (struct ap_data *) ((((long) (local + 1)) + 3) & ~3); - local->dev = iface->dev = dev; - iface->local = local; - iface->type = HOSTAP_INTERFACE_MASTER; - INIT_LIST_HEAD(&local->hostap_interfaces); - - local->hw_module = THIS_MODULE; - -#ifdef PRISM2_IO_DEBUG - local->io_debug_enabled = 1; -#endif /* PRISM2_IO_DEBUG */ - - local->func = funcs; - local->func->cmd = hfa384x_cmd; - local->func->read_regs = hfa384x_read_regs; - local->func->get_rid = hfa384x_get_rid; - local->func->set_rid = hfa384x_set_rid; - local->func->hw_enable = prism2_hw_enable; - local->func->hw_config = prism2_hw_config; - local->func->hw_reset = prism2_hw_reset; - local->func->hw_shutdown = prism2_hw_shutdown; - local->func->reset_port = prism2_reset_port; - local->func->schedule_reset = prism2_schedule_reset; -#ifdef PRISM2_DOWNLOAD_SUPPORT - local->func->read_aux = prism2_download_aux_dump; - local->func->download = prism2_download; -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - local->func->tx = prism2_tx_80211; - local->func->set_tim = prism2_set_tim; - local->func->need_tx_headroom = 0; /* no need to add txdesc in - * skb->data (FIX: maybe for DMA bus - * mastering? */ - - local->mtu = mtu; - - rwlock_init(&local->iface_lock); - spin_lock_init(&local->txfidlock); - spin_lock_init(&local->cmdlock); - spin_lock_init(&local->baplock); - spin_lock_init(&local->lock); - spin_lock_init(&local->irq_init_lock); - mutex_init(&local->rid_bap_mtx); - - if (card_idx < 0 || card_idx >= MAX_PARM_DEVICES) - card_idx = 0; - local->card_idx = card_idx; - - len = strlen(essid); - memcpy(local->essid, essid, - len > MAX_SSID_LEN ? MAX_SSID_LEN : len); - local->essid[MAX_SSID_LEN] = '\0'; - i = GET_INT_PARM(iw_mode, card_idx); - if ((i >= IW_MODE_ADHOC && i <= IW_MODE_REPEAT) || - i == IW_MODE_MONITOR) { - local->iw_mode = i; - } else { - printk(KERN_WARNING "prism2: Unknown iw_mode %d; using " - "IW_MODE_MASTER\n", i); - local->iw_mode = IW_MODE_MASTER; - } - local->channel = GET_INT_PARM(channel, card_idx); - local->beacon_int = GET_INT_PARM(beacon_int, card_idx); - local->dtim_period = GET_INT_PARM(dtim_period, card_idx); - local->wds_max_connections = 16; - local->tx_control = HFA384X_TX_CTRL_FLAGS; - local->manual_retry_count = -1; - local->rts_threshold = 2347; - local->fragm_threshold = 2346; - local->rssi_to_dBm = 100; /* default; to be overriden by - * cnfDbmAdjust, if available */ - local->auth_algs = PRISM2_AUTH_OPEN | PRISM2_AUTH_SHARED_KEY; - local->sram_type = -1; - local->scan_channel_mask = 0xffff; - local->monitor_type = PRISM2_MONITOR_RADIOTAP; - - /* Initialize task queue structures */ - INIT_WORK(&local->reset_queue, handle_reset_queue); - INIT_WORK(&local->set_multicast_list_queue, - hostap_set_multicast_list_queue); - - INIT_WORK(&local->set_tim_queue, handle_set_tim_queue); - INIT_LIST_HEAD(&local->set_tim_list); - spin_lock_init(&local->set_tim_lock); - - INIT_WORK(&local->comms_qual_update, handle_comms_qual_update); - - /* Initialize tasklets for handling hardware IRQ related operations - * outside hw IRQ handler */ -#define HOSTAP_TASKLET_INIT(q, f, d) \ -do { memset((q), 0, sizeof(*(q))); (q)->func = (f); (q)->data = (d); } \ -while (0) - HOSTAP_TASKLET_INIT(&local->bap_tasklet, hostap_bap_tasklet, - (unsigned long) local); - - HOSTAP_TASKLET_INIT(&local->info_tasklet, hostap_info_tasklet, - (unsigned long) local); - hostap_info_init(local); - - HOSTAP_TASKLET_INIT(&local->rx_tasklet, - hostap_rx_tasklet, (unsigned long) local); - skb_queue_head_init(&local->rx_list); - - HOSTAP_TASKLET_INIT(&local->sta_tx_exc_tasklet, - hostap_sta_tx_exc_tasklet, (unsigned long) local); - skb_queue_head_init(&local->sta_tx_exc_list); - - INIT_LIST_HEAD(&local->cmd_queue); - init_waitqueue_head(&local->hostscan_wq); - - lib80211_crypt_info_init(&local->crypt_info, dev->name, &local->lock); - - init_timer(&local->passive_scan_timer); - local->passive_scan_timer.data = (unsigned long) local; - local->passive_scan_timer.function = hostap_passive_scan; - - init_timer(&local->tick_timer); - local->tick_timer.data = (unsigned long) local; - local->tick_timer.function = hostap_tick_timer; - local->tick_timer.expires = jiffies + 2 * HZ; - add_timer(&local->tick_timer); - - INIT_LIST_HEAD(&local->bss_list); - - hostap_setup_dev(dev, local, HOSTAP_INTERFACE_MASTER); - - dev->type = ARPHRD_IEEE80211; - dev->header_ops = &hostap_80211_ops; - - rtnl_lock(); - ret = dev_alloc_name(dev, "wifi%d"); - SET_NETDEV_DEV(dev, sdev); - if (ret >= 0) - ret = register_netdevice(dev); - - prism2_set_lockdep_class(dev); - rtnl_unlock(); - if (ret < 0) { - printk(KERN_WARNING "%s: register netdevice failed!\n", - dev_info); - goto fail; - } - printk(KERN_INFO "%s: Registered netdevice %s\n", dev_info, dev->name); - - hostap_init_data(local); - return dev; - - fail: - free_netdev(dev); - return NULL; -} - - -static int hostap_hw_ready(struct net_device *dev) -{ - struct hostap_interface *iface; - struct local_info *local; - - iface = netdev_priv(dev); - local = iface->local; - local->ddev = hostap_add_interface(local, HOSTAP_INTERFACE_MAIN, 0, - "", dev_template); - - if (local->ddev) { - if (local->iw_mode == IW_MODE_INFRA || - local->iw_mode == IW_MODE_ADHOC) { - netif_carrier_off(local->dev); - netif_carrier_off(local->ddev); - } - hostap_init_proc(local); -#ifndef PRISM2_NO_PROCFS_DEBUG - create_proc_read_entry("registers", 0, local->proc, - prism2_registers_proc_read, local); -#endif /* PRISM2_NO_PROCFS_DEBUG */ - hostap_init_ap_proc(local); - return 0; - } - - return -1; -} - - -static void prism2_free_local_data(struct net_device *dev) -{ - struct hostap_tx_callback_info *tx_cb, *tx_cb_prev; - int i; - struct hostap_interface *iface; - struct local_info *local; - struct list_head *ptr, *n; - - if (dev == NULL) - return; - - iface = netdev_priv(dev); - local = iface->local; - - /* Unregister all netdevs before freeing local data. */ - list_for_each_safe(ptr, n, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - if (iface->type == HOSTAP_INTERFACE_MASTER) { - /* special handling for this interface below */ - continue; - } - hostap_remove_interface(iface->dev, 0, 1); - } - - unregister_netdev(local->dev); - - flush_scheduled_work(); - - lib80211_crypt_info_free(&local->crypt_info); - - if (timer_pending(&local->passive_scan_timer)) - del_timer(&local->passive_scan_timer); - - if (timer_pending(&local->tick_timer)) - del_timer(&local->tick_timer); - - prism2_clear_cmd_queue(local); - - skb_queue_purge(&local->info_list); - skb_queue_purge(&local->rx_list); - skb_queue_purge(&local->sta_tx_exc_list); - - if (local->dev_enabled) - prism2_callback(local, PRISM2_CALLBACK_DISABLE); - - if (local->ap != NULL) - hostap_free_data(local->ap); - -#ifndef PRISM2_NO_PROCFS_DEBUG - if (local->proc != NULL) - remove_proc_entry("registers", local->proc); -#endif /* PRISM2_NO_PROCFS_DEBUG */ - hostap_remove_proc(local); - - tx_cb = local->tx_callback; - while (tx_cb != NULL) { - tx_cb_prev = tx_cb; - tx_cb = tx_cb->next; - kfree(tx_cb_prev); - } - - hostap_set_hostapd(local, 0, 0); - hostap_set_hostapd_sta(local, 0, 0); - - for (i = 0; i < PRISM2_FRAG_CACHE_LEN; i++) { - if (local->frag_cache[i].skb != NULL) - dev_kfree_skb(local->frag_cache[i].skb); - } - -#ifdef PRISM2_DOWNLOAD_SUPPORT - prism2_download_free_data(local->dl_pri); - prism2_download_free_data(local->dl_sec); -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - - prism2_clear_set_tim_queue(local); - - list_for_each_safe(ptr, n, &local->bss_list) { - struct hostap_bss_info *bss = - list_entry(ptr, struct hostap_bss_info, list); - kfree(bss); - } - - kfree(local->pda); - kfree(local->last_scan_results); - kfree(local->generic_elem); - - free_netdev(local->dev); -} - - -#if (defined(PRISM2_PCI) && defined(CONFIG_PM)) || defined(PRISM2_PCCARD) -static void prism2_suspend(struct net_device *dev) -{ - struct hostap_interface *iface; - struct local_info *local; - union iwreq_data wrqu; - - iface = netdev_priv(dev); - local = iface->local; - - /* Send disconnect event, e.g., to trigger reassociation after resume - * if wpa_supplicant is used. */ - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); - - /* Disable hardware and firmware */ - prism2_hw_shutdown(dev, 0); -} -#endif /* (PRISM2_PCI && CONFIG_PM) || PRISM2_PCCARD */ - - -/* These might at some point be compiled separately and used as separate - * kernel modules or linked into one */ -#ifdef PRISM2_DOWNLOAD_SUPPORT -#include "hostap_download.c" -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - -#ifdef PRISM2_CALLBACK -/* External hostap_callback.c file can be used to, e.g., blink activity led. - * This can use platform specific code and must define prism2_callback() - * function (if PRISM2_CALLBACK is not defined, these function calls are not - * used. */ -#include "hostap_callback.c" -#endif /* PRISM2_CALLBACK */ diff --git a/drivers/net/wireless/hostap/hostap_info.c b/drivers/net/wireless/hostap/hostap_info.c deleted file mode 100644 index 4dfb40a84c96..000000000000 --- a/drivers/net/wireless/hostap/hostap_info.c +++ /dev/null @@ -1,505 +0,0 @@ -/* Host AP driver Info Frame processing (part of hostap.o module) */ - -#include -#include -#include "hostap_wlan.h" -#include "hostap.h" -#include "hostap_ap.h" - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info_commtallies16(local_info_t *local, unsigned char *buf, - int left) -{ - struct hfa384x_comm_tallies *tallies; - - if (left < sizeof(struct hfa384x_comm_tallies)) { - printk(KERN_DEBUG "%s: too short (len=%d) commtallies " - "info frame\n", local->dev->name, left); - return; - } - - tallies = (struct hfa384x_comm_tallies *) buf; -#define ADD_COMM_TALLIES(name) \ -local->comm_tallies.name += le16_to_cpu(tallies->name) - ADD_COMM_TALLIES(tx_unicast_frames); - ADD_COMM_TALLIES(tx_multicast_frames); - ADD_COMM_TALLIES(tx_fragments); - ADD_COMM_TALLIES(tx_unicast_octets); - ADD_COMM_TALLIES(tx_multicast_octets); - ADD_COMM_TALLIES(tx_deferred_transmissions); - ADD_COMM_TALLIES(tx_single_retry_frames); - ADD_COMM_TALLIES(tx_multiple_retry_frames); - ADD_COMM_TALLIES(tx_retry_limit_exceeded); - ADD_COMM_TALLIES(tx_discards); - ADD_COMM_TALLIES(rx_unicast_frames); - ADD_COMM_TALLIES(rx_multicast_frames); - ADD_COMM_TALLIES(rx_fragments); - ADD_COMM_TALLIES(rx_unicast_octets); - ADD_COMM_TALLIES(rx_multicast_octets); - ADD_COMM_TALLIES(rx_fcs_errors); - ADD_COMM_TALLIES(rx_discards_no_buffer); - ADD_COMM_TALLIES(tx_discards_wrong_sa); - ADD_COMM_TALLIES(rx_discards_wep_undecryptable); - ADD_COMM_TALLIES(rx_message_in_msg_fragments); - ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments); -#undef ADD_COMM_TALLIES -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info_commtallies32(local_info_t *local, unsigned char *buf, - int left) -{ - struct hfa384x_comm_tallies32 *tallies; - - if (left < sizeof(struct hfa384x_comm_tallies32)) { - printk(KERN_DEBUG "%s: too short (len=%d) commtallies32 " - "info frame\n", local->dev->name, left); - return; - } - - tallies = (struct hfa384x_comm_tallies32 *) buf; -#define ADD_COMM_TALLIES(name) \ -local->comm_tallies.name += le32_to_cpu(tallies->name) - ADD_COMM_TALLIES(tx_unicast_frames); - ADD_COMM_TALLIES(tx_multicast_frames); - ADD_COMM_TALLIES(tx_fragments); - ADD_COMM_TALLIES(tx_unicast_octets); - ADD_COMM_TALLIES(tx_multicast_octets); - ADD_COMM_TALLIES(tx_deferred_transmissions); - ADD_COMM_TALLIES(tx_single_retry_frames); - ADD_COMM_TALLIES(tx_multiple_retry_frames); - ADD_COMM_TALLIES(tx_retry_limit_exceeded); - ADD_COMM_TALLIES(tx_discards); - ADD_COMM_TALLIES(rx_unicast_frames); - ADD_COMM_TALLIES(rx_multicast_frames); - ADD_COMM_TALLIES(rx_fragments); - ADD_COMM_TALLIES(rx_unicast_octets); - ADD_COMM_TALLIES(rx_multicast_octets); - ADD_COMM_TALLIES(rx_fcs_errors); - ADD_COMM_TALLIES(rx_discards_no_buffer); - ADD_COMM_TALLIES(tx_discards_wrong_sa); - ADD_COMM_TALLIES(rx_discards_wep_undecryptable); - ADD_COMM_TALLIES(rx_message_in_msg_fragments); - ADD_COMM_TALLIES(rx_message_in_bad_msg_fragments); -#undef ADD_COMM_TALLIES -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info_commtallies(local_info_t *local, unsigned char *buf, - int left) -{ - if (local->tallies32) - prism2_info_commtallies32(local, buf, left); - else - prism2_info_commtallies16(local, buf, left); -} - - -#ifndef PRISM2_NO_STATION_MODES -#ifndef PRISM2_NO_DEBUG -static const char* hfa384x_linkstatus_str(u16 linkstatus) -{ - switch (linkstatus) { - case HFA384X_LINKSTATUS_CONNECTED: - return "Connected"; - case HFA384X_LINKSTATUS_DISCONNECTED: - return "Disconnected"; - case HFA384X_LINKSTATUS_AP_CHANGE: - return "Access point change"; - case HFA384X_LINKSTATUS_AP_OUT_OF_RANGE: - return "Access point out of range"; - case HFA384X_LINKSTATUS_AP_IN_RANGE: - return "Access point in range"; - case HFA384X_LINKSTATUS_ASSOC_FAILED: - return "Association failed"; - default: - return "Unknown"; - } -} -#endif /* PRISM2_NO_DEBUG */ - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info_linkstatus(local_info_t *local, unsigned char *buf, - int left) -{ - u16 val; - int non_sta_mode; - - /* Alloc new JoinRequests to occur since LinkStatus for the previous - * has been received */ - local->last_join_time = 0; - - if (left != 2) { - printk(KERN_DEBUG "%s: invalid linkstatus info frame " - "length %d\n", local->dev->name, left); - return; - } - - non_sta_mode = local->iw_mode == IW_MODE_MASTER || - local->iw_mode == IW_MODE_REPEAT || - local->iw_mode == IW_MODE_MONITOR; - - val = buf[0] | (buf[1] << 8); - if (!non_sta_mode || val != HFA384X_LINKSTATUS_DISCONNECTED) { - PDEBUG(DEBUG_EXTRA, "%s: LinkStatus=%d (%s)\n", - local->dev->name, val, hfa384x_linkstatus_str(val)); - } - - if (non_sta_mode) { - netif_carrier_on(local->dev); - netif_carrier_on(local->ddev); - return; - } - - /* Get current BSSID later in scheduled task */ - set_bit(PRISM2_INFO_PENDING_LINKSTATUS, &local->pending_info); - local->prev_link_status = val; - schedule_work(&local->info_queue); -} - - -static void prism2_host_roaming(local_info_t *local) -{ - struct hfa384x_join_request req; - struct net_device *dev = local->dev; - struct hfa384x_hostscan_result *selected, *entry; - int i; - unsigned long flags; - - if (local->last_join_time && - time_before(jiffies, local->last_join_time + 10 * HZ)) { - PDEBUG(DEBUG_EXTRA, "%s: last join request has not yet been " - "completed - waiting for it before issuing new one\n", - dev->name); - return; - } - - /* ScanResults are sorted: first ESS results in decreasing signal - * quality then IBSS results in similar order. - * Trivial roaming policy: just select the first entry. - * This could probably be improved by adding hysteresis to limit - * number of handoffs, etc. - * - * Could do periodic RID_SCANREQUEST or Inquire F101 to get new - * ScanResults */ - spin_lock_irqsave(&local->lock, flags); - if (local->last_scan_results == NULL || - local->last_scan_results_count == 0) { - spin_unlock_irqrestore(&local->lock, flags); - PDEBUG(DEBUG_EXTRA, "%s: no scan results for host roaming\n", - dev->name); - return; - } - - selected = &local->last_scan_results[0]; - - if (local->preferred_ap[0] || local->preferred_ap[1] || - local->preferred_ap[2] || local->preferred_ap[3] || - local->preferred_ap[4] || local->preferred_ap[5]) { - /* Try to find preferred AP */ - PDEBUG(DEBUG_EXTRA, "%s: Preferred AP BSSID %pM\n", - dev->name, local->preferred_ap); - for (i = 0; i < local->last_scan_results_count; i++) { - entry = &local->last_scan_results[i]; - if (memcmp(local->preferred_ap, entry->bssid, 6) == 0) - { - PDEBUG(DEBUG_EXTRA, "%s: using preferred AP " - "selection\n", dev->name); - selected = entry; - break; - } - } - } - - memcpy(req.bssid, selected->bssid, 6); - req.channel = selected->chid; - spin_unlock_irqrestore(&local->lock, flags); - - PDEBUG(DEBUG_EXTRA, "%s: JoinRequest: BSSID=%pM" - " channel=%d\n", - dev->name, req.bssid, le16_to_cpu(req.channel)); - if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req, - sizeof(req))) { - printk(KERN_DEBUG "%s: JoinRequest failed\n", dev->name); - } - local->last_join_time = jiffies; -} - - -static void hostap_report_scan_complete(local_info_t *local) -{ - union iwreq_data wrqu; - - /* Inform user space about new scan results (just empty event, - * SIOCGIWSCAN can be used to fetch data */ - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(local->dev, SIOCGIWSCAN, &wrqu, NULL); - - /* Allow SIOCGIWSCAN handling to occur since we have received - * scanning result */ - local->scan_timestamp = 0; -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info_scanresults(local_info_t *local, unsigned char *buf, - int left) -{ - u16 *pos; - int new_count, i; - unsigned long flags; - struct hfa384x_scan_result *res; - struct hfa384x_hostscan_result *results, *prev; - - if (left < 4) { - printk(KERN_DEBUG "%s: invalid scanresult info frame " - "length %d\n", local->dev->name, left); - return; - } - - pos = (u16 *) buf; - pos++; - pos++; - left -= 4; - - new_count = left / sizeof(struct hfa384x_scan_result); - results = kmalloc(new_count * sizeof(struct hfa384x_hostscan_result), - GFP_ATOMIC); - if (results == NULL) - return; - - /* Convert to hostscan result format. */ - res = (struct hfa384x_scan_result *) pos; - for (i = 0; i < new_count; i++) { - memcpy(&results[i], &res[i], - sizeof(struct hfa384x_scan_result)); - results[i].atim = 0; - } - - spin_lock_irqsave(&local->lock, flags); - local->last_scan_type = PRISM2_SCAN; - prev = local->last_scan_results; - local->last_scan_results = results; - local->last_scan_results_count = new_count; - spin_unlock_irqrestore(&local->lock, flags); - kfree(prev); - - hostap_report_scan_complete(local); - - /* Perform rest of ScanResults handling later in scheduled task */ - set_bit(PRISM2_INFO_PENDING_SCANRESULTS, &local->pending_info); - schedule_work(&local->info_queue); -} - - -/* Called only as a tasklet (software IRQ) */ -static void prism2_info_hostscanresults(local_info_t *local, - unsigned char *buf, int left) -{ - int i, result_size, copy_len, new_count; - struct hfa384x_hostscan_result *results, *prev; - unsigned long flags; - __le16 *pos; - u8 *ptr; - - wake_up_interruptible(&local->hostscan_wq); - - if (left < 4) { - printk(KERN_DEBUG "%s: invalid hostscanresult info frame " - "length %d\n", local->dev->name, left); - return; - } - - pos = (__le16 *) buf; - copy_len = result_size = le16_to_cpu(*pos); - if (result_size == 0) { - printk(KERN_DEBUG "%s: invalid result_size (0) in " - "hostscanresults\n", local->dev->name); - return; - } - if (copy_len > sizeof(struct hfa384x_hostscan_result)) - copy_len = sizeof(struct hfa384x_hostscan_result); - - pos++; - pos++; - left -= 4; - ptr = (u8 *) pos; - - new_count = left / result_size; - results = kcalloc(new_count, sizeof(struct hfa384x_hostscan_result), - GFP_ATOMIC); - if (results == NULL) - return; - - for (i = 0; i < new_count; i++) { - memcpy(&results[i], ptr, copy_len); - ptr += result_size; - left -= result_size; - } - - if (left) { - printk(KERN_DEBUG "%s: short HostScan result entry (%d/%d)\n", - local->dev->name, left, result_size); - } - - spin_lock_irqsave(&local->lock, flags); - local->last_scan_type = PRISM2_HOSTSCAN; - prev = local->last_scan_results; - local->last_scan_results = results; - local->last_scan_results_count = new_count; - spin_unlock_irqrestore(&local->lock, flags); - kfree(prev); - - hostap_report_scan_complete(local); -} -#endif /* PRISM2_NO_STATION_MODES */ - - -/* Called only as a tasklet (software IRQ) */ -void hostap_info_process(local_info_t *local, struct sk_buff *skb) -{ - struct hfa384x_info_frame *info; - unsigned char *buf; - int left; -#ifndef PRISM2_NO_DEBUG - int i; -#endif /* PRISM2_NO_DEBUG */ - - info = (struct hfa384x_info_frame *) skb->data; - buf = skb->data + sizeof(*info); - left = skb->len - sizeof(*info); - - switch (le16_to_cpu(info->type)) { - case HFA384X_INFO_COMMTALLIES: - prism2_info_commtallies(local, buf, left); - break; - -#ifndef PRISM2_NO_STATION_MODES - case HFA384X_INFO_LINKSTATUS: - prism2_info_linkstatus(local, buf, left); - break; - - case HFA384X_INFO_SCANRESULTS: - prism2_info_scanresults(local, buf, left); - break; - - case HFA384X_INFO_HOSTSCANRESULTS: - prism2_info_hostscanresults(local, buf, left); - break; -#endif /* PRISM2_NO_STATION_MODES */ - -#ifndef PRISM2_NO_DEBUG - default: - PDEBUG(DEBUG_EXTRA, "%s: INFO - len=%d type=0x%04x\n", - local->dev->name, le16_to_cpu(info->len), - le16_to_cpu(info->type)); - PDEBUG(DEBUG_EXTRA, "Unknown info frame:"); - for (i = 0; i < (left < 100 ? left : 100); i++) - PDEBUG2(DEBUG_EXTRA, " %02x", buf[i]); - PDEBUG2(DEBUG_EXTRA, "\n"); - break; -#endif /* PRISM2_NO_DEBUG */ - } -} - - -#ifndef PRISM2_NO_STATION_MODES -static void handle_info_queue_linkstatus(local_info_t *local) -{ - int val = local->prev_link_status; - int connected; - union iwreq_data wrqu; - - connected = - val == HFA384X_LINKSTATUS_CONNECTED || - val == HFA384X_LINKSTATUS_AP_CHANGE || - val == HFA384X_LINKSTATUS_AP_IN_RANGE; - - if (local->func->get_rid(local->dev, HFA384X_RID_CURRENTBSSID, - local->bssid, ETH_ALEN, 1) < 0) { - printk(KERN_DEBUG "%s: could not read CURRENTBSSID after " - "LinkStatus event\n", local->dev->name); - } else { - PDEBUG(DEBUG_EXTRA, "%s: LinkStatus: BSSID=%pM\n", - local->dev->name, - (unsigned char *) local->bssid); - if (local->wds_type & HOSTAP_WDS_AP_CLIENT) - hostap_add_sta(local->ap, local->bssid); - } - - /* Get BSSID if we have a valid AP address */ - if (connected) { - netif_carrier_on(local->dev); - netif_carrier_on(local->ddev); - memcpy(wrqu.ap_addr.sa_data, local->bssid, ETH_ALEN); - } else { - netif_carrier_off(local->dev); - netif_carrier_off(local->ddev); - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - } - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - /* - * Filter out sequential disconnect events in order not to cause a - * flood of SIOCGIWAP events that have a race condition with EAPOL - * frames and can confuse wpa_supplicant about the current association - * status. - */ - if (connected || local->prev_linkstatus_connected) - wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); - local->prev_linkstatus_connected = connected; -} - - -static void handle_info_queue_scanresults(local_info_t *local) -{ - if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) - prism2_host_roaming(local); - - if (local->host_roaming == 2 && local->iw_mode == IW_MODE_INFRA && - memcmp(local->preferred_ap, "\x00\x00\x00\x00\x00\x00", - ETH_ALEN) != 0) { - /* - * Firmware seems to be getting into odd state in host_roaming - * mode 2 when hostscan is used without join command, so try - * to fix this by re-joining the current AP. This does not - * actually trigger a new association if the current AP is - * still in the scan results. - */ - prism2_host_roaming(local); - } -} - - -/* Called only as scheduled task after receiving info frames (used to avoid - * pending too much time in HW IRQ handler). */ -static void handle_info_queue(struct work_struct *work) -{ - local_info_t *local = container_of(work, local_info_t, info_queue); - - if (test_and_clear_bit(PRISM2_INFO_PENDING_LINKSTATUS, - &local->pending_info)) - handle_info_queue_linkstatus(local); - - if (test_and_clear_bit(PRISM2_INFO_PENDING_SCANRESULTS, - &local->pending_info)) - handle_info_queue_scanresults(local); -} -#endif /* PRISM2_NO_STATION_MODES */ - - -void hostap_info_init(local_info_t *local) -{ - skb_queue_head_init(&local->info_list); -#ifndef PRISM2_NO_STATION_MODES - INIT_WORK(&local->info_queue, handle_info_queue); -#endif /* PRISM2_NO_STATION_MODES */ -} - - -EXPORT_SYMBOL(hostap_info_init); -EXPORT_SYMBOL(hostap_info_process); diff --git a/drivers/net/wireless/hostap/hostap_ioctl.c b/drivers/net/wireless/hostap/hostap_ioctl.c deleted file mode 100644 index 9419cebca8a5..000000000000 --- a/drivers/net/wireless/hostap/hostap_ioctl.c +++ /dev/null @@ -1,4058 +0,0 @@ -/* ioctl() (mostly Linux Wireless Extensions) routines for Host AP driver */ - -#include -#include -#include -#include -#include - -#include "hostap_wlan.h" -#include "hostap.h" -#include "hostap_ap.h" - -static struct iw_statistics *hostap_get_wireless_stats(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct iw_statistics *wstats; - - iface = netdev_priv(dev); - local = iface->local; - - /* Why are we doing that ? Jean II */ - if (iface->type != HOSTAP_INTERFACE_MAIN) - return NULL; - - wstats = &local->wstats; - - wstats->status = 0; - wstats->discard.code = - local->comm_tallies.rx_discards_wep_undecryptable; - wstats->discard.misc = - local->comm_tallies.rx_fcs_errors + - local->comm_tallies.rx_discards_no_buffer + - local->comm_tallies.tx_discards_wrong_sa; - - wstats->discard.retries = - local->comm_tallies.tx_retry_limit_exceeded; - wstats->discard.fragment = - local->comm_tallies.rx_message_in_bad_msg_fragments; - - if (local->iw_mode != IW_MODE_MASTER && - local->iw_mode != IW_MODE_REPEAT) { - int update = 1; -#ifdef in_atomic - /* RID reading might sleep and it must not be called in - * interrupt context or while atomic. However, this - * function seems to be called while atomic (at least in Linux - * 2.5.59). Update signal quality values only if in suitable - * context. Otherwise, previous values read from tick timer - * will be used. */ - if (in_atomic()) - update = 0; -#endif /* in_atomic */ - - if (update && prism2_update_comms_qual(dev) == 0) - wstats->qual.updated = IW_QUAL_ALL_UPDATED | - IW_QUAL_DBM; - - wstats->qual.qual = local->comms_qual; - wstats->qual.level = local->avg_signal; - wstats->qual.noise = local->avg_noise; - } else { - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = IW_QUAL_ALL_INVALID; - } - - return wstats; -} - - -static int prism2_get_datarates(struct net_device *dev, u8 *rates) -{ - struct hostap_interface *iface; - local_info_t *local; - u8 buf[12]; - int len; - u16 val; - - iface = netdev_priv(dev); - local = iface->local; - - len = local->func->get_rid(dev, HFA384X_RID_SUPPORTEDDATARATES, buf, - sizeof(buf), 0); - if (len < 2) - return 0; - - val = le16_to_cpu(*(__le16 *) buf); /* string length */ - - if (len - 2 < val || val > 10) - return 0; - - memcpy(rates, buf + 2, val); - return val; -} - - -static int prism2_get_name(struct net_device *dev, - struct iw_request_info *info, - char *name, char *extra) -{ - u8 rates[10]; - int len, i, over2 = 0; - - len = prism2_get_datarates(dev, rates); - - for (i = 0; i < len; i++) { - if (rates[i] == 0x0b || rates[i] == 0x16) { - over2 = 1; - break; - } - } - - strcpy(name, over2 ? "IEEE 802.11b" : "IEEE 802.11-DS"); - - return 0; -} - - -static int prism2_ioctl_siwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *keybuf) -{ - struct hostap_interface *iface; - local_info_t *local; - int i; - struct lib80211_crypt_data **crypt; - - iface = netdev_priv(dev); - local = iface->local; - - i = erq->flags & IW_ENCODE_INDEX; - if (i < 1 || i > 4) - i = local->crypt_info.tx_keyidx; - else - i--; - if (i < 0 || i >= WEP_KEYS) - return -EINVAL; - - crypt = &local->crypt_info.crypt[i]; - - if (erq->flags & IW_ENCODE_DISABLED) { - if (*crypt) - lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); - goto done; - } - - if (*crypt != NULL && (*crypt)->ops != NULL && - strcmp((*crypt)->ops->name, "WEP") != 0) { - /* changing to use WEP; deinit previously used algorithm */ - lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); - } - - if (*crypt == NULL) { - struct lib80211_crypt_data *new_crypt; - - /* take WEP into use */ - new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), - GFP_KERNEL); - if (new_crypt == NULL) - return -ENOMEM; - new_crypt->ops = lib80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) { - request_module("lib80211_crypt_wep"); - new_crypt->ops = lib80211_get_crypto_ops("WEP"); - } - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = new_crypt->ops->init(i); - if (!new_crypt->ops || !new_crypt->priv) { - kfree(new_crypt); - new_crypt = NULL; - - printk(KERN_WARNING "%s: could not initialize WEP: " - "load module hostap_crypt_wep.o\n", - dev->name); - return -EOPNOTSUPP; - } - *crypt = new_crypt; - } - - if (erq->length > 0) { - int len = erq->length <= 5 ? 5 : 13; - int first = 1, j; - if (len > erq->length) - memset(keybuf + erq->length, 0, len - erq->length); - (*crypt)->ops->set_key(keybuf, len, NULL, (*crypt)->priv); - for (j = 0; j < WEP_KEYS; j++) { - if (j != i && local->crypt_info.crypt[j]) { - first = 0; - break; - } - } - if (first) - local->crypt_info.tx_keyidx = i; - } else { - /* No key data - just set the default TX key index */ - local->crypt_info.tx_keyidx = i; - } - - done: - local->open_wep = erq->flags & IW_ENCODE_OPEN; - - if (hostap_set_encryption(local)) { - printk(KERN_DEBUG "%s: set_encryption failed\n", dev->name); - return -EINVAL; - } - - /* Do not reset port0 if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. Prism2 documentation seem to require port reset - * after WEP configuration. However, keys are apparently changed at - * least in Managed mode. */ - if (local->iw_mode != IW_MODE_INFRA && local->func->reset_port(dev)) { - printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); - return -EINVAL; - } - - return 0; -} - - -static int prism2_ioctl_giwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *key) -{ - struct hostap_interface *iface; - local_info_t *local; - int i, len; - u16 val; - struct lib80211_crypt_data *crypt; - - iface = netdev_priv(dev); - local = iface->local; - - i = erq->flags & IW_ENCODE_INDEX; - if (i < 1 || i > 4) - i = local->crypt_info.tx_keyidx; - else - i--; - if (i < 0 || i >= WEP_KEYS) - return -EINVAL; - - crypt = local->crypt_info.crypt[i]; - erq->flags = i + 1; - - if (crypt == NULL || crypt->ops == NULL) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - - if (strcmp(crypt->ops->name, "WEP") != 0) { - /* only WEP is supported with wireless extensions, so just - * report that encryption is used */ - erq->length = 0; - erq->flags |= IW_ENCODE_ENABLED; - return 0; - } - - /* Reads from HFA384X_RID_CNFDEFAULTKEY* return bogus values, so show - * the keys from driver buffer */ - len = crypt->ops->get_key(key, WEP_KEY_LEN, NULL, crypt->priv); - erq->length = (len >= 0 ? len : 0); - - if (local->func->get_rid(dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, 1) < 0) - { - printk("CNFWEPFLAGS reading failed\n"); - return -EOPNOTSUPP; - } - le16_to_cpus(&val); - if (val & HFA384X_WEPFLAGS_PRIVACYINVOKED) - erq->flags |= IW_ENCODE_ENABLED; - else - erq->flags |= IW_ENCODE_DISABLED; - if (val & HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - return 0; -} - - -static int hostap_set_rate(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - int ret, basic_rates; - - iface = netdev_priv(dev); - local = iface->local; - - basic_rates = local->basic_rates & local->tx_rate_control; - if (!basic_rates || basic_rates != local->basic_rates) { - printk(KERN_INFO "%s: updating basic rate set automatically " - "to match with the new supported rate set\n", - dev->name); - if (!basic_rates) - basic_rates = local->tx_rate_control; - - local->basic_rates = basic_rates; - if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES, - basic_rates)) - printk(KERN_WARNING "%s: failed to set " - "cnfBasicRates\n", dev->name); - } - - ret = (hostap_set_word(dev, HFA384X_RID_TXRATECONTROL, - local->tx_rate_control) || - hostap_set_word(dev, HFA384X_RID_CNFSUPPORTEDRATES, - local->tx_rate_control) || - local->func->reset_port(dev)); - - if (ret) { - printk(KERN_WARNING "%s: TXRateControl/cnfSupportedRates " - "setting to 0x%x failed\n", - dev->name, local->tx_rate_control); - } - - /* Update TX rate configuration for all STAs based on new operational - * rate set. */ - hostap_update_rates(local); - - return ret; -} - - -static int prism2_ioctl_siwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (rrq->fixed) { - switch (rrq->value) { - case 11000000: - local->tx_rate_control = HFA384X_RATES_11MBPS; - break; - case 5500000: - local->tx_rate_control = HFA384X_RATES_5MBPS; - break; - case 2000000: - local->tx_rate_control = HFA384X_RATES_2MBPS; - break; - case 1000000: - local->tx_rate_control = HFA384X_RATES_1MBPS; - break; - default: - local->tx_rate_control = HFA384X_RATES_1MBPS | - HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS | - HFA384X_RATES_11MBPS; - break; - } - } else { - switch (rrq->value) { - case 11000000: - local->tx_rate_control = HFA384X_RATES_1MBPS | - HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS | - HFA384X_RATES_11MBPS; - break; - case 5500000: - local->tx_rate_control = HFA384X_RATES_1MBPS | - HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS; - break; - case 2000000: - local->tx_rate_control = HFA384X_RATES_1MBPS | - HFA384X_RATES_2MBPS; - break; - case 1000000: - local->tx_rate_control = HFA384X_RATES_1MBPS; - break; - default: - local->tx_rate_control = HFA384X_RATES_1MBPS | - HFA384X_RATES_2MBPS | HFA384X_RATES_5MBPS | - HFA384X_RATES_11MBPS; - break; - } - } - - return hostap_set_rate(dev); -} - - -static int prism2_ioctl_giwrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - u16 val; - struct hostap_interface *iface; - local_info_t *local; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->get_rid(dev, HFA384X_RID_TXRATECONTROL, &val, 2, 1) < - 0) - return -EINVAL; - - if ((val & 0x1) && (val > 1)) - rrq->fixed = 0; - else - rrq->fixed = 1; - - if (local->iw_mode == IW_MODE_MASTER && local->ap != NULL && - !local->fw_tx_rate_control) { - /* HFA384X_RID_CURRENTTXRATE seems to always be 2 Mbps in - * Host AP mode, so use the recorded TX rate of the last sent - * frame */ - rrq->value = local->ap->last_tx_rate > 0 ? - local->ap->last_tx_rate * 100000 : 11000000; - return 0; - } - - if (local->func->get_rid(dev, HFA384X_RID_CURRENTTXRATE, &val, 2, 1) < - 0) - return -EINVAL; - - switch (val) { - case HFA384X_RATES_1MBPS: - rrq->value = 1000000; - break; - case HFA384X_RATES_2MBPS: - rrq->value = 2000000; - break; - case HFA384X_RATES_5MBPS: - rrq->value = 5500000; - break; - case HFA384X_RATES_11MBPS: - rrq->value = 11000000; - break; - default: - /* should not happen */ - rrq->value = 11000000; - ret = -EINVAL; - break; - } - - return ret; -} - - -static int prism2_ioctl_siwsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *sens, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - /* Set the desired AP density */ - if (sens->value < 1 || sens->value > 3) - return -EINVAL; - - if (hostap_set_word(dev, HFA384X_RID_CNFSYSTEMSCALE, sens->value) || - local->func->reset_port(dev)) - return -EINVAL; - - return 0; -} - -static int prism2_ioctl_giwsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *sens, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 val; - - iface = netdev_priv(dev); - local = iface->local; - - /* Get the current AP density */ - if (local->func->get_rid(dev, HFA384X_RID_CNFSYSTEMSCALE, &val, 2, 1) < - 0) - return -EINVAL; - - sens->value = le16_to_cpu(val); - sens->fixed = 1; - - return 0; -} - - -/* Deprecated in new wireless extension API */ -static int prism2_ioctl_giwaplist(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - struct sockaddr *addr; - struct iw_quality *qual; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->iw_mode != IW_MODE_MASTER) { - printk(KERN_DEBUG "SIOCGIWAPLIST is currently only supported " - "in Host AP mode\n"); - data->length = 0; - return -EOPNOTSUPP; - } - - addr = kmalloc(sizeof(struct sockaddr) * IW_MAX_AP, GFP_KERNEL); - qual = kmalloc(sizeof(struct iw_quality) * IW_MAX_AP, GFP_KERNEL); - if (addr == NULL || qual == NULL) { - kfree(addr); - kfree(qual); - data->length = 0; - return -ENOMEM; - } - - data->length = prism2_ap_get_sta_qual(local, addr, qual, IW_MAX_AP, 1); - - memcpy(extra, &addr, sizeof(struct sockaddr) * data->length); - data->flags = 1; /* has quality information */ - memcpy(extra + sizeof(struct sockaddr) * data->length, &qual, - sizeof(struct iw_quality) * data->length); - - kfree(addr); - kfree(qual); - return 0; -} - - -static int prism2_ioctl_siwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 val; - - iface = netdev_priv(dev); - local = iface->local; - - if (rts->disabled) - val = cpu_to_le16(2347); - else if (rts->value < 0 || rts->value > 2347) - return -EINVAL; - else - val = cpu_to_le16(rts->value); - - if (local->func->set_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2) || - local->func->reset_port(dev)) - return -EINVAL; - - local->rts_threshold = rts->value; - - return 0; -} - -static int prism2_ioctl_giwrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 val; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->get_rid(dev, HFA384X_RID_RTSTHRESHOLD, &val, 2, 1) < - 0) - return -EINVAL; - - rts->value = le16_to_cpu(val); - rts->disabled = (rts->value == 2347); - rts->fixed = 1; - - return 0; -} - - -static int prism2_ioctl_siwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 val; - - iface = netdev_priv(dev); - local = iface->local; - - if (rts->disabled) - val = cpu_to_le16(2346); - else if (rts->value < 256 || rts->value > 2346) - return -EINVAL; - else - val = cpu_to_le16(rts->value & ~0x1); /* even numbers only */ - - local->fragm_threshold = rts->value & ~0x1; - if (local->func->set_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, &val, - 2) - || local->func->reset_port(dev)) - return -EINVAL; - - return 0; -} - -static int prism2_ioctl_giwfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 val; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->get_rid(dev, HFA384X_RID_FRAGMENTATIONTHRESHOLD, - &val, 2, 1) < 0) - return -EINVAL; - - rts->value = le16_to_cpu(val); - rts->disabled = (rts->value == 2346); - rts->fixed = 1; - - return 0; -} - - -#ifndef PRISM2_NO_STATION_MODES -static int hostap_join_ap(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hfa384x_join_request req; - unsigned long flags; - int i; - struct hfa384x_hostscan_result *entry; - - iface = netdev_priv(dev); - local = iface->local; - - memcpy(req.bssid, local->preferred_ap, ETH_ALEN); - req.channel = 0; - - spin_lock_irqsave(&local->lock, flags); - for (i = 0; i < local->last_scan_results_count; i++) { - if (!local->last_scan_results) - break; - entry = &local->last_scan_results[i]; - if (memcmp(local->preferred_ap, entry->bssid, ETH_ALEN) == 0) { - req.channel = entry->chid; - break; - } - } - spin_unlock_irqrestore(&local->lock, flags); - - if (local->func->set_rid(dev, HFA384X_RID_JOINREQUEST, &req, - sizeof(req))) { - printk(KERN_DEBUG "%s: JoinRequest %pM failed\n", - dev->name, local->preferred_ap); - return -1; - } - - printk(KERN_DEBUG "%s: Trying to join BSSID %pM\n", - dev->name, local->preferred_ap); - - return 0; -} -#endif /* PRISM2_NO_STATION_MODES */ - - -static int prism2_ioctl_siwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ -#ifdef PRISM2_NO_STATION_MODES - return -EOPNOTSUPP; -#else /* PRISM2_NO_STATION_MODES */ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - memcpy(local->preferred_ap, &ap_addr->sa_data, ETH_ALEN); - - if (local->host_roaming == 1 && local->iw_mode == IW_MODE_INFRA) { - struct hfa384x_scan_request scan_req; - memset(&scan_req, 0, sizeof(scan_req)); - scan_req.channel_list = cpu_to_le16(0x3fff); - scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS); - if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, - &scan_req, sizeof(scan_req))) { - printk(KERN_DEBUG "%s: ScanResults request failed - " - "preferred AP delayed to next unsolicited " - "scan\n", dev->name); - } - } else if (local->host_roaming == 2 && - local->iw_mode == IW_MODE_INFRA) { - if (hostap_join_ap(dev)) - return -EINVAL; - } else { - printk(KERN_DEBUG "%s: Preferred AP (SIOCSIWAP) is used only " - "in Managed mode when host_roaming is enabled\n", - dev->name); - } - - return 0; -#endif /* PRISM2_NO_STATION_MODES */ -} - -static int prism2_ioctl_giwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - ap_addr->sa_family = ARPHRD_ETHER; - switch (iface->type) { - case HOSTAP_INTERFACE_AP: - memcpy(&ap_addr->sa_data, dev->dev_addr, ETH_ALEN); - break; - case HOSTAP_INTERFACE_STA: - memcpy(&ap_addr->sa_data, local->assoc_ap_addr, ETH_ALEN); - break; - case HOSTAP_INTERFACE_WDS: - memcpy(&ap_addr->sa_data, iface->u.wds.remote_addr, ETH_ALEN); - break; - default: - if (local->func->get_rid(dev, HFA384X_RID_CURRENTBSSID, - &ap_addr->sa_data, ETH_ALEN, 1) < 0) - return -EOPNOTSUPP; - - /* local->bssid is also updated in LinkStatus handler when in - * station mode */ - memcpy(local->bssid, &ap_addr->sa_data, ETH_ALEN); - break; - } - - return 0; -} - - -static int prism2_ioctl_siwnickn(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *nickname) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - memset(local->name, 0, sizeof(local->name)); - memcpy(local->name, nickname, data->length); - local->name_set = 1; - - if (hostap_set_string(dev, HFA384X_RID_CNFOWNNAME, local->name) || - local->func->reset_port(dev)) - return -EINVAL; - - return 0; -} - -static int prism2_ioctl_giwnickn(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *nickname) -{ - struct hostap_interface *iface; - local_info_t *local; - int len; - char name[MAX_NAME_LEN + 3]; - u16 val; - - iface = netdev_priv(dev); - local = iface->local; - - len = local->func->get_rid(dev, HFA384X_RID_CNFOWNNAME, - &name, MAX_NAME_LEN + 2, 0); - val = le16_to_cpu(*(__le16 *) name); - if (len > MAX_NAME_LEN + 2 || len < 0 || val > MAX_NAME_LEN) - return -EOPNOTSUPP; - - name[val + 2] = '\0'; - data->length = val + 1; - memcpy(nickname, name + 2, val + 1); - - return 0; -} - - -static int prism2_ioctl_siwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - /* freq => chan. */ - if (freq->e == 1 && - freq->m / 100000 >= freq_list[0] && - freq->m / 100000 <= freq_list[FREQ_COUNT - 1]) { - int ch; - int fr = freq->m / 100000; - for (ch = 0; ch < FREQ_COUNT; ch++) { - if (fr == freq_list[ch]) { - freq->e = 0; - freq->m = ch + 1; - break; - } - } - } - - if (freq->e != 0 || freq->m < 1 || freq->m > FREQ_COUNT || - !(local->channel_mask & (1 << (freq->m - 1)))) - return -EINVAL; - - local->channel = freq->m; /* channel is used in prism2_setup_rids() */ - if (hostap_set_word(dev, HFA384X_RID_CNFOWNCHANNEL, local->channel) || - local->func->reset_port(dev)) - return -EINVAL; - - return 0; -} - -static int prism2_ioctl_giwfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *freq, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - u16 val; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->get_rid(dev, HFA384X_RID_CURRENTCHANNEL, &val, 2, 1) < - 0) - return -EINVAL; - - le16_to_cpus(&val); - if (val < 1 || val > FREQ_COUNT) - return -EINVAL; - - freq->m = freq_list[val - 1] * 100000; - freq->e = 1; - - return 0; -} - - -static void hostap_monitor_set_type(local_info_t *local) -{ - struct net_device *dev = local->ddev; - - if (dev == NULL) - return; - - if (local->monitor_type == PRISM2_MONITOR_PRISM || - local->monitor_type == PRISM2_MONITOR_CAPHDR) { - dev->type = ARPHRD_IEEE80211_PRISM; - } else if (local->monitor_type == PRISM2_MONITOR_RADIOTAP) { - dev->type = ARPHRD_IEEE80211_RADIOTAP; - } else { - dev->type = ARPHRD_IEEE80211; - } -} - - -static int prism2_ioctl_siwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *ssid) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (iface->type == HOSTAP_INTERFACE_WDS) - return -EOPNOTSUPP; - - if (data->flags == 0) - ssid[0] = '\0'; /* ANY */ - - if (local->iw_mode == IW_MODE_MASTER && ssid[0] == '\0') { - /* Setting SSID to empty string seems to kill the card in - * Host AP mode */ - printk(KERN_DEBUG "%s: Host AP mode does not support " - "'Any' essid\n", dev->name); - return -EINVAL; - } - - memcpy(local->essid, ssid, data->length); - local->essid[data->length] = '\0'; - - if ((!local->fw_ap && - hostap_set_string(dev, HFA384X_RID_CNFDESIREDSSID, local->essid)) - || hostap_set_string(dev, HFA384X_RID_CNFOWNSSID, local->essid) || - local->func->reset_port(dev)) - return -EINVAL; - - return 0; -} - -static int prism2_ioctl_giwessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *essid) -{ - struct hostap_interface *iface; - local_info_t *local; - u16 val; - - iface = netdev_priv(dev); - local = iface->local; - - if (iface->type == HOSTAP_INTERFACE_WDS) - return -EOPNOTSUPP; - - data->flags = 1; /* active */ - if (local->iw_mode == IW_MODE_MASTER) { - data->length = strlen(local->essid); - memcpy(essid, local->essid, IW_ESSID_MAX_SIZE); - } else { - int len; - char ssid[MAX_SSID_LEN + 2]; - memset(ssid, 0, sizeof(ssid)); - len = local->func->get_rid(dev, HFA384X_RID_CURRENTSSID, - &ssid, MAX_SSID_LEN + 2, 0); - val = le16_to_cpu(*(__le16 *) ssid); - if (len > MAX_SSID_LEN + 2 || len < 0 || val > MAX_SSID_LEN) { - return -EOPNOTSUPP; - } - data->length = val; - memcpy(essid, ssid + 2, IW_ESSID_MAX_SIZE); - } - - return 0; -} - - -static int prism2_ioctl_giwrange(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - struct iw_range *range = (struct iw_range *) extra; - u8 rates[10]; - u16 val; - int i, len, over2; - - iface = netdev_priv(dev); - local = iface->local; - - data->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - /* TODO: could fill num_txpower and txpower array with - * something; however, there are 128 different values.. */ - - range->txpower_capa = IW_TXPOW_DBM; - - if (local->iw_mode == IW_MODE_INFRA || local->iw_mode == IW_MODE_ADHOC) - { - range->min_pmp = 1 * 1024; - range->max_pmp = 65535 * 1024; - range->min_pmt = 1 * 1024; - range->max_pmt = 1000 * 1024; - range->pmp_flags = IW_POWER_PERIOD; - range->pmt_flags = IW_POWER_TIMEOUT; - range->pm_capa = IW_POWER_PERIOD | IW_POWER_TIMEOUT | - IW_POWER_UNICAST_R | IW_POWER_ALL_R; - } - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 18; - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT; - range->min_retry = 0; - range->max_retry = 255; - - range->num_channels = FREQ_COUNT; - - val = 0; - for (i = 0; i < FREQ_COUNT; i++) { - if (local->channel_mask & (1 << i)) { - range->freq[val].i = i + 1; - range->freq[val].m = freq_list[i] * 100000; - range->freq[val].e = 1; - val++; - } - if (val == IW_MAX_FREQUENCIES) - break; - } - range->num_frequency = val; - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) { - range->max_qual.qual = 70; /* what is correct max? This was not - * documented exactly. At least - * 69 has been observed. */ - range->max_qual.level = 0; /* dB */ - range->max_qual.noise = 0; /* dB */ - - /* What would be suitable values for "average/typical" qual? */ - range->avg_qual.qual = 20; - range->avg_qual.level = -60; - range->avg_qual.noise = -95; - } else { - range->max_qual.qual = 92; /* 0 .. 92 */ - range->max_qual.level = 154; /* 27 .. 154 */ - range->max_qual.noise = 154; /* 27 .. 154 */ - } - range->sensitivity = 3; - - range->max_encoding_tokens = WEP_KEYS; - range->num_encoding_sizes = 2; - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - - over2 = 0; - len = prism2_get_datarates(dev, rates); - range->num_bitrates = 0; - for (i = 0; i < len; i++) { - if (range->num_bitrates < IW_MAX_BITRATES) { - range->bitrate[range->num_bitrates] = - rates[i] * 500000; - range->num_bitrates++; - } - if (rates[i] == 0x0b || rates[i] == 0x16) - over2 = 1; - } - /* estimated maximum TCP throughput values (bps) */ - range->throughput = over2 ? 5500000 : 1500000; - - range->min_rts = 0; - range->max_rts = 2347; - range->min_frag = 256; - range->max_frag = 2346; - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->event_capa[4] = (IW_EVENT_CAPA_MASK(IWEVTXDROP) | - IW_EVENT_CAPA_MASK(IWEVCUSTOM) | - IW_EVENT_CAPA_MASK(IWEVREGISTERED) | - IW_EVENT_CAPA_MASK(IWEVEXPIRED)); - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) - range->scan_capa = IW_SCAN_CAPA_ESSID; - - return 0; -} - - -static int hostap_monitor_mode_enable(local_info_t *local) -{ - struct net_device *dev = local->dev; - - printk(KERN_DEBUG "Enabling monitor mode\n"); - hostap_monitor_set_type(local); - - if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, - HFA384X_PORTTYPE_PSEUDO_IBSS)) { - printk(KERN_DEBUG "Port type setting for monitor mode " - "failed\n"); - return -EOPNOTSUPP; - } - - /* Host decrypt is needed to get the IV and ICV fields; - * however, monitor mode seems to remove WEP flag from frame - * control field */ - if (hostap_set_word(dev, HFA384X_RID_CNFWEPFLAGS, - HFA384X_WEPFLAGS_HOSTENCRYPT | - HFA384X_WEPFLAGS_HOSTDECRYPT)) { - printk(KERN_DEBUG "WEP flags setting failed\n"); - return -EOPNOTSUPP; - } - - if (local->func->reset_port(dev) || - local->func->cmd(dev, HFA384X_CMDCODE_TEST | - (HFA384X_TEST_MONITOR << 8), - 0, NULL, NULL)) { - printk(KERN_DEBUG "Setting monitor mode failed\n"); - return -EOPNOTSUPP; - } - - return 0; -} - - -static int hostap_monitor_mode_disable(local_info_t *local) -{ - struct net_device *dev = local->ddev; - - if (dev == NULL) - return -1; - - printk(KERN_DEBUG "%s: Disabling monitor mode\n", dev->name); - dev->type = ARPHRD_ETHER; - - if (local->func->cmd(dev, HFA384X_CMDCODE_TEST | - (HFA384X_TEST_STOP << 8), - 0, NULL, NULL)) - return -1; - return hostap_set_encryption(local); -} - - -static int prism2_ioctl_siwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - int double_reset = 0; - - iface = netdev_priv(dev); - local = iface->local; - - if (*mode != IW_MODE_ADHOC && *mode != IW_MODE_INFRA && - *mode != IW_MODE_MASTER && *mode != IW_MODE_REPEAT && - *mode != IW_MODE_MONITOR) - return -EOPNOTSUPP; - -#ifdef PRISM2_NO_STATION_MODES - if (*mode == IW_MODE_ADHOC || *mode == IW_MODE_INFRA) - return -EOPNOTSUPP; -#endif /* PRISM2_NO_STATION_MODES */ - - if (*mode == local->iw_mode) - return 0; - - if (*mode == IW_MODE_MASTER && local->essid[0] == '\0') { - printk(KERN_WARNING "%s: empty SSID not allowed in Master " - "mode\n", dev->name); - return -EINVAL; - } - - if (local->iw_mode == IW_MODE_MONITOR) - hostap_monitor_mode_disable(local); - - if ((local->iw_mode == IW_MODE_ADHOC || - local->iw_mode == IW_MODE_MONITOR) && *mode == IW_MODE_MASTER) { - /* There seems to be a firmware bug in at least STA f/w v1.5.6 - * that leaves beacon frames to use IBSS type when moving from - * IBSS to Host AP mode. Doing double Port0 reset seems to be - * enough to workaround this. */ - double_reset = 1; - } - - printk(KERN_DEBUG "prism2: %s: operating mode changed " - "%d -> %d\n", dev->name, local->iw_mode, *mode); - local->iw_mode = *mode; - - if (local->iw_mode == IW_MODE_MONITOR) - hostap_monitor_mode_enable(local); - else if (local->iw_mode == IW_MODE_MASTER && !local->host_encrypt && - !local->fw_encrypt_ok) { - printk(KERN_DEBUG "%s: defaulting to host-based encryption as " - "a workaround for firmware bug in Host AP mode WEP\n", - dev->name); - local->host_encrypt = 1; - } - - if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, - hostap_get_porttype(local))) - return -EOPNOTSUPP; - - if (local->func->reset_port(dev)) - return -EINVAL; - if (double_reset && local->func->reset_port(dev)) - return -EINVAL; - - if (local->iw_mode != IW_MODE_INFRA && local->iw_mode != IW_MODE_ADHOC) - { - /* netif_carrier is used only in client modes for now, so make - * sure carrier is on when moving to non-client modes. */ - netif_carrier_on(local->dev); - netif_carrier_on(local->ddev); - } - return 0; -} - - -static int prism2_ioctl_giwmode(struct net_device *dev, - struct iw_request_info *info, - __u32 *mode, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - switch (iface->type) { - case HOSTAP_INTERFACE_STA: - *mode = IW_MODE_INFRA; - break; - case HOSTAP_INTERFACE_WDS: - *mode = IW_MODE_REPEAT; - break; - default: - *mode = local->iw_mode; - break; - } - return 0; -} - - -static int prism2_ioctl_siwpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *wrq, char *extra) -{ -#ifdef PRISM2_NO_STATION_MODES - return -EOPNOTSUPP; -#else /* PRISM2_NO_STATION_MODES */ - int ret = 0; - - if (wrq->disabled) - return hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 0); - - switch (wrq->flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 0); - if (ret) - return ret; - ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); - if (ret) - return ret; - break; - case IW_POWER_ALL_R: - ret = hostap_set_word(dev, HFA384X_RID_CNFMULTICASTRECEIVE, 1); - if (ret) - return ret; - ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); - if (ret) - return ret; - break; - case IW_POWER_ON: - break; - default: - return -EINVAL; - } - - if (wrq->flags & IW_POWER_TIMEOUT) { - ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); - if (ret) - return ret; - ret = hostap_set_word(dev, HFA384X_RID_CNFPMHOLDOVERDURATION, - wrq->value / 1024); - if (ret) - return ret; - } - if (wrq->flags & IW_POWER_PERIOD) { - ret = hostap_set_word(dev, HFA384X_RID_CNFPMENABLED, 1); - if (ret) - return ret; - ret = hostap_set_word(dev, HFA384X_RID_CNFMAXSLEEPDURATION, - wrq->value / 1024); - if (ret) - return ret; - } - - return ret; -#endif /* PRISM2_NO_STATION_MODES */ -} - - -static int prism2_ioctl_giwpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ -#ifdef PRISM2_NO_STATION_MODES - return -EOPNOTSUPP; -#else /* PRISM2_NO_STATION_MODES */ - struct hostap_interface *iface; - local_info_t *local; - __le16 enable, mcast; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->get_rid(dev, HFA384X_RID_CNFPMENABLED, &enable, 2, 1) - < 0) - return -EINVAL; - - if (!le16_to_cpu(enable)) { - rrq->disabled = 1; - return 0; - } - - rrq->disabled = 0; - - if ((rrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - __le16 timeout; - if (local->func->get_rid(dev, - HFA384X_RID_CNFPMHOLDOVERDURATION, - &timeout, 2, 1) < 0) - return -EINVAL; - - rrq->flags = IW_POWER_TIMEOUT; - rrq->value = le16_to_cpu(timeout) * 1024; - } else { - __le16 period; - if (local->func->get_rid(dev, HFA384X_RID_CNFMAXSLEEPDURATION, - &period, 2, 1) < 0) - return -EINVAL; - - rrq->flags = IW_POWER_PERIOD; - rrq->value = le16_to_cpu(period) * 1024; - } - - if (local->func->get_rid(dev, HFA384X_RID_CNFMULTICASTRECEIVE, &mcast, - 2, 1) < 0) - return -EINVAL; - - if (le16_to_cpu(mcast)) - rrq->flags |= IW_POWER_ALL_R; - else - rrq->flags |= IW_POWER_UNICAST_R; - - return 0; -#endif /* PRISM2_NO_STATION_MODES */ -} - - -static int prism2_ioctl_siwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (rrq->disabled) - return -EINVAL; - - /* setting retry limits is not supported with the current station - * firmware code; simulate this with alternative retry count for now */ - if (rrq->flags == IW_RETRY_LIMIT) { - if (rrq->value < 0) { - /* disable manual retry count setting and use firmware - * defaults */ - local->manual_retry_count = -1; - local->tx_control &= ~HFA384X_TX_CTRL_ALT_RTRY; - } else { - if (hostap_set_word(dev, HFA384X_RID_CNFALTRETRYCOUNT, - rrq->value)) { - printk(KERN_DEBUG "%s: Alternate retry count " - "setting to %d failed\n", - dev->name, rrq->value); - return -EOPNOTSUPP; - } - - local->manual_retry_count = rrq->value; - local->tx_control |= HFA384X_TX_CTRL_ALT_RTRY; - } - return 0; - } - - return -EOPNOTSUPP; - -#if 0 - /* what could be done, if firmware would support this.. */ - - if (rrq->flags & IW_RETRY_LIMIT) { - if (rrq->flags & IW_RETRY_LONG) - HFA384X_RID_LONGRETRYLIMIT = rrq->value; - else if (rrq->flags & IW_RETRY_SHORT) - HFA384X_RID_SHORTRETRYLIMIT = rrq->value; - else { - HFA384X_RID_LONGRETRYLIMIT = rrq->value; - HFA384X_RID_SHORTRETRYLIMIT = rrq->value; - } - - } - - if (rrq->flags & IW_RETRY_LIFETIME) { - HFA384X_RID_MAXTRANSMITLIFETIME = rrq->value / 1024; - } - - return 0; -#endif /* 0 */ -} - -static int prism2_ioctl_giwretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - __le16 shortretry, longretry, lifetime, altretry; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->get_rid(dev, HFA384X_RID_SHORTRETRYLIMIT, &shortretry, - 2, 1) < 0 || - local->func->get_rid(dev, HFA384X_RID_LONGRETRYLIMIT, &longretry, - 2, 1) < 0 || - local->func->get_rid(dev, HFA384X_RID_MAXTRANSMITLIFETIME, - &lifetime, 2, 1) < 0) - return -EINVAL; - - rrq->disabled = 0; - - if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - rrq->flags = IW_RETRY_LIFETIME; - rrq->value = le16_to_cpu(lifetime) * 1024; - } else { - if (local->manual_retry_count >= 0) { - rrq->flags = IW_RETRY_LIMIT; - if (local->func->get_rid(dev, - HFA384X_RID_CNFALTRETRYCOUNT, - &altretry, 2, 1) >= 0) - rrq->value = le16_to_cpu(altretry); - else - rrq->value = local->manual_retry_count; - } else if ((rrq->flags & IW_RETRY_LONG)) { - rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - rrq->value = le16_to_cpu(longretry); - } else { - rrq->flags = IW_RETRY_LIMIT; - rrq->value = le16_to_cpu(shortretry); - if (shortretry != longretry) - rrq->flags |= IW_RETRY_SHORT; - } - } - return 0; -} - - -/* Note! This TX power controlling is experimental and should not be used in - * production use. It just sets raw power register and does not use any kind of - * feedback information from the measured TX power (CR58). This is now - * commented out to make sure that it is not used by accident. TX power - * configuration will be enabled again after proper algorithm using feedback - * has been implemented. */ - -#ifdef RAW_TXPOWER_SETTING -/* Map HFA386x's CR31 to and from dBm with some sort of ad hoc mapping.. - * This version assumes following mapping: - * CR31 is 7-bit value with -64 to +63 range. - * -64 is mapped into +20dBm and +63 into -43dBm. - * This is certainly not an exact mapping for every card, but at least - * increasing dBm value should correspond to increasing TX power. - */ - -static int prism2_txpower_hfa386x_to_dBm(u16 val) -{ - signed char tmp; - - if (val > 255) - val = 255; - - tmp = val; - tmp >>= 2; - - return -12 - tmp; -} - -static u16 prism2_txpower_dBm_to_hfa386x(int val) -{ - signed char tmp; - - if (val > 20) - return 128; - else if (val < -43) - return 127; - - tmp = val; - tmp = -12 - tmp; - tmp <<= 2; - - return (unsigned char) tmp; -} -#endif /* RAW_TXPOWER_SETTING */ - - -static int prism2_ioctl_siwtxpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; -#ifdef RAW_TXPOWER_SETTING - char *tmp; -#endif - u16 val; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - if (rrq->disabled) { - if (local->txpower_type != PRISM2_TXPOWER_OFF) { - val = 0xff; /* use all standby and sleep modes */ - ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, - HFA386X_CR_A_D_TEST_MODES2, - &val, NULL); - printk(KERN_DEBUG "%s: Turning radio off: %s\n", - dev->name, ret ? "failed" : "OK"); - local->txpower_type = PRISM2_TXPOWER_OFF; - } - return (ret ? -EOPNOTSUPP : 0); - } - - if (local->txpower_type == PRISM2_TXPOWER_OFF) { - val = 0; /* disable all standby and sleep modes */ - ret = local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, - HFA386X_CR_A_D_TEST_MODES2, &val, NULL); - printk(KERN_DEBUG "%s: Turning radio on: %s\n", - dev->name, ret ? "failed" : "OK"); - local->txpower_type = PRISM2_TXPOWER_UNKNOWN; - } - -#ifdef RAW_TXPOWER_SETTING - if (!rrq->fixed && local->txpower_type != PRISM2_TXPOWER_AUTO) { - printk(KERN_DEBUG "Setting ALC on\n"); - val = HFA384X_TEST_CFG_BIT_ALC; - local->func->cmd(dev, HFA384X_CMDCODE_TEST | - (HFA384X_TEST_CFG_BITS << 8), 1, &val, NULL); - local->txpower_type = PRISM2_TXPOWER_AUTO; - return 0; - } - - if (local->txpower_type != PRISM2_TXPOWER_FIXED) { - printk(KERN_DEBUG "Setting ALC off\n"); - val = HFA384X_TEST_CFG_BIT_ALC; - local->func->cmd(dev, HFA384X_CMDCODE_TEST | - (HFA384X_TEST_CFG_BITS << 8), 0, &val, NULL); - local->txpower_type = PRISM2_TXPOWER_FIXED; - } - - if (rrq->flags == IW_TXPOW_DBM) - tmp = "dBm"; - else if (rrq->flags == IW_TXPOW_MWATT) - tmp = "mW"; - else - tmp = "UNKNOWN"; - printk(KERN_DEBUG "Setting TX power to %d %s\n", rrq->value, tmp); - - if (rrq->flags != IW_TXPOW_DBM) { - printk("SIOCSIWTXPOW with mW is not supported; use dBm\n"); - return -EOPNOTSUPP; - } - - local->txpower = rrq->value; - val = prism2_txpower_dBm_to_hfa386x(local->txpower); - if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, - HFA386X_CR_MANUAL_TX_POWER, &val, NULL)) - ret = -EOPNOTSUPP; -#else /* RAW_TXPOWER_SETTING */ - if (rrq->fixed) - ret = -EOPNOTSUPP; -#endif /* RAW_TXPOWER_SETTING */ - - return ret; -} - -static int prism2_ioctl_giwtxpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, char *extra) -{ -#ifdef RAW_TXPOWER_SETTING - struct hostap_interface *iface; - local_info_t *local; - u16 resp0; - - iface = netdev_priv(dev); - local = iface->local; - - rrq->flags = IW_TXPOW_DBM; - rrq->disabled = 0; - rrq->fixed = 0; - - if (local->txpower_type == PRISM2_TXPOWER_AUTO) { - if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, - HFA386X_CR_MANUAL_TX_POWER, - NULL, &resp0) == 0) { - rrq->value = prism2_txpower_hfa386x_to_dBm(resp0); - } else { - /* Could not get real txpower; guess 15 dBm */ - rrq->value = 15; - } - } else if (local->txpower_type == PRISM2_TXPOWER_OFF) { - rrq->value = 0; - rrq->disabled = 1; - } else if (local->txpower_type == PRISM2_TXPOWER_FIXED) { - rrq->value = local->txpower; - rrq->fixed = 1; - } else { - printk("SIOCGIWTXPOW - unknown txpower_type=%d\n", - local->txpower_type); - } - return 0; -#else /* RAW_TXPOWER_SETTING */ - return -EOPNOTSUPP; -#endif /* RAW_TXPOWER_SETTING */ -} - - -#ifndef PRISM2_NO_STATION_MODES - -/* HostScan request works with and without host_roaming mode. In addition, it - * does not break current association. However, it requires newer station - * firmware version (>= 1.3.1) than scan request. */ -static int prism2_request_hostscan(struct net_device *dev, - u8 *ssid, u8 ssid_len) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hfa384x_hostscan_request scan_req; - - iface = netdev_priv(dev); - local = iface->local; - - memset(&scan_req, 0, sizeof(scan_req)); - scan_req.channel_list = cpu_to_le16(local->channel_mask & - local->scan_channel_mask); - scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS); - if (ssid) { - if (ssid_len > 32) - return -EINVAL; - scan_req.target_ssid_len = cpu_to_le16(ssid_len); - memcpy(scan_req.target_ssid, ssid, ssid_len); - } - - if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req, - sizeof(scan_req))) { - printk(KERN_DEBUG "%s: HOSTSCAN failed\n", dev->name); - return -EINVAL; - } - return 0; -} - - -static int prism2_request_scan(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hfa384x_scan_request scan_req; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - memset(&scan_req, 0, sizeof(scan_req)); - scan_req.channel_list = cpu_to_le16(local->channel_mask & - local->scan_channel_mask); - scan_req.txrate = cpu_to_le16(HFA384X_RATES_1MBPS); - - /* FIX: - * It seems to be enough to set roaming mode for a short moment to - * host-based and then setup scanrequest data and return the mode to - * firmware-based. - * - * Master mode would need to drop to Managed mode for a short while - * to make scanning work.. Or sweep through the different channels and - * use passive scan based on beacons. */ - - if (!local->host_roaming) - hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, - HFA384X_ROAMING_HOST); - - if (local->func->set_rid(dev, HFA384X_RID_SCANREQUEST, &scan_req, - sizeof(scan_req))) { - printk(KERN_DEBUG "SCANREQUEST failed\n"); - ret = -EINVAL; - } - - if (!local->host_roaming) - hostap_set_word(dev, HFA384X_RID_CNFROAMINGMODE, - HFA384X_ROAMING_FIRMWARE); - - return 0; -} - -#else /* !PRISM2_NO_STATION_MODES */ - -static inline int prism2_request_hostscan(struct net_device *dev, - u8 *ssid, u8 ssid_len) -{ - return -EOPNOTSUPP; -} - - -static inline int prism2_request_scan(struct net_device *dev) -{ - return -EOPNOTSUPP; -} - -#endif /* !PRISM2_NO_STATION_MODES */ - - -static int prism2_ioctl_siwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - int ret; - u8 *ssid = NULL, ssid_len = 0; - struct iw_scan_req *req = (struct iw_scan_req *) extra; - - iface = netdev_priv(dev); - local = iface->local; - - if (data->length < sizeof(struct iw_scan_req)) - req = NULL; - - if (local->iw_mode == IW_MODE_MASTER) { - /* In master mode, we just return the results of our local - * tables, so we don't need to start anything... - * Jean II */ - data->length = 0; - return 0; - } - - if (!local->dev_enabled) - return -ENETDOWN; - - if (req && data->flags & IW_SCAN_THIS_ESSID) { - ssid = req->essid; - ssid_len = req->essid_len; - - if (ssid_len && - ((local->iw_mode != IW_MODE_INFRA && - local->iw_mode != IW_MODE_ADHOC) || - (local->sta_fw_ver < PRISM2_FW_VER(1,3,1)))) - return -EOPNOTSUPP; - } - - if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) - ret = prism2_request_hostscan(dev, ssid, ssid_len); - else - ret = prism2_request_scan(dev); - - if (ret == 0) - local->scan_timestamp = jiffies; - - /* Could inquire F101, F103 or wait for SIOCGIWSCAN and read RID */ - - return ret; -} - - -#ifndef PRISM2_NO_STATION_MODES -static char * __prism2_translate_scan(local_info_t *local, - struct iw_request_info *info, - struct hfa384x_hostscan_result *scan, - struct hostap_bss_info *bss, - char *current_ev, char *end_buf) -{ - int i, chan; - struct iw_event iwe; - char *current_val; - u16 capabilities; - u8 *pos; - u8 *ssid, *bssid; - size_t ssid_len; - char *buf; - - if (bss) { - ssid = bss->ssid; - ssid_len = bss->ssid_len; - bssid = bss->bssid; - } else { - ssid = scan->ssid; - ssid_len = le16_to_cpu(scan->ssid_len); - bssid = scan->bssid; - } - if (ssid_len > 32) - ssid_len = 32; - - /* First entry *MUST* be the AP MAC address */ - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, end_buf, &iwe, - IW_EV_ADDR_LEN); - - /* Other entries will be displayed in the order we give them */ - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = ssid_len; - iwe.u.data.flags = 1; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, ssid); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWMODE; - if (bss) { - capabilities = bss->capab_info; - } else { - capabilities = le16_to_cpu(scan->capability); - } - if (capabilities & (WLAN_CAPABILITY_ESS | - WLAN_CAPABILITY_IBSS)) { - if (capabilities & WLAN_CAPABILITY_ESS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); - } - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWFREQ; - if (scan) { - chan = le16_to_cpu(scan->chid); - } else if (bss) { - chan = bss->chan; - } else { - chan = 0; - } - - if (chan > 0) { - iwe.u.freq.m = freq_list[chan - 1] * 100000; - iwe.u.freq.e = 1; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); - } - - if (scan) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVQUAL; - if (local->last_scan_type == PRISM2_HOSTSCAN) { - iwe.u.qual.level = le16_to_cpu(scan->sl); - iwe.u.qual.noise = le16_to_cpu(scan->anl); - } else { - iwe.u.qual.level = - HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->sl)); - iwe.u.qual.noise = - HFA384X_LEVEL_TO_dBm(le16_to_cpu(scan->anl)); - } - iwe.u.qual.updated = IW_QUAL_LEVEL_UPDATED - | IW_QUAL_NOISE_UPDATED - | IW_QUAL_QUAL_INVALID - | IW_QUAL_DBM; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); - } - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWENCODE; - if (capabilities & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, &iwe, ""); - - /* TODO: add SuppRates into BSS table */ - if (scan) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = SIOCGIWRATE; - current_val = current_ev + iwe_stream_lcp_len(info); - pos = scan->sup_rates; - for (i = 0; i < sizeof(scan->sup_rates); i++) { - if (pos[i] == 0) - break; - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((pos[i] & 0x7f) * 500000); - current_val = iwe_stream_add_value( - info, current_ev, current_val, end_buf, &iwe, - IW_EV_PARAM_LEN); - } - /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) - current_ev = current_val; - } - - /* TODO: add BeaconInt,resp_rate,atim into BSS table */ - buf = kmalloc(MAX_WPA_IE_LEN * 2 + 30, GFP_ATOMIC); - if (buf && scan) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "bcn_int=%d", le16_to_cpu(scan->beacon_interval)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); - - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "resp_rate=%d", le16_to_cpu(scan->rate)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, buf); - - if (local->last_scan_type == PRISM2_HOSTSCAN && - (capabilities & WLAN_CAPABILITY_IBSS)) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVCUSTOM; - sprintf(buf, "atim=%d", le16_to_cpu(scan->atim)); - iwe.u.data.length = strlen(buf); - current_ev = iwe_stream_add_point(info, current_ev, - end_buf, &iwe, buf); - } - } - kfree(buf); - - if (bss && bss->wpa_ie_len > 0 && bss->wpa_ie_len <= MAX_WPA_IE_LEN) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->wpa_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->wpa_ie); - } - - if (bss && bss->rsn_ie_len > 0 && bss->rsn_ie_len <= MAX_WPA_IE_LEN) { - memset(&iwe, 0, sizeof(iwe)); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->rsn_ie_len; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->rsn_ie); - } - - return current_ev; -} - - -/* Translate scan data returned from the card to a card independant - * format that the Wireless Tools will understand - Jean II */ -static inline int prism2_translate_scan(local_info_t *local, - struct iw_request_info *info, - char *buffer, int buflen) -{ - struct hfa384x_hostscan_result *scan; - int entry, hostscan; - char *current_ev = buffer; - char *end_buf = buffer + buflen; - struct list_head *ptr; - - spin_lock_bh(&local->lock); - - list_for_each(ptr, &local->bss_list) { - struct hostap_bss_info *bss; - bss = list_entry(ptr, struct hostap_bss_info, list); - bss->included = 0; - } - - hostscan = local->last_scan_type == PRISM2_HOSTSCAN; - for (entry = 0; entry < local->last_scan_results_count; entry++) { - int found = 0; - scan = &local->last_scan_results[entry]; - - /* Report every SSID if the AP is using multiple SSIDs. If no - * BSS record is found (e.g., when WPA mode is disabled), - * report the AP once. */ - list_for_each(ptr, &local->bss_list) { - struct hostap_bss_info *bss; - bss = list_entry(ptr, struct hostap_bss_info, list); - if (memcmp(bss->bssid, scan->bssid, ETH_ALEN) == 0) { - bss->included = 1; - current_ev = __prism2_translate_scan( - local, info, scan, bss, current_ev, - end_buf); - found++; - } - } - if (!found) { - current_ev = __prism2_translate_scan( - local, info, scan, NULL, current_ev, end_buf); - } - /* Check if there is space for one more entry */ - if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { - /* Ask user space to try again with a bigger buffer */ - spin_unlock_bh(&local->lock); - return -E2BIG; - } - } - - /* Prism2 firmware has limits (32 at least in some versions) for number - * of BSSes in scan results. Extend this limit by using local BSS list. - */ - list_for_each(ptr, &local->bss_list) { - struct hostap_bss_info *bss; - bss = list_entry(ptr, struct hostap_bss_info, list); - if (bss->included) - continue; - current_ev = __prism2_translate_scan(local, info, NULL, bss, - current_ev, end_buf); - /* Check if there is space for one more entry */ - if ((end_buf - current_ev) <= IW_EV_ADDR_LEN) { - /* Ask user space to try again with a bigger buffer */ - spin_unlock_bh(&local->lock); - return -E2BIG; - } - } - - spin_unlock_bh(&local->lock); - - return current_ev - buffer; -} -#endif /* PRISM2_NO_STATION_MODES */ - - -static inline int prism2_ioctl_giwscan_sta(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ -#ifdef PRISM2_NO_STATION_MODES - return -EOPNOTSUPP; -#else /* PRISM2_NO_STATION_MODES */ - struct hostap_interface *iface; - local_info_t *local; - int res; - - iface = netdev_priv(dev); - local = iface->local; - - /* Wait until the scan is finished. We can probably do better - * than that - Jean II */ - if (local->scan_timestamp && - time_before(jiffies, local->scan_timestamp + 3 * HZ)) { - /* Important note : we don't want to block the caller - * until results are ready for various reasons. - * First, managing wait queues is complex and racy - * (there may be multiple simultaneous callers). - * Second, we grab some rtnetlink lock before comming - * here (in dev_ioctl()). - * Third, the caller can wait on the Wireless Event - * - Jean II */ - return -EAGAIN; - } - local->scan_timestamp = 0; - - res = prism2_translate_scan(local, info, extra, data->length); - - if (res >= 0) { - data->length = res; - return 0; - } else { - data->length = 0; - return res; - } -#endif /* PRISM2_NO_STATION_MODES */ -} - - -static int prism2_ioctl_giwscan(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - int res; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->iw_mode == IW_MODE_MASTER) { - /* In MASTER mode, it doesn't make sense to go around - * scanning the frequencies and make the stations we serve - * wait when what the user is really interested about is the - * list of stations and access points we are talking to. - * So, just extract results from our cache... - * Jean II */ - - /* Translate to WE format */ - res = prism2_ap_translate_scan(dev, info, extra); - if (res >= 0) { - printk(KERN_DEBUG "Scan result translation succeeded " - "(length=%d)\n", res); - data->length = res; - return 0; - } else { - printk(KERN_DEBUG - "Scan result translation failed (res=%d)\n", - res); - data->length = 0; - return res; - } - } else { - /* Station mode */ - return prism2_ioctl_giwscan_sta(dev, info, data, extra); - } -} - - -static const struct iw_priv_args prism2_priv[] = { - { PRISM2_IOCTL_MONITOR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor" }, - { PRISM2_IOCTL_READMIF, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "readmif" }, - { PRISM2_IOCTL_WRITEMIF, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 2, 0, "writemif" }, - { PRISM2_IOCTL_RESET, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "reset" }, - { PRISM2_IOCTL_INQUIRE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "inquire" }, - { PRISM2_IOCTL_SET_RID_WORD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "set_rid_word" }, - { PRISM2_IOCTL_MACCMD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "maccmd" }, - { PRISM2_IOCTL_WDS_ADD, - IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_add" }, - { PRISM2_IOCTL_WDS_DEL, - IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "wds_del" }, - { PRISM2_IOCTL_ADDMAC, - IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "addmac" }, - { PRISM2_IOCTL_DELMAC, - IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "delmac" }, - { PRISM2_IOCTL_KICKMAC, - IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "kickmac" }, - /* --- raw access to sub-ioctls --- */ - { PRISM2_IOCTL_PRISM2_PARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "prism2_param" }, - { PRISM2_IOCTL_GET_PRISM2_PARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprism2_param" }, - /* --- sub-ioctls handlers --- */ - { PRISM2_IOCTL_PRISM2_PARAM, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "" }, - { PRISM2_IOCTL_GET_PRISM2_PARAM, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "" }, - /* --- sub-ioctls definitions --- */ - { PRISM2_PARAM_TXRATECTRL, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "txratectrl" }, - { PRISM2_PARAM_TXRATECTRL, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettxratectrl" }, - { PRISM2_PARAM_BEACON_INT, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "beacon_int" }, - { PRISM2_PARAM_BEACON_INT, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbeacon_int" }, -#ifndef PRISM2_NO_STATION_MODES - { PRISM2_PARAM_PSEUDO_IBSS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "pseudo_ibss" }, - { PRISM2_PARAM_PSEUDO_IBSS, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getpseudo_ibss" }, -#endif /* PRISM2_NO_STATION_MODES */ - { PRISM2_PARAM_ALC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "alc" }, - { PRISM2_PARAM_ALC, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getalc" }, - { PRISM2_PARAM_DUMP, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dump" }, - { PRISM2_PARAM_DUMP, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdump" }, - { PRISM2_PARAM_OTHER_AP_POLICY, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "other_ap_policy" }, - { PRISM2_PARAM_OTHER_AP_POLICY, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getother_ap_pol" }, - { PRISM2_PARAM_AP_MAX_INACTIVITY, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_inactivity" }, - { PRISM2_PARAM_AP_MAX_INACTIVITY, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_inactivi" }, - { PRISM2_PARAM_AP_BRIDGE_PACKETS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bridge_packets" }, - { PRISM2_PARAM_AP_BRIDGE_PACKETS, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbridge_packe" }, - { PRISM2_PARAM_DTIM_PERIOD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "dtim_period" }, - { PRISM2_PARAM_DTIM_PERIOD, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdtim_period" }, - { PRISM2_PARAM_AP_NULLFUNC_ACK, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "nullfunc_ack" }, - { PRISM2_PARAM_AP_NULLFUNC_ACK, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getnullfunc_ack" }, - { PRISM2_PARAM_MAX_WDS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "max_wds" }, - { PRISM2_PARAM_MAX_WDS, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmax_wds" }, - { PRISM2_PARAM_AP_AUTOM_AP_WDS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "autom_ap_wds" }, - { PRISM2_PARAM_AP_AUTOM_AP_WDS, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getautom_ap_wds" }, - { PRISM2_PARAM_AP_AUTH_ALGS, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_auth_algs" }, - { PRISM2_PARAM_AP_AUTH_ALGS, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_auth_algs" }, - { PRISM2_PARAM_MONITOR_ALLOW_FCSERR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "allow_fcserr" }, - { PRISM2_PARAM_MONITOR_ALLOW_FCSERR, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getallow_fcserr" }, - { PRISM2_PARAM_HOST_ENCRYPT, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_encrypt" }, - { PRISM2_PARAM_HOST_ENCRYPT, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_encrypt" }, - { PRISM2_PARAM_HOST_DECRYPT, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_decrypt" }, - { PRISM2_PARAM_HOST_DECRYPT, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_decrypt" }, -#ifndef PRISM2_NO_STATION_MODES - { PRISM2_PARAM_HOST_ROAMING, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "host_roaming" }, - { PRISM2_PARAM_HOST_ROAMING, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethost_roaming" }, -#endif /* PRISM2_NO_STATION_MODES */ - { PRISM2_PARAM_BCRX_STA_KEY, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "bcrx_sta_key" }, - { PRISM2_PARAM_BCRX_STA_KEY, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbcrx_sta_key" }, - { PRISM2_PARAM_IEEE_802_1X, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ieee_802_1x" }, - { PRISM2_PARAM_IEEE_802_1X, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getieee_802_1x" }, - { PRISM2_PARAM_ANTSEL_TX, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_tx" }, - { PRISM2_PARAM_ANTSEL_TX, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_tx" }, - { PRISM2_PARAM_ANTSEL_RX, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "antsel_rx" }, - { PRISM2_PARAM_ANTSEL_RX, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getantsel_rx" }, - { PRISM2_PARAM_MONITOR_TYPE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "monitor_type" }, - { PRISM2_PARAM_MONITOR_TYPE, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmonitor_type" }, - { PRISM2_PARAM_WDS_TYPE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wds_type" }, - { PRISM2_PARAM_WDS_TYPE, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwds_type" }, - { PRISM2_PARAM_HOSTSCAN, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostscan" }, - { PRISM2_PARAM_HOSTSCAN, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostscan" }, - { PRISM2_PARAM_AP_SCAN, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "ap_scan" }, - { PRISM2_PARAM_AP_SCAN, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getap_scan" }, - { PRISM2_PARAM_ENH_SEC, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "enh_sec" }, - { PRISM2_PARAM_ENH_SEC, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getenh_sec" }, -#ifdef PRISM2_IO_DEBUG - { PRISM2_PARAM_IO_DEBUG, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "io_debug" }, - { PRISM2_PARAM_IO_DEBUG, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getio_debug" }, -#endif /* PRISM2_IO_DEBUG */ - { PRISM2_PARAM_BASIC_RATES, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "basic_rates" }, - { PRISM2_PARAM_BASIC_RATES, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getbasic_rates" }, - { PRISM2_PARAM_OPER_RATES, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "oper_rates" }, - { PRISM2_PARAM_OPER_RATES, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getoper_rates" }, - { PRISM2_PARAM_HOSTAPD, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd" }, - { PRISM2_PARAM_HOSTAPD, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd" }, - { PRISM2_PARAM_HOSTAPD_STA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "hostapd_sta" }, - { PRISM2_PARAM_HOSTAPD_STA, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostapd_sta" }, - { PRISM2_PARAM_WPA, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wpa" }, - { PRISM2_PARAM_WPA, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwpa" }, - { PRISM2_PARAM_PRIVACY_INVOKED, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "privacy_invoked" }, - { PRISM2_PARAM_PRIVACY_INVOKED, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getprivacy_invo" }, - { PRISM2_PARAM_TKIP_COUNTERMEASURES, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "tkip_countermea" }, - { PRISM2_PARAM_TKIP_COUNTERMEASURES, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gettkip_counter" }, - { PRISM2_PARAM_DROP_UNENCRYPTED, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "drop_unencrypte" }, - { PRISM2_PARAM_DROP_UNENCRYPTED, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getdrop_unencry" }, - { PRISM2_PARAM_SCAN_CHANNEL_MASK, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "scan_channels" }, - { PRISM2_PARAM_SCAN_CHANNEL_MASK, - 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getscan_channel" }, -}; - - -static int prism2_ioctl_priv_inquire(struct net_device *dev, int *i) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->cmd(dev, HFA384X_CMDCODE_INQUIRE, *i, NULL, NULL)) - return -EOPNOTSUPP; - - return 0; -} - - -static int prism2_ioctl_priv_prism2_param(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - int *i = (int *) extra; - int param = *i; - int value = *(i + 1); - int ret = 0; - u16 val; - - iface = netdev_priv(dev); - local = iface->local; - - switch (param) { - case PRISM2_PARAM_TXRATECTRL: - local->fw_tx_rate_control = value; - break; - - case PRISM2_PARAM_BEACON_INT: - if (hostap_set_word(dev, HFA384X_RID_CNFBEACONINT, value) || - local->func->reset_port(dev)) - ret = -EINVAL; - else - local->beacon_int = value; - break; - -#ifndef PRISM2_NO_STATION_MODES - case PRISM2_PARAM_PSEUDO_IBSS: - if (value == local->pseudo_adhoc) - break; - - if (value != 0 && value != 1) { - ret = -EINVAL; - break; - } - - printk(KERN_DEBUG "prism2: %s: pseudo IBSS change %d -> %d\n", - dev->name, local->pseudo_adhoc, value); - local->pseudo_adhoc = value; - if (local->iw_mode != IW_MODE_ADHOC) - break; - - if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, - hostap_get_porttype(local))) { - ret = -EOPNOTSUPP; - break; - } - - if (local->func->reset_port(dev)) - ret = -EINVAL; - break; -#endif /* PRISM2_NO_STATION_MODES */ - - case PRISM2_PARAM_ALC: - printk(KERN_DEBUG "%s: %s ALC\n", dev->name, - value == 0 ? "Disabling" : "Enabling"); - val = HFA384X_TEST_CFG_BIT_ALC; - local->func->cmd(dev, HFA384X_CMDCODE_TEST | - (HFA384X_TEST_CFG_BITS << 8), - value == 0 ? 0 : 1, &val, NULL); - break; - - case PRISM2_PARAM_DUMP: - local->frame_dump = value; - break; - - case PRISM2_PARAM_OTHER_AP_POLICY: - if (value < 0 || value > 3) { - ret = -EINVAL; - break; - } - if (local->ap != NULL) - local->ap->ap_policy = value; - break; - - case PRISM2_PARAM_AP_MAX_INACTIVITY: - if (value < 0 || value > 7 * 24 * 60 * 60) { - ret = -EINVAL; - break; - } - if (local->ap != NULL) - local->ap->max_inactivity = value * HZ; - break; - - case PRISM2_PARAM_AP_BRIDGE_PACKETS: - if (local->ap != NULL) - local->ap->bridge_packets = value; - break; - - case PRISM2_PARAM_DTIM_PERIOD: - if (value < 0 || value > 65535) { - ret = -EINVAL; - break; - } - if (hostap_set_word(dev, HFA384X_RID_CNFOWNDTIMPERIOD, value) - || local->func->reset_port(dev)) - ret = -EINVAL; - else - local->dtim_period = value; - break; - - case PRISM2_PARAM_AP_NULLFUNC_ACK: - if (local->ap != NULL) - local->ap->nullfunc_ack = value; - break; - - case PRISM2_PARAM_MAX_WDS: - local->wds_max_connections = value; - break; - - case PRISM2_PARAM_AP_AUTOM_AP_WDS: - if (local->ap != NULL) { - if (!local->ap->autom_ap_wds && value) { - /* add WDS link to all APs in STA table */ - hostap_add_wds_links(local); - } - local->ap->autom_ap_wds = value; - } - break; - - case PRISM2_PARAM_AP_AUTH_ALGS: - local->auth_algs = value; - if (hostap_set_auth_algs(local)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_MONITOR_ALLOW_FCSERR: - local->monitor_allow_fcserr = value; - break; - - case PRISM2_PARAM_HOST_ENCRYPT: - local->host_encrypt = value; - if (hostap_set_encryption(local) || - local->func->reset_port(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_HOST_DECRYPT: - local->host_decrypt = value; - if (hostap_set_encryption(local) || - local->func->reset_port(dev)) - ret = -EINVAL; - break; - -#ifndef PRISM2_NO_STATION_MODES - case PRISM2_PARAM_HOST_ROAMING: - if (value < 0 || value > 2) { - ret = -EINVAL; - break; - } - local->host_roaming = value; - if (hostap_set_roaming(local) || local->func->reset_port(dev)) - ret = -EINVAL; - break; -#endif /* PRISM2_NO_STATION_MODES */ - - case PRISM2_PARAM_BCRX_STA_KEY: - local->bcrx_sta_key = value; - break; - - case PRISM2_PARAM_IEEE_802_1X: - local->ieee_802_1x = value; - break; - - case PRISM2_PARAM_ANTSEL_TX: - if (value < 0 || value > HOSTAP_ANTSEL_HIGH) { - ret = -EINVAL; - break; - } - local->antsel_tx = value; - hostap_set_antsel(local); - break; - - case PRISM2_PARAM_ANTSEL_RX: - if (value < 0 || value > HOSTAP_ANTSEL_HIGH) { - ret = -EINVAL; - break; - } - local->antsel_rx = value; - hostap_set_antsel(local); - break; - - case PRISM2_PARAM_MONITOR_TYPE: - if (value != PRISM2_MONITOR_80211 && - value != PRISM2_MONITOR_CAPHDR && - value != PRISM2_MONITOR_PRISM && - value != PRISM2_MONITOR_RADIOTAP) { - ret = -EINVAL; - break; - } - local->monitor_type = value; - if (local->iw_mode == IW_MODE_MONITOR) - hostap_monitor_set_type(local); - break; - - case PRISM2_PARAM_WDS_TYPE: - local->wds_type = value; - break; - - case PRISM2_PARAM_HOSTSCAN: - { - struct hfa384x_hostscan_request scan_req; - u16 rate; - - memset(&scan_req, 0, sizeof(scan_req)); - scan_req.channel_list = cpu_to_le16(0x3fff); - switch (value) { - case 1: rate = HFA384X_RATES_1MBPS; break; - case 2: rate = HFA384X_RATES_2MBPS; break; - case 3: rate = HFA384X_RATES_5MBPS; break; - case 4: rate = HFA384X_RATES_11MBPS; break; - default: rate = HFA384X_RATES_1MBPS; break; - } - scan_req.txrate = cpu_to_le16(rate); - /* leave SSID empty to accept all SSIDs */ - - if (local->iw_mode == IW_MODE_MASTER) { - if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, - HFA384X_PORTTYPE_BSS) || - local->func->reset_port(dev)) - printk(KERN_DEBUG "Leaving Host AP mode " - "for HostScan failed\n"); - } - - if (local->func->set_rid(dev, HFA384X_RID_HOSTSCAN, &scan_req, - sizeof(scan_req))) { - printk(KERN_DEBUG "HOSTSCAN failed\n"); - ret = -EINVAL; - } - if (local->iw_mode == IW_MODE_MASTER) { - wait_queue_t __wait; - init_waitqueue_entry(&__wait, current); - add_wait_queue(&local->hostscan_wq, &__wait); - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ); - if (signal_pending(current)) - ret = -EINTR; - set_current_state(TASK_RUNNING); - remove_wait_queue(&local->hostscan_wq, &__wait); - - if (hostap_set_word(dev, HFA384X_RID_CNFPORTTYPE, - HFA384X_PORTTYPE_HOSTAP) || - local->func->reset_port(dev)) - printk(KERN_DEBUG "Returning to Host AP mode " - "after HostScan failed\n"); - } - break; - } - - case PRISM2_PARAM_AP_SCAN: - local->passive_scan_interval = value; - if (timer_pending(&local->passive_scan_timer)) - del_timer(&local->passive_scan_timer); - if (value > 0) { - local->passive_scan_timer.expires = jiffies + - local->passive_scan_interval * HZ; - add_timer(&local->passive_scan_timer); - } - break; - - case PRISM2_PARAM_ENH_SEC: - if (value < 0 || value > 3) { - ret = -EINVAL; - break; - } - local->enh_sec = value; - if (hostap_set_word(dev, HFA384X_RID_CNFENHSECURITY, - local->enh_sec) || - local->func->reset_port(dev)) { - printk(KERN_INFO "%s: cnfEnhSecurity requires STA f/w " - "1.6.3 or newer\n", dev->name); - ret = -EOPNOTSUPP; - } - break; - -#ifdef PRISM2_IO_DEBUG - case PRISM2_PARAM_IO_DEBUG: - local->io_debug_enabled = value; - break; -#endif /* PRISM2_IO_DEBUG */ - - case PRISM2_PARAM_BASIC_RATES: - if ((value & local->tx_rate_control) != value || value == 0) { - printk(KERN_INFO "%s: invalid basic rate set - basic " - "rates must be in supported rate set\n", - dev->name); - ret = -EINVAL; - break; - } - local->basic_rates = value; - if (hostap_set_word(dev, HFA384X_RID_CNFBASICRATES, - local->basic_rates) || - local->func->reset_port(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_OPER_RATES: - local->tx_rate_control = value; - if (hostap_set_rate(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_HOSTAPD: - ret = hostap_set_hostapd(local, value, 1); - break; - - case PRISM2_PARAM_HOSTAPD_STA: - ret = hostap_set_hostapd_sta(local, value, 1); - break; - - case PRISM2_PARAM_WPA: - local->wpa = value; - if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0)) - ret = -EOPNOTSUPP; - else if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, - value ? 1 : 0)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_PRIVACY_INVOKED: - local->privacy_invoked = value; - if (hostap_set_encryption(local) || - local->func->reset_port(dev)) - ret = -EINVAL; - break; - - case PRISM2_PARAM_TKIP_COUNTERMEASURES: - local->tkip_countermeasures = value; - break; - - case PRISM2_PARAM_DROP_UNENCRYPTED: - local->drop_unencrypted = value; - break; - - case PRISM2_PARAM_SCAN_CHANNEL_MASK: - local->scan_channel_mask = value; - break; - - default: - printk(KERN_DEBUG "%s: prism2_param: unknown param %d\n", - dev->name, param); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - - -static int prism2_ioctl_priv_get_prism2_param(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - int *param = (int *) extra; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - switch (*param) { - case PRISM2_PARAM_TXRATECTRL: - *param = local->fw_tx_rate_control; - break; - - case PRISM2_PARAM_BEACON_INT: - *param = local->beacon_int; - break; - - case PRISM2_PARAM_PSEUDO_IBSS: - *param = local->pseudo_adhoc; - break; - - case PRISM2_PARAM_ALC: - ret = -EOPNOTSUPP; /* FIX */ - break; - - case PRISM2_PARAM_DUMP: - *param = local->frame_dump; - break; - - case PRISM2_PARAM_OTHER_AP_POLICY: - if (local->ap != NULL) - *param = local->ap->ap_policy; - else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_AP_MAX_INACTIVITY: - if (local->ap != NULL) - *param = local->ap->max_inactivity / HZ; - else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_AP_BRIDGE_PACKETS: - if (local->ap != NULL) - *param = local->ap->bridge_packets; - else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_DTIM_PERIOD: - *param = local->dtim_period; - break; - - case PRISM2_PARAM_AP_NULLFUNC_ACK: - if (local->ap != NULL) - *param = local->ap->nullfunc_ack; - else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_MAX_WDS: - *param = local->wds_max_connections; - break; - - case PRISM2_PARAM_AP_AUTOM_AP_WDS: - if (local->ap != NULL) - *param = local->ap->autom_ap_wds; - else - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_AP_AUTH_ALGS: - *param = local->auth_algs; - break; - - case PRISM2_PARAM_MONITOR_ALLOW_FCSERR: - *param = local->monitor_allow_fcserr; - break; - - case PRISM2_PARAM_HOST_ENCRYPT: - *param = local->host_encrypt; - break; - - case PRISM2_PARAM_HOST_DECRYPT: - *param = local->host_decrypt; - break; - - case PRISM2_PARAM_HOST_ROAMING: - *param = local->host_roaming; - break; - - case PRISM2_PARAM_BCRX_STA_KEY: - *param = local->bcrx_sta_key; - break; - - case PRISM2_PARAM_IEEE_802_1X: - *param = local->ieee_802_1x; - break; - - case PRISM2_PARAM_ANTSEL_TX: - *param = local->antsel_tx; - break; - - case PRISM2_PARAM_ANTSEL_RX: - *param = local->antsel_rx; - break; - - case PRISM2_PARAM_MONITOR_TYPE: - *param = local->monitor_type; - break; - - case PRISM2_PARAM_WDS_TYPE: - *param = local->wds_type; - break; - - case PRISM2_PARAM_HOSTSCAN: - ret = -EOPNOTSUPP; - break; - - case PRISM2_PARAM_AP_SCAN: - *param = local->passive_scan_interval; - break; - - case PRISM2_PARAM_ENH_SEC: - *param = local->enh_sec; - break; - -#ifdef PRISM2_IO_DEBUG - case PRISM2_PARAM_IO_DEBUG: - *param = local->io_debug_enabled; - break; -#endif /* PRISM2_IO_DEBUG */ - - case PRISM2_PARAM_BASIC_RATES: - *param = local->basic_rates; - break; - - case PRISM2_PARAM_OPER_RATES: - *param = local->tx_rate_control; - break; - - case PRISM2_PARAM_HOSTAPD: - *param = local->hostapd; - break; - - case PRISM2_PARAM_HOSTAPD_STA: - *param = local->hostapd_sta; - break; - - case PRISM2_PARAM_WPA: - if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0)) - ret = -EOPNOTSUPP; - *param = local->wpa; - break; - - case PRISM2_PARAM_PRIVACY_INVOKED: - *param = local->privacy_invoked; - break; - - case PRISM2_PARAM_TKIP_COUNTERMEASURES: - *param = local->tkip_countermeasures; - break; - - case PRISM2_PARAM_DROP_UNENCRYPTED: - *param = local->drop_unencrypted; - break; - - case PRISM2_PARAM_SCAN_CHANNEL_MASK: - *param = local->scan_channel_mask; - break; - - default: - printk(KERN_DEBUG "%s: get_prism2_param: unknown param %d\n", - dev->name, *param); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - - -static int prism2_ioctl_priv_readmif(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - u16 resp0; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->cmd(dev, HFA384X_CMDCODE_READMIF, *extra, NULL, - &resp0)) - return -EOPNOTSUPP; - else - *extra = resp0; - - return 0; -} - - -static int prism2_ioctl_priv_writemif(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, char *extra) -{ - struct hostap_interface *iface; - local_info_t *local; - u16 cr, val; - - iface = netdev_priv(dev); - local = iface->local; - - cr = *extra; - val = *(extra + 1); - if (local->func->cmd(dev, HFA384X_CMDCODE_WRITEMIF, cr, &val, NULL)) - return -EOPNOTSUPP; - - return 0; -} - - -static int prism2_ioctl_priv_monitor(struct net_device *dev, int *i) -{ - struct hostap_interface *iface; - local_info_t *local; - int ret = 0; - u32 mode; - - iface = netdev_priv(dev); - local = iface->local; - - printk(KERN_DEBUG "%s: process %d (%s) used deprecated iwpriv monitor " - "- update software to use iwconfig mode monitor\n", - dev->name, task_pid_nr(current), current->comm); - - /* Backward compatibility code - this can be removed at some point */ - - if (*i == 0) { - /* Disable monitor mode - old mode was not saved, so go to - * Master mode */ - mode = IW_MODE_MASTER; - ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL); - } else if (*i == 1) { - /* netlink socket mode is not supported anymore since it did - * not separate different devices from each other and was not - * best method for delivering large amount of packets to - * user space */ - ret = -EOPNOTSUPP; - } else if (*i == 2 || *i == 3) { - switch (*i) { - case 2: - local->monitor_type = PRISM2_MONITOR_80211; - break; - case 3: - local->monitor_type = PRISM2_MONITOR_PRISM; - break; - } - mode = IW_MODE_MONITOR; - ret = prism2_ioctl_siwmode(dev, NULL, &mode, NULL); - hostap_monitor_mode_enable(local); - } else - ret = -EINVAL; - - return ret; -} - - -static int prism2_ioctl_priv_reset(struct net_device *dev, int *i) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - printk(KERN_DEBUG "%s: manual reset request(%d)\n", dev->name, *i); - switch (*i) { - case 0: - /* Disable and enable card */ - local->func->hw_shutdown(dev, 1); - local->func->hw_config(dev, 0); - break; - - case 1: - /* COR sreset */ - local->func->hw_reset(dev); - break; - - case 2: - /* Disable and enable port 0 */ - local->func->reset_port(dev); - break; - - case 3: - prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING); - if (local->func->cmd(dev, HFA384X_CMDCODE_DISABLE, 0, NULL, - NULL)) - return -EINVAL; - break; - - case 4: - if (local->func->cmd(dev, HFA384X_CMDCODE_ENABLE, 0, NULL, - NULL)) - return -EINVAL; - break; - - default: - printk(KERN_DEBUG "Unknown reset request %d\n", *i); - return -EOPNOTSUPP; - } - - return 0; -} - - -static int prism2_ioctl_priv_set_rid_word(struct net_device *dev, int *i) -{ - int rid = *i; - int value = *(i + 1); - - printk(KERN_DEBUG "%s: Set RID[0x%X] = %d\n", dev->name, rid, value); - - if (hostap_set_word(dev, rid, value)) - return -EINVAL; - - return 0; -} - - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT -static int ap_mac_cmd_ioctl(local_info_t *local, int *cmd) -{ - int ret = 0; - - switch (*cmd) { - case AP_MAC_CMD_POLICY_OPEN: - local->ap->mac_restrictions.policy = MAC_POLICY_OPEN; - break; - case AP_MAC_CMD_POLICY_ALLOW: - local->ap->mac_restrictions.policy = MAC_POLICY_ALLOW; - break; - case AP_MAC_CMD_POLICY_DENY: - local->ap->mac_restrictions.policy = MAC_POLICY_DENY; - break; - case AP_MAC_CMD_FLUSH: - ap_control_flush_macs(&local->ap->mac_restrictions); - break; - case AP_MAC_CMD_KICKALL: - ap_control_kickall(local->ap); - hostap_deauth_all_stas(local->dev, local->ap, 0); - break; - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - -#ifdef PRISM2_DOWNLOAD_SUPPORT -static int prism2_ioctl_priv_download(local_info_t *local, struct iw_point *p) -{ - struct prism2_download_param *param; - int ret = 0; - - if (p->length < sizeof(struct prism2_download_param) || - p->length > 1024 || !p->pointer) - return -EINVAL; - - param = (struct prism2_download_param *) - kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - ret = -EFAULT; - goto out; - } - - if (p->length < sizeof(struct prism2_download_param) + - param->num_areas * sizeof(struct prism2_download_area)) { - ret = -EINVAL; - goto out; - } - - ret = local->func->download(local, param); - - out: - kfree(param); - return ret; -} -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - - -static int prism2_set_genericelement(struct net_device *dev, u8 *elem, - size_t len) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - u8 *buf; - - /* - * Add 16-bit length in the beginning of the buffer because Prism2 RID - * includes it. - */ - buf = kmalloc(len + 2, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - *((__le16 *) buf) = cpu_to_le16(len); - memcpy(buf + 2, elem, len); - - kfree(local->generic_elem); - local->generic_elem = buf; - local->generic_elem_len = len + 2; - - return local->func->set_rid(local->dev, HFA384X_RID_GENERICELEMENT, - buf, len + 2); -} - - -static int prism2_ioctl_siwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* - * Host AP driver does not use these parameters and allows - * wpa_supplicant to control them internally. - */ - break; - case IW_AUTH_TKIP_COUNTERMEASURES: - local->tkip_countermeasures = data->value; - break; - case IW_AUTH_DROP_UNENCRYPTED: - local->drop_unencrypted = data->value; - break; - case IW_AUTH_80211_AUTH_ALG: - local->auth_algs = data->value; - break; - case IW_AUTH_WPA_ENABLED: - if (data->value == 0) { - local->wpa = 0; - if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0)) - break; - prism2_set_genericelement(dev, "", 0); - local->host_roaming = 0; - local->privacy_invoked = 0; - if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, - 0) || - hostap_set_roaming(local) || - hostap_set_encryption(local) || - local->func->reset_port(dev)) - return -EINVAL; - break; - } - if (local->sta_fw_ver < PRISM2_FW_VER(1,7,0)) - return -EOPNOTSUPP; - local->host_roaming = 2; - local->privacy_invoked = 1; - local->wpa = 1; - if (hostap_set_word(dev, HFA384X_RID_SSNHANDLINGMODE, 1) || - hostap_set_roaming(local) || - hostap_set_encryption(local) || - local->func->reset_port(dev)) - return -EINVAL; - break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - local->ieee_802_1x = data->value; - break; - case IW_AUTH_PRIVACY_INVOKED: - local->privacy_invoked = data->value; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - - -static int prism2_ioctl_giwauth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *data, char *extra) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - - switch (data->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* - * Host AP driver does not use these parameters and allows - * wpa_supplicant to control them internally. - */ - return -EOPNOTSUPP; - case IW_AUTH_TKIP_COUNTERMEASURES: - data->value = local->tkip_countermeasures; - break; - case IW_AUTH_DROP_UNENCRYPTED: - data->value = local->drop_unencrypted; - break; - case IW_AUTH_80211_AUTH_ALG: - data->value = local->auth_algs; - break; - case IW_AUTH_WPA_ENABLED: - data->value = local->wpa; - break; - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - data->value = local->ieee_802_1x; - break; - default: - return -EOPNOTSUPP; - } - return 0; -} - - -static int prism2_ioctl_siwencodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *extra) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; - int i, ret = 0; - struct lib80211_crypto_ops *ops; - struct lib80211_crypt_data **crypt; - void *sta_ptr; - u8 *addr; - const char *alg, *module; - - i = erq->flags & IW_ENCODE_INDEX; - if (i > WEP_KEYS) - return -EINVAL; - if (i < 1 || i > WEP_KEYS) - i = local->crypt_info.tx_keyidx; - else - i--; - if (i < 0 || i >= WEP_KEYS) - return -EINVAL; - - addr = ext->addr.sa_data; - if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && - addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) { - sta_ptr = NULL; - crypt = &local->crypt_info.crypt[i]; - } else { - if (i != 0) - return -EINVAL; - sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt); - if (sta_ptr == NULL) { - if (local->iw_mode == IW_MODE_INFRA) { - /* - * TODO: add STA entry for the current AP so - * that unicast key can be used. For now, this - * is emulated by using default key idx 0. - */ - i = 0; - crypt = &local->crypt_info.crypt[i]; - } else - return -EINVAL; - } - } - - if ((erq->flags & IW_ENCODE_DISABLED) || - ext->alg == IW_ENCODE_ALG_NONE) { - if (*crypt) - lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); - goto done; - } - - switch (ext->alg) { - case IW_ENCODE_ALG_WEP: - alg = "WEP"; - module = "lib80211_crypt_wep"; - break; - case IW_ENCODE_ALG_TKIP: - alg = "TKIP"; - module = "lib80211_crypt_tkip"; - break; - case IW_ENCODE_ALG_CCMP: - alg = "CCMP"; - module = "lib80211_crypt_ccmp"; - break; - default: - printk(KERN_DEBUG "%s: unsupported algorithm %d\n", - local->dev->name, ext->alg); - ret = -EOPNOTSUPP; - goto done; - } - - ops = lib80211_get_crypto_ops(alg); - if (ops == NULL) { - request_module(module); - ops = lib80211_get_crypto_ops(alg); - } - if (ops == NULL) { - printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", - local->dev->name, alg); - ret = -EOPNOTSUPP; - goto done; - } - - if (sta_ptr || ext->alg != IW_ENCODE_ALG_WEP) { - /* - * Per station encryption and other than WEP algorithms - * require host-based encryption, so force them on - * automatically. - */ - local->host_decrypt = local->host_encrypt = 1; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct lib80211_crypt_data *new_crypt; - - lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); - - new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), - GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = new_crypt->ops->init(i); - if (new_crypt->priv == NULL) { - kfree(new_crypt); - ret = -EINVAL; - goto done; - } - - *crypt = new_crypt; - } - - /* - * TODO: if ext_flags does not have IW_ENCODE_EXT_RX_SEQ_VALID, the - * existing seq# should not be changed. - * TODO: if ext_flags has IW_ENCODE_EXT_TX_SEQ_VALID, next TX seq# - * should be changed to something else than zero. - */ - if ((!(ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) || ext->key_len > 0) - && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, - (*crypt)->priv) < 0) { - printk(KERN_DEBUG "%s: key setting failed\n", - local->dev->name); - ret = -EINVAL; - goto done; - } - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - if (!sta_ptr) - local->crypt_info.tx_keyidx = i; - } - - - if (sta_ptr == NULL && ext->key_len > 0) { - int first = 1, j; - for (j = 0; j < WEP_KEYS; j++) { - if (j != i && local->crypt_info.crypt[j]) { - first = 0; - break; - } - } - if (first) - local->crypt_info.tx_keyidx = i; - } - - done: - if (sta_ptr) - hostap_handle_sta_release(sta_ptr); - - local->open_wep = erq->flags & IW_ENCODE_OPEN; - - /* - * Do not reset port0 if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. Prism2 documentation seem to require port reset - * after WEP configuration. However, keys are apparently changed at - * least in Managed mode. - */ - if (ret == 0 && - (hostap_set_encryption(local) || - (local->iw_mode != IW_MODE_INFRA && - local->func->reset_port(local->dev)))) - ret = -EINVAL; - - return ret; -} - - -static int prism2_ioctl_giwencodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, char *extra) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - struct lib80211_crypt_data **crypt; - void *sta_ptr; - int max_key_len, i; - struct iw_encode_ext *ext = (struct iw_encode_ext *) extra; - u8 *addr; - - max_key_len = erq->length - sizeof(*ext); - if (max_key_len < 0) - return -EINVAL; - - i = erq->flags & IW_ENCODE_INDEX; - if (i < 1 || i > WEP_KEYS) - i = local->crypt_info.tx_keyidx; - else - i--; - - addr = ext->addr.sa_data; - if (addr[0] == 0xff && addr[1] == 0xff && addr[2] == 0xff && - addr[3] == 0xff && addr[4] == 0xff && addr[5] == 0xff) { - sta_ptr = NULL; - crypt = &local->crypt_info.crypt[i]; - } else { - i = 0; - sta_ptr = ap_crypt_get_ptrs(local->ap, addr, 0, &crypt); - if (sta_ptr == NULL) - return -EINVAL; - } - erq->flags = i + 1; - memset(ext, 0, sizeof(*ext)); - - if (*crypt == NULL || (*crypt)->ops == NULL) { - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - erq->flags |= IW_ENCODE_DISABLED; - } else { - if (strcmp((*crypt)->ops->name, "WEP") == 0) - ext->alg = IW_ENCODE_ALG_WEP; - else if (strcmp((*crypt)->ops->name, "TKIP") == 0) - ext->alg = IW_ENCODE_ALG_TKIP; - else if (strcmp((*crypt)->ops->name, "CCMP") == 0) - ext->alg = IW_ENCODE_ALG_CCMP; - else - return -EINVAL; - - if ((*crypt)->ops->get_key) { - ext->key_len = - (*crypt)->ops->get_key(ext->key, - max_key_len, - ext->tx_seq, - (*crypt)->priv); - if (ext->key_len && - (ext->alg == IW_ENCODE_ALG_TKIP || - ext->alg == IW_ENCODE_ALG_CCMP)) - ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; - } - } - - if (sta_ptr) - hostap_handle_sta_release(sta_ptr); - - return 0; -} - - -static int prism2_ioctl_set_encryption(local_info_t *local, - struct prism2_hostapd_param *param, - int param_len) -{ - int ret = 0; - struct lib80211_crypto_ops *ops; - struct lib80211_crypt_data **crypt; - void *sta_ptr; - - param->u.crypt.err = 0; - param->u.crypt.alg[HOSTAP_CRYPT_ALG_NAME_LEN - 1] = '\0'; - - if (param_len != - (int) ((char *) param->u.crypt.key - (char *) param) + - param->u.crypt.key_len) - return -EINVAL; - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - if (param->u.crypt.idx >= WEP_KEYS) - return -EINVAL; - sta_ptr = NULL; - crypt = &local->crypt_info.crypt[param->u.crypt.idx]; - } else { - if (param->u.crypt.idx) - return -EINVAL; - sta_ptr = ap_crypt_get_ptrs( - local->ap, param->sta_addr, - (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_PERMANENT), - &crypt); - - if (sta_ptr == NULL) { - param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; - return -EINVAL; - } - } - - if (strcmp(param->u.crypt.alg, "none") == 0) { - if (crypt) - lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); - goto done; - } - - ops = lib80211_get_crypto_ops(param->u.crypt.alg); - if (ops == NULL && strcmp(param->u.crypt.alg, "WEP") == 0) { - request_module("lib80211_crypt_wep"); - ops = lib80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "TKIP") == 0) { - request_module("lib80211_crypt_tkip"); - ops = lib80211_get_crypto_ops(param->u.crypt.alg); - } else if (ops == NULL && strcmp(param->u.crypt.alg, "CCMP") == 0) { - request_module("lib80211_crypt_ccmp"); - ops = lib80211_get_crypto_ops(param->u.crypt.alg); - } - if (ops == NULL) { - printk(KERN_DEBUG "%s: unknown crypto alg '%s'\n", - local->dev->name, param->u.crypt.alg); - param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ALG; - ret = -EINVAL; - goto done; - } - - /* station based encryption and other than WEP algorithms require - * host-based encryption, so force them on automatically */ - local->host_decrypt = local->host_encrypt = 1; - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct lib80211_crypt_data *new_crypt; - - lib80211_crypt_delayed_deinit(&local->crypt_info, crypt); - - new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), - GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - new_crypt->ops = ops; - new_crypt->priv = new_crypt->ops->init(param->u.crypt.idx); - if (new_crypt->priv == NULL) { - kfree(new_crypt); - param->u.crypt.err = - HOSTAP_CRYPT_ERR_CRYPT_INIT_FAILED; - ret = -EINVAL; - goto done; - } - - *crypt = new_crypt; - } - - if ((!(param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) || - param->u.crypt.key_len > 0) && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(param->u.crypt.key, - param->u.crypt.key_len, param->u.crypt.seq, - (*crypt)->priv) < 0) { - printk(KERN_DEBUG "%s: key setting failed\n", - local->dev->name); - param->u.crypt.err = HOSTAP_CRYPT_ERR_KEY_SET_FAILED; - ret = -EINVAL; - goto done; - } - - if (param->u.crypt.flags & HOSTAP_CRYPT_FLAG_SET_TX_KEY) { - if (!sta_ptr) - local->crypt_info.tx_keyidx = param->u.crypt.idx; - else if (param->u.crypt.idx) { - printk(KERN_DEBUG "%s: TX key idx setting failed\n", - local->dev->name); - param->u.crypt.err = - HOSTAP_CRYPT_ERR_TX_KEY_SET_FAILED; - ret = -EINVAL; - goto done; - } - } - - done: - if (sta_ptr) - hostap_handle_sta_release(sta_ptr); - - /* Do not reset port0 if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. Prism2 documentation seem to require port reset - * after WEP configuration. However, keys are apparently changed at - * least in Managed mode. */ - if (ret == 0 && - (hostap_set_encryption(local) || - (local->iw_mode != IW_MODE_INFRA && - local->func->reset_port(local->dev)))) { - param->u.crypt.err = HOSTAP_CRYPT_ERR_CARD_CONF_FAILED; - return -EINVAL; - } - - return ret; -} - - -static int prism2_ioctl_get_encryption(local_info_t *local, - struct prism2_hostapd_param *param, - int param_len) -{ - struct lib80211_crypt_data **crypt; - void *sta_ptr; - int max_key_len; - - param->u.crypt.err = 0; - - max_key_len = param_len - - (int) ((char *) param->u.crypt.key - (char *) param); - if (max_key_len < 0) - return -EINVAL; - - if (param->sta_addr[0] == 0xff && param->sta_addr[1] == 0xff && - param->sta_addr[2] == 0xff && param->sta_addr[3] == 0xff && - param->sta_addr[4] == 0xff && param->sta_addr[5] == 0xff) { - sta_ptr = NULL; - if (param->u.crypt.idx >= WEP_KEYS) - param->u.crypt.idx = local->crypt_info.tx_keyidx; - crypt = &local->crypt_info.crypt[param->u.crypt.idx]; - } else { - param->u.crypt.idx = 0; - sta_ptr = ap_crypt_get_ptrs(local->ap, param->sta_addr, 0, - &crypt); - - if (sta_ptr == NULL) { - param->u.crypt.err = HOSTAP_CRYPT_ERR_UNKNOWN_ADDR; - return -EINVAL; - } - } - - if (*crypt == NULL || (*crypt)->ops == NULL) { - memcpy(param->u.crypt.alg, "none", 5); - param->u.crypt.key_len = 0; - param->u.crypt.idx = 0xff; - } else { - strncpy(param->u.crypt.alg, (*crypt)->ops->name, - HOSTAP_CRYPT_ALG_NAME_LEN); - param->u.crypt.key_len = 0; - - memset(param->u.crypt.seq, 0, 8); - if ((*crypt)->ops->get_key) { - param->u.crypt.key_len = - (*crypt)->ops->get_key(param->u.crypt.key, - max_key_len, - param->u.crypt.seq, - (*crypt)->priv); - } - } - - if (sta_ptr) - hostap_handle_sta_release(sta_ptr); - - return 0; -} - - -static int prism2_ioctl_get_rid(local_info_t *local, - struct prism2_hostapd_param *param, - int param_len) -{ - int max_len, res; - - max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN; - if (max_len < 0) - return -EINVAL; - - res = local->func->get_rid(local->dev, param->u.rid.rid, - param->u.rid.data, param->u.rid.len, 0); - if (res >= 0) { - param->u.rid.len = res; - return 0; - } - - return res; -} - - -static int prism2_ioctl_set_rid(local_info_t *local, - struct prism2_hostapd_param *param, - int param_len) -{ - int max_len; - - max_len = param_len - PRISM2_HOSTAPD_RID_HDR_LEN; - if (max_len < 0 || max_len < param->u.rid.len) - return -EINVAL; - - return local->func->set_rid(local->dev, param->u.rid.rid, - param->u.rid.data, param->u.rid.len); -} - - -static int prism2_ioctl_set_assoc_ap_addr(local_info_t *local, - struct prism2_hostapd_param *param, - int param_len) -{ - printk(KERN_DEBUG "%ssta: associated as client with AP %pM\n", - local->dev->name, param->sta_addr); - memcpy(local->assoc_ap_addr, param->sta_addr, ETH_ALEN); - return 0; -} - - -static int prism2_ioctl_siwgenie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - return prism2_set_genericelement(dev, extra, data->length); -} - - -static int prism2_ioctl_giwgenie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - int len = local->generic_elem_len - 2; - - if (len <= 0 || local->generic_elem == NULL) { - data->length = 0; - return 0; - } - - if (data->length < len) - return -E2BIG; - - data->length = len; - memcpy(extra, local->generic_elem + 2, len); - - return 0; -} - - -static int prism2_ioctl_set_generic_element(local_info_t *local, - struct prism2_hostapd_param *param, - int param_len) -{ - int max_len, len; - - len = param->u.generic_elem.len; - max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; - if (max_len < 0 || max_len < len) - return -EINVAL; - - return prism2_set_genericelement(local->dev, - param->u.generic_elem.data, len); -} - - -static int prism2_ioctl_siwmlme(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - struct iw_mlme *mlme = (struct iw_mlme *) extra; - __le16 reason; - - reason = cpu_to_le16(mlme->reason_code); - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - return prism2_sta_send_mgmt(local, mlme->addr.sa_data, - IEEE80211_STYPE_DEAUTH, - (u8 *) &reason, 2); - case IW_MLME_DISASSOC: - return prism2_sta_send_mgmt(local, mlme->addr.sa_data, - IEEE80211_STYPE_DISASSOC, - (u8 *) &reason, 2); - default: - return -EOPNOTSUPP; - } -} - - -static int prism2_ioctl_mlme(local_info_t *local, - struct prism2_hostapd_param *param) -{ - __le16 reason; - - reason = cpu_to_le16(param->u.mlme.reason_code); - switch (param->u.mlme.cmd) { - case MLME_STA_DEAUTH: - return prism2_sta_send_mgmt(local, param->sta_addr, - IEEE80211_STYPE_DEAUTH, - (u8 *) &reason, 2); - case MLME_STA_DISASSOC: - return prism2_sta_send_mgmt(local, param->sta_addr, - IEEE80211_STYPE_DISASSOC, - (u8 *) &reason, 2); - default: - return -EOPNOTSUPP; - } -} - - -static int prism2_ioctl_scan_req(local_info_t *local, - struct prism2_hostapd_param *param) -{ -#ifndef PRISM2_NO_STATION_MODES - if ((local->iw_mode != IW_MODE_INFRA && - local->iw_mode != IW_MODE_ADHOC) || - (local->sta_fw_ver < PRISM2_FW_VER(1,3,1))) - return -EOPNOTSUPP; - - if (!local->dev_enabled) - return -ENETDOWN; - - return prism2_request_hostscan(local->dev, param->u.scan_req.ssid, - param->u.scan_req.ssid_len); -#else /* PRISM2_NO_STATION_MODES */ - return -EOPNOTSUPP; -#endif /* PRISM2_NO_STATION_MODES */ -} - - -static int prism2_ioctl_priv_hostapd(local_info_t *local, struct iw_point *p) -{ - struct prism2_hostapd_param *param; - int ret = 0; - int ap_ioctl = 0; - - if (p->length < sizeof(struct prism2_hostapd_param) || - p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) - return -EINVAL; - - param = kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - ret = -EFAULT; - goto out; - } - - switch (param->cmd) { - case PRISM2_SET_ENCRYPTION: - ret = prism2_ioctl_set_encryption(local, param, p->length); - break; - case PRISM2_GET_ENCRYPTION: - ret = prism2_ioctl_get_encryption(local, param, p->length); - break; - case PRISM2_HOSTAPD_GET_RID: - ret = prism2_ioctl_get_rid(local, param, p->length); - break; - case PRISM2_HOSTAPD_SET_RID: - ret = prism2_ioctl_set_rid(local, param, p->length); - break; - case PRISM2_HOSTAPD_SET_ASSOC_AP_ADDR: - ret = prism2_ioctl_set_assoc_ap_addr(local, param, p->length); - break; - case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: - ret = prism2_ioctl_set_generic_element(local, param, - p->length); - break; - case PRISM2_HOSTAPD_MLME: - ret = prism2_ioctl_mlme(local, param); - break; - case PRISM2_HOSTAPD_SCAN_REQ: - ret = prism2_ioctl_scan_req(local, param); - break; - default: - ret = prism2_hostapd(local->ap, param); - ap_ioctl = 1; - break; - } - - if (ret == 1 || !ap_ioctl) { - if (copy_to_user(p->pointer, param, p->length)) { - ret = -EFAULT; - goto out; - } else if (ap_ioctl) - ret = 0; - } - - out: - kfree(param); - return ret; -} - - -static void prism2_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - - strncpy(info->driver, "hostap", sizeof(info->driver) - 1); - snprintf(info->fw_version, sizeof(info->fw_version) - 1, - "%d.%d.%d", (local->sta_fw_ver >> 16) & 0xff, - (local->sta_fw_ver >> 8) & 0xff, - local->sta_fw_ver & 0xff); -} - -const struct ethtool_ops prism2_ethtool_ops = { - .get_drvinfo = prism2_get_drvinfo -}; - - -/* Structures to export the Wireless Handlers */ - -static const iw_handler prism2_handler[] = -{ - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) prism2_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) prism2_ioctl_siwfreq, /* SIOCSIWFREQ */ - (iw_handler) prism2_ioctl_giwfreq, /* SIOCGIWFREQ */ - (iw_handler) prism2_ioctl_siwmode, /* SIOCSIWMODE */ - (iw_handler) prism2_ioctl_giwmode, /* SIOCGIWMODE */ - (iw_handler) prism2_ioctl_siwsens, /* SIOCSIWSENS */ - (iw_handler) prism2_ioctl_giwsens, /* SIOCGIWSENS */ - (iw_handler) NULL /* not used */, /* SIOCSIWRANGE */ - (iw_handler) prism2_ioctl_giwrange, /* SIOCGIWRANGE */ - (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */ - (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */ - (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) prism2_ioctl_siwap, /* SIOCSIWAP */ - (iw_handler) prism2_ioctl_giwap, /* SIOCGIWAP */ - (iw_handler) prism2_ioctl_siwmlme, /* SIOCSIWMLME */ - (iw_handler) prism2_ioctl_giwaplist, /* SIOCGIWAPLIST */ - (iw_handler) prism2_ioctl_siwscan, /* SIOCSIWSCAN */ - (iw_handler) prism2_ioctl_giwscan, /* SIOCGIWSCAN */ - (iw_handler) prism2_ioctl_siwessid, /* SIOCSIWESSID */ - (iw_handler) prism2_ioctl_giwessid, /* SIOCGIWESSID */ - (iw_handler) prism2_ioctl_siwnickn, /* SIOCSIWNICKN */ - (iw_handler) prism2_ioctl_giwnickn, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) prism2_ioctl_siwrate, /* SIOCSIWRATE */ - (iw_handler) prism2_ioctl_giwrate, /* SIOCGIWRATE */ - (iw_handler) prism2_ioctl_siwrts, /* SIOCSIWRTS */ - (iw_handler) prism2_ioctl_giwrts, /* SIOCGIWRTS */ - (iw_handler) prism2_ioctl_siwfrag, /* SIOCSIWFRAG */ - (iw_handler) prism2_ioctl_giwfrag, /* SIOCGIWFRAG */ - (iw_handler) prism2_ioctl_siwtxpow, /* SIOCSIWTXPOW */ - (iw_handler) prism2_ioctl_giwtxpow, /* SIOCGIWTXPOW */ - (iw_handler) prism2_ioctl_siwretry, /* SIOCSIWRETRY */ - (iw_handler) prism2_ioctl_giwretry, /* SIOCGIWRETRY */ - (iw_handler) prism2_ioctl_siwencode, /* SIOCSIWENCODE */ - (iw_handler) prism2_ioctl_giwencode, /* SIOCGIWENCODE */ - (iw_handler) prism2_ioctl_siwpower, /* SIOCSIWPOWER */ - (iw_handler) prism2_ioctl_giwpower, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) prism2_ioctl_siwgenie, /* SIOCSIWGENIE */ - (iw_handler) prism2_ioctl_giwgenie, /* SIOCGIWGENIE */ - (iw_handler) prism2_ioctl_siwauth, /* SIOCSIWAUTH */ - (iw_handler) prism2_ioctl_giwauth, /* SIOCGIWAUTH */ - (iw_handler) prism2_ioctl_siwencodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) prism2_ioctl_giwencodeext, /* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ - (iw_handler) NULL, /* -- hole -- */ -}; - -static const iw_handler prism2_private_handler[] = -{ /* SIOCIWFIRSTPRIV + */ - (iw_handler) prism2_ioctl_priv_prism2_param, /* 0 */ - (iw_handler) prism2_ioctl_priv_get_prism2_param, /* 1 */ - (iw_handler) prism2_ioctl_priv_writemif, /* 2 */ - (iw_handler) prism2_ioctl_priv_readmif, /* 3 */ -}; - -const struct iw_handler_def hostap_iw_handler_def = -{ - .num_standard = ARRAY_SIZE(prism2_handler), - .num_private = ARRAY_SIZE(prism2_private_handler), - .num_private_args = ARRAY_SIZE(prism2_priv), - .standard = (iw_handler *) prism2_handler, - .private = (iw_handler *) prism2_private_handler, - .private_args = (struct iw_priv_args *) prism2_priv, - .get_wireless_stats = hostap_get_wireless_stats, -}; - - -int hostap_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct iwreq *wrq = (struct iwreq *) ifr; - struct hostap_interface *iface; - local_info_t *local; - int ret = 0; - - iface = netdev_priv(dev); - local = iface->local; - - switch (cmd) { - /* Private ioctls (iwpriv) that have not yet been converted - * into new wireless extensions API */ - - case PRISM2_IOCTL_INQUIRE: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_inquire(dev, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_MONITOR: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_monitor(dev, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_RESET: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_reset(dev, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_WDS_ADD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_wds_add(local, wrq->u.ap_addr.sa_data, 1); - break; - - case PRISM2_IOCTL_WDS_DEL: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_wds_del(local, wrq->u.ap_addr.sa_data, 1, 0); - break; - - case PRISM2_IOCTL_SET_RID_WORD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_set_rid_word(dev, - (int *) wrq->u.name); - break; - -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - case PRISM2_IOCTL_MACCMD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_mac_cmd_ioctl(local, (int *) wrq->u.name); - break; - - case PRISM2_IOCTL_ADDMAC: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_control_add_mac(&local->ap->mac_restrictions, - wrq->u.ap_addr.sa_data); - break; - case PRISM2_IOCTL_DELMAC: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_control_del_mac(&local->ap->mac_restrictions, - wrq->u.ap_addr.sa_data); - break; - case PRISM2_IOCTL_KICKMAC: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = ap_control_kick_mac(local->ap, local->dev, - wrq->u.ap_addr.sa_data); - break; -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - - /* Private ioctls that are not used with iwpriv; - * in SIOCDEVPRIVATE range */ - -#ifdef PRISM2_DOWNLOAD_SUPPORT - case PRISM2_IOCTL_DOWNLOAD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_download(local, &wrq->u.data); - break; -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - - case PRISM2_IOCTL_HOSTAPD: - if (!capable(CAP_NET_ADMIN)) ret = -EPERM; - else ret = prism2_ioctl_priv_hostapd(local, &wrq->u.data); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c deleted file mode 100644 index eb57d1ea361f..000000000000 --- a/drivers/net/wireless/hostap/hostap_main.c +++ /dev/null @@ -1,1151 +0,0 @@ -/* - * Host AP (software wireless LAN access point) driver for - * Intersil Prism2/2.5/3 - hostap.o module, common routines - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2005, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hostap_wlan.h" -#include "hostap_80211.h" -#include "hostap_ap.h" -#include "hostap.h" - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Host AP common routines"); -MODULE_LICENSE("GPL"); - -#define TX_TIMEOUT (2 * HZ) - -#define PRISM2_MAX_FRAME_SIZE 2304 -#define PRISM2_MIN_MTU 256 -/* FIX: */ -#define PRISM2_MAX_MTU (PRISM2_MAX_FRAME_SIZE - (6 /* LLC */ + 8 /* WEP */)) - - -struct net_device * hostap_add_interface(struct local_info *local, - int type, int rtnl_locked, - const char *prefix, - const char *name) -{ - struct net_device *dev, *mdev; - struct hostap_interface *iface; - int ret; - - dev = alloc_etherdev(sizeof(struct hostap_interface)); - if (dev == NULL) - return NULL; - - iface = netdev_priv(dev); - iface->dev = dev; - iface->local = local; - iface->type = type; - list_add(&iface->list, &local->hostap_interfaces); - - mdev = local->dev; - memcpy(dev->dev_addr, mdev->dev_addr, ETH_ALEN); - dev->base_addr = mdev->base_addr; - dev->irq = mdev->irq; - dev->mem_start = mdev->mem_start; - dev->mem_end = mdev->mem_end; - - hostap_setup_dev(dev, local, type); - dev->destructor = free_netdev; - - sprintf(dev->name, "%s%s", prefix, name); - if (!rtnl_locked) - rtnl_lock(); - - ret = 0; - if (strchr(dev->name, '%')) - ret = dev_alloc_name(dev, dev->name); - - SET_NETDEV_DEV(dev, mdev->dev.parent); - if (ret >= 0) - ret = register_netdevice(dev); - - if (!rtnl_locked) - rtnl_unlock(); - - if (ret < 0) { - printk(KERN_WARNING "%s: failed to add new netdevice!\n", - dev->name); - free_netdev(dev); - return NULL; - } - - printk(KERN_DEBUG "%s: registered netdevice %s\n", - mdev->name, dev->name); - - return dev; -} - - -void hostap_remove_interface(struct net_device *dev, int rtnl_locked, - int remove_from_list) -{ - struct hostap_interface *iface; - - if (!dev) - return; - - iface = netdev_priv(dev); - - if (remove_from_list) { - list_del(&iface->list); - } - - if (dev == iface->local->ddev) - iface->local->ddev = NULL; - else if (dev == iface->local->apdev) - iface->local->apdev = NULL; - else if (dev == iface->local->stadev) - iface->local->stadev = NULL; - - if (rtnl_locked) - unregister_netdevice(dev); - else - unregister_netdev(dev); - - /* dev->destructor = free_netdev() will free the device data, including - * private data, when removing the device */ -} - - -static inline int prism2_wds_special_addr(u8 *addr) -{ - if (addr[0] || addr[1] || addr[2] || addr[3] || addr[4] || addr[5]) - return 0; - - return 1; -} - - -int prism2_wds_add(local_info_t *local, u8 *remote_addr, - int rtnl_locked) -{ - struct net_device *dev; - struct list_head *ptr; - struct hostap_interface *iface, *empty, *match; - - empty = match = NULL; - read_lock_bh(&local->iface_lock); - list_for_each(ptr, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - if (iface->type != HOSTAP_INTERFACE_WDS) - continue; - - if (prism2_wds_special_addr(iface->u.wds.remote_addr)) - empty = iface; - else if (memcmp(iface->u.wds.remote_addr, remote_addr, - ETH_ALEN) == 0) { - match = iface; - break; - } - } - if (!match && empty && !prism2_wds_special_addr(remote_addr)) { - /* take pre-allocated entry into use */ - memcpy(empty->u.wds.remote_addr, remote_addr, ETH_ALEN); - read_unlock_bh(&local->iface_lock); - printk(KERN_DEBUG "%s: using pre-allocated WDS netdevice %s\n", - local->dev->name, empty->dev->name); - return 0; - } - read_unlock_bh(&local->iface_lock); - - if (!prism2_wds_special_addr(remote_addr)) { - if (match) - return -EEXIST; - hostap_add_sta(local->ap, remote_addr); - } - - if (local->wds_connections >= local->wds_max_connections) - return -ENOBUFS; - - /* verify that there is room for wds# postfix in the interface name */ - if (strlen(local->dev->name) > IFNAMSIZ - 5) { - printk(KERN_DEBUG "'%s' too long base device name\n", - local->dev->name); - return -EINVAL; - } - - dev = hostap_add_interface(local, HOSTAP_INTERFACE_WDS, rtnl_locked, - local->ddev->name, "wds%d"); - if (dev == NULL) - return -ENOMEM; - - iface = netdev_priv(dev); - memcpy(iface->u.wds.remote_addr, remote_addr, ETH_ALEN); - - local->wds_connections++; - - return 0; -} - - -int prism2_wds_del(local_info_t *local, u8 *remote_addr, - int rtnl_locked, int do_not_remove) -{ - unsigned long flags; - struct list_head *ptr; - struct hostap_interface *iface, *selected = NULL; - - write_lock_irqsave(&local->iface_lock, flags); - list_for_each(ptr, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - if (iface->type != HOSTAP_INTERFACE_WDS) - continue; - - if (memcmp(iface->u.wds.remote_addr, remote_addr, - ETH_ALEN) == 0) { - selected = iface; - break; - } - } - if (selected && !do_not_remove) - list_del(&selected->list); - write_unlock_irqrestore(&local->iface_lock, flags); - - if (selected) { - if (do_not_remove) - memset(selected->u.wds.remote_addr, 0, ETH_ALEN); - else { - hostap_remove_interface(selected->dev, rtnl_locked, 0); - local->wds_connections--; - } - } - - return selected ? 0 : -ENODEV; -} - - -u16 hostap_tx_callback_register(local_info_t *local, - void (*func)(struct sk_buff *, int ok, void *), - void *data) -{ - unsigned long flags; - struct hostap_tx_callback_info *entry; - - entry = kmalloc(sizeof(*entry), - GFP_ATOMIC); - if (entry == NULL) - return 0; - - entry->func = func; - entry->data = data; - - spin_lock_irqsave(&local->lock, flags); - entry->idx = local->tx_callback ? local->tx_callback->idx + 1 : 1; - entry->next = local->tx_callback; - local->tx_callback = entry; - spin_unlock_irqrestore(&local->lock, flags); - - return entry->idx; -} - - -int hostap_tx_callback_unregister(local_info_t *local, u16 idx) -{ - unsigned long flags; - struct hostap_tx_callback_info *cb, *prev = NULL; - - spin_lock_irqsave(&local->lock, flags); - cb = local->tx_callback; - while (cb != NULL && cb->idx != idx) { - prev = cb; - cb = cb->next; - } - if (cb) { - if (prev == NULL) - local->tx_callback = cb->next; - else - prev->next = cb->next; - kfree(cb); - } - spin_unlock_irqrestore(&local->lock, flags); - - return cb ? 0 : -1; -} - - -/* val is in host byte order */ -int hostap_set_word(struct net_device *dev, int rid, u16 val) -{ - struct hostap_interface *iface; - __le16 tmp = cpu_to_le16(val); - iface = netdev_priv(dev); - return iface->local->func->set_rid(dev, rid, &tmp, 2); -} - - -int hostap_set_string(struct net_device *dev, int rid, const char *val) -{ - struct hostap_interface *iface; - char buf[MAX_SSID_LEN + 2]; - int len; - - iface = netdev_priv(dev); - len = strlen(val); - if (len > MAX_SSID_LEN) - return -1; - memset(buf, 0, sizeof(buf)); - buf[0] = len; /* little endian 16 bit word */ - memcpy(buf + 2, val, len); - - return iface->local->func->set_rid(dev, rid, &buf, MAX_SSID_LEN + 2); -} - - -u16 hostap_get_porttype(local_info_t *local) -{ - if (local->iw_mode == IW_MODE_ADHOC && local->pseudo_adhoc) - return HFA384X_PORTTYPE_PSEUDO_IBSS; - if (local->iw_mode == IW_MODE_ADHOC) - return HFA384X_PORTTYPE_IBSS; - if (local->iw_mode == IW_MODE_INFRA) - return HFA384X_PORTTYPE_BSS; - if (local->iw_mode == IW_MODE_REPEAT) - return HFA384X_PORTTYPE_WDS; - if (local->iw_mode == IW_MODE_MONITOR) - return HFA384X_PORTTYPE_PSEUDO_IBSS; - return HFA384X_PORTTYPE_HOSTAP; -} - - -int hostap_set_encryption(local_info_t *local) -{ - u16 val, old_val; - int i, keylen, len, idx; - char keybuf[WEP_KEY_LEN + 1]; - enum { NONE, WEP, OTHER } encrypt_type; - - idx = local->crypt_info.tx_keyidx; - if (local->crypt_info.crypt[idx] == NULL || - local->crypt_info.crypt[idx]->ops == NULL) - encrypt_type = NONE; - else if (strcmp(local->crypt_info.crypt[idx]->ops->name, "WEP") == 0) - encrypt_type = WEP; - else - encrypt_type = OTHER; - - if (local->func->get_rid(local->dev, HFA384X_RID_CNFWEPFLAGS, &val, 2, - 1) < 0) { - printk(KERN_DEBUG "Could not read current WEP flags.\n"); - goto fail; - } - le16_to_cpus(&val); - old_val = val; - - if (encrypt_type != NONE || local->privacy_invoked) - val |= HFA384X_WEPFLAGS_PRIVACYINVOKED; - else - val &= ~HFA384X_WEPFLAGS_PRIVACYINVOKED; - - if (local->open_wep || encrypt_type == NONE || - ((local->ieee_802_1x || local->wpa) && local->host_decrypt)) - val &= ~HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED; - else - val |= HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED; - - if ((encrypt_type != NONE || local->privacy_invoked) && - (encrypt_type == OTHER || local->host_encrypt)) - val |= HFA384X_WEPFLAGS_HOSTENCRYPT; - else - val &= ~HFA384X_WEPFLAGS_HOSTENCRYPT; - if ((encrypt_type != NONE || local->privacy_invoked) && - (encrypt_type == OTHER || local->host_decrypt)) - val |= HFA384X_WEPFLAGS_HOSTDECRYPT; - else - val &= ~HFA384X_WEPFLAGS_HOSTDECRYPT; - - if (val != old_val && - hostap_set_word(local->dev, HFA384X_RID_CNFWEPFLAGS, val)) { - printk(KERN_DEBUG "Could not write new WEP flags (0x%x)\n", - val); - goto fail; - } - - if (encrypt_type != WEP) - return 0; - - /* 104-bit support seems to require that all the keys are set to the - * same keylen */ - keylen = 6; /* first 5 octets */ - len = local->crypt_info.crypt[idx]->ops->get_key(keybuf, sizeof(keybuf), NULL, - local->crypt_info.crypt[idx]->priv); - if (idx >= 0 && idx < WEP_KEYS && len > 5) - keylen = WEP_KEY_LEN + 1; /* first 13 octets */ - - for (i = 0; i < WEP_KEYS; i++) { - memset(keybuf, 0, sizeof(keybuf)); - if (local->crypt_info.crypt[i]) { - (void) local->crypt_info.crypt[i]->ops->get_key( - keybuf, sizeof(keybuf), - NULL, local->crypt_info.crypt[i]->priv); - } - if (local->func->set_rid(local->dev, - HFA384X_RID_CNFDEFAULTKEY0 + i, - keybuf, keylen)) { - printk(KERN_DEBUG "Could not set key %d (len=%d)\n", - i, keylen); - goto fail; - } - } - if (hostap_set_word(local->dev, HFA384X_RID_CNFWEPDEFAULTKEYID, idx)) { - printk(KERN_DEBUG "Could not set default keyid %d\n", idx); - goto fail; - } - - return 0; - - fail: - printk(KERN_DEBUG "%s: encryption setup failed\n", local->dev->name); - return -1; -} - - -int hostap_set_antsel(local_info_t *local) -{ - u16 val; - int ret = 0; - - if (local->antsel_tx != HOSTAP_ANTSEL_DO_NOT_TOUCH && - local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF, - HFA386X_CR_TX_CONFIGURE, - NULL, &val) == 0) { - val &= ~(BIT(2) | BIT(1)); - switch (local->antsel_tx) { - case HOSTAP_ANTSEL_DIVERSITY: - val |= BIT(1); - break; - case HOSTAP_ANTSEL_LOW: - break; - case HOSTAP_ANTSEL_HIGH: - val |= BIT(2); - break; - } - - if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF, - HFA386X_CR_TX_CONFIGURE, &val, NULL)) { - printk(KERN_INFO "%s: setting TX AntSel failed\n", - local->dev->name); - ret = -1; - } - } - - if (local->antsel_rx != HOSTAP_ANTSEL_DO_NOT_TOUCH && - local->func->cmd(local->dev, HFA384X_CMDCODE_READMIF, - HFA386X_CR_RX_CONFIGURE, - NULL, &val) == 0) { - val &= ~(BIT(1) | BIT(0)); - switch (local->antsel_rx) { - case HOSTAP_ANTSEL_DIVERSITY: - break; - case HOSTAP_ANTSEL_LOW: - val |= BIT(0); - break; - case HOSTAP_ANTSEL_HIGH: - val |= BIT(0) | BIT(1); - break; - } - - if (local->func->cmd(local->dev, HFA384X_CMDCODE_WRITEMIF, - HFA386X_CR_RX_CONFIGURE, &val, NULL)) { - printk(KERN_INFO "%s: setting RX AntSel failed\n", - local->dev->name); - ret = -1; - } - } - - return ret; -} - - -int hostap_set_roaming(local_info_t *local) -{ - u16 val; - - switch (local->host_roaming) { - case 1: - val = HFA384X_ROAMING_HOST; - break; - case 2: - val = HFA384X_ROAMING_DISABLED; - break; - case 0: - default: - val = HFA384X_ROAMING_FIRMWARE; - break; - } - - return hostap_set_word(local->dev, HFA384X_RID_CNFROAMINGMODE, val); -} - - -int hostap_set_auth_algs(local_info_t *local) -{ - int val = local->auth_algs; - /* At least STA f/w v0.6.2 seems to have issues with cnfAuthentication - * set to include both Open and Shared Key flags. It tries to use - * Shared Key authentication in that case even if WEP keys are not - * configured.. STA f/w v0.7.6 is able to handle such configuration, - * but it is unknown when this was fixed between 0.6.2 .. 0.7.6. */ - if (local->sta_fw_ver < PRISM2_FW_VER(0,7,0) && - val != PRISM2_AUTH_OPEN && val != PRISM2_AUTH_SHARED_KEY) - val = PRISM2_AUTH_OPEN; - - if (hostap_set_word(local->dev, HFA384X_RID_CNFAUTHENTICATION, val)) { - printk(KERN_INFO "%s: cnfAuthentication setting to 0x%x " - "failed\n", local->dev->name, local->auth_algs); - return -EINVAL; - } - - return 0; -} - - -void hostap_dump_rx_header(const char *name, const struct hfa384x_rx_frame *rx) -{ - u16 status, fc; - - status = __le16_to_cpu(rx->status); - - printk(KERN_DEBUG "%s: RX status=0x%04x (port=%d, type=%d, " - "fcserr=%d) silence=%d signal=%d rate=%d rxflow=%d; " - "jiffies=%ld\n", - name, status, (status >> 8) & 0x07, status >> 13, status & 1, - rx->silence, rx->signal, rx->rate, rx->rxflow, jiffies); - - fc = __le16_to_cpu(rx->frame_control); - printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x " - "data_len=%d%s%s\n", - fc, (fc & IEEE80211_FCTL_FTYPE) >> 2, - (fc & IEEE80211_FCTL_STYPE) >> 4, - __le16_to_cpu(rx->duration_id), __le16_to_cpu(rx->seq_ctrl), - __le16_to_cpu(rx->data_len), - fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "", - fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : ""); - - printk(KERN_DEBUG " A1=%pM A2=%pM A3=%pM A4=%pM\n", - rx->addr1, rx->addr2, rx->addr3, rx->addr4); - - printk(KERN_DEBUG " dst=%pM src=%pM len=%d\n", - rx->dst_addr, rx->src_addr, - __be16_to_cpu(rx->len)); -} - - -void hostap_dump_tx_header(const char *name, const struct hfa384x_tx_frame *tx) -{ - u16 fc; - - printk(KERN_DEBUG "%s: TX status=0x%04x retry_count=%d tx_rate=%d " - "tx_control=0x%04x; jiffies=%ld\n", - name, __le16_to_cpu(tx->status), tx->retry_count, tx->tx_rate, - __le16_to_cpu(tx->tx_control), jiffies); - - fc = __le16_to_cpu(tx->frame_control); - printk(KERN_DEBUG " FC=0x%04x (type=%d:%d) dur=0x%04x seq=0x%04x " - "data_len=%d%s%s\n", - fc, (fc & IEEE80211_FCTL_FTYPE) >> 2, - (fc & IEEE80211_FCTL_STYPE) >> 4, - __le16_to_cpu(tx->duration_id), __le16_to_cpu(tx->seq_ctrl), - __le16_to_cpu(tx->data_len), - fc & IEEE80211_FCTL_TODS ? " [ToDS]" : "", - fc & IEEE80211_FCTL_FROMDS ? " [FromDS]" : ""); - - printk(KERN_DEBUG " A1=%pM A2=%pM A3=%pM A4=%pM\n", - tx->addr1, tx->addr2, tx->addr3, tx->addr4); - - printk(KERN_DEBUG " dst=%pM src=%pM len=%d\n", - tx->dst_addr, tx->src_addr, - __be16_to_cpu(tx->len)); -} - - -static int hostap_80211_header_parse(const struct sk_buff *skb, - unsigned char *haddr) -{ - memcpy(haddr, skb_mac_header(skb) + 10, ETH_ALEN); /* addr2 */ - return ETH_ALEN; -} - - -int hostap_80211_get_hdrlen(__le16 fc) -{ - if (ieee80211_is_data(fc) && ieee80211_has_a4 (fc)) - return 30; /* Addr4 */ - else if (ieee80211_is_cts(fc) || ieee80211_is_ack(fc)) - return 10; - else if (ieee80211_is_ctl(fc)) - return 16; - - return 24; -} - - -static int prism2_close(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - - PDEBUG(DEBUG_FLOW, "%s: prism2_close\n", dev->name); - - iface = netdev_priv(dev); - local = iface->local; - - if (dev == local->ddev) { - prism2_sta_deauth(local, WLAN_REASON_DEAUTH_LEAVING); - } -#ifndef PRISM2_NO_KERNEL_IEEE80211_MGMT - if (!local->hostapd && dev == local->dev && - (!local->func->card_present || local->func->card_present(local)) && - local->hw_ready && local->ap && local->iw_mode == IW_MODE_MASTER) - hostap_deauth_all_stas(dev, local->ap, 1); -#endif /* PRISM2_NO_KERNEL_IEEE80211_MGMT */ - - if (dev == local->dev) { - local->func->hw_shutdown(dev, HOSTAP_HW_ENABLE_CMDCOMPL); - } - - if (netif_running(dev)) { - netif_stop_queue(dev); - netif_device_detach(dev); - } - - cancel_work_sync(&local->reset_queue); - cancel_work_sync(&local->set_multicast_list_queue); - cancel_work_sync(&local->set_tim_queue); -#ifndef PRISM2_NO_STATION_MODES - cancel_work_sync(&local->info_queue); -#endif - cancel_work_sync(&local->comms_qual_update); - - module_put(local->hw_module); - - local->num_dev_open--; - - if (dev != local->dev && local->dev->flags & IFF_UP && - local->master_dev_auto_open && local->num_dev_open == 1) { - /* Close master radio interface automatically if it was also - * opened automatically and we are now closing the last - * remaining non-master device. */ - dev_close(local->dev); - } - - return 0; -} - - -static int prism2_open(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - - PDEBUG(DEBUG_FLOW, "%s: prism2_open\n", dev->name); - - iface = netdev_priv(dev); - local = iface->local; - - if (local->no_pri) { - printk(KERN_DEBUG "%s: could not set interface UP - no PRI " - "f/w\n", dev->name); - return 1; - } - - if ((local->func->card_present && !local->func->card_present(local)) || - local->hw_downloading) - return -ENODEV; - - if (!try_module_get(local->hw_module)) - return -ENODEV; - local->num_dev_open++; - - if (!local->dev_enabled && local->func->hw_enable(dev, 1)) { - printk(KERN_WARNING "%s: could not enable MAC port\n", - dev->name); - prism2_close(dev); - return 1; - } - if (!local->dev_enabled) - prism2_callback(local, PRISM2_CALLBACK_ENABLE); - local->dev_enabled = 1; - - if (dev != local->dev && !(local->dev->flags & IFF_UP)) { - /* Master radio interface is needed for all operation, so open - * it automatically when any virtual net_device is opened. */ - local->master_dev_auto_open = 1; - dev_open(local->dev); - } - - netif_device_attach(dev); - netif_start_queue(dev); - - return 0; -} - - -static int prism2_set_mac_address(struct net_device *dev, void *p) -{ - struct hostap_interface *iface; - local_info_t *local; - struct list_head *ptr; - struct sockaddr *addr = p; - - iface = netdev_priv(dev); - local = iface->local; - - if (local->func->set_rid(dev, HFA384X_RID_CNFOWNMACADDR, addr->sa_data, - ETH_ALEN) < 0 || local->func->reset_port(dev)) - return -EINVAL; - - read_lock_bh(&local->iface_lock); - list_for_each(ptr, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - memcpy(iface->dev->dev_addr, addr->sa_data, ETH_ALEN); - } - memcpy(local->dev->dev_addr, addr->sa_data, ETH_ALEN); - read_unlock_bh(&local->iface_lock); - - return 0; -} - - -/* TODO: to be further implemented as soon as Prism2 fully supports - * GroupAddresses and correct documentation is available */ -void hostap_set_multicast_list_queue(struct work_struct *work) -{ - local_info_t *local = - container_of(work, local_info_t, set_multicast_list_queue); - struct net_device *dev = local->dev; - struct hostap_interface *iface; - - iface = netdev_priv(dev); - if (hostap_set_word(dev, HFA384X_RID_PROMISCUOUSMODE, - local->is_promisc)) { - printk(KERN_INFO "%s: %sabling promiscuous mode failed\n", - dev->name, local->is_promisc ? "en" : "dis"); - } -} - - -static void hostap_set_multicast_list(struct net_device *dev) -{ -#if 0 - /* FIX: promiscuous mode seems to be causing a lot of problems with - * some station firmware versions (FCSErr frames, invalid MACPort, etc. - * corrupted incoming frames). This code is now commented out while the - * problems are investigated. */ - struct hostap_interface *iface; - local_info_t *local; - - iface = netdev_priv(dev); - local = iface->local; - if ((dev->flags & IFF_ALLMULTI) || (dev->flags & IFF_PROMISC)) { - local->is_promisc = 1; - } else { - local->is_promisc = 0; - } - - schedule_work(&local->set_multicast_list_queue); -#endif -} - - -static int prism2_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < PRISM2_MIN_MTU || new_mtu > PRISM2_MAX_MTU) - return -EINVAL; - - dev->mtu = new_mtu; - return 0; -} - - -static void prism2_tx_timeout(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - struct hfa384x_regs regs; - - iface = netdev_priv(dev); - local = iface->local; - - printk(KERN_WARNING "%s Tx timed out! Resetting card\n", dev->name); - netif_stop_queue(local->dev); - - local->func->read_regs(dev, ®s); - printk(KERN_DEBUG "%s: CMD=%04x EVSTAT=%04x " - "OFFSET0=%04x OFFSET1=%04x SWSUPPORT0=%04x\n", - dev->name, regs.cmd, regs.evstat, regs.offset0, regs.offset1, - regs.swsupport0); - - local->func->schedule_reset(local); -} - -const struct header_ops hostap_80211_ops = { - .create = eth_header, - .rebuild = eth_rebuild_header, - .cache = eth_header_cache, - .cache_update = eth_header_cache_update, - .parse = hostap_80211_header_parse, -}; -EXPORT_SYMBOL(hostap_80211_ops); - - -static const struct net_device_ops hostap_netdev_ops = { - .ndo_start_xmit = hostap_data_start_xmit, - - .ndo_open = prism2_open, - .ndo_stop = prism2_close, - .ndo_do_ioctl = hostap_ioctl, - .ndo_set_mac_address = prism2_set_mac_address, - .ndo_set_multicast_list = hostap_set_multicast_list, - .ndo_change_mtu = prism2_change_mtu, - .ndo_tx_timeout = prism2_tx_timeout, - .ndo_validate_addr = eth_validate_addr, -}; - -static const struct net_device_ops hostap_mgmt_netdev_ops = { - .ndo_start_xmit = hostap_mgmt_start_xmit, - - .ndo_open = prism2_open, - .ndo_stop = prism2_close, - .ndo_do_ioctl = hostap_ioctl, - .ndo_set_mac_address = prism2_set_mac_address, - .ndo_set_multicast_list = hostap_set_multicast_list, - .ndo_change_mtu = prism2_change_mtu, - .ndo_tx_timeout = prism2_tx_timeout, - .ndo_validate_addr = eth_validate_addr, -}; - -static const struct net_device_ops hostap_master_ops = { - .ndo_start_xmit = hostap_master_start_xmit, - - .ndo_open = prism2_open, - .ndo_stop = prism2_close, - .ndo_do_ioctl = hostap_ioctl, - .ndo_set_mac_address = prism2_set_mac_address, - .ndo_set_multicast_list = hostap_set_multicast_list, - .ndo_change_mtu = prism2_change_mtu, - .ndo_tx_timeout = prism2_tx_timeout, - .ndo_validate_addr = eth_validate_addr, -}; - -void hostap_setup_dev(struct net_device *dev, local_info_t *local, - int type) -{ - struct hostap_interface *iface; - - iface = netdev_priv(dev); - ether_setup(dev); - - /* kernel callbacks */ - if (iface) { - /* Currently, we point to the proper spy_data only on - * the main_dev. This could be fixed. Jean II */ - iface->wireless_data.spy_data = &iface->spy_data; - dev->wireless_data = &iface->wireless_data; - } - dev->wireless_handlers = &hostap_iw_handler_def; - dev->watchdog_timeo = TX_TIMEOUT; - - switch(type) { - case HOSTAP_INTERFACE_AP: - dev->tx_queue_len = 0; /* use main radio device queue */ - dev->netdev_ops = &hostap_mgmt_netdev_ops; - dev->type = ARPHRD_IEEE80211; - dev->header_ops = &hostap_80211_ops; - break; - case HOSTAP_INTERFACE_MASTER: - dev->netdev_ops = &hostap_master_ops; - break; - default: - dev->tx_queue_len = 0; /* use main radio device queue */ - dev->netdev_ops = &hostap_netdev_ops; - } - - dev->mtu = local->mtu; - - - SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops); - - netif_stop_queue(dev); -} - -static int hostap_enable_hostapd(local_info_t *local, int rtnl_locked) -{ - struct net_device *dev = local->dev; - - if (local->apdev) - return -EEXIST; - - printk(KERN_DEBUG "%s: enabling hostapd mode\n", dev->name); - - local->apdev = hostap_add_interface(local, HOSTAP_INTERFACE_AP, - rtnl_locked, local->ddev->name, - "ap"); - if (local->apdev == NULL) - return -ENOMEM; - - return 0; -} - - -static int hostap_disable_hostapd(local_info_t *local, int rtnl_locked) -{ - struct net_device *dev = local->dev; - - printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name); - - hostap_remove_interface(local->apdev, rtnl_locked, 1); - local->apdev = NULL; - - return 0; -} - - -static int hostap_enable_hostapd_sta(local_info_t *local, int rtnl_locked) -{ - struct net_device *dev = local->dev; - - if (local->stadev) - return -EEXIST; - - printk(KERN_DEBUG "%s: enabling hostapd STA mode\n", dev->name); - - local->stadev = hostap_add_interface(local, HOSTAP_INTERFACE_STA, - rtnl_locked, local->ddev->name, - "sta"); - if (local->stadev == NULL) - return -ENOMEM; - - return 0; -} - - -static int hostap_disable_hostapd_sta(local_info_t *local, int rtnl_locked) -{ - struct net_device *dev = local->dev; - - printk(KERN_DEBUG "%s: disabling hostapd mode\n", dev->name); - - hostap_remove_interface(local->stadev, rtnl_locked, 1); - local->stadev = NULL; - - return 0; -} - - -int hostap_set_hostapd(local_info_t *local, int val, int rtnl_locked) -{ - int ret; - - if (val < 0 || val > 1) - return -EINVAL; - - if (local->hostapd == val) - return 0; - - if (val) { - ret = hostap_enable_hostapd(local, rtnl_locked); - if (ret == 0) - local->hostapd = 1; - } else { - local->hostapd = 0; - ret = hostap_disable_hostapd(local, rtnl_locked); - if (ret != 0) - local->hostapd = 1; - } - - return ret; -} - - -int hostap_set_hostapd_sta(local_info_t *local, int val, int rtnl_locked) -{ - int ret; - - if (val < 0 || val > 1) - return -EINVAL; - - if (local->hostapd_sta == val) - return 0; - - if (val) { - ret = hostap_enable_hostapd_sta(local, rtnl_locked); - if (ret == 0) - local->hostapd_sta = 1; - } else { - local->hostapd_sta = 0; - ret = hostap_disable_hostapd_sta(local, rtnl_locked); - if (ret != 0) - local->hostapd_sta = 1; - } - - - return ret; -} - - -int prism2_update_comms_qual(struct net_device *dev) -{ - struct hostap_interface *iface; - local_info_t *local; - int ret = 0; - struct hfa384x_comms_quality sq; - - iface = netdev_priv(dev); - local = iface->local; - if (!local->sta_fw_ver) - ret = -1; - else if (local->sta_fw_ver >= PRISM2_FW_VER(1,3,1)) { - if (local->func->get_rid(local->dev, - HFA384X_RID_DBMCOMMSQUALITY, - &sq, sizeof(sq), 1) >= 0) { - local->comms_qual = (s16) le16_to_cpu(sq.comm_qual); - local->avg_signal = (s16) le16_to_cpu(sq.signal_level); - local->avg_noise = (s16) le16_to_cpu(sq.noise_level); - local->last_comms_qual_update = jiffies; - } else - ret = -1; - } else { - if (local->func->get_rid(local->dev, HFA384X_RID_COMMSQUALITY, - &sq, sizeof(sq), 1) >= 0) { - local->comms_qual = le16_to_cpu(sq.comm_qual); - local->avg_signal = HFA384X_LEVEL_TO_dBm( - le16_to_cpu(sq.signal_level)); - local->avg_noise = HFA384X_LEVEL_TO_dBm( - le16_to_cpu(sq.noise_level)); - local->last_comms_qual_update = jiffies; - } else - ret = -1; - } - - return ret; -} - - -int prism2_sta_send_mgmt(local_info_t *local, u8 *dst, u16 stype, - u8 *body, size_t bodylen) -{ - struct sk_buff *skb; - struct hostap_ieee80211_mgmt *mgmt; - struct hostap_skb_tx_data *meta; - struct net_device *dev = local->dev; - - skb = dev_alloc_skb(IEEE80211_MGMT_HDR_LEN + bodylen); - if (skb == NULL) - return -ENOMEM; - - mgmt = (struct hostap_ieee80211_mgmt *) - skb_put(skb, IEEE80211_MGMT_HDR_LEN); - memset(mgmt, 0, IEEE80211_MGMT_HDR_LEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype); - memcpy(mgmt->da, dst, ETH_ALEN); - memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN); - memcpy(mgmt->bssid, dst, ETH_ALEN); - if (body) - memcpy(skb_put(skb, bodylen), body, bodylen); - - meta = (struct hostap_skb_tx_data *) skb->cb; - memset(meta, 0, sizeof(*meta)); - meta->magic = HOSTAP_SKB_TX_DATA_MAGIC; - meta->iface = netdev_priv(dev); - - skb->dev = dev; - skb_reset_mac_header(skb); - skb_reset_network_header(skb); - dev_queue_xmit(skb); - - return 0; -} - - -int prism2_sta_deauth(local_info_t *local, u16 reason) -{ - union iwreq_data wrqu; - int ret; - __le16 val = cpu_to_le16(reason); - - if (local->iw_mode != IW_MODE_INFRA || - memcmp(local->bssid, "\x00\x00\x00\x00\x00\x00", ETH_ALEN) == 0 || - memcmp(local->bssid, "\x44\x44\x44\x44\x44\x44", ETH_ALEN) == 0) - return 0; - - ret = prism2_sta_send_mgmt(local, local->bssid, IEEE80211_STYPE_DEAUTH, - (u8 *) &val, 2); - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(local->dev, SIOCGIWAP, &wrqu, NULL); - return ret; -} - - -struct proc_dir_entry *hostap_proc; - -static int __init hostap_init(void) -{ - if (init_net.proc_net != NULL) { - hostap_proc = proc_mkdir("hostap", init_net.proc_net); - if (!hostap_proc) - printk(KERN_WARNING "Failed to mkdir " - "/proc/net/hostap\n"); - } else - hostap_proc = NULL; - - return 0; -} - - -static void __exit hostap_exit(void) -{ - if (hostap_proc != NULL) { - hostap_proc = NULL; - remove_proc_entry("hostap", init_net.proc_net); - } -} - - -EXPORT_SYMBOL(hostap_set_word); -EXPORT_SYMBOL(hostap_set_string); -EXPORT_SYMBOL(hostap_get_porttype); -EXPORT_SYMBOL(hostap_set_encryption); -EXPORT_SYMBOL(hostap_set_antsel); -EXPORT_SYMBOL(hostap_set_roaming); -EXPORT_SYMBOL(hostap_set_auth_algs); -EXPORT_SYMBOL(hostap_dump_rx_header); -EXPORT_SYMBOL(hostap_dump_tx_header); -EXPORT_SYMBOL(hostap_80211_get_hdrlen); -EXPORT_SYMBOL(hostap_setup_dev); -EXPORT_SYMBOL(hostap_set_multicast_list_queue); -EXPORT_SYMBOL(hostap_set_hostapd); -EXPORT_SYMBOL(hostap_set_hostapd_sta); -EXPORT_SYMBOL(hostap_add_interface); -EXPORT_SYMBOL(hostap_remove_interface); -EXPORT_SYMBOL(prism2_update_comms_qual); - -module_init(hostap_init); -module_exit(hostap_exit); diff --git a/drivers/net/wireless/hostap/hostap_pci.c b/drivers/net/wireless/hostap/hostap_pci.c deleted file mode 100644 index e131161137ae..000000000000 --- a/drivers/net/wireless/hostap/hostap_pci.c +++ /dev/null @@ -1,473 +0,0 @@ -#define PRISM2_PCI - -/* Host AP driver's support for Intersil Prism2.5 PCI cards is based on - * driver patches from Reyk Floeter and - * Andy Warner */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "hostap_wlan.h" - - -static char *dev_info = "hostap_pci"; - - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Support for Intersil Prism2.5-based 802.11 wireless LAN " - "PCI cards."); -MODULE_SUPPORTED_DEVICE("Intersil Prism2.5-based WLAN PCI cards"); -MODULE_LICENSE("GPL"); - - -/* struct local_info::hw_priv */ -struct hostap_pci_priv { - void __iomem *mem_start; -}; - - -/* FIX: do we need mb/wmb/rmb with memory operations? */ - - -static struct pci_device_id prism2_pci_id_table[] __devinitdata = { - /* Intersil Prism3 ISL3872 11Mb/s WLAN Controller */ - { 0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID }, - /* Intersil Prism2.5 ISL3874 11Mb/s WLAN Controller */ - { 0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID }, - /* Samsung MagicLAN SWL-2210P */ - { 0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID }, - { 0 } -}; - - -#ifdef PRISM2_IO_DEBUG - -static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - hw_priv = local->hw_priv; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); - writeb(v, hw_priv->mem_start + a); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - local_info_t *local; - unsigned long flags; - u8 v; - - iface = netdev_priv(dev); - local = iface->local; - hw_priv = local->hw_priv; - - spin_lock_irqsave(&local->lock, flags); - v = readb(hw_priv->mem_start + a); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); - spin_unlock_irqrestore(&local->lock, flags); - return v; -} - -static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - hw_priv = local->hw_priv; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); - writew(v, hw_priv->mem_start + a); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - local_info_t *local; - unsigned long flags; - u16 v; - - iface = netdev_priv(dev); - local = iface->local; - hw_priv = local->hw_priv; - - spin_lock_irqsave(&local->lock, flags); - v = readw(hw_priv->mem_start + a); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); - spin_unlock_irqrestore(&local->lock, flags); - return v; -} - -#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) -#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) -#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) -#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) -#define HFA384X_OUTW_DATA(v,a) hfa384x_outw_debug(dev, (a), le16_to_cpu((v))) -#define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw_debug(dev, (a))) - -#else /* PRISM2_IO_DEBUG */ - -static inline void hfa384x_outb(struct net_device *dev, int a, u8 v) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - writeb(v, hw_priv->mem_start + a); -} - -static inline u8 hfa384x_inb(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - return readb(hw_priv->mem_start + a); -} - -static inline void hfa384x_outw(struct net_device *dev, int a, u16 v) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - writew(v, hw_priv->mem_start + a); -} - -static inline u16 hfa384x_inw(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - return readw(hw_priv->mem_start + a); -} - -#define HFA384X_OUTB(v,a) hfa384x_outb(dev, (a), (v)) -#define HFA384X_INB(a) hfa384x_inb(dev, (a)) -#define HFA384X_OUTW(v,a) hfa384x_outw(dev, (a), (v)) -#define HFA384X_INW(a) hfa384x_inw(dev, (a)) -#define HFA384X_OUTW_DATA(v,a) hfa384x_outw(dev, (a), le16_to_cpu((v))) -#define HFA384X_INW_DATA(a) cpu_to_le16(hfa384x_inw(dev, (a))) - -#endif /* PRISM2_IO_DEBUG */ - - -static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, - int len) -{ - u16 d_off; - __le16 *pos; - - d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; - pos = (__le16 *) buf; - - for ( ; len > 1; len -= 2) - *pos++ = HFA384X_INW_DATA(d_off); - - if (len & 1) - *((char *) pos) = HFA384X_INB(d_off); - - return 0; -} - - -static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) -{ - u16 d_off; - __le16 *pos; - - d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; - pos = (__le16 *) buf; - - for ( ; len > 1; len -= 2) - HFA384X_OUTW_DATA(*pos++, d_off); - - if (len & 1) - HFA384X_OUTB(*((char *) pos), d_off); - - return 0; -} - - -/* FIX: This might change at some point.. */ -#include "hostap_hw.c" - -static void prism2_pci_cor_sreset(local_info_t *local) -{ - struct net_device *dev = local->dev; - u16 reg; - - reg = HFA384X_INB(HFA384X_PCICOR_OFF); - printk(KERN_DEBUG "%s: Original COR value: 0x%0x\n", dev->name, reg); - - /* linux-wlan-ng uses extremely long hold and settle times for - * COR sreset. A comment in the driver code mentions that the long - * delays appear to be necessary. However, at least IBM 22P6901 seems - * to work fine with shorter delays. - * - * Longer delays can be configured by uncommenting following line: */ -/* #define PRISM2_PCI_USE_LONG_DELAYS */ - -#ifdef PRISM2_PCI_USE_LONG_DELAYS - int i; - - HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF); - mdelay(250); - - HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF); - mdelay(500); - - /* Wait for f/w to complete initialization (CMD:BUSY == 0) */ - i = 2000000 / 10; - while ((HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) && --i) - udelay(10); - -#else /* PRISM2_PCI_USE_LONG_DELAYS */ - - HFA384X_OUTW(reg | 0x0080, HFA384X_PCICOR_OFF); - mdelay(2); - HFA384X_OUTW(reg & ~0x0080, HFA384X_PCICOR_OFF); - mdelay(2); - -#endif /* PRISM2_PCI_USE_LONG_DELAYS */ - - if (HFA384X_INW(HFA384X_CMD_OFF) & HFA384X_CMD_BUSY) { - printk(KERN_DEBUG "%s: COR sreset timeout\n", dev->name); - } -} - - -static void prism2_pci_genesis_reset(local_info_t *local, int hcr) -{ - struct net_device *dev = local->dev; - - HFA384X_OUTW(0x00C5, HFA384X_PCICOR_OFF); - mdelay(10); - HFA384X_OUTW(hcr, HFA384X_PCIHCR_OFF); - mdelay(10); - HFA384X_OUTW(0x0045, HFA384X_PCICOR_OFF); - mdelay(10); -} - - -static struct prism2_helper_functions prism2_pci_funcs = -{ - .card_present = NULL, - .cor_sreset = prism2_pci_cor_sreset, - .genesis_reset = prism2_pci_genesis_reset, - .hw_type = HOSTAP_HW_PCI, -}; - - -static int prism2_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned long phymem; - void __iomem *mem = NULL; - local_info_t *local = NULL; - struct net_device *dev = NULL; - static int cards_found /* = 0 */; - int irq_registered = 0; - struct hostap_interface *iface; - struct hostap_pci_priv *hw_priv; - - hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); - if (hw_priv == NULL) - return -ENOMEM; - - if (pci_enable_device(pdev)) - goto err_out_free; - - phymem = pci_resource_start(pdev, 0); - - if (!request_mem_region(phymem, pci_resource_len(pdev, 0), "Prism2")) { - printk(KERN_ERR "prism2: Cannot reserve PCI memory region\n"); - goto err_out_disable; - } - - mem = pci_ioremap_bar(pdev, 0); - if (mem == NULL) { - printk(KERN_ERR "prism2: Cannot remap PCI memory region\n") ; - goto fail; - } - - dev = prism2_init_local_data(&prism2_pci_funcs, cards_found, - &pdev->dev); - if (dev == NULL) - goto fail; - iface = netdev_priv(dev); - local = iface->local; - local->hw_priv = hw_priv; - cards_found++; - - dev->irq = pdev->irq; - hw_priv->mem_start = mem; - dev->base_addr = (unsigned long) mem; - - prism2_pci_cor_sreset(local); - - pci_set_drvdata(pdev, dev); - - if (request_irq(dev->irq, prism2_interrupt, IRQF_SHARED, dev->name, - dev)) { - printk(KERN_WARNING "%s: request_irq failed\n", dev->name); - goto fail; - } else - irq_registered = 1; - - if (!local->pri_only && prism2_hw_config(dev, 1)) { - printk(KERN_DEBUG "%s: hardware initialization failed\n", - dev_info); - goto fail; - } - - printk(KERN_INFO "%s: Intersil Prism2.5 PCI: " - "mem=0x%lx, irq=%d\n", dev->name, phymem, dev->irq); - - return hostap_hw_ready(dev); - - fail: - if (irq_registered && dev) - free_irq(dev->irq, dev); - - if (mem) - iounmap(mem); - - release_mem_region(phymem, pci_resource_len(pdev, 0)); - - err_out_disable: - pci_disable_device(pdev); - prism2_free_local_data(dev); - - err_out_free: - kfree(hw_priv); - - return -ENODEV; -} - - -static void prism2_pci_remove(struct pci_dev *pdev) -{ - struct net_device *dev; - struct hostap_interface *iface; - void __iomem *mem_start; - struct hostap_pci_priv *hw_priv; - - dev = pci_get_drvdata(pdev); - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - - /* Reset the hardware, and ensure interrupts are disabled. */ - prism2_pci_cor_sreset(iface->local); - hfa384x_disable_interrupts(dev); - - if (dev->irq) - free_irq(dev->irq, dev); - - mem_start = hw_priv->mem_start; - prism2_free_local_data(dev); - kfree(hw_priv); - - iounmap(mem_start); - - release_mem_region(pci_resource_start(pdev, 0), - pci_resource_len(pdev, 0)); - pci_disable_device(pdev); -} - - -#ifdef CONFIG_PM -static int prism2_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - - if (netif_running(dev)) { - netif_stop_queue(dev); - netif_device_detach(dev); - } - prism2_suspend(dev); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int prism2_pci_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - int err; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s: pci_enable_device failed on resume\n", - dev->name); - return err; - } - pci_restore_state(pdev); - prism2_hw_config(dev, 0); - if (netif_running(dev)) { - netif_device_attach(dev); - netif_start_queue(dev); - } - - return 0; -} -#endif /* CONFIG_PM */ - - -MODULE_DEVICE_TABLE(pci, prism2_pci_id_table); - -static struct pci_driver prism2_pci_driver = { - .name = "hostap_pci", - .id_table = prism2_pci_id_table, - .probe = prism2_pci_probe, - .remove = prism2_pci_remove, -#ifdef CONFIG_PM - .suspend = prism2_pci_suspend, - .resume = prism2_pci_resume, -#endif /* CONFIG_PM */ -}; - - -static int __init init_prism2_pci(void) -{ - return pci_register_driver(&prism2_pci_driver); -} - - -static void __exit exit_prism2_pci(void) -{ - pci_unregister_driver(&prism2_pci_driver); -} - - -module_init(init_prism2_pci); -module_exit(exit_prism2_pci); diff --git a/drivers/net/wireless/hostap/hostap_plx.c b/drivers/net/wireless/hostap/hostap_plx.c deleted file mode 100644 index 0e5d51086a44..000000000000 --- a/drivers/net/wireless/hostap/hostap_plx.c +++ /dev/null @@ -1,632 +0,0 @@ -#define PRISM2_PLX - -/* Host AP driver's support for PC Cards on PCI adapters using PLX9052 is - * based on: - * - Host AP driver patch from james@madingley.org - * - linux-wlan-ng driver, Copyright (C) AbsoluteValue Systems, Inc. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "hostap_wlan.h" - - -static char *dev_info = "hostap_plx"; - - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Support for Intersil Prism2-based 802.11 wireless LAN " - "cards (PLX)."); -MODULE_SUPPORTED_DEVICE("Intersil Prism2-based WLAN cards (PLX)"); -MODULE_LICENSE("GPL"); - - -static int ignore_cis; -module_param(ignore_cis, int, 0444); -MODULE_PARM_DESC(ignore_cis, "Do not verify manfid information in CIS"); - - -/* struct local_info::hw_priv */ -struct hostap_plx_priv { - void __iomem *attr_mem; - unsigned int cor_offset; -}; - - -#define PLX_MIN_ATTR_LEN 512 /* at least 2 x 256 is needed for CIS */ -#define COR_SRESET 0x80 -#define COR_LEVLREQ 0x40 -#define COR_ENABLE_FUNC 0x01 -/* PCI Configuration Registers */ -#define PLX_PCIIPR 0x3d /* PCI Interrupt Pin */ -/* Local Configuration Registers */ -#define PLX_INTCSR 0x4c /* Interrupt Control/Status Register */ -#define PLX_INTCSR_PCI_INTEN BIT(6) /* PCI Interrupt Enable */ -#define PLX_CNTRL 0x50 -#define PLX_CNTRL_SERIAL_EEPROM_PRESENT BIT(28) - - -#define PLXDEV(vendor,dev,str) { vendor, dev, PCI_ANY_ID, PCI_ANY_ID } - -static struct pci_device_id prism2_plx_id_table[] __devinitdata = { - PLXDEV(0x10b7, 0x7770, "3Com AirConnect PCI 777A"), - PLXDEV(0x111a, 0x1023, "Siemens SpeedStream SS1023"), - PLXDEV(0x126c, 0x8030, "Nortel emobility"), - PLXDEV(0x1562, 0x0001, "Symbol LA-4123"), - PLXDEV(0x1385, 0x4100, "Netgear MA301"), - PLXDEV(0x15e8, 0x0130, "National Datacomm NCP130 (PLX9052)"), - PLXDEV(0x15e8, 0x0131, "National Datacomm NCP130 (TMD7160)"), - PLXDEV(0x1638, 0x1100, "Eumitcom WL11000"), - PLXDEV(0x16ab, 0x1100, "Global Sun Tech GL24110P"), - PLXDEV(0x16ab, 0x1101, "Global Sun Tech GL24110P (?)"), - PLXDEV(0x16ab, 0x1102, "Linksys WPC11 with WDT11"), - PLXDEV(0x16ab, 0x1103, "Longshine 8031"), - PLXDEV(0x16ec, 0x3685, "US Robotics USR2415"), - PLXDEV(0xec80, 0xec00, "Belkin F5D6000"), - { 0 } -}; - - -/* Array of known Prism2/2.5 PC Card manufactured ids. If your card's manfid - * is not listed here, you will need to add it here to get the driver - * initialized. */ -static struct prism2_plx_manfid { - u16 manfid1, manfid2; -} prism2_plx_known_manfids[] = { - { 0x000b, 0x7110 } /* D-Link DWL-650 Rev. P1 */, - { 0x000b, 0x7300 } /* Philips 802.11b WLAN PCMCIA */, - { 0x0101, 0x0777 } /* 3Com AirConnect PCI 777A */, - { 0x0126, 0x8000 } /* Proxim RangeLAN */, - { 0x0138, 0x0002 } /* Compaq WL100 */, - { 0x0156, 0x0002 } /* Intersil Prism II Ref. Design (and others) */, - { 0x026f, 0x030b } /* Buffalo WLI-CF-S11G */, - { 0x0274, 0x1612 } /* Linksys WPC11 Ver 2.5 */, - { 0x0274, 0x1613 } /* Linksys WPC11 Ver 3 */, - { 0x028a, 0x0002 } /* D-Link DRC-650 */, - { 0x0250, 0x0002 } /* Samsung SWL2000-N */, - { 0xc250, 0x0002 } /* EMTAC A2424i */, - { 0xd601, 0x0002 } /* Z-Com XI300 */, - { 0xd601, 0x0005 } /* Zcomax XI-325H 200mW */, - { 0, 0} -}; - - -#ifdef PRISM2_IO_DEBUG - -static inline void hfa384x_outb_debug(struct net_device *dev, int a, u8 v) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTB, a, v); - outb(v, dev->base_addr + a); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline u8 hfa384x_inb_debug(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - u8 v; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock_irqsave(&local->lock, flags); - v = inb(dev->base_addr + a); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INB, a, v); - spin_unlock_irqrestore(&local->lock, flags); - return v; -} - -static inline void hfa384x_outw_debug(struct net_device *dev, int a, u16 v) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTW, a, v); - outw(v, dev->base_addr + a); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline u16 hfa384x_inw_debug(struct net_device *dev, int a) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - u16 v; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock_irqsave(&local->lock, flags); - v = inw(dev->base_addr + a); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INW, a, v); - spin_unlock_irqrestore(&local->lock, flags); - return v; -} - -static inline void hfa384x_outsw_debug(struct net_device *dev, int a, - u8 *buf, int wc) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_OUTSW, a, wc); - outsw(dev->base_addr + a, buf, wc); - spin_unlock_irqrestore(&local->lock, flags); -} - -static inline void hfa384x_insw_debug(struct net_device *dev, int a, - u8 *buf, int wc) -{ - struct hostap_interface *iface; - local_info_t *local; - unsigned long flags; - - iface = netdev_priv(dev); - local = iface->local; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_INSW, a, wc); - insw(dev->base_addr + a, buf, wc); - spin_unlock_irqrestore(&local->lock, flags); -} - -#define HFA384X_OUTB(v,a) hfa384x_outb_debug(dev, (a), (v)) -#define HFA384X_INB(a) hfa384x_inb_debug(dev, (a)) -#define HFA384X_OUTW(v,a) hfa384x_outw_debug(dev, (a), (v)) -#define HFA384X_INW(a) hfa384x_inw_debug(dev, (a)) -#define HFA384X_OUTSW(a, buf, wc) hfa384x_outsw_debug(dev, (a), (buf), (wc)) -#define HFA384X_INSW(a, buf, wc) hfa384x_insw_debug(dev, (a), (buf), (wc)) - -#else /* PRISM2_IO_DEBUG */ - -#define HFA384X_OUTB(v,a) outb((v), dev->base_addr + (a)) -#define HFA384X_INB(a) inb(dev->base_addr + (a)) -#define HFA384X_OUTW(v,a) outw((v), dev->base_addr + (a)) -#define HFA384X_INW(a) inw(dev->base_addr + (a)) -#define HFA384X_INSW(a, buf, wc) insw(dev->base_addr + (a), buf, wc) -#define HFA384X_OUTSW(a, buf, wc) outsw(dev->base_addr + (a), buf, wc) - -#endif /* PRISM2_IO_DEBUG */ - - -static int hfa384x_from_bap(struct net_device *dev, u16 bap, void *buf, - int len) -{ - u16 d_off; - u16 *pos; - - d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; - pos = (u16 *) buf; - - if (len / 2) - HFA384X_INSW(d_off, buf, len / 2); - pos += len / 2; - - if (len & 1) - *((char *) pos) = HFA384X_INB(d_off); - - return 0; -} - - -static int hfa384x_to_bap(struct net_device *dev, u16 bap, void *buf, int len) -{ - u16 d_off; - u16 *pos; - - d_off = (bap == 1) ? HFA384X_DATA1_OFF : HFA384X_DATA0_OFF; - pos = (u16 *) buf; - - if (len / 2) - HFA384X_OUTSW(d_off, buf, len / 2); - pos += len / 2; - - if (len & 1) - HFA384X_OUTB(*((char *) pos), d_off); - - return 0; -} - - -/* FIX: This might change at some point.. */ -#include "hostap_hw.c" - - -static void prism2_plx_cor_sreset(local_info_t *local) -{ - unsigned char corsave; - struct hostap_plx_priv *hw_priv = local->hw_priv; - - printk(KERN_DEBUG "%s: Doing reset via direct COR access.\n", - dev_info); - - /* Set sreset bit of COR and clear it after hold time */ - - if (hw_priv->attr_mem == NULL) { - /* TMD7160 - COR at card's first I/O addr */ - corsave = inb(hw_priv->cor_offset); - outb(corsave | COR_SRESET, hw_priv->cor_offset); - mdelay(2); - outb(corsave & ~COR_SRESET, hw_priv->cor_offset); - mdelay(2); - } else { - /* PLX9052 */ - corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset); - writeb(corsave | COR_SRESET, - hw_priv->attr_mem + hw_priv->cor_offset); - mdelay(2); - writeb(corsave & ~COR_SRESET, - hw_priv->attr_mem + hw_priv->cor_offset); - mdelay(2); - } -} - - -static void prism2_plx_genesis_reset(local_info_t *local, int hcr) -{ - unsigned char corsave; - struct hostap_plx_priv *hw_priv = local->hw_priv; - - if (hw_priv->attr_mem == NULL) { - /* TMD7160 - COR at card's first I/O addr */ - corsave = inb(hw_priv->cor_offset); - outb(corsave | COR_SRESET, hw_priv->cor_offset); - mdelay(10); - outb(hcr, hw_priv->cor_offset + 2); - mdelay(10); - outb(corsave & ~COR_SRESET, hw_priv->cor_offset); - mdelay(10); - } else { - /* PLX9052 */ - corsave = readb(hw_priv->attr_mem + hw_priv->cor_offset); - writeb(corsave | COR_SRESET, - hw_priv->attr_mem + hw_priv->cor_offset); - mdelay(10); - writeb(hcr, hw_priv->attr_mem + hw_priv->cor_offset + 2); - mdelay(10); - writeb(corsave & ~COR_SRESET, - hw_priv->attr_mem + hw_priv->cor_offset); - mdelay(10); - } -} - - -static struct prism2_helper_functions prism2_plx_funcs = -{ - .card_present = NULL, - .cor_sreset = prism2_plx_cor_sreset, - .genesis_reset = prism2_plx_genesis_reset, - .hw_type = HOSTAP_HW_PLX, -}; - - -static int prism2_plx_check_cis(void __iomem *attr_mem, int attr_len, - unsigned int *cor_offset, - unsigned int *cor_index) -{ -#define CISTPL_CONFIG 0x1A -#define CISTPL_MANFID 0x20 -#define CISTPL_END 0xFF -#define CIS_MAX_LEN 256 - u8 *cis; - int i, pos; - unsigned int rmsz, rasz, manfid1, manfid2; - struct prism2_plx_manfid *manfid; - - cis = kmalloc(CIS_MAX_LEN, GFP_KERNEL); - if (cis == NULL) - return -ENOMEM; - - /* read CIS; it is in even offsets in the beginning of attr_mem */ - for (i = 0; i < CIS_MAX_LEN; i++) - cis[i] = readb(attr_mem + 2 * i); - printk(KERN_DEBUG "%s: CIS: %02x %02x %02x %02x %02x %02x ...\n", - dev_info, cis[0], cis[1], cis[2], cis[3], cis[4], cis[5]); - - /* set reasonable defaults for Prism2 cards just in case CIS parsing - * fails */ - *cor_offset = 0x3e0; - *cor_index = 0x01; - manfid1 = manfid2 = 0; - - pos = 0; - while (pos < CIS_MAX_LEN - 1 && cis[pos] != CISTPL_END) { - if (pos + 2 + cis[pos + 1] > CIS_MAX_LEN) - goto cis_error; - - switch (cis[pos]) { - case CISTPL_CONFIG: - if (cis[pos + 1] < 2) - goto cis_error; - rmsz = (cis[pos + 2] & 0x3c) >> 2; - rasz = cis[pos + 2] & 0x03; - if (4 + rasz + rmsz > cis[pos + 1]) - goto cis_error; - *cor_index = cis[pos + 3] & 0x3F; - *cor_offset = 0; - for (i = 0; i <= rasz; i++) - *cor_offset += cis[pos + 4 + i] << (8 * i); - printk(KERN_DEBUG "%s: cor_index=0x%x " - "cor_offset=0x%x\n", dev_info, - *cor_index, *cor_offset); - if (*cor_offset > attr_len) { - printk(KERN_ERR "%s: COR offset not within " - "attr_mem\n", dev_info); - kfree(cis); - return -1; - } - break; - - case CISTPL_MANFID: - if (cis[pos + 1] < 4) - goto cis_error; - manfid1 = cis[pos + 2] + (cis[pos + 3] << 8); - manfid2 = cis[pos + 4] + (cis[pos + 5] << 8); - printk(KERN_DEBUG "%s: manfid=0x%04x, 0x%04x\n", - dev_info, manfid1, manfid2); - break; - } - - pos += cis[pos + 1] + 2; - } - - if (pos >= CIS_MAX_LEN || cis[pos] != CISTPL_END) - goto cis_error; - - for (manfid = prism2_plx_known_manfids; manfid->manfid1 != 0; manfid++) - if (manfid1 == manfid->manfid1 && manfid2 == manfid->manfid2) { - kfree(cis); - return 0; - } - - printk(KERN_INFO "%s: unknown manfid 0x%04x, 0x%04x - assuming this is" - " not supported card\n", dev_info, manfid1, manfid2); - goto fail; - - cis_error: - printk(KERN_WARNING "%s: invalid CIS data\n", dev_info); - - fail: - kfree(cis); - if (ignore_cis) { - printk(KERN_INFO "%s: ignore_cis parameter set - ignoring " - "errors during CIS verification\n", dev_info); - return 0; - } - return -1; -} - - -static int prism2_plx_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - unsigned int pccard_ioaddr, plx_ioaddr; - unsigned long pccard_attr_mem; - unsigned int pccard_attr_len; - void __iomem *attr_mem = NULL; - unsigned int cor_offset = 0, cor_index = 0; - u32 reg; - local_info_t *local = NULL; - struct net_device *dev = NULL; - struct hostap_interface *iface; - static int cards_found /* = 0 */; - int irq_registered = 0; - int tmd7160; - struct hostap_plx_priv *hw_priv; - - hw_priv = kzalloc(sizeof(*hw_priv), GFP_KERNEL); - if (hw_priv == NULL) - return -ENOMEM; - - if (pci_enable_device(pdev)) - goto err_out_free; - - /* National Datacomm NCP130 based on TMD7160, not PLX9052. */ - tmd7160 = (pdev->vendor == 0x15e8) && (pdev->device == 0x0131); - - plx_ioaddr = pci_resource_start(pdev, 1); - pccard_ioaddr = pci_resource_start(pdev, tmd7160 ? 2 : 3); - - if (tmd7160) { - /* TMD7160 */ - attr_mem = NULL; /* no access to PC Card attribute memory */ - - printk(KERN_INFO "TMD7160 PCI/PCMCIA adapter: io=0x%x, " - "irq=%d, pccard_io=0x%x\n", - plx_ioaddr, pdev->irq, pccard_ioaddr); - - cor_offset = plx_ioaddr; - cor_index = 0x04; - - outb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, plx_ioaddr); - mdelay(1); - reg = inb(plx_ioaddr); - if (reg != (cor_index | COR_LEVLREQ | COR_ENABLE_FUNC)) { - printk(KERN_ERR "%s: Error setting COR (expected=" - "0x%02x, was=0x%02x)\n", dev_info, - cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, reg); - goto fail; - } - } else { - /* PLX9052 */ - pccard_attr_mem = pci_resource_start(pdev, 2); - pccard_attr_len = pci_resource_len(pdev, 2); - if (pccard_attr_len < PLX_MIN_ATTR_LEN) - goto fail; - - - attr_mem = ioremap(pccard_attr_mem, pccard_attr_len); - if (attr_mem == NULL) { - printk(KERN_ERR "%s: cannot remap attr_mem\n", - dev_info); - goto fail; - } - - printk(KERN_INFO "PLX9052 PCI/PCMCIA adapter: " - "mem=0x%lx, plx_io=0x%x, irq=%d, pccard_io=0x%x\n", - pccard_attr_mem, plx_ioaddr, pdev->irq, pccard_ioaddr); - - if (prism2_plx_check_cis(attr_mem, pccard_attr_len, - &cor_offset, &cor_index)) { - printk(KERN_INFO "Unknown PC Card CIS - not a " - "Prism2/2.5 card?\n"); - goto fail; - } - - printk(KERN_DEBUG "Prism2/2.5 PC Card detected in PLX9052 " - "adapter\n"); - - /* Write COR to enable PC Card */ - writeb(cor_index | COR_LEVLREQ | COR_ENABLE_FUNC, - attr_mem + cor_offset); - - /* Enable PCI interrupts if they are not already enabled */ - reg = inl(plx_ioaddr + PLX_INTCSR); - printk(KERN_DEBUG "PLX_INTCSR=0x%x\n", reg); - if (!(reg & PLX_INTCSR_PCI_INTEN)) { - outl(reg | PLX_INTCSR_PCI_INTEN, - plx_ioaddr + PLX_INTCSR); - if (!(inl(plx_ioaddr + PLX_INTCSR) & - PLX_INTCSR_PCI_INTEN)) { - printk(KERN_WARNING "%s: Could not enable " - "Local Interrupts\n", dev_info); - goto fail; - } - } - - reg = inl(plx_ioaddr + PLX_CNTRL); - printk(KERN_DEBUG "PLX_CNTRL=0x%x (Serial EEPROM " - "present=%d)\n", - reg, (reg & PLX_CNTRL_SERIAL_EEPROM_PRESENT) != 0); - /* should set PLX_PCIIPR to 0x01 (INTA#) if Serial EEPROM is - * not present; but are there really such cards in use(?) */ - } - - dev = prism2_init_local_data(&prism2_plx_funcs, cards_found, - &pdev->dev); - if (dev == NULL) - goto fail; - iface = netdev_priv(dev); - local = iface->local; - local->hw_priv = hw_priv; - cards_found++; - - dev->irq = pdev->irq; - dev->base_addr = pccard_ioaddr; - hw_priv->attr_mem = attr_mem; - hw_priv->cor_offset = cor_offset; - - pci_set_drvdata(pdev, dev); - - if (request_irq(dev->irq, prism2_interrupt, IRQF_SHARED, dev->name, - dev)) { - printk(KERN_WARNING "%s: request_irq failed\n", dev->name); - goto fail; - } else - irq_registered = 1; - - if (prism2_hw_config(dev, 1)) { - printk(KERN_DEBUG "%s: hardware initialization failed\n", - dev_info); - goto fail; - } - - return hostap_hw_ready(dev); - - fail: - if (irq_registered && dev) - free_irq(dev->irq, dev); - - if (attr_mem) - iounmap(attr_mem); - - pci_disable_device(pdev); - prism2_free_local_data(dev); - - err_out_free: - kfree(hw_priv); - - return -ENODEV; -} - - -static void prism2_plx_remove(struct pci_dev *pdev) -{ - struct net_device *dev; - struct hostap_interface *iface; - struct hostap_plx_priv *hw_priv; - - dev = pci_get_drvdata(pdev); - iface = netdev_priv(dev); - hw_priv = iface->local->hw_priv; - - /* Reset the hardware, and ensure interrupts are disabled. */ - prism2_plx_cor_sreset(iface->local); - hfa384x_disable_interrupts(dev); - - if (hw_priv->attr_mem) - iounmap(hw_priv->attr_mem); - if (dev->irq) - free_irq(dev->irq, dev); - - prism2_free_local_data(dev); - kfree(hw_priv); - pci_disable_device(pdev); -} - - -MODULE_DEVICE_TABLE(pci, prism2_plx_id_table); - -static struct pci_driver prism2_plx_driver = { - .name = "hostap_plx", - .id_table = prism2_plx_id_table, - .probe = prism2_plx_probe, - .remove = prism2_plx_remove, -}; - - -static int __init init_prism2_plx(void) -{ - return pci_register_driver(&prism2_plx_driver); -} - - -static void __exit exit_prism2_plx(void) -{ - pci_unregister_driver(&prism2_plx_driver); -} - - -module_init(init_prism2_plx); -module_exit(exit_prism2_plx); diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c deleted file mode 100644 index 005ff25a405f..000000000000 --- a/drivers/net/wireless/hostap/hostap_proc.c +++ /dev/null @@ -1,457 +0,0 @@ -/* /proc routines for Host AP driver */ - -#include -#include -#include - -#include "hostap_wlan.h" -#include "hostap.h" - -#define PROC_LIMIT (PAGE_SIZE - 80) - - -#ifndef PRISM2_NO_PROCFS_DEBUG -static int prism2_debug_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - int i; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "next_txfid=%d next_alloc=%d\n", - local->next_txfid, local->next_alloc); - for (i = 0; i < PRISM2_TXFID_COUNT; i++) - p += sprintf(p, "FID: tx=%04X intransmit=%04X\n", - local->txfid[i], local->intransmitfid[i]); - p += sprintf(p, "FW TX rate control: %d\n", local->fw_tx_rate_control); - p += sprintf(p, "beacon_int=%d\n", local->beacon_int); - p += sprintf(p, "dtim_period=%d\n", local->dtim_period); - p += sprintf(p, "wds_max_connections=%d\n", - local->wds_max_connections); - p += sprintf(p, "dev_enabled=%d\n", local->dev_enabled); - p += sprintf(p, "sw_tick_stuck=%d\n", local->sw_tick_stuck); - for (i = 0; i < WEP_KEYS; i++) { - if (local->crypt_info.crypt[i] && - local->crypt_info.crypt[i]->ops) { - p += sprintf(p, "crypt[%d]=%s\n", i, - local->crypt_info.crypt[i]->ops->name); - } - } - p += sprintf(p, "pri_only=%d\n", local->pri_only); - p += sprintf(p, "pci=%d\n", local->func->hw_type == HOSTAP_HW_PCI); - p += sprintf(p, "sram_type=%d\n", local->sram_type); - p += sprintf(p, "no_pri=%d\n", local->no_pri); - - return (p - page); -} -#endif /* PRISM2_NO_PROCFS_DEBUG */ - - -static int prism2_stats_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - struct comm_tallies_sums *sums = (struct comm_tallies_sums *) - &local->comm_tallies; - - if (off != 0) { - *eof = 1; - return 0; - } - - p += sprintf(p, "TxUnicastFrames=%u\n", sums->tx_unicast_frames); - p += sprintf(p, "TxMulticastframes=%u\n", sums->tx_multicast_frames); - p += sprintf(p, "TxFragments=%u\n", sums->tx_fragments); - p += sprintf(p, "TxUnicastOctets=%u\n", sums->tx_unicast_octets); - p += sprintf(p, "TxMulticastOctets=%u\n", sums->tx_multicast_octets); - p += sprintf(p, "TxDeferredTransmissions=%u\n", - sums->tx_deferred_transmissions); - p += sprintf(p, "TxSingleRetryFrames=%u\n", - sums->tx_single_retry_frames); - p += sprintf(p, "TxMultipleRetryFrames=%u\n", - sums->tx_multiple_retry_frames); - p += sprintf(p, "TxRetryLimitExceeded=%u\n", - sums->tx_retry_limit_exceeded); - p += sprintf(p, "TxDiscards=%u\n", sums->tx_discards); - p += sprintf(p, "RxUnicastFrames=%u\n", sums->rx_unicast_frames); - p += sprintf(p, "RxMulticastFrames=%u\n", sums->rx_multicast_frames); - p += sprintf(p, "RxFragments=%u\n", sums->rx_fragments); - p += sprintf(p, "RxUnicastOctets=%u\n", sums->rx_unicast_octets); - p += sprintf(p, "RxMulticastOctets=%u\n", sums->rx_multicast_octets); - p += sprintf(p, "RxFCSErrors=%u\n", sums->rx_fcs_errors); - p += sprintf(p, "RxDiscardsNoBuffer=%u\n", - sums->rx_discards_no_buffer); - p += sprintf(p, "TxDiscardsWrongSA=%u\n", sums->tx_discards_wrong_sa); - p += sprintf(p, "RxDiscardsWEPUndecryptable=%u\n", - sums->rx_discards_wep_undecryptable); - p += sprintf(p, "RxMessageInMsgFragments=%u\n", - sums->rx_message_in_msg_fragments); - p += sprintf(p, "RxMessageInBadMsgFragments=%u\n", - sums->rx_message_in_bad_msg_fragments); - /* FIX: this may grow too long for one page(?) */ - - return (p - page); -} - - -static int prism2_wds_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - struct list_head *ptr; - struct hostap_interface *iface; - - if (off > PROC_LIMIT) { - *eof = 1; - return 0; - } - - read_lock_bh(&local->iface_lock); - list_for_each(ptr, &local->hostap_interfaces) { - iface = list_entry(ptr, struct hostap_interface, list); - if (iface->type != HOSTAP_INTERFACE_WDS) - continue; - p += sprintf(p, "%s\t%pM\n", - iface->dev->name, - iface->u.wds.remote_addr); - if ((p - page) > PROC_LIMIT) { - printk(KERN_DEBUG "%s: wds proc did not fit\n", - local->dev->name); - break; - } - } - read_unlock_bh(&local->iface_lock); - - if ((p - page) <= off) { - *eof = 1; - return 0; - } - - *start = page + off; - - return (p - page - off); -} - - -static int prism2_bss_list_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - struct list_head *ptr; - struct hostap_bss_info *bss; - int i; - - if (off > PROC_LIMIT) { - *eof = 1; - return 0; - } - - p += sprintf(p, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t" - "SSID(hex)\tWPA IE\n"); - spin_lock_bh(&local->lock); - list_for_each(ptr, &local->bss_list) { - bss = list_entry(ptr, struct hostap_bss_info, list); - p += sprintf(p, "%pM\t%lu\t%u\t0x%x\t", - bss->bssid, bss->last_update, - bss->count, bss->capab_info); - for (i = 0; i < bss->ssid_len; i++) { - p += sprintf(p, "%c", - bss->ssid[i] >= 32 && bss->ssid[i] < 127 ? - bss->ssid[i] : '_'); - } - p += sprintf(p, "\t"); - for (i = 0; i < bss->ssid_len; i++) { - p += sprintf(p, "%02x", bss->ssid[i]); - } - p += sprintf(p, "\t"); - for (i = 0; i < bss->wpa_ie_len; i++) { - p += sprintf(p, "%02x", bss->wpa_ie[i]); - } - p += sprintf(p, "\n"); - if ((p - page) > PROC_LIMIT) { - printk(KERN_DEBUG "%s: BSS proc did not fit\n", - local->dev->name); - break; - } - } - spin_unlock_bh(&local->lock); - - if ((p - page) <= off) { - *eof = 1; - return 0; - } - - *start = page + off; - - return (p - page - off); -} - - -static int prism2_crypt_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - int i; - - if (off > PROC_LIMIT) { - *eof = 1; - return 0; - } - - p += sprintf(p, "tx_keyidx=%d\n", local->crypt_info.tx_keyidx); - for (i = 0; i < WEP_KEYS; i++) { - if (local->crypt_info.crypt[i] && - local->crypt_info.crypt[i]->ops && - local->crypt_info.crypt[i]->ops->print_stats) { - p = local->crypt_info.crypt[i]->ops->print_stats( - p, local->crypt_info.crypt[i]->priv); - } - } - - if ((p - page) <= off) { - *eof = 1; - return 0; - } - - *start = page + off; - - return (p - page - off); -} - - -static int prism2_pda_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - local_info_t *local = (local_info_t *) data; - - if (local->pda == NULL || off >= PRISM2_PDA_SIZE) { - *eof = 1; - return 0; - } - - if (off + count > PRISM2_PDA_SIZE) - count = PRISM2_PDA_SIZE - off; - - memcpy(page, local->pda + off, count); - return count; -} - - -static int prism2_aux_dump_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - local_info_t *local = (local_info_t *) data; - - if (local->func->read_aux == NULL) { - *eof = 1; - return 0; - } - - if (local->func->read_aux(local->dev, off, count, page)) { - *eof = 1; - return 0; - } - *start = page; - - return count; -} - - -#ifdef PRISM2_IO_DEBUG -static int prism2_io_debug_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - local_info_t *local = (local_info_t *) data; - int head = local->io_debug_head; - int start_bytes, left, copy, copied; - - if (off + count > PRISM2_IO_DEBUG_SIZE * 4) { - *eof = 1; - if (off >= PRISM2_IO_DEBUG_SIZE * 4) - return 0; - count = PRISM2_IO_DEBUG_SIZE * 4 - off; - } - - copied = 0; - start_bytes = (PRISM2_IO_DEBUG_SIZE - head) * 4; - left = count; - - if (off < start_bytes) { - copy = start_bytes - off; - if (copy > count) - copy = count; - memcpy(page, ((u8 *) &local->io_debug[head]) + off, copy); - left -= copy; - if (left > 0) - memcpy(&page[copy], local->io_debug, left); - } else { - memcpy(page, ((u8 *) local->io_debug) + (off - start_bytes), - left); - } - - *start = page; - - return count; -} -#endif /* PRISM2_IO_DEBUG */ - - -#ifndef PRISM2_NO_STATION_MODES -static int prism2_scan_results_proc_read(char *page, char **start, off_t off, - int count, int *eof, void *data) -{ - char *p = page; - local_info_t *local = (local_info_t *) data; - int entry, i, len, total = 0; - struct hfa384x_hostscan_result *scanres; - u8 *pos; - - p += sprintf(p, "CHID ANL SL BcnInt Capab Rate BSSID ATIM SupRates " - "SSID\n"); - - spin_lock_bh(&local->lock); - for (entry = 0; entry < local->last_scan_results_count; entry++) { - scanres = &local->last_scan_results[entry]; - - if (total + (p - page) <= off) { - total += p - page; - p = page; - } - if (total + (p - page) > off + count) - break; - if ((p - page) > (PAGE_SIZE - 200)) - break; - - p += sprintf(p, "%d %d %d %d 0x%02x %d %pM %d ", - le16_to_cpu(scanres->chid), - (s16) le16_to_cpu(scanres->anl), - (s16) le16_to_cpu(scanres->sl), - le16_to_cpu(scanres->beacon_interval), - le16_to_cpu(scanres->capability), - le16_to_cpu(scanres->rate), - scanres->bssid, - le16_to_cpu(scanres->atim)); - - pos = scanres->sup_rates; - for (i = 0; i < sizeof(scanres->sup_rates); i++) { - if (pos[i] == 0) - break; - p += sprintf(p, "<%02x>", pos[i]); - } - p += sprintf(p, " "); - - pos = scanres->ssid; - len = le16_to_cpu(scanres->ssid_len); - if (len > 32) - len = 32; - for (i = 0; i < len; i++) { - unsigned char c = pos[i]; - if (c >= 32 && c < 127) - p += sprintf(p, "%c", c); - else - p += sprintf(p, "<%02x>", c); - } - p += sprintf(p, "\n"); - } - spin_unlock_bh(&local->lock); - - total += (p - page); - if (total >= off + count) - *eof = 1; - - if (total < off) { - *eof = 1; - return 0; - } - - len = total - off; - if (len > (p - page)) - len = p - page; - *start = p - len; - if (len > count) - len = count; - - return len; -} -#endif /* PRISM2_NO_STATION_MODES */ - - -void hostap_init_proc(local_info_t *local) -{ - local->proc = NULL; - - if (hostap_proc == NULL) { - printk(KERN_WARNING "%s: hostap proc directory not created\n", - local->dev->name); - return; - } - - local->proc = proc_mkdir(local->ddev->name, hostap_proc); - if (local->proc == NULL) { - printk(KERN_INFO "/proc/net/hostap/%s creation failed\n", - local->ddev->name); - return; - } - -#ifndef PRISM2_NO_PROCFS_DEBUG - create_proc_read_entry("debug", 0, local->proc, - prism2_debug_proc_read, local); -#endif /* PRISM2_NO_PROCFS_DEBUG */ - create_proc_read_entry("stats", 0, local->proc, - prism2_stats_proc_read, local); - create_proc_read_entry("wds", 0, local->proc, - prism2_wds_proc_read, local); - create_proc_read_entry("pda", 0, local->proc, - prism2_pda_proc_read, local); - create_proc_read_entry("aux_dump", 0, local->proc, - prism2_aux_dump_proc_read, local); - create_proc_read_entry("bss_list", 0, local->proc, - prism2_bss_list_proc_read, local); - create_proc_read_entry("crypt", 0, local->proc, - prism2_crypt_proc_read, local); -#ifdef PRISM2_IO_DEBUG - create_proc_read_entry("io_debug", 0, local->proc, - prism2_io_debug_proc_read, local); -#endif /* PRISM2_IO_DEBUG */ -#ifndef PRISM2_NO_STATION_MODES - create_proc_read_entry("scan_results", 0, local->proc, - prism2_scan_results_proc_read, local); -#endif /* PRISM2_NO_STATION_MODES */ -} - - -void hostap_remove_proc(local_info_t *local) -{ - if (local->proc != NULL) { -#ifndef PRISM2_NO_STATION_MODES - remove_proc_entry("scan_results", local->proc); -#endif /* PRISM2_NO_STATION_MODES */ -#ifdef PRISM2_IO_DEBUG - remove_proc_entry("io_debug", local->proc); -#endif /* PRISM2_IO_DEBUG */ - remove_proc_entry("pda", local->proc); - remove_proc_entry("aux_dump", local->proc); - remove_proc_entry("wds", local->proc); - remove_proc_entry("stats", local->proc); - remove_proc_entry("bss_list", local->proc); - remove_proc_entry("crypt", local->proc); -#ifndef PRISM2_NO_PROCFS_DEBUG - remove_proc_entry("debug", local->proc); -#endif /* PRISM2_NO_PROCFS_DEBUG */ - if (hostap_proc != NULL) - remove_proc_entry(local->proc->name, hostap_proc); - } -} - - -EXPORT_SYMBOL(hostap_init_proc); -EXPORT_SYMBOL(hostap_remove_proc); diff --git a/drivers/net/wireless/hostap/hostap_wlan.h b/drivers/net/wireless/hostap/hostap_wlan.h deleted file mode 100644 index 1ba33be98b25..000000000000 --- a/drivers/net/wireless/hostap/hostap_wlan.h +++ /dev/null @@ -1,1046 +0,0 @@ -#ifndef HOSTAP_WLAN_H -#define HOSTAP_WLAN_H - -#include -#include -#include -#include -#include -#include - -#include "hostap_config.h" -#include "hostap_common.h" - -#define MAX_PARM_DEVICES 8 -#define PARM_MIN_MAX "1-" __MODULE_STRING(MAX_PARM_DEVICES) -#define DEF_INTS -1, -1, -1, -1, -1, -1, -1 -#define GET_INT_PARM(var,idx) var[var[idx] < 0 ? 0 : idx] - - -/* Specific skb->protocol value that indicates that the packet already contains - * txdesc header. - * FIX: This might need own value that would be allocated especially for Prism2 - * txdesc; ETH_P_CONTROL is commented as "Card specific control frames". - * However, these skb's should have only minimal path in the kernel side since - * prism2_send_mgmt() sends these with dev_queue_xmit() to prism2_tx(). */ -#define ETH_P_HOSTAP ETH_P_CONTROL - -/* ARPHRD_IEEE80211_PRISM uses a bloated version of Prism2 RX frame header - * (from linux-wlan-ng) */ -struct linux_wlan_ng_val { - u32 did; - u16 status, len; - u32 data; -} __attribute__ ((packed)); - -struct linux_wlan_ng_prism_hdr { - u32 msgcode, msglen; - char devname[16]; - struct linux_wlan_ng_val hosttime, mactime, channel, rssi, sq, signal, - noise, rate, istx, frmlen; -} __attribute__ ((packed)); - -struct linux_wlan_ng_cap_hdr { - __be32 version; - __be32 length; - __be64 mactime; - __be64 hosttime; - __be32 phytype; - __be32 channel; - __be32 datarate; - __be32 antenna; - __be32 priority; - __be32 ssi_type; - __be32 ssi_signal; - __be32 ssi_noise; - __be32 preamble; - __be32 encoding; -} __attribute__ ((packed)); - -struct hostap_radiotap_rx { - struct ieee80211_radiotap_header hdr; - __le64 tsft; - u8 rate; - u8 padding; - __le16 chan_freq; - __le16 chan_flags; - s8 dbm_antsignal; - s8 dbm_antnoise; -} __attribute__ ((packed)); - -#define LWNG_CAP_DID_BASE (4 | (1 << 6)) /* section 4, group 1 */ -#define LWNG_CAPHDR_VERSION 0x80211001 - -struct hfa384x_rx_frame { - /* HFA384X RX frame descriptor */ - __le16 status; /* HFA384X_RX_STATUS_ flags */ - __le32 time; /* timestamp, 1 microsecond resolution */ - u8 silence; /* 27 .. 154; seems to be 0 */ - u8 signal; /* 27 .. 154 */ - u8 rate; /* 10, 20, 55, or 110 */ - u8 rxflow; - __le32 reserved; - - /* 802.11 */ - __le16 frame_control; - __le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; - u8 addr3[6]; - __le16 seq_ctrl; - u8 addr4[6]; - __le16 data_len; - - /* 802.3 */ - u8 dst_addr[6]; - u8 src_addr[6]; - __be16 len; - - /* followed by frame data; max 2304 bytes */ -} __attribute__ ((packed)); - - -struct hfa384x_tx_frame { - /* HFA384X TX frame descriptor */ - __le16 status; /* HFA384X_TX_STATUS_ flags */ - __le16 reserved1; - __le16 reserved2; - __le32 sw_support; - u8 retry_count; /* not yet implemented */ - u8 tx_rate; /* Host AP only; 0 = firmware, or 10, 20, 55, 110 */ - __le16 tx_control; /* HFA384X_TX_CTRL_ flags */ - - /* 802.11 */ - __le16 frame_control; /* parts not used */ - __le16 duration_id; - u8 addr1[6]; - u8 addr2[6]; /* filled by firmware */ - u8 addr3[6]; - __le16 seq_ctrl; /* filled by firmware */ - u8 addr4[6]; - __le16 data_len; - - /* 802.3 */ - u8 dst_addr[6]; - u8 src_addr[6]; - __be16 len; - - /* followed by frame data; max 2304 bytes */ -} __attribute__ ((packed)); - - -struct hfa384x_rid_hdr -{ - __le16 len; - __le16 rid; -} __attribute__ ((packed)); - - -/* Macro for converting signal levels (range 27 .. 154) to wireless ext - * dBm value with some accuracy */ -#define HFA384X_LEVEL_TO_dBm(v) 0x100 + (v) * 100 / 255 - 100 - -#define HFA384X_LEVEL_TO_dBm_sign(v) (v) * 100 / 255 - 100 - -struct hfa384x_scan_request { - __le16 channel_list; - __le16 txrate; /* HFA384X_RATES_* */ -} __attribute__ ((packed)); - -struct hfa384x_hostscan_request { - __le16 channel_list; - __le16 txrate; - __le16 target_ssid_len; - u8 target_ssid[32]; -} __attribute__ ((packed)); - -struct hfa384x_join_request { - u8 bssid[6]; - __le16 channel; -} __attribute__ ((packed)); - -struct hfa384x_info_frame { - __le16 len; - __le16 type; -} __attribute__ ((packed)); - -struct hfa384x_comm_tallies { - __le16 tx_unicast_frames; - __le16 tx_multicast_frames; - __le16 tx_fragments; - __le16 tx_unicast_octets; - __le16 tx_multicast_octets; - __le16 tx_deferred_transmissions; - __le16 tx_single_retry_frames; - __le16 tx_multiple_retry_frames; - __le16 tx_retry_limit_exceeded; - __le16 tx_discards; - __le16 rx_unicast_frames; - __le16 rx_multicast_frames; - __le16 rx_fragments; - __le16 rx_unicast_octets; - __le16 rx_multicast_octets; - __le16 rx_fcs_errors; - __le16 rx_discards_no_buffer; - __le16 tx_discards_wrong_sa; - __le16 rx_discards_wep_undecryptable; - __le16 rx_message_in_msg_fragments; - __le16 rx_message_in_bad_msg_fragments; -} __attribute__ ((packed)); - -struct hfa384x_comm_tallies32 { - __le32 tx_unicast_frames; - __le32 tx_multicast_frames; - __le32 tx_fragments; - __le32 tx_unicast_octets; - __le32 tx_multicast_octets; - __le32 tx_deferred_transmissions; - __le32 tx_single_retry_frames; - __le32 tx_multiple_retry_frames; - __le32 tx_retry_limit_exceeded; - __le32 tx_discards; - __le32 rx_unicast_frames; - __le32 rx_multicast_frames; - __le32 rx_fragments; - __le32 rx_unicast_octets; - __le32 rx_multicast_octets; - __le32 rx_fcs_errors; - __le32 rx_discards_no_buffer; - __le32 tx_discards_wrong_sa; - __le32 rx_discards_wep_undecryptable; - __le32 rx_message_in_msg_fragments; - __le32 rx_message_in_bad_msg_fragments; -} __attribute__ ((packed)); - -struct hfa384x_scan_result_hdr { - __le16 reserved; - __le16 scan_reason; -#define HFA384X_SCAN_IN_PROGRESS 0 /* no results available yet */ -#define HFA384X_SCAN_HOST_INITIATED 1 -#define HFA384X_SCAN_FIRMWARE_INITIATED 2 -#define HFA384X_SCAN_INQUIRY_FROM_HOST 3 -} __attribute__ ((packed)); - -#define HFA384X_SCAN_MAX_RESULTS 32 - -struct hfa384x_scan_result { - __le16 chid; - __le16 anl; - __le16 sl; - u8 bssid[6]; - __le16 beacon_interval; - __le16 capability; - __le16 ssid_len; - u8 ssid[32]; - u8 sup_rates[10]; - __le16 rate; -} __attribute__ ((packed)); - -struct hfa384x_hostscan_result { - __le16 chid; - __le16 anl; - __le16 sl; - u8 bssid[6]; - __le16 beacon_interval; - __le16 capability; - __le16 ssid_len; - u8 ssid[32]; - u8 sup_rates[10]; - __le16 rate; - __le16 atim; -} __attribute__ ((packed)); - -struct comm_tallies_sums { - unsigned int tx_unicast_frames; - unsigned int tx_multicast_frames; - unsigned int tx_fragments; - unsigned int tx_unicast_octets; - unsigned int tx_multicast_octets; - unsigned int tx_deferred_transmissions; - unsigned int tx_single_retry_frames; - unsigned int tx_multiple_retry_frames; - unsigned int tx_retry_limit_exceeded; - unsigned int tx_discards; - unsigned int rx_unicast_frames; - unsigned int rx_multicast_frames; - unsigned int rx_fragments; - unsigned int rx_unicast_octets; - unsigned int rx_multicast_octets; - unsigned int rx_fcs_errors; - unsigned int rx_discards_no_buffer; - unsigned int tx_discards_wrong_sa; - unsigned int rx_discards_wep_undecryptable; - unsigned int rx_message_in_msg_fragments; - unsigned int rx_message_in_bad_msg_fragments; -}; - - -struct hfa384x_regs { - u16 cmd; - u16 evstat; - u16 offset0; - u16 offset1; - u16 swsupport0; -}; - - -#if defined(PRISM2_PCCARD) || defined(PRISM2_PLX) -/* I/O ports for HFA384X Controller access */ -#define HFA384X_CMD_OFF 0x00 -#define HFA384X_PARAM0_OFF 0x02 -#define HFA384X_PARAM1_OFF 0x04 -#define HFA384X_PARAM2_OFF 0x06 -#define HFA384X_STATUS_OFF 0x08 -#define HFA384X_RESP0_OFF 0x0A -#define HFA384X_RESP1_OFF 0x0C -#define HFA384X_RESP2_OFF 0x0E -#define HFA384X_INFOFID_OFF 0x10 -#define HFA384X_CONTROL_OFF 0x14 -#define HFA384X_SELECT0_OFF 0x18 -#define HFA384X_SELECT1_OFF 0x1A -#define HFA384X_OFFSET0_OFF 0x1C -#define HFA384X_OFFSET1_OFF 0x1E -#define HFA384X_RXFID_OFF 0x20 -#define HFA384X_ALLOCFID_OFF 0x22 -#define HFA384X_TXCOMPLFID_OFF 0x24 -#define HFA384X_SWSUPPORT0_OFF 0x28 -#define HFA384X_SWSUPPORT1_OFF 0x2A -#define HFA384X_SWSUPPORT2_OFF 0x2C -#define HFA384X_EVSTAT_OFF 0x30 -#define HFA384X_INTEN_OFF 0x32 -#define HFA384X_EVACK_OFF 0x34 -#define HFA384X_DATA0_OFF 0x36 -#define HFA384X_DATA1_OFF 0x38 -#define HFA384X_AUXPAGE_OFF 0x3A -#define HFA384X_AUXOFFSET_OFF 0x3C -#define HFA384X_AUXDATA_OFF 0x3E -#endif /* PRISM2_PCCARD || PRISM2_PLX */ - -#ifdef PRISM2_PCI -/* Memory addresses for ISL3874 controller access */ -#define HFA384X_CMD_OFF 0x00 -#define HFA384X_PARAM0_OFF 0x04 -#define HFA384X_PARAM1_OFF 0x08 -#define HFA384X_PARAM2_OFF 0x0C -#define HFA384X_STATUS_OFF 0x10 -#define HFA384X_RESP0_OFF 0x14 -#define HFA384X_RESP1_OFF 0x18 -#define HFA384X_RESP2_OFF 0x1C -#define HFA384X_INFOFID_OFF 0x20 -#define HFA384X_CONTROL_OFF 0x28 -#define HFA384X_SELECT0_OFF 0x30 -#define HFA384X_SELECT1_OFF 0x34 -#define HFA384X_OFFSET0_OFF 0x38 -#define HFA384X_OFFSET1_OFF 0x3C -#define HFA384X_RXFID_OFF 0x40 -#define HFA384X_ALLOCFID_OFF 0x44 -#define HFA384X_TXCOMPLFID_OFF 0x48 -#define HFA384X_PCICOR_OFF 0x4C -#define HFA384X_SWSUPPORT0_OFF 0x50 -#define HFA384X_SWSUPPORT1_OFF 0x54 -#define HFA384X_SWSUPPORT2_OFF 0x58 -#define HFA384X_PCIHCR_OFF 0x5C -#define HFA384X_EVSTAT_OFF 0x60 -#define HFA384X_INTEN_OFF 0x64 -#define HFA384X_EVACK_OFF 0x68 -#define HFA384X_DATA0_OFF 0x6C -#define HFA384X_DATA1_OFF 0x70 -#define HFA384X_AUXPAGE_OFF 0x74 -#define HFA384X_AUXOFFSET_OFF 0x78 -#define HFA384X_AUXDATA_OFF 0x7C -#define HFA384X_PCI_M0_ADDRH_OFF 0x80 -#define HFA384X_PCI_M0_ADDRL_OFF 0x84 -#define HFA384X_PCI_M0_LEN_OFF 0x88 -#define HFA384X_PCI_M0_CTL_OFF 0x8C -#define HFA384X_PCI_STATUS_OFF 0x98 -#define HFA384X_PCI_M1_ADDRH_OFF 0xA0 -#define HFA384X_PCI_M1_ADDRL_OFF 0xA4 -#define HFA384X_PCI_M1_LEN_OFF 0xA8 -#define HFA384X_PCI_M1_CTL_OFF 0xAC - -/* PCI bus master control bits (these are undocumented; based on guessing and - * experimenting..) */ -#define HFA384X_PCI_CTL_FROM_BAP (BIT(5) | BIT(1) | BIT(0)) -#define HFA384X_PCI_CTL_TO_BAP (BIT(5) | BIT(0)) - -#endif /* PRISM2_PCI */ - - -/* Command codes for CMD reg. */ -#define HFA384X_CMDCODE_INIT 0x00 -#define HFA384X_CMDCODE_ENABLE 0x01 -#define HFA384X_CMDCODE_DISABLE 0x02 -#define HFA384X_CMDCODE_ALLOC 0x0A -#define HFA384X_CMDCODE_TRANSMIT 0x0B -#define HFA384X_CMDCODE_INQUIRE 0x11 -#define HFA384X_CMDCODE_ACCESS 0x21 -#define HFA384X_CMDCODE_ACCESS_WRITE (0x21 | BIT(8)) -#define HFA384X_CMDCODE_DOWNLOAD 0x22 -#define HFA384X_CMDCODE_READMIF 0x30 -#define HFA384X_CMDCODE_WRITEMIF 0x31 -#define HFA384X_CMDCODE_TEST 0x38 - -#define HFA384X_CMDCODE_MASK 0x3F - -/* Test mode operations */ -#define HFA384X_TEST_CHANGE_CHANNEL 0x08 -#define HFA384X_TEST_MONITOR 0x0B -#define HFA384X_TEST_STOP 0x0F -#define HFA384X_TEST_CFG_BITS 0x15 -#define HFA384X_TEST_CFG_BIT_ALC BIT(3) - -#define HFA384X_CMD_BUSY BIT(15) - -#define HFA384X_CMD_TX_RECLAIM BIT(8) - -#define HFA384X_OFFSET_ERR BIT(14) -#define HFA384X_OFFSET_BUSY BIT(15) - - -/* ProgMode for download command */ -#define HFA384X_PROGMODE_DISABLE 0 -#define HFA384X_PROGMODE_ENABLE_VOLATILE 1 -#define HFA384X_PROGMODE_ENABLE_NON_VOLATILE 2 -#define HFA384X_PROGMODE_PROGRAM_NON_VOLATILE 3 - -#define HFA384X_AUX_MAGIC0 0xfe01 -#define HFA384X_AUX_MAGIC1 0xdc23 -#define HFA384X_AUX_MAGIC2 0xba45 - -#define HFA384X_AUX_PORT_DISABLED 0 -#define HFA384X_AUX_PORT_DISABLE BIT(14) -#define HFA384X_AUX_PORT_ENABLE BIT(15) -#define HFA384X_AUX_PORT_ENABLED (BIT(14) | BIT(15)) -#define HFA384X_AUX_PORT_MASK (BIT(14) | BIT(15)) - -#define PRISM2_PDA_SIZE 1024 - - -/* Events; EvStat, Interrupt mask (IntEn), and acknowledge bits (EvAck) */ -#define HFA384X_EV_TICK BIT(15) -#define HFA384X_EV_WTERR BIT(14) -#define HFA384X_EV_INFDROP BIT(13) -#ifdef PRISM2_PCI -#define HFA384X_EV_PCI_M1 BIT(9) -#define HFA384X_EV_PCI_M0 BIT(8) -#endif /* PRISM2_PCI */ -#define HFA384X_EV_INFO BIT(7) -#define HFA384X_EV_DTIM BIT(5) -#define HFA384X_EV_CMD BIT(4) -#define HFA384X_EV_ALLOC BIT(3) -#define HFA384X_EV_TXEXC BIT(2) -#define HFA384X_EV_TX BIT(1) -#define HFA384X_EV_RX BIT(0) - - -/* HFA384X Information frames */ -#define HFA384X_INFO_HANDOVERADDR 0xF000 /* AP f/w ? */ -#define HFA384X_INFO_HANDOVERDEAUTHADDR 0xF001 /* AP f/w 1.3.7 */ -#define HFA384X_INFO_COMMTALLIES 0xF100 -#define HFA384X_INFO_SCANRESULTS 0xF101 -#define HFA384X_INFO_CHANNELINFORESULTS 0xF102 /* AP f/w only */ -#define HFA384X_INFO_HOSTSCANRESULTS 0xF103 -#define HFA384X_INFO_LINKSTATUS 0xF200 -#define HFA384X_INFO_ASSOCSTATUS 0xF201 /* ? */ -#define HFA384X_INFO_AUTHREQ 0xF202 /* ? */ -#define HFA384X_INFO_PSUSERCNT 0xF203 /* ? */ -#define HFA384X_INFO_KEYIDCHANGED 0xF204 /* ? */ - -enum { HFA384X_LINKSTATUS_CONNECTED = 1, - HFA384X_LINKSTATUS_DISCONNECTED = 2, - HFA384X_LINKSTATUS_AP_CHANGE = 3, - HFA384X_LINKSTATUS_AP_OUT_OF_RANGE = 4, - HFA384X_LINKSTATUS_AP_IN_RANGE = 5, - HFA384X_LINKSTATUS_ASSOC_FAILED = 6 }; - -enum { HFA384X_PORTTYPE_BSS = 1, HFA384X_PORTTYPE_WDS = 2, - HFA384X_PORTTYPE_PSEUDO_IBSS = 3, HFA384X_PORTTYPE_IBSS = 0, - HFA384X_PORTTYPE_HOSTAP = 6 }; - -#define HFA384X_RATES_1MBPS BIT(0) -#define HFA384X_RATES_2MBPS BIT(1) -#define HFA384X_RATES_5MBPS BIT(2) -#define HFA384X_RATES_11MBPS BIT(3) - -#define HFA384X_ROAMING_FIRMWARE 1 -#define HFA384X_ROAMING_HOST 2 -#define HFA384X_ROAMING_DISABLED 3 - -#define HFA384X_WEPFLAGS_PRIVACYINVOKED BIT(0) -#define HFA384X_WEPFLAGS_EXCLUDEUNENCRYPTED BIT(1) -#define HFA384X_WEPFLAGS_HOSTENCRYPT BIT(4) -#define HFA384X_WEPFLAGS_HOSTDECRYPT BIT(7) - -#define HFA384X_RX_STATUS_MSGTYPE (BIT(15) | BIT(14) | BIT(13)) -#define HFA384X_RX_STATUS_PCF BIT(12) -#define HFA384X_RX_STATUS_MACPORT (BIT(10) | BIT(9) | BIT(8)) -#define HFA384X_RX_STATUS_UNDECR BIT(1) -#define HFA384X_RX_STATUS_FCSERR BIT(0) - -#define HFA384X_RX_STATUS_GET_MSGTYPE(s) \ -(((s) & HFA384X_RX_STATUS_MSGTYPE) >> 13) -#define HFA384X_RX_STATUS_GET_MACPORT(s) \ -(((s) & HFA384X_RX_STATUS_MACPORT) >> 8) - -enum { HFA384X_RX_MSGTYPE_NORMAL = 0, HFA384X_RX_MSGTYPE_RFC1042 = 1, - HFA384X_RX_MSGTYPE_BRIDGETUNNEL = 2, HFA384X_RX_MSGTYPE_MGMT = 4 }; - - -#define HFA384X_TX_CTRL_ALT_RTRY BIT(5) -#define HFA384X_TX_CTRL_802_11 BIT(3) -#define HFA384X_TX_CTRL_802_3 0 -#define HFA384X_TX_CTRL_TX_EX BIT(2) -#define HFA384X_TX_CTRL_TX_OK BIT(1) - -#define HFA384X_TX_STATUS_RETRYERR BIT(0) -#define HFA384X_TX_STATUS_AGEDERR BIT(1) -#define HFA384X_TX_STATUS_DISCON BIT(2) -#define HFA384X_TX_STATUS_FORMERR BIT(3) - -/* HFA3861/3863 (BBP) Control Registers */ -#define HFA386X_CR_TX_CONFIGURE 0x12 /* CR9 */ -#define HFA386X_CR_RX_CONFIGURE 0x14 /* CR10 */ -#define HFA386X_CR_A_D_TEST_MODES2 0x1A /* CR13 */ -#define HFA386X_CR_MANUAL_TX_POWER 0x3E /* CR31 */ -#define HFA386X_CR_MEASURED_TX_POWER 0x74 /* CR58 */ - - -#ifdef __KERNEL__ - -#define PRISM2_TXFID_COUNT 8 -#define PRISM2_DATA_MAXLEN 2304 -#define PRISM2_TXFID_LEN (PRISM2_DATA_MAXLEN + sizeof(struct hfa384x_tx_frame)) -#define PRISM2_TXFID_EMPTY 0xffff -#define PRISM2_TXFID_RESERVED 0xfffe -#define PRISM2_DUMMY_FID 0xffff -#define MAX_SSID_LEN 32 -#define MAX_NAME_LEN 32 /* this is assumed to be equal to MAX_SSID_LEN */ - -#define PRISM2_DUMP_RX_HDR BIT(0) -#define PRISM2_DUMP_TX_HDR BIT(1) -#define PRISM2_DUMP_TXEXC_HDR BIT(2) - -struct hostap_tx_callback_info { - u16 idx; - void (*func)(struct sk_buff *, int ok, void *); - void *data; - struct hostap_tx_callback_info *next; -}; - - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -#define PRISM2_FRAG_CACHE_LEN 4 - -struct prism2_frag_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int last_frag; - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - - -struct hostap_cmd_queue { - struct list_head list; - wait_queue_head_t compl; - volatile enum { CMD_SLEEP, CMD_CALLBACK, CMD_COMPLETED } type; - void (*callback)(struct net_device *dev, long context, u16 resp0, - u16 res); - long context; - u16 cmd, param0, param1; - u16 resp0, res; - volatile int issued, issuing; - - atomic_t usecnt; - int del_req; -}; - -/* options for hw_shutdown */ -#define HOSTAP_HW_NO_DISABLE BIT(0) -#define HOSTAP_HW_ENABLE_CMDCOMPL BIT(1) - -typedef struct local_info local_info_t; - -struct prism2_helper_functions { - /* these functions are defined in hardware model specific files - * (hostap_{cs,plx,pci}.c */ - int (*card_present)(local_info_t *local); - void (*cor_sreset)(local_info_t *local); - void (*genesis_reset)(local_info_t *local, int hcr); - - /* the following functions are from hostap_hw.c, but they may have some - * hardware model specific code */ - - /* FIX: low-level commands like cmd might disappear at some point to - * make it easier to change them if needed (e.g., cmd would be replaced - * with write_mif/read_mif/testcmd/inquire); at least get_rid and - * set_rid might move to hostap_{cs,plx,pci}.c */ - int (*cmd)(struct net_device *dev, u16 cmd, u16 param0, u16 *param1, - u16 *resp0); - void (*read_regs)(struct net_device *dev, struct hfa384x_regs *regs); - int (*get_rid)(struct net_device *dev, u16 rid, void *buf, int len, - int exact_len); - int (*set_rid)(struct net_device *dev, u16 rid, void *buf, int len); - int (*hw_enable)(struct net_device *dev, int initial); - int (*hw_config)(struct net_device *dev, int initial); - void (*hw_reset)(struct net_device *dev); - void (*hw_shutdown)(struct net_device *dev, int no_disable); - int (*reset_port)(struct net_device *dev); - void (*schedule_reset)(local_info_t *local); - int (*download)(local_info_t *local, - struct prism2_download_param *param); - int (*tx)(struct sk_buff *skb, struct net_device *dev); - int (*set_tim)(struct net_device *dev, int aid, int set); - int (*read_aux)(struct net_device *dev, unsigned addr, int len, - u8 *buf); - - int need_tx_headroom; /* number of bytes of headroom needed before - * IEEE 802.11 header */ - enum { HOSTAP_HW_PCCARD, HOSTAP_HW_PLX, HOSTAP_HW_PCI } hw_type; -}; - - -struct prism2_download_data { - u32 dl_cmd; - u32 start_addr; - u32 num_areas; - struct prism2_download_data_area { - u32 addr; /* wlan card address */ - u32 len; - u8 *data; /* allocated data */ - } data[0]; -}; - - -#define HOSTAP_MAX_BSS_COUNT 64 -#define MAX_WPA_IE_LEN 64 - -struct hostap_bss_info { - struct list_head list; - unsigned long last_update; - unsigned int count; - u8 bssid[ETH_ALEN]; - u16 capab_info; - u8 ssid[32]; - size_t ssid_len; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - int chan; - int included; -}; - - -/* Per radio private Host AP data - shared by all net devices interfaces used - * by each radio (wlan#, wlan#ap, wlan#sta, WDS). - * ((struct hostap_interface *) netdev_priv(dev))->local points to this - * structure. */ -struct local_info { - struct module *hw_module; - int card_idx; - int dev_enabled; - int master_dev_auto_open; /* was master device opened automatically */ - int num_dev_open; /* number of open devices */ - struct net_device *dev; /* master radio device */ - struct net_device *ddev; /* main data device */ - struct list_head hostap_interfaces; /* Host AP interface list (contains - * struct hostap_interface entries) - */ - rwlock_t iface_lock; /* hostap_interfaces read lock; use write lock - * when removing entries from the list. - * TX and RX paths can use read lock. */ - spinlock_t cmdlock, baplock, lock, irq_init_lock; - struct mutex rid_bap_mtx; - u16 infofid; /* MAC buffer id for info frame */ - /* txfid, intransmitfid, next_txtid, and next_alloc are protected by - * txfidlock */ - spinlock_t txfidlock; - int txfid_len; /* length of allocated TX buffers */ - u16 txfid[PRISM2_TXFID_COUNT]; /* buffer IDs for TX frames */ - /* buffer IDs for intransmit frames or PRISM2_TXFID_EMPTY if - * corresponding txfid is free for next TX frame */ - u16 intransmitfid[PRISM2_TXFID_COUNT]; - int next_txfid; /* index to the next txfid to be checked for - * availability */ - int next_alloc; /* index to the next intransmitfid to be checked for - * allocation events */ - - /* bitfield for atomic bitops */ -#define HOSTAP_BITS_TRANSMIT 0 -#define HOSTAP_BITS_BAP_TASKLET 1 -#define HOSTAP_BITS_BAP_TASKLET2 2 - unsigned long bits; - - struct ap_data *ap; - - char essid[MAX_SSID_LEN + 1]; - char name[MAX_NAME_LEN + 1]; - int name_set; - u16 channel_mask; /* mask of allowed channels */ - u16 scan_channel_mask; /* mask of channels to be scanned */ - struct comm_tallies_sums comm_tallies; - struct proc_dir_entry *proc; - int iw_mode; /* operating mode (IW_MODE_*) */ - int pseudo_adhoc; /* 0: IW_MODE_ADHOC is real 802.11 compliant IBSS - * 1: IW_MODE_ADHOC is "pseudo IBSS" */ - char bssid[ETH_ALEN]; - int channel; - int beacon_int; - int dtim_period; - int mtu; - int frame_dump; /* dump RX/TX frame headers, PRISM2_DUMP_ flags */ - int fw_tx_rate_control; - u16 tx_rate_control; - u16 basic_rates; - int hw_resetting; - int hw_ready; - int hw_reset_tries; /* how many times reset has been tried */ - int hw_downloading; - int shutdown; - int pri_only; - int no_pri; /* no PRI f/w present */ - int sram_type; /* 8 = x8 SRAM, 16 = x16 SRAM, -1 = unknown */ - - enum { - PRISM2_TXPOWER_AUTO = 0, PRISM2_TXPOWER_OFF, - PRISM2_TXPOWER_FIXED, PRISM2_TXPOWER_UNKNOWN - } txpower_type; - int txpower; /* if txpower_type == PRISM2_TXPOWER_FIXED */ - - /* command queue for hfa384x_cmd(); protected with cmdlock */ - struct list_head cmd_queue; - /* max_len for cmd_queue; in addition, cmd_callback can use two - * additional entries to prevent sleeping commands from stopping - * transmits */ -#define HOSTAP_CMD_QUEUE_MAX_LEN 16 - int cmd_queue_len; /* number of entries in cmd_queue */ - - /* if card timeout is detected in interrupt context, reset_queue is - * used to schedule card reseting to be done in user context */ - struct work_struct reset_queue; - - /* For scheduling a change of the promiscuous mode RID */ - int is_promisc; - struct work_struct set_multicast_list_queue; - - struct work_struct set_tim_queue; - struct list_head set_tim_list; - spinlock_t set_tim_lock; - - int wds_max_connections; - int wds_connections; -#define HOSTAP_WDS_BROADCAST_RA BIT(0) -#define HOSTAP_WDS_AP_CLIENT BIT(1) -#define HOSTAP_WDS_STANDARD_FRAME BIT(2) - u32 wds_type; - u16 tx_control; /* flags to be used in TX description */ - int manual_retry_count; /* -1 = use f/w default; otherwise retry count - * to be used with all frames */ - - struct iw_statistics wstats; - unsigned long scan_timestamp; /* Time started to scan */ - enum { - PRISM2_MONITOR_80211 = 0, PRISM2_MONITOR_PRISM = 1, - PRISM2_MONITOR_CAPHDR = 2, PRISM2_MONITOR_RADIOTAP = 3 - } monitor_type; - int monitor_allow_fcserr; - - int hostapd; /* whether user space daemon, hostapd, is used for AP - * management */ - int hostapd_sta; /* whether hostapd is used with an extra STA interface - */ - struct net_device *apdev; - struct net_device_stats apdevstats; - - char assoc_ap_addr[ETH_ALEN]; - struct net_device *stadev; - struct net_device_stats stadevstats; - -#define WEP_KEYS 4 -#define WEP_KEY_LEN 13 - struct lib80211_crypt_info crypt_info; - - int open_wep; /* allow unencrypted frames */ - int host_encrypt; - int host_decrypt; - int privacy_invoked; /* force privacy invoked flag even if no keys are - * configured */ - int fw_encrypt_ok; /* whether firmware-based WEP encrypt is working - * in Host AP mode (STA f/w 1.4.9 or newer) */ - int bcrx_sta_key; /* use individual keys to override default keys even - * with RX of broad/multicast frames */ - - struct prism2_frag_entry frag_cache[PRISM2_FRAG_CACHE_LEN]; - unsigned int frag_next_idx; - - int ieee_802_1x; /* is IEEE 802.1X used */ - - int antsel_tx, antsel_rx; - int rts_threshold; /* dot11RTSThreshold */ - int fragm_threshold; /* dot11FragmentationThreshold */ - int auth_algs; /* PRISM2_AUTH_ flags */ - - int enh_sec; /* cnfEnhSecurity options (broadcast SSID hide/ignore) */ - int tallies32; /* 32-bit tallies in use */ - - struct prism2_helper_functions *func; - - u8 *pda; - int fw_ap; -#define PRISM2_FW_VER(major, minor, variant) \ -(((major) << 16) | ((minor) << 8) | variant) - u32 sta_fw_ver; - - /* Tasklets for handling hardware IRQ related operations outside hw IRQ - * handler */ - struct tasklet_struct bap_tasklet; - - struct tasklet_struct info_tasklet; - struct sk_buff_head info_list; /* info frames as skb's for - * info_tasklet */ - - struct hostap_tx_callback_info *tx_callback; /* registered TX callbacks - */ - - struct tasklet_struct rx_tasklet; - struct sk_buff_head rx_list; - - struct tasklet_struct sta_tx_exc_tasklet; - struct sk_buff_head sta_tx_exc_list; - - int host_roaming; - unsigned long last_join_time; /* time of last JoinRequest */ - struct hfa384x_hostscan_result *last_scan_results; - int last_scan_results_count; - enum { PRISM2_SCAN, PRISM2_HOSTSCAN } last_scan_type; - struct work_struct info_queue; - unsigned long pending_info; /* bit field of pending info_queue items */ -#define PRISM2_INFO_PENDING_LINKSTATUS 0 -#define PRISM2_INFO_PENDING_SCANRESULTS 1 - int prev_link_status; /* previous received LinkStatus info */ - int prev_linkstatus_connected; - u8 preferred_ap[6]; /* use this AP if possible */ - -#ifdef PRISM2_CALLBACK - void *callback_data; /* Can be used in callbacks; e.g., allocate - * on enable event and free on disable event. - * Host AP driver code does not touch this. */ -#endif /* PRISM2_CALLBACK */ - - wait_queue_head_t hostscan_wq; - - /* Passive scan in Host AP mode */ - struct timer_list passive_scan_timer; - int passive_scan_interval; /* in seconds, 0 = disabled */ - int passive_scan_channel; - enum { PASSIVE_SCAN_WAIT, PASSIVE_SCAN_LISTEN } passive_scan_state; - - struct timer_list tick_timer; - unsigned long last_tick_timer; - unsigned int sw_tick_stuck; - - /* commsQuality / dBmCommsQuality data from periodic polling; only - * valid for Managed and Ad-hoc modes */ - unsigned long last_comms_qual_update; - int comms_qual; /* in some odd unit.. */ - int avg_signal; /* in dB (note: negative) */ - int avg_noise; /* in dB (note: negative) */ - struct work_struct comms_qual_update; - - /* RSSI to dBm adjustment (for RX descriptor fields) */ - int rssi_to_dBm; /* substract from RSSI to get approximate dBm value */ - - /* BSS list / protected by local->lock */ - struct list_head bss_list; - int num_bss_info; - int wpa; /* WPA support enabled */ - int tkip_countermeasures; - int drop_unencrypted; - /* Generic IEEE 802.11 info element to be added to - * ProbeResp/Beacon/(Re)AssocReq */ - u8 *generic_elem; - size_t generic_elem_len; - -#ifdef PRISM2_DOWNLOAD_SUPPORT - /* Persistent volatile download data */ - struct prism2_download_data *dl_pri; - struct prism2_download_data *dl_sec; -#endif /* PRISM2_DOWNLOAD_SUPPORT */ - -#ifdef PRISM2_IO_DEBUG -#define PRISM2_IO_DEBUG_SIZE 10000 - u32 io_debug[PRISM2_IO_DEBUG_SIZE]; - int io_debug_head; - int io_debug_enabled; -#endif /* PRISM2_IO_DEBUG */ - - /* Pointer to hardware model specific (cs,pci,plx) private data. */ - void *hw_priv; -}; - - -/* Per interface private Host AP data - * Allocated for each net device that Host AP uses (wlan#, wlan#ap, wlan#sta, - * WDS) and netdev_priv(dev) points to this structure. */ -struct hostap_interface { - struct list_head list; /* list entry in Host AP interface list */ - struct net_device *dev; /* pointer to this device */ - struct local_info *local; /* pointer to shared private data */ - struct net_device_stats stats; - struct iw_spy_data spy_data; /* iwspy support */ - struct iw_public_data wireless_data; - - enum { - HOSTAP_INTERFACE_MASTER, - HOSTAP_INTERFACE_MAIN, - HOSTAP_INTERFACE_AP, - HOSTAP_INTERFACE_STA, - HOSTAP_INTERFACE_WDS, - } type; - - union { - struct hostap_interface_wds { - u8 remote_addr[ETH_ALEN]; - } wds; - } u; -}; - - -#define HOSTAP_SKB_TX_DATA_MAGIC 0xf08a36a2 - -/* - * TX meta data - stored in skb->cb buffer, so this must not be increased over - * the 48-byte limit. - * THE PADDING THIS STARTS WITH IS A HORRIBLE HACK THAT SHOULD NOT LIVE - * TO SEE THE DAY. - */ -struct hostap_skb_tx_data { - unsigned int __padding_for_default_qdiscs; - u32 magic; /* HOSTAP_SKB_TX_DATA_MAGIC */ - u8 rate; /* transmit rate */ -#define HOSTAP_TX_FLAGS_WDS BIT(0) -#define HOSTAP_TX_FLAGS_BUFFERED_FRAME BIT(1) -#define HOSTAP_TX_FLAGS_ADD_MOREDATA BIT(2) - u8 flags; /* HOSTAP_TX_FLAGS_* */ - u16 tx_cb_idx; - struct hostap_interface *iface; - unsigned long jiffies; /* queueing timestamp */ - unsigned short ethertype; -}; - - -#ifndef PRISM2_NO_DEBUG - -#define DEBUG_FID BIT(0) -#define DEBUG_PS BIT(1) -#define DEBUG_FLOW BIT(2) -#define DEBUG_AP BIT(3) -#define DEBUG_HW BIT(4) -#define DEBUG_EXTRA BIT(5) -#define DEBUG_EXTRA2 BIT(6) -#define DEBUG_PS2 BIT(7) -#define DEBUG_MASK (DEBUG_PS | DEBUG_AP | DEBUG_HW | DEBUG_EXTRA) -#define PDEBUG(n, args...) \ -do { if ((n) & DEBUG_MASK) printk(KERN_DEBUG args); } while (0) -#define PDEBUG2(n, args...) \ -do { if ((n) & DEBUG_MASK) printk(args); } while (0) - -#else /* PRISM2_NO_DEBUG */ - -#define PDEBUG(n, args...) -#define PDEBUG2(n, args...) - -#endif /* PRISM2_NO_DEBUG */ - -enum { BAP0 = 0, BAP1 = 1 }; - -#define PRISM2_IO_DEBUG_CMD_INB 0 -#define PRISM2_IO_DEBUG_CMD_INW 1 -#define PRISM2_IO_DEBUG_CMD_INSW 2 -#define PRISM2_IO_DEBUG_CMD_OUTB 3 -#define PRISM2_IO_DEBUG_CMD_OUTW 4 -#define PRISM2_IO_DEBUG_CMD_OUTSW 5 -#define PRISM2_IO_DEBUG_CMD_ERROR 6 -#define PRISM2_IO_DEBUG_CMD_INTERRUPT 7 - -#ifdef PRISM2_IO_DEBUG - -#define PRISM2_IO_DEBUG_ENTRY(cmd, reg, value) \ -(((cmd) << 24) | ((reg) << 16) | value) - -static inline void prism2_io_debug_add(struct net_device *dev, int cmd, - int reg, int value) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - - if (!local->io_debug_enabled) - return; - - local->io_debug[local->io_debug_head] = jiffies & 0xffffffff; - if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE) - local->io_debug_head = 0; - local->io_debug[local->io_debug_head] = - PRISM2_IO_DEBUG_ENTRY(cmd, reg, value); - if (++local->io_debug_head >= PRISM2_IO_DEBUG_SIZE) - local->io_debug_head = 0; -} - - -static inline void prism2_io_debug_error(struct net_device *dev, int err) -{ - struct hostap_interface *iface = netdev_priv(dev); - local_info_t *local = iface->local; - unsigned long flags; - - if (!local->io_debug_enabled) - return; - - spin_lock_irqsave(&local->lock, flags); - prism2_io_debug_add(dev, PRISM2_IO_DEBUG_CMD_ERROR, 0, err); - if (local->io_debug_enabled == 1) { - local->io_debug_enabled = 0; - printk(KERN_DEBUG "%s: I/O debug stopped\n", dev->name); - } - spin_unlock_irqrestore(&local->lock, flags); -} - -#else /* PRISM2_IO_DEBUG */ - -static inline void prism2_io_debug_add(struct net_device *dev, int cmd, - int reg, int value) -{ -} - -static inline void prism2_io_debug_error(struct net_device *dev, int err) -{ -} - -#endif /* PRISM2_IO_DEBUG */ - - -#ifdef PRISM2_CALLBACK -enum { - /* Called when card is enabled */ - PRISM2_CALLBACK_ENABLE, - - /* Called when card is disabled */ - PRISM2_CALLBACK_DISABLE, - - /* Called when RX/TX starts/ends */ - PRISM2_CALLBACK_RX_START, PRISM2_CALLBACK_RX_END, - PRISM2_CALLBACK_TX_START, PRISM2_CALLBACK_TX_END -}; -void prism2_callback(local_info_t *local, int event); -#else /* PRISM2_CALLBACK */ -#define prism2_callback(d, e) do { } while (0) -#endif /* PRISM2_CALLBACK */ - -#endif /* __KERNEL__ */ - -#endif /* HOSTAP_WLAN_H */ diff --git a/drivers/net/wireless/i82586.h b/drivers/net/wireless/i82586.h deleted file mode 100644 index 5f65b250646f..000000000000 --- a/drivers/net/wireless/i82586.h +++ /dev/null @@ -1,413 +0,0 @@ -/* - * Intel 82586 IEEE 802.3 Ethernet LAN Coprocessor. - * - * See: - * Intel Microcommunications 1991 - * p1-1 to p1-37 - * Intel order No. 231658 - * ISBN 1-55512-119-5 - * - * Unfortunately, the above chapter mentions neither - * the System Configuration Pointer (SCP) nor the - * Intermediate System Configuration Pointer (ISCP), - * so we probably need to look elsewhere for the - * whole story -- some recommend the "Intel LAN - * Components manual" but I have neither a copy - * nor a full reference. But "elsewhere" may be - * in the same publication... - * The description of a later device, the - * "82596CA High-Performance 32-Bit Local Area Network - * Coprocessor", (ibid. p1-38 to p1-109) does mention - * the SCP and ISCP and also has an i82586 compatibility - * mode. Even more useful is "AP-235 An 82586 Data Link - * Driver" (ibid. p1-337 to p1-417). - */ - -#define I82586_MEMZ (64 * 1024) - -#define I82586_SCP_ADDR (I82586_MEMZ - sizeof(scp_t)) - -#define ADDR_LEN 6 -#define I82586NULL 0xFFFF - -#define toff(t,p,f) (unsigned short)((void *)(&((t *)((void *)0 + (p)))->f) - (void *)0) - -/* - * System Configuration Pointer (SCP). - */ -typedef struct scp_t scp_t; -struct scp_t -{ - unsigned short scp_sysbus; /* 82586 bus width: */ -#define SCP_SY_16BBUS (0x0 << 0) /* 16 bits */ -#define SCP_SY_8BBUS (0x1 << 0) /* 8 bits. */ - unsigned short scp_junk[2]; /* Unused */ - unsigned short scp_iscpl; /* lower 16 bits of ISCP_ADDR */ - unsigned short scp_iscph; /* upper 16 bits of ISCP_ADDR */ -}; - -/* - * Intermediate System Configuration Pointer (ISCP). - */ -typedef struct iscp_t iscp_t; -struct iscp_t -{ - unsigned short iscp_busy; /* set by CPU before first CA, */ - /* cleared by 82586 after read. */ - unsigned short iscp_offset; /* offset of SCB */ - unsigned short iscp_basel; /* base of SCB */ - unsigned short iscp_baseh; /* " */ -}; - -/* - * System Control Block (SCB). - * The 82586 writes its status to scb_status and then - * raises an interrupt to alert the CPU. - * The CPU writes a command to scb_command and - * then issues a Channel Attention (CA) to alert the 82586. - */ -typedef struct scb_t scb_t; -struct scb_t -{ - unsigned short scb_status; /* Status of 82586 */ -#define SCB_ST_INT (0xF << 12) /* Some of: */ -#define SCB_ST_CX (0x1 << 15) /* Cmd completed */ -#define SCB_ST_FR (0x1 << 14) /* Frame received */ -#define SCB_ST_CNA (0x1 << 13) /* Cmd unit not active */ -#define SCB_ST_RNR (0x1 << 12) /* Rcv unit not ready */ -#define SCB_ST_JUNK0 (0x1 << 11) /* 0 */ -#define SCB_ST_CUS (0x7 << 8) /* Cmd unit status */ -#define SCB_ST_CUS_IDLE (0 << 8) /* Idle */ -#define SCB_ST_CUS_SUSP (1 << 8) /* Suspended */ -#define SCB_ST_CUS_ACTV (2 << 8) /* Active */ -#define SCB_ST_JUNK1 (0x1 << 7) /* 0 */ -#define SCB_ST_RUS (0x7 << 4) /* Rcv unit status */ -#define SCB_ST_RUS_IDLE (0 << 4) /* Idle */ -#define SCB_ST_RUS_SUSP (1 << 4) /* Suspended */ -#define SCB_ST_RUS_NRES (2 << 4) /* No resources */ -#define SCB_ST_RUS_RDY (4 << 4) /* Ready */ - unsigned short scb_command; /* Next command */ -#define SCB_CMD_ACK_CX (0x1 << 15) /* Ack cmd completion */ -#define SCB_CMD_ACK_FR (0x1 << 14) /* Ack frame received */ -#define SCB_CMD_ACK_CNA (0x1 << 13) /* Ack CU not active */ -#define SCB_CMD_ACK_RNR (0x1 << 12) /* Ack RU not ready */ -#define SCB_CMD_JUNKX (0x1 << 11) /* Unused */ -#define SCB_CMD_CUC (0x7 << 8) /* Command Unit command */ -#define SCB_CMD_CUC_NOP (0 << 8) /* Nop */ -#define SCB_CMD_CUC_GO (1 << 8) /* Start cbl_offset */ -#define SCB_CMD_CUC_RES (2 << 8) /* Resume execution */ -#define SCB_CMD_CUC_SUS (3 << 8) /* Suspend " */ -#define SCB_CMD_CUC_ABT (4 << 8) /* Abort " */ -#define SCB_CMD_RESET (0x1 << 7) /* Reset chip (hardware) */ -#define SCB_CMD_RUC (0x7 << 4) /* Receive Unit command */ -#define SCB_CMD_RUC_NOP (0 << 4) /* Nop */ -#define SCB_CMD_RUC_GO (1 << 4) /* Start rfa_offset */ -#define SCB_CMD_RUC_RES (2 << 4) /* Resume reception */ -#define SCB_CMD_RUC_SUS (3 << 4) /* Suspend " */ -#define SCB_CMD_RUC_ABT (4 << 4) /* Abort " */ - unsigned short scb_cbl_offset; /* Offset of first command unit */ - /* Action Command */ - unsigned short scb_rfa_offset; /* Offset of first Receive */ - /* Frame Descriptor in the */ - /* Receive Frame Area */ - unsigned short scb_crcerrs; /* Properly aligned frames */ - /* received with a CRC error */ - unsigned short scb_alnerrs; /* Misaligned frames received */ - /* with a CRC error */ - unsigned short scb_rscerrs; /* Frames lost due to no space */ - unsigned short scb_ovrnerrs; /* Frames lost due to slow bus */ -}; - -#define scboff(p,f) toff(scb_t, p, f) - -/* - * The eight Action Commands. - */ -typedef enum acmd_e acmd_e; -enum acmd_e -{ - acmd_nop = 0, /* Do nothing */ - acmd_ia_setup = 1, /* Load an (ethernet) address into the */ - /* 82586 */ - acmd_configure = 2, /* Update the 82586 operating parameters */ - acmd_mc_setup = 3, /* Load a list of (ethernet) multicast */ - /* addresses into the 82586 */ - acmd_transmit = 4, /* Transmit a frame */ - acmd_tdr = 5, /* Perform a Time Domain Reflectometer */ - /* test on the serial link */ - acmd_dump = 6, /* Copy 82586 registers to memory */ - acmd_diagnose = 7, /* Run an internal self test */ -}; - -/* - * Generic Action Command header. - */ -typedef struct ach_t ach_t; -struct ach_t -{ - unsigned short ac_status; /* Command status: */ -#define AC_SFLD_C (0x1 << 15) /* Command completed */ -#define AC_SFLD_B (0x1 << 14) /* Busy executing */ -#define AC_SFLD_OK (0x1 << 13) /* Completed error free */ -#define AC_SFLD_A (0x1 << 12) /* Command aborted */ -#define AC_SFLD_FAIL (0x1 << 11) /* Selftest failed */ -#define AC_SFLD_S10 (0x1 << 10) /* No carrier sense */ - /* during transmission */ -#define AC_SFLD_S9 (0x1 << 9) /* Tx unsuccessful: */ - /* (stopped) lost CTS */ -#define AC_SFLD_S8 (0x1 << 8) /* Tx unsuccessful: */ - /* (stopped) slow DMA */ -#define AC_SFLD_S7 (0x1 << 7) /* Tx deferred: */ - /* other link traffic */ -#define AC_SFLD_S6 (0x1 << 6) /* Heart Beat: collision */ - /* detect after last tx */ -#define AC_SFLD_S5 (0x1 << 5) /* Tx stopped: */ - /* excessive collisions */ -#define AC_SFLD_MAXCOL (0xF << 0) /* Collision count */ - unsigned short ac_command; /* Command specifier: */ -#define AC_CFLD_EL (0x1 << 15) /* End of command list */ -#define AC_CFLD_S (0x1 << 14) /* Suspend on completion */ -#define AC_CFLD_I (0x1 << 13) /* Interrupt on completion */ -#define AC_CFLD_CMD (0x7 << 0) /* acmd_e */ - unsigned short ac_link; /* Next Action Command */ -}; - -#define acoff(p,f) toff(ach_t, p, f) - -/* - * The Nop Action Command. - */ -typedef struct ac_nop_t ac_nop_t; -struct ac_nop_t -{ - ach_t nop_h; -}; - -/* - * The IA-Setup Action Command. - */ -typedef struct ac_ias_t ac_ias_t; -struct ac_ias_t -{ - ach_t ias_h; - unsigned char ias_addr[ADDR_LEN]; /* The (ethernet) address */ -}; - -/* - * The Configure Action Command. - */ -typedef struct ac_cfg_t ac_cfg_t; -struct ac_cfg_t -{ - ach_t cfg_h; - unsigned char cfg_byte_cnt; /* Size foll data: 4-12 */ -#define AC_CFG_BYTE_CNT(v) (((v) & 0xF) << 0) - unsigned char cfg_fifolim; /* FIFO threshold */ -#define AC_CFG_FIFOLIM(v) (((v) & 0xF) << 0) - unsigned char cfg_byte8; -#define AC_CFG_SAV_BF(v) (((v) & 0x1) << 7) /* Save rxd bad frames */ -#define AC_CFG_SRDY(v) (((v) & 0x1) << 6) /* SRDY/ARDY pin means */ - /* external sync. */ - unsigned char cfg_byte9; -#define AC_CFG_ELPBCK(v) (((v) & 0x1) << 7) /* External loopback */ -#define AC_CFG_ILPBCK(v) (((v) & 0x1) << 6) /* Internal loopback */ -#define AC_CFG_PRELEN(v) (((v) & 0x3) << 4) /* Preamble length */ -#define AC_CFG_PLEN_2 0 /* 2 bytes */ -#define AC_CFG_PLEN_4 1 /* 4 bytes */ -#define AC_CFG_PLEN_8 2 /* 8 bytes */ -#define AC_CFG_PLEN_16 3 /* 16 bytes */ -#define AC_CFG_ALOC(v) (((v) & 0x1) << 3) /* Addr/len data is */ - /* explicit in buffers */ -#define AC_CFG_ADDRLEN(v) (((v) & 0x7) << 0) /* Bytes per address */ - unsigned char cfg_byte10; -#define AC_CFG_BOFMET(v) (((v) & 0x1) << 7) /* Use alternate expo. */ - /* backoff method */ -#define AC_CFG_ACR(v) (((v) & 0x7) << 4) /* Accelerated cont. res. */ -#define AC_CFG_LINPRIO(v) (((v) & 0x7) << 0) /* Linear priority */ - unsigned char cfg_ifs; /* Interframe spacing */ - unsigned char cfg_slotl; /* Slot time (low byte) */ - unsigned char cfg_byte13; -#define AC_CFG_RETRYNUM(v) (((v) & 0xF) << 4) /* Max. collision retry */ -#define AC_CFG_SLTTMHI(v) (((v) & 0x7) << 0) /* Slot time (high bits) */ - unsigned char cfg_byte14; -#define AC_CFG_FLGPAD(v) (((v) & 0x1) << 7) /* Pad with HDLC flags */ -#define AC_CFG_BTSTF(v) (((v) & 0x1) << 6) /* Do HDLC bitstuffing */ -#define AC_CFG_CRC16(v) (((v) & 0x1) << 5) /* 16 bit CCITT CRC */ -#define AC_CFG_NCRC(v) (((v) & 0x1) << 4) /* Insert no CRC */ -#define AC_CFG_TNCRS(v) (((v) & 0x1) << 3) /* Tx even if no carrier */ -#define AC_CFG_MANCH(v) (((v) & 0x1) << 2) /* Manchester coding */ -#define AC_CFG_BCDIS(v) (((v) & 0x1) << 1) /* Disable broadcast */ -#define AC_CFG_PRM(v) (((v) & 0x1) << 0) /* Promiscuous mode */ - unsigned char cfg_byte15; -#define AC_CFG_ICDS(v) (((v) & 0x1) << 7) /* Internal collision */ - /* detect source */ -#define AC_CFG_CDTF(v) (((v) & 0x7) << 4) /* Collision detect */ - /* filter in bit times */ -#define AC_CFG_ICSS(v) (((v) & 0x1) << 3) /* Internal carrier */ - /* sense source */ -#define AC_CFG_CSTF(v) (((v) & 0x7) << 0) /* Carrier sense */ - /* filter in bit times */ - unsigned short cfg_min_frm_len; -#define AC_CFG_MNFRM(v) (((v) & 0xFF) << 0) /* Min. bytes/frame (<= 255) */ -}; - -/* - * The MC-Setup Action Command. - */ -typedef struct ac_mcs_t ac_mcs_t; -struct ac_mcs_t -{ - ach_t mcs_h; - unsigned short mcs_cnt; /* No. of bytes of MC addresses */ -#if 0 - unsigned char mcs_data[ADDR_LEN]; /* The first MC address .. */ - ... -#endif -}; - -#define I82586_MAX_MULTICAST_ADDRESSES 128 /* Hardware hashed filter */ - -/* - * The Transmit Action Command. - */ -typedef struct ac_tx_t ac_tx_t; -struct ac_tx_t -{ - ach_t tx_h; - unsigned short tx_tbd_offset; /* Address of list of buffers. */ -#if 0 -Linux packets are passed down with the destination MAC address -and length/type field already prepended to the data, -so we do not need to insert it. Consistent with this -we must also set the AC_CFG_ALOC(..) flag during the -ac_cfg_t action command. - unsigned char tx_addr[ADDR_LEN]; /* The frame dest. address */ - unsigned short tx_length; /* The frame length */ -#endif /* 0 */ -}; - -/* - * The Time Domain Reflectometer Action Command. - */ -typedef struct ac_tdr_t ac_tdr_t; -struct ac_tdr_t -{ - ach_t tdr_h; - unsigned short tdr_result; /* Result. */ -#define AC_TDR_LNK_OK (0x1 << 15) /* No link problem */ -#define AC_TDR_XCVR_PRB (0x1 << 14) /* Txcvr cable problem */ -#define AC_TDR_ET_OPN (0x1 << 13) /* Open on the link */ -#define AC_TDR_ET_SRT (0x1 << 12) /* Short on the link */ -#define AC_TDR_TIME (0x7FF << 0) /* Distance to problem */ - /* site in transmit */ - /* clock cycles */ -}; - -/* - * The Dump Action Command. - */ -typedef struct ac_dmp_t ac_dmp_t; -struct ac_dmp_t -{ - ach_t dmp_h; - unsigned short dmp_offset; /* Result. */ -}; - -/* - * Size of the result of the dump command. - */ -#define DUMPBYTES 170 - -/* - * The Diagnose Action Command. - */ -typedef struct ac_dgn_t ac_dgn_t; -struct ac_dgn_t -{ - ach_t dgn_h; -}; - -/* - * Transmit Buffer Descriptor (TBD). - */ -typedef struct tbd_t tbd_t; -struct tbd_t -{ - unsigned short tbd_status; /* Written by the CPU */ -#define TBD_STATUS_EOF (0x1 << 15) /* This TBD is the */ - /* last for this frame */ -#define TBD_STATUS_ACNT (0x3FFF << 0) /* Actual count of data */ - /* bytes in this buffer */ - unsigned short tbd_next_bd_offset; /* Next in list */ - unsigned short tbd_bufl; /* Buffer address (low) */ - unsigned short tbd_bufh; /* " " (high) */ -}; - -/* - * Receive Buffer Descriptor (RBD). - */ -typedef struct rbd_t rbd_t; -struct rbd_t -{ - unsigned short rbd_status; /* Written by the 82586 */ -#define RBD_STATUS_EOF (0x1 << 15) /* This RBD is the */ - /* last for this frame */ -#define RBD_STATUS_F (0x1 << 14) /* ACNT field is valid */ -#define RBD_STATUS_ACNT (0x3FFF << 0) /* Actual no. of data */ - /* bytes in this buffer */ - unsigned short rbd_next_rbd_offset; /* Next rbd in list */ - unsigned short rbd_bufl; /* Data pointer (low) */ - unsigned short rbd_bufh; /* " " (high) */ - unsigned short rbd_el_size; /* EL+Data buf. size */ -#define RBD_EL (0x1 << 15) /* This BD is the */ - /* last in the list */ -#define RBD_SIZE (0x3FFF << 0) /* No. of bytes the */ - /* buffer can hold */ -}; - -#define rbdoff(p,f) toff(rbd_t, p, f) - -/* - * Frame Descriptor (FD). - */ -typedef struct fd_t fd_t; -struct fd_t -{ - unsigned short fd_status; /* Written by the 82586 */ -#define FD_STATUS_C (0x1 << 15) /* Completed storing frame */ -#define FD_STATUS_B (0x1 << 14) /* FD was consumed by RU */ -#define FD_STATUS_OK (0x1 << 13) /* Frame rxd successfully */ -#define FD_STATUS_S11 (0x1 << 11) /* CRC error */ -#define FD_STATUS_S10 (0x1 << 10) /* Alignment error */ -#define FD_STATUS_S9 (0x1 << 9) /* Ran out of resources */ -#define FD_STATUS_S8 (0x1 << 8) /* Rx DMA overrun */ -#define FD_STATUS_S7 (0x1 << 7) /* Frame too short */ -#define FD_STATUS_S6 (0x1 << 6) /* No EOF flag */ - unsigned short fd_command; /* Command */ -#define FD_COMMAND_EL (0x1 << 15) /* Last FD in list */ -#define FD_COMMAND_S (0x1 << 14) /* Suspend RU after rx */ - unsigned short fd_link_offset; /* Next FD */ - unsigned short fd_rbd_offset; /* First RBD (data) */ - /* Prepared by CPU, */ - /* updated by 82586 */ -#if 0 -I think the rest is unused since we -have set AC_CFG_ALOC(..). However, just -in case, we leave the space. -#endif /* 0 */ - unsigned char fd_dest[ADDR_LEN]; /* Destination address */ - /* Written by 82586 */ - unsigned char fd_src[ADDR_LEN]; /* Source address */ - /* Written by 82586 */ - unsigned short fd_length; /* Frame length or type */ - /* Written by 82586 */ -}; - -#define fdoff(p,f) toff(fd_t, p, f) - -/* - * This software may only be used and distributed - * according to the terms of the GNU General Public License. - * - * For more details, see wavelan.c. - */ diff --git a/drivers/net/wireless/i82593.h b/drivers/net/wireless/i82593.h deleted file mode 100644 index afac5c7a323d..000000000000 --- a/drivers/net/wireless/i82593.h +++ /dev/null @@ -1,229 +0,0 @@ -/* - * Definitions for Intel 82593 CSMA/CD Core LAN Controller - * The definitions are taken from the 1992 users manual with Intel - * order number 297125-001. - * - * /usr/src/pc/RCS/i82593.h,v 1.1 1996/07/17 15:23:12 root Exp - * - * Copyright 1994, Anders Klemets - * - * HISTORY - * i82593.h,v - * Revision 1.4 2005/11/4 09:15:00 baroniunas - * Modified copyright with permission of author as follows: - * - * "If I82539.H is the only file with my copyright statement - * that is included in the Source Forge project, then you have - * my approval to change the copyright statement to be a GPL - * license, in the way you proposed on October 10." - * - * Revision 1.1 1996/07/17 15:23:12 root - * Initial revision - * - * Revision 1.3 1995/04/05 15:13:58 adj - * Initial alpha release - * - * Revision 1.2 1994/06/16 23:57:31 klemets - * Mirrored all the fields in the configuration block. - * - * Revision 1.1 1994/06/02 20:25:34 klemets - * Initial revision - * - * - */ -#ifndef _I82593_H -#define _I82593_H - -/* Intel 82593 CSMA/CD Core LAN Controller */ - -/* Port 0 Command Register definitions */ - -/* Execution operations */ -#define OP0_NOP 0 /* CHNL = 0 */ -#define OP0_SWIT_TO_PORT_1 0 /* CHNL = 1 */ -#define OP0_IA_SETUP 1 -#define OP0_CONFIGURE 2 -#define OP0_MC_SETUP 3 -#define OP0_TRANSMIT 4 -#define OP0_TDR 5 -#define OP0_DUMP 6 -#define OP0_DIAGNOSE 7 -#define OP0_TRANSMIT_NO_CRC 9 -#define OP0_RETRANSMIT 12 -#define OP0_ABORT 13 -/* Reception operations */ -#define OP0_RCV_ENABLE 8 -#define OP0_RCV_DISABLE 10 -#define OP0_STOP_RCV 11 -/* Status pointer control operations */ -#define OP0_FIX_PTR 15 /* CHNL = 1 */ -#define OP0_RLS_PTR 15 /* CHNL = 0 */ -#define OP0_RESET 14 - -#define CR0_CHNL (1 << 4) /* 0=Channel 0, 1=Channel 1 */ -#define CR0_STATUS_0 0x00 -#define CR0_STATUS_1 0x20 -#define CR0_STATUS_2 0x40 -#define CR0_STATUS_3 0x60 -#define CR0_INT_ACK (1 << 7) /* 0=No ack, 1=acknowledge */ - -/* Port 0 Status Register definitions */ - -#define SR0_NO_RESULT 0 /* dummy */ -#define SR0_EVENT_MASK 0x0f -#define SR0_IA_SETUP_DONE 1 -#define SR0_CONFIGURE_DONE 2 -#define SR0_MC_SETUP_DONE 3 -#define SR0_TRANSMIT_DONE 4 -#define SR0_TDR_DONE 5 -#define SR0_DUMP_DONE 6 -#define SR0_DIAGNOSE_PASSED 7 -#define SR0_TRANSMIT_NO_CRC_DONE 9 -#define SR0_RETRANSMIT_DONE 12 -#define SR0_EXECUTION_ABORTED 13 -#define SR0_END_OF_FRAME 8 -#define SR0_RECEPTION_ABORTED 10 -#define SR0_DIAGNOSE_FAILED 15 -#define SR0_STOP_REG_HIT 11 - -#define SR0_CHNL (1 << 4) -#define SR0_EXECUTION (1 << 5) -#define SR0_RECEPTION (1 << 6) -#define SR0_INTERRUPT (1 << 7) -#define SR0_BOTH_RX_TX (SR0_EXECUTION | SR0_RECEPTION) - -#define SR3_EXEC_STATE_MASK 0x03 -#define SR3_EXEC_IDLE 0 -#define SR3_TX_ABORT_IN_PROGRESS 1 -#define SR3_EXEC_ACTIVE 2 -#define SR3_ABORT_IN_PROGRESS 3 -#define SR3_EXEC_CHNL (1 << 2) -#define SR3_STP_ON_NO_RSRC (1 << 3) -#define SR3_RCVING_NO_RSRC (1 << 4) -#define SR3_RCV_STATE_MASK 0x60 -#define SR3_RCV_IDLE 0x00 -#define SR3_RCV_READY 0x20 -#define SR3_RCV_ACTIVE 0x40 -#define SR3_RCV_STOP_IN_PROG 0x60 -#define SR3_RCV_CHNL (1 << 7) - -/* Port 1 Command Register definitions */ - -#define OP1_NOP 0 -#define OP1_SWIT_TO_PORT_0 1 -#define OP1_INT_DISABLE 2 -#define OP1_INT_ENABLE 3 -#define OP1_SET_TS 5 -#define OP1_RST_TS 7 -#define OP1_POWER_DOWN 8 -#define OP1_RESET_RING_MNGMT 11 -#define OP1_RESET 14 -#define OP1_SEL_RST 15 - -#define CR1_STATUS_4 0x00 -#define CR1_STATUS_5 0x20 -#define CR1_STATUS_6 0x40 -#define CR1_STOP_REG_UPDATE (1 << 7) - -/* Receive frame status bits */ - -#define RX_RCLD (1 << 0) -#define RX_IA_MATCH (1 << 1) -#define RX_NO_AD_MATCH (1 << 2) -#define RX_NO_SFD (1 << 3) -#define RX_SRT_FRM (1 << 7) -#define RX_OVRRUN (1 << 8) -#define RX_ALG_ERR (1 << 10) -#define RX_CRC_ERR (1 << 11) -#define RX_LEN_ERR (1 << 12) -#define RX_RCV_OK (1 << 13) -#define RX_TYP_LEN (1 << 15) - -/* Transmit status bits */ - -#define TX_NCOL_MASK 0x0f -#define TX_FRTL (1 << 4) -#define TX_MAX_COL (1 << 5) -#define TX_HRT_BEAT (1 << 6) -#define TX_DEFER (1 << 7) -#define TX_UND_RUN (1 << 8) -#define TX_LOST_CTS (1 << 9) -#define TX_LOST_CRS (1 << 10) -#define TX_LTCOL (1 << 11) -#define TX_OK (1 << 13) -#define TX_COLL (1 << 15) - -struct i82593_conf_block { - u_char fifo_limit : 4, - forgnesi : 1, - fifo_32 : 1, - d6mod : 1, - throttle_enb : 1; - u_char throttle : 6, - cntrxint : 1, - contin : 1; - u_char addr_len : 3, - acloc : 1, - preamb_len : 2, - loopback : 2; - u_char lin_prio : 3, - tbofstop : 1, - exp_prio : 3, - bof_met : 1; - u_char : 4, - ifrm_spc : 4; - u_char : 5, - slottim_low : 3; - u_char slottim_hi : 3, - : 1, - max_retr : 4; - u_char prmisc : 1, - bc_dis : 1, - : 1, - crs_1 : 1, - nocrc_ins : 1, - crc_1632 : 1, - : 1, - crs_cdt : 1; - u_char cs_filter : 3, - crs_src : 1, - cd_filter : 3, - : 1; - u_char : 2, - min_fr_len : 6; - u_char lng_typ : 1, - lng_fld : 1, - rxcrc_xf : 1, - artx : 1, - sarec : 1, - tx_jabber : 1, /* why is this called max_len in the manual? */ - hash_1 : 1, - lbpkpol : 1; - u_char : 6, - fdx : 1, - : 1; - u_char dummy_6 : 6, /* supposed to be ones */ - mult_ia : 1, - dis_bof : 1; - u_char dummy_1 : 1, /* supposed to be one */ - tx_ifs_retrig : 2, - mc_all : 1, - rcv_mon : 2, - frag_acpt : 1, - tstrttrs : 1; - u_char fretx : 1, - runt_eop : 1, - hw_sw_pin : 1, - big_endn : 1, - syncrqs : 1, - sttlen : 1, - tx_eop : 1, - rx_eop : 1; - u_char rbuf_size : 5, - rcvstop : 1, - : 2; -}; - -#define I82593_MAX_MULTICAST_ADDRESSES 128 /* Hardware hashed filter */ - -#endif /* _I82593_H */ diff --git a/drivers/net/wireless/ipw2x00/Kconfig b/drivers/net/wireless/ipw2x00/Kconfig deleted file mode 100644 index a8131384c6b9..000000000000 --- a/drivers/net/wireless/ipw2x00/Kconfig +++ /dev/null @@ -1,192 +0,0 @@ -# -# Intel Centrino wireless drivers -# - -config IPW2100 - tristate "Intel PRO/Wireless 2100 Network Connection" - depends on PCI && WLAN_80211 && CFG80211 - select WIRELESS_EXT - select FW_LOADER - select LIB80211 - select LIBIPW - ---help--- - A driver for the Intel PRO/Wireless 2100 Network - Connection 802.11b wireless network adapter. - - See for information on - the capabilities currently enabled in this driver and for tips - for debugging issues and problems. - - In order to use this driver, you will need a firmware image for it. - You can obtain the firmware from - . Once you have the firmware image, you - will need to place it in /lib/firmware. - - You will also very likely need the Wireless Tools in order to - configure your card: - - . - - It is recommended that you compile this driver as a module (M) - rather than built-in (Y). This driver requires firmware at device - initialization time, and when built-in this typically happens - before the filesystem is accessible (hence firmware will be - unavailable and initialization will fail). If you do choose to build - this driver into your kernel image, you can avoid this problem by - including the firmware and a firmware loader in an initramfs. - -config IPW2100_MONITOR - bool "Enable promiscuous mode" - depends on IPW2100 - ---help--- - Enables promiscuous/monitor mode support for the ipw2100 driver. - With this feature compiled into the driver, you can switch to - promiscuous mode via the Wireless Tool's Monitor mode. While in this - mode, no packets can be sent. - -config IPW2100_DEBUG - bool "Enable full debugging output in IPW2100 module." - depends on IPW2100 - ---help--- - This option will enable debug tracing output for the IPW2100. - - This will result in the kernel module being ~60k larger. You can - control which debug output is sent to the kernel log by setting the - value in - - /sys/bus/pci/drivers/ipw2100/debug_level - - This entry will only exist if this option is enabled. - - If you are not trying to debug or develop the IPW2100 driver, you - most likely want to say N here. - -config IPW2200 - tristate "Intel PRO/Wireless 2200BG and 2915ABG Network Connection" - depends on PCI && WLAN_80211 && CFG80211 - select WIRELESS_EXT - select FW_LOADER - select LIB80211 - select LIBIPW - ---help--- - A driver for the Intel PRO/Wireless 2200BG and 2915ABG Network - Connection adapters. - - See for - information on the capabilities currently enabled in this - driver and for tips for debugging issues and problems. - - In order to use this driver, you will need a firmware image for it. - You can obtain the firmware from - . See the above referenced README.ipw2200 - for information on where to install the firmware images. - - You will also very likely need the Wireless Tools in order to - configure your card: - - . - - It is recommended that you compile this driver as a module (M) - rather than built-in (Y). This driver requires firmware at device - initialization time, and when built-in this typically happens - before the filesystem is accessible (hence firmware will be - unavailable and initialization will fail). If you do choose to build - this driver into your kernel image, you can avoid this problem by - including the firmware and a firmware loader in an initramfs. - -config IPW2200_MONITOR - bool "Enable promiscuous mode" - depends on IPW2200 - ---help--- - Enables promiscuous/monitor mode support for the ipw2200 driver. - With this feature compiled into the driver, you can switch to - promiscuous mode via the Wireless Tool's Monitor mode. While in this - mode, no packets can be sent. - -config IPW2200_RADIOTAP - bool "Enable radiotap format 802.11 raw packet support" - depends on IPW2200_MONITOR - -config IPW2200_PROMISCUOUS - bool "Enable creation of a RF radiotap promiscuous interface" - depends on IPW2200_MONITOR - select IPW2200_RADIOTAP - ---help--- - Enables the creation of a second interface prefixed 'rtap'. - This second interface will provide every received in radiotap - format. - - This is useful for performing wireless network analysis while - maintaining an active association. - - Example usage: - - % modprobe ipw2200 rtap_iface=1 - % ifconfig rtap0 up - % tethereal -i rtap0 - - If you do not specify 'rtap_iface=1' as a module parameter then - the rtap interface will not be created and you will need to turn - it on via sysfs: - - % echo 1 > /sys/bus/pci/drivers/ipw2200/*/rtap_iface - -config IPW2200_QOS - bool "Enable QoS support" - depends on IPW2200 && EXPERIMENTAL - -config IPW2200_DEBUG - bool "Enable full debugging output in IPW2200 module." - depends on IPW2200 - ---help--- - This option will enable low level debug tracing output for IPW2200. - - Note, normal debug code is already compiled in. This low level - debug option enables debug on hot paths (e.g Tx, Rx, ISR) and - will result in the kernel module being ~70 larger. Most users - will typically not need this high verbosity debug information. - - If you are not sure, say N here. - -config LIBIPW - tristate - depends on PCI && WLAN_80211 && CFG80211 - select WIRELESS_EXT - select CRYPTO - select CRYPTO_ARC4 - select CRYPTO_ECB - select CRYPTO_AES - select CRYPTO_MICHAEL_MIC - select CRYPTO_ECB - select CRC32 - select LIB80211 - select LIB80211_CRYPT_WEP - select LIB80211_CRYPT_TKIP - select LIB80211_CRYPT_CCMP - ---help--- - This option enables the hardware independent IEEE 802.11 - networking stack. This component is deprecated in favor of the - mac80211 component. - -config LIBIPW_DEBUG - bool "Full debugging output for the LIBIPW component" - depends on LIBIPW - ---help--- - This option will enable debug tracing output for the - libipw component. - - This will result in the kernel module being ~70k larger. You - can control which debug output is sent to the kernel log by - setting the value in - - /proc/net/ieee80211/debug_level - - For example: - - % echo 0x00000FFO > /proc/net/ieee80211/debug_level - - For a list of values you can assign to debug_level, you - can look at the bit mask values in ieee80211.h - - If you are not trying to debug or develop the libipw - component, you most likely want to say N here. diff --git a/drivers/net/wireless/ipw2x00/Makefile b/drivers/net/wireless/ipw2x00/Makefile deleted file mode 100644 index aecd2cff462b..000000000000 --- a/drivers/net/wireless/ipw2x00/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -# -# Makefile for the Intel Centrino wireless drivers -# - -obj-$(CONFIG_IPW2100) += ipw2100.o -obj-$(CONFIG_IPW2200) += ipw2200.o - -obj-$(CONFIG_LIBIPW) += libipw.o -libipw-objs := \ - libipw_module.o \ - libipw_tx.o \ - libipw_rx.o \ - libipw_wx.o \ - libipw_geo.o diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c deleted file mode 100644 index 43102bff8dee..000000000000 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ /dev/null @@ -1,8682 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - - Portions of this file are based on the sample_* files provided by Wireless - Extensions 0.26 package and copyright (c) 1997-2003 Jean Tourrilhes - - - Portions of this file are based on the Host AP project, - Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen - - Portions of ipw2100_mod_firmware_load, ipw2100_do_mod_firmware_load, and - ipw2100_fw_load are loosely based on drivers/sound/sound_firmware.c - available in the 2.4.25 kernel sources, and are copyright (c) Alan Cox - -******************************************************************************/ -/* - - Initial driver on which this is based was developed by Janusz Gorycki, - Maciej Urbaniak, and Maciej Sosnowski. - - Promiscuous mode support added by Jacek Wysoczynski and Maciej Urbaniak. - -Theory of Operation - -Tx - Commands and Data - -Firmware and host share a circular queue of Transmit Buffer Descriptors (TBDs) -Each TBD contains a pointer to the physical (dma_addr_t) address of data being -sent to the firmware as well as the length of the data. - -The host writes to the TBD queue at the WRITE index. The WRITE index points -to the _next_ packet to be written and is advanced when after the TBD has been -filled. - -The firmware pulls from the TBD queue at the READ index. The READ index points -to the currently being read entry, and is advanced once the firmware is -done with a packet. - -When data is sent to the firmware, the first TBD is used to indicate to the -firmware if a Command or Data is being sent. If it is Command, all of the -command information is contained within the physical address referred to by the -TBD. If it is Data, the first TBD indicates the type of data packet, number -of fragments, etc. The next TBD then referrs to the actual packet location. - -The Tx flow cycle is as follows: - -1) ipw2100_tx() is called by kernel with SKB to transmit -2) Packet is move from the tx_free_list and appended to the transmit pending - list (tx_pend_list) -3) work is scheduled to move pending packets into the shared circular queue. -4) when placing packet in the circular queue, the incoming SKB is DMA mapped - to a physical address. That address is entered into a TBD. Two TBDs are - filled out. The first indicating a data packet, the second referring to the - actual payload data. -5) the packet is removed from tx_pend_list and placed on the end of the - firmware pending list (fw_pend_list) -6) firmware is notified that the WRITE index has -7) Once the firmware has processed the TBD, INTA is triggered. -8) For each Tx interrupt received from the firmware, the READ index is checked - to see which TBDs are done being processed. -9) For each TBD that has been processed, the ISR pulls the oldest packet - from the fw_pend_list. -10)The packet structure contained in the fw_pend_list is then used - to unmap the DMA address and to free the SKB originally passed to the driver - from the kernel. -11)The packet structure is placed onto the tx_free_list - -The above steps are the same for commands, only the msg_free_list/msg_pend_list -are used instead of tx_free_list/tx_pend_list - -... - -Critical Sections / Locking : - -There are two locks utilized. The first is the low level lock (priv->low_lock) -that protects the following: - -- Access to the Tx/Rx queue lists via priv->low_lock. The lists are as follows: - - tx_free_list : Holds pre-allocated Tx buffers. - TAIL modified in __ipw2100_tx_process() - HEAD modified in ipw2100_tx() - - tx_pend_list : Holds used Tx buffers waiting to go into the TBD ring - TAIL modified ipw2100_tx() - HEAD modified by ipw2100_tx_send_data() - - msg_free_list : Holds pre-allocated Msg (Command) buffers - TAIL modified in __ipw2100_tx_process() - HEAD modified in ipw2100_hw_send_command() - - msg_pend_list : Holds used Msg buffers waiting to go into the TBD ring - TAIL modified in ipw2100_hw_send_command() - HEAD modified in ipw2100_tx_send_commands() - - The flow of data on the TX side is as follows: - - MSG_FREE_LIST + COMMAND => MSG_PEND_LIST => TBD => MSG_FREE_LIST - TX_FREE_LIST + DATA => TX_PEND_LIST => TBD => TX_FREE_LIST - - The methods that work on the TBD ring are protected via priv->low_lock. - -- The internal data state of the device itself -- Access to the firmware read/write indexes for the BD queues - and associated logic - -All external entry functions are locked with the priv->action_lock to ensure -that only one external action is invoked at a time. - - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ipw2100.h" - -#define IPW2100_VERSION "git-1.2.2" - -#define DRV_NAME "ipw2100" -#define DRV_VERSION IPW2100_VERSION -#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2100 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" - -/* Debugging stuff */ -#ifdef CONFIG_IPW2100_DEBUG -#define IPW2100_RX_DEBUG /* Reception debugging */ -#endif - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); - -static int debug = 0; -static int network_mode = 0; -static int channel = 0; -static int associate = 0; -static int disable = 0; -#ifdef CONFIG_PM -static struct ipw2100_fw ipw2100_firmware; -#endif - -#include -module_param(debug, int, 0444); -module_param_named(mode, network_mode, int, 0444); -module_param(channel, int, 0444); -module_param(associate, int, 0444); -module_param(disable, int, 0444); - -MODULE_PARM_DESC(debug, "debug level"); -MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); -MODULE_PARM_DESC(channel, "channel"); -MODULE_PARM_DESC(associate, "auto associate when scanning (default off)"); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); - -static u32 ipw2100_debug_level = IPW_DL_NONE; - -#ifdef CONFIG_IPW2100_DEBUG -#define IPW_DEBUG(level, message...) \ -do { \ - if (ipw2100_debug_level & (level)) { \ - printk(KERN_DEBUG "ipw2100: %c %s ", \ - in_interrupt() ? 'I' : 'U', __func__); \ - printk(message); \ - } \ -} while (0) -#else -#define IPW_DEBUG(level, message...) do {} while (0) -#endif /* CONFIG_IPW2100_DEBUG */ - -#ifdef CONFIG_IPW2100_DEBUG -static const char *command_types[] = { - "undefined", - "unused", /* HOST_ATTENTION */ - "HOST_COMPLETE", - "unused", /* SLEEP */ - "unused", /* HOST_POWER_DOWN */ - "unused", - "SYSTEM_CONFIG", - "unused", /* SET_IMR */ - "SSID", - "MANDATORY_BSSID", - "AUTHENTICATION_TYPE", - "ADAPTER_ADDRESS", - "PORT_TYPE", - "INTERNATIONAL_MODE", - "CHANNEL", - "RTS_THRESHOLD", - "FRAG_THRESHOLD", - "POWER_MODE", - "TX_RATES", - "BASIC_TX_RATES", - "WEP_KEY_INFO", - "unused", - "unused", - "unused", - "unused", - "WEP_KEY_INDEX", - "WEP_FLAGS", - "ADD_MULTICAST", - "CLEAR_ALL_MULTICAST", - "BEACON_INTERVAL", - "ATIM_WINDOW", - "CLEAR_STATISTICS", - "undefined", - "undefined", - "undefined", - "undefined", - "TX_POWER_INDEX", - "undefined", - "undefined", - "undefined", - "undefined", - "undefined", - "undefined", - "BROADCAST_SCAN", - "CARD_DISABLE", - "PREFERRED_BSSID", - "SET_SCAN_OPTIONS", - "SCAN_DWELL_TIME", - "SWEEP_TABLE", - "AP_OR_STATION_TABLE", - "GROUP_ORDINALS", - "SHORT_RETRY_LIMIT", - "LONG_RETRY_LIMIT", - "unused", /* SAVE_CALIBRATION */ - "unused", /* RESTORE_CALIBRATION */ - "undefined", - "undefined", - "undefined", - "HOST_PRE_POWER_DOWN", - "unused", /* HOST_INTERRUPT_COALESCING */ - "undefined", - "CARD_DISABLE_PHY_OFF", - "MSDU_TX_RATES" "undefined", - "undefined", - "SET_STATION_STAT_BITS", - "CLEAR_STATIONS_STAT_BITS", - "LEAP_ROGUE_MODE", - "SET_SECURITY_INFORMATION", - "DISASSOCIATION_BSSID", - "SET_WPA_ASS_IE" -}; -#endif - -/* Pre-decl until we get the code solid and then we can clean it up */ -static void ipw2100_tx_send_commands(struct ipw2100_priv *priv); -static void ipw2100_tx_send_data(struct ipw2100_priv *priv); -static int ipw2100_adapter_setup(struct ipw2100_priv *priv); - -static void ipw2100_queues_initialize(struct ipw2100_priv *priv); -static void ipw2100_queues_free(struct ipw2100_priv *priv); -static int ipw2100_queues_allocate(struct ipw2100_priv *priv); - -static int ipw2100_fw_download(struct ipw2100_priv *priv, - struct ipw2100_fw *fw); -static int ipw2100_get_firmware(struct ipw2100_priv *priv, - struct ipw2100_fw *fw); -static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf, - size_t max); -static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf, - size_t max); -static void ipw2100_release_firmware(struct ipw2100_priv *priv, - struct ipw2100_fw *fw); -static int ipw2100_ucode_download(struct ipw2100_priv *priv, - struct ipw2100_fw *fw); -static void ipw2100_wx_event_work(struct work_struct *work); -static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev); -static struct iw_handler_def ipw2100_wx_handler_def; - -static inline void read_register(struct net_device *dev, u32 reg, u32 * val) -{ - *val = readl((void __iomem *)(dev->base_addr + reg)); - IPW_DEBUG_IO("r: 0x%08X => 0x%08X\n", reg, *val); -} - -static inline void write_register(struct net_device *dev, u32 reg, u32 val) -{ - writel(val, (void __iomem *)(dev->base_addr + reg)); - IPW_DEBUG_IO("w: 0x%08X <= 0x%08X\n", reg, val); -} - -static inline void read_register_word(struct net_device *dev, u32 reg, - u16 * val) -{ - *val = readw((void __iomem *)(dev->base_addr + reg)); - IPW_DEBUG_IO("r: 0x%08X => %04X\n", reg, *val); -} - -static inline void read_register_byte(struct net_device *dev, u32 reg, u8 * val) -{ - *val = readb((void __iomem *)(dev->base_addr + reg)); - IPW_DEBUG_IO("r: 0x%08X => %02X\n", reg, *val); -} - -static inline void write_register_word(struct net_device *dev, u32 reg, u16 val) -{ - writew(val, (void __iomem *)(dev->base_addr + reg)); - IPW_DEBUG_IO("w: 0x%08X <= %04X\n", reg, val); -} - -static inline void write_register_byte(struct net_device *dev, u32 reg, u8 val) -{ - writeb(val, (void __iomem *)(dev->base_addr + reg)); - IPW_DEBUG_IO("w: 0x%08X =< %02X\n", reg, val); -} - -static inline void read_nic_dword(struct net_device *dev, u32 addr, u32 * val) -{ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); - read_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); -} - -static inline void write_nic_dword(struct net_device *dev, u32 addr, u32 val) -{ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); - write_register(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); -} - -static inline void read_nic_word(struct net_device *dev, u32 addr, u16 * val) -{ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); - read_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); -} - -static inline void write_nic_word(struct net_device *dev, u32 addr, u16 val) -{ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); - write_register_word(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); -} - -static inline void read_nic_byte(struct net_device *dev, u32 addr, u8 * val) -{ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); - read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); -} - -static inline void write_nic_byte(struct net_device *dev, u32 addr, u8 val) -{ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); - write_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA, val); -} - -static inline void write_nic_auto_inc_address(struct net_device *dev, u32 addr) -{ - write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, - addr & IPW_REG_INDIRECT_ADDR_MASK); -} - -static inline void write_nic_dword_auto_inc(struct net_device *dev, u32 val) -{ - write_register(dev, IPW_REG_AUTOINCREMENT_DATA, val); -} - -static void write_nic_memory(struct net_device *dev, u32 addr, u32 len, - const u8 * buf) -{ - u32 aligned_addr; - u32 aligned_len; - u32 dif_len; - u32 i; - - /* read first nibble byte by byte */ - aligned_addr = addr & (~0x3); - dif_len = addr - aligned_addr; - if (dif_len) { - /* Start reading at aligned_addr + dif_len */ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - aligned_addr); - for (i = dif_len; i < 4; i++, buf++) - write_register_byte(dev, - IPW_REG_INDIRECT_ACCESS_DATA + i, - *buf); - - len -= dif_len; - aligned_addr += 4; - } - - /* read DWs through autoincrement registers */ - write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, aligned_addr); - aligned_len = len & (~0x3); - for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4) - write_register(dev, IPW_REG_AUTOINCREMENT_DATA, *(u32 *) buf); - - /* copy the last nibble */ - dif_len = len - aligned_len; - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr); - for (i = 0; i < dif_len; i++, buf++) - write_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA + i, - *buf); -} - -static void read_nic_memory(struct net_device *dev, u32 addr, u32 len, - u8 * buf) -{ - u32 aligned_addr; - u32 aligned_len; - u32 dif_len; - u32 i; - - /* read first nibble byte by byte */ - aligned_addr = addr & (~0x3); - dif_len = addr - aligned_addr; - if (dif_len) { - /* Start reading at aligned_addr + dif_len */ - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, - aligned_addr); - for (i = dif_len; i < 4; i++, buf++) - read_register_byte(dev, - IPW_REG_INDIRECT_ACCESS_DATA + i, - buf); - - len -= dif_len; - aligned_addr += 4; - } - - /* read DWs through autoincrement registers */ - write_register(dev, IPW_REG_AUTOINCREMENT_ADDRESS, aligned_addr); - aligned_len = len & (~0x3); - for (i = 0; i < aligned_len; i += 4, buf += 4, aligned_addr += 4) - read_register(dev, IPW_REG_AUTOINCREMENT_DATA, (u32 *) buf); - - /* copy the last nibble */ - dif_len = len - aligned_len; - write_register(dev, IPW_REG_INDIRECT_ACCESS_ADDRESS, aligned_addr); - for (i = 0; i < dif_len; i++, buf++) - read_register_byte(dev, IPW_REG_INDIRECT_ACCESS_DATA + i, buf); -} - -static inline int ipw2100_hw_is_adapter_in_system(struct net_device *dev) -{ - return (dev->base_addr && - (readl - ((void __iomem *)(dev->base_addr + - IPW_REG_DOA_DEBUG_AREA_START)) - == IPW_DATA_DOA_DEBUG_VALUE)); -} - -static int ipw2100_get_ordinal(struct ipw2100_priv *priv, u32 ord, - void *val, u32 * len) -{ - struct ipw2100_ordinals *ordinals = &priv->ordinals; - u32 addr; - u32 field_info; - u16 field_len; - u16 field_count; - u32 total_length; - - if (ordinals->table1_addr == 0) { - printk(KERN_WARNING DRV_NAME ": attempt to use fw ordinals " - "before they have been loaded.\n"); - return -EINVAL; - } - - if (IS_ORDINAL_TABLE_ONE(ordinals, ord)) { - if (*len < IPW_ORD_TAB_1_ENTRY_SIZE) { - *len = IPW_ORD_TAB_1_ENTRY_SIZE; - - printk(KERN_WARNING DRV_NAME - ": ordinal buffer length too small, need %zd\n", - IPW_ORD_TAB_1_ENTRY_SIZE); - - return -EINVAL; - } - - read_nic_dword(priv->net_dev, - ordinals->table1_addr + (ord << 2), &addr); - read_nic_dword(priv->net_dev, addr, val); - - *len = IPW_ORD_TAB_1_ENTRY_SIZE; - - return 0; - } - - if (IS_ORDINAL_TABLE_TWO(ordinals, ord)) { - - ord -= IPW_START_ORD_TAB_2; - - /* get the address of statistic */ - read_nic_dword(priv->net_dev, - ordinals->table2_addr + (ord << 3), &addr); - - /* get the second DW of statistics ; - * two 16-bit words - first is length, second is count */ - read_nic_dword(priv->net_dev, - ordinals->table2_addr + (ord << 3) + sizeof(u32), - &field_info); - - /* get each entry length */ - field_len = *((u16 *) & field_info); - - /* get number of entries */ - field_count = *(((u16 *) & field_info) + 1); - - /* abort if no enought memory */ - total_length = field_len * field_count; - if (total_length > *len) { - *len = total_length; - return -EINVAL; - } - - *len = total_length; - if (!total_length) - return 0; - - /* read the ordinal data from the SRAM */ - read_nic_memory(priv->net_dev, addr, total_length, val); - - return 0; - } - - printk(KERN_WARNING DRV_NAME ": ordinal %d neither in table 1 nor " - "in table 2\n", ord); - - return -EINVAL; -} - -static int ipw2100_set_ordinal(struct ipw2100_priv *priv, u32 ord, u32 * val, - u32 * len) -{ - struct ipw2100_ordinals *ordinals = &priv->ordinals; - u32 addr; - - if (IS_ORDINAL_TABLE_ONE(ordinals, ord)) { - if (*len != IPW_ORD_TAB_1_ENTRY_SIZE) { - *len = IPW_ORD_TAB_1_ENTRY_SIZE; - IPW_DEBUG_INFO("wrong size\n"); - return -EINVAL; - } - - read_nic_dword(priv->net_dev, - ordinals->table1_addr + (ord << 2), &addr); - - write_nic_dword(priv->net_dev, addr, *val); - - *len = IPW_ORD_TAB_1_ENTRY_SIZE; - - return 0; - } - - IPW_DEBUG_INFO("wrong table\n"); - if (IS_ORDINAL_TABLE_TWO(ordinals, ord)) - return -EINVAL; - - return -EINVAL; -} - -static char *snprint_line(char *buf, size_t count, - const u8 * data, u32 len, u32 ofs) -{ - int out, i, j, l; - char c; - - out = snprintf(buf, count, "%08X", ofs); - - for (l = 0, i = 0; i < 2; i++) { - out += snprintf(buf + out, count - out, " "); - for (j = 0; j < 8 && l < len; j++, l++) - out += snprintf(buf + out, count - out, "%02X ", - data[(i * 8 + j)]); - for (; j < 8; j++) - out += snprintf(buf + out, count - out, " "); - } - - out += snprintf(buf + out, count - out, " "); - for (l = 0, i = 0; i < 2; i++) { - out += snprintf(buf + out, count - out, " "); - for (j = 0; j < 8 && l < len; j++, l++) { - c = data[(i * 8 + j)]; - if (!isascii(c) || !isprint(c)) - c = '.'; - - out += snprintf(buf + out, count - out, "%c", c); - } - - for (; j < 8; j++) - out += snprintf(buf + out, count - out, " "); - } - - return buf; -} - -static void printk_buf(int level, const u8 * data, u32 len) -{ - char line[81]; - u32 ofs = 0; - if (!(ipw2100_debug_level & level)) - return; - - while (len) { - printk(KERN_DEBUG "%s\n", - snprint_line(line, sizeof(line), &data[ofs], - min(len, 16U), ofs)); - ofs += 16; - len -= min(len, 16U); - } -} - -#define MAX_RESET_BACKOFF 10 - -static void schedule_reset(struct ipw2100_priv *priv) -{ - unsigned long now = get_seconds(); - - /* If we haven't received a reset request within the backoff period, - * then we can reset the backoff interval so this reset occurs - * immediately */ - if (priv->reset_backoff && - (now - priv->last_reset > priv->reset_backoff)) - priv->reset_backoff = 0; - - priv->last_reset = get_seconds(); - - if (!(priv->status & STATUS_RESET_PENDING)) { - IPW_DEBUG_INFO("%s: Scheduling firmware restart (%ds).\n", - priv->net_dev->name, priv->reset_backoff); - netif_carrier_off(priv->net_dev); - netif_stop_queue(priv->net_dev); - priv->status |= STATUS_RESET_PENDING; - if (priv->reset_backoff) - queue_delayed_work(priv->workqueue, &priv->reset_work, - priv->reset_backoff * HZ); - else - queue_delayed_work(priv->workqueue, &priv->reset_work, - 0); - - if (priv->reset_backoff < MAX_RESET_BACKOFF) - priv->reset_backoff++; - - wake_up_interruptible(&priv->wait_command_queue); - } else - IPW_DEBUG_INFO("%s: Firmware restart already in progress.\n", - priv->net_dev->name); - -} - -#define HOST_COMPLETE_TIMEOUT (2 * HZ) -static int ipw2100_hw_send_command(struct ipw2100_priv *priv, - struct host_command *cmd) -{ - struct list_head *element; - struct ipw2100_tx_packet *packet; - unsigned long flags; - int err = 0; - - IPW_DEBUG_HC("Sending %s command (#%d), %d bytes\n", - command_types[cmd->host_command], cmd->host_command, - cmd->host_command_length); - printk_buf(IPW_DL_HC, (u8 *) cmd->host_command_parameters, - cmd->host_command_length); - - spin_lock_irqsave(&priv->low_lock, flags); - - if (priv->fatal_error) { - IPW_DEBUG_INFO - ("Attempt to send command while hardware in fatal error condition.\n"); - err = -EIO; - goto fail_unlock; - } - - if (!(priv->status & STATUS_RUNNING)) { - IPW_DEBUG_INFO - ("Attempt to send command while hardware is not running.\n"); - err = -EIO; - goto fail_unlock; - } - - if (priv->status & STATUS_CMD_ACTIVE) { - IPW_DEBUG_INFO - ("Attempt to send command while another command is pending.\n"); - err = -EBUSY; - goto fail_unlock; - } - - if (list_empty(&priv->msg_free_list)) { - IPW_DEBUG_INFO("no available msg buffers\n"); - goto fail_unlock; - } - - priv->status |= STATUS_CMD_ACTIVE; - priv->messages_sent++; - - element = priv->msg_free_list.next; - - packet = list_entry(element, struct ipw2100_tx_packet, list); - packet->jiffy_start = jiffies; - - /* initialize the firmware command packet */ - packet->info.c_struct.cmd->host_command_reg = cmd->host_command; - packet->info.c_struct.cmd->host_command_reg1 = cmd->host_command1; - packet->info.c_struct.cmd->host_command_len_reg = - cmd->host_command_length; - packet->info.c_struct.cmd->sequence = cmd->host_command_sequence; - - memcpy(packet->info.c_struct.cmd->host_command_params_reg, - cmd->host_command_parameters, - sizeof(packet->info.c_struct.cmd->host_command_params_reg)); - - list_del(element); - DEC_STAT(&priv->msg_free_stat); - - list_add_tail(element, &priv->msg_pend_list); - INC_STAT(&priv->msg_pend_stat); - - ipw2100_tx_send_commands(priv); - ipw2100_tx_send_data(priv); - - spin_unlock_irqrestore(&priv->low_lock, flags); - - /* - * We must wait for this command to complete before another - * command can be sent... but if we wait more than 3 seconds - * then there is a problem. - */ - - err = - wait_event_interruptible_timeout(priv->wait_command_queue, - !(priv-> - status & STATUS_CMD_ACTIVE), - HOST_COMPLETE_TIMEOUT); - - if (err == 0) { - IPW_DEBUG_INFO("Command completion failed out after %dms.\n", - 1000 * (HOST_COMPLETE_TIMEOUT / HZ)); - priv->fatal_error = IPW2100_ERR_MSG_TIMEOUT; - priv->status &= ~STATUS_CMD_ACTIVE; - schedule_reset(priv); - return -EIO; - } - - if (priv->fatal_error) { - printk(KERN_WARNING DRV_NAME ": %s: firmware fatal error\n", - priv->net_dev->name); - return -EIO; - } - - /* !!!!! HACK TEST !!!!! - * When lots of debug trace statements are enabled, the driver - * doesn't seem to have as many firmware restart cycles... - * - * As a test, we're sticking in a 1/100s delay here */ - schedule_timeout_uninterruptible(msecs_to_jiffies(10)); - - return 0; - - fail_unlock: - spin_unlock_irqrestore(&priv->low_lock, flags); - - return err; -} - -/* - * Verify the values and data access of the hardware - * No locks needed or used. No functions called. - */ -static int ipw2100_verify(struct ipw2100_priv *priv) -{ - u32 data1, data2; - u32 address; - - u32 val1 = 0x76543210; - u32 val2 = 0xFEDCBA98; - - /* Domain 0 check - all values should be DOA_DEBUG */ - for (address = IPW_REG_DOA_DEBUG_AREA_START; - address < IPW_REG_DOA_DEBUG_AREA_END; address += sizeof(u32)) { - read_register(priv->net_dev, address, &data1); - if (data1 != IPW_DATA_DOA_DEBUG_VALUE) - return -EIO; - } - - /* Domain 1 check - use arbitrary read/write compare */ - for (address = 0; address < 5; address++) { - /* The memory area is not used now */ - write_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x32, - val1); - write_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x36, - val2); - read_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x32, - &data1); - read_register(priv->net_dev, IPW_REG_DOMAIN_1_OFFSET + 0x36, - &data2); - if (val1 == data1 && val2 == data2) - return 0; - } - - return -EIO; -} - -/* - * - * Loop until the CARD_DISABLED bit is the same value as the - * supplied parameter - * - * TODO: See if it would be more efficient to do a wait/wake - * cycle and have the completion event trigger the wakeup - * - */ -#define IPW_CARD_DISABLE_COMPLETE_WAIT 100 // 100 milli -static int ipw2100_wait_for_card_state(struct ipw2100_priv *priv, int state) -{ - int i; - u32 card_state; - u32 len = sizeof(card_state); - int err; - - for (i = 0; i <= IPW_CARD_DISABLE_COMPLETE_WAIT * 1000; i += 50) { - err = ipw2100_get_ordinal(priv, IPW_ORD_CARD_DISABLED, - &card_state, &len); - if (err) { - IPW_DEBUG_INFO("Query of CARD_DISABLED ordinal " - "failed.\n"); - return 0; - } - - /* We'll break out if either the HW state says it is - * in the state we want, or if HOST_COMPLETE command - * finishes */ - if ((card_state == state) || - ((priv->status & STATUS_ENABLED) ? - IPW_HW_STATE_ENABLED : IPW_HW_STATE_DISABLED) == state) { - if (state == IPW_HW_STATE_ENABLED) - priv->status |= STATUS_ENABLED; - else - priv->status &= ~STATUS_ENABLED; - - return 0; - } - - udelay(50); - } - - IPW_DEBUG_INFO("ipw2100_wait_for_card_state to %s state timed out\n", - state ? "DISABLED" : "ENABLED"); - return -EIO; -} - -/********************************************************************* - Procedure : sw_reset_and_clock - Purpose : Asserts s/w reset, asserts clock initialization - and waits for clock stabilization - ********************************************************************/ -static int sw_reset_and_clock(struct ipw2100_priv *priv) -{ - int i; - u32 r; - - // assert s/w reset - write_register(priv->net_dev, IPW_REG_RESET_REG, - IPW_AUX_HOST_RESET_REG_SW_RESET); - - // wait for clock stabilization - for (i = 0; i < 1000; i++) { - udelay(IPW_WAIT_RESET_ARC_COMPLETE_DELAY); - - // check clock ready bit - read_register(priv->net_dev, IPW_REG_RESET_REG, &r); - if (r & IPW_AUX_HOST_RESET_REG_PRINCETON_RESET) - break; - } - - if (i == 1000) - return -EIO; // TODO: better error value - - /* set "initialization complete" bit to move adapter to - * D0 state */ - write_register(priv->net_dev, IPW_REG_GP_CNTRL, - IPW_AUX_HOST_GP_CNTRL_BIT_INIT_DONE); - - /* wait for clock stabilization */ - for (i = 0; i < 10000; i++) { - udelay(IPW_WAIT_CLOCK_STABILIZATION_DELAY * 4); - - /* check clock ready bit */ - read_register(priv->net_dev, IPW_REG_GP_CNTRL, &r); - if (r & IPW_AUX_HOST_GP_CNTRL_BIT_CLOCK_READY) - break; - } - - if (i == 10000) - return -EIO; /* TODO: better error value */ - - /* set D0 standby bit */ - read_register(priv->net_dev, IPW_REG_GP_CNTRL, &r); - write_register(priv->net_dev, IPW_REG_GP_CNTRL, - r | IPW_AUX_HOST_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY); - - return 0; -} - -/********************************************************************* - Procedure : ipw2100_download_firmware - Purpose : Initiaze adapter after power on. - The sequence is: - 1. assert s/w reset first! - 2. awake clocks & wait for clock stabilization - 3. hold ARC (don't ask me why...) - 4. load Dino ucode and reset/clock init again - 5. zero-out shared mem - 6. download f/w - *******************************************************************/ -static int ipw2100_download_firmware(struct ipw2100_priv *priv) -{ - u32 address; - int err; - -#ifndef CONFIG_PM - /* Fetch the firmware and microcode */ - struct ipw2100_fw ipw2100_firmware; -#endif - - if (priv->fatal_error) { - IPW_DEBUG_ERROR("%s: ipw2100_download_firmware called after " - "fatal error %d. Interface must be brought down.\n", - priv->net_dev->name, priv->fatal_error); - return -EINVAL; - } -#ifdef CONFIG_PM - if (!ipw2100_firmware.version) { - err = ipw2100_get_firmware(priv, &ipw2100_firmware); - if (err) { - IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n", - priv->net_dev->name, err); - priv->fatal_error = IPW2100_ERR_FW_LOAD; - goto fail; - } - } -#else - err = ipw2100_get_firmware(priv, &ipw2100_firmware); - if (err) { - IPW_DEBUG_ERROR("%s: ipw2100_get_firmware failed: %d\n", - priv->net_dev->name, err); - priv->fatal_error = IPW2100_ERR_FW_LOAD; - goto fail; - } -#endif - priv->firmware_version = ipw2100_firmware.version; - - /* s/w reset and clock stabilization */ - err = sw_reset_and_clock(priv); - if (err) { - IPW_DEBUG_ERROR("%s: sw_reset_and_clock failed: %d\n", - priv->net_dev->name, err); - goto fail; - } - - err = ipw2100_verify(priv); - if (err) { - IPW_DEBUG_ERROR("%s: ipw2100_verify failed: %d\n", - priv->net_dev->name, err); - goto fail; - } - - /* Hold ARC */ - write_nic_dword(priv->net_dev, - IPW_INTERNAL_REGISTER_HALT_AND_RESET, 0x80000000); - - /* allow ARC to run */ - write_register(priv->net_dev, IPW_REG_RESET_REG, 0); - - /* load microcode */ - err = ipw2100_ucode_download(priv, &ipw2100_firmware); - if (err) { - printk(KERN_ERR DRV_NAME ": %s: Error loading microcode: %d\n", - priv->net_dev->name, err); - goto fail; - } - - /* release ARC */ - write_nic_dword(priv->net_dev, - IPW_INTERNAL_REGISTER_HALT_AND_RESET, 0x00000000); - - /* s/w reset and clock stabilization (again!!!) */ - err = sw_reset_and_clock(priv); - if (err) { - printk(KERN_ERR DRV_NAME - ": %s: sw_reset_and_clock failed: %d\n", - priv->net_dev->name, err); - goto fail; - } - - /* load f/w */ - err = ipw2100_fw_download(priv, &ipw2100_firmware); - if (err) { - IPW_DEBUG_ERROR("%s: Error loading firmware: %d\n", - priv->net_dev->name, err); - goto fail; - } -#ifndef CONFIG_PM - /* - * When the .resume method of the driver is called, the other - * part of the system, i.e. the ide driver could still stay in - * the suspend stage. This prevents us from loading the firmware - * from the disk. --YZ - */ - - /* free any storage allocated for firmware image */ - ipw2100_release_firmware(priv, &ipw2100_firmware); -#endif - - /* zero out Domain 1 area indirectly (Si requirement) */ - for (address = IPW_HOST_FW_SHARED_AREA0; - address < IPW_HOST_FW_SHARED_AREA0_END; address += 4) - write_nic_dword(priv->net_dev, address, 0); - for (address = IPW_HOST_FW_SHARED_AREA1; - address < IPW_HOST_FW_SHARED_AREA1_END; address += 4) - write_nic_dword(priv->net_dev, address, 0); - for (address = IPW_HOST_FW_SHARED_AREA2; - address < IPW_HOST_FW_SHARED_AREA2_END; address += 4) - write_nic_dword(priv->net_dev, address, 0); - for (address = IPW_HOST_FW_SHARED_AREA3; - address < IPW_HOST_FW_SHARED_AREA3_END; address += 4) - write_nic_dword(priv->net_dev, address, 0); - for (address = IPW_HOST_FW_INTERRUPT_AREA; - address < IPW_HOST_FW_INTERRUPT_AREA_END; address += 4) - write_nic_dword(priv->net_dev, address, 0); - - return 0; - - fail: - ipw2100_release_firmware(priv, &ipw2100_firmware); - return err; -} - -static inline void ipw2100_enable_interrupts(struct ipw2100_priv *priv) -{ - if (priv->status & STATUS_INT_ENABLED) - return; - priv->status |= STATUS_INT_ENABLED; - write_register(priv->net_dev, IPW_REG_INTA_MASK, IPW_INTERRUPT_MASK); -} - -static inline void ipw2100_disable_interrupts(struct ipw2100_priv *priv) -{ - if (!(priv->status & STATUS_INT_ENABLED)) - return; - priv->status &= ~STATUS_INT_ENABLED; - write_register(priv->net_dev, IPW_REG_INTA_MASK, 0x0); -} - -static void ipw2100_initialize_ordinals(struct ipw2100_priv *priv) -{ - struct ipw2100_ordinals *ord = &priv->ordinals; - - IPW_DEBUG_INFO("enter\n"); - - read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1, - &ord->table1_addr); - - read_register(priv->net_dev, IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2, - &ord->table2_addr); - - read_nic_dword(priv->net_dev, ord->table1_addr, &ord->table1_size); - read_nic_dword(priv->net_dev, ord->table2_addr, &ord->table2_size); - - ord->table2_size &= 0x0000FFFF; - - IPW_DEBUG_INFO("table 1 size: %d\n", ord->table1_size); - IPW_DEBUG_INFO("table 2 size: %d\n", ord->table2_size); - IPW_DEBUG_INFO("exit\n"); -} - -static inline void ipw2100_hw_set_gpio(struct ipw2100_priv *priv) -{ - u32 reg = 0; - /* - * Set GPIO 3 writable by FW; GPIO 1 writable - * by driver and enable clock - */ - reg = (IPW_BIT_GPIO_GPIO3_MASK | IPW_BIT_GPIO_GPIO1_ENABLE | - IPW_BIT_GPIO_LED_OFF); - write_register(priv->net_dev, IPW_REG_GPIO, reg); -} - -static int rf_kill_active(struct ipw2100_priv *priv) -{ -#define MAX_RF_KILL_CHECKS 5 -#define RF_KILL_CHECK_DELAY 40 - - unsigned short value = 0; - u32 reg = 0; - int i; - - if (!(priv->hw_features & HW_FEATURE_RFKILL)) { - priv->status &= ~STATUS_RF_KILL_HW; - return 0; - } - - for (i = 0; i < MAX_RF_KILL_CHECKS; i++) { - udelay(RF_KILL_CHECK_DELAY); - read_register(priv->net_dev, IPW_REG_GPIO, ®); - value = (value << 1) | ((reg & IPW_BIT_GPIO_RF_KILL) ? 0 : 1); - } - - if (value == 0) - priv->status |= STATUS_RF_KILL_HW; - else - priv->status &= ~STATUS_RF_KILL_HW; - - return (value == 0); -} - -static int ipw2100_get_hw_features(struct ipw2100_priv *priv) -{ - u32 addr, len; - u32 val; - - /* - * EEPROM_SRAM_DB_START_ADDRESS using ordinal in ordinal table 1 - */ - len = sizeof(addr); - if (ipw2100_get_ordinal - (priv, IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, &addr, &len)) { - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - return -EIO; - } - - IPW_DEBUG_INFO("EEPROM address: %08X\n", addr); - - /* - * EEPROM version is the byte at offset 0xfd in firmware - * We read 4 bytes, then shift out the byte we actually want */ - read_nic_dword(priv->net_dev, addr + 0xFC, &val); - priv->eeprom_version = (val >> 24) & 0xFF; - IPW_DEBUG_INFO("EEPROM version: %d\n", priv->eeprom_version); - - /* - * HW RF Kill enable is bit 0 in byte at offset 0x21 in firmware - * - * notice that the EEPROM bit is reverse polarity, i.e. - * bit = 0 signifies HW RF kill switch is supported - * bit = 1 signifies HW RF kill switch is NOT supported - */ - read_nic_dword(priv->net_dev, addr + 0x20, &val); - if (!((val >> 24) & 0x01)) - priv->hw_features |= HW_FEATURE_RFKILL; - - IPW_DEBUG_INFO("HW RF Kill: %ssupported.\n", - (priv->hw_features & HW_FEATURE_RFKILL) ? "" : "not "); - - return 0; -} - -/* - * Start firmware execution after power on and intialization - * The sequence is: - * 1. Release ARC - * 2. Wait for f/w initialization completes; - */ -static int ipw2100_start_adapter(struct ipw2100_priv *priv) -{ - int i; - u32 inta, inta_mask, gpio; - - IPW_DEBUG_INFO("enter\n"); - - if (priv->status & STATUS_RUNNING) - return 0; - - /* - * Initialize the hw - drive adapter to DO state by setting - * init_done bit. Wait for clk_ready bit and Download - * fw & dino ucode - */ - if (ipw2100_download_firmware(priv)) { - printk(KERN_ERR DRV_NAME - ": %s: Failed to power on the adapter.\n", - priv->net_dev->name); - return -EIO; - } - - /* Clear the Tx, Rx and Msg queues and the r/w indexes - * in the firmware RBD and TBD ring queue */ - ipw2100_queues_initialize(priv); - - ipw2100_hw_set_gpio(priv); - - /* TODO -- Look at disabling interrupts here to make sure none - * get fired during FW initialization */ - - /* Release ARC - clear reset bit */ - write_register(priv->net_dev, IPW_REG_RESET_REG, 0); - - /* wait for f/w intialization complete */ - IPW_DEBUG_FW("Waiting for f/w initialization to complete...\n"); - i = 5000; - do { - schedule_timeout_uninterruptible(msecs_to_jiffies(40)); - /* Todo... wait for sync command ... */ - - read_register(priv->net_dev, IPW_REG_INTA, &inta); - - /* check "init done" bit */ - if (inta & IPW2100_INTA_FW_INIT_DONE) { - /* reset "init done" bit */ - write_register(priv->net_dev, IPW_REG_INTA, - IPW2100_INTA_FW_INIT_DONE); - break; - } - - /* check error conditions : we check these after the firmware - * check so that if there is an error, the interrupt handler - * will see it and the adapter will be reset */ - if (inta & - (IPW2100_INTA_FATAL_ERROR | IPW2100_INTA_PARITY_ERROR)) { - /* clear error conditions */ - write_register(priv->net_dev, IPW_REG_INTA, - IPW2100_INTA_FATAL_ERROR | - IPW2100_INTA_PARITY_ERROR); - } - } while (--i); - - /* Clear out any pending INTAs since we aren't supposed to have - * interrupts enabled at this point... */ - read_register(priv->net_dev, IPW_REG_INTA, &inta); - read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask); - inta &= IPW_INTERRUPT_MASK; - /* Clear out any pending interrupts */ - if (inta & inta_mask) - write_register(priv->net_dev, IPW_REG_INTA, inta); - - IPW_DEBUG_FW("f/w initialization complete: %s\n", - i ? "SUCCESS" : "FAILED"); - - if (!i) { - printk(KERN_WARNING DRV_NAME - ": %s: Firmware did not initialize.\n", - priv->net_dev->name); - return -EIO; - } - - /* allow firmware to write to GPIO1 & GPIO3 */ - read_register(priv->net_dev, IPW_REG_GPIO, &gpio); - - gpio |= (IPW_BIT_GPIO_GPIO1_MASK | IPW_BIT_GPIO_GPIO3_MASK); - - write_register(priv->net_dev, IPW_REG_GPIO, gpio); - - /* Ready to receive commands */ - priv->status |= STATUS_RUNNING; - - /* The adapter has been reset; we are not associated */ - priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED); - - IPW_DEBUG_INFO("exit\n"); - - return 0; -} - -static inline void ipw2100_reset_fatalerror(struct ipw2100_priv *priv) -{ - if (!priv->fatal_error) - return; - - priv->fatal_errors[priv->fatal_index++] = priv->fatal_error; - priv->fatal_index %= IPW2100_ERROR_QUEUE; - priv->fatal_error = 0; -} - -/* NOTE: Our interrupt is disabled when this method is called */ -static int ipw2100_power_cycle_adapter(struct ipw2100_priv *priv) -{ - u32 reg; - int i; - - IPW_DEBUG_INFO("Power cycling the hardware.\n"); - - ipw2100_hw_set_gpio(priv); - - /* Step 1. Stop Master Assert */ - write_register(priv->net_dev, IPW_REG_RESET_REG, - IPW_AUX_HOST_RESET_REG_STOP_MASTER); - - /* Step 2. Wait for stop Master Assert - * (not more than 50us, otherwise ret error */ - i = 5; - do { - udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY); - read_register(priv->net_dev, IPW_REG_RESET_REG, ®); - - if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) - break; - } while (--i); - - priv->status &= ~STATUS_RESET_PENDING; - - if (!i) { - IPW_DEBUG_INFO - ("exit - waited too long for master assert stop\n"); - return -EIO; - } - - write_register(priv->net_dev, IPW_REG_RESET_REG, - IPW_AUX_HOST_RESET_REG_SW_RESET); - - /* Reset any fatal_error conditions */ - ipw2100_reset_fatalerror(priv); - - /* At this point, the adapter is now stopped and disabled */ - priv->status &= ~(STATUS_RUNNING | STATUS_ASSOCIATING | - STATUS_ASSOCIATED | STATUS_ENABLED); - - return 0; -} - -/* - * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it - * - * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent. - * - * STATUS_CARD_DISABLE_NOTIFICATION will be sent regardless of - * if STATUS_ASSN_LOST is sent. - */ -static int ipw2100_hw_phy_off(struct ipw2100_priv *priv) -{ - -#define HW_PHY_OFF_LOOP_DELAY (HZ / 5000) - - struct host_command cmd = { - .host_command = CARD_DISABLE_PHY_OFF, - .host_command_sequence = 0, - .host_command_length = 0, - }; - int err, i; - u32 val1, val2; - - IPW_DEBUG_HC("CARD_DISABLE_PHY_OFF\n"); - - /* Turn off the radio */ - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - - for (i = 0; i < 2500; i++) { - read_nic_dword(priv->net_dev, IPW2100_CONTROL_REG, &val1); - read_nic_dword(priv->net_dev, IPW2100_COMMAND, &val2); - - if ((val1 & IPW2100_CONTROL_PHY_OFF) && - (val2 & IPW2100_COMMAND_PHY_OFF)) - return 0; - - schedule_timeout_uninterruptible(HW_PHY_OFF_LOOP_DELAY); - } - - return -EIO; -} - -static int ipw2100_enable_adapter(struct ipw2100_priv *priv) -{ - struct host_command cmd = { - .host_command = HOST_COMPLETE, - .host_command_sequence = 0, - .host_command_length = 0 - }; - int err = 0; - - IPW_DEBUG_HC("HOST_COMPLETE\n"); - - if (priv->status & STATUS_ENABLED) - return 0; - - mutex_lock(&priv->adapter_mutex); - - if (rf_kill_active(priv)) { - IPW_DEBUG_HC("Command aborted due to RF kill active.\n"); - goto fail_up; - } - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) { - IPW_DEBUG_INFO("Failed to send HOST_COMPLETE command\n"); - goto fail_up; - } - - err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_ENABLED); - if (err) { - IPW_DEBUG_INFO("%s: card not responding to init command.\n", - priv->net_dev->name); - goto fail_up; - } - - if (priv->stop_hang_check) { - priv->stop_hang_check = 0; - queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2); - } - - fail_up: - mutex_unlock(&priv->adapter_mutex); - return err; -} - -static int ipw2100_hw_stop_adapter(struct ipw2100_priv *priv) -{ -#define HW_POWER_DOWN_DELAY (msecs_to_jiffies(100)) - - struct host_command cmd = { - .host_command = HOST_PRE_POWER_DOWN, - .host_command_sequence = 0, - .host_command_length = 0, - }; - int err, i; - u32 reg; - - if (!(priv->status & STATUS_RUNNING)) - return 0; - - priv->status |= STATUS_STOPPING; - - /* We can only shut down the card if the firmware is operational. So, - * if we haven't reset since a fatal_error, then we can not send the - * shutdown commands. */ - if (!priv->fatal_error) { - /* First, make sure the adapter is enabled so that the PHY_OFF - * command can shut it down */ - ipw2100_enable_adapter(priv); - - err = ipw2100_hw_phy_off(priv); - if (err) - printk(KERN_WARNING DRV_NAME - ": Error disabling radio %d\n", err); - - /* - * If in D0-standby mode going directly to D3 may cause a - * PCI bus violation. Therefore we must change out of the D0 - * state. - * - * Sending the PREPARE_FOR_POWER_DOWN will restrict the - * hardware from going into standby mode and will transition - * out of D0-standby if it is already in that state. - * - * STATUS_PREPARE_POWER_DOWN_COMPLETE will be sent by the - * driver upon completion. Once received, the driver can - * proceed to the D3 state. - * - * Prepare for power down command to fw. This command would - * take HW out of D0-standby and prepare it for D3 state. - * - * Currently FW does not support event notification for this - * event. Therefore, skip waiting for it. Just wait a fixed - * 100ms - */ - IPW_DEBUG_HC("HOST_PRE_POWER_DOWN\n"); - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - printk(KERN_WARNING DRV_NAME ": " - "%s: Power down command failed: Error %d\n", - priv->net_dev->name, err); - else - schedule_timeout_uninterruptible(HW_POWER_DOWN_DELAY); - } - - priv->status &= ~STATUS_ENABLED; - - /* - * Set GPIO 3 writable by FW; GPIO 1 writable - * by driver and enable clock - */ - ipw2100_hw_set_gpio(priv); - - /* - * Power down adapter. Sequence: - * 1. Stop master assert (RESET_REG[9]=1) - * 2. Wait for stop master (RESET_REG[8]==1) - * 3. S/w reset assert (RESET_REG[7] = 1) - */ - - /* Stop master assert */ - write_register(priv->net_dev, IPW_REG_RESET_REG, - IPW_AUX_HOST_RESET_REG_STOP_MASTER); - - /* wait stop master not more than 50 usec. - * Otherwise return error. */ - for (i = 5; i > 0; i--) { - udelay(10); - - /* Check master stop bit */ - read_register(priv->net_dev, IPW_REG_RESET_REG, ®); - - if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) - break; - } - - if (i == 0) - printk(KERN_WARNING DRV_NAME - ": %s: Could now power down adapter.\n", - priv->net_dev->name); - - /* assert s/w reset */ - write_register(priv->net_dev, IPW_REG_RESET_REG, - IPW_AUX_HOST_RESET_REG_SW_RESET); - - priv->status &= ~(STATUS_RUNNING | STATUS_STOPPING); - - return 0; -} - -static int ipw2100_disable_adapter(struct ipw2100_priv *priv) -{ - struct host_command cmd = { - .host_command = CARD_DISABLE, - .host_command_sequence = 0, - .host_command_length = 0 - }; - int err = 0; - - IPW_DEBUG_HC("CARD_DISABLE\n"); - - if (!(priv->status & STATUS_ENABLED)) - return 0; - - /* Make sure we clear the associated state */ - priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); - - if (!priv->stop_hang_check) { - priv->stop_hang_check = 1; - cancel_delayed_work(&priv->hang_check); - } - - mutex_lock(&priv->adapter_mutex); - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) { - printk(KERN_WARNING DRV_NAME - ": exit - failed to send CARD_DISABLE command\n"); - goto fail_up; - } - - err = ipw2100_wait_for_card_state(priv, IPW_HW_STATE_DISABLED); - if (err) { - printk(KERN_WARNING DRV_NAME - ": exit - card failed to change to DISABLED\n"); - goto fail_up; - } - - IPW_DEBUG_INFO("TODO: implement scan state machine\n"); - - fail_up: - mutex_unlock(&priv->adapter_mutex); - return err; -} - -static int ipw2100_set_scan_options(struct ipw2100_priv *priv) -{ - struct host_command cmd = { - .host_command = SET_SCAN_OPTIONS, - .host_command_sequence = 0, - .host_command_length = 8 - }; - int err; - - IPW_DEBUG_INFO("enter\n"); - - IPW_DEBUG_SCAN("setting scan options\n"); - - cmd.host_command_parameters[0] = 0; - - if (!(priv->config & CFG_ASSOCIATE)) - cmd.host_command_parameters[0] |= IPW_SCAN_NOASSOCIATE; - if ((priv->ieee->sec.flags & SEC_ENABLED) && priv->ieee->sec.enabled) - cmd.host_command_parameters[0] |= IPW_SCAN_MIXED_CELL; - if (priv->config & CFG_PASSIVE_SCAN) - cmd.host_command_parameters[0] |= IPW_SCAN_PASSIVE; - - cmd.host_command_parameters[1] = priv->channel_mask; - - err = ipw2100_hw_send_command(priv, &cmd); - - IPW_DEBUG_HC("SET_SCAN_OPTIONS 0x%04X\n", - cmd.host_command_parameters[0]); - - return err; -} - -static int ipw2100_start_scan(struct ipw2100_priv *priv) -{ - struct host_command cmd = { - .host_command = BROADCAST_SCAN, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - IPW_DEBUG_HC("START_SCAN\n"); - - cmd.host_command_parameters[0] = 0; - - /* No scanning if in monitor mode */ - if (priv->ieee->iw_mode == IW_MODE_MONITOR) - return 1; - - if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_SCAN("Scan requested while already in scan...\n"); - return 0; - } - - IPW_DEBUG_INFO("enter\n"); - - /* Not clearing here; doing so makes iwlist always return nothing... - * - * We should modify the table logic to use aging tables vs. clearing - * the table on each scan start. - */ - IPW_DEBUG_SCAN("starting scan\n"); - - priv->status |= STATUS_SCANNING; - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - priv->status &= ~STATUS_SCANNING; - - IPW_DEBUG_INFO("exit\n"); - - return err; -} - -static const struct libipw_geo ipw_geos[] = { - { /* Restricted */ - "---", - .bg_channels = 14, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, {2467, 12}, - {2472, 13}, {2484, 14}}, - }, -}; - -static int ipw2100_up(struct ipw2100_priv *priv, int deferred) -{ - unsigned long flags; - int rc = 0; - u32 lock; - u32 ord_len = sizeof(lock); - - /* Age scan list entries found before suspend */ - if (priv->suspend_time) { - libipw_networks_age(priv->ieee, priv->suspend_time); - priv->suspend_time = 0; - } - - /* Quiet if manually disabled. */ - if (priv->status & STATUS_RF_KILL_SW) { - IPW_DEBUG_INFO("%s: Radio is disabled by Manual Disable " - "switch\n", priv->net_dev->name); - return 0; - } - - /* the ipw2100 hardware really doesn't want power management delays - * longer than 175usec - */ - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", 175); - - /* If the interrupt is enabled, turn it off... */ - spin_lock_irqsave(&priv->low_lock, flags); - ipw2100_disable_interrupts(priv); - - /* Reset any fatal_error conditions */ - ipw2100_reset_fatalerror(priv); - spin_unlock_irqrestore(&priv->low_lock, flags); - - if (priv->status & STATUS_POWERED || - (priv->status & STATUS_RESET_PENDING)) { - /* Power cycle the card ... */ - if (ipw2100_power_cycle_adapter(priv)) { - printk(KERN_WARNING DRV_NAME - ": %s: Could not cycle adapter.\n", - priv->net_dev->name); - rc = 1; - goto exit; - } - } else - priv->status |= STATUS_POWERED; - - /* Load the firmware, start the clocks, etc. */ - if (ipw2100_start_adapter(priv)) { - printk(KERN_ERR DRV_NAME - ": %s: Failed to start the firmware.\n", - priv->net_dev->name); - rc = 1; - goto exit; - } - - ipw2100_initialize_ordinals(priv); - - /* Determine capabilities of this particular HW configuration */ - if (ipw2100_get_hw_features(priv)) { - printk(KERN_ERR DRV_NAME - ": %s: Failed to determine HW features.\n", - priv->net_dev->name); - rc = 1; - goto exit; - } - - /* Initialize the geo */ - if (libipw_set_geo(priv->ieee, &ipw_geos[0])) { - printk(KERN_WARNING DRV_NAME "Could not set geo\n"); - return 0; - } - priv->ieee->freq_band = LIBIPW_24GHZ_BAND; - - lock = LOCK_NONE; - if (ipw2100_set_ordinal(priv, IPW_ORD_PERS_DB_LOCK, &lock, &ord_len)) { - printk(KERN_ERR DRV_NAME - ": %s: Failed to clear ordinal lock.\n", - priv->net_dev->name); - rc = 1; - goto exit; - } - - priv->status &= ~STATUS_SCANNING; - - if (rf_kill_active(priv)) { - printk(KERN_INFO "%s: Radio is disabled by RF switch.\n", - priv->net_dev->name); - - if (priv->stop_rf_kill) { - priv->stop_rf_kill = 0; - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies_relative(HZ)); - } - - deferred = 1; - } - - /* Turn on the interrupt so that commands can be processed */ - ipw2100_enable_interrupts(priv); - - /* Send all of the commands that must be sent prior to - * HOST_COMPLETE */ - if (ipw2100_adapter_setup(priv)) { - printk(KERN_ERR DRV_NAME ": %s: Failed to start the card.\n", - priv->net_dev->name); - rc = 1; - goto exit; - } - - if (!deferred) { - /* Enable the adapter - sends HOST_COMPLETE */ - if (ipw2100_enable_adapter(priv)) { - printk(KERN_ERR DRV_NAME ": " - "%s: failed in call to enable adapter.\n", - priv->net_dev->name); - ipw2100_hw_stop_adapter(priv); - rc = 1; - goto exit; - } - - /* Start a scan . . . */ - ipw2100_set_scan_options(priv); - ipw2100_start_scan(priv); - } - - exit: - return rc; -} - -/* Called by register_netdev() */ -static int ipw2100_net_init(struct net_device *dev) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - return ipw2100_up(priv, 1); -} - -static void ipw2100_down(struct ipw2100_priv *priv) -{ - unsigned long flags; - union iwreq_data wrqu = { - .ap_addr = { - .sa_family = ARPHRD_ETHER} - }; - int associated = priv->status & STATUS_ASSOCIATED; - - /* Kill the RF switch timer */ - if (!priv->stop_rf_kill) { - priv->stop_rf_kill = 1; - cancel_delayed_work(&priv->rf_kill); - } - - /* Kill the firmware hang check timer */ - if (!priv->stop_hang_check) { - priv->stop_hang_check = 1; - cancel_delayed_work(&priv->hang_check); - } - - /* Kill any pending resets */ - if (priv->status & STATUS_RESET_PENDING) - cancel_delayed_work(&priv->reset_work); - - /* Make sure the interrupt is on so that FW commands will be - * processed correctly */ - spin_lock_irqsave(&priv->low_lock, flags); - ipw2100_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->low_lock, flags); - - if (ipw2100_hw_stop_adapter(priv)) - printk(KERN_ERR DRV_NAME ": %s: Error stopping adapter.\n", - priv->net_dev->name); - - /* Do not disable the interrupt until _after_ we disable - * the adaptor. Otherwise the CARD_DISABLE command will never - * be ack'd by the firmware */ - spin_lock_irqsave(&priv->low_lock, flags); - ipw2100_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->low_lock, flags); - - pm_qos_update_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", - PM_QOS_DEFAULT_VALUE); - - /* We have to signal any supplicant if we are disassociating */ - if (associated) - wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); - - priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); - netif_carrier_off(priv->net_dev); - netif_stop_queue(priv->net_dev); -} - -static void ipw2100_reset_adapter(struct work_struct *work) -{ - struct ipw2100_priv *priv = - container_of(work, struct ipw2100_priv, reset_work.work); - unsigned long flags; - union iwreq_data wrqu = { - .ap_addr = { - .sa_family = ARPHRD_ETHER} - }; - int associated = priv->status & STATUS_ASSOCIATED; - - spin_lock_irqsave(&priv->low_lock, flags); - IPW_DEBUG_INFO(": %s: Restarting adapter.\n", priv->net_dev->name); - priv->resets++; - priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); - priv->status |= STATUS_SECURITY_UPDATED; - - /* Force a power cycle even if interface hasn't been opened - * yet */ - cancel_delayed_work(&priv->reset_work); - priv->status |= STATUS_RESET_PENDING; - spin_unlock_irqrestore(&priv->low_lock, flags); - - mutex_lock(&priv->action_mutex); - /* stop timed checks so that they don't interfere with reset */ - priv->stop_hang_check = 1; - cancel_delayed_work(&priv->hang_check); - - /* We have to signal any supplicant if we are disassociating */ - if (associated) - wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); - - ipw2100_up(priv, 0); - mutex_unlock(&priv->action_mutex); - -} - -static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) -{ - -#define MAC_ASSOCIATION_READ_DELAY (HZ) - int ret; - unsigned int len, essid_len; - char essid[IW_ESSID_MAX_SIZE]; - u32 txrate; - u32 chan; - char *txratename; - u8 bssid[ETH_ALEN]; - DECLARE_SSID_BUF(ssid); - - /* - * TBD: BSSID is usually 00:00:00:00:00:00 here and not - * an actual MAC of the AP. Seems like FW sets this - * address too late. Read it later and expose through - * /proc or schedule a later task to query and update - */ - - essid_len = IW_ESSID_MAX_SIZE; - ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID, - essid, &essid_len); - if (ret) { - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - return; - } - - len = sizeof(u32); - ret = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, &txrate, &len); - if (ret) { - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - return; - } - - len = sizeof(u32); - ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &len); - if (ret) { - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - return; - } - len = ETH_ALEN; - ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len); - if (ret) { - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - return; - } - memcpy(priv->ieee->bssid, bssid, ETH_ALEN); - - switch (txrate) { - case TX_RATE_1_MBIT: - txratename = "1Mbps"; - break; - case TX_RATE_2_MBIT: - txratename = "2Mbsp"; - break; - case TX_RATE_5_5_MBIT: - txratename = "5.5Mbps"; - break; - case TX_RATE_11_MBIT: - txratename = "11Mbps"; - break; - default: - IPW_DEBUG_INFO("Unknown rate: %d\n", txrate); - txratename = "unknown rate"; - break; - } - - IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n", - priv->net_dev->name, print_ssid(ssid, essid, essid_len), - txratename, chan, bssid); - - /* now we copy read ssid into dev */ - if (!(priv->config & CFG_STATIC_ESSID)) { - priv->essid_len = min((u8) essid_len, (u8) IW_ESSID_MAX_SIZE); - memcpy(priv->essid, essid, priv->essid_len); - } - priv->channel = chan; - memcpy(priv->bssid, bssid, ETH_ALEN); - - priv->status |= STATUS_ASSOCIATING; - priv->connect_start = get_seconds(); - - queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10); -} - -static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, - int length, int batch_mode) -{ - int ssid_len = min(length, IW_ESSID_MAX_SIZE); - struct host_command cmd = { - .host_command = SSID, - .host_command_sequence = 0, - .host_command_length = ssid_len - }; - int err; - DECLARE_SSID_BUF(ssid); - - IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len)); - - if (ssid_len) - memcpy(cmd.host_command_parameters, essid, ssid_len); - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - /* Bug in FW currently doesn't honor bit 0 in SET_SCAN_OPTIONS to - * disable auto association -- so we cheat by setting a bogus SSID */ - if (!ssid_len && !(priv->config & CFG_ASSOCIATE)) { - int i; - u8 *bogus = (u8 *) cmd.host_command_parameters; - for (i = 0; i < IW_ESSID_MAX_SIZE; i++) - bogus[i] = 0x18 + i; - cmd.host_command_length = IW_ESSID_MAX_SIZE; - } - - /* NOTE: We always send the SSID command even if the provided ESSID is - * the same as what we currently think is set. */ - - err = ipw2100_hw_send_command(priv, &cmd); - if (!err) { - memset(priv->essid + ssid_len, 0, IW_ESSID_MAX_SIZE - ssid_len); - memcpy(priv->essid, essid, ssid_len); - priv->essid_len = ssid_len; - } - - if (!batch_mode) { - if (ipw2100_enable_adapter(priv)) - err = -EIO; - } - - return err; -} - -static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) -{ - DECLARE_SSID_BUF(ssid); - - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, - "disassociated: '%s' %pM \n", - print_ssid(ssid, priv->essid, priv->essid_len), - priv->bssid); - - priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); - - if (priv->status & STATUS_STOPPING) { - IPW_DEBUG_INFO("Card is stopping itself, discard ASSN_LOST.\n"); - return; - } - - memset(priv->bssid, 0, ETH_ALEN); - memset(priv->ieee->bssid, 0, ETH_ALEN); - - netif_carrier_off(priv->net_dev); - netif_stop_queue(priv->net_dev); - - if (!(priv->status & STATUS_RUNNING)) - return; - - if (priv->status & STATUS_SECURITY_UPDATED) - queue_delayed_work(priv->workqueue, &priv->security_work, 0); - - queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0); -} - -static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) -{ - IPW_DEBUG_INFO("%s: RF Kill state changed to radio OFF.\n", - priv->net_dev->name); - - /* RF_KILL is now enabled (else we wouldn't be here) */ - priv->status |= STATUS_RF_KILL_HW; - - /* Make sure the RF Kill check timer is running */ - priv->stop_rf_kill = 0; - cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies_relative(HZ)); -} - -static void send_scan_event(void *data) -{ - struct ipw2100_priv *priv = data; - union iwreq_data wrqu; - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); -} - -static void ipw2100_scan_event_later(struct work_struct *work) -{ - send_scan_event(container_of(work, struct ipw2100_priv, - scan_event_later.work)); -} - -static void ipw2100_scan_event_now(struct work_struct *work) -{ - send_scan_event(container_of(work, struct ipw2100_priv, - scan_event_now)); -} - -static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) -{ - IPW_DEBUG_SCAN("scan complete\n"); - /* Age the scan results... */ - priv->ieee->scans++; - priv->status &= ~STATUS_SCANNING; - - /* Only userspace-requested scan completion events go out immediately */ - if (!priv->user_requested_scan) { - if (!delayed_work_pending(&priv->scan_event_later)) - queue_delayed_work(priv->workqueue, - &priv->scan_event_later, - round_jiffies_relative(msecs_to_jiffies(4000))); - } else { - priv->user_requested_scan = 0; - cancel_delayed_work(&priv->scan_event_later); - queue_work(priv->workqueue, &priv->scan_event_now); - } -} - -#ifdef CONFIG_IPW2100_DEBUG -#define IPW2100_HANDLER(v, f) { v, f, # v } -struct ipw2100_status_indicator { - int status; - void (*cb) (struct ipw2100_priv * priv, u32 status); - char *name; -}; -#else -#define IPW2100_HANDLER(v, f) { v, f } -struct ipw2100_status_indicator { - int status; - void (*cb) (struct ipw2100_priv * priv, u32 status); -}; -#endif /* CONFIG_IPW2100_DEBUG */ - -static void isr_indicate_scanning(struct ipw2100_priv *priv, u32 status) -{ - IPW_DEBUG_SCAN("Scanning...\n"); - priv->status |= STATUS_SCANNING; -} - -static const struct ipw2100_status_indicator status_handlers[] = { - IPW2100_HANDLER(IPW_STATE_INITIALIZED, NULL), - IPW2100_HANDLER(IPW_STATE_COUNTRY_FOUND, NULL), - IPW2100_HANDLER(IPW_STATE_ASSOCIATED, isr_indicate_associated), - IPW2100_HANDLER(IPW_STATE_ASSN_LOST, isr_indicate_association_lost), - IPW2100_HANDLER(IPW_STATE_ASSN_CHANGED, NULL), - IPW2100_HANDLER(IPW_STATE_SCAN_COMPLETE, isr_scan_complete), - IPW2100_HANDLER(IPW_STATE_ENTERED_PSP, NULL), - IPW2100_HANDLER(IPW_STATE_LEFT_PSP, NULL), - IPW2100_HANDLER(IPW_STATE_RF_KILL, isr_indicate_rf_kill), - IPW2100_HANDLER(IPW_STATE_DISABLED, NULL), - IPW2100_HANDLER(IPW_STATE_POWER_DOWN, NULL), - IPW2100_HANDLER(IPW_STATE_SCANNING, isr_indicate_scanning), - IPW2100_HANDLER(-1, NULL) -}; - -static void isr_status_change(struct ipw2100_priv *priv, int status) -{ - int i; - - if (status == IPW_STATE_SCANNING && - priv->status & STATUS_ASSOCIATED && - !(priv->status & STATUS_SCANNING)) { - IPW_DEBUG_INFO("Scan detected while associated, with " - "no scan request. Restarting firmware.\n"); - - /* Wake up any sleeping jobs */ - schedule_reset(priv); - } - - for (i = 0; status_handlers[i].status != -1; i++) { - if (status == status_handlers[i].status) { - IPW_DEBUG_NOTIF("Status change: %s\n", - status_handlers[i].name); - if (status_handlers[i].cb) - status_handlers[i].cb(priv, status); - priv->wstats.status = status; - return; - } - } - - IPW_DEBUG_NOTIF("unknown status received: %04x\n", status); -} - -static void isr_rx_complete_command(struct ipw2100_priv *priv, - struct ipw2100_cmd_header *cmd) -{ -#ifdef CONFIG_IPW2100_DEBUG - if (cmd->host_command_reg < ARRAY_SIZE(command_types)) { - IPW_DEBUG_HC("Command completed '%s (%d)'\n", - command_types[cmd->host_command_reg], - cmd->host_command_reg); - } -#endif - if (cmd->host_command_reg == HOST_COMPLETE) - priv->status |= STATUS_ENABLED; - - if (cmd->host_command_reg == CARD_DISABLE) - priv->status &= ~STATUS_ENABLED; - - priv->status &= ~STATUS_CMD_ACTIVE; - - wake_up_interruptible(&priv->wait_command_queue); -} - -#ifdef CONFIG_IPW2100_DEBUG -static const char *frame_types[] = { - "COMMAND_STATUS_VAL", - "STATUS_CHANGE_VAL", - "P80211_DATA_VAL", - "P8023_DATA_VAL", - "HOST_NOTIFICATION_VAL" -}; -#endif - -static int ipw2100_alloc_skb(struct ipw2100_priv *priv, - struct ipw2100_rx_packet *packet) -{ - packet->skb = dev_alloc_skb(sizeof(struct ipw2100_rx)); - if (!packet->skb) - return -ENOMEM; - - packet->rxp = (struct ipw2100_rx *)packet->skb->data; - packet->dma_addr = pci_map_single(priv->pci_dev, packet->skb->data, - sizeof(struct ipw2100_rx), - PCI_DMA_FROMDEVICE); - /* NOTE: pci_map_single does not return an error code, and 0 is a valid - * dma_addr */ - - return 0; -} - -#define SEARCH_ERROR 0xffffffff -#define SEARCH_FAIL 0xfffffffe -#define SEARCH_SUCCESS 0xfffffff0 -#define SEARCH_DISCARD 0 -#define SEARCH_SNAPSHOT 1 - -#define SNAPSHOT_ADDR(ofs) (priv->snapshot[((ofs) >> 12) & 0xff] + ((ofs) & 0xfff)) -static void ipw2100_snapshot_free(struct ipw2100_priv *priv) -{ - int i; - if (!priv->snapshot[0]) - return; - for (i = 0; i < 0x30; i++) - kfree(priv->snapshot[i]); - priv->snapshot[0] = NULL; -} - -#ifdef IPW2100_DEBUG_C3 -static int ipw2100_snapshot_alloc(struct ipw2100_priv *priv) -{ - int i; - if (priv->snapshot[0]) - return 1; - for (i = 0; i < 0x30; i++) { - priv->snapshot[i] = kmalloc(0x1000, GFP_ATOMIC); - if (!priv->snapshot[i]) { - IPW_DEBUG_INFO("%s: Error allocating snapshot " - "buffer %d\n", priv->net_dev->name, i); - while (i > 0) - kfree(priv->snapshot[--i]); - priv->snapshot[0] = NULL; - return 0; - } - } - - return 1; -} - -static u32 ipw2100_match_buf(struct ipw2100_priv *priv, u8 * in_buf, - size_t len, int mode) -{ - u32 i, j; - u32 tmp; - u8 *s, *d; - u32 ret; - - s = in_buf; - if (mode == SEARCH_SNAPSHOT) { - if (!ipw2100_snapshot_alloc(priv)) - mode = SEARCH_DISCARD; - } - - for (ret = SEARCH_FAIL, i = 0; i < 0x30000; i += 4) { - read_nic_dword(priv->net_dev, i, &tmp); - if (mode == SEARCH_SNAPSHOT) - *(u32 *) SNAPSHOT_ADDR(i) = tmp; - if (ret == SEARCH_FAIL) { - d = (u8 *) & tmp; - for (j = 0; j < 4; j++) { - if (*s != *d) { - s = in_buf; - continue; - } - - s++; - d++; - - if ((s - in_buf) == len) - ret = (i + j) - len + 1; - } - } else if (mode == SEARCH_DISCARD) - return ret; - } - - return ret; -} -#endif - -/* - * - * 0) Disconnect the SKB from the firmware (just unmap) - * 1) Pack the ETH header into the SKB - * 2) Pass the SKB to the network stack - * - * When packet is provided by the firmware, it contains the following: - * - * . libipw_hdr - * . libipw_snap_hdr - * - * The size of the constructed ethernet - * - */ -#ifdef IPW2100_RX_DEBUG -static u8 packet_data[IPW_RX_NIC_BUFFER_LENGTH]; -#endif - -static void ipw2100_corruption_detected(struct ipw2100_priv *priv, int i) -{ -#ifdef IPW2100_DEBUG_C3 - struct ipw2100_status *status = &priv->status_queue.drv[i]; - u32 match, reg; - int j; -#endif - - IPW_DEBUG_INFO(": PCI latency error detected at 0x%04zX.\n", - i * sizeof(struct ipw2100_status)); - -#ifdef IPW2100_DEBUG_C3 - /* Halt the firmware so we can get a good image */ - write_register(priv->net_dev, IPW_REG_RESET_REG, - IPW_AUX_HOST_RESET_REG_STOP_MASTER); - j = 5; - do { - udelay(IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY); - read_register(priv->net_dev, IPW_REG_RESET_REG, ®); - - if (reg & IPW_AUX_HOST_RESET_REG_MASTER_DISABLED) - break; - } while (j--); - - match = ipw2100_match_buf(priv, (u8 *) status, - sizeof(struct ipw2100_status), - SEARCH_SNAPSHOT); - if (match < SEARCH_SUCCESS) - IPW_DEBUG_INFO("%s: DMA status match in Firmware at " - "offset 0x%06X, length %d:\n", - priv->net_dev->name, match, - sizeof(struct ipw2100_status)); - else - IPW_DEBUG_INFO("%s: No DMA status match in " - "Firmware.\n", priv->net_dev->name); - - printk_buf((u8 *) priv->status_queue.drv, - sizeof(struct ipw2100_status) * RX_QUEUE_LENGTH); -#endif - - priv->fatal_error = IPW2100_ERR_C3_CORRUPTION; - priv->net_dev->stats.rx_errors++; - schedule_reset(priv); -} - -static void isr_rx(struct ipw2100_priv *priv, int i, - struct libipw_rx_stats *stats) -{ - struct net_device *dev = priv->net_dev; - struct ipw2100_status *status = &priv->status_queue.drv[i]; - struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; - - IPW_DEBUG_RX("Handler...\n"); - - if (unlikely(status->frame_size > skb_tailroom(packet->skb))) { - IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" - " Dropping.\n", - dev->name, - status->frame_size, skb_tailroom(packet->skb)); - dev->stats.rx_errors++; - return; - } - - if (unlikely(!netif_running(dev))) { - dev->stats.rx_errors++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); - return; - } - - if (unlikely(priv->ieee->iw_mode != IW_MODE_MONITOR && - !(priv->status & STATUS_ASSOCIATED))) { - IPW_DEBUG_DROP("Dropping packet while not associated.\n"); - priv->wstats.discard.misc++; - return; - } - - pci_unmap_single(priv->pci_dev, - packet->dma_addr, - sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE); - - skb_put(packet->skb, status->frame_size); - -#ifdef IPW2100_RX_DEBUG - /* Make a copy of the frame so we can dump it to the logs if - * libipw_rx fails */ - skb_copy_from_linear_data(packet->skb, packet_data, - min_t(u32, status->frame_size, - IPW_RX_NIC_BUFFER_LENGTH)); -#endif - - if (!libipw_rx(priv->ieee, packet->skb, stats)) { -#ifdef IPW2100_RX_DEBUG - IPW_DEBUG_DROP("%s: Non consumed packet:\n", - dev->name); - printk_buf(IPW_DL_DROP, packet_data, status->frame_size); -#endif - dev->stats.rx_errors++; - - /* libipw_rx failed, so it didn't free the SKB */ - dev_kfree_skb_any(packet->skb); - packet->skb = NULL; - } - - /* We need to allocate a new SKB and attach it to the RDB. */ - if (unlikely(ipw2100_alloc_skb(priv, packet))) { - printk(KERN_WARNING DRV_NAME ": " - "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", dev->name); - /* TODO: schedule adapter shutdown */ - IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); - } - - /* Update the RDB entry */ - priv->rx_queue.drv[i].host_addr = packet->dma_addr; -} - -#ifdef CONFIG_IPW2100_MONITOR - -static void isr_rx_monitor(struct ipw2100_priv *priv, int i, - struct libipw_rx_stats *stats) -{ - struct net_device *dev = priv->net_dev; - struct ipw2100_status *status = &priv->status_queue.drv[i]; - struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; - - /* Magic struct that slots into the radiotap header -- no reason - * to build this manually element by element, we can write it much - * more efficiently than we can parse it. ORDER MATTERS HERE */ - struct ipw_rt_hdr { - struct ieee80211_radiotap_header rt_hdr; - s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ - } *ipw_rt; - - IPW_DEBUG_RX("Handler...\n"); - - if (unlikely(status->frame_size > skb_tailroom(packet->skb) - - sizeof(struct ipw_rt_hdr))) { - IPW_DEBUG_INFO("%s: frame_size (%u) > skb_tailroom (%u)!" - " Dropping.\n", - dev->name, - status->frame_size, - skb_tailroom(packet->skb)); - dev->stats.rx_errors++; - return; - } - - if (unlikely(!netif_running(dev))) { - dev->stats.rx_errors++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); - return; - } - - if (unlikely(priv->config & CFG_CRC_CHECK && - status->flags & IPW_STATUS_FLAG_CRC_ERROR)) { - IPW_DEBUG_RX("CRC error in packet. Dropping.\n"); - dev->stats.rx_errors++; - return; - } - - pci_unmap_single(priv->pci_dev, packet->dma_addr, - sizeof(struct ipw2100_rx), PCI_DMA_FROMDEVICE); - memmove(packet->skb->data + sizeof(struct ipw_rt_hdr), - packet->skb->data, status->frame_size); - - ipw_rt = (struct ipw_rt_hdr *) packet->skb->data; - - ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct ipw_rt_hdr)); /* total hdr+data */ - - ipw_rt->rt_hdr.it_present = cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL); - - ipw_rt->rt_dbmsignal = status->rssi + IPW2100_RSSI_TO_DBM; - - skb_put(packet->skb, status->frame_size + sizeof(struct ipw_rt_hdr)); - - if (!libipw_rx(priv->ieee, packet->skb, stats)) { - dev->stats.rx_errors++; - - /* libipw_rx failed, so it didn't free the SKB */ - dev_kfree_skb_any(packet->skb); - packet->skb = NULL; - } - - /* We need to allocate a new SKB and attach it to the RDB. */ - if (unlikely(ipw2100_alloc_skb(priv, packet))) { - IPW_DEBUG_WARNING( - "%s: Unable to allocate SKB onto RBD ring - disabling " - "adapter.\n", dev->name); - /* TODO: schedule adapter shutdown */ - IPW_DEBUG_INFO("TODO: Shutdown adapter...\n"); - } - - /* Update the RDB entry */ - priv->rx_queue.drv[i].host_addr = packet->dma_addr; -} - -#endif - -static int ipw2100_corruption_check(struct ipw2100_priv *priv, int i) -{ - struct ipw2100_status *status = &priv->status_queue.drv[i]; - struct ipw2100_rx *u = priv->rx_buffers[i].rxp; - u16 frame_type = status->status_fields & STATUS_TYPE_MASK; - - switch (frame_type) { - case COMMAND_STATUS_VAL: - return (status->frame_size != sizeof(u->rx_data.command)); - case STATUS_CHANGE_VAL: - return (status->frame_size != sizeof(u->rx_data.status)); - case HOST_NOTIFICATION_VAL: - return (status->frame_size < sizeof(u->rx_data.notification)); - case P80211_DATA_VAL: - case P8023_DATA_VAL: -#ifdef CONFIG_IPW2100_MONITOR - return 0; -#else - switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) { - case IEEE80211_FTYPE_MGMT: - case IEEE80211_FTYPE_CTL: - return 0; - case IEEE80211_FTYPE_DATA: - return (status->frame_size > - IPW_MAX_802_11_PAYLOAD_LENGTH); - } -#endif - } - - return 1; -} - -/* - * ipw2100 interrupts are disabled at this point, and the ISR - * is the only code that calls this method. So, we do not need - * to play with any locks. - * - * RX Queue works as follows: - * - * Read index - firmware places packet in entry identified by the - * Read index and advances Read index. In this manner, - * Read index will always point to the next packet to - * be filled--but not yet valid. - * - * Write index - driver fills this entry with an unused RBD entry. - * This entry has not filled by the firmware yet. - * - * In between the W and R indexes are the RBDs that have been received - * but not yet processed. - * - * The process of handling packets will start at WRITE + 1 and advance - * until it reaches the READ index. - * - * The WRITE index is cached in the variable 'priv->rx_queue.next'. - * - */ -static void __ipw2100_rx_process(struct ipw2100_priv *priv) -{ - struct ipw2100_bd_queue *rxq = &priv->rx_queue; - struct ipw2100_status_queue *sq = &priv->status_queue; - struct ipw2100_rx_packet *packet; - u16 frame_type; - u32 r, w, i, s; - struct ipw2100_rx *u; - struct libipw_rx_stats stats = { - .mac_time = jiffies, - }; - - read_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_READ_INDEX, &r); - read_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_WRITE_INDEX, &w); - - if (r >= rxq->entries) { - IPW_DEBUG_RX("exit - bad read index\n"); - return; - } - - i = (rxq->next + 1) % rxq->entries; - s = i; - while (i != r) { - /* IPW_DEBUG_RX("r = %d : w = %d : processing = %d\n", - r, rxq->next, i); */ - - packet = &priv->rx_buffers[i]; - - /* Sync the DMA for the STATUS buffer so CPU is sure to get - * the correct values */ - pci_dma_sync_single_for_cpu(priv->pci_dev, - sq->nic + - sizeof(struct ipw2100_status) * i, - sizeof(struct ipw2100_status), - PCI_DMA_FROMDEVICE); - - /* Sync the DMA for the RX buffer so CPU is sure to get - * the correct values */ - pci_dma_sync_single_for_cpu(priv->pci_dev, packet->dma_addr, - sizeof(struct ipw2100_rx), - PCI_DMA_FROMDEVICE); - - if (unlikely(ipw2100_corruption_check(priv, i))) { - ipw2100_corruption_detected(priv, i); - goto increment; - } - - u = packet->rxp; - frame_type = sq->drv[i].status_fields & STATUS_TYPE_MASK; - stats.rssi = sq->drv[i].rssi + IPW2100_RSSI_TO_DBM; - stats.len = sq->drv[i].frame_size; - - stats.mask = 0; - if (stats.rssi != 0) - stats.mask |= LIBIPW_STATMASK_RSSI; - stats.freq = LIBIPW_24GHZ_BAND; - - IPW_DEBUG_RX("%s: '%s' frame type received (%d).\n", - priv->net_dev->name, frame_types[frame_type], - stats.len); - - switch (frame_type) { - case COMMAND_STATUS_VAL: - /* Reset Rx watchdog */ - isr_rx_complete_command(priv, &u->rx_data.command); - break; - - case STATUS_CHANGE_VAL: - isr_status_change(priv, u->rx_data.status); - break; - - case P80211_DATA_VAL: - case P8023_DATA_VAL: -#ifdef CONFIG_IPW2100_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - isr_rx_monitor(priv, i, &stats); - break; - } -#endif - if (stats.len < sizeof(struct libipw_hdr_3addr)) - break; - switch (WLAN_FC_GET_TYPE(le16_to_cpu(u->rx_data.header.frame_ctl))) { - case IEEE80211_FTYPE_MGMT: - libipw_rx_mgt(priv->ieee, - &u->rx_data.header, &stats); - break; - - case IEEE80211_FTYPE_CTL: - break; - - case IEEE80211_FTYPE_DATA: - isr_rx(priv, i, &stats); - break; - - } - break; - } - - increment: - /* clear status field associated with this RBD */ - rxq->drv[i].status.info.field = 0; - - i = (i + 1) % rxq->entries; - } - - if (i != s) { - /* backtrack one entry, wrapping to end if at 0 */ - rxq->next = (i ? i : rxq->entries) - 1; - - write_register(priv->net_dev, - IPW_MEM_HOST_SHARED_RX_WRITE_INDEX, rxq->next); - } -} - -/* - * __ipw2100_tx_process - * - * This routine will determine whether the next packet on - * the fw_pend_list has been processed by the firmware yet. - * - * If not, then it does nothing and returns. - * - * If so, then it removes the item from the fw_pend_list, frees - * any associated storage, and places the item back on the - * free list of its source (either msg_free_list or tx_free_list) - * - * TX Queue works as follows: - * - * Read index - points to the next TBD that the firmware will - * process. The firmware will read the data, and once - * done processing, it will advance the Read index. - * - * Write index - driver fills this entry with an constructed TBD - * entry. The Write index is not advanced until the - * packet has been configured. - * - * In between the W and R indexes are the TBDs that have NOT been - * processed. Lagging behind the R index are packets that have - * been processed but have not been freed by the driver. - * - * In order to free old storage, an internal index will be maintained - * that points to the next packet to be freed. When all used - * packets have been freed, the oldest index will be the same as the - * firmware's read index. - * - * The OLDEST index is cached in the variable 'priv->tx_queue.oldest' - * - * Because the TBD structure can not contain arbitrary data, the - * driver must keep an internal queue of cached allocations such that - * it can put that data back into the tx_free_list and msg_free_list - * for use by future command and data packets. - * - */ -static int __ipw2100_tx_process(struct ipw2100_priv *priv) -{ - struct ipw2100_bd_queue *txq = &priv->tx_queue; - struct ipw2100_bd *tbd; - struct list_head *element; - struct ipw2100_tx_packet *packet; - int descriptors_used; - int e, i; - u32 r, w, frag_num = 0; - - if (list_empty(&priv->fw_pend_list)) - return 0; - - element = priv->fw_pend_list.next; - - packet = list_entry(element, struct ipw2100_tx_packet, list); - tbd = &txq->drv[packet->index]; - - /* Determine how many TBD entries must be finished... */ - switch (packet->type) { - case COMMAND: - /* COMMAND uses only one slot; don't advance */ - descriptors_used = 1; - e = txq->oldest; - break; - - case DATA: - /* DATA uses two slots; advance and loop position. */ - descriptors_used = tbd->num_fragments; - frag_num = tbd->num_fragments - 1; - e = txq->oldest + frag_num; - e %= txq->entries; - break; - - default: - printk(KERN_WARNING DRV_NAME ": %s: Bad fw_pend_list entry!\n", - priv->net_dev->name); - return 0; - } - - /* if the last TBD is not done by NIC yet, then packet is - * not ready to be released. - * - */ - read_register(priv->net_dev, IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX, - &r); - read_register(priv->net_dev, IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX, - &w); - if (w != txq->next) - printk(KERN_WARNING DRV_NAME ": %s: write index mismatch\n", - priv->net_dev->name); - - /* - * txq->next is the index of the last packet written txq->oldest is - * the index of the r is the index of the next packet to be read by - * firmware - */ - - /* - * Quick graphic to help you visualize the following - * if / else statement - * - * ===>| s---->|=============== - * e>| - * | a | b | c | d | e | f | g | h | i | j | k | l - * r---->| - * w - * - * w - updated by driver - * r - updated by firmware - * s - start of oldest BD entry (txq->oldest) - * e - end of oldest BD entry - * - */ - if (!((r <= w && (e < r || e >= w)) || (e < r && e >= w))) { - IPW_DEBUG_TX("exit - no processed packets ready to release.\n"); - return 0; - } - - list_del(element); - DEC_STAT(&priv->fw_pend_stat); - -#ifdef CONFIG_IPW2100_DEBUG - { - i = txq->oldest; - IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, - &txq->drv[i], - (u32) (txq->nic + i * sizeof(struct ipw2100_bd)), - txq->drv[i].host_addr, txq->drv[i].buf_length); - - if (packet->type == DATA) { - i = (i + 1) % txq->entries; - - IPW_DEBUG_TX("TX%d V=%p P=%04X T=%04X L=%d\n", i, - &txq->drv[i], - (u32) (txq->nic + i * - sizeof(struct ipw2100_bd)), - (u32) txq->drv[i].host_addr, - txq->drv[i].buf_length); - } - } -#endif - - switch (packet->type) { - case DATA: - if (txq->drv[txq->oldest].status.info.fields.txType != 0) - printk(KERN_WARNING DRV_NAME ": %s: Queue mismatch. " - "Expecting DATA TBD but pulled " - "something else: ids %d=%d.\n", - priv->net_dev->name, txq->oldest, packet->index); - - /* DATA packet; we have to unmap and free the SKB */ - for (i = 0; i < frag_num; i++) { - tbd = &txq->drv[(packet->index + 1 + i) % txq->entries]; - - IPW_DEBUG_TX("TX%d P=%08x L=%d\n", - (packet->index + 1 + i) % txq->entries, - tbd->host_addr, tbd->buf_length); - - pci_unmap_single(priv->pci_dev, - tbd->host_addr, - tbd->buf_length, PCI_DMA_TODEVICE); - } - - libipw_txb_free(packet->info.d_struct.txb); - packet->info.d_struct.txb = NULL; - - list_add_tail(element, &priv->tx_free_list); - INC_STAT(&priv->tx_free_stat); - - /* We have a free slot in the Tx queue, so wake up the - * transmit layer if it is stopped. */ - if (priv->status & STATUS_ASSOCIATED) - netif_wake_queue(priv->net_dev); - - /* A packet was processed by the hardware, so update the - * watchdog */ - priv->net_dev->trans_start = jiffies; - - break; - - case COMMAND: - if (txq->drv[txq->oldest].status.info.fields.txType != 1) - printk(KERN_WARNING DRV_NAME ": %s: Queue mismatch. " - "Expecting COMMAND TBD but pulled " - "something else: ids %d=%d.\n", - priv->net_dev->name, txq->oldest, packet->index); - -#ifdef CONFIG_IPW2100_DEBUG - if (packet->info.c_struct.cmd->host_command_reg < - ARRAY_SIZE(command_types)) - IPW_DEBUG_TX("Command '%s (%d)' processed: %d.\n", - command_types[packet->info.c_struct.cmd-> - host_command_reg], - packet->info.c_struct.cmd-> - host_command_reg, - packet->info.c_struct.cmd->cmd_status_reg); -#endif - - list_add_tail(element, &priv->msg_free_list); - INC_STAT(&priv->msg_free_stat); - break; - } - - /* advance oldest used TBD pointer to start of next entry */ - txq->oldest = (e + 1) % txq->entries; - /* increase available TBDs number */ - txq->available += descriptors_used; - SET_STAT(&priv->txq_stat, txq->available); - - IPW_DEBUG_TX("packet latency (send to process) %ld jiffies\n", - jiffies - packet->jiffy_start); - - return (!list_empty(&priv->fw_pend_list)); -} - -static inline void __ipw2100_tx_complete(struct ipw2100_priv *priv) -{ - int i = 0; - - while (__ipw2100_tx_process(priv) && i < 200) - i++; - - if (i == 200) { - printk(KERN_WARNING DRV_NAME ": " - "%s: Driver is running slow (%d iters).\n", - priv->net_dev->name, i); - } -} - -static void ipw2100_tx_send_commands(struct ipw2100_priv *priv) -{ - struct list_head *element; - struct ipw2100_tx_packet *packet; - struct ipw2100_bd_queue *txq = &priv->tx_queue; - struct ipw2100_bd *tbd; - int next = txq->next; - - while (!list_empty(&priv->msg_pend_list)) { - /* if there isn't enough space in TBD queue, then - * don't stuff a new one in. - * NOTE: 3 are needed as a command will take one, - * and there is a minimum of 2 that must be - * maintained between the r and w indexes - */ - if (txq->available <= 3) { - IPW_DEBUG_TX("no room in tx_queue\n"); - break; - } - - element = priv->msg_pend_list.next; - list_del(element); - DEC_STAT(&priv->msg_pend_stat); - - packet = list_entry(element, struct ipw2100_tx_packet, list); - - IPW_DEBUG_TX("using TBD at virt=%p, phys=%p\n", - &txq->drv[txq->next], - (void *)(txq->nic + txq->next * - sizeof(struct ipw2100_bd))); - - packet->index = txq->next; - - tbd = &txq->drv[txq->next]; - - /* initialize TBD */ - tbd->host_addr = packet->info.c_struct.cmd_phys; - tbd->buf_length = sizeof(struct ipw2100_cmd_header); - /* not marking number of fragments causes problems - * with f/w debug version */ - tbd->num_fragments = 1; - tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_COMMAND | - IPW_BD_STATUS_TX_INTERRUPT_ENABLE; - - /* update TBD queue counters */ - txq->next++; - txq->next %= txq->entries; - txq->available--; - DEC_STAT(&priv->txq_stat); - - list_add_tail(element, &priv->fw_pend_list); - INC_STAT(&priv->fw_pend_stat); - } - - if (txq->next != next) { - /* kick off the DMA by notifying firmware the - * write index has moved; make sure TBD stores are sync'd */ - wmb(); - write_register(priv->net_dev, - IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX, - txq->next); - } -} - -/* - * ipw2100_tx_send_data - * - */ -static void ipw2100_tx_send_data(struct ipw2100_priv *priv) -{ - struct list_head *element; - struct ipw2100_tx_packet *packet; - struct ipw2100_bd_queue *txq = &priv->tx_queue; - struct ipw2100_bd *tbd; - int next = txq->next; - int i = 0; - struct ipw2100_data_header *ipw_hdr; - struct libipw_hdr_3addr *hdr; - - while (!list_empty(&priv->tx_pend_list)) { - /* if there isn't enough space in TBD queue, then - * don't stuff a new one in. - * NOTE: 4 are needed as a data will take two, - * and there is a minimum of 2 that must be - * maintained between the r and w indexes - */ - element = priv->tx_pend_list.next; - packet = list_entry(element, struct ipw2100_tx_packet, list); - - if (unlikely(1 + packet->info.d_struct.txb->nr_frags > - IPW_MAX_BDS)) { - /* TODO: Support merging buffers if more than - * IPW_MAX_BDS are used */ - IPW_DEBUG_INFO("%s: Maximum BD theshold exceeded. " - "Increase fragmentation level.\n", - priv->net_dev->name); - } - - if (txq->available <= 3 + packet->info.d_struct.txb->nr_frags) { - IPW_DEBUG_TX("no room in tx_queue\n"); - break; - } - - list_del(element); - DEC_STAT(&priv->tx_pend_stat); - - tbd = &txq->drv[txq->next]; - - packet->index = txq->next; - - ipw_hdr = packet->info.d_struct.data; - hdr = (struct libipw_hdr_3addr *)packet->info.d_struct.txb-> - fragments[0]->data; - - if (priv->ieee->iw_mode == IW_MODE_INFRA) { - /* To DS: Addr1 = BSSID, Addr2 = SA, - Addr3 = DA */ - memcpy(ipw_hdr->src_addr, hdr->addr2, ETH_ALEN); - memcpy(ipw_hdr->dst_addr, hdr->addr3, ETH_ALEN); - } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - /* not From/To DS: Addr1 = DA, Addr2 = SA, - Addr3 = BSSID */ - memcpy(ipw_hdr->src_addr, hdr->addr2, ETH_ALEN); - memcpy(ipw_hdr->dst_addr, hdr->addr1, ETH_ALEN); - } - - ipw_hdr->host_command_reg = SEND; - ipw_hdr->host_command_reg1 = 0; - - /* For now we only support host based encryption */ - ipw_hdr->needs_encryption = 0; - ipw_hdr->encrypted = packet->info.d_struct.txb->encrypted; - if (packet->info.d_struct.txb->nr_frags > 1) - ipw_hdr->fragment_size = - packet->info.d_struct.txb->frag_size - - LIBIPW_3ADDR_LEN; - else - ipw_hdr->fragment_size = 0; - - tbd->host_addr = packet->info.d_struct.data_phys; - tbd->buf_length = sizeof(struct ipw2100_data_header); - tbd->num_fragments = 1 + packet->info.d_struct.txb->nr_frags; - tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_802_3 | - IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT; - txq->next++; - txq->next %= txq->entries; - - IPW_DEBUG_TX("data header tbd TX%d P=%08x L=%d\n", - packet->index, tbd->host_addr, tbd->buf_length); -#ifdef CONFIG_IPW2100_DEBUG - if (packet->info.d_struct.txb->nr_frags > 1) - IPW_DEBUG_FRAG("fragment Tx: %d frames\n", - packet->info.d_struct.txb->nr_frags); -#endif - - for (i = 0; i < packet->info.d_struct.txb->nr_frags; i++) { - tbd = &txq->drv[txq->next]; - if (i == packet->info.d_struct.txb->nr_frags - 1) - tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_802_3 | - IPW_BD_STATUS_TX_INTERRUPT_ENABLE; - else - tbd->status.info.field = - IPW_BD_STATUS_TX_FRAME_802_3 | - IPW_BD_STATUS_TX_FRAME_NOT_LAST_FRAGMENT; - - tbd->buf_length = packet->info.d_struct.txb-> - fragments[i]->len - LIBIPW_3ADDR_LEN; - - tbd->host_addr = pci_map_single(priv->pci_dev, - packet->info.d_struct. - txb->fragments[i]-> - data + - LIBIPW_3ADDR_LEN, - tbd->buf_length, - PCI_DMA_TODEVICE); - - IPW_DEBUG_TX("data frag tbd TX%d P=%08x L=%d\n", - txq->next, tbd->host_addr, - tbd->buf_length); - - pci_dma_sync_single_for_device(priv->pci_dev, - tbd->host_addr, - tbd->buf_length, - PCI_DMA_TODEVICE); - - txq->next++; - txq->next %= txq->entries; - } - - txq->available -= 1 + packet->info.d_struct.txb->nr_frags; - SET_STAT(&priv->txq_stat, txq->available); - - list_add_tail(element, &priv->fw_pend_list); - INC_STAT(&priv->fw_pend_stat); - } - - if (txq->next != next) { - /* kick off the DMA by notifying firmware the - * write index has moved; make sure TBD stores are sync'd */ - write_register(priv->net_dev, - IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX, - txq->next); - } - return; -} - -static void ipw2100_irq_tasklet(struct ipw2100_priv *priv) -{ - struct net_device *dev = priv->net_dev; - unsigned long flags; - u32 inta, tmp; - - spin_lock_irqsave(&priv->low_lock, flags); - ipw2100_disable_interrupts(priv); - - read_register(dev, IPW_REG_INTA, &inta); - - IPW_DEBUG_ISR("enter - INTA: 0x%08lX\n", - (unsigned long)inta & IPW_INTERRUPT_MASK); - - priv->in_isr++; - priv->interrupts++; - - /* We do not loop and keep polling for more interrupts as this - * is frowned upon and doesn't play nicely with other potentially - * chained IRQs */ - IPW_DEBUG_ISR("INTA: 0x%08lX\n", - (unsigned long)inta & IPW_INTERRUPT_MASK); - - if (inta & IPW2100_INTA_FATAL_ERROR) { - printk(KERN_WARNING DRV_NAME - ": Fatal interrupt. Scheduling firmware restart.\n"); - priv->inta_other++; - write_register(dev, IPW_REG_INTA, IPW2100_INTA_FATAL_ERROR); - - read_nic_dword(dev, IPW_NIC_FATAL_ERROR, &priv->fatal_error); - IPW_DEBUG_INFO("%s: Fatal error value: 0x%08X\n", - priv->net_dev->name, priv->fatal_error); - - read_nic_dword(dev, IPW_ERROR_ADDR(priv->fatal_error), &tmp); - IPW_DEBUG_INFO("%s: Fatal error address value: 0x%08X\n", - priv->net_dev->name, tmp); - - /* Wake up any sleeping jobs */ - schedule_reset(priv); - } - - if (inta & IPW2100_INTA_PARITY_ERROR) { - printk(KERN_ERR DRV_NAME - ": ***** PARITY ERROR INTERRUPT !!!! \n"); - priv->inta_other++; - write_register(dev, IPW_REG_INTA, IPW2100_INTA_PARITY_ERROR); - } - - if (inta & IPW2100_INTA_RX_TRANSFER) { - IPW_DEBUG_ISR("RX interrupt\n"); - - priv->rx_interrupts++; - - write_register(dev, IPW_REG_INTA, IPW2100_INTA_RX_TRANSFER); - - __ipw2100_rx_process(priv); - __ipw2100_tx_complete(priv); - } - - if (inta & IPW2100_INTA_TX_TRANSFER) { - IPW_DEBUG_ISR("TX interrupt\n"); - - priv->tx_interrupts++; - - write_register(dev, IPW_REG_INTA, IPW2100_INTA_TX_TRANSFER); - - __ipw2100_tx_complete(priv); - ipw2100_tx_send_commands(priv); - ipw2100_tx_send_data(priv); - } - - if (inta & IPW2100_INTA_TX_COMPLETE) { - IPW_DEBUG_ISR("TX complete\n"); - priv->inta_other++; - write_register(dev, IPW_REG_INTA, IPW2100_INTA_TX_COMPLETE); - - __ipw2100_tx_complete(priv); - } - - if (inta & IPW2100_INTA_EVENT_INTERRUPT) { - /* ipw2100_handle_event(dev); */ - priv->inta_other++; - write_register(dev, IPW_REG_INTA, IPW2100_INTA_EVENT_INTERRUPT); - } - - if (inta & IPW2100_INTA_FW_INIT_DONE) { - IPW_DEBUG_ISR("FW init done interrupt\n"); - priv->inta_other++; - - read_register(dev, IPW_REG_INTA, &tmp); - if (tmp & (IPW2100_INTA_FATAL_ERROR | - IPW2100_INTA_PARITY_ERROR)) { - write_register(dev, IPW_REG_INTA, - IPW2100_INTA_FATAL_ERROR | - IPW2100_INTA_PARITY_ERROR); - } - - write_register(dev, IPW_REG_INTA, IPW2100_INTA_FW_INIT_DONE); - } - - if (inta & IPW2100_INTA_STATUS_CHANGE) { - IPW_DEBUG_ISR("Status change interrupt\n"); - priv->inta_other++; - write_register(dev, IPW_REG_INTA, IPW2100_INTA_STATUS_CHANGE); - } - - if (inta & IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE) { - IPW_DEBUG_ISR("slave host mode interrupt\n"); - priv->inta_other++; - write_register(dev, IPW_REG_INTA, - IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE); - } - - priv->in_isr--; - ipw2100_enable_interrupts(priv); - - spin_unlock_irqrestore(&priv->low_lock, flags); - - IPW_DEBUG_ISR("exit\n"); -} - -static irqreturn_t ipw2100_interrupt(int irq, void *data) -{ - struct ipw2100_priv *priv = data; - u32 inta, inta_mask; - - if (!data) - return IRQ_NONE; - - spin_lock(&priv->low_lock); - - /* We check to see if we should be ignoring interrupts before - * we touch the hardware. During ucode load if we try and handle - * an interrupt we can cause keyboard problems as well as cause - * the ucode to fail to initialize */ - if (!(priv->status & STATUS_INT_ENABLED)) { - /* Shared IRQ */ - goto none; - } - - read_register(priv->net_dev, IPW_REG_INTA_MASK, &inta_mask); - read_register(priv->net_dev, IPW_REG_INTA, &inta); - - if (inta == 0xFFFFFFFF) { - /* Hardware disappeared */ - printk(KERN_WARNING DRV_NAME ": IRQ INTA == 0xFFFFFFFF\n"); - goto none; - } - - inta &= IPW_INTERRUPT_MASK; - - if (!(inta & inta_mask)) { - /* Shared interrupt */ - goto none; - } - - /* We disable the hardware interrupt here just to prevent unneeded - * calls to be made. We disable this again within the actual - * work tasklet, so if another part of the code re-enables the - * interrupt, that is fine */ - ipw2100_disable_interrupts(priv); - - tasklet_schedule(&priv->irq_tasklet); - spin_unlock(&priv->low_lock); - - return IRQ_HANDLED; - none: - spin_unlock(&priv->low_lock); - return IRQ_NONE; -} - -static netdev_tx_t ipw2100_tx(struct libipw_txb *txb, - struct net_device *dev, int pri) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct list_head *element; - struct ipw2100_tx_packet *packet; - unsigned long flags; - - spin_lock_irqsave(&priv->low_lock, flags); - - if (!(priv->status & STATUS_ASSOCIATED)) { - IPW_DEBUG_INFO("Can not transmit when not connected.\n"); - priv->net_dev->stats.tx_carrier_errors++; - netif_stop_queue(dev); - goto fail_unlock; - } - - if (list_empty(&priv->tx_free_list)) - goto fail_unlock; - - element = priv->tx_free_list.next; - packet = list_entry(element, struct ipw2100_tx_packet, list); - - packet->info.d_struct.txb = txb; - - IPW_DEBUG_TX("Sending fragment (%d bytes):\n", txb->fragments[0]->len); - printk_buf(IPW_DL_TX, txb->fragments[0]->data, txb->fragments[0]->len); - - packet->jiffy_start = jiffies; - - list_del(element); - DEC_STAT(&priv->tx_free_stat); - - list_add_tail(element, &priv->tx_pend_list); - INC_STAT(&priv->tx_pend_stat); - - ipw2100_tx_send_data(priv); - - spin_unlock_irqrestore(&priv->low_lock, flags); - return NETDEV_TX_OK; - -fail_unlock: - netif_stop_queue(dev); - spin_unlock_irqrestore(&priv->low_lock, flags); - return NETDEV_TX_BUSY; -} - -static int ipw2100_msg_allocate(struct ipw2100_priv *priv) -{ - int i, j, err = -EINVAL; - void *v; - dma_addr_t p; - - priv->msg_buffers = - (struct ipw2100_tx_packet *)kmalloc(IPW_COMMAND_POOL_SIZE * - sizeof(struct - ipw2100_tx_packet), - GFP_KERNEL); - if (!priv->msg_buffers) { - printk(KERN_ERR DRV_NAME ": %s: PCI alloc failed for msg " - "buffers.\n", priv->net_dev->name); - return -ENOMEM; - } - - for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) { - v = pci_alloc_consistent(priv->pci_dev, - sizeof(struct ipw2100_cmd_header), &p); - if (!v) { - printk(KERN_ERR DRV_NAME ": " - "%s: PCI alloc failed for msg " - "buffers.\n", priv->net_dev->name); - err = -ENOMEM; - break; - } - - memset(v, 0, sizeof(struct ipw2100_cmd_header)); - - priv->msg_buffers[i].type = COMMAND; - priv->msg_buffers[i].info.c_struct.cmd = - (struct ipw2100_cmd_header *)v; - priv->msg_buffers[i].info.c_struct.cmd_phys = p; - } - - if (i == IPW_COMMAND_POOL_SIZE) - return 0; - - for (j = 0; j < i; j++) { - pci_free_consistent(priv->pci_dev, - sizeof(struct ipw2100_cmd_header), - priv->msg_buffers[j].info.c_struct.cmd, - priv->msg_buffers[j].info.c_struct. - cmd_phys); - } - - kfree(priv->msg_buffers); - priv->msg_buffers = NULL; - - return err; -} - -static int ipw2100_msg_initialize(struct ipw2100_priv *priv) -{ - int i; - - INIT_LIST_HEAD(&priv->msg_free_list); - INIT_LIST_HEAD(&priv->msg_pend_list); - - for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) - list_add_tail(&priv->msg_buffers[i].list, &priv->msg_free_list); - SET_STAT(&priv->msg_free_stat, i); - - return 0; -} - -static void ipw2100_msg_free(struct ipw2100_priv *priv) -{ - int i; - - if (!priv->msg_buffers) - return; - - for (i = 0; i < IPW_COMMAND_POOL_SIZE; i++) { - pci_free_consistent(priv->pci_dev, - sizeof(struct ipw2100_cmd_header), - priv->msg_buffers[i].info.c_struct.cmd, - priv->msg_buffers[i].info.c_struct. - cmd_phys); - } - - kfree(priv->msg_buffers); - priv->msg_buffers = NULL; -} - -static ssize_t show_pci(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct pci_dev *pci_dev = container_of(d, struct pci_dev, dev); - char *out = buf; - int i, j; - u32 val; - - for (i = 0; i < 16; i++) { - out += sprintf(out, "[%08X] ", i * 16); - for (j = 0; j < 16; j += 4) { - pci_read_config_dword(pci_dev, i * 16 + j, &val); - out += sprintf(out, "%08X ", val); - } - out += sprintf(out, "\n"); - } - - return out - buf; -} - -static DEVICE_ATTR(pci, S_IRUGO, show_pci, NULL); - -static ssize_t show_cfg(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *p = dev_get_drvdata(d); - return sprintf(buf, "0x%08x\n", (int)p->config); -} - -static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); - -static ssize_t show_status(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *p = dev_get_drvdata(d); - return sprintf(buf, "0x%08x\n", (int)p->status); -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - -static ssize_t show_capability(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *p = dev_get_drvdata(d); - return sprintf(buf, "0x%08x\n", (int)p->capability); -} - -static DEVICE_ATTR(capability, S_IRUGO, show_capability, NULL); - -#define IPW2100_REG(x) { IPW_ ##x, #x } -static const struct { - u32 addr; - const char *name; -} hw_data[] = { -IPW2100_REG(REG_GP_CNTRL), - IPW2100_REG(REG_GPIO), - IPW2100_REG(REG_INTA), - IPW2100_REG(REG_INTA_MASK), IPW2100_REG(REG_RESET_REG),}; -#define IPW2100_NIC(x, s) { x, #x, s } -static const struct { - u32 addr; - const char *name; - size_t size; -} nic_data[] = { -IPW2100_NIC(IPW2100_CONTROL_REG, 2), - IPW2100_NIC(0x210014, 1), IPW2100_NIC(0x210000, 1),}; -#define IPW2100_ORD(x, d) { IPW_ORD_ ##x, #x, d } -static const struct { - u8 index; - const char *name; - const char *desc; -} ord_data[] = { -IPW2100_ORD(STAT_TX_HOST_REQUESTS, "requested Host Tx's (MSDU)"), - IPW2100_ORD(STAT_TX_HOST_COMPLETE, - "successful Host Tx's (MSDU)"), - IPW2100_ORD(STAT_TX_DIR_DATA, - "successful Directed Tx's (MSDU)"), - IPW2100_ORD(STAT_TX_DIR_DATA1, - "successful Directed Tx's (MSDU) @ 1MB"), - IPW2100_ORD(STAT_TX_DIR_DATA2, - "successful Directed Tx's (MSDU) @ 2MB"), - IPW2100_ORD(STAT_TX_DIR_DATA5_5, - "successful Directed Tx's (MSDU) @ 5_5MB"), - IPW2100_ORD(STAT_TX_DIR_DATA11, - "successful Directed Tx's (MSDU) @ 11MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA1, - "successful Non_Directed Tx's (MSDU) @ 1MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA2, - "successful Non_Directed Tx's (MSDU) @ 2MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA5_5, - "successful Non_Directed Tx's (MSDU) @ 5.5MB"), - IPW2100_ORD(STAT_TX_NODIR_DATA11, - "successful Non_Directed Tx's (MSDU) @ 11MB"), - IPW2100_ORD(STAT_NULL_DATA, "successful NULL data Tx's"), - IPW2100_ORD(STAT_TX_RTS, "successful Tx RTS"), - IPW2100_ORD(STAT_TX_CTS, "successful Tx CTS"), - IPW2100_ORD(STAT_TX_ACK, "successful Tx ACK"), - IPW2100_ORD(STAT_TX_ASSN, "successful Association Tx's"), - IPW2100_ORD(STAT_TX_ASSN_RESP, - "successful Association response Tx's"), - IPW2100_ORD(STAT_TX_REASSN, - "successful Reassociation Tx's"), - IPW2100_ORD(STAT_TX_REASSN_RESP, - "successful Reassociation response Tx's"), - IPW2100_ORD(STAT_TX_PROBE, - "probes successfully transmitted"), - IPW2100_ORD(STAT_TX_PROBE_RESP, - "probe responses successfully transmitted"), - IPW2100_ORD(STAT_TX_BEACON, "tx beacon"), - IPW2100_ORD(STAT_TX_ATIM, "Tx ATIM"), - IPW2100_ORD(STAT_TX_DISASSN, - "successful Disassociation TX"), - IPW2100_ORD(STAT_TX_AUTH, "successful Authentication Tx"), - IPW2100_ORD(STAT_TX_DEAUTH, - "successful Deauthentication TX"), - IPW2100_ORD(STAT_TX_TOTAL_BYTES, - "Total successful Tx data bytes"), - IPW2100_ORD(STAT_TX_RETRIES, "Tx retries"), - IPW2100_ORD(STAT_TX_RETRY1, "Tx retries at 1MBPS"), - IPW2100_ORD(STAT_TX_RETRY2, "Tx retries at 2MBPS"), - IPW2100_ORD(STAT_TX_RETRY5_5, "Tx retries at 5.5MBPS"), - IPW2100_ORD(STAT_TX_RETRY11, "Tx retries at 11MBPS"), - IPW2100_ORD(STAT_TX_FAILURES, "Tx Failures"), - IPW2100_ORD(STAT_TX_MAX_TRIES_IN_HOP, - "times max tries in a hop failed"), - IPW2100_ORD(STAT_TX_DISASSN_FAIL, - "times disassociation failed"), - IPW2100_ORD(STAT_TX_ERR_CTS, "missed/bad CTS frames"), - IPW2100_ORD(STAT_TX_ERR_ACK, "tx err due to acks"), - IPW2100_ORD(STAT_RX_HOST, "packets passed to host"), - IPW2100_ORD(STAT_RX_DIR_DATA, "directed packets"), - IPW2100_ORD(STAT_RX_DIR_DATA1, "directed packets at 1MB"), - IPW2100_ORD(STAT_RX_DIR_DATA2, "directed packets at 2MB"), - IPW2100_ORD(STAT_RX_DIR_DATA5_5, - "directed packets at 5.5MB"), - IPW2100_ORD(STAT_RX_DIR_DATA11, "directed packets at 11MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA, "nondirected packets"), - IPW2100_ORD(STAT_RX_NODIR_DATA1, - "nondirected packets at 1MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA2, - "nondirected packets at 2MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA5_5, - "nondirected packets at 5.5MB"), - IPW2100_ORD(STAT_RX_NODIR_DATA11, - "nondirected packets at 11MB"), - IPW2100_ORD(STAT_RX_NULL_DATA, "null data rx's"), - IPW2100_ORD(STAT_RX_RTS, "Rx RTS"), IPW2100_ORD(STAT_RX_CTS, - "Rx CTS"), - IPW2100_ORD(STAT_RX_ACK, "Rx ACK"), - IPW2100_ORD(STAT_RX_CFEND, "Rx CF End"), - IPW2100_ORD(STAT_RX_CFEND_ACK, "Rx CF End + CF Ack"), - IPW2100_ORD(STAT_RX_ASSN, "Association Rx's"), - IPW2100_ORD(STAT_RX_ASSN_RESP, "Association response Rx's"), - IPW2100_ORD(STAT_RX_REASSN, "Reassociation Rx's"), - IPW2100_ORD(STAT_RX_REASSN_RESP, - "Reassociation response Rx's"), - IPW2100_ORD(STAT_RX_PROBE, "probe Rx's"), - IPW2100_ORD(STAT_RX_PROBE_RESP, "probe response Rx's"), - IPW2100_ORD(STAT_RX_BEACON, "Rx beacon"), - IPW2100_ORD(STAT_RX_ATIM, "Rx ATIM"), - IPW2100_ORD(STAT_RX_DISASSN, "disassociation Rx"), - IPW2100_ORD(STAT_RX_AUTH, "authentication Rx"), - IPW2100_ORD(STAT_RX_DEAUTH, "deauthentication Rx"), - IPW2100_ORD(STAT_RX_TOTAL_BYTES, - "Total rx data bytes received"), - IPW2100_ORD(STAT_RX_ERR_CRC, "packets with Rx CRC error"), - IPW2100_ORD(STAT_RX_ERR_CRC1, "Rx CRC errors at 1MB"), - IPW2100_ORD(STAT_RX_ERR_CRC2, "Rx CRC errors at 2MB"), - IPW2100_ORD(STAT_RX_ERR_CRC5_5, "Rx CRC errors at 5.5MB"), - IPW2100_ORD(STAT_RX_ERR_CRC11, "Rx CRC errors at 11MB"), - IPW2100_ORD(STAT_RX_DUPLICATE1, - "duplicate rx packets at 1MB"), - IPW2100_ORD(STAT_RX_DUPLICATE2, - "duplicate rx packets at 2MB"), - IPW2100_ORD(STAT_RX_DUPLICATE5_5, - "duplicate rx packets at 5.5MB"), - IPW2100_ORD(STAT_RX_DUPLICATE11, - "duplicate rx packets at 11MB"), - IPW2100_ORD(STAT_RX_DUPLICATE, "duplicate rx packets"), - IPW2100_ORD(PERS_DB_LOCK, "locking fw permanent db"), - IPW2100_ORD(PERS_DB_SIZE, "size of fw permanent db"), - IPW2100_ORD(PERS_DB_ADDR, "address of fw permanent db"), - IPW2100_ORD(STAT_RX_INVALID_PROTOCOL, - "rx frames with invalid protocol"), - IPW2100_ORD(SYS_BOOT_TIME, "Boot time"), - IPW2100_ORD(STAT_RX_NO_BUFFER, - "rx frames rejected due to no buffer"), - IPW2100_ORD(STAT_RX_MISSING_FRAG, - "rx frames dropped due to missing fragment"), - IPW2100_ORD(STAT_RX_ORPHAN_FRAG, - "rx frames dropped due to non-sequential fragment"), - IPW2100_ORD(STAT_RX_ORPHAN_FRAME, - "rx frames dropped due to unmatched 1st frame"), - IPW2100_ORD(STAT_RX_FRAG_AGEOUT, - "rx frames dropped due to uncompleted frame"), - IPW2100_ORD(STAT_RX_ICV_ERRORS, - "ICV errors during decryption"), - IPW2100_ORD(STAT_PSP_SUSPENSION, "times adapter suspended"), - IPW2100_ORD(STAT_PSP_BCN_TIMEOUT, "beacon timeout"), - IPW2100_ORD(STAT_PSP_POLL_TIMEOUT, - "poll response timeouts"), - IPW2100_ORD(STAT_PSP_NONDIR_TIMEOUT, - "timeouts waiting for last {broad,multi}cast pkt"), - IPW2100_ORD(STAT_PSP_RX_DTIMS, "PSP DTIMs received"), - IPW2100_ORD(STAT_PSP_RX_TIMS, "PSP TIMs received"), - IPW2100_ORD(STAT_PSP_STATION_ID, "PSP Station ID"), - IPW2100_ORD(LAST_ASSN_TIME, "RTC time of last association"), - IPW2100_ORD(STAT_PERCENT_MISSED_BCNS, - "current calculation of % missed beacons"), - IPW2100_ORD(STAT_PERCENT_RETRIES, - "current calculation of % missed tx retries"), - IPW2100_ORD(ASSOCIATED_AP_PTR, - "0 if not associated, else pointer to AP table entry"), - IPW2100_ORD(AVAILABLE_AP_CNT, - "AP's decsribed in the AP table"), - IPW2100_ORD(AP_LIST_PTR, "Ptr to list of available APs"), - IPW2100_ORD(STAT_AP_ASSNS, "associations"), - IPW2100_ORD(STAT_ASSN_FAIL, "association failures"), - IPW2100_ORD(STAT_ASSN_RESP_FAIL, - "failures due to response fail"), - IPW2100_ORD(STAT_FULL_SCANS, "full scans"), - IPW2100_ORD(CARD_DISABLED, "Card Disabled"), - IPW2100_ORD(STAT_ROAM_INHIBIT, - "times roaming was inhibited due to activity"), - IPW2100_ORD(RSSI_AT_ASSN, - "RSSI of associated AP at time of association"), - IPW2100_ORD(STAT_ASSN_CAUSE1, - "reassociation: no probe response or TX on hop"), - IPW2100_ORD(STAT_ASSN_CAUSE2, - "reassociation: poor tx/rx quality"), - IPW2100_ORD(STAT_ASSN_CAUSE3, - "reassociation: tx/rx quality (excessive AP load"), - IPW2100_ORD(STAT_ASSN_CAUSE4, - "reassociation: AP RSSI level"), - IPW2100_ORD(STAT_ASSN_CAUSE5, - "reassociations due to load leveling"), - IPW2100_ORD(STAT_AUTH_FAIL, "times authentication failed"), - IPW2100_ORD(STAT_AUTH_RESP_FAIL, - "times authentication response failed"), - IPW2100_ORD(STATION_TABLE_CNT, - "entries in association table"), - IPW2100_ORD(RSSI_AVG_CURR, "Current avg RSSI"), - IPW2100_ORD(POWER_MGMT_MODE, "Power mode - 0=CAM, 1=PSP"), - IPW2100_ORD(COUNTRY_CODE, - "IEEE country code as recv'd from beacon"), - IPW2100_ORD(COUNTRY_CHANNELS, - "channels suported by country"), - IPW2100_ORD(RESET_CNT, "adapter resets (warm)"), - IPW2100_ORD(BEACON_INTERVAL, "Beacon interval"), - IPW2100_ORD(ANTENNA_DIVERSITY, - "TRUE if antenna diversity is disabled"), - IPW2100_ORD(DTIM_PERIOD, "beacon intervals between DTIMs"), - IPW2100_ORD(OUR_FREQ, - "current radio freq lower digits - channel ID"), - IPW2100_ORD(RTC_TIME, "current RTC time"), - IPW2100_ORD(PORT_TYPE, "operating mode"), - IPW2100_ORD(CURRENT_TX_RATE, "current tx rate"), - IPW2100_ORD(SUPPORTED_RATES, "supported tx rates"), - IPW2100_ORD(ATIM_WINDOW, "current ATIM Window"), - IPW2100_ORD(BASIC_RATES, "basic tx rates"), - IPW2100_ORD(NIC_HIGHEST_RATE, "NIC highest tx rate"), - IPW2100_ORD(AP_HIGHEST_RATE, "AP highest tx rate"), - IPW2100_ORD(CAPABILITIES, - "Management frame capability field"), - IPW2100_ORD(AUTH_TYPE, "Type of authentication"), - IPW2100_ORD(RADIO_TYPE, "Adapter card platform type"), - IPW2100_ORD(RTS_THRESHOLD, - "Min packet length for RTS handshaking"), - IPW2100_ORD(INT_MODE, "International mode"), - IPW2100_ORD(FRAGMENTATION_THRESHOLD, - "protocol frag threshold"), - IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_START_ADDRESS, - "EEPROM offset in SRAM"), - IPW2100_ORD(EEPROM_SRAM_DB_BLOCK_SIZE, - "EEPROM size in SRAM"), - IPW2100_ORD(EEPROM_SKU_CAPABILITY, "EEPROM SKU Capability"), - IPW2100_ORD(EEPROM_IBSS_11B_CHANNELS, - "EEPROM IBSS 11b channel set"), - IPW2100_ORD(MAC_VERSION, "MAC Version"), - IPW2100_ORD(MAC_REVISION, "MAC Revision"), - IPW2100_ORD(RADIO_VERSION, "Radio Version"), - IPW2100_ORD(NIC_MANF_DATE_TIME, "MANF Date/Time STAMP"), - IPW2100_ORD(UCODE_VERSION, "Ucode Version"),}; - -static ssize_t show_registers(struct device *d, struct device_attribute *attr, - char *buf) -{ - int i; - struct ipw2100_priv *priv = dev_get_drvdata(d); - struct net_device *dev = priv->net_dev; - char *out = buf; - u32 val = 0; - - out += sprintf(out, "%30s [Address ] : Hex\n", "Register"); - - for (i = 0; i < ARRAY_SIZE(hw_data); i++) { - read_register(dev, hw_data[i].addr, &val); - out += sprintf(out, "%30s [%08X] : %08X\n", - hw_data[i].name, hw_data[i].addr, val); - } - - return out - buf; -} - -static DEVICE_ATTR(registers, S_IRUGO, show_registers, NULL); - -static ssize_t show_hardware(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - struct net_device *dev = priv->net_dev; - char *out = buf; - int i; - - out += sprintf(out, "%30s [Address ] : Hex\n", "NIC entry"); - - for (i = 0; i < ARRAY_SIZE(nic_data); i++) { - u8 tmp8; - u16 tmp16; - u32 tmp32; - - switch (nic_data[i].size) { - case 1: - read_nic_byte(dev, nic_data[i].addr, &tmp8); - out += sprintf(out, "%30s [%08X] : %02X\n", - nic_data[i].name, nic_data[i].addr, - tmp8); - break; - case 2: - read_nic_word(dev, nic_data[i].addr, &tmp16); - out += sprintf(out, "%30s [%08X] : %04X\n", - nic_data[i].name, nic_data[i].addr, - tmp16); - break; - case 4: - read_nic_dword(dev, nic_data[i].addr, &tmp32); - out += sprintf(out, "%30s [%08X] : %08X\n", - nic_data[i].name, nic_data[i].addr, - tmp32); - break; - } - } - return out - buf; -} - -static DEVICE_ATTR(hardware, S_IRUGO, show_hardware, NULL); - -static ssize_t show_memory(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - struct net_device *dev = priv->net_dev; - static unsigned long loop = 0; - int len = 0; - u32 buffer[4]; - int i; - char line[81]; - - if (loop >= 0x30000) - loop = 0; - - /* sysfs provides us PAGE_SIZE buffer */ - while (len < PAGE_SIZE - 128 && loop < 0x30000) { - - if (priv->snapshot[0]) - for (i = 0; i < 4; i++) - buffer[i] = - *(u32 *) SNAPSHOT_ADDR(loop + i * 4); - else - for (i = 0; i < 4; i++) - read_nic_dword(dev, loop + i * 4, &buffer[i]); - - if (priv->dump_raw) - len += sprintf(buf + len, - "%c%c%c%c" - "%c%c%c%c" - "%c%c%c%c" - "%c%c%c%c", - ((u8 *) buffer)[0x0], - ((u8 *) buffer)[0x1], - ((u8 *) buffer)[0x2], - ((u8 *) buffer)[0x3], - ((u8 *) buffer)[0x4], - ((u8 *) buffer)[0x5], - ((u8 *) buffer)[0x6], - ((u8 *) buffer)[0x7], - ((u8 *) buffer)[0x8], - ((u8 *) buffer)[0x9], - ((u8 *) buffer)[0xa], - ((u8 *) buffer)[0xb], - ((u8 *) buffer)[0xc], - ((u8 *) buffer)[0xd], - ((u8 *) buffer)[0xe], - ((u8 *) buffer)[0xf]); - else - len += sprintf(buf + len, "%s\n", - snprint_line(line, sizeof(line), - (u8 *) buffer, 16, loop)); - loop += 16; - } - - return len; -} - -static ssize_t store_memory(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - struct net_device *dev = priv->net_dev; - const char *p = buf; - - (void)dev; /* kill unused-var warning for debug-only code */ - - if (count < 1) - return count; - - if (p[0] == '1' || - (count >= 2 && tolower(p[0]) == 'o' && tolower(p[1]) == 'n')) { - IPW_DEBUG_INFO("%s: Setting memory dump to RAW mode.\n", - dev->name); - priv->dump_raw = 1; - - } else if (p[0] == '0' || (count >= 2 && tolower(p[0]) == 'o' && - tolower(p[1]) == 'f')) { - IPW_DEBUG_INFO("%s: Setting memory dump to HEX mode.\n", - dev->name); - priv->dump_raw = 0; - - } else if (tolower(p[0]) == 'r') { - IPW_DEBUG_INFO("%s: Resetting firmware snapshot.\n", dev->name); - ipw2100_snapshot_free(priv); - - } else - IPW_DEBUG_INFO("%s: Usage: 0|on = HEX, 1|off = RAW, " - "reset = clear memory snapshot\n", dev->name); - - return count; -} - -static DEVICE_ATTR(memory, S_IWUSR | S_IRUGO, show_memory, store_memory); - -static ssize_t show_ordinals(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - u32 val = 0; - int len = 0; - u32 val_len; - static int loop = 0; - - if (priv->status & STATUS_RF_KILL_MASK) - return 0; - - if (loop >= ARRAY_SIZE(ord_data)) - loop = 0; - - /* sysfs provides us PAGE_SIZE buffer */ - while (len < PAGE_SIZE - 128 && loop < ARRAY_SIZE(ord_data)) { - val_len = sizeof(u32); - - if (ipw2100_get_ordinal(priv, ord_data[loop].index, &val, - &val_len)) - len += sprintf(buf + len, "[0x%02X] = ERROR %s\n", - ord_data[loop].index, - ord_data[loop].desc); - else - len += sprintf(buf + len, "[0x%02X] = 0x%08X %s\n", - ord_data[loop].index, val, - ord_data[loop].desc); - loop++; - } - - return len; -} - -static DEVICE_ATTR(ordinals, S_IRUGO, show_ordinals, NULL); - -static ssize_t show_stats(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - char *out = buf; - - out += sprintf(out, "interrupts: %d {tx: %d, rx: %d, other: %d}\n", - priv->interrupts, priv->tx_interrupts, - priv->rx_interrupts, priv->inta_other); - out += sprintf(out, "firmware resets: %d\n", priv->resets); - out += sprintf(out, "firmware hangs: %d\n", priv->hangs); -#ifdef CONFIG_IPW2100_DEBUG - out += sprintf(out, "packet mismatch image: %s\n", - priv->snapshot[0] ? "YES" : "NO"); -#endif - - return out - buf; -} - -static DEVICE_ATTR(stats, S_IRUGO, show_stats, NULL); - -static int ipw2100_switch_mode(struct ipw2100_priv *priv, u32 mode) -{ - int err; - - if (mode == priv->ieee->iw_mode) - return 0; - - err = ipw2100_disable_adapter(priv); - if (err) { - printk(KERN_ERR DRV_NAME ": %s: Could not disable adapter %d\n", - priv->net_dev->name, err); - return err; - } - - switch (mode) { - case IW_MODE_INFRA: - priv->net_dev->type = ARPHRD_ETHER; - break; - case IW_MODE_ADHOC: - priv->net_dev->type = ARPHRD_ETHER; - break; -#ifdef CONFIG_IPW2100_MONITOR - case IW_MODE_MONITOR: - priv->last_mode = priv->ieee->iw_mode; - priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; - break; -#endif /* CONFIG_IPW2100_MONITOR */ - } - - priv->ieee->iw_mode = mode; - -#ifdef CONFIG_PM - /* Indicate ipw2100_download_firmware download firmware - * from disk instead of memory. */ - ipw2100_firmware.version = 0; -#endif - - printk(KERN_INFO "%s: Reseting on mode change.\n", priv->net_dev->name); - priv->reset_backoff = 0; - schedule_reset(priv); - - return 0; -} - -static ssize_t show_internals(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - int len = 0; - -#define DUMP_VAR(x,y) len += sprintf(buf + len, # x ": %" y "\n", priv-> x) - - if (priv->status & STATUS_ASSOCIATED) - len += sprintf(buf + len, "connected: %lu\n", - get_seconds() - priv->connect_start); - else - len += sprintf(buf + len, "not connected\n"); - - DUMP_VAR(ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx], "p"); - DUMP_VAR(status, "08lx"); - DUMP_VAR(config, "08lx"); - DUMP_VAR(capability, "08lx"); - - len += - sprintf(buf + len, "last_rtc: %lu\n", - (unsigned long)priv->last_rtc); - - DUMP_VAR(fatal_error, "d"); - DUMP_VAR(stop_hang_check, "d"); - DUMP_VAR(stop_rf_kill, "d"); - DUMP_VAR(messages_sent, "d"); - - DUMP_VAR(tx_pend_stat.value, "d"); - DUMP_VAR(tx_pend_stat.hi, "d"); - - DUMP_VAR(tx_free_stat.value, "d"); - DUMP_VAR(tx_free_stat.lo, "d"); - - DUMP_VAR(msg_free_stat.value, "d"); - DUMP_VAR(msg_free_stat.lo, "d"); - - DUMP_VAR(msg_pend_stat.value, "d"); - DUMP_VAR(msg_pend_stat.hi, "d"); - - DUMP_VAR(fw_pend_stat.value, "d"); - DUMP_VAR(fw_pend_stat.hi, "d"); - - DUMP_VAR(txq_stat.value, "d"); - DUMP_VAR(txq_stat.lo, "d"); - - DUMP_VAR(ieee->scans, "d"); - DUMP_VAR(reset_backoff, "d"); - - return len; -} - -static DEVICE_ATTR(internals, S_IRUGO, show_internals, NULL); - -static ssize_t show_bssinfo(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - char essid[IW_ESSID_MAX_SIZE + 1]; - u8 bssid[ETH_ALEN]; - u32 chan = 0; - char *out = buf; - unsigned int length; - int ret; - - if (priv->status & STATUS_RF_KILL_MASK) - return 0; - - memset(essid, 0, sizeof(essid)); - memset(bssid, 0, sizeof(bssid)); - - length = IW_ESSID_MAX_SIZE; - ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_SSID, essid, &length); - if (ret) - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - - length = sizeof(bssid); - ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, - bssid, &length); - if (ret) - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - - length = sizeof(u32); - ret = ipw2100_get_ordinal(priv, IPW_ORD_OUR_FREQ, &chan, &length); - if (ret) - IPW_DEBUG_INFO("failed querying ordinals at line %d\n", - __LINE__); - - out += sprintf(out, "ESSID: %s\n", essid); - out += sprintf(out, "BSSID: %pM\n", bssid); - out += sprintf(out, "Channel: %d\n", chan); - - return out - buf; -} - -static DEVICE_ATTR(bssinfo, S_IRUGO, show_bssinfo, NULL); - -#ifdef CONFIG_IPW2100_DEBUG -static ssize_t show_debug_level(struct device_driver *d, char *buf) -{ - return sprintf(buf, "0x%08X\n", ipw2100_debug_level); -} - -static ssize_t store_debug_level(struct device_driver *d, - const char *buf, size_t count) -{ - char *p = (char *)buf; - u32 val; - - if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { - p++; - if (p[0] == 'x' || p[0] == 'X') - p++; - val = simple_strtoul(p, &p, 16); - } else - val = simple_strtoul(p, &p, 10); - if (p == buf) - IPW_DEBUG_INFO(": %s is not in hex or decimal form.\n", buf); - else - ipw2100_debug_level = val; - - return strnlen(buf, count); -} - -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, show_debug_level, - store_debug_level); -#endif /* CONFIG_IPW2100_DEBUG */ - -static ssize_t show_fatal_error(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - char *out = buf; - int i; - - if (priv->fatal_error) - out += sprintf(out, "0x%08X\n", priv->fatal_error); - else - out += sprintf(out, "0\n"); - - for (i = 1; i <= IPW2100_ERROR_QUEUE; i++) { - if (!priv->fatal_errors[(priv->fatal_index - i) % - IPW2100_ERROR_QUEUE]) - continue; - - out += sprintf(out, "%d. 0x%08X\n", i, - priv->fatal_errors[(priv->fatal_index - i) % - IPW2100_ERROR_QUEUE]); - } - - return out - buf; -} - -static ssize_t store_fatal_error(struct device *d, - struct device_attribute *attr, const char *buf, - size_t count) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - schedule_reset(priv); - return count; -} - -static DEVICE_ATTR(fatal_error, S_IWUSR | S_IRUGO, show_fatal_error, - store_fatal_error); - -static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%d\n", priv->ieee->scan_age); -} - -static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - struct net_device *dev = priv->net_dev; - char buffer[] = "00000000"; - unsigned long len = - (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; - unsigned long val; - char *p = buffer; - - (void)dev; /* kill unused-var warning for debug-only code */ - - IPW_DEBUG_INFO("enter\n"); - - strncpy(buffer, buf, len); - buffer[len] = 0; - - if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { - p++; - if (p[0] == 'x' || p[0] == 'X') - p++; - val = simple_strtoul(p, &p, 16); - } else - val = simple_strtoul(p, &p, 10); - if (p == buffer) { - IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); - } else { - priv->ieee->scan_age = val; - IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age); - } - - IPW_DEBUG_INFO("exit\n"); - return len; -} - -static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); - -static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, - char *buf) -{ - /* 0 - RF kill not enabled - 1 - SW based RF kill active (sysfs) - 2 - HW based RF kill active - 3 - Both HW and SW baed RF kill active */ - struct ipw2100_priv *priv = dev_get_drvdata(d); - int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | - (rf_kill_active(priv) ? 0x2 : 0x0); - return sprintf(buf, "%i\n", val); -} - -static int ipw_radio_kill_sw(struct ipw2100_priv *priv, int disable_radio) -{ - if ((disable_radio ? 1 : 0) == - (priv->status & STATUS_RF_KILL_SW ? 1 : 0)) - return 0; - - IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n", - disable_radio ? "OFF" : "ON"); - - mutex_lock(&priv->action_mutex); - - if (disable_radio) { - priv->status |= STATUS_RF_KILL_SW; - ipw2100_down(priv); - } else { - priv->status &= ~STATUS_RF_KILL_SW; - if (rf_kill_active(priv)) { - IPW_DEBUG_RF_KILL("Can not turn radio back on - " - "disabled by HW switch\n"); - /* Make sure the RF_KILL check timer is running */ - priv->stop_rf_kill = 0; - cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies_relative(HZ)); - } else - schedule_reset(priv); - } - - mutex_unlock(&priv->action_mutex); - return 1; -} - -static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw2100_priv *priv = dev_get_drvdata(d); - ipw_radio_kill_sw(priv, buf[0] == '1'); - return count; -} - -static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); - -static struct attribute *ipw2100_sysfs_entries[] = { - &dev_attr_hardware.attr, - &dev_attr_registers.attr, - &dev_attr_ordinals.attr, - &dev_attr_pci.attr, - &dev_attr_stats.attr, - &dev_attr_internals.attr, - &dev_attr_bssinfo.attr, - &dev_attr_memory.attr, - &dev_attr_scan_age.attr, - &dev_attr_fatal_error.attr, - &dev_attr_rf_kill.attr, - &dev_attr_cfg.attr, - &dev_attr_status.attr, - &dev_attr_capability.attr, - NULL, -}; - -static struct attribute_group ipw2100_attribute_group = { - .attrs = ipw2100_sysfs_entries, -}; - -static int status_queue_allocate(struct ipw2100_priv *priv, int entries) -{ - struct ipw2100_status_queue *q = &priv->status_queue; - - IPW_DEBUG_INFO("enter\n"); - - q->size = entries * sizeof(struct ipw2100_status); - q->drv = - (struct ipw2100_status *)pci_alloc_consistent(priv->pci_dev, - q->size, &q->nic); - if (!q->drv) { - IPW_DEBUG_WARNING("Can not allocate status queue.\n"); - return -ENOMEM; - } - - memset(q->drv, 0, q->size); - - IPW_DEBUG_INFO("exit\n"); - - return 0; -} - -static void status_queue_free(struct ipw2100_priv *priv) -{ - IPW_DEBUG_INFO("enter\n"); - - if (priv->status_queue.drv) { - pci_free_consistent(priv->pci_dev, priv->status_queue.size, - priv->status_queue.drv, - priv->status_queue.nic); - priv->status_queue.drv = NULL; - } - - IPW_DEBUG_INFO("exit\n"); -} - -static int bd_queue_allocate(struct ipw2100_priv *priv, - struct ipw2100_bd_queue *q, int entries) -{ - IPW_DEBUG_INFO("enter\n"); - - memset(q, 0, sizeof(struct ipw2100_bd_queue)); - - q->entries = entries; - q->size = entries * sizeof(struct ipw2100_bd); - q->drv = pci_alloc_consistent(priv->pci_dev, q->size, &q->nic); - if (!q->drv) { - IPW_DEBUG_INFO - ("can't allocate shared memory for buffer descriptors\n"); - return -ENOMEM; - } - memset(q->drv, 0, q->size); - - IPW_DEBUG_INFO("exit\n"); - - return 0; -} - -static void bd_queue_free(struct ipw2100_priv *priv, struct ipw2100_bd_queue *q) -{ - IPW_DEBUG_INFO("enter\n"); - - if (!q) - return; - - if (q->drv) { - pci_free_consistent(priv->pci_dev, q->size, q->drv, q->nic); - q->drv = NULL; - } - - IPW_DEBUG_INFO("exit\n"); -} - -static void bd_queue_initialize(struct ipw2100_priv *priv, - struct ipw2100_bd_queue *q, u32 base, u32 size, - u32 r, u32 w) -{ - IPW_DEBUG_INFO("enter\n"); - - IPW_DEBUG_INFO("initializing bd queue at virt=%p, phys=%08x\n", q->drv, - (u32) q->nic); - - write_register(priv->net_dev, base, q->nic); - write_register(priv->net_dev, size, q->entries); - write_register(priv->net_dev, r, q->oldest); - write_register(priv->net_dev, w, q->next); - - IPW_DEBUG_INFO("exit\n"); -} - -static void ipw2100_kill_workqueue(struct ipw2100_priv *priv) -{ - if (priv->workqueue) { - priv->stop_rf_kill = 1; - priv->stop_hang_check = 1; - cancel_delayed_work(&priv->reset_work); - cancel_delayed_work(&priv->security_work); - cancel_delayed_work(&priv->wx_event_work); - cancel_delayed_work(&priv->hang_check); - cancel_delayed_work(&priv->rf_kill); - cancel_delayed_work(&priv->scan_event_later); - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - } -} - -static int ipw2100_tx_allocate(struct ipw2100_priv *priv) -{ - int i, j, err = -EINVAL; - void *v; - dma_addr_t p; - - IPW_DEBUG_INFO("enter\n"); - - err = bd_queue_allocate(priv, &priv->tx_queue, TX_QUEUE_LENGTH); - if (err) { - IPW_DEBUG_ERROR("%s: failed bd_queue_allocate\n", - priv->net_dev->name); - return err; - } - - priv->tx_buffers = - (struct ipw2100_tx_packet *)kmalloc(TX_PENDED_QUEUE_LENGTH * - sizeof(struct - ipw2100_tx_packet), - GFP_ATOMIC); - if (!priv->tx_buffers) { - printk(KERN_ERR DRV_NAME - ": %s: alloc failed form tx buffers.\n", - priv->net_dev->name); - bd_queue_free(priv, &priv->tx_queue); - return -ENOMEM; - } - - for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) { - v = pci_alloc_consistent(priv->pci_dev, - sizeof(struct ipw2100_data_header), - &p); - if (!v) { - printk(KERN_ERR DRV_NAME - ": %s: PCI alloc failed for tx " "buffers.\n", - priv->net_dev->name); - err = -ENOMEM; - break; - } - - priv->tx_buffers[i].type = DATA; - priv->tx_buffers[i].info.d_struct.data = - (struct ipw2100_data_header *)v; - priv->tx_buffers[i].info.d_struct.data_phys = p; - priv->tx_buffers[i].info.d_struct.txb = NULL; - } - - if (i == TX_PENDED_QUEUE_LENGTH) - return 0; - - for (j = 0; j < i; j++) { - pci_free_consistent(priv->pci_dev, - sizeof(struct ipw2100_data_header), - priv->tx_buffers[j].info.d_struct.data, - priv->tx_buffers[j].info.d_struct. - data_phys); - } - - kfree(priv->tx_buffers); - priv->tx_buffers = NULL; - - return err; -} - -static void ipw2100_tx_initialize(struct ipw2100_priv *priv) -{ - int i; - - IPW_DEBUG_INFO("enter\n"); - - /* - * reinitialize packet info lists - */ - INIT_LIST_HEAD(&priv->fw_pend_list); - INIT_STAT(&priv->fw_pend_stat); - - /* - * reinitialize lists - */ - INIT_LIST_HEAD(&priv->tx_pend_list); - INIT_LIST_HEAD(&priv->tx_free_list); - INIT_STAT(&priv->tx_pend_stat); - INIT_STAT(&priv->tx_free_stat); - - for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) { - /* We simply drop any SKBs that have been queued for - * transmit */ - if (priv->tx_buffers[i].info.d_struct.txb) { - libipw_txb_free(priv->tx_buffers[i].info.d_struct. - txb); - priv->tx_buffers[i].info.d_struct.txb = NULL; - } - - list_add_tail(&priv->tx_buffers[i].list, &priv->tx_free_list); - } - - SET_STAT(&priv->tx_free_stat, i); - - priv->tx_queue.oldest = 0; - priv->tx_queue.available = priv->tx_queue.entries; - priv->tx_queue.next = 0; - INIT_STAT(&priv->txq_stat); - SET_STAT(&priv->txq_stat, priv->tx_queue.available); - - bd_queue_initialize(priv, &priv->tx_queue, - IPW_MEM_HOST_SHARED_TX_QUEUE_BD_BASE, - IPW_MEM_HOST_SHARED_TX_QUEUE_BD_SIZE, - IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX, - IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX); - - IPW_DEBUG_INFO("exit\n"); - -} - -static void ipw2100_tx_free(struct ipw2100_priv *priv) -{ - int i; - - IPW_DEBUG_INFO("enter\n"); - - bd_queue_free(priv, &priv->tx_queue); - - if (!priv->tx_buffers) - return; - - for (i = 0; i < TX_PENDED_QUEUE_LENGTH; i++) { - if (priv->tx_buffers[i].info.d_struct.txb) { - libipw_txb_free(priv->tx_buffers[i].info.d_struct. - txb); - priv->tx_buffers[i].info.d_struct.txb = NULL; - } - if (priv->tx_buffers[i].info.d_struct.data) - pci_free_consistent(priv->pci_dev, - sizeof(struct ipw2100_data_header), - priv->tx_buffers[i].info.d_struct. - data, - priv->tx_buffers[i].info.d_struct. - data_phys); - } - - kfree(priv->tx_buffers); - priv->tx_buffers = NULL; - - IPW_DEBUG_INFO("exit\n"); -} - -static int ipw2100_rx_allocate(struct ipw2100_priv *priv) -{ - int i, j, err = -EINVAL; - - IPW_DEBUG_INFO("enter\n"); - - err = bd_queue_allocate(priv, &priv->rx_queue, RX_QUEUE_LENGTH); - if (err) { - IPW_DEBUG_INFO("failed bd_queue_allocate\n"); - return err; - } - - err = status_queue_allocate(priv, RX_QUEUE_LENGTH); - if (err) { - IPW_DEBUG_INFO("failed status_queue_allocate\n"); - bd_queue_free(priv, &priv->rx_queue); - return err; - } - - /* - * allocate packets - */ - priv->rx_buffers = (struct ipw2100_rx_packet *) - kmalloc(RX_QUEUE_LENGTH * sizeof(struct ipw2100_rx_packet), - GFP_KERNEL); - if (!priv->rx_buffers) { - IPW_DEBUG_INFO("can't allocate rx packet buffer table\n"); - - bd_queue_free(priv, &priv->rx_queue); - - status_queue_free(priv); - - return -ENOMEM; - } - - for (i = 0; i < RX_QUEUE_LENGTH; i++) { - struct ipw2100_rx_packet *packet = &priv->rx_buffers[i]; - - err = ipw2100_alloc_skb(priv, packet); - if (unlikely(err)) { - err = -ENOMEM; - break; - } - - /* The BD holds the cache aligned address */ - priv->rx_queue.drv[i].host_addr = packet->dma_addr; - priv->rx_queue.drv[i].buf_length = IPW_RX_NIC_BUFFER_LENGTH; - priv->status_queue.drv[i].status_fields = 0; - } - - if (i == RX_QUEUE_LENGTH) - return 0; - - for (j = 0; j < i; j++) { - pci_unmap_single(priv->pci_dev, priv->rx_buffers[j].dma_addr, - sizeof(struct ipw2100_rx_packet), - PCI_DMA_FROMDEVICE); - dev_kfree_skb(priv->rx_buffers[j].skb); - } - - kfree(priv->rx_buffers); - priv->rx_buffers = NULL; - - bd_queue_free(priv, &priv->rx_queue); - - status_queue_free(priv); - - return err; -} - -static void ipw2100_rx_initialize(struct ipw2100_priv *priv) -{ - IPW_DEBUG_INFO("enter\n"); - - priv->rx_queue.oldest = 0; - priv->rx_queue.available = priv->rx_queue.entries - 1; - priv->rx_queue.next = priv->rx_queue.entries - 1; - - INIT_STAT(&priv->rxq_stat); - SET_STAT(&priv->rxq_stat, priv->rx_queue.available); - - bd_queue_initialize(priv, &priv->rx_queue, - IPW_MEM_HOST_SHARED_RX_BD_BASE, - IPW_MEM_HOST_SHARED_RX_BD_SIZE, - IPW_MEM_HOST_SHARED_RX_READ_INDEX, - IPW_MEM_HOST_SHARED_RX_WRITE_INDEX); - - /* set up the status queue */ - write_register(priv->net_dev, IPW_MEM_HOST_SHARED_RX_STATUS_BASE, - priv->status_queue.nic); - - IPW_DEBUG_INFO("exit\n"); -} - -static void ipw2100_rx_free(struct ipw2100_priv *priv) -{ - int i; - - IPW_DEBUG_INFO("enter\n"); - - bd_queue_free(priv, &priv->rx_queue); - status_queue_free(priv); - - if (!priv->rx_buffers) - return; - - for (i = 0; i < RX_QUEUE_LENGTH; i++) { - if (priv->rx_buffers[i].rxp) { - pci_unmap_single(priv->pci_dev, - priv->rx_buffers[i].dma_addr, - sizeof(struct ipw2100_rx), - PCI_DMA_FROMDEVICE); - dev_kfree_skb(priv->rx_buffers[i].skb); - } - } - - kfree(priv->rx_buffers); - priv->rx_buffers = NULL; - - IPW_DEBUG_INFO("exit\n"); -} - -static int ipw2100_read_mac_address(struct ipw2100_priv *priv) -{ - u32 length = ETH_ALEN; - u8 addr[ETH_ALEN]; - - int err; - - err = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ADAPTER_MAC, addr, &length); - if (err) { - IPW_DEBUG_INFO("MAC address read failed\n"); - return -EIO; - } - - memcpy(priv->net_dev->dev_addr, addr, ETH_ALEN); - IPW_DEBUG_INFO("card MAC is %pM\n", priv->net_dev->dev_addr); - - return 0; -} - -/******************************************************************** - * - * Firmware Commands - * - ********************************************************************/ - -static int ipw2100_set_mac_address(struct ipw2100_priv *priv, int batch_mode) -{ - struct host_command cmd = { - .host_command = ADAPTER_ADDRESS, - .host_command_sequence = 0, - .host_command_length = ETH_ALEN - }; - int err; - - IPW_DEBUG_HC("SET_MAC_ADDRESS\n"); - - IPW_DEBUG_INFO("enter\n"); - - if (priv->config & CFG_CUSTOM_MAC) { - memcpy(cmd.host_command_parameters, priv->mac_addr, ETH_ALEN); - memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); - } else - memcpy(cmd.host_command_parameters, priv->net_dev->dev_addr, - ETH_ALEN); - - err = ipw2100_hw_send_command(priv, &cmd); - - IPW_DEBUG_INFO("exit\n"); - return err; -} - -static int ipw2100_set_port_type(struct ipw2100_priv *priv, u32 port_type, - int batch_mode) -{ - struct host_command cmd = { - .host_command = PORT_TYPE, - .host_command_sequence = 0, - .host_command_length = sizeof(u32) - }; - int err; - - switch (port_type) { - case IW_MODE_INFRA: - cmd.host_command_parameters[0] = IPW_BSS; - break; - case IW_MODE_ADHOC: - cmd.host_command_parameters[0] = IPW_IBSS; - break; - } - - IPW_DEBUG_HC("PORT_TYPE: %s\n", - port_type == IPW_IBSS ? "Ad-Hoc" : "Managed"); - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) { - printk(KERN_ERR DRV_NAME - ": %s: Could not disable adapter %d\n", - priv->net_dev->name, err); - return err; - } - } - - /* send cmd to firmware */ - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) - ipw2100_enable_adapter(priv); - - return err; -} - -static int ipw2100_set_channel(struct ipw2100_priv *priv, u32 channel, - int batch_mode) -{ - struct host_command cmd = { - .host_command = CHANNEL, - .host_command_sequence = 0, - .host_command_length = sizeof(u32) - }; - int err; - - cmd.host_command_parameters[0] = channel; - - IPW_DEBUG_HC("CHANNEL: %d\n", channel); - - /* If BSS then we don't support channel selection */ - if (priv->ieee->iw_mode == IW_MODE_INFRA) - return 0; - - if ((channel != 0) && - ((channel < REG_MIN_CHANNEL) || (channel > REG_MAX_CHANNEL))) - return -EINVAL; - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) { - IPW_DEBUG_INFO("Failed to set channel to %d", channel); - return err; - } - - if (channel) - priv->config |= CFG_STATIC_CHANNEL; - else - priv->config &= ~CFG_STATIC_CHANNEL; - - priv->channel = channel; - - if (!batch_mode) { - err = ipw2100_enable_adapter(priv); - if (err) - return err; - } - - return 0; -} - -static int ipw2100_system_config(struct ipw2100_priv *priv, int batch_mode) -{ - struct host_command cmd = { - .host_command = SYSTEM_CONFIG, - .host_command_sequence = 0, - .host_command_length = 12, - }; - u32 ibss_mask, len = sizeof(u32); - int err; - - /* Set system configuration */ - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) - cmd.host_command_parameters[0] |= IPW_CFG_IBSS_AUTO_START; - - cmd.host_command_parameters[0] |= IPW_CFG_IBSS_MASK | - IPW_CFG_BSS_MASK | IPW_CFG_802_1x_ENABLE; - - if (!(priv->config & CFG_LONG_PREAMBLE)) - cmd.host_command_parameters[0] |= IPW_CFG_PREAMBLE_AUTO; - - err = ipw2100_get_ordinal(priv, - IPW_ORD_EEPROM_IBSS_11B_CHANNELS, - &ibss_mask, &len); - if (err) - ibss_mask = IPW_IBSS_11B_DEFAULT_MASK; - - cmd.host_command_parameters[1] = REG_CHANNEL_MASK; - cmd.host_command_parameters[2] = REG_CHANNEL_MASK & ibss_mask; - - /* 11b only */ - /*cmd.host_command_parameters[0] |= DIVERSITY_ANTENNA_A; */ - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - -/* If IPv6 is configured in the kernel then we don't want to filter out all - * of the multicast packets as IPv6 needs some. */ -#if !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) - cmd.host_command = ADD_MULTICAST; - cmd.host_command_sequence = 0; - cmd.host_command_length = 0; - - ipw2100_hw_send_command(priv, &cmd); -#endif - if (!batch_mode) { - err = ipw2100_enable_adapter(priv); - if (err) - return err; - } - - return 0; -} - -static int ipw2100_set_tx_rates(struct ipw2100_priv *priv, u32 rate, - int batch_mode) -{ - struct host_command cmd = { - .host_command = BASIC_TX_RATES, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - cmd.host_command_parameters[0] = rate & TX_RATE_MASK; - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - /* Set BASIC TX Rate first */ - ipw2100_hw_send_command(priv, &cmd); - - /* Set TX Rate */ - cmd.host_command = TX_RATES; - ipw2100_hw_send_command(priv, &cmd); - - /* Set MSDU TX Rate */ - cmd.host_command = MSDU_TX_RATES; - ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) { - err = ipw2100_enable_adapter(priv); - if (err) - return err; - } - - priv->tx_rates = rate; - - return 0; -} - -static int ipw2100_set_power_mode(struct ipw2100_priv *priv, int power_level) -{ - struct host_command cmd = { - .host_command = POWER_MODE, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - cmd.host_command_parameters[0] = power_level; - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - - if (power_level == IPW_POWER_MODE_CAM) - priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); - else - priv->power_mode = IPW_POWER_ENABLED | power_level; - -#ifdef IPW2100_TX_POWER - if (priv->port_type == IBSS && priv->adhoc_power != DFTL_IBSS_TX_POWER) { - /* Set beacon interval */ - cmd.host_command = TX_POWER_INDEX; - cmd.host_command_parameters[0] = (u32) priv->adhoc_power; - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - } -#endif - - return 0; -} - -static int ipw2100_set_rts_threshold(struct ipw2100_priv *priv, u32 threshold) -{ - struct host_command cmd = { - .host_command = RTS_THRESHOLD, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - if (threshold & RTS_DISABLED) - cmd.host_command_parameters[0] = MAX_RTS_THRESHOLD; - else - cmd.host_command_parameters[0] = threshold & ~RTS_DISABLED; - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - - priv->rts_threshold = threshold; - - return 0; -} - -#if 0 -int ipw2100_set_fragmentation_threshold(struct ipw2100_priv *priv, - u32 threshold, int batch_mode) -{ - struct host_command cmd = { - .host_command = FRAG_THRESHOLD, - .host_command_sequence = 0, - .host_command_length = 4, - .host_command_parameters[0] = 0, - }; - int err; - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - if (threshold == 0) - threshold = DEFAULT_FRAG_THRESHOLD; - else { - threshold = max(threshold, MIN_FRAG_THRESHOLD); - threshold = min(threshold, MAX_FRAG_THRESHOLD); - } - - cmd.host_command_parameters[0] = threshold; - - IPW_DEBUG_HC("FRAG_THRESHOLD: %u\n", threshold); - - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) - ipw2100_enable_adapter(priv); - - if (!err) - priv->frag_threshold = threshold; - - return err; -} -#endif - -static int ipw2100_set_short_retry(struct ipw2100_priv *priv, u32 retry) -{ - struct host_command cmd = { - .host_command = SHORT_RETRY_LIMIT, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - cmd.host_command_parameters[0] = retry; - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - - priv->short_retry_limit = retry; - - return 0; -} - -static int ipw2100_set_long_retry(struct ipw2100_priv *priv, u32 retry) -{ - struct host_command cmd = { - .host_command = LONG_RETRY_LIMIT, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - cmd.host_command_parameters[0] = retry; - - err = ipw2100_hw_send_command(priv, &cmd); - if (err) - return err; - - priv->long_retry_limit = retry; - - return 0; -} - -static int ipw2100_set_mandatory_bssid(struct ipw2100_priv *priv, u8 * bssid, - int batch_mode) -{ - struct host_command cmd = { - .host_command = MANDATORY_BSSID, - .host_command_sequence = 0, - .host_command_length = (bssid == NULL) ? 0 : ETH_ALEN - }; - int err; - -#ifdef CONFIG_IPW2100_DEBUG - if (bssid != NULL) - IPW_DEBUG_HC("MANDATORY_BSSID: %pM\n", bssid); - else - IPW_DEBUG_HC("MANDATORY_BSSID: \n"); -#endif - /* if BSSID is empty then we disable mandatory bssid mode */ - if (bssid != NULL) - memcpy(cmd.host_command_parameters, bssid, ETH_ALEN); - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) - ipw2100_enable_adapter(priv); - - return err; -} - -static int ipw2100_disassociate_bssid(struct ipw2100_priv *priv) -{ - struct host_command cmd = { - .host_command = DISASSOCIATION_BSSID, - .host_command_sequence = 0, - .host_command_length = ETH_ALEN - }; - int err; - int len; - - IPW_DEBUG_HC("DISASSOCIATION_BSSID\n"); - - len = ETH_ALEN; - /* The Firmware currently ignores the BSSID and just disassociates from - * the currently associated AP -- but in the off chance that a future - * firmware does use the BSSID provided here, we go ahead and try and - * set it to the currently associated AP's BSSID */ - memcpy(cmd.host_command_parameters, priv->bssid, ETH_ALEN); - - err = ipw2100_hw_send_command(priv, &cmd); - - return err; -} - -static int ipw2100_set_wpa_ie(struct ipw2100_priv *, - struct ipw2100_wpa_assoc_frame *, int) - __attribute__ ((unused)); - -static int ipw2100_set_wpa_ie(struct ipw2100_priv *priv, - struct ipw2100_wpa_assoc_frame *wpa_frame, - int batch_mode) -{ - struct host_command cmd = { - .host_command = SET_WPA_IE, - .host_command_sequence = 0, - .host_command_length = sizeof(struct ipw2100_wpa_assoc_frame), - }; - int err; - - IPW_DEBUG_HC("SET_WPA_IE\n"); - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - memcpy(cmd.host_command_parameters, wpa_frame, - sizeof(struct ipw2100_wpa_assoc_frame)); - - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) { - if (ipw2100_enable_adapter(priv)) - err = -EIO; - } - - return err; -} - -struct security_info_params { - u32 allowed_ciphers; - u16 version; - u8 auth_mode; - u8 replay_counters_number; - u8 unicast_using_group; -} __attribute__ ((packed)); - -static int ipw2100_set_security_information(struct ipw2100_priv *priv, - int auth_mode, - int security_level, - int unicast_using_group, - int batch_mode) -{ - struct host_command cmd = { - .host_command = SET_SECURITY_INFORMATION, - .host_command_sequence = 0, - .host_command_length = sizeof(struct security_info_params) - }; - struct security_info_params *security = - (struct security_info_params *)&cmd.host_command_parameters; - int err; - memset(security, 0, sizeof(*security)); - - /* If shared key AP authentication is turned on, then we need to - * configure the firmware to try and use it. - * - * Actual data encryption/decryption is handled by the host. */ - security->auth_mode = auth_mode; - security->unicast_using_group = unicast_using_group; - - switch (security_level) { - default: - case SEC_LEVEL_0: - security->allowed_ciphers = IPW_NONE_CIPHER; - break; - case SEC_LEVEL_1: - security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER; - break; - case SEC_LEVEL_2: - security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER | IPW_TKIP_CIPHER; - break; - case SEC_LEVEL_2_CKIP: - security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER | IPW_CKIP_CIPHER; - break; - case SEC_LEVEL_3: - security->allowed_ciphers = IPW_WEP40_CIPHER | - IPW_WEP104_CIPHER | IPW_TKIP_CIPHER | IPW_CCMP_CIPHER; - break; - } - - IPW_DEBUG_HC - ("SET_SECURITY_INFORMATION: auth:%d cipher:0x%02X (level %d)\n", - security->auth_mode, security->allowed_ciphers, security_level); - - security->replay_counters_number = 0; - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) - ipw2100_enable_adapter(priv); - - return err; -} - -static int ipw2100_set_tx_power(struct ipw2100_priv *priv, u32 tx_power) -{ - struct host_command cmd = { - .host_command = TX_POWER_INDEX, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err = 0; - u32 tmp = tx_power; - - if (tx_power != IPW_TX_POWER_DEFAULT) - tmp = (tx_power - IPW_TX_POWER_MIN_DBM) * 16 / - (IPW_TX_POWER_MAX_DBM - IPW_TX_POWER_MIN_DBM); - - cmd.host_command_parameters[0] = tmp; - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) - err = ipw2100_hw_send_command(priv, &cmd); - if (!err) - priv->tx_power = tx_power; - - return 0; -} - -static int ipw2100_set_ibss_beacon_interval(struct ipw2100_priv *priv, - u32 interval, int batch_mode) -{ - struct host_command cmd = { - .host_command = BEACON_INTERVAL, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - cmd.host_command_parameters[0] = interval; - - IPW_DEBUG_INFO("enter\n"); - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) { - err = ipw2100_enable_adapter(priv); - if (err) - return err; - } - } - - IPW_DEBUG_INFO("exit\n"); - - return 0; -} - -static void ipw2100_queues_initialize(struct ipw2100_priv *priv) -{ - ipw2100_tx_initialize(priv); - ipw2100_rx_initialize(priv); - ipw2100_msg_initialize(priv); -} - -static void ipw2100_queues_free(struct ipw2100_priv *priv) -{ - ipw2100_tx_free(priv); - ipw2100_rx_free(priv); - ipw2100_msg_free(priv); -} - -static int ipw2100_queues_allocate(struct ipw2100_priv *priv) -{ - if (ipw2100_tx_allocate(priv) || - ipw2100_rx_allocate(priv) || ipw2100_msg_allocate(priv)) - goto fail; - - return 0; - - fail: - ipw2100_tx_free(priv); - ipw2100_rx_free(priv); - ipw2100_msg_free(priv); - return -ENOMEM; -} - -#define IPW_PRIVACY_CAPABLE 0x0008 - -static int ipw2100_set_wep_flags(struct ipw2100_priv *priv, u32 flags, - int batch_mode) -{ - struct host_command cmd = { - .host_command = WEP_FLAGS, - .host_command_sequence = 0, - .host_command_length = 4 - }; - int err; - - cmd.host_command_parameters[0] = flags; - - IPW_DEBUG_HC("WEP_FLAGS: flags = 0x%08X\n", flags); - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) { - printk(KERN_ERR DRV_NAME - ": %s: Could not disable adapter %d\n", - priv->net_dev->name, err); - return err; - } - } - - /* send cmd to firmware */ - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) - ipw2100_enable_adapter(priv); - - return err; -} - -struct ipw2100_wep_key { - u8 idx; - u8 len; - u8 key[13]; -}; - -/* Macros to ease up priting WEP keys */ -#define WEP_FMT_64 "%02X%02X%02X%02X-%02X" -#define WEP_FMT_128 "%02X%02X%02X%02X-%02X%02X%02X%02X-%02X%02X%02X" -#define WEP_STR_64(x) x[0],x[1],x[2],x[3],x[4] -#define WEP_STR_128(x) x[0],x[1],x[2],x[3],x[4],x[5],x[6],x[7],x[8],x[9],x[10] - -/** - * Set a the wep key - * - * @priv: struct to work on - * @idx: index of the key we want to set - * @key: ptr to the key data to set - * @len: length of the buffer at @key - * @batch_mode: FIXME perform the operation in batch mode, not - * disabling the device. - * - * @returns 0 if OK, < 0 errno code on error. - * - * Fill out a command structure with the new wep key, length an - * index and send it down the wire. - */ -static int ipw2100_set_key(struct ipw2100_priv *priv, - int idx, char *key, int len, int batch_mode) -{ - int keylen = len ? (len <= 5 ? 5 : 13) : 0; - struct host_command cmd = { - .host_command = WEP_KEY_INFO, - .host_command_sequence = 0, - .host_command_length = sizeof(struct ipw2100_wep_key), - }; - struct ipw2100_wep_key *wep_key = (void *)cmd.host_command_parameters; - int err; - - IPW_DEBUG_HC("WEP_KEY_INFO: index = %d, len = %d/%d\n", - idx, keylen, len); - - /* NOTE: We don't check cached values in case the firmware was reset - * or some other problem is occurring. If the user is setting the key, - * then we push the change */ - - wep_key->idx = idx; - wep_key->len = keylen; - - if (keylen) { - memcpy(wep_key->key, key, len); - memset(wep_key->key + len, 0, keylen - len); - } - - /* Will be optimized out on debug not being configured in */ - if (keylen == 0) - IPW_DEBUG_WEP("%s: Clearing key %d\n", - priv->net_dev->name, wep_key->idx); - else if (keylen == 5) - IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_64 "\n", - priv->net_dev->name, wep_key->idx, wep_key->len, - WEP_STR_64(wep_key->key)); - else - IPW_DEBUG_WEP("%s: idx: %d, len: %d key: " WEP_FMT_128 - "\n", - priv->net_dev->name, wep_key->idx, wep_key->len, - WEP_STR_128(wep_key->key)); - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - /* FIXME: IPG: shouldn't this prink be in _disable_adapter()? */ - if (err) { - printk(KERN_ERR DRV_NAME - ": %s: Could not disable adapter %d\n", - priv->net_dev->name, err); - return err; - } - } - - /* send cmd to firmware */ - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) { - int err2 = ipw2100_enable_adapter(priv); - if (err == 0) - err = err2; - } - return err; -} - -static int ipw2100_set_key_index(struct ipw2100_priv *priv, - int idx, int batch_mode) -{ - struct host_command cmd = { - .host_command = WEP_KEY_INDEX, - .host_command_sequence = 0, - .host_command_length = 4, - .host_command_parameters = {idx}, - }; - int err; - - IPW_DEBUG_HC("WEP_KEY_INDEX: index = %d\n", idx); - - if (idx < 0 || idx > 3) - return -EINVAL; - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) { - printk(KERN_ERR DRV_NAME - ": %s: Could not disable adapter %d\n", - priv->net_dev->name, err); - return err; - } - } - - /* send cmd to firmware */ - err = ipw2100_hw_send_command(priv, &cmd); - - if (!batch_mode) - ipw2100_enable_adapter(priv); - - return err; -} - -static int ipw2100_configure_security(struct ipw2100_priv *priv, int batch_mode) -{ - int i, err, auth_mode, sec_level, use_group; - - if (!(priv->status & STATUS_RUNNING)) - return 0; - - if (!batch_mode) { - err = ipw2100_disable_adapter(priv); - if (err) - return err; - } - - if (!priv->ieee->sec.enabled) { - err = - ipw2100_set_security_information(priv, IPW_AUTH_OPEN, - SEC_LEVEL_0, 0, 1); - } else { - auth_mode = IPW_AUTH_OPEN; - if (priv->ieee->sec.flags & SEC_AUTH_MODE) { - if (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY) - auth_mode = IPW_AUTH_SHARED; - else if (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP) - auth_mode = IPW_AUTH_LEAP_CISCO_ID; - } - - sec_level = SEC_LEVEL_0; - if (priv->ieee->sec.flags & SEC_LEVEL) - sec_level = priv->ieee->sec.level; - - use_group = 0; - if (priv->ieee->sec.flags & SEC_UNICAST_GROUP) - use_group = priv->ieee->sec.unicast_uses_group; - - err = - ipw2100_set_security_information(priv, auth_mode, sec_level, - use_group, 1); - } - - if (err) - goto exit; - - if (priv->ieee->sec.enabled) { - for (i = 0; i < 4; i++) { - if (!(priv->ieee->sec.flags & (1 << i))) { - memset(priv->ieee->sec.keys[i], 0, WEP_KEY_LEN); - priv->ieee->sec.key_sizes[i] = 0; - } else { - err = ipw2100_set_key(priv, i, - priv->ieee->sec.keys[i], - priv->ieee->sec. - key_sizes[i], 1); - if (err) - goto exit; - } - } - - ipw2100_set_key_index(priv, priv->ieee->crypt_info.tx_keyidx, 1); - } - - /* Always enable privacy so the Host can filter WEP packets if - * encrypted data is sent up */ - err = - ipw2100_set_wep_flags(priv, - priv->ieee->sec. - enabled ? IPW_PRIVACY_CAPABLE : 0, 1); - if (err) - goto exit; - - priv->status &= ~STATUS_SECURITY_UPDATED; - - exit: - if (!batch_mode) - ipw2100_enable_adapter(priv); - - return err; -} - -static void ipw2100_security_work(struct work_struct *work) -{ - struct ipw2100_priv *priv = - container_of(work, struct ipw2100_priv, security_work.work); - - /* If we happen to have reconnected before we get a chance to - * process this, then update the security settings--which causes - * a disassociation to occur */ - if (!(priv->status & STATUS_ASSOCIATED) && - priv->status & STATUS_SECURITY_UPDATED) - ipw2100_configure_security(priv, 0); -} - -static void shim__set_security(struct net_device *dev, - struct libipw_security *sec) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int i, force_update = 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) - goto done; - - for (i = 0; i < 4; i++) { - if (sec->flags & (1 << i)) { - priv->ieee->sec.key_sizes[i] = sec->key_sizes[i]; - if (sec->key_sizes[i] == 0) - priv->ieee->sec.flags &= ~(1 << i); - else - memcpy(priv->ieee->sec.keys[i], sec->keys[i], - sec->key_sizes[i]); - if (sec->level == SEC_LEVEL_1) { - priv->ieee->sec.flags |= (1 << i); - priv->status |= STATUS_SECURITY_UPDATED; - } else - priv->ieee->sec.flags &= ~(1 << i); - } - } - - if ((sec->flags & SEC_ACTIVE_KEY) && - priv->ieee->sec.active_key != sec->active_key) { - if (sec->active_key <= 3) { - priv->ieee->sec.active_key = sec->active_key; - priv->ieee->sec.flags |= SEC_ACTIVE_KEY; - } else - priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; - - priv->status |= STATUS_SECURITY_UPDATED; - } - - if ((sec->flags & SEC_AUTH_MODE) && - (priv->ieee->sec.auth_mode != sec->auth_mode)) { - priv->ieee->sec.auth_mode = sec->auth_mode; - priv->ieee->sec.flags |= SEC_AUTH_MODE; - priv->status |= STATUS_SECURITY_UPDATED; - } - - if (sec->flags & SEC_ENABLED && priv->ieee->sec.enabled != sec->enabled) { - priv->ieee->sec.flags |= SEC_ENABLED; - priv->ieee->sec.enabled = sec->enabled; - priv->status |= STATUS_SECURITY_UPDATED; - force_update = 1; - } - - if (sec->flags & SEC_ENCRYPT) - priv->ieee->sec.encrypt = sec->encrypt; - - if (sec->flags & SEC_LEVEL && priv->ieee->sec.level != sec->level) { - priv->ieee->sec.level = sec->level; - priv->ieee->sec.flags |= SEC_LEVEL; - priv->status |= STATUS_SECURITY_UPDATED; - } - - IPW_DEBUG_WEP("Security flags: %c %c%c%c%c %c%c%c%c\n", - priv->ieee->sec.flags & (1 << 8) ? '1' : '0', - priv->ieee->sec.flags & (1 << 7) ? '1' : '0', - priv->ieee->sec.flags & (1 << 6) ? '1' : '0', - priv->ieee->sec.flags & (1 << 5) ? '1' : '0', - priv->ieee->sec.flags & (1 << 4) ? '1' : '0', - priv->ieee->sec.flags & (1 << 3) ? '1' : '0', - priv->ieee->sec.flags & (1 << 2) ? '1' : '0', - priv->ieee->sec.flags & (1 << 1) ? '1' : '0', - priv->ieee->sec.flags & (1 << 0) ? '1' : '0'); - -/* As a temporary work around to enable WPA until we figure out why - * wpa_supplicant toggles the security capability of the driver, which - * forces a disassocation with force_update... - * - * if (force_update || !(priv->status & STATUS_ASSOCIATED))*/ - if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) - ipw2100_configure_security(priv, 0); - done: - mutex_unlock(&priv->action_mutex); -} - -static int ipw2100_adapter_setup(struct ipw2100_priv *priv) -{ - int err; - int batch_mode = 1; - u8 *bssid; - - IPW_DEBUG_INFO("enter\n"); - - err = ipw2100_disable_adapter(priv); - if (err) - return err; -#ifdef CONFIG_IPW2100_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - err = ipw2100_set_channel(priv, priv->channel, batch_mode); - if (err) - return err; - - IPW_DEBUG_INFO("exit\n"); - - return 0; - } -#endif /* CONFIG_IPW2100_MONITOR */ - - err = ipw2100_read_mac_address(priv); - if (err) - return -EIO; - - err = ipw2100_set_mac_address(priv, batch_mode); - if (err) - return err; - - err = ipw2100_set_port_type(priv, priv->ieee->iw_mode, batch_mode); - if (err) - return err; - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - err = ipw2100_set_channel(priv, priv->channel, batch_mode); - if (err) - return err; - } - - err = ipw2100_system_config(priv, batch_mode); - if (err) - return err; - - err = ipw2100_set_tx_rates(priv, priv->tx_rates, batch_mode); - if (err) - return err; - - /* Default to power mode OFF */ - err = ipw2100_set_power_mode(priv, IPW_POWER_MODE_CAM); - if (err) - return err; - - err = ipw2100_set_rts_threshold(priv, priv->rts_threshold); - if (err) - return err; - - if (priv->config & CFG_STATIC_BSSID) - bssid = priv->bssid; - else - bssid = NULL; - err = ipw2100_set_mandatory_bssid(priv, bssid, batch_mode); - if (err) - return err; - - if (priv->config & CFG_STATIC_ESSID) - err = ipw2100_set_essid(priv, priv->essid, priv->essid_len, - batch_mode); - else - err = ipw2100_set_essid(priv, NULL, 0, batch_mode); - if (err) - return err; - - err = ipw2100_configure_security(priv, batch_mode); - if (err) - return err; - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - err = - ipw2100_set_ibss_beacon_interval(priv, - priv->beacon_interval, - batch_mode); - if (err) - return err; - - err = ipw2100_set_tx_power(priv, priv->tx_power); - if (err) - return err; - } - - /* - err = ipw2100_set_fragmentation_threshold( - priv, priv->frag_threshold, batch_mode); - if (err) - return err; - */ - - IPW_DEBUG_INFO("exit\n"); - - return 0; -} - -/************************************************************************* - * - * EXTERNALLY CALLED METHODS - * - *************************************************************************/ - -/* This method is called by the network layer -- not to be confused with - * ipw2100_set_mac_address() declared above called by this driver (and this - * method as well) to talk to the firmware */ -static int ipw2100_set_address(struct net_device *dev, void *p) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct sockaddr *addr = p; - int err = 0; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - mutex_lock(&priv->action_mutex); - - priv->config |= CFG_CUSTOM_MAC; - memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); - - err = ipw2100_set_mac_address(priv, 0); - if (err) - goto done; - - priv->reset_backoff = 0; - mutex_unlock(&priv->action_mutex); - ipw2100_reset_adapter(&priv->reset_work.work); - return 0; - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_open(struct net_device *dev) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - unsigned long flags; - IPW_DEBUG_INFO("dev->open\n"); - - spin_lock_irqsave(&priv->low_lock, flags); - if (priv->status & STATUS_ASSOCIATED) { - netif_carrier_on(dev); - netif_start_queue(dev); - } - spin_unlock_irqrestore(&priv->low_lock, flags); - - return 0; -} - -static int ipw2100_close(struct net_device *dev) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - unsigned long flags; - struct list_head *element; - struct ipw2100_tx_packet *packet; - - IPW_DEBUG_INFO("enter\n"); - - spin_lock_irqsave(&priv->low_lock, flags); - - if (priv->status & STATUS_ASSOCIATED) - netif_carrier_off(dev); - netif_stop_queue(dev); - - /* Flush the TX queue ... */ - while (!list_empty(&priv->tx_pend_list)) { - element = priv->tx_pend_list.next; - packet = list_entry(element, struct ipw2100_tx_packet, list); - - list_del(element); - DEC_STAT(&priv->tx_pend_stat); - - libipw_txb_free(packet->info.d_struct.txb); - packet->info.d_struct.txb = NULL; - - list_add_tail(element, &priv->tx_free_list); - INC_STAT(&priv->tx_free_stat); - } - spin_unlock_irqrestore(&priv->low_lock, flags); - - IPW_DEBUG_INFO("exit\n"); - - return 0; -} - -/* - * TODO: Fix this function... its just wrong - */ -static void ipw2100_tx_timeout(struct net_device *dev) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - - dev->stats.tx_errors++; - -#ifdef CONFIG_IPW2100_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) - return; -#endif - - IPW_DEBUG_INFO("%s: TX timed out. Scheduling firmware restart.\n", - dev->name); - schedule_reset(priv); -} - -static int ipw2100_wpa_enable(struct ipw2100_priv *priv, int value) -{ - /* This is called when wpa_supplicant loads and closes the driver - * interface. */ - priv->ieee->wpa_enabled = value; - return 0; -} - -static int ipw2100_wpa_set_auth_algs(struct ipw2100_priv *priv, int value) -{ - - struct libipw_device *ieee = priv->ieee; - struct libipw_security sec = { - .flags = SEC_AUTH_MODE, - }; - int ret = 0; - - if (value & IW_AUTH_ALG_SHARED_KEY) { - sec.auth_mode = WLAN_AUTH_SHARED_KEY; - ieee->open_wep = 0; - } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { - sec.auth_mode = WLAN_AUTH_OPEN; - ieee->open_wep = 1; - } else if (value & IW_AUTH_ALG_LEAP) { - sec.auth_mode = WLAN_AUTH_LEAP; - ieee->open_wep = 1; - } else - return -EINVAL; - - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - else - ret = -EOPNOTSUPP; - - return ret; -} - -static void ipw2100_wpa_assoc_frame(struct ipw2100_priv *priv, - char *wpa_ie, int wpa_ie_len) -{ - - struct ipw2100_wpa_assoc_frame frame; - - frame.fixed_ie_mask = 0; - - /* copy WPA IE */ - memcpy(frame.var_ie, wpa_ie, wpa_ie_len); - frame.var_ie_len = wpa_ie_len; - - /* make sure WPA is enabled */ - ipw2100_wpa_enable(priv, 1); - ipw2100_set_wpa_ie(priv, &frame, 0); -} - -static void ipw_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - char fw_ver[64], ucode_ver[64]; - - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - - ipw2100_get_fwversion(priv, fw_ver, sizeof(fw_ver)); - ipw2100_get_ucodeversion(priv, ucode_ver, sizeof(ucode_ver)); - - snprintf(info->fw_version, sizeof(info->fw_version), "%s:%d:%s", - fw_ver, priv->eeprom_version, ucode_ver); - - strcpy(info->bus_info, pci_name(priv->pci_dev)); -} - -static u32 ipw2100_ethtool_get_link(struct net_device *dev) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - return (priv->status & STATUS_ASSOCIATED) ? 1 : 0; -} - -static const struct ethtool_ops ipw2100_ethtool_ops = { - .get_link = ipw2100_ethtool_get_link, - .get_drvinfo = ipw_ethtool_get_drvinfo, -}; - -static void ipw2100_hang_check(struct work_struct *work) -{ - struct ipw2100_priv *priv = - container_of(work, struct ipw2100_priv, hang_check.work); - unsigned long flags; - u32 rtc = 0xa5a5a5a5; - u32 len = sizeof(rtc); - int restart = 0; - - spin_lock_irqsave(&priv->low_lock, flags); - - if (priv->fatal_error != 0) { - /* If fatal_error is set then we need to restart */ - IPW_DEBUG_INFO("%s: Hardware fatal error detected.\n", - priv->net_dev->name); - - restart = 1; - } else if (ipw2100_get_ordinal(priv, IPW_ORD_RTC_TIME, &rtc, &len) || - (rtc == priv->last_rtc)) { - /* Check if firmware is hung */ - IPW_DEBUG_INFO("%s: Firmware RTC stalled.\n", - priv->net_dev->name); - - restart = 1; - } - - if (restart) { - /* Kill timer */ - priv->stop_hang_check = 1; - priv->hangs++; - - /* Restart the NIC */ - schedule_reset(priv); - } - - priv->last_rtc = rtc; - - if (!priv->stop_hang_check) - queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2); - - spin_unlock_irqrestore(&priv->low_lock, flags); -} - -static void ipw2100_rf_kill(struct work_struct *work) -{ - struct ipw2100_priv *priv = - container_of(work, struct ipw2100_priv, rf_kill.work); - unsigned long flags; - - spin_lock_irqsave(&priv->low_lock, flags); - - if (rf_kill_active(priv)) { - IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); - if (!priv->stop_rf_kill) - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies_relative(HZ)); - goto exit_unlock; - } - - /* RF Kill is now disabled, so bring the device back up */ - - if (!(priv->status & STATUS_RF_KILL_MASK)) { - IPW_DEBUG_RF_KILL("HW RF Kill no longer active, restarting " - "device\n"); - schedule_reset(priv); - } else - IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still " - "enabled\n"); - - exit_unlock: - spin_unlock_irqrestore(&priv->low_lock, flags); -} - -static void ipw2100_irq_tasklet(struct ipw2100_priv *priv); - -static const struct net_device_ops ipw2100_netdev_ops = { - .ndo_open = ipw2100_open, - .ndo_stop = ipw2100_close, - .ndo_start_xmit = libipw_xmit, - .ndo_change_mtu = libipw_change_mtu, - .ndo_init = ipw2100_net_init, - .ndo_tx_timeout = ipw2100_tx_timeout, - .ndo_set_mac_address = ipw2100_set_address, - .ndo_validate_addr = eth_validate_addr, -}; - -/* Look into using netdev destructor to shutdown ieee80211? */ - -static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, - void __iomem * base_addr, - unsigned long mem_start, - unsigned long mem_len) -{ - struct ipw2100_priv *priv; - struct net_device *dev; - - dev = alloc_ieee80211(sizeof(struct ipw2100_priv)); - if (!dev) - return NULL; - priv = libipw_priv(dev); - priv->ieee = netdev_priv(dev); - priv->pci_dev = pci_dev; - priv->net_dev = dev; - - priv->ieee->hard_start_xmit = ipw2100_tx; - priv->ieee->set_security = shim__set_security; - - priv->ieee->perfect_rssi = -20; - priv->ieee->worst_rssi = -85; - - dev->netdev_ops = &ipw2100_netdev_ops; - dev->ethtool_ops = &ipw2100_ethtool_ops; - dev->wireless_handlers = &ipw2100_wx_handler_def; - priv->wireless_data.libipw = priv->ieee; - dev->wireless_data = &priv->wireless_data; - dev->watchdog_timeo = 3 * HZ; - dev->irq = 0; - - dev->base_addr = (unsigned long)base_addr; - dev->mem_start = mem_start; - dev->mem_end = dev->mem_start + mem_len - 1; - - /* NOTE: We don't use the wireless_handlers hook - * in dev as the system will start throwing WX requests - * to us before we're actually initialized and it just - * ends up causing problems. So, we just handle - * the WX extensions through the ipw2100_ioctl interface */ - - /* memset() puts everything to 0, so we only have explicitly set - * those values that need to be something else */ - - /* If power management is turned on, default to AUTO mode */ - priv->power_mode = IPW_POWER_AUTO; - -#ifdef CONFIG_IPW2100_MONITOR - priv->config |= CFG_CRC_CHECK; -#endif - priv->ieee->wpa_enabled = 0; - priv->ieee->drop_unencrypted = 0; - priv->ieee->privacy_invoked = 0; - priv->ieee->ieee802_1x = 1; - - /* Set module parameters */ - switch (network_mode) { - case 1: - priv->ieee->iw_mode = IW_MODE_ADHOC; - break; -#ifdef CONFIG_IPW2100_MONITOR - case 2: - priv->ieee->iw_mode = IW_MODE_MONITOR; - break; -#endif - default: - case 0: - priv->ieee->iw_mode = IW_MODE_INFRA; - break; - } - - if (disable == 1) - priv->status |= STATUS_RF_KILL_SW; - - if (channel != 0 && - ((channel >= REG_MIN_CHANNEL) && (channel <= REG_MAX_CHANNEL))) { - priv->config |= CFG_STATIC_CHANNEL; - priv->channel = channel; - } - - if (associate) - priv->config |= CFG_ASSOCIATE; - - priv->beacon_interval = DEFAULT_BEACON_INTERVAL; - priv->short_retry_limit = DEFAULT_SHORT_RETRY_LIMIT; - priv->long_retry_limit = DEFAULT_LONG_RETRY_LIMIT; - priv->rts_threshold = DEFAULT_RTS_THRESHOLD | RTS_DISABLED; - priv->frag_threshold = DEFAULT_FTS | FRAG_DISABLED; - priv->tx_power = IPW_TX_POWER_DEFAULT; - priv->tx_rates = DEFAULT_TX_RATES; - - strcpy(priv->nick, "ipw2100"); - - spin_lock_init(&priv->low_lock); - mutex_init(&priv->action_mutex); - mutex_init(&priv->adapter_mutex); - - init_waitqueue_head(&priv->wait_command_queue); - - netif_carrier_off(dev); - - INIT_LIST_HEAD(&priv->msg_free_list); - INIT_LIST_HEAD(&priv->msg_pend_list); - INIT_STAT(&priv->msg_free_stat); - INIT_STAT(&priv->msg_pend_stat); - - INIT_LIST_HEAD(&priv->tx_free_list); - INIT_LIST_HEAD(&priv->tx_pend_list); - INIT_STAT(&priv->tx_free_stat); - INIT_STAT(&priv->tx_pend_stat); - - INIT_LIST_HEAD(&priv->fw_pend_list); - INIT_STAT(&priv->fw_pend_stat); - - priv->workqueue = create_workqueue(DRV_NAME); - - INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter); - INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work); - INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); - INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); - INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); - INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); - INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); - - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - ipw2100_irq_tasklet, (unsigned long)priv); - - /* NOTE: We do not start the deferred work for status checks yet */ - priv->stop_rf_kill = 1; - priv->stop_hang_check = 1; - - return dev; -} - -static int ipw2100_pci_init_one(struct pci_dev *pci_dev, - const struct pci_device_id *ent) -{ - unsigned long mem_start, mem_len, mem_flags; - void __iomem *base_addr = NULL; - struct net_device *dev = NULL; - struct ipw2100_priv *priv = NULL; - int err = 0; - int registered = 0; - u32 val; - - IPW_DEBUG_INFO("enter\n"); - - mem_start = pci_resource_start(pci_dev, 0); - mem_len = pci_resource_len(pci_dev, 0); - mem_flags = pci_resource_flags(pci_dev, 0); - - if ((mem_flags & IORESOURCE_MEM) != IORESOURCE_MEM) { - IPW_DEBUG_INFO("weird - resource type is not memory\n"); - err = -ENODEV; - goto fail; - } - - base_addr = ioremap_nocache(mem_start, mem_len); - if (!base_addr) { - printk(KERN_WARNING DRV_NAME - "Error calling ioremap_nocache.\n"); - err = -EIO; - goto fail; - } - - /* allocate and initialize our net_device */ - dev = ipw2100_alloc_device(pci_dev, base_addr, mem_start, mem_len); - if (!dev) { - printk(KERN_WARNING DRV_NAME - "Error calling ipw2100_alloc_device.\n"); - err = -ENOMEM; - goto fail; - } - - /* set up PCI mappings for device */ - err = pci_enable_device(pci_dev); - if (err) { - printk(KERN_WARNING DRV_NAME - "Error calling pci_enable_device.\n"); - return err; - } - - priv = libipw_priv(dev); - - pci_set_master(pci_dev); - pci_set_drvdata(pci_dev, priv); - - err = pci_set_dma_mask(pci_dev, DMA_BIT_MASK(32)); - if (err) { - printk(KERN_WARNING DRV_NAME - "Error calling pci_set_dma_mask.\n"); - pci_disable_device(pci_dev); - return err; - } - - err = pci_request_regions(pci_dev, DRV_NAME); - if (err) { - printk(KERN_WARNING DRV_NAME - "Error calling pci_request_regions.\n"); - pci_disable_device(pci_dev); - return err; - } - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_read_config_dword(pci_dev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff); - - pci_set_power_state(pci_dev, PCI_D0); - - if (!ipw2100_hw_is_adapter_in_system(dev)) { - printk(KERN_WARNING DRV_NAME - "Device not found via register read.\n"); - err = -ENODEV; - goto fail; - } - - SET_NETDEV_DEV(dev, &pci_dev->dev); - - /* Force interrupts to be shut off on the device */ - priv->status |= STATUS_INT_ENABLED; - ipw2100_disable_interrupts(priv); - - /* Allocate and initialize the Tx/Rx queues and lists */ - if (ipw2100_queues_allocate(priv)) { - printk(KERN_WARNING DRV_NAME - "Error calling ipw2100_queues_allocate.\n"); - err = -ENOMEM; - goto fail; - } - ipw2100_queues_initialize(priv); - - err = request_irq(pci_dev->irq, - ipw2100_interrupt, IRQF_SHARED, dev->name, priv); - if (err) { - printk(KERN_WARNING DRV_NAME - "Error calling request_irq: %d.\n", pci_dev->irq); - goto fail; - } - dev->irq = pci_dev->irq; - - IPW_DEBUG_INFO("Attempting to register device...\n"); - - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2100 Network Connection\n"); - - /* Bring up the interface. Pre 0.46, after we registered the - * network device we would call ipw2100_up. This introduced a race - * condition with newer hotplug configurations (network was coming - * up and making calls before the device was initialized). - * - * If we called ipw2100_up before we registered the device, then the - * device name wasn't registered. So, we instead use the net_dev->init - * member to call a function that then just turns and calls ipw2100_up. - * net_dev->init is called after name allocation but before the - * notifier chain is called */ - err = register_netdev(dev); - if (err) { - printk(KERN_WARNING DRV_NAME - "Error calling register_netdev.\n"); - goto fail; - } - - mutex_lock(&priv->action_mutex); - registered = 1; - - IPW_DEBUG_INFO("%s: Bound to %s\n", dev->name, pci_name(pci_dev)); - - /* perform this after register_netdev so that dev->name is set */ - err = sysfs_create_group(&pci_dev->dev.kobj, &ipw2100_attribute_group); - if (err) - goto fail_unlock; - - /* If the RF Kill switch is disabled, go ahead and complete the - * startup sequence */ - if (!(priv->status & STATUS_RF_KILL_MASK)) { - /* Enable the adapter - sends HOST_COMPLETE */ - if (ipw2100_enable_adapter(priv)) { - printk(KERN_WARNING DRV_NAME - ": %s: failed in call to enable adapter.\n", - priv->net_dev->name); - ipw2100_hw_stop_adapter(priv); - err = -EIO; - goto fail_unlock; - } - - /* Start a scan . . . */ - ipw2100_set_scan_options(priv); - ipw2100_start_scan(priv); - } - - IPW_DEBUG_INFO("exit\n"); - - priv->status |= STATUS_INITIALIZED; - - mutex_unlock(&priv->action_mutex); - - return 0; - - fail_unlock: - mutex_unlock(&priv->action_mutex); - - fail: - if (dev) { - if (registered) - unregister_netdev(dev); - - ipw2100_hw_stop_adapter(priv); - - ipw2100_disable_interrupts(priv); - - if (dev->irq) - free_irq(dev->irq, priv); - - ipw2100_kill_workqueue(priv); - - /* These are safe to call even if they weren't allocated */ - ipw2100_queues_free(priv); - sysfs_remove_group(&pci_dev->dev.kobj, - &ipw2100_attribute_group); - - free_ieee80211(dev); - pci_set_drvdata(pci_dev, NULL); - } - - if (base_addr) - iounmap(base_addr); - - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - - return err; -} - -static void __devexit ipw2100_pci_remove_one(struct pci_dev *pci_dev) -{ - struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); - struct net_device *dev; - - if (priv) { - mutex_lock(&priv->action_mutex); - - priv->status &= ~STATUS_INITIALIZED; - - dev = priv->net_dev; - sysfs_remove_group(&pci_dev->dev.kobj, - &ipw2100_attribute_group); - -#ifdef CONFIG_PM - if (ipw2100_firmware.version) - ipw2100_release_firmware(priv, &ipw2100_firmware); -#endif - /* Take down the hardware */ - ipw2100_down(priv); - - /* Release the mutex so that the network subsystem can - * complete any needed calls into the driver... */ - mutex_unlock(&priv->action_mutex); - - /* Unregister the device first - this results in close() - * being called if the device is open. If we free storage - * first, then close() will crash. */ - unregister_netdev(dev); - - /* ipw2100_down will ensure that there is no more pending work - * in the workqueue's, so we can safely remove them now. */ - ipw2100_kill_workqueue(priv); - - ipw2100_queues_free(priv); - - /* Free potential debugging firmware snapshot */ - ipw2100_snapshot_free(priv); - - if (dev->irq) - free_irq(dev->irq, priv); - - if (dev->base_addr) - iounmap((void __iomem *)dev->base_addr); - - free_ieee80211(dev); - } - - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - - IPW_DEBUG_INFO("exit\n"); -} - -#ifdef CONFIG_PM -static int ipw2100_suspend(struct pci_dev *pci_dev, pm_message_t state) -{ - struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); - struct net_device *dev = priv->net_dev; - - IPW_DEBUG_INFO("%s: Going into suspend...\n", dev->name); - - mutex_lock(&priv->action_mutex); - if (priv->status & STATUS_INITIALIZED) { - /* Take down the device; powers it off, etc. */ - ipw2100_down(priv); - } - - /* Remove the PRESENT state of the device */ - netif_device_detach(dev); - - pci_save_state(pci_dev); - pci_disable_device(pci_dev); - pci_set_power_state(pci_dev, PCI_D3hot); - - priv->suspend_at = get_seconds(); - - mutex_unlock(&priv->action_mutex); - - return 0; -} - -static int ipw2100_resume(struct pci_dev *pci_dev) -{ - struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); - struct net_device *dev = priv->net_dev; - int err; - u32 val; - - if (IPW2100_PM_DISABLED) - return 0; - - mutex_lock(&priv->action_mutex); - - IPW_DEBUG_INFO("%s: Coming out of suspend...\n", dev->name); - - pci_set_power_state(pci_dev, PCI_D0); - err = pci_enable_device(pci_dev); - if (err) { - printk(KERN_ERR "%s: pci_enable_device failed on resume\n", - dev->name); - mutex_unlock(&priv->action_mutex); - return err; - } - pci_restore_state(pci_dev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries - * from interfering with C3 CPU state. pci_restore_state won't help - * here since it only restores the first 64 bytes pci config header. - */ - pci_read_config_dword(pci_dev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pci_dev, 0x40, val & 0xffff00ff); - - /* Set the device back into the PRESENT state; this will also wake - * the queue of needed */ - netif_device_attach(dev); - - priv->suspend_time = get_seconds() - priv->suspend_at; - - /* Bring the device back up */ - if (!(priv->status & STATUS_RF_KILL_SW)) - ipw2100_up(priv, 0); - - mutex_unlock(&priv->action_mutex); - - return 0; -} -#endif - -static void ipw2100_shutdown(struct pci_dev *pci_dev) -{ - struct ipw2100_priv *priv = pci_get_drvdata(pci_dev); - - /* Take down the device; powers it off, etc. */ - ipw2100_down(priv); - - pci_disable_device(pci_dev); -} - -#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } - -static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = { - IPW2100_DEV_ID(0x2520), /* IN 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2521), /* IN 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2524), /* IN 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2525), /* IN 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2526), /* IN 2100A mPCI Gen A3 */ - IPW2100_DEV_ID(0x2522), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2523), /* IN 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2527), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2528), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2529), /* IN 2100 mPCI 3B */ - IPW2100_DEV_ID(0x252B), /* IN 2100 mPCI 3A */ - IPW2100_DEV_ID(0x252C), /* IN 2100 mPCI 3A */ - IPW2100_DEV_ID(0x252D), /* IN 2100 mPCI 3A */ - - IPW2100_DEV_ID(0x2550), /* IB 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2551), /* IB 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2553), /* IB 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2554), /* IB 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2555), /* IB 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x2560), /* DE 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2562), /* DE 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2563), /* DE 2100A mPCI 3A */ - IPW2100_DEV_ID(0x2561), /* DE 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2565), /* DE 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2566), /* DE 2100 mPCI 3A */ - IPW2100_DEV_ID(0x2567), /* DE 2100 mPCI 3A */ - - IPW2100_DEV_ID(0x2570), /* GA 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x2580), /* TO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2582), /* TO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2583), /* TO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2581), /* TO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2585), /* TO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2586), /* TO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2587), /* TO 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x2590), /* SO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2592), /* SO 2100A mPCI 3B */ - IPW2100_DEV_ID(0x2591), /* SO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2593), /* SO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2596), /* SO 2100 mPCI 3B */ - IPW2100_DEV_ID(0x2598), /* SO 2100 mPCI 3B */ - - IPW2100_DEV_ID(0x25A0), /* HP 2100 mPCI 3B */ - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, ipw2100_pci_id_table); - -static struct pci_driver ipw2100_pci_driver = { - .name = DRV_NAME, - .id_table = ipw2100_pci_id_table, - .probe = ipw2100_pci_init_one, - .remove = __devexit_p(ipw2100_pci_remove_one), -#ifdef CONFIG_PM - .suspend = ipw2100_suspend, - .resume = ipw2100_resume, -#endif - .shutdown = ipw2100_shutdown, -}; - -/** - * Initialize the ipw2100 driver/module - * - * @returns 0 if ok, < 0 errno node con error. - * - * Note: we cannot init the /proc stuff until the PCI driver is there, - * or we risk an unlikely race condition on someone accessing - * uninitialized data in the PCI dev struct through /proc. - */ -static int __init ipw2100_init(void) -{ - int ret; - - printk(KERN_INFO DRV_NAME ": %s, %s\n", DRV_DESCRIPTION, DRV_VERSION); - printk(KERN_INFO DRV_NAME ": %s\n", DRV_COPYRIGHT); - - ret = pci_register_driver(&ipw2100_pci_driver); - if (ret) - goto out; - - pm_qos_add_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100", - PM_QOS_DEFAULT_VALUE); -#ifdef CONFIG_IPW2100_DEBUG - ipw2100_debug_level = debug; - ret = driver_create_file(&ipw2100_pci_driver.driver, - &driver_attr_debug_level); -#endif - -out: - return ret; -} - -/** - * Cleanup ipw2100 driver registration - */ -static void __exit ipw2100_exit(void) -{ - /* FIXME: IPG: check that we have no instances of the devices open */ -#ifdef CONFIG_IPW2100_DEBUG - driver_remove_file(&ipw2100_pci_driver.driver, - &driver_attr_debug_level); -#endif - pci_unregister_driver(&ipw2100_pci_driver); - pm_qos_remove_requirement(PM_QOS_CPU_DMA_LATENCY, "ipw2100"); -} - -module_init(ipw2100_init); -module_exit(ipw2100_exit); - -#define WEXT_USECHANNELS 1 - -static const long ipw2100_frequencies[] = { - 2412, 2417, 2422, 2427, - 2432, 2437, 2442, 2447, - 2452, 2457, 2462, 2467, - 2472, 2484 -}; - -#define FREQ_COUNT ARRAY_SIZE(ipw2100_frequencies) - -static const long ipw2100_rates_11b[] = { - 1000000, - 2000000, - 5500000, - 11000000 -}; - -#define RATE_COUNT ARRAY_SIZE(ipw2100_rates_11b) - -static int ipw2100_wx_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - if (!(priv->status & STATUS_ASSOCIATED)) - strcpy(wrqu->name, "unassociated"); - else - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11b"); - - IPW_DEBUG_WX("Name: %s\n", wrqu->name); - return 0; -} - -static int ipw2100_wx_set_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct iw_freq *fwrq = &wrqu->freq; - int err = 0; - - if (priv->ieee->iw_mode == IW_MODE_INFRA) - return -EOPNOTSUPP; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - /* if setting by freq convert to channel */ - if (fwrq->e == 1) { - if ((fwrq->m >= (int)2.412e8 && fwrq->m <= (int)2.487e8)) { - int f = fwrq->m / 100000; - int c = 0; - - while ((c < REG_MAX_CHANNEL) && - (f != ipw2100_frequencies[c])) - c++; - - /* hack to fall through */ - fwrq->e = 0; - fwrq->m = c + 1; - } - } - - if (fwrq->e > 0 || fwrq->m > 1000) { - err = -EOPNOTSUPP; - goto done; - } else { /* Set the channel */ - IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); - err = ipw2100_set_channel(priv, fwrq->m, 0); - } - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - wrqu->freq.e = 0; - - /* If we are associated, trying to associate, or have a statically - * configured CHANNEL then return that; otherwise return ANY */ - if (priv->config & CFG_STATIC_CHANNEL || - priv->status & STATUS_ASSOCIATED) - wrqu->freq.m = priv->channel; - else - wrqu->freq.m = 0; - - IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); - return 0; - -} - -static int ipw2100_wx_set_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0; - - IPW_DEBUG_WX("SET Mode -> %d \n", wrqu->mode); - - if (wrqu->mode == priv->ieee->iw_mode) - return 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - switch (wrqu->mode) { -#ifdef CONFIG_IPW2100_MONITOR - case IW_MODE_MONITOR: - err = ipw2100_switch_mode(priv, IW_MODE_MONITOR); - break; -#endif /* CONFIG_IPW2100_MONITOR */ - case IW_MODE_ADHOC: - err = ipw2100_switch_mode(priv, IW_MODE_ADHOC); - break; - case IW_MODE_INFRA: - case IW_MODE_AUTO: - default: - err = ipw2100_switch_mode(priv, IW_MODE_INFRA); - break; - } - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - wrqu->mode = priv->ieee->iw_mode; - IPW_DEBUG_WX("GET Mode -> %d\n", wrqu->mode); - - return 0; -} - -#define POWER_MODES 5 - -/* Values are in microsecond */ -static const s32 timeout_duration[POWER_MODES] = { - 350000, - 250000, - 75000, - 37000, - 25000, -}; - -static const s32 period_duration[POWER_MODES] = { - 400000, - 700000, - 1000000, - 1000000, - 1000000 -}; - -static int ipw2100_wx_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - struct iw_range *range = (struct iw_range *)extra; - u16 val; - int i, level; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - /* Let's try to keep this struct in the same order as in - * linux/include/wireless.h - */ - - /* TODO: See what values we can set, and remove the ones we can't - * set, or fill them with some default data. - */ - - /* ~5 Mb/s real (802.11b) */ - range->throughput = 5 * 1000 * 1000; - -// range->sensitivity; /* signal level threshold range */ - - range->max_qual.qual = 100; - /* TODO: Find real max RSSI and stick here */ - range->max_qual.level = 0; - range->max_qual.noise = 0; - range->max_qual.updated = 7; /* Updated all three */ - - range->avg_qual.qual = 70; /* > 8% missed beacons is 'bad' */ - /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ - range->avg_qual.level = 20 + IPW2100_RSSI_TO_DBM; - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - - range->num_bitrates = RATE_COUNT; - - for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++) { - range->bitrate[i] = ipw2100_rates_11b[i]; - } - - range->min_rts = MIN_RTS_THRESHOLD; - range->max_rts = MAX_RTS_THRESHOLD; - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->min_pmp = period_duration[0]; /* Minimal PM period */ - range->max_pmp = period_duration[POWER_MODES - 1]; /* Maximal PM period */ - range->min_pmt = timeout_duration[POWER_MODES - 1]; /* Minimal PM timeout */ - range->max_pmt = timeout_duration[0]; /* Maximal PM timeout */ - - /* How to decode max/min PM period */ - range->pmp_flags = IW_POWER_PERIOD; - /* How to decode max/min PM period */ - range->pmt_flags = IW_POWER_TIMEOUT; - /* What PM options are supported */ - range->pm_capa = IW_POWER_TIMEOUT | IW_POWER_PERIOD; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; /* Different token sizes */ - range->num_encoding_sizes = 2; /* Number of entry in the list */ - range->max_encoding_tokens = WEP_KEYS; /* Max number of tokens */ -// range->encoding_login_index; /* token index for login token */ - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - range->txpower_capa = IW_TXPOW_DBM; - range->num_txpower = IW_MAX_TXPOWER; - for (i = 0, level = (IPW_TX_POWER_MAX_DBM * 16); - i < IW_MAX_TXPOWER; - i++, level -= - ((IPW_TX_POWER_MAX_DBM - - IPW_TX_POWER_MIN_DBM) * 16) / (IW_MAX_TXPOWER - 1)) - range->txpower[i] = level / 16; - } else { - range->txpower_capa = 0; - range->num_txpower = 0; - } - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 18; - -// range->retry_capa; /* What retry options are supported */ -// range->retry_flags; /* How to decode max/min retry limit */ -// range->r_time_flags; /* How to decode max/min retry life */ -// range->min_retry; /* Minimal number of retries */ -// range->max_retry; /* Maximal number of retries */ -// range->min_r_time; /* Minimal retry lifetime */ -// range->max_r_time; /* Maximal retry lifetime */ - - range->num_channels = FREQ_COUNT; - - val = 0; - for (i = 0; i < FREQ_COUNT; i++) { - // TODO: Include only legal frequencies for some countries -// if (local->channel_mask & (1 << i)) { - range->freq[val].i = i + 1; - range->freq[val].m = ipw2100_frequencies[i] * 100000; - range->freq[val].e = 1; - val++; -// } - if (val == IW_MAX_FREQUENCIES) - break; - } - range->num_frequency = val; - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWAP)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - IPW_DEBUG_WX("GET Range\n"); - - return 0; -} - -static int ipw2100_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0; - - static const unsigned char any[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - static const unsigned char off[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - // sanity checks - if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) - return -EINVAL; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || - !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { - /* we disable mandatory BSSID association */ - IPW_DEBUG_WX("exit - disable mandatory BSSID\n"); - priv->config &= ~CFG_STATIC_BSSID; - err = ipw2100_set_mandatory_bssid(priv, NULL, 0); - goto done; - } - - priv->config |= CFG_STATIC_BSSID; - memcpy(priv->mandatory_bssid_mac, wrqu->ap_addr.sa_data, ETH_ALEN); - - err = ipw2100_set_mandatory_bssid(priv, wrqu->ap_addr.sa_data, 0); - - IPW_DEBUG_WX("SET BSSID -> %pM\n", wrqu->ap_addr.sa_data); - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - /* If we are associated, trying to associate, or have a statically - * configured BSSID then return that; otherwise return ANY */ - if (priv->config & CFG_STATIC_BSSID || priv->status & STATUS_ASSOCIATED) { - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - memcpy(wrqu->ap_addr.sa_data, priv->bssid, ETH_ALEN); - } else - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - - IPW_DEBUG_WX("Getting WAP BSSID: %pM\n", wrqu->ap_addr.sa_data); - return 0; -} - -static int ipw2100_wx_set_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - char *essid = ""; /* ANY */ - int length = 0; - int err = 0; - DECLARE_SSID_BUF(ssid); - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (wrqu->essid.flags && wrqu->essid.length) { - length = wrqu->essid.length; - essid = extra; - } - - if (length == 0) { - IPW_DEBUG_WX("Setting ESSID to ANY\n"); - priv->config &= ~CFG_STATIC_ESSID; - err = ipw2100_set_essid(priv, NULL, 0, 0); - goto done; - } - - length = min(length, IW_ESSID_MAX_SIZE); - - priv->config |= CFG_STATIC_ESSID; - - if (priv->essid_len == length && !memcmp(priv->essid, extra, length)) { - IPW_DEBUG_WX("ESSID set to current ESSID.\n"); - err = 0; - goto done; - } - - IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", - print_ssid(ssid, essid, length), length); - - priv->essid_len = length; - memcpy(priv->essid, essid, priv->essid_len); - - err = ipw2100_set_essid(priv, essid, length, 0); - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - DECLARE_SSID_BUF(ssid); - - /* If we are associated, trying to associate, or have a statically - * configured ESSID then return that; otherwise return ANY */ - if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) { - IPW_DEBUG_WX("Getting essid: '%s'\n", - print_ssid(ssid, priv->essid, priv->essid_len)); - memcpy(extra, priv->essid, priv->essid_len); - wrqu->essid.length = priv->essid_len; - wrqu->essid.flags = 1; /* active */ - } else { - IPW_DEBUG_WX("Getting essid: ANY\n"); - wrqu->essid.length = 0; - wrqu->essid.flags = 0; /* active */ - } - - return 0; -} - -static int ipw2100_wx_set_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - if (wrqu->data.length > IW_ESSID_MAX_SIZE) - return -E2BIG; - - wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); - memset(priv->nick, 0, sizeof(priv->nick)); - memcpy(priv->nick, extra, wrqu->data.length); - - IPW_DEBUG_WX("SET Nickname -> %s \n", priv->nick); - - return 0; -} - -static int ipw2100_wx_get_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - wrqu->data.length = strlen(priv->nick); - memcpy(extra, priv->nick, wrqu->data.length); - wrqu->data.flags = 1; /* active */ - - IPW_DEBUG_WX("GET Nickname -> %s \n", extra); - - return 0; -} - -static int ipw2100_wx_set_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - u32 target_rate = wrqu->bitrate.value; - u32 rate; - int err = 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - rate = 0; - - if (target_rate == 1000000 || - (!wrqu->bitrate.fixed && target_rate > 1000000)) - rate |= TX_RATE_1_MBIT; - if (target_rate == 2000000 || - (!wrqu->bitrate.fixed && target_rate > 2000000)) - rate |= TX_RATE_2_MBIT; - if (target_rate == 5500000 || - (!wrqu->bitrate.fixed && target_rate > 5500000)) - rate |= TX_RATE_5_5_MBIT; - if (target_rate == 11000000 || - (!wrqu->bitrate.fixed && target_rate > 11000000)) - rate |= TX_RATE_11_MBIT; - if (rate == 0) - rate = DEFAULT_TX_RATES; - - err = ipw2100_set_tx_rates(priv, rate, 0); - - IPW_DEBUG_WX("SET Rate -> %04X \n", rate); - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int val; - unsigned int len = sizeof(val); - int err = 0; - - if (!(priv->status & STATUS_ENABLED) || - priv->status & STATUS_RF_KILL_MASK || - !(priv->status & STATUS_ASSOCIATED)) { - wrqu->bitrate.value = 0; - return 0; - } - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - err = ipw2100_get_ordinal(priv, IPW_ORD_CURRENT_TX_RATE, &val, &len); - if (err) { - IPW_DEBUG_WX("failed querying ordinals.\n"); - goto done; - } - - switch (val & TX_RATE_MASK) { - case TX_RATE_1_MBIT: - wrqu->bitrate.value = 1000000; - break; - case TX_RATE_2_MBIT: - wrqu->bitrate.value = 2000000; - break; - case TX_RATE_5_5_MBIT: - wrqu->bitrate.value = 5500000; - break; - case TX_RATE_11_MBIT: - wrqu->bitrate.value = 11000000; - break; - default: - wrqu->bitrate.value = 0; - } - - IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int value, err; - - /* Auto RTS not yet supported */ - if (wrqu->rts.fixed == 0) - return -EINVAL; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (wrqu->rts.disabled) - value = priv->rts_threshold | RTS_DISABLED; - else { - if (wrqu->rts.value < 1 || wrqu->rts.value > 2304) { - err = -EINVAL; - goto done; - } - value = wrqu->rts.value; - } - - err = ipw2100_set_rts_threshold(priv, value); - - IPW_DEBUG_WX("SET RTS Threshold -> 0x%08X \n", value); - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - wrqu->rts.value = priv->rts_threshold & ~RTS_DISABLED; - wrqu->rts.fixed = 1; /* no auto select */ - - /* If RTS is set to the default value, then it is disabled */ - wrqu->rts.disabled = (priv->rts_threshold & RTS_DISABLED) ? 1 : 0; - - IPW_DEBUG_WX("GET RTS Threshold -> 0x%08X \n", wrqu->rts.value); - - return 0; -} - -static int ipw2100_wx_set_txpow(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0, value; - - if (ipw_radio_kill_sw(priv, wrqu->txpower.disabled)) - return -EINPROGRESS; - - if (priv->ieee->iw_mode != IW_MODE_ADHOC) - return 0; - - if ((wrqu->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) - return -EINVAL; - - if (wrqu->txpower.fixed == 0) - value = IPW_TX_POWER_DEFAULT; - else { - if (wrqu->txpower.value < IPW_TX_POWER_MIN_DBM || - wrqu->txpower.value > IPW_TX_POWER_MAX_DBM) - return -EINVAL; - - value = wrqu->txpower.value; - } - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - err = ipw2100_set_tx_power(priv, value); - - IPW_DEBUG_WX("SET TX Power -> %d \n", value); - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_txpow(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - wrqu->txpower.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; - - if (priv->tx_power == IPW_TX_POWER_DEFAULT) { - wrqu->txpower.fixed = 0; - wrqu->txpower.value = IPW_TX_POWER_MAX_DBM; - } else { - wrqu->txpower.fixed = 1; - wrqu->txpower.value = priv->tx_power; - } - - wrqu->txpower.flags = IW_TXPOW_DBM; - - IPW_DEBUG_WX("GET TX Power -> %d \n", wrqu->txpower.value); - - return 0; -} - -static int ipw2100_wx_set_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - if (!wrqu->frag.fixed) - return -EINVAL; - - if (wrqu->frag.disabled) { - priv->frag_threshold |= FRAG_DISABLED; - priv->ieee->fts = DEFAULT_FTS; - } else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) - return -EINVAL; - - priv->ieee->fts = wrqu->frag.value & ~0x1; - priv->frag_threshold = priv->ieee->fts; - } - - IPW_DEBUG_WX("SET Frag Threshold -> %d \n", priv->ieee->fts); - - return 0; -} - -static int ipw2100_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - wrqu->frag.value = priv->frag_threshold & ~FRAG_DISABLED; - wrqu->frag.fixed = 0; /* no auto select */ - wrqu->frag.disabled = (priv->frag_threshold & FRAG_DISABLED) ? 1 : 0; - - IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); - - return 0; -} - -static int ipw2100_wx_set_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0; - - if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled) - return -EINVAL; - - if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) - return 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (wrqu->retry.flags & IW_RETRY_SHORT) { - err = ipw2100_set_short_retry(priv, wrqu->retry.value); - IPW_DEBUG_WX("SET Short Retry Limit -> %d \n", - wrqu->retry.value); - goto done; - } - - if (wrqu->retry.flags & IW_RETRY_LONG) { - err = ipw2100_set_long_retry(priv, wrqu->retry.value); - IPW_DEBUG_WX("SET Long Retry Limit -> %d \n", - wrqu->retry.value); - goto done; - } - - err = ipw2100_set_short_retry(priv, wrqu->retry.value); - if (!err) - err = ipw2100_set_long_retry(priv, wrqu->retry.value); - - IPW_DEBUG_WX("SET Both Retry Limits -> %d \n", wrqu->retry.value); - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - wrqu->retry.disabled = 0; /* can't be disabled */ - - if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) - return -EINVAL; - - if (wrqu->retry.flags & IW_RETRY_LONG) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - wrqu->retry.value = priv->long_retry_limit; - } else { - wrqu->retry.flags = - (priv->short_retry_limit != - priv->long_retry_limit) ? - IW_RETRY_LIMIT | IW_RETRY_SHORT : IW_RETRY_LIMIT; - - wrqu->retry.value = priv->short_retry_limit; - } - - IPW_DEBUG_WX("GET Retry -> %d \n", wrqu->retry.value); - - return 0; -} - -static int ipw2100_wx_set_scan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - IPW_DEBUG_WX("Initiating scan...\n"); - - priv->user_requested_scan = 1; - if (ipw2100_set_scan_options(priv) || ipw2100_start_scan(priv)) { - IPW_DEBUG_WX("Start scan failed.\n"); - - /* TODO: Mark a scan as pending so when hardware initialized - * a scan starts */ - } - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_scan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - return libipw_wx_get_scan(priv->ieee, info, wrqu, extra); -} - -/* - * Implementation based on code in hostap-driver v0.1.3 hostap_ioctl.c - */ -static int ipw2100_wx_set_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - /* - * No check of STATUS_INITIALIZED required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - return libipw_wx_set_encode(priv->ieee, info, wrqu, key); -} - -static int ipw2100_wx_get_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - return libipw_wx_get_encode(priv->ieee, info, wrqu, key); -} - -static int ipw2100_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (wrqu->power.disabled) { - priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); - err = ipw2100_set_power_mode(priv, IPW_POWER_MODE_CAM); - IPW_DEBUG_WX("SET Power Management Mode -> off\n"); - goto done; - } - - switch (wrqu->power.flags & IW_POWER_MODE) { - case IW_POWER_ON: /* If not specified */ - case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitly state all */ - break; - default: /* Otherwise we don't support it */ - IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", - wrqu->power.flags); - err = -EOPNOTSUPP; - goto done; - } - - /* If the user hasn't specified a power management mode yet, default - * to BATTERY */ - priv->power_mode = IPW_POWER_ENABLED | priv->power_mode; - err = ipw2100_set_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); - - IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); - - done: - mutex_unlock(&priv->action_mutex); - return err; - -} - -static int ipw2100_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - if (!(priv->power_mode & IPW_POWER_ENABLED)) - wrqu->power.disabled = 1; - else { - wrqu->power.disabled = 0; - wrqu->power.flags = 0; - } - - IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); - - return 0; -} - -/* - * WE-18 WPA support - */ - -/* SIOCSIWGENIE */ -static int ipw2100_wx_set_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - - struct ipw2100_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - u8 *buf; - - if (!ieee->wpa_enabled) - return -EOPNOTSUPP; - - if (wrqu->data.length > MAX_WPA_IE_LEN || - (wrqu->data.length && extra == NULL)) - return -EINVAL; - - if (wrqu->data.length) { - buf = kmemdup(extra, wrqu->data.length, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = wrqu->data.length; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - - ipw2100_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); - - return 0; -} - -/* SIOCGIWGENIE */ -static int ipw2100_wx_get_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - - if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { - wrqu->data.length = 0; - return 0; - } - - if (wrqu->data.length < ieee->wpa_ie_len) - return -E2BIG; - - wrqu->data.length = ieee->wpa_ie_len; - memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); - - return 0; -} - -/* SIOCSIWAUTH */ -static int ipw2100_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - struct iw_param *param = &wrqu->param; - struct lib80211_crypt_data *crypt; - unsigned long flags; - int ret = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* - * ipw2200 does not use these parameters - */ - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; - if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) - break; - - flags = crypt->ops->get_flags(crypt->priv); - - if (param->value) - flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; - else - flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; - - crypt->ops->set_flags(flags, crypt->priv); - - break; - - case IW_AUTH_DROP_UNENCRYPTED:{ - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - struct libipw_security sec = { - .flags = SEC_ENABLED, - .enabled = param->value, - }; - priv->ieee->drop_unencrypted = param->value; - /* We only change SEC_LEVEL for open mode. Others - * are set by ipw_wpa_set_encryption. - */ - if (!param->value) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_0; - } else { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } - if (priv->ieee->set_security) - priv->ieee->set_security(priv->ieee->dev, &sec); - break; - } - - case IW_AUTH_80211_AUTH_ALG: - ret = ipw2100_wpa_set_auth_algs(priv, param->value); - break; - - case IW_AUTH_WPA_ENABLED: - ret = ipw2100_wpa_enable(priv, param->value); - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ieee->ieee802_1x = param->value; - break; - - //case IW_AUTH_ROAMING_CONTROL: - case IW_AUTH_PRIVACY_INVOKED: - ieee->privacy_invoked = param->value; - break; - - default: - return -EOPNOTSUPP; - } - return ret; -} - -/* SIOCGIWAUTH */ -static int ipw2100_wx_get_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - struct lib80211_crypt_data *crypt; - struct iw_param *param = &wrqu->param; - int ret = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* - * wpa_supplicant will control these internally - */ - ret = -EOPNOTSUPP; - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; - if (!crypt || !crypt->ops->get_flags) { - IPW_DEBUG_WARNING("Can't get TKIP countermeasures: " - "crypt not set!\n"); - break; - } - - param->value = (crypt->ops->get_flags(crypt->priv) & - IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0; - - break; - - case IW_AUTH_DROP_UNENCRYPTED: - param->value = ieee->drop_unencrypted; - break; - - case IW_AUTH_80211_AUTH_ALG: - param->value = priv->ieee->sec.auth_mode; - break; - - case IW_AUTH_WPA_ENABLED: - param->value = ieee->wpa_enabled; - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - param->value = ieee->ieee802_1x; - break; - - case IW_AUTH_ROAMING_CONTROL: - case IW_AUTH_PRIVACY_INVOKED: - param->value = ieee->privacy_invoked; - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - -/* SIOCSIWENCODEEXT */ -static int ipw2100_wx_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - return libipw_wx_set_encodeext(priv->ieee, info, wrqu, extra); -} - -/* SIOCGIWENCODEEXT */ -static int ipw2100_wx_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - return libipw_wx_get_encodeext(priv->ieee, info, wrqu, extra); -} - -/* SIOCSIWMLME */ -static int ipw2100_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - struct iw_mlme *mlme = (struct iw_mlme *)extra; - __le16 reason; - - reason = cpu_to_le16(mlme->reason_code); - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - // silently ignore - break; - - case IW_MLME_DISASSOC: - ipw2100_disassociate_bssid(priv); - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - -/* - * - * IWPRIV handlers - * - */ -#ifdef CONFIG_IPW2100_MONITOR -static int ipw2100_wx_set_promisc(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int *parms = (int *)extra; - int enable = (parms[0] > 0); - int err = 0; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (enable) { - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - err = ipw2100_set_channel(priv, parms[1], 0); - goto done; - } - priv->channel = parms[1]; - err = ipw2100_switch_mode(priv, IW_MODE_MONITOR); - } else { - if (priv->ieee->iw_mode == IW_MODE_MONITOR) - err = ipw2100_switch_mode(priv, priv->last_mode); - } - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_reset(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - if (priv->status & STATUS_INITIALIZED) - schedule_reset(priv); - return 0; -} - -#endif - -static int ipw2100_wx_set_powermode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err = 0, mode = *(int *)extra; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if ((mode < 0) || (mode > POWER_MODES)) - mode = IPW_POWER_AUTO; - - if (IPW_POWER_LEVEL(priv->power_mode) != mode) - err = ipw2100_set_power_mode(priv, mode); - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -#define MAX_POWER_STRING 80 -static int ipw2100_wx_get_powermode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - int level = IPW_POWER_LEVEL(priv->power_mode); - s32 timeout, period; - - if (!(priv->power_mode & IPW_POWER_ENABLED)) { - snprintf(extra, MAX_POWER_STRING, - "Power save level: %d (Off)", level); - } else { - switch (level) { - case IPW_POWER_MODE_CAM: - snprintf(extra, MAX_POWER_STRING, - "Power save level: %d (None)", level); - break; - case IPW_POWER_AUTO: - snprintf(extra, MAX_POWER_STRING, - "Power save level: %d (Auto)", level); - break; - default: - timeout = timeout_duration[level - 1] / 1000; - period = period_duration[level - 1] / 1000; - snprintf(extra, MAX_POWER_STRING, - "Power save level: %d " - "(Timeout %dms, Period %dms)", - level, timeout, period); - } - } - - wrqu->data.length = strlen(extra) + 1; - - return 0; -} - -static int ipw2100_wx_set_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err, mode = *(int *)extra; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (mode == 1) - priv->config |= CFG_LONG_PREAMBLE; - else if (mode == 0) - priv->config &= ~CFG_LONG_PREAMBLE; - else { - err = -EINVAL; - goto done; - } - - err = ipw2100_system_config(priv, 0); - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - if (priv->config & CFG_LONG_PREAMBLE) - snprintf(wrqu->name, IFNAMSIZ, "long (1)"); - else - snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); - - return 0; -} - -#ifdef CONFIG_IPW2100_MONITOR -static int ipw2100_wx_set_crc_check(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw2100_priv *priv = libipw_priv(dev); - int err, mode = *(int *)extra; - - mutex_lock(&priv->action_mutex); - if (!(priv->status & STATUS_INITIALIZED)) { - err = -EIO; - goto done; - } - - if (mode == 1) - priv->config |= CFG_CRC_CHECK; - else if (mode == 0) - priv->config &= ~CFG_CRC_CHECK; - else { - err = -EINVAL; - goto done; - } - err = 0; - - done: - mutex_unlock(&priv->action_mutex); - return err; -} - -static int ipw2100_wx_get_crc_check(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * This can be called at any time. No action lock required - */ - - struct ipw2100_priv *priv = libipw_priv(dev); - - if (priv->config & CFG_CRC_CHECK) - snprintf(wrqu->name, IFNAMSIZ, "CRC checked (1)"); - else - snprintf(wrqu->name, IFNAMSIZ, "CRC ignored (0)"); - - return 0; -} -#endif /* CONFIG_IPW2100_MONITOR */ - -static iw_handler ipw2100_wx_handlers[] = { - NULL, /* SIOCSIWCOMMIT */ - ipw2100_wx_get_name, /* SIOCGIWNAME */ - NULL, /* SIOCSIWNWID */ - NULL, /* SIOCGIWNWID */ - ipw2100_wx_set_freq, /* SIOCSIWFREQ */ - ipw2100_wx_get_freq, /* SIOCGIWFREQ */ - ipw2100_wx_set_mode, /* SIOCSIWMODE */ - ipw2100_wx_get_mode, /* SIOCGIWMODE */ - NULL, /* SIOCSIWSENS */ - NULL, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - ipw2100_wx_get_range, /* SIOCGIWRANGE */ - NULL, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ - NULL, /* SIOCGIWTHRSPY */ - NULL, /* SIOCWIWTHRSPY */ - ipw2100_wx_set_wap, /* SIOCSIWAP */ - ipw2100_wx_get_wap, /* SIOCGIWAP */ - ipw2100_wx_set_mlme, /* SIOCSIWMLME */ - NULL, /* SIOCGIWAPLIST -- deprecated */ - ipw2100_wx_set_scan, /* SIOCSIWSCAN */ - ipw2100_wx_get_scan, /* SIOCGIWSCAN */ - ipw2100_wx_set_essid, /* SIOCSIWESSID */ - ipw2100_wx_get_essid, /* SIOCGIWESSID */ - ipw2100_wx_set_nick, /* SIOCSIWNICKN */ - ipw2100_wx_get_nick, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - ipw2100_wx_set_rate, /* SIOCSIWRATE */ - ipw2100_wx_get_rate, /* SIOCGIWRATE */ - ipw2100_wx_set_rts, /* SIOCSIWRTS */ - ipw2100_wx_get_rts, /* SIOCGIWRTS */ - ipw2100_wx_set_frag, /* SIOCSIWFRAG */ - ipw2100_wx_get_frag, /* SIOCGIWFRAG */ - ipw2100_wx_set_txpow, /* SIOCSIWTXPOW */ - ipw2100_wx_get_txpow, /* SIOCGIWTXPOW */ - ipw2100_wx_set_retry, /* SIOCSIWRETRY */ - ipw2100_wx_get_retry, /* SIOCGIWRETRY */ - ipw2100_wx_set_encode, /* SIOCSIWENCODE */ - ipw2100_wx_get_encode, /* SIOCGIWENCODE */ - ipw2100_wx_set_power, /* SIOCSIWPOWER */ - ipw2100_wx_get_power, /* SIOCGIWPOWER */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - ipw2100_wx_set_genie, /* SIOCSIWGENIE */ - ipw2100_wx_get_genie, /* SIOCGIWGENIE */ - ipw2100_wx_set_auth, /* SIOCSIWAUTH */ - ipw2100_wx_get_auth, /* SIOCGIWAUTH */ - ipw2100_wx_set_encodeext, /* SIOCSIWENCODEEXT */ - ipw2100_wx_get_encodeext, /* SIOCGIWENCODEEXT */ - NULL, /* SIOCSIWPMKSA */ -}; - -#define IPW2100_PRIV_SET_MONITOR SIOCIWFIRSTPRIV -#define IPW2100_PRIV_RESET SIOCIWFIRSTPRIV+1 -#define IPW2100_PRIV_SET_POWER SIOCIWFIRSTPRIV+2 -#define IPW2100_PRIV_GET_POWER SIOCIWFIRSTPRIV+3 -#define IPW2100_PRIV_SET_LONGPREAMBLE SIOCIWFIRSTPRIV+4 -#define IPW2100_PRIV_GET_LONGPREAMBLE SIOCIWFIRSTPRIV+5 -#define IPW2100_PRIV_SET_CRC_CHECK SIOCIWFIRSTPRIV+6 -#define IPW2100_PRIV_GET_CRC_CHECK SIOCIWFIRSTPRIV+7 - -static const struct iw_priv_args ipw2100_private_args[] = { - -#ifdef CONFIG_IPW2100_MONITOR - { - IPW2100_PRIV_SET_MONITOR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, - { - IPW2100_PRIV_RESET, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, -#endif /* CONFIG_IPW2100_MONITOR */ - - { - IPW2100_PRIV_SET_POWER, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_power"}, - { - IPW2100_PRIV_GET_POWER, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_POWER_STRING, - "get_power"}, - { - IPW2100_PRIV_SET_LONGPREAMBLE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_preamble"}, - { - IPW2100_PRIV_GET_LONGPREAMBLE, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_preamble"}, -#ifdef CONFIG_IPW2100_MONITOR - { - IPW2100_PRIV_SET_CRC_CHECK, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "set_crc_check"}, - { - IPW2100_PRIV_GET_CRC_CHECK, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, "get_crc_check"}, -#endif /* CONFIG_IPW2100_MONITOR */ -}; - -static iw_handler ipw2100_private_handler[] = { -#ifdef CONFIG_IPW2100_MONITOR - ipw2100_wx_set_promisc, - ipw2100_wx_reset, -#else /* CONFIG_IPW2100_MONITOR */ - NULL, - NULL, -#endif /* CONFIG_IPW2100_MONITOR */ - ipw2100_wx_set_powermode, - ipw2100_wx_get_powermode, - ipw2100_wx_set_preamble, - ipw2100_wx_get_preamble, -#ifdef CONFIG_IPW2100_MONITOR - ipw2100_wx_set_crc_check, - ipw2100_wx_get_crc_check, -#else /* CONFIG_IPW2100_MONITOR */ - NULL, - NULL, -#endif /* CONFIG_IPW2100_MONITOR */ -}; - -/* - * Get wireless statistics. - * Called by /proc/net/wireless - * Also called by SIOCGIWSTATS - */ -static struct iw_statistics *ipw2100_wx_wireless_stats(struct net_device *dev) -{ - enum { - POOR = 30, - FAIR = 60, - GOOD = 80, - VERY_GOOD = 90, - EXCELLENT = 95, - PERFECT = 100 - }; - int rssi_qual; - int tx_qual; - int beacon_qual; - int quality; - - struct ipw2100_priv *priv = libipw_priv(dev); - struct iw_statistics *wstats; - u32 rssi, tx_retries, missed_beacons, tx_failures; - u32 ord_len = sizeof(u32); - - if (!priv) - return (struct iw_statistics *)NULL; - - wstats = &priv->wstats; - - /* if hw is disabled, then ipw2100_get_ordinal() can't be called. - * ipw2100_wx_wireless_stats seems to be called before fw is - * initialized. STATUS_ASSOCIATED will only be set if the hw is up - * and associated; if not associcated, the values are all meaningless - * anyway, so set them all to NULL and INVALID */ - if (!(priv->status & STATUS_ASSOCIATED)) { - wstats->miss.beacon = 0; - wstats->discard.retries = 0; - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = 7; - wstats->qual.updated |= IW_QUAL_NOISE_INVALID | - IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; - return wstats; - } - - if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_MISSED_BCNS, - &missed_beacons, &ord_len)) - goto fail_get_ordinal; - - /* If we don't have a connection the quality and level is 0 */ - if (!(priv->status & STATUS_ASSOCIATED)) { - wstats->qual.qual = 0; - wstats->qual.level = 0; - } else { - if (ipw2100_get_ordinal(priv, IPW_ORD_RSSI_AVG_CURR, - &rssi, &ord_len)) - goto fail_get_ordinal; - wstats->qual.level = rssi + IPW2100_RSSI_TO_DBM; - if (rssi < 10) - rssi_qual = rssi * POOR / 10; - else if (rssi < 15) - rssi_qual = (rssi - 10) * (FAIR - POOR) / 5 + POOR; - else if (rssi < 20) - rssi_qual = (rssi - 15) * (GOOD - FAIR) / 5 + FAIR; - else if (rssi < 30) - rssi_qual = (rssi - 20) * (VERY_GOOD - GOOD) / - 10 + GOOD; - else - rssi_qual = (rssi - 30) * (PERFECT - VERY_GOOD) / - 10 + VERY_GOOD; - - if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_PERCENT_RETRIES, - &tx_retries, &ord_len)) - goto fail_get_ordinal; - - if (tx_retries > 75) - tx_qual = (90 - tx_retries) * POOR / 15; - else if (tx_retries > 70) - tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR; - else if (tx_retries > 65) - tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; - else if (tx_retries > 50) - tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / - 15 + GOOD; - else - tx_qual = (50 - tx_retries) * - (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; - - if (missed_beacons > 50) - beacon_qual = (60 - missed_beacons) * POOR / 10; - else if (missed_beacons > 40) - beacon_qual = (50 - missed_beacons) * (FAIR - POOR) / - 10 + POOR; - else if (missed_beacons > 32) - beacon_qual = (40 - missed_beacons) * (GOOD - FAIR) / - 18 + FAIR; - else if (missed_beacons > 20) - beacon_qual = (32 - missed_beacons) * - (VERY_GOOD - GOOD) / 20 + GOOD; - else - beacon_qual = (20 - missed_beacons) * - (PERFECT - VERY_GOOD) / 20 + VERY_GOOD; - - quality = min(tx_qual, rssi_qual); - quality = min(beacon_qual, quality); - -#ifdef CONFIG_IPW2100_DEBUG - if (beacon_qual == quality) - IPW_DEBUG_WX("Quality clamped by Missed Beacons\n"); - else if (tx_qual == quality) - IPW_DEBUG_WX("Quality clamped by Tx Retries\n"); - else if (quality != 100) - IPW_DEBUG_WX("Quality clamped by Signal Strength\n"); - else - IPW_DEBUG_WX("Quality not clamped.\n"); -#endif - - wstats->qual.qual = quality; - wstats->qual.level = rssi + IPW2100_RSSI_TO_DBM; - } - - wstats->qual.noise = 0; - wstats->qual.updated = 7; - wstats->qual.updated |= IW_QUAL_NOISE_INVALID; - - /* FIXME: this is percent and not a # */ - wstats->miss.beacon = missed_beacons; - - if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURES, - &tx_failures, &ord_len)) - goto fail_get_ordinal; - wstats->discard.retries = tx_failures; - - return wstats; - - fail_get_ordinal: - IPW_DEBUG_WX("failed querying ordinals.\n"); - - return (struct iw_statistics *)NULL; -} - -static struct iw_handler_def ipw2100_wx_handler_def = { - .standard = ipw2100_wx_handlers, - .num_standard = ARRAY_SIZE(ipw2100_wx_handlers), - .num_private = ARRAY_SIZE(ipw2100_private_handler), - .num_private_args = ARRAY_SIZE(ipw2100_private_args), - .private = (iw_handler *) ipw2100_private_handler, - .private_args = (struct iw_priv_args *)ipw2100_private_args, - .get_wireless_stats = ipw2100_wx_wireless_stats, -}; - -static void ipw2100_wx_event_work(struct work_struct *work) -{ - struct ipw2100_priv *priv = - container_of(work, struct ipw2100_priv, wx_event_work.work); - union iwreq_data wrqu; - unsigned int len = ETH_ALEN; - - if (priv->status & STATUS_STOPPING) - return; - - mutex_lock(&priv->action_mutex); - - IPW_DEBUG_WX("enter\n"); - - mutex_unlock(&priv->action_mutex); - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - /* Fetch BSSID from the hardware */ - if (!(priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) || - priv->status & STATUS_RF_KILL_MASK || - ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, - &priv->bssid, &len)) { - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - } else { - /* We now have the BSSID, so can finish setting to the full - * associated state */ - memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); - memcpy(priv->ieee->bssid, priv->bssid, ETH_ALEN); - priv->status &= ~STATUS_ASSOCIATING; - priv->status |= STATUS_ASSOCIATED; - netif_carrier_on(priv->net_dev); - netif_wake_queue(priv->net_dev); - } - - if (!(priv->status & STATUS_ASSOCIATED)) { - IPW_DEBUG_WX("Configuring ESSID\n"); - mutex_lock(&priv->action_mutex); - /* This is a disassociation event, so kick the firmware to - * look for another AP */ - if (priv->config & CFG_STATIC_ESSID) - ipw2100_set_essid(priv, priv->essid, priv->essid_len, - 0); - else - ipw2100_set_essid(priv, NULL, 0, 0); - mutex_unlock(&priv->action_mutex); - } - - wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); -} - -#define IPW2100_FW_MAJOR_VERSION 1 -#define IPW2100_FW_MINOR_VERSION 3 - -#define IPW2100_FW_MINOR(x) ((x & 0xff) >> 8) -#define IPW2100_FW_MAJOR(x) (x & 0xff) - -#define IPW2100_FW_VERSION ((IPW2100_FW_MINOR_VERSION << 8) | \ - IPW2100_FW_MAJOR_VERSION) - -#define IPW2100_FW_PREFIX "ipw2100-" __stringify(IPW2100_FW_MAJOR_VERSION) \ -"." __stringify(IPW2100_FW_MINOR_VERSION) - -#define IPW2100_FW_NAME(x) IPW2100_FW_PREFIX "" x ".fw" - -/* - -BINARY FIRMWARE HEADER FORMAT - -offset length desc -0 2 version -2 2 mode == 0:BSS,1:IBSS,2:MONITOR -4 4 fw_len -8 4 uc_len -C fw_len firmware data -12 + fw_len uc_len microcode data - -*/ - -struct ipw2100_fw_header { - short version; - short mode; - unsigned int fw_size; - unsigned int uc_size; -} __attribute__ ((packed)); - -static int ipw2100_mod_firmware_load(struct ipw2100_fw *fw) -{ - struct ipw2100_fw_header *h = - (struct ipw2100_fw_header *)fw->fw_entry->data; - - if (IPW2100_FW_MAJOR(h->version) != IPW2100_FW_MAJOR_VERSION) { - printk(KERN_WARNING DRV_NAME ": Firmware image not compatible " - "(detected version id of %u). " - "See Documentation/networking/README.ipw2100\n", - h->version); - return 1; - } - - fw->version = h->version; - fw->fw.data = fw->fw_entry->data + sizeof(struct ipw2100_fw_header); - fw->fw.size = h->fw_size; - fw->uc.data = fw->fw.data + h->fw_size; - fw->uc.size = h->uc_size; - - return 0; -} - -static int ipw2100_get_firmware(struct ipw2100_priv *priv, - struct ipw2100_fw *fw) -{ - char *fw_name; - int rc; - - IPW_DEBUG_INFO("%s: Using hotplug firmware load.\n", - priv->net_dev->name); - - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - fw_name = IPW2100_FW_NAME("-i"); - break; -#ifdef CONFIG_IPW2100_MONITOR - case IW_MODE_MONITOR: - fw_name = IPW2100_FW_NAME("-p"); - break; -#endif - case IW_MODE_INFRA: - default: - fw_name = IPW2100_FW_NAME(""); - break; - } - - rc = request_firmware(&fw->fw_entry, fw_name, &priv->pci_dev->dev); - - if (rc < 0) { - printk(KERN_ERR DRV_NAME ": " - "%s: Firmware '%s' not available or load failed.\n", - priv->net_dev->name, fw_name); - return rc; - } - IPW_DEBUG_INFO("firmware data %p size %zd\n", fw->fw_entry->data, - fw->fw_entry->size); - - ipw2100_mod_firmware_load(fw); - - return 0; -} - -static void ipw2100_release_firmware(struct ipw2100_priv *priv, - struct ipw2100_fw *fw) -{ - fw->version = 0; - if (fw->fw_entry) - release_firmware(fw->fw_entry); - fw->fw_entry = NULL; -} - -static int ipw2100_get_fwversion(struct ipw2100_priv *priv, char *buf, - size_t max) -{ - char ver[MAX_FW_VERSION_LEN]; - u32 len = MAX_FW_VERSION_LEN; - u32 tmp; - int i; - /* firmware version is an ascii string (max len of 14) */ - if (ipw2100_get_ordinal(priv, IPW_ORD_STAT_FW_VER_NUM, ver, &len)) - return -EIO; - tmp = max; - if (len >= max) - len = max - 1; - for (i = 0; i < len; i++) - buf[i] = ver[i]; - buf[i] = '\0'; - return tmp; -} - -static int ipw2100_get_ucodeversion(struct ipw2100_priv *priv, char *buf, - size_t max) -{ - u32 ver; - u32 len = sizeof(ver); - /* microcode version is a 32 bit integer */ - if (ipw2100_get_ordinal(priv, IPW_ORD_UCODE_VERSION, &ver, &len)) - return -EIO; - return snprintf(buf, max, "%08X", ver); -} - -/* - * On exit, the firmware will have been freed from the fw list - */ -static int ipw2100_fw_download(struct ipw2100_priv *priv, struct ipw2100_fw *fw) -{ - /* firmware is constructed of N contiguous entries, each entry is - * structured as: - * - * offset sie desc - * 0 4 address to write to - * 4 2 length of data run - * 6 length data - */ - unsigned int addr; - unsigned short len; - - const unsigned char *firmware_data = fw->fw.data; - unsigned int firmware_data_left = fw->fw.size; - - while (firmware_data_left > 0) { - addr = *(u32 *) (firmware_data); - firmware_data += 4; - firmware_data_left -= 4; - - len = *(u16 *) (firmware_data); - firmware_data += 2; - firmware_data_left -= 2; - - if (len > 32) { - printk(KERN_ERR DRV_NAME ": " - "Invalid firmware run-length of %d bytes\n", - len); - return -EINVAL; - } - - write_nic_memory(priv->net_dev, addr, len, firmware_data); - firmware_data += len; - firmware_data_left -= len; - } - - return 0; -} - -struct symbol_alive_response { - u8 cmd_id; - u8 seq_num; - u8 ucode_rev; - u8 eeprom_valid; - u16 valid_flags; - u8 IEEE_addr[6]; - u16 flags; - u16 pcb_rev; - u16 clock_settle_time; // 1us LSB - u16 powerup_settle_time; // 1us LSB - u16 hop_settle_time; // 1us LSB - u8 date[3]; // month, day, year - u8 time[2]; // hours, minutes - u8 ucode_valid; -}; - -static int ipw2100_ucode_download(struct ipw2100_priv *priv, - struct ipw2100_fw *fw) -{ - struct net_device *dev = priv->net_dev; - const unsigned char *microcode_data = fw->uc.data; - unsigned int microcode_data_left = fw->uc.size; - void __iomem *reg = (void __iomem *)dev->base_addr; - - struct symbol_alive_response response; - int i, j; - u8 data; - - /* Symbol control */ - write_nic_word(dev, IPW2100_CONTROL_REG, 0x703); - readl(reg); - write_nic_word(dev, IPW2100_CONTROL_REG, 0x707); - readl(reg); - - /* HW config */ - write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */ - readl(reg); - write_nic_byte(dev, 0x210014, 0x72); /* fifo width =16 */ - readl(reg); - - /* EN_CS_ACCESS bit to reset control store pointer */ - write_nic_byte(dev, 0x210000, 0x40); - readl(reg); - write_nic_byte(dev, 0x210000, 0x0); - readl(reg); - write_nic_byte(dev, 0x210000, 0x40); - readl(reg); - - /* copy microcode from buffer into Symbol */ - - while (microcode_data_left > 0) { - write_nic_byte(dev, 0x210010, *microcode_data++); - write_nic_byte(dev, 0x210010, *microcode_data++); - microcode_data_left -= 2; - } - - /* EN_CS_ACCESS bit to reset the control store pointer */ - write_nic_byte(dev, 0x210000, 0x0); - readl(reg); - - /* Enable System (Reg 0) - * first enable causes garbage in RX FIFO */ - write_nic_byte(dev, 0x210000, 0x0); - readl(reg); - write_nic_byte(dev, 0x210000, 0x80); - readl(reg); - - /* Reset External Baseband Reg */ - write_nic_word(dev, IPW2100_CONTROL_REG, 0x703); - readl(reg); - write_nic_word(dev, IPW2100_CONTROL_REG, 0x707); - readl(reg); - - /* HW Config (Reg 5) */ - write_nic_byte(dev, 0x210014, 0x72); // fifo width =16 - readl(reg); - write_nic_byte(dev, 0x210014, 0x72); // fifo width =16 - readl(reg); - - /* Enable System (Reg 0) - * second enable should be OK */ - write_nic_byte(dev, 0x210000, 0x00); // clear enable system - readl(reg); - write_nic_byte(dev, 0x210000, 0x80); // set enable system - - /* check Symbol is enabled - upped this from 5 as it wasn't always - * catching the update */ - for (i = 0; i < 10; i++) { - udelay(10); - - /* check Dino is enabled bit */ - read_nic_byte(dev, 0x210000, &data); - if (data & 0x1) - break; - } - - if (i == 10) { - printk(KERN_ERR DRV_NAME ": %s: Error initializing Symbol\n", - dev->name); - return -EIO; - } - - /* Get Symbol alive response */ - for (i = 0; i < 30; i++) { - /* Read alive response structure */ - for (j = 0; - j < (sizeof(struct symbol_alive_response) >> 1); j++) - read_nic_word(dev, 0x210004, ((u16 *) & response) + j); - - if ((response.cmd_id == 1) && (response.ucode_valid == 0x1)) - break; - udelay(10); - } - - if (i == 30) { - printk(KERN_ERR DRV_NAME - ": %s: No response from Symbol - hw not alive\n", - dev->name); - printk_buf(IPW_DL_ERROR, (u8 *) & response, sizeof(response)); - return -EIO; - } - - return 0; -} diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h deleted file mode 100644 index 1eab0d698f4d..000000000000 --- a/drivers/net/wireless/ipw2x00/ipw2100.h +++ /dev/null @@ -1,1166 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -******************************************************************************/ -#ifndef _IPW2100_H -#define _IPW2100_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // new driver API - -#ifdef CONFIG_IPW2100_MONITOR -#include -#endif - -#include -#include - -#include "libipw.h" - -struct ipw2100_priv; -struct ipw2100_tx_packet; -struct ipw2100_rx_packet; - -#define IPW_DL_UNINIT 0x80000000 -#define IPW_DL_NONE 0x00000000 -#define IPW_DL_ALL 0x7FFFFFFF - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IPW_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IPW2100_xxxx_DEBUG() macro definition for your - * classification, or use IPW_DEBUG(IPW_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/ipw2100/debug_level - * - * you simply need to add your entry to the ipw2100_debug_levels array. - * - * If you do not see debug_level in /proc/net/ipw2100 then you do not have - * CONFIG_IPW2100_DEBUG defined in your kernel configuration - * - */ - -#define IPW_DL_ERROR (1<<0) -#define IPW_DL_WARNING (1<<1) -#define IPW_DL_INFO (1<<2) -#define IPW_DL_WX (1<<3) -#define IPW_DL_HC (1<<5) -#define IPW_DL_STATE (1<<6) - -#define IPW_DL_NOTIF (1<<10) -#define IPW_DL_SCAN (1<<11) -#define IPW_DL_ASSOC (1<<12) -#define IPW_DL_DROP (1<<13) - -#define IPW_DL_IOCTL (1<<14) -#define IPW_DL_RF_KILL (1<<17) - -#define IPW_DL_MANAGE (1<<15) -#define IPW_DL_FW (1<<16) - -#define IPW_DL_FRAG (1<<21) -#define IPW_DL_WEP (1<<22) -#define IPW_DL_TX (1<<23) -#define IPW_DL_RX (1<<24) -#define IPW_DL_ISR (1<<25) -#define IPW_DL_IO (1<<26) -#define IPW_DL_TRACE (1<<28) - -#define IPW_DEBUG_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) -#define IPW_DEBUG_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) -#define IPW_DEBUG_INFO(f...) IPW_DEBUG(IPW_DL_INFO, ## f) -#define IPW_DEBUG_WX(f...) IPW_DEBUG(IPW_DL_WX, ## f) -#define IPW_DEBUG_SCAN(f...) IPW_DEBUG(IPW_DL_SCAN, ## f) -#define IPW_DEBUG_NOTIF(f...) IPW_DEBUG(IPW_DL_NOTIF, ## f) -#define IPW_DEBUG_TRACE(f...) IPW_DEBUG(IPW_DL_TRACE, ## f) -#define IPW_DEBUG_RX(f...) IPW_DEBUG(IPW_DL_RX, ## f) -#define IPW_DEBUG_TX(f...) IPW_DEBUG(IPW_DL_TX, ## f) -#define IPW_DEBUG_ISR(f...) IPW_DEBUG(IPW_DL_ISR, ## f) -#define IPW_DEBUG_MANAGEMENT(f...) IPW_DEBUG(IPW_DL_MANAGE, ## f) -#define IPW_DEBUG_WEP(f...) IPW_DEBUG(IPW_DL_WEP, ## f) -#define IPW_DEBUG_HC(f...) IPW_DEBUG(IPW_DL_HC, ## f) -#define IPW_DEBUG_FRAG(f...) IPW_DEBUG(IPW_DL_FRAG, ## f) -#define IPW_DEBUG_FW(f...) IPW_DEBUG(IPW_DL_FW, ## f) -#define IPW_DEBUG_RF_KILL(f...) IPW_DEBUG(IPW_DL_RF_KILL, ## f) -#define IPW_DEBUG_DROP(f...) IPW_DEBUG(IPW_DL_DROP, ## f) -#define IPW_DEBUG_IO(f...) IPW_DEBUG(IPW_DL_IO, ## f) -#define IPW_DEBUG_IOCTL(f...) IPW_DEBUG(IPW_DL_IOCTL, ## f) -#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) -#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) - -enum { - IPW_HW_STATE_DISABLED = 1, - IPW_HW_STATE_ENABLED = 0 -}; - -struct ssid_context { - char ssid[IW_ESSID_MAX_SIZE + 1]; - int ssid_len; - unsigned char bssid[ETH_ALEN]; - int port_type; - int channel; - -}; - -extern const char *port_type_str[]; -extern const char *band_str[]; - -#define NUMBER_OF_BD_PER_COMMAND_PACKET 1 -#define NUMBER_OF_BD_PER_DATA_PACKET 2 - -#define IPW_MAX_BDS 6 -#define NUMBER_OF_OVERHEAD_BDS_PER_PACKETR 2 -#define NUMBER_OF_BDS_TO_LEAVE_FOR_COMMANDS 1 - -#define REQUIRED_SPACE_IN_RING_FOR_COMMAND_PACKET \ - (IPW_BD_QUEUE_W_R_MIN_SPARE + NUMBER_OF_BD_PER_COMMAND_PACKET) - -struct bd_status { - union { - struct { - u8 nlf:1, txType:2, intEnabled:1, reserved:4; - } fields; - u8 field; - } info; -} __attribute__ ((packed)); - -struct ipw2100_bd { - u32 host_addr; - u32 buf_length; - struct bd_status status; - /* number of fragments for frame (should be set only for - * 1st TBD) */ - u8 num_fragments; - u8 reserved[6]; -} __attribute__ ((packed)); - -#define IPW_BD_QUEUE_LENGTH(n) (1<value = (x)->hi = 0; \ - (x)->lo = 0x7fffffff; \ -} while (0) -#define SET_STAT(x,y) do { \ - (x)->value = y; \ - if ((x)->value > (x)->hi) (x)->hi = (x)->value; \ - if ((x)->value < (x)->lo) (x)->lo = (x)->value; \ -} while (0) -#define INC_STAT(x) do { if (++(x)->value > (x)->hi) (x)->hi = (x)->value; } \ -while (0) -#define DEC_STAT(x) do { if (--(x)->value < (x)->lo) (x)->lo = (x)->value; } \ -while (0) - -#define IPW2100_ERROR_QUEUE 5 - -/* Power management code: enable or disable? */ -enum { -#ifdef CONFIG_PM - IPW2100_PM_DISABLED = 0, - PM_STATE_SIZE = 16, -#else - IPW2100_PM_DISABLED = 1, - PM_STATE_SIZE = 0, -#endif -}; - -#define STATUS_POWERED (1<<0) -#define STATUS_CMD_ACTIVE (1<<1) /**< host command in progress */ -#define STATUS_RUNNING (1<<2) /* Card initialized, but not enabled */ -#define STATUS_ENABLED (1<<3) /* Card enabled -- can scan,Tx,Rx */ -#define STATUS_STOPPING (1<<4) /* Card is in shutdown phase */ -#define STATUS_INITIALIZED (1<<5) /* Card is ready for external calls */ -#define STATUS_ASSOCIATING (1<<9) /* Associated, but no BSSID yet */ -#define STATUS_ASSOCIATED (1<<10) /* Associated and BSSID valid */ -#define STATUS_INT_ENABLED (1<<11) -#define STATUS_RF_KILL_HW (1<<12) -#define STATUS_RF_KILL_SW (1<<13) -#define STATUS_RF_KILL_MASK (STATUS_RF_KILL_HW | STATUS_RF_KILL_SW) -#define STATUS_EXIT_PENDING (1<<14) - -#define STATUS_SCAN_PENDING (1<<23) -#define STATUS_SCANNING (1<<24) -#define STATUS_SCAN_ABORTING (1<<25) -#define STATUS_SCAN_COMPLETE (1<<26) -#define STATUS_WX_EVENT_PENDING (1<<27) -#define STATUS_RESET_PENDING (1<<29) -#define STATUS_SECURITY_UPDATED (1<<30) /* Security sync needed */ - -/* Internal NIC states */ -#define IPW_STATE_INITIALIZED (1<<0) -#define IPW_STATE_COUNTRY_FOUND (1<<1) -#define IPW_STATE_ASSOCIATED (1<<2) -#define IPW_STATE_ASSN_LOST (1<<3) -#define IPW_STATE_ASSN_CHANGED (1<<4) -#define IPW_STATE_SCAN_COMPLETE (1<<5) -#define IPW_STATE_ENTERED_PSP (1<<6) -#define IPW_STATE_LEFT_PSP (1<<7) -#define IPW_STATE_RF_KILL (1<<8) -#define IPW_STATE_DISABLED (1<<9) -#define IPW_STATE_POWER_DOWN (1<<10) -#define IPW_STATE_SCANNING (1<<11) - -#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */ -#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */ -#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */ -#define CFG_CUSTOM_MAC (1<<3) -#define CFG_LONG_PREAMBLE (1<<4) -#define CFG_ASSOCIATE (1<<6) -#define CFG_FIXED_RATE (1<<7) -#define CFG_ADHOC_CREATE (1<<8) -#define CFG_PASSIVE_SCAN (1<<10) -#ifdef CONFIG_IPW2100_MONITOR -#define CFG_CRC_CHECK (1<<11) -#endif - -#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ -#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ - -struct ipw2100_priv { - - int stop_hang_check; /* Set 1 when shutting down to kill hang_check */ - int stop_rf_kill; /* Set 1 when shutting down to kill rf_kill */ - - struct libipw_device *ieee; - unsigned long status; - unsigned long config; - unsigned long capability; - - /* Statistics */ - int resets; - int reset_backoff; - - /* Context */ - u8 essid[IW_ESSID_MAX_SIZE]; - u8 essid_len; - u8 bssid[ETH_ALEN]; - u8 channel; - int last_mode; - - unsigned long connect_start; - unsigned long last_reset; - - u32 channel_mask; - u32 fatal_error; - u32 fatal_errors[IPW2100_ERROR_QUEUE]; - u32 fatal_index; - int eeprom_version; - int firmware_version; - unsigned long hw_features; - int hangs; - u32 last_rtc; - int dump_raw; /* 1 to dump raw bytes in /sys/.../memory */ - u8 *snapshot[0x30]; - - u8 mandatory_bssid_mac[ETH_ALEN]; - u8 mac_addr[ETH_ALEN]; - - int power_mode; - - int messages_sent; - - int short_retry_limit; - int long_retry_limit; - - u32 rts_threshold; - u32 frag_threshold; - - int in_isr; - - u32 tx_rates; - int tx_power; - u32 beacon_interval; - - char nick[IW_ESSID_MAX_SIZE + 1]; - - struct ipw2100_status_queue status_queue; - - struct statistic txq_stat; - struct statistic rxq_stat; - struct ipw2100_bd_queue rx_queue; - struct ipw2100_bd_queue tx_queue; - struct ipw2100_rx_packet *rx_buffers; - - struct statistic fw_pend_stat; - struct list_head fw_pend_list; - - struct statistic msg_free_stat; - struct statistic msg_pend_stat; - struct list_head msg_free_list; - struct list_head msg_pend_list; - struct ipw2100_tx_packet *msg_buffers; - - struct statistic tx_free_stat; - struct statistic tx_pend_stat; - struct list_head tx_free_list; - struct list_head tx_pend_list; - struct ipw2100_tx_packet *tx_buffers; - - struct ipw2100_ordinals ordinals; - - struct pci_dev *pci_dev; - - struct proc_dir_entry *dir_dev; - - struct net_device *net_dev; - struct iw_statistics wstats; - - struct iw_public_data wireless_data; - - struct tasklet_struct irq_tasklet; - - struct workqueue_struct *workqueue; - struct delayed_work reset_work; - struct delayed_work security_work; - struct delayed_work wx_event_work; - struct delayed_work hang_check; - struct delayed_work rf_kill; - struct work_struct scan_event_now; - struct delayed_work scan_event_later; - - int user_requested_scan; - - /* Track time in suspend */ - unsigned long suspend_at; - unsigned long suspend_time; - - u32 interrupts; - int tx_interrupts; - int rx_interrupts; - int inta_other; - - spinlock_t low_lock; - struct mutex action_mutex; - struct mutex adapter_mutex; - - wait_queue_head_t wait_command_queue; -}; - -/********************************************************* - * Host Command -> From Driver to FW - *********************************************************/ - -/** - * Host command identifiers - */ -#define HOST_COMPLETE 2 -#define SYSTEM_CONFIG 6 -#define SSID 8 -#define MANDATORY_BSSID 9 -#define AUTHENTICATION_TYPE 10 -#define ADAPTER_ADDRESS 11 -#define PORT_TYPE 12 -#define INTERNATIONAL_MODE 13 -#define CHANNEL 14 -#define RTS_THRESHOLD 15 -#define FRAG_THRESHOLD 16 -#define POWER_MODE 17 -#define TX_RATES 18 -#define BASIC_TX_RATES 19 -#define WEP_KEY_INFO 20 -#define WEP_KEY_INDEX 25 -#define WEP_FLAGS 26 -#define ADD_MULTICAST 27 -#define CLEAR_ALL_MULTICAST 28 -#define BEACON_INTERVAL 29 -#define ATIM_WINDOW 30 -#define CLEAR_STATISTICS 31 -#define SEND 33 -#define TX_POWER_INDEX 36 -#define BROADCAST_SCAN 43 -#define CARD_DISABLE 44 -#define PREFERRED_BSSID 45 -#define SET_SCAN_OPTIONS 46 -#define SCAN_DWELL_TIME 47 -#define SWEEP_TABLE 48 -#define AP_OR_STATION_TABLE 49 -#define GROUP_ORDINALS 50 -#define SHORT_RETRY_LIMIT 51 -#define LONG_RETRY_LIMIT 52 - -#define HOST_PRE_POWER_DOWN 58 -#define CARD_DISABLE_PHY_OFF 61 -#define MSDU_TX_RATES 62 - -/* Rogue AP Detection */ -#define SET_STATION_STAT_BITS 64 -#define CLEAR_STATIONS_STAT_BITS 65 -#define LEAP_ROGUE_MODE 66 //TODO tbw replaced by CFG_LEAP_ROGUE_AP -#define SET_SECURITY_INFORMATION 67 -#define DISASSOCIATION_BSSID 68 -#define SET_WPA_IE 69 - -/* system configuration bit mask: */ -#define IPW_CFG_MONITOR 0x00004 -#define IPW_CFG_PREAMBLE_AUTO 0x00010 -#define IPW_CFG_IBSS_AUTO_START 0x00020 -#define IPW_CFG_LOOPBACK 0x00100 -#define IPW_CFG_ANSWER_BCSSID_PROBE 0x00800 -#define IPW_CFG_BT_SIDEBAND_SIGNAL 0x02000 -#define IPW_CFG_802_1x_ENABLE 0x04000 -#define IPW_CFG_BSS_MASK 0x08000 -#define IPW_CFG_IBSS_MASK 0x10000 - -#define IPW_SCAN_NOASSOCIATE (1<<0) -#define IPW_SCAN_MIXED_CELL (1<<1) -/* RESERVED (1<<2) */ -#define IPW_SCAN_PASSIVE (1<<3) - -#define IPW_NIC_FATAL_ERROR 0x2A7F0 -#define IPW_ERROR_ADDR(x) (x & 0x3FFFF) -#define IPW_ERROR_CODE(x) ((x & 0xFF000000) >> 24) -#define IPW2100_ERR_C3_CORRUPTION (0x10 << 24) -#define IPW2100_ERR_MSG_TIMEOUT (0x11 << 24) -#define IPW2100_ERR_FW_LOAD (0x12 << 24) - -#define IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND 0x200 -#define IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x0D80 - -#define IPW_MEM_HOST_SHARED_RX_BD_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x40) -#define IPW_MEM_HOST_SHARED_RX_STATUS_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x44) -#define IPW_MEM_HOST_SHARED_RX_BD_SIZE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x48) -#define IPW_MEM_HOST_SHARED_RX_READ_INDEX (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0xa0) - -#define IPW_MEM_HOST_SHARED_TX_QUEUE_BD_BASE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x00) -#define IPW_MEM_HOST_SHARED_TX_QUEUE_BD_SIZE (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x04) -#define IPW_MEM_HOST_SHARED_TX_QUEUE_READ_INDEX (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x80) - -#define IPW_MEM_HOST_SHARED_RX_WRITE_INDEX \ - (IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND + 0x20) - -#define IPW_MEM_HOST_SHARED_TX_QUEUE_WRITE_INDEX \ - (IPW_MEM_SRAM_HOST_INTERRUPT_AREA_LOWER_BOUND) - -#define IPW_MEM_HOST_SHARED_ORDINALS_TABLE_1 (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x180) -#define IPW_MEM_HOST_SHARED_ORDINALS_TABLE_2 (IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND + 0x184) - -#define IPW2100_INTA_TX_TRANSFER (0x00000001) // Bit 0 (LSB) -#define IPW2100_INTA_RX_TRANSFER (0x00000002) // Bit 1 -#define IPW2100_INTA_TX_COMPLETE (0x00000004) // Bit 2 -#define IPW2100_INTA_EVENT_INTERRUPT (0x00000008) // Bit 3 -#define IPW2100_INTA_STATUS_CHANGE (0x00000010) // Bit 4 -#define IPW2100_INTA_BEACON_PERIOD_EXPIRED (0x00000020) // Bit 5 -#define IPW2100_INTA_SLAVE_MODE_HOST_COMMAND_DONE (0x00010000) // Bit 16 -#define IPW2100_INTA_FW_INIT_DONE (0x01000000) // Bit 24 -#define IPW2100_INTA_FW_CALIBRATION_CALC (0x02000000) // Bit 25 -#define IPW2100_INTA_FATAL_ERROR (0x40000000) // Bit 30 -#define IPW2100_INTA_PARITY_ERROR (0x80000000) // Bit 31 (MSB) - -#define IPW_AUX_HOST_RESET_REG_PRINCETON_RESET (0x00000001) -#define IPW_AUX_HOST_RESET_REG_FORCE_NMI (0x00000002) -#define IPW_AUX_HOST_RESET_REG_PCI_HOST_CLUSTER_FATAL_NMI (0x00000004) -#define IPW_AUX_HOST_RESET_REG_CORE_FATAL_NMI (0x00000008) -#define IPW_AUX_HOST_RESET_REG_SW_RESET (0x00000080) -#define IPW_AUX_HOST_RESET_REG_MASTER_DISABLED (0x00000100) -#define IPW_AUX_HOST_RESET_REG_STOP_MASTER (0x00000200) - -#define IPW_AUX_HOST_GP_CNTRL_BIT_CLOCK_READY (0x00000001) // Bit 0 (LSB) -#define IPW_AUX_HOST_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY (0x00000002) // Bit 1 -#define IPW_AUX_HOST_GP_CNTRL_BIT_INIT_DONE (0x00000004) // Bit 2 -#define IPW_AUX_HOST_GP_CNTRL_BITS_SYS_CONFIG (0x000007c0) // Bits 6-10 -#define IPW_AUX_HOST_GP_CNTRL_BIT_BUS_TYPE (0x00000200) // Bit 9 -#define IPW_AUX_HOST_GP_CNTRL_BIT_BAR0_BLOCK_SIZE (0x00000400) // Bit 10 -#define IPW_AUX_HOST_GP_CNTRL_BIT_USB_MODE (0x20000000) // Bit 29 -#define IPW_AUX_HOST_GP_CNTRL_BIT_HOST_FORCES_SYS_CLK (0x40000000) // Bit 30 -#define IPW_AUX_HOST_GP_CNTRL_BIT_FW_FORCES_SYS_CLK (0x80000000) // Bit 31 (MSB) - -#define IPW_BIT_GPIO_GPIO1_MASK 0x0000000C -#define IPW_BIT_GPIO_GPIO3_MASK 0x000000C0 -#define IPW_BIT_GPIO_GPIO1_ENABLE 0x00000008 -#define IPW_BIT_GPIO_RF_KILL 0x00010000 - -#define IPW_BIT_GPIO_LED_OFF 0x00002000 // Bit 13 = 1 - -#define IPW_REG_DOMAIN_0_OFFSET 0x0000 -#define IPW_REG_DOMAIN_1_OFFSET IPW_MEM_SRAM_HOST_SHARED_LOWER_BOUND - -#define IPW_REG_INTA IPW_REG_DOMAIN_0_OFFSET + 0x0008 -#define IPW_REG_INTA_MASK IPW_REG_DOMAIN_0_OFFSET + 0x000C -#define IPW_REG_INDIRECT_ACCESS_ADDRESS IPW_REG_DOMAIN_0_OFFSET + 0x0010 -#define IPW_REG_INDIRECT_ACCESS_DATA IPW_REG_DOMAIN_0_OFFSET + 0x0014 -#define IPW_REG_AUTOINCREMENT_ADDRESS IPW_REG_DOMAIN_0_OFFSET + 0x0018 -#define IPW_REG_AUTOINCREMENT_DATA IPW_REG_DOMAIN_0_OFFSET + 0x001C -#define IPW_REG_RESET_REG IPW_REG_DOMAIN_0_OFFSET + 0x0020 -#define IPW_REG_GP_CNTRL IPW_REG_DOMAIN_0_OFFSET + 0x0024 -#define IPW_REG_GPIO IPW_REG_DOMAIN_0_OFFSET + 0x0030 -#define IPW_REG_FW_TYPE IPW_REG_DOMAIN_1_OFFSET + 0x0188 -#define IPW_REG_FW_VERSION IPW_REG_DOMAIN_1_OFFSET + 0x018C -#define IPW_REG_FW_COMPATABILITY_VERSION IPW_REG_DOMAIN_1_OFFSET + 0x0190 - -#define IPW_REG_INDIRECT_ADDR_MASK 0x00FFFFFC - -#define IPW_INTERRUPT_MASK 0xC1010013 - -#define IPW2100_CONTROL_REG 0x220000 -#define IPW2100_CONTROL_PHY_OFF 0x8 - -#define IPW2100_COMMAND 0x00300004 -#define IPW2100_COMMAND_PHY_ON 0x0 -#define IPW2100_COMMAND_PHY_OFF 0x1 - -/* in DEBUG_AREA, values of memory always 0xd55555d5 */ -#define IPW_REG_DOA_DEBUG_AREA_START IPW_REG_DOMAIN_0_OFFSET + 0x0090 -#define IPW_REG_DOA_DEBUG_AREA_END IPW_REG_DOMAIN_0_OFFSET + 0x00FF -#define IPW_DATA_DOA_DEBUG_VALUE 0xd55555d5 - -#define IPW_INTERNAL_REGISTER_HALT_AND_RESET 0x003000e0 - -#define IPW_WAIT_CLOCK_STABILIZATION_DELAY 50 // micro seconds -#define IPW_WAIT_RESET_ARC_COMPLETE_DELAY 10 // micro seconds -#define IPW_WAIT_RESET_MASTER_ASSERT_COMPLETE_DELAY 10 // micro seconds - -// BD ring queue read/write difference -#define IPW_BD_QUEUE_W_R_MIN_SPARE 2 - -#define IPW_CACHE_LINE_LENGTH_DEFAULT 0x80 - -#define IPW_CARD_DISABLE_PHY_OFF_COMPLETE_WAIT 100 // 100 milli -#define IPW_PREPARE_POWER_DOWN_COMPLETE_WAIT 100 // 100 milli - -#define IPW_HEADER_802_11_SIZE sizeof(struct libipw_hdr_3addr) -#define IPW_MAX_80211_PAYLOAD_SIZE 2304U -#define IPW_MAX_802_11_PAYLOAD_LENGTH 2312 -#define IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH 1536 -#define IPW_MIN_ACCEPTABLE_RX_FRAME_LENGTH 60 -#define IPW_MAX_ACCEPTABLE_RX_FRAME_LENGTH \ - (IPW_MAX_ACCEPTABLE_TX_FRAME_LENGTH + IPW_HEADER_802_11_SIZE - \ - sizeof(struct ethhdr)) - -#define IPW_802_11_FCS_LENGTH 4 -#define IPW_RX_NIC_BUFFER_LENGTH \ - (IPW_MAX_802_11_PAYLOAD_LENGTH + IPW_HEADER_802_11_SIZE + \ - IPW_802_11_FCS_LENGTH) - -#define IPW_802_11_PAYLOAD_OFFSET \ - (sizeof(struct libipw_hdr_3addr) + \ - sizeof(struct libipw_snap_hdr)) - -struct ipw2100_rx { - union { - unsigned char payload[IPW_RX_NIC_BUFFER_LENGTH]; - struct libipw_hdr_4addr header; - u32 status; - struct ipw2100_notification notification; - struct ipw2100_cmd_header command; - } rx_data; -} __attribute__ ((packed)); - -/* Bit 0-7 are for 802.11b tx rates - . Bit 5-7 are reserved */ -#define TX_RATE_1_MBIT 0x0001 -#define TX_RATE_2_MBIT 0x0002 -#define TX_RATE_5_5_MBIT 0x0004 -#define TX_RATE_11_MBIT 0x0008 -#define TX_RATE_MASK 0x000F -#define DEFAULT_TX_RATES 0x000F - -#define IPW_POWER_MODE_CAM 0x00 //(always on) -#define IPW_POWER_INDEX_1 0x01 -#define IPW_POWER_INDEX_2 0x02 -#define IPW_POWER_INDEX_3 0x03 -#define IPW_POWER_INDEX_4 0x04 -#define IPW_POWER_INDEX_5 0x05 -#define IPW_POWER_AUTO 0x06 -#define IPW_POWER_MASK 0x0F -#define IPW_POWER_ENABLED 0x10 -#define IPW_POWER_LEVEL(x) ((x) & IPW_POWER_MASK) - -#define IPW_TX_POWER_AUTO 0 -#define IPW_TX_POWER_ENHANCED 1 - -#define IPW_TX_POWER_DEFAULT 32 -#define IPW_TX_POWER_MIN 0 -#define IPW_TX_POWER_MAX 16 -#define IPW_TX_POWER_MIN_DBM (-12) -#define IPW_TX_POWER_MAX_DBM 16 - -#define FW_SCAN_DONOT_ASSOCIATE 0x0001 // Dont Attempt to Associate after Scan -#define FW_SCAN_PASSIVE 0x0008 // Force PASSSIVE Scan - -#define REG_MIN_CHANNEL 0 -#define REG_MAX_CHANNEL 14 - -#define REG_CHANNEL_MASK 0x00003FFF -#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff - -#define DIVERSITY_EITHER 0 // Use both antennas -#define DIVERSITY_ANTENNA_A 1 // Use antenna A -#define DIVERSITY_ANTENNA_B 2 // Use antenna B - -#define HOST_COMMAND_WAIT 0 -#define HOST_COMMAND_NO_WAIT 1 - -#define LOCK_NONE 0 -#define LOCK_DRIVER 1 -#define LOCK_FW 2 - -#define TYPE_SWEEP_ORD 0x000D -#define TYPE_IBSS_STTN_ORD 0x000E -#define TYPE_BSS_AP_ORD 0x000F -#define TYPE_RAW_BEACON_ENTRY 0x0010 -#define TYPE_CALIBRATION_DATA 0x0011 -#define TYPE_ROGUE_AP_DATA 0x0012 -#define TYPE_ASSOCIATION_REQUEST 0x0013 -#define TYPE_REASSOCIATION_REQUEST 0x0014 - -#define HW_FEATURE_RFKILL 0x0001 -#define RF_KILLSWITCH_OFF 1 -#define RF_KILLSWITCH_ON 0 - -#define IPW_COMMAND_POOL_SIZE 40 - -#define IPW_START_ORD_TAB_1 1 -#define IPW_START_ORD_TAB_2 1000 - -#define IPW_ORD_TAB_1_ENTRY_SIZE sizeof(u32) - -#define IS_ORDINAL_TABLE_ONE(mgr,id) \ - ((id >= IPW_START_ORD_TAB_1) && (id < mgr->table1_size)) -#define IS_ORDINAL_TABLE_TWO(mgr,id) \ - ((id >= IPW_START_ORD_TAB_2) && (id < (mgr->table2_size + IPW_START_ORD_TAB_2))) - -#define BSS_ID_LENGTH 6 - -// Fixed size data: Ordinal Table 1 -typedef enum _ORDINAL_TABLE_1 { // NS - means Not Supported by FW -// Transmit statistics - IPW_ORD_STAT_TX_HOST_REQUESTS = 1, // # of requested Host Tx's (MSDU) - IPW_ORD_STAT_TX_HOST_COMPLETE, // # of successful Host Tx's (MSDU) - IPW_ORD_STAT_TX_DIR_DATA, // # of successful Directed Tx's (MSDU) - - IPW_ORD_STAT_TX_DIR_DATA1 = 4, // # of successful Directed Tx's (MSDU) @ 1MB - IPW_ORD_STAT_TX_DIR_DATA2, // # of successful Directed Tx's (MSDU) @ 2MB - IPW_ORD_STAT_TX_DIR_DATA5_5, // # of successful Directed Tx's (MSDU) @ 5_5MB - IPW_ORD_STAT_TX_DIR_DATA11, // # of successful Directed Tx's (MSDU) @ 11MB - IPW_ORD_STAT_TX_DIR_DATA22, // # of successful Directed Tx's (MSDU) @ 22MB - - IPW_ORD_STAT_TX_NODIR_DATA1 = 13, // # of successful Non_Directed Tx's (MSDU) @ 1MB - IPW_ORD_STAT_TX_NODIR_DATA2, // # of successful Non_Directed Tx's (MSDU) @ 2MB - IPW_ORD_STAT_TX_NODIR_DATA5_5, // # of successful Non_Directed Tx's (MSDU) @ 5.5MB - IPW_ORD_STAT_TX_NODIR_DATA11, // # of successful Non_Directed Tx's (MSDU) @ 11MB - - IPW_ORD_STAT_NULL_DATA = 21, // # of successful NULL data Tx's - IPW_ORD_STAT_TX_RTS, // # of successful Tx RTS - IPW_ORD_STAT_TX_CTS, // # of successful Tx CTS - IPW_ORD_STAT_TX_ACK, // # of successful Tx ACK - IPW_ORD_STAT_TX_ASSN, // # of successful Association Tx's - IPW_ORD_STAT_TX_ASSN_RESP, // # of successful Association response Tx's - IPW_ORD_STAT_TX_REASSN, // # of successful Reassociation Tx's - IPW_ORD_STAT_TX_REASSN_RESP, // # of successful Reassociation response Tx's - IPW_ORD_STAT_TX_PROBE, // # of probes successfully transmitted - IPW_ORD_STAT_TX_PROBE_RESP, // # of probe responses successfully transmitted - IPW_ORD_STAT_TX_BEACON, // # of tx beacon - IPW_ORD_STAT_TX_ATIM, // # of Tx ATIM - IPW_ORD_STAT_TX_DISASSN, // # of successful Disassociation TX - IPW_ORD_STAT_TX_AUTH, // # of successful Authentication Tx - IPW_ORD_STAT_TX_DEAUTH, // # of successful Deauthentication TX - - IPW_ORD_STAT_TX_TOTAL_BYTES = 41, // Total successful Tx data bytes - IPW_ORD_STAT_TX_RETRIES, // # of Tx retries - IPW_ORD_STAT_TX_RETRY1, // # of Tx retries at 1MBPS - IPW_ORD_STAT_TX_RETRY2, // # of Tx retries at 2MBPS - IPW_ORD_STAT_TX_RETRY5_5, // # of Tx retries at 5.5MBPS - IPW_ORD_STAT_TX_RETRY11, // # of Tx retries at 11MBPS - - IPW_ORD_STAT_TX_FAILURES = 51, // # of Tx Failures - IPW_ORD_STAT_TX_ABORT_AT_HOP, //NS // # of Tx's aborted at hop time - IPW_ORD_STAT_TX_MAX_TRIES_IN_HOP, // # of times max tries in a hop failed - IPW_ORD_STAT_TX_ABORT_LATE_DMA, //NS // # of times tx aborted due to late dma setup - IPW_ORD_STAT_TX_ABORT_STX, //NS // # of times backoff aborted - IPW_ORD_STAT_TX_DISASSN_FAIL, // # of times disassociation failed - IPW_ORD_STAT_TX_ERR_CTS, // # of missed/bad CTS frames - IPW_ORD_STAT_TX_BPDU, //NS // # of spanning tree BPDUs sent - IPW_ORD_STAT_TX_ERR_ACK, // # of tx err due to acks - - // Receive statistics - IPW_ORD_STAT_RX_HOST = 61, // # of packets passed to host - IPW_ORD_STAT_RX_DIR_DATA, // # of directed packets - IPW_ORD_STAT_RX_DIR_DATA1, // # of directed packets at 1MB - IPW_ORD_STAT_RX_DIR_DATA2, // # of directed packets at 2MB - IPW_ORD_STAT_RX_DIR_DATA5_5, // # of directed packets at 5.5MB - IPW_ORD_STAT_RX_DIR_DATA11, // # of directed packets at 11MB - IPW_ORD_STAT_RX_DIR_DATA22, // # of directed packets at 22MB - - IPW_ORD_STAT_RX_NODIR_DATA = 71, // # of nondirected packets - IPW_ORD_STAT_RX_NODIR_DATA1, // # of nondirected packets at 1MB - IPW_ORD_STAT_RX_NODIR_DATA2, // # of nondirected packets at 2MB - IPW_ORD_STAT_RX_NODIR_DATA5_5, // # of nondirected packets at 5.5MB - IPW_ORD_STAT_RX_NODIR_DATA11, // # of nondirected packets at 11MB - - IPW_ORD_STAT_RX_NULL_DATA = 80, // # of null data rx's - IPW_ORD_STAT_RX_POLL, //NS // # of poll rx - IPW_ORD_STAT_RX_RTS, // # of Rx RTS - IPW_ORD_STAT_RX_CTS, // # of Rx CTS - IPW_ORD_STAT_RX_ACK, // # of Rx ACK - IPW_ORD_STAT_RX_CFEND, // # of Rx CF End - IPW_ORD_STAT_RX_CFEND_ACK, // # of Rx CF End + CF Ack - IPW_ORD_STAT_RX_ASSN, // # of Association Rx's - IPW_ORD_STAT_RX_ASSN_RESP, // # of Association response Rx's - IPW_ORD_STAT_RX_REASSN, // # of Reassociation Rx's - IPW_ORD_STAT_RX_REASSN_RESP, // # of Reassociation response Rx's - IPW_ORD_STAT_RX_PROBE, // # of probe Rx's - IPW_ORD_STAT_RX_PROBE_RESP, // # of probe response Rx's - IPW_ORD_STAT_RX_BEACON, // # of Rx beacon - IPW_ORD_STAT_RX_ATIM, // # of Rx ATIM - IPW_ORD_STAT_RX_DISASSN, // # of disassociation Rx - IPW_ORD_STAT_RX_AUTH, // # of authentication Rx - IPW_ORD_STAT_RX_DEAUTH, // # of deauthentication Rx - - IPW_ORD_STAT_RX_TOTAL_BYTES = 101, // Total rx data bytes received - IPW_ORD_STAT_RX_ERR_CRC, // # of packets with Rx CRC error - IPW_ORD_STAT_RX_ERR_CRC1, // # of Rx CRC errors at 1MB - IPW_ORD_STAT_RX_ERR_CRC2, // # of Rx CRC errors at 2MB - IPW_ORD_STAT_RX_ERR_CRC5_5, // # of Rx CRC errors at 5.5MB - IPW_ORD_STAT_RX_ERR_CRC11, // # of Rx CRC errors at 11MB - - IPW_ORD_STAT_RX_DUPLICATE1 = 112, // # of duplicate rx packets at 1MB - IPW_ORD_STAT_RX_DUPLICATE2, // # of duplicate rx packets at 2MB - IPW_ORD_STAT_RX_DUPLICATE5_5, // # of duplicate rx packets at 5.5MB - IPW_ORD_STAT_RX_DUPLICATE11, // # of duplicate rx packets at 11MB - IPW_ORD_STAT_RX_DUPLICATE = 119, // # of duplicate rx packets - - IPW_ORD_PERS_DB_LOCK = 120, // # locking fw permanent db - IPW_ORD_PERS_DB_SIZE, // # size of fw permanent db - IPW_ORD_PERS_DB_ADDR, // # address of fw permanent db - IPW_ORD_STAT_RX_INVALID_PROTOCOL, // # of rx frames with invalid protocol - IPW_ORD_SYS_BOOT_TIME, // # Boot time - IPW_ORD_STAT_RX_NO_BUFFER, // # of rx frames rejected due to no buffer - IPW_ORD_STAT_RX_ABORT_LATE_DMA, //NS // # of rx frames rejected due to dma setup too late - IPW_ORD_STAT_RX_ABORT_AT_HOP, //NS // # of rx frames aborted due to hop - IPW_ORD_STAT_RX_MISSING_FRAG, // # of rx frames dropped due to missing fragment - IPW_ORD_STAT_RX_ORPHAN_FRAG, // # of rx frames dropped due to non-sequential fragment - IPW_ORD_STAT_RX_ORPHAN_FRAME, // # of rx frames dropped due to unmatched 1st frame - IPW_ORD_STAT_RX_FRAG_AGEOUT, // # of rx frames dropped due to uncompleted frame - IPW_ORD_STAT_RX_BAD_SSID, //NS // Bad SSID (unused) - IPW_ORD_STAT_RX_ICV_ERRORS, // # of ICV errors during decryption - -// PSP Statistics - IPW_ORD_STAT_PSP_SUSPENSION = 137, // # of times adapter suspended - IPW_ORD_STAT_PSP_BCN_TIMEOUT, // # of beacon timeout - IPW_ORD_STAT_PSP_POLL_TIMEOUT, // # of poll response timeouts - IPW_ORD_STAT_PSP_NONDIR_TIMEOUT, // # of timeouts waiting for last broadcast/muticast pkt - IPW_ORD_STAT_PSP_RX_DTIMS, // # of PSP DTIMs received - IPW_ORD_STAT_PSP_RX_TIMS, // # of PSP TIMs received - IPW_ORD_STAT_PSP_STATION_ID, // PSP Station ID - -// Association and roaming - IPW_ORD_LAST_ASSN_TIME = 147, // RTC time of last association - IPW_ORD_STAT_PERCENT_MISSED_BCNS, // current calculation of % missed beacons - IPW_ORD_STAT_PERCENT_RETRIES, // current calculation of % missed tx retries - IPW_ORD_ASSOCIATED_AP_PTR, // If associated, this is ptr to the associated - // AP table entry. set to 0 if not associated - IPW_ORD_AVAILABLE_AP_CNT, // # of AP's decsribed in the AP table - IPW_ORD_AP_LIST_PTR, // Ptr to list of available APs - IPW_ORD_STAT_AP_ASSNS, // # of associations - IPW_ORD_STAT_ASSN_FAIL, // # of association failures - IPW_ORD_STAT_ASSN_RESP_FAIL, // # of failuresdue to response fail - IPW_ORD_STAT_FULL_SCANS, // # of full scans - - IPW_ORD_CARD_DISABLED, // # Card Disabled - IPW_ORD_STAT_ROAM_INHIBIT, // # of times roaming was inhibited due to ongoing activity - IPW_FILLER_40, - IPW_ORD_RSSI_AT_ASSN = 160, // RSSI of associated AP at time of association - IPW_ORD_STAT_ASSN_CAUSE1, // # of reassociations due to no tx from AP in last N - // hops or no prob_ responses in last 3 minutes - IPW_ORD_STAT_ASSN_CAUSE2, // # of reassociations due to poor tx/rx quality - IPW_ORD_STAT_ASSN_CAUSE3, // # of reassociations due to tx/rx quality with excessive - // load at the AP - IPW_ORD_STAT_ASSN_CAUSE4, // # of reassociations due to AP RSSI level fell below - // eligible group - IPW_ORD_STAT_ASSN_CAUSE5, // # of reassociations due to load leveling - IPW_ORD_STAT_ASSN_CAUSE6, //NS // # of reassociations due to dropped by Ap - IPW_FILLER_41, - IPW_FILLER_42, - IPW_FILLER_43, - IPW_ORD_STAT_AUTH_FAIL, // # of times authentication failed - IPW_ORD_STAT_AUTH_RESP_FAIL, // # of times authentication response failed - IPW_ORD_STATION_TABLE_CNT, // # of entries in association table - -// Other statistics - IPW_ORD_RSSI_AVG_CURR = 173, // Current avg RSSI - IPW_ORD_STEST_RESULTS_CURR, //NS // Current self test results word - IPW_ORD_STEST_RESULTS_CUM, //NS // Cummulative self test results word - IPW_ORD_SELF_TEST_STATUS, //NS // - IPW_ORD_POWER_MGMT_MODE, // Power mode - 0=CAM, 1=PSP - IPW_ORD_POWER_MGMT_INDEX, //NS // - IPW_ORD_COUNTRY_CODE, // IEEE country code as recv'd from beacon - IPW_ORD_COUNTRY_CHANNELS, // channels suported by country -// IPW_ORD_COUNTRY_CHANNELS: -// For 11b the lower 2-byte are used for channels from 1-14 -// and the higher 2-byte are not used. - IPW_ORD_RESET_CNT, // # of adapter resets (warm) - IPW_ORD_BEACON_INTERVAL, // Beacon interval - - IPW_ORD_PRINCETON_VERSION = 184, //NS // Princeton Version - IPW_ORD_ANTENNA_DIVERSITY, // TRUE if antenna diversity is disabled - IPW_ORD_CCA_RSSI, //NS // CCA RSSI value (factory programmed) - IPW_ORD_STAT_EEPROM_UPDATE, //NS // # of times config EEPROM updated - IPW_ORD_DTIM_PERIOD, // # of beacon intervals between DTIMs - IPW_ORD_OUR_FREQ, // current radio freq lower digits - channel ID - - IPW_ORD_RTC_TIME = 190, // current RTC time - IPW_ORD_PORT_TYPE, // operating mode - IPW_ORD_CURRENT_TX_RATE, // current tx rate - IPW_ORD_SUPPORTED_RATES, // Bitmap of supported tx rates - IPW_ORD_ATIM_WINDOW, // current ATIM Window - IPW_ORD_BASIC_RATES, // bitmap of basic tx rates - IPW_ORD_NIC_HIGHEST_RATE, // bitmap of basic tx rates - IPW_ORD_AP_HIGHEST_RATE, // bitmap of basic tx rates - IPW_ORD_CAPABILITIES, // Management frame capability field - IPW_ORD_AUTH_TYPE, // Type of authentication - IPW_ORD_RADIO_TYPE, // Adapter card platform type - IPW_ORD_RTS_THRESHOLD = 201, // Min length of packet after which RTS handshaking is used - IPW_ORD_INT_MODE, // International mode - IPW_ORD_FRAGMENTATION_THRESHOLD, // protocol frag threshold - IPW_ORD_EEPROM_SRAM_DB_BLOCK_START_ADDRESS, // EEPROM offset in SRAM - IPW_ORD_EEPROM_SRAM_DB_BLOCK_SIZE, // EEPROM size in SRAM - IPW_ORD_EEPROM_SKU_CAPABILITY, // EEPROM SKU Capability 206 = - IPW_ORD_EEPROM_IBSS_11B_CHANNELS, // EEPROM IBSS 11b channel set - - IPW_ORD_MAC_VERSION = 209, // MAC Version - IPW_ORD_MAC_REVISION, // MAC Revision - IPW_ORD_RADIO_VERSION, // Radio Version - IPW_ORD_NIC_MANF_DATE_TIME, // MANF Date/Time STAMP - IPW_ORD_UCODE_VERSION, // Ucode Version - IPW_ORD_HW_RF_SWITCH_STATE = 214, // HW RF Kill Switch State -} ORDINALTABLE1; - -// ordinal table 2 -// Variable length data: -#define IPW_FIRST_VARIABLE_LENGTH_ORDINAL 1001 - -typedef enum _ORDINAL_TABLE_2 { // NS - means Not Supported by FW - IPW_ORD_STAT_BASE = 1000, // contains number of variable ORDs - IPW_ORD_STAT_ADAPTER_MAC = 1001, // 6 bytes: our adapter MAC address - IPW_ORD_STAT_PREFERRED_BSSID = 1002, // 6 bytes: BSSID of the preferred AP - IPW_ORD_STAT_MANDATORY_BSSID = 1003, // 6 bytes: BSSID of the mandatory AP - IPW_FILL_1, //NS // - IPW_ORD_STAT_COUNTRY_TEXT = 1005, // 36 bytes: Country name text, First two bytes are Country code - IPW_ORD_STAT_ASSN_SSID = 1006, // 32 bytes: ESSID String - IPW_ORD_STATION_TABLE = 1007, // ? bytes: Station/AP table (via Direct SSID Scans) - IPW_ORD_STAT_SWEEP_TABLE = 1008, // ? bytes: Sweep/Host Table table (via Broadcast Scans) - IPW_ORD_STAT_ROAM_LOG = 1009, // ? bytes: Roaming log - IPW_ORD_STAT_RATE_LOG = 1010, //NS // 0 bytes: Rate log - IPW_ORD_STAT_FIFO = 1011, //NS // 0 bytes: Fifo buffer data structures - IPW_ORD_STAT_FW_VER_NUM = 1012, // 14 bytes: fw version ID string as in (a.bb.ccc; "0.08.011") - IPW_ORD_STAT_FW_DATE = 1013, // 14 bytes: fw date string (mmm dd yyyy; "Mar 13 2002") - IPW_ORD_STAT_ASSN_AP_BSSID = 1014, // 6 bytes: MAC address of associated AP - IPW_ORD_STAT_DEBUG = 1015, //NS // ? bytes: - IPW_ORD_STAT_NIC_BPA_NUM = 1016, // 11 bytes: NIC BPA number in ASCII - IPW_ORD_STAT_UCODE_DATE = 1017, // 5 bytes: uCode date - IPW_ORD_SECURITY_NGOTIATION_RESULT = 1018, -} ORDINALTABLE2; // NS - means Not Supported by FW - -#define IPW_LAST_VARIABLE_LENGTH_ORDINAL 1018 - -#ifndef WIRELESS_SPY -#define WIRELESS_SPY // enable iwspy support -#endif - -#define IPW_HOST_FW_SHARED_AREA0 0x0002f200 -#define IPW_HOST_FW_SHARED_AREA0_END 0x0002f510 // 0x310 bytes - -#define IPW_HOST_FW_SHARED_AREA1 0x0002f610 -#define IPW_HOST_FW_SHARED_AREA1_END 0x0002f630 // 0x20 bytes - -#define IPW_HOST_FW_SHARED_AREA2 0x0002fa00 -#define IPW_HOST_FW_SHARED_AREA2_END 0x0002fa20 // 0x20 bytes - -#define IPW_HOST_FW_SHARED_AREA3 0x0002fc00 -#define IPW_HOST_FW_SHARED_AREA3_END 0x0002fc10 // 0x10 bytes - -#define IPW_HOST_FW_INTERRUPT_AREA 0x0002ff80 -#define IPW_HOST_FW_INTERRUPT_AREA_END 0x00030000 // 0x80 bytes - -struct ipw2100_fw_chunk { - unsigned char *buf; - long len; - long pos; - struct list_head list; -}; - -struct ipw2100_fw_chunk_set { - const void *data; - unsigned long size; -}; - -struct ipw2100_fw { - int version; - struct ipw2100_fw_chunk_set fw; - struct ipw2100_fw_chunk_set uc; - const struct firmware *fw_entry; -}; - -#define MAX_FW_VERSION_LEN 14 - -#endif /* _IPW2100_H */ diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c deleted file mode 100644 index a6ca536e44f8..000000000000 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ /dev/null @@ -1,12020 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved. - - 802.11 status code portion of this file from ethereal-0.10.6: - Copyright 2000, Axis Communications AB - Ethereal - Network traffic analyzer - By Gerald Combs - Copyright 1998 Gerald Combs - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -******************************************************************************/ - -#include -#include "ipw2200.h" - - -#ifndef KBUILD_EXTMOD -#define VK "k" -#else -#define VK -#endif - -#ifdef CONFIG_IPW2200_DEBUG -#define VD "d" -#else -#define VD -#endif - -#ifdef CONFIG_IPW2200_MONITOR -#define VM "m" -#else -#define VM -#endif - -#ifdef CONFIG_IPW2200_PROMISCUOUS -#define VP "p" -#else -#define VP -#endif - -#ifdef CONFIG_IPW2200_RADIOTAP -#define VR "r" -#else -#define VR -#endif - -#ifdef CONFIG_IPW2200_QOS -#define VQ "q" -#else -#define VQ -#endif - -#define IPW2200_VERSION "1.2.2" VK VD VM VP VR VQ -#define DRV_DESCRIPTION "Intel(R) PRO/Wireless 2200/2915 Network Driver" -#define DRV_COPYRIGHT "Copyright(c) 2003-2006 Intel Corporation" -#define DRV_VERSION IPW2200_VERSION - -#define ETH_P_80211_STATS (ETH_P_80211_RAW + 1) - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); - -static int cmdlog = 0; -static int debug = 0; -static int default_channel = 0; -static int network_mode = 0; - -static u32 ipw_debug_level; -static int associate; -static int auto_create = 1; -static int led_support = 0; -static int disable = 0; -static int bt_coexist = 0; -static int hwcrypto = 0; -static int roaming = 1; -static const char ipw_modes[] = { - 'a', 'b', 'g', '?' -}; -static int antenna = CFG_SYS_ANTENNA_BOTH; - -#ifdef CONFIG_IPW2200_PROMISCUOUS -static int rtap_iface = 0; /* def: 0 -- do not create rtap interface */ -#endif - - -#ifdef CONFIG_IPW2200_QOS -static int qos_enable = 0; -static int qos_burst_enable = 0; -static int qos_no_ack_mask = 0; -static int burst_duration_CCK = 0; -static int burst_duration_OFDM = 0; - -static struct libipw_qos_parameters def_qos_parameters_OFDM = { - {QOS_TX0_CW_MIN_OFDM, QOS_TX1_CW_MIN_OFDM, QOS_TX2_CW_MIN_OFDM, - QOS_TX3_CW_MIN_OFDM}, - {QOS_TX0_CW_MAX_OFDM, QOS_TX1_CW_MAX_OFDM, QOS_TX2_CW_MAX_OFDM, - QOS_TX3_CW_MAX_OFDM}, - {QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS}, - {QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM}, - {QOS_TX0_TXOP_LIMIT_OFDM, QOS_TX1_TXOP_LIMIT_OFDM, - QOS_TX2_TXOP_LIMIT_OFDM, QOS_TX3_TXOP_LIMIT_OFDM} -}; - -static struct libipw_qos_parameters def_qos_parameters_CCK = { - {QOS_TX0_CW_MIN_CCK, QOS_TX1_CW_MIN_CCK, QOS_TX2_CW_MIN_CCK, - QOS_TX3_CW_MIN_CCK}, - {QOS_TX0_CW_MAX_CCK, QOS_TX1_CW_MAX_CCK, QOS_TX2_CW_MAX_CCK, - QOS_TX3_CW_MAX_CCK}, - {QOS_TX0_AIFS, QOS_TX1_AIFS, QOS_TX2_AIFS, QOS_TX3_AIFS}, - {QOS_TX0_ACM, QOS_TX1_ACM, QOS_TX2_ACM, QOS_TX3_ACM}, - {QOS_TX0_TXOP_LIMIT_CCK, QOS_TX1_TXOP_LIMIT_CCK, QOS_TX2_TXOP_LIMIT_CCK, - QOS_TX3_TXOP_LIMIT_CCK} -}; - -static struct libipw_qos_parameters def_parameters_OFDM = { - {DEF_TX0_CW_MIN_OFDM, DEF_TX1_CW_MIN_OFDM, DEF_TX2_CW_MIN_OFDM, - DEF_TX3_CW_MIN_OFDM}, - {DEF_TX0_CW_MAX_OFDM, DEF_TX1_CW_MAX_OFDM, DEF_TX2_CW_MAX_OFDM, - DEF_TX3_CW_MAX_OFDM}, - {DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS}, - {DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM}, - {DEF_TX0_TXOP_LIMIT_OFDM, DEF_TX1_TXOP_LIMIT_OFDM, - DEF_TX2_TXOP_LIMIT_OFDM, DEF_TX3_TXOP_LIMIT_OFDM} -}; - -static struct libipw_qos_parameters def_parameters_CCK = { - {DEF_TX0_CW_MIN_CCK, DEF_TX1_CW_MIN_CCK, DEF_TX2_CW_MIN_CCK, - DEF_TX3_CW_MIN_CCK}, - {DEF_TX0_CW_MAX_CCK, DEF_TX1_CW_MAX_CCK, DEF_TX2_CW_MAX_CCK, - DEF_TX3_CW_MAX_CCK}, - {DEF_TX0_AIFS, DEF_TX1_AIFS, DEF_TX2_AIFS, DEF_TX3_AIFS}, - {DEF_TX0_ACM, DEF_TX1_ACM, DEF_TX2_ACM, DEF_TX3_ACM}, - {DEF_TX0_TXOP_LIMIT_CCK, DEF_TX1_TXOP_LIMIT_CCK, DEF_TX2_TXOP_LIMIT_CCK, - DEF_TX3_TXOP_LIMIT_CCK} -}; - -static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; - -static int from_priority_to_tx_queue[] = { - IPW_TX_QUEUE_1, IPW_TX_QUEUE_2, IPW_TX_QUEUE_2, IPW_TX_QUEUE_1, - IPW_TX_QUEUE_3, IPW_TX_QUEUE_3, IPW_TX_QUEUE_4, IPW_TX_QUEUE_4 -}; - -static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv); - -static int ipw_send_qos_params_command(struct ipw_priv *priv, struct libipw_qos_parameters - *qos_param); -static int ipw_send_qos_info_command(struct ipw_priv *priv, struct libipw_qos_information_element - *qos_param); -#endif /* CONFIG_IPW2200_QOS */ - -static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev); -static void ipw_remove_current_network(struct ipw_priv *priv); -static void ipw_rx(struct ipw_priv *priv); -static int ipw_queue_tx_reclaim(struct ipw_priv *priv, - struct clx2_tx_queue *txq, int qindex); -static int ipw_queue_reset(struct ipw_priv *priv); - -static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, - int len, int sync); - -static void ipw_tx_queue_free(struct ipw_priv *); - -static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *); -static void ipw_rx_queue_free(struct ipw_priv *, struct ipw_rx_queue *); -static void ipw_rx_queue_replenish(void *); -static int ipw_up(struct ipw_priv *); -static void ipw_bg_up(struct work_struct *work); -static void ipw_down(struct ipw_priv *); -static void ipw_bg_down(struct work_struct *work); -static int ipw_config(struct ipw_priv *); -static int init_supported_rates(struct ipw_priv *priv, - struct ipw_supported_rates *prates); -static void ipw_set_hwcrypto_keys(struct ipw_priv *); -static void ipw_send_wep_keys(struct ipw_priv *, int); - -static int snprint_line(char *buf, size_t count, - const u8 * data, u32 len, u32 ofs) -{ - int out, i, j, l; - char c; - - out = snprintf(buf, count, "%08X", ofs); - - for (l = 0, i = 0; i < 2; i++) { - out += snprintf(buf + out, count - out, " "); - for (j = 0; j < 8 && l < len; j++, l++) - out += snprintf(buf + out, count - out, "%02X ", - data[(i * 8 + j)]); - for (; j < 8; j++) - out += snprintf(buf + out, count - out, " "); - } - - out += snprintf(buf + out, count - out, " "); - for (l = 0, i = 0; i < 2; i++) { - out += snprintf(buf + out, count - out, " "); - for (j = 0; j < 8 && l < len; j++, l++) { - c = data[(i * 8 + j)]; - if (!isascii(c) || !isprint(c)) - c = '.'; - - out += snprintf(buf + out, count - out, "%c", c); - } - - for (; j < 8; j++) - out += snprintf(buf + out, count - out, " "); - } - - return out; -} - -static void printk_buf(int level, const u8 * data, u32 len) -{ - char line[81]; - u32 ofs = 0; - if (!(ipw_debug_level & level)) - return; - - while (len) { - snprint_line(line, sizeof(line), &data[ofs], - min(len, 16U), ofs); - printk(KERN_DEBUG "%s\n", line); - ofs += 16; - len -= min(len, 16U); - } -} - -static int snprintk_buf(u8 * output, size_t size, const u8 * data, size_t len) -{ - size_t out = size; - u32 ofs = 0; - int total = 0; - - while (size && len) { - out = snprint_line(output, size, &data[ofs], - min_t(size_t, len, 16U), ofs); - - ofs += 16; - output += out; - size -= out; - len -= min_t(size_t, len, 16U); - total += out; - } - return total; -} - -/* alias for 32-bit indirect read (for SRAM/reg above 4K), with debug wrapper */ -static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg); -#define ipw_read_reg32(a, b) _ipw_read_reg32(a, b) - -/* alias for 8-bit indirect read (for SRAM/reg above 4K), with debug wrapper */ -static u8 _ipw_read_reg8(struct ipw_priv *ipw, u32 reg); -#define ipw_read_reg8(a, b) _ipw_read_reg8(a, b) - -/* 8-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ -static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value); -static inline void ipw_write_reg8(struct ipw_priv *a, u32 b, u8 c) -{ - IPW_DEBUG_IO("%s %d: write_indirect8(0x%08X, 0x%08X)\n", __FILE__, - __LINE__, (u32) (b), (u32) (c)); - _ipw_write_reg8(a, b, c); -} - -/* 16-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ -static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value); -static inline void ipw_write_reg16(struct ipw_priv *a, u32 b, u16 c) -{ - IPW_DEBUG_IO("%s %d: write_indirect16(0x%08X, 0x%08X)\n", __FILE__, - __LINE__, (u32) (b), (u32) (c)); - _ipw_write_reg16(a, b, c); -} - -/* 32-bit indirect write (for SRAM/reg above 4K), with debug wrapper */ -static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value); -static inline void ipw_write_reg32(struct ipw_priv *a, u32 b, u32 c) -{ - IPW_DEBUG_IO("%s %d: write_indirect32(0x%08X, 0x%08X)\n", __FILE__, - __LINE__, (u32) (b), (u32) (c)); - _ipw_write_reg32(a, b, c); -} - -/* 8-bit direct write (low 4K) */ -static inline void _ipw_write8(struct ipw_priv *ipw, unsigned long ofs, - u8 val) -{ - writeb(val, ipw->hw_base + ofs); -} - -/* 8-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ -#define ipw_write8(ipw, ofs, val) do { \ - IPW_DEBUG_IO("%s %d: write_direct8(0x%08X, 0x%08X)\n", __FILE__, \ - __LINE__, (u32)(ofs), (u32)(val)); \ - _ipw_write8(ipw, ofs, val); \ -} while (0) - -/* 16-bit direct write (low 4K) */ -static inline void _ipw_write16(struct ipw_priv *ipw, unsigned long ofs, - u16 val) -{ - writew(val, ipw->hw_base + ofs); -} - -/* 16-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ -#define ipw_write16(ipw, ofs, val) do { \ - IPW_DEBUG_IO("%s %d: write_direct16(0x%08X, 0x%08X)\n", __FILE__, \ - __LINE__, (u32)(ofs), (u32)(val)); \ - _ipw_write16(ipw, ofs, val); \ -} while (0) - -/* 32-bit direct write (low 4K) */ -static inline void _ipw_write32(struct ipw_priv *ipw, unsigned long ofs, - u32 val) -{ - writel(val, ipw->hw_base + ofs); -} - -/* 32-bit direct write (for low 4K of SRAM/regs), with debug wrapper */ -#define ipw_write32(ipw, ofs, val) do { \ - IPW_DEBUG_IO("%s %d: write_direct32(0x%08X, 0x%08X)\n", __FILE__, \ - __LINE__, (u32)(ofs), (u32)(val)); \ - _ipw_write32(ipw, ofs, val); \ -} while (0) - -/* 8-bit direct read (low 4K) */ -static inline u8 _ipw_read8(struct ipw_priv *ipw, unsigned long ofs) -{ - return readb(ipw->hw_base + ofs); -} - -/* alias to 8-bit direct read (low 4K of SRAM/regs), with debug wrapper */ -#define ipw_read8(ipw, ofs) ({ \ - IPW_DEBUG_IO("%s %d: read_direct8(0x%08X)\n", __FILE__, __LINE__, \ - (u32)(ofs)); \ - _ipw_read8(ipw, ofs); \ -}) - -/* 16-bit direct read (low 4K) */ -static inline u16 _ipw_read16(struct ipw_priv *ipw, unsigned long ofs) -{ - return readw(ipw->hw_base + ofs); -} - -/* alias to 16-bit direct read (low 4K of SRAM/regs), with debug wrapper */ -#define ipw_read16(ipw, ofs) ({ \ - IPW_DEBUG_IO("%s %d: read_direct16(0x%08X)\n", __FILE__, __LINE__, \ - (u32)(ofs)); \ - _ipw_read16(ipw, ofs); \ -}) - -/* 32-bit direct read (low 4K) */ -static inline u32 _ipw_read32(struct ipw_priv *ipw, unsigned long ofs) -{ - return readl(ipw->hw_base + ofs); -} - -/* alias to 32-bit direct read (low 4K of SRAM/regs), with debug wrapper */ -#define ipw_read32(ipw, ofs) ({ \ - IPW_DEBUG_IO("%s %d: read_direct32(0x%08X)\n", __FILE__, __LINE__, \ - (u32)(ofs)); \ - _ipw_read32(ipw, ofs); \ -}) - -static void _ipw_read_indirect(struct ipw_priv *, u32, u8 *, int); -/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */ -#define ipw_read_indirect(a, b, c, d) ({ \ - IPW_DEBUG_IO("%s %d: read_indirect(0x%08X) %u bytes\n", __FILE__, \ - __LINE__, (u32)(b), (u32)(d)); \ - _ipw_read_indirect(a, b, c, d); \ -}) - -/* alias to multi-byte read (SRAM/regs above 4K), with debug wrapper */ -static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * data, - int num); -#define ipw_write_indirect(a, b, c, d) do { \ - IPW_DEBUG_IO("%s %d: write_indirect(0x%08X) %u bytes\n", __FILE__, \ - __LINE__, (u32)(b), (u32)(d)); \ - _ipw_write_indirect(a, b, c, d); \ -} while (0) - -/* 32-bit indirect write (above 4K) */ -static void _ipw_write_reg32(struct ipw_priv *priv, u32 reg, u32 value) -{ - IPW_DEBUG_IO(" %p : reg = 0x%8X : value = 0x%8X\n", priv, reg, value); - _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); - _ipw_write32(priv, IPW_INDIRECT_DATA, value); -} - -/* 8-bit indirect write (above 4K) */ -static void _ipw_write_reg8(struct ipw_priv *priv, u32 reg, u8 value) -{ - u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ - u32 dif_len = reg - aligned_addr; - - IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); - _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - _ipw_write8(priv, IPW_INDIRECT_DATA + dif_len, value); -} - -/* 16-bit indirect write (above 4K) */ -static void _ipw_write_reg16(struct ipw_priv *priv, u32 reg, u16 value) -{ - u32 aligned_addr = reg & IPW_INDIRECT_ADDR_MASK; /* dword align */ - u32 dif_len = (reg - aligned_addr) & (~0x1ul); - - IPW_DEBUG_IO(" reg = 0x%8X : value = 0x%8X\n", reg, value); - _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - _ipw_write16(priv, IPW_INDIRECT_DATA + dif_len, value); -} - -/* 8-bit indirect read (above 4K) */ -static u8 _ipw_read_reg8(struct ipw_priv *priv, u32 reg) -{ - u32 word; - _ipw_write32(priv, IPW_INDIRECT_ADDR, reg & IPW_INDIRECT_ADDR_MASK); - IPW_DEBUG_IO(" reg = 0x%8X : \n", reg); - word = _ipw_read32(priv, IPW_INDIRECT_DATA); - return (word >> ((reg & 0x3) * 8)) & 0xff; -} - -/* 32-bit indirect read (above 4K) */ -static u32 _ipw_read_reg32(struct ipw_priv *priv, u32 reg) -{ - u32 value; - - IPW_DEBUG_IO("%p : reg = 0x%08x\n", priv, reg); - - _ipw_write32(priv, IPW_INDIRECT_ADDR, reg); - value = _ipw_read32(priv, IPW_INDIRECT_DATA); - IPW_DEBUG_IO(" reg = 0x%4X : value = 0x%4x \n", reg, value); - return value; -} - -/* General purpose, no alignment requirement, iterative (multi-byte) read, */ -/* for area above 1st 4K of SRAM/reg space */ -static void _ipw_read_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, - int num) -{ - u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ - u32 dif_len = addr - aligned_addr; - u32 i; - - IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num); - - if (num <= 0) { - return; - } - - /* Read the first dword (or portion) byte by byte */ - if (unlikely(dif_len)) { - _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - /* Start reading at aligned_addr + dif_len */ - for (i = dif_len; ((i < 4) && (num > 0)); i++, num--) - *buf++ = _ipw_read8(priv, IPW_INDIRECT_DATA + i); - aligned_addr += 4; - } - - /* Read all of the middle dwords as dwords, with auto-increment */ - _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); - for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) - *(u32 *) buf = _ipw_read32(priv, IPW_AUTOINC_DATA); - - /* Read the last dword (or portion) byte by byte */ - if (unlikely(num)) { - _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - for (i = 0; num > 0; i++, num--) - *buf++ = ipw_read8(priv, IPW_INDIRECT_DATA + i); - } -} - -/* General purpose, no alignment requirement, iterative (multi-byte) write, */ -/* for area above 1st 4K of SRAM/reg space */ -static void _ipw_write_indirect(struct ipw_priv *priv, u32 addr, u8 * buf, - int num) -{ - u32 aligned_addr = addr & IPW_INDIRECT_ADDR_MASK; /* dword align */ - u32 dif_len = addr - aligned_addr; - u32 i; - - IPW_DEBUG_IO("addr = %i, buf = %p, num = %i\n", addr, buf, num); - - if (num <= 0) { - return; - } - - /* Write the first dword (or portion) byte by byte */ - if (unlikely(dif_len)) { - _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - /* Start writing at aligned_addr + dif_len */ - for (i = dif_len; ((i < 4) && (num > 0)); i++, num--, buf++) - _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); - aligned_addr += 4; - } - - /* Write all of the middle dwords as dwords, with auto-increment */ - _ipw_write32(priv, IPW_AUTOINC_ADDR, aligned_addr); - for (; num >= 4; buf += 4, aligned_addr += 4, num -= 4) - _ipw_write32(priv, IPW_AUTOINC_DATA, *(u32 *) buf); - - /* Write the last dword (or portion) byte by byte */ - if (unlikely(num)) { - _ipw_write32(priv, IPW_INDIRECT_ADDR, aligned_addr); - for (i = 0; num > 0; i++, num--, buf++) - _ipw_write8(priv, IPW_INDIRECT_DATA + i, *buf); - } -} - -/* General purpose, no alignment requirement, iterative (multi-byte) write, */ -/* for 1st 4K of SRAM/regs space */ -static void ipw_write_direct(struct ipw_priv *priv, u32 addr, void *buf, - int num) -{ - memcpy_toio((priv->hw_base + addr), buf, num); -} - -/* Set bit(s) in low 4K of SRAM/regs */ -static inline void ipw_set_bit(struct ipw_priv *priv, u32 reg, u32 mask) -{ - ipw_write32(priv, reg, ipw_read32(priv, reg) | mask); -} - -/* Clear bit(s) in low 4K of SRAM/regs */ -static inline void ipw_clear_bit(struct ipw_priv *priv, u32 reg, u32 mask) -{ - ipw_write32(priv, reg, ipw_read32(priv, reg) & ~mask); -} - -static inline void __ipw_enable_interrupts(struct ipw_priv *priv) -{ - if (priv->status & STATUS_INT_ENABLED) - return; - priv->status |= STATUS_INT_ENABLED; - ipw_write32(priv, IPW_INTA_MASK_R, IPW_INTA_MASK_ALL); -} - -static inline void __ipw_disable_interrupts(struct ipw_priv *priv) -{ - if (!(priv->status & STATUS_INT_ENABLED)) - return; - priv->status &= ~STATUS_INT_ENABLED; - ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); -} - -static inline void ipw_enable_interrupts(struct ipw_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->irq_lock, flags); - __ipw_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->irq_lock, flags); -} - -static inline void ipw_disable_interrupts(struct ipw_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->irq_lock, flags); - __ipw_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->irq_lock, flags); -} - -static char *ipw_error_desc(u32 val) -{ - switch (val) { - case IPW_FW_ERROR_OK: - return "ERROR_OK"; - case IPW_FW_ERROR_FAIL: - return "ERROR_FAIL"; - case IPW_FW_ERROR_MEMORY_UNDERFLOW: - return "MEMORY_UNDERFLOW"; - case IPW_FW_ERROR_MEMORY_OVERFLOW: - return "MEMORY_OVERFLOW"; - case IPW_FW_ERROR_BAD_PARAM: - return "BAD_PARAM"; - case IPW_FW_ERROR_BAD_CHECKSUM: - return "BAD_CHECKSUM"; - case IPW_FW_ERROR_NMI_INTERRUPT: - return "NMI_INTERRUPT"; - case IPW_FW_ERROR_BAD_DATABASE: - return "BAD_DATABASE"; - case IPW_FW_ERROR_ALLOC_FAIL: - return "ALLOC_FAIL"; - case IPW_FW_ERROR_DMA_UNDERRUN: - return "DMA_UNDERRUN"; - case IPW_FW_ERROR_DMA_STATUS: - return "DMA_STATUS"; - case IPW_FW_ERROR_DINO_ERROR: - return "DINO_ERROR"; - case IPW_FW_ERROR_EEPROM_ERROR: - return "EEPROM_ERROR"; - case IPW_FW_ERROR_SYSASSERT: - return "SYSASSERT"; - case IPW_FW_ERROR_FATAL_ERROR: - return "FATAL_ERROR"; - default: - return "UNKNOWN_ERROR"; - } -} - -static void ipw_dump_error_log(struct ipw_priv *priv, - struct ipw_fw_error *error) -{ - u32 i; - - if (!error) { - IPW_ERROR("Error allocating and capturing error log. " - "Nothing to dump.\n"); - return; - } - - IPW_ERROR("Start IPW Error Log Dump:\n"); - IPW_ERROR("Status: 0x%08X, Config: %08X\n", - error->status, error->config); - - for (i = 0; i < error->elem_len; i++) - IPW_ERROR("%s %i 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", - ipw_error_desc(error->elem[i].desc), - error->elem[i].time, - error->elem[i].blink1, - error->elem[i].blink2, - error->elem[i].link1, - error->elem[i].link2, error->elem[i].data); - for (i = 0; i < error->log_len; i++) - IPW_ERROR("%i\t0x%08x\t%i\n", - error->log[i].time, - error->log[i].data, error->log[i].event); -} - -static inline int ipw_is_init(struct ipw_priv *priv) -{ - return (priv->status & STATUS_INIT) ? 1 : 0; -} - -static int ipw_get_ordinal(struct ipw_priv *priv, u32 ord, void *val, u32 * len) -{ - u32 addr, field_info, field_len, field_count, total_len; - - IPW_DEBUG_ORD("ordinal = %i\n", ord); - - if (!priv || !val || !len) { - IPW_DEBUG_ORD("Invalid argument\n"); - return -EINVAL; - } - - /* verify device ordinal tables have been initialized */ - if (!priv->table0_addr || !priv->table1_addr || !priv->table2_addr) { - IPW_DEBUG_ORD("Access ordinals before initialization\n"); - return -EINVAL; - } - - switch (IPW_ORD_TABLE_ID_MASK & ord) { - case IPW_ORD_TABLE_0_MASK: - /* - * TABLE 0: Direct access to a table of 32 bit values - * - * This is a very simple table with the data directly - * read from the table - */ - - /* remove the table id from the ordinal */ - ord &= IPW_ORD_TABLE_VALUE_MASK; - - /* boundary check */ - if (ord > priv->table0_len) { - IPW_DEBUG_ORD("ordinal value (%i) longer then " - "max (%i)\n", ord, priv->table0_len); - return -EINVAL; - } - - /* verify we have enough room to store the value */ - if (*len < sizeof(u32)) { - IPW_DEBUG_ORD("ordinal buffer length too small, " - "need %zd\n", sizeof(u32)); - return -EINVAL; - } - - IPW_DEBUG_ORD("Reading TABLE0[%i] from offset 0x%08x\n", - ord, priv->table0_addr + (ord << 2)); - - *len = sizeof(u32); - ord <<= 2; - *((u32 *) val) = ipw_read32(priv, priv->table0_addr + ord); - break; - - case IPW_ORD_TABLE_1_MASK: - /* - * TABLE 1: Indirect access to a table of 32 bit values - * - * This is a fairly large table of u32 values each - * representing starting addr for the data (which is - * also a u32) - */ - - /* remove the table id from the ordinal */ - ord &= IPW_ORD_TABLE_VALUE_MASK; - - /* boundary check */ - if (ord > priv->table1_len) { - IPW_DEBUG_ORD("ordinal value too long\n"); - return -EINVAL; - } - - /* verify we have enough room to store the value */ - if (*len < sizeof(u32)) { - IPW_DEBUG_ORD("ordinal buffer length too small, " - "need %zd\n", sizeof(u32)); - return -EINVAL; - } - - *((u32 *) val) = - ipw_read_reg32(priv, (priv->table1_addr + (ord << 2))); - *len = sizeof(u32); - break; - - case IPW_ORD_TABLE_2_MASK: - /* - * TABLE 2: Indirect access to a table of variable sized values - * - * This table consist of six values, each containing - * - dword containing the starting offset of the data - * - dword containing the lengh in the first 16bits - * and the count in the second 16bits - */ - - /* remove the table id from the ordinal */ - ord &= IPW_ORD_TABLE_VALUE_MASK; - - /* boundary check */ - if (ord > priv->table2_len) { - IPW_DEBUG_ORD("ordinal value too long\n"); - return -EINVAL; - } - - /* get the address of statistic */ - addr = ipw_read_reg32(priv, priv->table2_addr + (ord << 3)); - - /* get the second DW of statistics ; - * two 16-bit words - first is length, second is count */ - field_info = - ipw_read_reg32(priv, - priv->table2_addr + (ord << 3) + - sizeof(u32)); - - /* get each entry length */ - field_len = *((u16 *) & field_info); - - /* get number of entries */ - field_count = *(((u16 *) & field_info) + 1); - - /* abort if not enought memory */ - total_len = field_len * field_count; - if (total_len > *len) { - *len = total_len; - return -EINVAL; - } - - *len = total_len; - if (!total_len) - return 0; - - IPW_DEBUG_ORD("addr = 0x%08x, total_len = %i, " - "field_info = 0x%08x\n", - addr, total_len, field_info); - ipw_read_indirect(priv, addr, val, total_len); - break; - - default: - IPW_DEBUG_ORD("Invalid ordinal!\n"); - return -EINVAL; - - } - - return 0; -} - -static void ipw_init_ordinals(struct ipw_priv *priv) -{ - priv->table0_addr = IPW_ORDINALS_TABLE_LOWER; - priv->table0_len = ipw_read32(priv, priv->table0_addr); - - IPW_DEBUG_ORD("table 0 offset at 0x%08x, len = %i\n", - priv->table0_addr, priv->table0_len); - - priv->table1_addr = ipw_read32(priv, IPW_ORDINALS_TABLE_1); - priv->table1_len = ipw_read_reg32(priv, priv->table1_addr); - - IPW_DEBUG_ORD("table 1 offset at 0x%08x, len = %i\n", - priv->table1_addr, priv->table1_len); - - priv->table2_addr = ipw_read32(priv, IPW_ORDINALS_TABLE_2); - priv->table2_len = ipw_read_reg32(priv, priv->table2_addr); - priv->table2_len &= 0x0000ffff; /* use first two bytes */ - - IPW_DEBUG_ORD("table 2 offset at 0x%08x, len = %i\n", - priv->table2_addr, priv->table2_len); - -} - -static u32 ipw_register_toggle(u32 reg) -{ - reg &= ~IPW_START_STANDBY; - if (reg & IPW_GATE_ODMA) - reg &= ~IPW_GATE_ODMA; - if (reg & IPW_GATE_IDMA) - reg &= ~IPW_GATE_IDMA; - if (reg & IPW_GATE_ADMA) - reg &= ~IPW_GATE_ADMA; - return reg; -} - -/* - * LED behavior: - * - On radio ON, turn on any LEDs that require to be on during start - * - On initialization, start unassociated blink - * - On association, disable unassociated blink - * - On disassociation, start unassociated blink - * - On radio OFF, turn off any LEDs started during radio on - * - */ -#define LD_TIME_LINK_ON msecs_to_jiffies(300) -#define LD_TIME_LINK_OFF msecs_to_jiffies(2700) -#define LD_TIME_ACT_ON msecs_to_jiffies(250) - -static void ipw_led_link_on(struct ipw_priv *priv) -{ - unsigned long flags; - u32 led; - - /* If configured to not use LEDs, or nic_type is 1, - * then we don't toggle a LINK led */ - if (priv->config & CFG_NO_LED || priv->nic_type == EEPROM_NIC_TYPE_1) - return; - - spin_lock_irqsave(&priv->lock, flags); - - if (!(priv->status & STATUS_RF_KILL_MASK) && - !(priv->status & STATUS_LED_LINK_ON)) { - IPW_DEBUG_LED("Link LED On\n"); - led = ipw_read_reg32(priv, IPW_EVENT_REG); - led |= priv->led_association_on; - - led = ipw_register_toggle(led); - - IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, IPW_EVENT_REG, led); - - priv->status |= STATUS_LED_LINK_ON; - - /* If we aren't associated, schedule turning the LED off */ - if (!(priv->status & STATUS_ASSOCIATED)) - queue_delayed_work(priv->workqueue, - &priv->led_link_off, - LD_TIME_LINK_ON); - } - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void ipw_bg_led_link_on(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, led_link_on.work); - mutex_lock(&priv->mutex); - ipw_led_link_on(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_led_link_off(struct ipw_priv *priv) -{ - unsigned long flags; - u32 led; - - /* If configured not to use LEDs, or nic type is 1, - * then we don't goggle the LINK led. */ - if (priv->config & CFG_NO_LED || priv->nic_type == EEPROM_NIC_TYPE_1) - return; - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->status & STATUS_LED_LINK_ON) { - led = ipw_read_reg32(priv, IPW_EVENT_REG); - led &= priv->led_association_off; - led = ipw_register_toggle(led); - - IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, IPW_EVENT_REG, led); - - IPW_DEBUG_LED("Link LED Off\n"); - - priv->status &= ~STATUS_LED_LINK_ON; - - /* If we aren't associated and the radio is on, schedule - * turning the LED on (blink while unassociated) */ - if (!(priv->status & STATUS_RF_KILL_MASK) && - !(priv->status & STATUS_ASSOCIATED)) - queue_delayed_work(priv->workqueue, &priv->led_link_on, - LD_TIME_LINK_OFF); - - } - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void ipw_bg_led_link_off(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, led_link_off.work); - mutex_lock(&priv->mutex); - ipw_led_link_off(priv); - mutex_unlock(&priv->mutex); -} - -static void __ipw_led_activity_on(struct ipw_priv *priv) -{ - u32 led; - - if (priv->config & CFG_NO_LED) - return; - - if (priv->status & STATUS_RF_KILL_MASK) - return; - - if (!(priv->status & STATUS_LED_ACT_ON)) { - led = ipw_read_reg32(priv, IPW_EVENT_REG); - led |= priv->led_activity_on; - - led = ipw_register_toggle(led); - - IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, IPW_EVENT_REG, led); - - IPW_DEBUG_LED("Activity LED On\n"); - - priv->status |= STATUS_LED_ACT_ON; - - cancel_delayed_work(&priv->led_act_off); - queue_delayed_work(priv->workqueue, &priv->led_act_off, - LD_TIME_ACT_ON); - } else { - /* Reschedule LED off for full time period */ - cancel_delayed_work(&priv->led_act_off); - queue_delayed_work(priv->workqueue, &priv->led_act_off, - LD_TIME_ACT_ON); - } -} - -#if 0 -void ipw_led_activity_on(struct ipw_priv *priv) -{ - unsigned long flags; - spin_lock_irqsave(&priv->lock, flags); - __ipw_led_activity_on(priv); - spin_unlock_irqrestore(&priv->lock, flags); -} -#endif /* 0 */ - -static void ipw_led_activity_off(struct ipw_priv *priv) -{ - unsigned long flags; - u32 led; - - if (priv->config & CFG_NO_LED) - return; - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->status & STATUS_LED_ACT_ON) { - led = ipw_read_reg32(priv, IPW_EVENT_REG); - led &= priv->led_activity_off; - - led = ipw_register_toggle(led); - - IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, IPW_EVENT_REG, led); - - IPW_DEBUG_LED("Activity LED Off\n"); - - priv->status &= ~STATUS_LED_ACT_ON; - } - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void ipw_bg_led_activity_off(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, led_act_off.work); - mutex_lock(&priv->mutex); - ipw_led_activity_off(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_led_band_on(struct ipw_priv *priv) -{ - unsigned long flags; - u32 led; - - /* Only nic type 1 supports mode LEDs */ - if (priv->config & CFG_NO_LED || - priv->nic_type != EEPROM_NIC_TYPE_1 || !priv->assoc_network) - return; - - spin_lock_irqsave(&priv->lock, flags); - - led = ipw_read_reg32(priv, IPW_EVENT_REG); - if (priv->assoc_network->mode == IEEE_A) { - led |= priv->led_ofdm_on; - led &= priv->led_association_off; - IPW_DEBUG_LED("Mode LED On: 802.11a\n"); - } else if (priv->assoc_network->mode == IEEE_G) { - led |= priv->led_ofdm_on; - led |= priv->led_association_on; - IPW_DEBUG_LED("Mode LED On: 802.11g\n"); - } else { - led &= priv->led_ofdm_off; - led |= priv->led_association_on; - IPW_DEBUG_LED("Mode LED On: 802.11b\n"); - } - - led = ipw_register_toggle(led); - - IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, IPW_EVENT_REG, led); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void ipw_led_band_off(struct ipw_priv *priv) -{ - unsigned long flags; - u32 led; - - /* Only nic type 1 supports mode LEDs */ - if (priv->config & CFG_NO_LED || priv->nic_type != EEPROM_NIC_TYPE_1) - return; - - spin_lock_irqsave(&priv->lock, flags); - - led = ipw_read_reg32(priv, IPW_EVENT_REG); - led &= priv->led_ofdm_off; - led &= priv->led_association_off; - - led = ipw_register_toggle(led); - - IPW_DEBUG_LED("Reg: 0x%08X\n", led); - ipw_write_reg32(priv, IPW_EVENT_REG, led); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void ipw_led_radio_on(struct ipw_priv *priv) -{ - ipw_led_link_on(priv); -} - -static void ipw_led_radio_off(struct ipw_priv *priv) -{ - ipw_led_activity_off(priv); - ipw_led_link_off(priv); -} - -static void ipw_led_link_up(struct ipw_priv *priv) -{ - /* Set the Link Led on for all nic types */ - ipw_led_link_on(priv); -} - -static void ipw_led_link_down(struct ipw_priv *priv) -{ - ipw_led_activity_off(priv); - ipw_led_link_off(priv); - - if (priv->status & STATUS_RF_KILL_MASK) - ipw_led_radio_off(priv); -} - -static void ipw_led_init(struct ipw_priv *priv) -{ - priv->nic_type = priv->eeprom[EEPROM_NIC_TYPE]; - - /* Set the default PINs for the link and activity leds */ - priv->led_activity_on = IPW_ACTIVITY_LED; - priv->led_activity_off = ~(IPW_ACTIVITY_LED); - - priv->led_association_on = IPW_ASSOCIATED_LED; - priv->led_association_off = ~(IPW_ASSOCIATED_LED); - - /* Set the default PINs for the OFDM leds */ - priv->led_ofdm_on = IPW_OFDM_LED; - priv->led_ofdm_off = ~(IPW_OFDM_LED); - - switch (priv->nic_type) { - case EEPROM_NIC_TYPE_1: - /* In this NIC type, the LEDs are reversed.... */ - priv->led_activity_on = IPW_ASSOCIATED_LED; - priv->led_activity_off = ~(IPW_ASSOCIATED_LED); - priv->led_association_on = IPW_ACTIVITY_LED; - priv->led_association_off = ~(IPW_ACTIVITY_LED); - - if (!(priv->config & CFG_NO_LED)) - ipw_led_band_on(priv); - - /* And we don't blink link LEDs for this nic, so - * just return here */ - return; - - case EEPROM_NIC_TYPE_3: - case EEPROM_NIC_TYPE_2: - case EEPROM_NIC_TYPE_4: - case EEPROM_NIC_TYPE_0: - break; - - default: - IPW_DEBUG_INFO("Unknown NIC type from EEPROM: %d\n", - priv->nic_type); - priv->nic_type = EEPROM_NIC_TYPE_0; - break; - } - - if (!(priv->config & CFG_NO_LED)) { - if (priv->status & STATUS_ASSOCIATED) - ipw_led_link_on(priv); - else - ipw_led_link_off(priv); - } -} - -static void ipw_led_shutdown(struct ipw_priv *priv) -{ - ipw_led_activity_off(priv); - ipw_led_link_off(priv); - ipw_led_band_off(priv); - cancel_delayed_work(&priv->led_link_on); - cancel_delayed_work(&priv->led_link_off); - cancel_delayed_work(&priv->led_act_off); -} - -/* - * The following adds a new attribute to the sysfs representation - * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/) - * used for controling the debug level. - * - * See the level definitions in ipw for details. - */ -static ssize_t show_debug_level(struct device_driver *d, char *buf) -{ - return sprintf(buf, "0x%08X\n", ipw_debug_level); -} - -static ssize_t store_debug_level(struct device_driver *d, const char *buf, - size_t count) -{ - char *p = (char *)buf; - u32 val; - - if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { - p++; - if (p[0] == 'x' || p[0] == 'X') - p++; - val = simple_strtoul(p, &p, 16); - } else - val = simple_strtoul(p, &p, 10); - if (p == buf) - printk(KERN_INFO DRV_NAME - ": %s is not in hex or decimal form.\n", buf); - else - ipw_debug_level = val; - - return strnlen(buf, count); -} - -static DRIVER_ATTR(debug_level, S_IWUSR | S_IRUGO, - show_debug_level, store_debug_level); - -static inline u32 ipw_get_event_log_len(struct ipw_priv *priv) -{ - /* length = 1st dword in log */ - return ipw_read_reg32(priv, ipw_read32(priv, IPW_EVENT_LOG)); -} - -static void ipw_capture_event_log(struct ipw_priv *priv, - u32 log_len, struct ipw_event *log) -{ - u32 base; - - if (log_len) { - base = ipw_read32(priv, IPW_EVENT_LOG); - ipw_read_indirect(priv, base + sizeof(base) + sizeof(u32), - (u8 *) log, sizeof(*log) * log_len); - } -} - -static struct ipw_fw_error *ipw_alloc_error_log(struct ipw_priv *priv) -{ - struct ipw_fw_error *error; - u32 log_len = ipw_get_event_log_len(priv); - u32 base = ipw_read32(priv, IPW_ERROR_LOG); - u32 elem_len = ipw_read_reg32(priv, base); - - error = kmalloc(sizeof(*error) + - sizeof(*error->elem) * elem_len + - sizeof(*error->log) * log_len, GFP_ATOMIC); - if (!error) { - IPW_ERROR("Memory allocation for firmware error log " - "failed.\n"); - return NULL; - } - error->jiffies = jiffies; - error->status = priv->status; - error->config = priv->config; - error->elem_len = elem_len; - error->log_len = log_len; - error->elem = (struct ipw_error_elem *)error->payload; - error->log = (struct ipw_event *)(error->elem + elem_len); - - ipw_capture_event_log(priv, log_len, error->log); - - if (elem_len) - ipw_read_indirect(priv, base + sizeof(base), (u8 *) error->elem, - sizeof(*error->elem) * elem_len); - - return error; -} - -static ssize_t show_event_log(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - u32 log_len = ipw_get_event_log_len(priv); - u32 log_size; - struct ipw_event *log; - u32 len = 0, i; - - /* not using min() because of its strict type checking */ - log_size = PAGE_SIZE / sizeof(*log) > log_len ? - sizeof(*log) * log_len : PAGE_SIZE; - log = kzalloc(log_size, GFP_KERNEL); - if (!log) { - IPW_ERROR("Unable to allocate memory for log\n"); - return 0; - } - log_len = log_size / sizeof(*log); - ipw_capture_event_log(priv, log_len, log); - - len += snprintf(buf + len, PAGE_SIZE - len, "%08X", log_len); - for (i = 0; i < log_len; i++) - len += snprintf(buf + len, PAGE_SIZE - len, - "\n%08X%08X%08X", - log[i].time, log[i].event, log[i].data); - len += snprintf(buf + len, PAGE_SIZE - len, "\n"); - kfree(log); - return len; -} - -static DEVICE_ATTR(event_log, S_IRUGO, show_event_log, NULL); - -static ssize_t show_error(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - u32 len = 0, i; - if (!priv->error) - return 0; - len += snprintf(buf + len, PAGE_SIZE - len, - "%08lX%08X%08X%08X", - priv->error->jiffies, - priv->error->status, - priv->error->config, priv->error->elem_len); - for (i = 0; i < priv->error->elem_len; i++) - len += snprintf(buf + len, PAGE_SIZE - len, - "\n%08X%08X%08X%08X%08X%08X%08X", - priv->error->elem[i].time, - priv->error->elem[i].desc, - priv->error->elem[i].blink1, - priv->error->elem[i].blink2, - priv->error->elem[i].link1, - priv->error->elem[i].link2, - priv->error->elem[i].data); - - len += snprintf(buf + len, PAGE_SIZE - len, - "\n%08X", priv->error->log_len); - for (i = 0; i < priv->error->log_len; i++) - len += snprintf(buf + len, PAGE_SIZE - len, - "\n%08X%08X%08X", - priv->error->log[i].time, - priv->error->log[i].event, - priv->error->log[i].data); - len += snprintf(buf + len, PAGE_SIZE - len, "\n"); - return len; -} - -static ssize_t clear_error(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - kfree(priv->error); - priv->error = NULL; - return count; -} - -static DEVICE_ATTR(error, S_IRUGO | S_IWUSR, show_error, clear_error); - -static ssize_t show_cmd_log(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - u32 len = 0, i; - if (!priv->cmdlog) - return 0; - for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len; - (i != priv->cmdlog_pos) && (PAGE_SIZE - len); - i = (i + 1) % priv->cmdlog_len) { - len += - snprintf(buf + len, PAGE_SIZE - len, - "\n%08lX%08X%08X%08X\n", priv->cmdlog[i].jiffies, - priv->cmdlog[i].retcode, priv->cmdlog[i].cmd.cmd, - priv->cmdlog[i].cmd.len); - len += - snprintk_buf(buf + len, PAGE_SIZE - len, - (u8 *) priv->cmdlog[i].cmd.param, - priv->cmdlog[i].cmd.len); - len += snprintf(buf + len, PAGE_SIZE - len, "\n"); - } - len += snprintf(buf + len, PAGE_SIZE - len, "\n"); - return len; -} - -static DEVICE_ATTR(cmd_log, S_IRUGO, show_cmd_log, NULL); - -#ifdef CONFIG_IPW2200_PROMISCUOUS -static void ipw_prom_free(struct ipw_priv *priv); -static int ipw_prom_alloc(struct ipw_priv *priv); -static ssize_t store_rtap_iface(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - int rc = 0; - - if (count < 1) - return -EINVAL; - - switch (buf[0]) { - case '0': - if (!rtap_iface) - return count; - - if (netif_running(priv->prom_net_dev)) { - IPW_WARNING("Interface is up. Cannot unregister.\n"); - return count; - } - - ipw_prom_free(priv); - rtap_iface = 0; - break; - - case '1': - if (rtap_iface) - return count; - - rc = ipw_prom_alloc(priv); - if (!rc) - rtap_iface = 1; - break; - - default: - return -EINVAL; - } - - if (rc) { - IPW_ERROR("Failed to register promiscuous network " - "device (error %d).\n", rc); - } - - return count; -} - -static ssize_t show_rtap_iface(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - if (rtap_iface) - return sprintf(buf, "%s", priv->prom_net_dev->name); - else { - buf[0] = '-'; - buf[1] = '1'; - buf[2] = '\0'; - return 3; - } -} - -static DEVICE_ATTR(rtap_iface, S_IWUSR | S_IRUSR, show_rtap_iface, - store_rtap_iface); - -static ssize_t store_rtap_filter(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - if (!priv->prom_priv) { - IPW_ERROR("Attempting to set filter without " - "rtap_iface enabled.\n"); - return -EPERM; - } - - priv->prom_priv->filter = simple_strtol(buf, NULL, 0); - - IPW_DEBUG_INFO("Setting rtap filter to " BIT_FMT16 "\n", - BIT_ARG16(priv->prom_priv->filter)); - - return count; -} - -static ssize_t show_rtap_filter(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "0x%04X", - priv->prom_priv ? priv->prom_priv->filter : 0); -} - -static DEVICE_ATTR(rtap_filter, S_IWUSR | S_IRUSR, show_rtap_filter, - store_rtap_filter); -#endif - -static ssize_t show_scan_age(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%d\n", priv->ieee->scan_age); -} - -static ssize_t store_scan_age(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - struct net_device *dev = priv->net_dev; - char buffer[] = "00000000"; - unsigned long len = - (sizeof(buffer) - 1) > count ? count : sizeof(buffer) - 1; - unsigned long val; - char *p = buffer; - - IPW_DEBUG_INFO("enter\n"); - - strncpy(buffer, buf, len); - buffer[len] = 0; - - if (p[1] == 'x' || p[1] == 'X' || p[0] == 'x' || p[0] == 'X') { - p++; - if (p[0] == 'x' || p[0] == 'X') - p++; - val = simple_strtoul(p, &p, 16); - } else - val = simple_strtoul(p, &p, 10); - if (p == buffer) { - IPW_DEBUG_INFO("%s: user supplied invalid value.\n", dev->name); - } else { - priv->ieee->scan_age = val; - IPW_DEBUG_INFO("set scan_age = %u\n", priv->ieee->scan_age); - } - - IPW_DEBUG_INFO("exit\n"); - return len; -} - -static DEVICE_ATTR(scan_age, S_IWUSR | S_IRUGO, show_scan_age, store_scan_age); - -static ssize_t show_led(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%d\n", (priv->config & CFG_NO_LED) ? 0 : 1); -} - -static ssize_t store_led(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - IPW_DEBUG_INFO("enter\n"); - - if (count == 0) - return 0; - - if (*buf == 0) { - IPW_DEBUG_LED("Disabling LED control.\n"); - priv->config |= CFG_NO_LED; - ipw_led_shutdown(priv); - } else { - IPW_DEBUG_LED("Enabling LED control.\n"); - priv->config &= ~CFG_NO_LED; - ipw_led_init(priv); - } - - IPW_DEBUG_INFO("exit\n"); - return count; -} - -static DEVICE_ATTR(led, S_IWUSR | S_IRUGO, show_led, store_led); - -static ssize_t show_status(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw_priv *p = dev_get_drvdata(d); - return sprintf(buf, "0x%08x\n", (int)p->status); -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - -static ssize_t show_cfg(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *p = dev_get_drvdata(d); - return sprintf(buf, "0x%08x\n", (int)p->config); -} - -static DEVICE_ATTR(cfg, S_IRUGO, show_cfg, NULL); - -static ssize_t show_nic_type(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "TYPE: %d\n", priv->nic_type); -} - -static DEVICE_ATTR(nic_type, S_IRUGO, show_nic_type, NULL); - -static ssize_t show_ucode_version(struct device *d, - struct device_attribute *attr, char *buf) -{ - u32 len = sizeof(u32), tmp = 0; - struct ipw_priv *p = dev_get_drvdata(d); - - if (ipw_get_ordinal(p, IPW_ORD_STAT_UCODE_VERSION, &tmp, &len)) - return 0; - - return sprintf(buf, "0x%08x\n", tmp); -} - -static DEVICE_ATTR(ucode_version, S_IWUSR | S_IRUGO, show_ucode_version, NULL); - -static ssize_t show_rtc(struct device *d, struct device_attribute *attr, - char *buf) -{ - u32 len = sizeof(u32), tmp = 0; - struct ipw_priv *p = dev_get_drvdata(d); - - if (ipw_get_ordinal(p, IPW_ORD_STAT_RTC, &tmp, &len)) - return 0; - - return sprintf(buf, "0x%08x\n", tmp); -} - -static DEVICE_ATTR(rtc, S_IWUSR | S_IRUGO, show_rtc, NULL); - -/* - * Add a device attribute to view/control the delay between eeprom - * operations. - */ -static ssize_t show_eeprom_delay(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct ipw_priv *p = dev_get_drvdata(d); - int n = p->eeprom_delay; - return sprintf(buf, "%i\n", n); -} -static ssize_t store_eeprom_delay(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *p = dev_get_drvdata(d); - sscanf(buf, "%i", &p->eeprom_delay); - return strnlen(buf, count); -} - -static DEVICE_ATTR(eeprom_delay, S_IWUSR | S_IRUGO, - show_eeprom_delay, store_eeprom_delay); - -static ssize_t show_command_event_reg(struct device *d, - struct device_attribute *attr, char *buf) -{ - u32 reg = 0; - struct ipw_priv *p = dev_get_drvdata(d); - - reg = ipw_read_reg32(p, IPW_INTERNAL_CMD_EVENT); - return sprintf(buf, "0x%08x\n", reg); -} -static ssize_t store_command_event_reg(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 reg; - struct ipw_priv *p = dev_get_drvdata(d); - - sscanf(buf, "%x", ®); - ipw_write_reg32(p, IPW_INTERNAL_CMD_EVENT, reg); - return strnlen(buf, count); -} - -static DEVICE_ATTR(command_event_reg, S_IWUSR | S_IRUGO, - show_command_event_reg, store_command_event_reg); - -static ssize_t show_mem_gpio_reg(struct device *d, - struct device_attribute *attr, char *buf) -{ - u32 reg = 0; - struct ipw_priv *p = dev_get_drvdata(d); - - reg = ipw_read_reg32(p, 0x301100); - return sprintf(buf, "0x%08x\n", reg); -} -static ssize_t store_mem_gpio_reg(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - u32 reg; - struct ipw_priv *p = dev_get_drvdata(d); - - sscanf(buf, "%x", ®); - ipw_write_reg32(p, 0x301100, reg); - return strnlen(buf, count); -} - -static DEVICE_ATTR(mem_gpio_reg, S_IWUSR | S_IRUGO, - show_mem_gpio_reg, store_mem_gpio_reg); - -static ssize_t show_indirect_dword(struct device *d, - struct device_attribute *attr, char *buf) -{ - u32 reg = 0; - struct ipw_priv *priv = dev_get_drvdata(d); - - if (priv->status & STATUS_INDIRECT_DWORD) - reg = ipw_read_reg32(priv, priv->indirect_dword); - else - reg = 0; - - return sprintf(buf, "0x%08x\n", reg); -} -static ssize_t store_indirect_dword(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - sscanf(buf, "%x", &priv->indirect_dword); - priv->status |= STATUS_INDIRECT_DWORD; - return strnlen(buf, count); -} - -static DEVICE_ATTR(indirect_dword, S_IWUSR | S_IRUGO, - show_indirect_dword, store_indirect_dword); - -static ssize_t show_indirect_byte(struct device *d, - struct device_attribute *attr, char *buf) -{ - u8 reg = 0; - struct ipw_priv *priv = dev_get_drvdata(d); - - if (priv->status & STATUS_INDIRECT_BYTE) - reg = ipw_read_reg8(priv, priv->indirect_byte); - else - reg = 0; - - return sprintf(buf, "0x%02x\n", reg); -} -static ssize_t store_indirect_byte(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - sscanf(buf, "%x", &priv->indirect_byte); - priv->status |= STATUS_INDIRECT_BYTE; - return strnlen(buf, count); -} - -static DEVICE_ATTR(indirect_byte, S_IWUSR | S_IRUGO, - show_indirect_byte, store_indirect_byte); - -static ssize_t show_direct_dword(struct device *d, - struct device_attribute *attr, char *buf) -{ - u32 reg = 0; - struct ipw_priv *priv = dev_get_drvdata(d); - - if (priv->status & STATUS_DIRECT_DWORD) - reg = ipw_read32(priv, priv->direct_dword); - else - reg = 0; - - return sprintf(buf, "0x%08x\n", reg); -} -static ssize_t store_direct_dword(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - sscanf(buf, "%x", &priv->direct_dword); - priv->status |= STATUS_DIRECT_DWORD; - return strnlen(buf, count); -} - -static DEVICE_ATTR(direct_dword, S_IWUSR | S_IRUGO, - show_direct_dword, store_direct_dword); - -static int rf_kill_active(struct ipw_priv *priv) -{ - if (0 == (ipw_read32(priv, 0x30) & 0x10000)) - priv->status |= STATUS_RF_KILL_HW; - else - priv->status &= ~STATUS_RF_KILL_HW; - - return (priv->status & STATUS_RF_KILL_HW) ? 1 : 0; -} - -static ssize_t show_rf_kill(struct device *d, struct device_attribute *attr, - char *buf) -{ - /* 0 - RF kill not enabled - 1 - SW based RF kill active (sysfs) - 2 - HW based RF kill active - 3 - Both HW and SW baed RF kill active */ - struct ipw_priv *priv = dev_get_drvdata(d); - int val = ((priv->status & STATUS_RF_KILL_SW) ? 0x1 : 0x0) | - (rf_kill_active(priv) ? 0x2 : 0x0); - return sprintf(buf, "%i\n", val); -} - -static int ipw_radio_kill_sw(struct ipw_priv *priv, int disable_radio) -{ - if ((disable_radio ? 1 : 0) == - ((priv->status & STATUS_RF_KILL_SW) ? 1 : 0)) - return 0; - - IPW_DEBUG_RF_KILL("Manual SW RF Kill set to: RADIO %s\n", - disable_radio ? "OFF" : "ON"); - - if (disable_radio) { - priv->status |= STATUS_RF_KILL_SW; - - if (priv->workqueue) { - cancel_delayed_work(&priv->request_scan); - cancel_delayed_work(&priv->request_direct_scan); - cancel_delayed_work(&priv->request_passive_scan); - cancel_delayed_work(&priv->scan_event); - } - queue_work(priv->workqueue, &priv->down); - } else { - priv->status &= ~STATUS_RF_KILL_SW; - if (rf_kill_active(priv)) { - IPW_DEBUG_RF_KILL("Can not turn radio back on - " - "disabled by HW switch\n"); - /* Make sure the RF_KILL check timer is running */ - cancel_delayed_work(&priv->rf_kill); - queue_delayed_work(priv->workqueue, &priv->rf_kill, - round_jiffies_relative(2 * HZ)); - } else - queue_work(priv->workqueue, &priv->up); - } - - return 1; -} - -static ssize_t store_rf_kill(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - - ipw_radio_kill_sw(priv, buf[0] == '1'); - - return count; -} - -static DEVICE_ATTR(rf_kill, S_IWUSR | S_IRUGO, show_rf_kill, store_rf_kill); - -static ssize_t show_speed_scan(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - int pos = 0, len = 0; - if (priv->config & CFG_SPEED_SCAN) { - while (priv->speed_scan[pos] != 0) - len += sprintf(&buf[len], "%d ", - priv->speed_scan[pos++]); - return len + sprintf(&buf[len], "\n"); - } - - return sprintf(buf, "0\n"); -} - -static ssize_t store_speed_scan(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - int channel, pos = 0; - const char *p = buf; - - /* list of space separated channels to scan, optionally ending with 0 */ - while ((channel = simple_strtol(p, NULL, 0))) { - if (pos == MAX_SPEED_SCAN - 1) { - priv->speed_scan[pos] = 0; - break; - } - - if (libipw_is_valid_channel(priv->ieee, channel)) - priv->speed_scan[pos++] = channel; - else - IPW_WARNING("Skipping invalid channel request: %d\n", - channel); - p = strchr(p, ' '); - if (!p) - break; - while (*p == ' ' || *p == '\t') - p++; - } - - if (pos == 0) - priv->config &= ~CFG_SPEED_SCAN; - else { - priv->speed_scan_pos = 0; - priv->config |= CFG_SPEED_SCAN; - } - - return count; -} - -static DEVICE_ATTR(speed_scan, S_IWUSR | S_IRUGO, show_speed_scan, - store_speed_scan); - -static ssize_t show_net_stats(struct device *d, struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%c\n", (priv->config & CFG_NET_STATS) ? '1' : '0'); -} - -static ssize_t store_net_stats(struct device *d, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - if (buf[0] == '1') - priv->config |= CFG_NET_STATS; - else - priv->config &= ~CFG_NET_STATS; - - return count; -} - -static DEVICE_ATTR(net_stats, S_IWUSR | S_IRUGO, - show_net_stats, store_net_stats); - -static ssize_t show_channels(struct device *d, - struct device_attribute *attr, - char *buf) -{ - struct ipw_priv *priv = dev_get_drvdata(d); - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - int len = 0, i; - - len = sprintf(&buf[len], - "Displaying %d channels in 2.4Ghz band " - "(802.11bg):\n", geo->bg_channels); - - for (i = 0; i < geo->bg_channels; i++) { - len += sprintf(&buf[len], "%d: BSS%s%s, %s, Band %s.\n", - geo->bg[i].channel, - geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT ? - " (radar spectrum)" : "", - ((geo->bg[i].flags & LIBIPW_CH_NO_IBSS) || - (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)) - ? "" : ", IBSS", - geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY ? - "passive only" : "active/passive", - geo->bg[i].flags & LIBIPW_CH_B_ONLY ? - "B" : "B/G"); - } - - len += sprintf(&buf[len], - "Displaying %d channels in 5.2Ghz band " - "(802.11a):\n", geo->a_channels); - for (i = 0; i < geo->a_channels; i++) { - len += sprintf(&buf[len], "%d: BSS%s%s, %s.\n", - geo->a[i].channel, - geo->a[i].flags & LIBIPW_CH_RADAR_DETECT ? - " (radar spectrum)" : "", - ((geo->a[i].flags & LIBIPW_CH_NO_IBSS) || - (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)) - ? "" : ", IBSS", - geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY ? - "passive only" : "active/passive"); - } - - return len; -} - -static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); - -static void notify_wx_assoc_event(struct ipw_priv *priv) -{ - union iwreq_data wrqu; - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - if (priv->status & STATUS_ASSOCIATED) - memcpy(wrqu.ap_addr.sa_data, priv->bssid, ETH_ALEN); - else - memset(wrqu.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(priv->net_dev, SIOCGIWAP, &wrqu, NULL); -} - -static void ipw_irq_tasklet(struct ipw_priv *priv) -{ - u32 inta, inta_mask, handled = 0; - unsigned long flags; - int rc = 0; - - spin_lock_irqsave(&priv->irq_lock, flags); - - inta = ipw_read32(priv, IPW_INTA_RW); - inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); - inta &= (IPW_INTA_MASK_ALL & inta_mask); - - /* Add any cached INTA values that need to be handled */ - inta |= priv->isr_inta; - - spin_unlock_irqrestore(&priv->irq_lock, flags); - - spin_lock_irqsave(&priv->lock, flags); - - /* handle all the justifications for the interrupt */ - if (inta & IPW_INTA_BIT_RX_TRANSFER) { - ipw_rx(priv); - handled |= IPW_INTA_BIT_RX_TRANSFER; - } - - if (inta & IPW_INTA_BIT_TX_CMD_QUEUE) { - IPW_DEBUG_HC("Command completed.\n"); - rc = ipw_queue_tx_reclaim(priv, &priv->txq_cmd, -1); - priv->status &= ~STATUS_HCMD_ACTIVE; - wake_up_interruptible(&priv->wait_command_queue); - handled |= IPW_INTA_BIT_TX_CMD_QUEUE; - } - - if (inta & IPW_INTA_BIT_TX_QUEUE_1) { - IPW_DEBUG_TX("TX_QUEUE_1\n"); - rc = ipw_queue_tx_reclaim(priv, &priv->txq[0], 0); - handled |= IPW_INTA_BIT_TX_QUEUE_1; - } - - if (inta & IPW_INTA_BIT_TX_QUEUE_2) { - IPW_DEBUG_TX("TX_QUEUE_2\n"); - rc = ipw_queue_tx_reclaim(priv, &priv->txq[1], 1); - handled |= IPW_INTA_BIT_TX_QUEUE_2; - } - - if (inta & IPW_INTA_BIT_TX_QUEUE_3) { - IPW_DEBUG_TX("TX_QUEUE_3\n"); - rc = ipw_queue_tx_reclaim(priv, &priv->txq[2], 2); - handled |= IPW_INTA_BIT_TX_QUEUE_3; - } - - if (inta & IPW_INTA_BIT_TX_QUEUE_4) { - IPW_DEBUG_TX("TX_QUEUE_4\n"); - rc = ipw_queue_tx_reclaim(priv, &priv->txq[3], 3); - handled |= IPW_INTA_BIT_TX_QUEUE_4; - } - - if (inta & IPW_INTA_BIT_STATUS_CHANGE) { - IPW_WARNING("STATUS_CHANGE\n"); - handled |= IPW_INTA_BIT_STATUS_CHANGE; - } - - if (inta & IPW_INTA_BIT_BEACON_PERIOD_EXPIRED) { - IPW_WARNING("TX_PERIOD_EXPIRED\n"); - handled |= IPW_INTA_BIT_BEACON_PERIOD_EXPIRED; - } - - if (inta & IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE) { - IPW_WARNING("HOST_CMD_DONE\n"); - handled |= IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE; - } - - if (inta & IPW_INTA_BIT_FW_INITIALIZATION_DONE) { - IPW_WARNING("FW_INITIALIZATION_DONE\n"); - handled |= IPW_INTA_BIT_FW_INITIALIZATION_DONE; - } - - if (inta & IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE) { - IPW_WARNING("PHY_OFF_DONE\n"); - handled |= IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE; - } - - if (inta & IPW_INTA_BIT_RF_KILL_DONE) { - IPW_DEBUG_RF_KILL("RF_KILL_DONE\n"); - priv->status |= STATUS_RF_KILL_HW; - wake_up_interruptible(&priv->wait_command_queue); - priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); - cancel_delayed_work(&priv->request_scan); - cancel_delayed_work(&priv->request_direct_scan); - cancel_delayed_work(&priv->request_passive_scan); - cancel_delayed_work(&priv->scan_event); - schedule_work(&priv->link_down); - queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ); - handled |= IPW_INTA_BIT_RF_KILL_DONE; - } - - if (inta & IPW_INTA_BIT_FATAL_ERROR) { - IPW_WARNING("Firmware error detected. Restarting.\n"); - if (priv->error) { - IPW_DEBUG_FW("Sysfs 'error' log already exists.\n"); - if (ipw_debug_level & IPW_DL_FW_ERRORS) { - struct ipw_fw_error *error = - ipw_alloc_error_log(priv); - ipw_dump_error_log(priv, error); - kfree(error); - } - } else { - priv->error = ipw_alloc_error_log(priv); - if (priv->error) - IPW_DEBUG_FW("Sysfs 'error' log captured.\n"); - else - IPW_DEBUG_FW("Error allocating sysfs 'error' " - "log.\n"); - if (ipw_debug_level & IPW_DL_FW_ERRORS) - ipw_dump_error_log(priv, priv->error); - } - - /* XXX: If hardware encryption is for WPA/WPA2, - * we have to notify the supplicant. */ - if (priv->ieee->sec.encrypt) { - priv->status &= ~STATUS_ASSOCIATED; - notify_wx_assoc_event(priv); - } - - /* Keep the restart process from trying to send host - * commands by clearing the INIT status bit */ - priv->status &= ~STATUS_INIT; - - /* Cancel currently queued command. */ - priv->status &= ~STATUS_HCMD_ACTIVE; - wake_up_interruptible(&priv->wait_command_queue); - - queue_work(priv->workqueue, &priv->adapter_restart); - handled |= IPW_INTA_BIT_FATAL_ERROR; - } - - if (inta & IPW_INTA_BIT_PARITY_ERROR) { - IPW_ERROR("Parity error\n"); - handled |= IPW_INTA_BIT_PARITY_ERROR; - } - - if (handled != inta) { - IPW_ERROR("Unhandled INTA bits 0x%08x\n", inta & ~handled); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - /* enable all interrupts */ - ipw_enable_interrupts(priv); -} - -#define IPW_CMD(x) case IPW_CMD_ ## x : return #x -static char *get_cmd_string(u8 cmd) -{ - switch (cmd) { - IPW_CMD(HOST_COMPLETE); - IPW_CMD(POWER_DOWN); - IPW_CMD(SYSTEM_CONFIG); - IPW_CMD(MULTICAST_ADDRESS); - IPW_CMD(SSID); - IPW_CMD(ADAPTER_ADDRESS); - IPW_CMD(PORT_TYPE); - IPW_CMD(RTS_THRESHOLD); - IPW_CMD(FRAG_THRESHOLD); - IPW_CMD(POWER_MODE); - IPW_CMD(WEP_KEY); - IPW_CMD(TGI_TX_KEY); - IPW_CMD(SCAN_REQUEST); - IPW_CMD(SCAN_REQUEST_EXT); - IPW_CMD(ASSOCIATE); - IPW_CMD(SUPPORTED_RATES); - IPW_CMD(SCAN_ABORT); - IPW_CMD(TX_FLUSH); - IPW_CMD(QOS_PARAMETERS); - IPW_CMD(DINO_CONFIG); - IPW_CMD(RSN_CAPABILITIES); - IPW_CMD(RX_KEY); - IPW_CMD(CARD_DISABLE); - IPW_CMD(SEED_NUMBER); - IPW_CMD(TX_POWER); - IPW_CMD(COUNTRY_INFO); - IPW_CMD(AIRONET_INFO); - IPW_CMD(AP_TX_POWER); - IPW_CMD(CCKM_INFO); - IPW_CMD(CCX_VER_INFO); - IPW_CMD(SET_CALIBRATION); - IPW_CMD(SENSITIVITY_CALIB); - IPW_CMD(RETRY_LIMIT); - IPW_CMD(IPW_PRE_POWER_DOWN); - IPW_CMD(VAP_BEACON_TEMPLATE); - IPW_CMD(VAP_DTIM_PERIOD); - IPW_CMD(EXT_SUPPORTED_RATES); - IPW_CMD(VAP_LOCAL_TX_PWR_CONSTRAINT); - IPW_CMD(VAP_QUIET_INTERVALS); - IPW_CMD(VAP_CHANNEL_SWITCH); - IPW_CMD(VAP_MANDATORY_CHANNELS); - IPW_CMD(VAP_CELL_PWR_LIMIT); - IPW_CMD(VAP_CF_PARAM_SET); - IPW_CMD(VAP_SET_BEACONING_STATE); - IPW_CMD(MEASUREMENT); - IPW_CMD(POWER_CAPABILITY); - IPW_CMD(SUPPORTED_CHANNELS); - IPW_CMD(TPC_REPORT); - IPW_CMD(WME_INFO); - IPW_CMD(PRODUCTION_COMMAND); - default: - return "UNKNOWN"; - } -} - -#define HOST_COMPLETE_TIMEOUT HZ - -static int __ipw_send_cmd(struct ipw_priv *priv, struct host_cmd *cmd) -{ - int rc = 0; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - if (priv->status & STATUS_HCMD_ACTIVE) { - IPW_ERROR("Failed to send %s: Already sending a command.\n", - get_cmd_string(cmd->cmd)); - spin_unlock_irqrestore(&priv->lock, flags); - return -EAGAIN; - } - - priv->status |= STATUS_HCMD_ACTIVE; - - if (priv->cmdlog) { - priv->cmdlog[priv->cmdlog_pos].jiffies = jiffies; - priv->cmdlog[priv->cmdlog_pos].cmd.cmd = cmd->cmd; - priv->cmdlog[priv->cmdlog_pos].cmd.len = cmd->len; - memcpy(priv->cmdlog[priv->cmdlog_pos].cmd.param, cmd->param, - cmd->len); - priv->cmdlog[priv->cmdlog_pos].retcode = -1; - } - - IPW_DEBUG_HC("%s command (#%d) %d bytes: 0x%08X\n", - get_cmd_string(cmd->cmd), cmd->cmd, cmd->len, - priv->status); - -#ifndef DEBUG_CMD_WEP_KEY - if (cmd->cmd == IPW_CMD_WEP_KEY) - IPW_DEBUG_HC("WEP_KEY command masked out for secure.\n"); - else -#endif - printk_buf(IPW_DL_HOST_COMMAND, (u8 *) cmd->param, cmd->len); - - rc = ipw_queue_tx_hcmd(priv, cmd->cmd, cmd->param, cmd->len, 0); - if (rc) { - priv->status &= ~STATUS_HCMD_ACTIVE; - IPW_ERROR("Failed to send %s: Reason %d\n", - get_cmd_string(cmd->cmd), rc); - spin_unlock_irqrestore(&priv->lock, flags); - goto exit; - } - spin_unlock_irqrestore(&priv->lock, flags); - - rc = wait_event_interruptible_timeout(priv->wait_command_queue, - !(priv-> - status & STATUS_HCMD_ACTIVE), - HOST_COMPLETE_TIMEOUT); - if (rc == 0) { - spin_lock_irqsave(&priv->lock, flags); - if (priv->status & STATUS_HCMD_ACTIVE) { - IPW_ERROR("Failed to send %s: Command timed out.\n", - get_cmd_string(cmd->cmd)); - priv->status &= ~STATUS_HCMD_ACTIVE; - spin_unlock_irqrestore(&priv->lock, flags); - rc = -EIO; - goto exit; - } - spin_unlock_irqrestore(&priv->lock, flags); - } else - rc = 0; - - if (priv->status & STATUS_RF_KILL_HW) { - IPW_ERROR("Failed to send %s: Aborted due to RF kill switch.\n", - get_cmd_string(cmd->cmd)); - rc = -EIO; - goto exit; - } - - exit: - if (priv->cmdlog) { - priv->cmdlog[priv->cmdlog_pos++].retcode = rc; - priv->cmdlog_pos %= priv->cmdlog_len; - } - return rc; -} - -static int ipw_send_cmd_simple(struct ipw_priv *priv, u8 command) -{ - struct host_cmd cmd = { - .cmd = command, - }; - - return __ipw_send_cmd(priv, &cmd); -} - -static int ipw_send_cmd_pdu(struct ipw_priv *priv, u8 command, u8 len, - void *data) -{ - struct host_cmd cmd = { - .cmd = command, - .len = len, - .param = data, - }; - - return __ipw_send_cmd(priv, &cmd); -} - -static int ipw_send_host_complete(struct ipw_priv *priv) -{ - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_simple(priv, IPW_CMD_HOST_COMPLETE); -} - -static int ipw_send_system_config(struct ipw_priv *priv) -{ - return ipw_send_cmd_pdu(priv, IPW_CMD_SYSTEM_CONFIG, - sizeof(priv->sys_config), - &priv->sys_config); -} - -static int ipw_send_ssid(struct ipw_priv *priv, u8 * ssid, int len) -{ - if (!priv || !ssid) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_SSID, min(len, IW_ESSID_MAX_SIZE), - ssid); -} - -static int ipw_send_adapter_address(struct ipw_priv *priv, u8 * mac) -{ - if (!priv || !mac) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - IPW_DEBUG_INFO("%s: Setting MAC to %pM\n", - priv->net_dev->name, mac); - - return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac); -} - -/* - * NOTE: This must be executed from our workqueue as it results in udelay - * being called which may corrupt the keyboard if executed on default - * workqueue - */ -static void ipw_adapter_restart(void *adapter) -{ - struct ipw_priv *priv = adapter; - - if (priv->status & STATUS_RF_KILL_MASK) - return; - - ipw_down(priv); - - if (priv->assoc_network && - (priv->assoc_network->capability & WLAN_CAPABILITY_IBSS)) - ipw_remove_current_network(priv); - - if (ipw_up(priv)) { - IPW_ERROR("Failed to up device\n"); - return; - } -} - -static void ipw_bg_adapter_restart(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, adapter_restart); - mutex_lock(&priv->mutex); - ipw_adapter_restart(priv); - mutex_unlock(&priv->mutex); -} - -#define IPW_SCAN_CHECK_WATCHDOG (5 * HZ) - -static void ipw_scan_check(void *data) -{ - struct ipw_priv *priv = data; - if (priv->status & (STATUS_SCANNING | STATUS_SCAN_ABORTING)) { - IPW_DEBUG_SCAN("Scan completion watchdog resetting " - "adapter after (%dms).\n", - jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG)); - queue_work(priv->workqueue, &priv->adapter_restart); - } -} - -static void ipw_bg_scan_check(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, scan_check.work); - mutex_lock(&priv->mutex); - ipw_scan_check(priv); - mutex_unlock(&priv->mutex); -} - -static int ipw_send_scan_request_ext(struct ipw_priv *priv, - struct ipw_scan_request_ext *request) -{ - return ipw_send_cmd_pdu(priv, IPW_CMD_SCAN_REQUEST_EXT, - sizeof(*request), request); -} - -static int ipw_send_scan_abort(struct ipw_priv *priv) -{ - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_simple(priv, IPW_CMD_SCAN_ABORT); -} - -static int ipw_set_sensitivity(struct ipw_priv *priv, u16 sens) -{ - struct ipw_sensitivity_calib calib = { - .beacon_rssi_raw = cpu_to_le16(sens), - }; - - return ipw_send_cmd_pdu(priv, IPW_CMD_SENSITIVITY_CALIB, sizeof(calib), - &calib); -} - -static int ipw_send_associate(struct ipw_priv *priv, - struct ipw_associate *associate) -{ - if (!priv || !associate) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_ASSOCIATE, sizeof(*associate), - associate); -} - -static int ipw_send_supported_rates(struct ipw_priv *priv, - struct ipw_supported_rates *rates) -{ - if (!priv || !rates) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_SUPPORTED_RATES, sizeof(*rates), - rates); -} - -static int ipw_set_random_seed(struct ipw_priv *priv) -{ - u32 val; - - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - get_random_bytes(&val, sizeof(val)); - - return ipw_send_cmd_pdu(priv, IPW_CMD_SEED_NUMBER, sizeof(val), &val); -} - -static int ipw_send_card_disable(struct ipw_priv *priv, u32 phy_off) -{ - __le32 v = cpu_to_le32(phy_off); - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_CARD_DISABLE, sizeof(v), &v); -} - -static int ipw_send_tx_power(struct ipw_priv *priv, struct ipw_tx_power *power) -{ - if (!priv || !power) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_TX_POWER, sizeof(*power), power); -} - -static int ipw_set_tx_power(struct ipw_priv *priv) -{ - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - struct ipw_tx_power tx_power; - s8 max_power; - int i; - - memset(&tx_power, 0, sizeof(tx_power)); - - /* configure device for 'G' band */ - tx_power.ieee_mode = IPW_G_MODE; - tx_power.num_channels = geo->bg_channels; - for (i = 0; i < geo->bg_channels; i++) { - max_power = geo->bg[i].max_power; - tx_power.channels_tx_power[i].channel_number = - geo->bg[i].channel; - tx_power.channels_tx_power[i].tx_power = max_power ? - min(max_power, priv->tx_power) : priv->tx_power; - } - if (ipw_send_tx_power(priv, &tx_power)) - return -EIO; - - /* configure device to also handle 'B' band */ - tx_power.ieee_mode = IPW_B_MODE; - if (ipw_send_tx_power(priv, &tx_power)) - return -EIO; - - /* configure device to also handle 'A' band */ - if (priv->ieee->abg_true) { - tx_power.ieee_mode = IPW_A_MODE; - tx_power.num_channels = geo->a_channels; - for (i = 0; i < tx_power.num_channels; i++) { - max_power = geo->a[i].max_power; - tx_power.channels_tx_power[i].channel_number = - geo->a[i].channel; - tx_power.channels_tx_power[i].tx_power = max_power ? - min(max_power, priv->tx_power) : priv->tx_power; - } - if (ipw_send_tx_power(priv, &tx_power)) - return -EIO; - } - return 0; -} - -static int ipw_send_rts_threshold(struct ipw_priv *priv, u16 rts) -{ - struct ipw_rts_threshold rts_threshold = { - .rts_threshold = cpu_to_le16(rts), - }; - - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_RTS_THRESHOLD, - sizeof(rts_threshold), &rts_threshold); -} - -static int ipw_send_frag_threshold(struct ipw_priv *priv, u16 frag) -{ - struct ipw_frag_threshold frag_threshold = { - .frag_threshold = cpu_to_le16(frag), - }; - - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_FRAG_THRESHOLD, - sizeof(frag_threshold), &frag_threshold); -} - -static int ipw_send_power_mode(struct ipw_priv *priv, u32 mode) -{ - __le32 param; - - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - /* If on battery, set to 3, if AC set to CAM, else user - * level */ - switch (mode) { - case IPW_POWER_BATTERY: - param = cpu_to_le32(IPW_POWER_INDEX_3); - break; - case IPW_POWER_AC: - param = cpu_to_le32(IPW_POWER_MODE_CAM); - break; - default: - param = cpu_to_le32(mode); - break; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_POWER_MODE, sizeof(param), - ¶m); -} - -static int ipw_send_retry_limit(struct ipw_priv *priv, u8 slimit, u8 llimit) -{ - struct ipw_retry_limit retry_limit = { - .short_retry_limit = slimit, - .long_retry_limit = llimit - }; - - if (!priv) { - IPW_ERROR("Invalid args\n"); - return -1; - } - - return ipw_send_cmd_pdu(priv, IPW_CMD_RETRY_LIMIT, sizeof(retry_limit), - &retry_limit); -} - -/* - * The IPW device contains a Microwire compatible EEPROM that stores - * various data like the MAC address. Usually the firmware has exclusive - * access to the eeprom, but during device initialization (before the - * device driver has sent the HostComplete command to the firmware) the - * device driver has read access to the EEPROM by way of indirect addressing - * through a couple of memory mapped registers. - * - * The following is a simplified implementation for pulling data out of the - * the eeprom, along with some helper functions to find information in - * the per device private data's copy of the eeprom. - * - * NOTE: To better understand how these functions work (i.e what is a chip - * select and why do have to keep driving the eeprom clock?), read - * just about any data sheet for a Microwire compatible EEPROM. - */ - -/* write a 32 bit value into the indirect accessor register */ -static inline void eeprom_write_reg(struct ipw_priv *p, u32 data) -{ - ipw_write_reg32(p, FW_MEM_REG_EEPROM_ACCESS, data); - - /* the eeprom requires some time to complete the operation */ - udelay(p->eeprom_delay); - - return; -} - -/* perform a chip select operation */ -static void eeprom_cs(struct ipw_priv *priv) -{ - eeprom_write_reg(priv, 0); - eeprom_write_reg(priv, EEPROM_BIT_CS); - eeprom_write_reg(priv, EEPROM_BIT_CS | EEPROM_BIT_SK); - eeprom_write_reg(priv, EEPROM_BIT_CS); -} - -/* perform a chip select operation */ -static void eeprom_disable_cs(struct ipw_priv *priv) -{ - eeprom_write_reg(priv, EEPROM_BIT_CS); - eeprom_write_reg(priv, 0); - eeprom_write_reg(priv, EEPROM_BIT_SK); -} - -/* push a single bit down to the eeprom */ -static inline void eeprom_write_bit(struct ipw_priv *p, u8 bit) -{ - int d = (bit ? EEPROM_BIT_DI : 0); - eeprom_write_reg(p, EEPROM_BIT_CS | d); - eeprom_write_reg(p, EEPROM_BIT_CS | d | EEPROM_BIT_SK); -} - -/* push an opcode followed by an address down to the eeprom */ -static void eeprom_op(struct ipw_priv *priv, u8 op, u8 addr) -{ - int i; - - eeprom_cs(priv); - eeprom_write_bit(priv, 1); - eeprom_write_bit(priv, op & 2); - eeprom_write_bit(priv, op & 1); - for (i = 7; i >= 0; i--) { - eeprom_write_bit(priv, addr & (1 << i)); - } -} - -/* pull 16 bits off the eeprom, one bit at a time */ -static u16 eeprom_read_u16(struct ipw_priv *priv, u8 addr) -{ - int i; - u16 r = 0; - - /* Send READ Opcode */ - eeprom_op(priv, EEPROM_CMD_READ, addr); - - /* Send dummy bit */ - eeprom_write_reg(priv, EEPROM_BIT_CS); - - /* Read the byte off the eeprom one bit at a time */ - for (i = 0; i < 16; i++) { - u32 data = 0; - eeprom_write_reg(priv, EEPROM_BIT_CS | EEPROM_BIT_SK); - eeprom_write_reg(priv, EEPROM_BIT_CS); - data = ipw_read_reg32(priv, FW_MEM_REG_EEPROM_ACCESS); - r = (r << 1) | ((data & EEPROM_BIT_DO) ? 1 : 0); - } - - /* Send another dummy bit */ - eeprom_write_reg(priv, 0); - eeprom_disable_cs(priv); - - return r; -} - -/* helper function for pulling the mac address out of the private */ -/* data's copy of the eeprom data */ -static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac) -{ - memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], 6); -} - -/* - * Either the device driver (i.e. the host) or the firmware can - * load eeprom data into the designated region in SRAM. If neither - * happens then the FW will shutdown with a fatal error. - * - * In order to signal the FW to load the EEPROM, the EEPROM_LOAD_DISABLE - * bit needs region of shared SRAM needs to be non-zero. - */ -static void ipw_eeprom_init_sram(struct ipw_priv *priv) -{ - int i; - __le16 *eeprom = (__le16 *) priv->eeprom; - - IPW_DEBUG_TRACE(">>\n"); - - /* read entire contents of eeprom into private buffer */ - for (i = 0; i < 128; i++) - eeprom[i] = cpu_to_le16(eeprom_read_u16(priv, (u8) i)); - - /* - If the data looks correct, then copy it to our private - copy. Otherwise let the firmware know to perform the operation - on its own. - */ - if (priv->eeprom[EEPROM_VERSION] != 0) { - IPW_DEBUG_INFO("Writing EEPROM data into SRAM\n"); - - /* write the eeprom data to sram */ - for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++) - ipw_write8(priv, IPW_EEPROM_DATA + i, priv->eeprom[i]); - - /* Do not load eeprom data on fatal error or suspend */ - ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); - } else { - IPW_DEBUG_INFO("Enabling FW initializationg of SRAM\n"); - - /* Load eeprom data on fatal error or suspend */ - ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 1); - } - - IPW_DEBUG_TRACE("<<\n"); -} - -static void ipw_zero_memory(struct ipw_priv *priv, u32 start, u32 count) -{ - count >>= 2; - if (!count) - return; - _ipw_write32(priv, IPW_AUTOINC_ADDR, start); - while (count--) - _ipw_write32(priv, IPW_AUTOINC_DATA, 0); -} - -static inline void ipw_fw_dma_reset_command_blocks(struct ipw_priv *priv) -{ - ipw_zero_memory(priv, IPW_SHARED_SRAM_DMA_CONTROL, - CB_NUMBER_OF_ELEMENTS_SMALL * - sizeof(struct command_block)); -} - -static int ipw_fw_dma_enable(struct ipw_priv *priv) -{ /* start dma engine but no transfers yet */ - - IPW_DEBUG_FW(">> : \n"); - - /* Start the dma */ - ipw_fw_dma_reset_command_blocks(priv); - - /* Write CB base address */ - ipw_write_reg32(priv, IPW_DMA_I_CB_BASE, IPW_SHARED_SRAM_DMA_CONTROL); - - IPW_DEBUG_FW("<< : \n"); - return 0; -} - -static void ipw_fw_dma_abort(struct ipw_priv *priv) -{ - u32 control = 0; - - IPW_DEBUG_FW(">> :\n"); - - /* set the Stop and Abort bit */ - control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_STOP_AND_ABORT; - ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); - priv->sram_desc.last_cb_index = 0; - - IPW_DEBUG_FW("<< \n"); -} - -static int ipw_fw_dma_write_command_block(struct ipw_priv *priv, int index, - struct command_block *cb) -{ - u32 address = - IPW_SHARED_SRAM_DMA_CONTROL + - (sizeof(struct command_block) * index); - IPW_DEBUG_FW(">> :\n"); - - ipw_write_indirect(priv, address, (u8 *) cb, - (int)sizeof(struct command_block)); - - IPW_DEBUG_FW("<< :\n"); - return 0; - -} - -static int ipw_fw_dma_kick(struct ipw_priv *priv) -{ - u32 control = 0; - u32 index = 0; - - IPW_DEBUG_FW(">> :\n"); - - for (index = 0; index < priv->sram_desc.last_cb_index; index++) - ipw_fw_dma_write_command_block(priv, index, - &priv->sram_desc.cb_list[index]); - - /* Enable the DMA in the CSR register */ - ipw_clear_bit(priv, IPW_RESET_REG, - IPW_RESET_REG_MASTER_DISABLED | - IPW_RESET_REG_STOP_MASTER); - - /* Set the Start bit. */ - control = DMA_CONTROL_SMALL_CB_CONST_VALUE | DMA_CB_START; - ipw_write_reg32(priv, IPW_DMA_I_DMA_CONTROL, control); - - IPW_DEBUG_FW("<< :\n"); - return 0; -} - -static void ipw_fw_dma_dump_command_block(struct ipw_priv *priv) -{ - u32 address; - u32 register_value = 0; - u32 cb_fields_address = 0; - - IPW_DEBUG_FW(">> :\n"); - address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); - IPW_DEBUG_FW_INFO("Current CB is 0x%x \n", address); - - /* Read the DMA Controlor register */ - register_value = ipw_read_reg32(priv, IPW_DMA_I_DMA_CONTROL); - IPW_DEBUG_FW_INFO("IPW_DMA_I_DMA_CONTROL is 0x%x \n", register_value); - - /* Print the CB values */ - cb_fields_address = address; - register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB ControlField is 0x%x \n", register_value); - - cb_fields_address += sizeof(u32); - register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB Source Field is 0x%x \n", register_value); - - cb_fields_address += sizeof(u32); - register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB Destination Field is 0x%x \n", - register_value); - - cb_fields_address += sizeof(u32); - register_value = ipw_read_reg32(priv, cb_fields_address); - IPW_DEBUG_FW_INFO("Current CB Status Field is 0x%x \n", register_value); - - IPW_DEBUG_FW(">> :\n"); -} - -static int ipw_fw_dma_command_block_index(struct ipw_priv *priv) -{ - u32 current_cb_address = 0; - u32 current_cb_index = 0; - - IPW_DEBUG_FW("<< :\n"); - current_cb_address = ipw_read_reg32(priv, IPW_DMA_I_CURRENT_CB); - - current_cb_index = (current_cb_address - IPW_SHARED_SRAM_DMA_CONTROL) / - sizeof(struct command_block); - - IPW_DEBUG_FW_INFO("Current CB index 0x%x address = 0x%X \n", - current_cb_index, current_cb_address); - - IPW_DEBUG_FW(">> :\n"); - return current_cb_index; - -} - -static int ipw_fw_dma_add_command_block(struct ipw_priv *priv, - u32 src_address, - u32 dest_address, - u32 length, - int interrupt_enabled, int is_last) -{ - - u32 control = CB_VALID | CB_SRC_LE | CB_DEST_LE | CB_SRC_AUTOINC | - CB_SRC_IO_GATED | CB_DEST_AUTOINC | CB_SRC_SIZE_LONG | - CB_DEST_SIZE_LONG; - struct command_block *cb; - u32 last_cb_element = 0; - - IPW_DEBUG_FW_INFO("src_address=0x%x dest_address=0x%x length=0x%x\n", - src_address, dest_address, length); - - if (priv->sram_desc.last_cb_index >= CB_NUMBER_OF_ELEMENTS_SMALL) - return -1; - - last_cb_element = priv->sram_desc.last_cb_index; - cb = &priv->sram_desc.cb_list[last_cb_element]; - priv->sram_desc.last_cb_index++; - - /* Calculate the new CB control word */ - if (interrupt_enabled) - control |= CB_INT_ENABLED; - - if (is_last) - control |= CB_LAST_VALID; - - control |= length; - - /* Calculate the CB Element's checksum value */ - cb->status = control ^ src_address ^ dest_address; - - /* Copy the Source and Destination addresses */ - cb->dest_addr = dest_address; - cb->source_addr = src_address; - - /* Copy the Control Word last */ - cb->control = control; - - return 0; -} - -static int ipw_fw_dma_add_buffer(struct ipw_priv *priv, dma_addr_t *src_address, - int nr, u32 dest_address, u32 len) -{ - int ret, i; - u32 size; - - IPW_DEBUG_FW(">> \n"); - IPW_DEBUG_FW_INFO("nr=%d dest_address=0x%x len=0x%x\n", - nr, dest_address, len); - - for (i = 0; i < nr; i++) { - size = min_t(u32, len - i * CB_MAX_LENGTH, CB_MAX_LENGTH); - ret = ipw_fw_dma_add_command_block(priv, src_address[i], - dest_address + - i * CB_MAX_LENGTH, size, - 0, 0); - if (ret) { - IPW_DEBUG_FW_INFO(": Failed\n"); - return -1; - } else - IPW_DEBUG_FW_INFO(": Added new cb\n"); - } - - IPW_DEBUG_FW("<< \n"); - return 0; -} - -static int ipw_fw_dma_wait(struct ipw_priv *priv) -{ - u32 current_index = 0, previous_index; - u32 watchdog = 0; - - IPW_DEBUG_FW(">> : \n"); - - current_index = ipw_fw_dma_command_block_index(priv); - IPW_DEBUG_FW_INFO("sram_desc.last_cb_index:0x%08X\n", - (int)priv->sram_desc.last_cb_index); - - while (current_index < priv->sram_desc.last_cb_index) { - udelay(50); - previous_index = current_index; - current_index = ipw_fw_dma_command_block_index(priv); - - if (previous_index < current_index) { - watchdog = 0; - continue; - } - if (++watchdog > 400) { - IPW_DEBUG_FW_INFO("Timeout\n"); - ipw_fw_dma_dump_command_block(priv); - ipw_fw_dma_abort(priv); - return -1; - } - } - - ipw_fw_dma_abort(priv); - - /*Disable the DMA in the CSR register */ - ipw_set_bit(priv, IPW_RESET_REG, - IPW_RESET_REG_MASTER_DISABLED | IPW_RESET_REG_STOP_MASTER); - - IPW_DEBUG_FW("<< dmaWaitSync \n"); - return 0; -} - -static void ipw_remove_current_network(struct ipw_priv *priv) -{ - struct list_head *element, *safe; - struct libipw_network *network = NULL; - unsigned long flags; - - spin_lock_irqsave(&priv->ieee->lock, flags); - list_for_each_safe(element, safe, &priv->ieee->network_list) { - network = list_entry(element, struct libipw_network, list); - if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) { - list_del(element); - list_add_tail(&network->list, - &priv->ieee->network_free_list); - } - } - spin_unlock_irqrestore(&priv->ieee->lock, flags); -} - -/** - * Check that card is still alive. - * Reads debug register from domain0. - * If card is present, pre-defined value should - * be found there. - * - * @param priv - * @return 1 if card is present, 0 otherwise - */ -static inline int ipw_alive(struct ipw_priv *priv) -{ - return ipw_read32(priv, 0x90) == 0xd55555d5; -} - -/* timeout in msec, attempted in 10-msec quanta */ -static int ipw_poll_bit(struct ipw_priv *priv, u32 addr, u32 mask, - int timeout) -{ - int i = 0; - - do { - if ((ipw_read32(priv, addr) & mask) == mask) - return i; - mdelay(10); - i += 10; - } while (i < timeout); - - return -ETIME; -} - -/* These functions load the firmware and micro code for the operation of - * the ipw hardware. It assumes the buffer has all the bits for the - * image and the caller is handling the memory allocation and clean up. - */ - -static int ipw_stop_master(struct ipw_priv *priv) -{ - int rc; - - IPW_DEBUG_TRACE(">> \n"); - /* stop master. typical delay - 0 */ - ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); - - /* timeout is in msec, polled in 10-msec quanta */ - rc = ipw_poll_bit(priv, IPW_RESET_REG, - IPW_RESET_REG_MASTER_DISABLED, 100); - if (rc < 0) { - IPW_ERROR("wait for stop master failed after 100ms\n"); - return -1; - } - - IPW_DEBUG_INFO("stop master %dms\n", rc); - - return rc; -} - -static void ipw_arc_release(struct ipw_priv *priv) -{ - IPW_DEBUG_TRACE(">> \n"); - mdelay(5); - - ipw_clear_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); - - /* no one knows timing, for safety add some delay */ - mdelay(5); -} - -struct fw_chunk { - __le32 address; - __le32 length; -}; - -static int ipw_load_ucode(struct ipw_priv *priv, u8 * data, size_t len) -{ - int rc = 0, i, addr; - u8 cr = 0; - __le16 *image; - - image = (__le16 *) data; - - IPW_DEBUG_TRACE(">> \n"); - - rc = ipw_stop_master(priv); - - if (rc < 0) - return rc; - - for (addr = IPW_SHARED_LOWER_BOUND; - addr < IPW_REGISTER_DOMAIN1_END; addr += 4) { - ipw_write32(priv, addr, 0); - } - - /* no ucode (yet) */ - memset(&priv->dino_alive, 0, sizeof(priv->dino_alive)); - /* destroy DMA queues */ - /* reset sequence */ - - ipw_write_reg32(priv, IPW_MEM_HALT_AND_RESET, IPW_BIT_HALT_RESET_ON); - ipw_arc_release(priv); - ipw_write_reg32(priv, IPW_MEM_HALT_AND_RESET, IPW_BIT_HALT_RESET_OFF); - mdelay(1); - - /* reset PHY */ - ipw_write_reg32(priv, IPW_INTERNAL_CMD_EVENT, IPW_BASEBAND_POWER_DOWN); - mdelay(1); - - ipw_write_reg32(priv, IPW_INTERNAL_CMD_EVENT, 0); - mdelay(1); - - /* enable ucode store */ - ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0x0); - ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_CS); - mdelay(1); - - /* write ucode */ - /** - * @bug - * Do NOT set indirect address register once and then - * store data to indirect data register in the loop. - * It seems very reasonable, but in this case DINO do not - * accept ucode. It is essential to set address each time. - */ - /* load new ipw uCode */ - for (i = 0; i < len / 2; i++) - ipw_write_reg16(priv, IPW_BASEBAND_CONTROL_STORE, - le16_to_cpu(image[i])); - - /* enable DINO */ - ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); - ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, DINO_ENABLE_SYSTEM); - - /* this is where the igx / win driver deveates from the VAP driver. */ - - /* wait for alive response */ - for (i = 0; i < 100; i++) { - /* poll for incoming data */ - cr = ipw_read_reg8(priv, IPW_BASEBAND_CONTROL_STATUS); - if (cr & DINO_RXFIFO_DATA) - break; - mdelay(1); - } - - if (cr & DINO_RXFIFO_DATA) { - /* alive_command_responce size is NOT multiple of 4 */ - __le32 response_buffer[(sizeof(priv->dino_alive) + 3) / 4]; - - for (i = 0; i < ARRAY_SIZE(response_buffer); i++) - response_buffer[i] = - cpu_to_le32(ipw_read_reg32(priv, - IPW_BASEBAND_RX_FIFO_READ)); - memcpy(&priv->dino_alive, response_buffer, - sizeof(priv->dino_alive)); - if (priv->dino_alive.alive_command == 1 - && priv->dino_alive.ucode_valid == 1) { - rc = 0; - IPW_DEBUG_INFO - ("Microcode OK, rev. %d (0x%x) dev. %d (0x%x) " - "of %02d/%02d/%02d %02d:%02d\n", - priv->dino_alive.software_revision, - priv->dino_alive.software_revision, - priv->dino_alive.device_identifier, - priv->dino_alive.device_identifier, - priv->dino_alive.time_stamp[0], - priv->dino_alive.time_stamp[1], - priv->dino_alive.time_stamp[2], - priv->dino_alive.time_stamp[3], - priv->dino_alive.time_stamp[4]); - } else { - IPW_DEBUG_INFO("Microcode is not alive\n"); - rc = -EINVAL; - } - } else { - IPW_DEBUG_INFO("No alive response from DINO\n"); - rc = -ETIME; - } - - /* disable DINO, otherwise for some reason - firmware have problem getting alive resp. */ - ipw_write_reg8(priv, IPW_BASEBAND_CONTROL_STATUS, 0); - - return rc; -} - -static int ipw_load_firmware(struct ipw_priv *priv, u8 * data, size_t len) -{ - int ret = -1; - int offset = 0; - struct fw_chunk *chunk; - int total_nr = 0; - int i; - struct pci_pool *pool; - u32 *virts[CB_NUMBER_OF_ELEMENTS_SMALL]; - dma_addr_t phys[CB_NUMBER_OF_ELEMENTS_SMALL]; - - IPW_DEBUG_TRACE("<< : \n"); - - pool = pci_pool_create("ipw2200", priv->pci_dev, CB_MAX_LENGTH, 0, 0); - if (!pool) { - IPW_ERROR("pci_pool_create failed\n"); - return -ENOMEM; - } - - /* Start the Dma */ - ret = ipw_fw_dma_enable(priv); - - /* the DMA is already ready this would be a bug. */ - BUG_ON(priv->sram_desc.last_cb_index > 0); - - do { - u32 chunk_len; - u8 *start; - int size; - int nr = 0; - - chunk = (struct fw_chunk *)(data + offset); - offset += sizeof(struct fw_chunk); - chunk_len = le32_to_cpu(chunk->length); - start = data + offset; - - nr = (chunk_len + CB_MAX_LENGTH - 1) / CB_MAX_LENGTH; - for (i = 0; i < nr; i++) { - virts[total_nr] = pci_pool_alloc(pool, GFP_KERNEL, - &phys[total_nr]); - if (!virts[total_nr]) { - ret = -ENOMEM; - goto out; - } - size = min_t(u32, chunk_len - i * CB_MAX_LENGTH, - CB_MAX_LENGTH); - memcpy(virts[total_nr], start, size); - start += size; - total_nr++; - /* We don't support fw chunk larger than 64*8K */ - BUG_ON(total_nr > CB_NUMBER_OF_ELEMENTS_SMALL); - } - - /* build DMA packet and queue up for sending */ - /* dma to chunk->address, the chunk->length bytes from data + - * offeset*/ - /* Dma loading */ - ret = ipw_fw_dma_add_buffer(priv, &phys[total_nr - nr], - nr, le32_to_cpu(chunk->address), - chunk_len); - if (ret) { - IPW_DEBUG_INFO("dmaAddBuffer Failed\n"); - goto out; - } - - offset += chunk_len; - } while (offset < len); - - /* Run the DMA and wait for the answer */ - ret = ipw_fw_dma_kick(priv); - if (ret) { - IPW_ERROR("dmaKick Failed\n"); - goto out; - } - - ret = ipw_fw_dma_wait(priv); - if (ret) { - IPW_ERROR("dmaWaitSync Failed\n"); - goto out; - } - out: - for (i = 0; i < total_nr; i++) - pci_pool_free(pool, virts[i], phys[i]); - - pci_pool_destroy(pool); - - return ret; -} - -/* stop nic */ -static int ipw_stop_nic(struct ipw_priv *priv) -{ - int rc = 0; - - /* stop */ - ipw_write32(priv, IPW_RESET_REG, IPW_RESET_REG_STOP_MASTER); - - rc = ipw_poll_bit(priv, IPW_RESET_REG, - IPW_RESET_REG_MASTER_DISABLED, 500); - if (rc < 0) { - IPW_ERROR("wait for reg master disabled failed after 500ms\n"); - return rc; - } - - ipw_set_bit(priv, IPW_RESET_REG, CBD_RESET_REG_PRINCETON_RESET); - - return rc; -} - -static void ipw_start_nic(struct ipw_priv *priv) -{ - IPW_DEBUG_TRACE(">>\n"); - - /* prvHwStartNic release ARC */ - ipw_clear_bit(priv, IPW_RESET_REG, - IPW_RESET_REG_MASTER_DISABLED | - IPW_RESET_REG_STOP_MASTER | - CBD_RESET_REG_PRINCETON_RESET); - - /* enable power management */ - ipw_set_bit(priv, IPW_GP_CNTRL_RW, - IPW_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY); - - IPW_DEBUG_TRACE("<<\n"); -} - -static int ipw_init_nic(struct ipw_priv *priv) -{ - int rc; - - IPW_DEBUG_TRACE(">>\n"); - /* reset */ - /*prvHwInitNic */ - /* set "initialization complete" bit to move adapter to D0 state */ - ipw_set_bit(priv, IPW_GP_CNTRL_RW, IPW_GP_CNTRL_BIT_INIT_DONE); - - /* low-level PLL activation */ - ipw_write32(priv, IPW_READ_INT_REGISTER, - IPW_BIT_INT_HOST_SRAM_READ_INT_REGISTER); - - /* wait for clock stabilization */ - rc = ipw_poll_bit(priv, IPW_GP_CNTRL_RW, - IPW_GP_CNTRL_BIT_CLOCK_READY, 250); - if (rc < 0) - IPW_DEBUG_INFO("FAILED wait for clock stablization\n"); - - /* assert SW reset */ - ipw_set_bit(priv, IPW_RESET_REG, IPW_RESET_REG_SW_RESET); - - udelay(10); - - /* set "initialization complete" bit to move adapter to D0 state */ - ipw_set_bit(priv, IPW_GP_CNTRL_RW, IPW_GP_CNTRL_BIT_INIT_DONE); - - IPW_DEBUG_TRACE(">>\n"); - return 0; -} - -/* Call this function from process context, it will sleep in request_firmware. - * Probe is an ok place to call this from. - */ -static int ipw_reset_nic(struct ipw_priv *priv) -{ - int rc = 0; - unsigned long flags; - - IPW_DEBUG_TRACE(">>\n"); - - rc = ipw_init_nic(priv); - - spin_lock_irqsave(&priv->lock, flags); - /* Clear the 'host command active' bit... */ - priv->status &= ~STATUS_HCMD_ACTIVE; - wake_up_interruptible(&priv->wait_command_queue); - priv->status &= ~(STATUS_SCANNING | STATUS_SCAN_ABORTING); - wake_up_interruptible(&priv->wait_state); - spin_unlock_irqrestore(&priv->lock, flags); - - IPW_DEBUG_TRACE("<<\n"); - return rc; -} - - -struct ipw_fw { - __le32 ver; - __le32 boot_size; - __le32 ucode_size; - __le32 fw_size; - u8 data[0]; -}; - -static int ipw_get_fw(struct ipw_priv *priv, - const struct firmware **raw, const char *name) -{ - struct ipw_fw *fw; - int rc; - - /* ask firmware_class module to get the boot firmware off disk */ - rc = request_firmware(raw, name, &priv->pci_dev->dev); - if (rc < 0) { - IPW_ERROR("%s request_firmware failed: Reason %d\n", name, rc); - return rc; - } - - if ((*raw)->size < sizeof(*fw)) { - IPW_ERROR("%s is too small (%zd)\n", name, (*raw)->size); - return -EINVAL; - } - - fw = (void *)(*raw)->data; - - if ((*raw)->size < sizeof(*fw) + le32_to_cpu(fw->boot_size) + - le32_to_cpu(fw->ucode_size) + le32_to_cpu(fw->fw_size)) { - IPW_ERROR("%s is too small or corrupt (%zd)\n", - name, (*raw)->size); - return -EINVAL; - } - - IPW_DEBUG_INFO("Read firmware '%s' image v%d.%d (%zd bytes)\n", - name, - le32_to_cpu(fw->ver) >> 16, - le32_to_cpu(fw->ver) & 0xff, - (*raw)->size - sizeof(*fw)); - return 0; -} - -#define IPW_RX_BUF_SIZE (3000) - -static void ipw_rx_queue_reset(struct ipw_priv *priv, - struct ipw_rx_queue *rxq) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&rxq->lock, flags); - - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rxq->pool[i].skb); - rxq->pool[i].skb = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - } - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->free_count = 0; - spin_unlock_irqrestore(&rxq->lock, flags); -} - -#ifdef CONFIG_PM -static int fw_loaded = 0; -static const struct firmware *raw = NULL; - -static void free_firmware(void) -{ - if (fw_loaded) { - release_firmware(raw); - raw = NULL; - fw_loaded = 0; - } -} -#else -#define free_firmware() do {} while (0) -#endif - -static int ipw_load(struct ipw_priv *priv) -{ -#ifndef CONFIG_PM - const struct firmware *raw = NULL; -#endif - struct ipw_fw *fw; - u8 *boot_img, *ucode_img, *fw_img; - u8 *name = NULL; - int rc = 0, retries = 3; - - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - name = "ipw2200-ibss.fw"; - break; -#ifdef CONFIG_IPW2200_MONITOR - case IW_MODE_MONITOR: - name = "ipw2200-sniffer.fw"; - break; -#endif - case IW_MODE_INFRA: - name = "ipw2200-bss.fw"; - break; - } - - if (!name) { - rc = -EINVAL; - goto error; - } - -#ifdef CONFIG_PM - if (!fw_loaded) { -#endif - rc = ipw_get_fw(priv, &raw, name); - if (rc < 0) - goto error; -#ifdef CONFIG_PM - } -#endif - - fw = (void *)raw->data; - boot_img = &fw->data[0]; - ucode_img = &fw->data[le32_to_cpu(fw->boot_size)]; - fw_img = &fw->data[le32_to_cpu(fw->boot_size) + - le32_to_cpu(fw->ucode_size)]; - - if (rc < 0) - goto error; - - if (!priv->rxq) - priv->rxq = ipw_rx_queue_alloc(priv); - else - ipw_rx_queue_reset(priv, priv->rxq); - if (!priv->rxq) { - IPW_ERROR("Unable to initialize Rx queue\n"); - goto error; - } - - retry: - /* Ensure interrupts are disabled */ - ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); - priv->status &= ~STATUS_INT_ENABLED; - - /* ack pending interrupts */ - ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); - - ipw_stop_nic(priv); - - rc = ipw_reset_nic(priv); - if (rc < 0) { - IPW_ERROR("Unable to reset NIC\n"); - goto error; - } - - ipw_zero_memory(priv, IPW_NIC_SRAM_LOWER_BOUND, - IPW_NIC_SRAM_UPPER_BOUND - IPW_NIC_SRAM_LOWER_BOUND); - - /* DMA the initial boot firmware into the device */ - rc = ipw_load_firmware(priv, boot_img, le32_to_cpu(fw->boot_size)); - if (rc < 0) { - IPW_ERROR("Unable to load boot firmware: %d\n", rc); - goto error; - } - - /* kick start the device */ - ipw_start_nic(priv); - - /* wait for the device to finish its initial startup sequence */ - rc = ipw_poll_bit(priv, IPW_INTA_RW, - IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); - if (rc < 0) { - IPW_ERROR("device failed to boot initial fw image\n"); - goto error; - } - IPW_DEBUG_INFO("initial device response after %dms\n", rc); - - /* ack fw init done interrupt */ - ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); - - /* DMA the ucode into the device */ - rc = ipw_load_ucode(priv, ucode_img, le32_to_cpu(fw->ucode_size)); - if (rc < 0) { - IPW_ERROR("Unable to load ucode: %d\n", rc); - goto error; - } - - /* stop nic */ - ipw_stop_nic(priv); - - /* DMA bss firmware into the device */ - rc = ipw_load_firmware(priv, fw_img, le32_to_cpu(fw->fw_size)); - if (rc < 0) { - IPW_ERROR("Unable to load firmware: %d\n", rc); - goto error; - } -#ifdef CONFIG_PM - fw_loaded = 1; -#endif - - ipw_write32(priv, IPW_EEPROM_LOAD_DISABLE, 0); - - rc = ipw_queue_reset(priv); - if (rc < 0) { - IPW_ERROR("Unable to initialize queues\n"); - goto error; - } - - /* Ensure interrupts are disabled */ - ipw_write32(priv, IPW_INTA_MASK_R, ~IPW_INTA_MASK_ALL); - /* ack pending interrupts */ - ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); - - /* kick start the device */ - ipw_start_nic(priv); - - if (ipw_read32(priv, IPW_INTA_RW) & IPW_INTA_BIT_PARITY_ERROR) { - if (retries > 0) { - IPW_WARNING("Parity error. Retrying init.\n"); - retries--; - goto retry; - } - - IPW_ERROR("TODO: Handle parity error -- schedule restart?\n"); - rc = -EIO; - goto error; - } - - /* wait for the device */ - rc = ipw_poll_bit(priv, IPW_INTA_RW, - IPW_INTA_BIT_FW_INITIALIZATION_DONE, 500); - if (rc < 0) { - IPW_ERROR("device failed to start within 500ms\n"); - goto error; - } - IPW_DEBUG_INFO("device response after %dms\n", rc); - - /* ack fw init done interrupt */ - ipw_write32(priv, IPW_INTA_RW, IPW_INTA_BIT_FW_INITIALIZATION_DONE); - - /* read eeprom data and initialize the eeprom region of sram */ - priv->eeprom_delay = 1; - ipw_eeprom_init_sram(priv); - - /* enable interrupts */ - ipw_enable_interrupts(priv); - - /* Ensure our queue has valid packets */ - ipw_rx_queue_replenish(priv); - - ipw_write32(priv, IPW_RX_READ_INDEX, priv->rxq->read); - - /* ack pending interrupts */ - ipw_write32(priv, IPW_INTA_RW, IPW_INTA_MASK_ALL); - -#ifndef CONFIG_PM - release_firmware(raw); -#endif - return 0; - - error: - if (priv->rxq) { - ipw_rx_queue_free(priv, priv->rxq); - priv->rxq = NULL; - } - ipw_tx_queue_free(priv); - if (raw) - release_firmware(raw); -#ifdef CONFIG_PM - fw_loaded = 0; - raw = NULL; -#endif - - return rc; -} - -/** - * DMA services - * - * Theory of operation - * - * A queue is a circular buffers with 'Read' and 'Write' pointers. - * 2 empty entries always kept in the buffer to protect from overflow. - * - * For Tx queue, there are low mark and high mark limits. If, after queuing - * the packet for Tx, free space become < low mark, Tx queue stopped. When - * reclaiming packets (on 'tx done IRQ), if free space become > high mark, - * Tx queue resumed. - * - * The IPW operates with six queues, one receive queue in the device's - * sram, one transmit queue for sending commands to the device firmware, - * and four transmit queues for data. - * - * The four transmit queues allow for performing quality of service (qos) - * transmissions as per the 802.11 protocol. Currently Linux does not - * provide a mechanism to the user for utilizing prioritized queues, so - * we only utilize the first data transmit queue (queue1). - */ - -/** - * Driver allocates buffers of this size for Rx - */ - -/** - * ipw_rx_queue_space - Return number of free slots available in queue. - */ -static int ipw_rx_queue_space(const struct ipw_rx_queue *q) -{ - int s = q->read - q->write; - if (s <= 0) - s += RX_QUEUE_SIZE; - /* keep some buffer to not confuse full and empty queue */ - s -= 2; - if (s < 0) - s = 0; - return s; -} - -static inline int ipw_tx_queue_space(const struct clx2_queue *q) -{ - int s = q->last_used - q->first_empty; - if (s <= 0) - s += q->n_bd; - s -= 2; /* keep some reserve to not confuse empty and full situations */ - if (s < 0) - s = 0; - return s; -} - -static inline int ipw_queue_inc_wrap(int index, int n_bd) -{ - return (++index == n_bd) ? 0 : index; -} - -/** - * Initialize common DMA queue structure - * - * @param q queue to init - * @param count Number of BD's to allocate. Should be power of 2 - * @param read_register Address for 'read' register - * (not offset within BAR, full address) - * @param write_register Address for 'write' register - * (not offset within BAR, full address) - * @param base_register Address for 'base' register - * (not offset within BAR, full address) - * @param size Address for 'size' register - * (not offset within BAR, full address) - */ -static void ipw_queue_init(struct ipw_priv *priv, struct clx2_queue *q, - int count, u32 read, u32 write, u32 base, u32 size) -{ - q->n_bd = count; - - q->low_mark = q->n_bd / 4; - if (q->low_mark < 4) - q->low_mark = 4; - - q->high_mark = q->n_bd / 8; - if (q->high_mark < 2) - q->high_mark = 2; - - q->first_empty = q->last_used = 0; - q->reg_r = read; - q->reg_w = write; - - ipw_write32(priv, base, q->dma_addr); - ipw_write32(priv, size, count); - ipw_write32(priv, read, 0); - ipw_write32(priv, write, 0); - - _ipw_read32(priv, 0x90); -} - -static int ipw_queue_tx_init(struct ipw_priv *priv, - struct clx2_tx_queue *q, - int count, u32 read, u32 write, u32 base, u32 size) -{ - struct pci_dev *dev = priv->pci_dev; - - q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL); - if (!q->txb) { - IPW_ERROR("vmalloc for auxilary BD structures failed\n"); - return -ENOMEM; - } - - q->bd = - pci_alloc_consistent(dev, sizeof(q->bd[0]) * count, &q->q.dma_addr); - if (!q->bd) { - IPW_ERROR("pci_alloc_consistent(%zd) failed\n", - sizeof(q->bd[0]) * count); - kfree(q->txb); - q->txb = NULL; - return -ENOMEM; - } - - ipw_queue_init(priv, &q->q, count, read, write, base, size); - return 0; -} - -/** - * Free one TFD, those at index [txq->q.last_used]. - * Do NOT advance any indexes - * - * @param dev - * @param txq - */ -static void ipw_queue_tx_free_tfd(struct ipw_priv *priv, - struct clx2_tx_queue *txq) -{ - struct tfd_frame *bd = &txq->bd[txq->q.last_used]; - struct pci_dev *dev = priv->pci_dev; - int i; - - /* classify bd */ - if (bd->control_flags.message_type == TX_HOST_COMMAND_TYPE) - /* nothing to cleanup after for host commands */ - return; - - /* sanity check */ - if (le32_to_cpu(bd->u.data.num_chunks) > NUM_TFD_CHUNKS) { - IPW_ERROR("Too many chunks: %i\n", - le32_to_cpu(bd->u.data.num_chunks)); - /** @todo issue fatal error, it is quite serious situation */ - return; - } - - /* unmap chunks if any */ - for (i = 0; i < le32_to_cpu(bd->u.data.num_chunks); i++) { - pci_unmap_single(dev, le32_to_cpu(bd->u.data.chunk_ptr[i]), - le16_to_cpu(bd->u.data.chunk_len[i]), - PCI_DMA_TODEVICE); - if (txq->txb[txq->q.last_used]) { - libipw_txb_free(txq->txb[txq->q.last_used]); - txq->txb[txq->q.last_used] = NULL; - } - } -} - -/** - * Deallocate DMA queue. - * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * - * @param dev - * @param q - */ -static void ipw_queue_tx_free(struct ipw_priv *priv, struct clx2_tx_queue *txq) -{ - struct clx2_queue *q = &txq->q; - struct pci_dev *dev = priv->pci_dev; - - if (q->n_bd == 0) - return; - - /* first, empty all BD's */ - for (; q->first_empty != q->last_used; - q->last_used = ipw_queue_inc_wrap(q->last_used, q->n_bd)) { - ipw_queue_tx_free_tfd(priv, txq); - } - - /* free buffers belonging to queue itself */ - pci_free_consistent(dev, sizeof(txq->bd[0]) * q->n_bd, txq->bd, - q->dma_addr); - kfree(txq->txb); - - /* 0 fill whole structure */ - memset(txq, 0, sizeof(*txq)); -} - -/** - * Destroy all DMA queues and structures - * - * @param priv - */ -static void ipw_tx_queue_free(struct ipw_priv *priv) -{ - /* Tx CMD queue */ - ipw_queue_tx_free(priv, &priv->txq_cmd); - - /* Tx queues */ - ipw_queue_tx_free(priv, &priv->txq[0]); - ipw_queue_tx_free(priv, &priv->txq[1]); - ipw_queue_tx_free(priv, &priv->txq[2]); - ipw_queue_tx_free(priv, &priv->txq[3]); -} - -static void ipw_create_bssid(struct ipw_priv *priv, u8 * bssid) -{ - /* First 3 bytes are manufacturer */ - bssid[0] = priv->mac_addr[0]; - bssid[1] = priv->mac_addr[1]; - bssid[2] = priv->mac_addr[2]; - - /* Last bytes are random */ - get_random_bytes(&bssid[3], ETH_ALEN - 3); - - bssid[0] &= 0xfe; /* clear multicast bit */ - bssid[0] |= 0x02; /* set local assignment bit (IEEE802) */ -} - -static u8 ipw_add_station(struct ipw_priv *priv, u8 * bssid) -{ - struct ipw_station_entry entry; - int i; - - for (i = 0; i < priv->num_stations; i++) { - if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) { - /* Another node is active in network */ - priv->missed_adhoc_beacons = 0; - if (!(priv->config & CFG_STATIC_CHANNEL)) - /* when other nodes drop out, we drop out */ - priv->config &= ~CFG_ADHOC_PERSIST; - - return i; - } - } - - if (i == MAX_STATIONS) - return IPW_INVALID_STATION; - - IPW_DEBUG_SCAN("Adding AdHoc station: %pM\n", bssid); - - entry.reserved = 0; - entry.support_mode = 0; - memcpy(entry.mac_addr, bssid, ETH_ALEN); - memcpy(priv->stations[i], bssid, ETH_ALEN); - ipw_write_direct(priv, IPW_STATION_TABLE_LOWER + i * sizeof(entry), - &entry, sizeof(entry)); - priv->num_stations++; - - return i; -} - -static u8 ipw_find_station(struct ipw_priv *priv, u8 * bssid) -{ - int i; - - for (i = 0; i < priv->num_stations; i++) - if (!memcmp(priv->stations[i], bssid, ETH_ALEN)) - return i; - - return IPW_INVALID_STATION; -} - -static void ipw_send_disassociate(struct ipw_priv *priv, int quiet) -{ - int err; - - if (priv->status & STATUS_ASSOCIATING) { - IPW_DEBUG_ASSOC("Disassociating while associating.\n"); - queue_work(priv->workqueue, &priv->disassociate); - return; - } - - if (!(priv->status & STATUS_ASSOCIATED)) { - IPW_DEBUG_ASSOC("Disassociating while not associated.\n"); - return; - } - - IPW_DEBUG_ASSOC("Disassocation attempt from %pM " - "on channel %d.\n", - priv->assoc_request.bssid, - priv->assoc_request.channel); - - priv->status &= ~(STATUS_ASSOCIATING | STATUS_ASSOCIATED); - priv->status |= STATUS_DISASSOCIATING; - - if (quiet) - priv->assoc_request.assoc_type = HC_DISASSOC_QUIET; - else - priv->assoc_request.assoc_type = HC_DISASSOCIATE; - - err = ipw_send_associate(priv, &priv->assoc_request); - if (err) { - IPW_DEBUG_HC("Attempt to send [dis]associate command " - "failed.\n"); - return; - } - -} - -static int ipw_disassociate(void *data) -{ - struct ipw_priv *priv = data; - if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) - return 0; - ipw_send_disassociate(data, 0); - netif_carrier_off(priv->net_dev); - return 1; -} - -static void ipw_bg_disassociate(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, disassociate); - mutex_lock(&priv->mutex); - ipw_disassociate(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_system_config(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, system_config); - -#ifdef CONFIG_IPW2200_PROMISCUOUS - if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { - priv->sys_config.accept_all_data_frames = 1; - priv->sys_config.accept_non_directed_frames = 1; - priv->sys_config.accept_all_mgmt_bcpr = 1; - priv->sys_config.accept_all_mgmt_frames = 1; - } -#endif - - ipw_send_system_config(priv); -} - -struct ipw_status_code { - u16 status; - const char *reason; -}; - -static const struct ipw_status_code ipw_status_codes[] = { - {0x00, "Successful"}, - {0x01, "Unspecified failure"}, - {0x0A, "Cannot support all requested capabilities in the " - "Capability information field"}, - {0x0B, "Reassociation denied due to inability to confirm that " - "association exists"}, - {0x0C, "Association denied due to reason outside the scope of this " - "standard"}, - {0x0D, - "Responding station does not support the specified authentication " - "algorithm"}, - {0x0E, - "Received an Authentication frame with authentication sequence " - "transaction sequence number out of expected sequence"}, - {0x0F, "Authentication rejected because of challenge failure"}, - {0x10, "Authentication rejected due to timeout waiting for next " - "frame in sequence"}, - {0x11, "Association denied because AP is unable to handle additional " - "associated stations"}, - {0x12, - "Association denied due to requesting station not supporting all " - "of the datarates in the BSSBasicServiceSet Parameter"}, - {0x13, - "Association denied due to requesting station not supporting " - "short preamble operation"}, - {0x14, - "Association denied due to requesting station not supporting " - "PBCC encoding"}, - {0x15, - "Association denied due to requesting station not supporting " - "channel agility"}, - {0x19, - "Association denied due to requesting station not supporting " - "short slot operation"}, - {0x1A, - "Association denied due to requesting station not supporting " - "DSSS-OFDM operation"}, - {0x28, "Invalid Information Element"}, - {0x29, "Group Cipher is not valid"}, - {0x2A, "Pairwise Cipher is not valid"}, - {0x2B, "AKMP is not valid"}, - {0x2C, "Unsupported RSN IE version"}, - {0x2D, "Invalid RSN IE Capabilities"}, - {0x2E, "Cipher suite is rejected per security policy"}, -}; - -static const char *ipw_get_status_code(u16 status) -{ - int i; - for (i = 0; i < ARRAY_SIZE(ipw_status_codes); i++) - if (ipw_status_codes[i].status == (status & 0xff)) - return ipw_status_codes[i].reason; - return "Unknown status value."; -} - -static void inline average_init(struct average *avg) -{ - memset(avg, 0, sizeof(*avg)); -} - -#define DEPTH_RSSI 8 -#define DEPTH_NOISE 16 -static s16 exponential_average(s16 prev_avg, s16 val, u8 depth) -{ - return ((depth-1)*prev_avg + val)/depth; -} - -static void average_add(struct average *avg, s16 val) -{ - avg->sum -= avg->entries[avg->pos]; - avg->sum += val; - avg->entries[avg->pos++] = val; - if (unlikely(avg->pos == AVG_ENTRIES)) { - avg->init = 1; - avg->pos = 0; - } -} - -static s16 average_value(struct average *avg) -{ - if (!unlikely(avg->init)) { - if (avg->pos) - return avg->sum / avg->pos; - return 0; - } - - return avg->sum / AVG_ENTRIES; -} - -static void ipw_reset_stats(struct ipw_priv *priv) -{ - u32 len = sizeof(u32); - - priv->quality = 0; - - average_init(&priv->average_missed_beacons); - priv->exp_avg_rssi = -60; - priv->exp_avg_noise = -85 + 0x100; - - priv->last_rate = 0; - priv->last_missed_beacons = 0; - priv->last_rx_packets = 0; - priv->last_tx_packets = 0; - priv->last_tx_failures = 0; - - /* Firmware managed, reset only when NIC is restarted, so we have to - * normalize on the current value */ - ipw_get_ordinal(priv, IPW_ORD_STAT_RX_ERR_CRC, - &priv->last_rx_err, &len); - ipw_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURE, - &priv->last_tx_failures, &len); - - /* Driver managed, reset with each association */ - priv->missed_adhoc_beacons = 0; - priv->missed_beacons = 0; - priv->tx_packets = 0; - priv->rx_packets = 0; - -} - -static u32 ipw_get_max_rate(struct ipw_priv *priv) -{ - u32 i = 0x80000000; - u32 mask = priv->rates_mask; - /* If currently associated in B mode, restrict the maximum - * rate match to B rates */ - if (priv->assoc_request.ieee_mode == IPW_B_MODE) - mask &= LIBIPW_CCK_RATES_MASK; - - /* TODO: Verify that the rate is supported by the current rates - * list. */ - - while (i && !(mask & i)) - i >>= 1; - switch (i) { - case LIBIPW_CCK_RATE_1MB_MASK: - return 1000000; - case LIBIPW_CCK_RATE_2MB_MASK: - return 2000000; - case LIBIPW_CCK_RATE_5MB_MASK: - return 5500000; - case LIBIPW_OFDM_RATE_6MB_MASK: - return 6000000; - case LIBIPW_OFDM_RATE_9MB_MASK: - return 9000000; - case LIBIPW_CCK_RATE_11MB_MASK: - return 11000000; - case LIBIPW_OFDM_RATE_12MB_MASK: - return 12000000; - case LIBIPW_OFDM_RATE_18MB_MASK: - return 18000000; - case LIBIPW_OFDM_RATE_24MB_MASK: - return 24000000; - case LIBIPW_OFDM_RATE_36MB_MASK: - return 36000000; - case LIBIPW_OFDM_RATE_48MB_MASK: - return 48000000; - case LIBIPW_OFDM_RATE_54MB_MASK: - return 54000000; - } - - if (priv->ieee->mode == IEEE_B) - return 11000000; - else - return 54000000; -} - -static u32 ipw_get_current_rate(struct ipw_priv *priv) -{ - u32 rate, len = sizeof(rate); - int err; - - if (!(priv->status & STATUS_ASSOCIATED)) - return 0; - - if (priv->tx_packets > IPW_REAL_RATE_RX_PACKET_THRESHOLD) { - err = ipw_get_ordinal(priv, IPW_ORD_STAT_TX_CURR_RATE, &rate, - &len); - if (err) { - IPW_DEBUG_INFO("failed querying ordinals.\n"); - return 0; - } - } else - return ipw_get_max_rate(priv); - - switch (rate) { - case IPW_TX_RATE_1MB: - return 1000000; - case IPW_TX_RATE_2MB: - return 2000000; - case IPW_TX_RATE_5MB: - return 5500000; - case IPW_TX_RATE_6MB: - return 6000000; - case IPW_TX_RATE_9MB: - return 9000000; - case IPW_TX_RATE_11MB: - return 11000000; - case IPW_TX_RATE_12MB: - return 12000000; - case IPW_TX_RATE_18MB: - return 18000000; - case IPW_TX_RATE_24MB: - return 24000000; - case IPW_TX_RATE_36MB: - return 36000000; - case IPW_TX_RATE_48MB: - return 48000000; - case IPW_TX_RATE_54MB: - return 54000000; - } - - return 0; -} - -#define IPW_STATS_INTERVAL (2 * HZ) -static void ipw_gather_stats(struct ipw_priv *priv) -{ - u32 rx_err, rx_err_delta, rx_packets_delta; - u32 tx_failures, tx_failures_delta, tx_packets_delta; - u32 missed_beacons_percent, missed_beacons_delta; - u32 quality = 0; - u32 len = sizeof(u32); - s16 rssi; - u32 beacon_quality, signal_quality, tx_quality, rx_quality, - rate_quality; - u32 max_rate; - - if (!(priv->status & STATUS_ASSOCIATED)) { - priv->quality = 0; - return; - } - - /* Update the statistics */ - ipw_get_ordinal(priv, IPW_ORD_STAT_MISSED_BEACONS, - &priv->missed_beacons, &len); - missed_beacons_delta = priv->missed_beacons - priv->last_missed_beacons; - priv->last_missed_beacons = priv->missed_beacons; - if (priv->assoc_request.beacon_interval) { - missed_beacons_percent = missed_beacons_delta * - (HZ * le16_to_cpu(priv->assoc_request.beacon_interval)) / - (IPW_STATS_INTERVAL * 10); - } else { - missed_beacons_percent = 0; - } - average_add(&priv->average_missed_beacons, missed_beacons_percent); - - ipw_get_ordinal(priv, IPW_ORD_STAT_RX_ERR_CRC, &rx_err, &len); - rx_err_delta = rx_err - priv->last_rx_err; - priv->last_rx_err = rx_err; - - ipw_get_ordinal(priv, IPW_ORD_STAT_TX_FAILURE, &tx_failures, &len); - tx_failures_delta = tx_failures - priv->last_tx_failures; - priv->last_tx_failures = tx_failures; - - rx_packets_delta = priv->rx_packets - priv->last_rx_packets; - priv->last_rx_packets = priv->rx_packets; - - tx_packets_delta = priv->tx_packets - priv->last_tx_packets; - priv->last_tx_packets = priv->tx_packets; - - /* Calculate quality based on the following: - * - * Missed beacon: 100% = 0, 0% = 70% missed - * Rate: 60% = 1Mbs, 100% = Max - * Rx and Tx errors represent a straight % of total Rx/Tx - * RSSI: 100% = > -50, 0% = < -80 - * Rx errors: 100% = 0, 0% = 50% missed - * - * The lowest computed quality is used. - * - */ -#define BEACON_THRESHOLD 5 - beacon_quality = 100 - missed_beacons_percent; - if (beacon_quality < BEACON_THRESHOLD) - beacon_quality = 0; - else - beacon_quality = (beacon_quality - BEACON_THRESHOLD) * 100 / - (100 - BEACON_THRESHOLD); - IPW_DEBUG_STATS("Missed beacon: %3d%% (%d%%)\n", - beacon_quality, missed_beacons_percent); - - priv->last_rate = ipw_get_current_rate(priv); - max_rate = ipw_get_max_rate(priv); - rate_quality = priv->last_rate * 40 / max_rate + 60; - IPW_DEBUG_STATS("Rate quality : %3d%% (%dMbs)\n", - rate_quality, priv->last_rate / 1000000); - - if (rx_packets_delta > 100 && rx_packets_delta + rx_err_delta) - rx_quality = 100 - (rx_err_delta * 100) / - (rx_packets_delta + rx_err_delta); - else - rx_quality = 100; - IPW_DEBUG_STATS("Rx quality : %3d%% (%u errors, %u packets)\n", - rx_quality, rx_err_delta, rx_packets_delta); - - if (tx_packets_delta > 100 && tx_packets_delta + tx_failures_delta) - tx_quality = 100 - (tx_failures_delta * 100) / - (tx_packets_delta + tx_failures_delta); - else - tx_quality = 100; - IPW_DEBUG_STATS("Tx quality : %3d%% (%u errors, %u packets)\n", - tx_quality, tx_failures_delta, tx_packets_delta); - - rssi = priv->exp_avg_rssi; - signal_quality = - (100 * - (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * - (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) - - (priv->ieee->perfect_rssi - rssi) * - (15 * (priv->ieee->perfect_rssi - priv->ieee->worst_rssi) + - 62 * (priv->ieee->perfect_rssi - rssi))) / - ((priv->ieee->perfect_rssi - priv->ieee->worst_rssi) * - (priv->ieee->perfect_rssi - priv->ieee->worst_rssi)); - if (signal_quality > 100) - signal_quality = 100; - else if (signal_quality < 1) - signal_quality = 0; - - IPW_DEBUG_STATS("Signal level : %3d%% (%d dBm)\n", - signal_quality, rssi); - - quality = min(rx_quality, signal_quality); - quality = min(tx_quality, quality); - quality = min(rate_quality, quality); - quality = min(beacon_quality, quality); - if (quality == beacon_quality) - IPW_DEBUG_STATS("Quality (%d%%): Clamped to missed beacons.\n", - quality); - if (quality == rate_quality) - IPW_DEBUG_STATS("Quality (%d%%): Clamped to rate quality.\n", - quality); - if (quality == tx_quality) - IPW_DEBUG_STATS("Quality (%d%%): Clamped to Tx quality.\n", - quality); - if (quality == rx_quality) - IPW_DEBUG_STATS("Quality (%d%%): Clamped to Rx quality.\n", - quality); - if (quality == signal_quality) - IPW_DEBUG_STATS("Quality (%d%%): Clamped to signal quality.\n", - quality); - - priv->quality = quality; - - queue_delayed_work(priv->workqueue, &priv->gather_stats, - IPW_STATS_INTERVAL); -} - -static void ipw_bg_gather_stats(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, gather_stats.work); - mutex_lock(&priv->mutex); - ipw_gather_stats(priv); - mutex_unlock(&priv->mutex); -} - -/* Missed beacon behavior: - * 1st missed -> roaming_threshold, just wait, don't do any scan/roam. - * roaming_threshold -> disassociate_threshold, scan and roam for better signal. - * Above disassociate threshold, give up and stop scanning. - * Roaming is disabled if disassociate_threshold <= roaming_threshold */ -static void ipw_handle_missed_beacon(struct ipw_priv *priv, - int missed_count) -{ - priv->notif_missed_beacons = missed_count; - - if (missed_count > priv->disassociate_threshold && - priv->status & STATUS_ASSOCIATED) { - /* If associated and we've hit the missed - * beacon threshold, disassociate, turn - * off roaming, and abort any active scans */ - IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | - IPW_DL_STATE | IPW_DL_ASSOC, - "Missed beacon: %d - disassociate\n", missed_count); - priv->status &= ~STATUS_ROAMING; - if (priv->status & STATUS_SCANNING) { - IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | - IPW_DL_STATE, - "Aborting scan with missed beacon.\n"); - queue_work(priv->workqueue, &priv->abort_scan); - } - - queue_work(priv->workqueue, &priv->disassociate); - return; - } - - if (priv->status & STATUS_ROAMING) { - /* If we are currently roaming, then just - * print a debug statement... */ - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "Missed beacon: %d - roam in progress\n", - missed_count); - return; - } - - if (roaming && - (missed_count > priv->roaming_threshold && - missed_count <= priv->disassociate_threshold)) { - /* If we are not already roaming, set the ROAM - * bit in the status and kick off a scan. - * This can happen several times before we reach - * disassociate_threshold. */ - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "Missed beacon: %d - initiate " - "roaming\n", missed_count); - if (!(priv->status & STATUS_ROAMING)) { - priv->status |= STATUS_ROAMING; - if (!(priv->status & STATUS_SCANNING)) - queue_delayed_work(priv->workqueue, - &priv->request_scan, 0); - } - return; - } - - if (priv->status & STATUS_SCANNING && - missed_count > IPW_MB_SCAN_CANCEL_THRESHOLD) { - /* Stop scan to keep fw from getting - * stuck (only if we aren't roaming -- - * otherwise we'll never scan more than 2 or 3 - * channels..) */ - IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | IPW_DL_STATE, - "Aborting scan with missed beacon.\n"); - queue_work(priv->workqueue, &priv->abort_scan); - } - - IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count); -} - -static void ipw_scan_event(struct work_struct *work) -{ - union iwreq_data wrqu; - - struct ipw_priv *priv = - container_of(work, struct ipw_priv, scan_event.work); - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); -} - -static void handle_scan_event(struct ipw_priv *priv) -{ - /* Only userspace-requested scan completion events go out immediately */ - if (!priv->user_requested_scan) { - if (!delayed_work_pending(&priv->scan_event)) - queue_delayed_work(priv->workqueue, &priv->scan_event, - round_jiffies_relative(msecs_to_jiffies(4000))); - } else { - union iwreq_data wrqu; - - priv->user_requested_scan = 0; - cancel_delayed_work(&priv->scan_event); - - wrqu.data.length = 0; - wrqu.data.flags = 0; - wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); - } -} - -/** - * Handle host notification packet. - * Called from interrupt routine - */ -static void ipw_rx_notification(struct ipw_priv *priv, - struct ipw_rx_notification *notif) -{ - DECLARE_SSID_BUF(ssid); - u16 size = le16_to_cpu(notif->size); - - IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); - - switch (notif->subtype) { - case HOST_NOTIFICATION_STATUS_ASSOCIATED:{ - struct notif_association *assoc = ¬if->u.assoc; - - switch (assoc->state) { - case CMAS_ASSOCIATED:{ - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, - "associated: '%s' %pM \n", - print_ssid(ssid, priv->essid, - priv->essid_len), - priv->bssid); - - switch (priv->ieee->iw_mode) { - case IW_MODE_INFRA: - memcpy(priv->ieee->bssid, - priv->bssid, ETH_ALEN); - break; - - case IW_MODE_ADHOC: - memcpy(priv->ieee->bssid, - priv->bssid, ETH_ALEN); - - /* clear out the station table */ - priv->num_stations = 0; - - IPW_DEBUG_ASSOC - ("queueing adhoc check\n"); - queue_delayed_work(priv-> - workqueue, - &priv-> - adhoc_check, - le16_to_cpu(priv-> - assoc_request. - beacon_interval)); - break; - } - - priv->status &= ~STATUS_ASSOCIATING; - priv->status |= STATUS_ASSOCIATED; - queue_work(priv->workqueue, - &priv->system_config); - -#ifdef CONFIG_IPW2200_QOS -#define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \ - le16_to_cpu(((struct ieee80211_hdr *)(x))->frame_control)) - if ((priv->status & STATUS_AUTH) && - (IPW_GET_PACKET_STYPE(¬if->u.raw) - == IEEE80211_STYPE_ASSOC_RESP)) { - if ((sizeof - (struct - libipw_assoc_response) - <= size) - && (size <= 2314)) { - struct - libipw_rx_stats - stats = { - .len = size - 1, - }; - - IPW_DEBUG_QOS - ("QoS Associate " - "size %d\n", size); - libipw_rx_mgt(priv-> - ieee, - (struct - libipw_hdr_4addr - *) - ¬if->u.raw, &stats); - } - } -#endif - - schedule_work(&priv->link_up); - - break; - } - - case CMAS_AUTHENTICATED:{ - if (priv-> - status & (STATUS_ASSOCIATED | - STATUS_AUTH)) { - struct notif_authenticate *auth - = ¬if->u.auth; - IPW_DEBUG(IPW_DL_NOTIF | - IPW_DL_STATE | - IPW_DL_ASSOC, - "deauthenticated: '%s' " - "%pM" - ": (0x%04X) - %s \n", - print_ssid(ssid, - priv-> - essid, - priv-> - essid_len), - priv->bssid, - le16_to_cpu(auth->status), - ipw_get_status_code - (le16_to_cpu - (auth->status))); - - priv->status &= - ~(STATUS_ASSOCIATING | - STATUS_AUTH | - STATUS_ASSOCIATED); - - schedule_work(&priv->link_down); - break; - } - - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, - "authenticated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), - priv->bssid); - break; - } - - case CMAS_INIT:{ - if (priv->status & STATUS_AUTH) { - struct - libipw_assoc_response - *resp; - resp = - (struct - libipw_assoc_response - *)¬if->u.raw; - IPW_DEBUG(IPW_DL_NOTIF | - IPW_DL_STATE | - IPW_DL_ASSOC, - "association failed (0x%04X): %s\n", - le16_to_cpu(resp->status), - ipw_get_status_code - (le16_to_cpu - (resp->status))); - } - - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, - "disassociated: '%s' %pM \n", - print_ssid(ssid, priv->essid, - priv->essid_len), - priv->bssid); - - priv->status &= - ~(STATUS_DISASSOCIATING | - STATUS_ASSOCIATING | - STATUS_ASSOCIATED | STATUS_AUTH); - if (priv->assoc_network - && (priv->assoc_network-> - capability & - WLAN_CAPABILITY_IBSS)) - ipw_remove_current_network - (priv); - - schedule_work(&priv->link_down); - - break; - } - - case CMAS_RX_ASSOC_RESP: - break; - - default: - IPW_ERROR("assoc: unknown (%d)\n", - assoc->state); - break; - } - - break; - } - - case HOST_NOTIFICATION_STATUS_AUTHENTICATE:{ - struct notif_authenticate *auth = ¬if->u.auth; - switch (auth->state) { - case CMAS_AUTHENTICATED: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "authenticated: '%s' %pM \n", - print_ssid(ssid, priv->essid, - priv->essid_len), - priv->bssid); - priv->status |= STATUS_AUTH; - break; - - case CMAS_INIT: - if (priv->status & STATUS_AUTH) { - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, - "authentication failed (0x%04X): %s\n", - le16_to_cpu(auth->status), - ipw_get_status_code(le16_to_cpu - (auth-> - status))); - } - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, - "deauthenticated: '%s' %pM\n", - print_ssid(ssid, priv->essid, - priv->essid_len), - priv->bssid); - - priv->status &= ~(STATUS_ASSOCIATING | - STATUS_AUTH | - STATUS_ASSOCIATED); - - schedule_work(&priv->link_down); - break; - - case CMAS_TX_AUTH_SEQ_1: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUTH_SEQ_1\n"); - break; - case CMAS_RX_AUTH_SEQ_2: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUTH_SEQ_2\n"); - break; - case CMAS_AUTH_SEQ_1_PASS: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUTH_SEQ_1_PASS\n"); - break; - case CMAS_AUTH_SEQ_1_FAIL: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUTH_SEQ_1_FAIL\n"); - break; - case CMAS_TX_AUTH_SEQ_3: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUTH_SEQ_3\n"); - break; - case CMAS_RX_AUTH_SEQ_4: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "RX_AUTH_SEQ_4\n"); - break; - case CMAS_AUTH_SEQ_2_PASS: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUTH_SEQ_2_PASS\n"); - break; - case CMAS_AUTH_SEQ_2_FAIL: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "AUT_SEQ_2_FAIL\n"); - break; - case CMAS_TX_ASSOC: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "TX_ASSOC\n"); - break; - case CMAS_RX_ASSOC_RESP: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "RX_ASSOC_RESP\n"); - - break; - case CMAS_ASSOCIATED: - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | - IPW_DL_ASSOC, "ASSOCIATED\n"); - break; - default: - IPW_DEBUG_NOTIF("auth: failure - %d\n", - auth->state); - break; - } - break; - } - - case HOST_NOTIFICATION_STATUS_SCAN_CHANNEL_RESULT:{ - struct notif_channel_result *x = - ¬if->u.channel_result; - - if (size == sizeof(*x)) { - IPW_DEBUG_SCAN("Scan result for channel %d\n", - x->channel_num); - } else { - IPW_DEBUG_SCAN("Scan result of wrong size %d " - "(should be %zd)\n", - size, sizeof(*x)); - } - break; - } - - case HOST_NOTIFICATION_STATUS_SCAN_COMPLETED:{ - struct notif_scan_complete *x = ¬if->u.scan_complete; - if (size == sizeof(*x)) { - IPW_DEBUG_SCAN - ("Scan completed: type %d, %d channels, " - "%d status\n", x->scan_type, - x->num_channels, x->status); - } else { - IPW_ERROR("Scan completed of wrong size %d " - "(should be %zd)\n", - size, sizeof(*x)); - } - - priv->status &= - ~(STATUS_SCANNING | STATUS_SCAN_ABORTING); - - wake_up_interruptible(&priv->wait_state); - cancel_delayed_work(&priv->scan_check); - - if (priv->status & STATUS_EXIT_PENDING) - break; - - priv->ieee->scans++; - -#ifdef CONFIG_IPW2200_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - priv->status |= STATUS_SCAN_FORCED; - queue_delayed_work(priv->workqueue, - &priv->request_scan, 0); - break; - } - priv->status &= ~STATUS_SCAN_FORCED; -#endif /* CONFIG_IPW2200_MONITOR */ - - /* Do queued direct scans first */ - if (priv->status & STATUS_DIRECT_SCAN_PENDING) { - queue_delayed_work(priv->workqueue, - &priv->request_direct_scan, 0); - } - - if (!(priv->status & (STATUS_ASSOCIATED | - STATUS_ASSOCIATING | - STATUS_ROAMING | - STATUS_DISASSOCIATING))) - queue_work(priv->workqueue, &priv->associate); - else if (priv->status & STATUS_ROAMING) { - if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) - /* If a scan completed and we are in roam mode, then - * the scan that completed was the one requested as a - * result of entering roam... so, schedule the - * roam work */ - queue_work(priv->workqueue, - &priv->roam); - else - /* Don't schedule if we aborted the scan */ - priv->status &= ~STATUS_ROAMING; - } else if (priv->status & STATUS_SCAN_PENDING) - queue_delayed_work(priv->workqueue, - &priv->request_scan, 0); - else if (priv->config & CFG_BACKGROUND_SCAN - && priv->status & STATUS_ASSOCIATED) - queue_delayed_work(priv->workqueue, - &priv->request_scan, - round_jiffies_relative(HZ)); - - /* Send an empty event to user space. - * We don't send the received data on the event because - * it would require us to do complex transcoding, and - * we want to minimise the work done in the irq handler - * Use a request to extract the data. - * Also, we generate this even for any scan, regardless - * on how the scan was initiated. User space can just - * sync on periodic scan to get fresh data... - * Jean II */ - if (x->status == SCAN_COMPLETED_STATUS_COMPLETE) - handle_scan_event(priv); - break; - } - - case HOST_NOTIFICATION_STATUS_FRAG_LENGTH:{ - struct notif_frag_length *x = ¬if->u.frag_len; - - if (size == sizeof(*x)) - IPW_ERROR("Frag length: %d\n", - le16_to_cpu(x->frag_length)); - else - IPW_ERROR("Frag length of wrong size %d " - "(should be %zd)\n", - size, sizeof(*x)); - break; - } - - case HOST_NOTIFICATION_STATUS_LINK_DETERIORATION:{ - struct notif_link_deterioration *x = - ¬if->u.link_deterioration; - - if (size == sizeof(*x)) { - IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, - "link deterioration: type %d, cnt %d\n", - x->silence_notification_type, - x->silence_count); - memcpy(&priv->last_link_deterioration, x, - sizeof(*x)); - } else { - IPW_ERROR("Link Deterioration of wrong size %d " - "(should be %zd)\n", - size, sizeof(*x)); - } - break; - } - - case HOST_NOTIFICATION_DINO_CONFIG_RESPONSE:{ - IPW_ERROR("Dino config\n"); - if (priv->hcmd - && priv->hcmd->cmd != HOST_CMD_DINO_CONFIG) - IPW_ERROR("Unexpected DINO_CONFIG_RESPONSE\n"); - - break; - } - - case HOST_NOTIFICATION_STATUS_BEACON_STATE:{ - struct notif_beacon_state *x = ¬if->u.beacon_state; - if (size != sizeof(*x)) { - IPW_ERROR - ("Beacon state of wrong size %d (should " - "be %zd)\n", size, sizeof(*x)); - break; - } - - if (le32_to_cpu(x->state) == - HOST_NOTIFICATION_STATUS_BEACON_MISSING) - ipw_handle_missed_beacon(priv, - le32_to_cpu(x-> - number)); - - break; - } - - case HOST_NOTIFICATION_STATUS_TGI_TX_KEY:{ - struct notif_tgi_tx_key *x = ¬if->u.tgi_tx_key; - if (size == sizeof(*x)) { - IPW_ERROR("TGi Tx Key: state 0x%02x sec type " - "0x%02x station %d\n", - x->key_state, x->security_type, - x->station_index); - break; - } - - IPW_ERROR - ("TGi Tx Key of wrong size %d (should be %zd)\n", - size, sizeof(*x)); - break; - } - - case HOST_NOTIFICATION_CALIB_KEEP_RESULTS:{ - struct notif_calibration *x = ¬if->u.calibration; - - if (size == sizeof(*x)) { - memcpy(&priv->calib, x, sizeof(*x)); - IPW_DEBUG_INFO("TODO: Calibration\n"); - break; - } - - IPW_ERROR - ("Calibration of wrong size %d (should be %zd)\n", - size, sizeof(*x)); - break; - } - - case HOST_NOTIFICATION_NOISE_STATS:{ - if (size == sizeof(u32)) { - priv->exp_avg_noise = - exponential_average(priv->exp_avg_noise, - (u8) (le32_to_cpu(notif->u.noise.value) & 0xff), - DEPTH_NOISE); - break; - } - - IPW_ERROR - ("Noise stat is wrong size %d (should be %zd)\n", - size, sizeof(u32)); - break; - } - - default: - IPW_DEBUG_NOTIF("Unknown notification: " - "subtype=%d,flags=0x%2x,size=%d\n", - notif->subtype, notif->flags, size); - } -} - -/** - * Destroys all DMA structures and initialise them again - * - * @param priv - * @return error code - */ -static int ipw_queue_reset(struct ipw_priv *priv) -{ - int rc = 0; - /** @todo customize queue sizes */ - int nTx = 64, nTxCmd = 8; - ipw_tx_queue_free(priv); - /* Tx CMD queue */ - rc = ipw_queue_tx_init(priv, &priv->txq_cmd, nTxCmd, - IPW_TX_CMD_QUEUE_READ_INDEX, - IPW_TX_CMD_QUEUE_WRITE_INDEX, - IPW_TX_CMD_QUEUE_BD_BASE, - IPW_TX_CMD_QUEUE_BD_SIZE); - if (rc) { - IPW_ERROR("Tx Cmd queue init failed\n"); - goto error; - } - /* Tx queue(s) */ - rc = ipw_queue_tx_init(priv, &priv->txq[0], nTx, - IPW_TX_QUEUE_0_READ_INDEX, - IPW_TX_QUEUE_0_WRITE_INDEX, - IPW_TX_QUEUE_0_BD_BASE, IPW_TX_QUEUE_0_BD_SIZE); - if (rc) { - IPW_ERROR("Tx 0 queue init failed\n"); - goto error; - } - rc = ipw_queue_tx_init(priv, &priv->txq[1], nTx, - IPW_TX_QUEUE_1_READ_INDEX, - IPW_TX_QUEUE_1_WRITE_INDEX, - IPW_TX_QUEUE_1_BD_BASE, IPW_TX_QUEUE_1_BD_SIZE); - if (rc) { - IPW_ERROR("Tx 1 queue init failed\n"); - goto error; - } - rc = ipw_queue_tx_init(priv, &priv->txq[2], nTx, - IPW_TX_QUEUE_2_READ_INDEX, - IPW_TX_QUEUE_2_WRITE_INDEX, - IPW_TX_QUEUE_2_BD_BASE, IPW_TX_QUEUE_2_BD_SIZE); - if (rc) { - IPW_ERROR("Tx 2 queue init failed\n"); - goto error; - } - rc = ipw_queue_tx_init(priv, &priv->txq[3], nTx, - IPW_TX_QUEUE_3_READ_INDEX, - IPW_TX_QUEUE_3_WRITE_INDEX, - IPW_TX_QUEUE_3_BD_BASE, IPW_TX_QUEUE_3_BD_SIZE); - if (rc) { - IPW_ERROR("Tx 3 queue init failed\n"); - goto error; - } - /* statistics */ - priv->rx_bufs_min = 0; - priv->rx_pend_max = 0; - return rc; - - error: - ipw_tx_queue_free(priv); - return rc; -} - -/** - * Reclaim Tx queue entries no more used by NIC. - * - * When FW advances 'R' index, all entries between old and - * new 'R' index need to be reclaimed. As result, some free space - * forms. If there is enough free space (> low mark), wake Tx queue. - * - * @note Need to protect against garbage in 'R' index - * @param priv - * @param txq - * @param qindex - * @return Number of used entries remains in the queue - */ -static int ipw_queue_tx_reclaim(struct ipw_priv *priv, - struct clx2_tx_queue *txq, int qindex) -{ - u32 hw_tail; - int used; - struct clx2_queue *q = &txq->q; - - hw_tail = ipw_read32(priv, q->reg_r); - if (hw_tail >= q->n_bd) { - IPW_ERROR - ("Read index for DMA queue (%d) is out of range [0-%d)\n", - hw_tail, q->n_bd); - goto done; - } - for (; q->last_used != hw_tail; - q->last_used = ipw_queue_inc_wrap(q->last_used, q->n_bd)) { - ipw_queue_tx_free_tfd(priv, txq); - priv->tx_packets++; - } - done: - if ((ipw_tx_queue_space(q) > q->low_mark) && - (qindex >= 0)) - netif_wake_queue(priv->net_dev); - used = q->first_empty - q->last_used; - if (used < 0) - used += q->n_bd; - - return used; -} - -static int ipw_queue_tx_hcmd(struct ipw_priv *priv, int hcmd, void *buf, - int len, int sync) -{ - struct clx2_tx_queue *txq = &priv->txq_cmd; - struct clx2_queue *q = &txq->q; - struct tfd_frame *tfd; - - if (ipw_tx_queue_space(q) < (sync ? 1 : 2)) { - IPW_ERROR("No space for Tx\n"); - return -EBUSY; - } - - tfd = &txq->bd[q->first_empty]; - txq->txb[q->first_empty] = NULL; - - memset(tfd, 0, sizeof(*tfd)); - tfd->control_flags.message_type = TX_HOST_COMMAND_TYPE; - tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK; - priv->hcmd_seq++; - tfd->u.cmd.index = hcmd; - tfd->u.cmd.length = len; - memcpy(tfd->u.cmd.payload, buf, len); - q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); - ipw_write32(priv, q->reg_w, q->first_empty); - _ipw_read32(priv, 0x90); - - return 0; -} - -/* - * Rx theory of operation - * - * The host allocates 32 DMA target addresses and passes the host address - * to the firmware at register IPW_RFDS_TABLE_LOWER + N * RFD_SIZE where N is - * 0 to 31 - * - * Rx Queue Indexes - * The host/firmware share two index registers for managing the Rx buffers. - * - * The READ index maps to the first position that the firmware may be writing - * to -- the driver can read up to (but not including) this position and get - * good data. - * The READ index is managed by the firmware once the card is enabled. - * - * The WRITE index maps to the last position the driver has read from -- the - * position preceding WRITE is the last slot the firmware can place a packet. - * - * The queue is empty (no good data) if WRITE = READ - 1, and is full if - * WRITE = READ. - * - * During initialization the host sets up the READ queue position to the first - * INDEX position, and WRITE to the last (READ - 1 wrapped) - * - * When the firmware places a packet in a buffer it will advance the READ index - * and fire the RX interrupt. The driver can then query the READ index and - * process as many packets as possible, moving the WRITE index forward as it - * resets the Rx queue buffers with new memory. - * - * The management in the driver is as follows: - * + A list of pre-allocated SKBs is stored in ipw->rxq->rx_free. When - * ipw->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled - * to replensish the ipw->rxq->rx_free. - * + In ipw_rx_queue_replenish (scheduled) if 'processed' != 'read' then the - * ipw->rxq is replenished and the READ INDEX is updated (updating the - * 'processed' and 'read' driver indexes as well) - * + A received packet is processed and handed to the kernel network stack, - * detached from the ipw->rxq. The driver 'processed' index is updated. - * + The Host/Firmware ipw->rxq is replenished at tasklet time from the rx_free - * list. If there are no allocated buffers in ipw->rxq->rx_free, the READ - * INDEX is not incremented and ipw->status(RX_STALLED) is set. If there - * were enough free buffers and RX_STALLED is set it is cleared. - * - * - * Driver sequence: - * - * ipw_rx_queue_alloc() Allocates rx_free - * ipw_rx_queue_replenish() Replenishes rx_free list from rx_used, and calls - * ipw_rx_queue_restock - * ipw_rx_queue_restock() Moves available buffers from rx_free into Rx - * queue, updates firmware pointers, and updates - * the WRITE index. If insufficient rx_free buffers - * are available, schedules ipw_rx_queue_replenish - * - * -- enable interrupts -- - * ISR - ipw_rx() Detach ipw_rx_mem_buffers from pool up to the - * READ INDEX, detaching the SKB from the pool. - * Moves the packet buffer from queue to rx_used. - * Calls ipw_rx_queue_restock to refill any empty - * slots. - * ... - * - */ - -/* - * If there are slots in the RX queue that need to be restocked, - * and we have free pre-allocated buffers, fill the ranks as much - * as we can pulling from rx_free. - * - * This moves the 'write' index forward to catch up with 'processed', and - * also updates the memory address in the firmware to reference the new - * target buffer. - */ -static void ipw_rx_queue_restock(struct ipw_priv *priv) -{ - struct ipw_rx_queue *rxq = priv->rxq; - struct list_head *element; - struct ipw_rx_mem_buffer *rxb; - unsigned long flags; - int write; - - spin_lock_irqsave(&rxq->lock, flags); - write = rxq->write; - while ((ipw_rx_queue_space(rxq) > 0) && (rxq->free_count)) { - element = rxq->rx_free.next; - rxb = list_entry(element, struct ipw_rx_mem_buffer, list); - list_del(element); - - ipw_write32(priv, IPW_RFDS_TABLE_LOWER + rxq->write * RFD_SIZE, - rxb->dma_addr); - rxq->queue[rxq->write] = rxb; - rxq->write = (rxq->write + 1) % RX_QUEUE_SIZE; - rxq->free_count--; - } - spin_unlock_irqrestore(&rxq->lock, flags); - - /* If the pre-allocated buffer pool is dropping low, schedule to - * refill it */ - if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->workqueue, &priv->rx_replenish); - - /* If we've added more space for the firmware to place data, tell it */ - if (write != rxq->write) - ipw_write32(priv, IPW_RX_WRITE_INDEX, rxq->write); -} - -/* - * Move all used packet from rx_used to rx_free, allocating a new SKB for each. - * Also restock the Rx queue via ipw_rx_queue_restock. - * - * This is called as a scheduled work item (except for during intialization) - */ -static void ipw_rx_queue_replenish(void *data) -{ - struct ipw_priv *priv = data; - struct ipw_rx_queue *rxq = priv->rxq; - struct list_head *element; - struct ipw_rx_mem_buffer *rxb; - unsigned long flags; - - spin_lock_irqsave(&rxq->lock, flags); - while (!list_empty(&rxq->rx_used)) { - element = rxq->rx_used.next; - rxb = list_entry(element, struct ipw_rx_mem_buffer, list); - rxb->skb = alloc_skb(IPW_RX_BUF_SIZE, GFP_ATOMIC); - if (!rxb->skb) { - printk(KERN_CRIT "%s: Can not allocate SKB buffers.\n", - priv->net_dev->name); - /* We don't reschedule replenish work here -- we will - * call the restock method and if it still needs - * more buffers it will schedule replenish */ - break; - } - list_del(element); - - rxb->dma_addr = - pci_map_single(priv->pci_dev, rxb->skb->data, - IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - } - spin_unlock_irqrestore(&rxq->lock, flags); - - ipw_rx_queue_restock(priv); -} - -static void ipw_bg_rx_queue_replenish(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, rx_replenish); - mutex_lock(&priv->mutex); - ipw_rx_queue_replenish(priv); - mutex_unlock(&priv->mutex); -} - -/* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have its SKB set to NULL - * This free routine walks the list of POOL entries and if SKB is set to - * non NULL it is unmapped and freed - */ -static void ipw_rx_queue_free(struct ipw_priv *priv, struct ipw_rx_queue *rxq) -{ - int i; - - if (!rxq) - return; - - for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, rxq->pool[i].dma_addr, - IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - dev_kfree_skb(rxq->pool[i].skb); - } - } - - kfree(rxq); -} - -static struct ipw_rx_queue *ipw_rx_queue_alloc(struct ipw_priv *priv) -{ - struct ipw_rx_queue *rxq; - int i; - - rxq = kzalloc(sizeof(*rxq), GFP_KERNEL); - if (unlikely(!rxq)) { - IPW_ERROR("memory allocation failed\n"); - return NULL; - } - spin_lock_init(&rxq->lock); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->free_count = 0; - - return rxq; -} - -static int ipw_is_rate_in_mask(struct ipw_priv *priv, int ieee_mode, u8 rate) -{ - rate &= ~LIBIPW_BASIC_RATE_MASK; - if (ieee_mode == IEEE_A) { - switch (rate) { - case LIBIPW_OFDM_RATE_6MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_6MB_MASK ? - 1 : 0; - case LIBIPW_OFDM_RATE_9MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_9MB_MASK ? - 1 : 0; - case LIBIPW_OFDM_RATE_12MB: - return priv-> - rates_mask & LIBIPW_OFDM_RATE_12MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_18MB: - return priv-> - rates_mask & LIBIPW_OFDM_RATE_18MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_24MB: - return priv-> - rates_mask & LIBIPW_OFDM_RATE_24MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_36MB: - return priv-> - rates_mask & LIBIPW_OFDM_RATE_36MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_48MB: - return priv-> - rates_mask & LIBIPW_OFDM_RATE_48MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_54MB: - return priv-> - rates_mask & LIBIPW_OFDM_RATE_54MB_MASK ? 1 : 0; - default: - return 0; - } - } - - /* B and G mixed */ - switch (rate) { - case LIBIPW_CCK_RATE_1MB: - return priv->rates_mask & LIBIPW_CCK_RATE_1MB_MASK ? 1 : 0; - case LIBIPW_CCK_RATE_2MB: - return priv->rates_mask & LIBIPW_CCK_RATE_2MB_MASK ? 1 : 0; - case LIBIPW_CCK_RATE_5MB: - return priv->rates_mask & LIBIPW_CCK_RATE_5MB_MASK ? 1 : 0; - case LIBIPW_CCK_RATE_11MB: - return priv->rates_mask & LIBIPW_CCK_RATE_11MB_MASK ? 1 : 0; - } - - /* If we are limited to B modulations, bail at this point */ - if (ieee_mode == IEEE_B) - return 0; - - /* G */ - switch (rate) { - case LIBIPW_OFDM_RATE_6MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_6MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_9MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_9MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_12MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_12MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_18MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_18MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_24MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_24MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_36MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_36MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_48MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_48MB_MASK ? 1 : 0; - case LIBIPW_OFDM_RATE_54MB: - return priv->rates_mask & LIBIPW_OFDM_RATE_54MB_MASK ? 1 : 0; - } - - return 0; -} - -static int ipw_compatible_rates(struct ipw_priv *priv, - const struct libipw_network *network, - struct ipw_supported_rates *rates) -{ - int num_rates, i; - - memset(rates, 0, sizeof(*rates)); - num_rates = min(network->rates_len, (u8) IPW_MAX_RATES); - rates->num_rates = 0; - for (i = 0; i < num_rates; i++) { - if (!ipw_is_rate_in_mask(priv, network->mode, - network->rates[i])) { - - if (network->rates[i] & LIBIPW_BASIC_RATE_MASK) { - IPW_DEBUG_SCAN("Adding masked mandatory " - "rate %02X\n", - network->rates[i]); - rates->supported_rates[rates->num_rates++] = - network->rates[i]; - continue; - } - - IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", - network->rates[i], priv->rates_mask); - continue; - } - - rates->supported_rates[rates->num_rates++] = network->rates[i]; - } - - num_rates = min(network->rates_ex_len, - (u8) (IPW_MAX_RATES - num_rates)); - for (i = 0; i < num_rates; i++) { - if (!ipw_is_rate_in_mask(priv, network->mode, - network->rates_ex[i])) { - if (network->rates_ex[i] & LIBIPW_BASIC_RATE_MASK) { - IPW_DEBUG_SCAN("Adding masked mandatory " - "rate %02X\n", - network->rates_ex[i]); - rates->supported_rates[rates->num_rates++] = - network->rates[i]; - continue; - } - - IPW_DEBUG_SCAN("Rate %02X masked : 0x%08X\n", - network->rates_ex[i], priv->rates_mask); - continue; - } - - rates->supported_rates[rates->num_rates++] = - network->rates_ex[i]; - } - - return 1; -} - -static void ipw_copy_rates(struct ipw_supported_rates *dest, - const struct ipw_supported_rates *src) -{ - u8 i; - for (i = 0; i < src->num_rates; i++) - dest->supported_rates[i] = src->supported_rates[i]; - dest->num_rates = src->num_rates; -} - -/* TODO: Look at sniffed packets in the air to determine if the basic rate - * mask should ever be used -- right now all callers to add the scan rates are - * set with the modulation = CCK, so BASIC_RATE_MASK is never set... */ -static void ipw_add_cck_scan_rates(struct ipw_supported_rates *rates, - u8 modulation, u32 rate_mask) -{ - u8 basic_mask = (LIBIPW_OFDM_MODULATION == modulation) ? - LIBIPW_BASIC_RATE_MASK : 0; - - if (rate_mask & LIBIPW_CCK_RATE_1MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_BASIC_RATE_MASK | LIBIPW_CCK_RATE_1MB; - - if (rate_mask & LIBIPW_CCK_RATE_2MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_BASIC_RATE_MASK | LIBIPW_CCK_RATE_2MB; - - if (rate_mask & LIBIPW_CCK_RATE_5MB_MASK) - rates->supported_rates[rates->num_rates++] = basic_mask | - LIBIPW_CCK_RATE_5MB; - - if (rate_mask & LIBIPW_CCK_RATE_11MB_MASK) - rates->supported_rates[rates->num_rates++] = basic_mask | - LIBIPW_CCK_RATE_11MB; -} - -static void ipw_add_ofdm_scan_rates(struct ipw_supported_rates *rates, - u8 modulation, u32 rate_mask) -{ - u8 basic_mask = (LIBIPW_OFDM_MODULATION == modulation) ? - LIBIPW_BASIC_RATE_MASK : 0; - - if (rate_mask & LIBIPW_OFDM_RATE_6MB_MASK) - rates->supported_rates[rates->num_rates++] = basic_mask | - LIBIPW_OFDM_RATE_6MB; - - if (rate_mask & LIBIPW_OFDM_RATE_9MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_OFDM_RATE_9MB; - - if (rate_mask & LIBIPW_OFDM_RATE_12MB_MASK) - rates->supported_rates[rates->num_rates++] = basic_mask | - LIBIPW_OFDM_RATE_12MB; - - if (rate_mask & LIBIPW_OFDM_RATE_18MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_OFDM_RATE_18MB; - - if (rate_mask & LIBIPW_OFDM_RATE_24MB_MASK) - rates->supported_rates[rates->num_rates++] = basic_mask | - LIBIPW_OFDM_RATE_24MB; - - if (rate_mask & LIBIPW_OFDM_RATE_36MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_OFDM_RATE_36MB; - - if (rate_mask & LIBIPW_OFDM_RATE_48MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_OFDM_RATE_48MB; - - if (rate_mask & LIBIPW_OFDM_RATE_54MB_MASK) - rates->supported_rates[rates->num_rates++] = - LIBIPW_OFDM_RATE_54MB; -} - -struct ipw_network_match { - struct libipw_network *network; - struct ipw_supported_rates rates; -}; - -static int ipw_find_adhoc_network(struct ipw_priv *priv, - struct ipw_network_match *match, - struct libipw_network *network, - int roaming) -{ - struct ipw_supported_rates rates; - DECLARE_SSID_BUF(ssid); - - /* Verify that this network's capability is compatible with the - * current mode (AdHoc or Infrastructure) */ - if ((priv->ieee->iw_mode == IW_MODE_ADHOC && - !(network->capability & WLAN_CAPABILITY_IBSS))) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to " - "capability mismatch.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - if (unlikely(roaming)) { - /* If we are roaming, then ensure check if this is a valid - * network to try and roam to */ - if ((network->ssid_len != match->network->ssid_len) || - memcmp(network->ssid, match->network->ssid, - network->ssid_len)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of non-network ESSID.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - } else { - /* If an ESSID has been configured then compare the broadcast - * ESSID to ours */ - if ((priv->config & CFG_STATIC_ESSID) && - ((network->ssid_len != priv->essid_len) || - memcmp(network->ssid, priv->essid, - min(network->ssid_len, priv->essid_len)))) { - char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - - strncpy(escaped, - print_ssid(ssid, network->ssid, - network->ssid_len), - sizeof(escaped)); - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of ESSID mismatch: '%s'.\n", - escaped, network->bssid, - print_ssid(ssid, priv->essid, - priv->essid_len)); - return 0; - } - } - - /* If the old network rate is better than this one, don't bother - * testing everything else. */ - - if (network->time_stamp[0] < match->network->time_stamp[0]) { - IPW_DEBUG_MERGE("Network '%s excluded because newer than " - "current network.\n", - print_ssid(ssid, match->network->ssid, - match->network->ssid_len)); - return 0; - } else if (network->time_stamp[1] < match->network->time_stamp[1]) { - IPW_DEBUG_MERGE("Network '%s excluded because newer than " - "current network.\n", - print_ssid(ssid, match->network->ssid, - match->network->ssid_len)); - return 0; - } - - /* Now go through and see if the requested network is valid... */ - if (priv->ieee->scan_age != 0 && - time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of age: %ums.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - jiffies_to_msecs(jiffies - - network->last_scanned)); - return 0; - } - - if ((priv->config & CFG_STATIC_CHANNEL) && - (network->channel != priv->channel)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of channel mismatch: %d != %d.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - network->channel, priv->channel); - return 0; - } - - /* Verify privacy compatability */ - if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != - ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of privacy mismatch: %s != %s.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - priv-> - capability & CAP_PRIVACY_ON ? "on" : "off", - network-> - capability & WLAN_CAPABILITY_PRIVACY ? "on" : - "off"); - return 0; - } - - if (!memcmp(network->bssid, priv->bssid, ETH_ALEN)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of the same BSSID match: %pM" - ".\n", print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - priv->bssid); - return 0; - } - - /* Filter out any incompatible freq / mode combinations */ - if (!libipw_is_valid_mode(priv->ieee, network->mode)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of invalid frequency/mode " - "combination.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - /* Ensure that the rates supported by the driver are compatible with - * this AP, including verification of basic rates (mandatory) */ - if (!ipw_compatible_rates(priv, network, &rates)) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because configured rate mask excludes " - "AP mandatory rate.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - if (rates.num_rates == 0) { - IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " - "because of no compatible rates.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - /* TODO: Perform any further minimal comparititive tests. We do not - * want to put too much policy logic here; intelligent scan selection - * should occur within a generic IEEE 802.11 user space tool. */ - - /* Set up 'new' AP to this network */ - ipw_copy_rates(&match->rates, &rates); - match->network = network; - IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n", - print_ssid(ssid, network->ssid, network->ssid_len), - network->bssid); - - return 1; -} - -static void ipw_merge_adhoc_network(struct work_struct *work) -{ - DECLARE_SSID_BUF(ssid); - struct ipw_priv *priv = - container_of(work, struct ipw_priv, merge_networks); - struct libipw_network *network = NULL; - struct ipw_network_match match = { - .network = priv->assoc_network - }; - - if ((priv->status & STATUS_ASSOCIATED) && - (priv->ieee->iw_mode == IW_MODE_ADHOC)) { - /* First pass through ROAM process -- look for a better - * network */ - unsigned long flags; - - spin_lock_irqsave(&priv->ieee->lock, flags); - list_for_each_entry(network, &priv->ieee->network_list, list) { - if (network != priv->assoc_network) - ipw_find_adhoc_network(priv, &match, network, - 1); - } - spin_unlock_irqrestore(&priv->ieee->lock, flags); - - if (match.network == priv->assoc_network) { - IPW_DEBUG_MERGE("No better ADHOC in this network to " - "merge to.\n"); - return; - } - - mutex_lock(&priv->mutex); - if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { - IPW_DEBUG_MERGE("remove network %s\n", - print_ssid(ssid, priv->essid, - priv->essid_len)); - ipw_remove_current_network(priv); - } - - ipw_disassociate(priv); - priv->assoc_network = match.network; - mutex_unlock(&priv->mutex); - return; - } -} - -static int ipw_best_network(struct ipw_priv *priv, - struct ipw_network_match *match, - struct libipw_network *network, int roaming) -{ - struct ipw_supported_rates rates; - DECLARE_SSID_BUF(ssid); - - /* Verify that this network's capability is compatible with the - * current mode (AdHoc or Infrastructure) */ - if ((priv->ieee->iw_mode == IW_MODE_INFRA && - !(network->capability & WLAN_CAPABILITY_ESS)) || - (priv->ieee->iw_mode == IW_MODE_ADHOC && - !(network->capability & WLAN_CAPABILITY_IBSS))) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to " - "capability mismatch.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - if (unlikely(roaming)) { - /* If we are roaming, then ensure check if this is a valid - * network to try and roam to */ - if ((network->ssid_len != match->network->ssid_len) || - memcmp(network->ssid, match->network->ssid, - network->ssid_len)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of non-network ESSID.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - } else { - /* If an ESSID has been configured then compare the broadcast - * ESSID to ours */ - if ((priv->config & CFG_STATIC_ESSID) && - ((network->ssid_len != priv->essid_len) || - memcmp(network->ssid, priv->essid, - min(network->ssid_len, priv->essid_len)))) { - char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - strncpy(escaped, - print_ssid(ssid, network->ssid, - network->ssid_len), - sizeof(escaped)); - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of ESSID mismatch: '%s'.\n", - escaped, network->bssid, - print_ssid(ssid, priv->essid, - priv->essid_len)); - return 0; - } - } - - /* If the old network rate is better than this one, don't bother - * testing everything else. */ - if (match->network && match->network->stats.rssi > network->stats.rssi) { - char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; - strncpy(escaped, - print_ssid(ssid, network->ssid, network->ssid_len), - sizeof(escaped)); - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because " - "'%s (%pM)' has a stronger signal.\n", - escaped, network->bssid, - print_ssid(ssid, match->network->ssid, - match->network->ssid_len), - match->network->bssid); - return 0; - } - - /* If this network has already had an association attempt within the - * last 3 seconds, do not try and associate again... */ - if (network->last_associate && - time_after(network->last_associate + (HZ * 3UL), jiffies)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of storming (%ums since last " - "assoc attempt).\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - jiffies_to_msecs(jiffies - - network->last_associate)); - return 0; - } - - /* Now go through and see if the requested network is valid... */ - if (priv->ieee->scan_age != 0 && - time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of age: %ums.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - jiffies_to_msecs(jiffies - - network->last_scanned)); - return 0; - } - - if ((priv->config & CFG_STATIC_CHANNEL) && - (network->channel != priv->channel)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of channel mismatch: %d != %d.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - network->channel, priv->channel); - return 0; - } - - /* Verify privacy compatability */ - if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != - ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of privacy mismatch: %s != %s.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - priv->capability & CAP_PRIVACY_ON ? "on" : - "off", - network->capability & - WLAN_CAPABILITY_PRIVACY ? "on" : "off"); - return 0; - } - - if ((priv->config & CFG_STATIC_BSSID) && - memcmp(network->bssid, priv->bssid, ETH_ALEN)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of BSSID mismatch: %pM.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, priv->bssid); - return 0; - } - - /* Filter out any incompatible freq / mode combinations */ - if (!libipw_is_valid_mode(priv->ieee, network->mode)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of invalid frequency/mode " - "combination.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - /* Filter out invalid channel in current GEO */ - if (!libipw_is_valid_channel(priv->ieee, network->channel)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of invalid channel in current GEO\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - /* Ensure that the rates supported by the driver are compatible with - * this AP, including verification of basic rates (mandatory) */ - if (!ipw_compatible_rates(priv, network, &rates)) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because configured rate mask excludes " - "AP mandatory rate.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - if (rates.num_rates == 0) { - IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " - "because of no compatible rates.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 0; - } - - /* TODO: Perform any further minimal comparititive tests. We do not - * want to put too much policy logic here; intelligent scan selection - * should occur within a generic IEEE 802.11 user space tool. */ - - /* Set up 'new' AP to this network */ - ipw_copy_rates(&match->rates, &rates); - match->network = network; - - IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n", - print_ssid(ssid, network->ssid, network->ssid_len), - network->bssid); - - return 1; -} - -static void ipw_adhoc_create(struct ipw_priv *priv, - struct libipw_network *network) -{ - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - int i; - - /* - * For the purposes of scanning, we can set our wireless mode - * to trigger scans across combinations of bands, but when it - * comes to creating a new ad-hoc network, we have tell the FW - * exactly which band to use. - * - * We also have the possibility of an invalid channel for the - * chossen band. Attempting to create a new ad-hoc network - * with an invalid channel for wireless mode will trigger a - * FW fatal error. - * - */ - switch (libipw_is_valid_channel(priv->ieee, priv->channel)) { - case LIBIPW_52GHZ_BAND: - network->mode = IEEE_A; - i = libipw_channel_to_index(priv->ieee, priv->channel); - BUG_ON(i == -1); - if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY) { - IPW_WARNING("Overriding invalid channel\n"); - priv->channel = geo->a[0].channel; - } - break; - - case LIBIPW_24GHZ_BAND: - if (priv->ieee->mode & IEEE_G) - network->mode = IEEE_G; - else - network->mode = IEEE_B; - i = libipw_channel_to_index(priv->ieee, priv->channel); - BUG_ON(i == -1); - if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY) { - IPW_WARNING("Overriding invalid channel\n"); - priv->channel = geo->bg[0].channel; - } - break; - - default: - IPW_WARNING("Overriding invalid channel\n"); - if (priv->ieee->mode & IEEE_A) { - network->mode = IEEE_A; - priv->channel = geo->a[0].channel; - } else if (priv->ieee->mode & IEEE_G) { - network->mode = IEEE_G; - priv->channel = geo->bg[0].channel; - } else { - network->mode = IEEE_B; - priv->channel = geo->bg[0].channel; - } - break; - } - - network->channel = priv->channel; - priv->config |= CFG_ADHOC_PERSIST; - ipw_create_bssid(priv, network->bssid); - network->ssid_len = priv->essid_len; - memcpy(network->ssid, priv->essid, priv->essid_len); - memset(&network->stats, 0, sizeof(network->stats)); - network->capability = WLAN_CAPABILITY_IBSS; - if (!(priv->config & CFG_PREAMBLE_LONG)) - network->capability |= WLAN_CAPABILITY_SHORT_PREAMBLE; - if (priv->capability & CAP_PRIVACY_ON) - network->capability |= WLAN_CAPABILITY_PRIVACY; - network->rates_len = min(priv->rates.num_rates, MAX_RATES_LENGTH); - memcpy(network->rates, priv->rates.supported_rates, network->rates_len); - network->rates_ex_len = priv->rates.num_rates - network->rates_len; - memcpy(network->rates_ex, - &priv->rates.supported_rates[network->rates_len], - network->rates_ex_len); - network->last_scanned = 0; - network->flags = 0; - network->last_associate = 0; - network->time_stamp[0] = 0; - network->time_stamp[1] = 0; - network->beacon_interval = 100; /* Default */ - network->listen_interval = 10; /* Default */ - network->atim_window = 0; /* Default */ - network->wpa_ie_len = 0; - network->rsn_ie_len = 0; -} - -static void ipw_send_tgi_tx_key(struct ipw_priv *priv, int type, int index) -{ - struct ipw_tgi_tx_key key; - - if (!(priv->ieee->sec.flags & (1 << index))) - return; - - key.key_id = index; - memcpy(key.key, priv->ieee->sec.keys[index], SCM_TEMPORAL_KEY_LENGTH); - key.security_type = type; - key.station_index = 0; /* always 0 for BSS */ - key.flags = 0; - /* 0 for new key; previous value of counter (after fatal error) */ - key.tx_counter[0] = cpu_to_le32(0); - key.tx_counter[1] = cpu_to_le32(0); - - ipw_send_cmd_pdu(priv, IPW_CMD_TGI_TX_KEY, sizeof(key), &key); -} - -static void ipw_send_wep_keys(struct ipw_priv *priv, int type) -{ - struct ipw_wep_key key; - int i; - - key.cmd_id = DINO_CMD_WEP_KEY; - key.seq_num = 0; - - /* Note: AES keys cannot be set for multiple times. - * Only set it at the first time. */ - for (i = 0; i < 4; i++) { - key.key_index = i | type; - if (!(priv->ieee->sec.flags & (1 << i))) { - key.key_size = 0; - continue; - } - - key.key_size = priv->ieee->sec.key_sizes[i]; - memcpy(key.key, priv->ieee->sec.keys[i], key.key_size); - - ipw_send_cmd_pdu(priv, IPW_CMD_WEP_KEY, sizeof(key), &key); - } -} - -static void ipw_set_hw_decrypt_unicast(struct ipw_priv *priv, int level) -{ - if (priv->ieee->host_encrypt) - return; - - switch (level) { - case SEC_LEVEL_3: - priv->sys_config.disable_unicast_decryption = 0; - priv->ieee->host_decrypt = 0; - break; - case SEC_LEVEL_2: - priv->sys_config.disable_unicast_decryption = 1; - priv->ieee->host_decrypt = 1; - break; - case SEC_LEVEL_1: - priv->sys_config.disable_unicast_decryption = 0; - priv->ieee->host_decrypt = 0; - break; - case SEC_LEVEL_0: - priv->sys_config.disable_unicast_decryption = 1; - break; - default: - break; - } -} - -static void ipw_set_hw_decrypt_multicast(struct ipw_priv *priv, int level) -{ - if (priv->ieee->host_encrypt) - return; - - switch (level) { - case SEC_LEVEL_3: - priv->sys_config.disable_multicast_decryption = 0; - break; - case SEC_LEVEL_2: - priv->sys_config.disable_multicast_decryption = 1; - break; - case SEC_LEVEL_1: - priv->sys_config.disable_multicast_decryption = 0; - break; - case SEC_LEVEL_0: - priv->sys_config.disable_multicast_decryption = 1; - break; - default: - break; - } -} - -static void ipw_set_hwcrypto_keys(struct ipw_priv *priv) -{ - switch (priv->ieee->sec.level) { - case SEC_LEVEL_3: - if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) - ipw_send_tgi_tx_key(priv, - DCT_FLAG_EXT_SECURITY_CCM, - priv->ieee->sec.active_key); - - if (!priv->ieee->host_mc_decrypt) - ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_CCM); - break; - case SEC_LEVEL_2: - if (priv->ieee->sec.flags & SEC_ACTIVE_KEY) - ipw_send_tgi_tx_key(priv, - DCT_FLAG_EXT_SECURITY_TKIP, - priv->ieee->sec.active_key); - break; - case SEC_LEVEL_1: - ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); - ipw_set_hw_decrypt_unicast(priv, priv->ieee->sec.level); - ipw_set_hw_decrypt_multicast(priv, priv->ieee->sec.level); - break; - case SEC_LEVEL_0: - default: - break; - } -} - -static void ipw_adhoc_check(void *data) -{ - struct ipw_priv *priv = data; - - if (priv->missed_adhoc_beacons++ > priv->disassociate_threshold && - !(priv->config & CFG_ADHOC_PERSIST)) { - IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | - IPW_DL_STATE | IPW_DL_ASSOC, - "Missed beacon: %d - disassociate\n", - priv->missed_adhoc_beacons); - ipw_remove_current_network(priv); - ipw_disassociate(priv); - return; - } - - queue_delayed_work(priv->workqueue, &priv->adhoc_check, - le16_to_cpu(priv->assoc_request.beacon_interval)); -} - -static void ipw_bg_adhoc_check(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, adhoc_check.work); - mutex_lock(&priv->mutex); - ipw_adhoc_check(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_debug_config(struct ipw_priv *priv) -{ - DECLARE_SSID_BUF(ssid); - IPW_DEBUG_INFO("Scan completed, no valid APs matched " - "[CFG 0x%08X]\n", priv->config); - if (priv->config & CFG_STATIC_CHANNEL) - IPW_DEBUG_INFO("Channel locked to %d\n", priv->channel); - else - IPW_DEBUG_INFO("Channel unlocked.\n"); - if (priv->config & CFG_STATIC_ESSID) - IPW_DEBUG_INFO("ESSID locked to '%s'\n", - print_ssid(ssid, priv->essid, priv->essid_len)); - else - IPW_DEBUG_INFO("ESSID unlocked.\n"); - if (priv->config & CFG_STATIC_BSSID) - IPW_DEBUG_INFO("BSSID locked to %pM\n", priv->bssid); - else - IPW_DEBUG_INFO("BSSID unlocked.\n"); - if (priv->capability & CAP_PRIVACY_ON) - IPW_DEBUG_INFO("PRIVACY on\n"); - else - IPW_DEBUG_INFO("PRIVACY off\n"); - IPW_DEBUG_INFO("RATE MASK: 0x%08X\n", priv->rates_mask); -} - -static void ipw_set_fixed_rate(struct ipw_priv *priv, int mode) -{ - /* TODO: Verify that this works... */ - struct ipw_fixed_rate fr; - u32 reg; - u16 mask = 0; - u16 new_tx_rates = priv->rates_mask; - - /* Identify 'current FW band' and match it with the fixed - * Tx rates */ - - switch (priv->ieee->freq_band) { - case LIBIPW_52GHZ_BAND: /* A only */ - /* IEEE_A */ - if (priv->rates_mask & ~LIBIPW_OFDM_RATES_MASK) { - /* Invalid fixed rate mask */ - IPW_DEBUG_WX - ("invalid fixed rate mask in ipw_set_fixed_rate\n"); - new_tx_rates = 0; - break; - } - - new_tx_rates >>= LIBIPW_OFDM_SHIFT_MASK_A; - break; - - default: /* 2.4Ghz or Mixed */ - /* IEEE_B */ - if (mode == IEEE_B) { - if (new_tx_rates & ~LIBIPW_CCK_RATES_MASK) { - /* Invalid fixed rate mask */ - IPW_DEBUG_WX - ("invalid fixed rate mask in ipw_set_fixed_rate\n"); - new_tx_rates = 0; - } - break; - } - - /* IEEE_G */ - if (new_tx_rates & ~(LIBIPW_CCK_RATES_MASK | - LIBIPW_OFDM_RATES_MASK)) { - /* Invalid fixed rate mask */ - IPW_DEBUG_WX - ("invalid fixed rate mask in ipw_set_fixed_rate\n"); - new_tx_rates = 0; - break; - } - - if (LIBIPW_OFDM_RATE_6MB_MASK & new_tx_rates) { - mask |= (LIBIPW_OFDM_RATE_6MB_MASK >> 1); - new_tx_rates &= ~LIBIPW_OFDM_RATE_6MB_MASK; - } - - if (LIBIPW_OFDM_RATE_9MB_MASK & new_tx_rates) { - mask |= (LIBIPW_OFDM_RATE_9MB_MASK >> 1); - new_tx_rates &= ~LIBIPW_OFDM_RATE_9MB_MASK; - } - - if (LIBIPW_OFDM_RATE_12MB_MASK & new_tx_rates) { - mask |= (LIBIPW_OFDM_RATE_12MB_MASK >> 1); - new_tx_rates &= ~LIBIPW_OFDM_RATE_12MB_MASK; - } - - new_tx_rates |= mask; - break; - } - - fr.tx_rates = cpu_to_le16(new_tx_rates); - - reg = ipw_read32(priv, IPW_MEM_FIXED_OVERRIDE); - ipw_write_reg32(priv, reg, *(u32 *) & fr); -} - -static void ipw_abort_scan(struct ipw_priv *priv) -{ - int err; - - if (priv->status & STATUS_SCAN_ABORTING) { - IPW_DEBUG_HC("Ignoring concurrent scan abort request.\n"); - return; - } - priv->status |= STATUS_SCAN_ABORTING; - - err = ipw_send_scan_abort(priv); - if (err) - IPW_DEBUG_HC("Request to abort scan failed.\n"); -} - -static void ipw_add_scan_channels(struct ipw_priv *priv, - struct ipw_scan_request_ext *scan, - int scan_type) -{ - int channel_index = 0; - const struct libipw_geo *geo; - int i; - - geo = libipw_get_geo(priv->ieee); - - if (priv->ieee->freq_band & LIBIPW_52GHZ_BAND) { - int start = channel_index; - for (i = 0; i < geo->a_channels; i++) { - if ((priv->status & STATUS_ASSOCIATED) && - geo->a[i].channel == priv->channel) - continue; - channel_index++; - scan->channels_list[channel_index] = geo->a[i].channel; - ipw_set_scan_type(scan, channel_index, - geo->a[i]. - flags & LIBIPW_CH_PASSIVE_ONLY ? - IPW_SCAN_PASSIVE_FULL_DWELL_SCAN : - scan_type); - } - - if (start != channel_index) { - scan->channels_list[start] = (u8) (IPW_A_MODE << 6) | - (channel_index - start); - channel_index++; - } - } - - if (priv->ieee->freq_band & LIBIPW_24GHZ_BAND) { - int start = channel_index; - if (priv->config & CFG_SPEED_SCAN) { - int index; - u8 channels[LIBIPW_24GHZ_CHANNELS] = { - /* nop out the list */ - [0] = 0 - }; - - u8 channel; - while (channel_index < IPW_SCAN_CHANNELS - 1) { - channel = - priv->speed_scan[priv->speed_scan_pos]; - if (channel == 0) { - priv->speed_scan_pos = 0; - channel = priv->speed_scan[0]; - } - if ((priv->status & STATUS_ASSOCIATED) && - channel == priv->channel) { - priv->speed_scan_pos++; - continue; - } - - /* If this channel has already been - * added in scan, break from loop - * and this will be the first channel - * in the next scan. - */ - if (channels[channel - 1] != 0) - break; - - channels[channel - 1] = 1; - priv->speed_scan_pos++; - channel_index++; - scan->channels_list[channel_index] = channel; - index = - libipw_channel_to_index(priv->ieee, channel); - ipw_set_scan_type(scan, channel_index, - geo->bg[index]. - flags & - LIBIPW_CH_PASSIVE_ONLY ? - IPW_SCAN_PASSIVE_FULL_DWELL_SCAN - : scan_type); - } - } else { - for (i = 0; i < geo->bg_channels; i++) { - if ((priv->status & STATUS_ASSOCIATED) && - geo->bg[i].channel == priv->channel) - continue; - channel_index++; - scan->channels_list[channel_index] = - geo->bg[i].channel; - ipw_set_scan_type(scan, channel_index, - geo->bg[i]. - flags & - LIBIPW_CH_PASSIVE_ONLY ? - IPW_SCAN_PASSIVE_FULL_DWELL_SCAN - : scan_type); - } - } - - if (start != channel_index) { - scan->channels_list[start] = (u8) (IPW_B_MODE << 6) | - (channel_index - start); - } - } -} - -static int ipw_passive_dwell_time(struct ipw_priv *priv) -{ - /* staying on passive channels longer than the DTIM interval during a - * scan, while associated, causes the firmware to cancel the scan - * without notification. Hence, don't stay on passive channels longer - * than the beacon interval. - */ - if (priv->status & STATUS_ASSOCIATED - && priv->assoc_network->beacon_interval > 10) - return priv->assoc_network->beacon_interval - 10; - else - return 120; -} - -static int ipw_request_scan_helper(struct ipw_priv *priv, int type, int direct) -{ - struct ipw_scan_request_ext scan; - int err = 0, scan_type; - - if (!(priv->status & STATUS_INIT) || - (priv->status & STATUS_EXIT_PENDING)) - return 0; - - mutex_lock(&priv->mutex); - - if (direct && (priv->direct_scan_ssid_len == 0)) { - IPW_DEBUG_HC("Direct scan requested but no SSID to scan for\n"); - priv->status &= ~STATUS_DIRECT_SCAN_PENDING; - goto done; - } - - if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_HC("Concurrent scan requested. Queuing.\n"); - priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : - STATUS_SCAN_PENDING; - goto done; - } - - if (!(priv->status & STATUS_SCAN_FORCED) && - priv->status & STATUS_SCAN_ABORTING) { - IPW_DEBUG_HC("Scan request while abort pending. Queuing.\n"); - priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : - STATUS_SCAN_PENDING; - goto done; - } - - if (priv->status & STATUS_RF_KILL_MASK) { - IPW_DEBUG_HC("Queuing scan due to RF Kill activation\n"); - priv->status |= direct ? STATUS_DIRECT_SCAN_PENDING : - STATUS_SCAN_PENDING; - goto done; - } - - memset(&scan, 0, sizeof(scan)); - scan.full_scan_index = cpu_to_le32(libipw_get_scans(priv->ieee)); - - if (type == IW_SCAN_TYPE_PASSIVE) { - IPW_DEBUG_WX("use passive scanning\n"); - scan_type = IPW_SCAN_PASSIVE_FULL_DWELL_SCAN; - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = - cpu_to_le16(ipw_passive_dwell_time(priv)); - ipw_add_scan_channels(priv, &scan, scan_type); - goto send_request; - } - - /* Use active scan by default. */ - if (priv->config & CFG_SPEED_SCAN) - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = - cpu_to_le16(30); - else - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_SCAN] = - cpu_to_le16(20); - - scan.dwell_time[IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN] = - cpu_to_le16(20); - - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = - cpu_to_le16(ipw_passive_dwell_time(priv)); - scan.dwell_time[IPW_SCAN_ACTIVE_DIRECT_SCAN] = cpu_to_le16(20); - -#ifdef CONFIG_IPW2200_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - u8 channel; - u8 band = 0; - - switch (libipw_is_valid_channel(priv->ieee, priv->channel)) { - case LIBIPW_52GHZ_BAND: - band = (u8) (IPW_A_MODE << 6) | 1; - channel = priv->channel; - break; - - case LIBIPW_24GHZ_BAND: - band = (u8) (IPW_B_MODE << 6) | 1; - channel = priv->channel; - break; - - default: - band = (u8) (IPW_B_MODE << 6) | 1; - channel = 9; - break; - } - - scan.channels_list[0] = band; - scan.channels_list[1] = channel; - ipw_set_scan_type(&scan, 1, IPW_SCAN_PASSIVE_FULL_DWELL_SCAN); - - /* NOTE: The card will sit on this channel for this time - * period. Scan aborts are timing sensitive and frequently - * result in firmware restarts. As such, it is best to - * set a small dwell_time here and just keep re-issuing - * scans. Otherwise fast channel hopping will not actually - * hop channels. - * - * TODO: Move SPEED SCAN support to all modes and bands */ - scan.dwell_time[IPW_SCAN_PASSIVE_FULL_DWELL_SCAN] = - cpu_to_le16(2000); - } else { -#endif /* CONFIG_IPW2200_MONITOR */ - /* Honor direct scans first, otherwise if we are roaming make - * this a direct scan for the current network. Finally, - * ensure that every other scan is a fast channel hop scan */ - if (direct) { - err = ipw_send_ssid(priv, priv->direct_scan_ssid, - priv->direct_scan_ssid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command " - "failed\n"); - goto done; - } - - scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; - } else if ((priv->status & STATUS_ROAMING) - || (!(priv->status & STATUS_ASSOCIATED) - && (priv->config & CFG_STATIC_ESSID) - && (le32_to_cpu(scan.full_scan_index) % 2))) { - err = ipw_send_ssid(priv, priv->essid, priv->essid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command " - "failed.\n"); - goto done; - } - - scan_type = IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN; - } else - scan_type = IPW_SCAN_ACTIVE_BROADCAST_SCAN; - - ipw_add_scan_channels(priv, &scan, scan_type); -#ifdef CONFIG_IPW2200_MONITOR - } -#endif - -send_request: - err = ipw_send_scan_request_ext(priv, &scan); - if (err) { - IPW_DEBUG_HC("Sending scan command failed: %08X\n", err); - goto done; - } - - priv->status |= STATUS_SCANNING; - if (direct) { - priv->status &= ~STATUS_DIRECT_SCAN_PENDING; - priv->direct_scan_ssid_len = 0; - } else - priv->status &= ~STATUS_SCAN_PENDING; - - queue_delayed_work(priv->workqueue, &priv->scan_check, - IPW_SCAN_CHECK_WATCHDOG); -done: - mutex_unlock(&priv->mutex); - return err; -} - -static void ipw_request_passive_scan(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, request_passive_scan.work); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_PASSIVE, 0); -} - -static void ipw_request_scan(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, request_scan.work); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 0); -} - -static void ipw_request_direct_scan(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, request_direct_scan.work); - ipw_request_scan_helper(priv, IW_SCAN_TYPE_ACTIVE, 1); -} - -static void ipw_bg_abort_scan(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, abort_scan); - mutex_lock(&priv->mutex); - ipw_abort_scan(priv); - mutex_unlock(&priv->mutex); -} - -static int ipw_wpa_enable(struct ipw_priv *priv, int value) -{ - /* This is called when wpa_supplicant loads and closes the driver - * interface. */ - priv->ieee->wpa_enabled = value; - return 0; -} - -static int ipw_wpa_set_auth_algs(struct ipw_priv *priv, int value) -{ - struct libipw_device *ieee = priv->ieee; - struct libipw_security sec = { - .flags = SEC_AUTH_MODE, - }; - int ret = 0; - - if (value & IW_AUTH_ALG_SHARED_KEY) { - sec.auth_mode = WLAN_AUTH_SHARED_KEY; - ieee->open_wep = 0; - } else if (value & IW_AUTH_ALG_OPEN_SYSTEM) { - sec.auth_mode = WLAN_AUTH_OPEN; - ieee->open_wep = 1; - } else if (value & IW_AUTH_ALG_LEAP) { - sec.auth_mode = WLAN_AUTH_LEAP; - ieee->open_wep = 1; - } else - return -EINVAL; - - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - else - ret = -EOPNOTSUPP; - - return ret; -} - -static void ipw_wpa_assoc_frame(struct ipw_priv *priv, char *wpa_ie, - int wpa_ie_len) -{ - /* make sure WPA is enabled */ - ipw_wpa_enable(priv, 1); -} - -static int ipw_set_rsn_capa(struct ipw_priv *priv, - char *capabilities, int length) -{ - IPW_DEBUG_HC("HOST_CMD_RSN_CAPABILITIES\n"); - - return ipw_send_cmd_pdu(priv, IPW_CMD_RSN_CAPABILITIES, length, - capabilities); -} - -/* - * WE-18 support - */ - -/* SIOCSIWGENIE */ -static int ipw_wx_set_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - u8 *buf; - int err = 0; - - if (wrqu->data.length > MAX_WPA_IE_LEN || - (wrqu->data.length && extra == NULL)) - return -EINVAL; - - if (wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_KERNEL); - if (buf == NULL) { - err = -ENOMEM; - goto out; - } - - memcpy(buf, extra, wrqu->data.length); - kfree(ieee->wpa_ie); - ieee->wpa_ie = buf; - ieee->wpa_ie_len = wrqu->data.length; - } else { - kfree(ieee->wpa_ie); - ieee->wpa_ie = NULL; - ieee->wpa_ie_len = 0; - } - - ipw_wpa_assoc_frame(priv, ieee->wpa_ie, ieee->wpa_ie_len); - out: - return err; -} - -/* SIOCGIWGENIE */ -static int ipw_wx_get_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - int err = 0; - - if (ieee->wpa_ie_len == 0 || ieee->wpa_ie == NULL) { - wrqu->data.length = 0; - goto out; - } - - if (wrqu->data.length < ieee->wpa_ie_len) { - err = -E2BIG; - goto out; - } - - wrqu->data.length = ieee->wpa_ie_len; - memcpy(extra, ieee->wpa_ie, ieee->wpa_ie_len); - - out: - return err; -} - -static int wext_cipher2level(int cipher) -{ - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - return SEC_LEVEL_0; - case IW_AUTH_CIPHER_WEP40: - case IW_AUTH_CIPHER_WEP104: - return SEC_LEVEL_1; - case IW_AUTH_CIPHER_TKIP: - return SEC_LEVEL_2; - case IW_AUTH_CIPHER_CCMP: - return SEC_LEVEL_3; - default: - return -1; - } -} - -/* SIOCSIWAUTH */ -static int ipw_wx_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - struct iw_param *param = &wrqu->param; - struct lib80211_crypt_data *crypt; - unsigned long flags; - int ret = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - break; - case IW_AUTH_CIPHER_PAIRWISE: - ipw_set_hw_decrypt_unicast(priv, - wext_cipher2level(param->value)); - break; - case IW_AUTH_CIPHER_GROUP: - ipw_set_hw_decrypt_multicast(priv, - wext_cipher2level(param->value)); - break; - case IW_AUTH_KEY_MGMT: - /* - * ipw2200 does not use these parameters - */ - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; - if (!crypt || !crypt->ops->set_flags || !crypt->ops->get_flags) - break; - - flags = crypt->ops->get_flags(crypt->priv); - - if (param->value) - flags |= IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; - else - flags &= ~IEEE80211_CRYPTO_TKIP_COUNTERMEASURES; - - crypt->ops->set_flags(flags, crypt->priv); - - break; - - case IW_AUTH_DROP_UNENCRYPTED:{ - /* HACK: - * - * wpa_supplicant calls set_wpa_enabled when the driver - * is loaded and unloaded, regardless of if WPA is being - * used. No other calls are made which can be used to - * determine if encryption will be used or not prior to - * association being expected. If encryption is not being - * used, drop_unencrypted is set to false, else true -- we - * can use this to determine if the CAP_PRIVACY_ON bit should - * be set. - */ - struct libipw_security sec = { - .flags = SEC_ENABLED, - .enabled = param->value, - }; - priv->ieee->drop_unencrypted = param->value; - /* We only change SEC_LEVEL for open mode. Others - * are set by ipw_wpa_set_encryption. - */ - if (!param->value) { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_0; - } else { - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } - if (priv->ieee->set_security) - priv->ieee->set_security(priv->ieee->dev, &sec); - break; - } - - case IW_AUTH_80211_AUTH_ALG: - ret = ipw_wpa_set_auth_algs(priv, param->value); - break; - - case IW_AUTH_WPA_ENABLED: - ret = ipw_wpa_enable(priv, param->value); - ipw_disassociate(priv); - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ieee->ieee802_1x = param->value; - break; - - case IW_AUTH_PRIVACY_INVOKED: - ieee->privacy_invoked = param->value; - break; - - default: - return -EOPNOTSUPP; - } - return ret; -} - -/* SIOCGIWAUTH */ -static int ipw_wx_get_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct libipw_device *ieee = priv->ieee; - struct lib80211_crypt_data *crypt; - struct iw_param *param = &wrqu->param; - int ret = 0; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* - * wpa_supplicant will control these internally - */ - ret = -EOPNOTSUPP; - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - crypt = priv->ieee->crypt_info.crypt[priv->ieee->crypt_info.tx_keyidx]; - if (!crypt || !crypt->ops->get_flags) - break; - - param->value = (crypt->ops->get_flags(crypt->priv) & - IEEE80211_CRYPTO_TKIP_COUNTERMEASURES) ? 1 : 0; - - break; - - case IW_AUTH_DROP_UNENCRYPTED: - param->value = ieee->drop_unencrypted; - break; - - case IW_AUTH_80211_AUTH_ALG: - param->value = ieee->sec.auth_mode; - break; - - case IW_AUTH_WPA_ENABLED: - param->value = ieee->wpa_enabled; - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - param->value = ieee->ieee802_1x; - break; - - case IW_AUTH_ROAMING_CONTROL: - case IW_AUTH_PRIVACY_INVOKED: - param->value = ieee->privacy_invoked; - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - -/* SIOCSIWENCODEEXT */ -static int ipw_wx_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - - if (hwcrypto) { - if (ext->alg == IW_ENCODE_ALG_TKIP) { - /* IPW HW can't build TKIP MIC, - host decryption still needed */ - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) - priv->ieee->host_mc_decrypt = 1; - else { - priv->ieee->host_encrypt = 0; - priv->ieee->host_encrypt_msdu = 1; - priv->ieee->host_decrypt = 1; - } - } else { - priv->ieee->host_encrypt = 0; - priv->ieee->host_encrypt_msdu = 0; - priv->ieee->host_decrypt = 0; - priv->ieee->host_mc_decrypt = 0; - } - } - - return libipw_wx_set_encodeext(priv->ieee, info, wrqu, extra); -} - -/* SIOCGIWENCODEEXT */ -static int ipw_wx_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - return libipw_wx_get_encodeext(priv->ieee, info, wrqu, extra); -} - -/* SIOCSIWMLME */ -static int ipw_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct iw_mlme *mlme = (struct iw_mlme *)extra; - __le16 reason; - - reason = cpu_to_le16(mlme->reason_code); - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - /* silently ignore */ - break; - - case IW_MLME_DISASSOC: - ipw_disassociate(priv); - break; - - default: - return -EOPNOTSUPP; - } - return 0; -} - -#ifdef CONFIG_IPW2200_QOS - -/* QoS */ -/* -* get the modulation type of the current network or -* the card current mode -*/ -static u8 ipw_qos_current_mode(struct ipw_priv * priv) -{ - u8 mode = 0; - - if (priv->status & STATUS_ASSOCIATED) { - unsigned long flags; - - spin_lock_irqsave(&priv->ieee->lock, flags); - mode = priv->assoc_network->mode; - spin_unlock_irqrestore(&priv->ieee->lock, flags); - } else { - mode = priv->ieee->mode; - } - IPW_DEBUG_QOS("QoS network/card mode %d \n", mode); - return mode; -} - -/* -* Handle management frame beacon and probe response -*/ -static int ipw_qos_handle_probe_response(struct ipw_priv *priv, - int active_network, - struct libipw_network *network) -{ - u32 size = sizeof(struct libipw_qos_parameters); - - if (network->capability & WLAN_CAPABILITY_IBSS) - network->qos_data.active = network->qos_data.supported; - - if (network->flags & NETWORK_HAS_QOS_MASK) { - if (active_network && - (network->flags & NETWORK_HAS_QOS_PARAMETERS)) - network->qos_data.active = network->qos_data.supported; - - if ((network->qos_data.active == 1) && (active_network == 1) && - (network->flags & NETWORK_HAS_QOS_PARAMETERS) && - (network->qos_data.old_param_count != - network->qos_data.param_count)) { - network->qos_data.old_param_count = - network->qos_data.param_count; - schedule_work(&priv->qos_activate); - IPW_DEBUG_QOS("QoS parameters change call " - "qos_activate\n"); - } - } else { - if ((priv->ieee->mode == IEEE_B) || (network->mode == IEEE_B)) - memcpy(&network->qos_data.parameters, - &def_parameters_CCK, size); - else - memcpy(&network->qos_data.parameters, - &def_parameters_OFDM, size); - - if ((network->qos_data.active == 1) && (active_network == 1)) { - IPW_DEBUG_QOS("QoS was disabled call qos_activate \n"); - schedule_work(&priv->qos_activate); - } - - network->qos_data.active = 0; - network->qos_data.supported = 0; - } - if ((priv->status & STATUS_ASSOCIATED) && - (priv->ieee->iw_mode == IW_MODE_ADHOC) && (active_network == 0)) { - if (memcmp(network->bssid, priv->bssid, ETH_ALEN)) - if (network->capability & WLAN_CAPABILITY_IBSS) - if ((network->ssid_len == - priv->assoc_network->ssid_len) && - !memcmp(network->ssid, - priv->assoc_network->ssid, - network->ssid_len)) { - queue_work(priv->workqueue, - &priv->merge_networks); - } - } - - return 0; -} - -/* -* This function set up the firmware to support QoS. It sends -* IPW_CMD_QOS_PARAMETERS and IPW_CMD_WME_INFO -*/ -static int ipw_qos_activate(struct ipw_priv *priv, - struct libipw_qos_data *qos_network_data) -{ - int err; - struct libipw_qos_parameters qos_parameters[QOS_QOS_SETS]; - struct libipw_qos_parameters *active_one = NULL; - u32 size = sizeof(struct libipw_qos_parameters); - u32 burst_duration; - int i; - u8 type; - - type = ipw_qos_current_mode(priv); - - active_one = &(qos_parameters[QOS_PARAM_SET_DEF_CCK]); - memcpy(active_one, priv->qos_data.def_qos_parm_CCK, size); - active_one = &(qos_parameters[QOS_PARAM_SET_DEF_OFDM]); - memcpy(active_one, priv->qos_data.def_qos_parm_OFDM, size); - - if (qos_network_data == NULL) { - if (type == IEEE_B) { - IPW_DEBUG_QOS("QoS activate network mode %d\n", type); - active_one = &def_parameters_CCK; - } else - active_one = &def_parameters_OFDM; - - memcpy(&qos_parameters[QOS_PARAM_SET_ACTIVE], active_one, size); - burst_duration = ipw_qos_get_burst_duration(priv); - for (i = 0; i < QOS_QUEUE_NUM; i++) - qos_parameters[QOS_PARAM_SET_ACTIVE].tx_op_limit[i] = - cpu_to_le16(burst_duration); - } else if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - if (type == IEEE_B) { - IPW_DEBUG_QOS("QoS activate IBSS nework mode %d\n", - type); - if (priv->qos_data.qos_enable == 0) - active_one = &def_parameters_CCK; - else - active_one = priv->qos_data.def_qos_parm_CCK; - } else { - if (priv->qos_data.qos_enable == 0) - active_one = &def_parameters_OFDM; - else - active_one = priv->qos_data.def_qos_parm_OFDM; - } - memcpy(&qos_parameters[QOS_PARAM_SET_ACTIVE], active_one, size); - } else { - unsigned long flags; - int active; - - spin_lock_irqsave(&priv->ieee->lock, flags); - active_one = &(qos_network_data->parameters); - qos_network_data->old_param_count = - qos_network_data->param_count; - memcpy(&qos_parameters[QOS_PARAM_SET_ACTIVE], active_one, size); - active = qos_network_data->supported; - spin_unlock_irqrestore(&priv->ieee->lock, flags); - - if (active == 0) { - burst_duration = ipw_qos_get_burst_duration(priv); - for (i = 0; i < QOS_QUEUE_NUM; i++) - qos_parameters[QOS_PARAM_SET_ACTIVE]. - tx_op_limit[i] = cpu_to_le16(burst_duration); - } - } - - IPW_DEBUG_QOS("QoS sending IPW_CMD_QOS_PARAMETERS\n"); - err = ipw_send_qos_params_command(priv, - (struct libipw_qos_parameters *) - &(qos_parameters[0])); - if (err) - IPW_DEBUG_QOS("QoS IPW_CMD_QOS_PARAMETERS failed\n"); - - return err; -} - -/* -* send IPW_CMD_WME_INFO to the firmware -*/ -static int ipw_qos_set_info_element(struct ipw_priv *priv) -{ - int ret = 0; - struct libipw_qos_information_element qos_info; - - if (priv == NULL) - return -1; - - qos_info.elementID = QOS_ELEMENT_ID; - qos_info.length = sizeof(struct libipw_qos_information_element) - 2; - - qos_info.version = QOS_VERSION_1; - qos_info.ac_info = 0; - - memcpy(qos_info.qui, qos_oui, QOS_OUI_LEN); - qos_info.qui_type = QOS_OUI_TYPE; - qos_info.qui_subtype = QOS_OUI_INFO_SUB_TYPE; - - ret = ipw_send_qos_info_command(priv, &qos_info); - if (ret != 0) { - IPW_DEBUG_QOS("QoS error calling ipw_send_qos_info_command\n"); - } - return ret; -} - -/* -* Set the QoS parameter with the association request structure -*/ -static int ipw_qos_association(struct ipw_priv *priv, - struct libipw_network *network) -{ - int err = 0; - struct libipw_qos_data *qos_data = NULL; - struct libipw_qos_data ibss_data = { - .supported = 1, - .active = 1, - }; - - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - BUG_ON(!(network->capability & WLAN_CAPABILITY_IBSS)); - - qos_data = &ibss_data; - break; - - case IW_MODE_INFRA: - qos_data = &network->qos_data; - break; - - default: - BUG(); - break; - } - - err = ipw_qos_activate(priv, qos_data); - if (err) { - priv->assoc_request.policy_support &= ~HC_QOS_SUPPORT_ASSOC; - return err; - } - - if (priv->qos_data.qos_enable && qos_data->supported) { - IPW_DEBUG_QOS("QoS will be enabled for this association\n"); - priv->assoc_request.policy_support |= HC_QOS_SUPPORT_ASSOC; - return ipw_qos_set_info_element(priv); - } - - return 0; -} - -/* -* handling the beaconing responses. if we get different QoS setting -* off the network from the associated setting, adjust the QoS -* setting -*/ -static int ipw_qos_association_resp(struct ipw_priv *priv, - struct libipw_network *network) -{ - int ret = 0; - unsigned long flags; - u32 size = sizeof(struct libipw_qos_parameters); - int set_qos_param = 0; - - if ((priv == NULL) || (network == NULL) || - (priv->assoc_network == NULL)) - return ret; - - if (!(priv->status & STATUS_ASSOCIATED)) - return ret; - - if ((priv->ieee->iw_mode != IW_MODE_INFRA)) - return ret; - - spin_lock_irqsave(&priv->ieee->lock, flags); - if (network->flags & NETWORK_HAS_QOS_PARAMETERS) { - memcpy(&priv->assoc_network->qos_data, &network->qos_data, - sizeof(struct libipw_qos_data)); - priv->assoc_network->qos_data.active = 1; - if ((network->qos_data.old_param_count != - network->qos_data.param_count)) { - set_qos_param = 1; - network->qos_data.old_param_count = - network->qos_data.param_count; - } - - } else { - if ((network->mode == IEEE_B) || (priv->ieee->mode == IEEE_B)) - memcpy(&priv->assoc_network->qos_data.parameters, - &def_parameters_CCK, size); - else - memcpy(&priv->assoc_network->qos_data.parameters, - &def_parameters_OFDM, size); - priv->assoc_network->qos_data.active = 0; - priv->assoc_network->qos_data.supported = 0; - set_qos_param = 1; - } - - spin_unlock_irqrestore(&priv->ieee->lock, flags); - - if (set_qos_param == 1) - schedule_work(&priv->qos_activate); - - return ret; -} - -static u32 ipw_qos_get_burst_duration(struct ipw_priv *priv) -{ - u32 ret = 0; - - if ((priv == NULL)) - return 0; - - if (!(priv->ieee->modulation & LIBIPW_OFDM_MODULATION)) - ret = priv->qos_data.burst_duration_CCK; - else - ret = priv->qos_data.burst_duration_OFDM; - - return ret; -} - -/* -* Initialize the setting of QoS global -*/ -static void ipw_qos_init(struct ipw_priv *priv, int enable, - int burst_enable, u32 burst_duration_CCK, - u32 burst_duration_OFDM) -{ - priv->qos_data.qos_enable = enable; - - if (priv->qos_data.qos_enable) { - priv->qos_data.def_qos_parm_CCK = &def_qos_parameters_CCK; - priv->qos_data.def_qos_parm_OFDM = &def_qos_parameters_OFDM; - IPW_DEBUG_QOS("QoS is enabled\n"); - } else { - priv->qos_data.def_qos_parm_CCK = &def_parameters_CCK; - priv->qos_data.def_qos_parm_OFDM = &def_parameters_OFDM; - IPW_DEBUG_QOS("QoS is not enabled\n"); - } - - priv->qos_data.burst_enable = burst_enable; - - if (burst_enable) { - priv->qos_data.burst_duration_CCK = burst_duration_CCK; - priv->qos_data.burst_duration_OFDM = burst_duration_OFDM; - } else { - priv->qos_data.burst_duration_CCK = 0; - priv->qos_data.burst_duration_OFDM = 0; - } -} - -/* -* map the packet priority to the right TX Queue -*/ -static int ipw_get_tx_queue_number(struct ipw_priv *priv, u16 priority) -{ - if (priority > 7 || !priv->qos_data.qos_enable) - priority = 0; - - return from_priority_to_tx_queue[priority] - 1; -} - -static int ipw_is_qos_active(struct net_device *dev, - struct sk_buff *skb) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct libipw_qos_data *qos_data = NULL; - int active, supported; - u8 *daddr = skb->data + ETH_ALEN; - int unicast = !is_multicast_ether_addr(daddr); - - if (!(priv->status & STATUS_ASSOCIATED)) - return 0; - - qos_data = &priv->assoc_network->qos_data; - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - if (unicast == 0) - qos_data->active = 0; - else - qos_data->active = qos_data->supported; - } - active = qos_data->active; - supported = qos_data->supported; - IPW_DEBUG_QOS("QoS %d network is QoS active %d supported %d " - "unicast %d\n", - priv->qos_data.qos_enable, active, supported, unicast); - if (active && priv->qos_data.qos_enable) - return 1; - - return 0; - -} -/* -* add QoS parameter to the TX command -*/ -static int ipw_qos_set_tx_queue_command(struct ipw_priv *priv, - u16 priority, - struct tfd_data *tfd) -{ - int tx_queue_id = 0; - - - tx_queue_id = from_priority_to_tx_queue[priority] - 1; - tfd->tx_flags_ext |= DCT_FLAG_EXT_QOS_ENABLED; - - if (priv->qos_data.qos_no_ack_mask & (1UL << tx_queue_id)) { - tfd->tx_flags &= ~DCT_FLAG_ACK_REQD; - tfd->tfd.tfd_26.mchdr.qos_ctrl |= cpu_to_le16(CTRL_QOS_NO_ACK); - } - return 0; -} - -/* -* background support to run QoS activate functionality -*/ -static void ipw_bg_qos_activate(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, qos_activate); - - mutex_lock(&priv->mutex); - - if (priv->status & STATUS_ASSOCIATED) - ipw_qos_activate(priv, &(priv->assoc_network->qos_data)); - - mutex_unlock(&priv->mutex); -} - -static int ipw_handle_probe_response(struct net_device *dev, - struct libipw_probe_response *resp, - struct libipw_network *network) -{ - struct ipw_priv *priv = libipw_priv(dev); - int active_network = ((priv->status & STATUS_ASSOCIATED) && - (network == priv->assoc_network)); - - ipw_qos_handle_probe_response(priv, active_network, network); - - return 0; -} - -static int ipw_handle_beacon(struct net_device *dev, - struct libipw_beacon *resp, - struct libipw_network *network) -{ - struct ipw_priv *priv = libipw_priv(dev); - int active_network = ((priv->status & STATUS_ASSOCIATED) && - (network == priv->assoc_network)); - - ipw_qos_handle_probe_response(priv, active_network, network); - - return 0; -} - -static int ipw_handle_assoc_response(struct net_device *dev, - struct libipw_assoc_response *resp, - struct libipw_network *network) -{ - struct ipw_priv *priv = libipw_priv(dev); - ipw_qos_association_resp(priv, network); - return 0; -} - -static int ipw_send_qos_params_command(struct ipw_priv *priv, struct libipw_qos_parameters - *qos_param) -{ - return ipw_send_cmd_pdu(priv, IPW_CMD_QOS_PARAMETERS, - sizeof(*qos_param) * 3, qos_param); -} - -static int ipw_send_qos_info_command(struct ipw_priv *priv, struct libipw_qos_information_element - *qos_param) -{ - return ipw_send_cmd_pdu(priv, IPW_CMD_WME_INFO, sizeof(*qos_param), - qos_param); -} - -#endif /* CONFIG_IPW2200_QOS */ - -static int ipw_associate_network(struct ipw_priv *priv, - struct libipw_network *network, - struct ipw_supported_rates *rates, int roaming) -{ - int err; - DECLARE_SSID_BUF(ssid); - - if (priv->config & CFG_FIXED_RATE) - ipw_set_fixed_rate(priv, network->mode); - - if (!(priv->config & CFG_STATIC_ESSID)) { - priv->essid_len = min(network->ssid_len, - (u8) IW_ESSID_MAX_SIZE); - memcpy(priv->essid, network->ssid, priv->essid_len); - } - - network->last_associate = jiffies; - - memset(&priv->assoc_request, 0, sizeof(priv->assoc_request)); - priv->assoc_request.channel = network->channel; - priv->assoc_request.auth_key = 0; - - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->ieee->sec.auth_mode == WLAN_AUTH_SHARED_KEY)) { - priv->assoc_request.auth_type = AUTH_SHARED_KEY; - priv->assoc_request.auth_key = priv->ieee->sec.active_key; - - if (priv->ieee->sec.level == SEC_LEVEL_1) - ipw_send_wep_keys(priv, DCW_WEP_KEY_SEC_TYPE_WEP); - - } else if ((priv->capability & CAP_PRIVACY_ON) && - (priv->ieee->sec.auth_mode == WLAN_AUTH_LEAP)) - priv->assoc_request.auth_type = AUTH_LEAP; - else - priv->assoc_request.auth_type = AUTH_OPEN; - - if (priv->ieee->wpa_ie_len) { - priv->assoc_request.policy_support = cpu_to_le16(0x02); /* RSN active */ - ipw_set_rsn_capa(priv, priv->ieee->wpa_ie, - priv->ieee->wpa_ie_len); - } - - /* - * It is valid for our ieee device to support multiple modes, but - * when it comes to associating to a given network we have to choose - * just one mode. - */ - if (network->mode & priv->ieee->mode & IEEE_A) - priv->assoc_request.ieee_mode = IPW_A_MODE; - else if (network->mode & priv->ieee->mode & IEEE_G) - priv->assoc_request.ieee_mode = IPW_G_MODE; - else if (network->mode & priv->ieee->mode & IEEE_B) - priv->assoc_request.ieee_mode = IPW_B_MODE; - - priv->assoc_request.capability = cpu_to_le16(network->capability); - if ((network->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - && !(priv->config & CFG_PREAMBLE_LONG)) { - priv->assoc_request.preamble_length = DCT_FLAG_SHORT_PREAMBLE; - } else { - priv->assoc_request.preamble_length = DCT_FLAG_LONG_PREAMBLE; - - /* Clear the short preamble if we won't be supporting it */ - priv->assoc_request.capability &= - ~cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - } - - /* Clear capability bits that aren't used in Ad Hoc */ - if (priv->ieee->iw_mode == IW_MODE_ADHOC) - priv->assoc_request.capability &= - ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); - - IPW_DEBUG_ASSOC("%sssocation attempt: '%s', channel %d, " - "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", - roaming ? "Rea" : "A", - print_ssid(ssid, priv->essid, priv->essid_len), - network->channel, - ipw_modes[priv->assoc_request.ieee_mode], - rates->num_rates, - (priv->assoc_request.preamble_length == - DCT_FLAG_LONG_PREAMBLE) ? "long" : "short", - network->capability & - WLAN_CAPABILITY_SHORT_PREAMBLE ? "short" : "long", - priv->capability & CAP_PRIVACY_ON ? "on " : "off", - priv->capability & CAP_PRIVACY_ON ? - (priv->capability & CAP_SHARED_KEY ? "(shared)" : - "(open)") : "", - priv->capability & CAP_PRIVACY_ON ? " key=" : "", - priv->capability & CAP_PRIVACY_ON ? - '1' + priv->ieee->sec.active_key : '.', - priv->capability & CAP_PRIVACY_ON ? '.' : ' '); - - priv->assoc_request.beacon_interval = cpu_to_le16(network->beacon_interval); - if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && - (network->time_stamp[0] == 0) && (network->time_stamp[1] == 0)) { - priv->assoc_request.assoc_type = HC_IBSS_START; - priv->assoc_request.assoc_tsf_msw = 0; - priv->assoc_request.assoc_tsf_lsw = 0; - } else { - if (unlikely(roaming)) - priv->assoc_request.assoc_type = HC_REASSOCIATE; - else - priv->assoc_request.assoc_type = HC_ASSOCIATE; - priv->assoc_request.assoc_tsf_msw = cpu_to_le32(network->time_stamp[1]); - priv->assoc_request.assoc_tsf_lsw = cpu_to_le32(network->time_stamp[0]); - } - - memcpy(priv->assoc_request.bssid, network->bssid, ETH_ALEN); - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - memset(&priv->assoc_request.dest, 0xFF, ETH_ALEN); - priv->assoc_request.atim_window = cpu_to_le16(network->atim_window); - } else { - memcpy(priv->assoc_request.dest, network->bssid, ETH_ALEN); - priv->assoc_request.atim_window = 0; - } - - priv->assoc_request.listen_interval = cpu_to_le16(network->listen_interval); - - err = ipw_send_ssid(priv, priv->essid, priv->essid_len); - if (err) { - IPW_DEBUG_HC("Attempt to send SSID command failed.\n"); - return err; - } - - rates->ieee_mode = priv->assoc_request.ieee_mode; - rates->purpose = IPW_RATE_CONNECT; - ipw_send_supported_rates(priv, rates); - - if (priv->assoc_request.ieee_mode == IPW_G_MODE) - priv->sys_config.dot11g_auto_detection = 1; - else - priv->sys_config.dot11g_auto_detection = 0; - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) - priv->sys_config.answer_broadcast_ssid_probe = 1; - else - priv->sys_config.answer_broadcast_ssid_probe = 0; - - err = ipw_send_system_config(priv); - if (err) { - IPW_DEBUG_HC("Attempt to send sys config command failed.\n"); - return err; - } - - IPW_DEBUG_ASSOC("Association sensitivity: %d\n", network->stats.rssi); - err = ipw_set_sensitivity(priv, network->stats.rssi + IPW_RSSI_TO_DBM); - if (err) { - IPW_DEBUG_HC("Attempt to send associate command failed.\n"); - return err; - } - - /* - * If preemption is enabled, it is possible for the association - * to complete before we return from ipw_send_associate. Therefore - * we have to be sure and update our priviate data first. - */ - priv->channel = network->channel; - memcpy(priv->bssid, network->bssid, ETH_ALEN); - priv->status |= STATUS_ASSOCIATING; - priv->status &= ~STATUS_SECURITY_UPDATED; - - priv->assoc_network = network; - -#ifdef CONFIG_IPW2200_QOS - ipw_qos_association(priv, network); -#endif - - err = ipw_send_associate(priv, &priv->assoc_request); - if (err) { - IPW_DEBUG_HC("Attempt to send associate command failed.\n"); - return err; - } - - IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM \n", - print_ssid(ssid, priv->essid, priv->essid_len), - priv->bssid); - - return 0; -} - -static void ipw_roam(void *data) -{ - struct ipw_priv *priv = data; - struct libipw_network *network = NULL; - struct ipw_network_match match = { - .network = priv->assoc_network - }; - - /* The roaming process is as follows: - * - * 1. Missed beacon threshold triggers the roaming process by - * setting the status ROAM bit and requesting a scan. - * 2. When the scan completes, it schedules the ROAM work - * 3. The ROAM work looks at all of the known networks for one that - * is a better network than the currently associated. If none - * found, the ROAM process is over (ROAM bit cleared) - * 4. If a better network is found, a disassociation request is - * sent. - * 5. When the disassociation completes, the roam work is again - * scheduled. The second time through, the driver is no longer - * associated, and the newly selected network is sent an - * association request. - * 6. At this point ,the roaming process is complete and the ROAM - * status bit is cleared. - */ - - /* If we are no longer associated, and the roaming bit is no longer - * set, then we are not actively roaming, so just return */ - if (!(priv->status & (STATUS_ASSOCIATED | STATUS_ROAMING))) - return; - - if (priv->status & STATUS_ASSOCIATED) { - /* First pass through ROAM process -- look for a better - * network */ - unsigned long flags; - u8 rssi = priv->assoc_network->stats.rssi; - priv->assoc_network->stats.rssi = -128; - spin_lock_irqsave(&priv->ieee->lock, flags); - list_for_each_entry(network, &priv->ieee->network_list, list) { - if (network != priv->assoc_network) - ipw_best_network(priv, &match, network, 1); - } - spin_unlock_irqrestore(&priv->ieee->lock, flags); - priv->assoc_network->stats.rssi = rssi; - - if (match.network == priv->assoc_network) { - IPW_DEBUG_ASSOC("No better APs in this network to " - "roam to.\n"); - priv->status &= ~STATUS_ROAMING; - ipw_debug_config(priv); - return; - } - - ipw_send_disassociate(priv, 1); - priv->assoc_network = match.network; - - return; - } - - /* Second pass through ROAM process -- request association */ - ipw_compatible_rates(priv, priv->assoc_network, &match.rates); - ipw_associate_network(priv, priv->assoc_network, &match.rates, 1); - priv->status &= ~STATUS_ROAMING; -} - -static void ipw_bg_roam(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, roam); - mutex_lock(&priv->mutex); - ipw_roam(priv); - mutex_unlock(&priv->mutex); -} - -static int ipw_associate(void *data) -{ - struct ipw_priv *priv = data; - - struct libipw_network *network = NULL; - struct ipw_network_match match = { - .network = NULL - }; - struct ipw_supported_rates *rates; - struct list_head *element; - unsigned long flags; - DECLARE_SSID_BUF(ssid); - - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n"); - return 0; - } - - if (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_ASSOC("Not attempting association (already in " - "progress)\n"); - return 0; - } - - if (priv->status & STATUS_DISASSOCIATING) { - IPW_DEBUG_ASSOC("Not attempting association (in " - "disassociating)\n "); - queue_work(priv->workqueue, &priv->associate); - return 0; - } - - if (!ipw_is_init(priv) || (priv->status & STATUS_SCANNING)) { - IPW_DEBUG_ASSOC("Not attempting association (scanning or not " - "initialized)\n"); - return 0; - } - - if (!(priv->config & CFG_ASSOCIATE) && - !(priv->config & (CFG_STATIC_ESSID | CFG_STATIC_BSSID))) { - IPW_DEBUG_ASSOC("Not attempting association (associate=0)\n"); - return 0; - } - - /* Protect our use of the network_list */ - spin_lock_irqsave(&priv->ieee->lock, flags); - list_for_each_entry(network, &priv->ieee->network_list, list) - ipw_best_network(priv, &match, network, 0); - - network = match.network; - rates = &match.rates; - - if (network == NULL && - priv->ieee->iw_mode == IW_MODE_ADHOC && - priv->config & CFG_ADHOC_CREATE && - priv->config & CFG_STATIC_ESSID && - priv->config & CFG_STATIC_CHANNEL) { - /* Use oldest network if the free list is empty */ - if (list_empty(&priv->ieee->network_free_list)) { - struct libipw_network *oldest = NULL; - struct libipw_network *target; - - list_for_each_entry(target, &priv->ieee->network_list, list) { - if ((oldest == NULL) || - (target->last_scanned < oldest->last_scanned)) - oldest = target; - } - - /* If there are no more slots, expire the oldest */ - list_del(&oldest->list); - target = oldest; - IPW_DEBUG_ASSOC("Expired '%s' (%pM) from " - "network list.\n", - print_ssid(ssid, target->ssid, - target->ssid_len), - target->bssid); - list_add_tail(&target->list, - &priv->ieee->network_free_list); - } - - element = priv->ieee->network_free_list.next; - network = list_entry(element, struct libipw_network, list); - ipw_adhoc_create(priv, network); - rates = &priv->rates; - list_del(element); - list_add_tail(&network->list, &priv->ieee->network_list); - } - spin_unlock_irqrestore(&priv->ieee->lock, flags); - - /* If we reached the end of the list, then we don't have any valid - * matching APs */ - if (!network) { - ipw_debug_config(priv); - - if (!(priv->status & STATUS_SCANNING)) { - if (!(priv->config & CFG_SPEED_SCAN)) - queue_delayed_work(priv->workqueue, - &priv->request_scan, - SCAN_INTERVAL); - else - queue_delayed_work(priv->workqueue, - &priv->request_scan, 0); - } - - return 0; - } - - ipw_associate_network(priv, network, rates, 0); - - return 1; -} - -static void ipw_bg_associate(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, associate); - mutex_lock(&priv->mutex); - ipw_associate(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_rebuild_decrypted_skb(struct ipw_priv *priv, - struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr; - u16 fc; - - hdr = (struct ieee80211_hdr *)skb->data; - fc = le16_to_cpu(hdr->frame_control); - if (!(fc & IEEE80211_FCTL_PROTECTED)) - return; - - fc &= ~IEEE80211_FCTL_PROTECTED; - hdr->frame_control = cpu_to_le16(fc); - switch (priv->ieee->sec.level) { - case SEC_LEVEL_3: - /* Remove CCMP HDR */ - memmove(skb->data + LIBIPW_3ADDR_LEN, - skb->data + LIBIPW_3ADDR_LEN + 8, - skb->len - LIBIPW_3ADDR_LEN - 8); - skb_trim(skb, skb->len - 16); /* CCMP_HDR_LEN + CCMP_MIC_LEN */ - break; - case SEC_LEVEL_2: - break; - case SEC_LEVEL_1: - /* Remove IV */ - memmove(skb->data + LIBIPW_3ADDR_LEN, - skb->data + LIBIPW_3ADDR_LEN + 4, - skb->len - LIBIPW_3ADDR_LEN - 4); - skb_trim(skb, skb->len - 8); /* IV + ICV */ - break; - case SEC_LEVEL_0: - break; - default: - printk(KERN_ERR "Unknow security level %d\n", - priv->ieee->sec.level); - break; - } -} - -static void ipw_handle_data_packet(struct ipw_priv *priv, - struct ipw_rx_mem_buffer *rxb, - struct libipw_rx_stats *stats) -{ - struct net_device *dev = priv->net_dev; - struct libipw_hdr_4addr *hdr; - struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; - - /* We received data from the HW, so stop the watchdog */ - dev->trans_start = jiffies; - - /* We only process data packets if the - * interface is open */ - if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > - skb_tailroom(rxb->skb))) { - dev->stats.rx_errors++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); - return; - } else if (unlikely(!netif_running(priv->net_dev))) { - dev->stats.rx_dropped++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); - return; - } - - /* Advance skb->data to the start of the actual payload */ - skb_reserve(rxb->skb, offsetof(struct ipw_rx_packet, u.frame.data)); - - /* Set the size of the skb to the size of the frame */ - skb_put(rxb->skb, le16_to_cpu(pkt->u.frame.length)); - - IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); - - /* HW decrypt will not clear the WEP bit, MIC, PN, etc. */ - hdr = (struct libipw_hdr_4addr *)rxb->skb->data; - if (priv->ieee->iw_mode != IW_MODE_MONITOR && - (is_multicast_ether_addr(hdr->addr1) ? - !priv->ieee->host_mc_decrypt : !priv->ieee->host_decrypt)) - ipw_rebuild_decrypted_skb(priv, rxb->skb); - - if (!libipw_rx(priv->ieee, rxb->skb, stats)) - dev->stats.rx_errors++; - else { /* libipw_rx succeeded, so it now owns the SKB */ - rxb->skb = NULL; - __ipw_led_activity_on(priv); - } -} - -#ifdef CONFIG_IPW2200_RADIOTAP -static void ipw_handle_data_packet_monitor(struct ipw_priv *priv, - struct ipw_rx_mem_buffer *rxb, - struct libipw_rx_stats *stats) -{ - struct net_device *dev = priv->net_dev; - struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; - struct ipw_rx_frame *frame = &pkt->u.frame; - - /* initial pull of some data */ - u16 received_channel = frame->received_channel; - u8 antennaAndPhy = frame->antennaAndPhy; - s8 antsignal = frame->rssi_dbm - IPW_RSSI_TO_DBM; /* call it signed anyhow */ - u16 pktrate = frame->rate; - - /* Magic struct that slots into the radiotap header -- no reason - * to build this manually element by element, we can write it much - * more efficiently than we can parse it. ORDER MATTERS HERE */ - struct ipw_rt_hdr *ipw_rt; - - short len = le16_to_cpu(pkt->u.frame.length); - - /* We received data from the HW, so stop the watchdog */ - dev->trans_start = jiffies; - - /* We only process data packets if the - * interface is open */ - if (unlikely((le16_to_cpu(pkt->u.frame.length) + IPW_RX_FRAME_SIZE) > - skb_tailroom(rxb->skb))) { - dev->stats.rx_errors++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); - return; - } else if (unlikely(!netif_running(priv->net_dev))) { - dev->stats.rx_dropped++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); - return; - } - - /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use - * that now */ - if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { - /* FIXME: Should alloc bigger skb instead */ - dev->stats.rx_dropped++; - priv->wstats.discard.misc++; - IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); - return; - } - - /* copy the frame itself */ - memmove(rxb->skb->data + sizeof(struct ipw_rt_hdr), - rxb->skb->data + IPW_RX_FRAME_SIZE, len); - - ipw_rt = (struct ipw_rt_hdr *)rxb->skb->data; - - ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(struct ipw_rt_hdr)); /* total header+data */ - - /* Big bitfield of all the fields we provide in radiotap */ - ipw_rt->rt_hdr.it_present = cpu_to_le32( - (1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA)); - - /* Zero the flags, we'll add to them as we go */ - ipw_rt->rt_flags = 0; - ipw_rt->rt_tsf = (u64)(frame->parent_tsf[3] << 24 | - frame->parent_tsf[2] << 16 | - frame->parent_tsf[1] << 8 | - frame->parent_tsf[0]); - - /* Convert signal to DBM */ - ipw_rt->rt_dbmsignal = antsignal; - ipw_rt->rt_dbmnoise = (s8) le16_to_cpu(frame->noise); - - /* Convert the channel data and set the flags */ - ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(received_channel)); - if (received_channel > 14) { /* 802.11a */ - ipw_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); - } else if (antennaAndPhy & 32) { /* 802.11b */ - ipw_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); - } else { /* 802.11g */ - ipw_rt->rt_chbitmask = - cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); - } - - /* set the rate in multiples of 500k/s */ - switch (pktrate) { - case IPW_TX_RATE_1MB: - ipw_rt->rt_rate = 2; - break; - case IPW_TX_RATE_2MB: - ipw_rt->rt_rate = 4; - break; - case IPW_TX_RATE_5MB: - ipw_rt->rt_rate = 10; - break; - case IPW_TX_RATE_6MB: - ipw_rt->rt_rate = 12; - break; - case IPW_TX_RATE_9MB: - ipw_rt->rt_rate = 18; - break; - case IPW_TX_RATE_11MB: - ipw_rt->rt_rate = 22; - break; - case IPW_TX_RATE_12MB: - ipw_rt->rt_rate = 24; - break; - case IPW_TX_RATE_18MB: - ipw_rt->rt_rate = 36; - break; - case IPW_TX_RATE_24MB: - ipw_rt->rt_rate = 48; - break; - case IPW_TX_RATE_36MB: - ipw_rt->rt_rate = 72; - break; - case IPW_TX_RATE_48MB: - ipw_rt->rt_rate = 96; - break; - case IPW_TX_RATE_54MB: - ipw_rt->rt_rate = 108; - break; - default: - ipw_rt->rt_rate = 0; - break; - } - - /* antenna number */ - ipw_rt->rt_antenna = (antennaAndPhy & 3); /* Is this right? */ - - /* set the preamble flag if we have it */ - if ((antennaAndPhy & 64)) - ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - /* Set the size of the skb to the size of the frame */ - skb_put(rxb->skb, len + sizeof(struct ipw_rt_hdr)); - - IPW_DEBUG_RX("Rx packet of %d bytes.\n", rxb->skb->len); - - if (!libipw_rx(priv->ieee, rxb->skb, stats)) - dev->stats.rx_errors++; - else { /* libipw_rx succeeded, so it now owns the SKB */ - rxb->skb = NULL; - /* no LED during capture */ - } -} -#endif - -#ifdef CONFIG_IPW2200_PROMISCUOUS -#define libipw_is_probe_response(fc) \ - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT && \ - (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PROBE_RESP ) - -#define libipw_is_management(fc) \ - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) - -#define libipw_is_control(fc) \ - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) - -#define libipw_is_data(fc) \ - ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA) - -#define libipw_is_assoc_request(fc) \ - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_ASSOC_REQ) - -#define libipw_is_reassoc_request(fc) \ - ((fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_REASSOC_REQ) - -static void ipw_handle_promiscuous_rx(struct ipw_priv *priv, - struct ipw_rx_mem_buffer *rxb, - struct libipw_rx_stats *stats) -{ - struct net_device *dev = priv->prom_net_dev; - struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)rxb->skb->data; - struct ipw_rx_frame *frame = &pkt->u.frame; - struct ipw_rt_hdr *ipw_rt; - - /* First cache any information we need before we overwrite - * the information provided in the skb from the hardware */ - struct ieee80211_hdr *hdr; - u16 channel = frame->received_channel; - u8 phy_flags = frame->antennaAndPhy; - s8 signal = frame->rssi_dbm - IPW_RSSI_TO_DBM; - s8 noise = (s8) le16_to_cpu(frame->noise); - u8 rate = frame->rate; - short len = le16_to_cpu(pkt->u.frame.length); - struct sk_buff *skb; - int hdr_only = 0; - u16 filter = priv->prom_priv->filter; - - /* If the filter is set to not include Rx frames then return */ - if (filter & IPW_PROM_NO_RX) - return; - - /* We received data from the HW, so stop the watchdog */ - dev->trans_start = jiffies; - - if (unlikely((len + IPW_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - dev->stats.rx_errors++; - IPW_DEBUG_DROP("Corruption detected! Oh no!\n"); - return; - } - - /* We only process data packets if the interface is open */ - if (unlikely(!netif_running(dev))) { - dev->stats.rx_dropped++; - IPW_DEBUG_DROP("Dropping packet while interface is not up.\n"); - return; - } - - /* Libpcap 0.9.3+ can handle variable length radiotap, so we'll use - * that now */ - if (len > IPW_RX_BUF_SIZE - sizeof(struct ipw_rt_hdr)) { - /* FIXME: Should alloc bigger skb instead */ - dev->stats.rx_dropped++; - IPW_DEBUG_DROP("Dropping too large packet in monitor\n"); - return; - } - - hdr = (void *)rxb->skb->data + IPW_RX_FRAME_SIZE; - if (libipw_is_management(le16_to_cpu(hdr->frame_control))) { - if (filter & IPW_PROM_NO_MGMT) - return; - if (filter & IPW_PROM_MGMT_HEADER_ONLY) - hdr_only = 1; - } else if (libipw_is_control(le16_to_cpu(hdr->frame_control))) { - if (filter & IPW_PROM_NO_CTL) - return; - if (filter & IPW_PROM_CTL_HEADER_ONLY) - hdr_only = 1; - } else if (libipw_is_data(le16_to_cpu(hdr->frame_control))) { - if (filter & IPW_PROM_NO_DATA) - return; - if (filter & IPW_PROM_DATA_HEADER_ONLY) - hdr_only = 1; - } - - /* Copy the SKB since this is for the promiscuous side */ - skb = skb_copy(rxb->skb, GFP_ATOMIC); - if (skb == NULL) { - IPW_ERROR("skb_clone failed for promiscuous copy.\n"); - return; - } - - /* copy the frame data to write after where the radiotap header goes */ - ipw_rt = (void *)skb->data; - - if (hdr_only) - len = libipw_get_hdrlen(le16_to_cpu(hdr->frame_control)); - - memcpy(ipw_rt->payload, hdr, len); - - ipw_rt->rt_hdr.it_version = PKTHDR_RADIOTAP_VERSION; - ipw_rt->rt_hdr.it_pad = 0; /* always good to zero */ - ipw_rt->rt_hdr.it_len = cpu_to_le16(sizeof(*ipw_rt)); /* total header+data */ - - /* Set the size of the skb to the size of the frame */ - skb_put(skb, sizeof(*ipw_rt) + len); - - /* Big bitfield of all the fields we provide in radiotap */ - ipw_rt->rt_hdr.it_present = cpu_to_le32( - (1 << IEEE80211_RADIOTAP_TSFT) | - (1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) | - (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) | - (1 << IEEE80211_RADIOTAP_ANTENNA)); - - /* Zero the flags, we'll add to them as we go */ - ipw_rt->rt_flags = 0; - ipw_rt->rt_tsf = (u64)(frame->parent_tsf[3] << 24 | - frame->parent_tsf[2] << 16 | - frame->parent_tsf[1] << 8 | - frame->parent_tsf[0]); - - /* Convert to DBM */ - ipw_rt->rt_dbmsignal = signal; - ipw_rt->rt_dbmnoise = noise; - - /* Convert the channel data and set the flags */ - ipw_rt->rt_channel = cpu_to_le16(ieee80211chan2mhz(channel)); - if (channel > 14) { /* 802.11a */ - ipw_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ)); - } else if (phy_flags & (1 << 5)) { /* 802.11b */ - ipw_rt->rt_chbitmask = - cpu_to_le16((IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ)); - } else { /* 802.11g */ - ipw_rt->rt_chbitmask = - cpu_to_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ); - } - - /* set the rate in multiples of 500k/s */ - switch (rate) { - case IPW_TX_RATE_1MB: - ipw_rt->rt_rate = 2; - break; - case IPW_TX_RATE_2MB: - ipw_rt->rt_rate = 4; - break; - case IPW_TX_RATE_5MB: - ipw_rt->rt_rate = 10; - break; - case IPW_TX_RATE_6MB: - ipw_rt->rt_rate = 12; - break; - case IPW_TX_RATE_9MB: - ipw_rt->rt_rate = 18; - break; - case IPW_TX_RATE_11MB: - ipw_rt->rt_rate = 22; - break; - case IPW_TX_RATE_12MB: - ipw_rt->rt_rate = 24; - break; - case IPW_TX_RATE_18MB: - ipw_rt->rt_rate = 36; - break; - case IPW_TX_RATE_24MB: - ipw_rt->rt_rate = 48; - break; - case IPW_TX_RATE_36MB: - ipw_rt->rt_rate = 72; - break; - case IPW_TX_RATE_48MB: - ipw_rt->rt_rate = 96; - break; - case IPW_TX_RATE_54MB: - ipw_rt->rt_rate = 108; - break; - default: - ipw_rt->rt_rate = 0; - break; - } - - /* antenna number */ - ipw_rt->rt_antenna = (phy_flags & 3); - - /* set the preamble flag if we have it */ - if (phy_flags & (1 << 6)) - ipw_rt->rt_flags |= IEEE80211_RADIOTAP_F_SHORTPRE; - - IPW_DEBUG_RX("Rx packet of %d bytes.\n", skb->len); - - if (!libipw_rx(priv->prom_priv->ieee, skb, stats)) { - dev->stats.rx_errors++; - dev_kfree_skb_any(skb); - } -} -#endif - -static int is_network_packet(struct ipw_priv *priv, - struct libipw_hdr_4addr *header) -{ - /* Filter incoming packets to determine if they are targetted toward - * this network, discarding packets coming from ourselves */ - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: /* Header: Dest. | Source | BSSID */ - /* packets from our adapter are dropped (echo) */ - if (!memcmp(header->addr2, priv->net_dev->dev_addr, ETH_ALEN)) - return 0; - - /* {broad,multi}cast packets to our BSSID go through */ - if (is_multicast_ether_addr(header->addr1)) - return !memcmp(header->addr3, priv->bssid, ETH_ALEN); - - /* packets to our adapter go through */ - return !memcmp(header->addr1, priv->net_dev->dev_addr, - ETH_ALEN); - - case IW_MODE_INFRA: /* Header: Dest. | BSSID | Source */ - /* packets from our adapter are dropped (echo) */ - if (!memcmp(header->addr3, priv->net_dev->dev_addr, ETH_ALEN)) - return 0; - - /* {broad,multi}cast packets to our BSS go through */ - if (is_multicast_ether_addr(header->addr1)) - return !memcmp(header->addr2, priv->bssid, ETH_ALEN); - - /* packets to our adapter go through */ - return !memcmp(header->addr1, priv->net_dev->dev_addr, - ETH_ALEN); - } - - return 1; -} - -#define IPW_PACKET_RETRY_TIME HZ - -static int is_duplicate_packet(struct ipw_priv *priv, - struct libipw_hdr_4addr *header) -{ - u16 sc = le16_to_cpu(header->seq_ctl); - u16 seq = WLAN_GET_SEQ_SEQ(sc); - u16 frag = WLAN_GET_SEQ_FRAG(sc); - u16 *last_seq, *last_frag; - unsigned long *last_time; - - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - { - struct list_head *p; - struct ipw_ibss_seq *entry = NULL; - u8 *mac = header->addr2; - int index = mac[5] % IPW_IBSS_MAC_HASH_SIZE; - - __list_for_each(p, &priv->ibss_mac_hash[index]) { - entry = - list_entry(p, struct ipw_ibss_seq, list); - if (!memcmp(entry->mac, mac, ETH_ALEN)) - break; - } - if (p == &priv->ibss_mac_hash[index]) { - entry = kmalloc(sizeof(*entry), GFP_ATOMIC); - if (!entry) { - IPW_ERROR - ("Cannot malloc new mac entry\n"); - return 0; - } - memcpy(entry->mac, mac, ETH_ALEN); - entry->seq_num = seq; - entry->frag_num = frag; - entry->packet_time = jiffies; - list_add(&entry->list, - &priv->ibss_mac_hash[index]); - return 0; - } - last_seq = &entry->seq_num; - last_frag = &entry->frag_num; - last_time = &entry->packet_time; - break; - } - case IW_MODE_INFRA: - last_seq = &priv->last_seq_num; - last_frag = &priv->last_frag_num; - last_time = &priv->last_packet_time; - break; - default: - return 0; - } - if ((*last_seq == seq) && - time_after(*last_time + IPW_PACKET_RETRY_TIME, jiffies)) { - if (*last_frag == frag) - goto drop; - if (*last_frag + 1 != frag) - /* out-of-order fragment */ - goto drop; - } else - *last_seq = seq; - - *last_frag = frag; - *last_time = jiffies; - return 0; - - drop: - /* Comment this line now since we observed the card receives - * duplicate packets but the FCTL_RETRY bit is not set in the - * IBSS mode with fragmentation enabled. - BUG_ON(!(le16_to_cpu(header->frame_control) & IEEE80211_FCTL_RETRY)); */ - return 1; -} - -static void ipw_handle_mgmt_packet(struct ipw_priv *priv, - struct ipw_rx_mem_buffer *rxb, - struct libipw_rx_stats *stats) -{ - struct sk_buff *skb = rxb->skb; - struct ipw_rx_packet *pkt = (struct ipw_rx_packet *)skb->data; - struct libipw_hdr_4addr *header = (struct libipw_hdr_4addr *) - (skb->data + IPW_RX_FRAME_SIZE); - - libipw_rx_mgt(priv->ieee, header, stats); - - if (priv->ieee->iw_mode == IW_MODE_ADHOC && - ((WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) == - IEEE80211_STYPE_PROBE_RESP) || - (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl)) == - IEEE80211_STYPE_BEACON))) { - if (!memcmp(header->addr3, priv->bssid, ETH_ALEN)) - ipw_add_station(priv, header->addr2); - } - - if (priv->config & CFG_NET_STATS) { - IPW_DEBUG_HC("sending stat packet\n"); - - /* Set the size of the skb to the size of the full - * ipw header and 802.11 frame */ - skb_put(skb, le16_to_cpu(pkt->u.frame.length) + - IPW_RX_FRAME_SIZE); - - /* Advance past the ipw packet header to the 802.11 frame */ - skb_pull(skb, IPW_RX_FRAME_SIZE); - - /* Push the libipw_rx_stats before the 802.11 frame */ - memcpy(skb_push(skb, sizeof(*stats)), stats, sizeof(*stats)); - - skb->dev = priv->ieee->dev; - - /* Point raw at the libipw_stats */ - skb_reset_mac_header(skb); - - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = cpu_to_be16(ETH_P_80211_STATS); - memset(skb->cb, 0, sizeof(rxb->skb->cb)); - netif_rx(skb); - rxb->skb = NULL; - } -} - -/* - * Main entry function for recieving a packet with 80211 headers. This - * should be called when ever the FW has notified us that there is a new - * skb in the recieve queue. - */ -static void ipw_rx(struct ipw_priv *priv) -{ - struct ipw_rx_mem_buffer *rxb; - struct ipw_rx_packet *pkt; - struct libipw_hdr_4addr *header; - u32 r, w, i; - u8 network_packet; - u8 fill_rx = 0; - - r = ipw_read32(priv, IPW_RX_READ_INDEX); - w = ipw_read32(priv, IPW_RX_WRITE_INDEX); - i = priv->rxq->read; - - if (ipw_rx_queue_space (priv->rxq) > (RX_QUEUE_SIZE / 2)) - fill_rx = 1; - - while (i != r) { - rxb = priv->rxq->queue[i]; - if (unlikely(rxb == NULL)) { - printk(KERN_CRIT "Queue not allocated!\n"); - break; - } - priv->rxq->queue[i] = NULL; - - pci_dma_sync_single_for_cpu(priv->pci_dev, rxb->dma_addr, - IPW_RX_BUF_SIZE, - PCI_DMA_FROMDEVICE); - - pkt = (struct ipw_rx_packet *)rxb->skb->data; - IPW_DEBUG_RX("Packet: type=%02X seq=%02X bits=%02X\n", - pkt->header.message_type, - pkt->header.rx_seq_num, pkt->header.control_bits); - - switch (pkt->header.message_type) { - case RX_FRAME_TYPE: /* 802.11 frame */ { - struct libipw_rx_stats stats = { - .rssi = pkt->u.frame.rssi_dbm - - IPW_RSSI_TO_DBM, - .signal = - pkt->u.frame.rssi_dbm - - IPW_RSSI_TO_DBM + 0x100, - .noise = - le16_to_cpu(pkt->u.frame.noise), - .rate = pkt->u.frame.rate, - .mac_time = jiffies, - .received_channel = - pkt->u.frame.received_channel, - .freq = - (pkt->u.frame. - control & (1 << 0)) ? - LIBIPW_24GHZ_BAND : - LIBIPW_52GHZ_BAND, - .len = le16_to_cpu(pkt->u.frame.length), - }; - - if (stats.rssi != 0) - stats.mask |= LIBIPW_STATMASK_RSSI; - if (stats.signal != 0) - stats.mask |= LIBIPW_STATMASK_SIGNAL; - if (stats.noise != 0) - stats.mask |= LIBIPW_STATMASK_NOISE; - if (stats.rate != 0) - stats.mask |= LIBIPW_STATMASK_RATE; - - priv->rx_packets++; - -#ifdef CONFIG_IPW2200_PROMISCUOUS - if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) - ipw_handle_promiscuous_rx(priv, rxb, &stats); -#endif - -#ifdef CONFIG_IPW2200_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { -#ifdef CONFIG_IPW2200_RADIOTAP - - ipw_handle_data_packet_monitor(priv, - rxb, - &stats); -#else - ipw_handle_data_packet(priv, rxb, - &stats); -#endif - break; - } -#endif - - header = - (struct libipw_hdr_4addr *)(rxb->skb-> - data + - IPW_RX_FRAME_SIZE); - /* TODO: Check Ad-Hoc dest/source and make sure - * that we are actually parsing these packets - * correctly -- we should probably use the - * frame control of the packet and disregard - * the current iw_mode */ - - network_packet = - is_network_packet(priv, header); - if (network_packet && priv->assoc_network) { - priv->assoc_network->stats.rssi = - stats.rssi; - priv->exp_avg_rssi = - exponential_average(priv->exp_avg_rssi, - stats.rssi, DEPTH_RSSI); - } - - IPW_DEBUG_RX("Frame: len=%u\n", - le16_to_cpu(pkt->u.frame.length)); - - if (le16_to_cpu(pkt->u.frame.length) < - libipw_get_hdrlen(le16_to_cpu( - header->frame_ctl))) { - IPW_DEBUG_DROP - ("Received packet is too small. " - "Dropping.\n"); - priv->net_dev->stats.rx_errors++; - priv->wstats.discard.misc++; - break; - } - - switch (WLAN_FC_GET_TYPE - (le16_to_cpu(header->frame_ctl))) { - - case IEEE80211_FTYPE_MGMT: - ipw_handle_mgmt_packet(priv, rxb, - &stats); - break; - - case IEEE80211_FTYPE_CTL: - break; - - case IEEE80211_FTYPE_DATA: - if (unlikely(!network_packet || - is_duplicate_packet(priv, - header))) - { - IPW_DEBUG_DROP("Dropping: " - "%pM, " - "%pM, " - "%pM\n", - header->addr1, - header->addr2, - header->addr3); - break; - } - - ipw_handle_data_packet(priv, rxb, - &stats); - - break; - } - break; - } - - case RX_HOST_NOTIFICATION_TYPE:{ - IPW_DEBUG_RX - ("Notification: subtype=%02X flags=%02X size=%d\n", - pkt->u.notification.subtype, - pkt->u.notification.flags, - le16_to_cpu(pkt->u.notification.size)); - ipw_rx_notification(priv, &pkt->u.notification); - break; - } - - default: - IPW_DEBUG_RX("Bad Rx packet of type %d\n", - pkt->header.message_type); - break; - } - - /* For now we just don't re-use anything. We can tweak this - * later to try and re-use notification packets and SKBs that - * fail to Rx correctly */ - if (rxb->skb != NULL) { - dev_kfree_skb_any(rxb->skb); - rxb->skb = NULL; - } - - pci_unmap_single(priv->pci_dev, rxb->dma_addr, - IPW_RX_BUF_SIZE, PCI_DMA_FROMDEVICE); - list_add_tail(&rxb->list, &priv->rxq->rx_used); - - i = (i + 1) % RX_QUEUE_SIZE; - - /* If there are a lot of unsued frames, restock the Rx queue - * so the ucode won't assert */ - if (fill_rx) { - priv->rxq->read = i; - ipw_rx_queue_replenish(priv); - } - } - - /* Backtrack one entry */ - priv->rxq->read = i; - ipw_rx_queue_restock(priv); -} - -#define DEFAULT_RTS_THRESHOLD 2304U -#define MIN_RTS_THRESHOLD 1U -#define MAX_RTS_THRESHOLD 2304U -#define DEFAULT_BEACON_INTERVAL 100U -#define DEFAULT_SHORT_RETRY_LIMIT 7U -#define DEFAULT_LONG_RETRY_LIMIT 4U - -/** - * ipw_sw_reset - * @option: options to control different reset behaviour - * 0 = reset everything except the 'disable' module_param - * 1 = reset everything and print out driver info (for probe only) - * 2 = reset everything - */ -static int ipw_sw_reset(struct ipw_priv *priv, int option) -{ - int band, modulation; - int old_mode = priv->ieee->iw_mode; - - /* Initialize module parameter values here */ - priv->config = 0; - - /* We default to disabling the LED code as right now it causes - * too many systems to lock up... */ - if (!led_support) - priv->config |= CFG_NO_LED; - - if (associate) - priv->config |= CFG_ASSOCIATE; - else - IPW_DEBUG_INFO("Auto associate disabled.\n"); - - if (auto_create) - priv->config |= CFG_ADHOC_CREATE; - else - IPW_DEBUG_INFO("Auto adhoc creation disabled.\n"); - - priv->config &= ~CFG_STATIC_ESSID; - priv->essid_len = 0; - memset(priv->essid, 0, IW_ESSID_MAX_SIZE); - - if (disable && option) { - priv->status |= STATUS_RF_KILL_SW; - IPW_DEBUG_INFO("Radio disabled.\n"); - } - - if (default_channel != 0) { - priv->config |= CFG_STATIC_CHANNEL; - priv->channel = default_channel; - IPW_DEBUG_INFO("Bind to static channel %d\n", default_channel); - /* TODO: Validate that provided channel is in range */ - } -#ifdef CONFIG_IPW2200_QOS - ipw_qos_init(priv, qos_enable, qos_burst_enable, - burst_duration_CCK, burst_duration_OFDM); -#endif /* CONFIG_IPW2200_QOS */ - - switch (network_mode) { - case 1: - priv->ieee->iw_mode = IW_MODE_ADHOC; - priv->net_dev->type = ARPHRD_ETHER; - - break; -#ifdef CONFIG_IPW2200_MONITOR - case 2: - priv->ieee->iw_mode = IW_MODE_MONITOR; -#ifdef CONFIG_IPW2200_RADIOTAP - priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; -#else - priv->net_dev->type = ARPHRD_IEEE80211; -#endif - break; -#endif - default: - case 0: - priv->net_dev->type = ARPHRD_ETHER; - priv->ieee->iw_mode = IW_MODE_INFRA; - break; - } - - if (hwcrypto) { - priv->ieee->host_encrypt = 0; - priv->ieee->host_encrypt_msdu = 0; - priv->ieee->host_decrypt = 0; - priv->ieee->host_mc_decrypt = 0; - } - IPW_DEBUG_INFO("Hardware crypto [%s]\n", hwcrypto ? "on" : "off"); - - /* IPW2200/2915 is abled to do hardware fragmentation. */ - priv->ieee->host_open_frag = 0; - - if ((priv->pci_dev->device == 0x4223) || - (priv->pci_dev->device == 0x4224)) { - if (option == 1) - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2915ABG Network " - "Connection\n"); - priv->ieee->abg_true = 1; - band = LIBIPW_52GHZ_BAND | LIBIPW_24GHZ_BAND; - modulation = LIBIPW_OFDM_MODULATION | - LIBIPW_CCK_MODULATION; - priv->adapter = IPW_2915ABG; - priv->ieee->mode = IEEE_A | IEEE_G | IEEE_B; - } else { - if (option == 1) - printk(KERN_INFO DRV_NAME - ": Detected Intel PRO/Wireless 2200BG Network " - "Connection\n"); - - priv->ieee->abg_true = 0; - band = LIBIPW_24GHZ_BAND; - modulation = LIBIPW_OFDM_MODULATION | - LIBIPW_CCK_MODULATION; - priv->adapter = IPW_2200BG; - priv->ieee->mode = IEEE_G | IEEE_B; - } - - priv->ieee->freq_band = band; - priv->ieee->modulation = modulation; - - priv->rates_mask = LIBIPW_DEFAULT_RATES_MASK; - - priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; - priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; - - priv->rts_threshold = DEFAULT_RTS_THRESHOLD; - priv->short_retry_limit = DEFAULT_SHORT_RETRY_LIMIT; - priv->long_retry_limit = DEFAULT_LONG_RETRY_LIMIT; - - /* If power management is turned on, default to AC mode */ - priv->power_mode = IPW_POWER_AC; - priv->tx_power = IPW_TX_POWER_DEFAULT; - - return old_mode == priv->ieee->iw_mode; -} - -/* - * This file defines the Wireless Extension handlers. It does not - * define any methods of hardware manipulation and relies on the - * functions defined in ipw_main to provide the HW interaction. - * - * The exception to this is the use of the ipw_get_ordinal() - * function used to poll the hardware vs. making unecessary calls. - * - */ - -static int ipw_wx_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - if (priv->status & STATUS_RF_KILL_MASK) - strcpy(wrqu->name, "radio off"); - else if (!(priv->status & STATUS_ASSOCIATED)) - strcpy(wrqu->name, "unassociated"); - else - snprintf(wrqu->name, IFNAMSIZ, "IEEE 802.11%c", - ipw_modes[priv->assoc_request.ieee_mode]); - IPW_DEBUG_WX("Name: %s\n", wrqu->name); - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_set_channel(struct ipw_priv *priv, u8 channel) -{ - if (channel == 0) { - IPW_DEBUG_INFO("Setting channel to ANY (0)\n"); - priv->config &= ~CFG_STATIC_CHANNEL; - IPW_DEBUG_ASSOC("Attempting to associate with new " - "parameters.\n"); - ipw_associate(priv); - return 0; - } - - priv->config |= CFG_STATIC_CHANNEL; - - if (priv->channel == channel) { - IPW_DEBUG_INFO("Request to set channel to current value (%d)\n", - channel); - return 0; - } - - IPW_DEBUG_INFO("Setting channel to %i\n", (int)channel); - priv->channel = channel; - -#ifdef CONFIG_IPW2200_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) { - int i; - if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_SCAN("Scan abort triggered due to " - "channel change.\n"); - ipw_abort_scan(priv); - } - - for (i = 1000; i && (priv->status & STATUS_SCANNING); i--) - udelay(10); - - if (priv->status & STATUS_SCANNING) - IPW_DEBUG_SCAN("Still scanning...\n"); - else - IPW_DEBUG_SCAN("Took %dms to abort current scan\n", - 1000 - i); - - return 0; - } -#endif /* CONFIG_IPW2200_MONITOR */ - - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC("[re]association triggered due to channel change.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - - return 0; -} - -static int ipw_wx_set_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - struct iw_freq *fwrq = &wrqu->freq; - int ret = 0, i; - u8 channel, flags; - int band; - - if (fwrq->m == 0) { - IPW_DEBUG_WX("SET Freq/Channel -> any\n"); - mutex_lock(&priv->mutex); - ret = ipw_set_channel(priv, 0); - mutex_unlock(&priv->mutex); - return ret; - } - /* if setting by freq convert to channel */ - if (fwrq->e == 1) { - channel = libipw_freq_to_channel(priv->ieee, fwrq->m); - if (channel == 0) - return -EINVAL; - } else - channel = fwrq->m; - - if (!(band = libipw_is_valid_channel(priv->ieee, channel))) - return -EINVAL; - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) { - i = libipw_channel_to_index(priv->ieee, channel); - if (i == -1) - return -EINVAL; - - flags = (band == LIBIPW_24GHZ_BAND) ? - geo->bg[i].flags : geo->a[i].flags; - if (flags & LIBIPW_CH_PASSIVE_ONLY) { - IPW_DEBUG_WX("Invalid Ad-Hoc channel for 802.11a\n"); - return -EINVAL; - } - } - - IPW_DEBUG_WX("SET Freq/Channel -> %d \n", fwrq->m); - mutex_lock(&priv->mutex); - ret = ipw_set_channel(priv, channel); - mutex_unlock(&priv->mutex); - return ret; -} - -static int ipw_wx_get_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - - wrqu->freq.e = 0; - - /* If we are associated, trying to associate, or have a statically - * configured CHANNEL then return that; otherwise return ANY */ - mutex_lock(&priv->mutex); - if (priv->config & CFG_STATIC_CHANNEL || - priv->status & (STATUS_ASSOCIATING | STATUS_ASSOCIATED)) { - int i; - - i = libipw_channel_to_index(priv->ieee, priv->channel); - BUG_ON(i == -1); - wrqu->freq.e = 1; - - switch (libipw_is_valid_channel(priv->ieee, priv->channel)) { - case LIBIPW_52GHZ_BAND: - wrqu->freq.m = priv->ieee->geo.a[i].freq * 100000; - break; - - case LIBIPW_24GHZ_BAND: - wrqu->freq.m = priv->ieee->geo.bg[i].freq * 100000; - break; - - default: - BUG(); - } - } else - wrqu->freq.m = 0; - - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Freq/Channel -> %d \n", priv->channel); - return 0; -} - -static int ipw_wx_set_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int err = 0; - - IPW_DEBUG_WX("Set MODE: %d\n", wrqu->mode); - - switch (wrqu->mode) { -#ifdef CONFIG_IPW2200_MONITOR - case IW_MODE_MONITOR: -#endif - case IW_MODE_ADHOC: - case IW_MODE_INFRA: - break; - case IW_MODE_AUTO: - wrqu->mode = IW_MODE_INFRA; - break; - default: - return -EINVAL; - } - if (wrqu->mode == priv->ieee->iw_mode) - return 0; - - mutex_lock(&priv->mutex); - - ipw_sw_reset(priv, 0); - -#ifdef CONFIG_IPW2200_MONITOR - if (priv->ieee->iw_mode == IW_MODE_MONITOR) - priv->net_dev->type = ARPHRD_ETHER; - - if (wrqu->mode == IW_MODE_MONITOR) -#ifdef CONFIG_IPW2200_RADIOTAP - priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; -#else - priv->net_dev->type = ARPHRD_IEEE80211; -#endif -#endif /* CONFIG_IPW2200_MONITOR */ - - /* Free the existing firmware and reset the fw_loaded - * flag so ipw_load() will bring in the new firmware */ - free_firmware(); - - priv->ieee->iw_mode = wrqu->mode; - - queue_work(priv->workqueue, &priv->adapter_restart); - mutex_unlock(&priv->mutex); - return err; -} - -static int ipw_wx_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - wrqu->mode = priv->ieee->iw_mode; - IPW_DEBUG_WX("Get MODE -> %d\n", wrqu->mode); - mutex_unlock(&priv->mutex); - return 0; -} - -/* Values are in microsecond */ -static const s32 timeout_duration[] = { - 350000, - 250000, - 75000, - 37000, - 25000, -}; - -static const s32 period_duration[] = { - 400000, - 700000, - 1000000, - 1000000, - 1000000 -}; - -static int ipw_wx_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct iw_range *range = (struct iw_range *)extra; - const struct libipw_geo *geo = libipw_get_geo(priv->ieee); - int i = 0, j; - - wrqu->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - /* 54Mbs == ~27 Mb/s real (802.11g) */ - range->throughput = 27 * 1000 * 1000; - - range->max_qual.qual = 100; - /* TODO: Find real max RSSI and stick here */ - range->max_qual.level = 0; - range->max_qual.noise = 0; - range->max_qual.updated = 7; /* Updated all three */ - - range->avg_qual.qual = 70; - /* TODO: Find real 'good' to 'bad' threshol value for RSSI */ - range->avg_qual.level = 0; /* FIXME to real average level */ - range->avg_qual.noise = 0; - range->avg_qual.updated = 7; /* Updated all three */ - mutex_lock(&priv->mutex); - range->num_bitrates = min(priv->rates.num_rates, (u8) IW_MAX_BITRATES); - - for (i = 0; i < range->num_bitrates; i++) - range->bitrate[i] = (priv->rates.supported_rates[i] & 0x7F) * - 500000; - - range->max_rts = DEFAULT_RTS_THRESHOLD; - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = WEP_KEYS; - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 18; - - i = 0; - if (priv->ieee->mode & (IEEE_B | IEEE_G)) { - for (j = 0; j < geo->bg_channels && i < IW_MAX_FREQUENCIES; j++) { - if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && - (geo->bg[j].flags & LIBIPW_CH_PASSIVE_ONLY)) - continue; - - range->freq[i].i = geo->bg[j].channel; - range->freq[i].m = geo->bg[j].freq * 100000; - range->freq[i].e = 1; - i++; - } - } - - if (priv->ieee->mode & IEEE_A) { - for (j = 0; j < geo->a_channels && i < IW_MAX_FREQUENCIES; j++) { - if ((priv->ieee->iw_mode == IW_MODE_ADHOC) && - (geo->a[j].flags & LIBIPW_CH_PASSIVE_ONLY)) - continue; - - range->freq[i].i = geo->a[j].channel; - range->freq[i].m = geo->a[j].freq * 100000; - range->freq[i].e = 1; - i++; - } - } - - range->num_channels = i; - range->num_frequency = i; - - mutex_unlock(&priv->mutex); - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | IW_ENC_CAPA_CIPHER_CCMP; - - range->scan_capa = IW_SCAN_CAPA_ESSID | IW_SCAN_CAPA_TYPE; - - IPW_DEBUG_WX("GET Range\n"); - return 0; -} - -static int ipw_wx_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - - static const unsigned char any[] = { - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff - }; - static const unsigned char off[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 - }; - - if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) - return -EINVAL; - mutex_lock(&priv->mutex); - if (!memcmp(any, wrqu->ap_addr.sa_data, ETH_ALEN) || - !memcmp(off, wrqu->ap_addr.sa_data, ETH_ALEN)) { - /* we disable mandatory BSSID association */ - IPW_DEBUG_WX("Setting AP BSSID to ANY\n"); - priv->config &= ~CFG_STATIC_BSSID; - IPW_DEBUG_ASSOC("Attempting to associate with new " - "parameters.\n"); - ipw_associate(priv); - mutex_unlock(&priv->mutex); - return 0; - } - - priv->config |= CFG_STATIC_BSSID; - if (!memcmp(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN)) { - IPW_DEBUG_WX("BSSID set to current BSSID.\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - IPW_DEBUG_WX("Setting mandatory BSSID to %pM\n", - wrqu->ap_addr.sa_data); - - memcpy(priv->bssid, wrqu->ap_addr.sa_data, ETH_ALEN); - - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC("[re]association triggered due to BSSID change.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - - /* If we are associated, trying to associate, or have a statically - * configured BSSID then return that; otherwise return ANY */ - mutex_lock(&priv->mutex); - if (priv->config & CFG_STATIC_BSSID || - priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - memcpy(wrqu->ap_addr.sa_data, priv->bssid, ETH_ALEN); - } else - memset(wrqu->ap_addr.sa_data, 0, ETH_ALEN); - - IPW_DEBUG_WX("Getting WAP BSSID: %pM\n", - wrqu->ap_addr.sa_data); - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_set_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int length; - DECLARE_SSID_BUF(ssid); - - mutex_lock(&priv->mutex); - - if (!wrqu->essid.flags) - { - IPW_DEBUG_WX("Setting ESSID to ANY\n"); - ipw_disassociate(priv); - priv->config &= ~CFG_STATIC_ESSID; - ipw_associate(priv); - mutex_unlock(&priv->mutex); - return 0; - } - - length = min((int)wrqu->essid.length, IW_ESSID_MAX_SIZE); - - priv->config |= CFG_STATIC_ESSID; - - if (priv->essid_len == length && !memcmp(priv->essid, extra, length) - && (priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING))) { - IPW_DEBUG_WX("ESSID set to current ESSID.\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", - print_ssid(ssid, extra, length), length); - - priv->essid_len = length; - memcpy(priv->essid, extra, priv->essid_len); - - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC("[re]association triggered due to ESSID change.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_get_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - DECLARE_SSID_BUF(ssid); - - /* If we are associated, trying to associate, or have a statically - * configured ESSID then return that; otherwise return ANY */ - mutex_lock(&priv->mutex); - if (priv->config & CFG_STATIC_ESSID || - priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { - IPW_DEBUG_WX("Getting essid: '%s'\n", - print_ssid(ssid, priv->essid, priv->essid_len)); - memcpy(extra, priv->essid, priv->essid_len); - wrqu->essid.length = priv->essid_len; - wrqu->essid.flags = 1; /* active */ - } else { - IPW_DEBUG_WX("Getting essid: ANY\n"); - wrqu->essid.length = 0; - wrqu->essid.flags = 0; /* active */ - } - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_set_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - - IPW_DEBUG_WX("Setting nick to '%s'\n", extra); - if (wrqu->data.length > IW_ESSID_MAX_SIZE) - return -E2BIG; - mutex_lock(&priv->mutex); - wrqu->data.length = min((size_t) wrqu->data.length, sizeof(priv->nick)); - memset(priv->nick, 0, sizeof(priv->nick)); - memcpy(priv->nick, extra, wrqu->data.length); - IPW_DEBUG_TRACE("<<\n"); - mutex_unlock(&priv->mutex); - return 0; - -} - -static int ipw_wx_get_nick(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - IPW_DEBUG_WX("Getting nick\n"); - mutex_lock(&priv->mutex); - wrqu->data.length = strlen(priv->nick); - memcpy(extra, priv->nick, wrqu->data.length); - wrqu->data.flags = 1; /* active */ - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int err = 0; - - IPW_DEBUG_WX("Setting roaming threshold to %d\n", wrqu->sens.value); - IPW_DEBUG_WX("Setting disassociate threshold to %d\n", 3*wrqu->sens.value); - mutex_lock(&priv->mutex); - - if (wrqu->sens.fixed == 0) - { - priv->roaming_threshold = IPW_MB_ROAMING_THRESHOLD_DEFAULT; - priv->disassociate_threshold = IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT; - goto out; - } - if ((wrqu->sens.value > IPW_MB_ROAMING_THRESHOLD_MAX) || - (wrqu->sens.value < IPW_MB_ROAMING_THRESHOLD_MIN)) { - err = -EINVAL; - goto out; - } - - priv->roaming_threshold = wrqu->sens.value; - priv->disassociate_threshold = 3*wrqu->sens.value; - out: - mutex_unlock(&priv->mutex); - return err; -} - -static int ipw_wx_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - wrqu->sens.fixed = 1; - wrqu->sens.value = priv->roaming_threshold; - mutex_unlock(&priv->mutex); - - IPW_DEBUG_WX("GET roaming threshold -> %s %d \n", - wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); - - return 0; -} - -static int ipw_wx_set_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* TODO: We should use semaphores or locks for access to priv */ - struct ipw_priv *priv = libipw_priv(dev); - u32 target_rate = wrqu->bitrate.value; - u32 fixed, mask; - - /* value = -1, fixed = 0 means auto only, so we should use all rates offered by AP */ - /* value = X, fixed = 1 means only rate X */ - /* value = X, fixed = 0 means all rates lower equal X */ - - if (target_rate == -1) { - fixed = 0; - mask = LIBIPW_DEFAULT_RATES_MASK; - /* Now we should reassociate */ - goto apply; - } - - mask = 0; - fixed = wrqu->bitrate.fixed; - - if (target_rate == 1000000 || !fixed) - mask |= LIBIPW_CCK_RATE_1MB_MASK; - if (target_rate == 1000000) - goto apply; - - if (target_rate == 2000000 || !fixed) - mask |= LIBIPW_CCK_RATE_2MB_MASK; - if (target_rate == 2000000) - goto apply; - - if (target_rate == 5500000 || !fixed) - mask |= LIBIPW_CCK_RATE_5MB_MASK; - if (target_rate == 5500000) - goto apply; - - if (target_rate == 6000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_6MB_MASK; - if (target_rate == 6000000) - goto apply; - - if (target_rate == 9000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_9MB_MASK; - if (target_rate == 9000000) - goto apply; - - if (target_rate == 11000000 || !fixed) - mask |= LIBIPW_CCK_RATE_11MB_MASK; - if (target_rate == 11000000) - goto apply; - - if (target_rate == 12000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_12MB_MASK; - if (target_rate == 12000000) - goto apply; - - if (target_rate == 18000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_18MB_MASK; - if (target_rate == 18000000) - goto apply; - - if (target_rate == 24000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_24MB_MASK; - if (target_rate == 24000000) - goto apply; - - if (target_rate == 36000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_36MB_MASK; - if (target_rate == 36000000) - goto apply; - - if (target_rate == 48000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_48MB_MASK; - if (target_rate == 48000000) - goto apply; - - if (target_rate == 54000000 || !fixed) - mask |= LIBIPW_OFDM_RATE_54MB_MASK; - if (target_rate == 54000000) - goto apply; - - IPW_DEBUG_WX("invalid rate specified, returning error\n"); - return -EINVAL; - - apply: - IPW_DEBUG_WX("Setting rate mask to 0x%08X [%s]\n", - mask, fixed ? "fixed" : "sub-rates"); - mutex_lock(&priv->mutex); - if (mask == LIBIPW_DEFAULT_RATES_MASK) { - priv->config &= ~CFG_FIXED_RATE; - ipw_set_fixed_rate(priv, priv->ieee->mode); - } else - priv->config |= CFG_FIXED_RATE; - - if (priv->rates_mask == mask) { - IPW_DEBUG_WX("Mask set to current mask.\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - priv->rates_mask = mask; - - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC("[re]association triggered due to rates change.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_get_rate(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - wrqu->bitrate.value = priv->last_rate; - wrqu->bitrate.fixed = (priv->config & CFG_FIXED_RATE) ? 1 : 0; - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Rate -> %d \n", wrqu->bitrate.value); - return 0; -} - -static int ipw_wx_set_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - if (wrqu->rts.disabled || !wrqu->rts.fixed) - priv->rts_threshold = DEFAULT_RTS_THRESHOLD; - else { - if (wrqu->rts.value < MIN_RTS_THRESHOLD || - wrqu->rts.value > MAX_RTS_THRESHOLD) { - mutex_unlock(&priv->mutex); - return -EINVAL; - } - priv->rts_threshold = wrqu->rts.value; - } - - ipw_send_rts_threshold(priv, priv->rts_threshold); - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("SET RTS Threshold -> %d \n", priv->rts_threshold); - return 0; -} - -static int ipw_wx_get_rts(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - wrqu->rts.value = priv->rts_threshold; - wrqu->rts.fixed = 0; /* no auto select */ - wrqu->rts.disabled = (wrqu->rts.value == DEFAULT_RTS_THRESHOLD); - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET RTS Threshold -> %d \n", wrqu->rts.value); - return 0; -} - -static int ipw_wx_set_txpow(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int err = 0; - - mutex_lock(&priv->mutex); - if (ipw_radio_kill_sw(priv, wrqu->power.disabled)) { - err = -EINPROGRESS; - goto out; - } - - if (!wrqu->power.fixed) - wrqu->power.value = IPW_TX_POWER_DEFAULT; - - if (wrqu->power.flags != IW_TXPOW_DBM) { - err = -EINVAL; - goto out; - } - - if ((wrqu->power.value > IPW_TX_POWER_MAX) || - (wrqu->power.value < IPW_TX_POWER_MIN)) { - err = -EINVAL; - goto out; - } - - priv->tx_power = wrqu->power.value; - err = ipw_set_tx_power(priv); - out: - mutex_unlock(&priv->mutex); - return err; -} - -static int ipw_wx_get_txpow(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - wrqu->power.value = priv->tx_power; - wrqu->power.fixed = 1; - wrqu->power.flags = IW_TXPOW_DBM; - wrqu->power.disabled = (priv->status & STATUS_RF_KILL_MASK) ? 1 : 0; - mutex_unlock(&priv->mutex); - - IPW_DEBUG_WX("GET TX Power -> %s %d \n", - wrqu->power.disabled ? "OFF" : "ON", wrqu->power.value); - - return 0; -} - -static int ipw_wx_set_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - if (wrqu->frag.disabled || !wrqu->frag.fixed) - priv->ieee->fts = DEFAULT_FTS; - else { - if (wrqu->frag.value < MIN_FRAG_THRESHOLD || - wrqu->frag.value > MAX_FRAG_THRESHOLD) { - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - priv->ieee->fts = wrqu->frag.value & ~0x1; - } - - ipw_send_frag_threshold(priv, wrqu->frag.value); - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("SET Frag Threshold -> %d \n", wrqu->frag.value); - return 0; -} - -static int ipw_wx_get_frag(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - wrqu->frag.value = priv->ieee->fts; - wrqu->frag.fixed = 0; /* no auto select */ - wrqu->frag.disabled = (wrqu->frag.value == DEFAULT_FTS); - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Frag Threshold -> %d \n", wrqu->frag.value); - - return 0; -} - -static int ipw_wx_set_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - - if (wrqu->retry.flags & IW_RETRY_LIFETIME || wrqu->retry.disabled) - return -EINVAL; - - if (!(wrqu->retry.flags & IW_RETRY_LIMIT)) - return 0; - - if (wrqu->retry.value < 0 || wrqu->retry.value >= 255) - return -EINVAL; - - mutex_lock(&priv->mutex); - if (wrqu->retry.flags & IW_RETRY_SHORT) - priv->short_retry_limit = (u8) wrqu->retry.value; - else if (wrqu->retry.flags & IW_RETRY_LONG) - priv->long_retry_limit = (u8) wrqu->retry.value; - else { - priv->short_retry_limit = (u8) wrqu->retry.value; - priv->long_retry_limit = (u8) wrqu->retry.value; - } - - ipw_send_retry_limit(priv, priv->short_retry_limit, - priv->long_retry_limit); - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("SET retry limit -> short:%d long:%d\n", - priv->short_retry_limit, priv->long_retry_limit); - return 0; -} - -static int ipw_wx_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - - mutex_lock(&priv->mutex); - wrqu->retry.disabled = 0; - - if ((wrqu->retry.flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - if (wrqu->retry.flags & IW_RETRY_LONG) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - wrqu->retry.value = priv->long_retry_limit; - } else if (wrqu->retry.flags & IW_RETRY_SHORT) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; - wrqu->retry.value = priv->short_retry_limit; - } else { - wrqu->retry.flags = IW_RETRY_LIMIT; - wrqu->retry.value = priv->short_retry_limit; - } - mutex_unlock(&priv->mutex); - - IPW_DEBUG_WX("GET retry -> %d \n", wrqu->retry.value); - - return 0; -} - -static int ipw_wx_set_scan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct iw_scan_req *req = (struct iw_scan_req *)extra; - struct delayed_work *work = NULL; - - mutex_lock(&priv->mutex); - - priv->user_requested_scan = 1; - - if (wrqu->data.length == sizeof(struct iw_scan_req)) { - if (wrqu->data.flags & IW_SCAN_THIS_ESSID) { - int len = min((int)req->essid_len, - (int)sizeof(priv->direct_scan_ssid)); - memcpy(priv->direct_scan_ssid, req->essid, len); - priv->direct_scan_ssid_len = len; - work = &priv->request_direct_scan; - } else if (req->scan_type == IW_SCAN_TYPE_PASSIVE) { - work = &priv->request_passive_scan; - } - } else { - /* Normal active broadcast scan */ - work = &priv->request_scan; - } - - mutex_unlock(&priv->mutex); - - IPW_DEBUG_WX("Start scan\n"); - - queue_delayed_work(priv->workqueue, work, 0); - - return 0; -} - -static int ipw_wx_get_scan(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - return libipw_wx_get_scan(priv->ieee, info, wrqu, extra); -} - -static int ipw_wx_set_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct ipw_priv *priv = libipw_priv(dev); - int ret; - u32 cap = priv->capability; - - mutex_lock(&priv->mutex); - ret = libipw_wx_set_encode(priv->ieee, info, wrqu, key); - - /* In IBSS mode, we need to notify the firmware to update - * the beacon info after we changed the capability. */ - if (cap != priv->capability && - priv->ieee->iw_mode == IW_MODE_ADHOC && - priv->status & STATUS_ASSOCIATED) - ipw_disassociate(priv); - - mutex_unlock(&priv->mutex); - return ret; -} - -static int ipw_wx_get_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key) -{ - struct ipw_priv *priv = libipw_priv(dev); - return libipw_wx_get_encode(priv->ieee, info, wrqu, key); -} - -static int ipw_wx_set_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int err; - mutex_lock(&priv->mutex); - if (wrqu->power.disabled) { - priv->power_mode = IPW_POWER_LEVEL(priv->power_mode); - err = ipw_send_power_mode(priv, IPW_POWER_MODE_CAM); - if (err) { - IPW_DEBUG_WX("failed setting power mode.\n"); - mutex_unlock(&priv->mutex); - return err; - } - IPW_DEBUG_WX("SET Power Management Mode -> off\n"); - mutex_unlock(&priv->mutex); - return 0; - } - - switch (wrqu->power.flags & IW_POWER_MODE) { - case IW_POWER_ON: /* If not specified */ - case IW_POWER_MODE: /* If set all mask */ - case IW_POWER_ALL_R: /* If explicitly state all */ - break; - default: /* Otherwise we don't support it */ - IPW_DEBUG_WX("SET PM Mode: %X not supported.\n", - wrqu->power.flags); - mutex_unlock(&priv->mutex); - return -EOPNOTSUPP; - } - - /* If the user hasn't specified a power management mode yet, default - * to BATTERY */ - if (IPW_POWER_LEVEL(priv->power_mode) == IPW_POWER_AC) - priv->power_mode = IPW_POWER_ENABLED | IPW_POWER_BATTERY; - else - priv->power_mode = IPW_POWER_ENABLED | priv->power_mode; - - err = ipw_send_power_mode(priv, IPW_POWER_LEVEL(priv->power_mode)); - if (err) { - IPW_DEBUG_WX("failed setting power mode.\n"); - mutex_unlock(&priv->mutex); - return err; - } - - IPW_DEBUG_WX("SET Power Management Mode -> 0x%02X\n", priv->power_mode); - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - if (!(priv->power_mode & IPW_POWER_ENABLED)) - wrqu->power.disabled = 1; - else - wrqu->power.disabled = 0; - - mutex_unlock(&priv->mutex); - IPW_DEBUG_WX("GET Power Management Mode -> %02X\n", priv->power_mode); - - return 0; -} - -static int ipw_wx_set_powermode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int mode = *(int *)extra; - int err; - - mutex_lock(&priv->mutex); - if ((mode < 1) || (mode > IPW_POWER_LIMIT)) - mode = IPW_POWER_AC; - - if (IPW_POWER_LEVEL(priv->power_mode) != mode) { - err = ipw_send_power_mode(priv, mode); - if (err) { - IPW_DEBUG_WX("failed setting power mode.\n"); - mutex_unlock(&priv->mutex); - return err; - } - priv->power_mode = IPW_POWER_ENABLED | mode; - } - mutex_unlock(&priv->mutex); - return 0; -} - -#define MAX_WX_STRING 80 -static int ipw_wx_get_powermode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int level = IPW_POWER_LEVEL(priv->power_mode); - char *p = extra; - - p += snprintf(p, MAX_WX_STRING, "Power save level: %d ", level); - - switch (level) { - case IPW_POWER_AC: - p += snprintf(p, MAX_WX_STRING - (p - extra), "(AC)"); - break; - case IPW_POWER_BATTERY: - p += snprintf(p, MAX_WX_STRING - (p - extra), "(BATTERY)"); - break; - default: - p += snprintf(p, MAX_WX_STRING - (p - extra), - "(Timeout %dms, Period %dms)", - timeout_duration[level - 1] / 1000, - period_duration[level - 1] / 1000); - } - - if (!(priv->power_mode & IPW_POWER_ENABLED)) - p += snprintf(p, MAX_WX_STRING - (p - extra), " OFF"); - - wrqu->data.length = p - extra + 1; - - return 0; -} - -static int ipw_wx_set_wireless_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int mode = *(int *)extra; - u8 band = 0, modulation = 0; - - if (mode == 0 || mode & ~IEEE_MODE_MASK) { - IPW_WARNING("Attempt to set invalid wireless mode: %d\n", mode); - return -EINVAL; - } - mutex_lock(&priv->mutex); - if (priv->adapter == IPW_2915ABG) { - priv->ieee->abg_true = 1; - if (mode & IEEE_A) { - band |= LIBIPW_52GHZ_BAND; - modulation |= LIBIPW_OFDM_MODULATION; - } else - priv->ieee->abg_true = 0; - } else { - if (mode & IEEE_A) { - IPW_WARNING("Attempt to set 2200BG into " - "802.11a mode\n"); - mutex_unlock(&priv->mutex); - return -EINVAL; - } - - priv->ieee->abg_true = 0; - } - - if (mode & IEEE_B) { - band |= LIBIPW_24GHZ_BAND; - modulation |= LIBIPW_CCK_MODULATION; - } else - priv->ieee->abg_true = 0; - - if (mode & IEEE_G) { - band |= LIBIPW_24GHZ_BAND; - modulation |= LIBIPW_OFDM_MODULATION; - } else - priv->ieee->abg_true = 0; - - priv->ieee->mode = mode; - priv->ieee->freq_band = band; - priv->ieee->modulation = modulation; - init_supported_rates(priv, &priv->rates); - - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC("[re]association triggered due to mode change.\n"); - if (!ipw_disassociate(priv)) { - ipw_send_supported_rates(priv, &priv->rates); - ipw_associate(priv); - } - - /* Update the band LEDs */ - ipw_led_band_on(priv); - - IPW_DEBUG_WX("PRIV SET MODE: %c%c%c\n", - mode & IEEE_A ? 'a' : '.', - mode & IEEE_B ? 'b' : '.', mode & IEEE_G ? 'g' : '.'); - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_get_wireless_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - switch (priv->ieee->mode) { - case IEEE_A: - strncpy(extra, "802.11a (1)", MAX_WX_STRING); - break; - case IEEE_B: - strncpy(extra, "802.11b (2)", MAX_WX_STRING); - break; - case IEEE_A | IEEE_B: - strncpy(extra, "802.11ab (3)", MAX_WX_STRING); - break; - case IEEE_G: - strncpy(extra, "802.11g (4)", MAX_WX_STRING); - break; - case IEEE_A | IEEE_G: - strncpy(extra, "802.11ag (5)", MAX_WX_STRING); - break; - case IEEE_B | IEEE_G: - strncpy(extra, "802.11bg (6)", MAX_WX_STRING); - break; - case IEEE_A | IEEE_B | IEEE_G: - strncpy(extra, "802.11abg (7)", MAX_WX_STRING); - break; - default: - strncpy(extra, "unknown", MAX_WX_STRING); - break; - } - - IPW_DEBUG_WX("PRIV GET MODE: %s\n", extra); - - wrqu->data.length = strlen(extra) + 1; - mutex_unlock(&priv->mutex); - - return 0; -} - -static int ipw_wx_set_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int mode = *(int *)extra; - mutex_lock(&priv->mutex); - /* Switching from SHORT -> LONG requires a disassociation */ - if (mode == 1) { - if (!(priv->config & CFG_PREAMBLE_LONG)) { - priv->config |= CFG_PREAMBLE_LONG; - - /* Network configuration changed -- force [re]association */ - IPW_DEBUG_ASSOC - ("[re]association triggered due to preamble change.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - } - goto done; - } - - if (mode == 0) { - priv->config &= ~CFG_PREAMBLE_LONG; - goto done; - } - mutex_unlock(&priv->mutex); - return -EINVAL; - - done: - mutex_unlock(&priv->mutex); - return 0; -} - -static int ipw_wx_get_preamble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - if (priv->config & CFG_PREAMBLE_LONG) - snprintf(wrqu->name, IFNAMSIZ, "long (1)"); - else - snprintf(wrqu->name, IFNAMSIZ, "auto (0)"); - mutex_unlock(&priv->mutex); - return 0; -} - -#ifdef CONFIG_IPW2200_MONITOR -static int ipw_wx_set_monitor(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - int *parms = (int *)extra; - int enable = (parms[0] > 0); - mutex_lock(&priv->mutex); - IPW_DEBUG_WX("SET MONITOR: %d %d\n", enable, parms[1]); - if (enable) { - if (priv->ieee->iw_mode != IW_MODE_MONITOR) { -#ifdef CONFIG_IPW2200_RADIOTAP - priv->net_dev->type = ARPHRD_IEEE80211_RADIOTAP; -#else - priv->net_dev->type = ARPHRD_IEEE80211; -#endif - queue_work(priv->workqueue, &priv->adapter_restart); - } - - ipw_set_channel(priv, parms[1]); - } else { - if (priv->ieee->iw_mode != IW_MODE_MONITOR) { - mutex_unlock(&priv->mutex); - return 0; - } - priv->net_dev->type = ARPHRD_ETHER; - queue_work(priv->workqueue, &priv->adapter_restart); - } - mutex_unlock(&priv->mutex); - return 0; -} - -#endif /* CONFIG_IPW2200_MONITOR */ - -static int ipw_wx_reset(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - IPW_DEBUG_WX("RESET\n"); - queue_work(priv->workqueue, &priv->adapter_restart); - return 0; -} - -static int ipw_wx_sw_reset(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct ipw_priv *priv = libipw_priv(dev); - union iwreq_data wrqu_sec = { - .encoding = { - .flags = IW_ENCODE_DISABLED, - }, - }; - int ret; - - IPW_DEBUG_WX("SW_RESET\n"); - - mutex_lock(&priv->mutex); - - ret = ipw_sw_reset(priv, 2); - if (!ret) { - free_firmware(); - ipw_adapter_restart(priv); - } - - /* The SW reset bit might have been toggled on by the 'disable' - * module parameter, so take appropriate action */ - ipw_radio_kill_sw(priv, priv->status & STATUS_RF_KILL_SW); - - mutex_unlock(&priv->mutex); - libipw_wx_set_encode(priv->ieee, info, &wrqu_sec, NULL); - mutex_lock(&priv->mutex); - - if (!(priv->status & STATUS_RF_KILL_MASK)) { - /* Configuration likely changed -- force [re]association */ - IPW_DEBUG_ASSOC("[re]association triggered due to sw " - "reset.\n"); - if (!ipw_disassociate(priv)) - ipw_associate(priv); - } - - mutex_unlock(&priv->mutex); - - return 0; -} - -/* Rebase the WE IOCTLs to zero for the handler array */ -#define IW_IOCTL(x) [(x)-SIOCSIWCOMMIT] -static iw_handler ipw_wx_handlers[] = { - IW_IOCTL(SIOCGIWNAME) = ipw_wx_get_name, - IW_IOCTL(SIOCSIWFREQ) = ipw_wx_set_freq, - IW_IOCTL(SIOCGIWFREQ) = ipw_wx_get_freq, - IW_IOCTL(SIOCSIWMODE) = ipw_wx_set_mode, - IW_IOCTL(SIOCGIWMODE) = ipw_wx_get_mode, - IW_IOCTL(SIOCSIWSENS) = ipw_wx_set_sens, - IW_IOCTL(SIOCGIWSENS) = ipw_wx_get_sens, - IW_IOCTL(SIOCGIWRANGE) = ipw_wx_get_range, - IW_IOCTL(SIOCSIWAP) = ipw_wx_set_wap, - IW_IOCTL(SIOCGIWAP) = ipw_wx_get_wap, - IW_IOCTL(SIOCSIWSCAN) = ipw_wx_set_scan, - IW_IOCTL(SIOCGIWSCAN) = ipw_wx_get_scan, - IW_IOCTL(SIOCSIWESSID) = ipw_wx_set_essid, - IW_IOCTL(SIOCGIWESSID) = ipw_wx_get_essid, - IW_IOCTL(SIOCSIWNICKN) = ipw_wx_set_nick, - IW_IOCTL(SIOCGIWNICKN) = ipw_wx_get_nick, - IW_IOCTL(SIOCSIWRATE) = ipw_wx_set_rate, - IW_IOCTL(SIOCGIWRATE) = ipw_wx_get_rate, - IW_IOCTL(SIOCSIWRTS) = ipw_wx_set_rts, - IW_IOCTL(SIOCGIWRTS) = ipw_wx_get_rts, - IW_IOCTL(SIOCSIWFRAG) = ipw_wx_set_frag, - IW_IOCTL(SIOCGIWFRAG) = ipw_wx_get_frag, - IW_IOCTL(SIOCSIWTXPOW) = ipw_wx_set_txpow, - IW_IOCTL(SIOCGIWTXPOW) = ipw_wx_get_txpow, - IW_IOCTL(SIOCSIWRETRY) = ipw_wx_set_retry, - IW_IOCTL(SIOCGIWRETRY) = ipw_wx_get_retry, - IW_IOCTL(SIOCSIWENCODE) = ipw_wx_set_encode, - IW_IOCTL(SIOCGIWENCODE) = ipw_wx_get_encode, - IW_IOCTL(SIOCSIWPOWER) = ipw_wx_set_power, - IW_IOCTL(SIOCGIWPOWER) = ipw_wx_get_power, - IW_IOCTL(SIOCSIWSPY) = iw_handler_set_spy, - IW_IOCTL(SIOCGIWSPY) = iw_handler_get_spy, - IW_IOCTL(SIOCSIWTHRSPY) = iw_handler_set_thrspy, - IW_IOCTL(SIOCGIWTHRSPY) = iw_handler_get_thrspy, - IW_IOCTL(SIOCSIWGENIE) = ipw_wx_set_genie, - IW_IOCTL(SIOCGIWGENIE) = ipw_wx_get_genie, - IW_IOCTL(SIOCSIWMLME) = ipw_wx_set_mlme, - IW_IOCTL(SIOCSIWAUTH) = ipw_wx_set_auth, - IW_IOCTL(SIOCGIWAUTH) = ipw_wx_get_auth, - IW_IOCTL(SIOCSIWENCODEEXT) = ipw_wx_set_encodeext, - IW_IOCTL(SIOCGIWENCODEEXT) = ipw_wx_get_encodeext, -}; - -enum { - IPW_PRIV_SET_POWER = SIOCIWFIRSTPRIV, - IPW_PRIV_GET_POWER, - IPW_PRIV_SET_MODE, - IPW_PRIV_GET_MODE, - IPW_PRIV_SET_PREAMBLE, - IPW_PRIV_GET_PREAMBLE, - IPW_PRIV_RESET, - IPW_PRIV_SW_RESET, -#ifdef CONFIG_IPW2200_MONITOR - IPW_PRIV_SET_MONITOR, -#endif -}; - -static struct iw_priv_args ipw_priv_args[] = { - { - .cmd = IPW_PRIV_SET_POWER, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_power"}, - { - .cmd = IPW_PRIV_GET_POWER, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_power"}, - { - .cmd = IPW_PRIV_SET_MODE, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_mode"}, - { - .cmd = IPW_PRIV_GET_MODE, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_mode"}, - { - .cmd = IPW_PRIV_SET_PREAMBLE, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_preamble"}, - { - .cmd = IPW_PRIV_GET_PREAMBLE, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | IFNAMSIZ, - .name = "get_preamble"}, - { - IPW_PRIV_RESET, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "reset"}, - { - IPW_PRIV_SW_RESET, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 0, 0, "sw_reset"}, -#ifdef CONFIG_IPW2200_MONITOR - { - IPW_PRIV_SET_MONITOR, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "monitor"}, -#endif /* CONFIG_IPW2200_MONITOR */ -}; - -static iw_handler ipw_priv_handler[] = { - ipw_wx_set_powermode, - ipw_wx_get_powermode, - ipw_wx_set_wireless_mode, - ipw_wx_get_wireless_mode, - ipw_wx_set_preamble, - ipw_wx_get_preamble, - ipw_wx_reset, - ipw_wx_sw_reset, -#ifdef CONFIG_IPW2200_MONITOR - ipw_wx_set_monitor, -#endif -}; - -static struct iw_handler_def ipw_wx_handler_def = { - .standard = ipw_wx_handlers, - .num_standard = ARRAY_SIZE(ipw_wx_handlers), - .num_private = ARRAY_SIZE(ipw_priv_handler), - .num_private_args = ARRAY_SIZE(ipw_priv_args), - .private = ipw_priv_handler, - .private_args = ipw_priv_args, - .get_wireless_stats = ipw_get_wireless_stats, -}; - -/* - * Get wireless statistics. - * Called by /proc/net/wireless - * Also called by SIOCGIWSTATS - */ -static struct iw_statistics *ipw_get_wireless_stats(struct net_device *dev) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct iw_statistics *wstats; - - wstats = &priv->wstats; - - /* if hw is disabled, then ipw_get_ordinal() can't be called. - * netdev->get_wireless_stats seems to be called before fw is - * initialized. STATUS_ASSOCIATED will only be set if the hw is up - * and associated; if not associcated, the values are all meaningless - * anyway, so set them all to NULL and INVALID */ - if (!(priv->status & STATUS_ASSOCIATED)) { - wstats->miss.beacon = 0; - wstats->discard.retries = 0; - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = 7; - wstats->qual.updated |= IW_QUAL_NOISE_INVALID | - IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; - return wstats; - } - - wstats->qual.qual = priv->quality; - wstats->qual.level = priv->exp_avg_rssi; - wstats->qual.noise = priv->exp_avg_noise; - wstats->qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED | IW_QUAL_DBM; - - wstats->miss.beacon = average_value(&priv->average_missed_beacons); - wstats->discard.retries = priv->last_tx_failures; - wstats->discard.code = priv->ieee->ieee_stats.rx_discards_undecryptable; - -/* if (ipw_get_ordinal(priv, IPW_ORD_STAT_TX_RETRY, &tx_retry, &len)) - goto fail_get_ordinal; - wstats->discard.retries += tx_retry; */ - - return wstats; -} - -/* net device stuff */ - -static void init_sys_config(struct ipw_sys_config *sys_config) -{ - memset(sys_config, 0, sizeof(struct ipw_sys_config)); - sys_config->bt_coexistence = 0; - sys_config->answer_broadcast_ssid_probe = 0; - sys_config->accept_all_data_frames = 0; - sys_config->accept_non_directed_frames = 1; - sys_config->exclude_unicast_unencrypted = 0; - sys_config->disable_unicast_decryption = 1; - sys_config->exclude_multicast_unencrypted = 0; - sys_config->disable_multicast_decryption = 1; - if (antenna < CFG_SYS_ANTENNA_BOTH || antenna > CFG_SYS_ANTENNA_B) - antenna = CFG_SYS_ANTENNA_BOTH; - sys_config->antenna_diversity = antenna; - sys_config->pass_crc_to_host = 0; /* TODO: See if 1 gives us FCS */ - sys_config->dot11g_auto_detection = 0; - sys_config->enable_cts_to_self = 0; - sys_config->bt_coexist_collision_thr = 0; - sys_config->pass_noise_stats_to_host = 1; /* 1 -- fix for 256 */ - sys_config->silence_threshold = 0x1e; -} - -static int ipw_net_open(struct net_device *dev) -{ - IPW_DEBUG_INFO("dev->open\n"); - netif_start_queue(dev); - return 0; -} - -static int ipw_net_stop(struct net_device *dev) -{ - IPW_DEBUG_INFO("dev->close\n"); - netif_stop_queue(dev); - return 0; -} - -/* -todo: - -modify to send one tfd per fragment instead of using chunking. otherwise -we need to heavily modify the libipw_skb_to_txb. -*/ - -static int ipw_tx_skb(struct ipw_priv *priv, struct libipw_txb *txb, - int pri) -{ - struct libipw_hdr_3addrqos *hdr = (struct libipw_hdr_3addrqos *) - txb->fragments[0]->data; - int i = 0; - struct tfd_frame *tfd; -#ifdef CONFIG_IPW2200_QOS - int tx_id = ipw_get_tx_queue_number(priv, pri); - struct clx2_tx_queue *txq = &priv->txq[tx_id]; -#else - struct clx2_tx_queue *txq = &priv->txq[0]; -#endif - struct clx2_queue *q = &txq->q; - u8 id, hdr_len, unicast; - int fc; - - if (!(priv->status & STATUS_ASSOCIATED)) - goto drop; - - hdr_len = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - switch (priv->ieee->iw_mode) { - case IW_MODE_ADHOC: - unicast = !is_multicast_ether_addr(hdr->addr1); - id = ipw_find_station(priv, hdr->addr1); - if (id == IPW_INVALID_STATION) { - id = ipw_add_station(priv, hdr->addr1); - if (id == IPW_INVALID_STATION) { - IPW_WARNING("Attempt to send data to " - "invalid cell: %pM\n", - hdr->addr1); - goto drop; - } - } - break; - - case IW_MODE_INFRA: - default: - unicast = !is_multicast_ether_addr(hdr->addr3); - id = 0; - break; - } - - tfd = &txq->bd[q->first_empty]; - txq->txb[q->first_empty] = txb; - memset(tfd, 0, sizeof(*tfd)); - tfd->u.data.station_number = id; - - tfd->control_flags.message_type = TX_FRAME_TYPE; - tfd->control_flags.control_bits = TFD_NEED_IRQ_MASK; - - tfd->u.data.cmd_id = DINO_CMD_TX; - tfd->u.data.len = cpu_to_le16(txb->payload_size); - - if (priv->assoc_request.ieee_mode == IPW_B_MODE) - tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_CCK; - else - tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_MODE_OFDM; - - if (priv->assoc_request.preamble_length == DCT_FLAG_SHORT_PREAMBLE) - tfd->u.data.tx_flags |= DCT_FLAG_SHORT_PREAMBLE; - - fc = le16_to_cpu(hdr->frame_ctl); - hdr->frame_ctl = cpu_to_le16(fc & ~IEEE80211_FCTL_MOREFRAGS); - - memcpy(&tfd->u.data.tfd.tfd_24.mchdr, hdr, hdr_len); - - if (likely(unicast)) - tfd->u.data.tx_flags |= DCT_FLAG_ACK_REQD; - - if (txb->encrypted && !priv->ieee->host_encrypt) { - switch (priv->ieee->sec.level) { - case SEC_LEVEL_3: - tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - /* XXX: ACK flag must be set for CCMP even if it - * is a multicast/broadcast packet, because CCMP - * group communication encrypted by GTK is - * actually done by the AP. */ - if (!unicast) - tfd->u.data.tx_flags |= DCT_FLAG_ACK_REQD; - - tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; - tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_CCM; - tfd->u.data.key_index = 0; - tfd->u.data.key_index |= DCT_WEP_INDEX_USE_IMMEDIATE; - break; - case SEC_LEVEL_2: - tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - tfd->u.data.tx_flags &= ~DCT_FLAG_NO_WEP; - tfd->u.data.tx_flags_ext |= DCT_FLAG_EXT_SECURITY_TKIP; - tfd->u.data.key_index = DCT_WEP_INDEX_USE_IMMEDIATE; - break; - case SEC_LEVEL_1: - tfd->u.data.tfd.tfd_24.mchdr.frame_ctl |= - cpu_to_le16(IEEE80211_FCTL_PROTECTED); - tfd->u.data.key_index = priv->ieee->crypt_info.tx_keyidx; - if (priv->ieee->sec.key_sizes[priv->ieee->crypt_info.tx_keyidx] <= - 40) - tfd->u.data.key_index |= DCT_WEP_KEY_64Bit; - else - tfd->u.data.key_index |= DCT_WEP_KEY_128Bit; - break; - case SEC_LEVEL_0: - break; - default: - printk(KERN_ERR "Unknow security level %d\n", - priv->ieee->sec.level); - break; - } - } else - /* No hardware encryption */ - tfd->u.data.tx_flags |= DCT_FLAG_NO_WEP; - -#ifdef CONFIG_IPW2200_QOS - if (fc & IEEE80211_STYPE_QOS_DATA) - ipw_qos_set_tx_queue_command(priv, pri, &(tfd->u.data)); -#endif /* CONFIG_IPW2200_QOS */ - - /* payload */ - tfd->u.data.num_chunks = cpu_to_le32(min((u8) (NUM_TFD_CHUNKS - 2), - txb->nr_frags)); - IPW_DEBUG_FRAG("%i fragments being sent as %i chunks.\n", - txb->nr_frags, le32_to_cpu(tfd->u.data.num_chunks)); - for (i = 0; i < le32_to_cpu(tfd->u.data.num_chunks); i++) { - IPW_DEBUG_FRAG("Adding fragment %i of %i (%d bytes).\n", - i, le32_to_cpu(tfd->u.data.num_chunks), - txb->fragments[i]->len - hdr_len); - IPW_DEBUG_TX("Dumping TX packet frag %i of %i (%d bytes):\n", - i, tfd->u.data.num_chunks, - txb->fragments[i]->len - hdr_len); - printk_buf(IPW_DL_TX, txb->fragments[i]->data + hdr_len, - txb->fragments[i]->len - hdr_len); - - tfd->u.data.chunk_ptr[i] = - cpu_to_le32(pci_map_single - (priv->pci_dev, - txb->fragments[i]->data + hdr_len, - txb->fragments[i]->len - hdr_len, - PCI_DMA_TODEVICE)); - tfd->u.data.chunk_len[i] = - cpu_to_le16(txb->fragments[i]->len - hdr_len); - } - - if (i != txb->nr_frags) { - struct sk_buff *skb; - u16 remaining_bytes = 0; - int j; - - for (j = i; j < txb->nr_frags; j++) - remaining_bytes += txb->fragments[j]->len - hdr_len; - - printk(KERN_INFO "Trying to reallocate for %d bytes\n", - remaining_bytes); - skb = alloc_skb(remaining_bytes, GFP_ATOMIC); - if (skb != NULL) { - tfd->u.data.chunk_len[i] = cpu_to_le16(remaining_bytes); - for (j = i; j < txb->nr_frags; j++) { - int size = txb->fragments[j]->len - hdr_len; - - printk(KERN_INFO "Adding frag %d %d...\n", - j, size); - memcpy(skb_put(skb, size), - txb->fragments[j]->data + hdr_len, size); - } - dev_kfree_skb_any(txb->fragments[i]); - txb->fragments[i] = skb; - tfd->u.data.chunk_ptr[i] = - cpu_to_le32(pci_map_single - (priv->pci_dev, skb->data, - remaining_bytes, - PCI_DMA_TODEVICE)); - - le32_add_cpu(&tfd->u.data.num_chunks, 1); - } - } - - /* kick DMA */ - q->first_empty = ipw_queue_inc_wrap(q->first_empty, q->n_bd); - ipw_write32(priv, q->reg_w, q->first_empty); - - if (ipw_tx_queue_space(q) < q->high_mark) - netif_stop_queue(priv->net_dev); - - return NETDEV_TX_OK; - - drop: - IPW_DEBUG_DROP("Silently dropping Tx packet.\n"); - libipw_txb_free(txb); - return NETDEV_TX_OK; -} - -static int ipw_net_is_queue_full(struct net_device *dev, int pri) -{ - struct ipw_priv *priv = libipw_priv(dev); -#ifdef CONFIG_IPW2200_QOS - int tx_id = ipw_get_tx_queue_number(priv, pri); - struct clx2_tx_queue *txq = &priv->txq[tx_id]; -#else - struct clx2_tx_queue *txq = &priv->txq[0]; -#endif /* CONFIG_IPW2200_QOS */ - - if (ipw_tx_queue_space(&txq->q) < txq->q.high_mark) - return 1; - - return 0; -} - -#ifdef CONFIG_IPW2200_PROMISCUOUS -static void ipw_handle_promiscuous_tx(struct ipw_priv *priv, - struct libipw_txb *txb) -{ - struct libipw_rx_stats dummystats; - struct ieee80211_hdr *hdr; - u8 n; - u16 filter = priv->prom_priv->filter; - int hdr_only = 0; - - if (filter & IPW_PROM_NO_TX) - return; - - memset(&dummystats, 0, sizeof(dummystats)); - - /* Filtering of fragment chains is done agains the first fragment */ - hdr = (void *)txb->fragments[0]->data; - if (libipw_is_management(le16_to_cpu(hdr->frame_control))) { - if (filter & IPW_PROM_NO_MGMT) - return; - if (filter & IPW_PROM_MGMT_HEADER_ONLY) - hdr_only = 1; - } else if (libipw_is_control(le16_to_cpu(hdr->frame_control))) { - if (filter & IPW_PROM_NO_CTL) - return; - if (filter & IPW_PROM_CTL_HEADER_ONLY) - hdr_only = 1; - } else if (libipw_is_data(le16_to_cpu(hdr->frame_control))) { - if (filter & IPW_PROM_NO_DATA) - return; - if (filter & IPW_PROM_DATA_HEADER_ONLY) - hdr_only = 1; - } - - for(n=0; nnr_frags; ++n) { - struct sk_buff *src = txb->fragments[n]; - struct sk_buff *dst; - struct ieee80211_radiotap_header *rt_hdr; - int len; - - if (hdr_only) { - hdr = (void *)src->data; - len = libipw_get_hdrlen(le16_to_cpu(hdr->frame_control)); - } else - len = src->len; - - dst = alloc_skb(len + sizeof(*rt_hdr), GFP_ATOMIC); - if (!dst) - continue; - - rt_hdr = (void *)skb_put(dst, sizeof(*rt_hdr)); - - rt_hdr->it_version = PKTHDR_RADIOTAP_VERSION; - rt_hdr->it_pad = 0; - rt_hdr->it_present = 0; /* after all, it's just an idea */ - rt_hdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_CHANNEL); - - *(__le16*)skb_put(dst, sizeof(u16)) = cpu_to_le16( - ieee80211chan2mhz(priv->channel)); - if (priv->channel > 14) /* 802.11a */ - *(__le16*)skb_put(dst, sizeof(u16)) = - cpu_to_le16(IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_5GHZ); - else if (priv->ieee->mode == IEEE_B) /* 802.11b */ - *(__le16*)skb_put(dst, sizeof(u16)) = - cpu_to_le16(IEEE80211_CHAN_CCK | - IEEE80211_CHAN_2GHZ); - else /* 802.11g */ - *(__le16*)skb_put(dst, sizeof(u16)) = - cpu_to_le16(IEEE80211_CHAN_OFDM | - IEEE80211_CHAN_2GHZ); - - rt_hdr->it_len = cpu_to_le16(dst->len); - - skb_copy_from_linear_data(src, skb_put(dst, len), len); - - if (!libipw_rx(priv->prom_priv->ieee, dst, &dummystats)) - dev_kfree_skb_any(dst); - } -} -#endif - -static netdev_tx_t ipw_net_hard_start_xmit(struct libipw_txb *txb, - struct net_device *dev, int pri) -{ - struct ipw_priv *priv = libipw_priv(dev); - unsigned long flags; - netdev_tx_t ret; - - IPW_DEBUG_TX("dev->xmit(%d bytes)\n", txb->payload_size); - spin_lock_irqsave(&priv->lock, flags); - -#ifdef CONFIG_IPW2200_PROMISCUOUS - if (rtap_iface && netif_running(priv->prom_net_dev)) - ipw_handle_promiscuous_tx(priv, txb); -#endif - - ret = ipw_tx_skb(priv, txb, pri); - if (ret == NETDEV_TX_OK) - __ipw_led_activity_on(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return ret; -} - -static void ipw_net_set_multicast_list(struct net_device *dev) -{ - -} - -static int ipw_net_set_mac_address(struct net_device *dev, void *p) -{ - struct ipw_priv *priv = libipw_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - mutex_lock(&priv->mutex); - priv->config |= CFG_CUSTOM_MAC; - memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN); - printk(KERN_INFO "%s: Setting MAC to %pM\n", - priv->net_dev->name, priv->mac_addr); - queue_work(priv->workqueue, &priv->adapter_restart); - mutex_unlock(&priv->mutex); - return 0; -} - -static void ipw_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct ipw_priv *p = libipw_priv(dev); - char vers[64]; - char date[32]; - u32 len; - - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); - - len = sizeof(vers); - ipw_get_ordinal(p, IPW_ORD_STAT_FW_VERSION, vers, &len); - len = sizeof(date); - ipw_get_ordinal(p, IPW_ORD_STAT_FW_DATE, date, &len); - - snprintf(info->fw_version, sizeof(info->fw_version), "%s (%s)", - vers, date); - strcpy(info->bus_info, pci_name(p->pci_dev)); - info->eedump_len = IPW_EEPROM_IMAGE_SIZE; -} - -static u32 ipw_ethtool_get_link(struct net_device *dev) -{ - struct ipw_priv *priv = libipw_priv(dev); - return (priv->status & STATUS_ASSOCIATED) != 0; -} - -static int ipw_ethtool_get_eeprom_len(struct net_device *dev) -{ - return IPW_EEPROM_IMAGE_SIZE; -} - -static int ipw_ethtool_get_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 * bytes) -{ - struct ipw_priv *p = libipw_priv(dev); - - if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) - return -EINVAL; - mutex_lock(&p->mutex); - memcpy(bytes, &p->eeprom[eeprom->offset], eeprom->len); - mutex_unlock(&p->mutex); - return 0; -} - -static int ipw_ethtool_set_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 * bytes) -{ - struct ipw_priv *p = libipw_priv(dev); - int i; - - if (eeprom->offset + eeprom->len > IPW_EEPROM_IMAGE_SIZE) - return -EINVAL; - mutex_lock(&p->mutex); - memcpy(&p->eeprom[eeprom->offset], bytes, eeprom->len); - for (i = 0; i < IPW_EEPROM_IMAGE_SIZE; i++) - ipw_write8(p, i + IPW_EEPROM_DATA, p->eeprom[i]); - mutex_unlock(&p->mutex); - return 0; -} - -static const struct ethtool_ops ipw_ethtool_ops = { - .get_link = ipw_ethtool_get_link, - .get_drvinfo = ipw_ethtool_get_drvinfo, - .get_eeprom_len = ipw_ethtool_get_eeprom_len, - .get_eeprom = ipw_ethtool_get_eeprom, - .set_eeprom = ipw_ethtool_set_eeprom, -}; - -static irqreturn_t ipw_isr(int irq, void *data) -{ - struct ipw_priv *priv = data; - u32 inta, inta_mask; - - if (!priv) - return IRQ_NONE; - - spin_lock(&priv->irq_lock); - - if (!(priv->status & STATUS_INT_ENABLED)) { - /* IRQ is disabled */ - goto none; - } - - inta = ipw_read32(priv, IPW_INTA_RW); - inta_mask = ipw_read32(priv, IPW_INTA_MASK_R); - - if (inta == 0xFFFFFFFF) { - /* Hardware disappeared */ - IPW_WARNING("IRQ INTA == 0xFFFFFFFF\n"); - goto none; - } - - if (!(inta & (IPW_INTA_MASK_ALL & inta_mask))) { - /* Shared interrupt */ - goto none; - } - - /* tell the device to stop sending interrupts */ - __ipw_disable_interrupts(priv); - - /* ack current interrupts */ - inta &= (IPW_INTA_MASK_ALL & inta_mask); - ipw_write32(priv, IPW_INTA_RW, inta); - - /* Cache INTA value for our tasklet */ - priv->isr_inta = inta; - - tasklet_schedule(&priv->irq_tasklet); - - spin_unlock(&priv->irq_lock); - - return IRQ_HANDLED; - none: - spin_unlock(&priv->irq_lock); - return IRQ_NONE; -} - -static void ipw_rf_kill(void *adapter) -{ - struct ipw_priv *priv = adapter; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - if (rf_kill_active(priv)) { - IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n"); - if (priv->workqueue) - queue_delayed_work(priv->workqueue, - &priv->rf_kill, 2 * HZ); - goto exit_unlock; - } - - /* RF Kill is now disabled, so bring the device back up */ - - if (!(priv->status & STATUS_RF_KILL_MASK)) { - IPW_DEBUG_RF_KILL("HW RF Kill no longer active, restarting " - "device\n"); - - /* we can not do an adapter restart while inside an irq lock */ - queue_work(priv->workqueue, &priv->adapter_restart); - } else - IPW_DEBUG_RF_KILL("HW RF Kill deactivated. SW RF Kill still " - "enabled\n"); - - exit_unlock: - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void ipw_bg_rf_kill(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, rf_kill.work); - mutex_lock(&priv->mutex); - ipw_rf_kill(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_link_up(struct ipw_priv *priv) -{ - priv->last_seq_num = -1; - priv->last_frag_num = -1; - priv->last_packet_time = 0; - - netif_carrier_on(priv->net_dev); - - cancel_delayed_work(&priv->request_scan); - cancel_delayed_work(&priv->request_direct_scan); - cancel_delayed_work(&priv->request_passive_scan); - cancel_delayed_work(&priv->scan_event); - ipw_reset_stats(priv); - /* Ensure the rate is updated immediately */ - priv->last_rate = ipw_get_current_rate(priv); - ipw_gather_stats(priv); - ipw_led_link_up(priv); - notify_wx_assoc_event(priv); - - if (priv->config & CFG_BACKGROUND_SCAN) - queue_delayed_work(priv->workqueue, &priv->request_scan, HZ); -} - -static void ipw_bg_link_up(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, link_up); - mutex_lock(&priv->mutex); - ipw_link_up(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_link_down(struct ipw_priv *priv) -{ - ipw_led_link_down(priv); - netif_carrier_off(priv->net_dev); - notify_wx_assoc_event(priv); - - /* Cancel any queued work ... */ - cancel_delayed_work(&priv->request_scan); - cancel_delayed_work(&priv->request_direct_scan); - cancel_delayed_work(&priv->request_passive_scan); - cancel_delayed_work(&priv->adhoc_check); - cancel_delayed_work(&priv->gather_stats); - - ipw_reset_stats(priv); - - if (!(priv->status & STATUS_EXIT_PENDING)) { - /* Queue up another scan... */ - queue_delayed_work(priv->workqueue, &priv->request_scan, 0); - } else - cancel_delayed_work(&priv->scan_event); -} - -static void ipw_bg_link_down(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, link_down); - mutex_lock(&priv->mutex); - ipw_link_down(priv); - mutex_unlock(&priv->mutex); -} - -static int __devinit ipw_setup_deferred_work(struct ipw_priv *priv) -{ - int ret = 0; - - priv->workqueue = create_workqueue(DRV_NAME); - init_waitqueue_head(&priv->wait_command_queue); - init_waitqueue_head(&priv->wait_state); - - INIT_DELAYED_WORK(&priv->adhoc_check, ipw_bg_adhoc_check); - INIT_WORK(&priv->associate, ipw_bg_associate); - INIT_WORK(&priv->disassociate, ipw_bg_disassociate); - INIT_WORK(&priv->system_config, ipw_system_config); - INIT_WORK(&priv->rx_replenish, ipw_bg_rx_queue_replenish); - INIT_WORK(&priv->adapter_restart, ipw_bg_adapter_restart); - INIT_DELAYED_WORK(&priv->rf_kill, ipw_bg_rf_kill); - INIT_WORK(&priv->up, ipw_bg_up); - INIT_WORK(&priv->down, ipw_bg_down); - INIT_DELAYED_WORK(&priv->request_scan, ipw_request_scan); - INIT_DELAYED_WORK(&priv->request_direct_scan, ipw_request_direct_scan); - INIT_DELAYED_WORK(&priv->request_passive_scan, ipw_request_passive_scan); - INIT_DELAYED_WORK(&priv->scan_event, ipw_scan_event); - INIT_DELAYED_WORK(&priv->gather_stats, ipw_bg_gather_stats); - INIT_WORK(&priv->abort_scan, ipw_bg_abort_scan); - INIT_WORK(&priv->roam, ipw_bg_roam); - INIT_DELAYED_WORK(&priv->scan_check, ipw_bg_scan_check); - INIT_WORK(&priv->link_up, ipw_bg_link_up); - INIT_WORK(&priv->link_down, ipw_bg_link_down); - INIT_DELAYED_WORK(&priv->led_link_on, ipw_bg_led_link_on); - INIT_DELAYED_WORK(&priv->led_link_off, ipw_bg_led_link_off); - INIT_DELAYED_WORK(&priv->led_act_off, ipw_bg_led_activity_off); - INIT_WORK(&priv->merge_networks, ipw_merge_adhoc_network); - -#ifdef CONFIG_IPW2200_QOS - INIT_WORK(&priv->qos_activate, ipw_bg_qos_activate); -#endif /* CONFIG_IPW2200_QOS */ - - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - ipw_irq_tasklet, (unsigned long)priv); - - return ret; -} - -static void shim__set_security(struct net_device *dev, - struct libipw_security *sec) -{ - struct ipw_priv *priv = libipw_priv(dev); - int i; - for (i = 0; i < 4; i++) { - if (sec->flags & (1 << i)) { - priv->ieee->sec.encode_alg[i] = sec->encode_alg[i]; - priv->ieee->sec.key_sizes[i] = sec->key_sizes[i]; - if (sec->key_sizes[i] == 0) - priv->ieee->sec.flags &= ~(1 << i); - else { - memcpy(priv->ieee->sec.keys[i], sec->keys[i], - sec->key_sizes[i]); - priv->ieee->sec.flags |= (1 << i); - } - priv->status |= STATUS_SECURITY_UPDATED; - } else if (sec->level != SEC_LEVEL_1) - priv->ieee->sec.flags &= ~(1 << i); - } - - if (sec->flags & SEC_ACTIVE_KEY) { - if (sec->active_key <= 3) { - priv->ieee->sec.active_key = sec->active_key; - priv->ieee->sec.flags |= SEC_ACTIVE_KEY; - } else - priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; - priv->status |= STATUS_SECURITY_UPDATED; - } else - priv->ieee->sec.flags &= ~SEC_ACTIVE_KEY; - - if ((sec->flags & SEC_AUTH_MODE) && - (priv->ieee->sec.auth_mode != sec->auth_mode)) { - priv->ieee->sec.auth_mode = sec->auth_mode; - priv->ieee->sec.flags |= SEC_AUTH_MODE; - if (sec->auth_mode == WLAN_AUTH_SHARED_KEY) - priv->capability |= CAP_SHARED_KEY; - else - priv->capability &= ~CAP_SHARED_KEY; - priv->status |= STATUS_SECURITY_UPDATED; - } - - if (sec->flags & SEC_ENABLED && priv->ieee->sec.enabled != sec->enabled) { - priv->ieee->sec.flags |= SEC_ENABLED; - priv->ieee->sec.enabled = sec->enabled; - priv->status |= STATUS_SECURITY_UPDATED; - if (sec->enabled) - priv->capability |= CAP_PRIVACY_ON; - else - priv->capability &= ~CAP_PRIVACY_ON; - } - - if (sec->flags & SEC_ENCRYPT) - priv->ieee->sec.encrypt = sec->encrypt; - - if (sec->flags & SEC_LEVEL && priv->ieee->sec.level != sec->level) { - priv->ieee->sec.level = sec->level; - priv->ieee->sec.flags |= SEC_LEVEL; - priv->status |= STATUS_SECURITY_UPDATED; - } - - if (!priv->ieee->host_encrypt && (sec->flags & SEC_ENCRYPT)) - ipw_set_hwcrypto_keys(priv); - - /* To match current functionality of ipw2100 (which works well w/ - * various supplicants, we don't force a disassociate if the - * privacy capability changes ... */ -#if 0 - if ((priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) && - (((priv->assoc_request.capability & - cpu_to_le16(WLAN_CAPABILITY_PRIVACY)) && !sec->enabled) || - (!(priv->assoc_request.capability & - cpu_to_le16(WLAN_CAPABILITY_PRIVACY)) && sec->enabled))) { - IPW_DEBUG_ASSOC("Disassociating due to capability " - "change.\n"); - ipw_disassociate(priv); - } -#endif -} - -static int init_supported_rates(struct ipw_priv *priv, - struct ipw_supported_rates *rates) -{ - /* TODO: Mask out rates based on priv->rates_mask */ - - memset(rates, 0, sizeof(*rates)); - /* configure supported rates */ - switch (priv->ieee->freq_band) { - case LIBIPW_52GHZ_BAND: - rates->ieee_mode = IPW_A_MODE; - rates->purpose = IPW_RATE_CAPABILITIES; - ipw_add_ofdm_scan_rates(rates, LIBIPW_CCK_MODULATION, - LIBIPW_OFDM_DEFAULT_RATES_MASK); - break; - - default: /* Mixed or 2.4Ghz */ - rates->ieee_mode = IPW_G_MODE; - rates->purpose = IPW_RATE_CAPABILITIES; - ipw_add_cck_scan_rates(rates, LIBIPW_CCK_MODULATION, - LIBIPW_CCK_DEFAULT_RATES_MASK); - if (priv->ieee->modulation & LIBIPW_OFDM_MODULATION) { - ipw_add_ofdm_scan_rates(rates, LIBIPW_CCK_MODULATION, - LIBIPW_OFDM_DEFAULT_RATES_MASK); - } - break; - } - - return 0; -} - -static int ipw_config(struct ipw_priv *priv) -{ - /* This is only called from ipw_up, which resets/reloads the firmware - so, we don't need to first disable the card before we configure - it */ - if (ipw_set_tx_power(priv)) - goto error; - - /* initialize adapter address */ - if (ipw_send_adapter_address(priv, priv->net_dev->dev_addr)) - goto error; - - /* set basic system config settings */ - init_sys_config(&priv->sys_config); - - /* Support Bluetooth if we have BT h/w on board, and user wants to. - * Does not support BT priority yet (don't abort or defer our Tx) */ - if (bt_coexist) { - unsigned char bt_caps = priv->eeprom[EEPROM_SKU_CAPABILITY]; - - if (bt_caps & EEPROM_SKU_CAP_BT_CHANNEL_SIG) - priv->sys_config.bt_coexistence - |= CFG_BT_COEXISTENCE_SIGNAL_CHNL; - if (bt_caps & EEPROM_SKU_CAP_BT_OOB) - priv->sys_config.bt_coexistence - |= CFG_BT_COEXISTENCE_OOB; - } - -#ifdef CONFIG_IPW2200_PROMISCUOUS - if (priv->prom_net_dev && netif_running(priv->prom_net_dev)) { - priv->sys_config.accept_all_data_frames = 1; - priv->sys_config.accept_non_directed_frames = 1; - priv->sys_config.accept_all_mgmt_bcpr = 1; - priv->sys_config.accept_all_mgmt_frames = 1; - } -#endif - - if (priv->ieee->iw_mode == IW_MODE_ADHOC) - priv->sys_config.answer_broadcast_ssid_probe = 1; - else - priv->sys_config.answer_broadcast_ssid_probe = 0; - - if (ipw_send_system_config(priv)) - goto error; - - init_supported_rates(priv, &priv->rates); - if (ipw_send_supported_rates(priv, &priv->rates)) - goto error; - - /* Set request-to-send threshold */ - if (priv->rts_threshold) { - if (ipw_send_rts_threshold(priv, priv->rts_threshold)) - goto error; - } -#ifdef CONFIG_IPW2200_QOS - IPW_DEBUG_QOS("QoS: call ipw_qos_activate\n"); - ipw_qos_activate(priv, NULL); -#endif /* CONFIG_IPW2200_QOS */ - - if (ipw_set_random_seed(priv)) - goto error; - - /* final state transition to the RUN state */ - if (ipw_send_host_complete(priv)) - goto error; - - priv->status |= STATUS_INIT; - - ipw_led_init(priv); - ipw_led_radio_on(priv); - priv->notif_missed_beacons = 0; - - /* Set hardware WEP key if it is configured. */ - if ((priv->capability & CAP_PRIVACY_ON) && - (priv->ieee->sec.level == SEC_LEVEL_1) && - !(priv->ieee->host_encrypt || priv->ieee->host_decrypt)) - ipw_set_hwcrypto_keys(priv); - - return 0; - - error: - return -EIO; -} - -/* - * NOTE: - * - * These tables have been tested in conjunction with the - * Intel PRO/Wireless 2200BG and 2915ABG Network Connection Adapters. - * - * Altering this values, using it on other hardware, or in geographies - * not intended for resale of the above mentioned Intel adapters has - * not been tested. - * - * Remember to update the table in README.ipw2200 when changing this - * table. - * - */ -static const struct libipw_geo ipw_geos[] = { - { /* Restricted */ - "---", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - }, - - { /* Custom US/Canada */ - "ZZF", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - .a_channels = 8, - .a = {{5180, 36}, - {5200, 40}, - {5220, 44}, - {5240, 48}, - {5260, 52, LIBIPW_CH_PASSIVE_ONLY}, - {5280, 56, LIBIPW_CH_PASSIVE_ONLY}, - {5300, 60, LIBIPW_CH_PASSIVE_ONLY}, - {5320, 64, LIBIPW_CH_PASSIVE_ONLY}}, - }, - - { /* Rest of World */ - "ZZD", - .bg_channels = 13, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, {2467, 12}, - {2472, 13}}, - }, - - { /* Custom USA & Europe & High */ - "ZZA", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - .a_channels = 13, - .a = {{5180, 36}, - {5200, 40}, - {5220, 44}, - {5240, 48}, - {5260, 52, LIBIPW_CH_PASSIVE_ONLY}, - {5280, 56, LIBIPW_CH_PASSIVE_ONLY}, - {5300, 60, LIBIPW_CH_PASSIVE_ONLY}, - {5320, 64, LIBIPW_CH_PASSIVE_ONLY}, - {5745, 149}, - {5765, 153}, - {5785, 157}, - {5805, 161}, - {5825, 165}}, - }, - - { /* Custom NA & Europe */ - "ZZB", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - .a_channels = 13, - .a = {{5180, 36}, - {5200, 40}, - {5220, 44}, - {5240, 48}, - {5260, 52, LIBIPW_CH_PASSIVE_ONLY}, - {5280, 56, LIBIPW_CH_PASSIVE_ONLY}, - {5300, 60, LIBIPW_CH_PASSIVE_ONLY}, - {5320, 64, LIBIPW_CH_PASSIVE_ONLY}, - {5745, 149, LIBIPW_CH_PASSIVE_ONLY}, - {5765, 153, LIBIPW_CH_PASSIVE_ONLY}, - {5785, 157, LIBIPW_CH_PASSIVE_ONLY}, - {5805, 161, LIBIPW_CH_PASSIVE_ONLY}, - {5825, 165, LIBIPW_CH_PASSIVE_ONLY}}, - }, - - { /* Custom Japan */ - "ZZC", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - .a_channels = 4, - .a = {{5170, 34}, {5190, 38}, - {5210, 42}, {5230, 46}}, - }, - - { /* Custom */ - "ZZM", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - }, - - { /* Europe */ - "ZZE", - .bg_channels = 13, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, {2467, 12}, - {2472, 13}}, - .a_channels = 19, - .a = {{5180, 36}, - {5200, 40}, - {5220, 44}, - {5240, 48}, - {5260, 52, LIBIPW_CH_PASSIVE_ONLY}, - {5280, 56, LIBIPW_CH_PASSIVE_ONLY}, - {5300, 60, LIBIPW_CH_PASSIVE_ONLY}, - {5320, 64, LIBIPW_CH_PASSIVE_ONLY}, - {5500, 100, LIBIPW_CH_PASSIVE_ONLY}, - {5520, 104, LIBIPW_CH_PASSIVE_ONLY}, - {5540, 108, LIBIPW_CH_PASSIVE_ONLY}, - {5560, 112, LIBIPW_CH_PASSIVE_ONLY}, - {5580, 116, LIBIPW_CH_PASSIVE_ONLY}, - {5600, 120, LIBIPW_CH_PASSIVE_ONLY}, - {5620, 124, LIBIPW_CH_PASSIVE_ONLY}, - {5640, 128, LIBIPW_CH_PASSIVE_ONLY}, - {5660, 132, LIBIPW_CH_PASSIVE_ONLY}, - {5680, 136, LIBIPW_CH_PASSIVE_ONLY}, - {5700, 140, LIBIPW_CH_PASSIVE_ONLY}}, - }, - - { /* Custom Japan */ - "ZZJ", - .bg_channels = 14, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, {2467, 12}, - {2472, 13}, {2484, 14, LIBIPW_CH_B_ONLY}}, - .a_channels = 4, - .a = {{5170, 34}, {5190, 38}, - {5210, 42}, {5230, 46}}, - }, - - { /* Rest of World */ - "ZZR", - .bg_channels = 14, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, {2467, 12}, - {2472, 13}, {2484, 14, LIBIPW_CH_B_ONLY | - LIBIPW_CH_PASSIVE_ONLY}}, - }, - - { /* High Band */ - "ZZH", - .bg_channels = 13, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, - {2467, 12, LIBIPW_CH_PASSIVE_ONLY}, - {2472, 13, LIBIPW_CH_PASSIVE_ONLY}}, - .a_channels = 4, - .a = {{5745, 149}, {5765, 153}, - {5785, 157}, {5805, 161}}, - }, - - { /* Custom Europe */ - "ZZG", - .bg_channels = 13, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, - {2467, 12}, {2472, 13}}, - .a_channels = 4, - .a = {{5180, 36}, {5200, 40}, - {5220, 44}, {5240, 48}}, - }, - - { /* Europe */ - "ZZK", - .bg_channels = 13, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}, - {2467, 12, LIBIPW_CH_PASSIVE_ONLY}, - {2472, 13, LIBIPW_CH_PASSIVE_ONLY}}, - .a_channels = 24, - .a = {{5180, 36, LIBIPW_CH_PASSIVE_ONLY}, - {5200, 40, LIBIPW_CH_PASSIVE_ONLY}, - {5220, 44, LIBIPW_CH_PASSIVE_ONLY}, - {5240, 48, LIBIPW_CH_PASSIVE_ONLY}, - {5260, 52, LIBIPW_CH_PASSIVE_ONLY}, - {5280, 56, LIBIPW_CH_PASSIVE_ONLY}, - {5300, 60, LIBIPW_CH_PASSIVE_ONLY}, - {5320, 64, LIBIPW_CH_PASSIVE_ONLY}, - {5500, 100, LIBIPW_CH_PASSIVE_ONLY}, - {5520, 104, LIBIPW_CH_PASSIVE_ONLY}, - {5540, 108, LIBIPW_CH_PASSIVE_ONLY}, - {5560, 112, LIBIPW_CH_PASSIVE_ONLY}, - {5580, 116, LIBIPW_CH_PASSIVE_ONLY}, - {5600, 120, LIBIPW_CH_PASSIVE_ONLY}, - {5620, 124, LIBIPW_CH_PASSIVE_ONLY}, - {5640, 128, LIBIPW_CH_PASSIVE_ONLY}, - {5660, 132, LIBIPW_CH_PASSIVE_ONLY}, - {5680, 136, LIBIPW_CH_PASSIVE_ONLY}, - {5700, 140, LIBIPW_CH_PASSIVE_ONLY}, - {5745, 149, LIBIPW_CH_PASSIVE_ONLY}, - {5765, 153, LIBIPW_CH_PASSIVE_ONLY}, - {5785, 157, LIBIPW_CH_PASSIVE_ONLY}, - {5805, 161, LIBIPW_CH_PASSIVE_ONLY}, - {5825, 165, LIBIPW_CH_PASSIVE_ONLY}}, - }, - - { /* Europe */ - "ZZL", - .bg_channels = 11, - .bg = {{2412, 1}, {2417, 2}, {2422, 3}, - {2427, 4}, {2432, 5}, {2437, 6}, - {2442, 7}, {2447, 8}, {2452, 9}, - {2457, 10}, {2462, 11}}, - .a_channels = 13, - .a = {{5180, 36, LIBIPW_CH_PASSIVE_ONLY}, - {5200, 40, LIBIPW_CH_PASSIVE_ONLY}, - {5220, 44, LIBIPW_CH_PASSIVE_ONLY}, - {5240, 48, LIBIPW_CH_PASSIVE_ONLY}, - {5260, 52, LIBIPW_CH_PASSIVE_ONLY}, - {5280, 56, LIBIPW_CH_PASSIVE_ONLY}, - {5300, 60, LIBIPW_CH_PASSIVE_ONLY}, - {5320, 64, LIBIPW_CH_PASSIVE_ONLY}, - {5745, 149, LIBIPW_CH_PASSIVE_ONLY}, - {5765, 153, LIBIPW_CH_PASSIVE_ONLY}, - {5785, 157, LIBIPW_CH_PASSIVE_ONLY}, - {5805, 161, LIBIPW_CH_PASSIVE_ONLY}, - {5825, 165, LIBIPW_CH_PASSIVE_ONLY}}, - } -}; - -#define MAX_HW_RESTARTS 5 -static int ipw_up(struct ipw_priv *priv) -{ - int rc, i, j; - - /* Age scan list entries found before suspend */ - if (priv->suspend_time) { - libipw_networks_age(priv->ieee, priv->suspend_time); - priv->suspend_time = 0; - } - - if (priv->status & STATUS_EXIT_PENDING) - return -EIO; - - if (cmdlog && !priv->cmdlog) { - priv->cmdlog = kcalloc(cmdlog, sizeof(*priv->cmdlog), - GFP_KERNEL); - if (priv->cmdlog == NULL) { - IPW_ERROR("Error allocating %d command log entries.\n", - cmdlog); - return -ENOMEM; - } else { - priv->cmdlog_len = cmdlog; - } - } - - for (i = 0; i < MAX_HW_RESTARTS; i++) { - /* Load the microcode, firmware, and eeprom. - * Also start the clocks. */ - rc = ipw_load(priv); - if (rc) { - IPW_ERROR("Unable to load firmware: %d\n", rc); - return rc; - } - - ipw_init_ordinals(priv); - if (!(priv->config & CFG_CUSTOM_MAC)) - eeprom_parse_mac(priv, priv->mac_addr); - memcpy(priv->net_dev->dev_addr, priv->mac_addr, ETH_ALEN); - - for (j = 0; j < ARRAY_SIZE(ipw_geos); j++) { - if (!memcmp(&priv->eeprom[EEPROM_COUNTRY_CODE], - ipw_geos[j].name, 3)) - break; - } - if (j == ARRAY_SIZE(ipw_geos)) { - IPW_WARNING("SKU [%c%c%c] not recognized.\n", - priv->eeprom[EEPROM_COUNTRY_CODE + 0], - priv->eeprom[EEPROM_COUNTRY_CODE + 1], - priv->eeprom[EEPROM_COUNTRY_CODE + 2]); - j = 0; - } - if (libipw_set_geo(priv->ieee, &ipw_geos[j])) { - IPW_WARNING("Could not set geography."); - return 0; - } - - if (priv->status & STATUS_RF_KILL_SW) { - IPW_WARNING("Radio disabled by module parameter.\n"); - return 0; - } else if (rf_kill_active(priv)) { - IPW_WARNING("Radio Frequency Kill Switch is On:\n" - "Kill switch must be turned off for " - "wireless networking to work.\n"); - queue_delayed_work(priv->workqueue, &priv->rf_kill, - 2 * HZ); - return 0; - } - - rc = ipw_config(priv); - if (!rc) { - IPW_DEBUG_INFO("Configured device on count %i\n", i); - - /* If configure to try and auto-associate, kick - * off a scan. */ - queue_delayed_work(priv->workqueue, - &priv->request_scan, 0); - - return 0; - } - - IPW_DEBUG_INFO("Device configuration failed: 0x%08X\n", rc); - IPW_DEBUG_INFO("Failed to config device on retry %d of %d\n", - i, MAX_HW_RESTARTS); - - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - ipw_down(priv); - } - - /* tried to restart and config the device for as long as our - * patience could withstand */ - IPW_ERROR("Unable to initialize device after %d attempts.\n", i); - - return -EIO; -} - -static void ipw_bg_up(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, up); - mutex_lock(&priv->mutex); - ipw_up(priv); - mutex_unlock(&priv->mutex); -} - -static void ipw_deinit(struct ipw_priv *priv) -{ - int i; - - if (priv->status & STATUS_SCANNING) { - IPW_DEBUG_INFO("Aborting scan during shutdown.\n"); - ipw_abort_scan(priv); - } - - if (priv->status & STATUS_ASSOCIATED) { - IPW_DEBUG_INFO("Disassociating during shutdown.\n"); - ipw_disassociate(priv); - } - - ipw_led_shutdown(priv); - - /* Wait up to 1s for status to change to not scanning and not - * associated (disassociation can take a while for a ful 802.11 - * exchange */ - for (i = 1000; i && (priv->status & - (STATUS_DISASSOCIATING | - STATUS_ASSOCIATED | STATUS_SCANNING)); i--) - udelay(10); - - if (priv->status & (STATUS_DISASSOCIATING | - STATUS_ASSOCIATED | STATUS_SCANNING)) - IPW_DEBUG_INFO("Still associated or scanning...\n"); - else - IPW_DEBUG_INFO("Took %dms to de-init\n", 1000 - i); - - /* Attempt to disable the card */ - ipw_send_card_disable(priv, 0); - - priv->status &= ~STATUS_INIT; -} - -static void ipw_down(struct ipw_priv *priv) -{ - int exit_pending = priv->status & STATUS_EXIT_PENDING; - - priv->status |= STATUS_EXIT_PENDING; - - if (ipw_is_init(priv)) - ipw_deinit(priv); - - /* Wipe out the EXIT_PENDING status bit if we are not actually - * exiting the module */ - if (!exit_pending) - priv->status &= ~STATUS_EXIT_PENDING; - - /* tell the device to stop sending interrupts */ - ipw_disable_interrupts(priv); - - /* Clear all bits but the RF Kill */ - priv->status &= STATUS_RF_KILL_MASK | STATUS_EXIT_PENDING; - netif_carrier_off(priv->net_dev); - - ipw_stop_nic(priv); - - ipw_led_radio_off(priv); -} - -static void ipw_bg_down(struct work_struct *work) -{ - struct ipw_priv *priv = - container_of(work, struct ipw_priv, down); - mutex_lock(&priv->mutex); - ipw_down(priv); - mutex_unlock(&priv->mutex); -} - -/* Called by register_netdev() */ -static int ipw_net_init(struct net_device *dev) -{ - struct ipw_priv *priv = libipw_priv(dev); - mutex_lock(&priv->mutex); - - if (ipw_up(priv)) { - mutex_unlock(&priv->mutex); - return -EIO; - } - - mutex_unlock(&priv->mutex); - return 0; -} - -/* PCI driver stuff */ -static struct pci_device_id card_ids[] = { - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2701, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2702, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2711, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2712, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2721, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2722, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2731, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2732, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2741, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x103c, 0x2741, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2742, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2751, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2752, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2753, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2754, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2761, 0, 0, 0}, - {PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, 0x2762, 0, 0, 0}, - {PCI_VDEVICE(INTEL, 0x104f), 0}, - {PCI_VDEVICE(INTEL, 0x4220), 0}, /* BG */ - {PCI_VDEVICE(INTEL, 0x4221), 0}, /* BG */ - {PCI_VDEVICE(INTEL, 0x4223), 0}, /* ABG */ - {PCI_VDEVICE(INTEL, 0x4224), 0}, /* ABG */ - - /* required last entry */ - {0,} -}; - -MODULE_DEVICE_TABLE(pci, card_ids); - -static struct attribute *ipw_sysfs_entries[] = { - &dev_attr_rf_kill.attr, - &dev_attr_direct_dword.attr, - &dev_attr_indirect_byte.attr, - &dev_attr_indirect_dword.attr, - &dev_attr_mem_gpio_reg.attr, - &dev_attr_command_event_reg.attr, - &dev_attr_nic_type.attr, - &dev_attr_status.attr, - &dev_attr_cfg.attr, - &dev_attr_error.attr, - &dev_attr_event_log.attr, - &dev_attr_cmd_log.attr, - &dev_attr_eeprom_delay.attr, - &dev_attr_ucode_version.attr, - &dev_attr_rtc.attr, - &dev_attr_scan_age.attr, - &dev_attr_led.attr, - &dev_attr_speed_scan.attr, - &dev_attr_net_stats.attr, - &dev_attr_channels.attr, -#ifdef CONFIG_IPW2200_PROMISCUOUS - &dev_attr_rtap_iface.attr, - &dev_attr_rtap_filter.attr, -#endif - NULL -}; - -static struct attribute_group ipw_attribute_group = { - .name = NULL, /* put in device directory */ - .attrs = ipw_sysfs_entries, -}; - -#ifdef CONFIG_IPW2200_PROMISCUOUS -static int ipw_prom_open(struct net_device *dev) -{ - struct ipw_prom_priv *prom_priv = libipw_priv(dev); - struct ipw_priv *priv = prom_priv->priv; - - IPW_DEBUG_INFO("prom dev->open\n"); - netif_carrier_off(dev); - - if (priv->ieee->iw_mode != IW_MODE_MONITOR) { - priv->sys_config.accept_all_data_frames = 1; - priv->sys_config.accept_non_directed_frames = 1; - priv->sys_config.accept_all_mgmt_bcpr = 1; - priv->sys_config.accept_all_mgmt_frames = 1; - - ipw_send_system_config(priv); - } - - return 0; -} - -static int ipw_prom_stop(struct net_device *dev) -{ - struct ipw_prom_priv *prom_priv = libipw_priv(dev); - struct ipw_priv *priv = prom_priv->priv; - - IPW_DEBUG_INFO("prom dev->stop\n"); - - if (priv->ieee->iw_mode != IW_MODE_MONITOR) { - priv->sys_config.accept_all_data_frames = 0; - priv->sys_config.accept_non_directed_frames = 0; - priv->sys_config.accept_all_mgmt_bcpr = 0; - priv->sys_config.accept_all_mgmt_frames = 0; - - ipw_send_system_config(priv); - } - - return 0; -} - -static netdev_tx_t ipw_prom_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - IPW_DEBUG_INFO("prom dev->xmit\n"); - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -static const struct net_device_ops ipw_prom_netdev_ops = { - .ndo_open = ipw_prom_open, - .ndo_stop = ipw_prom_stop, - .ndo_start_xmit = ipw_prom_hard_start_xmit, - .ndo_change_mtu = libipw_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static int ipw_prom_alloc(struct ipw_priv *priv) -{ - int rc = 0; - - if (priv->prom_net_dev) - return -EPERM; - - priv->prom_net_dev = alloc_ieee80211(sizeof(struct ipw_prom_priv)); - if (priv->prom_net_dev == NULL) - return -ENOMEM; - - priv->prom_priv = libipw_priv(priv->prom_net_dev); - priv->prom_priv->ieee = netdev_priv(priv->prom_net_dev); - priv->prom_priv->priv = priv; - - strcpy(priv->prom_net_dev->name, "rtap%d"); - memcpy(priv->prom_net_dev->dev_addr, priv->mac_addr, ETH_ALEN); - - priv->prom_net_dev->type = ARPHRD_IEEE80211_RADIOTAP; - priv->prom_net_dev->netdev_ops = &ipw_prom_netdev_ops; - - priv->prom_priv->ieee->iw_mode = IW_MODE_MONITOR; - SET_NETDEV_DEV(priv->prom_net_dev, &priv->pci_dev->dev); - - rc = register_netdev(priv->prom_net_dev); - if (rc) { - free_ieee80211(priv->prom_net_dev); - priv->prom_net_dev = NULL; - return rc; - } - - return 0; -} - -static void ipw_prom_free(struct ipw_priv *priv) -{ - if (!priv->prom_net_dev) - return; - - unregister_netdev(priv->prom_net_dev); - free_ieee80211(priv->prom_net_dev); - - priv->prom_net_dev = NULL; -} - -#endif - -static const struct net_device_ops ipw_netdev_ops = { - .ndo_init = ipw_net_init, - .ndo_open = ipw_net_open, - .ndo_stop = ipw_net_stop, - .ndo_set_multicast_list = ipw_net_set_multicast_list, - .ndo_set_mac_address = ipw_net_set_mac_address, - .ndo_start_xmit = libipw_xmit, - .ndo_change_mtu = libipw_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -static int __devinit ipw_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int err = 0; - struct net_device *net_dev; - void __iomem *base; - u32 length, val; - struct ipw_priv *priv; - int i; - - net_dev = alloc_ieee80211(sizeof(struct ipw_priv)); - if (net_dev == NULL) { - err = -ENOMEM; - goto out; - } - - priv = libipw_priv(net_dev); - priv->ieee = netdev_priv(net_dev); - - priv->net_dev = net_dev; - priv->pci_dev = pdev; - ipw_debug_level = debug; - spin_lock_init(&priv->irq_lock); - spin_lock_init(&priv->lock); - for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) - INIT_LIST_HEAD(&priv->ibss_mac_hash[i]); - - mutex_init(&priv->mutex); - if (pci_enable_device(pdev)) { - err = -ENODEV; - goto out_free_ieee80211; - } - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - printk(KERN_WARNING DRV_NAME ": No suitable DMA available.\n"); - goto out_pci_disable_device; - } - - pci_set_drvdata(pdev, priv); - - err = pci_request_regions(pdev, DRV_NAME); - if (err) - goto out_pci_disable_device; - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - length = pci_resource_len(pdev, 0); - priv->hw_len = length; - - base = pci_ioremap_bar(pdev, 0); - if (!base) { - err = -ENODEV; - goto out_pci_release_regions; - } - - priv->hw_base = base; - IPW_DEBUG_INFO("pci_resource_len = 0x%08x\n", length); - IPW_DEBUG_INFO("pci_resource_base = %p\n", base); - - err = ipw_setup_deferred_work(priv); - if (err) { - IPW_ERROR("Unable to setup deferred work\n"); - goto out_iounmap; - } - - ipw_sw_reset(priv, 1); - - err = request_irq(pdev->irq, ipw_isr, IRQF_SHARED, DRV_NAME, priv); - if (err) { - IPW_ERROR("Error allocating IRQ %d\n", pdev->irq); - goto out_destroy_workqueue; - } - - SET_NETDEV_DEV(net_dev, &pdev->dev); - - mutex_lock(&priv->mutex); - - priv->ieee->hard_start_xmit = ipw_net_hard_start_xmit; - priv->ieee->set_security = shim__set_security; - priv->ieee->is_queue_full = ipw_net_is_queue_full; - -#ifdef CONFIG_IPW2200_QOS - priv->ieee->is_qos_active = ipw_is_qos_active; - priv->ieee->handle_probe_response = ipw_handle_beacon; - priv->ieee->handle_beacon = ipw_handle_probe_response; - priv->ieee->handle_assoc_response = ipw_handle_assoc_response; -#endif /* CONFIG_IPW2200_QOS */ - - priv->ieee->perfect_rssi = -20; - priv->ieee->worst_rssi = -85; - - net_dev->netdev_ops = &ipw_netdev_ops; - priv->wireless_data.spy_data = &priv->ieee->spy_data; - net_dev->wireless_data = &priv->wireless_data; - net_dev->wireless_handlers = &ipw_wx_handler_def; - net_dev->ethtool_ops = &ipw_ethtool_ops; - net_dev->irq = pdev->irq; - net_dev->base_addr = (unsigned long)priv->hw_base; - net_dev->mem_start = pci_resource_start(pdev, 0); - net_dev->mem_end = net_dev->mem_start + pci_resource_len(pdev, 0) - 1; - - err = sysfs_create_group(&pdev->dev.kobj, &ipw_attribute_group); - if (err) { - IPW_ERROR("failed to create sysfs device attributes\n"); - mutex_unlock(&priv->mutex); - goto out_release_irq; - } - - mutex_unlock(&priv->mutex); - err = register_netdev(net_dev); - if (err) { - IPW_ERROR("failed to register network device\n"); - goto out_remove_sysfs; - } - -#ifdef CONFIG_IPW2200_PROMISCUOUS - if (rtap_iface) { - err = ipw_prom_alloc(priv); - if (err) { - IPW_ERROR("Failed to register promiscuous network " - "device (error %d).\n", err); - unregister_netdev(priv->net_dev); - goto out_remove_sysfs; - } - } -#endif - - printk(KERN_INFO DRV_NAME ": Detected geography %s (%d 802.11bg " - "channels, %d 802.11a channels)\n", - priv->ieee->geo.name, priv->ieee->geo.bg_channels, - priv->ieee->geo.a_channels); - - return 0; - - out_remove_sysfs: - sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); - out_release_irq: - free_irq(pdev->irq, priv); - out_destroy_workqueue: - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - out_iounmap: - iounmap(priv->hw_base); - out_pci_release_regions: - pci_release_regions(pdev); - out_pci_disable_device: - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - out_free_ieee80211: - free_ieee80211(priv->net_dev); - out: - return err; -} - -static void __devexit ipw_pci_remove(struct pci_dev *pdev) -{ - struct ipw_priv *priv = pci_get_drvdata(pdev); - struct list_head *p, *q; - int i; - - if (!priv) - return; - - mutex_lock(&priv->mutex); - - priv->status |= STATUS_EXIT_PENDING; - ipw_down(priv); - sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group); - - mutex_unlock(&priv->mutex); - - unregister_netdev(priv->net_dev); - - if (priv->rxq) { - ipw_rx_queue_free(priv, priv->rxq); - priv->rxq = NULL; - } - ipw_tx_queue_free(priv); - - if (priv->cmdlog) { - kfree(priv->cmdlog); - priv->cmdlog = NULL; - } - /* ipw_down will ensure that there is no more pending work - * in the workqueue's, so we can safely remove them now. */ - cancel_delayed_work(&priv->adhoc_check); - cancel_delayed_work(&priv->gather_stats); - cancel_delayed_work(&priv->request_scan); - cancel_delayed_work(&priv->request_direct_scan); - cancel_delayed_work(&priv->request_passive_scan); - cancel_delayed_work(&priv->scan_event); - cancel_delayed_work(&priv->rf_kill); - cancel_delayed_work(&priv->scan_check); - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - - /* Free MAC hash list for ADHOC */ - for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) { - list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) { - list_del(p); - kfree(list_entry(p, struct ipw_ibss_seq, list)); - } - } - - kfree(priv->error); - priv->error = NULL; - -#ifdef CONFIG_IPW2200_PROMISCUOUS - ipw_prom_free(priv); -#endif - - free_irq(pdev->irq, priv); - iounmap(priv->hw_base); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - free_ieee80211(priv->net_dev); - free_firmware(); -} - -#ifdef CONFIG_PM -static int ipw_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ipw_priv *priv = pci_get_drvdata(pdev); - struct net_device *dev = priv->net_dev; - - printk(KERN_INFO "%s: Going into suspend...\n", dev->name); - - /* Take down the device; powers it off, etc. */ - ipw_down(priv); - - /* Remove the PRESENT state of the device */ - netif_device_detach(dev); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - priv->suspend_at = get_seconds(); - - return 0; -} - -static int ipw_pci_resume(struct pci_dev *pdev) -{ - struct ipw_priv *priv = pci_get_drvdata(pdev); - struct net_device *dev = priv->net_dev; - int err; - u32 val; - - printk(KERN_INFO "%s: Coming out of suspend...\n", dev->name); - - pci_set_power_state(pdev, PCI_D0); - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s: pci_enable_device failed on resume\n", - dev->name); - return err; - } - pci_restore_state(pdev); - - /* - * Suspend/Resume resets the PCI configuration space, so we have to - * re-disable the RETRY_TIMEOUT register (0x41) to keep PCI Tx retries - * from interfering with C3 CPU state. pci_restore_state won't help - * here since it only restores the first 64 bytes pci config header. - */ - pci_read_config_dword(pdev, 0x40, &val); - if ((val & 0x0000ff00) != 0) - pci_write_config_dword(pdev, 0x40, val & 0xffff00ff); - - /* Set the device back into the PRESENT state; this will also wake - * the queue of needed */ - netif_device_attach(dev); - - priv->suspend_time = get_seconds() - priv->suspend_at; - - /* Bring the device back up */ - queue_work(priv->workqueue, &priv->up); - - return 0; -} -#endif - -static void ipw_pci_shutdown(struct pci_dev *pdev) -{ - struct ipw_priv *priv = pci_get_drvdata(pdev); - - /* Take down the device; powers it off, etc. */ - ipw_down(priv); - - pci_disable_device(pdev); -} - -/* driver initialization stuff */ -static struct pci_driver ipw_driver = { - .name = DRV_NAME, - .id_table = card_ids, - .probe = ipw_pci_probe, - .remove = __devexit_p(ipw_pci_remove), -#ifdef CONFIG_PM - .suspend = ipw_pci_suspend, - .resume = ipw_pci_resume, -#endif - .shutdown = ipw_pci_shutdown, -}; - -static int __init ipw_init(void) -{ - int ret; - - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); - - ret = pci_register_driver(&ipw_driver); - if (ret) { - IPW_ERROR("Unable to initialize PCI module\n"); - return ret; - } - - ret = driver_create_file(&ipw_driver.driver, &driver_attr_debug_level); - if (ret) { - IPW_ERROR("Unable to create driver sysfs file\n"); - pci_unregister_driver(&ipw_driver); - return ret; - } - - return ret; -} - -static void __exit ipw_exit(void) -{ - driver_remove_file(&ipw_driver.driver, &driver_attr_debug_level); - pci_unregister_driver(&ipw_driver); -} - -module_param(disable, int, 0444); -MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); - -module_param(associate, int, 0444); -MODULE_PARM_DESC(associate, "auto associate when scanning (default off)"); - -module_param(auto_create, int, 0444); -MODULE_PARM_DESC(auto_create, "auto create adhoc network (default on)"); - -module_param_named(led, led_support, int, 0444); -MODULE_PARM_DESC(led, "enable led control on some systems (default 0 off)"); - -module_param(debug, int, 0444); -MODULE_PARM_DESC(debug, "debug output mask"); - -module_param_named(channel, default_channel, int, 0444); -MODULE_PARM_DESC(channel, "channel to limit associate to (default 0 [ANY])"); - -#ifdef CONFIG_IPW2200_PROMISCUOUS -module_param(rtap_iface, int, 0444); -MODULE_PARM_DESC(rtap_iface, "create the rtap interface (1 - create, default 0)"); -#endif - -#ifdef CONFIG_IPW2200_QOS -module_param(qos_enable, int, 0444); -MODULE_PARM_DESC(qos_enable, "enable all QoS functionalitis"); - -module_param(qos_burst_enable, int, 0444); -MODULE_PARM_DESC(qos_burst_enable, "enable QoS burst mode"); - -module_param(qos_no_ack_mask, int, 0444); -MODULE_PARM_DESC(qos_no_ack_mask, "mask Tx_Queue to no ack"); - -module_param(burst_duration_CCK, int, 0444); -MODULE_PARM_DESC(burst_duration_CCK, "set CCK burst value"); - -module_param(burst_duration_OFDM, int, 0444); -MODULE_PARM_DESC(burst_duration_OFDM, "set OFDM burst value"); -#endif /* CONFIG_IPW2200_QOS */ - -#ifdef CONFIG_IPW2200_MONITOR -module_param_named(mode, network_mode, int, 0444); -MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS,2=Monitor)"); -#else -module_param_named(mode, network_mode, int, 0444); -MODULE_PARM_DESC(mode, "network mode (0=BSS,1=IBSS)"); -#endif - -module_param(bt_coexist, int, 0444); -MODULE_PARM_DESC(bt_coexist, "enable bluetooth coexistence (default off)"); - -module_param(hwcrypto, int, 0444); -MODULE_PARM_DESC(hwcrypto, "enable hardware crypto (default off)"); - -module_param(cmdlog, int, 0444); -MODULE_PARM_DESC(cmdlog, - "allocate a ring buffer for logging firmware commands"); - -module_param(roaming, int, 0444); -MODULE_PARM_DESC(roaming, "enable roaming support (default on)"); - -module_param(antenna, int, 0444); -MODULE_PARM_DESC(antenna, "select antenna 1=Main, 3=Aux, default 0 [both], 2=slow_diversity (choose the one with lower background noise)"); - -module_exit(ipw_exit); -module_init(ipw_init); diff --git a/drivers/net/wireless/ipw2x00/ipw2200.h b/drivers/net/wireless/ipw2x00/ipw2200.h deleted file mode 100644 index bf0eeb2e873a..000000000000 --- a/drivers/net/wireless/ipw2x00/ipw2200.h +++ /dev/null @@ -1,2017 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2006 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -******************************************************************************/ - -#ifndef __ipw2200_h__ -#define __ipw2200_h__ - -#define WEXT_USECHANNELS 1 - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#define DRV_NAME "ipw2200" - -#include - -#include "libipw.h" - -/* Authentication and Association States */ -enum connection_manager_assoc_states { - CMAS_INIT = 0, - CMAS_TX_AUTH_SEQ_1, - CMAS_RX_AUTH_SEQ_2, - CMAS_AUTH_SEQ_1_PASS, - CMAS_AUTH_SEQ_1_FAIL, - CMAS_TX_AUTH_SEQ_3, - CMAS_RX_AUTH_SEQ_4, - CMAS_AUTH_SEQ_2_PASS, - CMAS_AUTH_SEQ_2_FAIL, - CMAS_AUTHENTICATED, - CMAS_TX_ASSOC, - CMAS_RX_ASSOC_RESP, - CMAS_ASSOCIATED, - CMAS_LAST -}; - -#define IPW_WAIT (1<<0) -#define IPW_QUIET (1<<1) -#define IPW_ROAMING (1<<2) - -#define IPW_POWER_MODE_CAM 0x00 //(always on) -#define IPW_POWER_INDEX_1 0x01 -#define IPW_POWER_INDEX_2 0x02 -#define IPW_POWER_INDEX_3 0x03 -#define IPW_POWER_INDEX_4 0x04 -#define IPW_POWER_INDEX_5 0x05 -#define IPW_POWER_AC 0x06 -#define IPW_POWER_BATTERY 0x07 -#define IPW_POWER_LIMIT 0x07 -#define IPW_POWER_MASK 0x0F -#define IPW_POWER_ENABLED 0x10 -#define IPW_POWER_LEVEL(x) ((x) & IPW_POWER_MASK) - -#define IPW_CMD_HOST_COMPLETE 2 -#define IPW_CMD_POWER_DOWN 4 -#define IPW_CMD_SYSTEM_CONFIG 6 -#define IPW_CMD_MULTICAST_ADDRESS 7 -#define IPW_CMD_SSID 8 -#define IPW_CMD_ADAPTER_ADDRESS 11 -#define IPW_CMD_PORT_TYPE 12 -#define IPW_CMD_RTS_THRESHOLD 15 -#define IPW_CMD_FRAG_THRESHOLD 16 -#define IPW_CMD_POWER_MODE 17 -#define IPW_CMD_WEP_KEY 18 -#define IPW_CMD_TGI_TX_KEY 19 -#define IPW_CMD_SCAN_REQUEST 20 -#define IPW_CMD_ASSOCIATE 21 -#define IPW_CMD_SUPPORTED_RATES 22 -#define IPW_CMD_SCAN_ABORT 23 -#define IPW_CMD_TX_FLUSH 24 -#define IPW_CMD_QOS_PARAMETERS 25 -#define IPW_CMD_SCAN_REQUEST_EXT 26 -#define IPW_CMD_DINO_CONFIG 30 -#define IPW_CMD_RSN_CAPABILITIES 31 -#define IPW_CMD_RX_KEY 32 -#define IPW_CMD_CARD_DISABLE 33 -#define IPW_CMD_SEED_NUMBER 34 -#define IPW_CMD_TX_POWER 35 -#define IPW_CMD_COUNTRY_INFO 36 -#define IPW_CMD_AIRONET_INFO 37 -#define IPW_CMD_AP_TX_POWER 38 -#define IPW_CMD_CCKM_INFO 39 -#define IPW_CMD_CCX_VER_INFO 40 -#define IPW_CMD_SET_CALIBRATION 41 -#define IPW_CMD_SENSITIVITY_CALIB 42 -#define IPW_CMD_RETRY_LIMIT 51 -#define IPW_CMD_IPW_PRE_POWER_DOWN 58 -#define IPW_CMD_VAP_BEACON_TEMPLATE 60 -#define IPW_CMD_VAP_DTIM_PERIOD 61 -#define IPW_CMD_EXT_SUPPORTED_RATES 62 -#define IPW_CMD_VAP_LOCAL_TX_PWR_CONSTRAINT 63 -#define IPW_CMD_VAP_QUIET_INTERVALS 64 -#define IPW_CMD_VAP_CHANNEL_SWITCH 65 -#define IPW_CMD_VAP_MANDATORY_CHANNELS 66 -#define IPW_CMD_VAP_CELL_PWR_LIMIT 67 -#define IPW_CMD_VAP_CF_PARAM_SET 68 -#define IPW_CMD_VAP_SET_BEACONING_STATE 69 -#define IPW_CMD_MEASUREMENT 80 -#define IPW_CMD_POWER_CAPABILITY 81 -#define IPW_CMD_SUPPORTED_CHANNELS 82 -#define IPW_CMD_TPC_REPORT 83 -#define IPW_CMD_WME_INFO 84 -#define IPW_CMD_PRODUCTION_COMMAND 85 -#define IPW_CMD_LINKSYS_EOU_INFO 90 - -#define RFD_SIZE 4 -#define NUM_TFD_CHUNKS 6 - -#define TX_QUEUE_SIZE 32 -#define RX_QUEUE_SIZE 32 - -#define DINO_CMD_WEP_KEY 0x08 -#define DINO_CMD_TX 0x0B -#define DCT_ANTENNA_A 0x01 -#define DCT_ANTENNA_B 0x02 - -#define IPW_A_MODE 0 -#define IPW_B_MODE 1 -#define IPW_G_MODE 2 - -/* - * TX Queue Flag Definitions - */ - -/* tx wep key definition */ -#define DCT_WEP_KEY_NOT_IMMIDIATE 0x00 -#define DCT_WEP_KEY_64Bit 0x40 -#define DCT_WEP_KEY_128Bit 0x80 -#define DCT_WEP_KEY_128bitIV 0xC0 -#define DCT_WEP_KEY_SIZE_MASK 0xC0 - -#define DCT_WEP_KEY_INDEX_MASK 0x0F -#define DCT_WEP_INDEX_USE_IMMEDIATE 0x20 - -/* abort attempt if mgmt frame is rx'd */ -#define DCT_FLAG_ABORT_MGMT 0x01 - -/* require CTS */ -#define DCT_FLAG_CTS_REQUIRED 0x02 - -/* use short preamble */ -#define DCT_FLAG_LONG_PREAMBLE 0x00 -#define DCT_FLAG_SHORT_PREAMBLE 0x04 - -/* RTS/CTS first */ -#define DCT_FLAG_RTS_REQD 0x08 - -/* dont calculate duration field */ -#define DCT_FLAG_DUR_SET 0x10 - -/* even if MAC WEP set (allows pre-encrypt) */ -#define DCT_FLAG_NO_WEP 0x20 - -/* overwrite TSF field */ -#define DCT_FLAG_TSF_REQD 0x40 - -/* ACK rx is expected to follow */ -#define DCT_FLAG_ACK_REQD 0x80 - -/* TX flags extension */ -#define DCT_FLAG_EXT_MODE_CCK 0x01 -#define DCT_FLAG_EXT_MODE_OFDM 0x00 - -#define DCT_FLAG_EXT_SECURITY_WEP 0x00 -#define DCT_FLAG_EXT_SECURITY_NO DCT_FLAG_EXT_SECURITY_WEP -#define DCT_FLAG_EXT_SECURITY_CKIP 0x04 -#define DCT_FLAG_EXT_SECURITY_CCM 0x08 -#define DCT_FLAG_EXT_SECURITY_TKIP 0x0C -#define DCT_FLAG_EXT_SECURITY_MASK 0x0C - -#define DCT_FLAG_EXT_QOS_ENABLED 0x10 - -#define DCT_FLAG_EXT_HC_NO_SIFS_PIFS 0x00 -#define DCT_FLAG_EXT_HC_SIFS 0x20 -#define DCT_FLAG_EXT_HC_PIFS 0x40 - -#define TX_RX_TYPE_MASK 0xFF -#define TX_FRAME_TYPE 0x00 -#define TX_HOST_COMMAND_TYPE 0x01 -#define RX_FRAME_TYPE 0x09 -#define RX_HOST_NOTIFICATION_TYPE 0x03 -#define RX_HOST_CMD_RESPONSE_TYPE 0x04 -#define RX_TX_FRAME_RESPONSE_TYPE 0x05 -#define TFD_NEED_IRQ_MASK 0x04 - -#define HOST_CMD_DINO_CONFIG 30 - -#define HOST_NOTIFICATION_STATUS_ASSOCIATED 10 -#define HOST_NOTIFICATION_STATUS_AUTHENTICATE 11 -#define HOST_NOTIFICATION_STATUS_SCAN_CHANNEL_RESULT 12 -#define HOST_NOTIFICATION_STATUS_SCAN_COMPLETED 13 -#define HOST_NOTIFICATION_STATUS_FRAG_LENGTH 14 -#define HOST_NOTIFICATION_STATUS_LINK_DETERIORATION 15 -#define HOST_NOTIFICATION_DINO_CONFIG_RESPONSE 16 -#define HOST_NOTIFICATION_STATUS_BEACON_STATE 17 -#define HOST_NOTIFICATION_STATUS_TGI_TX_KEY 18 -#define HOST_NOTIFICATION_TX_STATUS 19 -#define HOST_NOTIFICATION_CALIB_KEEP_RESULTS 20 -#define HOST_NOTIFICATION_MEASUREMENT_STARTED 21 -#define HOST_NOTIFICATION_MEASUREMENT_ENDED 22 -#define HOST_NOTIFICATION_CHANNEL_SWITCHED 23 -#define HOST_NOTIFICATION_RX_DURING_QUIET_PERIOD 24 -#define HOST_NOTIFICATION_NOISE_STATS 25 -#define HOST_NOTIFICATION_S36_MEASUREMENT_ACCEPTED 30 -#define HOST_NOTIFICATION_S36_MEASUREMENT_REFUSED 31 - -#define HOST_NOTIFICATION_STATUS_BEACON_MISSING 1 -#define IPW_MB_SCAN_CANCEL_THRESHOLD 3 -#define IPW_MB_ROAMING_THRESHOLD_MIN 1 -#define IPW_MB_ROAMING_THRESHOLD_DEFAULT 8 -#define IPW_MB_ROAMING_THRESHOLD_MAX 30 -#define IPW_MB_DISASSOCIATE_THRESHOLD_DEFAULT 3*IPW_MB_ROAMING_THRESHOLD_DEFAULT -#define IPW_REAL_RATE_RX_PACKET_THRESHOLD 300 - -#define MACADRR_BYTE_LEN 6 - -#define DCR_TYPE_AP 0x01 -#define DCR_TYPE_WLAP 0x02 -#define DCR_TYPE_MU_ESS 0x03 -#define DCR_TYPE_MU_IBSS 0x04 -#define DCR_TYPE_MU_PIBSS 0x05 -#define DCR_TYPE_SNIFFER 0x06 -#define DCR_TYPE_MU_BSS DCR_TYPE_MU_ESS - -/* QoS definitions */ - -#define CW_MIN_OFDM 15 -#define CW_MAX_OFDM 1023 -#define CW_MIN_CCK 31 -#define CW_MAX_CCK 1023 - -#define QOS_TX0_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) -#define QOS_TX1_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) -#define QOS_TX2_CW_MIN_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/2 - 1) -#define QOS_TX3_CW_MIN_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/4 - 1) - -#define QOS_TX0_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) -#define QOS_TX1_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) -#define QOS_TX2_CW_MIN_CCK cpu_to_le16((CW_MIN_CCK + 1)/2 - 1) -#define QOS_TX3_CW_MIN_CCK cpu_to_le16((CW_MIN_CCK + 1)/4 - 1) - -#define QOS_TX0_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) -#define QOS_TX1_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) -#define QOS_TX2_CW_MAX_OFDM cpu_to_le16(CW_MIN_OFDM) -#define QOS_TX3_CW_MAX_OFDM cpu_to_le16((CW_MIN_OFDM + 1)/2 - 1) - -#define QOS_TX0_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) -#define QOS_TX1_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) -#define QOS_TX2_CW_MAX_CCK cpu_to_le16(CW_MIN_CCK) -#define QOS_TX3_CW_MAX_CCK cpu_to_le16((CW_MIN_CCK + 1)/2 - 1) - -#define QOS_TX0_AIFS (3 - QOS_AIFSN_MIN_VALUE) -#define QOS_TX1_AIFS (7 - QOS_AIFSN_MIN_VALUE) -#define QOS_TX2_AIFS (2 - QOS_AIFSN_MIN_VALUE) -#define QOS_TX3_AIFS (2 - QOS_AIFSN_MIN_VALUE) - -#define QOS_TX0_ACM 0 -#define QOS_TX1_ACM 0 -#define QOS_TX2_ACM 0 -#define QOS_TX3_ACM 0 - -#define QOS_TX0_TXOP_LIMIT_CCK 0 -#define QOS_TX1_TXOP_LIMIT_CCK 0 -#define QOS_TX2_TXOP_LIMIT_CCK cpu_to_le16(6016) -#define QOS_TX3_TXOP_LIMIT_CCK cpu_to_le16(3264) - -#define QOS_TX0_TXOP_LIMIT_OFDM 0 -#define QOS_TX1_TXOP_LIMIT_OFDM 0 -#define QOS_TX2_TXOP_LIMIT_OFDM cpu_to_le16(3008) -#define QOS_TX3_TXOP_LIMIT_OFDM cpu_to_le16(1504) - -#define DEF_TX0_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) -#define DEF_TX1_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) -#define DEF_TX2_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) -#define DEF_TX3_CW_MIN_OFDM cpu_to_le16(CW_MIN_OFDM) - -#define DEF_TX0_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) -#define DEF_TX1_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) -#define DEF_TX2_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) -#define DEF_TX3_CW_MIN_CCK cpu_to_le16(CW_MIN_CCK) - -#define DEF_TX0_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) -#define DEF_TX1_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) -#define DEF_TX2_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) -#define DEF_TX3_CW_MAX_OFDM cpu_to_le16(CW_MAX_OFDM) - -#define DEF_TX0_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) -#define DEF_TX1_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) -#define DEF_TX2_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) -#define DEF_TX3_CW_MAX_CCK cpu_to_le16(CW_MAX_CCK) - -#define DEF_TX0_AIFS 0 -#define DEF_TX1_AIFS 0 -#define DEF_TX2_AIFS 0 -#define DEF_TX3_AIFS 0 - -#define DEF_TX0_ACM 0 -#define DEF_TX1_ACM 0 -#define DEF_TX2_ACM 0 -#define DEF_TX3_ACM 0 - -#define DEF_TX0_TXOP_LIMIT_CCK 0 -#define DEF_TX1_TXOP_LIMIT_CCK 0 -#define DEF_TX2_TXOP_LIMIT_CCK 0 -#define DEF_TX3_TXOP_LIMIT_CCK 0 - -#define DEF_TX0_TXOP_LIMIT_OFDM 0 -#define DEF_TX1_TXOP_LIMIT_OFDM 0 -#define DEF_TX2_TXOP_LIMIT_OFDM 0 -#define DEF_TX3_TXOP_LIMIT_OFDM 0 - -#define QOS_QOS_SETS 3 -#define QOS_PARAM_SET_ACTIVE 0 -#define QOS_PARAM_SET_DEF_CCK 1 -#define QOS_PARAM_SET_DEF_OFDM 2 - -#define CTRL_QOS_NO_ACK (0x0020) - -#define IPW_TX_QUEUE_1 1 -#define IPW_TX_QUEUE_2 2 -#define IPW_TX_QUEUE_3 3 -#define IPW_TX_QUEUE_4 4 - -/* QoS sturctures */ -struct ipw_qos_info { - int qos_enable; - struct libipw_qos_parameters *def_qos_parm_OFDM; - struct libipw_qos_parameters *def_qos_parm_CCK; - u32 burst_duration_CCK; - u32 burst_duration_OFDM; - u16 qos_no_ack_mask; - int burst_enable; -}; - -/**************************************************************/ -/** - * Generic queue structure - * - * Contains common data for Rx and Tx queues - */ -struct clx2_queue { - int n_bd; /**< number of BDs in this queue */ - int first_empty; /**< 1-st empty entry (index) */ - int last_used; /**< last used entry (index) */ - u32 reg_w; /**< 'write' reg (queue head), addr in domain 1 */ - u32 reg_r; /**< 'read' reg (queue tail), addr in domain 1 */ - dma_addr_t dma_addr; /**< physical addr for BD's */ - int low_mark; /**< low watermark, resume queue if free space more than this */ - int high_mark; /**< high watermark, stop queue if free space less than this */ -} __attribute__ ((packed)); /* XXX */ - -struct machdr32 { - __le16 frame_ctl; - __le16 duration; // watch out for endians! - u8 addr1[MACADRR_BYTE_LEN]; - u8 addr2[MACADRR_BYTE_LEN]; - u8 addr3[MACADRR_BYTE_LEN]; - __le16 seq_ctrl; // more endians! - u8 addr4[MACADRR_BYTE_LEN]; - __le16 qos_ctrl; -} __attribute__ ((packed)); - -struct machdr30 { - __le16 frame_ctl; - __le16 duration; // watch out for endians! - u8 addr1[MACADRR_BYTE_LEN]; - u8 addr2[MACADRR_BYTE_LEN]; - u8 addr3[MACADRR_BYTE_LEN]; - __le16 seq_ctrl; // more endians! - u8 addr4[MACADRR_BYTE_LEN]; -} __attribute__ ((packed)); - -struct machdr26 { - __le16 frame_ctl; - __le16 duration; // watch out for endians! - u8 addr1[MACADRR_BYTE_LEN]; - u8 addr2[MACADRR_BYTE_LEN]; - u8 addr3[MACADRR_BYTE_LEN]; - __le16 seq_ctrl; // more endians! - __le16 qos_ctrl; -} __attribute__ ((packed)); - -struct machdr24 { - __le16 frame_ctl; - __le16 duration; // watch out for endians! - u8 addr1[MACADRR_BYTE_LEN]; - u8 addr2[MACADRR_BYTE_LEN]; - u8 addr3[MACADRR_BYTE_LEN]; - __le16 seq_ctrl; // more endians! -} __attribute__ ((packed)); - -// TX TFD with 32 byte MAC Header -struct tx_tfd_32 { - struct machdr32 mchdr; // 32 - __le32 uivplaceholder[2]; // 8 -} __attribute__ ((packed)); - -// TX TFD with 30 byte MAC Header -struct tx_tfd_30 { - struct machdr30 mchdr; // 30 - u8 reserved[2]; // 2 - __le32 uivplaceholder[2]; // 8 -} __attribute__ ((packed)); - -// tx tfd with 26 byte mac header -struct tx_tfd_26 { - struct machdr26 mchdr; // 26 - u8 reserved1[2]; // 2 - __le32 uivplaceholder[2]; // 8 - u8 reserved2[4]; // 4 -} __attribute__ ((packed)); - -// tx tfd with 24 byte mac header -struct tx_tfd_24 { - struct machdr24 mchdr; // 24 - __le32 uivplaceholder[2]; // 8 - u8 reserved[8]; // 8 -} __attribute__ ((packed)); - -#define DCT_WEP_KEY_FIELD_LENGTH 16 - -struct tfd_command { - u8 index; - u8 length; - __le16 reserved; - u8 payload[0]; -} __attribute__ ((packed)); - -struct tfd_data { - /* Header */ - __le32 work_area_ptr; - u8 station_number; /* 0 for BSS */ - u8 reserved1; - __le16 reserved2; - - /* Tx Parameters */ - u8 cmd_id; - u8 seq_num; - __le16 len; - u8 priority; - u8 tx_flags; - u8 tx_flags_ext; - u8 key_index; - u8 wepkey[DCT_WEP_KEY_FIELD_LENGTH]; - u8 rate; - u8 antenna; - __le16 next_packet_duration; - __le16 next_frag_len; - __le16 back_off_counter; //////txop; - u8 retrylimit; - __le16 cwcurrent; - u8 reserved3; - - /* 802.11 MAC Header */ - union { - struct tx_tfd_24 tfd_24; - struct tx_tfd_26 tfd_26; - struct tx_tfd_30 tfd_30; - struct tx_tfd_32 tfd_32; - } tfd; - - /* Payload DMA info */ - __le32 num_chunks; - __le32 chunk_ptr[NUM_TFD_CHUNKS]; - __le16 chunk_len[NUM_TFD_CHUNKS]; -} __attribute__ ((packed)); - -struct txrx_control_flags { - u8 message_type; - u8 rx_seq_num; - u8 control_bits; - u8 reserved; -} __attribute__ ((packed)); - -#define TFD_SIZE 128 -#define TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH (TFD_SIZE - sizeof(struct txrx_control_flags)) - -struct tfd_frame { - struct txrx_control_flags control_flags; - union { - struct tfd_data data; - struct tfd_command cmd; - u8 raw[TFD_CMD_IMMEDIATE_PAYLOAD_LENGTH]; - } u; -} __attribute__ ((packed)); - -typedef void destructor_func(const void *); - -/** - * Tx Queue for DMA. Queue consists of circular buffer of - * BD's and required locking structures. - */ -struct clx2_tx_queue { - struct clx2_queue q; - struct tfd_frame *bd; - struct libipw_txb **txb; -}; - -/* - * RX related structures and functions - */ -#define RX_FREE_BUFFERS 32 -#define RX_LOW_WATERMARK 8 - -#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 -#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 -#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 - -// Used for passing to driver number of successes and failures per rate -struct rate_histogram { - union { - __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } success; - union { - __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } failed; -} __attribute__ ((packed)); - -/* statistics command response */ -struct ipw_cmd_stats { - u8 cmd_id; - u8 seq_num; - __le16 good_sfd; - __le16 bad_plcp; - __le16 wrong_bssid; - __le16 valid_mpdu; - __le16 bad_mac_header; - __le16 reserved_frame_types; - __le16 rx_ina; - __le16 bad_crc32; - __le16 invalid_cts; - __le16 invalid_acks; - __le16 long_distance_ina_fina; - __le16 dsp_silence_unreachable; - __le16 accumulated_rssi; - __le16 rx_ovfl_frame_tossed; - __le16 rssi_silence_threshold; - __le16 rx_ovfl_frame_supplied; - __le16 last_rx_frame_signal; - __le16 last_rx_frame_noise; - __le16 rx_autodetec_no_ofdm; - __le16 rx_autodetec_no_barker; - __le16 reserved; -} __attribute__ ((packed)); - -struct notif_channel_result { - u8 channel_num; - struct ipw_cmd_stats stats; - u8 uReserved; -} __attribute__ ((packed)); - -#define SCAN_COMPLETED_STATUS_COMPLETE 1 -#define SCAN_COMPLETED_STATUS_ABORTED 2 - -struct notif_scan_complete { - u8 scan_type; - u8 num_channels; - u8 status; - u8 reserved; -} __attribute__ ((packed)); - -struct notif_frag_length { - __le16 frag_length; - __le16 reserved; -} __attribute__ ((packed)); - -struct notif_beacon_state { - __le32 state; - __le32 number; -} __attribute__ ((packed)); - -struct notif_tgi_tx_key { - u8 key_state; - u8 security_type; - u8 station_index; - u8 reserved; -} __attribute__ ((packed)); - -#define SILENCE_OVER_THRESH (1) -#define SILENCE_UNDER_THRESH (2) - -struct notif_link_deterioration { - struct ipw_cmd_stats stats; - u8 rate; - u8 modulation; - struct rate_histogram histogram; - u8 silence_notification_type; /* SILENCE_OVER/UNDER_THRESH */ - __le16 silence_count; -} __attribute__ ((packed)); - -struct notif_association { - u8 state; -} __attribute__ ((packed)); - -struct notif_authenticate { - u8 state; - struct machdr24 addr; - __le16 status; -} __attribute__ ((packed)); - -struct notif_calibration { - u8 data[104]; -} __attribute__ ((packed)); - -struct notif_noise { - __le32 value; -} __attribute__ ((packed)); - -struct ipw_rx_notification { - u8 reserved[8]; - u8 subtype; - u8 flags; - __le16 size; - union { - struct notif_association assoc; - struct notif_authenticate auth; - struct notif_channel_result channel_result; - struct notif_scan_complete scan_complete; - struct notif_frag_length frag_len; - struct notif_beacon_state beacon_state; - struct notif_tgi_tx_key tgi_tx_key; - struct notif_link_deterioration link_deterioration; - struct notif_calibration calibration; - struct notif_noise noise; - u8 raw[0]; - } u; -} __attribute__ ((packed)); - -struct ipw_rx_frame { - __le32 reserved1; - u8 parent_tsf[4]; // fw_use[0] is boolean for OUR_TSF_IS_GREATER - u8 received_channel; // The channel that this frame was received on. - // Note that for .11b this does not have to be - // the same as the channel that it was sent. - // Filled by LMAC - u8 frameStatus; - u8 rate; - u8 rssi; - u8 agc; - u8 rssi_dbm; - __le16 signal; - __le16 noise; - u8 antennaAndPhy; - u8 control; // control bit should be on in bg - u8 rtscts_rate; // rate of rts or cts (in rts cts sequence rate - // is identical) - u8 rtscts_seen; // 0x1 RTS seen ; 0x2 CTS seen - __le16 length; - u8 data[0]; -} __attribute__ ((packed)); - -struct ipw_rx_header { - u8 message_type; - u8 rx_seq_num; - u8 control_bits; - u8 reserved; -} __attribute__ ((packed)); - -struct ipw_rx_packet { - struct ipw_rx_header header; - union { - struct ipw_rx_frame frame; - struct ipw_rx_notification notification; - } u; -} __attribute__ ((packed)); - -#define IPW_RX_NOTIFICATION_SIZE sizeof(struct ipw_rx_header) + 12 -#define IPW_RX_FRAME_SIZE (unsigned int)(sizeof(struct ipw_rx_header) + \ - sizeof(struct ipw_rx_frame)) - -struct ipw_rx_mem_buffer { - dma_addr_t dma_addr; - struct sk_buff *skb; - struct list_head list; -}; /* Not transferred over network, so not __attribute__ ((packed)) */ - -struct ipw_rx_queue { - struct ipw_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct ipw_rx_mem_buffer *queue[RX_QUEUE_SIZE]; - u32 processed; /* Internal index to last handled Rx packet */ - u32 read; /* Shared index to newest available Rx buffer */ - u32 write; /* Shared index to oldest written Rx packet */ - u32 free_count; /* Number of pre-allocated buffers in rx_free */ - /* Each of these lists is used as a FIFO for ipw_rx_mem_buffers */ - struct list_head rx_free; /* Own an SKBs */ - struct list_head rx_used; /* No SKB allocated */ - spinlock_t lock; -}; /* Not transferred over network, so not __attribute__ ((packed)) */ - -struct alive_command_responce { - u8 alive_command; - u8 sequence_number; - __le16 software_revision; - u8 device_identifier; - u8 reserved1[5]; - __le16 reserved2; - __le16 reserved3; - __le16 clock_settle_time; - __le16 powerup_settle_time; - __le16 reserved4; - u8 time_stamp[5]; /* month, day, year, hours, minutes */ - u8 ucode_valid; -} __attribute__ ((packed)); - -#define IPW_MAX_RATES 12 - -struct ipw_rates { - u8 num_rates; - u8 rates[IPW_MAX_RATES]; -} __attribute__ ((packed)); - -struct command_block { - unsigned int control; - u32 source_addr; - u32 dest_addr; - unsigned int status; -} __attribute__ ((packed)); - -#define CB_NUMBER_OF_ELEMENTS_SMALL 64 -struct fw_image_desc { - unsigned long last_cb_index; - unsigned long current_cb_index; - struct command_block cb_list[CB_NUMBER_OF_ELEMENTS_SMALL]; - void *v_addr; - unsigned long p_addr; - unsigned long len; -}; - -struct ipw_sys_config { - u8 bt_coexistence; - u8 reserved1; - u8 answer_broadcast_ssid_probe; - u8 accept_all_data_frames; - u8 accept_non_directed_frames; - u8 exclude_unicast_unencrypted; - u8 disable_unicast_decryption; - u8 exclude_multicast_unencrypted; - u8 disable_multicast_decryption; - u8 antenna_diversity; - u8 pass_crc_to_host; - u8 dot11g_auto_detection; - u8 enable_cts_to_self; - u8 enable_multicast_filtering; - u8 bt_coexist_collision_thr; - u8 silence_threshold; - u8 accept_all_mgmt_bcpr; - u8 accept_all_mgmt_frames; - u8 pass_noise_stats_to_host; - u8 reserved3; -} __attribute__ ((packed)); - -struct ipw_multicast_addr { - u8 num_of_multicast_addresses; - u8 reserved[3]; - u8 mac1[6]; - u8 mac2[6]; - u8 mac3[6]; - u8 mac4[6]; -} __attribute__ ((packed)); - -#define DCW_WEP_KEY_INDEX_MASK 0x03 /* bits [0:1] */ -#define DCW_WEP_KEY_SEC_TYPE_MASK 0x30 /* bits [4:5] */ - -#define DCW_WEP_KEY_SEC_TYPE_WEP 0x00 -#define DCW_WEP_KEY_SEC_TYPE_CCM 0x20 -#define DCW_WEP_KEY_SEC_TYPE_TKIP 0x30 - -#define DCW_WEP_KEY_INVALID_SIZE 0x00 /* 0 = Invalid key */ -#define DCW_WEP_KEY64Bit_SIZE 0x05 /* 64-bit encryption */ -#define DCW_WEP_KEY128Bit_SIZE 0x0D /* 128-bit encryption */ -#define DCW_CCM_KEY128Bit_SIZE 0x10 /* 128-bit key */ -//#define DCW_WEP_KEY128BitIV_SIZE 0x10 /* 128-bit key and 128-bit IV */ - -struct ipw_wep_key { - u8 cmd_id; - u8 seq_num; - u8 key_index; - u8 key_size; - u8 key[16]; -} __attribute__ ((packed)); - -struct ipw_tgi_tx_key { - u8 key_id; - u8 security_type; - u8 station_index; - u8 flags; - u8 key[16]; - __le32 tx_counter[2]; -} __attribute__ ((packed)); - -#define IPW_SCAN_CHANNELS 54 - -struct ipw_scan_request { - u8 scan_type; - __le16 dwell_time; - u8 channels_list[IPW_SCAN_CHANNELS]; - u8 channels_reserved[3]; -} __attribute__ ((packed)); - -enum { - IPW_SCAN_PASSIVE_TILL_FIRST_BEACON_SCAN = 0, - IPW_SCAN_PASSIVE_FULL_DWELL_SCAN, - IPW_SCAN_ACTIVE_DIRECT_SCAN, - IPW_SCAN_ACTIVE_BROADCAST_SCAN, - IPW_SCAN_ACTIVE_BROADCAST_AND_DIRECT_SCAN, - IPW_SCAN_TYPES -}; - -struct ipw_scan_request_ext { - __le32 full_scan_index; - u8 channels_list[IPW_SCAN_CHANNELS]; - u8 scan_type[IPW_SCAN_CHANNELS / 2]; - u8 reserved; - __le16 dwell_time[IPW_SCAN_TYPES]; -} __attribute__ ((packed)); - -static inline u8 ipw_get_scan_type(struct ipw_scan_request_ext *scan, u8 index) -{ - if (index % 2) - return scan->scan_type[index / 2] & 0x0F; - else - return (scan->scan_type[index / 2] & 0xF0) >> 4; -} - -static inline void ipw_set_scan_type(struct ipw_scan_request_ext *scan, - u8 index, u8 scan_type) -{ - if (index % 2) - scan->scan_type[index / 2] = - (scan->scan_type[index / 2] & 0xF0) | (scan_type & 0x0F); - else - scan->scan_type[index / 2] = - (scan->scan_type[index / 2] & 0x0F) | - ((scan_type & 0x0F) << 4); -} - -struct ipw_associate { - u8 channel; -#ifdef __LITTLE_ENDIAN_BITFIELD - u8 auth_type:4, auth_key:4; -#else - u8 auth_key:4, auth_type:4; -#endif - u8 assoc_type; - u8 reserved; - __le16 policy_support; - u8 preamble_length; - u8 ieee_mode; - u8 bssid[ETH_ALEN]; - __le32 assoc_tsf_msw; - __le32 assoc_tsf_lsw; - __le16 capability; - __le16 listen_interval; - __le16 beacon_interval; - u8 dest[ETH_ALEN]; - __le16 atim_window; - u8 smr; - u8 reserved1; - __le16 reserved2; -} __attribute__ ((packed)); - -struct ipw_supported_rates { - u8 ieee_mode; - u8 num_rates; - u8 purpose; - u8 reserved; - u8 supported_rates[IPW_MAX_RATES]; -} __attribute__ ((packed)); - -struct ipw_rts_threshold { - __le16 rts_threshold; - __le16 reserved; -} __attribute__ ((packed)); - -struct ipw_frag_threshold { - __le16 frag_threshold; - __le16 reserved; -} __attribute__ ((packed)); - -struct ipw_retry_limit { - u8 short_retry_limit; - u8 long_retry_limit; - __le16 reserved; -} __attribute__ ((packed)); - -struct ipw_dino_config { - __le32 dino_config_addr; - __le16 dino_config_size; - u8 dino_response; - u8 reserved; -} __attribute__ ((packed)); - -struct ipw_aironet_info { - u8 id; - u8 length; - __le16 reserved; -} __attribute__ ((packed)); - -struct ipw_rx_key { - u8 station_index; - u8 key_type; - u8 key_id; - u8 key_flag; - u8 key[16]; - u8 station_address[6]; - u8 key_index; - u8 reserved; -} __attribute__ ((packed)); - -struct ipw_country_channel_info { - u8 first_channel; - u8 no_channels; - s8 max_tx_power; -} __attribute__ ((packed)); - -struct ipw_country_info { - u8 id; - u8 length; - u8 country_str[3]; - struct ipw_country_channel_info groups[7]; -} __attribute__ ((packed)); - -struct ipw_channel_tx_power { - u8 channel_number; - s8 tx_power; -} __attribute__ ((packed)); - -#define SCAN_ASSOCIATED_INTERVAL (HZ) -#define SCAN_INTERVAL (HZ / 10) -#define MAX_A_CHANNELS 37 -#define MAX_B_CHANNELS 14 - -struct ipw_tx_power { - u8 num_channels; - u8 ieee_mode; - struct ipw_channel_tx_power channels_tx_power[MAX_A_CHANNELS]; -} __attribute__ ((packed)); - -struct ipw_rsn_capabilities { - u8 id; - u8 length; - __le16 version; -} __attribute__ ((packed)); - -struct ipw_sensitivity_calib { - __le16 beacon_rssi_raw; - __le16 reserved; -} __attribute__ ((packed)); - -/** - * Host command structure. - * - * On input, the following fields should be filled: - * - cmd - * - len - * - status_len - * - param (if needed) - * - * On output, - * - \a status contains status; - * - \a param filled with status parameters. - */ -struct ipw_cmd { /* XXX */ - u32 cmd; /**< Host command */ - u32 status;/**< Status */ - u32 status_len; - /**< How many 32 bit parameters in the status */ - u32 len; /**< incoming parameters length, bytes */ - /** - * command parameters. - * There should be enough space for incoming and - * outcoming parameters. - * Incoming parameters listed 1-st, followed by outcoming params. - * nParams=(len+3)/4+status_len - */ - u32 param[0]; -} __attribute__ ((packed)); - -#define STATUS_HCMD_ACTIVE (1<<0) /**< host command in progress */ - -#define STATUS_INT_ENABLED (1<<1) -#define STATUS_RF_KILL_HW (1<<2) -#define STATUS_RF_KILL_SW (1<<3) -#define STATUS_RF_KILL_MASK (STATUS_RF_KILL_HW | STATUS_RF_KILL_SW) - -#define STATUS_INIT (1<<5) -#define STATUS_AUTH (1<<6) -#define STATUS_ASSOCIATED (1<<7) -#define STATUS_STATE_MASK (STATUS_INIT | STATUS_AUTH | STATUS_ASSOCIATED) - -#define STATUS_ASSOCIATING (1<<8) -#define STATUS_DISASSOCIATING (1<<9) -#define STATUS_ROAMING (1<<10) -#define STATUS_EXIT_PENDING (1<<11) -#define STATUS_DISASSOC_PENDING (1<<12) -#define STATUS_STATE_PENDING (1<<13) - -#define STATUS_DIRECT_SCAN_PENDING (1<<19) -#define STATUS_SCAN_PENDING (1<<20) -#define STATUS_SCANNING (1<<21) -#define STATUS_SCAN_ABORTING (1<<22) -#define STATUS_SCAN_FORCED (1<<23) - -#define STATUS_LED_LINK_ON (1<<24) -#define STATUS_LED_ACT_ON (1<<25) - -#define STATUS_INDIRECT_BYTE (1<<28) /* sysfs entry configured for access */ -#define STATUS_INDIRECT_DWORD (1<<29) /* sysfs entry configured for access */ -#define STATUS_DIRECT_DWORD (1<<30) /* sysfs entry configured for access */ - -#define STATUS_SECURITY_UPDATED (1<<31) /* Security sync needed */ - -#define CFG_STATIC_CHANNEL (1<<0) /* Restrict assoc. to single channel */ -#define CFG_STATIC_ESSID (1<<1) /* Restrict assoc. to single SSID */ -#define CFG_STATIC_BSSID (1<<2) /* Restrict assoc. to single BSSID */ -#define CFG_CUSTOM_MAC (1<<3) -#define CFG_PREAMBLE_LONG (1<<4) -#define CFG_ADHOC_PERSIST (1<<5) -#define CFG_ASSOCIATE (1<<6) -#define CFG_FIXED_RATE (1<<7) -#define CFG_ADHOC_CREATE (1<<8) -#define CFG_NO_LED (1<<9) -#define CFG_BACKGROUND_SCAN (1<<10) -#define CFG_SPEED_SCAN (1<<11) -#define CFG_NET_STATS (1<<12) - -#define CAP_SHARED_KEY (1<<0) /* Off = OPEN */ -#define CAP_PRIVACY_ON (1<<1) /* Off = No privacy */ - -#define MAX_STATIONS 32 -#define IPW_INVALID_STATION (0xff) - -struct ipw_station_entry { - u8 mac_addr[ETH_ALEN]; - u8 reserved; - u8 support_mode; -}; - -#define AVG_ENTRIES 8 -struct average { - s16 entries[AVG_ENTRIES]; - u8 pos; - u8 init; - s32 sum; -}; - -#define MAX_SPEED_SCAN 100 -#define IPW_IBSS_MAC_HASH_SIZE 31 - -struct ipw_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - -struct ipw_error_elem { /* XXX */ - u32 desc; - u32 time; - u32 blink1; - u32 blink2; - u32 link1; - u32 link2; - u32 data; -}; - -struct ipw_event { /* XXX */ - u32 event; - u32 time; - u32 data; -} __attribute__ ((packed)); - -struct ipw_fw_error { /* XXX */ - unsigned long jiffies; - u32 status; - u32 config; - u32 elem_len; - u32 log_len; - struct ipw_error_elem *elem; - struct ipw_event *log; - u8 payload[0]; -} __attribute__ ((packed)); - -#ifdef CONFIG_IPW2200_PROMISCUOUS - -enum ipw_prom_filter { - IPW_PROM_CTL_HEADER_ONLY = (1 << 0), - IPW_PROM_MGMT_HEADER_ONLY = (1 << 1), - IPW_PROM_DATA_HEADER_ONLY = (1 << 2), - IPW_PROM_ALL_HEADER_ONLY = 0xf, /* bits 0..3 */ - IPW_PROM_NO_TX = (1 << 4), - IPW_PROM_NO_RX = (1 << 5), - IPW_PROM_NO_CTL = (1 << 6), - IPW_PROM_NO_MGMT = (1 << 7), - IPW_PROM_NO_DATA = (1 << 8), -}; - -struct ipw_priv; -struct ipw_prom_priv { - struct ipw_priv *priv; - struct libipw_device *ieee; - enum ipw_prom_filter filter; - int tx_packets; - int rx_packets; -}; -#endif - -#if defined(CONFIG_IPW2200_RADIOTAP) || defined(CONFIG_IPW2200_PROMISCUOUS) -/* Magic struct that slots into the radiotap header -- no reason - * to build this manually element by element, we can write it much - * more efficiently than we can parse it. ORDER MATTERS HERE - * - * When sent to us via the simulated Rx interface in sysfs, the entire - * structure is provided regardless of any bits unset. - */ -struct ipw_rt_hdr { - struct ieee80211_radiotap_header rt_hdr; - u64 rt_tsf; /* TSF */ /* XXX */ - u8 rt_flags; /* radiotap packet flags */ - u8 rt_rate; /* rate in 500kb/s */ - __le16 rt_channel; /* channel in mhz */ - __le16 rt_chbitmask; /* channel bitfield */ - s8 rt_dbmsignal; /* signal in dbM, kluged to signed */ - s8 rt_dbmnoise; - u8 rt_antenna; /* antenna number */ - u8 payload[0]; /* payload... */ -} __attribute__ ((packed)); -#endif - -struct ipw_priv { - /* ieee device used by generic ieee processing code */ - struct libipw_device *ieee; - - spinlock_t lock; - spinlock_t irq_lock; - struct mutex mutex; - - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; - struct net_device *net_dev; - -#ifdef CONFIG_IPW2200_PROMISCUOUS - /* Promiscuous mode */ - struct ipw_prom_priv *prom_priv; - struct net_device *prom_net_dev; -#endif - - /* pci hardware address support */ - void __iomem *hw_base; - unsigned long hw_len; - - struct fw_image_desc sram_desc; - - /* result of ucode download */ - struct alive_command_responce dino_alive; - - wait_queue_head_t wait_command_queue; - wait_queue_head_t wait_state; - - /* Rx and Tx DMA processing queues */ - struct ipw_rx_queue *rxq; - struct clx2_tx_queue txq_cmd; - struct clx2_tx_queue txq[4]; - u32 status; - u32 config; - u32 capability; - - struct average average_missed_beacons; - s16 exp_avg_rssi; - s16 exp_avg_noise; - u32 port_type; - int rx_bufs_min; /**< minimum number of bufs in Rx queue */ - int rx_pend_max; /**< maximum pending buffers for one IRQ */ - u32 hcmd_seq; /**< sequence number for hcmd */ - u32 disassociate_threshold; - u32 roaming_threshold; - - struct ipw_associate assoc_request; - struct libipw_network *assoc_network; - - unsigned long ts_scan_abort; - struct ipw_supported_rates rates; - struct ipw_rates phy[3]; /**< PHY restrictions, per band */ - struct ipw_rates supp; /**< software defined */ - struct ipw_rates extended; /**< use for corresp. IE, AP only */ - - struct notif_link_deterioration last_link_deterioration; /** for statistics */ - struct ipw_cmd *hcmd; /**< host command currently executed */ - - wait_queue_head_t hcmd_wq; /**< host command waits for execution */ - u32 tsf_bcn[2]; /**< TSF from latest beacon */ - - struct notif_calibration calib; /**< last calibration */ - - /* ordinal interface with firmware */ - u32 table0_addr; - u32 table0_len; - u32 table1_addr; - u32 table1_len; - u32 table2_addr; - u32 table2_len; - - /* context information */ - u8 essid[IW_ESSID_MAX_SIZE]; - u8 essid_len; - u8 nick[IW_ESSID_MAX_SIZE]; - u16 rates_mask; - u8 channel; - struct ipw_sys_config sys_config; - u32 power_mode; - u8 bssid[ETH_ALEN]; - u16 rts_threshold; - u8 mac_addr[ETH_ALEN]; - u8 num_stations; - u8 stations[MAX_STATIONS][ETH_ALEN]; - u8 short_retry_limit; - u8 long_retry_limit; - - u32 notif_missed_beacons; - - /* Statistics and counters normalized with each association */ - u32 last_missed_beacons; - u32 last_tx_packets; - u32 last_rx_packets; - u32 last_tx_failures; - u32 last_rx_err; - u32 last_rate; - - u32 missed_adhoc_beacons; - u32 missed_beacons; - u32 rx_packets; - u32 tx_packets; - u32 quality; - - u8 speed_scan[MAX_SPEED_SCAN]; - u8 speed_scan_pos; - - u16 last_seq_num; - u16 last_frag_num; - unsigned long last_packet_time; - struct list_head ibss_mac_hash[IPW_IBSS_MAC_HASH_SIZE]; - - /* eeprom */ - u8 eeprom[0x100]; /* 256 bytes of eeprom */ - u8 country[4]; - int eeprom_delay; - - struct iw_statistics wstats; - - struct iw_public_data wireless_data; - - int user_requested_scan; - u8 direct_scan_ssid[IW_ESSID_MAX_SIZE]; - u8 direct_scan_ssid_len; - - struct workqueue_struct *workqueue; - - struct delayed_work adhoc_check; - struct work_struct associate; - struct work_struct disassociate; - struct work_struct system_config; - struct work_struct rx_replenish; - struct delayed_work request_scan; - struct delayed_work request_direct_scan; - struct delayed_work request_passive_scan; - struct delayed_work scan_event; - struct work_struct adapter_restart; - struct delayed_work rf_kill; - struct work_struct up; - struct work_struct down; - struct delayed_work gather_stats; - struct work_struct abort_scan; - struct work_struct roam; - struct delayed_work scan_check; - struct work_struct link_up; - struct work_struct link_down; - - struct tasklet_struct irq_tasklet; - - /* LED related variables and work_struct */ - u8 nic_type; - u32 led_activity_on; - u32 led_activity_off; - u32 led_association_on; - u32 led_association_off; - u32 led_ofdm_on; - u32 led_ofdm_off; - - struct delayed_work led_link_on; - struct delayed_work led_link_off; - struct delayed_work led_act_off; - struct work_struct merge_networks; - - struct ipw_cmd_log *cmdlog; - int cmdlog_len; - int cmdlog_pos; - -#define IPW_2200BG 1 -#define IPW_2915ABG 2 - u8 adapter; - - s8 tx_power; - - /* Track time in suspend */ - unsigned long suspend_at; - unsigned long suspend_time; - -#ifdef CONFIG_PM - u32 pm_state[16]; -#endif - - struct ipw_fw_error *error; - - /* network state */ - - /* Used to pass the current INTA value from ISR to Tasklet */ - u32 isr_inta; - - /* QoS */ - struct ipw_qos_info qos_data; - struct work_struct qos_activate; - /*********************************/ - - /* debugging info */ - u32 indirect_dword; - u32 direct_dword; - u32 indirect_byte; -}; /*ipw_priv */ - -/* debug macros */ - -/* Debug and printf string expansion helpers for printing bitfields */ -#define BIT_FMT8 "%c%c%c%c-%c%c%c%c" -#define BIT_FMT16 BIT_FMT8 ":" BIT_FMT8 -#define BIT_FMT32 BIT_FMT16 " " BIT_FMT16 - -#define BITC(x,y) (((x>>y)&1)?'1':'0') -#define BIT_ARG8(x) \ -BITC(x,7),BITC(x,6),BITC(x,5),BITC(x,4),\ -BITC(x,3),BITC(x,2),BITC(x,1),BITC(x,0) - -#define BIT_ARG16(x) \ -BITC(x,15),BITC(x,14),BITC(x,13),BITC(x,12),\ -BITC(x,11),BITC(x,10),BITC(x,9),BITC(x,8),\ -BIT_ARG8(x) - -#define BIT_ARG32(x) \ -BITC(x,31),BITC(x,30),BITC(x,29),BITC(x,28),\ -BITC(x,27),BITC(x,26),BITC(x,25),BITC(x,24),\ -BITC(x,23),BITC(x,22),BITC(x,21),BITC(x,20),\ -BITC(x,19),BITC(x,18),BITC(x,17),BITC(x,16),\ -BIT_ARG16(x) - - -#define IPW_DEBUG(level, fmt, args...) \ -do { if (ipw_debug_level & (level)) \ - printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) - -#ifdef CONFIG_IPW2200_DEBUG -#define IPW_LL_DEBUG(level, fmt, args...) \ -do { if (ipw_debug_level & (level)) \ - printk(KERN_DEBUG DRV_NAME": %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) -#else -#define IPW_LL_DEBUG(level, fmt, args...) do {} while (0) -#endif /* CONFIG_IPW2200_DEBUG */ - -/* - * To use the debug system; - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define IPW_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a IPW_xxxx_DEBUG() macro definition for your - * classification, or use IPW_DEBUG(IPW_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/ipw/debug_level - * - * you simply need to add your entry to the ipw_debug_levels array. - * - * If you do not see debug_level in /proc/net/ipw then you do not have - * CONFIG_IPW2200_DEBUG defined in your kernel configuration - * - */ - -#define IPW_DL_ERROR (1<<0) -#define IPW_DL_WARNING (1<<1) -#define IPW_DL_INFO (1<<2) -#define IPW_DL_WX (1<<3) -#define IPW_DL_HOST_COMMAND (1<<5) -#define IPW_DL_STATE (1<<6) - -#define IPW_DL_NOTIF (1<<10) -#define IPW_DL_SCAN (1<<11) -#define IPW_DL_ASSOC (1<<12) -#define IPW_DL_DROP (1<<13) -#define IPW_DL_IOCTL (1<<14) - -#define IPW_DL_MANAGE (1<<15) -#define IPW_DL_FW (1<<16) -#define IPW_DL_RF_KILL (1<<17) -#define IPW_DL_FW_ERRORS (1<<18) - -#define IPW_DL_LED (1<<19) - -#define IPW_DL_ORD (1<<20) - -#define IPW_DL_FRAG (1<<21) -#define IPW_DL_WEP (1<<22) -#define IPW_DL_TX (1<<23) -#define IPW_DL_RX (1<<24) -#define IPW_DL_ISR (1<<25) -#define IPW_DL_FW_INFO (1<<26) -#define IPW_DL_IO (1<<27) -#define IPW_DL_TRACE (1<<28) - -#define IPW_DL_STATS (1<<29) -#define IPW_DL_MERGE (1<<30) -#define IPW_DL_QOS (1<<31) - -#define IPW_ERROR(f, a...) printk(KERN_ERR DRV_NAME ": " f, ## a) -#define IPW_WARNING(f, a...) printk(KERN_WARNING DRV_NAME ": " f, ## a) -#define IPW_DEBUG_INFO(f, a...) IPW_DEBUG(IPW_DL_INFO, f, ## a) - -#define IPW_DEBUG_WX(f, a...) IPW_DEBUG(IPW_DL_WX, f, ## a) -#define IPW_DEBUG_SCAN(f, a...) IPW_DEBUG(IPW_DL_SCAN, f, ## a) -#define IPW_DEBUG_TRACE(f, a...) IPW_LL_DEBUG(IPW_DL_TRACE, f, ## a) -#define IPW_DEBUG_RX(f, a...) IPW_LL_DEBUG(IPW_DL_RX, f, ## a) -#define IPW_DEBUG_TX(f, a...) IPW_LL_DEBUG(IPW_DL_TX, f, ## a) -#define IPW_DEBUG_ISR(f, a...) IPW_LL_DEBUG(IPW_DL_ISR, f, ## a) -#define IPW_DEBUG_MANAGEMENT(f, a...) IPW_DEBUG(IPW_DL_MANAGE, f, ## a) -#define IPW_DEBUG_LED(f, a...) IPW_LL_DEBUG(IPW_DL_LED, f, ## a) -#define IPW_DEBUG_WEP(f, a...) IPW_LL_DEBUG(IPW_DL_WEP, f, ## a) -#define IPW_DEBUG_HC(f, a...) IPW_LL_DEBUG(IPW_DL_HOST_COMMAND, f, ## a) -#define IPW_DEBUG_FRAG(f, a...) IPW_LL_DEBUG(IPW_DL_FRAG, f, ## a) -#define IPW_DEBUG_FW(f, a...) IPW_LL_DEBUG(IPW_DL_FW, f, ## a) -#define IPW_DEBUG_RF_KILL(f, a...) IPW_DEBUG(IPW_DL_RF_KILL, f, ## a) -#define IPW_DEBUG_DROP(f, a...) IPW_DEBUG(IPW_DL_DROP, f, ## a) -#define IPW_DEBUG_IO(f, a...) IPW_LL_DEBUG(IPW_DL_IO, f, ## a) -#define IPW_DEBUG_ORD(f, a...) IPW_LL_DEBUG(IPW_DL_ORD, f, ## a) -#define IPW_DEBUG_FW_INFO(f, a...) IPW_LL_DEBUG(IPW_DL_FW_INFO, f, ## a) -#define IPW_DEBUG_NOTIF(f, a...) IPW_DEBUG(IPW_DL_NOTIF, f, ## a) -#define IPW_DEBUG_STATE(f, a...) IPW_DEBUG(IPW_DL_STATE | IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) -#define IPW_DEBUG_ASSOC(f, a...) IPW_DEBUG(IPW_DL_ASSOC | IPW_DL_INFO, f, ## a) -#define IPW_DEBUG_STATS(f, a...) IPW_LL_DEBUG(IPW_DL_STATS, f, ## a) -#define IPW_DEBUG_MERGE(f, a...) IPW_LL_DEBUG(IPW_DL_MERGE, f, ## a) -#define IPW_DEBUG_QOS(f, a...) IPW_LL_DEBUG(IPW_DL_QOS, f, ## a) - -#include - -/* -* Register bit definitions -*/ - -#define IPW_INTA_RW 0x00000008 -#define IPW_INTA_MASK_R 0x0000000C -#define IPW_INDIRECT_ADDR 0x00000010 -#define IPW_INDIRECT_DATA 0x00000014 -#define IPW_AUTOINC_ADDR 0x00000018 -#define IPW_AUTOINC_DATA 0x0000001C -#define IPW_RESET_REG 0x00000020 -#define IPW_GP_CNTRL_RW 0x00000024 - -#define IPW_READ_INT_REGISTER 0xFF4 - -#define IPW_GP_CNTRL_BIT_INIT_DONE 0x00000004 - -#define IPW_REGISTER_DOMAIN1_END 0x00001000 -#define IPW_SRAM_READ_INT_REGISTER 0x00000ff4 - -#define IPW_SHARED_LOWER_BOUND 0x00000200 -#define IPW_INTERRUPT_AREA_LOWER_BOUND 0x00000f80 - -#define IPW_NIC_SRAM_LOWER_BOUND 0x00000000 -#define IPW_NIC_SRAM_UPPER_BOUND 0x00030000 - -#define IPW_BIT_INT_HOST_SRAM_READ_INT_REGISTER (1 << 29) -#define IPW_GP_CNTRL_BIT_CLOCK_READY 0x00000001 -#define IPW_GP_CNTRL_BIT_HOST_ALLOWS_STANDBY 0x00000002 - -/* - * RESET Register Bit Indexes - */ -#define CBD_RESET_REG_PRINCETON_RESET (1<<0) -#define IPW_START_STANDBY (1<<2) -#define IPW_ACTIVITY_LED (1<<4) -#define IPW_ASSOCIATED_LED (1<<5) -#define IPW_OFDM_LED (1<<6) -#define IPW_RESET_REG_SW_RESET (1<<7) -#define IPW_RESET_REG_MASTER_DISABLED (1<<8) -#define IPW_RESET_REG_STOP_MASTER (1<<9) -#define IPW_GATE_ODMA (1<<25) -#define IPW_GATE_IDMA (1<<26) -#define IPW_ARC_KESHET_CONFIG (1<<27) -#define IPW_GATE_ADMA (1<<29) - -#define IPW_CSR_CIS_UPPER_BOUND 0x00000200 -#define IPW_DOMAIN_0_END 0x1000 -#define CLX_MEM_BAR_SIZE 0x1000 - -/* Dino/baseband control registers bits */ - -#define DINO_ENABLE_SYSTEM 0x80 /* 1 = baseband processor on, 0 = reset */ -#define DINO_ENABLE_CS 0x40 /* 1 = enable ucode load */ -#define DINO_RXFIFO_DATA 0x01 /* 1 = data available */ -#define IPW_BASEBAND_CONTROL_STATUS 0X00200000 -#define IPW_BASEBAND_TX_FIFO_WRITE 0X00200004 -#define IPW_BASEBAND_RX_FIFO_READ 0X00200004 -#define IPW_BASEBAND_CONTROL_STORE 0X00200010 - -#define IPW_INTERNAL_CMD_EVENT 0X00300004 -#define IPW_BASEBAND_POWER_DOWN 0x00000001 - -#define IPW_MEM_HALT_AND_RESET 0x003000e0 - -/* defgroup bits_halt_reset MEM_HALT_AND_RESET register bits */ -#define IPW_BIT_HALT_RESET_ON 0x80000000 -#define IPW_BIT_HALT_RESET_OFF 0x00000000 - -#define CB_LAST_VALID 0x20000000 -#define CB_INT_ENABLED 0x40000000 -#define CB_VALID 0x80000000 -#define CB_SRC_LE 0x08000000 -#define CB_DEST_LE 0x04000000 -#define CB_SRC_AUTOINC 0x00800000 -#define CB_SRC_IO_GATED 0x00400000 -#define CB_DEST_AUTOINC 0x00080000 -#define CB_SRC_SIZE_LONG 0x00200000 -#define CB_DEST_SIZE_LONG 0x00020000 - -/* DMA DEFINES */ - -#define DMA_CONTROL_SMALL_CB_CONST_VALUE 0x00540000 -#define DMA_CB_STOP_AND_ABORT 0x00000C00 -#define DMA_CB_START 0x00000100 - -#define IPW_SHARED_SRAM_SIZE 0x00030000 -#define IPW_SHARED_SRAM_DMA_CONTROL 0x00027000 -#define CB_MAX_LENGTH 0x1FFF - -#define IPW_HOST_EEPROM_DATA_SRAM_SIZE 0xA18 -#define IPW_EEPROM_IMAGE_SIZE 0x100 - -/* DMA defs */ -#define IPW_DMA_I_CURRENT_CB 0x003000D0 -#define IPW_DMA_O_CURRENT_CB 0x003000D4 -#define IPW_DMA_I_DMA_CONTROL 0x003000A4 -#define IPW_DMA_I_CB_BASE 0x003000A0 - -#define IPW_TX_CMD_QUEUE_BD_BASE 0x00000200 -#define IPW_TX_CMD_QUEUE_BD_SIZE 0x00000204 -#define IPW_TX_QUEUE_0_BD_BASE 0x00000208 -#define IPW_TX_QUEUE_0_BD_SIZE (0x0000020C) -#define IPW_TX_QUEUE_1_BD_BASE 0x00000210 -#define IPW_TX_QUEUE_1_BD_SIZE 0x00000214 -#define IPW_TX_QUEUE_2_BD_BASE 0x00000218 -#define IPW_TX_QUEUE_2_BD_SIZE (0x0000021C) -#define IPW_TX_QUEUE_3_BD_BASE 0x00000220 -#define IPW_TX_QUEUE_3_BD_SIZE 0x00000224 -#define IPW_RX_BD_BASE 0x00000240 -#define IPW_RX_BD_SIZE 0x00000244 -#define IPW_RFDS_TABLE_LOWER 0x00000500 - -#define IPW_TX_CMD_QUEUE_READ_INDEX 0x00000280 -#define IPW_TX_QUEUE_0_READ_INDEX 0x00000284 -#define IPW_TX_QUEUE_1_READ_INDEX 0x00000288 -#define IPW_TX_QUEUE_2_READ_INDEX (0x0000028C) -#define IPW_TX_QUEUE_3_READ_INDEX 0x00000290 -#define IPW_RX_READ_INDEX (0x000002A0) - -#define IPW_TX_CMD_QUEUE_WRITE_INDEX (0x00000F80) -#define IPW_TX_QUEUE_0_WRITE_INDEX (0x00000F84) -#define IPW_TX_QUEUE_1_WRITE_INDEX (0x00000F88) -#define IPW_TX_QUEUE_2_WRITE_INDEX (0x00000F8C) -#define IPW_TX_QUEUE_3_WRITE_INDEX (0x00000F90) -#define IPW_RX_WRITE_INDEX (0x00000FA0) - -/* - * EEPROM Related Definitions - */ - -#define IPW_EEPROM_DATA_SRAM_ADDRESS (IPW_SHARED_LOWER_BOUND + 0x814) -#define IPW_EEPROM_DATA_SRAM_SIZE (IPW_SHARED_LOWER_BOUND + 0x818) -#define IPW_EEPROM_LOAD_DISABLE (IPW_SHARED_LOWER_BOUND + 0x81C) -#define IPW_EEPROM_DATA (IPW_SHARED_LOWER_BOUND + 0x820) -#define IPW_EEPROM_UPPER_ADDRESS (IPW_SHARED_LOWER_BOUND + 0x9E0) - -#define IPW_STATION_TABLE_LOWER (IPW_SHARED_LOWER_BOUND + 0xA0C) -#define IPW_STATION_TABLE_UPPER (IPW_SHARED_LOWER_BOUND + 0xB0C) -#define IPW_REQUEST_ATIM (IPW_SHARED_LOWER_BOUND + 0xB0C) -#define IPW_ATIM_SENT (IPW_SHARED_LOWER_BOUND + 0xB10) -#define IPW_WHO_IS_AWAKE (IPW_SHARED_LOWER_BOUND + 0xB14) -#define IPW_DURING_ATIM_WINDOW (IPW_SHARED_LOWER_BOUND + 0xB18) - -#define MSB 1 -#define LSB 0 -#define WORD_TO_BYTE(_word) ((_word) * sizeof(u16)) - -#define GET_EEPROM_ADDR(_wordoffset,_byteoffset) \ - ( WORD_TO_BYTE(_wordoffset) + (_byteoffset) ) - -/* EEPROM access by BYTE */ -#define EEPROM_PME_CAPABILITY (GET_EEPROM_ADDR(0x09,MSB)) /* 1 byte */ -#define EEPROM_MAC_ADDRESS (GET_EEPROM_ADDR(0x21,LSB)) /* 6 byte */ -#define EEPROM_VERSION (GET_EEPROM_ADDR(0x24,MSB)) /* 1 byte */ -#define EEPROM_NIC_TYPE (GET_EEPROM_ADDR(0x25,LSB)) /* 1 byte */ -#define EEPROM_SKU_CAPABILITY (GET_EEPROM_ADDR(0x25,MSB)) /* 1 byte */ -#define EEPROM_COUNTRY_CODE (GET_EEPROM_ADDR(0x26,LSB)) /* 3 bytes */ -#define EEPROM_IBSS_CHANNELS_BG (GET_EEPROM_ADDR(0x28,LSB)) /* 2 bytes */ -#define EEPROM_IBSS_CHANNELS_A (GET_EEPROM_ADDR(0x29,MSB)) /* 5 bytes */ -#define EEPROM_BSS_CHANNELS_BG (GET_EEPROM_ADDR(0x2c,LSB)) /* 2 bytes */ -#define EEPROM_HW_VERSION (GET_EEPROM_ADDR(0x72,LSB)) /* 2 bytes */ - -/* NIC type as found in the one byte EEPROM_NIC_TYPE offset */ -#define EEPROM_NIC_TYPE_0 0 -#define EEPROM_NIC_TYPE_1 1 -#define EEPROM_NIC_TYPE_2 2 -#define EEPROM_NIC_TYPE_3 3 -#define EEPROM_NIC_TYPE_4 4 - -/* Bluetooth Coexistence capabilities as found in EEPROM_SKU_CAPABILITY */ -#define EEPROM_SKU_CAP_BT_CHANNEL_SIG 0x01 /* we can tell BT our channel # */ -#define EEPROM_SKU_CAP_BT_PRIORITY 0x02 /* BT can take priority over us */ -#define EEPROM_SKU_CAP_BT_OOB 0x04 /* we can signal BT out-of-band */ - -#define FW_MEM_REG_LOWER_BOUND 0x00300000 -#define FW_MEM_REG_EEPROM_ACCESS (FW_MEM_REG_LOWER_BOUND + 0x40) -#define IPW_EVENT_REG (FW_MEM_REG_LOWER_BOUND + 0x04) -#define EEPROM_BIT_SK (1<<0) -#define EEPROM_BIT_CS (1<<1) -#define EEPROM_BIT_DI (1<<2) -#define EEPROM_BIT_DO (1<<4) - -#define EEPROM_CMD_READ 0x2 - -/* Interrupts masks */ -#define IPW_INTA_NONE 0x00000000 - -#define IPW_INTA_BIT_RX_TRANSFER 0x00000002 -#define IPW_INTA_BIT_STATUS_CHANGE 0x00000010 -#define IPW_INTA_BIT_BEACON_PERIOD_EXPIRED 0x00000020 - -//Inta Bits for CF -#define IPW_INTA_BIT_TX_CMD_QUEUE 0x00000800 -#define IPW_INTA_BIT_TX_QUEUE_1 0x00001000 -#define IPW_INTA_BIT_TX_QUEUE_2 0x00002000 -#define IPW_INTA_BIT_TX_QUEUE_3 0x00004000 -#define IPW_INTA_BIT_TX_QUEUE_4 0x00008000 - -#define IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE 0x00010000 - -#define IPW_INTA_BIT_PREPARE_FOR_POWER_DOWN 0x00100000 -#define IPW_INTA_BIT_POWER_DOWN 0x00200000 - -#define IPW_INTA_BIT_FW_INITIALIZATION_DONE 0x01000000 -#define IPW_INTA_BIT_FW_CARD_DISABLE_PHY_OFF_DONE 0x02000000 -#define IPW_INTA_BIT_RF_KILL_DONE 0x04000000 -#define IPW_INTA_BIT_FATAL_ERROR 0x40000000 -#define IPW_INTA_BIT_PARITY_ERROR 0x80000000 - -/* Interrupts enabled at init time. */ -#define IPW_INTA_MASK_ALL \ - (IPW_INTA_BIT_TX_QUEUE_1 | \ - IPW_INTA_BIT_TX_QUEUE_2 | \ - IPW_INTA_BIT_TX_QUEUE_3 | \ - IPW_INTA_BIT_TX_QUEUE_4 | \ - IPW_INTA_BIT_TX_CMD_QUEUE | \ - IPW_INTA_BIT_RX_TRANSFER | \ - IPW_INTA_BIT_FATAL_ERROR | \ - IPW_INTA_BIT_PARITY_ERROR | \ - IPW_INTA_BIT_STATUS_CHANGE | \ - IPW_INTA_BIT_FW_INITIALIZATION_DONE | \ - IPW_INTA_BIT_BEACON_PERIOD_EXPIRED | \ - IPW_INTA_BIT_SLAVE_MODE_HOST_CMD_DONE | \ - IPW_INTA_BIT_PREPARE_FOR_POWER_DOWN | \ - IPW_INTA_BIT_POWER_DOWN | \ - IPW_INTA_BIT_RF_KILL_DONE ) - -/* FW event log definitions */ -#define EVENT_ELEM_SIZE (3 * sizeof(u32)) -#define EVENT_START_OFFSET (1 * sizeof(u32) + 2 * sizeof(u16)) - -/* FW error log definitions */ -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) -#define ERROR_START_OFFSET (1 * sizeof(u32)) - -/* TX power level (dbm) */ -#define IPW_TX_POWER_MIN -12 -#define IPW_TX_POWER_MAX 20 -#define IPW_TX_POWER_DEFAULT IPW_TX_POWER_MAX - -enum { - IPW_FW_ERROR_OK = 0, - IPW_FW_ERROR_FAIL, - IPW_FW_ERROR_MEMORY_UNDERFLOW, - IPW_FW_ERROR_MEMORY_OVERFLOW, - IPW_FW_ERROR_BAD_PARAM, - IPW_FW_ERROR_BAD_CHECKSUM, - IPW_FW_ERROR_NMI_INTERRUPT, - IPW_FW_ERROR_BAD_DATABASE, - IPW_FW_ERROR_ALLOC_FAIL, - IPW_FW_ERROR_DMA_UNDERRUN, - IPW_FW_ERROR_DMA_STATUS, - IPW_FW_ERROR_DINO_ERROR, - IPW_FW_ERROR_EEPROM_ERROR, - IPW_FW_ERROR_SYSASSERT, - IPW_FW_ERROR_FATAL_ERROR -}; - -#define AUTH_OPEN 0 -#define AUTH_SHARED_KEY 1 -#define AUTH_LEAP 2 -#define AUTH_IGNORE 3 - -#define HC_ASSOCIATE 0 -#define HC_REASSOCIATE 1 -#define HC_DISASSOCIATE 2 -#define HC_IBSS_START 3 -#define HC_IBSS_RECONF 4 -#define HC_DISASSOC_QUIET 5 - -#define HC_QOS_SUPPORT_ASSOC cpu_to_le16(0x01) - -#define IPW_RATE_CAPABILITIES 1 -#define IPW_RATE_CONNECT 0 - -/* - * Rate values and masks - */ -#define IPW_TX_RATE_1MB 0x0A -#define IPW_TX_RATE_2MB 0x14 -#define IPW_TX_RATE_5MB 0x37 -#define IPW_TX_RATE_6MB 0x0D -#define IPW_TX_RATE_9MB 0x0F -#define IPW_TX_RATE_11MB 0x6E -#define IPW_TX_RATE_12MB 0x05 -#define IPW_TX_RATE_18MB 0x07 -#define IPW_TX_RATE_24MB 0x09 -#define IPW_TX_RATE_36MB 0x0B -#define IPW_TX_RATE_48MB 0x01 -#define IPW_TX_RATE_54MB 0x03 - -#define IPW_ORD_TABLE_ID_MASK 0x0000FF00 -#define IPW_ORD_TABLE_VALUE_MASK 0x000000FF - -#define IPW_ORD_TABLE_0_MASK 0x0000F000 -#define IPW_ORD_TABLE_1_MASK 0x0000F100 -#define IPW_ORD_TABLE_2_MASK 0x0000F200 -#define IPW_ORD_TABLE_3_MASK 0x0000F300 -#define IPW_ORD_TABLE_4_MASK 0x0000F400 -#define IPW_ORD_TABLE_5_MASK 0x0000F500 -#define IPW_ORD_TABLE_6_MASK 0x0000F600 -#define IPW_ORD_TABLE_7_MASK 0x0000F700 - -/* - * Table 0 Entries (all entries are 32 bits) - */ -enum { - IPW_ORD_STAT_TX_CURR_RATE = IPW_ORD_TABLE_0_MASK + 1, - IPW_ORD_STAT_FRAG_TRESHOLD, - IPW_ORD_STAT_RTS_THRESHOLD, - IPW_ORD_STAT_TX_HOST_REQUESTS, - IPW_ORD_STAT_TX_HOST_COMPLETE, - IPW_ORD_STAT_TX_DIR_DATA, - IPW_ORD_STAT_TX_DIR_DATA_B_1, - IPW_ORD_STAT_TX_DIR_DATA_B_2, - IPW_ORD_STAT_TX_DIR_DATA_B_5_5, - IPW_ORD_STAT_TX_DIR_DATA_B_11, - /* Hole */ - - IPW_ORD_STAT_TX_DIR_DATA_G_1 = IPW_ORD_TABLE_0_MASK + 19, - IPW_ORD_STAT_TX_DIR_DATA_G_2, - IPW_ORD_STAT_TX_DIR_DATA_G_5_5, - IPW_ORD_STAT_TX_DIR_DATA_G_6, - IPW_ORD_STAT_TX_DIR_DATA_G_9, - IPW_ORD_STAT_TX_DIR_DATA_G_11, - IPW_ORD_STAT_TX_DIR_DATA_G_12, - IPW_ORD_STAT_TX_DIR_DATA_G_18, - IPW_ORD_STAT_TX_DIR_DATA_G_24, - IPW_ORD_STAT_TX_DIR_DATA_G_36, - IPW_ORD_STAT_TX_DIR_DATA_G_48, - IPW_ORD_STAT_TX_DIR_DATA_G_54, - IPW_ORD_STAT_TX_NON_DIR_DATA, - IPW_ORD_STAT_TX_NON_DIR_DATA_B_1, - IPW_ORD_STAT_TX_NON_DIR_DATA_B_2, - IPW_ORD_STAT_TX_NON_DIR_DATA_B_5_5, - IPW_ORD_STAT_TX_NON_DIR_DATA_B_11, - /* Hole */ - - IPW_ORD_STAT_TX_NON_DIR_DATA_G_1 = IPW_ORD_TABLE_0_MASK + 44, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_2, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_5_5, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_6, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_9, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_11, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_12, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_18, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_24, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_36, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_48, - IPW_ORD_STAT_TX_NON_DIR_DATA_G_54, - IPW_ORD_STAT_TX_RETRY, - IPW_ORD_STAT_TX_FAILURE, - IPW_ORD_STAT_RX_ERR_CRC, - IPW_ORD_STAT_RX_ERR_ICV, - IPW_ORD_STAT_RX_NO_BUFFER, - IPW_ORD_STAT_FULL_SCANS, - IPW_ORD_STAT_PARTIAL_SCANS, - IPW_ORD_STAT_TGH_ABORTED_SCANS, - IPW_ORD_STAT_TX_TOTAL_BYTES, - IPW_ORD_STAT_CURR_RSSI_RAW, - IPW_ORD_STAT_RX_BEACON, - IPW_ORD_STAT_MISSED_BEACONS, - IPW_ORD_TABLE_0_LAST -}; - -#define IPW_RSSI_TO_DBM 112 - -/* Table 1 Entries - */ -enum { - IPW_ORD_TABLE_1_LAST = IPW_ORD_TABLE_1_MASK | 1, -}; - -/* - * Table 2 Entries - * - * FW_VERSION: 16 byte string - * FW_DATE: 16 byte string (only 14 bytes used) - * UCODE_VERSION: 4 byte version code - * UCODE_DATE: 5 bytes code code - * ADDAPTER_MAC: 6 byte MAC address - * RTC: 4 byte clock - */ -enum { - IPW_ORD_STAT_FW_VERSION = IPW_ORD_TABLE_2_MASK | 1, - IPW_ORD_STAT_FW_DATE, - IPW_ORD_STAT_UCODE_VERSION, - IPW_ORD_STAT_UCODE_DATE, - IPW_ORD_STAT_ADAPTER_MAC, - IPW_ORD_STAT_RTC, - IPW_ORD_TABLE_2_LAST -}; - -/* Table 3 */ -enum { - IPW_ORD_STAT_TX_PACKET = IPW_ORD_TABLE_3_MASK | 0, - IPW_ORD_STAT_TX_PACKET_FAILURE, - IPW_ORD_STAT_TX_PACKET_SUCCESS, - IPW_ORD_STAT_TX_PACKET_ABORTED, - IPW_ORD_TABLE_3_LAST -}; - -/* Table 4 */ -enum { - IPW_ORD_TABLE_4_LAST = IPW_ORD_TABLE_4_MASK -}; - -/* Table 5 */ -enum { - IPW_ORD_STAT_AVAILABLE_AP_COUNT = IPW_ORD_TABLE_5_MASK, - IPW_ORD_STAT_AP_ASSNS, - IPW_ORD_STAT_ROAM, - IPW_ORD_STAT_ROAM_CAUSE_MISSED_BEACONS, - IPW_ORD_STAT_ROAM_CAUSE_UNASSOC, - IPW_ORD_STAT_ROAM_CAUSE_RSSI, - IPW_ORD_STAT_ROAM_CAUSE_LINK_QUALITY, - IPW_ORD_STAT_ROAM_CAUSE_AP_LOAD_BALANCE, - IPW_ORD_STAT_ROAM_CAUSE_AP_NO_TX, - IPW_ORD_STAT_LINK_UP, - IPW_ORD_STAT_LINK_DOWN, - IPW_ORD_ANTENNA_DIVERSITY, - IPW_ORD_CURR_FREQ, - IPW_ORD_TABLE_5_LAST -}; - -/* Table 6 */ -enum { - IPW_ORD_COUNTRY_CODE = IPW_ORD_TABLE_6_MASK, - IPW_ORD_CURR_BSSID, - IPW_ORD_CURR_SSID, - IPW_ORD_TABLE_6_LAST -}; - -/* Table 7 */ -enum { - IPW_ORD_STAT_PERCENT_MISSED_BEACONS = IPW_ORD_TABLE_7_MASK, - IPW_ORD_STAT_PERCENT_TX_RETRIES, - IPW_ORD_STAT_PERCENT_LINK_QUALITY, - IPW_ORD_STAT_CURR_RSSI_DBM, - IPW_ORD_TABLE_7_LAST -}; - -#define IPW_ERROR_LOG (IPW_SHARED_LOWER_BOUND + 0x410) -#define IPW_EVENT_LOG (IPW_SHARED_LOWER_BOUND + 0x414) -#define IPW_ORDINALS_TABLE_LOWER (IPW_SHARED_LOWER_BOUND + 0x500) -#define IPW_ORDINALS_TABLE_0 (IPW_SHARED_LOWER_BOUND + 0x180) -#define IPW_ORDINALS_TABLE_1 (IPW_SHARED_LOWER_BOUND + 0x184) -#define IPW_ORDINALS_TABLE_2 (IPW_SHARED_LOWER_BOUND + 0x188) -#define IPW_MEM_FIXED_OVERRIDE (IPW_SHARED_LOWER_BOUND + 0x41C) - -struct ipw_fixed_rate { - __le16 tx_rates; - __le16 reserved; -} __attribute__ ((packed)); - -#define IPW_INDIRECT_ADDR_MASK (~0x3ul) - -struct host_cmd { - u8 cmd; - u8 len; - u16 reserved; - u32 *param; -} __attribute__ ((packed)); /* XXX */ - -struct cmdlog_host_cmd { - u8 cmd; - u8 len; - __le16 reserved; - char param[124]; -} __attribute__ ((packed)); - -struct ipw_cmd_log { - unsigned long jiffies; - int retcode; - struct cmdlog_host_cmd cmd; -}; - -/* SysConfig command parameters ... */ -/* bt_coexistence param */ -#define CFG_BT_COEXISTENCE_SIGNAL_CHNL 0x01 /* tell BT our chnl # */ -#define CFG_BT_COEXISTENCE_DEFER 0x02 /* defer our Tx if BT traffic */ -#define CFG_BT_COEXISTENCE_KILL 0x04 /* kill our Tx if BT traffic */ -#define CFG_BT_COEXISTENCE_WME_OVER_BT 0x08 /* multimedia extensions */ -#define CFG_BT_COEXISTENCE_OOB 0x10 /* signal BT via out-of-band */ - -/* clear-to-send to self param */ -#define CFG_CTS_TO_ITSELF_ENABLED_MIN 0x00 -#define CFG_CTS_TO_ITSELF_ENABLED_MAX 0x01 -#define CFG_CTS_TO_ITSELF_ENABLED_DEF CFG_CTS_TO_ITSELF_ENABLED_MIN - -/* Antenna diversity param (h/w can select best antenna, based on signal) */ -#define CFG_SYS_ANTENNA_BOTH 0x00 /* NIC selects best antenna */ -#define CFG_SYS_ANTENNA_A 0x01 /* force antenna A */ -#define CFG_SYS_ANTENNA_B 0x03 /* force antenna B */ -#define CFG_SYS_ANTENNA_SLOW_DIV 0x02 /* consider background noise */ - -/* - * The definitions below were lifted off the ipw2100 driver, which only - * supports 'b' mode, so I'm sure these are not exactly correct. - * - * Somebody fix these!! - */ -#define REG_MIN_CHANNEL 0 -#define REG_MAX_CHANNEL 14 - -#define REG_CHANNEL_MASK 0x00003FFF -#define IPW_IBSS_11B_DEFAULT_MASK 0x87ff - -#define IPW_MAX_CONFIG_RETRIES 10 - -#endif /* __ipw2200_h__ */ diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h deleted file mode 100644 index 1e334ff6bd52..000000000000 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ /dev/null @@ -1,1088 +0,0 @@ -/* - * Merged with mainline ieee80211.h in Aug 2004. Original ieee802_11 - * remains copyright by the original authors - * - * Portions of the merged code are based on Host AP (software wireless - * LAN access point) driver for Intersil Prism2/2.5/3. - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * - * Adaption to a generic IEEE 802.11 stack by James Ketrenos - * - * Copyright (c) 2004-2005, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - * - * API Version History - * 1.0.x -- Initial version - * 1.1.x -- Added radiotap, QoS, TIM, libipw_geo APIs, - * various structure changes, and crypto API init method - */ -#ifndef LIBIPW_H -#define LIBIPW_H -#include /* ETH_ALEN */ -#include /* ARRAY_SIZE */ -#include -#include - -#include - -#define LIBIPW_VERSION "git-1.1.13" - -#define LIBIPW_DATA_LEN 2304 -/* Maximum size for the MA-UNITDATA primitive, 802.11 standard section - 6.2.1.1.2. - - The figure in section 7.1.2 suggests a body size of up to 2312 - bytes is allowed, which is a bit confusing, I suspect this - represents the 2304 bytes of real data, plus a possible 8 bytes of - WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */ - -#define LIBIPW_1ADDR_LEN 10 -#define LIBIPW_2ADDR_LEN 16 -#define LIBIPW_3ADDR_LEN 24 -#define LIBIPW_4ADDR_LEN 30 -#define LIBIPW_FCS_LEN 4 -#define LIBIPW_HLEN (LIBIPW_4ADDR_LEN) -#define LIBIPW_FRAME_LEN (LIBIPW_DATA_LEN + LIBIPW_HLEN) - -#define MIN_FRAG_THRESHOLD 256U -#define MAX_FRAG_THRESHOLD 2346U - -/* QOS control */ -#define LIBIPW_QCTL_TID 0x000F - -/* debug macros */ - -#ifdef CONFIG_LIBIPW_DEBUG -extern u32 libipw_debug_level; -#define LIBIPW_DEBUG(level, fmt, args...) \ -do { if (libipw_debug_level & (level)) \ - printk(KERN_DEBUG "ieee80211: %c %s " fmt, \ - in_interrupt() ? 'I' : 'U', __func__ , ## args); } while (0) -static inline bool libipw_ratelimit_debug(u32 level) -{ - return (libipw_debug_level & level) && net_ratelimit(); -} -#else -#define LIBIPW_DEBUG(level, fmt, args...) do {} while (0) -static inline bool libipw_ratelimit_debug(u32 level) -{ - return false; -} -#endif /* CONFIG_LIBIPW_DEBUG */ - -/* - * To use the debug system: - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of: - * - * #define LIBIPW_DL_xxxx VALUE - * - * shifting value to the left one bit from the previous entry. xxxx should be - * the name of the classification (for example, WEP) - * - * You then need to either add a LIBIPW_xxxx_DEBUG() macro definition for your - * classification, or use LIBIPW_DEBUG(LIBIPW_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * To add your debug level to the list of levels seen when you perform - * - * % cat /proc/net/ieee80211/debug_level - * - * you simply need to add your entry to the libipw_debug_level array. - * - * If you do not see debug_level in /proc/net/ieee80211 then you do not have - * CONFIG_LIBIPW_DEBUG defined in your kernel configuration - * - */ - -#define LIBIPW_DL_INFO (1<<0) -#define LIBIPW_DL_WX (1<<1) -#define LIBIPW_DL_SCAN (1<<2) -#define LIBIPW_DL_STATE (1<<3) -#define LIBIPW_DL_MGMT (1<<4) -#define LIBIPW_DL_FRAG (1<<5) -#define LIBIPW_DL_DROP (1<<7) - -#define LIBIPW_DL_TX (1<<8) -#define LIBIPW_DL_RX (1<<9) -#define LIBIPW_DL_QOS (1<<31) - -#define LIBIPW_ERROR(f, a...) printk(KERN_ERR "ieee80211: " f, ## a) -#define LIBIPW_WARNING(f, a...) printk(KERN_WARNING "ieee80211: " f, ## a) -#define LIBIPW_DEBUG_INFO(f, a...) LIBIPW_DEBUG(LIBIPW_DL_INFO, f, ## a) - -#define LIBIPW_DEBUG_WX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_WX, f, ## a) -#define LIBIPW_DEBUG_SCAN(f, a...) LIBIPW_DEBUG(LIBIPW_DL_SCAN, f, ## a) -#define LIBIPW_DEBUG_STATE(f, a...) LIBIPW_DEBUG(LIBIPW_DL_STATE, f, ## a) -#define LIBIPW_DEBUG_MGMT(f, a...) LIBIPW_DEBUG(LIBIPW_DL_MGMT, f, ## a) -#define LIBIPW_DEBUG_FRAG(f, a...) LIBIPW_DEBUG(LIBIPW_DL_FRAG, f, ## a) -#define LIBIPW_DEBUG_DROP(f, a...) LIBIPW_DEBUG(LIBIPW_DL_DROP, f, ## a) -#define LIBIPW_DEBUG_TX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_TX, f, ## a) -#define LIBIPW_DEBUG_RX(f, a...) LIBIPW_DEBUG(LIBIPW_DL_RX, f, ## a) -#define LIBIPW_DEBUG_QOS(f, a...) LIBIPW_DEBUG(LIBIPW_DL_QOS, f, ## a) -#include -#include /* ARPHRD_ETHER */ - -#ifndef WIRELESS_SPY -#define WIRELESS_SPY /* enable iwspy support */ -#endif -#include /* new driver API */ - -#define ETH_P_PREAUTH 0x88C7 /* IEEE 802.11i pre-authentication */ - -#ifndef ETH_P_80211_RAW -#define ETH_P_80211_RAW (ETH_P_ECONET + 1) -#endif - -/* IEEE 802.11 defines */ - -#define P80211_OUI_LEN 3 - -struct libipw_snap_hdr { - - u8 dsap; /* always 0xAA */ - u8 ssap; /* always 0xAA */ - u8 ctrl; /* always 0x03 */ - u8 oui[P80211_OUI_LEN]; /* organizational universal id */ - -} __attribute__ ((packed)); - -#define SNAP_SIZE sizeof(struct libipw_snap_hdr) - -#define WLAN_FC_GET_VERS(fc) ((fc) & IEEE80211_FCTL_VERS) -#define WLAN_FC_GET_TYPE(fc) ((fc) & IEEE80211_FCTL_FTYPE) -#define WLAN_FC_GET_STYPE(fc) ((fc) & IEEE80211_FCTL_STYPE) - -#define WLAN_GET_SEQ_FRAG(seq) ((seq) & IEEE80211_SCTL_FRAG) -#define WLAN_GET_SEQ_SEQ(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) - -#define LIBIPW_STATMASK_SIGNAL (1<<0) -#define LIBIPW_STATMASK_RSSI (1<<1) -#define LIBIPW_STATMASK_NOISE (1<<2) -#define LIBIPW_STATMASK_RATE (1<<3) -#define LIBIPW_STATMASK_WEMASK 0x7 - -#define LIBIPW_CCK_MODULATION (1<<0) -#define LIBIPW_OFDM_MODULATION (1<<1) - -#define LIBIPW_24GHZ_BAND (1<<0) -#define LIBIPW_52GHZ_BAND (1<<1) - -#define LIBIPW_CCK_RATE_1MB 0x02 -#define LIBIPW_CCK_RATE_2MB 0x04 -#define LIBIPW_CCK_RATE_5MB 0x0B -#define LIBIPW_CCK_RATE_11MB 0x16 -#define LIBIPW_OFDM_RATE_6MB 0x0C -#define LIBIPW_OFDM_RATE_9MB 0x12 -#define LIBIPW_OFDM_RATE_12MB 0x18 -#define LIBIPW_OFDM_RATE_18MB 0x24 -#define LIBIPW_OFDM_RATE_24MB 0x30 -#define LIBIPW_OFDM_RATE_36MB 0x48 -#define LIBIPW_OFDM_RATE_48MB 0x60 -#define LIBIPW_OFDM_RATE_54MB 0x6C -#define LIBIPW_BASIC_RATE_MASK 0x80 - -#define LIBIPW_CCK_RATE_1MB_MASK (1<<0) -#define LIBIPW_CCK_RATE_2MB_MASK (1<<1) -#define LIBIPW_CCK_RATE_5MB_MASK (1<<2) -#define LIBIPW_CCK_RATE_11MB_MASK (1<<3) -#define LIBIPW_OFDM_RATE_6MB_MASK (1<<4) -#define LIBIPW_OFDM_RATE_9MB_MASK (1<<5) -#define LIBIPW_OFDM_RATE_12MB_MASK (1<<6) -#define LIBIPW_OFDM_RATE_18MB_MASK (1<<7) -#define LIBIPW_OFDM_RATE_24MB_MASK (1<<8) -#define LIBIPW_OFDM_RATE_36MB_MASK (1<<9) -#define LIBIPW_OFDM_RATE_48MB_MASK (1<<10) -#define LIBIPW_OFDM_RATE_54MB_MASK (1<<11) - -#define LIBIPW_CCK_RATES_MASK 0x0000000F -#define LIBIPW_CCK_BASIC_RATES_MASK (LIBIPW_CCK_RATE_1MB_MASK | \ - LIBIPW_CCK_RATE_2MB_MASK) -#define LIBIPW_CCK_DEFAULT_RATES_MASK (LIBIPW_CCK_BASIC_RATES_MASK | \ - LIBIPW_CCK_RATE_5MB_MASK | \ - LIBIPW_CCK_RATE_11MB_MASK) - -#define LIBIPW_OFDM_RATES_MASK 0x00000FF0 -#define LIBIPW_OFDM_BASIC_RATES_MASK (LIBIPW_OFDM_RATE_6MB_MASK | \ - LIBIPW_OFDM_RATE_12MB_MASK | \ - LIBIPW_OFDM_RATE_24MB_MASK) -#define LIBIPW_OFDM_DEFAULT_RATES_MASK (LIBIPW_OFDM_BASIC_RATES_MASK | \ - LIBIPW_OFDM_RATE_9MB_MASK | \ - LIBIPW_OFDM_RATE_18MB_MASK | \ - LIBIPW_OFDM_RATE_36MB_MASK | \ - LIBIPW_OFDM_RATE_48MB_MASK | \ - LIBIPW_OFDM_RATE_54MB_MASK) -#define LIBIPW_DEFAULT_RATES_MASK (LIBIPW_OFDM_DEFAULT_RATES_MASK | \ - LIBIPW_CCK_DEFAULT_RATES_MASK) - -#define LIBIPW_NUM_OFDM_RATES 8 -#define LIBIPW_NUM_CCK_RATES 4 -#define LIBIPW_OFDM_SHIFT_MASK_A 4 - -/* NOTE: This data is for statistical purposes; not all hardware provides this - * information for frames received. - * For libipw_rx_mgt, you need to set at least the 'len' parameter. - */ -struct libipw_rx_stats { - u32 mac_time; - s8 rssi; - u8 signal; - u8 noise; - u16 rate; /* in 100 kbps */ - u8 received_channel; - u8 control; - u8 mask; - u8 freq; - u16 len; - u64 tsf; - u32 beacon_time; -}; - -/* IEEE 802.11 requires that STA supports concurrent reception of at least - * three fragmented frames. This define can be increased to support more - * concurrent frames, but it should be noted that each entry can consume about - * 2 kB of RAM and increasing cache size will slow down frame reassembly. */ -#define LIBIPW_FRAG_CACHE_LEN 4 - -struct libipw_frag_entry { - unsigned long first_frag_time; - unsigned int seq; - unsigned int last_frag; - struct sk_buff *skb; - u8 src_addr[ETH_ALEN]; - u8 dst_addr[ETH_ALEN]; -}; - -struct libipw_stats { - unsigned int tx_unicast_frames; - unsigned int tx_multicast_frames; - unsigned int tx_fragments; - unsigned int tx_unicast_octets; - unsigned int tx_multicast_octets; - unsigned int tx_deferred_transmissions; - unsigned int tx_single_retry_frames; - unsigned int tx_multiple_retry_frames; - unsigned int tx_retry_limit_exceeded; - unsigned int tx_discards; - unsigned int rx_unicast_frames; - unsigned int rx_multicast_frames; - unsigned int rx_fragments; - unsigned int rx_unicast_octets; - unsigned int rx_multicast_octets; - unsigned int rx_fcs_errors; - unsigned int rx_discards_no_buffer; - unsigned int tx_discards_wrong_sa; - unsigned int rx_discards_undecryptable; - unsigned int rx_message_in_msg_fragments; - unsigned int rx_message_in_bad_msg_fragments; -}; - -struct libipw_device; - -#define SEC_KEY_1 (1<<0) -#define SEC_KEY_2 (1<<1) -#define SEC_KEY_3 (1<<2) -#define SEC_KEY_4 (1<<3) -#define SEC_ACTIVE_KEY (1<<4) -#define SEC_AUTH_MODE (1<<5) -#define SEC_UNICAST_GROUP (1<<6) -#define SEC_LEVEL (1<<7) -#define SEC_ENABLED (1<<8) -#define SEC_ENCRYPT (1<<9) - -#define SEC_LEVEL_0 0 /* None */ -#define SEC_LEVEL_1 1 /* WEP 40 and 104 bit */ -#define SEC_LEVEL_2 2 /* Level 1 + TKIP */ -#define SEC_LEVEL_2_CKIP 3 /* Level 1 + CKIP */ -#define SEC_LEVEL_3 4 /* Level 2 + CCMP */ - -#define SEC_ALG_NONE 0 -#define SEC_ALG_WEP 1 -#define SEC_ALG_TKIP 2 -#define SEC_ALG_CCMP 3 - -#define WEP_KEYS 4 -#define WEP_KEY_LEN 13 -#define SCM_KEY_LEN 32 -#define SCM_TEMPORAL_KEY_LENGTH 16 - -struct libipw_security { - u16 active_key:2, enabled:1, unicast_uses_group:1, encrypt:1; - u8 auth_mode; - u8 encode_alg[WEP_KEYS]; - u8 key_sizes[WEP_KEYS]; - u8 keys[WEP_KEYS][SCM_KEY_LEN]; - u8 level; - u16 flags; -} __attribute__ ((packed)); - -/* - - 802.11 data frame from AP - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `-------------------------------------------------------------------' - -Total: 28-2340 bytes - -*/ - -#define BEACON_PROBE_SSID_ID_POSITION 12 - -struct libipw_hdr_1addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 payload[0]; -} __attribute__ ((packed)); - -struct libipw_hdr_2addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 payload[0]; -} __attribute__ ((packed)); - -struct libipw_hdr_3addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 payload[0]; -} __attribute__ ((packed)); - -struct libipw_hdr_4addr { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 addr4[ETH_ALEN]; - u8 payload[0]; -} __attribute__ ((packed)); - -struct libipw_hdr_3addrqos { - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 payload[0]; - __le16 qos_ctl; -} __attribute__ ((packed)); - -struct libipw_info_element { - u8 id; - u8 len; - u8 data[0]; -} __attribute__ ((packed)); - -/* - * These are the data types that can make up management packets - * - u16 auth_algorithm; - u16 auth_sequence; - u16 beacon_interval; - u16 capability; - u8 current_ap[ETH_ALEN]; - u16 listen_interval; - struct { - u16 association_id:14, reserved:2; - } __attribute__ ((packed)); - u32 time_stamp[2]; - u16 reason; - u16 status; -*/ - -struct libipw_auth { - struct libipw_hdr_3addr header; - __le16 algorithm; - __le16 transaction; - __le16 status; - /* challenge */ - struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); - -struct libipw_channel_switch { - u8 id; - u8 len; - u8 mode; - u8 channel; - u8 count; -} __attribute__ ((packed)); - -struct libipw_action { - struct libipw_hdr_3addr header; - u8 category; - u8 action; - union { - struct libipw_action_exchange { - u8 token; - struct libipw_info_element info_element[0]; - } exchange; - struct libipw_channel_switch channel_switch; - - } format; -} __attribute__ ((packed)); - -struct libipw_disassoc { - struct libipw_hdr_3addr header; - __le16 reason; -} __attribute__ ((packed)); - -/* Alias deauth for disassoc */ -#define libipw_deauth libipw_disassoc - -struct libipw_probe_request { - struct libipw_hdr_3addr header; - /* SSID, supported rates */ - struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); - -struct libipw_probe_response { - struct libipw_hdr_3addr header; - __le32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - /* SSID, supported rates, FH params, DS params, - * CF params, IBSS params, TIM (if beacon), RSN */ - struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); - -/* Alias beacon for probe_response */ -#define libipw_beacon libipw_probe_response - -struct libipw_assoc_request { - struct libipw_hdr_3addr header; - __le16 capability; - __le16 listen_interval; - /* SSID, supported rates, RSN */ - struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); - -struct libipw_reassoc_request { - struct libipw_hdr_3addr header; - __le16 capability; - __le16 listen_interval; - u8 current_ap[ETH_ALEN]; - struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); - -struct libipw_assoc_response { - struct libipw_hdr_3addr header; - __le16 capability; - __le16 status; - __le16 aid; - /* supported rates */ - struct libipw_info_element info_element[0]; -} __attribute__ ((packed)); - -struct libipw_txb { - u8 nr_frags; - u8 encrypted; - u8 rts_included; - u8 reserved; - u16 frag_size; - u16 payload_size; - struct sk_buff *fragments[0]; -}; - -/* SWEEP TABLE ENTRIES NUMBER */ -#define MAX_SWEEP_TAB_ENTRIES 42 -#define MAX_SWEEP_TAB_ENTRIES_PER_PACKET 7 -/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs - * only use 8, and then use extended rates for the remaining supported - * rates. Other APs, however, stick all of their supported rates on the - * main rates information element... */ -#define MAX_RATES_LENGTH ((u8)12) -#define MAX_RATES_EX_LENGTH ((u8)16) -#define MAX_NETWORK_COUNT 128 - -#define CRC_LENGTH 4U - -#define MAX_WPA_IE_LEN 64 - -#define NETWORK_HAS_OFDM (1<<1) -#define NETWORK_HAS_CCK (1<<2) - -/* QoS structure */ -#define NETWORK_HAS_QOS_PARAMETERS (1<<3) -#define NETWORK_HAS_QOS_INFORMATION (1<<4) -#define NETWORK_HAS_QOS_MASK (NETWORK_HAS_QOS_PARAMETERS | \ - NETWORK_HAS_QOS_INFORMATION) - -/* 802.11h */ -#define NETWORK_HAS_POWER_CONSTRAINT (1<<5) -#define NETWORK_HAS_CSA (1<<6) -#define NETWORK_HAS_QUIET (1<<7) -#define NETWORK_HAS_IBSS_DFS (1<<8) -#define NETWORK_HAS_TPC_REPORT (1<<9) - -#define NETWORK_HAS_ERP_VALUE (1<<10) - -#define QOS_QUEUE_NUM 4 -#define QOS_OUI_LEN 3 -#define QOS_OUI_TYPE 2 -#define QOS_ELEMENT_ID 221 -#define QOS_OUI_INFO_SUB_TYPE 0 -#define QOS_OUI_PARAM_SUB_TYPE 1 -#define QOS_VERSION_1 1 -#define QOS_AIFSN_MIN_VALUE 2 - -struct libipw_qos_information_element { - u8 elementID; - u8 length; - u8 qui[QOS_OUI_LEN]; - u8 qui_type; - u8 qui_subtype; - u8 version; - u8 ac_info; -} __attribute__ ((packed)); - -struct libipw_qos_ac_parameter { - u8 aci_aifsn; - u8 ecw_min_max; - __le16 tx_op_limit; -} __attribute__ ((packed)); - -struct libipw_qos_parameter_info { - struct libipw_qos_information_element info_element; - u8 reserved; - struct libipw_qos_ac_parameter ac_params_record[QOS_QUEUE_NUM]; -} __attribute__ ((packed)); - -struct libipw_qos_parameters { - __le16 cw_min[QOS_QUEUE_NUM]; - __le16 cw_max[QOS_QUEUE_NUM]; - u8 aifs[QOS_QUEUE_NUM]; - u8 flag[QOS_QUEUE_NUM]; - __le16 tx_op_limit[QOS_QUEUE_NUM]; -} __attribute__ ((packed)); - -struct libipw_qos_data { - struct libipw_qos_parameters parameters; - int active; - int supported; - u8 param_count; - u8 old_param_count; -}; - -struct libipw_tim_parameters { - u8 tim_count; - u8 tim_period; -} __attribute__ ((packed)); - -/*******************************************************/ - -enum { /* libipw_basic_report.map */ - LIBIPW_BASIC_MAP_BSS = (1 << 0), - LIBIPW_BASIC_MAP_OFDM = (1 << 1), - LIBIPW_BASIC_MAP_UNIDENTIFIED = (1 << 2), - LIBIPW_BASIC_MAP_RADAR = (1 << 3), - LIBIPW_BASIC_MAP_UNMEASURED = (1 << 4), - /* Bits 5-7 are reserved */ - -}; -struct libipw_basic_report { - u8 channel; - __le64 start_time; - __le16 duration; - u8 map; -} __attribute__ ((packed)); - -enum { /* libipw_measurement_request.mode */ - /* Bit 0 is reserved */ - LIBIPW_MEASUREMENT_ENABLE = (1 << 1), - LIBIPW_MEASUREMENT_REQUEST = (1 << 2), - LIBIPW_MEASUREMENT_REPORT = (1 << 3), - /* Bits 4-7 are reserved */ -}; - -enum { - LIBIPW_REPORT_BASIC = 0, /* required */ - LIBIPW_REPORT_CCA = 1, /* optional */ - LIBIPW_REPORT_RPI = 2, /* optional */ - /* 3-255 reserved */ -}; - -struct libipw_measurement_params { - u8 channel; - __le64 start_time; - __le16 duration; -} __attribute__ ((packed)); - -struct libipw_measurement_request { - struct libipw_info_element ie; - u8 token; - u8 mode; - u8 type; - struct libipw_measurement_params params[0]; -} __attribute__ ((packed)); - -struct libipw_measurement_report { - struct libipw_info_element ie; - u8 token; - u8 mode; - u8 type; - union { - struct libipw_basic_report basic[0]; - } u; -} __attribute__ ((packed)); - -struct libipw_tpc_report { - u8 transmit_power; - u8 link_margin; -} __attribute__ ((packed)); - -struct libipw_channel_map { - u8 channel; - u8 map; -} __attribute__ ((packed)); - -struct libipw_ibss_dfs { - struct libipw_info_element ie; - u8 owner[ETH_ALEN]; - u8 recovery_interval; - struct libipw_channel_map channel_map[0]; -}; - -struct libipw_csa { - u8 mode; - u8 channel; - u8 count; -} __attribute__ ((packed)); - -struct libipw_quiet { - u8 count; - u8 period; - u8 duration; - u8 offset; -} __attribute__ ((packed)); - -struct libipw_network { - /* These entries are used to identify a unique network */ - u8 bssid[ETH_ALEN]; - u8 channel; - /* Ensure null-terminated for any debug msgs */ - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - struct libipw_qos_data qos_data; - - /* These are network statistics */ - struct libipw_rx_stats stats; - u16 capability; - u8 rates[MAX_RATES_LENGTH]; - u8 rates_len; - u8 rates_ex[MAX_RATES_EX_LENGTH]; - u8 rates_ex_len; - unsigned long last_scanned; - u8 mode; - u32 flags; - u32 last_associate; - u32 time_stamp[2]; - u16 beacon_interval; - u16 listen_interval; - u16 atim_window; - u8 erp_value; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - struct libipw_tim_parameters tim; - - /* 802.11h info */ - - /* Power Constraint - mandatory if spctrm mgmt required */ - u8 power_constraint; - - /* TPC Report - mandatory if spctrm mgmt required */ - struct libipw_tpc_report tpc_report; - - /* IBSS DFS - mandatory if spctrm mgmt required and IBSS - * NOTE: This is variable length and so must be allocated dynamically */ - struct libipw_ibss_dfs *ibss_dfs; - - /* Channel Switch Announcement - optional if spctrm mgmt required */ - struct libipw_csa csa; - - /* Quiet - optional if spctrm mgmt required */ - struct libipw_quiet quiet; - - struct list_head list; -}; - -enum libipw_state { - LIBIPW_UNINITIALIZED = 0, - LIBIPW_INITIALIZED, - LIBIPW_ASSOCIATING, - LIBIPW_ASSOCIATED, - LIBIPW_AUTHENTICATING, - LIBIPW_AUTHENTICATED, - LIBIPW_SHUTDOWN -}; - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) -#define DEFAULT_FTS 2346 - -#define CFG_LIBIPW_RESERVE_FCS (1<<0) -#define CFG_LIBIPW_COMPUTE_FCS (1<<1) -#define CFG_LIBIPW_RTS (1<<2) - -#define LIBIPW_24GHZ_MIN_CHANNEL 1 -#define LIBIPW_24GHZ_MAX_CHANNEL 14 -#define LIBIPW_24GHZ_CHANNELS (LIBIPW_24GHZ_MAX_CHANNEL - \ - LIBIPW_24GHZ_MIN_CHANNEL + 1) - -#define LIBIPW_52GHZ_MIN_CHANNEL 34 -#define LIBIPW_52GHZ_MAX_CHANNEL 165 -#define LIBIPW_52GHZ_CHANNELS (LIBIPW_52GHZ_MAX_CHANNEL - \ - LIBIPW_52GHZ_MIN_CHANNEL + 1) - -enum { - LIBIPW_CH_PASSIVE_ONLY = (1 << 0), - LIBIPW_CH_80211H_RULES = (1 << 1), - LIBIPW_CH_B_ONLY = (1 << 2), - LIBIPW_CH_NO_IBSS = (1 << 3), - LIBIPW_CH_UNIFORM_SPREADING = (1 << 4), - LIBIPW_CH_RADAR_DETECT = (1 << 5), - LIBIPW_CH_INVALID = (1 << 6), -}; - -struct libipw_channel { - u32 freq; /* in MHz */ - u8 channel; - u8 flags; - u8 max_power; /* in dBm */ -}; - -struct libipw_geo { - u8 name[4]; - u8 bg_channels; - u8 a_channels; - struct libipw_channel bg[LIBIPW_24GHZ_CHANNELS]; - struct libipw_channel a[LIBIPW_52GHZ_CHANNELS]; -}; - -struct libipw_device { - struct net_device *dev; - struct libipw_security sec; - - /* Bookkeeping structures */ - struct libipw_stats ieee_stats; - - struct libipw_geo geo; - - /* Probe / Beacon management */ - struct list_head network_free_list; - struct list_head network_list; - struct libipw_network *networks; - int scans; - int scan_age; - - int iw_mode; /* operating mode (IW_MODE_*) */ - struct iw_spy_data spy_data; /* iwspy support */ - - spinlock_t lock; - - int tx_headroom; /* Set to size of any additional room needed at front - * of allocated Tx SKBs */ - u32 config; - - /* WEP and other encryption related settings at the device level */ - int open_wep; /* Set to 1 to allow unencrypted frames */ - - int reset_on_keychange; /* Set to 1 if the HW needs to be reset on - * WEP key changes */ - - /* If the host performs {en,de}cryption, then set to 1 */ - int host_encrypt; - int host_encrypt_msdu; - int host_decrypt; - /* host performs multicast decryption */ - int host_mc_decrypt; - - /* host should strip IV and ICV from protected frames */ - /* meaningful only when hardware decryption is being used */ - int host_strip_iv_icv; - - int host_open_frag; - int host_build_iv; - int ieee802_1x; /* is IEEE 802.1X used */ - - /* WPA data */ - int wpa_enabled; - int drop_unencrypted; - int privacy_invoked; - size_t wpa_ie_len; - u8 *wpa_ie; - - struct lib80211_crypt_info crypt_info; - - int bcrx_sta_key; /* use individual keys to override default keys even - * with RX of broad/multicast frames */ - - /* Fragmentation structures */ - struct libipw_frag_entry frag_cache[LIBIPW_FRAG_CACHE_LEN]; - unsigned int frag_next_idx; - u16 fts; /* Fragmentation Threshold */ - u16 rts; /* RTS threshold */ - - /* Association info */ - u8 bssid[ETH_ALEN]; - - enum libipw_state state; - - int mode; /* A, B, G */ - int modulation; /* CCK, OFDM */ - int freq_band; /* 2.4Ghz, 5.2Ghz, Mixed */ - int abg_true; /* ABG flag */ - - int perfect_rssi; - int worst_rssi; - - u16 prev_seq_ctl; /* used to drop duplicate frames */ - - /* Callback functions */ - void (*set_security) (struct net_device * dev, - struct libipw_security * sec); - netdev_tx_t (*hard_start_xmit) (struct libipw_txb * txb, - struct net_device * dev, int pri); - int (*reset_port) (struct net_device * dev); - int (*is_queue_full) (struct net_device * dev, int pri); - - int (*handle_management) (struct net_device * dev, - struct libipw_network * network, u16 type); - int (*is_qos_active) (struct net_device *dev, struct sk_buff *skb); - - /* Typical STA methods */ - int (*handle_auth) (struct net_device * dev, - struct libipw_auth * auth); - int (*handle_deauth) (struct net_device * dev, - struct libipw_deauth * auth); - int (*handle_action) (struct net_device * dev, - struct libipw_action * action, - struct libipw_rx_stats * stats); - int (*handle_disassoc) (struct net_device * dev, - struct libipw_disassoc * assoc); - int (*handle_beacon) (struct net_device * dev, - struct libipw_beacon * beacon, - struct libipw_network * network); - int (*handle_probe_response) (struct net_device * dev, - struct libipw_probe_response * resp, - struct libipw_network * network); - int (*handle_probe_request) (struct net_device * dev, - struct libipw_probe_request * req, - struct libipw_rx_stats * stats); - int (*handle_assoc_response) (struct net_device * dev, - struct libipw_assoc_response * resp, - struct libipw_network * network); - - /* Typical AP methods */ - int (*handle_assoc_request) (struct net_device * dev); - int (*handle_reassoc_request) (struct net_device * dev, - struct libipw_reassoc_request * req); - - /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_ieee80211 */ - u8 priv[0]; -}; - -#define IEEE_A (1<<0) -#define IEEE_B (1<<1) -#define IEEE_G (1<<2) -#define IEEE_MODE_MASK (IEEE_A|IEEE_B|IEEE_G) - -static inline void *libipw_priv(struct net_device *dev) -{ - return ((struct libipw_device *)netdev_priv(dev))->priv; -} - -static inline int libipw_is_valid_mode(struct libipw_device *ieee, - int mode) -{ - /* - * It is possible for both access points and our device to support - * combinations of modes, so as long as there is one valid combination - * of ap/device supported modes, then return success - * - */ - if ((mode & IEEE_A) && - (ieee->modulation & LIBIPW_OFDM_MODULATION) && - (ieee->freq_band & LIBIPW_52GHZ_BAND)) - return 1; - - if ((mode & IEEE_G) && - (ieee->modulation & LIBIPW_OFDM_MODULATION) && - (ieee->freq_band & LIBIPW_24GHZ_BAND)) - return 1; - - if ((mode & IEEE_B) && - (ieee->modulation & LIBIPW_CCK_MODULATION) && - (ieee->freq_band & LIBIPW_24GHZ_BAND)) - return 1; - - return 0; -} - -static inline int libipw_get_hdrlen(u16 fc) -{ - int hdrlen = LIBIPW_3ADDR_LEN; - u16 stype = WLAN_FC_GET_STYPE(fc); - - switch (WLAN_FC_GET_TYPE(fc)) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_FROMDS) && (fc & IEEE80211_FCTL_TODS)) - hdrlen = LIBIPW_4ADDR_LEN; - if (stype & IEEE80211_STYPE_QOS_DATA) - hdrlen += 2; - break; - case IEEE80211_FTYPE_CTL: - switch (WLAN_FC_GET_STYPE(fc)) { - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = LIBIPW_1ADDR_LEN; - break; - default: - hdrlen = LIBIPW_2ADDR_LEN; - break; - } - break; - } - - return hdrlen; -} - -static inline u8 *libipw_get_payload(struct ieee80211_hdr *hdr) -{ - switch (libipw_get_hdrlen(le16_to_cpu(hdr->frame_control))) { - case LIBIPW_1ADDR_LEN: - return ((struct libipw_hdr_1addr *)hdr)->payload; - case LIBIPW_2ADDR_LEN: - return ((struct libipw_hdr_2addr *)hdr)->payload; - case LIBIPW_3ADDR_LEN: - return ((struct libipw_hdr_3addr *)hdr)->payload; - case LIBIPW_4ADDR_LEN: - return ((struct libipw_hdr_4addr *)hdr)->payload; - } - return NULL; -} - -static inline int libipw_is_ofdm_rate(u8 rate) -{ - switch (rate & ~LIBIPW_BASIC_RATE_MASK) { - case LIBIPW_OFDM_RATE_6MB: - case LIBIPW_OFDM_RATE_9MB: - case LIBIPW_OFDM_RATE_12MB: - case LIBIPW_OFDM_RATE_18MB: - case LIBIPW_OFDM_RATE_24MB: - case LIBIPW_OFDM_RATE_36MB: - case LIBIPW_OFDM_RATE_48MB: - case LIBIPW_OFDM_RATE_54MB: - return 1; - } - return 0; -} - -static inline int libipw_is_cck_rate(u8 rate) -{ - switch (rate & ~LIBIPW_BASIC_RATE_MASK) { - case LIBIPW_CCK_RATE_1MB: - case LIBIPW_CCK_RATE_2MB: - case LIBIPW_CCK_RATE_5MB: - case LIBIPW_CCK_RATE_11MB: - return 1; - } - return 0; -} - -/* ieee80211.c */ -extern void free_ieee80211(struct net_device *dev); -extern struct net_device *alloc_ieee80211(int sizeof_priv); -extern int libipw_change_mtu(struct net_device *dev, int new_mtu); - -extern void libipw_networks_age(struct libipw_device *ieee, - unsigned long age_secs); - -extern int libipw_set_encryption(struct libipw_device *ieee); - -/* libipw_tx.c */ -extern netdev_tx_t libipw_xmit(struct sk_buff *skb, - struct net_device *dev); -extern void libipw_txb_free(struct libipw_txb *); - -/* libipw_rx.c */ -extern void libipw_rx_any(struct libipw_device *ieee, - struct sk_buff *skb, struct libipw_rx_stats *stats); -extern int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, - struct libipw_rx_stats *rx_stats); -/* make sure to set stats->len */ -extern void libipw_rx_mgt(struct libipw_device *ieee, - struct libipw_hdr_4addr *header, - struct libipw_rx_stats *stats); -extern void libipw_network_reset(struct libipw_network *network); - -/* libipw_geo.c */ -extern const struct libipw_geo *libipw_get_geo(struct libipw_device - *ieee); -extern int libipw_set_geo(struct libipw_device *ieee, - const struct libipw_geo *geo); - -extern int libipw_is_valid_channel(struct libipw_device *ieee, - u8 channel); -extern int libipw_channel_to_index(struct libipw_device *ieee, - u8 channel); -extern u8 libipw_freq_to_channel(struct libipw_device *ieee, u32 freq); -extern u8 libipw_get_channel_flags(struct libipw_device *ieee, - u8 channel); -extern const struct libipw_channel *libipw_get_channel(struct - libipw_device - *ieee, u8 channel); -extern u32 libipw_channel_to_freq(struct libipw_device * ieee, - u8 channel); - -/* libipw_wx.c */ -extern int libipw_wx_get_scan(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int libipw_wx_set_encode(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int libipw_wx_get_encode(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *key); -extern int libipw_wx_set_encodeext(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); -extern int libipw_wx_get_encodeext(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -static inline void libipw_increment_scans(struct libipw_device *ieee) -{ - ieee->scans++; -} - -static inline int libipw_get_scans(struct libipw_device *ieee) -{ - return ieee->scans; -} - -#endif /* LIBIPW_H */ diff --git a/drivers/net/wireless/ipw2x00/libipw_geo.c b/drivers/net/wireless/ipw2x00/libipw_geo.c deleted file mode 100644 index 65e8c175a4a0..000000000000 --- a/drivers/net/wireless/ipw2x00/libipw_geo.c +++ /dev/null @@ -1,195 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2005 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libipw.h" - -int libipw_is_valid_channel(struct libipw_device *ieee, u8 channel) -{ - int i; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) - return 0; - - if (ieee->freq_band & LIBIPW_24GHZ_BAND) - for (i = 0; i < ieee->geo.bg_channels; i++) - /* NOTE: If G mode is currently supported but - * this is a B only channel, we don't see it - * as valid. */ - if ((ieee->geo.bg[i].channel == channel) && - !(ieee->geo.bg[i].flags & LIBIPW_CH_INVALID) && - (!(ieee->mode & IEEE_G) || - !(ieee->geo.bg[i].flags & LIBIPW_CH_B_ONLY))) - return LIBIPW_24GHZ_BAND; - - if (ieee->freq_band & LIBIPW_52GHZ_BAND) - for (i = 0; i < ieee->geo.a_channels; i++) - if ((ieee->geo.a[i].channel == channel) && - !(ieee->geo.a[i].flags & LIBIPW_CH_INVALID)) - return LIBIPW_52GHZ_BAND; - - return 0; -} - -int libipw_channel_to_index(struct libipw_device *ieee, u8 channel) -{ - int i; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) - return -1; - - if (ieee->freq_band & LIBIPW_24GHZ_BAND) - for (i = 0; i < ieee->geo.bg_channels; i++) - if (ieee->geo.bg[i].channel == channel) - return i; - - if (ieee->freq_band & LIBIPW_52GHZ_BAND) - for (i = 0; i < ieee->geo.a_channels; i++) - if (ieee->geo.a[i].channel == channel) - return i; - - return -1; -} - -u32 libipw_channel_to_freq(struct libipw_device * ieee, u8 channel) -{ - const struct libipw_channel * ch; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) - return 0; - - ch = libipw_get_channel(ieee, channel); - if (!ch->channel) - return 0; - return ch->freq; -} - -u8 libipw_freq_to_channel(struct libipw_device * ieee, u32 freq) -{ - int i; - - /* Driver needs to initialize the geography map before using - * these helper functions */ - if (ieee->geo.bg_channels == 0 && ieee->geo.a_channels == 0) - return 0; - - freq /= 100000; - - if (ieee->freq_band & LIBIPW_24GHZ_BAND) - for (i = 0; i < ieee->geo.bg_channels; i++) - if (ieee->geo.bg[i].freq == freq) - return ieee->geo.bg[i].channel; - - if (ieee->freq_band & LIBIPW_52GHZ_BAND) - for (i = 0; i < ieee->geo.a_channels; i++) - if (ieee->geo.a[i].freq == freq) - return ieee->geo.a[i].channel; - - return 0; -} - -int libipw_set_geo(struct libipw_device *ieee, - const struct libipw_geo *geo) -{ - memcpy(ieee->geo.name, geo->name, 3); - ieee->geo.name[3] = '\0'; - ieee->geo.bg_channels = geo->bg_channels; - ieee->geo.a_channels = geo->a_channels; - memcpy(ieee->geo.bg, geo->bg, geo->bg_channels * - sizeof(struct libipw_channel)); - memcpy(ieee->geo.a, geo->a, ieee->geo.a_channels * - sizeof(struct libipw_channel)); - return 0; -} - -const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee) -{ - return &ieee->geo; -} - -u8 libipw_get_channel_flags(struct libipw_device * ieee, u8 channel) -{ - int index = libipw_channel_to_index(ieee, channel); - - if (index == -1) - return LIBIPW_CH_INVALID; - - if (channel <= LIBIPW_24GHZ_CHANNELS) - return ieee->geo.bg[index].flags; - - return ieee->geo.a[index].flags; -} - -static const struct libipw_channel bad_channel = { - .channel = 0, - .flags = LIBIPW_CH_INVALID, - .max_power = 0, -}; - -const struct libipw_channel *libipw_get_channel(struct libipw_device - *ieee, u8 channel) -{ - int index = libipw_channel_to_index(ieee, channel); - - if (index == -1) - return &bad_channel; - - if (channel <= LIBIPW_24GHZ_CHANNELS) - return &ieee->geo.bg[index]; - - return &ieee->geo.a[index]; -} - -EXPORT_SYMBOL(libipw_get_channel); -EXPORT_SYMBOL(libipw_get_channel_flags); -EXPORT_SYMBOL(libipw_is_valid_channel); -EXPORT_SYMBOL(libipw_freq_to_channel); -EXPORT_SYMBOL(libipw_channel_to_freq); -EXPORT_SYMBOL(libipw_channel_to_index); -EXPORT_SYMBOL(libipw_set_geo); -EXPORT_SYMBOL(libipw_get_geo); diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c deleted file mode 100644 index eb2b60834c17..000000000000 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ /dev/null @@ -1,296 +0,0 @@ -/******************************************************************************* - - Copyright(c) 2004-2005 Intel Corporation. All rights reserved. - - Portions of this file are based on the WEP enablement code provided by the - Host AP project hostap-drivers v0.1.3 - Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libipw.h" - -#define DRV_DESCRIPTION "802.11 data/management/control stack" -#define DRV_NAME "ieee80211" -#define DRV_VERSION LIBIPW_VERSION -#define DRV_COPYRIGHT "Copyright (C) 2004-2005 Intel Corporation " - -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT); -MODULE_LICENSE("GPL"); - -static int libipw_networks_allocate(struct libipw_device *ieee) -{ - if (ieee->networks) - return 0; - - ieee->networks = - kzalloc(MAX_NETWORK_COUNT * sizeof(struct libipw_network), - GFP_KERNEL); - if (!ieee->networks) { - printk(KERN_WARNING "%s: Out of memory allocating beacons\n", - ieee->dev->name); - return -ENOMEM; - } - - return 0; -} - -void libipw_network_reset(struct libipw_network *network) -{ - if (!network) - return; - - if (network->ibss_dfs) { - kfree(network->ibss_dfs); - network->ibss_dfs = NULL; - } -} - -static inline void libipw_networks_free(struct libipw_device *ieee) -{ - int i; - - if (!ieee->networks) - return; - - for (i = 0; i < MAX_NETWORK_COUNT; i++) - if (ieee->networks[i].ibss_dfs) - kfree(ieee->networks[i].ibss_dfs); - - kfree(ieee->networks); - ieee->networks = NULL; -} - -void libipw_networks_age(struct libipw_device *ieee, - unsigned long age_secs) -{ - struct libipw_network *network = NULL; - unsigned long flags; - unsigned long age_jiffies = msecs_to_jiffies(age_secs * MSEC_PER_SEC); - - spin_lock_irqsave(&ieee->lock, flags); - list_for_each_entry(network, &ieee->network_list, list) { - network->last_scanned -= age_jiffies; - } - spin_unlock_irqrestore(&ieee->lock, flags); -} -EXPORT_SYMBOL(libipw_networks_age); - -static void libipw_networks_initialize(struct libipw_device *ieee) -{ - int i; - - INIT_LIST_HEAD(&ieee->network_free_list); - INIT_LIST_HEAD(&ieee->network_list); - for (i = 0; i < MAX_NETWORK_COUNT; i++) - list_add_tail(&ieee->networks[i].list, - &ieee->network_free_list); -} - -int libipw_change_mtu(struct net_device *dev, int new_mtu) -{ - if ((new_mtu < 68) || (new_mtu > LIBIPW_DATA_LEN)) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} -EXPORT_SYMBOL(libipw_change_mtu); - -struct net_device *alloc_ieee80211(int sizeof_priv) -{ - struct libipw_device *ieee; - struct net_device *dev; - int err; - - LIBIPW_DEBUG_INFO("Initializing...\n"); - - dev = alloc_etherdev(sizeof(struct libipw_device) + sizeof_priv); - if (!dev) { - LIBIPW_ERROR("Unable to allocate network device.\n"); - goto failed; - } - ieee = netdev_priv(dev); - - ieee->dev = dev; - - err = libipw_networks_allocate(ieee); - if (err) { - LIBIPW_ERROR("Unable to allocate beacon storage: %d\n", err); - goto failed_free_netdev; - } - libipw_networks_initialize(ieee); - - /* Default fragmentation threshold is maximum payload size */ - ieee->fts = DEFAULT_FTS; - ieee->rts = DEFAULT_FTS; - ieee->scan_age = DEFAULT_MAX_SCAN_AGE; - ieee->open_wep = 1; - - /* Default to enabling full open WEP with host based encrypt/decrypt */ - ieee->host_encrypt = 1; - ieee->host_decrypt = 1; - ieee->host_mc_decrypt = 1; - - /* Host fragementation in Open mode. Default is enabled. - * Note: host fragmentation is always enabled if host encryption - * is enabled. For cards can do hardware encryption, they must do - * hardware fragmentation as well. So we don't need a variable - * like host_enc_frag. */ - ieee->host_open_frag = 1; - ieee->ieee802_1x = 1; /* Default to supporting 802.1x */ - - spin_lock_init(&ieee->lock); - - lib80211_crypt_info_init(&ieee->crypt_info, dev->name, &ieee->lock); - - ieee->wpa_enabled = 0; - ieee->drop_unencrypted = 0; - ieee->privacy_invoked = 0; - - return dev; - -failed_free_netdev: - free_netdev(dev); -failed: - return NULL; -} - -void free_ieee80211(struct net_device *dev) -{ - struct libipw_device *ieee = netdev_priv(dev); - - lib80211_crypt_info_free(&ieee->crypt_info); - - libipw_networks_free(ieee); - free_netdev(dev); -} - -#ifdef CONFIG_LIBIPW_DEBUG - -static int debug = 0; -u32 libipw_debug_level = 0; -EXPORT_SYMBOL_GPL(libipw_debug_level); -static struct proc_dir_entry *libipw_proc = NULL; - -static int show_debug_level(char *page, char **start, off_t offset, - int count, int *eof, void *data) -{ - return snprintf(page, count, "0x%08X\n", libipw_debug_level); -} - -static int store_debug_level(struct file *file, const char __user * buffer, - unsigned long count, void *data) -{ - char buf[] = "0x00000000\n"; - unsigned long len = min((unsigned long)sizeof(buf) - 1, count); - unsigned long val; - - if (copy_from_user(buf, buffer, len)) - return count; - buf[len] = 0; - if (sscanf(buf, "%li", &val) != 1) - printk(KERN_INFO DRV_NAME - ": %s is not in hex or decimal form.\n", buf); - else - libipw_debug_level = val; - - return strnlen(buf, len); -} -#endif /* CONFIG_LIBIPW_DEBUG */ - -static int __init libipw_init(void) -{ -#ifdef CONFIG_LIBIPW_DEBUG - struct proc_dir_entry *e; - - libipw_debug_level = debug; - libipw_proc = proc_mkdir(DRV_NAME, init_net.proc_net); - if (libipw_proc == NULL) { - LIBIPW_ERROR("Unable to create " DRV_NAME - " proc directory\n"); - return -EIO; - } - e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, - libipw_proc); - if (!e) { - remove_proc_entry(DRV_NAME, init_net.proc_net); - libipw_proc = NULL; - return -EIO; - } - e->read_proc = show_debug_level; - e->write_proc = store_debug_level; - e->data = NULL; -#endif /* CONFIG_LIBIPW_DEBUG */ - - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); - - return 0; -} - -static void __exit libipw_exit(void) -{ -#ifdef CONFIG_LIBIPW_DEBUG - if (libipw_proc) { - remove_proc_entry("debug_level", libipw_proc); - remove_proc_entry(DRV_NAME, init_net.proc_net); - libipw_proc = NULL; - } -#endif /* CONFIG_LIBIPW_DEBUG */ -} - -#ifdef CONFIG_LIBIPW_DEBUG -#include -module_param(debug, int, 0444); -MODULE_PARM_DESC(debug, "debug output mask"); -#endif /* CONFIG_LIBIPW_DEBUG */ - -module_exit(libipw_exit); -module_init(libipw_init); - -EXPORT_SYMBOL(alloc_ieee80211); -EXPORT_SYMBOL(free_ieee80211); diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c deleted file mode 100644 index 282b1f7ff1e9..000000000000 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ /dev/null @@ -1,1798 +0,0 @@ -/* - * Original code based Host AP (software wireless LAN access point) driver - * for Intersil Prism2/2.5/3 - hostap.o module, common routines - * - * Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - * - * Copyright (c) 2002-2003, Jouni Malinen - * Copyright (c) 2004-2005, Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. See README and COPYING for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "libipw.h" - -static void libipw_monitor_rx(struct libipw_device *ieee, - struct sk_buff *skb, - struct libipw_rx_stats *rx_stats) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 fc = le16_to_cpu(hdr->frame_control); - - skb->dev = ieee->dev; - skb_reset_mac_header(skb); - skb_pull(skb, libipw_get_hdrlen(fc)); - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_80211_RAW); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - -/* Called only as a tasklet (software IRQ) */ -static struct libipw_frag_entry *libipw_frag_cache_find(struct - libipw_device - *ieee, - unsigned int seq, - unsigned int frag, - u8 * src, - u8 * dst) -{ - struct libipw_frag_entry *entry; - int i; - - for (i = 0; i < LIBIPW_FRAG_CACHE_LEN; i++) { - entry = &ieee->frag_cache[i]; - if (entry->skb != NULL && - time_after(jiffies, entry->first_frag_time + 2 * HZ)) { - LIBIPW_DEBUG_FRAG("expiring fragment cache entry " - "seq=%u last_frag=%u\n", - entry->seq, entry->last_frag); - dev_kfree_skb_any(entry->skb); - entry->skb = NULL; - } - - if (entry->skb != NULL && entry->seq == seq && - (entry->last_frag + 1 == frag || frag == -1) && - !compare_ether_addr(entry->src_addr, src) && - !compare_ether_addr(entry->dst_addr, dst)) - return entry; - } - - return NULL; -} - -/* Called only as a tasklet (software IRQ) */ -static struct sk_buff *libipw_frag_cache_get(struct libipw_device *ieee, - struct libipw_hdr_4addr *hdr) -{ - struct sk_buff *skb = NULL; - u16 sc; - unsigned int frag, seq; - struct libipw_frag_entry *entry; - - sc = le16_to_cpu(hdr->seq_ctl); - frag = WLAN_GET_SEQ_FRAG(sc); - seq = WLAN_GET_SEQ_SEQ(sc); - - if (frag == 0) { - /* Reserve enough space to fit maximum frame length */ - skb = dev_alloc_skb(ieee->dev->mtu + - sizeof(struct libipw_hdr_4addr) + - 8 /* LLC */ + - 2 /* alignment */ + - 8 /* WEP */ + ETH_ALEN /* WDS */ ); - if (skb == NULL) - return NULL; - - entry = &ieee->frag_cache[ieee->frag_next_idx]; - ieee->frag_next_idx++; - if (ieee->frag_next_idx >= LIBIPW_FRAG_CACHE_LEN) - ieee->frag_next_idx = 0; - - if (entry->skb != NULL) - dev_kfree_skb_any(entry->skb); - - entry->first_frag_time = jiffies; - entry->seq = seq; - entry->last_frag = frag; - entry->skb = skb; - memcpy(entry->src_addr, hdr->addr2, ETH_ALEN); - memcpy(entry->dst_addr, hdr->addr1, ETH_ALEN); - } else { - /* received a fragment of a frame for which the head fragment - * should have already been received */ - entry = libipw_frag_cache_find(ieee, seq, frag, hdr->addr2, - hdr->addr1); - if (entry != NULL) { - entry->last_frag = frag; - skb = entry->skb; - } - } - - return skb; -} - -/* Called only as a tasklet (software IRQ) */ -static int libipw_frag_cache_invalidate(struct libipw_device *ieee, - struct libipw_hdr_4addr *hdr) -{ - u16 sc; - unsigned int seq; - struct libipw_frag_entry *entry; - - sc = le16_to_cpu(hdr->seq_ctl); - seq = WLAN_GET_SEQ_SEQ(sc); - - entry = libipw_frag_cache_find(ieee, seq, -1, hdr->addr2, - hdr->addr1); - - if (entry == NULL) { - LIBIPW_DEBUG_FRAG("could not invalidate fragment cache " - "entry (seq=%u)\n", seq); - return -1; - } - - entry->skb = NULL; - return 0; -} - -#ifdef NOT_YET -/* libipw_rx_frame_mgtmt - * - * Responsible for handling management control frames - * - * Called by libipw_rx */ -static int -libipw_rx_frame_mgmt(struct libipw_device *ieee, struct sk_buff *skb, - struct libipw_rx_stats *rx_stats, u16 type, - u16 stype) -{ - if (ieee->iw_mode == IW_MODE_MASTER) { - printk(KERN_DEBUG "%s: Master mode not yet suppported.\n", - ieee->dev->name); - return 0; -/* - hostap_update_sta_ps(ieee, (struct hostap_libipw_hdr_4addr *) - skb->data);*/ - } - - if (ieee->hostapd && type == WLAN_FC_TYPE_MGMT) { - if (stype == WLAN_FC_STYPE_BEACON && - ieee->iw_mode == IW_MODE_MASTER) { - struct sk_buff *skb2; - /* Process beacon frames also in kernel driver to - * update STA(AP) table statistics */ - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2) - hostap_rx(skb2->dev, skb2, rx_stats); - } - - /* send management frames to the user space daemon for - * processing */ - ieee->apdevstats.rx_packets++; - ieee->apdevstats.rx_bytes += skb->len; - prism2_rx_80211(ieee->apdev, skb, rx_stats, PRISM2_RX_MGMT); - return 0; - } - - if (ieee->iw_mode == IW_MODE_MASTER) { - if (type != WLAN_FC_TYPE_MGMT && type != WLAN_FC_TYPE_CTRL) { - printk(KERN_DEBUG "%s: unknown management frame " - "(type=0x%02x, stype=0x%02x) dropped\n", - skb->dev->name, type, stype); - return -1; - } - - hostap_rx(skb->dev, skb, rx_stats); - return 0; - } - - printk(KERN_DEBUG "%s: hostap_rx_frame_mgmt: management frame " - "received in non-Host AP mode\n", skb->dev->name); - return -1; -} -#endif - -/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */ -/* Ethernet-II snap header (RFC1042 for most EtherTypes) */ -static unsigned char libipw_rfc1042_header[] = - { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - -/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */ -static unsigned char libipw_bridge_tunnel_header[] = - { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 }; -/* No encapsulation header if EtherType < 0x600 (=length) */ - -/* Called by libipw_rx_frame_decrypt */ -static int libipw_is_eapol_frame(struct libipw_device *ieee, - struct sk_buff *skb) -{ - struct net_device *dev = ieee->dev; - u16 fc, ethertype; - struct libipw_hdr_3addr *hdr; - u8 *pos; - - if (skb->len < 24) - return 0; - - hdr = (struct libipw_hdr_3addr *)skb->data; - fc = le16_to_cpu(hdr->frame_ctl); - - /* check that the frame is unicast frame to us */ - if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS && - !compare_ether_addr(hdr->addr1, dev->dev_addr) && - !compare_ether_addr(hdr->addr3, dev->dev_addr)) { - /* ToDS frame with own addr BSSID and DA */ - } else if ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && - !compare_ether_addr(hdr->addr1, dev->dev_addr)) { - /* FromDS frame with own addr as DA */ - } else - return 0; - - if (skb->len < 24 + 8) - return 0; - - /* check for port access entity Ethernet type */ - pos = skb->data + 24; - ethertype = (pos[6] << 8) | pos[7]; - if (ethertype == ETH_P_PAE) - return 1; - - return 0; -} - -/* Called only as a tasklet (software IRQ), by libipw_rx */ -static int -libipw_rx_frame_decrypt(struct libipw_device *ieee, struct sk_buff *skb, - struct lib80211_crypt_data *crypt) -{ - struct libipw_hdr_3addr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_mpdu == NULL) - return 0; - - hdr = (struct libipw_hdr_3addr *)skb->data; - hdrlen = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_mpdu(skb, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - LIBIPW_DEBUG_DROP("decryption failed (SA=%pM) res=%d\n", - hdr->addr2, res); - if (res == -2) - LIBIPW_DEBUG_DROP("Decryption failed ICV " - "mismatch (key %d)\n", - skb->data[hdrlen + 3] >> 6); - ieee->ieee_stats.rx_discards_undecryptable++; - return -1; - } - - return res; -} - -/* Called only as a tasklet (software IRQ), by libipw_rx */ -static int -libipw_rx_frame_decrypt_msdu(struct libipw_device *ieee, - struct sk_buff *skb, int keyidx, - struct lib80211_crypt_data *crypt) -{ - struct libipw_hdr_3addr *hdr; - int res, hdrlen; - - if (crypt == NULL || crypt->ops->decrypt_msdu == NULL) - return 0; - - hdr = (struct libipw_hdr_3addr *)skb->data; - hdrlen = libipw_get_hdrlen(le16_to_cpu(hdr->frame_ctl)); - - atomic_inc(&crypt->refcnt); - res = crypt->ops->decrypt_msdu(skb, keyidx, hdrlen, crypt->priv); - atomic_dec(&crypt->refcnt); - if (res < 0) { - printk(KERN_DEBUG "%s: MSDU decryption/MIC verification failed" - " (SA=%pM keyidx=%d)\n", ieee->dev->name, hdr->addr2, - keyidx); - return -1; - } - - return 0; -} - -/* All received frames are sent to this function. @skb contains the frame in - * IEEE 802.11 format, i.e., in the format it was sent over air. - * This function is called only as a tasklet (software IRQ). */ -int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, - struct libipw_rx_stats *rx_stats) -{ - struct net_device *dev = ieee->dev; - struct libipw_hdr_4addr *hdr; - size_t hdrlen; - u16 fc, type, stype, sc; - unsigned int frag; - u8 *payload; - u16 ethertype; -#ifdef NOT_YET - struct net_device *wds = NULL; - struct sk_buff *skb2 = NULL; - struct net_device *wds = NULL; - int frame_authorized = 0; - int from_assoc_ap = 0; - void *sta = NULL; -#endif - u8 dst[ETH_ALEN]; - u8 src[ETH_ALEN]; - struct lib80211_crypt_data *crypt = NULL; - int keyidx = 0; - int can_be_decrypted = 0; - - hdr = (struct libipw_hdr_4addr *)skb->data; - if (skb->len < 10) { - printk(KERN_INFO "%s: SKB length < 10\n", dev->name); - goto rx_dropped; - } - - fc = le16_to_cpu(hdr->frame_ctl); - type = WLAN_FC_GET_TYPE(fc); - stype = WLAN_FC_GET_STYPE(fc); - sc = le16_to_cpu(hdr->seq_ctl); - frag = WLAN_GET_SEQ_FRAG(sc); - hdrlen = libipw_get_hdrlen(fc); - - if (skb->len < hdrlen) { - printk(KERN_INFO "%s: invalid SKB length %d\n", - dev->name, skb->len); - goto rx_dropped; - } - - /* Put this code here so that we avoid duplicating it in all - * Rx paths. - Jean II */ -#ifdef CONFIG_WIRELESS_EXT -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ - /* If spy monitoring on */ - if (ieee->spy_data.spy_number > 0) { - struct iw_quality wstats; - - wstats.updated = 0; - if (rx_stats->mask & LIBIPW_STATMASK_RSSI) { - wstats.level = rx_stats->signal; - wstats.updated |= IW_QUAL_LEVEL_UPDATED; - } else - wstats.updated |= IW_QUAL_LEVEL_INVALID; - - if (rx_stats->mask & LIBIPW_STATMASK_NOISE) { - wstats.noise = rx_stats->noise; - wstats.updated |= IW_QUAL_NOISE_UPDATED; - } else - wstats.updated |= IW_QUAL_NOISE_INVALID; - - if (rx_stats->mask & LIBIPW_STATMASK_SIGNAL) { - wstats.qual = rx_stats->signal; - wstats.updated |= IW_QUAL_QUAL_UPDATED; - } else - wstats.updated |= IW_QUAL_QUAL_INVALID; - - /* Update spy records */ - wireless_spy_update(ieee->dev, hdr->addr2, &wstats); - } -#endif /* IW_WIRELESS_SPY */ -#endif /* CONFIG_WIRELESS_EXT */ - -#ifdef NOT_YET - hostap_update_rx_stats(local->ap, hdr, rx_stats); -#endif - - if (ieee->iw_mode == IW_MODE_MONITOR) { - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - libipw_monitor_rx(ieee, skb, rx_stats); - return 1; - } - - can_be_decrypted = (is_multicast_ether_addr(hdr->addr1) || - is_broadcast_ether_addr(hdr->addr2)) ? - ieee->host_mc_decrypt : ieee->host_decrypt; - - if (can_be_decrypted) { - if (skb->len >= hdrlen + 3) { - /* Top two-bits of byte 3 are the key index */ - keyidx = skb->data[hdrlen + 3] >> 6; - } - - /* ieee->crypt[] is WEP_KEY (4) in length. Given that keyidx - * is only allowed 2-bits of storage, no value of keyidx can - * be provided via above code that would result in keyidx - * being out of range */ - crypt = ieee->crypt_info.crypt[keyidx]; - -#ifdef NOT_YET - sta = NULL; - - /* Use station specific key to override default keys if the - * receiver address is a unicast address ("individual RA"). If - * bcrx_sta_key parameter is set, station specific key is used - * even with broad/multicast targets (this is against IEEE - * 802.11, but makes it easier to use different keys with - * stations that do not support WEP key mapping). */ - - if (!(hdr->addr1[0] & 0x01) || local->bcrx_sta_key) - (void)hostap_handle_sta_crypto(local, hdr, &crypt, - &sta); -#endif - - /* allow NULL decrypt to indicate an station specific override - * for default encryption */ - if (crypt && (crypt->ops == NULL || - crypt->ops->decrypt_mpdu == NULL)) - crypt = NULL; - - if (!crypt && (fc & IEEE80211_FCTL_PROTECTED)) { - /* This seems to be triggered by some (multicast?) - * frames from other than current BSS, so just drop the - * frames silently instead of filling system log with - * these reports. */ - LIBIPW_DEBUG_DROP("Decryption failed (not set)" - " (SA=%pM)\n", hdr->addr2); - ieee->ieee_stats.rx_discards_undecryptable++; - goto rx_dropped; - } - } -#ifdef NOT_YET - if (type != WLAN_FC_TYPE_DATA) { - if (type == WLAN_FC_TYPE_MGMT && stype == WLAN_FC_STYPE_AUTH && - fc & IEEE80211_FCTL_PROTECTED && ieee->host_decrypt && - (keyidx = hostap_rx_frame_decrypt(ieee, skb, crypt)) < 0) { - printk(KERN_DEBUG "%s: failed to decrypt mgmt::auth " - "from %pM\n", dev->name, hdr->addr2); - /* TODO: could inform hostapd about this so that it - * could send auth failure report */ - goto rx_dropped; - } - - if (libipw_rx_frame_mgmt(ieee, skb, rx_stats, type, stype)) - goto rx_dropped; - else - goto rx_exit; - } -#endif - /* drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.29) */ - if (sc == ieee->prev_seq_ctl) - goto rx_dropped; - else - ieee->prev_seq_ctl = sc; - - /* Data frame - extract src/dst addresses */ - if (skb->len < LIBIPW_3ADDR_LEN) - goto rx_dropped; - - switch (fc & (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) { - case IEEE80211_FCTL_FROMDS: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr3, ETH_ALEN); - break; - case IEEE80211_FCTL_TODS: - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - break; - case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS: - if (skb->len < LIBIPW_4ADDR_LEN) - goto rx_dropped; - memcpy(dst, hdr->addr3, ETH_ALEN); - memcpy(src, hdr->addr4, ETH_ALEN); - break; - case 0: - memcpy(dst, hdr->addr1, ETH_ALEN); - memcpy(src, hdr->addr2, ETH_ALEN); - break; - } - -#ifdef NOT_YET - if (hostap_rx_frame_wds(ieee, hdr, fc, &wds)) - goto rx_dropped; - if (wds) { - skb->dev = dev = wds; - stats = hostap_get_stats(dev); - } - - if (ieee->iw_mode == IW_MODE_MASTER && !wds && - (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_FROMDS && ieee->stadev - && !compare_ether_addr(hdr->addr2, ieee->assoc_ap_addr)) { - /* Frame from BSSID of the AP for which we are a client */ - skb->dev = dev = ieee->stadev; - stats = hostap_get_stats(dev); - from_assoc_ap = 1; - } -#endif - -#ifdef NOT_YET - if ((ieee->iw_mode == IW_MODE_MASTER || - ieee->iw_mode == IW_MODE_REPEAT) && !from_assoc_ap) { - switch (hostap_handle_sta_rx(ieee, dev, skb, rx_stats, - wds != NULL)) { - case AP_RX_CONTINUE_NOT_AUTHORIZED: - frame_authorized = 0; - break; - case AP_RX_CONTINUE: - frame_authorized = 1; - break; - case AP_RX_DROP: - goto rx_dropped; - case AP_RX_EXIT: - goto rx_exit; - } - } -#endif - - /* Nullfunc frames may have PS-bit set, so they must be passed to - * hostap_handle_sta_rx() before being dropped here. */ - - stype &= ~IEEE80211_STYPE_QOS_DATA; - - if (stype != IEEE80211_STYPE_DATA && - stype != IEEE80211_STYPE_DATA_CFACK && - stype != IEEE80211_STYPE_DATA_CFPOLL && - stype != IEEE80211_STYPE_DATA_CFACKPOLL) { - if (stype != IEEE80211_STYPE_NULLFUNC) - LIBIPW_DEBUG_DROP("RX: dropped data frame " - "with no data (type=0x%02x, " - "subtype=0x%02x, len=%d)\n", - type, stype, skb->len); - goto rx_dropped; - } - - /* skb: hdr + (possibly fragmented, possibly encrypted) payload */ - - if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted && - (keyidx = libipw_rx_frame_decrypt(ieee, skb, crypt)) < 0) - goto rx_dropped; - - hdr = (struct libipw_hdr_4addr *)skb->data; - - /* skb: hdr + (possibly fragmented) plaintext payload */ - // PR: FIXME: hostap has additional conditions in the "if" below: - // ieee->host_decrypt && (fc & IEEE80211_FCTL_PROTECTED) && - if ((frag != 0) || (fc & IEEE80211_FCTL_MOREFRAGS)) { - int flen; - struct sk_buff *frag_skb = libipw_frag_cache_get(ieee, hdr); - LIBIPW_DEBUG_FRAG("Rx Fragment received (%u)\n", frag); - - if (!frag_skb) { - LIBIPW_DEBUG(LIBIPW_DL_RX | LIBIPW_DL_FRAG, - "Rx cannot get skb from fragment " - "cache (morefrag=%d seq=%u frag=%u)\n", - (fc & IEEE80211_FCTL_MOREFRAGS) != 0, - WLAN_GET_SEQ_SEQ(sc), frag); - goto rx_dropped; - } - - flen = skb->len; - if (frag != 0) - flen -= hdrlen; - - if (frag_skb->tail + flen > frag_skb->end) { - printk(KERN_WARNING "%s: host decrypted and " - "reassembled frame did not fit skb\n", - dev->name); - libipw_frag_cache_invalidate(ieee, hdr); - goto rx_dropped; - } - - if (frag == 0) { - /* copy first fragment (including full headers) into - * beginning of the fragment cache skb */ - skb_copy_from_linear_data(skb, skb_put(frag_skb, flen), flen); - } else { - /* append frame payload to the end of the fragment - * cache skb */ - skb_copy_from_linear_data_offset(skb, hdrlen, - skb_put(frag_skb, flen), flen); - } - dev_kfree_skb_any(skb); - skb = NULL; - - if (fc & IEEE80211_FCTL_MOREFRAGS) { - /* more fragments expected - leave the skb in fragment - * cache for now; it will be delivered to upper layers - * after all fragments have been received */ - goto rx_exit; - } - - /* this was the last fragment and the frame will be - * delivered, so remove skb from fragment cache */ - skb = frag_skb; - hdr = (struct libipw_hdr_4addr *)skb->data; - libipw_frag_cache_invalidate(ieee, hdr); - } - - /* skb: hdr + (possible reassembled) full MSDU payload; possibly still - * encrypted/authenticated */ - if ((fc & IEEE80211_FCTL_PROTECTED) && can_be_decrypted && - libipw_rx_frame_decrypt_msdu(ieee, skb, keyidx, crypt)) - goto rx_dropped; - - hdr = (struct libipw_hdr_4addr *)skb->data; - if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep) { - if ( /*ieee->ieee802_1x && */ - libipw_is_eapol_frame(ieee, skb)) { - /* pass unencrypted EAPOL frames even if encryption is - * configured */ - } else { - LIBIPW_DEBUG_DROP("encryption configured, but RX " - "frame not encrypted (SA=%pM)\n", - hdr->addr2); - goto rx_dropped; - } - } - - if (crypt && !(fc & IEEE80211_FCTL_PROTECTED) && !ieee->open_wep && - !libipw_is_eapol_frame(ieee, skb)) { - LIBIPW_DEBUG_DROP("dropped unencrypted RX data " - "frame from %pM (drop_unencrypted=1)\n", - hdr->addr2); - goto rx_dropped; - } - - /* If the frame was decrypted in hardware, we may need to strip off - * any security data (IV, ICV, etc) that was left behind */ - if (!can_be_decrypted && (fc & IEEE80211_FCTL_PROTECTED) && - ieee->host_strip_iv_icv) { - int trimlen = 0; - - /* Top two-bits of byte 3 are the key index */ - if (skb->len >= hdrlen + 3) - keyidx = skb->data[hdrlen + 3] >> 6; - - /* To strip off any security data which appears before the - * payload, we simply increase hdrlen (as the header gets - * chopped off immediately below). For the security data which - * appears after the payload, we use skb_trim. */ - - switch (ieee->sec.encode_alg[keyidx]) { - case SEC_ALG_WEP: - /* 4 byte IV */ - hdrlen += 4; - /* 4 byte ICV */ - trimlen = 4; - break; - case SEC_ALG_TKIP: - /* 4 byte IV, 4 byte ExtIV */ - hdrlen += 8; - /* 8 byte MIC, 4 byte ICV */ - trimlen = 12; - break; - case SEC_ALG_CCMP: - /* 8 byte CCMP header */ - hdrlen += 8; - /* 8 byte MIC */ - trimlen = 8; - break; - } - - if (skb->len < trimlen) - goto rx_dropped; - - __skb_trim(skb, skb->len - trimlen); - - if (skb->len < hdrlen) - goto rx_dropped; - } - - /* skb: hdr + (possible reassembled) full plaintext payload */ - - payload = skb->data + hdrlen; - ethertype = (payload[6] << 8) | payload[7]; - -#ifdef NOT_YET - /* If IEEE 802.1X is used, check whether the port is authorized to send - * the received frame. */ - if (ieee->ieee802_1x && ieee->iw_mode == IW_MODE_MASTER) { - if (ethertype == ETH_P_PAE) { - printk(KERN_DEBUG "%s: RX: IEEE 802.1X frame\n", - dev->name); - if (ieee->hostapd && ieee->apdev) { - /* Send IEEE 802.1X frames to the user - * space daemon for processing */ - prism2_rx_80211(ieee->apdev, skb, rx_stats, - PRISM2_RX_MGMT); - ieee->apdevstats.rx_packets++; - ieee->apdevstats.rx_bytes += skb->len; - goto rx_exit; - } - } else if (!frame_authorized) { - printk(KERN_DEBUG "%s: dropped frame from " - "unauthorized port (IEEE 802.1X): " - "ethertype=0x%04x\n", dev->name, ethertype); - goto rx_dropped; - } - } -#endif - - /* convert hdr + possible LLC headers into Ethernet header */ - if (skb->len - hdrlen >= 8 && - ((memcmp(payload, libipw_rfc1042_header, SNAP_SIZE) == 0 && - ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) || - memcmp(payload, libipw_bridge_tunnel_header, SNAP_SIZE) == 0)) { - /* remove RFC1042 or Bridge-Tunnel encapsulation and - * replace EtherType */ - skb_pull(skb, hdrlen + SNAP_SIZE); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } else { - __be16 len; - /* Leave Ethernet header part of hdr and full payload */ - skb_pull(skb, hdrlen); - len = htons(skb->len); - memcpy(skb_push(skb, 2), &len, 2); - memcpy(skb_push(skb, ETH_ALEN), src, ETH_ALEN); - memcpy(skb_push(skb, ETH_ALEN), dst, ETH_ALEN); - } - -#ifdef NOT_YET - if (wds && ((fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) == - IEEE80211_FCTL_TODS) && skb->len >= ETH_HLEN + ETH_ALEN) { - /* Non-standard frame: get addr4 from its bogus location after - * the payload */ - skb_copy_to_linear_data_offset(skb, ETH_ALEN, - skb->data + skb->len - ETH_ALEN, - ETH_ALEN); - skb_trim(skb, skb->len - ETH_ALEN); - } -#endif - - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - -#ifdef NOT_YET - if (ieee->iw_mode == IW_MODE_MASTER && !wds && ieee->ap->bridge_packets) { - if (dst[0] & 0x01) { - /* copy multicast frame both to the higher layers and - * to the wireless media */ - ieee->ap->bridged_multicast++; - skb2 = skb_clone(skb, GFP_ATOMIC); - if (skb2 == NULL) - printk(KERN_DEBUG "%s: skb_clone failed for " - "multicast frame\n", dev->name); - } else if (hostap_is_sta_assoc(ieee->ap, dst)) { - /* send frame directly to the associated STA using - * wireless media and not passing to higher layers */ - ieee->ap->bridged_unicast++; - skb2 = skb; - skb = NULL; - } - } - - if (skb2 != NULL) { - /* send to wireless media */ - skb2->dev = dev; - skb2->protocol = htons(ETH_P_802_3); - skb_reset_mac_header(skb2); - skb_reset_network_header(skb2); - /* skb2->network_header += ETH_HLEN; */ - dev_queue_xmit(skb2); - } -#endif - - if (skb) { - skb->protocol = eth_type_trans(skb, dev); - memset(skb->cb, 0, sizeof(skb->cb)); - skb->ip_summed = CHECKSUM_NONE; /* 802.11 crc not sufficient */ - if (netif_rx(skb) == NET_RX_DROP) { - /* netif_rx always succeeds, but it might drop - * the packet. If it drops the packet, we log that - * in our stats. */ - LIBIPW_DEBUG_DROP - ("RX: netif_rx dropped the packet\n"); - dev->stats.rx_dropped++; - } - } - - rx_exit: -#ifdef NOT_YET - if (sta) - hostap_handle_sta_release(sta); -#endif - return 1; - - rx_dropped: - dev->stats.rx_dropped++; - - /* Returning 0 indicates to caller that we have not handled the SKB-- - * so it is still allocated and can be used again by underlying - * hardware as a DMA target */ - return 0; -} - -/* Filter out unrelated packets, call libipw_rx[_mgt] - * This function takes over the skb, it should not be used again after calling - * this function. */ -void libipw_rx_any(struct libipw_device *ieee, - struct sk_buff *skb, struct libipw_rx_stats *stats) -{ - struct libipw_hdr_4addr *hdr; - int is_packet_for_us; - u16 fc; - - if (ieee->iw_mode == IW_MODE_MONITOR) { - if (!libipw_rx(ieee, skb, stats)) - dev_kfree_skb_irq(skb); - return; - } - - if (skb->len < sizeof(struct ieee80211_hdr)) - goto drop_free; - - hdr = (struct libipw_hdr_4addr *)skb->data; - fc = le16_to_cpu(hdr->frame_ctl); - - if ((fc & IEEE80211_FCTL_VERS) != 0) - goto drop_free; - - switch (fc & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_MGMT: - if (skb->len < sizeof(struct libipw_hdr_3addr)) - goto drop_free; - libipw_rx_mgt(ieee, hdr, stats); - dev_kfree_skb_irq(skb); - return; - case IEEE80211_FTYPE_DATA: - break; - case IEEE80211_FTYPE_CTL: - return; - default: - return; - } - - is_packet_for_us = 0; - switch (ieee->iw_mode) { - case IW_MODE_ADHOC: - /* our BSS and not from/to DS */ - if (memcmp(hdr->addr3, ieee->bssid, ETH_ALEN) == 0) - if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == 0) { - /* promisc: get all */ - if (ieee->dev->flags & IFF_PROMISC) - is_packet_for_us = 1; - /* to us */ - else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0) - is_packet_for_us = 1; - /* mcast */ - else if (is_multicast_ether_addr(hdr->addr1)) - is_packet_for_us = 1; - } - break; - case IW_MODE_INFRA: - /* our BSS (== from our AP) and from DS */ - if (memcmp(hdr->addr2, ieee->bssid, ETH_ALEN) == 0) - if ((fc & (IEEE80211_FCTL_TODS+IEEE80211_FCTL_FROMDS)) == IEEE80211_FCTL_FROMDS) { - /* promisc: get all */ - if (ieee->dev->flags & IFF_PROMISC) - is_packet_for_us = 1; - /* to us */ - else if (memcmp(hdr->addr1, ieee->dev->dev_addr, ETH_ALEN) == 0) - is_packet_for_us = 1; - /* mcast */ - else if (is_multicast_ether_addr(hdr->addr1)) { - /* not our own packet bcasted from AP */ - if (memcmp(hdr->addr3, ieee->dev->dev_addr, ETH_ALEN)) - is_packet_for_us = 1; - } - } - break; - default: - /* ? */ - break; - } - - if (is_packet_for_us) - if (!libipw_rx(ieee, skb, stats)) - dev_kfree_skb_irq(skb); - return; - -drop_free: - dev_kfree_skb_irq(skb); - ieee->dev->stats.rx_dropped++; - return; -} - -#define MGMT_FRAME_FIXED_PART_LENGTH 0x24 - -static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 }; - -/* -* Make ther structure we read from the beacon packet has -* the right values -*/ -static int libipw_verify_qos_info(struct libipw_qos_information_element - *info_element, int sub_type) -{ - - if (info_element->qui_subtype != sub_type) - return -1; - if (memcmp(info_element->qui, qos_oui, QOS_OUI_LEN)) - return -1; - if (info_element->qui_type != QOS_OUI_TYPE) - return -1; - if (info_element->version != QOS_VERSION_1) - return -1; - - return 0; -} - -/* - * Parse a QoS parameter element - */ -static int libipw_read_qos_param_element(struct libipw_qos_parameter_info - *element_param, struct libipw_info_element - *info_element) -{ - int ret = 0; - u16 size = sizeof(struct libipw_qos_parameter_info) - 2; - - if ((info_element == NULL) || (element_param == NULL)) - return -1; - - if (info_element->id == QOS_ELEMENT_ID && info_element->len == size) { - memcpy(element_param->info_element.qui, info_element->data, - info_element->len); - element_param->info_element.elementID = info_element->id; - element_param->info_element.length = info_element->len; - } else - ret = -1; - if (ret == 0) - ret = libipw_verify_qos_info(&element_param->info_element, - QOS_OUI_PARAM_SUB_TYPE); - return ret; -} - -/* - * Parse a QoS information element - */ -static int libipw_read_qos_info_element(struct - libipw_qos_information_element - *element_info, struct libipw_info_element - *info_element) -{ - int ret = 0; - u16 size = sizeof(struct libipw_qos_information_element) - 2; - - if (element_info == NULL) - return -1; - if (info_element == NULL) - return -1; - - if ((info_element->id == QOS_ELEMENT_ID) && (info_element->len == size)) { - memcpy(element_info->qui, info_element->data, - info_element->len); - element_info->elementID = info_element->id; - element_info->length = info_element->len; - } else - ret = -1; - - if (ret == 0) - ret = libipw_verify_qos_info(element_info, - QOS_OUI_INFO_SUB_TYPE); - return ret; -} - -/* - * Write QoS parameters from the ac parameters. - */ -static int libipw_qos_convert_ac_to_parameters(struct - libipw_qos_parameter_info - *param_elm, struct - libipw_qos_parameters - *qos_param) -{ - int rc = 0; - int i; - struct libipw_qos_ac_parameter *ac_params; - u32 txop; - u8 cw_min; - u8 cw_max; - - for (i = 0; i < QOS_QUEUE_NUM; i++) { - ac_params = &(param_elm->ac_params_record[i]); - - qos_param->aifs[i] = (ac_params->aci_aifsn) & 0x0F; - qos_param->aifs[i] -= (qos_param->aifs[i] < 2) ? 0 : 2; - - cw_min = ac_params->ecw_min_max & 0x0F; - qos_param->cw_min[i] = cpu_to_le16((1 << cw_min) - 1); - - cw_max = (ac_params->ecw_min_max & 0xF0) >> 4; - qos_param->cw_max[i] = cpu_to_le16((1 << cw_max) - 1); - - qos_param->flag[i] = - (ac_params->aci_aifsn & 0x10) ? 0x01 : 0x00; - - txop = le16_to_cpu(ac_params->tx_op_limit) * 32; - qos_param->tx_op_limit[i] = cpu_to_le16(txop); - } - return rc; -} - -/* - * we have a generic data element which it may contain QoS information or - * parameters element. check the information element length to decide - * which type to read - */ -static int libipw_parse_qos_info_param_IE(struct libipw_info_element - *info_element, - struct libipw_network *network) -{ - int rc = 0; - struct libipw_qos_parameters *qos_param = NULL; - struct libipw_qos_information_element qos_info_element; - - rc = libipw_read_qos_info_element(&qos_info_element, info_element); - - if (rc == 0) { - network->qos_data.param_count = qos_info_element.ac_info & 0x0F; - network->flags |= NETWORK_HAS_QOS_INFORMATION; - } else { - struct libipw_qos_parameter_info param_element; - - rc = libipw_read_qos_param_element(¶m_element, - info_element); - if (rc == 0) { - qos_param = &(network->qos_data.parameters); - libipw_qos_convert_ac_to_parameters(¶m_element, - qos_param); - network->flags |= NETWORK_HAS_QOS_PARAMETERS; - network->qos_data.param_count = - param_element.info_element.ac_info & 0x0F; - } - } - - if (rc == 0) { - LIBIPW_DEBUG_QOS("QoS is supported\n"); - network->qos_data.supported = 1; - } - return rc; -} - -#ifdef CONFIG_LIBIPW_DEBUG -#define MFIE_STRING(x) case WLAN_EID_ ##x: return #x - -static const char *get_info_element_string(u16 id) -{ - switch (id) { - MFIE_STRING(SSID); - MFIE_STRING(SUPP_RATES); - MFIE_STRING(FH_PARAMS); - MFIE_STRING(DS_PARAMS); - MFIE_STRING(CF_PARAMS); - MFIE_STRING(TIM); - MFIE_STRING(IBSS_PARAMS); - MFIE_STRING(COUNTRY); - MFIE_STRING(HP_PARAMS); - MFIE_STRING(HP_TABLE); - MFIE_STRING(REQUEST); - MFIE_STRING(CHALLENGE); - MFIE_STRING(PWR_CONSTRAINT); - MFIE_STRING(PWR_CAPABILITY); - MFIE_STRING(TPC_REQUEST); - MFIE_STRING(TPC_REPORT); - MFIE_STRING(SUPPORTED_CHANNELS); - MFIE_STRING(CHANNEL_SWITCH); - MFIE_STRING(MEASURE_REQUEST); - MFIE_STRING(MEASURE_REPORT); - MFIE_STRING(QUIET); - MFIE_STRING(IBSS_DFS); - MFIE_STRING(ERP_INFO); - MFIE_STRING(RSN); - MFIE_STRING(EXT_SUPP_RATES); - MFIE_STRING(GENERIC); - MFIE_STRING(QOS_PARAMETER); - default: - return "UNKNOWN"; - } -} -#endif - -static int libipw_parse_info_param(struct libipw_info_element - *info_element, u16 length, - struct libipw_network *network) -{ - DECLARE_SSID_BUF(ssid); - u8 i; -#ifdef CONFIG_LIBIPW_DEBUG - char rates_str[64]; - char *p; -#endif - - while (length >= sizeof(*info_element)) { - if (sizeof(*info_element) + info_element->len > length) { - LIBIPW_DEBUG_MGMT("Info elem: parse failed: " - "info_element->len + 2 > left : " - "info_element->len+2=%zd left=%d, id=%d.\n", - info_element->len + - sizeof(*info_element), - length, info_element->id); - /* We stop processing but don't return an error here - * because some misbehaviour APs break this rule. ie. - * Orinoco AP1000. */ - break; - } - - switch (info_element->id) { - case WLAN_EID_SSID: - network->ssid_len = min(info_element->len, - (u8) IW_ESSID_MAX_SIZE); - memcpy(network->ssid, info_element->data, - network->ssid_len); - if (network->ssid_len < IW_ESSID_MAX_SIZE) - memset(network->ssid + network->ssid_len, 0, - IW_ESSID_MAX_SIZE - network->ssid_len); - - LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->ssid_len); - break; - - case WLAN_EID_SUPP_RATES: -#ifdef CONFIG_LIBIPW_DEBUG - p = rates_str; -#endif - network->rates_len = min(info_element->len, - MAX_RATES_LENGTH); - for (i = 0; i < network->rates_len; i++) { - network->rates[i] = info_element->data[i]; -#ifdef CONFIG_LIBIPW_DEBUG - p += snprintf(p, sizeof(rates_str) - - (p - rates_str), "%02X ", - network->rates[i]); -#endif - if (libipw_is_ofdm_rate - (info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - LIBIPW_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - LIBIPW_DEBUG_MGMT("WLAN_EID_SUPP_RATES: '%s' (%d)\n", - rates_str, network->rates_len); - break; - - case WLAN_EID_EXT_SUPP_RATES: -#ifdef CONFIG_LIBIPW_DEBUG - p = rates_str; -#endif - network->rates_ex_len = min(info_element->len, - MAX_RATES_EX_LENGTH); - for (i = 0; i < network->rates_ex_len; i++) { - network->rates_ex[i] = info_element->data[i]; -#ifdef CONFIG_LIBIPW_DEBUG - p += snprintf(p, sizeof(rates_str) - - (p - rates_str), "%02X ", - network->rates[i]); -#endif - if (libipw_is_ofdm_rate - (info_element->data[i])) { - network->flags |= NETWORK_HAS_OFDM; - if (info_element->data[i] & - LIBIPW_BASIC_RATE_MASK) - network->flags &= - ~NETWORK_HAS_CCK; - } - } - - LIBIPW_DEBUG_MGMT("WLAN_EID_EXT_SUPP_RATES: '%s' (%d)\n", - rates_str, network->rates_ex_len); - break; - - case WLAN_EID_DS_PARAMS: - LIBIPW_DEBUG_MGMT("WLAN_EID_DS_PARAMS: %d\n", - info_element->data[0]); - network->channel = info_element->data[0]; - break; - - case WLAN_EID_FH_PARAMS: - LIBIPW_DEBUG_MGMT("WLAN_EID_FH_PARAMS: ignored\n"); - break; - - case WLAN_EID_CF_PARAMS: - LIBIPW_DEBUG_MGMT("WLAN_EID_CF_PARAMS: ignored\n"); - break; - - case WLAN_EID_TIM: - network->tim.tim_count = info_element->data[0]; - network->tim.tim_period = info_element->data[1]; - LIBIPW_DEBUG_MGMT("WLAN_EID_TIM: partially ignored\n"); - break; - - case WLAN_EID_ERP_INFO: - network->erp_value = info_element->data[0]; - network->flags |= NETWORK_HAS_ERP_VALUE; - LIBIPW_DEBUG_MGMT("MFIE_TYPE_ERP_SET: %d\n", - network->erp_value); - break; - - case WLAN_EID_IBSS_PARAMS: - network->atim_window = info_element->data[0]; - LIBIPW_DEBUG_MGMT("WLAN_EID_IBSS_PARAMS: %d\n", - network->atim_window); - break; - - case WLAN_EID_CHALLENGE: - LIBIPW_DEBUG_MGMT("WLAN_EID_CHALLENGE: ignored\n"); - break; - - case WLAN_EID_GENERIC: - LIBIPW_DEBUG_MGMT("WLAN_EID_GENERIC: %d bytes\n", - info_element->len); - if (!libipw_parse_qos_info_param_IE(info_element, - network)) - break; - - if (info_element->len >= 4 && - info_element->data[0] == 0x00 && - info_element->data[1] == 0x50 && - info_element->data[2] == 0xf2 && - info_element->data[3] == 0x01) { - network->wpa_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->wpa_ie, info_element, - network->wpa_ie_len); - } - break; - - case WLAN_EID_RSN: - LIBIPW_DEBUG_MGMT("WLAN_EID_RSN: %d bytes\n", - info_element->len); - network->rsn_ie_len = min(info_element->len + 2, - MAX_WPA_IE_LEN); - memcpy(network->rsn_ie, info_element, - network->rsn_ie_len); - break; - - case WLAN_EID_QOS_PARAMETER: - printk(KERN_ERR - "QoS Error need to parse QOS_PARAMETER IE\n"); - break; - /* 802.11h */ - case WLAN_EID_PWR_CONSTRAINT: - network->power_constraint = info_element->data[0]; - network->flags |= NETWORK_HAS_POWER_CONSTRAINT; - break; - - case WLAN_EID_CHANNEL_SWITCH: - network->power_constraint = info_element->data[0]; - network->flags |= NETWORK_HAS_CSA; - break; - - case WLAN_EID_QUIET: - network->quiet.count = info_element->data[0]; - network->quiet.period = info_element->data[1]; - network->quiet.duration = info_element->data[2]; - network->quiet.offset = info_element->data[3]; - network->flags |= NETWORK_HAS_QUIET; - break; - - case WLAN_EID_IBSS_DFS: - if (network->ibss_dfs) - break; - network->ibss_dfs = kmemdup(info_element->data, - info_element->len, - GFP_ATOMIC); - if (!network->ibss_dfs) - return 1; - network->flags |= NETWORK_HAS_IBSS_DFS; - break; - - case WLAN_EID_TPC_REPORT: - network->tpc_report.transmit_power = - info_element->data[0]; - network->tpc_report.link_margin = info_element->data[1]; - network->flags |= NETWORK_HAS_TPC_REPORT; - break; - - default: - LIBIPW_DEBUG_MGMT - ("Unsupported info element: %s (%d)\n", - get_info_element_string(info_element->id), - info_element->id); - break; - } - - length -= sizeof(*info_element) + info_element->len; - info_element = - (struct libipw_info_element *)&info_element-> - data[info_element->len]; - } - - return 0; -} - -static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_assoc_response - *frame, struct libipw_rx_stats *stats) -{ - struct libipw_network network_resp = { - .ibss_dfs = NULL, - }; - struct libipw_network *network = &network_resp; - struct net_device *dev = ieee->dev; - - network->flags = 0; - network->qos_data.active = 0; - network->qos_data.supported = 0; - network->qos_data.param_count = 0; - network->qos_data.old_param_count = 0; - - //network->atim_window = le16_to_cpu(frame->aid) & (0x3FFF); - network->atim_window = le16_to_cpu(frame->aid); - network->listen_interval = le16_to_cpu(frame->status); - memcpy(network->bssid, frame->header.addr3, ETH_ALEN); - network->capability = le16_to_cpu(frame->capability); - network->last_scanned = jiffies; - network->rates_len = network->rates_ex_len = 0; - network->last_associate = 0; - network->ssid_len = 0; - network->erp_value = - (network->capability & WLAN_CAPABILITY_IBSS) ? 0x3 : 0x0; - - if (stats->freq == LIBIPW_52GHZ_BAND) { - /* for A band (No DS info) */ - network->channel = stats->received_channel; - } else - network->flags |= NETWORK_HAS_CCK; - - network->wpa_ie_len = 0; - network->rsn_ie_len = 0; - - if (libipw_parse_info_param - (frame->info_element, stats->len - sizeof(*frame), network)) - return 1; - - network->mode = 0; - if (stats->freq == LIBIPW_52GHZ_BAND) - network->mode = IEEE_A; - else { - if (network->flags & NETWORK_HAS_OFDM) - network->mode |= IEEE_G; - if (network->flags & NETWORK_HAS_CCK) - network->mode |= IEEE_B; - } - - memcpy(&network->stats, stats, sizeof(network->stats)); - - if (ieee->handle_assoc_response != NULL) - ieee->handle_assoc_response(dev, frame, network); - - return 0; -} - -/***************************************************/ - -static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_response - *beacon, - struct libipw_network *network, - struct libipw_rx_stats *stats) -{ - DECLARE_SSID_BUF(ssid); - - network->qos_data.active = 0; - network->qos_data.supported = 0; - network->qos_data.param_count = 0; - network->qos_data.old_param_count = 0; - - /* Pull out fixed field data */ - memcpy(network->bssid, beacon->header.addr3, ETH_ALEN); - network->capability = le16_to_cpu(beacon->capability); - network->last_scanned = jiffies; - network->time_stamp[0] = le32_to_cpu(beacon->time_stamp[0]); - network->time_stamp[1] = le32_to_cpu(beacon->time_stamp[1]); - network->beacon_interval = le16_to_cpu(beacon->beacon_interval); - /* Where to pull this? beacon->listen_interval; */ - network->listen_interval = 0x0A; - network->rates_len = network->rates_ex_len = 0; - network->last_associate = 0; - network->ssid_len = 0; - network->flags = 0; - network->atim_window = 0; - network->erp_value = (network->capability & WLAN_CAPABILITY_IBSS) ? - 0x3 : 0x0; - - if (stats->freq == LIBIPW_52GHZ_BAND) { - /* for A band (No DS info) */ - network->channel = stats->received_channel; - } else - network->flags |= NETWORK_HAS_CCK; - - network->wpa_ie_len = 0; - network->rsn_ie_len = 0; - - if (libipw_parse_info_param - (beacon->info_element, stats->len - sizeof(*beacon), network)) - return 1; - - network->mode = 0; - if (stats->freq == LIBIPW_52GHZ_BAND) - network->mode = IEEE_A; - else { - if (network->flags & NETWORK_HAS_OFDM) - network->mode |= IEEE_G; - if (network->flags & NETWORK_HAS_CCK) - network->mode |= IEEE_B; - } - - if (network->mode == 0) { - LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' " - "network.\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid); - return 1; - } - - memcpy(&network->stats, stats, sizeof(network->stats)); - - return 0; -} - -static inline int is_same_network(struct libipw_network *src, - struct libipw_network *dst) -{ - /* A network is only a duplicate if the channel, BSSID, and ESSID - * all match. We treat all with the same BSSID and channel - * as one network */ - return ((src->ssid_len == dst->ssid_len) && - (src->channel == dst->channel) && - !compare_ether_addr(src->bssid, dst->bssid) && - !memcmp(src->ssid, dst->ssid, src->ssid_len)); -} - -static void update_network(struct libipw_network *dst, - struct libipw_network *src) -{ - int qos_active; - u8 old_param; - - libipw_network_reset(dst); - dst->ibss_dfs = src->ibss_dfs; - - /* We only update the statistics if they were created by receiving - * the network information on the actual channel the network is on. - * - * This keeps beacons received on neighbor channels from bringing - * down the signal level of an AP. */ - if (dst->channel == src->stats.received_channel) - memcpy(&dst->stats, &src->stats, - sizeof(struct libipw_rx_stats)); - else - LIBIPW_DEBUG_SCAN("Network %pM info received " - "off channel (%d vs. %d)\n", src->bssid, - dst->channel, src->stats.received_channel); - - dst->capability = src->capability; - memcpy(dst->rates, src->rates, src->rates_len); - dst->rates_len = src->rates_len; - memcpy(dst->rates_ex, src->rates_ex, src->rates_ex_len); - dst->rates_ex_len = src->rates_ex_len; - - dst->mode = src->mode; - dst->flags = src->flags; - dst->time_stamp[0] = src->time_stamp[0]; - dst->time_stamp[1] = src->time_stamp[1]; - - dst->beacon_interval = src->beacon_interval; - dst->listen_interval = src->listen_interval; - dst->atim_window = src->atim_window; - dst->erp_value = src->erp_value; - dst->tim = src->tim; - - memcpy(dst->wpa_ie, src->wpa_ie, src->wpa_ie_len); - dst->wpa_ie_len = src->wpa_ie_len; - memcpy(dst->rsn_ie, src->rsn_ie, src->rsn_ie_len); - dst->rsn_ie_len = src->rsn_ie_len; - - dst->last_scanned = jiffies; - qos_active = src->qos_data.active; - old_param = dst->qos_data.old_param_count; - if (dst->flags & NETWORK_HAS_QOS_MASK) - memcpy(&dst->qos_data, &src->qos_data, - sizeof(struct libipw_qos_data)); - else { - dst->qos_data.supported = src->qos_data.supported; - dst->qos_data.param_count = src->qos_data.param_count; - } - - if (dst->qos_data.supported == 1) { - if (dst->ssid_len) - LIBIPW_DEBUG_QOS - ("QoS the network %s is QoS supported\n", - dst->ssid); - else - LIBIPW_DEBUG_QOS - ("QoS the network is QoS supported\n"); - } - dst->qos_data.active = qos_active; - dst->qos_data.old_param_count = old_param; - - /* dst->last_associate is not overwritten */ -} - -static inline int is_beacon(__le16 fc) -{ - return (WLAN_FC_GET_STYPE(le16_to_cpu(fc)) == IEEE80211_STYPE_BEACON); -} - -static void libipw_process_probe_response(struct libipw_device - *ieee, struct - libipw_probe_response - *beacon, struct libipw_rx_stats - *stats) -{ - struct net_device *dev = ieee->dev; - struct libipw_network network = { - .ibss_dfs = NULL, - }; - struct libipw_network *target; - struct libipw_network *oldest = NULL; -#ifdef CONFIG_LIBIPW_DEBUG - struct libipw_info_element *info_element = beacon->info_element; -#endif - unsigned long flags; - DECLARE_SSID_BUF(ssid); - - LIBIPW_DEBUG_SCAN("'%s' (%pM" - "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", - print_ssid(ssid, info_element->data, info_element->len), - beacon->header.addr3, - (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0xd)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0xc)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0xb)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0xa)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x9)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x8)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x7)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x6)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x5)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x4)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x3)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x2)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x1)) ? '1' : '0', - (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0'); - - if (libipw_network_init(ieee, beacon, &network, stats)) { - LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", - print_ssid(ssid, info_element->data, - info_element->len), - beacon->header.addr3, - is_beacon(beacon->header.frame_ctl) ? - "BEACON" : "PROBE RESPONSE"); - return; - } - - /* The network parsed correctly -- so now we scan our known networks - * to see if we can find it in our list. - * - * NOTE: This search is definitely not optimized. Once its doing - * the "right thing" we'll optimize it for efficiency if - * necessary */ - - /* Search for this entry in the list and update it if it is - * already there. */ - - spin_lock_irqsave(&ieee->lock, flags); - - list_for_each_entry(target, &ieee->network_list, list) { - if (is_same_network(target, &network)) - break; - - if ((oldest == NULL) || - time_before(target->last_scanned, oldest->last_scanned)) - oldest = target; - } - - /* If we didn't find a match, then get a new network slot to initialize - * with this beacon's information */ - if (&target->list == &ieee->network_list) { - if (list_empty(&ieee->network_free_list)) { - /* If there are no more slots, expire the oldest */ - list_del(&oldest->list); - target = oldest; - LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from " - "network list.\n", - print_ssid(ssid, target->ssid, - target->ssid_len), - target->bssid); - libipw_network_reset(target); - } else { - /* Otherwise just pull from the free list */ - target = list_entry(ieee->network_free_list.next, - struct libipw_network, list); - list_del(ieee->network_free_list.next); - } - -#ifdef CONFIG_LIBIPW_DEBUG - LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", - print_ssid(ssid, network.ssid, - network.ssid_len), - network.bssid, - is_beacon(beacon->header.frame_ctl) ? - "BEACON" : "PROBE RESPONSE"); -#endif - memcpy(target, &network, sizeof(*target)); - network.ibss_dfs = NULL; - list_add_tail(&target->list, &ieee->network_list); - } else { - LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", - print_ssid(ssid, target->ssid, - target->ssid_len), - target->bssid, - is_beacon(beacon->header.frame_ctl) ? - "BEACON" : "PROBE RESPONSE"); - update_network(target, &network); - network.ibss_dfs = NULL; - } - - spin_unlock_irqrestore(&ieee->lock, flags); - - if (is_beacon(beacon->header.frame_ctl)) { - if (ieee->handle_beacon != NULL) - ieee->handle_beacon(dev, beacon, target); - } else { - if (ieee->handle_probe_response != NULL) - ieee->handle_probe_response(dev, beacon, target); - } -} - -void libipw_rx_mgt(struct libipw_device *ieee, - struct libipw_hdr_4addr *header, - struct libipw_rx_stats *stats) -{ - switch (WLAN_FC_GET_STYPE(le16_to_cpu(header->frame_ctl))) { - case IEEE80211_STYPE_ASSOC_RESP: - LIBIPW_DEBUG_MGMT("received ASSOCIATION RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - libipw_handle_assoc_resp(ieee, - (struct libipw_assoc_response *) - header, stats); - break; - - case IEEE80211_STYPE_REASSOC_RESP: - LIBIPW_DEBUG_MGMT("received REASSOCIATION RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - break; - - case IEEE80211_STYPE_PROBE_REQ: - LIBIPW_DEBUG_MGMT("received auth (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - - if (ieee->handle_probe_request != NULL) - ieee->handle_probe_request(ieee->dev, - (struct - libipw_probe_request *) - header, stats); - break; - - case IEEE80211_STYPE_PROBE_RESP: - LIBIPW_DEBUG_MGMT("received PROBE RESPONSE (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - LIBIPW_DEBUG_SCAN("Probe response\n"); - libipw_process_probe_response(ieee, - (struct - libipw_probe_response *) - header, stats); - break; - - case IEEE80211_STYPE_BEACON: - LIBIPW_DEBUG_MGMT("received BEACON (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - LIBIPW_DEBUG_SCAN("Beacon\n"); - libipw_process_probe_response(ieee, - (struct - libipw_probe_response *) - header, stats); - break; - case IEEE80211_STYPE_AUTH: - - LIBIPW_DEBUG_MGMT("received auth (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - - if (ieee->handle_auth != NULL) - ieee->handle_auth(ieee->dev, - (struct libipw_auth *)header); - break; - - case IEEE80211_STYPE_DISASSOC: - if (ieee->handle_disassoc != NULL) - ieee->handle_disassoc(ieee->dev, - (struct libipw_disassoc *) - header); - break; - - case IEEE80211_STYPE_ACTION: - LIBIPW_DEBUG_MGMT("ACTION\n"); - if (ieee->handle_action) - ieee->handle_action(ieee->dev, - (struct libipw_action *) - header, stats); - break; - - case IEEE80211_STYPE_REASSOC_REQ: - LIBIPW_DEBUG_MGMT("received reassoc (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - - LIBIPW_DEBUG_MGMT("%s: LIBIPW_REASSOC_REQ received\n", - ieee->dev->name); - if (ieee->handle_reassoc_request != NULL) - ieee->handle_reassoc_request(ieee->dev, - (struct libipw_reassoc_request *) - header); - break; - - case IEEE80211_STYPE_ASSOC_REQ: - LIBIPW_DEBUG_MGMT("received assoc (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - - LIBIPW_DEBUG_MGMT("%s: LIBIPW_ASSOC_REQ received\n", - ieee->dev->name); - if (ieee->handle_assoc_request != NULL) - ieee->handle_assoc_request(ieee->dev); - break; - - case IEEE80211_STYPE_DEAUTH: - LIBIPW_DEBUG_MGMT("DEAUTH\n"); - if (ieee->handle_deauth != NULL) - ieee->handle_deauth(ieee->dev, - (struct libipw_deauth *) - header); - break; - default: - LIBIPW_DEBUG_MGMT("received UNKNOWN (%d)\n", - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - LIBIPW_DEBUG_MGMT("%s: Unknown management packet: %d\n", - ieee->dev->name, - WLAN_FC_GET_STYPE(le16_to_cpu - (header->frame_ctl))); - break; - } -} - -EXPORT_SYMBOL_GPL(libipw_rx_any); -EXPORT_SYMBOL(libipw_rx_mgt); -EXPORT_SYMBOL(libipw_rx); diff --git a/drivers/net/wireless/ipw2x00/libipw_tx.c b/drivers/net/wireless/ipw2x00/libipw_tx.c deleted file mode 100644 index da8beac7fcf3..000000000000 --- a/drivers/net/wireless/ipw2x00/libipw_tx.c +++ /dev/null @@ -1,546 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2003 - 2005 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -******************************************************************************/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "libipw.h" - -/* - -802.11 Data Frame - - ,-------------------------------------------------------------------. -Bytes | 2 | 2 | 6 | 6 | 6 | 2 | 0..2312 | 4 | - |------|------|---------|---------|---------|------|---------|------| -Desc. | ctrl | dura | DA/RA | TA | SA | Sequ | Frame | fcs | - | | tion | (BSSID) | | | ence | data | | - `--------------------------------------------------| |------' -Total: 28 non-data bytes `----.----' - | - .- 'Frame data' expands, if WEP enabled, to <----------' - | - V - ,-----------------------. -Bytes | 4 | 0-2296 | 4 | - |-----|-----------|-----| -Desc. | IV | Encrypted | ICV | - | | Packet | | - `-----| |-----' - `-----.-----' - | - .- 'Encrypted Packet' expands to - | - V - ,---------------------------------------------------. -Bytes | 1 | 1 | 1 | 3 | 2 | 0-2304 | - |------|------|---------|----------|------|---------| -Desc. | SNAP | SNAP | Control |Eth Tunnel| Type | IP | - | DSAP | SSAP | | | | Packet | - | 0xAA | 0xAA |0x03 (UI)|0x00-00-F8| | | - `---------------------------------------------------- -Total: 8 non-data bytes - -802.3 Ethernet Data Frame - - ,-----------------------------------------. -Bytes | 6 | 6 | 2 | Variable | 4 | - |-------|-------|------|-----------|------| -Desc. | Dest. | Source| Type | IP Packet | fcs | - | MAC | MAC | | | | - `-----------------------------------------' -Total: 18 non-data bytes - -In the event that fragmentation is required, the incoming payload is split into -N parts of size ieee->fts. The first fragment contains the SNAP header and the -remaining packets are just data. - -If encryption is enabled, each fragment payload size is reduced by enough space -to add the prefix and postfix (IV and ICV totalling 8 bytes in the case of WEP) -So if you have 1500 bytes of payload with ieee->fts set to 500 without -encryption it will take 3 frames. With WEP it will take 4 frames as the -payload of each frame is reduced to 492 bytes. - -* SKB visualization -* -* ,- skb->data -* | -* | ETHERNET HEADER ,-<-- PAYLOAD -* | | 14 bytes from skb->data -* | 2 bytes for Type --> ,T. | (sizeof ethhdr) -* | | | | -* |,-Dest.--. ,--Src.---. | | | -* | 6 bytes| | 6 bytes | | | | -* v | | | | | | -* 0 | v 1 | v | v 2 -* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 -* ^ | ^ | ^ | -* | | | | | | -* | | | | `T' <---- 2 bytes for Type -* | | | | -* | | '---SNAP--' <-------- 6 bytes for SNAP -* | | -* `-IV--' <-------------------- 4 bytes for IV (WEP) -* -* SNAP HEADER -* -*/ - -static u8 P802_1H_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0xf8 }; -static u8 RFC1042_OUI[P80211_OUI_LEN] = { 0x00, 0x00, 0x00 }; - -static int libipw_copy_snap(u8 * data, __be16 h_proto) -{ - struct libipw_snap_hdr *snap; - u8 *oui; - - snap = (struct libipw_snap_hdr *)data; - snap->dsap = 0xaa; - snap->ssap = 0xaa; - snap->ctrl = 0x03; - - if (h_proto == htons(ETH_P_AARP) || h_proto == htons(ETH_P_IPX)) - oui = P802_1H_OUI; - else - oui = RFC1042_OUI; - snap->oui[0] = oui[0]; - snap->oui[1] = oui[1]; - snap->oui[2] = oui[2]; - - memcpy(data + SNAP_SIZE, &h_proto, sizeof(u16)); - - return SNAP_SIZE + sizeof(u16); -} - -static int libipw_encrypt_fragment(struct libipw_device *ieee, - struct sk_buff *frag, int hdr_len) -{ - struct lib80211_crypt_data *crypt = - ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; - int res; - - if (crypt == NULL) - return -1; - - /* To encrypt, frame format is: - * IV (4 bytes), clear payload (including SNAP), ICV (4 bytes) */ - atomic_inc(&crypt->refcnt); - res = 0; - if (crypt->ops && crypt->ops->encrypt_mpdu) - res = crypt->ops->encrypt_mpdu(frag, hdr_len, crypt->priv); - - atomic_dec(&crypt->refcnt); - if (res < 0) { - printk(KERN_INFO "%s: Encryption failed: len=%d.\n", - ieee->dev->name, frag->len); - ieee->ieee_stats.tx_discards++; - return -1; - } - - return 0; -} - -void libipw_txb_free(struct libipw_txb *txb) -{ - int i; - if (unlikely(!txb)) - return; - for (i = 0; i < txb->nr_frags; i++) - if (txb->fragments[i]) - dev_kfree_skb_any(txb->fragments[i]); - kfree(txb); -} - -static struct libipw_txb *libipw_alloc_txb(int nr_frags, int txb_size, - int headroom, gfp_t gfp_mask) -{ - struct libipw_txb *txb; - int i; - txb = kmalloc(sizeof(struct libipw_txb) + (sizeof(u8 *) * nr_frags), - gfp_mask); - if (!txb) - return NULL; - - memset(txb, 0, sizeof(struct libipw_txb)); - txb->nr_frags = nr_frags; - txb->frag_size = txb_size; - - for (i = 0; i < nr_frags; i++) { - txb->fragments[i] = __dev_alloc_skb(txb_size + headroom, - gfp_mask); - if (unlikely(!txb->fragments[i])) { - i--; - break; - } - skb_reserve(txb->fragments[i], headroom); - } - if (unlikely(i != nr_frags)) { - while (i >= 0) - dev_kfree_skb_any(txb->fragments[i--]); - kfree(txb); - return NULL; - } - return txb; -} - -static int libipw_classify(struct sk_buff *skb) -{ - struct ethhdr *eth; - struct iphdr *ip; - - eth = (struct ethhdr *)skb->data; - if (eth->h_proto != htons(ETH_P_IP)) - return 0; - - ip = ip_hdr(skb); - switch (ip->tos & 0xfc) { - case 0x20: - return 2; - case 0x40: - return 1; - case 0x60: - return 3; - case 0x80: - return 4; - case 0xa0: - return 5; - case 0xc0: - return 6; - case 0xe0: - return 7; - default: - return 0; - } -} - -/* Incoming skb is converted to a txb which consists of - * a block of 802.11 fragment packets (stored as skbs) */ -netdev_tx_t libipw_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct libipw_device *ieee = netdev_priv(dev); - struct libipw_txb *txb = NULL; - struct libipw_hdr_3addrqos *frag_hdr; - int i, bytes_per_frag, nr_frags, bytes_last_frag, frag_size, - rts_required; - unsigned long flags; - int encrypt, host_encrypt, host_encrypt_msdu, host_build_iv; - __be16 ether_type; - int bytes, fc, hdr_len; - struct sk_buff *skb_frag; - struct libipw_hdr_3addrqos header = {/* Ensure zero initialized */ - .duration_id = 0, - .seq_ctl = 0, - .qos_ctl = 0 - }; - u8 dest[ETH_ALEN], src[ETH_ALEN]; - struct lib80211_crypt_data *crypt; - int priority = skb->priority; - int snapped = 0; - - if (ieee->is_queue_full && (*ieee->is_queue_full) (dev, priority)) - return NETDEV_TX_BUSY; - - spin_lock_irqsave(&ieee->lock, flags); - - /* If there is no driver handler to take the TXB, dont' bother - * creating it... */ - if (!ieee->hard_start_xmit) { - printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); - goto success; - } - - if (unlikely(skb->len < SNAP_SIZE + sizeof(u16))) { - printk(KERN_WARNING "%s: skb too small (%d).\n", - ieee->dev->name, skb->len); - goto success; - } - - ether_type = ((struct ethhdr *)skb->data)->h_proto; - - crypt = ieee->crypt_info.crypt[ieee->crypt_info.tx_keyidx]; - - encrypt = !(ether_type == htons(ETH_P_PAE) && ieee->ieee802_1x) && - ieee->sec.encrypt; - - host_encrypt = ieee->host_encrypt && encrypt && crypt; - host_encrypt_msdu = ieee->host_encrypt_msdu && encrypt && crypt; - host_build_iv = ieee->host_build_iv && encrypt && crypt; - - if (!encrypt && ieee->ieee802_1x && - ieee->drop_unencrypted && ether_type != htons(ETH_P_PAE)) { - dev->stats.tx_dropped++; - goto success; - } - - /* Save source and destination addresses */ - skb_copy_from_linear_data(skb, dest, ETH_ALEN); - skb_copy_from_linear_data_offset(skb, ETH_ALEN, src, ETH_ALEN); - - if (host_encrypt || host_build_iv) - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA | - IEEE80211_FCTL_PROTECTED; - else - fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA; - - if (ieee->iw_mode == IW_MODE_INFRA) { - fc |= IEEE80211_FCTL_TODS; - /* To DS: Addr1 = BSSID, Addr2 = SA, Addr3 = DA */ - memcpy(header.addr1, ieee->bssid, ETH_ALEN); - memcpy(header.addr2, src, ETH_ALEN); - memcpy(header.addr3, dest, ETH_ALEN); - } else if (ieee->iw_mode == IW_MODE_ADHOC) { - /* not From/To DS: Addr1 = DA, Addr2 = SA, Addr3 = BSSID */ - memcpy(header.addr1, dest, ETH_ALEN); - memcpy(header.addr2, src, ETH_ALEN); - memcpy(header.addr3, ieee->bssid, ETH_ALEN); - } - hdr_len = LIBIPW_3ADDR_LEN; - - if (ieee->is_qos_active && ieee->is_qos_active(dev, skb)) { - fc |= IEEE80211_STYPE_QOS_DATA; - hdr_len += 2; - - skb->priority = libipw_classify(skb); - header.qos_ctl |= cpu_to_le16(skb->priority & LIBIPW_QCTL_TID); - } - header.frame_ctl = cpu_to_le16(fc); - - /* Advance the SKB to the start of the payload */ - skb_pull(skb, sizeof(struct ethhdr)); - - /* Determine total amount of storage required for TXB packets */ - bytes = skb->len + SNAP_SIZE + sizeof(u16); - - /* Encrypt msdu first on the whole data packet. */ - if ((host_encrypt || host_encrypt_msdu) && - crypt && crypt->ops && crypt->ops->encrypt_msdu) { - int res = 0; - int len = bytes + hdr_len + crypt->ops->extra_msdu_prefix_len + - crypt->ops->extra_msdu_postfix_len; - struct sk_buff *skb_new = dev_alloc_skb(len); - - if (unlikely(!skb_new)) - goto failed; - - skb_reserve(skb_new, crypt->ops->extra_msdu_prefix_len); - memcpy(skb_put(skb_new, hdr_len), &header, hdr_len); - snapped = 1; - libipw_copy_snap(skb_put(skb_new, SNAP_SIZE + sizeof(u16)), - ether_type); - skb_copy_from_linear_data(skb, skb_put(skb_new, skb->len), skb->len); - res = crypt->ops->encrypt_msdu(skb_new, hdr_len, crypt->priv); - if (res < 0) { - LIBIPW_ERROR("msdu encryption failed\n"); - dev_kfree_skb_any(skb_new); - goto failed; - } - dev_kfree_skb_any(skb); - skb = skb_new; - bytes += crypt->ops->extra_msdu_prefix_len + - crypt->ops->extra_msdu_postfix_len; - skb_pull(skb, hdr_len); - } - - if (host_encrypt || ieee->host_open_frag) { - /* Determine fragmentation size based on destination (multicast - * and broadcast are not fragmented) */ - if (is_multicast_ether_addr(dest) || - is_broadcast_ether_addr(dest)) - frag_size = MAX_FRAG_THRESHOLD; - else - frag_size = ieee->fts; - - /* Determine amount of payload per fragment. Regardless of if - * this stack is providing the full 802.11 header, one will - * eventually be affixed to this fragment -- so we must account - * for it when determining the amount of payload space. */ - bytes_per_frag = frag_size - hdr_len; - if (ieee->config & - (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS)) - bytes_per_frag -= LIBIPW_FCS_LEN; - - /* Each fragment may need to have room for encryptiong - * pre/postfix */ - if (host_encrypt) - bytes_per_frag -= crypt->ops->extra_mpdu_prefix_len + - crypt->ops->extra_mpdu_postfix_len; - - /* Number of fragments is the total - * bytes_per_frag / payload_per_fragment */ - nr_frags = bytes / bytes_per_frag; - bytes_last_frag = bytes % bytes_per_frag; - if (bytes_last_frag) - nr_frags++; - else - bytes_last_frag = bytes_per_frag; - } else { - nr_frags = 1; - bytes_per_frag = bytes_last_frag = bytes; - frag_size = bytes + hdr_len; - } - - rts_required = (frag_size > ieee->rts - && ieee->config & CFG_LIBIPW_RTS); - if (rts_required) - nr_frags++; - - /* When we allocate the TXB we allocate enough space for the reserve - * and full fragment bytes (bytes_per_frag doesn't include prefix, - * postfix, header, FCS, etc.) */ - txb = libipw_alloc_txb(nr_frags, frag_size, - ieee->tx_headroom, GFP_ATOMIC); - if (unlikely(!txb)) { - printk(KERN_WARNING "%s: Could not allocate TXB\n", - ieee->dev->name); - goto failed; - } - txb->encrypted = encrypt; - if (host_encrypt) - txb->payload_size = frag_size * (nr_frags - 1) + - bytes_last_frag; - else - txb->payload_size = bytes; - - if (rts_required) { - skb_frag = txb->fragments[0]; - frag_hdr = - (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len); - - /* - * Set header frame_ctl to the RTS. - */ - header.frame_ctl = - cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS); - memcpy(frag_hdr, &header, hdr_len); - - /* - * Restore header frame_ctl to the original data setting. - */ - header.frame_ctl = cpu_to_le16(fc); - - if (ieee->config & - (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS)) - skb_put(skb_frag, 4); - - txb->rts_included = 1; - i = 1; - } else - i = 0; - - for (; i < nr_frags; i++) { - skb_frag = txb->fragments[i]; - - if (host_encrypt || host_build_iv) - skb_reserve(skb_frag, - crypt->ops->extra_mpdu_prefix_len); - - frag_hdr = - (struct libipw_hdr_3addrqos *)skb_put(skb_frag, hdr_len); - memcpy(frag_hdr, &header, hdr_len); - - /* If this is not the last fragment, then add the MOREFRAGS - * bit to the frame control */ - if (i != nr_frags - 1) { - frag_hdr->frame_ctl = - cpu_to_le16(fc | IEEE80211_FCTL_MOREFRAGS); - bytes = bytes_per_frag; - } else { - /* The last fragment takes the remaining length */ - bytes = bytes_last_frag; - } - - if (i == 0 && !snapped) { - libipw_copy_snap(skb_put - (skb_frag, SNAP_SIZE + sizeof(u16)), - ether_type); - bytes -= SNAP_SIZE + sizeof(u16); - } - - skb_copy_from_linear_data(skb, skb_put(skb_frag, bytes), bytes); - - /* Advance the SKB... */ - skb_pull(skb, bytes); - - /* Encryption routine will move the header forward in order - * to insert the IV between the header and the payload */ - if (host_encrypt) - libipw_encrypt_fragment(ieee, skb_frag, hdr_len); - else if (host_build_iv) { - atomic_inc(&crypt->refcnt); - if (crypt->ops->build_iv) - crypt->ops->build_iv(skb_frag, hdr_len, - ieee->sec.keys[ieee->sec.active_key], - ieee->sec.key_sizes[ieee->sec.active_key], - crypt->priv); - atomic_dec(&crypt->refcnt); - } - - if (ieee->config & - (CFG_LIBIPW_COMPUTE_FCS | CFG_LIBIPW_RESERVE_FCS)) - skb_put(skb_frag, 4); - } - - success: - spin_unlock_irqrestore(&ieee->lock, flags); - - dev_kfree_skb_any(skb); - - if (txb) { - netdev_tx_t ret = (*ieee->hard_start_xmit)(txb, dev, priority); - if (ret == NETDEV_TX_OK) { - dev->stats.tx_packets++; - dev->stats.tx_bytes += txb->payload_size; - return NETDEV_TX_OK; - } - - libipw_txb_free(txb); - } - - return NETDEV_TX_OK; - - failed: - spin_unlock_irqrestore(&ieee->lock, flags); - netif_stop_queue(dev); - dev->stats.tx_errors++; - return NETDEV_TX_BUSY; -} -EXPORT_SYMBOL(libipw_xmit); - -EXPORT_SYMBOL(libipw_txb_free); diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c deleted file mode 100644 index 4d89f66f53b2..000000000000 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ /dev/null @@ -1,771 +0,0 @@ -/****************************************************************************** - - Copyright(c) 2004-2005 Intel Corporation. All rights reserved. - - Portions of this file are based on the WEP enablement code provided by the - Host AP project hostap-drivers v0.1.3 - Copyright (c) 2001-2002, SSH Communications Security Corp and Jouni Malinen - - Copyright (c) 2002-2003, Jouni Malinen - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - - The full GNU General Public License is included in this distribution in the - file called LICENSE. - - Contact Information: - Intel Linux Wireless - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -******************************************************************************/ - -#include -#include -#include - -#include -#include - -#include "libipw.h" - -static const char *libipw_modes[] = { - "?", "a", "b", "ab", "g", "ag", "bg", "abg" -}; - -static inline unsigned int elapsed_jiffies_msecs(unsigned long start) -{ - unsigned long end = jiffies; - - if (end >= start) - return jiffies_to_msecs(end - start); - - return jiffies_to_msecs(end + (MAX_JIFFY_OFFSET - start) + 1); -} - -#define MAX_CUSTOM_LEN 64 -static char *libipw_translate_scan(struct libipw_device *ieee, - char *start, char *stop, - struct libipw_network *network, - struct iw_request_info *info) -{ - char custom[MAX_CUSTOM_LEN]; - char *p; - struct iw_event iwe; - int i, j; - char *current_val; /* For rates */ - u8 rate; - - /* First entry *MUST* be the AP MAC address */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, network->bssid, ETH_ALEN); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - - /* Remaining entries will be displayed in the order we provide them */ - - /* Add the ESSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = min(network->ssid_len, (u8) 32); - start = iwe_stream_add_point(info, start, stop, - &iwe, network->ssid); - - /* Add the protocol name */ - iwe.cmd = SIOCGIWNAME; - snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11%s", - libipw_modes[network->mode]); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN); - - /* Add mode */ - iwe.cmd = SIOCGIWMODE; - if (network->capability & (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) { - if (network->capability & WLAN_CAPABILITY_ESS) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - - start = iwe_stream_add_event(info, start, stop, - &iwe, IW_EV_UINT_LEN); - } - - /* Add channel and frequency */ - /* Note : userspace automatically computes channel using iwrange */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = libipw_channel_to_freq(ieee, network->channel); - iwe.u.freq.e = 6; - iwe.u.freq.i = 0; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (network->capability & WLAN_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, - &iwe, network->ssid); - - /* Add basic and extended rates */ - /* Rate : stuffing multiple values in a single event require a bit - * more of magic - Jean II */ - current_val = start + iwe_stream_lcp_len(info); - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - - for (i = 0, j = 0; i < network->rates_len;) { - if (j < network->rates_ex_len && - ((network->rates_ex[j] & 0x7F) < - (network->rates[i] & 0x7F))) - rate = network->rates_ex[j++] & 0x7F; - else - rate = network->rates[i++] & 0x7F; - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((rate & 0x7f) * 500000); - /* Add new value to event */ - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); - } - for (; j < network->rates_ex_len; j++) { - rate = network->rates_ex[j] & 0x7F; - /* Bit rate given in 500 kb/s units (+ 0x80) */ - iwe.u.bitrate.value = ((rate & 0x7f) * 500000); - /* Add new value to event */ - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); - } - /* Check if we added any rate */ - if ((current_val - start) > iwe_stream_lcp_len(info)) - start = current_val; - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.updated = IW_QUAL_QUAL_UPDATED | IW_QUAL_LEVEL_UPDATED | - IW_QUAL_NOISE_UPDATED; - - if (!(network->stats.mask & LIBIPW_STATMASK_RSSI)) { - iwe.u.qual.updated |= IW_QUAL_QUAL_INVALID | - IW_QUAL_LEVEL_INVALID; - iwe.u.qual.qual = 0; - } else { - if (ieee->perfect_rssi == ieee->worst_rssi) - iwe.u.qual.qual = 100; - else - iwe.u.qual.qual = - (100 * - (ieee->perfect_rssi - ieee->worst_rssi) * - (ieee->perfect_rssi - ieee->worst_rssi) - - (ieee->perfect_rssi - network->stats.rssi) * - (15 * (ieee->perfect_rssi - ieee->worst_rssi) + - 62 * (ieee->perfect_rssi - - network->stats.rssi))) / - ((ieee->perfect_rssi - - ieee->worst_rssi) * (ieee->perfect_rssi - - ieee->worst_rssi)); - if (iwe.u.qual.qual > 100) - iwe.u.qual.qual = 100; - else if (iwe.u.qual.qual < 1) - iwe.u.qual.qual = 0; - } - - if (!(network->stats.mask & LIBIPW_STATMASK_NOISE)) { - iwe.u.qual.updated |= IW_QUAL_NOISE_INVALID; - iwe.u.qual.noise = 0; - } else { - iwe.u.qual.noise = network->stats.noise; - } - - if (!(network->stats.mask & LIBIPW_STATMASK_SIGNAL)) { - iwe.u.qual.updated |= IW_QUAL_LEVEL_INVALID; - iwe.u.qual.level = 0; - } else { - iwe.u.qual.level = network->stats.signal; - } - - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); - - iwe.cmd = IWEVCUSTOM; - p = custom; - - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - memset(&iwe, 0, sizeof(iwe)); - if (network->wpa_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, network->wpa_ie, network->wpa_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - memset(&iwe, 0, sizeof(iwe)); - if (network->rsn_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, network->rsn_ie, network->rsn_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = network->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - /* Add EXTRA: Age to display seconds since last beacon/probe response - * for given network. */ - iwe.cmd = IWEVCUSTOM; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), - " Last beacon: %ums ago", - elapsed_jiffies_msecs(network->last_scanned)); - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - - /* Add spectrum management information */ - iwe.cmd = -1; - p = custom; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), " Channel flags: "); - - if (libipw_get_channel_flags(ieee, network->channel) & - LIBIPW_CH_INVALID) { - iwe.cmd = IWEVCUSTOM; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "INVALID "); - } - - if (libipw_get_channel_flags(ieee, network->channel) & - LIBIPW_CH_RADAR_DETECT) { - iwe.cmd = IWEVCUSTOM; - p += snprintf(p, MAX_CUSTOM_LEN - (p - custom), "DFS "); - } - - if (iwe.cmd == IWEVCUSTOM) { - iwe.u.data.length = p - custom; - start = iwe_stream_add_point(info, start, stop, &iwe, custom); - } - - return start; -} - -#define SCAN_ITEM_SIZE 128 - -int libipw_wx_get_scan(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct libipw_network *network; - unsigned long flags; - int err = 0; - - char *ev = extra; - char *stop = ev + wrqu->data.length; - int i = 0; - DECLARE_SSID_BUF(ssid); - - LIBIPW_DEBUG_WX("Getting scan\n"); - - spin_lock_irqsave(&ieee->lock, flags); - - list_for_each_entry(network, &ieee->network_list, list) { - i++; - if (stop - ev < SCAN_ITEM_SIZE) { - err = -E2BIG; - break; - } - - if (ieee->scan_age == 0 || - time_after(network->last_scanned + ieee->scan_age, jiffies)) - ev = libipw_translate_scan(ieee, ev, stop, network, - info); - else { - LIBIPW_DEBUG_SCAN("Not showing network '%s (" - "%pM)' due to age (%ums).\n", - print_ssid(ssid, network->ssid, - network->ssid_len), - network->bssid, - elapsed_jiffies_msecs( - network->last_scanned)); - } - } - - spin_unlock_irqrestore(&ieee->lock, flags); - - wrqu->data.length = ev - extra; - wrqu->data.flags = 0; - - LIBIPW_DEBUG_WX("exit: %d networks returned.\n", i); - - return err; -} - -int libipw_wx_set_encode(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &(wrqu->encoding); - struct net_device *dev = ieee->dev; - struct libipw_security sec = { - .flags = 0 - }; - int i, key, key_provided, len; - struct lib80211_crypt_data **crypt; - int host_crypto = ieee->host_encrypt || ieee->host_decrypt || ieee->host_build_iv; - DECLARE_SSID_BUF(ssid); - - LIBIPW_DEBUG_WX("SET_ENCODE\n"); - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - key_provided = 1; - } else { - key_provided = 0; - key = ieee->crypt_info.tx_keyidx; - } - - LIBIPW_DEBUG_WX("Key: %d [%s]\n", key, key_provided ? - "provided" : "default"); - - crypt = &ieee->crypt_info.crypt[key]; - - if (erq->flags & IW_ENCODE_DISABLED) { - if (key_provided && *crypt) { - LIBIPW_DEBUG_WX("Disabling encryption on key %d.\n", - key); - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - } else - LIBIPW_DEBUG_WX("Disabling encryption.\n"); - - /* Check all the keys to see if any are still configured, - * and if no key index was provided, de-init them all */ - for (i = 0; i < WEP_KEYS; i++) { - if (ieee->crypt_info.crypt[i] != NULL) { - if (key_provided) - break; - lib80211_crypt_delayed_deinit(&ieee->crypt_info, - &ieee->crypt_info.crypt[i]); - } - } - - if (i == WEP_KEYS) { - sec.enabled = 0; - sec.encrypt = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_ENABLED | SEC_LEVEL | SEC_ENCRYPT; - } - - goto done; - } - - sec.enabled = 1; - sec.encrypt = 1; - sec.flags |= SEC_ENABLED | SEC_ENCRYPT; - - if (*crypt != NULL && (*crypt)->ops != NULL && - strcmp((*crypt)->ops->name, "WEP") != 0) { - /* changing to use WEP; deinit previously used algorithm - * on this key */ - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - } - - if (*crypt == NULL && host_crypto) { - struct lib80211_crypt_data *new_crypt; - - /* take WEP into use */ - new_crypt = kzalloc(sizeof(struct lib80211_crypt_data), - GFP_KERNEL); - if (new_crypt == NULL) - return -ENOMEM; - new_crypt->ops = lib80211_get_crypto_ops("WEP"); - if (!new_crypt->ops) { - request_module("lib80211_crypt_wep"); - new_crypt->ops = lib80211_get_crypto_ops("WEP"); - } - - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = new_crypt->ops->init(key); - - if (!new_crypt->ops || !new_crypt->priv) { - kfree(new_crypt); - new_crypt = NULL; - - printk(KERN_WARNING "%s: could not initialize WEP: " - "load module lib80211_crypt_wep\n", dev->name); - return -EOPNOTSUPP; - } - *crypt = new_crypt; - } - - /* If a new key was provided, set it up */ - if (erq->length > 0) { -#ifdef CONFIG_LIBIPW_DEBUG - DECLARE_SSID_BUF(ssid); -#endif - - len = erq->length <= 5 ? 5 : 13; - memcpy(sec.keys[key], keybuf, erq->length); - if (len > erq->length) - memset(sec.keys[key] + erq->length, 0, - len - erq->length); - LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", - key, print_ssid(ssid, sec.keys[key], len), - erq->length, len); - sec.key_sizes[key] = len; - if (*crypt) - (*crypt)->ops->set_key(sec.keys[key], len, NULL, - (*crypt)->priv); - sec.flags |= (1 << key); - /* This ensures a key will be activated if no key is - * explicitly set */ - if (key == sec.active_key) - sec.flags |= SEC_ACTIVE_KEY; - - } else { - if (host_crypto) { - len = (*crypt)->ops->get_key(sec.keys[key], WEP_KEY_LEN, - NULL, (*crypt)->priv); - if (len == 0) { - /* Set a default key of all 0 */ - LIBIPW_DEBUG_WX("Setting key %d to all " - "zero.\n", key); - memset(sec.keys[key], 0, 13); - (*crypt)->ops->set_key(sec.keys[key], 13, NULL, - (*crypt)->priv); - sec.key_sizes[key] = 13; - sec.flags |= (1 << key); - } - } - /* No key data - just set the default TX key index */ - if (key_provided) { - LIBIPW_DEBUG_WX("Setting key %d to default Tx " - "key.\n", key); - ieee->crypt_info.tx_keyidx = key; - sec.active_key = key; - sec.flags |= SEC_ACTIVE_KEY; - } - } - if (erq->flags & (IW_ENCODE_OPEN | IW_ENCODE_RESTRICTED)) { - ieee->open_wep = !(erq->flags & IW_ENCODE_RESTRICTED); - sec.auth_mode = ieee->open_wep ? WLAN_AUTH_OPEN : - WLAN_AUTH_SHARED_KEY; - sec.flags |= SEC_AUTH_MODE; - LIBIPW_DEBUG_WX("Auth: %s\n", - sec.auth_mode == WLAN_AUTH_OPEN ? - "OPEN" : "SHARED KEY"); - } - - /* For now we just support WEP, so only set that security level... - * TODO: When WPA is added this is one place that needs to change */ - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; /* 40 and 104 bit WEP */ - sec.encode_alg[key] = SEC_ALG_WEP; - - done: - if (ieee->set_security) - ieee->set_security(dev, &sec); - - /* Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - printk(KERN_DEBUG "%s: reset_port failed\n", dev->name); - return -EINVAL; - } - return 0; -} - -int libipw_wx_get_encode(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *keybuf) -{ - struct iw_point *erq = &(wrqu->encoding); - int len, key; - struct lib80211_crypt_data *crypt; - struct libipw_security *sec = &ieee->sec; - - LIBIPW_DEBUG_WX("GET_ENCODE\n"); - - key = erq->flags & IW_ENCODE_INDEX; - if (key) { - if (key > WEP_KEYS) - return -EINVAL; - key--; - } else - key = ieee->crypt_info.tx_keyidx; - - crypt = ieee->crypt_info.crypt[key]; - erq->flags = key + 1; - - if (!sec->enabled) { - erq->length = 0; - erq->flags |= IW_ENCODE_DISABLED; - return 0; - } - - len = sec->key_sizes[key]; - memcpy(keybuf, sec->keys[key], len); - - erq->length = len; - erq->flags |= IW_ENCODE_ENABLED; - - if (ieee->open_wep) - erq->flags |= IW_ENCODE_OPEN; - else - erq->flags |= IW_ENCODE_RESTRICTED; - - return 0; -} - -int libipw_wx_set_encodeext(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct net_device *dev = ieee->dev; - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int i, idx, ret = 0; - int group_key = 0; - const char *alg, *module; - struct lib80211_crypto_ops *ops; - struct lib80211_crypt_data **crypt; - - struct libipw_security sec = { - .flags = 0, - }; - - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > WEP_KEYS) - return -EINVAL; - idx--; - } else - idx = ieee->crypt_info.tx_keyidx; - - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - crypt = &ieee->crypt_info.crypt[idx]; - group_key = 1; - } else { - /* some Cisco APs use idx>0 for unicast in dynamic WEP */ - if (idx != 0 && ext->alg != IW_ENCODE_ALG_WEP) - return -EINVAL; - if (ieee->iw_mode == IW_MODE_INFRA) - crypt = &ieee->crypt_info.crypt[idx]; - else - return -EINVAL; - } - - sec.flags |= SEC_ENABLED | SEC_ENCRYPT; - if ((encoding->flags & IW_ENCODE_DISABLED) || - ext->alg == IW_ENCODE_ALG_NONE) { - if (*crypt) - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - - for (i = 0; i < WEP_KEYS; i++) - if (ieee->crypt_info.crypt[i] != NULL) - break; - - if (i == WEP_KEYS) { - sec.enabled = 0; - sec.encrypt = 0; - sec.level = SEC_LEVEL_0; - sec.flags |= SEC_LEVEL; - } - goto done; - } - - sec.enabled = 1; - sec.encrypt = 1; - - if (group_key ? !ieee->host_mc_decrypt : - !(ieee->host_encrypt || ieee->host_decrypt || - ieee->host_encrypt_msdu)) - goto skip_host_crypt; - - switch (ext->alg) { - case IW_ENCODE_ALG_WEP: - alg = "WEP"; - module = "lib80211_crypt_wep"; - break; - case IW_ENCODE_ALG_TKIP: - alg = "TKIP"; - module = "lib80211_crypt_tkip"; - break; - case IW_ENCODE_ALG_CCMP: - alg = "CCMP"; - module = "lib80211_crypt_ccmp"; - break; - default: - LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n", - dev->name, ext->alg); - ret = -EINVAL; - goto done; - } - - ops = lib80211_get_crypto_ops(alg); - if (ops == NULL) { - request_module(module); - ops = lib80211_get_crypto_ops(alg); - } - if (ops == NULL) { - LIBIPW_DEBUG_WX("%s: unknown crypto alg %d\n", - dev->name, ext->alg); - ret = -EINVAL; - goto done; - } - - if (*crypt == NULL || (*crypt)->ops != ops) { - struct lib80211_crypt_data *new_crypt; - - lib80211_crypt_delayed_deinit(&ieee->crypt_info, crypt); - - new_crypt = kzalloc(sizeof(*new_crypt), GFP_KERNEL); - if (new_crypt == NULL) { - ret = -ENOMEM; - goto done; - } - new_crypt->ops = ops; - if (new_crypt->ops && try_module_get(new_crypt->ops->owner)) - new_crypt->priv = new_crypt->ops->init(idx); - if (new_crypt->priv == NULL) { - kfree(new_crypt); - ret = -EINVAL; - goto done; - } - *crypt = new_crypt; - } - - if (ext->key_len > 0 && (*crypt)->ops->set_key && - (*crypt)->ops->set_key(ext->key, ext->key_len, ext->rx_seq, - (*crypt)->priv) < 0) { - LIBIPW_DEBUG_WX("%s: key setting failed\n", dev->name); - ret = -EINVAL; - goto done; - } - - skip_host_crypt: - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - ieee->crypt_info.tx_keyidx = idx; - sec.active_key = idx; - sec.flags |= SEC_ACTIVE_KEY; - } - - if (ext->alg != IW_ENCODE_ALG_NONE) { - memcpy(sec.keys[idx], ext->key, ext->key_len); - sec.key_sizes[idx] = ext->key_len; - sec.flags |= (1 << idx); - if (ext->alg == IW_ENCODE_ALG_WEP) { - sec.encode_alg[idx] = SEC_ALG_WEP; - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_1; - } else if (ext->alg == IW_ENCODE_ALG_TKIP) { - sec.encode_alg[idx] = SEC_ALG_TKIP; - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_2; - } else if (ext->alg == IW_ENCODE_ALG_CCMP) { - sec.encode_alg[idx] = SEC_ALG_CCMP; - sec.flags |= SEC_LEVEL; - sec.level = SEC_LEVEL_3; - } - /* Don't set sec level for group keys. */ - if (group_key) - sec.flags &= ~SEC_LEVEL; - } - done: - if (ieee->set_security) - ieee->set_security(ieee->dev, &sec); - - /* - * Do not reset port if card is in Managed mode since resetting will - * generate new IEEE 802.11 authentication which may end up in looping - * with IEEE 802.1X. If your hardware requires a reset after WEP - * configuration (for example... Prism2), implement the reset_port in - * the callbacks structures used to initialize the 802.11 stack. - */ - if (ieee->reset_on_keychange && - ieee->iw_mode != IW_MODE_INFRA && - ieee->reset_port && ieee->reset_port(dev)) { - LIBIPW_DEBUG_WX("%s: reset_port failed\n", dev->name); - return -EINVAL; - } - - return ret; -} - -int libipw_wx_get_encodeext(struct libipw_device *ieee, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - struct libipw_security *sec = &ieee->sec; - int idx, max_key_len; - - max_key_len = encoding->length - sizeof(*ext); - if (max_key_len < 0) - return -EINVAL; - - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if (idx < 1 || idx > WEP_KEYS) - return -EINVAL; - idx--; - } else - idx = ieee->crypt_info.tx_keyidx; - - if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && - ext->alg != IW_ENCODE_ALG_WEP) - if (idx != 0 || ieee->iw_mode != IW_MODE_INFRA) - return -EINVAL; - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - if (!sec->enabled) { - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - encoding->flags |= IW_ENCODE_DISABLED; - } else { - if (sec->encode_alg[idx] == SEC_ALG_WEP) - ext->alg = IW_ENCODE_ALG_WEP; - else if (sec->encode_alg[idx] == SEC_ALG_TKIP) - ext->alg = IW_ENCODE_ALG_TKIP; - else if (sec->encode_alg[idx] == SEC_ALG_CCMP) - ext->alg = IW_ENCODE_ALG_CCMP; - else - return -EINVAL; - - ext->key_len = sec->key_sizes[idx]; - memcpy(ext->key, sec->keys[idx], ext->key_len); - encoding->flags |= IW_ENCODE_ENABLED; - if (ext->key_len && - (ext->alg == IW_ENCODE_ALG_TKIP || - ext->alg == IW_ENCODE_ALG_CCMP)) - ext->ext_flags |= IW_ENCODE_EXT_TX_SEQ_VALID; - - } - - return 0; -} - -EXPORT_SYMBOL(libipw_wx_set_encodeext); -EXPORT_SYMBOL(libipw_wx_get_encodeext); - -EXPORT_SYMBOL(libipw_wx_get_scan); -EXPORT_SYMBOL(libipw_wx_set_encode); -EXPORT_SYMBOL(libipw_wx_get_encode); diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig deleted file mode 100644 index 99310c033253..000000000000 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ /dev/null @@ -1,120 +0,0 @@ -config IWLWIFI - tristate "Intel Wireless Wifi" - depends on PCI && MAC80211 && WLAN_80211 && EXPERIMENTAL - select LIB80211 - select FW_LOADER - select MAC80211_LEDS if IWLWIFI_LEDS - select LEDS_CLASS if IWLWIFI_LEDS - -config IWLWIFI_LEDS - bool "Enable LED support in iwlagn and iwl3945 drivers" - depends on IWLWIFI - default y - ---help--- - Select this if you want LED support. - -config IWLWIFI_SPECTRUM_MEASUREMENT - bool "Enable Spectrum Measurement in iwlagn driver" - depends on IWLWIFI - ---help--- - This option will enable spectrum measurement for the iwlagn driver. - -config IWLWIFI_DEBUG - bool "Enable full debugging output in iwlagn and iwl3945 drivers" - depends on IWLWIFI - ---help--- - This option will enable debug tracing output for the iwlwifi drivers - - This will result in the kernel module being ~100k larger. You can - control which debug output is sent to the kernel log by setting the - value in - - /sys/class/net/wlan0/device/debug_level - - This entry will only exist if this option is enabled. - - To set a value, simply echo an 8-byte hex value to the same file: - - % echo 0x43fff > /sys/class/net/wlan0/device/debug_level - - You can find the list of debug mask values in: - drivers/net/wireless/iwlwifi/iwl-debug.h - - If this is your first time using this driver, you should say Y here - as the debug information can assist others in helping you resolve - any problems you may encounter. - -config IWLWIFI_DEBUGFS - bool "iwlagn debugfs support" - depends on IWLWIFI && IWLWIFI_DEBUG && MAC80211_DEBUGFS - ---help--- - Enable creation of debugfs files for the iwlwifi drivers. - -config IWLAGN - tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)" - depends on IWLWIFI - ---help--- - Select to build the driver supporting the: - - Intel Wireless WiFi Link Next-Gen AGN - - This driver uses the kernel's mac80211 subsystem. - - In order to use this driver, you will need a microcode (uCode) - image for it. You can obtain the microcode from: - - . - - The microcode is typically installed in /lib/firmware. You can - look in the hotplug script /etc/hotplug/firmware.agent to - determine which directory FIRMWARE_DIR is set to when the script - runs. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The - module will be called iwlagn. - - -config IWL4965 - bool "Intel Wireless WiFi 4965AGN" - depends on IWLAGN - ---help--- - This option enables support for Intel Wireless WiFi Link 4965AGN - -config IWL5000 - bool "Intel Wireless WiFi 5000AGN; Intel WiFi Link 1000, 6000, and 6050 Series" - depends on IWLAGN - ---help--- - This option enables support for Intel Wireless WiFi Link 5000AGN Family - -config IWL3945 - tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)" - depends on IWLWIFI - ---help--- - Select to build the driver supporting the: - - Intel PRO/Wireless 3945ABG/BG Network Connection - - This driver uses the kernel's mac80211 subsystem. - - In order to use this driver, you will need a microcode (uCode) - image for it. You can obtain the microcode from: - - . - - The microcode is typically installed in /lib/firmware. You can - look in the hotplug script /etc/hotplug/firmware.agent to - determine which directory FIRMWARE_DIR is set to when the script - runs. - - If you want to compile the driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The - module will be called iwl3945. - -config IWL3945_SPECTRUM_MEASUREMENT - bool "Enable Spectrum Measurement in iwl3945 driver" - depends on IWL3945 - ---help--- - This option will enable spectrum measurement for the iwl3945 driver. diff --git a/drivers/net/wireless/iwlwifi/Makefile b/drivers/net/wireless/iwlwifi/Makefile deleted file mode 100644 index 1d4e0a226fd4..000000000000 --- a/drivers/net/wireless/iwlwifi/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -obj-$(CONFIG_IWLWIFI) += iwlcore.o -iwlcore-objs := iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o -iwlcore-objs += iwl-rx.o iwl-tx.o iwl-sta.o iwl-calib.o -iwlcore-objs += iwl-scan.o -iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o -iwlcore-$(CONFIG_IWLWIFI_LEDS) += iwl-led.o -iwlcore-$(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) += iwl-spectrum.o - -obj-$(CONFIG_IWLAGN) += iwlagn.o -iwlagn-objs := iwl-agn.o iwl-agn-rs.o - -iwlagn-$(CONFIG_IWL4965) += iwl-4965.o -iwlagn-$(CONFIG_IWL5000) += iwl-5000.o -iwlagn-$(CONFIG_IWL5000) += iwl-6000.o -iwlagn-$(CONFIG_IWL5000) += iwl-1000.o - -obj-$(CONFIG_IWL3945) += iwl3945.o -iwl3945-objs := iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o - - diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c deleted file mode 100644 index 950267ab556a..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-1000.c +++ /dev/null @@ -1,166 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-sta.h" -#include "iwl-helpers.h" -#include "iwl-5000-hw.h" - -/* Highest firmware API version supported */ -#define IWL1000_UCODE_API_MAX 3 - -/* Lowest firmware API version supported */ -#define IWL1000_UCODE_API_MIN 1 - -#define IWL1000_FW_PRE "iwlwifi-1000-" -#define _IWL1000_MODULE_FIRMWARE(api) IWL1000_FW_PRE #api ".ucode" -#define IWL1000_MODULE_FIRMWARE(api) _IWL1000_MODULE_FIRMWARE(api) - - -/* - * For 1000, use advance thermal throttling critical temperature threshold, - * but legacy thermal management implementation for now. - * This is for the reason of 1000 uCode using advance thermal throttling API - * but not implement ct_kill_exit based on ct_kill exit temperature - * so the thermal throttling will still based on legacy thermal throttling - * management. - * The code here need to be modified once 1000 uCode has the advanced thermal - * throttling algorithm in place - */ -static void iwl1000_set_ct_threshold(struct iwl_priv *priv) -{ - /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; - priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; -} - -/* NIC configuration for 1000 series */ -static void iwl1000_nic_config(struct iwl_priv *priv) -{ - iwl5000_nic_config(priv); - - /* Setting digital SVR for 1000 card to 1.32V */ - /* locking is acquired in iwl_set_bits_mask_prph() function */ - iwl_set_bits_mask_prph(priv, APMG_DIGITAL_SVR_REG, - APMG_SVR_DIGITAL_VOLTAGE_1_32, - ~APMG_SVR_VOLTAGE_CONFIG_BIT_MSK); -} - -static struct iwl_lib_ops iwl1000_lib = { - .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .load_ucode = iwl5000_load_ucode, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, - .send_tx_power = iwl5000_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .apm_ops = { - .init = iwl5000_apm_init, - .reset = iwl5000_apm_reset, - .stop = iwl5000_apm_stop, - .config = iwl1000_nic_config, - .set_pwr_src = iwl_set_pwr_src, - }, - .eeprom_ops = { - .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS - }, - .verify_signature = iwlcore_eeprom_verify_signature, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, - }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, - .temp_ops = { - .temperature = iwl5000_temperature, - .set_ct_kill = iwl1000_set_ct_threshold, - }, -}; - -static struct iwl_ops iwl1000_ops = { - .ucode = &iwl5000_ucode, - .lib = &iwl1000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, -}; - -struct iwl_cfg iwl1000_bgn_cfg = { - .name = "1000 Series BGN", - .fw_name_pre = IWL1000_FW_PRE, - .ucode_api_max = IWL1000_UCODE_API_MAX, - .ucode_api_min = IWL1000_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .ops = &iwl1000_ops, - .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = true, - .max_ll_items = OTP_MAX_LL_ITEMS_1000, - .shadow_ram_support = false, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h b/drivers/net/wireless/iwlwifi/iwl-3945-fh.h deleted file mode 100644 index 08ce259a0e60..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-fh.h +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_3945_fh_h__ -#define __iwl_3945_fh_h__ - -/************************************/ -/* iwl3945 Flow Handler Definitions */ -/************************************/ - -/** - * This I/O area is directly read/writable by driver (e.g. Linux uses writel()) - * Addresses are offsets from device's PCI hardware base address. - */ -#define FH39_MEM_LOWER_BOUND (0x0800) -#define FH39_MEM_UPPER_BOUND (0x1000) - -#define FH39_CBCC_TABLE (FH39_MEM_LOWER_BOUND + 0x140) -#define FH39_TFDB_TABLE (FH39_MEM_LOWER_BOUND + 0x180) -#define FH39_RCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x400) -#define FH39_RSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x4c0) -#define FH39_TCSR_TABLE (FH39_MEM_LOWER_BOUND + 0x500) -#define FH39_TSSR_TABLE (FH39_MEM_LOWER_BOUND + 0x680) - -/* TFDB (Transmit Frame Buffer Descriptor) */ -#define FH39_TFDB(_ch, buf) (FH39_TFDB_TABLE + \ - ((_ch) * 2 + (buf)) * 0x28) -#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch) (FH39_TFDB_TABLE + 0x50 * (_ch)) - -/* CBCC channel is [0,2] */ -#define FH39_CBCC(_ch) (FH39_CBCC_TABLE + (_ch) * 0x8) -#define FH39_CBCC_CTRL(_ch) (FH39_CBCC(_ch) + 0x00) -#define FH39_CBCC_BASE(_ch) (FH39_CBCC(_ch) + 0x04) - -/* RCSR channel is [0,2] */ -#define FH39_RCSR(_ch) (FH39_RCSR_TABLE + (_ch) * 0x40) -#define FH39_RCSR_CONFIG(_ch) (FH39_RCSR(_ch) + 0x00) -#define FH39_RCSR_RBD_BASE(_ch) (FH39_RCSR(_ch) + 0x04) -#define FH39_RCSR_WPTR(_ch) (FH39_RCSR(_ch) + 0x20) -#define FH39_RCSR_RPTR_ADDR(_ch) (FH39_RCSR(_ch) + 0x24) - -#define FH39_RSCSR_CHNL0_WPTR (FH39_RCSR_WPTR(0)) - -/* RSSR */ -#define FH39_RSSR_CTRL (FH39_RSSR_TABLE + 0x000) -#define FH39_RSSR_STATUS (FH39_RSSR_TABLE + 0x004) - -/* TCSR */ -#define FH39_TCSR(_ch) (FH39_TCSR_TABLE + (_ch) * 0x20) -#define FH39_TCSR_CONFIG(_ch) (FH39_TCSR(_ch) + 0x00) -#define FH39_TCSR_CREDIT(_ch) (FH39_TCSR(_ch) + 0x04) -#define FH39_TCSR_BUFF_STTS(_ch) (FH39_TCSR(_ch) + 0x08) - -/* TSSR */ -#define FH39_TSSR_CBB_BASE (FH39_TSSR_TABLE + 0x000) -#define FH39_TSSR_MSG_CONFIG (FH39_TSSR_TABLE + 0x008) -#define FH39_TSSR_TX_STATUS (FH39_TSSR_TABLE + 0x010) - - -/* DBM */ - -#define FH39_SRVC_CHNL (6) - -#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE (20) -#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH (4) - -#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN (0x08000000) - -#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE (0x80000000) - -#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE (0x20000000) - -#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 (0x01000000) - -#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST (0x00001000) - -#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH (0x00000000) - -#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) -#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER (0x00000001) - -#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL (0x00000000) -#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL (0x00000008) - -#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) - -#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) - -#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) -#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) - -#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00004000) - -#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR (0x00000001) - -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON (0xFF000000) -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON (0x00FF0000) - -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B (0x00000400) - -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON (0x00000100) -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON (0x00000080) - -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH (0x00000020) -#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH (0x00000005) - -#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) (BIT(_ch) << 24) -#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch) (BIT(_ch) << 16) - -#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \ - (FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \ - FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)) - -#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) - -struct iwl3945_tfd_tb { - __le32 addr; - __le32 len; -} __attribute__ ((packed)); - -struct iwl3945_tfd { - __le32 control_flags; - struct iwl3945_tfd_tb tbs[4]; - u8 __pad[28]; -} __attribute__ ((packed)); - - -#endif /* __iwl_3945_fh_h__ */ - diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h b/drivers/net/wireless/iwlwifi/iwl-3945-hw.h deleted file mode 100644 index 16772780c5b0..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-hw.h +++ /dev/null @@ -1,308 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -/* - * Please use this file (iwl-3945-hw.h) only for hardware-related definitions. - * Please use iwl-3945-commands.h for uCode API definitions. - * Please use iwl-3945.h for driver implementation definitions. - */ - -#ifndef __iwl_3945_hw__ -#define __iwl_3945_hw__ - -#include "iwl-eeprom.h" - -/* - * uCode queue management definitions ... - * Queue #4 is the command queue for 3945 and 4965. - */ -#define IWL_CMD_QUEUE_NUM 4 - -/* Time constants */ -#define SHORT_SLOT_TIME 9 -#define LONG_SLOT_TIME 20 - -/* RSSI to dBm */ -#define IWL39_RSSI_OFFSET 95 - -/* - * EEPROM related constants, enums, and structures. - */ -#define EEPROM_SKU_CAP_OP_MODE_MRC (1 << 7) - -/* - * Mapping of a Tx power level, at factory calibration temperature, - * to a radio/DSP gain table index. - * One for each of 5 "sample" power levels in each band. - * v_det is measured at the factory, using the 3945's built-in power amplifier - * (PA) output voltage detector. This same detector is used during Tx of - * long packets in normal operation to provide feedback as to proper output - * level. - * Data copied from EEPROM. - * DO NOT ALTER THIS STRUCTURE!!! - */ -struct iwl3945_eeprom_txpower_sample { - u8 gain_index; /* index into power (gain) setup table ... */ - s8 power; /* ... for this pwr level for this chnl group */ - u16 v_det; /* PA output voltage */ -} __attribute__ ((packed)); - -/* - * Mappings of Tx power levels -> nominal radio/DSP gain table indexes. - * One for each channel group (a.k.a. "band") (1 for BG, 4 for A). - * Tx power setup code interpolates between the 5 "sample" power levels - * to determine the nominal setup for a requested power level. - * Data copied from EEPROM. - * DO NOT ALTER THIS STRUCTURE!!! - */ -struct iwl3945_eeprom_txpower_group { - struct iwl3945_eeprom_txpower_sample samples[5]; /* 5 power levels */ - s32 a, b, c, d, e; /* coefficients for voltage->power - * formula (signed) */ - s32 Fa, Fb, Fc, Fd, Fe; /* these modify coeffs based on - * frequency (signed) */ - s8 saturation_power; /* highest power possible by h/w in this - * band */ - u8 group_channel; /* "representative" channel # in this band */ - s16 temperature; /* h/w temperature at factory calib this band - * (signed) */ -} __attribute__ ((packed)); - -/* - * Temperature-based Tx-power compensation data, not band-specific. - * These coefficients are use to modify a/b/c/d/e coeffs based on - * difference between current temperature and factory calib temperature. - * Data copied from EEPROM. - */ -struct iwl3945_eeprom_temperature_corr { - u32 Ta; - u32 Tb; - u32 Tc; - u32 Td; - u32 Te; -} __attribute__ ((packed)); - -/* - * EEPROM map - */ -struct iwl3945_eeprom { - u8 reserved0[16]; - u16 device_id; /* abs.ofs: 16 */ - u8 reserved1[2]; - u16 pmc; /* abs.ofs: 20 */ - u8 reserved2[20]; - u8 mac_address[6]; /* abs.ofs: 42 */ - u8 reserved3[58]; - u16 board_revision; /* abs.ofs: 106 */ - u8 reserved4[11]; - u8 board_pba_number[9]; /* abs.ofs: 119 */ - u8 reserved5[8]; - u16 version; /* abs.ofs: 136 */ - u8 sku_cap; /* abs.ofs: 138 */ - u8 leds_mode; /* abs.ofs: 139 */ - u16 oem_mode; - u16 wowlan_mode; /* abs.ofs: 142 */ - u16 leds_time_interval; /* abs.ofs: 144 */ - u8 leds_off_time; /* abs.ofs: 146 */ - u8 leds_on_time; /* abs.ofs: 147 */ - u8 almgor_m_version; /* abs.ofs: 148 */ - u8 antenna_switch_type; /* abs.ofs: 149 */ - u8 reserved6[42]; - u8 sku_id[4]; /* abs.ofs: 192 */ - -/* - * Per-channel regulatory data. - * - * Each channel that *might* be supported by 3945 or 4965 has a fixed location - * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory - * txpower (MSB). - * - * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz) - * channels (only for 4965, not supported by 3945) appear later in the EEPROM. - * - * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - */ - u16 band_1_count; /* abs.ofs: 196 */ - struct iwl_eeprom_channel band_1_channels[14]; /* abs.ofs: 198 */ - -/* - * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, - * 5.0 GHz channels 7, 8, 11, 12, 16 - * (4915-5080MHz) (none of these is ever supported) - */ - u16 band_2_count; /* abs.ofs: 226 */ - struct iwl_eeprom_channel band_2_channels[13]; /* abs.ofs: 228 */ - -/* - * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 - * (5170-5320MHz) - */ - u16 band_3_count; /* abs.ofs: 254 */ - struct iwl_eeprom_channel band_3_channels[12]; /* abs.ofs: 256 */ - -/* - * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 - * (5500-5700MHz) - */ - u16 band_4_count; /* abs.ofs: 280 */ - struct iwl_eeprom_channel band_4_channels[11]; /* abs.ofs: 282 */ - -/* - * 5.7 GHz channels 145, 149, 153, 157, 161, 165 - * (5725-5825MHz) - */ - u16 band_5_count; /* abs.ofs: 304 */ - struct iwl_eeprom_channel band_5_channels[6]; /* abs.ofs: 306 */ - - u8 reserved9[194]; - -/* - * 3945 Txpower calibration data. - */ -#define IWL_NUM_TX_CALIB_GROUPS 5 - struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS]; -/* abs.ofs: 512 */ - struct iwl3945_eeprom_temperature_corr corrections; /* abs.ofs: 832 */ - u8 reserved16[172]; /* fill out to full 1024 byte block */ -} __attribute__ ((packed)); - -#define IWL3945_EEPROM_IMG_SIZE 1024 - -/* End of EEPROM */ - -#define PCI_CFG_REV_ID_BIT_BASIC_SKU (0x40) /* bit 6 */ -#define PCI_CFG_REV_ID_BIT_RTP (0x80) /* bit 7 */ - -/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */ -#define IWL39_NUM_QUEUES 5 -#define IWL_NUM_SCAN_RATES (2) - -#define IWL_DEFAULT_TX_RETRY 15 - -/*********************************************/ - -#define RFD_SIZE 4 -#define NUM_TFD_CHUNKS 4 - -#define RX_QUEUE_SIZE 256 -#define RX_QUEUE_MASK 255 -#define RX_QUEUE_SIZE_LOG 8 - -#define U32_PAD(n) ((4-(n))&0x3) - -#define TFD_CTL_COUNT_SET(n) (n << 24) -#define TFD_CTL_COUNT_GET(ctl) ((ctl >> 24) & 7) -#define TFD_CTL_PAD_SET(n) (n << 28) -#define TFD_CTL_PAD_GET(ctl) (ctl >> 28) - -/* - * RX related structures and functions - */ -#define RX_FREE_BUFFERS 64 -#define RX_LOW_WATERMARK 8 - -/* Sizes and addresses for instruction and data memory (SRAM) in - * 3945's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ -#define IWL39_RTC_INST_LOWER_BOUND (0x000000) -#define IWL39_RTC_INST_UPPER_BOUND (0x014000) - -#define IWL39_RTC_DATA_LOWER_BOUND (0x800000) -#define IWL39_RTC_DATA_UPPER_BOUND (0x808000) - -#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \ - IWL39_RTC_INST_LOWER_BOUND) -#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \ - IWL39_RTC_DATA_LOWER_BOUND) - -#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE -#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE - -/* Size of uCode instruction memory in bootstrap state machine */ -#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE - -static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr) -{ - return (addr >= IWL39_RTC_DATA_LOWER_BOUND) && - (addr < IWL39_RTC_DATA_UPPER_BOUND); -} - -/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE - * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */ -struct iwl3945_shared { - __le32 tx_base_ptr[8]; -} __attribute__ ((packed)); - -static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags) -{ - return le16_to_cpu(rate_n_flags) & 0xFF; -} - -static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags) -{ - return le16_to_cpu(rate_n_flags); -} - -static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags) -{ - return cpu_to_le16((u16)rate|flags); -} -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.c b/drivers/net/wireless/iwlwifi/iwl-3945-led.c deleted file mode 100644 index 8c29ded7d02c..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.c +++ /dev/null @@ -1,430 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifdef CONFIG_IWLWIFI_LEDS - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-commands.h" -#include "iwl-3945.h" -#include "iwl-core.h" -#include "iwl-dev.h" - -#ifdef CONFIG_IWLWIFI_DEBUG -static const char *led_type_str[] = { - __stringify(IWL_LED_TRG_TX), - __stringify(IWL_LED_TRG_RX), - __stringify(IWL_LED_TRG_ASSOC), - __stringify(IWL_LED_TRG_RADIO), - NULL -}; -#endif /* CONFIG_IWLWIFI_DEBUG */ - -static const struct { - u16 brightness; - u8 on_time; - u8 off_time; -} blink_tbl[] = -{ - {300, 25, 25}, - {200, 40, 40}, - {100, 55, 55}, - {70, 65, 65}, - {50, 75, 75}, - {20, 85, 85}, - {15, 95, 95 }, - {10, 110, 110}, - {5, 130, 130}, - {0, 167, 167}, - /* SOLID_ON */ - {-1, IWL_LED_SOLID, 0} -}; - -#define IWL_1MB_RATE (128 * 1024) -#define IWL_LED_THRESHOLD (16) -#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/ -#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) - -static void iwl3945_led_cmd_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb) -{ -} - -static inline int iwl3945_brightness_to_idx(enum led_brightness brightness) -{ - return fls(0x000000FF & (u32)brightness); -} - -/* Send led command */ -static int iwl_send_led_cmd(struct iwl_priv *priv, - struct iwl_led_cmd *led_cmd) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl_led_cmd), - .data = led_cmd, - .flags = CMD_ASYNC, - .callback = iwl3945_led_cmd_callback, - }; - - return iwl_send_cmd(priv, &cmd); -} - - - -/* Set led on command */ -static int iwl3945_led_pattern(struct iwl_priv *priv, int led_id, - unsigned int idx) -{ - struct iwl_led_cmd led_cmd = { - .id = led_id, - .interval = IWL_DEF_LED_INTRVL - }; - - BUG_ON(idx > IWL_MAX_BLINK_TBL); - - led_cmd.on = blink_tbl[idx].on_time; - led_cmd.off = blink_tbl[idx].off_time; - - return iwl_send_led_cmd(priv, &led_cmd); -} - - -/* Set led on command */ -static int iwl3945_led_on(struct iwl_priv *priv, int led_id) -{ - struct iwl_led_cmd led_cmd = { - .id = led_id, - .on = IWL_LED_SOLID, - .off = 0, - .interval = IWL_DEF_LED_INTRVL - }; - return iwl_send_led_cmd(priv, &led_cmd); -} - -/* Set led off command */ -static int iwl3945_led_off(struct iwl_priv *priv, int led_id) -{ - struct iwl_led_cmd led_cmd = { - .id = led_id, - .on = 0, - .off = 0, - .interval = IWL_DEF_LED_INTRVL - }; - IWL_DEBUG_LED(priv, "led off %d\n", led_id); - return iwl_send_led_cmd(priv, &led_cmd); -} - -/* - * Set led on in case of association - * */ -static int iwl3945_led_associate(struct iwl_priv *priv, int led_id) -{ - IWL_DEBUG_LED(priv, "Associated\n"); - - priv->allow_blinking = 1; - return iwl3945_led_on(priv, led_id); -} -/* Set Led off in case of disassociation */ -static int iwl3945_led_disassociate(struct iwl_priv *priv, int led_id) -{ - IWL_DEBUG_LED(priv, "Disassociated\n"); - - priv->allow_blinking = 0; - - return 0; -} - -/* - * brightness call back function for Tx/Rx LED - */ -static int iwl3945_led_associated(struct iwl_priv *priv, int led_id) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - !test_bit(STATUS_READY, &priv->status)) - return 0; - - - /* start counting Tx/Rx bytes */ - if (!priv->last_blink_time && priv->allow_blinking) - priv->last_blink_time = jiffies; - return 0; -} - -/* - * brightness call back for association and radio - */ -static void iwl3945_led_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct iwl_led *led = container_of(led_cdev, - struct iwl_led, led_dev); - struct iwl_priv *priv = led->priv; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", - led_type_str[led->type], brightness); - - switch (brightness) { - case LED_FULL: - if (led->led_on) - led->led_on(priv, IWL_LED_LINK); - break; - case LED_OFF: - if (led->led_off) - led->led_off(priv, IWL_LED_LINK); - break; - default: - if (led->led_pattern) { - int idx = iwl3945_brightness_to_idx(brightness); - led->led_pattern(priv, IWL_LED_LINK, idx); - } - break; - } -} - -/* - * Register led class with the system - */ -static int iwl3945_led_register_led(struct iwl_priv *priv, - struct iwl_led *led, - enum led_type type, u8 set_led, - char *trigger) -{ - struct device *device = wiphy_dev(priv->hw->wiphy); - int ret; - - led->led_dev.name = led->name; - led->led_dev.brightness_set = iwl3945_led_brightness_set; - led->led_dev.default_trigger = trigger; - - led->priv = priv; - led->type = type; - - ret = led_classdev_register(device, &led->led_dev); - if (ret) { - IWL_ERR(priv, "Error: failed to register led handler.\n"); - return ret; - } - - led->registered = 1; - - if (set_led && led->led_on) - led->led_on(priv, IWL_LED_LINK); - return 0; -} - - -/* - * calculate blink rate according to last 2 sec Tx/Rx activities - */ -static inline u8 get_blink_rate(struct iwl_priv *priv) -{ - int index; - s64 tpt = priv->rxtxpackets; - - if (tpt < 0) - tpt = -tpt; - - IWL_DEBUG_LED(priv, "tpt %lld \n", (long long)tpt); - - if (!priv->allow_blinking) - index = IWL_MAX_BLINK_TBL; - else - for (index = 0; index < IWL_MAX_BLINK_TBL; index++) - if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE)) - break; - - IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", index); - return index; -} - -/* - * this function called from handler. Since setting Led command can - * happen very frequent we postpone led command to be called from - * REPLY handler so we know ucode is up - */ -void iwl3945_led_background(struct iwl_priv *priv) -{ - u8 blink_idx; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - priv->last_blink_time = 0; - return; - } - if (iwl_is_rfkill(priv)) { - priv->last_blink_time = 0; - return; - } - - if (!priv->allow_blinking) { - priv->last_blink_time = 0; - if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { - priv->last_blink_rate = IWL_SOLID_BLINK_IDX; - iwl3945_led_pattern(priv, IWL_LED_LINK, - IWL_SOLID_BLINK_IDX); - } - return; - } - if (!priv->last_blink_time || - !time_after(jiffies, priv->last_blink_time + - msecs_to_jiffies(1000))) - return; - - blink_idx = get_blink_rate(priv); - - /* call only if blink rate change */ - if (blink_idx != priv->last_blink_rate) - iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx); - - priv->last_blink_time = jiffies; - priv->last_blink_rate = blink_idx; - priv->rxtxpackets = 0; -} - - -/* Register all led handler */ -int iwl3945_led_register(struct iwl_priv *priv) -{ - char *trigger; - int ret; - - priv->last_blink_rate = 0; - priv->rxtxpackets = 0; - priv->led_tpt = 0; - priv->last_blink_time = 0; - priv->allow_blinking = 0; - - trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_RADIO].name, - sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", - wiphy_name(priv->hw->wiphy)); - - priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on; - priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off; - priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; - - ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, trigger); - - if (ret) - goto exit_fail; - - trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_ASSOC].name, - sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", - wiphy_name(priv->hw->wiphy)); - - ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, trigger); - - /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_associate; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_disassociate; - priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; - - if (ret) - goto exit_fail; - - trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_RX].name, - sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", - wiphy_name(priv->hw->wiphy)); - - ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, trigger); - - priv->led[IWL_LED_TRG_RX].led_on = iwl3945_led_associated; - priv->led[IWL_LED_TRG_RX].led_off = iwl3945_led_associated; - priv->led[IWL_LED_TRG_RX].led_pattern = iwl3945_led_pattern; - - if (ret) - goto exit_fail; - - trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_TX].name, - sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", - wiphy_name(priv->hw->wiphy)); - - ret = iwl3945_led_register_led(priv, - &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, trigger); - - priv->led[IWL_LED_TRG_TX].led_on = iwl3945_led_associated; - priv->led[IWL_LED_TRG_TX].led_off = iwl3945_led_associated; - priv->led[IWL_LED_TRG_TX].led_pattern = iwl3945_led_pattern; - - if (ret) - goto exit_fail; - - return 0; - -exit_fail: - iwl3945_led_unregister(priv); - return ret; -} - - -/* unregister led class */ -static void iwl3945_led_unregister_led(struct iwl_led *led, u8 set_led) -{ - if (!led->registered) - return; - - led_classdev_unregister(&led->led_dev); - - if (set_led) - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - led->registered = 0; -} - -/* Unregister all led handlers */ -void iwl3945_led_unregister(struct iwl_priv *priv) -{ - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); - iwl3945_led_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); -} - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-led.h b/drivers/net/wireless/iwlwifi/iwl-3945-led.h deleted file mode 100644 index 3b65642258ca..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-led.h +++ /dev/null @@ -1,46 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef IWL3945_LEDS_H -#define IWL3945_LEDS_H - -struct iwl_priv; - -#ifdef CONFIG_IWLWIFI_LEDS - -#include "iwl-led.h" - -extern int iwl3945_led_register(struct iwl_priv *priv); -extern void iwl3945_led_unregister(struct iwl_priv *priv); -extern void iwl3945_led_background(struct iwl_priv *priv); - -#else -static inline int iwl3945_led_register(struct iwl_priv *priv) { return 0; } -static inline void iwl3945_led_unregister(struct iwl_priv *priv) {} -static inline void iwl3945_led_background(struct iwl_priv *priv) {} - -#endif /* IWLWIFI_LEDS*/ -#endif /* IWL3945_LEDS_H */ diff --git a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c b/drivers/net/wireless/iwlwifi/iwl-3945-rs.c deleted file mode 100644 index cbb0585083a9..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945-rs.c +++ /dev/null @@ -1,1019 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "iwl-commands.h" -#include "iwl-3945.h" -#include "iwl-sta.h" - -#define RS_NAME "iwl-3945-rs" - -struct iwl3945_rate_scale_data { - u64 data; - s32 success_counter; - s32 success_ratio; - s32 counter; - s32 average_tpt; - unsigned long stamp; -}; - -struct iwl3945_rs_sta { - spinlock_t lock; - struct iwl_priv *priv; - s32 *expected_tpt; - unsigned long last_partial_flush; - unsigned long last_flush; - u32 flush_time; - u32 last_tx_packets; - u32 tx_packets; - u8 tgg; - u8 flush_pending; - u8 start_rate; - u8 ibss_sta_added; - struct timer_list rate_scale_flush; - struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945]; -#ifdef CONFIG_MAC80211_DEBUGFS - struct dentry *rs_sta_dbgfs_stats_table_file; -#endif - - /* used to be in sta_info */ - int last_txrate_idx; -}; - -static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = { - 7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202 -}; - -static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = { - 7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125 -}; - -static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = { - 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186 -}; - -static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = { - 7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0 -}; - -struct iwl3945_tpt_entry { - s8 min_rssi; - u8 index; -}; - -static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = { - {-60, IWL_RATE_54M_INDEX}, - {-64, IWL_RATE_48M_INDEX}, - {-72, IWL_RATE_36M_INDEX}, - {-80, IWL_RATE_24M_INDEX}, - {-84, IWL_RATE_18M_INDEX}, - {-85, IWL_RATE_12M_INDEX}, - {-87, IWL_RATE_9M_INDEX}, - {-89, IWL_RATE_6M_INDEX} -}; - -static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = { - {-60, IWL_RATE_54M_INDEX}, - {-64, IWL_RATE_48M_INDEX}, - {-68, IWL_RATE_36M_INDEX}, - {-80, IWL_RATE_24M_INDEX}, - {-84, IWL_RATE_18M_INDEX}, - {-85, IWL_RATE_12M_INDEX}, - {-86, IWL_RATE_11M_INDEX}, - {-88, IWL_RATE_5M_INDEX}, - {-90, IWL_RATE_2M_INDEX}, - {-92, IWL_RATE_1M_INDEX} -}; - -#define IWL_RATE_MAX_WINDOW 62 -#define IWL_RATE_FLUSH (3*HZ) -#define IWL_RATE_WIN_FLUSH (HZ/2) -#define IWL39_RATE_HIGH_TH 11520 -#define IWL_SUCCESS_UP_TH 8960 -#define IWL_SUCCESS_DOWN_TH 10880 -#define IWL_RATE_MIN_FAILURE_TH 6 -#define IWL_RATE_MIN_SUCCESS_TH 8 -#define IWL_RATE_DECREASE_TH 1920 -#define IWL_RATE_RETRY_TH 15 - -static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band) -{ - u32 index = 0; - u32 table_size = 0; - struct iwl3945_tpt_entry *tpt_table = NULL; - - if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL)) - rssi = IWL_MIN_RSSI_VAL; - - switch (band) { - case IEEE80211_BAND_2GHZ: - tpt_table = iwl3945_tpt_table_g; - table_size = ARRAY_SIZE(iwl3945_tpt_table_g); - break; - - case IEEE80211_BAND_5GHZ: - tpt_table = iwl3945_tpt_table_a; - table_size = ARRAY_SIZE(iwl3945_tpt_table_a); - break; - - default: - BUG(); - break; - } - - while ((index < table_size) && (rssi < tpt_table[index].min_rssi)) - index++; - - index = min(index, (table_size - 1)); - - return tpt_table[index].index; -} - -static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window) -{ - window->data = 0; - window->success_counter = 0; - window->success_ratio = -1; - window->counter = 0; - window->average_tpt = IWL_INVALID_VALUE; - window->stamp = 0; -} - -/** - * iwl3945_rate_scale_flush_windows - flush out the rate scale windows - * - * Returns the number of windows that have gathered data but were - * not flushed. If there were any that were not flushed, then - * reschedule the rate flushing routine. - */ -static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta) -{ - int unflushed = 0; - int i; - unsigned long flags; - struct iwl_priv *priv __maybe_unused = rs_sta->priv; - - /* - * For each rate, if we have collected data on that rate - * and it has been more than IWL_RATE_WIN_FLUSH - * since we flushed, clear out the gathered statistics - */ - for (i = 0; i < IWL_RATE_COUNT_3945; i++) { - if (!rs_sta->win[i].counter) - continue; - - spin_lock_irqsave(&rs_sta->lock, flags); - if (time_after(jiffies, rs_sta->win[i].stamp + - IWL_RATE_WIN_FLUSH)) { - IWL_DEBUG_RATE(priv, "flushing %d samples of rate " - "index %d\n", - rs_sta->win[i].counter, i); - iwl3945_clear_window(&rs_sta->win[i]); - } else - unflushed++; - spin_unlock_irqrestore(&rs_sta->lock, flags); - } - - return unflushed; -} - -#define IWL_RATE_FLUSH_MAX 5000 /* msec */ -#define IWL_RATE_FLUSH_MIN 50 /* msec */ -#define IWL_AVERAGE_PACKETS 1500 - -static void iwl3945_bg_rate_scale_flush(unsigned long data) -{ - struct iwl3945_rs_sta *rs_sta = (void *)data; - struct iwl_priv *priv __maybe_unused = rs_sta->priv; - int unflushed = 0; - unsigned long flags; - u32 packet_count, duration, pps; - - IWL_DEBUG_RATE(priv, "enter\n"); - - unflushed = iwl3945_rate_scale_flush_windows(rs_sta); - - spin_lock_irqsave(&rs_sta->lock, flags); - - /* Number of packets Rx'd since last time this timer ran */ - packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1; - - rs_sta->last_tx_packets = rs_sta->tx_packets + 1; - - if (unflushed) { - duration = - jiffies_to_msecs(jiffies - rs_sta->last_partial_flush); - - IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n", - packet_count, duration); - - /* Determine packets per second */ - if (duration) - pps = (packet_count * 1000) / duration; - else - pps = 0; - - if (pps) { - duration = (IWL_AVERAGE_PACKETS * 1000) / pps; - if (duration < IWL_RATE_FLUSH_MIN) - duration = IWL_RATE_FLUSH_MIN; - else if (duration > IWL_RATE_FLUSH_MAX) - duration = IWL_RATE_FLUSH_MAX; - } else - duration = IWL_RATE_FLUSH_MAX; - - rs_sta->flush_time = msecs_to_jiffies(duration); - - IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n", - duration, packet_count); - - mod_timer(&rs_sta->rate_scale_flush, jiffies + - rs_sta->flush_time); - - rs_sta->last_partial_flush = jiffies; - } else { - rs_sta->flush_time = IWL_RATE_FLUSH; - rs_sta->flush_pending = 0; - } - /* If there weren't any unflushed entries, we don't schedule the timer - * to run again */ - - rs_sta->last_flush = jiffies; - - spin_unlock_irqrestore(&rs_sta->lock, flags); - - IWL_DEBUG_RATE(priv, "leave\n"); -} - -/** - * iwl3945_collect_tx_data - Update the success/failure sliding window - * - * We keep a sliding window of the last 64 packets transmitted - * at this rate. window->data contains the bitmask of successful - * packets. - */ -static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta, - struct iwl3945_rate_scale_data *window, - int success, int retries, int index) -{ - unsigned long flags; - s32 fail_count; - struct iwl_priv *priv __maybe_unused = rs_sta->priv; - - if (!retries) { - IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n"); - return; - } - - spin_lock_irqsave(&rs_sta->lock, flags); - - /* - * Keep track of only the latest 62 tx frame attempts in this rate's - * history window; anything older isn't really relevant any more. - * If we have filled up the sliding window, drop the oldest attempt; - * if the oldest attempt (highest bit in bitmap) shows "success", - * subtract "1" from the success counter (this is the main reason - * we keep these bitmaps!). - * */ - while (retries > 0) { - if (window->counter >= IWL_RATE_MAX_WINDOW) { - - /* remove earliest */ - window->counter = IWL_RATE_MAX_WINDOW - 1; - - if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) { - window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1)); - window->success_counter--; - } - } - - /* Increment frames-attempted counter */ - window->counter++; - - /* Shift bitmap by one frame (throw away oldest history), - * OR in "1", and increment "success" if this - * frame was successful. */ - window->data <<= 1; - if (success > 0) { - window->success_counter++; - window->data |= 0x1; - success--; - } - - retries--; - } - - /* Calculate current success ratio, avoid divide-by-0! */ - if (window->counter > 0) - window->success_ratio = 128 * (100 * window->success_counter) - / window->counter; - else - window->success_ratio = IWL_INVALID_VALUE; - - fail_count = window->counter - window->success_counter; - - /* Calculate average throughput, if we have enough history. */ - if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || - (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) - window->average_tpt = ((window->success_ratio * - rs_sta->expected_tpt[index] + 64) / 128); - else - window->average_tpt = IWL_INVALID_VALUE; - - /* Tag this window as having been updated */ - window->stamp = jiffies; - - spin_unlock_irqrestore(&rs_sta->lock, flags); - -} - -static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) -{ - struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; - int i; - - IWL_DEBUG_RATE(priv, "enter\n"); - - /* TODO: what is a good starting rate for STA? About middle? Maybe not - * the lowest or the highest rate.. Could consider using RSSI from - * previous packets? Need to have IEEE 802.1X auth succeed immediately - * after assoc.. */ - - for (i = sband->n_bitrates - 1; i >= 0; i--) { - if (sta->supp_rates[sband->band] & (1 << i)) { - rs_sta->last_txrate_idx = i; - break; - } - } - - priv->sta_supp_rates = sta->supp_rates[sband->band]; - /* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */ - if (sband->band == IEEE80211_BAND_5GHZ) { - rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; - priv->sta_supp_rates = priv->sta_supp_rates << - IWL_FIRST_OFDM_RATE; - } - - - IWL_DEBUG_RATE(priv, "leave\n"); -} - -static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -{ - return hw->priv; -} - -/* rate scale requires free function to be implemented */ -static void rs_free(void *priv) -{ - return; -} - -static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp) -{ - struct iwl3945_rs_sta *rs_sta; - struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; - struct iwl_priv *priv = iwl_priv; - int i; - - /* - * XXX: If it's using sta->drv_priv anyway, it might - * as well just put all the information there. - */ - - IWL_DEBUG_RATE(priv, "enter\n"); - - rs_sta = kzalloc(sizeof(struct iwl3945_rs_sta), gfp); - if (!rs_sta) { - IWL_DEBUG_RATE(priv, "leave: ENOMEM\n"); - return NULL; - } - - psta->rs_sta = rs_sta; - - spin_lock_init(&rs_sta->lock); - - rs_sta->priv = priv; - - rs_sta->start_rate = IWL_RATE_INVALID; - - /* default to just 802.11b */ - rs_sta->expected_tpt = iwl3945_expected_tpt_b; - - rs_sta->last_partial_flush = jiffies; - rs_sta->last_flush = jiffies; - rs_sta->flush_time = IWL_RATE_FLUSH; - rs_sta->last_tx_packets = 0; - rs_sta->ibss_sta_added = 0; - - init_timer(&rs_sta->rate_scale_flush); - rs_sta->rate_scale_flush.data = (unsigned long)rs_sta; - rs_sta->rate_scale_flush.function = &iwl3945_bg_rate_scale_flush; - - for (i = 0; i < IWL_RATE_COUNT_3945; i++) - iwl3945_clear_window(&rs_sta->win[i]); - - IWL_DEBUG_RATE(priv, "leave\n"); - - return rs_sta; -} - -static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta, - void *priv_sta) -{ - struct iwl3945_sta_priv *psta = (void *) sta->drv_priv; - struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl_priv *priv __maybe_unused = rs_sta->priv; - - psta->rs_sta = NULL; - - IWL_DEBUG_RATE(priv, "enter\n"); - del_timer_sync(&rs_sta->rate_scale_flush); - kfree(rs_sta); - IWL_DEBUG_RATE(priv, "leave\n"); -} - - -/** - * rs_tx_status - Update rate control values based on Tx results - * - * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by - * the hardware for each rate. - */ -static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) -{ - s8 retries = 0, current_count; - int scale_rate_index, first_index, last_index; - unsigned long flags; - struct iwl_priv *priv = (struct iwl_priv *)priv_rate; - struct iwl3945_rs_sta *rs_sta = priv_sta; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - IWL_DEBUG_RATE(priv, "enter\n"); - - retries = info->status.rates[0].count; - /* Sanity Check for retries */ - if (retries > IWL_RATE_RETRY_TH) - retries = IWL_RATE_RETRY_TH; - - first_index = sband->bitrates[info->status.rates[0].idx].hw_value; - if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) { - IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index); - return; - } - - if (!priv_sta) { - IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n"); - return; - } - - rs_sta->tx_packets++; - - scale_rate_index = first_index; - last_index = first_index; - - /* - * Update the window for each rate. We determine which rates - * were Tx'd based on the total number of retries vs. the number - * of retries configured for each rate -- currently set to the - * priv value 'retry_rate' vs. rate specific - * - * On exit from this while loop last_index indicates the rate - * at which the frame was finally transmitted (or failed if no - * ACK) - */ - while (retries > 1) { - if ((retries - 1) < priv->retry_rate) { - current_count = (retries - 1); - last_index = scale_rate_index; - } else { - current_count = priv->retry_rate; - last_index = iwl3945_rs_next_rate(priv, - scale_rate_index); - } - - /* Update this rate accounting for as many retries - * as was used for it (per current_count) */ - iwl3945_collect_tx_data(rs_sta, - &rs_sta->win[scale_rate_index], - 0, current_count, scale_rate_index); - IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n", - scale_rate_index, current_count); - - retries -= current_count; - - scale_rate_index = last_index; - } - - - /* Update the last index window with success/failure based on ACK */ - IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n", - last_index, - (info->flags & IEEE80211_TX_STAT_ACK) ? - "success" : "failure"); - iwl3945_collect_tx_data(rs_sta, - &rs_sta->win[last_index], - info->flags & IEEE80211_TX_STAT_ACK, 1, last_index); - - /* We updated the rate scale window -- if its been more than - * flush_time since the last run, schedule the flush - * again */ - spin_lock_irqsave(&rs_sta->lock, flags); - - if (!rs_sta->flush_pending && - time_after(jiffies, rs_sta->last_flush + - rs_sta->flush_time)) { - - rs_sta->last_partial_flush = jiffies; - rs_sta->flush_pending = 1; - mod_timer(&rs_sta->rate_scale_flush, - jiffies + rs_sta->flush_time); - } - - spin_unlock_irqrestore(&rs_sta->lock, flags); - - IWL_DEBUG_RATE(priv, "leave\n"); - - return; -} - -static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta, - u8 index, u16 rate_mask, enum ieee80211_band band) -{ - u8 high = IWL_RATE_INVALID; - u8 low = IWL_RATE_INVALID; - struct iwl_priv *priv __maybe_unused = rs_sta->priv; - - /* 802.11A walks to the next literal adjacent rate in - * the rate table */ - if (unlikely(band == IEEE80211_BAND_5GHZ)) { - int i; - u32 mask; - - /* Find the previous rate that is in the rate mask */ - i = index - 1; - for (mask = (1 << i); i >= 0; i--, mask >>= 1) { - if (rate_mask & mask) { - low = i; - break; - } - } - - /* Find the next rate that is in the rate mask */ - i = index + 1; - for (mask = (1 << i); i < IWL_RATE_COUNT_3945; - i++, mask <<= 1) { - if (rate_mask & mask) { - high = i; - break; - } - } - - return (high << 8) | low; - } - - low = index; - while (low != IWL_RATE_INVALID) { - if (rs_sta->tgg) - low = iwl3945_rates[low].prev_rs_tgg; - else - low = iwl3945_rates[low].prev_rs; - if (low == IWL_RATE_INVALID) - break; - if (rate_mask & (1 << low)) - break; - IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low); - } - - high = index; - while (high != IWL_RATE_INVALID) { - if (rs_sta->tgg) - high = iwl3945_rates[high].next_rs_tgg; - else - high = iwl3945_rates[high].next_rs; - if (high == IWL_RATE_INVALID) - break; - if (rate_mask & (1 << high)) - break; - IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high); - } - - return (high << 8) | low; -} - -/** - * rs_get_rate - find the rate for the requested packet - * - * Returns the ieee80211_rate structure allocated by the driver. - * - * The rate control algorithm has no internal mapping between hw_mode's - * rate ordering and the rate ordering used by the rate control algorithm. - * - * The rate control algorithm uses a single table of rates that goes across - * the entire A/B/G spectrum vs. being limited to just one particular - * hw_mode. - * - * As such, we can't convert the index obtained below into the hw_mode's - * rate table and must reference the driver allocated rate table - * - */ -static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, - void *priv_sta, struct ieee80211_tx_rate_control *txrc) -{ - struct ieee80211_supported_band *sband = txrc->sband; - struct sk_buff *skb = txrc->skb; - u8 low = IWL_RATE_INVALID; - u8 high = IWL_RATE_INVALID; - u16 high_low; - int index; - struct iwl3945_rs_sta *rs_sta = priv_sta; - struct iwl3945_rate_scale_data *window = NULL; - int current_tpt = IWL_INVALID_VALUE; - int low_tpt = IWL_INVALID_VALUE; - int high_tpt = IWL_INVALID_VALUE; - u32 fail_count; - s8 scale_action = 0; - unsigned long flags; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0; - s8 max_rate_idx = -1; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - IWL_DEBUG_RATE(priv, "enter\n"); - - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - - rate_mask = sta->supp_rates[sband->band]; - - /* get user max rate if set */ - max_rate_idx = txrc->max_rate_idx; - if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1)) - max_rate_idx += IWL_FIRST_OFDM_RATE; - if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT)) - max_rate_idx = -1; - - index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1); - - if (sband->band == IEEE80211_BAND_5GHZ) - rate_mask = rate_mask << IWL_FIRST_OFDM_RATE; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !rs_sta->ibss_sta_added) { - u8 sta_id = iwl_find_station(priv, hdr->addr1); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", - hdr->addr1); - sta_id = iwl_add_station(priv, hdr->addr1, false, - CMD_ASYNC, NULL); - } - if (sta_id != IWL_INVALID_STATION) - rs_sta->ibss_sta_added = 1; - } - - spin_lock_irqsave(&rs_sta->lock, flags); - - /* for recent assoc, choose best rate regarding - * to rssi value - */ - if (rs_sta->start_rate != IWL_RATE_INVALID) { - if (rs_sta->start_rate < index && - (rate_mask & (1 << rs_sta->start_rate))) - index = rs_sta->start_rate; - rs_sta->start_rate = IWL_RATE_INVALID; - } - - /* force user max rate if set by user */ - if ((max_rate_idx != -1) && (max_rate_idx < index)) { - if (rate_mask & (1 << max_rate_idx)) - index = max_rate_idx; - } - - window = &(rs_sta->win[index]); - - fail_count = window->counter - window->success_counter; - - if (((fail_count < IWL_RATE_MIN_FAILURE_TH) && - (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) { - spin_unlock_irqrestore(&rs_sta->lock, flags); - - IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: " - "counter: %d, success_counter: %d, " - "expected_tpt is %sNULL\n", - index, - window->counter, - window->success_counter, - rs_sta->expected_tpt ? "not " : ""); - - /* Can't calculate this yet; not enough history */ - window->average_tpt = IWL_INVALID_VALUE; - goto out; - - } - - current_tpt = window->average_tpt; - - high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask, - sband->band); - low = high_low & 0xff; - high = (high_low >> 8) & 0xff; - - /* If user set max rate, dont allow higher than user constrain */ - if ((max_rate_idx != -1) && (max_rate_idx < high)) - high = IWL_RATE_INVALID; - - /* Collect Measured throughputs of adjacent rates */ - if (low != IWL_RATE_INVALID) - low_tpt = rs_sta->win[low].average_tpt; - - if (high != IWL_RATE_INVALID) - high_tpt = rs_sta->win[high].average_tpt; - - spin_unlock_irqrestore(&rs_sta->lock, flags); - - scale_action = 0; - - /* Low success ratio , need to drop the rate */ - if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) { - IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); - scale_action = -1; - /* No throughput measured yet for adjacent rates, - * try increase */ - } else if ((low_tpt == IWL_INVALID_VALUE) && - (high_tpt == IWL_INVALID_VALUE)) { - - if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH) - scale_action = 1; - else if (low != IWL_RATE_INVALID) - scale_action = 0; - - /* Both adjacent throughputs are measured, but neither one has - * better throughput; we're using the best rate, don't change - * it! */ - } else if ((low_tpt != IWL_INVALID_VALUE) && - (high_tpt != IWL_INVALID_VALUE) && - (low_tpt < current_tpt) && (high_tpt < current_tpt)) { - - IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < " - "current_tpt [%d]\n", - low_tpt, high_tpt, current_tpt); - scale_action = 0; - - /* At least one of the rates has better throughput */ - } else { - if (high_tpt != IWL_INVALID_VALUE) { - - /* High rate has better throughput, Increase - * rate */ - if (high_tpt > current_tpt && - window->success_ratio >= IWL_RATE_INCREASE_TH) - scale_action = 1; - else { - IWL_DEBUG_RATE(priv, - "decrease rate because of high tpt\n"); - scale_action = 0; - } - } else if (low_tpt != IWL_INVALID_VALUE) { - if (low_tpt > current_tpt) { - IWL_DEBUG_RATE(priv, - "decrease rate because of low tpt\n"); - scale_action = -1; - } else if (window->success_ratio >= IWL_RATE_INCREASE_TH) { - /* Lower rate has better - * throughput,decrease rate */ - scale_action = 1; - } - } - } - - /* Sanity check; asked for decrease, but success rate or throughput - * has been good at old rate. Don't change it. */ - if ((scale_action == -1) && (low != IWL_RATE_INVALID) && - ((window->success_ratio > IWL_RATE_HIGH_TH) || - (current_tpt > (100 * rs_sta->expected_tpt[low])))) - scale_action = 0; - - switch (scale_action) { - case -1: - - /* Decrese rate */ - if (low != IWL_RATE_INVALID) - index = low; - break; - - case 1: - /* Increase rate */ - if (high != IWL_RATE_INVALID) - index = high; - - break; - - case 0: - default: - /* No change */ - break; - } - - IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n", - index, scale_action, low, high); - - out: - - rs_sta->last_txrate_idx = index; - if (sband->band == IEEE80211_BAND_5GHZ) - info->control.rates[0].idx = rs_sta->last_txrate_idx - - IWL_FIRST_OFDM_RATE; - else - info->control.rates[0].idx = rs_sta->last_txrate_idx; - - IWL_DEBUG_RATE(priv, "leave: %d\n", index); -} - -#ifdef CONFIG_MAC80211_DEBUGFS -static int iwl3945_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - char *buff; - int desc = 0; - int j; - ssize_t ret; - struct iwl3945_rs_sta *lq_sta = file->private_data; - - buff = kmalloc(1024, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n" - "rate=0x%X flush time %d\n", - lq_sta->tx_packets, - lq_sta->last_txrate_idx, - lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time)); - for (j = 0; j < IWL_RATE_COUNT_3945; j++) { - desc += sprintf(buff+desc, - "counter=%d success=%d %%=%d\n", - lq_sta->win[j].counter, - lq_sta->win[j].success_counter, - lq_sta->win[j].success_ratio); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); - kfree(buff); - return ret; -} - -static const struct file_operations rs_sta_dbgfs_stats_table_ops = { - .read = iwl3945_sta_dbgfs_stats_table_read, - .open = iwl3945_open_file_generic, -}; - -static void iwl3945_add_debugfs(void *priv, void *priv_sta, - struct dentry *dir) -{ - struct iwl3945_rs_sta *lq_sta = priv_sta; - - lq_sta->rs_sta_dbgfs_stats_table_file = - debugfs_create_file("rate_stats_table", 0600, dir, - lq_sta, &rs_sta_dbgfs_stats_table_ops); - -} - -static void iwl3945_remove_debugfs(void *priv, void *priv_sta) -{ - struct iwl3945_rs_sta *lq_sta = priv_sta; - debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); -} -#endif - -static struct rate_control_ops rs_ops = { - .module = NULL, - .name = RS_NAME, - .tx_status = rs_tx_status, - .get_rate = rs_get_rate, - .rate_init = rs_rate_init, - .alloc = rs_alloc, - .free = rs_free, - .alloc_sta = rs_alloc_sta, - .free_sta = rs_free_sta, -#ifdef CONFIG_MAC80211_DEBUGFS - .add_sta_debugfs = iwl3945_add_debugfs, - .remove_sta_debugfs = iwl3945_remove_debugfs, -#endif - -}; - -void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id) -{ - struct iwl_priv *priv = hw->priv; - s32 rssi = 0; - unsigned long flags; - struct iwl3945_rs_sta *rs_sta; - struct ieee80211_sta *sta; - struct iwl3945_sta_priv *psta; - - IWL_DEBUG_RATE(priv, "enter\n"); - - rcu_read_lock(); - - sta = ieee80211_find_sta(hw, priv->stations[sta_id].sta.sta.addr); - if (!sta) { - rcu_read_unlock(); - return; - } - - psta = (void *) sta->drv_priv; - rs_sta = psta->rs_sta; - - spin_lock_irqsave(&rs_sta->lock, flags); - - rs_sta->tgg = 0; - switch (priv->band) { - case IEEE80211_BAND_2GHZ: - /* TODO: this always does G, not a regression */ - if (priv->active_rxon.flags & RXON_FLG_TGG_PROTECT_MSK) { - rs_sta->tgg = 1; - rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot; - } else - rs_sta->expected_tpt = iwl3945_expected_tpt_g; - break; - - case IEEE80211_BAND_5GHZ: - rs_sta->expected_tpt = iwl3945_expected_tpt_a; - break; - case IEEE80211_NUM_BANDS: - BUG(); - break; - } - - spin_unlock_irqrestore(&rs_sta->lock, flags); - - rssi = priv->last_rx_rssi; - if (rssi == 0) - rssi = IWL_MIN_RSSI_VAL; - - IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi); - - rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band); - - IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: " - "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate, - iwl3945_rates[rs_sta->start_rate].plcp); - rcu_read_unlock(); -} - -int iwl3945_rate_control_register(void) -{ - return ieee80211_rate_control_register(&rs_ops); -} - -void iwl3945_rate_control_unregister(void) -{ - ieee80211_rate_control_unregister(&rs_ops); -} - - diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c deleted file mode 100644 index 56bfcc35c9f0..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ /dev/null @@ -1,2924 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-fh.h" -#include "iwl-3945-fh.h" -#include "iwl-commands.h" -#include "iwl-sta.h" -#include "iwl-3945.h" -#include "iwl-eeprom.h" -#include "iwl-helpers.h" -#include "iwl-core.h" -#include "iwl-agn-rs.h" - -#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np) \ - [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ - IWL_RATE_##r##M_IEEE, \ - IWL_RATE_##ip##M_INDEX, \ - IWL_RATE_##in##M_INDEX, \ - IWL_RATE_##rp##M_INDEX, \ - IWL_RATE_##rn##M_INDEX, \ - IWL_RATE_##pp##M_INDEX, \ - IWL_RATE_##np##M_INDEX, \ - IWL_RATE_##r##M_INDEX_TABLE, \ - IWL_RATE_##ip##M_INDEX_TABLE } - -/* - * Parameter order: - * rate, prev rate, next rate, prev tgg rate, next tgg rate - * - * If there isn't a valid next or previous rate then INV is used which - * maps to IWL_RATE_INVALID - * - */ -const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = { - IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2), /* 1mbps */ - IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5), /* 2mbps */ - IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11), /*5.5mbps */ - IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18), /* 11mbps */ - IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11), /* 6mbps */ - IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11), /* 9mbps */ - IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18), /* 12mbps */ - IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24), /* 18mbps */ - IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36), /* 24mbps */ - IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48), /* 36mbps */ - IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54), /* 48mbps */ - IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */ -}; - -/* 1 = enable the iwl3945_disable_events() function */ -#define IWL_EVT_DISABLE (0) -#define IWL_EVT_DISABLE_SIZE (1532/32) - -/** - * iwl3945_disable_events - Disable selected events in uCode event log - * - * Disable an event by writing "1"s into "disable" - * bitmap in SRAM. Bit position corresponds to Event # (id/type). - * Default values of 0 enable uCode events to be logged. - * Use for only special debugging. This function is just a placeholder as-is, - * you'll need to provide the special bits! ... - * ... and set IWL_EVT_DISABLE to 1. */ -void iwl3945_disable_events(struct iwl_priv *priv) -{ - int i; - u32 base; /* SRAM address of event log header */ - u32 disable_ptr; /* SRAM address of event-disable bitmap array */ - u32 array_size; /* # of u32 entries in array */ - u32 evt_disable[IWL_EVT_DISABLE_SIZE] = { - 0x00000000, /* 31 - 0 Event id numbers */ - 0x00000000, /* 63 - 32 */ - 0x00000000, /* 95 - 64 */ - 0x00000000, /* 127 - 96 */ - 0x00000000, /* 159 - 128 */ - 0x00000000, /* 191 - 160 */ - 0x00000000, /* 223 - 192 */ - 0x00000000, /* 255 - 224 */ - 0x00000000, /* 287 - 256 */ - 0x00000000, /* 319 - 288 */ - 0x00000000, /* 351 - 320 */ - 0x00000000, /* 383 - 352 */ - 0x00000000, /* 415 - 384 */ - 0x00000000, /* 447 - 416 */ - 0x00000000, /* 479 - 448 */ - 0x00000000, /* 511 - 480 */ - 0x00000000, /* 543 - 512 */ - 0x00000000, /* 575 - 544 */ - 0x00000000, /* 607 - 576 */ - 0x00000000, /* 639 - 608 */ - 0x00000000, /* 671 - 640 */ - 0x00000000, /* 703 - 672 */ - 0x00000000, /* 735 - 704 */ - 0x00000000, /* 767 - 736 */ - 0x00000000, /* 799 - 768 */ - 0x00000000, /* 831 - 800 */ - 0x00000000, /* 863 - 832 */ - 0x00000000, /* 895 - 864 */ - 0x00000000, /* 927 - 896 */ - 0x00000000, /* 959 - 928 */ - 0x00000000, /* 991 - 960 */ - 0x00000000, /* 1023 - 992 */ - 0x00000000, /* 1055 - 1024 */ - 0x00000000, /* 1087 - 1056 */ - 0x00000000, /* 1119 - 1088 */ - 0x00000000, /* 1151 - 1120 */ - 0x00000000, /* 1183 - 1152 */ - 0x00000000, /* 1215 - 1184 */ - 0x00000000, /* 1247 - 1216 */ - 0x00000000, /* 1279 - 1248 */ - 0x00000000, /* 1311 - 1280 */ - 0x00000000, /* 1343 - 1312 */ - 0x00000000, /* 1375 - 1344 */ - 0x00000000, /* 1407 - 1376 */ - 0x00000000, /* 1439 - 1408 */ - 0x00000000, /* 1471 - 1440 */ - 0x00000000, /* 1503 - 1472 */ - }; - - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - if (!iwl3945_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); - return; - } - - disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32))); - array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32))); - - if (IWL_EVT_DISABLE && (array_size == IWL_EVT_DISABLE_SIZE)) { - IWL_DEBUG_INFO(priv, "Disabling selected uCode log events at 0x%x\n", - disable_ptr); - for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++) - iwl_write_targ_mem(priv, - disable_ptr + (i * sizeof(u32)), - evt_disable[i]); - - } else { - IWL_DEBUG_INFO(priv, "Selected uCode log events may be disabled\n"); - IWL_DEBUG_INFO(priv, " by writing \"1\"s into disable bitmap\n"); - IWL_DEBUG_INFO(priv, " in SRAM at 0x%x, size %d u32s\n", - disable_ptr, array_size); - } - -} - -static int iwl3945_hwrate_to_plcp_idx(u8 plcp) -{ - int idx; - - for (idx = 0; idx < IWL_RATE_COUNT; idx++) - if (iwl3945_rates[idx].plcp == plcp) - return idx; - return -1; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x - -static const char *iwl3945_get_tx_fail_reason(u32 status) -{ - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_ENTRY(SHORT_LIMIT); - TX_STATUS_ENTRY(LONG_LIMIT); - TX_STATUS_ENTRY(FIFO_UNDERRUN); - TX_STATUS_ENTRY(MGMNT_ABORT); - TX_STATUS_ENTRY(NEXT_FRAG); - TX_STATUS_ENTRY(LIFE_EXPIRE); - TX_STATUS_ENTRY(DEST_PS); - TX_STATUS_ENTRY(ABORTED); - TX_STATUS_ENTRY(BT_RETRY); - TX_STATUS_ENTRY(STA_INVALID); - TX_STATUS_ENTRY(FRAG_DROPPED); - TX_STATUS_ENTRY(TID_DISABLE); - TX_STATUS_ENTRY(FRAME_FLUSHED); - TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); - TX_STATUS_ENTRY(TX_LOCKED); - TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); - } - - return "UNKNOWN"; -} -#else -static inline const char *iwl3945_get_tx_fail_reason(u32 status) -{ - return ""; -} -#endif - -/* - * get ieee prev rate from rate scale table. - * for A and B mode we need to overright prev - * value - */ -int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate) -{ - int next_rate = iwl3945_get_prev_ieee_rate(rate); - - switch (priv->band) { - case IEEE80211_BAND_5GHZ: - if (rate == IWL_RATE_12M_INDEX) - next_rate = IWL_RATE_9M_INDEX; - else if (rate == IWL_RATE_6M_INDEX) - next_rate = IWL_RATE_6M_INDEX; - break; - case IEEE80211_BAND_2GHZ: - if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && - iwl_is_associated(priv)) { - if (rate == IWL_RATE_11M_INDEX) - next_rate = IWL_RATE_5M_INDEX; - } - break; - - default: - break; - } - - return next_rate; -} - - -/** - * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd - * - * When FW advances 'R' index, all entries between old and new 'R' index - * need to be reclaimed. As result, some free space forms. If there is - * enough free space (> low mark), wake the stack that feeds us. - */ -static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv, - int txq_id, int index) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - struct iwl_tx_info *tx_info; - - BUG_ON(txq_id == IWL_CMD_QUEUE_NUM); - - for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - tx_info = &txq->txb[txq->q.read_ptr]; - ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); - tx_info->skb[0] = NULL; - priv->cfg->ops->lib->txq_free_tfd(priv, txq); - } - - if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) && - (txq_id != IWL_CMD_QUEUE_NUM) && - priv->mac80211_registered) - iwl_wake_queue(priv, txq_id); -} - -/** - * iwl3945_rx_reply_tx - Handle Tx response - */ -static void iwl3945_rx_reply_tx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_tx_info *info; - struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->status); - int rate_idx; - int fail; - - if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " - "is out of range [0-%d] %d %d\n", txq_id, - index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - ieee80211_tx_info_clear_status(info); - - /* Fill the MRR chain with some info about on-chip retransmissions */ - rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); - if (info->band == IEEE80211_BAND_5GHZ) - rate_idx -= IWL_FIRST_OFDM_RATE; - - fail = tx_resp->failure_frame; - - info->status.rates[0].idx = rate_idx; - info->status.rates[0].count = fail + 1; /* add final attempt */ - - /* tx_status->rts_retry_count = tx_resp->failure_rts; */ - info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? - IEEE80211_TX_STAT_ACK : 0; - - IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n", - txq_id, iwl3945_get_tx_fail_reason(status), status, - tx_resp->rate, tx_resp->failure_frame); - - IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index); - iwl3945_tx_queue_reclaim(priv, txq_id, index); - - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); -} - - - -/***************************************************************************** - * - * Intel PRO/Wireless 3945ABG/BG Network Connection - * - * RX handler implementations - * - *****************************************************************************/ - -void iwl3945_hw_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", - (int)sizeof(struct iwl3945_notif_statistics), - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); - - memcpy(&priv->statistics_39, pkt->u.raw, sizeof(priv->statistics_39)); - - iwl3945_led_background(priv); - - priv->last_statistics_time = jiffies; -} - -/****************************************************************************** - * - * Misc. internal state and helper functions - * - ******************************************************************************/ -#ifdef CONFIG_IWLWIFI_DEBUG - -/** - * iwl3945_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good frames. - */ -static void _iwl3945_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - __le16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - u16 length; - u16 status; - u16 bcn_tmr; - u32 tsf_low; - u64 tsf; - u8 rssi; - u8 agc; - u16 sig_avg; - u16 noise_diff; - struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); - struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - u8 *data = IWL_RX_DATA(pkt); - - /* MAC header */ - fc = header->frame_control; - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(rx_hdr->channel); - phy_flags = le16_to_cpu(rx_hdr->phy_flags); - length = le16_to_cpu(rx_hdr->len); - - /* end-of-frame status and timestamp */ - status = le32_to_cpu(rx_end->status); - bcn_tmr = le32_to_cpu(rx_end->beacon_timestamp); - tsf_low = le64_to_cpu(rx_end->timestamp) & 0x0ffffffff; - tsf = le64_to_cpu(rx_end->timestamp); - - /* signal statistics */ - rssi = rx_stats->rssi; - agc = rx_stats->agc; - sig_avg = le16_to_cpu(rx_stats->sig_avg); - noise_diff = le16_to_cpu(rx_stats->noise_diff); - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == - cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - int rate; - - if (hundred) - title = "100Frames"; - else if (ieee80211_has_retry(fc)) - title = "Retry"; - else if (ieee80211_is_assoc_resp(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_resp(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_resp(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); - if (rate == -1) - rate = 0; - else - rate = iwl3945_rates[rate].ieee / 2; - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%d, \n", - title, le16_to_cpu(fc), header->addr1[5], - length, rssi, channel, rate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, " - "src=0x%02x, rssi=%u, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, le16_to_cpu(fc), header->addr1[5], - header->addr3[5], rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, data, length); -} - -static void iwl3945_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ - if (iwl_get_debug_level(priv) & IWL_DL_RX) - _iwl3945_dbg_report_frame(priv, pkt, header, group100); -} - -#else -static inline void iwl3945_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_packet *pkt, - struct ieee80211_hdr *header, int group100) -{ -} -#endif - -/* This is necessary only for a number of statistics, see the caller. */ -static int iwl3945_is_network_packet(struct iwl_priv *priv, - struct ieee80211_hdr *header) -{ - /* Filter incoming packets to determine if they are targeted toward - * this network, discarding packets coming from ourselves */ - switch (priv->iw_mode) { - case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ - /* packets to our IBSS update information */ - return !compare_ether_addr(header->addr3, priv->bssid); - case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ - /* packets to our IBSS update information */ - return !compare_ether_addr(header->addr2, priv->bssid); - default: - return 1; - } -} - -static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb, - struct ieee80211_rx_status *stats) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); - struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - short len = le16_to_cpu(rx_hdr->len); - - /* We received data from the HW, so stop the watchdog */ - if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) { - IWL_DEBUG_DROP(priv, "Corruption detected!\n"); - return; - } - - /* We only process data packets if the interface is open */ - if (unlikely(!priv->is_open)) { - IWL_DEBUG_DROP_LIMIT(priv, - "Dropping packet while interface is not open.\n"); - return; - } - - skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt); - /* Set the size of the skb to the size of the frame */ - skb_put(rxb->skb, le16_to_cpu(rx_hdr->len)); - - if (!iwl3945_mod_params.sw_crypto) - iwl_set_decrypted_flag(priv, - (struct ieee80211_hdr *)rxb->skb->data, - le32_to_cpu(rx_end->status), stats); - -#ifdef CONFIG_IWLWIFI_LEDS - if (ieee80211_is_data(hdr->frame_control)) - priv->rxtxpackets += len; -#endif - iwl_update_stats(priv, false, hdr->frame_control, len); - - memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); - ieee80211_rx_irqsafe(priv->hw, rxb->skb); - rxb->skb = NULL; -} - -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) - -static void iwl3945_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct ieee80211_hdr *header; - struct ieee80211_rx_status rx_status; - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt); - struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt); - struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt); - int snr; - u16 rx_stats_sig_avg = le16_to_cpu(rx_stats->sig_avg); - u16 rx_stats_noise_diff = le16_to_cpu(rx_stats->noise_diff); - u8 network_packet; - - rx_status.flag = 0; - rx_status.mactime = le64_to_cpu(rx_end->timestamp); - rx_status.freq = - ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel)); - rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - - rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate); - if (rx_status.band == IEEE80211_BAND_5GHZ) - rx_status.rate_idx -= IWL_FIRST_OFDM_RATE; - - rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) & - RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4; - - /* set the preamble flag if appropriate */ - if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) - rx_status.flag |= RX_FLAG_SHORTPRE; - - if ((unlikely(rx_stats->phy_count > 20))) { - IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", - rx_stats->phy_count); - return; - } - - if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR) - || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { - IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status); - return; - } - - - - /* Convert 3945's rssi indicator to dBm */ - rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET; - - /* Set default noise value to -127 */ - if (priv->last_rx_noise == 0) - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - - /* 3945 provides noise info for OFDM frames only. - * sig_avg and noise_diff are measured by the 3945's digital signal - * processor (DSP), and indicate linear levels of signal level and - * distortion/noise within the packet preamble after - * automatic gain control (AGC). sig_avg should stay fairly - * constant if the radio's AGC is working well. - * Since these values are linear (not dB or dBm), linear - * signal-to-noise ratio (SNR) is (sig_avg / noise_diff). - * Convert linear SNR to dB SNR, then subtract that from rssi dBm - * to obtain noise level in dBm. - * Calculate rx_status.signal (quality indicator in %) based on SNR. */ - if (rx_stats_noise_diff) { - snr = rx_stats_sig_avg / rx_stats_noise_diff; - rx_status.noise = rx_status.signal - - iwl3945_calc_db_from_ratio(snr); - rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, - rx_status.noise); - - /* If noise info not available, calculate signal quality indicator (%) - * using just the dBm signal level. */ - } else { - rx_status.noise = priv->last_rx_noise; - rx_status.qual = iwl3945_calc_sig_qual(rx_status.signal, 0); - } - - - IWL_DEBUG_STATS(priv, "Rssi %d noise %d qual %d sig_avg %d noise_diff %d\n", - rx_status.signal, rx_status.noise, rx_status.qual, - rx_stats_sig_avg, rx_stats_noise_diff); - - header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt); - - network_packet = iwl3945_is_network_packet(priv, header); - - IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Noise:%u, Rate:%u\n", - network_packet ? '*' : ' ', - le16_to_cpu(rx_hdr->channel), - rx_status.signal, rx_status.signal, - rx_status.noise, rx_status.rate_idx); - - /* Set "1" to report good data frames in groups of 100 */ - iwl3945_dbg_report_frame(priv, pkt, header, 1); - iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header); - - if (network_packet) { - priv->last_beacon_time = le32_to_cpu(rx_end->beacon_timestamp); - priv->last_tsf = le64_to_cpu(rx_end->timestamp); - priv->last_rx_rssi = rx_status.signal; - priv->last_rx_noise = rx_status.noise; - } - - iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status); -} - -int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, u8 reset, u8 pad) -{ - int count; - struct iwl_queue *q; - struct iwl3945_tfd *tfd, *tfd_tmp; - - q = &txq->q; - tfd_tmp = (struct iwl3945_tfd *)txq->tfds; - tfd = &tfd_tmp[q->write_ptr]; - - if (reset) - memset(tfd, 0, sizeof(*tfd)); - - count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); - - if ((count >= NUM_TFD_CHUNKS) || (count < 0)) { - IWL_ERR(priv, "Error can not send more than %d chunks\n", - NUM_TFD_CHUNKS); - return -EINVAL; - } - - tfd->tbs[count].addr = cpu_to_le32(addr); - tfd->tbs[count].len = cpu_to_le32(len); - - count++; - - tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) | - TFD_CTL_PAD_SET(pad)); - - return 0; -} - -/** - * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr] - * - * Does NOT advance any indexes - */ -void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds; - int index = txq->q.read_ptr; - struct iwl3945_tfd *tfd = &tfd_tmp[index]; - struct pci_dev *dev = priv->pci_dev; - int i; - int counter; - - /* sanity check */ - counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags)); - if (counter > NUM_TFD_CHUNKS) { - IWL_ERR(priv, "Too many chunks: %i\n", counter); - /* @todo issue fatal error, it is quite serious situation */ - return; - } - - /* Unmap tx_cmd */ - if (counter) - pci_unmap_single(dev, - pci_unmap_addr(&txq->meta[index], mapping), - pci_unmap_len(&txq->meta[index], len), - PCI_DMA_TODEVICE); - - /* unmap chunks if any */ - - for (i = 1; i < counter; i++) { - pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr), - le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE); - if (txq->txb[txq->q.read_ptr].skb[0]) { - struct sk_buff *skb = txq->txb[txq->q.read_ptr].skb[0]; - if (txq->txb[txq->q.read_ptr].skb[0]) { - /* Can be called from interrupt context */ - dev_kfree_skb_any(skb); - txq->txb[txq->q.read_ptr].skb[0] = NULL; - } - } - } - return ; -} - -/** - * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD: - * -*/ -void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - int sta_id, int tx_id) -{ - u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value; - u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT - 1); - u16 rate_mask; - int rate; - u8 rts_retry_limit; - u8 data_retry_limit; - __le32 tx_flags; - __le16 fc = hdr->frame_control; - struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; - - rate = iwl3945_rates[rate_index].plcp; - tx_flags = tx->tx_flags; - - /* We need to figure out how to get the sta->supp_rates while - * in this running context */ - rate_mask = IWL_RATES_MASK; - - if (tx_id >= IWL_CMD_QUEUE_NUM) - rts_retry_limit = 3; - else - rts_retry_limit = 7; - - if (ieee80211_is_probe_resp(fc)) { - data_retry_limit = 3; - if (data_retry_limit < rts_retry_limit) - rts_retry_limit = data_retry_limit; - } else - data_retry_limit = IWL_DEFAULT_TX_RETRY; - - if (priv->data_retry_limit != -1) - data_retry_limit = priv->data_retry_limit; - - if (ieee80211_is_mgmt(fc)) { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - if (tx_flags & TX_CMD_FLG_RTS_MSK) { - tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_flags |= TX_CMD_FLG_CTS_MSK; - } - break; - default: - break; - } - } - - tx->rts_retry_limit = rts_retry_limit; - tx->data_retry_limit = data_retry_limit; - tx->rate = rate; - tx->tx_flags = tx_flags; - - /* OFDM */ - tx->supp_rates[0] = - ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF; - - /* CCK */ - tx->supp_rates[1] = (rate_mask & 0xF); - - IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X " - "cck/ofdm mask: 0x%x/0x%x\n", sta_id, - tx->rate, le32_to_cpu(tx->tx_flags), - tx->supp_rates[1], tx->supp_rates[0]); -} - -u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate, u8 flags) -{ - unsigned long flags_spin; - struct iwl_station_entry *station; - - if (sta_id == IWL_INVALID_STATION) - return IWL_INVALID_STATION; - - spin_lock_irqsave(&priv->sta_lock, flags_spin); - station = &priv->stations[sta_id]; - - station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK; - station->sta.rate_n_flags = cpu_to_le16(tx_rate); - station->sta.mode = STA_CONTROL_MODIFY_MSK; - - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - - iwl_send_add_sta(priv, &station->sta, flags); - IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n", - sta_id, tx_rate); - return sta_id; -} - -static int iwl3945_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) -{ - if (src == IWL_PWR_SRC_VAUX) { - if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - - iwl_poll_bit(priv, CSR_GPIO_IN, - CSR_GPIO_IN_VAL_VAUX_PWR_SRC, - CSR_GPIO_IN_BIT_AUX_POWER, 5000); - } - } else { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); - - iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC, - CSR_GPIO_IN_BIT_AUX_POWER, 5000); /* uS */ - } - - return 0; -} - -static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->dma_addr); - iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma); - iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0); - iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), - FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE | - FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE | - FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN | - FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 | - (RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) | - FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST | - (1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) | - FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH); - - /* fake read to flush all prev I/O */ - iwl_read_direct32(priv, FH39_RSSR_CTRL); - - return 0; -} - -static int iwl3945_tx_reset(struct iwl_priv *priv) -{ - - /* bypass mode */ - iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2); - - /* RA 0 is active */ - iwl_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01); - - /* all 6 fifo are active */ - iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f); - - iwl_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000); - iwl_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002); - iwl_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004); - iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005); - - iwl_write_direct32(priv, FH39_TSSR_CBB_BASE, - priv->shared_phys); - - iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG, - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON | - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON | - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B | - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON | - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON | - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH | - FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH); - - - return 0; -} - -/** - * iwl3945_txq_ctx_reset - Reset TX queue context - * - * Destroys all DMA structures and initialize them again - */ -static int iwl3945_txq_ctx_reset(struct iwl_priv *priv) -{ - int rc; - int txq_id, slots_num; - - iwl3945_hw_txq_ctx_free(priv); - - /* Tx CMD queue */ - rc = iwl3945_tx_reset(priv); - if (rc) - goto error; - - /* Tx queue(s) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? - TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, - txq_id); - if (rc) { - IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); - goto error; - } - } - - return rc; - - error: - iwl3945_hw_txq_ctx_free(priv); - return rc; -} - -static int iwl3945_apm_init(struct iwl_priv *priv) -{ - int ret; - - iwl_power_initialize(priv); - - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); - - /* set "initialization complete" bit to move adapter - * D0U* --> D0A* state */ - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (ret < 0) { - IWL_DEBUG_INFO(priv, "Failed to init the card\n"); - goto out; - } - - /* enable DMA */ - iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); - - udelay(20); - - /* disable L1-Active */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - -out: - return ret; -} - -static void iwl3945_nic_config(struct iwl_priv *priv) -{ - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - unsigned long flags; - u8 rev_id = 0; - - spin_lock_irqsave(&priv->lock, flags); - - /* Determine HW type */ - pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &rev_id); - - IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", rev_id); - - if (rev_id & PCI_CFG_REV_ID_BIT_RTP) - IWL_DEBUG_INFO(priv, "RTP type \n"); - else if (rev_id & PCI_CFG_REV_ID_BIT_BASIC_SKU) { - IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n"); - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BIT_3945_MB); - } else { - IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n"); - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BIT_3945_MM); - } - - if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) { - IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n"); - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC); - } else - IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n"); - - if ((eeprom->board_revision & 0xF0) == 0xD0) { - IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n", - eeprom->board_revision); - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); - } else { - IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n", - eeprom->board_revision); - iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE); - } - - if (eeprom->almgor_m_version <= 1) { - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A); - IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n", - eeprom->almgor_m_version); - } else { - IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n", - eeprom->almgor_m_version); - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B); - } - spin_unlock_irqrestore(&priv->lock, flags); - - if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE) - IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n"); - - if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE) - IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n"); -} - -int iwl3945_hw_nic_init(struct iwl_priv *priv) -{ - int rc; - unsigned long flags; - struct iwl_rx_queue *rxq = &priv->rxq; - - spin_lock_irqsave(&priv->lock, flags); - priv->cfg->ops->lib->apm_ops.init(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - rc = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); - if (rc) - return rc; - - priv->cfg->ops->lib->apm_ops.config(priv); - - /* Allocate the RX queue, or reset if it is already allocated */ - if (!rxq->bd) { - rc = iwl_rx_queue_alloc(priv); - if (rc) { - IWL_ERR(priv, "Unable to initialize Rx queue\n"); - return -ENOMEM; - } - } else - iwl3945_rx_queue_reset(priv, rxq); - - iwl3945_rx_replenish(priv); - - iwl3945_rx_init(priv, rxq); - - - /* Look at using this instead: - rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(priv, rxq); - */ - - iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7); - - rc = iwl3945_txq_ctx_reset(priv); - if (rc) - return rc; - - set_bit(STATUS_INIT, &priv->status); - - return 0; -} - -/** - * iwl3945_hw_txq_ctx_free - Free TXQ Context - * - * Destroy all TX DMA queues and structures - */ -void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv) -{ - int txq_id; - - /* Tx queues */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - if (txq_id == IWL_CMD_QUEUE_NUM) - iwl_cmd_queue_free(priv); - else - iwl_tx_queue_free(priv, txq_id); - -} - -void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv) -{ - int txq_id; - - /* stop SCD */ - iwl_write_prph(priv, ALM_SCD_MODE_REG, 0); - - /* reset TFD queues */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0); - iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS, - FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id), - 1000); - } - - iwl3945_hw_txq_ctx_free(priv); -} - -static int iwl3945_apm_stop_master(struct iwl_priv *priv) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - /* set stop master bit */ - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - - iwl_poll_direct_bit(priv, CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - - if (ret < 0) - goto out; - -out: - spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO(priv, "stop master\n"); - - return ret; -} - -static void iwl3945_apm_stop(struct iwl_priv *priv) -{ - unsigned long flags; - - iwl3945_apm_stop_master(priv); - - spin_lock_irqsave(&priv->lock, flags); - - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - - udelay(10); - /* clear "init complete" move adapter D0A* --> D0U state */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int iwl3945_apm_reset(struct iwl_priv *priv) -{ - iwl3945_apm_stop_master(priv); - - - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - udelay(10); - - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - - iwl_write_prph(priv, APMG_CLK_CTRL_REG, - APMG_CLK_VAL_BSM_CLK_RQT); - - iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0); - iwl_write_prph(priv, APMG_RTC_INT_STT_REG, - 0xFFFFFFFF); - - /* enable DMA */ - iwl_write_prph(priv, APMG_CLK_EN_REG, - APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); - udelay(10); - - iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); - udelay(5); - iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); - - /* Clear the 'host command active' bit... */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - - wake_up_interruptible(&priv->wait_command_queue); - - return 0; -} - -/** - * iwl3945_hw_reg_adjust_power_by_temp - * return index delta into power gain settings table -*/ -static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading) -{ - return (new_reading - old_reading) * (-11) / 100; -} - -/** - * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range - */ -static inline int iwl3945_hw_reg_temp_out_of_range(int temperature) -{ - return ((temperature < -260) || (temperature > 25)) ? 1 : 0; -} - -int iwl3945_hw_get_temperature(struct iwl_priv *priv) -{ - return iwl_read32(priv, CSR_UCODE_DRV_GP2); -} - -/** - * iwl3945_hw_reg_txpower_get_temperature - * get the current temperature by reading from NIC -*/ -static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv) -{ - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - int temperature; - - temperature = iwl3945_hw_get_temperature(priv); - - /* driver's okay range is -260 to +25. - * human readable okay range is 0 to +285 */ - IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT); - - /* handle insane temp reading */ - if (iwl3945_hw_reg_temp_out_of_range(temperature)) { - IWL_ERR(priv, "Error bad temperature value %d\n", temperature); - - /* if really really hot(?), - * substitute the 3rd band/group's temp measured at factory */ - if (priv->last_temperature > 100) - temperature = eeprom->groups[2].temperature; - else /* else use most recent "sane" value from driver */ - temperature = priv->last_temperature; - } - - return temperature; /* raw, not "human readable" */ -} - -/* Adjust Txpower only if temperature variance is greater than threshold. - * - * Both are lower than older versions' 9 degrees */ -#define IWL_TEMPERATURE_LIMIT_TIMER 6 - -/** - * is_temp_calib_needed - determines if new calibration is needed - * - * records new temperature in tx_mgr->temperature. - * replaces tx_mgr->last_temperature *only* if calib needed - * (assumes caller will actually do the calibration!). */ -static int is_temp_calib_needed(struct iwl_priv *priv) -{ - int temp_diff; - - priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv); - temp_diff = priv->temperature - priv->last_temperature; - - /* get absolute value */ - if (temp_diff < 0) { - IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff); - temp_diff = -temp_diff; - } else if (temp_diff == 0) - IWL_DEBUG_POWER(priv, "Same temp,\n"); - else - IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff); - - /* if we don't need calibration, *don't* update last_temperature */ - if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) { - IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n"); - return 0; - } - - IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n"); - - /* assume that caller will actually do calib ... - * update the "last temperature" value */ - priv->last_temperature = priv->temperature; - return 1; -} - -#define IWL_MAX_GAIN_ENTRIES 78 -#define IWL_CCK_FROM_OFDM_POWER_DIFF -5 -#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10) - -/* radio and DSP power table, each step is 1/2 dB. - * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */ -static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = { - { - {251, 127}, /* 2.4 GHz, highest power */ - {251, 127}, - {251, 127}, - {251, 127}, - {251, 125}, - {251, 110}, - {251, 105}, - {251, 98}, - {187, 125}, - {187, 115}, - {187, 108}, - {187, 99}, - {243, 119}, - {243, 111}, - {243, 105}, - {243, 97}, - {243, 92}, - {211, 106}, - {211, 100}, - {179, 120}, - {179, 113}, - {179, 107}, - {147, 125}, - {147, 119}, - {147, 112}, - {147, 106}, - {147, 101}, - {147, 97}, - {147, 91}, - {115, 107}, - {235, 121}, - {235, 115}, - {235, 109}, - {203, 127}, - {203, 121}, - {203, 115}, - {203, 108}, - {203, 102}, - {203, 96}, - {203, 92}, - {171, 110}, - {171, 104}, - {171, 98}, - {139, 116}, - {227, 125}, - {227, 119}, - {227, 113}, - {227, 107}, - {227, 101}, - {227, 96}, - {195, 113}, - {195, 106}, - {195, 102}, - {195, 95}, - {163, 113}, - {163, 106}, - {163, 102}, - {163, 95}, - {131, 113}, - {131, 106}, - {131, 102}, - {131, 95}, - {99, 113}, - {99, 106}, - {99, 102}, - {99, 95}, - {67, 113}, - {67, 106}, - {67, 102}, - {67, 95}, - {35, 113}, - {35, 106}, - {35, 102}, - {35, 95}, - {3, 113}, - {3, 106}, - {3, 102}, - {3, 95} }, /* 2.4 GHz, lowest power */ - { - {251, 127}, /* 5.x GHz, highest power */ - {251, 120}, - {251, 114}, - {219, 119}, - {219, 101}, - {187, 113}, - {187, 102}, - {155, 114}, - {155, 103}, - {123, 117}, - {123, 107}, - {123, 99}, - {123, 92}, - {91, 108}, - {59, 125}, - {59, 118}, - {59, 109}, - {59, 102}, - {59, 96}, - {59, 90}, - {27, 104}, - {27, 98}, - {27, 92}, - {115, 118}, - {115, 111}, - {115, 104}, - {83, 126}, - {83, 121}, - {83, 113}, - {83, 105}, - {83, 99}, - {51, 118}, - {51, 111}, - {51, 104}, - {51, 98}, - {19, 116}, - {19, 109}, - {19, 102}, - {19, 98}, - {19, 93}, - {171, 113}, - {171, 107}, - {171, 99}, - {139, 120}, - {139, 113}, - {139, 107}, - {139, 99}, - {107, 120}, - {107, 113}, - {107, 107}, - {107, 99}, - {75, 120}, - {75, 113}, - {75, 107}, - {75, 99}, - {43, 120}, - {43, 113}, - {43, 107}, - {43, 99}, - {11, 120}, - {11, 113}, - {11, 107}, - {11, 99}, - {131, 107}, - {131, 99}, - {99, 120}, - {99, 113}, - {99, 107}, - {99, 99}, - {67, 120}, - {67, 113}, - {67, 107}, - {67, 99}, - {35, 120}, - {35, 113}, - {35, 107}, - {35, 99}, - {3, 120} } /* 5.x GHz, lowest power */ -}; - -static inline u8 iwl3945_hw_reg_fix_power_index(int index) -{ - if (index < 0) - return 0; - if (index >= IWL_MAX_GAIN_ENTRIES) - return IWL_MAX_GAIN_ENTRIES - 1; - return (u8) index; -} - -/* Kick off thermal recalibration check every 60 seconds */ -#define REG_RECALIB_PERIOD (60) - -/** - * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests - * - * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK) - * or 6 Mbit (OFDM) rates. - */ -static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index, - s32 rate_index, const s8 *clip_pwrs, - struct iwl_channel_info *ch_info, - int band_index) -{ - struct iwl3945_scan_power_info *scan_power_info; - s8 power; - u8 power_index; - - scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index]; - - /* use this channel group's 6Mbit clipping/saturation pwr, - * but cap at regulatory scan power restriction (set during init - * based on eeprom channel data) for this channel. */ - power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]); - - /* further limit to user's max power preference. - * FIXME: Other spectrum management power limitations do not - * seem to apply?? */ - power = min(power, priv->tx_power_user_lmt); - scan_power_info->requested_power = power; - - /* find difference between new scan *power* and current "normal" - * Tx *power* for 6Mb. Use this difference (x2) to adjust the - * current "normal" temperature-compensated Tx power *index* for - * this rate (1Mb or 6Mb) to yield new temp-compensated scan power - * *index*. */ - power_index = ch_info->power_info[rate_index].power_table_index - - (power - ch_info->power_info - [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2; - - /* store reference index that we use when adjusting *all* scan - * powers. So we can accommodate user (all channel) or spectrum - * management (single channel) power changes "between" temperature - * feedback compensation procedures. - * don't force fit this reference index into gain table; it may be a - * negative number. This will help avoid errors when we're at - * the lower bounds (highest gains, for warmest temperatures) - * of the table. */ - - /* don't exceed table bounds for "real" setting */ - power_index = iwl3945_hw_reg_fix_power_index(power_index); - - scan_power_info->power_table_index = power_index; - scan_power_info->tpc.tx_gain = - power_gain_table[band_index][power_index].tx_gain; - scan_power_info->tpc.dsp_atten = - power_gain_table[band_index][power_index].dsp_atten; -} - -/** - * iwl3945_send_tx_power - fill in Tx Power command with gain settings - * - * Configures power settings for all rates for the current channel, - * using values from channel info struct, and send to NIC - */ -static int iwl3945_send_tx_power(struct iwl_priv *priv) -{ - int rate_idx, i; - const struct iwl_channel_info *ch_info = NULL; - struct iwl3945_txpowertable_cmd txpower = { - .channel = priv->active_rxon.channel, - }; - - txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1; - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->active_rxon.channel)); - if (!ch_info) { - IWL_ERR(priv, - "Failed to get channel info for channel %d [%d]\n", - le16_to_cpu(priv->active_rxon.channel), priv->band); - return -EINVAL; - } - - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on " - "non-Tx channel.\n"); - return 0; - } - - /* fill cmd with power settings for all rates for current channel */ - /* Fill OFDM rate */ - for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0; - rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) { - - txpower.power[i].tpc = ch_info->power_info[i].tpc; - txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; - - IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n", - le16_to_cpu(txpower.channel), - txpower.band, - txpower.power[i].tpc.tx_gain, - txpower.power[i].tpc.dsp_atten, - txpower.power[i].rate); - } - /* Fill CCK rates */ - for (rate_idx = IWL_FIRST_CCK_RATE; - rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) { - txpower.power[i].tpc = ch_info->power_info[i].tpc; - txpower.power[i].rate = iwl3945_rates[rate_idx].plcp; - - IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n", - le16_to_cpu(txpower.channel), - txpower.band, - txpower.power[i].tpc.tx_gain, - txpower.power[i].tpc.dsp_atten, - txpower.power[i].rate); - } - - return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, - sizeof(struct iwl3945_txpowertable_cmd), - &txpower); - -} - -/** - * iwl3945_hw_reg_set_new_power - Configures power tables at new levels - * @ch_info: Channel to update. Uses power_info.requested_power. - * - * Replace requested_power and base_power_index ch_info fields for - * one channel. - * - * Called if user or spectrum management changes power preferences. - * Takes into account h/w and modulation limitations (clip power). - * - * This does *not* send anything to NIC, just sets up ch_info for one channel. - * - * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to - * properly fill out the scan powers, and actual h/w gain settings, - * and send changes to NIC - */ -static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv, - struct iwl_channel_info *ch_info) -{ - struct iwl3945_channel_power_info *power_info; - int power_changed = 0; - int i; - const s8 *clip_pwrs; - int power; - - /* Get this chnlgrp's rate-to-max/clip-powers table */ - clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; - - /* Get this channel's rate-to-current-power settings table */ - power_info = ch_info->power_info; - - /* update OFDM Txpower settings */ - for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE; - i++, ++power_info) { - int delta_idx; - - /* limit new power to be no more than h/w capability */ - power = min(ch_info->curr_txpow, clip_pwrs[i]); - if (power == power_info->requested_power) - continue; - - /* find difference between old and new requested powers, - * update base (non-temp-compensated) power index */ - delta_idx = (power - power_info->requested_power) * 2; - power_info->base_power_index -= delta_idx; - - /* save new requested power value */ - power_info->requested_power = power; - - power_changed = 1; - } - - /* update CCK Txpower settings, based on OFDM 12M setting ... - * ... all CCK power settings for a given channel are the *same*. */ - if (power_changed) { - power = - ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. - requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF; - - /* do all CCK rates' iwl3945_channel_power_info structures */ - for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) { - power_info->requested_power = power; - power_info->base_power_index = - ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]. - base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF; - ++power_info; - } - } - - return 0; -} - -/** - * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel - * - * NOTE: Returned power limit may be less (but not more) than requested, - * based strictly on regulatory (eeprom and spectrum mgt) limitations - * (no consideration for h/w clipping limitations). - */ -static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info) -{ - s8 max_power; - -#if 0 - /* if we're using TGd limits, use lower of TGd or EEPROM */ - if (ch_info->tgd_data.max_power != 0) - max_power = min(ch_info->tgd_data.max_power, - ch_info->eeprom.max_power_avg); - - /* else just use EEPROM limits */ - else -#endif - max_power = ch_info->eeprom.max_power_avg; - - return min(max_power, ch_info->max_power_avg); -} - -/** - * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature - * - * Compensate txpower settings of *all* channels for temperature. - * This only accounts for the difference between current temperature - * and the factory calibration temperatures, and bases the new settings - * on the channel's base_power_index. - * - * If RxOn is "associated", this sends the new Txpower to NIC! - */ -static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv) -{ - struct iwl_channel_info *ch_info = NULL; - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - int delta_index; - const s8 *clip_pwrs; /* array of h/w max power levels for each rate */ - u8 a_band; - u8 rate_index; - u8 scan_tbl_index; - u8 i; - int ref_temp; - int temperature = priv->temperature; - - /* set up new Tx power info for each and every channel, 2.4 and 5.x */ - for (i = 0; i < priv->channel_count; i++) { - ch_info = &priv->channel_info[i]; - a_band = is_channel_a_band(ch_info); - - /* Get this chnlgrp's factory calibration temperature */ - ref_temp = (s16)eeprom->groups[ch_info->group_index]. - temperature; - - /* get power index adjustment based on current and factory - * temps */ - delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature, - ref_temp); - - /* set tx power value for all rates, OFDM and CCK */ - for (rate_index = 0; rate_index < IWL_RATE_COUNT; - rate_index++) { - int power_idx = - ch_info->power_info[rate_index].base_power_index; - - /* temperature compensate */ - power_idx += delta_index; - - /* stay within table range */ - power_idx = iwl3945_hw_reg_fix_power_index(power_idx); - ch_info->power_info[rate_index]. - power_table_index = (u8) power_idx; - ch_info->power_info[rate_index].tpc = - power_gain_table[a_band][power_idx]; - } - - /* Get this chnlgrp's rate-to-max/clip-powers table */ - clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; - - /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ - for (scan_tbl_index = 0; - scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { - s32 actual_index = (scan_tbl_index == 0) ? - IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; - iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index, - actual_index, clip_pwrs, - ch_info, a_band); - } - } - - /* send Txpower command for current channel to ucode */ - return priv->cfg->ops->lib->send_tx_power(priv); -} - -int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power) -{ - struct iwl_channel_info *ch_info; - s8 max_power; - u8 a_band; - u8 i; - - if (priv->tx_power_user_lmt == power) { - IWL_DEBUG_POWER(priv, "Requested Tx power same as current " - "limit: %ddBm.\n", power); - return 0; - } - - IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power); - priv->tx_power_user_lmt = power; - - /* set up new Tx powers for each and every channel, 2.4 and 5.x */ - - for (i = 0; i < priv->channel_count; i++) { - ch_info = &priv->channel_info[i]; - a_band = is_channel_a_band(ch_info); - - /* find minimum power of all user and regulatory constraints - * (does not consider h/w clipping limitations) */ - max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info); - max_power = min(power, max_power); - if (max_power != ch_info->curr_txpow) { - ch_info->curr_txpow = max_power; - - /* this considers the h/w clipping limitations */ - iwl3945_hw_reg_set_new_power(priv, ch_info); - } - } - - /* update txpower settings for all channels, - * send to NIC if associated. */ - is_temp_calib_needed(priv); - iwl3945_hw_reg_comp_txpower_temp(priv); - - return 0; -} - -static int iwl3945_send_rxon_assoc(struct iwl_priv *priv) -{ - int rc = 0; - struct iwl_rx_packet *res = NULL; - struct iwl3945_rxon_assoc_cmd rxon_assoc; - struct iwl_host_cmd cmd = { - .id = REPLY_RXON_ASSOC, - .len = sizeof(rxon_assoc), - .flags = CMD_WANT_SKB, - .data = &rxon_assoc, - }; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved = 0; - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl_rx_packet *)cmd.reply_skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n"); - rc = -EIO; - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.reply_skb); - - return rc; -} - -/** - * iwl3945_commit_rxon - commit staging_rxon to hardware - * - * The RXON command in staging_rxon is committed to the hardware and - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. - */ -static int iwl3945_commit_rxon(struct iwl_priv *priv) -{ - /* cast away the const for active_rxon in this function */ - struct iwl3945_rxon_cmd *active_rxon = (void *)&priv->active_rxon; - struct iwl3945_rxon_cmd *staging_rxon = (void *)&priv->staging_rxon; - int rc = 0; - bool new_assoc = - !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); - - if (!iwl_is_alive(priv)) - return -1; - - /* always get timestamp with Rx frame */ - staging_rxon->flags |= RXON_FLG_TSF2HOST_MSK; - - /* select antenna */ - staging_rxon->flags &= - ~(RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_SEL_MSK); - staging_rxon->flags |= iwl3945_get_antenna_flags(priv); - - rc = iwl_check_rxon_cmd(priv); - if (rc) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); - return -EINVAL; - } - - /* If we don't need to send a full RXON, we can use - * iwl3945_rxon_assoc_cmd which is used to reconfigure filter - * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv)) { - rc = iwl_send_rxon_assoc(priv); - if (rc) { - IWL_ERR(priv, "Error setting RXON_ASSOC " - "configuration (%d).\n", rc); - return rc; - } - - memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - - return 0; - } - - /* If we are currently associated and the new config requires - * an RXON_ASSOC and the new config wants the associated mask enabled, - * we must clear the associated from the active configuration - * before we apply the new config */ - if (iwl_is_associated(priv) && new_assoc) { - IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - - /* - * reserved4 and 5 could have been filled by the iwlcore code. - * Let's clear them before pushing to the 3945. - */ - active_rxon->reserved4 = 0; - active_rxon->reserved5 = 0; - rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), - &priv->active_rxon); - - /* If the mask clearing failed then we set - * active_rxon back to what it was previously */ - if (rc) { - active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERR(priv, "Error clearing ASSOC_MSK on current " - "configuration (%d).\n", rc); - return rc; - } - } - - IWL_DEBUG_INFO(priv, "Sending RXON\n" - "* with%s RXON_FILTER_ASSOC_MSK\n" - "* channel = %d\n" - "* bssid = %pM\n", - (new_assoc ? "" : "out"), - le16_to_cpu(staging_rxon->channel), - staging_rxon->bssid_addr); - - /* - * reserved4 and 5 could have been filled by the iwlcore code. - * Let's clear them before pushing to the 3945. - */ - staging_rxon->reserved4 = 0; - staging_rxon->reserved5 = 0; - - iwl_set_rxon_hwcrypto(priv, !iwl3945_mod_params.sw_crypto); - - /* Apply the new configuration */ - rc = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl3945_rxon_cmd), - staging_rxon); - if (rc) { - IWL_ERR(priv, "Error setting new configuration (%d).\n", rc); - return rc; - } - - memcpy(active_rxon, staging_rxon, sizeof(*active_rxon)); - - iwl_clear_stations_table(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - rc = priv->cfg->ops->lib->send_tx_power(priv); - if (rc) { - IWL_ERR(priv, "Error setting Tx power (%d).\n", rc); - return rc; - } - - /* Add the broadcast address so we can send broadcast frames */ - if (iwl_add_station(priv, iwl_bcast_addr, false, CMD_SYNC, NULL) == - IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); - return -EIO; - } - - /* If we have set the ASSOC_MSK and we are in BSS mode then - * add the IWL_AP_ID to the station rate table */ - if (iwl_is_associated(priv) && - (priv->iw_mode == NL80211_IFTYPE_STATION)) - if (iwl_add_station(priv, priv->active_rxon.bssid_addr, - true, CMD_SYNC, NULL) == IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding AP address for transmit\n"); - return -EIO; - } - - /* Init the hardware's rate fallback order based on the band */ - rc = iwl3945_init_hw_rate_table(priv); - if (rc) { - IWL_ERR(priv, "Error setting HW rate table: %02X\n", rc); - return -EIO; - } - - return 0; -} - -/* will add 3945 channel switch cmd handling later */ -int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel) -{ - return 0; -} - -/** - * iwl3945_reg_txpower_periodic - called when time to check our temperature. - * - * -- reset periodic timer - * -- see if temp has changed enough to warrant re-calibration ... if so: - * -- correct coeffs for temp (can reset temp timer) - * -- save this temp as "last", - * -- send new set of gain settings to NIC - * NOTE: This should continue working, even when we're not associated, - * so we can keep our internal table of scan powers current. */ -void iwl3945_reg_txpower_periodic(struct iwl_priv *priv) -{ - /* This will kick in the "brute force" - * iwl3945_hw_reg_comp_txpower_temp() below */ - if (!is_temp_calib_needed(priv)) - goto reschedule; - - /* Set up a new set of temp-adjusted TxPowers, send to NIC. - * This is based *only* on current temperature, - * ignoring any previous power measurements */ - iwl3945_hw_reg_comp_txpower_temp(priv); - - reschedule: - queue_delayed_work(priv->workqueue, - &priv->thermal_periodic, REG_RECALIB_PERIOD * HZ); -} - -static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, - thermal_periodic.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - iwl3945_reg_txpower_periodic(priv); - mutex_unlock(&priv->mutex); -} - -/** - * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4) - * for the channel. - * - * This function is used when initializing channel-info structs. - * - * NOTE: These channel groups do *NOT* match the bands above! - * These channel groups are based on factory-tested channels; - * on A-band, EEPROM's "group frequency" entries represent the top - * channel in each group 1-4. Group 5 All B/G channels are in group 0. - */ -static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv, - const struct iwl_channel_info *ch_info) -{ - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0]; - u8 group; - u16 group_index = 0; /* based on factory calib frequencies */ - u8 grp_channel; - - /* Find the group index for the channel ... don't use index 1(?) */ - if (is_channel_a_band(ch_info)) { - for (group = 1; group < 5; group++) { - grp_channel = ch_grp[group].group_channel; - if (ch_info->channel <= grp_channel) { - group_index = group; - break; - } - } - /* group 4 has a few channels *above* its factory cal freq */ - if (group == 5) - group_index = 4; - } else - group_index = 0; /* 2.4 GHz, group 0 */ - - IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel, - group_index); - return group_index; -} - -/** - * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index - * - * Interpolate to get nominal (i.e. at factory calibration temperature) index - * into radio/DSP gain settings table for requested power. - */ -static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv, - s8 requested_power, - s32 setting_index, s32 *new_index) -{ - const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL; - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - s32 index0, index1; - s32 power = 2 * requested_power; - s32 i; - const struct iwl3945_eeprom_txpower_sample *samples; - s32 gains0, gains1; - s32 res; - s32 denominator; - - chnl_grp = &eeprom->groups[setting_index]; - samples = chnl_grp->samples; - for (i = 0; i < 5; i++) { - if (power == samples[i].power) { - *new_index = samples[i].gain_index; - return 0; - } - } - - if (power > samples[1].power) { - index0 = 0; - index1 = 1; - } else if (power > samples[2].power) { - index0 = 1; - index1 = 2; - } else if (power > samples[3].power) { - index0 = 2; - index1 = 3; - } else { - index0 = 3; - index1 = 4; - } - - denominator = (s32) samples[index1].power - (s32) samples[index0].power; - if (denominator == 0) - return -EINVAL; - gains0 = (s32) samples[index0].gain_index * (1 << 19); - gains1 = (s32) samples[index1].gain_index * (1 << 19); - res = gains0 + (gains1 - gains0) * - ((s32) power - (s32) samples[index0].power) / denominator + - (1 << 18); - *new_index = res >> 19; - return 0; -} - -static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv) -{ - u32 i; - s32 rate_index; - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - const struct iwl3945_eeprom_txpower_group *group; - - IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n"); - - for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) { - s8 *clip_pwrs; /* table of power levels for each rate */ - s8 satur_pwr; /* saturation power for each chnl group */ - group = &eeprom->groups[i]; - - /* sanity check on factory saturation power value */ - if (group->saturation_power < 40) { - IWL_WARN(priv, "Error: saturation power is %d, " - "less than minimum expected 40\n", - group->saturation_power); - return; - } - - /* - * Derive requested power levels for each rate, based on - * hardware capabilities (saturation power for band). - * Basic value is 3dB down from saturation, with further - * power reductions for highest 3 data rates. These - * backoffs provide headroom for high rate modulation - * power peaks, without too much distortion (clipping). - */ - /* we'll fill in this array with h/w max power levels */ - clip_pwrs = (s8 *) priv->clip39_groups[i].clip_powers; - - /* divide factory saturation power by 2 to find -3dB level */ - satur_pwr = (s8) (group->saturation_power >> 1); - - /* fill in channel group's nominal powers for each rate */ - for (rate_index = 0; - rate_index < IWL_RATE_COUNT; rate_index++, clip_pwrs++) { - switch (rate_index) { - case IWL_RATE_36M_INDEX_TABLE: - if (i == 0) /* B/G */ - *clip_pwrs = satur_pwr; - else /* A */ - *clip_pwrs = satur_pwr - 5; - break; - case IWL_RATE_48M_INDEX_TABLE: - if (i == 0) - *clip_pwrs = satur_pwr - 7; - else - *clip_pwrs = satur_pwr - 10; - break; - case IWL_RATE_54M_INDEX_TABLE: - if (i == 0) - *clip_pwrs = satur_pwr - 9; - else - *clip_pwrs = satur_pwr - 12; - break; - default: - *clip_pwrs = satur_pwr; - break; - } - } - } -} - -/** - * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM - * - * Second pass (during init) to set up priv->channel_info - * - * Set up Tx-power settings in our channel info database for each VALID - * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values - * and current temperature. - * - * Since this is based on current temperature (at init time), these values may - * not be valid for very long, but it gives us a starting/default point, - * and allows us to active (i.e. using Tx) scan. - * - * This does *not* write values to NIC, just sets up our internal table. - */ -int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv) -{ - struct iwl_channel_info *ch_info = NULL; - struct iwl3945_channel_power_info *pwr_info; - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - int delta_index; - u8 rate_index; - u8 scan_tbl_index; - const s8 *clip_pwrs; /* array of power levels for each rate */ - u8 gain, dsp_atten; - s8 power; - u8 pwr_index, base_pwr_index, a_band; - u8 i; - int temperature; - - /* save temperature reference, - * so we can determine next time to calibrate */ - temperature = iwl3945_hw_reg_txpower_get_temperature(priv); - priv->last_temperature = temperature; - - iwl3945_hw_reg_init_channel_groups(priv); - - /* initialize Tx power info for each and every channel, 2.4 and 5.x */ - for (i = 0, ch_info = priv->channel_info; i < priv->channel_count; - i++, ch_info++) { - a_band = is_channel_a_band(ch_info); - if (!is_channel_valid(ch_info)) - continue; - - /* find this channel's channel group (*not* "band") index */ - ch_info->group_index = - iwl3945_hw_reg_get_ch_grp_index(priv, ch_info); - - /* Get this chnlgrp's rate->max/clip-powers table */ - clip_pwrs = priv->clip39_groups[ch_info->group_index].clip_powers; - - /* calculate power index *adjustment* value according to - * diff between current temperature and factory temperature */ - delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature, - eeprom->groups[ch_info->group_index]. - temperature); - - IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n", - ch_info->channel, delta_index, temperature + - IWL_TEMP_CONVERT); - - /* set tx power value for all OFDM rates */ - for (rate_index = 0; rate_index < IWL_OFDM_RATES; - rate_index++) { - s32 uninitialized_var(power_idx); - int rc; - - /* use channel group's clip-power table, - * but don't exceed channel's max power */ - s8 pwr = min(ch_info->max_power_avg, - clip_pwrs[rate_index]); - - pwr_info = &ch_info->power_info[rate_index]; - - /* get base (i.e. at factory-measured temperature) - * power table index for this rate's power */ - rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr, - ch_info->group_index, - &power_idx); - if (rc) { - IWL_ERR(priv, "Invalid power index\n"); - return rc; - } - pwr_info->base_power_index = (u8) power_idx; - - /* temperature compensate */ - power_idx += delta_index; - - /* stay within range of gain table */ - power_idx = iwl3945_hw_reg_fix_power_index(power_idx); - - /* fill 1 OFDM rate's iwl3945_channel_power_info struct */ - pwr_info->requested_power = pwr; - pwr_info->power_table_index = (u8) power_idx; - pwr_info->tpc.tx_gain = - power_gain_table[a_band][power_idx].tx_gain; - pwr_info->tpc.dsp_atten = - power_gain_table[a_band][power_idx].dsp_atten; - } - - /* set tx power for CCK rates, based on OFDM 12 Mbit settings*/ - pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE]; - power = pwr_info->requested_power + - IWL_CCK_FROM_OFDM_POWER_DIFF; - pwr_index = pwr_info->power_table_index + - IWL_CCK_FROM_OFDM_INDEX_DIFF; - base_pwr_index = pwr_info->base_power_index + - IWL_CCK_FROM_OFDM_INDEX_DIFF; - - /* stay within table range */ - pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index); - gain = power_gain_table[a_band][pwr_index].tx_gain; - dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten; - - /* fill each CCK rate's iwl3945_channel_power_info structure - * NOTE: All CCK-rate Txpwrs are the same for a given chnl! - * NOTE: CCK rates start at end of OFDM rates! */ - for (rate_index = 0; - rate_index < IWL_CCK_RATES; rate_index++) { - pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES]; - pwr_info->requested_power = power; - pwr_info->power_table_index = pwr_index; - pwr_info->base_power_index = base_pwr_index; - pwr_info->tpc.tx_gain = gain; - pwr_info->tpc.dsp_atten = dsp_atten; - } - - /* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */ - for (scan_tbl_index = 0; - scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) { - s32 actual_index = (scan_tbl_index == 0) ? - IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE; - iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index, - actual_index, clip_pwrs, ch_info, a_band); - } - } - - return 0; -} - -int iwl3945_hw_rxq_stop(struct iwl_priv *priv) -{ - int rc; - - iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0); - rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS, - FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); - if (rc < 0) - IWL_ERR(priv, "Can't stop Rx DMA.\n"); - - return 0; -} - -int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - int txq_id = txq->q.id; - - struct iwl3945_shared *shared_data = priv->shared_virt; - - shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr); - - iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0); - iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0); - - iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), - FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT | - FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF | - FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD | - FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL | - FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE); - - /* fake read to flush all prev. writes */ - iwl_read32(priv, FH39_TSSR_CBB_BASE); - - return 0; -} - -/* - * HCMD utils - */ -static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len) -{ - switch (cmd_id) { - case REPLY_RXON: - return sizeof(struct iwl3945_rxon_cmd); - case POWER_TABLE_CMD: - return sizeof(struct iwl3945_powertable_cmd); - default: - return len; - } -} - - -static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) -{ - struct iwl3945_addsta_cmd *addsta = (struct iwl3945_addsta_cmd *)data; - addsta->mode = cmd->mode; - memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify)); - memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo)); - addsta->station_flags = cmd->station_flags; - addsta->station_flags_msk = cmd->station_flags_msk; - addsta->tid_disable_tx = cpu_to_le16(0); - addsta->rate_n_flags = cmd->rate_n_flags; - addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; - addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; - addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; - - return (u16)sizeof(struct iwl3945_addsta_cmd); -} - - -/** - * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table - */ -int iwl3945_init_hw_rate_table(struct iwl_priv *priv) -{ - int rc, i, index, prev_index; - struct iwl3945_rate_scaling_cmd rate_cmd = { - .reserved = {0, 0, 0}, - }; - struct iwl3945_rate_scaling_info *table = rate_cmd.table; - - for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) { - index = iwl3945_rates[i].table_rs_index; - - table[index].rate_n_flags = - iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0); - table[index].try_cnt = priv->retry_rate; - prev_index = iwl3945_get_prev_ieee_rate(i); - table[index].next_rate_index = - iwl3945_rates[prev_index].table_rs_index; - } - - switch (priv->band) { - case IEEE80211_BAND_5GHZ: - IWL_DEBUG_RATE(priv, "Select A mode rate scale\n"); - /* If one of the following CCK rates is used, - * have it fall back to the 6M OFDM rate */ - for (i = IWL_RATE_1M_INDEX_TABLE; - i <= IWL_RATE_11M_INDEX_TABLE; i++) - table[i].next_rate_index = - iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index; - - /* Don't fall back to CCK rates */ - table[IWL_RATE_12M_INDEX_TABLE].next_rate_index = - IWL_RATE_9M_INDEX_TABLE; - - /* Don't drop out of OFDM rates */ - table[IWL_RATE_6M_INDEX_TABLE].next_rate_index = - iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index; - break; - - case IEEE80211_BAND_2GHZ: - IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n"); - /* If an OFDM rate is used, have it fall back to the - * 1M CCK rates */ - - if (!(priv->sta_supp_rates & IWL_OFDM_RATES_MASK) && - iwl_is_associated(priv)) { - - index = IWL_FIRST_CCK_RATE; - for (i = IWL_RATE_6M_INDEX_TABLE; - i <= IWL_RATE_54M_INDEX_TABLE; i++) - table[i].next_rate_index = - iwl3945_rates[index].table_rs_index; - - index = IWL_RATE_11M_INDEX_TABLE; - /* CCK shouldn't fall back to OFDM... */ - table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE; - } - break; - - default: - WARN_ON(1); - break; - } - - /* Update the rate scaling for control frame Tx */ - rate_cmd.table_id = 0; - rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), - &rate_cmd); - if (rc) - return rc; - - /* Update the rate scaling for data frame Tx */ - rate_cmd.table_id = 1; - return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd), - &rate_cmd); -} - -/* Called when initializing driver */ -int iwl3945_hw_set_hw_params(struct iwl_priv *priv) -{ - memset((void *)&priv->hw_params, 0, - sizeof(struct iwl_hw_params)); - - priv->shared_virt = dma_alloc_coherent(&priv->pci_dev->dev, - sizeof(struct iwl3945_shared), - &priv->shared_phys, GFP_KERNEL); - if (!priv->shared_virt) { - IWL_ERR(priv, "failed to allocate pci memory\n"); - mutex_unlock(&priv->mutex); - return -ENOMEM; - } - - /* Assign number of Usable TX queues */ - priv->hw_params.max_txq_num = IWL39_NUM_QUEUES; - - priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd); - priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K; - priv->hw_params.max_pkt_size = 2342; - priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; - priv->hw_params.max_stations = IWL3945_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWL3945_BROADCAST_ID; - - priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR; - priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL; - - return 0; -} - -unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl3945_frame *frame, u8 rate) -{ - struct iwl3945_tx_beacon_cmd *tx_beacon_cmd; - unsigned int frame_size; - - tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u; - memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; - tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - frame_size = iwl3945_fill_beacon_frame(priv, - tx_beacon_cmd->frame, - sizeof(frame->u) - sizeof(*tx_beacon_cmd)); - - BUG_ON(frame_size > MAX_MPDU_SIZE); - tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); - - tx_beacon_cmd->tx.rate = rate; - tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK | - TX_CMD_FLG_TSF_MSK); - - /* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/ - tx_beacon_cmd->tx.supp_rates[0] = - (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; - - tx_beacon_cmd->tx.supp_rates[1] = - (IWL_CCK_BASIC_RATES_MASK & 0xF); - - return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size; -} - -void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv) -{ - priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx; - priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx; -} - -void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv) -{ - INIT_DELAYED_WORK(&priv->thermal_periodic, - iwl3945_bg_reg_txpower_periodic); -} - -void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv) -{ - cancel_delayed_work(&priv->thermal_periodic); -} - -/* check contents of special bootstrap uCode SRAM */ -static int iwl3945_verify_bsm(struct iwl_priv *priv) - { - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - u32 reg; - u32 val; - - IWL_DEBUG_INFO(priv, "Begin verify bsm\n"); - - /* verify BSM SRAM contents */ - val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); - for (reg = BSM_SRAM_LOWER_BOUND; - reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image++) { - val = iwl_read_prph(priv, reg); - if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "BSM uCode verification failed at " - "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", - BSM_SRAM_LOWER_BOUND, - reg - BSM_SRAM_LOWER_BOUND, len, - val, le32_to_cpu(*image)); - return -EIO; - } - } - - IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n"); - - return 0; -} - - -/****************************************************************************** - * - * EEPROM related functions - * - ******************************************************************************/ - -/* - * Clear the OWNER_MSK, to establish driver (instead of uCode running on - * embedded controller) as EEPROM reader; each read is a series of pulses - * to/from the EEPROM chip, not a single event, so even reads could conflict - * if they weren't arbitrated by some ownership mechanism. Here, the driver - * simply claims ownership, which should be safe when this function is called - * (i.e. before loading uCode!). - */ -static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv) -{ - _iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK); - return 0; -} - - -static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv) -{ - return; -} - - /** - * iwl3945_load_bsm - Load bootstrap instructions - * - * BSM operation: - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down during RFKILL. When powering back - * up after power-saving sleeps (or during initial uCode load), the BSM loads - * the bootstrap program into the on-board processor, and starts it. - * - * The bootstrap program loads (via DMA) instructions and data for a new - * program from host DRAM locations indicated by the host driver in the - * BSM_DRAM_* registers. Once the new program is loaded, it starts - * automatically. - * - * When initializing the NIC, the host driver points the BSM to the - * "initialize" uCode image. This uCode sets up some internal data, then - * notifies host via "initialize alive" that it is complete. - * - * The host then replaces the BSM_DRAM_* pointer values to point to the - * normal runtime uCode instructions and a backup uCode data cache buffer - * (filled initially with starting data values for the on-board processor), - * then triggers the "initialize" uCode to load and launch the runtime uCode, - * which begins normal operation. - * - * When doing a power-save shutdown, runtime uCode saves data SRAM into - * the backup data cache in DRAM before SRAM is powered down. - * - * When powering back up, the BSM loads the bootstrap program. This reloads - * the runtime uCode instructions and the backup data cache into SRAM, - * and re-launches the runtime uCode from where it left off. - */ -static int iwl3945_load_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - dma_addr_t pinst; - dma_addr_t pdata; - u32 inst_len; - u32 data_len; - int rc; - int i; - u32 done; - u32 reg_offset; - - IWL_DEBUG_INFO(priv, "Begin load bsm\n"); - - /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL39_MAX_BSM_SIZE) - return -EINVAL; - - /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... host DRAM physical address bits 31:0 for 3945. - * NOTE: iwl3945_initialize_alive_start() will replace these values, - * after the "initialize" uCode has run, to point to - * runtime/protocol instructions and backup data cache. */ - pinst = priv->ucode_init.p_addr; - pdata = priv->ucode_init_data.p_addr; - inst_len = priv->ucode_init.len; - data_len = priv->ucode_init_data.len; - - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); - - /* Fill BSM memory with bootstrap instructions */ - for (reg_offset = BSM_SRAM_LOWER_BOUND; - reg_offset < BSM_SRAM_LOWER_BOUND + len; - reg_offset += sizeof(u32), image++) - _iwl_write_prph(priv, reg_offset, - le32_to_cpu(*image)); - - rc = iwl3945_verify_bsm(priv); - if (rc) - return rc; - - /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl_write_prph(priv, BSM_WR_MEM_DST_REG, - IWL39_RTC_INST_LOWER_BOUND); - iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); - - /* Load bootstrap code into instruction SRAM now, - * to prepare to load "initialize" uCode */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, - BSM_WR_CTRL_REG_BIT_START); - - /* Wait for load of bootstrap uCode to finish */ - for (i = 0; i < 100; i++) { - done = iwl_read_prph(priv, BSM_WR_CTRL_REG); - if (!(done & BSM_WR_CTRL_REG_BIT_START)) - break; - udelay(10); - } - if (i < 100) - IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i); - else { - IWL_ERR(priv, "BSM write did not complete!\n"); - return -EIO; - } - - /* Enable future boot loads whenever power management unit triggers it - * (e.g. when powering back up after power-save shutdown) */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, - BSM_WR_CTRL_REG_BIT_START_EN); - - return 0; -} - -#define IWL3945_UCODE_GET(item) \ -static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - return le32_to_cpu(ucode->u.v1.item); \ -} - -static u32 iwl3945_ucode_get_header_size(u32 api_ver) -{ - return UCODE_HEADER_SIZE(1); -} -static u32 iwl3945_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return 0; -} -static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return (u8 *) ucode->u.v1.data; -} - -IWL3945_UCODE_GET(inst_size); -IWL3945_UCODE_GET(data_size); -IWL3945_UCODE_GET(init_size); -IWL3945_UCODE_GET(init_data_size); -IWL3945_UCODE_GET(boot_size); - -static struct iwl_hcmd_ops iwl3945_hcmd = { - .rxon_assoc = iwl3945_send_rxon_assoc, - .commit_rxon = iwl3945_commit_rxon, -}; - -static struct iwl_ucode_ops iwl3945_ucode = { - .get_header_size = iwl3945_ucode_get_header_size, - .get_build = iwl3945_ucode_get_build, - .get_inst_size = iwl3945_ucode_get_inst_size, - .get_data_size = iwl3945_ucode_get_data_size, - .get_init_size = iwl3945_ucode_get_init_size, - .get_init_data_size = iwl3945_ucode_get_init_data_size, - .get_boot_size = iwl3945_ucode_get_boot_size, - .get_data = iwl3945_ucode_get_data, -}; - -static struct iwl_lib_ops iwl3945_lib = { - .txq_attach_buf_to_tfd = iwl3945_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl3945_hw_txq_free_tfd, - .txq_init = iwl3945_hw_tx_queue_init, - .load_ucode = iwl3945_load_bsm, - .dump_nic_event_log = iwl3945_dump_nic_event_log, - .dump_nic_error_log = iwl3945_dump_nic_error_log, - .apm_ops = { - .init = iwl3945_apm_init, - .reset = iwl3945_apm_reset, - .stop = iwl3945_apm_stop, - .config = iwl3945_nic_config, - .set_pwr_src = iwl3945_set_pwr_src, - }, - .eeprom_ops = { - .regulatory_bands = { - EEPROM_REGULATORY_BAND_1_CHANNELS, - EEPROM_REGULATORY_BAND_2_CHANNELS, - EEPROM_REGULATORY_BAND_3_CHANNELS, - EEPROM_REGULATORY_BAND_4_CHANNELS, - EEPROM_REGULATORY_BAND_5_CHANNELS, - EEPROM_REGULATORY_BAND_NO_HT40, - EEPROM_REGULATORY_BAND_NO_HT40, - }, - .verify_signature = iwlcore_eeprom_verify_signature, - .acquire_semaphore = iwl3945_eeprom_acquire_semaphore, - .release_semaphore = iwl3945_eeprom_release_semaphore, - .query_addr = iwlcore_eeprom_query_addr, - }, - .send_tx_power = iwl3945_send_tx_power, - .is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr, - .post_associate = iwl3945_post_associate, - .isr = iwl_isr_legacy, - .config_ap = iwl3945_config_ap, -}; - -static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = { - .get_hcmd_size = iwl3945_get_hcmd_size, - .build_addsta_hcmd = iwl3945_build_addsta_hcmd, -}; - -static struct iwl_ops iwl3945_ops = { - .ucode = &iwl3945_ucode, - .lib = &iwl3945_lib, - .hcmd = &iwl3945_hcmd, - .utils = &iwl3945_hcmd_utils, -}; - -static struct iwl_cfg iwl3945_bg_cfg = { - .name = "3945BG", - .fw_name_pre = IWL3945_FW_PRE, - .ucode_api_max = IWL3945_UCODE_API_MAX, - .ucode_api_min = IWL3945_UCODE_API_MIN, - .sku = IWL_SKU_G, - .eeprom_size = IWL3945_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_3945_EEPROM_VERSION, - .ops = &iwl3945_ops, - .mod_params = &iwl3945_mod_params, - .use_isr_legacy = true, - .ht_greenfield_support = false, - .broken_powersave = true, -}; - -static struct iwl_cfg iwl3945_abg_cfg = { - .name = "3945ABG", - .fw_name_pre = IWL3945_FW_PRE, - .ucode_api_max = IWL3945_UCODE_API_MAX, - .ucode_api_min = IWL3945_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .eeprom_size = IWL3945_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_3945_EEPROM_VERSION, - .ops = &iwl3945_ops, - .mod_params = &iwl3945_mod_params, - .use_isr_legacy = true, - .ht_greenfield_support = false, - .broken_powersave = true, -}; - -struct pci_device_id iwl3945_hw_card_ids[] = { - {IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)}, - {IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)}, - {IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)}, - {IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)}, - {IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)}, - {IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)}, - {0} -}; - -MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids); diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h deleted file mode 100644 index 21679bf3a1aa..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ /dev/null @@ -1,303 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ -/* - * Please use this file (iwl-3945.h) for driver implementation definitions. - * Please use iwl-3945-commands.h for uCode API definitions. - * Please use iwl-3945-hw.h for hardware-related definitions. - */ - -#ifndef __iwl_3945_h__ -#define __iwl_3945_h__ - -#include /* for struct pci_device_id */ -#include -#include - -/* Hardware specific file defines the PCI IDs table for that hardware module */ -extern struct pci_device_id iwl3945_hw_card_ids[]; - -#include "iwl-csr.h" -#include "iwl-prph.h" -#include "iwl-fh.h" -#include "iwl-3945-hw.h" -#include "iwl-debug.h" -#include "iwl-power.h" -#include "iwl-dev.h" -#include "iwl-3945-led.h" - -/* Highest firmware API version supported */ -#define IWL3945_UCODE_API_MAX 2 - -/* Lowest firmware API version supported */ -#define IWL3945_UCODE_API_MIN 1 - -#define IWL3945_FW_PRE "iwlwifi-3945-" -#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE #api ".ucode" -#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api) - -/* Default noise level to report when noise measurement is not available. - * This may be because we're: - * 1) Not associated (4965, no beacon statistics being sent to driver) - * 2) Scanning (noise measurement does not apply to associated channel) - * 3) Receiving CCK (3945 delivers noise info only for OFDM frames) - * Use default noise value of -127 ... this is below the range of measurable - * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user. - * Also, -127 works better than 0 when averaging frames with/without - * noise info (e.g. averaging might be done in app); measured dBm values are - * always negative ... using a negative value as the default keeps all - * averages within an s8's (used in some apps) range of negative values. */ -#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127) - -/* Module parameters accessible from iwl-*.c */ -extern struct iwl_mod_params iwl3945_mod_params; - -struct iwl3945_sta_priv { - struct iwl3945_rs_sta *rs_sta; -}; - -enum iwl3945_antenna { - IWL_ANTENNA_DIVERSITY, - IWL_ANTENNA_MAIN, - IWL_ANTENNA_AUX -}; - -/* - * RTS threshold here is total size [2347] minus 4 FCS bytes - * Per spec: - * a value of 0 means RTS on all data/management packets - * a value > max MSDU size means no RTS - * else RTS for data/management frames where MPDU is larger - * than RTS value. - */ -#define DEFAULT_RTS_THRESHOLD 2347U -#define MIN_RTS_THRESHOLD 0U -#define MAX_RTS_THRESHOLD 2347U -#define MAX_MSDU_SIZE 2304U -#define MAX_MPDU_SIZE 2346U -#define DEFAULT_BEACON_INTERVAL 100U -#define DEFAULT_SHORT_RETRY_LIMIT 7U -#define DEFAULT_LONG_RETRY_LIMIT 4U - -#include "iwl-agn-rs.h" - -#define IWL_TX_FIFO_AC0 0 -#define IWL_TX_FIFO_AC1 1 -#define IWL_TX_FIFO_AC2 2 -#define IWL_TX_FIFO_AC3 3 -#define IWL_TX_FIFO_HCCA_1 5 -#define IWL_TX_FIFO_HCCA_2 6 -#define IWL_TX_FIFO_NONE 7 - -#define IEEE80211_DATA_LEN 2304 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) - -struct iwl3945_frame { - union { - struct ieee80211_hdr frame; - struct iwl3945_tx_beacon_cmd beacon; - u8 raw[IEEE80211_FRAME_LEN]; - u8 cmd[360]; - } u; - struct list_head list; -}; - -#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) -#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) -#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) - -/* - * RX related structures and functions - */ -#define RX_FREE_BUFFERS 64 -#define RX_LOW_WATERMARK 8 - -#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 -#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 -#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 - -#define IWL_SUPPORTED_RATES_IE_LEN 8 - -#define SCAN_INTERVAL 100 - -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_CONF_PENDING 18 - -#define MAX_TID_COUNT 9 - -#define IWL_INVALID_RATE 0xFF -#define IWL_INVALID_VALUE -1 - -#define STA_PS_STATUS_WAKE 0 -#define STA_PS_STATUS_SLEEP 1 - -struct iwl3945_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - -#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\ - x->u.rx_frame.stats.payload + \ - x->u.rx_frame.stats.phy_count)) -#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\ - IWL_RX_HDR(x)->payload + \ - le16_to_cpu(IWL_RX_HDR(x)->len))) -#define IWL_RX_STATS(x) (&x->u.rx_frame.stats) -#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload) - - -/****************************************************************************** - * - * Functions implemented in iwl-base.c which are forward declared here - * for use by iwl-*.c - * - *****************************************************************************/ -extern int iwl3945_power_init_handle(struct iwl_priv *priv); -extern int iwl3945_eeprom_init(struct iwl_priv *priv); -extern int iwl3945_calc_db_from_ratio(int sig_ratio); -extern int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm); -extern int iwl3945_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq, int count, u32 id); -extern void iwl3945_rx_replenish(void *data); -extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -extern void iwl3945_tx_queue_free(struct iwl_priv *priv, struct iwl_tx_queue *txq); -extern int iwl3945_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, - const void *data); -extern int __must_check iwl3945_send_cmd(struct iwl_priv *priv, - struct iwl_host_cmd *cmd); -extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr,int left); -extern void iwl3945_dump_nic_event_log(struct iwl_priv *priv); -extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv); - -/* - * Currently used by iwl-3945-rs... look at restructuring so that it doesn't - * call this... todo... fix that. -*/ -extern u8 iwl3945_sync_station(struct iwl_priv *priv, int sta_id, - u16 tx_rate, u8 flags); - -/****************************************************************************** - * - * Functions implemented in iwl-[34]*.c which are forward declared here - * for use by iwl-base.c - * - * NOTE: The implementation of these functions are hardware specific - * which is why they are in the hardware specific files (vs. iwl-base.c) - * - * Naming convention -- - * iwl3945_ <-- Its part of iwlwifi (should be changed to iwl3945_) - * iwl3945_hw_ <-- Hardware specific (implemented in iwl-XXXX.c by all HW) - * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) - * iwl3945_bg_ <-- Called from work queue context - * iwl3945_mac_ <-- mac80211 callback - * - ****************************************************************************/ -extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv); -extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv); -extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv); -extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv); -extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv); -extern int iwl3945_hw_nic_init(struct iwl_priv *priv); -extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv); -extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv); -extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv); -extern int iwl3945_hw_nic_reset(struct iwl_priv *priv); -extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, - u8 reset, u8 pad); -extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq); -extern int iwl3945_hw_get_temperature(struct iwl_priv *priv); -extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq); -extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl3945_frame *frame, u8 rate); -void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - int sta_id, int tx_id); -extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv); -extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power); -extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -extern void iwl3945_disable_events(struct iwl_priv *priv); -extern int iwl4965_get_temperature(const struct iwl_priv *priv); -extern void iwl3945_post_associate(struct iwl_priv *priv); -extern void iwl3945_config_ap(struct iwl_priv *priv); - -/** - * iwl3945_hw_find_station - Find station id for a given BSSID - * @bssid: MAC address of station ID to find - * - * NOTE: This should not be hardware specific but the code has - * not yet been merged into a single common layer for managing the - * station tables. - */ -extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid); - -extern int iwl3945_hw_channel_switch(struct iwl_priv *priv, u16 channel); - -/* - * Forward declare iwl-3945.c functions for iwl-base.c - */ -extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv); -extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv); -extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv); -extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv); -extern u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, - u16 tx_rate, u8 flags); - -extern const struct iwl_channel_info *iwl3945_get_channel_info( - const struct iwl_priv *priv, enum ieee80211_band band, u16 channel); - -extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate); - -/* Requires full declaration of iwl_priv before including */ -#include "iwl-io.h" - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h b/drivers/net/wireless/iwlwifi/iwl-4965-hw.h deleted file mode 100644 index b34322a32458..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-4965-hw.h +++ /dev/null @@ -1,819 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -/* - * Please use this file (iwl-4965-hw.h) only for hardware-related definitions. - * Use iwl-commands.h for uCode API definitions. - * Use iwl-dev.h for driver implementation definitions. - */ - -#ifndef __iwl_4965_hw_h__ -#define __iwl_4965_hw_h__ - -#include "iwl-fh.h" - -/* EEPROM */ -#define IWL4965_EEPROM_IMG_SIZE 1024 - -/* - * uCode queue management definitions ... - * Queue #4 is the command queue for 3945 and 4965; map it to Tx FIFO chnl 4. - * The first queue used for block-ack aggregation is #7 (4965 only). - * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7. - */ -#define IWL_CMD_QUEUE_NUM 4 -#define IWL_CMD_FIFO_NUM 4 -#define IWL49_FIRST_AMPDU_QUEUE 7 - -/* Time constants */ -#define SHORT_SLOT_TIME 9 -#define LONG_SLOT_TIME 20 - -/* RSSI to dBm */ -#define IWL49_RSSI_OFFSET 44 - - -/* PCI registers */ -#define PCI_CFG_RETRY_TIMEOUT 0x041 - -/* PCI register values */ -#define PCI_CFG_LINK_CTRL_VAL_L0S_EN 0x01 -#define PCI_CFG_LINK_CTRL_VAL_L1_EN 0x02 - -#define IWL_NUM_SCAN_RATES (2) - -#define IWL_DEFAULT_TX_RETRY 15 - - -/* Sizes and addresses for instruction and data memory (SRAM) in - * 4965's embedded processor. Driver access is via HBUS_TARG_MEM_* regs. */ -#define IWL49_RTC_INST_LOWER_BOUND (0x000000) -#define IWL49_RTC_INST_UPPER_BOUND (0x018000) - -#define IWL49_RTC_DATA_LOWER_BOUND (0x800000) -#define IWL49_RTC_DATA_UPPER_BOUND (0x80A000) - -#define IWL49_RTC_INST_SIZE (IWL49_RTC_INST_UPPER_BOUND - \ - IWL49_RTC_INST_LOWER_BOUND) -#define IWL49_RTC_DATA_SIZE (IWL49_RTC_DATA_UPPER_BOUND - \ - IWL49_RTC_DATA_LOWER_BOUND) - -#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE -#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE - -/* Size of uCode instruction memory in bootstrap state machine */ -#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE - -static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr) -{ - return (addr >= IWL49_RTC_DATA_LOWER_BOUND) && - (addr < IWL49_RTC_DATA_UPPER_BOUND); -} - -/********************* START TEMPERATURE *************************************/ - -/** - * 4965 temperature calculation. - * - * The driver must calculate the device temperature before calculating - * a txpower setting (amplifier gain is temperature dependent). The - * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration - * values used for the life of the driver, and one of which (R4) is the - * real-time temperature indicator. - * - * uCode provides all 4 values to the driver via the "initialize alive" - * notification (see struct iwl4965_init_alive_resp). After the runtime uCode - * image loads, uCode updates the R4 value via statistics notifications - * (see STATISTICS_NOTIFICATION), which occur after each received beacon - * when associated, or can be requested via REPLY_STATISTICS_CMD. - * - * NOTE: uCode provides the R4 value as a 23-bit signed value. Driver - * must sign-extend to 32 bits before applying formula below. - * - * Formula: - * - * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8 - * - * NOTE: The basic formula is 259 * (R4-R2) / (R3-R1). The 97/100 is - * an additional correction, which should be centered around 0 degrees - * Celsius (273 degrees Kelvin). The 8 (3 percent of 273) compensates for - * centering the 97/100 correction around 0 degrees K. - * - * Add 273 to Kelvin value to find degrees Celsius, for comparing current - * temperature with factory-measured temperatures when calculating txpower - * settings. - */ -#define TEMPERATURE_CALIB_KELVIN_OFFSET 8 -#define TEMPERATURE_CALIB_A_VAL 259 - -/* Limit range of calculated temperature to be between these Kelvin values */ -#define IWL_TX_POWER_TEMPERATURE_MIN (263) -#define IWL_TX_POWER_TEMPERATURE_MAX (410) - -#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \ - (((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \ - ((t) > IWL_TX_POWER_TEMPERATURE_MAX)) - -/********************* END TEMPERATURE ***************************************/ - -/********************* START TXPOWER *****************************************/ - -/** - * 4965 txpower calculations rely on information from three sources: - * - * 1) EEPROM - * 2) "initialize" alive notification - * 3) statistics notifications - * - * EEPROM data consists of: - * - * 1) Regulatory information (max txpower and channel usage flags) is provided - * separately for each channel that can possibly supported by 4965. - * 40 MHz wide (.11n HT40) channels are listed separately from 20 MHz - * (legacy) channels. - * - * See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom - * for locations in EEPROM. - * - * 2) Factory txpower calibration information is provided separately for - * sub-bands of contiguous channels. 2.4GHz has just one sub-band, - * but 5 GHz has several sub-bands. - * - * In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided. - * - * See struct iwl4965_eeprom_calib_info (and the tree of structures - * contained within it) for format, and struct iwl4965_eeprom for - * locations in EEPROM. - * - * "Initialization alive" notification (see struct iwl4965_init_alive_resp) - * consists of: - * - * 1) Temperature calculation parameters. - * - * 2) Power supply voltage measurement. - * - * 3) Tx gain compensation to balance 2 transmitters for MIMO use. - * - * Statistics notifications deliver: - * - * 1) Current values for temperature param R4. - */ - -/** - * To calculate a txpower setting for a given desired target txpower, channel, - * modulation bit rate, and transmitter chain (4965 has 2 transmitters to - * support MIMO and transmit diversity), driver must do the following: - * - * 1) Compare desired txpower vs. (EEPROM) regulatory limit for this channel. - * Do not exceed regulatory limit; reduce target txpower if necessary. - * - * If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), - * 2 transmitters will be used simultaneously; driver must reduce the - * regulatory limit by 3 dB (half-power) for each transmitter, so the - * combined total output of the 2 transmitters is within regulatory limits. - * - * - * 2) Compare target txpower vs. (EEPROM) saturation txpower *reduced by - * backoff for this bit rate*. Do not exceed (saturation - backoff[rate]); - * reduce target txpower if necessary. - * - * Backoff values below are in 1/2 dB units (equivalent to steps in - * txpower gain tables): - * - * OFDM 6 - 36 MBit: 10 steps (5 dB) - * OFDM 48 MBit: 15 steps (7.5 dB) - * OFDM 54 MBit: 17 steps (8.5 dB) - * OFDM 60 MBit: 20 steps (10 dB) - * CCK all rates: 10 steps (5 dB) - * - * Backoff values apply to saturation txpower on a per-transmitter basis; - * when using MIMO (2 transmitters), each transmitter uses the same - * saturation level provided in EEPROM, and the same backoff values; - * no reduction (such as with regulatory txpower limits) is required. - * - * Saturation and Backoff values apply equally to 20 Mhz (legacy) channel - * widths and 40 Mhz (.11n HT40) channel widths; there is no separate - * factory measurement for ht40 channels. - * - * The result of this step is the final target txpower. The rest of - * the steps figure out the proper settings for the device to achieve - * that target txpower. - * - * - * 3) Determine (EEPROM) calibration sub band for the target channel, by - * comparing against first and last channels in each sub band - * (see struct iwl4965_eeprom_calib_subband_info). - * - * - * 4) Linearly interpolate (EEPROM) factory calibration measurement sets, - * referencing the 2 factory-measured (sample) channels within the sub band. - * - * Interpolation is based on difference between target channel's frequency - * and the sample channels' frequencies. Since channel numbers are based - * on frequency (5 MHz between each channel number), this is equivalent - * to interpolating based on channel number differences. - * - * Note that the sample channels may or may not be the channels at the - * edges of the sub band. The target channel may be "outside" of the - * span of the sampled channels. - * - * Driver may choose the pair (for 2 Tx chains) of measurements (see - * struct iwl4965_eeprom_calib_ch_info) for which the actual measured - * txpower comes closest to the desired txpower. Usually, though, - * the middle set of measurements is closest to the regulatory limits, - * and is therefore a good choice for all txpower calculations (this - * assumes that high accuracy is needed for maximizing legal txpower, - * while lower txpower configurations do not need as much accuracy). - * - * Driver should interpolate both members of the chosen measurement pair, - * i.e. for both Tx chains (radio transmitters), unless the driver knows - * that only one of the chains will be used (e.g. only one tx antenna - * connected, but this should be unusual). The rate scaling algorithm - * switches antennas to find best performance, so both Tx chains will - * be used (although only one at a time) even for non-MIMO transmissions. - * - * Driver should interpolate factory values for temperature, gain table - * index, and actual power. The power amplifier detector values are - * not used by the driver. - * - * Sanity check: If the target channel happens to be one of the sample - * channels, the results should agree with the sample channel's - * measurements! - * - * - * 5) Find difference between desired txpower and (interpolated) - * factory-measured txpower. Using (interpolated) factory gain table index - * (shown elsewhere) as a starting point, adjust this index lower to - * increase txpower, or higher to decrease txpower, until the target - * txpower is reached. Each step in the gain table is 1/2 dB. - * - * For example, if factory measured txpower is 16 dBm, and target txpower - * is 13 dBm, add 6 steps to the factory gain index to reduce txpower - * by 3 dB. - * - * - * 6) Find difference between current device temperature and (interpolated) - * factory-measured temperature for sub-band. Factory values are in - * degrees Celsius. To calculate current temperature, see comments for - * "4965 temperature calculation". - * - * If current temperature is higher than factory temperature, driver must - * increase gain (lower gain table index), and vice verse. - * - * Temperature affects gain differently for different channels: - * - * 2.4 GHz all channels: 3.5 degrees per half-dB step - * 5 GHz channels 34-43: 4.5 degrees per half-dB step - * 5 GHz channels >= 44: 4.0 degrees per half-dB step - * - * NOTE: Temperature can increase rapidly when transmitting, especially - * with heavy traffic at high txpowers. Driver should update - * temperature calculations often under these conditions to - * maintain strong txpower in the face of rising temperature. - * - * - * 7) Find difference between current power supply voltage indicator - * (from "initialize alive") and factory-measured power supply voltage - * indicator (EEPROM). - * - * If the current voltage is higher (indicator is lower) than factory - * voltage, gain should be reduced (gain table index increased) by: - * - * (eeprom - current) / 7 - * - * If the current voltage is lower (indicator is higher) than factory - * voltage, gain should be increased (gain table index decreased) by: - * - * 2 * (current - eeprom) / 7 - * - * If number of index steps in either direction turns out to be > 2, - * something is wrong ... just use 0. - * - * NOTE: Voltage compensation is independent of band/channel. - * - * NOTE: "Initialize" uCode measures current voltage, which is assumed - * to be constant after this initial measurement. Voltage - * compensation for txpower (number of steps in gain table) - * may be calculated once and used until the next uCode bootload. - * - * - * 8) If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31), - * adjust txpower for each transmitter chain, so txpower is balanced - * between the two chains. There are 5 pairs of tx_atten[group][chain] - * values in "initialize alive", one pair for each of 5 channel ranges: - * - * Group 0: 5 GHz channel 34-43 - * Group 1: 5 GHz channel 44-70 - * Group 2: 5 GHz channel 71-124 - * Group 3: 5 GHz channel 125-200 - * Group 4: 2.4 GHz all channels - * - * Add the tx_atten[group][chain] value to the index for the target chain. - * The values are signed, but are in pairs of 0 and a non-negative number, - * so as to reduce gain (if necessary) of the "hotter" channel. This - * avoids any need to double-check for regulatory compliance after - * this step. - * - * - * 9) If setting up for a CCK rate, lower the gain by adding a CCK compensation - * value to the index: - * - * Hardware rev B: 9 steps (4.5 dB) - * Hardware rev C: 5 steps (2.5 dB) - * - * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, - * bits [3:2], 1 = B, 2 = C. - * - * NOTE: This compensation is in addition to any saturation backoff that - * might have been applied in an earlier step. - * - * - * 10) Select the gain table, based on band (2.4 vs 5 GHz). - * - * Limit the adjusted index to stay within the table! - * - * - * 11) Read gain table entries for DSP and radio gain, place into appropriate - * location(s) in command (struct iwl4965_txpowertable_cmd). - */ - -/* Limit range of txpower output target to be between these values */ -#define IWL_TX_POWER_TARGET_POWER_MIN (0) /* 0 dBm = 1 milliwatt */ -#define IWL_TX_POWER_TARGET_POWER_MAX (16) /* 16 dBm */ - -/** - * When MIMO is used (2 transmitters operating simultaneously), driver should - * limit each transmitter to deliver a max of 3 dB below the regulatory limit - * for the device. That is, use half power for each transmitter, so total - * txpower is within regulatory limits. - * - * The value "6" represents number of steps in gain table to reduce power 3 dB. - * Each step is 1/2 dB. - */ -#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6) - -/** - * CCK gain compensation. - * - * When calculating txpowers for CCK, after making sure that the target power - * is within regulatory and saturation limits, driver must additionally - * back off gain by adding these values to the gain table index. - * - * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG, - * bits [3:2], 1 = B, 2 = C. - */ -#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9) -#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5) - -/* - * 4965 power supply voltage compensation for txpower - */ -#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V (7) - -/** - * Gain tables. - * - * The following tables contain pair of values for setting txpower, i.e. - * gain settings for the output of the device's digital signal processor (DSP), - * and for the analog gain structure of the transmitter. - * - * Each entry in the gain tables represents a step of 1/2 dB. Note that these - * are *relative* steps, not indications of absolute output power. Output - * power varies with temperature, voltage, and channel frequency, and also - * requires consideration of average power (to satisfy regulatory constraints), - * and peak power (to avoid distortion of the output signal). - * - * Each entry contains two values: - * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained - * linear value that multiplies the output of the digital signal processor, - * before being sent to the analog radio. - * 2) Radio gain. This sets the analog gain of the radio Tx path. - * It is a coarser setting, and behaves in a logarithmic (dB) fashion. - * - * EEPROM contains factory calibration data for txpower. This maps actual - * measured txpower levels to gain settings in the "well known" tables - * below ("well-known" means here that both factory calibration *and* the - * driver work with the same table). - * - * There are separate tables for 2.4 GHz and 5 GHz bands. The 5 GHz table - * has an extension (into negative indexes), in case the driver needs to - * boost power setting for high device temperatures (higher than would be - * present during factory calibration). A 5 Ghz EEPROM index of "40" - * corresponds to the 49th entry in the table used by the driver. - */ -#define MIN_TX_GAIN_INDEX (0) /* highest gain, lowest idx, 2.4 */ -#define MIN_TX_GAIN_INDEX_52GHZ_EXT (-9) /* highest gain, lowest idx, 5 */ - -/** - * 2.4 GHz gain table - * - * Index Dsp gain Radio gain - * 0 110 0x3f (highest gain) - * 1 104 0x3f - * 2 98 0x3f - * 3 110 0x3e - * 4 104 0x3e - * 5 98 0x3e - * 6 110 0x3d - * 7 104 0x3d - * 8 98 0x3d - * 9 110 0x3c - * 10 104 0x3c - * 11 98 0x3c - * 12 110 0x3b - * 13 104 0x3b - * 14 98 0x3b - * 15 110 0x3a - * 16 104 0x3a - * 17 98 0x3a - * 18 110 0x39 - * 19 104 0x39 - * 20 98 0x39 - * 21 110 0x38 - * 22 104 0x38 - * 23 98 0x38 - * 24 110 0x37 - * 25 104 0x37 - * 26 98 0x37 - * 27 110 0x36 - * 28 104 0x36 - * 29 98 0x36 - * 30 110 0x35 - * 31 104 0x35 - * 32 98 0x35 - * 33 110 0x34 - * 34 104 0x34 - * 35 98 0x34 - * 36 110 0x33 - * 37 104 0x33 - * 38 98 0x33 - * 39 110 0x32 - * 40 104 0x32 - * 41 98 0x32 - * 42 110 0x31 - * 43 104 0x31 - * 44 98 0x31 - * 45 110 0x30 - * 46 104 0x30 - * 47 98 0x30 - * 48 110 0x6 - * 49 104 0x6 - * 50 98 0x6 - * 51 110 0x5 - * 52 104 0x5 - * 53 98 0x5 - * 54 110 0x4 - * 55 104 0x4 - * 56 98 0x4 - * 57 110 0x3 - * 58 104 0x3 - * 59 98 0x3 - * 60 110 0x2 - * 61 104 0x2 - * 62 98 0x2 - * 63 110 0x1 - * 64 104 0x1 - * 65 98 0x1 - * 66 110 0x0 - * 67 104 0x0 - * 68 98 0x0 - * 69 97 0 - * 70 96 0 - * 71 95 0 - * 72 94 0 - * 73 93 0 - * 74 92 0 - * 75 91 0 - * 76 90 0 - * 77 89 0 - * 78 88 0 - * 79 87 0 - * 80 86 0 - * 81 85 0 - * 82 84 0 - * 83 83 0 - * 84 82 0 - * 85 81 0 - * 86 80 0 - * 87 79 0 - * 88 78 0 - * 89 77 0 - * 90 76 0 - * 91 75 0 - * 92 74 0 - * 93 73 0 - * 94 72 0 - * 95 71 0 - * 96 70 0 - * 97 69 0 - * 98 68 0 - */ - -/** - * 5 GHz gain table - * - * Index Dsp gain Radio gain - * -9 123 0x3F (highest gain) - * -8 117 0x3F - * -7 110 0x3F - * -6 104 0x3F - * -5 98 0x3F - * -4 110 0x3E - * -3 104 0x3E - * -2 98 0x3E - * -1 110 0x3D - * 0 104 0x3D - * 1 98 0x3D - * 2 110 0x3C - * 3 104 0x3C - * 4 98 0x3C - * 5 110 0x3B - * 6 104 0x3B - * 7 98 0x3B - * 8 110 0x3A - * 9 104 0x3A - * 10 98 0x3A - * 11 110 0x39 - * 12 104 0x39 - * 13 98 0x39 - * 14 110 0x38 - * 15 104 0x38 - * 16 98 0x38 - * 17 110 0x37 - * 18 104 0x37 - * 19 98 0x37 - * 20 110 0x36 - * 21 104 0x36 - * 22 98 0x36 - * 23 110 0x35 - * 24 104 0x35 - * 25 98 0x35 - * 26 110 0x34 - * 27 104 0x34 - * 28 98 0x34 - * 29 110 0x33 - * 30 104 0x33 - * 31 98 0x33 - * 32 110 0x32 - * 33 104 0x32 - * 34 98 0x32 - * 35 110 0x31 - * 36 104 0x31 - * 37 98 0x31 - * 38 110 0x30 - * 39 104 0x30 - * 40 98 0x30 - * 41 110 0x25 - * 42 104 0x25 - * 43 98 0x25 - * 44 110 0x24 - * 45 104 0x24 - * 46 98 0x24 - * 47 110 0x23 - * 48 104 0x23 - * 49 98 0x23 - * 50 110 0x22 - * 51 104 0x18 - * 52 98 0x18 - * 53 110 0x17 - * 54 104 0x17 - * 55 98 0x17 - * 56 110 0x16 - * 57 104 0x16 - * 58 98 0x16 - * 59 110 0x15 - * 60 104 0x15 - * 61 98 0x15 - * 62 110 0x14 - * 63 104 0x14 - * 64 98 0x14 - * 65 110 0x13 - * 66 104 0x13 - * 67 98 0x13 - * 68 110 0x12 - * 69 104 0x08 - * 70 98 0x08 - * 71 110 0x07 - * 72 104 0x07 - * 73 98 0x07 - * 74 110 0x06 - * 75 104 0x06 - * 76 98 0x06 - * 77 110 0x05 - * 78 104 0x05 - * 79 98 0x05 - * 80 110 0x04 - * 81 104 0x04 - * 82 98 0x04 - * 83 110 0x03 - * 84 104 0x03 - * 85 98 0x03 - * 86 110 0x02 - * 87 104 0x02 - * 88 98 0x02 - * 89 110 0x01 - * 90 104 0x01 - * 91 98 0x01 - * 92 110 0x00 - * 93 104 0x00 - * 94 98 0x00 - * 95 93 0x00 - * 96 88 0x00 - * 97 83 0x00 - * 98 78 0x00 - */ - - -/** - * Sanity checks and default values for EEPROM regulatory levels. - * If EEPROM values fall outside MIN/MAX range, use default values. - * - * Regulatory limits refer to the maximum average txpower allowed by - * regulatory agencies in the geographies in which the device is meant - * to be operated. These limits are SKU-specific (i.e. geography-specific), - * and channel-specific; each channel has an individual regulatory limit - * listed in the EEPROM. - * - * Units are in half-dBm (i.e. "34" means 17 dBm). - */ -#define IWL_TX_POWER_DEFAULT_REGULATORY_24 (34) -#define IWL_TX_POWER_DEFAULT_REGULATORY_52 (34) -#define IWL_TX_POWER_REGULATORY_MIN (0) -#define IWL_TX_POWER_REGULATORY_MAX (34) - -/** - * Sanity checks and default values for EEPROM saturation levels. - * If EEPROM values fall outside MIN/MAX range, use default values. - * - * Saturation is the highest level that the output power amplifier can produce - * without significant clipping distortion. This is a "peak" power level. - * Different types of modulation (i.e. various "rates", and OFDM vs. CCK) - * require differing amounts of backoff, relative to their average power output, - * in order to avoid clipping distortion. - * - * Driver must make sure that it is violating neither the saturation limit, - * nor the regulatory limit, when calculating Tx power settings for various - * rates. - * - * Units are in half-dBm (i.e. "38" means 19 dBm). - */ -#define IWL_TX_POWER_DEFAULT_SATURATION_24 (38) -#define IWL_TX_POWER_DEFAULT_SATURATION_52 (38) -#define IWL_TX_POWER_SATURATION_MIN (20) -#define IWL_TX_POWER_SATURATION_MAX (50) - -/** - * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance) - * and thermal Txpower calibration. - * - * When calculating txpower, driver must compensate for current device - * temperature; higher temperature requires higher gain. Driver must calculate - * current temperature (see "4965 temperature calculation"), then compare vs. - * factory calibration temperature in EEPROM; if current temperature is higher - * than factory temperature, driver must *increase* gain by proportions shown - * in table below. If current temperature is lower than factory, driver must - * *decrease* gain. - * - * Different frequency ranges require different compensation, as shown below. - */ -/* Group 0, 5.2 GHz ch 34-43: 4.5 degrees per 1/2 dB. */ -#define CALIB_IWL_TX_ATTEN_GR1_FCH 34 -#define CALIB_IWL_TX_ATTEN_GR1_LCH 43 - -/* Group 1, 5.3 GHz ch 44-70: 4.0 degrees per 1/2 dB. */ -#define CALIB_IWL_TX_ATTEN_GR2_FCH 44 -#define CALIB_IWL_TX_ATTEN_GR2_LCH 70 - -/* Group 2, 5.5 GHz ch 71-124: 4.0 degrees per 1/2 dB. */ -#define CALIB_IWL_TX_ATTEN_GR3_FCH 71 -#define CALIB_IWL_TX_ATTEN_GR3_LCH 124 - -/* Group 3, 5.7 GHz ch 125-200: 4.0 degrees per 1/2 dB. */ -#define CALIB_IWL_TX_ATTEN_GR4_FCH 125 -#define CALIB_IWL_TX_ATTEN_GR4_LCH 200 - -/* Group 4, 2.4 GHz all channels: 3.5 degrees per 1/2 dB. */ -#define CALIB_IWL_TX_ATTEN_GR5_FCH 1 -#define CALIB_IWL_TX_ATTEN_GR5_LCH 20 - -enum { - CALIB_CH_GROUP_1 = 0, - CALIB_CH_GROUP_2 = 1, - CALIB_CH_GROUP_3 = 2, - CALIB_CH_GROUP_4 = 3, - CALIB_CH_GROUP_5 = 4, - CALIB_CH_GROUP_MAX -}; - -/********************* END TXPOWER *****************************************/ - - -/** - * Tx/Rx Queues - * - * Most communication between driver and 4965 is via queues of data buffers. - * For example, all commands that the driver issues to device's embedded - * controller (uCode) are via the command queue (one of the Tx queues). All - * uCode command responses/replies/notifications, including Rx frames, are - * conveyed from uCode to driver via the Rx queue. - * - * Most support for these queues, including handshake support, resides in - * structures in host DRAM, shared between the driver and the device. When - * allocating this memory, the driver must make sure that data written by - * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's - * cache memory), so DRAM and cache are consistent, and the device can - * immediately see changes made by the driver. - * - * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via - * up to 7 DMA channels (FIFOs). Each Tx queue is supported by a circular array - * in DRAM containing 256 Transmit Frame Descriptors (TFDs). - */ -#define IWL49_NUM_FIFOS 7 -#define IWL49_CMD_FIFO_NUM 4 -#define IWL49_NUM_QUEUES 16 -#define IWL49_NUM_AMPDU_QUEUES 8 - - -/** - * struct iwl4965_schedq_bc_tbl - * - * Byte Count table - * - * Each Tx queue uses a byte-count table containing 320 entries: - * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that - * duplicate the first 64 entries (to avoid wrap-around within a Tx window; - * max Tx window is 64 TFDs). - * - * When driver sets up a new TFD, it must also enter the total byte count - * of the frame to be transmitted into the corresponding entry in the byte - * count table for the chosen Tx queue. If the TFD index is 0-63, the driver - * must duplicate the byte count entry in corresponding index 256-319. - * - * padding puts each byte count table on a 1024-byte boundary; - * 4965 assumes tables are separated by 1024 bytes. - */ -struct iwl4965_scd_bc_tbl { - __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; - u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)]; -} __attribute__ ((packed)); - -#endif /* !__iwl_4965_hw_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c deleted file mode 100644 index 585b8d49f35b..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ /dev/null @@ -1,2391 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-helpers.h" -#include "iwl-calib.h" -#include "iwl-sta.h" - -static int iwl4965_send_tx_power(struct iwl_priv *priv); -static int iwl4965_hw_get_temperature(struct iwl_priv *priv); - -/* Highest firmware API version supported */ -#define IWL4965_UCODE_API_MAX 2 - -/* Lowest firmware API version supported */ -#define IWL4965_UCODE_API_MIN 2 - -#define IWL4965_FW_PRE "iwlwifi-4965-" -#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE #api ".ucode" -#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api) - - -/* module parameters */ -static struct iwl_mod_params iwl4965_mod_params = { - .num_of_queues = IWL49_NUM_QUEUES, - .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES, - .amsdu_size_8K = 1, - .restart_fw = 1, - /* the rest are 0 by default */ -}; - -/* check contents of special bootstrap uCode SRAM */ -static int iwl4965_verify_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - u32 reg; - u32 val; - - IWL_DEBUG_INFO(priv, "Begin verify bsm\n"); - - /* verify BSM SRAM contents */ - val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG); - for (reg = BSM_SRAM_LOWER_BOUND; - reg < BSM_SRAM_LOWER_BOUND + len; - reg += sizeof(u32), image++) { - val = iwl_read_prph(priv, reg); - if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "BSM uCode verification failed at " - "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n", - BSM_SRAM_LOWER_BOUND, - reg - BSM_SRAM_LOWER_BOUND, len, - val, le32_to_cpu(*image)); - return -EIO; - } - } - - IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n"); - - return 0; -} - -/** - * iwl4965_load_bsm - Load bootstrap instructions - * - * BSM operation: - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down during RFKILL. When powering back - * up after power-saving sleeps (or during initial uCode load), the BSM loads - * the bootstrap program into the on-board processor, and starts it. - * - * The bootstrap program loads (via DMA) instructions and data for a new - * program from host DRAM locations indicated by the host driver in the - * BSM_DRAM_* registers. Once the new program is loaded, it starts - * automatically. - * - * When initializing the NIC, the host driver points the BSM to the - * "initialize" uCode image. This uCode sets up some internal data, then - * notifies host via "initialize alive" that it is complete. - * - * The host then replaces the BSM_DRAM_* pointer values to point to the - * normal runtime uCode instructions and a backup uCode data cache buffer - * (filled initially with starting data values for the on-board processor), - * then triggers the "initialize" uCode to load and launch the runtime uCode, - * which begins normal operation. - * - * When doing a power-save shutdown, runtime uCode saves data SRAM into - * the backup data cache in DRAM before SRAM is powered down. - * - * When powering back up, the BSM loads the bootstrap program. This reloads - * the runtime uCode instructions and the backup data cache into SRAM, - * and re-launches the runtime uCode from where it left off. - */ -static int iwl4965_load_bsm(struct iwl_priv *priv) -{ - __le32 *image = priv->ucode_boot.v_addr; - u32 len = priv->ucode_boot.len; - dma_addr_t pinst; - dma_addr_t pdata; - u32 inst_len; - u32 data_len; - int i; - u32 done; - u32 reg_offset; - int ret; - - IWL_DEBUG_INFO(priv, "Begin load bsm\n"); - - priv->ucode_type = UCODE_RT; - - /* make sure bootstrap program is no larger than BSM's SRAM size */ - if (len > IWL49_MAX_BSM_SIZE) - return -EINVAL; - - /* Tell bootstrap uCode where to find the "Initialize" uCode - * in host DRAM ... host DRAM physical address bits 35:4 for 4965. - * NOTE: iwl_init_alive_start() will replace these values, - * after the "initialize" uCode has run, to point to - * runtime/protocol instructions and backup data cache. - */ - pinst = priv->ucode_init.p_addr >> 4; - pdata = priv->ucode_init_data.p_addr >> 4; - inst_len = priv->ucode_init.len; - data_len = priv->ucode_init_data.len; - - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len); - - /* Fill BSM memory with bootstrap instructions */ - for (reg_offset = BSM_SRAM_LOWER_BOUND; - reg_offset < BSM_SRAM_LOWER_BOUND + len; - reg_offset += sizeof(u32), image++) - _iwl_write_prph(priv, reg_offset, le32_to_cpu(*image)); - - ret = iwl4965_verify_bsm(priv); - if (ret) - return ret; - - /* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */ - iwl_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0); - iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND); - iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32)); - - /* Load bootstrap code into instruction SRAM now, - * to prepare to load "initialize" uCode */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START); - - /* Wait for load of bootstrap uCode to finish */ - for (i = 0; i < 100; i++) { - done = iwl_read_prph(priv, BSM_WR_CTRL_REG); - if (!(done & BSM_WR_CTRL_REG_BIT_START)) - break; - udelay(10); - } - if (i < 100) - IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i); - else { - IWL_ERR(priv, "BSM write did not complete!\n"); - return -EIO; - } - - /* Enable future boot loads whenever power management unit triggers it - * (e.g. when powering back up after power-save shutdown) */ - iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN); - - - return 0; -} - -/** - * iwl4965_set_ucode_ptrs - Set uCode address location - * - * Tell initialization uCode where to find runtime uCode. - * - * BSM registers initially contain pointers to initialization uCode. - * We need to replace them to load runtime uCode inst and data, - * and to save runtime data when powering down. - */ -static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv) -{ - dma_addr_t pinst; - dma_addr_t pdata; - int ret = 0; - - /* bits 35:4 for 4965 */ - pinst = priv->ucode_code.p_addr >> 4; - pdata = priv->ucode_data_backup.p_addr >> 4; - - /* Tell bootstrap uCode where to find image to load */ - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, - priv->ucode_data.len); - - /* Inst byte count must be last to set up, bit 31 signals uCode - * that all new ptr/size info is in place */ - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, - priv->ucode_code.len | BSM_DRAM_INST_LOAD); - IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); - - return ret; -} - -/** - * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received - * - * Called after REPLY_ALIVE notification received from "initialize" uCode. - * - * The 4965 "initialize" ALIVE reply contains calibration data for: - * Voltage, temperature, and MIMO tx gain correction, now stored in priv - * (3945 does not contain this data). - * - * Tell "initialize" uCode to go ahead and load the runtime uCode. -*/ -static void iwl4965_init_alive_start(struct iwl_priv *priv) -{ - /* Check alive response for "valid" sign from uCode */ - if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); - goto restart; - } - - /* Bootstrap uCode has loaded initialize uCode ... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "initialize" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); - goto restart; - } - - /* Calculate temperature */ - priv->temperature = iwl4965_hw_get_temperature(priv); - - /* Send pointers to protocol/runtime uCode image ... init code will - * load and launch runtime uCode, which will send us another "Alive" - * notification. */ - IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); - if (iwl4965_set_ucode_ptrs(priv)) { - /* Runtime instruction load won't happen; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); - goto restart; - } - return; - -restart: - queue_work(priv->workqueue, &priv->restart); -} - -static bool is_ht40_channel(__le32 rxon_flags) -{ - int chan_mod = le32_to_cpu(rxon_flags & RXON_FLG_CHANNEL_MODE_MSK) - >> RXON_FLG_CHANNEL_MODE_POS; - return ((chan_mod == CHANNEL_MODE_PURE_40) || - (chan_mod == CHANNEL_MODE_MIXED)); -} - -/* - * EEPROM handlers - */ -static u16 iwl4965_eeprom_calib_version(struct iwl_priv *priv) -{ - return iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET); -} - -/* - * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->lock and mac access - */ -static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask) -{ - iwl_write_prph(priv, IWL49_SCD_TXFACT, mask); -} - -static int iwl4965_apm_init(struct iwl_priv *priv) -{ - int ret = 0; - - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); - - /* set "initialization complete" bit to move adapter - * D0U* --> D0A* state */ - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - /* wait for clock stabilization */ - ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (ret < 0) { - IWL_DEBUG_INFO(priv, "Failed to init the card\n"); - goto out; - } - - /* enable DMA */ - iwl_write_prph(priv, APMG_CLK_CTRL_REG, APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); - - udelay(20); - - /* disable L1-Active */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - -out: - return ret; -} - - -static void iwl4965_nic_config(struct iwl_priv *priv) -{ - unsigned long flags; - u16 radio_cfg; - u16 lctl; - - spin_lock_irqsave(&priv->lock, flags); - - lctl = iwl_pcie_link_ctl(priv); - - /* HW bug W/A - negligible power consumption */ - /* L1-ASPM is enabled by BIOS */ - if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) - /* L1-ASPM enabled: disable L0S */ - iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - else - /* L1-ASPM disabled: enable L0S */ - iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - - radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); - - /* write radio config values to register */ - if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX) - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | - EEPROM_RF_CFG_STEP_MSK(radio_cfg) | - EEPROM_RF_CFG_DASH_MSK(radio_cfg)); - - /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | - CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); - - priv->calib_info = (struct iwl_eeprom_calib_info *) - iwl_eeprom_query_addr(priv, EEPROM_4965_CALIB_TXPOWER_OFFSET); - - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int iwl4965_apm_stop_master(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - /* set stop master bit */ - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - - iwl_poll_direct_bit(priv, CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - - spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO(priv, "stop master\n"); - - return 0; -} - -static void iwl4965_apm_stop(struct iwl_priv *priv) -{ - unsigned long flags; - - iwl4965_apm_stop_master(priv); - - spin_lock_irqsave(&priv->lock, flags); - - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - - udelay(10); - /* clear "init complete" move adapter D0A* --> D0U state */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int iwl4965_apm_reset(struct iwl_priv *priv) -{ - int ret = 0; - - iwl4965_apm_stop_master(priv); - - - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - - udelay(10); - - /* FIXME: put here L1A -L0S w/a */ - - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (ret < 0) - goto out; - - udelay(10); - - /* Enable DMA and BSM Clock */ - iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT | - APMG_CLK_VAL_BSM_CLK_RQT); - - udelay(10); - - /* disable L1A */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); - -out: - return ret; -} - -/* Reset differential Rx gains in NIC to prepare for chain noise calibration. - * Called after every association, but this runs only once! - * ... once chain noise is calibrated the first time, it's good forever. */ -static void iwl4965_chain_noise_reset(struct iwl_priv *priv) -{ - struct iwl_chain_noise_data *data = &(priv->chain_noise_data); - - if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { - struct iwl_calib_diff_gain_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; - cmd.diff_gain_a = 0; - cmd.diff_gain_b = 0; - cmd.diff_gain_c = 0; - if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd)) - IWL_ERR(priv, - "Could not send REPLY_PHY_CALIBRATION_CMD\n"); - data->state = IWL_CHAIN_NOISE_ACCUMULATE; - IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); - } -} - -static void iwl4965_gain_computation(struct iwl_priv *priv, - u32 *average_noise, - u16 min_average_noise_antenna_i, - u32 min_average_noise) -{ - int i, ret; - struct iwl_chain_noise_data *data = &priv->chain_noise_data; - - data->delta_gain_code[min_average_noise_antenna_i] = 0; - - for (i = 0; i < NUM_RX_CHAINS; i++) { - s32 delta_g = 0; - - if (!(data->disconn_array[i]) && - (data->delta_gain_code[i] == - CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) { - delta_g = average_noise[i] - min_average_noise; - data->delta_gain_code[i] = (u8)((delta_g * 10) / 15); - data->delta_gain_code[i] = - min(data->delta_gain_code[i], - (u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); - - data->delta_gain_code[i] = - (data->delta_gain_code[i] | (1 << 2)); - } else { - data->delta_gain_code[i] = 0; - } - } - IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n", - data->delta_gain_code[0], - data->delta_gain_code[1], - data->delta_gain_code[2]); - - /* Differential gain gets sent to uCode only once */ - if (!data->radio_write) { - struct iwl_calib_diff_gain_cmd cmd; - data->radio_write = 1; - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD; - cmd.diff_gain_a = data->delta_gain_code[0]; - cmd.diff_gain_b = data->delta_gain_code[1]; - cmd.diff_gain_c = data->delta_gain_code[2]; - ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd); - if (ret) - IWL_DEBUG_CALIB(priv, "fail sending cmd " - "REPLY_PHY_CALIBRATION_CMD \n"); - - /* TODO we might want recalculate - * rx_chain in rxon cmd */ - - /* Mark so we run this algo only once! */ - data->state = IWL_CHAIN_NOISE_CALIBRATED; - } - data->chain_noise_a = 0; - data->chain_noise_b = 0; - data->chain_noise_c = 0; - data->chain_signal_a = 0; - data->chain_signal_b = 0; - data->chain_signal_c = 0; - data->beacon_count = 0; -} - -static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) -{ - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - *tx_flags |= TX_CMD_FLG_RTS_MSK; - *tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - *tx_flags &= ~TX_CMD_FLG_RTS_MSK; - *tx_flags |= TX_CMD_FLG_CTS_MSK; - } -} - -static void iwl4965_bg_txpower_work(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, - txpower_work); - - /* If a scan happened to start before we got here - * then just return; the statistics notification will - * kick off another scheduled work to compensate for - * any temperature delta we missed here. */ - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - - /* Regardless of if we are associated, we must reconfigure the - * TX power since frames can be sent on non-radar channels while - * not associated */ - iwl4965_send_tx_power(priv); - - /* Update last_temperature to keep is_calib_needed from running - * when it isn't needed... */ - priv->last_temperature = priv->temperature; - - mutex_unlock(&priv->mutex); -} - -/* - * Acquire priv->lock before calling this function ! - */ -static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index) -{ - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index); -} - -/** - * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue - * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed - * @scd_retry: (1) Indicates queue will be used in aggregation mode - * - * NOTE: Acquire priv->lock before calling this function ! - */ -static void iwl4965_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry) -{ - int txq_id = txq->q.id; - - /* Find out whether to activate Tx queue */ - int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - - /* Set up and activate */ - iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id), - (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) | - (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) | - (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) | - IWL49_SCD_QUEUE_STTS_REG_MSK); - - txq->sched_retry = scd_retry; - - IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", - active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); -} - -static const u16 default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, - IWL49_CMD_FIFO_NUM, - IWL_TX_FIFO_HCCA_1, - IWL_TX_FIFO_HCCA_2 -}; - -static int iwl4965_alive_notify(struct iwl_priv *priv) -{ - u32 a; - unsigned long flags; - int i, chan; - u32 reg_val; - - spin_lock_irqsave(&priv->lock, flags); - - /* Clear 4965's internal Tx Scheduler data base */ - priv->scd_base_addr = iwl_read_prph(priv, IWL49_SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET; - for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) - iwl_write_targ_mem(priv, a, 0); - - /* Tel 4965 where to find Tx byte count tables */ - iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR, - priv->scd_bc_tbls.dma >> 10); - - /* Enable DMA channel */ - for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); - - /* Update FH chicken bits */ - reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - - /* Disable chain mode for all queues */ - iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0); - - /* Initialize each Tx queue (including the command queue) */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { - - /* TFD circular buffer read/write indexes */ - iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - - /* Max Tx Window size for Scheduler-ACK mode */ - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL49_SCD_CONTEXT_QUEUE_OFFSET(i), - (SCD_WIN_SIZE << - IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & - IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); - - /* Frame limit */ - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) + - sizeof(u32), - (SCD_FRAME_LIMIT << - IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); - - } - iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK, - (1 << priv->hw_params.max_txq_num) - 1); - - /* Activate all Tx DMA/FIFO channels */ - priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6)); - - iwl4965_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); - - /* make sure all queue are not stopped */ - memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); - for (i = 0; i < 4; i++) - atomic_set(&priv->queue_stop_count[i], 0); - - /* reset to 0 to enable all the queue first */ - priv->txq_ctx_active_msk = 0; - /* Map each Tx/cmd queue to its corresponding fifo */ - for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) { - int ac = default_queue_to_tx_fifo[i]; - iwl_txq_ctx_activate(priv, i); - iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0); - } - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -static struct iwl_sensitivity_ranges iwl4965_sensitivity = { - .min_nrg_cck = 97, - .max_nrg_cck = 0, /* not used, set to 0 */ - - .auto_corr_min_ofdm = 85, - .auto_corr_min_ofdm_mrc = 170, - .auto_corr_min_ofdm_x1 = 105, - .auto_corr_min_ofdm_mrc_x1 = 220, - - .auto_corr_max_ofdm = 120, - .auto_corr_max_ofdm_mrc = 210, - .auto_corr_max_ofdm_x1 = 140, - .auto_corr_max_ofdm_mrc_x1 = 270, - - .auto_corr_min_cck = 125, - .auto_corr_max_cck = 200, - .auto_corr_min_cck_mrc = 200, - .auto_corr_max_cck_mrc = 400, - - .nrg_th_cck = 100, - .nrg_th_ofdm = 100, -}; - -static void iwl4965_set_ct_threshold(struct iwl_priv *priv) -{ - /* want Kelvin */ - priv->hw_params.ct_kill_threshold = - CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY); -} - -/** - * iwl4965_hw_set_hw_params - * - * Called when initializing driver - */ -static int iwl4965_hw_set_hw_params(struct iwl_priv *priv) -{ - - if ((priv->cfg->mod_params->num_of_queues > IWL49_NUM_QUEUES) || - (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { - IWL_ERR(priv, - "invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL49_NUM_QUEUES); - return -EINVAL; - } - - priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM; - priv->hw_params.scd_bc_tbls_size = - IWL49_NUM_QUEUES * sizeof(struct iwl4965_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWL4965_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; - priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE; - priv->hw_params.max_bsm_size = BSM_SRAM_SIZE; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ); - - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; - - priv->hw_params.tx_chains_num = 2; - priv->hw_params.rx_chains_num = 2; - priv->hw_params.valid_tx_ant = ANT_A | ANT_B; - priv->hw_params.valid_rx_ant = ANT_A | ANT_B; - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); - - priv->hw_params.sens = &iwl4965_sensitivity; - - return 0; -} - -static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res) -{ - s32 sign = 1; - - if (num < 0) { - sign = -sign; - num = -num; - } - if (denom < 0) { - sign = -sign; - denom = -denom; - } - *res = 1; - *res = ((num * 2 + denom) / (denom * 2)) * sign; - - return 1; -} - -/** - * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower - * - * Determines power supply voltage compensation for txpower calculations. - * Returns number of 1/2-dB steps to subtract from gain table index, - * to compensate for difference between power supply voltage during - * factory measurements, vs. current power supply voltage. - * - * Voltage indication is higher for lower voltage. - * Lower voltage requires more gain (lower gain table index). - */ -static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage, - s32 current_voltage) -{ - s32 comp = 0; - - if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) || - (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage)) - return 0; - - iwl4965_math_div_round(current_voltage - eeprom_voltage, - TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp); - - if (current_voltage > eeprom_voltage) - comp *= 2; - if ((comp < -2) || (comp > 2)) - comp = 0; - - return comp; -} - -static s32 iwl4965_get_tx_atten_grp(u16 channel) -{ - if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH && - channel <= CALIB_IWL_TX_ATTEN_GR5_LCH) - return CALIB_CH_GROUP_5; - - if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH && - channel <= CALIB_IWL_TX_ATTEN_GR1_LCH) - return CALIB_CH_GROUP_1; - - if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH && - channel <= CALIB_IWL_TX_ATTEN_GR2_LCH) - return CALIB_CH_GROUP_2; - - if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH && - channel <= CALIB_IWL_TX_ATTEN_GR3_LCH) - return CALIB_CH_GROUP_3; - - if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH && - channel <= CALIB_IWL_TX_ATTEN_GR4_LCH) - return CALIB_CH_GROUP_4; - - return -1; -} - -static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel) -{ - s32 b = -1; - - for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) { - if (priv->calib_info->band_info[b].ch_from == 0) - continue; - - if ((channel >= priv->calib_info->band_info[b].ch_from) - && (channel <= priv->calib_info->band_info[b].ch_to)) - break; - } - - return b; -} - -static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2) -{ - s32 val; - - if (x2 == x1) - return y1; - else { - iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val); - return val + y2; - } -} - -/** - * iwl4965_interpolate_chan - Interpolate factory measurements for one channel - * - * Interpolates factory measurements from the two sample channels within a - * sub-band, to apply to channel of interest. Interpolation is proportional to - * differences in channel frequencies, which is proportional to differences - * in channel number. - */ -static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel, - struct iwl_eeprom_calib_ch_info *chan_info) -{ - s32 s = -1; - u32 c; - u32 m; - const struct iwl_eeprom_calib_measure *m1; - const struct iwl_eeprom_calib_measure *m2; - struct iwl_eeprom_calib_measure *omeas; - u32 ch_i1; - u32 ch_i2; - - s = iwl4965_get_sub_band(priv, channel); - if (s >= EEPROM_TX_POWER_BANDS) { - IWL_ERR(priv, "Tx Power can not find channel %d\n", channel); - return -1; - } - - ch_i1 = priv->calib_info->band_info[s].ch1.ch_num; - ch_i2 = priv->calib_info->band_info[s].ch2.ch_num; - chan_info->ch_num = (u8) channel; - - IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n", - channel, s, ch_i1, ch_i2); - - for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) { - for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) { - m1 = &(priv->calib_info->band_info[s].ch1. - measurements[c][m]); - m2 = &(priv->calib_info->band_info[s].ch2. - measurements[c][m]); - omeas = &(chan_info->measurements[c][m]); - - omeas->actual_pow = - (u8) iwl4965_interpolate_value(channel, ch_i1, - m1->actual_pow, - ch_i2, - m2->actual_pow); - omeas->gain_idx = - (u8) iwl4965_interpolate_value(channel, ch_i1, - m1->gain_idx, ch_i2, - m2->gain_idx); - omeas->temperature = - (u8) iwl4965_interpolate_value(channel, ch_i1, - m1->temperature, - ch_i2, - m2->temperature); - omeas->pa_det = - (s8) iwl4965_interpolate_value(channel, ch_i1, - m1->pa_det, ch_i2, - m2->pa_det); - - IWL_DEBUG_TXPOWER(priv, - "chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m, - m1->actual_pow, m2->actual_pow, omeas->actual_pow); - IWL_DEBUG_TXPOWER(priv, - "chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m, - m1->gain_idx, m2->gain_idx, omeas->gain_idx); - IWL_DEBUG_TXPOWER(priv, - "chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m, - m1->pa_det, m2->pa_det, omeas->pa_det); - IWL_DEBUG_TXPOWER(priv, - "chain %d meas %d T1=%d T2=%d T=%d\n", c, m, - m1->temperature, m2->temperature, - omeas->temperature); - } - } - - return 0; -} - -/* bit-rate-dependent table to prevent Tx distortion, in half-dB units, - * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */ -static s32 back_off_table[] = { - 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 20 MHz */ - 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 20 MHz */ - 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM SISO 40 MHz */ - 10, 10, 10, 10, 10, 15, 17, 20, /* OFDM MIMO 40 MHz */ - 10 /* CCK */ -}; - -/* Thermal compensation values for txpower for various frequency ranges ... - * ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */ -static struct iwl4965_txpower_comp_entry { - s32 degrees_per_05db_a; - s32 degrees_per_05db_a_denom; -} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = { - {9, 2}, /* group 0 5.2, ch 34-43 */ - {4, 1}, /* group 1 5.2, ch 44-70 */ - {4, 1}, /* group 2 5.2, ch 71-124 */ - {4, 1}, /* group 3 5.2, ch 125-200 */ - {3, 1} /* group 4 2.4, ch all */ -}; - -static s32 get_min_power_index(s32 rate_power_index, u32 band) -{ - if (!band) { - if ((rate_power_index & 7) <= 4) - return MIN_TX_GAIN_INDEX_52GHZ_EXT; - } - return MIN_TX_GAIN_INDEX; -} - -struct gain_entry { - u8 dsp; - u8 radio; -}; - -static const struct gain_entry gain_table[2][108] = { - /* 5.2GHz power gain index table */ - { - {123, 0x3F}, /* highest txpower */ - {117, 0x3F}, - {110, 0x3F}, - {104, 0x3F}, - {98, 0x3F}, - {110, 0x3E}, - {104, 0x3E}, - {98, 0x3E}, - {110, 0x3D}, - {104, 0x3D}, - {98, 0x3D}, - {110, 0x3C}, - {104, 0x3C}, - {98, 0x3C}, - {110, 0x3B}, - {104, 0x3B}, - {98, 0x3B}, - {110, 0x3A}, - {104, 0x3A}, - {98, 0x3A}, - {110, 0x39}, - {104, 0x39}, - {98, 0x39}, - {110, 0x38}, - {104, 0x38}, - {98, 0x38}, - {110, 0x37}, - {104, 0x37}, - {98, 0x37}, - {110, 0x36}, - {104, 0x36}, - {98, 0x36}, - {110, 0x35}, - {104, 0x35}, - {98, 0x35}, - {110, 0x34}, - {104, 0x34}, - {98, 0x34}, - {110, 0x33}, - {104, 0x33}, - {98, 0x33}, - {110, 0x32}, - {104, 0x32}, - {98, 0x32}, - {110, 0x31}, - {104, 0x31}, - {98, 0x31}, - {110, 0x30}, - {104, 0x30}, - {98, 0x30}, - {110, 0x25}, - {104, 0x25}, - {98, 0x25}, - {110, 0x24}, - {104, 0x24}, - {98, 0x24}, - {110, 0x23}, - {104, 0x23}, - {98, 0x23}, - {110, 0x22}, - {104, 0x18}, - {98, 0x18}, - {110, 0x17}, - {104, 0x17}, - {98, 0x17}, - {110, 0x16}, - {104, 0x16}, - {98, 0x16}, - {110, 0x15}, - {104, 0x15}, - {98, 0x15}, - {110, 0x14}, - {104, 0x14}, - {98, 0x14}, - {110, 0x13}, - {104, 0x13}, - {98, 0x13}, - {110, 0x12}, - {104, 0x08}, - {98, 0x08}, - {110, 0x07}, - {104, 0x07}, - {98, 0x07}, - {110, 0x06}, - {104, 0x06}, - {98, 0x06}, - {110, 0x05}, - {104, 0x05}, - {98, 0x05}, - {110, 0x04}, - {104, 0x04}, - {98, 0x04}, - {110, 0x03}, - {104, 0x03}, - {98, 0x03}, - {110, 0x02}, - {104, 0x02}, - {98, 0x02}, - {110, 0x01}, - {104, 0x01}, - {98, 0x01}, - {110, 0x00}, - {104, 0x00}, - {98, 0x00}, - {93, 0x00}, - {88, 0x00}, - {83, 0x00}, - {78, 0x00}, - }, - /* 2.4GHz power gain index table */ - { - {110, 0x3f}, /* highest txpower */ - {104, 0x3f}, - {98, 0x3f}, - {110, 0x3e}, - {104, 0x3e}, - {98, 0x3e}, - {110, 0x3d}, - {104, 0x3d}, - {98, 0x3d}, - {110, 0x3c}, - {104, 0x3c}, - {98, 0x3c}, - {110, 0x3b}, - {104, 0x3b}, - {98, 0x3b}, - {110, 0x3a}, - {104, 0x3a}, - {98, 0x3a}, - {110, 0x39}, - {104, 0x39}, - {98, 0x39}, - {110, 0x38}, - {104, 0x38}, - {98, 0x38}, - {110, 0x37}, - {104, 0x37}, - {98, 0x37}, - {110, 0x36}, - {104, 0x36}, - {98, 0x36}, - {110, 0x35}, - {104, 0x35}, - {98, 0x35}, - {110, 0x34}, - {104, 0x34}, - {98, 0x34}, - {110, 0x33}, - {104, 0x33}, - {98, 0x33}, - {110, 0x32}, - {104, 0x32}, - {98, 0x32}, - {110, 0x31}, - {104, 0x31}, - {98, 0x31}, - {110, 0x30}, - {104, 0x30}, - {98, 0x30}, - {110, 0x6}, - {104, 0x6}, - {98, 0x6}, - {110, 0x5}, - {104, 0x5}, - {98, 0x5}, - {110, 0x4}, - {104, 0x4}, - {98, 0x4}, - {110, 0x3}, - {104, 0x3}, - {98, 0x3}, - {110, 0x2}, - {104, 0x2}, - {98, 0x2}, - {110, 0x1}, - {104, 0x1}, - {98, 0x1}, - {110, 0x0}, - {104, 0x0}, - {98, 0x0}, - {97, 0}, - {96, 0}, - {95, 0}, - {94, 0}, - {93, 0}, - {92, 0}, - {91, 0}, - {90, 0}, - {89, 0}, - {88, 0}, - {87, 0}, - {86, 0}, - {85, 0}, - {84, 0}, - {83, 0}, - {82, 0}, - {81, 0}, - {80, 0}, - {79, 0}, - {78, 0}, - {77, 0}, - {76, 0}, - {75, 0}, - {74, 0}, - {73, 0}, - {72, 0}, - {71, 0}, - {70, 0}, - {69, 0}, - {68, 0}, - {67, 0}, - {66, 0}, - {65, 0}, - {64, 0}, - {63, 0}, - {62, 0}, - {61, 0}, - {60, 0}, - {59, 0}, - } -}; - -static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel, - u8 is_ht40, u8 ctrl_chan_high, - struct iwl4965_tx_power_db *tx_power_tbl) -{ - u8 saturation_power; - s32 target_power; - s32 user_target_power; - s32 power_limit; - s32 current_temp; - s32 reg_limit; - s32 current_regulatory; - s32 txatten_grp = CALIB_CH_GROUP_MAX; - int i; - int c; - const struct iwl_channel_info *ch_info = NULL; - struct iwl_eeprom_calib_ch_info ch_eeprom_info; - const struct iwl_eeprom_calib_measure *measurement; - s16 voltage; - s32 init_voltage; - s32 voltage_compensation; - s32 degrees_per_05db_num; - s32 degrees_per_05db_denom; - s32 factory_temp; - s32 temperature_comp[2]; - s32 factory_gain_index[2]; - s32 factory_actual_pwr[2]; - s32 power_index; - - /* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units - * are used for indexing into txpower table) */ - user_target_power = 2 * priv->tx_power_user_lmt; - - /* Get current (RXON) channel, band, width */ - IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band, - is_ht40); - - ch_info = iwl_get_channel_info(priv, priv->band, channel); - - if (!is_channel_valid(ch_info)) - return -EINVAL; - - /* get txatten group, used to select 1) thermal txpower adjustment - * and 2) mimo txpower balance between Tx chains. */ - txatten_grp = iwl4965_get_tx_atten_grp(channel); - if (txatten_grp < 0) { - IWL_ERR(priv, "Can't find txatten group for channel %d.\n", - channel); - return -EINVAL; - } - - IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n", - channel, txatten_grp); - - if (is_ht40) { - if (ctrl_chan_high) - channel -= 2; - else - channel += 2; - } - - /* hardware txpower limits ... - * saturation (clipping distortion) txpowers are in half-dBm */ - if (band) - saturation_power = priv->calib_info->saturation_power24; - else - saturation_power = priv->calib_info->saturation_power52; - - if (saturation_power < IWL_TX_POWER_SATURATION_MIN || - saturation_power > IWL_TX_POWER_SATURATION_MAX) { - if (band) - saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24; - else - saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52; - } - - /* regulatory txpower limits ... reg_limit values are in half-dBm, - * max_power_avg values are in dBm, convert * 2 */ - if (is_ht40) - reg_limit = ch_info->ht40_max_power_avg * 2; - else - reg_limit = ch_info->max_power_avg * 2; - - if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) || - (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) { - if (band) - reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24; - else - reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52; - } - - /* Interpolate txpower calibration values for this channel, - * based on factory calibration tests on spaced channels. */ - iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info); - - /* calculate tx gain adjustment based on power supply voltage */ - voltage = le16_to_cpu(priv->calib_info->voltage); - init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage); - voltage_compensation = - iwl4965_get_voltage_compensation(voltage, init_voltage); - - IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n", - init_voltage, - voltage, voltage_compensation); - - /* get current temperature (Celsius) */ - current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN); - current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX); - current_temp = KELVIN_TO_CELSIUS(current_temp); - - /* select thermal txpower adjustment params, based on channel group - * (same frequency group used for mimo txatten adjustment) */ - degrees_per_05db_num = - tx_power_cmp_tble[txatten_grp].degrees_per_05db_a; - degrees_per_05db_denom = - tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom; - - /* get per-chain txpower values from factory measurements */ - for (c = 0; c < 2; c++) { - measurement = &ch_eeprom_info.measurements[c][1]; - - /* txgain adjustment (in half-dB steps) based on difference - * between factory and current temperature */ - factory_temp = measurement->temperature; - iwl4965_math_div_round((current_temp - factory_temp) * - degrees_per_05db_denom, - degrees_per_05db_num, - &temperature_comp[c]); - - factory_gain_index[c] = measurement->gain_idx; - factory_actual_pwr[c] = measurement->actual_pow; - - IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c); - IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, " - "curr tmp %d, comp %d steps\n", - factory_temp, current_temp, - temperature_comp[c]); - - IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n", - factory_gain_index[c], - factory_actual_pwr[c]); - } - - /* for each of 33 bit-rates (including 1 for CCK) */ - for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) { - u8 is_mimo_rate; - union iwl4965_tx_power_dual_stream tx_power; - - /* for mimo, reduce each chain's txpower by half - * (3dB, 6 steps), so total output power is regulatory - * compliant. */ - if (i & 0x8) { - current_regulatory = reg_limit - - IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION; - is_mimo_rate = 1; - } else { - current_regulatory = reg_limit; - is_mimo_rate = 0; - } - - /* find txpower limit, either hardware or regulatory */ - power_limit = saturation_power - back_off_table[i]; - if (power_limit > current_regulatory) - power_limit = current_regulatory; - - /* reduce user's txpower request if necessary - * for this rate on this channel */ - target_power = user_target_power; - if (target_power > power_limit) - target_power = power_limit; - - IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n", - i, saturation_power - back_off_table[i], - current_regulatory, user_target_power, - target_power); - - /* for each of 2 Tx chains (radio transmitters) */ - for (c = 0; c < 2; c++) { - s32 atten_value; - - if (is_mimo_rate) - atten_value = - (s32)le32_to_cpu(priv->card_alive_init. - tx_atten[txatten_grp][c]); - else - atten_value = 0; - - /* calculate index; higher index means lower txpower */ - power_index = (u8) (factory_gain_index[c] - - (target_power - - factory_actual_pwr[c]) - - temperature_comp[c] - - voltage_compensation + - atten_value); - -/* IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n", - power_index); */ - - if (power_index < get_min_power_index(i, band)) - power_index = get_min_power_index(i, band); - - /* adjust 5 GHz index to support negative indexes */ - if (!band) - power_index += 9; - - /* CCK, rate 32, reduce txpower for CCK */ - if (i == POWER_TABLE_CCK_ENTRY) - power_index += - IWL_TX_POWER_CCK_COMPENSATION_C_STEP; - - /* stay within the table! */ - if (power_index > 107) { - IWL_WARN(priv, "txpower index %d > 107\n", - power_index); - power_index = 107; - } - if (power_index < 0) { - IWL_WARN(priv, "txpower index %d < 0\n", - power_index); - power_index = 0; - } - - /* fill txpower command for this rate/chain */ - tx_power.s.radio_tx_gain[c] = - gain_table[band][power_index].radio; - tx_power.s.dsp_predis_atten[c] = - gain_table[band][power_index].dsp; - - IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d " - "gain 0x%02x dsp %d\n", - c, atten_value, power_index, - tx_power.s.radio_tx_gain[c], - tx_power.s.dsp_predis_atten[c]); - } /* for each chain */ - - tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw); - - } /* for each rate */ - - return 0; -} - -/** - * iwl4965_send_tx_power - Configure the TXPOWER level user limit - * - * Uses the active RXON for channel, band, and characteristics (ht40, high) - * The power limit is taken from priv->tx_power_user_lmt. - */ -static int iwl4965_send_tx_power(struct iwl_priv *priv) -{ - struct iwl4965_txpowertable_cmd cmd = { 0 }; - int ret; - u8 band = 0; - bool is_ht40 = false; - u8 ctrl_chan_high = 0; - - if (test_bit(STATUS_SCANNING, &priv->status)) { - /* If this gets hit a lot, switch it to a BUG() and catch - * the stack trace to find out who is calling this during - * a scan. */ - IWL_WARN(priv, "TX Power requested while scanning!\n"); - return -EAGAIN; - } - - band = priv->band == IEEE80211_BAND_2GHZ; - - is_ht40 = is_ht40_channel(priv->active_rxon.flags); - - if (is_ht40 && - (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) - ctrl_chan_high = 1; - - cmd.band = band; - cmd.channel = priv->active_rxon.channel; - - ret = iwl4965_fill_txpower_tbl(priv, band, - le16_to_cpu(priv->active_rxon.channel), - is_ht40, ctrl_chan_high, &cmd.tx_power); - if (ret) - goto out; - - ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd); - -out: - return ret; -} - -static int iwl4965_send_rxon_assoc(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl4965_rxon_assoc_cmd rxon_assoc; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_ht_single_stream_basic_rates == - rxon2->ofdm_ht_single_stream_basic_rates) && - (rxon1->ofdm_ht_dual_stream_basic_rates == - rxon2->ofdm_ht_dual_stream_basic_rates) && - (rxon1->rx_chain == rxon2->rx_chain) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved = 0; - rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; - rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - - ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, - sizeof(rxon_assoc), &rxon_assoc, NULL); - if (ret) - return ret; - - return ret; -} - -#ifdef IEEE80211_CONF_CHANNEL_SWITCH -static int iwl4965_hw_channel_switch(struct iwl_priv *priv, u16 channel) -{ - int rc; - u8 band = 0; - bool is_ht40 = false; - u8 ctrl_chan_high = 0; - struct iwl4965_channel_switch_cmd cmd = { 0 }; - const struct iwl_channel_info *ch_info; - - band = priv->band == IEEE80211_BAND_2GHZ; - - ch_info = iwl_get_channel_info(priv, priv->band, channel); - - is_ht40 = is_ht40_channel(priv->staging_rxon.flags); - - if (is_ht40 && - (priv->active_rxon.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK)) - ctrl_chan_high = 1; - - cmd.band = band; - cmd.expect_beacon = 0; - cmd.channel = cpu_to_le16(channel); - cmd.rxon_flags = priv->active_rxon.flags; - cmd.rxon_filter_flags = priv->active_rxon.filter_flags; - cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time); - if (ch_info) - cmd.expect_beacon = is_channel_radar(ch_info); - else - cmd.expect_beacon = 1; - - rc = iwl4965_fill_txpower_tbl(priv, band, channel, is_ht40, - ctrl_chan_high, &cmd.tx_power); - if (rc) { - IWL_DEBUG_11H(priv, "error:%d fill txpower_tbl\n", rc); - return rc; - } - - rc = iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd); - return rc; -} -#endif - -/** - * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array - */ -static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt) -{ - struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int txq_id = txq->q.id; - int write_ptr = txq->q.write_ptr; - int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; - __le16 bc_ent; - - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - - bc_ent = cpu_to_le16(len & 0xFFF); - /* Set up byte count within first 256 entries */ - scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; - - /* If within first 64 entries, duplicate at end */ - if (write_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; -} - -/** - * sign_extend - Sign extend a value using specified bit as sign-bit - * - * Example: sign_extend(9, 3) would return -7 as bit3 of 1001b is 1 - * and bit0..2 is 001b which when sign extended to 1111111111111001b is -7. - * - * @param oper value to sign extend - * @param index 0 based bit index (0<=index<32) to sign bit - */ -static s32 sign_extend(u32 oper, int index) -{ - u8 shift = 31 - index; - - return (s32)(oper << shift) >> shift; -} - -/** - * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin) - * @statistics: Provides the temperature reading from the uCode - * - * A return of <0 indicates bogus data in the statistics - */ -static int iwl4965_hw_get_temperature(struct iwl_priv *priv) -{ - s32 temperature; - s32 vt; - s32 R1, R2, R3; - u32 R4; - - if (test_bit(STATUS_TEMPERATURE, &priv->status) && - (priv->statistics.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK)) { - IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n"); - R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]); - R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]); - R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]); - R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]); - } else { - IWL_DEBUG_TEMP(priv, "Running temperature calibration\n"); - R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]); - R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]); - R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]); - R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]); - } - - /* - * Temperature is only 23 bits, so sign extend out to 32. - * - * NOTE If we haven't received a statistics notification yet - * with an updated temperature, use R4 provided to us in the - * "initialize" ALIVE response. - */ - if (!test_bit(STATUS_TEMPERATURE, &priv->status)) - vt = sign_extend(R4, 23); - else - vt = sign_extend( - le32_to_cpu(priv->statistics.general.temperature), 23); - - IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt); - - if (R3 == R1) { - IWL_ERR(priv, "Calibration conflict R1 == R3\n"); - return -1; - } - - /* Calculate temperature in degrees Kelvin, adjust by 97%. - * Add offset to center the adjustment around 0 degrees Centigrade. */ - temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2); - temperature /= (R3 - R1); - temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET; - - IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n", - temperature, KELVIN_TO_CELSIUS(temperature)); - - return temperature; -} - -/* Adjust Txpower only if temperature variance is greater than threshold. */ -#define IWL_TEMPERATURE_THRESHOLD 3 - -/** - * iwl4965_is_temp_calib_needed - determines if new calibration is needed - * - * If the temperature changed has changed sufficiently, then a recalibration - * is needed. - * - * Assumes caller will replace priv->last_temperature once calibration - * executed. - */ -static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv) -{ - int temp_diff; - - if (!test_bit(STATUS_STATISTICS, &priv->status)) { - IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n"); - return 0; - } - - temp_diff = priv->temperature - priv->last_temperature; - - /* get absolute value */ - if (temp_diff < 0) { - IWL_DEBUG_POWER(priv, "Getting cooler, delta %d, \n", temp_diff); - temp_diff = -temp_diff; - } else if (temp_diff == 0) - IWL_DEBUG_POWER(priv, "Same temp, \n"); - else - IWL_DEBUG_POWER(priv, "Getting warmer, delta %d, \n", temp_diff); - - if (temp_diff < IWL_TEMPERATURE_THRESHOLD) { - IWL_DEBUG_POWER(priv, "Thermal txpower calib not needed\n"); - return 0; - } - - IWL_DEBUG_POWER(priv, "Thermal txpower calib needed\n"); - - return 1; -} - -static void iwl4965_temperature_calib(struct iwl_priv *priv) -{ - s32 temp; - - temp = iwl4965_hw_get_temperature(priv); - if (temp < 0) - return; - - if (priv->temperature != temp) { - if (priv->temperature) - IWL_DEBUG_TEMP(priv, "Temperature changed " - "from %dC to %dC\n", - KELVIN_TO_CELSIUS(priv->temperature), - KELVIN_TO_CELSIUS(temp)); - else - IWL_DEBUG_TEMP(priv, "Temperature " - "initialized to %dC\n", - KELVIN_TO_CELSIUS(temp)); - } - - priv->temperature = temp; - iwl_tt_handler(priv); - set_bit(STATUS_TEMPERATURE, &priv->status); - - if (!priv->disable_tx_power_cal && - unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && - iwl4965_is_temp_calib_needed(priv)) - queue_work(priv->workqueue, &priv->txpower_work); -} - -/** - * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration - */ -static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, - u16 txq_id) -{ - /* Simply stop the queue, but don't change any configuration; - * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv, - IWL49_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); -} - -/** - * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE - * priv->lock must be held by the caller - */ -static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) -{ - if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || - (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARN(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL49_FIRST_AMPDU_QUEUE, - IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); - return -EINVAL; - } - - iwl4965_tx_queue_stop_scheduler(priv, txq_id); - - iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); - - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); - - iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv, txq_id); - iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - - return 0; -} - -/** - * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue - */ -static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, - u16 txq_id) -{ - u32 tbl_dw_addr; - u32 tbl_dw; - u16 scd_q2ratid; - - scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; - - tbl_dw_addr = priv->scd_base_addr + - IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); - - tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); - - if (txq_id & 0x1) - tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); - else - tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - - iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); - - return 0; -} - - -/** - * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue - * - * NOTE: txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE, - * i.e. it must be one of the higher queues used for aggregation - */ -static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx) -{ - unsigned long flags; - u16 ra_tid; - - if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) || - (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARN(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL49_FIRST_AMPDU_QUEUE, - IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1); - return -EINVAL; - } - - ra_tid = BUILD_RAxTID(sta_id, tid); - - /* Modify device's station table to Tx this TID */ - iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); - - spin_lock_irqsave(&priv->lock, flags); - - /* Stop this Tx queue before configuring it */ - iwl4965_tx_queue_stop_scheduler(priv, txq_id); - - /* Map receiver-address / traffic-ID to this queue */ - iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id); - - /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id)); - - /* Place first TFD at index corresponding to start sequence number. - * Assumes that ssn_idx is valid (!= 0xFFF) */ - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx); - - /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(priv, - priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id), - (SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) & - IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK); - - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32), - (SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) - & IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK); - - iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id)); - - /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - - -static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len) -{ - switch (cmd_id) { - case REPLY_RXON: - return (u16) sizeof(struct iwl4965_rxon_cmd); - default: - return len; - } -} - -static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) -{ - struct iwl4965_addsta_cmd *addsta = (struct iwl4965_addsta_cmd *)data; - addsta->mode = cmd->mode; - memcpy(&addsta->sta, &cmd->sta, sizeof(struct sta_id_modify)); - memcpy(&addsta->key, &cmd->key, sizeof(struct iwl4965_keyinfo)); - addsta->station_flags = cmd->station_flags; - addsta->station_flags_msk = cmd->station_flags_msk; - addsta->tid_disable_tx = cmd->tid_disable_tx; - addsta->add_immediate_ba_tid = cmd->add_immediate_ba_tid; - addsta->remove_immediate_ba_tid = cmd->remove_immediate_ba_tid; - addsta->add_immediate_ba_ssn = cmd->add_immediate_ba_ssn; - addsta->reserved1 = cpu_to_le16(0); - addsta->reserved2 = cpu_to_le32(0); - - return (u16)sizeof(struct iwl4965_addsta_cmd); -} - -static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp) -{ - return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN; -} - -/** - * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue - */ -static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwl4965_tx_resp *tx_resp, - int txq_id, u16 start_idx) -{ - u16 status; - struct agg_tx_status *frame_status = tx_resp->u.agg_status; - struct ieee80211_tx_info *info = NULL; - struct ieee80211_hdr *hdr = NULL; - u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - int i, sh, idx; - u16 seq; - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); - - agg->frame_count = tx_resp->frame_count; - agg->start_idx = start_idx; - agg->rate_n_flags = rate_n_flags; - agg->bitmap = 0; - - /* num frames attempted by Tx command */ - if (agg->frame_count == 1) { - /* Only one frame was attempted; no block-ack will arrive */ - status = le16_to_cpu(frame_status[0].status); - idx = start_idx; - - /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", - agg->frame_count, agg->start_idx, idx); - - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_is_tx_success(status) ? - IEEE80211_TX_STAT_ACK : 0; - iwl_hwrate_to_tx_control(priv, rate_n_flags, info); - /* FIXME: code repetition end */ - - IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", - status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); - - agg->wait_for_ba = 0; - } else { - /* Two or more frames were attempted; expect block-ack */ - u64 bitmap = 0; - int start = agg->start_idx; - - /* Construct bit-map of pending frames within Tx window */ - for (i = 0; i < agg->frame_count; i++) { - u16 sc; - status = le16_to_cpu(frame_status[i].status); - seq = le16_to_cpu(frame_status[i].sequence); - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); - - if (status & (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; - - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", - agg->frame_count, txq_id, idx); - - hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); - if (!hdr) { - IWL_ERR(priv, - "BUG_ON idx doesn't point to valid skb" - " idx=%d, txq_id=%d\n", idx, txq_id); - return -1; - } - - sc = le16_to_cpu(hdr->seq_ctrl); - if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IWL_ERR(priv, - "BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", - idx, SEQ_TO_SN(sc), hdr->seq_ctrl); - return -1; - } - - IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", - i, idx, SEQ_TO_SN(sc)); - - sh = idx - start; - if (sh > 64) { - sh = (start - idx) + 0xff; - bitmap = bitmap << sh; - sh = 0; - start = idx; - } else if (sh < -64) - sh = 0xff - (start - idx); - else if (sh < 0) { - sh = start - idx; - start = idx; - bitmap = bitmap << sh; - sh = 0; - } - bitmap |= 1ULL << sh; - IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", - start, (unsigned long long)bitmap); - } - - agg->bitmap = bitmap; - agg->start_idx = start; - IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", - agg->frame_count, agg->start_idx, - (unsigned long long)agg->bitmap); - - if (bitmap) - agg->wait_for_ba = 1; - } - return 0; -} - -/** - * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response - */ -static void iwl4965_rx_reply_tx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_hdr *hdr; - struct ieee80211_tx_info *info; - struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le32_to_cpu(tx_resp->u.status); - int tid = MAX_TID_COUNT - 1; - int sta_id; - int freed; - u8 *qc = NULL; - - if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " - "is out of range [0-%d] %d %d\n", txq_id, - index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - memset(&info->status, 0, sizeof(info->status)); - - hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); - if (ieee80211_is_data_qos(hdr->frame_control)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - } - - sta_id = iwl_get_ra_sta_id(priv, hdr); - if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) { - IWL_ERR(priv, "Station not known\n"); - return; - } - - if (txq->sched_retry) { - const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); - struct iwl_ht_agg *agg = NULL; - - WARN_ON(!qc); - - agg = &priv->stations[sta_id].tid[tid].agg; - - iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - - /* check if BAR is needed */ - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (txq->q.read_ptr != (scd_ssn & 0xff)) { - index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn " - "%d index %d\n", scd_ssn , index); - freed = iwl_tx_queue_reclaim(priv, txq_id, index); - if (qc) - iwl_free_tfds_in_queue(priv, sta_id, - tid, freed); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } - } - } else { - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags |= iwl_is_tx_success(status) ? - IEEE80211_TX_STAT_ACK : 0; - iwl_hwrate_to_tx_control(priv, - le32_to_cpu(tx_resp->rate_n_flags), - info); - - IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) " - "rate_n_flags 0x%x retries %d\n", - txq_id, - iwl_get_tx_fail_reason(status), status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - freed = iwl_tx_queue_reclaim(priv, txq_id, index); - if (qc && likely(sta_id != IWL_INVALID_STATION)) - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - else if (sta_id == IWL_INVALID_STATION) - IWL_DEBUG_TX_REPLY(priv, "Station not known\n"); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); - } - if (qc && likely(sta_id != IWL_INVALID_STATION)) - iwl_txq_check_empty(priv, sta_id, tid, txq_id); - - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); -} - -static int iwl4965_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp) -{ - /* data from PHY/DSP regarding signal strength, etc., - * contents are always there, not configurable by host. */ - struct iwl4965_rx_non_cfg_phy *ncphy = - (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf; - u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK) - >> IWL49_AGC_DB_POS; - - u32 valid_antennae = - (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK) - >> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET; - u8 max_rssi = 0; - u32 i; - - /* Find max rssi among 3 possible receivers. - * These values are measured by the digital signal processor (DSP). - * They should stay fairly constant even as the signal strength varies, - * if the radio's automatic gain control (AGC) is working right. - * AGC value (see below) will provide the "interesting" info. */ - for (i = 0; i < 3; i++) - if (valid_antennae & (1 << i)) - max_rssi = max(ncphy->rssi_info[i << 1], max_rssi); - - IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", - ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4], - max_rssi, agc); - - /* dBm = max_rssi dB - agc dB - constant. - * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL49_RSSI_OFFSET; -} - - -/* Set up 4965-specific Rx frame reply handlers */ -static void iwl4965_rx_handler_setup(struct iwl_priv *priv) -{ - /* Legacy Rx frames */ - priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; - /* Tx response */ - priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; -} - -static void iwl4965_setup_deferred_work(struct iwl_priv *priv) -{ - INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work); -} - -static void iwl4965_cancel_deferred_work(struct iwl_priv *priv) -{ - cancel_work_sync(&priv->txpower_work); -} - -#define IWL4965_UCODE_GET(item) \ -static u32 iwl4965_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - return le32_to_cpu(ucode->u.v1.item); \ -} - -static u32 iwl4965_ucode_get_header_size(u32 api_ver) -{ - return UCODE_HEADER_SIZE(1); -} -static u32 iwl4965_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return 0; -} -static u8 *iwl4965_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - return (u8 *) ucode->u.v1.data; -} - -IWL4965_UCODE_GET(inst_size); -IWL4965_UCODE_GET(data_size); -IWL4965_UCODE_GET(init_size); -IWL4965_UCODE_GET(init_data_size); -IWL4965_UCODE_GET(boot_size); - -static struct iwl_hcmd_ops iwl4965_hcmd = { - .rxon_assoc = iwl4965_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, -}; - -static struct iwl_ucode_ops iwl4965_ucode = { - .get_header_size = iwl4965_ucode_get_header_size, - .get_build = iwl4965_ucode_get_build, - .get_inst_size = iwl4965_ucode_get_inst_size, - .get_data_size = iwl4965_ucode_get_data_size, - .get_init_size = iwl4965_ucode_get_init_size, - .get_init_data_size = iwl4965_ucode_get_init_data_size, - .get_boot_size = iwl4965_ucode_get_boot_size, - .get_data = iwl4965_ucode_get_data, -}; -static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = { - .get_hcmd_size = iwl4965_get_hcmd_size, - .build_addsta_hcmd = iwl4965_build_addsta_hcmd, - .chain_noise_reset = iwl4965_chain_noise_reset, - .gain_computation = iwl4965_gain_computation, - .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag, - .calc_rssi = iwl4965_calc_rssi, -}; - -static struct iwl_lib_ops iwl4965_lib = { - .set_hw_params = iwl4965_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl, - .txq_set_sched = iwl4965_txq_set_sched, - .txq_agg_enable = iwl4965_txq_agg_enable, - .txq_agg_disable = iwl4965_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl4965_rx_handler_setup, - .setup_deferred_work = iwl4965_setup_deferred_work, - .cancel_deferred_work = iwl4965_cancel_deferred_work, - .is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr, - .alive_notify = iwl4965_alive_notify, - .init_alive_start = iwl4965_init_alive_start, - .load_ucode = iwl4965_load_bsm, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .apm_ops = { - .init = iwl4965_apm_init, - .reset = iwl4965_apm_reset, - .stop = iwl4965_apm_stop, - .config = iwl4965_nic_config, - .set_pwr_src = iwl_set_pwr_src, - }, - .eeprom_ops = { - .regulatory_bands = { - EEPROM_REGULATORY_BAND_1_CHANNELS, - EEPROM_REGULATORY_BAND_2_CHANNELS, - EEPROM_REGULATORY_BAND_3_CHANNELS, - EEPROM_REGULATORY_BAND_4_CHANNELS, - EEPROM_REGULATORY_BAND_5_CHANNELS, - EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS, - EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS - }, - .verify_signature = iwlcore_eeprom_verify_signature, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl4965_eeprom_calib_version, - .query_addr = iwlcore_eeprom_query_addr, - }, - .send_tx_power = iwl4965_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .post_associate = iwl_post_associate, - .config_ap = iwl_config_ap, - .isr = iwl_isr_legacy, - .temp_ops = { - .temperature = iwl4965_temperature_calib, - .set_ct_kill = iwl4965_set_ct_threshold, - }, -}; - -static struct iwl_ops iwl4965_ops = { - .ucode = &iwl4965_ucode, - .lib = &iwl4965_lib, - .hcmd = &iwl4965_hcmd, - .utils = &iwl4965_hcmd_utils, -}; - -struct iwl_cfg iwl4965_agn_cfg = { - .name = "4965AGN", - .fw_name_pre = IWL4965_FW_PRE, - .ucode_api_max = IWL4965_UCODE_API_MAX, - .ucode_api_min = IWL4965_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .eeprom_size = IWL4965_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_4965_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION, - .ops = &iwl4965_ops, - .mod_params = &iwl4965_mod_params, - .use_isr_legacy = true, - .ht_greenfield_support = false, - .broken_powersave = true, -}; - -/* Module firmware */ -MODULE_FIRMWARE(IWL4965_MODULE_FIRMWARE(IWL4965_UCODE_API_MAX)); - -module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444); -MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); -MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); -module_param_named( - disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); -MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); - -module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, 0444); -MODULE_PARM_DESC(queues_num, "number of hw queues."); -/* 11n */ -module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, 0444); -MODULE_PARM_DESC(11n_disable, "disable 11n functionality"); -module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K, int, 0444); -MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); - -module_param_named(fw_restart4965, iwl4965_mod_params.restart_fw, int, 0444); -MODULE_PARM_DESC(fw_restart4965, "restart firmware in case of error"); diff --git a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h b/drivers/net/wireless/iwlwifi/iwl-5000-hw.h deleted file mode 100644 index bc056e9ab85f..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-5000-hw.h +++ /dev/null @@ -1,121 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -/* - * Please use this file (iwl-5000-hw.h) only for hardware-related definitions. - * Use iwl-5000-commands.h for uCode API definitions. - */ - -#ifndef __iwl_5000_hw_h__ -#define __iwl_5000_hw_h__ - -#define IWL50_RTC_INST_LOWER_BOUND (0x000000) -#define IWL50_RTC_INST_UPPER_BOUND (0x020000) - -#define IWL50_RTC_DATA_LOWER_BOUND (0x800000) -#define IWL50_RTC_DATA_UPPER_BOUND (0x80C000) - -#define IWL50_RTC_INST_SIZE (IWL50_RTC_INST_UPPER_BOUND - \ - IWL50_RTC_INST_LOWER_BOUND) -#define IWL50_RTC_DATA_SIZE (IWL50_RTC_DATA_UPPER_BOUND - \ - IWL50_RTC_DATA_LOWER_BOUND) - -/* EEPROM */ -#define IWL_5000_EEPROM_IMG_SIZE 2048 - -#define IWL50_CMD_FIFO_NUM 7 -#define IWL50_NUM_QUEUES 20 -#define IWL50_NUM_AMPDU_QUEUES 10 -#define IWL50_FIRST_AMPDU_QUEUE 10 - -/* 5150 only */ -#define IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF (-5) - -static inline s32 iwl_temp_calib_to_offset(struct iwl_priv *priv) -{ - u16 temperature, voltage; - __le16 *temp_calib = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_TEMPERATURE); - - temperature = le16_to_cpu(temp_calib[0]); - voltage = le16_to_cpu(temp_calib[1]); - - /* offset = temp - volt / coeff */ - return (s32)(temperature - voltage / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF); -} - -/* Fixed (non-configurable) rx data from phy */ - -/** - * struct iwl5000_schedq_bc_tbl scheduler byte count table - * base physical address of iwl5000_shared - * is provided to SCD_DRAM_BASE_ADDR - * @tfd_offset 0-12 - tx command byte count - * 12-16 - station index - */ -struct iwl5000_scd_bc_tbl { - __le16 tfd_offset[TFD_QUEUE_BC_SIZE]; -} __attribute__ ((packed)); - - -#endif /* __iwl_5000_hw_h__ */ - diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c deleted file mode 100644 index 1f423f2f6a25..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ /dev/null @@ -1,1793 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-sta.h" -#include "iwl-helpers.h" -#include "iwl-5000-hw.h" -#include "iwl-6000-hw.h" - -/* Highest firmware API version supported */ -#define IWL5000_UCODE_API_MAX 2 -#define IWL5150_UCODE_API_MAX 2 - -/* Lowest firmware API version supported */ -#define IWL5000_UCODE_API_MIN 1 -#define IWL5150_UCODE_API_MIN 1 - -#define IWL5000_FW_PRE "iwlwifi-5000-" -#define _IWL5000_MODULE_FIRMWARE(api) IWL5000_FW_PRE #api ".ucode" -#define IWL5000_MODULE_FIRMWARE(api) _IWL5000_MODULE_FIRMWARE(api) - -#define IWL5150_FW_PRE "iwlwifi-5150-" -#define _IWL5150_MODULE_FIRMWARE(api) IWL5150_FW_PRE #api ".ucode" -#define IWL5150_MODULE_FIRMWARE(api) _IWL5150_MODULE_FIRMWARE(api) - -static const u16 iwl5000_default_queue_to_tx_fifo[] = { - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, - IWL50_CMD_FIFO_NUM, - IWL_TX_FIFO_HCCA_1, - IWL_TX_FIFO_HCCA_2 -}; - -/* FIXME: same implementation as 4965 */ -static int iwl5000_apm_stop_master(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - - /* set stop master bit */ - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); - - iwl_poll_direct_bit(priv, CSR_RESET, - CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); - - spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_INFO(priv, "stop master\n"); - - return 0; -} - - -int iwl5000_apm_init(struct iwl_priv *priv) -{ - int ret = 0; - - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER); - - /* disable L0s without affecting L1 :don't wait for ICH L0s bug W/A) */ - iwl_set_bit(priv, CSR_GIO_CHICKEN_BITS, - CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX); - - /* Set FH wait threshold to maximum (HW error during stress W/A) */ - iwl_set_bit(priv, CSR_DBG_HPET_MEM_REG, CSR_DBG_HPET_MEM_REG_VAL); - - /* enable HAP INTA to move device L1a -> L0s */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A); - - if (priv->cfg->need_pll_cfg) - iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); - - /* set "initialization complete" bit to move adapter - * D0U* --> D0A* state */ - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - /* wait for clock stabilization */ - ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (ret < 0) { - IWL_DEBUG_INFO(priv, "Failed to init the card\n"); - return ret; - } - - /* enable DMA */ - iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); - - udelay(20); - - /* disable L1-Active */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); - - return ret; -} - -/* FIXME: this is identical to 4965 */ -void iwl5000_apm_stop(struct iwl_priv *priv) -{ - unsigned long flags; - - iwl5000_apm_stop_master(priv); - - spin_lock_irqsave(&priv->lock, flags); - - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - - udelay(10); - - /* clear "init complete" move adapter D0A* --> D0U state */ - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - spin_unlock_irqrestore(&priv->lock, flags); -} - - -int iwl5000_apm_reset(struct iwl_priv *priv) -{ - int ret = 0; - - iwl5000_apm_stop_master(priv); - - iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET); - - udelay(10); - - - /* FIXME: put here L1A -L0S w/a */ - - if (priv->cfg->need_pll_cfg) - iwl_set_bit(priv, CSR_ANA_PLL_CFG, CSR50_ANA_PLL_CFG_VAL); - - /* set "initialization complete" bit to move adapter - * D0U* --> D0A* state */ - iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - /* wait for clock stabilization */ - ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000); - if (ret < 0) { - IWL_DEBUG_INFO(priv, "Failed to init the card\n"); - goto out; - } - - /* enable DMA */ - iwl_write_prph(priv, APMG_CLK_EN_REG, APMG_CLK_VAL_DMA_CLK_RQT); - - udelay(20); - - /* disable L1-Active */ - iwl_set_bits_prph(priv, APMG_PCIDEV_STT_REG, - APMG_PCIDEV_STT_VAL_L1_ACT_DIS); -out: - - return ret; -} - - -/* NIC configuration for 5000 series and up */ -void iwl5000_nic_config(struct iwl_priv *priv) -{ - unsigned long flags; - u16 radio_cfg; - u16 lctl; - - spin_lock_irqsave(&priv->lock, flags); - - lctl = iwl_pcie_link_ctl(priv); - - /* HW bug W/A */ - /* L1-ASPM is enabled by BIOS */ - if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) == PCI_CFG_LINK_CTRL_VAL_L1_EN) - /* L1-APSM enabled: disable L0S */ - iwl_set_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - else - /* L1-ASPM disabled: enable L0S */ - iwl_clear_bit(priv, CSR_GIO_REG, CSR_GIO_REG_VAL_L0S_ENABLED); - - radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG); - - /* write radio config values to register */ - if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) < EEPROM_5000_RF_CFG_TYPE_MAX) - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - EEPROM_RF_CFG_TYPE_MSK(radio_cfg) | - EEPROM_RF_CFG_STEP_MSK(radio_cfg) | - EEPROM_RF_CFG_DASH_MSK(radio_cfg)); - - /* set CSR_HW_CONFIG_REG for uCode use */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI | - CSR_HW_IF_CONFIG_REG_BIT_MAC_SI); - - /* W/A : NIC is stuck in a reset state after Early PCIe power off - * (PCIe power is lost before PERST# is asserted), - * causing ME FW to lose ownership and not being able to obtain it back. - */ - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS, - ~APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS); - - - spin_unlock_irqrestore(&priv->lock, flags); -} - - -/* - * EEPROM - */ -static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address) -{ - u16 offset = 0; - - if ((address & INDIRECT_ADDRESS) == 0) - return address; - - switch (address & INDIRECT_TYPE_MSK) { - case INDIRECT_HOST: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_HOST); - break; - case INDIRECT_GENERAL: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_GENERAL); - break; - case INDIRECT_REGULATORY: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_REGULATORY); - break; - case INDIRECT_CALIBRATION: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_CALIBRATION); - break; - case INDIRECT_PROCESS_ADJST: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_PROCESS_ADJST); - break; - case INDIRECT_OTHERS: - offset = iwl_eeprom_query16(priv, EEPROM_5000_LINK_OTHERS); - break; - default: - IWL_ERR(priv, "illegal indirect type: 0x%X\n", - address & INDIRECT_TYPE_MSK); - break; - } - - /* translate the offset from words to byte */ - return (address & ADDRESS_MSK) + (offset << 1); -} - -u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv) -{ - struct iwl_eeprom_calib_hdr { - u8 version; - u8 pa_type; - u16 voltage; - } *hdr; - - hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv, - EEPROM_5000_CALIB_ALL); - return hdr->version; - -} - -static void iwl5000_gain_computation(struct iwl_priv *priv, - u32 average_noise[NUM_RX_CHAINS], - u16 min_average_noise_antenna_i, - u32 min_average_noise) -{ - int i; - s32 delta_g; - struct iwl_chain_noise_data *data = &priv->chain_noise_data; - - /* Find Gain Code for the antennas B and C */ - for (i = 1; i < NUM_RX_CHAINS; i++) { - if ((data->disconn_array[i])) { - data->delta_gain_code[i] = 0; - continue; - } - delta_g = (1000 * ((s32)average_noise[0] - - (s32)average_noise[i])) / 1500; - /* bound gain by 2 bits value max, 3rd bit is sign */ - data->delta_gain_code[i] = - min(abs(delta_g), (long) CHAIN_NOISE_MAX_DELTA_GAIN_CODE); - - if (delta_g < 0) - /* set negative sign */ - data->delta_gain_code[i] |= (1 << 2); - } - - IWL_DEBUG_CALIB(priv, "Delta gains: ANT_B = %d ANT_C = %d\n", - data->delta_gain_code[1], data->delta_gain_code[2]); - - if (!data->radio_write) { - struct iwl_calib_chain_noise_gain_cmd cmd; - - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD; - cmd.hdr.first_group = 0; - cmd.hdr.groups_num = 1; - cmd.hdr.data_valid = 1; - cmd.delta_gain_1 = data->delta_gain_code[1]; - cmd.delta_gain_2 = data->delta_gain_code[2]; - iwl_send_cmd_pdu_async(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd, NULL); - - data->radio_write = 1; - data->state = IWL_CHAIN_NOISE_CALIBRATED; - } - - data->chain_noise_a = 0; - data->chain_noise_b = 0; - data->chain_noise_c = 0; - data->chain_signal_a = 0; - data->chain_signal_b = 0; - data->chain_signal_c = 0; - data->beacon_count = 0; -} - -static void iwl5000_chain_noise_reset(struct iwl_priv *priv) -{ - struct iwl_chain_noise_data *data = &priv->chain_noise_data; - int ret; - - if ((data->state == IWL_CHAIN_NOISE_ALIVE) && iwl_is_associated(priv)) { - struct iwl_calib_chain_noise_reset_cmd cmd; - memset(&cmd, 0, sizeof(cmd)); - - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD; - cmd.hdr.first_group = 0; - cmd.hdr.groups_num = 1; - cmd.hdr.data_valid = 1; - ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD, - sizeof(cmd), &cmd); - if (ret) - IWL_ERR(priv, - "Could not send REPLY_PHY_CALIBRATION_CMD\n"); - data->state = IWL_CHAIN_NOISE_ACCUMULATE; - IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n"); - } -} - -void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags) -{ - if ((info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) || - (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT)) - *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK; - else - *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK; -} - -static struct iwl_sensitivity_ranges iwl5000_sensitivity = { - .min_nrg_cck = 95, - .max_nrg_cck = 0, /* not used, set to 0 */ - .auto_corr_min_ofdm = 90, - .auto_corr_min_ofdm_mrc = 170, - .auto_corr_min_ofdm_x1 = 120, - .auto_corr_min_ofdm_mrc_x1 = 240, - - .auto_corr_max_ofdm = 120, - .auto_corr_max_ofdm_mrc = 210, - .auto_corr_max_ofdm_x1 = 155, - .auto_corr_max_ofdm_mrc_x1 = 290, - - .auto_corr_min_cck = 125, - .auto_corr_max_cck = 200, - .auto_corr_min_cck_mrc = 170, - .auto_corr_max_cck_mrc = 400, - .nrg_th_cck = 95, - .nrg_th_ofdm = 95, -}; - -static struct iwl_sensitivity_ranges iwl5150_sensitivity = { - .min_nrg_cck = 95, - .max_nrg_cck = 0, /* not used, set to 0 */ - .auto_corr_min_ofdm = 90, - .auto_corr_min_ofdm_mrc = 170, - .auto_corr_min_ofdm_x1 = 105, - .auto_corr_min_ofdm_mrc_x1 = 220, - - .auto_corr_max_ofdm = 120, - .auto_corr_max_ofdm_mrc = 210, - /* max = min for performance bug in 5150 DSP */ - .auto_corr_max_ofdm_x1 = 105, - .auto_corr_max_ofdm_mrc_x1 = 220, - - .auto_corr_min_cck = 125, - .auto_corr_max_cck = 200, - .auto_corr_min_cck_mrc = 170, - .auto_corr_max_cck_mrc = 400, - .nrg_th_cck = 95, - .nrg_th_ofdm = 95, -}; - -const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, - size_t offset) -{ - u32 address = eeprom_indirect_address(priv, offset); - BUG_ON(address >= priv->cfg->eeprom_size); - return &priv->eeprom[address]; -} - -static void iwl5150_set_ct_threshold(struct iwl_priv *priv) -{ - const s32 volt2temp_coef = IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF; - s32 threshold = (s32)CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY) - - iwl_temp_calib_to_offset(priv); - - priv->hw_params.ct_kill_threshold = threshold * volt2temp_coef; -} - -static void iwl5000_set_ct_threshold(struct iwl_priv *priv) -{ - /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD_LEGACY; -} - -/* - * Calibration - */ -static int iwl5000_set_Xtal_calib(struct iwl_priv *priv) -{ - struct iwl_calib_xtal_freq_cmd cmd; - __le16 *xtal_calib = - (__le16 *)iwl_eeprom_query_addr(priv, EEPROM_5000_XTAL); - - cmd.hdr.op_code = IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD; - cmd.hdr.first_group = 0; - cmd.hdr.groups_num = 1; - cmd.hdr.data_valid = 1; - cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]); - cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]); - return iwl_calib_set(&priv->calib_results[IWL_CALIB_XTAL], - (u8 *)&cmd, sizeof(cmd)); -} - -static int iwl5000_send_calib_cfg(struct iwl_priv *priv) -{ - struct iwl_calib_cfg_cmd calib_cfg_cmd; - struct iwl_host_cmd cmd = { - .id = CALIBRATION_CFG_CMD, - .len = sizeof(struct iwl_calib_cfg_cmd), - .data = &calib_cfg_cmd, - }; - - memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd)); - calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL; - calib_cfg_cmd.ucd_calib_cfg.flags = IWL_CALIB_INIT_CFG_ALL; - - return iwl_send_cmd(priv, &cmd); -} - -static void iwl5000_rx_calib_result(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw; - int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - int index; - - /* reduce the size of the length field itself */ - len -= 4; - - /* Define the order in which the results will be sent to the runtime - * uCode. iwl_send_calib_results sends them in a row according to their - * index. We sort them here */ - switch (hdr->op_code) { - case IWL_PHY_CALIBRATE_DC_CMD: - index = IWL_CALIB_DC; - break; - case IWL_PHY_CALIBRATE_LO_CMD: - index = IWL_CALIB_LO; - break; - case IWL_PHY_CALIBRATE_TX_IQ_CMD: - index = IWL_CALIB_TX_IQ; - break; - case IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD: - index = IWL_CALIB_TX_IQ_PERD; - break; - case IWL_PHY_CALIBRATE_BASE_BAND_CMD: - index = IWL_CALIB_BASE_BAND; - break; - default: - IWL_ERR(priv, "Unknown calibration notification %d\n", - hdr->op_code); - return; - } - iwl_calib_set(&priv->calib_results[index], pkt->u.raw, len); -} - -static void iwl5000_rx_calib_complete(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - IWL_DEBUG_INFO(priv, "Init. calibration is completed, restarting fw.\n"); - queue_work(priv->workqueue, &priv->restart); -} - -/* - * ucode - */ -static int iwl5000_load_section(struct iwl_priv *priv, - struct fw_desc *image, - u32 dst_addr) -{ - dma_addr_t phy_addr = image->p_addr; - u32 byte_cnt = image->len; - - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE); - - iwl_write_direct32(priv, - FH_SRVC_CHNL_SRAM_ADDR_REG(FH_SRVC_CHNL), dst_addr); - - iwl_write_direct32(priv, - FH_TFDIB_CTRL0_REG(FH_SRVC_CHNL), - phy_addr & FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK); - - iwl_write_direct32(priv, - FH_TFDIB_CTRL1_REG(FH_SRVC_CHNL), - (iwl_get_dma_hi_addr(phy_addr) - << FH_MEM_TFDIB_REG1_ADDR_BITSHIFT) | byte_cnt); - - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_BUF_STS_REG(FH_SRVC_CHNL), - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM | - 1 << FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX | - FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID); - - iwl_write_direct32(priv, - FH_TCSR_CHNL_TX_CONFIG_REG(FH_SRVC_CHNL), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE | - FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD); - - return 0; -} - -static int iwl5000_load_given_ucode(struct iwl_priv *priv, - struct fw_desc *inst_image, - struct fw_desc *data_image) -{ - int ret = 0; - - ret = iwl5000_load_section(priv, inst_image, - IWL50_RTC_INST_LOWER_BOUND); - if (ret) - return ret; - - IWL_DEBUG_INFO(priv, "INST uCode section being loaded...\n"); - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - priv->ucode_write_complete, 5 * HZ); - if (ret == -ERESTARTSYS) { - IWL_ERR(priv, "Could not load the INST uCode section due " - "to interrupt\n"); - return ret; - } - if (!ret) { - IWL_ERR(priv, "Could not load the INST uCode section\n"); - return -ETIMEDOUT; - } - - priv->ucode_write_complete = 0; - - ret = iwl5000_load_section( - priv, data_image, IWL50_RTC_DATA_LOWER_BOUND); - if (ret) - return ret; - - IWL_DEBUG_INFO(priv, "DATA uCode section being loaded...\n"); - - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - priv->ucode_write_complete, 5 * HZ); - if (ret == -ERESTARTSYS) { - IWL_ERR(priv, "Could not load the INST uCode section due " - "to interrupt\n"); - return ret; - } else if (!ret) { - IWL_ERR(priv, "Could not load the DATA uCode section\n"); - return -ETIMEDOUT; - } else - ret = 0; - - priv->ucode_write_complete = 0; - - return ret; -} - -int iwl5000_load_ucode(struct iwl_priv *priv) -{ - int ret = 0; - - /* check whether init ucode should be loaded, or rather runtime ucode */ - if (priv->ucode_init.len && (priv->ucode_type == UCODE_NONE)) { - IWL_DEBUG_INFO(priv, "Init ucode found. Loading init ucode...\n"); - ret = iwl5000_load_given_ucode(priv, - &priv->ucode_init, &priv->ucode_init_data); - if (!ret) { - IWL_DEBUG_INFO(priv, "Init ucode load complete.\n"); - priv->ucode_type = UCODE_INIT; - } - } else { - IWL_DEBUG_INFO(priv, "Init ucode not found, or already loaded. " - "Loading runtime ucode...\n"); - ret = iwl5000_load_given_ucode(priv, - &priv->ucode_code, &priv->ucode_data); - if (!ret) { - IWL_DEBUG_INFO(priv, "Runtime ucode load complete.\n"); - priv->ucode_type = UCODE_RT; - } - } - - return ret; -} - -void iwl5000_init_alive_start(struct iwl_priv *priv) -{ - int ret = 0; - - /* Check alive response for "valid" sign from uCode */ - if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); - goto restart; - } - - /* initialize uCode was loaded... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "initialize" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); - goto restart; - } - - iwl_clear_stations_table(priv); - ret = priv->cfg->ops->lib->alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition: %d\n", ret); - goto restart; - } - - iwl5000_send_calib_cfg(priv); - return; - -restart: - /* real restart (first load init_ucode) */ - queue_work(priv->workqueue, &priv->restart); -} - -static void iwl5000_set_wr_ptrs(struct iwl_priv *priv, - int txq_id, u32 index) -{ - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - (index & 0xff) | (txq_id << 8)); - iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(txq_id), index); -} - -static void iwl5000_tx_queue_set_status(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - int tx_fifo_id, int scd_retry) -{ - int txq_id = txq->q.id; - int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0; - - iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), - (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | - (tx_fifo_id << IWL50_SCD_QUEUE_STTS_REG_POS_TXF) | - (1 << IWL50_SCD_QUEUE_STTS_REG_POS_WSL) | - IWL50_SCD_QUEUE_STTS_REG_MSK); - - txq->sched_retry = scd_retry; - - IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n", - active ? "Activate" : "Deactivate", - scd_retry ? "BA" : "AC", txq_id, tx_fifo_id); -} - -static int iwl5000_send_wimax_coex(struct iwl_priv *priv) -{ - struct iwl_wimax_coex_cmd coex_cmd; - - memset(&coex_cmd, 0, sizeof(coex_cmd)); - - return iwl_send_cmd_pdu(priv, COEX_PRIORITY_TABLE_CMD, - sizeof(coex_cmd), &coex_cmd); -} - -int iwl5000_alive_notify(struct iwl_priv *priv) -{ - u32 a; - unsigned long flags; - int i, chan; - u32 reg_val; - - spin_lock_irqsave(&priv->lock, flags); - - priv->scd_base_addr = iwl_read_prph(priv, IWL50_SCD_SRAM_BASE_ADDR); - a = priv->scd_base_addr + IWL50_SCD_CONTEXT_DATA_OFFSET; - for (; a < priv->scd_base_addr + IWL50_SCD_TX_STTS_BITMAP_OFFSET; - a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < priv->scd_base_addr + IWL50_SCD_TRANSLATE_TBL_OFFSET; - a += 4) - iwl_write_targ_mem(priv, a, 0); - for (; a < sizeof(u16) * priv->hw_params.max_txq_num; a += 4) - iwl_write_targ_mem(priv, a, 0); - - iwl_write_prph(priv, IWL50_SCD_DRAM_BASE_ADDR, - priv->scd_bc_tbls.dma >> 10); - - /* Enable DMA channel */ - for (chan = 0; chan < FH50_TCSR_CHNL_NUM ; chan++) - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan), - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE); - - /* Update FH chicken bits */ - reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG); - iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG, - reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN); - - iwl_write_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, - IWL50_SCD_QUEUECHAIN_SEL_ALL(priv->hw_params.max_txq_num)); - iwl_write_prph(priv, IWL50_SCD_AGGR_SEL, 0); - - /* initiate the queues */ - for (i = 0; i < priv->hw_params.max_txq_num; i++) { - iwl_write_prph(priv, IWL50_SCD_QUEUE_RDPTR(i), 0); - iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8)); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(i), 0); - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(i) + - sizeof(u32), - ((SCD_WIN_SIZE << - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - } - - iwl_write_prph(priv, IWL50_SCD_INTERRUPT_MASK, - IWL_MASK(0, priv->hw_params.max_txq_num)); - - /* Activate all Tx DMA/FIFO channels */ - priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 7)); - - iwl5000_set_wr_ptrs(priv, IWL_CMD_QUEUE_NUM, 0); - - /* make sure all queue are not stopped */ - memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped)); - for (i = 0; i < 4; i++) - atomic_set(&priv->queue_stop_count[i], 0); - - /* reset to 0 to enable all the queue first */ - priv->txq_ctx_active_msk = 0; - /* map qos queues to fifos one-to-one */ - for (i = 0; i < ARRAY_SIZE(iwl5000_default_queue_to_tx_fifo); i++) { - int ac = iwl5000_default_queue_to_tx_fifo[i]; - iwl_txq_ctx_activate(priv, i); - iwl5000_tx_queue_set_status(priv, &priv->txq[i], ac, 0); - } - /* TODO - need to initialize those FIFOs inside the loop above, - * not only mark them as active */ - iwl_txq_ctx_activate(priv, 4); - iwl_txq_ctx_activate(priv, 7); - iwl_txq_ctx_activate(priv, 8); - iwl_txq_ctx_activate(priv, 9); - - spin_unlock_irqrestore(&priv->lock, flags); - - - iwl5000_send_wimax_coex(priv); - - iwl5000_set_Xtal_calib(priv); - iwl_send_calib_results(priv); - - return 0; -} - -int iwl5000_hw_set_hw_params(struct iwl_priv *priv) -{ - if ((priv->cfg->mod_params->num_of_queues > IWL50_NUM_QUEUES) || - (priv->cfg->mod_params->num_of_queues < IWL_MIN_NUM_QUEUES)) { - IWL_ERR(priv, - "invalid queues_num, should be between %d and %d\n", - IWL_MIN_NUM_QUEUES, IWL50_NUM_QUEUES); - return -EINVAL; - } - - priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; - priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM; - priv->hw_params.scd_bc_tbls_size = - IWL50_NUM_QUEUES * sizeof(struct iwl5000_scd_bc_tbl); - priv->hw_params.tfd_size = sizeof(struct iwl_tfd); - priv->hw_params.max_stations = IWL5000_STATION_COUNT; - priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; - - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_6x00: - case CSR_HW_REV_TYPE_6x50: - priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; - break; - default: - priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; - priv->hw_params.max_inst_size = IWL50_RTC_INST_SIZE; - } - - priv->hw_params.max_bsm_size = 0; - priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | - BIT(IEEE80211_BAND_5GHZ); - priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR; - - priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); - priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant); - priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant; - priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant; - - if (priv->cfg->ops->lib->temp_ops.set_ct_kill) - priv->cfg->ops->lib->temp_ops.set_ct_kill(priv); - - /* Set initial sensitivity parameters */ - /* Set initial calibration set */ - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_5150: - priv->hw_params.sens = &iwl5150_sensitivity; - priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_DC) | - BIT(IWL_CALIB_LO) | - BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_BASE_BAND); - - break; - default: - priv->hw_params.sens = &iwl5000_sensitivity; - priv->hw_params.calib_init_cfg = - BIT(IWL_CALIB_XTAL) | - BIT(IWL_CALIB_LO) | - BIT(IWL_CALIB_TX_IQ) | - BIT(IWL_CALIB_TX_IQ_PERD) | - BIT(IWL_CALIB_BASE_BAND); - break; - } - - return 0; -} - -/** - * iwl5000_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array - */ -void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt) -{ - struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int write_ptr = txq->q.write_ptr; - int txq_id = txq->q.id; - u8 sec_ctl = 0; - u8 sta_id = 0; - u16 len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE; - __le16 bc_ent; - - WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != IWL_CMD_QUEUE_NUM) { - sta_id = txq->cmd[txq->q.write_ptr]->cmd.tx.sta_id; - sec_ctl = txq->cmd[txq->q.write_ptr]->cmd.tx.sec_ctl; - - switch (sec_ctl & TX_CMD_SEC_MSK) { - case TX_CMD_SEC_CCM: - len += CCMP_MIC_LEN; - break; - case TX_CMD_SEC_TKIP: - len += TKIP_ICV_LEN; - break; - case TX_CMD_SEC_WEP: - len += WEP_IV_LEN + WEP_ICV_LEN; - break; - } - } - - bc_ent = cpu_to_le16((len & 0xFFF) | (sta_id << 12)); - - scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent; - - if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent; -} - -void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - struct iwl5000_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr; - int txq_id = txq->q.id; - int read_ptr = txq->q.read_ptr; - u8 sta_id = 0; - __le16 bc_ent; - - WARN_ON(read_ptr >= TFD_QUEUE_SIZE_MAX); - - if (txq_id != IWL_CMD_QUEUE_NUM) - sta_id = txq->cmd[read_ptr]->cmd.tx.sta_id; - - bc_ent = cpu_to_le16(1 | (sta_id << 12)); - scd_bc_tbl[txq_id].tfd_offset[read_ptr] = bc_ent; - - if (txq->q.write_ptr < TFD_QUEUE_SIZE_BC_DUP) - scd_bc_tbl[txq_id]. - tfd_offset[TFD_QUEUE_SIZE_MAX + read_ptr] = bc_ent; -} - -static int iwl5000_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid, - u16 txq_id) -{ - u32 tbl_dw_addr; - u32 tbl_dw; - u16 scd_q2ratid; - - scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK; - - tbl_dw_addr = priv->scd_base_addr + - IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id); - - tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr); - - if (txq_id & 0x1) - tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF); - else - tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000); - - iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw); - - return 0; -} -static void iwl5000_tx_queue_stop_scheduler(struct iwl_priv *priv, u16 txq_id) -{ - /* Simply stop the queue, but don't change any configuration; - * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */ - iwl_write_prph(priv, - IWL50_SCD_QUEUE_STATUS_BITS(txq_id), - (0 << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE)| - (1 << IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN)); -} - -int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx) -{ - unsigned long flags; - u16 ra_tid; - - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || - (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_WARN(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE, - IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); - return -EINVAL; - } - - ra_tid = BUILD_RAxTID(sta_id, tid); - - /* Modify device's station table to Tx this TID */ - iwl_sta_tx_modify_enable_tid(priv, sta_id, tid); - - spin_lock_irqsave(&priv->lock, flags); - - /* Stop this Tx queue before configuring it */ - iwl5000_tx_queue_stop_scheduler(priv, txq_id); - - /* Map receiver-address / traffic-ID to this queue */ - iwl5000_tx_queue_set_q2ratid(priv, ra_tid, txq_id); - - /* Set this queue as a chain-building queue */ - iwl_set_bits_prph(priv, IWL50_SCD_QUEUECHAIN_SEL, (1<txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); - - /* Set up Tx window size and frame limit for this queue */ - iwl_write_targ_mem(priv, priv->scd_base_addr + - IWL50_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + - sizeof(u32), - ((SCD_WIN_SIZE << - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS) & - IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK) | - ((SCD_FRAME_LIMIT << - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) & - IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK)); - - iwl_set_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); - - /* Set up Status area in SRAM, map to Tx DMA/FIFO, activate the queue */ - iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 1); - - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} - -int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo) -{ - if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) || - (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) { - IWL_ERR(priv, - "queue number out of range: %d, must be %d to %d\n", - txq_id, IWL50_FIRST_AMPDU_QUEUE, - IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1); - return -EINVAL; - } - - iwl5000_tx_queue_stop_scheduler(priv, txq_id); - - iwl_clear_bits_prph(priv, IWL50_SCD_AGGR_SEL, (1 << txq_id)); - - priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff); - priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff); - /* supposes that ssn_idx is valid (!= 0xFFF) */ - iwl5000_set_wr_ptrs(priv, txq_id, ssn_idx); - - iwl_clear_bits_prph(priv, IWL50_SCD_INTERRUPT_MASK, (1 << txq_id)); - iwl_txq_ctx_deactivate(priv, txq_id); - iwl5000_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0); - - return 0; -} - -u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data) -{ - u16 size = (u16)sizeof(struct iwl_addsta_cmd); - struct iwl_addsta_cmd *addsta = (struct iwl_addsta_cmd *)data; - memcpy(addsta, cmd, size); - /* resrved in 5000 */ - addsta->rate_n_flags = cpu_to_le16(0); - return size; -} - - -/* - * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask - * must be called under priv->lock and mac access - */ -void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask) -{ - iwl_write_prph(priv, IWL50_SCD_TXFACT, mask); -} - - -static inline u32 iwl5000_get_scd_ssn(struct iwl5000_tx_resp *tx_resp) -{ - return le32_to_cpup((__le32 *)&tx_resp->status + - tx_resp->frame_count) & MAX_SN; -} - -static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwl5000_tx_resp *tx_resp, - int txq_id, u16 start_idx) -{ - u16 status; - struct agg_tx_status *frame_status = &tx_resp->status; - struct ieee80211_tx_info *info = NULL; - struct ieee80211_hdr *hdr = NULL; - u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags); - int i, sh, idx; - u16 seq; - - if (agg->wait_for_ba) - IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n"); - - agg->frame_count = tx_resp->frame_count; - agg->start_idx = start_idx; - agg->rate_n_flags = rate_n_flags; - agg->bitmap = 0; - - /* # frames attempted by Tx command */ - if (agg->frame_count == 1) { - /* Only one frame was attempted; no block-ack will arrive */ - status = le16_to_cpu(frame_status[0].status); - idx = start_idx; - - /* FIXME: code repetition */ - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n", - agg->frame_count, agg->start_idx, idx); - - info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb[0]); - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags &= ~IEEE80211_TX_CTL_AMPDU; - info->flags |= iwl_is_tx_success(status) ? - IEEE80211_TX_STAT_ACK : 0; - iwl_hwrate_to_tx_control(priv, rate_n_flags, info); - - /* FIXME: code repetition end */ - - IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n", - status & 0xff, tx_resp->failure_frame); - IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags); - - agg->wait_for_ba = 0; - } else { - /* Two or more frames were attempted; expect block-ack */ - u64 bitmap = 0; - int start = agg->start_idx; - - /* Construct bit-map of pending frames within Tx window */ - for (i = 0; i < agg->frame_count; i++) { - u16 sc; - status = le16_to_cpu(frame_status[i].status); - seq = le16_to_cpu(frame_status[i].sequence); - idx = SEQ_TO_INDEX(seq); - txq_id = SEQ_TO_QUEUE(seq); - - if (status & (AGG_TX_STATE_FEW_BYTES_MSK | - AGG_TX_STATE_ABORT_MSK)) - continue; - - IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n", - agg->frame_count, txq_id, idx); - - hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx); - if (!hdr) { - IWL_ERR(priv, - "BUG_ON idx doesn't point to valid skb" - " idx=%d, txq_id=%d\n", idx, txq_id); - return -1; - } - - sc = le16_to_cpu(hdr->seq_ctrl); - if (idx != (SEQ_TO_SN(sc) & 0xff)) { - IWL_ERR(priv, - "BUG_ON idx doesn't match seq control" - " idx=%d, seq_idx=%d, seq=%d\n", - idx, SEQ_TO_SN(sc), - hdr->seq_ctrl); - return -1; - } - - IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n", - i, idx, SEQ_TO_SN(sc)); - - sh = idx - start; - if (sh > 64) { - sh = (start - idx) + 0xff; - bitmap = bitmap << sh; - sh = 0; - start = idx; - } else if (sh < -64) - sh = 0xff - (start - idx); - else if (sh < 0) { - sh = start - idx; - start = idx; - bitmap = bitmap << sh; - sh = 0; - } - bitmap |= 1ULL << sh; - IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n", - start, (unsigned long long)bitmap); - } - - agg->bitmap = bitmap; - agg->start_idx = start; - IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n", - agg->frame_count, agg->start_idx, - (unsigned long long)agg->bitmap); - - if (bitmap) - agg->wait_for_ba = 1; - } - return 0; -} - -static void iwl5000_rx_reply_tx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct ieee80211_tx_info *info; - struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; - u32 status = le16_to_cpu(tx_resp->status.status); - int tid; - int sta_id; - int freed; - - if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d " - "is out of range [0-%d] %d %d\n", txq_id, - index, txq->q.n_bd, txq->q.write_ptr, - txq->q.read_ptr); - return; - } - - info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); - memset(&info->status, 0, sizeof(info->status)); - - tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS; - sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS; - - if (txq->sched_retry) { - const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp); - struct iwl_ht_agg *agg = NULL; - - agg = &priv->stations[sta_id].tid[tid].agg; - - iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); - - /* check if BAR is needed */ - if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status)) - info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; - - if (txq->q.read_ptr != (scd_ssn & 0xff)) { - index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); - IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim " - "scd_ssn=%d idx=%d txq=%d swq=%d\n", - scd_ssn , index, txq_id, txq->swq_id); - - freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark) && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) { - if (agg->state == IWL_AGG_OFF) - iwl_wake_queue(priv, txq_id); - else - iwl_wake_queue(priv, txq->swq_id); - } - } - } else { - BUG_ON(txq_id != txq->swq_id); - - info->status.rates[0].count = tx_resp->failure_frame + 1; - info->flags |= iwl_is_tx_success(status) ? - IEEE80211_TX_STAT_ACK : 0; - iwl_hwrate_to_tx_control(priv, - le32_to_cpu(tx_resp->rate_n_flags), - info); - - IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) rate_n_flags " - "0x%x retries %d\n", - txq_id, - iwl_get_tx_fail_reason(status), status, - le32_to_cpu(tx_resp->rate_n_flags), - tx_resp->failure_frame); - - freed = iwl_tx_queue_reclaim(priv, txq_id, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if (priv->mac80211_registered && - (iwl_queue_space(&txq->q) > txq->q.low_mark)) - iwl_wake_queue(priv, txq_id); - } - - iwl_txq_check_empty(priv, sta_id, tid, txq_id); - - if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) - IWL_ERR(priv, "TODO: Implement Tx ABORT REQUIRED!!!\n"); -} - -/* Currently 5000 is the superset of everything */ -u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len) -{ - return len; -} - -void iwl5000_setup_deferred_work(struct iwl_priv *priv) -{ - /* in 5000 the tx power calibration is done in uCode */ - priv->disable_tx_power_cal = 1; -} - -void iwl5000_rx_handler_setup(struct iwl_priv *priv) -{ - /* init calibration handlers */ - priv->rx_handlers[CALIBRATION_RES_NOTIFICATION] = - iwl5000_rx_calib_result; - priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] = - iwl5000_rx_calib_complete; - priv->rx_handlers[REPLY_TX] = iwl5000_rx_reply_tx; -} - - -int iwl5000_hw_valid_rtc_data_addr(u32 addr) -{ - return (addr >= IWL50_RTC_DATA_LOWER_BOUND) && - (addr < IWL50_RTC_DATA_UPPER_BOUND); -} - -static int iwl5000_send_rxon_assoc(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl5000_rxon_assoc_cmd rxon_assoc; - const struct iwl_rxon_cmd *rxon1 = &priv->staging_rxon; - const struct iwl_rxon_cmd *rxon2 = &priv->active_rxon; - - if ((rxon1->flags == rxon2->flags) && - (rxon1->filter_flags == rxon2->filter_flags) && - (rxon1->cck_basic_rates == rxon2->cck_basic_rates) && - (rxon1->ofdm_ht_single_stream_basic_rates == - rxon2->ofdm_ht_single_stream_basic_rates) && - (rxon1->ofdm_ht_dual_stream_basic_rates == - rxon2->ofdm_ht_dual_stream_basic_rates) && - (rxon1->ofdm_ht_triple_stream_basic_rates == - rxon2->ofdm_ht_triple_stream_basic_rates) && - (rxon1->acquisition_data == rxon2->acquisition_data) && - (rxon1->rx_chain == rxon2->rx_chain) && - (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) { - IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC. Not resending.\n"); - return 0; - } - - rxon_assoc.flags = priv->staging_rxon.flags; - rxon_assoc.filter_flags = priv->staging_rxon.filter_flags; - rxon_assoc.ofdm_basic_rates = priv->staging_rxon.ofdm_basic_rates; - rxon_assoc.cck_basic_rates = priv->staging_rxon.cck_basic_rates; - rxon_assoc.reserved1 = 0; - rxon_assoc.reserved2 = 0; - rxon_assoc.reserved3 = 0; - rxon_assoc.ofdm_ht_single_stream_basic_rates = - priv->staging_rxon.ofdm_ht_single_stream_basic_rates; - rxon_assoc.ofdm_ht_dual_stream_basic_rates = - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates; - rxon_assoc.rx_chain_select_flags = priv->staging_rxon.rx_chain; - rxon_assoc.ofdm_ht_triple_stream_basic_rates = - priv->staging_rxon.ofdm_ht_triple_stream_basic_rates; - rxon_assoc.acquisition_data = priv->staging_rxon.acquisition_data; - - ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC, - sizeof(rxon_assoc), &rxon_assoc, NULL); - if (ret) - return ret; - - return ret; -} -int iwl5000_send_tx_power(struct iwl_priv *priv) -{ - struct iwl5000_tx_power_dbm_cmd tx_power_cmd; - u8 tx_ant_cfg_cmd; - - /* half dBm need to multiply */ - tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt); - tx_power_cmd.flags = IWL50_TX_POWER_NO_CLOSED; - tx_power_cmd.srv_chan_lmt = IWL50_TX_POWER_AUTO; - - if (IWL_UCODE_API(priv->ucode_ver) == 1) - tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1; - else - tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD; - - return iwl_send_cmd_pdu_async(priv, tx_ant_cfg_cmd, - sizeof(tx_power_cmd), &tx_power_cmd, - NULL); -} - -void iwl5000_temperature(struct iwl_priv *priv) -{ - /* store temperature from statistics (in Celsius) */ - priv->temperature = le32_to_cpu(priv->statistics.general.temperature); - iwl_tt_handler(priv); -} - -static void iwl5150_temperature(struct iwl_priv *priv) -{ - u32 vt = 0; - s32 offset = iwl_temp_calib_to_offset(priv); - - vt = le32_to_cpu(priv->statistics.general.temperature); - vt = vt / IWL_5150_VOLTAGE_TO_TEMPERATURE_COEFF + offset; - /* now vt hold the temperature in Kelvin */ - priv->temperature = KELVIN_TO_CELSIUS(vt); - iwl_tt_handler(priv); -} - -/* Calc max signal level (dBm) among 3 possible receivers */ -int iwl5000_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp) -{ - /* data from PHY/DSP regarding signal strength, etc., - * contents are always there, not configurable by host - */ - struct iwl5000_non_cfg_phy *ncphy = - (struct iwl5000_non_cfg_phy *)rx_resp->non_cfg_phy_buf; - u32 val, rssi_a, rssi_b, rssi_c, max_rssi; - u8 agc; - - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_AGC_IDX]); - agc = (val & IWL50_OFDM_AGC_MSK) >> IWL50_OFDM_AGC_BIT_POS; - - /* Find max rssi among 3 possible receivers. - * These values are measured by the digital signal processor (DSP). - * They should stay fairly constant even as the signal strength varies, - * if the radio's automatic gain control (AGC) is working right. - * AGC value (see below) will provide the "interesting" info. - */ - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_AB_IDX]); - rssi_a = (val & IWL50_OFDM_RSSI_A_MSK) >> IWL50_OFDM_RSSI_A_BIT_POS; - rssi_b = (val & IWL50_OFDM_RSSI_B_MSK) >> IWL50_OFDM_RSSI_B_BIT_POS; - val = le32_to_cpu(ncphy->non_cfg_phy[IWL50_RX_RES_RSSI_C_IDX]); - rssi_c = (val & IWL50_OFDM_RSSI_C_MSK) >> IWL50_OFDM_RSSI_C_BIT_POS; - - max_rssi = max_t(u32, rssi_a, rssi_b); - max_rssi = max_t(u32, max_rssi, rssi_c); - - IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", - rssi_a, rssi_b, rssi_c, max_rssi, agc); - - /* dBm = max_rssi dB - agc dB - constant. - * Higher AGC (higher radio gain) means lower signal. */ - return max_rssi - agc - IWL49_RSSI_OFFSET; -} - -#define IWL5000_UCODE_GET(item) \ -static u32 iwl5000_ucode_get_##item(const struct iwl_ucode_header *ucode,\ - u32 api_ver) \ -{ \ - if (api_ver <= 2) \ - return le32_to_cpu(ucode->u.v1.item); \ - return le32_to_cpu(ucode->u.v2.item); \ -} - -static u32 iwl5000_ucode_get_header_size(u32 api_ver) -{ - if (api_ver <= 2) - return UCODE_HEADER_SIZE(1); - return UCODE_HEADER_SIZE(2); -} - -static u32 iwl5000_ucode_get_build(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - if (api_ver <= 2) - return 0; - return le32_to_cpu(ucode->u.v2.build); -} - -static u8 *iwl5000_ucode_get_data(const struct iwl_ucode_header *ucode, - u32 api_ver) -{ - if (api_ver <= 2) - return (u8 *) ucode->u.v1.data; - return (u8 *) ucode->u.v2.data; -} - -IWL5000_UCODE_GET(inst_size); -IWL5000_UCODE_GET(data_size); -IWL5000_UCODE_GET(init_size); -IWL5000_UCODE_GET(init_data_size); -IWL5000_UCODE_GET(boot_size); - -struct iwl_hcmd_ops iwl5000_hcmd = { - .rxon_assoc = iwl5000_send_rxon_assoc, - .commit_rxon = iwl_commit_rxon, - .set_rxon_chain = iwl_set_rxon_chain, -}; - -struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = { - .get_hcmd_size = iwl5000_get_hcmd_size, - .build_addsta_hcmd = iwl5000_build_addsta_hcmd, - .gain_computation = iwl5000_gain_computation, - .chain_noise_reset = iwl5000_chain_noise_reset, - .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, - .calc_rssi = iwl5000_calc_rssi, -}; - -struct iwl_ucode_ops iwl5000_ucode = { - .get_header_size = iwl5000_ucode_get_header_size, - .get_build = iwl5000_ucode_get_build, - .get_inst_size = iwl5000_ucode_get_inst_size, - .get_data_size = iwl5000_ucode_get_data_size, - .get_init_size = iwl5000_ucode_get_init_size, - .get_init_data_size = iwl5000_ucode_get_init_data_size, - .get_boot_size = iwl5000_ucode_get_boot_size, - .get_data = iwl5000_ucode_get_data, -}; - -struct iwl_lib_ops iwl5000_lib = { - .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .load_ucode = iwl5000_load_ucode, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, - .send_tx_power = iwl5000_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .apm_ops = { - .init = iwl5000_apm_init, - .reset = iwl5000_apm_reset, - .stop = iwl5000_apm_stop, - .config = iwl5000_nic_config, - .set_pwr_src = iwl_set_pwr_src, - }, - .eeprom_ops = { - .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS - }, - .verify_signature = iwlcore_eeprom_verify_signature, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, - }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, - .temp_ops = { - .temperature = iwl5000_temperature, - .set_ct_kill = iwl5000_set_ct_threshold, - }, -}; - -static struct iwl_lib_ops iwl5150_lib = { - .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .load_ucode = iwl5000_load_ucode, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, - .send_tx_power = iwl5000_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .apm_ops = { - .init = iwl5000_apm_init, - .reset = iwl5000_apm_reset, - .stop = iwl5000_apm_stop, - .config = iwl5000_nic_config, - .set_pwr_src = iwl_set_pwr_src, - }, - .eeprom_ops = { - .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS - }, - .verify_signature = iwlcore_eeprom_verify_signature, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, - }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, - .temp_ops = { - .temperature = iwl5150_temperature, - .set_ct_kill = iwl5150_set_ct_threshold, - }, -}; - -struct iwl_ops iwl5000_ops = { - .ucode = &iwl5000_ucode, - .lib = &iwl5000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, -}; - -static struct iwl_ops iwl5150_ops = { - .ucode = &iwl5000_ucode, - .lib = &iwl5150_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl5000_hcmd_utils, -}; - -struct iwl_mod_params iwl50_mod_params = { - .num_of_queues = IWL50_NUM_QUEUES, - .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES, - .amsdu_size_8K = 1, - .restart_fw = 1, - /* the rest are 0 by default */ -}; - - -struct iwl_cfg iwl5300_agn_cfg = { - .name = "5300AGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, - .need_pll_cfg = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl5100_bgn_cfg = { - .name = "5100BGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = true, - .ht_greenfield_support = true, -}; - -struct iwl_cfg iwl5100_abg_cfg = { - .name = "5100ABG", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = true, -}; - -struct iwl_cfg iwl5100_agn_cfg = { - .name = "5100AGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_B, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl5350_agn_cfg = { - .name = "5350AGN", - .fw_name_pre = IWL5000_FW_PRE, - .ucode_api_max = IWL5000_UCODE_API_MAX, - .ucode_api_min = IWL5000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5000_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, - .need_pll_cfg = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl5150_agn_cfg = { - .name = "5150AGN", - .fw_name_pre = IWL5150_FW_PRE, - .ucode_api_max = IWL5150_UCODE_API_MAX, - .ucode_api_min = IWL5150_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl5150_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl5150_abg_cfg = { - .name = "5150ABG", - .fw_name_pre = IWL5150_FW_PRE, - .ucode_api_max = IWL5150_UCODE_API_MAX, - .ucode_api_min = IWL5150_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G, - .ops = &iwl5150_ops, - .eeprom_size = IWL_5000_EEPROM_IMG_SIZE, - .eeprom_ver = EEPROM_5050_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5050_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_A, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = true, -}; - -MODULE_FIRMWARE(IWL5000_MODULE_FIRMWARE(IWL5000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL5150_MODULE_FIRMWARE(IWL5150_UCODE_API_MAX)); - -module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); -MODULE_PARM_DESC(swcrypto50, - "using software crypto engine (default 0 [hardware])\n"); -module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); -MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); -module_param_named(11n_disable50, iwl50_mod_params.disable_11n, int, 0444); -MODULE_PARM_DESC(11n_disable50, "disable 50XX 11n functionality"); -module_param_named(amsdu_size_8K50, iwl50_mod_params.amsdu_size_8K, int, 0444); -MODULE_PARM_DESC(amsdu_size_8K50, "enable 8K amsdu size in 50XX series"); -module_param_named(fw_restart50, iwl50_mod_params.restart_fw, int, 0444); -MODULE_PARM_DESC(fw_restart50, "restart firmware in case of error"); diff --git a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h b/drivers/net/wireless/iwlwifi/iwl-6000-hw.h deleted file mode 100644 index 90185777d98b..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-6000-hw.h +++ /dev/null @@ -1,81 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -/* - * Please use this file (iwl-6000-hw.h) only for hardware-related definitions. - * Use iwl-5000-commands.h for uCode API definitions. - */ - -#ifndef __iwl_6000_hw_h__ -#define __iwl_6000_hw_h__ - -#define IWL60_RTC_INST_LOWER_BOUND (0x000000) -#define IWL60_RTC_INST_UPPER_BOUND (0x040000) -#define IWL60_RTC_DATA_LOWER_BOUND (0x800000) -#define IWL60_RTC_DATA_UPPER_BOUND (0x814000) -#define IWL60_RTC_INST_SIZE \ - (IWL60_RTC_INST_UPPER_BOUND - IWL60_RTC_INST_LOWER_BOUND) -#define IWL60_RTC_DATA_SIZE \ - (IWL60_RTC_DATA_UPPER_BOUND - IWL60_RTC_DATA_LOWER_BOUND) - -#endif /* __iwl_6000_hw_h__ */ - diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c deleted file mode 100644 index 1473452ba22f..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-6000.c +++ /dev/null @@ -1,269 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2008-2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-sta.h" -#include "iwl-helpers.h" -#include "iwl-5000-hw.h" - -/* Highest firmware API version supported */ -#define IWL6000_UCODE_API_MAX 4 -#define IWL6050_UCODE_API_MAX 4 - -/* Lowest firmware API version supported */ -#define IWL6000_UCODE_API_MIN 1 -#define IWL6050_UCODE_API_MIN 1 - -#define IWL6000_FW_PRE "iwlwifi-6000-" -#define _IWL6000_MODULE_FIRMWARE(api) IWL6000_FW_PRE #api ".ucode" -#define IWL6000_MODULE_FIRMWARE(api) _IWL6000_MODULE_FIRMWARE(api) - -#define IWL6050_FW_PRE "iwlwifi-6050-" -#define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE #api ".ucode" -#define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api) - -static void iwl6000_set_ct_threshold(struct iwl_priv *priv) -{ - /* want Celsius */ - priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD; - priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD; -} - -/* NIC configuration for 6000 series */ -static void iwl6000_nic_config(struct iwl_priv *priv) -{ - iwl5000_nic_config(priv); - - /* no locking required for register write */ - if (priv->cfg->pa_type == IWL_PA_HYBRID) { - /* 2x2 hybrid phy type */ - iwl_write32(priv, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB); - } else if (priv->cfg->pa_type == IWL_PA_INTERNAL) { - /* 2x2 IPA phy type */ - iwl_write32(priv, CSR_GP_DRIVER_REG, - CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA); - } - /* else do nothing, uCode configured */ -} - -static struct iwl_lib_ops iwl6000_lib = { - .set_hw_params = iwl5000_hw_set_hw_params, - .txq_update_byte_cnt_tbl = iwl5000_txq_update_byte_cnt_tbl, - .txq_inval_byte_cnt_tbl = iwl5000_txq_inval_byte_cnt_tbl, - .txq_set_sched = iwl5000_txq_set_sched, - .txq_agg_enable = iwl5000_txq_agg_enable, - .txq_agg_disable = iwl5000_txq_agg_disable, - .txq_attach_buf_to_tfd = iwl_hw_txq_attach_buf_to_tfd, - .txq_free_tfd = iwl_hw_txq_free_tfd, - .txq_init = iwl_hw_tx_queue_init, - .rx_handler_setup = iwl5000_rx_handler_setup, - .setup_deferred_work = iwl5000_setup_deferred_work, - .is_valid_rtc_data_addr = iwl5000_hw_valid_rtc_data_addr, - .load_ucode = iwl5000_load_ucode, - .dump_nic_event_log = iwl_dump_nic_event_log, - .dump_nic_error_log = iwl_dump_nic_error_log, - .init_alive_start = iwl5000_init_alive_start, - .alive_notify = iwl5000_alive_notify, - .send_tx_power = iwl5000_send_tx_power, - .update_chain_flags = iwl_update_chain_flags, - .apm_ops = { - .init = iwl5000_apm_init, - .reset = iwl5000_apm_reset, - .stop = iwl5000_apm_stop, - .config = iwl6000_nic_config, - .set_pwr_src = iwl_set_pwr_src, - }, - .eeprom_ops = { - .regulatory_bands = { - EEPROM_5000_REG_BAND_1_CHANNELS, - EEPROM_5000_REG_BAND_2_CHANNELS, - EEPROM_5000_REG_BAND_3_CHANNELS, - EEPROM_5000_REG_BAND_4_CHANNELS, - EEPROM_5000_REG_BAND_5_CHANNELS, - EEPROM_5000_REG_BAND_24_HT40_CHANNELS, - EEPROM_5000_REG_BAND_52_HT40_CHANNELS - }, - .verify_signature = iwlcore_eeprom_verify_signature, - .acquire_semaphore = iwlcore_eeprom_acquire_semaphore, - .release_semaphore = iwlcore_eeprom_release_semaphore, - .calib_version = iwl5000_eeprom_calib_version, - .query_addr = iwl5000_eeprom_query_addr, - .update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower, - }, - .post_associate = iwl_post_associate, - .isr = iwl_isr_ict, - .config_ap = iwl_config_ap, - .temp_ops = { - .temperature = iwl5000_temperature, - .set_ct_kill = iwl6000_set_ct_threshold, - }, -}; - -static struct iwl_hcmd_utils_ops iwl6000_hcmd_utils = { - .get_hcmd_size = iwl5000_get_hcmd_size, - .build_addsta_hcmd = iwl5000_build_addsta_hcmd, - .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag, - .calc_rssi = iwl5000_calc_rssi, -}; - -static struct iwl_ops iwl6000_ops = { - .ucode = &iwl5000_ucode, - .lib = &iwl6000_lib, - .hcmd = &iwl5000_hcmd, - .utils = &iwl6000_hcmd_utils, -}; - - -/* - * "h": Hybrid configuration, use both internal and external Power Amplifier - */ -struct iwl_cfg iwl6000h_2agn_cfg = { - .name = "6000 Series 2x2 AGN", - .fw_name_pre = IWL6000_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6000_ops, - .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = false, - .pa_type = IWL_PA_HYBRID, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -/* - * "i": Internal configuration, use internal Power Amplifier - */ -struct iwl_cfg iwl6000i_2agn_cfg = { - .name = "6000 Series 2x2 AGN", - .fw_name_pre = IWL6000_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6000_ops, - .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_BC, - .valid_rx_ant = ANT_BC, - .need_pll_cfg = false, - .pa_type = IWL_PA_INTERNAL, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl6050_2agn_cfg = { - .name = "6050 Series 2x2 AGN", - .fw_name_pre = IWL6050_FW_PRE, - .ucode_api_max = IWL6050_UCODE_API_MAX, - .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6000_ops, - .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_AB, - .valid_rx_ant = ANT_AB, - .need_pll_cfg = false, - .pa_type = IWL_PA_SYSTEM, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl6000_3agn_cfg = { - .name = "6000 Series 3x3 AGN", - .fw_name_pre = IWL6000_FW_PRE, - .ucode_api_max = IWL6000_UCODE_API_MAX, - .ucode_api_min = IWL6000_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6000_ops, - .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, - .need_pll_cfg = false, - .pa_type = IWL_PA_SYSTEM, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -struct iwl_cfg iwl6050_3agn_cfg = { - .name = "6050 Series 3x3 AGN", - .fw_name_pre = IWL6050_FW_PRE, - .ucode_api_max = IWL6050_UCODE_API_MAX, - .ucode_api_min = IWL6050_UCODE_API_MIN, - .sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N, - .ops = &iwl6000_ops, - .eeprom_size = OTP_LOW_IMAGE_SIZE, - .eeprom_ver = EEPROM_5000_EEPROM_VERSION, - .eeprom_calib_ver = EEPROM_5000_TX_POWER_VERSION, - .mod_params = &iwl50_mod_params, - .valid_tx_ant = ANT_ABC, - .valid_rx_ant = ANT_ABC, - .need_pll_cfg = false, - .pa_type = IWL_PA_SYSTEM, - .max_ll_items = OTP_MAX_LL_ITEMS_6x00, - .shadow_ram_support = true, - .ht_greenfield_support = true, - .use_rts_for_ht = true, /* use rts/cts protection */ -}; - -MODULE_FIRMWARE(IWL6000_MODULE_FIRMWARE(IWL6000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL6050_MODULE_FIRMWARE(IWL6050_UCODE_API_MAX)); diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c deleted file mode 100644 index 1a3dfa2b1ef0..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ /dev/null @@ -1,3144 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#include "iwl-dev.h" -#include "iwl-sta.h" -#include "iwl-core.h" - -#define RS_NAME "iwl-agn-rs" - -#define NUM_TRY_BEFORE_ANT_TOGGLE 1 -#define IWL_NUMBER_TRY 1 -#define IWL_HT_NUMBER_TRY 3 - -#define IWL_RATE_MAX_WINDOW 62 /* # tx in history window */ -#define IWL_RATE_MIN_FAILURE_TH 6 /* min failures to calc tpt */ -#define IWL_RATE_MIN_SUCCESS_TH 8 /* min successes to calc tpt */ - -/* max allowed rate miss before sync LQ cmd */ -#define IWL_MISSED_RATE_MAX 15 -/* max time to accum history 2 seconds */ -#define IWL_RATE_SCALE_FLUSH_INTVL (3*HZ) - -static u8 rs_ht_to_legacy[] = { - IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, - IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX, - IWL_RATE_6M_INDEX, - IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX, - IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX, - IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX, - IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX -}; - -static const u8 ant_toggle_lookup[] = { - /*ANT_NONE -> */ ANT_NONE, - /*ANT_A -> */ ANT_B, - /*ANT_B -> */ ANT_C, - /*ANT_AB -> */ ANT_BC, - /*ANT_C -> */ ANT_A, - /*ANT_AC -> */ ANT_AB, - /*ANT_BC -> */ ANT_AC, - /*ANT_ABC -> */ ANT_ABC, -}; - -/** - * struct iwl_rate_scale_data -- tx success history for one rate - */ -struct iwl_rate_scale_data { - u64 data; /* bitmap of successful frames */ - s32 success_counter; /* number of frames successful */ - s32 success_ratio; /* per-cent * 128 */ - s32 counter; /* number of frames attempted */ - s32 average_tpt; /* success ratio * expected throughput */ - unsigned long stamp; -}; - -/** - * struct iwl_scale_tbl_info -- tx params and success history for all rates - * - * There are two of these in struct iwl_lq_sta, - * one for "active", and one for "search". - */ -struct iwl_scale_tbl_info { - enum iwl_table_type lq_type; - u8 ant_type; - u8 is_SGI; /* 1 = short guard interval */ - u8 is_ht40; /* 1 = 40 MHz channel width */ - u8 is_dup; /* 1 = duplicated data streams */ - u8 action; /* change modulation; IWL_[LEGACY/SISO/MIMO]_SWITCH_* */ - u8 max_search; /* maximun number of tables we can search */ - s32 *expected_tpt; /* throughput metrics; expected_tpt_G, etc. */ - u32 current_rate; /* rate_n_flags, uCode API format */ - struct iwl_rate_scale_data win[IWL_RATE_COUNT]; /* rate histories */ -}; - -struct iwl_traffic_load { - unsigned long time_stamp; /* age of the oldest statistics */ - u32 packet_count[TID_QUEUE_MAX_SIZE]; /* packet count in this time - * slice */ - u32 total; /* total num of packets during the - * last TID_MAX_TIME_DIFF */ - u8 queue_count; /* number of queues that has - * been used since the last cleanup */ - u8 head; /* start of the circular buffer */ -}; - -/** - * struct iwl_lq_sta -- driver's rate scaling private structure - * - * Pointer to this gets passed back and forth between driver and mac80211. - */ -struct iwl_lq_sta { - u8 active_tbl; /* index of active table, range 0-1 */ - u8 enable_counter; /* indicates HT mode */ - u8 stay_in_tbl; /* 1: disallow, 0: allow search for new mode */ - u8 search_better_tbl; /* 1: currently trying alternate mode */ - s32 last_tpt; - - /* The following determine when to search for a new mode */ - u32 table_count_limit; - u32 max_failure_limit; /* # failed frames before new search */ - u32 max_success_limit; /* # successful frames before new search */ - u32 table_count; - u32 total_failed; /* total failed frames, any/all rates */ - u32 total_success; /* total successful frames, any/all rates */ - u64 flush_timer; /* time staying in mode before new search */ - - u8 action_counter; /* # mode-switch actions tried */ - u8 is_green; - u8 is_dup; - enum ieee80211_band band; - u8 ibss_sta_added; - - /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ - u32 supp_rates; - u16 active_legacy_rate; - u16 active_siso_rate; - u16 active_mimo2_rate; - u16 active_mimo3_rate; - u16 active_rate_basic; - s8 max_rate_idx; /* Max rate set by user */ - u8 missed_rate_counter; - - struct iwl_link_quality_cmd lq; - struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */ - struct iwl_traffic_load load[TID_MAX_LOAD_COUNT]; - u8 tx_agg_tid_en; -#ifdef CONFIG_MAC80211_DEBUGFS - struct dentry *rs_sta_dbgfs_scale_table_file; - struct dentry *rs_sta_dbgfs_stats_table_file; - struct dentry *rs_sta_dbgfs_rate_scale_data_file; - struct dentry *rs_sta_dbgfs_tx_agg_tid_en_file; - u32 dbg_fixed_rate; -#endif - struct iwl_priv *drv; - - /* used to be in sta_info */ - int last_txrate_idx; - /* last tx rate_n_flags */ - u32 last_rate_n_flags; -}; - -static void rs_rate_scale_perform(struct iwl_priv *priv, - struct sk_buff *skb, - struct ieee80211_sta *sta, - struct iwl_lq_sta *lq_sta); -static void rs_fill_link_cmd(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, u32 rate_n_flags); - - -#ifdef CONFIG_MAC80211_DEBUGFS -static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, - u32 *rate_n_flags, int index); -#else -static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, - u32 *rate_n_flags, int index) -{} -#endif - -/* - * Expected throughput metrics for following rates: - * 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits - * "G" is the only table that supports CCK (the first 4 rates). - */ - -static s32 expected_tpt_A[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186, 186 -}; - -static s32 expected_tpt_G[IWL_RATE_COUNT] = { - 7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 186 -}; - -static s32 expected_tpt_siso20MHz[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 42, 42, 76, 102, 124, 159, 183, 193, 202 -}; - -static s32 expected_tpt_siso20MHzSGI[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 46, 46, 82, 110, 132, 168, 192, 202, 211 -}; - -static s32 expected_tpt_mimo2_20MHz[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 74, 74, 123, 155, 179, 214, 236, 244, 251 -}; - -static s32 expected_tpt_mimo2_20MHzSGI[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 81, 81, 131, 164, 188, 222, 243, 251, 257 -}; - -static s32 expected_tpt_siso40MHz[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 77, 77, 127, 160, 184, 220, 242, 250, 257 -}; - -static s32 expected_tpt_siso40MHzSGI[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 83, 83, 135, 169, 193, 229, 250, 257, 264 -}; - -static s32 expected_tpt_mimo2_40MHz[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 123, 123, 182, 214, 235, 264, 279, 285, 289 -}; - -static s32 expected_tpt_mimo2_40MHzSGI[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 131, 131, 191, 222, 242, 270, 284, 289, 293 -}; - -/* Expected throughput metric MIMO3 */ -static s32 expected_tpt_mimo3_20MHz[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 99, 99, 153, 186, 208, 239, 256, 263, 268 -}; - -static s32 expected_tpt_mimo3_20MHzSGI[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 106, 106, 162, 194, 215, 246, 262, 268, 273 -}; - -static s32 expected_tpt_mimo3_40MHz[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 152, 152, 211, 239, 255, 279, 290, 294, 297 -}; - -static s32 expected_tpt_mimo3_40MHzSGI[IWL_RATE_COUNT] = { - 0, 0, 0, 0, 160, 160, 219, 245, 261, 284, 294, 297, 300 -}; - -/* mbps, mcs */ -const static struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = { - {"1", ""}, - {"2", ""}, - {"5.5", ""}, - {"11", ""}, - {"6", "BPSK 1/2"}, - {"9", "BPSK 1/2"}, - {"12", "QPSK 1/2"}, - {"18", "QPSK 3/4"}, - {"24", "16QAM 1/2"}, - {"36", "16QAM 3/4"}, - {"48", "64QAM 2/3"}, - {"54", "64QAM 3/4"}, - {"60", "64QAM 5/6"} -}; - -#define MCS_INDEX_PER_STREAM (8) - -static inline u8 rs_extract_rate(u32 rate_n_flags) -{ - return (u8)(rate_n_flags & 0xFF); -} - -static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) -{ - window->data = 0; - window->success_counter = 0; - window->success_ratio = IWL_INVALID_VALUE; - window->counter = 0; - window->average_tpt = IWL_INVALID_VALUE; - window->stamp = 0; -} - -static inline u8 rs_is_valid_ant(u8 valid_antenna, u8 ant_type) -{ - return (ant_type & valid_antenna) == ant_type; -} - -/* - * removes the old data from the statistics. All data that is older than - * TID_MAX_TIME_DIFF, will be deleted. - */ -static void rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time) -{ - /* The oldest age we want to keep */ - u32 oldest_time = curr_time - TID_MAX_TIME_DIFF; - - while (tl->queue_count && - (tl->time_stamp < oldest_time)) { - tl->total -= tl->packet_count[tl->head]; - tl->packet_count[tl->head] = 0; - tl->time_stamp += TID_QUEUE_CELL_SPACING; - tl->queue_count--; - tl->head++; - if (tl->head >= TID_QUEUE_MAX_SIZE) - tl->head = 0; - } -} - -/* - * increment traffic load value for tid and also remove - * any old values if passed the certain time period - */ -static u8 rs_tl_add_packet(struct iwl_lq_sta *lq_data, - struct ieee80211_hdr *hdr) -{ - u32 curr_time = jiffies_to_msecs(jiffies); - u32 time_diff; - s32 index; - struct iwl_traffic_load *tl = NULL; - u8 tid; - - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & 0xf; - } else - return MAX_TID_COUNT; - - if (unlikely(tid >= TID_MAX_LOAD_COUNT)) - return MAX_TID_COUNT; - - tl = &lq_data->load[tid]; - - curr_time -= curr_time % TID_ROUND_VALUE; - - /* Happens only for the first packet. Initialize the data */ - if (!(tl->queue_count)) { - tl->total = 1; - tl->time_stamp = curr_time; - tl->queue_count = 1; - tl->head = 0; - tl->packet_count[0] = 1; - return MAX_TID_COUNT; - } - - time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); - index = time_diff / TID_QUEUE_CELL_SPACING; - - /* The history is too long: remove data that is older than */ - /* TID_MAX_TIME_DIFF */ - if (index >= TID_QUEUE_MAX_SIZE) - rs_tl_rm_old_stats(tl, curr_time); - - index = (tl->head + index) % TID_QUEUE_MAX_SIZE; - tl->packet_count[index] = tl->packet_count[index] + 1; - tl->total = tl->total + 1; - - if ((index + 1) > tl->queue_count) - tl->queue_count = index + 1; - - return tid; -} - -/* - get the traffic load value for tid -*/ -static u32 rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid) -{ - u32 curr_time = jiffies_to_msecs(jiffies); - u32 time_diff; - s32 index; - struct iwl_traffic_load *tl = NULL; - - if (tid >= TID_MAX_LOAD_COUNT) - return 0; - - tl = &(lq_data->load[tid]); - - curr_time -= curr_time % TID_ROUND_VALUE; - - if (!(tl->queue_count)) - return 0; - - time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time); - index = time_diff / TID_QUEUE_CELL_SPACING; - - /* The history is too long: remove data that is older than */ - /* TID_MAX_TIME_DIFF */ - if (index >= TID_QUEUE_MAX_SIZE) - rs_tl_rm_old_stats(tl, curr_time); - - return tl->total; -} - -static void rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv, - struct iwl_lq_sta *lq_data, u8 tid, - struct ieee80211_sta *sta) -{ - int ret; - - if (rs_tl_get_load(lq_data, tid) > IWL_AGG_LOAD_THRESHOLD) { - IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n", - sta->addr, tid); - ret = ieee80211_start_tx_ba_session(priv->hw, sta->addr, tid); - if (ret == -EAGAIN) { - /* - * driver and mac80211 is out of sync - * this might be cause by reloading firmware - * stop the tx ba session here - */ - IWL_DEBUG_HT(priv, "Fail start Tx agg on tid: %d\n", - tid); - ret = ieee80211_stop_tx_ba_session(priv->hw, sta->addr, tid, - WLAN_BACK_INITIATOR); - } - } -} - -static void rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid, - struct iwl_lq_sta *lq_data, - struct ieee80211_sta *sta) -{ - if ((tid < TID_MAX_LOAD_COUNT)) - rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); - else if (tid == IWL_AGG_ALL_TID) - for (tid = 0; tid < TID_MAX_LOAD_COUNT; tid++) - rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta); - if (priv->cfg->use_rts_for_ht) { - /* - * switch to RTS/CTS if it is the prefer protection method - * for HT traffic - */ - IWL_DEBUG_HT(priv, "use RTS/CTS protection for HT\n"); - priv->staging_rxon.flags &= ~RXON_FLG_SELF_CTS_EN; - iwlcore_commit_rxon(priv); - } -} - -static inline int get_num_of_ant_from_rate(u32 rate_n_flags) -{ - return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_B_MSK) + - !!(rate_n_flags & RATE_MCS_ANT_C_MSK); -} - -/** - * rs_collect_tx_data - Update the success/failure sliding window - * - * We keep a sliding window of the last 62 packets transmitted - * at this rate. window->data contains the bitmask of successful - * packets. - */ -static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, - int scale_index, s32 tpt, int retries, - int successes) -{ - struct iwl_rate_scale_data *window = NULL; - static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); - s32 fail_count; - - if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) - return -EINVAL; - - /* Select data for current tx bit rate */ - window = &(windows[scale_index]); - - /* - * Keep track of only the latest 62 tx frame attempts in this rate's - * history window; anything older isn't really relevant any more. - * If we have filled up the sliding window, drop the oldest attempt; - * if the oldest attempt (highest bit in bitmap) shows "success", - * subtract "1" from the success counter (this is the main reason - * we keep these bitmaps!). - */ - while (retries > 0) { - if (window->counter >= IWL_RATE_MAX_WINDOW) { - - /* remove earliest */ - window->counter = IWL_RATE_MAX_WINDOW - 1; - - if (window->data & mask) { - window->data &= ~mask; - window->success_counter--; - } - } - - /* Increment frames-attempted counter */ - window->counter++; - - /* Shift bitmap by one frame (throw away oldest history), - * OR in "1", and increment "success" if this - * frame was successful. */ - window->data <<= 1; - if (successes > 0) { - window->success_counter++; - window->data |= 0x1; - successes--; - } - - retries--; - } - - /* Calculate current success ratio, avoid divide-by-0! */ - if (window->counter > 0) - window->success_ratio = 128 * (100 * window->success_counter) - / window->counter; - else - window->success_ratio = IWL_INVALID_VALUE; - - fail_count = window->counter - window->success_counter; - - /* Calculate average throughput, if we have enough history. */ - if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) || - (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH)) - window->average_tpt = (window->success_ratio * tpt + 64) / 128; - else - window->average_tpt = IWL_INVALID_VALUE; - - /* Tag this window as having been updated */ - window->stamp = jiffies; - - return 0; -} - -/* - * Fill uCode API rate_n_flags field, based on "search" or "active" table. - */ -/* FIXME:RS:remove this function and put the flags statically in the table */ -static u32 rate_n_flags_from_tbl(struct iwl_priv *priv, - struct iwl_scale_tbl_info *tbl, - int index, u8 use_green) -{ - u32 rate_n_flags = 0; - - if (is_legacy(tbl->lq_type)) { - rate_n_flags = iwl_rates[index].plcp; - if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE) - rate_n_flags |= RATE_MCS_CCK_MSK; - - } else if (is_Ht(tbl->lq_type)) { - if (index > IWL_LAST_OFDM_RATE) { - IWL_ERR(priv, "Invalid HT rate index %d\n", index); - index = IWL_LAST_OFDM_RATE; - } - rate_n_flags = RATE_MCS_HT_MSK; - - if (is_siso(tbl->lq_type)) - rate_n_flags |= iwl_rates[index].plcp_siso; - else if (is_mimo2(tbl->lq_type)) - rate_n_flags |= iwl_rates[index].plcp_mimo2; - else - rate_n_flags |= iwl_rates[index].plcp_mimo3; - } else { - IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type); - } - - rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) & - RATE_MCS_ANT_ABC_MSK); - - if (is_Ht(tbl->lq_type)) { - if (tbl->is_ht40) { - if (tbl->is_dup) - rate_n_flags |= RATE_MCS_DUP_MSK; - else - rate_n_flags |= RATE_MCS_HT40_MSK; - } - if (tbl->is_SGI) - rate_n_flags |= RATE_MCS_SGI_MSK; - - if (use_green) { - rate_n_flags |= RATE_MCS_GF_MSK; - if (is_siso(tbl->lq_type) && tbl->is_SGI) { - rate_n_flags &= ~RATE_MCS_SGI_MSK; - IWL_ERR(priv, "GF was set with SGI:SISO\n"); - } - } - } - return rate_n_flags; -} - -/* - * Interpret uCode API's rate_n_flags format, - * fill "search" or "active" tx mode table. - */ -static int rs_get_tbl_info_from_mcs(const u32 rate_n_flags, - enum ieee80211_band band, - struct iwl_scale_tbl_info *tbl, - int *rate_idx) -{ - u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK); - u8 num_of_ant = get_num_of_ant_from_rate(rate_n_flags); - u8 mcs; - - *rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); - - if (*rate_idx == IWL_RATE_INVALID) { - *rate_idx = -1; - return -EINVAL; - } - tbl->is_SGI = 0; /* default legacy setup */ - tbl->is_ht40 = 0; - tbl->is_dup = 0; - tbl->ant_type = (ant_msk >> RATE_MCS_ANT_POS); - tbl->lq_type = LQ_NONE; - tbl->max_search = IWL_MAX_SEARCH; - - /* legacy rate format */ - if (!(rate_n_flags & RATE_MCS_HT_MSK)) { - if (num_of_ant == 1) { - if (band == IEEE80211_BAND_5GHZ) - tbl->lq_type = LQ_A; - else - tbl->lq_type = LQ_G; - } - /* HT rate format */ - } else { - if (rate_n_flags & RATE_MCS_SGI_MSK) - tbl->is_SGI = 1; - - if ((rate_n_flags & RATE_MCS_HT40_MSK) || - (rate_n_flags & RATE_MCS_DUP_MSK)) - tbl->is_ht40 = 1; - - if (rate_n_flags & RATE_MCS_DUP_MSK) - tbl->is_dup = 1; - - mcs = rs_extract_rate(rate_n_flags); - - /* SISO */ - if (mcs <= IWL_RATE_SISO_60M_PLCP) { - if (num_of_ant == 1) - tbl->lq_type = LQ_SISO; /*else NONE*/ - /* MIMO2 */ - } else if (mcs <= IWL_RATE_MIMO2_60M_PLCP) { - if (num_of_ant == 2) - tbl->lq_type = LQ_MIMO2; - /* MIMO3 */ - } else { - if (num_of_ant == 3) { - tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; - tbl->lq_type = LQ_MIMO3; - } - } - } - return 0; -} - -/* switch to another antenna/antennas and return 1 */ -/* if no other valid antenna found, return 0 */ -static int rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags, - struct iwl_scale_tbl_info *tbl) -{ - u8 new_ant_type; - - if (!tbl->ant_type || tbl->ant_type > ANT_ABC) - return 0; - - if (!rs_is_valid_ant(valid_ant, tbl->ant_type)) - return 0; - - new_ant_type = ant_toggle_lookup[tbl->ant_type]; - - while ((new_ant_type != tbl->ant_type) && - !rs_is_valid_ant(valid_ant, new_ant_type)) - new_ant_type = ant_toggle_lookup[new_ant_type]; - - if (new_ant_type == tbl->ant_type) - return 0; - - tbl->ant_type = new_ant_type; - *rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK; - *rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS; - return 1; -} - -/** - * Green-field mode is valid if the station supports it and - * there are no non-GF stations present in the BSS. - */ -static inline u8 rs_use_green(struct ieee80211_sta *sta, - struct iwl_ht_info *ht_conf) -{ - return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) && - !(ht_conf->non_GF_STA_present); -} - -/** - * rs_get_supported_rates - get the available rates - * - * if management frame or broadcast frame only return - * basic available rates. - * - */ -static u16 rs_get_supported_rates(struct iwl_lq_sta *lq_sta, - struct ieee80211_hdr *hdr, - enum iwl_table_type rate_type) -{ - if (hdr && is_multicast_ether_addr(hdr->addr1) && - lq_sta->active_rate_basic) - return lq_sta->active_rate_basic; - - if (is_legacy(rate_type)) { - return lq_sta->active_legacy_rate; - } else { - if (is_siso(rate_type)) - return lq_sta->active_siso_rate; - else if (is_mimo2(rate_type)) - return lq_sta->active_mimo2_rate; - else - return lq_sta->active_mimo3_rate; - } -} - -static u16 rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask, - int rate_type) -{ - u8 high = IWL_RATE_INVALID; - u8 low = IWL_RATE_INVALID; - - /* 802.11A or ht walks to the next literal adjacent rate in - * the rate table */ - if (is_a_band(rate_type) || !is_legacy(rate_type)) { - int i; - u32 mask; - - /* Find the previous rate that is in the rate mask */ - i = index - 1; - for (mask = (1 << i); i >= 0; i--, mask >>= 1) { - if (rate_mask & mask) { - low = i; - break; - } - } - - /* Find the next rate that is in the rate mask */ - i = index + 1; - for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) { - if (rate_mask & mask) { - high = i; - break; - } - } - - return (high << 8) | low; - } - - low = index; - while (low != IWL_RATE_INVALID) { - low = iwl_rates[low].prev_rs; - if (low == IWL_RATE_INVALID) - break; - if (rate_mask & (1 << low)) - break; - IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low); - } - - high = index; - while (high != IWL_RATE_INVALID) { - high = iwl_rates[high].next_rs; - if (high == IWL_RATE_INVALID) - break; - if (rate_mask & (1 << high)) - break; - IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high); - } - - return (high << 8) | low; -} - -static u32 rs_get_lower_rate(struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, - u8 scale_index, u8 ht_possible) -{ - s32 low; - u16 rate_mask; - u16 high_low; - u8 switch_to_legacy = 0; - u8 is_green = lq_sta->is_green; - struct iwl_priv *priv = lq_sta->drv; - - /* check if we need to switch from HT to legacy rates. - * assumption is that mandatory rates (1Mbps or 6Mbps) - * are always supported (spec demand) */ - if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) { - switch_to_legacy = 1; - scale_index = rs_ht_to_legacy[scale_index]; - if (lq_sta->band == IEEE80211_BAND_5GHZ) - tbl->lq_type = LQ_A; - else - tbl->lq_type = LQ_G; - - if (num_of_ant(tbl->ant_type) > 1) - tbl->ant_type = - first_antenna(priv->hw_params.valid_tx_ant); - - tbl->is_ht40 = 0; - tbl->is_SGI = 0; - tbl->max_search = IWL_MAX_SEARCH; - } - - rate_mask = rs_get_supported_rates(lq_sta, NULL, tbl->lq_type); - - /* Mask with station rate restriction */ - if (is_legacy(tbl->lq_type)) { - /* supp_rates has no CCK bits in A mode */ - if (lq_sta->band == IEEE80211_BAND_5GHZ) - rate_mask = (u16)(rate_mask & - (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); - else - rate_mask = (u16)(rate_mask & lq_sta->supp_rates); - } - - /* If we switched from HT to legacy, check current rate */ - if (switch_to_legacy && (rate_mask & (1 << scale_index))) { - low = scale_index; - goto out; - } - - high_low = rs_get_adjacent_rate(lq_sta->drv, scale_index, rate_mask, - tbl->lq_type); - low = high_low & 0xff; - - if (low == IWL_RATE_INVALID) - low = scale_index; - -out: - return rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green); -} - -/* - * mac80211 sends us Tx status - */ -static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta, - struct sk_buff *skb) -{ - int status; - u8 retries; - int rs_index, mac_index, index = 0; - struct iwl_lq_sta *lq_sta = priv_sta; - struct iwl_link_quality_cmd *table; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_rate_scale_data *window = NULL; - struct iwl_rate_scale_data *search_win = NULL; - enum mac80211_rate_control_flags mac_flags; - u32 tx_rate; - struct iwl_scale_tbl_info tbl_type; - struct iwl_scale_tbl_info *curr_tbl, *search_tbl; - u8 active_index = 0; - s32 tpt = 0; - - IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); - - if (!ieee80211_is_data(hdr->frame_control) || - info->flags & IEEE80211_TX_CTL_NO_ACK) - return; - - /* This packet was aggregated but doesn't carry rate scale info */ - if ((info->flags & IEEE80211_TX_CTL_AMPDU) && - !(info->flags & IEEE80211_TX_STAT_AMPDU)) - return; - - if (info->flags & IEEE80211_TX_STAT_AMPDU) - retries = 0; - else - retries = info->status.rates[0].count - 1; - - if (retries > 15) - retries = 15; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !lq_sta->ibss_sta_added) - goto out; - - table = &lq_sta->lq; - active_index = lq_sta->active_tbl; - - curr_tbl = &(lq_sta->lq_info[active_index]); - search_tbl = &(lq_sta->lq_info[(1 - active_index)]); - window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]); - search_win = (struct iwl_rate_scale_data *)&(search_tbl->win[0]); - - /* - * Ignore this Tx frame response if its initial rate doesn't match - * that of latest Link Quality command. There may be stragglers - * from a previous Link Quality command, but we're no longer interested - * in those; they're either from the "active" mode while we're trying - * to check "search" mode, or a prior "search" mode after we've moved - * to a new "search" mode (which might become the new "active" mode). - */ - tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); - rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); - if (priv->band == IEEE80211_BAND_5GHZ) - rs_index -= IWL_FIRST_OFDM_RATE; - mac_flags = info->status.rates[0].flags; - mac_index = info->status.rates[0].idx; - /* For HT packets, map MCS to PLCP */ - if (mac_flags & IEEE80211_TX_RC_MCS) { - mac_index &= RATE_MCS_CODE_MSK; /* Remove # of streams */ - if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE)) - mac_index++; - /* - * mac80211 HT index is always zero-indexed; we need to move - * HT OFDM rates after CCK rates in 2.4 GHz band - */ - if (priv->band == IEEE80211_BAND_2GHZ) - mac_index += IWL_FIRST_OFDM_RATE; - } - - if ((mac_index < 0) || - (tbl_type.is_SGI != !!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) || - (tbl_type.is_ht40 != !!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) || - (tbl_type.is_dup != !!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) || - (tbl_type.ant_type != info->antenna_sel_tx) || - (!!(tx_rate & RATE_MCS_HT_MSK) != !!(mac_flags & IEEE80211_TX_RC_MCS)) || - (!!(tx_rate & RATE_MCS_GF_MSK) != !!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) || - (rs_index != mac_index)) { - IWL_DEBUG_RATE(priv, "initial rate %d does not match %d (0x%x)\n", mac_index, rs_index, tx_rate); - /* the last LQ command could failed so the LQ in ucode not - * the same in driver sync up - */ - lq_sta->missed_rate_counter++; - if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) { - lq_sta->missed_rate_counter = 0; - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); - } - goto out; - } - - lq_sta->missed_rate_counter = 0; - /* Update frame history window with "failure" for each Tx retry. */ - while (retries) { - /* Look up the rate and other info used for each tx attempt. - * Each tx attempt steps one entry deeper in the rate table. */ - tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); - rs_get_tbl_info_from_mcs(tx_rate, priv->band, - &tbl_type, &rs_index); - - /* If type matches "search" table, - * add failure to "search" history */ - if ((tbl_type.lq_type == search_tbl->lq_type) && - (tbl_type.ant_type == search_tbl->ant_type) && - (tbl_type.is_SGI == search_tbl->is_SGI)) { - if (search_tbl->expected_tpt) - tpt = search_tbl->expected_tpt[rs_index]; - else - tpt = 0; - rs_collect_tx_data(search_win, rs_index, tpt, 1, 0); - - /* Else if type matches "current/active" table, - * add failure to "current/active" history */ - } else if ((tbl_type.lq_type == curr_tbl->lq_type) && - (tbl_type.ant_type == curr_tbl->ant_type) && - (tbl_type.is_SGI == curr_tbl->is_SGI)) { - if (curr_tbl->expected_tpt) - tpt = curr_tbl->expected_tpt[rs_index]; - else - tpt = 0; - rs_collect_tx_data(window, rs_index, tpt, 1, 0); - } - - /* If not searching for a new mode, increment failed counter - * ... this helps determine when to start searching again */ - if (lq_sta->stay_in_tbl) - lq_sta->total_failed++; - --retries; - index++; - - } - - /* - * Find (by rate) the history window to update with final Tx attempt; - * if Tx was successful first try, use original rate, - * else look up the rate that was, finally, successful. - */ - tx_rate = le32_to_cpu(table->rs_table[index].rate_n_flags); - lq_sta->last_rate_n_flags = tx_rate; - rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, &rs_index); - - /* Update frame history window with "success" if Tx got ACKed ... */ - status = !!(info->flags & IEEE80211_TX_STAT_ACK); - - /* If type matches "search" table, - * add final tx status to "search" history */ - if ((tbl_type.lq_type == search_tbl->lq_type) && - (tbl_type.ant_type == search_tbl->ant_type) && - (tbl_type.is_SGI == search_tbl->is_SGI)) { - if (search_tbl->expected_tpt) - tpt = search_tbl->expected_tpt[rs_index]; - else - tpt = 0; - if (info->flags & IEEE80211_TX_STAT_AMPDU) - rs_collect_tx_data(search_win, rs_index, tpt, - info->status.ampdu_ack_len, - info->status.ampdu_ack_map); - else - rs_collect_tx_data(search_win, rs_index, tpt, - 1, status); - /* Else if type matches "current/active" table, - * add final tx status to "current/active" history */ - } else if ((tbl_type.lq_type == curr_tbl->lq_type) && - (tbl_type.ant_type == curr_tbl->ant_type) && - (tbl_type.is_SGI == curr_tbl->is_SGI)) { - if (curr_tbl->expected_tpt) - tpt = curr_tbl->expected_tpt[rs_index]; - else - tpt = 0; - if (info->flags & IEEE80211_TX_STAT_AMPDU) - rs_collect_tx_data(window, rs_index, tpt, - info->status.ampdu_ack_len, - info->status.ampdu_ack_map); - else - rs_collect_tx_data(window, rs_index, tpt, - 1, status); - } - - /* If not searching for new mode, increment success/failed counter - * ... these help determine when to start searching again */ - if (lq_sta->stay_in_tbl) { - if (info->flags & IEEE80211_TX_STAT_AMPDU) { - lq_sta->total_success += info->status.ampdu_ack_map; - lq_sta->total_failed += - (info->status.ampdu_ack_len - info->status.ampdu_ack_map); - } else { - if (status) - lq_sta->total_success++; - else - lq_sta->total_failed++; - } - } - - /* See if there's a better rate or modulation mode to try. */ - if (sta && sta->supp_rates[sband->band]) - rs_rate_scale_perform(priv, skb, sta, lq_sta); -out: - return; -} - -/* - * Begin a period of staying with a selected modulation mode. - * Set "stay_in_tbl" flag to prevent any mode switches. - * Set frame tx success limits according to legacy vs. high-throughput, - * and reset overall (spanning all rates) tx success history statistics. - * These control how long we stay using same modulation mode before - * searching for a new mode. - */ -static void rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy, - struct iwl_lq_sta *lq_sta) -{ - IWL_DEBUG_RATE(priv, "we are staying in the same table\n"); - lq_sta->stay_in_tbl = 1; /* only place this gets set */ - if (is_legacy) { - lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT; - lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT; - lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT; - } else { - lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT; - lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT; - lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT; - } - lq_sta->table_count = 0; - lq_sta->total_failed = 0; - lq_sta->total_success = 0; - lq_sta->flush_timer = jiffies; - lq_sta->action_counter = 0; -} - -/* - * Find correct throughput table for given mode of modulation - */ -static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl) -{ - if (is_legacy(tbl->lq_type)) { - if (!is_a_band(tbl->lq_type)) - tbl->expected_tpt = expected_tpt_G; - else - tbl->expected_tpt = expected_tpt_A; - } else if (is_siso(tbl->lq_type)) { - if (tbl->is_ht40 && !lq_sta->is_dup) - if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_siso40MHzSGI; - else - tbl->expected_tpt = expected_tpt_siso40MHz; - else if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_siso20MHzSGI; - else - tbl->expected_tpt = expected_tpt_siso20MHz; - } else if (is_mimo2(tbl->lq_type)) { - if (tbl->is_ht40 && !lq_sta->is_dup) - if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo2_40MHzSGI; - else - tbl->expected_tpt = expected_tpt_mimo2_40MHz; - else if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo2_20MHzSGI; - else - tbl->expected_tpt = expected_tpt_mimo2_20MHz; - } else if (is_mimo3(tbl->lq_type)) { - if (tbl->is_ht40 && !lq_sta->is_dup) - if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo3_40MHzSGI; - else - tbl->expected_tpt = expected_tpt_mimo3_40MHz; - else if (tbl->is_SGI) - tbl->expected_tpt = expected_tpt_mimo3_20MHzSGI; - else - tbl->expected_tpt = expected_tpt_mimo3_20MHz; - } else - tbl->expected_tpt = expected_tpt_G; -} - -/* - * Find starting rate for new "search" high-throughput mode of modulation. - * Goal is to find lowest expected rate (under perfect conditions) that is - * above the current measured throughput of "active" mode, to give new mode - * a fair chance to prove itself without too many challenges. - * - * This gets called when transitioning to more aggressive modulation - * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive - * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need - * to decrease to match "active" throughput. When moving from MIMO to SISO, - * bit rate will typically need to increase, but not if performance was bad. - */ -static s32 rs_get_best_rate(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, /* "search" */ - u16 rate_mask, s8 index) -{ - /* "active" values */ - struct iwl_scale_tbl_info *active_tbl = - &(lq_sta->lq_info[lq_sta->active_tbl]); - s32 active_sr = active_tbl->win[index].success_ratio; - s32 active_tpt = active_tbl->expected_tpt[index]; - - /* expected "search" throughput */ - s32 *tpt_tbl = tbl->expected_tpt; - - s32 new_rate, high, low, start_hi; - u16 high_low; - s8 rate = index; - - new_rate = high = low = start_hi = IWL_RATE_INVALID; - - for (; ;) { - high_low = rs_get_adjacent_rate(priv, rate, rate_mask, - tbl->lq_type); - - low = high_low & 0xff; - high = (high_low >> 8) & 0xff; - - /* - * Lower the "search" bit rate, to give new "search" mode - * approximately the same throughput as "active" if: - * - * 1) "Active" mode has been working modestly well (but not - * great), and expected "search" throughput (under perfect - * conditions) at candidate rate is above the actual - * measured "active" throughput (but less than expected - * "active" throughput under perfect conditions). - * OR - * 2) "Active" mode has been working perfectly or very well - * and expected "search" throughput (under perfect - * conditions) at candidate rate is above expected - * "active" throughput (under perfect conditions). - */ - if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) && - ((active_sr > IWL_RATE_DECREASE_TH) && - (active_sr <= IWL_RATE_HIGH_TH) && - (tpt_tbl[rate] <= active_tpt))) || - ((active_sr >= IWL_RATE_SCALE_SWITCH) && - (tpt_tbl[rate] > active_tpt))) { - - /* (2nd or later pass) - * If we've already tried to raise the rate, and are - * now trying to lower it, use the higher rate. */ - if (start_hi != IWL_RATE_INVALID) { - new_rate = start_hi; - break; - } - - new_rate = rate; - - /* Loop again with lower rate */ - if (low != IWL_RATE_INVALID) - rate = low; - - /* Lower rate not available, use the original */ - else - break; - - /* Else try to raise the "search" rate to match "active" */ - } else { - /* (2nd or later pass) - * If we've already tried to lower the rate, and are - * now trying to raise it, use the lower rate. */ - if (new_rate != IWL_RATE_INVALID) - break; - - /* Loop again with higher rate */ - else if (high != IWL_RATE_INVALID) { - start_hi = high; - rate = high; - - /* Higher rate not available, use the original */ - } else { - new_rate = rate; - break; - } - } - } - - return new_rate; -} - -/* - * Set up search table for MIMO2 - */ -static int rs_switch_to_mimo2(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, - struct iwl_scale_tbl_info *tbl, int index) -{ - u16 rate_mask; - s32 rate; - s8 is_green = lq_sta->is_green; - - if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) - return -1; - - if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) - == WLAN_HT_CAP_SM_PS_STATIC) - return -1; - - /* Need both Tx chains/antennas to support MIMO */ - if (priv->hw_params.tx_chains_num < 2) - return -1; - - IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n"); - - tbl->lq_type = LQ_MIMO2; - tbl->is_dup = lq_sta->is_dup; - tbl->action = 0; - tbl->max_search = IWL_MAX_SEARCH; - rate_mask = lq_sta->active_mimo2_rate; - - if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) - tbl->is_ht40 = 1; - else - tbl->is_ht40 = 0; - - rs_set_expected_tpt_table(lq_sta, tbl); - - rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); - - IWL_DEBUG_RATE(priv, "LQ: MIMO2 best rate %d mask %X\n", rate, rate_mask); - if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { - IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", - rate, rate_mask); - return -1; - } - tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); - - IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", - tbl->current_rate, is_green); - return 0; -} - -/* - * Set up search table for MIMO3 - */ -static int rs_switch_to_mimo3(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, - struct iwl_scale_tbl_info *tbl, int index) -{ - u16 rate_mask; - s32 rate; - s8 is_green = lq_sta->is_green; - - if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) - return -1; - - if (((sta->ht_cap.cap & IEEE80211_HT_CAP_SM_PS) >> 2) - == WLAN_HT_CAP_SM_PS_STATIC) - return -1; - - /* Need both Tx chains/antennas to support MIMO */ - if (priv->hw_params.tx_chains_num < 3) - return -1; - - IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO3\n"); - - tbl->lq_type = LQ_MIMO3; - tbl->is_dup = lq_sta->is_dup; - tbl->action = 0; - tbl->max_search = IWL_MAX_11N_MIMO3_SEARCH; - rate_mask = lq_sta->active_mimo3_rate; - - if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) - tbl->is_ht40 = 1; - else - tbl->is_ht40 = 0; - - rs_set_expected_tpt_table(lq_sta, tbl); - - rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); - - IWL_DEBUG_RATE(priv, "LQ: MIMO3 best rate %d mask %X\n", - rate, rate_mask); - if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { - IWL_DEBUG_RATE(priv, "Can't switch with index %d rate mask %x\n", - rate, rate_mask); - return -1; - } - tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); - - IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", - tbl->current_rate, is_green); - return 0; -} - -/* - * Set up search table for SISO - */ -static int rs_switch_to_siso(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, - struct iwl_scale_tbl_info *tbl, int index) -{ - u16 rate_mask; - u8 is_green = lq_sta->is_green; - s32 rate; - - if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported) - return -1; - - IWL_DEBUG_RATE(priv, "LQ: try to switch to SISO\n"); - - tbl->is_dup = lq_sta->is_dup; - tbl->lq_type = LQ_SISO; - tbl->action = 0; - tbl->max_search = IWL_MAX_SEARCH; - rate_mask = lq_sta->active_siso_rate; - - if (iwl_is_ht40_tx_allowed(priv, &sta->ht_cap)) - tbl->is_ht40 = 1; - else - tbl->is_ht40 = 0; - - if (is_green) - tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/ - - rs_set_expected_tpt_table(lq_sta, tbl); - rate = rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index); - - IWL_DEBUG_RATE(priv, "LQ: get best rate %d mask %X\n", rate, rate_mask); - if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) { - IWL_DEBUG_RATE(priv, "can not switch with index %d rate mask %x\n", - rate, rate_mask); - return -1; - } - tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, rate, is_green); - IWL_DEBUG_RATE(priv, "LQ: Switch to new mcs %X index is green %X\n", - tbl->current_rate, is_green); - return 0; -} - -/* - * Try to switch to new modulation mode from legacy - */ -static int rs_move_legacy_other(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, - int index) -{ - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl_rate_scale_data *window = &(tbl->win[index]); - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; - int ret = 0; - u8 update_search_tbl_counter = 0; - - if (!iwl_ht_enabled(priv)) - /* stay in Legacy */ - tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; - else if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && - tbl->action > IWL_LEGACY_SWITCH_SISO) - tbl->action = IWL_LEGACY_SWITCH_SISO; - for (; ;) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_LEGACY_SWITCH_ANTENNA1: - case IWL_LEGACY_SWITCH_ANTENNA2: - IWL_DEBUG_RATE(priv, "LQ: Legacy toggle Antenna\n"); - - if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 && - tx_chains_num <= 1) || - (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 && - tx_chains_num <= 2)) - break; - - /* Don't change antenna if success has been great */ - if (window->success_ratio >= IWL_RS_GOOD_RATIO) - break; - - /* Set up search table to try other antenna */ - memcpy(search_tbl, tbl, sz); - - if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) { - update_search_tbl_counter = 1; - rs_set_expected_tpt_table(lq_sta, search_tbl); - goto out; - } - break; - case IWL_LEGACY_SWITCH_SISO: - IWL_DEBUG_RATE(priv, "LQ: Legacy switch to SISO\n"); - - /* Set up search table to try SISO */ - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - ret = rs_switch_to_siso(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) { - lq_sta->action_counter = 0; - goto out; - } - - break; - case IWL_LEGACY_SWITCH_MIMO2_AB: - case IWL_LEGACY_SWITCH_MIMO2_AC: - case IWL_LEGACY_SWITCH_MIMO2_BC: - IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO2\n"); - - /* Set up search table to try MIMO */ - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - - if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB) - search_tbl->ant_type = ANT_AB; - else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC) - search_tbl->ant_type = ANT_AC; - else - search_tbl->ant_type = ANT_BC; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) { - lq_sta->action_counter = 0; - goto out; - } - break; - - case IWL_LEGACY_SWITCH_MIMO3_ABC: - IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO3\n"); - - /* Set up search table to try MIMO3 */ - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - - search_tbl->ant_type = ANT_ABC; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) { - lq_sta->action_counter = 0; - goto out; - } - break; - } - tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) - tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; - - if (tbl->action == start_action) - break; - - } - search_tbl->lq_type = LQ_NONE; - return 0; - -out: - lq_sta->search_better_tbl = 1; - tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) - tbl->action = IWL_LEGACY_SWITCH_ANTENNA1; - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - return 0; - -} - -/* - * Try to switch to new modulation mode from SISO - */ -static int rs_move_siso_to_other(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, int index) -{ - u8 is_green = lq_sta->is_green; - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl_rate_scale_data *window = &(tbl->win[index]); - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; - u8 update_search_tbl_counter = 0; - int ret; - - if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE && - tbl->action > IWL_SISO_SWITCH_ANTENNA2) { - /* stay in SISO */ - tbl->action = IWL_SISO_SWITCH_ANTENNA1; - } - for (;;) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_SISO_SWITCH_ANTENNA1: - case IWL_SISO_SWITCH_ANTENNA2: - IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n"); - - if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 && - tx_chains_num <= 1) || - (tbl->action == IWL_SISO_SWITCH_ANTENNA2 && - tx_chains_num <= 2)) - break; - - if (window->success_ratio >= IWL_RS_GOOD_RATIO) - break; - - memcpy(search_tbl, tbl, sz); - if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) { - update_search_tbl_counter = 1; - goto out; - } - break; - case IWL_SISO_SWITCH_MIMO2_AB: - case IWL_SISO_SWITCH_MIMO2_AC: - case IWL_SISO_SWITCH_MIMO2_BC: - IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO2\n"); - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - - if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB) - search_tbl->ant_type = ANT_AB; - else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC) - search_tbl->ant_type = ANT_AC; - else - search_tbl->ant_type = ANT_BC; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) - goto out; - break; - case IWL_SISO_SWITCH_GI: - if (!tbl->is_ht40 && !(ht_cap->cap & - IEEE80211_HT_CAP_SGI_20)) - break; - if (tbl->is_ht40 && !(ht_cap->cap & - IEEE80211_HT_CAP_SGI_40)) - break; - - IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n"); - - memcpy(search_tbl, tbl, sz); - if (is_green) { - if (!tbl->is_SGI) - break; - else - IWL_ERR(priv, - "SGI was set in GF+SISO\n"); - } - search_tbl->is_SGI = !tbl->is_SGI; - rs_set_expected_tpt_table(lq_sta, search_tbl); - if (tbl->is_SGI) { - s32 tpt = lq_sta->last_tpt / 100; - if (tpt >= search_tbl->expected_tpt[index]) - break; - } - search_tbl->current_rate = - rate_n_flags_from_tbl(priv, search_tbl, - index, is_green); - update_search_tbl_counter = 1; - goto out; - case IWL_SISO_SWITCH_MIMO3_ABC: - IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO3\n"); - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - search_tbl->ant_type = ANT_ABC; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) - goto out; - break; - } - tbl->action++; - if (tbl->action > IWL_LEGACY_SWITCH_MIMO3_ABC) - tbl->action = IWL_SISO_SWITCH_ANTENNA1; - - if (tbl->action == start_action) - break; - } - search_tbl->lq_type = LQ_NONE; - return 0; - - out: - lq_sta->search_better_tbl = 1; - tbl->action++; - if (tbl->action > IWL_SISO_SWITCH_MIMO3_ABC) - tbl->action = IWL_SISO_SWITCH_ANTENNA1; - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - - return 0; -} - -/* - * Try to switch to new modulation mode from MIMO2 - */ -static int rs_move_mimo2_to_other(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, int index) -{ - s8 is_green = lq_sta->is_green; - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl_rate_scale_data *window = &(tbl->win[index]); - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; - u8 update_search_tbl_counter = 0; - int ret; - - if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && - (tbl->action < IWL_MIMO2_SWITCH_SISO_A || - tbl->action > IWL_MIMO2_SWITCH_SISO_C)) { - /* switch in SISO */ - tbl->action = IWL_MIMO2_SWITCH_SISO_A; - } - for (;;) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_MIMO2_SWITCH_ANTENNA1: - case IWL_MIMO2_SWITCH_ANTENNA2: - IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n"); - - if (tx_chains_num <= 2) - break; - - if (window->success_ratio >= IWL_RS_GOOD_RATIO) - break; - - memcpy(search_tbl, tbl, sz); - if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) { - update_search_tbl_counter = 1; - goto out; - } - break; - case IWL_MIMO2_SWITCH_SISO_A: - case IWL_MIMO2_SWITCH_SISO_B: - case IWL_MIMO2_SWITCH_SISO_C: - IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to SISO\n"); - - /* Set up new search table for SISO */ - memcpy(search_tbl, tbl, sz); - - if (tbl->action == IWL_MIMO2_SWITCH_SISO_A) - search_tbl->ant_type = ANT_A; - else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B) - search_tbl->ant_type = ANT_B; - else - search_tbl->ant_type = ANT_C; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_siso(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) - goto out; - - break; - - case IWL_MIMO2_SWITCH_GI: - if (!tbl->is_ht40 && !(ht_cap->cap & - IEEE80211_HT_CAP_SGI_20)) - break; - if (tbl->is_ht40 && !(ht_cap->cap & - IEEE80211_HT_CAP_SGI_40)) - break; - - IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n"); - - /* Set up new search table for MIMO2 */ - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = !tbl->is_SGI; - rs_set_expected_tpt_table(lq_sta, search_tbl); - /* - * If active table already uses the fastest possible - * modulation (dual stream with short guard interval), - * and it's working well, there's no need to look - * for a better type of modulation! - */ - if (tbl->is_SGI) { - s32 tpt = lq_sta->last_tpt / 100; - if (tpt >= search_tbl->expected_tpt[index]) - break; - } - search_tbl->current_rate = - rate_n_flags_from_tbl(priv, search_tbl, - index, is_green); - update_search_tbl_counter = 1; - goto out; - - case IWL_MIMO2_SWITCH_MIMO3_ABC: - IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to MIMO3\n"); - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - search_tbl->ant_type = ANT_ABC; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_mimo3(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) - goto out; - - break; - } - tbl->action++; - if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) - tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; - - if (tbl->action == start_action) - break; - } - search_tbl->lq_type = LQ_NONE; - return 0; - out: - lq_sta->search_better_tbl = 1; - tbl->action++; - if (tbl->action > IWL_MIMO2_SWITCH_MIMO3_ABC) - tbl->action = IWL_MIMO2_SWITCH_ANTENNA1; - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - - return 0; - -} - -/* - * Try to switch to new modulation mode from MIMO3 - */ -static int rs_move_mimo3_to_other(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, int index) -{ - s8 is_green = lq_sta->is_green; - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - struct iwl_scale_tbl_info *search_tbl = - &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - struct iwl_rate_scale_data *window = &(tbl->win[index]); - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - u32 sz = (sizeof(struct iwl_scale_tbl_info) - - (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT)); - u8 start_action = tbl->action; - u8 valid_tx_ant = priv->hw_params.valid_tx_ant; - u8 tx_chains_num = priv->hw_params.tx_chains_num; - int ret; - u8 update_search_tbl_counter = 0; - - if ((iwl_tx_ant_restriction(priv) == IWL_ANT_OK_SINGLE) && - (tbl->action < IWL_MIMO3_SWITCH_SISO_A || - tbl->action > IWL_MIMO3_SWITCH_SISO_C)) { - /* switch in SISO */ - tbl->action = IWL_MIMO3_SWITCH_SISO_A; - } - for (;;) { - lq_sta->action_counter++; - switch (tbl->action) { - case IWL_MIMO3_SWITCH_ANTENNA1: - case IWL_MIMO3_SWITCH_ANTENNA2: - IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle Antennas\n"); - - if (tx_chains_num <= 3) - break; - - if (window->success_ratio >= IWL_RS_GOOD_RATIO) - break; - - memcpy(search_tbl, tbl, sz); - if (rs_toggle_antenna(valid_tx_ant, - &search_tbl->current_rate, search_tbl)) - goto out; - break; - case IWL_MIMO3_SWITCH_SISO_A: - case IWL_MIMO3_SWITCH_SISO_B: - case IWL_MIMO3_SWITCH_SISO_C: - IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to SISO\n"); - - /* Set up new search table for SISO */ - memcpy(search_tbl, tbl, sz); - - if (tbl->action == IWL_MIMO3_SWITCH_SISO_A) - search_tbl->ant_type = ANT_A; - else if (tbl->action == IWL_MIMO3_SWITCH_SISO_B) - search_tbl->ant_type = ANT_B; - else - search_tbl->ant_type = ANT_C; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_siso(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) - goto out; - - break; - - case IWL_MIMO3_SWITCH_MIMO2_AB: - case IWL_MIMO3_SWITCH_MIMO2_AC: - case IWL_MIMO3_SWITCH_MIMO2_BC: - IWL_DEBUG_RATE(priv, "LQ: MIMO3 switch to MIMO2\n"); - - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = 0; - if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AB) - search_tbl->ant_type = ANT_AB; - else if (tbl->action == IWL_MIMO3_SWITCH_MIMO2_AC) - search_tbl->ant_type = ANT_AC; - else - search_tbl->ant_type = ANT_BC; - - if (!rs_is_valid_ant(valid_tx_ant, search_tbl->ant_type)) - break; - - ret = rs_switch_to_mimo2(priv, lq_sta, conf, sta, - search_tbl, index); - if (!ret) - goto out; - - break; - - case IWL_MIMO3_SWITCH_GI: - if (!tbl->is_ht40 && !(ht_cap->cap & - IEEE80211_HT_CAP_SGI_20)) - break; - if (tbl->is_ht40 && !(ht_cap->cap & - IEEE80211_HT_CAP_SGI_40)) - break; - - IWL_DEBUG_RATE(priv, "LQ: MIMO3 toggle SGI/NGI\n"); - - /* Set up new search table for MIMO */ - memcpy(search_tbl, tbl, sz); - search_tbl->is_SGI = !tbl->is_SGI; - rs_set_expected_tpt_table(lq_sta, search_tbl); - /* - * If active table already uses the fastest possible - * modulation (dual stream with short guard interval), - * and it's working well, there's no need to look - * for a better type of modulation! - */ - if (tbl->is_SGI) { - s32 tpt = lq_sta->last_tpt / 100; - if (tpt >= search_tbl->expected_tpt[index]) - break; - } - search_tbl->current_rate = - rate_n_flags_from_tbl(priv, search_tbl, - index, is_green); - update_search_tbl_counter = 1; - goto out; - } - tbl->action++; - if (tbl->action > IWL_MIMO3_SWITCH_GI) - tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; - - if (tbl->action == start_action) - break; - } - search_tbl->lq_type = LQ_NONE; - return 0; - out: - lq_sta->search_better_tbl = 1; - tbl->action++; - if (tbl->action > IWL_MIMO3_SWITCH_GI) - tbl->action = IWL_MIMO3_SWITCH_ANTENNA1; - if (update_search_tbl_counter) - search_tbl->action = tbl->action; - - return 0; - -} - -/* - * Check whether we should continue using same modulation mode, or - * begin search for a new mode, based on: - * 1) # tx successes or failures while using this mode - * 2) # times calling this function - * 3) elapsed time in this mode (not used, for now) - */ -static void rs_stay_in_table(struct iwl_lq_sta *lq_sta) -{ - struct iwl_scale_tbl_info *tbl; - int i; - int active_tbl; - int flush_interval_passed = 0; - struct iwl_priv *priv; - - priv = lq_sta->drv; - active_tbl = lq_sta->active_tbl; - - tbl = &(lq_sta->lq_info[active_tbl]); - - /* If we've been disallowing search, see if we should now allow it */ - if (lq_sta->stay_in_tbl) { - - /* Elapsed time using current modulation mode */ - if (lq_sta->flush_timer) - flush_interval_passed = - time_after(jiffies, - (unsigned long)(lq_sta->flush_timer + - IWL_RATE_SCALE_FLUSH_INTVL)); - - /* - * Check if we should allow search for new modulation mode. - * If many frames have failed or succeeded, or we've used - * this same modulation for a long time, allow search, and - * reset history stats that keep track of whether we should - * allow a new search. Also (below) reset all bitmaps and - * stats in active history. - */ - if ((lq_sta->total_failed > lq_sta->max_failure_limit) || - (lq_sta->total_success > lq_sta->max_success_limit) || - ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer) - && (flush_interval_passed))) { - IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n:", - lq_sta->total_failed, - lq_sta->total_success, - flush_interval_passed); - - /* Allow search for new mode */ - lq_sta->stay_in_tbl = 0; /* only place reset */ - lq_sta->total_failed = 0; - lq_sta->total_success = 0; - lq_sta->flush_timer = 0; - - /* - * Else if we've used this modulation mode enough repetitions - * (regardless of elapsed time or success/failure), reset - * history bitmaps and rate-specific stats for all rates in - * active table. - */ - } else { - lq_sta->table_count++; - if (lq_sta->table_count >= - lq_sta->table_count_limit) { - lq_sta->table_count = 0; - - IWL_DEBUG_RATE(priv, "LQ: stay in table clear win\n"); - for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window( - &(tbl->win[i])); - } - } - - /* If transitioning to allow "search", reset all history - * bitmaps and stats in active table (this will become the new - * "search" table). */ - if (!lq_sta->stay_in_tbl) { - for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&(tbl->win[i])); - } - } -} - -/* - * setup rate table in uCode - * return rate_n_flags as used in the table - */ -static u32 rs_update_rate_tbl(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, - struct iwl_scale_tbl_info *tbl, - int index, u8 is_green) -{ - u32 rate; - - /* Update uCode's rate table. */ - rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); - rs_fill_link_cmd(priv, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); - - return rate; -} - -/* - * Do rate scaling and search for new modulation mode. - */ -static void rs_rate_scale_perform(struct iwl_priv *priv, - struct sk_buff *skb, - struct ieee80211_sta *sta, - struct iwl_lq_sta *lq_sta) -{ - struct ieee80211_hw *hw = priv->hw; - struct ieee80211_conf *conf = &hw->conf; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - int low = IWL_RATE_INVALID; - int high = IWL_RATE_INVALID; - int index; - int i; - struct iwl_rate_scale_data *window = NULL; - int current_tpt = IWL_INVALID_VALUE; - int low_tpt = IWL_INVALID_VALUE; - int high_tpt = IWL_INVALID_VALUE; - u32 fail_count; - s8 scale_action = 0; - u16 rate_mask; - u8 update_lq = 0; - struct iwl_scale_tbl_info *tbl, *tbl1; - u16 rate_scale_index_msk = 0; - u32 rate; - u8 is_green = 0; - u8 active_tbl = 0; - u8 done_search = 0; - u16 high_low; - s32 sr; - u8 tid = MAX_TID_COUNT; - struct iwl_tid_data *tid_data; - - IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n"); - - /* Send management frames and NO_ACK data using lowest rate. */ - /* TODO: this could probably be improved.. */ - if (!ieee80211_is_data(hdr->frame_control) || - info->flags & IEEE80211_TX_CTL_NO_ACK) - return; - - if (!sta || !lq_sta) - return; - - lq_sta->supp_rates = sta->supp_rates[lq_sta->band]; - - tid = rs_tl_add_packet(lq_sta, hdr); - - /* - * Select rate-scale / modulation-mode table to work with in - * the rest of this function: "search" if searching for better - * modulation mode, or "active" if doing rate scaling within a mode. - */ - if (!lq_sta->search_better_tbl) - active_tbl = lq_sta->active_tbl; - else - active_tbl = 1 - lq_sta->active_tbl; - - tbl = &(lq_sta->lq_info[active_tbl]); - if (is_legacy(tbl->lq_type)) - lq_sta->is_green = 0; - else - lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); - is_green = lq_sta->is_green; - - /* current tx rate */ - index = lq_sta->last_txrate_idx; - - IWL_DEBUG_RATE(priv, "Rate scale index %d for type %d\n", index, - tbl->lq_type); - - /* rates available for this association, and for modulation mode */ - rate_mask = rs_get_supported_rates(lq_sta, hdr, tbl->lq_type); - - IWL_DEBUG_RATE(priv, "mask 0x%04X \n", rate_mask); - - /* mask with station rate restriction */ - if (is_legacy(tbl->lq_type)) { - if (lq_sta->band == IEEE80211_BAND_5GHZ) - /* supp_rates has no CCK bits in A mode */ - rate_scale_index_msk = (u16) (rate_mask & - (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE)); - else - rate_scale_index_msk = (u16) (rate_mask & - lq_sta->supp_rates); - - } else - rate_scale_index_msk = rate_mask; - - if (!rate_scale_index_msk) - rate_scale_index_msk = rate_mask; - - if (!((1 << index) & rate_scale_index_msk)) { - IWL_ERR(priv, "Current Rate is not valid\n"); - if (lq_sta->search_better_tbl) { - /* revert to active table if search table is not valid*/ - tbl->lq_type = LQ_NONE; - lq_sta->search_better_tbl = 0; - tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - /* get "active" rate info */ - index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - rate = rs_update_rate_tbl(priv, lq_sta, - tbl, index, is_green); - } - return; - } - - /* Get expected throughput table and history window for current rate */ - if (!tbl->expected_tpt) { - IWL_ERR(priv, "tbl->expected_tpt is NULL\n"); - return; - } - - /* force user max rate if set by user */ - if ((lq_sta->max_rate_idx != -1) && - (lq_sta->max_rate_idx < index)) { - index = lq_sta->max_rate_idx; - update_lq = 1; - window = &(tbl->win[index]); - goto lq_update; - } - - window = &(tbl->win[index]); - - /* - * If there is not enough history to calculate actual average - * throughput, keep analyzing results of more tx frames, without - * changing rate or mode (bypass most of the rest of this function). - * Set up new rate table in uCode only if old rate is not supported - * in current association (use new rate found above). - */ - fail_count = window->counter - window->success_counter; - if ((fail_count < IWL_RATE_MIN_FAILURE_TH) && - (window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) { - IWL_DEBUG_RATE(priv, "LQ: still below TH. succ=%d total=%d " - "for index %d\n", - window->success_counter, window->counter, index); - - /* Can't calculate this yet; not enough history */ - window->average_tpt = IWL_INVALID_VALUE; - - /* Should we stay with this modulation mode, - * or search for a new one? */ - rs_stay_in_table(lq_sta); - - goto out; - } - - /* Else we have enough samples; calculate estimate of - * actual average throughput */ - if (window->average_tpt != ((window->success_ratio * - tbl->expected_tpt[index] + 64) / 128)) { - IWL_ERR(priv, "expected_tpt should have been calculated by now\n"); - window->average_tpt = ((window->success_ratio * - tbl->expected_tpt[index] + 64) / 128); - } - - /* If we are searching for better modulation mode, check success. */ - if (lq_sta->search_better_tbl && - (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI)) { - /* If good success, continue using the "search" mode; - * no need to send new link quality command, since we're - * continuing to use the setup that we've been trying. */ - if (window->average_tpt > lq_sta->last_tpt) { - - IWL_DEBUG_RATE(priv, "LQ: SWITCHING TO NEW TABLE " - "suc=%d cur-tpt=%d old-tpt=%d\n", - window->success_ratio, - window->average_tpt, - lq_sta->last_tpt); - - if (!is_legacy(tbl->lq_type)) - lq_sta->enable_counter = 1; - - /* Swap tables; "search" becomes "active" */ - lq_sta->active_tbl = active_tbl; - current_tpt = window->average_tpt; - - /* Else poor success; go back to mode in "active" table */ - } else { - - IWL_DEBUG_RATE(priv, "LQ: GOING BACK TO THE OLD TABLE " - "suc=%d cur-tpt=%d old-tpt=%d\n", - window->success_ratio, - window->average_tpt, - lq_sta->last_tpt); - - /* Nullify "search" table */ - tbl->lq_type = LQ_NONE; - - /* Revert to "active" table */ - active_tbl = lq_sta->active_tbl; - tbl = &(lq_sta->lq_info[active_tbl]); - - /* Revert to "active" rate and throughput info */ - index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - current_tpt = lq_sta->last_tpt; - - /* Need to set up a new rate table in uCode */ - update_lq = 1; - } - - /* Either way, we've made a decision; modulation mode - * search is done, allow rate adjustment next time. */ - lq_sta->search_better_tbl = 0; - done_search = 1; /* Don't switch modes below! */ - goto lq_update; - } - - /* (Else) not in search of better modulation mode, try for better - * starting rate, while staying in this mode. */ - high_low = rs_get_adjacent_rate(priv, index, rate_scale_index_msk, - tbl->lq_type); - low = high_low & 0xff; - high = (high_low >> 8) & 0xff; - - /* If user set max rate, dont allow higher than user constrain */ - if ((lq_sta->max_rate_idx != -1) && - (lq_sta->max_rate_idx < high)) - high = IWL_RATE_INVALID; - - sr = window->success_ratio; - - /* Collect measured throughputs for current and adjacent rates */ - current_tpt = window->average_tpt; - if (low != IWL_RATE_INVALID) - low_tpt = tbl->win[low].average_tpt; - if (high != IWL_RATE_INVALID) - high_tpt = tbl->win[high].average_tpt; - - scale_action = 0; - - /* Too many failures, decrease rate */ - if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) { - IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n"); - scale_action = -1; - - /* No throughput measured yet for adjacent rates; try increase. */ - } else if ((low_tpt == IWL_INVALID_VALUE) && - (high_tpt == IWL_INVALID_VALUE)) { - - if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH) - scale_action = 1; - else if (low != IWL_RATE_INVALID) - scale_action = 0; - } - - /* Both adjacent throughputs are measured, but neither one has better - * throughput; we're using the best rate, don't change it! */ - else if ((low_tpt != IWL_INVALID_VALUE) && - (high_tpt != IWL_INVALID_VALUE) && - (low_tpt < current_tpt) && - (high_tpt < current_tpt)) - scale_action = 0; - - /* At least one adjacent rate's throughput is measured, - * and may have better performance. */ - else { - /* Higher adjacent rate's throughput is measured */ - if (high_tpt != IWL_INVALID_VALUE) { - /* Higher rate has better throughput */ - if (high_tpt > current_tpt && - sr >= IWL_RATE_INCREASE_TH) { - scale_action = 1; - } else { - scale_action = 0; - } - - /* Lower adjacent rate's throughput is measured */ - } else if (low_tpt != IWL_INVALID_VALUE) { - /* Lower rate has better throughput */ - if (low_tpt > current_tpt) { - IWL_DEBUG_RATE(priv, - "decrease rate because of low tpt\n"); - scale_action = -1; - } else if (sr >= IWL_RATE_INCREASE_TH) { - scale_action = 1; - } - } - } - - /* Sanity check; asked for decrease, but success rate or throughput - * has been good at old rate. Don't change it. */ - if ((scale_action == -1) && (low != IWL_RATE_INVALID) && - ((sr > IWL_RATE_HIGH_TH) || - (current_tpt > (100 * tbl->expected_tpt[low])))) - scale_action = 0; - if (!iwl_ht_enabled(priv) && !is_legacy(tbl->lq_type)) - scale_action = -1; - if (iwl_tx_ant_restriction(priv) != IWL_ANT_OK_MULTI && - (is_mimo2(tbl->lq_type) || is_mimo3(tbl->lq_type))) - scale_action = -1; - switch (scale_action) { - case -1: - /* Decrease starting rate, update uCode's rate table */ - if (low != IWL_RATE_INVALID) { - update_lq = 1; - index = low; - } - - break; - case 1: - /* Increase starting rate, update uCode's rate table */ - if (high != IWL_RATE_INVALID) { - update_lq = 1; - index = high; - } - - break; - case 0: - /* No change */ - default: - break; - } - - IWL_DEBUG_RATE(priv, "choose rate scale index %d action %d low %d " - "high %d type %d\n", - index, scale_action, low, high, tbl->lq_type); - -lq_update: - /* Replace uCode's rate table for the destination station. */ - if (update_lq) - rate = rs_update_rate_tbl(priv, lq_sta, - tbl, index, is_green); - - if (iwl_tx_ant_restriction(priv) == IWL_ANT_OK_MULTI) { - /* Should we stay with this modulation mode, - * or search for a new one? */ - rs_stay_in_table(lq_sta); - } - /* - * Search for new modulation mode if we're: - * 1) Not changing rates right now - * 2) Not just finishing up a search - * 3) Allowing a new search - */ - if (!update_lq && !done_search && !lq_sta->stay_in_tbl && window->counter) { - /* Save current throughput to compare with "search" throughput*/ - lq_sta->last_tpt = current_tpt; - - /* Select a new "search" modulation mode to try. - * If one is found, set up the new "search" table. */ - if (is_legacy(tbl->lq_type)) - rs_move_legacy_other(priv, lq_sta, conf, sta, index); - else if (is_siso(tbl->lq_type)) - rs_move_siso_to_other(priv, lq_sta, conf, sta, index); - else if (is_mimo2(tbl->lq_type)) - rs_move_mimo2_to_other(priv, lq_sta, conf, sta, index); - else - rs_move_mimo3_to_other(priv, lq_sta, conf, sta, index); - - /* If new "search" mode was selected, set up in uCode table */ - if (lq_sta->search_better_tbl) { - /* Access the "search" table, clear its history. */ - tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]); - for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&(tbl->win[i])); - - /* Use new "search" start rate */ - index = iwl_hwrate_to_plcp_idx(tbl->current_rate); - - IWL_DEBUG_RATE(priv, "Switch current mcs: %X index: %d\n", - tbl->current_rate, index); - rs_fill_link_cmd(priv, lq_sta, tbl->current_rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); - } else - done_search = 1; - } - - if (done_search && !lq_sta->stay_in_tbl) { - /* If the "active" (non-search) mode was legacy, - * and we've tried switching antennas, - * but we haven't been able to try HT modes (not available), - * stay with best antenna legacy modulation for a while - * before next round of mode comparisons. */ - tbl1 = &(lq_sta->lq_info[lq_sta->active_tbl]); - if (is_legacy(tbl1->lq_type) && !conf_is_ht(conf) && - lq_sta->action_counter > tbl1->max_search) { - IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n"); - rs_set_stay_in_table(priv, 1, lq_sta); - } - - /* If we're in an HT mode, and all 3 mode switch actions - * have been tried and compared, stay in this best modulation - * mode for a while before next round of mode comparisons. */ - if (lq_sta->enable_counter && - (lq_sta->action_counter >= tbl1->max_search) && - iwl_ht_enabled(priv)) { - if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) && - (lq_sta->tx_agg_tid_en & (1 << tid)) && - (tid != MAX_TID_COUNT)) { - tid_data = - &priv->stations[lq_sta->lq.sta_id].tid[tid]; - if (tid_data->agg.state == IWL_AGG_OFF) { - IWL_DEBUG_RATE(priv, - "try to aggregate tid %d\n", - tid); - rs_tl_turn_on_agg(priv, tid, - lq_sta, sta); - } - } - rs_set_stay_in_table(priv, 0, lq_sta); - } - } - -out: - tbl->current_rate = rate_n_flags_from_tbl(priv, tbl, index, is_green); - i = index; - lq_sta->last_txrate_idx = i; - - return; -} - - -static void rs_initialize_lq(struct iwl_priv *priv, - struct ieee80211_conf *conf, - struct ieee80211_sta *sta, - struct iwl_lq_sta *lq_sta) -{ - struct iwl_scale_tbl_info *tbl; - int rate_idx; - int i; - u32 rate; - u8 use_green = rs_use_green(sta, &priv->current_ht_config); - u8 active_tbl = 0; - u8 valid_tx_ant; - - if (!sta || !lq_sta) - goto out; - - i = lq_sta->last_txrate_idx; - - if ((lq_sta->lq.sta_id == 0xff) && - (priv->iw_mode == NL80211_IFTYPE_ADHOC)) - goto out; - - valid_tx_ant = priv->hw_params.valid_tx_ant; - - if (!lq_sta->search_better_tbl) - active_tbl = lq_sta->active_tbl; - else - active_tbl = 1 - lq_sta->active_tbl; - - tbl = &(lq_sta->lq_info[active_tbl]); - - if ((i < 0) || (i >= IWL_RATE_COUNT)) - i = 0; - - rate = iwl_rates[i].plcp; - tbl->ant_type = first_antenna(valid_tx_ant); - rate |= tbl->ant_type << RATE_MCS_ANT_POS; - - if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE) - rate |= RATE_MCS_CCK_MSK; - - rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx); - if (!rs_is_valid_ant(valid_tx_ant, tbl->ant_type)) - rs_toggle_antenna(valid_tx_ant, &rate, tbl); - - rate = rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green); - tbl->current_rate = rate; - rs_set_expected_tpt_table(lq_sta, tbl); - rs_fill_link_cmd(NULL, lq_sta, rate); - iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); - out: - return; -} - -static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta, - struct ieee80211_tx_rate_control *txrc) -{ - - struct sk_buff *skb = txrc->skb; - struct ieee80211_supported_band *sband = txrc->sband; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; - struct ieee80211_conf *conf = &priv->hw->conf; - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_lq_sta *lq_sta = priv_sta; - int rate_idx; - - IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n"); - - /* Get max rate if user set max rate */ - if (lq_sta) { - lq_sta->max_rate_idx = txrc->max_rate_idx; - if ((sband->band == IEEE80211_BAND_5GHZ) && - (lq_sta->max_rate_idx != -1)) - lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE; - if ((lq_sta->max_rate_idx < 0) || - (lq_sta->max_rate_idx >= IWL_RATE_COUNT)) - lq_sta->max_rate_idx = -1; - } - - /* Send management frames and NO_ACK data using lowest rate. */ - if (rate_control_send_low(sta, priv_sta, txrc)) - return; - - rate_idx = lq_sta->last_txrate_idx; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !lq_sta->ibss_sta_added) { - u8 sta_id = iwl_find_station(priv, hdr->addr1); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", - hdr->addr1); - sta_id = iwl_add_station(priv, hdr->addr1, - false, CMD_ASYNC, ht_cap); - } - if ((sta_id != IWL_INVALID_STATION)) { - lq_sta->lq.sta_id = sta_id; - lq_sta->lq.rs_table[0].rate_n_flags = 0; - lq_sta->ibss_sta_added = 1; - rs_initialize_lq(priv, conf, sta, lq_sta); - } - } - - if (lq_sta->last_rate_n_flags & RATE_MCS_HT_MSK) { - rate_idx -= IWL_FIRST_OFDM_RATE; - /* 6M and 9M shared same MCS index */ - rate_idx = (rate_idx > 0) ? (rate_idx - 1) : 0; - if (rs_extract_rate(lq_sta->last_rate_n_flags) >= - IWL_RATE_MIMO3_6M_PLCP) - rate_idx = rate_idx + (2 * MCS_INDEX_PER_STREAM); - else if (rs_extract_rate(lq_sta->last_rate_n_flags) >= - IWL_RATE_MIMO2_6M_PLCP) - rate_idx = rate_idx + MCS_INDEX_PER_STREAM; - info->control.rates[0].flags = IEEE80211_TX_RC_MCS; - if (lq_sta->last_rate_n_flags & RATE_MCS_SGI_MSK) - info->control.rates[0].flags |= IEEE80211_TX_RC_SHORT_GI; - if (lq_sta->last_rate_n_flags & RATE_MCS_DUP_MSK) - info->control.rates[0].flags |= IEEE80211_TX_RC_DUP_DATA; - if (lq_sta->last_rate_n_flags & RATE_MCS_HT40_MSK) - info->control.rates[0].flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (lq_sta->last_rate_n_flags & RATE_MCS_GF_MSK) - info->control.rates[0].flags |= IEEE80211_TX_RC_GREEN_FIELD; - } else { - /* Check for invalid rates */ - if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) || - ((sband->band == IEEE80211_BAND_5GHZ) && - (rate_idx < IWL_FIRST_OFDM_RATE))) - rate_idx = rate_lowest_index(sband, sta); - /* On valid 5 GHz rate, adjust index */ - else if (sband->band == IEEE80211_BAND_5GHZ) - rate_idx -= IWL_FIRST_OFDM_RATE; - info->control.rates[0].flags = 0; - } - info->control.rates[0].idx = rate_idx; - -} - -static void *rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta, - gfp_t gfp) -{ - struct iwl_lq_sta *lq_sta; - struct iwl_priv *priv; - int i, j; - - priv = (struct iwl_priv *)priv_rate; - IWL_DEBUG_RATE(priv, "create station rate scale window\n"); - - lq_sta = kzalloc(sizeof(struct iwl_lq_sta), gfp); - - if (lq_sta == NULL) - return NULL; - lq_sta->lq.sta_id = 0xff; - - - for (j = 0; j < LQ_SIZE; j++) - for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - - return lq_sta; -} - -static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, - struct ieee80211_sta *sta, void *priv_sta) -{ - int i, j; - struct iwl_priv *priv = (struct iwl_priv *)priv_r; - struct ieee80211_conf *conf = &priv->hw->conf; - struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap; - struct iwl_lq_sta *lq_sta = priv_sta; - - lq_sta->flush_timer = 0; - lq_sta->supp_rates = sta->supp_rates[sband->band]; - for (j = 0; j < LQ_SIZE; j++) - for (i = 0; i < IWL_RATE_COUNT; i++) - rs_rate_scale_clear_window(&lq_sta->lq_info[j].win[i]); - - IWL_DEBUG_RATE(priv, "LQ: *** rate scale station global init ***\n"); - /* TODO: what is a good starting rate for STA? About middle? Maybe not - * the lowest or the highest rate.. Could consider using RSSI from - * previous packets? Need to have IEEE 802.1X auth succeed immediately - * after assoc.. */ - - lq_sta->ibss_sta_added = 0; - if (priv->iw_mode == NL80211_IFTYPE_AP) { - u8 sta_id = iwl_find_station(priv, - sta->addr); - - /* for IBSS the call are from tasklet */ - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_RATE(priv, "LQ: ADD station %pM\n", sta->addr); - sta_id = iwl_add_station(priv, sta->addr, false, - CMD_ASYNC, ht_cap); - } - if ((sta_id != IWL_INVALID_STATION)) { - lq_sta->lq.sta_id = sta_id; - lq_sta->lq.rs_table[0].rate_n_flags = 0; - } - /* FIXME: this is w/a remove it later */ - priv->assoc_station_added = 1; - } - - lq_sta->is_dup = 0; - lq_sta->max_rate_idx = -1; - lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX; - lq_sta->is_green = rs_use_green(sta, &priv->current_ht_config); - lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); - lq_sta->active_rate_basic = priv->active_rate_basic; - lq_sta->band = priv->band; - /* - * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3), - * supp_rates[] does not; shift to convert format, force 9 MBits off. - */ - lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1; - lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1; - lq_sta->active_siso_rate &= ~((u16)0x2); - lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE; - - /* Same here */ - lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1; - lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1; - lq_sta->active_mimo2_rate &= ~((u16)0x2); - lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE; - - lq_sta->active_mimo3_rate = ht_cap->mcs.rx_mask[2] << 1; - lq_sta->active_mimo3_rate |= ht_cap->mcs.rx_mask[2] & 0x1; - lq_sta->active_mimo3_rate &= ~((u16)0x2); - lq_sta->active_mimo3_rate <<= IWL_FIRST_OFDM_RATE; - - IWL_DEBUG_RATE(priv, "SISO-RATE=%X MIMO2-RATE=%X MIMO3-RATE=%X\n", - lq_sta->active_siso_rate, - lq_sta->active_mimo2_rate, - lq_sta->active_mimo3_rate); - - /* These values will be overridden later */ - lq_sta->lq.general_params.single_stream_ant_msk = ANT_A; - lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB; - - /* as default allow aggregation for all tids */ - lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; - lq_sta->drv = priv; - - /* Set last_txrate_idx to lowest rate */ - lq_sta->last_txrate_idx = rate_lowest_index(sband, sta); - if (sband->band == IEEE80211_BAND_5GHZ) - lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; - - rs_initialize_lq(priv, conf, sta, lq_sta); -} - -static void rs_fill_link_cmd(struct iwl_priv *priv, - struct iwl_lq_sta *lq_sta, u32 new_rate) -{ - struct iwl_scale_tbl_info tbl_type; - int index = 0; - int rate_idx; - int repeat_rate = 0; - u8 ant_toggle_cnt = 0; - u8 use_ht_possible = 1; - u8 valid_tx_ant = 0; - struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq; - - /* Override starting rate (index 0) if needed for debug purposes */ - rs_dbgfs_set_mcs(lq_sta, &new_rate, index); - - /* Interpret new_rate (rate_n_flags) */ - memset(&tbl_type, 0, sizeof(tbl_type)); - rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, - &tbl_type, &rate_idx); - - /* How many times should we repeat the initial rate? */ - if (is_legacy(tbl_type.lq_type)) { - ant_toggle_cnt = 1; - repeat_rate = IWL_NUMBER_TRY; - } else { - repeat_rate = IWL_HT_NUMBER_TRY; - } - - lq_cmd->general_params.mimo_delimiter = - is_mimo(tbl_type.lq_type) ? 1 : 0; - - /* Fill 1st table entry (index 0) */ - lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); - - if (num_of_ant(tbl_type.ant_type) == 1) { - lq_cmd->general_params.single_stream_ant_msk = - tbl_type.ant_type; - } else if (num_of_ant(tbl_type.ant_type) == 2) { - lq_cmd->general_params.dual_stream_ant_msk = - tbl_type.ant_type; - } /* otherwise we don't modify the existing value */ - - index++; - repeat_rate--; - - if (priv) - valid_tx_ant = priv->hw_params.valid_tx_ant; - - /* Fill rest of rate table */ - while (index < LINK_QUAL_MAX_RETRY_NUM) { - /* Repeat initial/next rate. - * For legacy IWL_NUMBER_TRY == 1, this loop will not execute. - * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */ - while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) { - if (is_legacy(tbl_type.lq_type)) { - if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) - ant_toggle_cnt++; - else if (priv && - rs_toggle_antenna(valid_tx_ant, - &new_rate, &tbl_type)) - ant_toggle_cnt = 1; -} - - /* Override next rate if needed for debug purposes */ - rs_dbgfs_set_mcs(lq_sta, &new_rate, index); - - /* Fill next table entry */ - lq_cmd->rs_table[index].rate_n_flags = - cpu_to_le32(new_rate); - repeat_rate--; - index++; - } - - rs_get_tbl_info_from_mcs(new_rate, lq_sta->band, &tbl_type, - &rate_idx); - - /* Indicate to uCode which entries might be MIMO. - * If initial rate was MIMO, this will finally end up - * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */ - if (is_mimo(tbl_type.lq_type)) - lq_cmd->general_params.mimo_delimiter = index; - - /* Get next rate */ - new_rate = rs_get_lower_rate(lq_sta, &tbl_type, rate_idx, - use_ht_possible); - - /* How many times should we repeat the next rate? */ - if (is_legacy(tbl_type.lq_type)) { - if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE) - ant_toggle_cnt++; - else if (priv && - rs_toggle_antenna(valid_tx_ant, - &new_rate, &tbl_type)) - ant_toggle_cnt = 1; - - repeat_rate = IWL_NUMBER_TRY; - } else { - repeat_rate = IWL_HT_NUMBER_TRY; - } - - /* Don't allow HT rates after next pass. - * rs_get_lower_rate() will change type to LQ_A or LQ_G. */ - use_ht_possible = 0; - - /* Override next rate if needed for debug purposes */ - rs_dbgfs_set_mcs(lq_sta, &new_rate, index); - - /* Fill next table entry */ - lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate); - - index++; - repeat_rate--; - } - - lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF; - lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - lq_cmd->agg_params.agg_time_limit = - cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); -} - -static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir) -{ - return hw->priv; -} -/* rate scale requires free function to be implemented */ -static void rs_free(void *priv_rate) -{ - return; -} - -static void rs_free_sta(void *priv_r, struct ieee80211_sta *sta, - void *priv_sta) -{ - struct iwl_lq_sta *lq_sta = priv_sta; - struct iwl_priv *priv __maybe_unused = priv_r; - - IWL_DEBUG_RATE(priv, "enter\n"); - kfree(lq_sta); - IWL_DEBUG_RATE(priv, "leave\n"); -} - - -#ifdef CONFIG_MAC80211_DEBUGFS -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} -static void rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta, - u32 *rate_n_flags, int index) -{ - struct iwl_priv *priv; - u8 valid_tx_ant; - u8 ant_sel_tx; - - priv = lq_sta->drv; - valid_tx_ant = priv->hw_params.valid_tx_ant; - if (lq_sta->dbg_fixed_rate) { - ant_sel_tx = - ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK) - >> RATE_MCS_ANT_POS); - if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) { - *rate_n_flags = lq_sta->dbg_fixed_rate; - IWL_DEBUG_RATE(priv, "Fixed rate ON\n"); - } else { - lq_sta->dbg_fixed_rate = 0; - IWL_ERR(priv, - "Invalid antenna selection 0x%X, Valid is 0x%X\n", - ant_sel_tx, valid_tx_ant); - IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); - } - } else { - IWL_DEBUG_RATE(priv, "Fixed rate OFF\n"); - } -} - -static ssize_t rs_sta_dbgfs_scale_table_write(struct file *file, - const char __user *user_buf, size_t count, loff_t *ppos) -{ - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_priv *priv; - char buf[64]; - int buf_size; - u32 parsed_rate; - - priv = lq_sta->drv; - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - - if (sscanf(buf, "%x", &parsed_rate) == 1) - lq_sta->dbg_fixed_rate = parsed_rate; - else - lq_sta->dbg_fixed_rate = 0; - - lq_sta->active_legacy_rate = 0x0FFF; /* 1 - 54 MBits, includes CCK */ - lq_sta->active_siso_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - lq_sta->active_mimo2_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - lq_sta->active_mimo3_rate = 0x1FD0; /* 6 - 60 MBits, no 9, no CCK */ - - IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n", - lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate); - - if (lq_sta->dbg_fixed_rate) { - rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate); - iwl_send_lq_cmd(lq_sta->drv, &lq_sta->lq, CMD_ASYNC); - } - - return count; -} - -static ssize_t rs_sta_dbgfs_scale_table_read(struct file *file, - char __user *user_buf, size_t count, loff_t *ppos) -{ - char *buff; - int desc = 0; - int i = 0; - int index = 0; - ssize_t ret; - - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_priv *priv; - struct iwl_scale_tbl_info *tbl = &(lq_sta->lq_info[lq_sta->active_tbl]); - - priv = lq_sta->drv; - buff = kmalloc(1024, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id); - desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n", - lq_sta->total_failed, lq_sta->total_success, - lq_sta->active_legacy_rate); - desc += sprintf(buff+desc, "fixed rate 0x%X\n", - lq_sta->dbg_fixed_rate); - desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n", - (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "", - (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "", - (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : ""); - desc += sprintf(buff+desc, "lq type %s\n", - (is_legacy(tbl->lq_type)) ? "legacy" : "HT"); - if (is_Ht(tbl->lq_type)) { - desc += sprintf(buff+desc, " %s", - (is_siso(tbl->lq_type)) ? "SISO" : - ((is_mimo2(tbl->lq_type)) ? "MIMO2" : "MIMO3")); - desc += sprintf(buff+desc, " %s", - (tbl->is_ht40) ? "40MHz" : "20MHz"); - desc += sprintf(buff+desc, " %s %s\n", (tbl->is_SGI) ? "SGI" : "", - (lq_sta->is_green) ? "GF enabled" : ""); - } - desc += sprintf(buff+desc, "last tx rate=0x%X\n", - lq_sta->last_rate_n_flags); - desc += sprintf(buff+desc, "general:" - "flags=0x%X mimo-d=%d s-ant0x%x d-ant=0x%x\n", - lq_sta->lq.general_params.flags, - lq_sta->lq.general_params.mimo_delimiter, - lq_sta->lq.general_params.single_stream_ant_msk, - lq_sta->lq.general_params.dual_stream_ant_msk); - - desc += sprintf(buff+desc, "agg:" - "time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n", - le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit), - lq_sta->lq.agg_params.agg_dis_start_th, - lq_sta->lq.agg_params.agg_frame_cnt_limit); - - desc += sprintf(buff+desc, - "Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n", - lq_sta->lq.general_params.start_rate_index[0], - lq_sta->lq.general_params.start_rate_index[1], - lq_sta->lq.general_params.start_rate_index[2], - lq_sta->lq.general_params.start_rate_index[3]); - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { - index = iwl_hwrate_to_plcp_idx( - le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags)); - if (is_legacy(tbl->lq_type)) { - desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps\n", - i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), - iwl_rate_mcs[index].mbps); - } else { - desc += sprintf(buff+desc, " rate[%d] 0x%X %smbps (%s)\n", - i, le32_to_cpu(lq_sta->lq.rs_table[i].rate_n_flags), - iwl_rate_mcs[index].mbps, iwl_rate_mcs[index].mcs); - } - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); - kfree(buff); - return ret; -} - -static const struct file_operations rs_sta_dbgfs_scale_table_ops = { - .write = rs_sta_dbgfs_scale_table_write, - .read = rs_sta_dbgfs_scale_table_read, - .open = open_file_generic, -}; -static ssize_t rs_sta_dbgfs_stats_table_read(struct file *file, - char __user *user_buf, size_t count, loff_t *ppos) -{ - char *buff; - int desc = 0; - int i, j; - ssize_t ret; - - struct iwl_lq_sta *lq_sta = file->private_data; - - buff = kmalloc(1024, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - for (i = 0; i < LQ_SIZE; i++) { - desc += sprintf(buff+desc, - "%s type=%d SGI=%d HT40=%d DUP=%d GF=%d\n" - "rate=0x%X\n", - lq_sta->active_tbl == i ? "*" : "x", - lq_sta->lq_info[i].lq_type, - lq_sta->lq_info[i].is_SGI, - lq_sta->lq_info[i].is_ht40, - lq_sta->lq_info[i].is_dup, - lq_sta->is_green, - lq_sta->lq_info[i].current_rate); - for (j = 0; j < IWL_RATE_COUNT; j++) { - desc += sprintf(buff+desc, - "counter=%d success=%d %%=%d\n", - lq_sta->lq_info[i].win[j].counter, - lq_sta->lq_info[i].win[j].success_counter, - lq_sta->lq_info[i].win[j].success_ratio); - } - } - ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); - kfree(buff); - return ret; -} - -static const struct file_operations rs_sta_dbgfs_stats_table_ops = { - .read = rs_sta_dbgfs_stats_table_read, - .open = open_file_generic, -}; - -static ssize_t rs_sta_dbgfs_rate_scale_data_read(struct file *file, - char __user *user_buf, size_t count, loff_t *ppos) -{ - char buff[120]; - int desc = 0; - ssize_t ret; - - struct iwl_lq_sta *lq_sta = file->private_data; - struct iwl_priv *priv; - struct iwl_scale_tbl_info *tbl = &lq_sta->lq_info[lq_sta->active_tbl]; - - priv = lq_sta->drv; - - if (is_Ht(tbl->lq_type)) - desc += sprintf(buff+desc, - "Bit Rate= %d Mb/s\n", - tbl->expected_tpt[lq_sta->last_txrate_idx]); - else - desc += sprintf(buff+desc, - "Bit Rate= %d Mb/s\n", - iwl_rates[lq_sta->last_txrate_idx].ieee >> 1); - desc += sprintf(buff+desc, - "Signal Level= %d dBm\tNoise Level= %d dBm\n", - priv->last_rx_rssi, priv->last_rx_noise); - desc += sprintf(buff+desc, - "Tsf= 0x%llx\tBeacon time= 0x%08X\n", - priv->last_tsf, priv->last_beacon_time); - - ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc); - return ret; -} - -static const struct file_operations rs_sta_dbgfs_rate_scale_data_ops = { - .read = rs_sta_dbgfs_rate_scale_data_read, - .open = open_file_generic, -}; - -static void rs_add_debugfs(void *priv, void *priv_sta, - struct dentry *dir) -{ - struct iwl_lq_sta *lq_sta = priv_sta; - lq_sta->rs_sta_dbgfs_scale_table_file = - debugfs_create_file("rate_scale_table", 0600, dir, - lq_sta, &rs_sta_dbgfs_scale_table_ops); - lq_sta->rs_sta_dbgfs_stats_table_file = - debugfs_create_file("rate_stats_table", 0600, dir, - lq_sta, &rs_sta_dbgfs_stats_table_ops); - lq_sta->rs_sta_dbgfs_rate_scale_data_file = - debugfs_create_file("rate_scale_data", 0600, dir, - lq_sta, &rs_sta_dbgfs_rate_scale_data_ops); - lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file = - debugfs_create_u8("tx_agg_tid_enable", 0600, dir, - &lq_sta->tx_agg_tid_en); - -} - -static void rs_remove_debugfs(void *priv, void *priv_sta) -{ - struct iwl_lq_sta *lq_sta = priv_sta; - debugfs_remove(lq_sta->rs_sta_dbgfs_scale_table_file); - debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file); - debugfs_remove(lq_sta->rs_sta_dbgfs_rate_scale_data_file); - debugfs_remove(lq_sta->rs_sta_dbgfs_tx_agg_tid_en_file); -} -#endif - -static struct rate_control_ops rs_ops = { - .module = NULL, - .name = RS_NAME, - .tx_status = rs_tx_status, - .get_rate = rs_get_rate, - .rate_init = rs_rate_init, - .alloc = rs_alloc, - .free = rs_free, - .alloc_sta = rs_alloc_sta, - .free_sta = rs_free_sta, -#ifdef CONFIG_MAC80211_DEBUGFS - .add_sta_debugfs = rs_add_debugfs, - .remove_sta_debugfs = rs_remove_debugfs, -#endif -}; - -int iwlagn_rate_control_register(void) -{ - return ieee80211_rate_control_register(&rs_ops); -} - -void iwlagn_rate_control_unregister(void) -{ - ieee80211_rate_control_unregister(&rs_ops); -} - diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h b/drivers/net/wireless/iwlwifi/iwl-agn-rs.h deleted file mode 100644 index 9fac530cfb7e..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.h +++ /dev/null @@ -1,403 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_agn_rs_h__ -#define __iwl_agn_rs_h__ - -struct iwl_rate_info { - u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ - u8 plcp_siso; /* uCode API: IWL_RATE_SISO_6M_PLCP, etc. */ - u8 plcp_mimo2; /* uCode API: IWL_RATE_MIMO2_6M_PLCP, etc. */ - u8 plcp_mimo3; /* uCode API: IWL_RATE_MIMO3_6M_PLCP, etc. */ - u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ - u8 prev_ieee; /* previous rate in IEEE speeds */ - u8 next_ieee; /* next rate in IEEE speeds */ - u8 prev_rs; /* previous rate used in rs algo */ - u8 next_rs; /* next rate used in rs algo */ - u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ - u8 next_rs_tgg; /* next rate used in TGG rs algo */ -}; - -struct iwl3945_rate_info { - u8 plcp; /* uCode API: IWL_RATE_6M_PLCP, etc. */ - u8 ieee; /* MAC header: IWL_RATE_6M_IEEE, etc. */ - u8 prev_ieee; /* previous rate in IEEE speeds */ - u8 next_ieee; /* next rate in IEEE speeds */ - u8 prev_rs; /* previous rate used in rs algo */ - u8 next_rs; /* next rate used in rs algo */ - u8 prev_rs_tgg; /* previous rate used in TGG rs algo */ - u8 next_rs_tgg; /* next rate used in TGG rs algo */ - u8 table_rs_index; /* index in rate scale table cmd */ - u8 prev_table_rs; /* prev in rate table cmd */ -}; - -/* - * These serve as indexes into - * struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; - */ -enum { - IWL_RATE_1M_INDEX = 0, - IWL_RATE_2M_INDEX, - IWL_RATE_5M_INDEX, - IWL_RATE_11M_INDEX, - IWL_RATE_6M_INDEX, - IWL_RATE_9M_INDEX, - IWL_RATE_12M_INDEX, - IWL_RATE_18M_INDEX, - IWL_RATE_24M_INDEX, - IWL_RATE_36M_INDEX, - IWL_RATE_48M_INDEX, - IWL_RATE_54M_INDEX, - IWL_RATE_60M_INDEX, - IWL_RATE_COUNT, /*FIXME:RS:change to IWL_RATE_INDEX_COUNT,*/ - IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1, /* Excluding 60M */ - IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1, - IWL_RATE_INVM_INDEX = IWL_RATE_COUNT, - IWL_RATE_INVALID = IWL_RATE_COUNT, -}; - -enum { - IWL_RATE_6M_INDEX_TABLE = 0, - IWL_RATE_9M_INDEX_TABLE, - IWL_RATE_12M_INDEX_TABLE, - IWL_RATE_18M_INDEX_TABLE, - IWL_RATE_24M_INDEX_TABLE, - IWL_RATE_36M_INDEX_TABLE, - IWL_RATE_48M_INDEX_TABLE, - IWL_RATE_54M_INDEX_TABLE, - IWL_RATE_1M_INDEX_TABLE, - IWL_RATE_2M_INDEX_TABLE, - IWL_RATE_5M_INDEX_TABLE, - IWL_RATE_11M_INDEX_TABLE, - IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1, -}; - -enum { - IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX, - IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX, - IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX, - IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX, - IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX, -}; - -/* #define vs. enum to keep from defaulting to 'large integer' */ -#define IWL_RATE_6M_MASK (1 << IWL_RATE_6M_INDEX) -#define IWL_RATE_9M_MASK (1 << IWL_RATE_9M_INDEX) -#define IWL_RATE_12M_MASK (1 << IWL_RATE_12M_INDEX) -#define IWL_RATE_18M_MASK (1 << IWL_RATE_18M_INDEX) -#define IWL_RATE_24M_MASK (1 << IWL_RATE_24M_INDEX) -#define IWL_RATE_36M_MASK (1 << IWL_RATE_36M_INDEX) -#define IWL_RATE_48M_MASK (1 << IWL_RATE_48M_INDEX) -#define IWL_RATE_54M_MASK (1 << IWL_RATE_54M_INDEX) -#define IWL_RATE_60M_MASK (1 << IWL_RATE_60M_INDEX) -#define IWL_RATE_1M_MASK (1 << IWL_RATE_1M_INDEX) -#define IWL_RATE_2M_MASK (1 << IWL_RATE_2M_INDEX) -#define IWL_RATE_5M_MASK (1 << IWL_RATE_5M_INDEX) -#define IWL_RATE_11M_MASK (1 << IWL_RATE_11M_INDEX) - -/* uCode API values for legacy bit rates, both OFDM and CCK */ -enum { - IWL_RATE_6M_PLCP = 13, - IWL_RATE_9M_PLCP = 15, - IWL_RATE_12M_PLCP = 5, - IWL_RATE_18M_PLCP = 7, - IWL_RATE_24M_PLCP = 9, - IWL_RATE_36M_PLCP = 11, - IWL_RATE_48M_PLCP = 1, - IWL_RATE_54M_PLCP = 3, - IWL_RATE_60M_PLCP = 3,/*FIXME:RS:should be removed*/ - IWL_RATE_1M_PLCP = 10, - IWL_RATE_2M_PLCP = 20, - IWL_RATE_5M_PLCP = 55, - IWL_RATE_11M_PLCP = 110, - /*FIXME:RS:change to IWL_RATE_LEGACY_??M_PLCP */ - /*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/ -}; - -/* uCode API values for OFDM high-throughput (HT) bit rates */ -enum { - IWL_RATE_SISO_6M_PLCP = 0, - IWL_RATE_SISO_12M_PLCP = 1, - IWL_RATE_SISO_18M_PLCP = 2, - IWL_RATE_SISO_24M_PLCP = 3, - IWL_RATE_SISO_36M_PLCP = 4, - IWL_RATE_SISO_48M_PLCP = 5, - IWL_RATE_SISO_54M_PLCP = 6, - IWL_RATE_SISO_60M_PLCP = 7, - IWL_RATE_MIMO2_6M_PLCP = 0x8, - IWL_RATE_MIMO2_12M_PLCP = 0x9, - IWL_RATE_MIMO2_18M_PLCP = 0xa, - IWL_RATE_MIMO2_24M_PLCP = 0xb, - IWL_RATE_MIMO2_36M_PLCP = 0xc, - IWL_RATE_MIMO2_48M_PLCP = 0xd, - IWL_RATE_MIMO2_54M_PLCP = 0xe, - IWL_RATE_MIMO2_60M_PLCP = 0xf, - IWL_RATE_MIMO3_6M_PLCP = 0x10, - IWL_RATE_MIMO3_12M_PLCP = 0x11, - IWL_RATE_MIMO3_18M_PLCP = 0x12, - IWL_RATE_MIMO3_24M_PLCP = 0x13, - IWL_RATE_MIMO3_36M_PLCP = 0x14, - IWL_RATE_MIMO3_48M_PLCP = 0x15, - IWL_RATE_MIMO3_54M_PLCP = 0x16, - IWL_RATE_MIMO3_60M_PLCP = 0x17, - IWL_RATE_SISO_INVM_PLCP, - IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, - IWL_RATE_MIMO3_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP, -}; - -/* MAC header values for bit rates */ -enum { - IWL_RATE_6M_IEEE = 12, - IWL_RATE_9M_IEEE = 18, - IWL_RATE_12M_IEEE = 24, - IWL_RATE_18M_IEEE = 36, - IWL_RATE_24M_IEEE = 48, - IWL_RATE_36M_IEEE = 72, - IWL_RATE_48M_IEEE = 96, - IWL_RATE_54M_IEEE = 108, - IWL_RATE_60M_IEEE = 120, - IWL_RATE_1M_IEEE = 2, - IWL_RATE_2M_IEEE = 4, - IWL_RATE_5M_IEEE = 11, - IWL_RATE_11M_IEEE = 22, -}; - -#define IWL_CCK_BASIC_RATES_MASK \ - (IWL_RATE_1M_MASK | \ - IWL_RATE_2M_MASK) - -#define IWL_CCK_RATES_MASK \ - (IWL_BASIC_RATES_MASK | \ - IWL_RATE_5M_MASK | \ - IWL_RATE_11M_MASK) - -#define IWL_OFDM_BASIC_RATES_MASK \ - (IWL_RATE_6M_MASK | \ - IWL_RATE_12M_MASK | \ - IWL_RATE_24M_MASK) - -#define IWL_OFDM_RATES_MASK \ - (IWL_OFDM_BASIC_RATES_MASK | \ - IWL_RATE_9M_MASK | \ - IWL_RATE_18M_MASK | \ - IWL_RATE_36M_MASK | \ - IWL_RATE_48M_MASK | \ - IWL_RATE_54M_MASK) - -#define IWL_BASIC_RATES_MASK \ - (IWL_OFDM_BASIC_RATES_MASK | \ - IWL_CCK_BASIC_RATES_MASK) - -#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1) - -#define IWL_INVALID_VALUE -1 - -#define IWL_MIN_RSSI_VAL -100 -#define IWL_MAX_RSSI_VAL 0 - -/* These values specify how many Tx frame attempts before - * searching for a new modulation mode */ -#define IWL_LEGACY_FAILURE_LIMIT 160 -#define IWL_LEGACY_SUCCESS_LIMIT 480 -#define IWL_LEGACY_TABLE_COUNT 160 - -#define IWL_NONE_LEGACY_FAILURE_LIMIT 400 -#define IWL_NONE_LEGACY_SUCCESS_LIMIT 4500 -#define IWL_NONE_LEGACY_TABLE_COUNT 1500 - -/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */ -#define IWL_RS_GOOD_RATIO 12800 /* 100% */ -#define IWL_RATE_SCALE_SWITCH 10880 /* 85% */ -#define IWL_RATE_HIGH_TH 10880 /* 85% */ -#define IWL_RATE_INCREASE_TH 6400 /* 50% */ -#define IWL_RATE_DECREASE_TH 1920 /* 15% */ - -/* possible actions when in legacy mode */ -#define IWL_LEGACY_SWITCH_ANTENNA1 0 -#define IWL_LEGACY_SWITCH_ANTENNA2 1 -#define IWL_LEGACY_SWITCH_SISO 2 -#define IWL_LEGACY_SWITCH_MIMO2_AB 3 -#define IWL_LEGACY_SWITCH_MIMO2_AC 4 -#define IWL_LEGACY_SWITCH_MIMO2_BC 5 -#define IWL_LEGACY_SWITCH_MIMO3_ABC 6 - -/* possible actions when in siso mode */ -#define IWL_SISO_SWITCH_ANTENNA1 0 -#define IWL_SISO_SWITCH_ANTENNA2 1 -#define IWL_SISO_SWITCH_MIMO2_AB 2 -#define IWL_SISO_SWITCH_MIMO2_AC 3 -#define IWL_SISO_SWITCH_MIMO2_BC 4 -#define IWL_SISO_SWITCH_GI 5 -#define IWL_SISO_SWITCH_MIMO3_ABC 6 - - -/* possible actions when in mimo mode */ -#define IWL_MIMO2_SWITCH_ANTENNA1 0 -#define IWL_MIMO2_SWITCH_ANTENNA2 1 -#define IWL_MIMO2_SWITCH_SISO_A 2 -#define IWL_MIMO2_SWITCH_SISO_B 3 -#define IWL_MIMO2_SWITCH_SISO_C 4 -#define IWL_MIMO2_SWITCH_GI 5 -#define IWL_MIMO2_SWITCH_MIMO3_ABC 6 - - -/* possible actions when in mimo3 mode */ -#define IWL_MIMO3_SWITCH_ANTENNA1 0 -#define IWL_MIMO3_SWITCH_ANTENNA2 1 -#define IWL_MIMO3_SWITCH_SISO_A 2 -#define IWL_MIMO3_SWITCH_SISO_B 3 -#define IWL_MIMO3_SWITCH_SISO_C 4 -#define IWL_MIMO3_SWITCH_MIMO2_AB 5 -#define IWL_MIMO3_SWITCH_MIMO2_AC 6 -#define IWL_MIMO3_SWITCH_MIMO2_BC 7 -#define IWL_MIMO3_SWITCH_GI 8 - - -#define IWL_MAX_11N_MIMO3_SEARCH IWL_MIMO3_SWITCH_GI -#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_MIMO3_ABC - -/*FIXME:RS:add possible actions for MIMO3*/ - -#define IWL_ACTION_LIMIT 3 /* # possible actions */ - -#define LQ_SIZE 2 /* 2 mode tables: "Active" and "Search" */ - -/* load per tid defines for A-MPDU activation */ -#define IWL_AGG_TPT_THREHOLD 0 -#define IWL_AGG_LOAD_THRESHOLD 10 -#define IWL_AGG_ALL_TID 0xff -#define TID_QUEUE_CELL_SPACING 50 /*mS */ -#define TID_QUEUE_MAX_SIZE 20 -#define TID_ROUND_VALUE 5 /* mS */ -#define TID_MAX_LOAD_COUNT 8 - -#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING) -#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y)) - -extern const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT]; -extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945]; - -enum iwl_table_type { - LQ_NONE, - LQ_G, /* legacy types */ - LQ_A, - LQ_SISO, /* high-throughput types */ - LQ_MIMO2, - LQ_MIMO3, - LQ_MAX, -}; - -#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A)) -#define is_siso(tbl) ((tbl) == LQ_SISO) -#define is_mimo2(tbl) ((tbl) == LQ_MIMO2) -#define is_mimo3(tbl) ((tbl) == LQ_MIMO3) -#define is_mimo(tbl) (is_mimo2(tbl) || is_mimo3(tbl)) -#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl)) -#define is_a_band(tbl) ((tbl) == LQ_A) -#define is_g_and(tbl) ((tbl) == LQ_G) - -#define ANT_NONE 0x0 -#define ANT_A BIT(0) -#define ANT_B BIT(1) -#define ANT_AB (ANT_A | ANT_B) -#define ANT_C BIT(2) -#define ANT_AC (ANT_A | ANT_C) -#define ANT_BC (ANT_B | ANT_C) -#define ANT_ABC (ANT_AB | ANT_C) - -#define IWL_MAX_MCS_DISPLAY_SIZE 12 - -struct iwl_rate_mcs_info { - char mbps[IWL_MAX_MCS_DISPLAY_SIZE]; - char mcs[IWL_MAX_MCS_DISPLAY_SIZE]; -}; - -static inline u8 num_of_ant(u8 mask) -{ - return !!((mask) & ANT_A) + - !!((mask) & ANT_B) + - !!((mask) & ANT_C); -} - -static inline u8 first_antenna(u8 mask) -{ - if (mask & ANT_A) - return ANT_A; - if (mask & ANT_B) - return ANT_B; - return ANT_C; -} - - -static inline u8 iwl_get_prev_ieee_rate(u8 rate_index) -{ - u8 rate = iwl_rates[rate_index].prev_ieee; - - if (rate == IWL_RATE_INVALID) - rate = rate_index; - return rate; -} - -static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index) -{ - u8 rate = iwl3945_rates[rate_index].prev_ieee; - - if (rate == IWL_RATE_INVALID) - rate = rate_index; - return rate; -} - -/** - * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info - * - * The specific throughput table used is based on the type of network - * the associated with, including A, B, G, and G w/ TGG protection - */ -extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id); - -/** - * iwl_rate_control_register - Register the rate control algorithm callbacks - * - * Since the rate control algorithm is hardware specific, there is no need - * or reason to place it as a stand alone module. The driver can call - * iwl_rate_control_register in order to register the rate control callbacks - * with the mac80211 subsystem. This should be performed prior to calling - * ieee80211_register_hw - * - */ -extern int iwlagn_rate_control_register(void); -extern int iwl3945_rate_control_register(void); - -/** - * iwl_rate_control_unregister - Unregister the rate control callbacks - * - * This should be called after calling ieee80211_unregister_hw, but before - * the driver is unloaded. - */ -extern void iwlagn_rate_control_unregister(void); -extern void iwl3945_rate_control_unregister(void); - -#endif /* __iwl_agn__rs__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c deleted file mode 100644 index 166bedd3c615..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ /dev/null @@ -1,3336 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include - -#define DRV_NAME "iwlagn" - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-helpers.h" -#include "iwl-sta.h" -#include "iwl-calib.h" - - -/****************************************************************************** - * - * module boiler plate - * - ******************************************************************************/ - -/* - * module name, copyright, version, etc. - */ -#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" - -#ifdef CONFIG_IWLWIFI_DEBUG -#define VD "d" -#else -#define VD -#endif - -#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT -#define VS "s" -#else -#define VS -#endif - -#define DRV_VERSION IWLWIFI_VERSION VD VS - - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("iwl4965"); - -/*************** STATION TABLE MANAGEMENT **** - * mac80211 should be examined to determine if sta_info is duplicating - * the functionality provided here - */ - -/**************************************************************/ - -/** - * iwl_commit_rxon - commit staging_rxon to hardware - * - * The RXON command in staging_rxon is committed to the hardware and - * the active_rxon structure is updated with the new data. This - * function correctly transitions out of the RXON_ASSOC_MSK state if - * a HW tune is required based on the RXON structure changes. - */ -int iwl_commit_rxon(struct iwl_priv *priv) -{ - /* cast away the const for active_rxon in this function */ - struct iwl_rxon_cmd *active_rxon = (void *)&priv->active_rxon; - int ret; - bool new_assoc = - !!(priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK); - - if (!iwl_is_alive(priv)) - return -EBUSY; - - /* always get timestamp with Rx frame */ - priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK; - - ret = iwl_check_rxon_cmd(priv); - if (ret) { - IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n"); - return -EINVAL; - } - - /* If we don't need to send a full RXON, we can use - * iwl_rxon_assoc_cmd which is used to reconfigure filter - * and other flags for the current radio configuration. */ - if (!iwl_full_rxon_required(priv)) { - ret = iwl_send_rxon_assoc(priv); - if (ret) { - IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret); - return ret; - } - - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); - return 0; - } - - /* station table will be cleared */ - priv->assoc_station_added = 0; - - /* If we are currently associated and the new config requires - * an RXON_ASSOC and the new config wants the associated mask enabled, - * we must clear the associated from the active configuration - * before we apply the new config */ - if (iwl_is_associated(priv) && new_assoc) { - IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n"); - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - - ret = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl_rxon_cmd), - &priv->active_rxon); - - /* If the mask clearing failed then we set - * active_rxon back to what it was previously */ - if (ret) { - active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK; - IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret); - return ret; - } - } - - IWL_DEBUG_INFO(priv, "Sending RXON\n" - "* with%s RXON_FILTER_ASSOC_MSK\n" - "* channel = %d\n" - "* bssid = %pM\n", - (new_assoc ? "" : "out"), - le16_to_cpu(priv->staging_rxon.channel), - priv->staging_rxon.bssid_addr); - - iwl_set_rxon_hwcrypto(priv, !priv->cfg->mod_params->sw_crypto); - - /* Apply the new configuration - * RXON unassoc clears the station table in uCode, send it before - * we add the bcast station. If assoc bit is set, we will send RXON - * after having added the bcast and bssid station. - */ - if (!new_assoc) { - ret = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); - } - - iwl_clear_stations_table(priv); - - priv->start_calib = 0; - - /* Add the broadcast address so we can send broadcast frames */ - if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) == - IWL_INVALID_STATION) { - IWL_ERR(priv, "Error adding BROADCAST address for transmit.\n"); - return -EIO; - } - - /* If we have set the ASSOC_MSK and we are in BSS mode then - * add the IWL_AP_ID to the station rate table */ - if (new_assoc) { - if (priv->iw_mode == NL80211_IFTYPE_STATION) { - ret = iwl_rxon_add_station(priv, - priv->active_rxon.bssid_addr, 1); - if (ret == IWL_INVALID_STATION) { - IWL_ERR(priv, - "Error adding AP address for TX.\n"); - return -EIO; - } - priv->assoc_station_added = 1; - if (priv->default_wep_key && - iwl_send_static_wepkey_cmd(priv, 0)) - IWL_ERR(priv, - "Could not send WEP static key.\n"); - } - - /* - * allow CTS-to-self if possible for new association. - * this is relevant only for 5000 series and up, - * but will not damage 4965 - */ - priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN; - - /* Apply the new configuration - * RXON assoc doesn't clear the station table in uCode, - */ - ret = iwl_send_cmd_pdu(priv, REPLY_RXON, - sizeof(struct iwl_rxon_cmd), &priv->staging_rxon); - if (ret) { - IWL_ERR(priv, "Error setting new RXON (%d)\n", ret); - return ret; - } - memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon)); - } - - iwl_init_sensitivity(priv); - - /* If we issue a new RXON command which required a tune then we must - * send a new TXPOWER command or we won't be able to Tx any frames */ - ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - if (ret) { - IWL_ERR(priv, "Error sending TX power (%d)\n", ret); - return ret; - } - - return 0; -} - -void iwl_update_chain_flags(struct iwl_priv *priv) -{ - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - iwlcore_commit_rxon(priv); -} - -static void iwl_clear_free_frames(struct iwl_priv *priv) -{ - struct list_head *element; - - IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", - priv->frames_count); - - while (!list_empty(&priv->free_frames)) { - element = priv->free_frames.next; - list_del(element); - kfree(list_entry(element, struct iwl_frame, list)); - priv->frames_count--; - } - - if (priv->frames_count) { - IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", - priv->frames_count); - priv->frames_count = 0; - } -} - -static struct iwl_frame *iwl_get_free_frame(struct iwl_priv *priv) -{ - struct iwl_frame *frame; - struct list_head *element; - if (list_empty(&priv->free_frames)) { - frame = kzalloc(sizeof(*frame), GFP_KERNEL); - if (!frame) { - IWL_ERR(priv, "Could not allocate frame!\n"); - return NULL; - } - - priv->frames_count++; - return frame; - } - - element = priv->free_frames.next; - list_del(element); - return list_entry(element, struct iwl_frame, list); -} - -static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) -{ - memset(frame, 0, sizeof(*frame)); - list_add(&frame->list, &priv->free_frames); -} - -static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - int left) -{ - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && - (priv->iw_mode != NL80211_IFTYPE_AP))) - return 0; - - if (priv->ibss_beacon->len > left) - return 0; - - memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len); - - return priv->ibss_beacon->len; -} - -static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, - struct iwl_frame *frame, u8 rate) -{ - struct iwl_tx_beacon_cmd *tx_beacon_cmd; - unsigned int frame_size; - - tx_beacon_cmd = &frame->u.beacon; - memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd)); - - tx_beacon_cmd->tx.sta_id = priv->hw_params.bcast_sta_id; - tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, - sizeof(frame->u) - sizeof(*tx_beacon_cmd)); - - BUG_ON(frame_size > MAX_MPDU_SIZE); - tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size); - - if ((rate == IWL_RATE_1M_PLCP) || (rate >= IWL_RATE_2M_PLCP)) - tx_beacon_cmd->tx.rate_n_flags = - iwl_hw_set_rate_n_flags(rate, RATE_MCS_CCK_MSK); - else - tx_beacon_cmd->tx.rate_n_flags = - iwl_hw_set_rate_n_flags(rate, 0); - - tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK | - TX_CMD_FLG_TSF_MSK | - TX_CMD_FLG_STA_RATE_MSK; - - return sizeof(*tx_beacon_cmd) + frame_size; -} -static int iwl_send_beacon_cmd(struct iwl_priv *priv) -{ - struct iwl_frame *frame; - unsigned int frame_size; - int rc; - u8 rate; - - frame = iwl_get_free_frame(priv); - - if (!frame) { - IWL_ERR(priv, "Could not obtain free frame buffer for beacon " - "command.\n"); - return -ENOMEM; - } - - rate = iwl_rate_get_lowest_plcp(priv); - - frame_size = iwl_hw_get_beacon_cmd(priv, frame, rate); - - rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, - &frame->u.cmd[0]); - - iwl_free_frame(priv, frame); - - return rc; -} - -static inline dma_addr_t iwl_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - dma_addr_t addr = get_unaligned_le32(&tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - addr |= - ((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16; - - return addr; -} - -static inline u16 iwl_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - - return le16_to_cpu(tb->hi_n_len) >> 4; -} - -static inline void iwl_tfd_set_tb(struct iwl_tfd *tfd, u8 idx, - dma_addr_t addr, u16 len) -{ - struct iwl_tfd_tb *tb = &tfd->tbs[idx]; - u16 hi_n_len = len << 4; - - put_unaligned_le32(addr, &tb->lo); - if (sizeof(dma_addr_t) > sizeof(u32)) - hi_n_len |= ((addr >> 16) >> 16) & 0xF; - - tb->hi_n_len = cpu_to_le16(hi_n_len); - - tfd->num_tbs = idx + 1; -} - -static inline u8 iwl_tfd_get_num_tbs(struct iwl_tfd *tfd) -{ - return tfd->num_tbs & 0x1f; -} - -/** - * iwl_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr] - * @priv - driver private data - * @txq - tx queue - * - * Does NOT advance any TFD circular buffer read/write indexes - * Does NOT free the TFD itself (which is within circular buffer) - */ -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds; - struct iwl_tfd *tfd; - struct pci_dev *dev = priv->pci_dev; - int index = txq->q.read_ptr; - int i; - int num_tbs; - - tfd = &tfd_tmp[index]; - - /* Sanity check on number of chunks */ - num_tbs = iwl_tfd_get_num_tbs(tfd); - - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Too many chunks: %i\n", num_tbs); - /* @todo issue fatal error, it is quite serious situation */ - return; - } - - /* Unmap tx_cmd */ - if (num_tbs) - pci_unmap_single(dev, - pci_unmap_addr(&txq->meta[index], mapping), - pci_unmap_len(&txq->meta[index], len), - PCI_DMA_BIDIRECTIONAL); - - /* Unmap chunks, if any. */ - for (i = 1; i < num_tbs; i++) { - pci_unmap_single(dev, iwl_tfd_tb_get_addr(tfd, i), - iwl_tfd_tb_get_len(tfd, i), PCI_DMA_TODEVICE); - - if (txq->txb) { - dev_kfree_skb(txq->txb[txq->q.read_ptr].skb[i - 1]); - txq->txb[txq->q.read_ptr].skb[i - 1] = NULL; - } - } -} - -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, - u8 reset, u8 pad) -{ - struct iwl_queue *q; - struct iwl_tfd *tfd, *tfd_tmp; - u32 num_tbs; - - q = &txq->q; - tfd_tmp = (struct iwl_tfd *)txq->tfds; - tfd = &tfd_tmp[q->write_ptr]; - - if (reset) - memset(tfd, 0, sizeof(*tfd)); - - num_tbs = iwl_tfd_get_num_tbs(tfd); - - /* Each TFD can point to a maximum 20 Tx buffers */ - if (num_tbs >= IWL_NUM_OF_TBS) { - IWL_ERR(priv, "Error can not send more than %d chunks\n", - IWL_NUM_OF_TBS); - return -EINVAL; - } - - BUG_ON(addr & ~DMA_BIT_MASK(36)); - if (unlikely(addr & ~IWL_TX_DMA_MASK)) - IWL_ERR(priv, "Unaligned address = %llx\n", - (unsigned long long)addr); - - iwl_tfd_set_tb(tfd, num_tbs, addr, len); - - return 0; -} - -/* - * Tell nic where to find circular buffer of Tx Frame Descriptors for - * given Tx queue, and enable the DMA channel used for that queue. - * - * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA - * channels supported in hardware. - */ -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq) -{ - int txq_id = txq->q.id; - - /* Circular buffer (TFD queue in DRAM) physical base address */ - iwl_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id), - txq->q.dma_addr >> 8); - - return 0; -} - -/****************************************************************************** - * - * Generic RX handler implementations - * - ******************************************************************************/ -static void iwl_rx_reply_alive(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_alive_resp *palive; - struct delayed_work *pwork; - - palive = &pkt->u.alive_frame; - - IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " - "0x%01X 0x%01X\n", - palive->is_valid, palive->ver_type, - palive->ver_subtype); - - if (palive->ver_subtype == INITIALIZE_SUBTYPE) { - IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); - memcpy(&priv->card_alive_init, - &pkt->u.alive_frame, - sizeof(struct iwl_init_alive_resp)); - pwork = &priv->init_alive_start; - } else { - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - memcpy(&priv->card_alive, &pkt->u.alive_frame, - sizeof(struct iwl_alive_resp)); - pwork = &priv->alive_start; - } - - /* We delay the ALIVE response by 5ms to - * give the HW RF Kill time to activate... */ - if (palive->is_valid == UCODE_VALID_OK) - queue_delayed_work(priv->workqueue, pwork, - msecs_to_jiffies(5)); - else - IWL_WARN(priv, "uCode did not respond OK.\n"); -} - -static void iwl_bg_beacon_update(struct work_struct *work) -{ - struct iwl_priv *priv = - container_of(work, struct iwl_priv, beacon_update); - struct sk_buff *beacon; - - /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ - beacon = ieee80211_beacon_get(priv->hw, priv->vif); - - if (!beacon) { - IWL_ERR(priv, "update beacon failed\n"); - return; - } - - mutex_lock(&priv->mutex); - /* new beacon skb is allocated every time; dispose previous.*/ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = beacon; - mutex_unlock(&priv->mutex); - - iwl_send_beacon_cmd(priv); -} - -/** - * iwl_bg_statistics_periodic - Timer callback to queue statistics - * - * This callback is provided in order to send a statistics request. - * - * This timer function is continually reset to execute within - * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION - * was received. We need to ensure we receive the statistics in order - * to update the temperature used for calibrating the TXPOWER. - */ -static void iwl_bg_statistics_periodic(unsigned long data) -{ - struct iwl_priv *priv = (struct iwl_priv *)data; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* dont send host command if rf-kill is on */ - if (!iwl_is_ready_rf(priv)) - return; - - iwl_send_statistics_request(priv, CMD_ASYNC); -} - -static void iwl_rx_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl4965_beacon_notif *beacon = - (struct iwl4965_beacon_notif *)pkt->u.raw; - u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags); - - IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " - "tsf %d %d rate %d\n", - le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK, - beacon->beacon_notify_hdr.failure_frame, - le32_to_cpu(beacon->ibss_mgr_status), - le32_to_cpu(beacon->high_tsf), - le32_to_cpu(beacon->low_tsf), rate); -#endif - - if ((priv->iw_mode == NL80211_IFTYPE_AP) && - (!test_bit(STATUS_EXIT_PENDING, &priv->status))) - queue_work(priv->workqueue, &priv->beacon_update); -} - -/* Handle notification from uCode that card's power state is changing - * due to software, hardware, or critical temperature RFKILL */ -static void iwl_rx_card_state_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); - unsigned long status = priv->status; - - IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s\n", - (flags & HW_CARD_DISABLED) ? "Kill" : "On", - (flags & SW_CARD_DISABLED) ? "Kill" : "On"); - - if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED | - RF_CARD_DISABLED)) { - - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - iwl_write_direct32(priv, HBUS_TARG_MBX_C, - HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); - - if (!(flags & RXON_CARD_DISABLED)) { - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - iwl_write_direct32(priv, HBUS_TARG_MBX_C, - HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED); - } - if (flags & RF_CARD_DISABLED) - iwl_tt_enter_ct_kill(priv); - } - if (!(flags & RF_CARD_DISABLED)) - iwl_tt_exit_ct_kill(priv); - - if (flags & HW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_HW, &priv->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->status); - - - if (!(flags & RXON_CARD_DISABLED)) - iwl_scan_cancel(priv); - - if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->status))) - wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->status)); - else - wake_up_interruptible(&priv->wait_command_queue); -} - -int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src) -{ - if (src == IWL_PWR_SRC_VAUX) { - if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VAUX, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } else { - iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_PWR_SRC_VMAIN, - ~APMG_PS_CTRL_MSK_PWR_SRC); - } - - return 0; -} - -/** - * iwl_setup_rx_handlers - Initialize Rx handler callbacks - * - * Setup the RX handlers for each of the reply types sent from the uCode - * to the host. - * - * This function chains into the hardware specific files for them to setup - * any hardware specific handlers as well. - */ -static void iwl_setup_rx_handlers(struct iwl_priv *priv) -{ - priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; - priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; - priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; - priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; - priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = - iwl_rx_pm_debug_statistics_notif; - priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif; - - /* - * The same handler is used for both the REPLY to a discrete - * statistics request from the host as well as for the periodic - * statistics notifications (after received beacons) from the uCode. - */ - priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_rx_statistics; - priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics; - - iwl_setup_spectrum_handlers(priv); - iwl_setup_rx_scan_handlers(priv); - - /* status change handler */ - priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif; - - priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] = - iwl_rx_missed_beacon_notif; - /* Rx handlers */ - priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; - priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; - /* block ack */ - priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba; - /* Set up hardware specific Rx handlers */ - priv->cfg->ops->lib->rx_handler_setup(priv); -} - -/** - * iwl_rx_handle - Main entry function for receiving responses from uCode - * - * Uses the priv->rx_handlers callback function array to invoke - * the appropriate handlers, including command responses, - * frame-received notifications, and other notifications. - */ -void iwl_rx_handle(struct iwl_priv *priv) -{ - struct iwl_rx_mem_buffer *rxb; - struct iwl_rx_packet *pkt; - struct iwl_rx_queue *rxq = &priv->rxq; - u32 r, i; - int reclaim; - unsigned long flags; - u8 fill_rx = 0; - u32 count = 8; - int total_empty; - - /* uCode's read index (stored in shared DRAM) indicates the last Rx - * buffer that the driver may process (last buffer filled by ucode). */ - r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; - i = rxq->read; - - /* Rx interrupt, but nothing sent from uCode */ - if (i == r) - IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); - - /* calculate total frames need to be restock after handling RX */ - total_empty = r - priv->rxq.write_actual; - if (total_empty < 0) - total_empty += RX_QUEUE_SIZE; - - if (total_empty > (RX_QUEUE_SIZE / 2)) - fill_rx = 1; - - while (i != r) { - rxb = rxq->queue[i]; - - /* If an RXB doesn't have a Rx queue slot associated with it, - * then a bug has been introduced in the queue refilling - * routines -- catch it here */ - BUG_ON(rxb == NULL); - - rxq->queue[i] = NULL; - - pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, - priv->hw_params.rx_buf_size + 256, - PCI_DMA_FROMDEVICE); - pkt = (struct iwl_rx_packet *)rxb->skb->data; - - /* Reclaim a command buffer only if this packet is a response - * to a (driver-originated) command. - * If the packet (e.g. Rx frame) originated from uCode, - * there is no command buffer to reclaim. - * Ucode should set SEQ_RX_FRAME bit if ucode-originated, - * but apparently a few don't get set; catch them here. */ - reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && - (pkt->hdr.cmd != REPLY_RX_PHY_CMD) && - (pkt->hdr.cmd != REPLY_RX) && - (pkt->hdr.cmd != REPLY_RX_MPDU_CMD) && - (pkt->hdr.cmd != REPLY_COMPRESSED_BA) && - (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && - (pkt->hdr.cmd != REPLY_TX); - - /* Based on type of command response or notification, - * handle those that need handling via function in - * rx_handlers table. See iwl_setup_rx_handlers() */ - if (priv->rx_handlers[pkt->hdr.cmd]) { - IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, - i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); - priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); - priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; - } else { - /* No handling needed */ - IWL_DEBUG_RX(priv, - "r %d i %d No handler needed for %s, 0x%02x\n", - r, i, get_cmd_string(pkt->hdr.cmd), - pkt->hdr.cmd); - } - - if (reclaim) { - /* Invoke any callbacks, transfer the skb to caller, and - * fire off the (possibly) blocking iwl_send_cmd() - * as we reclaim the driver command queue */ - if (rxb && rxb->skb) - iwl_tx_cmd_complete(priv, rxb); - else - IWL_WARN(priv, "Claim null rxb?\n"); - } - - /* For now we just don't re-use anything. We can tweak this - * later to try and re-use notification packets and SKBs that - * fail to Rx correctly */ - if (rxb->skb != NULL) { - priv->alloc_rxb_skb--; - dev_kfree_skb_any(rxb->skb); - rxb->skb = NULL; - } - - spin_lock_irqsave(&rxq->lock, flags); - list_add_tail(&rxb->list, &priv->rxq.rx_used); - spin_unlock_irqrestore(&rxq->lock, flags); - i = (i + 1) & RX_QUEUE_MASK; - /* If there are a lot of unused frames, - * restock the Rx queue so ucode wont assert. */ - if (fill_rx) { - count++; - if (count >= 8) { - priv->rxq.read = i; - iwl_rx_replenish_now(priv); - count = 0; - } - } - } - - /* Backtrack one entry */ - priv->rxq.read = i; - if (fill_rx) - iwl_rx_replenish_now(priv); - else - iwl_rx_queue_restock(priv); -} - -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->pci_dev->irq); - tasklet_kill(&priv->irq_tasklet); -} - -static void iwl_irq_tasklet_legacy(struct iwl_priv *priv) -{ - u32 inta, handled = 0; - u32 inta_fh; - unsigned long flags; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_mask; -#endif - - spin_lock_irqsave(&priv->lock, flags); - - /* Ack/clear/reset pending uCode interrupts. - * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, - * and will clear only when CSR_FH_INT_STATUS gets cleared. */ - inta = iwl_read32(priv, CSR_INT); - iwl_write32(priv, CSR_INT, inta); - - /* Ack/clear/reset pending flow-handler (DMA) interrupts. - * Any new interrupts that happen after this, either while we're - * in this tasklet, or later, will show up in next ISR/tasklet. */ - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_ISR) { - /* just for debug */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", - inta, inta_mask, inta_fh); - } -#endif - - /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not - * atomic, make sure that inta covers all the interrupts that - * we've discovered, even if FH interrupt came in just after - * reading CSR_INT. */ - if (inta_fh & CSR49_FH_INT_RX_MASK) - inta |= CSR_INT_BIT_FH_RX; - if (inta_fh & CSR49_FH_INT_TX_MASK) - inta |= CSR_INT_BIT_FH_TX; - - /* Now service all interrupt bits discovered above. */ - if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Hardware error detected. Restarting.\n"); - - /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(priv); - - priv->isr_stats.hw++; - iwl_irq_handle_error(priv); - - handled |= CSR_INT_BIT_HW_ERR; - - spin_unlock_irqrestore(&priv->lock, flags); - - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " - "the frame/frames.\n"); - priv->isr_stats.sch++; - } - - /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(priv, "Alive interrupt\n"); - priv->isr_stats.alive++; - } - } -#endif - /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); - - /* HW RF KILL switch toggled */ - if (inta & CSR_INT_BIT_RF_KILL) { - int hw_rf_kill = 0; - if (!(iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rf_kill = 1; - - IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", - hw_rf_kill ? "disable radio" : "enable radio"); - - priv->isr_stats.rfkill++; - - /* driver only loads ucode once setting the interface up. - * the driver allows loading the ucode even if the radio - * is killed. Hence update the killswitch state here. The - * rfkill handler will care about restarting if needed. - */ - if (!test_bit(STATUS_ALIVE, &priv->status)) { - if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, &priv->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->status); - wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); - } - - handled |= CSR_INT_BIT_RF_KILL; - } - - /* Chip got too hot and stopped itself */ - if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(priv, "Microcode CT kill error detected.\n"); - priv->isr_stats.ctkill++; - handled |= CSR_INT_BIT_CT_KILL; - } - - /* Error detected by uCode */ - if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(priv, "Microcode SW error detected. " - " Restarting 0x%X.\n", inta); - priv->isr_stats.sw++; - priv->isr_stats.sw_err = inta; - iwl_irq_handle_error(priv); - handled |= CSR_INT_BIT_SW_ERR; - } - - /* uCode wakes up after power-down sleep */ - if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - iwl_txq_update_write_ptr(priv, &priv->txq[0]); - iwl_txq_update_write_ptr(priv, &priv->txq[1]); - iwl_txq_update_write_ptr(priv, &priv->txq[2]); - iwl_txq_update_write_ptr(priv, &priv->txq[3]); - iwl_txq_update_write_ptr(priv, &priv->txq[4]); - iwl_txq_update_write_ptr(priv, &priv->txq[5]); - - priv->isr_stats.wakeup++; - - handled |= CSR_INT_BIT_WAKEUP; - } - - /* All uCode command responses, including Tx command responses, - * Rx "responses" (frame-received notification), and other - * notifications from uCode come through here*/ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { - iwl_rx_handle(priv); - priv->isr_stats.rx++; - handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - } - - if (inta & CSR_INT_BIT_FH_TX) { - IWL_DEBUG_ISR(priv, "Tx interrupt\n"); - priv->isr_stats.tx++; - handled |= CSR_INT_BIT_FH_TX; - /* FH finished to write, send event */ - priv->ucode_write_complete = 1; - wake_up_interruptible(&priv->wait_command_queue); - } - - if (inta & ~handled) { - IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv->isr_stats.unhandled++; - } - - if (inta & ~(priv->inta_mask)) { - IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~priv->inta_mask); - IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); - } - - /* Re-enable all interrupts */ - /* only Re-enable if diabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - inta = iwl_read32(priv, CSR_INT); - inta_mask = iwl_read32(priv, CSR_INT_MASK); - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " - "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); - } -#endif - spin_unlock_irqrestore(&priv->lock, flags); -} - -/* tasklet for iwlagn interrupt */ -static void iwl_irq_tasklet(struct iwl_priv *priv) -{ - u32 inta = 0; - u32 handled = 0; - unsigned long flags; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_mask; -#endif - - spin_lock_irqsave(&priv->lock, flags); - - /* Ack/clear/reset pending uCode interrupts. - * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, - */ - iwl_write32(priv, CSR_INT, priv->inta); - - inta = priv->inta; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_ISR) { - /* just for debug */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x\n ", - inta, inta_mask); - } -#endif - /* saved interrupt in inta variable now we can reset priv->inta */ - priv->inta = 0; - - /* Now service all interrupt bits discovered above. */ - if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Hardware error detected. Restarting.\n"); - - /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(priv); - - priv->isr_stats.hw++; - iwl_irq_handle_error(priv); - - handled |= CSR_INT_BIT_HW_ERR; - - spin_unlock_irqrestore(&priv->lock, flags); - - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " - "the frame/frames.\n"); - priv->isr_stats.sch++; - } - - /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(priv, "Alive interrupt\n"); - priv->isr_stats.alive++; - } - } -#endif - /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); - - /* HW RF KILL switch toggled */ - if (inta & CSR_INT_BIT_RF_KILL) { - int hw_rf_kill = 0; - if (!(iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW)) - hw_rf_kill = 1; - - IWL_WARN(priv, "RF_KILL bit toggled to %s.\n", - hw_rf_kill ? "disable radio" : "enable radio"); - - priv->isr_stats.rfkill++; - - /* driver only loads ucode once setting the interface up. - * the driver allows loading the ucode even if the radio - * is killed. Hence update the killswitch state here. The - * rfkill handler will care about restarting if needed. - */ - if (!test_bit(STATUS_ALIVE, &priv->status)) { - if (hw_rf_kill) - set_bit(STATUS_RF_KILL_HW, &priv->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->status); - wiphy_rfkill_set_hw_state(priv->hw->wiphy, hw_rf_kill); - } - - handled |= CSR_INT_BIT_RF_KILL; - } - - /* Chip got too hot and stopped itself */ - if (inta & CSR_INT_BIT_CT_KILL) { - IWL_ERR(priv, "Microcode CT kill error detected.\n"); - priv->isr_stats.ctkill++; - handled |= CSR_INT_BIT_CT_KILL; - } - - /* Error detected by uCode */ - if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(priv, "Microcode SW error detected. " - " Restarting 0x%X.\n", inta); - priv->isr_stats.sw++; - priv->isr_stats.sw_err = inta; - iwl_irq_handle_error(priv); - handled |= CSR_INT_BIT_SW_ERR; - } - - /* uCode wakes up after power-down sleep */ - if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - iwl_txq_update_write_ptr(priv, &priv->txq[0]); - iwl_txq_update_write_ptr(priv, &priv->txq[1]); - iwl_txq_update_write_ptr(priv, &priv->txq[2]); - iwl_txq_update_write_ptr(priv, &priv->txq[3]); - iwl_txq_update_write_ptr(priv, &priv->txq[4]); - iwl_txq_update_write_ptr(priv, &priv->txq[5]); - - priv->isr_stats.wakeup++; - - handled |= CSR_INT_BIT_WAKEUP; - } - - /* All uCode command responses, including Tx command responses, - * Rx "responses" (frame-received notification), and other - * notifications from uCode come through here*/ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX | - CSR_INT_BIT_RX_PERIODIC)) { - IWL_DEBUG_ISR(priv, "Rx interrupt\n"); - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { - handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - iwl_write32(priv, CSR_FH_INT_STATUS, - CSR49_FH_INT_RX_MASK); - } - if (inta & CSR_INT_BIT_RX_PERIODIC) { - handled |= CSR_INT_BIT_RX_PERIODIC; - iwl_write32(priv, CSR_INT, CSR_INT_BIT_RX_PERIODIC); - } - /* Sending RX interrupt require many steps to be done in the - * the device: - * 1- write interrupt to current index in ICT table. - * 2- dma RX frame. - * 3- update RX shared data to indicate last write index. - * 4- send interrupt. - * This could lead to RX race, driver could receive RX interrupt - * but the shared data changes does not reflect this. - * this could lead to RX race, RX periodic will solve this race - */ - iwl_write32(priv, CSR_INT_PERIODIC_REG, - CSR_INT_PERIODIC_DIS); - iwl_rx_handle(priv); - /* Only set RX periodic if real RX is received. */ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) - iwl_write32(priv, CSR_INT_PERIODIC_REG, - CSR_INT_PERIODIC_ENA); - - priv->isr_stats.rx++; - } - - if (inta & CSR_INT_BIT_FH_TX) { - iwl_write32(priv, CSR_FH_INT_STATUS, CSR49_FH_INT_TX_MASK); - IWL_DEBUG_ISR(priv, "Tx interrupt\n"); - priv->isr_stats.tx++; - handled |= CSR_INT_BIT_FH_TX; - /* FH finished to write, send event */ - priv->ucode_write_complete = 1; - wake_up_interruptible(&priv->wait_command_queue); - } - - if (inta & ~handled) { - IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv->isr_stats.unhandled++; - } - - if (inta & ~(priv->inta_mask)) { - IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~priv->inta_mask); - } - - - /* Re-enable all interrupts */ - /* only Re-enable if diabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - - spin_unlock_irqrestore(&priv->lock, flags); - -} - - -/****************************************************************************** - * - * uCode download functions - * - ******************************************************************************/ - -static void iwl_dealloc_ucode_pci(struct iwl_priv *priv) -{ - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); -} - -static void iwl_nic_start(struct iwl_priv *priv) -{ - /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); -} - - -/** - * iwl_read_ucode - Read uCode images from disk file. - * - * Copy into buffers for card to fetch via bus-mastering - */ -static int iwl_read_ucode(struct iwl_priv *priv) -{ - struct iwl_ucode_header *ucode; - int ret = -EINVAL, index; - const struct firmware *ucode_raw; - const char *name_pre = priv->cfg->fw_name_pre; - const unsigned int api_max = priv->cfg->ucode_api_max; - const unsigned int api_min = priv->cfg->ucode_api_min; - char buf[25]; - u8 *src; - size_t len; - u32 api_ver, build; - u32 inst_size, data_size, init_size, init_data_size, boot_size; - u16 eeprom_ver; - - /* Ask kernel firmware_class module to get the boot firmware off disk. - * request_firmware() is synchronous, file is in memory on return. */ - for (index = api_max; index >= api_min; index--) { - sprintf(buf, "%s%d%s", name_pre, index, ".ucode"); - ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); - if (ret < 0) { - IWL_ERR(priv, "%s firmware file req failed: %d\n", - buf, ret); - if (ret == -ENOENT) - continue; - else - goto error; - } else { - if (index < api_max) - IWL_ERR(priv, "Loaded firmware %s, " - "which is deprecated. " - "Please use API v%u instead.\n", - buf, api_max); - - IWL_DEBUG_INFO(priv, "Got firmware '%s' file (%zd bytes) from disk\n", - buf, ucode_raw->size); - break; - } - } - - if (ret < 0) - goto error; - - /* Make sure that we got at least the v1 header! */ - if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { - IWL_ERR(priv, "File size way too small!\n"); - ret = -EINVAL; - goto err_release; - } - - /* Data from ucode file: header followed by uCode images */ - ucode = (struct iwl_ucode_header *)ucode_raw->data; - - priv->ucode_ver = le32_to_cpu(ucode->ver); - api_ver = IWL_UCODE_API(priv->ucode_ver); - build = priv->cfg->ops->ucode->get_build(ucode, api_ver); - inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); - data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); - init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); - init_data_size = - priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); - boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); - src = priv->cfg->ops->ucode->get_data(ucode, api_ver); - - /* api_ver should match the api version forming part of the - * firmware filename ... but we don't check for that and only rely - * on the API version read from firmware header from here on forward */ - - if (api_ver < api_min || api_ver > api_max) { - IWL_ERR(priv, "Driver unable to support your firmware API. " - "Driver supports v%u, firmware is v%u.\n", - api_max, api_ver); - priv->ucode_ver = 0; - ret = -EINVAL; - goto err_release; - } - if (api_ver != api_max) - IWL_ERR(priv, "Firmware has old API version. Expected v%u, " - "got v%u. New firmware can be obtained " - "from http://www.intellinuxwireless.org.\n", - api_max, api_ver); - - IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); - - if (build) - IWL_DEBUG_INFO(priv, "Build %u\n", build); - - eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); - IWL_DEBUG_INFO(priv, "NVM Type: %s, version: 0x%x\n", - (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) - ? "OTP" : "EEPROM", eeprom_ver); - - IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", - priv->ucode_ver); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", - inst_size); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", - data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", - init_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", - init_data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", - boot_size); - - /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != - priv->cfg->ops->ucode->get_header_size(api_ver) + - inst_size + data_size + init_size + - init_data_size + boot_size) { - - IWL_DEBUG_INFO(priv, - "uCode file size %d does not match expected size\n", - (int)ucode_raw->size); - ret = -EINVAL; - goto err_release; - } - - /* Verify that uCode images will fit in card's SRAM */ - if (inst_size > priv->hw_params.max_inst_size) { - IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", - inst_size); - ret = -EINVAL; - goto err_release; - } - - if (data_size > priv->hw_params.max_data_size) { - IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", - data_size); - ret = -EINVAL; - goto err_release; - } - if (init_size > priv->hw_params.max_inst_size) { - IWL_INFO(priv, "uCode init instr len %d too large to fit in\n", - init_size); - ret = -EINVAL; - goto err_release; - } - if (init_data_size > priv->hw_params.max_data_size) { - IWL_INFO(priv, "uCode init data len %d too large to fit in\n", - init_data_size); - ret = -EINVAL; - goto err_release; - } - if (boot_size > priv->hw_params.max_bsm_size) { - IWL_INFO(priv, "uCode boot instr len %d too large to fit in\n", - boot_size); - ret = -EINVAL; - goto err_release; - } - - /* Allocate ucode buffers for card's bus-master loading ... */ - - /* Runtime instructions and 2 copies of data: - * 1) unmodified from disk - * 2) backup cache for save/restore during power-downs */ - priv->ucode_code.len = inst_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); - - priv->ucode_data.len = data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); - - priv->ucode_data_backup.len = data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); - - if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || - !priv->ucode_data_backup.v_addr) - goto err_pci_alloc; - - /* Initialization instructions and data */ - if (init_size && init_data_size) { - priv->ucode_init.len = init_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); - - priv->ucode_init_data.len = init_data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); - - if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) - goto err_pci_alloc; - } - - /* Bootstrap (instructions only, no data) */ - if (boot_size) { - priv->ucode_boot.len = boot_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); - - if (!priv->ucode_boot.v_addr) - goto err_pci_alloc; - } - - /* Copy images into buffers for card's bus-master reads ... */ - - /* Runtime instructions (first block of data in file) */ - len = inst_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n", len); - memcpy(priv->ucode_code.v_addr, src, len); - src += len; - - IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", - priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); - - /* Runtime data (2nd block) - * NOTE: Copy into backup buffer will be done in iwl_up() */ - len = data_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n", len); - memcpy(priv->ucode_data.v_addr, src, len); - memcpy(priv->ucode_data_backup.v_addr, src, len); - src += len; - - /* Initialization instructions (3rd block) */ - if (init_size) { - len = init_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) init instr len %Zd\n", - len); - memcpy(priv->ucode_init.v_addr, src, len); - src += len; - } - - /* Initialization data (4th block) */ - if (init_data_size) { - len = init_data_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) init data len %Zd\n", - len); - memcpy(priv->ucode_init_data.v_addr, src, len); - src += len; - } - - /* Bootstrap instructions (5th block) */ - len = boot_size; - IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n", len); - memcpy(priv->ucode_boot.v_addr, src, len); - - /* We have our copies now, allow OS release its copies */ - release_firmware(ucode_raw); - return 0; - - err_pci_alloc: - IWL_ERR(priv, "failed to allocate pci memory\n"); - ret = -ENOMEM; - iwl_dealloc_ucode_pci(priv); - - err_release: - release_firmware(ucode_raw); - - error: - return ret; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static const char *desc_lookup_text[] = { - "OK", - "FAIL", - "BAD_PARAM", - "BAD_CHECKSUM", - "NMI_INTERRUPT_WDG", - "SYSASSERT", - "FATAL_ERROR", - "BAD_COMMAND", - "HW_ERROR_TUNE_LOCK", - "HW_ERROR_TEMPERATURE", - "ILLEGAL_CHAN_FREQ", - "VCC_NOT_STABLE", - "FH_ERROR", - "NMI_INTERRUPT_HOST", - "NMI_INTERRUPT_ACTION_PT", - "NMI_INTERRUPT_UNKNOWN", - "UCODE_VERSION_MISMATCH", - "HW_ERROR_ABS_LOCK", - "HW_ERROR_CAL_LOCK_FAIL", - "NMI_INTERRUPT_INST_ACTION_PT", - "NMI_INTERRUPT_DATA_ACTION_PT", - "NMI_TRM_HW_ER", - "NMI_INTERRUPT_TRM", - "NMI_INTERRUPT_BREAK_POINT" - "DEBUG_0", - "DEBUG_1", - "DEBUG_2", - "DEBUG_3", - "UNKNOWN" -}; - -static const char *desc_lookup(int i) -{ - int max = ARRAY_SIZE(desc_lookup_text) - 1; - - if (i < 0 || i > max) - i = max; - - return desc_lookup_text[i]; -} - -#define ERROR_START_OFFSET (1 * sizeof(u32)) -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) - -void iwl_dump_nic_error_log(struct iwl_priv *priv) -{ - u32 data2, line; - u32 desc, time, count, base, data1; - u32 blink1, blink2, ilink1, ilink2; - - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.error_event_table_ptr); - - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); - return; - } - - count = iwl_read_targ_mem(priv, base); - - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IWL_ERR(priv, "Start IWL Error Log Dump:\n"); - IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->status, count); - } - - desc = iwl_read_targ_mem(priv, base + 1 * sizeof(u32)); - blink1 = iwl_read_targ_mem(priv, base + 3 * sizeof(u32)); - blink2 = iwl_read_targ_mem(priv, base + 4 * sizeof(u32)); - ilink1 = iwl_read_targ_mem(priv, base + 5 * sizeof(u32)); - ilink2 = iwl_read_targ_mem(priv, base + 6 * sizeof(u32)); - data1 = iwl_read_targ_mem(priv, base + 7 * sizeof(u32)); - data2 = iwl_read_targ_mem(priv, base + 8 * sizeof(u32)); - line = iwl_read_targ_mem(priv, base + 9 * sizeof(u32)); - time = iwl_read_targ_mem(priv, base + 11 * sizeof(u32)); - - IWL_ERR(priv, "Desc Time " - "data1 data2 line\n"); - IWL_ERR(priv, "%-28s (#%02d) %010u 0x%08X 0x%08X %u\n", - desc_lookup(desc), desc, time, data1, data2, line); - IWL_ERR(priv, "blink1 blink2 ilink1 ilink2\n"); - IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X\n", blink1, blink2, - ilink1, ilink2); - -} - -#define EVENT_START_OFFSET (4 * sizeof(u32)) - -/** - * iwl_print_event_log - Dump error event log to syslog - * - */ -static void iwl_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode) -{ - u32 i; - u32 base; /* SRAM byte address of event log header */ - u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ - u32 ptr; /* SRAM byte address of log data */ - u32 ev, time, data; /* event log data */ - - if (num_events == 0) - return; - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - - if (mode == 0) - event_size = 2 * sizeof(u32); - else - event_size = 3 * sizeof(u32); - - ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { - ev = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - time = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - if (mode == 0) { - /* data, ev */ - IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n", time, ev); - } else { - data = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n", - time, data, ev); - } - } -} - -void iwl_dump_nic_event_log(struct iwl_priv *priv) -{ - u32 base; /* SRAM byte address of event log header */ - u32 capacity; /* event log capacity in # entries */ - u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ - u32 num_wraps; /* # times uCode wrapped to top of log */ - u32 next_entry; /* index of next entry to be written by uCode */ - u32 size; /* # entries that we'll print */ - - if (priv->ucode_type == UCODE_INIT) - base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr); - else - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - - if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); - return; - } - - /* event log header */ - capacity = iwl_read_targ_mem(priv, base); - mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - - size = num_wraps ? capacity : next_entry; - - /* bail out if nothing in log */ - if (size == 0) { - IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - return; - } - - IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", - size, num_wraps); - - /* if uCode has wrapped back to top of log, start at the oldest entry, - * i.e the next one that uCode would fill. */ - if (num_wraps) - iwl_print_event_log(priv, next_entry, - capacity - next_entry, mode); - /* (then/else) start at top of log */ - iwl_print_event_log(priv, 0, next_entry, mode); - -} -#endif - -/** - * iwl_alive_start - called after REPLY_ALIVE notification received - * from protocol/runtime uCode (initialization uCode's - * Alive gets handled by iwl_init_alive_start()). - */ -static void iwl_alive_start(struct iwl_priv *priv) -{ - int ret = 0; - - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - - if (priv->card_alive.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Alive failed.\n"); - goto restart; - } - - /* Initialize uCode has loaded Runtime uCode ... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "runtime" alive if code weren't properly loaded. */ - if (iwl_verify_ucode(priv)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); - goto restart; - } - - iwl_clear_stations_table(priv); - ret = priv->cfg->ops->lib->alive_notify(priv); - if (ret) { - IWL_WARN(priv, - "Could not complete ALIVE transition [ntf]: %d\n", ret); - goto restart; - } - - /* After the ALIVE response, we can send host commands to the uCode */ - set_bit(STATUS_ALIVE, &priv->status); - - if (iwl_is_rfkill(priv)) - return; - - ieee80211_wake_queues(priv->hw); - - priv->active_rate = priv->rates_mask; - priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; - - if (iwl_is_associated(priv)) { - struct iwl_rxon_cmd *active_rxon = - (struct iwl_rxon_cmd *)&priv->active_rxon; - /* apply any changes in staging */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - } else { - /* Initialize our rx_config data */ - iwl_connection_init_rx_config(priv, priv->iw_mode); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - } - - /* Configure Bluetooth device coexistence support */ - iwl_send_bt_config(priv); - - iwl_reset_run_time_calib(priv); - - /* Configure the adapter for unassociated operation */ - iwlcore_commit_rxon(priv); - - /* At this point, the NIC is initialized and operational */ - iwl_rf_kill_ct_config(priv); - - iwl_leds_register(priv); - - IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - set_bit(STATUS_READY, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); - - iwl_power_update_mode(priv, true); - - /* reassociate for ADHOC mode */ - if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { - struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, - priv->vif); - if (beacon) - iwl_mac_beacon_update(priv->hw, beacon); - } - - - if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) - iwl_set_mode(priv, priv->iw_mode); - - return; - - restart: - queue_work(priv->workqueue, &priv->restart); -} - -static void iwl_cancel_deferred_work(struct iwl_priv *priv); - -static void __iwl_down(struct iwl_priv *priv) -{ - unsigned long flags; - int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); - - IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); - - if (!exit_pending) - set_bit(STATUS_EXIT_PENDING, &priv->status); - - iwl_leds_unregister(priv); - - iwl_clear_stations_table(priv); - - /* Unblock any waiting calls */ - wake_up_interruptible_all(&priv->wait_command_queue); - - /* Wipe out the EXIT_PENDING status bit if we are not actually - * exiting the module */ - if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->status); - - /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - - /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); - - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - - /* If we have not previously called iwl_init() then - * clear all bits but the RF Kill bit and return */ - if (!iwl_is_init(priv)) { - priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << - STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << - STATUS_GEO_CONFIGURED | - test_bit(STATUS_EXIT_PENDING, &priv->status) << - STATUS_EXIT_PENDING; - goto exit; - } - - /* ...otherwise clear out all the status bits but the RF Kill - * bit and continue taking the NIC down. */ - priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << - STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << - STATUS_GEO_CONFIGURED | - test_bit(STATUS_FW_ERROR, &priv->status) << - STATUS_FW_ERROR | - test_bit(STATUS_EXIT_PENDING, &priv->status) << - STATUS_EXIT_PENDING; - - /* device going down, Stop using ICT table */ - iwl_disable_ict(priv); - spin_lock_irqsave(&priv->lock, flags); - iwl_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_txq_ctx_stop(priv); - iwl_rxq_stop(priv); - - iwl_write_prph(priv, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); - - udelay(5); - - /* FIXME: apm_ops.suspend(priv) */ - if (exit_pending) - priv->cfg->ops->lib->apm_ops.stop(priv); - else - priv->cfg->ops->lib->apm_ops.reset(priv); - exit: - memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = NULL; - - /* clear out any free frames */ - iwl_clear_free_frames(priv); -} - -static void iwl_down(struct iwl_priv *priv) -{ - mutex_lock(&priv->mutex); - __iwl_down(priv); - mutex_unlock(&priv->mutex); - - iwl_cancel_deferred_work(priv); -} - -#define HW_READY_TIMEOUT (50) - -static int iwl_set_hw_ready(struct iwl_priv *priv) -{ - int ret = 0; - - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY); - - /* See if we got it */ - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - CSR_HW_IF_CONFIG_REG_BIT_NIC_READY, - HW_READY_TIMEOUT); - if (ret != -ETIMEDOUT) - priv->hw_ready = true; - else - priv->hw_ready = false; - - IWL_DEBUG_INFO(priv, "hardware %s\n", - (priv->hw_ready == 1) ? "ready" : "not ready"); - return ret; -} - -static int iwl_prepare_card_hw(struct iwl_priv *priv) -{ - int ret = 0; - - IWL_DEBUG_INFO(priv, "iwl_prepare_card_hw enter \n"); - - ret = iwl_set_hw_ready(priv); - if (priv->hw_ready) - return ret; - - /* If HW is not ready, prepare the conditions to check again */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_PREPARE); - - ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG, - ~CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, - CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE, 150000); - - /* HW should be ready by now, check again. */ - if (ret != -ETIMEDOUT) - iwl_set_hw_ready(priv); - - return ret; -} - -#define MAX_HW_RESTARTS 5 - -static int __iwl_up(struct iwl_priv *priv) -{ - int i; - int ret; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); - return -EIO; - } - - if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { - IWL_ERR(priv, "ucode not available for device bringup\n"); - return -EIO; - } - - iwl_prepare_card_hw(priv); - - if (!priv->hw_ready) { - IWL_WARN(priv, "Exit HW not ready\n"); - return -EIO; - } - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - if (iwl_is_rfkill(priv)) { - wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - - iwl_enable_interrupts(priv); - IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); - return 0; - } - - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - - ret = iwl_hw_nic_init(priv); - if (ret) { - IWL_ERR(priv, "Unable to init nic\n"); - return ret; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - /* Copy original ucode data image from disk into backup cache. - * This will be used to initialize the on-board processor's - * data SRAM for a clean start when the runtime program first loads. */ - memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, - priv->ucode_data.len); - - for (i = 0; i < MAX_HW_RESTARTS; i++) { - - iwl_clear_stations_table(priv); - - /* load bootstrap state machine, - * load bootstrap program into processor's memory, - * prepare to load the "initialize" uCode */ - ret = priv->cfg->ops->lib->load_ucode(priv); - - if (ret) { - IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n", - ret); - continue; - } - - /* start card; "initialize" will load runtime ucode */ - iwl_nic_start(priv); - - IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); - - return 0; - } - - set_bit(STATUS_EXIT_PENDING, &priv->status); - __iwl_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->status); - - /* tried to restart and config the device for as long as our - * patience could withstand */ - IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); - return -EIO; -} - - -/***************************************************************************** - * - * Workqueue callbacks - * - *****************************************************************************/ - -static void iwl_bg_init_alive_start(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, init_alive_start.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - priv->cfg->ops->lib->init_alive_start(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl_bg_alive_start(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, alive_start.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* enable dram interrupt */ - iwl_reset_ict(priv); - - mutex_lock(&priv->mutex); - iwl_alive_start(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl_bg_run_time_calib_work(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, - run_time_calib_work); - - mutex_lock(&priv->mutex); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - test_bit(STATUS_SCANNING, &priv->status)) { - mutex_unlock(&priv->mutex); - return; - } - - if (priv->start_calib) { - iwl_chain_noise_calibration(priv, &priv->statistics); - - iwl_sensitivity_calibration(priv, &priv->statistics); - } - - mutex_unlock(&priv->mutex); - return; -} - -static void iwl_bg_up(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, up); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - __iwl_up(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl_bg_restart(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { - mutex_lock(&priv->mutex); - priv->vif = NULL; - priv->is_open = 0; - mutex_unlock(&priv->mutex); - iwl_down(priv); - ieee80211_restart_hw(priv->hw); - } else { - iwl_down(priv); - queue_work(priv->workqueue, &priv->up); - } -} - -static void iwl_bg_rx_replenish(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, rx_replenish); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - iwl_rx_replenish(priv); - mutex_unlock(&priv->mutex); -} - -#define IWL_DELAY_NEXT_SCAN (HZ*2) - -void iwl_post_associate(struct iwl_priv *priv) -{ - struct ieee80211_conf *conf = NULL; - int ret = 0; - unsigned long flags; - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); - return; - } - - IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - priv->assoc_id, priv->active_rxon.bssid_addr); - - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - - if (!priv->vif || !priv->is_open) - return; - - iwl_scan_cancel_timeout(priv, 200); - - conf = ieee80211_get_hw_conf(priv->hw); - - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - - iwl_setup_rxon_timing(priv); - ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); - if (ret) - IWL_WARN(priv, "REPLY_RXON_TIMING failed - " - "Attempting to continue.\n"); - - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - - iwl_set_rxon_ht(priv, &priv->current_ht_config); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - - IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - priv->assoc_id, priv->beacon_int); - - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - } - - iwlcore_commit_rxon(priv); - - switch (priv->iw_mode) { - case NL80211_IFTYPE_STATION: - break; - - case NL80211_IFTYPE_ADHOC: - - /* assume default assoc id */ - priv->assoc_id = 1; - - iwl_rxon_add_station(priv, priv->bssid, 0); - iwl_send_beacon_cmd(priv); - - break; - - default: - IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, priv->iw_mode); - break; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->assoc_station_added = 1; - - spin_lock_irqsave(&priv->lock, flags); - iwl_activate_qos(priv, 0); - spin_unlock_irqrestore(&priv->lock, flags); - - /* the chain noise calibration will enabled PM upon completion - * If chain noise has already been run, then we need to enable - * power management here */ - if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) - iwl_power_update_mode(priv, false); - - /* Enable Rx differential gain and sensitivity calibrations */ - iwl_chain_noise_reset(priv); - priv->start_calib = 1; - -} - -/***************************************************************************** - * - * mac80211 entry point functions - * - *****************************************************************************/ - -#define UCODE_READY_TIMEOUT (4 * HZ) - -static int iwl_mac_start(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - int ret; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - /* we should be verifying the device is ready to be opened */ - mutex_lock(&priv->mutex); - - /* fetch ucode file from disk, alloc and copy to bus-master buffers ... - * ucode filename and max sizes are card-specific. */ - - if (!priv->ucode_code.len) { - ret = iwl_read_ucode(priv); - if (ret) { - IWL_ERR(priv, "Could not read microcode: %d\n", ret); - mutex_unlock(&priv->mutex); - return ret; - } - } - - ret = __iwl_up(priv); - - mutex_unlock(&priv->mutex); - - if (ret) - return ret; - - if (iwl_is_rfkill(priv)) - goto out; - - IWL_DEBUG_INFO(priv, "Start UP work done.\n"); - - /* Wait for START_ALIVE from Run Time ucode. Otherwise callbacks from - * mac80211 will not be run successfully. */ - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - test_bit(STATUS_READY, &priv->status), - UCODE_READY_TIMEOUT); - if (!ret) { - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_ERR(priv, "START_ALIVE timeout after %dms.\n", - jiffies_to_msecs(UCODE_READY_TIMEOUT)); - return -ETIMEDOUT; - } - } - -out: - priv->is_open = 1; - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} - -static void iwl_mac_stop(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!priv->is_open) - return; - - priv->is_open = 0; - - if (iwl_is_ready_rf(priv) || test_bit(STATUS_SCAN_HW, &priv->status)) { - /* stop mac, cancel any scan request and clear - * RXON_FILTER_ASSOC_MSK BIT - */ - mutex_lock(&priv->mutex); - iwl_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); - } - - iwl_down(priv); - - flush_workqueue(priv->workqueue); - - /* enable interrupts again in order to receive rfkill changes */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - -static int iwl_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MACDUMP(priv, "enter\n"); - - IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); - - if (iwl_tx_skb(priv, skb)) - dev_kfree_skb_any(skb); - - IWL_DEBUG_MACDUMP(priv, "leave\n"); - return NETDEV_TX_OK; -} - -void iwl_config_ap(struct iwl_priv *priv) -{ - int ret = 0; - unsigned long flags; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* The following should be done only at AP bring up */ - if (!iwl_is_associated(priv)) { - - /* RXON - unassoc (to set timing command) */ - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - - /* RXON Timing */ - iwl_setup_rxon_timing(priv); - ret = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); - if (ret) - IWL_WARN(priv, "REPLY_RXON_TIMING failed - " - "Attempting to continue.\n"); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - /* FIXME: what should be the assoc_id for AP? */ - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging_rxon.flags |= - RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= - RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; - } - /* restore RXON assoc */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - spin_lock_irqsave(&priv->lock, flags); - iwl_activate_qos(priv, 1); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_rxon_add_station(priv, iwl_bcast_addr, 0); - } - iwl_send_beacon_cmd(priv); - - /* FIXME - we need to add code here to detect a totally new - * configuration, reset the AP, unassoc, rxon timing, assoc, - * clear sta table, add BCAST sta... */ -} - -static void iwl_mac_update_tkip_key(struct ieee80211_hw *hw, - struct ieee80211_key_conf *keyconf, const u8 *addr, - u32 iv32, u16 *phase1key) -{ - - struct iwl_priv *priv = hw->priv; - IWL_DEBUG_MAC80211(priv, "enter\n"); - - iwl_update_tkip_key(priv, keyconf, addr, iv32, phase1key); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - -static int iwl_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct iwl_priv *priv = hw->priv; - const u8 *addr; - int ret; - u8 sta_id; - bool is_default_wep_key = false; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (priv->cfg->mod_params->sw_crypto) { - IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); - return -EOPNOTSUPP; - } - addr = sta ? sta->addr : iwl_bcast_addr; - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - addr); - return -EINVAL; - - } - - mutex_lock(&priv->mutex); - iwl_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); - - /* If we are getting WEP group key and we didn't receive any key mapping - * so far, we are in legacy wep mode (group key only), otherwise we are - * in 1X mode. - * In legacy wep mode, we use another host command to the uCode */ - if (key->alg == ALG_WEP && sta_id == priv->hw_params.bcast_sta_id && - priv->iw_mode != NL80211_IFTYPE_AP) { - if (cmd == SET_KEY) - is_default_wep_key = !priv->key_mapping_key; - else - is_default_wep_key = - (key->hw_key_idx == HW_KEY_DEFAULT); - } - - switch (cmd) { - case SET_KEY: - if (is_default_wep_key) - ret = iwl_set_default_wep_key(priv, key); - else - ret = iwl_set_dynamic_key(priv, key, sta_id); - - IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); - break; - case DISABLE_KEY: - if (is_default_wep_key) - ret = iwl_remove_default_wep_key(priv, key); - else - ret = iwl_remove_dynamic_key(priv, key, sta_id); - - IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); - break; - default: - ret = -EINVAL; - } - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return ret; -} - -static int iwl_mac_ampdu_action(struct ieee80211_hw *hw, - enum ieee80211_ampdu_mlme_action action, - struct ieee80211_sta *sta, u16 tid, u16 *ssn) -{ - struct iwl_priv *priv = hw->priv; - int ret; - - IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n", - sta->addr, tid); - - if (!(priv->cfg->sku & IWL_SKU_N)) - return -EACCES; - - switch (action) { - case IEEE80211_AMPDU_RX_START: - IWL_DEBUG_HT(priv, "start Rx\n"); - return iwl_sta_rx_agg_start(priv, sta->addr, tid, *ssn); - case IEEE80211_AMPDU_RX_STOP: - IWL_DEBUG_HT(priv, "stop Rx\n"); - ret = iwl_sta_rx_agg_stop(priv, sta->addr, tid); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return 0; - else - return ret; - case IEEE80211_AMPDU_TX_START: - IWL_DEBUG_HT(priv, "start Tx\n"); - return iwl_tx_agg_start(priv, sta->addr, tid, ssn); - case IEEE80211_AMPDU_TX_STOP: - IWL_DEBUG_HT(priv, "stop Tx\n"); - ret = iwl_tx_agg_stop(priv, sta->addr, tid); - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return 0; - else - return ret; - default: - IWL_DEBUG_HT(priv, "unknown\n"); - return -EINVAL; - break; - } - return 0; -} - -static int iwl_mac_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - - priv = hw->priv; - IWL_DEBUG_MAC80211(priv, "enter\n"); - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} - -/***************************************************************************** - * - * sysfs attributes - * - *****************************************************************************/ - -#ifdef CONFIG_IWLWIFI_DEBUG - -/* - * The following adds a new attribute to the sysfs representation - * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) - * used for controlling the debug level. - * - * See the level definitions in iwl for details. - * - * The debug_level being managed using sysfs below is a per device debug - * level that is used instead of the global debug level if it (the per - * device debug level) is set. - */ -static ssize_t show_debug_level(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); -} -static ssize_t store_debug_level(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - int ret; - - ret = strict_strtoul(buf, 0, &val); - if (ret) - IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf); - else { - priv->debug_level = val; - if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, - "Not enough memory to generate traffic log\n"); - } - return strnlen(buf, count); -} - -static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, - show_debug_level, store_debug_level); - - -#endif /* CONFIG_IWLWIFI_DEBUG */ - - -static ssize_t show_temperature(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - return sprintf(buf, "%d\n", priv->temperature); -} - -static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); - -static ssize_t show_tx_power(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - if (!iwl_is_ready_rf(priv)) - return sprintf(buf, "off\n"); - else - return sprintf(buf, "%d\n", priv->tx_power_user_lmt); -} - -static ssize_t store_tx_power(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - int ret; - - ret = strict_strtoul(buf, 10, &val); - if (ret) - IWL_INFO(priv, "%s is not in decimal form.\n", buf); - else { - ret = iwl_set_tx_power(priv, val, false); - if (ret) - IWL_ERR(priv, "failed setting tx power (0x%d).\n", - ret); - else - ret = count; - } - return ret; -} - -static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); - -static ssize_t show_flags(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); -} - -static ssize_t store_flags(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - u32 flags; - int ret = strict_strtoul(buf, 0, &val); - if (ret) - return ret; - flags = (u32)val; - - mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.flags) != flags) { - /* Cancel any currently running scans... */ - if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARN(priv, "Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO(priv, "Commit rxon.flags = 0x%04X\n", flags); - priv->staging_rxon.flags = cpu_to_le32(flags); - iwlcore_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); - -static ssize_t show_filter_flags(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active_rxon.filter_flags)); -} - -static ssize_t store_filter_flags(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - u32 filter_flags; - int ret = strict_strtoul(buf, 0, &val); - if (ret) - return ret; - filter_flags = (u32)val; - - mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { - /* Cancel any currently running scans... */ - if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARN(priv, "Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " - "0x%04X\n", filter_flags); - priv->staging_rxon.filter_flags = - cpu_to_le32(filter_flags); - iwlcore_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, - store_filter_flags); - - -static ssize_t show_statistics(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - u32 size = sizeof(struct iwl_notif_statistics); - u32 len = 0, ofs = 0; - u8 *data = (u8 *)&priv->statistics; - int rc = 0; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - rc = iwl_send_statistics_request(priv, 0); - mutex_unlock(&priv->mutex); - - if (rc) { - len = sprintf(buf, - "Error sending statistics request: 0x%08X\n", rc); - return len; - } - - while (size && (PAGE_SIZE - len)) { - hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, - PAGE_SIZE - len, 1); - len = strlen(buf); - if (PAGE_SIZE - len) - buf[len++] = '\n'; - - ofs += 16; - size -= min(size, 16U); - } - - return len; -} - -static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); - - -/***************************************************************************** - * - * driver setup and teardown - * - *****************************************************************************/ - -static void iwl_setup_deferred_work(struct iwl_priv *priv) -{ - priv->workqueue = create_singlethread_workqueue(DRV_NAME); - - init_waitqueue_head(&priv->wait_command_queue); - - INIT_WORK(&priv->up, iwl_bg_up); - INIT_WORK(&priv->restart, iwl_bg_restart); - INIT_WORK(&priv->rx_replenish, iwl_bg_rx_replenish); - INIT_WORK(&priv->beacon_update, iwl_bg_beacon_update); - INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work); - INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start); - INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start); - - iwl_setup_scan_deferred_work(priv); - - if (priv->cfg->ops->lib->setup_deferred_work) - priv->cfg->ops->lib->setup_deferred_work(priv); - - init_timer(&priv->statistics_periodic); - priv->statistics_periodic.data = (unsigned long)priv; - priv->statistics_periodic.function = iwl_bg_statistics_periodic; - - if (!priv->cfg->use_isr_legacy) - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet, (unsigned long)priv); - else - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl_irq_tasklet_legacy, (unsigned long)priv); -} - -static void iwl_cancel_deferred_work(struct iwl_priv *priv) -{ - if (priv->cfg->ops->lib->cancel_deferred_work) - priv->cfg->ops->lib->cancel_deferred_work(priv); - - cancel_delayed_work_sync(&priv->init_alive_start); - cancel_delayed_work(&priv->scan_check); - cancel_delayed_work(&priv->alive_start); - cancel_work_sync(&priv->beacon_update); - del_timer_sync(&priv->statistics_periodic); -} - -static struct attribute *iwl_sysfs_entries[] = { - &dev_attr_flags.attr, - &dev_attr_filter_flags.attr, - &dev_attr_statistics.attr, - &dev_attr_temperature.attr, - &dev_attr_tx_power.attr, -#ifdef CONFIG_IWLWIFI_DEBUG - &dev_attr_debug_level.attr, -#endif - NULL -}; - -static struct attribute_group iwl_attribute_group = { - .name = NULL, /* put in device directory */ - .attrs = iwl_sysfs_entries, -}; - -static struct ieee80211_ops iwl_hw_ops = { - .tx = iwl_mac_tx, - .start = iwl_mac_start, - .stop = iwl_mac_stop, - .add_interface = iwl_mac_add_interface, - .remove_interface = iwl_mac_remove_interface, - .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, - .set_key = iwl_mac_set_key, - .update_tkip_key = iwl_mac_update_tkip_key, - .get_stats = iwl_mac_get_stats, - .get_tx_stats = iwl_mac_get_tx_stats, - .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl_mac_reset_tsf, - .bss_info_changed = iwl_bss_info_changed, - .ampdu_action = iwl_mac_ampdu_action, - .hw_scan = iwl_mac_hw_scan -}; - -static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = 0; - struct iwl_priv *priv; - struct ieee80211_hw *hw; - struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - unsigned long flags; - u16 pci_cmd; - - /************************ - * 1. Allocating HW data - ************************/ - - /* Disabling hardware scan means that mac80211 will perform scans - * "the hard way", rather than using device's scan. */ - if (cfg->mod_params->disable_hw_scan) { - if (iwl_debug_level & IWL_DL_INFO) - dev_printk(KERN_DEBUG, &(pdev->dev), - "Disabling hw_scan\n"); - iwl_hw_ops.hw_scan = NULL; - } - - hw = iwl_alloc_all(cfg, &iwl_hw_ops); - if (!hw) { - err = -ENOMEM; - goto out; - } - priv = hw->priv; - /* At this point both hw and priv are allocated. */ - - SET_IEEE80211_DEV(hw, &pdev->dev); - - IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); - priv->cfg = cfg; - priv->pci_dev = pdev; - priv->inta_mask = CSR_INI_SET_MASK; - -#ifdef CONFIG_IWLWIFI_DEBUG - atomic_set(&priv->restrict_refcnt, 0); -#endif - if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, "Not enough memory to generate traffic log\n"); - - /************************** - * 2. Initializing PCI bus - **************************/ - if (pci_enable_device(pdev)) { - err = -ENODEV; - goto out_ieee80211_free_hw; - } - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36)); - if (err) { - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - /* both attempts failed: */ - if (err) { - IWL_WARN(priv, "No suitable DMA available.\n"); - goto out_pci_disable_device; - } - } - - err = pci_request_regions(pdev, DRV_NAME); - if (err) - goto out_pci_disable_device; - - pci_set_drvdata(pdev, priv); - - - /*********************** - * 3. Read REV register - ***********************/ - priv->hw_base = pci_iomap(pdev, 0, 0); - if (!priv->hw_base) { - err = -ENODEV; - goto out_pci_release_regions; - } - - IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", - (unsigned long long) pci_resource_len(pdev, 0)); - IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); - - /* this spin lock will be used in apm_ops.init and EEPROM access - * we should init now - */ - spin_lock_init(&priv->reg_lock); - iwl_hw_detect(priv); - IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s REV=0x%X\n", - priv->cfg->name, priv->hw_rev); - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00); - - iwl_prepare_card_hw(priv); - if (!priv->hw_ready) { - IWL_WARN(priv, "Failed, HW not ready\n"); - goto out_iounmap; - } - - /* amp init */ - err = priv->cfg->ops->lib->apm_ops.init(priv); - if (err < 0) { - IWL_ERR(priv, "Failed to init APMG\n"); - goto out_iounmap; - } - /***************** - * 4. Read EEPROM - *****************/ - /* Read the EEPROM */ - err = iwl_eeprom_init(priv); - if (err) { - IWL_ERR(priv, "Unable to init EEPROM\n"); - goto out_iounmap; - } - err = iwl_eeprom_check_version(priv); - if (err) - goto out_free_eeprom; - - /* extract MAC Address */ - iwl_eeprom_get_mac(priv, priv->mac_addr); - IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); - SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); - - /************************ - * 5. Setup HW constants - ************************/ - if (iwl_set_hw_params(priv)) { - IWL_ERR(priv, "failed to set hw parameters\n"); - goto out_free_eeprom; - } - - /******************* - * 6. Setup priv - *******************/ - - err = iwl_init_drv(priv); - if (err) - goto out_free_eeprom; - /* At this point both hw and priv are initialized. */ - - /******************** - * 7. Setup services - ********************/ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - pci_enable_msi(priv->pci_dev); - - iwl_alloc_isr_ict(priv); - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, - IRQF_SHARED, DRV_NAME, priv); - if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); - goto out_disable_msi; - } - err = sysfs_create_group(&pdev->dev.kobj, &iwl_attribute_group); - if (err) { - IWL_ERR(priv, "failed to create sysfs device attributes\n"); - goto out_free_irq; - } - - iwl_setup_deferred_work(priv); - iwl_setup_rx_handlers(priv); - - /********************************** - * 8. Setup and register mac80211 - **********************************/ - - /* enable interrupts if needed: hw bug w/a */ - pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_INTX_DISABLE) { - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd); - } - - iwl_enable_interrupts(priv); - - err = iwl_setup_mac(priv); - if (err) - goto out_remove_sysfs; - - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) - IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->status)); - - iwl_power_initialize(priv); - iwl_tt_initialize(priv); - return 0; - - out_remove_sysfs: - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); - out_free_irq: - free_irq(priv->pci_dev->irq, priv); - iwl_free_isr_ict(priv); - out_disable_msi: - pci_disable_msi(priv->pci_dev); - iwl_uninit_drv(priv); - out_free_eeprom: - iwl_eeprom_free(priv); - out_iounmap: - pci_iounmap(pdev, priv->hw_base); - out_pci_release_regions: - pci_set_drvdata(pdev, NULL); - pci_release_regions(pdev); - out_pci_disable_device: - pci_disable_device(pdev); - out_ieee80211_free_hw: - iwl_free_traffic_mem(priv); - ieee80211_free_hw(priv->hw); - out: - return err; -} - -static void __devexit iwl_pci_remove(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - unsigned long flags; - - if (!priv) - return; - - IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); - - iwl_dbgfs_unregister(priv); - sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group); - - /* ieee80211_unregister_hw call wil cause iwl_mac_stop to - * to be called and iwl_down since we are removing the device - * we need to set STATUS_EXIT_PENDING bit. - */ - set_bit(STATUS_EXIT_PENDING, &priv->status); - if (priv->mac80211_registered) { - ieee80211_unregister_hw(priv->hw); - priv->mac80211_registered = 0; - } else { - iwl_down(priv); - } - - iwl_tt_exit(priv); - - /* make sure we flush any pending irq or - * tasklet for the driver - */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_synchronize_irq(priv); - - iwl_dealloc_ucode_pci(priv); - - if (priv->rxq.bd) - iwl_rx_queue_free(priv, &priv->rxq); - iwl_hw_txq_ctx_free(priv); - - iwl_clear_stations_table(priv); - iwl_eeprom_free(priv); - - - /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); - - /* ieee80211_unregister_hw calls iwl_mac_stop, which flushes - * priv->workqueue... so we can't take down the workqueue - * until now... */ - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - iwl_free_traffic_mem(priv); - - free_irq(priv->pci_dev->irq, priv); - pci_disable_msi(priv->pci_dev); - pci_iounmap(pdev, priv->hw_base); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - - iwl_uninit_drv(priv); - - iwl_free_isr_ict(priv); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - ieee80211_free_hw(priv->hw); -} - - -/***************************************************************************** - * - * driver and module entry point - * - *****************************************************************************/ - -/* Hardware specific file defines the PCI IDs table for that hardware module */ -static struct pci_device_id iwl_hw_card_ids[] = { -#ifdef CONFIG_IWL4965 - {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)}, - {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)}, -#endif /* CONFIG_IWL4965 */ -#ifdef CONFIG_IWL5000 -/* 5100 Series WiFi */ - {IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1304, iwl5100_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bgn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bgn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1221, iwl5100_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1321, iwl5100_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1224, iwl5100_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1324, iwl5100_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1225, iwl5100_bgn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1325, iwl5100_bgn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1226, iwl5100_abg_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1211, iwl5100_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1311, iwl5100_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1214, iwl5100_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1314, iwl5100_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1215, iwl5100_bgn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1315, iwl5100_bgn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4237, 0x1316, iwl5100_abg_cfg)}, /* Half Mini Card */ - -/* 5300 Series WiFi */ - {IWL_PCI_DEVICE(0x4235, 0x1021, iwl5300_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1121, iwl5300_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1024, iwl5300_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1124, iwl5300_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1001, iwl5300_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1101, iwl5300_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1004, iwl5300_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4235, 0x1104, iwl5300_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4236, 0x1011, iwl5300_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4236, 0x1111, iwl5300_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x4236, 0x1014, iwl5300_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x4236, 0x1114, iwl5300_agn_cfg)}, /* Half Mini Card */ - -/* 5350 Series WiFi/WiMax */ - {IWL_PCI_DEVICE(0x423A, 0x1001, iwl5350_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423A, 0x1021, iwl5350_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423B, 0x1011, iwl5350_agn_cfg)}, /* Mini Card */ - -/* 5150 Series Wifi/WiMax */ - {IWL_PCI_DEVICE(0x423C, 0x1201, iwl5150_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423C, 0x1301, iwl5150_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x423C, 0x1206, iwl5150_abg_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423C, 0x1306, iwl5150_abg_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x423C, 0x1221, iwl5150_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423C, 0x1321, iwl5150_agn_cfg)}, /* Half Mini Card */ - - {IWL_PCI_DEVICE(0x423D, 0x1211, iwl5150_agn_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423D, 0x1311, iwl5150_agn_cfg)}, /* Half Mini Card */ - {IWL_PCI_DEVICE(0x423D, 0x1216, iwl5150_abg_cfg)}, /* Mini Card */ - {IWL_PCI_DEVICE(0x423D, 0x1316, iwl5150_abg_cfg)}, /* Half Mini Card */ -/* 6000/6050 Series */ - {IWL_PCI_DEVICE(0x008D, PCI_ANY_ID, iwl6000h_2agn_cfg)}, - {IWL_PCI_DEVICE(0x008E, PCI_ANY_ID, iwl6000h_2agn_cfg)}, - {IWL_PCI_DEVICE(0x422B, PCI_ANY_ID, iwl6000_3agn_cfg)}, - {IWL_PCI_DEVICE(0x422C, PCI_ANY_ID, iwl6000i_2agn_cfg)}, - {IWL_PCI_DEVICE(0x4238, PCI_ANY_ID, iwl6000_3agn_cfg)}, - {IWL_PCI_DEVICE(0x4239, PCI_ANY_ID, iwl6000i_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0086, PCI_ANY_ID, iwl6050_3agn_cfg)}, - {IWL_PCI_DEVICE(0x0087, PCI_ANY_ID, iwl6050_2agn_cfg)}, - {IWL_PCI_DEVICE(0x0088, PCI_ANY_ID, iwl6050_3agn_cfg)}, - {IWL_PCI_DEVICE(0x0089, PCI_ANY_ID, iwl6050_2agn_cfg)}, -/* 1000 Series WiFi */ - {IWL_PCI_DEVICE(0x0083, PCI_ANY_ID, iwl1000_bgn_cfg)}, - {IWL_PCI_DEVICE(0x0084, PCI_ANY_ID, iwl1000_bgn_cfg)}, -#endif /* CONFIG_IWL5000 */ - - {0} -}; -MODULE_DEVICE_TABLE(pci, iwl_hw_card_ids); - -static struct pci_driver iwl_driver = { - .name = DRV_NAME, - .id_table = iwl_hw_card_ids, - .probe = iwl_pci_probe, - .remove = __devexit_p(iwl_pci_remove), -#ifdef CONFIG_PM - .suspend = iwl_pci_suspend, - .resume = iwl_pci_resume, -#endif -}; - -static int __init iwl_init(void) -{ - - int ret; - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); - - ret = iwlagn_rate_control_register(); - if (ret) { - printk(KERN_ERR DRV_NAME - "Unable to register rate control algorithm: %d\n", ret); - return ret; - } - - ret = pci_register_driver(&iwl_driver); - if (ret) { - printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); - goto error_register; - } - - return ret; - -error_register: - iwlagn_rate_control_unregister(); - return ret; -} - -static void __exit iwl_exit(void) -{ - pci_unregister_driver(&iwl_driver); - iwlagn_rate_control_unregister(); -} - -module_exit(iwl_exit); -module_init(iwl_init); - -#ifdef CONFIG_IWLWIFI_DEBUG -module_param_named(debug50, iwl_debug_level, uint, 0444); -MODULE_PARM_DESC(debug50, "50XX debug output mask (deprecated)"); -module_param_named(debug, iwl_debug_level, uint, 0644); -MODULE_PARM_DESC(debug, "debug output mask"); -#endif - diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c deleted file mode 100644 index c4b565a2de94..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ /dev/null @@ -1,876 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#include - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-calib.h" - -/***************************************************************************** - * INIT calibrations framework - *****************************************************************************/ - -struct statistics_general_data { - u32 beacon_silence_rssi_a; - u32 beacon_silence_rssi_b; - u32 beacon_silence_rssi_c; - u32 beacon_energy_a; - u32 beacon_energy_b; - u32 beacon_energy_c; -}; - -int iwl_send_calib_results(struct iwl_priv *priv) -{ - int ret = 0; - int i = 0; - - struct iwl_host_cmd hcmd = { - .id = REPLY_PHY_CALIBRATION_CMD, - .flags = CMD_SIZE_HUGE, - }; - - for (i = 0; i < IWL_CALIB_MAX; i++) { - if ((BIT(i) & priv->hw_params.calib_init_cfg) && - priv->calib_results[i].buf) { - hcmd.len = priv->calib_results[i].buf_len; - hcmd.data = priv->calib_results[i].buf; - ret = iwl_send_cmd_sync(priv, &hcmd); - if (ret) - goto err; - } - } - - return 0; -err: - IWL_ERR(priv, "Error %d iteration %d\n", ret, i); - return ret; -} -EXPORT_SYMBOL(iwl_send_calib_results); - -int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len) -{ - if (res->buf_len != len) { - kfree(res->buf); - res->buf = kzalloc(len, GFP_ATOMIC); - } - if (unlikely(res->buf == NULL)) - return -ENOMEM; - - res->buf_len = len; - memcpy(res->buf, buf, len); - return 0; -} -EXPORT_SYMBOL(iwl_calib_set); - -void iwl_calib_free_results(struct iwl_priv *priv) -{ - int i; - - for (i = 0; i < IWL_CALIB_MAX; i++) { - kfree(priv->calib_results[i].buf); - priv->calib_results[i].buf = NULL; - priv->calib_results[i].buf_len = 0; - } -} - -/***************************************************************************** - * RUNTIME calibrations framework - *****************************************************************************/ - -/* "false alarms" are signals that our DSP tries to lock onto, - * but then determines that they are either noise, or transmissions - * from a distant wireless network (also "noise", really) that get - * "stepped on" by stronger transmissions within our own network. - * This algorithm attempts to set a sensitivity level that is high - * enough to receive all of our own network traffic, but not so - * high that our DSP gets too busy trying to lock onto non-network - * activity/noise. */ -static int iwl_sens_energy_cck(struct iwl_priv *priv, - u32 norm_fa, - u32 rx_enable_time, - struct statistics_general_data *rx_info) -{ - u32 max_nrg_cck = 0; - int i = 0; - u8 max_silence_rssi = 0; - u32 silence_ref = 0; - u8 silence_rssi_a = 0; - u8 silence_rssi_b = 0; - u8 silence_rssi_c = 0; - u32 val; - - /* "false_alarms" values below are cross-multiplications to assess the - * numbers of false alarms within the measured period of actual Rx - * (Rx is off when we're txing), vs the min/max expected false alarms - * (some should be expected if rx is sensitive enough) in a - * hypothetical listening period of 200 time units (TU), 204.8 msec: - * - * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time - * - * */ - u32 false_alarms = norm_fa * 200 * 1024; - u32 max_false_alarms = MAX_FA_CCK * rx_enable_time; - u32 min_false_alarms = MIN_FA_CCK * rx_enable_time; - struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; - - data = &(priv->sensitivity_data); - - data->nrg_auto_corr_silence_diff = 0; - - /* Find max silence rssi among all 3 receivers. - * This is background noise, which may include transmissions from other - * networks, measured during silence before our network's beacon */ - silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a & - ALL_BAND_FILTER) >> 8); - silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b & - ALL_BAND_FILTER) >> 8); - silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c & - ALL_BAND_FILTER) >> 8); - - val = max(silence_rssi_b, silence_rssi_c); - max_silence_rssi = max(silence_rssi_a, (u8) val); - - /* Store silence rssi in 20-beacon history table */ - data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi; - data->nrg_silence_idx++; - if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L) - data->nrg_silence_idx = 0; - - /* Find max silence rssi across 20 beacon history */ - for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) { - val = data->nrg_silence_rssi[i]; - silence_ref = max(silence_ref, val); - } - IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n", - silence_rssi_a, silence_rssi_b, silence_rssi_c, - silence_ref); - - /* Find max rx energy (min value!) among all 3 receivers, - * measured during beacon frame. - * Save it in 10-beacon history table. */ - i = data->nrg_energy_idx; - val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c); - data->nrg_value[i] = min(rx_info->beacon_energy_a, val); - - data->nrg_energy_idx++; - if (data->nrg_energy_idx >= 10) - data->nrg_energy_idx = 0; - - /* Find min rx energy (max value) across 10 beacon history. - * This is the minimum signal level that we want to receive well. - * Add backoff (margin so we don't miss slightly lower energy frames). - * This establishes an upper bound (min value) for energy threshold. */ - max_nrg_cck = data->nrg_value[0]; - for (i = 1; i < 10; i++) - max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i])); - max_nrg_cck += 6; - - IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n", - rx_info->beacon_energy_a, rx_info->beacon_energy_b, - rx_info->beacon_energy_c, max_nrg_cck - 6); - - /* Count number of consecutive beacons with fewer-than-desired - * false alarms. */ - if (false_alarms < min_false_alarms) - data->num_in_cck_no_fa++; - else - data->num_in_cck_no_fa = 0; - IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n", - data->num_in_cck_no_fa); - - /* If we got too many false alarms this time, reduce sensitivity */ - if ((false_alarms > max_false_alarms) && - (data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) { - IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n", - false_alarms, max_false_alarms); - IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n"); - data->nrg_curr_state = IWL_FA_TOO_MANY; - /* Store for "fewer than desired" on later beacon */ - data->nrg_silence_ref = silence_ref; - - /* increase energy threshold (reduce nrg value) - * to decrease sensitivity */ - data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK; - /* Else if we got fewer than desired, increase sensitivity */ - } else if (false_alarms < min_false_alarms) { - data->nrg_curr_state = IWL_FA_TOO_FEW; - - /* Compare silence level with silence level for most recent - * healthy number or too many false alarms */ - data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref - - (s32)silence_ref; - - IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u, silence diff %d\n", - false_alarms, min_false_alarms, - data->nrg_auto_corr_silence_diff); - - /* Increase value to increase sensitivity, but only if: - * 1a) previous beacon did *not* have *too many* false alarms - * 1b) AND there's a significant difference in Rx levels - * from a previous beacon with too many, or healthy # FAs - * OR 2) We've seen a lot of beacons (100) with too few - * false alarms */ - if ((data->nrg_prev_state != IWL_FA_TOO_MANY) && - ((data->nrg_auto_corr_silence_diff > NRG_DIFF) || - (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) { - - IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n"); - /* Increase nrg value to increase sensitivity */ - val = data->nrg_th_cck + NRG_STEP_CCK; - data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val); - } else { - IWL_DEBUG_CALIB(priv, "... but not changing sensitivity\n"); - } - - /* Else we got a healthy number of false alarms, keep status quo */ - } else { - IWL_DEBUG_CALIB(priv, " FA in safe zone\n"); - data->nrg_curr_state = IWL_FA_GOOD_RANGE; - - /* Store for use in "fewer than desired" with later beacon */ - data->nrg_silence_ref = silence_ref; - - /* If previous beacon had too many false alarms, - * give it some extra margin by reducing sensitivity again - * (but don't go below measured energy of desired Rx) */ - if (IWL_FA_TOO_MANY == data->nrg_prev_state) { - IWL_DEBUG_CALIB(priv, "... increasing margin\n"); - if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN)) - data->nrg_th_cck -= NRG_MARGIN; - else - data->nrg_th_cck = max_nrg_cck; - } - } - - /* Make sure the energy threshold does not go above the measured - * energy of the desired Rx signals (reduced by backoff margin), - * or else we might start missing Rx frames. - * Lower value is higher energy, so we use max()! - */ - data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck); - IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck); - - data->nrg_prev_state = data->nrg_curr_state; - - /* Auto-correlation CCK algorithm */ - if (false_alarms > min_false_alarms) { - - /* increase auto_corr values to decrease sensitivity - * so the DSP won't be disturbed by the noise - */ - if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK) - data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1; - else { - val = data->auto_corr_cck + AUTO_CORR_STEP_CCK; - data->auto_corr_cck = - min((u32)ranges->auto_corr_max_cck, val); - } - val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK; - data->auto_corr_cck_mrc = - min((u32)ranges->auto_corr_max_cck_mrc, val); - } else if ((false_alarms < min_false_alarms) && - ((data->nrg_auto_corr_silence_diff > NRG_DIFF) || - (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) { - - /* Decrease auto_corr values to increase sensitivity */ - val = data->auto_corr_cck - AUTO_CORR_STEP_CCK; - data->auto_corr_cck = - max((u32)ranges->auto_corr_min_cck, val); - val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK; - data->auto_corr_cck_mrc = - max((u32)ranges->auto_corr_min_cck_mrc, val); - } - - return 0; -} - - -static int iwl_sens_auto_corr_ofdm(struct iwl_priv *priv, - u32 norm_fa, - u32 rx_enable_time) -{ - u32 val; - u32 false_alarms = norm_fa * 200 * 1024; - u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time; - u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time; - struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; - - data = &(priv->sensitivity_data); - - /* If we got too many false alarms this time, reduce sensitivity */ - if (false_alarms > max_false_alarms) { - - IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n", - false_alarms, max_false_alarms); - - val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm = - min((u32)ranges->auto_corr_max_ofdm, val); - - val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm_mrc = - min((u32)ranges->auto_corr_max_ofdm_mrc, val); - - val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm_x1 = - min((u32)ranges->auto_corr_max_ofdm_x1, val); - - val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm_mrc_x1 = - min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val); - } - - /* Else if we got fewer than desired, increase sensitivity */ - else if (false_alarms < min_false_alarms) { - - IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n", - false_alarms, min_false_alarms); - - val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm = - max((u32)ranges->auto_corr_min_ofdm, val); - - val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm_mrc = - max((u32)ranges->auto_corr_min_ofdm_mrc, val); - - val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm_x1 = - max((u32)ranges->auto_corr_min_ofdm_x1, val); - - val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM; - data->auto_corr_ofdm_mrc_x1 = - max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val); - } else { - IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n", - min_false_alarms, false_alarms, max_false_alarms); - } - return 0; -} - -/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */ -static int iwl_sensitivity_write(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl_sensitivity_cmd cmd ; - struct iwl_sensitivity_data *data = NULL; - struct iwl_host_cmd cmd_out = { - .id = SENSITIVITY_CMD, - .len = sizeof(struct iwl_sensitivity_cmd), - .flags = CMD_ASYNC, - .data = &cmd, - }; - - data = &(priv->sensitivity_data); - - memset(&cmd, 0, sizeof(cmd)); - - cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] = - cpu_to_le16((u16)data->auto_corr_ofdm); - cmd.table[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] = - cpu_to_le16((u16)data->auto_corr_ofdm_mrc); - cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] = - cpu_to_le16((u16)data->auto_corr_ofdm_x1); - cmd.table[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] = - cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1); - - cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] = - cpu_to_le16((u16)data->auto_corr_cck); - cmd.table[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] = - cpu_to_le16((u16)data->auto_corr_cck_mrc); - - cmd.table[HD_MIN_ENERGY_CCK_DET_INDEX] = - cpu_to_le16((u16)data->nrg_th_cck); - cmd.table[HD_MIN_ENERGY_OFDM_DET_INDEX] = - cpu_to_le16((u16)data->nrg_th_ofdm); - - cmd.table[HD_BARKER_CORR_TH_ADD_MIN_INDEX] = - cpu_to_le16(190); - cmd.table[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] = - cpu_to_le16(390); - cmd.table[HD_OFDM_ENERGY_TH_IN_INDEX] = - cpu_to_le16(62); - - IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n", - data->auto_corr_ofdm, data->auto_corr_ofdm_mrc, - data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1, - data->nrg_th_ofdm); - - IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n", - data->auto_corr_cck, data->auto_corr_cck_mrc, - data->nrg_th_cck); - - /* Update uCode's "work" table, and copy it to DSP */ - cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE; - - /* Don't send command to uCode if nothing has changed */ - if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]), - sizeof(u16)*HD_TABLE_SIZE)) { - IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n"); - return 0; - } - - /* Copy table for comparison next time */ - memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]), - sizeof(u16)*HD_TABLE_SIZE); - - ret = iwl_send_cmd(priv, &cmd_out); - if (ret) - IWL_ERR(priv, "SENSITIVITY_CMD failed\n"); - - return ret; -} - -void iwl_init_sensitivity(struct iwl_priv *priv) -{ - int ret = 0; - int i; - struct iwl_sensitivity_data *data = NULL; - const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens; - - if (priv->disable_sens_cal) - return; - - IWL_DEBUG_CALIB(priv, "Start iwl_init_sensitivity\n"); - - /* Clear driver's sensitivity algo data */ - data = &(priv->sensitivity_data); - - if (ranges == NULL) - return; - - memset(data, 0, sizeof(struct iwl_sensitivity_data)); - - data->num_in_cck_no_fa = 0; - data->nrg_curr_state = IWL_FA_TOO_MANY; - data->nrg_prev_state = IWL_FA_TOO_MANY; - data->nrg_silence_ref = 0; - data->nrg_silence_idx = 0; - data->nrg_energy_idx = 0; - - for (i = 0; i < 10; i++) - data->nrg_value[i] = 0; - - for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) - data->nrg_silence_rssi[i] = 0; - - data->auto_corr_ofdm = 90; - data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc; - data->auto_corr_ofdm_x1 = ranges->auto_corr_min_ofdm_x1; - data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1; - data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF; - data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc; - data->nrg_th_cck = ranges->nrg_th_cck; - data->nrg_th_ofdm = ranges->nrg_th_ofdm; - - data->last_bad_plcp_cnt_ofdm = 0; - data->last_fa_cnt_ofdm = 0; - data->last_bad_plcp_cnt_cck = 0; - data->last_fa_cnt_cck = 0; - - ret |= iwl_sensitivity_write(priv); - IWL_DEBUG_CALIB(priv, "<rx.general); - struct statistics_rx *statistics = &(resp->rx); - unsigned long flags; - struct statistics_general_data statis; - - if (priv->disable_sens_cal) - return; - - data = &(priv->sensitivity_data); - - if (!iwl_is_associated(priv)) { - IWL_DEBUG_CALIB(priv, "<< - not associated\n"); - return; - } - - spin_lock_irqsave(&priv->lock, flags); - if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { - IWL_DEBUG_CALIB(priv, "<< invalid data.\n"); - spin_unlock_irqrestore(&priv->lock, flags); - return; - } - - /* Extract Statistics: */ - rx_enable_time = le32_to_cpu(rx_info->channel_load); - fa_cck = le32_to_cpu(statistics->cck.false_alarm_cnt); - fa_ofdm = le32_to_cpu(statistics->ofdm.false_alarm_cnt); - bad_plcp_cck = le32_to_cpu(statistics->cck.plcp_err); - bad_plcp_ofdm = le32_to_cpu(statistics->ofdm.plcp_err); - - statis.beacon_silence_rssi_a = - le32_to_cpu(statistics->general.beacon_silence_rssi_a); - statis.beacon_silence_rssi_b = - le32_to_cpu(statistics->general.beacon_silence_rssi_b); - statis.beacon_silence_rssi_c = - le32_to_cpu(statistics->general.beacon_silence_rssi_c); - statis.beacon_energy_a = - le32_to_cpu(statistics->general.beacon_energy_a); - statis.beacon_energy_b = - le32_to_cpu(statistics->general.beacon_energy_b); - statis.beacon_energy_c = - le32_to_cpu(statistics->general.beacon_energy_c); - - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time); - - if (!rx_enable_time) { - IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0! \n"); - return; - } - - /* These statistics increase monotonically, and do not reset - * at each beacon. Calculate difference from last value, or just - * use the new statistics value if it has reset or wrapped around. */ - if (data->last_bad_plcp_cnt_cck > bad_plcp_cck) - data->last_bad_plcp_cnt_cck = bad_plcp_cck; - else { - bad_plcp_cck -= data->last_bad_plcp_cnt_cck; - data->last_bad_plcp_cnt_cck += bad_plcp_cck; - } - - if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm) - data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm; - else { - bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm; - data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm; - } - - if (data->last_fa_cnt_ofdm > fa_ofdm) - data->last_fa_cnt_ofdm = fa_ofdm; - else { - fa_ofdm -= data->last_fa_cnt_ofdm; - data->last_fa_cnt_ofdm += fa_ofdm; - } - - if (data->last_fa_cnt_cck > fa_cck) - data->last_fa_cnt_cck = fa_cck; - else { - fa_cck -= data->last_fa_cnt_cck; - data->last_fa_cnt_cck += fa_cck; - } - - /* Total aborted signal locks */ - norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm; - norm_fa_cck = fa_cck + bad_plcp_cck; - - IWL_DEBUG_CALIB(priv, "cck: fa %u badp %u ofdm: fa %u badp %u\n", fa_cck, - bad_plcp_cck, fa_ofdm, bad_plcp_ofdm); - - iwl_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time); - iwl_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis); - iwl_sensitivity_write(priv); - - return; -} -EXPORT_SYMBOL(iwl_sensitivity_calibration); - -/* - * Accumulate 20 beacons of signal and noise statistics for each of - * 3 receivers/antennas/rx-chains, then figure out: - * 1) Which antennas are connected. - * 2) Differential rx gain settings to balance the 3 receivers. - */ -void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *stat_resp) -{ - struct iwl_chain_noise_data *data = NULL; - - u32 chain_noise_a; - u32 chain_noise_b; - u32 chain_noise_c; - u32 chain_sig_a; - u32 chain_sig_b; - u32 chain_sig_c; - u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; - u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE}; - u32 max_average_sig; - u16 max_average_sig_antenna_i; - u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE; - u16 min_average_noise_antenna_i = INITIALIZATION_VALUE; - u16 i = 0; - u16 rxon_chnum = INITIALIZATION_VALUE; - u16 stat_chnum = INITIALIZATION_VALUE; - u8 rxon_band24; - u8 stat_band24; - u32 active_chains = 0; - u8 num_tx_chains; - unsigned long flags; - struct statistics_rx_non_phy *rx_info = &(stat_resp->rx.general); - - if (priv->disable_chain_noise_cal) - return; - - data = &(priv->chain_noise_data); - - /* Accumulate just the first 20 beacons after the first association, - * then we're done forever. */ - if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) { - if (data->state == IWL_CHAIN_NOISE_ALIVE) - IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n"); - return; - } - - spin_lock_irqsave(&priv->lock, flags); - if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) { - IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n"); - spin_unlock_irqrestore(&priv->lock, flags); - return; - } - - rxon_band24 = !!(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK); - rxon_chnum = le16_to_cpu(priv->staging_rxon.channel); - stat_band24 = !!(stat_resp->flag & STATISTICS_REPLY_FLG_BAND_24G_MSK); - stat_chnum = le32_to_cpu(stat_resp->flag) >> 16; - - /* Make sure we accumulate data for just the associated channel - * (even if scanning). */ - if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) { - IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n", - rxon_chnum, rxon_band24); - spin_unlock_irqrestore(&priv->lock, flags); - return; - } - - /* Accumulate beacon statistics values across 20 beacons */ - chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) & - IN_BAND_FILTER; - chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) & - IN_BAND_FILTER; - chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) & - IN_BAND_FILTER; - - chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER; - chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER; - chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER; - - spin_unlock_irqrestore(&priv->lock, flags); - - data->beacon_count++; - - data->chain_noise_a = (chain_noise_a + data->chain_noise_a); - data->chain_noise_b = (chain_noise_b + data->chain_noise_b); - data->chain_noise_c = (chain_noise_c + data->chain_noise_c); - - data->chain_signal_a = (chain_sig_a + data->chain_signal_a); - data->chain_signal_b = (chain_sig_b + data->chain_signal_b); - data->chain_signal_c = (chain_sig_c + data->chain_signal_c); - - IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n", - rxon_chnum, rxon_band24, data->beacon_count); - IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n", - chain_sig_a, chain_sig_b, chain_sig_c); - IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n", - chain_noise_a, chain_noise_b, chain_noise_c); - - /* If this is the 20th beacon, determine: - * 1) Disconnected antennas (using signal strengths) - * 2) Differential gain (using silence noise) to balance receivers */ - if (data->beacon_count != CAL_NUM_OF_BEACONS) - return; - - /* Analyze signal for disconnected antenna */ - average_sig[0] = (data->chain_signal_a) / CAL_NUM_OF_BEACONS; - average_sig[1] = (data->chain_signal_b) / CAL_NUM_OF_BEACONS; - average_sig[2] = (data->chain_signal_c) / CAL_NUM_OF_BEACONS; - - if (average_sig[0] >= average_sig[1]) { - max_average_sig = average_sig[0]; - max_average_sig_antenna_i = 0; - active_chains = (1 << max_average_sig_antenna_i); - } else { - max_average_sig = average_sig[1]; - max_average_sig_antenna_i = 1; - active_chains = (1 << max_average_sig_antenna_i); - } - - if (average_sig[2] >= max_average_sig) { - max_average_sig = average_sig[2]; - max_average_sig_antenna_i = 2; - active_chains = (1 << max_average_sig_antenna_i); - } - - IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n", - average_sig[0], average_sig[1], average_sig[2]); - IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n", - max_average_sig, max_average_sig_antenna_i); - - /* Compare signal strengths for all 3 receivers. */ - for (i = 0; i < NUM_RX_CHAINS; i++) { - if (i != max_average_sig_antenna_i) { - s32 rssi_delta = (max_average_sig - average_sig[i]); - - /* If signal is very weak, compared with - * strongest, mark it as disconnected. */ - if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS) - data->disconn_array[i] = 1; - else - active_chains |= (1 << i); - IWL_DEBUG_CALIB(priv, "i = %d rssiDelta = %d " - "disconn_array[i] = %d\n", - i, rssi_delta, data->disconn_array[i]); - } - } - - num_tx_chains = 0; - for (i = 0; i < NUM_RX_CHAINS; i++) { - /* loops on all the bits of - * priv->hw_setting.valid_tx_ant */ - u8 ant_msk = (1 << i); - if (!(priv->hw_params.valid_tx_ant & ant_msk)) - continue; - - num_tx_chains++; - if (data->disconn_array[i] == 0) - /* there is a Tx antenna connected */ - break; - if (num_tx_chains == priv->hw_params.tx_chains_num && - data->disconn_array[i]) { - /* This is the last TX antenna and is also - * disconnected connect it anyway */ - data->disconn_array[i] = 0; - active_chains |= ant_msk; - IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected W/A - " - "declare %d as connected\n", i); - break; - } - } - - /* Save for use within RXON, TX, SCAN commands, etc. */ - priv->chain_noise_data.active_chains = active_chains; - IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n", - active_chains); - - /* Analyze noise for rx balance */ - average_noise[0] = ((data->chain_noise_a)/CAL_NUM_OF_BEACONS); - average_noise[1] = ((data->chain_noise_b)/CAL_NUM_OF_BEACONS); - average_noise[2] = ((data->chain_noise_c)/CAL_NUM_OF_BEACONS); - - for (i = 0; i < NUM_RX_CHAINS; i++) { - if (!(data->disconn_array[i]) && - (average_noise[i] <= min_average_noise)) { - /* This means that chain i is active and has - * lower noise values so far: */ - min_average_noise = average_noise[i]; - min_average_noise_antenna_i = i; - } - } - - IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n", - average_noise[0], average_noise[1], - average_noise[2]); - - IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n", - min_average_noise, min_average_noise_antenna_i); - - if (priv->cfg->ops->utils->gain_computation) - priv->cfg->ops->utils->gain_computation(priv, average_noise, - min_average_noise_antenna_i, min_average_noise); - - /* Some power changes may have been made during the calibration. - * Update and commit the RXON - */ - if (priv->cfg->ops->lib->update_chain_flags) - priv->cfg->ops->lib->update_chain_flags(priv); - - data->state = IWL_CHAIN_NOISE_DONE; - iwl_power_update_mode(priv, false); -} -EXPORT_SYMBOL(iwl_chain_noise_calibration); - - -void iwl_reset_run_time_calib(struct iwl_priv *priv) -{ - int i; - memset(&(priv->sensitivity_data), 0, - sizeof(struct iwl_sensitivity_data)); - memset(&(priv->chain_noise_data), 0, - sizeof(struct iwl_chain_noise_data)); - for (i = 0; i < NUM_RX_CHAINS; i++) - priv->chain_noise_data.delta_gain_code[i] = - CHAIN_NOISE_DELTA_GAIN_INIT_VAL; - - /* Ask for statistics now, the uCode will send notification - * periodically after association */ - iwl_send_statistics_request(priv, CMD_ASYNC); -} -EXPORT_SYMBOL(iwl_reset_run_time_calib); - diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.h b/drivers/net/wireless/iwlwifi/iwl-calib.h deleted file mode 100644 index b6cef989a796..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-calib.h +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ -#ifndef __iwl_calib_h__ -#define __iwl_calib_h__ - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-commands.h" - -void iwl_chain_noise_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *stat_resp); -void iwl_sensitivity_calibration(struct iwl_priv *priv, - struct iwl_notif_statistics *resp); - -void iwl_init_sensitivity(struct iwl_priv *priv); -void iwl_reset_run_time_calib(struct iwl_priv *priv); -static inline void iwl_chain_noise_reset(struct iwl_priv *priv) -{ - - if (!priv->disable_chain_noise_cal && - priv->cfg->ops->utils->chain_noise_reset) - priv->cfg->ops->utils->chain_noise_reset(priv); -} - -#endif /* __iwl_calib_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h deleted file mode 100644 index 4afaf773aeac..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ /dev/null @@ -1,3524 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -/* - * Please use this file (iwl-commands.h) only for uCode API definitions. - * Please use iwl-4965-hw.h for hardware-related definitions. - * Please use iwl-dev.h for driver implementation definitions. - */ - -#ifndef __iwl_commands_h__ -#define __iwl_commands_h__ - -struct iwl_priv; - -/* uCode version contains 4 values: Major/Minor/API/Serial */ -#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24) -#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16) -#define IWL_UCODE_API(ver) (((ver) & 0x0000FF00) >> 8) -#define IWL_UCODE_SERIAL(ver) ((ver) & 0x000000FF) - - -/* Tx rates */ -#define IWL_CCK_RATES 4 -#define IWL_OFDM_RATES 8 -#define IWL_MAX_RATES (IWL_CCK_RATES + IWL_OFDM_RATES) - -enum { - REPLY_ALIVE = 0x1, - REPLY_ERROR = 0x2, - - /* RXON and QOS commands */ - REPLY_RXON = 0x10, - REPLY_RXON_ASSOC = 0x11, - REPLY_QOS_PARAM = 0x13, - REPLY_RXON_TIMING = 0x14, - - /* Multi-Station support */ - REPLY_ADD_STA = 0x18, - REPLY_REMOVE_STA = 0x19, /* not used */ - REPLY_REMOVE_ALL_STA = 0x1a, /* not used */ - - /* Security */ - REPLY_WEPKEY = 0x20, - - /* RX, TX, LEDs */ - REPLY_3945_RX = 0x1b, /* 3945 only */ - REPLY_TX = 0x1c, - REPLY_RATE_SCALE = 0x47, /* 3945 only */ - REPLY_LEDS_CMD = 0x48, - REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* 4965 only */ - - /* WiMAX coexistence */ - COEX_PRIORITY_TABLE_CMD = 0x5a, /*5000 only */ - COEX_MEDIUM_NOTIFICATION = 0x5b, - COEX_EVENT_CMD = 0x5c, - - /* Calibration */ - CALIBRATION_CFG_CMD = 0x65, - CALIBRATION_RES_NOTIFICATION = 0x66, - CALIBRATION_COMPLETE_NOTIFICATION = 0x67, - - /* 802.11h related */ - RADAR_NOTIFICATION = 0x70, /* not used */ - REPLY_QUIET_CMD = 0x71, /* not used */ - REPLY_CHANNEL_SWITCH = 0x72, - CHANNEL_SWITCH_NOTIFICATION = 0x73, - REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74, - SPECTRUM_MEASURE_NOTIFICATION = 0x75, - - /* Power Management */ - POWER_TABLE_CMD = 0x77, - PM_SLEEP_NOTIFICATION = 0x7A, - PM_DEBUG_STATISTIC_NOTIFIC = 0x7B, - - /* Scan commands and notifications */ - REPLY_SCAN_CMD = 0x80, - REPLY_SCAN_ABORT_CMD = 0x81, - SCAN_START_NOTIFICATION = 0x82, - SCAN_RESULTS_NOTIFICATION = 0x83, - SCAN_COMPLETE_NOTIFICATION = 0x84, - - /* IBSS/AP commands */ - BEACON_NOTIFICATION = 0x90, - REPLY_TX_BEACON = 0x91, - WHO_IS_AWAKE_NOTIFICATION = 0x94, /* not used */ - - /* Miscellaneous commands */ - REPLY_TX_POWER_DBM_CMD = 0x95, - QUIET_NOTIFICATION = 0x96, /* not used */ - REPLY_TX_PWR_TABLE_CMD = 0x97, - REPLY_TX_POWER_DBM_CMD_V1 = 0x98, /* old version of API */ - TX_ANT_CONFIGURATION_CMD = 0x98, /* not used */ - MEASURE_ABORT_NOTIFICATION = 0x99, /* not used */ - - /* Bluetooth device coexistence config command */ - REPLY_BT_CONFIG = 0x9b, - - /* Statistics */ - REPLY_STATISTICS_CMD = 0x9c, - STATISTICS_NOTIFICATION = 0x9d, - - /* RF-KILL commands and notifications */ - REPLY_CARD_STATE_CMD = 0xa0, - CARD_STATE_NOTIFICATION = 0xa1, - - /* Missed beacons notification */ - MISSED_BEACONS_NOTIFICATION = 0xa2, - - REPLY_CT_KILL_CONFIG_CMD = 0xa4, - SENSITIVITY_CMD = 0xa8, - REPLY_PHY_CALIBRATION_CMD = 0xb0, - REPLY_RX_PHY_CMD = 0xc0, - REPLY_RX_MPDU_CMD = 0xc1, - REPLY_RX = 0xc3, - REPLY_COMPRESSED_BA = 0xc5, - REPLY_MAX = 0xff -}; - -/****************************************************************************** - * (0) - * Commonly used structures and definitions: - * Command header, rate_n_flags, txpower - * - *****************************************************************************/ - -/* iwl_cmd_header flags value */ -#define IWL_CMD_FAILED_MSK 0x40 - -#define SEQ_TO_QUEUE(s) (((s) >> 8) & 0x1f) -#define QUEUE_TO_SEQ(q) (((q) & 0x1f) << 8) -#define SEQ_TO_INDEX(s) ((s) & 0xff) -#define INDEX_TO_SEQ(i) ((i) & 0xff) -#define SEQ_HUGE_FRAME cpu_to_le16(0x4000) -#define SEQ_RX_FRAME cpu_to_le16(0x8000) - -/** - * struct iwl_cmd_header - * - * This header format appears in the beginning of each command sent from the - * driver, and each response/notification received from uCode. - */ -struct iwl_cmd_header { - u8 cmd; /* Command ID: REPLY_RXON, etc. */ - u8 flags; /* 0:5 reserved, 6 abort, 7 internal */ - /* - * The driver sets up the sequence number to values of its choosing. - * uCode does not use this value, but passes it back to the driver - * when sending the response to each driver-originated command, so - * the driver can match the response to the command. Since the values - * don't get used by uCode, the driver may set up an arbitrary format. - * - * There is one exception: uCode sets bit 15 when it originates - * the response/notification, i.e. when the response/notification - * is not a direct response to a command sent by the driver. For - * example, uCode issues REPLY_3945_RX when it sends a received frame - * to the driver; it is not a direct response to any driver command. - * - * The Linux driver uses the following format: - * - * 0:7 tfd index - position within TX queue - * 8:12 TX queue id - * 13 reserved - * 14 huge - driver sets this to indicate command is in the - * 'huge' storage at the end of the command buffers - * 15 unsolicited RX or uCode-originated notification - */ - __le16 sequence; - - /* command or response/notification data follows immediately */ - u8 data[0]; -} __attribute__ ((packed)); - - -/** - * struct iwl3945_tx_power - * - * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH - * - * Each entry contains two values: - * 1) DSP gain (or sometimes called DSP attenuation). This is a fine-grained - * linear value that multiplies the output of the digital signal processor, - * before being sent to the analog radio. - * 2) Radio gain. This sets the analog gain of the radio Tx path. - * It is a coarser setting, and behaves in a logarithmic (dB) fashion. - * - * Driver obtains values from struct iwl3945_tx_power power_gain_table[][]. - */ -struct iwl3945_tx_power { - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ -} __attribute__ ((packed)); - -/** - * struct iwl3945_power_per_rate - * - * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - */ -struct iwl3945_power_per_rate { - u8 rate; /* plcp */ - struct iwl3945_tx_power tpc; - u8 reserved; -} __attribute__ ((packed)); - -/** - * iwlagn rate_n_flags bit fields - * - * rate_n_flags format is used in following iwlagn commands: - * REPLY_RX (response only) - * REPLY_RX_MPDU (response only) - * REPLY_TX (both command and response) - * REPLY_TX_LINK_QUALITY_CMD - * - * High-throughput (HT) rate format for bits 7:0 (bit 8 must be "1"): - * 2-0: 0) 6 Mbps - * 1) 12 Mbps - * 2) 18 Mbps - * 3) 24 Mbps - * 4) 36 Mbps - * 5) 48 Mbps - * 6) 54 Mbps - * 7) 60 Mbps - * - * 4-3: 0) Single stream (SISO) - * 1) Dual stream (MIMO) - * 2) Triple stream (MIMO) - * - * 5: Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data - * - * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"): - * 3-0: 0xD) 6 Mbps - * 0xF) 9 Mbps - * 0x5) 12 Mbps - * 0x7) 18 Mbps - * 0x9) 24 Mbps - * 0xB) 36 Mbps - * 0x1) 48 Mbps - * 0x3) 54 Mbps - * - * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"): - * 6-0: 10) 1 Mbps - * 20) 2 Mbps - * 55) 5.5 Mbps - * 110) 11 Mbps - */ -#define RATE_MCS_CODE_MSK 0x7 -#define RATE_MCS_SPATIAL_POS 3 -#define RATE_MCS_SPATIAL_MSK 0x18 -#define RATE_MCS_HT_DUP_POS 5 -#define RATE_MCS_HT_DUP_MSK 0x20 - -/* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */ -#define RATE_MCS_FLAGS_POS 8 -#define RATE_MCS_HT_POS 8 -#define RATE_MCS_HT_MSK 0x100 - -/* Bit 9: (1) CCK, (0) OFDM. HT (bit 8) must be "0" for this bit to be valid */ -#define RATE_MCS_CCK_POS 9 -#define RATE_MCS_CCK_MSK 0x200 - -/* Bit 10: (1) Use Green Field preamble */ -#define RATE_MCS_GF_POS 10 -#define RATE_MCS_GF_MSK 0x400 - -/* Bit 11: (1) Use 40Mhz HT40 chnl width, (0) use 20 MHz legacy chnl width */ -#define RATE_MCS_HT40_POS 11 -#define RATE_MCS_HT40_MSK 0x800 - -/* Bit 12: (1) Duplicate data on both 20MHz chnls. HT40 (bit 11) must be set. */ -#define RATE_MCS_DUP_POS 12 -#define RATE_MCS_DUP_MSK 0x1000 - -/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */ -#define RATE_MCS_SGI_POS 13 -#define RATE_MCS_SGI_MSK 0x2000 - -/** - * rate_n_flags Tx antenna masks - * 4965 has 2 transmitters - * 5100 has 1 transmitter B - * 5150 has 1 transmitter A - * 5300 has 3 transmitters - * 5350 has 3 transmitters - * bit14:16 - */ -#define RATE_MCS_ANT_POS 14 -#define RATE_MCS_ANT_A_MSK 0x04000 -#define RATE_MCS_ANT_B_MSK 0x08000 -#define RATE_MCS_ANT_C_MSK 0x10000 -#define RATE_MCS_ANT_AB_MSK (RATE_MCS_ANT_A_MSK | RATE_MCS_ANT_B_MSK) -#define RATE_MCS_ANT_ABC_MSK (RATE_MCS_ANT_AB_MSK | RATE_MCS_ANT_C_MSK) -#define RATE_ANT_NUM 3 - -#define POWER_TABLE_NUM_ENTRIES 33 -#define POWER_TABLE_NUM_HT_OFDM_ENTRIES 32 -#define POWER_TABLE_CCK_ENTRY 32 - -/** - * union iwl4965_tx_power_dual_stream - * - * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - * Use __le32 version (struct tx_power_dual_stream) when building command. - * - * Driver provides radio gain and DSP attenuation settings to device in pairs, - * one value for each transmitter chain. The first value is for transmitter A, - * second for transmitter B. - * - * For SISO bit rates, both values in a pair should be identical. - * For MIMO rates, one value may be different from the other, - * in order to balance the Tx output between the two transmitters. - * - * See more details in doc for TXPOWER in iwl-4965-hw.h. - */ -union iwl4965_tx_power_dual_stream { - struct { - u8 radio_tx_gain[2]; - u8 dsp_predis_atten[2]; - } s; - u32 dw; -}; - -/** - * struct tx_power_dual_stream - * - * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - * - * Same format as iwl_tx_power_dual_stream, but __le32 - */ -struct tx_power_dual_stream { - __le32 dw; -} __attribute__ ((packed)); - -/** - * struct iwl4965_tx_power_db - * - * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH - */ -struct iwl4965_tx_power_db { - struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES]; -} __attribute__ ((packed)); - -/** - * Command REPLY_TX_POWER_DBM_CMD = 0x98 - * struct iwl5000_tx_power_dbm_cmd - */ -#define IWL50_TX_POWER_AUTO 0x7f -#define IWL50_TX_POWER_NO_CLOSED (0x1 << 6) - -struct iwl5000_tx_power_dbm_cmd { - s8 global_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ - u8 flags; - s8 srv_chan_lmt; /*in half-dBm (e.g. 30 = 15 dBm) */ - u8 reserved; -} __attribute__ ((packed)); - -/****************************************************************************** - * (0a) - * Alive and Error Commands & Responses: - * - *****************************************************************************/ - -#define UCODE_VALID_OK cpu_to_le32(0x1) -#define INITIALIZE_SUBTYPE (9) - -/* - * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command) - * - * uCode issues this "initialize alive" notification once the initialization - * uCode image has completed its work, and is ready to load the runtime image. - * This is the *first* "alive" notification that the driver will receive after - * rebooting uCode; the "initialize" alive is indicated by subtype field == 9. - * - * See comments documenting "BSM" (bootstrap state machine). - * - * For 4965, this notification contains important calibration data for - * calculating txpower settings: - * - * 1) Power supply voltage indication. The voltage sensor outputs higher - * values for lower voltage, and vice verse. - * - * 2) Temperature measurement parameters, for each of two channel widths - * (20 MHz and 40 MHz) supported by the radios. Temperature sensing - * is done via one of the receiver chains, and channel width influences - * the results. - * - * 3) Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation, - * for each of 5 frequency ranges. - */ -struct iwl_init_alive_resp { - u8 ucode_minor; - u8 ucode_major; - __le16 reserved1; - u8 sw_rev[8]; - u8 ver_type; - u8 ver_subtype; /* "9" for initialize alive */ - __le16 reserved2; - __le32 log_event_table_ptr; - __le32 error_event_table_ptr; - __le32 timestamp; - __le32 is_valid; - - /* calibration values from "initialize" uCode */ - __le32 voltage; /* signed, higher value is lower voltage */ - __le32 therm_r1[2]; /* signed, 1st for normal, 2nd for HT40 */ - __le32 therm_r2[2]; /* signed */ - __le32 therm_r3[2]; /* signed */ - __le32 therm_r4[2]; /* signed */ - __le32 tx_atten[5][2]; /* signed MIMO gain comp, 5 freq groups, - * 2 Tx chains */ -} __attribute__ ((packed)); - - -/** - * REPLY_ALIVE = 0x1 (response only, not a command) - * - * uCode issues this "alive" notification once the runtime image is ready - * to receive commands from the driver. This is the *second* "alive" - * notification that the driver will receive after rebooting uCode; - * this "alive" is indicated by subtype field != 9. - * - * See comments documenting "BSM" (bootstrap state machine). - * - * This response includes two pointers to structures within the device's - * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging: - * - * 1) log_event_table_ptr indicates base of the event log. This traces - * a 256-entry history of uCode execution within a circular buffer. - * Its header format is: - * - * __le32 log_size; log capacity (in number of entries) - * __le32 type; (1) timestamp with each entry, (0) no timestamp - * __le32 wraps; # times uCode has wrapped to top of circular buffer - * __le32 write_index; next circular buffer entry that uCode would fill - * - * The header is followed by the circular buffer of log entries. Entries - * with timestamps have the following format: - * - * __le32 event_id; range 0 - 1500 - * __le32 timestamp; low 32 bits of TSF (of network, if associated) - * __le32 data; event_id-specific data value - * - * Entries without timestamps contain only event_id and data. - * - * 2) error_event_table_ptr indicates base of the error log. This contains - * information about any uCode error that occurs. For 4965, the format - * of the error log is: - * - * __le32 valid; (nonzero) valid, (0) log is empty - * __le32 error_id; type of error - * __le32 pc; program counter - * __le32 blink1; branch link - * __le32 blink2; branch link - * __le32 ilink1; interrupt link - * __le32 ilink2; interrupt link - * __le32 data1; error-specific data - * __le32 data2; error-specific data - * __le32 line; source code line of error - * __le32 bcon_time; beacon timer - * __le32 tsf_low; network timestamp function timer - * __le32 tsf_hi; network timestamp function timer - * - * The Linux driver can print both logs to the system log when a uCode error - * occurs. - */ -struct iwl_alive_resp { - u8 ucode_minor; - u8 ucode_major; - __le16 reserved1; - u8 sw_rev[8]; - u8 ver_type; - u8 ver_subtype; /* not "9" for runtime alive */ - __le16 reserved2; - __le32 log_event_table_ptr; /* SRAM address for event log */ - __le32 error_event_table_ptr; /* SRAM address for error log */ - __le32 timestamp; - __le32 is_valid; -} __attribute__ ((packed)); - -/* - * REPLY_ERROR = 0x2 (response only, not a command) - */ -struct iwl_error_resp { - __le32 error_type; - u8 cmd_id; - u8 reserved1; - __le16 bad_cmd_seq_num; - __le32 error_info; - __le64 timestamp; -} __attribute__ ((packed)); - -/****************************************************************************** - * (1) - * RXON Commands & Responses: - * - *****************************************************************************/ - -/* - * Rx config defines & structure - */ -/* rx_config device types */ -enum { - RXON_DEV_TYPE_AP = 1, - RXON_DEV_TYPE_ESS = 3, - RXON_DEV_TYPE_IBSS = 4, - RXON_DEV_TYPE_SNIFFER = 6, -}; - - -#define RXON_RX_CHAIN_DRIVER_FORCE_MSK cpu_to_le16(0x1 << 0) -#define RXON_RX_CHAIN_DRIVER_FORCE_POS (0) -#define RXON_RX_CHAIN_VALID_MSK cpu_to_le16(0x7 << 1) -#define RXON_RX_CHAIN_VALID_POS (1) -#define RXON_RX_CHAIN_FORCE_SEL_MSK cpu_to_le16(0x7 << 4) -#define RXON_RX_CHAIN_FORCE_SEL_POS (4) -#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK cpu_to_le16(0x7 << 7) -#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS (7) -#define RXON_RX_CHAIN_CNT_MSK cpu_to_le16(0x3 << 10) -#define RXON_RX_CHAIN_CNT_POS (10) -#define RXON_RX_CHAIN_MIMO_CNT_MSK cpu_to_le16(0x3 << 12) -#define RXON_RX_CHAIN_MIMO_CNT_POS (12) -#define RXON_RX_CHAIN_MIMO_FORCE_MSK cpu_to_le16(0x1 << 14) -#define RXON_RX_CHAIN_MIMO_FORCE_POS (14) - -/* rx_config flags */ -/* band & modulation selection */ -#define RXON_FLG_BAND_24G_MSK cpu_to_le32(1 << 0) -#define RXON_FLG_CCK_MSK cpu_to_le32(1 << 1) -/* auto detection enable */ -#define RXON_FLG_AUTO_DETECT_MSK cpu_to_le32(1 << 2) -/* TGg protection when tx */ -#define RXON_FLG_TGG_PROTECT_MSK cpu_to_le32(1 << 3) -/* cck short slot & preamble */ -#define RXON_FLG_SHORT_SLOT_MSK cpu_to_le32(1 << 4) -#define RXON_FLG_SHORT_PREAMBLE_MSK cpu_to_le32(1 << 5) -/* antenna selection */ -#define RXON_FLG_DIS_DIV_MSK cpu_to_le32(1 << 7) -#define RXON_FLG_ANT_SEL_MSK cpu_to_le32(0x0f00) -#define RXON_FLG_ANT_A_MSK cpu_to_le32(1 << 8) -#define RXON_FLG_ANT_B_MSK cpu_to_le32(1 << 9) -/* radar detection enable */ -#define RXON_FLG_RADAR_DETECT_MSK cpu_to_le32(1 << 12) -#define RXON_FLG_TGJ_NARROW_BAND_MSK cpu_to_le32(1 << 13) -/* rx response to host with 8-byte TSF -* (according to ON_AIR deassertion) */ -#define RXON_FLG_TSF2HOST_MSK cpu_to_le32(1 << 15) - - -/* HT flags */ -#define RXON_FLG_CTRL_CHANNEL_LOC_POS (22) -#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK cpu_to_le32(0x1 << 22) - -#define RXON_FLG_HT_OPERATING_MODE_POS (23) - -#define RXON_FLG_HT_PROT_MSK cpu_to_le32(0x1 << 23) -#define RXON_FLG_HT40_PROT_MSK cpu_to_le32(0x2 << 23) - -#define RXON_FLG_CHANNEL_MODE_POS (25) -#define RXON_FLG_CHANNEL_MODE_MSK cpu_to_le32(0x3 << 25) - -/* channel mode */ -enum { - CHANNEL_MODE_LEGACY = 0, - CHANNEL_MODE_PURE_40 = 1, - CHANNEL_MODE_MIXED = 2, - CHANNEL_MODE_RESERVED = 3, -}; -#define RXON_FLG_CHANNEL_MODE_LEGACY cpu_to_le32(CHANNEL_MODE_LEGACY << RXON_FLG_CHANNEL_MODE_POS) -#define RXON_FLG_CHANNEL_MODE_PURE_40 cpu_to_le32(CHANNEL_MODE_PURE_40 << RXON_FLG_CHANNEL_MODE_POS) -#define RXON_FLG_CHANNEL_MODE_MIXED cpu_to_le32(CHANNEL_MODE_MIXED << RXON_FLG_CHANNEL_MODE_POS) - -/* CTS to self (if spec allows) flag */ -#define RXON_FLG_SELF_CTS_EN cpu_to_le32(0x1<<30) - -/* rx_config filter flags */ -/* accept all data frames */ -#define RXON_FILTER_PROMISC_MSK cpu_to_le32(1 << 0) -/* pass control & management to host */ -#define RXON_FILTER_CTL2HOST_MSK cpu_to_le32(1 << 1) -/* accept multi-cast */ -#define RXON_FILTER_ACCEPT_GRP_MSK cpu_to_le32(1 << 2) -/* don't decrypt uni-cast frames */ -#define RXON_FILTER_DIS_DECRYPT_MSK cpu_to_le32(1 << 3) -/* don't decrypt multi-cast frames */ -#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4) -/* STA is associated */ -#define RXON_FILTER_ASSOC_MSK cpu_to_le32(1 << 5) -/* transfer to host non bssid beacons in associated state */ -#define RXON_FILTER_BCON_AWARE_MSK cpu_to_le32(1 << 6) - -/** - * REPLY_RXON = 0x10 (command, has simple generic response) - * - * RXON tunes the radio tuner to a service channel, and sets up a number - * of parameters that are used primarily for Rx, but also for Tx operations. - * - * NOTE: When tuning to a new channel, driver must set the - * RXON_FILTER_ASSOC_MSK to 0. This will clear station-dependent - * info within the device, including the station tables, tx retry - * rate tables, and txpower tables. Driver must build a new station - * table and txpower table before transmitting anything on the RXON - * channel. - * - * NOTE: All RXONs wipe clean the internal txpower table. Driver must - * issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10), - * regardless of whether RXON_FILTER_ASSOC_MSK is set. - */ - -struct iwl3945_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; - u8 bssid_addr[6]; - __le16 reserved2; - u8 wlap_bssid_addr[6]; - __le16 reserved3; - u8 dev_type; - u8 air_propagation; - __le16 reserved4; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 assoc_id; - __le32 flags; - __le32 filter_flags; - __le16 channel; - __le16 reserved5; -} __attribute__ ((packed)); - -struct iwl4965_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; - u8 bssid_addr[6]; - __le16 reserved2; - u8 wlap_bssid_addr[6]; - __le16 reserved3; - u8 dev_type; - u8 air_propagation; - __le16 rx_chain; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 assoc_id; - __le32 flags; - __le32 filter_flags; - __le16 channel; - u8 ofdm_ht_single_stream_basic_rates; - u8 ofdm_ht_dual_stream_basic_rates; -} __attribute__ ((packed)); - -/* 5000 HW just extend this command */ -struct iwl_rxon_cmd { - u8 node_addr[6]; - __le16 reserved1; - u8 bssid_addr[6]; - __le16 reserved2; - u8 wlap_bssid_addr[6]; - __le16 reserved3; - u8 dev_type; - u8 air_propagation; - __le16 rx_chain; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 assoc_id; - __le32 flags; - __le32 filter_flags; - __le16 channel; - u8 ofdm_ht_single_stream_basic_rates; - u8 ofdm_ht_dual_stream_basic_rates; - u8 ofdm_ht_triple_stream_basic_rates; - u8 reserved5; - __le16 acquisition_data; - __le16 reserved6; -} __attribute__ ((packed)); - -/* - * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response) - */ -struct iwl3945_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 reserved; -} __attribute__ ((packed)); - -struct iwl4965_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - u8 ofdm_ht_single_stream_basic_rates; - u8 ofdm_ht_dual_stream_basic_rates; - __le16 rx_chain_select_flags; - __le16 reserved; -} __attribute__ ((packed)); - -struct iwl5000_rxon_assoc_cmd { - __le32 flags; - __le32 filter_flags; - u8 ofdm_basic_rates; - u8 cck_basic_rates; - __le16 reserved1; - u8 ofdm_ht_single_stream_basic_rates; - u8 ofdm_ht_dual_stream_basic_rates; - u8 ofdm_ht_triple_stream_basic_rates; - u8 reserved2; - __le16 rx_chain_select_flags; - __le16 acquisition_data; - __le32 reserved3; -} __attribute__ ((packed)); - -#define IWL_CONN_MAX_LISTEN_INTERVAL 10 -#define IWL_MAX_UCODE_BEACON_INTERVAL 4 /* 4096 */ -#define IWL39_MAX_UCODE_BEACON_INTERVAL 1 /* 1024 */ - -/* - * REPLY_RXON_TIMING = 0x14 (command, has simple generic response) - */ -struct iwl_rxon_time_cmd { - __le64 timestamp; - __le16 beacon_interval; - __le16 atim_window; - __le32 beacon_init_val; - __le16 listen_interval; - __le16 reserved; -} __attribute__ ((packed)); - -/* - * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response) - */ -struct iwl3945_channel_switch_cmd { - u8 band; - u8 expect_beacon; - __le16 channel; - __le32 rxon_flags; - __le32 rxon_filter_flags; - __le32 switch_time; - struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __attribute__ ((packed)); - -struct iwl_channel_switch_cmd { - u8 band; - u8 expect_beacon; - __le16 channel; - __le32 rxon_flags; - __le32 rxon_filter_flags; - __le32 switch_time; - struct iwl4965_tx_power_db tx_power; -} __attribute__ ((packed)); - -/* - * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command) - */ -struct iwl_csa_notification { - __le16 band; - __le16 channel; - __le32 status; /* 0 - OK, 1 - fail */ -} __attribute__ ((packed)); - -/****************************************************************************** - * (2) - * Quality-of-Service (QOS) Commands & Responses: - * - *****************************************************************************/ - -/** - * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM - * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd - * - * @cw_min: Contention window, start value in numbers of slots. - * Should be a power-of-2, minus 1. Device's default is 0x0f. - * @cw_max: Contention window, max value in numbers of slots. - * Should be a power-of-2, minus 1. Device's default is 0x3f. - * @aifsn: Number of slots in Arbitration Interframe Space (before - * performing random backoff timing prior to Tx). Device default 1. - * @edca_txop: Length of Tx opportunity, in uSecs. Device default is 0. - * - * Device will automatically increase contention window by (2*CW) + 1 for each - * transmission retry. Device uses cw_max as a bit mask, ANDed with new CW - * value, to cap the CW value. - */ -struct iwl_ac_qos { - __le16 cw_min; - __le16 cw_max; - u8 aifsn; - u8 reserved1; - __le16 edca_txop; -} __attribute__ ((packed)); - -/* QoS flags defines */ -#define QOS_PARAM_FLG_UPDATE_EDCA_MSK cpu_to_le32(0x01) -#define QOS_PARAM_FLG_TGN_MSK cpu_to_le32(0x02) -#define QOS_PARAM_FLG_TXOP_TYPE_MSK cpu_to_le32(0x10) - -/* Number of Access Categories (AC) (EDCA), queues 0..3 */ -#define AC_NUM 4 - -/* - * REPLY_QOS_PARAM = 0x13 (command, has simple generic response) - * - * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs - * 0: Background, 1: Best Effort, 2: Video, 3: Voice. - */ -struct iwl_qosparam_cmd { - __le32 qos_flags; - struct iwl_ac_qos ac[AC_NUM]; -} __attribute__ ((packed)); - -/****************************************************************************** - * (3) - * Add/Modify Stations Commands & Responses: - * - *****************************************************************************/ -/* - * Multi station support - */ - -/* Special, dedicated locations within device's station table */ -#define IWL_AP_ID 0 -#define IWL_MULTICAST_ID 1 -#define IWL_STA_ID 2 -#define IWL3945_BROADCAST_ID 24 -#define IWL3945_STATION_COUNT 25 -#define IWL4965_BROADCAST_ID 31 -#define IWL4965_STATION_COUNT 32 -#define IWL5000_BROADCAST_ID 15 -#define IWL5000_STATION_COUNT 16 - -#define IWL_STATION_COUNT 32 /* MAX(3945,4965)*/ -#define IWL_INVALID_STATION 255 - -#define STA_FLG_TX_RATE_MSK cpu_to_le32(1 << 2); -#define STA_FLG_PWR_SAVE_MSK cpu_to_le32(1 << 8); -#define STA_FLG_RTS_MIMO_PROT_MSK cpu_to_le32(1 << 17) -#define STA_FLG_AGG_MPDU_8US_MSK cpu_to_le32(1 << 18) -#define STA_FLG_MAX_AGG_SIZE_POS (19) -#define STA_FLG_MAX_AGG_SIZE_MSK cpu_to_le32(3 << 19) -#define STA_FLG_HT40_EN_MSK cpu_to_le32(1 << 21) -#define STA_FLG_MIMO_DIS_MSK cpu_to_le32(1 << 22) -#define STA_FLG_AGG_MPDU_DENSITY_POS (23) -#define STA_FLG_AGG_MPDU_DENSITY_MSK cpu_to_le32(7 << 23) - -/* Use in mode field. 1: modify existing entry, 0: add new station entry */ -#define STA_CONTROL_MODIFY_MSK 0x01 - -/* key flags __le16*/ -#define STA_KEY_FLG_ENCRYPT_MSK cpu_to_le16(0x0007) -#define STA_KEY_FLG_NO_ENC cpu_to_le16(0x0000) -#define STA_KEY_FLG_WEP cpu_to_le16(0x0001) -#define STA_KEY_FLG_CCMP cpu_to_le16(0x0002) -#define STA_KEY_FLG_TKIP cpu_to_le16(0x0003) - -#define STA_KEY_FLG_KEYID_POS 8 -#define STA_KEY_FLG_INVALID cpu_to_le16(0x0800) -/* wep key is either from global key (0) or from station info array (1) */ -#define STA_KEY_FLG_MAP_KEY_MSK cpu_to_le16(0x0008) - -/* wep key in STA: 5-bytes (0) or 13-bytes (1) */ -#define STA_KEY_FLG_KEY_SIZE_MSK cpu_to_le16(0x1000) -#define STA_KEY_MULTICAST_MSK cpu_to_le16(0x4000) -#define STA_KEY_MAX_NUM 8 - -/* Flags indicate whether to modify vs. don't change various station params */ -#define STA_MODIFY_KEY_MASK 0x01 -#define STA_MODIFY_TID_DISABLE_TX 0x02 -#define STA_MODIFY_TX_RATE_MSK 0x04 -#define STA_MODIFY_ADDBA_TID_MSK 0x08 -#define STA_MODIFY_DELBA_TID_MSK 0x10 - -/* Receiver address (actually, Rx station's index into station table), - * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */ -#define BUILD_RAxTID(sta_id, tid) (((sta_id) << 4) + (tid)) - -struct iwl4965_keyinfo { - __le16 key_flags; - u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ - u8 reserved1; - __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ - u8 key_offset; - u8 reserved2; - u8 key[16]; /* 16-byte unicast decryption key */ -} __attribute__ ((packed)); - -/* 5000 */ -struct iwl_keyinfo { - __le16 key_flags; - u8 tkip_rx_tsc_byte2; /* TSC[2] for key mix ph1 detection */ - u8 reserved1; - __le16 tkip_rx_ttak[5]; /* 10-byte unicast TKIP TTAK */ - u8 key_offset; - u8 reserved2; - u8 key[16]; /* 16-byte unicast decryption key */ - __le64 tx_secur_seq_cnt; - __le64 hw_tkip_mic_rx_key; - __le64 hw_tkip_mic_tx_key; -} __attribute__ ((packed)); - -/** - * struct sta_id_modify - * @addr[ETH_ALEN]: station's MAC address - * @sta_id: index of station in uCode's station table - * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change - * - * Driver selects unused table index when adding new station, - * or the index to a pre-existing station entry when modifying that station. - * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP). - * - * modify_mask flags select which parameters to modify vs. leave alone. - */ -struct sta_id_modify { - u8 addr[ETH_ALEN]; - __le16 reserved1; - u8 sta_id; - u8 modify_mask; - __le16 reserved2; -} __attribute__ ((packed)); - -/* - * REPLY_ADD_STA = 0x18 (command) - * - * The device contains an internal table of per-station information, - * with info on security keys, aggregation parameters, and Tx rates for - * initial Tx attempt and any retries (4965 uses REPLY_TX_LINK_QUALITY_CMD, - * 3945 uses REPLY_RATE_SCALE to set up rate tables). - * - * REPLY_ADD_STA sets up the table entry for one station, either creating - * a new entry, or modifying a pre-existing one. - * - * NOTE: RXON command (without "associated" bit set) wipes the station table - * clean. Moving into RF_KILL state does this also. Driver must set up - * new station table before transmitting anything on the RXON channel - * (except active scans or active measurements; those commands carry - * their own txpower/rate setup data). - * - * When getting started on a new channel, driver must set up the - * IWL_BROADCAST_ID entry (last entry in the table). For a client - * station in a BSS, once an AP is selected, driver sets up the AP STA - * in the IWL_AP_ID entry (1st entry in the table). BROADCAST and AP - * are all that are needed for a BSS client station. If the device is - * used as AP, or in an IBSS network, driver must set up station table - * entries for all STAs in network, starting with index IWL_STA_ID. - */ - -struct iwl3945_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; - struct sta_id_modify sta; - struct iwl4965_keyinfo key; - __le32 station_flags; /* STA_FLG_* */ - __le32 station_flags_msk; /* STA_FLG_* */ - - /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) - * corresponding to bit (e.g. bit 5 controls TID 5). - * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ - __le16 tid_disable_tx; - - __le16 rate_n_flags; - - /* TID for which to add block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - u8 add_immediate_ba_tid; - - /* TID for which to remove block-ack support. - * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ - u8 remove_immediate_ba_tid; - - /* Starting Sequence Number for added block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - __le16 add_immediate_ba_ssn; -} __attribute__ ((packed)); - -struct iwl4965_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; - struct sta_id_modify sta; - struct iwl4965_keyinfo key; - __le32 station_flags; /* STA_FLG_* */ - __le32 station_flags_msk; /* STA_FLG_* */ - - /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) - * corresponding to bit (e.g. bit 5 controls TID 5). - * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ - __le16 tid_disable_tx; - - __le16 reserved1; - - /* TID for which to add block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - u8 add_immediate_ba_tid; - - /* TID for which to remove block-ack support. - * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ - u8 remove_immediate_ba_tid; - - /* Starting Sequence Number for added block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - __le16 add_immediate_ba_ssn; - - __le32 reserved2; -} __attribute__ ((packed)); - -/* 5000 */ -struct iwl_addsta_cmd { - u8 mode; /* 1: modify existing, 0: add new station */ - u8 reserved[3]; - struct sta_id_modify sta; - struct iwl_keyinfo key; - __le32 station_flags; /* STA_FLG_* */ - __le32 station_flags_msk; /* STA_FLG_* */ - - /* bit field to disable (1) or enable (0) Tx for Traffic ID (TID) - * corresponding to bit (e.g. bit 5 controls TID 5). - * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */ - __le16 tid_disable_tx; - - __le16 rate_n_flags; /* 3945 only */ - - /* TID for which to add block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - u8 add_immediate_ba_tid; - - /* TID for which to remove block-ack support. - * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */ - u8 remove_immediate_ba_tid; - - /* Starting Sequence Number for added block-ack support. - * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */ - __le16 add_immediate_ba_ssn; - - __le32 reserved2; -} __attribute__ ((packed)); - - -#define ADD_STA_SUCCESS_MSK 0x1 -#define ADD_STA_NO_ROOM_IN_TABLE 0x2 -#define ADD_STA_NO_BLOCK_ACK_RESOURCE 0x4 -#define ADD_STA_MODIFY_NON_EXIST_STA 0x8 -/* - * REPLY_ADD_STA = 0x18 (response) - */ -struct iwl_add_sta_resp { - u8 status; /* ADD_STA_* */ -} __attribute__ ((packed)); - -#define REM_STA_SUCCESS_MSK 0x1 -/* - * REPLY_REM_STA = 0x19 (response) - */ -struct iwl_rem_sta_resp { - u8 status; -} __attribute__ ((packed)); - -/* - * REPLY_REM_STA = 0x19 (command) - */ -struct iwl_rem_sta_cmd { - u8 num_sta; /* number of removed stations */ - u8 reserved[3]; - u8 addr[ETH_ALEN]; /* MAC addr of the first station */ - u8 reserved2[2]; -} __attribute__ ((packed)); - -/* - * REPLY_WEP_KEY = 0x20 - */ -struct iwl_wep_key { - u8 key_index; - u8 key_offset; - u8 reserved1[2]; - u8 key_size; - u8 reserved2[3]; - u8 key[16]; -} __attribute__ ((packed)); - -struct iwl_wep_cmd { - u8 num_keys; - u8 global_key_type; - u8 flags; - u8 reserved; - struct iwl_wep_key key[0]; -} __attribute__ ((packed)); - -#define WEP_KEY_WEP_TYPE 1 -#define WEP_KEYS_MAX 4 -#define WEP_INVALID_OFFSET 0xff -#define WEP_KEY_LEN_64 5 -#define WEP_KEY_LEN_128 13 - -/****************************************************************************** - * (4) - * Rx Responses: - * - *****************************************************************************/ - -#define RX_RES_STATUS_NO_CRC32_ERROR cpu_to_le32(1 << 0) -#define RX_RES_STATUS_NO_RXE_OVERFLOW cpu_to_le32(1 << 1) - -#define RX_RES_PHY_FLAGS_BAND_24_MSK cpu_to_le16(1 << 0) -#define RX_RES_PHY_FLAGS_MOD_CCK_MSK cpu_to_le16(1 << 1) -#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK cpu_to_le16(1 << 2) -#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK cpu_to_le16(1 << 3) -#define RX_RES_PHY_FLAGS_ANTENNA_MSK 0xf0 -#define RX_RES_PHY_FLAGS_ANTENNA_POS 4 - -#define RX_RES_STATUS_SEC_TYPE_MSK (0x7 << 8) -#define RX_RES_STATUS_SEC_TYPE_NONE (0x0 << 8) -#define RX_RES_STATUS_SEC_TYPE_WEP (0x1 << 8) -#define RX_RES_STATUS_SEC_TYPE_CCMP (0x2 << 8) -#define RX_RES_STATUS_SEC_TYPE_TKIP (0x3 << 8) -#define RX_RES_STATUS_SEC_TYPE_ERR (0x7 << 8) - -#define RX_RES_STATUS_STATION_FOUND (1<<6) -#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH (1<<7) - -#define RX_RES_STATUS_DECRYPT_TYPE_MSK (0x3 << 11) -#define RX_RES_STATUS_NOT_DECRYPT (0x0 << 11) -#define RX_RES_STATUS_DECRYPT_OK (0x3 << 11) -#define RX_RES_STATUS_BAD_ICV_MIC (0x1 << 11) -#define RX_RES_STATUS_BAD_KEY_TTAK (0x2 << 11) - -#define RX_MPDU_RES_STATUS_ICV_OK (0x20) -#define RX_MPDU_RES_STATUS_MIC_OK (0x40) -#define RX_MPDU_RES_STATUS_TTAK_OK (1 << 7) -#define RX_MPDU_RES_STATUS_DEC_DONE_MSK (0x800) - - -struct iwl3945_rx_frame_stats { - u8 phy_count; - u8 id; - u8 rssi; - u8 agc; - __le16 sig_avg; - __le16 noise_diff; - u8 payload[0]; -} __attribute__ ((packed)); - -struct iwl3945_rx_frame_hdr { - __le16 channel; - __le16 phy_flags; - u8 reserved1; - u8 rate; - __le16 len; - u8 payload[0]; -} __attribute__ ((packed)); - -struct iwl3945_rx_frame_end { - __le32 status; - __le64 timestamp; - __le32 beacon_timestamp; -} __attribute__ ((packed)); - -/* - * REPLY_3945_RX = 0x1b (response only, not a command) - * - * NOTE: DO NOT dereference from casts to this structure - * It is provided only for calculating minimum data set size. - * The actual offsets of the hdr and end are dynamic based on - * stats.phy_count - */ -struct iwl3945_rx_frame { - struct iwl3945_rx_frame_stats stats; - struct iwl3945_rx_frame_hdr hdr; - struct iwl3945_rx_frame_end end; -} __attribute__ ((packed)); - -#define IWL39_RX_FRAME_SIZE (4 + sizeof(struct iwl3945_rx_frame)) - -/* Fixed (non-configurable) rx data from phy */ - -#define IWL49_RX_RES_PHY_CNT 14 -#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET (4) -#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK (0x70) -#define IWL49_AGC_DB_MASK (0x3f80) /* MASK(7,13) */ -#define IWL49_AGC_DB_POS (7) -struct iwl4965_rx_non_cfg_phy { - __le16 ant_selection; /* ant A bit 4, ant B bit 5, ant C bit 6 */ - __le16 agc_info; /* agc code 0:6, agc dB 7:13, reserved 14:15 */ - u8 rssi_info[6]; /* we use even entries, 0/2/4 for A/B/C rssi */ - u8 pad[0]; -} __attribute__ ((packed)); - - -#define IWL50_RX_RES_PHY_CNT 8 -#define IWL50_RX_RES_AGC_IDX 1 -#define IWL50_RX_RES_RSSI_AB_IDX 2 -#define IWL50_RX_RES_RSSI_C_IDX 3 -#define IWL50_OFDM_AGC_MSK 0xfe00 -#define IWL50_OFDM_AGC_BIT_POS 9 -#define IWL50_OFDM_RSSI_A_MSK 0x00ff -#define IWL50_OFDM_RSSI_A_BIT_POS 0 -#define IWL50_OFDM_RSSI_B_MSK 0xff0000 -#define IWL50_OFDM_RSSI_B_BIT_POS 16 -#define IWL50_OFDM_RSSI_C_MSK 0x00ff -#define IWL50_OFDM_RSSI_C_BIT_POS 0 - -struct iwl5000_non_cfg_phy { - __le32 non_cfg_phy[IWL50_RX_RES_PHY_CNT]; /* up to 8 phy entries */ -} __attribute__ ((packed)); - - -/* - * REPLY_RX = 0xc3 (response only, not a command) - * Used only for legacy (non 11n) frames. - */ -struct iwl_rx_phy_res { - u8 non_cfg_phy_cnt; /* non configurable DSP phy data byte count */ - u8 cfg_phy_cnt; /* configurable DSP phy data byte count */ - u8 stat_id; /* configurable DSP phy data set ID */ - u8 reserved1; - __le64 timestamp; /* TSF at on air rise */ - __le32 beacon_time_stamp; /* beacon at on-air rise */ - __le16 phy_flags; /* general phy flags: band, modulation, ... */ - __le16 channel; /* channel number */ - u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */ - __le32 rate_n_flags; /* RATE_MCS_* */ - __le16 byte_count; /* frame's byte-count */ - __le16 reserved3; -} __attribute__ ((packed)); - -struct iwl4965_rx_mpdu_res_start { - __le16 byte_count; - __le16 reserved; -} __attribute__ ((packed)); - - -/****************************************************************************** - * (5) - * Tx Commands & Responses: - * - * Driver must place each REPLY_TX command into one of the prioritized Tx - * queues in host DRAM, shared between driver and device (see comments for - * SCD registers and Tx/Rx Queues). When the device's Tx scheduler and uCode - * are preparing to transmit, the device pulls the Tx command over the PCI - * bus via one of the device's Tx DMA channels, to fill an internal FIFO - * from which data will be transmitted. - * - * uCode handles all timing and protocol related to control frames - * (RTS/CTS/ACK), based on flags in the Tx command. uCode and Tx scheduler - * handle reception of block-acks; uCode updates the host driver via - * REPLY_COMPRESSED_BA (4965). - * - * uCode handles retrying Tx when an ACK is expected but not received. - * This includes trying lower data rates than the one requested in the Tx - * command, as set up by the REPLY_RATE_SCALE (for 3945) or - * REPLY_TX_LINK_QUALITY_CMD (4965). - * - * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD. - * This command must be executed after every RXON command, before Tx can occur. - *****************************************************************************/ - -/* REPLY_TX Tx flags field */ - -/* 1: Use RTS/CTS protocol or CTS-to-self if spec allows it - * before this frame. if CTS-to-self required check - * RXON_FLG_SELF_CTS_EN status. */ -#define TX_CMD_FLG_RTS_CTS_MSK cpu_to_le32(1 << 0) - -/* 1: Use Request-To-Send protocol before this frame. - * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */ -#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1) - -/* 1: Transmit Clear-To-Send to self before this frame. - * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames. - * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK. */ -#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2) - -/* 1: Expect ACK from receiving station - * 0: Don't expect ACK (MAC header's duration field s/b 0) - * Set this for unicast frames, but not broadcast/multicast. */ -#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3) - -/* For 4965: - * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD). - * Tx command's initial_rate_index indicates first rate to try; - * uCode walks through table for additional Tx attempts. - * 0: Use Tx rate/MCS from Tx command's rate_n_flags field. - * This rate will be used for all Tx attempts; it will not be scaled. */ -#define TX_CMD_FLG_STA_RATE_MSK cpu_to_le32(1 << 4) - -/* 1: Expect immediate block-ack. - * Set when Txing a block-ack request frame. Also set TX_CMD_FLG_ACK_MSK. */ -#define TX_CMD_FLG_IMM_BA_RSP_MASK cpu_to_le32(1 << 6) - -/* 1: Frame requires full Tx-Op protection. - * Set this if either RTS or CTS Tx Flag gets set. */ -#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7) - -/* Tx antenna selection field; used only for 3945, reserved (0) for 4965. - * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */ -#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00) -#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8) -#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9) - -/* 1: Ignore Bluetooth priority for this frame. - * 0: Delay Tx until Bluetooth device is done (normal usage). */ -#define TX_CMD_FLG_BT_DIS_MSK cpu_to_le32(1 << 12) - -/* 1: uCode overrides sequence control field in MAC header. - * 0: Driver provides sequence control field in MAC header. - * Set this for management frames, non-QOS data frames, non-unicast frames, - * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */ -#define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13) - -/* 1: This frame is non-last MPDU; more fragments are coming. - * 0: Last fragment, or not using fragmentation. */ -#define TX_CMD_FLG_MORE_FRAG_MSK cpu_to_le32(1 << 14) - -/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame. - * 0: No TSF required in outgoing frame. - * Set this for transmitting beacons and probe responses. */ -#define TX_CMD_FLG_TSF_MSK cpu_to_le32(1 << 16) - -/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword - * alignment of frame's payload data field. - * 0: No pad - * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4 - * field (but not both). Driver must align frame data (i.e. data following - * MAC header) to DWORD boundary. */ -#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(1 << 20) - -/* accelerate aggregation support - * 0 - no CCMP encryption; 1 - CCMP encryption */ -#define TX_CMD_FLG_AGG_CCMP_MSK cpu_to_le32(1 << 22) - -/* HCCA-AP - disable duration overwriting. */ -#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25) - - -/* - * TX command security control - */ -#define TX_CMD_SEC_WEP 0x01 -#define TX_CMD_SEC_CCM 0x02 -#define TX_CMD_SEC_TKIP 0x03 -#define TX_CMD_SEC_MSK 0x03 -#define TX_CMD_SEC_SHIFT 6 -#define TX_CMD_SEC_KEY128 0x08 - -/* - * security overhead sizes - */ -#define WEP_IV_LEN 4 -#define WEP_ICV_LEN 4 -#define CCMP_MIC_LEN 8 -#define TKIP_ICV_LEN 4 - -/* - * REPLY_TX = 0x1c (command) - */ - -struct iwl3945_tx_cmd { - /* - * MPDU byte count: - * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, - * + 8 byte IV for CCM or TKIP (not used for WEP) - * + Data payload - * + 8-byte MIC (not used for CCM/WEP) - * NOTE: Does not include Tx command bytes, post-MAC pad bytes, - * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i - * Range: 14-2342 bytes. - */ - __le16 len; - - /* - * MPDU or MSDU byte count for next frame. - * Used for fragmentation and bursting, but not 11n aggregation. - * Same as "len", but for next frame. Set to 0 if not applicable. - */ - __le16 next_frame_len; - - __le32 tx_flags; /* TX_CMD_FLG_* */ - - u8 rate; - - /* Index of recipient station in uCode's station table */ - u8 sta_id; - u8 tid_tspec; - u8 sec_ctl; - u8 key[16]; - union { - u8 byte[8]; - __le16 word[4]; - __le32 dw[2]; - } tkip_mic; - __le32 next_frame_info; - union { - __le32 life_time; - __le32 attempt; - } stop_time; - u8 supp_rates[2]; - u8 rts_retry_limit; /*byte 50 */ - u8 data_retry_limit; /*byte 51 */ - union { - __le16 pm_frame_timeout; - __le16 attempt_duration; - } timeout; - - /* - * Duration of EDCA burst Tx Opportunity, in 32-usec units. - * Set this if txop time is not specified by HCCA protocol (e.g. by AP). - */ - __le16 driver_txop; - - /* - * MAC header goes here, followed by 2 bytes padding if MAC header - * length is 26 or 30 bytes, followed by payload data - */ - u8 payload[0]; - struct ieee80211_hdr hdr[0]; -} __attribute__ ((packed)); - -/* - * REPLY_TX = 0x1c (response) - */ -struct iwl3945_tx_resp { - u8 failure_rts; - u8 failure_frame; - u8 bt_kill_count; - u8 rate; - __le32 wireless_media_time; - __le32 status; /* TX status */ -} __attribute__ ((packed)); - - -/* - * 4965 uCode updates these Tx attempt count values in host DRAM. - * Used for managing Tx retries when expecting block-acks. - * Driver should set these fields to 0. - */ -struct iwl_dram_scratch { - u8 try_cnt; /* Tx attempts */ - u8 bt_kill_cnt; /* Tx attempts blocked by Bluetooth device */ - __le16 reserved; -} __attribute__ ((packed)); - -struct iwl_tx_cmd { - /* - * MPDU byte count: - * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size, - * + 8 byte IV for CCM or TKIP (not used for WEP) - * + Data payload - * + 8-byte MIC (not used for CCM/WEP) - * NOTE: Does not include Tx command bytes, post-MAC pad bytes, - * MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i - * Range: 14-2342 bytes. - */ - __le16 len; - - /* - * MPDU or MSDU byte count for next frame. - * Used for fragmentation and bursting, but not 11n aggregation. - * Same as "len", but for next frame. Set to 0 if not applicable. - */ - __le16 next_frame_len; - - __le32 tx_flags; /* TX_CMD_FLG_* */ - - /* uCode may modify this field of the Tx command (in host DRAM!). - * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */ - struct iwl_dram_scratch scratch; - - /* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */ - __le32 rate_n_flags; /* RATE_MCS_* */ - - /* Index of destination station in uCode's station table */ - u8 sta_id; - - /* Type of security encryption: CCM or TKIP */ - u8 sec_ctl; /* TX_CMD_SEC_* */ - - /* - * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial - * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set. Normally "0" for - * data frames, this field may be used to selectively reduce initial - * rate (via non-0 value) for special frames (e.g. management), while - * still supporting rate scaling for all frames. - */ - u8 initial_rate_index; - u8 reserved; - u8 key[16]; - __le16 next_frame_flags; - __le16 reserved2; - union { - __le32 life_time; - __le32 attempt; - } stop_time; - - /* Host DRAM physical address pointer to "scratch" in this command. - * Must be dword aligned. "0" in dram_lsb_ptr disables usage. */ - __le32 dram_lsb_ptr; - u8 dram_msb_ptr; - - u8 rts_retry_limit; /*byte 50 */ - u8 data_retry_limit; /*byte 51 */ - u8 tid_tspec; - union { - __le16 pm_frame_timeout; - __le16 attempt_duration; - } timeout; - - /* - * Duration of EDCA burst Tx Opportunity, in 32-usec units. - * Set this if txop time is not specified by HCCA protocol (e.g. by AP). - */ - __le16 driver_txop; - - /* - * MAC header goes here, followed by 2 bytes padding if MAC header - * length is 26 or 30 bytes, followed by payload data - */ - u8 payload[0]; - struct ieee80211_hdr hdr[0]; -} __attribute__ ((packed)); - -/* TX command response is sent after *all* transmission attempts. - * - * NOTES: - * - * TX_STATUS_FAIL_NEXT_FRAG - * - * If the fragment flag in the MAC header for the frame being transmitted - * is set and there is insufficient time to transmit the next frame, the - * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'. - * - * TX_STATUS_FIFO_UNDERRUN - * - * Indicates the host did not provide bytes to the FIFO fast enough while - * a TX was in progress. - * - * TX_STATUS_FAIL_MGMNT_ABORT - * - * This status is only possible if the ABORT ON MGMT RX parameter was - * set to true with the TX command. - * - * If the MSB of the status parameter is set then an abort sequence is - * required. This sequence consists of the host activating the TX Abort - * control line, and then waiting for the TX Abort command response. This - * indicates that a the device is no longer in a transmit state, and that the - * command FIFO has been cleared. The host must then deactivate the TX Abort - * control line. Receiving is still allowed in this case. - */ -enum { - TX_STATUS_SUCCESS = 0x01, - TX_STATUS_DIRECT_DONE = 0x02, - TX_STATUS_FAIL_SHORT_LIMIT = 0x82, - TX_STATUS_FAIL_LONG_LIMIT = 0x83, - TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84, - TX_STATUS_FAIL_MGMNT_ABORT = 0x85, - TX_STATUS_FAIL_NEXT_FRAG = 0x86, - TX_STATUS_FAIL_LIFE_EXPIRE = 0x87, - TX_STATUS_FAIL_DEST_PS = 0x88, - TX_STATUS_FAIL_ABORTED = 0x89, - TX_STATUS_FAIL_BT_RETRY = 0x8a, - TX_STATUS_FAIL_STA_INVALID = 0x8b, - TX_STATUS_FAIL_FRAG_DROPPED = 0x8c, - TX_STATUS_FAIL_TID_DISABLE = 0x8d, - TX_STATUS_FAIL_FRAME_FLUSHED = 0x8e, - TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f, - TX_STATUS_FAIL_TX_LOCKED = 0x90, - TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91, -}; - -#define TX_PACKET_MODE_REGULAR 0x0000 -#define TX_PACKET_MODE_BURST_SEQ 0x0100 -#define TX_PACKET_MODE_BURST_FIRST 0x0200 - -enum { - TX_POWER_PA_NOT_ACTIVE = 0x0, -}; - -enum { - TX_STATUS_MSK = 0x000000ff, /* bits 0:7 */ - TX_STATUS_DELAY_MSK = 0x00000040, - TX_STATUS_ABORT_MSK = 0x00000080, - TX_PACKET_MODE_MSK = 0x0000ff00, /* bits 8:15 */ - TX_FIFO_NUMBER_MSK = 0x00070000, /* bits 16:18 */ - TX_RESERVED = 0x00780000, /* bits 19:22 */ - TX_POWER_PA_DETECT_MSK = 0x7f800000, /* bits 23:30 */ - TX_ABORT_REQUIRED_MSK = 0x80000000, /* bits 31:31 */ -}; - -static inline bool iwl_is_tx_success(u32 status) -{ - status &= TX_STATUS_MSK; - return (status == TX_STATUS_SUCCESS) || - (status == TX_STATUS_DIRECT_DONE); -} - - - -/* ******************************* - * TX aggregation status - ******************************* */ - -enum { - AGG_TX_STATE_TRANSMITTED = 0x00, - AGG_TX_STATE_UNDERRUN_MSK = 0x01, - AGG_TX_STATE_BT_PRIO_MSK = 0x02, - AGG_TX_STATE_FEW_BYTES_MSK = 0x04, - AGG_TX_STATE_ABORT_MSK = 0x08, - AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10, - AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20, - AGG_TX_STATE_LAST_SENT_BT_KILL_MSK = 0x40, - AGG_TX_STATE_SCD_QUERY_MSK = 0x80, - AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100, - AGG_TX_STATE_RESPONSE_MSK = 0x1ff, - AGG_TX_STATE_DUMP_TX_MSK = 0x200, - AGG_TX_STATE_DELAY_TX_MSK = 0x400 -}; - -#define AGG_TX_STATE_LAST_SENT_MSK (AGG_TX_STATE_LAST_SENT_TTL_MSK | \ - AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK | \ - AGG_TX_STATE_LAST_SENT_BT_KILL_MSK) - -/* # tx attempts for first frame in aggregation */ -#define AGG_TX_STATE_TRY_CNT_POS 12 -#define AGG_TX_STATE_TRY_CNT_MSK 0xf000 - -/* Command ID and sequence number of Tx command for this frame */ -#define AGG_TX_STATE_SEQ_NUM_POS 16 -#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000 - -/* - * REPLY_TX = 0x1c (response) - * - * This response may be in one of two slightly different formats, indicated - * by the frame_count field: - * - * 1) No aggregation (frame_count == 1). This reports Tx results for - * a single frame. Multiple attempts, at various bit rates, may have - * been made for this frame. - * - * 2) Aggregation (frame_count > 1). This reports Tx results for - * 2 or more frames that used block-acknowledge. All frames were - * transmitted at same rate. Rate scaling may have been used if first - * frame in this new agg block failed in previous agg block(s). - * - * Note that, for aggregation, ACK (block-ack) status is not delivered here; - * block-ack has not been received by the time the 4965 records this status. - * This status relates to reasons the tx might have been blocked or aborted - * within the sending station (this 4965), rather than whether it was - * received successfully by the destination station. - */ -struct agg_tx_status { - __le16 status; - __le16 sequence; -} __attribute__ ((packed)); - -struct iwl4965_tx_resp { - u8 frame_count; /* 1 no aggregation, >1 aggregation */ - u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ - u8 failure_rts; /* # failures due to unsuccessful RTS */ - u8 failure_frame; /* # failures due to no ACK (unused for agg) */ - - /* For non-agg: Rate at which frame was successful. - * For agg: Rate at which all frames were transmitted. */ - __le32 rate_n_flags; /* RATE_MCS_* */ - - /* For non-agg: RTS + CTS + frame tx attempts time + ACK. - * For agg: RTS + CTS + aggregation tx time + block-ack time. */ - __le16 wireless_media_time; /* uSecs */ - - __le16 reserved; - __le32 pa_power1; /* RF power amplifier measurement (not used) */ - __le32 pa_power2; - - /* - * For non-agg: frame status TX_STATUS_* - * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status - * fields follow this one, up to frame_count. - * Bit fields: - * 11- 0: AGG_TX_STATE_* status code - * 15-12: Retry count for 1st frame in aggregation (retries - * occur if tx failed for this frame when it was a - * member of a previous aggregation block). If rate - * scaling is used, retry count indicates the rate - * table entry used for all frames in the new agg. - * 31-16: Sequence # for this frame's Tx cmd (not SSN!) - */ - union { - __le32 status; - struct agg_tx_status agg_status[0]; /* for each agg frame */ - } u; -} __attribute__ ((packed)); - -/* - * definitions for initial rate index field - * bits [3:0] initial rate index - * bits [6:4] rate table color, used for the initial rate - * bit-7 invalid rate indication - * i.e. rate was not chosen from rate table - * or rate table color was changed during frame retries - * refer tlc rate info - */ - -#define IWL50_TX_RES_INIT_RATE_INDEX_POS 0 -#define IWL50_TX_RES_INIT_RATE_INDEX_MSK 0x0f -#define IWL50_TX_RES_RATE_TABLE_COLOR_POS 4 -#define IWL50_TX_RES_RATE_TABLE_COLOR_MSK 0x70 -#define IWL50_TX_RES_INV_RATE_INDEX_MSK 0x80 - -/* refer to ra_tid */ -#define IWL50_TX_RES_TID_POS 0 -#define IWL50_TX_RES_TID_MSK 0x0f -#define IWL50_TX_RES_RA_POS 4 -#define IWL50_TX_RES_RA_MSK 0xf0 - -struct iwl5000_tx_resp { - u8 frame_count; /* 1 no aggregation, >1 aggregation */ - u8 bt_kill_count; /* # blocked by bluetooth (unused for agg) */ - u8 failure_rts; /* # failures due to unsuccessful RTS */ - u8 failure_frame; /* # failures due to no ACK (unused for agg) */ - - /* For non-agg: Rate at which frame was successful. - * For agg: Rate at which all frames were transmitted. */ - __le32 rate_n_flags; /* RATE_MCS_* */ - - /* For non-agg: RTS + CTS + frame tx attempts time + ACK. - * For agg: RTS + CTS + aggregation tx time + block-ack time. */ - __le16 wireless_media_time; /* uSecs */ - - u8 pa_status; /* RF power amplifier measurement (not used) */ - u8 pa_integ_res_a[3]; - u8 pa_integ_res_b[3]; - u8 pa_integ_res_C[3]; - - __le32 tfd_info; - __le16 seq_ctl; - __le16 byte_cnt; - u8 tlc_info; - u8 ra_tid; /* tid (0:3), sta_id (4:7) */ - __le16 frame_ctrl; - /* - * For non-agg: frame status TX_STATUS_* - * For agg: status of 1st frame, AGG_TX_STATE_*; other frame status - * fields follow this one, up to frame_count. - * Bit fields: - * 11- 0: AGG_TX_STATE_* status code - * 15-12: Retry count for 1st frame in aggregation (retries - * occur if tx failed for this frame when it was a - * member of a previous aggregation block). If rate - * scaling is used, retry count indicates the rate - * table entry used for all frames in the new agg. - * 31-16: Sequence # for this frame's Tx cmd (not SSN!) - */ - struct agg_tx_status status; /* TX status (in aggregation - - * status of 1st frame) */ -} __attribute__ ((packed)); -/* - * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command) - * - * Reports Block-Acknowledge from recipient station - */ -struct iwl_compressed_ba_resp { - __le32 sta_addr_lo32; - __le16 sta_addr_hi16; - __le16 reserved; - - /* Index of recipient (BA-sending) station in uCode's station table */ - u8 sta_id; - u8 tid; - __le16 seq_ctl; - __le64 bitmap; - __le16 scd_flow; - __le16 scd_ssn; -} __attribute__ ((packed)); - -/* - * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response) - * - * See details under "TXPOWER" in iwl-4965-hw.h. - */ - -struct iwl3945_txpowertable_cmd { - u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ - u8 reserved; - __le16 channel; - struct iwl3945_power_per_rate power[IWL_MAX_RATES]; -} __attribute__ ((packed)); - -struct iwl4965_txpowertable_cmd { - u8 band; /* 0: 5 GHz, 1: 2.4 GHz */ - u8 reserved; - __le16 channel; - struct iwl4965_tx_power_db tx_power; -} __attribute__ ((packed)); - - -/** - * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response - * - * REPLY_RATE_SCALE = 0x47 (command, has simple generic response) - * - * NOTE: The table of rates passed to the uCode via the - * RATE_SCALE command sets up the corresponding order of - * rates used for all related commands, including rate - * masks, etc. - * - * For example, if you set 9MB (PLCP 0x0f) as the first - * rate in the rate table, the bit mask for that rate - * when passed through ofdm_basic_rates on the REPLY_RXON - * command would be bit 0 (1 << 0) - */ -struct iwl3945_rate_scaling_info { - __le16 rate_n_flags; - u8 try_cnt; - u8 next_rate_index; -} __attribute__ ((packed)); - -struct iwl3945_rate_scaling_cmd { - u8 table_id; - u8 reserved[3]; - struct iwl3945_rate_scaling_info table[IWL_MAX_RATES]; -} __attribute__ ((packed)); - - -/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */ -#define LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK (1 << 0) - -/* # of EDCA prioritized tx fifos */ -#define LINK_QUAL_AC_NUM AC_NUM - -/* # entries in rate scale table to support Tx retries */ -#define LINK_QUAL_MAX_RETRY_NUM 16 - -/* Tx antenna selection values */ -#define LINK_QUAL_ANT_A_MSK (1 << 0) -#define LINK_QUAL_ANT_B_MSK (1 << 1) -#define LINK_QUAL_ANT_MSK (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK) - - -/** - * struct iwl_link_qual_general_params - * - * Used in REPLY_TX_LINK_QUALITY_CMD - */ -struct iwl_link_qual_general_params { - u8 flags; - - /* No entries at or above this (driver chosen) index contain MIMO */ - u8 mimo_delimiter; - - /* Best single antenna to use for single stream (legacy, SISO). */ - u8 single_stream_ant_msk; /* LINK_QUAL_ANT_* */ - - /* Best antennas to use for MIMO (unused for 4965, assumes both). */ - u8 dual_stream_ant_msk; /* LINK_QUAL_ANT_* */ - - /* - * If driver needs to use different initial rates for different - * EDCA QOS access categories (as implemented by tx fifos 0-3), - * this table will set that up, by indicating the indexes in the - * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start. - * Otherwise, driver should set all entries to 0. - * - * Entry usage: - * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice - * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3. - */ - u8 start_rate_index[LINK_QUAL_AC_NUM]; -} __attribute__ ((packed)); - -#define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000) /* 4 milliseconds */ -#define LINK_QUAL_AGG_TIME_LIMIT_MAX (65535) -#define LINK_QUAL_AGG_TIME_LIMIT_MIN (0) - -#define LINK_QUAL_AGG_DISABLE_START_DEF (3) -#define LINK_QUAL_AGG_DISABLE_START_MAX (255) -#define LINK_QUAL_AGG_DISABLE_START_MIN (0) - -#define LINK_QUAL_AGG_FRAME_LIMIT_DEF (31) -#define LINK_QUAL_AGG_FRAME_LIMIT_MAX (63) -#define LINK_QUAL_AGG_FRAME_LIMIT_MIN (0) - -/** - * struct iwl_link_qual_agg_params - * - * Used in REPLY_TX_LINK_QUALITY_CMD - */ -struct iwl_link_qual_agg_params { - - /* Maximum number of uSec in aggregation. - * Driver should set this to 4000 (4 milliseconds). */ - __le16 agg_time_limit; - - /* - * Number of Tx retries allowed for a frame, before that frame will - * no longer be considered for the start of an aggregation sequence - * (scheduler will then try to tx it as single frame). - * Driver should set this to 3. - */ - u8 agg_dis_start_th; - - /* - * Maximum number of frames in aggregation. - * 0 = no limit (default). 1 = no aggregation. - * Other values = max # frames in aggregation. - */ - u8 agg_frame_cnt_limit; - - __le32 reserved; -} __attribute__ ((packed)); - -/* - * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response) - * - * For 4965 only; 3945 uses REPLY_RATE_SCALE. - * - * Each station in the 4965's internal station table has its own table of 16 - * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when - * an ACK is not received. This command replaces the entire table for - * one station. - * - * NOTE: Station must already be in 4965's station table. Use REPLY_ADD_STA. - * - * The rate scaling procedures described below work well. Of course, other - * procedures are possible, and may work better for particular environments. - * - * - * FILLING THE RATE TABLE - * - * Given a particular initial rate and mode, as determined by the rate - * scaling algorithm described below, the Linux driver uses the following - * formula to fill the rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table in the - * Link Quality command: - * - * - * 1) If using High-throughput (HT) (SISO or MIMO) initial rate: - * a) Use this same initial rate for first 3 entries. - * b) Find next lower available rate using same mode (SISO or MIMO), - * use for next 3 entries. If no lower rate available, switch to - * legacy mode (no HT40 channel, no MIMO, no short guard interval). - * c) If using MIMO, set command's mimo_delimiter to number of entries - * using MIMO (3 or 6). - * d) After trying 2 HT rates, switch to legacy mode (no HT40 channel, - * no MIMO, no short guard interval), at the next lower bit rate - * (e.g. if second HT bit rate was 54, try 48 legacy), and follow - * legacy procedure for remaining table entries. - * - * 2) If using legacy initial rate: - * a) Use the initial rate for only one entry. - * b) For each following entry, reduce the rate to next lower available - * rate, until reaching the lowest available rate. - * c) When reducing rate, also switch antenna selection. - * d) Once lowest available rate is reached, repeat this rate until - * rate table is filled (16 entries), switching antenna each entry. - * - * - * ACCUMULATING HISTORY - * - * The rate scaling algorithm for 4965, as implemented in Linux driver, uses - * two sets of frame Tx success history: One for the current/active modulation - * mode, and one for a speculative/search mode that is being attempted. If the - * speculative mode turns out to be more effective (i.e. actual transfer - * rate is better), then the driver continues to use the speculative mode - * as the new current active mode. - * - * Each history set contains, separately for each possible rate, data for a - * sliding window of the 62 most recent tx attempts at that rate. The data - * includes a shifting bitmap of success(1)/failure(0), and sums of successful - * and attempted frames, from which the driver can additionally calculate a - * success ratio (success / attempted) and number of failures - * (attempted - success), and control the size of the window (attempted). - * The driver uses the bit map to remove successes from the success sum, as - * the oldest tx attempts fall out of the window. - * - * When the 4965 makes multiple tx attempts for a given frame, each attempt - * might be at a different rate, and have different modulation characteristics - * (e.g. antenna, fat channel, short guard interval), as set up in the rate - * scaling table in the Link Quality command. The driver must determine - * which rate table entry was used for each tx attempt, to determine which - * rate-specific history to update, and record only those attempts that - * match the modulation characteristics of the history set. - * - * When using block-ack (aggregation), all frames are transmitted at the same - * rate, since there is no per-attempt acknowledgment from the destination - * station. The Tx response struct iwl_tx_resp indicates the Tx rate in - * rate_n_flags field. After receiving a block-ack, the driver can update - * history for the entire block all at once. - * - * - * FINDING BEST STARTING RATE: - * - * When working with a selected initial modulation mode (see below), the - * driver attempts to find a best initial rate. The initial rate is the - * first entry in the Link Quality command's rate table. - * - * 1) Calculate actual throughput (success ratio * expected throughput, see - * table below) for current initial rate. Do this only if enough frames - * have been attempted to make the value meaningful: at least 6 failed - * tx attempts, or at least 8 successes. If not enough, don't try rate - * scaling yet. - * - * 2) Find available rates adjacent to current initial rate. Available means: - * a) supported by hardware && - * b) supported by association && - * c) within any constraints selected by user - * - * 3) Gather measured throughputs for adjacent rates. These might not have - * enough history to calculate a throughput. That's okay, we might try - * using one of them anyway! - * - * 4) Try decreasing rate if, for current rate: - * a) success ratio is < 15% || - * b) lower adjacent rate has better measured throughput || - * c) higher adjacent rate has worse throughput, and lower is unmeasured - * - * As a sanity check, if decrease was determined above, leave rate - * unchanged if: - * a) lower rate unavailable - * b) success ratio at current rate > 85% (very good) - * c) current measured throughput is better than expected throughput - * of lower rate (under perfect 100% tx conditions, see table below) - * - * 5) Try increasing rate if, for current rate: - * a) success ratio is < 15% || - * b) both adjacent rates' throughputs are unmeasured (try it!) || - * b) higher adjacent rate has better measured throughput || - * c) lower adjacent rate has worse throughput, and higher is unmeasured - * - * As a sanity check, if increase was determined above, leave rate - * unchanged if: - * a) success ratio at current rate < 70%. This is not particularly - * good performance; higher rate is sure to have poorer success. - * - * 6) Re-evaluate the rate after each tx frame. If working with block- - * acknowledge, history and statistics may be calculated for the entire - * block (including prior history that fits within the history windows), - * before re-evaluation. - * - * FINDING BEST STARTING MODULATION MODE: - * - * After working with a modulation mode for a "while" (and doing rate scaling), - * the driver searches for a new initial mode in an attempt to improve - * throughput. The "while" is measured by numbers of attempted frames: - * - * For legacy mode, search for new mode after: - * 480 successful frames, or 160 failed frames - * For high-throughput modes (SISO or MIMO), search for new mode after: - * 4500 successful frames, or 400 failed frames - * - * Mode switch possibilities are (3 for each mode): - * - * For legacy: - * Change antenna, try SISO (if HT association), try MIMO (if HT association) - * For SISO: - * Change antenna, try MIMO, try shortened guard interval (SGI) - * For MIMO: - * Try SISO antenna A, SISO antenna B, try shortened guard interval (SGI) - * - * When trying a new mode, use the same bit rate as the old/current mode when - * trying antenna switches and shortened guard interval. When switching to - * SISO from MIMO or legacy, or to MIMO from SISO or legacy, use a rate - * for which the expected throughput (under perfect conditions) is about the - * same or slightly better than the actual measured throughput delivered by - * the old/current mode. - * - * Actual throughput can be estimated by multiplying the expected throughput - * by the success ratio (successful / attempted tx frames). Frame size is - * not considered in this calculation; it assumes that frame size will average - * out to be fairly consistent over several samples. The following are - * metric values for expected throughput assuming 100% success ratio. - * Only G band has support for CCK rates: - * - * RATE: 1 2 5 11 6 9 12 18 24 36 48 54 60 - * - * G: 7 13 35 58 40 57 72 98 121 154 177 186 186 - * A: 0 0 0 0 40 57 72 98 121 154 177 186 186 - * SISO 20MHz: 0 0 0 0 42 42 76 102 124 159 183 193 202 - * SGI SISO 20MHz: 0 0 0 0 46 46 82 110 132 168 192 202 211 - * MIMO 20MHz: 0 0 0 0 74 74 123 155 179 214 236 244 251 - * SGI MIMO 20MHz: 0 0 0 0 81 81 131 164 188 222 243 251 257 - * SISO 40MHz: 0 0 0 0 77 77 127 160 184 220 242 250 257 - * SGI SISO 40MHz: 0 0 0 0 83 83 135 169 193 229 250 257 264 - * MIMO 40MHz: 0 0 0 0 123 123 182 214 235 264 279 285 289 - * SGI MIMO 40MHz: 0 0 0 0 131 131 191 222 242 270 284 289 293 - * - * After the new mode has been tried for a short while (minimum of 6 failed - * frames or 8 successful frames), compare success ratio and actual throughput - * estimate of the new mode with the old. If either is better with the new - * mode, continue to use the new mode. - * - * Continue comparing modes until all 3 possibilities have been tried. - * If moving from legacy to HT, try all 3 possibilities from the new HT - * mode. After trying all 3, a best mode is found. Continue to use this mode - * for the longer "while" described above (e.g. 480 successful frames for - * legacy), and then repeat the search process. - * - */ -struct iwl_link_quality_cmd { - - /* Index of destination/recipient station in uCode's station table */ - u8 sta_id; - u8 reserved1; - __le16 control; /* not used */ - struct iwl_link_qual_general_params general_params; - struct iwl_link_qual_agg_params agg_params; - - /* - * Rate info; when using rate-scaling, Tx command's initial_rate_index - * specifies 1st Tx rate attempted, via index into this table. - * 4965 works its way through table when retrying Tx. - */ - struct { - __le32 rate_n_flags; /* RATE_MCS_*, IWL_RATE_* */ - } rs_table[LINK_QUAL_MAX_RETRY_NUM]; - __le32 reserved2; -} __attribute__ ((packed)); - -/* - * REPLY_BT_CONFIG = 0x9b (command, has simple generic response) - * - * 3945 and 4965 support hardware handshake with Bluetooth device on - * same platform. Bluetooth device alerts wireless device when it will Tx; - * wireless device can delay or kill its own Tx to accommodate. - */ -struct iwl_bt_cmd { - u8 flags; - u8 lead_time; - u8 max_kill; - u8 reserved; - __le32 kill_ack_mask; - __le32 kill_cts_mask; -} __attribute__ ((packed)); - -/****************************************************************************** - * (6) - * Spectrum Management (802.11h) Commands, Responses, Notifications: - * - *****************************************************************************/ - -/* - * Spectrum Management - */ -#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK | \ - RXON_FILTER_CTL2HOST_MSK | \ - RXON_FILTER_ACCEPT_GRP_MSK | \ - RXON_FILTER_DIS_DECRYPT_MSK | \ - RXON_FILTER_DIS_GRP_DECRYPT_MSK | \ - RXON_FILTER_ASSOC_MSK | \ - RXON_FILTER_BCON_AWARE_MSK) - -struct iwl_measure_channel { - __le32 duration; /* measurement duration in extended beacon - * format */ - u8 channel; /* channel to measure */ - u8 type; /* see enum iwl_measure_type */ - __le16 reserved; -} __attribute__ ((packed)); - -/* - * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command) - */ -struct iwl_spectrum_cmd { - __le16 len; /* number of bytes starting from token */ - u8 token; /* token id */ - u8 id; /* measurement id -- 0 or 1 */ - u8 origin; /* 0 = TGh, 1 = other, 2 = TGk */ - u8 periodic; /* 1 = periodic */ - __le16 path_loss_timeout; - __le32 start_time; /* start time in extended beacon format */ - __le32 reserved2; - __le32 flags; /* rxon flags */ - __le32 filter_flags; /* rxon filter flags */ - __le16 channel_count; /* minimum 1, maximum 10 */ - __le16 reserved3; - struct iwl_measure_channel channels[10]; -} __attribute__ ((packed)); - -/* - * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response) - */ -struct iwl_spectrum_resp { - u8 token; - u8 id; /* id of the prior command replaced, or 0xff */ - __le16 status; /* 0 - command will be handled - * 1 - cannot handle (conflicts with another - * measurement) */ -} __attribute__ ((packed)); - -enum iwl_measurement_state { - IWL_MEASUREMENT_START = 0, - IWL_MEASUREMENT_STOP = 1, -}; - -enum iwl_measurement_status { - IWL_MEASUREMENT_OK = 0, - IWL_MEASUREMENT_CONCURRENT = 1, - IWL_MEASUREMENT_CSA_CONFLICT = 2, - IWL_MEASUREMENT_TGH_CONFLICT = 3, - /* 4-5 reserved */ - IWL_MEASUREMENT_STOPPED = 6, - IWL_MEASUREMENT_TIMEOUT = 7, - IWL_MEASUREMENT_PERIODIC_FAILED = 8, -}; - -#define NUM_ELEMENTS_IN_HISTOGRAM 8 - -struct iwl_measurement_histogram { - __le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 0.8usec counts */ - __le32 cck[NUM_ELEMENTS_IN_HISTOGRAM]; /* in 1usec counts */ -} __attribute__ ((packed)); - -/* clear channel availability counters */ -struct iwl_measurement_cca_counters { - __le32 ofdm; - __le32 cck; -} __attribute__ ((packed)); - -enum iwl_measure_type { - IWL_MEASURE_BASIC = (1 << 0), - IWL_MEASURE_CHANNEL_LOAD = (1 << 1), - IWL_MEASURE_HISTOGRAM_RPI = (1 << 2), - IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3), - IWL_MEASURE_FRAME = (1 << 4), - /* bits 5:6 are reserved */ - IWL_MEASURE_IDLE = (1 << 7), -}; - -/* - * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command) - */ -struct iwl_spectrum_notification { - u8 id; /* measurement id -- 0 or 1 */ - u8 token; - u8 channel_index; /* index in measurement channel list */ - u8 state; /* 0 - start, 1 - stop */ - __le32 start_time; /* lower 32-bits of TSF */ - u8 band; /* 0 - 5.2GHz, 1 - 2.4GHz */ - u8 channel; - u8 type; /* see enum iwl_measurement_type */ - u8 reserved1; - /* NOTE: cca_ofdm, cca_cck, basic_type, and histogram are only only - * valid if applicable for measurement type requested. */ - __le32 cca_ofdm; /* cca fraction time in 40Mhz clock periods */ - __le32 cca_cck; /* cca fraction time in 44Mhz clock periods */ - __le32 cca_time; /* channel load time in usecs */ - u8 basic_type; /* 0 - bss, 1 - ofdm preamble, 2 - - * unidentified */ - u8 reserved2[3]; - struct iwl_measurement_histogram histogram; - __le32 stop_time; /* lower 32-bits of TSF */ - __le32 status; /* see iwl_measurement_status */ -} __attribute__ ((packed)); - -/****************************************************************************** - * (7) - * Power Management Commands, Responses, Notifications: - * - *****************************************************************************/ - -/** - * struct iwl_powertable_cmd - Power Table Command - * @flags: See below: - * - * POWER_TABLE_CMD = 0x77 (command, has simple generic response) - * - * PM allow: - * bit 0 - '0' Driver not allow power management - * '1' Driver allow PM (use rest of parameters) - * - * uCode send sleep notifications: - * bit 1 - '0' Don't send sleep notification - * '1' send sleep notification (SEND_PM_NOTIFICATION) - * - * Sleep over DTIM - * bit 2 - '0' PM have to walk up every DTIM - * '1' PM could sleep over DTIM till listen Interval. - * - * PCI power managed - * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1) - * '1' !(PCI_CFG_LINK_CTRL & 0x1) - * - * Fast PD - * bit 4 - '1' Put radio to sleep when receiving frame for others - * - * Force sleep Modes - * bit 31/30- '00' use both mac/xtal sleeps - * '01' force Mac sleep - * '10' force xtal sleep - * '11' Illegal set - * - * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then - * ucode assume sleep over DTIM is allowed and we don't need to wake up - * for every DTIM. - */ -#define IWL_POWER_VEC_SIZE 5 - -#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0)) -#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2)) -#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3)) -#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4)) - -struct iwl3945_powertable_cmd { - __le16 flags; - u8 reserved[2]; - __le32 rx_data_timeout; - __le32 tx_data_timeout; - __le32 sleep_interval[IWL_POWER_VEC_SIZE]; -} __attribute__ ((packed)); - -struct iwl_powertable_cmd { - __le16 flags; - u8 keep_alive_seconds; /* 3945 reserved */ - u8 debug_flags; /* 3945 reserved */ - __le32 rx_data_timeout; - __le32 tx_data_timeout; - __le32 sleep_interval[IWL_POWER_VEC_SIZE]; - __le32 keep_alive_beacons; -} __attribute__ ((packed)); - -/* - * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command) - * 3945 and 4965 identical. - */ -struct iwl_sleep_notification { - u8 pm_sleep_mode; - u8 pm_wakeup_src; - __le16 reserved; - __le32 sleep_time; - __le32 tsf_low; - __le32 bcon_timer; -} __attribute__ ((packed)); - -/* Sleep states. 3945 and 4965 identical. */ -enum { - IWL_PM_NO_SLEEP = 0, - IWL_PM_SLP_MAC = 1, - IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2, - IWL_PM_SLP_FULL_MAC_CARD_STATE = 3, - IWL_PM_SLP_PHY = 4, - IWL_PM_SLP_REPENT = 5, - IWL_PM_WAKEUP_BY_TIMER = 6, - IWL_PM_WAKEUP_BY_DRIVER = 7, - IWL_PM_WAKEUP_BY_RFKILL = 8, - /* 3 reserved */ - IWL_PM_NUM_OF_MODES = 12, -}; - -/* - * REPLY_CARD_STATE_CMD = 0xa0 (command, has simple generic response) - */ -#define CARD_STATE_CMD_DISABLE 0x00 /* Put card to sleep */ -#define CARD_STATE_CMD_ENABLE 0x01 /* Wake up card */ -#define CARD_STATE_CMD_HALT 0x02 /* Power down permanently */ -struct iwl_card_state_cmd { - __le32 status; /* CARD_STATE_CMD_* request new power state */ -} __attribute__ ((packed)); - -/* - * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command) - */ -struct iwl_card_state_notif { - __le32 flags; -} __attribute__ ((packed)); - -#define HW_CARD_DISABLED 0x01 -#define SW_CARD_DISABLED 0x02 -#define RF_CARD_DISABLED 0x04 -#define RXON_CARD_DISABLED 0x10 - -struct iwl_ct_kill_config { - __le32 reserved; - __le32 critical_temperature_M; - __le32 critical_temperature_R; -} __attribute__ ((packed)); - -/* 1000, and 6x00 */ -struct iwl_ct_kill_throttling_config { - __le32 critical_temperature_exit; - __le32 reserved; - __le32 critical_temperature_enter; -} __attribute__ ((packed)); - -/****************************************************************************** - * (8) - * Scan Commands, Responses, Notifications: - * - *****************************************************************************/ - -#define SCAN_CHANNEL_TYPE_PASSIVE cpu_to_le32(0) -#define SCAN_CHANNEL_TYPE_ACTIVE cpu_to_le32(1) - -/** - * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table - * - * One for each channel in the scan list. - * Each channel can independently select: - * 1) SSID for directed active scans - * 2) Txpower setting (for rate specified within Tx command) - * 3) How long to stay on-channel (behavior may be modified by quiet_time, - * quiet_plcp_th, good_CRC_th) - * - * To avoid uCode errors, make sure the following are true (see comments - * under struct iwl_scan_cmd about max_out_time and quiet_time): - * 1) If using passive_dwell (i.e. passive_dwell != 0): - * active_dwell <= passive_dwell (< max_out_time if max_out_time != 0) - * 2) quiet_time <= active_dwell - * 3) If restricting off-channel time (i.e. max_out_time !=0): - * passive_dwell < max_out_time - * active_dwell < max_out_time - */ - -/* FIXME: rename to AP1, remove tpc */ -struct iwl3945_scan_channel { - /* - * type is defined as: - * 0:0 1 = active, 0 = passive - * 1:4 SSID direct bit map; if a bit is set, then corresponding - * SSID IE is transmitted in probe request. - * 5:7 reserved - */ - u8 type; - u8 channel; /* band is selected by iwl3945_scan_cmd "flags" field */ - struct iwl3945_tx_power tpc; - __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ - __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ -} __attribute__ ((packed)); - -/* set number of direct probes u8 type */ -#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1)))) - -struct iwl_scan_channel { - /* - * type is defined as: - * 0:0 1 = active, 0 = passive - * 1:20 SSID direct bit map; if a bit is set, then corresponding - * SSID IE is transmitted in probe request. - * 21:31 reserved - */ - __le32 type; - __le16 channel; /* band is selected by iwl_scan_cmd "flags" field */ - u8 tx_gain; /* gain for analog radio */ - u8 dsp_atten; /* gain for DSP */ - __le16 active_dwell; /* in 1024-uSec TU (time units), typ 5-50 */ - __le16 passive_dwell; /* in 1024-uSec TU (time units), typ 20-500 */ -} __attribute__ ((packed)); - -/* set number of direct probes __le32 type */ -#define IWL_SCAN_PROBE_MASK(n) cpu_to_le32((BIT(n) | (BIT(n) - BIT(1)))) - -/** - * struct iwl_ssid_ie - directed scan network information element - * - * Up to 4 of these may appear in REPLY_SCAN_CMD, selected by "type" field - * in struct iwl_scan_channel; each channel may select different ssids from - * among the 4 entries. SSID IEs get transmitted in reverse order of entry. - */ -struct iwl_ssid_ie { - u8 id; - u8 len; - u8 ssid[32]; -} __attribute__ ((packed)); - -#define PROBE_OPTION_MAX_3945 4 -#define PROBE_OPTION_MAX 20 -#define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) -#define IWL_GOOD_CRC_TH cpu_to_le16(1) -#define IWL_MAX_SCAN_SIZE 1024 -#define IWL_MAX_PROBE_REQUEST 200 - -/* - * REPLY_SCAN_CMD = 0x80 (command) - * - * The hardware scan command is very powerful; the driver can set it up to - * maintain (relatively) normal network traffic while doing a scan in the - * background. The max_out_time and suspend_time control the ratio of how - * long the device stays on an associated network channel ("service channel") - * vs. how long it's away from the service channel, i.e. tuned to other channels - * for scanning. - * - * max_out_time is the max time off-channel (in usec), and suspend_time - * is how long (in "extended beacon" format) that the scan is "suspended" - * after returning to the service channel. That is, suspend_time is the - * time that we stay on the service channel, doing normal work, between - * scan segments. The driver may set these parameters differently to support - * scanning when associated vs. not associated, and light vs. heavy traffic - * loads when associated. - * - * After receiving this command, the device's scan engine does the following; - * - * 1) Sends SCAN_START notification to driver - * 2) Checks to see if it has time to do scan for one channel - * 3) Sends NULL packet, with power-save (PS) bit set to 1, - * to tell AP that we're going off-channel - * 4) Tunes to first channel in scan list, does active or passive scan - * 5) Sends SCAN_RESULT notification to driver - * 6) Checks to see if it has time to do scan on *next* channel in list - * 7) Repeats 4-6 until it no longer has time to scan the next channel - * before max_out_time expires - * 8) Returns to service channel - * 9) Sends NULL packet with PS=0 to tell AP that we're back - * 10) Stays on service channel until suspend_time expires - * 11) Repeats entire process 2-10 until list is complete - * 12) Sends SCAN_COMPLETE notification - * - * For fast, efficient scans, the scan command also has support for staying on - * a channel for just a short time, if doing active scanning and getting no - * responses to the transmitted probe request. This time is controlled by - * quiet_time, and the number of received packets below which a channel is - * considered "quiet" is controlled by quiet_plcp_threshold. - * - * For active scanning on channels that have regulatory restrictions against - * blindly transmitting, the scan can listen before transmitting, to make sure - * that there is already legitimate activity on the channel. If enough - * packets are cleanly received on the channel (controlled by good_CRC_th, - * typical value 1), the scan engine starts transmitting probe requests. - * - * Driver must use separate scan commands for 2.4 vs. 5 GHz bands. - * - * To avoid uCode errors, see timing restrictions described under - * struct iwl_scan_channel. - */ - -struct iwl3945_scan_cmd { - __le16 len; - u8 reserved0; - u8 channel_count; /* # channels in channel list */ - __le16 quiet_time; /* dwell only this # millisecs on quiet channel - * (only for active scan) */ - __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ - __le16 good_CRC_th; /* passive -> active promotion threshold */ - __le16 reserved1; - __le32 max_out_time; /* max usec to be away from associated (service) - * channel */ - __le32 suspend_time; /* pause scan this long (in "extended beacon - * format") when returning to service channel: - * 3945; 31:24 # beacons, 19:0 additional usec, - * 4965; 31:22 # beacons, 21:0 additional usec. - */ - __le32 flags; /* RXON_FLG_* */ - __le32 filter_flags; /* RXON_FILTER_* */ - - /* For active scans (set to all-0s for passive scans). - * Does not include payload. Must specify Tx rate; no rate scaling. */ - struct iwl3945_tx_cmd tx_cmd; - - /* For directed active scans (set to all-0s otherwise) */ - struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945]; - - /* - * Probe request frame, followed by channel list. - * - * Size of probe request frame is specified by byte count in tx_cmd. - * Channel list follows immediately after probe request frame. - * Number of channels in list is specified by channel_count. - * Each channel in list is of type: - * - * struct iwl3945_scan_channel channels[0]; - * - * NOTE: Only one band of channels can be scanned per pass. You - * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait - * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) - * before requesting another scan. - */ - u8 data[0]; -} __attribute__ ((packed)); - -struct iwl_scan_cmd { - __le16 len; - u8 reserved0; - u8 channel_count; /* # channels in channel list */ - __le16 quiet_time; /* dwell only this # millisecs on quiet channel - * (only for active scan) */ - __le16 quiet_plcp_th; /* quiet chnl is < this # pkts (typ. 1) */ - __le16 good_CRC_th; /* passive -> active promotion threshold */ - __le16 rx_chain; /* RXON_RX_CHAIN_* */ - __le32 max_out_time; /* max usec to be away from associated (service) - * channel */ - __le32 suspend_time; /* pause scan this long (in "extended beacon - * format") when returning to service chnl: - * 3945; 31:24 # beacons, 19:0 additional usec, - * 4965; 31:22 # beacons, 21:0 additional usec. - */ - __le32 flags; /* RXON_FLG_* */ - __le32 filter_flags; /* RXON_FILTER_* */ - - /* For active scans (set to all-0s for passive scans). - * Does not include payload. Must specify Tx rate; no rate scaling. */ - struct iwl_tx_cmd tx_cmd; - - /* For directed active scans (set to all-0s otherwise) */ - struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX]; - - /* - * Probe request frame, followed by channel list. - * - * Size of probe request frame is specified by byte count in tx_cmd. - * Channel list follows immediately after probe request frame. - * Number of channels in list is specified by channel_count. - * Each channel in list is of type: - * - * struct iwl_scan_channel channels[0]; - * - * NOTE: Only one band of channels can be scanned per pass. You - * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait - * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION) - * before requesting another scan. - */ - u8 data[0]; -} __attribute__ ((packed)); - -/* Can abort will notify by complete notification with abort status. */ -#define CAN_ABORT_STATUS cpu_to_le32(0x1) -/* complete notification statuses */ -#define ABORT_STATUS 0x2 - -/* - * REPLY_SCAN_CMD = 0x80 (response) - */ -struct iwl_scanreq_notification { - __le32 status; /* 1: okay, 2: cannot fulfill request */ -} __attribute__ ((packed)); - -/* - * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command) - */ -struct iwl_scanstart_notification { - __le32 tsf_low; - __le32 tsf_high; - __le32 beacon_timer; - u8 channel; - u8 band; - u8 reserved[2]; - __le32 status; -} __attribute__ ((packed)); - -#define SCAN_OWNER_STATUS 0x1; -#define MEASURE_OWNER_STATUS 0x2; - -#define NUMBER_OF_STATISTICS 1 /* first __le32 is good CRC */ -/* - * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command) - */ -struct iwl_scanresults_notification { - u8 channel; - u8 band; - u8 reserved[2]; - __le32 tsf_low; - __le32 tsf_high; - __le32 statistics[NUMBER_OF_STATISTICS]; -} __attribute__ ((packed)); - -/* - * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command) - */ -struct iwl_scancomplete_notification { - u8 scanned_channels; - u8 status; - u8 reserved; - u8 last_channel; - __le32 tsf_low; - __le32 tsf_high; -} __attribute__ ((packed)); - - -/****************************************************************************** - * (9) - * IBSS/AP Commands and Notifications: - * - *****************************************************************************/ - -/* - * BEACON_NOTIFICATION = 0x90 (notification only, not a command) - */ - -struct iwl3945_beacon_notif { - struct iwl3945_tx_resp beacon_notify_hdr; - __le32 low_tsf; - __le32 high_tsf; - __le32 ibss_mgr_status; -} __attribute__ ((packed)); - -struct iwl4965_beacon_notif { - struct iwl4965_tx_resp beacon_notify_hdr; - __le32 low_tsf; - __le32 high_tsf; - __le32 ibss_mgr_status; -} __attribute__ ((packed)); - -/* - * REPLY_TX_BEACON = 0x91 (command, has simple generic response) - */ - -struct iwl3945_tx_beacon_cmd { - struct iwl3945_tx_cmd tx; - __le16 tim_idx; - u8 tim_size; - u8 reserved1; - struct ieee80211_hdr frame[0]; /* beacon frame */ -} __attribute__ ((packed)); - -struct iwl_tx_beacon_cmd { - struct iwl_tx_cmd tx; - __le16 tim_idx; - u8 tim_size; - u8 reserved1; - struct ieee80211_hdr frame[0]; /* beacon frame */ -} __attribute__ ((packed)); - -/****************************************************************************** - * (10) - * Statistics Commands and Notifications: - * - *****************************************************************************/ - -#define IWL_TEMP_CONVERT 260 - -#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 -#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 -#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 - -/* Used for passing to driver number of successes and failures per rate */ -struct rate_histogram { - union { - __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } success; - union { - __le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS]; - __le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS]; - __le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS]; - } failed; -} __attribute__ ((packed)); - -/* statistics command response */ - -struct iwl39_statistics_rx_phy { - __le32 ina_cnt; - __le32 fina_cnt; - __le32 plcp_err; - __le32 crc32_err; - __le32 overrun_err; - __le32 early_overrun_err; - __le32 crc32_good; - __le32 false_alarm_cnt; - __le32 fina_sync_err_cnt; - __le32 sfd_timeout; - __le32 fina_timeout; - __le32 unresponded_rts; - __le32 rxe_frame_limit_overrun; - __le32 sent_ack_cnt; - __le32 sent_cts_cnt; -} __attribute__ ((packed)); - -struct iwl39_statistics_rx_non_phy { - __le32 bogus_cts; /* CTS received when not expecting CTS */ - __le32 bogus_ack; /* ACK received when not expecting ACK */ - __le32 non_bssid_frames; /* number of frames with BSSID that - * doesn't belong to the STA BSSID */ - __le32 filtered_frames; /* count frames that were dumped in the - * filtering process */ - __le32 non_channel_beacons; /* beacons with our bss id but not on - * our serving channel */ -} __attribute__ ((packed)); - -struct iwl39_statistics_rx { - struct iwl39_statistics_rx_phy ofdm; - struct iwl39_statistics_rx_phy cck; - struct iwl39_statistics_rx_non_phy general; -} __attribute__ ((packed)); - -struct iwl39_statistics_tx { - __le32 preamble_cnt; - __le32 rx_detected_cnt; - __le32 bt_prio_defer_cnt; - __le32 bt_prio_kill_cnt; - __le32 few_bytes_cnt; - __le32 cts_timeout; - __le32 ack_timeout; - __le32 expected_ack_cnt; - __le32 actual_ack_cnt; -} __attribute__ ((packed)); - -struct statistics_dbg { - __le32 burst_check; - __le32 burst_count; - __le32 reserved[4]; -} __attribute__ ((packed)); - -struct iwl39_statistics_div { - __le32 tx_on_a; - __le32 tx_on_b; - __le32 exec_time; - __le32 probe_time; -} __attribute__ ((packed)); - -struct iwl39_statistics_general { - __le32 temperature; - struct statistics_dbg dbg; - __le32 sleep_time; - __le32 slots_out; - __le32 slots_idle; - __le32 ttl_timestamp; - struct iwl39_statistics_div div; -} __attribute__ ((packed)); - -struct statistics_rx_phy { - __le32 ina_cnt; - __le32 fina_cnt; - __le32 plcp_err; - __le32 crc32_err; - __le32 overrun_err; - __le32 early_overrun_err; - __le32 crc32_good; - __le32 false_alarm_cnt; - __le32 fina_sync_err_cnt; - __le32 sfd_timeout; - __le32 fina_timeout; - __le32 unresponded_rts; - __le32 rxe_frame_limit_overrun; - __le32 sent_ack_cnt; - __le32 sent_cts_cnt; - __le32 sent_ba_rsp_cnt; - __le32 dsp_self_kill; - __le32 mh_format_err; - __le32 re_acq_main_rssi_sum; - __le32 reserved3; -} __attribute__ ((packed)); - -struct statistics_rx_ht_phy { - __le32 plcp_err; - __le32 overrun_err; - __le32 early_overrun_err; - __le32 crc32_good; - __le32 crc32_err; - __le32 mh_format_err; - __le32 agg_crc32_good; - __le32 agg_mpdu_cnt; - __le32 agg_cnt; - __le32 reserved2; -} __attribute__ ((packed)); - -#define INTERFERENCE_DATA_AVAILABLE cpu_to_le32(1) - -struct statistics_rx_non_phy { - __le32 bogus_cts; /* CTS received when not expecting CTS */ - __le32 bogus_ack; /* ACK received when not expecting ACK */ - __le32 non_bssid_frames; /* number of frames with BSSID that - * doesn't belong to the STA BSSID */ - __le32 filtered_frames; /* count frames that were dumped in the - * filtering process */ - __le32 non_channel_beacons; /* beacons with our bss id but not on - * our serving channel */ - __le32 channel_beacons; /* beacons with our bss id and in our - * serving channel */ - __le32 num_missed_bcon; /* number of missed beacons */ - __le32 adc_rx_saturation_time; /* count in 0.8us units the time the - * ADC was in saturation */ - __le32 ina_detection_search_time;/* total time (in 0.8us) searched - * for INA */ - __le32 beacon_silence_rssi_a; /* RSSI silence after beacon frame */ - __le32 beacon_silence_rssi_b; /* RSSI silence after beacon frame */ - __le32 beacon_silence_rssi_c; /* RSSI silence after beacon frame */ - __le32 interference_data_flag; /* flag for interference data - * availability. 1 when data is - * available. */ - __le32 channel_load; /* counts RX Enable time in uSec */ - __le32 dsp_false_alarms; /* DSP false alarm (both OFDM - * and CCK) counter */ - __le32 beacon_rssi_a; - __le32 beacon_rssi_b; - __le32 beacon_rssi_c; - __le32 beacon_energy_a; - __le32 beacon_energy_b; - __le32 beacon_energy_c; -} __attribute__ ((packed)); - -struct statistics_rx { - struct statistics_rx_phy ofdm; - struct statistics_rx_phy cck; - struct statistics_rx_non_phy general; - struct statistics_rx_ht_phy ofdm_ht; -} __attribute__ ((packed)); - -/** - * struct statistics_tx_power - current tx power - * - * @ant_a: current tx power on chain a in 1/2 dB step - * @ant_b: current tx power on chain b in 1/2 dB step - * @ant_c: current tx power on chain c in 1/2 dB step - */ -struct statistics_tx_power { - u8 ant_a; - u8 ant_b; - u8 ant_c; - u8 reserved; -} __attribute__ ((packed)); - -struct statistics_tx_non_phy_agg { - __le32 ba_timeout; - __le32 ba_reschedule_frames; - __le32 scd_query_agg_frame_cnt; - __le32 scd_query_no_agg; - __le32 scd_query_agg; - __le32 scd_query_mismatch; - __le32 frame_not_ready; - __le32 underrun; - __le32 bt_prio_kill; - __le32 rx_ba_rsp_cnt; -} __attribute__ ((packed)); - -struct statistics_tx { - __le32 preamble_cnt; - __le32 rx_detected_cnt; - __le32 bt_prio_defer_cnt; - __le32 bt_prio_kill_cnt; - __le32 few_bytes_cnt; - __le32 cts_timeout; - __le32 ack_timeout; - __le32 expected_ack_cnt; - __le32 actual_ack_cnt; - __le32 dump_msdu_cnt; - __le32 burst_abort_next_frame_mismatch_cnt; - __le32 burst_abort_missing_next_frame_cnt; - __le32 cts_timeout_collision; - __le32 ack_or_ba_timeout_collision; - struct statistics_tx_non_phy_agg agg; - struct statistics_tx_power tx_power; - __le32 reserved1; -} __attribute__ ((packed)); - - -struct statistics_div { - __le32 tx_on_a; - __le32 tx_on_b; - __le32 exec_time; - __le32 probe_time; - __le32 reserved1; - __le32 reserved2; -} __attribute__ ((packed)); - -struct statistics_general { - __le32 temperature; - __le32 temperature_m; - struct statistics_dbg dbg; - __le32 sleep_time; - __le32 slots_out; - __le32 slots_idle; - __le32 ttl_timestamp; - struct statistics_div div; - __le32 rx_enable_counter; - __le32 reserved1; - __le32 reserved2; - __le32 reserved3; -} __attribute__ ((packed)); - -/* - * REPLY_STATISTICS_CMD = 0x9c, - * 3945 and 4965 identical. - * - * This command triggers an immediate response containing uCode statistics. - * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below. - * - * If the CLEAR_STATS configuration flag is set, uCode will clear its - * internal copy of the statistics (counters) after issuing the response. - * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below). - * - * If the DISABLE_NOTIF configuration flag is set, uCode will not issue - * STATISTICS_NOTIFICATIONs after received beacons (see below). This flag - * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself. - */ -#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1) /* see above */ -#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */ -struct iwl_statistics_cmd { - __le32 configuration_flags; /* IWL_STATS_CONF_* */ -} __attribute__ ((packed)); - -/* - * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command) - * - * By default, uCode issues this notification after receiving a beacon - * while associated. To disable this behavior, set DISABLE_NOTIF flag in the - * REPLY_STATISTICS_CMD 0x9c, above. - * - * Statistics counters continue to increment beacon after beacon, but are - * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD - * 0x9c with CLEAR_STATS bit set (see above). - * - * uCode also issues this notification during scans. uCode clears statistics - * appropriately so that each notification contains statistics for only the - * one channel that has just been scanned. - */ -#define STATISTICS_REPLY_FLG_BAND_24G_MSK cpu_to_le32(0x2) -#define STATISTICS_REPLY_FLG_HT40_MODE_MSK cpu_to_le32(0x8) - -struct iwl3945_notif_statistics { - __le32 flag; - struct iwl39_statistics_rx rx; - struct iwl39_statistics_tx tx; - struct iwl39_statistics_general general; -} __attribute__ ((packed)); - -struct iwl_notif_statistics { - __le32 flag; - struct statistics_rx rx; - struct statistics_tx tx; - struct statistics_general general; -} __attribute__ ((packed)); - - -/* - * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command) - */ -/* if ucode missed CONSECUTIVE_MISSED_BCONS_TH beacons in a row, - * then this notification will be sent. */ -#define CONSECUTIVE_MISSED_BCONS_TH 20 - -struct iwl_missed_beacon_notif { - __le32 consequtive_missed_beacons; - __le32 total_missed_becons; - __le32 num_expected_beacons; - __le32 num_recvd_beacons; -} __attribute__ ((packed)); - - -/****************************************************************************** - * (11) - * Rx Calibration Commands: - * - * With the uCode used for open source drivers, most Tx calibration (except - * for Tx Power) and most Rx calibration is done by uCode during the - * "initialize" phase of uCode boot. Driver must calibrate only: - * - * 1) Tx power (depends on temperature), described elsewhere - * 2) Receiver gain balance (optimize MIMO, and detect disconnected antennas) - * 3) Receiver sensitivity (to optimize signal detection) - * - *****************************************************************************/ - -/** - * SENSITIVITY_CMD = 0xa8 (command, has simple generic response) - * - * This command sets up the Rx signal detector for a sensitivity level that - * is high enough to lock onto all signals within the associated network, - * but low enough to ignore signals that are below a certain threshold, so as - * not to have too many "false alarms". False alarms are signals that the - * Rx DSP tries to lock onto, but then discards after determining that they - * are noise. - * - * The optimum number of false alarms is between 5 and 50 per 200 TUs - * (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e. - * time listening, not transmitting). Driver must adjust sensitivity so that - * the ratio of actual false alarms to actual Rx time falls within this range. - * - * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each - * received beacon. These provide information to the driver to analyze the - * sensitivity. Don't analyze statistics that come in from scanning, or any - * other non-associated-network source. Pertinent statistics include: - * - * From "general" statistics (struct statistics_rx_non_phy): - * - * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level) - * Measure of energy of desired signal. Used for establishing a level - * below which the device does not detect signals. - * - * (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB) - * Measure of background noise in silent period after beacon. - * - * channel_load - * uSecs of actual Rx time during beacon period (varies according to - * how much time was spent transmitting). - * - * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately: - * - * false_alarm_cnt - * Signal locks abandoned early (before phy-level header). - * - * plcp_err - * Signal locks abandoned late (during phy-level header). - * - * NOTE: Both false_alarm_cnt and plcp_err increment monotonically from - * beacon to beacon, i.e. each value is an accumulation of all errors - * before and including the latest beacon. Values will wrap around to 0 - * after counting up to 2^32 - 1. Driver must differentiate vs. - * previous beacon's values to determine # false alarms in the current - * beacon period. - * - * Total number of false alarms = false_alarms + plcp_errs - * - * For OFDM, adjust the following table entries in struct iwl_sensitivity_cmd - * (notice that the start points for OFDM are at or close to settings for - * maximum sensitivity): - * - * START / MIN / MAX - * HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX 90 / 85 / 120 - * HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX 170 / 170 / 210 - * HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX 105 / 105 / 140 - * HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX 220 / 220 / 270 - * - * If actual rate of OFDM false alarms (+ plcp_errors) is too high - * (greater than 50 for each 204.8 msecs listening), reduce sensitivity - * by *adding* 1 to all 4 of the table entries above, up to the max for - * each entry. Conversely, if false alarm rate is too low (less than 5 - * for each 204.8 msecs listening), *subtract* 1 from each entry to - * increase sensitivity. - * - * For CCK sensitivity, keep track of the following: - * - * 1). 20-beacon history of maximum background noise, indicated by - * (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the - * 3 receivers. For any given beacon, the "silence reference" is - * the maximum of last 60 samples (20 beacons * 3 receivers). - * - * 2). 10-beacon history of strongest signal level, as indicated - * by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers, - * i.e. the strength of the signal through the best receiver at the - * moment. These measurements are "upside down", with lower values - * for stronger signals, so max energy will be *minimum* value. - * - * Then for any given beacon, the driver must determine the *weakest* - * of the strongest signals; this is the minimum level that needs to be - * successfully detected, when using the best receiver at the moment. - * "Max cck energy" is the maximum (higher value means lower energy!) - * of the last 10 minima. Once this is determined, driver must add - * a little margin by adding "6" to it. - * - * 3). Number of consecutive beacon periods with too few false alarms. - * Reset this to 0 at the first beacon period that falls within the - * "good" range (5 to 50 false alarms per 204.8 milliseconds rx). - * - * Then, adjust the following CCK table entries in struct iwl_sensitivity_cmd - * (notice that the start points for CCK are at maximum sensitivity): - * - * START / MIN / MAX - * HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX 125 / 125 / 200 - * HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX 200 / 200 / 400 - * HD_MIN_ENERGY_CCK_DET_INDEX 100 / 0 / 100 - * - * If actual rate of CCK false alarms (+ plcp_errors) is too high - * (greater than 50 for each 204.8 msecs listening), method for reducing - * sensitivity is: - * - * 1) *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX, - * up to max 400. - * - * 2) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160, - * sensitivity has been reduced a significant amount; bring it up to - * a moderate 161. Otherwise, *add* 3, up to max 200. - * - * 3) a) If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160, - * sensitivity has been reduced only a moderate or small amount; - * *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX, - * down to min 0. Otherwise (if gain has been significantly reduced), - * don't change the HD_MIN_ENERGY_CCK_DET_INDEX value. - * - * b) Save a snapshot of the "silence reference". - * - * If actual rate of CCK false alarms (+ plcp_errors) is too low - * (less than 5 for each 204.8 msecs listening), method for increasing - * sensitivity is used only if: - * - * 1a) Previous beacon did not have too many false alarms - * 1b) AND difference between previous "silence reference" and current - * "silence reference" (prev - current) is 2 or more, - * OR 2) 100 or more consecutive beacon periods have had rate of - * less than 5 false alarms per 204.8 milliseconds rx time. - * - * Method for increasing sensitivity: - * - * 1) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX, - * down to min 125. - * - * 2) *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX, - * down to min 200. - * - * 3) *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100. - * - * If actual rate of CCK false alarms (+ plcp_errors) is within good range - * (between 5 and 50 for each 204.8 msecs listening): - * - * 1) Save a snapshot of the silence reference. - * - * 2) If previous beacon had too many CCK false alarms (+ plcp_errors), - * give some extra margin to energy threshold by *subtracting* 8 - * from value in HD_MIN_ENERGY_CCK_DET_INDEX. - * - * For all cases (too few, too many, good range), make sure that the CCK - * detection threshold (energy) is below the energy level for robust - * detection over the past 10 beacon periods, the "Max cck energy". - * Lower values mean higher energy; this means making sure that the value - * in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy". - * - * Driver should set the following entries to fixed values: - * - * HD_MIN_ENERGY_OFDM_DET_INDEX 100 - * HD_BARKER_CORR_TH_ADD_MIN_INDEX 190 - * HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX 390 - * HD_OFDM_ENERGY_TH_IN_INDEX 62 - */ - -/* - * Table entries in SENSITIVITY_CMD (struct iwl_sensitivity_cmd) - */ -#define HD_TABLE_SIZE (11) /* number of entries */ -#define HD_MIN_ENERGY_CCK_DET_INDEX (0) /* table indexes */ -#define HD_MIN_ENERGY_OFDM_DET_INDEX (1) -#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX (2) -#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX (3) -#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX (4) -#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX (5) -#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX (6) -#define HD_BARKER_CORR_TH_ADD_MIN_INDEX (7) -#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX (8) -#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX (9) -#define HD_OFDM_ENERGY_TH_IN_INDEX (10) - -/* Control field in struct iwl_sensitivity_cmd */ -#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE cpu_to_le16(0) -#define SENSITIVITY_CMD_CONTROL_WORK_TABLE cpu_to_le16(1) - -/** - * struct iwl_sensitivity_cmd - * @control: (1) updates working table, (0) updates default table - * @table: energy threshold values, use HD_* as index into table - * - * Always use "1" in "control" to update uCode's working table and DSP. - */ -struct iwl_sensitivity_cmd { - __le16 control; /* always use "1" */ - __le16 table[HD_TABLE_SIZE]; /* use HD_* as index */ -} __attribute__ ((packed)); - - -/** - * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response) - * - * This command sets the relative gains of 4965's 3 radio receiver chains. - * - * After the first association, driver should accumulate signal and noise - * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20 - * beacons from the associated network (don't collect statistics that come - * in from scanning, or any other non-network source). - * - * DISCONNECTED ANTENNA: - * - * Driver should determine which antennas are actually connected, by comparing - * average beacon signal levels for the 3 Rx chains. Accumulate (add) the - * following values over 20 beacons, one accumulator for each of the chains - * a/b/c, from struct statistics_rx_non_phy: - * - * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB) - * - * Find the strongest signal from among a/b/c. Compare the other two to the - * strongest. If any signal is more than 15 dB (times 20, unless you - * divide the accumulated values by 20) below the strongest, the driver - * considers that antenna to be disconnected, and should not try to use that - * antenna/chain for Rx or Tx. If both A and B seem to be disconnected, - * driver should declare the stronger one as connected, and attempt to use it - * (A and B are the only 2 Tx chains!). - * - * - * RX BALANCE: - * - * Driver should balance the 3 receivers (but just the ones that are connected - * to antennas, see above) for gain, by comparing the average signal levels - * detected during the silence after each beacon (background noise). - * Accumulate (add) the following values over 20 beacons, one accumulator for - * each of the chains a/b/c, from struct statistics_rx_non_phy: - * - * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB) - * - * Find the weakest background noise level from among a/b/c. This Rx chain - * will be the reference, with 0 gain adjustment. Attenuate other channels by - * finding noise difference: - * - * (accum_noise[i] - accum_noise[reference]) / 30 - * - * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB. - * For use in diff_gain_[abc] fields of struct iwl_calibration_cmd, the - * driver should limit the difference results to a range of 0-3 (0-4.5 dB), - * and set bit 2 to indicate "reduce gain". The value for the reference - * (weakest) chain should be "0". - * - * diff_gain_[abc] bit fields: - * 2: (1) reduce gain, (0) increase gain - * 1-0: amount of gain, units of 1.5 dB - */ - -/* Phy calibration command for series */ - -enum { - IWL_PHY_CALIBRATE_DIFF_GAIN_CMD = 7, - IWL_PHY_CALIBRATE_DC_CMD = 8, - IWL_PHY_CALIBRATE_LO_CMD = 9, - IWL_PHY_CALIBRATE_RX_BB_CMD = 10, - IWL_PHY_CALIBRATE_TX_IQ_CMD = 11, - IWL_PHY_CALIBRATE_RX_IQ_CMD = 12, - IWL_PHY_CALIBRATION_NOISE_CMD = 13, - IWL_PHY_CALIBRATE_AGC_TABLE_CMD = 14, - IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, - IWL_PHY_CALIBRATE_BASE_BAND_CMD = 16, - IWL_PHY_CALIBRATE_TX_IQ_PERD_CMD = 17, - IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD = 18, - IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD = 19, -}; - - -#define IWL_CALIB_INIT_CFG_ALL cpu_to_le32(0xffffffff) - -struct iwl_calib_cfg_elmnt_s { - __le32 is_enable; - __le32 start; - __le32 send_res; - __le32 apply_res; - __le32 reserved; -} __attribute__ ((packed)); - -struct iwl_calib_cfg_status_s { - struct iwl_calib_cfg_elmnt_s once; - struct iwl_calib_cfg_elmnt_s perd; - __le32 flags; -} __attribute__ ((packed)); - -struct iwl_calib_cfg_cmd { - struct iwl_calib_cfg_status_s ucd_calib_cfg; - struct iwl_calib_cfg_status_s drv_calib_cfg; - __le32 reserved1; -} __attribute__ ((packed)); - -struct iwl_calib_hdr { - u8 op_code; - u8 first_group; - u8 groups_num; - u8 data_valid; -} __attribute__ ((packed)); - -struct iwl_calib_cmd { - struct iwl_calib_hdr hdr; - u8 data[0]; -} __attribute__ ((packed)); - -/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */ -struct iwl_calib_diff_gain_cmd { - struct iwl_calib_hdr hdr; - s8 diff_gain_a; /* see above */ - s8 diff_gain_b; - s8 diff_gain_c; - u8 reserved1; -} __attribute__ ((packed)); - -struct iwl_calib_xtal_freq_cmd { - struct iwl_calib_hdr hdr; - u8 cap_pin1; - u8 cap_pin2; - u8 pad[2]; -} __attribute__ ((packed)); - -/* IWL_PHY_CALIBRATE_CHAIN_NOISE_RESET_CMD */ -struct iwl_calib_chain_noise_reset_cmd { - struct iwl_calib_hdr hdr; - u8 data[0]; -}; - -/* IWL_PHY_CALIBRATE_CHAIN_NOISE_GAIN_CMD */ -struct iwl_calib_chain_noise_gain_cmd { - struct iwl_calib_hdr hdr; - u8 delta_gain_1; - u8 delta_gain_2; - u8 pad[2]; -} __attribute__ ((packed)); - -/****************************************************************************** - * (12) - * Miscellaneous Commands: - * - *****************************************************************************/ - -/* - * LEDs Command & Response - * REPLY_LEDS_CMD = 0x48 (command, has simple generic response) - * - * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field), - * this command turns it on or off, or sets up a periodic blinking cycle. - */ -struct iwl_led_cmd { - __le32 interval; /* "interval" in uSec */ - u8 id; /* 1: Activity, 2: Link, 3: Tech */ - u8 off; /* # intervals off while blinking; - * "0", with >0 "on" value, turns LED on */ - u8 on; /* # intervals on while blinking; - * "0", regardless of "off", turns LED off */ - u8 reserved; -} __attribute__ ((packed)); - -/* - * Coexistence WIFI/WIMAX Command - * COEX_PRIORITY_TABLE_CMD = 0x5a - * - */ -enum { - COEX_UNASSOC_IDLE = 0, - COEX_UNASSOC_MANUAL_SCAN = 1, - COEX_UNASSOC_AUTO_SCAN = 2, - COEX_CALIBRATION = 3, - COEX_PERIODIC_CALIBRATION = 4, - COEX_CONNECTION_ESTAB = 5, - COEX_ASSOCIATED_IDLE = 6, - COEX_ASSOC_MANUAL_SCAN = 7, - COEX_ASSOC_AUTO_SCAN = 8, - COEX_ASSOC_ACTIVE_LEVEL = 9, - COEX_RF_ON = 10, - COEX_RF_OFF = 11, - COEX_STAND_ALONE_DEBUG = 12, - COEX_IPAN_ASSOC_LEVEL = 13, - COEX_RSRVD1 = 14, - COEX_RSRVD2 = 15, - COEX_NUM_OF_EVENTS = 16 -}; - -struct iwl_wimax_coex_event_entry { - u8 request_prio; - u8 win_medium_prio; - u8 reserved; - u8 flags; -} __attribute__ ((packed)); - -/* COEX flag masks */ - -/* Station table is valid */ -#define COEX_FLAGS_STA_TABLE_VALID_MSK (0x1) -/* UnMask wake up src at unassociated sleep */ -#define COEX_FLAGS_UNASSOC_WA_UNMASK_MSK (0x4) -/* UnMask wake up src at associated sleep */ -#define COEX_FLAGS_ASSOC_WA_UNMASK_MSK (0x8) -/* Enable CoEx feature. */ -#define COEX_FLAGS_COEX_ENABLE_MSK (0x80) - -struct iwl_wimax_coex_cmd { - u8 flags; - u8 reserved[3]; - struct iwl_wimax_coex_event_entry sta_prio[COEX_NUM_OF_EVENTS]; -} __attribute__ ((packed)); - -/****************************************************************************** - * (13) - * Union of all expected notifications/responses: - * - *****************************************************************************/ - -struct iwl_rx_packet { - __le32 len_n_flags; - struct iwl_cmd_header hdr; - union { - struct iwl3945_rx_frame rx_frame; - struct iwl3945_tx_resp tx_resp; - struct iwl3945_beacon_notif beacon_status; - - struct iwl_alive_resp alive_frame; - struct iwl_spectrum_notification spectrum_notif; - struct iwl_csa_notification csa_notif; - struct iwl_error_resp err_resp; - struct iwl_card_state_notif card_state_notif; - struct iwl_add_sta_resp add_sta; - struct iwl_rem_sta_resp rem_sta; - struct iwl_sleep_notification sleep_notif; - struct iwl_spectrum_resp spectrum; - struct iwl_notif_statistics stats; - struct iwl_compressed_ba_resp compressed_ba; - struct iwl_missed_beacon_notif missed_beacon; - __le32 status; - u8 raw[0]; - } u; -} __attribute__ ((packed)); - -int iwl_agn_check_rxon_cmd(struct iwl_priv *priv); - -#endif /* __iwl_commands_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c deleted file mode 100644 index 4a4f7e49a883..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-core.c +++ /dev/null @@ -1,3077 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include -#include -#include -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" /* FIXME: remove */ -#include "iwl-debug.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-power.h" -#include "iwl-sta.h" -#include "iwl-helpers.h" - - -MODULE_DESCRIPTION("iwl core"); -MODULE_VERSION(IWLWIFI_VERSION); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); -MODULE_LICENSE("GPL"); - -#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np) \ - [IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP, \ - IWL_RATE_SISO_##s##M_PLCP, \ - IWL_RATE_MIMO2_##s##M_PLCP,\ - IWL_RATE_MIMO3_##s##M_PLCP,\ - IWL_RATE_##r##M_IEEE, \ - IWL_RATE_##ip##M_INDEX, \ - IWL_RATE_##in##M_INDEX, \ - IWL_RATE_##rp##M_INDEX, \ - IWL_RATE_##rn##M_INDEX, \ - IWL_RATE_##pp##M_INDEX, \ - IWL_RATE_##np##M_INDEX } - -u32 iwl_debug_level; -EXPORT_SYMBOL(iwl_debug_level); - -static irqreturn_t iwl_isr(int irq, void *data); - -/* - * Parameter order: - * rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate - * - * If there isn't a valid next or previous rate then INV is used which - * maps to IWL_RATE_INVALID - * - */ -const struct iwl_rate_info iwl_rates[IWL_RATE_COUNT] = { - IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2), /* 1mbps */ - IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5), /* 2mbps */ - IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11), /*5.5mbps */ - IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18), /* 11mbps */ - IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11), /* 6mbps */ - IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11), /* 9mbps */ - IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18), /* 12mbps */ - IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24), /* 18mbps */ - IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36), /* 24mbps */ - IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48), /* 36mbps */ - IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54), /* 48mbps */ - IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */ - IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */ - /* FIXME:RS: ^^ should be INV (legacy) */ -}; -EXPORT_SYMBOL(iwl_rates); - -/** - * translate ucode response to mac80211 tx status control values - */ -void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info) -{ - struct ieee80211_tx_rate *r = &info->control.rates[0]; - - info->antenna_sel_tx = - ((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS); - if (rate_n_flags & RATE_MCS_HT_MSK) - r->flags |= IEEE80211_TX_RC_MCS; - if (rate_n_flags & RATE_MCS_GF_MSK) - r->flags |= IEEE80211_TX_RC_GREEN_FIELD; - if (rate_n_flags & RATE_MCS_HT40_MSK) - r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; - if (rate_n_flags & RATE_MCS_DUP_MSK) - r->flags |= IEEE80211_TX_RC_DUP_DATA; - if (rate_n_flags & RATE_MCS_SGI_MSK) - r->flags |= IEEE80211_TX_RC_SHORT_GI; - r->idx = iwl_hwrate_to_mac80211_idx(rate_n_flags, info->band); -} -EXPORT_SYMBOL(iwl_hwrate_to_tx_control); - -int iwl_hwrate_to_plcp_idx(u32 rate_n_flags) -{ - int idx = 0; - - /* HT rate format */ - if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = (rate_n_flags & 0xff); - - if (idx >= IWL_RATE_MIMO3_6M_PLCP) - idx = idx - IWL_RATE_MIMO3_6M_PLCP; - else if (idx >= IWL_RATE_MIMO2_6M_PLCP) - idx = idx - IWL_RATE_MIMO2_6M_PLCP; - - idx += IWL_FIRST_OFDM_RATE; - /* skip 9M not supported in ht*/ - if (idx >= IWL_RATE_9M_INDEX) - idx += 1; - if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE)) - return idx; - - /* legacy rate format, search for match in table */ - } else { - for (idx = 0; idx < ARRAY_SIZE(iwl_rates); idx++) - if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) - return idx; - } - - return -1; -} -EXPORT_SYMBOL(iwl_hwrate_to_plcp_idx); - -int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band) -{ - int idx = 0; - int band_offset = 0; - - /* HT rate format: mac80211 wants an MCS number, which is just LSB */ - if (rate_n_flags & RATE_MCS_HT_MSK) { - idx = (rate_n_flags & 0xff); - return idx; - /* Legacy rate format, search for match in table */ - } else { - if (band == IEEE80211_BAND_5GHZ) - band_offset = IWL_FIRST_OFDM_RATE; - for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++) - if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF)) - return idx - band_offset; - } - - return -1; -} - -u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant) -{ - int i; - u8 ind = ant; - for (i = 0; i < RATE_ANT_NUM - 1; i++) { - ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0; - if (priv->hw_params.valid_tx_ant & BIT(ind)) - return ind; - } - return ant; -} - -const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -EXPORT_SYMBOL(iwl_bcast_addr); - - -/* This function both allocates and initializes hw and priv. */ -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, - struct ieee80211_ops *hw_ops) -{ - struct iwl_priv *priv; - - /* mac80211 allocates memory for this device instance, including - * space for this driver's private structure */ - struct ieee80211_hw *hw = - ieee80211_alloc_hw(sizeof(struct iwl_priv), hw_ops); - if (hw == NULL) { - printk(KERN_ERR "%s: Can not allocate network device\n", - cfg->name); - goto out; - } - - priv = hw->priv; - priv->hw = hw; - -out: - return hw; -} -EXPORT_SYMBOL(iwl_alloc_all); - -void iwl_hw_detect(struct iwl_priv *priv) -{ - priv->hw_rev = _iwl_read32(priv, CSR_HW_REV); - priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG); - pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id); -} -EXPORT_SYMBOL(iwl_hw_detect); - -int iwl_hw_nic_init(struct iwl_priv *priv) -{ - unsigned long flags; - struct iwl_rx_queue *rxq = &priv->rxq; - int ret; - - /* nic_init */ - spin_lock_irqsave(&priv->lock, flags); - priv->cfg->ops->lib->apm_ops.init(priv); - iwl_write32(priv, CSR_INT_COALESCING, 512 / 32); - spin_unlock_irqrestore(&priv->lock, flags); - - ret = priv->cfg->ops->lib->apm_ops.set_pwr_src(priv, IWL_PWR_SRC_VMAIN); - - priv->cfg->ops->lib->apm_ops.config(priv); - - /* Allocate the RX queue, or reset if it is already allocated */ - if (!rxq->bd) { - ret = iwl_rx_queue_alloc(priv); - if (ret) { - IWL_ERR(priv, "Unable to initialize Rx queue\n"); - return -ENOMEM; - } - } else - iwl_rx_queue_reset(priv, rxq); - - iwl_rx_replenish(priv); - - iwl_rx_init(priv, rxq); - - spin_lock_irqsave(&priv->lock, flags); - - rxq->need_update = 1; - iwl_rx_queue_update_write_ptr(priv, rxq); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Allocate and init all Tx and Command queues */ - ret = iwl_txq_ctx_reset(priv); - if (ret) - return ret; - - set_bit(STATUS_INIT, &priv->status); - - return 0; -} -EXPORT_SYMBOL(iwl_hw_nic_init); - -/* - * QoS support -*/ -void iwl_activate_qos(struct iwl_priv *priv, u8 force) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - priv->qos_data.def_qos_parm.qos_flags = 0; - - if (priv->qos_data.qos_cap.q_AP.queue_request && - !priv->qos_data.qos_cap.q_AP.txop_request) - priv->qos_data.def_qos_parm.qos_flags |= - QOS_PARAM_FLG_TXOP_TYPE_MSK; - if (priv->qos_data.qos_active) - priv->qos_data.def_qos_parm.qos_flags |= - QOS_PARAM_FLG_UPDATE_EDCA_MSK; - - if (priv->current_ht_config.is_ht) - priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK; - - if (force || iwl_is_associated(priv)) { - IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n", - priv->qos_data.qos_active, - priv->qos_data.def_qos_parm.qos_flags); - - iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM, - sizeof(struct iwl_qosparam_cmd), - &priv->qos_data.def_qos_parm, NULL); - } -} -EXPORT_SYMBOL(iwl_activate_qos); - -/* - * AC CWmin CW max AIFSN TXOP Limit TXOP Limit - * (802.11b) (802.11a/g) - * AC_BK 15 1023 7 0 0 - * AC_BE 15 1023 3 0 0 - * AC_VI 7 15 2 6.016ms 3.008ms - * AC_VO 3 7 2 3.264ms 1.504ms - */ -void iwl_reset_qos(struct iwl_priv *priv) -{ - u16 cw_min = 15; - u16 cw_max = 1023; - u8 aifs = 2; - bool is_legacy = false; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->lock, flags); - /* QoS always active in AP and ADHOC mode - * In STA mode wait for association - */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC || - priv->iw_mode == NL80211_IFTYPE_AP) - priv->qos_data.qos_active = 1; - else - priv->qos_data.qos_active = 0; - - /* check for legacy mode */ - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC && - (priv->active_rate & IWL_OFDM_RATES_MASK) == 0) || - (priv->iw_mode == NL80211_IFTYPE_STATION && - (priv->staging_rxon.flags & RXON_FLG_SHORT_SLOT_MSK) == 0)) { - cw_min = 31; - is_legacy = 1; - } - - if (priv->qos_data.qos_active) - aifs = 3; - - /* AC_BE */ - priv->qos_data.def_qos_parm.ac[0].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[0].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[0].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[0].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[0].reserved1 = 0; - - if (priv->qos_data.qos_active) { - /* AC_BK */ - i = 1; - priv->qos_data.def_qos_parm.ac[i].cw_min = cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = 7; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - /* AC_VI */ - i = 2; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(6016); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3008); - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - - /* AC_VO */ - i = 3; - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16((cw_min + 1) / 4 - 1); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16((cw_min + 1) / 2 - 1); - priv->qos_data.def_qos_parm.ac[i].aifsn = 2; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - if (is_legacy) - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(3264); - else - priv->qos_data.def_qos_parm.ac[i].edca_txop = - cpu_to_le16(1504); - } else { - for (i = 1; i < 4; i++) { - priv->qos_data.def_qos_parm.ac[i].cw_min = - cpu_to_le16(cw_min); - priv->qos_data.def_qos_parm.ac[i].cw_max = - cpu_to_le16(cw_max); - priv->qos_data.def_qos_parm.ac[i].aifsn = aifs; - priv->qos_data.def_qos_parm.ac[i].edca_txop = 0; - priv->qos_data.def_qos_parm.ac[i].reserved1 = 0; - } - } - IWL_DEBUG_QOS(priv, "set QoS to default \n"); - - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(iwl_reset_qos); - -#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */ -#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */ -static void iwlcore_init_ht_hw_capab(const struct iwl_priv *priv, - struct ieee80211_sta_ht_cap *ht_info, - enum ieee80211_band band) -{ - u16 max_bit_rate = 0; - u8 rx_chains_num = priv->hw_params.rx_chains_num; - u8 tx_chains_num = priv->hw_params.tx_chains_num; - - ht_info->cap = 0; - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - - ht_info->ht_supported = true; - - if (priv->cfg->ht_greenfield_support) - ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; - ht_info->cap |= IEEE80211_HT_CAP_SGI_20; - ht_info->cap |= (IEEE80211_HT_CAP_SM_PS & - (WLAN_HT_CAP_SM_PS_DISABLED << 2)); - - max_bit_rate = MAX_BIT_RATE_20_MHZ; - if (priv->hw_params.ht40_channel & BIT(band)) { - ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - ht_info->cap |= IEEE80211_HT_CAP_SGI_40; - ht_info->mcs.rx_mask[4] = 0x01; - max_bit_rate = MAX_BIT_RATE_40_MHZ; - } - - if (priv->cfg->mod_params->amsdu_size_8K) - ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU; - - ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF; - ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF; - - ht_info->mcs.rx_mask[0] = 0xFF; - if (rx_chains_num >= 2) - ht_info->mcs.rx_mask[1] = 0xFF; - if (rx_chains_num >= 3) - ht_info->mcs.rx_mask[2] = 0xFF; - - /* Highest supported Rx data rate */ - max_bit_rate *= rx_chains_num; - WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK); - ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate); - - /* Tx MCS capabilities */ - ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - if (tx_chains_num != rx_chains_num) { - ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF; - ht_info->mcs.tx_params |= ((tx_chains_num - 1) << - IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - } -} - -static void iwlcore_init_hw_rates(struct iwl_priv *priv, - struct ieee80211_rate *rates) -{ - int i; - - for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { - rates[i].bitrate = iwl_rates[i].ieee * 5; - rates[i].hw_value = i; /* Rate scaling will work on indexes */ - rates[i].hw_value_short = i; - rates[i].flags = 0; - if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) { - /* - * If CCK != 1M then set short preamble rate flag. - */ - rates[i].flags |= - (iwl_rates[i].plcp == IWL_RATE_1M_PLCP) ? - 0 : IEEE80211_RATE_SHORT_PREAMBLE; - } - } -} - - -/** - * iwlcore_init_geos - Initialize mac80211's geo/channel info based from eeprom - */ -int iwlcore_init_geos(struct iwl_priv *priv) -{ - struct iwl_channel_info *ch; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *channels; - struct ieee80211_channel *geo_ch; - struct ieee80211_rate *rates; - int i = 0; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates || - priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) { - IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n"); - set_bit(STATUS_GEO_CONFIGURED, &priv->status); - return 0; - } - - channels = kzalloc(sizeof(struct ieee80211_channel) * - priv->channel_count, GFP_KERNEL); - if (!channels) - return -ENOMEM; - - rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY), - GFP_KERNEL); - if (!rates) { - kfree(channels); - return -ENOMEM; - } - - /* 5.2GHz channels start after the 2.4GHz channels */ - sband = &priv->bands[IEEE80211_BAND_5GHZ]; - sband->channels = &channels[ARRAY_SIZE(iwl_eeprom_band_1)]; - /* just OFDM */ - sband->bitrates = &rates[IWL_FIRST_OFDM_RATE]; - sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE; - - if (priv->cfg->sku & IWL_SKU_N) - iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, - IEEE80211_BAND_5GHZ); - - sband = &priv->bands[IEEE80211_BAND_2GHZ]; - sband->channels = channels; - /* OFDM & CCK */ - sband->bitrates = rates; - sband->n_bitrates = IWL_RATE_COUNT_LEGACY; - - if (priv->cfg->sku & IWL_SKU_N) - iwlcore_init_ht_hw_capab(priv, &sband->ht_cap, - IEEE80211_BAND_2GHZ); - - priv->ieee_channels = channels; - priv->ieee_rates = rates; - - for (i = 0; i < priv->channel_count; i++) { - ch = &priv->channel_info[i]; - - /* FIXME: might be removed if scan is OK */ - if (!is_channel_valid(ch)) - continue; - - if (is_channel_a_band(ch)) - sband = &priv->bands[IEEE80211_BAND_5GHZ]; - else - sband = &priv->bands[IEEE80211_BAND_2GHZ]; - - geo_ch = &sband->channels[sband->n_channels++]; - - geo_ch->center_freq = - ieee80211_channel_to_frequency(ch->channel); - geo_ch->max_power = ch->max_power_avg; - geo_ch->max_antenna_gain = 0xff; - geo_ch->hw_value = ch->channel; - - if (is_channel_valid(ch)) { - if (!(ch->flags & EEPROM_CHANNEL_IBSS)) - geo_ch->flags |= IEEE80211_CHAN_NO_IBSS; - - if (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) - geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN; - - if (ch->flags & EEPROM_CHANNEL_RADAR) - geo_ch->flags |= IEEE80211_CHAN_RADAR; - - geo_ch->flags |= ch->ht40_extension_channel; - - if (ch->max_power_avg > priv->tx_power_device_lmt) - priv->tx_power_device_lmt = ch->max_power_avg; - } else { - geo_ch->flags |= IEEE80211_CHAN_DISABLED; - } - - IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n", - ch->channel, geo_ch->center_freq, - is_channel_a_band(ch) ? "5.2" : "2.4", - geo_ch->flags & IEEE80211_CHAN_DISABLED ? - "restricted" : "valid", - geo_ch->flags); - } - - if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) && - priv->cfg->sku & IWL_SKU_A) { - IWL_INFO(priv, "Incorrectly detected BG card as ABG. " - "Please send your PCI ID 0x%04X:0x%04X to maintainer.\n", - priv->pci_dev->device, - priv->pci_dev->subsystem_device); - priv->cfg->sku &= ~IWL_SKU_A; - } - - IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n", - priv->bands[IEEE80211_BAND_2GHZ].n_channels, - priv->bands[IEEE80211_BAND_5GHZ].n_channels); - - set_bit(STATUS_GEO_CONFIGURED, &priv->status); - - return 0; -} -EXPORT_SYMBOL(iwlcore_init_geos); - -/* - * iwlcore_free_geos - undo allocations in iwlcore_init_geos - */ -void iwlcore_free_geos(struct iwl_priv *priv) -{ - kfree(priv->ieee_channels); - kfree(priv->ieee_rates); - clear_bit(STATUS_GEO_CONFIGURED, &priv->status); -} -EXPORT_SYMBOL(iwlcore_free_geos); - -static bool is_single_rx_stream(struct iwl_priv *priv) -{ - return !priv->current_ht_config.is_ht || - ((priv->current_ht_config.mcs.rx_mask[1] == 0) && - (priv->current_ht_config.mcs.rx_mask[2] == 0)); -} - -static u8 iwl_is_channel_extension(struct iwl_priv *priv, - enum ieee80211_band band, - u16 channel, u8 extension_chan_offset) -{ - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, band, channel); - if (!is_channel_valid(ch_info)) - return 0; - - if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) - return !(ch_info->ht40_extension_channel & - IEEE80211_CHAN_NO_HT40PLUS); - else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) - return !(ch_info->ht40_extension_channel & - IEEE80211_CHAN_NO_HT40MINUS); - - return 0; -} - -u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, - struct ieee80211_sta_ht_cap *sta_ht_inf) -{ - struct iwl_ht_info *iwl_ht_conf = &priv->current_ht_config; - - if ((!iwl_ht_conf->is_ht) || - (iwl_ht_conf->supported_chan_width != IWL_CHANNEL_WIDTH_40MHZ)) - return 0; - - /* We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40 - * the bit will not set if it is pure 40MHz case - */ - if (sta_ht_inf) { - if (!sta_ht_inf->ht_supported) - return 0; - } -#ifdef CONFIG_IWLWIFI_DEBUG - if (priv->disable_ht40) - return 0; -#endif - return iwl_is_channel_extension(priv, priv->band, - le16_to_cpu(priv->staging_rxon.channel), - iwl_ht_conf->extension_chan_offset); -} -EXPORT_SYMBOL(iwl_is_ht40_tx_allowed); - -static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val) -{ - u16 new_val = 0; - u16 beacon_factor = 0; - - beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val; - new_val = beacon_val / beacon_factor; - - if (!new_val) - new_val = max_beacon_val; - - return new_val; -} - -void iwl_setup_rxon_timing(struct iwl_priv *priv) -{ - u64 tsf; - s32 interval_tm, rem; - unsigned long flags; - struct ieee80211_conf *conf = NULL; - u16 beacon_int; - - conf = ieee80211_get_hw_conf(priv->hw); - - spin_lock_irqsave(&priv->lock, flags); - priv->rxon_timing.timestamp = cpu_to_le64(priv->timestamp); - priv->rxon_timing.listen_interval = cpu_to_le16(conf->listen_interval); - - if (priv->iw_mode == NL80211_IFTYPE_STATION) { - beacon_int = priv->beacon_int; - priv->rxon_timing.atim_window = 0; - } else { - beacon_int = priv->vif->bss_conf.beacon_int; - - /* TODO: we need to get atim_window from upper stack - * for now we set to 0 */ - priv->rxon_timing.atim_window = 0; - } - - beacon_int = iwl_adjust_beacon_interval(beacon_int, - priv->hw_params.max_beacon_itrvl * 1024); - priv->rxon_timing.beacon_interval = cpu_to_le16(beacon_int); - - tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */ - interval_tm = beacon_int * 1024; - rem = do_div(tsf, interval_tm); - priv->rxon_timing.beacon_init_val = cpu_to_le32(interval_tm - rem); - - spin_unlock_irqrestore(&priv->lock, flags); - IWL_DEBUG_ASSOC(priv, - "beacon interval %d beacon timer %d beacon tim %d\n", - le16_to_cpu(priv->rxon_timing.beacon_interval), - le32_to_cpu(priv->rxon_timing.beacon_init_val), - le16_to_cpu(priv->rxon_timing.atim_window)); -} -EXPORT_SYMBOL(iwl_setup_rxon_timing); - -void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt) -{ - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (hw_decrypt) - rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK; - else - rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK; - -} -EXPORT_SYMBOL(iwl_set_rxon_hwcrypto); - -/** - * iwl_check_rxon_cmd - validate RXON structure is valid - * - * NOTE: This is really only useful during development and can eventually - * be #ifdef'd out once the driver is stable and folks aren't actively - * making changes - */ -int iwl_check_rxon_cmd(struct iwl_priv *priv) -{ - int error = 0; - int counter = 1; - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (rxon->flags & RXON_FLG_BAND_24G_MSK) { - error |= le32_to_cpu(rxon->flags & - (RXON_FLG_TGJ_NARROW_BAND_MSK | - RXON_FLG_RADAR_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check 24G fields %d | %d\n", - counter++, error); - } else { - error |= (rxon->flags & RXON_FLG_SHORT_SLOT_MSK) ? - 0 : le32_to_cpu(RXON_FLG_SHORT_SLOT_MSK); - if (error) - IWL_WARN(priv, "check 52 fields %d | %d\n", - counter++, error); - error |= le32_to_cpu(rxon->flags & RXON_FLG_CCK_MSK); - if (error) - IWL_WARN(priv, "check 52 CCK %d | %d\n", - counter++, error); - } - error |= (rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1; - if (error) - IWL_WARN(priv, "check mac addr %d | %d\n", counter++, error); - - /* make sure basic rates 6Mbps and 1Mbps are supported */ - error |= (((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0) && - ((rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0)); - if (error) - IWL_WARN(priv, "check basic rate %d | %d\n", counter++, error); - - error |= (le16_to_cpu(rxon->assoc_id) > 2007); - if (error) - IWL_WARN(priv, "check assoc id %d | %d\n", counter++, error); - - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)); - if (error) - IWL_WARN(priv, "check CCK and short slot %d | %d\n", - counter++, error); - - error |= ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) - == (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)); - if (error) - IWL_WARN(priv, "check CCK & auto detect %d | %d\n", - counter++, error); - - error |= ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK | - RXON_FLG_TGG_PROTECT_MSK)) == RXON_FLG_TGG_PROTECT_MSK); - if (error) - IWL_WARN(priv, "check TGG and auto detect %d | %d\n", - counter++, error); - - if (error) - IWL_WARN(priv, "Tuning to channel %d\n", - le16_to_cpu(rxon->channel)); - - if (error) { - IWL_ERR(priv, "Not a valid iwl_rxon_assoc_cmd field values\n"); - return -1; - } - return 0; -} -EXPORT_SYMBOL(iwl_check_rxon_cmd); - -/** - * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed - * @priv: staging_rxon is compared to active_rxon - * - * If the RXON structure is changing enough to require a new tune, - * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that - * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required. - */ -int iwl_full_rxon_required(struct iwl_priv *priv) -{ - - /* These items are only settable from the full RXON command */ - if (!(iwl_is_associated(priv)) || - compare_ether_addr(priv->staging_rxon.bssid_addr, - priv->active_rxon.bssid_addr) || - compare_ether_addr(priv->staging_rxon.node_addr, - priv->active_rxon.node_addr) || - compare_ether_addr(priv->staging_rxon.wlap_bssid_addr, - priv->active_rxon.wlap_bssid_addr) || - (priv->staging_rxon.dev_type != priv->active_rxon.dev_type) || - (priv->staging_rxon.channel != priv->active_rxon.channel) || - (priv->staging_rxon.air_propagation != - priv->active_rxon.air_propagation) || - (priv->staging_rxon.ofdm_ht_single_stream_basic_rates != - priv->active_rxon.ofdm_ht_single_stream_basic_rates) || - (priv->staging_rxon.ofdm_ht_dual_stream_basic_rates != - priv->active_rxon.ofdm_ht_dual_stream_basic_rates) || - (priv->staging_rxon.ofdm_ht_triple_stream_basic_rates != - priv->active_rxon.ofdm_ht_triple_stream_basic_rates) || - (priv->staging_rxon.assoc_id != priv->active_rxon.assoc_id)) - return 1; - - /* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can - * be updated with the RXON_ASSOC command -- however only some - * flag transitions are allowed using RXON_ASSOC */ - - /* Check if we are not switching bands */ - if ((priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) != - (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK)) - return 1; - - /* Check if we are switching association toggle */ - if ((priv->staging_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) != - (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK)) - return 1; - - return 0; -} -EXPORT_SYMBOL(iwl_full_rxon_required); - -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv) -{ - int i; - int rate_mask; - - /* Set rate mask*/ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) - rate_mask = priv->active_rate_basic & IWL_CCK_RATES_MASK; - else - rate_mask = priv->active_rate_basic & IWL_OFDM_RATES_MASK; - - /* Find lowest valid rate */ - for (i = IWL_RATE_1M_INDEX; i != IWL_RATE_INVALID; - i = iwl_rates[i].next_ieee) { - if (rate_mask & (1 << i)) - return iwl_rates[i].plcp; - } - - /* No valid rate was found. Assign the lowest one */ - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) - return IWL_RATE_1M_PLCP; - else - return IWL_RATE_6M_PLCP; -} -EXPORT_SYMBOL(iwl_rate_get_lowest_plcp); - -void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info) -{ - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (!ht_info->is_ht) { - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | - RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | - RXON_FLG_HT40_PROT_MSK | - RXON_FLG_HT_PROT_MSK); - return; - } - - /* FIXME: if the definition of ht_protection changed, the "translation" - * will be needed for rxon->flags - */ - rxon->flags |= cpu_to_le32(ht_info->ht_protection << RXON_FLG_HT_OPERATING_MODE_POS); - - /* Set up channel bandwidth: - * 20 MHz only, 20/40 mixed or pure 40 if ht40 ok */ - /* clear the HT channel mode before set the mode */ - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | - RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); - if (iwl_is_ht40_tx_allowed(priv, NULL)) { - /* pure ht40 */ - if (ht_info->ht_protection == IEEE80211_HT_OP_MODE_PROTECTION_20MHZ) { - rxon->flags |= RXON_FLG_CHANNEL_MODE_PURE_40; - /* Note: control channel is opposite of extension channel */ - switch (ht_info->extension_chan_offset) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - rxon->flags &= ~RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; - break; - } - } else { - /* Note: control channel is opposite of extension channel */ - switch (ht_info->extension_chan_offset) { - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - rxon->flags &= ~(RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK); - rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; - break; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - rxon->flags |= RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK; - rxon->flags |= RXON_FLG_CHANNEL_MODE_MIXED; - break; - case IEEE80211_HT_PARAM_CHA_SEC_NONE: - default: - /* channel location only valid if in Mixed mode */ - IWL_ERR(priv, "invalid extension channel offset\n"); - break; - } - } - } else { - rxon->flags |= RXON_FLG_CHANNEL_MODE_LEGACY; - } - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - IWL_DEBUG_ASSOC(priv, "supported HT rate 0x%X 0x%X 0x%X " - "rxon flags 0x%X operation mode :0x%X " - "extension channel offset 0x%x\n", - ht_info->mcs.rx_mask[0], - ht_info->mcs.rx_mask[1], - ht_info->mcs.rx_mask[2], - le32_to_cpu(rxon->flags), ht_info->ht_protection, - ht_info->extension_chan_offset); - return; -} -EXPORT_SYMBOL(iwl_set_rxon_ht); - -#define IWL_NUM_RX_CHAINS_MULTIPLE 3 -#define IWL_NUM_RX_CHAINS_SINGLE 2 -#define IWL_NUM_IDLE_CHAINS_DUAL 2 -#define IWL_NUM_IDLE_CHAINS_SINGLE 1 - -/* Determine how many receiver/antenna chains to use. - * More provides better reception via diversity. Fewer saves power. - * MIMO (dual stream) requires at least 2, but works better with 3. - * This does not determine *which* chains to use, just how many. - */ -static int iwl_get_active_rx_chain_count(struct iwl_priv *priv) -{ - bool is_single = is_single_rx_stream(priv); - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); - - /* # of Rx chains to use when expecting MIMO. */ - if (is_single || (!is_cam && (priv->current_ht_config.sm_ps == - WLAN_HT_CAP_SM_PS_STATIC))) - return IWL_NUM_RX_CHAINS_SINGLE; - else - return IWL_NUM_RX_CHAINS_MULTIPLE; -} - -static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt) -{ - int idle_cnt; - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); - /* # Rx chains when idling and maybe trying to save power */ - switch (priv->current_ht_config.sm_ps) { - case WLAN_HT_CAP_SM_PS_STATIC: - case WLAN_HT_CAP_SM_PS_DYNAMIC: - idle_cnt = (is_cam) ? IWL_NUM_IDLE_CHAINS_DUAL : - IWL_NUM_IDLE_CHAINS_SINGLE; - break; - case WLAN_HT_CAP_SM_PS_DISABLED: - idle_cnt = (is_cam) ? active_cnt : IWL_NUM_IDLE_CHAINS_SINGLE; - break; - case WLAN_HT_CAP_SM_PS_INVALID: - default: - IWL_ERR(priv, "invalid mimo ps mode %d\n", - priv->current_ht_config.sm_ps); - WARN_ON(1); - idle_cnt = -1; - break; - } - return idle_cnt; -} - -/* up to 4 chains */ -static u8 iwl_count_chain_bitmap(u32 chain_bitmap) -{ - u8 res; - res = (chain_bitmap & BIT(0)) >> 0; - res += (chain_bitmap & BIT(1)) >> 1; - res += (chain_bitmap & BIT(2)) >> 2; - res += (chain_bitmap & BIT(4)) >> 4; - return res; -} - -/** - * iwl_is_monitor_mode - Determine if interface in monitor mode - * - * priv->iw_mode is set in add_interface, but add_interface is - * never called for monitor mode. The only way mac80211 informs us about - * monitor mode is through configuring filters (call to configure_filter). - */ -bool iwl_is_monitor_mode(struct iwl_priv *priv) -{ - return !!(priv->staging_rxon.filter_flags & RXON_FILTER_PROMISC_MSK); -} -EXPORT_SYMBOL(iwl_is_monitor_mode); - -/** - * iwl_set_rxon_chain - Set up Rx chain usage in "staging" RXON image - * - * Selects how many and which Rx receivers/antennas/chains to use. - * This should not be used for scan command ... it puts data in wrong place. - */ -void iwl_set_rxon_chain(struct iwl_priv *priv) -{ - bool is_single = is_single_rx_stream(priv); - bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status); - u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt; - u32 active_chains; - u16 rx_chain; - - /* Tell uCode which antennas are actually connected. - * Before first association, we assume all antennas are connected. - * Just after first association, iwl_chain_noise_calibration() - * checks which antennas actually *are* connected. */ - if (priv->chain_noise_data.active_chains) - active_chains = priv->chain_noise_data.active_chains; - else - active_chains = priv->hw_params.valid_rx_ant; - - rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS; - - /* How many receivers should we use? */ - active_rx_cnt = iwl_get_active_rx_chain_count(priv); - idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt); - - - /* correct rx chain count according hw settings - * and chain noise calibration - */ - valid_rx_cnt = iwl_count_chain_bitmap(active_chains); - if (valid_rx_cnt < active_rx_cnt) - active_rx_cnt = valid_rx_cnt; - - if (valid_rx_cnt < idle_rx_cnt) - idle_rx_cnt = valid_rx_cnt; - - rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS; - rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS; - - /* copied from 'iwl_bg_request_scan()' */ - /* Force use of chains B and C (0x6) for Rx for 4965 - * Avoid A (0x1) because of its off-channel reception on A-band. - * MIMO is not used here, but value is required */ - if (iwl_is_monitor_mode(priv) && - !(priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) && - ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)) { - rx_chain = ANT_ABC << RXON_RX_CHAIN_VALID_POS; - rx_chain |= ANT_BC << RXON_RX_CHAIN_FORCE_SEL_POS; - rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; - rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; - } - - priv->staging_rxon.rx_chain = cpu_to_le16(rx_chain); - - if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam) - priv->staging_rxon.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK; - else - priv->staging_rxon.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK; - - IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n", - priv->staging_rxon.rx_chain, - active_rx_cnt, idle_rx_cnt); - - WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 || - active_rx_cnt < idle_rx_cnt); -} -EXPORT_SYMBOL(iwl_set_rxon_chain); - -/** - * iwl_set_rxon_channel - Set the phymode and channel values in staging RXON - * @phymode: MODE_IEEE80211A sets to 5.2GHz; all else set to 2.4GHz - * @channel: Any channel valid for the requested phymode - - * In addition to setting the staging RXON, priv->phymode is also set. - * - * NOTE: Does not commit to the hardware; it sets appropriate bit fields - * in the staging RXON flag structure based on the phymode - */ -int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch) -{ - enum ieee80211_band band = ch->band; - u16 channel = ieee80211_frequency_to_channel(ch->center_freq); - - if (!iwl_get_channel_info(priv, band, channel)) { - IWL_DEBUG_INFO(priv, "Could not set channel to %d [%d]\n", - channel, band); - return -EINVAL; - } - - if ((le16_to_cpu(priv->staging_rxon.channel) == channel) && - (priv->band == band)) - return 0; - - priv->staging_rxon.channel = cpu_to_le16(channel); - if (band == IEEE80211_BAND_5GHZ) - priv->staging_rxon.flags &= ~RXON_FLG_BAND_24G_MSK; - else - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - - priv->band = band; - - IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band); - - return 0; -} -EXPORT_SYMBOL(iwl_set_rxon_channel); - -void iwl_set_flags_for_band(struct iwl_priv *priv, - enum ieee80211_band band) -{ - if (band == IEEE80211_BAND_5GHZ) { - priv->staging_rxon.flags &= - ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK - | RXON_FLG_CCK_MSK); - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - } else { - /* Copied from iwl_post_associate() */ - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - priv->staging_rxon.flags |= RXON_FLG_BAND_24G_MSK; - priv->staging_rxon.flags |= RXON_FLG_AUTO_DETECT_MSK; - priv->staging_rxon.flags &= ~RXON_FLG_CCK_MSK; - } -} - -/* - * initialize rxon structure with default values from eeprom - */ -void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode) -{ - const struct iwl_channel_info *ch_info; - - memset(&priv->staging_rxon, 0, sizeof(priv->staging_rxon)); - - switch (mode) { - case NL80211_IFTYPE_AP: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_AP; - break; - - case NL80211_IFTYPE_STATION: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_ESS; - priv->staging_rxon.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; - break; - - case NL80211_IFTYPE_ADHOC: - priv->staging_rxon.dev_type = RXON_DEV_TYPE_IBSS; - priv->staging_rxon.flags = RXON_FLG_SHORT_PREAMBLE_MSK; - priv->staging_rxon.filter_flags = RXON_FILTER_BCON_AWARE_MSK | - RXON_FILTER_ACCEPT_GRP_MSK; - break; - - default: - IWL_ERR(priv, "Unsupported interface type %d\n", mode); - break; - } - -#if 0 - /* TODO: Figure out when short_preamble would be set and cache from - * that */ - if (!hw_to_local(priv->hw)->short_preamble) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; -#endif - - ch_info = iwl_get_channel_info(priv, priv->band, - le16_to_cpu(priv->active_rxon.channel)); - - if (!ch_info) - ch_info = &priv->channel_info[0]; - - /* - * in some case A channels are all non IBSS - * in this case force B/G channel - */ - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) && - !(is_channel_ibss(ch_info))) - ch_info = &priv->channel_info[0]; - - priv->staging_rxon.channel = cpu_to_le16(ch_info->channel); - priv->band = ch_info->band; - - iwl_set_flags_for_band(priv, priv->band); - - priv->staging_rxon.ofdm_basic_rates = - (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; - priv->staging_rxon.cck_basic_rates = - (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - - /* clear both MIX and PURE40 mode flag */ - priv->staging_rxon.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED | - RXON_FLG_CHANNEL_MODE_PURE_40); - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - memcpy(priv->staging_rxon.wlap_bssid_addr, priv->mac_addr, ETH_ALEN); - priv->staging_rxon.ofdm_ht_single_stream_basic_rates = 0xff; - priv->staging_rxon.ofdm_ht_dual_stream_basic_rates = 0xff; - priv->staging_rxon.ofdm_ht_triple_stream_basic_rates = 0xff; -} -EXPORT_SYMBOL(iwl_connection_init_rx_config); - -static void iwl_set_rate(struct iwl_priv *priv) -{ - const struct ieee80211_supported_band *hw = NULL; - struct ieee80211_rate *rate; - int i; - - hw = iwl_get_hw_mode(priv, priv->band); - if (!hw) { - IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n"); - return; - } - - priv->active_rate = 0; - priv->active_rate_basic = 0; - - for (i = 0; i < hw->n_bitrates; i++) { - rate = &(hw->bitrates[i]); - if (rate->hw_value < IWL_RATE_COUNT_LEGACY) - priv->active_rate |= (1 << rate->hw_value); - } - - IWL_DEBUG_RATE(priv, "Set active_rate = %0x, active_rate_basic = %0x\n", - priv->active_rate, priv->active_rate_basic); - - /* - * If a basic rate is configured, then use it (adding IWL_RATE_1M_MASK) - * otherwise set it to the default of all CCK rates and 6, 12, 24 for - * OFDM - */ - if (priv->active_rate_basic & IWL_CCK_BASIC_RATES_MASK) - priv->staging_rxon.cck_basic_rates = - ((priv->active_rate_basic & - IWL_CCK_RATES_MASK) >> IWL_FIRST_CCK_RATE) & 0xF; - else - priv->staging_rxon.cck_basic_rates = - (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF; - - if (priv->active_rate_basic & IWL_OFDM_BASIC_RATES_MASK) - priv->staging_rxon.ofdm_basic_rates = - ((priv->active_rate_basic & - (IWL_OFDM_BASIC_RATES_MASK | IWL_RATE_6M_MASK)) >> - IWL_FIRST_OFDM_RATE) & 0xFF; - else - priv->staging_rxon.ofdm_basic_rates = - (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF; -} - -void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon; - struct iwl_csa_notification *csa = &(pkt->u.csa_notif); - IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n", - le16_to_cpu(csa->channel), le32_to_cpu(csa->status)); - rxon->channel = csa->channel; - priv->staging_rxon.channel = csa->channel; -} -EXPORT_SYMBOL(iwl_rx_csa); - -#ifdef CONFIG_IWLWIFI_DEBUG -static void iwl_print_rx_config_cmd(struct iwl_priv *priv) -{ - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - IWL_DEBUG_RADIO(priv, "RX CONFIG:\n"); - iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon)); - IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n", le16_to_cpu(rxon->channel)); - IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags)); - IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n", - le32_to_cpu(rxon->filter_flags)); - IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type); - IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n", - rxon->ofdm_basic_rates); - IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n", rxon->cck_basic_rates); - IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr); - IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr); - IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id)); -} -#endif -/** - * iwl_irq_handle_error - called for HW or SW error interrupt from card - */ -void iwl_irq_handle_error(struct iwl_priv *priv) -{ - /* Set the FW error flag -- cleared on iwl_down */ - set_bit(STATUS_FW_ERROR, &priv->status); - - /* Cancel currently queued command. */ - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) { - priv->cfg->ops->lib->dump_nic_error_log(priv); - priv->cfg->ops->lib->dump_nic_event_log(priv); - iwl_print_rx_config_cmd(priv); - } -#endif - - wake_up_interruptible(&priv->wait_command_queue); - - /* Keep the restart process from trying to send host - * commands by clearing the INIT status bit */ - clear_bit(STATUS_READY, &priv->status); - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG(priv, IWL_DL_FW_ERRORS, - "Restarting adapter due to uCode error.\n"); - - if (priv->cfg->mod_params->restart_fw) - queue_work(priv->workqueue, &priv->restart); - } -} -EXPORT_SYMBOL(iwl_irq_handle_error); - -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct iwl_priv *priv = hw->priv; - __le32 *filter_flags = &priv->staging_rxon.filter_flags; - - IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n", - changed_flags, *total_flags); - - if (changed_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) { - if (*total_flags & (FIF_OTHER_BSS | FIF_PROMISC_IN_BSS)) - *filter_flags |= RXON_FILTER_PROMISC_MSK; - else - *filter_flags &= ~RXON_FILTER_PROMISC_MSK; - } - if (changed_flags & FIF_ALLMULTI) { - if (*total_flags & FIF_ALLMULTI) - *filter_flags |= RXON_FILTER_ACCEPT_GRP_MSK; - else - *filter_flags &= ~RXON_FILTER_ACCEPT_GRP_MSK; - } - if (changed_flags & FIF_CONTROL) { - if (*total_flags & FIF_CONTROL) - *filter_flags |= RXON_FILTER_CTL2HOST_MSK; - else - *filter_flags &= ~RXON_FILTER_CTL2HOST_MSK; - } - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - *filter_flags |= RXON_FILTER_BCON_AWARE_MSK; - else - *filter_flags &= ~RXON_FILTER_BCON_AWARE_MSK; - } - - /* We avoid iwl_commit_rxon here to commit the new filter flags - * since mac80211 will call ieee80211_hw_config immediately. - * (mc_list is not supported at this time). Otherwise, we need to - * queue a background iwl_commit_rxon work. - */ - - *total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS | - FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL; -} -EXPORT_SYMBOL(iwl_configure_filter); - -int iwl_setup_mac(struct iwl_priv *priv) -{ - int ret; - struct ieee80211_hw *hw = priv->hw; - hw->rate_control_algorithm = "iwl-agn-rs"; - - /* Tell mac80211 our characteristics */ - hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_AMPDU_AGGREGATION | - IEEE80211_HW_SPECTRUM_MGMT; - - if (!priv->cfg->broken_powersave) - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); - - hw->wiphy->custom_regulatory = true; - - /* Firmware does not support this */ - hw->wiphy->disable_beacon_hints = true; - - /* - * For now, disable PS by default because it affects - * RX performance significantly. - */ - hw->wiphy->ps_default = false; - - hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX; - /* we create the 802.11 header and a zero-length SSID element */ - hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; - - /* Default value; 4 EDCA QOS priorities */ - hw->queues = 4; - - hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &priv->bands[IEEE80211_BAND_2GHZ]; - if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &priv->bands[IEEE80211_BAND_5GHZ]; - - ret = ieee80211_register_hw(priv->hw); - if (ret) { - IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); - return ret; - } - priv->mac80211_registered = 1; - - return 0; -} -EXPORT_SYMBOL(iwl_setup_mac); - -int iwl_set_hw_params(struct iwl_priv *priv) -{ - priv->hw_params.max_rxq_size = RX_QUEUE_SIZE; - priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG; - if (priv->cfg->mod_params->amsdu_size_8K) - priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K; - else - priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K; - priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256; - - priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL; - - if (priv->cfg->mod_params->disable_11n) - priv->cfg->sku &= ~IWL_SKU_N; - - /* Device-specific setup */ - return priv->cfg->ops->lib->set_hw_params(priv); -} -EXPORT_SYMBOL(iwl_set_hw_params); - -int iwl_init_drv(struct iwl_priv *priv) -{ - int ret; - - priv->ibss_beacon = NULL; - - spin_lock_init(&priv->lock); - spin_lock_init(&priv->sta_lock); - spin_lock_init(&priv->hcmd_lock); - - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); - - /* Clear the driver's (not device's) station table */ - iwl_clear_stations_table(priv); - - priv->data_retry_limit = -1; - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; - priv->band = IEEE80211_BAND_2GHZ; - - priv->iw_mode = NL80211_IFTYPE_STATION; - - priv->current_ht_config.sm_ps = WLAN_HT_CAP_SM_PS_DISABLED; - - /* Choose which receivers/antennas to use */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - iwl_init_scan_params(priv); - - iwl_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - - priv->rates_mask = IWL_RATES_MASK; - /* Set the tx_power_user_lmt to the lowest power level - * this value will get overwritten by channel max power avg - * from eeprom */ - priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MIN; - - ret = iwl_init_channel_map(priv); - if (ret) { - IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); - goto err; - } - - ret = iwlcore_init_geos(priv); - if (ret) { - IWL_ERR(priv, "initializing geos failed: %d\n", ret); - goto err_free_channel_map; - } - iwlcore_init_hw_rates(priv, priv->ieee_rates); - - return 0; - -err_free_channel_map: - iwl_free_channel_map(priv); -err: - return ret; -} -EXPORT_SYMBOL(iwl_init_drv); - -int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) -{ - int ret = 0; - s8 prev_tx_power = priv->tx_power_user_lmt; - - if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) { - IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n", - tx_power, - IWL_TX_POWER_TARGET_POWER_MIN); - return -EINVAL; - } - - if (tx_power > priv->tx_power_device_lmt) { - IWL_WARN(priv, - "Requested user TXPOWER %d above upper limit %d.\n", - tx_power, priv->tx_power_device_lmt); - return -EINVAL; - } - - if (priv->tx_power_user_lmt != tx_power) - force = true; - - /* if nic is not up don't send command */ - if (iwl_is_ready_rf(priv)) { - priv->tx_power_user_lmt = tx_power; - if (force && priv->cfg->ops->lib->send_tx_power) - ret = priv->cfg->ops->lib->send_tx_power(priv); - else if (!priv->cfg->ops->lib->send_tx_power) - ret = -EOPNOTSUPP; - /* - * if fail to set tx_power, restore the orig. tx power - */ - if (ret) - priv->tx_power_user_lmt = prev_tx_power; - } - - /* - * Even this is an async host command, the command - * will always report success from uCode - * So once driver can placing the command into the queue - * successfully, driver can use priv->tx_power_user_lmt - * to reflect the current tx power - */ - return ret; -} -EXPORT_SYMBOL(iwl_set_tx_power); - -void iwl_uninit_drv(struct iwl_priv *priv) -{ - iwl_calib_free_results(priv); - iwlcore_free_geos(priv); - iwl_free_channel_map(priv); - kfree(priv->scan); -} -EXPORT_SYMBOL(iwl_uninit_drv); - -#define ICT_COUNT (PAGE_SIZE/sizeof(u32)) - -/* Free dram table */ -void iwl_free_isr_ict(struct iwl_priv *priv) -{ - if (priv->ict_tbl_vir) { - dma_free_coherent(&priv->pci_dev->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - priv->ict_tbl_vir, priv->ict_tbl_dma); - priv->ict_tbl_vir = NULL; - } -} -EXPORT_SYMBOL(iwl_free_isr_ict); - - -/* allocate dram shared table it is a PAGE_SIZE aligned - * also reset all data related to ICT table interrupt. - */ -int iwl_alloc_isr_ict(struct iwl_priv *priv) -{ - - if (priv->cfg->use_isr_legacy) - return 0; - /* allocate shrared data table */ - priv->ict_tbl_vir = dma_alloc_coherent(&priv->pci_dev->dev, - (sizeof(u32) * ICT_COUNT) + PAGE_SIZE, - &priv->ict_tbl_dma, GFP_KERNEL); - if (!priv->ict_tbl_vir) - return -ENOMEM; - - /* align table to PAGE_SIZE boundry */ - priv->aligned_ict_tbl_dma = ALIGN(priv->ict_tbl_dma, PAGE_SIZE); - - IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n", - (unsigned long long)priv->ict_tbl_dma, - (unsigned long long)priv->aligned_ict_tbl_dma, - (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); - - priv->ict_tbl = priv->ict_tbl_vir + - (priv->aligned_ict_tbl_dma - priv->ict_tbl_dma); - - IWL_DEBUG_ISR(priv, "ict vir addr %p vir aligned %p diff %d\n", - priv->ict_tbl, priv->ict_tbl_vir, - (int)(priv->aligned_ict_tbl_dma - priv->ict_tbl_dma)); - - /* reset table and index to all 0 */ - memset(priv->ict_tbl_vir,0, (sizeof(u32) * ICT_COUNT) + PAGE_SIZE); - priv->ict_index = 0; - - /* add periodic RX interrupt */ - priv->inta_mask |= CSR_INT_BIT_RX_PERIODIC; - return 0; -} -EXPORT_SYMBOL(iwl_alloc_isr_ict); - -/* Device is going up inform it about using ICT interrupt table, - * also we need to tell the driver to start using ICT interrupt. - */ -int iwl_reset_ict(struct iwl_priv *priv) -{ - u32 val; - unsigned long flags; - - if (!priv->ict_tbl_vir) - return 0; - - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - - memset(&priv->ict_tbl[0], 0, sizeof(u32) * ICT_COUNT); - - val = priv->aligned_ict_tbl_dma >> PAGE_SHIFT; - - val |= CSR_DRAM_INT_TBL_ENABLE; - val |= CSR_DRAM_INIT_TBL_WRAP_CHECK; - - IWL_DEBUG_ISR(priv, "CSR_DRAM_INT_TBL_REG =0x%X " - "aligned dma address %Lx\n", - val, (unsigned long long)priv->aligned_ict_tbl_dma); - - iwl_write32(priv, CSR_DRAM_INT_TBL_REG, val); - priv->use_ict = true; - priv->ict_index = 0; - iwl_write32(priv, CSR_INT, priv->inta_mask); - iwl_enable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} -EXPORT_SYMBOL(iwl_reset_ict); - -/* Device is going down disable ict interrupt usage */ -void iwl_disable_ict(struct iwl_priv *priv) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - priv->use_ict = false; - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(iwl_disable_ict); - -/* interrupt handler using ict table, with this interrupt driver will - * stop using INTA register to get device's interrupt, reading this register - * is expensive, device will write interrupts in ICT dram table, increment - * index then will fire interrupt to driver, driver will OR all ICT table - * entries from current index up to table entry with 0 value. the result is - * the interrupt we need to service, driver will set the entries back to 0 and - * set index. - */ -irqreturn_t iwl_isr_ict(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - u32 val = 0; - - if (!priv) - return IRQ_NONE; - - /* dram interrupt table not set yet, - * use legacy interrupt. - */ - if (!priv->use_ict) - return iwl_isr(irq, data); - - spin_lock(&priv->lock); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. - */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!priv->ict_tbl[priv->ict_index]) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); - goto none; - } - - /* read all entries that not 0 start with ict_index */ - while (priv->ict_tbl[priv->ict_index]) { - - val |= le32_to_cpu(priv->ict_tbl[priv->ict_index]); - IWL_DEBUG_ISR(priv, "ICT index %d value 0x%08X\n", - priv->ict_index, - le32_to_cpu(priv->ict_tbl[priv->ict_index])); - priv->ict_tbl[priv->ict_index] = 0; - priv->ict_index = iwl_queue_inc_wrap(priv->ict_index, - ICT_COUNT); - - } - - /* We should not get this value, just ignore it. */ - if (val == 0xffffffff) - val = 0; - - inta = (0xff & val) | ((0xff00 & val) << 16); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x ict 0x%08x\n", - inta, inta_mask, val); - - inta &= priv->inta_mask; - priv->inta |= inta; - - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) { - /* Allow interrupt if was disabled by this handler and - * no tasklet was schedules, We should not enable interrupt, - * tasklet will enable it. - */ - iwl_enable_interrupts(priv); - } - - spin_unlock(&priv->lock); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. - * only Re-enable if disabled by irq. - */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) - iwl_enable_interrupts(priv); - - spin_unlock(&priv->lock); - return IRQ_NONE; -} -EXPORT_SYMBOL(iwl_isr_ict); - - -static irqreturn_t iwl_isr(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_fh; -#endif - if (!priv) - return IRQ_NONE; - - spin_lock(&priv->lock); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!inta) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0\n"); - goto none; - } - - if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared. It might have already raised - * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); - goto unplugged; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, " - "fh 0x%08x\n", inta, inta_mask, inta_fh); - } -#endif - - priv->inta |= inta; - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta)) - tasklet_schedule(&priv->irq_tasklet); - else if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) - iwl_enable_interrupts(priv); - - unplugged: - spin_unlock(&priv->lock); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if diabled by irq and no schedules tasklet. */ - if (test_bit(STATUS_INT_ENABLED, &priv->status) && !priv->inta) - iwl_enable_interrupts(priv); - - spin_unlock(&priv->lock); - return IRQ_NONE; -} - -irqreturn_t iwl_isr_legacy(int irq, void *data) -{ - struct iwl_priv *priv = data; - u32 inta, inta_mask; - u32 inta_fh; - if (!priv) - return IRQ_NONE; - - spin_lock(&priv->lock); - - /* Disable (but don't clear!) interrupts here to avoid - * back-to-back ISRs and sporadic interrupts from our NIC. - * If we have something to service, the tasklet will re-enable ints. - * If we *don't* have something, we'll re-enable before leaving here. */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* Discover which interrupts are active/pending */ - inta = iwl_read32(priv, CSR_INT); - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - - /* Ignore interrupt if there's nothing in NIC to service. - * This may be due to IRQ shared with another device, - * or due to sporadic interrupts thrown from our NIC. */ - if (!inta && !inta_fh) { - IWL_DEBUG_ISR(priv, "Ignore interrupt, inta == 0, inta_fh == 0\n"); - goto none; - } - - if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) { - /* Hardware disappeared. It might have already raised - * an interrupt */ - IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta); - goto unplugged; - } - - IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", - inta, inta_mask, inta_fh); - - inta &= ~CSR_INT_BIT_SCD; - - /* iwl_irq_tasklet() will service interrupts and re-enable them */ - if (likely(inta || inta_fh)) - tasklet_schedule(&priv->irq_tasklet); - - unplugged: - spin_unlock(&priv->lock); - return IRQ_HANDLED; - - none: - /* re-enable interrupts here since we don't have anything to service. */ - /* only Re-enable if diabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - spin_unlock(&priv->lock); - return IRQ_NONE; -} -EXPORT_SYMBOL(iwl_isr_legacy); - -int iwl_send_bt_config(struct iwl_priv *priv) -{ - struct iwl_bt_cmd bt_cmd = { - .flags = 3, - .lead_time = 0xAA, - .max_kill = 1, - .kill_ack_mask = 0, - .kill_cts_mask = 0, - }; - - return iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, - sizeof(struct iwl_bt_cmd), &bt_cmd); -} -EXPORT_SYMBOL(iwl_send_bt_config); - -int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags) -{ - u32 stat_flags = 0; - struct iwl_host_cmd cmd = { - .id = REPLY_STATISTICS_CMD, - .flags = flags, - .len = sizeof(stat_flags), - .data = (u8 *) &stat_flags, - }; - return iwl_send_cmd(priv, &cmd); -} -EXPORT_SYMBOL(iwl_send_statistics_request); - -/** - * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host, - * using sample data 100 bytes apart. If these sample points are good, - * it's a pretty good bet that everything between them is good, too. - */ -static int iwlcore_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) -{ - u32 val; - int ret = 0; - u32 errcnt = 0; - u32 i; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - i + IWL49_RTC_INST_LOWER_BOUND); - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - ret = -EIO; - errcnt++; - if (errcnt >= 3) - break; - } - } - - return ret; -} - -/** - * iwlcore_verify_inst_full - verify runtime uCode image in card vs. host, - * looking at all data. - */ -static int iwl_verify_inst_full(struct iwl_priv *priv, __le32 *image, - u32 len) -{ - u32 val; - u32 save_len = len; - int ret = 0; - u32 errcnt; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - IWL49_RTC_INST_LOWER_BOUND); - - errcnt = 0; - for (; len > 0; len -= sizeof(u32), image++) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "uCode INST section is invalid at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - save_len - len, val, le32_to_cpu(*image)); - ret = -EIO; - errcnt++; - if (errcnt >= 20) - break; - } - } - - if (!errcnt) - IWL_DEBUG_INFO(priv, - "ucode image in INSTRUCTION memory is good\n"); - - return ret; -} - -/** - * iwl_verify_ucode - determine which instruction image is in SRAM, - * and verify its contents - */ -int iwl_verify_ucode(struct iwl_priv *priv) -{ - __le32 *image; - u32 len; - int ret; - - /* Try bootstrap */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); - return 0; - } - - /* Try initialize */ - image = (__le32 *)priv->ucode_init.v_addr; - len = priv->ucode_init.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); - return 0; - } - - /* Try runtime/protocol */ - image = (__le32 *)priv->ucode_code.v_addr; - len = priv->ucode_code.len; - ret = iwlcore_verify_inst_sparse(priv, image, len); - if (!ret) { - IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); - return 0; - } - - IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - - /* Since nothing seems to match, show first several data entries in - * instruction SRAM, so maybe visual inspection will give a clue. - * Selection of bootstrap image (vs. other images) is arbitrary. */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - ret = iwl_verify_inst_full(priv, image, len); - - return ret; -} -EXPORT_SYMBOL(iwl_verify_ucode); - - -void iwl_rf_kill_ct_config(struct iwl_priv *priv) -{ - struct iwl_ct_kill_config cmd; - struct iwl_ct_kill_throttling_config adv_cmd; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&priv->lock, flags); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - spin_unlock_irqrestore(&priv->lock, flags); - priv->thermal_throttle.ct_kill_toggle = false; - - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_1000: - case CSR_HW_REV_TYPE_6x00: - case CSR_HW_REV_TYPE_6x50: - adv_cmd.critical_temperature_enter = - cpu_to_le32(priv->hw_params.ct_kill_threshold); - adv_cmd.critical_temperature_exit = - cpu_to_le32(priv->hw_params.ct_kill_exit_threshold); - - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, - sizeof(adv_cmd), &adv_cmd); - if (ret) - IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); - else - IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature enter is %d," - "exit is %d\n", - priv->hw_params.ct_kill_threshold, - priv->hw_params.ct_kill_exit_threshold); - break; - default: - cmd.critical_temperature_R = - cpu_to_le32(priv->hw_params.ct_kill_threshold); - - ret = iwl_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD, - sizeof(cmd), &cmd); - if (ret) - IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n"); - else - IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD " - "succeeded, " - "critical temperature is %d\n", - priv->hw_params.ct_kill_threshold); - break; - } -} -EXPORT_SYMBOL(iwl_rf_kill_ct_config); - - -/* - * CARD_STATE_CMD - * - * Use: Sets the device's internal card state to enable, disable, or halt - * - * When in the 'enable' state the card operates as normal. - * When in the 'disable' state, the card enters into a low power mode. - * When in the 'halt' state, the card is shut down and must be fully - * restarted to come back on. - */ -int iwl_send_card_state(struct iwl_priv *priv, u32 flags, u8 meta_flag) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_CARD_STATE_CMD, - .len = sizeof(u32), - .data = &flags, - .flags = meta_flag, - }; - - return iwl_send_cmd(priv, &cmd); -} - -void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif); - IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n", - sleep->pm_sleep_mode, sleep->pm_wakeup_src); -#endif -} -EXPORT_SYMBOL(iwl_rx_pm_sleep_notif); - -void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK; - IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled " - "notification for %s:\n", len, - get_cmd_string(pkt->hdr.cmd)); - iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len); -} -EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif); - -void iwl_rx_reply_error(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - - IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) " - "seq 0x%04X ser 0x%08X\n", - le32_to_cpu(pkt->u.err_resp.error_type), - get_cmd_string(pkt->u.err_resp.cmd_id), - pkt->u.err_resp.cmd_id, - le16_to_cpu(pkt->u.err_resp.bad_cmd_seq_num), - le32_to_cpu(pkt->u.err_resp.error_info)); -} -EXPORT_SYMBOL(iwl_rx_reply_error); - -void iwl_clear_isr_stats(struct iwl_priv *priv) -{ - memset(&priv->isr_stats, 0, sizeof(priv->isr_stats)); -} - -int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - int q; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (queue >= AC_NUM) { - IWL_DEBUG_MAC80211(priv, "leave - queue >= AC_NUM %d\n", queue); - return 0; - } - - q = AC_NUM - 1 - queue; - - spin_lock_irqsave(&priv->lock, flags); - - priv->qos_data.def_qos_parm.ac[q].cw_min = cpu_to_le16(params->cw_min); - priv->qos_data.def_qos_parm.ac[q].cw_max = cpu_to_le16(params->cw_max); - priv->qos_data.def_qos_parm.ac[q].aifsn = params->aifs; - priv->qos_data.def_qos_parm.ac[q].edca_txop = - cpu_to_le16((params->txop * 32)); - - priv->qos_data.def_qos_parm.ac[q].reserved1 = 0; - priv->qos_data.qos_active = 1; - - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_activate_qos(priv, 1); - else if (priv->assoc_id && iwl_is_associated(priv)) - iwl_activate_qos(priv, 0); - - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} -EXPORT_SYMBOL(iwl_mac_conf_tx); - -static void iwl_ht_conf(struct iwl_priv *priv, - struct ieee80211_bss_conf *bss_conf) -{ - struct ieee80211_sta_ht_cap *ht_conf; - struct iwl_ht_info *iwl_conf = &priv->current_ht_config; - struct ieee80211_sta *sta; - - IWL_DEBUG_MAC80211(priv, "enter: \n"); - - if (!iwl_conf->is_ht) - return; - - - /* - * It is totally wrong to base global information on something - * that is valid only when associated, alas, this driver works - * that way and I don't know how to fix it. - */ - - rcu_read_lock(); - sta = ieee80211_find_sta(priv->hw, priv->bssid); - if (!sta) { - rcu_read_unlock(); - return; - } - ht_conf = &sta->ht_cap; - - iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); - - memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); - - iwl_conf->ht_protection = - bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; - iwl_conf->non_GF_STA_present = - !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - - rcu_read_unlock(); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - -#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6) -void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct iwl_priv *priv = hw->priv; - int ret; - - IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes); - - if (!iwl_is_alive(priv)) - return; - - mutex_lock(&priv->mutex); - - if (changes & BSS_CHANGED_BEACON && - priv->iw_mode == NL80211_IFTYPE_AP) { - dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = ieee80211_beacon_get(hw, vif); - } - - if (changes & BSS_CHANGED_BEACON_INT) { - priv->beacon_int = bss_conf->beacon_int; - /* TODO: in AP mode, do something to make this take effect */ - } - - if (changes & BSS_CHANGED_BSSID) { - IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid); - - /* - * If there is currently a HW scan going on in the - * background then we need to cancel it else the RXON - * below/in post_associate will fail. - */ - if (iwl_scan_cancel_timeout(priv, 100)) { - IWL_WARN(priv, "Aborted scan still in progress after 100ms\n"); - IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* mac80211 only sets assoc when in STATION mode */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC || - bss_conf->assoc) { - memcpy(priv->staging_rxon.bssid_addr, - bss_conf->bssid, ETH_ALEN); - - /* currently needed in a few places */ - memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); - } else { - priv->staging_rxon.filter_flags &= - ~RXON_FILTER_ASSOC_MSK; - } - - } - - /* - * This needs to be after setting the BSSID in case - * mac80211 decides to do both changes at once because - * it will invoke post_associate. - */ - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - changes & BSS_CHANGED_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - - if (beacon) - iwl_mac_beacon_update(hw, beacon); - } - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", - bss_conf->use_short_preamble); - if (bss_conf->use_short_preamble) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - } - - if (changes & BSS_CHANGED_ERP_CTS_PROT) { - IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot); - if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ)) - priv->staging_rxon.flags |= RXON_FLG_TGG_PROTECT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; - } - - if (changes & BSS_CHANGED_BASIC_RATES) { - /* XXX use this information - * - * To do that, remove code from iwl_set_rate() and put something - * like this here: - * - if (A-band) - priv->staging_rxon.ofdm_basic_rates = - bss_conf->basic_rates; - else - priv->staging_rxon.ofdm_basic_rates = - bss_conf->basic_rates >> 4; - priv->staging_rxon.cck_basic_rates = - bss_conf->basic_rates & 0xF; - */ - } - - if (changes & BSS_CHANGED_HT) { - iwl_ht_conf(priv, bss_conf); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - } - - if (changes & BSS_CHANGED_ASSOC) { - IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); - if (bss_conf->assoc) { - priv->assoc_id = bss_conf->aid; - priv->beacon_int = bss_conf->beacon_int; - priv->timestamp = bss_conf->timestamp; - priv->assoc_capability = bss_conf->assoc_capability; - - /* - * We have just associated, don't start scan too early - * leave time for EAPOL exchange to complete. - * - * XXX: do this in mac80211 - */ - priv->next_scan_jiffies = jiffies + - IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; - if (!iwl_is_rfkill(priv)) - priv->cfg->ops->lib->post_associate(priv); - } else - priv->assoc_id = 0; - - } - - if (changes && iwl_is_associated(priv) && priv->assoc_id) { - IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n", - changes); - ret = iwl_send_rxon_assoc(priv); - if (!ret) { - /* Sync active_rxon with latest change. */ - memcpy((void *)&priv->active_rxon, - &priv->staging_rxon, - sizeof(struct iwl_rxon_cmd)); - } - } - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} -EXPORT_SYMBOL(iwl_bss_info_changed); - -int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - __le64 timestamp; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not IBSS\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = skb; - - priv->assoc_id = 0; - timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp; - priv->timestamp = le64_to_cpu(timestamp); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - priv->cfg->ops->lib->post_associate(priv); - - - return 0; -} -EXPORT_SYMBOL(iwl_mac_beacon_update); - -int iwl_set_mode(struct iwl_priv *priv, int mode) -{ - if (mode == NL80211_IFTYPE_ADHOC) { - const struct iwl_channel_info *ch_info; - - ch_info = iwl_get_channel_info(priv, - priv->band, - le16_to_cpu(priv->staging_rxon.channel)); - - if (!ch_info || !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d not IBSS channel\n", - le16_to_cpu(priv->staging_rxon.channel)); - return -EINVAL; - } - } - - iwl_connection_init_rx_config(priv, mode); - - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - memcpy(priv->staging_rxon.node_addr, priv->mac_addr, ETH_ALEN); - - iwl_clear_stations_table(priv); - - /* dont commit rxon if rf-kill is on*/ - if (!iwl_is_ready_rf(priv)) - return -EAGAIN; - - iwlcore_commit_rxon(priv); - - return 0; -} -EXPORT_SYMBOL(iwl_set_mode); - -int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter: type %d\n", conf->type); - - if (priv->vif) { - IWL_DEBUG_MAC80211(priv, "leave - vif != NULL\n"); - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&priv->lock, flags); - priv->vif = conf->vif; - priv->iw_mode = conf->type; - - spin_unlock_irqrestore(&priv->lock, flags); - - mutex_lock(&priv->mutex); - - if (conf->mac_addr) { - IWL_DEBUG_MAC80211(priv, "Set %pM\n", conf->mac_addr); - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - } - - if (iwl_set_mode(priv, conf->type) == -EAGAIN) - /* we are not ready, will run again when ready */ - set_bit(STATUS_MODE_PENDING, &priv->status); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; -} -EXPORT_SYMBOL(iwl_mac_add_interface); - -void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - - if (iwl_is_ready_rf(priv)) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - if (priv->vif == conf->vif) { - priv->vif = NULL; - memset(priv->bssid, 0, ETH_ALEN); - } - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -} -EXPORT_SYMBOL(iwl_mac_remove_interface); - -/** - * iwl_mac_config - mac80211 config callback - * - * We ignore conf->flags & IEEE80211_CONF_SHORT_SLOT_TIME since it seems to - * be set inappropriately and the driver currently sets the hardware up to - * use it whenever needed. - */ -int iwl_mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct iwl_priv *priv = hw->priv; - const struct iwl_channel_info *ch_info; - struct ieee80211_conf *conf = &hw->conf; - struct iwl_ht_info *ht_conf = &priv->current_ht_config; - unsigned long flags = 0; - int ret = 0; - u16 ch; - int scan_active = 0; - - mutex_lock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n", - conf->channel->hw_value, changed); - - if (unlikely(!priv->cfg->mod_params->disable_hw_scan && - test_bit(STATUS_SCANNING, &priv->status))) { - scan_active = 1; - IWL_DEBUG_MAC80211(priv, "leave - scanning\n"); - } - - - /* during scanning mac80211 will delay channel setting until - * scan finish with changed = 0 - */ - if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) { - if (scan_active) - goto set_ch_out; - - ch = ieee80211_frequency_to_channel(conf->channel->center_freq); - ch_info = iwl_get_channel_info(priv, conf->channel->band, ch); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n"); - ret = -EINVAL; - goto set_ch_out; - } - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC && - !is_channel_ibss(ch_info)) { - IWL_ERR(priv, "channel %d in band %d not " - "IBSS channel\n", - conf->channel->hw_value, conf->channel->band); - ret = -EINVAL; - goto set_ch_out; - } - - spin_lock_irqsave(&priv->lock, flags); - - /* Configure HT40 channels */ - ht_conf->is_ht = conf_is_ht(conf); - if (ht_conf->is_ht) { - if (conf_is_ht40_minus(conf)) { - ht_conf->extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_BELOW; - ht_conf->supported_chan_width = - IWL_CHANNEL_WIDTH_40MHZ; - } else if (conf_is_ht40_plus(conf)) { - ht_conf->extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - ht_conf->supported_chan_width = - IWL_CHANNEL_WIDTH_40MHZ; - } else { - ht_conf->extension_chan_offset = - IEEE80211_HT_PARAM_CHA_SEC_NONE; - ht_conf->supported_chan_width = - IWL_CHANNEL_WIDTH_20MHZ; - } - } else - ht_conf->supported_chan_width = IWL_CHANNEL_WIDTH_20MHZ; - /* Default to no protection. Protection mode will later be set - * from BSS config in iwl_ht_conf */ - ht_conf->ht_protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE; - - /* if we are switching from ht to 2.4 clear flags - * from any ht related info since 2.4 does not - * support ht */ - if ((le16_to_cpu(priv->staging_rxon.channel) != ch)) - priv->staging_rxon.flags = 0; - - iwl_set_rxon_channel(priv, conf->channel); - iwl_set_rxon_ht(priv, ht_conf); - - iwl_set_flags_for_band(priv, conf->channel->band); - spin_unlock_irqrestore(&priv->lock, flags); - set_ch_out: - /* The list of supported rates and rate mask can be different - * for each band; since the band may have changed, reset - * the rate mask to what mac80211 lists */ - iwl_set_rate(priv); - } - - if (changed & IEEE80211_CONF_CHANGE_PS) { - ret = iwl_power_update_mode(priv, false); - if (ret) - IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n"); - } - - if (changed & IEEE80211_CONF_CHANGE_POWER) { - IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", - priv->tx_power_user_lmt, conf->power_level); - - iwl_set_tx_power(priv, conf->power_level, false); - } - - /* call to ensure that 4965 rx_chain is set properly in monitor mode */ - if (priv->cfg->ops->hcmd->set_rxon_chain) - priv->cfg->ops->hcmd->set_rxon_chain(priv); - - if (!iwl_is_ready(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - goto out; - } - - if (scan_active) - goto out; - - if (memcmp(&priv->active_rxon, - &priv->staging_rxon, sizeof(priv->staging_rxon))) - iwlcore_commit_rxon(priv); - else - IWL_DEBUG_INFO(priv, "Not re-sending same RXON configuration.\n"); - - -out: - IWL_DEBUG_MAC80211(priv, "leave\n"); - mutex_unlock(&priv->mutex); - return ret; -} -EXPORT_SYMBOL(iwl_mac_config); - -int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct iwl_priv *priv = hw->priv; - int i, avail; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - unsigned long flags; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n"); - return -EIO; - } - - spin_lock_irqsave(&priv->lock, flags); - - for (i = 0; i < AC_NUM; i++) { - txq = &priv->txq[i]; - q = &txq->q; - avail = iwl_queue_space(q); - - stats[i].len = q->n_window - avail; - stats[i].limit = q->n_window - q->high_mark; - stats[i].count = q->n_window; - - } - spin_unlock_irqrestore(&priv->lock, flags); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return 0; -} -EXPORT_SYMBOL(iwl_mac_get_tx_stats); - -void iwl_mac_reset_tsf(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - unsigned long flags; - - mutex_lock(&priv->mutex); - IWL_DEBUG_MAC80211(priv, "enter\n"); - - spin_lock_irqsave(&priv->lock, flags); - memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_info)); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_reset_qos(priv); - - spin_lock_irqsave(&priv->lock, flags); - priv->assoc_id = 0; - priv->assoc_capability = 0; - priv->assoc_station_added = 0; - - /* new association get rid of ibss beacon skb */ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = NULL; - - priv->beacon_int = priv->vif->bss_conf.beacon_int; - priv->timestamp = 0; - if ((priv->iw_mode == NL80211_IFTYPE_STATION)) - priv->beacon_int = 0; - - spin_unlock_irqrestore(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - IWL_DEBUG_MAC80211(priv, "leave - not ready\n"); - mutex_unlock(&priv->mutex); - return; - } - - /* we are restarting association process - * clear RXON_FILTER_ASSOC_MSK bit - */ - if (priv->iw_mode != NL80211_IFTYPE_AP) { - iwl_scan_cancel_timeout(priv, 100); - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - } - - if (priv->iw_mode != NL80211_IFTYPE_ADHOC) { - IWL_DEBUG_MAC80211(priv, "leave - not in IBSS\n"); - mutex_unlock(&priv->mutex); - return; - } - - iwl_set_rate(priv); - - mutex_unlock(&priv->mutex); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} -EXPORT_SYMBOL(iwl_mac_reset_tsf); - -#ifdef CONFIG_IWLWIFI_DEBUGFS - -#define IWL_TRAFFIC_DUMP_SIZE (IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES) - -void iwl_reset_traffic_log(struct iwl_priv *priv) -{ - priv->tx_traffic_idx = 0; - priv->rx_traffic_idx = 0; - if (priv->tx_traffic) - memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE); - if (priv->rx_traffic) - memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE); -} - -int iwl_alloc_traffic_mem(struct iwl_priv *priv) -{ - u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE; - - if (iwl_debug_level & IWL_DL_TX) { - if (!priv->tx_traffic) { - priv->tx_traffic = - kzalloc(traffic_size, GFP_KERNEL); - if (!priv->tx_traffic) - return -ENOMEM; - } - } - if (iwl_debug_level & IWL_DL_RX) { - if (!priv->rx_traffic) { - priv->rx_traffic = - kzalloc(traffic_size, GFP_KERNEL); - if (!priv->rx_traffic) - return -ENOMEM; - } - } - iwl_reset_traffic_log(priv); - return 0; -} -EXPORT_SYMBOL(iwl_alloc_traffic_mem); - -void iwl_free_traffic_mem(struct iwl_priv *priv) -{ - kfree(priv->tx_traffic); - priv->tx_traffic = NULL; - - kfree(priv->rx_traffic); - priv->rx_traffic = NULL; -} -EXPORT_SYMBOL(iwl_free_traffic_mem); - -void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, - u16 length, struct ieee80211_hdr *header) -{ - __le16 fc; - u16 len; - - if (likely(!(iwl_debug_level & IWL_DL_TX))) - return; - - if (!priv->tx_traffic) - return; - - fc = header->frame_control; - if (ieee80211_is_data(fc)) { - len = (length > IWL_TRAFFIC_ENTRY_SIZE) - ? IWL_TRAFFIC_ENTRY_SIZE : length; - memcpy((priv->tx_traffic + - (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)), - header, len); - priv->tx_traffic_idx = - (priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES; - } -} -EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame); - -void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, - u16 length, struct ieee80211_hdr *header) -{ - __le16 fc; - u16 len; - - if (likely(!(iwl_debug_level & IWL_DL_RX))) - return; - - if (!priv->rx_traffic) - return; - - fc = header->frame_control; - if (ieee80211_is_data(fc)) { - len = (length > IWL_TRAFFIC_ENTRY_SIZE) - ? IWL_TRAFFIC_ENTRY_SIZE : length; - memcpy((priv->rx_traffic + - (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)), - header, len); - priv->rx_traffic_idx = - (priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES; - } -} -EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame); - -const char *get_mgmt_string(int cmd) -{ - switch (cmd) { - IWL_CMD(MANAGEMENT_ASSOC_REQ); - IWL_CMD(MANAGEMENT_ASSOC_RESP); - IWL_CMD(MANAGEMENT_REASSOC_REQ); - IWL_CMD(MANAGEMENT_REASSOC_RESP); - IWL_CMD(MANAGEMENT_PROBE_REQ); - IWL_CMD(MANAGEMENT_PROBE_RESP); - IWL_CMD(MANAGEMENT_BEACON); - IWL_CMD(MANAGEMENT_ATIM); - IWL_CMD(MANAGEMENT_DISASSOC); - IWL_CMD(MANAGEMENT_AUTH); - IWL_CMD(MANAGEMENT_DEAUTH); - IWL_CMD(MANAGEMENT_ACTION); - default: - return "UNKNOWN"; - - } -} - -const char *get_ctrl_string(int cmd) -{ - switch (cmd) { - IWL_CMD(CONTROL_BACK_REQ); - IWL_CMD(CONTROL_BACK); - IWL_CMD(CONTROL_PSPOLL); - IWL_CMD(CONTROL_RTS); - IWL_CMD(CONTROL_CTS); - IWL_CMD(CONTROL_ACK); - IWL_CMD(CONTROL_CFEND); - IWL_CMD(CONTROL_CFENDACK); - default: - return "UNKNOWN"; - - } -} - -void iwl_clear_tx_stats(struct iwl_priv *priv) -{ - memset(&priv->tx_stats, 0, sizeof(struct traffic_stats)); - -} - -void iwl_clear_rx_stats(struct iwl_priv *priv) -{ - memset(&priv->rx_stats, 0, sizeof(struct traffic_stats)); -} - -/* - * if CONFIG_IWLWIFI_DEBUGFS defined, iwl_update_stats function will - * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass. - * Use debugFs to display the rx/rx_statistics - * if CONFIG_IWLWIFI_DEBUGFS not being defined, then no MGMT and CTRL - * information will be recorded, but DATA pkt still will be recorded - * for the reason of iwl_led.c need to control the led blinking based on - * number of tx and rx data. - * - */ -void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len) -{ - struct traffic_stats *stats; - - if (is_tx) - stats = &priv->tx_stats; - else - stats = &priv->rx_stats; - - if (ieee80211_is_mgmt(fc)) { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - stats->mgmt[MANAGEMENT_ASSOC_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP): - stats->mgmt[MANAGEMENT_ASSOC_RESP]++; - break; - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - stats->mgmt[MANAGEMENT_REASSOC_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP): - stats->mgmt[MANAGEMENT_REASSOC_RESP]++; - break; - case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ): - stats->mgmt[MANAGEMENT_PROBE_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP): - stats->mgmt[MANAGEMENT_PROBE_RESP]++; - break; - case cpu_to_le16(IEEE80211_STYPE_BEACON): - stats->mgmt[MANAGEMENT_BEACON]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ATIM): - stats->mgmt[MANAGEMENT_ATIM]++; - break; - case cpu_to_le16(IEEE80211_STYPE_DISASSOC): - stats->mgmt[MANAGEMENT_DISASSOC]++; - break; - case cpu_to_le16(IEEE80211_STYPE_AUTH): - stats->mgmt[MANAGEMENT_AUTH]++; - break; - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - stats->mgmt[MANAGEMENT_DEAUTH]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ACTION): - stats->mgmt[MANAGEMENT_ACTION]++; - break; - } - } else if (ieee80211_is_ctl(fc)) { - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_BACK_REQ): - stats->ctrl[CONTROL_BACK_REQ]++; - break; - case cpu_to_le16(IEEE80211_STYPE_BACK): - stats->ctrl[CONTROL_BACK]++; - break; - case cpu_to_le16(IEEE80211_STYPE_PSPOLL): - stats->ctrl[CONTROL_PSPOLL]++; - break; - case cpu_to_le16(IEEE80211_STYPE_RTS): - stats->ctrl[CONTROL_RTS]++; - break; - case cpu_to_le16(IEEE80211_STYPE_CTS): - stats->ctrl[CONTROL_CTS]++; - break; - case cpu_to_le16(IEEE80211_STYPE_ACK): - stats->ctrl[CONTROL_ACK]++; - break; - case cpu_to_le16(IEEE80211_STYPE_CFEND): - stats->ctrl[CONTROL_CFEND]++; - break; - case cpu_to_le16(IEEE80211_STYPE_CFENDACK): - stats->ctrl[CONTROL_CFENDACK]++; - break; - } - } else { - /* data */ - stats->data_cnt++; - stats->data_bytes += len; - } -} -EXPORT_SYMBOL(iwl_update_stats); -#endif - -#ifdef CONFIG_PM - -int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - - /* - * This function is called when system goes into suspend state - * mac80211 will call iwl_mac_stop() from the mac80211 suspend function - * first but since iwl_mac_stop() has no knowledge of who the caller is, - * it will not call apm_ops.stop() to stop the DMA operation. - * Calling apm_ops.stop here to make sure we stop the DMA. - */ - priv->cfg->ops->lib->apm_ops.stop(priv); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} -EXPORT_SYMBOL(iwl_pci_suspend); - -int iwl_pci_resume(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - int ret; - - pci_set_power_state(pdev, PCI_D0); - ret = pci_enable_device(pdev); - if (ret) - return ret; - pci_restore_state(pdev); - iwl_enable_interrupts(priv); - - return 0; -} -EXPORT_SYMBOL(iwl_pci_resume); - -#endif /* CONFIG_PM */ diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h deleted file mode 100644 index 40ec0c148d11..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ /dev/null @@ -1,661 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef __iwl_core_h__ -#define __iwl_core_h__ - -/************************ - * forward declarations * - ************************/ -struct iwl_host_cmd; -struct iwl_cmd; - - -#define IWLWIFI_VERSION "1.3.27k" -#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" -#define DRV_AUTHOR "" - -#define IWL_PCI_DEVICE(dev, subdev, cfg) \ - .vendor = PCI_VENDOR_ID_INTEL, .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = (subdev), \ - .driver_data = (kernel_ulong_t)&(cfg) - -#define IWL_SKU_G 0x1 -#define IWL_SKU_A 0x2 -#define IWL_SKU_N 0x8 - -#define IWL_CMD(x) case x: return #x - -struct iwl_hcmd_ops { - int (*rxon_assoc)(struct iwl_priv *priv); - int (*commit_rxon)(struct iwl_priv *priv); - void (*set_rxon_chain)(struct iwl_priv *priv); -}; - -struct iwl_hcmd_utils_ops { - u16 (*get_hcmd_size)(u8 cmd_id, u16 len); - u16 (*build_addsta_hcmd)(const struct iwl_addsta_cmd *cmd, u8 *data); - void (*gain_computation)(struct iwl_priv *priv, - u32 *average_noise, - u16 min_average_noise_antennat_i, - u32 min_average_noise); - void (*chain_noise_reset)(struct iwl_priv *priv); - void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info, - __le32 *tx_flags); - int (*calc_rssi)(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp); -}; - -struct iwl_apm_ops { - int (*init)(struct iwl_priv *priv); - int (*reset)(struct iwl_priv *priv); - void (*stop)(struct iwl_priv *priv); - void (*config)(struct iwl_priv *priv); - int (*set_pwr_src)(struct iwl_priv *priv, enum iwl_pwr_src src); -}; - -struct iwl_temp_ops { - void (*temperature)(struct iwl_priv *priv); - void (*set_ct_kill)(struct iwl_priv *priv); -}; - -struct iwl_ucode_ops { - u32 (*get_header_size)(u32); - u32 (*get_build)(const struct iwl_ucode_header *, u32); - u32 (*get_inst_size)(const struct iwl_ucode_header *, u32); - u32 (*get_data_size)(const struct iwl_ucode_header *, u32); - u32 (*get_init_size)(const struct iwl_ucode_header *, u32); - u32 (*get_init_data_size)(const struct iwl_ucode_header *, u32); - u32 (*get_boot_size)(const struct iwl_ucode_header *, u32); - u8 * (*get_data)(const struct iwl_ucode_header *, u32); -}; - -struct iwl_lib_ops { - /* set hw dependent parameters */ - int (*set_hw_params)(struct iwl_priv *priv); - /* Handling TX */ - void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); - void (*txq_inval_byte_cnt_tbl)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - void (*txq_set_sched)(struct iwl_priv *priv, u32 mask); - int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, - u16 len, u8 reset, u8 pad); - void (*txq_free_tfd)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - int (*txq_init)(struct iwl_priv *priv, - struct iwl_tx_queue *txq); - /* aggregations */ - int (*txq_agg_enable)(struct iwl_priv *priv, int txq_id, int tx_fifo, - int sta_id, int tid, u16 ssn_idx); - int (*txq_agg_disable)(struct iwl_priv *priv, u16 txq_id, u16 ssn_idx, - u8 tx_fifo); - /* setup Rx handler */ - void (*rx_handler_setup)(struct iwl_priv *priv); - /* setup deferred work */ - void (*setup_deferred_work)(struct iwl_priv *priv); - /* cancel deferred work */ - void (*cancel_deferred_work)(struct iwl_priv *priv); - /* alive notification after init uCode load */ - void (*init_alive_start)(struct iwl_priv *priv); - /* alive notification */ - int (*alive_notify)(struct iwl_priv *priv); - /* check validity of rtc data address */ - int (*is_valid_rtc_data_addr)(u32 addr); - /* 1st ucode load */ - int (*load_ucode)(struct iwl_priv *priv); - void (*dump_nic_event_log)(struct iwl_priv *priv); - void (*dump_nic_error_log)(struct iwl_priv *priv); - /* power management */ - struct iwl_apm_ops apm_ops; - - /* power */ - int (*send_tx_power) (struct iwl_priv *priv); - void (*update_chain_flags)(struct iwl_priv *priv); - void (*post_associate) (struct iwl_priv *priv); - void (*config_ap) (struct iwl_priv *priv); - irqreturn_t (*isr) (int irq, void *data); - - /* eeprom operations (as defined in iwl-eeprom.h) */ - struct iwl_eeprom_ops eeprom_ops; - - /* temperature */ - struct iwl_temp_ops temp_ops; -}; - -struct iwl_ops { - const struct iwl_ucode_ops *ucode; - const struct iwl_lib_ops *lib; - const struct iwl_hcmd_ops *hcmd; - const struct iwl_hcmd_utils_ops *utils; -}; - -struct iwl_mod_params { - int sw_crypto; /* def: 0 = using hardware encryption */ - int disable_hw_scan; /* def: 0 = use h/w scan */ - int num_of_queues; /* def: HW dependent */ - int num_of_ampdu_queues;/* def: HW dependent */ - int disable_11n; /* def: 0 = 11n capabilities enabled */ - int amsdu_size_8K; /* def: 1 = enable 8K amsdu size */ - int antenna; /* def: 0 = both antennas (use diversity) */ - int restart_fw; /* def: 1 = restart firmware */ -}; - -/** - * struct iwl_cfg - * @fw_name_pre: Firmware filename prefix. The api version and extension - * (.ucode) will be added to filename before loading from disk. The - * filename is constructed as fw_name_pre.ucode. - * @ucode_api_max: Highest version of uCode API supported by driver. - * @ucode_api_min: Lowest version of uCode API supported by driver. - * @pa_type: used by 6000 series only to identify the type of Power Amplifier - * @max_ll_items: max number of OTP blocks - * @shadow_ram_support: shadow support for OTP memory - * @use_rts_for_ht: use rts/cts protection for HT traffic - * - * We enable the driver to be backward compatible wrt API version. The - * driver specifies which APIs it supports (with @ucode_api_max being the - * highest and @ucode_api_min the lowest). Firmware will only be loaded if - * it has a supported API version. The firmware's API version will be - * stored in @iwl_priv, enabling the driver to make runtime changes based - * on firmware version used. - * - * For example, - * if (IWL_UCODE_API(priv->ucode_ver) >= 2) { - * Driver interacts with Firmware API version >= 2. - * } else { - * Driver interacts with Firmware API version 1. - * } - * - * The ideal usage of this infrastructure is to treat a new ucode API - * release as a new hardware revision. That is, through utilizing the - * iwl_hcmd_utils_ops etc. we accommodate different command structures - * and flows between hardware versions (4965/5000) as well as their API - * versions. - * - */ -struct iwl_cfg { - const char *name; - const char *fw_name_pre; - const unsigned int ucode_api_max; - const unsigned int ucode_api_min; - unsigned int sku; - int eeprom_size; - u16 eeprom_ver; - u16 eeprom_calib_ver; - const struct iwl_ops *ops; - const struct iwl_mod_params *mod_params; - u8 valid_tx_ant; - u8 valid_rx_ant; - bool need_pll_cfg; - bool use_isr_legacy; - enum iwl_pa_type pa_type; - const u16 max_ll_items; - const bool shadow_ram_support; - const bool ht_greenfield_support; - const bool broken_powersave; - bool use_rts_for_ht; -}; - -/*************************** - * L i b * - ***************************/ - -struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg, - struct ieee80211_ops *hw_ops); -void iwl_hw_detect(struct iwl_priv *priv); -void iwl_reset_qos(struct iwl_priv *priv); -void iwl_activate_qos(struct iwl_priv *priv, u8 force); -int iwl_mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params); -void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, int hw_decrypt); -int iwl_check_rxon_cmd(struct iwl_priv *priv); -int iwl_full_rxon_required(struct iwl_priv *priv); -void iwl_set_rxon_chain(struct iwl_priv *priv); -int iwl_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch); -void iwl_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_info *ht_info); -u8 iwl_is_ht40_tx_allowed(struct iwl_priv *priv, - struct ieee80211_sta_ht_cap *sta_ht_inf); -void iwl_set_flags_for_band(struct iwl_priv *priv, enum ieee80211_band band); -void iwl_connection_init_rx_config(struct iwl_priv *priv, int mode); -int iwl_set_decrypted_flag(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - u32 decrypt_res, - struct ieee80211_rx_status *stats); -void iwl_irq_handle_error(struct iwl_priv *priv); -void iwl_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, u64 multicast); -int iwl_hw_nic_init(struct iwl_priv *priv); -int iwl_setup_mac(struct iwl_priv *priv); -int iwl_set_hw_params(struct iwl_priv *priv); -int iwl_init_drv(struct iwl_priv *priv); -void iwl_uninit_drv(struct iwl_priv *priv); -bool iwl_is_monitor_mode(struct iwl_priv *priv); -void iwl_post_associate(struct iwl_priv *priv); -void iwl_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes); -int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb); -int iwl_commit_rxon(struct iwl_priv *priv); -int iwl_set_mode(struct iwl_priv *priv, int mode); -int iwl_mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -void iwl_mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -int iwl_mac_config(struct ieee80211_hw *hw, u32 changed); -void iwl_config_ap(struct iwl_priv *priv); -int iwl_mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); -void iwl_mac_reset_tsf(struct ieee80211_hw *hw); -#ifdef CONFIG_IWLWIFI_DEBUGFS -int iwl_alloc_traffic_mem(struct iwl_priv *priv); -void iwl_free_traffic_mem(struct iwl_priv *priv); -void iwl_reset_traffic_log(struct iwl_priv *priv); -void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, - u16 length, struct ieee80211_hdr *header); -void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, - u16 length, struct ieee80211_hdr *header); -const char *get_mgmt_string(int cmd); -const char *get_ctrl_string(int cmd); -void iwl_clear_tx_stats(struct iwl_priv *priv); -void iwl_clear_rx_stats(struct iwl_priv *priv); -void iwl_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, - u16 len); -#else -static inline int iwl_alloc_traffic_mem(struct iwl_priv *priv) -{ - return 0; -} -static inline void iwl_free_traffic_mem(struct iwl_priv *priv) -{ -} -static inline void iwl_reset_traffic_log(struct iwl_priv *priv) -{ -} -static inline void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv, - u16 length, struct ieee80211_hdr *header) -{ -} -static inline void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv, - u16 length, struct ieee80211_hdr *header) -{ -} -static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx, - __le16 fc, u16 len) -{ - struct traffic_stats *stats; - - if (is_tx) - stats = &priv->tx_stats; - else - stats = &priv->rx_stats; - - if (ieee80211_is_data(fc)) { - /* data */ - stats->data_bytes += len; - } -} -#endif -/***************************************************** - * RX handlers. - * **************************************************/ -void iwl_rx_pm_sleep_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -void iwl_rx_reply_error(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); - -/***************************************************** -* RX -******************************************************/ -void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -void iwl_cmd_queue_free(struct iwl_priv *priv); -int iwl_rx_queue_alloc(struct iwl_priv *priv); -void iwl_rx_handle(struct iwl_priv *priv); -int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, - struct iwl_rx_queue *q); -void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -void iwl_rx_replenish(struct iwl_priv *priv); -void iwl_rx_replenish_now(struct iwl_priv *priv); -int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq); -int iwl_rx_queue_restock(struct iwl_priv *priv); -int iwl_rx_queue_space(const struct iwl_rx_queue *q); -void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority); -void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); -int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); -/* Handlers */ -void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -void iwl_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb); - -/* TX helpers */ - -/***************************************************** -* TX -******************************************************/ -int iwl_txq_ctx_reset(struct iwl_priv *priv); -void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); -int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - dma_addr_t addr, u16 len, u8 reset, u8 pad); -int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb); -void iwl_hw_txq_ctx_free(struct iwl_priv *priv); -int iwl_hw_tx_queue_init(struct iwl_priv *priv, - struct iwl_tx_queue *txq); -int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed); -int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, - int slots_num, u32 txq_id); -void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); -int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); -int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); -int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id); -/***************************************************** - * TX power - ****************************************************/ -int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force); - -/******************************************************************************* - * Rate - ******************************************************************************/ - -void iwl_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags, - struct ieee80211_tx_info *info); -int iwl_hwrate_to_plcp_idx(u32 rate_n_flags); -int iwl_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band); - -u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv); - -u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx); - -static inline u32 iwl_ant_idx_to_flags(u8 ant_idx) -{ - return BIT(ant_idx) << RATE_MCS_ANT_POS; -} - -static inline u8 iwl_hw_get_rate(__le32 rate_n_flags) -{ - return le32_to_cpu(rate_n_flags) & 0xFF; -} -static inline u32 iwl_hw_get_rate_n_flags(__le32 rate_n_flags) -{ - return le32_to_cpu(rate_n_flags) & 0x1FFFF; -} -static inline __le32 iwl_hw_set_rate_n_flags(u8 rate, u32 flags) -{ - return cpu_to_le32(flags|(u32)rate); -} - -/******************************************************************************* - * Scanning - ******************************************************************************/ -void iwl_init_scan_params(struct iwl_priv *priv); -int iwl_scan_cancel(struct iwl_priv *priv); -int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms); -int iwl_mac_hw_scan(struct ieee80211_hw *hw, struct cfg80211_scan_request *req); -u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, - const u8 *ie, int ie_len, int left); -void iwl_setup_rx_scan_handlers(struct iwl_priv *priv); -u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band, - u8 n_probes); -u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band); -void iwl_bg_scan_check(struct work_struct *data); -void iwl_bg_abort_scan(struct work_struct *work); -void iwl_bg_scan_completed(struct work_struct *work); -void iwl_setup_scan_deferred_work(struct iwl_priv *priv); - -/* For faster active scanning, scan will move to the next channel if fewer than - * PLCP_QUIET_THRESH packets are heard on this channel within - * ACTIVE_QUIET_TIME after sending probe request. This shortens the dwell - * time if it's a quiet channel (nothing responded to our probe, and there's - * no other traffic). - * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */ -#define IWL_ACTIVE_QUIET_TIME cpu_to_le16(10) /* msec */ -#define IWL_PLCP_QUIET_THRESH cpu_to_le16(1) /* packets */ - - -/******************************************************************************* - * Calibrations - implemented in iwl-calib.c - ******************************************************************************/ -int iwl_send_calib_results(struct iwl_priv *priv); -int iwl_calib_set(struct iwl_calib_result *res, const u8 *buf, int len); -void iwl_calib_free_results(struct iwl_priv *priv); - -/******************************************************************************* - * Spectrum Measureemtns in iwl-spectrum.c - ******************************************************************************/ -#ifdef CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT -void iwl_setup_spectrum_handlers(struct iwl_priv *priv); -#else -static inline void iwl_setup_spectrum_handlers(struct iwl_priv *priv) {} -#endif -/***************************************************** - * S e n d i n g H o s t C o m m a n d s * - *****************************************************/ - -const char *get_cmd_string(u8 cmd); -int __must_check iwl_send_cmd_sync(struct iwl_priv *priv, - struct iwl_host_cmd *cmd); -int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); -int __must_check iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, - u16 len, const void *data); -int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len, - const void *data, - void (*callback)(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb)); - -int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd); - -int iwl_send_card_state(struct iwl_priv *priv, u32 flags, - u8 meta_flag); - -/***************************************************** - * PCI * - *****************************************************/ -irqreturn_t iwl_isr_legacy(int irq, void *data); -int iwl_reset_ict(struct iwl_priv *priv); -void iwl_disable_ict(struct iwl_priv *priv); -int iwl_alloc_isr_ict(struct iwl_priv *priv); -void iwl_free_isr_ict(struct iwl_priv *priv); -irqreturn_t iwl_isr_ict(int irq, void *data); - -static inline u16 iwl_pcie_link_ctl(struct iwl_priv *priv) -{ - int pos; - u16 pci_lnk_ctl; - pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP); - pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl); - return pci_lnk_ctl; -} -#ifdef CONFIG_PM -int iwl_pci_suspend(struct pci_dev *pdev, pm_message_t state); -int iwl_pci_resume(struct pci_dev *pdev); -#endif /* CONFIG_PM */ - -/***************************************************** -* Error Handling Debugging -******************************************************/ -#ifdef CONFIG_IWLWIFI_DEBUG -void iwl_dump_nic_event_log(struct iwl_priv *priv); -void iwl_dump_nic_error_log(struct iwl_priv *priv); -#else -static inline void iwl_dump_nic_event_log(struct iwl_priv *priv) -{ -} - -static inline void iwl_dump_nic_error_log(struct iwl_priv *priv) -{ -} -#endif - -void iwl_clear_isr_stats(struct iwl_priv *priv); - -/***************************************************** -* GEOS -******************************************************/ -int iwlcore_init_geos(struct iwl_priv *priv); -void iwlcore_free_geos(struct iwl_priv *priv); - -/*************** DRIVER STATUS FUNCTIONS *****/ - -#define STATUS_HCMD_ACTIVE 0 /* host command in progress */ -#define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ -#define STATUS_INT_ENABLED 2 -#define STATUS_RF_KILL_HW 3 -#define STATUS_INIT 5 -#define STATUS_ALIVE 6 -#define STATUS_READY 7 -#define STATUS_TEMPERATURE 8 -#define STATUS_GEO_CONFIGURED 9 -#define STATUS_EXIT_PENDING 10 -#define STATUS_STATISTICS 12 -#define STATUS_SCANNING 13 -#define STATUS_SCAN_ABORTING 14 -#define STATUS_SCAN_HW 15 -#define STATUS_POWER_PMI 16 -#define STATUS_FW_ERROR 17 -#define STATUS_MODE_PENDING 18 - - -static inline int iwl_is_ready(struct iwl_priv *priv) -{ - /* The adapter is 'ready' if READY and GEO_CONFIGURED bits are - * set but EXIT_PENDING is not */ - return test_bit(STATUS_READY, &priv->status) && - test_bit(STATUS_GEO_CONFIGURED, &priv->status) && - !test_bit(STATUS_EXIT_PENDING, &priv->status); -} - -static inline int iwl_is_alive(struct iwl_priv *priv) -{ - return test_bit(STATUS_ALIVE, &priv->status); -} - -static inline int iwl_is_init(struct iwl_priv *priv) -{ - return test_bit(STATUS_INIT, &priv->status); -} - -static inline int iwl_is_rfkill_hw(struct iwl_priv *priv) -{ - return test_bit(STATUS_RF_KILL_HW, &priv->status); -} - -static inline int iwl_is_rfkill(struct iwl_priv *priv) -{ - return iwl_is_rfkill_hw(priv); -} - -static inline int iwl_is_ready_rf(struct iwl_priv *priv) -{ - - if (iwl_is_rfkill(priv)) - return 0; - - return iwl_is_ready(priv); -} - -extern void iwl_rf_kill_ct_config(struct iwl_priv *priv); -extern int iwl_send_bt_config(struct iwl_priv *priv); -extern int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags); -extern int iwl_verify_ucode(struct iwl_priv *priv); -extern int iwl_send_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq, u8 flags); -extern void iwl_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); -void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); - -void iwl_setup_rxon_timing(struct iwl_priv *priv); -static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) -{ - return priv->cfg->ops->hcmd->rxon_assoc(priv); -} -static inline int iwlcore_commit_rxon(struct iwl_priv *priv) -{ - return priv->cfg->ops->hcmd->commit_rxon(priv); -} -static inline void iwlcore_config_ap(struct iwl_priv *priv) -{ - priv->cfg->ops->lib->config_ap(priv); -} -static inline const struct ieee80211_supported_band *iwl_get_hw_mode( - struct iwl_priv *priv, enum ieee80211_band band) -{ - return priv->hw->wiphy->bands[band]; -} - -#endif /* __iwl_core_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-csr.h b/drivers/net/wireless/iwlwifi/iwl-csr.h deleted file mode 100644 index 06437d13e73e..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-csr.h +++ /dev/null @@ -1,318 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_csr_h__ -#define __iwl_csr_h__ -/*=== CSR (control and status registers) ===*/ -#define CSR_BASE (0x000) - -#define CSR_HW_IF_CONFIG_REG (CSR_BASE+0x000) /* hardware interface config */ -#define CSR_INT_COALESCING (CSR_BASE+0x004) /* accum ints, 32-usec units */ -#define CSR_INT (CSR_BASE+0x008) /* host interrupt status/ack */ -#define CSR_INT_MASK (CSR_BASE+0x00c) /* host interrupt enable */ -#define CSR_FH_INT_STATUS (CSR_BASE+0x010) /* busmaster int status/ack*/ -#define CSR_GPIO_IN (CSR_BASE+0x018) /* read external chip pins */ -#define CSR_RESET (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/ -#define CSR_GP_CNTRL (CSR_BASE+0x024) - -/* - * Hardware revision info - * Bit fields: - * 31-8: Reserved - * 7-4: Type of device: 0x0 = 4965, 0xd = 3945 - * 3-2: Revision step: 0 = A, 1 = B, 2 = C, 3 = D - * 1-0: "Dash" value, as in A-1, etc. - * - * NOTE: Revision step affects calculation of CCK txpower for 4965. - */ -#define CSR_HW_REV (CSR_BASE+0x028) - -/* EEPROM reads */ -#define CSR_EEPROM_REG (CSR_BASE+0x02c) -#define CSR_EEPROM_GP (CSR_BASE+0x030) -#define CSR_OTP_GP_REG (CSR_BASE+0x034) -#define CSR_GIO_REG (CSR_BASE+0x03C) -#define CSR_GP_UCODE_REG (CSR_BASE+0x048) -#define CSR_GP_DRIVER_REG (CSR_BASE+0x050) -#define CSR_UCODE_DRV_GP1 (CSR_BASE+0x054) -#define CSR_UCODE_DRV_GP1_SET (CSR_BASE+0x058) -#define CSR_UCODE_DRV_GP1_CLR (CSR_BASE+0x05c) -#define CSR_UCODE_DRV_GP2 (CSR_BASE+0x060) -#define CSR_LED_REG (CSR_BASE+0x094) -#define CSR_DRAM_INT_TBL_REG (CSR_BASE+0x0A0) -#define CSR_GIO_CHICKEN_BITS (CSR_BASE+0x100) - -#define CSR_INT_PERIODIC_REG (CSR_BASE+0x005) -/* Analog phase-lock-loop configuration */ -#define CSR_ANA_PLL_CFG (CSR_BASE+0x20c) -/* - * Indicates hardware rev, to determine CCK backoff for txpower calculation. - * Bit fields: - * 3-2: 0 = A, 1 = B, 2 = C, 3 = D step - */ -#define CSR_HW_REV_WA_REG (CSR_BASE+0x22C) -#define CSR_DBG_HPET_MEM_REG (CSR_BASE+0x240) - -/* Bits for CSR_HW_IF_CONFIG_REG */ -#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R (0x00000010) -#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER (0x00000C00) -#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI (0x00000100) -#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI (0x00000200) - -#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB (0x00000100) -#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM (0x00000200) -#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC (0x00000400) -#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE (0x00000800) -#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A (0x00000000) -#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B (0x00001000) - -#define CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A (0x00080000) -#define CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM (0x00200000) -#define CSR_HW_IF_CONFIG_REG_BIT_NIC_READY (0x00400000) -#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) -#define CSR_HW_IF_CONFIG_REG_PREPARE (0x08000000) - -#define CSR_INT_PERIODIC_DIS (0x00) -#define CSR_INT_PERIODIC_ENA (0xFF) - -/* interrupt flags in INTA, set by uCode or hardware (e.g. dma), - * acknowledged (reset) by host writing "1" to flagged bits. */ -#define CSR_INT_BIT_FH_RX (1 << 31) /* Rx DMA, cmd responses, FH_INT[17:16] */ -#define CSR_INT_BIT_HW_ERR (1 << 29) /* DMA hardware error FH_INT[31] */ -#define CSR_INT_BIT_RX_PERIODIC (1 << 28) /* Rx periodic */ -#define CSR_INT_BIT_FH_TX (1 << 27) /* Tx DMA FH_INT[1:0] */ -#define CSR_INT_BIT_SCD (1 << 26) /* TXQ pointer advanced */ -#define CSR_INT_BIT_SW_ERR (1 << 25) /* uCode error */ -#define CSR_INT_BIT_RF_KILL (1 << 7) /* HW RFKILL switch GP_CNTRL[27] toggled */ -#define CSR_INT_BIT_CT_KILL (1 << 6) /* Critical temp (chip too hot) rfkill */ -#define CSR_INT_BIT_SW_RX (1 << 3) /* Rx, command responses, 3945 */ -#define CSR_INT_BIT_WAKEUP (1 << 1) /* NIC controller waking up (pwr mgmt) */ -#define CSR_INT_BIT_ALIVE (1 << 0) /* uCode interrupts once it initializes */ - -#define CSR_INI_SET_MASK (CSR_INT_BIT_FH_RX | \ - CSR_INT_BIT_HW_ERR | \ - CSR_INT_BIT_FH_TX | \ - CSR_INT_BIT_SW_ERR | \ - CSR_INT_BIT_RF_KILL | \ - CSR_INT_BIT_SW_RX | \ - CSR_INT_BIT_WAKEUP | \ - CSR_INT_BIT_ALIVE) - -/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */ -#define CSR_FH_INT_BIT_ERR (1 << 31) /* Error */ -#define CSR_FH_INT_BIT_HI_PRIOR (1 << 30) /* High priority Rx, bypass coalescing */ -#define CSR39_FH_INT_BIT_RX_CHNL2 (1 << 18) /* Rx channel 2 (3945 only) */ -#define CSR_FH_INT_BIT_RX_CHNL1 (1 << 17) /* Rx channel 1 */ -#define CSR_FH_INT_BIT_RX_CHNL0 (1 << 16) /* Rx channel 0 */ -#define CSR39_FH_INT_BIT_TX_CHNL6 (1 << 6) /* Tx channel 6 (3945 only) */ -#define CSR_FH_INT_BIT_TX_CHNL1 (1 << 1) /* Tx channel 1 */ -#define CSR_FH_INT_BIT_TX_CHNL0 (1 << 0) /* Tx channel 0 */ - -#define CSR39_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR39_FH_INT_BIT_RX_CHNL2 | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) - - -#define CSR39_FH_INT_TX_MASK (CSR39_FH_INT_BIT_TX_CHNL6 | \ - CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) - -#define CSR49_FH_INT_RX_MASK (CSR_FH_INT_BIT_HI_PRIOR | \ - CSR_FH_INT_BIT_RX_CHNL1 | \ - CSR_FH_INT_BIT_RX_CHNL0) - -#define CSR49_FH_INT_TX_MASK (CSR_FH_INT_BIT_TX_CHNL1 | \ - CSR_FH_INT_BIT_TX_CHNL0) - -/* GPIO */ -#define CSR_GPIO_IN_BIT_AUX_POWER (0x00000200) -#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC (0x00000000) -#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC (0x00000200) - -/* RESET */ -#define CSR_RESET_REG_FLAG_NEVO_RESET (0x00000001) -#define CSR_RESET_REG_FLAG_FORCE_NMI (0x00000002) -#define CSR_RESET_REG_FLAG_SW_RESET (0x00000080) -#define CSR_RESET_REG_FLAG_MASTER_DISABLED (0x00000100) -#define CSR_RESET_REG_FLAG_STOP_MASTER (0x00000200) - -/* GP (general purpose) CONTROL */ -#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY (0x00000001) -#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE (0x00000004) -#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ (0x00000008) -#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP (0x00000010) - -#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN (0x00000001) - -#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE (0x07000000) -#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE (0x04000000) -#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW (0x08000000) - - -/* HW REV */ -#define CSR_HW_REV_TYPE_MSK (0x00000F0) -#define CSR_HW_REV_TYPE_3945 (0x00000D0) -#define CSR_HW_REV_TYPE_4965 (0x0000000) -#define CSR_HW_REV_TYPE_5300 (0x0000020) -#define CSR_HW_REV_TYPE_5350 (0x0000030) -#define CSR_HW_REV_TYPE_5100 (0x0000050) -#define CSR_HW_REV_TYPE_5150 (0x0000040) -#define CSR_HW_REV_TYPE_1000 (0x0000060) -#define CSR_HW_REV_TYPE_6x00 (0x0000070) -#define CSR_HW_REV_TYPE_6x50 (0x0000080) -#define CSR_HW_REV_TYPE_NONE (0x00000F0) - -/* EEPROM REG */ -#define CSR_EEPROM_REG_READ_VALID_MSK (0x00000001) -#define CSR_EEPROM_REG_BIT_CMD (0x00000002) -#define CSR_EEPROM_REG_MSK_ADDR (0x0000FFFC) -#define CSR_EEPROM_REG_MSK_DATA (0xFFFF0000) - -/* EEPROM GP */ -#define CSR_EEPROM_GP_VALID_MSK (0x00000007) -#define CSR_EEPROM_GP_BAD_SIGNATURE (0x00000000) -#define CSR_EEPROM_GP_IF_OWNER_MSK (0x00000180) -#define CSR_OTP_GP_REG_DEVICE_SELECT (0x00010000) /* 0 - EEPROM, 1 - OTP */ -#define CSR_OTP_GP_REG_OTP_ACCESS_MODE (0x00020000) /* 0 - absolute, 1 - relative */ -#define CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK (0x00100000) /* bit 20 */ -#define CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK (0x00200000) /* bit 21 */ - -/* CSR GIO */ -#define CSR_GIO_REG_VAL_L0S_ENABLED (0x00000002) - -/* UCODE DRV GP */ -#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP (0x00000001) -#define CSR_UCODE_SW_BIT_RFKILL (0x00000002) -#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED (0x00000004) -#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT (0x00000008) - -/* GP Driver */ -#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_MSK (0x00000003) -#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_3x3_HYB (0x00000000) -#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_HYB (0x00000001) -#define CSR_GP_DRIVER_REG_BIT_RADIO_SKU_2x2_IPA (0x00000002) - - -/* GI Chicken Bits */ -#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX (0x00800000) -#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER (0x20000000) - -/* LED */ -#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF) -#define CSR_LED_REG_TRUN_ON (0x78) -#define CSR_LED_REG_TRUN_OFF (0x38) - -/* ANA_PLL */ -#define CSR39_ANA_PLL_CFG_VAL (0x01000000) -#define CSR50_ANA_PLL_CFG_VAL (0x00880300) - -/* HPET MEM debug */ -#define CSR_DBG_HPET_MEM_REG_VAL (0xFFFF0000) - -/* DRAM INT TABLE */ -#define CSR_DRAM_INT_TBL_ENABLE (1 << 31) -#define CSR_DRAM_INIT_TBL_WRAP_CHECK (1 << 27) - -/*=== HBUS (Host-side Bus) ===*/ -#define HBUS_BASE (0x400) -/* - * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM - * structures, error log, event log, verifying uCode load). - * First write to address register, then read from or write to data register - * to complete the job. Once the address register is set up, accesses to - * data registers auto-increment the address by one dword. - * Bit usage for address registers (read or write): - * 0-31: memory address within device - */ -#define HBUS_TARG_MEM_RADDR (HBUS_BASE+0x00c) -#define HBUS_TARG_MEM_WADDR (HBUS_BASE+0x010) -#define HBUS_TARG_MEM_WDAT (HBUS_BASE+0x018) -#define HBUS_TARG_MEM_RDAT (HBUS_BASE+0x01c) - -/* - * Registers for accessing device's internal peripheral registers - * (e.g. SCD, BSM, etc.). First write to address register, - * then read from or write to data register to complete the job. - * Bit usage for address registers (read or write): - * 0-15: register address (offset) within device - * 24-25: (# bytes - 1) to read or write (e.g. 3 for dword) - */ -#define HBUS_TARG_PRPH_WADDR (HBUS_BASE+0x044) -#define HBUS_TARG_PRPH_RADDR (HBUS_BASE+0x048) -#define HBUS_TARG_PRPH_WDAT (HBUS_BASE+0x04c) -#define HBUS_TARG_PRPH_RDAT (HBUS_BASE+0x050) - -/* - * Per-Tx-queue write pointer (index, really!) (3945 and 4965). - * Indicates index to next TFD that driver will fill (1 past latest filled). - * Bit usage: - * 0-7: queue write index - * 11-8: queue selector - */ -#define HBUS_TARG_WRPTR (HBUS_BASE+0x060) -#define HBUS_TARG_MBX_C (HBUS_BASE+0x030) - -#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED (0x00000004) - - -#endif /* !__iwl_csr_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h deleted file mode 100644 index cbc62904655d..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ /dev/null @@ -1,243 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_debug_h__ -#define __iwl_debug_h__ - -struct iwl_priv; -extern u32 iwl_debug_level; - -#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a) -#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a) -#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a) -#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a) - -#define iwl_print_hex_error(priv, p, len) \ -do { \ - print_hex_dump(KERN_ERR, "iwl data: ", \ - DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ -} while (0) - -#ifdef CONFIG_IWLWIFI_DEBUG -#define IWL_DEBUG(__priv, level, fmt, args...) \ -do { \ - if (iwl_get_debug_level(__priv) & (level)) \ - dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ - "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ - __func__ , ## args); \ -} while (0) - -#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) \ -do { \ - if ((iwl_get_debug_level(__priv) & (level)) && net_ratelimit()) \ - dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev), \ - "%c %s " fmt, in_interrupt() ? 'I' : 'U', \ - __func__ , ## args); \ -} while (0) - -#define iwl_print_hex_dump(priv, level, p, len) \ -do { \ - if (iwl_get_debug_level(priv) & level) \ - print_hex_dump(KERN_DEBUG, "iwl data: ", \ - DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \ -} while (0) - -#ifdef CONFIG_IWLWIFI_DEBUGFS -struct iwl_debugfs { - const char *name; - struct dentry *dir_drv; - struct dentry *dir_data; - struct dentry *dir_debug; - struct dentry *dir_rf; - struct dir_data_files { - struct dentry *file_sram; - struct dentry *file_nvm; - struct dentry *file_stations; - struct dentry *file_log_event; - struct dentry *file_channels; - struct dentry *file_status; - struct dentry *file_interrupt; - struct dentry *file_qos; - struct dentry *file_thermal_throttling; -#ifdef CONFIG_IWLWIFI_LEDS - struct dentry *file_led; -#endif - struct dentry *file_disable_ht40; - struct dentry *file_sleep_level_override; - struct dentry *file_current_sleep_command; - } dbgfs_data_files; - struct dir_rf_files { - struct dentry *file_disable_sensitivity; - struct dentry *file_disable_chain_noise; - struct dentry *file_disable_tx_power; - } dbgfs_rf_files; - struct dir_debug_files { - struct dentry *file_rx_statistics; - struct dentry *file_tx_statistics; - struct dentry *file_traffic_log; - struct dentry *file_rx_queue; - struct dentry *file_tx_queue; - struct dentry *file_ucode_rx_stats; - struct dentry *file_ucode_tx_stats; - struct dentry *file_ucode_general_stats; - struct dentry *file_sensitivity; - struct dentry *file_chain_noise; - struct dentry *file_tx_power; - } dbgfs_debug_files; - u32 sram_offset; - u32 sram_len; -}; - -int iwl_dbgfs_register(struct iwl_priv *priv, const char *name); -void iwl_dbgfs_unregister(struct iwl_priv *priv); -#endif - -#else -#define IWL_DEBUG(__priv, level, fmt, args...) -#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...) -static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level, - void *p, u32 len) -{} -#endif /* CONFIG_IWLWIFI_DEBUG */ - - - -#ifndef CONFIG_IWLWIFI_DEBUGFS -static inline int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) -{ - return 0; -} -static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) -{ -} -#endif /* CONFIG_IWLWIFI_DEBUGFS */ - -/* - * To use the debug system: - * - * If you are defining a new debug classification, simply add it to the #define - * list here in the form of - * - * #define IWL_DL_xxxx VALUE - * - * where xxxx should be the name of the classification (for example, WEP). - * - * You then need to either add a IWL_xxxx_DEBUG() macro definition for your - * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want - * to send output to that classification. - * - * The active debug levels can be accessed via files - * - * /sys/module/iwlagn/parameters/debug{50} - * /sys/class/net/wlan0/device/debug_level - * - * when CONFIG_IWLWIFI_DEBUG=y. - */ - -/* 0x0000000F - 0x00000001 */ -#define IWL_DL_INFO (1 << 0) -#define IWL_DL_MAC80211 (1 << 1) -#define IWL_DL_HCMD (1 << 2) -#define IWL_DL_STATE (1 << 3) -/* 0x000000F0 - 0x00000010 */ -#define IWL_DL_MACDUMP (1 << 4) -#define IWL_DL_HCMD_DUMP (1 << 5) -#define IWL_DL_RADIO (1 << 7) -/* 0x00000F00 - 0x00000100 */ -#define IWL_DL_POWER (1 << 8) -#define IWL_DL_TEMP (1 << 9) -#define IWL_DL_NOTIF (1 << 10) -#define IWL_DL_SCAN (1 << 11) -/* 0x0000F000 - 0x00001000 */ -#define IWL_DL_ASSOC (1 << 12) -#define IWL_DL_DROP (1 << 13) -#define IWL_DL_TXPOWER (1 << 14) -#define IWL_DL_AP (1 << 15) -/* 0x000F0000 - 0x00010000 */ -#define IWL_DL_FW (1 << 16) -#define IWL_DL_RF_KILL (1 << 17) -#define IWL_DL_FW_ERRORS (1 << 18) -#define IWL_DL_LED (1 << 19) -/* 0x00F00000 - 0x00100000 */ -#define IWL_DL_RATE (1 << 20) -#define IWL_DL_CALIB (1 << 21) -#define IWL_DL_WEP (1 << 22) -#define IWL_DL_TX (1 << 23) -/* 0x0F000000 - 0x01000000 */ -#define IWL_DL_RX (1 << 24) -#define IWL_DL_ISR (1 << 25) -#define IWL_DL_HT (1 << 26) -#define IWL_DL_IO (1 << 27) -/* 0xF0000000 - 0x10000000 */ -#define IWL_DL_11H (1 << 28) -#define IWL_DL_STATS (1 << 29) -#define IWL_DL_TX_REPLY (1 << 30) -#define IWL_DL_QOS (1 << 31) - -#define IWL_DEBUG_INFO(p, f, a...) IWL_DEBUG(p, IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_MAC80211(p, f, a...) IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a) -#define IWL_DEBUG_MACDUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a) -#define IWL_DEBUG_TEMP(p, f, a...) IWL_DEBUG(p, IWL_DL_TEMP, f, ## a) -#define IWL_DEBUG_SCAN(p, f, a...) IWL_DEBUG(p, IWL_DL_SCAN, f, ## a) -#define IWL_DEBUG_RX(p, f, a...) IWL_DEBUG(p, IWL_DL_RX, f, ## a) -#define IWL_DEBUG_TX(p, f, a...) IWL_DEBUG(p, IWL_DL_TX, f, ## a) -#define IWL_DEBUG_ISR(p, f, a...) IWL_DEBUG(p, IWL_DL_ISR, f, ## a) -#define IWL_DEBUG_LED(p, f, a...) IWL_DEBUG(p, IWL_DL_LED, f, ## a) -#define IWL_DEBUG_WEP(p, f, a...) IWL_DEBUG(p, IWL_DL_WEP, f, ## a) -#define IWL_DEBUG_HC(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD, f, ## a) -#define IWL_DEBUG_HC_DUMP(p, f, a...) IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a) -#define IWL_DEBUG_CALIB(p, f, a...) IWL_DEBUG(p, IWL_DL_CALIB, f, ## a) -#define IWL_DEBUG_FW(p, f, a...) IWL_DEBUG(p, IWL_DL_FW, f, ## a) -#define IWL_DEBUG_RF_KILL(p, f, a...) IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a) -#define IWL_DEBUG_DROP(p, f, a...) IWL_DEBUG(p, IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_DROP_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a) -#define IWL_DEBUG_AP(p, f, a...) IWL_DEBUG(p, IWL_DL_AP, f, ## a) -#define IWL_DEBUG_TXPOWER(p, f, a...) IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a) -#define IWL_DEBUG_IO(p, f, a...) IWL_DEBUG(p, IWL_DL_IO, f, ## a) -#define IWL_DEBUG_RATE(p, f, a...) IWL_DEBUG(p, IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_RATE_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a) -#define IWL_DEBUG_NOTIF(p, f, a...) IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a) -#define IWL_DEBUG_ASSOC(p, f, a...) \ - IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a) -#define IWL_DEBUG_HT(p, f, a...) IWL_DEBUG(p, IWL_DL_HT, f, ## a) -#define IWL_DEBUG_STATS(p, f, a...) IWL_DEBUG(p, IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_STATS_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a) -#define IWL_DEBUG_TX_REPLY(p, f, a...) IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \ - IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a) -#define IWL_DEBUG_QOS(p, f, a...) IWL_DEBUG(p, IWL_DL_QOS, f, ## a) -#define IWL_DEBUG_RADIO(p, f, a...) IWL_DEBUG(p, IWL_DL_RADIO, f, ## a) -#define IWL_DEBUG_POWER(p, f, a...) IWL_DEBUG(p, IWL_DL_POWER, f, ## a) -#define IWL_DEBUG_11H(p, f, a...) IWL_DEBUG(p, IWL_DL_11H, f, ## a) - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c deleted file mode 100644 index a198bcf61022..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c +++ /dev/null @@ -1,1757 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include -#include -#include - -#include -#include - - -#include "iwl-dev.h" -#include "iwl-debug.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-calib.h" - -/* create and remove of files */ -#define DEBUGFS_ADD_DIR(name, parent) do { \ - dbgfs->dir_##name = debugfs_create_dir(#name, parent); \ - if (!(dbgfs->dir_##name)) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_FILE(name, parent) do { \ - dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_file(#name, S_IWUSR | S_IRUSR, \ - dbgfs->dir_##parent, priv, \ - &iwl_dbgfs_##name##_ops); \ - if (!(dbgfs->dbgfs_##parent##_files.file_##name)) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_BOOL(name, parent, ptr) do { \ - dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_bool(#name, S_IWUSR | S_IRUSR, \ - dbgfs->dir_##parent, ptr); \ - if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ - || !dbgfs->dbgfs_##parent##_files.file_##name) \ - goto err; \ -} while (0) - -#define DEBUGFS_ADD_X32(name, parent, ptr) do { \ - dbgfs->dbgfs_##parent##_files.file_##name = \ - debugfs_create_x32(#name, S_IRUSR, dbgfs->dir_##parent, ptr); \ - if (IS_ERR(dbgfs->dbgfs_##parent##_files.file_##name) \ - || !dbgfs->dbgfs_##parent##_files.file_##name) \ - goto err; \ -} while (0) - -#define DEBUGFS_REMOVE(name) do { \ - debugfs_remove(name); \ - name = NULL; \ -} while (0); - -/* file operation */ -#define DEBUGFS_READ_FUNC(name) \ -static ssize_t iwl_dbgfs_##name##_read(struct file *file, \ - char __user *user_buf, \ - size_t count, loff_t *ppos); - -#define DEBUGFS_WRITE_FUNC(name) \ -static ssize_t iwl_dbgfs_##name##_write(struct file *file, \ - const char __user *user_buf, \ - size_t count, loff_t *ppos); - - -static int iwl_dbgfs_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -#define DEBUGFS_READ_FILE_OPS(name) \ - DEBUGFS_READ_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ -}; - -#define DEBUGFS_WRITE_FILE_OPS(name) \ - DEBUGFS_WRITE_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .open = iwl_dbgfs_open_file_generic, \ -}; - - -#define DEBUGFS_READ_WRITE_FILE_OPS(name) \ - DEBUGFS_READ_FUNC(name); \ - DEBUGFS_WRITE_FUNC(name); \ -static const struct file_operations iwl_dbgfs_##name##_ops = { \ - .write = iwl_dbgfs_##name##_write, \ - .read = iwl_dbgfs_##name##_read, \ - .open = iwl_dbgfs_open_file_generic, \ -}; - - -static ssize_t iwl_dbgfs_tx_statistics_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char *buf; - int pos = 0; - - int cnt; - ssize_t ret; - const size_t bufsz = 100 + sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX); - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); - for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, - "\t%s\t\t: %u\n", - get_mgmt_string(cnt), - priv->tx_stats.mgmt[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "Control\n"); - for (cnt = 0; cnt < CONTROL_MAX; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, - "\t%s\t\t: %u\n", - get_ctrl_string(cnt), - priv->tx_stats.ctrl[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", - priv->tx_stats.data_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", - priv->tx_stats.data_bytes); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_tx_statistics_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - u32 clear_flag; - char buf[8]; - int buf_size; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x", &clear_flag) != 1) - return -EFAULT; - if (clear_flag == 1) - iwl_clear_tx_stats(priv); - - return count; -} - -static ssize_t iwl_dbgfs_rx_statistics_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char *buf; - int pos = 0; - int cnt; - ssize_t ret; - const size_t bufsz = 100 + - sizeof(char) * 24 * (MANAGEMENT_MAX + CONTROL_MAX); - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - pos += scnprintf(buf + pos, bufsz - pos, "Management:\n"); - for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, - "\t%s\t\t: %u\n", - get_mgmt_string(cnt), - priv->rx_stats.mgmt[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "Control:\n"); - for (cnt = 0; cnt < CONTROL_MAX; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, - "\t%s\t\t: %u\n", - get_ctrl_string(cnt), - priv->rx_stats.ctrl[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "Data:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n", - priv->rx_stats.data_cnt); - pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n", - priv->rx_stats.data_bytes); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_rx_statistics_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - u32 clear_flag; - char buf[8]; - int buf_size; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x", &clear_flag) != 1) - return -EFAULT; - if (clear_flag == 1) - iwl_clear_rx_stats(priv); - return count; -} - -#define BYTE1_MASK 0x000000ff; -#define BYTE2_MASK 0x0000ffff; -#define BYTE3_MASK 0x00ffffff; -static ssize_t iwl_dbgfs_sram_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - u32 val; - char buf[1024]; - ssize_t ret; - int i; - int pos = 0; - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - const size_t bufsz = sizeof(buf); - - for (i = priv->dbgfs->sram_len; i > 0; i -= 4) { - val = iwl_read_targ_mem(priv, priv->dbgfs->sram_offset + \ - priv->dbgfs->sram_len - i); - if (i < 4) { - switch (i) { - case 1: - val &= BYTE1_MASK; - break; - case 2: - val &= BYTE2_MASK; - break; - case 3: - val &= BYTE3_MASK; - break; - } - } - pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val); - } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; -} - -static ssize_t iwl_dbgfs_sram_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[64]; - int buf_size; - u32 offset, len; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - - if (sscanf(buf, "%x,%x", &offset, &len) == 2) { - priv->dbgfs->sram_offset = offset; - priv->dbgfs->sram_len = len; - } else { - priv->dbgfs->sram_offset = 0; - priv->dbgfs->sram_len = 0; - } - - return count; -} - -static ssize_t iwl_dbgfs_stations_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - struct iwl_station_entry *station; - int max_sta = priv->hw_params.max_stations; - char *buf; - int i, j, pos = 0; - ssize_t ret; - /* Add 30 for initial string */ - const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations); - - buf = kmalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n", - priv->num_stations); - - for (i = 0; i < max_sta; i++) { - station = &priv->stations[i]; - if (station->used) { - pos += scnprintf(buf + pos, bufsz - pos, - "station %d:\ngeneral data:\n", i+1); - pos += scnprintf(buf + pos, bufsz - pos, "id: %u\n", - station->sta.sta.sta_id); - pos += scnprintf(buf + pos, bufsz - pos, "mode: %u\n", - station->sta.mode); - pos += scnprintf(buf + pos, bufsz - pos, - "flags: 0x%x\n", - station->sta.station_flags_msk); - pos += scnprintf(buf + pos, bufsz - pos, - "ps_status: %u\n", station->ps_status); - pos += scnprintf(buf + pos, bufsz - pos, "tid data:\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "seq_num\t\ttxq_id"); - pos += scnprintf(buf + pos, bufsz - pos, - "\tframe_count\twait_for_ba\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "start_idx\tbitmap0\t"); - pos += scnprintf(buf + pos, bufsz - pos, - "bitmap1\trate_n_flags"); - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - - for (j = 0; j < MAX_TID_COUNT; j++) { - pos += scnprintf(buf + pos, bufsz - pos, - "[%d]:\t\t%u", j, - station->tid[j].seq_number); - pos += scnprintf(buf + pos, bufsz - pos, - "\t%u\t\t%u\t\t%u\t\t", - station->tid[j].agg.txq_id, - station->tid[j].agg.frame_count, - station->tid[j].agg.wait_for_ba); - pos += scnprintf(buf + pos, bufsz - pos, - "%u\t%llu\t%u", - station->tid[j].agg.start_idx, - (unsigned long long)station->tid[j].agg.bitmap, - station->tid[j].agg.rate_n_flags); - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - } - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_nvm_read(struct file *file, - char __user *user_buf, - size_t count, - loff_t *ppos) -{ - ssize_t ret; - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0, ofs = 0, buf_size = 0; - const u8 *ptr; - char *buf; - size_t eeprom_len = priv->cfg->eeprom_size; - buf_size = 4 * eeprom_len + 256; - - if (eeprom_len % 16) { - IWL_ERR(priv, "NVM size is not multiple of 16.\n"); - return -ENODATA; - } - - ptr = priv->eeprom; - if (!ptr) { - IWL_ERR(priv, "Invalid EEPROM/OTP memory\n"); - return -ENOMEM; - } - - /* 4 characters for byte 0xYY */ - buf = kzalloc(buf_size, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - pos += scnprintf(buf + pos, buf_size - pos, "NVM Type: %s\n", - (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) - ? "OTP" : "EEPROM"); - for (ofs = 0 ; ofs < eeprom_len ; ofs += 16) { - pos += scnprintf(buf + pos, buf_size - pos, "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16 , 16, 2, buf + pos, - buf_size - pos, 0); - pos += strlen(buf + pos); - if (buf_size - pos > 0) - buf[pos++] = '\n'; - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_log_event_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - u32 event_log_flag; - char buf[8]; - int buf_size; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &event_log_flag) != 1) - return -EFAULT; - if (event_log_flag == 1) - priv->cfg->ops->lib->dump_nic_event_log(priv); - - return count; -} - - - -static ssize_t iwl_dbgfs_channels_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - struct ieee80211_channel *channels = NULL; - const struct ieee80211_supported_band *supp_band = NULL; - int pos = 0, i, bufsz = PAGE_SIZE; - char *buf; - ssize_t ret; - - if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status)) - return -EAGAIN; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ); - if (supp_band) { - channels = supp_band->channels; - - pos += scnprintf(buf + pos, bufsz - pos, - "Displaying %d channels in 2.4GHz band 802.11bg):\n", - supp_band->n_channels); - - for (i = 0; i < supp_band->n_channels; i++) - pos += scnprintf(buf + pos, bufsz - pos, - "%d: %ddBm: BSS%s%s, %s.\n", - ieee80211_frequency_to_channel( - channels[i].center_freq), - channels[i].max_power, - channels[i].flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", - ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) - || (channels[i].flags & - IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i].flags & - IEEE80211_CHAN_PASSIVE_SCAN ? - "passive only" : "active/passive"); - } - supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_5GHZ); - if (supp_band) { - channels = supp_band->channels; - - pos += scnprintf(buf + pos, bufsz - pos, - "Displaying %d channels in 5.2GHz band (802.11a)\n", - supp_band->n_channels); - - for (i = 0; i < supp_band->n_channels; i++) - pos += scnprintf(buf + pos, bufsz - pos, - "%d: %ddBm: BSS%s%s, %s.\n", - ieee80211_frequency_to_channel( - channels[i].center_freq), - channels[i].max_power, - channels[i].flags & IEEE80211_CHAN_RADAR ? - " (IEEE 802.11h required)" : "", - ((channels[i].flags & IEEE80211_CHAN_NO_IBSS) - || (channels[i].flags & - IEEE80211_CHAN_RADAR)) ? "" : - ", IBSS", - channels[i].flags & - IEEE80211_CHAN_PASSIVE_SCAN ? - "passive only" : "active/passive"); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_status_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char buf[512]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n", - test_bit(STATUS_HCMD_ACTIVE, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_SYNC_ACTIVE: %d\n", - test_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n", - test_bit(STATUS_INT_ENABLED, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_RF_KILL_HW:\t %d\n", - test_bit(STATUS_RF_KILL_HW, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INIT:\t\t %d\n", - test_bit(STATUS_INIT, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_ALIVE:\t\t %d\n", - test_bit(STATUS_ALIVE, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n", - test_bit(STATUS_READY, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n", - test_bit(STATUS_TEMPERATURE, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n", - test_bit(STATUS_GEO_CONFIGURED, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_EXIT_PENDING:\t %d\n", - test_bit(STATUS_EXIT_PENDING, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_STATISTICS:\t %d\n", - test_bit(STATUS_STATISTICS, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n", - test_bit(STATUS_SCANNING, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n", - test_bit(STATUS_SCAN_ABORTING, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n", - test_bit(STATUS_SCAN_HW, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n", - test_bit(STATUS_POWER_PMI, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n", - test_bit(STATUS_FW_ERROR, &priv->status)); - pos += scnprintf(buf + pos, bufsz - pos, "STATUS_MODE_PENDING:\t %d\n", - test_bit(STATUS_MODE_PENDING, &priv->status)); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_interrupt_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - int cnt = 0; - char *buf; - int bufsz = 24 * 64; /* 24 items * 64 char per item */ - ssize_t ret; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - pos += scnprintf(buf + pos, bufsz - pos, - "Interrupt Statistics Report:\n"); - - pos += scnprintf(buf + pos, bufsz - pos, "HW Error:\t\t\t %u\n", - priv->isr_stats.hw); - pos += scnprintf(buf + pos, bufsz - pos, "SW Error:\t\t\t %u\n", - priv->isr_stats.sw); - if (priv->isr_stats.sw > 0) { - pos += scnprintf(buf + pos, bufsz - pos, - "\tLast Restarting Code: 0x%X\n", - priv->isr_stats.sw_err); - } -#ifdef CONFIG_IWLWIFI_DEBUG - pos += scnprintf(buf + pos, bufsz - pos, "Frame transmitted:\t\t %u\n", - priv->isr_stats.sch); - pos += scnprintf(buf + pos, bufsz - pos, "Alive interrupt:\t\t %u\n", - priv->isr_stats.alive); -#endif - pos += scnprintf(buf + pos, bufsz - pos, - "HW RF KILL switch toggled:\t %u\n", - priv->isr_stats.rfkill); - - pos += scnprintf(buf + pos, bufsz - pos, "CT KILL:\t\t\t %u\n", - priv->isr_stats.ctkill); - - pos += scnprintf(buf + pos, bufsz - pos, "Wakeup Interrupt:\t\t %u\n", - priv->isr_stats.wakeup); - - pos += scnprintf(buf + pos, bufsz - pos, - "Rx command responses:\t\t %u\n", - priv->isr_stats.rx); - for (cnt = 0; cnt < REPLY_MAX; cnt++) { - if (priv->isr_stats.rx_handlers[cnt] > 0) - pos += scnprintf(buf + pos, bufsz - pos, - "\tRx handler[%36s]:\t\t %u\n", - get_cmd_string(cnt), - priv->isr_stats.rx_handlers[cnt]); - } - - pos += scnprintf(buf + pos, bufsz - pos, "Tx/FH interrupt:\t\t %u\n", - priv->isr_stats.tx); - - pos += scnprintf(buf + pos, bufsz - pos, "Unexpected INTA:\t\t %u\n", - priv->isr_stats.unhandled); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_interrupt_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - u32 reset_flag; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%x", &reset_flag) != 1) - return -EFAULT; - if (reset_flag == 0) - iwl_clear_isr_stats(priv); - - return count; -} - -static ssize_t iwl_dbgfs_qos_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0, i; - char buf[256]; - const size_t bufsz = sizeof(buf); - ssize_t ret; - - for (i = 0; i < AC_NUM; i++) { - pos += scnprintf(buf + pos, bufsz - pos, - "\tcw_min\tcw_max\taifsn\ttxop\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "AC[%d]\t%u\t%u\t%u\t%u\n", i, - priv->qos_data.def_qos_parm.ac[i].cw_min, - priv->qos_data.def_qos_parm.ac[i].cw_max, - priv->qos_data.def_qos_parm.ac[i].aifsn, - priv->qos_data.def_qos_parm.ac[i].edca_txop); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; -} - -#ifdef CONFIG_IWLWIFI_LEDS -static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - char buf[256]; - const size_t bufsz = sizeof(buf); - ssize_t ret; - - pos += scnprintf(buf + pos, bufsz - pos, - "allow blinking: %s\n", - (priv->allow_blinking) ? "True" : "False"); - if (priv->allow_blinking) { - pos += scnprintf(buf + pos, bufsz - pos, - "Led blinking rate: %u\n", - priv->last_blink_rate); - pos += scnprintf(buf + pos, bufsz - pos, - "Last blink time: %lu\n", - priv->last_blink_time); - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; -} -#endif - -static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - char buf[100]; - int pos = 0; - const size_t bufsz = sizeof(buf); - ssize_t ret; - - pos += scnprintf(buf + pos, bufsz - pos, - "Thermal Throttling Mode: %s\n", - tt->advanced_tt ? "Advance" : "Legacy"); - pos += scnprintf(buf + pos, bufsz - pos, - "Thermal Throttling State: %d\n", - tt->state); - if (tt->advanced_tt) { - restriction = tt->restriction + tt->state; - pos += scnprintf(buf + pos, bufsz - pos, - "Tx mode: %d\n", - restriction->tx_stream); - pos += scnprintf(buf + pos, bufsz - pos, - "Rx mode: %d\n", - restriction->rx_stream); - pos += scnprintf(buf + pos, bufsz - pos, - "HT mode: %d\n", - restriction->is_ht); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; -} - -static ssize_t iwl_dbgfs_disable_ht40_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - int ht40; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &ht40) != 1) - return -EFAULT; - if (!iwl_is_associated(priv)) - priv->disable_ht40 = ht40 ? true : false; - else { - IWL_ERR(priv, "Sta associated with AP - " - "Change to 40MHz channel support is not allowed\n"); - return -EINVAL; - } - - return count; -} - -static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char buf[100]; - int pos = 0; - const size_t bufsz = sizeof(buf); - ssize_t ret; - - pos += scnprintf(buf + pos, bufsz - pos, - "11n 40MHz Mode: %s\n", - priv->disable_ht40 ? "Disabled" : "Enabled"); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - return ret; -} - -static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - int value; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - - if (sscanf(buf, "%d", &value) != 1) - return -EINVAL; - - /* - * Our users expect 0 to be "CAM", but 0 isn't actually - * valid here. However, let's not confuse them and present - * IWL_POWER_INDEX_1 as "1", not "0". - */ - if (value > 0) - value -= 1; - - if (value != -1 && (value < 0 || value >= IWL_POWER_NUM)) - return -EINVAL; - - priv->power_data.debug_sleep_level_override = value; - - iwl_power_update_mode(priv, false); - - return count; -} - -static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char buf[10]; - int pos, value; - const size_t bufsz = sizeof(buf); - - /* see the write function */ - value = priv->power_data.debug_sleep_level_override; - if (value >= 0) - value += 1; - - pos = scnprintf(buf, bufsz, "%d\n", value); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char buf[200]; - int pos = 0, i; - const size_t bufsz = sizeof(buf); - struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd; - - pos += scnprintf(buf + pos, bufsz - pos, - "flags: %#.2x\n", le16_to_cpu(cmd->flags)); - pos += scnprintf(buf + pos, bufsz - pos, - "RX/TX timeout: %d/%d usec\n", - le32_to_cpu(cmd->rx_data_timeout), - le32_to_cpu(cmd->tx_data_timeout)); - for (i = 0; i < IWL_POWER_VEC_SIZE; i++) - pos += scnprintf(buf + pos, bufsz - pos, - "sleep_interval[%d]: %d\n", i, - le32_to_cpu(cmd->sleep_interval[i])); - - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -DEBUGFS_READ_WRITE_FILE_OPS(sram); -DEBUGFS_WRITE_FILE_OPS(log_event); -DEBUGFS_READ_FILE_OPS(nvm); -DEBUGFS_READ_FILE_OPS(stations); -DEBUGFS_READ_FILE_OPS(channels); -DEBUGFS_READ_FILE_OPS(status); -DEBUGFS_READ_WRITE_FILE_OPS(interrupt); -DEBUGFS_READ_FILE_OPS(qos); -#ifdef CONFIG_IWLWIFI_LEDS -DEBUGFS_READ_FILE_OPS(led); -#endif -DEBUGFS_READ_FILE_OPS(thermal_throttling); -DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); -DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override); -DEBUGFS_READ_FILE_OPS(current_sleep_command); - -static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - int pos = 0, ofs = 0; - int cnt = 0, entry; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_rx_queue *rxq = &priv->rxq; - char *buf; - int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) + - (IWL_MAX_NUM_QUEUES * 32 * 8) + 400; - const u8 *ptr; - ssize_t ret; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate buffer\n"); - return -ENOMEM; - } - pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n"); - for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { - txq = &priv->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "q[%d]: read_ptr: %u, write_ptr: %u\n", - cnt, q->read_ptr, q->write_ptr); - } - if (priv->tx_traffic && (iwl_debug_level & IWL_DL_TX)) { - ptr = priv->tx_traffic; - pos += scnprintf(buf + pos, bufsz - pos, - "Tx Traffic idx: %u\n", priv->tx_traffic_idx); - for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { - for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; - entry++, ofs += 16) { - pos += scnprintf(buf + pos, bufsz - pos, - "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16, 16, 2, - buf + pos, bufsz - pos, 0); - pos += strlen(buf + pos); - if (bufsz - pos > 0) - buf[pos++] = '\n'; - } - } - } - - pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n"); - pos += scnprintf(buf + pos, bufsz - pos, - "read: %u, write: %u\n", - rxq->read, rxq->write); - - if (priv->rx_traffic && (iwl_debug_level & IWL_DL_RX)) { - ptr = priv->rx_traffic; - pos += scnprintf(buf + pos, bufsz - pos, - "Rx Traffic idx: %u\n", priv->rx_traffic_idx); - for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) { - for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16; - entry++, ofs += 16) { - pos += scnprintf(buf + pos, bufsz - pos, - "0x%.4x ", ofs); - hex_dump_to_buffer(ptr + ofs, 16, 16, 2, - buf + pos, bufsz - pos, 0); - pos += strlen(buf + pos); - if (bufsz - pos > 0) - buf[pos++] = '\n'; - } - } - } - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_traffic_log_write(struct file *file, - const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = file->private_data; - char buf[8]; - int buf_size; - int traffic_log; - - memset(buf, 0, sizeof(buf)); - buf_size = min(count, sizeof(buf) - 1); - if (copy_from_user(buf, user_buf, buf_size)) - return -EFAULT; - if (sscanf(buf, "%d", &traffic_log) != 1) - return -EFAULT; - if (traffic_log == 0) - iwl_reset_traffic_log(priv); - - return count; -} - -static ssize_t iwl_dbgfs_tx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - struct iwl_tx_queue *txq; - struct iwl_queue *q; - char *buf; - int pos = 0; - int cnt; - int ret; - const size_t bufsz = sizeof(char) * 60 * IWL_MAX_NUM_QUEUES; - - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) { - txq = &priv->txq[cnt]; - q = &txq->q; - pos += scnprintf(buf + pos, bufsz - pos, - "hwq %.2d: read=%u write=%u stop=%d" - " swq_id=%#.2x (ac %d/hwq %d)\n", - cnt, q->read_ptr, q->write_ptr, - !!test_bit(cnt, priv->queue_stopped), - txq->swq_id, - txq->swq_id & 0x80 ? txq->swq_id & 3 : - txq->swq_id, - txq->swq_id & 0x80 ? (txq->swq_id >> 2) & - 0x1f : txq->swq_id); - if (cnt >= 4) - continue; - /* for the ACs, display the stop count too */ - pos += scnprintf(buf + pos, bufsz - pos, - " stop-count: %d\n", - atomic_read(&priv->queue_stop_count[cnt])); - } - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_rx_queue_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - struct iwl_rx_queue *rxq = &priv->rxq; - char buf[256]; - int pos = 0; - const size_t bufsz = sizeof(buf); - - pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n", - rxq->read); - pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n", - rxq->write); - pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n", - rxq->free_count); - pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n", - le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF); - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -#define UCODE_STATISTICS_CLEAR_MSK (0x1 << 0) -#define UCODE_STATISTICS_FREQUENCY_MSK (0x1 << 1) -#define UCODE_STATISTICS_NARROW_BAND_MSK (0x1 << 2) - -static int iwl_dbgfs_statistics_flag(struct iwl_priv *priv, char *buf, - int bufsz) -{ - int p = 0; - - p += scnprintf(buf + p, bufsz - p, - "Statistics Flag(0x%X):\n", - le32_to_cpu(priv->statistics.flag)); - if (le32_to_cpu(priv->statistics.flag) & UCODE_STATISTICS_CLEAR_MSK) - p += scnprintf(buf + p, bufsz - p, - "\tStatistics have been cleared\n"); - p += scnprintf(buf + p, bufsz - p, - "\tOperational Frequency: %s\n", - (le32_to_cpu(priv->statistics.flag) & - UCODE_STATISTICS_FREQUENCY_MSK) - ? "2.4 GHz" : "5.2 GHz"); - p += scnprintf(buf + p, bufsz - p, - "\tTGj Narrow Band: %s\n", - (le32_to_cpu(priv->statistics.flag) & - UCODE_STATISTICS_NARROW_BAND_MSK) - ? "enabled" : "disabled"); - return p; -} - - -static ssize_t iwl_dbgfs_ucode_rx_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - char *buf; - int bufsz = sizeof(struct statistics_rx_phy) * 20 + - sizeof(struct statistics_rx_non_phy) * 20 + - sizeof(struct statistics_rx_ht_phy) * 20 + 400; - ssize_t ret; - struct statistics_rx_phy *ofdm; - struct statistics_rx_phy *cck; - struct statistics_rx_non_phy *general; - struct statistics_rx_ht_phy *ht; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, 0); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - ofdm = &priv->statistics.rx.ofdm; - cck = &priv->statistics.rx.cck; - general = &priv->statistics.rx.general; - ht = &priv->statistics.rx.ofdm_ht; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n", - le32_to_cpu(ofdm->ina_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n", - le32_to_cpu(ofdm->fina_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", - le32_to_cpu(ofdm->plcp_err)); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", - le32_to_cpu(ofdm->crc32_err)); - pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", - le32_to_cpu(ofdm->overrun_err)); - pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", - le32_to_cpu(ofdm->early_overrun_err)); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", - le32_to_cpu(ofdm->crc32_good)); - pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n", - le32_to_cpu(ofdm->false_alarm_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n", - le32_to_cpu(ofdm->fina_sync_err_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n", - le32_to_cpu(ofdm->sfd_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n", - le32_to_cpu(ofdm->fina_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n", - le32_to_cpu(ofdm->unresponded_rts)); - pos += scnprintf(buf + pos, bufsz - pos, - "rxe_frame_limit_overrun: %u\n", - le32_to_cpu(ofdm->rxe_frame_limit_overrun)); - pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n", - le32_to_cpu(ofdm->sent_ack_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n", - le32_to_cpu(ofdm->sent_cts_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n", - le32_to_cpu(ofdm->sent_ba_rsp_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n", - le32_to_cpu(ofdm->dsp_self_kill)); - pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", - le32_to_cpu(ofdm->mh_format_err)); - pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n", - le32_to_cpu(ofdm->re_acq_main_rssi_sum)); - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - CCK:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "ina_cnt: %u\n", - le32_to_cpu(cck->ina_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "fina_cnt: %u\n", - le32_to_cpu(cck->fina_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", - le32_to_cpu(cck->plcp_err)); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", - le32_to_cpu(cck->crc32_err)); - pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", - le32_to_cpu(cck->overrun_err)); - pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", - le32_to_cpu(cck->early_overrun_err)); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", - le32_to_cpu(cck->crc32_good)); - pos += scnprintf(buf + pos, bufsz - pos, "false_alarm_cnt: %u\n", - le32_to_cpu(cck->false_alarm_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "fina_sync_err_cnt: %u\n", - le32_to_cpu(cck->fina_sync_err_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "sfd_timeout: %u\n", - le32_to_cpu(cck->sfd_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, "fina_timeout: %u\n", - le32_to_cpu(cck->fina_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, "unresponded_rts: %u\n", - le32_to_cpu(cck->unresponded_rts)); - pos += scnprintf(buf + pos, bufsz - pos, - "rxe_frame_limit_overrun: %u\n", - le32_to_cpu(cck->rxe_frame_limit_overrun)); - pos += scnprintf(buf + pos, bufsz - pos, "sent_ack_cnt: %u\n", - le32_to_cpu(cck->sent_ack_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "sent_cts_cnt: %u\n", - le32_to_cpu(cck->sent_cts_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "sent_ba_rsp_cnt: %u\n", - le32_to_cpu(cck->sent_ba_rsp_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "dsp_self_kill: %u\n", - le32_to_cpu(cck->dsp_self_kill)); - pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", - le32_to_cpu(cck->mh_format_err)); - pos += scnprintf(buf + pos, bufsz - pos, "re_acq_main_rssi_sum: %u\n", - le32_to_cpu(cck->re_acq_main_rssi_sum)); - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - GENERAL:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "bogus_cts: %u\n", - le32_to_cpu(general->bogus_cts)); - pos += scnprintf(buf + pos, bufsz - pos, "bogus_ack: %u\n", - le32_to_cpu(general->bogus_ack)); - pos += scnprintf(buf + pos, bufsz - pos, "non_bssid_frames: %u\n", - le32_to_cpu(general->non_bssid_frames)); - pos += scnprintf(buf + pos, bufsz - pos, "filtered_frames: %u\n", - le32_to_cpu(general->filtered_frames)); - pos += scnprintf(buf + pos, bufsz - pos, "non_channel_beacons: %u\n", - le32_to_cpu(general->non_channel_beacons)); - pos += scnprintf(buf + pos, bufsz - pos, "channel_beacons: %u\n", - le32_to_cpu(general->channel_beacons)); - pos += scnprintf(buf + pos, bufsz - pos, "num_missed_bcon: %u\n", - le32_to_cpu(general->num_missed_bcon)); - pos += scnprintf(buf + pos, bufsz - pos, - "adc_rx_saturation_time: %u\n", - le32_to_cpu(general->adc_rx_saturation_time)); - pos += scnprintf(buf + pos, bufsz - pos, - "ina_detection_search_time: %u\n", - le32_to_cpu(general->ina_detection_search_time)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_a: %u\n", - le32_to_cpu(general->beacon_silence_rssi_a)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_b: %u\n", - le32_to_cpu(general->beacon_silence_rssi_b)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_silence_rssi_c: %u\n", - le32_to_cpu(general->beacon_silence_rssi_c)); - pos += scnprintf(buf + pos, bufsz - pos, - "interference_data_flag: %u\n", - le32_to_cpu(general->interference_data_flag)); - pos += scnprintf(buf + pos, bufsz - pos, "channel_load: %u\n", - le32_to_cpu(general->channel_load)); - pos += scnprintf(buf + pos, bufsz - pos, "dsp_false_alarms: %u\n", - le32_to_cpu(general->dsp_false_alarms)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_a: %u\n", - le32_to_cpu(general->beacon_rssi_a)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_b: %u\n", - le32_to_cpu(general->beacon_rssi_b)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_rssi_c: %u\n", - le32_to_cpu(general->beacon_rssi_c)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_a: %u\n", - le32_to_cpu(general->beacon_energy_a)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_b: %u\n", - le32_to_cpu(general->beacon_energy_b)); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_energy_c: %u\n", - le32_to_cpu(general->beacon_energy_c)); - - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Rx - OFDM_HT:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "plcp_err: %u\n", - le32_to_cpu(ht->plcp_err)); - pos += scnprintf(buf + pos, bufsz - pos, "overrun_err: %u\n", - le32_to_cpu(ht->overrun_err)); - pos += scnprintf(buf + pos, bufsz - pos, "early_overrun_err: %u\n", - le32_to_cpu(ht->early_overrun_err)); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_good: %u\n", - le32_to_cpu(ht->crc32_good)); - pos += scnprintf(buf + pos, bufsz - pos, "crc32_err: %u\n", - le32_to_cpu(ht->crc32_err)); - pos += scnprintf(buf + pos, bufsz - pos, "mh_format_err: %u\n", - le32_to_cpu(ht->mh_format_err)); - pos += scnprintf(buf + pos, bufsz - pos, "agg_crc32_good: %u\n", - le32_to_cpu(ht->agg_crc32_good)); - pos += scnprintf(buf + pos, bufsz - pos, "agg_mpdu_cnt: %u\n", - le32_to_cpu(ht->agg_mpdu_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "agg_cnt: %u\n", - le32_to_cpu(ht->agg_cnt)); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_ucode_tx_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - char *buf; - int bufsz = (sizeof(struct statistics_tx) * 24) + 250; - ssize_t ret; - struct statistics_tx *tx; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, 0); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - tx = &priv->statistics.tx; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_Tx:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "preamble: %u\n", - le32_to_cpu(tx->preamble_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "rx_detected_cnt: %u\n", - le32_to_cpu(tx->rx_detected_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_defer_cnt: %u\n", - le32_to_cpu(tx->bt_prio_defer_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "bt_prio_kill_cnt: %u\n", - le32_to_cpu(tx->bt_prio_kill_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "few_bytes_cnt: %u\n", - le32_to_cpu(tx->few_bytes_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout: %u\n", - le32_to_cpu(tx->cts_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, "ack_timeout: %u\n", - le32_to_cpu(tx->ack_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, "expected_ack_cnt: %u\n", - le32_to_cpu(tx->expected_ack_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "actual_ack_cnt: %u\n", - le32_to_cpu(tx->actual_ack_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "dump_msdu_cnt: %u\n", - le32_to_cpu(tx->dump_msdu_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, - "burst_abort_next_frame_mismatch_cnt: %u\n", - le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, - "burst_abort_missing_next_frame_cnt: %u\n", - le32_to_cpu(tx->burst_abort_missing_next_frame_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "cts_timeout_collision: %u\n", - le32_to_cpu(tx->cts_timeout_collision)); - pos += scnprintf(buf + pos, bufsz - pos, - "ack_or_ba_timeout_collision: %u\n", - le32_to_cpu(tx->ack_or_ba_timeout_collision)); - pos += scnprintf(buf + pos, bufsz - pos, "agg ba_timeout: %u\n", - le32_to_cpu(tx->agg.ba_timeout)); - pos += scnprintf(buf + pos, bufsz - pos, - "agg ba_reschedule_frames: %u\n", - le32_to_cpu(tx->agg.ba_reschedule_frames)); - pos += scnprintf(buf + pos, bufsz - pos, - "agg scd_query_agg_frame_cnt: %u\n", - le32_to_cpu(tx->agg.scd_query_agg_frame_cnt)); - pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_no_agg: %u\n", - le32_to_cpu(tx->agg.scd_query_no_agg)); - pos += scnprintf(buf + pos, bufsz - pos, "agg scd_query_agg: %u\n", - le32_to_cpu(tx->agg.scd_query_agg)); - pos += scnprintf(buf + pos, bufsz - pos, - "agg scd_query_mismatch: %u\n", - le32_to_cpu(tx->agg.scd_query_mismatch)); - pos += scnprintf(buf + pos, bufsz - pos, "agg frame_not_ready: %u\n", - le32_to_cpu(tx->agg.frame_not_ready)); - pos += scnprintf(buf + pos, bufsz - pos, "agg underrun: %u\n", - le32_to_cpu(tx->agg.underrun)); - pos += scnprintf(buf + pos, bufsz - pos, "agg bt_prio_kill: %u\n", - le32_to_cpu(tx->agg.bt_prio_kill)); - pos += scnprintf(buf + pos, bufsz - pos, "agg rx_ba_rsp_cnt: %u\n", - le32_to_cpu(tx->agg.rx_ba_rsp_cnt)); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_ucode_general_stats_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - char *buf; - int bufsz = sizeof(struct statistics_general) * 4 + 250; - ssize_t ret; - struct statistics_general *general; - struct statistics_dbg *dbg; - struct statistics_div *div; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, 0); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, - "Error sending statistics request: %zd\n", ret); - return -EAGAIN; - } - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - /* the statistic information display here is based on - * the last statistics notification from uCode - * might not reflect the current uCode activity - */ - general = &priv->statistics.general; - dbg = &priv->statistics.general.dbg; - div = &priv->statistics.general.div; - pos += iwl_dbgfs_statistics_flag(priv, buf, bufsz); - pos += scnprintf(buf + pos, bufsz - pos, "Statistics_General:\n"); - pos += scnprintf(buf + pos, bufsz - pos, "temperature: %u\n", - le32_to_cpu(general->temperature)); - pos += scnprintf(buf + pos, bufsz - pos, "temperature_m: %u\n", - le32_to_cpu(general->temperature_m)); - pos += scnprintf(buf + pos, bufsz - pos, "burst_check: %u\n", - le32_to_cpu(dbg->burst_check)); - pos += scnprintf(buf + pos, bufsz - pos, "burst_count: %u\n", - le32_to_cpu(dbg->burst_count)); - pos += scnprintf(buf + pos, bufsz - pos, "sleep_time: %u\n", - le32_to_cpu(general->sleep_time)); - pos += scnprintf(buf + pos, bufsz - pos, "slots_out: %u\n", - le32_to_cpu(general->slots_out)); - pos += scnprintf(buf + pos, bufsz - pos, "slots_idle: %u\n", - le32_to_cpu(general->slots_idle)); - pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp: %u\n", - le32_to_cpu(general->ttl_timestamp)); - pos += scnprintf(buf + pos, bufsz - pos, "tx_on_a: %u\n", - le32_to_cpu(div->tx_on_a)); - pos += scnprintf(buf + pos, bufsz - pos, "tx_on_b: %u\n", - le32_to_cpu(div->tx_on_b)); - pos += scnprintf(buf + pos, bufsz - pos, "exec_time: %u\n", - le32_to_cpu(div->exec_time)); - pos += scnprintf(buf + pos, bufsz - pos, "probe_time: %u\n", - le32_to_cpu(div->probe_time)); - pos += scnprintf(buf + pos, bufsz - pos, "rx_enable_counter: %u\n", - le32_to_cpu(general->rx_enable_counter)); - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_sensitivity_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - int cnt = 0; - char *buf; - int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100; - ssize_t ret; - struct iwl_sensitivity_data *data; - - data = &priv->sensitivity_data; - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n", - data->auto_corr_ofdm); - pos += scnprintf(buf + pos, bufsz - pos, - "auto_corr_ofdm_mrc:\t\t %u\n", - data->auto_corr_ofdm_mrc); - pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n", - data->auto_corr_ofdm_x1); - pos += scnprintf(buf + pos, bufsz - pos, - "auto_corr_ofdm_mrc_x1:\t\t %u\n", - data->auto_corr_ofdm_mrc_x1); - pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n", - data->auto_corr_cck); - pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n", - data->auto_corr_cck_mrc); - pos += scnprintf(buf + pos, bufsz - pos, - "last_bad_plcp_cnt_ofdm:\t\t %u\n", - data->last_bad_plcp_cnt_ofdm); - pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n", - data->last_fa_cnt_ofdm); - pos += scnprintf(buf + pos, bufsz - pos, - "last_bad_plcp_cnt_cck:\t\t %u\n", - data->last_bad_plcp_cnt_cck); - pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n", - data->last_fa_cnt_cck); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n", - data->nrg_curr_state); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n", - data->nrg_prev_state); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t"); - for (cnt = 0; cnt < 10; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, " %u", - data->nrg_value[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t"); - for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, " %u", - data->nrg_silence_rssi[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n", - data->nrg_silence_ref); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n", - data->nrg_energy_idx); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n", - data->nrg_silence_idx); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n", - data->nrg_th_cck); - pos += scnprintf(buf + pos, bufsz - pos, - "nrg_auto_corr_silence_diff:\t %u\n", - data->nrg_auto_corr_silence_diff); - pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n", - data->num_in_cck_no_fa); - pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n", - data->nrg_th_ofdm); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - - -static ssize_t iwl_dbgfs_chain_noise_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - int pos = 0; - int cnt = 0; - char *buf; - int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100; - ssize_t ret; - struct iwl_chain_noise_data *data; - - data = &priv->chain_noise_data; - buf = kzalloc(bufsz, GFP_KERNEL); - if (!buf) { - IWL_ERR(priv, "Can not allocate Buffer\n"); - return -ENOMEM; - } - - pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n", - data->active_chains); - pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n", - data->chain_noise_a); - pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n", - data->chain_noise_b); - pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n", - data->chain_noise_c); - pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n", - data->chain_signal_a); - pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n", - data->chain_signal_b); - pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n", - data->chain_signal_c); - pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n", - data->beacon_count); - - pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t"); - for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, " %u", - data->disconn_array[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t"); - for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) { - pos += scnprintf(buf + pos, bufsz - pos, " %u", - data->delta_gain_code[cnt]); - } - pos += scnprintf(buf + pos, bufsz - pos, "\n"); - pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n", - data->radio_write); - pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n", - data->state); - - ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); - kfree(buf); - return ret; -} - -static ssize_t iwl_dbgfs_tx_power_read(struct file *file, - char __user *user_buf, - size_t count, loff_t *ppos) { - - struct iwl_priv *priv = (struct iwl_priv *)file->private_data; - char buf[128]; - int pos = 0; - ssize_t ret; - const size_t bufsz = sizeof(buf); - struct statistics_tx *tx; - - if (!iwl_is_alive(priv)) - pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); - else { - /* make request to uCode to retrieve statistics information */ - mutex_lock(&priv->mutex); - ret = iwl_send_statistics_request(priv, 0); - mutex_unlock(&priv->mutex); - - if (ret) { - IWL_ERR(priv, "Error sending statistics request: %zd\n", - ret); - return -EAGAIN; - } - tx = &priv->statistics.tx; - if (tx->tx_power.ant_a || - tx->tx_power.ant_b || - tx->tx_power.ant_c) { - pos += scnprintf(buf + pos, bufsz - pos, - "tx power: (1/2 dB step)\n"); - if ((priv->cfg->valid_tx_ant & ANT_A) && - tx->tx_power.ant_a) - pos += scnprintf(buf + pos, bufsz - pos, - "\tantenna A: 0x%X\n", - tx->tx_power.ant_a); - if ((priv->cfg->valid_tx_ant & ANT_B) && - tx->tx_power.ant_b) - pos += scnprintf(buf + pos, bufsz - pos, - "\tantenna B: 0x%X\n", - tx->tx_power.ant_b); - if ((priv->cfg->valid_tx_ant & ANT_C) && - tx->tx_power.ant_c) - pos += scnprintf(buf + pos, bufsz - pos, - "\tantenna C: 0x%X\n", - tx->tx_power.ant_c); - } else - pos += scnprintf(buf + pos, bufsz - pos, "N/A\n"); - } - return simple_read_from_buffer(user_buf, count, ppos, buf, pos); -} - -DEBUGFS_READ_WRITE_FILE_OPS(rx_statistics); -DEBUGFS_READ_WRITE_FILE_OPS(tx_statistics); -DEBUGFS_READ_WRITE_FILE_OPS(traffic_log); -DEBUGFS_READ_FILE_OPS(rx_queue); -DEBUGFS_READ_FILE_OPS(tx_queue); -DEBUGFS_READ_FILE_OPS(ucode_rx_stats); -DEBUGFS_READ_FILE_OPS(ucode_tx_stats); -DEBUGFS_READ_FILE_OPS(ucode_general_stats); -DEBUGFS_READ_FILE_OPS(sensitivity); -DEBUGFS_READ_FILE_OPS(chain_noise); -DEBUGFS_READ_FILE_OPS(tx_power); - -/* - * Create the debugfs files and directories - * - */ -int iwl_dbgfs_register(struct iwl_priv *priv, const char *name) -{ - struct iwl_debugfs *dbgfs; - struct dentry *phyd = priv->hw->wiphy->debugfsdir; - int ret = 0; - - dbgfs = kzalloc(sizeof(struct iwl_debugfs), GFP_KERNEL); - if (!dbgfs) { - ret = -ENOMEM; - goto err; - } - - priv->dbgfs = dbgfs; - dbgfs->name = name; - dbgfs->dir_drv = debugfs_create_dir(name, phyd); - if (!dbgfs->dir_drv || IS_ERR(dbgfs->dir_drv)) { - ret = -ENOENT; - goto err; - } - - DEBUGFS_ADD_DIR(data, dbgfs->dir_drv); - DEBUGFS_ADD_DIR(rf, dbgfs->dir_drv); - DEBUGFS_ADD_DIR(debug, dbgfs->dir_drv); - DEBUGFS_ADD_FILE(nvm, data); - DEBUGFS_ADD_FILE(sram, data); - DEBUGFS_ADD_FILE(log_event, data); - DEBUGFS_ADD_FILE(stations, data); - DEBUGFS_ADD_FILE(channels, data); - DEBUGFS_ADD_FILE(status, data); - DEBUGFS_ADD_FILE(interrupt, data); - DEBUGFS_ADD_FILE(qos, data); -#ifdef CONFIG_IWLWIFI_LEDS - DEBUGFS_ADD_FILE(led, data); -#endif - DEBUGFS_ADD_FILE(sleep_level_override, data); - DEBUGFS_ADD_FILE(current_sleep_command, data); - DEBUGFS_ADD_FILE(thermal_throttling, data); - DEBUGFS_ADD_FILE(disable_ht40, data); - DEBUGFS_ADD_FILE(rx_statistics, debug); - DEBUGFS_ADD_FILE(tx_statistics, debug); - DEBUGFS_ADD_FILE(traffic_log, debug); - DEBUGFS_ADD_FILE(rx_queue, debug); - DEBUGFS_ADD_FILE(tx_queue, debug); - DEBUGFS_ADD_FILE(tx_power, debug); - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { - DEBUGFS_ADD_FILE(ucode_rx_stats, debug); - DEBUGFS_ADD_FILE(ucode_tx_stats, debug); - DEBUGFS_ADD_FILE(ucode_general_stats, debug); - DEBUGFS_ADD_FILE(sensitivity, debug); - DEBUGFS_ADD_FILE(chain_noise, debug); - } - DEBUGFS_ADD_BOOL(disable_sensitivity, rf, &priv->disable_sens_cal); - DEBUGFS_ADD_BOOL(disable_chain_noise, rf, - &priv->disable_chain_noise_cal); - if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || - ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) - DEBUGFS_ADD_BOOL(disable_tx_power, rf, - &priv->disable_tx_power_cal); - return 0; - -err: - IWL_ERR(priv, "Can't open the debugfs directory\n"); - iwl_dbgfs_unregister(priv); - return ret; -} -EXPORT_SYMBOL(iwl_dbgfs_register); - -/** - * Remove the debugfs files and directories - * - */ -void iwl_dbgfs_unregister(struct iwl_priv *priv) -{ - if (!priv->dbgfs) - return; - - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_stations); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_channels); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_status); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_interrupt); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_qos); -#ifdef CONFIG_IWLWIFI_LEDS - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_led); -#endif - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_thermal_throttling); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_disable_ht40); - DEBUGFS_REMOVE(priv->dbgfs->dir_data); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_statistics); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_statistics); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_traffic_log); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_rx_queue); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_queue); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files.file_tx_power); - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) != CSR_HW_REV_TYPE_3945) { - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_rx_stats); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_tx_stats); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_ucode_general_stats); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_sensitivity); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_debug_files. - file_chain_noise); - } - DEBUGFS_REMOVE(priv->dbgfs->dir_debug); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_sensitivity); - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_chain_noise); - if (((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) || - ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_3945)) - DEBUGFS_REMOVE(priv->dbgfs->dbgfs_rf_files.file_disable_tx_power); - DEBUGFS_REMOVE(priv->dbgfs->dir_rf); - DEBUGFS_REMOVE(priv->dbgfs->dir_drv); - kfree(priv->dbgfs); - priv->dbgfs = NULL; -} -EXPORT_SYMBOL(iwl_dbgfs_unregister); - - - diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h deleted file mode 100644 index 3539ea4c9bd4..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ /dev/null @@ -1,1337 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ -/* - * Please use this file (iwl-dev.h) for driver implementation definitions. - * Please use iwl-commands.h for uCode API definitions. - * Please use iwl-4965-hw.h for hardware-related definitions. - */ - -#ifndef __iwl_dev_h__ -#define __iwl_dev_h__ - -#include /* for struct pci_device_id */ -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-csr.h" -#include "iwl-prph.h" -#include "iwl-fh.h" -#include "iwl-debug.h" -#include "iwl-4965-hw.h" -#include "iwl-3945-hw.h" -#include "iwl-3945-led.h" -#include "iwl-led.h" -#include "iwl-power.h" -#include "iwl-agn-rs.h" - -/* configuration for the iwl4965 */ -extern struct iwl_cfg iwl4965_agn_cfg; -extern struct iwl_cfg iwl5300_agn_cfg; -extern struct iwl_cfg iwl5100_agn_cfg; -extern struct iwl_cfg iwl5350_agn_cfg; -extern struct iwl_cfg iwl5100_bgn_cfg; -extern struct iwl_cfg iwl5100_abg_cfg; -extern struct iwl_cfg iwl5150_agn_cfg; -extern struct iwl_cfg iwl5150_abg_cfg; -extern struct iwl_cfg iwl6000h_2agn_cfg; -extern struct iwl_cfg iwl6000i_2agn_cfg; -extern struct iwl_cfg iwl6000_3agn_cfg; -extern struct iwl_cfg iwl6050_2agn_cfg; -extern struct iwl_cfg iwl6050_3agn_cfg; -extern struct iwl_cfg iwl1000_bgn_cfg; - -struct iwl_tx_queue; - -/* shared structures from iwl-5000.c */ -extern struct iwl_mod_params iwl50_mod_params; -extern struct iwl_ops iwl5000_ops; -extern struct iwl_ucode_ops iwl5000_ucode; -extern struct iwl_lib_ops iwl5000_lib; -extern struct iwl_hcmd_ops iwl5000_hcmd; -extern struct iwl_hcmd_utils_ops iwl5000_hcmd_utils; - -/* shared functions from iwl-5000.c */ -extern u16 iwl5000_get_hcmd_size(u8 cmd_id, u16 len); -extern u16 iwl5000_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, - u8 *data); -extern void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info, - __le32 *tx_flags); -extern int iwl5000_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp); -extern int iwl5000_apm_init(struct iwl_priv *priv); -extern void iwl5000_apm_stop(struct iwl_priv *priv); -extern int iwl5000_apm_reset(struct iwl_priv *priv); -extern void iwl5000_nic_config(struct iwl_priv *priv); -extern u16 iwl5000_eeprom_calib_version(struct iwl_priv *priv); -extern const u8 *iwl5000_eeprom_query_addr(const struct iwl_priv *priv, - size_t offset); -extern void iwl5000_txq_update_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq, - u16 byte_cnt); -extern void iwl5000_txq_inval_byte_cnt_tbl(struct iwl_priv *priv, - struct iwl_tx_queue *txq); -extern int iwl5000_load_ucode(struct iwl_priv *priv); -extern void iwl5000_init_alive_start(struct iwl_priv *priv); -extern int iwl5000_alive_notify(struct iwl_priv *priv); -extern int iwl5000_hw_set_hw_params(struct iwl_priv *priv); -extern int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id, - int tx_fifo, int sta_id, int tid, u16 ssn_idx); -extern int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id, - u16 ssn_idx, u8 tx_fifo); -extern void iwl5000_txq_set_sched(struct iwl_priv *priv, u32 mask); -extern void iwl5000_setup_deferred_work(struct iwl_priv *priv); -extern void iwl5000_rx_handler_setup(struct iwl_priv *priv); -extern int iwl5000_hw_valid_rtc_data_addr(u32 addr); -extern int iwl5000_send_tx_power(struct iwl_priv *priv); -extern void iwl5000_temperature(struct iwl_priv *priv); - -/* CT-KILL constants */ -#define CT_KILL_THRESHOLD_LEGACY 110 /* in Celsius */ -#define CT_KILL_THRESHOLD 114 /* in Celsius */ -#define CT_KILL_EXIT_THRESHOLD 95 /* in Celsius */ - -/* Default noise level to report when noise measurement is not available. - * This may be because we're: - * 1) Not associated (4965, no beacon statistics being sent to driver) - * 2) Scanning (noise measurement does not apply to associated channel) - * 3) Receiving CCK (3945 delivers noise info only for OFDM frames) - * Use default noise value of -127 ... this is below the range of measurable - * Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user. - * Also, -127 works better than 0 when averaging frames with/without - * noise info (e.g. averaging might be done in app); measured dBm values are - * always negative ... using a negative value as the default keeps all - * averages within an s8's (used in some apps) range of negative values. */ -#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127) - -/* - * RTS threshold here is total size [2347] minus 4 FCS bytes - * Per spec: - * a value of 0 means RTS on all data/management packets - * a value > max MSDU size means no RTS - * else RTS for data/management frames where MPDU is larger - * than RTS value. - */ -#define DEFAULT_RTS_THRESHOLD 2347U -#define MIN_RTS_THRESHOLD 0U -#define MAX_RTS_THRESHOLD 2347U -#define MAX_MSDU_SIZE 2304U -#define MAX_MPDU_SIZE 2346U -#define DEFAULT_BEACON_INTERVAL 100U -#define DEFAULT_SHORT_RETRY_LIMIT 7U -#define DEFAULT_LONG_RETRY_LIMIT 4U - -struct iwl_rx_mem_buffer { - dma_addr_t real_dma_addr; - dma_addr_t aligned_dma_addr; - struct sk_buff *skb; - struct list_head list; -}; - -/* defined below */ -struct iwl_device_cmd; - -struct iwl_cmd_meta { - /* only for SYNC commands, iff the reply skb is wanted */ - struct iwl_host_cmd *source; - /* - * only for ASYNC commands - * (which is somewhat stupid -- look at iwl-sta.c for instance - * which duplicates a bunch of code because the callback isn't - * invoked for SYNC commands, if it were and its result passed - * through it would be simpler...) - */ - void (*callback)(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb); - - /* The CMD_SIZE_HUGE flag bit indicates that the command - * structure is stored at the end of the shared queue memory. */ - u32 flags; - - DECLARE_PCI_UNMAP_ADDR(mapping) - DECLARE_PCI_UNMAP_LEN(len) -}; - -/* - * Generic queue structure - * - * Contains common data for Rx and Tx queues - */ -struct iwl_queue { - int n_bd; /* number of BDs in this queue */ - int write_ptr; /* 1-st empty entry (index) host_w*/ - int read_ptr; /* last used entry (index) host_r*/ - dma_addr_t dma_addr; /* physical addr for BD's */ - int n_window; /* safe queue window */ - u32 id; - int low_mark; /* low watermark, resume queue if free - * space more than this */ - int high_mark; /* high watermark, stop queue if free - * space less than this */ -} __attribute__ ((packed)); - -/* One for each TFD */ -struct iwl_tx_info { - struct sk_buff *skb[IWL_NUM_OF_TBS - 1]; -}; - -/** - * struct iwl_tx_queue - Tx Queue for DMA - * @q: generic Rx/Tx queue descriptor - * @bd: base of circular buffer of TFDs - * @cmd: array of command/TX buffer pointers - * @meta: array of meta data for each command/tx buffer - * @dma_addr_cmd: physical address of cmd/tx buffer array - * @txb: array of per-TFD driver data - * @need_update: indicates need to update read/write index - * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled - * - * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame - * descriptors) and required locking structures. - */ -#define TFD_TX_CMD_SLOTS 256 -#define TFD_CMD_SLOTS 32 - -struct iwl_tx_queue { - struct iwl_queue q; - void *tfds; - struct iwl_device_cmd **cmd; - struct iwl_cmd_meta *meta; - struct iwl_tx_info *txb; - u8 need_update; - u8 sched_retry; - u8 active; - u8 swq_id; -}; - -#define IWL_NUM_SCAN_RATES (2) - -struct iwl4965_channel_tgd_info { - u8 type; - s8 max_power; -}; - -struct iwl4965_channel_tgh_info { - s64 last_radar_time; -}; - -#define IWL4965_MAX_RATE (33) - -struct iwl3945_clip_group { - /* maximum power level to prevent clipping for each rate, derived by - * us from this band's saturation power in EEPROM */ - const s8 clip_powers[IWL_MAX_RATES]; -}; - -/* current Tx power values to use, one for each rate for each channel. - * requested power is limited by: - * -- regulatory EEPROM limits for this channel - * -- hardware capabilities (clip-powers) - * -- spectrum management - * -- user preference (e.g. iwconfig) - * when requested power is set, base power index must also be set. */ -struct iwl3945_channel_power_info { - struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 base_power_index; /* gain index for power at factory temp. */ - s8 requested_power; /* power (dBm) requested for this chnl/rate */ -}; - -/* current scan Tx power values to use, one for each scan rate for each - * channel. */ -struct iwl3945_scan_power_info { - struct iwl3945_tx_power tpc; /* actual radio and DSP gain settings */ - s8 power_table_index; /* actual (compenst'd) index into gain table */ - s8 requested_power; /* scan pwr (dBm) requested for chnl/rate */ -}; - -/* - * One for each channel, holds all channel setup data - * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant - * with one another! - */ -struct iwl_channel_info { - struct iwl4965_channel_tgd_info tgd; - struct iwl4965_channel_tgh_info tgh; - struct iwl_eeprom_channel eeprom; /* EEPROM regulatory limit */ - struct iwl_eeprom_channel ht40_eeprom; /* EEPROM regulatory limit for - * HT40 channel */ - - u8 channel; /* channel number */ - u8 flags; /* flags copied from EEPROM */ - s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ - s8 curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) limit */ - s8 min_power; /* always 0 */ - s8 scan_power; /* (dBm) regul. eeprom, direct scans, any rate */ - - u8 group_index; /* 0-4, maps channel to group1/2/3/4/5 */ - u8 band_index; /* 0-4, maps channel to band1/2/3/4/5 */ - enum ieee80211_band band; - - /* HT40 channel info */ - s8 ht40_max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */ - s8 ht40_curr_txpow; /* (dBm) regulatory/spectrum/user (not h/w) */ - s8 ht40_min_power; /* always 0 */ - s8 ht40_scan_power; /* (dBm) eeprom, direct scans, any rate */ - u8 ht40_flags; /* flags copied from EEPROM */ - u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */ - - /* Radio/DSP gain settings for each "normal" data Tx rate. - * These include, in addition to RF and DSP gain, a few fields for - * remembering/modifying gain settings (indexes). */ - struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE]; - - /* Radio/DSP gain settings for each scan rate, for directed scans. */ - struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES]; -}; - -#define IWL_TX_FIFO_AC0 0 -#define IWL_TX_FIFO_AC1 1 -#define IWL_TX_FIFO_AC2 2 -#define IWL_TX_FIFO_AC3 3 -#define IWL_TX_FIFO_HCCA_1 5 -#define IWL_TX_FIFO_HCCA_2 6 -#define IWL_TX_FIFO_NONE 7 - -/* Minimum number of queues. MAX_NUM is defined in hw specific files. - * Set the minimum to accommodate the 4 standard TX queues, 1 command - * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ -#define IWL_MIN_NUM_QUEUES 10 - -/* Power management (not Tx power) structures */ - -enum iwl_pwr_src { - IWL_PWR_SRC_VMAIN, - IWL_PWR_SRC_VAUX, -}; - -#define IEEE80211_DATA_LEN 2304 -#define IEEE80211_4ADDR_LEN 30 -#define IEEE80211_HLEN (IEEE80211_4ADDR_LEN) -#define IEEE80211_FRAME_LEN (IEEE80211_DATA_LEN + IEEE80211_HLEN) - -struct iwl_frame { - union { - struct ieee80211_hdr frame; - struct iwl_tx_beacon_cmd beacon; - u8 raw[IEEE80211_FRAME_LEN]; - u8 cmd[360]; - } u; - struct list_head list; -}; - -#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4) -#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ) -#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4) - -enum { - CMD_SYNC = 0, - CMD_SIZE_NORMAL = 0, - CMD_NO_SKB = 0, - CMD_SIZE_HUGE = (1 << 0), - CMD_ASYNC = (1 << 1), - CMD_WANT_SKB = (1 << 2), -}; - -#define IWL_CMD_MAX_PAYLOAD 320 - -/** - * struct iwl_device_cmd - * - * For allocation of the command and tx queues, this establishes the overall - * size of the largest command we send to uCode, except for a scan command - * (which is relatively huge; space is allocated separately). - */ -struct iwl_device_cmd { - struct iwl_cmd_header hdr; /* uCode API */ - union { - u32 flags; - u8 val8; - u16 val16; - u32 val32; - struct iwl_tx_cmd tx; - u8 payload[IWL_CMD_MAX_PAYLOAD]; - } __attribute__ ((packed)) cmd; -} __attribute__ ((packed)); - -#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) - - -struct iwl_host_cmd { - const void *data; - struct sk_buff *reply_skb; - void (*callback)(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb); - u32 flags; - u16 len; - u8 id; -}; - -/* - * RX related structures and functions - */ -#define RX_FREE_BUFFERS 64 -#define RX_LOW_WATERMARK 8 - -#define SUP_RATE_11A_MAX_NUM_CHANNELS 8 -#define SUP_RATE_11B_MAX_NUM_CHANNELS 4 -#define SUP_RATE_11G_MAX_NUM_CHANNELS 12 - -/** - * struct iwl_rx_queue - Rx queue - * @bd: driver's pointer to buffer of receive buffer descriptors (rbd) - * @dma_addr: bus address of buffer of receive buffer descriptors (rbd) - * @read: Shared index to newest available Rx buffer - * @write: Shared index to oldest written Rx packet - * @free_count: Number of pre-allocated buffers in rx_free - * @rx_free: list of free SKBs for use - * @rx_used: List of Rx buffers with no SKB - * @need_update: flag to indicate we need to update read/write index - * @rb_stts: driver's pointer to receive buffer status - * @rb_stts_dma: bus address of receive buffer status - * - * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers - */ -struct iwl_rx_queue { - __le32 *bd; - dma_addr_t dma_addr; - struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS]; - struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE]; - u32 read; - u32 write; - u32 free_count; - u32 write_actual; - struct list_head rx_free; - struct list_head rx_used; - int need_update; - struct iwl_rb_status *rb_stts; - dma_addr_t rb_stts_dma; - spinlock_t lock; -}; - -#define IWL_SUPPORTED_RATES_IE_LEN 8 - -#define MAX_TID_COUNT 9 - -#define IWL_INVALID_RATE 0xFF -#define IWL_INVALID_VALUE -1 - -/** - * struct iwl_ht_agg -- aggregation status while waiting for block-ack - * @txq_id: Tx queue used for Tx attempt - * @frame_count: # frames attempted by Tx command - * @wait_for_ba: Expect block-ack before next Tx reply - * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window - * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window - * @bitmap1: High order, one bit for each frame pending ACK in Tx window - * @rate_n_flags: Rate at which Tx was attempted - * - * If REPLY_TX indicates that aggregation was attempted, driver must wait - * for block ack (REPLY_COMPRESSED_BA). This struct stores tx reply info - * until block ack arrives. - */ -struct iwl_ht_agg { - u16 txq_id; - u16 frame_count; - u16 wait_for_ba; - u16 start_idx; - u64 bitmap; - u32 rate_n_flags; -#define IWL_AGG_OFF 0 -#define IWL_AGG_ON 1 -#define IWL_EMPTYING_HW_QUEUE_ADDBA 2 -#define IWL_EMPTYING_HW_QUEUE_DELBA 3 - u8 state; -}; - - -struct iwl_tid_data { - u16 seq_number; - u16 tfds_in_queue; - struct iwl_ht_agg agg; -}; - -struct iwl_hw_key { - enum ieee80211_key_alg alg; - int keylen; - u8 keyidx; - u8 key[32]; -}; - -union iwl_ht_rate_supp { - u16 rates; - struct { - u8 siso_rate; - u8 mimo_rate; - }; -}; - -#define CFG_HT_RX_AMPDU_FACTOR_DEF (0x3) - -/* - * Maximal MPDU density for TX aggregation - * 4 - 2us density - * 5 - 4us density - * 6 - 8us density - * 7 - 16us density - */ -#define CFG_HT_MPDU_DENSITY_4USEC (0x5) -#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC - -struct iwl_ht_info { - /* self configuration data */ - u8 is_ht; - u8 supported_chan_width; - u8 sm_ps; - struct ieee80211_mcs_info mcs; - /* BSS related data */ - u8 extension_chan_offset; - u8 ht_protection; - u8 non_GF_STA_present; -}; - -union iwl_qos_capabity { - struct { - u8 edca_count:4; /* bit 0-3 */ - u8 q_ack:1; /* bit 4 */ - u8 queue_request:1; /* bit 5 */ - u8 txop_request:1; /* bit 6 */ - u8 reserved:1; /* bit 7 */ - } q_AP; - struct { - u8 acvo_APSD:1; /* bit 0 */ - u8 acvi_APSD:1; /* bit 1 */ - u8 ac_bk_APSD:1; /* bit 2 */ - u8 ac_be_APSD:1; /* bit 3 */ - u8 q_ack:1; /* bit 4 */ - u8 max_len:2; /* bit 5-6 */ - u8 more_data_ack:1; /* bit 7 */ - } q_STA; - u8 val; -}; - -/* QoS structures */ -struct iwl_qos_info { - int qos_active; - union iwl_qos_capabity qos_cap; - struct iwl_qosparam_cmd def_qos_parm; -}; - -#define STA_PS_STATUS_WAKE 0 -#define STA_PS_STATUS_SLEEP 1 - - -struct iwl3945_station_entry { - struct iwl3945_addsta_cmd sta; - struct iwl_tid_data tid[MAX_TID_COUNT]; - u8 used; - u8 ps_status; - struct iwl_hw_key keyinfo; -}; - -struct iwl_station_entry { - struct iwl_addsta_cmd sta; - struct iwl_tid_data tid[MAX_TID_COUNT]; - u8 used; - u8 ps_status; - struct iwl_hw_key keyinfo; -}; - -/* one for each uCode image (inst/data, boot/init/runtime) */ -struct fw_desc { - void *v_addr; /* access by driver */ - dma_addr_t p_addr; /* access by card's busmaster DMA */ - u32 len; /* bytes */ -}; - -/* uCode file layout */ -struct iwl_ucode_header { - __le32 ver; /* major/minor/API/serial */ - union { - struct { - __le32 inst_size; /* bytes of runtime code */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of init code */ - __le32 init_data_size; /* bytes of init data */ - __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ - } v1; - struct { - __le32 build; /* build number */ - __le32 inst_size; /* bytes of runtime code */ - __le32 data_size; /* bytes of runtime data */ - __le32 init_size; /* bytes of init code */ - __le32 init_data_size; /* bytes of init data */ - __le32 boot_size; /* bytes of bootstrap code */ - u8 data[0]; /* in same order as sizes */ - } v2; - } u; -}; -#define UCODE_HEADER_SIZE(ver) ((ver) == 1 ? 24 : 28) - -struct iwl4965_ibss_seq { - u8 mac[ETH_ALEN]; - u16 seq_num; - u16 frag_num; - unsigned long packet_time; - struct list_head list; -}; - -struct iwl_sensitivity_ranges { - u16 min_nrg_cck; - u16 max_nrg_cck; - - u16 nrg_th_cck; - u16 nrg_th_ofdm; - - u16 auto_corr_min_ofdm; - u16 auto_corr_min_ofdm_mrc; - u16 auto_corr_min_ofdm_x1; - u16 auto_corr_min_ofdm_mrc_x1; - - u16 auto_corr_max_ofdm; - u16 auto_corr_max_ofdm_mrc; - u16 auto_corr_max_ofdm_x1; - u16 auto_corr_max_ofdm_mrc_x1; - - u16 auto_corr_max_cck; - u16 auto_corr_max_cck_mrc; - u16 auto_corr_min_cck; - u16 auto_corr_min_cck_mrc; -}; - - -#define KELVIN_TO_CELSIUS(x) ((x)-273) -#define CELSIUS_TO_KELVIN(x) ((x)+273) - - -/** - * struct iwl_hw_params - * @max_txq_num: Max # Tx queues supported - * @dma_chnl_num: Number of Tx DMA/FIFO channels - * @scd_bc_tbls_size: size of scheduler byte count tables - * @tfd_size: TFD size - * @tx/rx_chains_num: Number of TX/RX chains - * @valid_tx/rx_ant: usable antennas - * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2) - * @max_rxq_log: Log-base-2 of max_rxq_size - * @rx_buf_size: Rx buffer size - * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR - * @max_stations: - * @bcast_sta_id: - * @ht40_channel: is 40MHz width possible in band 2.4 - * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ) - * @sw_crypto: 0 for hw, 1 for sw - * @max_xxx_size: for ucode uses - * @ct_kill_threshold: temperature threshold - * @calib_init_cfg: setup initial calibrations for the hw - * @struct iwl_sensitivity_ranges: range of sensitivity values - */ -struct iwl_hw_params { - u8 max_txq_num; - u8 dma_chnl_num; - u16 scd_bc_tbls_size; - u32 tfd_size; - u8 tx_chains_num; - u8 rx_chains_num; - u8 valid_tx_ant; - u8 valid_rx_ant; - u16 max_rxq_size; - u16 max_rxq_log; - u32 rx_buf_size; - u32 rx_wrt_ptr_reg; - u32 max_pkt_size; - u8 max_stations; - u8 bcast_sta_id; - u8 ht40_channel; - u8 max_beacon_itrvl; /* in 1024 ms */ - u32 max_inst_size; - u32 max_data_size; - u32 max_bsm_size; - u32 ct_kill_threshold; /* value in hw-dependent units */ - u32 ct_kill_exit_threshold; /* value in hw-dependent units */ - /* for 1000, 6000 series and up */ - u32 calib_init_cfg; - const struct iwl_sensitivity_ranges *sens; -}; - - -/****************************************************************************** - * - * Functions implemented in core module which are forward declared here - * for use by iwl-[4-5].c - * - * NOTE: The implementation of these functions are not hardware specific - * which is why they are in the core module files. - * - * Naming convention -- - * iwl_ <-- Is part of iwlwifi - * iwlXXXX_ <-- Hardware specific (implemented in iwl-XXXX.c for XXXX) - * iwl4965_bg_ <-- Called from work queue context - * iwl4965_mac_ <-- mac80211 callback - * - ****************************************************************************/ -extern void iwl_update_chain_flags(struct iwl_priv *priv); -extern int iwl_set_pwr_src(struct iwl_priv *priv, enum iwl_pwr_src src); -extern const u8 iwl_bcast_addr[ETH_ALEN]; -extern int iwl_rxq_stop(struct iwl_priv *priv); -extern void iwl_txq_ctx_stop(struct iwl_priv *priv); -extern int iwl_queue_space(const struct iwl_queue *q); -static inline int iwl_queue_used(const struct iwl_queue *q, int i) -{ - return q->write_ptr >= q->read_ptr ? - (i >= q->read_ptr && i < q->write_ptr) : - !(i < q->read_ptr && i >= q->write_ptr); -} - - -static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) -{ - /* This is for scan command, the big buffer at end of command array */ - if (is_huge) - return q->n_window; /* must be power of 2 */ - - /* Otherwise, use normal size buffers */ - return index & (q->n_window - 1); -} - - -struct iwl_dma_ptr { - dma_addr_t dma; - void *addr; - size_t size; -}; - -#define IWL_CHANNEL_WIDTH_20MHZ 0 -#define IWL_CHANNEL_WIDTH_40MHZ 1 - -#define IWL_OPERATION_MODE_AUTO 0 -#define IWL_OPERATION_MODE_HT_ONLY 1 -#define IWL_OPERATION_MODE_MIXED 2 -#define IWL_OPERATION_MODE_20MHZ 3 - -#define IWL_TX_CRC_SIZE 4 -#define IWL_TX_DELIMITER_SIZE 4 - -#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 - -/* Sensitivity and chain noise calibration */ -#define INITIALIZATION_VALUE 0xFFFF -#define CAL_NUM_OF_BEACONS 20 -#define MAXIMUM_ALLOWED_PATHLOSS 15 - -#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3 - -#define MAX_FA_OFDM 50 -#define MIN_FA_OFDM 5 -#define MAX_FA_CCK 50 -#define MIN_FA_CCK 5 - -#define AUTO_CORR_STEP_OFDM 1 - -#define AUTO_CORR_STEP_CCK 3 -#define AUTO_CORR_MAX_TH_CCK 160 - -#define NRG_DIFF 2 -#define NRG_STEP_CCK 2 -#define NRG_MARGIN 8 -#define MAX_NUMBER_CCK_NO_FA 100 - -#define AUTO_CORR_CCK_MIN_VAL_DEF (125) - -#define CHAIN_A 0 -#define CHAIN_B 1 -#define CHAIN_C 2 -#define CHAIN_NOISE_DELTA_GAIN_INIT_VAL 4 -#define ALL_BAND_FILTER 0xFF00 -#define IN_BAND_FILTER 0xFF -#define MIN_AVERAGE_NOISE_MAX_VALUE 0xFFFFFFFF - -#define NRG_NUM_PREV_STAT_L 20 -#define NUM_RX_CHAINS 3 - -enum iwl4965_false_alarm_state { - IWL_FA_TOO_MANY = 0, - IWL_FA_TOO_FEW = 1, - IWL_FA_GOOD_RANGE = 2, -}; - -enum iwl4965_chain_noise_state { - IWL_CHAIN_NOISE_ALIVE = 0, /* must be 0 */ - IWL_CHAIN_NOISE_ACCUMULATE, - IWL_CHAIN_NOISE_CALIBRATED, - IWL_CHAIN_NOISE_DONE, -}; - -enum iwl4965_calib_enabled_state { - IWL_CALIB_DISABLED = 0, /* must be 0 */ - IWL_CALIB_ENABLED = 1, -}; - - -/* - * enum iwl_calib - * defines the order in which results of initial calibrations - * should be sent to the runtime uCode - */ -enum iwl_calib { - IWL_CALIB_XTAL, - IWL_CALIB_DC, - IWL_CALIB_LO, - IWL_CALIB_TX_IQ, - IWL_CALIB_TX_IQ_PERD, - IWL_CALIB_BASE_BAND, - IWL_CALIB_MAX -}; - -/* Opaque calibration results */ -struct iwl_calib_result { - void *buf; - size_t buf_len; -}; - -enum ucode_type { - UCODE_NONE = 0, - UCODE_INIT, - UCODE_RT -}; - -/* Sensitivity calib data */ -struct iwl_sensitivity_data { - u32 auto_corr_ofdm; - u32 auto_corr_ofdm_mrc; - u32 auto_corr_ofdm_x1; - u32 auto_corr_ofdm_mrc_x1; - u32 auto_corr_cck; - u32 auto_corr_cck_mrc; - - u32 last_bad_plcp_cnt_ofdm; - u32 last_fa_cnt_ofdm; - u32 last_bad_plcp_cnt_cck; - u32 last_fa_cnt_cck; - - u32 nrg_curr_state; - u32 nrg_prev_state; - u32 nrg_value[10]; - u8 nrg_silence_rssi[NRG_NUM_PREV_STAT_L]; - u32 nrg_silence_ref; - u32 nrg_energy_idx; - u32 nrg_silence_idx; - u32 nrg_th_cck; - s32 nrg_auto_corr_silence_diff; - u32 num_in_cck_no_fa; - u32 nrg_th_ofdm; -}; - -/* Chain noise (differential Rx gain) calib data */ -struct iwl_chain_noise_data { - u32 active_chains; - u32 chain_noise_a; - u32 chain_noise_b; - u32 chain_noise_c; - u32 chain_signal_a; - u32 chain_signal_b; - u32 chain_signal_c; - u16 beacon_count; - u8 disconn_array[NUM_RX_CHAINS]; - u8 delta_gain_code[NUM_RX_CHAINS]; - u8 radio_write; - u8 state; -}; - -#define EEPROM_SEM_TIMEOUT 10 /* milliseconds */ -#define EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ - -#define IWL_TRAFFIC_ENTRIES (256) -#define IWL_TRAFFIC_ENTRY_SIZE (64) - -enum { - MEASUREMENT_READY = (1 << 0), - MEASUREMENT_ACTIVE = (1 << 1), -}; - -enum iwl_nvm_type { - NVM_DEVICE_TYPE_EEPROM = 0, - NVM_DEVICE_TYPE_OTP, -}; - -/* - * Two types of OTP memory access modes - * IWL_OTP_ACCESS_ABSOLUTE - absolute address mode, - * based on physical memory addressing - * IWL_OTP_ACCESS_RELATIVE - relative address mode, - * based on logical memory addressing - */ -enum iwl_access_mode { - IWL_OTP_ACCESS_ABSOLUTE, - IWL_OTP_ACCESS_RELATIVE, -}; - -/** - * enum iwl_pa_type - Power Amplifier type - * @IWL_PA_SYSTEM: based on uCode configuration - * @IWL_PA_HYBRID: use both Internal and external PA - * @IWL_PA_INTERNAL: use Internal only - */ -enum iwl_pa_type { - IWL_PA_SYSTEM = 0, - IWL_PA_HYBRID = 1, - IWL_PA_INTERNAL = 2, -}; - -/* interrupt statistics */ -struct isr_statistics { - u32 hw; - u32 sw; - u32 sw_err; - u32 sch; - u32 alive; - u32 rfkill; - u32 ctkill; - u32 wakeup; - u32 rx; - u32 rx_handlers[REPLY_MAX]; - u32 tx; - u32 unhandled; -}; - -#ifdef CONFIG_IWLWIFI_DEBUGFS -/* management statistics */ -enum iwl_mgmt_stats { - MANAGEMENT_ASSOC_REQ = 0, - MANAGEMENT_ASSOC_RESP, - MANAGEMENT_REASSOC_REQ, - MANAGEMENT_REASSOC_RESP, - MANAGEMENT_PROBE_REQ, - MANAGEMENT_PROBE_RESP, - MANAGEMENT_BEACON, - MANAGEMENT_ATIM, - MANAGEMENT_DISASSOC, - MANAGEMENT_AUTH, - MANAGEMENT_DEAUTH, - MANAGEMENT_ACTION, - MANAGEMENT_MAX, -}; -/* control statistics */ -enum iwl_ctrl_stats { - CONTROL_BACK_REQ = 0, - CONTROL_BACK, - CONTROL_PSPOLL, - CONTROL_RTS, - CONTROL_CTS, - CONTROL_ACK, - CONTROL_CFEND, - CONTROL_CFENDACK, - CONTROL_MAX, -}; - -struct traffic_stats { - u32 mgmt[MANAGEMENT_MAX]; - u32 ctrl[CONTROL_MAX]; - u32 data_cnt; - u64 data_bytes; -}; -#else -struct traffic_stats { - u64 data_bytes; -}; -#endif - -#define IWL_MAX_NUM_QUEUES 20 /* FIXME: do dynamic allocation */ - -struct iwl_priv { - - /* ieee device used by generic ieee processing code */ - struct ieee80211_hw *hw; - struct ieee80211_channel *ieee_channels; - struct ieee80211_rate *ieee_rates; - struct iwl_cfg *cfg; - - /* temporary frame storage list */ - struct list_head free_frames; - int frames_count; - - enum ieee80211_band band; - int alloc_rxb_skb; - - void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb); - - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - -#if defined(CONFIG_IWLWIFI_SPECTRUM_MEASUREMENT) || defined(CONFIG_IWL3945_SPECTRUM_MEASUREMENT) - /* spectrum measurement report caching */ - struct iwl_spectrum_notification measure_report; - u8 measurement_status; -#endif - /* ucode beacon time */ - u32 ucode_beacon_time; - - /* we allocate array of iwl4965_channel_info for NIC's valid channels. - * Access via channel # using indirect index array */ - struct iwl_channel_info *channel_info; /* channel info array */ - u8 channel_count; /* # of channels */ - - /* each calibration channel group in the EEPROM has a derived - * clip setting for each rate. 3945 only.*/ - const struct iwl3945_clip_group clip39_groups[5]; - - /* thermal calibration */ - s32 temperature; /* degrees Kelvin */ - s32 last_temperature; - - /* init calibration results */ - struct iwl_calib_result calib_results[IWL_CALIB_MAX]; - - /* Scan related variables */ - unsigned long last_scan_jiffies; - unsigned long next_scan_jiffies; - unsigned long scan_start; - unsigned long scan_pass_start; - unsigned long scan_start_tsf; - void *scan; - int scan_bands; - struct cfg80211_scan_request *scan_request; - u8 scan_tx_ant[IEEE80211_NUM_BANDS]; - u8 mgmt_tx_ant; - - /* spinlock */ - spinlock_t lock; /* protect general shared data */ - spinlock_t hcmd_lock; /* protect hcmd */ - spinlock_t reg_lock; /* protect hw register access */ - struct mutex mutex; - - /* basic pci-network driver stuff */ - struct pci_dev *pci_dev; - - /* pci hardware address support */ - void __iomem *hw_base; - u32 hw_rev; - u32 hw_wa_rev; - u8 rev_id; - - /* uCode images, save to reload in case of failure */ - u32 ucode_ver; /* version of ucode, copy of - iwl_ucode.ver */ - struct fw_desc ucode_code; /* runtime inst */ - struct fw_desc ucode_data; /* runtime data original */ - struct fw_desc ucode_data_backup; /* runtime data save/restore */ - struct fw_desc ucode_init; /* initialization inst */ - struct fw_desc ucode_init_data; /* initialization data */ - struct fw_desc ucode_boot; /* bootstrap inst */ - enum ucode_type ucode_type; - u8 ucode_write_complete; /* the image write is complete */ - - - struct iwl_rxon_time_cmd rxon_timing; - - /* We declare this const so it can only be - * changed via explicit cast within the - * routines that actually update the physical - * hardware */ - const struct iwl_rxon_cmd active_rxon; - struct iwl_rxon_cmd staging_rxon; - - struct iwl_rxon_cmd recovery_rxon; - - /* 1st responses from initialize and runtime uCode images. - * 4965's initialize alive response contains some calibration data. */ - struct iwl_init_alive_resp card_alive_init; - struct iwl_alive_resp card_alive; - -#ifdef CONFIG_IWLWIFI_LEDS - unsigned long last_blink_time; - u8 last_blink_rate; - u8 allow_blinking; - u64 led_tpt; - struct iwl_led led[IWL_LED_TRG_MAX]; - unsigned int rxtxpackets; -#endif - u16 active_rate; - u16 active_rate_basic; - - u8 assoc_station_added; - u8 start_calib; - struct iwl_sensitivity_data sensitivity_data; - struct iwl_chain_noise_data chain_noise_data; - __le16 sensitivity_tbl[HD_TABLE_SIZE]; - - struct iwl_ht_info current_ht_config; - u8 last_phy_res[100]; - - /* Rate scaling data */ - s8 data_retry_limit; - u8 retry_rate; - - wait_queue_head_t wait_command_queue; - - int activity_timer_active; - - /* Rx and Tx DMA processing queues */ - struct iwl_rx_queue rxq; - struct iwl_tx_queue txq[IWL_MAX_NUM_QUEUES]; - unsigned long txq_ctx_active_msk; - struct iwl_dma_ptr kw; /* keep warm address */ - struct iwl_dma_ptr scd_bc_tbls; - - u32 scd_base_addr; /* scheduler sram base address */ - - unsigned long status; - - int last_rx_rssi; /* From Rx packet statistics */ - int last_rx_noise; /* From beacon statistics */ - - /* counts mgmt, ctl, and data packets */ - struct traffic_stats tx_stats; - struct traffic_stats rx_stats; - - /* counts interrupts */ - struct isr_statistics isr_stats; - - struct iwl_power_mgr power_data; - struct iwl_tt_mgmt thermal_throttle; - - struct iwl_notif_statistics statistics; - unsigned long last_statistics_time; - - /* context information */ - u16 rates_mask; - - u8 bssid[ETH_ALEN]; - u16 rts_threshold; - u8 mac_addr[ETH_ALEN]; - - /*station table variables */ - spinlock_t sta_lock; - int num_stations; - struct iwl_station_entry stations[IWL_STATION_COUNT]; - struct iwl_wep_key wep_keys[WEP_KEYS_MAX]; - u8 default_wep_key; - u8 key_mapping_key; - unsigned long ucode_key_table; - - /* queue refcounts */ -#define IWL_MAX_HW_QUEUES 32 - unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)]; - /* for each AC */ - atomic_t queue_stop_count[4]; - - /* Indication if ieee80211_ops->open has been called */ - u8 is_open; - - u8 mac80211_registered; - - /* Rx'd packet timing information */ - u32 last_beacon_time; - u64 last_tsf; - - /* eeprom -- this is in the card's little endian byte order */ - u8 *eeprom; - int nvm_device_type; - struct iwl_eeprom_calib_info *calib_info; - - enum nl80211_iftype iw_mode; - - struct sk_buff *ibss_beacon; - - /* Last Rx'd beacon timestamp */ - u64 timestamp; - u16 beacon_int; - struct ieee80211_vif *vif; - - /*Added for 3945 */ - void *shared_virt; - dma_addr_t shared_phys; - /*End*/ - struct iwl_hw_params hw_params; - - /* INT ICT Table */ - __le32 *ict_tbl; - dma_addr_t ict_tbl_dma; - dma_addr_t aligned_ict_tbl_dma; - int ict_index; - void *ict_tbl_vir; - u32 inta; - bool use_ict; - - u32 inta_mask; - /* Current association information needed to configure the - * hardware */ - u16 assoc_id; - u16 assoc_capability; - - struct iwl_qos_info qos_data; - - struct workqueue_struct *workqueue; - - struct work_struct up; - struct work_struct restart; - struct work_struct calibrated_work; - struct work_struct scan_completed; - struct work_struct rx_replenish; - struct work_struct abort_scan; - struct work_struct update_link_led; - struct work_struct auth_work; - struct work_struct report_work; - struct work_struct request_scan; - struct work_struct beacon_update; - struct work_struct tt_work; - struct work_struct ct_enter; - struct work_struct ct_exit; - - struct tasklet_struct irq_tasklet; - - struct delayed_work init_alive_start; - struct delayed_work alive_start; - struct delayed_work scan_check; - - /*For 3945 only*/ - struct delayed_work thermal_periodic; - struct delayed_work rfkill_poll; - - /* TX Power */ - s8 tx_power_user_lmt; - s8 tx_power_device_lmt; - - -#ifdef CONFIG_IWLWIFI_DEBUG - /* debugging info */ - u32 debug_level; /* per device debugging will override global - iwl_debug_level if set */ - u32 framecnt_to_us; - atomic_t restrict_refcnt; - bool disable_ht40; -#ifdef CONFIG_IWLWIFI_DEBUGFS - /* debugfs */ - u16 tx_traffic_idx; - u16 rx_traffic_idx; - u8 *tx_traffic; - u8 *rx_traffic; - struct iwl_debugfs *dbgfs; -#endif /* CONFIG_IWLWIFI_DEBUGFS */ -#endif /* CONFIG_IWLWIFI_DEBUG */ - - struct work_struct txpower_work; - u32 disable_sens_cal; - u32 disable_chain_noise_cal; - u32 disable_tx_power_cal; - struct work_struct run_time_calib_work; - struct timer_list statistics_periodic; - bool hw_ready; - /*For 3945*/ -#define IWL_DEFAULT_TX_POWER 0x0F - - struct iwl3945_notif_statistics statistics_39; - - u32 sta_supp_rates; -}; /*iwl_priv */ - -static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id) -{ - set_bit(txq_id, &priv->txq_ctx_active_msk); -} - -static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id) -{ - clear_bit(txq_id, &priv->txq_ctx_active_msk); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -const char *iwl_get_tx_fail_reason(u32 status); -/* - * iwl_get_debug_level: Return active debug level for device - * - * Using sysfs it is possible to set per device debug level. This debug - * level will be used if set, otherwise the global debug level which can be - * set via module parameter is used. - */ -static inline u32 iwl_get_debug_level(struct iwl_priv *priv) -{ - if (priv->debug_level) - return priv->debug_level; - else - return iwl_debug_level; -} -#else -static inline const char *iwl_get_tx_fail_reason(u32 status) { return ""; } - -static inline u32 iwl_get_debug_level(struct iwl_priv *priv) -{ - return iwl_debug_level; -} -#endif - - -static inline struct ieee80211_hdr *iwl_tx_queue_get_hdr(struct iwl_priv *priv, - int txq_id, int idx) -{ - if (priv->txq[txq_id].txb[idx].skb[0]) - return (struct ieee80211_hdr *)priv->txq[txq_id]. - txb[idx].skb[0]->data; - return NULL; -} - - -static inline int iwl_is_associated(struct iwl_priv *priv) -{ - return (priv->active_rxon.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0; -} - -static inline int is_channel_valid(const struct iwl_channel_info *ch_info) -{ - if (ch_info == NULL) - return 0; - return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0; -} - -static inline int is_channel_radar(const struct iwl_channel_info *ch_info) -{ - return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0; -} - -static inline u8 is_channel_a_band(const struct iwl_channel_info *ch_info) -{ - return ch_info->band == IEEE80211_BAND_5GHZ; -} - -static inline u8 is_channel_bg_band(const struct iwl_channel_info *ch_info) -{ - return ch_info->band == IEEE80211_BAND_2GHZ; -} - -static inline int is_channel_passive(const struct iwl_channel_info *ch) -{ - return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0; -} - -static inline int is_channel_ibss(const struct iwl_channel_info *ch) -{ - return ((ch->flags & EEPROM_CHANNEL_IBSS)) ? 1 : 0; -} - -#endif /* __iwl_dev_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.c b/drivers/net/wireless/iwlwifi/iwl-eeprom.c deleted file mode 100644 index 18dc3a4b7948..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.c +++ /dev/null @@ -1,1089 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - - -#include -#include -#include - -#include - -#include "iwl-commands.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-debug.h" -#include "iwl-eeprom.h" -#include "iwl-io.h" - -/************************** EEPROM BANDS **************************** - * - * The iwl_eeprom_band definitions below provide the mapping from the - * EEPROM contents to the specific channel number supported for each - * band. - * - * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3 - * definition below maps to physical channel 42 in the 5.2GHz spectrum. - * The specific geography and calibration information for that channel - * is contained in the eeprom map itself. - * - * During init, we copy the eeprom information and channel map - * information into priv->channel_info_24/52 and priv->channel_map_24/52 - * - * channel_map_24/52 provides the index in the channel_info array for a - * given channel. We have to have two separate maps as there is channel - * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and - * band_2 - * - * A value of 0xff stored in the channel_map indicates that the channel - * is not supported by the hardware at all. - * - * A value of 0xfe in the channel_map indicates that the channel is not - * valid for Tx with the current hardware. This means that - * while the system can tune and receive on a given channel, it may not - * be able to associate or transmit any frames on that - * channel. There is no corresponding channel information for that - * entry. - * - *********************************************************************/ - -/* 2.4 GHz */ -const u8 iwl_eeprom_band_1[14] = { - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 -}; - -/* 5.2 GHz bands */ -static const u8 iwl_eeprom_band_2[] = { /* 4915-5080MHz */ - 183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16 -}; - -static const u8 iwl_eeprom_band_3[] = { /* 5170-5320MHz */ - 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 -}; - -static const u8 iwl_eeprom_band_4[] = { /* 5500-5700MHz */ - 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 -}; - -static const u8 iwl_eeprom_band_5[] = { /* 5725-5825MHz */ - 145, 149, 153, 157, 161, 165 -}; - -static const u8 iwl_eeprom_band_6[] = { /* 2.4 ht40 channel */ - 1, 2, 3, 4, 5, 6, 7 -}; - -static const u8 iwl_eeprom_band_7[] = { /* 5.2 ht40 channel */ - 36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157 -}; - -/** - * struct iwl_txpwr_section: eeprom section information - * @offset: indirect address into eeprom image - * @count: number of "struct iwl_eeprom_enhanced_txpwr" in this section - * @band: band type for the section - * @is_common - true: common section, false: channel section - * @is_cck - true: cck section, false: not cck section - * @is_ht_40 - true: all channel in the section are HT40 channel, - * false: legacy or HT 20 MHz - * ignore if it is common section - * @iwl_eeprom_section_channel: channel array in the section, - * ignore if common section - */ -struct iwl_txpwr_section { - u32 offset; - u8 count; - enum ieee80211_band band; - bool is_common; - bool is_cck; - bool is_ht40; - u8 iwl_eeprom_section_channel[EEPROM_MAX_TXPOWER_SECTION_ELEMENTS]; -}; - -/** - * section 1 - 3 are regulatory tx power apply to all channels based on - * modulation: CCK, OFDM - * Band: 2.4GHz, 5.2GHz - * section 4 - 10 are regulatory tx power apply to specified channels - * For example: - * 1L - Channel 1 Legacy - * 1HT - Channel 1 HT - * (1,+1) - Channel 1 HT40 "_above_" - * - * Section 1: all CCK channels - * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40) channels - * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels - * Section 4: 2.4 GHz 20MHz channels: 1L, 1HT, 2L, 2HT, 10L, 10HT, 11L, 11HT - * Section 5: 2.4 GHz 40MHz channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) - * Section 6: 5.2 GHz 20MHz channels: 36L, 64L, 100L, 36HT, 64HT, 100HT - * Section 7: 5.2 GHz 40MHz channels: (36,+1) (60,+1) (100,+1) - * Section 8: 2.4 GHz channel: 13L, 13HT - * Section 9: 2.4 GHz channel: 140L, 140HT - * Section 10: 2.4 GHz 40MHz channels: (132,+1) (44,+1) - * - */ -static const struct iwl_txpwr_section enhinfo[] = { - { EEPROM_LB_CCK_20_COMMON, 1, IEEE80211_BAND_2GHZ, true, true, false }, - { EEPROM_LB_OFDM_COMMON, 3, IEEE80211_BAND_2GHZ, true, false, false }, - { EEPROM_HB_OFDM_COMMON, 3, IEEE80211_BAND_5GHZ, true, false, false }, - { EEPROM_LB_OFDM_20_BAND, 8, IEEE80211_BAND_2GHZ, - false, false, false, - {1, 1, 2, 2, 10, 10, 11, 11 } }, - { EEPROM_LB_OFDM_HT40_BAND, 5, IEEE80211_BAND_2GHZ, - false, false, true, - { 1, 2, 6, 7, 9 } }, - { EEPROM_HB_OFDM_20_BAND, 6, IEEE80211_BAND_5GHZ, - false, false, false, - { 36, 64, 100, 36, 64, 100 } }, - { EEPROM_HB_OFDM_HT40_BAND, 3, IEEE80211_BAND_5GHZ, - false, false, true, - { 36, 60, 100 } }, - { EEPROM_LB_OFDM_20_CHANNEL_13, 2, IEEE80211_BAND_2GHZ, - false, false, false, - { 13, 13 } }, - { EEPROM_HB_OFDM_20_CHANNEL_140, 2, IEEE80211_BAND_5GHZ, - false, false, false, - { 140, 140 } }, - { EEPROM_HB_OFDM_HT40_BAND_1, 2, IEEE80211_BAND_5GHZ, - false, false, true, - { 132, 44 } }, -}; - -/****************************************************************************** - * - * EEPROM related functions - * -******************************************************************************/ - -int iwlcore_eeprom_verify_signature(struct iwl_priv *priv) -{ - u32 gp = iwl_read32(priv, CSR_EEPROM_GP); - if ((gp & CSR_EEPROM_GP_VALID_MSK) == CSR_EEPROM_GP_BAD_SIGNATURE) { - IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); - return -ENOENT; - } - return 0; -} -EXPORT_SYMBOL(iwlcore_eeprom_verify_signature); - -static void iwl_set_otp_access(struct iwl_priv *priv, enum iwl_access_mode mode) -{ - u32 otpgp; - - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); - if (mode == IWL_OTP_ACCESS_ABSOLUTE) - iwl_clear_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); - else - iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_OTP_ACCESS_MODE); -} - -static int iwlcore_get_nvm_type(struct iwl_priv *priv) -{ - u32 otpgp; - int nvm_type; - - /* OTP only valid for CP/PP and after */ - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_NONE: - IWL_ERR(priv, "Unknown hardware type\n"); - return -ENOENT; - case CSR_HW_REV_TYPE_3945: - case CSR_HW_REV_TYPE_4965: - case CSR_HW_REV_TYPE_5300: - case CSR_HW_REV_TYPE_5350: - case CSR_HW_REV_TYPE_5100: - case CSR_HW_REV_TYPE_5150: - nvm_type = NVM_DEVICE_TYPE_EEPROM; - break; - default: - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); - if (otpgp & CSR_OTP_GP_REG_DEVICE_SELECT) - nvm_type = NVM_DEVICE_TYPE_OTP; - else - nvm_type = NVM_DEVICE_TYPE_EEPROM; - break; - } - return nvm_type; -} - -/* - * The device's EEPROM semaphore prevents conflicts between driver and uCode - * when accessing the EEPROM; each access is a series of pulses to/from the - * EEPROM chip, not a single event, so even reads could conflict if they - * weren't arbitrated by the semaphore. - */ -int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv) -{ - u16 count; - int ret; - - for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) { - /* Request semaphore */ - iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - - /* See if we got it */ - ret = iwl_poll_direct_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM, - EEPROM_SEM_TIMEOUT); - if (ret >= 0) { - IWL_DEBUG_IO(priv, "Acquired semaphore after %d tries.\n", - count+1); - return ret; - } - } - - return ret; -} -EXPORT_SYMBOL(iwlcore_eeprom_acquire_semaphore); - -void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv) -{ - iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG, - CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM); - -} -EXPORT_SYMBOL(iwlcore_eeprom_release_semaphore); - -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ - BUG_ON(offset >= priv->cfg->eeprom_size); - return &priv->eeprom[offset]; -} -EXPORT_SYMBOL(iwlcore_eeprom_query_addr); - -static int iwl_init_otp_access(struct iwl_priv *priv) -{ - int ret; - - /* Enable 40MHz radio clock */ - _iwl_write32(priv, CSR_GP_CNTRL, - _iwl_read32(priv, CSR_GP_CNTRL) | - CSR_GP_CNTRL_REG_FLAG_INIT_DONE); - - /* wait for clock to be ready */ - ret = iwl_poll_direct_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, - 25000); - if (ret < 0) - IWL_ERR(priv, "Time out access OTP\n"); - else { - iwl_set_bits_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); - udelay(5); - iwl_clear_bits_prph(priv, APMG_PS_CTRL_REG, - APMG_PS_CTRL_VAL_RESET_REQ); - } - return ret; -} - -static int iwl_read_otp_word(struct iwl_priv *priv, u16 addr, __le16 *eeprom_data) -{ - int ret = 0; - u32 r; - u32 otpgp; - - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { - IWL_ERR(priv, "Time out reading OTP[%d]\n", addr); - return ret; - } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - /* check for ECC errors: */ - otpgp = iwl_read32(priv, CSR_OTP_GP_REG); - if (otpgp & CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK) { - /* stop in this case */ - /* set the uncorrectable OTP ECC bit for acknowledgement */ - iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); - IWL_ERR(priv, "Uncorrectable OTP ECC error, abort OTP read\n"); - return -EINVAL; - } - if (otpgp & CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK) { - /* continue in this case */ - /* set the correctable OTP ECC bit for acknowledgement */ - iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK); - IWL_ERR(priv, "Correctable OTP ECC error, continue read\n"); - } - *eeprom_data = cpu_to_le16(r >> 16); - return 0; -} - -/* - * iwl_is_otp_empty: check for empty OTP - */ -static bool iwl_is_otp_empty(struct iwl_priv *priv) -{ - u16 next_link_addr = 0; - __le16 link_value; - bool is_empty = false; - - /* locate the beginning of OTP link list */ - if (!iwl_read_otp_word(priv, next_link_addr, &link_value)) { - if (!link_value) { - IWL_ERR(priv, "OTP is empty\n"); - is_empty = true; - } - } else { - IWL_ERR(priv, "Unable to read first block of OTP list.\n"); - is_empty = true; - } - - return is_empty; -} - - -/* - * iwl_find_otp_image: find EEPROM image in OTP - * finding the OTP block that contains the EEPROM image. - * the last valid block on the link list (the block _before_ the last block) - * is the block we should read and used to configure the device. - * If all the available OTP blocks are full, the last block will be the block - * we should read and used to configure the device. - * only perform this operation if shadow RAM is disabled - */ -static int iwl_find_otp_image(struct iwl_priv *priv, - u16 *validblockaddr) -{ - u16 next_link_addr = 0, valid_addr; - __le16 link_value = 0; - int usedblocks = 0; - - /* set addressing mode to absolute to traverse the link list */ - iwl_set_otp_access(priv, IWL_OTP_ACCESS_ABSOLUTE); - - /* checking for empty OTP or error */ - if (iwl_is_otp_empty(priv)) - return -EINVAL; - - /* - * start traverse link list - * until reach the max number of OTP blocks - * different devices have different number of OTP blocks - */ - do { - /* save current valid block address - * check for more block on the link list - */ - valid_addr = next_link_addr; - next_link_addr = le16_to_cpu(link_value) * sizeof(u16); - IWL_DEBUG_INFO(priv, "OTP blocks %d addr 0x%x\n", - usedblocks, next_link_addr); - if (iwl_read_otp_word(priv, next_link_addr, &link_value)) - return -EINVAL; - if (!link_value) { - /* - * reach the end of link list, return success and - * set address point to the starting address - * of the image - */ - *validblockaddr = valid_addr; - /* skip first 2 bytes (link list pointer) */ - *validblockaddr += 2; - return 0; - } - /* more in the link list, continue */ - usedblocks++; - } while (usedblocks <= priv->cfg->max_ll_items); - - /* OTP has no valid blocks */ - IWL_DEBUG_INFO(priv, "OTP has no valid blocks\n"); - return -EINVAL; -} - -/** - * iwl_eeprom_init - read EEPROM contents - * - * Load the EEPROM contents from adapter into priv->eeprom - * - * NOTE: This routine uses the non-debug IO access functions. - */ -int iwl_eeprom_init(struct iwl_priv *priv) -{ - __le16 *e; - u32 gp = iwl_read32(priv, CSR_EEPROM_GP); - int sz; - int ret; - u16 addr; - u16 validblockaddr = 0; - u16 cache_addr = 0; - - priv->nvm_device_type = iwlcore_get_nvm_type(priv); - if (priv->nvm_device_type == -ENOENT) - return -ENOENT; - /* allocate eeprom */ - IWL_DEBUG_INFO(priv, "NVM size = %d\n", priv->cfg->eeprom_size); - sz = priv->cfg->eeprom_size; - priv->eeprom = kzalloc(sz, GFP_KERNEL); - if (!priv->eeprom) { - ret = -ENOMEM; - goto alloc_err; - } - e = (__le16 *)priv->eeprom; - - ret = priv->cfg->ops->lib->eeprom_ops.verify_signature(priv); - if (ret < 0) { - IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp); - ret = -ENOENT; - goto err; - } - - /* Make sure driver (instead of uCode) is allowed to read EEPROM */ - ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv); - if (ret < 0) { - IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n"); - ret = -ENOENT; - goto err; - } - if (priv->nvm_device_type == NVM_DEVICE_TYPE_OTP) { - ret = iwl_init_otp_access(priv); - if (ret) { - IWL_ERR(priv, "Failed to initialize OTP access.\n"); - ret = -ENOENT; - goto done; - } - _iwl_write32(priv, CSR_EEPROM_GP, - iwl_read32(priv, CSR_EEPROM_GP) & - ~CSR_EEPROM_GP_IF_OWNER_MSK); - - iwl_set_bit(priv, CSR_OTP_GP_REG, - CSR_OTP_GP_REG_ECC_CORR_STATUS_MSK | - CSR_OTP_GP_REG_ECC_UNCORR_STATUS_MSK); - /* traversing the linked list if no shadow ram supported */ - if (!priv->cfg->shadow_ram_support) { - if (iwl_find_otp_image(priv, &validblockaddr)) { - ret = -ENOENT; - goto done; - } - } - for (addr = validblockaddr; addr < validblockaddr + sz; - addr += sizeof(u16)) { - __le16 eeprom_data; - - ret = iwl_read_otp_word(priv, addr, &eeprom_data); - if (ret) - goto done; - e[cache_addr / 2] = eeprom_data; - cache_addr += sizeof(u16); - } - } else { - /* eeprom is an array of 16bit values */ - for (addr = 0; addr < sz; addr += sizeof(u16)) { - u32 r; - - _iwl_write32(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_MSK_ADDR & (addr << 1)); - - ret = iwl_poll_direct_bit(priv, CSR_EEPROM_REG, - CSR_EEPROM_REG_READ_VALID_MSK, - IWL_EEPROM_ACCESS_TIMEOUT); - if (ret < 0) { - IWL_ERR(priv, "Time out reading EEPROM[%d]\n", addr); - goto done; - } - r = _iwl_read_direct32(priv, CSR_EEPROM_REG); - e[addr / 2] = cpu_to_le16(r >> 16); - } - } - ret = 0; -done: - priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv); -err: - if (ret) - iwl_eeprom_free(priv); -alloc_err: - return ret; -} -EXPORT_SYMBOL(iwl_eeprom_init); - -void iwl_eeprom_free(struct iwl_priv *priv) -{ - kfree(priv->eeprom); - priv->eeprom = NULL; -} -EXPORT_SYMBOL(iwl_eeprom_free); - -int iwl_eeprom_check_version(struct iwl_priv *priv) -{ - u16 eeprom_ver; - u16 calib_ver; - - eeprom_ver = iwl_eeprom_query16(priv, EEPROM_VERSION); - calib_ver = priv->cfg->ops->lib->eeprom_ops.calib_version(priv); - - if (eeprom_ver < priv->cfg->eeprom_ver || - calib_ver < priv->cfg->eeprom_calib_ver) - goto err; - - return 0; -err: - IWL_ERR(priv, "Unsupported (too old) EEPROM VER=0x%x < 0x%x CALIB=0x%x < 0x%x\n", - eeprom_ver, priv->cfg->eeprom_ver, - calib_ver, priv->cfg->eeprom_calib_ver); - return -EINVAL; - -} -EXPORT_SYMBOL(iwl_eeprom_check_version); - -const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset) -{ - return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset); -} -EXPORT_SYMBOL(iwl_eeprom_query_addr); - -u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset) -{ - if (!priv->eeprom) - return 0; - return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8); -} -EXPORT_SYMBOL(iwl_eeprom_query16); - -void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac) -{ - const u8 *addr = priv->cfg->ops->lib->eeprom_ops.query_addr(priv, - EEPROM_MAC_ADDRESS); - memcpy(mac, addr, ETH_ALEN); -} -EXPORT_SYMBOL(iwl_eeprom_get_mac); - -static void iwl_init_band_reference(const struct iwl_priv *priv, - int eep_band, int *eeprom_ch_count, - const struct iwl_eeprom_channel **eeprom_ch_info, - const u8 **eeprom_ch_index) -{ - u32 offset = priv->cfg->ops->lib-> - eeprom_ops.regulatory_bands[eep_band - 1]; - switch (eep_band) { - case 1: /* 2.4GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_1); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_1; - break; - case 2: /* 4.9GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_2); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_2; - break; - case 3: /* 5.2GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_3); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_3; - break; - case 4: /* 5.5GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_4); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_4; - break; - case 5: /* 5.7GHz band */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_5); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_5; - break; - case 6: /* 2.4GHz ht40 channels */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_6); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_6; - break; - case 7: /* 5 GHz ht40 channels */ - *eeprom_ch_count = ARRAY_SIZE(iwl_eeprom_band_7); - *eeprom_ch_info = (struct iwl_eeprom_channel *) - iwl_eeprom_query_addr(priv, offset); - *eeprom_ch_index = iwl_eeprom_band_7; - break; - default: - BUG(); - return; - } -} - -#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \ - ? # x " " : "") - -/** - * iwl_mod_ht40_chan_info - Copy ht40 channel info into driver's priv. - * - * Does not set up a command, or touch hardware. - */ -static int iwl_mod_ht40_chan_info(struct iwl_priv *priv, - enum ieee80211_band band, u16 channel, - const struct iwl_eeprom_channel *eeprom_ch, - u8 clear_ht40_extension_channel) -{ - struct iwl_channel_info *ch_info; - - ch_info = (struct iwl_channel_info *) - iwl_get_channel_info(priv, band, channel); - - if (!is_channel_valid(ch_info)) - return -1; - - IWL_DEBUG_INFO(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):" - " Ad-Hoc %ssupported\n", - ch_info->channel, - is_channel_a_band(ch_info) ? - "5.2" : "2.4", - CHECK_AND_PRINT(IBSS), - CHECK_AND_PRINT(ACTIVE), - CHECK_AND_PRINT(RADAR), - CHECK_AND_PRINT(WIDE), - CHECK_AND_PRINT(DFS), - eeprom_ch->flags, - eeprom_ch->max_power_avg, - ((eeprom_ch->flags & EEPROM_CHANNEL_IBSS) - && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ? - "" : "not "); - - ch_info->ht40_eeprom = *eeprom_ch; - ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg; - ch_info->ht40_curr_txpow = eeprom_ch->max_power_avg; - ch_info->ht40_min_power = 0; - ch_info->ht40_scan_power = eeprom_ch->max_power_avg; - ch_info->ht40_flags = eeprom_ch->flags; - if (eeprom_ch->flags & EEPROM_CHANNEL_VALID) - ch_info->ht40_extension_channel &= ~clear_ht40_extension_channel; - - return 0; -} - -/** - * iwl_get_max_txpower_avg - get the highest tx power from all chains. - * find the highest tx power from all chains for the channel - */ -static s8 iwl_get_max_txpower_avg(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, int element) -{ - s8 max_txpower_avg = 0; /* (dBm) */ - - IWL_DEBUG_INFO(priv, "%d - " - "chain_a: %d dB chain_b: %d dB " - "chain_c: %d dB mimo2: %d dB mimo3: %d dB\n", - element, - enhanced_txpower[element].chain_a_max >> 1, - enhanced_txpower[element].chain_b_max >> 1, - enhanced_txpower[element].chain_c_max >> 1, - enhanced_txpower[element].mimo2_max >> 1, - enhanced_txpower[element].mimo3_max >> 1); - /* Take the highest tx power from any valid chains */ - if ((priv->cfg->valid_tx_ant & ANT_A) && - (enhanced_txpower[element].chain_a_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].chain_a_max; - if ((priv->cfg->valid_tx_ant & ANT_B) && - (enhanced_txpower[element].chain_b_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].chain_b_max; - if ((priv->cfg->valid_tx_ant & ANT_C) && - (enhanced_txpower[element].chain_c_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].chain_c_max; - if (((priv->cfg->valid_tx_ant == ANT_AB) | - (priv->cfg->valid_tx_ant == ANT_BC) | - (priv->cfg->valid_tx_ant == ANT_AC)) && - (enhanced_txpower[element].mimo2_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].mimo2_max; - if ((priv->cfg->valid_tx_ant == ANT_ABC) && - (enhanced_txpower[element].mimo3_max > max_txpower_avg)) - max_txpower_avg = enhanced_txpower[element].mimo3_max; - - /* max. tx power in EEPROM is in 1/2 dBm format - * convert from 1/2 dBm to dBm - */ - return max_txpower_avg >> 1; -} - -/** - * iwl_update_common_txpower: update channel tx power - * update tx power per band based on EEPROM enhanced tx power info. - */ -static s8 iwl_update_common_txpower(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int section, int element) -{ - struct iwl_channel_info *ch_info; - int ch; - bool is_ht40 = false; - s8 max_txpower_avg; /* (dBm) */ - - /* it is common section, contain all type (Legacy, HT and HT40) - * based on the element in the section to determine - * is it HT 40 or not - */ - if (element == EEPROM_TXPOWER_COMMON_HT40_INDEX) - is_ht40 = true; - max_txpower_avg = - iwl_get_max_txpower_avg(priv, enhanced_txpower, element); - ch_info = priv->channel_info; - - for (ch = 0; ch < priv->channel_count; ch++) { - /* find matching band and update tx power if needed */ - if ((ch_info->band == enhinfo[section].band) && - (ch_info->max_power_avg < max_txpower_avg) && (!is_ht40)) { - /* Update regulatory-based run-time data */ - ch_info->max_power_avg = ch_info->curr_txpow = - max_txpower_avg; - ch_info->scan_power = max_txpower_avg; - } - if ((ch_info->band == enhinfo[section].band) && is_ht40 && - ch_info->ht40_max_power_avg && - (ch_info->ht40_max_power_avg < max_txpower_avg)) { - /* Update regulatory-based run-time data */ - ch_info->ht40_max_power_avg = max_txpower_avg; - ch_info->ht40_curr_txpow = max_txpower_avg; - ch_info->ht40_scan_power = max_txpower_avg; - } - ch_info++; - } - return max_txpower_avg; -} - -/** - * iwl_update_channel_txpower: update channel tx power - * update channel tx power based on EEPROM enhanced tx power info. - */ -static s8 iwl_update_channel_txpower(struct iwl_priv *priv, - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower, - int section, int element) -{ - struct iwl_channel_info *ch_info; - int ch; - u8 channel; - s8 max_txpower_avg; /* (dBm) */ - - channel = enhinfo[section].iwl_eeprom_section_channel[element]; - max_txpower_avg = - iwl_get_max_txpower_avg(priv, enhanced_txpower, element); - - ch_info = priv->channel_info; - for (ch = 0; ch < priv->channel_count; ch++) { - /* find matching channel and update tx power if needed */ - if (ch_info->channel == channel) { - if ((ch_info->max_power_avg < max_txpower_avg) && - (!enhinfo[section].is_ht40)) { - /* Update regulatory-based run-time data */ - ch_info->max_power_avg = max_txpower_avg; - ch_info->curr_txpow = max_txpower_avg; - ch_info->scan_power = max_txpower_avg; - } - if ((enhinfo[section].is_ht40) && - (ch_info->ht40_max_power_avg) && - (ch_info->ht40_max_power_avg < max_txpower_avg)) { - /* Update regulatory-based run-time data */ - ch_info->ht40_max_power_avg = max_txpower_avg; - ch_info->ht40_curr_txpow = max_txpower_avg; - ch_info->ht40_scan_power = max_txpower_avg; - } - break; - } - ch_info++; - } - return max_txpower_avg; -} - -/** - * iwlcore_eeprom_enhanced_txpower: process enhanced tx power info - */ -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv) -{ - int eeprom_section_count = 0; - int section, element; - struct iwl_eeprom_enhanced_txpwr *enhanced_txpower; - u32 offset; - s8 max_txpower_avg; /* (dBm) */ - - /* Loop through all the sections - * adjust bands and channel's max tx power - * Set the tx_power_user_lmt to the highest power - * supported by any channels and chains - */ - for (section = 0; section < ARRAY_SIZE(enhinfo); section++) { - eeprom_section_count = enhinfo[section].count; - offset = enhinfo[section].offset; - enhanced_txpower = (struct iwl_eeprom_enhanced_txpwr *) - iwl_eeprom_query_addr(priv, offset); - - for (element = 0; element < eeprom_section_count; element++) { - if (enhinfo[section].is_common) - max_txpower_avg = - iwl_update_common_txpower(priv, - enhanced_txpower, section, element); - else - max_txpower_avg = - iwl_update_channel_txpower(priv, - enhanced_txpower, section, element); - - /* Update the tx_power_user_lmt to the highest power - * supported by any channel */ - if (max_txpower_avg > priv->tx_power_user_lmt) - priv->tx_power_user_lmt = max_txpower_avg; - } - } -} -EXPORT_SYMBOL(iwlcore_eeprom_enhanced_txpower); - -#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \ - ? # x " " : "") - -/** - * iwl_init_channel_map - Set up driver's info for all possible channels - */ -int iwl_init_channel_map(struct iwl_priv *priv) -{ - int eeprom_ch_count = 0; - const u8 *eeprom_ch_index = NULL; - const struct iwl_eeprom_channel *eeprom_ch_info = NULL; - int band, ch; - struct iwl_channel_info *ch_info; - - if (priv->channel_count) { - IWL_DEBUG_INFO(priv, "Channel map already initialized.\n"); - return 0; - } - - IWL_DEBUG_INFO(priv, "Initializing regulatory info from EEPROM\n"); - - priv->channel_count = - ARRAY_SIZE(iwl_eeprom_band_1) + - ARRAY_SIZE(iwl_eeprom_band_2) + - ARRAY_SIZE(iwl_eeprom_band_3) + - ARRAY_SIZE(iwl_eeprom_band_4) + - ARRAY_SIZE(iwl_eeprom_band_5); - - IWL_DEBUG_INFO(priv, "Parsing data for %d channels.\n", priv->channel_count); - - priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) * - priv->channel_count, GFP_KERNEL); - if (!priv->channel_info) { - IWL_ERR(priv, "Could not allocate channel_info\n"); - priv->channel_count = 0; - return -ENOMEM; - } - - ch_info = priv->channel_info; - - /* Loop through the 5 EEPROM bands adding them in order to the - * channel map we maintain (that contains additional information than - * what just in the EEPROM) */ - for (band = 1; band <= 5; band++) { - - iwl_init_band_reference(priv, band, &eeprom_ch_count, - &eeprom_ch_info, &eeprom_ch_index); - - /* Loop through each band adding each of the channels */ - for (ch = 0; ch < eeprom_ch_count; ch++) { - ch_info->channel = eeprom_ch_index[ch]; - ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ : - IEEE80211_BAND_5GHZ; - - /* permanently store EEPROM's channel regulatory flags - * and max power in channel info database. */ - ch_info->eeprom = eeprom_ch_info[ch]; - - /* Copy the run-time flags so they are there even on - * invalid channels */ - ch_info->flags = eeprom_ch_info[ch].flags; - /* First write that ht40 is not enabled, and then enable - * one by one */ - ch_info->ht40_extension_channel = - IEEE80211_CHAN_NO_HT40; - - if (!(is_channel_valid(ch_info))) { - IWL_DEBUG_INFO(priv, "Ch. %d Flags %x [%sGHz] - " - "No traffic\n", - ch_info->channel, - ch_info->flags, - is_channel_a_band(ch_info) ? - "5.2" : "2.4"); - ch_info++; - continue; - } - - /* Initialize regulatory-based run-time data */ - ch_info->max_power_avg = ch_info->curr_txpow = - eeprom_ch_info[ch].max_power_avg; - ch_info->scan_power = eeprom_ch_info[ch].max_power_avg; - ch_info->min_power = 0; - - IWL_DEBUG_INFO(priv, "Ch. %d [%sGHz] %s%s%s%s%s%s(0x%02x %ddBm):" - " Ad-Hoc %ssupported\n", - ch_info->channel, - is_channel_a_band(ch_info) ? - "5.2" : "2.4", - CHECK_AND_PRINT_I(VALID), - CHECK_AND_PRINT_I(IBSS), - CHECK_AND_PRINT_I(ACTIVE), - CHECK_AND_PRINT_I(RADAR), - CHECK_AND_PRINT_I(WIDE), - CHECK_AND_PRINT_I(DFS), - eeprom_ch_info[ch].flags, - eeprom_ch_info[ch].max_power_avg, - ((eeprom_ch_info[ch]. - flags & EEPROM_CHANNEL_IBSS) - && !(eeprom_ch_info[ch]. - flags & EEPROM_CHANNEL_RADAR)) - ? "" : "not "); - - /* Set the tx_power_user_lmt to the highest power - * supported by any channel */ - if (eeprom_ch_info[ch].max_power_avg > - priv->tx_power_user_lmt) - priv->tx_power_user_lmt = - eeprom_ch_info[ch].max_power_avg; - - ch_info++; - } - } - - /* Check if we do have HT40 channels */ - if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] == - EEPROM_REGULATORY_BAND_NO_HT40 && - priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] == - EEPROM_REGULATORY_BAND_NO_HT40) - return 0; - - /* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */ - for (band = 6; band <= 7; band++) { - enum ieee80211_band ieeeband; - - iwl_init_band_reference(priv, band, &eeprom_ch_count, - &eeprom_ch_info, &eeprom_ch_index); - - /* EEPROM band 6 is 2.4, band 7 is 5 GHz */ - ieeeband = - (band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - - /* Loop through each band adding each of the channels */ - for (ch = 0; ch < eeprom_ch_count; ch++) { - /* Set up driver's info for lower half */ - iwl_mod_ht40_chan_info(priv, ieeeband, - eeprom_ch_index[ch], - &eeprom_ch_info[ch], - IEEE80211_CHAN_NO_HT40PLUS); - - /* Set up driver's info for upper half */ - iwl_mod_ht40_chan_info(priv, ieeeband, - eeprom_ch_index[ch] + 4, - &eeprom_ch_info[ch], - IEEE80211_CHAN_NO_HT40MINUS); - } - } - - /* for newer device (6000 series and up) - * EEPROM contain enhanced tx power information - * driver need to process addition information - * to determine the max channel tx power limits - */ - if (priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower) - priv->cfg->ops->lib->eeprom_ops.update_enhanced_txpower(priv); - - return 0; -} -EXPORT_SYMBOL(iwl_init_channel_map); - -/* - * iwl_free_channel_map - undo allocations in iwl_init_channel_map - */ -void iwl_free_channel_map(struct iwl_priv *priv) -{ - kfree(priv->channel_info); - priv->channel_count = 0; -} -EXPORT_SYMBOL(iwl_free_channel_map); - -/** - * iwl_get_channel_info - Find driver's private channel info - * - * Based on band and channel number. - */ -const struct iwl_channel_info *iwl_get_channel_info(const struct iwl_priv *priv, - enum ieee80211_band band, u16 channel) -{ - int i; - - switch (band) { - case IEEE80211_BAND_5GHZ: - for (i = 14; i < priv->channel_count; i++) { - if (priv->channel_info[i].channel == channel) - return &priv->channel_info[i]; - } - break; - case IEEE80211_BAND_2GHZ: - if (channel >= 1 && channel <= 14) - return &priv->channel_info[channel - 1]; - break; - default: - BUG(); - } - - return NULL; -} -EXPORT_SYMBOL(iwl_get_channel_info); - diff --git a/drivers/net/wireless/iwlwifi/iwl-eeprom.h b/drivers/net/wireless/iwlwifi/iwl-eeprom.h deleted file mode 100644 index fc93f12853ee..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-eeprom.h +++ /dev/null @@ -1,491 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef __iwl_eeprom_h__ -#define __iwl_eeprom_h__ - -struct iwl_priv; - -/* - * EEPROM access time values: - * - * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG. - * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1). - * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec. - * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG. - */ -#define IWL_EEPROM_ACCESS_TIMEOUT 5000 /* uSec */ - -#define IWL_EEPROM_SEM_TIMEOUT 10 /* microseconds */ -#define IWL_EEPROM_SEM_RETRY_LIMIT 1000 /* number of attempts (not time) */ - - -/* - * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags. - * - * IBSS and/or AP operation is allowed *only* on those channels with - * (VALID && IBSS && ACTIVE && !RADAR). This restriction is in place because - * RADAR detection is not supported by the 4965 driver, but is a - * requirement for establishing a new network for legal operation on channels - * requiring RADAR detection or restricting ACTIVE scanning. - * - * NOTE: "WIDE" flag does not indicate anything about "HT40" 40 MHz channels. - * It only indicates that 20 MHz channel use is supported; HT40 channel - * usage is indicated by a separate set of regulatory flags for each - * HT40 channel pair. - * - * NOTE: Using a channel inappropriately will result in a uCode error! - */ -#define IWL_NUM_TX_CALIB_GROUPS 5 -enum { - EEPROM_CHANNEL_VALID = (1 << 0), /* usable for this SKU/geo */ - EEPROM_CHANNEL_IBSS = (1 << 1), /* usable as an IBSS channel */ - /* Bit 2 Reserved */ - EEPROM_CHANNEL_ACTIVE = (1 << 3), /* active scanning allowed */ - EEPROM_CHANNEL_RADAR = (1 << 4), /* radar detection required */ - EEPROM_CHANNEL_WIDE = (1 << 5), /* 20 MHz channel okay */ - /* Bit 6 Reserved (was Narrow Channel) */ - EEPROM_CHANNEL_DFS = (1 << 7), /* dynamic freq selection candidate */ -}; - -/* SKU Capabilities */ -#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE (1 << 0) -#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE (1 << 1) - -/* *regulatory* channel data format in eeprom, one for each channel. - * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */ -struct iwl_eeprom_channel { - u8 flags; /* EEPROM_CHANNEL_* flags copied from EEPROM */ - s8 max_power_avg; /* max power (dBm) on this chnl, limit 31 */ -} __attribute__ ((packed)); - -/** - * iwl_eeprom_enhanced_txpwr structure - * This structure presents the enhanced regulatory tx power limit layout - * in eeprom image - * Enhanced regulatory tx power portion of eeprom image can be broken down - * into individual structures; each one is 8 bytes in size and contain the - * following information - * @chain_a_max_pwr: chain a max power in 1/2 dBm - * @chain_b_max_pwr: chain b max power in 1/2 dBm - * @chain_c_max_pwr: chain c max power in 1/2 dBm - * @mimo2_max_pwr: mimo2 max power in 1/2 dBm - * @mimo3_max_pwr: mimo3 max power in 1/2 dBm - * - */ -struct iwl_eeprom_enhanced_txpwr { - __le16 common; - s8 chain_a_max; - s8 chain_b_max; - s8 chain_c_max; - s8 reserved1; - s8 mimo2_max; - s8 mimo3_max; -} __attribute__ ((packed)); - -/* 3945 Specific */ -#define EEPROM_3945_EEPROM_VERSION (0x2f) - -/* 4965 has two radio transmitters (and 3 radio receivers) */ -#define EEPROM_TX_POWER_TX_CHAINS (2) - -/* 4965 has room for up to 8 sets of txpower calibration data */ -#define EEPROM_TX_POWER_BANDS (8) - -/* 4965 factory calibration measures txpower gain settings for - * each of 3 target output levels */ -#define EEPROM_TX_POWER_MEASUREMENTS (3) - -/* 4965 Specific */ -/* 4965 driver does not work with txpower calibration version < 5 */ -#define EEPROM_4965_TX_POWER_VERSION (5) -#define EEPROM_4965_EEPROM_VERSION (0x2f) -#define EEPROM_4965_CALIB_VERSION_OFFSET (2*0xB6) /* 2 bytes */ -#define EEPROM_4965_CALIB_TXPOWER_OFFSET (2*0xE8) /* 48 bytes */ -#define EEPROM_4965_BOARD_REVISION (2*0x4F) /* 2 bytes */ -#define EEPROM_4965_BOARD_PBA (2*0x56+1) /* 9 bytes */ - -/* 5000 Specific */ -#define EEPROM_5000_TX_POWER_VERSION (4) -#define EEPROM_5000_EEPROM_VERSION (0x11A) - -/*5000 calibrations */ -#define EEPROM_5000_CALIB_ALL (INDIRECT_ADDRESS | INDIRECT_CALIBRATION) -#define EEPROM_5000_XTAL ((2*0x128) | EEPROM_5000_CALIB_ALL) -#define EEPROM_5000_TEMPERATURE ((2*0x12A) | EEPROM_5000_CALIB_ALL) - -/* 5000 links */ -#define EEPROM_5000_LINK_HOST (2*0x64) -#define EEPROM_5000_LINK_GENERAL (2*0x65) -#define EEPROM_5000_LINK_REGULATORY (2*0x66) -#define EEPROM_5000_LINK_CALIBRATION (2*0x67) -#define EEPROM_5000_LINK_PROCESS_ADJST (2*0x68) -#define EEPROM_5000_LINK_OTHERS (2*0x69) - -/* 5000 regulatory - indirect access */ -#define EEPROM_5000_REG_SKU_ID ((0x02)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 4 bytes */ -#define EEPROM_5000_REG_BAND_1_CHANNELS ((0x08)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 28 bytes */ -#define EEPROM_5000_REG_BAND_2_CHANNELS ((0x26)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 26 bytes */ -#define EEPROM_5000_REG_BAND_3_CHANNELS ((0x42)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -#define EEPROM_5000_REG_BAND_4_CHANNELS ((0x5C)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ -#define EEPROM_5000_REG_BAND_5_CHANNELS ((0x74)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 12 bytes */ -#define EEPROM_5000_REG_BAND_24_HT40_CHANNELS ((0x82)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 14 bytes */ -#define EEPROM_5000_REG_BAND_52_HT40_CHANNELS ((0x92)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 22 bytes */ - -/* 6000 and up regulatory tx power - indirect access */ -/* max. elements per section */ -#define EEPROM_MAX_TXPOWER_SECTION_ELEMENTS (8) -#define EEPROM_TXPOWER_COMMON_HT40_INDEX (2) - -/** - * Partition the enhanced tx power portion of eeprom image into - * 10 sections based on band, modulation, frequency and channel - * - * Section 1: all CCK channels - * Section 2: all 2.4 GHz OFDM (Legacy, HT and HT40 ) channels - * Section 3: all 5.2 GHz OFDM (Legacy, HT and HT40) channels - * Section 4: 2.4 GHz 20MHz channels: 1, 2, 10, 11. Both Legacy and HT - * Section 5: 2.4 GHz 40MHz channels: 1, 2, 6, 7, 9, (_above_) - * Section 6: 5.2 GHz 20MHz channels: 36, 64, 100, both Legacy and HT - * Section 7: 5.2 GHz 40MHz channels: 36, 60, 100 (_above_) - * Section 8: 2.4 GHz channel 13, Both Legacy and HT - * Section 9: 2.4 GHz channel 140, Both Legacy and HT - * Section 10: 2.4 GHz 40MHz channels: 132, 44 (_above_) - */ -/* 2.4 GHz band: CCK */ -#define EEPROM_LB_CCK_20_COMMON ((0xA8)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 8 bytes */ -/* 2.4 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */ -#define EEPROM_LB_OFDM_COMMON ((0xB0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -/* 5.2 GHz band: 20MHz-Legacy, 20MHz-HT, 40MHz-HT */ -#define EEPROM_HB_OFDM_COMMON ((0xC8)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -/* 2.4GHz band channels: - * 1Legacy, 1HT, 2Legacy, 2HT, 10Legacy, 10HT, 11Legacy, 11HT */ -#define EEPROM_LB_OFDM_20_BAND ((0xE0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 64 bytes */ -/* 2.4 GHz band HT40 channels: (1,+1) (2,+1) (6,+1) (7,+1) (9,+1) */ -#define EEPROM_LB_OFDM_HT40_BAND ((0x120)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 40 bytes */ -/* 5.2GHz band channels: 36Legacy, 36HT, 64Legacy, 64HT, 100Legacy, 100HT */ -#define EEPROM_HB_OFDM_20_BAND ((0x148)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 48 bytes */ -/* 5.2 GHz band HT40 channels: (36,+1) (60,+1) (100,+1) */ -#define EEPROM_HB_OFDM_HT40_BAND ((0x178)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 24 bytes */ -/* 2.4 GHz band, channnel 13: Legacy, HT */ -#define EEPROM_LB_OFDM_20_CHANNEL_13 ((0x190)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */ -/* 5.2 GHz band, channnel 140: Legacy, HT */ -#define EEPROM_HB_OFDM_20_CHANNEL_140 ((0x1A0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */ -/* 5.2 GHz band, HT40 channnels (132,+1) (44,+1) */ -#define EEPROM_HB_OFDM_HT40_BAND_1 ((0x1B0)\ - | INDIRECT_ADDRESS | INDIRECT_REGULATORY) /* 16 bytes */ - - -/* 5050 Specific */ -#define EEPROM_5050_TX_POWER_VERSION (4) -#define EEPROM_5050_EEPROM_VERSION (0x21E) - -/* OTP */ -/* lower blocks contain EEPROM image and calibration data */ -#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */ -/* high blocks contain PAPD data */ -#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */ -#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */ -#define OTP_MAX_LL_ITEMS_1000 (3) /* OTP blocks for 1000 */ -#define OTP_MAX_LL_ITEMS_6x00 (4) /* OTP blocks for 6x00 */ -#define OTP_MAX_LL_ITEMS_6x50 (7) /* OTP blocks for 6x50 */ - -/* 2.4 GHz */ -extern const u8 iwl_eeprom_band_1[14]; - -/* - * factory calibration data for one txpower level, on one channel, - * measured on one of the 2 tx chains (radio transmitter and associated - * antenna). EEPROM contains: - * - * 1) Temperature (degrees Celsius) of device when measurement was made. - * - * 2) Gain table index used to achieve the target measurement power. - * This refers to the "well-known" gain tables (see iwl-4965-hw.h). - * - * 3) Actual measured output power, in half-dBm ("34" = 17 dBm). - * - * 4) RF power amplifier detector level measurement (not used). - */ -struct iwl_eeprom_calib_measure { - u8 temperature; /* Device temperature (Celsius) */ - u8 gain_idx; /* Index into gain table */ - u8 actual_pow; /* Measured RF output power, half-dBm */ - s8 pa_det; /* Power amp detector level (not used) */ -} __attribute__ ((packed)); - - -/* - * measurement set for one channel. EEPROM contains: - * - * 1) Channel number measured - * - * 2) Measurements for each of 3 power levels for each of 2 radio transmitters - * (a.k.a. "tx chains") (6 measurements altogether) - */ -struct iwl_eeprom_calib_ch_info { - u8 ch_num; - struct iwl_eeprom_calib_measure - measurements[EEPROM_TX_POWER_TX_CHAINS] - [EEPROM_TX_POWER_MEASUREMENTS]; -} __attribute__ ((packed)); - -/* - * txpower subband info. - * - * For each frequency subband, EEPROM contains the following: - * - * 1) First and last channels within range of the subband. "0" values - * indicate that this sample set is not being used. - * - * 2) Sample measurement sets for 2 channels close to the range endpoints. - */ -struct iwl_eeprom_calib_subband_info { - u8 ch_from; /* channel number of lowest channel in subband */ - u8 ch_to; /* channel number of highest channel in subband */ - struct iwl_eeprom_calib_ch_info ch1; - struct iwl_eeprom_calib_ch_info ch2; -} __attribute__ ((packed)); - - -/* - * txpower calibration info. EEPROM contains: - * - * 1) Factory-measured saturation power levels (maximum levels at which - * tx power amplifier can output a signal without too much distortion). - * There is one level for 2.4 GHz band and one for 5 GHz band. These - * values apply to all channels within each of the bands. - * - * 2) Factory-measured power supply voltage level. This is assumed to be - * constant (i.e. same value applies to all channels/bands) while the - * factory measurements are being made. - * - * 3) Up to 8 sets of factory-measured txpower calibration values. - * These are for different frequency ranges, since txpower gain - * characteristics of the analog radio circuitry vary with frequency. - * - * Not all sets need to be filled with data; - * struct iwl_eeprom_calib_subband_info contains range of channels - * (0 if unused) for each set of data. - */ -struct iwl_eeprom_calib_info { - u8 saturation_power24; /* half-dBm (e.g. "34" = 17 dBm) */ - u8 saturation_power52; /* half-dBm */ - __le16 voltage; /* signed */ - struct iwl_eeprom_calib_subband_info - band_info[EEPROM_TX_POWER_BANDS]; -} __attribute__ ((packed)); - - -#define ADDRESS_MSK 0x0000FFFF -#define INDIRECT_TYPE_MSK 0x000F0000 -#define INDIRECT_HOST 0x00010000 -#define INDIRECT_GENERAL 0x00020000 -#define INDIRECT_REGULATORY 0x00030000 -#define INDIRECT_CALIBRATION 0x00040000 -#define INDIRECT_PROCESS_ADJST 0x00050000 -#define INDIRECT_OTHERS 0x00060000 -#define INDIRECT_ADDRESS 0x00100000 - -/* General */ -#define EEPROM_DEVICE_ID (2*0x08) /* 2 bytes */ -#define EEPROM_MAC_ADDRESS (2*0x15) /* 6 bytes */ -#define EEPROM_BOARD_REVISION (2*0x35) /* 2 bytes */ -#define EEPROM_BOARD_PBA_NUMBER (2*0x3B+1) /* 9 bytes */ -#define EEPROM_VERSION (2*0x44) /* 2 bytes */ -#define EEPROM_SKU_CAP (2*0x45) /* 1 bytes */ -#define EEPROM_LEDS_MODE (2*0x45+1) /* 1 bytes */ -#define EEPROM_OEM_MODE (2*0x46) /* 2 bytes */ -#define EEPROM_WOWLAN_MODE (2*0x47) /* 2 bytes */ -#define EEPROM_RADIO_CONFIG (2*0x48) /* 2 bytes */ -#define EEPROM_3945_M_VERSION (2*0x4A) /* 1 bytes */ -#define EEPROM_ANTENNA_SWITCH_TYPE (2*0x4A+1) /* 1 bytes */ - -/* The following masks are to be applied on EEPROM_RADIO_CONFIG */ -#define EEPROM_RF_CFG_TYPE_MSK(x) (x & 0x3) /* bits 0-1 */ -#define EEPROM_RF_CFG_STEP_MSK(x) ((x >> 2) & 0x3) /* bits 2-3 */ -#define EEPROM_RF_CFG_DASH_MSK(x) ((x >> 4) & 0x3) /* bits 4-5 */ -#define EEPROM_RF_CFG_PNUM_MSK(x) ((x >> 6) & 0x3) /* bits 6-7 */ -#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8) & 0xF) /* bits 8-11 */ -#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */ - -#define EEPROM_3945_RF_CFG_TYPE_MAX 0x0 -#define EEPROM_4965_RF_CFG_TYPE_MAX 0x1 -#define EEPROM_5000_RF_CFG_TYPE_MAX 0x3 - -/* - * Per-channel regulatory data. - * - * Each channel that *might* be supported by iwl has a fixed location - * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory - * txpower (MSB). - * - * Entries immediately below are for 20 MHz channel width. HT40 (40 MHz) - * channels (only for 4965, not supported by 3945) appear later in the EEPROM. - * - * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 - */ -#define EEPROM_REGULATORY_SKU_ID (2*0x60) /* 4 bytes */ -#define EEPROM_REGULATORY_BAND_1 (2*0x62) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_1_CHANNELS (2*0x63) /* 28 bytes */ - -/* - * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196, - * 5.0 GHz channels 7, 8, 11, 12, 16 - * (4915-5080MHz) (none of these is ever supported) - */ -#define EEPROM_REGULATORY_BAND_2 (2*0x71) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_2_CHANNELS (2*0x72) /* 26 bytes */ - -/* - * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64 - * (5170-5320MHz) - */ -#define EEPROM_REGULATORY_BAND_3 (2*0x7F) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_3_CHANNELS (2*0x80) /* 24 bytes */ - -/* - * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140 - * (5500-5700MHz) - */ -#define EEPROM_REGULATORY_BAND_4 (2*0x8C) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_4_CHANNELS (2*0x8D) /* 22 bytes */ - -/* - * 5.7 GHz channels 145, 149, 153, 157, 161, 165 - * (5725-5825MHz) - */ -#define EEPROM_REGULATORY_BAND_5 (2*0x98) /* 2 bytes */ -#define EEPROM_REGULATORY_BAND_5_CHANNELS (2*0x99) /* 12 bytes */ - -/* - * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11) - * - * The channel listed is the center of the lower 20 MHz half of the channel. - * The overall center frequency is actually 2 channels (10 MHz) above that, - * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away - * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5, - * and the overall HT40 channel width centers on channel 3. - * - * NOTE: The RXON command uses 20 MHz channel numbers to specify the - * control channel to which to tune. RXON also specifies whether the - * control channel is the upper or lower half of a HT40 channel. - * - * NOTE: 4965 does not support HT40 channels on 2.4 GHz. - */ -#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0) /* 14 bytes */ - -/* - * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64), - * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161) - */ -#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8) /* 22 bytes */ - -#define EEPROM_REGULATORY_BAND_NO_HT40 (0) - -struct iwl_eeprom_ops { - const u32 regulatory_bands[7]; - int (*verify_signature) (struct iwl_priv *priv); - int (*acquire_semaphore) (struct iwl_priv *priv); - void (*release_semaphore) (struct iwl_priv *priv); - u16 (*calib_version) (struct iwl_priv *priv); - const u8* (*query_addr) (const struct iwl_priv *priv, size_t offset); - void (*update_enhanced_txpower) (struct iwl_priv *priv); -}; - - -void iwl_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac); -int iwl_eeprom_init(struct iwl_priv *priv); -void iwl_eeprom_free(struct iwl_priv *priv); -int iwl_eeprom_check_version(struct iwl_priv *priv); -const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); -u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset); - -int iwlcore_eeprom_verify_signature(struct iwl_priv *priv); -int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv); -void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv); -const u8 *iwlcore_eeprom_query_addr(const struct iwl_priv *priv, size_t offset); -void iwlcore_eeprom_enhanced_txpower(struct iwl_priv *priv); -int iwl_init_channel_map(struct iwl_priv *priv); -void iwl_free_channel_map(struct iwl_priv *priv); -const struct iwl_channel_info *iwl_get_channel_info( - const struct iwl_priv *priv, - enum ieee80211_band band, u16 channel); - -#endif /* __iwl_eeprom_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-fh.h b/drivers/net/wireless/iwlwifi/iwl-fh.h deleted file mode 100644 index 65fa8a69fd5a..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-fh.h +++ /dev/null @@ -1,499 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - *****************************************************************************/ -#ifndef __iwl_fh_h__ -#define __iwl_fh_h__ - -/****************************/ -/* Flow Handler Definitions */ -/****************************/ - -/** - * This I/O area is directly read/writable by driver (e.g. Linux uses writel()) - * Addresses are offsets from device's PCI hardware base address. - */ -#define FH_MEM_LOWER_BOUND (0x1000) -#define FH_MEM_UPPER_BOUND (0x2000) - -/** - * Keep-Warm (KW) buffer base address. - * - * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the - * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency - * DRAM access when 4965 is Txing or Rxing. The dummy accesses prevent host - * from going into a power-savings mode that would cause higher DRAM latency, - * and possible data over/under-runs, before all Tx/Rx is complete. - * - * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4) - * of the buffer, which must be 4K aligned. Once this is set up, the 4965 - * automatically invokes keep-warm accesses when normal accesses might not - * be sufficient to maintain fast DRAM response. - * - * Bit fields: - * 31-0: Keep-warm buffer physical base address [35:4], must be 4K aligned - */ -#define FH_KW_MEM_ADDR_REG (FH_MEM_LOWER_BOUND + 0x97C) - - -/** - * TFD Circular Buffers Base (CBBC) addresses - * - * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident - * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs) - * (see struct iwl_tfd_frame). These 16 pointer registers are offset by 0x04 - * bytes from one another. Each TFD circular buffer in DRAM must be 256-byte - * aligned (address bits 0-7 must be 0). - * - * Bit fields in each pointer register: - * 27-0: TFD CB physical base address [35:8], must be 256-byte aligned - */ -#define FH_MEM_CBBC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0) -#define FH_MEM_CBBC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xA10) - -/* Find TFD CB base pointer for given queue (range 0-15). */ -#define FH_MEM_CBBC_QUEUE(x) (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4) - - -/** - * Rx SRAM Control and Status Registers (RSCSR) - * - * These registers provide handshake between driver and 4965 for the Rx queue - * (this queue handles *all* command responses, notifications, Rx data, etc. - * sent from 4965 uCode to host driver). Unlike Tx, there is only one Rx - * queue, and only one Rx DMA/FIFO channel. Also unlike Tx, which can - * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer - * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1 - * mapping between RBDs and RBs. - * - * Driver must allocate host DRAM memory for the following, and set the - * physical address of each into 4965 registers: - * - * 1) Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256 - * entries (although any power of 2, up to 4096, is selectable by driver). - * Each entry (1 dword) points to a receive buffer (RB) of consistent size - * (typically 4K, although 8K or 16K are also selectable by driver). - * Driver sets up RB size and number of RBDs in the CB via Rx config - * register FH_MEM_RCSR_CHNL0_CONFIG_REG. - * - * Bit fields within one RBD: - * 27-0: Receive Buffer physical address bits [35:8], 256-byte aligned - * - * Driver sets physical address [35:8] of base of RBD circular buffer - * into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0]. - * - * 2) Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers - * (RBs) have been filled, via a "write pointer", actually the index of - * the RB's corresponding RBD within the circular buffer. Driver sets - * physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0]. - * - * Bit fields in lower dword of Rx status buffer (upper dword not used - * by driver; see struct iwl4965_shared, val0): - * 31-12: Not used by driver - * 11- 0: Index of last filled Rx buffer descriptor - * (4965 writes, driver reads this value) - * - * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must - * enter pointers to these RBs into contiguous RBD circular buffer entries, - * and update the 4965's "write" index register, - * FH_RSCSR_CHNL0_RBDCB_WPTR_REG. - * - * This "write" index corresponds to the *next* RBD that the driver will make - * available, i.e. one RBD past the tail of the ready-to-fill RBDs within - * the circular buffer. This value should initially be 0 (before preparing any - * RBs), should be 8 after preparing the first 8 RBs (for example), and must - * wrap back to 0 at the end of the circular buffer (but don't wrap before - * "read" index has advanced past 1! See below). - * NOTE: 4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8. - * - * As the 4965 fills RBs (referenced from contiguous RBDs within the circular - * buffer), it updates the Rx status buffer in host DRAM, 2) described above, - * to tell the driver the index of the latest filled RBD. The driver must - * read this "read" index from DRAM after receiving an Rx interrupt from 4965. - * - * The driver must also internally keep track of a third index, which is the - * next RBD to process. When receiving an Rx interrupt, driver should process - * all filled but unprocessed RBs up to, but not including, the RB - * corresponding to the "read" index. For example, if "read" index becomes "1", - * driver may process the RB pointed to by RBD 0. Depending on volume of - * traffic, there may be many RBs to process. - * - * If read index == write index, 4965 thinks there is no room to put new data. - * Due to this, the maximum number of filled RBs is 255, instead of 256. To - * be safe, make sure that there is a gap of at least 2 RBDs between "write" - * and "read" indexes; that is, make sure that there are no more than 254 - * buffers waiting to be filled. - */ -#define FH_MEM_RSCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xBC0) -#define FH_MEM_RSCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xC00) -#define FH_MEM_RSCSR_CHNL0 (FH_MEM_RSCSR_LOWER_BOUND) - -/** - * Physical base address of 8-byte Rx Status buffer. - * Bit fields: - * 31-0: Rx status buffer physical base address [35:4], must 16-byte aligned. - */ -#define FH_RSCSR_CHNL0_STTS_WPTR_REG (FH_MEM_RSCSR_CHNL0) - -/** - * Physical base address of Rx Buffer Descriptor Circular Buffer. - * Bit fields: - * 27-0: RBD CD physical base address [35:8], must be 256-byte aligned. - */ -#define FH_RSCSR_CHNL0_RBDCB_BASE_REG (FH_MEM_RSCSR_CHNL0 + 0x004) - -/** - * Rx write pointer (index, really!). - * Bit fields: - * 11-0: Index of driver's most recent prepared-to-be-filled RBD, + 1. - * NOTE: For 256-entry circular buffer, use only bits [7:0]. - */ -#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG (FH_MEM_RSCSR_CHNL0 + 0x008) -#define FH_RSCSR_CHNL0_WPTR (FH_RSCSR_CHNL0_RBDCB_WPTR_REG) - - -/** - * Rx Config/Status Registers (RCSR) - * Rx Config Reg for channel 0 (only channel used) - * - * Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for - * normal operation (see bit fields). - * - * Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA. - * Driver should poll FH_MEM_RSSR_RX_STATUS_REG for - * FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing. - * - * Bit fields: - * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame, - * '10' operate normally - * 29-24: reserved - * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal), - * min "5" for 32 RBDs, max "12" for 4096 RBDs. - * 19-18: reserved - * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K, - * '10' 12K, '11' 16K. - * 15-14: reserved - * 13-12: IRQ destination; '00' none, '01' host driver (normal operation) - * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec) - * typical value 0x10 (about 1/2 msec) - * 3- 0: reserved - */ -#define FH_MEM_RCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC00) -#define FH_MEM_RCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xCC0) -#define FH_MEM_RCSR_CHNL0 (FH_MEM_RCSR_LOWER_BOUND) - -#define FH_MEM_RCSR_CHNL0_CONFIG_REG (FH_MEM_RCSR_CHNL0) - -#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */ -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK (0x00001000) /* bits 12 */ -#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */ -#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK (0x00030000) /* bits 16-17 */ -#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */ -#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/ - -#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS (20) -#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS (4) -#define RX_RB_TIMEOUT (0x10) - -#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL (0x00000000) -#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL (0x40000000) -#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL (0x80000000) - -#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K (0x00000000) -#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K (0x00010000) -#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K (0x00020000) -#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K (0x00030000) - -#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY (0x00000004) -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL (0x00000000) -#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL (0x00001000) - -#define FH_RSCSR_FRAME_SIZE_MSK (0x00003FFF) /* bits 0-13 */ - -/** - * Rx Shared Status Registers (RSSR) - * - * After stopping Rx DMA channel (writing 0 to - * FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll - * FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle. - * - * Bit fields: - * 24: 1 = Channel 0 is idle - * - * FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV - * contain default values that should not be altered by the driver. - */ -#define FH_MEM_RSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xC40) -#define FH_MEM_RSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xD00) - -#define FH_MEM_RSSR_SHARED_CTRL_REG (FH_MEM_RSSR_LOWER_BOUND) -#define FH_MEM_RSSR_RX_STATUS_REG (FH_MEM_RSSR_LOWER_BOUND + 0x004) -#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\ - (FH_MEM_RSSR_LOWER_BOUND + 0x008) - -#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (0x01000000) - -#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT 28 - -/* TFDB Area - TFDs buffer table */ -#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK (0xFFFFFFFF) -#define FH_TFDIB_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x900) -#define FH_TFDIB_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x958) -#define FH_TFDIB_CTRL0_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl)) -#define FH_TFDIB_CTRL1_REG(_chnl) (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4) - -/** - * Transmit DMA Channel Control/Status Registers (TCSR) - * - * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels - * supported in hardware (don't confuse these with the 16 Tx queues in DRAM, - * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes. - * - * To use a Tx DMA channel, driver must initialize its - * FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with: - * - * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE | - * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL - * - * All other bits should be 0. - * - * Bit fields: - * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame, - * '10' operate normally - * 29- 4: Reserved, set to "0" - * 3: Enable internal DMA requests (1, normal operation), disable (0) - * 2- 0: Reserved, set to "0" - */ -#define FH_TCSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xD00) -#define FH_TCSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xE60) - -/* Find Control/Status reg for given Tx DMA/FIFO channel */ -#define FH49_TCSR_CHNL_NUM (7) -#define FH50_TCSR_CHNL_NUM (8) - -/* TCSR: tx_config register values */ -#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl) \ - (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl)) -#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl) \ - (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4) -#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl) \ - (FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8) - -#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF (0x00000000) -#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV (0x00000001) - -#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE (0x00000000) -#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE (0x00000008) - -#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT (0x00000000) -#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD (0x00100000) -#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD (0x00200000) - -#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT (0x00000000) -#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD (0x00400000) -#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD (0x00800000) - -#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE (0x00000000) -#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF (0x40000000) -#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE (0x80000000) - -#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY (0x00000000) -#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT (0x00002000) -#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID (0x00000003) - -#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM (20) -#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX (12) - -/** - * Tx Shared Status Registers (TSSR) - * - * After stopping Tx DMA channel (writing 0 to - * FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll - * FH_TSSR_TX_STATUS_REG until selected Tx channel is idle - * (channel's buffers empty | no pending requests). - * - * Bit fields: - * 31-24: 1 = Channel buffers empty (channel 7:0) - * 23-16: 1 = No pending requests (channel 7:0) - */ -#define FH_TSSR_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0xEA0) -#define FH_TSSR_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0xEC0) - -#define FH_TSSR_TX_STATUS_REG (FH_TSSR_LOWER_BOUND + 0x010) - -#define FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) ((1 << (_chnl)) << 24) -#define FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl) ((1 << (_chnl)) << 16) - -#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) \ - (FH_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_chnl) | \ - FH_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_chnl)) - -/* Tx service channels */ -#define FH_SRVC_CHNL (9) -#define FH_SRVC_LOWER_BOUND (FH_MEM_LOWER_BOUND + 0x9C8) -#define FH_SRVC_UPPER_BOUND (FH_MEM_LOWER_BOUND + 0x9D0) -#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \ - (FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4) - -#define FH_TX_CHICKEN_BITS_REG (FH_MEM_LOWER_BOUND + 0xE98) -/* Instruct FH to increment the retry count of a packet when - * it is brought from the memory to TX-FIFO - */ -#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN (0x00000002) - -#define RX_QUEUE_SIZE 256 -#define RX_QUEUE_MASK 255 -#define RX_QUEUE_SIZE_LOG 8 - -/* - * RX related structures and functions - */ -#define RX_FREE_BUFFERS 64 -#define RX_LOW_WATERMARK 8 - -/* Size of one Rx buffer in host DRAM */ -#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */ -#define IWL_RX_BUF_SIZE_4K (4 * 1024) -#define IWL_RX_BUF_SIZE_8K (8 * 1024) - -/** - * struct iwl_rb_status - reseve buffer status - * host memory mapped FH registers - * @closed_rb_num [0:11] - Indicates the index of the RB which was closed - * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed - * @finished_rb_num [0:11] - Indicates the index of the current RB - * in which the last frame was written to - * @finished_fr_num [0:11] - Indicates the index of the RX Frame - * which was transfered - */ -struct iwl_rb_status { - __le16 closed_rb_num; - __le16 closed_fr_num; - __le16 finished_rb_num; - __le16 finished_fr_nam; - __le32 __unused; /* 3945 only */ -} __attribute__ ((packed)); - - -#define TFD_QUEUE_SIZE_MAX (256) -#define TFD_QUEUE_SIZE_BC_DUP (64) -#define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) -#define IWL_TX_DMA_MASK DMA_BIT_MASK(36) -#define IWL_NUM_OF_TBS 20 - -static inline u8 iwl_get_dma_hi_addr(dma_addr_t addr) -{ - return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF; -} -/** - * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor - * - * This structure contains dma address and length of transmission address - * - * @lo: low [31:0] portion of the dma address of TX buffer - * every even is unaligned on 16 bit boundary - * @hi_n_len 0-3 [35:32] portion of dma - * 4-15 length of the tx buffer - */ -struct iwl_tfd_tb { - __le32 lo; - __le16 hi_n_len; -} __attribute__((packed)); - -/** - * struct iwl_tfd - * - * Transmit Frame Descriptor (TFD) - * - * @ __reserved1[3] reserved - * @ num_tbs 0-4 number of active tbs - * 5 reserved - * 6-7 padding (not used) - * @ tbs[20] transmit frame buffer descriptors - * @ __pad padding - * - * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM. - * Both driver and device share these circular buffers, each of which must be - * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes - * - * Driver must indicate the physical address of the base of each - * circular buffer via the FH_MEM_CBBC_QUEUE registers. - * - * Each TFD contains pointer/size information for up to 20 data buffers - * in host DRAM. These buffers collectively contain the (one) frame described - * by the TFD. Each buffer must be a single contiguous block of memory within - * itself, but buffers may be scattered in host DRAM. Each buffer has max size - * of (4K - 4). The concatenates all of a TFD's buffers into a single - * Tx frame, up to 8 KBytes in size. - * - * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx. - */ -struct iwl_tfd { - u8 __reserved1[3]; - u8 num_tbs; - struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS]; - __le32 __pad; -} __attribute__ ((packed)); - -/* Keep Warm Size */ -#define IWL_KW_SIZE 0x1000 /* 4k */ - -#endif /* !__iwl_fh_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c deleted file mode 100644 index a6856daf14cb..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c +++ /dev/null @@ -1,289 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - -#include -#include -#include -#include - -#include "iwl-dev.h" /* FIXME: remove */ -#include "iwl-debug.h" -#include "iwl-eeprom.h" -#include "iwl-core.h" - - -const char *get_cmd_string(u8 cmd) -{ - switch (cmd) { - IWL_CMD(REPLY_ALIVE); - IWL_CMD(REPLY_ERROR); - IWL_CMD(REPLY_RXON); - IWL_CMD(REPLY_RXON_ASSOC); - IWL_CMD(REPLY_QOS_PARAM); - IWL_CMD(REPLY_RXON_TIMING); - IWL_CMD(REPLY_ADD_STA); - IWL_CMD(REPLY_REMOVE_STA); - IWL_CMD(REPLY_REMOVE_ALL_STA); - IWL_CMD(REPLY_WEPKEY); - IWL_CMD(REPLY_3945_RX); - IWL_CMD(REPLY_TX); - IWL_CMD(REPLY_RATE_SCALE); - IWL_CMD(REPLY_LEDS_CMD); - IWL_CMD(REPLY_TX_LINK_QUALITY_CMD); - IWL_CMD(COEX_PRIORITY_TABLE_CMD); - IWL_CMD(RADAR_NOTIFICATION); - IWL_CMD(REPLY_QUIET_CMD); - IWL_CMD(REPLY_CHANNEL_SWITCH); - IWL_CMD(CHANNEL_SWITCH_NOTIFICATION); - IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD); - IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION); - IWL_CMD(POWER_TABLE_CMD); - IWL_CMD(PM_SLEEP_NOTIFICATION); - IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC); - IWL_CMD(REPLY_SCAN_CMD); - IWL_CMD(REPLY_SCAN_ABORT_CMD); - IWL_CMD(SCAN_START_NOTIFICATION); - IWL_CMD(SCAN_RESULTS_NOTIFICATION); - IWL_CMD(SCAN_COMPLETE_NOTIFICATION); - IWL_CMD(BEACON_NOTIFICATION); - IWL_CMD(REPLY_TX_BEACON); - IWL_CMD(WHO_IS_AWAKE_NOTIFICATION); - IWL_CMD(QUIET_NOTIFICATION); - IWL_CMD(REPLY_TX_PWR_TABLE_CMD); - IWL_CMD(MEASURE_ABORT_NOTIFICATION); - IWL_CMD(REPLY_BT_CONFIG); - IWL_CMD(REPLY_STATISTICS_CMD); - IWL_CMD(STATISTICS_NOTIFICATION); - IWL_CMD(REPLY_CARD_STATE_CMD); - IWL_CMD(CARD_STATE_NOTIFICATION); - IWL_CMD(MISSED_BEACONS_NOTIFICATION); - IWL_CMD(REPLY_CT_KILL_CONFIG_CMD); - IWL_CMD(SENSITIVITY_CMD); - IWL_CMD(REPLY_PHY_CALIBRATION_CMD); - IWL_CMD(REPLY_RX_PHY_CMD); - IWL_CMD(REPLY_RX_MPDU_CMD); - IWL_CMD(REPLY_RX); - IWL_CMD(REPLY_COMPRESSED_BA); - IWL_CMD(CALIBRATION_CFG_CMD); - IWL_CMD(CALIBRATION_RES_NOTIFICATION); - IWL_CMD(CALIBRATION_COMPLETE_NOTIFICATION); - IWL_CMD(REPLY_TX_POWER_DBM_CMD); - default: - return "UNKNOWN"; - - } -} -EXPORT_SYMBOL(get_cmd_string); - -#define HOST_COMPLETE_TIMEOUT (HZ / 2) - -static void iwl_generic_cmd_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb) -{ - struct iwl_rx_packet *pkt = NULL; - - if (!skb) { - IWL_ERR(priv, "Error: Response NULL in %s.\n", - get_cmd_string(cmd->hdr.cmd)); - return; - } - - pkt = (struct iwl_rx_packet *)skb->data; - if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - switch (cmd->hdr.cmd) { - case REPLY_TX_LINK_QUALITY_CMD: - case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); - break; - default: - IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n", - get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags); - } -#endif -} - -static int iwl_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - int ret; - - BUG_ON(!(cmd->flags & CMD_ASYNC)); - - /* An asynchronous command can not expect an SKB to be set. */ - BUG_ON(cmd->flags & CMD_WANT_SKB); - - /* Assign a generic callback if one is not provided */ - if (!cmd->callback) - cmd->callback = iwl_generic_cmd_callback; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return -EBUSY; - - ret = iwl_enqueue_hcmd(priv, cmd); - if (ret < 0) { - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - return ret; - } - return 0; -} - -int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - int cmd_idx; - int ret; - - BUG_ON(cmd->flags & CMD_ASYNC); - - /* A synchronous command can not have a callback set. */ - BUG_ON(cmd->callback); - - if (test_and_set_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status)) { - IWL_ERR(priv, - "Error sending %s: Already sending a host command\n", - get_cmd_string(cmd->id)); - ret = -EBUSY; - goto out; - } - - set_bit(STATUS_HCMD_ACTIVE, &priv->status); - - cmd_idx = iwl_enqueue_hcmd(priv, cmd); - if (cmd_idx < 0) { - ret = cmd_idx; - IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n", - get_cmd_string(cmd->id), ret); - goto out; - } - - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - !test_bit(STATUS_HCMD_ACTIVE, &priv->status), - HOST_COMPLETE_TIMEOUT); - if (!ret) { - if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) { - IWL_ERR(priv, - "Error sending %s: time out after %dms.\n", - get_cmd_string(cmd->id), - jiffies_to_msecs(HOST_COMPLETE_TIMEOUT)); - - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - ret = -ETIMEDOUT; - goto cancel; - } - } - - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) { - IWL_DEBUG_INFO(priv, "Command %s aborted: RF KILL Switch\n", - get_cmd_string(cmd->id)); - ret = -ECANCELED; - goto fail; - } - if (test_bit(STATUS_FW_ERROR, &priv->status)) { - IWL_DEBUG_INFO(priv, "Command %s failed: FW Error\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto fail; - } - if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) { - IWL_ERR(priv, "Error: Response NULL in '%s'\n", - get_cmd_string(cmd->id)); - ret = -EIO; - goto cancel; - } - - ret = 0; - goto out; - -cancel: - if (cmd->flags & CMD_WANT_SKB) { - /* - * Cancel the CMD_WANT_SKB flag for the cmd in the - * TX cmd queue. Otherwise in case the cmd comes - * in later, it will possibly set an invalid - * address (cmd->meta.source). - */ - priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_idx].flags &= - ~CMD_WANT_SKB; - } -fail: - if (cmd->reply_skb) { - dev_kfree_skb_any(cmd->reply_skb); - cmd->reply_skb = NULL; - } -out: - clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status); - return ret; -} -EXPORT_SYMBOL(iwl_send_cmd_sync); - -int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - if (cmd->flags & CMD_ASYNC) - return iwl_send_cmd_async(priv, cmd); - - return iwl_send_cmd_sync(priv, cmd); -} -EXPORT_SYMBOL(iwl_send_cmd); - -int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data) -{ - struct iwl_host_cmd cmd = { - .id = id, - .len = len, - .data = data, - }; - - return iwl_send_cmd_sync(priv, &cmd); -} -EXPORT_SYMBOL(iwl_send_cmd_pdu); - -int iwl_send_cmd_pdu_async(struct iwl_priv *priv, - u8 id, u16 len, const void *data, - void (*callback)(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb)) -{ - struct iwl_host_cmd cmd = { - .id = id, - .len = len, - .data = data, - }; - - cmd.flags |= CMD_ASYNC; - cmd.callback = callback; - - return iwl_send_cmd_async(priv, &cmd); -} -EXPORT_SYMBOL(iwl_send_cmd_pdu_async); diff --git a/drivers/net/wireless/iwlwifi/iwl-helpers.h b/drivers/net/wireless/iwlwifi/iwl-helpers.h deleted file mode 100644 index f8481e8bf04a..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-helpers.h +++ /dev/null @@ -1,170 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_helpers_h__ -#define __iwl_helpers_h__ - -#include - -#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo)))) - - -static inline struct ieee80211_conf *ieee80211_get_hw_conf( - struct ieee80211_hw *hw) -{ - return &hw->conf; -} - -static inline int iwl_check_bits(unsigned long field, unsigned long mask) -{ - return ((field & mask) == mask) ? 1 : 0; -} - -static inline unsigned long elapsed_jiffies(unsigned long start, - unsigned long end) -{ - if (end >= start) - return end - start; - - return end + (MAX_JIFFY_OFFSET - start) + 1; -} - -/** - * iwl_queue_inc_wrap - increment queue index, wrap back to beginning - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl_queue_inc_wrap(int index, int n_bd) -{ - return ++index & (n_bd - 1); -} - -/** - * iwl_queue_dec_wrap - decrement queue index, wrap back to end - * @index -- current index - * @n_bd -- total number of entries in queue (must be power of 2) - */ -static inline int iwl_queue_dec_wrap(int index, int n_bd) -{ - return --index & (n_bd - 1); -} - -/* TODO: Move fw_desc functions to iwl-pci.ko */ -static inline void iwl_free_fw_desc(struct pci_dev *pci_dev, - struct fw_desc *desc) -{ - if (desc->v_addr) - dma_free_coherent(&pci_dev->dev, desc->len, - desc->v_addr, desc->p_addr); - desc->v_addr = NULL; - desc->len = 0; -} - -static inline int iwl_alloc_fw_desc(struct pci_dev *pci_dev, - struct fw_desc *desc) -{ - desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len, - &desc->p_addr, GFP_KERNEL); - return (desc->v_addr != NULL) ? 0 : -ENOMEM; -} - -/* - * we have 8 bits used like this: - * - * 7 6 5 4 3 2 1 0 - * | | | | | | | | - * | | | | | | +-+-------- AC queue (0-3) - * | | | | | | - * | +-+-+-+-+------------ HW A-MPDU queue - * | - * +---------------------- indicates agg queue - */ -static inline u8 iwl_virtual_agg_queue_num(u8 ac, u8 hwq) -{ - BUG_ON(ac > 3); /* only have 2 bits */ - BUG_ON(hwq > 31); /* only have 5 bits */ - - return 0x80 | (hwq << 2) | ac; -} - -static inline void iwl_wake_queue(struct iwl_priv *priv, u8 queue) -{ - u8 ac = queue; - u8 hwq = queue; - - if (queue & 0x80) { - ac = queue & 3; - hwq = (queue >> 2) & 0x1f; - } - - if (test_and_clear_bit(hwq, priv->queue_stopped)) - if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0) - ieee80211_wake_queue(priv->hw, ac); -} - -static inline void iwl_stop_queue(struct iwl_priv *priv, u8 queue) -{ - u8 ac = queue; - u8 hwq = queue; - - if (queue & 0x80) { - ac = queue & 3; - hwq = (queue >> 2) & 0x1f; - } - - if (!test_and_set_bit(hwq, priv->queue_stopped)) - if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0) - ieee80211_stop_queue(priv->hw, ac); -} - -#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue -#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue - -static inline void iwl_disable_interrupts(struct iwl_priv *priv) -{ - clear_bit(STATUS_INT_ENABLED, &priv->status); - - /* disable interrupts from uCode/NIC to host */ - iwl_write32(priv, CSR_INT_MASK, 0x00000000); - - /* acknowledge/clear/reset any interrupts still pending - * from uCode or flow handler (Rx/Tx DMA) */ - iwl_write32(priv, CSR_INT, 0xffffffff); - iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff); - IWL_DEBUG_ISR(priv, "Disabled interrupts\n"); -} - -static inline void iwl_enable_interrupts(struct iwl_priv *priv) -{ - IWL_DEBUG_ISR(priv, "Enabling interrupts\n"); - set_bit(STATUS_INT_ENABLED, &priv->status); - iwl_write32(priv, CSR_INT_MASK, priv->inta_mask); -} - -#endif /* __iwl_helpers_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h deleted file mode 100644 index d30cb0275d19..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ /dev/null @@ -1,475 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_io_h__ -#define __iwl_io_h__ - -#include - -#include "iwl-debug.h" - -/* - * IO, register, and NIC memory access functions - * - * NOTE on naming convention and macro usage for these - * - * A single _ prefix before a an access function means that no state - * check or debug information is printed when that function is called. - * - * A double __ prefix before an access function means that state is checked - * and the current line number and caller function name are printed in addition - * to any other debug output. - * - * The non-prefixed name is the #define that maps the caller into a - * #define that provides the caller's name and __LINE__ to the double - * prefix version. - * - * If you wish to call the function without any debug or state checking, - * you should use the single _ prefix version (as is used by dependent IO - * routines, for example _iwl_read_direct32 calls the non-check version of - * _iwl_read32.) - * - * These declarations are *extremely* useful in quickly isolating code deltas - * which result in misconfiguration of the hardware I/O. In combination with - * git-bisect and the IO debug level you can quickly determine the specific - * commit which breaks the IO sequence to the hardware. - * - */ - -#define _iwl_write32(priv, ofs, val) iowrite32((val), (priv)->hw_base + (ofs)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_write32(const char *f, u32 l, struct iwl_priv *priv, - u32 ofs, u32 val) -{ - IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l); - _iwl_write32(priv, ofs, val); -} -#define iwl_write32(priv, ofs, val) \ - __iwl_write32(__FILE__, __LINE__, priv, ofs, val) -#else -#define iwl_write32(priv, ofs, val) _iwl_write32(priv, ofs, val) -#endif - -#define _iwl_read32(priv, ofs) ioread32((priv)->hw_base + (ofs)) -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) -{ - IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l); - return _iwl_read32(priv, ofs); -} -#define iwl_read32(priv, ofs) __iwl_read32(__FILE__, __LINE__, priv, ofs) -#else -#define iwl_read32(p, o) _iwl_read32(p, o) -#endif - -#define IWL_POLL_INTERVAL 10 /* microseconds */ -static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int t = 0; - - do { - if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl_poll_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 addr, - u32 bits, u32 mask, int timeout) -{ - int ret = _iwl_poll_bit(priv, addr, bits, mask, timeout); - IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n", - addr, bits, mask, - unlikely(ret == -ETIMEDOUT) ? "timeout" : "", f, l); - return ret; -} -#define iwl_poll_bit(priv, addr, bits, mask, timeout) \ - __iwl_poll_bit(__FILE__, __LINE__, priv, addr, bits, mask, timeout) -#else -#define iwl_poll_bit(p, a, b, m, t) _iwl_poll_bit(p, a, b, m, t) -#endif - -static inline void _iwl_set_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl_write32(priv, reg, _iwl_read32(priv, reg) | mask); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_set_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl_read32(priv, reg) | mask; - IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl_write32(priv, reg, val); -} -static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - __iwl_set_bit(__FILE__, __LINE__, p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#else -static inline void iwl_set_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - _iwl_set_bit(p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#endif - -static inline void _iwl_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask) -{ - _iwl_write32(priv, reg, _iwl_read32(priv, reg) & ~mask); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_clear_bit(const char *f, u32 l, - struct iwl_priv *priv, u32 reg, u32 mask) -{ - u32 val = _iwl_read32(priv, reg) & ~mask; - IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val); - _iwl_write32(priv, reg, val); -} -static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - __iwl_clear_bit(__FILE__, __LINE__, p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#else -static inline void iwl_clear_bit(struct iwl_priv *p, u32 r, u32 m) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&p->reg_lock, reg_flags); - _iwl_clear_bit(p, r, m); - spin_unlock_irqrestore(&p->reg_lock, reg_flags); -} -#endif - -static inline int _iwl_grab_nic_access(struct iwl_priv *priv) -{ - int ret; - u32 val; - - /* this bit wakes up the NIC */ - _iwl_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - ret = _iwl_poll_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN, - (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY | - CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000); - if (ret < 0) { - val = _iwl_read32(priv, CSR_GP_CNTRL); - IWL_ERR(priv, "MAC is in deep sleep!. CSR_GP_CNTRL = 0x%08X\n", val); - _iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_FORCE_NMI); - return -EIO; - } - - return 0; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl_grab_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l); - return _iwl_grab_nic_access(priv); -} -#define iwl_grab_nic_access(priv) \ - __iwl_grab_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl_grab_nic_access(priv) \ - _iwl_grab_nic_access(priv) -#endif - -static inline void _iwl_release_nic_access(struct iwl_priv *priv) -{ - _iwl_clear_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline void __iwl_release_nic_access(const char *f, u32 l, - struct iwl_priv *priv) -{ - - IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l); - _iwl_release_nic_access(priv); -} -#define iwl_release_nic_access(priv) \ - __iwl_release_nic_access(__FILE__, __LINE__, priv) -#else -#define iwl_release_nic_access(priv) \ - _iwl_release_nic_access(priv) -#endif - -static inline u32 _iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - return _iwl_read32(priv, reg); -} -#ifdef CONFIG_IWLWIFI_DEBUG -static inline u32 __iwl_read_direct32(const char *f, u32 l, - struct iwl_priv *priv, u32 reg) -{ - u32 value = _iwl_read_direct32(priv, reg); - IWL_DEBUG_IO(priv, "read_direct32(0x%4X) = 0x%08x - %s %d \n", reg, value, - f, l); - return value; -} -static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - u32 value; - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - value = __iwl_read_direct32(__FILE__, __LINE__, priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return value; -} - -#else -static inline u32 iwl_read_direct32(struct iwl_priv *priv, u32 reg) -{ - u32 value; - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - value = _iwl_read_direct32(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return value; - -} -#endif - -static inline void _iwl_write_direct32(struct iwl_priv *priv, - u32 reg, u32 value) -{ - _iwl_write32(priv, reg, value); -} -static inline void iwl_write_direct32(struct iwl_priv *priv, u32 reg, u32 value) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_direct32(priv, reg, value); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline void iwl_write_reg_buf(struct iwl_priv *priv, - u32 reg, u32 len, u32 *values) -{ - u32 count = sizeof(u32); - - if ((priv != NULL) && (values != NULL)) { - for (; 0 < len; len -= count, reg += count, values++) - iwl_write_direct32(priv, reg, *values); - } -} - -static inline int _iwl_poll_direct_bit(struct iwl_priv *priv, u32 addr, - u32 mask, int timeout) -{ - int t = 0; - - do { - if ((iwl_read_direct32(priv, addr) & mask) == mask) - return t; - udelay(IWL_POLL_INTERVAL); - t += IWL_POLL_INTERVAL; - } while (t < timeout); - - return -ETIMEDOUT; -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static inline int __iwl_poll_direct_bit(const char *f, u32 l, - struct iwl_priv *priv, - u32 addr, u32 mask, int timeout) -{ - int ret = _iwl_poll_direct_bit(priv, addr, mask, timeout); - - if (unlikely(ret == -ETIMEDOUT)) - IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - " - "timedout - %s %d\n", addr, mask, f, l); - else - IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X " - "- %s %d\n", addr, mask, ret, f, l); - return ret; -} -#define iwl_poll_direct_bit(priv, addr, mask, timeout) \ - __iwl_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout) -#else -#define iwl_poll_direct_bit _iwl_poll_direct_bit -#endif - -static inline u32 _iwl_read_prph(struct iwl_priv *priv, u32 reg) -{ - _iwl_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24)); - rmb(); - return _iwl_read_direct32(priv, HBUS_TARG_PRPH_RDAT); -} -static inline u32 iwl_read_prph(struct iwl_priv *priv, u32 reg) -{ - unsigned long reg_flags; - u32 val; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - val = _iwl_read_prph(priv, reg); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return val; -} - -static inline void _iwl_write_prph(struct iwl_priv *priv, - u32 addr, u32 val) -{ - _iwl_write_direct32(priv, HBUS_TARG_PRPH_WADDR, - ((addr & 0x0000FFFF) | (3 << 24))); - wmb(); - _iwl_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val); -} - -static inline void iwl_write_prph(struct iwl_priv *priv, u32 addr, u32 val) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_prph(priv, addr, val); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -#define _iwl_set_bits_prph(priv, reg, mask) \ - _iwl_write_prph(priv, reg, (_iwl_read_prph(priv, reg) | mask)) - -static inline void iwl_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - _iwl_set_bits_prph(priv, reg, mask); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -#define _iwl_set_bits_mask_prph(priv, reg, bits, mask) \ - _iwl_write_prph(priv, reg, ((_iwl_read_prph(priv, reg) & mask) | bits)) - -static inline void iwl_set_bits_mask_prph(struct iwl_priv *priv, u32 reg, - u32 bits, u32 mask) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - _iwl_set_bits_mask_prph(priv, reg, bits, mask); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline void iwl_clear_bits_prph(struct iwl_priv - *priv, u32 reg, u32 mask) -{ - unsigned long reg_flags; - u32 val; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - val = _iwl_read_prph(priv, reg); - _iwl_write_prph(priv, reg, (val & ~mask)); - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline u32 iwl_read_targ_mem(struct iwl_priv *priv, u32 addr) -{ - unsigned long reg_flags; - u32 value; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - iwl_grab_nic_access(priv); - - _iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr); - rmb(); - value = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); - return value; -} - -static inline void iwl_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, val); - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} - -static inline void iwl_write_targ_mem_buf(struct iwl_priv *priv, u32 addr, - u32 len, u32 *values) -{ - unsigned long reg_flags; - - spin_lock_irqsave(&priv->reg_lock, reg_flags); - if (!iwl_grab_nic_access(priv)) { - _iwl_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr); - wmb(); - for (; 0 < len; len -= sizeof(u32), values++) - _iwl_write_direct32(priv, HBUS_TARG_MEM_WDAT, *values); - - iwl_release_nic_access(priv); - } - spin_unlock_irqrestore(&priv->reg_lock, reg_flags); -} -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c deleted file mode 100644 index f420c99e7240..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ /dev/null @@ -1,441 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" - -#ifdef CONFIG_IWLWIFI_DEBUG -static const char *led_type_str[] = { - __stringify(IWL_LED_TRG_TX), - __stringify(IWL_LED_TRG_RX), - __stringify(IWL_LED_TRG_ASSOC), - __stringify(IWL_LED_TRG_RADIO), - NULL -}; -#endif /* CONFIG_IWLWIFI_DEBUG */ - - -static const struct { - u16 tpt; /* Mb/s */ - u8 on_time; - u8 off_time; -} blink_tbl[] = -{ - {300, 25, 25}, - {200, 40, 40}, - {100, 55, 55}, - {70, 65, 65}, - {50, 75, 75}, - {20, 85, 85}, - {15, 95, 95 }, - {10, 110, 110}, - {5, 130, 130}, - {0, 167, 167}, -/* SOLID_ON */ - {-1, IWL_LED_SOLID, 0} -}; - -#define IWL_1MB_RATE (128 * 1024) -#define IWL_LED_THRESHOLD (16) -#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */ -#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1) - -/* [0-256] -> [0..8] FIXME: we need [0..10] */ -static inline int iwl_brightness_to_idx(enum led_brightness brightness) -{ - return fls(0x000000FF & (u32)brightness); -} - -/* Send led command */ -static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_LEDS_CMD, - .len = sizeof(struct iwl_led_cmd), - .data = led_cmd, - .flags = CMD_ASYNC, - .callback = NULL, - }; - u32 reg; - - reg = iwl_read32(priv, CSR_LED_REG); - if (reg != (reg & CSR_LED_BSM_CTRL_MSK)) - iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK); - - return iwl_send_cmd(priv, &cmd); -} - -/* Set led pattern command */ -static int iwl_led_pattern(struct iwl_priv *priv, int led_id, - unsigned int idx) -{ - struct iwl_led_cmd led_cmd = { - .id = led_id, - .interval = IWL_DEF_LED_INTRVL - }; - - BUG_ON(idx > IWL_MAX_BLINK_TBL); - - led_cmd.on = blink_tbl[idx].on_time; - led_cmd.off = blink_tbl[idx].off_time; - - return iwl_send_led_cmd(priv, &led_cmd); -} - -/* Set led register off */ -static int iwl_led_on_reg(struct iwl_priv *priv, int led_id) -{ - IWL_DEBUG_LED(priv, "led on %d\n", led_id); - iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON); - return 0; -} - -#if 0 -/* Set led on command */ -static int iwl_led_on(struct iwl_priv *priv, int led_id) -{ - struct iwl_led_cmd led_cmd = { - .id = led_id, - .on = IWL_LED_SOLID, - .off = 0, - .interval = IWL_DEF_LED_INTRVL - }; - return iwl_send_led_cmd(priv, &led_cmd); -} - -/* Set led off command */ -int iwl_led_off(struct iwl_priv *priv, int led_id) -{ - struct iwl_led_cmd led_cmd = { - .id = led_id, - .on = 0, - .off = 0, - .interval = IWL_DEF_LED_INTRVL - }; - IWL_DEBUG_LED(priv, "led off %d\n", led_id); - return iwl_send_led_cmd(priv, &led_cmd); -} -#endif - - -/* Set led register off */ -static int iwl_led_off_reg(struct iwl_priv *priv, int led_id) -{ - IWL_DEBUG_LED(priv, "LED Reg off\n"); - iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF); - return 0; -} - -/* - * Set led register in case of disassociation according to rfkill state - */ -static int iwl_led_associate(struct iwl_priv *priv, int led_id) -{ - IWL_DEBUG_LED(priv, "Associated\n"); - priv->allow_blinking = 1; - return iwl_led_on_reg(priv, led_id); -} -static int iwl_led_disassociate(struct iwl_priv *priv, int led_id) -{ - priv->allow_blinking = 0; - - return 0; -} - -/* - * brightness call back function for Tx/Rx LED - */ -static int iwl_led_associated(struct iwl_priv *priv, int led_id) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status) || - !test_bit(STATUS_READY, &priv->status)) - return 0; - - - /* start counting Tx/Rx bytes */ - if (!priv->last_blink_time && priv->allow_blinking) - priv->last_blink_time = jiffies; - return 0; -} - -/* - * brightness call back for association and radio - */ -static void iwl_led_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev); - struct iwl_priv *priv = led->priv; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - - IWL_DEBUG_LED(priv, "Led type = %s brightness = %d\n", - led_type_str[led->type], brightness); - switch (brightness) { - case LED_FULL: - if (led->led_on) - led->led_on(priv, IWL_LED_LINK); - break; - case LED_OFF: - if (led->led_off) - led->led_off(priv, IWL_LED_LINK); - break; - default: - if (led->led_pattern) { - int idx = iwl_brightness_to_idx(brightness); - led->led_pattern(priv, IWL_LED_LINK, idx); - } - break; - } -} - - - -/* - * Register led class with the system - */ -static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led, - enum led_type type, u8 set_led, - char *trigger) -{ - struct device *device = wiphy_dev(priv->hw->wiphy); - int ret; - - led->led_dev.name = led->name; - led->led_dev.brightness_set = iwl_led_brightness_set; - led->led_dev.default_trigger = trigger; - - led->priv = priv; - led->type = type; - - ret = led_classdev_register(device, &led->led_dev); - if (ret) { - IWL_ERR(priv, "Error: failed to register led handler.\n"); - return ret; - } - - led->registered = 1; - - if (set_led && led->led_on) - led->led_on(priv, IWL_LED_LINK); - - return 0; -} - - -/* - * calculate blink rate according to last second Tx/Rx activities - */ -static int iwl_get_blink_rate(struct iwl_priv *priv) -{ - int i; - /* count both tx and rx traffic to be able to - * handle traffic in either direction - */ - u64 current_tpt = priv->tx_stats.data_bytes + - priv->rx_stats.data_bytes; - s64 tpt = current_tpt - priv->led_tpt; - - if (tpt < 0) /* wraparound */ - tpt = -tpt; - - IWL_DEBUG_LED(priv, "tpt %lld current_tpt %llu\n", - (long long)tpt, - (unsigned long long)current_tpt); - priv->led_tpt = current_tpt; - - if (!priv->allow_blinking) - i = IWL_MAX_BLINK_TBL; - else - for (i = 0; i < IWL_MAX_BLINK_TBL; i++) - if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) - break; - - IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i); - return i; -} - -/* - * this function called from handler. Since setting Led command can - * happen very frequent we postpone led command to be called from - * REPLY handler so we know ucode is up - */ -void iwl_leds_background(struct iwl_priv *priv) -{ - u8 blink_idx; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - priv->last_blink_time = 0; - return; - } - if (iwl_is_rfkill(priv)) { - priv->last_blink_time = 0; - return; - } - - if (!priv->allow_blinking) { - priv->last_blink_time = 0; - if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) { - priv->last_blink_rate = IWL_SOLID_BLINK_IDX; - iwl_led_pattern(priv, IWL_LED_LINK, - IWL_SOLID_BLINK_IDX); - } - return; - } - if (!priv->last_blink_time || - !time_after(jiffies, priv->last_blink_time + - msecs_to_jiffies(1000))) - return; - - blink_idx = iwl_get_blink_rate(priv); - - /* call only if blink rate change */ - if (blink_idx != priv->last_blink_rate) - iwl_led_pattern(priv, IWL_LED_LINK, blink_idx); - - priv->last_blink_time = jiffies; - priv->last_blink_rate = blink_idx; -} - -/* Register all led handler */ -int iwl_leds_register(struct iwl_priv *priv) -{ - char *trigger; - int ret; - - priv->last_blink_rate = 0; - priv->led_tpt = 0; - priv->last_blink_time = 0; - priv->allow_blinking = 0; - - trigger = ieee80211_get_radio_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_RADIO].name, - sizeof(priv->led[IWL_LED_TRG_RADIO].name), "iwl-%s::radio", - wiphy_name(priv->hw->wiphy)); - - priv->led[IWL_LED_TRG_RADIO].led_on = iwl_led_on_reg; - priv->led[IWL_LED_TRG_RADIO].led_off = iwl_led_off_reg; - priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL; - - ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO], - IWL_LED_TRG_RADIO, 1, trigger); - if (ret) - goto exit_fail; - - trigger = ieee80211_get_assoc_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_ASSOC].name, - sizeof(priv->led[IWL_LED_TRG_ASSOC].name), "iwl-%s::assoc", - wiphy_name(priv->hw->wiphy)); - - ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC], - IWL_LED_TRG_ASSOC, 0, trigger); - - /* for assoc always turn led on */ - priv->led[IWL_LED_TRG_ASSOC].led_on = iwl_led_associate; - priv->led[IWL_LED_TRG_ASSOC].led_off = iwl_led_disassociate; - priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL; - - if (ret) - goto exit_fail; - - trigger = ieee80211_get_rx_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_RX].name, - sizeof(priv->led[IWL_LED_TRG_RX].name), "iwl-%s::RX", - wiphy_name(priv->hw->wiphy)); - - ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX], - IWL_LED_TRG_RX, 0, trigger); - - priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated; - priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated; - priv->led[IWL_LED_TRG_RX].led_pattern = iwl_led_pattern; - - if (ret) - goto exit_fail; - - trigger = ieee80211_get_tx_led_name(priv->hw); - snprintf(priv->led[IWL_LED_TRG_TX].name, - sizeof(priv->led[IWL_LED_TRG_TX].name), "iwl-%s::TX", - wiphy_name(priv->hw->wiphy)); - - ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX], - IWL_LED_TRG_TX, 0, trigger); - - priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated; - priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated; - priv->led[IWL_LED_TRG_TX].led_pattern = iwl_led_pattern; - - if (ret) - goto exit_fail; - - return 0; - -exit_fail: - iwl_leds_unregister(priv); - return ret; -} -EXPORT_SYMBOL(iwl_leds_register); - -/* unregister led class */ -static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led) -{ - if (!led->registered) - return; - - led_classdev_unregister(&led->led_dev); - - if (set_led) - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - led->registered = 0; -} - -/* Unregister all led handlers */ -void iwl_leds_unregister(struct iwl_priv *priv) -{ - iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_ASSOC], 0); - iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RX], 0); - iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_TX], 0); - iwl_leds_unregister_led(&priv->led[IWL_LED_TRG_RADIO], 1); -} -EXPORT_SYMBOL(iwl_leds_unregister); - diff --git a/drivers/net/wireless/iwlwifi/iwl-led.h b/drivers/net/wireless/iwlwifi/iwl-led.h deleted file mode 100644 index ef9b174c37ff..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-led.h +++ /dev/null @@ -1,84 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_leds_h__ -#define __iwl_leds_h__ - - -struct iwl_priv; - -#ifdef CONFIG_IWLWIFI_LEDS -#include - -#define IWL_LED_SOLID 11 -#define IWL_LED_NAME_LEN 31 -#define IWL_DEF_LED_INTRVL cpu_to_le32(1000) - -#define IWL_LED_ACTIVITY (0<<1) -#define IWL_LED_LINK (1<<1) - -enum led_type { - IWL_LED_TRG_TX, - IWL_LED_TRG_RX, - IWL_LED_TRG_ASSOC, - IWL_LED_TRG_RADIO, - IWL_LED_TRG_MAX, -}; -#endif - -#ifdef CONFIG_IWLWIFI_LEDS - -struct iwl_led { - struct iwl_priv *priv; - struct led_classdev led_dev; - char name[32]; - - int (*led_on) (struct iwl_priv *priv, int led_id); - int (*led_off) (struct iwl_priv *priv, int led_id); - int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx); - - enum led_type type; - unsigned int registered; -}; - -int iwl_leds_register(struct iwl_priv *priv); -void iwl_leds_unregister(struct iwl_priv *priv); -void iwl_leds_background(struct iwl_priv *priv); - -#else -static inline int iwl_leds_register(struct iwl_priv *priv) -{ - return 0; -} -static inline void iwl_leds_unregister(struct iwl_priv *priv) -{ -} -static inline void iwl_leds_background(struct iwl_priv *priv) -{ -} - -#endif /* CONFIG_IWLWIFI_LEDS */ -#endif /* __iwl_leds_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c deleted file mode 100644 index 60be976afff8..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-power.c +++ /dev/null @@ -1,855 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ - - -#include -#include -#include - -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-commands.h" -#include "iwl-debug.h" -#include "iwl-power.h" - -/* - * Setting power level allows the card to go to sleep when not busy. - * - * We calculate a sleep command based on the required latency, which - * we get from mac80211. In order to handle thermal throttling, we can - * also use pre-defined power levels. - */ - -/* - * For now, keep using power level 1 instead of automatically - * adjusting ... - */ -bool no_sleep_autoadjust = true; -module_param(no_sleep_autoadjust, bool, S_IRUGO); -MODULE_PARM_DESC(no_sleep_autoadjust, - "don't automatically adjust sleep level " - "according to maximum network latency"); - -/* - * This defines the old power levels. They are still used by default - * (level 1) and for thermal throttle (levels 3 through 5) - */ - -struct iwl_power_vec_entry { - struct iwl_powertable_cmd cmd; - u8 no_dtim; -}; - -#define IWL_DTIM_RANGE_0_MAX 2 -#define IWL_DTIM_RANGE_1_MAX 10 - -#define NOSLP cpu_to_le16(0), 0, 0 -#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 -#define TU_TO_USEC 1024 -#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) -#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ - cpu_to_le32(X1), \ - cpu_to_le32(X2), \ - cpu_to_le32(X3), \ - cpu_to_le32(X4)} -/* default power management (not Tx power) table values */ -/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */ -static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { - {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1}, - {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2} -}; - - -/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */ -static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { - {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1}, - {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} -}; - -/* for DTIM period > IWL_DTIM_RANGE_1_MAX */ -static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { - {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, - {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, - {{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, - {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} -}; - -static void iwl_static_sleep_cmd(struct iwl_priv *priv, - struct iwl_powertable_cmd *cmd, - enum iwl_power_level lvl, int period) -{ - const struct iwl_power_vec_entry *table; - int max_sleep, i; - bool skip; - - table = range_2; - if (period < IWL_DTIM_RANGE_1_MAX) - table = range_1; - if (period < IWL_DTIM_RANGE_0_MAX) - table = range_0; - - BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); - - *cmd = table[lvl].cmd; - - if (period == 0) { - skip = false; - period = 1; - } else { - skip = !!table[lvl].no_dtim; - } - - if (skip) { - __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]; - max_sleep = le32_to_cpu(slp_itrvl); - if (max_sleep == 0xFF) - max_sleep = period * (skip + 1); - else if (max_sleep > period) - max_sleep = (le32_to_cpu(slp_itrvl) / period) * period; - cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK; - } else { - max_sleep = period; - cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK; - } - - for (i = 0; i < IWL_POWER_VEC_SIZE; i++) - if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) - cmd->sleep_interval[i] = cpu_to_le32(max_sleep); - - if (priv->power_data.pci_pm) - cmd->flags |= IWL_POWER_PCI_PM_MSK; - else - cmd->flags &= ~IWL_POWER_PCI_PM_MSK; - - IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1); -} - -/* default Thermal Throttling transaction table - * Current state | Throttling Down | Throttling Up - *============================================================================= - * Condition Nxt State Condition Nxt State Condition Nxt State - *----------------------------------------------------------------------------- - * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A - * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 - * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 - * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 - *============================================================================= - */ -static const struct iwl_tt_trans tt_range_0[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_0, IWL_ABSOLUTE_ZERO, 104}, - {IWL_TI_1, 105, CT_KILL_THRESHOLD}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} -}; -static const struct iwl_tt_trans tt_range_1[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_0, IWL_ABSOLUTE_ZERO, 95}, - {IWL_TI_2, 110, CT_KILL_THRESHOLD}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} -}; -static const struct iwl_tt_trans tt_range_2[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_1, IWL_ABSOLUTE_ZERO, 100}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, - {IWL_TI_CT_KILL, CT_KILL_THRESHOLD + 1, IWL_ABSOLUTE_MAX} -}; -static const struct iwl_tt_trans tt_range_3[IWL_TI_STATE_MAX - 1] = { - {IWL_TI_0, IWL_ABSOLUTE_ZERO, CT_KILL_EXIT_THRESHOLD}, - {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX}, - {IWL_TI_CT_KILL, CT_KILL_EXIT_THRESHOLD + 1, IWL_ABSOLUTE_MAX} -}; - -/* Advance Thermal Throttling default restriction table */ -static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = { - {IWL_ANT_OK_MULTI, IWL_ANT_OK_MULTI, true }, - {IWL_ANT_OK_SINGLE, IWL_ANT_OK_MULTI, true }, - {IWL_ANT_OK_SINGLE, IWL_ANT_OK_SINGLE, false }, - {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } -}; - - -static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv, - struct iwl_powertable_cmd *cmd) -{ - memset(cmd, 0, sizeof(*cmd)); - - if (priv->power_data.pci_pm) - cmd->flags |= IWL_POWER_PCI_PM_MSK; - - IWL_DEBUG_POWER(priv, "Sleep command for CAM\n"); -} - -static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv, - struct iwl_powertable_cmd *cmd, - int dynps_ms, int wakeup_period) -{ - /* - * These are the original power level 3 sleep successions. The - * device may behave better with such succession and was also - * only tested with that. Just like the original sleep commands, - * also adjust the succession here to the wakeup_period below. - * The ranges are the same as for the sleep commands, 0-2, 3-9 - * and >10, which is selected based on the DTIM interval for - * the sleep index but here we use the wakeup period since that - * is what we need to do for the latency requirements. - */ - static const u8 slp_succ_r0[IWL_POWER_VEC_SIZE] = { 2, 2, 2, 2, 2 }; - static const u8 slp_succ_r1[IWL_POWER_VEC_SIZE] = { 2, 4, 6, 7, 9 }; - static const u8 slp_succ_r2[IWL_POWER_VEC_SIZE] = { 2, 7, 9, 9, 0xFF }; - const u8 *slp_succ = slp_succ_r0; - int i; - - if (wakeup_period > IWL_DTIM_RANGE_0_MAX) - slp_succ = slp_succ_r1; - if (wakeup_period > IWL_DTIM_RANGE_1_MAX) - slp_succ = slp_succ_r2; - - memset(cmd, 0, sizeof(*cmd)); - - cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK | - IWL_POWER_FAST_PD; /* no use seeing frames for others */ - - if (priv->power_data.pci_pm) - cmd->flags |= IWL_POWER_PCI_PM_MSK; - - cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms); - cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms); - - for (i = 0; i < IWL_POWER_VEC_SIZE; i++) - cmd->sleep_interval[i] = - cpu_to_le32(min_t(int, slp_succ[i], wakeup_period)); - - IWL_DEBUG_POWER(priv, "Automatic sleep command\n"); -} - -static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd) -{ - IWL_DEBUG_POWER(priv, "Sending power/sleep command\n"); - IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); - IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); - IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); - IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n", - le32_to_cpu(cmd->sleep_interval[0]), - le32_to_cpu(cmd->sleep_interval[1]), - le32_to_cpu(cmd->sleep_interval[2]), - le32_to_cpu(cmd->sleep_interval[3]), - le32_to_cpu(cmd->sleep_interval[4])); - - return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD, - sizeof(struct iwl_powertable_cmd), cmd); -} - - -int iwl_power_update_mode(struct iwl_priv *priv, bool force) -{ - int ret = 0; - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) && - (priv->hw->conf.flags & IEEE80211_CONF_PS); - bool update_chains; - struct iwl_powertable_cmd cmd; - int dtimper; - - /* Don't update the RX chain when chain noise calibration is running */ - update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || - priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; - - if (priv->vif) - dtimper = priv->vif->bss_conf.dtim_period; - else - dtimper = 1; - - if (priv->cfg->broken_powersave) - iwl_power_sleep_cam_cmd(priv, &cmd); - else if (tt->state >= IWL_TI_1) - iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper); - else if (!enabled) - iwl_power_sleep_cam_cmd(priv, &cmd); - else if (priv->power_data.debug_sleep_level_override >= 0) - iwl_static_sleep_cmd(priv, &cmd, - priv->power_data.debug_sleep_level_override, - dtimper); - else if (no_sleep_autoadjust) - iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper); - else - iwl_power_fill_sleep_cmd(priv, &cmd, - priv->hw->conf.dynamic_ps_timeout, - priv->hw->conf.max_sleep_period); - - if (iwl_is_ready_rf(priv) && - (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) { - if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK) - set_bit(STATUS_POWER_PMI, &priv->status); - - ret = iwl_set_power(priv, &cmd); - if (!ret) { - if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)) - clear_bit(STATUS_POWER_PMI, &priv->status); - - if (priv->cfg->ops->lib->update_chain_flags && - update_chains) - priv->cfg->ops->lib->update_chain_flags(priv); - else if (priv->cfg->ops->lib->update_chain_flags) - IWL_DEBUG_POWER(priv, - "Cannot update the power, chain noise " - "calibration running: %d\n", - priv->chain_noise_data.state); - memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)); - } else - IWL_ERR(priv, "set power fail, ret = %d", ret); - } - - return ret; -} -EXPORT_SYMBOL(iwl_power_update_mode); - -bool iwl_ht_enabled(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - - if (!priv->thermal_throttle.advanced_tt) - return true; - restriction = tt->restriction + tt->state; - return restriction->is_ht; -} -EXPORT_SYMBOL(iwl_ht_enabled); - -enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - - if (!priv->thermal_throttle.advanced_tt) - return IWL_ANT_OK_MULTI; - restriction = tt->restriction + tt->state; - return restriction->tx_stream; -} -EXPORT_SYMBOL(iwl_tx_ant_restriction); - -enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - struct iwl_tt_restriction *restriction; - - if (!priv->thermal_throttle.advanced_tt) - return IWL_ANT_OK_MULTI; - restriction = tt->restriction + tt->state; - return restriction->rx_stream; -} - -#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ - -/* - * toggle the bit to wake up uCode and check the temperature - * if the temperature is below CT, uCode will stay awake and send card - * state notification with CT_KILL bit clear to inform Thermal Throttling - * Management to change state. Otherwise, uCode will go back to sleep - * without doing anything, driver should continue the 5 seconds timer - * to wake up uCode for temperature check until temperature drop below CT - */ -static void iwl_tt_check_exit_ct_kill(unsigned long data) -{ - struct iwl_priv *priv = (struct iwl_priv *)data; - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - unsigned long flags; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (tt->state == IWL_TI_CT_KILL) { - if (priv->thermal_throttle.ct_kill_toggle) { - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - priv->thermal_throttle.ct_kill_toggle = false; - } else { - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT); - priv->thermal_throttle.ct_kill_toggle = true; - } - iwl_read32(priv, CSR_UCODE_DRV_GP1); - spin_lock_irqsave(&priv->reg_lock, flags); - if (!iwl_grab_nic_access(priv)) - iwl_release_nic_access(priv); - spin_unlock_irqrestore(&priv->reg_lock, flags); - - /* Reschedule the ct_kill timer to occur in - * CT_KILL_EXIT_DURATION seconds to ensure we get a - * thermal update */ - mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + - CT_KILL_EXIT_DURATION * HZ); - } -} - -static void iwl_perform_ct_kill_task(struct iwl_priv *priv, - bool stop) -{ - if (stop) { - IWL_DEBUG_POWER(priv, "Stop all queues\n"); - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - IWL_DEBUG_POWER(priv, - "Schedule 5 seconds CT_KILL Timer\n"); - mod_timer(&priv->thermal_throttle.ct_kill_exit_tm, jiffies + - CT_KILL_EXIT_DURATION * HZ); - } else { - IWL_DEBUG_POWER(priv, "Wake all queues\n"); - if (priv->mac80211_registered) - ieee80211_wake_queues(priv->hw); - } -} - -#define IWL_MINIMAL_POWER_THRESHOLD (CT_KILL_THRESHOLD_LEGACY) -#define IWL_REDUCED_PERFORMANCE_THRESHOLD_2 (100) -#define IWL_REDUCED_PERFORMANCE_THRESHOLD_1 (90) - -/* - * Legacy thermal throttling - * 1) Avoid NIC destruction due to high temperatures - * Chip will identify dangerously high temperatures that can - * harm the device and will power down - * 2) Avoid the NIC power down due to high temperature - * Throttle early enough to lower the power consumption before - * drastic steps are needed - */ -static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - enum iwl_tt_state old_state; - -#ifdef CONFIG_IWLWIFI_DEBUG - if ((tt->tt_previous_temp) && - (temp > tt->tt_previous_temp) && - ((temp - tt->tt_previous_temp) > - IWL_TT_INCREASE_MARGIN)) { - IWL_DEBUG_POWER(priv, - "Temperature increase %d degree Celsius\n", - (temp - tt->tt_previous_temp)); - } -#endif - old_state = tt->state; - /* in Celsius */ - if (temp >= IWL_MINIMAL_POWER_THRESHOLD) - tt->state = IWL_TI_CT_KILL; - else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_2) - tt->state = IWL_TI_2; - else if (temp >= IWL_REDUCED_PERFORMANCE_THRESHOLD_1) - tt->state = IWL_TI_1; - else - tt->state = IWL_TI_0; - -#ifdef CONFIG_IWLWIFI_DEBUG - tt->tt_previous_temp = temp; -#endif - if (tt->state != old_state) { - switch (tt->state) { - case IWL_TI_0: - /* - * When the system is ready to go back to IWL_TI_0 - * we only have to call iwl_power_update_mode() to - * do so. - */ - break; - case IWL_TI_1: - tt->tt_power_mode = IWL_POWER_INDEX_3; - break; - case IWL_TI_2: - tt->tt_power_mode = IWL_POWER_INDEX_4; - break; - default: - tt->tt_power_mode = IWL_POWER_INDEX_5; - break; - } - mutex_lock(&priv->mutex); - if (iwl_power_update_mode(priv, true)) { - /* TT state not updated - * try again during next temperature read - */ - tt->state = old_state; - IWL_ERR(priv, "Cannot update power mode, " - "TT state not updated\n"); - } else { - if (tt->state == IWL_TI_CT_KILL) - iwl_perform_ct_kill_task(priv, true); - else if (old_state == IWL_TI_CT_KILL && - tt->state != IWL_TI_CT_KILL) - iwl_perform_ct_kill_task(priv, false); - IWL_DEBUG_POWER(priv, "Temperature state changed %u\n", - tt->state); - IWL_DEBUG_POWER(priv, "Power Index change to %u\n", - tt->tt_power_mode); - } - mutex_unlock(&priv->mutex); - } -} - -/* - * Advance thermal throttling - * 1) Avoid NIC destruction due to high temperatures - * Chip will identify dangerously high temperatures that can - * harm the device and will power down - * 2) Avoid the NIC power down due to high temperature - * Throttle early enough to lower the power consumption before - * drastic steps are needed - * Actions include relaxing the power down sleep thresholds and - * decreasing the number of TX streams - * 3) Avoid throughput performance impact as much as possible - * - *============================================================================= - * Condition Nxt State Condition Nxt State Condition Nxt State - *----------------------------------------------------------------------------- - * IWL_TI_0 T >= 115 CT_KILL 115>T>=105 TI_1 N/A N/A - * IWL_TI_1 T >= 115 CT_KILL 115>T>=110 TI_2 T<=95 TI_0 - * IWL_TI_2 T >= 115 CT_KILL T<=100 TI_1 - * IWL_CT_KILL N/A N/A N/A N/A T<=95 TI_0 - *============================================================================= - */ -static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - int i; - bool changed = false; - enum iwl_tt_state old_state; - struct iwl_tt_trans *transaction; - - old_state = tt->state; - for (i = 0; i < IWL_TI_STATE_MAX - 1; i++) { - /* based on the current TT state, - * find the curresponding transaction table - * each table has (IWL_TI_STATE_MAX - 1) entries - * tt->transaction + ((old_state * (IWL_TI_STATE_MAX - 1)) - * will advance to the correct table. - * then based on the current temperature - * find the next state need to transaction to - * go through all the possible (IWL_TI_STATE_MAX - 1) entries - * in the current table to see if transaction is needed - */ - transaction = tt->transaction + - ((old_state * (IWL_TI_STATE_MAX - 1)) + i); - if (temp >= transaction->tt_low && - temp <= transaction->tt_high) { -#ifdef CONFIG_IWLWIFI_DEBUG - if ((tt->tt_previous_temp) && - (temp > tt->tt_previous_temp) && - ((temp - tt->tt_previous_temp) > - IWL_TT_INCREASE_MARGIN)) { - IWL_DEBUG_POWER(priv, - "Temperature increase %d " - "degree Celsius\n", - (temp - tt->tt_previous_temp)); - } - tt->tt_previous_temp = temp; -#endif - if (old_state != - transaction->next_state) { - changed = true; - tt->state = - transaction->next_state; - } - break; - } - } - if (changed) { - struct iwl_rxon_cmd *rxon = &priv->staging_rxon; - - if (tt->state >= IWL_TI_1) { - /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ - tt->tt_power_mode = IWL_POWER_INDEX_5; - if (!iwl_ht_enabled(priv)) - /* disable HT */ - rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK | - RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK | - RXON_FLG_HT40_PROT_MSK | - RXON_FLG_HT_PROT_MSK); - else { - /* check HT capability and set - * according to the system HT capability - * in case get disabled before */ - iwl_set_rxon_ht(priv, &priv->current_ht_config); - } - - } else { - /* - * restore system power setting -- it will be - * recalculated automatically. - */ - - /* check HT capability and set - * according to the system HT capability - * in case get disabled before */ - iwl_set_rxon_ht(priv, &priv->current_ht_config); - } - mutex_lock(&priv->mutex); - if (iwl_power_update_mode(priv, true)) { - /* TT state not updated - * try again during next temperature read - */ - IWL_ERR(priv, "Cannot update power mode, " - "TT state not updated\n"); - tt->state = old_state; - } else { - IWL_DEBUG_POWER(priv, - "Thermal Throttling to new state: %u\n", - tt->state); - if (old_state != IWL_TI_CT_KILL && - tt->state == IWL_TI_CT_KILL) { - IWL_DEBUG_POWER(priv, "Enter IWL_TI_CT_KILL\n"); - iwl_perform_ct_kill_task(priv, true); - - } else if (old_state == IWL_TI_CT_KILL && - tt->state != IWL_TI_CT_KILL) { - IWL_DEBUG_POWER(priv, "Exit IWL_TI_CT_KILL\n"); - iwl_perform_ct_kill_task(priv, false); - } - } - mutex_unlock(&priv->mutex); - } -} - -/* Card State Notification indicated reach critical temperature - * if PSP not enable, no Thermal Throttling function will be performed - * just set the GP1 bit to acknowledge the event - * otherwise, go into IWL_TI_CT_KILL state - * since Card State Notification will not provide any temperature reading - * for Legacy mode - * so just pass the CT_KILL temperature to iwl_legacy_tt_handler() - * for advance mode - * pass CT_KILL_THRESHOLD+1 to make sure move into IWL_TI_CT_KILL state - */ -static void iwl_bg_ct_enter(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_enter); - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!iwl_is_ready(priv)) - return; - - if (tt->state != IWL_TI_CT_KILL) { - IWL_ERR(priv, "Device reached critical temperature " - "- ucode going to sleep!\n"); - if (!priv->thermal_throttle.advanced_tt) - iwl_legacy_tt_handler(priv, - IWL_MINIMAL_POWER_THRESHOLD); - else - iwl_advance_tt_handler(priv, - CT_KILL_THRESHOLD + 1); - } -} - -/* Card State Notification indicated out of critical temperature - * since Card State Notification will not provide any temperature reading - * so pass the IWL_REDUCED_PERFORMANCE_THRESHOLD_2 temperature - * to iwl_legacy_tt_handler() to get out of IWL_CT_KILL state - */ -static void iwl_bg_ct_exit(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, ct_exit); - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!iwl_is_ready(priv)) - return; - - /* stop ct_kill_exit_tm timer */ - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); - - if (tt->state == IWL_TI_CT_KILL) { - IWL_ERR(priv, - "Device temperature below critical" - "- ucode awake!\n"); - if (!priv->thermal_throttle.advanced_tt) - iwl_legacy_tt_handler(priv, - IWL_REDUCED_PERFORMANCE_THRESHOLD_2); - else - iwl_advance_tt_handler(priv, CT_KILL_EXIT_THRESHOLD); - } -} - -void iwl_tt_enter_ct_kill(struct iwl_priv *priv) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_POWER(priv, "Queueing critical temperature enter.\n"); - queue_work(priv->workqueue, &priv->ct_enter); -} -EXPORT_SYMBOL(iwl_tt_enter_ct_kill); - -void iwl_tt_exit_ct_kill(struct iwl_priv *priv) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_POWER(priv, "Queueing critical temperature exit.\n"); - queue_work(priv->workqueue, &priv->ct_exit); -} -EXPORT_SYMBOL(iwl_tt_exit_ct_kill); - -static void iwl_bg_tt_work(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, tt_work); - s32 temp = priv->temperature; /* degrees CELSIUS except 4965 */ - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) - temp = KELVIN_TO_CELSIUS(priv->temperature); - - if (!priv->thermal_throttle.advanced_tt) - iwl_legacy_tt_handler(priv, temp); - else - iwl_advance_tt_handler(priv, temp); -} - -void iwl_tt_handler(struct iwl_priv *priv) -{ - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - IWL_DEBUG_POWER(priv, "Queueing thermal throttling work.\n"); - queue_work(priv->workqueue, &priv->tt_work); -} -EXPORT_SYMBOL(iwl_tt_handler); - -/* Thermal throttling initialization - * For advance thermal throttling: - * Initialize Thermal Index and temperature threshold table - * Initialize thermal throttling restriction table - */ -void iwl_tt_initialize(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); - struct iwl_tt_trans *transaction; - - IWL_DEBUG_POWER(priv, "Initialize Thermal Throttling \n"); - - memset(tt, 0, sizeof(struct iwl_tt_mgmt)); - - tt->state = IWL_TI_0; - init_timer(&priv->thermal_throttle.ct_kill_exit_tm); - priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; - priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; - - /* setup deferred ct kill work */ - INIT_WORK(&priv->tt_work, iwl_bg_tt_work); - INIT_WORK(&priv->ct_enter, iwl_bg_ct_enter); - INIT_WORK(&priv->ct_exit, iwl_bg_ct_exit); - - switch (priv->hw_rev & CSR_HW_REV_TYPE_MSK) { - case CSR_HW_REV_TYPE_6x00: - case CSR_HW_REV_TYPE_6x50: - IWL_DEBUG_POWER(priv, "Advanced Thermal Throttling\n"); - tt->restriction = kzalloc(sizeof(struct iwl_tt_restriction) * - IWL_TI_STATE_MAX, GFP_KERNEL); - tt->transaction = kzalloc(sizeof(struct iwl_tt_trans) * - IWL_TI_STATE_MAX * (IWL_TI_STATE_MAX - 1), - GFP_KERNEL); - if (!tt->restriction || !tt->transaction) { - IWL_ERR(priv, "Fallback to Legacy Throttling\n"); - priv->thermal_throttle.advanced_tt = false; - kfree(tt->restriction); - tt->restriction = NULL; - kfree(tt->transaction); - tt->transaction = NULL; - } else { - transaction = tt->transaction + - (IWL_TI_0 * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_0[0], size); - transaction = tt->transaction + - (IWL_TI_1 * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_1[0], size); - transaction = tt->transaction + - (IWL_TI_2 * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_2[0], size); - transaction = tt->transaction + - (IWL_TI_CT_KILL * (IWL_TI_STATE_MAX - 1)); - memcpy(transaction, &tt_range_3[0], size); - size = sizeof(struct iwl_tt_restriction) * - IWL_TI_STATE_MAX; - memcpy(tt->restriction, - &restriction_range[0], size); - priv->thermal_throttle.advanced_tt = true; - } - break; - default: - IWL_DEBUG_POWER(priv, "Legacy Thermal Throttling\n"); - priv->thermal_throttle.advanced_tt = false; - break; - } -} -EXPORT_SYMBOL(iwl_tt_initialize); - -/* cleanup thermal throttling management related memory and timer */ -void iwl_tt_exit(struct iwl_priv *priv) -{ - struct iwl_tt_mgmt *tt = &priv->thermal_throttle; - - /* stop ct_kill_exit_tm timer if activated */ - del_timer_sync(&priv->thermal_throttle.ct_kill_exit_tm); - cancel_work_sync(&priv->tt_work); - cancel_work_sync(&priv->ct_enter); - cancel_work_sync(&priv->ct_exit); - - if (priv->thermal_throttle.advanced_tt) { - /* free advance thermal throttling memory */ - kfree(tt->restriction); - tt->restriction = NULL; - kfree(tt->transaction); - tt->transaction = NULL; - } -} -EXPORT_SYMBOL(iwl_tt_exit); - -/* initialize to default */ -void iwl_power_initialize(struct iwl_priv *priv) -{ - u16 lctl = iwl_pcie_link_ctl(priv); - - priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN); - - priv->power_data.debug_sleep_level_override = -1; - - memset(&priv->power_data.sleep_cmd, 0, - sizeof(priv->power_data.sleep_cmd)); -} -EXPORT_SYMBOL(iwl_power_initialize); diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h deleted file mode 100644 index df6f6a49712b..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-power.h +++ /dev/null @@ -1,143 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2007 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ -#ifndef __iwl_power_setting_h__ -#define __iwl_power_setting_h__ - -#include "iwl-commands.h" - -#define IWL_ABSOLUTE_ZERO 0 -#define IWL_ABSOLUTE_MAX 0xFFFFFFFF -#define IWL_TT_INCREASE_MARGIN 5 - -enum iwl_antenna_ok { - IWL_ANT_OK_NONE, - IWL_ANT_OK_SINGLE, - IWL_ANT_OK_MULTI, -}; - -/* Thermal Throttling State Machine states */ -enum iwl_tt_state { - IWL_TI_0, /* normal temperature, system power state */ - IWL_TI_1, /* high temperature detect, low power state */ - IWL_TI_2, /* higher temperature detected, lower power state */ - IWL_TI_CT_KILL, /* critical temperature detected, lowest power state */ - IWL_TI_STATE_MAX -}; - -/** - * struct iwl_tt_restriction - Thermal Throttling restriction table - * @tx_stream: number of tx stream allowed - * @is_ht: ht enable/disable - * @rx_stream: number of rx stream allowed - * - * This table is used by advance thermal throttling management - * based on the current thermal throttling state, and determines - * the number of tx/rx streams and the status of HT operation. - */ -struct iwl_tt_restriction { - enum iwl_antenna_ok tx_stream; - enum iwl_antenna_ok rx_stream; - bool is_ht; -}; - -/** - * struct iwl_tt_trans - Thermal Throttling transaction table - * @next_state: next thermal throttling mode - * @tt_low: low temperature threshold to change state - * @tt_high: high temperature threshold to change state - * - * This is used by the advanced thermal throttling algorithm - * to determine the next thermal state to go based on the - * current temperature. - */ -struct iwl_tt_trans { - enum iwl_tt_state next_state; - u32 tt_low; - u32 tt_high; -}; - -/** - * struct iwl_tt_mgnt - Thermal Throttling Management structure - * @advanced_tt: advanced thermal throttle required - * @state: current Thermal Throttling state - * @tt_power_mode: Thermal Throttling power mode index - * being used to set power level when - * when thermal throttling state != IWL_TI_0 - * the tt_power_mode should set to different - * power mode based on the current tt state - * @tt_previous_temperature: last measured temperature - * @iwl_tt_restriction: ptr to restriction tbl, used by advance - * thermal throttling to determine how many tx/rx streams - * should be used in tt state; and can HT be enabled or not - * @iwl_tt_trans: ptr to adv trans table, used by advance thermal throttling - * state transaction - * @ct_kill_toggle: used to toggle the CSR bit when checking uCode temperature - * @ct_kill_exit_tm: timer to exit thermal kill - */ -struct iwl_tt_mgmt { - enum iwl_tt_state state; - bool advanced_tt; - u8 tt_power_mode; - bool ct_kill_toggle; -#ifdef CONFIG_IWLWIFI_DEBUG - s32 tt_previous_temp; -#endif - struct iwl_tt_restriction *restriction; - struct iwl_tt_trans *transaction; - struct timer_list ct_kill_exit_tm; -}; - -enum iwl_power_level { - IWL_POWER_INDEX_1, - IWL_POWER_INDEX_2, - IWL_POWER_INDEX_3, - IWL_POWER_INDEX_4, - IWL_POWER_INDEX_5, - IWL_POWER_NUM -}; - -struct iwl_power_mgr { - struct iwl_powertable_cmd sleep_cmd; - int debug_sleep_level_override; - bool pci_pm; -}; - -int iwl_power_update_mode(struct iwl_priv *priv, bool force); -bool iwl_ht_enabled(struct iwl_priv *priv); -enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); -enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); -void iwl_tt_enter_ct_kill(struct iwl_priv *priv); -void iwl_tt_exit_ct_kill(struct iwl_priv *priv); -void iwl_tt_handler(struct iwl_priv *priv); -void iwl_tt_initialize(struct iwl_priv *priv); -void iwl_tt_exit(struct iwl_priv *priv); -void iwl_power_initialize(struct iwl_priv *priv); - -extern bool no_sleep_autoadjust; - -#endif /* __iwl_power_setting_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h deleted file mode 100644 index d393e8f02102..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-prph.h +++ /dev/null @@ -1,564 +0,0 @@ -/****************************************************************************** - * - * This file is provided under a dual BSD/GPLv2 license. When using or - * redistributing this file, you may do so under either license. - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - * BSD LICENSE - * - * Copyright(c) 2005 - 2009 Intel Corporation. All rights reserved. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - *****************************************************************************/ - -#ifndef __iwl_prph_h__ -#define __iwl_prph_h__ - -/* - * Registers in this file are internal, not PCI bus memory mapped. - * Driver accesses these via HBUS_TARG_PRPH_* registers. - */ -#define PRPH_BASE (0x00000) -#define PRPH_END (0xFFFFF) - -/* APMG (power management) constants */ -#define APMG_BASE (PRPH_BASE + 0x3000) -#define APMG_CLK_CTRL_REG (APMG_BASE + 0x0000) -#define APMG_CLK_EN_REG (APMG_BASE + 0x0004) -#define APMG_CLK_DIS_REG (APMG_BASE + 0x0008) -#define APMG_PS_CTRL_REG (APMG_BASE + 0x000c) -#define APMG_PCIDEV_STT_REG (APMG_BASE + 0x0010) -#define APMG_RFKILL_REG (APMG_BASE + 0x0014) -#define APMG_RTC_INT_STT_REG (APMG_BASE + 0x001c) -#define APMG_RTC_INT_MSK_REG (APMG_BASE + 0x0020) -#define APMG_DIGITAL_SVR_REG (APMG_BASE + 0x0058) -#define APMG_ANALOG_SVR_REG (APMG_BASE + 0x006C) - -#define APMG_CLK_VAL_DMA_CLK_RQT (0x00000200) -#define APMG_CLK_VAL_BSM_CLK_RQT (0x00000800) - - -#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS (0x00400000) -#define APMG_PS_CTRL_VAL_RESET_REQ (0x04000000) -#define APMG_PS_CTRL_MSK_PWR_SRC (0x03000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN (0x00000000) -#define APMG_PS_CTRL_VAL_PWR_SRC_MAX (0x01000000) /* 3945 only */ -#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX (0x02000000) -#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK (0x000001E0) /* bit 8:5 */ -#define APMG_SVR_DIGITAL_VOLTAGE_1_32 (0x00000060) - -#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS (0x00000800) - -/** - * BSM (Bootstrap State Machine) - * - * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program - * in special SRAM that does not power down when the embedded control - * processor is sleeping (e.g. for periodic power-saving shutdowns of radio). - * - * When powering back up after sleeps (or during initial uCode load), the BSM - * internally loads the short bootstrap program from the special SRAM into the - * embedded processor's instruction SRAM, and starts the processor so it runs - * the bootstrap program. - * - * This bootstrap program loads (via PCI busmaster DMA) instructions and data - * images for a uCode program from host DRAM locations. The host driver - * indicates DRAM locations and sizes for instruction and data images via the - * four BSM_DRAM_* registers. Once the bootstrap program loads the new program, - * the new program starts automatically. - * - * The uCode used for open-source drivers includes two programs: - * - * 1) Initialization -- performs hardware calibration and sets up some - * internal data, then notifies host via "initialize alive" notification - * (struct iwl_init_alive_resp) that it has completed all of its work. - * After signal from host, it then loads and starts the runtime program. - * The initialization program must be used when initially setting up the - * NIC after loading the driver. - * - * 2) Runtime/Protocol -- performs all normal runtime operations. This - * notifies host via "alive" notification (struct iwl_alive_resp) that it - * is ready to be used. - * - * When initializing the NIC, the host driver does the following procedure: - * - * 1) Load bootstrap program (instructions only, no data image for bootstrap) - * into bootstrap memory. Use dword writes starting at BSM_SRAM_LOWER_BOUND - * - * 2) Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction - * images in host DRAM. - * - * 3) Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked: - * BSM_WR_MEM_SRC_REG = 0 - * BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND - * BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image - * - * 4) Load bootstrap into instruction SRAM: - * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START - * - * 5) Wait for load completion: - * Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0 - * - * 6) Enable future boot loads whenever NIC's power management triggers it: - * BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN - * - * 7) Start the NIC by removing all reset bits: - * CSR_RESET = 0 - * - * The bootstrap uCode (already in instruction SRAM) loads initialization - * uCode. Initialization uCode performs data initialization, sends - * "initialize alive" notification to host, and waits for a signal from - * host to load runtime code. - * - * 4) Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction - * images in host DRAM. The last register loaded must be the instruction - * byte count register ("1" in MSbit tells initialization uCode to load - * the runtime uCode): - * BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD - * - * 5) Wait for "alive" notification, then issue normal runtime commands. - * - * Data caching during power-downs: - * - * Just before the embedded controller powers down (e.g for automatic - * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA) - * a current snapshot of the embedded processor's data SRAM into host DRAM. - * This caches the data while the embedded processor's memory is powered down. - * Location and size are controlled by BSM_DRAM_DATA_* registers. - * - * NOTE: Instruction SRAM does not need to be saved, since that doesn't - * change during operation; the original image (from uCode distribution - * file) can be used for reload. - * - * When powering back up, the BSM loads the bootstrap program. Bootstrap looks - * at the BSM_DRAM_* registers, which now point to the runtime instruction - * image and the cached (modified) runtime data (*not* the initialization - * uCode). Bootstrap reloads these runtime images into SRAM, and restarts the - * uCode from where it left off before the power-down. - * - * NOTE: Initialization uCode does *not* run as part of the save/restore - * procedure. - * - * This save/restore method is mostly for autonomous power management during - * normal operation (result of POWER_TABLE_CMD). Platform suspend/resume and - * RFKILL should use complete restarts (with total re-initialization) of uCode, - * allowing total shutdown (including BSM memory). - * - * Note that, during normal operation, the host DRAM that held the initial - * startup data for the runtime code is now being used as a backup data cache - * for modified data! If you need to completely re-initialize the NIC, make - * sure that you use the runtime data image from the uCode distribution file, - * not the modified/saved runtime data. You may want to store a separate - * "clean" runtime data image in DRAM to avoid disk reads of distribution file. - */ - -/* BSM bit fields */ -#define BSM_WR_CTRL_REG_BIT_START (0x80000000) /* start boot load now */ -#define BSM_WR_CTRL_REG_BIT_START_EN (0x40000000) /* enable boot after pwrup*/ -#define BSM_DRAM_INST_LOAD (0x80000000) /* start program load now */ - -/* BSM addresses */ -#define BSM_BASE (PRPH_BASE + 0x3400) -#define BSM_END (PRPH_BASE + 0x3800) - -#define BSM_WR_CTRL_REG (BSM_BASE + 0x000) /* ctl and status */ -#define BSM_WR_MEM_SRC_REG (BSM_BASE + 0x004) /* source in BSM mem */ -#define BSM_WR_MEM_DST_REG (BSM_BASE + 0x008) /* dest in SRAM mem */ -#define BSM_WR_DWCOUNT_REG (BSM_BASE + 0x00C) /* bytes */ -#define BSM_WR_STATUS_REG (BSM_BASE + 0x010) /* bit 0: 1 == done */ - -/* - * Pointers and size regs for bootstrap load and data SRAM save/restore. - * NOTE: 3945 pointers use bits 31:0 of DRAM address. - * 4965 pointers use bits 35:4 of DRAM address. - */ -#define BSM_DRAM_INST_PTR_REG (BSM_BASE + 0x090) -#define BSM_DRAM_INST_BYTECOUNT_REG (BSM_BASE + 0x094) -#define BSM_DRAM_DATA_PTR_REG (BSM_BASE + 0x098) -#define BSM_DRAM_DATA_BYTECOUNT_REG (BSM_BASE + 0x09C) - -/* - * BSM special memory, stays powered on during power-save sleeps. - * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1) - */ -#define BSM_SRAM_LOWER_BOUND (PRPH_BASE + 0x3800) -#define BSM_SRAM_SIZE (1024) /* bytes */ - - -/* 3945 Tx scheduler registers */ -#define ALM_SCD_BASE (PRPH_BASE + 0x2E00) -#define ALM_SCD_MODE_REG (ALM_SCD_BASE + 0x000) -#define ALM_SCD_ARASTAT_REG (ALM_SCD_BASE + 0x004) -#define ALM_SCD_TXFACT_REG (ALM_SCD_BASE + 0x010) -#define ALM_SCD_TXF4MF_REG (ALM_SCD_BASE + 0x014) -#define ALM_SCD_TXF5MF_REG (ALM_SCD_BASE + 0x020) -#define ALM_SCD_SBYP_MODE_1_REG (ALM_SCD_BASE + 0x02C) -#define ALM_SCD_SBYP_MODE_2_REG (ALM_SCD_BASE + 0x030) - -/** - * Tx Scheduler - * - * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs - * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in - * host DRAM. It steers each frame's Tx command (which contains the frame - * data) into one of up to 7 prioritized Tx DMA FIFO channels within the - * device. A queue maps to only one (selectable by driver) Tx DMA channel, - * but one DMA channel may take input from several queues. - * - * Tx DMA channels have dedicated purposes. For 4965, they are used as follows: - * - * 0 -- EDCA BK (background) frames, lowest priority - * 1 -- EDCA BE (best effort) frames, normal priority - * 2 -- EDCA VI (video) frames, higher priority - * 3 -- EDCA VO (voice) and management frames, highest priority - * 4 -- Commands (e.g. RXON, etc.) - * 5 -- HCCA short frames - * 6 -- HCCA long frames - * 7 -- not used by driver (device-internal only) - * - * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6. - * In addition, driver can map queues 7-15 to Tx DMA/FIFO channels 0-3 to - * support 11n aggregation via EDCA DMA channels. - * - * The driver sets up each queue to work in one of two modes: - * - * 1) Scheduler-Ack, in which the scheduler automatically supports a - * block-ack (BA) window of up to 64 TFDs. In this mode, each queue - * contains TFDs for a unique combination of Recipient Address (RA) - * and Traffic Identifier (TID), that is, traffic of a given - * Quality-Of-Service (QOS) priority, destined for a single station. - * - * In scheduler-ack mode, the scheduler keeps track of the Tx status of - * each frame within the BA window, including whether it's been transmitted, - * and whether it's been acknowledged by the receiving station. The device - * automatically processes block-acks received from the receiving STA, - * and reschedules un-acked frames to be retransmitted (successful - * Tx completion may end up being out-of-order). - * - * The driver must maintain the queue's Byte Count table in host DRAM - * (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode. - * This mode does not support fragmentation. - * - * 2) FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order. - * The device may automatically retry Tx, but will retry only one frame - * at a time, until receiving ACK from receiving station, or reaching - * retry limit and giving up. - * - * The command queue (#4) must use this mode! - * This mode does not require use of the Byte Count table in host DRAM. - * - * Driver controls scheduler operation via 3 means: - * 1) Scheduler registers - * 2) Shared scheduler data base in internal 4956 SRAM - * 3) Shared data in host DRAM - * - * Initialization: - * - * When loading, driver should allocate memory for: - * 1) 16 TFD circular buffers, each with space for (typically) 256 TFDs. - * 2) 16 Byte Count circular buffers in 16 KBytes contiguous memory - * (1024 bytes for each queue). - * - * After receiving "Alive" response from uCode, driver must initialize - * the scheduler (especially for queue #4, the command queue, otherwise - * the driver can't issue commands!): - */ - -/** - * Max Tx window size is the max number of contiguous TFDs that the scheduler - * can keep track of at one time when creating block-ack chains of frames. - * Note that "64" matches the number of ack bits in a block-ack packet. - * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize - * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values. - */ -#define SCD_WIN_SIZE 64 -#define SCD_FRAME_LIMIT 64 - -/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */ -#define IWL49_SCD_START_OFFSET 0xa02c00 - -/* - * 4965 tells driver SRAM address for internal scheduler structs via this reg. - * Value is valid only after "Alive" response from uCode. - */ -#define IWL49_SCD_SRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x0) - -/* - * Driver may need to update queue-empty bits after changing queue's - * write and read pointers (indexes) during (re-)initialization (i.e. when - * scheduler is not tracking what's happening). - * Bit fields: - * 31-16: Write mask -- 1: update empty bit, 0: don't change empty bit - * 15-00: Empty state, one for each queue -- 1: empty, 0: non-empty - * NOTE: This register is not used by Linux driver. - */ -#define IWL49_SCD_EMPTY_BITS (IWL49_SCD_START_OFFSET + 0x4) - -/* - * Physical base address of array of byte count (BC) circular buffers (CBs). - * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode. - * This register points to BC CB for queue 0, must be on 1024-byte boundary. - * Others are spaced by 1024 bytes. - * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad. - * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff). - * Bit fields: - * 25-00: Byte Count CB physical address [35:10], must be 1024-byte aligned. - */ -#define IWL49_SCD_DRAM_BASE_ADDR (IWL49_SCD_START_OFFSET + 0x10) - -/* - * Enables any/all Tx DMA/FIFO channels. - * Scheduler generates requests for only the active channels. - * Set this to 0xff to enable all 8 channels (normal usage). - * Bit fields: - * 7- 0: Enable (1), disable (0), one bit for each channel 0-7 - */ -#define IWL49_SCD_TXFACT (IWL49_SCD_START_OFFSET + 0x1c) -/* - * Queue (x) Write Pointers (indexes, really!), one for each Tx queue. - * Initialized and updated by driver as new TFDs are added to queue. - * NOTE: If using Block Ack, index must correspond to frame's - * Start Sequence Number; index = (SSN & 0xff) - * NOTE: Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses? - */ -#define IWL49_SCD_QUEUE_WRPTR(x) (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4) - -/* - * Queue (x) Read Pointers (indexes, really!), one for each Tx queue. - * For FIFO mode, index indicates next frame to transmit. - * For Scheduler-ACK mode, index indicates first frame in Tx window. - * Initialized by driver, updated by scheduler. - */ -#define IWL49_SCD_QUEUE_RDPTR(x) (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4) - -/* - * Select which queues work in chain mode (1) vs. not (0). - * Use chain mode to build chains of aggregated frames. - * Bit fields: - * 31-16: Reserved - * 15-00: Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time - * NOTE: If driver sets up queue for chain mode, it should be also set up - * Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x). - */ -#define IWL49_SCD_QUEUECHAIN_SEL (IWL49_SCD_START_OFFSET + 0xd0) - -/* - * Select which queues interrupt driver when scheduler increments - * a queue's read pointer (index). - * Bit fields: - * 31-16: Reserved - * 15-00: Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled - * NOTE: This functionality is apparently a no-op; driver relies on interrupts - * from Rx queue to read Tx command responses and update Tx queues. - */ -#define IWL49_SCD_INTERRUPT_MASK (IWL49_SCD_START_OFFSET + 0xe4) - -/* - * Queue search status registers. One for each queue. - * Sets up queue mode and assigns queue to Tx DMA channel. - * Bit fields: - * 19-10: Write mask/enable bits for bits 0-9 - * 9: Driver should init to "0" - * 8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0). - * Driver should init to "1" for aggregation mode, or "0" otherwise. - * 7-6: Driver should init to "0" - * 5: Window Size Left; indicates whether scheduler can request - * another TFD, based on window size, etc. Driver should init - * this bit to "1" for aggregation mode, or "0" for non-agg. - * 4-1: Tx FIFO to use (range 0-7). - * 0: Queue is active (1), not active (0). - * Other bits should be written as "0" - * - * NOTE: If enabling Scheduler-ACK mode, chain mode should also be enabled - * via SCD_QUEUECHAIN_SEL. - */ -#define IWL49_SCD_QUEUE_STATUS_BITS(x)\ - (IWL49_SCD_START_OFFSET + 0x104 + (x) * 4) - -/* Bit field positions */ -#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE (0) -#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF (1) -#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL (5) -#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK (8) - -/* Write masks */ -#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (10) -#define IWL49_SCD_QUEUE_STTS_REG_MSK (0x0007FC00) - -/** - * 4965 internal SRAM structures for scheduler, shared with driver ... - * - * Driver should clear and initialize the following areas after receiving - * "Alive" response from 4965 uCode, i.e. after initial - * uCode load, or after a uCode load done for error recovery: - * - * SCD_CONTEXT_DATA_OFFSET (size 128 bytes) - * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes) - * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes) - * - * Driver accesses SRAM via HBUS_TARG_MEM_* registers. - * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR. - * All OFFSET values must be added to this base address. - */ - -/* - * Queue context. One 8-byte entry for each of 16 queues. - * - * Driver should clear this entire area (size 0x80) to 0 after receiving - * "Alive" notification from uCode. Additionally, driver should init - * each queue's entry as follows: - * - * LS Dword bit fields: - * 0-06: Max Tx window size for Scheduler-ACK. Driver should init to 64. - * - * MS Dword bit fields: - * 16-22: Frame limit. Driver should init to 10 (0xa). - * - * Driver should init all other bits to 0. - * - * Init must be done after driver receives "Alive" response from 4965 uCode, - * and when setting up queue for aggregation. - */ -#define IWL49_SCD_CONTEXT_DATA_OFFSET 0x380 -#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \ - (IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) - -#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS (0) -#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK (0x0000007F) -#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) -#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) - -/* - * Tx Status Bitmap - * - * Driver should clear this entire area (size 0x100) to 0 after receiving - * "Alive" notification from uCode. Area is used only by device itself; - * no other support (besides clearing) is required from driver. - */ -#define IWL49_SCD_TX_STTS_BITMAP_OFFSET 0x400 - -/* - * RAxTID to queue translation mapping. - * - * When queue is in Scheduler-ACK mode, frames placed in a that queue must be - * for only one combination of receiver address (RA) and traffic ID (TID), i.e. - * one QOS priority level destined for one station (for this wireless link, - * not final destination). The SCD_TRANSLATE_TABLE area provides 16 16-bit - * mappings, one for each of the 16 queues. If queue is not in Scheduler-ACK - * mode, the device ignores the mapping value. - * - * Bit fields, for each 16-bit map: - * 15-9: Reserved, set to 0 - * 8-4: Index into device's station table for recipient station - * 3-0: Traffic ID (tid), range 0-15 - * - * Driver should clear this entire area (size 32 bytes) to 0 after receiving - * "Alive" notification from uCode. To update a 16-bit map value, driver - * must read a dword-aligned value from device SRAM, replace the 16-bit map - * value of interest, and write the dword value back into device SRAM. - */ -#define IWL49_SCD_TRANSLATE_TBL_OFFSET 0x500 - -/* Find translation table dword to read/write for given queue */ -#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc) - -#define IWL_SCD_TXFIFO_POS_TID (0) -#define IWL_SCD_TXFIFO_POS_RA (4) -#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK (0x01FF) - -/* 5000 SCD */ -#define IWL50_SCD_QUEUE_STTS_REG_POS_TXF (0) -#define IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE (3) -#define IWL50_SCD_QUEUE_STTS_REG_POS_WSL (4) -#define IWL50_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN (19) -#define IWL50_SCD_QUEUE_STTS_REG_MSK (0x00FF0000) - -#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_POS (8) -#define IWL50_SCD_QUEUE_CTX_REG1_CREDIT_MSK (0x00FFFF00) -#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_POS (24) -#define IWL50_SCD_QUEUE_CTX_REG1_SUPER_CREDIT_MSK (0xFF000000) -#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_POS (0) -#define IWL50_SCD_QUEUE_CTX_REG2_WIN_SIZE_MSK (0x0000007F) -#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS (16) -#define IWL50_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK (0x007F0000) - -#define IWL50_SCD_CONTEXT_DATA_OFFSET (0x600) -#define IWL50_SCD_TX_STTS_BITMAP_OFFSET (0x7B1) -#define IWL50_SCD_TRANSLATE_TBL_OFFSET (0x7E0) - -#define IWL50_SCD_CONTEXT_QUEUE_OFFSET(x)\ - (IWL50_SCD_CONTEXT_DATA_OFFSET + ((x) * 8)) - -#define IWL50_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \ - ((IWL50_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffc) - -#define IWL50_SCD_QUEUECHAIN_SEL_ALL(x) (((1<<(x)) - 1) &\ - (~(1< - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-sta.h" -#include "iwl-io.h" -#include "iwl-calib.h" -#include "iwl-helpers.h" -/************************** RX-FUNCTIONS ****************************/ -/* - * Rx theory of operation - * - * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs), - * each of which point to Receive Buffers to be filled by the NIC. These get - * used not only for Rx frames, but for any command response or notification - * from the NIC. The driver and NIC manage the Rx buffers by means - * of indexes into the circular buffer. - * - * Rx Queue Indexes - * The host/firmware share two index registers for managing the Rx buffers. - * - * The READ index maps to the first position that the firmware may be writing - * to -- the driver can read up to (but not including) this position and get - * good data. - * The READ index is managed by the firmware once the card is enabled. - * - * The WRITE index maps to the last position the driver has read from -- the - * position preceding WRITE is the last slot the firmware can place a packet. - * - * The queue is empty (no good data) if WRITE = READ - 1, and is full if - * WRITE = READ. - * - * During initialization, the host sets up the READ queue position to the first - * INDEX position, and WRITE to the last (READ - 1 wrapped) - * - * When the firmware places a packet in a buffer, it will advance the READ index - * and fire the RX interrupt. The driver can then query the READ index and - * process as many packets as possible, moving the WRITE index forward as it - * resets the Rx queue buffers with new memory. - * - * The management in the driver is as follows: - * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When - * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled - * to replenish the iwl->rxq->rx_free. - * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the - * iwl->rxq is replenished and the READ INDEX is updated (updating the - * 'processed' and 'read' driver indexes as well) - * + A received packet is processed and handed to the kernel network stack, - * detached from the iwl->rxq. The driver 'processed' index is updated. - * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free - * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ - * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there - * were enough free buffers and RX_STALLED is set it is cleared. - * - * - * Driver sequence: - * - * iwl_rx_queue_alloc() Allocates rx_free - * iwl_rx_replenish() Replenishes rx_free list from rx_used, and calls - * iwl_rx_queue_restock - * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx - * queue, updates firmware pointers, and updates - * the WRITE index. If insufficient rx_free buffers - * are available, schedules iwl_rx_replenish - * - * -- enable interrupts -- - * ISR - iwl_rx() Detach iwl_rx_mem_buffers from pool up to the - * READ INDEX, detaching the SKB from the pool. - * Moves the packet buffer from queue to rx_used. - * Calls iwl_rx_queue_restock to refill any empty - * slots. - * ... - * - */ - -/** - * iwl_rx_queue_space - Return number of free slots available in queue. - */ -int iwl_rx_queue_space(const struct iwl_rx_queue *q) -{ - int s = q->read - q->write; - if (s <= 0) - s += RX_QUEUE_SIZE; - /* keep some buffer to not confuse full and empty queue */ - s -= 2; - if (s < 0) - s = 0; - return s; -} -EXPORT_SYMBOL(iwl_rx_queue_space); - -/** - * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue - */ -int iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, struct iwl_rx_queue *q) -{ - unsigned long flags; - u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg; - u32 reg; - int ret = 0; - - spin_lock_irqsave(&q->lock, flags); - - if (q->need_update == 0) - goto exit_unlock; - - /* If power-saving is in use, make sure device is awake */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - goto exit_unlock; - } - - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); - - /* Else device is assumed to be awake */ - } else { - /* Device expects a multiple of 8 */ - q->write_actual = (q->write & ~0x7); - iwl_write_direct32(priv, rx_wrt_ptr_reg, q->write_actual); - } - - q->need_update = 0; - - exit_unlock: - spin_unlock_irqrestore(&q->lock, flags); - return ret; -} -EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr); -/** - * iwl_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr - */ -static inline __le32 iwl_dma_addr2rbd_ptr(struct iwl_priv *priv, - dma_addr_t dma_addr) -{ - return cpu_to_le32((u32)(dma_addr >> 8)); -} - -/** - * iwl_rx_queue_restock - refill RX queue from pre-allocated pool - * - * If there are slots in the RX queue that need to be restocked, - * and we have free pre-allocated buffers, fill the ranks as much - * as we can, pulling from rx_free. - * - * This moves the 'write' index forward to catch up with 'processed', and - * also updates the memory address in the firmware to reference the new - * target buffer. - */ -int iwl_rx_queue_restock(struct iwl_priv *priv) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - unsigned long flags; - int write; - int ret = 0; - - spin_lock_irqsave(&rxq->lock, flags); - write = rxq->write & ~0x7; - while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { - /* Get next free Rx buffer, remove from free list */ - element = rxq->rx_free.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr); - rxq->queue[rxq->write] = rxb; - rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; - rxq->free_count--; - } - spin_unlock_irqrestore(&rxq->lock, flags); - /* If the pre-allocated buffer pool is dropping low, schedule to - * refill it */ - if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->workqueue, &priv->rx_replenish); - - - /* If we've added more space for the firmware to place data, tell it. - * Increment device's write pointer in multiples of 8. */ - if (rxq->write_actual != (rxq->write & ~0x7)) { - spin_lock_irqsave(&rxq->lock, flags); - rxq->need_update = 1; - spin_unlock_irqrestore(&rxq->lock, flags); - ret = iwl_rx_queue_update_write_ptr(priv, rxq); - } - - return ret; -} -EXPORT_SYMBOL(iwl_rx_queue_restock); - - -/** - * iwl_rx_replenish - Move all used packet from rx_used to rx_free - * - * When moving to rx_free an SKB is allocated for the slot. - * - * Also restock the Rx queue via iwl_rx_queue_restock. - * This is called as a scheduled work item (except for during initialization) - */ -void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - struct sk_buff *skb; - unsigned long flags; - - while (1) { - spin_lock_irqsave(&rxq->lock, flags); - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - return; - } - spin_unlock_irqrestore(&rxq->lock, flags); - - if (rxq->free_count > RX_LOW_WATERMARK) - priority |= __GFP_NOWARN; - /* Alloc a new receive buffer */ - skb = alloc_skb(priv->hw_params.rx_buf_size + 256, - priority); - - if (!skb) { - if (net_ratelimit()) - IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); - if ((rxq->free_count <= RX_LOW_WATERMARK) && - net_ratelimit()) - IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", - priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", - rxq->free_count); - /* We don't reschedule replenish work here -- we will - * call the restock method and if it still needs - * more buffers it will schedule replenish */ - break; - } - - spin_lock_irqsave(&rxq->lock, flags); - - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - dev_kfree_skb_any(skb); - return; - } - element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - spin_unlock_irqrestore(&rxq->lock, flags); - - rxb->skb = skb; - /* Get physical address of RB/SKB */ - rxb->real_dma_addr = pci_map_single( - priv->pci_dev, - rxb->skb->data, - priv->hw_params.rx_buf_size + 256, - PCI_DMA_FROMDEVICE); - /* dma address must be no more than 36 bits */ - BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36)); - /* and also 256 byte aligned! */ - rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); - skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); - - spin_lock_irqsave(&rxq->lock, flags); - - list_add_tail(&rxb->list, &rxq->rx_free); - rxq->free_count++; - priv->alloc_rxb_skb++; - - spin_unlock_irqrestore(&rxq->lock, flags); - } -} - -void iwl_rx_replenish(struct iwl_priv *priv) -{ - unsigned long flags; - - iwl_rx_allocate(priv, GFP_KERNEL); - - spin_lock_irqsave(&priv->lock, flags); - iwl_rx_queue_restock(priv); - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(iwl_rx_replenish); - -void iwl_rx_replenish_now(struct iwl_priv *priv) -{ - iwl_rx_allocate(priv, GFP_ATOMIC); - - iwl_rx_queue_restock(priv); -} -EXPORT_SYMBOL(iwl_rx_replenish_now); - - -/* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have its SKB set to NULL - * This free routine walks the list of POOL entries and if SKB is set to - * non NULL it is unmapped and freed - */ -void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - int i; - for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, - rxq->pool[i].real_dma_addr, - priv->hw_params.rx_buf_size + 256, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(rxq->pool[i].skb); - } - } - - dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); - dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); - rxq->bd = NULL; - rxq->rb_stts = NULL; -} -EXPORT_SYMBOL(iwl_rx_queue_free); - -int iwl_rx_queue_alloc(struct iwl_priv *priv) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct device *dev = &priv->pci_dev->dev; - int i; - - spin_lock_init(&rxq->lock); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - - /* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */ - rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->dma_addr, - GFP_KERNEL); - if (!rxq->bd) - goto err_bd; - - rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status), - &rxq->rb_stts_dma, GFP_KERNEL); - if (!rxq->rb_stts) - goto err_rb; - - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->write_actual = 0; - rxq->free_count = 0; - rxq->need_update = 0; - return 0; - -err_rb: - dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); -err_bd: - return -ENOMEM; -} -EXPORT_SYMBOL(iwl_rx_queue_alloc); - -void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - unsigned long flags; - int i; - spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, - rxq->pool[i].real_dma_addr, - priv->hw_params.rx_buf_size + 256, - PCI_DMA_FROMDEVICE); - priv->alloc_rxb_skb--; - dev_kfree_skb(rxq->pool[i].skb); - rxq->pool[i].skb = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - } - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->write_actual = 0; - rxq->free_count = 0; - spin_unlock_irqrestore(&rxq->lock, flags); -} - -int iwl_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - u32 rb_size; - const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */ - u32 rb_timeout = 0; /* FIXME: RX_RB_TIMEOUT for all devices? */ - - if (!priv->cfg->use_isr_legacy) - rb_timeout = RX_RB_TIMEOUT; - - if (priv->cfg->mod_params->amsdu_size_8K) - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K; - else - rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K; - - /* Stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - - /* Reset driver's Rx queue write index */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0); - - /* Tell device where to find RBD circular buffer in DRAM */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG, - (u32)(rxq->dma_addr >> 8)); - - /* Tell device where in DRAM to update its Rx status */ - iwl_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG, - rxq->rb_stts_dma >> 4); - - /* Enable Rx DMA - * FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY is set because of HW bug in - * the credit mechanism in 5000 HW RX FIFO - * Direct rx interrupts to hosts - * Rx buffer size 4 or 8k - * RB timeout 0x10 - * 256 RBDs - */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, - FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL | - FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY | - FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL | - FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK | - rb_size| - (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)| - (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS)); - - iwl_write32(priv, CSR_INT_COALESCING, 0x40); - - return 0; -} - -int iwl_rxq_stop(struct iwl_priv *priv) -{ - - /* stop Rx DMA */ - iwl_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0); - iwl_poll_direct_bit(priv, FH_MEM_RSSR_RX_STATUS_REG, - FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000); - - return 0; -} -EXPORT_SYMBOL(iwl_rxq_stop); - -void iwl_rx_missed_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) - -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_missed_beacon_notif *missed_beacon; - - missed_beacon = &pkt->u.missed_beacon; - if (le32_to_cpu(missed_beacon->consequtive_missed_beacons) > 5) { - IWL_DEBUG_CALIB(priv, "missed bcn cnsq %d totl %d rcd %d expctd %d\n", - le32_to_cpu(missed_beacon->consequtive_missed_beacons), - le32_to_cpu(missed_beacon->total_missed_becons), - le32_to_cpu(missed_beacon->num_recvd_beacons), - le32_to_cpu(missed_beacon->num_expected_beacons)); - if (!test_bit(STATUS_SCANNING, &priv->status)) - iwl_init_sensitivity(priv); - } -} -EXPORT_SYMBOL(iwl_rx_missed_beacon_notif); - - -/* Calculate noise level, based on measurements during network silence just - * before arriving beacon. This measurement can be done only if we know - * exactly when to expect beacons, therefore only when we're associated. */ -static void iwl_rx_calc_noise(struct iwl_priv *priv) -{ - struct statistics_rx_non_phy *rx_info - = &(priv->statistics.rx.general); - int num_active_rx = 0; - int total_silence = 0; - int bcn_silence_a = - le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER; - int bcn_silence_b = - le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER; - int bcn_silence_c = - le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER; - - if (bcn_silence_a) { - total_silence += bcn_silence_a; - num_active_rx++; - } - if (bcn_silence_b) { - total_silence += bcn_silence_b; - num_active_rx++; - } - if (bcn_silence_c) { - total_silence += bcn_silence_c; - num_active_rx++; - } - - /* Average among active antennas */ - if (num_active_rx) - priv->last_rx_noise = (total_silence / num_active_rx) - 107; - else - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - - IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n", - bcn_silence_a, bcn_silence_b, bcn_silence_c, - priv->last_rx_noise); -} - -#define REG_RECALIB_PERIOD (60) - -void iwl_rx_statistics(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - int change; - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - - IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n", - (int)sizeof(priv->statistics), - le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK); - - change = ((priv->statistics.general.temperature != - pkt->u.stats.general.temperature) || - ((priv->statistics.flag & - STATISTICS_REPLY_FLG_HT40_MODE_MSK) != - (pkt->u.stats.flag & STATISTICS_REPLY_FLG_HT40_MODE_MSK))); - - memcpy(&priv->statistics, &pkt->u.stats, sizeof(priv->statistics)); - - set_bit(STATUS_STATISTICS, &priv->status); - - /* Reschedule the statistics timer to occur in - * REG_RECALIB_PERIOD seconds to ensure we get a - * thermal update even if the uCode doesn't give - * us one */ - mod_timer(&priv->statistics_periodic, jiffies + - msecs_to_jiffies(REG_RECALIB_PERIOD * 1000)); - - if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) && - (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) { - iwl_rx_calc_noise(priv); - queue_work(priv->workqueue, &priv->run_time_calib_work); - } - - iwl_leds_background(priv); - - if (priv->cfg->ops->lib->temp_ops.temperature && change) - priv->cfg->ops->lib->temp_ops.temperature(priv); -} -EXPORT_SYMBOL(iwl_rx_statistics); - -#define PERFECT_RSSI (-20) /* dBm */ -#define WORST_RSSI (-95) /* dBm */ -#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) - -/* Calculate an indication of rx signal quality (a percentage, not dBm!). - * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info - * about formulas used below. */ -static int iwl_calc_sig_qual(int rssi_dbm, int noise_dbm) -{ - int sig_qual; - int degradation = PERFECT_RSSI - rssi_dbm; - - /* If we get a noise measurement, use signal-to-noise ratio (SNR) - * as indicator; formula is (signal dbm - noise dbm). - * SNR at or above 40 is a great signal (100%). - * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. - * Weakest usable signal is usually 10 - 15 dB SNR. */ - if (noise_dbm) { - if (rssi_dbm - noise_dbm >= 40) - return 100; - else if (rssi_dbm < noise_dbm) - return 0; - sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; - - /* Else use just the signal level. - * This formula is a least squares fit of data points collected and - * compared with a reference system that had a percentage (%) display - * for signal quality. */ - } else - sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * - (15 * RSSI_RANGE + 62 * degradation)) / - (RSSI_RANGE * RSSI_RANGE); - - if (sig_qual > 100) - sig_qual = 100; - else if (sig_qual < 1) - sig_qual = 0; - - return sig_qual; -} - -/* Calc max signal level (dBm) among 3 possible receivers */ -static inline int iwl_calc_rssi(struct iwl_priv *priv, - struct iwl_rx_phy_res *rx_resp) -{ - return priv->cfg->ops->utils->calc_rssi(priv, rx_resp); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -/** - * iwl_dbg_report_frame - dump frame to syslog during debug sessions - * - * You may hack this function to show different aspects of received frames, - * including selective frame dumps. - * group100 parameter selects whether to show 1 out of 100 good data frames. - * All beacon and probe response frames are printed. - */ -static void iwl_dbg_report_frame(struct iwl_priv *priv, - struct iwl_rx_phy_res *phy_res, u16 length, - struct ieee80211_hdr *header, int group100) -{ - u32 to_us; - u32 print_summary = 0; - u32 print_dump = 0; /* set to 1 to dump all frames' contents */ - u32 hundred = 0; - u32 dataframe = 0; - __le16 fc; - u16 seq_ctl; - u16 channel; - u16 phy_flags; - u32 rate_n_flags; - u32 tsf_low; - int rssi; - - if (likely(!(iwl_get_debug_level(priv) & IWL_DL_RX))) - return; - - /* MAC header */ - fc = header->frame_control; - seq_ctl = le16_to_cpu(header->seq_ctrl); - - /* metadata */ - channel = le16_to_cpu(phy_res->channel); - phy_flags = le16_to_cpu(phy_res->phy_flags); - rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); - - /* signal statistics */ - rssi = iwl_calc_rssi(priv, phy_res); - tsf_low = le64_to_cpu(phy_res->timestamp) & 0x0ffffffff; - - to_us = !compare_ether_addr(header->addr1, priv->mac_addr); - - /* if data frame is to us and all is good, - * (optionally) print summary for only 1 out of every 100 */ - if (to_us && (fc & ~cpu_to_le16(IEEE80211_FCTL_PROTECTED)) == - cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FTYPE_DATA)) { - dataframe = 1; - if (!group100) - print_summary = 1; /* print each frame */ - else if (priv->framecnt_to_us < 100) { - priv->framecnt_to_us++; - print_summary = 0; - } else { - priv->framecnt_to_us = 0; - print_summary = 1; - hundred = 1; - } - } else { - /* print summary for all other frames */ - print_summary = 1; - } - - if (print_summary) { - char *title; - int rate_idx; - u32 bitrate; - - if (hundred) - title = "100Frames"; - else if (ieee80211_has_retry(fc)) - title = "Retry"; - else if (ieee80211_is_assoc_resp(fc)) - title = "AscRsp"; - else if (ieee80211_is_reassoc_resp(fc)) - title = "RasRsp"; - else if (ieee80211_is_probe_resp(fc)) { - title = "PrbRsp"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_beacon(fc)) { - title = "Beacon"; - print_dump = 1; /* dump frame contents */ - } else if (ieee80211_is_atim(fc)) - title = "ATIM"; - else if (ieee80211_is_auth(fc)) - title = "Auth"; - else if (ieee80211_is_deauth(fc)) - title = "DeAuth"; - else if (ieee80211_is_disassoc(fc)) - title = "DisAssoc"; - else - title = "Frame"; - - rate_idx = iwl_hwrate_to_plcp_idx(rate_n_flags); - if (unlikely((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT))) { - bitrate = 0; - WARN_ON_ONCE(1); - } else { - bitrate = iwl_rates[rate_idx].ieee / 2; - } - - /* print frame summary. - * MAC addresses show just the last byte (for brevity), - * but you can hack it to show more, if you'd like to. */ - if (dataframe) - IWL_DEBUG_RX(priv, "%s: mhd=0x%04x, dst=0x%02x, " - "len=%u, rssi=%d, chnl=%d, rate=%u, \n", - title, le16_to_cpu(fc), header->addr1[5], - length, rssi, channel, bitrate); - else { - /* src/dst addresses assume managed mode */ - IWL_DEBUG_RX(priv, "%s: 0x%04x, dst=0x%02x, src=0x%02x, " - "len=%u, rssi=%d, tim=%lu usec, " - "phy=0x%02x, chnl=%d\n", - title, le16_to_cpu(fc), header->addr1[5], - header->addr3[5], length, rssi, - tsf_low - priv->scan_start_tsf, - phy_flags, channel); - } - } - if (print_dump) - iwl_print_hex_dump(priv, IWL_DL_RX, header, length); -} -#endif - -/* - * returns non-zero if packet should be dropped - */ -int iwl_set_decrypted_flag(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - u32 decrypt_res, - struct ieee80211_rx_status *stats) -{ - u16 fc = le16_to_cpu(hdr->frame_control); - - if (priv->active_rxon.filter_flags & RXON_FILTER_DIS_DECRYPT_MSK) - return 0; - - if (!(fc & IEEE80211_FCTL_PROTECTED)) - return 0; - - IWL_DEBUG_RX(priv, "decrypt_res:0x%x\n", decrypt_res); - switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) { - case RX_RES_STATUS_SEC_TYPE_TKIP: - /* The uCode has got a bad phase 1 Key, pushes the packet. - * Decryption will be done in SW. */ - if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == - RX_RES_STATUS_BAD_KEY_TTAK) - break; - - case RX_RES_STATUS_SEC_TYPE_WEP: - if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == - RX_RES_STATUS_BAD_ICV_MIC) { - /* bad ICV, the packet is destroyed since the - * decryption is inplace, drop it */ - IWL_DEBUG_RX(priv, "Packet destroyed\n"); - return -1; - } - case RX_RES_STATUS_SEC_TYPE_CCMP: - if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) == - RX_RES_STATUS_DECRYPT_OK) { - IWL_DEBUG_RX(priv, "hw decrypt successfully!!!\n"); - stats->flag |= RX_FLAG_DECRYPTED; - } - break; - - default: - break; - } - return 0; -} -EXPORT_SYMBOL(iwl_set_decrypted_flag); - -static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in) -{ - u32 decrypt_out = 0; - - if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) == - RX_RES_STATUS_STATION_FOUND) - decrypt_out |= (RX_RES_STATUS_STATION_FOUND | - RX_RES_STATUS_NO_STATION_INFO_MISMATCH); - - decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK); - - /* packet was not encrypted */ - if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == - RX_RES_STATUS_SEC_TYPE_NONE) - return decrypt_out; - - /* packet was encrypted with unknown alg */ - if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) == - RX_RES_STATUS_SEC_TYPE_ERR) - return decrypt_out; - - /* decryption was not done in HW */ - if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) != - RX_MPDU_RES_STATUS_DEC_DONE_MSK) - return decrypt_out; - - switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) { - - case RX_RES_STATUS_SEC_TYPE_CCMP: - /* alg is CCM: check MIC only */ - if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK)) - /* Bad MIC */ - decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; - else - decrypt_out |= RX_RES_STATUS_DECRYPT_OK; - - break; - - case RX_RES_STATUS_SEC_TYPE_TKIP: - if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) { - /* Bad TTAK */ - decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK; - break; - } - /* fall through if TTAK OK */ - default: - if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK)) - decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC; - else - decrypt_out |= RX_RES_STATUS_DECRYPT_OK; - break; - }; - - IWL_DEBUG_RX(priv, "decrypt_in:0x%x decrypt_out = 0x%x\n", - decrypt_in, decrypt_out); - - return decrypt_out; -} - -static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - u16 len, - u32 ampdu_status, - struct iwl_rx_mem_buffer *rxb, - struct ieee80211_rx_status *stats) -{ - /* We only process data packets if the interface is open */ - if (unlikely(!priv->is_open)) { - IWL_DEBUG_DROP_LIMIT(priv, - "Dropping packet while interface is not open.\n"); - return; - } - - /* In case of HW accelerated crypto and bad decryption, drop */ - if (!priv->cfg->mod_params->sw_crypto && - iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats)) - return; - - /* Resize SKB from mac header to end of packet */ - skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data); - skb_put(rxb->skb, len); - - iwl_update_stats(priv, false, hdr->frame_control, len); - memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats)); - ieee80211_rx_irqsafe(priv->hw, rxb->skb); - priv->alloc_rxb_skb--; - rxb->skb = NULL; -} - -/* This is necessary only for a number of statistics, see the caller. */ -static int iwl_is_network_packet(struct iwl_priv *priv, - struct ieee80211_hdr *header) -{ - /* Filter incoming packets to determine if they are targeted toward - * this network, discarding packets coming from ourselves */ - switch (priv->iw_mode) { - case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source | BSSID */ - /* packets to our IBSS update information */ - return !compare_ether_addr(header->addr3, priv->bssid); - case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */ - /* packets to our IBSS update information */ - return !compare_ether_addr(header->addr2, priv->bssid); - default: - return 1; - } -} - -/* Called for REPLY_RX (legacy ABG frames), or - * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */ -void iwl_rx_reply_rx(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct ieee80211_hdr *header; - struct ieee80211_rx_status rx_status; - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_rx_phy_res *phy_res; - __le32 rx_pkt_status; - struct iwl4965_rx_mpdu_res_start *amsdu; - u32 len; - u32 ampdu_status; - u16 fc; - u32 rate_n_flags; - - /** - * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently. - * REPLY_RX: physical layer info is in this buffer - * REPLY_RX_MPDU_CMD: physical layer info was sent in separate - * command and cached in priv->last_phy_res - * - * Here we set up local variables depending on which command is - * received. - */ - if (pkt->hdr.cmd == REPLY_RX) { - phy_res = (struct iwl_rx_phy_res *)pkt->u.raw; - header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res) - + phy_res->cfg_phy_cnt); - - len = le16_to_cpu(phy_res->byte_count); - rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) + - phy_res->cfg_phy_cnt + len); - ampdu_status = le32_to_cpu(rx_pkt_status); - } else { - if (!priv->last_phy_res[0]) { - IWL_ERR(priv, "MPDU frame without cached PHY data\n"); - return; - } - phy_res = (struct iwl_rx_phy_res *)&priv->last_phy_res[1]; - amsdu = (struct iwl4965_rx_mpdu_res_start *)pkt->u.raw; - header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu)); - len = le16_to_cpu(amsdu->byte_count); - rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len); - ampdu_status = iwl_translate_rx_status(priv, - le32_to_cpu(rx_pkt_status)); - } - - if ((unlikely(phy_res->cfg_phy_cnt > 20))) { - IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n", - phy_res->cfg_phy_cnt); - return; - } - - if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) || - !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) { - IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", - le32_to_cpu(rx_pkt_status)); - return; - } - - /* This will be used in several places later */ - rate_n_flags = le32_to_cpu(phy_res->rate_n_flags); - - /* rx_status carries information about the packet to mac80211 */ - rx_status.mactime = le64_to_cpu(phy_res->timestamp); - rx_status.freq = - ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel)); - rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ? - IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ; - rx_status.rate_idx = - iwl_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band); - rx_status.flag = 0; - - /* TSF isn't reliable. In order to allow smooth user experience, - * this W/A doesn't propagate it to the mac80211 */ - /*rx_status.flag |= RX_FLAG_TSFT;*/ - - priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp); - - /* Find max signal strength (dBm) among 3 antenna/receiver chains */ - rx_status.signal = iwl_calc_rssi(priv, phy_res); - - /* Meaningful noise values are available only from beacon statistics, - * which are gathered only when associated, and indicate noise - * only for the associated network channel ... - * Ignore these noise values while scanning (other channels) */ - if (iwl_is_associated(priv) && - !test_bit(STATUS_SCANNING, &priv->status)) { - rx_status.noise = priv->last_rx_noise; - rx_status.qual = iwl_calc_sig_qual(rx_status.signal, - rx_status.noise); - } else { - rx_status.noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - rx_status.qual = iwl_calc_sig_qual(rx_status.signal, 0); - } - - /* Reset beacon noise level if not associated. */ - if (!iwl_is_associated(priv)) - priv->last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE; - -#ifdef CONFIG_IWLWIFI_DEBUG - /* Set "1" to report good data frames in groups of 100 */ - if (unlikely(iwl_get_debug_level(priv) & IWL_DL_RX)) - iwl_dbg_report_frame(priv, phy_res, len, header, 1); -#endif - iwl_dbg_log_rx_data_frame(priv, len, header); - IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, noise %d, qual %d, TSF %llu\n", - rx_status.signal, rx_status.noise, rx_status.qual, - (unsigned long long)rx_status.mactime); - - /* - * "antenna number" - * - * It seems that the antenna field in the phy flags value - * is actually a bit field. This is undefined by radiotap, - * it wants an actual antenna number but I always get "7" - * for most legacy frames I receive indicating that the - * same frame was received on all three RX chains. - * - * I think this field should be removed in favor of a - * new 802.11n radiotap field "RX chains" that is defined - * as a bitmask. - */ - rx_status.antenna = - (le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK) - >> RX_RES_PHY_FLAGS_ANTENNA_POS; - - /* set the preamble flag if appropriate */ - if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK) - rx_status.flag |= RX_FLAG_SHORTPRE; - - /* Set up the HT phy flags */ - if (rate_n_flags & RATE_MCS_HT_MSK) - rx_status.flag |= RX_FLAG_HT; - if (rate_n_flags & RATE_MCS_HT40_MSK) - rx_status.flag |= RX_FLAG_40MHZ; - if (rate_n_flags & RATE_MCS_SGI_MSK) - rx_status.flag |= RX_FLAG_SHORT_GI; - - if (iwl_is_network_packet(priv, header)) { - priv->last_rx_rssi = rx_status.signal; - priv->last_beacon_time = priv->ucode_beacon_time; - priv->last_tsf = le64_to_cpu(phy_res->timestamp); - } - - fc = le16_to_cpu(header->frame_control); - switch (fc & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_MGMT: - case IEEE80211_FTYPE_DATA: - if (priv->iw_mode == NL80211_IFTYPE_AP) - iwl_update_ps_mode(priv, fc & IEEE80211_FCTL_PM, - header->addr2); - /* fall through */ - default: - iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status, - rxb, &rx_status); - break; - - } -} -EXPORT_SYMBOL(iwl_rx_reply_rx); - -/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD). - * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */ -void iwl_rx_reply_rx_phy(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - priv->last_phy_res[0] = 1; - memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]), - sizeof(struct iwl_rx_phy_res)); -} -EXPORT_SYMBOL(iwl_rx_reply_rx_phy); diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c deleted file mode 100644 index faa286ff6939..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ /dev/null @@ -1,838 +0,0 @@ -/****************************************************************************** - * - * GPL LICENSE SUMMARY - * - * Copyright(c) 2008 - 2009 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, - * USA - * - * The full GNU General Public License is included in this distribution - * in the file called LICENSE.GPL. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - *****************************************************************************/ -#include -#include -#include -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-sta.h" -#include "iwl-io.h" -#include "iwl-helpers.h" - -/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after - * sending probe req. This should be set long enough to hear probe responses - * from more than one AP. */ -#define IWL_ACTIVE_DWELL_TIME_24 (30) /* all times in msec */ -#define IWL_ACTIVE_DWELL_TIME_52 (20) - -#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3) -#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2) - -/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel. - * Must be set longer than active dwell time. - * For the most reliable scan, set > AP beacon interval (typically 100msec). */ -#define IWL_PASSIVE_DWELL_TIME_24 (20) /* all times in msec */ -#define IWL_PASSIVE_DWELL_TIME_52 (10) -#define IWL_PASSIVE_DWELL_BASE (100) -#define IWL_CHANNEL_TUNE_TIME 5 - - - -/** - * iwl_scan_cancel - Cancel any currently executing HW scan - * - * NOTE: priv->mutex is not required before calling this function - */ -int iwl_scan_cancel(struct iwl_priv *priv) -{ - if (!test_bit(STATUS_SCAN_HW, &priv->status)) { - clear_bit(STATUS_SCANNING, &priv->status); - return 0; - } - - if (test_bit(STATUS_SCANNING, &priv->status)) { - if (!test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Queuing scan abort.\n"); - set_bit(STATUS_SCAN_ABORTING, &priv->status); - queue_work(priv->workqueue, &priv->abort_scan); - - } else - IWL_DEBUG_SCAN(priv, "Scan abort already in progress.\n"); - - return test_bit(STATUS_SCANNING, &priv->status); - } - - return 0; -} -EXPORT_SYMBOL(iwl_scan_cancel); -/** - * iwl_scan_cancel_timeout - Cancel any currently executing HW scan - * @ms: amount of time to wait (in milliseconds) for scan to abort - * - * NOTE: priv->mutex must be held before calling this function - */ -int iwl_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms) -{ - unsigned long now = jiffies; - int ret; - - ret = iwl_scan_cancel(priv); - if (ret && ms) { - mutex_unlock(&priv->mutex); - while (!time_after(jiffies, now + msecs_to_jiffies(ms)) && - test_bit(STATUS_SCANNING, &priv->status)) - msleep(1); - mutex_lock(&priv->mutex); - - return test_bit(STATUS_SCANNING, &priv->status); - } - - return ret; -} -EXPORT_SYMBOL(iwl_scan_cancel_timeout); - -static int iwl_send_scan_abort(struct iwl_priv *priv) -{ - int ret = 0; - struct iwl_rx_packet *res; - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_ABORT_CMD, - .flags = CMD_WANT_SKB, - }; - - /* If there isn't a scan actively going on in the hardware - * then we are in between scan bands and not actually - * actively scanning, so don't send the abort command */ - if (!test_bit(STATUS_SCAN_HW, &priv->status)) { - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - return 0; - } - - ret = iwl_send_cmd_sync(priv, &cmd); - if (ret) { - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - return ret; - } - - res = (struct iwl_rx_packet *)cmd.reply_skb->data; - if (res->u.status != CAN_ABORT_STATUS) { - /* The scan abort will return 1 for success or - * 2 for "failure". A failure condition can be - * due to simply not being in an active scan which - * can occur if we send the scan abort before we - * the microcode has notified us that a scan is - * completed. */ - IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - clear_bit(STATUS_SCAN_HW, &priv->status); - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.reply_skb); - - return ret; -} - -/* Service response to REPLY_SCAN_CMD (0x80) */ -static void iwl_rx_reply_scan(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_scanreq_notification *notif = - (struct iwl_scanreq_notification *)pkt->u.raw; - - IWL_DEBUG_RX(priv, "Scan request status = 0x%x\n", notif->status); -#endif -} - -/* Service SCAN_START_NOTIFICATION (0x82) */ -static void iwl_rx_scan_start_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_scanstart_notification *notif = - (struct iwl_scanstart_notification *)pkt->u.raw; - priv->scan_start_tsf = le32_to_cpu(notif->tsf_low); - IWL_DEBUG_SCAN(priv, "Scan start: " - "%d [802.11%s] " - "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n", - notif->channel, - notif->band ? "bg" : "a", - le32_to_cpu(notif->tsf_high), - le32_to_cpu(notif->tsf_low), - notif->status, notif->beacon_timer); -} - -/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ -static void iwl_rx_scan_results_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_scanresults_notification *notif = - (struct iwl_scanresults_notification *)pkt->u.raw; - - IWL_DEBUG_SCAN(priv, "Scan ch.res: " - "%d [802.11%s] " - "(TSF: 0x%08X:%08X) - %d " - "elapsed=%lu usec (%dms since last)\n", - notif->channel, - notif->band ? "bg" : "a", - le32_to_cpu(notif->tsf_high), - le32_to_cpu(notif->tsf_low), - le32_to_cpu(notif->statistics[0]), - le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf, - jiffies_to_msecs(elapsed_jiffies - (priv->last_scan_jiffies, jiffies))); -#endif - - priv->last_scan_jiffies = jiffies; - priv->next_scan_jiffies = 0; -} - -/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */ -static void iwl_rx_scan_complete_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw; - - IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n", - scan_notif->scanned_channels, - scan_notif->tsf_low, - scan_notif->tsf_high, scan_notif->status); -#endif - - /* The HW is no longer scanning */ - clear_bit(STATUS_SCAN_HW, &priv->status); - - IWL_DEBUG_INFO(priv, "Scan pass on %sGHz took %dms\n", - (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) ? - "2.4" : "5.2", - jiffies_to_msecs(elapsed_jiffies - (priv->scan_pass_start, jiffies))); - - /* Remove this scanned band from the list of pending - * bands to scan, band G precedes A in order of scanning - * as seen in iwl_bg_request_scan */ - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_2GHZ); - else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) - priv->scan_bands &= ~BIT(IEEE80211_BAND_5GHZ); - - /* If a request to abort was given, or the scan did not succeed - * then we reset the scan state machine and terminate, - * re-queuing another scan if one has been requested */ - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_INFO(priv, "Aborted scan completed.\n"); - clear_bit(STATUS_SCAN_ABORTING, &priv->status); - } else { - /* If there are more bands on this scan pass reschedule */ - if (priv->scan_bands) - goto reschedule; - } - - priv->last_scan_jiffies = jiffies; - priv->next_scan_jiffies = 0; - IWL_DEBUG_INFO(priv, "Setting scan to off\n"); - - clear_bit(STATUS_SCANNING, &priv->status); - - IWL_DEBUG_INFO(priv, "Scan took %dms\n", - jiffies_to_msecs(elapsed_jiffies(priv->scan_start, jiffies))); - - queue_work(priv->workqueue, &priv->scan_completed); - - return; - -reschedule: - priv->scan_pass_start = jiffies; - queue_work(priv->workqueue, &priv->request_scan); -} - -void iwl_setup_rx_scan_handlers(struct iwl_priv *priv) -{ - /* scan handlers */ - priv->rx_handlers[REPLY_SCAN_CMD] = iwl_rx_reply_scan; - priv->rx_handlers[SCAN_START_NOTIFICATION] = iwl_rx_scan_start_notif; - priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] = - iwl_rx_scan_results_notif; - priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] = - iwl_rx_scan_complete_notif; -} -EXPORT_SYMBOL(iwl_setup_rx_scan_handlers); - -inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band, - u8 n_probes) -{ - if (band == IEEE80211_BAND_5GHZ) - return IWL_ACTIVE_DWELL_TIME_52 + - IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1); - else - return IWL_ACTIVE_DWELL_TIME_24 + - IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1); -} -EXPORT_SYMBOL(iwl_get_active_dwell_time); - -u16 iwl_get_passive_dwell_time(struct iwl_priv *priv, - enum ieee80211_band band) -{ - u16 passive = (band == IEEE80211_BAND_2GHZ) ? - IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 : - IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52; - - if (iwl_is_associated(priv)) { - /* If we're associated, we clamp the maximum passive - * dwell time to be 98% of the beacon interval (minus - * 2 * channel tune time) */ - passive = priv->beacon_int; - if ((passive > IWL_PASSIVE_DWELL_BASE) || !passive) - passive = IWL_PASSIVE_DWELL_BASE; - passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2; - } - - return passive; -} -EXPORT_SYMBOL(iwl_get_passive_dwell_time); - -static int iwl_get_channels_for_scan(struct iwl_priv *priv, - enum ieee80211_band band, - u8 is_active, u8 n_probes, - struct iwl_scan_channel *scan_ch) -{ - struct ieee80211_channel *chan; - const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int added, i; - u16 channel; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) - return 0; - - active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl_get_passive_dwell_time(priv, band); - - if (passive_dwell <= active_dwell) - passive_dwell = active_dwell + 1; - - for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { - chan = priv->scan_request->channels[i]; - - if (chan->band != band) - continue; - - channel = ieee80211_frequency_to_channel(chan->center_freq); - scan_ch->channel = cpu_to_le16(channel); - - ch_info = iwl_get_channel_info(priv, band, channel); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", - channel); - continue; - } - - if (!is_active || is_channel_passive(ch_info) || - (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) - scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE; - else - scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; - - if (n_probes) - scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes); - - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - - /* Set txpower levels to defaults */ - scan_ch->dsp_atten = 110; - - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; - else - scan_ch->tx_gain = ((1 << 5) | (5 << 3)); - - IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n", - channel, le32_to_cpu(scan_ch->type), - (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? - "ACTIVE" : "PASSIVE", - (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ? - active_dwell : passive_dwell); - - scan_ch++; - added++; - } - - IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); - return added; -} - -void iwl_init_scan_params(struct iwl_priv *priv) -{ - u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1; - if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ]) - priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx; - if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ]) - priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; -} - -static int iwl_scan_initiate(struct iwl_priv *priv) -{ - IWL_DEBUG_INFO(priv, "Starting scan...\n"); - set_bit(STATUS_SCANNING, &priv->status); - priv->scan_start = jiffies; - priv->scan_pass_start = priv->scan_start; - - queue_work(priv->workqueue, &priv->request_scan); - - return 0; -} - -#define IWL_DELAY_NEXT_SCAN (HZ*2) - -int iwl_mac_hw_scan(struct ieee80211_hw *hw, - struct cfg80211_scan_request *req) -{ - unsigned long flags; - struct iwl_priv *priv = hw->priv; - int ret, i; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - mutex_lock(&priv->mutex); - spin_lock_irqsave(&priv->lock, flags); - - if (!iwl_is_ready_rf(priv)) { - ret = -EIO; - IWL_DEBUG_MAC80211(priv, "leave - not ready or exit pending\n"); - goto out_unlock; - } - - if (test_bit(STATUS_SCANNING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); - ret = -EAGAIN; - goto out_unlock; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); - ret = -EAGAIN; - goto out_unlock; - } - - /* We don't schedule scan within next_scan_jiffies period. - * Avoid scanning during possible EAPOL exchange, return - * success immediately. - */ - if (priv->next_scan_jiffies && - time_after(priv->next_scan_jiffies, jiffies)) { - IWL_DEBUG_SCAN(priv, "scan rejected: within next scan period\n"); - queue_work(priv->workqueue, &priv->scan_completed); - ret = 0; - goto out_unlock; - } - - /* if we just finished scan ask for delay */ - if (iwl_is_associated(priv) && priv->last_scan_jiffies && - time_after(priv->last_scan_jiffies + IWL_DELAY_NEXT_SCAN, jiffies)) { - IWL_DEBUG_SCAN(priv, "scan rejected: within previous scan period\n"); - queue_work(priv->workqueue, &priv->scan_completed); - ret = 0; - goto out_unlock; - } - - priv->scan_bands = 0; - for (i = 0; i < req->n_channels; i++) - priv->scan_bands |= BIT(req->channels[i]->band); - - priv->scan_request = req; - - ret = iwl_scan_initiate(priv); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - -out_unlock: - spin_unlock_irqrestore(&priv->lock, flags); - mutex_unlock(&priv->mutex); - - return ret; -} -EXPORT_SYMBOL(iwl_mac_hw_scan); - -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) - -void iwl_bg_scan_check(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, scan_check.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCANNING, &priv->status) && - !test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Scan completion watchdog (%dms)\n", - jiffies_to_msecs(IWL_SCAN_CHECK_WATCHDOG)); - - if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) - iwl_send_scan_abort(priv); - } - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL(iwl_bg_scan_check); - -/** - * iwl_fill_probe_req - fill in all required fields and IE for probe request - */ - -u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame, - const u8 *ies, int ie_len, int left) -{ - int len = 0; - u8 *pos = NULL; - - /* Make sure there is enough space for the probe request, - * two mandatory IEs and the data */ - left -= 24; - if (left < 0) - return 0; - - frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - memcpy(frame->da, iwl_bcast_addr, ETH_ALEN); - memcpy(frame->sa, priv->mac_addr, ETH_ALEN); - memcpy(frame->bssid, iwl_bcast_addr, ETH_ALEN); - frame->seq_ctrl = 0; - - len += 24; - - /* ...next IE... */ - pos = &frame->u.probe_req.variable[0]; - - /* fill in our indirect SSID IE */ - left -= 2; - if (left < 0) - return 0; - *pos++ = WLAN_EID_SSID; - *pos++ = 0; - - len += 2; - - if (WARN_ON(left < ie_len)) - return len; - - memcpy(pos, ies, ie_len); - len += ie_len; - left -= ie_len; - - return (u16)len; -} -EXPORT_SYMBOL(iwl_fill_probe_req); - -static void iwl_bg_request_scan(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, request_scan); - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_CMD, - .len = sizeof(struct iwl_scan_cmd), - .flags = CMD_SIZE_HUGE, - }; - struct iwl_scan_cmd *scan; - struct ieee80211_conf *conf = NULL; - int ret = 0; - u32 rate_flags = 0; - u16 cmd_len; - u16 rx_chain = 0; - enum ieee80211_band band; - u8 n_probes = 0; - u8 rx_ant = priv->hw_params.valid_rx_ant; - u8 rate; - bool is_active = false; - int chan_mod; - - conf = ieee80211_get_hw_conf(priv->hw); - - mutex_lock(&priv->mutex); - - cancel_delayed_work(&priv->scan_check); - - if (!iwl_is_ready(priv)) { - IWL_WARN(priv, "request scan called when driver not ready.\n"); - goto done; - } - - /* Make sure the scan wasn't canceled before this queued work - * was given the chance to run... */ - if (!test_bit(STATUS_SCANNING, &priv->status)) - goto done; - - /* This should never be called or scheduled if there is currently - * a scan active in the hardware. */ - if (test_bit(STATUS_SCAN_HW, &priv->status)) { - IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests in parallel. " - "Ignoring second request.\n"); - ret = -EIO; - goto done; - } - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); - goto done; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_HC(priv, "Scan request while abort pending. Queuing.\n"); - goto done; - } - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); - goto done; - } - - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_DEBUG_HC(priv, "Scan request while uninitialized. Queuing.\n"); - goto done; - } - - if (!priv->scan_bands) { - IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); - goto done; - } - - if (!priv->scan) { - priv->scan = kmalloc(sizeof(struct iwl_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan) { - ret = -ENOMEM; - goto done; - } - } - scan = priv->scan; - memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); - - scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; - scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - - if (iwl_is_associated(priv)) { - u16 interval = 0; - u32 extra; - u32 suspend_time = 100; - u32 scan_suspend_time = 100; - unsigned long flags; - - IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); - - spin_lock_irqsave(&priv->lock, flags); - interval = priv->beacon_int; - spin_unlock_irqrestore(&priv->lock, flags); - - scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(200 * 1024); - if (!interval) - interval = suspend_time; - - extra = (suspend_time / interval) << 22; - scan_suspend_time = (extra | - ((suspend_time % interval) * 1024)); - scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", - scan_suspend_time, interval); - } - - if (priv->scan_request->n_ssids) { - int i, p = 0; - IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - for (i = 0; i < priv->scan_request->n_ssids; i++) { - /* always does wildcard anyway */ - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; - } - is_active = true; - } else - IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); - - scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; - scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { - band = IEEE80211_BAND_2GHZ; - scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK) - >> RXON_FLG_CHANNEL_MODE_POS; - if (chan_mod == CHANNEL_MODE_PURE_40) { - rate = IWL_RATE_6M_PLCP; - } else { - rate = IWL_RATE_1M_PLCP; - rate_flags = RATE_MCS_CCK_MSK; - } - scan->good_CRC_th = 0; - } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { - band = IEEE80211_BAND_5GHZ; - rate = IWL_RATE_6M_PLCP; - /* - * If active scaning is requested but a certain channel - * is marked passive, we can do active scanning if we - * detect transmissions. - */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; - - /* Force use of chains B and C (0x6) for scan Rx for 4965 - * Avoid A (0x1) because of its off-channel reception on A-band. - */ - if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) - rx_ant = ANT_BC; - } else { - IWL_WARN(priv, "Invalid scan band count\n"); - goto done; - } - - priv->scan_tx_ant[band] = - iwl_toggle_tx_ant(priv, priv->scan_tx_ant[band]); - rate_flags |= iwl_ant_idx_to_flags(priv->scan_tx_ant[band]); - scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); - - /* MIMO is not used here, but value is required */ - rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS; - rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS; - rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; - rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; - scan->rx_chain = cpu_to_le16(rx_chain); - cmd_len = iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - priv->scan_request->ie, - priv->scan_request->ie_len, - IWL_MAX_SCAN_SIZE - sizeof(*scan)); - - scan->tx_cmd.len = cpu_to_le16(cmd_len); - - if (iwl_is_monitor_mode(priv)) - scan->filter_flags = RXON_FILTER_PROMISC_MSK; - - scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | - RXON_FILTER_BCON_AWARE_MSK); - - scan->channel_count = - iwl_get_channels_for_scan(priv, band, is_active, n_probes, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - - if (scan->channel_count == 0) { - IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); - goto done; - } - - cmd.len += le16_to_cpu(scan->tx_cmd.len) + - scan->channel_count * sizeof(struct iwl_scan_channel); - cmd.data = scan; - scan->len = cpu_to_le16(cmd.len); - - set_bit(STATUS_SCAN_HW, &priv->status); - ret = iwl_send_cmd_sync(priv, &cmd); - if (ret) - goto done; - - queue_delayed_work(priv->workqueue, &priv->scan_check, - IWL_SCAN_CHECK_WATCHDOG); - - mutex_unlock(&priv->mutex); - return; - - done: - /* Cannot perform scan. Make sure we clear scanning - * bits from status so next scan request can be performed. - * If we don't clear scanning status bit here all next scan - * will fail - */ - clear_bit(STATUS_SCAN_HW, &priv->status); - clear_bit(STATUS_SCANNING, &priv->status); - /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); - mutex_unlock(&priv->mutex); -} - -void iwl_bg_abort_scan(struct work_struct *work) -{ - struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan); - - if (!test_bit(STATUS_READY, &priv->status) || - !test_bit(STATUS_GEO_CONFIGURED, &priv->status)) - return; - - cancel_delayed_work(&priv->scan_check); - - mutex_lock(&priv->mutex); - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) - iwl_send_scan_abort(priv); - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL(iwl_bg_abort_scan); - -void iwl_bg_scan_completed(struct work_struct *work) -{ - struct iwl_priv *priv = - container_of(work, struct iwl_priv, scan_completed); - - IWL_DEBUG_SCAN(priv, "SCAN complete scan\n"); - - cancel_delayed_work(&priv->scan_check); - - ieee80211_scan_completed(priv->hw, false); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* Since setting the TXPOWER may have been deferred while - * performing the scan, fire one off */ - mutex_lock(&priv->mutex); - iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); - mutex_unlock(&priv->mutex); -} -EXPORT_SYMBOL(iwl_bg_scan_completed); - -void iwl_setup_scan_deferred_work(struct iwl_priv *priv) -{ - INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); - INIT_WORK(&priv->request_scan, iwl_bg_request_scan); - INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); - INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); -} -EXPORT_SYMBOL(iwl_setup_scan_deferred_work); - diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c deleted file mode 100644 index 022bcf115731..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c +++ /dev/null @@ -1,198 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-io.h" -#include "iwl-spectrum.h" - -#define BEACON_TIME_MASK_LOW 0x00FFFFFF -#define BEACON_TIME_MASK_HIGH 0xFF000000 -#define TIME_UNIT 1024 - -/* - * extended beacon time format - * time in usec will be changed into a 32-bit value in 8:24 format - * the high 1 byte is the beacon counts - * the lower 3 bytes is the time in usec within one beacon interval - */ - -/* TOOD: was used in sysfs debug interface need to add to mac */ -#if 0 -static u32 iwl_usecs_to_beacons(u32 usec, u32 beacon_interval) -{ - u32 quot; - u32 rem; - u32 interval = beacon_interval * 1024; - - if (!interval || !usec) - return 0; - - quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); - rem = (usec % interval) & BEACON_TIME_MASK_LOW; - - return (quot << 24) + rem; -} - -/* base is usually what we get from ucode with each received frame, - * the same as HW timer counter counting down - */ - -static __le32 iwl_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) -{ - u32 base_low = base & BEACON_TIME_MASK_LOW; - u32 addon_low = addon & BEACON_TIME_MASK_LOW; - u32 interval = beacon_interval * TIME_UNIT; - u32 res = (base & BEACON_TIME_MASK_HIGH) + - (addon & BEACON_TIME_MASK_HIGH); - - if (base_low > addon_low) - res += base_low - addon_low; - else if (base_low < addon_low) { - res += interval + base_low - addon_low; - res += (1 << 24); - } else - res += (1 << 24); - - return cpu_to_le32(res); -} -static int iwl_get_measurement(struct iwl_priv *priv, - struct ieee80211_measurement_params *params, - u8 type) -{ - struct iwl4965_spectrum_cmd spectrum; - struct iwl_rx_packet *res; - struct iwl_host_cmd cmd = { - .id = REPLY_SPECTRUM_MEASUREMENT_CMD, - .data = (void *)&spectrum, - .meta.flags = CMD_WANT_SKB, - }; - u32 add_time = le64_to_cpu(params->start_time); - int rc; - int spectrum_resp_status; - int duration = le16_to_cpu(params->duration); - - if (iwl_is_associated(priv)) - add_time = - iwl_usecs_to_beacons( - le64_to_cpu(params->start_time) - priv->last_tsf, - le16_to_cpu(priv->rxon_timing.beacon_interval)); - - memset(&spectrum, 0, sizeof(spectrum)); - - spectrum.channel_count = cpu_to_le16(1); - spectrum.flags = - RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; - spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; - cmd.len = sizeof(spectrum); - spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); - - if (iwl_is_associated(priv)) - spectrum.start_time = - iwl_add_beacon_time(priv->last_beacon_time, - add_time, - le16_to_cpu(priv->rxon_timing.beacon_interval)); - else - spectrum.start_time = 0; - - spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); - spectrum.channels[0].channel = params->channel; - spectrum.channels[0].type = type; - if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) - spectrum.flags |= RXON_FLG_BAND_24G_MSK | - RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl_rx_packet *)cmd.meta.u.skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); - rc = -EIO; - } - - spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); - switch (spectrum_resp_status) { - case 0: /* Command will be handled */ - if (res->u.spectrum.id != 0xff) { - IWL_DEBUG_INFO(priv, - "Replaced existing measurement: %d\n", - res->u.spectrum.id); - priv->measurement_status &= ~MEASUREMENT_READY; - } - priv->measurement_status |= MEASUREMENT_ACTIVE; - rc = 0; - break; - - case 1: /* Command will not be handled */ - rc = -EAGAIN; - break; - } - - dev_kfree_skb_any(cmd.meta.u.skb); - - return rc; -} -#endif - -static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif); - - if (!report->state) { - IWL_DEBUG_11H(priv, - "Spectrum Measure Notification: Start\n"); - return; - } - - memcpy(&priv->measure_report, report, sizeof(*report)); - priv->measurement_status |= MEASUREMENT_READY; -} - -void iwl_setup_spectrum_handlers(struct iwl_priv *priv) -{ - priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] = - iwl_rx_spectrum_measure_notif; -} -EXPORT_SYMBOL(iwl_setup_spectrum_handlers); diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.h b/drivers/net/wireless/iwlwifi/iwl-spectrum.h deleted file mode 100644 index a77c1e619062..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-spectrum.h +++ /dev/null @@ -1,92 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#ifndef __iwl_spectrum_h__ -#define __iwl_spectrum_h__ -enum { /* ieee80211_basic_report.map */ - IEEE80211_BASIC_MAP_BSS = (1 << 0), - IEEE80211_BASIC_MAP_OFDM = (1 << 1), - IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2), - IEEE80211_BASIC_MAP_RADAR = (1 << 3), - IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4), - /* Bits 5-7 are reserved */ - -}; -struct ieee80211_basic_report { - u8 channel; - __le64 start_time; - __le16 duration; - u8 map; -} __attribute__ ((packed)); - -enum { /* ieee80211_measurement_request.mode */ - /* Bit 0 is reserved */ - IEEE80211_MEASUREMENT_ENABLE = (1 << 1), - IEEE80211_MEASUREMENT_REQUEST = (1 << 2), - IEEE80211_MEASUREMENT_REPORT = (1 << 3), - /* Bits 4-7 are reserved */ -}; - -enum { - IEEE80211_REPORT_BASIC = 0, /* required */ - IEEE80211_REPORT_CCA = 1, /* optional */ - IEEE80211_REPORT_RPI = 2, /* optional */ - /* 3-255 reserved */ -}; - -struct ieee80211_measurement_params { - u8 channel; - __le64 start_time; - __le16 duration; -} __attribute__ ((packed)); - -struct ieee80211_info_element { - u8 id; - u8 len; - u8 data[0]; -} __attribute__ ((packed)); - -struct ieee80211_measurement_request { - struct ieee80211_info_element ie; - u8 token; - u8 mode; - u8 type; - struct ieee80211_measurement_params params[0]; -} __attribute__ ((packed)); - -struct ieee80211_measurement_report { - struct ieee80211_info_element ie; - u8 token; - u8 mode; - u8 type; - union { - struct ieee80211_basic_report basic[0]; - } u; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c deleted file mode 100644 index c6633fec8216..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-sta.c +++ /dev/null @@ -1,1197 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include - -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-sta.h" - -#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */ -#define IWL_STA_UCODE_ACTIVE BIT(1) /* ucode entry is active */ - -u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr) -{ - int i; - int start = 0; - int ret = IWL_INVALID_STATION; - unsigned long flags; - - if ((priv->iw_mode == NL80211_IFTYPE_ADHOC) || - (priv->iw_mode == NL80211_IFTYPE_AP)) - start = IWL_STA_ID; - - if (is_broadcast_ether_addr(addr)) - return priv->hw_params.bcast_sta_id; - - spin_lock_irqsave(&priv->sta_lock, flags); - for (i = start; i < priv->hw_params.max_stations; i++) - if (priv->stations[i].used && - (!compare_ether_addr(priv->stations[i].sta.sta.addr, - addr))) { - ret = i; - goto out; - } - - IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n", - addr, priv->num_stations); - - out: - spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; -} -EXPORT_SYMBOL(iwl_find_station); - -int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) -{ - if (priv->iw_mode == NL80211_IFTYPE_STATION) { - return IWL_AP_ID; - } else { - u8 *da = ieee80211_get_DA(hdr); - return iwl_find_station(priv, da); - } -} -EXPORT_SYMBOL(iwl_get_ra_sta_id); - -static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - - if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) - IWL_ERR(priv, "ACTIVATE a non DRIVER active station %d\n", - sta_id); - - priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE; - IWL_DEBUG_ASSOC(priv, "Added STA to Ucode: %pM\n", - priv->stations[sta_id].sta.sta.addr); - - spin_unlock_irqrestore(&priv->sta_lock, flags); -} - -static void iwl_add_sta_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb) -{ - struct iwl_rx_packet *res = NULL; - struct iwl_addsta_cmd *addsta = - (struct iwl_addsta_cmd *)cmd->cmd.payload; - u8 sta_id = addsta->sta.sta_id; - - if (!skb) { - IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n"); - return; - } - - res = (struct iwl_rx_packet *)skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", - res->hdr.flags); - return; - } - - switch (res->u.add_sta.status) { - case ADD_STA_SUCCESS_MSK: - iwl_sta_ucode_activate(priv, sta_id); - /* fall through */ - default: - IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n", - res->u.add_sta.status); - break; - } -} - -int iwl_send_add_sta(struct iwl_priv *priv, - struct iwl_addsta_cmd *sta, u8 flags) -{ - struct iwl_rx_packet *res = NULL; - int ret = 0; - u8 data[sizeof(*sta)]; - struct iwl_host_cmd cmd = { - .id = REPLY_ADD_STA, - .flags = flags, - .data = data, - }; - - if (flags & CMD_ASYNC) - cmd.callback = iwl_add_sta_callback; - else - cmd.flags |= CMD_WANT_SKB; - - cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data); - ret = iwl_send_cmd(priv, &cmd); - - if (ret || (flags & CMD_ASYNC)) - return ret; - - res = (struct iwl_rx_packet *)cmd.reply_skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n", - res->hdr.flags); - ret = -EIO; - } - - if (ret == 0) { - switch (res->u.add_sta.status) { - case ADD_STA_SUCCESS_MSK: - iwl_sta_ucode_activate(priv, sta->sta.sta_id); - IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n"); - break; - default: - ret = -EIO; - IWL_WARN(priv, "REPLY_ADD_STA failed\n"); - break; - } - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.reply_skb); - - return ret; -} -EXPORT_SYMBOL(iwl_send_add_sta); - -static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index, - struct ieee80211_sta_ht_cap *sta_ht_inf) -{ - __le32 sta_flags; - u8 mimo_ps_mode; - - if (!sta_ht_inf || !sta_ht_inf->ht_supported) - goto done; - - mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2; - - sta_flags = priv->stations[index].sta.station_flags; - - sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK); - - switch (mimo_ps_mode) { - case WLAN_HT_CAP_SM_PS_STATIC: - sta_flags |= STA_FLG_MIMO_DIS_MSK; - break; - case WLAN_HT_CAP_SM_PS_DYNAMIC: - sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK; - break; - case WLAN_HT_CAP_SM_PS_DISABLED: - break; - default: - IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode); - break; - } - - sta_flags |= cpu_to_le32( - (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS); - - sta_flags |= cpu_to_le32( - (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS); - - if (iwl_is_ht40_tx_allowed(priv, sta_ht_inf)) - sta_flags |= STA_FLG_HT40_EN_MSK; - else - sta_flags &= ~STA_FLG_HT40_EN_MSK; - - priv->stations[index].sta.station_flags = sta_flags; - done: - return; -} - -/** - * iwl_add_station - Add station to tables in driver and device - */ -u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, - struct ieee80211_sta_ht_cap *ht_info) -{ - struct iwl_station_entry *station; - unsigned long flags_spin; - int i; - int sta_id = IWL_INVALID_STATION; - u16 rate; - - spin_lock_irqsave(&priv->sta_lock, flags_spin); - if (is_ap) - sta_id = IWL_AP_ID; - else if (is_broadcast_ether_addr(addr)) - sta_id = priv->hw_params.bcast_sta_id; - else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) { - if (!compare_ether_addr(priv->stations[i].sta.sta.addr, - addr)) { - sta_id = i; - break; - } - - if (!priv->stations[i].used && - sta_id == IWL_INVALID_STATION) - sta_id = i; - } - - /* These two conditions have the same outcome, but keep them separate - since they have different meanings */ - if (unlikely(sta_id == IWL_INVALID_STATION)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - return sta_id; - } - - if (priv->stations[sta_id].used && - !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) { - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - return sta_id; - } - - - station = &priv->stations[sta_id]; - station->used = IWL_STA_DRIVER_ACTIVE; - IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n", - sta_id, addr); - priv->num_stations++; - - /* Set up the REPLY_ADD_STA command to send to device */ - memset(&station->sta, 0, sizeof(struct iwl_addsta_cmd)); - memcpy(station->sta.sta.addr, addr, ETH_ALEN); - station->sta.mode = 0; - station->sta.sta.sta_id = sta_id; - station->sta.station_flags = 0; - - /* BCAST station and IBSS stations do not work in HT mode */ - if (sta_id != priv->hw_params.bcast_sta_id && - priv->iw_mode != NL80211_IFTYPE_ADHOC) - iwl_set_ht_add_station(priv, sta_id, ht_info); - - /* 3945 only */ - rate = (priv->band == IEEE80211_BAND_5GHZ) ? - IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP; - /* Turn on both antennas for the station... */ - station->sta.rate_n_flags = cpu_to_le16(rate | RATE_MCS_ANT_AB_MSK); - - spin_unlock_irqrestore(&priv->sta_lock, flags_spin); - - /* Add station to device's station table */ - iwl_send_add_sta(priv, &station->sta, flags); - return sta_id; - -} -EXPORT_SYMBOL(iwl_add_station); - -static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr) -{ - unsigned long flags; - u8 sta_id = iwl_find_station(priv, addr); - - BUG_ON(sta_id == IWL_INVALID_STATION); - - IWL_DEBUG_ASSOC(priv, "Removed STA from Ucode: %pM\n", addr); - - spin_lock_irqsave(&priv->sta_lock, flags); - - /* Ucode must be active and driver must be non active */ - if (priv->stations[sta_id].used != IWL_STA_UCODE_ACTIVE) - IWL_ERR(priv, "removed non active STA %d\n", sta_id); - - priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE; - - memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry)); - spin_unlock_irqrestore(&priv->sta_lock, flags); -} - -static void iwl_remove_sta_callback(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct sk_buff *skb) -{ - struct iwl_rx_packet *res = NULL; - struct iwl_rem_sta_cmd *rm_sta = - (struct iwl_rem_sta_cmd *)cmd->cmd.payload; - const char *addr = rm_sta->addr; - - if (!skb) { - IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n"); - return; - } - - res = (struct iwl_rx_packet *)skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", - res->hdr.flags); - return; - } - - switch (res->u.rem_sta.status) { - case REM_STA_SUCCESS_MSK: - iwl_sta_ucode_deactivate(priv, addr); - break; - default: - IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); - break; - } -} - -static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr, - u8 flags) -{ - struct iwl_rx_packet *res = NULL; - int ret; - - struct iwl_rem_sta_cmd rm_sta_cmd; - - struct iwl_host_cmd cmd = { - .id = REPLY_REMOVE_STA, - .len = sizeof(struct iwl_rem_sta_cmd), - .flags = flags, - .data = &rm_sta_cmd, - }; - - memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd)); - rm_sta_cmd.num_sta = 1; - memcpy(&rm_sta_cmd.addr, addr , ETH_ALEN); - - if (flags & CMD_ASYNC) - cmd.callback = iwl_remove_sta_callback; - else - cmd.flags |= CMD_WANT_SKB; - ret = iwl_send_cmd(priv, &cmd); - - if (ret || (flags & CMD_ASYNC)) - return ret; - - res = (struct iwl_rx_packet *)cmd.reply_skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n", - res->hdr.flags); - ret = -EIO; - } - - if (!ret) { - switch (res->u.rem_sta.status) { - case REM_STA_SUCCESS_MSK: - iwl_sta_ucode_deactivate(priv, addr); - IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n"); - break; - default: - ret = -EIO; - IWL_ERR(priv, "REPLY_REMOVE_STA failed\n"); - break; - } - } - - priv->alloc_rxb_skb--; - dev_kfree_skb_any(cmd.reply_skb); - - return ret; -} - -/** - * iwl_remove_station - Remove driver's knowledge of station. - */ -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) -{ - int sta_id = IWL_INVALID_STATION; - int i, ret = -EINVAL; - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - - if (is_ap) - sta_id = IWL_AP_ID; - else if (is_broadcast_ether_addr(addr)) - sta_id = priv->hw_params.bcast_sta_id; - else - for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) - if (priv->stations[i].used && - !compare_ether_addr(priv->stations[i].sta.sta.addr, - addr)) { - sta_id = i; - break; - } - - if (unlikely(sta_id == IWL_INVALID_STATION)) - goto out; - - IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d %pM\n", - sta_id, addr); - - if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) { - IWL_ERR(priv, "Removing %pM but non DRIVER active\n", - addr); - goto out; - } - - if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) { - IWL_ERR(priv, "Removing %pM but non UCODE active\n", - addr); - goto out; - } - - - priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE; - - priv->num_stations--; - - BUG_ON(priv->num_stations < 0); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - ret = iwl_send_remove_station(priv, addr, CMD_ASYNC); - return ret; -out: - spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; -} - -/** - * iwl_clear_stations_table - Clear the driver's station table - * - * NOTE: This does not clear or otherwise alter the device's station table. - */ -void iwl_clear_stations_table(struct iwl_priv *priv) -{ - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->sta_lock, flags); - - if (iwl_is_alive(priv) && - !test_bit(STATUS_EXIT_PENDING, &priv->status) && - iwl_send_cmd_pdu_async(priv, REPLY_REMOVE_ALL_STA, 0, NULL, NULL)) - IWL_ERR(priv, "Couldn't clear the station table\n"); - - priv->num_stations = 0; - memset(priv->stations, 0, sizeof(priv->stations)); - - /* clean ucode key table bit map */ - priv->ucode_key_table = 0; - - /* keep track of static keys */ - for (i = 0; i < WEP_KEYS_MAX ; i++) { - if (priv->wep_keys[i].key_size) - set_bit(i, &priv->ucode_key_table); - } - - spin_unlock_irqrestore(&priv->sta_lock, flags); -} -EXPORT_SYMBOL(iwl_clear_stations_table); - -int iwl_get_free_ucode_key_index(struct iwl_priv *priv) -{ - int i; - - for (i = 0; i < STA_KEY_MAX_NUM; i++) - if (!test_and_set_bit(i, &priv->ucode_key_table)) - return i; - - return WEP_INVALID_OFFSET; -} -EXPORT_SYMBOL(iwl_get_free_ucode_key_index); - -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty) -{ - int i, not_empty = 0; - u8 buff[sizeof(struct iwl_wep_cmd) + - sizeof(struct iwl_wep_key) * WEP_KEYS_MAX]; - struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff; - size_t cmd_size = sizeof(struct iwl_wep_cmd); - struct iwl_host_cmd cmd = { - .id = REPLY_WEPKEY, - .data = wep_cmd, - .flags = CMD_ASYNC, - }; - - memset(wep_cmd, 0, cmd_size + - (sizeof(struct iwl_wep_key) * WEP_KEYS_MAX)); - - for (i = 0; i < WEP_KEYS_MAX ; i++) { - wep_cmd->key[i].key_index = i; - if (priv->wep_keys[i].key_size) { - wep_cmd->key[i].key_offset = i; - not_empty = 1; - } else { - wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET; - } - - wep_cmd->key[i].key_size = priv->wep_keys[i].key_size; - memcpy(&wep_cmd->key[i].key[3], priv->wep_keys[i].key, - priv->wep_keys[i].key_size); - } - - wep_cmd->global_key_type = WEP_KEY_WEP_TYPE; - wep_cmd->num_keys = WEP_KEYS_MAX; - - cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX; - - cmd.len = cmd_size; - - if (not_empty || send_if_empty) - return iwl_send_cmd(priv, &cmd); - else - return 0; -} -EXPORT_SYMBOL(iwl_send_static_wepkey_cmd); - -int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf) -{ - int ret; - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n", - keyconf->keyidx); - - if (!test_and_clear_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERR(priv, "index %d not used in uCode key table.\n", - keyconf->keyidx); - - priv->default_wep_key--; - memset(&priv->wep_keys[keyconf->keyidx], 0, sizeof(priv->wep_keys[0])); - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_WEP(priv, "Not sending REPLY_WEPKEY command due to RFKILL.\n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - ret = iwl_send_static_wepkey_cmd(priv, 1); - IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n", - keyconf->keyidx, ret); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} -EXPORT_SYMBOL(iwl_remove_default_wep_key); - -int iwl_set_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf) -{ - int ret; - unsigned long flags; - - if (keyconf->keylen != WEP_KEY_LEN_128 && - keyconf->keylen != WEP_KEY_LEN_64) { - IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen); - return -EINVAL; - } - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = HW_KEY_DEFAULT; - priv->stations[IWL_AP_ID].keyinfo.alg = ALG_WEP; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->default_wep_key++; - - if (test_and_set_bit(keyconf->keyidx, &priv->ucode_key_table)) - IWL_ERR(priv, "index %d already used in uCode key table.\n", - keyconf->keyidx); - - priv->wep_keys[keyconf->keyidx].key_size = keyconf->keylen; - memcpy(&priv->wep_keys[keyconf->keyidx].key, &keyconf->key, - keyconf->keylen); - - ret = iwl_send_static_wepkey_cmd(priv, 0); - IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n", - keyconf->keylen, keyconf->keyidx, ret); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} -EXPORT_SYMBOL(iwl_set_default_wep_key); - -static int iwl_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - int ret; - - keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV; - - key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (keyconf->keylen == WEP_KEY_LEN_128) - key_flags |= STA_KEY_FLG_KEY_SIZE_MSK; - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx; - - memcpy(priv->stations[sta_id].keyinfo.key, - keyconf->key, keyconf->keylen); - - memcpy(&priv->stations[sta_id].sta.key.key[3], - keyconf->key, keyconf->keylen); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -static int iwl_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - int ret; - - key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, - keyconf->keylen); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, - keyconf->keylen); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -static int iwl_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - int ret = 0; - __le16 key_flags = 0; - - key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - key_flags &= ~STA_KEY_FLG_INVALID; - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = 16; - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; - - - /* This copy is acutally not needed: we get the key with each TX */ - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -void iwl_update_tkip_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - const u8 *addr, u32 iv32, u16 *phase1key) -{ - u8 sta_id = IWL_INVALID_STATION; - unsigned long flags; - int i; - - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - addr); - return; - } - - if (iwl_scan_cancel(priv)) { - /* cancel scan failed, just live w/ bad key and rely - briefly on SW decryption */ - return; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - - priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32; - - for (i = 0; i < 5; i++) - priv->stations[sta_id].sta.key.tkip_rx_ttak[i] = - cpu_to_le16(phase1key[i]); - - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - -} -EXPORT_SYMBOL(iwl_update_tkip_key); - -int iwl_remove_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - int ret = 0; - u16 key_flags; - u8 keyidx; - - priv->key_mapping_key--; - - spin_lock_irqsave(&priv->sta_lock, flags); - key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags); - keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3; - - IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n", - keyconf->keyidx, sta_id); - - if (keyconf->keyidx != keyidx) { - /* We need to remove a key with index different that the one - * in the uCode. This means that the key we need to remove has - * been replaced by another one with different index. - * Don't do anything and return ok - */ - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - - if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) { - IWL_WARN(priv, "Removing wrong key %d 0x%x\n", - keyconf->keyidx, key_flags); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - - if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset, - &priv->ucode_key_table)) - IWL_ERR(priv, "index %d not used in uCode key table.\n", - priv->stations[sta_id].sta.key.key_offset); - memset(&priv->stations[sta_id].keyinfo, 0, - sizeof(struct iwl_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, - sizeof(struct iwl4965_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = - STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID; - priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_WEP(priv, "Not sending REPLY_ADD_STA command because RFKILL enabled. \n"); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return 0; - } - ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - spin_unlock_irqrestore(&priv->sta_lock, flags); - return ret; -} -EXPORT_SYMBOL(iwl_remove_dynamic_key); - -int iwl_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, u8 sta_id) -{ - int ret; - - priv->key_mapping_key++; - keyconf->hw_key_idx = HW_KEY_DYNAMIC; - - switch (keyconf->alg) { - case ALG_CCMP: - ret = iwl_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); - break; - case ALG_TKIP: - ret = iwl_set_tkip_dynamic_key_info(priv, keyconf, sta_id); - break; - case ALG_WEP: - ret = iwl_set_wep_dynamic_key_info(priv, keyconf, sta_id); - break; - default: - IWL_ERR(priv, - "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); - ret = -EINVAL; - } - - IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", - keyconf->alg, keyconf->keylen, keyconf->keyidx, - sta_id, ret); - - return ret; -} -EXPORT_SYMBOL(iwl_set_dynamic_key); - -#ifdef CONFIG_IWLWIFI_DEBUG -static void iwl_dump_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq) -{ - int i; - IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id); - IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n", - lq->general_params.single_stream_ant_msk, - lq->general_params.dual_stream_ant_msk); - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) - IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n", - i, lq->rs_table[i].rate_n_flags); -} -#else -static inline void iwl_dump_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq) -{ -} -#endif - -int iwl_send_lq_cmd(struct iwl_priv *priv, - struct iwl_link_quality_cmd *lq, u8 flags) -{ - struct iwl_host_cmd cmd = { - .id = REPLY_TX_LINK_QUALITY_CMD, - .len = sizeof(struct iwl_link_quality_cmd), - .flags = flags, - .data = lq, - }; - - if ((lq->sta_id == 0xFF) && - (priv->iw_mode == NL80211_IFTYPE_ADHOC)) - return -EINVAL; - - if (lq->sta_id == 0xFF) - lq->sta_id = IWL_AP_ID; - - iwl_dump_lq_cmd(priv, lq); - - if (iwl_is_associated(priv) && priv->assoc_station_added) - return iwl_send_cmd(priv, &cmd); - - return 0; -} -EXPORT_SYMBOL(iwl_send_lq_cmd); - -/** - * iwl_sta_init_lq - Initialize a station's hardware rate table - * - * The uCode's station table contains a table of fallback rates - * for automatic fallback during transmission. - * - * NOTE: This sets up a default set of values. These will be replaced later - * if the driver's iwl-agn-rs rate scaling algorithm is used, instead of - * rc80211_simple. - * - * NOTE: Run REPLY_ADD_STA command to set up station table entry, before - * calling this function (which runs REPLY_TX_LINK_QUALITY_CMD, - * which requires station table entry to exist). - */ -static void iwl_sta_init_lq(struct iwl_priv *priv, const u8 *addr, bool is_ap) -{ - int i, r; - struct iwl_link_quality_cmd link_cmd = { - .reserved1 = 0, - }; - u32 rate_flags; - - /* Set up the rate scaling to start at selected rate, fall back - * all the way down to 1M in IEEE order, and then spin on 1M */ - if (is_ap) - r = IWL_RATE_54M_INDEX; - else if (priv->band == IEEE80211_BAND_5GHZ) - r = IWL_RATE_6M_INDEX; - else - r = IWL_RATE_1M_INDEX; - - for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) { - rate_flags = 0; - if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE) - rate_flags |= RATE_MCS_CCK_MSK; - - rate_flags |= first_antenna(priv->hw_params.valid_tx_ant) << - RATE_MCS_ANT_POS; - - link_cmd.rs_table[i].rate_n_flags = - iwl_hw_set_rate_n_flags(iwl_rates[r].plcp, rate_flags); - r = iwl_get_prev_ieee_rate(r); - } - - link_cmd.general_params.single_stream_ant_msk = - first_antenna(priv->hw_params.valid_tx_ant); - link_cmd.general_params.dual_stream_ant_msk = 3; - link_cmd.agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF; - link_cmd.agg_params.agg_time_limit = - cpu_to_le16(LINK_QUAL_AGG_TIME_LIMIT_DEF); - - /* Update the rate scaling for control frame Tx to AP */ - link_cmd.sta_id = is_ap ? IWL_AP_ID : priv->hw_params.bcast_sta_id; - - iwl_send_cmd_pdu_async(priv, REPLY_TX_LINK_QUALITY_CMD, - sizeof(link_cmd), &link_cmd, NULL); -} - -/** - * iwl_rxon_add_station - add station into station table. - * - * there is only one AP station with id= IWL_AP_ID - * NOTE: mutex must be held before calling this function - */ -int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap) -{ - struct ieee80211_sta *sta; - struct ieee80211_sta_ht_cap ht_config; - struct ieee80211_sta_ht_cap *cur_ht_config = NULL; - u8 sta_id; - - /* Add station to device's station table */ - - /* - * XXX: This check is definitely not correct, if we're an AP - * it'll always be false which is not what we want, but - * it doesn't look like iwlagn is prepared to be an HT - * AP anyway. - */ - if (priv->current_ht_config.is_ht) { - rcu_read_lock(); - sta = ieee80211_find_sta(priv->hw, addr); - if (sta) { - memcpy(&ht_config, &sta->ht_cap, sizeof(ht_config)); - cur_ht_config = &ht_config; - } - rcu_read_unlock(); - } - - sta_id = iwl_add_station(priv, addr, is_ap, CMD_SYNC, cur_ht_config); - - /* Set up default rate scaling table in device's station table */ - iwl_sta_init_lq(priv, addr, is_ap); - - return sta_id; -} -EXPORT_SYMBOL(iwl_rxon_add_station); - -/** - * iwl_get_sta_id - Find station's index within station table - * - * If new IBSS station, create new entry in station table - */ -int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr) -{ - int sta_id; - __le16 fc = hdr->frame_control; - - /* If this frame is broadcast or management, use broadcast station id */ - if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) - return priv->hw_params.bcast_sta_id; - - switch (priv->iw_mode) { - - /* If we are a client station in a BSS network, use the special - * AP station entry (that's the only station we communicate with) */ - case NL80211_IFTYPE_STATION: - return IWL_AP_ID; - - /* If we are an AP, then find the station, or use BCAST */ - case NL80211_IFTYPE_AP: - sta_id = iwl_find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - return priv->hw_params.bcast_sta_id; - - /* If this frame is going out to an IBSS network, find the station, - * or create a new station table entry */ - case NL80211_IFTYPE_ADHOC: - sta_id = iwl_find_station(priv, hdr->addr1); - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - /* Create new station table entry */ - sta_id = iwl_add_station(priv, hdr->addr1, false, - CMD_ASYNC, NULL); - - if (sta_id != IWL_INVALID_STATION) - return sta_id; - - IWL_DEBUG_DROP(priv, "Station %pM not in station map. " - "Defaulting to broadcast...\n", - hdr->addr1); - iwl_print_hex_dump(priv, IWL_DL_DROP, (u8 *) hdr, sizeof(*hdr)); - return priv->hw_params.bcast_sta_id; - - default: - IWL_WARN(priv, "Unknown mode of operation: %d\n", - priv->iw_mode); - return priv->hw_params.bcast_sta_id; - } -} -EXPORT_SYMBOL(iwl_get_sta_id); - -/** - * iwl_sta_tx_modify_enable_tid - Enable Tx for this TID in station table - */ -void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid) -{ - unsigned long flags; - - /* Remove "disable" flag, to enable Tx for this TID */ - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX; - priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid)); - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); -} -EXPORT_SYMBOL(iwl_sta_tx_modify_enable_tid); - -int iwl_sta_rx_agg_start(struct iwl_priv *priv, - const u8 *addr, int tid, u16 ssn) -{ - unsigned long flags; - int sta_id; - - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) - return -ENXIO; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags_msk = 0; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK; - priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid; - priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn); - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, - CMD_ASYNC); -} -EXPORT_SYMBOL(iwl_sta_rx_agg_start); - -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid) -{ - unsigned long flags; - int sta_id; - - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); - return -ENXIO; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags_msk = 0; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK; - priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return iwl_send_add_sta(priv, &priv->stations[sta_id].sta, - CMD_ASYNC); -} -EXPORT_SYMBOL(iwl_sta_rx_agg_stop); - -static void iwl_sta_modify_ps_wake(struct iwl_priv *priv, int sta_id) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].sta.station_flags &= ~STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK; - priv->stations[sta_id].sta.sta.modify_mask = 0; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); -} - -void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr) -{ - /* FIXME: need locking over ps_status ??? */ - u8 sta_id = iwl_find_station(priv, addr); - - if (sta_id != IWL_INVALID_STATION) { - u8 sta_awake = priv->stations[sta_id]. - ps_status == STA_PS_STATUS_WAKE; - - if (sta_awake && ps_bit) - priv->stations[sta_id].ps_status = STA_PS_STATUS_SLEEP; - else if (!sta_awake && !ps_bit) { - iwl_sta_modify_ps_wake(priv, sta_id); - priv->stations[sta_id].ps_status = STA_PS_STATUS_WAKE; - } - } -} - diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.h b/drivers/net/wireless/iwlwifi/iwl-sta.h deleted file mode 100644 index 6deebade6361..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-sta.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ -#ifndef __iwl_sta_h__ -#define __iwl_sta_h__ - -#define HW_KEY_DYNAMIC 0 -#define HW_KEY_DEFAULT 1 - -/** - * iwl_find_station - Find station id for a given BSSID - * @bssid: MAC address of station ID to find - */ -u8 iwl_find_station(struct iwl_priv *priv, const u8 *bssid); - -int iwl_send_static_wepkey_cmd(struct iwl_priv *priv, u8 send_if_empty); -int iwl_remove_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key); -int iwl_set_default_wep_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key); -int iwl_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id); -int iwl_remove_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key, u8 sta_id); -void iwl_update_tkip_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - const u8 *addr, u32 iv32, u16 *phase1key); - -int iwl_rxon_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); -int iwl_remove_station(struct iwl_priv *priv, const u8 *addr, bool is_ap); -void iwl_clear_stations_table(struct iwl_priv *priv); -int iwl_get_free_ucode_key_index(struct iwl_priv *priv); -int iwl_get_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); -int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr); -int iwl_send_add_sta(struct iwl_priv *priv, - struct iwl_addsta_cmd *sta, u8 flags); -u8 iwl_add_station(struct iwl_priv *priv, const u8 *addr, bool is_ap, u8 flags, - struct ieee80211_sta_ht_cap *ht_info); -void iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid); -int iwl_sta_rx_agg_start(struct iwl_priv *priv, - const u8 *addr, int tid, u16 ssn); -int iwl_sta_rx_agg_stop(struct iwl_priv *priv, const u8 *addr, int tid); -void iwl_update_ps_mode(struct iwl_priv *priv, u16 ps_bit, u8 *addr); -#endif /* __iwl_sta_h__ */ diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c deleted file mode 100644 index d21c06ea0ec3..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ /dev/null @@ -1,1559 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include "iwl-eeprom.h" -#include "iwl-dev.h" -#include "iwl-core.h" -#include "iwl-sta.h" -#include "iwl-io.h" -#include "iwl-helpers.h" - -static const u16 default_tid_to_tx_fifo[] = { - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC0, - IWL_TX_FIFO_AC0, - IWL_TX_FIFO_AC1, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC2, - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_AC3, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_NONE, - IWL_TX_FIFO_AC3 -}; - -static inline int iwl_alloc_dma_ptr(struct iwl_priv *priv, - struct iwl_dma_ptr *ptr, size_t size) -{ - ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma, - GFP_KERNEL); - if (!ptr->addr) - return -ENOMEM; - ptr->size = size; - return 0; -} - -static inline void iwl_free_dma_ptr(struct iwl_priv *priv, - struct iwl_dma_ptr *ptr) -{ - if (unlikely(!ptr->addr)) - return; - - dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma); - memset(ptr, 0, sizeof(*ptr)); -} - -/** - * iwl_txq_update_write_ptr - Send new write index to hardware - */ -int iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) -{ - u32 reg = 0; - int ret = 0; - int txq_id = txq->q.id; - - if (txq->need_update == 0) - return ret; - - /* if we're trying to save power */ - if (test_bit(STATUS_POWER_PMI, &priv->status)) { - /* wake up nic if it's powered down ... - * uCode will wake up, and interrupt us again, so next - * time we'll skip this part. */ - reg = iwl_read32(priv, CSR_UCODE_DRV_GP1); - - if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) { - IWL_DEBUG_INFO(priv, "Requesting wakeup, GP1 = 0x%x\n", reg); - iwl_set_bit(priv, CSR_GP_CNTRL, - CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - return ret; - } - - iwl_write_direct32(priv, HBUS_TARG_WRPTR, - txq->q.write_ptr | (txq_id << 8)); - - /* else not in power-save mode, uCode will never sleep when we're - * trying to tx (during RFKILL, we're not trying to tx). */ - } else - iwl_write32(priv, HBUS_TARG_WRPTR, - txq->q.write_ptr | (txq_id << 8)); - - txq->need_update = 0; - - return ret; -} -EXPORT_SYMBOL(iwl_txq_update_write_ptr); - - -void iwl_free_tfds_in_queue(struct iwl_priv *priv, - int sta_id, int tid, int freed) -{ - if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed) - priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; - else { - IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n", - priv->stations[sta_id].tid[tid].tfds_in_queue, - freed); - priv->stations[sta_id].tid[tid].tfds_in_queue = 0; - } -} -EXPORT_SYMBOL(iwl_free_tfds_in_queue); - -/** - * iwl_tx_queue_free - Deallocate DMA queue. - * @txq: Transmit queue to deallocate. - * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * 0-fill, but do not free "txq" descriptor structure. - */ -void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - struct device *dev = &priv->pci_dev->dev; - int i, len; - - if (q->n_bd == 0) - return; - - /* first, empty all BD's */ - for (; q->write_ptr != q->read_ptr; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) - priv->cfg->ops->lib->txq_free_tfd(priv, txq); - - len = sizeof(struct iwl_device_cmd) * q->n_window; - - /* De-alloc array of command/tx buffers */ - for (i = 0; i < TFD_TX_CMD_SLOTS; i++) - kfree(txq->cmd[i]); - - /* De-alloc circular buffer of TFDs */ - if (txq->q.n_bd) - dma_free_coherent(dev, priv->hw_params.tfd_size * - txq->q.n_bd, txq->tfds, txq->q.dma_addr); - - /* De-alloc array of per-TFD driver data */ - kfree(txq->txb); - txq->txb = NULL; - - /* deallocate arrays */ - kfree(txq->cmd); - kfree(txq->meta); - txq->cmd = NULL; - txq->meta = NULL; - - /* 0-fill queue descriptor structure */ - memset(txq, 0, sizeof(*txq)); -} -EXPORT_SYMBOL(iwl_tx_queue_free); - -/** - * iwl_cmd_queue_free - Deallocate DMA queue. - * @txq: Transmit queue to deallocate. - * - * Empty queue by removing and destroying all BD's. - * Free all buffers. - * 0-fill, but do not free "txq" descriptor structure. - */ -void iwl_cmd_queue_free(struct iwl_priv *priv) -{ - struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; - struct iwl_queue *q = &txq->q; - struct device *dev = &priv->pci_dev->dev; - int i, len; - - if (q->n_bd == 0) - return; - - len = sizeof(struct iwl_device_cmd) * q->n_window; - len += IWL_MAX_SCAN_SIZE; - - /* De-alloc array of command/tx buffers */ - for (i = 0; i <= TFD_CMD_SLOTS; i++) - kfree(txq->cmd[i]); - - /* De-alloc circular buffer of TFDs */ - if (txq->q.n_bd) - dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd, - txq->tfds, txq->q.dma_addr); - - /* deallocate arrays */ - kfree(txq->cmd); - kfree(txq->meta); - txq->cmd = NULL; - txq->meta = NULL; - - /* 0-fill queue descriptor structure */ - memset(txq, 0, sizeof(*txq)); -} -EXPORT_SYMBOL(iwl_cmd_queue_free); - -/*************** DMA-QUEUE-GENERAL-FUNCTIONS ***** - * DMA services - * - * Theory of operation - * - * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer - * of buffer descriptors, each of which points to one or more data buffers for - * the device to read from or fill. Driver and device exchange status of each - * queue via "read" and "write" pointers. Driver keeps minimum of 2 empty - * entries in each circular buffer, to protect against confusing empty and full - * queue states. - * - * The device reads or writes the data in the queues via the device's several - * DMA/FIFO channels. Each queue is mapped to a single DMA channel. - * - * For Tx queue, there are low mark and high mark limits. If, after queuing - * the packet for Tx, free space become < low mark, Tx queue stopped. When - * reclaiming packets (on 'tx done IRQ), if free space become > high mark, - * Tx queue resumed. - * - * See more detailed info in iwl-4965-hw.h. - ***************************************************/ - -int iwl_queue_space(const struct iwl_queue *q) -{ - int s = q->read_ptr - q->write_ptr; - - if (q->read_ptr > q->write_ptr) - s -= q->n_bd; - - if (s <= 0) - s += q->n_window; - /* keep some reserve to not confuse empty and full situations */ - s -= 2; - if (s < 0) - s = 0; - return s; -} -EXPORT_SYMBOL(iwl_queue_space); - - -/** - * iwl_queue_init - Initialize queue's high/low-water and read/write indexes - */ -static int iwl_queue_init(struct iwl_priv *priv, struct iwl_queue *q, - int count, int slots_num, u32 id) -{ - q->n_bd = count; - q->n_window = slots_num; - q->id = id; - - /* count must be power-of-two size, otherwise iwl_queue_inc_wrap - * and iwl_queue_dec_wrap are broken. */ - BUG_ON(!is_power_of_2(count)); - - /* slots_num must be power-of-two size, otherwise - * get_cmd_index is broken. */ - BUG_ON(!is_power_of_2(slots_num)); - - q->low_mark = q->n_window / 4; - if (q->low_mark < 4) - q->low_mark = 4; - - q->high_mark = q->n_window / 8; - if (q->high_mark < 2) - q->high_mark = 2; - - q->write_ptr = q->read_ptr = 0; - - return 0; -} - -/** - * iwl_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue - */ -static int iwl_tx_queue_alloc(struct iwl_priv *priv, - struct iwl_tx_queue *txq, u32 id) -{ - struct device *dev = &priv->pci_dev->dev; - size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX; - - /* Driver private data, only for Tx (not command) queues, - * not shared with device. */ - if (id != IWL_CMD_QUEUE_NUM) { - txq->txb = kmalloc(sizeof(txq->txb[0]) * - TFD_QUEUE_SIZE_MAX, GFP_KERNEL); - if (!txq->txb) { - IWL_ERR(priv, "kmalloc for auxiliary BD " - "structures failed\n"); - goto error; - } - } else { - txq->txb = NULL; - } - - /* Circular buffer of transmit frame descriptors (TFDs), - * shared with device */ - txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr, - GFP_KERNEL); - if (!txq->tfds) { - IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz); - goto error; - } - txq->q.id = id; - - return 0; - - error: - kfree(txq->txb); - txq->txb = NULL; - - return -ENOMEM; -} - -/** - * iwl_tx_queue_init - Allocate and initialize one tx/cmd queue - */ -int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, - int slots_num, u32 txq_id) -{ - int i, len; - int ret; - int actual_slots = slots_num; - - /* - * Alloc buffer array for commands (Tx or other types of commands). - * For the command queue (#4), allocate command space + one big - * command for scan, since scan command is very huge; the system will - * not have two scans at the same time, so only one is needed. - * For normal Tx queues (all other queues), no super-size command - * space is needed. - */ - if (txq_id == IWL_CMD_QUEUE_NUM) - actual_slots++; - - txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots, - GFP_KERNEL); - txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots, - GFP_KERNEL); - - if (!txq->meta || !txq->cmd) - goto out_free_arrays; - - len = sizeof(struct iwl_device_cmd); - for (i = 0; i < actual_slots; i++) { - /* only happens for cmd queue */ - if (i == slots_num) - len += IWL_MAX_SCAN_SIZE; - - txq->cmd[i] = kmalloc(len, GFP_KERNEL); - if (!txq->cmd[i]) - goto err; - } - - /* Alloc driver data array and TFD circular buffer */ - ret = iwl_tx_queue_alloc(priv, txq, txq_id); - if (ret) - goto err; - - txq->need_update = 0; - - /* aggregation TX queues will get their ID when aggregation begins */ - if (txq_id <= IWL_TX_FIFO_AC3) - txq->swq_id = txq_id; - - /* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise - * iwl_queue_inc_wrap and iwl_queue_dec_wrap are broken. */ - BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1)); - - /* Initialize queue's high/low-water marks, and head/tail indexes */ - iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); - - /* Tell device where to find queue */ - priv->cfg->ops->lib->txq_init(priv, txq); - - return 0; -err: - for (i = 0; i < actual_slots; i++) - kfree(txq->cmd[i]); -out_free_arrays: - kfree(txq->meta); - kfree(txq->cmd); - - return -ENOMEM; -} -EXPORT_SYMBOL(iwl_tx_queue_init); - -/** - * iwl_hw_txq_ctx_free - Free TXQ Context - * - * Destroy all TX DMA queues and structures - */ -void iwl_hw_txq_ctx_free(struct iwl_priv *priv) -{ - int txq_id; - - /* Tx queues */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - if (txq_id == IWL_CMD_QUEUE_NUM) - iwl_cmd_queue_free(priv); - else - iwl_tx_queue_free(priv, txq_id); - - iwl_free_dma_ptr(priv, &priv->kw); - - iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); -} -EXPORT_SYMBOL(iwl_hw_txq_ctx_free); - -/** - * iwl_txq_ctx_reset - Reset TX queue context - * Destroys all DMA structures and initialize them again - * - * @param priv - * @return error code - */ -int iwl_txq_ctx_reset(struct iwl_priv *priv) -{ - int ret = 0; - int txq_id, slots_num; - unsigned long flags; - - /* Free all tx/cmd queues and keep-warm buffer */ - iwl_hw_txq_ctx_free(priv); - - ret = iwl_alloc_dma_ptr(priv, &priv->scd_bc_tbls, - priv->hw_params.scd_bc_tbls_size); - if (ret) { - IWL_ERR(priv, "Scheduler BC Table allocation failed\n"); - goto error_bc_tbls; - } - /* Alloc keep-warm buffer */ - ret = iwl_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE); - if (ret) { - IWL_ERR(priv, "Keep Warm allocation failed\n"); - goto error_kw; - } - spin_lock_irqsave(&priv->lock, flags); - - /* Turn off all Tx DMA fifos */ - priv->cfg->ops->lib->txq_set_sched(priv, 0); - - /* Tell NIC where to find the "keep warm" buffer */ - iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); - - spin_unlock_irqrestore(&priv->lock, flags); - - /* Alloc and init all Tx queues, including the command queue (#4) */ - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { - slots_num = (txq_id == IWL_CMD_QUEUE_NUM) ? - TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; - ret = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num, - txq_id); - if (ret) { - IWL_ERR(priv, "Tx %d queue init failed\n", txq_id); - goto error; - } - } - - return ret; - - error: - iwl_hw_txq_ctx_free(priv); - iwl_free_dma_ptr(priv, &priv->kw); - error_kw: - iwl_free_dma_ptr(priv, &priv->scd_bc_tbls); - error_bc_tbls: - return ret; -} - -/** - * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory - */ -void iwl_txq_ctx_stop(struct iwl_priv *priv) -{ - int ch; - unsigned long flags; - - /* Turn off all Tx DMA fifos */ - spin_lock_irqsave(&priv->lock, flags); - - priv->cfg->ops->lib->txq_set_sched(priv, 0); - - /* Stop each Tx DMA channel, and wait for it to be idle */ - for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) { - iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0); - iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG, - FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch), - 1000); - } - spin_unlock_irqrestore(&priv->lock, flags); - - /* Deallocate memory for all Tx queues */ - iwl_hw_txq_ctx_free(priv); -} -EXPORT_SYMBOL(iwl_txq_ctx_stop); - -/* - * handle build REPLY_TX command notification. - */ -static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, - struct iwl_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, - u8 std_id) -{ - __le16 fc = hdr->frame_control; - __le32 tx_flags = tx_cmd->tx_flags; - - tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - tx_flags |= TX_CMD_FLG_ACK_MSK; - if (ieee80211_is_mgmt(fc)) - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - if (ieee80211_is_probe_resp(fc) && - !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) - tx_flags |= TX_CMD_FLG_TSF_MSK; - } else { - tx_flags &= (~TX_CMD_FLG_ACK_MSK); - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - - if (ieee80211_is_back_req(fc)) - tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK; - - - tx_cmd->sta_id = std_id; - if (ieee80211_has_morefrags(fc)) - tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; - - if (ieee80211_is_data_qos(fc)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - tx_cmd->tid_tspec = qc[0] & 0xf; - tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; - } else { - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - - priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags); - - if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) - tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - - tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); - if (ieee80211_is_mgmt(fc)) { - if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) - tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3); - else - tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2); - } else { - tx_cmd->timeout.pm_frame_timeout = 0; - } - - tx_cmd->driver_txop = 0; - tx_cmd->tx_flags = tx_flags; - tx_cmd->next_frame_len = 0; -} - -#define RTS_HCCA_RETRY_LIMIT 3 -#define RTS_DFAULT_RETRY_LIMIT 60 - -static void iwl_tx_cmd_build_rate(struct iwl_priv *priv, - struct iwl_tx_cmd *tx_cmd, - struct ieee80211_tx_info *info, - __le16 fc, int is_hcca) -{ - u32 rate_flags; - int rate_idx; - u8 rts_retry_limit; - u8 data_retry_limit; - u8 rate_plcp; - - /* Set retry limit on DATA packets and Probe Responses*/ - if (priv->data_retry_limit != -1) - data_retry_limit = priv->data_retry_limit; - else if (ieee80211_is_probe_resp(fc)) - data_retry_limit = 3; - else - data_retry_limit = IWL_DEFAULT_TX_RETRY; - tx_cmd->data_retry_limit = data_retry_limit; - - /* Set retry limit on RTS packets */ - rts_retry_limit = (is_hcca) ? RTS_HCCA_RETRY_LIMIT : - RTS_DFAULT_RETRY_LIMIT; - if (data_retry_limit < rts_retry_limit) - rts_retry_limit = data_retry_limit; - tx_cmd->rts_retry_limit = rts_retry_limit; - - /* DATA packets will use the uCode station table for rate/antenna - * selection */ - if (ieee80211_is_data(fc)) { - tx_cmd->initial_rate_index = 0; - tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK; - return; - } - - /** - * If the current TX rate stored in mac80211 has the MCS bit set, it's - * not really a TX rate. Thus, we use the lowest supported rate for - * this band. Also use the lowest supported rate if the stored rate - * index is invalid. - */ - rate_idx = info->control.rates[0].idx; - if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS || - (rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY)) - rate_idx = rate_lowest_index(&priv->bands[info->band], - info->control.sta); - /* For 5 GHZ band, remap mac80211 rate indices into driver indices */ - if (info->band == IEEE80211_BAND_5GHZ) - rate_idx += IWL_FIRST_OFDM_RATE; - /* Get PLCP rate for tx_cmd->rate_n_flags */ - rate_plcp = iwl_rates[rate_idx].plcp; - /* Zero out flags for this packet */ - rate_flags = 0; - - /* Set CCK flag as needed */ - if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE)) - rate_flags |= RATE_MCS_CCK_MSK; - - /* Set up RTS and CTS flags for certain packets */ - switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) { - case cpu_to_le16(IEEE80211_STYPE_AUTH): - case cpu_to_le16(IEEE80211_STYPE_DEAUTH): - case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ): - case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ): - if (tx_cmd->tx_flags & TX_CMD_FLG_RTS_MSK) { - tx_cmd->tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_cmd->tx_flags |= TX_CMD_FLG_CTS_MSK; - } - break; - default: - break; - } - - /* Set up antennas */ - priv->mgmt_tx_ant = iwl_toggle_tx_ant(priv, priv->mgmt_tx_ant); - rate_flags |= iwl_ant_idx_to_flags(priv->mgmt_tx_ant); - - /* Set the rate in the TX cmd */ - tx_cmd->rate_n_flags = iwl_hw_set_rate_n_flags(rate_plcp, rate_flags); -} - -static void iwl_tx_cmd_build_hwcrypto(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwl_tx_cmd *tx_cmd, - struct sk_buff *skb_frag, - int sta_id) -{ - struct ieee80211_key_conf *keyconf = info->control.hw_key; - - switch (keyconf->alg) { - case ALG_CCMP: - tx_cmd->sec_ctl = TX_CMD_SEC_CCM; - memcpy(tx_cmd->key, keyconf->key, keyconf->keylen); - if (info->flags & IEEE80211_TX_CTL_AMPDU) - tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK; - IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); - break; - - case ALG_TKIP: - tx_cmd->sec_ctl = TX_CMD_SEC_TKIP; - ieee80211_get_tkip_key(keyconf, skb_frag, - IEEE80211_TKIP_P2_KEY, tx_cmd->key); - IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n"); - break; - - case ALG_WEP: - tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP | - (keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT); - - if (keyconf->keylen == WEP_KEY_LEN_128) - tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128; - - memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen); - - IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " - "with key %d\n", keyconf->keyidx); - break; - - default: - IWL_ERR(priv, "Unknown encode alg %d\n", keyconf->alg); - break; - } -} - -/* - * start REPLY_TX command process - */ -int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl_tx_queue *txq; - struct iwl_queue *q; - struct iwl_device_cmd *out_cmd; - struct iwl_cmd_meta *out_meta; - struct iwl_tx_cmd *tx_cmd; - int swq_id, txq_id; - dma_addr_t phys_addr; - dma_addr_t txcmd_phys; - dma_addr_t scratch_phys; - u16 len, len_org; - u16 seq_number = 0; - __le16 fc; - u8 hdr_len; - u8 sta_id; - u8 wait_write_ptr = 0; - u8 tid = 0; - u8 *qc = NULL; - unsigned long flags; - int ret; - - spin_lock_irqsave(&priv->lock, flags); - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); - goto drop_unlock; - } - - fc = hdr->frame_control; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (ieee80211_is_auth(fc)) - IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); - else if (ieee80211_is_assoc_req(fc)) - IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); - else if (ieee80211_is_reassoc_req(fc)) - IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); -#endif - - /* drop all non-injected data frame if we are not associated */ - if (ieee80211_is_data(fc) && - !(info->flags & IEEE80211_TX_CTL_INJECTED) && - (!iwl_is_associated(priv) || - ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id) || - !priv->assoc_station_added)) { - IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); - goto drop_unlock; - } - - hdr_len = ieee80211_hdrlen(fc); - - /* Find (or create) index into station table for destination station */ - if (info->flags & IEEE80211_TX_CTL_INJECTED) - sta_id = priv->hw_params.bcast_sta_id; - else - sta_id = iwl_get_sta_id(priv, hdr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", - hdr->addr1); - goto drop_unlock; - } - - IWL_DEBUG_TX(priv, "station Id %d\n", sta_id); - - txq_id = skb_get_queue_mapping(skb); - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - if (unlikely(tid >= MAX_TID_COUNT)) - goto drop_unlock; - seq_number = priv->stations[sta_id].tid[tid].seq_number; - seq_number &= IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(seq_number); - seq_number += 0x10; - /* aggregation is on for this */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) { - txq_id = priv->stations[sta_id].tid[tid].agg.txq_id; - } - } - - txq = &priv->txq[txq_id]; - swq_id = txq->swq_id; - q = &txq->q; - - if (unlikely(iwl_queue_space(q) < q->high_mark)) - goto drop_unlock; - - if (ieee80211_is_data_qos(fc)) - priv->stations[sta_id].tid[tid].tfds_in_queue++; - - /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb[0] = skb; - - /* Set up first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = txq->cmd[q->write_ptr]; - out_meta = &txq->meta[q->write_ptr]; - tx_cmd = &out_cmd->cmd.tx; - memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); - memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd)); - - /* - * Set up the Tx-command (not MAC!) header. - * Store the chosen Tx queue and TFD index within the sequence field; - * after Tx, uCode's Tx response will return this value so driver can - * locate the frame within the tx queue and do post-tx processing. - */ - out_cmd->hdr.cmd = REPLY_TX; - out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); - - /* Copy MAC header from skb into command buffer */ - memcpy(tx_cmd->hdr, hdr, hdr_len); - - - /* Total # bytes to be transmitted */ - len = (u16)skb->len; - tx_cmd->len = cpu_to_le16(len); - - if (info->control.hw_key) - iwl_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id); - - /* TODO need this for burst mode later on */ - iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); - iwl_dbg_log_tx_data_frame(priv, len, hdr); - - /* set is_hcca to 0; it probably will never be implemented */ - iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, 0); - - iwl_update_stats(priv, true, fc, len); - /* - * Use the first empty entry in this queue's command buffer array - * to contain the Tx command and MAC header concatenated together - * (payload data will be in another buffer). - * Size of this varies, due to varying MAC header length. - * If end is not dword aligned, we'll have 2 extra bytes at the end - * of the MAC header (device reads on dword boundaries). - * We'll tell device about this padding later. - */ - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; - len = (len + 3) & ~3; - - if (len_org != len) - len_org = 1; - else - len_org = 0; - - /* Tell NIC about any 2-byte padding after MAC header */ - if (len_org) - tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; - - /* Physical address of this Tx command's header (not MAC header!), - * within command buffer array. */ - txcmd_phys = pci_map_single(priv->pci_dev, - &out_cmd->hdr, len, - PCI_DMA_BIDIRECTIONAL); - pci_unmap_addr_set(out_meta, mapping, txcmd_phys); - pci_unmap_len_set(out_meta, len, len); - /* Add buffer containing Tx command and MAC(!) header to TFD's - * first entry */ - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, len, 1, 0); - - if (!ieee80211_has_morefrags(hdr->frame_control)) { - txq->need_update = 1; - if (qc) - priv->stations[sta_id].tid[tid].seq_number = seq_number; - } else { - wait_write_ptr = 1; - txq->need_update = 0; - } - - /* Set up TFD's 2nd entry to point directly to remainder of skb, - * if any (802.11 null frames have no payload). */ - len = skb->len - hdr_len; - if (len) { - phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, - len, PCI_DMA_TODEVICE); - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, len, - 0, 0); - } - - scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + - offsetof(struct iwl_tx_cmd, scratch); - - len = sizeof(struct iwl_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - /* take back ownership of DMA buffer to enable update */ - pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); - tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); - tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); - - IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", - le16_to_cpu(out_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx_cmd->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr, hdr_len); - - /* Set up entry for this TFD in Tx byte-count array */ - if (info->flags & IEEE80211_TX_CTL_AMPDU) - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, - le16_to_cpu(tx_cmd->len)); - - pci_dma_sync_single_for_device(priv->pci_dev, txcmd_phys, - len, PCI_DMA_BIDIRECTIONAL); - - /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - - if (ret) - return ret; - - if ((iwl_queue_space(q) < q->high_mark) && priv->mac80211_registered) { - if (wait_write_ptr) { - spin_lock_irqsave(&priv->lock, flags); - txq->need_update = 1; - iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - } else { - iwl_stop_queue(priv, txq->swq_id); - } - } - - return 0; - -drop_unlock: - spin_unlock_irqrestore(&priv->lock, flags); - return -1; -} -EXPORT_SYMBOL(iwl_tx_skb); - -/*************** HOST COMMAND QUEUE FUNCTIONS *****/ - -/** - * iwl_enqueue_hcmd - enqueue a uCode command - * @priv: device private data point - * @cmd: a point to the ucode command structure - * - * The function returns < 0 values to indicate the operation is - * failed. On success, it turns the index (> 0) of command in the - * command queue. - */ -int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd) -{ - struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM]; - struct iwl_queue *q = &txq->q; - struct iwl_device_cmd *out_cmd; - struct iwl_cmd_meta *out_meta; - dma_addr_t phys_addr; - unsigned long flags; - int len, ret; - u32 idx; - u16 fix_size; - - cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len); - fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr)); - - /* If any of the command structures end up being larger than - * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then - * we will need to increase the size of the TFD entries */ - BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) && - !(cmd->flags & CMD_SIZE_HUGE)); - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_INFO(priv, "Not sending command - RF KILL\n"); - return -EIO; - } - - if (iwl_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - IWL_ERR(priv, "No space for Tx\n"); - return -ENOSPC; - } - - spin_lock_irqsave(&priv->hcmd_lock, flags); - - idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); - out_cmd = txq->cmd[idx]; - out_meta = &txq->meta[idx]; - - memset(out_meta, 0, sizeof(*out_meta)); /* re-initialize to NULL */ - out_meta->flags = cmd->flags; - if (cmd->flags & CMD_WANT_SKB) - out_meta->source = cmd; - if (cmd->flags & CMD_ASYNC) - out_meta->callback = cmd->callback; - - out_cmd->hdr.cmd = cmd->id; - memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len); - - /* At this point, the out_cmd now has all of the incoming cmd - * information */ - - out_cmd->hdr.flags = 0; - out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(IWL_CMD_QUEUE_NUM) | - INDEX_TO_SEQ(q->write_ptr)); - if (cmd->flags & CMD_SIZE_HUGE) - out_cmd->hdr.sequence |= SEQ_HUGE_FRAME; - len = sizeof(struct iwl_device_cmd); - len += (idx == TFD_CMD_SLOTS) ? IWL_MAX_SCAN_SIZE : 0; - - -#ifdef CONFIG_IWLWIFI_DEBUG - switch (out_cmd->hdr.cmd) { - case REPLY_TX_LINK_QUALITY_CMD: - case SENSITIVITY_CMD: - IWL_DEBUG_HC_DUMP(priv, "Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, - le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, IWL_CMD_QUEUE_NUM); - break; - default: - IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, " - "%d bytes at %d[%d]:%d\n", - get_cmd_string(out_cmd->hdr.cmd), - out_cmd->hdr.cmd, - le16_to_cpu(out_cmd->hdr.sequence), fix_size, - q->write_ptr, idx, IWL_CMD_QUEUE_NUM); - } -#endif - txq->need_update = 1; - - if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl) - /* Set up entry in queue's byte count circular buffer */ - priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0); - - phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr, - fix_size, PCI_DMA_BIDIRECTIONAL); - pci_unmap_addr_set(out_meta, mapping, phys_addr); - pci_unmap_len_set(out_meta, len, fix_size); - - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, fix_size, 1, - U32_PAD(cmd->len)); - - /* Increment and update queue's write index */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - ret = iwl_txq_update_write_ptr(priv, txq); - - spin_unlock_irqrestore(&priv->hcmd_lock, flags); - return ret ? ret : idx; -} - -int iwl_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - struct iwl_tx_info *tx_info; - int nfreed = 0; - struct ieee80211_hdr *hdr; - - if ((index >= q->n_bd) || (iwl_queue_used(q, index) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " - "is out of range [0-%d] %d %d.\n", txq_id, - index, q->n_bd, q->write_ptr, q->read_ptr); - return 0; - } - - for (index = iwl_queue_inc_wrap(index, q->n_bd); - q->read_ptr != index; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - tx_info = &txq->txb[txq->q.read_ptr]; - ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb[0]); - - hdr = (struct ieee80211_hdr *)tx_info->skb[0]->data; - if (hdr && ieee80211_is_data_qos(hdr->frame_control)) - nfreed++; - tx_info->skb[0] = NULL; - - if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl) - priv->cfg->ops->lib->txq_inval_byte_cnt_tbl(priv, txq); - - priv->cfg->ops->lib->txq_free_tfd(priv, txq); - } - return nfreed; -} -EXPORT_SYMBOL(iwl_tx_queue_reclaim); - - -/** - * iwl_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd - * - * When FW advances 'R' index, all entries between old and new 'R' index - * need to be reclaimed. As result, some free space forms. If there is - * enough free space (> low mark), wake the stack that feeds us. - */ -static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id, - int idx, int cmd_idx) -{ - struct iwl_tx_queue *txq = &priv->txq[txq_id]; - struct iwl_queue *q = &txq->q; - int nfreed = 0; - - if ((idx >= q->n_bd) || (iwl_queue_used(q, idx) == 0)) { - IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, " - "is out of range [0-%d] %d %d.\n", txq_id, - idx, q->n_bd, q->write_ptr, q->read_ptr); - return; - } - - pci_unmap_single(priv->pci_dev, - pci_unmap_addr(&txq->meta[cmd_idx], mapping), - pci_unmap_len(&txq->meta[cmd_idx], len), - PCI_DMA_BIDIRECTIONAL); - - for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx; - q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { - - if (nfreed++ > 0) { - IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx, - q->write_ptr, q->read_ptr); - queue_work(priv->workqueue, &priv->restart); - } - - } -} - -/** - * iwl_tx_cmd_complete - Pull unused buffers off the queue and reclaim them - * @rxb: Rx buffer to reclaim - * - * If an Rx buffer has an async callback associated with it the callback - * will be executed. The attached skb (if present) will only be freed - * if the callback returns 1 - */ -void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - u16 sequence = le16_to_cpu(pkt->hdr.sequence); - int txq_id = SEQ_TO_QUEUE(sequence); - int index = SEQ_TO_INDEX(sequence); - int cmd_index; - bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); - struct iwl_device_cmd *cmd; - struct iwl_cmd_meta *meta; - - /* If a Tx command is being handled and it isn't in the actual - * command queue then there a command routing bug has been introduced - * in the queue management code. */ - if (WARN(txq_id != IWL_CMD_QUEUE_NUM, - "wrong command queue %d, sequence 0x%X readp=%d writep=%d\n", - txq_id, sequence, - priv->txq[IWL_CMD_QUEUE_NUM].q.read_ptr, - priv->txq[IWL_CMD_QUEUE_NUM].q.write_ptr)) { - iwl_print_hex_error(priv, pkt, 32); - return; - } - - cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); - cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; - meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; - - /* Input error checking is done when commands are added to queue. */ - if (meta->flags & CMD_WANT_SKB) { - meta->source->reply_skb = rxb->skb; - rxb->skb = NULL; - } else if (meta->callback) - meta->callback(priv, cmd, rxb->skb); - - iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index); - - if (!(meta->flags & CMD_ASYNC)) { - clear_bit(STATUS_HCMD_ACTIVE, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); - } -} -EXPORT_SYMBOL(iwl_tx_cmd_complete); - -/* - * Find first available (lowest unused) Tx Queue, mark it "active". - * Called only when finding queue for aggregation. - * Should never return anything < 7, because they should already - * be in use as EDCA AC (0-3), Command (4), HCCA (5, 6). - */ -static int iwl_txq_ctx_activate_free(struct iwl_priv *priv) -{ - int txq_id; - - for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) - if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk)) - return txq_id; - return -1; -} - -int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn) -{ - int sta_id; - int tx_fifo; - int txq_id; - int ret; - unsigned long flags; - struct iwl_tid_data *tid_data; - - if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) - tx_fifo = default_tid_to_tx_fifo[tid]; - else - return -EINVAL; - - IWL_WARN(priv, "%s on ra = %pM tid = %d\n", - __func__, ra, tid); - - sta_id = iwl_find_station(priv, ra); - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Start AGG on invalid station\n"); - return -ENXIO; - } - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_OFF) { - IWL_ERR(priv, "Start AGG when state is not IWL_AGG_OFF !\n"); - return -ENXIO; - } - - txq_id = iwl_txq_ctx_activate_free(priv); - if (txq_id == -1) { - IWL_ERR(priv, "No free aggregation queue available\n"); - return -ENXIO; - } - - spin_lock_irqsave(&priv->sta_lock, flags); - tid_data = &priv->stations[sta_id].tid[tid]; - *ssn = SEQ_TO_SN(tid_data->seq_number); - tid_data->agg.txq_id = txq_id; - priv->txq[txq_id].swq_id = iwl_virtual_agg_queue_num(tx_fifo, txq_id); - spin_unlock_irqrestore(&priv->sta_lock, flags); - - ret = priv->cfg->ops->lib->txq_agg_enable(priv, txq_id, tx_fifo, - sta_id, tid, *ssn); - if (ret) - return ret; - - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(priv, "HW queue is empty\n"); - tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(priv->hw, ra, tid); - } else { - IWL_DEBUG_HT(priv, "HW queue is NOT empty: %d packets in HW queue\n", - tid_data->tfds_in_queue); - tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA; - } - return ret; -} -EXPORT_SYMBOL(iwl_tx_agg_start); - -int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid) -{ - int tx_fifo_id, txq_id, sta_id, ssn = -1; - struct iwl_tid_data *tid_data; - int write_ptr, read_ptr; - unsigned long flags; - - if (!ra) { - IWL_ERR(priv, "ra = NULL\n"); - return -EINVAL; - } - - if (unlikely(tid >= MAX_TID_COUNT)) - return -EINVAL; - - if (likely(tid < ARRAY_SIZE(default_tid_to_tx_fifo))) - tx_fifo_id = default_tid_to_tx_fifo[tid]; - else - return -EINVAL; - - sta_id = iwl_find_station(priv, ra); - - if (sta_id == IWL_INVALID_STATION) { - IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid); - return -ENXIO; - } - - if (priv->stations[sta_id].tid[tid].agg.state == - IWL_EMPTYING_HW_QUEUE_ADDBA) { - IWL_DEBUG_HT(priv, "AGG stop before setup done\n"); - ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); - priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; - return 0; - } - - if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON) - IWL_WARN(priv, "Stopping AGG while state not ON or starting\n"); - - tid_data = &priv->stations[sta_id].tid[tid]; - ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; - txq_id = tid_data->agg.txq_id; - write_ptr = priv->txq[txq_id].q.write_ptr; - read_ptr = priv->txq[txq_id].q.read_ptr; - - /* The queue is not empty */ - if (write_ptr != read_ptr) { - IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n"); - priv->stations[sta_id].tid[tid].agg.state = - IWL_EMPTYING_HW_QUEUE_DELBA; - return 0; - } - - IWL_DEBUG_HT(priv, "HW queue is empty\n"); - priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; - - spin_lock_irqsave(&priv->lock, flags); - /* - * the only reason this call can fail is queue number out of range, - * which can happen if uCode is reloaded and all the station - * information are lost. if it is outside the range, there is no need - * to deactivate the uCode queue, just return "success" to allow - * mac80211 to clean up it own data. - */ - priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, ssn, - tx_fifo_id); - spin_unlock_irqrestore(&priv->lock, flags); - - ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, ra, tid); - - return 0; -} -EXPORT_SYMBOL(iwl_tx_agg_stop); - -int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id) -{ - struct iwl_queue *q = &priv->txq[txq_id].q; - u8 *addr = priv->stations[sta_id].sta.sta.addr; - struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid]; - - switch (priv->stations[sta_id].tid[tid].agg.state) { - case IWL_EMPTYING_HW_QUEUE_DELBA: - /* We are reclaiming the last packet of the */ - /* aggregated HW queue */ - if ((txq_id == tid_data->agg.txq_id) && - (q->read_ptr == q->write_ptr)) { - u16 ssn = SEQ_TO_SN(tid_data->seq_number); - int tx_fifo = default_tid_to_tx_fifo[tid]; - IWL_DEBUG_HT(priv, "HW queue empty: continue DELBA flow\n"); - priv->cfg->ops->lib->txq_agg_disable(priv, txq_id, - ssn, tx_fifo); - tid_data->agg.state = IWL_AGG_OFF; - ieee80211_stop_tx_ba_cb_irqsafe(priv->hw, addr, tid); - } - break; - case IWL_EMPTYING_HW_QUEUE_ADDBA: - /* We are reclaiming the last packet of the queue */ - if (tid_data->tfds_in_queue == 0) { - IWL_DEBUG_HT(priv, "HW queue empty: continue ADDBA flow\n"); - tid_data->agg.state = IWL_AGG_ON; - ieee80211_start_tx_ba_cb_irqsafe(priv->hw, addr, tid); - } - break; - } - return 0; -} -EXPORT_SYMBOL(iwl_txq_check_empty); - -/** - * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack - * - * Go through block-ack's bitmap of ACK'd frames, update driver's record of - * ACK vs. not. This gets sent to mac80211, then to rate scaling algo. - */ -static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_ht_agg *agg, - struct iwl_compressed_ba_resp *ba_resp) - -{ - int i, sh, ack; - u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl); - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - u64 bitmap; - int successes = 0; - struct ieee80211_tx_info *info; - - if (unlikely(!agg->wait_for_ba)) { - IWL_ERR(priv, "Received BA when not expected\n"); - return -EINVAL; - } - - /* Mark that the expected block-ack response arrived */ - agg->wait_for_ba = 0; - IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx, ba_resp->seq_ctl); - - /* Calculate shift to align block-ack bits with our Tx window bits */ - sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4); - if (sh < 0) /* tbw something is wrong with indices */ - sh += 0x100; - - /* don't use 64-bit values for now */ - bitmap = le64_to_cpu(ba_resp->bitmap) >> sh; - - if (agg->frame_count > (64 - sh)) { - IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size"); - return -1; - } - - /* check for success or failure according to the - * transmitted bitmap and block-ack bitmap */ - bitmap &= agg->bitmap; - - /* For each frame attempted in aggregation, - * update driver's record of tx frame's status. */ - for (i = 0; i < agg->frame_count ; i++) { - ack = bitmap & (1ULL << i); - successes += !!ack; - IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n", - ack ? "ACK" : "NACK", i, (agg->start_idx + i) & 0xff, - agg->start_idx + i); - } - - info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]); - memset(&info->status, 0, sizeof(info->status)); - info->flags = IEEE80211_TX_STAT_ACK; - info->flags |= IEEE80211_TX_STAT_AMPDU; - info->status.ampdu_ack_map = successes; - info->status.ampdu_ack_len = agg->frame_count; - iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info); - - IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n", (unsigned long long)bitmap); - - return 0; -} - -/** - * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA - * - * Handles block-acknowledge notification from device, which reports success - * of frames sent via aggregation. - */ -void iwl_rx_reply_compressed_ba(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data; - struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba; - struct iwl_tx_queue *txq = NULL; - struct iwl_ht_agg *agg; - int index; - int sta_id; - int tid; - - /* "flow" corresponds to Tx queue */ - u16 scd_flow = le16_to_cpu(ba_resp->scd_flow); - - /* "ssn" is start of block-ack Tx window, corresponds to index - * (in Tx queue's circular buffer) of first TFD/frame in window */ - u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn); - - if (scd_flow >= priv->hw_params.max_txq_num) { - IWL_ERR(priv, - "BUG_ON scd_flow is bigger than number of queues\n"); - return; - } - - txq = &priv->txq[scd_flow]; - sta_id = ba_resp->sta_id; - tid = ba_resp->tid; - agg = &priv->stations[sta_id].tid[tid].agg; - if (unlikely(agg->txq_id != scd_flow)) { - IWL_ERR(priv, "BA scd_flow %d does not match txq_id %d\n", - scd_flow, agg->txq_id); - return; - } - - /* Find index just before block-ack window */ - index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd); - - /* TODO: Need to get this copy more safely - now good for debug */ - - IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, " - "sta_id = %d\n", - agg->wait_for_ba, - (u8 *) &ba_resp->sta_addr_lo32, - ba_resp->sta_id); - IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = " - "%d, scd_ssn = %d\n", - ba_resp->tid, - ba_resp->seq_ctl, - (unsigned long long)le64_to_cpu(ba_resp->bitmap), - ba_resp->scd_flow, - ba_resp->scd_ssn); - IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx \n", - agg->start_idx, - (unsigned long long)agg->bitmap); - - /* Update driver's record of ACK vs. not for each frame in window */ - iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp); - - /* Release all TFDs before the SSN, i.e. all TFDs in front of - * block-ack window (we assume that they've been successfully - * transmitted ... if not, it's too late anyway). */ - if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) { - /* calculate mac80211 ampdu sw queue to wake */ - int freed = iwl_tx_queue_reclaim(priv, scd_flow, index); - iwl_free_tfds_in_queue(priv, sta_id, tid, freed); - - if ((iwl_queue_space(&txq->q) > txq->q.low_mark) && - priv->mac80211_registered && - (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) - iwl_wake_queue(priv, txq->swq_id); - - iwl_txq_check_empty(priv, sta_id, tid, scd_flow); - } -} -EXPORT_SYMBOL(iwl_rx_reply_compressed_ba); - -#ifdef CONFIG_IWLWIFI_DEBUG -#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x - -const char *iwl_get_tx_fail_reason(u32 status) -{ - switch (status & TX_STATUS_MSK) { - case TX_STATUS_SUCCESS: - return "SUCCESS"; - TX_STATUS_ENTRY(SHORT_LIMIT); - TX_STATUS_ENTRY(LONG_LIMIT); - TX_STATUS_ENTRY(FIFO_UNDERRUN); - TX_STATUS_ENTRY(MGMNT_ABORT); - TX_STATUS_ENTRY(NEXT_FRAG); - TX_STATUS_ENTRY(LIFE_EXPIRE); - TX_STATUS_ENTRY(DEST_PS); - TX_STATUS_ENTRY(ABORTED); - TX_STATUS_ENTRY(BT_RETRY); - TX_STATUS_ENTRY(STA_INVALID); - TX_STATUS_ENTRY(FRAG_DROPPED); - TX_STATUS_ENTRY(TID_DISABLE); - TX_STATUS_ENTRY(FRAME_FLUSHED); - TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL); - TX_STATUS_ENTRY(TX_LOCKED); - TX_STATUS_ENTRY(NO_BEACON_ON_RADAR); - } - - return "UNKNOWN"; -} -EXPORT_SYMBOL(iwl_get_tx_fail_reason); -#endif /* CONFIG_IWLWIFI_DEBUG */ diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c deleted file mode 100644 index 619590ddb096..000000000000 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ /dev/null @@ -1,4249 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) 2003 - 2009 Intel Corporation. All rights reserved. - * - * Portions of this file are derived from the ipw3945 project, as well - * as portions of the ieee80211 subsystem header files. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Intel Linux Wireless - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - *****************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include - -#define DRV_NAME "iwl3945" - -#include "iwl-fh.h" -#include "iwl-3945-fh.h" -#include "iwl-commands.h" -#include "iwl-sta.h" -#include "iwl-3945.h" -#include "iwl-helpers.h" -#include "iwl-core.h" -#include "iwl-dev.h" - -/* - * module name, copyright, version, etc. - */ - -#define DRV_DESCRIPTION \ -"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux" - -#ifdef CONFIG_IWLWIFI_DEBUG -#define VD "d" -#else -#define VD -#endif - -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT -#define VS "s" -#else -#define VS -#endif - -#define IWL39_VERSION "1.2.26k" VD VS -#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" -#define DRV_AUTHOR "" -#define DRV_VERSION IWL39_VERSION - - -MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_VERSION(DRV_VERSION); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); -MODULE_LICENSE("GPL"); - - /* module parameters */ -struct iwl_mod_params iwl3945_mod_params = { - .num_of_queues = IWL39_NUM_QUEUES, /* Not used */ - .sw_crypto = 1, - .restart_fw = 1, - /* the rest are 0 by default */ -}; - -/** - * iwl3945_get_antenna_flags - Get antenna flags for RXON command - * @priv: eeprom and antenna fields are used to determine antenna flags - * - * priv->eeprom39 is used to determine if antenna AUX/MAIN are reversed - * iwl3945_mod_params.antenna specifies the antenna diversity mode: - * - * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself - * IWL_ANTENNA_MAIN - Force MAIN antenna - * IWL_ANTENNA_AUX - Force AUX antenna - */ -__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv) -{ - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - - switch (iwl3945_mod_params.antenna) { - case IWL_ANTENNA_DIVERSITY: - return 0; - - case IWL_ANTENNA_MAIN: - if (eeprom->antenna_switch_type) - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; - - case IWL_ANTENNA_AUX: - if (eeprom->antenna_switch_type) - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK; - return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK; - } - - /* bad antenna selector value */ - IWL_ERR(priv, "Bad antenna selector value (0x%x)\n", - iwl3945_mod_params.antenna); - - return 0; /* "diversity" is default if error */ -} - -static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - unsigned long flags; - __le16 key_flags = 0; - int ret; - - key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK); - key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS); - - if (sta_id == priv->hw_params.bcast_sta_id) - key_flags |= STA_KEY_MULTICAST_MSK; - - keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - keyconf->hw_key_idx = keyconf->keyidx; - key_flags &= ~STA_KEY_FLG_INVALID; - - spin_lock_irqsave(&priv->sta_lock, flags); - priv->stations[sta_id].keyinfo.alg = keyconf->alg; - priv->stations[sta_id].keyinfo.keylen = keyconf->keylen; - memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, - keyconf->keylen); - - memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, - keyconf->keylen); - - if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK) - == STA_KEY_FLG_NO_ENC) - priv->stations[sta_id].sta.key.key_offset = - iwl_get_free_ucode_key_index(priv); - /* else, we are overriding an existing key => no need to allocated room - * in uCode. */ - - WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET, - "no space for a new key"); - - priv->stations[sta_id].sta.key.key_flags = key_flags; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - - IWL_DEBUG_INFO(priv, "hwcrypto: modify ucode station key info\n"); - - ret = iwl_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC); - - spin_unlock_irqrestore(&priv->sta_lock, flags); - - return ret; -} - -static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - return -EOPNOTSUPP; -} - -static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, - u8 sta_id) -{ - return -EOPNOTSUPP; -} - -static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->sta_lock, flags); - memset(&priv->stations[sta_id].keyinfo, 0, sizeof(struct iwl_hw_key)); - memset(&priv->stations[sta_id].sta.key, 0, - sizeof(struct iwl4965_keyinfo)); - priv->stations[sta_id].sta.key.key_flags = STA_KEY_FLG_NO_ENC; - priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK; - priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK; - spin_unlock_irqrestore(&priv->sta_lock, flags); - - IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n"); - iwl_send_add_sta(priv, &priv->stations[sta_id].sta, 0); - return 0; -} - -static int iwl3945_set_dynamic_key(struct iwl_priv *priv, - struct ieee80211_key_conf *keyconf, u8 sta_id) -{ - int ret = 0; - - keyconf->hw_key_idx = HW_KEY_DYNAMIC; - - switch (keyconf->alg) { - case ALG_CCMP: - ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id); - break; - case ALG_TKIP: - ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id); - break; - case ALG_WEP: - ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id); - break; - default: - IWL_ERR(priv, "Unknown alg: %s alg = %d\n", __func__, keyconf->alg); - ret = -EINVAL; - } - - IWL_DEBUG_WEP(priv, "Set dynamic key: alg= %d len=%d idx=%d sta=%d ret=%d\n", - keyconf->alg, keyconf->keylen, keyconf->keyidx, - sta_id, ret); - - return ret; -} - -static int iwl3945_remove_static_key(struct iwl_priv *priv) -{ - int ret = -EOPNOTSUPP; - - return ret; -} - -static int iwl3945_set_static_key(struct iwl_priv *priv, - struct ieee80211_key_conf *key) -{ - if (key->alg == ALG_WEP) - return -EOPNOTSUPP; - - IWL_ERR(priv, "Static key invalid: alg %d\n", key->alg); - return -EINVAL; -} - -static void iwl3945_clear_free_frames(struct iwl_priv *priv) -{ - struct list_head *element; - - IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n", - priv->frames_count); - - while (!list_empty(&priv->free_frames)) { - element = priv->free_frames.next; - list_del(element); - kfree(list_entry(element, struct iwl3945_frame, list)); - priv->frames_count--; - } - - if (priv->frames_count) { - IWL_WARN(priv, "%d frames still in use. Did we lose one?\n", - priv->frames_count); - priv->frames_count = 0; - } -} - -static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv) -{ - struct iwl3945_frame *frame; - struct list_head *element; - if (list_empty(&priv->free_frames)) { - frame = kzalloc(sizeof(*frame), GFP_KERNEL); - if (!frame) { - IWL_ERR(priv, "Could not allocate frame!\n"); - return NULL; - } - - priv->frames_count++; - return frame; - } - - element = priv->free_frames.next; - list_del(element); - return list_entry(element, struct iwl3945_frame, list); -} - -static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame) -{ - memset(frame, 0, sizeof(*frame)); - list_add(&frame->list, &priv->free_frames); -} - -unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv, - struct ieee80211_hdr *hdr, - int left) -{ - - if (!iwl_is_associated(priv) || !priv->ibss_beacon || - ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && - (priv->iw_mode != NL80211_IFTYPE_AP))) - return 0; - - if (priv->ibss_beacon->len > left) - return 0; - - memcpy(hdr, priv->ibss_beacon->data, priv->ibss_beacon->len); - - return priv->ibss_beacon->len; -} - -static int iwl3945_send_beacon_cmd(struct iwl_priv *priv) -{ - struct iwl3945_frame *frame; - unsigned int frame_size; - int rc; - u8 rate; - - frame = iwl3945_get_free_frame(priv); - - if (!frame) { - IWL_ERR(priv, "Could not obtain free frame buffer for beacon " - "command.\n"); - return -ENOMEM; - } - - rate = iwl_rate_get_lowest_plcp(priv); - - frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate); - - rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size, - &frame->u.cmd[0]); - - iwl3945_free_frame(priv, frame); - - return rc; -} - -static void iwl3945_unset_hw_params(struct iwl_priv *priv) -{ - if (priv->shared_virt) - dma_free_coherent(&priv->pci_dev->dev, - sizeof(struct iwl3945_shared), - priv->shared_virt, - priv->shared_phys); -} - -static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv, - struct ieee80211_tx_info *info, - struct iwl_device_cmd *cmd, - struct sk_buff *skb_frag, - int sta_id) -{ - struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; - struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo; - - switch (keyinfo->alg) { - case ALG_CCMP: - tx->sec_ctl = TX_CMD_SEC_CCM; - memcpy(tx->key, keyinfo->key, keyinfo->keylen); - IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n"); - break; - - case ALG_TKIP: - break; - - case ALG_WEP: - tx->sec_ctl = TX_CMD_SEC_WEP | - (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT; - - if (keyinfo->keylen == 13) - tx->sec_ctl |= TX_CMD_SEC_KEY128; - - memcpy(&tx->key[3], keyinfo->key, keyinfo->keylen); - - IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption " - "with key %d\n", info->control.hw_key->hw_key_idx); - break; - - default: - IWL_ERR(priv, "Unknown encode alg %d\n", keyinfo->alg); - break; - } -} - -/* - * handle build REPLY_TX command notification. - */ -static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv, - struct iwl_device_cmd *cmd, - struct ieee80211_tx_info *info, - struct ieee80211_hdr *hdr, u8 std_id) -{ - struct iwl3945_tx_cmd *tx = (struct iwl3945_tx_cmd *)cmd->cmd.payload; - __le32 tx_flags = tx->tx_flags; - __le16 fc = hdr->frame_control; - u8 rc_flags = info->control.rates[0].flags; - - tx->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - tx_flags |= TX_CMD_FLG_ACK_MSK; - if (ieee80211_is_mgmt(fc)) - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - if (ieee80211_is_probe_resp(fc) && - !(le16_to_cpu(hdr->seq_ctrl) & 0xf)) - tx_flags |= TX_CMD_FLG_TSF_MSK; - } else { - tx_flags &= (~TX_CMD_FLG_ACK_MSK); - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - - tx->sta_id = std_id; - if (ieee80211_has_morefrags(fc)) - tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; - - if (ieee80211_is_data_qos(fc)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - tx->tid_tspec = qc[0] & 0xf; - tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK; - } else { - tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK; - } - - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - tx_flags |= TX_CMD_FLG_RTS_MSK; - tx_flags &= ~TX_CMD_FLG_CTS_MSK; - } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - tx_flags &= ~TX_CMD_FLG_RTS_MSK; - tx_flags |= TX_CMD_FLG_CTS_MSK; - } - - if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK)) - tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK; - - tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK); - if (ieee80211_is_mgmt(fc)) { - if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc)) - tx->timeout.pm_frame_timeout = cpu_to_le16(3); - else - tx->timeout.pm_frame_timeout = cpu_to_le16(2); - } else { - tx->timeout.pm_frame_timeout = 0; -#ifdef CONFIG_IWLWIFI_LEDS - priv->rxtxpackets += le16_to_cpu(cmd->cmd.tx.len); -#endif - } - - tx->driver_txop = 0; - tx->tx_flags = tx_flags; - tx->next_frame_len = 0; -} - -/* - * start REPLY_TX command process - */ -static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct iwl3945_tx_cmd *tx; - struct iwl_tx_queue *txq = NULL; - struct iwl_queue *q = NULL; - struct iwl_device_cmd *out_cmd; - struct iwl_cmd_meta *out_meta; - dma_addr_t phys_addr; - dma_addr_t txcmd_phys; - int txq_id = skb_get_queue_mapping(skb); - u16 len, idx, len_org, hdr_len; /* TODO: len_org is not used */ - u8 id; - u8 unicast; - u8 sta_id; - u8 tid = 0; - u16 seq_number = 0; - __le16 fc; - u8 wait_write_ptr = 0; - u8 *qc = NULL; - unsigned long flags; - int rc; - - spin_lock_irqsave(&priv->lock, flags); - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n"); - goto drop_unlock; - } - - if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) { - IWL_ERR(priv, "ERROR: No TX rate available.\n"); - goto drop_unlock; - } - - unicast = !is_multicast_ether_addr(hdr->addr1); - id = 0; - - fc = hdr->frame_control; - -#ifdef CONFIG_IWLWIFI_DEBUG - if (ieee80211_is_auth(fc)) - IWL_DEBUG_TX(priv, "Sending AUTH frame\n"); - else if (ieee80211_is_assoc_req(fc)) - IWL_DEBUG_TX(priv, "Sending ASSOC frame\n"); - else if (ieee80211_is_reassoc_req(fc)) - IWL_DEBUG_TX(priv, "Sending REASSOC frame\n"); -#endif - - /* drop all non-injected data frame if we are not associated */ - if (ieee80211_is_data(fc) && - !(info->flags & IEEE80211_TX_CTL_INJECTED) && - (!iwl_is_associated(priv) || - ((priv->iw_mode == NL80211_IFTYPE_STATION) && !priv->assoc_id))) { - IWL_DEBUG_DROP(priv, "Dropping - !iwl_is_associated\n"); - goto drop_unlock; - } - - spin_unlock_irqrestore(&priv->lock, flags); - - hdr_len = ieee80211_hdrlen(fc); - - /* Find (or create) index into station table for destination station */ - if (info->flags & IEEE80211_TX_CTL_INJECTED) - sta_id = priv->hw_params.bcast_sta_id; - else - sta_id = iwl_get_sta_id(priv, hdr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n", - hdr->addr1); - goto drop; - } - - IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id); - - if (ieee80211_is_data_qos(fc)) { - qc = ieee80211_get_qos_ctl(hdr); - tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK; - if (unlikely(tid >= MAX_TID_COUNT)) - goto drop; - seq_number = priv->stations[sta_id].tid[tid].seq_number & - IEEE80211_SCTL_SEQ; - hdr->seq_ctrl = cpu_to_le16(seq_number) | - (hdr->seq_ctrl & - cpu_to_le16(IEEE80211_SCTL_FRAG)); - seq_number += 0x10; - } - - /* Descriptor for chosen Tx queue */ - txq = &priv->txq[txq_id]; - q = &txq->q; - - if ((iwl_queue_space(q) < q->high_mark)) - goto drop; - - spin_lock_irqsave(&priv->lock, flags); - - idx = get_cmd_index(q, q->write_ptr, 0); - - /* Set up driver data for this TFD */ - memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info)); - txq->txb[q->write_ptr].skb[0] = skb; - - /* Init first empty entry in queue's array of Tx/cmd buffers */ - out_cmd = txq->cmd[idx]; - out_meta = &txq->meta[idx]; - tx = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload; - memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr)); - memset(tx, 0, sizeof(*tx)); - - /* - * Set up the Tx-command (not MAC!) header. - * Store the chosen Tx queue and TFD index within the sequence field; - * after Tx, uCode's Tx response will return this value so driver can - * locate the frame within the tx queue and do post-tx processing. - */ - out_cmd->hdr.cmd = REPLY_TX; - out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | - INDEX_TO_SEQ(q->write_ptr))); - - /* Copy MAC header from skb into command buffer */ - memcpy(tx->hdr, hdr, hdr_len); - - - if (info->control.hw_key) - iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id); - - /* TODO need this for burst mode later on */ - iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id); - - /* set is_hcca to 0; it probably will never be implemented */ - iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0); - - /* Total # bytes to be transmitted */ - len = (u16)skb->len; - tx->len = cpu_to_le16(len); - - iwl_dbg_log_tx_data_frame(priv, len, hdr); - iwl_update_stats(priv, true, fc, len); - tx->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK; - tx->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK; - - if (!ieee80211_has_morefrags(hdr->frame_control)) { - txq->need_update = 1; - if (qc) - priv->stations[sta_id].tid[tid].seq_number = seq_number; - } else { - wait_write_ptr = 1; - txq->need_update = 0; - } - - IWL_DEBUG_TX(priv, "sequence nr = 0X%x \n", - le16_to_cpu(out_cmd->hdr.sequence)); - IWL_DEBUG_TX(priv, "tx_flags = 0X%x \n", le32_to_cpu(tx->tx_flags)); - iwl_print_hex_dump(priv, IWL_DL_TX, tx, sizeof(*tx)); - iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx->hdr, - ieee80211_hdrlen(fc)); - - /* - * Use the first empty entry in this queue's command buffer array - * to contain the Tx command and MAC header concatenated together - * (payload data will be in another buffer). - * Size of this varies, due to varying MAC header length. - * If end is not dword aligned, we'll have 2 extra bytes at the end - * of the MAC header (device reads on dword boundaries). - * We'll tell device about this padding later. - */ - len = sizeof(struct iwl3945_tx_cmd) + - sizeof(struct iwl_cmd_header) + hdr_len; - - len_org = len; - len = (len + 3) & ~3; - - if (len_org != len) - len_org = 1; - else - len_org = 0; - - /* Physical address of this Tx command's header (not MAC header!), - * within command buffer array. */ - txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr, - len, PCI_DMA_TODEVICE); - /* we do not map meta data ... so we can safely access address to - * provide to unmap command*/ - pci_unmap_addr_set(out_meta, mapping, txcmd_phys); - pci_unmap_len_set(out_meta, len, len); - - /* Add buffer containing Tx command and MAC(!) header to TFD's - * first entry */ - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - txcmd_phys, len, 1, 0); - - - /* Set up TFD's 2nd entry to point directly to remainder of skb, - * if any (802.11 null frames have no payload). */ - len = skb->len - hdr_len; - if (len) { - phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len, - len, PCI_DMA_TODEVICE); - priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq, - phys_addr, len, - 0, U32_PAD(len)); - } - - - /* Tell device the write index *just past* this latest filled TFD */ - q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd); - rc = iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - - if (rc) - return rc; - - if ((iwl_queue_space(q) < q->high_mark) - && priv->mac80211_registered) { - if (wait_write_ptr) { - spin_lock_irqsave(&priv->lock, flags); - txq->need_update = 1; - iwl_txq_update_write_ptr(priv, txq); - spin_unlock_irqrestore(&priv->lock, flags); - } - - iwl_stop_queue(priv, skb_get_queue_mapping(skb)); - } - - return 0; - -drop_unlock: - spin_unlock_irqrestore(&priv->lock, flags); -drop: - return -1; -} - -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - -#include "iwl-spectrum.h" - -#define BEACON_TIME_MASK_LOW 0x00FFFFFF -#define BEACON_TIME_MASK_HIGH 0xFF000000 -#define TIME_UNIT 1024 - -/* - * extended beacon time format - * time in usec will be changed into a 32-bit value in 8:24 format - * the high 1 byte is the beacon counts - * the lower 3 bytes is the time in usec within one beacon interval - */ - -static u32 iwl3945_usecs_to_beacons(u32 usec, u32 beacon_interval) -{ - u32 quot; - u32 rem; - u32 interval = beacon_interval * 1024; - - if (!interval || !usec) - return 0; - - quot = (usec / interval) & (BEACON_TIME_MASK_HIGH >> 24); - rem = (usec % interval) & BEACON_TIME_MASK_LOW; - - return (quot << 24) + rem; -} - -/* base is usually what we get from ucode with each received frame, - * the same as HW timer counter counting down - */ - -static __le32 iwl3945_add_beacon_time(u32 base, u32 addon, u32 beacon_interval) -{ - u32 base_low = base & BEACON_TIME_MASK_LOW; - u32 addon_low = addon & BEACON_TIME_MASK_LOW; - u32 interval = beacon_interval * TIME_UNIT; - u32 res = (base & BEACON_TIME_MASK_HIGH) + - (addon & BEACON_TIME_MASK_HIGH); - - if (base_low > addon_low) - res += base_low - addon_low; - else if (base_low < addon_low) { - res += interval + base_low - addon_low; - res += (1 << 24); - } else - res += (1 << 24); - - return cpu_to_le32(res); -} - -static int iwl3945_get_measurement(struct iwl_priv *priv, - struct ieee80211_measurement_params *params, - u8 type) -{ - struct iwl_spectrum_cmd spectrum; - struct iwl_rx_packet *res; - struct iwl_host_cmd cmd = { - .id = REPLY_SPECTRUM_MEASUREMENT_CMD, - .data = (void *)&spectrum, - .flags = CMD_WANT_SKB, - }; - u32 add_time = le64_to_cpu(params->start_time); - int rc; - int spectrum_resp_status; - int duration = le16_to_cpu(params->duration); - - if (iwl_is_associated(priv)) - add_time = - iwl3945_usecs_to_beacons( - le64_to_cpu(params->start_time) - priv->last_tsf, - le16_to_cpu(priv->rxon_timing.beacon_interval)); - - memset(&spectrum, 0, sizeof(spectrum)); - - spectrum.channel_count = cpu_to_le16(1); - spectrum.flags = - RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK; - spectrum.filter_flags = MEASUREMENT_FILTER_FLAG; - cmd.len = sizeof(spectrum); - spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len)); - - if (iwl_is_associated(priv)) - spectrum.start_time = - iwl3945_add_beacon_time(priv->last_beacon_time, - add_time, - le16_to_cpu(priv->rxon_timing.beacon_interval)); - else - spectrum.start_time = 0; - - spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT); - spectrum.channels[0].channel = params->channel; - spectrum.channels[0].type = type; - if (priv->active_rxon.flags & RXON_FLG_BAND_24G_MSK) - spectrum.flags |= RXON_FLG_BAND_24G_MSK | - RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK; - - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - return rc; - - res = (struct iwl_rx_packet *)cmd.reply_skb->data; - if (res->hdr.flags & IWL_CMD_FAILED_MSK) { - IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n"); - rc = -EIO; - } - - spectrum_resp_status = le16_to_cpu(res->u.spectrum.status); - switch (spectrum_resp_status) { - case 0: /* Command will be handled */ - if (res->u.spectrum.id != 0xff) { - IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n", - res->u.spectrum.id); - priv->measurement_status &= ~MEASUREMENT_READY; - } - priv->measurement_status |= MEASUREMENT_ACTIVE; - rc = 0; - break; - - case 1: /* Command will not be handled */ - rc = -EAGAIN; - break; - } - - dev_kfree_skb_any(cmd.reply_skb); - - return rc; -} -#endif - -static void iwl3945_rx_reply_alive(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl_alive_resp *palive; - struct delayed_work *pwork; - - palive = &pkt->u.alive_frame; - - IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision " - "0x%01X 0x%01X\n", - palive->is_valid, palive->ver_type, - palive->ver_subtype); - - if (palive->ver_subtype == INITIALIZE_SUBTYPE) { - IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); - memcpy(&priv->card_alive_init, &pkt->u.alive_frame, - sizeof(struct iwl_alive_resp)); - pwork = &priv->init_alive_start; - } else { - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - memcpy(&priv->card_alive, &pkt->u.alive_frame, - sizeof(struct iwl_alive_resp)); - pwork = &priv->alive_start; - iwl3945_disable_events(priv); - } - - /* We delay the ALIVE response by 5ms to - * give the HW RF Kill time to activate... */ - if (palive->is_valid == UCODE_VALID_OK) - queue_delayed_work(priv->workqueue, pwork, - msecs_to_jiffies(5)); - else - IWL_WARN(priv, "uCode did not respond OK.\n"); -} - -static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; -#endif - - IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status); - return; -} - -static void iwl3945_bg_beacon_update(struct work_struct *work) -{ - struct iwl_priv *priv = - container_of(work, struct iwl_priv, beacon_update); - struct sk_buff *beacon; - - /* Pull updated AP beacon from mac80211. will fail if not in AP mode */ - beacon = ieee80211_beacon_get(priv->hw, priv->vif); - - if (!beacon) { - IWL_ERR(priv, "update beacon failed\n"); - return; - } - - mutex_lock(&priv->mutex); - /* new beacon skb is allocated every time; dispose previous.*/ - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - priv->ibss_beacon = beacon; - mutex_unlock(&priv->mutex); - - iwl3945_send_beacon_cmd(priv); -} - -static void iwl3945_rx_beacon_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ -#ifdef CONFIG_IWLWIFI_DEBUG - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status); - u8 rate = beacon->beacon_notify_hdr.rate; - - IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d " - "tsf %d %d rate %d\n", - le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK, - beacon->beacon_notify_hdr.failure_frame, - le32_to_cpu(beacon->ibss_mgr_status), - le32_to_cpu(beacon->high_tsf), - le32_to_cpu(beacon->low_tsf), rate); -#endif - - if ((priv->iw_mode == NL80211_IFTYPE_AP) && - (!test_bit(STATUS_EXIT_PENDING, &priv->status))) - queue_work(priv->workqueue, &priv->beacon_update); -} - -/* Handle notification from uCode that card's power state is changing - * due to software, hardware, or critical temperature RFKILL */ -static void iwl3945_rx_card_state_notif(struct iwl_priv *priv, - struct iwl_rx_mem_buffer *rxb) -{ - struct iwl_rx_packet *pkt = (void *)rxb->skb->data; - u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags); - unsigned long status = priv->status; - - IWL_WARN(priv, "Card state received: HW:%s SW:%s\n", - (flags & HW_CARD_DISABLED) ? "Kill" : "On", - (flags & SW_CARD_DISABLED) ? "Kill" : "On"); - - iwl_write32(priv, CSR_UCODE_DRV_GP1_SET, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - if (flags & HW_CARD_DISABLED) - set_bit(STATUS_RF_KILL_HW, &priv->status); - else - clear_bit(STATUS_RF_KILL_HW, &priv->status); - - - iwl_scan_cancel(priv); - - if ((test_bit(STATUS_RF_KILL_HW, &status) != - test_bit(STATUS_RF_KILL_HW, &priv->status))) - wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->status)); - else - wake_up_interruptible(&priv->wait_command_queue); -} - -/** - * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks - * - * Setup the RX handlers for each of the reply types sent from the uCode - * to the host. - * - * This function chains into the hardware specific files for them to setup - * any hardware specific handlers as well. - */ -static void iwl3945_setup_rx_handlers(struct iwl_priv *priv) -{ - priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive; - priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta; - priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error; - priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa; - priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif; - priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] = - iwl_rx_pm_debug_statistics_notif; - priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif; - - /* - * The same handler is used for both the REPLY to a discrete - * statistics request from the host as well as for the periodic - * statistics notifications (after received beacons) from the uCode. - */ - priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_hw_rx_statistics; - priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics; - - iwl_setup_spectrum_handlers(priv); - iwl_setup_rx_scan_handlers(priv); - priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif; - - /* Set up hardware specific Rx handlers */ - iwl3945_hw_rx_handler_setup(priv); -} - -/************************** RX-FUNCTIONS ****************************/ -/* - * Rx theory of operation - * - * The host allocates 32 DMA target addresses and passes the host address - * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is - * 0 to 31 - * - * Rx Queue Indexes - * The host/firmware share two index registers for managing the Rx buffers. - * - * The READ index maps to the first position that the firmware may be writing - * to -- the driver can read up to (but not including) this position and get - * good data. - * The READ index is managed by the firmware once the card is enabled. - * - * The WRITE index maps to the last position the driver has read from -- the - * position preceding WRITE is the last slot the firmware can place a packet. - * - * The queue is empty (no good data) if WRITE = READ - 1, and is full if - * WRITE = READ. - * - * During initialization, the host sets up the READ queue position to the first - * INDEX position, and WRITE to the last (READ - 1 wrapped) - * - * When the firmware places a packet in a buffer, it will advance the READ index - * and fire the RX interrupt. The driver can then query the READ index and - * process as many packets as possible, moving the WRITE index forward as it - * resets the Rx queue buffers with new memory. - * - * The management in the driver is as follows: - * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free. When - * iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled - * to replenish the iwl->rxq->rx_free. - * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the - * iwl->rxq is replenished and the READ INDEX is updated (updating the - * 'processed' and 'read' driver indexes as well) - * + A received packet is processed and handed to the kernel network stack, - * detached from the iwl->rxq. The driver 'processed' index is updated. - * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free - * list. If there are no allocated buffers in iwl->rxq->rx_free, the READ - * INDEX is not incremented and iwl->status(RX_STALLED) is set. If there - * were enough free buffers and RX_STALLED is set it is cleared. - * - * - * Driver sequence: - * - * iwl3945_rx_replenish() Replenishes rx_free list from rx_used, and calls - * iwl3945_rx_queue_restock - * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx - * queue, updates firmware pointers, and updates - * the WRITE index. If insufficient rx_free buffers - * are available, schedules iwl3945_rx_replenish - * - * -- enable interrupts -- - * ISR - iwl3945_rx() Detach iwl_rx_mem_buffers from pool up to the - * READ INDEX, detaching the SKB from the pool. - * Moves the packet buffer from queue to rx_used. - * Calls iwl3945_rx_queue_restock to refill any empty - * slots. - * ... - * - */ - -/** - * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr - */ -static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv, - dma_addr_t dma_addr) -{ - return cpu_to_le32((u32)dma_addr); -} - -/** - * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool - * - * If there are slots in the RX queue that need to be restocked, - * and we have free pre-allocated buffers, fill the ranks as much - * as we can, pulling from rx_free. - * - * This moves the 'write' index forward to catch up with 'processed', and - * also updates the memory address in the firmware to reference the new - * target buffer. - */ -static int iwl3945_rx_queue_restock(struct iwl_priv *priv) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - unsigned long flags; - int write, rc; - - spin_lock_irqsave(&rxq->lock, flags); - write = rxq->write & ~0x7; - while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) { - /* Get next free Rx buffer, remove from free list */ - element = rxq->rx_free.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - - /* Point to Rx buffer via next RBD in circular buffer */ - rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr); - rxq->queue[rxq->write] = rxb; - rxq->write = (rxq->write + 1) & RX_QUEUE_MASK; - rxq->free_count--; - } - spin_unlock_irqrestore(&rxq->lock, flags); - /* If the pre-allocated buffer pool is dropping low, schedule to - * refill it */ - if (rxq->free_count <= RX_LOW_WATERMARK) - queue_work(priv->workqueue, &priv->rx_replenish); - - - /* If we've added more space for the firmware to place data, tell it. - * Increment device's write pointer in multiples of 8. */ - if ((rxq->write_actual != (rxq->write & ~0x7)) - || (abs(rxq->write - rxq->read) > 7)) { - spin_lock_irqsave(&rxq->lock, flags); - rxq->need_update = 1; - spin_unlock_irqrestore(&rxq->lock, flags); - rc = iwl_rx_queue_update_write_ptr(priv, rxq); - if (rc) - return rc; - } - - return 0; -} - -/** - * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free - * - * When moving to rx_free an SKB is allocated for the slot. - * - * Also restock the Rx queue via iwl3945_rx_queue_restock. - * This is called as a scheduled work item (except for during initialization) - */ -static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority) -{ - struct iwl_rx_queue *rxq = &priv->rxq; - struct list_head *element; - struct iwl_rx_mem_buffer *rxb; - struct sk_buff *skb; - unsigned long flags; - - while (1) { - spin_lock_irqsave(&rxq->lock, flags); - - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - return; - } - spin_unlock_irqrestore(&rxq->lock, flags); - - if (rxq->free_count > RX_LOW_WATERMARK) - priority |= __GFP_NOWARN; - /* Alloc a new receive buffer */ - skb = alloc_skb(priv->hw_params.rx_buf_size, priority); - if (!skb) { - if (net_ratelimit()) - IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); - if ((rxq->free_count <= RX_LOW_WATERMARK) && - net_ratelimit()) - IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n", - priority == GFP_ATOMIC ? "GFP_ATOMIC" : "GFP_KERNEL", - rxq->free_count); - /* We don't reschedule replenish work here -- we will - * call the restock method and if it still needs - * more buffers it will schedule replenish */ - break; - } - - spin_lock_irqsave(&rxq->lock, flags); - if (list_empty(&rxq->rx_used)) { - spin_unlock_irqrestore(&rxq->lock, flags); - dev_kfree_skb_any(skb); - return; - } - element = rxq->rx_used.next; - rxb = list_entry(element, struct iwl_rx_mem_buffer, list); - list_del(element); - spin_unlock_irqrestore(&rxq->lock, flags); - - rxb->skb = skb; - - /* If radiotap head is required, reserve some headroom here. - * The physical head count is a variable rx_stats->phy_count. - * We reserve 4 bytes here. Plus these extra bytes, the - * headroom of the physical head should be enough for the - * radiotap head that iwl3945 supported. See iwl3945_rt. - */ - skb_reserve(rxb->skb, 4); - - /* Get physical address of RB/SKB */ - rxb->real_dma_addr = pci_map_single(priv->pci_dev, - rxb->skb->data, - priv->hw_params.rx_buf_size, - PCI_DMA_FROMDEVICE); - - spin_lock_irqsave(&rxq->lock, flags); - list_add_tail(&rxb->list, &rxq->rx_free); - priv->alloc_rxb_skb++; - rxq->free_count++; - spin_unlock_irqrestore(&rxq->lock, flags); - } -} - -void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - unsigned long flags; - int i; - spin_lock_irqsave(&rxq->lock, flags); - INIT_LIST_HEAD(&rxq->rx_free); - INIT_LIST_HEAD(&rxq->rx_used); - /* Fill the rx_used queue with _all_ of the Rx buffers */ - for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) { - /* In the reset function, these buffers may have been allocated - * to an SKB, so we need to unmap and free potential storage */ - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, - rxq->pool[i].real_dma_addr, - priv->hw_params.rx_buf_size, - PCI_DMA_FROMDEVICE); - priv->alloc_rxb_skb--; - dev_kfree_skb(rxq->pool[i].skb); - rxq->pool[i].skb = NULL; - } - list_add_tail(&rxq->pool[i].list, &rxq->rx_used); - } - - /* Set us so that we have processed and used all buffers, but have - * not restocked the Rx queue with fresh buffers */ - rxq->read = rxq->write = 0; - rxq->free_count = 0; - rxq->write_actual = 0; - spin_unlock_irqrestore(&rxq->lock, flags); -} - -void iwl3945_rx_replenish(void *data) -{ - struct iwl_priv *priv = data; - unsigned long flags; - - iwl3945_rx_allocate(priv, GFP_KERNEL); - - spin_lock_irqsave(&priv->lock, flags); - iwl3945_rx_queue_restock(priv); - spin_unlock_irqrestore(&priv->lock, flags); -} - -static void iwl3945_rx_replenish_now(struct iwl_priv *priv) -{ - iwl3945_rx_allocate(priv, GFP_ATOMIC); - - iwl3945_rx_queue_restock(priv); -} - - -/* Assumes that the skb field of the buffers in 'pool' is kept accurate. - * If an SKB has been detached, the POOL needs to have its SKB set to NULL - * This free routine walks the list of POOL entries and if SKB is set to - * non NULL it is unmapped and freed - */ -static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq) -{ - int i; - for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) { - if (rxq->pool[i].skb != NULL) { - pci_unmap_single(priv->pci_dev, - rxq->pool[i].real_dma_addr, - priv->hw_params.rx_buf_size, - PCI_DMA_FROMDEVICE); - dev_kfree_skb(rxq->pool[i].skb); - } - } - - dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd, - rxq->dma_addr); - dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status), - rxq->rb_stts, rxq->rb_stts_dma); - rxq->bd = NULL; - rxq->rb_stts = NULL; -} - - -/* Convert linear signal-to-noise ratio into dB */ -static u8 ratio2dB[100] = { -/* 0 1 2 3 4 5 6 7 8 9 */ - 0, 0, 6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */ - 20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */ - 26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */ - 29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */ - 32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */ - 34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */ - 36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */ - 37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */ - 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */ - 39, 39, 39, 39, 39, 40, 40, 40, 40, 40 /* 90 - 99 */ -}; - -/* Calculates a relative dB value from a ratio of linear - * (i.e. not dB) signal levels. - * Conversion assumes that levels are voltages (20*log), not powers (10*log). */ -int iwl3945_calc_db_from_ratio(int sig_ratio) -{ - /* 1000:1 or higher just report as 60 dB */ - if (sig_ratio >= 1000) - return 60; - - /* 100:1 or higher, divide by 10 and use table, - * add 20 dB to make up for divide by 10 */ - if (sig_ratio >= 100) - return 20 + (int)ratio2dB[sig_ratio/10]; - - /* We shouldn't see this */ - if (sig_ratio < 1) - return 0; - - /* Use table for ratios 1:1 - 99:1 */ - return (int)ratio2dB[sig_ratio]; -} - -#define PERFECT_RSSI (-20) /* dBm */ -#define WORST_RSSI (-95) /* dBm */ -#define RSSI_RANGE (PERFECT_RSSI - WORST_RSSI) - -/* Calculate an indication of rx signal quality (a percentage, not dBm!). - * See http://www.ces.clemson.edu/linux/signal_quality.shtml for info - * about formulas used below. */ -int iwl3945_calc_sig_qual(int rssi_dbm, int noise_dbm) -{ - int sig_qual; - int degradation = PERFECT_RSSI - rssi_dbm; - - /* If we get a noise measurement, use signal-to-noise ratio (SNR) - * as indicator; formula is (signal dbm - noise dbm). - * SNR at or above 40 is a great signal (100%). - * Below that, scale to fit SNR of 0 - 40 dB within 0 - 100% indicator. - * Weakest usable signal is usually 10 - 15 dB SNR. */ - if (noise_dbm) { - if (rssi_dbm - noise_dbm >= 40) - return 100; - else if (rssi_dbm < noise_dbm) - return 0; - sig_qual = ((rssi_dbm - noise_dbm) * 5) / 2; - - /* Else use just the signal level. - * This formula is a least squares fit of data points collected and - * compared with a reference system that had a percentage (%) display - * for signal quality. */ - } else - sig_qual = (100 * (RSSI_RANGE * RSSI_RANGE) - degradation * - (15 * RSSI_RANGE + 62 * degradation)) / - (RSSI_RANGE * RSSI_RANGE); - - if (sig_qual > 100) - sig_qual = 100; - else if (sig_qual < 1) - sig_qual = 0; - - return sig_qual; -} - -/** - * iwl3945_rx_handle - Main entry function for receiving responses from uCode - * - * Uses the priv->rx_handlers callback function array to invoke - * the appropriate handlers, including command responses, - * frame-received notifications, and other notifications. - */ -static void iwl3945_rx_handle(struct iwl_priv *priv) -{ - struct iwl_rx_mem_buffer *rxb; - struct iwl_rx_packet *pkt; - struct iwl_rx_queue *rxq = &priv->rxq; - u32 r, i; - int reclaim; - unsigned long flags; - u8 fill_rx = 0; - u32 count = 8; - int total_empty = 0; - - /* uCode's read index (stored in shared DRAM) indicates the last Rx - * buffer that the driver may process (last buffer filled by ucode). */ - r = le16_to_cpu(rxq->rb_stts->closed_rb_num) & 0x0FFF; - i = rxq->read; - - /* calculate total frames need to be restock after handling RX */ - total_empty = r - priv->rxq.write_actual; - if (total_empty < 0) - total_empty += RX_QUEUE_SIZE; - - if (total_empty > (RX_QUEUE_SIZE / 2)) - fill_rx = 1; - /* Rx interrupt, but nothing sent from uCode */ - if (i == r) - IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i); - - while (i != r) { - rxb = rxq->queue[i]; - - /* If an RXB doesn't have a Rx queue slot associated with it, - * then a bug has been introduced in the queue refilling - * routines -- catch it here */ - BUG_ON(rxb == NULL); - - rxq->queue[i] = NULL; - - pci_unmap_single(priv->pci_dev, rxb->real_dma_addr, - priv->hw_params.rx_buf_size, - PCI_DMA_FROMDEVICE); - pkt = (struct iwl_rx_packet *)rxb->skb->data; - - /* Reclaim a command buffer only if this packet is a response - * to a (driver-originated) command. - * If the packet (e.g. Rx frame) originated from uCode, - * there is no command buffer to reclaim. - * Ucode should set SEQ_RX_FRAME bit if ucode-originated, - * but apparently a few don't get set; catch them here. */ - reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) && - (pkt->hdr.cmd != STATISTICS_NOTIFICATION) && - (pkt->hdr.cmd != REPLY_TX); - - /* Based on type of command response or notification, - * handle those that need handling via function in - * rx_handlers table. See iwl3945_setup_rx_handlers() */ - if (priv->rx_handlers[pkt->hdr.cmd]) { - IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, - get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); - priv->rx_handlers[pkt->hdr.cmd] (priv, rxb); - priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; - } else { - /* No handling needed */ - IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n", - r, i, get_cmd_string(pkt->hdr.cmd), - pkt->hdr.cmd); - } - - if (reclaim) { - /* Invoke any callbacks, transfer the skb to caller, and - * fire off the (possibly) blocking iwl_send_cmd() - * as we reclaim the driver command queue */ - if (rxb && rxb->skb) - iwl_tx_cmd_complete(priv, rxb); - else - IWL_WARN(priv, "Claim null rxb?\n"); - } - - /* For now we just don't re-use anything. We can tweak this - * later to try and re-use notification packets and SKBs that - * fail to Rx correctly */ - if (rxb->skb != NULL) { - priv->alloc_rxb_skb--; - dev_kfree_skb_any(rxb->skb); - rxb->skb = NULL; - } - - spin_lock_irqsave(&rxq->lock, flags); - list_add_tail(&rxb->list, &priv->rxq.rx_used); - spin_unlock_irqrestore(&rxq->lock, flags); - i = (i + 1) & RX_QUEUE_MASK; - /* If there are a lot of unused frames, - * restock the Rx queue so ucode won't assert. */ - if (fill_rx) { - count++; - if (count >= 8) { - priv->rxq.read = i; - iwl3945_rx_replenish_now(priv); - count = 0; - } - } - } - - /* Backtrack one entry */ - priv->rxq.read = i; - if (fill_rx) - iwl3945_rx_replenish_now(priv); - else - iwl3945_rx_queue_restock(priv); -} - -/* call this function to flush any scheduled tasklet */ -static inline void iwl_synchronize_irq(struct iwl_priv *priv) -{ - /* wait to make sure we flush pending tasklet*/ - synchronize_irq(priv->pci_dev->irq); - tasklet_kill(&priv->irq_tasklet); -} - -#ifdef CONFIG_IWLWIFI_DEBUG -static const char *desc_lookup(int i) -{ - switch (i) { - case 1: - return "FAIL"; - case 2: - return "BAD_PARAM"; - case 3: - return "BAD_CHECKSUM"; - case 4: - return "NMI_INTERRUPT"; - case 5: - return "SYSASSERT"; - case 6: - return "FATAL_ERROR"; - } - - return "UNKNOWN"; -} - -#define ERROR_START_OFFSET (1 * sizeof(u32)) -#define ERROR_ELEM_SIZE (7 * sizeof(u32)) - -void iwl3945_dump_nic_error_log(struct iwl_priv *priv) -{ - u32 i; - u32 desc, time, count, base, data1; - u32 blink1, blink2, ilink1, ilink2; - - base = le32_to_cpu(priv->card_alive.error_event_table_ptr); - - if (!iwl3945_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); - return; - } - - - count = iwl_read_targ_mem(priv, base); - - if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) { - IWL_ERR(priv, "Start IWL Error Log Dump:\n"); - IWL_ERR(priv, "Status: 0x%08lX, count: %d\n", - priv->status, count); - } - - IWL_ERR(priv, "Desc Time asrtPC blink2 " - "ilink1 nmiPC Line\n"); - for (i = ERROR_START_OFFSET; - i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET; - i += ERROR_ELEM_SIZE) { - desc = iwl_read_targ_mem(priv, base + i); - time = - iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32)); - blink1 = - iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32)); - blink2 = - iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32)); - ilink1 = - iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32)); - ilink2 = - iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32)); - data1 = - iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32)); - - IWL_ERR(priv, - "%-13s (#%d) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n", - desc_lookup(desc), desc, time, blink1, blink2, - ilink1, ilink2, data1); - } - -} - -#define EVENT_START_OFFSET (6 * sizeof(u32)) - -/** - * iwl3945_print_event_log - Dump error event log to syslog - * - */ -static void iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx, - u32 num_events, u32 mode) -{ - u32 i; - u32 base; /* SRAM byte address of event log header */ - u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */ - u32 ptr; /* SRAM byte address of log data */ - u32 ev, time, data; /* event log data */ - - if (num_events == 0) - return; - - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - - if (mode == 0) - event_size = 2 * sizeof(u32); - else - event_size = 3 * sizeof(u32); - - ptr = base + EVENT_START_OFFSET + (start_idx * event_size); - - /* "time" is actually "data" for mode 0 (no timestamp). - * place event id # at far right for easier visual parsing. */ - for (i = 0; i < num_events; i++) { - ev = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - time = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - if (mode == 0) { - /* data, ev */ - IWL_ERR(priv, "0x%08x\t%04u\n", time, ev); - } else { - data = iwl_read_targ_mem(priv, ptr); - ptr += sizeof(u32); - IWL_ERR(priv, "%010u\t0x%08x\t%04u\n", time, data, ev); - } - } -} - -void iwl3945_dump_nic_event_log(struct iwl_priv *priv) -{ - u32 base; /* SRAM byte address of event log header */ - u32 capacity; /* event log capacity in # entries */ - u32 mode; /* 0 - no timestamp, 1 - timestamp recorded */ - u32 num_wraps; /* # times uCode wrapped to top of log */ - u32 next_entry; /* index of next entry to be written by uCode */ - u32 size; /* # entries that we'll print */ - - base = le32_to_cpu(priv->card_alive.log_event_table_ptr); - if (!iwl3945_hw_valid_rtc_data_addr(base)) { - IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); - return; - } - - /* event log header */ - capacity = iwl_read_targ_mem(priv, base); - mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32))); - num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32))); - next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32))); - - size = num_wraps ? capacity : next_entry; - - /* bail out if nothing in log */ - if (size == 0) { - IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n"); - return; - } - - IWL_ERR(priv, "Start IWL Event Log Dump: display count %d, wraps %d\n", - size, num_wraps); - - /* if uCode has wrapped back to top of log, start at the oldest entry, - * i.e the next one that uCode would fill. */ - if (num_wraps) - iwl3945_print_event_log(priv, next_entry, - capacity - next_entry, mode); - - /* (then/else) start at top of log */ - iwl3945_print_event_log(priv, 0, next_entry, mode); - -} -#else -void iwl3945_dump_nic_event_log(struct iwl_priv *priv) -{ -} - -void iwl3945_dump_nic_error_log(struct iwl_priv *priv) -{ -} - -#endif - -static void iwl3945_irq_tasklet(struct iwl_priv *priv) -{ - u32 inta, handled = 0; - u32 inta_fh; - unsigned long flags; -#ifdef CONFIG_IWLWIFI_DEBUG - u32 inta_mask; -#endif - - spin_lock_irqsave(&priv->lock, flags); - - /* Ack/clear/reset pending uCode interrupts. - * Note: Some bits in CSR_INT are "OR" of bits in CSR_FH_INT_STATUS, - * and will clear only when CSR_FH_INT_STATUS gets cleared. */ - inta = iwl_read32(priv, CSR_INT); - iwl_write32(priv, CSR_INT, inta); - - /* Ack/clear/reset pending flow-handler (DMA) interrupts. - * Any new interrupts that happen after this, either while we're - * in this tasklet, or later, will show up in next ISR/tasklet. */ - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & IWL_DL_ISR) { - /* just for debug */ - inta_mask = iwl_read32(priv, CSR_INT_MASK); - IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n", - inta, inta_mask, inta_fh); - } -#endif - - /* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not - * atomic, make sure that inta covers all the interrupts that - * we've discovered, even if FH interrupt came in just after - * reading CSR_INT. */ - if (inta_fh & CSR39_FH_INT_RX_MASK) - inta |= CSR_INT_BIT_FH_RX; - if (inta_fh & CSR39_FH_INT_TX_MASK) - inta |= CSR_INT_BIT_FH_TX; - - /* Now service all interrupt bits discovered above. */ - if (inta & CSR_INT_BIT_HW_ERR) { - IWL_ERR(priv, "Hardware error detected. Restarting.\n"); - - /* Tell the device to stop sending interrupts */ - iwl_disable_interrupts(priv); - - priv->isr_stats.hw++; - iwl_irq_handle_error(priv); - - handled |= CSR_INT_BIT_HW_ERR; - - spin_unlock_irqrestore(&priv->lock, flags); - - return; - } - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - /* NIC fires this, but we don't use it, redundant with WAKEUP */ - if (inta & CSR_INT_BIT_SCD) { - IWL_DEBUG_ISR(priv, "Scheduler finished to transmit " - "the frame/frames.\n"); - priv->isr_stats.sch++; - } - - /* Alive notification via Rx interrupt will do the real work */ - if (inta & CSR_INT_BIT_ALIVE) { - IWL_DEBUG_ISR(priv, "Alive interrupt\n"); - priv->isr_stats.alive++; - } - } -#endif - /* Safely ignore these bits for debug checks below */ - inta &= ~(CSR_INT_BIT_SCD | CSR_INT_BIT_ALIVE); - - /* Error detected by uCode */ - if (inta & CSR_INT_BIT_SW_ERR) { - IWL_ERR(priv, "Microcode SW error detected. " - "Restarting 0x%X.\n", inta); - priv->isr_stats.sw++; - priv->isr_stats.sw_err = inta; - iwl_irq_handle_error(priv); - handled |= CSR_INT_BIT_SW_ERR; - } - - /* uCode wakes up after power-down sleep */ - if (inta & CSR_INT_BIT_WAKEUP) { - IWL_DEBUG_ISR(priv, "Wakeup interrupt\n"); - iwl_rx_queue_update_write_ptr(priv, &priv->rxq); - iwl_txq_update_write_ptr(priv, &priv->txq[0]); - iwl_txq_update_write_ptr(priv, &priv->txq[1]); - iwl_txq_update_write_ptr(priv, &priv->txq[2]); - iwl_txq_update_write_ptr(priv, &priv->txq[3]); - iwl_txq_update_write_ptr(priv, &priv->txq[4]); - iwl_txq_update_write_ptr(priv, &priv->txq[5]); - - priv->isr_stats.wakeup++; - handled |= CSR_INT_BIT_WAKEUP; - } - - /* All uCode command responses, including Tx command responses, - * Rx "responses" (frame-received notification), and other - * notifications from uCode come through here*/ - if (inta & (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX)) { - iwl3945_rx_handle(priv); - priv->isr_stats.rx++; - handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX); - } - - if (inta & CSR_INT_BIT_FH_TX) { - IWL_DEBUG_ISR(priv, "Tx interrupt\n"); - priv->isr_stats.tx++; - - iwl_write32(priv, CSR_FH_INT_STATUS, (1 << 6)); - iwl_write_direct32(priv, FH39_TCSR_CREDIT - (FH39_SRVC_CHNL), 0x0); - handled |= CSR_INT_BIT_FH_TX; - } - - if (inta & ~handled) { - IWL_ERR(priv, "Unhandled INTA bits 0x%08x\n", inta & ~handled); - priv->isr_stats.unhandled++; - } - - if (inta & ~priv->inta_mask) { - IWL_WARN(priv, "Disabled INTA bits 0x%08x were pending\n", - inta & ~priv->inta_mask); - IWL_WARN(priv, " with FH_INT = 0x%08x\n", inta_fh); - } - - /* Re-enable all interrupts */ - /* only Re-enable if disabled by irq */ - if (test_bit(STATUS_INT_ENABLED, &priv->status)) - iwl_enable_interrupts(priv); - -#ifdef CONFIG_IWLWIFI_DEBUG - if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) { - inta = iwl_read32(priv, CSR_INT); - inta_mask = iwl_read32(priv, CSR_INT_MASK); - inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS); - IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, " - "flags 0x%08lx\n", inta, inta_mask, inta_fh, flags); - } -#endif - spin_unlock_irqrestore(&priv->lock, flags); -} - -static int iwl3945_get_channels_for_scan(struct iwl_priv *priv, - enum ieee80211_band band, - u8 is_active, u8 n_probes, - struct iwl3945_scan_channel *scan_ch) -{ - struct ieee80211_channel *chan; - const struct ieee80211_supported_band *sband; - const struct iwl_channel_info *ch_info; - u16 passive_dwell = 0; - u16 active_dwell = 0; - int added, i; - - sband = iwl_get_hw_mode(priv, band); - if (!sband) - return 0; - - active_dwell = iwl_get_active_dwell_time(priv, band, n_probes); - passive_dwell = iwl_get_passive_dwell_time(priv, band); - - if (passive_dwell <= active_dwell) - passive_dwell = active_dwell + 1; - - for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) { - chan = priv->scan_request->channels[i]; - - if (chan->band != band) - continue; - - scan_ch->channel = chan->hw_value; - - ch_info = iwl_get_channel_info(priv, band, scan_ch->channel); - if (!is_channel_valid(ch_info)) { - IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n", - scan_ch->channel); - continue; - } - - scan_ch->active_dwell = cpu_to_le16(active_dwell); - scan_ch->passive_dwell = cpu_to_le16(passive_dwell); - /* If passive , set up for auto-switch - * and use long active_dwell time. - */ - if (!is_active || is_channel_passive(ch_info) || - (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) { - scan_ch->type = 0; /* passive */ - if (IWL_UCODE_API(priv->ucode_ver) == 1) - scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1); - } else { - scan_ch->type = 1; /* active */ - } - - /* Set direct probe bits. These may be used both for active - * scan channels (probes gets sent right away), - * or for passive channels (probes get se sent only after - * hearing clear Rx packet).*/ - if (IWL_UCODE_API(priv->ucode_ver) >= 2) { - if (n_probes) - scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes); - } else { - /* uCode v1 does not allow setting direct probe bits on - * passive channel. */ - if ((scan_ch->type & 1) && n_probes) - scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes); - } - - /* Set txpower levels to defaults */ - scan_ch->tpc.dsp_atten = 110; - /* scan_pwr_info->tpc.dsp_atten; */ - - /*scan_pwr_info->tpc.tx_gain; */ - if (band == IEEE80211_BAND_5GHZ) - scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3; - else { - scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3)); - /* NOTE: if we were doing 6Mb OFDM for scans we'd use - * power level: - * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3; - */ - } - - IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n", - scan_ch->channel, - (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE", - (scan_ch->type & 1) ? - active_dwell : passive_dwell); - - scan_ch++; - added++; - } - - IWL_DEBUG_SCAN(priv, "total channels to scan %d \n", added); - return added; -} - -static void iwl3945_init_hw_rates(struct iwl_priv *priv, - struct ieee80211_rate *rates) -{ - int i; - - for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) { - rates[i].bitrate = iwl3945_rates[i].ieee * 5; - rates[i].hw_value = i; /* Rate scaling will work on indexes */ - rates[i].hw_value_short = i; - rates[i].flags = 0; - if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) { - /* - * If CCK != 1M then set short preamble rate flag. - */ - rates[i].flags |= (iwl3945_rates[i].plcp == 10) ? - 0 : IEEE80211_RATE_SHORT_PREAMBLE; - } - } -} - -/****************************************************************************** - * - * uCode download functions - * - ******************************************************************************/ - -static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv) -{ - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data); - iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot); -} - -/** - * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host, - * looking at all data. - */ -static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len) -{ - u32 val; - u32 save_len = len; - int rc = 0; - u32 errcnt; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - IWL39_RTC_INST_LOWER_BOUND); - - errcnt = 0; - for (; len > 0; len -= sizeof(u32), image++) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { - IWL_ERR(priv, "uCode INST section is invalid at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - save_len - len, val, le32_to_cpu(*image)); - rc = -EIO; - errcnt++; - if (errcnt >= 20) - break; - } - } - - - if (!errcnt) - IWL_DEBUG_INFO(priv, - "ucode image in INSTRUCTION memory is good\n"); - - return rc; -} - - -/** - * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host, - * using sample data 100 bytes apart. If these sample points are good, - * it's a pretty good bet that everything between them is good, too. - */ -static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len) -{ - u32 val; - int rc = 0; - u32 errcnt = 0; - u32 i; - - IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len); - - for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) { - /* read data comes through single port, auto-incr addr */ - /* NOTE: Use the debugless read so we don't flood kernel log - * if IWL_DL_IO is set */ - iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, - i + IWL39_RTC_INST_LOWER_BOUND); - val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT); - if (val != le32_to_cpu(*image)) { -#if 0 /* Enable this if you want to see details */ - IWL_ERR(priv, "uCode INST section is invalid at " - "offset 0x%x, is 0x%x, s/b 0x%x\n", - i, val, *image); -#endif - rc = -EIO; - errcnt++; - if (errcnt >= 3) - break; - } - } - - return rc; -} - - -/** - * iwl3945_verify_ucode - determine which instruction image is in SRAM, - * and verify its contents - */ -static int iwl3945_verify_ucode(struct iwl_priv *priv) -{ - __le32 *image; - u32 len; - int rc = 0; - - /* Try bootstrap */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - rc = iwl3945_verify_inst_sparse(priv, image, len); - if (rc == 0) { - IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n"); - return 0; - } - - /* Try initialize */ - image = (__le32 *)priv->ucode_init.v_addr; - len = priv->ucode_init.len; - rc = iwl3945_verify_inst_sparse(priv, image, len); - if (rc == 0) { - IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n"); - return 0; - } - - /* Try runtime/protocol */ - image = (__le32 *)priv->ucode_code.v_addr; - len = priv->ucode_code.len; - rc = iwl3945_verify_inst_sparse(priv, image, len); - if (rc == 0) { - IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n"); - return 0; - } - - IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n"); - - /* Since nothing seems to match, show first several data entries in - * instruction SRAM, so maybe visual inspection will give a clue. - * Selection of bootstrap image (vs. other images) is arbitrary. */ - image = (__le32 *)priv->ucode_boot.v_addr; - len = priv->ucode_boot.len; - rc = iwl3945_verify_inst_full(priv, image, len); - - return rc; -} - -static void iwl3945_nic_start(struct iwl_priv *priv) -{ - /* Remove all resets to allow NIC to operate */ - iwl_write32(priv, CSR_RESET, 0); -} - -/** - * iwl3945_read_ucode - Read uCode images from disk file. - * - * Copy into buffers for card to fetch via bus-mastering - */ -static int iwl3945_read_ucode(struct iwl_priv *priv) -{ - const struct iwl_ucode_header *ucode; - int ret = -EINVAL, index; - const struct firmware *ucode_raw; - /* firmware file name contains uCode/driver compatibility version */ - const char *name_pre = priv->cfg->fw_name_pre; - const unsigned int api_max = priv->cfg->ucode_api_max; - const unsigned int api_min = priv->cfg->ucode_api_min; - char buf[25]; - u8 *src; - size_t len; - u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size; - - /* Ask kernel firmware_class module to get the boot firmware off disk. - * request_firmware() is synchronous, file is in memory on return. */ - for (index = api_max; index >= api_min; index--) { - sprintf(buf, "%s%u%s", name_pre, index, ".ucode"); - ret = request_firmware(&ucode_raw, buf, &priv->pci_dev->dev); - if (ret < 0) { - IWL_ERR(priv, "%s firmware file req failed: %d\n", - buf, ret); - if (ret == -ENOENT) - continue; - else - goto error; - } else { - if (index < api_max) - IWL_ERR(priv, "Loaded firmware %s, " - "which is deprecated. " - " Please use API v%u instead.\n", - buf, api_max); - IWL_DEBUG_INFO(priv, "Got firmware '%s' file " - "(%zd bytes) from disk\n", - buf, ucode_raw->size); - break; - } - } - - if (ret < 0) - goto error; - - /* Make sure that we got at least our header! */ - if (ucode_raw->size < priv->cfg->ops->ucode->get_header_size(1)) { - IWL_ERR(priv, "File size way too small!\n"); - ret = -EINVAL; - goto err_release; - } - - /* Data from ucode file: header followed by uCode images */ - ucode = (struct iwl_ucode_header *)ucode_raw->data; - - priv->ucode_ver = le32_to_cpu(ucode->ver); - api_ver = IWL_UCODE_API(priv->ucode_ver); - inst_size = priv->cfg->ops->ucode->get_inst_size(ucode, api_ver); - data_size = priv->cfg->ops->ucode->get_data_size(ucode, api_ver); - init_size = priv->cfg->ops->ucode->get_init_size(ucode, api_ver); - init_data_size = - priv->cfg->ops->ucode->get_init_data_size(ucode, api_ver); - boot_size = priv->cfg->ops->ucode->get_boot_size(ucode, api_ver); - src = priv->cfg->ops->ucode->get_data(ucode, api_ver); - - /* api_ver should match the api version forming part of the - * firmware filename ... but we don't check for that and only rely - * on the API version read from firmware header from here on forward */ - - if (api_ver < api_min || api_ver > api_max) { - IWL_ERR(priv, "Driver unable to support your firmware API. " - "Driver supports v%u, firmware is v%u.\n", - api_max, api_ver); - priv->ucode_ver = 0; - ret = -EINVAL; - goto err_release; - } - if (api_ver != api_max) - IWL_ERR(priv, "Firmware has old API version. Expected %u, " - "got %u. New firmware can be obtained " - "from http://www.intellinuxwireless.org.\n", - api_max, api_ver); - - IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n", - IWL_UCODE_MAJOR(priv->ucode_ver), - IWL_UCODE_MINOR(priv->ucode_ver), - IWL_UCODE_API(priv->ucode_ver), - IWL_UCODE_SERIAL(priv->ucode_ver)); - - IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n", - priv->ucode_ver); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n", - inst_size); - IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n", - data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n", - init_size); - IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n", - init_data_size); - IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n", - boot_size); - - - /* Verify size of file vs. image size info in file's header */ - if (ucode_raw->size != priv->cfg->ops->ucode->get_header_size(api_ver) + - inst_size + data_size + init_size + - init_data_size + boot_size) { - - IWL_DEBUG_INFO(priv, - "uCode file size %zd does not match expected size\n", - ucode_raw->size); - ret = -EINVAL; - goto err_release; - } - - /* Verify that uCode images will fit in card's SRAM */ - if (inst_size > IWL39_MAX_INST_SIZE) { - IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n", - inst_size); - ret = -EINVAL; - goto err_release; - } - - if (data_size > IWL39_MAX_DATA_SIZE) { - IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n", - data_size); - ret = -EINVAL; - goto err_release; - } - if (init_size > IWL39_MAX_INST_SIZE) { - IWL_DEBUG_INFO(priv, - "uCode init instr len %d too large to fit in\n", - init_size); - ret = -EINVAL; - goto err_release; - } - if (init_data_size > IWL39_MAX_DATA_SIZE) { - IWL_DEBUG_INFO(priv, - "uCode init data len %d too large to fit in\n", - init_data_size); - ret = -EINVAL; - goto err_release; - } - if (boot_size > IWL39_MAX_BSM_SIZE) { - IWL_DEBUG_INFO(priv, - "uCode boot instr len %d too large to fit in\n", - boot_size); - ret = -EINVAL; - goto err_release; - } - - /* Allocate ucode buffers for card's bus-master loading ... */ - - /* Runtime instructions and 2 copies of data: - * 1) unmodified from disk - * 2) backup cache for save/restore during power-downs */ - priv->ucode_code.len = inst_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code); - - priv->ucode_data.len = data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data); - - priv->ucode_data_backup.len = data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup); - - if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr || - !priv->ucode_data_backup.v_addr) - goto err_pci_alloc; - - /* Initialization instructions and data */ - if (init_size && init_data_size) { - priv->ucode_init.len = init_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init); - - priv->ucode_init_data.len = init_data_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data); - - if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr) - goto err_pci_alloc; - } - - /* Bootstrap (instructions only, no data) */ - if (boot_size) { - priv->ucode_boot.len = boot_size; - iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot); - - if (!priv->ucode_boot.v_addr) - goto err_pci_alloc; - } - - /* Copy images into buffers for card's bus-master reads ... */ - - /* Runtime instructions (first block of data in file) */ - len = inst_size; - IWL_DEBUG_INFO(priv, - "Copying (but not loading) uCode instr len %zd\n", len); - memcpy(priv->ucode_code.v_addr, src, len); - src += len; - - IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n", - priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr); - - /* Runtime data (2nd block) - * NOTE: Copy into backup buffer will be done in iwl3945_up() */ - len = data_size; - IWL_DEBUG_INFO(priv, - "Copying (but not loading) uCode data len %zd\n", len); - memcpy(priv->ucode_data.v_addr, src, len); - memcpy(priv->ucode_data_backup.v_addr, src, len); - src += len; - - /* Initialization instructions (3rd block) */ - if (init_size) { - len = init_size; - IWL_DEBUG_INFO(priv, - "Copying (but not loading) init instr len %zd\n", len); - memcpy(priv->ucode_init.v_addr, src, len); - src += len; - } - - /* Initialization data (4th block) */ - if (init_data_size) { - len = init_data_size; - IWL_DEBUG_INFO(priv, - "Copying (but not loading) init data len %zd\n", len); - memcpy(priv->ucode_init_data.v_addr, src, len); - src += len; - } - - /* Bootstrap instructions (5th block) */ - len = boot_size; - IWL_DEBUG_INFO(priv, - "Copying (but not loading) boot instr len %zd\n", len); - memcpy(priv->ucode_boot.v_addr, src, len); - - /* We have our copies now, allow OS release its copies */ - release_firmware(ucode_raw); - return 0; - - err_pci_alloc: - IWL_ERR(priv, "failed to allocate pci memory\n"); - ret = -ENOMEM; - iwl3945_dealloc_ucode_pci(priv); - - err_release: - release_firmware(ucode_raw); - - error: - return ret; -} - - -/** - * iwl3945_set_ucode_ptrs - Set uCode address location - * - * Tell initialization uCode where to find runtime uCode. - * - * BSM registers initially contain pointers to initialization uCode. - * We need to replace them to load runtime uCode inst and data, - * and to save runtime data when powering down. - */ -static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv) -{ - dma_addr_t pinst; - dma_addr_t pdata; - - /* bits 31:0 for 3945 */ - pinst = priv->ucode_code.p_addr; - pdata = priv->ucode_data_backup.p_addr; - - /* Tell bootstrap uCode where to find image to load */ - iwl_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst); - iwl_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata); - iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, - priv->ucode_data.len); - - /* Inst byte count must be last to set up, bit 31 signals uCode - * that all new ptr/size info is in place */ - iwl_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, - priv->ucode_code.len | BSM_DRAM_INST_LOAD); - - IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n"); - - return 0; -} - -/** - * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received - * - * Called after REPLY_ALIVE notification received from "initialize" uCode. - * - * Tell "initialize" uCode to go ahead and load the runtime uCode. - */ -static void iwl3945_init_alive_start(struct iwl_priv *priv) -{ - /* Check alive response for "valid" sign from uCode */ - if (priv->card_alive_init.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n"); - goto restart; - } - - /* Bootstrap uCode has loaded initialize uCode ... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "initialize" alive if code weren't properly loaded. */ - if (iwl3945_verify_ucode(priv)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n"); - goto restart; - } - - /* Send pointers to protocol/runtime uCode image ... init code will - * load and launch runtime uCode, which will send us another "Alive" - * notification. */ - IWL_DEBUG_INFO(priv, "Initialization Alive received.\n"); - if (iwl3945_set_ucode_ptrs(priv)) { - /* Runtime instruction load won't happen; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n"); - goto restart; - } - return; - - restart: - queue_work(priv->workqueue, &priv->restart); -} - -/** - * iwl3945_alive_start - called after REPLY_ALIVE notification received - * from protocol/runtime uCode (initialization uCode's - * Alive gets handled by iwl3945_init_alive_start()). - */ -static void iwl3945_alive_start(struct iwl_priv *priv) -{ - int thermal_spin = 0; - u32 rfkill; - - IWL_DEBUG_INFO(priv, "Runtime Alive received.\n"); - - if (priv->card_alive.is_valid != UCODE_VALID_OK) { - /* We had an error bringing up the hardware, so take it - * all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Alive failed.\n"); - goto restart; - } - - /* Initialize uCode has loaded Runtime uCode ... verify inst image. - * This is a paranoid check, because we would not have gotten the - * "runtime" alive if code weren't properly loaded. */ - if (iwl3945_verify_ucode(priv)) { - /* Runtime instruction load was bad; - * take it all the way back down so we can try again */ - IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n"); - goto restart; - } - - iwl_clear_stations_table(priv); - - rfkill = iwl_read_prph(priv, APMG_RFKILL_REG); - IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill); - - if (rfkill & 0x1) { - clear_bit(STATUS_RF_KILL_HW, &priv->status); - /* if RFKILL is not on, then wait for thermal - * sensor in adapter to kick in */ - while (iwl3945_hw_get_temperature(priv) == 0) { - thermal_spin++; - udelay(10); - } - - if (thermal_spin) - IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n", - thermal_spin * 10); - } else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - /* After the ALIVE response, we can send commands to 3945 uCode */ - set_bit(STATUS_ALIVE, &priv->status); - - if (iwl_is_rfkill(priv)) - return; - - ieee80211_wake_queues(priv->hw); - - priv->active_rate = priv->rates_mask; - priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK; - - iwl_power_update_mode(priv, false); - - if (iwl_is_associated(priv)) { - struct iwl3945_rxon_cmd *active_rxon = - (struct iwl3945_rxon_cmd *)(&priv->active_rxon); - - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK; - } else { - /* Initialize our rx_config data */ - iwl_connection_init_rx_config(priv, priv->iw_mode); - } - - /* Configure Bluetooth device coexistence support */ - iwl_send_bt_config(priv); - - /* Configure the adapter for unassociated operation */ - iwlcore_commit_rxon(priv); - - iwl3945_reg_txpower_periodic(priv); - - iwl3945_led_register(priv); - - IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n"); - set_bit(STATUS_READY, &priv->status); - wake_up_interruptible(&priv->wait_command_queue); - - /* reassociate for ADHOC mode */ - if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { - struct sk_buff *beacon = ieee80211_beacon_get(priv->hw, - priv->vif); - if (beacon) - iwl_mac_beacon_update(priv->hw, beacon); - } - - if (test_and_clear_bit(STATUS_MODE_PENDING, &priv->status)) - iwl_set_mode(priv, priv->iw_mode); - - return; - - restart: - queue_work(priv->workqueue, &priv->restart); -} - -static void iwl3945_cancel_deferred_work(struct iwl_priv *priv); - -static void __iwl3945_down(struct iwl_priv *priv) -{ - unsigned long flags; - int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status); - struct ieee80211_conf *conf = NULL; - - IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n"); - - conf = ieee80211_get_hw_conf(priv->hw); - - if (!exit_pending) - set_bit(STATUS_EXIT_PENDING, &priv->status); - - iwl3945_led_unregister(priv); - iwl_clear_stations_table(priv); - - /* Unblock any waiting calls */ - wake_up_interruptible_all(&priv->wait_command_queue); - - /* Wipe out the EXIT_PENDING status bit if we are not actually - * exiting the module */ - if (!exit_pending) - clear_bit(STATUS_EXIT_PENDING, &priv->status); - - /* stop and reset the on-board processor */ - iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET); - - /* tell the device to stop sending interrupts */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - iwl_synchronize_irq(priv); - - if (priv->mac80211_registered) - ieee80211_stop_queues(priv->hw); - - /* If we have not previously called iwl3945_init() then - * clear all bits but the RF Kill bits and return */ - if (!iwl_is_init(priv)) { - priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) << - STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << - STATUS_GEO_CONFIGURED | - test_bit(STATUS_EXIT_PENDING, &priv->status) << - STATUS_EXIT_PENDING; - goto exit; - } - - /* ...otherwise clear out all the status bits but the RF Kill - * bit and continue taking the NIC down. */ - priv->status &= test_bit(STATUS_RF_KILL_HW, &priv->status) << - STATUS_RF_KILL_HW | - test_bit(STATUS_GEO_CONFIGURED, &priv->status) << - STATUS_GEO_CONFIGURED | - test_bit(STATUS_FW_ERROR, &priv->status) << - STATUS_FW_ERROR | - test_bit(STATUS_EXIT_PENDING, &priv->status) << - STATUS_EXIT_PENDING; - - priv->cfg->ops->lib->apm_ops.reset(priv); - spin_lock_irqsave(&priv->lock, flags); - iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl3945_hw_txq_ctx_stop(priv); - iwl3945_hw_rxq_stop(priv); - - iwl_write_prph(priv, APMG_CLK_DIS_REG, - APMG_CLK_VAL_DMA_CLK_RQT); - - udelay(5); - - if (exit_pending) - priv->cfg->ops->lib->apm_ops.stop(priv); - else - priv->cfg->ops->lib->apm_ops.reset(priv); - - exit: - memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp)); - - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - priv->ibss_beacon = NULL; - - /* clear out any free frames */ - iwl3945_clear_free_frames(priv); -} - -static void iwl3945_down(struct iwl_priv *priv) -{ - mutex_lock(&priv->mutex); - __iwl3945_down(priv); - mutex_unlock(&priv->mutex); - - iwl3945_cancel_deferred_work(priv); -} - -#define MAX_HW_RESTARTS 5 - -static int __iwl3945_up(struct iwl_priv *priv) -{ - int rc, i; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_WARN(priv, "Exit pending; will not bring the NIC up\n"); - return -EIO; - } - - if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) { - IWL_ERR(priv, "ucode not available for device bring up\n"); - return -EIO; - } - - /* If platform's RF_KILL switch is NOT set to KILL */ - if (iwl_read32(priv, CSR_GP_CNTRL) & - CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else { - set_bit(STATUS_RF_KILL_HW, &priv->status); - IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n"); - return -ENODEV; - } - - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - - rc = iwl3945_hw_nic_init(priv); - if (rc) { - IWL_ERR(priv, "Unable to int nic\n"); - return rc; - } - - /* make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, - CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED); - - /* clear (again), then enable host interrupts */ - iwl_write32(priv, CSR_INT, 0xFFFFFFFF); - iwl_enable_interrupts(priv); - - /* really make sure rfkill handshake bits are cleared */ - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); - - /* Copy original ucode data image from disk into backup cache. - * This will be used to initialize the on-board processor's - * data SRAM for a clean start when the runtime program first loads. */ - memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr, - priv->ucode_data.len); - - /* We return success when we resume from suspend and rf_kill is on. */ - if (test_bit(STATUS_RF_KILL_HW, &priv->status)) - return 0; - - for (i = 0; i < MAX_HW_RESTARTS; i++) { - - iwl_clear_stations_table(priv); - - /* load bootstrap state machine, - * load bootstrap program into processor's memory, - * prepare to load the "initialize" uCode */ - priv->cfg->ops->lib->load_ucode(priv); - - if (rc) { - IWL_ERR(priv, - "Unable to set up bootstrap uCode: %d\n", rc); - continue; - } - - /* start card; "initialize" will load runtime ucode */ - iwl3945_nic_start(priv); - - IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n"); - - return 0; - } - - set_bit(STATUS_EXIT_PENDING, &priv->status); - __iwl3945_down(priv); - clear_bit(STATUS_EXIT_PENDING, &priv->status); - - /* tried to restart and config the device for as long as our - * patience could withstand */ - IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i); - return -EIO; -} - - -/***************************************************************************** - * - * Workqueue callbacks - * - *****************************************************************************/ - -static void iwl3945_bg_init_alive_start(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, init_alive_start.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - iwl3945_init_alive_start(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl3945_bg_alive_start(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, alive_start.work); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - iwl3945_alive_start(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl3945_rfkill_poll(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, rfkill_poll.work); - - if (iwl_read32(priv, CSR_GP_CNTRL) & CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW) - clear_bit(STATUS_RF_KILL_HW, &priv->status); - else - set_bit(STATUS_RF_KILL_HW, &priv->status); - - wiphy_rfkill_set_hw_state(priv->hw->wiphy, - test_bit(STATUS_RF_KILL_HW, &priv->status)); - - queue_delayed_work(priv->workqueue, &priv->rfkill_poll, - round_jiffies_relative(2 * HZ)); - -} - -#define IWL_SCAN_CHECK_WATCHDOG (7 * HZ) -static void iwl3945_bg_request_scan(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, request_scan); - struct iwl_host_cmd cmd = { - .id = REPLY_SCAN_CMD, - .len = sizeof(struct iwl3945_scan_cmd), - .flags = CMD_SIZE_HUGE, - }; - int rc = 0; - struct iwl3945_scan_cmd *scan; - struct ieee80211_conf *conf = NULL; - u8 n_probes = 0; - enum ieee80211_band band; - bool is_active = false; - - conf = ieee80211_get_hw_conf(priv->hw); - - mutex_lock(&priv->mutex); - - cancel_delayed_work(&priv->scan_check); - - if (!iwl_is_ready(priv)) { - IWL_WARN(priv, "request scan called when driver not ready.\n"); - goto done; - } - - /* Make sure the scan wasn't canceled before this queued work - * was given the chance to run... */ - if (!test_bit(STATUS_SCANNING, &priv->status)) - goto done; - - /* This should never be called or scheduled if there is currently - * a scan active in the hardware. */ - if (test_bit(STATUS_SCAN_HW, &priv->status)) { - IWL_DEBUG_INFO(priv, "Multiple concurrent scan requests " - "Ignoring second request.\n"); - rc = -EIO; - goto done; - } - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) { - IWL_DEBUG_SCAN(priv, "Aborting scan due to device shutdown\n"); - goto done; - } - - if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { - IWL_DEBUG_HC(priv, - "Scan request while abort pending. Queuing.\n"); - goto done; - } - - if (iwl_is_rfkill(priv)) { - IWL_DEBUG_HC(priv, "Aborting scan due to RF Kill activation\n"); - goto done; - } - - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_DEBUG_HC(priv, - "Scan request while uninitialized. Queuing.\n"); - goto done; - } - - if (!priv->scan_bands) { - IWL_DEBUG_HC(priv, "Aborting scan due to no requested bands\n"); - goto done; - } - - if (!priv->scan) { - priv->scan = kmalloc(sizeof(struct iwl3945_scan_cmd) + - IWL_MAX_SCAN_SIZE, GFP_KERNEL); - if (!priv->scan) { - rc = -ENOMEM; - goto done; - } - } - scan = priv->scan; - memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE); - - scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; - scan->quiet_time = IWL_ACTIVE_QUIET_TIME; - - if (iwl_is_associated(priv)) { - u16 interval = 0; - u32 extra; - u32 suspend_time = 100; - u32 scan_suspend_time = 100; - unsigned long flags; - - IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); - - spin_lock_irqsave(&priv->lock, flags); - interval = priv->beacon_int; - spin_unlock_irqrestore(&priv->lock, flags); - - scan->suspend_time = 0; - scan->max_out_time = cpu_to_le32(200 * 1024); - if (!interval) - interval = suspend_time; - /* - * suspend time format: - * 0-19: beacon interval in usec (time before exec.) - * 20-23: 0 - * 24-31: number of beacons (suspend between channels) - */ - - extra = (suspend_time / interval) << 24; - scan_suspend_time = 0xFF0FFFFF & - (extra | ((suspend_time % interval) * 1024)); - - scan->suspend_time = cpu_to_le32(scan_suspend_time); - IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", - scan_suspend_time, interval); - } - - if (priv->scan_request->n_ssids) { - int i, p = 0; - IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); - for (i = 0; i < priv->scan_request->n_ssids; i++) { - /* always does wildcard anyway */ - if (!priv->scan_request->ssids[i].ssid_len) - continue; - scan->direct_scan[p].id = WLAN_EID_SSID; - scan->direct_scan[p].len = - priv->scan_request->ssids[i].ssid_len; - memcpy(scan->direct_scan[p].ssid, - priv->scan_request->ssids[i].ssid, - priv->scan_request->ssids[i].ssid_len); - n_probes++; - p++; - } - is_active = true; - } else - IWL_DEBUG_SCAN(priv, "Kicking off passive scan.\n"); - - /* We don't build a direct scan probe request; the uCode will do - * that based on the direct_mask added to each channel entry */ - scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; - scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; - scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; - - /* flags + rate selection */ - - if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { - scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; - scan->tx_cmd.rate = IWL_RATE_1M_PLCP; - scan->good_CRC_th = 0; - band = IEEE80211_BAND_2GHZ; - } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { - scan->tx_cmd.rate = IWL_RATE_6M_PLCP; - /* - * If active scaning is requested but a certain channel - * is marked passive, we can do active scanning if we - * detect transmissions. - */ - scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; - band = IEEE80211_BAND_5GHZ; - } else { - IWL_WARN(priv, "Invalid scan band count\n"); - goto done; - } - - scan->tx_cmd.len = cpu_to_le16( - iwl_fill_probe_req(priv, - (struct ieee80211_mgmt *)scan->data, - priv->scan_request->ie, - priv->scan_request->ie_len, - IWL_MAX_SCAN_SIZE - sizeof(*scan))); - - /* select Rx antennas */ - scan->flags |= iwl3945_get_antenna_flags(priv); - - if (iwl_is_monitor_mode(priv)) - scan->filter_flags = RXON_FILTER_PROMISC_MSK; - - scan->channel_count = - iwl3945_get_channels_for_scan(priv, band, is_active, n_probes, - (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); - - if (scan->channel_count == 0) { - IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); - goto done; - } - - cmd.len += le16_to_cpu(scan->tx_cmd.len) + - scan->channel_count * sizeof(struct iwl3945_scan_channel); - cmd.data = scan; - scan->len = cpu_to_le16(cmd.len); - - set_bit(STATUS_SCAN_HW, &priv->status); - rc = iwl_send_cmd_sync(priv, &cmd); - if (rc) - goto done; - - queue_delayed_work(priv->workqueue, &priv->scan_check, - IWL_SCAN_CHECK_WATCHDOG); - - mutex_unlock(&priv->mutex); - return; - - done: - /* can not perform scan make sure we clear scanning - * bits from status so next scan request can be performed. - * if we dont clear scanning status bit here all next scan - * will fail - */ - clear_bit(STATUS_SCAN_HW, &priv->status); - clear_bit(STATUS_SCANNING, &priv->status); - - /* inform mac80211 scan aborted */ - queue_work(priv->workqueue, &priv->scan_completed); - mutex_unlock(&priv->mutex); -} - -static void iwl3945_bg_up(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, up); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - __iwl3945_up(priv); - mutex_unlock(&priv->mutex); -} - -static void iwl3945_bg_restart(struct work_struct *data) -{ - struct iwl_priv *priv = container_of(data, struct iwl_priv, restart); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) { - mutex_lock(&priv->mutex); - priv->vif = NULL; - priv->is_open = 0; - mutex_unlock(&priv->mutex); - iwl3945_down(priv); - ieee80211_restart_hw(priv->hw); - } else { - iwl3945_down(priv); - queue_work(priv->workqueue, &priv->up); - } -} - -static void iwl3945_bg_rx_replenish(struct work_struct *data) -{ - struct iwl_priv *priv = - container_of(data, struct iwl_priv, rx_replenish); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - mutex_lock(&priv->mutex); - iwl3945_rx_replenish(priv); - mutex_unlock(&priv->mutex); -} - -#define IWL_DELAY_NEXT_SCAN (HZ*2) - -void iwl3945_post_associate(struct iwl_priv *priv) -{ - int rc = 0; - struct ieee80211_conf *conf = NULL; - - if (priv->iw_mode == NL80211_IFTYPE_AP) { - IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__); - return; - } - - - IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n", - priv->assoc_id, priv->active_rxon.bssid_addr); - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - if (!priv->vif || !priv->is_open) - return; - - iwl_scan_cancel_timeout(priv, 200); - - conf = ieee80211_get_hw_conf(priv->hw); - - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - - memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); - iwl_setup_rxon_timing(priv); - rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), &priv->rxon_timing); - if (rc) - IWL_WARN(priv, "REPLY_RXON_TIMING failed - " - "Attempting to continue.\n"); - - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - - IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n", - priv->assoc_id, priv->beacon_int); - - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging_rxon.flags |= RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= ~RXON_FLG_SHORT_SLOT_MSK; - - } - - iwlcore_commit_rxon(priv); - - switch (priv->iw_mode) { - case NL80211_IFTYPE_STATION: - iwl3945_rate_scale_init(priv->hw, IWL_AP_ID); - break; - - case NL80211_IFTYPE_ADHOC: - - priv->assoc_id = 1; - iwl_add_station(priv, priv->bssid, 0, CMD_SYNC, NULL); - iwl3945_sync_sta(priv, IWL_STA_ID, - (priv->band == IEEE80211_BAND_5GHZ) ? - IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP, - CMD_ASYNC); - iwl3945_rate_scale_init(priv->hw, IWL_STA_ID); - iwl3945_send_beacon_cmd(priv); - - break; - - default: - IWL_ERR(priv, "%s Should not be called in %d mode\n", - __func__, priv->iw_mode); - break; - } - - iwl_activate_qos(priv, 0); - - /* we have just associated, don't start scan too early */ - priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN; -} - -/***************************************************************************** - * - * mac80211 entry point functions - * - *****************************************************************************/ - -#define UCODE_READY_TIMEOUT (2 * HZ) - -static int iwl3945_mac_start(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - int ret; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - /* we should be verifying the device is ready to be opened */ - mutex_lock(&priv->mutex); - - /* fetch ucode file from disk, alloc and copy to bus-master buffers ... - * ucode filename and max sizes are card-specific. */ - - if (!priv->ucode_code.len) { - ret = iwl3945_read_ucode(priv); - if (ret) { - IWL_ERR(priv, "Could not read microcode: %d\n", ret); - mutex_unlock(&priv->mutex); - goto out_release_irq; - } - } - - ret = __iwl3945_up(priv); - - mutex_unlock(&priv->mutex); - - if (ret) - goto out_release_irq; - - IWL_DEBUG_INFO(priv, "Start UP work.\n"); - - /* Wait for START_ALIVE from ucode. Otherwise callbacks from - * mac80211 will not be run successfully. */ - ret = wait_event_interruptible_timeout(priv->wait_command_queue, - test_bit(STATUS_READY, &priv->status), - UCODE_READY_TIMEOUT); - if (!ret) { - if (!test_bit(STATUS_READY, &priv->status)) { - IWL_ERR(priv, - "Wait for START_ALIVE timeout after %dms.\n", - jiffies_to_msecs(UCODE_READY_TIMEOUT)); - ret = -ETIMEDOUT; - goto out_release_irq; - } - } - - /* ucode is running and will send rfkill notifications, - * no need to poll the killswitch state anymore */ - cancel_delayed_work(&priv->rfkill_poll); - - priv->is_open = 1; - IWL_DEBUG_MAC80211(priv, "leave\n"); - return 0; - -out_release_irq: - priv->is_open = 0; - IWL_DEBUG_MAC80211(priv, "leave - failed\n"); - return ret; -} - -static void iwl3945_mac_stop(struct ieee80211_hw *hw) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (!priv->is_open) { - IWL_DEBUG_MAC80211(priv, "leave - skip\n"); - return; - } - - priv->is_open = 0; - - if (iwl_is_ready_rf(priv)) { - /* stop mac, cancel any scan request and clear - * RXON_FILTER_ASSOC_MSK BIT - */ - mutex_lock(&priv->mutex); - iwl_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); - } - - iwl3945_down(priv); - - flush_workqueue(priv->workqueue); - - /* start polling the killswitch state again */ - queue_delayed_work(priv->workqueue, &priv->rfkill_poll, - round_jiffies_relative(2 * HZ)); - - IWL_DEBUG_MAC80211(priv, "leave\n"); -} - -static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct iwl_priv *priv = hw->priv; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len, - ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate); - - if (iwl3945_tx_skb(priv, skb)) - dev_kfree_skb_any(skb); - - IWL_DEBUG_MAC80211(priv, "leave\n"); - return NETDEV_TX_OK; -} - -void iwl3945_config_ap(struct iwl_priv *priv) -{ - int rc = 0; - - if (test_bit(STATUS_EXIT_PENDING, &priv->status)) - return; - - /* The following should be done only at AP bring up */ - if (!(iwl_is_associated(priv))) { - - /* RXON - unassoc (to set timing command) */ - priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - - /* RXON Timing */ - memset(&priv->rxon_timing, 0, sizeof(struct iwl_rxon_time_cmd)); - iwl_setup_rxon_timing(priv); - rc = iwl_send_cmd_pdu(priv, REPLY_RXON_TIMING, - sizeof(priv->rxon_timing), - &priv->rxon_timing); - if (rc) - IWL_WARN(priv, "REPLY_RXON_TIMING failed - " - "Attempting to continue.\n"); - - /* FIXME: what should be the assoc_id for AP? */ - priv->staging_rxon.assoc_id = cpu_to_le16(priv->assoc_id); - if (priv->assoc_capability & WLAN_CAPABILITY_SHORT_PREAMBLE) - priv->staging_rxon.flags |= - RXON_FLG_SHORT_PREAMBLE_MSK; - else - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_PREAMBLE_MSK; - - if (priv->staging_rxon.flags & RXON_FLG_BAND_24G_MSK) { - if (priv->assoc_capability & - WLAN_CAPABILITY_SHORT_SLOT_TIME) - priv->staging_rxon.flags |= - RXON_FLG_SHORT_SLOT_MSK; - else - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) - priv->staging_rxon.flags &= - ~RXON_FLG_SHORT_SLOT_MSK; - } - /* restore RXON assoc */ - priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK; - iwlcore_commit_rxon(priv); - iwl_add_station(priv, iwl_bcast_addr, 0, CMD_SYNC, NULL); - } - iwl3945_send_beacon_cmd(priv); - - /* FIXME - we need to add code here to detect a totally new - * configuration, reset the AP, unassoc, rxon timing, assoc, - * clear sta table, add BCAST sta... */ -} - -static int iwl3945_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct iwl_priv *priv = hw->priv; - const u8 *addr; - int ret = 0; - u8 sta_id = IWL_INVALID_STATION; - u8 static_key; - - IWL_DEBUG_MAC80211(priv, "enter\n"); - - if (iwl3945_mod_params.sw_crypto) { - IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n"); - return -EOPNOTSUPP; - } - - addr = sta ? sta->addr : iwl_bcast_addr; - static_key = !iwl_is_associated(priv); - - if (!static_key) { - sta_id = iwl_find_station(priv, addr); - if (sta_id == IWL_INVALID_STATION) { - IWL_DEBUG_MAC80211(priv, "leave - %pM not in station map.\n", - addr); - return -EINVAL; - } - } - - mutex_lock(&priv->mutex); - iwl_scan_cancel_timeout(priv, 100); - mutex_unlock(&priv->mutex); - - switch (cmd) { - case SET_KEY: - if (static_key) - ret = iwl3945_set_static_key(priv, key); - else - ret = iwl3945_set_dynamic_key(priv, key, sta_id); - IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n"); - break; - case DISABLE_KEY: - if (static_key) - ret = iwl3945_remove_static_key(priv); - else - ret = iwl3945_clear_sta_key_info(priv, sta_id); - IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n"); - break; - default: - ret = -EINVAL; - } - - IWL_DEBUG_MAC80211(priv, "leave\n"); - - return ret; -} - -/***************************************************************************** - * - * sysfs attributes - * - *****************************************************************************/ - -#ifdef CONFIG_IWLWIFI_DEBUG - -/* - * The following adds a new attribute to the sysfs representation - * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/) - * used for controlling the debug level. - * - * See the level definitions in iwl for details. - * - * The debug_level being managed using sysfs below is a per device debug - * level that is used instead of the global debug level if it (the per - * device debug level) is set. - */ -static ssize_t show_debug_level(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv)); -} -static ssize_t store_debug_level(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - unsigned long val; - int ret; - - ret = strict_strtoul(buf, 0, &val); - if (ret) - IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf); - else { - priv->debug_level = val; - if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, - "Not enough memory to generate traffic log\n"); - } - return strnlen(buf, count); -} - -static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO, - show_debug_level, store_debug_level); - -#endif /* CONFIG_IWLWIFI_DEBUG */ - -static ssize_t show_temperature(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv)); -} - -static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL); - -static ssize_t show_tx_power(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%d\n", priv->tx_power_user_lmt); -} - -static ssize_t store_tx_power(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - char *p = (char *)buf; - u32 val; - - val = simple_strtoul(p, &p, 10); - if (p == buf) - IWL_INFO(priv, ": %s is not in decimal form.\n", buf); - else - iwl3945_hw_reg_set_txpower(priv, val); - - return count; -} - -static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power); - -static ssize_t show_flags(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%04X\n", priv->active_rxon.flags); -} - -static ssize_t store_flags(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - u32 flags = simple_strtoul(buf, NULL, 0); - - mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.flags) != flags) { - /* Cancel any currently running scans... */ - if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARN(priv, "Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n", - flags); - priv->staging_rxon.flags = cpu_to_le32(flags); - iwlcore_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags); - -static ssize_t show_filter_flags(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - return sprintf(buf, "0x%04X\n", - le32_to_cpu(priv->active_rxon.filter_flags)); -} - -static ssize_t store_filter_flags(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - u32 filter_flags = simple_strtoul(buf, NULL, 0); - - mutex_lock(&priv->mutex); - if (le32_to_cpu(priv->staging_rxon.filter_flags) != filter_flags) { - /* Cancel any currently running scans... */ - if (iwl_scan_cancel_timeout(priv, 100)) - IWL_WARN(priv, "Could not cancel scan.\n"); - else { - IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = " - "0x%04X\n", filter_flags); - priv->staging_rxon.filter_flags = - cpu_to_le32(filter_flags); - iwlcore_commit_rxon(priv); - } - } - mutex_unlock(&priv->mutex); - - return count; -} - -static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, - store_filter_flags); - -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - -static ssize_t show_measurement(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - struct iwl_spectrum_notification measure_report; - u32 size = sizeof(measure_report), len = 0, ofs = 0; - u8 *data = (u8 *)&measure_report; - unsigned long flags; - - spin_lock_irqsave(&priv->lock, flags); - if (!(priv->measurement_status & MEASUREMENT_READY)) { - spin_unlock_irqrestore(&priv->lock, flags); - return 0; - } - memcpy(&measure_report, &priv->measure_report, size); - priv->measurement_status = 0; - spin_unlock_irqrestore(&priv->lock, flags); - - while (size && (PAGE_SIZE - len)) { - hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, - PAGE_SIZE - len, 1); - len = strlen(buf); - if (PAGE_SIZE - len) - buf[len++] = '\n'; - - ofs += 16; - size -= min(size, 16U); - } - - return len; -} - -static ssize_t store_measurement(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - struct ieee80211_measurement_params params = { - .channel = le16_to_cpu(priv->active_rxon.channel), - .start_time = cpu_to_le64(priv->last_tsf), - .duration = cpu_to_le16(1), - }; - u8 type = IWL_MEASURE_BASIC; - u8 buffer[32]; - u8 channel; - - if (count) { - char *p = buffer; - strncpy(buffer, buf, min(sizeof(buffer), count)); - channel = simple_strtoul(p, NULL, 0); - if (channel) - params.channel = channel; - - p = buffer; - while (*p && *p != ' ') - p++; - if (*p) - type = simple_strtoul(p + 1, NULL, 0); - } - - IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on " - "channel %d (for '%s')\n", type, params.channel, buf); - iwl3945_get_measurement(priv, ¶ms, type); - - return count; -} - -static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR, - show_measurement, store_measurement); -#endif /* CONFIG_IWL3945_SPECTRUM_MEASUREMENT */ - -static ssize_t store_retry_rate(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - priv->retry_rate = simple_strtoul(buf, NULL, 0); - if (priv->retry_rate <= 0) - priv->retry_rate = 1; - - return count; -} - -static ssize_t show_retry_rate(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - return sprintf(buf, "%d", priv->retry_rate); -} - -static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate, - store_retry_rate); - - -static ssize_t show_channels(struct device *d, - struct device_attribute *attr, char *buf) -{ - /* all this shit doesn't belong into sysfs anyway */ - return 0; -} - -static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL); - -static ssize_t show_statistics(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - u32 size = sizeof(struct iwl3945_notif_statistics); - u32 len = 0, ofs = 0; - u8 *data = (u8 *)&priv->statistics_39; - int rc = 0; - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - mutex_lock(&priv->mutex); - rc = iwl_send_statistics_request(priv, 0); - mutex_unlock(&priv->mutex); - - if (rc) { - len = sprintf(buf, - "Error sending statistics request: 0x%08X\n", rc); - return len; - } - - while (size && (PAGE_SIZE - len)) { - hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len, - PAGE_SIZE - len, 1); - len = strlen(buf); - if (PAGE_SIZE - len) - buf[len++] = '\n'; - - ofs += 16; - size -= min(size, 16U); - } - - return len; -} - -static DEVICE_ATTR(statistics, S_IRUGO, show_statistics, NULL); - -static ssize_t show_antenna(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - - if (!iwl_is_alive(priv)) - return -EAGAIN; - - return sprintf(buf, "%d\n", iwl3945_mod_params.antenna); -} - -static ssize_t store_antenna(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d); - int ant; - - if (count == 0) - return 0; - - if (sscanf(buf, "%1i", &ant) != 1) { - IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n"); - return count; - } - - if ((ant >= 0) && (ant <= 2)) { - IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant); - iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant; - } else - IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant); - - - return count; -} - -static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna); - -static ssize_t show_status(struct device *d, - struct device_attribute *attr, char *buf) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - if (!iwl_is_alive(priv)) - return -EAGAIN; - return sprintf(buf, "0x%08x\n", (int)priv->status); -} - -static DEVICE_ATTR(status, S_IRUGO, show_status, NULL); - -static ssize_t dump_error_log(struct device *d, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct iwl_priv *priv = dev_get_drvdata(d); - char *p = (char *)buf; - - if (p[0] == '1') - iwl3945_dump_nic_error_log(priv); - - return strnlen(buf, count); -} - -static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log); - -/***************************************************************************** - * - * driver setup and tear down - * - *****************************************************************************/ - -static void iwl3945_setup_deferred_work(struct iwl_priv *priv) -{ - priv->workqueue = create_singlethread_workqueue(DRV_NAME); - - init_waitqueue_head(&priv->wait_command_queue); - - INIT_WORK(&priv->up, iwl3945_bg_up); - INIT_WORK(&priv->restart, iwl3945_bg_restart); - INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish); - INIT_WORK(&priv->beacon_update, iwl3945_bg_beacon_update); - INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start); - INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start); - INIT_DELAYED_WORK(&priv->rfkill_poll, iwl3945_rfkill_poll); - INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); - INIT_WORK(&priv->request_scan, iwl3945_bg_request_scan); - INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); - INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); - - iwl3945_hw_setup_deferred_work(priv); - - tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) - iwl3945_irq_tasklet, (unsigned long)priv); -} - -static void iwl3945_cancel_deferred_work(struct iwl_priv *priv) -{ - iwl3945_hw_cancel_deferred_work(priv); - - cancel_delayed_work_sync(&priv->init_alive_start); - cancel_delayed_work(&priv->scan_check); - cancel_delayed_work(&priv->alive_start); - cancel_work_sync(&priv->beacon_update); -} - -static struct attribute *iwl3945_sysfs_entries[] = { - &dev_attr_antenna.attr, - &dev_attr_channels.attr, - &dev_attr_dump_errors.attr, - &dev_attr_flags.attr, - &dev_attr_filter_flags.attr, -#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT - &dev_attr_measurement.attr, -#endif - &dev_attr_retry_rate.attr, - &dev_attr_statistics.attr, - &dev_attr_status.attr, - &dev_attr_temperature.attr, - &dev_attr_tx_power.attr, -#ifdef CONFIG_IWLWIFI_DEBUG - &dev_attr_debug_level.attr, -#endif - NULL -}; - -static struct attribute_group iwl3945_attribute_group = { - .name = NULL, /* put in device directory */ - .attrs = iwl3945_sysfs_entries, -}; - -static struct ieee80211_ops iwl3945_hw_ops = { - .tx = iwl3945_mac_tx, - .start = iwl3945_mac_start, - .stop = iwl3945_mac_stop, - .add_interface = iwl_mac_add_interface, - .remove_interface = iwl_mac_remove_interface, - .config = iwl_mac_config, - .configure_filter = iwl_configure_filter, - .set_key = iwl3945_mac_set_key, - .get_tx_stats = iwl_mac_get_tx_stats, - .conf_tx = iwl_mac_conf_tx, - .reset_tsf = iwl_mac_reset_tsf, - .bss_info_changed = iwl_bss_info_changed, - .hw_scan = iwl_mac_hw_scan -}; - -static int iwl3945_init_drv(struct iwl_priv *priv) -{ - int ret; - struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom; - - priv->retry_rate = 1; - priv->ibss_beacon = NULL; - - spin_lock_init(&priv->lock); - spin_lock_init(&priv->sta_lock); - spin_lock_init(&priv->hcmd_lock); - - INIT_LIST_HEAD(&priv->free_frames); - - mutex_init(&priv->mutex); - - /* Clear the driver's (not device's) station table */ - iwl_clear_stations_table(priv); - - priv->data_retry_limit = -1; - priv->ieee_channels = NULL; - priv->ieee_rates = NULL; - priv->band = IEEE80211_BAND_2GHZ; - - priv->iw_mode = NL80211_IFTYPE_STATION; - - iwl_reset_qos(priv); - - priv->qos_data.qos_active = 0; - priv->qos_data.qos_cap.val = 0; - - priv->rates_mask = IWL_RATES_MASK; - priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; - - if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { - IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", - eeprom->version); - ret = -EINVAL; - goto err; - } - ret = iwl_init_channel_map(priv); - if (ret) { - IWL_ERR(priv, "initializing regulatory failed: %d\n", ret); - goto err; - } - - /* Set up txpower settings in driver for all channels */ - if (iwl3945_txpower_set_from_eeprom(priv)) { - ret = -EIO; - goto err_free_channel_map; - } - - ret = iwlcore_init_geos(priv); - if (ret) { - IWL_ERR(priv, "initializing geos failed: %d\n", ret); - goto err_free_channel_map; - } - iwl3945_init_hw_rates(priv, priv->ieee_rates); - - return 0; - -err_free_channel_map: - iwl_free_channel_map(priv); -err: - return ret; -} - -static int iwl3945_setup_mac(struct iwl_priv *priv) -{ - int ret; - struct ieee80211_hw *hw = priv->hw; - - hw->rate_control_algorithm = "iwl-3945-rs"; - hw->sta_data_size = sizeof(struct iwl3945_sta_priv); - - /* Tell mac80211 our characteristics */ - hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM | - IEEE80211_HW_SPECTRUM_MGMT; - - if (!priv->cfg->broken_powersave) - hw->flags |= IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_SUPPORTS_DYNAMIC_PS; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); - - hw->wiphy->custom_regulatory = true; - - /* Firmware does not support this */ - hw->wiphy->disable_beacon_hints = true; - - hw->wiphy->max_scan_ssids = PROBE_OPTION_MAX_3945; - /* we create the 802.11 header and a zero-length SSID element */ - hw->wiphy->max_scan_ie_len = IWL_MAX_PROBE_REQUEST - 24 - 2; - - /* Default value; 4 EDCA QOS priorities */ - hw->queues = 4; - - if (priv->bands[IEEE80211_BAND_2GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &priv->bands[IEEE80211_BAND_2GHZ]; - - if (priv->bands[IEEE80211_BAND_5GHZ].n_channels) - priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &priv->bands[IEEE80211_BAND_5GHZ]; - - ret = ieee80211_register_hw(priv->hw); - if (ret) { - IWL_ERR(priv, "Failed to register hw (error %d)\n", ret); - return ret; - } - priv->mac80211_registered = 1; - - return 0; -} - -static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - int err = 0; - struct iwl_priv *priv; - struct ieee80211_hw *hw; - struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data); - struct iwl3945_eeprom *eeprom; - unsigned long flags; - - /*********************** - * 1. Allocating HW data - * ********************/ - - /* mac80211 allocates memory for this device instance, including - * space for this driver's private structure */ - hw = iwl_alloc_all(cfg, &iwl3945_hw_ops); - if (hw == NULL) { - printk(KERN_ERR DRV_NAME "Can not allocate network device\n"); - err = -ENOMEM; - goto out; - } - priv = hw->priv; - SET_IEEE80211_DEV(hw, &pdev->dev); - - /* - * Disabling hardware scan means that mac80211 will perform scans - * "the hard way", rather than using device's scan. - */ - if (iwl3945_mod_params.disable_hw_scan) { - IWL_DEBUG_INFO(priv, "Disabling hw_scan\n"); - iwl3945_hw_ops.hw_scan = NULL; - } - - - IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); - priv->cfg = cfg; - priv->pci_dev = pdev; - priv->inta_mask = CSR_INI_SET_MASK; - -#ifdef CONFIG_IWLWIFI_DEBUG - atomic_set(&priv->restrict_refcnt, 0); -#endif - if (iwl_alloc_traffic_mem(priv)) - IWL_ERR(priv, "Not enough memory to generate traffic log\n"); - - /*************************** - * 2. Initializing PCI bus - * *************************/ - if (pci_enable_device(pdev)) { - err = -ENODEV; - goto out_ieee80211_free_hw; - } - - pci_set_master(pdev); - - err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (!err) - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (err) { - IWL_WARN(priv, "No suitable DMA available.\n"); - goto out_pci_disable_device; - } - - pci_set_drvdata(pdev, priv); - err = pci_request_regions(pdev, DRV_NAME); - if (err) - goto out_pci_disable_device; - - /*********************** - * 3. Read REV Register - * ********************/ - priv->hw_base = pci_iomap(pdev, 0, 0); - if (!priv->hw_base) { - err = -ENODEV; - goto out_pci_release_regions; - } - - IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n", - (unsigned long long) pci_resource_len(pdev, 0)); - IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base); - - /* We disable the RETRY_TIMEOUT register (0x41) to keep - * PCI Tx retries from interfering with C3 CPU state */ - pci_write_config_byte(pdev, 0x41, 0x00); - - /* this spin lock will be used in apm_ops.init and EEPROM access - * we should init now - */ - spin_lock_init(&priv->reg_lock); - - /* amp init */ - err = priv->cfg->ops->lib->apm_ops.init(priv); - if (err < 0) { - IWL_DEBUG_INFO(priv, "Failed to init the card\n"); - goto out_iounmap; - } - - /*********************** - * 4. Read EEPROM - * ********************/ - - /* Read the EEPROM */ - err = iwl_eeprom_init(priv); - if (err) { - IWL_ERR(priv, "Unable to init EEPROM\n"); - goto out_iounmap; - } - /* MAC Address location in EEPROM same for 3945/4965 */ - eeprom = (struct iwl3945_eeprom *)priv->eeprom; - memcpy(priv->mac_addr, eeprom->mac_address, ETH_ALEN); - IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->mac_addr); - SET_IEEE80211_PERM_ADDR(priv->hw, priv->mac_addr); - - /*********************** - * 5. Setup HW Constants - * ********************/ - /* Device-specific setup */ - if (iwl3945_hw_set_hw_params(priv)) { - IWL_ERR(priv, "failed to set hw settings\n"); - goto out_eeprom_free; - } - - /*********************** - * 6. Setup priv - * ********************/ - - err = iwl3945_init_drv(priv); - if (err) { - IWL_ERR(priv, "initializing driver failed\n"); - goto out_unset_hw_params; - } - - IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n", - priv->cfg->name); - - /*********************** - * 7. Setup Services - * ********************/ - - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - pci_enable_msi(priv->pci_dev); - - err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr, - IRQF_SHARED, DRV_NAME, priv); - if (err) { - IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq); - goto out_disable_msi; - } - - err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group); - if (err) { - IWL_ERR(priv, "failed to create sysfs device attributes\n"); - goto out_release_irq; - } - - iwl_set_rxon_channel(priv, - &priv->bands[IEEE80211_BAND_2GHZ].channels[5]); - iwl3945_setup_deferred_work(priv); - iwl3945_setup_rx_handlers(priv); - - /********************************* - * 8. Setup and Register mac80211 - * *******************************/ - - iwl_enable_interrupts(priv); - - err = iwl3945_setup_mac(priv); - if (err) - goto out_remove_sysfs; - - err = iwl_dbgfs_register(priv, DRV_NAME); - if (err) - IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err); - - /* Start monitoring the killswitch */ - queue_delayed_work(priv->workqueue, &priv->rfkill_poll, - 2 * HZ); - - return 0; - - out_remove_sysfs: - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); - out_release_irq: - free_irq(priv->pci_dev->irq, priv); - out_disable_msi: - pci_disable_msi(priv->pci_dev); - iwlcore_free_geos(priv); - iwl_free_channel_map(priv); - out_unset_hw_params: - iwl3945_unset_hw_params(priv); - out_eeprom_free: - iwl_eeprom_free(priv); - out_iounmap: - pci_iounmap(pdev, priv->hw_base); - out_pci_release_regions: - pci_release_regions(pdev); - out_pci_disable_device: - pci_set_drvdata(pdev, NULL); - pci_disable_device(pdev); - out_ieee80211_free_hw: - iwl_free_traffic_mem(priv); - ieee80211_free_hw(priv->hw); - out: - return err; -} - -static void __devexit iwl3945_pci_remove(struct pci_dev *pdev) -{ - struct iwl_priv *priv = pci_get_drvdata(pdev); - unsigned long flags; - - if (!priv) - return; - - IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n"); - - iwl_dbgfs_unregister(priv); - - set_bit(STATUS_EXIT_PENDING, &priv->status); - - if (priv->mac80211_registered) { - ieee80211_unregister_hw(priv->hw); - priv->mac80211_registered = 0; - } else { - iwl3945_down(priv); - } - - /* make sure we flush any pending irq or - * tasklet for the driver - */ - spin_lock_irqsave(&priv->lock, flags); - iwl_disable_interrupts(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - iwl_synchronize_irq(priv); - - sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group); - - cancel_delayed_work_sync(&priv->rfkill_poll); - - iwl3945_dealloc_ucode_pci(priv); - - if (priv->rxq.bd) - iwl3945_rx_queue_free(priv, &priv->rxq); - iwl3945_hw_txq_ctx_free(priv); - - iwl3945_unset_hw_params(priv); - iwl_clear_stations_table(priv); - - /*netif_stop_queue(dev); */ - flush_workqueue(priv->workqueue); - - /* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes - * priv->workqueue... so we can't take down the workqueue - * until now... */ - destroy_workqueue(priv->workqueue); - priv->workqueue = NULL; - iwl_free_traffic_mem(priv); - - free_irq(pdev->irq, priv); - pci_disable_msi(pdev); - - pci_iounmap(pdev, priv->hw_base); - pci_release_regions(pdev); - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); - - iwl_free_channel_map(priv); - iwlcore_free_geos(priv); - kfree(priv->scan); - if (priv->ibss_beacon) - dev_kfree_skb(priv->ibss_beacon); - - ieee80211_free_hw(priv->hw); -} - - -/***************************************************************************** - * - * driver and module entry point - * - *****************************************************************************/ - -static struct pci_driver iwl3945_driver = { - .name = DRV_NAME, - .id_table = iwl3945_hw_card_ids, - .probe = iwl3945_pci_probe, - .remove = __devexit_p(iwl3945_pci_remove), -#ifdef CONFIG_PM - .suspend = iwl_pci_suspend, - .resume = iwl_pci_resume, -#endif -}; - -static int __init iwl3945_init(void) -{ - - int ret; - printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); - printk(KERN_INFO DRV_NAME ": " DRV_COPYRIGHT "\n"); - - ret = iwl3945_rate_control_register(); - if (ret) { - printk(KERN_ERR DRV_NAME - "Unable to register rate control algorithm: %d\n", ret); - return ret; - } - - ret = pci_register_driver(&iwl3945_driver); - if (ret) { - printk(KERN_ERR DRV_NAME "Unable to initialize PCI module\n"); - goto error_register; - } - - return ret; - -error_register: - iwl3945_rate_control_unregister(); - return ret; -} - -static void __exit iwl3945_exit(void) -{ - pci_unregister_driver(&iwl3945_driver); - iwl3945_rate_control_unregister(); -} - -MODULE_FIRMWARE(IWL3945_MODULE_FIRMWARE(IWL3945_UCODE_API_MAX)); - -module_param_named(antenna, iwl3945_mod_params.antenna, int, 0444); -MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])"); -module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, 0444); -MODULE_PARM_DESC(swcrypto, - "using software crypto (default 1 [software])\n"); -#ifdef CONFIG_IWLWIFI_DEBUG -module_param_named(debug, iwl_debug_level, uint, 0644); -MODULE_PARM_DESC(debug, "debug output mask"); -#endif -module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan, int, 0444); -MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); -module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, 0444); -MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error"); - -module_exit(iwl3945_exit); -module_init(iwl3945_init); diff --git a/drivers/net/wireless/iwmc3200wifi/Kconfig b/drivers/net/wireless/iwmc3200wifi/Kconfig deleted file mode 100644 index c25a04371ca8..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/Kconfig +++ /dev/null @@ -1,31 +0,0 @@ -config IWM - tristate "Intel Wireless Multicomm 3200 WiFi driver" - depends on MMC && WLAN_80211 && EXPERIMENTAL - depends on CFG80211 - select FW_LOADER - help - The Intel Wireless Multicomm 3200 hardware is a combo - card with GPS, Bluetooth, WiMax and 802.11 radios. It - runs over SDIO and is typically found on Moorestown - based platform. This driver takes care of the 802.11 - part, which is a fullmac one. - - If you choose to build it as a module, it'll be called - iwmc3200wifi.ko. - -config IWM_DEBUG - bool "Enable full debugging output in iwmc3200wifi" - depends on IWM && DEBUG_FS - ---help--- - This option will enable debug tracing and setting for iwm - - You can set the debug level and module through debugfs. By - default all modules are set to the IWL_DL_ERR level. - To see the list of debug modules and levels, see iwm/debug.h - - For example, if you want the full MLME debug output: - echo 0xff > /sys/kernel/debug/iwm/phyN/debug/mlme - - Or, if you want the full debug, for all modules: - echo 0xff > /sys/kernel/debug/iwm/phyN/debug/level - echo 0xff > /sys/kernel/debug/iwm/phyN/debug/modules diff --git a/drivers/net/wireless/iwmc3200wifi/Makefile b/drivers/net/wireless/iwmc3200wifi/Makefile deleted file mode 100644 index d34291b652d3..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-$(CONFIG_IWM) := iwmc3200wifi.o -iwmc3200wifi-objs += main.o netdev.o rx.o tx.o sdio.o hal.o fw.o -iwmc3200wifi-objs += commands.o cfg80211.o eeprom.o - -iwmc3200wifi-$(CONFIG_IWM_DEBUG) += debugfs.o diff --git a/drivers/net/wireless/iwmc3200wifi/bus.h b/drivers/net/wireless/iwmc3200wifi/bus.h deleted file mode 100644 index 836663eec257..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/bus.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#ifndef __IWM_BUS_H__ -#define __IWM_BUS_H__ - -#include "iwm.h" - -struct iwm_if_ops { - int (*enable)(struct iwm_priv *iwm); - int (*disable)(struct iwm_priv *iwm); - int (*send_chunk)(struct iwm_priv *iwm, u8* buf, int count); - - int (*debugfs_init)(struct iwm_priv *iwm, struct dentry *parent_dir); - void (*debugfs_exit)(struct iwm_priv *iwm); - - const char *umac_name; - const char *calib_lmac_name; - const char *lmac_name; -}; - -static inline int iwm_bus_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) -{ - return iwm->bus_ops->send_chunk(iwm, buf, count); -} - -static inline int iwm_bus_enable(struct iwm_priv *iwm) -{ - return iwm->bus_ops->enable(iwm); -} - -static inline int iwm_bus_disable(struct iwm_priv *iwm) -{ - return iwm->bus_ops->disable(iwm); -} - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c deleted file mode 100644 index f3c55658225b..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c +++ /dev/null @@ -1,822 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "iwm.h" -#include "commands.h" -#include "cfg80211.h" -#include "debug.h" - -#define RATETAB_ENT(_rate, _rateid, _flags) \ - { \ - .bitrate = (_rate), \ - .hw_value = (_rateid), \ - .flags = (_flags), \ - } - -#define CHAN2G(_channel, _freq, _flags) { \ - .band = IEEE80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -#define CHAN5G(_channel, _flags) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = 5000 + (5 * (_channel)), \ - .hw_value = (_channel), \ - .flags = (_flags), \ - .max_antenna_gain = 0, \ - .max_power = 30, \ -} - -static struct ieee80211_rate iwm_rates[] = { - RATETAB_ENT(10, 0x1, 0), - RATETAB_ENT(20, 0x2, 0), - RATETAB_ENT(55, 0x4, 0), - RATETAB_ENT(110, 0x8, 0), - RATETAB_ENT(60, 0x10, 0), - RATETAB_ENT(90, 0x20, 0), - RATETAB_ENT(120, 0x40, 0), - RATETAB_ENT(180, 0x80, 0), - RATETAB_ENT(240, 0x100, 0), - RATETAB_ENT(360, 0x200, 0), - RATETAB_ENT(480, 0x400, 0), - RATETAB_ENT(540, 0x800, 0), -}; - -#define iwm_a_rates (iwm_rates + 4) -#define iwm_a_rates_size 8 -#define iwm_g_rates (iwm_rates + 0) -#define iwm_g_rates_size 12 - -static struct ieee80211_channel iwm_2ghz_channels[] = { - CHAN2G(1, 2412, 0), - CHAN2G(2, 2417, 0), - CHAN2G(3, 2422, 0), - CHAN2G(4, 2427, 0), - CHAN2G(5, 2432, 0), - CHAN2G(6, 2437, 0), - CHAN2G(7, 2442, 0), - CHAN2G(8, 2447, 0), - CHAN2G(9, 2452, 0), - CHAN2G(10, 2457, 0), - CHAN2G(11, 2462, 0), - CHAN2G(12, 2467, 0), - CHAN2G(13, 2472, 0), - CHAN2G(14, 2484, 0), -}; - -static struct ieee80211_channel iwm_5ghz_a_channels[] = { - CHAN5G(34, 0), CHAN5G(36, 0), - CHAN5G(38, 0), CHAN5G(40, 0), - CHAN5G(42, 0), CHAN5G(44, 0), - CHAN5G(46, 0), CHAN5G(48, 0), - CHAN5G(52, 0), CHAN5G(56, 0), - CHAN5G(60, 0), CHAN5G(64, 0), - CHAN5G(100, 0), CHAN5G(104, 0), - CHAN5G(108, 0), CHAN5G(112, 0), - CHAN5G(116, 0), CHAN5G(120, 0), - CHAN5G(124, 0), CHAN5G(128, 0), - CHAN5G(132, 0), CHAN5G(136, 0), - CHAN5G(140, 0), CHAN5G(149, 0), - CHAN5G(153, 0), CHAN5G(157, 0), - CHAN5G(161, 0), CHAN5G(165, 0), - CHAN5G(184, 0), CHAN5G(188, 0), - CHAN5G(192, 0), CHAN5G(196, 0), - CHAN5G(200, 0), CHAN5G(204, 0), - CHAN5G(208, 0), CHAN5G(212, 0), - CHAN5G(216, 0), -}; - -static struct ieee80211_supported_band iwm_band_2ghz = { - .channels = iwm_2ghz_channels, - .n_channels = ARRAY_SIZE(iwm_2ghz_channels), - .bitrates = iwm_g_rates, - .n_bitrates = iwm_g_rates_size, -}; - -static struct ieee80211_supported_band iwm_band_5ghz = { - .channels = iwm_5ghz_a_channels, - .n_channels = ARRAY_SIZE(iwm_5ghz_a_channels), - .bitrates = iwm_a_rates, - .n_bitrates = iwm_a_rates_size, -}; - -static int iwm_key_init(struct iwm_key *key, u8 key_index, - const u8 *mac_addr, struct key_params *params) -{ - key->hdr.key_idx = key_index; - if (!mac_addr || is_broadcast_ether_addr(mac_addr)) { - key->hdr.multicast = 1; - memset(key->hdr.mac, 0xff, ETH_ALEN); - } else { - key->hdr.multicast = 0; - memcpy(key->hdr.mac, mac_addr, ETH_ALEN); - } - - if (params) { - if (params->key_len > WLAN_MAX_KEY_LEN || - params->seq_len > IW_ENCODE_SEQ_MAX_SIZE) - return -EINVAL; - - key->cipher = params->cipher; - key->key_len = params->key_len; - key->seq_len = params->seq_len; - memcpy(key->key, params->key, key->key_len); - memcpy(key->seq, params->seq, key->seq_len); - } - - return 0; -} - -static int iwm_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, const u8 *mac_addr, - struct key_params *params) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - struct iwm_key *key = &iwm->keys[key_index]; - int ret; - - IWM_DBG_WEXT(iwm, DBG, "Adding key for %pM\n", mac_addr); - - memset(key, 0, sizeof(struct iwm_key)); - ret = iwm_key_init(key, key_index, mac_addr, params); - if (ret < 0) { - IWM_ERR(iwm, "Invalid key_params\n"); - return ret; - } - - return iwm_set_key(iwm, 0, key); -} - -static int iwm_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, const u8 *mac_addr, void *cookie, - void (*callback)(void *cookie, - struct key_params*)) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - struct iwm_key *key = &iwm->keys[key_index]; - struct key_params params; - - IWM_DBG_WEXT(iwm, DBG, "Getting key %d\n", key_index); - - memset(¶ms, 0, sizeof(params)); - - params.cipher = key->cipher; - params.key_len = key->key_len; - params.seq_len = key->seq_len; - params.seq = key->seq; - params.key = key->key; - - callback(cookie, ¶ms); - - return key->key_len ? 0 : -ENOENT; -} - - -static int iwm_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, - u8 key_index, const u8 *mac_addr) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - struct iwm_key *key = &iwm->keys[key_index]; - - if (!iwm->keys[key_index].key_len) { - IWM_DBG_WEXT(iwm, DBG, "Key %d not used\n", key_index); - return 0; - } - - if (key_index == iwm->default_key) - iwm->default_key = -1; - - return iwm_set_key(iwm, 1, key); -} - -static int iwm_cfg80211_set_default_key(struct wiphy *wiphy, - struct net_device *ndev, - u8 key_index) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - - IWM_DBG_WEXT(iwm, DBG, "Default key index is: %d\n", key_index); - - if (!iwm->keys[key_index].key_len) { - IWM_ERR(iwm, "Key %d not used\n", key_index); - return -EINVAL; - } - - iwm->default_key = key_index; - - return iwm_set_tx_key(iwm, key_index); -} - -static int iwm_cfg80211_get_station(struct wiphy *wiphy, - struct net_device *ndev, - u8 *mac, struct station_info *sinfo) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - - if (memcmp(mac, iwm->bssid, ETH_ALEN)) - return -ENOENT; - - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = iwm->rate * 10; - - if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = iwm->wstats.qual.level; - } - - return 0; -} - - -int iwm_cfg80211_inform_bss(struct iwm_priv *iwm) -{ - struct wiphy *wiphy = iwm_to_wiphy(iwm); - struct iwm_bss_info *bss, *next; - struct iwm_umac_notif_bss_info *umac_bss; - struct ieee80211_mgmt *mgmt; - struct ieee80211_channel *channel; - struct ieee80211_supported_band *band; - s32 signal; - int freq; - - list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { - umac_bss = bss->bss; - mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); - - if (umac_bss->band == UMAC_BAND_2GHZ) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - else if (umac_bss->band == UMAC_BAND_5GHZ) - band = wiphy->bands[IEEE80211_BAND_5GHZ]; - else { - IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); - return -EINVAL; - } - - freq = ieee80211_channel_to_frequency(umac_bss->channel); - channel = ieee80211_get_channel(wiphy, freq); - signal = umac_bss->rssi * 100; - - if (!cfg80211_inform_bss_frame(wiphy, channel, mgmt, - le16_to_cpu(umac_bss->frame_len), - signal, GFP_KERNEL)) - return -EINVAL; - } - - return 0; -} - -static int iwm_cfg80211_change_iface(struct wiphy *wiphy, - struct net_device *ndev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct wireless_dev *wdev; - struct iwm_priv *iwm; - u32 old_mode; - - wdev = ndev->ieee80211_ptr; - iwm = ndev_to_iwm(ndev); - old_mode = iwm->conf.mode; - - switch (type) { - case NL80211_IFTYPE_STATION: - iwm->conf.mode = UMAC_MODE_BSS; - break; - case NL80211_IFTYPE_ADHOC: - iwm->conf.mode = UMAC_MODE_IBSS; - break; - default: - return -EOPNOTSUPP; - } - - wdev->iftype = type; - - if ((old_mode == iwm->conf.mode) || !iwm->umac_profile) - return 0; - - iwm->umac_profile->mode = cpu_to_le32(iwm->conf.mode); - - if (iwm->umac_profile_active) - iwm_invalidate_mlme_profile(iwm); - - return 0; -} - -static int iwm_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, - struct cfg80211_scan_request *request) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - int ret; - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) { - IWM_ERR(iwm, "Scan while device is not ready\n"); - return -EIO; - } - - if (test_bit(IWM_STATUS_SCANNING, &iwm->status)) { - IWM_ERR(iwm, "Scanning already\n"); - return -EAGAIN; - } - - if (test_bit(IWM_STATUS_SCAN_ABORTING, &iwm->status)) { - IWM_ERR(iwm, "Scanning being aborted\n"); - return -EAGAIN; - } - - set_bit(IWM_STATUS_SCANNING, &iwm->status); - - ret = iwm_scan_ssids(iwm, request->ssids, request->n_ssids); - if (ret) { - clear_bit(IWM_STATUS_SCANNING, &iwm->status); - return ret; - } - - iwm->scan_request = request; - return 0; -} - -static int iwm_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - - if (changed & WIPHY_PARAM_RTS_THRESHOLD && - (iwm->conf.rts_threshold != wiphy->rts_threshold)) { - int ret; - - iwm->conf.rts_threshold = wiphy->rts_threshold; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_RTS_THRESHOLD, - iwm->conf.rts_threshold); - if (ret < 0) - return ret; - } - - if (changed & WIPHY_PARAM_FRAG_THRESHOLD && - (iwm->conf.frag_threshold != wiphy->frag_threshold)) { - int ret; - - iwm->conf.frag_threshold = wiphy->frag_threshold; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, - CFG_FRAG_THRESHOLD, - iwm->conf.frag_threshold); - if (ret < 0) - return ret; - } - - return 0; -} - -static int iwm_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - struct ieee80211_channel *chan = params->channel; - struct cfg80211_bss *bss; - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - /* UMAC doesn't support creating IBSS network with specified bssid. - * This should be removed after we have join only mode supported. */ - if (params->bssid) - return -EOPNOTSUPP; - - bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL, - params->ssid, params->ssid_len); - if (!bss) { - iwm_scan_one_ssid(iwm, params->ssid, params->ssid_len); - schedule_timeout_interruptible(2 * HZ); - bss = cfg80211_get_ibss(iwm_to_wiphy(iwm), NULL, - params->ssid, params->ssid_len); - } - /* IBSS join only mode is not supported by UMAC ATM */ - if (bss) { - cfg80211_put_bss(bss); - return -EOPNOTSUPP; - } - - iwm->channel = ieee80211_frequency_to_channel(chan->center_freq); - iwm->umac_profile->ibss.band = chan->band; - iwm->umac_profile->ibss.channel = iwm->channel; - iwm->umac_profile->ssid.ssid_len = params->ssid_len; - memcpy(iwm->umac_profile->ssid.ssid, params->ssid, params->ssid_len); - - if (params->bssid) - memcpy(&iwm->umac_profile->bssid[0], params->bssid, ETH_ALEN); - - return iwm_send_mlme_profile(iwm); -} - -static int iwm_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - - if (iwm->umac_profile_active) - return iwm_invalidate_mlme_profile(iwm); - - return 0; -} - -static int iwm_set_auth_type(struct iwm_priv *iwm, - enum nl80211_auth_type sme_auth_type) -{ - u8 *auth_type = &iwm->umac_profile->sec.auth_type; - - switch (sme_auth_type) { - case NL80211_AUTHTYPE_AUTOMATIC: - case NL80211_AUTHTYPE_OPEN_SYSTEM: - IWM_DBG_WEXT(iwm, DBG, "OPEN auth\n"); - *auth_type = UMAC_AUTH_TYPE_OPEN; - break; - case NL80211_AUTHTYPE_SHARED_KEY: - if (iwm->umac_profile->sec.flags & - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) { - IWM_DBG_WEXT(iwm, DBG, "WPA auth alg\n"); - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; - } else { - IWM_DBG_WEXT(iwm, DBG, "WEP shared key auth alg\n"); - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - } - - break; - default: - IWM_ERR(iwm, "Unsupported auth alg: 0x%x\n", sme_auth_type); - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_set_wpa_version(struct iwm_priv *iwm, u32 wpa_version) -{ - IWM_DBG_WEXT(iwm, DBG, "wpa_version: %d\n", wpa_version); - - if (!wpa_version) { - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; - return 0; - } - - if (wpa_version & NL80211_WPA_VERSION_2) - iwm->umac_profile->sec.flags = UMAC_SEC_FLG_RSNA_ON_MSK; - - if (wpa_version & NL80211_WPA_VERSION_1) - iwm->umac_profile->sec.flags |= UMAC_SEC_FLG_WPA_ON_MSK; - - return 0; -} - -static int iwm_set_cipher(struct iwm_priv *iwm, u32 cipher, bool ucast) -{ - u8 *profile_cipher = ucast ? &iwm->umac_profile->sec.ucast_cipher : - &iwm->umac_profile->sec.mcast_cipher; - - if (!cipher) { - *profile_cipher = UMAC_CIPHER_TYPE_NONE; - return 0; - } - - IWM_DBG_WEXT(iwm, DBG, "%ccast cipher is 0x%x\n", ucast ? 'u' : 'm', - cipher); - - switch (cipher) { - case IW_AUTH_CIPHER_NONE: - *profile_cipher = UMAC_CIPHER_TYPE_NONE; - break; - case WLAN_CIPHER_SUITE_WEP40: - *profile_cipher = UMAC_CIPHER_TYPE_WEP_40; - break; - case WLAN_CIPHER_SUITE_WEP104: - *profile_cipher = UMAC_CIPHER_TYPE_WEP_104; - break; - case WLAN_CIPHER_SUITE_TKIP: - *profile_cipher = UMAC_CIPHER_TYPE_TKIP; - break; - case WLAN_CIPHER_SUITE_CCMP: - *profile_cipher = UMAC_CIPHER_TYPE_CCMP; - break; - default: - IWM_ERR(iwm, "Unsupported cipher: 0x%x\n", cipher); - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_set_key_mgt(struct iwm_priv *iwm, u32 key_mgt) -{ - u8 *auth_type = &iwm->umac_profile->sec.auth_type; - - IWM_DBG_WEXT(iwm, DBG, "key_mgt: 0x%x\n", key_mgt); - - if (key_mgt == WLAN_AKM_SUITE_8021X) - *auth_type = UMAC_AUTH_TYPE_8021X; - else if (key_mgt == WLAN_AKM_SUITE_PSK) { - if (iwm->umac_profile->sec.flags & - (UMAC_SEC_FLG_WPA_ON_MSK | UMAC_SEC_FLG_RSNA_ON_MSK)) - *auth_type = UMAC_AUTH_TYPE_RSNA_PSK; - else - *auth_type = UMAC_AUTH_TYPE_LEGACY_PSK; - } else { - IWM_ERR(iwm, "Invalid key mgt: 0x%x\n", key_mgt); - return -EINVAL; - } - - return 0; -} - - -static int iwm_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - struct ieee80211_channel *chan = sme->channel; - struct key_params key_param; - int ret; - - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return -EIO; - - if (!sme->ssid) - return -EINVAL; - - if (iwm->umac_profile_active) { - ret = iwm_invalidate_mlme_profile(iwm); - if (ret) { - IWM_ERR(iwm, "Couldn't invalidate profile\n"); - return ret; - } - } - - if (chan) - iwm->channel = - ieee80211_frequency_to_channel(chan->center_freq); - - iwm->umac_profile->ssid.ssid_len = sme->ssid_len; - memcpy(iwm->umac_profile->ssid.ssid, sme->ssid, sme->ssid_len); - - if (sme->bssid) { - IWM_DBG_WEXT(iwm, DBG, "BSSID: %pM\n", sme->bssid); - memcpy(&iwm->umac_profile->bssid[0], sme->bssid, ETH_ALEN); - iwm->umac_profile->bss_num = 1; - } else { - memset(&iwm->umac_profile->bssid[0], 0, ETH_ALEN); - iwm->umac_profile->bss_num = 0; - } - - ret = iwm_set_wpa_version(iwm, sme->crypto.wpa_versions); - if (ret < 0) - return ret; - - ret = iwm_set_auth_type(iwm, sme->auth_type); - if (ret < 0) - return ret; - - if (sme->crypto.n_ciphers_pairwise) { - ret = iwm_set_cipher(iwm, sme->crypto.ciphers_pairwise[0], - true); - if (ret < 0) - return ret; - } - - ret = iwm_set_cipher(iwm, sme->crypto.cipher_group, false); - if (ret < 0) - return ret; - - if (sme->crypto.n_akm_suites) { - ret = iwm_set_key_mgt(iwm, sme->crypto.akm_suites[0]); - if (ret < 0) - return ret; - } - - /* - * We save the WEP key in case we want to do shared authentication. - * We have to do it so because UMAC will assert whenever it gets a - * key before a profile. - */ - if (sme->key) { - key_param.key = kmemdup(sme->key, sme->key_len, GFP_KERNEL); - if (key_param.key == NULL) - return -ENOMEM; - key_param.key_len = sme->key_len; - key_param.seq_len = 0; - key_param.cipher = sme->crypto.ciphers_pairwise[0]; - - ret = iwm_key_init(&iwm->keys[sme->key_idx], sme->key_idx, - NULL, &key_param); - kfree(key_param.key); - if (ret < 0) { - IWM_ERR(iwm, "Invalid key_params\n"); - return ret; - } - - iwm->default_key = sme->key_idx; - } - - ret = iwm_send_mlme_profile(iwm); - - if (iwm->umac_profile->sec.auth_type != UMAC_AUTH_TYPE_LEGACY_PSK || - sme->key == NULL) - return ret; - - /* - * We want to do shared auth. - * We need to actually set the key we previously cached, - * and then tell the UMAC it's the default one. - * That will trigger the auth+assoc UMAC machinery, and again, - * this must be done after setting the profile. - */ - ret = iwm_set_key(iwm, 0, &iwm->keys[sme->key_idx]); - if (ret < 0) - return ret; - - return iwm_set_tx_key(iwm, iwm->default_key); -} - -static int iwm_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - - IWM_DBG_WEXT(iwm, DBG, "Active: %d\n", iwm->umac_profile_active); - - if (iwm->umac_profile_active) - iwm_invalidate_mlme_profile(iwm); - - return 0; -} - -static int iwm_cfg80211_set_txpower(struct wiphy *wiphy, - enum tx_power_setting type, int dbm) -{ - switch (type) { - case TX_POWER_AUTOMATIC: - return 0; - default: - return -EOPNOTSUPP; - } - - return 0; -} - -static int iwm_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - - *dbm = iwm->txpower; - - return 0; -} - -static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy, - struct net_device *dev, - bool enabled, int timeout) -{ - struct iwm_priv *iwm = wiphy_to_iwm(wiphy); - u32 power_index; - - if (enabled) - power_index = IWM_POWER_INDEX_DEFAULT; - else - power_index = IWM_POWER_INDEX_MIN; - - if (power_index == iwm->conf.power_index) - return 0; - - iwm->conf.power_index = power_index; - - return iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_POWER_INDEX, iwm->conf.power_index); -} - -static struct cfg80211_ops iwm_cfg80211_ops = { - .change_virtual_intf = iwm_cfg80211_change_iface, - .add_key = iwm_cfg80211_add_key, - .get_key = iwm_cfg80211_get_key, - .del_key = iwm_cfg80211_del_key, - .set_default_key = iwm_cfg80211_set_default_key, - .get_station = iwm_cfg80211_get_station, - .scan = iwm_cfg80211_scan, - .set_wiphy_params = iwm_cfg80211_set_wiphy_params, - .connect = iwm_cfg80211_connect, - .disconnect = iwm_cfg80211_disconnect, - .join_ibss = iwm_cfg80211_join_ibss, - .leave_ibss = iwm_cfg80211_leave_ibss, - .set_tx_power = iwm_cfg80211_set_txpower, - .get_tx_power = iwm_cfg80211_get_txpower, - .set_power_mgmt = iwm_cfg80211_set_power_mgmt, -}; - -static const u32 cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, -}; - -struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev) -{ - int ret = 0; - struct wireless_dev *wdev; - - /* - * We're trying to have the following memory - * layout: - * - * +-------------------------+ - * | struct wiphy | - * +-------------------------+ - * | struct iwm_priv | - * +-------------------------+ - * | bus private data | - * | (e.g. iwm_priv_sdio) | - * +-------------------------+ - * - */ - - wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); - if (!wdev) { - dev_err(dev, "Couldn't allocate wireless device\n"); - return ERR_PTR(-ENOMEM); - } - - wdev->wiphy = wiphy_new(&iwm_cfg80211_ops, - sizeof(struct iwm_priv) + sizeof_bus); - if (!wdev->wiphy) { - dev_err(dev, "Couldn't allocate wiphy device\n"); - ret = -ENOMEM; - goto out_err_new; - } - - set_wiphy_dev(wdev->wiphy, dev); - wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX; - wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); - wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz; - wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &iwm_band_5ghz; - wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - wdev->wiphy->cipher_suites = cipher_suites; - wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); - - ret = wiphy_register(wdev->wiphy); - if (ret < 0) { - dev_err(dev, "Couldn't register wiphy device\n"); - goto out_err_register; - } - - return wdev; - - out_err_register: - wiphy_free(wdev->wiphy); - - out_err_new: - kfree(wdev); - - return ERR_PTR(ret); -} - -void iwm_wdev_free(struct iwm_priv *iwm) -{ - struct wireless_dev *wdev = iwm_to_wdev(iwm); - - if (!wdev) - return; - - wiphy_unregister(wdev->wiphy); - wiphy_free(wdev->wiphy); - kfree(wdev); -} diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.h b/drivers/net/wireless/iwmc3200wifi/cfg80211.h deleted file mode 100644 index 56a34145acbf..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/cfg80211.h +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#ifndef __IWM_CFG80211_H__ -#define __IWM_CFG80211_H__ - -int iwm_cfg80211_inform_bss(struct iwm_priv *iwm); -struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev); -void iwm_wdev_free(struct iwm_priv *iwm); - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c deleted file mode 100644 index 84158b6d35d8..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/commands.c +++ /dev/null @@ -1,902 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#include -#include -#include -#include -#include - -#include "iwm.h" -#include "bus.h" -#include "hal.h" -#include "umac.h" -#include "commands.h" -#include "debug.h" - -static int iwm_send_lmac_ptrough_cmd(struct iwm_priv *iwm, - u8 lmac_cmd_id, - const void *lmac_payload, - u16 lmac_payload_size, - u8 resp) -{ - struct iwm_udma_wifi_cmd udma_cmd = UDMA_LMAC_INIT; - struct iwm_umac_cmd umac_cmd; - struct iwm_lmac_cmd lmac_cmd; - - lmac_cmd.id = lmac_cmd_id; - - umac_cmd.id = UMAC_CMD_OPCODE_WIFI_PASS_THROUGH; - umac_cmd.resp = resp; - - return iwm_hal_send_host_cmd(iwm, &udma_cmd, &umac_cmd, &lmac_cmd, - lmac_payload, lmac_payload_size); -} - -int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, - bool resp) -{ - struct iwm_umac_wifi_if *hdr = (struct iwm_umac_wifi_if *)payload; - struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; - struct iwm_umac_cmd umac_cmd; - int ret; - u8 oid = hdr->oid; - - umac_cmd.id = UMAC_CMD_OPCODE_WIFI_IF_WRAPPER; - umac_cmd.resp = resp; - - ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, - payload, payload_size); - - if (resp) { - ret = wait_event_interruptible_timeout(iwm->wifi_ntfy_queue, - test_and_clear_bit(oid, &iwm->wifi_ntfy[0]), - 3 * HZ); - - return ret ? 0 : -EBUSY; - } - - return ret; -} - -static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = -{ - {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS}, - {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, - {4, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, - {4, 3, 0, COEX_CALIBRATION_FLAGS}, - {4, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, - {4, 3, 0, COEX_CONNECTION_ESTAB_FLAGS}, - {4, 3, 0, COEX_ASSOCIATED_IDLE_FLAGS}, - {4, 3, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, - {4, 3, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, - {4, 3, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, - {6, 3, 0, COEX_XOR_RF_ON_FLAGS}, - {4, 3, 0, COEX_RF_OFF_FLAGS}, - {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, - {4, 3, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, - {4, 3, 0, COEX_RSRVD1_FLAGS}, - {4, 3, 0, COEX_RSRVD2_FLAGS} -}; - -static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = -{ - {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS}, - {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, - {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, - {5, 5, 0, COEX_CALIBRATION_FLAGS}, - {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, - {5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS}, - {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS}, - {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, - {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, - {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, - {1, 1, 0, COEX_RF_ON_FLAGS}, - {1, 1, 0, COEX_RF_OFF_FLAGS}, - {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, - {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, - {1, 1, 0, COEX_RSRVD1_FLAGS}, - {1, 1, 0, COEX_RSRVD2_FLAGS} -}; - -int iwm_send_prio_table(struct iwm_priv *iwm) -{ - struct iwm_coex_prio_table_cmd coex_table_cmd; - u32 coex_enabled, mode_enabled; - - memset(&coex_table_cmd, 0, sizeof(struct iwm_coex_prio_table_cmd)); - - coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK; - - switch (iwm->conf.coexist_mode) { - case COEX_MODE_XOR: - case COEX_MODE_CM: - coex_enabled = 1; - break; - default: - coex_enabled = 0; - break; - } - - switch (iwm->conf.mode) { - case UMAC_MODE_BSS: - case UMAC_MODE_IBSS: - mode_enabled = 1; - break; - default: - mode_enabled = 0; - break; - } - - if (coex_enabled && mode_enabled) { - coex_table_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK | - COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK | - COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK; - - switch (iwm->conf.coexist_mode) { - case COEX_MODE_XOR: - memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl, - sizeof(iwm_sta_xor_prio_tbl)); - break; - case COEX_MODE_CM: - memcpy(coex_table_cmd.sta_prio, iwm_sta_cm_prio_tbl, - sizeof(iwm_sta_cm_prio_tbl)); - break; - default: - IWM_ERR(iwm, "Invalid coex_mode 0x%x\n", - iwm->conf.coexist_mode); - break; - } - } else - IWM_WARN(iwm, "coexistense disabled\n"); - - return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD, - &coex_table_cmd, - sizeof(struct iwm_coex_prio_table_cmd), 1); -} - -int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) -{ - struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd; - - memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd)); - - cal_cfg_cmd.ucode_cfg.init.enable = cpu_to_le32(calib_requested); - cal_cfg_cmd.ucode_cfg.init.start = cpu_to_le32(calib_requested); - cal_cfg_cmd.ucode_cfg.init.send_res = cpu_to_le32(calib_requested); - cal_cfg_cmd.ucode_cfg.flags = - cpu_to_le32(CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK); - - return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd, - sizeof(struct iwm_lmac_cal_cfg_cmd), 1); -} - -int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) -{ - struct iwm_lmac_cal_cfg_cmd cal_cfg_cmd; - - memset(&cal_cfg_cmd, 0, sizeof(struct iwm_lmac_cal_cfg_cmd)); - - cal_cfg_cmd.ucode_cfg.periodic.enable = cpu_to_le32(calib_requested); - cal_cfg_cmd.ucode_cfg.periodic.start = cpu_to_le32(calib_requested); - - return iwm_send_lmac_ptrough_cmd(iwm, CALIBRATION_CFG_CMD, &cal_cfg_cmd, - sizeof(struct iwm_lmac_cal_cfg_cmd), 0); -} - -int iwm_store_rxiq_calib_result(struct iwm_priv *iwm) -{ - struct iwm_calib_rxiq *rxiq; - u8 *eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ); - int grplen = sizeof(struct iwm_calib_rxiq_group); - - rxiq = kzalloc(sizeof(struct iwm_calib_rxiq), GFP_KERNEL); - if (!rxiq) { - IWM_ERR(iwm, "Couldn't alloc memory for RX IQ\n"); - return -ENOMEM; - } - - eeprom_rxiq = iwm_eeprom_access(iwm, IWM_EEPROM_CALIB_RXIQ); - if (IS_ERR(eeprom_rxiq)) { - IWM_ERR(iwm, "Couldn't access EEPROM RX IQ entry\n"); - kfree(rxiq); - return PTR_ERR(eeprom_rxiq); - } - - iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].buf = (u8 *)rxiq; - iwm->calib_res[SHILOH_PHY_CALIBRATE_RX_IQ_CMD].size = sizeof(*rxiq); - - rxiq->hdr.opcode = SHILOH_PHY_CALIBRATE_RX_IQ_CMD; - rxiq->hdr.first_grp = 0; - rxiq->hdr.grp_num = 1; - rxiq->hdr.all_data_valid = 1; - - memcpy(&rxiq->group[0], eeprom_rxiq, 4 * grplen); - memcpy(&rxiq->group[4], eeprom_rxiq + 6 * grplen, grplen); - - return 0; -} - -int iwm_send_calib_results(struct iwm_priv *iwm) -{ - int i, ret = 0; - - for (i = PHY_CALIBRATE_OPCODES_NUM; i < CALIBRATION_CMD_NUM; i++) { - if (test_bit(i - PHY_CALIBRATE_OPCODES_NUM, - &iwm->calib_done_map)) { - IWM_DBG_CMD(iwm, DBG, - "Send calibration %d result\n", i); - ret |= iwm_send_lmac_ptrough_cmd(iwm, - REPLY_PHY_CALIBRATION_CMD, - iwm->calib_res[i].buf, - iwm->calib_res[i].size, 0); - - kfree(iwm->calib_res[i].buf); - iwm->calib_res[i].buf = NULL; - iwm->calib_res[i].size = 0; - } - } - - return ret; -} - -int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp) -{ - struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; - struct iwm_umac_cmd umac_cmd; - struct iwm_umac_cmd_reset reset; - - reset.flags = reset_flags; - - umac_cmd.id = UMAC_CMD_OPCODE_RESET; - umac_cmd.resp = resp; - - return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &reset, - sizeof(struct iwm_umac_cmd_reset)); -} - -int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value) -{ - struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; - struct iwm_umac_cmd umac_cmd; - struct iwm_umac_cmd_set_param_fix param; - - if ((tbl != UMAC_PARAM_TBL_CFG_FIX) && - (tbl != UMAC_PARAM_TBL_FA_CFG_FIX)) - return -EINVAL; - - umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_FIX; - umac_cmd.resp = 0; - - param.tbl = cpu_to_le16(tbl); - param.key = cpu_to_le16(key); - param.value = cpu_to_le32(value); - - return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ¶m, - sizeof(struct iwm_umac_cmd_set_param_fix)); -} - -int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, - void *payload, u16 payload_size) -{ - struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; - struct iwm_umac_cmd umac_cmd; - struct iwm_umac_cmd_set_param_var *param_hdr; - u8 *param; - int ret; - - param = kzalloc(payload_size + - sizeof(struct iwm_umac_cmd_set_param_var), GFP_KERNEL); - if (!param) { - IWM_ERR(iwm, "Couldn't allocate param\n"); - return -ENOMEM; - } - - param_hdr = (struct iwm_umac_cmd_set_param_var *)param; - - umac_cmd.id = UMAC_CMD_OPCODE_SET_PARAM_VAR; - umac_cmd.resp = 0; - - param_hdr->tbl = cpu_to_le16(UMAC_PARAM_TBL_CFG_VAR); - param_hdr->key = cpu_to_le16(key); - param_hdr->len = cpu_to_le16(payload_size); - memcpy(param + sizeof(struct iwm_umac_cmd_set_param_var), - payload, payload_size); - - ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, param, - sizeof(struct iwm_umac_cmd_set_param_var) + - payload_size); - kfree(param); - - return ret; -} - -int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags) -{ - int ret; - - /* Use UMAC default values */ - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_POWER_INDEX, iwm->conf.power_index); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_FA_CFG_FIX, - CFG_FRAG_THRESHOLD, - iwm->conf.frag_threshold); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_RTS_THRESHOLD, - iwm->conf.rts_threshold); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_CTS_TO_SELF, iwm->conf.cts_to_self); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_WIRELESS_MODE, - iwm->conf.wireless_mode); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_COEX_MODE, iwm->conf.coexist_mode); - if (ret < 0) - return ret; - - /* - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_ASSOCIATION_TIMEOUT, - iwm->conf.assoc_timeout); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_ROAM_TIMEOUT, - iwm->conf.roam_timeout); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_WIRELESS_MODE, - WIRELESS_MODE_11A | WIRELESS_MODE_11G); - if (ret < 0) - return ret; - */ - - ret = iwm_umac_set_config_var(iwm, CFG_NET_ADDR, - iwm_to_ndev(iwm)->dev_addr, ETH_ALEN); - if (ret < 0) - return ret; - - /* UMAC PM static configurations */ - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_PM_LEGACY_RX_TIMEOUT, 0x12C); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_PM_LEGACY_TX_TIMEOUT, 0x15E); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_PM_CTRL_FLAGS, 0x1); - if (ret < 0) - return ret; - - ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, - CFG_PM_KEEP_ALIVE_IN_BEACONS, 0x80); - if (ret < 0) - return ret; - - /* reset UMAC */ - ret = iwm_send_umac_reset(iwm, reset_flags, 1); - if (ret < 0) - return ret; - - ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC, - WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Wait for UMAC RESET timeout\n"); - return ret; - } - - return ret; -} - -int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id) -{ - struct iwm_udma_wifi_cmd udma_cmd; - struct iwm_umac_cmd umac_cmd; - struct iwm_tx_info *tx_info = skb_to_tx_info(skb); - - udma_cmd.eop = 1; /* always set eop for non-concatenated Tx */ - udma_cmd.credit_group = pool_id; - udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; - udma_cmd.lmac_offset = 0; - - umac_cmd.id = REPLY_TX; - umac_cmd.color = tx_info->color; - umac_cmd.resp = 0; - - return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, - skb->data, skb->len); -} - -static int iwm_target_read(struct iwm_priv *iwm, __le32 address, - u8 *response, u32 resp_size) -{ - struct iwm_udma_nonwifi_cmd target_cmd; - struct iwm_nonwifi_cmd *cmd; - u16 seq_num; - int ret = 0; - - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ; - target_cmd.addr = address; - target_cmd.op1_sz = cpu_to_le32(resp_size); - target_cmd.op2 = 0; - target_cmd.handle_by_hw = 0; - target_cmd.resp = 1; - target_cmd.eop = 1; - - ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't send READ command\n"); - return ret; - } - - /* When succeding, the send_target routine returns the seq number */ - seq_num = ret; - - ret = wait_event_interruptible_timeout(iwm->nonwifi_queue, - (cmd = iwm_get_pending_nonwifi_cmd(iwm, seq_num, - UMAC_HDI_OUT_OPCODE_READ)) != NULL, - 2 * HZ); - - if (!ret) { - IWM_ERR(iwm, "Didn't receive a target READ answer\n"); - return ret; - } - - memcpy(response, cmd->buf.hdr + sizeof(struct iwm_udma_in_hdr), - resp_size); - - kfree(cmd); - - return 0; -} - -int iwm_read_mac(struct iwm_priv *iwm, u8 *mac) -{ - int ret; - u8 mac_align[ALIGN(ETH_ALEN, 8)]; - - ret = iwm_target_read(iwm, cpu_to_le32(WICO_MAC_ADDRESS_ADDR), - mac_align, sizeof(mac_align)); - if (ret) - return ret; - - if (is_valid_ether_addr(mac_align)) - memcpy(mac, mac_align, ETH_ALEN); - else { - IWM_ERR(iwm, "Invalid EEPROM MAC\n"); - memcpy(mac, iwm->conf.mac_addr, ETH_ALEN); - get_random_bytes(&mac[3], 3); - } - - return 0; -} - -static int iwm_check_profile(struct iwm_priv *iwm) -{ - if (!iwm->umac_profile_active) - return -EAGAIN; - - if (iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 && - iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104 && - iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_TKIP && - iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_CCMP) { - IWM_ERR(iwm, "Wrong unicast cipher: 0x%x\n", - iwm->umac_profile->sec.ucast_cipher); - return -EAGAIN; - } - - if (iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_40 && - iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_WEP_104 && - iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_TKIP && - iwm->umac_profile->sec.mcast_cipher != UMAC_CIPHER_TYPE_CCMP) { - IWM_ERR(iwm, "Wrong multicast cipher: 0x%x\n", - iwm->umac_profile->sec.mcast_cipher); - return -EAGAIN; - } - - if ((iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_40 || - iwm->umac_profile->sec.ucast_cipher == UMAC_CIPHER_TYPE_WEP_104) && - (iwm->umac_profile->sec.ucast_cipher != - iwm->umac_profile->sec.mcast_cipher)) { - IWM_ERR(iwm, "Unicast and multicast ciphers differ for WEP\n"); - } - - return 0; -} - -int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx) -{ - struct iwm_umac_tx_key_id tx_key_id; - int ret; - - ret = iwm_check_profile(iwm); - if (ret < 0) - return ret; - - /* UMAC only allows to set default key for WEP and auth type is - * NOT 802.1X or RSNA. */ - if ((iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_40 && - iwm->umac_profile->sec.ucast_cipher != UMAC_CIPHER_TYPE_WEP_104) || - iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_8021X || - iwm->umac_profile->sec.auth_type == UMAC_AUTH_TYPE_RSNA_PSK) - return 0; - - tx_key_id.hdr.oid = UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID; - tx_key_id.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_tx_key_id) - - sizeof(struct iwm_umac_wifi_if)); - - tx_key_id.key_idx = key_idx; - - return iwm_send_wifi_if_cmd(iwm, &tx_key_id, sizeof(tx_key_id), 1); -} - -int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key) -{ - int ret = 0; - u8 cmd[64], *sta_addr, *key_data, key_len; - s8 key_idx; - u16 cmd_size = 0; - struct iwm_umac_key_hdr *key_hdr = &key->hdr; - struct iwm_umac_key_wep40 *wep40 = (struct iwm_umac_key_wep40 *)cmd; - struct iwm_umac_key_wep104 *wep104 = (struct iwm_umac_key_wep104 *)cmd; - struct iwm_umac_key_tkip *tkip = (struct iwm_umac_key_tkip *)cmd; - struct iwm_umac_key_ccmp *ccmp = (struct iwm_umac_key_ccmp *)cmd; - - if (!remove) { - ret = iwm_check_profile(iwm); - if (ret < 0) - return ret; - } - - sta_addr = key->hdr.mac; - key_data = key->key; - key_len = key->key_len; - key_idx = key->hdr.key_idx; - - if (!remove) { - u8 auth_type = iwm->umac_profile->sec.auth_type; - - IWM_DBG_WEXT(iwm, DBG, "key_idx:%d\n", key_idx); - IWM_DBG_WEXT(iwm, DBG, "key_len:%d\n", key_len); - IWM_DBG_WEXT(iwm, DBG, "MAC:%pM, idx:%d, multicast:%d\n", - key_hdr->mac, key_hdr->key_idx, key_hdr->multicast); - - IWM_DBG_WEXT(iwm, DBG, "profile: mcast:0x%x, ucast:0x%x\n", - iwm->umac_profile->sec.mcast_cipher, - iwm->umac_profile->sec.ucast_cipher); - IWM_DBG_WEXT(iwm, DBG, "profile: auth_type:0x%x, flags:0x%x\n", - iwm->umac_profile->sec.auth_type, - iwm->umac_profile->sec.flags); - - switch (key->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - wep40->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP40_KEY; - wep40->hdr.buf_size = - cpu_to_le16(sizeof(struct iwm_umac_key_wep40) - - sizeof(struct iwm_umac_wifi_if)); - - memcpy(&wep40->key_hdr, key_hdr, - sizeof(struct iwm_umac_key_hdr)); - memcpy(wep40->key, key_data, key_len); - wep40->static_key = - !!((auth_type != UMAC_AUTH_TYPE_8021X) && - (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); - - cmd_size = sizeof(struct iwm_umac_key_wep40); - break; - - case WLAN_CIPHER_SUITE_WEP104: - wep104->hdr.oid = UMAC_WIFI_IF_CMD_ADD_WEP104_KEY; - wep104->hdr.buf_size = - cpu_to_le16(sizeof(struct iwm_umac_key_wep104) - - sizeof(struct iwm_umac_wifi_if)); - - memcpy(&wep104->key_hdr, key_hdr, - sizeof(struct iwm_umac_key_hdr)); - memcpy(wep104->key, key_data, key_len); - wep104->static_key = - !!((auth_type != UMAC_AUTH_TYPE_8021X) && - (auth_type != UMAC_AUTH_TYPE_RSNA_PSK)); - - cmd_size = sizeof(struct iwm_umac_key_wep104); - break; - - case WLAN_CIPHER_SUITE_CCMP: - key_hdr->key_idx++; - ccmp->hdr.oid = UMAC_WIFI_IF_CMD_ADD_CCMP_KEY; - ccmp->hdr.buf_size = - cpu_to_le16(sizeof(struct iwm_umac_key_ccmp) - - sizeof(struct iwm_umac_wifi_if)); - - memcpy(&ccmp->key_hdr, key_hdr, - sizeof(struct iwm_umac_key_hdr)); - - memcpy(ccmp->key, key_data, key_len); - - if (key->seq_len) - memcpy(ccmp->iv_count, key->seq, key->seq_len); - - cmd_size = sizeof(struct iwm_umac_key_ccmp); - break; - - case WLAN_CIPHER_SUITE_TKIP: - key_hdr->key_idx++; - tkip->hdr.oid = UMAC_WIFI_IF_CMD_ADD_TKIP_KEY; - tkip->hdr.buf_size = - cpu_to_le16(sizeof(struct iwm_umac_key_tkip) - - sizeof(struct iwm_umac_wifi_if)); - - memcpy(&tkip->key_hdr, key_hdr, - sizeof(struct iwm_umac_key_hdr)); - - memcpy(tkip->tkip_key, key_data, IWM_TKIP_KEY_SIZE); - memcpy(tkip->mic_tx_key, key_data + IWM_TKIP_KEY_SIZE, - IWM_TKIP_MIC_SIZE); - memcpy(tkip->mic_rx_key, - key_data + IWM_TKIP_KEY_SIZE + IWM_TKIP_MIC_SIZE, - IWM_TKIP_MIC_SIZE); - - if (key->seq_len) - memcpy(ccmp->iv_count, key->seq, key->seq_len); - - cmd_size = sizeof(struct iwm_umac_key_tkip); - break; - - default: - return -ENOTSUPP; - } - - if ((key->cipher == WLAN_CIPHER_SUITE_TKIP) || - (key->cipher == WLAN_CIPHER_SUITE_CCMP)) - /* - * UGLY_UGLY_UGLY - * Copied HACK from the MWG driver. - * Without it, the key is set before the second - * EAPOL frame is sent, and the latter is thus - * encrypted. - */ - schedule_timeout_interruptible(usecs_to_jiffies(300)); - - ret = iwm_send_wifi_if_cmd(iwm, cmd, cmd_size, 1); - } else { - struct iwm_umac_key_remove key_remove; - - IWM_DBG_WEXT(iwm, ERR, "Removing key_idx:%d\n", key_idx); - - key_remove.hdr.oid = UMAC_WIFI_IF_CMD_REMOVE_KEY; - key_remove.hdr.buf_size = - cpu_to_le16(sizeof(struct iwm_umac_key_remove) - - sizeof(struct iwm_umac_wifi_if)); - memcpy(&key_remove.key_hdr, key_hdr, - sizeof(struct iwm_umac_key_hdr)); - - ret = iwm_send_wifi_if_cmd(iwm, &key_remove, - sizeof(struct iwm_umac_key_remove), - 1); - if (ret) - return ret; - - iwm->keys[key_idx].key_len = 0; - } - - return ret; -} - - -int iwm_send_mlme_profile(struct iwm_priv *iwm) -{ - int ret; - struct iwm_umac_profile profile; - - memcpy(&profile, iwm->umac_profile, sizeof(profile)); - - profile.hdr.oid = UMAC_WIFI_IF_CMD_SET_PROFILE; - profile.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_profile) - - sizeof(struct iwm_umac_wifi_if)); - - ret = iwm_send_wifi_if_cmd(iwm, &profile, sizeof(profile), 1); - if (ret) { - IWM_ERR(iwm, "Send profile command failed\n"); - return ret; - } - - set_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); - return 0; -} - -int iwm_invalidate_mlme_profile(struct iwm_priv *iwm) -{ - struct iwm_umac_invalidate_profile invalid; - int ret; - - invalid.hdr.oid = UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE; - invalid.hdr.buf_size = - cpu_to_le16(sizeof(struct iwm_umac_invalidate_profile) - - sizeof(struct iwm_umac_wifi_if)); - - invalid.reason = WLAN_REASON_UNSPECIFIED; - - ret = iwm_send_wifi_if_cmd(iwm, &invalid, sizeof(invalid), 1); - if (ret) - return ret; - - ret = wait_event_interruptible_timeout(iwm->mlme_queue, - (iwm->umac_profile_active == 0), 2 * HZ); - - return ret ? 0 : -EBUSY; -} - -int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags) -{ - struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; - struct iwm_umac_cmd umac_cmd; - struct iwm_umac_cmd_stats_req stats_req; - - stats_req.flags = cpu_to_le32(flags); - - umac_cmd.id = UMAC_CMD_OPCODE_STATISTIC_REQUEST; - umac_cmd.resp = 0; - - return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stats_req, - sizeof(struct iwm_umac_cmd_stats_req)); -} - -int iwm_send_umac_channel_list(struct iwm_priv *iwm) -{ - struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT; - struct iwm_umac_cmd umac_cmd; - struct iwm_umac_cmd_get_channel_list *ch_list; - int size = sizeof(struct iwm_umac_cmd_get_channel_list) + - sizeof(struct iwm_umac_channel_info) * 4; - int ret; - - ch_list = kzalloc(size, GFP_KERNEL); - if (!ch_list) { - IWM_ERR(iwm, "Couldn't allocate channel list cmd\n"); - return -ENOMEM; - } - - ch_list->ch[0].band = UMAC_BAND_2GHZ; - ch_list->ch[0].type = UMAC_CHANNEL_WIDTH_20MHZ; - ch_list->ch[0].flags = UMAC_CHANNEL_FLAG_VALID; - - ch_list->ch[1].band = UMAC_BAND_5GHZ; - ch_list->ch[1].type = UMAC_CHANNEL_WIDTH_20MHZ; - ch_list->ch[1].flags = UMAC_CHANNEL_FLAG_VALID; - - ch_list->ch[2].band = UMAC_BAND_2GHZ; - ch_list->ch[2].type = UMAC_CHANNEL_WIDTH_20MHZ; - ch_list->ch[2].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; - - ch_list->ch[3].band = UMAC_BAND_5GHZ; - ch_list->ch[3].type = UMAC_CHANNEL_WIDTH_20MHZ; - ch_list->ch[3].flags = UMAC_CHANNEL_FLAG_VALID | UMAC_CHANNEL_FLAG_IBSS; - - ch_list->count = cpu_to_le16(4); - - umac_cmd.id = UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST; - umac_cmd.resp = 1; - - ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, ch_list, size); - - kfree(ch_list); - - return ret; -} - -int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, - int ssid_num) -{ - struct iwm_umac_cmd_scan_request req; - int i, ret; - - memset(&req, 0, sizeof(struct iwm_umac_cmd_scan_request)); - - req.hdr.oid = UMAC_WIFI_IF_CMD_SCAN_REQUEST; - req.hdr.buf_size = cpu_to_le16(sizeof(struct iwm_umac_cmd_scan_request) - - sizeof(struct iwm_umac_wifi_if)); - req.type = UMAC_WIFI_IF_SCAN_TYPE_USER; - req.timeout = 2; - req.seq_num = iwm->scan_id; - req.ssid_num = min(ssid_num, UMAC_WIFI_IF_PROBE_OPTION_MAX); - - for (i = 0; i < req.ssid_num; i++) { - memcpy(req.ssids[i].ssid, ssids[i].ssid, ssids[i].ssid_len); - req.ssids[i].ssid_len = ssids[i].ssid_len; - } - - ret = iwm_send_wifi_if_cmd(iwm, &req, sizeof(req), 0); - if (ret) { - IWM_ERR(iwm, "Couldn't send scan request\n"); - return ret; - } - - iwm->scan_id = iwm->scan_id++ % IWM_SCAN_ID_MAX; - - return 0; -} - -int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len) -{ - struct cfg80211_ssid one_ssid; - - if (test_and_set_bit(IWM_STATUS_SCANNING, &iwm->status)) - return 0; - - one_ssid.ssid_len = min(ssid_len, IEEE80211_MAX_SSID_LEN); - memcpy(&one_ssid.ssid, ssid, one_ssid.ssid_len); - - return iwm_scan_ssids(iwm, &one_ssid, 1); -} - -int iwm_target_reset(struct iwm_priv *iwm) -{ - struct iwm_udma_nonwifi_cmd target_cmd; - - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_REBOOT; - target_cmd.addr = 0; - target_cmd.op1_sz = 0; - target_cmd.op2 = 0; - target_cmd.handle_by_hw = 0; - target_cmd.resp = 0; - target_cmd.eop = 1; - - return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); -} diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h deleted file mode 100644 index e24d5b633997..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/commands.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_COMMANDS_H__ -#define __IWM_COMMANDS_H__ - -#include - -#define IWM_BARKER_REBOOT_NOTIFICATION 0xF -#define IWM_ACK_BARKER_NOTIFICATION 0x10 - -/* UMAC commands */ -#define UMAC_RST_CTRL_FLG_LARC_CLK_EN 0x0001 -#define UMAC_RST_CTRL_FLG_LARC_RESET 0x0002 -#define UMAC_RST_CTRL_FLG_FUNC_RESET 0x0004 -#define UMAC_RST_CTRL_FLG_DEV_RESET 0x0008 -#define UMAC_RST_CTRL_FLG_WIFI_CORE_EN 0x0010 -#define UMAC_RST_CTRL_FLG_WIFI_LINK_EN 0x0040 -#define UMAC_RST_CTRL_FLG_WIFI_MLME_EN 0x0080 -#define UMAC_RST_CTRL_FLG_NVM_RELOAD 0x0100 - -struct iwm_umac_cmd_reset { - __le32 flags; -} __attribute__ ((packed)); - -#define UMAC_PARAM_TBL_ORD_FIX 0x0 -#define UMAC_PARAM_TBL_ORD_VAR 0x1 -#define UMAC_PARAM_TBL_CFG_FIX 0x2 -#define UMAC_PARAM_TBL_CFG_VAR 0x3 -#define UMAC_PARAM_TBL_BSS_TRK 0x4 -#define UMAC_PARAM_TBL_FA_CFG_FIX 0x5 -#define UMAC_PARAM_TBL_STA 0x6 -#define UMAC_PARAM_TBL_CHN 0x7 -#define UMAC_PARAM_TBL_STATISTICS 0x8 - -/* fast access table */ -enum { - CFG_FRAG_THRESHOLD = 0, - CFG_FRAME_RETRY_LIMIT, - CFG_OS_QUEUE_UTIL_TH, - CFG_RX_FILTER, - /* <-- LAST --> */ - FAST_ACCESS_CFG_TBL_FIX_LAST -}; - -/* fixed size table */ -enum { - CFG_POWER_INDEX = 0, - CFG_PM_LEGACY_RX_TIMEOUT, - CFG_PM_LEGACY_TX_TIMEOUT, - CFG_PM_CTRL_FLAGS, - CFG_PM_KEEP_ALIVE_IN_BEACONS, - CFG_BT_ON_THRESHOLD, - CFG_RTS_THRESHOLD, - CFG_CTS_TO_SELF, - CFG_COEX_MODE, - CFG_WIRELESS_MODE, - CFG_ASSOCIATION_TIMEOUT, - CFG_ROAM_TIMEOUT, - CFG_CAPABILITY_SUPPORTED_RATES, - CFG_SCAN_ALLOWED_UNASSOC_FLAGS, - CFG_SCAN_ALLOWED_MAIN_ASSOC_FLAGS, - CFG_SCAN_ALLOWED_PAN_ASSOC_FLAGS, - CFG_SCAN_INTERNAL_PERIODIC_ENABLED, - CFG_SCAN_IMM_INTERNAL_PERIODIC_SCAN_ON_INIT, - CFG_SCAN_DEFAULT_PERIODIC_FREQ_SEC, - CFG_SCAN_NUM_PASSIVE_CHAN_PER_PARTIAL_SCAN, - CFG_TLC_SUPPORTED_TX_HT_RATES, - CFG_TLC_SUPPORTED_TX_RATES, - CFG_TLC_VALID_ANTENNA, - CFG_TLC_SPATIAL_STREAM_SUPPORTED, - CFG_TLC_RETRY_PER_RATE, - CFG_TLC_RETRY_PER_HT_RATE, - CFG_TLC_FIXED_MCS, - CFG_TLC_CONTROL_FLAGS, - CFG_TLC_SR_MIN_FAIL, - CFG_TLC_SR_MIN_PASS, - CFG_TLC_HT_STAY_IN_COL_PASS_THRESH, - CFG_TLC_HT_STAY_IN_COL_FAIL_THRESH, - CFG_TLC_LEGACY_STAY_IN_COL_PASS_THRESH, - CFG_TLC_LEGACY_STAY_IN_COL_FAIL_THRESH, - CFG_TLC_HT_FLUSH_STATS_PACKETS, - CFG_TLC_LEGACY_FLUSH_STATS_PACKETS, - CFG_TLC_LEGACY_FLUSH_STATS_MS, - CFG_TLC_HT_FLUSH_STATS_MS, - CFG_TLC_STAY_IN_COL_TIME_OUT, - CFG_TLC_AGG_SHORT_LIM, - CFG_TLC_AGG_LONG_LIM, - CFG_TLC_HT_SR_NO_DECREASE, - CFG_TLC_LEGACY_SR_NO_DECREASE, - CFG_TLC_SR_FORCE_DECREASE, - CFG_TLC_SR_ALLOW_INCREASE, - CFG_TLC_AGG_SET_LONG, - CFG_TLC_AUTO_AGGREGATION, - CFG_TLC_AGG_THRESHOLD, - CFG_TLC_TID_LOAD_THRESHOLD, - CFG_TLC_BLOCK_ACK_TIMEOUT, - CFG_TLC_NO_BA_COUNTED_AS_ONE, - CFG_TLC_NUM_BA_STREAMS_ALLOWED, - CFG_TLC_NUM_BA_STREAMS_PRESENT, - CFG_TLC_RENEW_ADDBA_DELAY, - CFG_TLC_NUM_OF_MULTISEC_TO_COUN_LOAD, - CFG_TLC_IS_STABLE_IN_HT, - CFG_RLC_CHAIN_CTRL, - CFG_TRK_TABLE_OP_MODE, - CFG_TRK_TABLE_RSSI_THRESHOLD, - CFG_TX_PWR_TARGET, /* Used By xVT */ - CFG_TX_PWR_LIMIT_USR, - CFG_TX_PWR_LIMIT_BSS, /* 11d limit */ - CFG_TX_PWR_LIMIT_BSS_CONSTRAINT, /* 11h constraint */ - CFG_TX_PWR_MODE, - CFG_MLME_DBG_NOTIF_BLOCK, - CFG_BT_OFF_BECONS_INTERVALS, - CFG_BT_FRAG_DURATION, - - /* <-- LAST --> */ - CFG_TBL_FIX_LAST -}; - -/* variable size table */ -enum { - CFG_NET_ADDR = 0, - CFG_PROFILE, - /* <-- LAST --> */ - CFG_TBL_VAR_LAST -}; - -struct iwm_umac_cmd_set_param_fix { - __le16 tbl; - __le16 key; - __le32 value; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_set_param_var { - __le16 tbl; - __le16 key; - __le16 len; - __le16 reserved; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_get_param { - __le16 tbl; - __le16 key; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_get_param_resp { - __le16 tbl; - __le16 key; - __le16 len; - __le16 reserved; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_eeprom_proxy_hdr { - __le32 type; - __le32 offset; - __le32 len; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_eeprom_proxy { - struct iwm_umac_cmd_eeprom_proxy_hdr hdr; - u8 buf[0]; -} __attribute__ ((packed)); - -#define IWM_UMAC_CMD_EEPROM_TYPE_READ 0x1 -#define IWM_UMAC_CMD_EEPROM_TYPE_WRITE 0x2 - -#define UMAC_CHANNEL_FLAG_VALID BIT(0) -#define UMAC_CHANNEL_FLAG_IBSS BIT(1) -#define UMAC_CHANNEL_FLAG_ACTIVE BIT(3) -#define UMAC_CHANNEL_FLAG_RADAR BIT(4) -#define UMAC_CHANNEL_FLAG_DFS BIT(7) - -struct iwm_umac_channel_info { - u8 band; - u8 type; - u8 reserved; - u8 flags; - __le32 channels_mask; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_get_channel_list { - __le16 count; - __le16 reserved; - struct iwm_umac_channel_info ch[0]; -} __attribute__ ((packed)); - - -/* UMAC WiFi interface commands */ - -/* Coexistence mode */ -#define COEX_MODE_SA 0x1 -#define COEX_MODE_XOR 0x2 -#define COEX_MODE_CM 0x3 -#define COEX_MODE_MAX 0x4 - -/* Wireless mode */ -#define WIRELESS_MODE_11A 0x1 -#define WIRELESS_MODE_11G 0x2 -#define WIRELESS_MODE_11N 0x4 - -#define UMAC_PROFILE_EX_IE_REQUIRED 0x1 -#define UMAC_PROFILE_QOS_ALLOWED 0x2 - -/* Scanning */ -#define UMAC_WIFI_IF_PROBE_OPTION_MAX 10 - -#define UMAC_WIFI_IF_SCAN_TYPE_USER 0x0 -#define UMAC_WIFI_IF_SCAN_TYPE_UMAC_RESERVED 0x1 -#define UMAC_WIFI_IF_SCAN_TYPE_HOST_PERIODIC 0x2 -#define UMAC_WIFI_IF_SCAN_TYPE_MAX 0x3 - -struct iwm_umac_ssid { - u8 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 reserved[3]; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_scan_request { - struct iwm_umac_wifi_if hdr; - __le32 type; /* UMAC_WIFI_IF_SCAN_TYPE_* */ - u8 ssid_num; - u8 seq_num; - u8 timeout; /* In seconds */ - u8 reserved; - struct iwm_umac_ssid ssids[UMAC_WIFI_IF_PROBE_OPTION_MAX]; -} __attribute__ ((packed)); - -#define UMAC_CIPHER_TYPE_NONE 0xFF -#define UMAC_CIPHER_TYPE_USE_GROUPCAST 0x00 -#define UMAC_CIPHER_TYPE_WEP_40 0x01 -#define UMAC_CIPHER_TYPE_WEP_104 0x02 -#define UMAC_CIPHER_TYPE_TKIP 0x04 -#define UMAC_CIPHER_TYPE_CCMP 0x08 - -/* Supported authentication types - bitmap */ -#define UMAC_AUTH_TYPE_OPEN 0x00 -#define UMAC_AUTH_TYPE_LEGACY_PSK 0x01 -#define UMAC_AUTH_TYPE_8021X 0x02 -#define UMAC_AUTH_TYPE_RSNA_PSK 0x04 - -/* iwm_umac_security.flag is WPA supported -- bits[0:0] */ -#define UMAC_SEC_FLG_WPA_ON_POS 0 -#define UMAC_SEC_FLG_WPA_ON_SEED 1 -#define UMAC_SEC_FLG_WPA_ON_MSK (UMAC_SEC_FLG_WPA_ON_SEED << \ - UMAC_SEC_FLG_WPA_ON_POS) - -/* iwm_umac_security.flag is WPA2 supported -- bits [1:1] */ -#define UMAC_SEC_FLG_RSNA_ON_POS 1 -#define UMAC_SEC_FLG_RSNA_ON_SEED 1 -#define UMAC_SEC_FLG_RSNA_ON_MSK (UMAC_SEC_FLG_RSNA_ON_SEED << \ - UMAC_SEC_FLG_RSNA_ON_POS) - -/* iwm_umac_security.flag is WSC mode on -- bits [2:2] */ -#define UMAC_SEC_FLG_WSC_ON_POS 2 -#define UMAC_SEC_FLG_WSC_ON_SEED 1 - -/* Legacy profile can use only WEP40 and WEP104 for encryption and - * OPEN or PSK for authentication */ -#define UMAC_SEC_FLG_LEGACY_PROFILE 0 - -struct iwm_umac_security { - u8 auth_type; - u8 ucast_cipher; - u8 mcast_cipher; - u8 flags; -} __attribute__ ((packed)); - -struct iwm_umac_ibss { - u8 beacon_interval; /* in millisecond */ - u8 atim; /* in millisecond */ - s8 join_only; - u8 band; - u8 channel; - u8 reserved[3]; -} __attribute__ ((packed)); - -#define UMAC_MODE_BSS 0 -#define UMAC_MODE_IBSS 1 - -#define UMAC_BSSID_MAX 4 - -struct iwm_umac_profile { - struct iwm_umac_wifi_if hdr; - __le32 mode; - struct iwm_umac_ssid ssid; - u8 bssid[UMAC_BSSID_MAX][ETH_ALEN]; - struct iwm_umac_security sec; - struct iwm_umac_ibss ibss; - __le32 channel_2ghz; - __le32 channel_5ghz; - __le16 flags; - u8 wireless_mode; - u8 bss_num; -} __attribute__ ((packed)); - -struct iwm_umac_invalidate_profile { - struct iwm_umac_wifi_if hdr; - u8 reason; - u8 reserved[3]; -} __attribute__ ((packed)); - -/* Encryption key commands */ -struct iwm_umac_key_wep40 { - struct iwm_umac_wifi_if hdr; - struct iwm_umac_key_hdr key_hdr; - u8 key[WLAN_KEY_LEN_WEP40]; - u8 static_key; - u8 reserved[2]; -} __attribute__ ((packed)); - -struct iwm_umac_key_wep104 { - struct iwm_umac_wifi_if hdr; - struct iwm_umac_key_hdr key_hdr; - u8 key[WLAN_KEY_LEN_WEP104]; - u8 static_key; - u8 reserved[2]; -} __attribute__ ((packed)); - -#define IWM_TKIP_KEY_SIZE 16 -#define IWM_TKIP_MIC_SIZE 8 -struct iwm_umac_key_tkip { - struct iwm_umac_wifi_if hdr; - struct iwm_umac_key_hdr key_hdr; - u8 iv_count[6]; - u8 reserved[2]; - u8 tkip_key[IWM_TKIP_KEY_SIZE]; - u8 mic_rx_key[IWM_TKIP_MIC_SIZE]; - u8 mic_tx_key[IWM_TKIP_MIC_SIZE]; -} __attribute__ ((packed)); - -struct iwm_umac_key_ccmp { - struct iwm_umac_wifi_if hdr; - struct iwm_umac_key_hdr key_hdr; - u8 iv_count[6]; - u8 reserved[2]; - u8 key[WLAN_KEY_LEN_CCMP]; -} __attribute__ ((packed)); - -struct iwm_umac_key_remove { - struct iwm_umac_wifi_if hdr; - struct iwm_umac_key_hdr key_hdr; -} __attribute__ ((packed)); - -struct iwm_umac_tx_key_id { - struct iwm_umac_wifi_if hdr; - u8 key_idx; - u8 reserved[3]; -} __attribute__ ((packed)); - -struct iwm_umac_cmd_stats_req { - __le32 flags; -} __attribute__ ((packed)); - -/* LMAC commands */ -int iwm_read_mac(struct iwm_priv *iwm, u8 *mac); -int iwm_send_prio_table(struct iwm_priv *iwm); -int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); -int iwm_send_periodic_calib_cfg(struct iwm_priv *iwm, u8 calib_requested); -int iwm_send_calib_results(struct iwm_priv *iwm); -int iwm_store_rxiq_calib_result(struct iwm_priv *iwm); - -/* UMAC commands */ -int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size, - bool resp); -int iwm_send_umac_reset(struct iwm_priv *iwm, __le32 reset_flags, bool resp); -int iwm_umac_set_config_fix(struct iwm_priv *iwm, u16 tbl, u16 key, u32 value); -int iwm_umac_set_config_var(struct iwm_priv *iwm, u16 key, - void *payload, u16 payload_size); -int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags); -int iwm_send_mlme_profile(struct iwm_priv *iwm); -int iwm_invalidate_mlme_profile(struct iwm_priv *iwm); -int iwm_send_packet(struct iwm_priv *iwm, struct sk_buff *skb, int pool_id); -int iwm_set_tx_key(struct iwm_priv *iwm, u8 key_idx); -int iwm_set_key(struct iwm_priv *iwm, bool remove, struct iwm_key *key); -int iwm_send_umac_stats_req(struct iwm_priv *iwm, u32 flags); -int iwm_send_umac_channel_list(struct iwm_priv *iwm); -int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, - int ssid_num); -int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len); - -/* UDMA commands */ -int iwm_target_reset(struct iwm_priv *iwm); -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/debug.h b/drivers/net/wireless/iwmc3200wifi/debug.h deleted file mode 100644 index e35c9b693d1f..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/debug.h +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#ifndef __IWM_DEBUG_H__ -#define __IWM_DEBUG_H__ - -#define IWM_ERR(p, f, a...) dev_err(iwm_to_dev(p), f, ## a) -#define IWM_WARN(p, f, a...) dev_warn(iwm_to_dev(p), f, ## a) -#define IWM_INFO(p, f, a...) dev_info(iwm_to_dev(p), f, ## a) -#define IWM_CRIT(p, f, a...) dev_crit(iwm_to_dev(p), f, ## a) - -#ifdef CONFIG_IWM_DEBUG - -#define IWM_DEBUG_MODULE(i, level, module, f, a...) \ -do { \ - if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\ - dev_printk(KERN_INFO, (iwm_to_dev(i)), \ - "%s " f, __func__ , ## a); \ -} while (0) - -#define IWM_HEXDUMP(i, level, module, pref, buf, len) \ -do { \ - if (unlikely(i->dbg.dbg_module[IWM_DM_##module] >= (IWM_DL_##level)))\ - print_hex_dump(KERN_INFO, pref, DUMP_PREFIX_OFFSET, \ - 16, 1, buf, len, 1); \ -} while (0) - -#else - -#define IWM_DEBUG_MODULE(i, level, module, f, a...) -#define IWM_HEXDUMP(i, level, module, pref, buf, len) - -#endif /* CONFIG_IWM_DEBUG */ - -/* Debug modules */ -enum iwm_debug_module_id { - IWM_DM_BOOT = 0, - IWM_DM_FW, - IWM_DM_SDIO, - IWM_DM_NTF, - IWM_DM_RX, - IWM_DM_TX, - IWM_DM_MLME, - IWM_DM_CMD, - IWM_DM_WEXT, - __IWM_DM_NR, -}; -#define IWM_DM_DEFAULT 0 - -#define IWM_DBG_BOOT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, BOOT, f, ## a) -#define IWM_DBG_FW(i, l, f, a...) IWM_DEBUG_MODULE(i, l, FW, f, ## a) -#define IWM_DBG_SDIO(i, l, f, a...) IWM_DEBUG_MODULE(i, l, SDIO, f, ## a) -#define IWM_DBG_NTF(i, l, f, a...) IWM_DEBUG_MODULE(i, l, NTF, f, ## a) -#define IWM_DBG_RX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, RX, f, ## a) -#define IWM_DBG_TX(i, l, f, a...) IWM_DEBUG_MODULE(i, l, TX, f, ## a) -#define IWM_DBG_MLME(i, l, f, a...) IWM_DEBUG_MODULE(i, l, MLME, f, ## a) -#define IWM_DBG_CMD(i, l, f, a...) IWM_DEBUG_MODULE(i, l, CMD, f, ## a) -#define IWM_DBG_WEXT(i, l, f, a...) IWM_DEBUG_MODULE(i, l, WEXT, f, ## a) - -/* Debug levels */ -enum iwm_debug_level { - IWM_DL_NONE = 0, - IWM_DL_ERR, - IWM_DL_WARN, - IWM_DL_INFO, - IWM_DL_DBG, -}; -#define IWM_DL_DEFAULT IWM_DL_ERR - -struct iwm_debugfs { - struct iwm_priv *iwm; - struct dentry *rootdir; - struct dentry *devdir; - struct dentry *dbgdir; - struct dentry *txdir; - struct dentry *rxdir; - struct dentry *busdir; - - u32 dbg_level; - struct dentry *dbg_level_dentry; - - unsigned long dbg_modules; - struct dentry *dbg_modules_dentry; - - u8 dbg_module[__IWM_DM_NR]; - struct dentry *dbg_module_dentries[__IWM_DM_NR]; - - struct dentry *txq_dentry; - struct dentry *tx_credit_dentry; - struct dentry *rx_ticket_dentry; - - struct dentry *fw_err_dentry; -}; - -#ifdef CONFIG_IWM_DEBUG -int iwm_debugfs_init(struct iwm_priv *iwm); -void iwm_debugfs_exit(struct iwm_priv *iwm); -#else -static inline int iwm_debugfs_init(struct iwm_priv *iwm) -{ - return 0; -} -static inline void iwm_debugfs_exit(struct iwm_priv *iwm) {} -#endif - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c deleted file mode 100644 index 1465379f900a..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/debugfs.c +++ /dev/null @@ -1,550 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -#include -#include -#include - -#include "iwm.h" -#include "bus.h" -#include "rx.h" -#include "debug.h" - -static struct { - u8 id; - char *name; -} iwm_debug_module[__IWM_DM_NR] = { - {IWM_DM_BOOT, "boot"}, - {IWM_DM_FW, "fw"}, - {IWM_DM_SDIO, "sdio"}, - {IWM_DM_NTF, "ntf"}, - {IWM_DM_RX, "rx"}, - {IWM_DM_TX, "tx"}, - {IWM_DM_MLME, "mlme"}, - {IWM_DM_CMD, "cmd"}, - {IWM_DM_WEXT, "wext"}, -}; - -#define add_dbg_module(dbg, name, id, initlevel) \ -do { \ - struct dentry *d; \ - dbg.dbg_module[id] = (initlevel); \ - d = debugfs_create_x8(name, 0600, dbg.dbgdir, \ - &(dbg.dbg_module[id])); \ - if (!IS_ERR(d)) \ - dbg.dbg_module_dentries[id] = d; \ -} while (0) - -static int iwm_debugfs_u32_read(void *data, u64 *val) -{ - struct iwm_priv *iwm = data; - - *val = iwm->dbg.dbg_level; - return 0; -} - -static int iwm_debugfs_dbg_level_write(void *data, u64 val) -{ - struct iwm_priv *iwm = data; - int i; - - iwm->dbg.dbg_level = val; - - for (i = 0; i < __IWM_DM_NR; i++) - iwm->dbg.dbg_module[i] = val; - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_level, - iwm_debugfs_u32_read, iwm_debugfs_dbg_level_write, - "%llu\n"); - -static int iwm_debugfs_dbg_modules_write(void *data, u64 val) -{ - struct iwm_priv *iwm = data; - int i, bit; - - iwm->dbg.dbg_modules = val; - - for (i = 0; i < __IWM_DM_NR; i++) - iwm->dbg.dbg_module[i] = 0; - - for_each_bit(bit, &iwm->dbg.dbg_modules, __IWM_DM_NR) - iwm->dbg.dbg_module[bit] = iwm->dbg.dbg_level; - - return 0; -} -DEFINE_SIMPLE_ATTRIBUTE(fops_iwm_dbg_modules, - iwm_debugfs_u32_read, iwm_debugfs_dbg_modules_write, - "%llu\n"); - -static int iwm_generic_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - - -static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct iwm_priv *iwm = filp->private_data; - char *buf; - int i, buf_len = 4096; - size_t len = 0; - ssize_t ret; - - if (*ppos != 0) - return 0; - if (count < sizeof(buf)) - return -ENOSPC; - - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - for (i = 0; i < IWM_TX_QUEUES; i++) { - struct iwm_tx_queue *txq = &iwm->txq[i]; - struct sk_buff *skb; - int j; - unsigned long flags; - - spin_lock_irqsave(&txq->queue.lock, flags); - - skb = (struct sk_buff *)&txq->queue; - - len += snprintf(buf + len, buf_len - len, "TXQ #%d\n", i); - len += snprintf(buf + len, buf_len - len, "\tStopped: %d\n", - __netif_subqueue_stopped(iwm_to_ndev(iwm), - txq->id)); - len += snprintf(buf + len, buf_len - len, "\tConcat count:%d\n", - txq->concat_count); - len += snprintf(buf + len, buf_len - len, "\tQueue len: %d\n", - skb_queue_len(&txq->queue)); - for (j = 0; j < skb_queue_len(&txq->queue); j++) { - struct iwm_tx_info *tx_info; - - skb = skb->next; - tx_info = skb_to_tx_info(skb); - - len += snprintf(buf + len, buf_len - len, - "\tSKB #%d\n", j); - len += snprintf(buf + len, buf_len - len, - "\t\tsta: %d\n", tx_info->sta); - len += snprintf(buf + len, buf_len - len, - "\t\tcolor: %d\n", tx_info->color); - len += snprintf(buf + len, buf_len - len, - "\t\ttid: %d\n", tx_info->tid); - } - - spin_unlock_irqrestore(&txq->queue.lock, flags); - } - - ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); - kfree(buf); - - return ret; -} - -static ssize_t iwm_debugfs_tx_credit_read(struct file *filp, - char __user *buffer, - size_t count, loff_t *ppos) -{ - struct iwm_priv *iwm = filp->private_data; - struct iwm_tx_credit *credit = &iwm->tx_credit; - char *buf; - int i, buf_len = 4096; - size_t len = 0; - ssize_t ret; - - if (*ppos != 0) - return 0; - if (count < sizeof(buf)) - return -ENOSPC; - - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - len += snprintf(buf + len, buf_len - len, - "NR pools: %d\n", credit->pool_nr); - len += snprintf(buf + len, buf_len - len, - "pools map: 0x%lx\n", credit->full_pools_map); - - len += snprintf(buf + len, buf_len - len, "\n### POOLS ###\n"); - for (i = 0; i < IWM_MACS_OUT_GROUPS; i++) { - len += snprintf(buf + len, buf_len - len, - "pools entry #%d\n", i); - len += snprintf(buf + len, buf_len - len, - "\tid: %d\n", - credit->pools[i].id); - len += snprintf(buf + len, buf_len - len, - "\tsid: %d\n", - credit->pools[i].sid); - len += snprintf(buf + len, buf_len - len, - "\tmin_pages: %d\n", - credit->pools[i].min_pages); - len += snprintf(buf + len, buf_len - len, - "\tmax_pages: %d\n", - credit->pools[i].max_pages); - len += snprintf(buf + len, buf_len - len, - "\talloc_pages: %d\n", - credit->pools[i].alloc_pages); - len += snprintf(buf + len, buf_len - len, - "\tfreed_pages: %d\n", - credit->pools[i].total_freed_pages); - } - - len += snprintf(buf + len, buf_len - len, "\n### SPOOLS ###\n"); - for (i = 0; i < IWM_MACS_OUT_SGROUPS; i++) { - len += snprintf(buf + len, buf_len - len, - "spools entry #%d\n", i); - len += snprintf(buf + len, buf_len - len, - "\tid: %d\n", - credit->spools[i].id); - len += snprintf(buf + len, buf_len - len, - "\tmax_pages: %d\n", - credit->spools[i].max_pages); - len += snprintf(buf + len, buf_len - len, - "\talloc_pages: %d\n", - credit->spools[i].alloc_pages); - - } - - ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); - kfree(buf); - - return ret; -} - -static ssize_t iwm_debugfs_rx_ticket_read(struct file *filp, - char __user *buffer, - size_t count, loff_t *ppos) -{ - struct iwm_priv *iwm = filp->private_data; - struct iwm_rx_ticket_node *ticket, *next; - char *buf; - int buf_len = 4096, i; - size_t len = 0; - ssize_t ret; - - if (*ppos != 0) - return 0; - if (count < sizeof(buf)) - return -ENOSPC; - - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { - len += snprintf(buf + len, buf_len - len, "Ticket #%d\n", - ticket->ticket->id); - len += snprintf(buf + len, buf_len - len, "\taction: 0x%x\n", - ticket->ticket->action); - len += snprintf(buf + len, buf_len - len, "\tflags: 0x%x\n", - ticket->ticket->flags); - } - - for (i = 0; i < IWM_RX_ID_HASH; i++) { - struct iwm_rx_packet *packet, *nxt; - struct list_head *pkt_list = &iwm->rx_packets[i]; - if (!list_empty(pkt_list)) { - len += snprintf(buf + len, buf_len - len, - "Packet hash #%d\n", i); - list_for_each_entry_safe(packet, nxt, pkt_list, node) { - len += snprintf(buf + len, buf_len - len, - "\tPacket id: %d\n", - packet->id); - len += snprintf(buf + len, buf_len - len, - "\tPacket length: %lu\n", - packet->pkt_size); - } - } - } - - ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); - kfree(buf); - - return ret; -} - -static ssize_t iwm_debugfs_fw_err_read(struct file *filp, - char __user *buffer, - size_t count, loff_t *ppos) -{ - - struct iwm_priv *iwm = filp->private_data; - char buf[512]; - int buf_len = 512; - size_t len = 0; - - if (*ppos != 0) - return 0; - if (count < sizeof(buf)) - return -ENOSPC; - - if (!iwm->last_fw_err) - return -ENOMEM; - - if (iwm->last_fw_err->line_num == 0) - goto out; - - len += snprintf(buf + len, buf_len - len, "%cMAC FW ERROR:\n", - (le32_to_cpu(iwm->last_fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) - ? 'L' : 'U'); - len += snprintf(buf + len, buf_len - len, - "\tCategory: %d\n", - le32_to_cpu(iwm->last_fw_err->category)); - - len += snprintf(buf + len, buf_len - len, - "\tStatus: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->status)); - - len += snprintf(buf + len, buf_len - len, - "\tPC: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->pc)); - - len += snprintf(buf + len, buf_len - len, - "\tblink1: %d\n", - le32_to_cpu(iwm->last_fw_err->blink1)); - - len += snprintf(buf + len, buf_len - len, - "\tblink2: %d\n", - le32_to_cpu(iwm->last_fw_err->blink2)); - - len += snprintf(buf + len, buf_len - len, - "\tilink1: %d\n", - le32_to_cpu(iwm->last_fw_err->ilink1)); - - len += snprintf(buf + len, buf_len - len, - "\tilink2: %d\n", - le32_to_cpu(iwm->last_fw_err->ilink2)); - - len += snprintf(buf + len, buf_len - len, - "\tData1: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->data1)); - - len += snprintf(buf + len, buf_len - len, - "\tData2: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->data2)); - - len += snprintf(buf + len, buf_len - len, - "\tLine number: %d\n", - le32_to_cpu(iwm->last_fw_err->line_num)); - - len += snprintf(buf + len, buf_len - len, - "\tUMAC status: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->umac_status)); - - len += snprintf(buf + len, buf_len - len, - "\tLMAC status: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->lmac_status)); - - len += snprintf(buf + len, buf_len - len, - "\tSDIO status: 0x%x\n", - le32_to_cpu(iwm->last_fw_err->sdio_status)); - -out: - - return simple_read_from_buffer(buffer, len, ppos, buf, buf_len); -} - -static const struct file_operations iwm_debugfs_txq_fops = { - .owner = THIS_MODULE, - .open = iwm_generic_open, - .read = iwm_debugfs_txq_read, -}; - -static const struct file_operations iwm_debugfs_tx_credit_fops = { - .owner = THIS_MODULE, - .open = iwm_generic_open, - .read = iwm_debugfs_tx_credit_read, -}; - -static const struct file_operations iwm_debugfs_rx_ticket_fops = { - .owner = THIS_MODULE, - .open = iwm_generic_open, - .read = iwm_debugfs_rx_ticket_read, -}; - -static const struct file_operations iwm_debugfs_fw_err_fops = { - .owner = THIS_MODULE, - .open = iwm_generic_open, - .read = iwm_debugfs_fw_err_read, -}; - -int iwm_debugfs_init(struct iwm_priv *iwm) -{ - int i, result; - char devdir[16]; - - iwm->dbg.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - result = PTR_ERR(iwm->dbg.rootdir); - if (!result || IS_ERR(iwm->dbg.rootdir)) { - if (result == -ENODEV) { - IWM_ERR(iwm, "DebugFS (CONFIG_DEBUG_FS) not " - "enabled in kernel config\n"); - result = 0; /* No debugfs support */ - } - IWM_ERR(iwm, "Couldn't create rootdir: %d\n", result); - goto error; - } - - snprintf(devdir, sizeof(devdir), "%s", wiphy_name(iwm_to_wiphy(iwm))); - - iwm->dbg.devdir = debugfs_create_dir(devdir, iwm->dbg.rootdir); - result = PTR_ERR(iwm->dbg.devdir); - if (IS_ERR(iwm->dbg.devdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create devdir: %d\n", result); - goto error; - } - - iwm->dbg.dbgdir = debugfs_create_dir("debug", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.dbgdir); - if (IS_ERR(iwm->dbg.dbgdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create dbgdir: %d\n", result); - goto error; - } - - iwm->dbg.rxdir = debugfs_create_dir("rx", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.rxdir); - if (IS_ERR(iwm->dbg.rxdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create rx dir: %d\n", result); - goto error; - } - - iwm->dbg.txdir = debugfs_create_dir("tx", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.txdir); - if (IS_ERR(iwm->dbg.txdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create tx dir: %d\n", result); - goto error; - } - - iwm->dbg.busdir = debugfs_create_dir("bus", iwm->dbg.devdir); - result = PTR_ERR(iwm->dbg.busdir); - if (IS_ERR(iwm->dbg.busdir) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create bus dir: %d\n", result); - goto error; - } - - if (iwm->bus_ops->debugfs_init) { - result = iwm->bus_ops->debugfs_init(iwm, iwm->dbg.busdir); - if (result < 0) { - IWM_ERR(iwm, "Couldn't create bus entry: %d\n", result); - goto error; - } - } - - - iwm->dbg.dbg_level = IWM_DL_NONE; - iwm->dbg.dbg_level_dentry = - debugfs_create_file("level", 0200, iwm->dbg.dbgdir, iwm, - &fops_iwm_dbg_level); - result = PTR_ERR(iwm->dbg.dbg_level_dentry); - if (IS_ERR(iwm->dbg.dbg_level_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create dbg_level: %d\n", result); - goto error; - } - - - iwm->dbg.dbg_modules = IWM_DM_DEFAULT; - iwm->dbg.dbg_modules_dentry = - debugfs_create_file("modules", 0200, iwm->dbg.dbgdir, iwm, - &fops_iwm_dbg_modules); - result = PTR_ERR(iwm->dbg.dbg_modules_dentry); - if (IS_ERR(iwm->dbg.dbg_modules_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create dbg_modules: %d\n", result); - goto error; - } - - for (i = 0; i < __IWM_DM_NR; i++) - add_dbg_module(iwm->dbg, iwm_debug_module[i].name, - iwm_debug_module[i].id, IWM_DL_DEFAULT); - - iwm->dbg.txq_dentry = debugfs_create_file("queues", 0200, - iwm->dbg.txdir, iwm, - &iwm_debugfs_txq_fops); - result = PTR_ERR(iwm->dbg.txq_dentry); - if (IS_ERR(iwm->dbg.txq_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create tx queue: %d\n", result); - goto error; - } - - iwm->dbg.tx_credit_dentry = debugfs_create_file("credits", 0200, - iwm->dbg.txdir, iwm, - &iwm_debugfs_tx_credit_fops); - result = PTR_ERR(iwm->dbg.tx_credit_dentry); - if (IS_ERR(iwm->dbg.tx_credit_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create tx credit: %d\n", result); - goto error; - } - - iwm->dbg.rx_ticket_dentry = debugfs_create_file("tickets", 0200, - iwm->dbg.rxdir, iwm, - &iwm_debugfs_rx_ticket_fops); - result = PTR_ERR(iwm->dbg.rx_ticket_dentry); - if (IS_ERR(iwm->dbg.rx_ticket_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create rx ticket: %d\n", result); - goto error; - } - - iwm->dbg.fw_err_dentry = debugfs_create_file("last_fw_err", 0200, - iwm->dbg.dbgdir, iwm, - &iwm_debugfs_fw_err_fops); - result = PTR_ERR(iwm->dbg.fw_err_dentry); - if (IS_ERR(iwm->dbg.fw_err_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create last FW err: %d\n", result); - goto error; - } - - - return 0; - - error: - return result; -} - -void iwm_debugfs_exit(struct iwm_priv *iwm) -{ - int i; - - for (i = 0; i < __IWM_DM_NR; i++) - debugfs_remove(iwm->dbg.dbg_module_dentries[i]); - - debugfs_remove(iwm->dbg.dbg_modules_dentry); - debugfs_remove(iwm->dbg.dbg_level_dentry); - debugfs_remove(iwm->dbg.txq_dentry); - debugfs_remove(iwm->dbg.tx_credit_dentry); - debugfs_remove(iwm->dbg.rx_ticket_dentry); - debugfs_remove(iwm->dbg.fw_err_dentry); - if (iwm->bus_ops->debugfs_exit) - iwm->bus_ops->debugfs_exit(iwm); - - debugfs_remove(iwm->dbg.busdir); - debugfs_remove(iwm->dbg.dbgdir); - debugfs_remove(iwm->dbg.txdir); - debugfs_remove(iwm->dbg.rxdir); - debugfs_remove(iwm->dbg.devdir); - debugfs_remove(iwm->dbg.rootdir); -} diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c deleted file mode 100644 index 365910fbe01e..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/eeprom.c +++ /dev/null @@ -1,183 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#include - -#include "iwm.h" -#include "umac.h" -#include "commands.h" -#include "eeprom.h" - -static struct iwm_eeprom_entry eeprom_map[] = { - [IWM_EEPROM_SIG] = - {"Signature", IWM_EEPROM_SIG_OFF, IWM_EEPROM_SIG_LEN}, - - [IWM_EEPROM_VERSION] = - {"Version", IWM_EEPROM_VERSION_OFF, IWM_EEPROM_VERSION_LEN}, - - [IWM_EEPROM_OEM_HW_VERSION] = - {"OEM HW version", IWM_EEPROM_OEM_HW_VERSION_OFF, - IWM_EEPROM_OEM_HW_VERSION_LEN}, - - [IWM_EEPROM_MAC_VERSION] = - {"MAC version", IWM_EEPROM_MAC_VERSION_OFF, IWM_EEPROM_MAC_VERSION_LEN}, - - [IWM_EEPROM_CARD_ID] = - {"Card ID", IWM_EEPROM_CARD_ID_OFF, IWM_EEPROM_CARD_ID_LEN}, - - [IWM_EEPROM_RADIO_CONF] = - {"Radio config", IWM_EEPROM_RADIO_CONF_OFF, IWM_EEPROM_RADIO_CONF_LEN}, - - [IWM_EEPROM_SKU_CAP] = - {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN}, - - [IWM_EEPROM_CALIB_RXIQ_OFFSET] = - {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN}, - - [IWM_EEPROM_CALIB_RXIQ] = - {"Calib RX IQ", 0, IWM_EEPROM_CALIB_RXIQ_LEN}, -}; - - -static int iwm_eeprom_read(struct iwm_priv *iwm, u8 eeprom_id) -{ - int ret; - u32 entry_size, chunk_size, data_offset = 0, addr_offset = 0; - u32 addr; - struct iwm_udma_wifi_cmd udma_cmd; - struct iwm_umac_cmd umac_cmd; - struct iwm_umac_cmd_eeprom_proxy eeprom_cmd; - - if (eeprom_id > (IWM_EEPROM_LAST - 1)) - return -EINVAL; - - entry_size = eeprom_map[eeprom_id].length; - - if (eeprom_id >= IWM_EEPROM_INDIRECT_DATA) { - /* indirect data */ - u32 off_id = eeprom_id - IWM_EEPROM_INDIRECT_DATA + - IWM_EEPROM_INDIRECT_OFFSET; - - eeprom_map[eeprom_id].offset = - *(u16 *)(iwm->eeprom + eeprom_map[off_id].offset) << 1; - } - - addr = eeprom_map[eeprom_id].offset; - - udma_cmd.eop = 1; - udma_cmd.credit_group = 0x4; - udma_cmd.ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD; - udma_cmd.lmac_offset = 0; - - umac_cmd.id = UMAC_CMD_OPCODE_EEPROM_PROXY; - umac_cmd.resp = 1; - - while (entry_size > 0) { - chunk_size = min_t(u32, entry_size, IWM_MAX_EEPROM_DATA_LEN); - - eeprom_cmd.hdr.type = - cpu_to_le32(IWM_UMAC_CMD_EEPROM_TYPE_READ); - eeprom_cmd.hdr.offset = cpu_to_le32(addr + addr_offset); - eeprom_cmd.hdr.len = cpu_to_le32(chunk_size); - - ret = iwm_hal_send_umac_cmd(iwm, &udma_cmd, - &umac_cmd, &eeprom_cmd, - sizeof(struct iwm_umac_cmd_eeprom_proxy)); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't read eeprom\n"); - return ret; - } - - ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_EEPROM_PROXY, - IWM_SRC_UMAC, 2*HZ); - if (ret < 0) { - IWM_ERR(iwm, "Did not get any eeprom answer\n"); - return ret; - } - - data_offset += chunk_size; - addr_offset += chunk_size; - entry_size -= chunk_size; - } - - return 0; -} - -u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id) -{ - if (!iwm->eeprom) - return ERR_PTR(-ENODEV); - - return iwm->eeprom + eeprom_map[eeprom_id].offset; -} - -int iwm_eeprom_init(struct iwm_priv *iwm) -{ - int i, ret = 0; - char name[32]; - - iwm->eeprom = kzalloc(IWM_EEPROM_LEN, GFP_KERNEL); - if (!iwm->eeprom) - return -ENOMEM; - - for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) { - ret = iwm_eeprom_read(iwm, i); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't read eeprom entry #%d: %s\n", - i, eeprom_map[i].name); - break; - } - } - - IWM_DBG_BOOT(iwm, DBG, "EEPROM dump:\n"); - for (i = IWM_EEPROM_FIRST; i < IWM_EEPROM_LAST; i++) { - memset(name, 0, 32); - sprintf(name, "%s: ", eeprom_map[i].name); - - IWM_HEXDUMP(iwm, DBG, BOOT, name, - iwm->eeprom + eeprom_map[i].offset, - eeprom_map[i].length); - } - - return ret; -} - -void iwm_eeprom_exit(struct iwm_priv *iwm) -{ - kfree(iwm->eeprom); -} diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.h b/drivers/net/wireless/iwmc3200wifi/eeprom.h deleted file mode 100644 index cdb31a6a1f5f..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/eeprom.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_EEPROM_H__ -#define __IWM_EEPROM_H__ - -enum { - IWM_EEPROM_SIG = 0, - IWM_EEPROM_FIRST = IWM_EEPROM_SIG, - IWM_EEPROM_VERSION, - IWM_EEPROM_OEM_HW_VERSION, - IWM_EEPROM_MAC_VERSION, - IWM_EEPROM_CARD_ID, - IWM_EEPROM_RADIO_CONF, - IWM_EEPROM_SKU_CAP, - - IWM_EEPROM_INDIRECT_OFFSET, - IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET, - - IWM_EEPROM_INDIRECT_DATA, - IWM_EEPROM_CALIB_RXIQ = IWM_EEPROM_INDIRECT_DATA, - - IWM_EEPROM_LAST, -}; - -#define IWM_EEPROM_SIG_OFF 0x00 -#define IWM_EEPROM_VERSION_OFF (0x54 << 1) -#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1) -#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1) -#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1) -#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1) -#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1) -#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1) - -#define IWM_EEPROM_SIG_LEN 4 -#define IWM_EEPROM_VERSION_LEN 2 -#define IWM_EEPROM_OEM_HW_VERSION_LEN 2 -#define IWM_EEPROM_MAC_VERSION_LEN 1 -#define IWM_EEPROM_CARD_ID_LEN 2 -#define IWM_EEPROM_RADIO_CONF_LEN 2 -#define IWM_EEPROM_SKU_CAP_LEN 2 -#define IWM_EEPROM_INDIRECT_LEN 2 - -#define IWM_MAX_EEPROM_DATA_LEN 240 -#define IWM_EEPROM_LEN 0x800 - -#define IWM_EEPROM_MIN_ALLOWED_VERSION 0x0610 -#define IWM_EEPROM_MAX_ALLOWED_VERSION 0x0700 -#define IWM_EEPROM_CURRENT_VERSION 0x0612 - -#define IWM_EEPROM_SKU_CAP_BAND_24GHZ (1 << 4) -#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) -#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6) - -enum { - IWM_EEPROM_CALIB_CAL_HDR, - IWM_EEPROM_CALIB_TX_POWER, - IWM_EEPROM_CALIB_XTAL, - IWM_EEPROM_CALIB_TEMPERATURE, - IWM_EEPROM_CALIB_RX_BB_FILTER, - IWM_EEPROM_CALIB_RX_IQ, - IWM_EEPROM_CALIB_MAX, -}; - -#define IWM_EEPROM_CALIB_RXIQ_OFF (IWM_EEPROM_CALIB_CONFIG_OFF + \ - (IWM_EEPROM_CALIB_RX_IQ << 1)) -#define IWM_EEPROM_CALIB_RXIQ_LEN sizeof(struct iwm_lmac_calib_rxiq) - -struct iwm_eeprom_entry { - char *name; - u32 offset; - u32 length; -}; - -int iwm_eeprom_init(struct iwm_priv *iwm); -void iwm_eeprom_exit(struct iwm_priv *iwm); -u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id); - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/fw.c b/drivers/net/wireless/iwmc3200wifi/fw.c deleted file mode 100644 index 6b0bcad758ca..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/fw.c +++ /dev/null @@ -1,407 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#include -#include - -#include "iwm.h" -#include "bus.h" -#include "hal.h" -#include "umac.h" -#include "debug.h" -#include "fw.h" -#include "commands.h" - -static const char fw_barker[] = "*WESTOPFORNOONE*"; - -/* - * @op_code: Op code we're looking for. - * @index: There can be several instances of the same opcode within - * the firmware. Index specifies which one we're looking for. - */ -static int iwm_fw_op_offset(struct iwm_priv *iwm, const struct firmware *fw, - u16 op_code, u32 index) -{ - int offset = -EINVAL, fw_offset; - u32 op_index = 0; - const u8 *fw_ptr; - struct iwm_fw_hdr_rec *rec; - - fw_offset = 0; - fw_ptr = fw->data; - - /* We first need to look for the firmware barker */ - if (memcmp(fw_ptr, fw_barker, IWM_HDR_BARKER_LEN)) { - IWM_ERR(iwm, "No barker string in this FW\n"); - return -EINVAL; - } - - if (fw->size < IWM_HDR_LEN) { - IWM_ERR(iwm, "FW is too small (%zu)\n", fw->size); - return -EINVAL; - } - - fw_offset += IWM_HDR_BARKER_LEN; - - while (fw_offset < fw->size) { - rec = (struct iwm_fw_hdr_rec *)(fw_ptr + fw_offset); - - IWM_DBG_FW(iwm, DBG, "FW: op_code: 0x%x, len: %d @ 0x%x\n", - rec->op_code, rec->len, fw_offset); - - if (rec->op_code == IWM_HDR_REC_OP_INVALID) { - IWM_DBG_FW(iwm, DBG, "Reached INVALID op code\n"); - break; - } - - if (rec->op_code == op_code) { - if (op_index == index) { - fw_offset += sizeof(struct iwm_fw_hdr_rec); - offset = fw_offset; - goto out; - } - op_index++; - } - - fw_offset += sizeof(struct iwm_fw_hdr_rec) + rec->len; - } - - out: - return offset; -} - -static int iwm_load_firmware_chunk(struct iwm_priv *iwm, - const struct firmware *fw, - struct iwm_fw_img_desc *img_desc) -{ - struct iwm_udma_nonwifi_cmd target_cmd; - u32 chunk_size; - const u8 *chunk_ptr; - int ret = 0; - - IWM_DBG_FW(iwm, INFO, "Loading FW chunk: %d bytes @ 0x%x\n", - img_desc->length, img_desc->address); - - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; - target_cmd.handle_by_hw = 1; - target_cmd.op2 = 0; - target_cmd.resp = 0; - target_cmd.eop = 1; - - chunk_size = img_desc->length; - chunk_ptr = fw->data + img_desc->offset; - - while (chunk_size > 0) { - u32 tmp_chunk_size; - - tmp_chunk_size = min_t(u32, chunk_size, - IWM_MAX_NONWIFI_CMD_BUFF_SIZE); - - target_cmd.addr = cpu_to_le32(img_desc->address + - (chunk_ptr - fw->data - img_desc->offset)); - target_cmd.op1_sz = cpu_to_le32(tmp_chunk_size); - - IWM_DBG_FW(iwm, DBG, "\t%d bytes @ 0x%x\n", - tmp_chunk_size, target_cmd.addr); - - ret = iwm_hal_send_target_cmd(iwm, &target_cmd, chunk_ptr); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't load FW chunk\n"); - break; - } - - chunk_size -= tmp_chunk_size; - chunk_ptr += tmp_chunk_size; - } - - return ret; -} -/* - * To load a fw image to the target, we basically go through the - * fw, looking for OP_MEM_DESC records. Once we found one, we - * pass it to iwm_load_firmware_chunk(). - * The OP_MEM_DESC records contain the actuall memory chunk to be - * sent, but also the destination address. - */ -static int iwm_load_img(struct iwm_priv *iwm, const char *img_name) -{ - const struct firmware *fw; - struct iwm_fw_img_desc *img_desc; - struct iwm_fw_img_ver *ver; - int ret = 0, fw_offset; - u32 opcode_idx = 0, build_date; - char *build_tag; - - ret = request_firmware(&fw, img_name, iwm_to_dev(iwm)); - if (ret) { - IWM_ERR(iwm, "Request firmware failed"); - return ret; - } - - IWM_DBG_FW(iwm, INFO, "Start to load FW %s\n", img_name); - - while (1) { - fw_offset = iwm_fw_op_offset(iwm, fw, - IWM_HDR_REC_OP_MEM_DESC, - opcode_idx); - if (fw_offset < 0) - break; - - img_desc = (struct iwm_fw_img_desc *)(fw->data + fw_offset); - ret = iwm_load_firmware_chunk(iwm, fw, img_desc); - if (ret < 0) - goto err_release_fw; - opcode_idx++; - }; - - /* Read firmware version */ - fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_SW_VER, 0); - if (fw_offset < 0) - goto err_release_fw; - - ver = (struct iwm_fw_img_ver *)(fw->data + fw_offset); - - /* Read build tag */ - fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_TAG, 0); - if (fw_offset < 0) - goto err_release_fw; - - build_tag = (char *)(fw->data + fw_offset); - - /* Read build date */ - fw_offset = iwm_fw_op_offset(iwm, fw, IWM_HDR_REC_OP_BUILD_DATE, 0); - if (fw_offset < 0) - goto err_release_fw; - - build_date = *(u32 *)(fw->data + fw_offset); - - IWM_INFO(iwm, "%s:\n", img_name); - IWM_INFO(iwm, "\tVersion: %02X.%02X\n", ver->major, ver->minor); - IWM_INFO(iwm, "\tBuild tag: %s\n", build_tag); - IWM_INFO(iwm, "\tBuild date: %x-%x-%x\n", - IWM_BUILD_YEAR(build_date), IWM_BUILD_MONTH(build_date), - IWM_BUILD_DAY(build_date)); - - - err_release_fw: - release_firmware(fw); - - return ret; -} - -static int iwm_load_umac(struct iwm_priv *iwm) -{ - struct iwm_udma_nonwifi_cmd target_cmd; - int ret; - - ret = iwm_load_img(iwm, iwm->bus_ops->umac_name); - if (ret < 0) - return ret; - - /* We've loaded the UMAC, we can tell the target to jump there */ - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_JUMP; - target_cmd.addr = cpu_to_le32(UMAC_MU_FW_INST_DATA_12_ADDR); - target_cmd.op1_sz = 0; - target_cmd.op2 = 0; - target_cmd.handle_by_hw = 0; - target_cmd.resp = 1 ; - target_cmd.eop = 1; - - ret = iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); - if (ret < 0) - IWM_ERR(iwm, "Couldn't send JMP command\n"); - - return ret; -} - -static int iwm_load_lmac(struct iwm_priv *iwm, const char *img_name) -{ - int ret; - - ret = iwm_load_img(iwm, img_name); - if (ret < 0) - return ret; - - return iwm_send_umac_reset(iwm, - cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_CLK_EN), 0); -} - -static int iwm_init_calib(struct iwm_priv *iwm, unsigned long cfg_bitmap, - unsigned long expected_bitmap, u8 rx_iq_cmd) -{ - /* Read RX IQ calibration result from EEPROM */ - if (test_bit(rx_iq_cmd, &cfg_bitmap)) { - iwm_store_rxiq_calib_result(iwm); - set_bit(PHY_CALIBRATE_RX_IQ_CMD, &iwm->calib_done_map); - } - - iwm_send_prio_table(iwm); - iwm_send_init_calib_cfg(iwm, cfg_bitmap); - - while (iwm->calib_done_map != expected_bitmap) { - if (iwm_notif_handle(iwm, CALIBRATION_RES_NOTIFICATION, - IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT)) { - IWM_DBG_FW(iwm, DBG, "Initial calibration timeout\n"); - return -ETIMEDOUT; - } - - IWM_DBG_FW(iwm, DBG, "Got calibration result. calib_done_map: " - "0x%lx, expected calibrations: 0x%lx\n", - iwm->calib_done_map, expected_bitmap); - } - - return 0; -} - -/* - * We currently have to load 3 FWs: - * 1) The UMAC (Upper MAC). - * 2) The calibration LMAC (Lower MAC). - * We then send the calibration init command, so that the device can - * run a first calibration round. - * 3) The operational LMAC, which replaces the calibration one when it's - * done with the first calibration round. - * - * Once those 3 FWs have been loaded, we send the periodic calibration - * command, and then the device is available for regular 802.11 operations. - */ -int iwm_load_fw(struct iwm_priv *iwm) -{ - unsigned long init_calib_map, periodic_calib_map; - unsigned long expected_calib_map; - int ret; - - /* We first start downloading the UMAC */ - ret = iwm_load_umac(iwm); - if (ret < 0) { - IWM_ERR(iwm, "UMAC loading failed\n"); - return ret; - } - - /* Handle UMAC_ALIVE notification */ - ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_ALIVE, IWM_SRC_UMAC, - WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Handle UMAC_ALIVE failed: %d\n", ret); - return ret; - } - - /* UMAC is alive, we can download the calibration LMAC */ - ret = iwm_load_lmac(iwm, iwm->bus_ops->calib_lmac_name); - if (ret) { - IWM_ERR(iwm, "Calibration LMAC loading failed\n"); - return ret; - } - - /* Handle UMAC_INIT_COMPLETE notification */ - ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE, - IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Handle INIT_COMPLETE failed for calibration " - "LMAC: %d\n", ret); - return ret; - } - - /* Read EEPROM data */ - ret = iwm_eeprom_init(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't init eeprom array\n"); - return ret; - } - - init_calib_map = iwm->conf.calib_map & IWM_CALIB_MAP_INIT_MSK; - expected_calib_map = iwm->conf.expected_calib_map & - IWM_CALIB_MAP_INIT_MSK; - periodic_calib_map = IWM_CALIB_MAP_PER_LMAC(iwm->conf.calib_map); - - ret = iwm_init_calib(iwm, init_calib_map, expected_calib_map, - CALIB_CFG_RX_IQ_IDX); - if (ret < 0) { - /* Let's try the old way */ - ret = iwm_init_calib(iwm, expected_calib_map, - expected_calib_map, - PHY_CALIBRATE_RX_IQ_CMD); - if (ret < 0) { - IWM_ERR(iwm, "Calibration result timeout\n"); - goto out; - } - } - - /* Handle LMAC CALIBRATION_COMPLETE notification */ - ret = iwm_notif_handle(iwm, CALIBRATION_COMPLETE_NOTIFICATION, - IWM_SRC_LMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Wait for CALIBRATION_COMPLETE timeout\n"); - goto out; - } - - IWM_INFO(iwm, "LMAC calibration done: 0x%lx\n", iwm->calib_done_map); - - iwm_send_umac_reset(iwm, cpu_to_le32(UMAC_RST_CTRL_FLG_LARC_RESET), 1); - - ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_RESET, IWM_SRC_UMAC, - WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Wait for UMAC RESET timeout\n"); - goto out; - } - - /* Download the operational LMAC */ - ret = iwm_load_lmac(iwm, iwm->bus_ops->lmac_name); - if (ret) { - IWM_ERR(iwm, "LMAC loading failed\n"); - goto out; - } - - ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_INIT_COMPLETE, - IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Handle INIT_COMPLETE failed for LMAC: %d\n", ret); - goto out; - } - - iwm_send_prio_table(iwm); - iwm_send_calib_results(iwm); - iwm_send_periodic_calib_cfg(iwm, periodic_calib_map); - - return 0; - - out: - iwm_eeprom_exit(iwm); - return ret; -} diff --git a/drivers/net/wireless/iwmc3200wifi/fw.h b/drivers/net/wireless/iwmc3200wifi/fw.h deleted file mode 100644 index c70a3b40dad3..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/fw.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_FW_H__ -#define __IWM_FW_H__ - -/** - * struct iwm_fw_hdr_rec - An iwm firmware image is a - * concatenation of various records. Each of them is - * defined by an ID (aka op code), a length, and the - * actual data. - * @op_code: The record ID, see IWM_HDR_REC_OP_* - * - * @len: The record payload length - * - * @buf: The record payload - */ -struct iwm_fw_hdr_rec { - u16 op_code; - u16 len; - u8 buf[0]; -}; - -/* Header's definitions */ -#define IWM_HDR_LEN (512) -#define IWM_HDR_BARKER_LEN (16) - -/* Header's opcodes */ -#define IWM_HDR_REC_OP_INVALID (0x00) -#define IWM_HDR_REC_OP_BUILD_DATE (0x01) -#define IWM_HDR_REC_OP_BUILD_TAG (0x02) -#define IWM_HDR_REC_OP_SW_VER (0x03) -#define IWM_HDR_REC_OP_HW_SKU (0x04) -#define IWM_HDR_REC_OP_BUILD_OPT (0x05) -#define IWM_HDR_REC_OP_MEM_DESC (0x06) -#define IWM_HDR_REC_USERDEFS (0x07) - -/* Header's records length (in bytes) */ -#define IWM_HDR_REC_LEN_BUILD_DATE (4) -#define IWM_HDR_REC_LEN_BUILD_TAG (64) -#define IWM_HDR_REC_LEN_SW_VER (4) -#define IWM_HDR_REC_LEN_HW_SKU (4) -#define IWM_HDR_REC_LEN_BUILD_OPT (4) -#define IWM_HDR_REC_LEN_MEM_DESC (12) -#define IWM_HDR_REC_LEN_USERDEF (64) - -#define IWM_BUILD_YEAR(date) ((date >> 16) & 0xffff) -#define IWM_BUILD_MONTH(date) ((date >> 8) & 0xff) -#define IWM_BUILD_DAY(date) (date & 0xff) - -struct iwm_fw_img_desc { - u32 offset; - u32 address; - u32 length; -}; - -struct iwm_fw_img_ver { - u8 minor; - u8 major; - u16 reserved; -}; - -int iwm_load_fw(struct iwm_priv *iwm); - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/hal.c b/drivers/net/wireless/iwmc3200wifi/hal.c deleted file mode 100644 index c430418248b4..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/hal.c +++ /dev/null @@ -1,466 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -/* - * Hardware Abstraction Layer for iwm. - * - * This file mostly defines an abstraction API for - * sending various commands to the target. - * - * We have 2 types of commands: wifi and non-wifi ones. - * - * - wifi commands: - * They are used for sending LMAC and UMAC commands, - * and thus are the most commonly used ones. - * There are 2 different wifi command types, the regular - * one and the LMAC one. The former is used to send - * UMAC commands (see UMAC_CMD_OPCODE_* from umac.h) - * while the latter is used for sending commands to the - * LMAC. If you look at LMAC commands you'll se that they - * are actually regular iwlwifi target commands encapsulated - * into a special UMAC command called UMAC passthrough. - * This is due to the fact the the host talks exclusively - * to the UMAC and so there needs to be a special UMAC - * command for talking to the LMAC. - * This is how a wifi command is layed out: - * ------------------------ - * | iwm_udma_out_wifi_hdr | - * ------------------------ - * | SW meta_data (32 bits) | - * ------------------------ - * | iwm_dev_cmd_hdr | - * ------------------------ - * | payload | - * | .... | - * - * - non-wifi, or general commands: - * Those commands are handled by the device's bootrom, - * and are typically sent when the UMAC and the LMAC - * are not yet available. - * * This is how a non-wifi command is layed out: - * --------------------------- - * | iwm_udma_out_nonwifi_hdr | - * --------------------------- - * | payload | - * | .... | - - * - * All the commands start with a UDMA header, which is - * basically a 32 bits field. The 4 LSB there define - * an opcode that allows the target to differentiate - * between wifi (opcode is 0xf) and non-wifi commands - * (opcode is [0..0xe]). - * - * When a command (wifi or non-wifi) is supposed to receive - * an answer, we queue the command buffer. When we do receive - * a command response from the UMAC, we go through the list - * of pending command, and pass both the command and the answer - * to the rx handler. Each command is sent with a unique - * sequence id, and the answer is sent with the same one. This - * is how we're supposed to match an answer with its command. - * See rx.c:iwm_rx_handle_[non]wifi() and iwm_get_pending_[non]wifi() - * for the implementation details. - */ -#include -#include - -#include "iwm.h" -#include "bus.h" -#include "hal.h" -#include "umac.h" -#include "debug.h" - -static int iwm_nonwifi_cmd_init(struct iwm_priv *iwm, - struct iwm_nonwifi_cmd *cmd, - struct iwm_udma_nonwifi_cmd *udma_cmd) -{ - INIT_LIST_HEAD(&cmd->pending); - - spin_lock(&iwm->cmd_lock); - - cmd->resp_received = 0; - - cmd->seq_num = iwm->nonwifi_seq_num; - udma_cmd->seq_num = cpu_to_le16(cmd->seq_num); - - iwm->nonwifi_seq_num++; - iwm->nonwifi_seq_num %= UMAC_NONWIFI_SEQ_NUM_MAX; - - if (udma_cmd->resp) - list_add_tail(&cmd->pending, &iwm->nonwifi_pending_cmd); - - spin_unlock(&iwm->cmd_lock); - - cmd->buf.start = cmd->buf.payload; - cmd->buf.len = 0; - - memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); - - return cmd->seq_num; -} - -u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm) -{ - u16 seq_num = iwm->wifi_seq_num; - - iwm->wifi_seq_num++; - iwm->wifi_seq_num %= UMAC_WIFI_SEQ_NUM_MAX; - - return seq_num; -} - -static void iwm_wifi_cmd_init(struct iwm_priv *iwm, - struct iwm_wifi_cmd *cmd, - struct iwm_udma_wifi_cmd *udma_cmd, - struct iwm_umac_cmd *umac_cmd, - struct iwm_lmac_cmd *lmac_cmd, - u16 payload_size) -{ - INIT_LIST_HEAD(&cmd->pending); - - spin_lock(&iwm->cmd_lock); - - cmd->seq_num = iwm_alloc_wifi_cmd_seq(iwm); - umac_cmd->seq_num = cpu_to_le16(cmd->seq_num); - - if (umac_cmd->resp) - list_add_tail(&cmd->pending, &iwm->wifi_pending_cmd); - - spin_unlock(&iwm->cmd_lock); - - cmd->buf.start = cmd->buf.payload; - cmd->buf.len = 0; - - if (lmac_cmd) { - cmd->buf.start -= sizeof(struct iwm_lmac_hdr); - - lmac_cmd->seq_num = cpu_to_le16(cmd->seq_num); - lmac_cmd->count = cpu_to_le16(payload_size); - - memcpy(&cmd->lmac_cmd, lmac_cmd, sizeof(*lmac_cmd)); - - umac_cmd->count = cpu_to_le16(sizeof(struct iwm_lmac_hdr)); - } else - umac_cmd->count = 0; - - umac_cmd->count = cpu_to_le16(payload_size + - le16_to_cpu(umac_cmd->count)); - udma_cmd->count = cpu_to_le16(sizeof(struct iwm_umac_fw_cmd_hdr) + - le16_to_cpu(umac_cmd->count)); - - memcpy(&cmd->udma_cmd, udma_cmd, sizeof(*udma_cmd)); - memcpy(&cmd->umac_cmd, umac_cmd, sizeof(*umac_cmd)); -} - -void iwm_cmd_flush(struct iwm_priv *iwm) -{ - struct iwm_wifi_cmd *wcmd, *wnext; - struct iwm_nonwifi_cmd *nwcmd, *nwnext; - - list_for_each_entry_safe(wcmd, wnext, &iwm->wifi_pending_cmd, pending) { - list_del(&wcmd->pending); - kfree(wcmd); - } - - list_for_each_entry_safe(nwcmd, nwnext, &iwm->nonwifi_pending_cmd, - pending) { - list_del(&nwcmd->pending); - kfree(nwcmd); - } -} - -struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, u16 seq_num) -{ - struct iwm_wifi_cmd *cmd, *next; - - list_for_each_entry_safe(cmd, next, &iwm->wifi_pending_cmd, pending) - if (cmd->seq_num == seq_num) { - list_del(&cmd->pending); - return cmd; - } - - return NULL; -} - -struct iwm_nonwifi_cmd * -iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, u8 seq_num, u8 cmd_opcode) -{ - struct iwm_nonwifi_cmd *cmd, *next; - - list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) - if ((cmd->seq_num == seq_num) && - (cmd->udma_cmd.opcode == cmd_opcode) && - (cmd->resp_received)) { - list_del(&cmd->pending); - return cmd; - } - - return NULL; -} - -static void iwm_build_udma_nonwifi_hdr(struct iwm_priv *iwm, - struct iwm_udma_out_nonwifi_hdr *hdr, - struct iwm_udma_nonwifi_cmd *cmd) -{ - memset(hdr, 0, sizeof(*hdr)); - - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, cmd->opcode); - SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_RESP, cmd->resp); - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, 1); - SET_VAL32(hdr->cmd, UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW, - cmd->handle_by_hw); - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE); - SET_VAL32(hdr->cmd, UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM, - le16_to_cpu(cmd->seq_num)); - - hdr->addr = cmd->addr; - hdr->op1_sz = cmd->op1_sz; - hdr->op2 = cmd->op2; -} - -static int iwm_send_udma_nonwifi_cmd(struct iwm_priv *iwm, - struct iwm_nonwifi_cmd *cmd) -{ - struct iwm_udma_out_nonwifi_hdr *udma_hdr; - struct iwm_nonwifi_cmd_buff *buf; - struct iwm_udma_nonwifi_cmd *udma_cmd = &cmd->udma_cmd; - - buf = &cmd->buf; - - buf->start -= sizeof(struct iwm_umac_nonwifi_out_hdr); - buf->len += sizeof(struct iwm_umac_nonwifi_out_hdr); - - udma_hdr = (struct iwm_udma_out_nonwifi_hdr *)(buf->start); - - iwm_build_udma_nonwifi_hdr(iwm, udma_hdr, udma_cmd); - - IWM_DBG_CMD(iwm, DBG, - "Send UDMA nonwifi cmd: opcode = 0x%x, resp = 0x%x, " - "hw = 0x%x, seqnum = %d, addr = 0x%x, op1_sz = 0x%x, " - "op2 = 0x%x\n", udma_cmd->opcode, udma_cmd->resp, - udma_cmd->handle_by_hw, cmd->seq_num, udma_cmd->addr, - udma_cmd->op1_sz, udma_cmd->op2); - - return iwm_bus_send_chunk(iwm, buf->start, buf->len); -} - -void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop) -{ - struct iwm_udma_out_wifi_hdr *hdr = (struct iwm_udma_out_wifi_hdr *)buf; - - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, eop); -} - -void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm, - struct iwm_udma_out_wifi_hdr *hdr, - struct iwm_udma_wifi_cmd *cmd) -{ - memset(hdr, 0, sizeof(*hdr)); - - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_OPCODE, UMAC_HDI_OUT_OPCODE_WIFI); - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_EOT, cmd->eop); - SET_VAL32(hdr->cmd, UMAC_HDI_OUT_CMD_SIGNATURE, UMAC_HDI_OUT_SIGNATURE); - - SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_BYTE_COUNT, - le16_to_cpu(cmd->count)); - SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_CREDIT_GRP, cmd->credit_group); - SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_RATID, cmd->ra_tid); - SET_VAL32(hdr->meta_data, UMAC_HDI_OUT_LMAC_OFFSET, cmd->lmac_offset); -} - -void iwm_build_umac_hdr(struct iwm_priv *iwm, - struct iwm_umac_fw_cmd_hdr *hdr, - struct iwm_umac_cmd *cmd) -{ - memset(hdr, 0, sizeof(*hdr)); - - SET_VAL32(hdr->meta_data, UMAC_FW_CMD_BYTE_COUNT, - le16_to_cpu(cmd->count)); - SET_VAL32(hdr->meta_data, UMAC_FW_CMD_TX_STA_COLOR, cmd->color); - SET_VAL8(hdr->cmd.flags, UMAC_DEV_CMD_FLAGS_RESP_REQ, cmd->resp); - - hdr->cmd.cmd = cmd->id; - hdr->cmd.seq_num = cmd->seq_num; -} - -static int iwm_send_udma_wifi_cmd(struct iwm_priv *iwm, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_wifi_out_hdr *umac_hdr; - struct iwm_wifi_cmd_buff *buf; - struct iwm_udma_wifi_cmd *udma_cmd = &cmd->udma_cmd; - struct iwm_umac_cmd *umac_cmd = &cmd->umac_cmd; - int ret; - - buf = &cmd->buf; - - buf->start -= sizeof(struct iwm_umac_wifi_out_hdr); - buf->len += sizeof(struct iwm_umac_wifi_out_hdr); - - umac_hdr = (struct iwm_umac_wifi_out_hdr *)(buf->start); - - iwm_build_udma_wifi_hdr(iwm, &umac_hdr->hw_hdr, udma_cmd); - iwm_build_umac_hdr(iwm, &umac_hdr->sw_hdr, umac_cmd); - - IWM_DBG_CMD(iwm, DBG, - "Send UDMA wifi cmd: opcode = 0x%x, UMAC opcode = 0x%x, " - "eop = 0x%x, count = 0x%x, credit_group = 0x%x, " - "ra_tid = 0x%x, lmac_offset = 0x%x, seqnum = %d\n", - UMAC_HDI_OUT_OPCODE_WIFI, umac_cmd->id, - udma_cmd->eop, udma_cmd->count, udma_cmd->credit_group, - udma_cmd->ra_tid, udma_cmd->lmac_offset, cmd->seq_num); - - if (umac_cmd->id == UMAC_CMD_OPCODE_WIFI_PASS_THROUGH) - IWM_DBG_CMD(iwm, DBG, "\tLMAC opcode: 0x%x\n", - cmd->lmac_cmd.id); - - ret = iwm_tx_credit_alloc(iwm, udma_cmd->credit_group, buf->len); - - /* We keep sending UMAC reset regardless of the command credits. - * The UMAC is supposed to be reset anyway and the Tx credits are - * reinitialized afterwards. If we are lucky, the reset could - * still be done even though we have run out of credits for the - * command pool at this moment.*/ - if (ret && (umac_cmd->id != UMAC_CMD_OPCODE_RESET)) { - IWM_DBG_TX(iwm, DBG, "Failed to alloc tx credit for cmd %d\n", - umac_cmd->id); - return ret; - } - - return iwm_bus_send_chunk(iwm, buf->start, buf->len); -} - -/* target_cmd a.k.a udma_nonwifi_cmd can be sent when UMAC is not available */ -int iwm_hal_send_target_cmd(struct iwm_priv *iwm, - struct iwm_udma_nonwifi_cmd *udma_cmd, - const void *payload) -{ - struct iwm_nonwifi_cmd *cmd; - int ret, seq_num; - - cmd = kzalloc(sizeof(struct iwm_nonwifi_cmd), GFP_KERNEL); - if (!cmd) { - IWM_ERR(iwm, "Couldn't alloc memory for hal cmd\n"); - return -ENOMEM; - } - - seq_num = iwm_nonwifi_cmd_init(iwm, cmd, udma_cmd); - - if (cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE || - cmd->udma_cmd.opcode == UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT) { - cmd->buf.len = le32_to_cpu(cmd->udma_cmd.op1_sz); - memcpy(&cmd->buf.payload, payload, cmd->buf.len); - } - - ret = iwm_send_udma_nonwifi_cmd(iwm, cmd); - - if (!udma_cmd->resp) - kfree(cmd); - - if (ret < 0) - return ret; - - return seq_num; -} - -static void iwm_build_lmac_hdr(struct iwm_priv *iwm, struct iwm_lmac_hdr *hdr, - struct iwm_lmac_cmd *cmd) -{ - memset(hdr, 0, sizeof(*hdr)); - - hdr->id = cmd->id; - hdr->flags = 0; /* Is this ever used? */ - hdr->seq_num = cmd->seq_num; -} - -/* - * iwm_hal_send_host_cmd(): sends commands to the UMAC or the LMAC. - * Sending command to the LMAC is equivalent to sending a - * regular UMAC command with the LMAC passtrough or the LMAC - * wrapper UMAC command IDs. - */ -int iwm_hal_send_host_cmd(struct iwm_priv *iwm, - struct iwm_udma_wifi_cmd *udma_cmd, - struct iwm_umac_cmd *umac_cmd, - struct iwm_lmac_cmd *lmac_cmd, - const void *payload, u16 payload_size) -{ - struct iwm_wifi_cmd *cmd; - struct iwm_lmac_hdr *hdr; - int lmac_hdr_len = 0; - int ret; - - cmd = kzalloc(sizeof(struct iwm_wifi_cmd), GFP_KERNEL); - if (!cmd) { - IWM_ERR(iwm, "Couldn't alloc memory for wifi hal cmd\n"); - return -ENOMEM; - } - - iwm_wifi_cmd_init(iwm, cmd, udma_cmd, umac_cmd, lmac_cmd, payload_size); - - if (lmac_cmd) { - hdr = (struct iwm_lmac_hdr *)(cmd->buf.start); - - iwm_build_lmac_hdr(iwm, hdr, &cmd->lmac_cmd); - lmac_hdr_len = sizeof(struct iwm_lmac_hdr); - } - - memcpy(cmd->buf.payload, payload, payload_size); - cmd->buf.len = le16_to_cpu(umac_cmd->count); - - ret = iwm_send_udma_wifi_cmd(iwm, cmd); - - /* We free the cmd if we're not expecting any response */ - if (!umac_cmd->resp) - kfree(cmd); - return ret; -} - -/* - * iwm_hal_send_umac_cmd(): This is a special case for - * iwm_hal_send_host_cmd() to send direct UMAC cmd (without - * LMAC involved). - */ -int iwm_hal_send_umac_cmd(struct iwm_priv *iwm, - struct iwm_udma_wifi_cmd *udma_cmd, - struct iwm_umac_cmd *umac_cmd, - const void *payload, u16 payload_size) -{ - return iwm_hal_send_host_cmd(iwm, udma_cmd, umac_cmd, NULL, - payload, payload_size); -} diff --git a/drivers/net/wireless/iwmc3200wifi/hal.h b/drivers/net/wireless/iwmc3200wifi/hal.h deleted file mode 100644 index 0adfdc85765d..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/hal.h +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef _IWM_HAL_H_ -#define _IWM_HAL_H_ - -#include "umac.h" - -#define GET_VAL8(s, name) ((s >> name##_POS) & name##_SEED) -#define GET_VAL16(s, name) ((le16_to_cpu(s) >> name##_POS) & name##_SEED) -#define GET_VAL32(s, name) ((le32_to_cpu(s) >> name##_POS) & name##_SEED) - -#define SET_VAL8(s, name, val) \ -do { \ - s = (s & ~(name##_SEED << name##_POS)) | \ - ((val & name##_SEED) << name##_POS); \ -} while (0) - -#define SET_VAL16(s, name, val) \ -do { \ - s = cpu_to_le16((le16_to_cpu(s) & ~(name##_SEED << name##_POS)) | \ - ((val & name##_SEED) << name##_POS)); \ -} while (0) - -#define SET_VAL32(s, name, val) \ -do { \ - s = cpu_to_le32((le32_to_cpu(s) & ~(name##_SEED << name##_POS)) | \ - ((val & name##_SEED) << name##_POS)); \ -} while (0) - - -#define UDMA_UMAC_INIT { .eop = 1, \ - .credit_group = 0x4, \ - .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \ - .lmac_offset = 0 } -#define UDMA_LMAC_INIT { .eop = 1, \ - .credit_group = 0x4, \ - .ra_tid = UMAC_HDI_ACT_TBL_IDX_HOST_CMD, \ - .lmac_offset = 4 } - - -/* UDMA IN OP CODE -- cmd bits [3:0] */ -#define UDMA_IN_OPCODE_MASK 0xF - -#define UDMA_IN_OPCODE_GENERAL_RESP 0x0 -#define UDMA_IN_OPCODE_READ_RESP 0x1 -#define UDMA_IN_OPCODE_WRITE_RESP 0x2 -#define UDMA_IN_OPCODE_PERS_WRITE_RESP 0x5 -#define UDMA_IN_OPCODE_PERS_READ_RESP 0x6 -#define UDMA_IN_OPCODE_RD_MDFY_WR_RESP 0x7 -#define UDMA_IN_OPCODE_EP_MNGMT_MSG 0x8 -#define UDMA_IN_OPCODE_CRDT_CHNG_MSG 0x9 -#define UDMA_IN_OPCODE_CNTRL_DATABASE_MSG 0xA -#define UDMA_IN_OPCODE_SW_MSG 0xB -#define UDMA_IN_OPCODE_WIFI 0xF -#define UDMA_IN_OPCODE_WIFI_LMAC 0x1F -#define UDMA_IN_OPCODE_WIFI_UMAC 0x2F - -/* HW API: udma_hdi_nonwifi API (OUT and IN) */ - -/* iwm_udma_nonwifi_cmd request response -- bits [9:9] */ -#define UDMA_HDI_OUT_NW_CMD_RESP_POS 9 -#define UDMA_HDI_OUT_NW_CMD_RESP_SEED 0x1 - -/* iwm_udma_nonwifi_cmd handle by HW -- bits [11:11] */ -#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_POS 11 -#define UDMA_HDI_OUT_NW_CMD_HANDLE_BY_HW_SEED 0x1 - -/* iwm_udma_nonwifi_cmd sequence-number -- bits [12:15] */ -#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_POS 12 -#define UDMA_HDI_OUT_NW_CMD_SEQ_NUM_SEED 0xF - -/* UDMA IN Non-WIFI HW sequence number -- bits [12:15] */ -#define UDMA_IN_NW_HW_SEQ_NUM_POS 12 -#define UDMA_IN_NW_HW_SEQ_NUM_SEED 0xF - -/* UDMA IN Non-WIFI HW signature -- bits [16:31] */ -#define UDMA_IN_NW_HW_SIG_POS 16 -#define UDMA_IN_NW_HW_SIG_SEED 0xFFFF - -/* fixed signature */ -#define UDMA_IN_NW_HW_SIG 0xCBBC - -/* UDMA IN Non-WIFI HW block length -- bits [32:35] */ -#define UDMA_IN_NW_HW_LENGTH_SEED 0xF -#define UDMA_IN_NW_HW_LENGTH_POS 32 - -/* End of HW API: udma_hdi_nonwifi API (OUT and IN) */ - -#define IWM_SDIO_FW_MAX_CHUNK_SIZE 2032 -#define IWM_MAX_WIFI_HEADERS_SIZE 32 -#define IWM_MAX_NONWIFI_HEADERS_SIZE 16 -#define IWM_MAX_NONWIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ - IWM_MAX_NONWIFI_HEADERS_SIZE) -#define IWM_MAX_WIFI_CMD_BUFF_SIZE (IWM_SDIO_FW_MAX_CHUNK_SIZE - \ - IWM_MAX_WIFI_HEADERS_SIZE) - -#define IWM_HAL_CONCATENATE_BUF_SIZE 8192 - -struct iwm_wifi_cmd_buff { - u16 len; - u8 *start; - u8 hdr[IWM_MAX_WIFI_HEADERS_SIZE]; - u8 payload[IWM_MAX_WIFI_CMD_BUFF_SIZE]; -}; - -struct iwm_nonwifi_cmd_buff { - u16 len; - u8 *start; - u8 hdr[IWM_MAX_NONWIFI_HEADERS_SIZE]; - u8 payload[IWM_MAX_NONWIFI_CMD_BUFF_SIZE]; -}; - -struct iwm_udma_nonwifi_cmd { - u8 opcode; - u8 eop; - u8 resp; - u8 handle_by_hw; - __le32 addr; - __le32 op1_sz; - __le32 op2; - __le16 seq_num; -}; - -struct iwm_udma_wifi_cmd { - __le16 count; - u8 eop; - u8 credit_group; - u8 ra_tid; - u8 lmac_offset; -}; - -struct iwm_umac_cmd { - u8 id; - __le16 count; - u8 resp; - __le16 seq_num; - u8 color; -}; - -struct iwm_lmac_cmd { - u8 id; - __le16 count; - u8 resp; - __le16 seq_num; -}; - -struct iwm_nonwifi_cmd { - u16 seq_num; - bool resp_received; - struct list_head pending; - struct iwm_udma_nonwifi_cmd udma_cmd; - struct iwm_umac_cmd umac_cmd; - struct iwm_lmac_cmd lmac_cmd; - struct iwm_nonwifi_cmd_buff buf; - u32 flags; -}; - -struct iwm_wifi_cmd { - u16 seq_num; - struct list_head pending; - struct iwm_udma_wifi_cmd udma_cmd; - struct iwm_umac_cmd umac_cmd; - struct iwm_lmac_cmd lmac_cmd; - struct iwm_wifi_cmd_buff buf; - u32 flags; -}; - -void iwm_cmd_flush(struct iwm_priv *iwm); - -struct iwm_wifi_cmd *iwm_get_pending_wifi_cmd(struct iwm_priv *iwm, - u16 seq_num); -struct iwm_nonwifi_cmd *iwm_get_pending_nonwifi_cmd(struct iwm_priv *iwm, - u8 seq_num, u8 cmd_opcode); - - -int iwm_hal_send_target_cmd(struct iwm_priv *iwm, - struct iwm_udma_nonwifi_cmd *ucmd, - const void *payload); - -int iwm_hal_send_host_cmd(struct iwm_priv *iwm, - struct iwm_udma_wifi_cmd *udma_cmd, - struct iwm_umac_cmd *umac_cmd, - struct iwm_lmac_cmd *lmac_cmd, - const void *payload, u16 payload_size); - -int iwm_hal_send_umac_cmd(struct iwm_priv *iwm, - struct iwm_udma_wifi_cmd *udma_cmd, - struct iwm_umac_cmd *umac_cmd, - const void *payload, u16 payload_size); - -u16 iwm_alloc_wifi_cmd_seq(struct iwm_priv *iwm); - -void iwm_udma_wifi_hdr_set_eop(struct iwm_priv *iwm, u8 *buf, u8 eop); -void iwm_build_udma_wifi_hdr(struct iwm_priv *iwm, - struct iwm_udma_out_wifi_hdr *hdr, - struct iwm_udma_wifi_cmd *cmd); -void iwm_build_umac_hdr(struct iwm_priv *iwm, - struct iwm_umac_fw_cmd_hdr *hdr, - struct iwm_umac_cmd *cmd); -#endif /* _IWM_HAL_H_ */ diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h deleted file mode 100644 index 93c898990cce..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/iwm.h +++ /dev/null @@ -1,349 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_H__ -#define __IWM_H__ - -#include -#include -#include - -#include "debug.h" -#include "hal.h" -#include "umac.h" -#include "lmac.h" -#include "eeprom.h" - -#define IWM_COPYRIGHT "Copyright(c) 2009 Intel Corporation" -#define IWM_AUTHOR "" - -#define IWM_SRC_LMAC UMAC_HDI_IN_SOURCE_FHRX -#define IWM_SRC_UDMA UMAC_HDI_IN_SOURCE_UDMA -#define IWM_SRC_UMAC UMAC_HDI_IN_SOURCE_FW -#define IWM_SRC_NUM 3 - -#define IWM_POWER_INDEX_MIN 0 -#define IWM_POWER_INDEX_MAX 5 -#define IWM_POWER_INDEX_DEFAULT 3 - -struct iwm_conf { - u32 sdio_ior_timeout; - unsigned long calib_map; - unsigned long expected_calib_map; - bool reset_on_fatal_err; - bool auto_connect; - bool wimax_not_present; - bool enable_qos; - u32 mode; - - u32 power_index; - u32 frag_threshold; - u32 rts_threshold; - bool cts_to_self; - - u32 assoc_timeout; - u32 roam_timeout; - u32 wireless_mode; - u32 coexist_mode; - - u8 ibss_band; - u8 ibss_channel; - - u8 mac_addr[ETH_ALEN]; -}; - -enum { - COEX_MODE_SA = 1, - COEX_MODE_XOR, - COEX_MODE_CM, - COEX_MODE_MAX, -}; - -struct iwm_if_ops; -struct iwm_wifi_cmd; - -struct pool_entry { - int id; /* group id */ - int sid; /* super group id */ - int min_pages; /* min capacity in pages */ - int max_pages; /* max capacity in pages */ - int alloc_pages; /* allocated # of pages. incresed by driver */ - int total_freed_pages; /* total freed # of pages. incresed by UMAC */ -}; - -struct spool_entry { - int id; - int max_pages; - int alloc_pages; -}; - -struct iwm_tx_credit { - spinlock_t lock; - int pool_nr; - unsigned long full_pools_map; /* bitmap for # of filled tx pools */ - struct pool_entry pools[IWM_MACS_OUT_GROUPS]; - struct spool_entry spools[IWM_MACS_OUT_SGROUPS]; -}; - -struct iwm_notif { - struct list_head pending; - u32 cmd_id; - void *cmd; - u8 src; - void *buf; - unsigned long buf_size; -}; - -struct iwm_sta_info { - u8 addr[ETH_ALEN]; - bool valid; - bool qos; - u8 color; -}; - -struct iwm_tx_info { - u8 sta; - u8 color; - u8 tid; -}; - -struct iwm_rx_info { - unsigned long rx_size; - unsigned long rx_buf_size; -}; - -#define IWM_NUM_KEYS 4 - -struct iwm_umac_key_hdr { - u8 mac[ETH_ALEN]; - u8 key_idx; - u8 multicast; /* BCast encrypt & BCast decrypt of frames FROM mac */ -} __attribute__ ((packed)); - -struct iwm_key { - struct iwm_umac_key_hdr hdr; - u32 cipher; - u8 key[WLAN_MAX_KEY_LEN]; - u8 seq[IW_ENCODE_SEQ_MAX_SIZE]; - int key_len; - int seq_len; -}; - -#define IWM_RX_ID_HASH 0xff -#define IWM_RX_ID_GET_HASH(id) ((id) % IWM_RX_ID_HASH) - -#define IWM_STA_TABLE_NUM 16 -#define IWM_TX_LIST_SIZE 64 -#define IWM_RX_LIST_SIZE 256 - -#define IWM_SCAN_ID_MAX 0xff - -#define IWM_STATUS_READY 0 -#define IWM_STATUS_SCANNING 1 -#define IWM_STATUS_SCAN_ABORTING 2 -#define IWM_STATUS_SME_CONNECTING 3 -#define IWM_STATUS_ASSOCIATED 4 -#define IWM_STATUS_RESETTING 5 - -struct iwm_tx_queue { - int id; - struct sk_buff_head queue; - struct workqueue_struct *wq; - struct work_struct worker; - u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE]; - int concat_count; - u8 *concat_ptr; -}; - -/* Queues 0 ~ 3 for AC data, 5 for iPAN */ -#define IWM_TX_QUEUES 5 -#define IWM_TX_DATA_QUEUES 4 -#define IWM_TX_CMD_QUEUE 4 - -struct iwm_bss_info { - struct list_head node; - struct cfg80211_bss *cfg_bss; - struct iwm_umac_notif_bss_info *bss; -}; - -typedef int (*iwm_handler)(struct iwm_priv *priv, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd); - -#define IWM_WATCHDOG_PERIOD (6 * HZ) - -struct iwm_priv { - struct wireless_dev *wdev; - struct iwm_if_ops *bus_ops; - - struct iwm_conf conf; - - unsigned long status; - - struct list_head pending_notif; - wait_queue_head_t notif_queue; - - wait_queue_head_t nonwifi_queue; - - unsigned long calib_done_map; - struct { - u8 *buf; - u32 size; - } calib_res[CALIBRATION_CMD_NUM]; - - struct iwm_umac_profile *umac_profile; - bool umac_profile_active; - - u8 bssid[ETH_ALEN]; - u8 channel; - u16 rate; - u32 txpower; - - struct iwm_sta_info sta_table[IWM_STA_TABLE_NUM]; - struct list_head bss_list; - - void (*nonwifi_rx_handlers[UMAC_HDI_IN_OPCODE_NONWIFI_MAX]) - (struct iwm_priv *priv, u8 *buf, unsigned long buf_size); - - const iwm_handler *umac_handlers; - const iwm_handler *lmac_handlers; - DECLARE_BITMAP(lmac_handler_map, LMAC_COMMAND_ID_NUM); - DECLARE_BITMAP(umac_handler_map, LMAC_COMMAND_ID_NUM); - DECLARE_BITMAP(udma_handler_map, LMAC_COMMAND_ID_NUM); - - struct list_head wifi_pending_cmd; - struct list_head nonwifi_pending_cmd; - u16 wifi_seq_num; - u8 nonwifi_seq_num; - spinlock_t cmd_lock; - - u32 core_enabled; - - u8 scan_id; - struct cfg80211_scan_request *scan_request; - - struct sk_buff_head rx_list; - struct list_head rx_tickets; - struct list_head rx_packets[IWM_RX_ID_HASH + 1]; - struct workqueue_struct *rx_wq; - struct work_struct rx_worker; - - struct iwm_tx_credit tx_credit; - struct iwm_tx_queue txq[IWM_TX_QUEUES]; - - struct iwm_key keys[IWM_NUM_KEYS]; - s8 default_key; - - DECLARE_BITMAP(wifi_ntfy, WIFI_IF_NTFY_MAX); - wait_queue_head_t wifi_ntfy_queue; - - wait_queue_head_t mlme_queue; - - struct iw_statistics wstats; - struct delayed_work stats_request; - struct delayed_work disconnect; - - struct iwm_debugfs dbg; - - u8 *eeprom; - struct timer_list watchdog; - struct work_struct reset_worker; - struct mutex mutex; - - u8 *req_ie; - int req_ie_len; - u8 *resp_ie; - int resp_ie_len; - - struct iwm_fw_error_hdr *last_fw_err; - - char private[0] __attribute__((__aligned__(NETDEV_ALIGN))); -}; - -static inline void *iwm_private(struct iwm_priv *iwm) -{ - BUG_ON(!iwm); - return &iwm->private; -} - -#define hw_to_iwm(h) (h->iwm) -#define iwm_to_dev(i) (wiphy_dev(i->wdev->wiphy)) -#define iwm_to_wiphy(i) (i->wdev->wiphy) -#define wiphy_to_iwm(w) (struct iwm_priv *)(wiphy_priv(w)) -#define iwm_to_wdev(i) (i->wdev) -#define wdev_to_iwm(w) (struct iwm_priv *)(wdev_priv(w)) -#define iwm_to_ndev(i) (i->wdev->netdev) -#define ndev_to_iwm(n) (wdev_to_iwm(n->ieee80211_ptr)) -#define skb_to_rx_info(s) ((struct iwm_rx_info *)(s->cb)) -#define skb_to_tx_info(s) ((struct iwm_tx_info *)s->cb) - -void *iwm_if_alloc(int sizeof_bus, struct device *dev, - struct iwm_if_ops *if_ops); -void iwm_if_free(struct iwm_priv *iwm); -int iwm_if_add(struct iwm_priv *iwm); -void iwm_if_remove(struct iwm_priv *iwm); -int iwm_mode_to_nl80211_iftype(int mode); -int iwm_priv_init(struct iwm_priv *iwm); -void iwm_priv_deinit(struct iwm_priv *iwm); -void iwm_reset(struct iwm_priv *iwm); -void iwm_resetting(struct iwm_priv *iwm); -void iwm_tx_credit_init_pools(struct iwm_priv *iwm, - struct iwm_umac_notif_alive *alive); -int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb); -int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, - u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size); -int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout); -void iwm_init_default_profile(struct iwm_priv *iwm, - struct iwm_umac_profile *profile); -void iwm_link_on(struct iwm_priv *iwm); -void iwm_link_off(struct iwm_priv *iwm); -int iwm_up(struct iwm_priv *iwm); -int iwm_down(struct iwm_priv *iwm); - -/* TX API */ -void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages); -void iwm_tx_worker(struct work_struct *work); -int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev); - -/* RX API */ -void iwm_rx_setup_handlers(struct iwm_priv *iwm); -int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size); -int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, - struct iwm_wifi_cmd *cmd); -void iwm_rx_free(struct iwm_priv *iwm); - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/lmac.h b/drivers/net/wireless/iwmc3200wifi/lmac.h deleted file mode 100644 index 6c1a14c4480f..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/lmac.h +++ /dev/null @@ -1,476 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_LMAC_H__ -#define __IWM_LMAC_H__ - -struct iwm_lmac_hdr { - u8 id; - u8 flags; - __le16 seq_num; -} __attribute__ ((packed)); - -/* LMAC commands */ -#define CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK 0x1 - -struct iwm_lmac_cal_cfg_elt { - __le32 enable; /* 1 means LMAC needs to do something */ - __le32 start; /* 1 to start calibration, 0 to stop */ - __le32 send_res; /* 1 for sending back results */ - __le32 apply_res; /* 1 for applying calibration results to HW */ - __le32 reserved; -} __attribute__ ((packed)); - -struct iwm_lmac_cal_cfg_status { - struct iwm_lmac_cal_cfg_elt init; - struct iwm_lmac_cal_cfg_elt periodic; - __le32 flags; /* CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_AFTER_MSK */ -} __attribute__ ((packed)); - -struct iwm_lmac_cal_cfg_cmd { - struct iwm_lmac_cal_cfg_status ucode_cfg; - struct iwm_lmac_cal_cfg_status driver_cfg; - __le32 reserved; -} __attribute__ ((packed)); - -struct iwm_lmac_cal_cfg_resp { - __le32 status; -} __attribute__ ((packed)); - -#define IWM_CARD_STATE_SW_HW_ENABLED 0x00 -#define IWM_CARD_STATE_HW_DISABLED 0x01 -#define IWM_CARD_STATE_SW_DISABLED 0x02 -#define IWM_CARD_STATE_CTKILL_DISABLED 0x04 -#define IWM_CARD_STATE_IS_RXON 0x10 - -struct iwm_lmac_card_state { - __le32 flags; -} __attribute__ ((packed)); - -/** - * COEX_PRIORITY_TABLE_CMD - * - * Priority entry for each state - * Will keep two tables, for STA and WIPAN - */ -enum { - /* UN-ASSOCIATION PART */ - COEX_UNASSOC_IDLE = 0, - COEX_UNASSOC_MANUAL_SCAN, - COEX_UNASSOC_AUTO_SCAN, - - /* CALIBRATION */ - COEX_CALIBRATION, - COEX_PERIODIC_CALIBRATION, - - /* CONNECTION */ - COEX_CONNECTION_ESTAB, - - /* ASSOCIATION PART */ - COEX_ASSOCIATED_IDLE, - COEX_ASSOC_MANUAL_SCAN, - COEX_ASSOC_AUTO_SCAN, - COEX_ASSOC_ACTIVE_LEVEL, - - /* RF ON/OFF */ - COEX_RF_ON, - COEX_RF_OFF, - COEX_STAND_ALONE_DEBUG, - - /* IPNN */ - COEX_IPAN_ASSOC_LEVEL, - - /* RESERVED */ - COEX_RSRVD1, - COEX_RSRVD2, - - COEX_EVENTS_NUM -}; - -#define COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK 0x1 -#define COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK 0x2 -#define COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK 0x4 - -struct coex_event { - u8 req_prio; - u8 win_med_prio; - u8 reserved; - u8 flags; -} __attribute__ ((packed)); - -#define COEX_FLAGS_STA_TABLE_VALID_MSK 0x1 -#define COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK 0x4 -#define COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK 0x8 -#define COEX_FLAGS_COEX_ENABLE_MSK 0x80 - -struct iwm_coex_prio_table_cmd { - u8 flags; - u8 reserved[3]; - struct coex_event sta_prio[COEX_EVENTS_NUM]; -} __attribute__ ((packed)); - -/* Coexistence definitions - * - * Constants to fill in the Priorities' Tables - * RP - Requested Priority - * WP - Win Medium Priority: priority assigned when the contention has been won - * FLAGS - Combination of COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK and - * COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK - */ - -#define COEX_UNASSOC_IDLE_FLAGS 0 -#define COEX_UNASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) -#define COEX_UNASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) -#define COEX_CALIBRATION_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) -#define COEX_PERIODIC_CALIBRATION_FLAGS 0 -/* COEX_CONNECTION_ESTAB: we need DELAY_MEDIUM_FREE_NTFY to let WiMAX - * disconnect from network. */ -#define COEX_CONNECTION_ESTAB_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ - COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) -#define COEX_ASSOCIATED_IDLE_FLAGS 0 -#define COEX_ASSOC_MANUAL_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) -#define COEX_ASSOC_AUTO_SCAN_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) -#define COEX_ASSOC_ACTIVE_LEVEL_FLAGS 0 -#define COEX_RF_ON_FLAGS 0 -#define COEX_RF_OFF_FLAGS 0 -#define COEX_STAND_ALONE_DEBUG_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK) -#define COEX_IPAN_ASSOC_LEVEL_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ - COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) -#define COEX_RSRVD1_FLAGS 0 -#define COEX_RSRVD2_FLAGS 0 -/* XOR_RF_ON is the event wrapping all radio ownership. We need - * DELAY_MEDIUM_FREE_NTFY to let WiMAX disconnect from network. */ -#define COEX_XOR_RF_ON_FLAGS (COEX_EVT_FLAG_MEDIUM_FREE_NTFY_MSK | \ - COEX_EVT_FLAG_MEDIUM_ACTV_NTFY_MSK | \ - COEX_EVT_FLAG_DELAY_MEDIUM_FREE_NTFY_MSK) - -/* LMAC OP CODES */ -#define REPLY_PAD 0x0 -#define REPLY_ALIVE 0x1 -#define REPLY_ERROR 0x2 -#define REPLY_ECHO 0x3 -#define REPLY_HALT 0x6 - -/* RXON state commands */ -#define REPLY_RX_ON 0x10 -#define REPLY_RX_ON_ASSOC 0x11 -#define REPLY_RX_OFF 0x12 -#define REPLY_QOS_PARAM 0x13 -#define REPLY_RX_ON_TIMING 0x14 -#define REPLY_INTERNAL_QOS_PARAM 0x15 -#define REPLY_RX_INT_TIMEOUT_CNFG 0x16 -#define REPLY_NULL 0x17 - -/* Multi-Station support */ -#define REPLY_ADD_STA 0x18 -#define REPLY_REMOVE_STA 0x19 -#define REPLY_RESET_ALL_STA 0x1a - -/* RX, TX */ -#define REPLY_ALM_RX 0x1b -#define REPLY_TX 0x1c -#define REPLY_TXFIFO_FLUSH 0x1e - -/* MISC commands */ -#define REPLY_MGMT_MCAST_KEY 0x1f -#define REPLY_WEPKEY 0x20 -#define REPLY_INIT_IV 0x21 -#define REPLY_WRITE_MIB 0x22 -#define REPLY_READ_MIB 0x23 -#define REPLY_RADIO_FE 0x24 -#define REPLY_TXFIFO_CFG 0x25 -#define REPLY_WRITE_READ 0x26 -#define REPLY_INSTALL_SEC_KEY 0x27 - - -#define REPLY_RATE_SCALE 0x47 -#define REPLY_LEDS_CMD 0x48 -#define REPLY_TX_LINK_QUALITY_CMD 0x4e -#define REPLY_ANA_MIB_OVERRIDE_CMD 0x4f -#define REPLY_WRITE2REG_CMD 0x50 - -/* winfi-wifi coexistence */ -#define COEX_PRIORITY_TABLE_CMD 0x5a -#define COEX_MEDIUM_NOTIFICATION 0x5b -#define COEX_EVENT_CMD 0x5c - -/* more Protocol and Protocol-test commands */ -#define REPLY_MAX_SLEEP_TIME_CMD 0x61 -#define CALIBRATION_CFG_CMD 0x65 -#define CALIBRATION_RES_NOTIFICATION 0x66 -#define CALIBRATION_COMPLETE_NOTIFICATION 0x67 - -/* Measurements */ -#define REPLY_QUIET_CMD 0x71 -#define REPLY_CHANNEL_SWITCH 0x72 -#define CHANNEL_SWITCH_NOTIFICATION 0x73 - -#define REPLY_SPECTRUM_MEASUREMENT_CMD 0x74 -#define SPECTRUM_MEASURE_NOTIFICATION 0x75 -#define REPLY_MEASUREMENT_ABORT_CMD 0x76 - -/* Power Management */ -#define POWER_TABLE_CMD 0x77 -#define SAVE_RESTORE_ADRESS_CMD 0x78 -#define REPLY_WATERMARK_CMD 0x79 -#define PM_DEBUG_STATISTIC_NOTIFIC 0x7B -#define PD_FLUSH_N_NOTIFICATION 0x7C - -/* Scan commands and notifications */ -#define REPLY_SCAN_REQUEST_CMD 0x80 -#define REPLY_SCAN_ABORT_CMD 0x81 -#define SCAN_START_NOTIFICATION 0x82 -#define SCAN_RESULTS_NOTIFICATION 0x83 -#define SCAN_COMPLETE_NOTIFICATION 0x84 - -/* Continuous TX commands */ -#define REPLY_CONT_TX_CMD 0x85 -#define END_OF_CONT_TX_NOTIFICATION 0x86 - -/* Timer/Eeprom commands */ -#define TIMER_CMD 0x87 -#define EEPROM_WRITE_CMD 0x88 - -/* PAPD commands */ -#define FEEDBACK_REQUEST_NOTIFICATION 0x8b -#define REPLY_CW_CMD 0x8c - -/* IBSS/AP commands Continue */ -#define BEACON_NOTIFICATION 0x90 -#define REPLY_TX_BEACON 0x91 -#define REPLY_REQUEST_ATIM 0x93 -#define WHO_IS_AWAKE_NOTIFICATION 0x94 -#define TX_PWR_DBM_LIMIT_CMD 0x95 -#define QUIET_NOTIFICATION 0x96 -#define TX_PWR_TABLE_CMD 0x97 -#define TX_ANT_CONFIGURATION_CMD 0x98 -#define MEASURE_ABORT_NOTIFICATION 0x99 -#define REPLY_CALIBRATION_TUNE 0x9a - -/* bt config command */ -#define REPLY_BT_CONFIG 0x9b -#define REPLY_STATISTICS_CMD 0x9c -#define STATISTICS_NOTIFICATION 0x9d - -/* RF-KILL commands and notifications */ -#define REPLY_CARD_STATE_CMD 0xa0 -#define CARD_STATE_NOTIFICATION 0xa1 - -/* Missed beacons notification */ -#define MISSED_BEACONS_NOTIFICATION 0xa2 -#define MISSED_BEACONS_NOTIFICATION_TH_CMD 0xa3 - -#define REPLY_CT_KILL_CONFIG_CMD 0xa4 - -/* HD commands and notifications */ -#define REPLY_HD_PARAMS_CMD 0xa6 -#define HD_PARAMS_NOTIFICATION 0xa7 -#define SENSITIVITY_CMD 0xa8 -#define U_APSD_PARAMS_CMD 0xa9 -#define NOISY_PLATFORM_CMD 0xaa -#define ILLEGAL_CMD 0xac -#define REPLY_PHY_CALIBRATION_CMD 0xb0 -#define REPLAY_RX_GAIN_CALIB_CMD 0xb1 - -/* WiPAN commands */ -#define REPLY_WIPAN_PARAMS_CMD 0xb2 -#define REPLY_WIPAN_RX_ON_CMD 0xb3 -#define REPLY_WIPAN_RX_ON_TIMING 0xb4 -#define REPLY_WIPAN_TX_PWR_TABLE_CMD 0xb5 -#define REPLY_WIPAN_RXON_ASSOC_CMD 0xb6 -#define REPLY_WIPAN_QOS_PARAM 0xb7 -#define WIPAN_REPLY_WEPKEY 0xb8 - -/* BeamForming commands */ -#define BEAMFORMER_CFG_CMD 0xba -#define BEAMFORMEE_NOTIFICATION 0xbb - -/* TGn new Commands */ -#define REPLY_RX_PHY_CMD 0xc0 -#define REPLY_RX_MPDU_CMD 0xc1 -#define REPLY_MULTICAST_HASH 0xc2 -#define REPLY_KDR_RX 0xc3 -#define REPLY_RX_DSP_EXT_INFO 0xc4 -#define REPLY_COMPRESSED_BA 0xc5 - -/* PNC commands */ -#define PNC_CONFIG_CMD 0xc8 -#define PNC_UPDATE_TABLE_CMD 0xc9 -#define XVT_GENERAL_CTRL_CMD 0xca -#define REPLY_LEGACY_RADIO_FE 0xdd - -/* WoWLAN commands */ -#define WOWLAN_PATTERNS 0xe0 -#define WOWLAN_WAKEUP_FILTER 0xe1 -#define WOWLAN_TSC_RSC_PARAM 0xe2 -#define WOWLAN_TKIP_PARAM 0xe3 -#define WOWLAN_KEK_KCK_MATERIAL 0xe4 -#define WOWLAN_GET_STATUSES 0xe5 -#define WOWLAN_TX_POWER_PER_DB 0xe6 -#define REPLY_WOWLAN_GET_STATUSES WOWLAN_GET_STATUSES - -#define REPLY_DEBUG_CMD 0xf0 -#define REPLY_DSP_DEBUG_CMD 0xf1 -#define REPLY_DEBUG_MONITOR_CMD 0xf2 -#define REPLY_DEBUG_XVT_CMD 0xf3 -#define REPLY_DEBUG_DC_CALIB 0xf4 -#define REPLY_DYNAMIC_BP 0xf5 - -/* General purpose Commands */ -#define REPLY_GP1_CMD 0xfa -#define REPLY_GP2_CMD 0xfb -#define REPLY_GP3_CMD 0xfc -#define REPLY_GP4_CMD 0xfd -#define REPLY_REPLAY_WRAPPER 0xfe -#define REPLY_FRAME_DURATION_CALC_CMD 0xff - -#define LMAC_COMMAND_ID_MAX 0xff -#define LMAC_COMMAND_ID_NUM (LMAC_COMMAND_ID_MAX + 1) - - -/* Calibration */ - -enum { - PHY_CALIBRATE_DC_CMD = 0, - PHY_CALIBRATE_LO_CMD = 1, - PHY_CALIBRATE_RX_BB_CMD = 2, - PHY_CALIBRATE_TX_IQ_CMD = 3, - PHY_CALIBRATE_RX_IQ_CMD = 4, - PHY_CALIBRATION_NOISE_CMD = 5, - PHY_CALIBRATE_AGC_TABLE_CMD = 6, - PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 7, - PHY_CALIBRATE_OPCODES_NUM, - SHILOH_PHY_CALIBRATE_DC_CMD = 8, - SHILOH_PHY_CALIBRATE_LO_CMD = 9, - SHILOH_PHY_CALIBRATE_RX_BB_CMD = 10, - SHILOH_PHY_CALIBRATE_TX_IQ_CMD = 11, - SHILOH_PHY_CALIBRATE_RX_IQ_CMD = 12, - SHILOH_PHY_CALIBRATION_NOISE_CMD = 13, - SHILOH_PHY_CALIBRATE_AGC_TABLE_CMD = 14, - SHILOH_PHY_CALIBRATE_CRYSTAL_FRQ_CMD = 15, - SHILOH_PHY_CALIBRATE_BASE_BAND_CMD = 16, - SHILOH_PHY_CALIBRATE_TXIQ_PERIODIC_CMD = 17, - CALIBRATION_CMD_NUM, -}; - -enum { - CALIB_CFG_RX_BB_IDX = 0, - CALIB_CFG_DC_IDX = 1, - CALIB_CFG_LO_IDX = 2, - CALIB_CFG_TX_IQ_IDX = 3, - CALIB_CFG_RX_IQ_IDX = 4, - CALIB_CFG_NOISE_IDX = 5, - CALIB_CFG_CRYSTAL_IDX = 6, - CALIB_CFG_TEMPERATURE_IDX = 7, - CALIB_CFG_PAPD_IDX = 8, - CALIB_CFG_LAST_IDX = CALIB_CFG_PAPD_IDX, - CALIB_CFG_MODULE_NUM, -}; - -#define IWM_CALIB_MAP_INIT_MSK 0xFFFF -#define IWM_CALIB_MAP_PER_LMAC(m) ((m & 0xFF0000) >> 16) -#define IWM_CALIB_MAP_PER_UMAC(m) ((m & 0xFF000000) >> 24) -#define IWM_CALIB_OPCODE_TO_INDEX(op) (op - PHY_CALIBRATE_OPCODES_NUM) - -struct iwm_lmac_calib_hdr { - u8 opcode; - u8 first_grp; - u8 grp_num; - u8 all_data_valid; -} __attribute__ ((packed)); - -#define IWM_LMAC_CALIB_FREQ_GROUPS_NR 7 -#define IWM_CALIB_FREQ_GROUPS_NR 5 -#define IWM_CALIB_DC_MODES_NR 12 - -struct iwm_calib_rxiq_entry { - u16 ptam_postdist_ars; - u16 ptam_postdist_arc; -} __attribute__ ((packed)); - -struct iwm_calib_rxiq_group { - struct iwm_calib_rxiq_entry mode[IWM_CALIB_DC_MODES_NR]; -} __attribute__ ((packed)); - -struct iwm_lmac_calib_rxiq { - struct iwm_calib_rxiq_group group[IWM_LMAC_CALIB_FREQ_GROUPS_NR]; -} __attribute__ ((packed)); - -struct iwm_calib_rxiq { - struct iwm_lmac_calib_hdr hdr; - struct iwm_calib_rxiq_group group[IWM_CALIB_FREQ_GROUPS_NR]; -} __attribute__ ((packed)); - -#define LMAC_STA_ID_SEED 0x0f -#define LMAC_STA_ID_POS 0 - -#define LMAC_STA_COLOR_SEED 0x7 -#define LMAC_STA_COLOR_POS 4 - -struct iwm_lmac_power_report { - u8 pa_status; - u8 pa_integ_res_A[3]; - u8 pa_integ_res_B[3]; - u8 pa_integ_res_C[3]; -} __attribute__ ((packed)); - -struct iwm_lmac_tx_resp { - u8 frame_cnt; /* 1-no aggregation, greater then 1 - aggregation */ - u8 bt_kill_cnt; - __le16 retry_cnt; - __le32 initial_tx_rate; - __le16 wireless_media_time; - struct iwm_lmac_power_report power_report; - __le32 tfd_info; - __le16 seq_ctl; - __le16 byte_cnt; - u8 tlc_rate_info; - u8 ra_tid; - __le16 frame_ctl; - __le32 status; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c deleted file mode 100644 index 222eb2cf1b30..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/main.c +++ /dev/null @@ -1,760 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#include -#include -#include -#include -#include - -#include "iwm.h" -#include "debug.h" -#include "bus.h" -#include "umac.h" -#include "commands.h" -#include "hal.h" -#include "fw.h" -#include "rx.h" - -static struct iwm_conf def_iwm_conf = { - - .sdio_ior_timeout = 5000, - .calib_map = BIT(CALIB_CFG_DC_IDX) | - BIT(CALIB_CFG_LO_IDX) | - BIT(CALIB_CFG_TX_IQ_IDX) | - BIT(CALIB_CFG_RX_IQ_IDX) | - BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), - .expected_calib_map = BIT(PHY_CALIBRATE_DC_CMD) | - BIT(PHY_CALIBRATE_LO_CMD) | - BIT(PHY_CALIBRATE_TX_IQ_CMD) | - BIT(PHY_CALIBRATE_RX_IQ_CMD) | - BIT(SHILOH_PHY_CALIBRATE_BASE_BAND_CMD), - .reset_on_fatal_err = 1, - .auto_connect = 1, - .wimax_not_present = 0, - .enable_qos = 1, - .mode = UMAC_MODE_BSS, - - /* UMAC configuration */ - .power_index = 0, - .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, - .rts_threshold = IEEE80211_MAX_RTS_THRESHOLD, - .cts_to_self = 0, - - .assoc_timeout = 2, - .roam_timeout = 10, - .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G, - .coexist_mode = COEX_MODE_CM, - - /* IBSS */ - .ibss_band = UMAC_BAND_2GHZ, - .ibss_channel = 1, - - .mac_addr = {0x00, 0x02, 0xb3, 0x01, 0x02, 0x03}, -}; - -static int modparam_reset; -module_param_named(reset, modparam_reset, bool, 0644); -MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])"); - -int iwm_mode_to_nl80211_iftype(int mode) -{ - switch (mode) { - case UMAC_MODE_BSS: - return NL80211_IFTYPE_STATION; - case UMAC_MODE_IBSS: - return NL80211_IFTYPE_ADHOC; - default: - return NL80211_IFTYPE_UNSPECIFIED; - } - - return 0; -} - -static void iwm_statistics_request(struct work_struct *work) -{ - struct iwm_priv *iwm = - container_of(work, struct iwm_priv, stats_request.work); - - iwm_send_umac_stats_req(iwm, 0); -} - -static void iwm_disconnect_work(struct work_struct *work) -{ - struct iwm_priv *iwm = - container_of(work, struct iwm_priv, disconnect.work); - - if (iwm->umac_profile_active) - iwm_invalidate_mlme_profile(iwm); - - clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); - iwm->umac_profile_active = 0; - memset(iwm->bssid, 0, ETH_ALEN); - iwm->channel = 0; - - iwm_link_off(iwm); - - wake_up_interruptible(&iwm->mlme_queue); - - cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, GFP_KERNEL); -} - -static int __iwm_up(struct iwm_priv *iwm); -static int __iwm_down(struct iwm_priv *iwm); - -static void iwm_reset_worker(struct work_struct *work) -{ - struct iwm_priv *iwm; - struct iwm_umac_profile *profile = NULL; - int uninitialized_var(ret), retry = 0; - - iwm = container_of(work, struct iwm_priv, reset_worker); - - /* - * XXX: The iwm->mutex is introduced purely for this reset work, - * because the other users for iwm_up and iwm_down are only netdev - * ndo_open and ndo_stop which are already protected by rtnl. - * Please remove iwm->mutex together if iwm_reset_worker() is not - * required in the future. - */ - if (!mutex_trylock(&iwm->mutex)) { - IWM_WARN(iwm, "We are in the middle of interface bringing " - "UP/DOWN. Skip driver resetting.\n"); - return; - } - - if (iwm->umac_profile_active) { - profile = kmalloc(sizeof(struct iwm_umac_profile), GFP_KERNEL); - if (profile) - memcpy(profile, iwm->umac_profile, sizeof(*profile)); - else - IWM_ERR(iwm, "Couldn't alloc memory for profile\n"); - } - - __iwm_down(iwm); - - while (retry++ < 3) { - ret = __iwm_up(iwm); - if (!ret) - break; - - schedule_timeout_uninterruptible(10 * HZ); - } - - if (ret) { - IWM_WARN(iwm, "iwm_up() failed: %d\n", ret); - - kfree(profile); - goto out; - } - - if (profile) { - IWM_DBG_MLME(iwm, DBG, "Resend UMAC profile\n"); - memcpy(iwm->umac_profile, profile, sizeof(*profile)); - iwm_send_mlme_profile(iwm); - kfree(profile); - } else - clear_bit(IWM_STATUS_RESETTING, &iwm->status); - - out: - mutex_unlock(&iwm->mutex); -} - -static void iwm_watchdog(unsigned long data) -{ - struct iwm_priv *iwm = (struct iwm_priv *)data; - - IWM_WARN(iwm, "Watchdog expired: UMAC stalls!\n"); - - if (modparam_reset) - iwm_resetting(iwm); -} - -int iwm_priv_init(struct iwm_priv *iwm) -{ - int i; - char name[32]; - - iwm->status = 0; - INIT_LIST_HEAD(&iwm->pending_notif); - init_waitqueue_head(&iwm->notif_queue); - init_waitqueue_head(&iwm->nonwifi_queue); - init_waitqueue_head(&iwm->wifi_ntfy_queue); - init_waitqueue_head(&iwm->mlme_queue); - memcpy(&iwm->conf, &def_iwm_conf, sizeof(struct iwm_conf)); - spin_lock_init(&iwm->tx_credit.lock); - INIT_LIST_HEAD(&iwm->wifi_pending_cmd); - INIT_LIST_HEAD(&iwm->nonwifi_pending_cmd); - iwm->wifi_seq_num = UMAC_WIFI_SEQ_NUM_BASE; - iwm->nonwifi_seq_num = UMAC_NONWIFI_SEQ_NUM_BASE; - spin_lock_init(&iwm->cmd_lock); - iwm->scan_id = 1; - INIT_DELAYED_WORK(&iwm->stats_request, iwm_statistics_request); - INIT_DELAYED_WORK(&iwm->disconnect, iwm_disconnect_work); - INIT_WORK(&iwm->reset_worker, iwm_reset_worker); - INIT_LIST_HEAD(&iwm->bss_list); - - skb_queue_head_init(&iwm->rx_list); - INIT_LIST_HEAD(&iwm->rx_tickets); - for (i = 0; i < IWM_RX_ID_HASH; i++) - INIT_LIST_HEAD(&iwm->rx_packets[i]); - - INIT_WORK(&iwm->rx_worker, iwm_rx_worker); - - iwm->rx_wq = create_singlethread_workqueue(KBUILD_MODNAME "_rx"); - if (!iwm->rx_wq) - return -EAGAIN; - - for (i = 0; i < IWM_TX_QUEUES; i++) { - INIT_WORK(&iwm->txq[i].worker, iwm_tx_worker); - snprintf(name, 32, KBUILD_MODNAME "_tx_%d", i); - iwm->txq[i].id = i; - iwm->txq[i].wq = create_singlethread_workqueue(name); - if (!iwm->txq[i].wq) - return -EAGAIN; - - skb_queue_head_init(&iwm->txq[i].queue); - } - - for (i = 0; i < IWM_NUM_KEYS; i++) - memset(&iwm->keys[i], 0, sizeof(struct iwm_key)); - - iwm->default_key = -1; - - init_timer(&iwm->watchdog); - iwm->watchdog.function = iwm_watchdog; - iwm->watchdog.data = (unsigned long)iwm; - mutex_init(&iwm->mutex); - - iwm->last_fw_err = kzalloc(sizeof(struct iwm_fw_error_hdr), - GFP_KERNEL); - if (iwm->last_fw_err == NULL) - return -ENOMEM; - - return 0; -} - -void iwm_priv_deinit(struct iwm_priv *iwm) -{ - int i; - - for (i = 0; i < IWM_TX_QUEUES; i++) - destroy_workqueue(iwm->txq[i].wq); - - destroy_workqueue(iwm->rx_wq); - kfree(iwm->last_fw_err); -} - -/* - * We reset all the structures, and we reset the UMAC. - * After calling this routine, you're expected to reload - * the firmware. - */ -void iwm_reset(struct iwm_priv *iwm) -{ - struct iwm_notif *notif, *next; - - if (test_bit(IWM_STATUS_READY, &iwm->status)) - iwm_target_reset(iwm); - - if (test_bit(IWM_STATUS_RESETTING, &iwm->status)) { - iwm->status = 0; - set_bit(IWM_STATUS_RESETTING, &iwm->status); - } else - iwm->status = 0; - iwm->scan_id = 1; - - list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { - list_del(¬if->pending); - kfree(notif->buf); - kfree(notif); - } - - iwm_cmd_flush(iwm); - - flush_workqueue(iwm->rx_wq); - - iwm_link_off(iwm); -} - -void iwm_resetting(struct iwm_priv *iwm) -{ - set_bit(IWM_STATUS_RESETTING, &iwm->status); - - schedule_work(&iwm->reset_worker); -} - -/* - * Notification code: - * - * We're faced with the following issue: Any host command can - * have an answer or not, and if there's an answer to expect, - * it can be treated synchronously or asynchronously. - * To work around the synchronous answer case, we implemented - * our notification mechanism. - * When a code path needs to wait for a command response - * synchronously, it calls notif_handle(), which waits for the - * right notification to show up, and then process it. Before - * starting to wait, it registered as a waiter for this specific - * answer (by toggling a bit in on of the handler_map), so that - * the rx code knows that it needs to send a notification to the - * waiting processes. It does so by calling iwm_notif_send(), - * which adds the notification to the pending notifications list, - * and then wakes the waiting processes up. - */ -int iwm_notif_send(struct iwm_priv *iwm, struct iwm_wifi_cmd *cmd, - u8 cmd_id, u8 source, u8 *buf, unsigned long buf_size) -{ - struct iwm_notif *notif; - - notif = kzalloc(sizeof(struct iwm_notif), GFP_KERNEL); - if (!notif) { - IWM_ERR(iwm, "Couldn't alloc memory for notification\n"); - return -ENOMEM; - } - - INIT_LIST_HEAD(¬if->pending); - notif->cmd = cmd; - notif->cmd_id = cmd_id; - notif->src = source; - notif->buf = kzalloc(buf_size, GFP_KERNEL); - if (!notif->buf) { - IWM_ERR(iwm, "Couldn't alloc notification buffer\n"); - kfree(notif); - return -ENOMEM; - } - notif->buf_size = buf_size; - memcpy(notif->buf, buf, buf_size); - list_add_tail(¬if->pending, &iwm->pending_notif); - - wake_up_interruptible(&iwm->notif_queue); - - return 0; -} - -static struct iwm_notif *iwm_notif_find(struct iwm_priv *iwm, u32 cmd, - u8 source) -{ - struct iwm_notif *notif, *next; - - list_for_each_entry_safe(notif, next, &iwm->pending_notif, pending) { - if ((notif->cmd_id == cmd) && (notif->src == source)) { - list_del(¬if->pending); - return notif; - } - } - - return NULL; -} - -static struct iwm_notif *iwm_notif_wait(struct iwm_priv *iwm, u32 cmd, - u8 source, long timeout) -{ - int ret; - struct iwm_notif *notif; - unsigned long *map = NULL; - - switch (source) { - case IWM_SRC_LMAC: - map = &iwm->lmac_handler_map[0]; - break; - case IWM_SRC_UMAC: - map = &iwm->umac_handler_map[0]; - break; - case IWM_SRC_UDMA: - map = &iwm->udma_handler_map[0]; - break; - } - - set_bit(cmd, map); - - ret = wait_event_interruptible_timeout(iwm->notif_queue, - ((notif = iwm_notif_find(iwm, cmd, source)) != NULL), - timeout); - clear_bit(cmd, map); - - if (!ret) - return NULL; - - return notif; -} - -int iwm_notif_handle(struct iwm_priv *iwm, u32 cmd, u8 source, long timeout) -{ - int ret; - struct iwm_notif *notif; - - notif = iwm_notif_wait(iwm, cmd, source, timeout); - if (!notif) - return -ETIME; - - ret = iwm_rx_handle_resp(iwm, notif->buf, notif->buf_size, notif->cmd); - kfree(notif->buf); - kfree(notif); - - return ret; -} - -static int iwm_config_boot_params(struct iwm_priv *iwm) -{ - struct iwm_udma_nonwifi_cmd target_cmd; - int ret; - - /* check Wimax is off and config debug monitor */ - if (iwm->conf.wimax_not_present) { - u32 data1 = 0x1f; - u32 addr1 = 0x606BE258; - - u32 data2_set = 0x0; - u32 data2_clr = 0x1; - u32 addr2 = 0x606BE100; - - u32 data3 = 0x1; - u32 addr3 = 0x606BEC00; - - target_cmd.resp = 0; - target_cmd.handle_by_hw = 0; - target_cmd.eop = 1; - - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; - target_cmd.addr = cpu_to_le32(addr1); - target_cmd.op1_sz = cpu_to_le32(sizeof(u32)); - target_cmd.op2 = 0; - - ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1); - if (ret < 0) { - IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); - return ret; - } - - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE; - target_cmd.addr = cpu_to_le32(addr2); - target_cmd.op1_sz = cpu_to_le32(data2_set); - target_cmd.op2 = cpu_to_le32(data2_clr); - - ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data1); - if (ret < 0) { - IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); - return ret; - } - - target_cmd.opcode = UMAC_HDI_OUT_OPCODE_WRITE; - target_cmd.addr = cpu_to_le32(addr3); - target_cmd.op1_sz = cpu_to_le32(sizeof(u32)); - target_cmd.op2 = 0; - - ret = iwm_hal_send_target_cmd(iwm, &target_cmd, &data3); - if (ret < 0) { - IWM_ERR(iwm, "iwm_hal_send_target_cmd failed\n"); - return ret; - } - } - - return 0; -} - -void iwm_init_default_profile(struct iwm_priv *iwm, - struct iwm_umac_profile *profile) -{ - memset(profile, 0, sizeof(struct iwm_umac_profile)); - - profile->sec.auth_type = UMAC_AUTH_TYPE_OPEN; - profile->sec.flags = UMAC_SEC_FLG_LEGACY_PROFILE; - profile->sec.ucast_cipher = UMAC_CIPHER_TYPE_NONE; - profile->sec.mcast_cipher = UMAC_CIPHER_TYPE_NONE; - - if (iwm->conf.enable_qos) - profile->flags |= cpu_to_le16(UMAC_PROFILE_QOS_ALLOWED); - - profile->wireless_mode = iwm->conf.wireless_mode; - profile->mode = cpu_to_le32(iwm->conf.mode); - - profile->ibss.atim = 0; - profile->ibss.beacon_interval = 100; - profile->ibss.join_only = 0; - profile->ibss.band = iwm->conf.ibss_band; - profile->ibss.channel = iwm->conf.ibss_channel; -} - -void iwm_link_on(struct iwm_priv *iwm) -{ - netif_carrier_on(iwm_to_ndev(iwm)); - netif_tx_wake_all_queues(iwm_to_ndev(iwm)); - - iwm_send_umac_stats_req(iwm, 0); -} - -void iwm_link_off(struct iwm_priv *iwm) -{ - struct iw_statistics *wstats = &iwm->wstats; - int i; - - netif_tx_stop_all_queues(iwm_to_ndev(iwm)); - netif_carrier_off(iwm_to_ndev(iwm)); - - for (i = 0; i < IWM_TX_QUEUES; i++) { - skb_queue_purge(&iwm->txq[i].queue); - - iwm->txq[i].concat_count = 0; - iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf; - - flush_workqueue(iwm->txq[i].wq); - } - - iwm_rx_free(iwm); - - cancel_delayed_work_sync(&iwm->stats_request); - memset(wstats, 0, sizeof(struct iw_statistics)); - wstats->qual.updated = IW_QUAL_ALL_INVALID; - - kfree(iwm->req_ie); - iwm->req_ie = NULL; - iwm->req_ie_len = 0; - kfree(iwm->resp_ie); - iwm->resp_ie = NULL; - iwm->resp_ie_len = 0; - - del_timer_sync(&iwm->watchdog); -} - -static void iwm_bss_list_clean(struct iwm_priv *iwm) -{ - struct iwm_bss_info *bss, *next; - - list_for_each_entry_safe(bss, next, &iwm->bss_list, node) { - list_del(&bss->node); - kfree(bss->bss); - kfree(bss); - } -} - -static int iwm_channels_init(struct iwm_priv *iwm) -{ - int ret; - - ret = iwm_send_umac_channel_list(iwm); - if (ret) { - IWM_ERR(iwm, "Send channel list failed\n"); - return ret; - } - - ret = iwm_notif_handle(iwm, UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST, - IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Didn't get a channel list notification\n"); - return ret; - } - - return 0; -} - -static int __iwm_up(struct iwm_priv *iwm) -{ - int ret; - struct iwm_notif *notif_reboot, *notif_ack = NULL; - - ret = iwm_bus_enable(iwm); - if (ret) { - IWM_ERR(iwm, "Couldn't enable function\n"); - return ret; - } - - iwm_rx_setup_handlers(iwm); - - /* Wait for initial BARKER_REBOOT from hardware */ - notif_reboot = iwm_notif_wait(iwm, IWM_BARKER_REBOOT_NOTIFICATION, - IWM_SRC_UDMA, 2 * HZ); - if (!notif_reboot) { - IWM_ERR(iwm, "Wait for REBOOT_BARKER timeout\n"); - goto err_disable; - } - - /* We send the barker back */ - ret = iwm_bus_send_chunk(iwm, notif_reboot->buf, 16); - if (ret) { - IWM_ERR(iwm, "REBOOT barker response failed\n"); - kfree(notif_reboot); - goto err_disable; - } - - kfree(notif_reboot->buf); - kfree(notif_reboot); - - /* Wait for ACK_BARKER from hardware */ - notif_ack = iwm_notif_wait(iwm, IWM_ACK_BARKER_NOTIFICATION, - IWM_SRC_UDMA, 2 * HZ); - if (!notif_ack) { - IWM_ERR(iwm, "Wait for ACK_BARKER timeout\n"); - goto err_disable; - } - - kfree(notif_ack->buf); - kfree(notif_ack); - - /* We start to config static boot parameters */ - ret = iwm_config_boot_params(iwm); - if (ret) { - IWM_ERR(iwm, "Config boot parameters failed\n"); - goto err_disable; - } - - ret = iwm_read_mac(iwm, iwm_to_ndev(iwm)->dev_addr); - if (ret) { - IWM_ERR(iwm, "MAC reading failed\n"); - goto err_disable; - } - - /* We can load the FWs */ - ret = iwm_load_fw(iwm); - if (ret) { - IWM_ERR(iwm, "FW loading failed\n"); - goto err_disable; - } - - /* We configure the UMAC and enable the wifi module */ - ret = iwm_send_umac_config(iwm, - cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_CORE_EN) | - cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_LINK_EN) | - cpu_to_le32(UMAC_RST_CTRL_FLG_WIFI_MLME_EN)); - if (ret) { - IWM_ERR(iwm, "UMAC config failed\n"); - goto err_fw; - } - - ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS, - IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Didn't get a wifi core status notification\n"); - goto err_fw; - } - - if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN | - UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) { - IWM_DBG_BOOT(iwm, DBG, "Not all cores enabled:0x%x\n", - iwm->core_enabled); - ret = iwm_notif_handle(iwm, UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS, - IWM_SRC_UMAC, WAIT_NOTIF_TIMEOUT); - if (ret) { - IWM_ERR(iwm, "Didn't get a core status notification\n"); - goto err_fw; - } - - if (iwm->core_enabled != (UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN | - UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN)) { - IWM_ERR(iwm, "Not all cores enabled: 0x%x\n", - iwm->core_enabled); - goto err_fw; - } else { - IWM_INFO(iwm, "All cores enabled\n"); - } - } - - ret = iwm_channels_init(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't init channels\n"); - goto err_fw; - } - - /* Set the READY bit to indicate interface is brought up successfully */ - set_bit(IWM_STATUS_READY, &iwm->status); - - return 0; - - err_fw: - iwm_eeprom_exit(iwm); - - err_disable: - ret = iwm_bus_disable(iwm); - if (ret < 0) - IWM_ERR(iwm, "Couldn't disable function\n"); - - return -EIO; -} - -int iwm_up(struct iwm_priv *iwm) -{ - int ret; - - mutex_lock(&iwm->mutex); - ret = __iwm_up(iwm); - mutex_unlock(&iwm->mutex); - - return ret; -} - -static int __iwm_down(struct iwm_priv *iwm) -{ - int ret; - - /* The interface is already down */ - if (!test_bit(IWM_STATUS_READY, &iwm->status)) - return 0; - - if (iwm->scan_request) { - cfg80211_scan_done(iwm->scan_request, true); - iwm->scan_request = NULL; - } - - clear_bit(IWM_STATUS_READY, &iwm->status); - - iwm_eeprom_exit(iwm); - iwm_bss_list_clean(iwm); - iwm_init_default_profile(iwm, iwm->umac_profile); - iwm->umac_profile_active = false; - iwm->default_key = -1; - iwm->core_enabled = 0; - - ret = iwm_bus_disable(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't disable function\n"); - return ret; - } - - return 0; -} - -int iwm_down(struct iwm_priv *iwm) -{ - int ret; - - mutex_lock(&iwm->mutex); - ret = __iwm_down(iwm); - mutex_unlock(&iwm->mutex); - - return ret; -} diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c deleted file mode 100644 index 35ec006c2d2c..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/netdev.c +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License version - * 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA - * 02110-1301, USA. - * - */ - -/* - * This is the netdev related hooks for iwm. - * - * Some interesting code paths: - * - * iwm_open() (Called at netdev interface bringup time) - * -> iwm_up() (main.c) - * -> iwm_bus_enable() - * -> if_sdio_enable() (In case of an SDIO bus) - * -> sdio_enable_func() - * -> iwm_notif_wait(BARKER_REBOOT) (wait for reboot barker) - * -> iwm_notif_wait(ACK_BARKER) (wait for ACK barker) - * -> iwm_load_fw() (fw.c) - * -> iwm_load_umac() - * -> iwm_load_lmac() (Calibration LMAC) - * -> iwm_load_lmac() (Operational LMAC) - * -> iwm_send_umac_config() - * - * iwm_stop() (Called at netdev interface bringdown time) - * -> iwm_down() - * -> iwm_bus_disable() - * -> if_sdio_disable() (In case of an SDIO bus) - * -> sdio_disable_func() - */ -#include - -#include "iwm.h" -#include "commands.h" -#include "cfg80211.h" -#include "debug.h" - -static int iwm_open(struct net_device *ndev) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - - return iwm_up(iwm); -} - -static int iwm_stop(struct net_device *ndev) -{ - struct iwm_priv *iwm = ndev_to_iwm(ndev); - - return iwm_down(iwm); -} - -/* - * iwm AC to queue mapping - * - * AC_VO -> queue 3 - * AC_VI -> queue 2 - * AC_BE -> queue 1 - * AC_BK -> queue 0 - */ -static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; - -static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - skb->priority = cfg80211_classify8021d(skb); - - return iwm_1d_to_queue[skb->priority]; -} - -static const struct net_device_ops iwm_netdev_ops = { - .ndo_open = iwm_open, - .ndo_stop = iwm_stop, - .ndo_start_xmit = iwm_xmit_frame, - .ndo_select_queue = iwm_select_queue, -}; - -void *iwm_if_alloc(int sizeof_bus, struct device *dev, - struct iwm_if_ops *if_ops) -{ - struct net_device *ndev; - struct wireless_dev *wdev; - struct iwm_priv *iwm; - int ret = 0; - - wdev = iwm_wdev_alloc(sizeof_bus, dev); - if (IS_ERR(wdev)) - return wdev; - - iwm = wdev_to_iwm(wdev); - iwm->bus_ops = if_ops; - iwm->wdev = wdev; - - ret = iwm_priv_init(iwm); - if (ret) { - dev_err(dev, "failed to init iwm_priv\n"); - goto out_wdev; - } - - wdev->iftype = iwm_mode_to_nl80211_iftype(iwm->conf.mode); - - ndev = alloc_netdev_mq(0, "wlan%d", ether_setup, IWM_TX_QUEUES); - if (!ndev) { - dev_err(dev, "no memory for network device instance\n"); - goto out_priv; - } - - ndev->netdev_ops = &iwm_netdev_ops; - ndev->ieee80211_ptr = wdev; - SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); - wdev->netdev = ndev; - - iwm->umac_profile = kmalloc(sizeof(struct iwm_umac_profile), - GFP_KERNEL); - if (!iwm->umac_profile) { - dev_err(dev, "Couldn't alloc memory for profile\n"); - goto out_profile; - } - - iwm_init_default_profile(iwm, iwm->umac_profile); - - return iwm; - - out_profile: - free_netdev(ndev); - - out_priv: - iwm_priv_deinit(iwm); - - out_wdev: - iwm_wdev_free(iwm); - return ERR_PTR(ret); -} - -void iwm_if_free(struct iwm_priv *iwm) -{ - if (!iwm_to_ndev(iwm)) - return; - - free_netdev(iwm_to_ndev(iwm)); - iwm_priv_deinit(iwm); - kfree(iwm->umac_profile); - iwm->umac_profile = NULL; - iwm_wdev_free(iwm); -} - -int iwm_if_add(struct iwm_priv *iwm) -{ - struct net_device *ndev = iwm_to_ndev(iwm); - int ret; - - ret = register_netdev(ndev); - if (ret < 0) { - dev_err(&ndev->dev, "Failed to register netdev: %d\n", ret); - return ret; - } - - return 0; -} - -void iwm_if_remove(struct iwm_priv *iwm) -{ - unregister_netdev(iwm_to_ndev(iwm)); -} diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c deleted file mode 100644 index 771a301003c9..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/rx.c +++ /dev/null @@ -1,1501 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "iwm.h" -#include "debug.h" -#include "hal.h" -#include "umac.h" -#include "lmac.h" -#include "commands.h" -#include "rx.h" -#include "cfg80211.h" -#include "eeprom.h" - -static int iwm_rx_check_udma_hdr(struct iwm_udma_in_hdr *hdr) -{ - if ((le32_to_cpu(hdr->cmd) == UMAC_PAD_TERMINAL) || - (le32_to_cpu(hdr->size) == UMAC_PAD_TERMINAL)) - return -EINVAL; - - return 0; -} - -static inline int iwm_rx_resp_size(struct iwm_udma_in_hdr *hdr) -{ - return ALIGN(le32_to_cpu(hdr->size) + sizeof(struct iwm_udma_in_hdr), - 16); -} - -/* - * Notification handlers: - * - * For every possible notification we can receive from the - * target, we have a handler. - * When we get a target notification, and there is no one - * waiting for it, it's just processed through the rx code - * path: - * - * iwm_rx_handle() - * -> iwm_rx_handle_umac() - * -> iwm_rx_handle_wifi() - * -> iwm_rx_handle_resp() - * -> iwm_ntf_*() - * - * OR - * - * -> iwm_rx_handle_non_wifi() - * - * If there are processes waiting for this notification, then - * iwm_rx_handle_wifi() just wakes those processes up and they - * grab the pending notification. - */ -static int iwm_ntf_error(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_error *error; - struct iwm_fw_error_hdr *fw_err; - - error = (struct iwm_umac_notif_error *)buf; - fw_err = &error->err; - - memcpy(iwm->last_fw_err, fw_err, sizeof(struct iwm_fw_error_hdr)); - - IWM_ERR(iwm, "%cMAC FW ERROR:\n", - (le32_to_cpu(fw_err->category) == UMAC_SYS_ERR_CAT_LMAC) ? 'L' : 'U'); - IWM_ERR(iwm, "\tCategory: %d\n", le32_to_cpu(fw_err->category)); - IWM_ERR(iwm, "\tStatus: 0x%x\n", le32_to_cpu(fw_err->status)); - IWM_ERR(iwm, "\tPC: 0x%x\n", le32_to_cpu(fw_err->pc)); - IWM_ERR(iwm, "\tblink1: %d\n", le32_to_cpu(fw_err->blink1)); - IWM_ERR(iwm, "\tblink2: %d\n", le32_to_cpu(fw_err->blink2)); - IWM_ERR(iwm, "\tilink1: %d\n", le32_to_cpu(fw_err->ilink1)); - IWM_ERR(iwm, "\tilink2: %d\n", le32_to_cpu(fw_err->ilink2)); - IWM_ERR(iwm, "\tData1: 0x%x\n", le32_to_cpu(fw_err->data1)); - IWM_ERR(iwm, "\tData2: 0x%x\n", le32_to_cpu(fw_err->data2)); - IWM_ERR(iwm, "\tLine number: %d\n", le32_to_cpu(fw_err->line_num)); - IWM_ERR(iwm, "\tUMAC status: 0x%x\n", le32_to_cpu(fw_err->umac_status)); - IWM_ERR(iwm, "\tLMAC status: 0x%x\n", le32_to_cpu(fw_err->lmac_status)); - IWM_ERR(iwm, "\tSDIO status: 0x%x\n", le32_to_cpu(fw_err->sdio_status)); - - iwm_resetting(iwm); - - return 0; -} - -static int iwm_ntf_umac_alive(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_alive *alive_resp = - (struct iwm_umac_notif_alive *)(buf); - u16 status = le16_to_cpu(alive_resp->status); - - if (status == UMAC_NTFY_ALIVE_STATUS_ERR) { - IWM_ERR(iwm, "Receive error UMAC_ALIVE\n"); - return -EIO; - } - - iwm_tx_credit_init_pools(iwm, alive_resp); - - return 0; -} - -static int iwm_ntf_init_complete(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct wiphy *wiphy = iwm_to_wiphy(iwm); - struct iwm_umac_notif_init_complete *init_complete = - (struct iwm_umac_notif_init_complete *)(buf); - u16 status = le16_to_cpu(init_complete->status); - bool blocked = (status == UMAC_NTFY_INIT_COMPLETE_STATUS_ERR); - - if (blocked) - IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is on (radio off)\n"); - else - IWM_DBG_NTF(iwm, DBG, "Hardware rf kill is off (radio on)\n"); - - wiphy_rfkill_set_hw_state(wiphy, blocked); - - return 0; -} - -static int iwm_ntf_tx_credit_update(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - int pool_nr, total_freed_pages; - unsigned long pool_map; - int i, id; - struct iwm_umac_notif_page_dealloc *dealloc = - (struct iwm_umac_notif_page_dealloc *)buf; - - pool_nr = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_CNT); - pool_map = GET_VAL32(dealloc->changes, UMAC_DEALLOC_NTFY_CHANGES_MSK); - - IWM_DBG_TX(iwm, DBG, "UMAC dealloc notification: pool nr %d, " - "update map 0x%lx\n", pool_nr, pool_map); - - spin_lock(&iwm->tx_credit.lock); - - for (i = 0; i < pool_nr; i++) { - id = GET_VAL32(dealloc->grp_info[i], - UMAC_DEALLOC_NTFY_GROUP_NUM); - if (test_bit(id, &pool_map)) { - total_freed_pages = GET_VAL32(dealloc->grp_info[i], - UMAC_DEALLOC_NTFY_PAGE_CNT); - iwm_tx_credit_inc(iwm, id, total_freed_pages); - } - } - - spin_unlock(&iwm->tx_credit.lock); - - return 0; -} - -static int iwm_ntf_umac_reset(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - IWM_DBG_NTF(iwm, DBG, "UMAC RESET done\n"); - - return 0; -} - -static int iwm_ntf_lmac_version(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - IWM_DBG_NTF(iwm, INFO, "LMAC Version: %x.%x\n", buf[9], buf[8]); - - return 0; -} - -static int iwm_ntf_tx(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_lmac_tx_resp *tx_resp; - struct iwm_umac_wifi_in_hdr *hdr; - - tx_resp = (struct iwm_lmac_tx_resp *) - (buf + sizeof(struct iwm_umac_wifi_in_hdr)); - hdr = (struct iwm_umac_wifi_in_hdr *)buf; - - IWM_DBG_TX(iwm, DBG, "REPLY_TX, buf size: %lu\n", buf_size); - - IWM_DBG_TX(iwm, DBG, "Seqnum: %d\n", - le16_to_cpu(hdr->sw_hdr.cmd.seq_num)); - IWM_DBG_TX(iwm, DBG, "\tFrame cnt: %d\n", tx_resp->frame_cnt); - IWM_DBG_TX(iwm, DBG, "\tRetry cnt: %d\n", - le16_to_cpu(tx_resp->retry_cnt)); - IWM_DBG_TX(iwm, DBG, "\tSeq ctl: %d\n", le16_to_cpu(tx_resp->seq_ctl)); - IWM_DBG_TX(iwm, DBG, "\tByte cnt: %d\n", - le16_to_cpu(tx_resp->byte_cnt)); - IWM_DBG_TX(iwm, DBG, "\tStatus: 0x%x\n", le32_to_cpu(tx_resp->status)); - - return 0; -} - - -static int iwm_ntf_calib_res(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - u8 opcode; - u8 *calib_buf; - struct iwm_lmac_calib_hdr *hdr = (struct iwm_lmac_calib_hdr *) - (buf + sizeof(struct iwm_umac_wifi_in_hdr)); - - opcode = hdr->opcode; - - BUG_ON(opcode >= CALIBRATION_CMD_NUM || - opcode < PHY_CALIBRATE_OPCODES_NUM); - - IWM_DBG_NTF(iwm, DBG, "Store calibration result for opcode: %d\n", - opcode); - - buf_size -= sizeof(struct iwm_umac_wifi_in_hdr); - calib_buf = iwm->calib_res[opcode].buf; - - if (!calib_buf || (iwm->calib_res[opcode].size < buf_size)) { - kfree(calib_buf); - calib_buf = kzalloc(buf_size, GFP_KERNEL); - if (!calib_buf) { - IWM_ERR(iwm, "Memory allocation failed: calib_res\n"); - return -ENOMEM; - } - iwm->calib_res[opcode].buf = calib_buf; - iwm->calib_res[opcode].size = buf_size; - } - - memcpy(calib_buf, hdr, buf_size); - set_bit(opcode - PHY_CALIBRATE_OPCODES_NUM, &iwm->calib_done_map); - - return 0; -} - -static int iwm_ntf_calib_complete(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - IWM_DBG_NTF(iwm, DBG, "Calibration completed\n"); - - return 0; -} - -static int iwm_ntf_calib_cfg(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_lmac_cal_cfg_resp *cal_resp; - - cal_resp = (struct iwm_lmac_cal_cfg_resp *) - (buf + sizeof(struct iwm_umac_wifi_in_hdr)); - - IWM_DBG_NTF(iwm, DBG, "Calibration CFG command status: %d\n", - le32_to_cpu(cal_resp->status)); - - return 0; -} - -static int iwm_ntf_wifi_status(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_wifi_status *status = - (struct iwm_umac_notif_wifi_status *)buf; - - iwm->core_enabled |= le16_to_cpu(status->status); - - return 0; -} - -static struct iwm_rx_ticket_node * -iwm_rx_ticket_node_alloc(struct iwm_priv *iwm, struct iwm_rx_ticket *ticket) -{ - struct iwm_rx_ticket_node *ticket_node; - - ticket_node = kzalloc(sizeof(struct iwm_rx_ticket_node), GFP_KERNEL); - if (!ticket_node) { - IWM_ERR(iwm, "Couldn't allocate ticket node\n"); - return ERR_PTR(-ENOMEM); - } - - ticket_node->ticket = kzalloc(sizeof(struct iwm_rx_ticket), GFP_KERNEL); - if (!ticket_node->ticket) { - IWM_ERR(iwm, "Couldn't allocate RX ticket\n"); - kfree(ticket_node); - return ERR_PTR(-ENOMEM); - } - - memcpy(ticket_node->ticket, ticket, sizeof(struct iwm_rx_ticket)); - INIT_LIST_HEAD(&ticket_node->node); - - return ticket_node; -} - -static void iwm_rx_ticket_node_free(struct iwm_rx_ticket_node *ticket_node) -{ - kfree(ticket_node->ticket); - kfree(ticket_node); -} - -static struct iwm_rx_packet *iwm_rx_packet_get(struct iwm_priv *iwm, u16 id) -{ - u8 id_hash = IWM_RX_ID_GET_HASH(id); - struct list_head *packet_list; - struct iwm_rx_packet *packet, *next; - - packet_list = &iwm->rx_packets[id_hash]; - - list_for_each_entry_safe(packet, next, packet_list, node) - if (packet->id == id) - return packet; - - return NULL; -} - -static struct iwm_rx_packet *iwm_rx_packet_alloc(struct iwm_priv *iwm, u8 *buf, - u32 size, u16 id) -{ - struct iwm_rx_packet *packet; - - packet = kzalloc(sizeof(struct iwm_rx_packet), GFP_KERNEL); - if (!packet) { - IWM_ERR(iwm, "Couldn't allocate packet\n"); - return ERR_PTR(-ENOMEM); - } - - packet->skb = dev_alloc_skb(size); - if (!packet->skb) { - IWM_ERR(iwm, "Couldn't allocate packet SKB\n"); - kfree(packet); - return ERR_PTR(-ENOMEM); - } - - packet->pkt_size = size; - - skb_put(packet->skb, size); - memcpy(packet->skb->data, buf, size); - INIT_LIST_HEAD(&packet->node); - packet->id = id; - - return packet; -} - -void iwm_rx_free(struct iwm_priv *iwm) -{ - struct iwm_rx_ticket_node *ticket, *nt; - struct iwm_rx_packet *packet, *np; - int i; - - list_for_each_entry_safe(ticket, nt, &iwm->rx_tickets, node) { - list_del(&ticket->node); - iwm_rx_ticket_node_free(ticket); - } - - for (i = 0; i < IWM_RX_ID_HASH; i++) { - list_for_each_entry_safe(packet, np, &iwm->rx_packets[i], - node) { - list_del(&packet->node); - kfree_skb(packet->skb); - kfree(packet); - } - } -} - -static int iwm_ntf_rx_ticket(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_rx_ticket *ntf_rx_ticket = - (struct iwm_umac_notif_rx_ticket *)buf; - struct iwm_rx_ticket *ticket = - (struct iwm_rx_ticket *)ntf_rx_ticket->tickets; - int i, schedule_rx = 0; - - for (i = 0; i < ntf_rx_ticket->num_tickets; i++) { - struct iwm_rx_ticket_node *ticket_node; - - switch (le16_to_cpu(ticket->action)) { - case IWM_RX_TICKET_RELEASE: - case IWM_RX_TICKET_DROP: - /* We can push the packet to the stack */ - ticket_node = iwm_rx_ticket_node_alloc(iwm, ticket); - if (IS_ERR(ticket_node)) - return PTR_ERR(ticket_node); - - IWM_DBG_RX(iwm, DBG, "TICKET RELEASE(%d)\n", - ticket->id); - list_add_tail(&ticket_node->node, &iwm->rx_tickets); - - /* - * We received an Rx ticket, most likely there's - * a packet pending for it, it's not worth going - * through the packet hash list to double check. - * Let's just fire the rx worker.. - */ - schedule_rx = 1; - - break; - - default: - IWM_ERR(iwm, "Invalid RX ticket action: 0x%x\n", - ticket->action); - } - - ticket++; - } - - if (schedule_rx) - queue_work(iwm->rx_wq, &iwm->rx_worker); - - return 0; -} - -static int iwm_ntf_rx_packet(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_wifi_in_hdr *wifi_hdr; - struct iwm_rx_packet *packet; - u16 id, buf_offset; - u32 packet_size; - - IWM_DBG_RX(iwm, DBG, "\n"); - - wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; - id = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); - buf_offset = sizeof(struct iwm_umac_wifi_in_hdr); - packet_size = buf_size - sizeof(struct iwm_umac_wifi_in_hdr); - - IWM_DBG_RX(iwm, DBG, "CMD:0x%x, seqnum: %d, packet size: %d\n", - wifi_hdr->sw_hdr.cmd.cmd, id, packet_size); - IWM_DBG_RX(iwm, DBG, "Packet id: %d\n", id); - IWM_HEXDUMP(iwm, DBG, RX, "PACKET: ", buf + buf_offset, packet_size); - - packet = iwm_rx_packet_alloc(iwm, buf + buf_offset, packet_size, id); - if (IS_ERR(packet)) - return PTR_ERR(packet); - - list_add_tail(&packet->node, &iwm->rx_packets[IWM_RX_ID_GET_HASH(id)]); - - /* We might (unlikely) have received the packet _after_ the ticket */ - queue_work(iwm->rx_wq, &iwm->rx_worker); - - return 0; -} - -/* MLME handlers */ -static int iwm_mlme_assoc_start(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_assoc_start *start; - - start = (struct iwm_umac_notif_assoc_start *)buf; - - IWM_DBG_MLME(iwm, INFO, "Association with %pM Started, reason: %d\n", - start->bssid, le32_to_cpu(start->roam_reason)); - - wake_up_interruptible(&iwm->mlme_queue); - - return 0; -} - -static int iwm_mlme_assoc_complete(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_assoc_complete *complete = - (struct iwm_umac_notif_assoc_complete *)buf; - - IWM_DBG_MLME(iwm, INFO, "Association with %pM completed, status: %d\n", - complete->bssid, complete->status); - - switch (le32_to_cpu(complete->status)) { - case UMAC_ASSOC_COMPLETE_SUCCESS: - set_bit(IWM_STATUS_ASSOCIATED, &iwm->status); - memcpy(iwm->bssid, complete->bssid, ETH_ALEN); - iwm->channel = complete->channel; - - /* Internal roaming state, avoid notifying SME. */ - if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) - && iwm->conf.mode == UMAC_MODE_BSS) { - cancel_delayed_work(&iwm->disconnect); - cfg80211_roamed(iwm_to_ndev(iwm), - complete->bssid, - iwm->req_ie, iwm->req_ie_len, - iwm->resp_ie, iwm->resp_ie_len, - GFP_KERNEL); - break; - } - - iwm_link_on(iwm); - - if (iwm->conf.mode == UMAC_MODE_IBSS) - goto ibss; - - if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) - cfg80211_connect_result(iwm_to_ndev(iwm), - complete->bssid, - iwm->req_ie, iwm->req_ie_len, - iwm->resp_ie, iwm->resp_ie_len, - WLAN_STATUS_SUCCESS, - GFP_KERNEL); - else - cfg80211_roamed(iwm_to_ndev(iwm), - complete->bssid, - iwm->req_ie, iwm->req_ie_len, - iwm->resp_ie, iwm->resp_ie_len, - GFP_KERNEL); - break; - case UMAC_ASSOC_COMPLETE_FAILURE: - clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); - memset(iwm->bssid, 0, ETH_ALEN); - iwm->channel = 0; - - /* Internal roaming state, avoid notifying SME. */ - if (!test_and_clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status) - && iwm->conf.mode == UMAC_MODE_BSS) { - cancel_delayed_work(&iwm->disconnect); - break; - } - - iwm_link_off(iwm); - - if (iwm->conf.mode == UMAC_MODE_IBSS) - goto ibss; - - if (!test_bit(IWM_STATUS_RESETTING, &iwm->status)) - cfg80211_connect_result(iwm_to_ndev(iwm), - complete->bssid, - NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - else - cfg80211_disconnected(iwm_to_ndev(iwm), 0, NULL, 0, - GFP_KERNEL); - break; - default: - break; - } - - clear_bit(IWM_STATUS_RESETTING, &iwm->status); - return 0; - - ibss: - cfg80211_ibss_joined(iwm_to_ndev(iwm), iwm->bssid, GFP_KERNEL); - clear_bit(IWM_STATUS_RESETTING, &iwm->status); - return 0; -} - -static int iwm_mlme_profile_invalidate(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_profile_invalidate *invalid; - u32 reason; - - invalid = (struct iwm_umac_notif_profile_invalidate *)buf; - reason = le32_to_cpu(invalid->reason); - - IWM_DBG_MLME(iwm, INFO, "Profile Invalidated. Reason: %d\n", reason); - - if (reason != UMAC_PROFILE_INVALID_REQUEST && - test_bit(IWM_STATUS_SME_CONNECTING, &iwm->status)) - cfg80211_connect_result(iwm_to_ndev(iwm), NULL, NULL, 0, NULL, - 0, WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - - clear_bit(IWM_STATUS_SME_CONNECTING, &iwm->status); - clear_bit(IWM_STATUS_ASSOCIATED, &iwm->status); - - iwm->umac_profile_active = 0; - memset(iwm->bssid, 0, ETH_ALEN); - iwm->channel = 0; - - iwm_link_off(iwm); - - wake_up_interruptible(&iwm->mlme_queue); - - return 0; -} - -#define IWM_DISCONNECT_INTERVAL (5 * HZ) - -static int iwm_mlme_connection_terminated(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - IWM_DBG_MLME(iwm, DBG, "Connection terminated\n"); - - schedule_delayed_work(&iwm->disconnect, IWM_DISCONNECT_INTERVAL); - - return 0; -} - -static int iwm_mlme_scan_complete(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - int ret; - struct iwm_umac_notif_scan_complete *scan_complete = - (struct iwm_umac_notif_scan_complete *)buf; - u32 result = le32_to_cpu(scan_complete->result); - - IWM_DBG_MLME(iwm, INFO, "type:0x%x result:0x%x seq:%d\n", - le32_to_cpu(scan_complete->type), - le32_to_cpu(scan_complete->result), - scan_complete->seq_num); - - if (!test_and_clear_bit(IWM_STATUS_SCANNING, &iwm->status)) { - IWM_ERR(iwm, "Scan complete while device not scanning\n"); - return -EIO; - } - if (!iwm->scan_request) - return 0; - - ret = iwm_cfg80211_inform_bss(iwm); - - cfg80211_scan_done(iwm->scan_request, - (result & UMAC_SCAN_RESULT_ABORTED) ? 1 : !!ret); - iwm->scan_request = NULL; - - return ret; -} - -static int iwm_mlme_update_sta_table(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_sta_info *umac_sta = - (struct iwm_umac_notif_sta_info *)buf; - struct iwm_sta_info *sta; - int i; - - switch (le32_to_cpu(umac_sta->opcode)) { - case UMAC_OPCODE_ADD_MODIFY: - sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)]; - - IWM_DBG_MLME(iwm, INFO, "%s STA: ID = %d, Color = %d, " - "addr = %pM, qos = %d\n", - sta->valid ? "Modify" : "Add", - GET_VAL8(umac_sta->sta_id, LMAC_STA_ID), - GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR), - umac_sta->mac_addr, - umac_sta->flags & UMAC_STA_FLAG_QOS); - - sta->valid = 1; - sta->qos = umac_sta->flags & UMAC_STA_FLAG_QOS; - sta->color = GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR); - memcpy(sta->addr, umac_sta->mac_addr, ETH_ALEN); - break; - case UMAC_OPCODE_REMOVE: - IWM_DBG_MLME(iwm, INFO, "Remove STA: ID = %d, Color = %d, " - "addr = %pM\n", - GET_VAL8(umac_sta->sta_id, LMAC_STA_ID), - GET_VAL8(umac_sta->sta_id, LMAC_STA_COLOR), - umac_sta->mac_addr); - - sta = &iwm->sta_table[GET_VAL8(umac_sta->sta_id, LMAC_STA_ID)]; - - if (!memcmp(sta->addr, umac_sta->mac_addr, ETH_ALEN)) - sta->valid = 0; - - break; - case UMAC_OPCODE_CLEAR_ALL: - for (i = 0; i < IWM_STA_TABLE_NUM; i++) - iwm->sta_table[i].valid = 0; - - break; - default: - break; - } - - return 0; -} - -static int iwm_mlme_update_bss_table(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct wiphy *wiphy = iwm_to_wiphy(iwm); - struct ieee80211_mgmt *mgmt; - struct iwm_umac_notif_bss_info *umac_bss = - (struct iwm_umac_notif_bss_info *)buf; - struct ieee80211_channel *channel; - struct ieee80211_supported_band *band; - struct iwm_bss_info *bss, *next; - s32 signal; - int freq; - u16 frame_len = le16_to_cpu(umac_bss->frame_len); - size_t bss_len = sizeof(struct iwm_umac_notif_bss_info) + frame_len; - - mgmt = (struct ieee80211_mgmt *)(umac_bss->frame_buf); - - IWM_DBG_MLME(iwm, DBG, "New BSS info entry: %pM\n", mgmt->bssid); - IWM_DBG_MLME(iwm, DBG, "\tType: 0x%x\n", le32_to_cpu(umac_bss->type)); - IWM_DBG_MLME(iwm, DBG, "\tTimestamp: %d\n", - le32_to_cpu(umac_bss->timestamp)); - IWM_DBG_MLME(iwm, DBG, "\tTable Index: %d\n", - le16_to_cpu(umac_bss->table_idx)); - IWM_DBG_MLME(iwm, DBG, "\tBand: %d\n", umac_bss->band); - IWM_DBG_MLME(iwm, DBG, "\tChannel: %d\n", umac_bss->channel); - IWM_DBG_MLME(iwm, DBG, "\tRSSI: %d\n", umac_bss->rssi); - IWM_DBG_MLME(iwm, DBG, "\tFrame Length: %d\n", frame_len); - - list_for_each_entry_safe(bss, next, &iwm->bss_list, node) - if (bss->bss->table_idx == umac_bss->table_idx) - break; - - if (&bss->node != &iwm->bss_list) { - /* Remove the old BSS entry, we will add it back later. */ - list_del(&bss->node); - kfree(bss->bss); - } else { - /* New BSS entry */ - - bss = kzalloc(sizeof(struct iwm_bss_info), GFP_KERNEL); - if (!bss) { - IWM_ERR(iwm, "Couldn't allocate bss_info\n"); - return -ENOMEM; - } - } - - bss->bss = kzalloc(bss_len, GFP_KERNEL); - if (!bss) { - kfree(bss); - IWM_ERR(iwm, "Couldn't allocate bss\n"); - return -ENOMEM; - } - - INIT_LIST_HEAD(&bss->node); - memcpy(bss->bss, umac_bss, bss_len); - - if (umac_bss->band == UMAC_BAND_2GHZ) - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - else if (umac_bss->band == UMAC_BAND_5GHZ) - band = wiphy->bands[IEEE80211_BAND_5GHZ]; - else { - IWM_ERR(iwm, "Invalid band: %d\n", umac_bss->band); - goto err; - } - - freq = ieee80211_channel_to_frequency(umac_bss->channel); - channel = ieee80211_get_channel(wiphy, freq); - signal = umac_bss->rssi * 100; - - bss->cfg_bss = cfg80211_inform_bss_frame(wiphy, channel, - mgmt, frame_len, - signal, GFP_KERNEL); - if (!bss->cfg_bss) - goto err; - - list_add_tail(&bss->node, &iwm->bss_list); - - return 0; - err: - kfree(bss->bss); - kfree(bss); - - return -EINVAL; -} - -static int iwm_mlme_remove_bss(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_bss_removed *bss_rm = - (struct iwm_umac_notif_bss_removed *)buf; - struct iwm_bss_info *bss, *next; - u16 table_idx; - int i; - - for (i = 0; i < le32_to_cpu(bss_rm->count); i++) { - table_idx = (le16_to_cpu(bss_rm->entries[i]) - & IWM_BSS_REMOVE_INDEX_MSK); - list_for_each_entry_safe(bss, next, &iwm->bss_list, node) - if (bss->bss->table_idx == cpu_to_le16(table_idx)) { - struct ieee80211_mgmt *mgmt; - - mgmt = (struct ieee80211_mgmt *) - (bss->bss->frame_buf); - IWM_DBG_MLME(iwm, ERR, - "BSS removed: %pM\n", - mgmt->bssid); - list_del(&bss->node); - kfree(bss->bss); - kfree(bss); - } - } - - return 0; -} - -static int iwm_mlme_mgt_frame(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_mgt_frame *mgt_frame = - (struct iwm_umac_notif_mgt_frame *)buf; - struct ieee80211_mgmt *mgt = (struct ieee80211_mgmt *)mgt_frame->frame; - u8 *ie; - - IWM_HEXDUMP(iwm, DBG, MLME, "MGT: ", mgt_frame->frame, - le16_to_cpu(mgt_frame->len)); - - if (ieee80211_is_assoc_req(mgt->frame_control)) { - ie = mgt->u.assoc_req.variable;; - iwm->req_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); - kfree(iwm->req_ie); - iwm->req_ie = kmemdup(mgt->u.assoc_req.variable, - iwm->req_ie_len, GFP_KERNEL); - } else if (ieee80211_is_reassoc_req(mgt->frame_control)) { - ie = mgt->u.reassoc_req.variable;; - iwm->req_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); - kfree(iwm->req_ie); - iwm->req_ie = kmemdup(mgt->u.reassoc_req.variable, - iwm->req_ie_len, GFP_KERNEL); - } else if (ieee80211_is_assoc_resp(mgt->frame_control)) { - ie = mgt->u.assoc_resp.variable;; - iwm->resp_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); - kfree(iwm->resp_ie); - iwm->resp_ie = kmemdup(mgt->u.assoc_resp.variable, - iwm->resp_ie_len, GFP_KERNEL); - } else if (ieee80211_is_reassoc_resp(mgt->frame_control)) { - ie = mgt->u.reassoc_resp.variable;; - iwm->resp_ie_len = - le16_to_cpu(mgt_frame->len) - (ie - (u8 *)mgt); - kfree(iwm->resp_ie); - iwm->resp_ie = kmemdup(mgt->u.reassoc_resp.variable, - iwm->resp_ie_len, GFP_KERNEL); - } else { - IWM_ERR(iwm, "Unsupported management frame: 0x%x", - le16_to_cpu(mgt->frame_control)); - return 0; - } - - return 0; -} - -static int iwm_ntf_mlme(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_wifi_if *notif = - (struct iwm_umac_notif_wifi_if *)buf; - - switch (notif->status) { - case WIFI_IF_NTFY_ASSOC_START: - return iwm_mlme_assoc_start(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_ASSOC_COMPLETE: - return iwm_mlme_assoc_complete(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE: - return iwm_mlme_profile_invalidate(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_CONNECTION_TERMINATED: - return iwm_mlme_connection_terminated(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_SCAN_COMPLETE: - return iwm_mlme_scan_complete(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_STA_TABLE_CHANGE: - return iwm_mlme_update_sta_table(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_EXTENDED_IE_REQUIRED: - IWM_DBG_MLME(iwm, DBG, "Extended IE required\n"); - break; - case WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED: - return iwm_mlme_update_bss_table(iwm, buf, buf_size, cmd); - case WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED: - return iwm_mlme_remove_bss(iwm, buf, buf_size, cmd); - break; - case WIFI_IF_NTFY_MGMT_FRAME: - return iwm_mlme_mgt_frame(iwm, buf, buf_size, cmd); - case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START: - case WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE: - case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START: - case WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT: - case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START: - case WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE: - case WIFI_DBG_IF_NTFY_CNCT_ATC_START: - case WIFI_DBG_IF_NTFY_COEX_NOTIFICATION: - case WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP: - case WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP: - IWM_DBG_MLME(iwm, DBG, "MLME debug notification: 0x%x\n", - notif->status); - break; - default: - IWM_ERR(iwm, "Unhandled notification: 0x%x\n", notif->status); - break; - } - - return 0; -} - -#define IWM_STATS_UPDATE_INTERVAL (2 * HZ) - -static int iwm_ntf_statistics(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_notif_stats *stats = (struct iwm_umac_notif_stats *)buf; - struct iw_statistics *wstats = &iwm->wstats; - u16 max_rate = 0; - int i; - - IWM_DBG_MLME(iwm, DBG, "Statistics notification received\n"); - - if (test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - for (i = 0; i < UMAC_NTF_RATE_SAMPLE_NR; i++) { - max_rate = max_t(u16, max_rate, - max(le16_to_cpu(stats->tx_rate[i]), - le16_to_cpu(stats->rx_rate[i]))); - } - /* UMAC passes rate info multiplies by 2 */ - iwm->rate = max_rate >> 1; - } - iwm->txpower = le32_to_cpu(stats->tx_power); - - wstats->status = 0; - - wstats->discard.nwid = le32_to_cpu(stats->rx_drop_other_bssid); - wstats->discard.code = le32_to_cpu(stats->rx_drop_decode); - wstats->discard.fragment = le32_to_cpu(stats->rx_drop_reassembly); - wstats->discard.retries = le32_to_cpu(stats->tx_drop_max_retry); - - wstats->miss.beacon = le32_to_cpu(stats->missed_beacons); - - /* according to cfg80211 */ - if (stats->rssi_dbm < -110) - wstats->qual.qual = 0; - else if (stats->rssi_dbm > -40) - wstats->qual.qual = 70; - else - wstats->qual.qual = stats->rssi_dbm + 110; - - wstats->qual.level = stats->rssi_dbm; - wstats->qual.noise = stats->noise_dbm; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - - schedule_delayed_work(&iwm->stats_request, IWM_STATS_UPDATE_INTERVAL); - - mod_timer(&iwm->watchdog, round_jiffies(jiffies + IWM_WATCHDOG_PERIOD)); - - return 0; -} - -static int iwm_ntf_eeprom_proxy(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_cmd_eeprom_proxy *eeprom_proxy = - (struct iwm_umac_cmd_eeprom_proxy *) - (buf + sizeof(struct iwm_umac_wifi_in_hdr)); - struct iwm_umac_cmd_eeprom_proxy_hdr *hdr = &eeprom_proxy->hdr; - u32 hdr_offset = le32_to_cpu(hdr->offset); - u32 hdr_len = le32_to_cpu(hdr->len); - u32 hdr_type = le32_to_cpu(hdr->type); - - IWM_DBG_NTF(iwm, DBG, "type: 0x%x, len: %d, offset: 0x%x\n", - hdr_type, hdr_len, hdr_offset); - - if ((hdr_offset + hdr_len) > IWM_EEPROM_LEN) - return -EINVAL; - - switch (hdr_type) { - case IWM_UMAC_CMD_EEPROM_TYPE_READ: - memcpy(iwm->eeprom + hdr_offset, eeprom_proxy->buf, hdr_len); - break; - case IWM_UMAC_CMD_EEPROM_TYPE_WRITE: - default: - return -ENOTSUPP; - } - - return 0; -} - -static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_cmd_get_channel_list *ch_list = - (struct iwm_umac_cmd_get_channel_list *) - (buf + sizeof(struct iwm_umac_wifi_in_hdr)); - struct wiphy *wiphy = iwm_to_wiphy(iwm); - struct ieee80211_supported_band *band; - int i; - - band = wiphy->bands[IEEE80211_BAND_2GHZ]; - - for (i = 0; i < band->n_channels; i++) { - unsigned long ch_mask_0 = - le32_to_cpu(ch_list->ch[0].channels_mask); - unsigned long ch_mask_2 = - le32_to_cpu(ch_list->ch[2].channels_mask); - - if (!test_bit(i, &ch_mask_0)) - band->channels[i].flags |= IEEE80211_CHAN_DISABLED; - - if (!test_bit(i, &ch_mask_2)) - band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS; - } - - band = wiphy->bands[IEEE80211_BAND_5GHZ]; - - for (i = 0; i < min(band->n_channels, 32); i++) { - unsigned long ch_mask_1 = - le32_to_cpu(ch_list->ch[1].channels_mask); - unsigned long ch_mask_3 = - le32_to_cpu(ch_list->ch[3].channels_mask); - - if (!test_bit(i, &ch_mask_1)) - band->channels[i].flags |= IEEE80211_CHAN_DISABLED; - - if (!test_bit(i, &ch_mask_3)) - band->channels[i].flags |= IEEE80211_CHAN_NO_IBSS; - } - - return 0; -} - -static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - struct iwm_umac_wifi_if *hdr = - (struct iwm_umac_wifi_if *)cmd->buf.payload; - - IWM_DBG_NTF(iwm, DBG, "WIFI_IF_WRAPPER cmd is delivered to UMAC: " - "oid is 0x%x\n", hdr->oid); - - if (hdr->oid <= WIFI_IF_NTFY_MAX) { - set_bit(hdr->oid, &iwm->wifi_ntfy[0]); - wake_up_interruptible(&iwm->wifi_ntfy_queue); - } else - return -EINVAL; - - switch (hdr->oid) { - case UMAC_WIFI_IF_CMD_SET_PROFILE: - iwm->umac_profile_active = 1; - break; - default: - break; - } - - return 0; -} - -static int iwm_ntf_card_state(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size, struct iwm_wifi_cmd *cmd) -{ - struct wiphy *wiphy = iwm_to_wiphy(iwm); - struct iwm_lmac_card_state *state = (struct iwm_lmac_card_state *) - (buf + sizeof(struct iwm_umac_wifi_in_hdr)); - u32 flags = le32_to_cpu(state->flags); - - IWM_INFO(iwm, "HW RF Kill %s, CT Kill %s\n", - flags & IWM_CARD_STATE_HW_DISABLED ? "ON" : "OFF", - flags & IWM_CARD_STATE_CTKILL_DISABLED ? "ON" : "OFF"); - - wiphy_rfkill_set_hw_state(wiphy, flags & IWM_CARD_STATE_HW_DISABLED); - - return 0; -} - -static int iwm_rx_handle_wifi(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size) -{ - struct iwm_umac_wifi_in_hdr *wifi_hdr; - struct iwm_wifi_cmd *cmd; - u8 source, cmd_id; - u16 seq_num; - u32 count; - u8 resp; - - wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; - cmd_id = wifi_hdr->sw_hdr.cmd.cmd; - - source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); - if (source >= IWM_SRC_NUM) { - IWM_CRIT(iwm, "invalid source %d\n", source); - return -EINVAL; - } - - count = (GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_BYTE_COUNT)); - count += sizeof(struct iwm_umac_wifi_in_hdr) - - sizeof(struct iwm_dev_cmd_hdr); - if (count > buf_size) { - IWM_CRIT(iwm, "count %d, buf size:%ld\n", count, buf_size); - return -EINVAL; - } - - resp = GET_VAL32(wifi_hdr->sw_hdr.meta_data, UMAC_FW_CMD_STATUS); - - seq_num = le16_to_cpu(wifi_hdr->sw_hdr.cmd.seq_num); - - IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x, seqnum: %d\n", - cmd_id, source, seq_num); - - /* - * If this is a response to a previously sent command, there must - * be a pending command for this sequence number. - */ - cmd = iwm_get_pending_wifi_cmd(iwm, seq_num); - - /* Notify the caller only for sync commands. */ - switch (source) { - case UMAC_HDI_IN_SOURCE_FHRX: - if (iwm->lmac_handlers[cmd_id] && - test_bit(cmd_id, &iwm->lmac_handler_map[0])) - return iwm_notif_send(iwm, cmd, cmd_id, source, - buf, count); - break; - case UMAC_HDI_IN_SOURCE_FW: - if (iwm->umac_handlers[cmd_id] && - test_bit(cmd_id, &iwm->umac_handler_map[0])) - return iwm_notif_send(iwm, cmd, cmd_id, source, - buf, count); - break; - case UMAC_HDI_IN_SOURCE_UDMA: - break; - } - - return iwm_rx_handle_resp(iwm, buf, count, cmd); -} - -int iwm_rx_handle_resp(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size, - struct iwm_wifi_cmd *cmd) -{ - u8 source, cmd_id; - struct iwm_umac_wifi_in_hdr *wifi_hdr; - int ret = 0; - - wifi_hdr = (struct iwm_umac_wifi_in_hdr *)buf; - cmd_id = wifi_hdr->sw_hdr.cmd.cmd; - - source = GET_VAL32(wifi_hdr->hw_hdr.cmd, UMAC_HDI_IN_CMD_SOURCE); - - IWM_DBG_RX(iwm, DBG, "CMD:0x%x, source: 0x%x\n", cmd_id, source); - - switch (source) { - case UMAC_HDI_IN_SOURCE_FHRX: - if (iwm->lmac_handlers[cmd_id]) - ret = iwm->lmac_handlers[cmd_id] - (iwm, buf, buf_size, cmd); - break; - case UMAC_HDI_IN_SOURCE_FW: - if (iwm->umac_handlers[cmd_id]) - ret = iwm->umac_handlers[cmd_id] - (iwm, buf, buf_size, cmd); - break; - case UMAC_HDI_IN_SOURCE_UDMA: - ret = -EINVAL; - break; - } - - kfree(cmd); - - return ret; -} - -static int iwm_rx_handle_nonwifi(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size) -{ - u8 seq_num; - struct iwm_udma_in_hdr *hdr = (struct iwm_udma_in_hdr *)buf; - struct iwm_nonwifi_cmd *cmd, *next; - - seq_num = GET_VAL32(hdr->cmd, UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM); - - /* - * We received a non wifi answer. - * Let's check if there's a pending command for it, and if so - * replace the command payload with the buffer, and then wake the - * callers up. - * That means we only support synchronised non wifi command response - * schemes. - */ - list_for_each_entry_safe(cmd, next, &iwm->nonwifi_pending_cmd, pending) - if (cmd->seq_num == seq_num) { - cmd->resp_received = 1; - cmd->buf.len = buf_size; - memcpy(cmd->buf.hdr, buf, buf_size); - wake_up_interruptible(&iwm->nonwifi_queue); - } - - return 0; -} - -static int iwm_rx_handle_umac(struct iwm_priv *iwm, u8 *buf, - unsigned long buf_size) -{ - int ret = 0; - u8 op_code; - unsigned long buf_offset = 0; - struct iwm_udma_in_hdr *hdr; - - /* - * To allow for a more efficient bus usage, UMAC - * messages are encapsulated into UDMA ones. This - * way we can have several UMAC messages in one bus - * transfer. - * A UDMA frame size is always aligned on 16 bytes, - * and a UDMA frame must not start with a UMAC_PAD_TERMINAL - * word. This is how we parse a bus frame into several - * UDMA ones. - */ - while (buf_offset < buf_size) { - - hdr = (struct iwm_udma_in_hdr *)(buf + buf_offset); - - if (iwm_rx_check_udma_hdr(hdr) < 0) { - IWM_DBG_RX(iwm, DBG, "End of frame\n"); - break; - } - - op_code = GET_VAL32(hdr->cmd, UMAC_HDI_IN_CMD_OPCODE); - - IWM_DBG_RX(iwm, DBG, "Op code: 0x%x\n", op_code); - - if (op_code == UMAC_HDI_IN_OPCODE_WIFI) { - ret |= iwm_rx_handle_wifi(iwm, buf + buf_offset, - buf_size - buf_offset); - } else if (op_code < UMAC_HDI_IN_OPCODE_NONWIFI_MAX) { - if (GET_VAL32(hdr->cmd, - UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) != - UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG) { - IWM_ERR(iwm, "Incorrect hw signature\n"); - return -EINVAL; - } - ret |= iwm_rx_handle_nonwifi(iwm, buf + buf_offset, - buf_size - buf_offset); - } else { - IWM_ERR(iwm, "Invalid RX opcode: 0x%x\n", op_code); - ret |= -EINVAL; - } - - buf_offset += iwm_rx_resp_size(hdr); - } - - return ret; -} - -int iwm_rx_handle(struct iwm_priv *iwm, u8 *buf, unsigned long buf_size) -{ - struct iwm_udma_in_hdr *hdr; - - hdr = (struct iwm_udma_in_hdr *)buf; - - switch (le32_to_cpu(hdr->cmd)) { - case UMAC_REBOOT_BARKER: - return iwm_notif_send(iwm, NULL, IWM_BARKER_REBOOT_NOTIFICATION, - IWM_SRC_UDMA, buf, buf_size); - case UMAC_ACK_BARKER: - return iwm_notif_send(iwm, NULL, IWM_ACK_BARKER_NOTIFICATION, - IWM_SRC_UDMA, NULL, 0); - default: - IWM_DBG_RX(iwm, DBG, "Received cmd: 0x%x\n", hdr->cmd); - return iwm_rx_handle_umac(iwm, buf, buf_size); - } - - return 0; -} - -static const iwm_handler iwm_umac_handlers[] = -{ - [UMAC_NOTIFY_OPCODE_ERROR] = iwm_ntf_error, - [UMAC_NOTIFY_OPCODE_ALIVE] = iwm_ntf_umac_alive, - [UMAC_NOTIFY_OPCODE_INIT_COMPLETE] = iwm_ntf_init_complete, - [UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS] = iwm_ntf_wifi_status, - [UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_mlme, - [UMAC_NOTIFY_OPCODE_PAGE_DEALLOC] = iwm_ntf_tx_credit_update, - [UMAC_NOTIFY_OPCODE_RX_TICKET] = iwm_ntf_rx_ticket, - [UMAC_CMD_OPCODE_RESET] = iwm_ntf_umac_reset, - [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, - [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, - [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, - [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, - [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, -}; - -static const iwm_handler iwm_lmac_handlers[] = -{ - [REPLY_TX] = iwm_ntf_tx, - [REPLY_ALIVE] = iwm_ntf_lmac_version, - [CALIBRATION_RES_NOTIFICATION] = iwm_ntf_calib_res, - [CALIBRATION_COMPLETE_NOTIFICATION] = iwm_ntf_calib_complete, - [CALIBRATION_CFG_CMD] = iwm_ntf_calib_cfg, - [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, - [CARD_STATE_NOTIFICATION] = iwm_ntf_card_state, -}; - -void iwm_rx_setup_handlers(struct iwm_priv *iwm) -{ - iwm->umac_handlers = (iwm_handler *) iwm_umac_handlers; - iwm->lmac_handlers = (iwm_handler *) iwm_lmac_handlers; -} - -static void iwm_remove_iv(struct sk_buff *skb, u32 hdr_total_len) -{ - struct ieee80211_hdr *hdr; - unsigned int hdr_len; - - hdr = (struct ieee80211_hdr *)skb->data; - - if (!ieee80211_has_protected(hdr->frame_control)) - return; - - hdr_len = ieee80211_hdrlen(hdr->frame_control); - if (hdr_total_len <= hdr_len) - return; - - memmove(skb->data + (hdr_total_len - hdr_len), skb->data, hdr_len); - skb_pull(skb, (hdr_total_len - hdr_len)); -} - -static void iwm_rx_adjust_packet(struct iwm_priv *iwm, - struct iwm_rx_packet *packet, - struct iwm_rx_ticket_node *ticket_node) -{ - u32 payload_offset = 0, payload_len; - struct iwm_rx_ticket *ticket = ticket_node->ticket; - struct iwm_rx_mpdu_hdr *mpdu_hdr; - struct ieee80211_hdr *hdr; - - mpdu_hdr = (struct iwm_rx_mpdu_hdr *)packet->skb->data; - payload_offset += sizeof(struct iwm_rx_mpdu_hdr); - /* Padding is 0 or 2 bytes */ - payload_len = le16_to_cpu(mpdu_hdr->len) + - (le16_to_cpu(ticket->flags) & IWM_RX_TICKET_PAD_SIZE_MSK); - payload_len -= ticket->tail_len; - - IWM_DBG_RX(iwm, DBG, "Packet adjusted, len:%d, offset:%d, " - "ticket offset:%d ticket tail len:%d\n", - payload_len, payload_offset, ticket->payload_offset, - ticket->tail_len); - - IWM_HEXDUMP(iwm, DBG, RX, "RAW: ", packet->skb->data, packet->skb->len); - - skb_pull(packet->skb, payload_offset); - skb_trim(packet->skb, payload_len); - - iwm_remove_iv(packet->skb, ticket->payload_offset); - - hdr = (struct ieee80211_hdr *) packet->skb->data; - if (ieee80211_is_data_qos(hdr->frame_control)) { - /* UMAC handed QOS_DATA frame with 2 padding bytes appended - * to the qos_ctl field in IEEE 802.11 headers. */ - memmove(packet->skb->data + IEEE80211_QOS_CTL_LEN + 2, - packet->skb->data, - ieee80211_hdrlen(hdr->frame_control) - - IEEE80211_QOS_CTL_LEN); - hdr = (struct ieee80211_hdr *) skb_pull(packet->skb, - IEEE80211_QOS_CTL_LEN + 2); - hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA); - } - - IWM_HEXDUMP(iwm, DBG, RX, "ADJUSTED: ", - packet->skb->data, packet->skb->len); -} - -static void classify8023(struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - - if (ieee80211_is_data_qos(hdr->frame_control)) { - u8 *qc = ieee80211_get_qos_ctl(hdr); - /* frame has qos control */ - skb->priority = *qc & IEEE80211_QOS_CTL_TID_MASK; - } else { - skb->priority = 0; - } -} - -static void iwm_rx_process_packet(struct iwm_priv *iwm, - struct iwm_rx_packet *packet, - struct iwm_rx_ticket_node *ticket_node) -{ - int ret; - struct sk_buff *skb = packet->skb; - struct wireless_dev *wdev = iwm_to_wdev(iwm); - struct net_device *ndev = iwm_to_ndev(iwm); - - IWM_DBG_RX(iwm, DBG, "Processing packet ID %d\n", packet->id); - - switch (le16_to_cpu(ticket_node->ticket->action)) { - case IWM_RX_TICKET_RELEASE: - IWM_DBG_RX(iwm, DBG, "RELEASE packet\n"); - classify8023(skb); - iwm_rx_adjust_packet(iwm, packet, ticket_node); - ret = ieee80211_data_to_8023(skb, ndev->dev_addr, wdev->iftype); - if (ret < 0) { - IWM_DBG_RX(iwm, DBG, "Couldn't convert 802.11 header - " - "%d\n", ret); - break; - } - - IWM_HEXDUMP(iwm, DBG, RX, "802.3: ", skb->data, skb->len); - - skb->dev = iwm_to_ndev(iwm); - skb->protocol = eth_type_trans(skb, ndev); - skb->ip_summed = CHECKSUM_NONE; - memset(skb->cb, 0, sizeof(skb->cb)); - - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += skb->len; - - if (netif_rx_ni(skb) == NET_RX_DROP) { - IWM_ERR(iwm, "Packet dropped\n"); - ndev->stats.rx_dropped++; - } - break; - case IWM_RX_TICKET_DROP: - IWM_DBG_RX(iwm, DBG, "DROP packet\n"); - kfree_skb(packet->skb); - break; - default: - IWM_ERR(iwm, "Unknow ticket action: %d\n", - le16_to_cpu(ticket_node->ticket->action)); - kfree_skb(packet->skb); - } - - kfree(packet); - iwm_rx_ticket_node_free(ticket_node); -} - -/* - * Rx data processing: - * - * We're receiving Rx packet from the LMAC, and Rx ticket from - * the UMAC. - * To forward a target data packet upstream (i.e. to the - * kernel network stack), we must have received an Rx ticket - * that tells us we're allowed to release this packet (ticket - * action is IWM_RX_TICKET_RELEASE). The Rx ticket also indicates, - * among other things, where valid data actually starts in the Rx - * packet. - */ -void iwm_rx_worker(struct work_struct *work) -{ - struct iwm_priv *iwm; - struct iwm_rx_ticket_node *ticket, *next; - - iwm = container_of(work, struct iwm_priv, rx_worker); - - /* - * We go through the tickets list and if there is a pending - * packet for it, we push it upstream. - * We stop whenever a ticket is missing its packet, as we're - * supposed to send the packets in order. - */ - list_for_each_entry_safe(ticket, next, &iwm->rx_tickets, node) { - struct iwm_rx_packet *packet = - iwm_rx_packet_get(iwm, le16_to_cpu(ticket->ticket->id)); - - if (!packet) { - IWM_DBG_RX(iwm, DBG, "Skip rx_work: Wait for ticket %d " - "to be handled first\n", - le16_to_cpu(ticket->ticket->id)); - return; - } - - list_del(&ticket->node); - list_del(&packet->node); - iwm_rx_process_packet(iwm, packet, ticket); - } -} - diff --git a/drivers/net/wireless/iwmc3200wifi/rx.h b/drivers/net/wireless/iwmc3200wifi/rx.h deleted file mode 100644 index da0db91cee59..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/rx.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_RX_H__ -#define __IWM_RX_H__ - -#include - -#include "umac.h" - -struct iwm_rx_ticket_node { - struct list_head node; - struct iwm_rx_ticket *ticket; -}; - -struct iwm_rx_packet { - struct list_head node; - u16 id; - struct sk_buff *skb; - unsigned long pkt_size; -}; - -void iwm_rx_worker(struct work_struct *work); - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.c b/drivers/net/wireless/iwmc3200wifi/sdio.c deleted file mode 100644 index 8b1de84003ca..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/sdio.c +++ /dev/null @@ -1,523 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -/* - * This is the SDIO bus specific hooks for iwm. - * It also is the module's entry point. - * - * Interesting code paths: - * iwm_sdio_probe() (Called by an SDIO bus scan) - * -> iwm_if_alloc() (netdev.c) - * -> iwm_wdev_alloc() (cfg80211.c, allocates and register our wiphy) - * -> wiphy_new() - * -> wiphy_register() - * -> alloc_netdev_mq() - * -> register_netdev() - * - * iwm_sdio_remove() - * -> iwm_if_free() (netdev.c) - * -> unregister_netdev() - * -> iwm_wdev_free() (cfg80211.c) - * -> wiphy_unregister() - * -> wiphy_free() - * - * iwm_sdio_isr() (called in process context from the SDIO core code) - * -> queue_work(.., isr_worker) - * -- [async] --> iwm_sdio_isr_worker() - * -> iwm_rx_handle() - */ - -#include -#include -#include -#include -#include -#include - -#include "iwm.h" -#include "debug.h" -#include "bus.h" -#include "sdio.h" - -static void iwm_sdio_isr_worker(struct work_struct *work) -{ - struct iwm_sdio_priv *hw; - struct iwm_priv *iwm; - struct iwm_rx_info *rx_info; - struct sk_buff *skb; - u8 *rx_buf; - unsigned long rx_size; - - hw = container_of(work, struct iwm_sdio_priv, isr_worker); - iwm = hw_to_iwm(hw); - - while (!skb_queue_empty(&iwm->rx_list)) { - skb = skb_dequeue(&iwm->rx_list); - rx_info = skb_to_rx_info(skb); - rx_size = rx_info->rx_size; - rx_buf = skb->data; - - IWM_HEXDUMP(iwm, DBG, SDIO, "RX: ", rx_buf, rx_size); - if (iwm_rx_handle(iwm, rx_buf, rx_size) < 0) - IWM_WARN(iwm, "RX error\n"); - - kfree_skb(skb); - } -} - -static void iwm_sdio_isr(struct sdio_func *func) -{ - struct iwm_priv *iwm; - struct iwm_sdio_priv *hw; - struct iwm_rx_info *rx_info; - struct sk_buff *skb; - unsigned long buf_size, read_size; - int ret; - u8 val; - - hw = sdio_get_drvdata(func); - iwm = hw_to_iwm(hw); - - buf_size = hw->blk_size; - - /* We're checking the status */ - val = sdio_readb(func, IWM_SDIO_INTR_STATUS_ADDR, &ret); - if (val == 0 || ret < 0) { - IWM_ERR(iwm, "Wrong INTR_STATUS\n"); - return; - } - - /* See if we have free buffers */ - if (skb_queue_len(&iwm->rx_list) > IWM_RX_LIST_SIZE) { - IWM_ERR(iwm, "No buffer for more Rx frames\n"); - return; - } - - /* We first read the transaction size */ - read_size = sdio_readb(func, IWM_SDIO_INTR_GET_SIZE_ADDR + 1, &ret); - read_size = read_size << 8; - - if (ret < 0) { - IWM_ERR(iwm, "Couldn't read the xfer size\n"); - return; - } - - /* We need to clear the INT register */ - sdio_writeb(func, 1, IWM_SDIO_INTR_CLEAR_ADDR, &ret); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't clear the INT register\n"); - return; - } - - while (buf_size < read_size) - buf_size <<= 1; - - skb = dev_alloc_skb(buf_size); - if (!skb) { - IWM_ERR(iwm, "Couldn't alloc RX skb\n"); - return; - } - rx_info = skb_to_rx_info(skb); - rx_info->rx_size = read_size; - rx_info->rx_buf_size = buf_size; - - /* Now we can read the actual buffer */ - ret = sdio_memcpy_fromio(func, skb_put(skb, read_size), - IWM_SDIO_DATA_ADDR, read_size); - - /* The skb is put on a driver's specific Rx SKB list */ - skb_queue_tail(&iwm->rx_list, skb); - - /* We can now schedule the actual worker */ - queue_work(hw->isr_wq, &hw->isr_worker); -} - -static void iwm_sdio_rx_free(struct iwm_sdio_priv *hw) -{ - struct iwm_priv *iwm = hw_to_iwm(hw); - - flush_workqueue(hw->isr_wq); - - skb_queue_purge(&iwm->rx_list); -} - -/* Bus ops */ -static int if_sdio_enable(struct iwm_priv *iwm) -{ - struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); - int ret; - - sdio_claim_host(hw->func); - - ret = sdio_enable_func(hw->func); - if (ret) { - IWM_ERR(iwm, "Couldn't enable the device: is TOP driver " - "loaded and functional?\n"); - goto release_host; - } - - iwm_reset(iwm); - - ret = sdio_claim_irq(hw->func, iwm_sdio_isr); - if (ret) { - IWM_ERR(iwm, "Failed to claim irq: %d\n", ret); - goto release_host; - } - - sdio_writeb(hw->func, 1, IWM_SDIO_INTR_ENABLE_ADDR, &ret); - if (ret < 0) { - IWM_ERR(iwm, "Couldn't enable INTR: %d\n", ret); - goto release_irq; - } - - sdio_release_host(hw->func); - - IWM_DBG_SDIO(iwm, INFO, "IWM SDIO enable\n"); - - return 0; - - release_irq: - sdio_release_irq(hw->func); - release_host: - sdio_release_host(hw->func); - - return ret; -} - -static int if_sdio_disable(struct iwm_priv *iwm) -{ - struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); - int ret; - - iwm_reset(iwm); - - sdio_claim_host(hw->func); - sdio_writeb(hw->func, 0, IWM_SDIO_INTR_ENABLE_ADDR, &ret); - if (ret < 0) - IWM_WARN(iwm, "Couldn't disable INTR: %d\n", ret); - - sdio_release_irq(hw->func); - sdio_disable_func(hw->func); - sdio_release_host(hw->func); - - iwm_sdio_rx_free(hw); - - IWM_DBG_SDIO(iwm, INFO, "IWM SDIO disable\n"); - - return 0; -} - -static int if_sdio_send_chunk(struct iwm_priv *iwm, u8 *buf, int count) -{ - struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); - int aligned_count = ALIGN(count, hw->blk_size); - int ret; - - if ((unsigned long)buf & 0x3) { - IWM_ERR(iwm, "buf <%p> is not dword aligned\n", buf); - /* TODO: Is this a hardware limitation? use get_unligned */ - return -EINVAL; - } - - sdio_claim_host(hw->func); - ret = sdio_memcpy_toio(hw->func, IWM_SDIO_DATA_ADDR, buf, - aligned_count); - sdio_release_host(hw->func); - - return ret; -} - -/* debugfs hooks */ -static int iwm_debugfs_sdio_open(struct inode *inode, struct file *filp) -{ - filp->private_data = inode->i_private; - return 0; -} - -static ssize_t iwm_debugfs_sdio_read(struct file *filp, char __user *buffer, - size_t count, loff_t *ppos) -{ - struct iwm_priv *iwm = filp->private_data; - struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); - char *buf; - u8 cccr; - int buf_len = 4096, ret; - size_t len = 0; - - if (*ppos != 0) - return 0; - if (count < sizeof(buf)) - return -ENOSPC; - - buf = kzalloc(buf_len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - sdio_claim_host(hw->func); - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IOEx, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_IOEx\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_IOEx: 0x%x\n", cccr); - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IORx, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_IORx\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_IORx: 0x%x\n", cccr); - - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IENx, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_IENx\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_IENx: 0x%x\n", cccr); - - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_INTx, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_INTx\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_INTx: 0x%x\n", cccr); - - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_ABORT, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_ABORTx\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_ABORT: 0x%x\n", cccr); - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_IF, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_IF\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_IF: 0x%x\n", cccr); - - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CAPS, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_CAPS\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_CAPS: 0x%x\n", cccr); - - cccr = sdio_f0_readb(hw->func, SDIO_CCCR_CIS, &ret); - if (ret) { - IWM_ERR(iwm, "Could not read SDIO_CCCR_CIS\n"); - goto err; - } - len += snprintf(buf + len, buf_len - len, "CCCR_CIS: 0x%x\n", cccr); - - ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); -err: - sdio_release_host(hw->func); - - kfree(buf); - - return ret; -} - -static const struct file_operations iwm_debugfs_sdio_fops = { - .owner = THIS_MODULE, - .open = iwm_debugfs_sdio_open, - .read = iwm_debugfs_sdio_read, -}; - -static int if_sdio_debugfs_init(struct iwm_priv *iwm, struct dentry *parent_dir) -{ - int result; - struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); - - hw->cccr_dentry = debugfs_create_file("cccr", 0200, - parent_dir, iwm, - &iwm_debugfs_sdio_fops); - result = PTR_ERR(hw->cccr_dentry); - if (IS_ERR(hw->cccr_dentry) && (result != -ENODEV)) { - IWM_ERR(iwm, "Couldn't create CCCR entry: %d\n", result); - return result; - } - - return 0; -} - -static void if_sdio_debugfs_exit(struct iwm_priv *iwm) -{ - struct iwm_sdio_priv *hw = iwm_to_if_sdio(iwm); - - debugfs_remove(hw->cccr_dentry); -} - -static struct iwm_if_ops if_sdio_ops = { - .enable = if_sdio_enable, - .disable = if_sdio_disable, - .send_chunk = if_sdio_send_chunk, - .debugfs_init = if_sdio_debugfs_init, - .debugfs_exit = if_sdio_debugfs_exit, - .umac_name = "iwmc3200wifi-umac-sdio.bin", - .calib_lmac_name = "iwmc3200wifi-calib-sdio.bin", - .lmac_name = "iwmc3200wifi-lmac-sdio.bin", -}; - -static int iwm_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - struct iwm_priv *iwm; - struct iwm_sdio_priv *hw; - struct device *dev = &func->dev; - int ret; - - /* check if TOP has already initialized the card */ - sdio_claim_host(func); - ret = sdio_enable_func(func); - if (ret) { - dev_err(dev, "wait for TOP to enable the device\n"); - sdio_release_host(func); - return ret; - } - - ret = sdio_set_block_size(func, IWM_SDIO_BLK_SIZE); - - sdio_disable_func(func); - sdio_release_host(func); - - if (ret < 0) { - dev_err(dev, "Failed to set block size: %d\n", ret); - return ret; - } - - iwm = iwm_if_alloc(sizeof(struct iwm_sdio_priv), dev, &if_sdio_ops); - if (IS_ERR(iwm)) { - dev_err(dev, "allocate SDIO interface failed\n"); - return PTR_ERR(iwm); - } - - hw = iwm_private(iwm); - hw->iwm = iwm; - - ret = iwm_debugfs_init(iwm); - if (ret < 0) { - IWM_ERR(iwm, "Debugfs registration failed\n"); - goto if_free; - } - - sdio_set_drvdata(func, hw); - - hw->func = func; - hw->blk_size = IWM_SDIO_BLK_SIZE; - - hw->isr_wq = create_singlethread_workqueue(KBUILD_MODNAME "_sdio"); - if (!hw->isr_wq) { - ret = -ENOMEM; - goto debugfs_exit; - } - - INIT_WORK(&hw->isr_worker, iwm_sdio_isr_worker); - - ret = iwm_if_add(iwm); - if (ret) { - dev_err(dev, "add SDIO interface failed\n"); - goto destroy_wq; - } - - dev_info(dev, "IWM SDIO probe\n"); - - return 0; - - destroy_wq: - destroy_workqueue(hw->isr_wq); - debugfs_exit: - iwm_debugfs_exit(iwm); - if_free: - iwm_if_free(iwm); - return ret; -} - -static void iwm_sdio_remove(struct sdio_func *func) -{ - struct iwm_sdio_priv *hw = sdio_get_drvdata(func); - struct iwm_priv *iwm = hw_to_iwm(hw); - struct device *dev = &func->dev; - - iwm_if_remove(iwm); - destroy_workqueue(hw->isr_wq); - iwm_debugfs_exit(iwm); - iwm_if_free(iwm); - - sdio_set_drvdata(func, NULL); - - dev_info(dev, "IWM SDIO remove\n"); - - return; -} - -static const struct sdio_device_id iwm_sdio_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_INTEL, - SDIO_DEVICE_ID_INTEL_IWMC3200WIFI) }, - { /* end: all zeroes */ }, -}; -MODULE_DEVICE_TABLE(sdio, iwm_sdio_ids); - -static struct sdio_driver iwm_sdio_driver = { - .name = "iwm_sdio", - .id_table = iwm_sdio_ids, - .probe = iwm_sdio_probe, - .remove = iwm_sdio_remove, -}; - -static int __init iwm_sdio_init_module(void) -{ - return sdio_register_driver(&iwm_sdio_driver); -} - -static void __exit iwm_sdio_exit_module(void) -{ - sdio_unregister_driver(&iwm_sdio_driver); -} - -module_init(iwm_sdio_init_module); -module_exit(iwm_sdio_exit_module); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR(IWM_COPYRIGHT " " IWM_AUTHOR); diff --git a/drivers/net/wireless/iwmc3200wifi/sdio.h b/drivers/net/wireless/iwmc3200wifi/sdio.h deleted file mode 100644 index aab6b6892e45..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/sdio.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_SDIO_H__ -#define __IWM_SDIO_H__ - -#define IWM_SDIO_DATA_ADDR 0x0 -#define IWM_SDIO_INTR_ENABLE_ADDR 0x14 -#define IWM_SDIO_INTR_STATUS_ADDR 0x13 -#define IWM_SDIO_INTR_CLEAR_ADDR 0x13 -#define IWM_SDIO_INTR_GET_SIZE_ADDR 0x2C - -#define IWM_SDIO_BLK_SIZE 256 - -#define iwm_to_if_sdio(i) (struct iwm_sdio_priv *)(iwm->private) - -struct iwm_sdio_priv { - struct sdio_func *func; - struct iwm_priv *iwm; - - struct workqueue_struct *isr_wq; - struct work_struct isr_worker; - - struct dentry *cccr_dentry; - - unsigned int blk_size; -}; - -#endif diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c deleted file mode 100644 index e3b4f7902daf..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/tx.c +++ /dev/null @@ -1,492 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -/* - * iwm Tx theory of operation: - * - * 1) We receive a 802.3 frame from the stack - * 2) We convert it to a 802.11 frame [iwm_xmit_frame] - * 3) We queue it to its corresponding tx queue [iwm_xmit_frame] - * 4) We schedule the tx worker. There is one worker per tx - * queue. [iwm_xmit_frame] - * 5) The tx worker is scheduled - * 6) We go through every queued skb on the tx queue, and for each - * and every one of them: [iwm_tx_worker] - * a) We check if we have enough Tx credits (see below for a Tx - * credits description) for the frame length. [iwm_tx_worker] - * b) If we do, we aggregate the Tx frame into a UDMA one, by - * concatenating one REPLY_TX command per Tx frame. [iwm_tx_worker] - * c) When we run out of credits, or when we reach the maximum - * concatenation size, we actually send the concatenated UDMA - * frame. [iwm_tx_worker] - * - * When we run out of Tx credits, the skbs are filling the tx queue, - * and eventually we will stop the netdev queue. [iwm_tx_worker] - * The tx queue is emptied as we're getting new tx credits, by - * scheduling the tx_worker. [iwm_tx_credit_inc] - * The netdev queue is started again when we have enough tx credits, - * and when our tx queue has some reasonable amout of space available - * (i.e. half of the max size). [iwm_tx_worker] - */ - -#include -#include -#include - -#include "iwm.h" -#include "debug.h" -#include "commands.h" -#include "hal.h" -#include "umac.h" -#include "bus.h" - -#define IWM_UMAC_PAGE_ALLOC_WRAP 0xffff - -#define BYTES_TO_PAGES(n) (1 + ((n) >> ilog2(IWM_UMAC_PAGE_SIZE)) - \ - (((n) & (IWM_UMAC_PAGE_SIZE - 1)) == 0)) - -#define pool_id_to_queue(id) ((id < IWM_TX_CMD_QUEUE) ? id : id - 1) -#define queue_to_pool_id(q) ((q < IWM_TX_CMD_QUEUE) ? q : q + 1) - -/* require to hold tx_credit lock */ -static int iwm_tx_credit_get(struct iwm_tx_credit *tx_credit, int id) -{ - struct pool_entry *pool = &tx_credit->pools[id]; - struct spool_entry *spool = &tx_credit->spools[pool->sid]; - int spool_pages; - - /* number of pages can be taken from spool by this pool */ - spool_pages = spool->max_pages - spool->alloc_pages + - max(pool->min_pages - pool->alloc_pages, 0); - - return min(pool->max_pages - pool->alloc_pages, spool_pages); -} - -static bool iwm_tx_credit_ok(struct iwm_priv *iwm, int id, int nb) -{ - u32 npages = BYTES_TO_PAGES(nb); - - if (npages <= iwm_tx_credit_get(&iwm->tx_credit, id)) - return 1; - - set_bit(id, &iwm->tx_credit.full_pools_map); - - IWM_DBG_TX(iwm, DBG, "LINK: stop txq[%d], available credit: %d\n", - pool_id_to_queue(id), - iwm_tx_credit_get(&iwm->tx_credit, id)); - - return 0; -} - -void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages) -{ - struct pool_entry *pool; - struct spool_entry *spool; - int freed_pages; - int queue; - - BUG_ON(id >= IWM_MACS_OUT_GROUPS); - - pool = &iwm->tx_credit.pools[id]; - spool = &iwm->tx_credit.spools[pool->sid]; - - freed_pages = total_freed_pages - pool->total_freed_pages; - IWM_DBG_TX(iwm, DBG, "Free %d pages for pool[%d]\n", freed_pages, id); - - if (!freed_pages) { - IWM_DBG_TX(iwm, DBG, "No pages are freed by UMAC\n"); - return; - } else if (freed_pages < 0) - freed_pages += IWM_UMAC_PAGE_ALLOC_WRAP + 1; - - if (pool->alloc_pages > pool->min_pages) { - int spool_pages = pool->alloc_pages - pool->min_pages; - spool_pages = min(spool_pages, freed_pages); - spool->alloc_pages -= spool_pages; - } - - pool->alloc_pages -= freed_pages; - pool->total_freed_pages = total_freed_pages; - - IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, " - "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages, - pool->total_freed_pages, pool->sid, spool->alloc_pages); - - if (test_bit(id, &iwm->tx_credit.full_pools_map) && - (pool->alloc_pages < pool->max_pages / 2)) { - clear_bit(id, &iwm->tx_credit.full_pools_map); - - queue = pool_id_to_queue(id); - - IWM_DBG_TX(iwm, DBG, "LINK: start txq[%d], available " - "credit: %d\n", queue, - iwm_tx_credit_get(&iwm->tx_credit, id)); - queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); - } -} - -static void iwm_tx_credit_dec(struct iwm_priv *iwm, int id, int alloc_pages) -{ - struct pool_entry *pool; - struct spool_entry *spool; - int spool_pages; - - IWM_DBG_TX(iwm, DBG, "Allocate %d pages for pool[%d]\n", - alloc_pages, id); - - BUG_ON(id >= IWM_MACS_OUT_GROUPS); - - pool = &iwm->tx_credit.pools[id]; - spool = &iwm->tx_credit.spools[pool->sid]; - - spool_pages = pool->alloc_pages + alloc_pages - pool->min_pages; - - if (pool->alloc_pages >= pool->min_pages) - spool->alloc_pages += alloc_pages; - else if (spool_pages > 0) - spool->alloc_pages += spool_pages; - - pool->alloc_pages += alloc_pages; - - IWM_DBG_TX(iwm, DBG, "Pool[%d] pages alloc: %d, total_freed: %d, " - "Spool[%d] pages alloc: %d\n", id, pool->alloc_pages, - pool->total_freed_pages, pool->sid, spool->alloc_pages); -} - -int iwm_tx_credit_alloc(struct iwm_priv *iwm, int id, int nb) -{ - u32 npages = BYTES_TO_PAGES(nb); - int ret = 0; - - spin_lock(&iwm->tx_credit.lock); - - if (!iwm_tx_credit_ok(iwm, id, nb)) { - IWM_DBG_TX(iwm, DBG, "No credit avaliable for pool[%d]\n", id); - ret = -ENOSPC; - goto out; - } - - iwm_tx_credit_dec(iwm, id, npages); - - out: - spin_unlock(&iwm->tx_credit.lock); - return ret; -} - -/* - * Since we're on an SDIO or USB bus, we are not sharing memory - * for storing to be transmitted frames. The host needs to push - * them upstream. As a consequence there needs to be a way for - * the target to let us know if it can actually take more TX frames - * or not. This is what Tx credits are for. - * - * For each Tx HW queue, we have a Tx pool, and then we have one - * unique super pool (spool), which is actually a global pool of - * all the UMAC pages. - * For each Tx pool we have a min_pages, a max_pages fields, and a - * alloc_pages fields. The alloc_pages tracks the number of pages - * currently allocated from the tx pool. - * Here are the rules to check if given a tx frame we have enough - * tx credits for it: - * 1) We translate the frame length into a number of UMAC pages. - * Let's call them n_pages. - * 2) For the corresponding tx pool, we check if n_pages + - * pool->alloc_pages is higher than pool->min_pages. min_pages - * represent a set of pre-allocated pages on the tx pool. If - * that's the case, then we need to allocate those pages from - * the spool. We can do so until we reach spool->max_pages. - * 3) Each tx pool is not allowed to allocate more than pool->max_pages - * from the spool, so once we're over min_pages, we can allocate - * pages from the spool, but not more than max_pages. - * - * When the tx code path needs to send a tx frame, it checks first - * if it has enough tx credits, following those rules. [iwm_tx_credit_get] - * If it does, it then updates the pool and spool counters and - * then send the frame. [iwm_tx_credit_alloc and iwm_tx_credit_dec] - * On the other side, when the UMAC is done transmitting frames, it - * will send a credit update notification to the host. This is when - * the pool and spool counters gets to be decreased. [iwm_tx_credit_inc, - * called from rx.c:iwm_ntf_tx_credit_update] - * - */ -void iwm_tx_credit_init_pools(struct iwm_priv *iwm, - struct iwm_umac_notif_alive *alive) -{ - int i, sid, pool_pages; - - spin_lock(&iwm->tx_credit.lock); - - iwm->tx_credit.pool_nr = le16_to_cpu(alive->page_grp_count); - iwm->tx_credit.full_pools_map = 0; - memset(&iwm->tx_credit.spools[0], 0, sizeof(struct spool_entry)); - - IWM_DBG_TX(iwm, DBG, "Pools number is %d\n", iwm->tx_credit.pool_nr); - - for (i = 0; i < iwm->tx_credit.pool_nr; i++) { - __le32 page_grp_state = alive->page_grp_state[i]; - - iwm->tx_credit.pools[i].id = GET_VAL32(page_grp_state, - UMAC_ALIVE_PAGE_STS_GRP_NUM); - iwm->tx_credit.pools[i].sid = GET_VAL32(page_grp_state, - UMAC_ALIVE_PAGE_STS_SGRP_NUM); - iwm->tx_credit.pools[i].min_pages = GET_VAL32(page_grp_state, - UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE); - iwm->tx_credit.pools[i].max_pages = GET_VAL32(page_grp_state, - UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE); - iwm->tx_credit.pools[i].alloc_pages = 0; - iwm->tx_credit.pools[i].total_freed_pages = 0; - - sid = iwm->tx_credit.pools[i].sid; - pool_pages = iwm->tx_credit.pools[i].min_pages; - - if (iwm->tx_credit.spools[sid].max_pages == 0) { - iwm->tx_credit.spools[sid].id = sid; - iwm->tx_credit.spools[sid].max_pages = - GET_VAL32(page_grp_state, - UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE); - iwm->tx_credit.spools[sid].alloc_pages = 0; - } - - iwm->tx_credit.spools[sid].alloc_pages += pool_pages; - - IWM_DBG_TX(iwm, DBG, "Pool idx: %d, id: %d, sid: %d, capacity " - "min: %d, max: %d, pool alloc: %d, total_free: %d, " - "super poll alloc: %d\n", - i, iwm->tx_credit.pools[i].id, - iwm->tx_credit.pools[i].sid, - iwm->tx_credit.pools[i].min_pages, - iwm->tx_credit.pools[i].max_pages, - iwm->tx_credit.pools[i].alloc_pages, - iwm->tx_credit.pools[i].total_freed_pages, - iwm->tx_credit.spools[sid].alloc_pages); - } - - spin_unlock(&iwm->tx_credit.lock); -} - -#define IWM_UDMA_HDR_LEN sizeof(struct iwm_umac_wifi_out_hdr) - -static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb, - int pool_id, u8 *buf) -{ - struct iwm_umac_wifi_out_hdr *hdr = (struct iwm_umac_wifi_out_hdr *)buf; - struct iwm_udma_wifi_cmd udma_cmd; - struct iwm_umac_cmd umac_cmd; - struct iwm_tx_info *tx_info = skb_to_tx_info(skb); - - udma_cmd.count = cpu_to_le16(skb->len + - sizeof(struct iwm_umac_fw_cmd_hdr)); - /* set EOP to 0 here. iwm_udma_wifi_hdr_set_eop() will be - * called later to set EOP for the last packet. */ - udma_cmd.eop = 0; - udma_cmd.credit_group = pool_id; - udma_cmd.ra_tid = tx_info->sta << 4 | tx_info->tid; - udma_cmd.lmac_offset = 0; - - umac_cmd.id = REPLY_TX; - umac_cmd.count = cpu_to_le16(skb->len); - umac_cmd.color = tx_info->color; - umac_cmd.resp = 0; - umac_cmd.seq_num = cpu_to_le16(iwm_alloc_wifi_cmd_seq(iwm)); - - iwm_build_udma_wifi_hdr(iwm, &hdr->hw_hdr, &udma_cmd); - iwm_build_umac_hdr(iwm, &hdr->sw_hdr, &umac_cmd); - - memcpy(buf + sizeof(*hdr), skb->data, skb->len); - - return 0; -} - -static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, - struct iwm_tx_queue *txq) -{ - int ret; - - if (!txq->concat_count) - return 0; - - IWM_DBG_TX(iwm, DBG, "Send concatenated Tx: queue %d, %d bytes\n", - txq->id, txq->concat_count); - - /* mark EOP for the last packet */ - iwm_udma_wifi_hdr_set_eop(iwm, txq->concat_ptr, 1); - - ret = iwm_bus_send_chunk(iwm, txq->concat_buf, txq->concat_count); - - txq->concat_count = 0; - txq->concat_ptr = txq->concat_buf; - - return ret; -} - -#define CONFIG_IWM_TX_CONCATENATED 1 - -void iwm_tx_worker(struct work_struct *work) -{ - struct iwm_priv *iwm; - struct iwm_tx_info *tx_info = NULL; - struct sk_buff *skb; - int cmdlen, ret; - struct iwm_tx_queue *txq; - int pool_id; - - txq = container_of(work, struct iwm_tx_queue, worker); - iwm = container_of(txq, struct iwm_priv, txq[txq->id]); - - pool_id = queue_to_pool_id(txq->id); - - while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) && - !skb_queue_empty(&txq->queue)) { - - skb = skb_dequeue(&txq->queue); - tx_info = skb_to_tx_info(skb); - cmdlen = IWM_UDMA_HDR_LEN + skb->len; - - IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: " - "%d, color: %d\n", txq->id, skb, tx_info->sta, - tx_info->color); - -#if !CONFIG_IWM_TX_CONCATENATED - /* temporarily keep this to comparing the performance */ - ret = iwm_send_packet(iwm, skb, pool_id); -#else - - if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE) - iwm_tx_send_concat_packets(iwm, txq); - - ret = iwm_tx_credit_alloc(iwm, pool_id, cmdlen); - if (ret) { - IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue " - "%d, Tx worker stopped\n", txq->id); - skb_queue_head(&txq->queue, skb); - break; - } - - txq->concat_ptr = txq->concat_buf + txq->concat_count; - iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr); - txq->concat_count += ALIGN(cmdlen, 16); -#endif - kfree_skb(skb); - } - - iwm_tx_send_concat_packets(iwm, txq); - - if (__netif_subqueue_stopped(iwm_to_ndev(iwm), txq->id) && - !test_bit(pool_id, &iwm->tx_credit.full_pools_map) && - (skb_queue_len(&txq->queue) < IWM_TX_LIST_SIZE / 2)) { - IWM_DBG_TX(iwm, DBG, "LINK: start netif_subqueue[%d]", txq->id); - netif_wake_subqueue(iwm_to_ndev(iwm), txq->id); - } -} - -int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev) -{ - struct iwm_priv *iwm = ndev_to_iwm(netdev); - struct net_device *ndev = iwm_to_ndev(iwm); - struct wireless_dev *wdev = iwm_to_wdev(iwm); - u8 *dst_addr; - struct iwm_tx_info *tx_info; - struct iwm_tx_queue *txq; - struct iwm_sta_info *sta_info; - u8 sta_id; - u16 queue; - int ret; - - if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { - IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: " - "not associated\n"); - netif_tx_stop_all_queues(netdev); - goto drop; - } - - queue = skb_get_queue_mapping(skb); - BUG_ON(queue >= IWM_TX_DATA_QUEUES); /* no iPAN yet */ - - txq = &iwm->txq[queue]; - - /* No free space for Tx, tx_worker is too slow */ - if (skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) { - IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue); - netif_stop_subqueue(netdev, queue); - return NETDEV_TX_BUSY; - } - - ret = ieee80211_data_from_8023(skb, netdev->dev_addr, wdev->iftype, - iwm->bssid, 0); - if (ret) { - IWM_ERR(iwm, "build wifi header failed\n"); - goto drop; - } - - dst_addr = ((struct ieee80211_hdr *)(skb->data))->addr1; - - for (sta_id = 0; sta_id < IWM_STA_TABLE_NUM; sta_id++) { - sta_info = &iwm->sta_table[sta_id]; - if (sta_info->valid && - !memcmp(dst_addr, sta_info->addr, ETH_ALEN)) - break; - } - - if (sta_id == IWM_STA_TABLE_NUM) { - IWM_ERR(iwm, "STA %pM not found in sta_table, Tx ignored\n", - dst_addr); - goto drop; - } - - tx_info = skb_to_tx_info(skb); - tx_info->sta = sta_id; - tx_info->color = sta_info->color; - /* UMAC uses TID 8 (vs. 0) for non QoS packets */ - if (sta_info->qos) - tx_info->tid = skb->priority; - else - tx_info->tid = IWM_UMAC_MGMT_TID; - - skb_queue_tail(&iwm->txq[queue].queue, skb); - - queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); - - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - return NETDEV_TX_OK; - - drop: - ndev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h deleted file mode 100644 index c5a14ae3160a..000000000000 --- a/drivers/net/wireless/iwmc3200wifi/umac.h +++ /dev/null @@ -1,752 +0,0 @@ -/* - * Intel Wireless Multicomm 3200 WiFi driver - * - * Copyright (C) 2009 Intel Corporation. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Intel Corporation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * - * Intel Corporation - * Samuel Ortiz - * Zhu Yi - * - */ - -#ifndef __IWM_UMAC_H__ -#define __IWM_UMAC_H__ - -struct iwm_udma_in_hdr { - __le32 cmd; - __le32 size; -} __attribute__ ((packed)); - -struct iwm_udma_out_nonwifi_hdr { - __le32 cmd; - __le32 addr; - __le32 op1_sz; - __le32 op2; -} __attribute__ ((packed)); - -struct iwm_udma_out_wifi_hdr { - __le32 cmd; - __le32 meta_data; -} __attribute__ ((packed)); - -/* Sequence numbering */ -#define UMAC_WIFI_SEQ_NUM_BASE 1 -#define UMAC_WIFI_SEQ_NUM_MAX 0x4000 -#define UMAC_NONWIFI_SEQ_NUM_BASE 1 -#define UMAC_NONWIFI_SEQ_NUM_MAX 0x10 - -/* MAC address address */ -#define WICO_MAC_ADDRESS_ADDR 0x604008F8 - -/* RA / TID */ -#define UMAC_HDI_ACT_TBL_IDX_TID_POS 0 -#define UMAC_HDI_ACT_TBL_IDX_TID_SEED 0xF - -#define UMAC_HDI_ACT_TBL_IDX_RA_POS 4 -#define UMAC_HDI_ACT_TBL_IDX_RA_SEED 0xF - -#define UMAC_HDI_ACT_TBL_IDX_RA_UMAC 0xF -#define UMAC_HDI_ACT_TBL_IDX_TID_UMAC 0x9 -#define UMAC_HDI_ACT_TBL_IDX_TID_LMAC 0xA - -#define UMAC_HDI_ACT_TBL_IDX_HOST_CMD \ - ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ - (UMAC_HDI_ACT_TBL_IDX_TID_UMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) -#define UMAC_HDI_ACT_TBL_IDX_UMAC_CMD \ - ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ - (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) - -/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */ -#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0 -#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF - -/* iwm_umac_notif_alive.page_grp_state Super group number -- bits [7:4] */ -#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_POS 4 -#define UMAC_ALIVE_PAGE_STS_SGRP_NUM_SEED 0xF - -/* iwm_umac_notif_alive.page_grp_state Group min size -- bits [15:8] */ -#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_POS 8 -#define UMAC_ALIVE_PAGE_STS_GRP_MIN_SIZE_SEED 0xFF - -/* iwm_umac_notif_alive.page_grp_state Group max size -- bits [23:16] */ -#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_POS 16 -#define UMAC_ALIVE_PAGE_STS_GRP_MAX_SIZE_SEED 0xFF - -/* iwm_umac_notif_alive.page_grp_state Super group max size -- bits [31:24] */ -#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_POS 24 -#define UMAC_ALIVE_PAGE_STS_SGRP_MAX_SIZE_SEED 0xFF - -/* Barkers */ -#define UMAC_REBOOT_BARKER 0xdeadbeef -#define UMAC_ACK_BARKER 0xfeedbabe -#define UMAC_PAD_TERMINAL 0xadadadad - -/* UMAC JMP address */ -#define UMAC_MU_FW_INST_DATA_12_ADDR 0xBF0000 - -/* iwm_umac_hdi_out_hdr.cmd OP code -- bits [3:0] */ -#define UMAC_HDI_OUT_CMD_OPCODE_POS 0 -#define UMAC_HDI_OUT_CMD_OPCODE_SEED 0xF - -/* iwm_umac_hdi_out_hdr.cmd End-Of-Transfer -- bits [10:10] */ -#define UMAC_HDI_OUT_CMD_EOT_POS 10 -#define UMAC_HDI_OUT_CMD_EOT_SEED 0x1 - -/* iwm_umac_hdi_out_hdr.cmd UTFD only usage -- bits [11:11] */ -#define UMAC_HDI_OUT_CMD_UTFD_ONLY_POS 11 -#define UMAC_HDI_OUT_CMD_UTFD_ONLY_SEED 0x1 - -/* iwm_umac_hdi_out_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */ -#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_POS 12 -#define UDMA_HDI_OUT_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF - -/* iwm_umac_hdi_out_hdr.cmd Signature -- bits [31:16] */ -#define UMAC_HDI_OUT_CMD_SIGNATURE_POS 16 -#define UMAC_HDI_OUT_CMD_SIGNATURE_SEED 0xFFFF - -/* iwm_umac_hdi_out_hdr.meta_data Byte count -- bits [11:0] */ -#define UMAC_HDI_OUT_BYTE_COUNT_POS 0 -#define UMAC_HDI_OUT_BYTE_COUNT_SEED 0xFFF - -/* iwm_umac_hdi_out_hdr.meta_data Credit group -- bits [15:12] */ -#define UMAC_HDI_OUT_CREDIT_GRP_POS 12 -#define UMAC_HDI_OUT_CREDIT_GRP_SEED 0xF - -/* iwm_umac_hdi_out_hdr.meta_data RA/TID -- bits [23:16] */ -#define UMAC_HDI_OUT_RATID_POS 16 -#define UMAC_HDI_OUT_RATID_SEED 0xFF - -/* iwm_umac_hdi_out_hdr.meta_data LMAC offset -- bits [31:24] */ -#define UMAC_HDI_OUT_LMAC_OFFSET_POS 24 -#define UMAC_HDI_OUT_LMAC_OFFSET_SEED 0xFF - -/* Signature */ -#define UMAC_HDI_OUT_SIGNATURE 0xCBBC - -/* buffer alignment */ -#define UMAC_HDI_BUF_ALIGN_MSK 0xF - -/* iwm_umac_hdi_in_hdr.cmd OP code -- bits [3:0] */ -#define UMAC_HDI_IN_CMD_OPCODE_POS 0 -#define UMAC_HDI_IN_CMD_OPCODE_SEED 0xF - -/* iwm_umac_hdi_in_hdr.cmd Non-WiFi API response -- bits [6:4] */ -#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_POS 4 -#define UMAC_HDI_IN_CMD_NON_WIFI_RESP_SEED 0x7 - -/* iwm_umac_hdi_in_hdr.cmd WiFi API source -- bits [5:4] */ -#define UMAC_HDI_IN_CMD_SOURCE_POS 4 -#define UMAC_HDI_IN_CMD_SOURCE_SEED 0x3 - -/* iwm_umac_hdi_in_hdr.cmd WiFi API EOT -- bits [6:6] */ -#define UMAC_HDI_IN_CMD_EOT_POS 6 -#define UMAC_HDI_IN_CMD_EOT_SEED 0x1 - -/* iwm_umac_hdi_in_hdr.cmd timestamp present -- bits [7:7] */ -#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_POS 7 -#define UMAC_HDI_IN_CMD_TIME_STAMP_PRESENT_SEED 0x1 - -/* iwm_umac_hdi_in_hdr.cmd WiFi Non-last AMSDU -- bits [8:8] */ -#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_POS 8 -#define UMAC_HDI_IN_CMD_NON_LAST_AMSDU_SEED 0x1 - -/* iwm_umac_hdi_in_hdr.cmd WiFi HW sequence number -- bits [31:9] */ -#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_POS 9 -#define UMAC_HDI_IN_CMD_HW_SEQ_NUM_SEED 0x7FFFFF - -/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW sequence number -- bits [12:15] */ -#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_POS 12 -#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SEQ_NUM_SEED 0xF - -/* iwm_umac_hdi_in_hdr.cmd Non-WiFi HW signature -- bits [16:31] */ -#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_POS 16 -#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG_SEED 0xFFFF - -/* Fixed Non-WiFi signature */ -#define UDMA_HDI_IN_CMD_NON_WIFI_HW_SIG 0xCBBC - -/* IN NTFY op-codes */ -#define UMAC_NOTIFY_OPCODE_ALIVE 0xA1 -#define UMAC_NOTIFY_OPCODE_INIT_COMPLETE 0xA2 -#define UMAC_NOTIFY_OPCODE_WIFI_CORE_STATUS 0xA3 -#define UMAC_NOTIFY_OPCODE_ERROR 0xA4 -#define UMAC_NOTIFY_OPCODE_DEBUG 0xA5 -#define UMAC_NOTIFY_OPCODE_WIFI_IF_WRAPPER 0xB0 -#define UMAC_NOTIFY_OPCODE_STATS 0xB1 -#define UMAC_NOTIFY_OPCODE_PAGE_DEALLOC 0xB3 -#define UMAC_NOTIFY_OPCODE_RX_TICKET 0xB4 -#define UMAC_NOTIFY_OPCODE_MAX (UMAC_NOTIFY_OPCODE_RX_TICKET -\ - UMAC_NOTIFY_OPCODE_ALIVE + 1) -#define UMAC_NOTIFY_OPCODE_FIRST (UMAC_NOTIFY_OPCODE_ALIVE) - -/* HDI OUT OP CODE */ -#define UMAC_HDI_OUT_OPCODE_PING 0x0 -#define UMAC_HDI_OUT_OPCODE_READ 0x1 -#define UMAC_HDI_OUT_OPCODE_WRITE 0x2 -#define UMAC_HDI_OUT_OPCODE_JUMP 0x3 -#define UMAC_HDI_OUT_OPCODE_REBOOT 0x4 -#define UMAC_HDI_OUT_OPCODE_WRITE_PERSISTENT 0x5 -#define UMAC_HDI_OUT_OPCODE_READ_PERSISTENT 0x6 -#define UMAC_HDI_OUT_OPCODE_READ_MODIFY_WRITE 0x7 -/* #define UMAC_HDI_OUT_OPCODE_RESERVED 0x8..0xA */ -#define UMAC_HDI_OUT_OPCODE_WRITE_AUX_REG 0xB -#define UMAC_HDI_OUT_OPCODE_WIFI 0xF - -/* HDI IN OP CODE -- Non WiFi*/ -#define UMAC_HDI_IN_OPCODE_PING 0x0 -#define UMAC_HDI_IN_OPCODE_READ 0x1 -#define UMAC_HDI_IN_OPCODE_WRITE 0x2 -#define UMAC_HDI_IN_OPCODE_WRITE_PERSISTENT 0x5 -#define UMAC_HDI_IN_OPCODE_READ_PERSISTENT 0x6 -#define UMAC_HDI_IN_OPCODE_READ_MODIFY_WRITE 0x7 -#define UMAC_HDI_IN_OPCODE_EP_MGMT 0x8 -#define UMAC_HDI_IN_OPCODE_CREDIT_CHANGE 0x9 -#define UMAC_HDI_IN_OPCODE_CTRL_DATABASE 0xA -#define UMAC_HDI_IN_OPCODE_WRITE_AUX_REG 0xB -#define UMAC_HDI_IN_OPCODE_NONWIFI_MAX \ - (UMAC_HDI_IN_OPCODE_WRITE_AUX_REG + 1) -#define UMAC_HDI_IN_OPCODE_WIFI 0xF - -/* HDI IN SOURCE */ -#define UMAC_HDI_IN_SOURCE_FHRX 0x0 -#define UMAC_HDI_IN_SOURCE_UDMA 0x1 -#define UMAC_HDI_IN_SOURCE_FW 0x2 -#define UMAC_HDI_IN_SOURCE_RESERVED 0x3 - -/* OUT CMD op-codes */ -#define UMAC_CMD_OPCODE_ECHO 0x01 -#define UMAC_CMD_OPCODE_HALT 0x02 -#define UMAC_CMD_OPCODE_RESET 0x03 -#define UMAC_CMD_OPCODE_BULK_EP_INACT_TIMEOUT 0x09 -#define UMAC_CMD_OPCODE_URB_CANCEL_ACK 0x0A -#define UMAC_CMD_OPCODE_DCACHE_FLUSH 0x0B -#define UMAC_CMD_OPCODE_EEPROM_PROXY 0x0C -#define UMAC_CMD_OPCODE_TX_ECHO 0x0D -#define UMAC_CMD_OPCODE_DBG_MON 0x0E -#define UMAC_CMD_OPCODE_INTERNAL_TX 0x0F -#define UMAC_CMD_OPCODE_SET_PARAM_FIX 0x10 -#define UMAC_CMD_OPCODE_SET_PARAM_VAR 0x11 -#define UMAC_CMD_OPCODE_GET_PARAM 0x12 -#define UMAC_CMD_OPCODE_DBG_EVENT_WRAPPER 0x13 -#define UMAC_CMD_OPCODE_TARGET 0x14 -#define UMAC_CMD_OPCODE_STATISTIC_REQUEST 0x15 -#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16 -#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17 -#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18 -#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA -#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB -#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC -#define UMAC_CMD_OPCODE_WIFI_IF_WRAPPER 0xFD -#define UMAC_CMD_OPCODE_WIFI_WRAPPER 0xFE -#define UMAC_CMD_OPCODE_WIFI_PASS_THROUGH 0xFF - -/* UMAC WiFi interface op-codes */ -#define UMAC_WIFI_IF_CMD_SET_PROFILE 0x11 -#define UMAC_WIFI_IF_CMD_INVALIDATE_PROFILE 0x12 -#define UMAC_WIFI_IF_CMD_SET_EXCLUDE_LIST 0x13 -#define UMAC_WIFI_IF_CMD_SCAN_REQUEST 0x14 -#define UMAC_WIFI_IF_CMD_SCAN_CONFIG 0x15 -#define UMAC_WIFI_IF_CMD_ADD_WEP40_KEY 0x16 -#define UMAC_WIFI_IF_CMD_ADD_WEP104_KEY 0x17 -#define UMAC_WIFI_IF_CMD_ADD_TKIP_KEY 0x18 -#define UMAC_WIFI_IF_CMD_ADD_CCMP_KEY 0x19 -#define UMAC_WIFI_IF_CMD_REMOVE_KEY 0x1A -#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B -#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C -#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E -#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20 - -/* UMAC WiFi interface ports */ -#define UMAC_WIFI_IF_FLG_PORT_DEF 0x00 -#define UMAC_WIFI_IF_FLG_PORT_PAN 0x01 -#define UMAC_WIFI_IF_FLG_PORT_PAN_INVALID WIFI_IF_FLG_PORT_DEF - -/* UMAC WiFi interface actions */ -#define UMAC_WIFI_IF_FLG_ACT_GET 0x10 -#define UMAC_WIFI_IF_FLG_ACT_SET 0x20 - -/* iwm_umac_fw_cmd_hdr.meta_data byte count -- bits [11:0] */ -#define UMAC_FW_CMD_BYTE_COUNT_POS 0 -#define UMAC_FW_CMD_BYTE_COUNT_SEED 0xFFF - -/* iwm_umac_fw_cmd_hdr.meta_data status -- bits [15:12] */ -#define UMAC_FW_CMD_STATUS_POS 12 -#define UMAC_FW_CMD_STATUS_SEED 0xF - -/* iwm_umac_fw_cmd_hdr.meta_data full TX command by Driver -- bits [16:16] */ -#define UMAC_FW_CMD_TX_DRV_FULL_CMD_POS 16 -#define UMAC_FW_CMD_TX_DRV_FULL_CMD_SEED 0x1 - -/* iwm_umac_fw_cmd_hdr.meta_data TX command by FW -- bits [17:17] */ -#define UMAC_FW_CMD_TX_FW_CMD_POS 17 -#define UMAC_FW_CMD_TX_FW_CMD_SEED 0x1 - -/* iwm_umac_fw_cmd_hdr.meta_data TX plaintext mode -- bits [18:18] */ -#define UMAC_FW_CMD_TX_PLAINTEXT_POS 18 -#define UMAC_FW_CMD_TX_PLAINTEXT_SEED 0x1 - -/* iwm_umac_fw_cmd_hdr.meta_data STA color -- bits [22:20] */ -#define UMAC_FW_CMD_TX_STA_COLOR_POS 20 -#define UMAC_FW_CMD_TX_STA_COLOR_SEED 0x7 - -/* iwm_umac_fw_cmd_hdr.meta_data TX life time (TU) -- bits [31:24] */ -#define UMAC_FW_CMD_TX_LIFETIME_TU_POS 24 -#define UMAC_FW_CMD_TX_LIFETIME_TU_SEED 0xFF - -/* iwm_dev_cmd_hdr.flags Response required -- bits [5:5] */ -#define UMAC_DEV_CMD_FLAGS_RESP_REQ_POS 5 -#define UMAC_DEV_CMD_FLAGS_RESP_REQ_SEED 0x1 - -/* iwm_dev_cmd_hdr.flags Aborted command -- bits [6:6] */ -#define UMAC_DEV_CMD_FLAGS_ABORT_POS 6 -#define UMAC_DEV_CMD_FLAGS_ABORT_SEED 0x1 - -/* iwm_dev_cmd_hdr.flags Internal command -- bits [7:7] */ -#define DEV_CMD_FLAGS_FLD_INTERNAL_POS 7 -#define DEV_CMD_FLAGS_FLD_INTERNAL_SEED 0x1 - -/* Rx */ -/* Rx actions */ -#define IWM_RX_TICKET_DROP 0x0 -#define IWM_RX_TICKET_RELEASE 0x1 -#define IWM_RX_TICKET_SNIFFER 0x2 -#define IWM_RX_TICKET_ENQUEUE 0x3 - -/* Rx flags */ -#define IWM_RX_TICKET_PAD_SIZE_MSK 0x2 -#define IWM_RX_TICKET_SPECIAL_SNAP_MSK 0x4 -#define IWM_RX_TICKET_AMSDU_MSK 0x8 -#define IWM_RX_TICKET_DROP_REASON_POS 4 -#define IWM_RX_TICKET_DROP_REASON_MSK (0x1F << RX_TICKET_FLAGS_DROP_REASON_POS) - -#define IWM_RX_DROP_NO_DROP 0x0 -#define IWM_RX_DROP_BAD_CRC 0x1 -/* L2P no address match */ -#define IWM_RX_DROP_LMAC_ADDR_FILTER 0x2 -/* Multicast address not in list */ -#define IWM_RX_DROP_MCAST_ADDR_FILTER 0x3 -/* Control frames are not sent to the driver */ -#define IWM_RX_DROP_CTL_FRAME 0x4 -/* Our frame is back */ -#define IWM_RX_DROP_OUR_TX 0x5 -/* Association class filtering */ -#define IWM_RX_DROP_CLASS_FILTER 0x6 -/* Duplicated frame */ -#define IWM_RX_DROP_DUPLICATE_FILTER 0x7 -/* Decryption error */ -#define IWM_RX_DROP_SEC_ERR 0x8 -/* Unencrypted frame while encryption is on */ -#define IWM_RX_DROP_SEC_NO_ENCRYPTION 0x9 -/* Replay check failure */ -#define IWM_RX_DROP_SEC_REPLAY_ERR 0xa -/* uCode and FW key color mismatch, check before replay */ -#define IWM_RX_DROP_SEC_KEY_COLOR_MISMATCH 0xb -#define IWM_RX_DROP_SEC_TKIP_COUNTER_MEASURE 0xc -/* No fragmentations Db is found */ -#define IWM_RX_DROP_FRAG_NO_RESOURCE 0xd -/* Fragmention Db has seqCtl mismatch Vs. non-1st frag */ -#define IWM_RX_DROP_FRAG_ERR 0xe -#define IWM_RX_DROP_FRAG_LOST 0xf -#define IWM_RX_DROP_FRAG_COMPLETE 0x10 -/* Should be handled by UMAC */ -#define IWM_RX_DROP_MANAGEMENT 0x11 -/* STA not found by UMAC */ -#define IWM_RX_DROP_NO_STATION 0x12 -/* NULL or QoS NULL */ -#define IWM_RX_DROP_NULL_DATA 0x13 -#define IWM_RX_DROP_BA_REORDER_OLD_SEQCTL 0x14 -#define IWM_RX_DROP_BA_REORDER_DUPLICATE 0x15 - -struct iwm_rx_ticket { - __le16 action; - __le16 id; - __le16 flags; - u8 payload_offset; /* includes: MAC header, pad, IV */ - u8 tail_len; /* includes: MIC, ICV, CRC (w/o STATUS) */ -} __attribute__ ((packed)); - -struct iwm_rx_mpdu_hdr { - __le16 len; - __le16 reserved; -} __attribute__ ((packed)); - -/* UMAC SW WIFI API */ - -struct iwm_dev_cmd_hdr { - u8 cmd; - u8 flags; - __le16 seq_num; -} __attribute__ ((packed)); - -struct iwm_umac_fw_cmd_hdr { - __le32 meta_data; - struct iwm_dev_cmd_hdr cmd; -} __attribute__ ((packed)); - -struct iwm_umac_wifi_out_hdr { - struct iwm_udma_out_wifi_hdr hw_hdr; - struct iwm_umac_fw_cmd_hdr sw_hdr; -} __attribute__ ((packed)); - -struct iwm_umac_nonwifi_out_hdr { - struct iwm_udma_out_nonwifi_hdr hw_hdr; -} __attribute__ ((packed)); - -struct iwm_umac_wifi_in_hdr { - struct iwm_udma_in_hdr hw_hdr; - struct iwm_umac_fw_cmd_hdr sw_hdr; -} __attribute__ ((packed)); - -struct iwm_umac_nonwifi_in_hdr { - struct iwm_udma_in_hdr hw_hdr; - __le32 time_stamp; -} __attribute__ ((packed)); - -#define IWM_UMAC_PAGE_SIZE 0x200 - -/* Notify structures */ -struct iwm_fw_version { - u8 minor; - u8 major; - __le16 id; -}; - -struct iwm_fw_build { - u8 type; - u8 subtype; - u8 platform; - u8 opt; -}; - -struct iwm_fw_alive_hdr { - struct iwm_fw_version ver; - struct iwm_fw_build build; - __le32 os_build; - __le32 log_hdr_addr; - __le32 log_buf_addr; - __le32 sys_timer_addr; -}; - -#define WAIT_NOTIF_TIMEOUT (2 * HZ) -#define SCAN_COMPLETE_TIMEOUT (3 * HZ) - -#define UMAC_NTFY_ALIVE_STATUS_ERR 0xDEAD -#define UMAC_NTFY_ALIVE_STATUS_OK 0xCAFE - -#define UMAC_NTFY_INIT_COMPLETE_STATUS_ERR 0xDEAD -#define UMAC_NTFY_INIT_COMPLETE_STATUS_OK 0xCAFE - -#define UMAC_NTFY_WIFI_CORE_STATUS_LINK_EN 0x40 -#define UMAC_NTFY_WIFI_CORE_STATUS_MLME_EN 0x80 - -#define IWM_MACS_OUT_GROUPS 6 -#define IWM_MACS_OUT_SGROUPS 1 - - -#define WIFI_IF_NTFY_ASSOC_START 0x80 -#define WIFI_IF_NTFY_ASSOC_COMPLETE 0x81 -#define WIFI_IF_NTFY_PROFILE_INVALIDATE_COMPLETE 0x82 -#define WIFI_IF_NTFY_CONNECTION_TERMINATED 0x83 -#define WIFI_IF_NTFY_SCAN_COMPLETE 0x84 -#define WIFI_IF_NTFY_STA_TABLE_CHANGE 0x85 -#define WIFI_IF_NTFY_EXTENDED_IE_REQUIRED 0x86 -#define WIFI_IF_NTFY_RADIO_PREEMPTION 0x87 -#define WIFI_IF_NTFY_BSS_TRK_TABLE_CHANGED 0x88 -#define WIFI_IF_NTFY_BSS_TRK_ENTRIES_REMOVED 0x89 -#define WIFI_IF_NTFY_LINK_QUALITY_STATISTICS 0x8A -#define WIFI_IF_NTFY_MGMT_FRAME 0x8B - -/* DEBUG INDICATIONS */ -#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_START 0xE0 -#define WIFI_DBG_IF_NTFY_SCAN_SUPER_JOB_COMPLETE 0xE1 -#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_START 0xE2 -#define WIFI_DBG_IF_NTFY_SCAN_CHANNEL_RESULT 0xE3 -#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_START 0xE4 -#define WIFI_DBG_IF_NTFY_SCAN_MINI_JOB_COMPLETE 0xE5 -#define WIFI_DBG_IF_NTFY_CNCT_ATC_START 0xE6 -#define WIFI_DBG_IF_NTFY_COEX_NOTIFICATION 0xE7 -#define WIFI_DBG_IF_NTFY_COEX_HANDLE_ENVELOP 0xE8 -#define WIFI_DBG_IF_NTFY_COEX_HANDLE_RELEASE_ENVELOP 0xE9 - -#define WIFI_IF_NTFY_MAX 0xff - -/* Notification structures */ -struct iwm_umac_notif_wifi_if { - struct iwm_umac_wifi_in_hdr hdr; - u8 status; - u8 flags; - __le16 buf_size; -} __attribute__ ((packed)); - -#define UMAC_ROAM_REASON_FIRST_SELECTION 0x1 -#define UMAC_ROAM_REASON_AP_DEAUTH 0x2 -#define UMAC_ROAM_REASON_AP_CONNECT_LOST 0x3 -#define UMAC_ROAM_REASON_RSSI 0x4 -#define UMAC_ROAM_REASON_AP_ASSISTED_ROAM 0x5 -#define UMAC_ROAM_REASON_IBSS_COALESCING 0x6 - -struct iwm_umac_notif_assoc_start { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 roam_reason; - u8 bssid[ETH_ALEN]; - u8 reserved[2]; -} __attribute__ ((packed)); - -#define UMAC_ASSOC_COMPLETE_SUCCESS 0x0 -#define UMAC_ASSOC_COMPLETE_FAILURE 0x1 - -struct iwm_umac_notif_assoc_complete { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 status; - u8 bssid[ETH_ALEN]; - u8 band; - u8 channel; -} __attribute__ ((packed)); - -#define UMAC_PROFILE_INVALID_ASSOC_TIMEOUT 0x0 -#define UMAC_PROFILE_INVALID_ROAM_TIMEOUT 0x1 -#define UMAC_PROFILE_INVALID_REQUEST 0x2 -#define UMAC_PROFILE_INVALID_RF_PREEMPTED 0x3 - -struct iwm_umac_notif_profile_invalidate { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 reason; -} __attribute__ ((packed)); - -#define UMAC_SCAN_RESULT_SUCCESS 0x0 -#define UMAC_SCAN_RESULT_ABORTED 0x1 -#define UMAC_SCAN_RESULT_REJECTED 0x2 -#define UMAC_SCAN_RESULT_FAILED 0x3 - -struct iwm_umac_notif_scan_complete { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 type; - __le32 result; - u8 seq_num; -} __attribute__ ((packed)); - -#define UMAC_OPCODE_ADD_MODIFY 0x0 -#define UMAC_OPCODE_REMOVE 0x1 -#define UMAC_OPCODE_CLEAR_ALL 0x2 - -#define UMAC_STA_FLAG_QOS 0x1 - -struct iwm_umac_notif_sta_info { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 opcode; - u8 mac_addr[ETH_ALEN]; - u8 sta_id; /* bits 0-3: station ID, bits 4-7: station color */ - u8 flags; -} __attribute__ ((packed)); - -#define UMAC_BAND_2GHZ 0 -#define UMAC_BAND_5GHZ 1 - -#define UMAC_CHANNEL_WIDTH_20MHZ 0 -#define UMAC_CHANNEL_WIDTH_40MHZ 1 - -struct iwm_umac_notif_bss_info { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 type; - __le32 timestamp; - __le16 table_idx; - __le16 frame_len; - u8 band; - u8 channel; - s8 rssi; - u8 reserved; - u8 frame_buf[1]; -} __attribute__ ((packed)); - -#define IWM_BSS_REMOVE_INDEX_MSK 0x0fff -#define IWM_BSS_REMOVE_FLAGS_MSK 0xfc00 - -#define IWM_BSS_REMOVE_FLG_AGE 0x1000 -#define IWM_BSS_REMOVE_FLG_TIMEOUT 0x2000 -#define IWM_BSS_REMOVE_FLG_TABLE_FULL 0x4000 - -struct iwm_umac_notif_bss_removed { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le32 count; - __le16 entries[0]; -} __attribute__ ((packed)); - -struct iwm_umac_notif_mgt_frame { - struct iwm_umac_notif_wifi_if mlme_hdr; - __le16 len; - u8 frame[1]; -} __attribute__ ((packed)); - -struct iwm_umac_notif_alive { - struct iwm_umac_wifi_in_hdr hdr; - __le16 status; - __le16 reserved1; - struct iwm_fw_alive_hdr alive_data; - __le16 reserved2; - __le16 page_grp_count; - __le32 page_grp_state[IWM_MACS_OUT_GROUPS]; -} __attribute__ ((packed)); - -struct iwm_umac_notif_init_complete { - struct iwm_umac_wifi_in_hdr hdr; - __le16 status; - __le16 reserved; -} __attribute__ ((packed)); - -/* error categories */ -enum { - UMAC_SYS_ERR_CAT_NONE = 0, - UMAC_SYS_ERR_CAT_BOOT, - UMAC_SYS_ERR_CAT_UMAC, - UMAC_SYS_ERR_CAT_UAXM, - UMAC_SYS_ERR_CAT_LMAC, - UMAC_SYS_ERR_CAT_MAX -}; - -struct iwm_fw_error_hdr { - __le32 category; - __le32 status; - __le32 pc; - __le32 blink1; - __le32 blink2; - __le32 ilink1; - __le32 ilink2; - __le32 data1; - __le32 data2; - __le32 line_num; - __le32 umac_status; - __le32 lmac_status; - __le32 sdio_status; - __le32 dbm_sample_ctrl; - __le32 dbm_buf_base; - __le32 dbm_buf_end; - __le32 dbm_buf_write_ptr; - __le32 dbm_buf_cycle_cnt; -} __attribute__ ((packed)); - -struct iwm_umac_notif_error { - struct iwm_umac_wifi_in_hdr hdr; - struct iwm_fw_error_hdr err; -} __attribute__ ((packed)); - -#define UMAC_DEALLOC_NTFY_CHANGES_CNT_POS 0 -#define UMAC_DEALLOC_NTFY_CHANGES_CNT_SEED 0xff -#define UMAC_DEALLOC_NTFY_CHANGES_MSK_POS 8 -#define UMAC_DEALLOC_NTFY_CHANGES_MSK_SEED 0xffffff -#define UMAC_DEALLOC_NTFY_PAGE_CNT_POS 0 -#define UMAC_DEALLOC_NTFY_PAGE_CNT_SEED 0xffffff -#define UMAC_DEALLOC_NTFY_GROUP_NUM_POS 24 -#define UMAC_DEALLOC_NTFY_GROUP_NUM_SEED 0xf - -struct iwm_umac_notif_page_dealloc { - struct iwm_umac_wifi_in_hdr hdr; - __le32 changes; - __le32 grp_info[IWM_MACS_OUT_GROUPS]; -} __attribute__ ((packed)); - -struct iwm_umac_notif_wifi_status { - struct iwm_umac_wifi_in_hdr hdr; - __le16 status; - __le16 reserved; -} __attribute__ ((packed)); - -struct iwm_umac_notif_rx_ticket { - struct iwm_umac_wifi_in_hdr hdr; - u8 num_tickets; - u8 reserved[3]; - struct iwm_rx_ticket tickets[1]; -} __attribute__ ((packed)); - -/* Tx/Rx rates window (number of max of last update window per second) */ -#define UMAC_NTF_RATE_SAMPLE_NR 4 - -#define IWM_UMAC_MGMT_TID 8 -#define IWM_UMAC_TID_NR 8 - -struct iwm_umac_notif_stats { - struct iwm_umac_wifi_in_hdr hdr; - __le32 flags; - __le32 timestamp; - __le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */ - __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR]; - __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR]; - s32 rssi_dbm; - s32 noise_dbm; - __le32 supp_rates; - __le32 missed_beacons; - __le32 rx_beacons; - __le32 rx_dir_pkts; - __le32 rx_nondir_pkts; - __le32 rx_multicast; - __le32 rx_errors; - __le32 rx_drop_other_bssid; - __le32 rx_drop_decode; - __le32 rx_drop_reassembly; - __le32 rx_drop_bad_len; - __le32 rx_drop_overflow; - __le32 rx_drop_crc; - __le32 rx_drop_missed; - __le32 tx_dir_pkts; - __le32 tx_nondir_pkts; - __le32 tx_failure; - __le32 tx_errors; - __le32 tx_drop_max_retry; - __le32 tx_err_abort; - __le32 tx_err_carrier; - __le32 rx_bytes; - __le32 tx_bytes; - __le32 tx_power; - __le32 tx_max_power; - __le32 roam_threshold; - __le32 ap_assoc_nr; - __le32 scan_full; - __le32 scan_abort; - __le32 ap_nr; - __le32 roam_nr; - __le32 roam_missed_beacons; - __le32 roam_rssi; - __le32 roam_unassoc; - __le32 roam_deauth; - __le32 roam_ap_loadblance; -} __attribute__ ((packed)); - -/* WiFi interface wrapper header */ -struct iwm_umac_wifi_if { - u8 oid; - u8 flags; - __le16 buf_size; -} __attribute__ ((packed)); - -#define IWM_SEQ_NUM_HOST_MSK 0x0000 -#define IWM_SEQ_NUM_UMAC_MSK 0x4000 -#define IWM_SEQ_NUM_LMAC_MSK 0x8000 -#define IWM_SEQ_NUM_MSK 0xC000 - -#endif diff --git a/drivers/net/wireless/libertas/11d.c b/drivers/net/wireless/libertas/11d.c deleted file mode 100644 index 5c6968101f0d..000000000000 --- a/drivers/net/wireless/libertas/11d.c +++ /dev/null @@ -1,696 +0,0 @@ -/** - * This file contains functions for 802.11D. - */ -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "11d.h" -#include "dev.h" -#include "wext.h" - -#define TX_PWR_DEFAULT 10 - -static struct region_code_mapping region_code_mapping[] = { - {"US ", 0x10}, /* US FCC */ - {"CA ", 0x10}, /* IC Canada */ - {"SG ", 0x10}, /* Singapore */ - {"EU ", 0x30}, /* ETSI */ - {"AU ", 0x30}, /* Australia */ - {"KR ", 0x30}, /* Republic Of Korea */ - {"ES ", 0x31}, /* Spain */ - {"FR ", 0x32}, /* France */ - {"JP ", 0x40}, /* Japan */ -}; - -/* Following 2 structure defines the supported channels */ -static struct chan_freq_power channel_freq_power_UN_BG[] = { - {1, 2412, TX_PWR_DEFAULT}, - {2, 2417, TX_PWR_DEFAULT}, - {3, 2422, TX_PWR_DEFAULT}, - {4, 2427, TX_PWR_DEFAULT}, - {5, 2432, TX_PWR_DEFAULT}, - {6, 2437, TX_PWR_DEFAULT}, - {7, 2442, TX_PWR_DEFAULT}, - {8, 2447, TX_PWR_DEFAULT}, - {9, 2452, TX_PWR_DEFAULT}, - {10, 2457, TX_PWR_DEFAULT}, - {11, 2462, TX_PWR_DEFAULT}, - {12, 2467, TX_PWR_DEFAULT}, - {13, 2472, TX_PWR_DEFAULT}, - {14, 2484, TX_PWR_DEFAULT} -}; - -static u8 lbs_region_2_code(u8 *region) -{ - u8 i; - - for (i = 0; i < COUNTRY_CODE_LEN && region[i]; i++) - region[i] = toupper(region[i]); - - for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) { - if (!memcmp(region, region_code_mapping[i].region, - COUNTRY_CODE_LEN)) - return (region_code_mapping[i].code); - } - - /* default is US */ - return (region_code_mapping[0].code); -} - -static u8 *lbs_code_2_region(u8 code) -{ - u8 i; - - for (i = 0; i < ARRAY_SIZE(region_code_mapping); i++) { - if (region_code_mapping[i].code == code) - return (region_code_mapping[i].region); - } - /* default is US */ - return (region_code_mapping[0].region); -} - -/** - * @brief This function finds the nrchan-th chan after the firstchan - * @param band band - * @param firstchan first channel number - * @param nrchan number of channels - * @return the nrchan-th chan number -*/ -static u8 lbs_get_chan_11d(u8 firstchan, u8 nrchan, u8 *chan) -/*find the nrchan-th chan after the firstchan*/ -{ - u8 i; - struct chan_freq_power *cfp; - u8 cfp_no; - - cfp = channel_freq_power_UN_BG; - cfp_no = ARRAY_SIZE(channel_freq_power_UN_BG); - - for (i = 0; i < cfp_no; i++) { - if ((cfp + i)->channel == firstchan) { - lbs_deb_11d("firstchan found\n"); - break; - } - } - - if (i < cfp_no) { - /*if beyond the boundary */ - if (i + nrchan < cfp_no) { - *chan = (cfp + i + nrchan)->channel; - return 1; - } - } - - return 0; -} - -/** - * @brief This function Checks if chan txpwr is learned from AP/IBSS - * @param chan chan number - * @param parsed_region_chan pointer to parsed_region_chan_11d - * @return TRUE; FALSE -*/ -static u8 lbs_channel_known_11d(u8 chan, - struct parsed_region_chan_11d * parsed_region_chan) -{ - struct chan_power_11d *chanpwr = parsed_region_chan->chanpwr; - u8 nr_chan = parsed_region_chan->nr_chan; - u8 i = 0; - - lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)chanpwr, - sizeof(struct chan_power_11d) * nr_chan); - - for (i = 0; i < nr_chan; i++) { - if (chan == chanpwr[i].chan) { - lbs_deb_11d("found chan %d\n", chan); - return 1; - } - } - - lbs_deb_11d("chan %d not found\n", chan); - return 0; -} - -u32 lbs_chan_2_freq(u8 chan) -{ - struct chan_freq_power *cf; - u16 i; - u32 freq = 0; - - cf = channel_freq_power_UN_BG; - - for (i = 0; i < ARRAY_SIZE(channel_freq_power_UN_BG); i++) { - if (chan == cf[i].channel) - freq = cf[i].freq; - } - - return freq; -} - -static int generate_domain_info_11d(struct parsed_region_chan_11d - *parsed_region_chan, - struct lbs_802_11d_domain_reg *domaininfo) -{ - u8 nr_subband = 0; - - u8 nr_chan = parsed_region_chan->nr_chan; - u8 nr_parsedchan = 0; - - u8 firstchan = 0, nextchan = 0, maxpwr = 0; - - u8 i, flag = 0; - - memcpy(domaininfo->countrycode, parsed_region_chan->countrycode, - COUNTRY_CODE_LEN); - - lbs_deb_11d("nrchan %d\n", nr_chan); - lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (char *)parsed_region_chan, - sizeof(struct parsed_region_chan_11d)); - - for (i = 0; i < nr_chan; i++) { - if (!flag) { - flag = 1; - nextchan = firstchan = - parsed_region_chan->chanpwr[i].chan; - maxpwr = parsed_region_chan->chanpwr[i].pwr; - nr_parsedchan = 1; - continue; - } - - if (parsed_region_chan->chanpwr[i].chan == nextchan + 1 && - parsed_region_chan->chanpwr[i].pwr == maxpwr) { - nextchan++; - nr_parsedchan++; - } else { - domaininfo->subband[nr_subband].firstchan = firstchan; - domaininfo->subband[nr_subband].nrchan = - nr_parsedchan; - domaininfo->subband[nr_subband].maxtxpwr = maxpwr; - nr_subband++; - nextchan = firstchan = - parsed_region_chan->chanpwr[i].chan; - maxpwr = parsed_region_chan->chanpwr[i].pwr; - } - } - - if (flag) { - domaininfo->subband[nr_subband].firstchan = firstchan; - domaininfo->subband[nr_subband].nrchan = nr_parsedchan; - domaininfo->subband[nr_subband].maxtxpwr = maxpwr; - nr_subband++; - } - domaininfo->nr_subband = nr_subband; - - lbs_deb_11d("nr_subband=%x\n", domaininfo->nr_subband); - lbs_deb_hex(LBS_DEB_11D, "domaininfo", (char *)domaininfo, - COUNTRY_CODE_LEN + 1 + - sizeof(struct ieee_subbandset) * nr_subband); - return 0; -} - -/** - * @brief This function generates parsed_region_chan from Domain Info learned from AP/IBSS - * @param region_chan pointer to struct region_channel - * @param *parsed_region_chan pointer to parsed_region_chan_11d - * @return N/A -*/ -static void lbs_generate_parsed_region_chan_11d(struct region_channel *region_chan, - struct parsed_region_chan_11d * - parsed_region_chan) -{ - u8 i; - struct chan_freq_power *cfp; - - if (region_chan == NULL) { - lbs_deb_11d("region_chan is NULL\n"); - return; - } - - cfp = region_chan->CFP; - if (cfp == NULL) { - lbs_deb_11d("cfp is NULL \n"); - return; - } - - parsed_region_chan->band = region_chan->band; - parsed_region_chan->region = region_chan->region; - memcpy(parsed_region_chan->countrycode, - lbs_code_2_region(region_chan->region), COUNTRY_CODE_LEN); - - lbs_deb_11d("region 0x%x, band %d\n", parsed_region_chan->region, - parsed_region_chan->band); - - for (i = 0; i < region_chan->nrcfp; i++, cfp++) { - parsed_region_chan->chanpwr[i].chan = cfp->channel; - parsed_region_chan->chanpwr[i].pwr = cfp->maxtxpower; - lbs_deb_11d("chan %d, pwr %d\n", - parsed_region_chan->chanpwr[i].chan, - parsed_region_chan->chanpwr[i].pwr); - } - parsed_region_chan->nr_chan = region_chan->nrcfp; - - lbs_deb_11d("nrchan %d\n", parsed_region_chan->nr_chan); - - return; -} - -/** - * @brief generate parsed_region_chan from Domain Info learned from AP/IBSS - * @param region region ID - * @param band band - * @param chan chan - * @return TRUE;FALSE -*/ -static u8 lbs_region_chan_supported_11d(u8 region, u8 chan) -{ - struct chan_freq_power *cfp; - int cfp_no; - u8 idx; - int ret = 0; - - lbs_deb_enter(LBS_DEB_11D); - - cfp = lbs_get_region_cfp_table(region, &cfp_no); - if (cfp == NULL) - return 0; - - for (idx = 0; idx < cfp_no; idx++) { - if (chan == (cfp + idx)->channel) { - /* If Mrvl Chip Supported? */ - if ((cfp + idx)->unsupported) { - ret = 0; - } else { - ret = 1; - } - goto done; - } - } - - /*chan is not in the region table */ - -done: - lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); - return ret; -} - -/** - * @brief This function checks if chan txpwr is learned from AP/IBSS - * @param chan chan number - * @param parsed_region_chan pointer to parsed_region_chan_11d - * @return 0 -*/ -static int parse_domain_info_11d(struct ieee_ie_country_info_full_set *countryinfo, - u8 band, - struct parsed_region_chan_11d *parsed_region_chan) -{ - u8 nr_subband, nrchan; - u8 lastchan, firstchan; - u8 region; - u8 curchan = 0; - - u8 idx = 0; /*chan index in parsed_region_chan */ - - u8 j, i; - - lbs_deb_enter(LBS_DEB_11D); - - /*validation Rules: - 1. valid region Code - 2. First Chan increment - 3. channel range no overlap - 4. channel is valid? - 5. channel is supported by region? - 6. Others - */ - - lbs_deb_hex(LBS_DEB_11D, "countryinfo", (u8 *) countryinfo, 30); - - if ((*(countryinfo->countrycode)) == 0 - || (countryinfo->header.len <= COUNTRY_CODE_LEN)) { - /* No region Info or Wrong region info: treat as No 11D info */ - goto done; - } - - /*Step1: check region_code */ - parsed_region_chan->region = region = - lbs_region_2_code(countryinfo->countrycode); - - lbs_deb_11d("regioncode=%x\n", (u8) parsed_region_chan->region); - lbs_deb_hex(LBS_DEB_11D, "countrycode", (char *)countryinfo->countrycode, - COUNTRY_CODE_LEN); - - parsed_region_chan->band = band; - - memcpy(parsed_region_chan->countrycode, countryinfo->countrycode, - COUNTRY_CODE_LEN); - - nr_subband = (countryinfo->header.len - COUNTRY_CODE_LEN) / - sizeof(struct ieee_subbandset); - - for (j = 0, lastchan = 0; j < nr_subband; j++) { - - if (countryinfo->subband[j].firstchan <= lastchan) { - /*Step2&3. Check First Chan Num increment and no overlap */ - lbs_deb_11d("chan %d>%d, overlap\n", - countryinfo->subband[j].firstchan, lastchan); - continue; - } - - firstchan = countryinfo->subband[j].firstchan; - nrchan = countryinfo->subband[j].nrchan; - - for (i = 0; idx < MAX_NO_OF_CHAN && i < nrchan; i++) { - /*step4: channel is supported? */ - - if (!lbs_get_chan_11d(firstchan, i, &curchan)) { - /* Chan is not found in UN table */ - lbs_deb_11d("chan is not supported: %d \n", i); - break; - } - - lastchan = curchan; - - if (lbs_region_chan_supported_11d(region, curchan)) { - /*step5: Check if curchan is supported by mrvl in region */ - parsed_region_chan->chanpwr[idx].chan = curchan; - parsed_region_chan->chanpwr[idx].pwr = - countryinfo->subband[j].maxtxpwr; - idx++; - } else { - /*not supported and ignore the chan */ - lbs_deb_11d( - "i %d, chan %d unsupported in region %x, band %d\n", - i, curchan, region, band); - } - } - - /*Step6: Add other checking if any */ - - } - - parsed_region_chan->nr_chan = idx; - - lbs_deb_11d("nrchan=%x\n", parsed_region_chan->nr_chan); - lbs_deb_hex(LBS_DEB_11D, "parsed_region_chan", (u8 *) parsed_region_chan, - 2 + COUNTRY_CODE_LEN + sizeof(struct parsed_region_chan_11d) * idx); - -done: - lbs_deb_enter(LBS_DEB_11D); - return 0; -} - -/** - * @brief This function calculates the scan type for channels - * @param chan chan number - * @param parsed_region_chan pointer to parsed_region_chan_11d - * @return PASSIVE if chan is unknown; ACTIVE if chan is known -*/ -u8 lbs_get_scan_type_11d(u8 chan, - struct parsed_region_chan_11d * parsed_region_chan) -{ - u8 scan_type = CMD_SCAN_TYPE_PASSIVE; - - lbs_deb_enter(LBS_DEB_11D); - - if (lbs_channel_known_11d(chan, parsed_region_chan)) { - lbs_deb_11d("found, do active scan\n"); - scan_type = CMD_SCAN_TYPE_ACTIVE; - } else { - lbs_deb_11d("not found, do passive scan\n"); - } - - lbs_deb_leave_args(LBS_DEB_11D, "ret scan_type %d", scan_type); - return scan_type; - -} - -void lbs_init_11d(struct lbs_private *priv) -{ - priv->enable11d = 0; - memset(&(priv->parsed_region_chan), 0, - sizeof(struct parsed_region_chan_11d)); - return; -} - -/** - * @brief This function sets DOMAIN INFO to FW - * @param priv pointer to struct lbs_private - * @return 0; -1 -*/ -static int set_domain_info_11d(struct lbs_private *priv) -{ - int ret; - - if (!priv->enable11d) { - lbs_deb_11d("dnld domain Info with 11d disabled\n"); - return 0; - } - - ret = lbs_prepare_and_send_command(priv, CMD_802_11D_DOMAIN_INFO, - CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, 0, NULL); - if (ret) - lbs_deb_11d("fail to dnld domain info\n"); - - return ret; -} - -/** - * @brief This function setups scan channels - * @param priv pointer to struct lbs_private - * @param band band - * @return 0 -*/ -int lbs_set_universaltable(struct lbs_private *priv, u8 band) -{ - u16 size = sizeof(struct chan_freq_power); - u16 i = 0; - - memset(priv->universal_channel, 0, - sizeof(priv->universal_channel)); - - priv->universal_channel[i].nrcfp = - sizeof(channel_freq_power_UN_BG) / size; - lbs_deb_11d("BG-band nrcfp %d\n", - priv->universal_channel[i].nrcfp); - - priv->universal_channel[i].CFP = channel_freq_power_UN_BG; - priv->universal_channel[i].valid = 1; - priv->universal_channel[i].region = UNIVERSAL_REGION_CODE; - priv->universal_channel[i].band = band; - i++; - - return 0; -} - -/** - * @brief This function implements command CMD_802_11D_DOMAIN_INFO - * @param priv pointer to struct lbs_private - * @param cmd pointer to cmd buffer - * @param cmdno cmd ID - * @param cmdOption cmd action - * @return 0 -*/ -int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, - struct cmd_ds_command *cmd, u16 cmdno, - u16 cmdoption) -{ - struct cmd_ds_802_11d_domain_info *pdomaininfo = - &cmd->params.domaininfo; - struct mrvl_ie_domain_param_set *domain = &pdomaininfo->domain; - u8 nr_subband = priv->domainreg.nr_subband; - - lbs_deb_enter(LBS_DEB_11D); - - lbs_deb_11d("nr_subband=%x\n", nr_subband); - - cmd->command = cpu_to_le16(cmdno); - pdomaininfo->action = cpu_to_le16(cmdoption); - if (cmdoption == CMD_ACT_GET) { - cmd->size = - cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); - lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, - le16_to_cpu(cmd->size)); - goto done; - } - - domain->header.type = cpu_to_le16(TLV_TYPE_DOMAIN); - memcpy(domain->countrycode, priv->domainreg.countrycode, - sizeof(domain->countrycode)); - - domain->header.len = - cpu_to_le16(nr_subband * sizeof(struct ieee_subbandset) + - sizeof(domain->countrycode)); - - if (nr_subband) { - memcpy(domain->subband, priv->domainreg.subband, - nr_subband * sizeof(struct ieee_subbandset)); - - cmd->size = cpu_to_le16(sizeof(pdomaininfo->action) + - le16_to_cpu(domain->header.len) + - sizeof(struct mrvl_ie_header) + - S_DS_GEN); - } else { - cmd->size = - cpu_to_le16(sizeof(pdomaininfo->action) + S_DS_GEN); - } - - lbs_deb_hex(LBS_DEB_11D, "802_11D_DOMAIN_INFO", (u8 *) cmd, le16_to_cpu(cmd->size)); - -done: - lbs_deb_enter(LBS_DEB_11D); - return 0; -} - -/** - * @brief This function parses countryinfo from AP and download country info to FW - * @param priv pointer to struct lbs_private - * @param resp pointer to command response buffer - * @return 0; -1 - */ -int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11d_domain_info *domaininfo = &resp->params.domaininforesp; - struct mrvl_ie_domain_param_set *domain = &domaininfo->domain; - u16 action = le16_to_cpu(domaininfo->action); - s16 ret = 0; - u8 nr_subband = 0; - - lbs_deb_enter(LBS_DEB_11D); - - lbs_deb_hex(LBS_DEB_11D, "domain info resp", (u8 *) resp, - (int)le16_to_cpu(resp->size)); - - nr_subband = (le16_to_cpu(domain->header.len) - COUNTRY_CODE_LEN) / - sizeof(struct ieee_subbandset); - - lbs_deb_11d("domain info resp: nr_subband %d\n", nr_subband); - - if (nr_subband > MRVDRV_MAX_SUBBAND_802_11D) { - lbs_deb_11d("Invalid Numrer of Subband returned!!\n"); - return -1; - } - - switch (action) { - case CMD_ACT_SET: /*Proc Set action */ - break; - - case CMD_ACT_GET: - break; - default: - lbs_deb_11d("Invalid action:%d\n", domaininfo->action); - ret = -1; - break; - } - - lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); - return ret; -} - -/** - * @brief This function parses countryinfo from AP and download country info to FW - * @param priv pointer to struct lbs_private - * @return 0; -1 - */ -int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, - struct bss_descriptor * bss) -{ - int ret; - - lbs_deb_enter(LBS_DEB_11D); - if (priv->enable11d) { - memset(&priv->parsed_region_chan, 0, - sizeof(struct parsed_region_chan_11d)); - ret = parse_domain_info_11d(&bss->countryinfo, 0, - &priv->parsed_region_chan); - - if (ret == -1) { - lbs_deb_11d("error parsing domain_info from AP\n"); - goto done; - } - - memset(&priv->domainreg, 0, - sizeof(struct lbs_802_11d_domain_reg)); - generate_domain_info_11d(&priv->parsed_region_chan, - &priv->domainreg); - - ret = set_domain_info_11d(priv); - - if (ret) { - lbs_deb_11d("error setting domain info\n"); - goto done; - } - } - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); - return ret; -} - -/** - * @brief This function generates 11D info from user specified regioncode and download to FW - * @param priv pointer to struct lbs_private - * @return 0; -1 - */ -int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv) -{ - int ret; - struct region_channel *region_chan; - u8 j; - - lbs_deb_enter(LBS_DEB_11D); - lbs_deb_11d("curbssparams.band %d\n", priv->curbssparams.band); - - if (priv->enable11d) { - /* update parsed_region_chan_11; dnld domaininf to FW */ - - for (j = 0; j < ARRAY_SIZE(priv->region_channel); j++) { - region_chan = &priv->region_channel[j]; - - lbs_deb_11d("%d region_chan->band %d\n", j, - region_chan->band); - - if (!region_chan || !region_chan->valid - || !region_chan->CFP) - continue; - if (region_chan->band != priv->curbssparams.band) - continue; - break; - } - - if (j >= ARRAY_SIZE(priv->region_channel)) { - lbs_deb_11d("region_chan not found, band %d\n", - priv->curbssparams.band); - ret = -1; - goto done; - } - - memset(&priv->parsed_region_chan, 0, - sizeof(struct parsed_region_chan_11d)); - lbs_generate_parsed_region_chan_11d(region_chan, - &priv-> - parsed_region_chan); - - memset(&priv->domainreg, 0, - sizeof(struct lbs_802_11d_domain_reg)); - generate_domain_info_11d(&priv->parsed_region_chan, - &priv->domainreg); - - ret = set_domain_info_11d(priv); - - if (ret) { - lbs_deb_11d("error setting domain info\n"); - goto done; - } - - } - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_11D, "ret %d", ret); - return ret; -} diff --git a/drivers/net/wireless/libertas/11d.h b/drivers/net/wireless/libertas/11d.h deleted file mode 100644 index fb75d3e321a0..000000000000 --- a/drivers/net/wireless/libertas/11d.h +++ /dev/null @@ -1,105 +0,0 @@ -/** - * This header file contains data structures and - * function declarations of 802.11d - */ -#ifndef _LBS_11D_ -#define _LBS_11D_ - -#include "types.h" -#include "defs.h" - -#define UNIVERSAL_REGION_CODE 0xff - -/** (Beaconsize(256)-5(IEId,len,contrystr(3))/3(FirstChan,NoOfChan,MaxPwr) - */ -#define MRVDRV_MAX_SUBBAND_802_11D 83 - -#define COUNTRY_CODE_LEN 3 -#define MAX_NO_OF_CHAN 40 - -struct cmd_ds_command; - -/** Data structure for Country IE*/ -struct ieee_subbandset { - u8 firstchan; - u8 nrchan; - u8 maxtxpwr; -} __attribute__ ((packed)); - -struct ieee_ie_country_info_set { - struct ieee_ie_header header; - - u8 countrycode[COUNTRY_CODE_LEN]; - struct ieee_subbandset subband[1]; -}; - -struct ieee_ie_country_info_full_set { - struct ieee_ie_header header; - - u8 countrycode[COUNTRY_CODE_LEN]; - struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; -} __attribute__ ((packed)); - -struct mrvl_ie_domain_param_set { - struct mrvl_ie_header header; - - u8 countrycode[COUNTRY_CODE_LEN]; - struct ieee_subbandset subband[1]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11d_domain_info { - __le16 action; - struct mrvl_ie_domain_param_set domain; -} __attribute__ ((packed)); - -/** domain regulatory information */ -struct lbs_802_11d_domain_reg { - /** country Code*/ - u8 countrycode[COUNTRY_CODE_LEN]; - /** No. of subband*/ - u8 nr_subband; - struct ieee_subbandset subband[MRVDRV_MAX_SUBBAND_802_11D]; -}; - -struct chan_power_11d { - u8 chan; - u8 pwr; -} __attribute__ ((packed)); - -struct parsed_region_chan_11d { - u8 band; - u8 region; - s8 countrycode[COUNTRY_CODE_LEN]; - struct chan_power_11d chanpwr[MAX_NO_OF_CHAN]; - u8 nr_chan; -} __attribute__ ((packed)); - -struct region_code_mapping { - u8 region[COUNTRY_CODE_LEN]; - u8 code; -}; - -struct lbs_private; - -u8 lbs_get_scan_type_11d(u8 chan, - struct parsed_region_chan_11d *parsed_region_chan); - -u32 lbs_chan_2_freq(u8 chan); - -void lbs_init_11d(struct lbs_private *priv); - -int lbs_set_universaltable(struct lbs_private *priv, u8 band); - -int lbs_cmd_802_11d_domain_info(struct lbs_private *priv, - struct cmd_ds_command *cmd, u16 cmdno, - u16 cmdOption); - -int lbs_ret_802_11d_domain_info(struct cmd_ds_command *resp); - -struct bss_descriptor; -int lbs_parse_dnld_countryinfo_11d(struct lbs_private *priv, - struct bss_descriptor * bss); - -int lbs_create_dnld_countryinfo_11d(struct lbs_private *priv); - -#endif diff --git a/drivers/net/wireless/libertas/LICENSE b/drivers/net/wireless/libertas/LICENSE deleted file mode 100644 index 8862742213b9..000000000000 --- a/drivers/net/wireless/libertas/LICENSE +++ /dev/null @@ -1,16 +0,0 @@ - Copyright (c) 2003-2006, Marvell International Ltd. - All Rights Reserved - - This program is free software; you can redistribute it and/or modify it - under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., 59 - Temple Place - Suite 330, Boston, MA 02111-1307, USA. - diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile deleted file mode 100644 index 2079e36c8521..000000000000 --- a/drivers/net/wireless/libertas/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -libertas-objs := main.o wext.o rx.o tx.o cmd.o cmdresp.o scan.o 11d.o \ - debugfs.o persistcfg.o ethtool.o assoc.o - -usb8xxx-objs += if_usb.o -libertas_cs-objs += if_cs.o -libertas_sdio-objs += if_sdio1.o -libertas_spi-objs += if_spi.o - -obj-$(CONFIG_LIBERTAS) += libertas.o -obj-$(CONFIG_LIBERTAS_USB) += usb8xxx.o -obj-$(CONFIG_LIBERTAS_CS) += libertas_cs.o -obj-$(CONFIG_LIBERTAS_SDIO) += libertas_sdio.o wifi_power.o -obj-$(CONFIG_LIBERTAS_SPI) += libertas_spi.o diff --git a/drivers/net/wireless/libertas/README b/drivers/net/wireless/libertas/README deleted file mode 100644 index ab6a2d518af0..000000000000 --- a/drivers/net/wireless/libertas/README +++ /dev/null @@ -1,229 +0,0 @@ -================================================================================ - README for USB8388 - - (c) Copyright © 2003-2006, Marvell International Ltd. - All Rights Reserved - - This software file (the "File") is distributed by Marvell International - Ltd. under the terms of the GNU General Public License Version 2, June 1991 - (the "License"). You may use, redistribute and/or modify this File in - accordance with the terms and conditions of the License, a copy of which - is available along with the File in the license.txt file or by writing to - the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 or on the worldwide web at http://www.gnu.org/licenses/gpl.txt. - - THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - ARE EXPRESSLY DISCLAIMED. The License provides additional details about - this warranty disclaimer. -================================================================================ - -===================== -DRIVER LOADING -===================== - - o. Copy the firmware image (e.g. usb8388.bin) to /lib/firmware/ - - o. Load driver by using the following command: - - insmod usb8388.ko [fw_name=usb8388.bin] - -========================= -ETHTOOL -========================= - - -Use the -i option to retrieve version information from the driver. - -# ethtool -i eth0 -driver: libertas -version: COMM-USB8388-318.p4 -firmware-version: 5.110.7 -bus-info: - -Use the -e option to read the EEPROM contents of the card. - - Usage: - ethtool -e ethX [raw on|off] [offset N] [length N] - - -e retrieves and prints an EEPROM dump for the specified ethernet - device. When raw is enabled, then it dumps the raw EEPROM data - to stdout. The length and offset parameters allow dumping cer- - tain portions of the EEPROM. Default is to dump the entire EEP- - ROM. - -# ethtool -e eth0 offset 0 length 16 -Offset Values ------- ------ -0x0000 38 33 30 58 00 00 34 f4 00 00 10 00 00 c4 17 00 - -======================== -DEBUGFS COMMANDS -======================== - -those commands are used via debugfs interface - -=========== -rdmac -rdbbp -rdrf - These commands are used to read the MAC, BBP and RF registers from the - card. These commands take one parameter that specifies the offset - location that is to be read. This parameter must be specified in - hexadecimal (its possible to preceed preceding the number with a "0x"). - - Path: /sys/kernel/debug/libertas_wireless/ethX/registers/ - - Usage: - echo "0xa123" > rdmac ; cat rdmac - echo "0xa123" > rdbbp ; cat rdbbp - echo "0xa123" > rdrf ; cat rdrf -wrmac -wrbbp -wrrf - These commands are used to write the MAC, BBP and RF registers in the - card. These commands take two parameters that specify the offset - location and the value that is to be written. This parameters must - be specified in hexadecimal (its possible to preceed the number - with a "0x"). - - Usage: - echo "0xa123 0xaa" > wrmac - echo "0xa123 0xaa" > wrbbp - echo "0xa123 0xaa" > wrrf - -sleepparams - This command is used to set the sleepclock configurations - - Path: /sys/kernel/debug/libertas_wireless/ethX/ - - Usage: - cat sleepparams: reads the current sleepclock configuration - - echo "p1 p2 p3 p4 p5 p6" > sleepparams: writes the sleepclock configuration. - - where: - p1 is Sleep clock error in ppm (0-65535) - p2 is Wakeup offset in usec (0-65535) - p3 is Clock stabilization time in usec (0-65535) - p4 is Control periodic calibration (0-2) - p5 is Control the use of external sleep clock (0-2) - p6 is reserved for debug (0-65535) - -subscribed_events - - The subscribed_events directory contains the interface for the - subscribed events API. - - Path: /sys/kernel/debug/libertas_wireless/ethX/subscribed_events/ - - Each event is represented by a filename. Each filename consists of the - following three fields: - Value Frequency Subscribed - - To read the current values for a given event, do: - cat event - To set the current values, do: - echo "60 2 1" > event - - Frequency field specifies the reporting frequency for this event. - If it is set to 0, then the event is reported only once, and then - automatically unsubscribed. If it is set to 1, then the event is - reported every time it occurs. If it is set to N, then the event is - reported every Nth time it occurs. - - beacon_missed - Value field specifies the number of consecutive missing beacons which - triggers the LINK_LOSS event. This event is generated only once after - which the firmware resets its state. At initialization, the LINK_LOSS - event is subscribed by default. The default value of MissedBeacons is - 60. - - failure_count - Value field specifies the consecutive failure count threshold which - triggers the generation of the MAX_FAIL event. Once this event is - generated, the consecutive failure count is reset to 0. - At initialization, the MAX_FAIL event is NOT subscribed by - default. - - high_rssi - This event is generated when the average received RSSI in beacons goes - above a threshold, specified by Value. - - low_rssi - This event is generated when the average received RSSI in beacons goes - below a threshold, specified by Value. - - high_snr - This event is generated when the average received SNR in beacons goes - above a threshold, specified by Value. - - low_snr - This event is generated when the average received SNR in beacons goes - below a threshold, specified by Value. - -extscan - This command is used to do a specific scan. - - Path: /sys/kernel/debug/libertas_wireless/ethX/ - - Usage: echo "SSID" > extscan - - Example: - echo "LINKSYS-AP" > extscan - - To see the results of use getscantable command. - -getscantable - - Display the current contents of the driver scan table (ie. get the - scan results). - - Path: /sys/kernel/debug/libertas_wireless/ethX/ - - Usage: - cat getscantable - -setuserscan - Initiate a customized scan and retrieve the results - - - Path: /sys/kernel/debug/libertas_wireless/ethX/ - - Usage: - echo "[ARGS]" > setuserscan - - where [ARGS]: - - bssid=xx:xx:xx:xx:xx:xx specify a BSSID filter for the scan - ssid="[SSID]" specify a SSID filter for the scan - keep=[0 or 1] keep the previous scan results (1), discard (0) - dur=[scan time] time to scan for each channel in milliseconds - type=[1,2,3] BSS type: 1 (Infra), 2(Adhoc), 3(Any) - - Any combination of the above arguments can be supplied on the command - line. If dur tokens are absent, the driver default setting will be used. - The bssid and ssid fields, if blank, will produce an unfiltered scan. - The type field will default to 3 (Any) and the keep field will default - to 0 (Discard). - - Examples: - 1) Perform a passive scan on all channels for 20 ms per channel: - echo "dur=20" > setuserscan - - 2) Perform an active scan for a specific SSID: - echo "ssid="TestAP"" > setuserscan - - 3) Scan all available channels (B/G, A bands) for a specific BSSID, keep - the current scan table intact, update existing or append new scan data: - echo "bssid=00:50:43:20:12:82 keep=1" > setuserscan - - 4) Scan for all infrastructure networks. - Keep the previous scan table intact. Update any duplicate BSSID/SSID - matches with the new scan data: - echo "type=1 keep=1" > setuserscan - - All entries in the scan table (not just the new scan data when keep=1) - will be displayed upon completion by use of the getscantable ioctl. - -============================================================================== diff --git a/drivers/net/wireless/libertas/assoc.c b/drivers/net/wireless/libertas/assoc.c deleted file mode 100644 index dd8732611ba9..000000000000 --- a/drivers/net/wireless/libertas/assoc.c +++ /dev/null @@ -1,1865 +0,0 @@ -/* Copyright (C) 2006, Red Hat, Inc. */ - -#include -#include -#include -#include -#include - -#include "assoc.h" -#include "decl.h" -#include "host.h" -#include "scan.h" -#include "cmd.h" - -static const u8 bssid_any[ETH_ALEN] __attribute__ ((aligned (2))) = - { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; -static const u8 bssid_off[ETH_ALEN] __attribute__ ((aligned (2))) = - { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -/* The firmware needs the following bits masked out of the beacon-derived - * capability field when associating/joining to a BSS: - * 9 (QoS), 11 (APSD), 12 (unused), 14 (unused), 15 (unused) - */ -#define CAPINFO_MASK (~(0xda00)) - - -/** - * @brief This function finds common rates between rates and card rates. - * - * It will fill common rates in rates as output if found. - * - * NOTE: Setting the MSB of the basic rates need to be taken - * care, either before or after calling this function - * - * @param priv A pointer to struct lbs_private structure - * @param rates the buffer which keeps input and output - * @param rates_size the size of rates buffer; new size of buffer on return, - * which will be less than or equal to original rates_size - * - * @return 0 on success, or -1 on error - */ -static int get_common_rates(struct lbs_private *priv, - u8 *rates, - u16 *rates_size) -{ - int i, j; - u8 intersection[MAX_RATES]; - u16 intersection_size; - u16 num_rates = 0; - - intersection_size = min_t(u16, *rates_size, ARRAY_SIZE(intersection)); - - /* Allow each rate from 'rates' that is supported by the hardware */ - for (i = 0; i < ARRAY_SIZE(lbs_bg_rates) && lbs_bg_rates[i]; i++) { - for (j = 0; j < intersection_size && rates[j]; j++) { - if (rates[j] == lbs_bg_rates[i]) - intersection[num_rates++] = rates[j]; - } - } - - lbs_deb_hex(LBS_DEB_JOIN, "AP rates ", rates, *rates_size); - lbs_deb_hex(LBS_DEB_JOIN, "card rates ", lbs_bg_rates, - ARRAY_SIZE(lbs_bg_rates)); - lbs_deb_hex(LBS_DEB_JOIN, "common rates", intersection, num_rates); - lbs_deb_join("TX data rate 0x%02x\n", priv->cur_rate); - - if (!priv->enablehwauto) { - for (i = 0; i < num_rates; i++) { - if (intersection[i] == priv->cur_rate) - goto done; - } - lbs_pr_alert("Previously set fixed data rate %#x isn't " - "compatible with the network.\n", priv->cur_rate); - return -1; - } - -done: - memset(rates, 0, *rates_size); - *rates_size = num_rates; - memcpy(rates, intersection, num_rates); - return 0; -} - - -/** - * @brief Sets the MSB on basic rates as the firmware requires - * - * Scan through an array and set the MSB for basic data rates. - * - * @param rates buffer of data rates - * @param len size of buffer - */ -static void lbs_set_basic_rate_flags(u8 *rates, size_t len) -{ - int i; - - for (i = 0; i < len; i++) { - if (rates[i] == 0x02 || rates[i] == 0x04 || - rates[i] == 0x0b || rates[i] == 0x16) - rates[i] |= 0x80; - } -} - - -static u8 iw_auth_to_ieee_auth(u8 auth) -{ - if (auth == IW_AUTH_ALG_OPEN_SYSTEM) - return 0x00; - else if (auth == IW_AUTH_ALG_SHARED_KEY) - return 0x01; - else if (auth == IW_AUTH_ALG_LEAP) - return 0x80; - - lbs_deb_join("%s: invalid auth alg 0x%X\n", __func__, auth); - return 0; -} - -/** - * @brief This function prepares the authenticate command. AUTHENTICATE only - * sets the authentication suite for future associations, as the firmware - * handles authentication internally during the ASSOCIATE command. - * - * @param priv A pointer to struct lbs_private structure - * @param bssid The peer BSSID with which to authenticate - * @param auth The authentication mode to use (from wireless.h) - * - * @return 0 or -1 - */ -static int lbs_set_authentication(struct lbs_private *priv, u8 bssid[6], u8 auth) -{ - struct cmd_ds_802_11_authenticate cmd; - int ret = -1; - - lbs_deb_enter(LBS_DEB_JOIN); - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.bssid, bssid, ETH_ALEN); - - cmd.authtype = iw_auth_to_ieee_auth(auth); - - lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", bssid, cmd.authtype); - - ret = lbs_cmd_with_response(priv, CMD_802_11_AUTHENTICATE, &cmd); - - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - - -static int lbs_assoc_post(struct lbs_private *priv, - struct cmd_ds_802_11_associate_response *resp) -{ - int ret = 0; - union iwreq_data wrqu; - struct bss_descriptor *bss; - u16 status_code; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (!priv->in_progress_assoc_req) { - lbs_deb_assoc("ASSOC_RESP: no in-progress assoc request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Older FW versions map the IEEE 802.11 Status Code in the association - * response to the following values returned in resp->statuscode: - * - * IEEE Status Code Marvell Status Code - * 0 -> 0x0000 ASSOC_RESULT_SUCCESS - * 13 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 14 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 15 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * 16 -> 0x0004 ASSOC_RESULT_AUTH_REFUSED - * others -> 0x0003 ASSOC_RESULT_REFUSED - * - * Other response codes: - * 0x0001 -> ASSOC_RESULT_INVALID_PARAMETERS (unused) - * 0x0002 -> ASSOC_RESULT_TIMEOUT (internal timer expired waiting for - * association response from the AP) - */ - - status_code = le16_to_cpu(resp->statuscode); - if (priv->fwrelease < 0x09000000) { - switch (status_code) { - case 0x00: - break; - case 0x01: - lbs_deb_assoc("ASSOC_RESP: invalid parameters\n"); - break; - case 0x02: - lbs_deb_assoc("ASSOC_RESP: internal timer " - "expired while waiting for the AP\n"); - break; - case 0x03: - lbs_deb_assoc("ASSOC_RESP: association " - "refused by AP\n"); - break; - case 0x04: - lbs_deb_assoc("ASSOC_RESP: authentication " - "refused by AP\n"); - break; - default: - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x " - " unknown\n", status_code); - break; - } - } else { - /* v9+ returns the AP's association response */ - lbs_deb_assoc("ASSOC_RESP: failure reason 0x%02x\n", status_code); - } - - if (status_code) { - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - lbs_deb_hex(LBS_DEB_ASSOC, "ASSOC_RESP", - (void *) (resp + sizeof (resp->hdr)), - le16_to_cpu(resp->hdr.size) - sizeof (resp->hdr)); - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - /* Update current SSID and BSSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - memcpy(priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - priv->SNR[TYPE_RXPD][TYPE_AVG] = 0; - priv->NF[TYPE_RXPD][TYPE_AVG] = 0; - - memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); - memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); - priv->nextSNRNF = 0; - priv->numSNRNF = 0; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** - * @brief This function prepares an association-class command. - * - * @param priv A pointer to struct lbs_private structure - * @param assoc_req The association request describing the BSS to associate - * or reassociate with - * @param command The actual command, either CMD_802_11_ASSOCIATE or - * CMD_802_11_REASSOCIATE - * - * @return 0 or -1 - */ -static int lbs_associate(struct lbs_private *priv, - struct assoc_request *assoc_req, - u16 command) -{ - struct cmd_ds_802_11_associate cmd; - int ret = 0; - struct bss_descriptor *bss = &assoc_req->bss; - u8 *pos = &(cmd.iebuf[0]); - u16 tmpcap, tmplen, tmpauth; - struct mrvl_ie_ssid_param_set *ssid; - struct mrvl_ie_ds_param_set *ds; - struct mrvl_ie_cf_param_set *cf; - struct mrvl_ie_rates_param_set *rates; - struct mrvl_ie_rsn_param_set *rsn; - struct mrvl_ie_auth_type *auth; - - lbs_deb_enter(LBS_DEB_ASSOC); - - BUG_ON((command != CMD_802_11_ASSOCIATE) && - (command != CMD_802_11_REASSOCIATE)); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.command = cpu_to_le16(command); - - /* Fill in static fields */ - memcpy(cmd.bssid, bss->bssid, ETH_ALEN); - cmd.listeninterval = cpu_to_le16(MRVDRV_DEFAULT_LISTEN_INTERVAL); - - /* Capability info */ - tmpcap = (bss->capability & CAPINFO_MASK); - if (bss->mode == IW_MODE_INFRA) - tmpcap |= WLAN_CAPABILITY_ESS; - cmd.capability = cpu_to_le16(tmpcap); - lbs_deb_assoc("ASSOC_CMD: capability 0x%04x\n", tmpcap); - - /* SSID */ - ssid = (struct mrvl_ie_ssid_param_set *) pos; - ssid->header.type = cpu_to_le16(TLV_TYPE_SSID); - tmplen = bss->ssid_len; - ssid->header.len = cpu_to_le16(tmplen); - memcpy(ssid->ssid, bss->ssid, tmplen); - pos += sizeof(ssid->header) + tmplen; - - ds = (struct mrvl_ie_ds_param_set *) pos; - ds->header.type = cpu_to_le16(TLV_TYPE_PHY_DS); - ds->header.len = cpu_to_le16(1); - ds->channel = bss->phy.ds.channel; - pos += sizeof(ds->header) + 1; - - cf = (struct mrvl_ie_cf_param_set *) pos; - cf->header.type = cpu_to_le16(TLV_TYPE_CF); - tmplen = sizeof(*cf) - sizeof (cf->header); - cf->header.len = cpu_to_le16(tmplen); - /* IE payload should be zeroed, firmware fills it in for us */ - pos += sizeof(*cf); - - rates = (struct mrvl_ie_rates_param_set *) pos; - rates->header.type = cpu_to_le16(TLV_TYPE_RATES); - tmplen = min_t(u16, ARRAY_SIZE(bss->rates), MAX_RATES); - memcpy(&rates->rates, &bss->rates, tmplen); - if (get_common_rates(priv, rates->rates, &tmplen)) { - ret = -1; - goto done; - } - pos += sizeof(rates->header) + tmplen; - rates->header.len = cpu_to_le16(tmplen); - lbs_deb_assoc("ASSOC_CMD: num rates %u\n", tmplen); - - /* Copy the infra. association rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &rates->rates, tmplen); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(rates->rates, tmplen); - - /* Firmware v9+ indicate authentication suites as a TLV */ - if (priv->fwrelease >= 0x09000000) { - auth = (struct mrvl_ie_auth_type *) pos; - auth->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); - auth->header.len = cpu_to_le16(2); - tmpauth = iw_auth_to_ieee_auth(priv->secinfo.auth_mode); - auth->auth = cpu_to_le16(tmpauth); - pos += sizeof(auth->header) + 2; - - lbs_deb_join("AUTH_CMD: BSSID %pM, auth 0x%x\n", - bss->bssid, priv->secinfo.auth_mode); - } - - /* WPA/WPA2 IEs */ - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - rsn = (struct mrvl_ie_rsn_param_set *) pos; - /* WPA_IE or WPA2_IE */ - rsn->header.type = cpu_to_le16((u16) assoc_req->wpa_ie[0]); - tmplen = (u16) assoc_req->wpa_ie[1]; - rsn->header.len = cpu_to_le16(tmplen); - memcpy(rsn->rsnie, &assoc_req->wpa_ie[2], tmplen); - lbs_deb_hex(LBS_DEB_JOIN, "ASSOC_CMD: WPA/RSN IE", (u8 *) rsn, - sizeof(rsn->header) + tmplen); - pos += sizeof(rsn->header) + tmplen; - } - - cmd.hdr.size = cpu_to_le16((sizeof(cmd) - sizeof(cmd.iebuf)) + - (u16)(pos - (u8 *) &cmd.iebuf)); - - /* update curbssparams */ - priv->curbssparams.channel = bss->phy.ds.channel; - - if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { - ret = -1; - goto done; - } - - ret = lbs_cmd_with_response(priv, command, &cmd); - if (ret == 0) { - ret = lbs_assoc_post(priv, - (struct cmd_ds_802_11_associate_response *) &cmd); - } - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** - * @brief Associate to a specific BSS discovered in a scan - * - * @param priv A pointer to struct lbs_private structure - * @param assoc_req The association request describing the BSS to associate with - * - * @return 0-success, otherwise fail - */ -static int lbs_try_associate(struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - int ret; - u8 preamble = RADIO_PREAMBLE_LONG; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* FW v9 and higher indicate authentication suites as a TLV in the - * association command, not as a separate authentication command. - */ - if (priv->fwrelease < 0x09000000) { - ret = lbs_set_authentication(priv, assoc_req->bss.bssid, - priv->secinfo.auth_mode); - if (ret) - goto out; - } - - /* Use short preamble only when both the BSS and firmware support it */ - if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - (assoc_req->bss.capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) - preamble = RADIO_PREAMBLE_SHORT; - - ret = lbs_set_radio(priv, preamble, 1); - if (ret) - goto out; - - ret = lbs_associate(priv, assoc_req, CMD_802_11_ASSOCIATE); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int lbs_adhoc_post(struct lbs_private *priv, - struct cmd_ds_802_11_ad_hoc_result *resp) -{ - int ret = 0; - u16 command = le16_to_cpu(resp->hdr.command); - u16 result = le16_to_cpu(resp->hdr.result); - union iwreq_data wrqu; - struct bss_descriptor *bss; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_JOIN); - - if (!priv->in_progress_assoc_req) { - lbs_deb_join("ADHOC_RESP: no in-progress association " - "request\n"); - ret = -1; - goto done; - } - bss = &priv->in_progress_assoc_req->bss; - - /* - * Join result code 0 --> SUCCESS - */ - if (result) { - lbs_deb_join("ADHOC_RESP: failed (result 0x%X)\n", result); - if (priv->connect_status == LBS_CONNECTED) - lbs_mac_event_disconnected(priv); - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->connect_status = LBS_CONNECTED; - - if (command == CMD_RET(CMD_802_11_AD_HOC_START)) { - /* Update the created network descriptor with the new BSSID */ - memcpy(bss->bssid, resp->bssid, ETH_ALEN); - } - - /* Set the BSSID from the joined/started descriptor */ - memcpy(&priv->curbssparams.bssid, bss->bssid, ETH_ALEN); - - /* Set the new SSID to current SSID */ - memcpy(&priv->curbssparams.ssid, &bss->ssid, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = bss->ssid_len; - - netif_carrier_on(priv->dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->dev); - - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - lbs_deb_join("ADHOC_RESP: Joined/started '%s', BSSID %pM, channel %d\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - priv->curbssparams.bssid, - priv->curbssparams.channel); - -done: - lbs_deb_leave_args(LBS_DEB_JOIN, "ret %d", ret); - return ret; -} - -/** - * @brief Join an adhoc network found in a previous scan - * - * @param priv A pointer to struct lbs_private structure - * @param assoc_req The association request describing the BSS to join - * - * @return 0 on success, error on failure - */ -static int lbs_adhoc_join(struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - struct cmd_ds_802_11_ad_hoc_join cmd; - struct bss_descriptor *bss = &assoc_req->bss; - u8 preamble = RADIO_PREAMBLE_LONG; - DECLARE_SSID_BUF(ssid); - u16 ratesize = 0; - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - lbs_deb_join("current SSID '%s', ssid length %u\n", - print_ssid(ssid, priv->curbssparams.ssid, - priv->curbssparams.ssid_len), - priv->curbssparams.ssid_len); - lbs_deb_join("requested ssid '%s', ssid length %u\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - bss->ssid_len); - - /* check if the requested SSID is already joined */ - if (priv->curbssparams.ssid_len && - !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len) && - (priv->mode == IW_MODE_ADHOC) && - (priv->connect_status == LBS_CONNECTED)) { - union iwreq_data wrqu; - - lbs_deb_join("ADHOC_J_CMD: New ad-hoc SSID is the same as " - "current, not attempting to re-join"); - - /* Send the re-association event though, because the association - * request really was successful, even if just a null-op. - */ - memset(&wrqu, 0, sizeof(wrqu)); - memcpy(wrqu.ap_addr.sa_data, priv->curbssparams.bssid, - ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - goto out; - } - - /* Use short preamble only when both the BSS and firmware support it */ - if ((priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) && - (bss->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) { - lbs_deb_join("AdhocJoin: Short preamble\n"); - preamble = RADIO_PREAMBLE_SHORT; - } - - ret = lbs_set_radio(priv, preamble, 1); - if (ret) - goto out; - - lbs_deb_join("AdhocJoin: channel = %d\n", assoc_req->channel); - lbs_deb_join("AdhocJoin: band = %c\n", assoc_req->band); - - priv->adhoccreate = 0; - priv->curbssparams.channel = bss->channel; - - /* Build the join command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.bss.type = CMD_BSS_TYPE_IBSS; - cmd.bss.beaconperiod = cpu_to_le16(bss->beaconperiod); - - memcpy(&cmd.bss.bssid, &bss->bssid, ETH_ALEN); - memcpy(&cmd.bss.ssid, &bss->ssid, bss->ssid_len); - - memcpy(&cmd.bss.ds, &bss->phy.ds, sizeof(struct ieee_ie_ds_param_set)); - - memcpy(&cmd.bss.ibss, &bss->ss.ibss, - sizeof(struct ieee_ie_ibss_param_set)); - - cmd.bss.capability = cpu_to_le16(bss->capability & CAPINFO_MASK); - lbs_deb_join("ADHOC_J_CMD: tmpcap=%4X CAPINFO_MASK=%4X\n", - bss->capability, CAPINFO_MASK); - - /* information on BSSID descriptor passed to FW */ - lbs_deb_join("ADHOC_J_CMD: BSSID = %pM, SSID = '%s'\n", - cmd.bss.bssid, cmd.bss.ssid); - - /* Only v8 and below support setting these */ - if (priv->fwrelease < 0x09000000) { - /* failtimeout */ - cmd.failtimeout = cpu_to_le16(MRVDRV_ASSOCIATION_TIME_OUT); - /* probedelay */ - cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); - } - - /* Copy Data rates from the rates recorded in scan response */ - memset(cmd.bss.rates, 0, sizeof(cmd.bss.rates)); - ratesize = min_t(u16, ARRAY_SIZE(cmd.bss.rates), ARRAY_SIZE (bss->rates)); - memcpy(cmd.bss.rates, bss->rates, ratesize); - if (get_common_rates(priv, cmd.bss.rates, &ratesize)) { - lbs_deb_join("ADHOC_JOIN: get_common_rates returned error.\n"); - ret = -1; - goto out; - } - - /* Copy the ad-hoc creation rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, cmd.bss.rates, ratesize); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(cmd.bss.rates, ratesize); - - cmd.bss.ibss.atimwindow = bss->atimwindow; - - if (assoc_req->secinfo.wep_enabled) { - u16 tmp = le16_to_cpu(cmd.bss.capability); - tmp |= WLAN_CAPABILITY_PRIVACY; - cmd.bss.capability = cpu_to_le16(tmp); - } - - if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { - __le32 local_ps_mode = cpu_to_le32(LBS802_11POWERMODECAM); - - /* wake up first */ - ret = lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, - CMD_ACT_SET, 0, 0, - &local_ps_mode); - if (ret) { - ret = -1; - goto out; - } - } - - if (lbs_parse_dnld_countryinfo_11d(priv, bss)) { - ret = -1; - goto out; - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_JOIN, &cmd); - if (ret == 0) { - ret = lbs_adhoc_post(priv, - (struct cmd_ds_802_11_ad_hoc_result *)&cmd); - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** - * @brief Start an Adhoc Network - * - * @param priv A pointer to struct lbs_private structure - * @param assoc_req The association request describing the BSS to start - * - * @return 0 on success, error on failure - */ -static int lbs_adhoc_start(struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - struct cmd_ds_802_11_ad_hoc_start cmd; - u8 preamble = RADIO_PREAMBLE_LONG; - size_t ratesize = 0; - u16 tmpcap = 0; - int ret = 0; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE) { - lbs_deb_join("ADHOC_START: Will use short preamble\n"); - preamble = RADIO_PREAMBLE_SHORT; - } - - ret = lbs_set_radio(priv, preamble, 1); - if (ret) - goto out; - - /* Build the start command */ - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - memcpy(cmd.ssid, assoc_req->ssid, assoc_req->ssid_len); - - lbs_deb_join("ADHOC_START: SSID '%s', ssid length %u\n", - print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len), - assoc_req->ssid_len); - - cmd.bsstype = CMD_BSS_TYPE_IBSS; - - if (priv->beacon_period == 0) - priv->beacon_period = MRVDRV_BEACON_INTERVAL; - cmd.beaconperiod = cpu_to_le16(priv->beacon_period); - - WARN_ON(!assoc_req->channel); - - /* set Physical parameter set */ - cmd.ds.header.id = WLAN_EID_DS_PARAMS; - cmd.ds.header.len = 1; - cmd.ds.channel = assoc_req->channel; - - /* set IBSS parameter set */ - cmd.ibss.header.id = WLAN_EID_IBSS_PARAMS; - cmd.ibss.header.len = 2; - cmd.ibss.atimwindow = cpu_to_le16(0); - - /* set capability info */ - tmpcap = WLAN_CAPABILITY_IBSS; - if (assoc_req->secinfo.wep_enabled || - assoc_req->secinfo.WPAenabled || - assoc_req->secinfo.WPA2enabled) { - lbs_deb_join("ADHOC_START: WEP/WPA enabled, privacy on\n"); - tmpcap |= WLAN_CAPABILITY_PRIVACY; - } else - lbs_deb_join("ADHOC_START: WEP disabled, privacy off\n"); - - cmd.capability = cpu_to_le16(tmpcap); - - /* Only v8 and below support setting probe delay */ - if (priv->fwrelease < 0x09000000) - cmd.probedelay = cpu_to_le16(CMD_SCAN_PROBE_DELAY_TIME); - - ratesize = min(sizeof(cmd.rates), sizeof(lbs_bg_rates)); - memcpy(cmd.rates, lbs_bg_rates, ratesize); - - /* Copy the ad-hoc creating rates into Current BSS state structure */ - memset(&priv->curbssparams.rates, 0, sizeof(priv->curbssparams.rates)); - memcpy(&priv->curbssparams.rates, &cmd.rates, ratesize); - - /* Set MSB on basic rates as the firmware requires, but _after_ - * copying to current bss rates. - */ - lbs_set_basic_rate_flags(cmd.rates, ratesize); - - lbs_deb_join("ADHOC_START: rates=%02x %02x %02x %02x\n", - cmd.rates[0], cmd.rates[1], cmd.rates[2], cmd.rates[3]); - - if (lbs_create_dnld_countryinfo_11d(priv)) { - lbs_deb_join("ADHOC_START: dnld_countryinfo_11d failed\n"); - ret = -1; - goto out; - } - - lbs_deb_join("ADHOC_START: Starting Ad-Hoc BSS on channel %d, band %d\n", - assoc_req->channel, assoc_req->band); - - priv->adhoccreate = 1; - priv->mode = IW_MODE_ADHOC; - - ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_START, &cmd); - if (ret == 0) - ret = lbs_adhoc_post(priv, - (struct cmd_ds_802_11_ad_hoc_result *)&cmd); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** - * @brief Stop and Ad-Hoc network and exit Ad-Hoc mode - * - * @param priv A pointer to struct lbs_private structure - * @return 0 on success, or an error - */ -int lbs_adhoc_stop(struct lbs_private *priv) -{ - struct cmd_ds_802_11_ad_hoc_stop cmd; - int ret; - - lbs_deb_enter(LBS_DEB_JOIN); - - memset(&cmd, 0, sizeof (cmd)); - cmd.hdr.size = cpu_to_le16 (sizeof (cmd)); - - ret = lbs_cmd_with_response(priv, CMD_802_11_AD_HOC_STOP, &cmd); - - /* Clean up everything even if there was an error */ - lbs_mac_event_disconnected(priv); - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static inline int match_bss_no_security(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && match_bss->wpa_ie[0] != WLAN_EID_GENERIC - && match_bss->rsn_ie[0] != WLAN_EID_RSN - && !(match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -static inline int match_bss_static_wep(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -static inline int match_bss_wpa(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && secinfo->WPAenabled - && (match_bss->wpa_ie[0] == WLAN_EID_GENERIC) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ - ) - return 1; - else - return 0; -} - -static inline int match_bss_wpa2(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && secinfo->WPA2enabled && - (match_bss->rsn_ie[0] == WLAN_EID_RSN) - /* privacy bit may NOT be set in some APs like LinkSys WRT54G - (match_bss->capability & WLAN_CAPABILITY_PRIVACY) */ - ) - return 1; - else - return 0; -} - -static inline int match_bss_dynamic_wep(struct lbs_802_11_security *secinfo, - struct bss_descriptor *match_bss) -{ - if (!secinfo->wep_enabled && !secinfo->WPAenabled - && !secinfo->WPA2enabled - && (match_bss->wpa_ie[0] != WLAN_EID_GENERIC) - && (match_bss->rsn_ie[0] != WLAN_EID_RSN) - && (match_bss->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - else - return 0; -} - -/** - * @brief Check if a scanned network compatible with the driver settings - * - * WEP WPA WPA2 ad-hoc encrypt Network - * enabled enabled enabled AES mode privacy WPA WPA2 Compatible - * 0 0 0 0 NONE 0 0 0 yes No security - * 1 0 0 0 NONE 1 0 0 yes Static WEP - * 0 1 0 0 x 1x 1 x yes WPA - * 0 0 1 0 x 1x x 1 yes WPA2 - * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES - * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP - * - * - * @param priv A pointer to struct lbs_private - * @param index Index in scantable to check against current driver settings - * @param mode Network mode: Infrastructure or IBSS - * - * @return Index in scantable, or error code if negative - */ -static int is_network_compatible(struct lbs_private *priv, - struct bss_descriptor *bss, uint8_t mode) -{ - int matched = 0; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (bss->mode != mode) - goto done; - - matched = match_bss_no_security(&priv->secinfo, bss); - if (matched) - goto done; - matched = match_bss_static_wep(&priv->secinfo, bss); - if (matched) - goto done; - matched = match_bss_wpa(&priv->secinfo, bss); - if (matched) { - lbs_deb_scan("is_network_compatible() WPA: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - matched = match_bss_wpa2(&priv->secinfo, bss); - if (matched) { - lbs_deb_scan("is_network_compatible() WPA2: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s " - "privacy 0x%x\n", bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - matched = match_bss_dynamic_wep(&priv->secinfo, bss); - if (matched) { - lbs_deb_scan("is_network_compatible() dynamic WEP: " - "wpa_ie 0x%x wpa2_ie 0x%x privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - goto done; - } - - /* bss security settings don't match those configured on card */ - lbs_deb_scan("is_network_compatible() FAILED: wpa_ie 0x%x " - "wpa2_ie 0x%x WEP %s WPA %s WPA2 %s privacy 0x%x\n", - bss->wpa_ie[0], bss->rsn_ie[0], - priv->secinfo.wep_enabled ? "e" : "d", - priv->secinfo.WPAenabled ? "e" : "d", - priv->secinfo.WPA2enabled ? "e" : "d", - (bss->capability & WLAN_CAPABILITY_PRIVACY)); - -done: - lbs_deb_leave_args(LBS_DEB_SCAN, "matched: %d", matched); - return matched; -} - -/** - * @brief This function finds a specific compatible BSSID in the scan list - * - * Used in association code - * - * @param priv A pointer to struct lbs_private - * @param bssid BSSID to find in the scan list - * @param mode Network mode: Infrastructure or IBSS - * - * @return index in BSSID list, or error return code (< 0) - */ -static struct bss_descriptor *lbs_find_bssid_in_list(struct lbs_private *priv, - uint8_t *bssid, uint8_t mode) -{ - struct bss_descriptor *iter_bss; - struct bss_descriptor *found_bss = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (!bssid) - goto out; - - lbs_deb_hex(LBS_DEB_SCAN, "looking for", bssid, ETH_ALEN); - - /* Look through the scan table for a compatible match. The loop will - * continue past a matched bssid that is not compatible in case there - * is an AP with multiple SSIDs assigned to the same BSSID - */ - mutex_lock(&priv->lock); - list_for_each_entry(iter_bss, &priv->network_list, list) { - if (compare_ether_addr(iter_bss->bssid, bssid)) - continue; /* bssid doesn't match */ - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - found_bss = iter_bss; - break; - default: - found_bss = iter_bss; - break; - } - } - mutex_unlock(&priv->lock); - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); - return found_bss; -} - -/** - * @brief This function finds ssid in ssid list. - * - * Used in association code - * - * @param priv A pointer to struct lbs_private - * @param ssid SSID to find in the list - * @param bssid BSSID to qualify the SSID selection (if provided) - * @param mode Network mode: Infrastructure or IBSS - * - * @return index in BSSID list - */ -static struct bss_descriptor *lbs_find_ssid_in_list(struct lbs_private *priv, - uint8_t *ssid, uint8_t ssid_len, - uint8_t *bssid, uint8_t mode, - int channel) -{ - u32 bestrssi = 0; - struct bss_descriptor *iter_bss = NULL; - struct bss_descriptor *found_bss = NULL; - struct bss_descriptor *tmp_oldest = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - mutex_lock(&priv->lock); - - list_for_each_entry(iter_bss, &priv->network_list, list) { - if (!tmp_oldest || - (iter_bss->last_scanned < tmp_oldest->last_scanned)) - tmp_oldest = iter_bss; - - if (lbs_ssid_cmp(iter_bss->ssid, iter_bss->ssid_len, - ssid, ssid_len) != 0) - continue; /* ssid doesn't match */ - if (bssid && compare_ether_addr(iter_bss->bssid, bssid) != 0) - continue; /* bssid doesn't match */ - if ((channel > 0) && (iter_bss->channel != channel)) - continue; /* channel doesn't match */ - - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - - if (bssid) { - /* Found requested BSSID */ - found_bss = iter_bss; - goto out; - } - - if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { - bestrssi = SCAN_RSSI(iter_bss->rssi); - found_bss = iter_bss; - } - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(iter_bss->rssi) > bestrssi) { - bestrssi = SCAN_RSSI(iter_bss->rssi); - found_bss = iter_bss; - } - break; - } - } - -out: - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_SCAN, "found_bss %p", found_bss); - return found_bss; -} - -static int assoc_helper_essid(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - struct bss_descriptor * bss; - int channel = -1; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* FIXME: take channel into account when picking SSIDs if a channel - * is set. - */ - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) - channel = assoc_req->channel; - - lbs_deb_assoc("SSID '%s' requested\n", - print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len)); - if (assoc_req->mode == IW_MODE_INFRA) { - lbs_send_specific_ssid_scan(priv, assoc_req->ssid, - assoc_req->ssid_len); - - bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, - assoc_req->ssid_len, NULL, IW_MODE_INFRA, channel); - if (bss != NULL) { - memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - ret = lbs_try_associate(priv, assoc_req); - } else { - lbs_deb_assoc("SSID not found; cannot associate\n"); - } - } else if (assoc_req->mode == IW_MODE_ADHOC) { - /* Scan for the network, do not save previous results. Stale - * scan data will cause us to join a non-existant adhoc network - */ - lbs_send_specific_ssid_scan(priv, assoc_req->ssid, - assoc_req->ssid_len); - - /* Search for the requested SSID in the scan table */ - bss = lbs_find_ssid_in_list(priv, assoc_req->ssid, - assoc_req->ssid_len, NULL, IW_MODE_ADHOC, channel); - if (bss != NULL) { - lbs_deb_assoc("SSID found, will join\n"); - memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - lbs_adhoc_join(priv, assoc_req); - } else { - /* else send START command */ - lbs_deb_assoc("SSID not found, creating adhoc network\n"); - memcpy(&assoc_req->bss.ssid, &assoc_req->ssid, - IW_ESSID_MAX_SIZE); - assoc_req->bss.ssid_len = assoc_req->ssid_len; - lbs_adhoc_start(priv, assoc_req); - } - } - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_bssid(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - struct bss_descriptor * bss; - - lbs_deb_enter_args(LBS_DEB_ASSOC, "BSSID %pM", assoc_req->bssid); - - /* Search for index position in list for requested MAC */ - bss = lbs_find_bssid_in_list(priv, assoc_req->bssid, - assoc_req->mode); - if (bss == NULL) { - lbs_deb_assoc("ASSOC: WAP: BSSID %pM not found, " - "cannot associate.\n", assoc_req->bssid); - goto out; - } - - memcpy(&assoc_req->bss, bss, sizeof(struct bss_descriptor)); - if (assoc_req->mode == IW_MODE_INFRA) { - ret = lbs_try_associate(priv, assoc_req); - lbs_deb_assoc("ASSOC: lbs_try_associate(bssid) returned %d\n", - ret); - } else if (assoc_req->mode == IW_MODE_ADHOC) { - lbs_adhoc_join(priv, assoc_req); - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_associate(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0, done = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* If we're given and 'any' BSSID, try associating based on SSID */ - - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (compare_ether_addr(bssid_any, assoc_req->bssid) - && compare_ether_addr(bssid_off, assoc_req->bssid)) { - ret = assoc_helper_bssid(priv, assoc_req); - done = 1; - } - } - - if (!done && test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - ret = assoc_helper_essid(priv, assoc_req); - } - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_mode(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (assoc_req->mode == priv->mode) - goto done; - - if (assoc_req->mode == IW_MODE_INFRA) { - if (priv->psstate != PS_STATE_FULL_POWER) - lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); - priv->psmode = LBS802_11POWERMODECAM; - } - - priv->mode = assoc_req->mode; - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_BSS_TYPE, assoc_req->mode); - -done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int assoc_helper_channel(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - ret = lbs_update_channel(priv); - if (ret) { - lbs_deb_assoc("ASSOC: channel: error getting channel.\n"); - goto done; - } - - if (assoc_req->channel == priv->curbssparams.channel) - goto done; - - if (priv->mesh_dev) { - /* Change mesh channel first; 21.p21 firmware won't let - you change channel otherwise (even though it'll return - an error to this */ - lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, - assoc_req->channel); - } - - lbs_deb_assoc("ASSOC: channel: %d -> %d\n", - priv->curbssparams.channel, assoc_req->channel); - - ret = lbs_set_channel(priv, assoc_req->channel); - if (ret < 0) - lbs_deb_assoc("ASSOC: channel: error setting channel.\n"); - - /* FIXME: shouldn't need to grab the channel _again_ after setting - * it since the firmware is supposed to return the new channel, but - * whatever... */ - ret = lbs_update_channel(priv); - if (ret) { - lbs_deb_assoc("ASSOC: channel: error getting channel.\n"); - goto done; - } - - if (assoc_req->channel != priv->curbssparams.channel) { - lbs_deb_assoc("ASSOC: channel: failed to update channel to %d\n", - assoc_req->channel); - goto restore_mesh; - } - - if ( assoc_req->secinfo.wep_enabled - && (assoc_req->wep_keys[0].len - || assoc_req->wep_keys[1].len - || assoc_req->wep_keys[2].len - || assoc_req->wep_keys[3].len)) { - /* Make sure WEP keys are re-sent to firmware */ - set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); - } - - /* Must restart/rejoin adhoc networks after channel change */ - set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); - - restore_mesh: - if (priv->mesh_dev) - lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->curbssparams.channel); - - done: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_wep_keys(struct lbs_private *priv, - struct assoc_request *assoc_req) -{ - int i; - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* Set or remove WEP keys */ - if (assoc_req->wep_keys[0].len || assoc_req->wep_keys[1].len || - assoc_req->wep_keys[2].len || assoc_req->wep_keys[3].len) - ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_ADD, assoc_req); - else - ret = lbs_cmd_802_11_set_wep(priv, CMD_ACT_REMOVE, assoc_req); - - if (ret) - goto out; - - /* enable/disable the MAC's WEP packet filter */ - if (assoc_req->secinfo.wep_enabled) - priv->mac_control |= CMD_ACT_MAC_WEP_ENABLE; - else - priv->mac_control &= ~CMD_ACT_MAC_WEP_ENABLE; - - lbs_set_mac_control(priv); - - mutex_lock(&priv->lock); - - /* Copy WEP keys into priv wep key fields */ - for (i = 0; i < 4; i++) { - memcpy(&priv->wep_keys[i], &assoc_req->wep_keys[i], - sizeof(struct enc_key)); - } - priv->wep_tx_keyidx = assoc_req->wep_tx_keyidx; - - mutex_unlock(&priv->lock); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -static int assoc_helper_secinfo(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - uint16_t do_wpa; - uint16_t rsn = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - memcpy(&priv->secinfo, &assoc_req->secinfo, - sizeof(struct lbs_802_11_security)); - - lbs_set_mac_control(priv); - - /* If RSN is already enabled, don't try to enable it again, since - * ENABLE_RSN resets internal state machines and will clobber the - * 4-way WPA handshake. - */ - - /* Get RSN enabled/disabled */ - ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_GET, &rsn); - if (ret) { - lbs_deb_assoc("Failed to get RSN status: %d\n", ret); - goto out; - } - - /* Don't re-enable RSN if it's already enabled */ - do_wpa = assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled; - if (do_wpa == rsn) - goto out; - - /* Set RSN enabled/disabled */ - ret = lbs_cmd_802_11_enable_rsn(priv, CMD_ACT_SET, &do_wpa); - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_wpa_keys(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - unsigned int flags = assoc_req->flags; - - lbs_deb_enter(LBS_DEB_ASSOC); - - /* Work around older firmware bug where WPA unicast and multicast - * keys must be set independently. Seen in SDIO parts with firmware - * version 5.0.11p0. - */ - - if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - clear_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); - assoc_req->flags = flags; - } - - if (ret) - goto out; - - memcpy(&priv->wpa_unicast_key, &assoc_req->wpa_unicast_key, - sizeof(struct enc_key)); - - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - clear_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - - ret = lbs_cmd_802_11_key_material(priv, CMD_ACT_SET, assoc_req); - assoc_req->flags = flags; - - memcpy(&priv->wpa_mcast_key, &assoc_req->wpa_mcast_key, - sizeof(struct enc_key)); - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int assoc_helper_wpa_ie(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - - if (assoc_req->secinfo.WPAenabled || assoc_req->secinfo.WPA2enabled) { - memcpy(&priv->wpa_ie, &assoc_req->wpa_ie, assoc_req->wpa_ie_len); - priv->wpa_ie_len = assoc_req->wpa_ie_len; - } else { - memset(&priv->wpa_ie, 0, MAX_WPA_IE_LEN); - priv->wpa_ie_len = 0; - } - - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int should_deauth_infrastructure(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - int ret = 0; - - if (priv->connect_status != LBS_CONNECTED) - return 0; - - lbs_deb_enter(LBS_DEB_ASSOC); - if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - lbs_deb_assoc("Deauthenticating due to new SSID\n"); - ret = 1; - goto out; - } - - if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - if (priv->secinfo.auth_mode != assoc_req->secinfo.auth_mode) { - lbs_deb_assoc("Deauthenticating due to new security\n"); - ret = 1; - goto out; - } - } - - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - lbs_deb_assoc("Deauthenticating due to new BSSID\n"); - ret = 1; - goto out; - } - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { - lbs_deb_assoc("Deauthenticating due to channel switch\n"); - ret = 1; - goto out; - } - - /* FIXME: deal with 'auto' mode somehow */ - if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - if (assoc_req->mode != IW_MODE_INFRA) { - lbs_deb_assoc("Deauthenticating due to leaving " - "infra mode\n"); - ret = 1; - goto out; - } - } - -out: - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - - -static int should_stop_adhoc(struct lbs_private *priv, - struct assoc_request * assoc_req) -{ - lbs_deb_enter(LBS_DEB_ASSOC); - - if (priv->connect_status != LBS_CONNECTED) - return 0; - - if (lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - assoc_req->ssid, assoc_req->ssid_len) != 0) - return 1; - - /* FIXME: deal with 'auto' mode somehow */ - if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - if (assoc_req->mode != IW_MODE_ADHOC) - return 1; - } - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { - if (assoc_req->channel != priv->curbssparams.channel) - return 1; - } - - lbs_deb_leave(LBS_DEB_ASSOC); - return 0; -} - - -/** - * @brief This function finds the best SSID in the Scan List - * - * Search the scan table for the best SSID that also matches the current - * adapter network preference (infrastructure or adhoc) - * - * @param priv A pointer to struct lbs_private - * - * @return index in BSSID list - */ -static struct bss_descriptor *lbs_find_best_ssid_in_list( - struct lbs_private *priv, uint8_t mode) -{ - uint8_t bestrssi = 0; - struct bss_descriptor *iter_bss; - struct bss_descriptor *best_bss = NULL; - - lbs_deb_enter(LBS_DEB_SCAN); - - mutex_lock(&priv->lock); - - list_for_each_entry(iter_bss, &priv->network_list, list) { - switch (mode) { - case IW_MODE_INFRA: - case IW_MODE_ADHOC: - if (!is_network_compatible(priv, iter_bss, mode)) - break; - if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) - break; - bestrssi = SCAN_RSSI(iter_bss->rssi); - best_bss = iter_bss; - break; - case IW_MODE_AUTO: - default: - if (SCAN_RSSI(iter_bss->rssi) <= bestrssi) - break; - bestrssi = SCAN_RSSI(iter_bss->rssi); - best_bss = iter_bss; - break; - } - } - - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_SCAN, "best_bss %p", best_bss); - return best_bss; -} - -/** - * @brief Find the best AP - * - * Used from association worker. - * - * @param priv A pointer to struct lbs_private structure - * @param pSSID A pointer to AP's ssid - * - * @return 0--success, otherwise--fail - */ -static int lbs_find_best_network_ssid(struct lbs_private *priv, - uint8_t *out_ssid, uint8_t *out_ssid_len, uint8_t preferred_mode, - uint8_t *out_mode) -{ - int ret = -1; - struct bss_descriptor *found; - - lbs_deb_enter(LBS_DEB_SCAN); - - priv->scan_ssid_len = 0; - lbs_scan_networks(priv, 1); - if (priv->surpriseremoved) - goto out; - - found = lbs_find_best_ssid_in_list(priv, preferred_mode); - if (found && (found->ssid_len > 0)) { - memcpy(out_ssid, &found->ssid, IW_ESSID_MAX_SIZE); - *out_ssid_len = found->ssid_len; - *out_mode = found->mode; - ret = 0; - } - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - - -void lbs_association_worker(struct work_struct *work) -{ - struct lbs_private *priv = container_of(work, struct lbs_private, - assoc_work.work); - struct assoc_request * assoc_req = NULL; - int ret = 0; - int find_any_ssid = 0; - DECLARE_SSID_BUF(ssid); - - lbs_deb_enter(LBS_DEB_ASSOC); - - mutex_lock(&priv->lock); - assoc_req = priv->pending_assoc_req; - priv->pending_assoc_req = NULL; - priv->in_progress_assoc_req = assoc_req; - mutex_unlock(&priv->lock); - - if (!assoc_req) - goto done; - - lbs_deb_assoc( - "Association Request:\n" - " flags: 0x%08lx\n" - " SSID: '%s'\n" - " chann: %d\n" - " band: %d\n" - " mode: %d\n" - " BSSID: %pM\n" - " secinfo: %s%s%s\n" - " auth_mode: %d\n", - assoc_req->flags, - print_ssid(ssid, assoc_req->ssid, assoc_req->ssid_len), - assoc_req->channel, assoc_req->band, assoc_req->mode, - assoc_req->bssid, - assoc_req->secinfo.WPAenabled ? " WPA" : "", - assoc_req->secinfo.WPA2enabled ? " WPA2" : "", - assoc_req->secinfo.wep_enabled ? " WEP" : "", - assoc_req->secinfo.auth_mode); - - /* If 'any' SSID was specified, find an SSID to associate with */ - if (test_bit(ASSOC_FLAG_SSID, &assoc_req->flags) - && !assoc_req->ssid_len) - find_any_ssid = 1; - - /* But don't use 'any' SSID if there's a valid locked BSSID to use */ - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - if (compare_ether_addr(assoc_req->bssid, bssid_any) - && compare_ether_addr(assoc_req->bssid, bssid_off)) - find_any_ssid = 0; - } - - if (find_any_ssid) { - u8 new_mode = assoc_req->mode; - - ret = lbs_find_best_network_ssid(priv, assoc_req->ssid, - &assoc_req->ssid_len, assoc_req->mode, &new_mode); - if (ret) { - lbs_deb_assoc("Could not find best network\n"); - ret = -ENETUNREACH; - goto out; - } - - /* Ensure we switch to the mode of the AP */ - if (assoc_req->mode == IW_MODE_AUTO) { - set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); - assoc_req->mode = new_mode; - } - } - - /* - * Check if the attributes being changing require deauthentication - * from the currently associated infrastructure access point. - */ - if (priv->mode == IW_MODE_INFRA) { - if (should_deauth_infrastructure(priv, assoc_req)) { - ret = lbs_cmd_80211_deauthenticate(priv, - priv->curbssparams.bssid, - WLAN_REASON_DEAUTH_LEAVING); - if (ret) { - lbs_deb_assoc("Deauthentication due to new " - "configuration request failed: %d\n", - ret); - } - } - } else if (priv->mode == IW_MODE_ADHOC) { - if (should_stop_adhoc(priv, assoc_req)) { - ret = lbs_adhoc_stop(priv); - if (ret) { - lbs_deb_assoc("Teardown of AdHoc network due to " - "new configuration request failed: %d\n", - ret); - } - - } - } - - /* Send the various configuration bits to the firmware */ - if (test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) { - ret = assoc_helper_mode(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) { - ret = assoc_helper_channel(priv, assoc_req); - if (ret) - goto out; - } - - if ( test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags) - || test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) { - ret = assoc_helper_wep_keys(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - ret = assoc_helper_secinfo(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { - ret = assoc_helper_wpa_ie(priv, assoc_req); - if (ret) - goto out; - } - - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags) - || test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - ret = assoc_helper_wpa_keys(priv, assoc_req); - if (ret) - goto out; - } - - /* SSID/BSSID should be the _last_ config option set, because they - * trigger the association attempt. - */ - if (test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags) - || test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - int success = 1; - - ret = assoc_helper_associate(priv, assoc_req); - if (ret) { - lbs_deb_assoc("ASSOC: association unsuccessful: %d\n", - ret); - success = 0; - } - - if (priv->connect_status != LBS_CONNECTED) { - lbs_deb_assoc("ASSOC: association unsuccessful, " - "not connected\n"); - success = 0; - } - - if (success) { - lbs_deb_assoc("associated to %pM\n", - priv->curbssparams.bssid); - lbs_prepare_and_send_command(priv, - CMD_802_11_RSSI, - 0, CMD_OPTION_WAITFORRSP, 0, NULL); - } else { - ret = -1; - } - } - -out: - if (ret) { - lbs_deb_assoc("ASSOC: reconfiguration attempt unsuccessful: %d\n", - ret); - } - - mutex_lock(&priv->lock); - priv->in_progress_assoc_req = NULL; - mutex_unlock(&priv->lock); - kfree(assoc_req); - -done: - lbs_deb_leave(LBS_DEB_ASSOC); -} - - -/* - * Caller MUST hold any necessary locks - */ -struct assoc_request *lbs_get_association_request(struct lbs_private *priv) -{ - struct assoc_request * assoc_req; - - lbs_deb_enter(LBS_DEB_ASSOC); - if (!priv->pending_assoc_req) { - priv->pending_assoc_req = kzalloc(sizeof(struct assoc_request), - GFP_KERNEL); - if (!priv->pending_assoc_req) { - lbs_pr_info("Not enough memory to allocate association" - " request!\n"); - return NULL; - } - } - - /* Copy current configuration attributes to the association request, - * but don't overwrite any that are already set. - */ - assoc_req = priv->pending_assoc_req; - if (!test_bit(ASSOC_FLAG_SSID, &assoc_req->flags)) { - memcpy(&assoc_req->ssid, &priv->curbssparams.ssid, - IW_ESSID_MAX_SIZE); - assoc_req->ssid_len = priv->curbssparams.ssid_len; - } - - if (!test_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags)) - assoc_req->channel = priv->curbssparams.channel; - - if (!test_bit(ASSOC_FLAG_BAND, &assoc_req->flags)) - assoc_req->band = priv->curbssparams.band; - - if (!test_bit(ASSOC_FLAG_MODE, &assoc_req->flags)) - assoc_req->mode = priv->mode; - - if (!test_bit(ASSOC_FLAG_BSSID, &assoc_req->flags)) { - memcpy(&assoc_req->bssid, priv->curbssparams.bssid, - ETH_ALEN); - } - - if (!test_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags)) { - int i; - for (i = 0; i < 4; i++) { - memcpy(&assoc_req->wep_keys[i], &priv->wep_keys[i], - sizeof(struct enc_key)); - } - } - - if (!test_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags)) - assoc_req->wep_tx_keyidx = priv->wep_tx_keyidx; - - if (!test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_mcast_key, &priv->wpa_mcast_key, - sizeof(struct enc_key)); - } - - if (!test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_unicast_key, &priv->wpa_unicast_key, - sizeof(struct enc_key)); - } - - if (!test_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags)) { - memcpy(&assoc_req->secinfo, &priv->secinfo, - sizeof(struct lbs_802_11_security)); - } - - if (!test_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags)) { - memcpy(&assoc_req->wpa_ie, &priv->wpa_ie, - MAX_WPA_IE_LEN); - assoc_req->wpa_ie_len = priv->wpa_ie_len; - } - - lbs_deb_leave(LBS_DEB_ASSOC); - return assoc_req; -} - - -/** - * @brief Deauthenticate from a specific BSS - * - * @param priv A pointer to struct lbs_private structure - * @param bssid The specific BSS to deauthenticate from - * @param reason The 802.11 sec. 7.3.1.7 Reason Code for deauthenticating - * - * @return 0 on success, error on failure - */ -int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, u8 bssid[ETH_ALEN], - u16 reason) -{ - struct cmd_ds_802_11_deauthenticate cmd; - int ret; - - lbs_deb_enter(LBS_DEB_JOIN); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.macaddr, &bssid[0], ETH_ALEN); - cmd.reasoncode = cpu_to_le16(reason); - - ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd); - - /* Clean up everything even if there was an error; can't assume that - * we're still authenticated to the AP after trying to deauth. - */ - lbs_mac_event_disconnected(priv); - - lbs_deb_leave(LBS_DEB_JOIN); - return ret; -} - diff --git a/drivers/net/wireless/libertas/assoc.h b/drivers/net/wireless/libertas/assoc.h deleted file mode 100644 index 6e765e9f91a3..000000000000 --- a/drivers/net/wireless/libertas/assoc.h +++ /dev/null @@ -1,16 +0,0 @@ -/* Copyright (C) 2006, Red Hat, Inc. */ - -#ifndef _LBS_ASSOC_H_ -#define _LBS_ASSOC_H_ - -#include "dev.h" - -void lbs_association_worker(struct work_struct *work); -struct assoc_request *lbs_get_association_request(struct lbs_private *priv); - -int lbs_adhoc_stop(struct lbs_private *priv); - -int lbs_cmd_80211_deauthenticate(struct lbs_private *priv, - u8 bssid[ETH_ALEN], u16 reason); - -#endif /* _LBS_ASSOC_H */ diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c deleted file mode 100644 index 0a324dcd264c..000000000000 --- a/drivers/net/wireless/libertas/cmd.c +++ /dev/null @@ -1,2121 +0,0 @@ -/** - * This file contains the handling of command. - * It prepares command and sends it to firmware when it is ready. - */ - -#include -#include -#include -#include -#include "host.h" -#include "hostcmd.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "assoc.h" -#include "wext.h" -#include "cmd.h" - -static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv); - - -/** - * @brief Simple callback that copies response back into command - * - * @param priv A pointer to struct lbs_private structure - * @param extra A pointer to the original command structure for which - * 'resp' is a response - * @param resp A pointer to the command response - * - * @return 0 on success, error on failure - */ -int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, - struct cmd_header *resp) -{ - struct cmd_header *buf = (void *)extra; - uint16_t copy_len; - - copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); - memcpy(buf, resp, copy_len); - return 0; -} -EXPORT_SYMBOL_GPL(lbs_cmd_copyback); - -/** - * @brief Simple callback that ignores the result. Use this if - * you just want to send a command to the hardware, but don't - * care for the result. - * - * @param priv ignored - * @param extra ignored - * @param resp ignored - * - * @return 0 for success - */ -static int lbs_cmd_async_callback(struct lbs_private *priv, unsigned long extra, - struct cmd_header *resp) -{ - return 0; -} - - -/** - * @brief Checks whether a command is allowed in Power Save mode - * - * @param command the command ID - * @return 1 if allowed, 0 if not allowed - */ -static u8 is_command_allowed_in_ps(u16 cmd) -{ - switch (cmd) { - case CMD_802_11_RSSI: - return 1; - default: - break; - } - return 0; -} - -/** - * @brief Updates the hardware details like MAC address and regulatory region - * - * @param priv A pointer to struct lbs_private structure - * - * @return 0 on success, error on failure - */ -int lbs_update_hw_spec(struct lbs_private *priv) -{ - struct cmd_ds_get_hw_spec cmd; - int ret = -1; - u32 i; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); - ret = lbs_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd); - if (ret) - goto out; - - priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo); - - /* The firmware release is in an interesting format: the patch - * level is in the most significant nibble ... so fix that: */ - priv->fwrelease = le32_to_cpu(cmd.fwrelease); - priv->fwrelease = (priv->fwrelease << 8) | - (priv->fwrelease >> 24 & 0xff); - - /* Some firmware capabilities: - * CF card firmware 5.0.16p0: cap 0x00000303 - * USB dongle firmware 5.110.17p2: cap 0x00000303 - */ - lbs_pr_info("%pM, fw %u.%u.%up%u, cap 0x%08x\n", - cmd.permanentaddr, - priv->fwrelease >> 24 & 0xff, - priv->fwrelease >> 16 & 0xff, - priv->fwrelease >> 8 & 0xff, - priv->fwrelease & 0xff, - priv->fwcapinfo); - lbs_deb_cmd("GET_HW_SPEC: hardware interface 0x%x, hardware spec 0x%04x\n", - cmd.hwifversion, cmd.version); - - /* Determine mesh_fw_ver from fwrelease and fwcapinfo */ - /* 5.0.16p0 9.0.0.p0 is known to NOT support any mesh */ - /* 5.110.22 have mesh command with 0xa3 command id */ - /* 10.0.0.p0 FW brings in mesh config command with different id */ - /* Check FW version MSB and initialize mesh_fw_ver */ - if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V5) - priv->mesh_fw_ver = MESH_FW_OLD; - else if ((MRVL_FW_MAJOR_REV(priv->fwrelease) >= MRVL_FW_V10) && - (priv->fwcapinfo & MESH_CAPINFO_ENABLE_MASK)) - priv->mesh_fw_ver = MESH_FW_NEW; - else - priv->mesh_fw_ver = MESH_NONE; - - /* Clamp region code to 8-bit since FW spec indicates that it should - * only ever be 8-bit, even though the field size is 16-bit. Some firmware - * returns non-zero high 8 bits here. - * - * Firmware version 4.0.102 used in CF8381 has region code shifted. We - * need to check for this problem and handle it properly. - */ - if (MRVL_FW_MAJOR_REV(priv->fwrelease) == MRVL_FW_V4) - priv->regioncode = (le16_to_cpu(cmd.regioncode) >> 8) & 0xFF; - else - priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF; - - for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { - /* use the region code to search for the index */ - if (priv->regioncode == lbs_region_code_to_index[i]) - break; - } - - /* if it's unidentified region code, use the default (USA) */ - if (i >= MRVDRV_MAX_REGION_CODE) { - priv->regioncode = 0x10; - lbs_pr_info("unidentified region code; using the default (USA)\n"); - } - - if (priv->current_addr[0] == 0xff) - memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); - - memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN); - if (priv->mesh_dev) - memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN); - - if (lbs_set_regiontable(priv, priv->regioncode, 0)) { - ret = -1; - goto out; - } - - if (lbs_set_universaltable(priv, 0)) { - ret = -1; - goto out; - } - -out: - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, - struct wol_config *p_wol_config) -{ - struct cmd_ds_host_sleep cmd_config; - int ret; - - cmd_config.hdr.size = cpu_to_le16(sizeof(cmd_config)); - cmd_config.criteria = cpu_to_le32(criteria); - cmd_config.gpio = priv->wol_gpio; - cmd_config.gap = priv->wol_gap; - - if (p_wol_config != NULL) - memcpy((uint8_t *)&cmd_config.wol_conf, (uint8_t *)p_wol_config, - sizeof(struct wol_config)); - else - cmd_config.wol_conf.action = CMD_ACT_ACTION_NONE; - - ret = lbs_cmd_with_response(priv, CMD_802_11_HOST_SLEEP_CFG, &cmd_config); - if (!ret) { - if (criteria) { - lbs_deb_cmd("Set WOL criteria to %x\n", criteria); - priv->wol_criteria = criteria; - } else - memcpy((uint8_t *) p_wol_config, - (uint8_t *)&cmd_config.wol_conf, - sizeof(struct wol_config)); - } else { - lbs_pr_info("HOST_SLEEP_CFG failed %d\n", ret); - } - - return ret; -} -EXPORT_SYMBOL_GPL(lbs_host_sleep_cfg); - -static int lbs_cmd_802_11_ps_mode(struct cmd_ds_command *cmd, - u16 cmd_action) -{ - struct cmd_ds_802_11_ps_mode *psm = &cmd->params.psmode; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd->command = cpu_to_le16(CMD_802_11_PS_MODE); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_ps_mode) + - S_DS_GEN); - psm->action = cpu_to_le16(cmd_action); - psm->multipledtim = 0; - switch (cmd_action) { - case CMD_SUBCMD_ENTER_PS: - lbs_deb_cmd("PS command:" "SubCode- Enter PS\n"); - - psm->locallisteninterval = 0; - psm->nullpktinterval = 0; - psm->multipledtim = - cpu_to_le16(MRVDRV_DEFAULT_MULTIPLE_DTIM); - break; - - case CMD_SUBCMD_EXIT_PS: - lbs_deb_cmd("PS command:" "SubCode- Exit PS\n"); - break; - - case CMD_SUBCMD_SLEEP_CONFIRMED: - lbs_deb_cmd("PS command: SubCode- sleep confirm\n"); - break; - - default: - break; - } - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, - uint16_t cmd_action, uint16_t *timeout) -{ - struct cmd_ds_802_11_inactivity_timeout cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.hdr.command = cpu_to_le16(CMD_802_11_INACTIVITY_TIMEOUT); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.action = cpu_to_le16(cmd_action); - - if (cmd_action == CMD_ACT_SET) - cmd.timeout = cpu_to_le16(*timeout); - else - cmd.timeout = 0; - - ret = lbs_cmd_with_response(priv, CMD_802_11_INACTIVITY_TIMEOUT, &cmd); - - if (!ret) - *timeout = le16_to_cpu(cmd.timeout); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return 0; -} - -int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, - struct sleep_params *sp) -{ - struct cmd_ds_802_11_sleep_params cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - if (cmd_action == CMD_ACT_GET) { - memset(&cmd, 0, sizeof(cmd)); - } else { - cmd.error = cpu_to_le16(sp->sp_error); - cmd.offset = cpu_to_le16(sp->sp_offset); - cmd.stabletime = cpu_to_le16(sp->sp_stabletime); - cmd.calcontrol = sp->sp_calcontrol; - cmd.externalsleepclk = sp->sp_extsleepclk; - cmd.reserved = cpu_to_le16(sp->sp_reserved); - } - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(cmd_action); - - ret = lbs_cmd_with_response(priv, CMD_802_11_SLEEP_PARAMS, &cmd); - - if (!ret) { - lbs_deb_cmd("error 0x%x, offset 0x%x, stabletime 0x%x, " - "calcontrol 0x%x extsleepclk 0x%x\n", - le16_to_cpu(cmd.error), le16_to_cpu(cmd.offset), - le16_to_cpu(cmd.stabletime), cmd.calcontrol, - cmd.externalsleepclk); - - sp->sp_error = le16_to_cpu(cmd.error); - sp->sp_offset = le16_to_cpu(cmd.offset); - sp->sp_stabletime = le16_to_cpu(cmd.stabletime); - sp->sp_calcontrol = cmd.calcontrol; - sp->sp_extsleepclk = cmd.externalsleepclk; - sp->sp_reserved = le16_to_cpu(cmd.reserved); - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return 0; -} - -int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, - struct assoc_request *assoc) -{ - struct cmd_ds_802_11_set_wep cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.command = cpu_to_le16(CMD_802_11_SET_WEP); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.action = cpu_to_le16(cmd_action); - - if (cmd_action == CMD_ACT_ADD) { - int i; - - /* default tx key index */ - cmd.keyindex = cpu_to_le16(assoc->wep_tx_keyidx & - CMD_WEP_KEY_INDEX_MASK); - - /* Copy key types and material to host command structure */ - for (i = 0; i < 4; i++) { - struct enc_key *pkey = &assoc->wep_keys[i]; - - switch (pkey->len) { - case KEY_LEN_WEP_40: - cmd.keytype[i] = CMD_TYPE_WEP_40_BIT; - memmove(cmd.keymaterial[i], pkey->key, pkey->len); - lbs_deb_cmd("SET_WEP: add key %d (40 bit)\n", i); - break; - case KEY_LEN_WEP_104: - cmd.keytype[i] = CMD_TYPE_WEP_104_BIT; - memmove(cmd.keymaterial[i], pkey->key, pkey->len); - lbs_deb_cmd("SET_WEP: add key %d (104 bit)\n", i); - break; - case 0: - break; - default: - lbs_deb_cmd("SET_WEP: invalid key %d, length %d\n", - i, pkey->len); - ret = -1; - goto done; - break; - } - } - } else if (cmd_action == CMD_ACT_REMOVE) { - /* ACT_REMOVE clears _all_ WEP keys */ - - /* default tx key index */ - cmd.keyindex = cpu_to_le16(priv->wep_tx_keyidx & - CMD_WEP_KEY_INDEX_MASK); - lbs_deb_cmd("SET_WEP: remove key %d\n", priv->wep_tx_keyidx); - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_SET_WEP, &cmd); -done: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, - uint16_t *enable) -{ - struct cmd_ds_802_11_enable_rsn cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(cmd_action); - - if (cmd_action == CMD_ACT_GET) - cmd.enable = 0; - else { - if (*enable) - cmd.enable = cpu_to_le16(CMD_ENABLE_RSN); - else - cmd.enable = cpu_to_le16(CMD_DISABLE_RSN); - lbs_deb_cmd("ENABLE_RSN: %d\n", *enable); - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_ENABLE_RSN, &cmd); - if (!ret && cmd_action == CMD_ACT_GET) - *enable = le16_to_cpu(cmd.enable); - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -static void set_one_wpa_key(struct MrvlIEtype_keyParamSet *keyparam, - struct enc_key *key) -{ - lbs_deb_enter(LBS_DEB_CMD); - - if (key->flags & KEY_INFO_WPA_ENABLED) - keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_ENABLED); - if (key->flags & KEY_INFO_WPA_UNICAST) - keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_UNICAST); - if (key->flags & KEY_INFO_WPA_MCAST) - keyparam->keyinfo |= cpu_to_le16(KEY_INFO_WPA_MCAST); - - keyparam->type = cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - keyparam->keytypeid = cpu_to_le16(key->type); - keyparam->keylen = cpu_to_le16(key->len); - memcpy(keyparam->key, key->key, key->len); - - /* Length field doesn't include the {type,length} header */ - keyparam->length = cpu_to_le16(sizeof(*keyparam) - 4); - lbs_deb_leave(LBS_DEB_CMD); -} - -int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, - struct assoc_request *assoc) -{ - struct cmd_ds_802_11_key_material cmd; - int ret = 0; - int index = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.action = cpu_to_le16(cmd_action); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - if (cmd_action == CMD_ACT_GET) { - cmd.hdr.size = cpu_to_le16(S_DS_GEN + 2); - } else { - memset(cmd.keyParamSet, 0, sizeof(cmd.keyParamSet)); - - if (test_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc->flags)) { - set_one_wpa_key(&cmd.keyParamSet[index], - &assoc->wpa_unicast_key); - index++; - } - - if (test_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc->flags)) { - set_one_wpa_key(&cmd.keyParamSet[index], - &assoc->wpa_mcast_key); - index++; - } - - /* The common header and as many keys as we included */ - cmd.hdr.size = cpu_to_le16(offsetof(typeof(cmd), - keyParamSet[index])); - } - ret = lbs_cmd_with_response(priv, CMD_802_11_KEY_MATERIAL, &cmd); - /* Copy the returned key to driver private data */ - if (!ret && cmd_action == CMD_ACT_GET) { - void *buf_ptr = cmd.keyParamSet; - void *resp_end = &(&cmd)[1]; - - while (buf_ptr < resp_end) { - struct MrvlIEtype_keyParamSet *keyparam = buf_ptr; - struct enc_key *key; - uint16_t param_set_len = le16_to_cpu(keyparam->length); - uint16_t key_len = le16_to_cpu(keyparam->keylen); - uint16_t key_flags = le16_to_cpu(keyparam->keyinfo); - uint16_t key_type = le16_to_cpu(keyparam->keytypeid); - void *end; - - end = (void *)keyparam + sizeof(keyparam->type) - + sizeof(keyparam->length) + param_set_len; - - /* Make sure we don't access past the end of the IEs */ - if (end > resp_end) - break; - - if (key_flags & KEY_INFO_WPA_UNICAST) - key = &priv->wpa_unicast_key; - else if (key_flags & KEY_INFO_WPA_MCAST) - key = &priv->wpa_mcast_key; - else - break; - - /* Copy returned key into driver */ - memset(key, 0, sizeof(struct enc_key)); - if (key_len > sizeof(key->key)) - break; - key->type = key_type; - key->flags = key_flags; - key->len = key_len; - memcpy(key->key, keyparam->key, key->len); - - buf_ptr = end + 1; - } - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * @brief Set an SNMP MIB value - * - * @param priv A pointer to struct lbs_private structure - * @param oid The OID to set in the firmware - * @param val Value to set the OID to - * - * @return 0 on success, error on failure - */ -int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val) -{ - struct cmd_ds_802_11_snmp_mib cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof (cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - cmd.oid = cpu_to_le16((u16) oid); - - switch (oid) { - case SNMP_MIB_OID_BSS_TYPE: - cmd.bufsize = cpu_to_le16(sizeof(u8)); - cmd.value[0] = (val == IW_MODE_ADHOC) ? 2 : 1; - break; - case SNMP_MIB_OID_11D_ENABLE: - case SNMP_MIB_OID_FRAG_THRESHOLD: - case SNMP_MIB_OID_RTS_THRESHOLD: - case SNMP_MIB_OID_SHORT_RETRY_LIMIT: - case SNMP_MIB_OID_LONG_RETRY_LIMIT: - cmd.bufsize = cpu_to_le16(sizeof(u16)); - *((__le16 *)(&cmd.value)) = cpu_to_le16(val); - break; - default: - lbs_deb_cmd("SNMP_CMD: (set) unhandled OID 0x%x\n", oid); - ret = -EINVAL; - goto out; - } - - lbs_deb_cmd("SNMP_CMD: (set) oid 0x%x, oid size 0x%x, value 0x%x\n", - le16_to_cpu(cmd.oid), le16_to_cpu(cmd.bufsize), val); - - ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd); - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * @brief Get an SNMP MIB value - * - * @param priv A pointer to struct lbs_private structure - * @param oid The OID to retrieve from the firmware - * @param out_val Location for the returned value - * - * @return 0 on success, error on failure - */ -int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val) -{ - struct cmd_ds_802_11_snmp_mib cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof (cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_GET); - cmd.oid = cpu_to_le16(oid); - - ret = lbs_cmd_with_response(priv, CMD_802_11_SNMP_MIB, &cmd); - if (ret) - goto out; - - switch (le16_to_cpu(cmd.bufsize)) { - case sizeof(u8): - if (oid == SNMP_MIB_OID_BSS_TYPE) { - if (cmd.value[0] == 2) - *out_val = IW_MODE_ADHOC; - else - *out_val = IW_MODE_INFRA; - } else - *out_val = cmd.value[0]; - break; - case sizeof(u16): - *out_val = le16_to_cpu(*((__le16 *)(&cmd.value))); - break; - default: - lbs_deb_cmd("SNMP_CMD: (get) unhandled OID 0x%x size %d\n", - oid, le16_to_cpu(cmd.bufsize)); - break; - } - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * @brief Get the min, max, and current TX power - * - * @param priv A pointer to struct lbs_private structure - * @param curlevel Current power level in dBm - * @param minlevel Minimum supported power level in dBm (optional) - * @param maxlevel Maximum supported power level in dBm (optional) - * - * @return 0 on success, error on failure - */ -int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, - s16 *maxlevel) -{ - struct cmd_ds_802_11_rf_tx_power cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_GET); - - ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd); - if (ret == 0) { - *curlevel = le16_to_cpu(cmd.curlevel); - if (minlevel) - *minlevel = cmd.minlevel; - if (maxlevel) - *maxlevel = cmd.maxlevel; - } - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -/** - * @brief Set the TX power - * - * @param priv A pointer to struct lbs_private structure - * @param dbm The desired power level in dBm - * - * @return 0 on success, error on failure - */ -int lbs_set_tx_power(struct lbs_private *priv, s16 dbm) -{ - struct cmd_ds_802_11_rf_tx_power cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - cmd.curlevel = cpu_to_le16(dbm); - - lbs_deb_cmd("SET_RF_TX_POWER: %d dBm\n", dbm); - - ret = lbs_cmd_with_response(priv, CMD_802_11_RF_TX_POWER, &cmd); - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -static int lbs_cmd_802_11_monitor_mode(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf) -{ - struct cmd_ds_802_11_monitor_mode *monitor = &cmd->params.monitor; - - cmd->command = cpu_to_le16(CMD_802_11_MONITOR_MODE); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_monitor_mode) + - S_DS_GEN); - - monitor->action = cpu_to_le16(cmd_action); - if (cmd_action == CMD_ACT_SET) { - monitor->mode = - cpu_to_le16((u16) (*(u32 *) pdata_buf)); - } - - return 0; -} - -static __le16 lbs_rate_to_fw_bitmap(int rate, int lower_rates_ok) -{ -/* Bit Rate -* 15:13 Reserved -* 12 54 Mbps -* 11 48 Mbps -* 10 36 Mbps -* 9 24 Mbps -* 8 18 Mbps -* 7 12 Mbps -* 6 9 Mbps -* 5 6 Mbps -* 4 Reserved -* 3 11 Mbps -* 2 5.5 Mbps -* 1 2 Mbps -* 0 1 Mbps -**/ - - uint16_t ratemask; - int i = lbs_data_rate_to_fw_index(rate); - if (lower_rates_ok) - ratemask = (0x1fef >> (12 - i)); - else - ratemask = (1 << i); - return cpu_to_le16(ratemask); -} - -int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, - uint16_t cmd_action) -{ - struct cmd_ds_802_11_rate_adapt_rateset cmd; - int ret; - - lbs_deb_enter(LBS_DEB_CMD); - - if (!priv->cur_rate && !priv->enablehwauto) - return -EINVAL; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - cmd.action = cpu_to_le16(cmd_action); - cmd.enablehwauto = cpu_to_le16(priv->enablehwauto); - cmd.bitmap = lbs_rate_to_fw_bitmap(priv->cur_rate, priv->enablehwauto); - ret = lbs_cmd_with_response(priv, CMD_802_11_RATE_ADAPT_RATESET, &cmd); - if (!ret && cmd_action == CMD_ACT_GET) { - priv->ratebitmap = le16_to_cpu(cmd.bitmap); - priv->enablehwauto = le16_to_cpu(cmd.enablehwauto); - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} -EXPORT_SYMBOL_GPL(lbs_cmd_802_11_rate_adapt_rateset); - -/** - * @brief Set the data rate - * - * @param priv A pointer to struct lbs_private structure - * @param rate The desired data rate, or 0 to clear a locked rate - * - * @return 0 on success, error on failure - */ -int lbs_set_data_rate(struct lbs_private *priv, u8 rate) -{ - struct cmd_ds_802_11_data_rate cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - - if (rate > 0) { - cmd.action = cpu_to_le16(CMD_ACT_SET_TX_FIX_RATE); - cmd.rates[0] = lbs_data_rate_to_fw_index(rate); - if (cmd.rates[0] == 0) { - lbs_deb_cmd("DATA_RATE: invalid requested rate of" - " 0x%02X\n", rate); - ret = 0; - goto out; - } - lbs_deb_cmd("DATA_RATE: set fixed 0x%02X\n", cmd.rates[0]); - } else { - cmd.action = cpu_to_le16(CMD_ACT_SET_TX_AUTO); - lbs_deb_cmd("DATA_RATE: setting auto\n"); - } - - ret = lbs_cmd_with_response(priv, CMD_802_11_DATA_RATE, &cmd); - if (ret) - goto out; - - lbs_deb_hex(LBS_DEB_CMD, "DATA_RATE_RESP", (u8 *) &cmd, sizeof (cmd)); - - /* FIXME: get actual rates FW can do if this command actually returns - * all data rates supported. - */ - priv->cur_rate = lbs_fw_index_to_data_rate(cmd.rates[0]); - lbs_deb_cmd("DATA_RATE: current rate is 0x%02x\n", priv->cur_rate); - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -/** - * @brief Get the radio channel - * - * @param priv A pointer to struct lbs_private structure - * - * @return The channel on success, error on failure - */ -int lbs_get_channel(struct lbs_private *priv) -{ - struct cmd_ds_802_11_rf_channel cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_GET); - - ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); - if (ret) - goto out; - - ret = le16_to_cpu(cmd.channel); - lbs_deb_cmd("current radio channel is %d\n", ret); - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -int lbs_update_channel(struct lbs_private *priv) -{ - int ret; - - /* the channel in f/w could be out of sync; get the current channel */ - lbs_deb_enter(LBS_DEB_ASSOC); - - ret = lbs_get_channel(priv); - if (ret > 0) { - priv->curbssparams.channel = ret; - ret = 0; - } - lbs_deb_leave_args(LBS_DEB_ASSOC, "ret %d", ret); - return ret; -} - -/** - * @brief Set the radio channel - * - * @param priv A pointer to struct lbs_private structure - * @param channel The desired channel, or 0 to clear a locked channel - * - * @return 0 on success, error on failure - */ -int lbs_set_channel(struct lbs_private *priv, u8 channel) -{ - struct cmd_ds_802_11_rf_channel cmd; -#ifdef DEBUG - u8 old_channel = priv->curbssparams.channel; -#endif - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); - cmd.channel = cpu_to_le16(channel); - - ret = lbs_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); - if (ret) - goto out; - - priv->curbssparams.channel = (uint8_t) le16_to_cpu(cmd.channel); - lbs_deb_cmd("channel switch from %d to %d\n", old_channel, - priv->curbssparams.channel); - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -static int lbs_cmd_802_11_rssi(struct lbs_private *priv, - struct cmd_ds_command *cmd) -{ - - lbs_deb_enter(LBS_DEB_CMD); - cmd->command = cpu_to_le16(CMD_802_11_RSSI); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_rssi) + S_DS_GEN); - cmd->params.rssi.N = cpu_to_le16(DEFAULT_BCN_AVG_FACTOR); - - /* reset Beacon SNR/NF/RSSI values */ - priv->SNR[TYPE_BEACON][TYPE_NOAVG] = 0; - priv->SNR[TYPE_BEACON][TYPE_AVG] = 0; - priv->NF[TYPE_BEACON][TYPE_NOAVG] = 0; - priv->NF[TYPE_BEACON][TYPE_AVG] = 0; - priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = 0; - priv->RSSI[TYPE_BEACON][TYPE_AVG] = 0; - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr, - u8 cmd_action, void *pdata_buf) -{ - struct lbs_offset_value *offval; - - lbs_deb_enter(LBS_DEB_CMD); - - offval = (struct lbs_offset_value *)pdata_buf; - - switch (le16_to_cpu(cmdptr->command)) { - case CMD_MAC_REG_ACCESS: - { - struct cmd_ds_mac_reg_access *macreg; - - cmdptr->size = - cpu_to_le16(sizeof (struct cmd_ds_mac_reg_access) - + S_DS_GEN); - macreg = - (struct cmd_ds_mac_reg_access *)&cmdptr->params. - macreg; - - macreg->action = cpu_to_le16(cmd_action); - macreg->offset = cpu_to_le16((u16) offval->offset); - macreg->value = cpu_to_le32(offval->value); - - break; - } - - case CMD_BBP_REG_ACCESS: - { - struct cmd_ds_bbp_reg_access *bbpreg; - - cmdptr->size = - cpu_to_le16(sizeof - (struct cmd_ds_bbp_reg_access) - + S_DS_GEN); - bbpreg = - (struct cmd_ds_bbp_reg_access *)&cmdptr->params. - bbpreg; - - bbpreg->action = cpu_to_le16(cmd_action); - bbpreg->offset = cpu_to_le16((u16) offval->offset); - bbpreg->value = (u8) offval->value; - - break; - } - - case CMD_RF_REG_ACCESS: - { - struct cmd_ds_rf_reg_access *rfreg; - - cmdptr->size = - cpu_to_le16(sizeof - (struct cmd_ds_rf_reg_access) + - S_DS_GEN); - rfreg = - (struct cmd_ds_rf_reg_access *)&cmdptr->params. - rfreg; - - rfreg->action = cpu_to_le16(cmd_action); - rfreg->offset = cpu_to_le16((u16) offval->offset); - rfreg->value = (u8) offval->value; - - break; - } - - default: - break; - } - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -static int lbs_cmd_bt_access(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf) -{ - struct cmd_ds_bt_access *bt_access = &cmd->params.bt; - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); - - cmd->command = cpu_to_le16(CMD_BT_ACCESS); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) + S_DS_GEN); - cmd->result = 0; - bt_access->action = cpu_to_le16(cmd_action); - - switch (cmd_action) { - case CMD_ACT_BT_ACCESS_ADD: - memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN); - lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6); - break; - case CMD_ACT_BT_ACCESS_DEL: - memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN); - lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6); - break; - case CMD_ACT_BT_ACCESS_LIST: - bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); - break; - case CMD_ACT_BT_ACCESS_RESET: - break; - case CMD_ACT_BT_ACCESS_SET_INVERT: - bt_access->id = cpu_to_le32(*(u32 *) pdata_buf); - break; - case CMD_ACT_BT_ACCESS_GET_INVERT: - break; - default: - break; - } - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd, - u16 cmd_action, void *pdata_buf) -{ - struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt; - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); - - cmd->command = cpu_to_le16(CMD_FWT_ACCESS); - cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) + S_DS_GEN); - cmd->result = 0; - - if (pdata_buf) - memcpy(fwt_access, pdata_buf, sizeof(*fwt_access)); - else - memset(fwt_access, 0, sizeof(*fwt_access)); - - fwt_access->action = cpu_to_le16(cmd_action); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, - struct cmd_ds_mesh_access *cmd) -{ - int ret; - - lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action); - - cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS); - cmd->hdr.size = cpu_to_le16(sizeof(*cmd)); - cmd->hdr.result = 0; - - cmd->action = cpu_to_le16(cmd_action); - - ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd); - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -static int __lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type) -{ - int ret; - u16 command = CMD_MESH_CONFIG_OLD; - - lbs_deb_enter(LBS_DEB_CMD); - - /* - * Command id is 0xac for v10 FW along with mesh interface - * id in bits 14-13-12. - */ - if (priv->mesh_fw_ver == MESH_FW_NEW) - command = CMD_MESH_CONFIG | - (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET); - - cmd->hdr.command = cpu_to_le16(command); - cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config)); - cmd->hdr.result = 0; - - cmd->type = cpu_to_le16(type); - cmd->action = cpu_to_le16(action); - - ret = lbs_cmd_with_response(priv, command, cmd); - - lbs_deb_leave(LBS_DEB_CMD); - return ret; -} - -int lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type) -{ - int ret; - - if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG)) - return -EOPNOTSUPP; - - ret = __lbs_mesh_config_send(priv, cmd, action, type); - return ret; -} - -/* This function is the CMD_MESH_CONFIG legacy function. It only handles the - * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG - * are all handled by preparing a struct cmd_ds_mesh_config and passing it to - * lbs_mesh_config_send. - */ -int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan) -{ - struct cmd_ds_mesh_config cmd; - struct mrvl_meshie *ie; - DECLARE_SSID_BUF(ssid); - - memset(&cmd, 0, sizeof(cmd)); - cmd.channel = cpu_to_le16(chan); - ie = (struct mrvl_meshie *)cmd.data; - - switch (action) { - case CMD_ACT_MESH_CONFIG_START: - ie->id = WLAN_EID_GENERIC; - ie->val.oui[0] = 0x00; - ie->val.oui[1] = 0x50; - ie->val.oui[2] = 0x43; - ie->val.type = MARVELL_MESH_IE_TYPE; - ie->val.subtype = MARVELL_MESH_IE_SUBTYPE; - ie->val.version = MARVELL_MESH_IE_VERSION; - ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP; - ie->val.active_metric_id = MARVELL_MESH_METRIC_ID; - ie->val.mesh_capability = MARVELL_MESH_CAPABILITY; - ie->val.mesh_id_len = priv->mesh_ssid_len; - memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len); - ie->len = sizeof(struct mrvl_meshie_val) - - IW_ESSID_MAX_SIZE + priv->mesh_ssid_len; - cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val)); - break; - case CMD_ACT_MESH_CONFIG_STOP: - break; - default: - return -1; - } - lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", - action, priv->mesh_tlv, chan, - print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); - - return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); -} - -static int lbs_cmd_bcn_ctrl(struct lbs_private * priv, - struct cmd_ds_command *cmd, - u16 cmd_action) -{ - struct cmd_ds_802_11_beacon_control - *bcn_ctrl = &cmd->params.bcn_ctrl; - - lbs_deb_enter(LBS_DEB_CMD); - cmd->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_beacon_control) - + S_DS_GEN); - cmd->command = cpu_to_le16(CMD_802_11_BEACON_CTRL); - - bcn_ctrl->action = cpu_to_le16(cmd_action); - bcn_ctrl->beacon_enable = cpu_to_le16(priv->beacon_enable); - bcn_ctrl->beacon_period = cpu_to_le16(priv->beacon_period); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -static void lbs_queue_cmd(struct lbs_private *priv, - struct cmd_ctrl_node *cmdnode) -{ - unsigned long flags; - int addtail = 1; - - lbs_deb_enter(LBS_DEB_HOST); - - if (!cmdnode) { - lbs_deb_host("QUEUE_CMD: cmdnode is NULL\n"); - goto done; - } - if (!cmdnode->cmdbuf->size) { - lbs_deb_host("DNLD_CMD: cmd size is zero\n"); - goto done; - } - cmdnode->result = 0; - - /* Exit_PS command needs to be queued in the header always. */ - if (le16_to_cpu(cmdnode->cmdbuf->command) == CMD_802_11_PS_MODE) { - struct cmd_ds_802_11_ps_mode *psm = (void *) &cmdnode->cmdbuf[1]; - - if (psm->action == cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { - if (priv->psstate != PS_STATE_FULL_POWER) - addtail = 0; - } - } - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (addtail) - list_add_tail(&cmdnode->list, &priv->cmdpendingq); - else - list_add(&cmdnode->list, &priv->cmdpendingq); - - spin_unlock_irqrestore(&priv->driver_lock, flags); - - lbs_deb_host("QUEUE_CMD: inserted command 0x%04x into cmdpendingq\n", - le16_to_cpu(cmdnode->cmdbuf->command)); - -done: - lbs_deb_leave(LBS_DEB_HOST); -} - -static void lbs_submit_command(struct lbs_private *priv, - struct cmd_ctrl_node *cmdnode) -{ - unsigned long flags; - struct cmd_header *cmd; - uint16_t cmdsize; - uint16_t command; - int timeo = 3 * HZ; - int ret; - - lbs_deb_enter(LBS_DEB_HOST); - - cmd = cmdnode->cmdbuf; - - spin_lock_irqsave(&priv->driver_lock, flags); - priv->cur_cmd = cmdnode; - priv->cur_cmd_retcode = 0; - spin_unlock_irqrestore(&priv->driver_lock, flags); - - cmdsize = le16_to_cpu(cmd->size); - command = le16_to_cpu(cmd->command); - - /* These commands take longer */ - if (command == CMD_802_11_SCAN || command == CMD_802_11_ASSOCIATE) - timeo = 5 * HZ; - - lbs_deb_cmd("DNLD_CMD: command 0x%04x, seq %d, size %d\n", - command, le16_to_cpu(cmd->seqnum), cmdsize); - lbs_deb_hex(LBS_DEB_CMD, "DNLD_CMD", (void *) cmdnode->cmdbuf, cmdsize); - - ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); - - if (ret) { - lbs_pr_info("DNLD_CMD: hw_host_to_card failed: %d\n", ret); - /* Let the timer kick in and retry, and potentially reset - the whole thing if the condition persists */ - timeo = HZ/4; - } - - /* Setup the timer after transmit command */ - mod_timer(&priv->command_timer, jiffies + timeo); - - lbs_deb_leave(LBS_DEB_HOST); -} - -/** - * This function inserts command node to cmdfreeq - * after cleans it. Requires priv->driver_lock held. - */ -static void __lbs_cleanup_and_insert_cmd(struct lbs_private *priv, - struct cmd_ctrl_node *cmdnode) -{ - lbs_deb_enter(LBS_DEB_HOST); - - if (!cmdnode) - goto out; - - cmdnode->callback = NULL; - cmdnode->callback_arg = 0; - - memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE); - - list_add_tail(&cmdnode->list, &priv->cmdfreeq); - out: - lbs_deb_leave(LBS_DEB_HOST); -} - -static void lbs_cleanup_and_insert_cmd(struct lbs_private *priv, - struct cmd_ctrl_node *ptempcmd) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->driver_lock, flags); - __lbs_cleanup_and_insert_cmd(priv, ptempcmd); - spin_unlock_irqrestore(&priv->driver_lock, flags); -} - -void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, - int result) -{ - if (cmd == priv->cur_cmd) - priv->cur_cmd_retcode = result; - - cmd->result = result; - cmd->cmdwaitqwoken = 1; - wake_up_interruptible(&cmd->cmdwait_q); - - if (!cmd->callback || cmd->callback == lbs_cmd_async_callback) - __lbs_cleanup_and_insert_cmd(priv, cmd); - priv->cur_cmd = NULL; -} - -int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on) -{ - struct cmd_ds_802_11_radio_control cmd; - int ret = -EINVAL; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - - /* Only v8 and below support setting the preamble */ - if (priv->fwrelease < 0x09000000) { - switch (preamble) { - case RADIO_PREAMBLE_SHORT: - if (!(priv->capability & WLAN_CAPABILITY_SHORT_PREAMBLE)) - goto out; - /* Fall through */ - case RADIO_PREAMBLE_AUTO: - case RADIO_PREAMBLE_LONG: - cmd.control = cpu_to_le16(preamble); - break; - default: - goto out; - } - } - - if (radio_on) - cmd.control |= cpu_to_le16(0x1); - else { - cmd.control &= cpu_to_le16(~0x1); - priv->txpower_cur = 0; - } - - lbs_deb_cmd("RADIO_CONTROL: radio %s, preamble %d\n", - radio_on ? "ON" : "OFF", preamble); - - priv->radio_on = radio_on; - - ret = lbs_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); - -out: - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -void lbs_set_mac_control(struct lbs_private *priv) -{ - struct cmd_ds_mac_control cmd; - - lbs_deb_enter(LBS_DEB_CMD); - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(priv->mac_control); - cmd.reserved = 0; - - lbs_cmd_async(priv, CMD_MAC_CONTROL, &cmd.hdr, sizeof(cmd)); - - lbs_deb_leave(LBS_DEB_CMD); -} - -/** - * @brief This function prepare the command before send to firmware. - * - * @param priv A pointer to struct lbs_private structure - * @param cmd_no command number - * @param cmd_action command action: GET or SET - * @param wait_option wait option: wait response or not - * @param cmd_oid cmd oid: treated as sub command - * @param pdata_buf A pointer to informaion buffer - * @return 0 or -1 - */ -int lbs_prepare_and_send_command(struct lbs_private *priv, - u16 cmd_no, - u16 cmd_action, - u16 wait_option, u32 cmd_oid, void *pdata_buf) -{ - int ret = 0; - struct cmd_ctrl_node *cmdnode; - struct cmd_ds_command *cmdptr; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_HOST); - - if (!priv) { - lbs_deb_host("PREP_CMD: priv is NULL\n"); - ret = -1; - goto done; - } - - if (priv->surpriseremoved) { - lbs_deb_host("PREP_CMD: card removed\n"); - ret = -1; - goto done; - } - - cmdnode = lbs_get_cmd_ctrl_node(priv); - - if (cmdnode == NULL) { - lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); - - /* Wake up main thread to execute next command */ - wake_up_interruptible(&priv->waitq); - ret = -1; - goto done; - } - - cmdnode->callback = NULL; - cmdnode->callback_arg = (unsigned long)pdata_buf; - - cmdptr = (struct cmd_ds_command *)cmdnode->cmdbuf; - - lbs_deb_host("PREP_CMD: command 0x%04x\n", cmd_no); - - /* Set sequence number, command and INT option */ - priv->seqnum++; - cmdptr->seqnum = cpu_to_le16(priv->seqnum); - - cmdptr->command = cpu_to_le16(cmd_no); - cmdptr->result = 0; - - switch (cmd_no) { - case CMD_802_11_PS_MODE: - ret = lbs_cmd_802_11_ps_mode(cmdptr, cmd_action); - break; - - case CMD_MAC_REG_ACCESS: - case CMD_BBP_REG_ACCESS: - case CMD_RF_REG_ACCESS: - ret = lbs_cmd_reg_access(cmdptr, cmd_action, pdata_buf); - break; - - case CMD_802_11_MONITOR_MODE: - ret = lbs_cmd_802_11_monitor_mode(cmdptr, - cmd_action, pdata_buf); - break; - - case CMD_802_11_RSSI: - ret = lbs_cmd_802_11_rssi(priv, cmdptr); - break; - - case CMD_802_11_SET_AFC: - case CMD_802_11_GET_AFC: - - cmdptr->command = cpu_to_le16(cmd_no); - cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_802_11_afc) + - S_DS_GEN); - - memmove(&cmdptr->params.afc, - pdata_buf, sizeof(struct cmd_ds_802_11_afc)); - - ret = 0; - goto done; - - case CMD_802_11D_DOMAIN_INFO: - ret = lbs_cmd_802_11d_domain_info(priv, cmdptr, - cmd_no, cmd_action); - break; - - case CMD_802_11_TPC_CFG: - cmdptr->command = cpu_to_le16(CMD_802_11_TPC_CFG); - cmdptr->size = - cpu_to_le16(sizeof(struct cmd_ds_802_11_tpc_cfg) + - S_DS_GEN); - - memmove(&cmdptr->params.tpccfg, - pdata_buf, sizeof(struct cmd_ds_802_11_tpc_cfg)); - - ret = 0; - break; - case CMD_802_11_LED_GPIO_CTRL: - { - struct mrvl_ie_ledgpio *gpio = - (struct mrvl_ie_ledgpio*) - cmdptr->params.ledgpio.data; - - memmove(&cmdptr->params.ledgpio, - pdata_buf, - sizeof(struct cmd_ds_802_11_led_ctrl)); - - cmdptr->command = - cpu_to_le16(CMD_802_11_LED_GPIO_CTRL); - -#define ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN 8 - cmdptr->size = - cpu_to_le16(le16_to_cpu(gpio->header.len) - + S_DS_GEN - + ACTION_NUMLED_TLVTYPE_LEN_FIELDS_LEN); - gpio->header.len = gpio->header.len; - - ret = 0; - break; - } - - case CMD_BT_ACCESS: - ret = lbs_cmd_bt_access(cmdptr, cmd_action, pdata_buf); - break; - - case CMD_FWT_ACCESS: - ret = lbs_cmd_fwt_access(cmdptr, cmd_action, pdata_buf); - break; - - case CMD_GET_TSF: - cmdptr->command = cpu_to_le16(CMD_GET_TSF); - cmdptr->size = cpu_to_le16(sizeof(struct cmd_ds_get_tsf) + - S_DS_GEN); - ret = 0; - break; - case CMD_802_11_BEACON_CTRL: - ret = lbs_cmd_bcn_ctrl(priv, cmdptr, cmd_action); - break; - default: - lbs_pr_err("PREP_CMD: unknown command 0x%04x\n", cmd_no); - ret = -1; - break; - } - - /* return error, since the command preparation failed */ - if (ret != 0) { - lbs_deb_host("PREP_CMD: command preparation failed\n"); - lbs_cleanup_and_insert_cmd(priv, cmdnode); - ret = -1; - goto done; - } - - cmdnode->cmdwaitqwoken = 0; - - lbs_queue_cmd(priv, cmdnode); - wake_up_interruptible(&priv->waitq); - - if (wait_option & CMD_OPTION_WAITFORRSP) { - lbs_deb_host("PREP_CMD: wait for response\n"); - might_sleep(); - wait_event_interruptible(cmdnode->cmdwait_q, - cmdnode->cmdwaitqwoken); - } - - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->cur_cmd_retcode) { - lbs_deb_host("PREP_CMD: command failed with return code %d\n", - priv->cur_cmd_retcode); - priv->cur_cmd_retcode = 0; - ret = -1; - } - spin_unlock_irqrestore(&priv->driver_lock, flags); - -done: - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} - -/** - * @brief This function allocates the command buffer and link - * it to command free queue. - * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 - */ -int lbs_allocate_cmd_buffer(struct lbs_private *priv) -{ - int ret = 0; - u32 bufsize; - u32 i; - struct cmd_ctrl_node *cmdarray; - - lbs_deb_enter(LBS_DEB_HOST); - - /* Allocate and initialize the command array */ - bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS; - if (!(cmdarray = kzalloc(bufsize, GFP_KERNEL))) { - lbs_deb_host("ALLOC_CMD_BUF: tempcmd_array is NULL\n"); - ret = -1; - goto done; - } - priv->cmd_array = cmdarray; - - /* Allocate and initialize each command buffer in the command array */ - for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { - cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL); - if (!cmdarray[i].cmdbuf) { - lbs_deb_host("ALLOC_CMD_BUF: ptempvirtualaddr is NULL\n"); - ret = -1; - goto done; - } - } - - for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { - init_waitqueue_head(&cmdarray[i].cmdwait_q); - lbs_cleanup_and_insert_cmd(priv, &cmdarray[i]); - } - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} - -/** - * @brief This function frees the command buffer. - * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 - */ -int lbs_free_cmd_buffer(struct lbs_private *priv) -{ - struct cmd_ctrl_node *cmdarray; - unsigned int i; - - lbs_deb_enter(LBS_DEB_HOST); - - /* need to check if cmd array is allocated or not */ - if (priv->cmd_array == NULL) { - lbs_deb_host("FREE_CMD_BUF: cmd_array is NULL\n"); - goto done; - } - - cmdarray = priv->cmd_array; - - /* Release shared memory buffers */ - for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { - if (cmdarray[i].cmdbuf) { - kfree(cmdarray[i].cmdbuf); - cmdarray[i].cmdbuf = NULL; - } - } - - /* Release cmd_ctrl_node */ - if (priv->cmd_array) { - kfree(priv->cmd_array); - priv->cmd_array = NULL; - } - -done: - lbs_deb_leave(LBS_DEB_HOST); - return 0; -} - -/** - * @brief This function gets a free command node if available in - * command free queue. - * - * @param priv A pointer to struct lbs_private structure - * @return cmd_ctrl_node A pointer to cmd_ctrl_node structure or NULL - */ -static struct cmd_ctrl_node *lbs_get_cmd_ctrl_node(struct lbs_private *priv) -{ - struct cmd_ctrl_node *tempnode; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_HOST); - - if (!priv) - return NULL; - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (!list_empty(&priv->cmdfreeq)) { - tempnode = list_first_entry(&priv->cmdfreeq, - struct cmd_ctrl_node, list); - list_del(&tempnode->list); - } else { - lbs_deb_host("GET_CMD_NODE: cmd_ctrl_node is not available\n"); - tempnode = NULL; - } - - spin_unlock_irqrestore(&priv->driver_lock, flags); - - lbs_deb_leave(LBS_DEB_HOST); - return tempnode; -} - -/** - * @brief This function executes next command in command - * pending queue. It will put firmware back to PS mode - * if applicable. - * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 - */ -int lbs_execute_next_command(struct lbs_private *priv) -{ - struct cmd_ctrl_node *cmdnode = NULL; - struct cmd_header *cmd; - unsigned long flags; - int ret = 0; - - /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the - * only caller to us is lbs_thread() and we get even when a - * data packet is received */ - lbs_deb_enter(LBS_DEB_THREAD); - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->cur_cmd) { - lbs_pr_alert( "EXEC_NEXT_CMD: already processing command!\n"); - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - - if (!list_empty(&priv->cmdpendingq)) { - cmdnode = list_first_entry(&priv->cmdpendingq, - struct cmd_ctrl_node, list); - } - - spin_unlock_irqrestore(&priv->driver_lock, flags); - - if (cmdnode) { - cmd = cmdnode->cmdbuf; - - if (is_command_allowed_in_ps(le16_to_cpu(cmd->command))) { - if ((priv->psstate == PS_STATE_SLEEP) || - (priv->psstate == PS_STATE_PRE_SLEEP)) { - lbs_deb_host( - "EXEC_NEXT_CMD: cannot send cmd 0x%04x in psstate %d\n", - le16_to_cpu(cmd->command), - priv->psstate); - ret = -1; - goto done; - } - lbs_deb_host("EXEC_NEXT_CMD: OK to send command " - "0x%04x in psstate %d\n", - le16_to_cpu(cmd->command), priv->psstate); - } else if (priv->psstate != PS_STATE_FULL_POWER) { - /* - * 1. Non-PS command: - * Queue it. set needtowakeup to TRUE if current state - * is SLEEP, otherwise call lbs_ps_wakeup to send Exit_PS. - * 2. PS command but not Exit_PS: - * Ignore it. - * 3. PS command Exit_PS: - * Set needtowakeup to TRUE if current state is SLEEP, - * otherwise send this command down to firmware - * immediately. - */ - if (cmd->command != cpu_to_le16(CMD_802_11_PS_MODE)) { - /* Prepare to send Exit PS, - * this non PS command will be sent later */ - if ((priv->psstate == PS_STATE_SLEEP) - || (priv->psstate == PS_STATE_PRE_SLEEP) - ) { - /* w/ new scheme, it will not reach here. - since it is blocked in main_thread. */ - priv->needtowakeup = 1; - } else - lbs_ps_wakeup(priv, 0); - - ret = 0; - goto done; - } else { - /* - * PS command. Ignore it if it is not Exit_PS. - * otherwise send it down immediately. - */ - struct cmd_ds_802_11_ps_mode *psm = (void *)&cmd[1]; - - lbs_deb_host( - "EXEC_NEXT_CMD: PS cmd, action 0x%02x\n", - psm->action); - if (psm->action != - cpu_to_le16(CMD_SUBCMD_EXIT_PS)) { - lbs_deb_host( - "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n"); - list_del(&cmdnode->list); - spin_lock_irqsave(&priv->driver_lock, flags); - lbs_complete_command(priv, cmdnode, 0); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - ret = 0; - goto done; - } - - if ((priv->psstate == PS_STATE_SLEEP) || - (priv->psstate == PS_STATE_PRE_SLEEP)) { - lbs_deb_host( - "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n"); - list_del(&cmdnode->list); - spin_lock_irqsave(&priv->driver_lock, flags); - lbs_complete_command(priv, cmdnode, 0); - spin_unlock_irqrestore(&priv->driver_lock, flags); - priv->needtowakeup = 1; - - ret = 0; - goto done; - } - - lbs_deb_host( - "EXEC_NEXT_CMD: sending EXIT_PS\n"); - } - } - list_del(&cmdnode->list); - lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n", - le16_to_cpu(cmd->command)); - lbs_submit_command(priv, cmdnode); - } else { - /* - * check if in power save mode, if yes, put the device back - * to PS mode - */ - if ((priv->psmode != LBS802_11POWERMODECAM) && - (priv->psstate == PS_STATE_FULL_POWER) && - ((priv->connect_status == LBS_CONNECTED) || - (priv->mesh_connect_status == LBS_CONNECTED))) { - if (priv->secinfo.WPAenabled || - priv->secinfo.WPA2enabled) { - /* check for valid WPA group keys */ - if (priv->wpa_mcast_key.len || - priv->wpa_unicast_key.len) { - lbs_deb_host( - "EXEC_NEXT_CMD: WPA enabled and GTK_SET" - " go back to PS_SLEEP"); - lbs_ps_sleep(priv, 0); - } - } else { - lbs_deb_host( - "EXEC_NEXT_CMD: cmdpendingq empty, " - "go back to PS_SLEEP"); - lbs_ps_sleep(priv, 0); - } - } - } - - ret = 0; -done: - lbs_deb_leave(LBS_DEB_THREAD); - return ret; -} - -void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str) -{ - union iwreq_data iwrq; - u8 buf[50]; - - lbs_deb_enter(LBS_DEB_WEXT); - - memset(&iwrq, 0, sizeof(union iwreq_data)); - memset(buf, 0, sizeof(buf)); - - snprintf(buf, sizeof(buf) - 1, "%s", str); - - iwrq.data.length = strlen(buf) + 1 + IW_EV_LCP_LEN; - - /* Send Event to upper layer */ - lbs_deb_wext("event indication string %s\n", (char *)buf); - lbs_deb_wext("event indication length %d\n", iwrq.data.length); - lbs_deb_wext("sending wireless event IWEVCUSTOM for %s\n", str); - - wireless_send_event(priv->dev, IWEVCUSTOM, &iwrq, buf); - - lbs_deb_leave(LBS_DEB_WEXT); -} - -static void lbs_send_confirmsleep(struct lbs_private *priv) -{ - unsigned long flags; - int ret; - - lbs_deb_enter(LBS_DEB_HOST); - lbs_deb_hex(LBS_DEB_HOST, "sleep confirm", (u8 *) &confirm_sleep, - sizeof(confirm_sleep)); - - ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &confirm_sleep, - sizeof(confirm_sleep)); - if (ret) { - lbs_pr_alert("confirm_sleep failed\n"); - goto out; - } - - spin_lock_irqsave(&priv->driver_lock, flags); - - /* We don't get a response on the sleep-confirmation */ - priv->dnld_sent = DNLD_RES_RECEIVED; - - /* If nothing to do, go back to sleep (?) */ - if (!__kfifo_len(priv->event_fifo) && !priv->resp_len[priv->resp_idx]) - priv->psstate = PS_STATE_SLEEP; - - spin_unlock_irqrestore(&priv->driver_lock, flags); - -out: - lbs_deb_leave(LBS_DEB_HOST); -} - -void lbs_ps_sleep(struct lbs_private *priv, int wait_option) -{ - lbs_deb_enter(LBS_DEB_HOST); - - /* - * PS is currently supported only in Infrastructure mode - * Remove this check if it is to be supported in IBSS mode also - */ - - lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, - CMD_SUBCMD_ENTER_PS, wait_option, 0, NULL); - - lbs_deb_leave(LBS_DEB_HOST); -} - -/** - * @brief This function sends Exit_PS command to firmware. - * - * @param priv A pointer to struct lbs_private structure - * @param wait_option wait response or not - * @return n/a - */ -void lbs_ps_wakeup(struct lbs_private *priv, int wait_option) -{ - __le32 Localpsmode; - - lbs_deb_enter(LBS_DEB_HOST); - - Localpsmode = cpu_to_le32(LBS802_11POWERMODECAM); - - lbs_prepare_and_send_command(priv, CMD_802_11_PS_MODE, - CMD_SUBCMD_EXIT_PS, - wait_option, 0, &Localpsmode); - - lbs_deb_leave(LBS_DEB_HOST); -} - -/** - * @brief This function checks condition and prepares to - * send sleep confirm command to firmware if ok. - * - * @param priv A pointer to struct lbs_private structure - * @param psmode Power Saving mode - * @return n/a - */ -void lbs_ps_confirm_sleep(struct lbs_private *priv) -{ - unsigned long flags =0; - int allowed = 1; - - lbs_deb_enter(LBS_DEB_HOST); - - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->dnld_sent) { - allowed = 0; - lbs_deb_host("dnld_sent was set\n"); - } - - /* In-progress command? */ - if (priv->cur_cmd) { - allowed = 0; - lbs_deb_host("cur_cmd was set\n"); - } - - /* Pending events or command responses? */ - if (__kfifo_len(priv->event_fifo) || priv->resp_len[priv->resp_idx]) { - allowed = 0; - lbs_deb_host("pending events or command responses\n"); - } - spin_unlock_irqrestore(&priv->driver_lock, flags); - - if (allowed) { - lbs_deb_host("sending lbs_ps_confirm_sleep\n"); - lbs_send_confirmsleep(priv); - } else { - lbs_deb_host("sleep confirm has been delayed\n"); - } - - lbs_deb_leave(LBS_DEB_HOST); -} - - -/** - * @brief Configures the transmission power control functionality. - * - * @param priv A pointer to struct lbs_private structure - * @param enable Transmission power control enable - * @param p0 Power level when link quality is good (dBm). - * @param p1 Power level when link quality is fair (dBm). - * @param p2 Power level when link quality is poor (dBm). - * @param usesnr Use Signal to Noise Ratio in TPC - * - * @return 0 on success - */ -int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, - int8_t p2, int usesnr) -{ - struct cmd_ds_802_11_tpc_cfg cmd; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - cmd.enable = !!enable; - cmd.usesnr = !!usesnr; - cmd.P0 = p0; - cmd.P1 = p1; - cmd.P2 = p2; - - ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd); - - return ret; -} - -/** - * @brief Configures the power adaptation settings. - * - * @param priv A pointer to struct lbs_private structure - * @param enable Power adaptation enable - * @param p0 Power level for 1, 2, 5.5 and 11 Mbps (dBm). - * @param p1 Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm). - * @param p2 Power level for 48 and 54 Mbps (dBm). - * - * @return 0 on Success - */ - -int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, - int8_t p1, int8_t p2) -{ - struct cmd_ds_802_11_pa_cfg cmd; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - cmd.enable = !!enable; - cmd.P0 = p0; - cmd.P1 = p1; - cmd.P2 = p2; - - ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd); - - return ret; -} - - -static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv, - uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), - unsigned long callback_arg) -{ - struct cmd_ctrl_node *cmdnode; - - lbs_deb_enter(LBS_DEB_HOST); - - if (priv->surpriseremoved) { - lbs_deb_host("PREP_CMD: card removed\n"); - cmdnode = ERR_PTR(-ENOENT); - goto done; - } - - cmdnode = lbs_get_cmd_ctrl_node(priv); - if (cmdnode == NULL) { - lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); - - /* Wake up main thread to execute next command */ - wake_up_interruptible(&priv->waitq); - cmdnode = ERR_PTR(-ENOBUFS); - goto done; - } - - cmdnode->callback = callback; - cmdnode->callback_arg = callback_arg; - - /* Copy the incoming command to the buffer */ - memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size); - - /* Set sequence number, clean result, move to buffer */ - priv->seqnum++; - cmdnode->cmdbuf->command = cpu_to_le16(command); - cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size); - cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum); - cmdnode->cmdbuf->result = 0; - - lbs_deb_host("PREP_CMD: command 0x%04x\n", command); - - cmdnode->cmdwaitqwoken = 0; - lbs_queue_cmd(priv, cmdnode); - wake_up_interruptible(&priv->waitq); - - done: - lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode); - return cmdnode; -} - -void lbs_cmd_async(struct lbs_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size) -{ - lbs_deb_enter(LBS_DEB_CMD); - __lbs_cmd_async(priv, command, in_cmd, in_cmd_size, - lbs_cmd_async_callback, 0); - lbs_deb_leave(LBS_DEB_CMD); -} - -int __lbs_cmd(struct lbs_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), - unsigned long callback_arg) -{ - struct cmd_ctrl_node *cmdnode; - unsigned long flags; - int ret = 0; - - lbs_deb_enter(LBS_DEB_HOST); - - cmdnode = __lbs_cmd_async(priv, command, in_cmd, in_cmd_size, - callback, callback_arg); - if (IS_ERR(cmdnode)) { - ret = PTR_ERR(cmdnode); - goto done; - } - - might_sleep(); - wait_event_interruptible(cmdnode->cmdwait_q, cmdnode->cmdwaitqwoken); - - spin_lock_irqsave(&priv->driver_lock, flags); - ret = cmdnode->result; - if (ret) - lbs_pr_info("PREP_CMD: command 0x%04x failed: %d\n", - command, ret); - - __lbs_cleanup_and_insert_cmd(priv, cmdnode); - spin_unlock_irqrestore(&priv->driver_lock, flags); - -done: - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} -EXPORT_SYMBOL_GPL(__lbs_cmd); - - diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h deleted file mode 100644 index 392e578ca095..000000000000 --- a/drivers/net/wireless/libertas/cmd.h +++ /dev/null @@ -1,87 +0,0 @@ -/* Copyright (C) 2007, Red Hat, Inc. */ - -#ifndef _LBS_CMD_H_ -#define _LBS_CMD_H_ - -#include "hostcmd.h" -#include "dev.h" - -/* lbs_cmd() infers the size of the buffer to copy data back into, from - the size of the target of the pointer. Since the command to be sent - may often be smaller, that size is set in cmd->size by the caller.*/ -#define lbs_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \ - uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \ - (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \ - __lbs_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \ -}) - -#define lbs_cmd_with_response(priv, cmdnr, cmd) \ - lbs_cmd(priv, cmdnr, cmd, lbs_cmd_copyback, (unsigned long) (cmd)) - -void lbs_cmd_async(struct lbs_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size); - -int __lbs_cmd(struct lbs_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *), - unsigned long callback_arg); - -int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, - int8_t p1, int8_t p2); - -int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, - int8_t p2, int usesnr); - -int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0, - int8_t p1, int8_t p2); - -int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1, - int8_t p2, int usesnr); - -int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra, - struct cmd_header *resp); - -int lbs_update_hw_spec(struct lbs_private *priv); - -int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action, - struct cmd_ds_mesh_access *cmd); - -int lbs_set_data_rate(struct lbs_private *priv, u8 rate); - -int lbs_get_channel(struct lbs_private *priv); -int lbs_set_channel(struct lbs_private *priv, u8 channel); - -int lbs_mesh_config_send(struct lbs_private *priv, - struct cmd_ds_mesh_config *cmd, - uint16_t action, uint16_t type); -int lbs_mesh_config(struct lbs_private *priv, uint16_t enable, uint16_t chan); - -int lbs_host_sleep_cfg(struct lbs_private *priv, uint32_t criteria, - struct wol_config *p_wol_config); -int lbs_suspend(struct lbs_private *priv); -void lbs_resume(struct lbs_private *priv); - -int lbs_cmd_802_11_rate_adapt_rateset(struct lbs_private *priv, - uint16_t cmd_action); -int lbs_cmd_802_11_inactivity_timeout(struct lbs_private *priv, - uint16_t cmd_action, uint16_t *timeout); -int lbs_cmd_802_11_sleep_params(struct lbs_private *priv, uint16_t cmd_action, - struct sleep_params *sp); -int lbs_cmd_802_11_set_wep(struct lbs_private *priv, uint16_t cmd_action, - struct assoc_request *assoc); -int lbs_cmd_802_11_enable_rsn(struct lbs_private *priv, uint16_t cmd_action, - uint16_t *enable); -int lbs_cmd_802_11_key_material(struct lbs_private *priv, uint16_t cmd_action, - struct assoc_request *assoc); - -int lbs_get_tx_power(struct lbs_private *priv, s16 *curlevel, s16 *minlevel, - s16 *maxlevel); -int lbs_set_tx_power(struct lbs_private *priv, s16 dbm); - -int lbs_set_radio(struct lbs_private *priv, u8 preamble, u8 radio_on); - -int lbs_set_snmp_mib(struct lbs_private *priv, u32 oid, u16 val); - -int lbs_get_snmp_mib(struct lbs_private *priv, u32 oid, u16 *out_val); - -#endif /* _LBS_CMD_H */ diff --git a/drivers/net/wireless/libertas/cmdresp.c b/drivers/net/wireless/libertas/cmdresp.c deleted file mode 100644 index 23f684337fdd..000000000000 --- a/drivers/net/wireless/libertas/cmdresp.c +++ /dev/null @@ -1,593 +0,0 @@ -/** - * This file contains the handling of command - * responses as well as events generated by firmware. - */ -#include -#include -#include -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "assoc.h" -#include "wext.h" - -/** - * @brief This function handles disconnect event. it - * reports disconnect to upper layer, clean tx/rx packets, - * reset link state etc. - * - * @param priv A pointer to struct lbs_private structure - * @return n/a - */ -void lbs_mac_event_disconnected(struct lbs_private *priv) -{ - union iwreq_data wrqu; - - if (priv->connect_status != LBS_CONNECTED) - return; - - lbs_deb_enter(LBS_DEB_ASSOC); - - memset(wrqu.ap_addr.sa_data, 0x00, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - /* - * Cisco AP sends EAP failure and de-auth in less than 0.5 ms. - * It causes problem in the Supplicant - */ - - msleep_interruptible(1000); - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - /* report disconnect to upper layer */ - netif_stop_queue(priv->dev); - netif_carrier_off(priv->dev); - - /* Free Tx and Rx packets */ - kfree_skb(priv->currenttxskb); - priv->currenttxskb = NULL; - priv->tx_pending_len = 0; - - /* reset SNR/NF/RSSI values */ - memset(priv->SNR, 0x00, sizeof(priv->SNR)); - memset(priv->NF, 0x00, sizeof(priv->NF)); - memset(priv->RSSI, 0x00, sizeof(priv->RSSI)); - memset(priv->rawSNR, 0x00, sizeof(priv->rawSNR)); - memset(priv->rawNF, 0x00, sizeof(priv->rawNF)); - priv->nextSNRNF = 0; - priv->numSNRNF = 0; - priv->connect_status = LBS_DISCONNECTED; - - /* Clear out associated SSID and BSSID since connection is - * no longer valid. - */ - memset(&priv->curbssparams.bssid, 0, ETH_ALEN); - memset(&priv->curbssparams.ssid, 0, IW_ESSID_MAX_SIZE); - priv->curbssparams.ssid_len = 0; - - if (priv->psstate != PS_STATE_FULL_POWER) { - /* make firmware to exit PS mode */ - lbs_deb_cmd("disconnected, so exit PS mode\n"); - lbs_ps_wakeup(priv, 0); - } - lbs_deb_leave(LBS_DEB_ASSOC); -} - -/** - * @brief This function handles MIC failure event. - * - * @param priv A pointer to struct lbs_private structure - * @para event the event id - * @return n/a - */ -static void handle_mic_failureevent(struct lbs_private *priv, u32 event) -{ - char buf[50]; - - lbs_deb_enter(LBS_DEB_CMD); - memset(buf, 0, sizeof(buf)); - - sprintf(buf, "%s", "MLME-MICHAELMICFAILURE.indication "); - - if (event == MACREG_INT_CODE_MIC_ERR_UNICAST) { - strcat(buf, "unicast "); - } else { - strcat(buf, "multicast "); - } - - lbs_send_iwevcustom_event(priv, buf); - lbs_deb_leave(LBS_DEB_CMD); -} - -static int lbs_ret_reg_access(struct lbs_private *priv, - u16 type, struct cmd_ds_command *resp) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - switch (type) { - case CMD_RET(CMD_MAC_REG_ACCESS): - { - struct cmd_ds_mac_reg_access *reg = &resp->params.macreg; - - priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); - priv->offsetvalue.value = le32_to_cpu(reg->value); - break; - } - - case CMD_RET(CMD_BBP_REG_ACCESS): - { - struct cmd_ds_bbp_reg_access *reg = &resp->params.bbpreg; - - priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); - priv->offsetvalue.value = reg->value; - break; - } - - case CMD_RET(CMD_RF_REG_ACCESS): - { - struct cmd_ds_rf_reg_access *reg = &resp->params.rfreg; - - priv->offsetvalue.offset = (u32)le16_to_cpu(reg->offset); - priv->offsetvalue.value = reg->value; - break; - } - - default: - ret = -1; - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} - -static int lbs_ret_802_11_rssi(struct lbs_private *priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_rssi_rsp *rssirsp = &resp->params.rssirsp; - - lbs_deb_enter(LBS_DEB_CMD); - - /* store the non average value */ - priv->SNR[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->SNR); - priv->NF[TYPE_BEACON][TYPE_NOAVG] = get_unaligned_le16(&rssirsp->noisefloor); - - priv->SNR[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgSNR); - priv->NF[TYPE_BEACON][TYPE_AVG] = get_unaligned_le16(&rssirsp->avgnoisefloor); - - priv->RSSI[TYPE_BEACON][TYPE_NOAVG] = - CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], - priv->NF[TYPE_BEACON][TYPE_NOAVG]); - - priv->RSSI[TYPE_BEACON][TYPE_AVG] = - CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_AVG] / AVG_SCALE, - priv->NF[TYPE_BEACON][TYPE_AVG] / AVG_SCALE); - - lbs_deb_cmd("RSSI: beacon %d, avg %d\n", - priv->RSSI[TYPE_BEACON][TYPE_NOAVG], - priv->RSSI[TYPE_BEACON][TYPE_AVG]); - - lbs_deb_leave(LBS_DEB_CMD); - return 0; -} - -static int lbs_ret_802_11_bcn_ctrl(struct lbs_private * priv, - struct cmd_ds_command *resp) -{ - struct cmd_ds_802_11_beacon_control *bcn_ctrl = - &resp->params.bcn_ctrl; - - lbs_deb_enter(LBS_DEB_CMD); - - if (bcn_ctrl->action == CMD_ACT_GET) { - priv->beacon_enable = (u8) le16_to_cpu(bcn_ctrl->beacon_enable); - priv->beacon_period = le16_to_cpu(bcn_ctrl->beacon_period); - } - - lbs_deb_enter(LBS_DEB_CMD); - return 0; -} - -static inline int handle_cmd_response(struct lbs_private *priv, - struct cmd_header *cmd_response) -{ - struct cmd_ds_command *resp = (struct cmd_ds_command *) cmd_response; - int ret = 0; - unsigned long flags; - uint16_t respcmd = le16_to_cpu(resp->command); - - lbs_deb_enter(LBS_DEB_HOST); - - switch (respcmd) { - case CMD_RET(CMD_MAC_REG_ACCESS): - case CMD_RET(CMD_BBP_REG_ACCESS): - case CMD_RET(CMD_RF_REG_ACCESS): - ret = lbs_ret_reg_access(priv, respcmd, resp); - break; - - case CMD_RET(CMD_802_11_SET_AFC): - case CMD_RET(CMD_802_11_GET_AFC): - spin_lock_irqsave(&priv->driver_lock, flags); - memmove((void *)priv->cur_cmd->callback_arg, &resp->params.afc, - sizeof(struct cmd_ds_802_11_afc)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - break; - - case CMD_RET(CMD_802_11_BEACON_STOP): - break; - - case CMD_RET(CMD_802_11_RSSI): - ret = lbs_ret_802_11_rssi(priv, resp); - break; - - case CMD_RET(CMD_802_11D_DOMAIN_INFO): - ret = lbs_ret_802_11d_domain_info(resp); - break; - - case CMD_RET(CMD_802_11_TPC_CFG): - spin_lock_irqsave(&priv->driver_lock, flags); - memmove((void *)priv->cur_cmd->callback_arg, &resp->params.tpccfg, - sizeof(struct cmd_ds_802_11_tpc_cfg)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - case CMD_RET(CMD_802_11_LED_GPIO_CTRL): - spin_lock_irqsave(&priv->driver_lock, flags); - memmove((void *)priv->cur_cmd->callback_arg, &resp->params.ledgpio, - sizeof(struct cmd_ds_802_11_led_ctrl)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - - case CMD_RET(CMD_GET_TSF): - spin_lock_irqsave(&priv->driver_lock, flags); - memcpy((void *)priv->cur_cmd->callback_arg, - &resp->params.gettsf.tsfvalue, sizeof(u64)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - case CMD_RET(CMD_BT_ACCESS): - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->cur_cmd->callback_arg) - memcpy((void *)priv->cur_cmd->callback_arg, - &resp->params.bt.addr1, 2 * ETH_ALEN); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - case CMD_RET(CMD_FWT_ACCESS): - spin_lock_irqsave(&priv->driver_lock, flags); - if (priv->cur_cmd->callback_arg) - memcpy((void *)priv->cur_cmd->callback_arg, &resp->params.fwt, - sizeof(resp->params.fwt)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - break; - case CMD_RET(CMD_802_11_BEACON_CTRL): - ret = lbs_ret_802_11_bcn_ctrl(priv, resp); - break; - - default: - lbs_pr_err("CMD_RESP: unknown cmd response 0x%04x\n", - le16_to_cpu(resp->command)); - break; - } - lbs_deb_leave(LBS_DEB_HOST); - return ret; -} - -int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len) -{ - uint16_t respcmd, curcmd; - struct cmd_header *resp; - int ret = 0; - unsigned long flags; - uint16_t result; - - lbs_deb_enter(LBS_DEB_HOST); - - mutex_lock(&priv->lock); - spin_lock_irqsave(&priv->driver_lock, flags); - - if (!priv->cur_cmd) { - lbs_deb_host("CMD_RESP: cur_cmd is NULL\n"); - ret = -1; - spin_unlock_irqrestore(&priv->driver_lock, flags); - goto done; - } - - resp = (void *)data; - curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); - respcmd = le16_to_cpu(resp->command); - result = le16_to_cpu(resp->result); - - lbs_deb_cmd("CMD_RESP: response 0x%04x, seq %d, size %d\n", - respcmd, le16_to_cpu(resp->seqnum), len); - lbs_deb_hex(LBS_DEB_CMD, "CMD_RESP", (void *) resp, len); - - if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { - lbs_pr_info("Received CMD_RESP with invalid sequence %d (expected %d)\n", - le16_to_cpu(resp->seqnum), le16_to_cpu(priv->cur_cmd->cmdbuf->seqnum)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - if (respcmd != CMD_RET(curcmd) && - respcmd != CMD_RET_802_11_ASSOCIATE && curcmd != CMD_802_11_ASSOCIATE) { - lbs_pr_info("Invalid CMD_RESP %x to command %x!\n", respcmd, curcmd); - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - - if (resp->result == cpu_to_le16(0x0004)) { - /* 0x0004 means -EAGAIN. Drop the response, let it time out - and be resubmitted */ - lbs_pr_info("Firmware returns DEFER to command %x. Will let it time out...\n", - le16_to_cpu(resp->command)); - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - - /* Now we got response from FW, cancel the command timer */ - del_timer(&priv->command_timer); - priv->cmd_timed_out = 0; - if (priv->nr_retries) { - lbs_pr_info("Received result %x to command %x after %d retries\n", - result, curcmd, priv->nr_retries); - priv->nr_retries = 0; - } - - /* Store the response code to cur_cmd_retcode. */ - priv->cur_cmd_retcode = result; - - if (respcmd == CMD_RET(CMD_802_11_PS_MODE)) { - struct cmd_ds_802_11_ps_mode *psmode = (void *) &resp[1]; - u16 action = le16_to_cpu(psmode->action); - - lbs_deb_host( - "CMD_RESP: PS_MODE cmd reply result 0x%x, action 0x%x\n", - result, action); - - if (result) { - lbs_deb_host("CMD_RESP: PS command failed with 0x%x\n", - result); - /* - * We should not re-try enter-ps command in - * ad-hoc mode. It takes place in - * lbs_execute_next_command(). - */ - if (priv->mode == IW_MODE_ADHOC && - action == CMD_SUBCMD_ENTER_PS) - priv->psmode = LBS802_11POWERMODECAM; - } else if (action == CMD_SUBCMD_ENTER_PS) { - priv->needtowakeup = 0; - priv->psstate = PS_STATE_AWAKE; - - lbs_deb_host("CMD_RESP: ENTER_PS command response\n"); - if (priv->connect_status != LBS_CONNECTED) { - /* - * When Deauth Event received before Enter_PS command - * response, We need to wake up the firmware. - */ - lbs_deb_host( - "disconnected, invoking lbs_ps_wakeup\n"); - - spin_unlock_irqrestore(&priv->driver_lock, flags); - mutex_unlock(&priv->lock); - lbs_ps_wakeup(priv, 0); - mutex_lock(&priv->lock); - spin_lock_irqsave(&priv->driver_lock, flags); - } - } else if (action == CMD_SUBCMD_EXIT_PS) { - priv->needtowakeup = 0; - priv->psstate = PS_STATE_FULL_POWER; - lbs_deb_host("CMD_RESP: EXIT_PS command response\n"); - } else { - lbs_deb_host("CMD_RESP: PS action 0x%X\n", action); - } - - lbs_complete_command(priv, priv->cur_cmd, result); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - ret = 0; - goto done; - } - - /* If the command is not successful, cleanup and return failure */ - if ((result != 0 || !(respcmd & 0x8000))) { - lbs_deb_host("CMD_RESP: error 0x%04x in command reply 0x%04x\n", - result, respcmd); - /* - * Handling errors here - */ - switch (respcmd) { - case CMD_RET(CMD_GET_HW_SPEC): - case CMD_RET(CMD_802_11_RESET): - lbs_deb_host("CMD_RESP: reset failed\n"); - break; - - } - lbs_complete_command(priv, priv->cur_cmd, result); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - ret = -1; - goto done; - } - - spin_unlock_irqrestore(&priv->driver_lock, flags); - - if (priv->cur_cmd && priv->cur_cmd->callback) { - ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg, - resp); - } else - ret = handle_cmd_response(priv, resp); - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->cur_cmd) { - /* Clean up and Put current command back to cmdfreeq */ - lbs_complete_command(priv, priv->cur_cmd, result); - } - spin_unlock_irqrestore(&priv->driver_lock, flags); - -done: - mutex_unlock(&priv->lock); - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} - -static int lbs_send_confirmwake(struct lbs_private *priv) -{ - struct cmd_header cmd; - int ret = 0; - - lbs_deb_enter(LBS_DEB_HOST); - - cmd.command = cpu_to_le16(CMD_802_11_WAKEUP_CONFIRM); - cmd.size = cpu_to_le16(sizeof(cmd)); - cmd.seqnum = cpu_to_le16(++priv->seqnum); - cmd.result = 0; - - lbs_deb_hex(LBS_DEB_HOST, "wake confirm", (u8 *) &cmd, - sizeof(cmd)); - - ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) &cmd, sizeof(cmd)); - if (ret) - lbs_pr_alert("SEND_WAKEC_CMD: Host to Card failed for Confirm Wake\n"); - - lbs_deb_leave_args(LBS_DEB_HOST, "ret %d", ret); - return ret; -} - -int lbs_process_event(struct lbs_private *priv, u32 event) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_CMD); - - switch (event) { - case MACREG_INT_CODE_LINK_SENSED: - lbs_deb_cmd("EVENT: link sensed\n"); - break; - - case MACREG_INT_CODE_DEAUTHENTICATED: - lbs_deb_cmd("EVENT: deauthenticated\n"); - lbs_mac_event_disconnected(priv); - break; - - case MACREG_INT_CODE_DISASSOCIATED: - lbs_deb_cmd("EVENT: disassociated\n"); - lbs_mac_event_disconnected(priv); - break; - - case MACREG_INT_CODE_LINK_LOST_NO_SCAN: - lbs_deb_cmd("EVENT: link lost\n"); - lbs_mac_event_disconnected(priv); - break; - - case MACREG_INT_CODE_PS_SLEEP: - lbs_deb_cmd("EVENT: ps sleep\n"); - - /* handle unexpected PS SLEEP event */ - if (priv->psstate == PS_STATE_FULL_POWER) { - lbs_deb_cmd( - "EVENT: in FULL POWER mode, ignoreing PS_SLEEP\n"); - break; - } - priv->psstate = PS_STATE_PRE_SLEEP; - - lbs_ps_confirm_sleep(priv); - - break; - - case MACREG_INT_CODE_HOST_AWAKE: - lbs_deb_cmd("EVENT: host awake\n"); - lbs_send_confirmwake(priv); - break; - - case MACREG_INT_CODE_PS_AWAKE: - lbs_deb_cmd("EVENT: ps awake\n"); - /* handle unexpected PS AWAKE event */ - if (priv->psstate == PS_STATE_FULL_POWER) { - lbs_deb_cmd( - "EVENT: In FULL POWER mode - ignore PS AWAKE\n"); - break; - } - - priv->psstate = PS_STATE_AWAKE; - - if (priv->needtowakeup) { - /* - * wait for the command processing to finish - * before resuming sending - * priv->needtowakeup will be set to FALSE - * in lbs_ps_wakeup() - */ - lbs_deb_cmd("waking up ...\n"); - lbs_ps_wakeup(priv, 0); - } - break; - - case MACREG_INT_CODE_MIC_ERR_UNICAST: - lbs_deb_cmd("EVENT: UNICAST MIC ERROR\n"); - handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_UNICAST); - break; - - case MACREG_INT_CODE_MIC_ERR_MULTICAST: - lbs_deb_cmd("EVENT: MULTICAST MIC ERROR\n"); - handle_mic_failureevent(priv, MACREG_INT_CODE_MIC_ERR_MULTICAST); - break; - - case MACREG_INT_CODE_MIB_CHANGED: - lbs_deb_cmd("EVENT: MIB CHANGED\n"); - break; - case MACREG_INT_CODE_INIT_DONE: - lbs_deb_cmd("EVENT: INIT DONE\n"); - break; - case MACREG_INT_CODE_ADHOC_BCN_LOST: - lbs_deb_cmd("EVENT: ADHOC beacon lost\n"); - break; - case MACREG_INT_CODE_RSSI_LOW: - lbs_pr_alert("EVENT: rssi low\n"); - break; - case MACREG_INT_CODE_SNR_LOW: - lbs_pr_alert("EVENT: snr low\n"); - break; - case MACREG_INT_CODE_MAX_FAIL: - lbs_pr_alert("EVENT: max fail\n"); - break; - case MACREG_INT_CODE_RSSI_HIGH: - lbs_pr_alert("EVENT: rssi high\n"); - break; - case MACREG_INT_CODE_SNR_HIGH: - lbs_pr_alert("EVENT: snr high\n"); - break; - - case MACREG_INT_CODE_MESH_AUTO_STARTED: - /* Ignore spurious autostart events if autostart is disabled */ - if (!priv->mesh_autostart_enabled) { - lbs_pr_info("EVENT: MESH_AUTO_STARTED (ignoring)\n"); - break; - } - lbs_pr_info("EVENT: MESH_AUTO_STARTED\n"); - priv->mesh_connect_status = LBS_CONNECTED; - if (priv->mesh_open) { - netif_carrier_on(priv->mesh_dev); - if (!priv->tx_pending_len) - netif_wake_queue(priv->mesh_dev); - } - priv->mode = IW_MODE_ADHOC; - schedule_work(&priv->sync_channel); - break; - - default: - lbs_pr_alert("EVENT: unknown event id %d\n", event); - break; - } - - lbs_deb_leave_args(LBS_DEB_CMD, "ret %d", ret); - return ret; -} diff --git a/drivers/net/wireless/libertas/debugfs.c b/drivers/net/wireless/libertas/debugfs.c deleted file mode 100644 index 893a55ca344a..000000000000 --- a/drivers/net/wireless/libertas/debugfs.c +++ /dev/null @@ -1,997 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -#include "dev.h" -#include "decl.h" -#include "host.h" -#include "debugfs.h" -#include "cmd.h" - -static struct dentry *lbs_dir; -static char *szStates[] = { - "Connected", - "Disconnected" -}; - -#ifdef PROC_DEBUG -static void lbs_debug_init(struct lbs_private *priv); -#endif - -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t write_file_dummy(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return -EINVAL; -} - -static const size_t len = PAGE_SIZE; - -static ssize_t lbs_dev_info(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - size_t pos = 0; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - ssize_t res; - if (!buf) - return -ENOMEM; - - pos += snprintf(buf+pos, len-pos, "state = %s\n", - szStates[priv->connect_status]); - pos += snprintf(buf+pos, len-pos, "region_code = %02x\n", - (u32) priv->regioncode); - - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - - free_page(addr); - return res; -} - - -static ssize_t lbs_getscantable(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - size_t pos = 0; - int numscansdone = 0, res; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - DECLARE_SSID_BUF(ssid); - struct bss_descriptor * iter_bss; - if (!buf) - return -ENOMEM; - - pos += snprintf(buf+pos, len-pos, - "# | ch | rssi | bssid | cap | Qual | SSID \n"); - - mutex_lock(&priv->lock); - list_for_each_entry (iter_bss, &priv->network_list, list) { - u16 ibss = (iter_bss->capability & WLAN_CAPABILITY_IBSS); - u16 privacy = (iter_bss->capability & WLAN_CAPABILITY_PRIVACY); - u16 spectrum_mgmt = (iter_bss->capability & WLAN_CAPABILITY_SPECTRUM_MGMT); - - pos += snprintf(buf+pos, len-pos, "%02u| %03d | %04d | %pM |", - numscansdone, iter_bss->channel, iter_bss->rssi, - iter_bss->bssid); - pos += snprintf(buf+pos, len-pos, " %04x-", iter_bss->capability); - pos += snprintf(buf+pos, len-pos, "%c%c%c |", - ibss ? 'A' : 'I', privacy ? 'P' : ' ', - spectrum_mgmt ? 'S' : ' '); - pos += snprintf(buf+pos, len-pos, " %04d |", SCAN_RSSI(iter_bss->rssi)); - pos += snprintf(buf+pos, len-pos, " %s\n", - print_ssid(ssid, iter_bss->ssid, - iter_bss->ssid_len)); - - numscansdone++; - } - mutex_unlock(&priv->lock); - - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - - free_page(addr); - return res; -} - -static ssize_t lbs_sleepparams_write(struct file *file, - const char __user *user_buf, size_t count, - loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t buf_size, ret; - struct sleep_params sp; - int p1, p2, p3, p4, p5, p6; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, user_buf, buf_size)) { - ret = -EFAULT; - goto out_unlock; - } - ret = sscanf(buf, "%d %d %d %d %d %d", &p1, &p2, &p3, &p4, &p5, &p6); - if (ret != 6) { - ret = -EINVAL; - goto out_unlock; - } - sp.sp_error = p1; - sp.sp_offset = p2; - sp.sp_stabletime = p3; - sp.sp_calcontrol = p4; - sp.sp_extsleepclk = p5; - sp.sp_reserved = p6; - - ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_SET, &sp); - if (!ret) - ret = count; - else if (ret > 0) - ret = -EINVAL; - -out_unlock: - free_page(addr); - return ret; -} - -static ssize_t lbs_sleepparams_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t ret; - size_t pos = 0; - struct sleep_params sp; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - ret = lbs_cmd_802_11_sleep_params(priv, CMD_ACT_GET, &sp); - if (ret) - goto out_unlock; - - pos += snprintf(buf, len, "%d %d %d %d %d %d\n", sp.sp_error, - sp.sp_offset, sp.sp_stabletime, - sp.sp_calcontrol, sp.sp_extsleepclk, - sp.sp_reserved); - - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - -out_unlock: - free_page(addr); - return ret; -} - -/* - * When calling CMD_802_11_SUBSCRIBE_EVENT with CMD_ACT_GET, me might - * get a bunch of vendor-specific TLVs (a.k.a. IEs) back from the - * firmware. Here's an example: - * 04 01 02 00 00 00 05 01 02 00 00 00 06 01 02 00 - * 00 00 07 01 02 00 3c 00 00 00 00 00 00 00 03 03 - * 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - * - * The 04 01 is the TLV type (here TLV_TYPE_RSSI_LOW), 02 00 is the length, - * 00 00 are the data bytes of this TLV. For this TLV, their meaning is - * defined in mrvlietypes_thresholds - * - * This function searches in this TLV data chunk for a given TLV type - * and returns a pointer to the first data byte of the TLV, or to NULL - * if the TLV hasn't been found. - */ -static void *lbs_tlv_find(uint16_t tlv_type, const uint8_t *tlv, uint16_t size) -{ - struct mrvl_ie_header *tlv_h; - uint16_t length; - ssize_t pos = 0; - - while (pos < size) { - tlv_h = (struct mrvl_ie_header *) tlv; - if (!tlv_h->len) - return NULL; - if (tlv_h->type == cpu_to_le16(tlv_type)) - return tlv_h; - length = le16_to_cpu(tlv_h->len) + sizeof(*tlv_h); - pos += length; - tlv += length; - } - return NULL; -} - - -static ssize_t lbs_threshold_read(uint16_t tlv_type, uint16_t event_mask, - struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct cmd_ds_802_11_subscribe_event *subscribed; - struct mrvl_ie_thresholds *got; - struct lbs_private *priv = file->private_data; - ssize_t ret = 0; - size_t pos = 0; - char *buf; - u8 value; - u8 freq; - int events = 0; - - buf = (char *)get_zeroed_page(GFP_KERNEL); - if (!buf) - return -ENOMEM; - - subscribed = kzalloc(sizeof(*subscribed), GFP_KERNEL); - if (!subscribed) { - ret = -ENOMEM; - goto out_page; - } - - subscribed->hdr.size = cpu_to_le16(sizeof(*subscribed)); - subscribed->action = cpu_to_le16(CMD_ACT_GET); - - ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, subscribed); - if (ret) - goto out_cmd; - - got = lbs_tlv_find(tlv_type, subscribed->tlv, sizeof(subscribed->tlv)); - if (got) { - value = got->value; - freq = got->freq; - events = le16_to_cpu(subscribed->events); - - pos += snprintf(buf, len, "%d %d %d\n", value, freq, - !!(events & event_mask)); - } - - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - - out_cmd: - kfree(subscribed); - - out_page: - free_page((unsigned long)buf); - return ret; -} - - -static ssize_t lbs_threshold_write(uint16_t tlv_type, uint16_t event_mask, - struct file *file, - const char __user *userbuf, size_t count, - loff_t *ppos) -{ - struct cmd_ds_802_11_subscribe_event *events; - struct mrvl_ie_thresholds *tlv; - struct lbs_private *priv = file->private_data; - ssize_t buf_size; - int value, freq, new_mask; - uint16_t curr_mask; - char *buf; - int ret; - - buf = (char *)get_zeroed_page(GFP_KERNEL); - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - ret = -EFAULT; - goto out_page; - } - ret = sscanf(buf, "%d %d %d", &value, &freq, &new_mask); - if (ret != 3) { - ret = -EINVAL; - goto out_page; - } - events = kzalloc(sizeof(*events), GFP_KERNEL); - if (!events) { - ret = -ENOMEM; - goto out_page; - } - - events->hdr.size = cpu_to_le16(sizeof(*events)); - events->action = cpu_to_le16(CMD_ACT_GET); - - ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); - if (ret) - goto out_events; - - curr_mask = le16_to_cpu(events->events); - - if (new_mask) - new_mask = curr_mask | event_mask; - else - new_mask = curr_mask & ~event_mask; - - /* Now everything is set and we can send stuff down to the firmware */ - - tlv = (void *)events->tlv; - - events->action = cpu_to_le16(CMD_ACT_SET); - events->events = cpu_to_le16(new_mask); - tlv->header.type = cpu_to_le16(tlv_type); - tlv->header.len = cpu_to_le16(sizeof(*tlv) - sizeof(tlv->header)); - tlv->value = value; - if (tlv_type != TLV_TYPE_BCNMISS) - tlv->freq = freq; - - /* The command header, the action, the event mask, and one TLV */ - events->hdr.size = cpu_to_le16(sizeof(events->hdr) + 4 + sizeof(*tlv)); - - ret = lbs_cmd_with_response(priv, CMD_802_11_SUBSCRIBE_EVENT, events); - - if (!ret) - ret = count; - out_events: - kfree(events); - out_page: - free_page((unsigned long)buf); - return ret; -} - - -static ssize_t lbs_lowrssi_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_read(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_lowrssi_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_write(TLV_TYPE_RSSI_LOW, CMD_SUBSCRIBE_RSSI_LOW, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_lowsnr_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_read(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_lowsnr_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_write(TLV_TYPE_SNR_LOW, CMD_SUBSCRIBE_SNR_LOW, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_failcount_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_read(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_failcount_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_write(TLV_TYPE_FAILCOUNT, CMD_SUBSCRIBE_FAILCOUNT, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_highrssi_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_read(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_highrssi_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_write(TLV_TYPE_RSSI_HIGH, CMD_SUBSCRIBE_RSSI_HIGH, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_highsnr_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_read(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_highsnr_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_write(TLV_TYPE_SNR_HIGH, CMD_SUBSCRIBE_SNR_HIGH, - file, userbuf, count, ppos); -} - -static ssize_t lbs_bcnmiss_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_read(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS, - file, userbuf, count, ppos); -} - - -static ssize_t lbs_bcnmiss_write(struct file *file, const char __user *userbuf, - size_t count, loff_t *ppos) -{ - return lbs_threshold_write(TLV_TYPE_BCNMISS, CMD_SUBSCRIBE_BCNMISS, - file, userbuf, count, ppos); -} - - - -static ssize_t lbs_rdmac_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - struct lbs_offset_value offval; - ssize_t pos = 0; - int ret; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - offval.offset = priv->mac_offset; - offval.value = 0; - - ret = lbs_prepare_and_send_command(priv, - CMD_MAC_REG_ACCESS, 0, - CMD_OPTION_WAITFORRSP, 0, &offval); - mdelay(10); - pos += snprintf(buf+pos, len-pos, "MAC[0x%x] = 0x%08x\n", - priv->mac_offset, priv->offsetvalue.value); - - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - free_page(addr); - return ret; -} - -static ssize_t lbs_rdmac_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - priv->mac_offset = simple_strtoul((char *)buf, NULL, 16); - res = count; -out_unlock: - free_page(addr); - return res; -} - -static ssize_t lbs_wrmac_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - u32 offset, value; - struct lbs_offset_value offval; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - res = sscanf(buf, "%x %x", &offset, &value); - if (res != 2) { - res = -EFAULT; - goto out_unlock; - } - - offval.offset = offset; - offval.value = value; - res = lbs_prepare_and_send_command(priv, - CMD_MAC_REG_ACCESS, 1, - CMD_OPTION_WAITFORRSP, 0, &offval); - mdelay(10); - - res = count; -out_unlock: - free_page(addr); - return res; -} - -static ssize_t lbs_rdbbp_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - struct lbs_offset_value offval; - ssize_t pos = 0; - int ret; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - offval.offset = priv->bbp_offset; - offval.value = 0; - - ret = lbs_prepare_and_send_command(priv, - CMD_BBP_REG_ACCESS, 0, - CMD_OPTION_WAITFORRSP, 0, &offval); - mdelay(10); - pos += snprintf(buf+pos, len-pos, "BBP[0x%x] = 0x%08x\n", - priv->bbp_offset, priv->offsetvalue.value); - - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - free_page(addr); - - return ret; -} - -static ssize_t lbs_rdbbp_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - priv->bbp_offset = simple_strtoul((char *)buf, NULL, 16); - res = count; -out_unlock: - free_page(addr); - return res; -} - -static ssize_t lbs_wrbbp_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - u32 offset, value; - struct lbs_offset_value offval; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - res = sscanf(buf, "%x %x", &offset, &value); - if (res != 2) { - res = -EFAULT; - goto out_unlock; - } - - offval.offset = offset; - offval.value = value; - res = lbs_prepare_and_send_command(priv, - CMD_BBP_REG_ACCESS, 1, - CMD_OPTION_WAITFORRSP, 0, &offval); - mdelay(10); - - res = count; -out_unlock: - free_page(addr); - return res; -} - -static ssize_t lbs_rdrf_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - struct lbs_offset_value offval; - ssize_t pos = 0; - int ret; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - offval.offset = priv->rf_offset; - offval.value = 0; - - ret = lbs_prepare_and_send_command(priv, - CMD_RF_REG_ACCESS, 0, - CMD_OPTION_WAITFORRSP, 0, &offval); - mdelay(10); - pos += snprintf(buf+pos, len-pos, "RF[0x%x] = 0x%08x\n", - priv->rf_offset, priv->offsetvalue.value); - - ret = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - free_page(addr); - - return ret; -} - -static ssize_t lbs_rdrf_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - priv->rf_offset = simple_strtoul(buf, NULL, 16); - res = count; -out_unlock: - free_page(addr); - return res; -} - -static ssize_t lbs_wrrf_write(struct file *file, - const char __user *userbuf, - size_t count, loff_t *ppos) -{ - - struct lbs_private *priv = file->private_data; - ssize_t res, buf_size; - u32 offset, value; - struct lbs_offset_value offval; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - buf_size = min(count, len - 1); - if (copy_from_user(buf, userbuf, buf_size)) { - res = -EFAULT; - goto out_unlock; - } - res = sscanf(buf, "%x %x", &offset, &value); - if (res != 2) { - res = -EFAULT; - goto out_unlock; - } - - offval.offset = offset; - offval.value = value; - res = lbs_prepare_and_send_command(priv, - CMD_RF_REG_ACCESS, 1, - CMD_OPTION_WAITFORRSP, 0, &offval); - mdelay(10); - - res = count; -out_unlock: - free_page(addr); - return res; -} - -#define FOPS(fread, fwrite) { \ - .owner = THIS_MODULE, \ - .open = open_file_generic, \ - .read = (fread), \ - .write = (fwrite), \ -} - -struct lbs_debugfs_files { - const char *name; - int perm; - struct file_operations fops; -}; - -static const struct lbs_debugfs_files debugfs_files[] = { - { "info", 0444, FOPS(lbs_dev_info, write_file_dummy), }, - { "getscantable", 0444, FOPS(lbs_getscantable, - write_file_dummy), }, - { "sleepparams", 0644, FOPS(lbs_sleepparams_read, - lbs_sleepparams_write), }, -}; - -static const struct lbs_debugfs_files debugfs_events_files[] = { - {"low_rssi", 0644, FOPS(lbs_lowrssi_read, - lbs_lowrssi_write), }, - {"low_snr", 0644, FOPS(lbs_lowsnr_read, - lbs_lowsnr_write), }, - {"failure_count", 0644, FOPS(lbs_failcount_read, - lbs_failcount_write), }, - {"beacon_missed", 0644, FOPS(lbs_bcnmiss_read, - lbs_bcnmiss_write), }, - {"high_rssi", 0644, FOPS(lbs_highrssi_read, - lbs_highrssi_write), }, - {"high_snr", 0644, FOPS(lbs_highsnr_read, - lbs_highsnr_write), }, -}; - -static const struct lbs_debugfs_files debugfs_regs_files[] = { - {"rdmac", 0644, FOPS(lbs_rdmac_read, lbs_rdmac_write), }, - {"wrmac", 0600, FOPS(NULL, lbs_wrmac_write), }, - {"rdbbp", 0644, FOPS(lbs_rdbbp_read, lbs_rdbbp_write), }, - {"wrbbp", 0600, FOPS(NULL, lbs_wrbbp_write), }, - {"rdrf", 0644, FOPS(lbs_rdrf_read, lbs_rdrf_write), }, - {"wrrf", 0600, FOPS(NULL, lbs_wrrf_write), }, -}; - -void lbs_debugfs_init(void) -{ - if (!lbs_dir) - lbs_dir = debugfs_create_dir("lbs_wireless", NULL); - - return; -} - -void lbs_debugfs_remove(void) -{ - if (lbs_dir) - debugfs_remove(lbs_dir); - return; -} - -void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev) -{ - int i; - const struct lbs_debugfs_files *files; - if (!lbs_dir) - goto exit; - - priv->debugfs_dir = debugfs_create_dir(dev->name, lbs_dir); - if (!priv->debugfs_dir) - goto exit; - - for (i=0; idebugfs_files[i] = debugfs_create_file(files->name, - files->perm, - priv->debugfs_dir, - priv, - &files->fops); - } - - priv->events_dir = debugfs_create_dir("subscribed_events", priv->debugfs_dir); - if (!priv->events_dir) - goto exit; - - for (i=0; idebugfs_events_files[i] = debugfs_create_file(files->name, - files->perm, - priv->events_dir, - priv, - &files->fops); - } - - priv->regs_dir = debugfs_create_dir("registers", priv->debugfs_dir); - if (!priv->regs_dir) - goto exit; - - for (i=0; idebugfs_regs_files[i] = debugfs_create_file(files->name, - files->perm, - priv->regs_dir, - priv, - &files->fops); - } - -#ifdef PROC_DEBUG - lbs_debug_init(priv); -#endif -exit: - return; -} - -void lbs_debugfs_remove_one(struct lbs_private *priv) -{ - int i; - - for(i=0; idebugfs_regs_files[i]); - - debugfs_remove(priv->regs_dir); - - for(i=0; idebugfs_events_files[i]); - - debugfs_remove(priv->events_dir); -#ifdef PROC_DEBUG - debugfs_remove(priv->debugfs_debug); -#endif - for(i=0; idebugfs_files[i]); - debugfs_remove(priv->debugfs_dir); -} - - - -/* debug entry */ - -#ifdef PROC_DEBUG - -#define item_size(n) (FIELD_SIZEOF(struct lbs_private, n)) -#define item_addr(n) (offsetof(struct lbs_private, n)) - - -struct debug_data { - char name[32]; - u32 size; - size_t addr; -}; - -/* To debug any member of struct lbs_private, simply add one line here. - */ -static struct debug_data items[] = { - {"psmode", item_size(psmode), item_addr(psmode)}, - {"psstate", item_size(psstate), item_addr(psstate)}, -}; - -static int num_of_items = ARRAY_SIZE(items); - -/** - * @brief proc read function - * - * @param page pointer to buffer - * @param s read data starting position - * @param off offset - * @param cnt counter - * @param eof end of file flag - * @param data data to output - * @return number of output data - */ -static ssize_t lbs_debugfs_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - int val = 0; - size_t pos = 0; - ssize_t res; - char *p; - int i; - struct debug_data *d; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - if (!buf) - return -ENOMEM; - - p = buf; - - d = (struct debug_data *)file->private_data; - - for (i = 0; i < num_of_items; i++) { - if (d[i].size == 1) - val = *((u8 *) d[i].addr); - else if (d[i].size == 2) - val = *((u16 *) d[i].addr); - else if (d[i].size == 4) - val = *((u32 *) d[i].addr); - else if (d[i].size == 8) - val = *((u64 *) d[i].addr); - - pos += sprintf(p + pos, "%s=%d\n", d[i].name, val); - } - - res = simple_read_from_buffer(userbuf, count, ppos, p, pos); - - free_page(addr); - return res; -} - -/** - * @brief proc write function - * - * @param f file pointer - * @param buf pointer to data buffer - * @param cnt data number to write - * @param data data to write - * @return number of data - */ -static ssize_t lbs_debugfs_write(struct file *f, const char __user *buf, - size_t cnt, loff_t *ppos) -{ - int r, i; - char *pdata; - char *p; - char *p0; - char *p1; - char *p2; - struct debug_data *d = (struct debug_data *)f->private_data; - - pdata = kmalloc(cnt, GFP_KERNEL); - if (pdata == NULL) - return 0; - - if (copy_from_user(pdata, buf, cnt)) { - lbs_deb_debugfs("Copy from user failed\n"); - kfree(pdata); - return 0; - } - - p0 = pdata; - for (i = 0; i < num_of_items; i++) { - do { - p = strstr(p0, d[i].name); - if (p == NULL) - break; - p1 = strchr(p, '\n'); - if (p1 == NULL) - break; - p0 = p1++; - p2 = strchr(p, '='); - if (!p2) - break; - p2++; - r = simple_strtoul(p2, NULL, 0); - if (d[i].size == 1) - *((u8 *) d[i].addr) = (u8) r; - else if (d[i].size == 2) - *((u16 *) d[i].addr) = (u16) r; - else if (d[i].size == 4) - *((u32 *) d[i].addr) = (u32) r; - else if (d[i].size == 8) - *((u64 *) d[i].addr) = (u64) r; - break; - } while (1); - } - kfree(pdata); - - return (ssize_t)cnt; -} - -static const struct file_operations lbs_debug_fops = { - .owner = THIS_MODULE, - .open = open_file_generic, - .write = lbs_debugfs_write, - .read = lbs_debugfs_read, -}; - -/** - * @brief create debug proc file - * - * @param priv pointer struct lbs_private - * @param dev pointer net_device - * @return N/A - */ -static void lbs_debug_init(struct lbs_private *priv) -{ - int i; - - if (!priv->debugfs_dir) - return; - - for (i = 0; i < num_of_items; i++) - items[i].addr += (size_t) priv; - - priv->debugfs_debug = debugfs_create_file("debug", 0644, - priv->debugfs_dir, &items[0], - &lbs_debug_fops); -} -#endif diff --git a/drivers/net/wireless/libertas/debugfs.h b/drivers/net/wireless/libertas/debugfs.h deleted file mode 100644 index f2b9c7ffe0fd..000000000000 --- a/drivers/net/wireless/libertas/debugfs.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _LBS_DEBUGFS_H_ -#define _LBS_DEBUGFS_H_ - -void lbs_debugfs_init(void); -void lbs_debugfs_remove(void); - -void lbs_debugfs_init_one(struct lbs_private *priv, struct net_device *dev); -void lbs_debugfs_remove_one(struct lbs_private *priv); - -#endif diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h deleted file mode 100644 index 8b15380ae6e1..000000000000 --- a/drivers/net/wireless/libertas/decl.h +++ /dev/null @@ -1,78 +0,0 @@ -/** - * This file contains declaration referring to - * functions defined in other source files - */ - -#ifndef _LBS_DECL_H_ -#define _LBS_DECL_H_ - -#include - -#include "defs.h" - -/** Function Prototype Declaration */ -struct lbs_private; -struct sk_buff; -struct net_device; -struct cmd_ctrl_node; -struct cmd_ds_command; - -void lbs_set_mac_control(struct lbs_private *priv); - -void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count); - -int lbs_free_cmd_buffer(struct lbs_private *priv); - -int lbs_prepare_and_send_command(struct lbs_private *priv, - u16 cmd_no, - u16 cmd_action, - u16 wait_option, u32 cmd_oid, void *pdata_buf); - -int lbs_allocate_cmd_buffer(struct lbs_private *priv); -int lbs_execute_next_command(struct lbs_private *priv); -int lbs_process_event(struct lbs_private *priv, u32 event); -void lbs_queue_event(struct lbs_private *priv, u32 event); -void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx); - -u32 lbs_fw_index_to_data_rate(u8 index); -u8 lbs_data_rate_to_fw_index(u32 rate); - -/** The proc fs interface */ -int lbs_process_command_response(struct lbs_private *priv, u8 *data, u32 len); -void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, - int result); -netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev); -int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band); - -int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); - -void lbs_ps_sleep(struct lbs_private *priv, int wait_option); -void lbs_ps_confirm_sleep(struct lbs_private *priv); -void lbs_ps_wakeup(struct lbs_private *priv, int wait_option); - -struct chan_freq_power *lbs_find_cfp_by_band_and_channel( - struct lbs_private *priv, - u8 band, - u16 channel); - -void lbs_mac_event_disconnected(struct lbs_private *priv); - -void lbs_send_iwevcustom_event(struct lbs_private *priv, s8 *str); - -/* persistcfg.c */ -void lbs_persist_config_init(struct net_device *net); -void lbs_persist_config_remove(struct net_device *net); - -/* main.c */ -struct chan_freq_power *lbs_get_region_cfp_table(u8 region, - int *cfp_no); -struct lbs_private *lbs_add_card(void *card, struct device *dmdev); -void lbs_remove_card(struct lbs_private *priv); -int lbs_start_card(struct lbs_private *priv); -void lbs_stop_card(struct lbs_private *priv); -void lbs_host_to_card_done(struct lbs_private *priv); - -int lbs_update_channel(struct lbs_private *priv); - -#endif diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h deleted file mode 100644 index 72f3479a4d70..000000000000 --- a/drivers/net/wireless/libertas/defs.h +++ /dev/null @@ -1,419 +0,0 @@ -/** - * This header file contains global constant/enum definitions, - * global variable declaration. - */ -#ifndef _LBS_DEFS_H_ -#define _LBS_DEFS_H_ - -#include - -#ifdef CONFIG_LIBERTAS_DEBUG -#define DEBUG -#define PROC_DEBUG -#endif - -#ifndef DRV_NAME -#define DRV_NAME "libertas" -#endif - - -#define LBS_DEB_ENTER 0x00000001 -#define LBS_DEB_LEAVE 0x00000002 -#define LBS_DEB_MAIN 0x00000004 -#define LBS_DEB_NET 0x00000008 -#define LBS_DEB_MESH 0x00000010 -#define LBS_DEB_WEXT 0x00000020 -#define LBS_DEB_IOCTL 0x00000040 -#define LBS_DEB_SCAN 0x00000080 -#define LBS_DEB_ASSOC 0x00000100 -#define LBS_DEB_JOIN 0x00000200 -#define LBS_DEB_11D 0x00000400 -#define LBS_DEB_DEBUGFS 0x00000800 -#define LBS_DEB_ETHTOOL 0x00001000 -#define LBS_DEB_HOST 0x00002000 -#define LBS_DEB_CMD 0x00004000 -#define LBS_DEB_RX 0x00008000 -#define LBS_DEB_TX 0x00010000 -#define LBS_DEB_USB 0x00020000 -#define LBS_DEB_CS 0x00040000 -#define LBS_DEB_FW 0x00080000 -#define LBS_DEB_THREAD 0x00100000 -#define LBS_DEB_HEX 0x00200000 -#define LBS_DEB_SDIO 0x00400000 -#define LBS_DEB_SYSFS 0x00800000 -#define LBS_DEB_SPI 0x01000000 - -extern unsigned int lbs_debug; - -#ifdef DEBUG -#define LBS_DEB_LL(grp, grpnam, fmt, args...) \ -do { if ((lbs_debug & (grp)) == (grp)) \ - printk(KERN_DEBUG DRV_NAME grpnam "%s: " fmt, \ - in_interrupt() ? " (INT)" : "", ## args); } while (0) -#else -#define LBS_DEB_LL(grp, grpnam, fmt, args...) do {} while (0) -#endif - -#define lbs_deb_enter(grp) \ - LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s()\n", __func__); -#define lbs_deb_enter_args(grp, fmt, args...) \ - LBS_DEB_LL(grp | LBS_DEB_ENTER, " enter", "%s(" fmt ")\n", __func__, ## args); -#define lbs_deb_leave(grp) \ - LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s()\n", __func__); -#define lbs_deb_leave_args(grp, fmt, args...) \ - LBS_DEB_LL(grp | LBS_DEB_LEAVE, " leave", "%s(), " fmt "\n", \ - __func__, ##args); -#define lbs_deb_main(fmt, args...) LBS_DEB_LL(LBS_DEB_MAIN, " main", fmt, ##args) -#define lbs_deb_net(fmt, args...) LBS_DEB_LL(LBS_DEB_NET, " net", fmt, ##args) -#define lbs_deb_mesh(fmt, args...) LBS_DEB_LL(LBS_DEB_MESH, " mesh", fmt, ##args) -#define lbs_deb_wext(fmt, args...) LBS_DEB_LL(LBS_DEB_WEXT, " wext", fmt, ##args) -#define lbs_deb_ioctl(fmt, args...) LBS_DEB_LL(LBS_DEB_IOCTL, " ioctl", fmt, ##args) -#define lbs_deb_scan(fmt, args...) LBS_DEB_LL(LBS_DEB_SCAN, " scan", fmt, ##args) -#define lbs_deb_assoc(fmt, args...) LBS_DEB_LL(LBS_DEB_ASSOC, " assoc", fmt, ##args) -#define lbs_deb_join(fmt, args...) LBS_DEB_LL(LBS_DEB_JOIN, " join", fmt, ##args) -#define lbs_deb_11d(fmt, args...) LBS_DEB_LL(LBS_DEB_11D, " 11d", fmt, ##args) -#define lbs_deb_debugfs(fmt, args...) LBS_DEB_LL(LBS_DEB_DEBUGFS, " debugfs", fmt, ##args) -#define lbs_deb_ethtool(fmt, args...) LBS_DEB_LL(LBS_DEB_ETHTOOL, " ethtool", fmt, ##args) -#define lbs_deb_host(fmt, args...) LBS_DEB_LL(LBS_DEB_HOST, " host", fmt, ##args) -#define lbs_deb_cmd(fmt, args...) LBS_DEB_LL(LBS_DEB_CMD, " cmd", fmt, ##args) -#define lbs_deb_rx(fmt, args...) LBS_DEB_LL(LBS_DEB_RX, " rx", fmt, ##args) -#define lbs_deb_tx(fmt, args...) LBS_DEB_LL(LBS_DEB_TX, " tx", fmt, ##args) -#define lbs_deb_fw(fmt, args...) LBS_DEB_LL(LBS_DEB_FW, " fw", fmt, ##args) -#define lbs_deb_usb(fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usb", fmt, ##args) -#define lbs_deb_usbd(dev, fmt, args...) LBS_DEB_LL(LBS_DEB_USB, " usbd", "%s:" fmt, dev_name(dev), ##args) -#define lbs_deb_cs(fmt, args...) LBS_DEB_LL(LBS_DEB_CS, " cs", fmt, ##args) -#define lbs_deb_thread(fmt, args...) LBS_DEB_LL(LBS_DEB_THREAD, " thread", fmt, ##args) -#define lbs_deb_sdio(fmt, args...) LBS_DEB_LL(LBS_DEB_SDIO, " sdio", fmt, ##args) -#define lbs_deb_sysfs(fmt, args...) LBS_DEB_LL(LBS_DEB_SYSFS, " sysfs", fmt, ##args) -#define lbs_deb_spi(fmt, args...) LBS_DEB_LL(LBS_DEB_SPI, " spi", fmt, ##args) - -#define lbs_pr_info(format, args...) \ - printk(KERN_INFO DRV_NAME": " format, ## args) -#define lbs_pr_err(format, args...) \ - printk(KERN_ERR DRV_NAME": " format, ## args) -#define lbs_pr_alert(format, args...) \ - printk(KERN_ALERT DRV_NAME": " format, ## args) - -#ifdef DEBUG -static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len) -{ - int i = 0; - - if (len && - (lbs_debug & LBS_DEB_HEX) && - (lbs_debug & grp)) - { - for (i = 1; i <= len; i++) { - if ((i & 0xf) == 1) { - if (i != 1) - printk("\n"); - printk(DRV_NAME " %s: ", prompt); - } - printk("%02x ", (u8) * buf); - buf++; - } - printk("\n"); - } -} -#else -#define lbs_deb_hex(grp,prompt,buf,len) do {} while (0) -#endif - - - -/** Buffer Constants */ - -/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical -* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas -* driver has more local TxPDs. Each TxPD on the host memory is associated -* with a Tx control node. The driver maintains 8 RxPD descriptors for -* station firmware to store Rx packet information. -* -* Current version of MAC has a 32x6 multicast address buffer. -* -* 802.11b can have up to 14 channels, the driver keeps the -* BSSID(MAC address) of each APs or Ad hoc stations it has sensed. -*/ - -#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 -#define LBS_NUM_CMD_BUFFERS 10 -#define LBS_CMD_BUFFER_SIZE (2 * 1024) -#define MRVDRV_MAX_CHANNEL_SIZE 14 -#define MRVDRV_ASSOCIATION_TIME_OUT 255 -#define MRVDRV_SNAP_HEADER_LEN 8 - -#define LBS_UPLD_SIZE 2312 -#define DEV_NAME_LEN 32 - -/* Wake criteria for HOST_SLEEP_CFG command */ -#define EHS_WAKE_ON_BROADCAST_DATA 0x0001 -#define EHS_WAKE_ON_UNICAST_DATA 0x0002 -#define EHS_WAKE_ON_MAC_EVENT 0x0004 -#define EHS_WAKE_ON_MULTICAST_DATA 0x0008 -#define EHS_REMOVE_WAKEUP 0xFFFFFFFF -/* Wake rules for Host_Sleep_CFG command */ -#define WOL_RULE_NET_TYPE_INFRA_OR_IBSS 0x00 -#define WOL_RULE_NET_TYPE_MESH 0x10 -#define WOL_RULE_ADDR_TYPE_BCAST 0x01 -#define WOL_RULE_ADDR_TYPE_MCAST 0x08 -#define WOL_RULE_ADDR_TYPE_UCAST 0x02 -#define WOL_RULE_OP_AND 0x01 -#define WOL_RULE_OP_OR 0x02 -#define WOL_RULE_OP_INVALID 0xFF -#define WOL_RESULT_VALID_CMD 0 -#define WOL_RESULT_NOSPC_ERR 1 -#define WOL_RESULT_EEXIST_ERR 2 - -/** Misc constants */ -/* This section defines 802.11 specific contants */ - -#define MRVDRV_MAX_BSS_DESCRIPTS 16 -#define MRVDRV_MAX_REGION_CODE 6 - -#define MRVDRV_IGNORE_MULTIPLE_DTIM 0xfffe -#define MRVDRV_MIN_MULTIPLE_DTIM 1 -#define MRVDRV_MAX_MULTIPLE_DTIM 5 -#define MRVDRV_DEFAULT_MULTIPLE_DTIM 1 - -#define MRVDRV_DEFAULT_LISTEN_INTERVAL 10 - -#define MRVDRV_CHANNELS_PER_SCAN 4 -#define MRVDRV_MAX_CHANNELS_PER_SCAN 14 - -#define MRVDRV_MIN_BEACON_INTERVAL 20 -#define MRVDRV_MAX_BEACON_INTERVAL 1000 -#define MRVDRV_BEACON_INTERVAL 100 - -#define MARVELL_MESH_IE_LENGTH 9 - -/* Values used to populate the struct mrvl_mesh_ie. The only time you need this - * is when enabling the mesh using CMD_MESH_CONFIG. - */ -#define MARVELL_MESH_IE_TYPE 4 -#define MARVELL_MESH_IE_SUBTYPE 0 -#define MARVELL_MESH_IE_VERSION 0 -#define MARVELL_MESH_PROTO_ID_HWMP 0 -#define MARVELL_MESH_METRIC_ID 0 -#define MARVELL_MESH_CAPABILITY 0 - -/** INT status Bit Definition*/ -#define MRVDRV_TX_DNLD_RDY 0x0001 -#define MRVDRV_RX_UPLD_RDY 0x0002 -#define MRVDRV_CMD_DNLD_RDY 0x0004 -#define MRVDRV_CMD_UPLD_RDY 0x0008 -#define MRVDRV_CARDEVENT 0x0010 - -/* Automatic TX control default levels */ -#define POW_ADAPT_DEFAULT_P0 13 -#define POW_ADAPT_DEFAULT_P1 15 -#define POW_ADAPT_DEFAULT_P2 18 -#define TPC_DEFAULT_P0 5 -#define TPC_DEFAULT_P1 10 -#define TPC_DEFAULT_P2 13 - -/** TxPD status */ - -/* Station firmware use TxPD status field to report final Tx transmit -* result, Bit masks are used to present combined situations. -*/ - -#define MRVDRV_TxPD_POWER_MGMT_NULL_PACKET 0x01 -#define MRVDRV_TxPD_POWER_MGMT_LAST_PACKET 0x08 - -/** Tx mesh flag */ -/* Currently we are using normal WDS flag as mesh flag. - * TODO: change to proper mesh flag when MAC understands it. - */ -#define TxPD_CONTROL_WDS_FRAME (1<<17) -#define TxPD_MESH_FRAME TxPD_CONTROL_WDS_FRAME - -/** Mesh interface ID */ -#define MESH_IFACE_ID 0x0001 -/** Mesh id should be in bits 14-13-12 */ -#define MESH_IFACE_BIT_OFFSET 0x000c -/** Mesh enable bit in FW capability */ -#define MESH_CAPINFO_ENABLE_MASK (1<<16) - -/** FW definition from Marvell v4 */ -#define MRVL_FW_V4 (0x04) -/** FW definition from Marvell v5 */ -#define MRVL_FW_V5 (0x05) -/** FW definition from Marvell v10 */ -#define MRVL_FW_V10 (0x0a) -/** FW major revision definition */ -#define MRVL_FW_MAJOR_REV(x) ((x)>>24) - -/** RxPD status */ - -#define MRVDRV_RXPD_STATUS_OK 0x0001 - -/** RxPD status - Received packet types */ -/** Rx mesh flag */ -/* Currently we are using normal WDS flag as mesh flag. - * TODO: change to proper mesh flag when MAC understands it. - */ -#define RxPD_CONTROL_WDS_FRAME (0x40) -#define RxPD_MESH_FRAME RxPD_CONTROL_WDS_FRAME - -/** RSSI-related defines */ -/* RSSI constants are used to implement 802.11 RSSI threshold -* indication. if the Rx packet signal got too weak for 5 consecutive -* times, miniport driver (driver) will report this event to wrapper -*/ - -#define MRVDRV_NF_DEFAULT_SCAN_VALUE (-96) - -/** RTS/FRAG related defines */ -#define MRVDRV_RTS_MIN_VALUE 0 -#define MRVDRV_RTS_MAX_VALUE 2347 -#define MRVDRV_FRAG_MIN_VALUE 256 -#define MRVDRV_FRAG_MAX_VALUE 2346 - -/* This is for firmware specific length */ -#define EXTRA_LEN 36 - -#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \ - (ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN) - -#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \ - (ETH_FRAME_LEN + sizeof(struct rxpd) \ - + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN) - -#define CMD_F_HOSTCMD (1 << 0) -#define FW_CAPINFO_WPA (1 << 0) -#define FW_CAPINFO_PS (1 << 1) -#define FW_CAPINFO_FIRMWARE_UPGRADE (1 << 13) -#define FW_CAPINFO_BOOT2_UPGRADE (1<<14) -#define FW_CAPINFO_PERSISTENT_CONFIG (1<<15) - -#define KEY_LEN_WPA_AES 16 -#define KEY_LEN_WPA_TKIP 32 -#define KEY_LEN_WEP_104 13 -#define KEY_LEN_WEP_40 5 - -#define RF_ANTENNA_1 0x1 -#define RF_ANTENNA_2 0x2 -#define RF_ANTENNA_AUTO 0xFFFF - -#define BAND_B (0x01) -#define BAND_G (0x02) -#define ALL_802_11_BANDS (BAND_B | BAND_G) - -/** MACRO DEFINITIONS */ -#define CAL_NF(NF) ((s32)(-(s32)(NF))) -#define CAL_RSSI(SNR, NF) ((s32)((s32)(SNR) + CAL_NF(NF))) -#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) - -#define DEFAULT_BCN_AVG_FACTOR 8 -#define DEFAULT_DATA_AVG_FACTOR 8 -#define AVG_SCALE 100 -#define CAL_AVG_SNR_NF(AVG, SNRNF, N) \ - (((AVG) == 0) ? ((u16)(SNRNF) * AVG_SCALE) : \ - ((((int)(AVG) * (N -1)) + ((u16)(SNRNF) * \ - AVG_SCALE)) / N)) - -#define MAX_RATES 14 - -#define MAX_LEDS 8 - -/** Global Variable Declaration */ -extern const char lbs_driver_version[]; -extern u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE]; - -extern u8 lbs_bg_rates[MAX_RATES]; - -/** ENUM definition*/ -/** SNRNF_TYPE */ -enum SNRNF_TYPE { - TYPE_BEACON = 0, - TYPE_RXPD, - MAX_TYPE_B -}; - -/** SNRNF_DATA*/ -enum SNRNF_DATA { - TYPE_NOAVG = 0, - TYPE_AVG, - MAX_TYPE_AVG -}; - -/** LBS_802_11_POWER_MODE */ -enum LBS_802_11_POWER_MODE { - LBS802_11POWERMODECAM, - LBS802_11POWERMODEMAX_PSP, - LBS802_11POWERMODEFAST_PSP, - /*not a real mode, defined as an upper bound */ - LBS802_11POWEMODEMAX -}; - -/** PS_STATE */ -enum PS_STATE { - PS_STATE_FULL_POWER, - PS_STATE_AWAKE, - PS_STATE_PRE_SLEEP, - PS_STATE_SLEEP -}; - -/** DNLD_STATE */ -enum DNLD_STATE { - DNLD_RES_RECEIVED, - DNLD_DATA_SENT, - DNLD_CMD_SENT, - DNLD_BOOTCMD_SENT, -}; - -/** LBS_MEDIA_STATE */ -enum LBS_MEDIA_STATE { - LBS_CONNECTED, - LBS_DISCONNECTED -}; - -/** LBS_802_11_PRIVACY_FILTER */ -enum LBS_802_11_PRIVACY_FILTER { - LBS802_11PRIVFILTERACCEPTALL, - LBS802_11PRIVFILTER8021XWEP -}; - -/** mv_ms_type */ -enum mv_ms_type { - MVMS_DAT = 0, - MVMS_CMD = 1, - MVMS_TXDONE = 2, - MVMS_EVENT -}; - -/** KEY_TYPE_ID */ -enum KEY_TYPE_ID { - KEY_TYPE_ID_WEP = 0, - KEY_TYPE_ID_TKIP, - KEY_TYPE_ID_AES -}; - -/** KEY_INFO_WPA (applies to both TKIP and AES/CCMP) */ -enum KEY_INFO_WPA { - KEY_INFO_WPA_MCAST = 0x01, - KEY_INFO_WPA_UNICAST = 0x02, - KEY_INFO_WPA_ENABLED = 0x04 -}; - -/** mesh_fw_ver */ -enum _mesh_fw_ver { - MESH_NONE = 0, /* MESH is not supported */ - MESH_FW_OLD, /* MESH is supported in FW V5 */ - MESH_FW_NEW, /* MESH is supported in FW V10 and newer */ -}; - -/* Default values for fwt commands. */ -#define FWT_DEFAULT_METRIC 0 -#define FWT_DEFAULT_DIR 1 -/* Default Rate, 11Mbps */ -#define FWT_DEFAULT_RATE 3 -#define FWT_DEFAULT_SSN 0xffffffff -#define FWT_DEFAULT_DSN 0 -#define FWT_DEFAULT_HOPCOUNT 0 -#define FWT_DEFAULT_TTL 0 -#define FWT_DEFAULT_EXPIRATION 0 -#define FWT_DEFAULT_SLEEPMODE 0 -#define FWT_DEFAULT_SNR 0 - -#endif diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h deleted file mode 100644 index d3b69a4b4b5e..000000000000 --- a/drivers/net/wireless/libertas/dev.h +++ /dev/null @@ -1,409 +0,0 @@ -/** - * This file contains definitions and data structures specific - * to Marvell 802.11 NIC. It contains the Device Information - * structure struct lbs_private.. - */ -#ifndef _LBS_DEV_H_ -#define _LBS_DEV_H_ - -#include -#include -#include -#include - -#include "defs.h" -#include "hostcmd.h" - -extern const struct ethtool_ops lbs_ethtool_ops; - -#define MAX_BSSID_PER_CHANNEL 16 - -#define NR_TX_QUEUE 3 - -/* For the extended Scan */ -#define MAX_EXTENDED_SCAN_BSSID_LIST MAX_BSSID_PER_CHANNEL * \ - MRVDRV_MAX_CHANNEL_SIZE + 1 - -#define MAX_REGION_CHANNEL_NUM 2 - -/** Chan-freq-TxPower mapping table*/ -struct chan_freq_power { - /** channel Number */ - u16 channel; - /** frequency of this channel */ - u32 freq; - /** Max allowed Tx power level */ - u16 maxtxpower; - /** TRUE:channel unsupported; FLASE:supported*/ - u8 unsupported; -}; - -/** region-band mapping table*/ -struct region_channel { - /** TRUE if this entry is valid */ - u8 valid; - /** region code for US, Japan ... */ - u8 region; - /** band B/G/A, used for BAND_CONFIG cmd */ - u8 band; - /** Actual No. of elements in the array below */ - u8 nrcfp; - /** chan-freq-txpower mapping table*/ - struct chan_freq_power *CFP; -}; - -struct lbs_802_11_security { - u8 WPAenabled; - u8 WPA2enabled; - u8 wep_enabled; - u8 auth_mode; - u32 key_mgmt; -}; - -/** Current Basic Service Set State Structure */ -struct current_bss_params { - /** bssid */ - u8 bssid[ETH_ALEN]; - /** ssid */ - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - /** band */ - u8 band; - /** channel */ - u8 channel; - /** zero-terminated array of supported data rates */ - u8 rates[MAX_RATES + 1]; -}; - -/** sleep_params */ -struct sleep_params { - uint16_t sp_error; - uint16_t sp_offset; - uint16_t sp_stabletime; - uint8_t sp_calcontrol; - uint8_t sp_extsleepclk; - uint16_t sp_reserved; -}; - -/* Mesh statistics */ -struct lbs_mesh_stats { - u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */ - u32 fwd_unicast_cnt; /* Fwd: Unicast counter */ - u32 fwd_drop_ttl; /* Fwd: TTL zero */ - u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */ - u32 fwd_drop_noroute; /* Fwd: No route to Destination */ - u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */ - u32 drop_blind; /* Rx: Dropped by blinding table */ - u32 tx_failed_cnt; /* Tx: Failed transmissions */ -}; - -/** Private structure for the MV device */ -struct lbs_private { - int mesh_open; - int mesh_fw_ver; - int infra_open; - int mesh_autostart_enabled; - - char name[DEV_NAME_LEN]; - - void *card; - struct net_device *dev; - - struct net_device *mesh_dev; /* Virtual device */ - struct net_device *rtap_net_dev; - - struct iw_statistics wstats; - struct lbs_mesh_stats mstats; - struct dentry *debugfs_dir; - struct dentry *debugfs_debug; - struct dentry *debugfs_files[6]; - - struct dentry *events_dir; - struct dentry *debugfs_events_files[6]; - - struct dentry *regs_dir; - struct dentry *debugfs_regs_files[6]; - - u32 mac_offset; - u32 bbp_offset; - u32 rf_offset; - - /* Download sent: - bit0 1/0=data_sent/data_tx_done, - bit1 1/0=cmd_sent/cmd_tx_done, - all other bits reserved 0 */ - u8 dnld_sent; - - /** thread to service interrupts */ - struct task_struct *main_thread; - wait_queue_head_t waitq; - struct workqueue_struct *work_thread; - - struct work_struct mcast_work; - - /** Scanning */ - struct delayed_work scan_work; - struct delayed_work assoc_work; - struct work_struct sync_channel; - /* remember which channel was scanned last, != 0 if currently scanning */ - int scan_channel; - u8 scan_ssid[IW_ESSID_MAX_SIZE + 1]; - u8 scan_ssid_len; - - /** Hardware access */ - int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); - void (*reset_card) (struct lbs_private *priv); - - /* Wake On LAN */ - uint32_t wol_criteria; - uint8_t wol_gpio; - uint8_t wol_gap; - - /** Wlan adapter data structure*/ - /** STATUS variables */ - u32 fwrelease; - u32 fwcapinfo; - - struct mutex lock; - - /* TX packet ready to be sent... */ - int tx_pending_len; /* -1 while building packet */ - - u8 tx_pending_buf[LBS_UPLD_SIZE]; - /* protected by hard_start_xmit serialization */ - - /** command-related variables */ - u16 seqnum; - - struct cmd_ctrl_node *cmd_array; - /** Current command */ - struct cmd_ctrl_node *cur_cmd; - int cur_cmd_retcode; - /** command Queues */ - /** Free command buffers */ - struct list_head cmdfreeq; - /** Pending command buffers */ - struct list_head cmdpendingq; - - wait_queue_head_t cmd_pending; - - /* Command responses sent from the hardware to the driver */ - u8 resp_idx; - u8 resp_buf[2][LBS_UPLD_SIZE]; - u32 resp_len[2]; - - /* Events sent from hardware to driver */ - struct kfifo *event_fifo; - - /* nickname */ - u8 nodename[16]; - - /** spin locks */ - spinlock_t driver_lock; - - /** Timers */ - struct timer_list command_timer; - int nr_retries; - int cmd_timed_out; - - /** current ssid/bssid related parameters*/ - struct current_bss_params curbssparams; - - uint16_t mesh_tlv; - u8 mesh_ssid[IW_ESSID_MAX_SIZE + 1]; - u8 mesh_ssid_len; - - /* IW_MODE_* */ - u8 mode; - - /* Scan results list */ - struct list_head network_list; - struct list_head network_free_list; - struct bss_descriptor *networks; - - u16 beacon_period; - u8 beacon_enable; - u8 adhoccreate; - - /** capability Info used in Association, start, join */ - u16 capability; - - /** MAC address information */ - u8 current_addr[ETH_ALEN]; - u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; - u32 nr_of_multicastmacaddr; - - /** 802.11 statistics */ -// struct cmd_DS_802_11_GET_STAT wlan802_11Stat; - - uint16_t enablehwauto; - uint16_t ratebitmap; - - u8 txretrycount; - - /** Tx-related variables (for single packet tx) */ - struct sk_buff *currenttxskb; - - /** NIC Operation characteristics */ - u16 mac_control; - u32 connect_status; - u32 mesh_connect_status; - u16 regioncode; - s16 txpower_cur; - s16 txpower_min; - s16 txpower_max; - - /** POWER MANAGEMENT AND PnP SUPPORT */ - u8 surpriseremoved; - - u16 psmode; /* Wlan802_11PowermodeCAM=disable - Wlan802_11PowermodeMAX_PSP=enable */ - u32 psstate; - u8 needtowakeup; - - struct assoc_request * pending_assoc_req; - struct assoc_request * in_progress_assoc_req; - - /** Encryption parameter */ - struct lbs_802_11_security secinfo; - - /** WEP keys */ - struct enc_key wep_keys[4]; - u16 wep_tx_keyidx; - - /** WPA keys */ - struct enc_key wpa_mcast_key; - struct enc_key wpa_unicast_key; - -/* - * In theory, the IE is limited to the IE length, 255, - * but in practice 64 bytes are enough. - */ -#define MAX_WPA_IE_LEN 64 - - /** WPA Information Elements*/ - u8 wpa_ie[MAX_WPA_IE_LEN]; - u8 wpa_ie_len; - - /** Requested Signal Strength*/ - u16 SNR[MAX_TYPE_B][MAX_TYPE_AVG]; - u16 NF[MAX_TYPE_B][MAX_TYPE_AVG]; - u8 RSSI[MAX_TYPE_B][MAX_TYPE_AVG]; - u8 rawSNR[DEFAULT_DATA_AVG_FACTOR]; - u8 rawNF[DEFAULT_DATA_AVG_FACTOR]; - u16 nextSNRNF; - u16 numSNRNF; - - u8 radio_on; - - /** data rate stuff */ - u8 cur_rate; - - /** RF calibration data */ - -#define MAX_REGION_CHANNEL_NUM 2 - /** region channel data */ - struct region_channel region_channel[MAX_REGION_CHANNEL_NUM]; - - struct region_channel universal_channel[MAX_REGION_CHANNEL_NUM]; - - /** 11D and Domain Regulatory Data */ - struct lbs_802_11d_domain_reg domainreg; - struct parsed_region_chan_11d parsed_region_chan; - - /** FSM variable for 11d support */ - u32 enable11d; - - /** MISCELLANEOUS */ - struct lbs_offset_value offsetvalue; - - u32 monitormode; - u8 fw_ready; -}; - -extern struct cmd_confirm_sleep confirm_sleep; - -/** - * @brief Structure used to store information for each beacon/probe response - */ -struct bss_descriptor { - u8 bssid[ETH_ALEN]; - - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - - u16 capability; - u32 rssi; - u32 channel; - u16 beaconperiod; - __le16 atimwindow; - - /* IW_MODE_AUTO, IW_MODE_ADHOC, IW_MODE_INFRA */ - u8 mode; - - /* zero-terminated array of supported data rates */ - u8 rates[MAX_RATES + 1]; - - unsigned long last_scanned; - - union ieee_phy_param_set phy; - union ieee_ss_param_set ss; - - struct ieee_ie_country_info_full_set countryinfo; - - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - u8 rsn_ie[MAX_WPA_IE_LEN]; - size_t rsn_ie_len; - - u8 mesh; - - struct list_head list; -}; - -/** Association request - * - * Encapsulates all the options that describe a specific assocation request - * or configuration of the wireless card's radio, mode, and security settings. - */ -struct assoc_request { -#define ASSOC_FLAG_SSID 1 -#define ASSOC_FLAG_CHANNEL 2 -#define ASSOC_FLAG_BAND 3 -#define ASSOC_FLAG_MODE 4 -#define ASSOC_FLAG_BSSID 5 -#define ASSOC_FLAG_WEP_KEYS 6 -#define ASSOC_FLAG_WEP_TX_KEYIDX 7 -#define ASSOC_FLAG_WPA_MCAST_KEY 8 -#define ASSOC_FLAG_WPA_UCAST_KEY 9 -#define ASSOC_FLAG_SECINFO 10 -#define ASSOC_FLAG_WPA_IE 11 - unsigned long flags; - - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - u8 channel; - u8 band; - u8 mode; - u8 bssid[ETH_ALEN] __attribute__ ((aligned (2))); - - /** WEP keys */ - struct enc_key wep_keys[4]; - u16 wep_tx_keyidx; - - /** WPA keys */ - struct enc_key wpa_mcast_key; - struct enc_key wpa_unicast_key; - - struct lbs_802_11_security secinfo; - - /** WPA Information Elements*/ - u8 wpa_ie[MAX_WPA_IE_LEN]; - u8 wpa_ie_len; - - /* BSS to associate with for infrastructure of Ad-Hoc join */ - struct bss_descriptor bss; -}; - -#endif diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c deleted file mode 100644 index 53d56ab83c03..000000000000 --- a/drivers/net/wireless/libertas/ethtool.c +++ /dev/null @@ -1,199 +0,0 @@ -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "wext.h" -#include "cmd.h" - -static const char * mesh_stat_strings[]= { - "drop_duplicate_bcast", - "drop_ttl_zero", - "drop_no_fwd_route", - "drop_no_buffers", - "fwded_unicast_cnt", - "fwded_bcast_cnt", - "drop_blind_table", - "tx_failed_cnt" -}; - -static void lbs_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct lbs_private *priv = dev->ml_priv; - - snprintf(info->fw_version, 32, "%u.%u.%u.p%u", - priv->fwrelease >> 24 & 0xff, - priv->fwrelease >> 16 & 0xff, - priv->fwrelease >> 8 & 0xff, - priv->fwrelease & 0xff); - strcpy(info->driver, "libertas"); - strcpy(info->version, lbs_driver_version); -} - -/* All 8388 parts have 16KiB EEPROM size at the time of writing. - * In case that changes this needs fixing. - */ -#define LBS_EEPROM_LEN 16384 - -static int lbs_ethtool_get_eeprom_len(struct net_device *dev) -{ - return LBS_EEPROM_LEN; -} - -static int lbs_ethtool_get_eeprom(struct net_device *dev, - struct ethtool_eeprom *eeprom, u8 * bytes) -{ - struct lbs_private *priv = dev->ml_priv; - struct cmd_ds_802_11_eeprom_access cmd; - int ret; - - lbs_deb_enter(LBS_DEB_ETHTOOL); - - if (eeprom->offset + eeprom->len > LBS_EEPROM_LEN || - eeprom->len > LBS_EEPROM_READ_LEN) { - ret = -EINVAL; - goto out; - } - - cmd.hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_eeprom_access) - - LBS_EEPROM_READ_LEN + eeprom->len); - cmd.action = cpu_to_le16(CMD_ACT_GET); - cmd.offset = cpu_to_le16(eeprom->offset); - cmd.len = cpu_to_le16(eeprom->len); - ret = lbs_cmd_with_response(priv, CMD_802_11_EEPROM_ACCESS, &cmd); - if (!ret) - memcpy(bytes, cmd.value, eeprom->len); - -out: - lbs_deb_leave_args(LBS_DEB_ETHTOOL, "ret %d", ret); - return ret; -} - -static void lbs_ethtool_get_stats(struct net_device *dev, - struct ethtool_stats *stats, uint64_t *data) -{ - struct lbs_private *priv = dev->ml_priv; - struct cmd_ds_mesh_access mesh_access; - int ret; - - lbs_deb_enter(LBS_DEB_ETHTOOL); - - /* Get Mesh Statistics */ - ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access); - - if (ret) { - memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t))); - return; - } - - priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]); - priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]); - priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]); - priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]); - priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]); - priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]); - priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]); - priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]); - - data[0] = priv->mstats.fwd_drop_rbt; - data[1] = priv->mstats.fwd_drop_ttl; - data[2] = priv->mstats.fwd_drop_noroute; - data[3] = priv->mstats.fwd_drop_nobuf; - data[4] = priv->mstats.fwd_unicast_cnt; - data[5] = priv->mstats.fwd_bcast_cnt; - data[6] = priv->mstats.drop_blind; - data[7] = priv->mstats.tx_failed_cnt; - - lbs_deb_enter(LBS_DEB_ETHTOOL); -} - -static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset) -{ - struct lbs_private *priv = dev->ml_priv; - - if (sset == ETH_SS_STATS && dev == priv->mesh_dev) - return MESH_STATS_NUM; - - return -EOPNOTSUPP; -} - -static void lbs_ethtool_get_strings(struct net_device *dev, - uint32_t stringset, uint8_t *s) -{ - int i; - - lbs_deb_enter(LBS_DEB_ETHTOOL); - - switch (stringset) { - case ETH_SS_STATS: - for (i=0; i < MESH_STATS_NUM; i++) { - memcpy(s + i * ETH_GSTRING_LEN, - mesh_stat_strings[i], - ETH_GSTRING_LEN); - } - break; - } - lbs_deb_enter(LBS_DEB_ETHTOOL); -} - -static void lbs_ethtool_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct lbs_private *priv = dev->ml_priv; - - if (priv->wol_criteria == 0xffffffff) { - /* Interface driver didn't configure wake */ - wol->supported = wol->wolopts = 0; - return; - } - - wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; - - if (priv->wol_criteria & EHS_WAKE_ON_UNICAST_DATA) - wol->wolopts |= WAKE_UCAST; - if (priv->wol_criteria & EHS_WAKE_ON_MULTICAST_DATA) - wol->wolopts |= WAKE_MCAST; - if (priv->wol_criteria & EHS_WAKE_ON_BROADCAST_DATA) - wol->wolopts |= WAKE_BCAST; - if (priv->wol_criteria & EHS_WAKE_ON_MAC_EVENT) - wol->wolopts |= WAKE_PHY; -} - -static int lbs_ethtool_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct lbs_private *priv = dev->ml_priv; - uint32_t criteria = 0; - - if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) - return -EOPNOTSUPP; - - if (wol->wolopts & WAKE_UCAST) - criteria |= EHS_WAKE_ON_UNICAST_DATA; - if (wol->wolopts & WAKE_MCAST) - criteria |= EHS_WAKE_ON_MULTICAST_DATA; - if (wol->wolopts & WAKE_BCAST) - criteria |= EHS_WAKE_ON_BROADCAST_DATA; - if (wol->wolopts & WAKE_PHY) - criteria |= EHS_WAKE_ON_MAC_EVENT; - if (wol->wolopts == 0) - criteria |= EHS_REMOVE_WAKEUP; - - return lbs_host_sleep_cfg(priv, criteria, (struct wol_config *)NULL); -} - -const struct ethtool_ops lbs_ethtool_ops = { - .get_drvinfo = lbs_ethtool_get_drvinfo, - .get_eeprom = lbs_ethtool_get_eeprom, - .get_eeprom_len = lbs_ethtool_get_eeprom_len, - .get_sset_count = lbs_ethtool_get_sset_count, - .get_ethtool_stats = lbs_ethtool_get_stats, - .get_strings = lbs_ethtool_get_strings, - .get_wol = lbs_ethtool_get_wol, - .set_wol = lbs_ethtool_set_wol, -}; - diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h deleted file mode 100644 index fe8f0cb737bc..000000000000 --- a/drivers/net/wireless/libertas/host.h +++ /dev/null @@ -1,305 +0,0 @@ -/** - * This file contains definitions of WLAN commands. - */ - -#ifndef _LBS_HOST_H_ -#define _LBS_HOST_H_ - -/** PUBLIC DEFINITIONS */ -#define DEFAULT_AD_HOC_CHANNEL 6 -#define DEFAULT_AD_HOC_CHANNEL_A 36 - -#define CMD_OPTION_WAITFORRSP 0x0002 - -/** Host command IDs */ - -/* Return command are almost always the same as the host command, but with - * bit 15 set high. There are a few exceptions, though... - */ -#define CMD_RET(cmd) (0x8000 | cmd) - -/* Return command convention exceptions: */ -#define CMD_RET_802_11_ASSOCIATE 0x8012 - -/* Command codes */ -#define CMD_GET_HW_SPEC 0x0003 -#define CMD_EEPROM_UPDATE 0x0004 -#define CMD_802_11_RESET 0x0005 -#define CMD_802_11_SCAN 0x0006 -#define CMD_802_11_GET_LOG 0x000b -#define CMD_MAC_MULTICAST_ADR 0x0010 -#define CMD_802_11_AUTHENTICATE 0x0011 -#define CMD_802_11_EEPROM_ACCESS 0x0059 -#define CMD_802_11_ASSOCIATE 0x0050 -#define CMD_802_11_SET_WEP 0x0013 -#define CMD_802_11_GET_STAT 0x0014 -#define CMD_802_3_GET_STAT 0x0015 -#define CMD_802_11_SNMP_MIB 0x0016 -#define CMD_MAC_REG_MAP 0x0017 -#define CMD_BBP_REG_MAP 0x0018 -#define CMD_MAC_REG_ACCESS 0x0019 -#define CMD_BBP_REG_ACCESS 0x001a -#define CMD_RF_REG_ACCESS 0x001b -#define CMD_802_11_RADIO_CONTROL 0x001c -#define CMD_802_11_RF_CHANNEL 0x001d -#define CMD_802_11_RF_TX_POWER 0x001e -#define CMD_802_11_RSSI 0x001f -#define CMD_802_11_RF_ANTENNA 0x0020 -#define CMD_802_11_PS_MODE 0x0021 -#define CMD_802_11_DATA_RATE 0x0022 -#define CMD_RF_REG_MAP 0x0023 -#define CMD_802_11_DEAUTHENTICATE 0x0024 -#define CMD_802_11_REASSOCIATE 0x0025 -#define CMD_MAC_CONTROL 0x0028 -#define CMD_802_11_AD_HOC_START 0x002b -#define CMD_802_11_AD_HOC_JOIN 0x002c -#define CMD_802_11_QUERY_TKIP_REPLY_CNTRS 0x002e -#define CMD_802_11_ENABLE_RSN 0x002f -#define CMD_802_11_SET_AFC 0x003c -#define CMD_802_11_GET_AFC 0x003d -#define CMD_802_11_AD_HOC_STOP 0x0040 -#define CMD_802_11_HOST_SLEEP_CFG 0x0043 -#define CMD_802_11_WAKEUP_CONFIRM 0x0044 -#define CMD_802_11_HOST_SLEEP_ACTIVATE 0x0045 -#define CMD_802_11_BEACON_STOP 0x0049 -#define CMD_802_11_MAC_ADDRESS 0x004d -#define CMD_802_11_LED_GPIO_CTRL 0x004e -#define CMD_802_11_EEPROM_ACCESS 0x0059 -#define CMD_802_11_BAND_CONFIG 0x0058 -#define CMD_GSPI_BUS_CONFIG 0x005a -#define CMD_802_11D_DOMAIN_INFO 0x005b -#define CMD_802_11_KEY_MATERIAL 0x005e -#define CMD_802_11_SLEEP_PARAMS 0x0066 -#define CMD_802_11_INACTIVITY_TIMEOUT 0x0067 -#define CMD_802_11_SLEEP_PERIOD 0x0068 -#define CMD_802_11_TPC_CFG 0x0072 -#define CMD_802_11_PA_CFG 0x0073 -#define CMD_802_11_FW_WAKE_METHOD 0x0074 -#define CMD_802_11_SUBSCRIBE_EVENT 0x0075 -#define CMD_802_11_RATE_ADAPT_RATESET 0x0076 -#define CMD_802_11_TX_RATE_QUERY 0x007f -#define CMD_GET_TSF 0x0080 -#define CMD_BT_ACCESS 0x0087 -#define CMD_FWT_ACCESS 0x0095 -#define CMD_802_11_MONITOR_MODE 0x0098 -#define CMD_MESH_ACCESS 0x009b -#define CMD_MESH_CONFIG_OLD 0x00a3 -#define CMD_MESH_CONFIG 0x00ac -#define CMD_SET_BOOT2_VER 0x00a5 -#define CMD_FUNC_INIT 0x00a9 -#define CMD_FUNC_SHUTDOWN 0x00aa -#define CMD_802_11_BEACON_CTRL 0x00b0 - -/* For the IEEE Power Save */ -#define CMD_SUBCMD_ENTER_PS 0x0030 -#define CMD_SUBCMD_EXIT_PS 0x0031 -#define CMD_SUBCMD_SLEEP_CONFIRMED 0x0034 -#define CMD_SUBCMD_FULL_POWERDOWN 0x0035 -#define CMD_SUBCMD_FULL_POWERUP 0x0036 - -#define CMD_ENABLE_RSN 0x0001 -#define CMD_DISABLE_RSN 0x0000 - -#define CMD_ACT_GET 0x0000 -#define CMD_ACT_SET 0x0001 -#define CMD_ACT_GET_AES 0x0002 -#define CMD_ACT_SET_AES 0x0003 -#define CMD_ACT_REMOVE_AES 0x0004 - -/* Define action or option for CMD_802_11_SET_WEP */ -#define CMD_ACT_ADD 0x0002 -#define CMD_ACT_REMOVE 0x0004 -#define CMD_ACT_USE_DEFAULT 0x0008 - -#define CMD_TYPE_WEP_40_BIT 0x01 -#define CMD_TYPE_WEP_104_BIT 0x02 - -#define CMD_NUM_OF_WEP_KEYS 4 - -#define CMD_WEP_KEY_INDEX_MASK 0x3fff - -/* Define action or option for CMD_802_11_RESET */ -#define CMD_ACT_HALT 0x0003 - -/* Define action or option for CMD_802_11_SCAN */ -#define CMD_BSS_TYPE_BSS 0x0001 -#define CMD_BSS_TYPE_IBSS 0x0002 -#define CMD_BSS_TYPE_ANY 0x0003 - -/* Define action or option for CMD_802_11_SCAN */ -#define CMD_SCAN_TYPE_ACTIVE 0x0000 -#define CMD_SCAN_TYPE_PASSIVE 0x0001 - -#define CMD_SCAN_RADIO_TYPE_BG 0 - -#define CMD_SCAN_PROBE_DELAY_TIME 0 - -/* Define action or option for CMD_MAC_CONTROL */ -#define CMD_ACT_MAC_RX_ON 0x0001 -#define CMD_ACT_MAC_TX_ON 0x0002 -#define CMD_ACT_MAC_LOOPBACK_ON 0x0004 -#define CMD_ACT_MAC_WEP_ENABLE 0x0008 -#define CMD_ACT_MAC_INT_ENABLE 0x0010 -#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020 -#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040 -#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 -#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 -#define CMD_ACT_MAC_STRICT_PROTECTION_ENABLE 0x0400 - -/* Event flags for CMD_802_11_SUBSCRIBE_EVENT */ -#define CMD_SUBSCRIBE_RSSI_LOW 0x0001 -#define CMD_SUBSCRIBE_SNR_LOW 0x0002 -#define CMD_SUBSCRIBE_FAILCOUNT 0x0004 -#define CMD_SUBSCRIBE_BCNMISS 0x0008 -#define CMD_SUBSCRIBE_RSSI_HIGH 0x0010 -#define CMD_SUBSCRIBE_SNR_HIGH 0x0020 - -#define RADIO_PREAMBLE_LONG 0x00 -#define RADIO_PREAMBLE_SHORT 0x02 -#define RADIO_PREAMBLE_AUTO 0x04 - -/* Define action or option for CMD_802_11_RF_CHANNEL */ -#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 -#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 - -/* Define action or option for CMD_802_11_DATA_RATE */ -#define CMD_ACT_SET_TX_AUTO 0x0000 -#define CMD_ACT_SET_TX_FIX_RATE 0x0001 -#define CMD_ACT_GET_TX_RATE 0x0002 - -#define CMD_ACT_SET_RX 0x0001 -#define CMD_ACT_SET_TX 0x0002 -#define CMD_ACT_SET_BOTH 0x0003 -#define CMD_ACT_GET_RX 0x0004 -#define CMD_ACT_GET_TX 0x0008 -#define CMD_ACT_GET_BOTH 0x000c - -/* Define action or option for CMD_802_11_PS_MODE */ -#define CMD_TYPE_CAM 0x0000 -#define CMD_TYPE_MAX_PSP 0x0001 -#define CMD_TYPE_FAST_PSP 0x0002 - -/* Options for CMD_802_11_FW_WAKE_METHOD */ -#define CMD_WAKE_METHOD_UNCHANGED 0x0000 -#define CMD_WAKE_METHOD_COMMAND_INT 0x0001 -#define CMD_WAKE_METHOD_GPIO 0x0002 - -/* Object IDs for CMD_802_11_SNMP_MIB */ -#define SNMP_MIB_OID_BSS_TYPE 0x0000 -#define SNMP_MIB_OID_OP_RATE_SET 0x0001 -#define SNMP_MIB_OID_BEACON_PERIOD 0x0002 /* Reserved on v9+ */ -#define SNMP_MIB_OID_DTIM_PERIOD 0x0003 /* Reserved on v9+ */ -#define SNMP_MIB_OID_ASSOC_TIMEOUT 0x0004 /* Reserved on v9+ */ -#define SNMP_MIB_OID_RTS_THRESHOLD 0x0005 -#define SNMP_MIB_OID_SHORT_RETRY_LIMIT 0x0006 -#define SNMP_MIB_OID_LONG_RETRY_LIMIT 0x0007 -#define SNMP_MIB_OID_FRAG_THRESHOLD 0x0008 -#define SNMP_MIB_OID_11D_ENABLE 0x0009 -#define SNMP_MIB_OID_11H_ENABLE 0x000A - -/* Define action or option for CMD_BT_ACCESS */ -enum cmd_bt_access_opts { - /* The bt commands start at 5 instead of 1 because the old dft commands - * are mapped to 1-4. These old commands are no longer maintained and - * should not be called. - */ - CMD_ACT_BT_ACCESS_ADD = 5, - CMD_ACT_BT_ACCESS_DEL, - CMD_ACT_BT_ACCESS_LIST, - CMD_ACT_BT_ACCESS_RESET, - CMD_ACT_BT_ACCESS_SET_INVERT, - CMD_ACT_BT_ACCESS_GET_INVERT -}; - -/* Define action or option for CMD_FWT_ACCESS */ -enum cmd_fwt_access_opts { - CMD_ACT_FWT_ACCESS_ADD = 1, - CMD_ACT_FWT_ACCESS_DEL, - CMD_ACT_FWT_ACCESS_LOOKUP, - CMD_ACT_FWT_ACCESS_LIST, - CMD_ACT_FWT_ACCESS_LIST_ROUTE, - CMD_ACT_FWT_ACCESS_LIST_NEIGHBOR, - CMD_ACT_FWT_ACCESS_RESET, - CMD_ACT_FWT_ACCESS_CLEANUP, - CMD_ACT_FWT_ACCESS_TIME, -}; - -/* Define action or option for CMD_802_11_HOST_SLEEP_CFG */ -enum cmd_wol_cfg_opts { - CMD_ACT_ACTION_NONE = 0, - CMD_ACT_SET_WOL_RULE, - CMD_ACT_GET_WOL_RULE, - CMD_ACT_RESET_WOL_RULE, -}; - -/* Define action or option for CMD_MESH_ACCESS */ -enum cmd_mesh_access_opts { - CMD_ACT_MESH_GET_TTL = 1, - CMD_ACT_MESH_SET_TTL, - CMD_ACT_MESH_GET_STATS, - CMD_ACT_MESH_GET_ANYCAST, - CMD_ACT_MESH_SET_ANYCAST, - CMD_ACT_MESH_SET_LINK_COSTS, - CMD_ACT_MESH_GET_LINK_COSTS, - CMD_ACT_MESH_SET_BCAST_RATE, - CMD_ACT_MESH_GET_BCAST_RATE, - CMD_ACT_MESH_SET_RREQ_DELAY, - CMD_ACT_MESH_GET_RREQ_DELAY, - CMD_ACT_MESH_SET_ROUTE_EXP, - CMD_ACT_MESH_GET_ROUTE_EXP, - CMD_ACT_MESH_SET_AUTOSTART_ENABLED, - CMD_ACT_MESH_GET_AUTOSTART_ENABLED, - CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT = 17, -}; - -/* Define actions and types for CMD_MESH_CONFIG */ -enum cmd_mesh_config_actions { - CMD_ACT_MESH_CONFIG_STOP = 0, - CMD_ACT_MESH_CONFIG_START, - CMD_ACT_MESH_CONFIG_SET, - CMD_ACT_MESH_CONFIG_GET, -}; - -enum cmd_mesh_config_types { - CMD_TYPE_MESH_SET_BOOTFLAG = 1, - CMD_TYPE_MESH_SET_BOOTTIME, - CMD_TYPE_MESH_SET_DEF_CHANNEL, - CMD_TYPE_MESH_SET_MESH_IE, - CMD_TYPE_MESH_GET_DEFAULTS, - CMD_TYPE_MESH_GET_MESH_IE, /* GET_DEFAULTS is superset of GET_MESHIE */ -}; - -/** Card Event definition */ -#define MACREG_INT_CODE_TX_PPA_FREE 0 -#define MACREG_INT_CODE_TX_DMA_DONE 1 -#define MACREG_INT_CODE_LINK_LOST_W_SCAN 2 -#define MACREG_INT_CODE_LINK_LOST_NO_SCAN 3 -#define MACREG_INT_CODE_LINK_SENSED 4 -#define MACREG_INT_CODE_CMD_FINISHED 5 -#define MACREG_INT_CODE_MIB_CHANGED 6 -#define MACREG_INT_CODE_INIT_DONE 7 -#define MACREG_INT_CODE_DEAUTHENTICATED 8 -#define MACREG_INT_CODE_DISASSOCIATED 9 -#define MACREG_INT_CODE_PS_AWAKE 10 -#define MACREG_INT_CODE_PS_SLEEP 11 -#define MACREG_INT_CODE_MIC_ERR_MULTICAST 13 -#define MACREG_INT_CODE_MIC_ERR_UNICAST 14 -#define MACREG_INT_CODE_WM_AWAKE 15 -#define MACREG_INT_CODE_DEEP_SLEEP_AWAKE 16 -#define MACREG_INT_CODE_ADHOC_BCN_LOST 17 -#define MACREG_INT_CODE_HOST_AWAKE 18 -#define MACREG_INT_CODE_STOP_TX 19 -#define MACREG_INT_CODE_START_TX 20 -#define MACREG_INT_CODE_CHANNEL_SWITCH 21 -#define MACREG_INT_CODE_MEASUREMENT_RDY 22 -#define MACREG_INT_CODE_WMM_CHANGE 23 -#define MACREG_INT_CODE_BG_SCAN_REPORT 24 -#define MACREG_INT_CODE_RSSI_LOW 25 -#define MACREG_INT_CODE_SNR_LOW 26 -#define MACREG_INT_CODE_MAX_FAIL 27 -#define MACREG_INT_CODE_RSSI_HIGH 28 -#define MACREG_INT_CODE_SNR_HIGH 29 -#define MACREG_INT_CODE_MESH_AUTO_STARTED 35 -#define MACREG_INT_CODE_FIRMWARE_READY 48 - -#endif diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h deleted file mode 100644 index c8a1998d4744..000000000000 --- a/drivers/net/wireless/libertas/hostcmd.h +++ /dev/null @@ -1,800 +0,0 @@ -/* - * This file contains the function prototypes, data structure - * and defines for all the host/station commands - */ -#ifndef _LBS_HOSTCMD_H -#define _LBS_HOSTCMD_H - -#include -#include "11d.h" -#include "types.h" - -/* 802.11-related definitions */ - -/* TxPD descriptor */ -struct txpd { - /* union to cope up with later FW revisions */ - union { - /* Current Tx packet status */ - __le32 tx_status; - struct { - /* BSS type: client, AP, etc. */ - u8 bss_type; - /* BSS number */ - u8 bss_num; - /* Reserved */ - __le16 reserved; - } bss; - } u; - /* Tx control */ - __le32 tx_control; - __le32 tx_packet_location; - /* Tx packet length */ - __le16 tx_packet_length; - /* First 2 byte of destination MAC address */ - u8 tx_dest_addr_high[2]; - /* Last 4 byte of destination MAC address */ - u8 tx_dest_addr_low[4]; - /* Pkt Priority */ - u8 priority; - /* Pkt Trasnit Power control */ - u8 powermgmt; - /* Amount of time the packet has been queued in the driver (units = 2ms) */ - u8 pktdelay_2ms; - /* reserved */ - u8 reserved1; -} __attribute__ ((packed)); - -/* RxPD Descriptor */ -struct rxpd { - /* union to cope up with later FW revisions */ - union { - /* Current Rx packet status */ - __le16 status; - struct { - /* BSS type: client, AP, etc. */ - u8 bss_type; - /* BSS number */ - u8 bss_num; - } __attribute__ ((packed)) bss; - } __attribute__ ((packed)) u; - - /* SNR */ - u8 snr; - - /* Tx control */ - u8 rx_control; - - /* Pkt length */ - __le16 pkt_len; - - /* Noise Floor */ - u8 nf; - - /* Rx Packet Rate */ - u8 rx_rate; - - /* Pkt addr */ - __le32 pkt_ptr; - - /* Next Rx RxPD addr */ - __le32 next_rxpd_ptr; - - /* Pkt Priority */ - u8 priority; - u8 reserved[3]; -} __attribute__ ((packed)); - -struct cmd_header { - __le16 command; - __le16 size; - __le16 seqnum; - __le16 result; -} __attribute__ ((packed)); - -struct cmd_ctrl_node { - struct list_head list; - int result; - /* command response */ - int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *); - unsigned long callback_arg; - /* command data */ - struct cmd_header *cmdbuf; - /* wait queue */ - u16 cmdwaitqwoken; - wait_queue_head_t cmdwait_q; -}; - -/* Generic structure to hold all key types. */ -struct enc_key { - u16 len; - u16 flags; /* KEY_INFO_* from defs.h */ - u16 type; /* KEY_TYPE_* from defs.h */ - u8 key[32]; -}; - -/* lbs_offset_value */ -struct lbs_offset_value { - u32 offset; - u32 value; -} __attribute__ ((packed)); - -/* Define general data structure */ -/* cmd_DS_GEN */ -struct cmd_ds_gen { - __le16 command; - __le16 size; - __le16 seqnum; - __le16 result; - void *cmdresp[0]; -} __attribute__ ((packed)); - -#define S_DS_GEN sizeof(struct cmd_ds_gen) - - -/* - * Define data structure for CMD_GET_HW_SPEC - * This structure defines the response for the GET_HW_SPEC command - */ -struct cmd_ds_get_hw_spec { - struct cmd_header hdr; - - /* HW Interface version number */ - __le16 hwifversion; - /* HW version number */ - __le16 version; - /* Max number of TxPD FW can handle */ - __le16 nr_txpd; - /* Max no of Multicast address */ - __le16 nr_mcast_adr; - /* MAC address */ - u8 permanentaddr[6]; - - /* region Code */ - __le16 regioncode; - - /* Number of antenna used */ - __le16 nr_antenna; - - /* FW release number, example 0x01030304 = 2.3.4p1 */ - __le32 fwrelease; - - /* Base Address of TxPD queue */ - __le32 wcb_base; - /* Read Pointer of RxPd queue */ - __le32 rxpd_rdptr; - - /* Write Pointer of RxPd queue */ - __le32 rxpd_wrptr; - - /*FW/HW capability */ - __le32 fwcapinfo; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_subscribe_event { - struct cmd_header hdr; - - __le16 action; - __le16 events; - - /* A TLV to the CMD_802_11_SUBSCRIBE_EVENT command can contain a - * number of TLVs. From the v5.1 manual, those TLVs would add up to - * 40 bytes. However, future firmware might add additional TLVs, so I - * bump this up a bit. - */ - uint8_t tlv[128]; -} __attribute__ ((packed)); - -/* - * This scan handle Country Information IE(802.11d compliant) - * Define data structure for CMD_802_11_SCAN - */ -struct cmd_ds_802_11_scan { - struct cmd_header hdr; - - uint8_t bsstype; - uint8_t bssid[ETH_ALEN]; - uint8_t tlvbuffer[0]; -#if 0 - mrvlietypes_ssidparamset_t ssidParamSet; - mrvlietypes_chanlistparamset_t ChanListParamSet; - mrvlietypes_ratesparamset_t OpRateSet; -#endif -} __attribute__ ((packed)); - -struct cmd_ds_802_11_scan_rsp { - struct cmd_header hdr; - - __le16 bssdescriptsize; - uint8_t nr_sets; - uint8_t bssdesc_and_tlvbuffer[0]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_get_log { - struct cmd_header hdr; - - __le32 mcasttxframe; - __le32 failed; - __le32 retry; - __le32 multiretry; - __le32 framedup; - __le32 rtssuccess; - __le32 rtsfailure; - __le32 ackfailure; - __le32 rxfrag; - __le32 mcastrxframe; - __le32 fcserror; - __le32 txframe; - __le32 wepundecryptable; -} __attribute__ ((packed)); - -struct cmd_ds_mac_control { - struct cmd_header hdr; - __le16 action; - u16 reserved; -} __attribute__ ((packed)); - -struct cmd_ds_mac_multicast_adr { - struct cmd_header hdr; - __le16 action; - __le16 nr_of_adrs; - u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; -} __attribute__ ((packed)); - -struct cmd_ds_gspi_bus_config { - struct cmd_header hdr; - __le16 action; - __le16 bus_delay_mode; - __le16 host_time_delay_to_read_port; - __le16 host_time_delay_to_read_register; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_authenticate { - struct cmd_header hdr; - - u8 bssid[ETH_ALEN]; - u8 authtype; - u8 reserved[10]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_deauthenticate { - struct cmd_header hdr; - - u8 macaddr[ETH_ALEN]; - __le16 reasoncode; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_associate { - struct cmd_header hdr; - - u8 bssid[6]; - __le16 capability; - __le16 listeninterval; - __le16 bcnperiod; - u8 dtimperiod; - u8 iebuf[512]; /* Enough for required and most optional IEs */ -} __attribute__ ((packed)); - -struct cmd_ds_802_11_associate_response { - struct cmd_header hdr; - - __le16 capability; - __le16 statuscode; - __le16 aid; - u8 iebuf[512]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_set_wep { - struct cmd_header hdr; - - /* ACT_ADD, ACT_REMOVE or ACT_ENABLE */ - __le16 action; - - /* key Index selected for Tx */ - __le16 keyindex; - - /* 40, 128bit or TXWEP */ - uint8_t keytype[4]; - uint8_t keymaterial[4][16]; -} __attribute__ ((packed)); - -struct cmd_ds_802_3_get_stat { - __le32 xmitok; - __le32 rcvok; - __le32 xmiterror; - __le32 rcverror; - __le32 rcvnobuffer; - __le32 rcvcrcerror; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_get_stat { - __le32 txfragmentcnt; - __le32 mcasttxframecnt; - __le32 failedcnt; - __le32 retrycnt; - __le32 Multipleretrycnt; - __le32 rtssuccesscnt; - __le32 rtsfailurecnt; - __le32 ackfailurecnt; - __le32 frameduplicatecnt; - __le32 rxfragmentcnt; - __le32 mcastrxframecnt; - __le32 fcserrorcnt; - __le32 bcasttxframecnt; - __le32 bcastrxframecnt; - __le32 txbeacon; - __le32 rxbeacon; - __le32 wepundecryptable; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_snmp_mib { - struct cmd_header hdr; - - __le16 action; - __le16 oid; - __le16 bufsize; - u8 value[128]; -} __attribute__ ((packed)); - -struct cmd_ds_mac_reg_map { - __le16 buffersize; - u8 regmap[128]; - __le16 reserved; -} __attribute__ ((packed)); - -struct cmd_ds_bbp_reg_map { - __le16 buffersize; - u8 regmap[128]; - __le16 reserved; -} __attribute__ ((packed)); - -struct cmd_ds_rf_reg_map { - __le16 buffersize; - u8 regmap[64]; - __le16 reserved; -} __attribute__ ((packed)); - -struct cmd_ds_mac_reg_access { - __le16 action; - __le16 offset; - __le32 value; -} __attribute__ ((packed)); - -struct cmd_ds_bbp_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __attribute__ ((packed)); - -struct cmd_ds_rf_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_radio_control { - struct cmd_header hdr; - - __le16 action; - __le16 control; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_beacon_control { - __le16 action; - __le16 beacon_enable; - __le16 beacon_period; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_sleep_params { - struct cmd_header hdr; - - /* ACT_GET/ACT_SET */ - __le16 action; - - /* Sleep clock error in ppm */ - __le16 error; - - /* Wakeup offset in usec */ - __le16 offset; - - /* Clock stabilization time in usec */ - __le16 stabletime; - - /* control periodic calibration */ - uint8_t calcontrol; - - /* control the use of external sleep clock */ - uint8_t externalsleepclk; - - /* reserved field, should be set to zero */ - __le16 reserved; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_inactivity_timeout { - struct cmd_header hdr; - - /* ACT_GET/ACT_SET */ - __le16 action; - - /* Inactivity timeout in msec */ - __le16 timeout; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_rf_channel { - struct cmd_header hdr; - - __le16 action; - __le16 channel; - __le16 rftype; /* unused */ - __le16 reserved; /* unused */ - u8 channellist[32]; /* unused */ -} __attribute__ ((packed)); - -struct cmd_ds_802_11_rssi { - /* weighting factor */ - __le16 N; - - __le16 reserved_0; - __le16 reserved_1; - __le16 reserved_2; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_rssi_rsp { - __le16 SNR; - __le16 noisefloor; - __le16 avgSNR; - __le16 avgnoisefloor; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_mac_address { - struct cmd_header hdr; - - __le16 action; - u8 macadd[ETH_ALEN]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_rf_tx_power { - struct cmd_header hdr; - - __le16 action; - __le16 curlevel; - s8 maxlevel; - s8 minlevel; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_rf_antenna { - __le16 action; - - /* Number of antennas or 0xffff(diversity) */ - __le16 antennamode; - -} __attribute__ ((packed)); - -struct cmd_ds_802_11_monitor_mode { - __le16 action; - __le16 mode; -} __attribute__ ((packed)); - -struct cmd_ds_set_boot2_ver { - struct cmd_header hdr; - - __le16 action; - __le16 version; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_fw_wake_method { - struct cmd_header hdr; - - __le16 action; - __le16 method; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_sleep_period { - struct cmd_header hdr; - - __le16 action; - __le16 period; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_ps_mode { - __le16 action; - __le16 nullpktinterval; - __le16 multipledtim; - __le16 reserved; - __le16 locallisteninterval; -} __attribute__ ((packed)); - -struct cmd_confirm_sleep { - struct cmd_header hdr; - - __le16 action; - __le16 nullpktinterval; - __le16 multipledtim; - __le16 reserved; - __le16 locallisteninterval; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_data_rate { - struct cmd_header hdr; - - __le16 action; - __le16 reserved; - u8 rates[MAX_RATES]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_rate_adapt_rateset { - struct cmd_header hdr; - __le16 action; - __le16 enablehwauto; - __le16 bitmap; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_ad_hoc_start { - struct cmd_header hdr; - - u8 ssid[IW_ESSID_MAX_SIZE]; - u8 bsstype; - __le16 beaconperiod; - u8 dtimperiod; /* Reserved on v9 and later */ - struct ieee_ie_ibss_param_set ibss; - u8 reserved1[4]; - struct ieee_ie_ds_param_set ds; - u8 reserved2[4]; - __le16 probedelay; /* Reserved on v9 and later */ - __le16 capability; - u8 rates[MAX_RATES]; - u8 tlv_memory_size_pad[100]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_ad_hoc_result { - struct cmd_header hdr; - - u8 pad[3]; - u8 bssid[ETH_ALEN]; -} __attribute__ ((packed)); - -struct adhoc_bssdesc { - u8 bssid[ETH_ALEN]; - u8 ssid[IW_ESSID_MAX_SIZE]; - u8 type; - __le16 beaconperiod; - u8 dtimperiod; - __le64 timestamp; - __le64 localtime; - struct ieee_ie_ds_param_set ds; - u8 reserved1[4]; - struct ieee_ie_ibss_param_set ibss; - u8 reserved2[4]; - __le16 capability; - u8 rates[MAX_RATES]; - - /* DO NOT ADD ANY FIELDS TO THIS STRUCTURE. It is used below in the - * Adhoc join command and will cause a binary layout mismatch with - * the firmware - */ -} __attribute__ ((packed)); - -struct cmd_ds_802_11_ad_hoc_join { - struct cmd_header hdr; - - struct adhoc_bssdesc bss; - __le16 failtimeout; /* Reserved on v9 and later */ - __le16 probedelay; /* Reserved on v9 and later */ -} __attribute__ ((packed)); - -struct cmd_ds_802_11_ad_hoc_stop { - struct cmd_header hdr; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_enable_rsn { - struct cmd_header hdr; - - __le16 action; - __le16 enable; -} __attribute__ ((packed)); - -struct MrvlIEtype_keyParamSet { - /* type ID */ - __le16 type; - - /* length of Payload */ - __le16 length; - - /* type of key: WEP=0, TKIP=1, AES=2 */ - __le16 keytypeid; - - /* key control Info specific to a keytypeid */ - __le16 keyinfo; - - /* length of key */ - __le16 keylen; - - /* key material of size keylen */ - u8 key[32]; -} __attribute__ ((packed)); - -#define MAX_WOL_RULES 16 - -struct host_wol_rule { - uint8_t rule_no; - uint8_t rule_ops; - __le16 sig_offset; - __le16 sig_length; - __le16 reserve; - __be32 sig_mask; - __be32 signature; -} __attribute__ ((packed)); - -struct wol_config { - uint8_t action; - uint8_t pattern; - uint8_t no_rules_in_cmd; - uint8_t result; - struct host_wol_rule rule[MAX_WOL_RULES]; -} __attribute__ ((packed)); - -struct cmd_ds_host_sleep { - struct cmd_header hdr; - __le32 criteria; - uint8_t gpio; - uint16_t gap; - struct wol_config wol_conf; -} __attribute__ ((packed)); - - - -struct cmd_ds_802_11_key_material { - struct cmd_header hdr; - - __le16 action; - struct MrvlIEtype_keyParamSet keyParamSet[2]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_eeprom_access { - struct cmd_header hdr; - __le16 action; - __le16 offset; - __le16 len; - /* firmware says it returns a maximum of 20 bytes */ -#define LBS_EEPROM_READ_LEN 20 - u8 value[LBS_EEPROM_READ_LEN]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_tpc_cfg { - struct cmd_header hdr; - - __le16 action; - uint8_t enable; - int8_t P0; - int8_t P1; - int8_t P2; - uint8_t usesnr; -} __attribute__ ((packed)); - - -struct cmd_ds_802_11_pa_cfg { - struct cmd_header hdr; - - __le16 action; - uint8_t enable; - int8_t P0; - int8_t P1; - int8_t P2; -} __attribute__ ((packed)); - - -struct cmd_ds_802_11_led_ctrl { - __le16 action; - __le16 numled; - u8 data[256]; -} __attribute__ ((packed)); - -struct cmd_ds_802_11_afc { - __le16 afc_auto; - union { - struct { - __le16 threshold; - __le16 period; - }; - struct { - __le16 timing_offset; /* signed */ - __le16 carrier_offset; /* signed */ - }; - }; -} __attribute__ ((packed)); - -struct cmd_tx_rate_query { - __le16 txrate; -} __attribute__ ((packed)); - -struct cmd_ds_get_tsf { - __le64 tsfvalue; -} __attribute__ ((packed)); - -struct cmd_ds_bt_access { - __le16 action; - __le32 id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; -} __attribute__ ((packed)); - -struct cmd_ds_fwt_access { - __le16 action; - __le32 id; - u8 valid; - u8 da[ETH_ALEN]; - u8 dir; - u8 ra[ETH_ALEN]; - __le32 ssn; - __le32 dsn; - __le32 metric; - u8 rate; - u8 hopcount; - u8 ttl; - __le32 expiration; - u8 sleepmode; - __le32 snr; - __le32 references; - u8 prec[ETH_ALEN]; -} __attribute__ ((packed)); - - -struct cmd_ds_mesh_config { - struct cmd_header hdr; - - __le16 action; - __le16 channel; - __le16 type; - __le16 length; - u8 data[128]; /* last position reserved */ -} __attribute__ ((packed)); - - -struct cmd_ds_mesh_access { - struct cmd_header hdr; - - __le16 action; - __le32 data[32]; /* last position reserved */ -} __attribute__ ((packed)); - -/* Number of stats counters returned by the firmware */ -#define MESH_STATS_NUM 8 - -struct cmd_ds_command { - /* command header */ - __le16 command; - __le16 size; - __le16 seqnum; - __le16 result; - - /* command Body */ - union { - struct cmd_ds_802_11_ps_mode psmode; - struct cmd_ds_802_11_get_stat gstat; - struct cmd_ds_802_3_get_stat gstat_8023; - struct cmd_ds_802_11_rf_antenna rant; - struct cmd_ds_802_11_monitor_mode monitor; - struct cmd_ds_802_11_rssi rssi; - struct cmd_ds_802_11_rssi_rsp rssirsp; - struct cmd_ds_mac_reg_access macreg; - struct cmd_ds_bbp_reg_access bbpreg; - struct cmd_ds_rf_reg_access rfreg; - - struct cmd_ds_802_11d_domain_info domaininfo; - struct cmd_ds_802_11d_domain_info domaininforesp; - - struct cmd_ds_802_11_tpc_cfg tpccfg; - struct cmd_ds_802_11_afc afc; - struct cmd_ds_802_11_led_ctrl ledgpio; - - struct cmd_tx_rate_query txrate; - struct cmd_ds_bt_access bt; - struct cmd_ds_fwt_access fwt; - struct cmd_ds_get_tsf gettsf; - struct cmd_ds_802_11_beacon_control bcn_ctrl; - } params; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/net/wireless/libertas/if_cs.c b/drivers/net/wireless/libertas/if_cs.c deleted file mode 100644 index 62381768f2d5..000000000000 --- a/drivers/net/wireless/libertas/if_cs.c +++ /dev/null @@ -1,1052 +0,0 @@ -/* - - Driver for the Marvell 8385 based compact flash WLAN cards. - - (C) 2007 by Holger Schurig - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include - -#define DRV_NAME "libertas_cs" - -#include "decl.h" -#include "defs.h" -#include "dev.h" - - -/********************************************************************/ -/* Module stuff */ -/********************************************************************/ - -MODULE_AUTHOR("Holger Schurig "); -MODULE_DESCRIPTION("Driver for Marvell 83xx compact flash WLAN cards"); -MODULE_LICENSE("GPL"); - - - -/********************************************************************/ -/* Data structures */ -/********************************************************************/ - -struct if_cs_card { - struct pcmcia_device *p_dev; - struct lbs_private *priv; - void __iomem *iobase; - bool align_regs; -}; - - - -/********************************************************************/ -/* Hardware access */ -/********************************************************************/ - -/* This define enables wrapper functions which allow you - to dump all register accesses. You normally won't this, - except for development */ -/* #define DEBUG_IO */ - -#ifdef DEBUG_IO -static int debug_output = 0; -#else -/* This way the compiler optimizes the printk's away */ -#define debug_output 0 -#endif - -static inline unsigned int if_cs_read8(struct if_cs_card *card, uint reg) -{ - unsigned int val = ioread8(card->iobase + reg); - if (debug_output) - printk(KERN_INFO "inb %08x<%02x\n", reg, val); - return val; -} -static inline unsigned int if_cs_read16(struct if_cs_card *card, uint reg) -{ - unsigned int val = ioread16(card->iobase + reg); - if (debug_output) - printk(KERN_INFO "inw %08x<%04x\n", reg, val); - return val; -} -static inline void if_cs_read16_rep( - struct if_cs_card *card, - uint reg, - void *buf, - unsigned long count) -{ - if (debug_output) - printk(KERN_INFO "insw %08x<(0x%lx words)\n", - reg, count); - ioread16_rep(card->iobase + reg, buf, count); -} - -static inline void if_cs_write8(struct if_cs_card *card, uint reg, u8 val) -{ - if (debug_output) - printk(KERN_INFO "outb %08x>%02x\n", reg, val); - iowrite8(val, card->iobase + reg); -} - -static inline void if_cs_write16(struct if_cs_card *card, uint reg, u16 val) -{ - if (debug_output) - printk(KERN_INFO "outw %08x>%04x\n", reg, val); - iowrite16(val, card->iobase + reg); -} - -static inline void if_cs_write16_rep( - struct if_cs_card *card, - uint reg, - const void *buf, - unsigned long count) -{ - if (debug_output) - printk(KERN_INFO "outsw %08x>(0x%lx words)\n", - reg, count); - iowrite16_rep(card->iobase + reg, buf, count); -} - - -/* - * I know that polling/delaying is frowned upon. However, this procedure - * with polling is needed while downloading the firmware. At this stage, - * the hardware does unfortunately not create any interrupts. - * - * Fortunately, this function is never used once the firmware is in - * the card. :-) - * - * As a reference, see the "Firmware Specification v5.1", page 18 - * and 19. I did not follow their suggested timing to the word, - * but this works nice & fast anyway. - */ -static int if_cs_poll_while_fw_download(struct if_cs_card *card, uint addr, u8 reg) -{ - int i; - - for (i = 0; i < 100000; i++) { - u8 val = if_cs_read8(card, addr); - if (val == reg) - return 0; - udelay(5); - } - return -ETIME; -} - - - -/* - * First the bitmasks for the host/card interrupt/status registers: - */ -#define IF_CS_BIT_TX 0x0001 -#define IF_CS_BIT_RX 0x0002 -#define IF_CS_BIT_COMMAND 0x0004 -#define IF_CS_BIT_RESP 0x0008 -#define IF_CS_BIT_EVENT 0x0010 -#define IF_CS_BIT_MASK 0x001f - - - -/* - * It's not really clear to me what the host status register is for. It - * needs to be set almost in union with "host int cause". The following - * bits from above are used: - * - * IF_CS_BIT_TX driver downloaded a data packet - * IF_CS_BIT_RX driver got a data packet - * IF_CS_BIT_COMMAND driver downloaded a command - * IF_CS_BIT_RESP not used (has some meaning with powerdown) - * IF_CS_BIT_EVENT driver read a host event - */ -#define IF_CS_HOST_STATUS 0x00000000 - -/* - * With the host int cause register can the host (that is, Linux) cause - * an interrupt in the firmware, to tell the firmware about those events: - * - * IF_CS_BIT_TX a data packet has been downloaded - * IF_CS_BIT_RX a received data packet has retrieved - * IF_CS_BIT_COMMAND a firmware block or a command has been downloaded - * IF_CS_BIT_RESP not used (has some meaning with powerdown) - * IF_CS_BIT_EVENT a host event (link lost etc) has been retrieved - */ -#define IF_CS_HOST_INT_CAUSE 0x00000002 - -/* - * The host int mask register is used to enable/disable interrupt. However, - * I have the suspicion that disabled interrupts are lost. - */ -#define IF_CS_HOST_INT_MASK 0x00000004 - -/* - * Used to send or receive data packets: - */ -#define IF_CS_WRITE 0x00000016 -#define IF_CS_WRITE_LEN 0x00000014 -#define IF_CS_READ 0x00000010 -#define IF_CS_READ_LEN 0x00000024 - -/* - * Used to send commands (and to send firmware block) and to - * receive command responses: - */ -#define IF_CS_CMD 0x0000001A -#define IF_CS_CMD_LEN 0x00000018 -#define IF_CS_RESP 0x00000012 -#define IF_CS_RESP_LEN 0x00000030 - -/* - * The card status registers shows what the card/firmware actually - * accepts: - * - * IF_CS_BIT_TX you may send a data packet - * IF_CS_BIT_RX you may retrieve a data packet - * IF_CS_BIT_COMMAND you may send a command - * IF_CS_BIT_RESP you may retrieve a command response - * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc) - * - * When reading this register several times, you will get back the same - * results --- with one exception: the IF_CS_BIT_EVENT clear itself - * automatically. - * - * Not that we don't rely on BIT_RX,_BIT_RESP or BIT_EVENT because - * we handle this via the card int cause register. - */ -#define IF_CS_CARD_STATUS 0x00000020 -#define IF_CS_CARD_STATUS_MASK 0x7f00 - -/* - * The card int cause register is used by the card/firmware to notify us - * about the following events: - * - * IF_CS_BIT_TX a data packet has successfully been sentx - * IF_CS_BIT_RX a data packet has been received and can be retrieved - * IF_CS_BIT_COMMAND not used - * IF_CS_BIT_RESP the firmware has a command response for us - * IF_CS_BIT_EVENT the card has a event for use (link lost, snr low etc) - */ -#define IF_CS_CARD_INT_CAUSE 0x00000022 - -/* - * This is used to for handshaking with the card's bootloader/helper image - * to synchronize downloading of firmware blocks. - */ -#define IF_CS_SQ_READ_LOW 0x00000028 -#define IF_CS_SQ_HELPER_OK 0x10 - -/* - * The scratch register tells us ... - * - * IF_CS_SCRATCH_BOOT_OK the bootloader runs - * IF_CS_SCRATCH_HELPER_OK the helper firmware already runs - */ -#define IF_CS_SCRATCH 0x0000003F -#define IF_CS_SCRATCH_BOOT_OK 0x00 -#define IF_CS_SCRATCH_HELPER_OK 0x5a - -/* - * Used to detect ancient chips: - */ -#define IF_CS_PRODUCT_ID 0x0000001C -#define IF_CS_CF8385_B1_REV 0x12 -#define IF_CS_CF8381_B3_REV 0x04 -#define IF_CS_CF8305_B1_REV 0x03 - -/* - * Used to detect other cards than CF8385 since their revisions of silicon - * doesn't match those from CF8385, eg. CF8381 B3 works with this driver. - */ -#define CF8305_MANFID 0x02db -#define CF8305_CARDID 0x8103 -#define CF8381_MANFID 0x02db -#define CF8381_CARDID 0x6064 -#define CF8385_MANFID 0x02df -#define CF8385_CARDID 0x8103 - -static inline int if_cs_hw_is_cf8305(struct pcmcia_device *p_dev) -{ - return (p_dev->manf_id == CF8305_MANFID && - p_dev->card_id == CF8305_CARDID); -} - -static inline int if_cs_hw_is_cf8381(struct pcmcia_device *p_dev) -{ - return (p_dev->manf_id == CF8381_MANFID && - p_dev->card_id == CF8381_CARDID); -} - -static inline int if_cs_hw_is_cf8385(struct pcmcia_device *p_dev) -{ - return (p_dev->manf_id == CF8385_MANFID && - p_dev->card_id == CF8385_CARDID); -} - -/********************************************************************/ -/* I/O and interrupt handling */ -/********************************************************************/ - -static inline void if_cs_enable_ints(struct if_cs_card *card) -{ - lbs_deb_enter(LBS_DEB_CS); - if_cs_write16(card, IF_CS_HOST_INT_MASK, 0); -} - -static inline void if_cs_disable_ints(struct if_cs_card *card) -{ - lbs_deb_enter(LBS_DEB_CS); - if_cs_write16(card, IF_CS_HOST_INT_MASK, IF_CS_BIT_MASK); -} - -/* - * Called from if_cs_host_to_card to send a command to the hardware - */ -static int if_cs_send_cmd(struct lbs_private *priv, u8 *buf, u16 nb) -{ - struct if_cs_card *card = (struct if_cs_card *)priv->card; - int ret = -1; - int loops = 0; - - lbs_deb_enter(LBS_DEB_CS); - if_cs_disable_ints(card); - - /* Is hardware ready? */ - while (1) { - u16 status = if_cs_read16(card, IF_CS_CARD_STATUS); - if (status & IF_CS_BIT_COMMAND) - break; - if (++loops > 100) { - lbs_pr_err("card not ready for commands\n"); - goto done; - } - mdelay(1); - } - - if_cs_write16(card, IF_CS_CMD_LEN, nb); - - if_cs_write16_rep(card, IF_CS_CMD, buf, nb / 2); - /* Are we supposed to transfer an odd amount of bytes? */ - if (nb & 1) - if_cs_write8(card, IF_CS_CMD, buf[nb-1]); - - /* "Assert the download over interrupt command in the Host - * status register" */ - if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); - - /* "Assert the download over interrupt command in the Card - * interrupt case register" */ - if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); - ret = 0; - -done: - if_cs_enable_ints(card); - lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); - return ret; -} - -/* - * Called from if_cs_host_to_card to send a data to the hardware - */ -static void if_cs_send_data(struct lbs_private *priv, u8 *buf, u16 nb) -{ - struct if_cs_card *card = (struct if_cs_card *)priv->card; - u16 status; - - lbs_deb_enter(LBS_DEB_CS); - if_cs_disable_ints(card); - - status = if_cs_read16(card, IF_CS_CARD_STATUS); - BUG_ON((status & IF_CS_BIT_TX) == 0); - - if_cs_write16(card, IF_CS_WRITE_LEN, nb); - - /* write even number of bytes, then odd byte if necessary */ - if_cs_write16_rep(card, IF_CS_WRITE, buf, nb / 2); - if (nb & 1) - if_cs_write8(card, IF_CS_WRITE, buf[nb-1]); - - if_cs_write16(card, IF_CS_HOST_STATUS, IF_CS_BIT_TX); - if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_TX); - if_cs_enable_ints(card); - - lbs_deb_leave(LBS_DEB_CS); -} - -/* - * Get the command result out of the card. - */ -static int if_cs_receive_cmdres(struct lbs_private *priv, u8 *data, u32 *len) -{ - unsigned long flags; - int ret = -1; - u16 status; - - lbs_deb_enter(LBS_DEB_CS); - - /* is hardware ready? */ - status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); - if ((status & IF_CS_BIT_RESP) == 0) { - lbs_pr_err("no cmd response in card\n"); - *len = 0; - goto out; - } - - *len = if_cs_read16(priv->card, IF_CS_RESP_LEN); - if ((*len == 0) || (*len > LBS_CMD_BUFFER_SIZE)) { - lbs_pr_err("card cmd buffer has invalid # of bytes (%d)\n", *len); - goto out; - } - - /* read even number of bytes, then odd byte if necessary */ - if_cs_read16_rep(priv->card, IF_CS_RESP, data, *len/sizeof(u16)); - if (*len & 1) - data[*len-1] = if_cs_read8(priv->card, IF_CS_RESP); - - /* This is a workaround for a firmware that reports too much - * bytes */ - *len -= 8; - ret = 0; - - /* Clear this flag again */ - spin_lock_irqsave(&priv->driver_lock, flags); - priv->dnld_sent = DNLD_RES_RECEIVED; - spin_unlock_irqrestore(&priv->driver_lock, flags); - -out: - lbs_deb_leave_args(LBS_DEB_CS, "ret %d, len %d", ret, *len); - return ret; -} - -static struct sk_buff *if_cs_receive_data(struct lbs_private *priv) -{ - struct sk_buff *skb = NULL; - u16 len; - u8 *data; - - lbs_deb_enter(LBS_DEB_CS); - - len = if_cs_read16(priv->card, IF_CS_READ_LEN); - if (len == 0 || len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - lbs_pr_err("card data buffer has invalid # of bytes (%d)\n", len); - priv->dev->stats.rx_dropped++; - goto dat_err; - } - - skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + 2); - if (!skb) - goto out; - skb_put(skb, len); - skb_reserve(skb, 2);/* 16 byte align */ - data = skb->data; - - /* read even number of bytes, then odd byte if necessary */ - if_cs_read16_rep(priv->card, IF_CS_READ, data, len/sizeof(u16)); - if (len & 1) - data[len-1] = if_cs_read8(priv->card, IF_CS_READ); - -dat_err: - if_cs_write16(priv->card, IF_CS_HOST_STATUS, IF_CS_BIT_RX); - if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_RX); - -out: - lbs_deb_leave_args(LBS_DEB_CS, "ret %p", skb); - return skb; -} - -static irqreturn_t if_cs_interrupt(int irq, void *data) -{ - struct if_cs_card *card = data; - struct lbs_private *priv = card->priv; - u16 cause; - - lbs_deb_enter(LBS_DEB_CS); - - /* Ask card interrupt cause register if there is something for us */ - cause = if_cs_read16(card, IF_CS_CARD_INT_CAUSE); - lbs_deb_cs("cause 0x%04x\n", cause); - - if (cause == 0) { - /* Not for us */ - return IRQ_NONE; - } - - if (cause == 0xffff) { - /* Read in junk, the card has probably been removed */ - card->priv->surpriseremoved = 1; - return IRQ_HANDLED; - } - - if (cause & IF_CS_BIT_RX) { - struct sk_buff *skb; - lbs_deb_cs("rx packet\n"); - skb = if_cs_receive_data(priv); - if (skb) - lbs_process_rxed_packet(priv, skb); - } - - if (cause & IF_CS_BIT_TX) { - lbs_deb_cs("tx done\n"); - lbs_host_to_card_done(priv); - } - - if (cause & IF_CS_BIT_RESP) { - unsigned long flags; - u8 i; - - lbs_deb_cs("cmd resp\n"); - spin_lock_irqsave(&priv->driver_lock, flags); - i = (priv->resp_idx == 0) ? 1 : 0; - spin_unlock_irqrestore(&priv->driver_lock, flags); - - BUG_ON(priv->resp_len[i]); - if_cs_receive_cmdres(priv, priv->resp_buf[i], - &priv->resp_len[i]); - - spin_lock_irqsave(&priv->driver_lock, flags); - lbs_notify_command_response(priv, i); - spin_unlock_irqrestore(&priv->driver_lock, flags); - } - - if (cause & IF_CS_BIT_EVENT) { - u16 status = if_cs_read16(priv->card, IF_CS_CARD_STATUS); - if_cs_write16(priv->card, IF_CS_HOST_INT_CAUSE, - IF_CS_BIT_EVENT); - lbs_queue_event(priv, (status & IF_CS_CARD_STATUS_MASK) >> 8); - } - - /* Clear interrupt cause */ - if_cs_write16(card, IF_CS_CARD_INT_CAUSE, cause & IF_CS_BIT_MASK); - - lbs_deb_leave(LBS_DEB_CS); - return IRQ_HANDLED; -} - - - - -/********************************************************************/ -/* Firmware */ -/********************************************************************/ - -/* - * Tries to program the helper firmware. - * - * Return 0 on success - */ -static int if_cs_prog_helper(struct if_cs_card *card) -{ - int ret = 0; - int sent = 0; - u8 scratch; - const struct firmware *fw; - - lbs_deb_enter(LBS_DEB_CS); - - /* - * This is the only place where an unaligned register access happens on - * the CF8305 card, therefore for the sake of speed of the driver, we do - * the alignment correction here. - */ - if (card->align_regs) - scratch = if_cs_read16(card, IF_CS_SCRATCH) >> 8; - else - scratch = if_cs_read8(card, IF_CS_SCRATCH); - - /* "If the value is 0x5a, the firmware is already - * downloaded successfully" - */ - if (scratch == IF_CS_SCRATCH_HELPER_OK) - goto done; - - /* "If the value is != 00, it is invalid value of register */ - if (scratch != IF_CS_SCRATCH_BOOT_OK) { - ret = -ENODEV; - goto done; - } - - /* TODO: make firmware file configurable */ - ret = request_firmware(&fw, "libertas_cs_helper.fw", - &handle_to_dev(card->p_dev)); - if (ret) { - lbs_pr_err("can't load helper firmware\n"); - ret = -ENODEV; - goto done; - } - lbs_deb_cs("helper size %td\n", fw->size); - - /* "Set the 5 bytes of the helper image to 0" */ - /* Not needed, this contains an ARM branch instruction */ - - for (;;) { - /* "the number of bytes to send is 256" */ - int count = 256; - int remain = fw->size - sent; - - if (remain < count) - count = remain; - - /* "write the number of bytes to be sent to the I/O Command - * write length register" */ - if_cs_write16(card, IF_CS_CMD_LEN, count); - - /* "write this to I/O Command port register as 16 bit writes */ - if (count) - if_cs_write16_rep(card, IF_CS_CMD, - &fw->data[sent], - count >> 1); - - /* "Assert the download over interrupt command in the Host - * status register" */ - if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); - - /* "Assert the download over interrupt command in the Card - * interrupt case register" */ - if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); - - /* "The host polls the Card Status register ... for 50 ms before - declaring a failure */ - ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, - IF_CS_BIT_COMMAND); - if (ret < 0) { - lbs_pr_err("can't download helper at 0x%x, ret %d\n", - sent, ret); - goto err_release; - } - - if (count == 0) - break; - - sent += count; - } - -err_release: - release_firmware(fw); -done: - lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); - return ret; -} - - -static int if_cs_prog_real(struct if_cs_card *card) -{ - const struct firmware *fw; - int ret = 0; - int retry = 0; - int len = 0; - int sent; - - lbs_deb_enter(LBS_DEB_CS); - - /* TODO: make firmware file configurable */ - ret = request_firmware(&fw, "libertas_cs.fw", - &handle_to_dev(card->p_dev)); - if (ret) { - lbs_pr_err("can't load firmware\n"); - ret = -ENODEV; - goto done; - } - lbs_deb_cs("fw size %td\n", fw->size); - - ret = if_cs_poll_while_fw_download(card, IF_CS_SQ_READ_LOW, - IF_CS_SQ_HELPER_OK); - if (ret < 0) { - lbs_pr_err("helper firmware doesn't answer\n"); - goto err_release; - } - - for (sent = 0; sent < fw->size; sent += len) { - len = if_cs_read16(card, IF_CS_SQ_READ_LOW); - if (len & 1) { - retry++; - lbs_pr_info("odd, need to retry this firmware block\n"); - } else { - retry = 0; - } - - if (retry > 20) { - lbs_pr_err("could not download firmware\n"); - ret = -ENODEV; - goto err_release; - } - if (retry) { - sent -= len; - } - - - if_cs_write16(card, IF_CS_CMD_LEN, len); - - if_cs_write16_rep(card, IF_CS_CMD, - &fw->data[sent], - (len+1) >> 1); - if_cs_write8(card, IF_CS_HOST_STATUS, IF_CS_BIT_COMMAND); - if_cs_write16(card, IF_CS_HOST_INT_CAUSE, IF_CS_BIT_COMMAND); - - ret = if_cs_poll_while_fw_download(card, IF_CS_CARD_STATUS, - IF_CS_BIT_COMMAND); - if (ret < 0) { - lbs_pr_err("can't download firmware at 0x%x\n", sent); - goto err_release; - } - } - - ret = if_cs_poll_while_fw_download(card, IF_CS_SCRATCH, 0x5a); - if (ret < 0) - lbs_pr_err("firmware download failed\n"); - -err_release: - release_firmware(fw); - -done: - lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); - return ret; -} - - - -/********************************************************************/ -/* Callback functions for libertas.ko */ -/********************************************************************/ - -/* Send commands or data packets to the card */ -static int if_cs_host_to_card(struct lbs_private *priv, - u8 type, - u8 *buf, - u16 nb) -{ - int ret = -1; - - lbs_deb_enter_args(LBS_DEB_CS, "type %d, bytes %d", type, nb); - - switch (type) { - case MVMS_DAT: - priv->dnld_sent = DNLD_DATA_SENT; - if_cs_send_data(priv, buf, nb); - ret = 0; - break; - case MVMS_CMD: - priv->dnld_sent = DNLD_CMD_SENT; - ret = if_cs_send_cmd(priv, buf, nb); - break; - default: - lbs_pr_err("%s: unsupported type %d\n", __func__, type); - } - - lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); - return ret; -} - - -/********************************************************************/ -/* Card Services */ -/********************************************************************/ - -/* - * After a card is removed, if_cs_release() will unregister the - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void if_cs_release(struct pcmcia_device *p_dev) -{ - struct if_cs_card *card = p_dev->priv; - - lbs_deb_enter(LBS_DEB_CS); - - free_irq(p_dev->irq.AssignedIRQ, card); - pcmcia_disable_device(p_dev); - if (card->iobase) - ioport_unmap(card->iobase); - - lbs_deb_leave(LBS_DEB_CS); -} - - -/* - * This creates an "instance" of the driver, allocating local data - * structures for one device. The device is registered with Card - * Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a card - * insertion event. - */ -static int if_cs_probe(struct pcmcia_device *p_dev) -{ - int ret = -ENOMEM; - unsigned int prod_id; - struct lbs_private *priv; - struct if_cs_card *card; - /* CIS parsing */ - tuple_t tuple; - cisparse_t parse; - cistpl_cftable_entry_t *cfg = &parse.cftable_entry; - cistpl_io_t *io = &cfg->io; - u_char buf[64]; - - lbs_deb_enter(LBS_DEB_CS); - - card = kzalloc(sizeof(struct if_cs_card), GFP_KERNEL); - if (!card) { - lbs_pr_err("error in kzalloc\n"); - goto out; - } - card->p_dev = p_dev; - p_dev->priv = card; - - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING; - p_dev->irq.Handler = NULL; - p_dev->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; - - p_dev->conf.Attributes = 0; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - - tuple.Attributes = 0; - tuple.TupleData = buf; - tuple.TupleDataMax = sizeof(buf); - tuple.TupleOffset = 0; - - tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; - if ((ret = pcmcia_get_first_tuple(p_dev, &tuple)) != 0 || - (ret = pcmcia_get_tuple_data(p_dev, &tuple)) != 0 || - (ret = pcmcia_parse_tuple(&tuple, &parse)) != 0) - { - lbs_pr_err("error in pcmcia_get_first_tuple etc\n"); - goto out1; - } - - p_dev->conf.ConfigIndex = cfg->index; - - /* Do we need to allocate an interrupt? */ - if (cfg->irq.IRQInfo1) { - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - } - - /* IO window settings */ - if (cfg->io.nwin != 1) { - lbs_pr_err("wrong CIS (check number of IO windows)\n"); - ret = -ENODEV; - goto out1; - } - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - - /* This reserves IO space but doesn't actually enable it */ - ret = pcmcia_request_io(p_dev, &p_dev->io); - if (ret) { - lbs_pr_err("error in pcmcia_request_io\n"); - goto out1; - } - - /* - * Allocate an interrupt line. Note that this does not assign - * a handler to the interrupt, unless the 'Handler' member of - * the irq structure is initialized. - */ - if (p_dev->conf.Attributes & CONF_ENABLE_IRQ) { - ret = pcmcia_request_irq(p_dev, &p_dev->irq); - if (ret) { - lbs_pr_err("error in pcmcia_request_irq\n"); - goto out1; - } - } - - /* Initialize io access */ - card->iobase = ioport_map(p_dev->io.BasePort1, p_dev->io.NumPorts1); - if (!card->iobase) { - lbs_pr_err("error in ioport_map\n"); - ret = -EIO; - goto out1; - } - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping, and putting the - * card and host interface into "Memory and IO" mode. - */ - ret = pcmcia_request_configuration(p_dev, &p_dev->conf); - if (ret) { - lbs_pr_err("error in pcmcia_request_configuration\n"); - goto out2; - } - - /* Finally, report what we've done */ - lbs_deb_cs("irq %d, io 0x%04x-0x%04x\n", - p_dev->irq.AssignedIRQ, p_dev->io.BasePort1, - p_dev->io.BasePort1 + p_dev->io.NumPorts1 - 1); - - /* - * Most of the libertas cards can do unaligned register access, but some - * weird ones can not. That's especially true for the CF8305 card. - */ - card->align_regs = 0; - - /* Check if we have a current silicon */ - prod_id = if_cs_read8(card, IF_CS_PRODUCT_ID); - if (if_cs_hw_is_cf8305(p_dev)) { - card->align_regs = 1; - if (prod_id < IF_CS_CF8305_B1_REV) { - lbs_pr_err("old chips like 8305 rev B3 " - "aren't supported\n"); - ret = -ENODEV; - goto out2; - } - } - - if (if_cs_hw_is_cf8381(p_dev) && prod_id < IF_CS_CF8381_B3_REV) { - lbs_pr_err("old chips like 8381 rev B3 aren't supported\n"); - ret = -ENODEV; - goto out2; - } - - if (if_cs_hw_is_cf8385(p_dev) && prod_id < IF_CS_CF8385_B1_REV) { - lbs_pr_err("old chips like 8385 rev B1 aren't supported\n"); - ret = -ENODEV; - goto out2; - } - - /* Load the firmware early, before calling into libertas.ko */ - ret = if_cs_prog_helper(card); - if (ret == 0 && !if_cs_hw_is_cf8305(p_dev)) - ret = if_cs_prog_real(card); - if (ret) - goto out2; - - /* Make this card known to the libertas driver */ - priv = lbs_add_card(card, &p_dev->dev); - if (!priv) { - ret = -ENOMEM; - goto out2; - } - - /* Finish setting up fields in lbs_private */ - card->priv = priv; - priv->card = card; - priv->hw_host_to_card = if_cs_host_to_card; - priv->fw_ready = 1; - - /* Now actually get the IRQ */ - ret = request_irq(p_dev->irq.AssignedIRQ, if_cs_interrupt, - IRQF_SHARED, DRV_NAME, card); - if (ret) { - lbs_pr_err("error in request_irq\n"); - goto out3; - } - - /* Clear any interrupt cause that happend while sending - * firmware/initializing card */ - if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK); - if_cs_enable_ints(card); - - /* And finally bring the card up */ - if (lbs_start_card(priv) != 0) { - lbs_pr_err("could not activate card\n"); - goto out3; - } - - ret = 0; - goto out; - -out3: - lbs_remove_card(priv); -out2: - ioport_unmap(card->iobase); -out1: - pcmcia_disable_device(p_dev); -out: - lbs_deb_leave_args(LBS_DEB_CS, "ret %d", ret); - return ret; -} - - -/* - * This deletes a driver "instance". The device is de-registered with - * Card Services. If it has been released, all local data structures - * are freed. Otherwise, the structures will be freed when the device - * is released. - */ -static void if_cs_detach(struct pcmcia_device *p_dev) -{ - struct if_cs_card *card = p_dev->priv; - - lbs_deb_enter(LBS_DEB_CS); - - lbs_stop_card(card->priv); - lbs_remove_card(card->priv); - if_cs_disable_ints(card); - if_cs_release(p_dev); - kfree(card); - - lbs_deb_leave(LBS_DEB_CS); -} - - - -/********************************************************************/ -/* Module initialization */ -/********************************************************************/ - -static struct pcmcia_device_id if_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(CF8305_MANFID, CF8305_CARDID), - PCMCIA_DEVICE_MANF_CARD(CF8381_MANFID, CF8381_CARDID), - PCMCIA_DEVICE_MANF_CARD(CF8385_MANFID, CF8385_CARDID), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, if_cs_ids); - - -static struct pcmcia_driver lbs_driver = { - .owner = THIS_MODULE, - .drv = { - .name = DRV_NAME, - }, - .probe = if_cs_probe, - .remove = if_cs_detach, - .id_table = if_cs_ids, -}; - - -static int __init if_cs_init(void) -{ - int ret; - - lbs_deb_enter(LBS_DEB_CS); - ret = pcmcia_register_driver(&lbs_driver); - lbs_deb_leave(LBS_DEB_CS); - return ret; -} - - -static void __exit if_cs_exit(void) -{ - lbs_deb_enter(LBS_DEB_CS); - pcmcia_unregister_driver(&lbs_driver); - lbs_deb_leave(LBS_DEB_CS); -} - - -module_init(if_cs_init); -module_exit(if_cs_exit); diff --git a/drivers/net/wireless/libertas/if_sdio.h b/drivers/net/wireless/libertas/if_sdio.h deleted file mode 100644 index 60c9b2fcef03..000000000000 --- a/drivers/net/wireless/libertas/if_sdio.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * linux/drivers/net/wireless/libertas/if_sdio.h - * - * Copyright 2007 Pierre Ossman - * - * 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. - */ - -#ifndef _LBS_IF_SDIO_H -#define _LBS_IF_SDIO_H - -#define IF_SDIO_MODEL_8385 0x04 -#define IF_SDIO_MODEL_8686 0x0b -#define IF_SDIO_MODEL_8688 0x10 - -#define IF_SDIO_IOPORT 0x00 - -#define IF_SDIO_H_INT_MASK 0x04 -#define IF_SDIO_H_INT_OFLOW 0x08 -#define IF_SDIO_H_INT_UFLOW 0x04 -#define IF_SDIO_H_INT_DNLD 0x02 -#define IF_SDIO_H_INT_UPLD 0x01 - -#define IF_SDIO_H_INT_STATUS 0x05 -#define IF_SDIO_H_INT_RSR 0x06 -#define IF_SDIO_H_INT_STATUS2 0x07 - -#define IF_SDIO_RD_BASE 0x10 - -#define IF_SDIO_STATUS 0x20 -#define IF_SDIO_IO_RDY 0x08 -#define IF_SDIO_CIS_RDY 0x04 -#define IF_SDIO_UL_RDY 0x02 -#define IF_SDIO_DL_RDY 0x01 - -#define IF_SDIO_C_INT_MASK 0x24 -#define IF_SDIO_C_INT_STATUS 0x28 -#define IF_SDIO_C_INT_RSR 0x2C - -#define IF_SDIO_SCRATCH 0x34 -#define IF_SDIO_SCRATCH_OLD 0x80fe -#define IF_SDIO_FW_STATUS 0x40 -#define IF_SDIO_FIRMWARE_OK 0xfedc - -#define IF_SDIO_RX_LEN 0x42 -#define IF_SDIO_RX_UNIT 0x43 - -#define IF_SDIO_EVENT 0x80fc - -#define IF_SDIO_BLOCK_SIZE 256 - -#endif diff --git a/drivers/net/wireless/libertas/if_sdio1.c b/drivers/net/wireless/libertas/if_sdio1.c deleted file mode 100755 index 2f45d6a3269a..000000000000 --- a/drivers/net/wireless/libertas/if_sdio1.c +++ /dev/null @@ -1,1272 +0,0 @@ -/* - * linux/drivers/net/wireless/libertas/if_sdio.c - * - * Copyright 2007-2008 Pierre Ossman - * - * Inspired by if_cs.c, Copyright 2007 Holger Schurig - * - * 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 hardware has more or less no CMD53 support, so all registers - * must be accessed using sdio_readb()/sdio_writeb(). - * - * Transfers must be in one transaction or the firmware goes bonkers. - * This means that the transfer must either be small enough to do a - * byte based transfer or it must be padded to a multiple of the - * current block size. - * - * As SDIO is still new to the kernel, it is unfortunately common with - * bugs in the host controllers related to that. One such bug is that - * controllers cannot do transfers that aren't a multiple of 4 bytes. - * If you don't have time to fix the host controller driver, you can - * work around the problem by modifying if_sdio_host_to_card() and - * if_sdio_card_to_host() to pad the data. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "cmd.h" -#include "if_sdio.h" -#include "wifi_power.h" - -extern struct mmc_host *wifi_mmc_host; - -/* The if_sdio_remove() callback function is called when - * user removes this module from kernel space or ejects - * the card from the slot. The driver handles these 2 cases - * differently for SD8688 combo chip. - * If the user is removing the module, the FUNC_SHUTDOWN - * command for SD8688 is sent to the firmware. - * If the card is removed, there is no need to send this command. - * - * The variable 'user_rmmod' is used to distinguish these two - * scenarios. This flag is initialized as FALSE in case the card - * is removed, and will be set to TRUE for module removal when - * module_exit function is called. - */ -static u8 user_rmmod; - -struct sdio_func *wifi_sdio_func; - -EXPORT_SYMBOL(wifi_sdio_func); -static char *lbs_helper_name = NULL; -module_param_named(helper_name, lbs_helper_name, charp, 0644); - -static char *lbs_fw_name = NULL; -module_param_named(fw_name, lbs_fw_name, charp, 0644); - -static const struct sdio_device_id if_sdio_ids[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, - SDIO_DEVICE_ID_MARVELL_LIBERTAS) }, - { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, - SDIO_DEVICE_ID_MARVELL_8688WLAN) }, - { /* end: all zeroes */ }, -}; - -MODULE_DEVICE_TABLE(sdio, if_sdio_ids); - -struct if_sdio_model { - int model; - const char *helper; - const char *firmware; -}; - -static struct if_sdio_model if_sdio_models[] = { - { - /* 8385 */ - .model = IF_SDIO_MODEL_8385, - .helper = "sd8385_helper.bin", - .firmware = "sd8385.bin", - }, - { - /* 8686 */ - .model = IF_SDIO_MODEL_8686, - .helper = "sd8686_helper.bin", - .firmware = "sd8686.bin", - }, - { - /* 8688 */ - .model = IF_SDIO_MODEL_8688, - .helper = "sd8688_helper.bin", - .firmware = "sd8688.bin", - }, -}; - -struct if_sdio_packet { - struct if_sdio_packet *next; - u16 nb; - u8 buffer[0] __attribute__((aligned(4))); -}; - -struct if_sdio_card { - struct sdio_func *func; - struct lbs_private *priv; - - int model; - unsigned long ioport; - unsigned int scratch_reg; - - const char *helper; - const char *firmware; - - u8 buffer[65536]; - - spinlock_t lock; - struct if_sdio_packet *packets; - - struct workqueue_struct *workqueue; - struct work_struct packet_worker; - - u8 rx_unit; -}; - -/********************************************************************/ -/* I/O */ -/********************************************************************/ - -/* - * For SD8385/SD8686, this function reads firmware status after - * the image is downloaded, or reads RX packet length when - * interrupt (with IF_SDIO_H_INT_UPLD bit set) is received. - * For SD8688, this function reads firmware status only. - */ -static u16 if_sdio_read_scratch(struct if_sdio_card *card, int *err) -{ - int ret; - u16 scratch; - - scratch = sdio_readb(card->func, card->scratch_reg, &ret); - if (!ret) - scratch |= sdio_readb(card->func, card->scratch_reg + 1, - &ret) << 8; - - if (err) - *err = ret; - - if (ret) - return 0xffff; - - return scratch; -} - -static u8 if_sdio_read_rx_unit(struct if_sdio_card *card) -{ - int ret; - u8 rx_unit; - - rx_unit = sdio_readb(card->func, IF_SDIO_RX_UNIT, &ret); - - if (ret) - rx_unit = 0; - - return rx_unit; -} - -static u16 if_sdio_read_rx_len(struct if_sdio_card *card, int *err) -{ - int ret; - u16 rx_len; - - switch (card->model) { - case IF_SDIO_MODEL_8385: - case IF_SDIO_MODEL_8686: - rx_len = if_sdio_read_scratch(card, &ret); - break; - case IF_SDIO_MODEL_8688: - default: /* for newer chipsets */ - rx_len = sdio_readb(card->func, IF_SDIO_RX_LEN, &ret); - if (!ret) - rx_len <<= card->rx_unit; - else - rx_len = 0xffff; /* invalid length */ - - break; - } - - if (err) - *err = ret; - - return rx_len; -} - -static int if_sdio_handle_cmd(struct if_sdio_card *card, - u8 *buffer, unsigned size) -{ - struct lbs_private *priv = card->priv; - int ret; - unsigned long flags; - u8 i; - - lbs_deb_enter(LBS_DEB_SDIO); - - if (size > LBS_CMD_BUFFER_SIZE) { - lbs_deb_sdio("response packet too large (%d bytes)\n", - (int)size); - ret = -E2BIG; - goto out; - } - - spin_lock_irqsave(&priv->driver_lock, flags); - - i = (priv->resp_idx == 0) ? 1 : 0; - BUG_ON(priv->resp_len[i]); - priv->resp_len[i] = size; - memcpy(priv->resp_buf[i], buffer, size); - lbs_notify_command_response(priv, i); - - spin_unlock_irqrestore(&card->priv->driver_lock, flags); - - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - return ret; -} - -static int if_sdio_handle_data(struct if_sdio_card *card, - u8 *buffer, unsigned size) -{ - int ret; - struct sk_buff *skb; - char *data; - - lbs_deb_enter(LBS_DEB_SDIO); - - if (size > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - lbs_deb_sdio("response packet too large (%d bytes)\n", - (int)size); - ret = -E2BIG; - goto out; - } - - skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + NET_IP_ALIGN); - if (!skb) { - ret = -ENOMEM; - goto out; - } - - skb_reserve(skb, NET_IP_ALIGN); - - data = skb_put(skb, size); - - memcpy(data, buffer, size); - - lbs_process_rxed_packet(card->priv, skb); - - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -static int if_sdio_handle_event(struct if_sdio_card *card, - u8 *buffer, unsigned size) -{ - int ret; - u32 event; - - lbs_deb_enter(LBS_DEB_SDIO); - - if (card->model == IF_SDIO_MODEL_8385) { - event = sdio_readb(card->func, IF_SDIO_EVENT, &ret); - if (ret) - goto out; - - /* right shift 3 bits to get the event id */ - event >>= 3; - } else { - if (size < 4) { - lbs_deb_sdio("event packet too small (%d bytes)\n", - (int)size); - ret = -EINVAL; - goto out; - } - event = buffer[3] << 24; - event |= buffer[2] << 16; - event |= buffer[1] << 8; - event |= buffer[0] << 0; - } - - lbs_queue_event(card->priv, event & 0xFF); - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -static int if_sdio_card_to_host(struct if_sdio_card *card) -{ - int ret; - u8 status; - u16 size, type, chunk; - unsigned long timeout; - - lbs_deb_enter(LBS_DEB_SDIO); - - size = if_sdio_read_rx_len(card, &ret); - if (ret) - goto out; - - if (size < 4) { - lbs_deb_sdio("invalid packet size (%d bytes) from firmware\n", - (int)size); - ret = -EINVAL; - goto out; - } - - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto out; - if (status & IF_SDIO_IO_RDY) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto out; - } - mdelay(1); - } - - /* - * The transfer must be in one transaction or the firmware - * goes suicidal. There's no way to guarantee that for all - * controllers, but we can at least try. - */ - chunk = sdio_align_size(card->func, size); - - ret = sdio_readsb(card->func, card->buffer, card->ioport, chunk); - if (ret) - goto out; - - chunk = card->buffer[0] | (card->buffer[1] << 8); - type = card->buffer[2] | (card->buffer[3] << 8); - - lbs_deb_sdio("packet of type %d and size %d bytes\n", - (int)type, (int)chunk); - - if (chunk > size) { - lbs_deb_sdio("packet fragment (%d > %d)\n", - (int)chunk, (int)size); - ret = -EINVAL; - goto out; - } - - if (chunk < size) { - lbs_deb_sdio("packet fragment (%d < %d)\n", - (int)chunk, (int)size); - } - - switch (type) { - case MVMS_CMD: - ret = if_sdio_handle_cmd(card, card->buffer + 4, chunk - 4); - if (ret) - goto out; - break; - case MVMS_DAT: - ret = if_sdio_handle_data(card, card->buffer + 4, chunk - 4); - if (ret) - goto out; - break; - case MVMS_EVENT: - ret = if_sdio_handle_event(card, card->buffer + 4, chunk - 4); - if (ret) - goto out; - break; - default: - lbs_deb_sdio("invalid type (%d) from firmware\n", - (int)type); - ret = -EINVAL; - goto out; - } - -out: - if (ret) - lbs_pr_err("problem fetching packet from firmware\n"); - - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -static void if_sdio_host_to_card_worker(struct work_struct *work) -{ - struct if_sdio_card *card; - struct if_sdio_packet *packet; - unsigned long timeout; - u8 status; - int ret; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_SDIO); - - card = container_of(work, struct if_sdio_card, packet_worker); - - while (1) { - spin_lock_irqsave(&card->lock, flags); - packet = card->packets; - if (packet) - card->packets = packet->next; - spin_unlock_irqrestore(&card->lock, flags); - - if (!packet) - break; - - sdio_claim_host(card->func); - - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto release; - if (status & IF_SDIO_IO_RDY) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - mdelay(1); - } - - ret = sdio_writesb(card->func, card->ioport, - packet->buffer, packet->nb); - if (ret) - goto release; -release: - sdio_release_host(card->func); - - kfree(packet); - } - - lbs_deb_leave(LBS_DEB_SDIO); -} - -/********************************************************************/ -/* Firmware */ -/********************************************************************/ - -static int if_sdio_prog_helper(struct if_sdio_card *card) -{ - int ret; - u8 status; - const struct firmware *fw; - unsigned long timeout; - u8 *chunk_buffer; - u32 chunk_size; - const u8 *firmware; - size_t size; - - lbs_deb_enter(LBS_DEB_SDIO); - - ret = request_firmware(&fw, card->helper, &card->func->dev); - if (ret) { - lbs_pr_err("can't load helper firmware\n"); - goto out; - } - - chunk_buffer = kzalloc(64, GFP_KERNEL); - if (!chunk_buffer) { - ret = -ENOMEM; - goto release_fw; - } - - sdio_claim_host(card->func); - - ret = sdio_set_block_size(card->func, 32); - if (ret) - goto release; - - firmware = fw->data; - size = fw->size; - - while (size) { - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto release; - if ((status & IF_SDIO_IO_RDY) && - (status & IF_SDIO_DL_RDY)) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - mdelay(1); - } - - chunk_size = min(size, (size_t)60); - - *((__le32*)chunk_buffer) = cpu_to_le32(chunk_size); - memcpy(chunk_buffer + 4, firmware, chunk_size); -/* - lbs_deb_sdio("sending %d bytes chunk\n", chunk_size); -*/ - ret = sdio_writesb(card->func, card->ioport, - chunk_buffer, 64); - if (ret) - goto release; - - firmware += chunk_size; - size -= chunk_size; - } - - /* an empty block marks the end of the transfer */ - memset(chunk_buffer, 0, 4); - ret = sdio_writesb(card->func, card->ioport, chunk_buffer, 64); - if (ret) - goto release; - - //lbs_deb_sdio("waiting for helper to boot...\n"); - printk("waiting for helper to boot...\n"); - mdelay(3000); - - /* wait for the helper to boot by looking at the size register */ - timeout = jiffies + HZ; - while (1) { - u16 req_size; - - req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); - if (ret) - goto release; - - req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8; - if (ret) - goto release; - - if (req_size != 0) - break; - - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - - msleep(10); - } - - ret = 0; - -release: - sdio_release_host(card->func); - kfree(chunk_buffer); -release_fw: - release_firmware(fw); - -out: - if (ret) - //lbs_pr_err("failed to load helper firmware\n"); - printk("failed to load helper firmware\n"); - else - printk("succeed to load helper firmware\n"); - - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -static int if_sdio_prog_real(struct if_sdio_card *card) -{ - int ret; - u8 status; - const struct firmware *fw; - unsigned long timeout; - u8 *chunk_buffer; - u32 chunk_size; - const u8 *firmware; - size_t size, req_size; - - lbs_deb_enter(LBS_DEB_SDIO); - - ret = request_firmware(&fw, card->firmware, &card->func->dev); - if (ret) { - lbs_pr_err("can't load firmware\n"); - goto out; - } - - chunk_buffer = kzalloc(512, GFP_KERNEL); - if (!chunk_buffer) { - ret = -ENOMEM; - goto release_fw; - } - - sdio_claim_host(card->func); - - ret = sdio_set_block_size(card->func, 32); - if (ret) - goto release; - - firmware = fw->data; - size = fw->size; - - while (size) { - timeout = jiffies + HZ; - while (1) { - status = sdio_readb(card->func, IF_SDIO_STATUS, &ret); - if (ret) - goto release; - if ((status & IF_SDIO_IO_RDY) && - (status & IF_SDIO_DL_RDY)) - break; - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - mdelay(1); - } - - req_size = sdio_readb(card->func, IF_SDIO_RD_BASE, &ret); - if (ret) - goto release; - - req_size |= sdio_readb(card->func, IF_SDIO_RD_BASE + 1, &ret) << 8; - if (ret) - goto release; -/* - lbs_deb_sdio("firmware wants %d bytes\n", (int)req_size); -*/ - if (req_size == 0) { - lbs_deb_sdio("firmware helper gave up early\n"); - ret = -EIO; - goto release; - } - - if (req_size & 0x01) { - lbs_deb_sdio("firmware helper signalled error\n"); - ret = -EIO; - goto release; - } - - if (req_size > size) - req_size = size; - - while (req_size) { - chunk_size = min(req_size, (size_t)512); - - memcpy(chunk_buffer, firmware, chunk_size); -/* - lbs_deb_sdio("sending %d bytes (%d bytes) chunk\n", - chunk_size, (chunk_size + 31) / 32 * 32); -*/ - ret = sdio_writesb(card->func, card->ioport, - chunk_buffer, roundup(chunk_size, 32)); - if (ret) - goto release; - - firmware += chunk_size; - size -= chunk_size; - req_size -= chunk_size; - } - } - - ret = 0; - - lbs_deb_sdio("waiting for firmware to boot...\n"); - - /* wait for the firmware to boot */ - timeout = jiffies + HZ; - while (1) { - u16 scratch; - - scratch = if_sdio_read_scratch(card, &ret); - if (ret) - goto release; - - if (scratch == IF_SDIO_FIRMWARE_OK) - break; - - if (time_after(jiffies, timeout)) { - ret = -ETIMEDOUT; - goto release; - } - - msleep(10); - } - - ret = 0; - -release: - sdio_release_host(card->func); - kfree(chunk_buffer); -release_fw: - release_firmware(fw); - -out: - if (ret) - lbs_pr_err("failed to load firmware\n"); - - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -static int if_sdio_prog_firmware(struct if_sdio_card *card) -{ - int ret; - u16 scratch; - - lbs_deb_enter(LBS_DEB_SDIO); - - sdio_claim_host(card->func); - scratch = if_sdio_read_scratch(card, &ret); - sdio_release_host(card->func); - - if (ret) - goto out; - - lbs_deb_sdio("firmware status = %#x\n", scratch); - - if (scratch == IF_SDIO_FIRMWARE_OK) { - lbs_deb_sdio("firmware already loaded\n"); - goto success; - } - - ret = if_sdio_prog_helper(card); - if (ret) - goto out; - - ret = if_sdio_prog_real(card); - if (ret) - goto out; - -success: - sdio_claim_host(card->func); - sdio_set_block_size(card->func, IF_SDIO_BLOCK_SIZE); - sdio_release_host(card->func); - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -/*******************************************************************/ -/* Libertas callbacks */ -/*******************************************************************/ - -static int if_sdio_host_to_card(struct lbs_private *priv, - u8 type, u8 *buf, u16 nb) -{ - int ret; - struct if_sdio_card *card; - struct if_sdio_packet *packet, *cur; - u16 size; - unsigned long flags; - - lbs_deb_enter_args(LBS_DEB_SDIO, "type %d, bytes %d", type, nb); - - card = priv->card; - - if (nb > (65536 - sizeof(struct if_sdio_packet) - 4)) { - ret = -EINVAL; - goto out; - } - - /* - * The transfer must be in one transaction or the firmware - * goes suicidal. There's no way to guarantee that for all - * controllers, but we can at least try. - */ - size = sdio_align_size(card->func, nb + 4); - - packet = kzalloc(sizeof(struct if_sdio_packet) + size, - GFP_ATOMIC); - if (!packet) { - ret = -ENOMEM; - goto out; - } - - packet->next = NULL; - packet->nb = size; - - /* - * SDIO specific header. - */ - packet->buffer[0] = (nb + 4) & 0xff; - packet->buffer[1] = ((nb + 4) >> 8) & 0xff; - packet->buffer[2] = type; - packet->buffer[3] = 0; - - memcpy(packet->buffer + 4, buf, nb); - - spin_lock_irqsave(&card->lock, flags); - - if (!card->packets) - card->packets = packet; - else { - cur = card->packets; - while (cur->next) - cur = cur->next; - cur->next = packet; - } - - switch (type) { - case MVMS_CMD: - priv->dnld_sent = DNLD_CMD_SENT; - break; - case MVMS_DAT: - priv->dnld_sent = DNLD_DATA_SENT; - break; - default: - lbs_deb_sdio("unknown packet type %d\n", (int)type); - } - - spin_unlock_irqrestore(&card->lock, flags); - - queue_work(card->workqueue, &card->packet_worker); - - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; -} - -/*******************************************************************/ -/* SDIO callbacks */ -/*******************************************************************/ - -static void if_sdio_interrupt(struct sdio_func *func) -{ - int ret; - struct if_sdio_card *card; - u8 cause; - - lbs_deb_enter(LBS_DEB_SDIO); - - card = sdio_get_drvdata(func); - - cause = sdio_readb(card->func, IF_SDIO_H_INT_STATUS, &ret); - if (ret) - goto out; - - lbs_deb_sdio("interrupt: 0x%X\n", (unsigned)cause); - - sdio_writeb(card->func, ~cause, IF_SDIO_H_INT_STATUS, &ret); - if (ret) - goto out; - - /* - * Ignore the define name, this really means the card has - * successfully received the command. - */ - if (cause & IF_SDIO_H_INT_DNLD) - lbs_host_to_card_done(card->priv); - - - if (cause & IF_SDIO_H_INT_UPLD) { - ret = if_sdio_card_to_host(card); - if (ret) - goto out; - } - - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); -} - -static int if_sdio_probe(struct sdio_func *func, - const struct sdio_device_id *id) -{ - struct if_sdio_card *card; - struct lbs_private *priv; - int ret, i; - unsigned int model; - struct if_sdio_packet *packet; - struct mmc_host *host = func->card->host; - - lbs_deb_enter(LBS_DEB_SDIO); - - for (i = 0;i < func->card->num_info;i++) { - if (sscanf(func->card->info[i], - "802.11 SDIO ID: %x", &model) == 1) - break; - if (sscanf(func->card->info[i], - "ID: %x", &model) == 1) - break; - if (!strcmp(func->card->info[i], "IBIS Wireless SDIO Card")) { - model = IF_SDIO_MODEL_8385; - break; - } - } - - if (i == func->card->num_info) { - lbs_pr_err("unable to identify card model\n"); - return -ENODEV; - } - - card = kzalloc(sizeof(struct if_sdio_card), GFP_KERNEL); - if (!card) - return -ENOMEM; - - card->func = func; - card->model = model; - - switch (card->model) { - case IF_SDIO_MODEL_8385: - card->scratch_reg = IF_SDIO_SCRATCH_OLD; - break; - case IF_SDIO_MODEL_8686: - card->scratch_reg = IF_SDIO_SCRATCH; - break; - case IF_SDIO_MODEL_8688: - default: /* for newer chipsets */ - card->scratch_reg = IF_SDIO_FW_STATUS; - break; - } - - spin_lock_init(&card->lock); - card->workqueue = create_workqueue("libertas_sdio"); - INIT_WORK(&card->packet_worker, if_sdio_host_to_card_worker); - - for (i = 0;i < ARRAY_SIZE(if_sdio_models);i++) { - if (card->model == if_sdio_models[i].model) - break; - } - - if (i == ARRAY_SIZE(if_sdio_models)) { - lbs_pr_err("unkown card model 0x%x\n", card->model); - ret = -ENODEV; - goto free; - } - - card->helper = if_sdio_models[i].helper; - card->firmware = if_sdio_models[i].firmware; - - if (lbs_helper_name) { - lbs_deb_sdio("overriding helper firmware: %s\n", - lbs_helper_name); - card->helper = lbs_helper_name; - } - - if (lbs_fw_name) { - lbs_deb_sdio("overriding firmware: %s\n", lbs_fw_name); - card->firmware = lbs_fw_name; - } - - sdio_claim_host(func); - - ret = sdio_enable_func(func); - if (ret) - goto release; - - ret = sdio_claim_irq(func, if_sdio_interrupt); - if (ret) - goto disable; - - /* For 1-bit transfers to the 8686 model, we need to enable the - * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0 - * bit to allow access to non-vendor registers. */ - if ((card->model == IF_SDIO_MODEL_8686) && - (host->caps & MMC_CAP_SDIO_IRQ) && - (host->ios.bus_width == MMC_BUS_WIDTH_1)) { - u8 reg; - - func->card->quirks |= MMC_QUIRK_LENIENT_FN0; - reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret); - if (ret) - goto release_int; - - reg |= SDIO_BUS_ECSI; - sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret); - if (ret) - goto release_int; - } - - card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret); - if (ret) - goto release_int; - - card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8; - if (ret) - goto release_int; - - card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16; - if (ret) - goto release_int; - - sdio_release_host(func); - - sdio_set_drvdata(func, card); - - lbs_deb_sdio("class = 0x%X, vendor = 0x%X, " - "device = 0x%X, model = 0x%X, ioport = 0x%X\n", - func->class, func->vendor, func->device, - model, (unsigned)card->ioport); - - ret = if_sdio_prog_firmware(card); - if (ret) - goto reclaim; - - priv = lbs_add_card(card, &func->dev); - if (!priv) { - ret = -ENOMEM; - goto reclaim; - } - - card->priv = priv; - - priv->card = card; - priv->hw_host_to_card = if_sdio_host_to_card; - - priv->fw_ready = 1; - - sdio_claim_host(func); - - /* - * Get rx_unit if the chip is SD8688 or newer. - * SD8385 & SD8686 do not have rx_unit. - */ - if ((card->model != IF_SDIO_MODEL_8385) - && (card->model != IF_SDIO_MODEL_8686)) - card->rx_unit = if_sdio_read_rx_unit(card); - else - card->rx_unit = 0; - - /* - * Enable interrupts now that everything is set up - */ - sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret); - sdio_release_host(func); - if (ret) - goto reclaim; - - /* - * FUNC_INIT is required for SD8688 WLAN/BT multiple functions - */ - if (card->model == IF_SDIO_MODEL_8688) { - struct cmd_header cmd; - - memset(&cmd, 0, sizeof(cmd)); - - lbs_deb_sdio("send function INIT command\n"); - if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd), - lbs_cmd_copyback, (unsigned long) &cmd)) - lbs_pr_alert("CMD_FUNC_INIT cmd failed\n"); - } - - ret = lbs_start_card(priv); - if (ret) - goto err_activate_card; - - wifi_sdio_func = func; - -out: - lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - return ret; - -err_activate_card: - flush_workqueue(card->workqueue); - lbs_remove_card(priv); -reclaim: - sdio_claim_host(func); -release_int: - sdio_release_irq(func); -disable: - sdio_disable_func(func); -release: - sdio_release_host(func); -free: - destroy_workqueue(card->workqueue); - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; - kfree(packet); - } - - kfree(card); - - goto out; -} - -static void if_sdio_remove(struct sdio_func *func) -{ - struct if_sdio_card *card; - struct if_sdio_packet *packet; - - lbs_deb_enter(LBS_DEB_SDIO); - - card = sdio_get_drvdata(func); - - if (user_rmmod && (card->model == IF_SDIO_MODEL_8688)) { - /* - * FUNC_SHUTDOWN is required for SD8688 WLAN/BT - * multiple functions - */ - struct cmd_header cmd; - - memset(&cmd, 0, sizeof(cmd)); - - lbs_deb_sdio("send function SHUTDOWN command\n"); - if (__lbs_cmd(card->priv, CMD_FUNC_SHUTDOWN, - &cmd, sizeof(cmd), lbs_cmd_copyback, - (unsigned long) &cmd)) - lbs_pr_alert("CMD_FUNC_SHUTDOWN cmd failed\n"); - } - - - lbs_deb_sdio("call remove card\n"); - lbs_stop_card(card->priv); - lbs_remove_card(card->priv); - card->priv->surpriseremoved = 1; - - flush_workqueue(card->workqueue); - destroy_workqueue(card->workqueue); - - sdio_claim_host(func); - sdio_release_irq(func); - sdio_disable_func(func); - sdio_release_host(func); - - while (card->packets) { - packet = card->packets; - card->packets = card->packets->next; - kfree(packet); - } - - kfree(card); - - lbs_deb_leave(LBS_DEB_SDIO); -} - -static struct sdio_driver if_sdio_driver = { - .name = "libertas_sdio", - .id_table = if_sdio_ids, - .probe = if_sdio_probe, - .remove = if_sdio_remove, -}; - -/*******************************************************************/ -/* Module functions */ -/*******************************************************************/ - -//static int __init if_sdio_init_module2(void) -//void if_sdio_init_module2(struct work_struct *work) -int wifi_no_power_gpio = 0; /* 0-No 1-Yes */ -void if_sdio_init_module2(void) -{ - int ret = 0,timeout; - - wifi_sdio_func = NULL; - wifi_no_power_gpio = 0; - - //lbs_deb_enter(LBS_DEB_SDIO); - - printk(KERN_INFO "libertas_sdio: Libertas SDIO driver\n"); - printk(KERN_INFO "libertas_sdio: Copyright Pierre Ossman\n"); - - /* Clear the flag in case user removes the card. */ - user_rmmod = 0; - ///lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); - - ret = sdio_register_driver(&if_sdio_driver); - -#ifdef WIFI_GPIO_POWER_CONTROL - if (wifi_mmc_host->bus_ops != NULL) /* mmc/card is attached already. */ - { - printk("SDIO maybe be attached already.\n"); - wifi_no_power_gpio = 1; - return ; - } - - wifi_turn_on_card(); - wifi_power_up_wifi(); - - mmc_detect_change(wifi_mmc_host, 2); - - for (timeout = 100; timeout >=0; timeout--) - { - if (wifi_sdio_func != NULL) - break; - msleep(50); - } - if (timeout <= 0) - printk("No WiFi function card has been attached.\n"); -#endif - return ; -} -EXPORT_SYMBOL(if_sdio_init_module2); - -#if 0 -static int __init if_sdio_init_module(void) -{ - struct delayed_work hook_worker; - - INIT_DELAYED_WORK(&hook_worker, if_sdio_init_module2); - - schedule_delayed_work(&hook_worker, msecs_to_jiffies(9000)); - - return 0; -} -#endif - - -void if_sdio_exit_module(void) -{ - int timeout; - - lbs_deb_enter(LBS_DEB_SDIO); - - /* Set the flag as user is removing this module. */ - user_rmmod = 1; - - sdio_unregister_driver(&if_sdio_driver); - -#ifdef WIFI_GPIO_POWER_CONTROL - - if (wifi_no_power_gpio == 1) - return; - - if (wifi_mmc_host == NULL) - { - printk("No SDIO host is present.\n"); - return; - } - - wifi_power_down_wifi(); - wifi_turn_off_card(); - - mmc_detect_change(wifi_mmc_host, 2); - - for (timeout = 50; timeout >= 0; timeout--) - { - msleep(100); - if (wifi_mmc_host->bus_ops == NULL) - break; - } - if (timeout < 0) - printk("Fail to release SDIO card.\n"); -#endif - lbs_deb_leave(LBS_DEB_SDIO); -} -EXPORT_SYMBOL(if_sdio_exit_module); -//module_init(if_sdio_init_module); -//module_exit(if_sdio_exit_module); - -MODULE_DESCRIPTION("Libertas SDIO WLAN Driver"); -MODULE_AUTHOR("Pierre Ossman"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c deleted file mode 100644 index 5b3672c4d0cc..000000000000 --- a/drivers/net/wireless/libertas/if_spi.c +++ /dev/null @@ -1,1225 +0,0 @@ -/* - * linux/drivers/net/wireless/libertas/if_spi.c - * - * Driver for Marvell SPI WLAN cards. - * - * Copyright 2008 Analog Devices Inc. - * - * Authors: - * Andrey Yurovsky - * Colin McCabe - * - * Inspired by if_sdio.c, Copyright 2007-2008 Pierre Ossman - * - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "if_spi.h" - -struct if_spi_packet { - struct list_head list; - u16 blen; - u8 buffer[0] __attribute__((aligned(4))); -}; - -struct if_spi_card { - struct spi_device *spi; - struct lbs_private *priv; - struct libertas_spi_platform_data *pdata; - - char helper_fw_name[IF_SPI_FW_NAME_MAX]; - char main_fw_name[IF_SPI_FW_NAME_MAX]; - - /* The card ID and card revision, as reported by the hardware. */ - u16 card_id; - u8 card_rev; - - /* The last time that we initiated an SPU operation */ - unsigned long prev_xfer_time; - - int use_dummy_writes; - unsigned long spu_port_delay; - unsigned long spu_reg_delay; - - /* Handles all SPI communication (except for FW load) */ - struct task_struct *spi_thread; - int run_thread; - - /* Used to wake up the spi_thread */ - struct semaphore spi_ready; - struct semaphore spi_thread_terminated; - - u8 cmd_buffer[IF_SPI_CMD_BUF_SIZE]; - - /* A buffer of incoming packets from libertas core. - * Since we can't sleep in hw_host_to_card, we have to buffer - * them. */ - struct list_head cmd_packet_list; - struct list_head data_packet_list; - - /* Protects cmd_packet_list and data_packet_list */ - spinlock_t buffer_lock; -}; - -static void free_if_spi_card(struct if_spi_card *card) -{ - struct list_head *cursor, *next; - struct if_spi_packet *packet; - - BUG_ON(card->run_thread); - list_for_each_safe(cursor, next, &card->cmd_packet_list) { - packet = container_of(cursor, struct if_spi_packet, list); - list_del(&packet->list); - kfree(packet); - } - list_for_each_safe(cursor, next, &card->data_packet_list) { - packet = container_of(cursor, struct if_spi_packet, list); - list_del(&packet->list); - kfree(packet); - } - spi_set_drvdata(card->spi, NULL); - kfree(card); -} - -static struct chip_ident chip_id_to_device_name[] = { - { .chip_id = 0x04, .name = 8385 }, - { .chip_id = 0x0b, .name = 8686 }, -}; - -/* - * SPI Interface Unit Routines - * - * The SPU sits between the host and the WLAN module. - * All communication with the firmware is through SPU transactions. - * - * First we have to put a SPU register name on the bus. Then we can - * either read from or write to that register. - * - */ - -static void spu_transaction_init(struct if_spi_card *card) -{ - if (!time_after(jiffies, card->prev_xfer_time + 1)) { - /* Unfortunately, the SPU requires a delay between successive - * transactions. If our last transaction was more than a jiffy - * ago, we have obviously already delayed enough. - * If not, we have to busy-wait to be on the safe side. */ - ndelay(400); - } -} - -static void spu_transaction_finish(struct if_spi_card *card) -{ - card->prev_xfer_time = jiffies; -} - -/* Write out a byte buffer to an SPI register, - * using a series of 16-bit transfers. */ -static int spu_write(struct if_spi_card *card, u16 reg, const u8 *buf, int len) -{ - int err = 0; - __le16 reg_out = cpu_to_le16(reg | IF_SPI_WRITE_OPERATION_MASK); - struct spi_message m; - struct spi_transfer reg_trans; - struct spi_transfer data_trans; - - spi_message_init(&m); - memset(®_trans, 0, sizeof(reg_trans)); - memset(&data_trans, 0, sizeof(data_trans)); - - /* You must give an even number of bytes to the SPU, even if it - * doesn't care about the last one. */ - BUG_ON(len & 0x1); - - spu_transaction_init(card); - - /* write SPU register index */ - reg_trans.tx_buf = ®_out; - reg_trans.len = sizeof(reg_out); - - data_trans.tx_buf = buf; - data_trans.len = len; - - spi_message_add_tail(®_trans, &m); - spi_message_add_tail(&data_trans, &m); - - err = spi_sync(card->spi, &m); - spu_transaction_finish(card); - return err; -} - -static inline int spu_write_u16(struct if_spi_card *card, u16 reg, u16 val) -{ - __le16 buff; - - buff = cpu_to_le16(val); - return spu_write(card, reg, (u8 *)&buff, sizeof(u16)); -} - -static inline int spu_reg_is_port_reg(u16 reg) -{ - switch (reg) { - case IF_SPI_IO_RDWRPORT_REG: - case IF_SPI_CMD_RDWRPORT_REG: - case IF_SPI_DATA_RDWRPORT_REG: - return 1; - default: - return 0; - } -} - -static int spu_read(struct if_spi_card *card, u16 reg, u8 *buf, int len) -{ - unsigned int delay; - int err = 0; - __le16 reg_out = cpu_to_le16(reg | IF_SPI_READ_OPERATION_MASK); - struct spi_message m; - struct spi_transfer reg_trans; - struct spi_transfer dummy_trans; - struct spi_transfer data_trans; - - /* You must take an even number of bytes from the SPU, even if you - * don't care about the last one. */ - BUG_ON(len & 0x1); - - spu_transaction_init(card); - - spi_message_init(&m); - memset(®_trans, 0, sizeof(reg_trans)); - memset(&dummy_trans, 0, sizeof(dummy_trans)); - memset(&data_trans, 0, sizeof(data_trans)); - - /* write SPU register index */ - reg_trans.tx_buf = ®_out; - reg_trans.len = sizeof(reg_out); - spi_message_add_tail(®_trans, &m); - - delay = spu_reg_is_port_reg(reg) ? card->spu_port_delay : - card->spu_reg_delay; - if (card->use_dummy_writes) { - /* Clock in dummy cycles while the SPU fills the FIFO */ - dummy_trans.len = delay / 8; - spi_message_add_tail(&dummy_trans, &m); - } else { - /* Busy-wait while the SPU fills the FIFO */ - reg_trans.delay_usecs = - DIV_ROUND_UP((100 + (delay * 10)), 1000); - } - - /* read in data */ - data_trans.rx_buf = buf; - data_trans.len = len; - spi_message_add_tail(&data_trans, &m); - - err = spi_sync(card->spi, &m); - spu_transaction_finish(card); - return err; -} - -/* Read 16 bits from an SPI register */ -static inline int spu_read_u16(struct if_spi_card *card, u16 reg, u16 *val) -{ - __le16 buf; - int ret; - - ret = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); - if (ret == 0) - *val = le16_to_cpup(&buf); - return ret; -} - -/* Read 32 bits from an SPI register. - * The low 16 bits are read first. */ -static int spu_read_u32(struct if_spi_card *card, u16 reg, u32 *val) -{ - __le32 buf; - int err; - - err = spu_read(card, reg, (u8 *)&buf, sizeof(buf)); - if (!err) - *val = le32_to_cpup(&buf); - return err; -} - -/* Keep reading 16 bits from an SPI register until you get the correct result. - * - * If mask = 0, the correct result is any non-zero number. - * If mask != 0, the correct result is any number where - * number & target_mask == target - * - * Returns -ETIMEDOUT if a second passes without the correct result. */ -static int spu_wait_for_u16(struct if_spi_card *card, u16 reg, - u16 target_mask, u16 target) -{ - int err; - unsigned long timeout = jiffies + 5*HZ; - while (1) { - u16 val; - err = spu_read_u16(card, reg, &val); - if (err) - return err; - if (target_mask) { - if ((val & target_mask) == target) - return 0; - } else { - if (val) - return 0; - } - udelay(100); - if (time_after(jiffies, timeout)) { - lbs_pr_err("%s: timeout with val=%02x, " - "target_mask=%02x, target=%02x\n", - __func__, val, target_mask, target); - return -ETIMEDOUT; - } - } -} - -/* Read 16 bits from an SPI register until you receive a specific value. - * Returns -ETIMEDOUT if a 4 tries pass without success. */ -static int spu_wait_for_u32(struct if_spi_card *card, u32 reg, u32 target) -{ - int err, try; - for (try = 0; try < 4; ++try) { - u32 val = 0; - err = spu_read_u32(card, reg, &val); - if (err) - return err; - if (val == target) - return 0; - mdelay(100); - } - return -ETIMEDOUT; -} - -static int spu_set_interrupt_mode(struct if_spi_card *card, - int suppress_host_int, - int auto_int) -{ - int err = 0; - - /* We can suppress a host interrupt by clearing the appropriate - * bit in the "host interrupt status mask" register */ - if (suppress_host_int) { - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); - if (err) - return err; - } else { - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, - IF_SPI_HISM_TX_DOWNLOAD_RDY | - IF_SPI_HISM_RX_UPLOAD_RDY | - IF_SPI_HISM_CMD_DOWNLOAD_RDY | - IF_SPI_HISM_CARDEVENT | - IF_SPI_HISM_CMD_UPLOAD_RDY); - if (err) - return err; - } - - /* If auto-interrupts are on, the completion of certain transactions - * will trigger an interrupt automatically. If auto-interrupts - * are off, we need to set the "Card Interrupt Cause" register to - * trigger a card interrupt. */ - if (auto_int) { - err = spu_write_u16(card, IF_SPI_HOST_INT_CTRL_REG, - IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO | - IF_SPI_HICT_RX_UPLOAD_OVER_AUTO | - IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO | - IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO); - if (err) - return err; - } else { - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_MASK_REG, 0); - if (err) - return err; - } - return err; -} - -static int spu_get_chip_revision(struct if_spi_card *card, - u16 *card_id, u8 *card_rev) -{ - int err = 0; - u32 dev_ctrl; - err = spu_read_u32(card, IF_SPI_DEVICEID_CTRL_REG, &dev_ctrl); - if (err) - return err; - *card_id = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dev_ctrl); - *card_rev = IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dev_ctrl); - return err; -} - -static int spu_set_bus_mode(struct if_spi_card *card, u16 mode) -{ - int err = 0; - u16 rval; - /* set bus mode */ - err = spu_write_u16(card, IF_SPI_SPU_BUS_MODE_REG, mode); - if (err) - return err; - /* Check that we were able to read back what we just wrote. */ - err = spu_read_u16(card, IF_SPI_SPU_BUS_MODE_REG, &rval); - if (err) - return err; - if ((rval & 0xF) != mode) { - lbs_pr_err("Can't read bus mode register.\n"); - return -EIO; - } - return 0; -} - -static int spu_init(struct if_spi_card *card, int use_dummy_writes) -{ - int err = 0; - u32 delay; - - /* We have to start up in timed delay mode so that we can safely - * read the Delay Read Register. */ - card->use_dummy_writes = 0; - err = spu_set_bus_mode(card, - IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | - IF_SPI_BUS_MODE_DELAY_METHOD_TIMED | - IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA); - if (err) - return err; - card->spu_port_delay = 1000; - card->spu_reg_delay = 1000; - err = spu_read_u32(card, IF_SPI_DELAY_READ_REG, &delay); - if (err) - return err; - card->spu_port_delay = delay & 0x0000ffff; - card->spu_reg_delay = (delay & 0xffff0000) >> 16; - - /* If dummy clock delay mode has been requested, switch to it now */ - if (use_dummy_writes) { - card->use_dummy_writes = 1; - err = spu_set_bus_mode(card, - IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING | - IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK | - IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA); - if (err) - return err; - } - - lbs_deb_spi("Initialized SPU unit. " - "spu_port_delay=0x%04lx, spu_reg_delay=0x%04lx\n", - card->spu_port_delay, card->spu_reg_delay); - return err; -} - -/* - * Firmware Loading - */ - -static int if_spi_prog_helper_firmware(struct if_spi_card *card) -{ - int err = 0; - const struct firmware *firmware = NULL; - int bytes_remaining; - const u8 *fw; - u8 temp[HELPER_FW_LOAD_CHUNK_SZ]; - struct spi_device *spi = card->spi; - - lbs_deb_enter(LBS_DEB_SPI); - - err = spu_set_interrupt_mode(card, 1, 0); - if (err) - goto out; - /* Get helper firmware image */ - err = request_firmware(&firmware, card->helper_fw_name, &spi->dev); - if (err) { - lbs_pr_err("request_firmware failed with err = %d\n", err); - goto out; - } - bytes_remaining = firmware->size; - fw = firmware->data; - - /* Load helper firmware image */ - while (bytes_remaining > 0) { - /* Scratch pad 1 should contain the number of bytes we - * want to download to the firmware */ - err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, - HELPER_FW_LOAD_CHUNK_SZ); - if (err) - goto release_firmware; - - err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, - IF_SPI_HIST_CMD_DOWNLOAD_RDY, - IF_SPI_HIST_CMD_DOWNLOAD_RDY); - if (err) - goto release_firmware; - - /* Feed the data into the command read/write port reg - * in chunks of 64 bytes */ - memset(temp, 0, sizeof(temp)); - memcpy(temp, fw, - min(bytes_remaining, HELPER_FW_LOAD_CHUNK_SZ)); - mdelay(10); - err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, - temp, HELPER_FW_LOAD_CHUNK_SZ); - if (err) - goto release_firmware; - - /* Interrupt the boot code */ - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); - if (err) - goto release_firmware; - err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, - IF_SPI_CIC_CMD_DOWNLOAD_OVER); - if (err) - goto release_firmware; - bytes_remaining -= HELPER_FW_LOAD_CHUNK_SZ; - fw += HELPER_FW_LOAD_CHUNK_SZ; - } - - /* Once the helper / single stage firmware download is complete, - * write 0 to scratch pad 1 and interrupt the - * bootloader. This completes the helper download. */ - err = spu_write_u16(card, IF_SPI_SCRATCH_1_REG, FIRMWARE_DNLD_OK); - if (err) - goto release_firmware; - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); - if (err) - goto release_firmware; - err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, - IF_SPI_CIC_CMD_DOWNLOAD_OVER); - goto release_firmware; - - lbs_deb_spi("waiting for helper to boot...\n"); - -release_firmware: - release_firmware(firmware); -out: - if (err) - lbs_pr_err("failed to load helper firmware (err=%d)\n", err); - lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); - return err; -} - -/* Returns the length of the next packet the firmware expects us to send - * Sets crc_err if the previous transfer had a CRC error. */ -static int if_spi_prog_main_firmware_check_len(struct if_spi_card *card, - int *crc_err) -{ - u16 len; - int err = 0; - - /* wait until the host interrupt status register indicates - * that we are ready to download */ - err = spu_wait_for_u16(card, IF_SPI_HOST_INT_STATUS_REG, - IF_SPI_HIST_CMD_DOWNLOAD_RDY, - IF_SPI_HIST_CMD_DOWNLOAD_RDY); - if (err) { - lbs_pr_err("timed out waiting for host_int_status\n"); - return err; - } - - /* Ask the device how many bytes of firmware it wants. */ - err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); - if (err) - return err; - - if (len > IF_SPI_CMD_BUF_SIZE) { - lbs_pr_err("firmware load device requested a larger " - "tranfer than we are prepared to " - "handle. (len = %d)\n", len); - return -EIO; - } - if (len & 0x1) { - lbs_deb_spi("%s: crc error\n", __func__); - len &= ~0x1; - *crc_err = 1; - } else - *crc_err = 0; - - return len; -} - -static int if_spi_prog_main_firmware(struct if_spi_card *card) -{ - int len, prev_len; - int bytes, crc_err = 0, err = 0; - const struct firmware *firmware = NULL; - const u8 *fw; - struct spi_device *spi = card->spi; - u16 num_crc_errs; - - lbs_deb_enter(LBS_DEB_SPI); - - err = spu_set_interrupt_mode(card, 1, 0); - if (err) - goto out; - - /* Get firmware image */ - err = request_firmware(&firmware, card->main_fw_name, &spi->dev); - if (err) { - lbs_pr_err("%s: can't get firmware '%s' from kernel. " - "err = %d\n", __func__, card->main_fw_name, err); - goto out; - } - - err = spu_wait_for_u16(card, IF_SPI_SCRATCH_1_REG, 0, 0); - if (err) { - lbs_pr_err("%s: timed out waiting for initial " - "scratch reg = 0\n", __func__); - goto release_firmware; - } - - num_crc_errs = 0; - prev_len = 0; - bytes = firmware->size; - fw = firmware->data; - while ((len = if_spi_prog_main_firmware_check_len(card, &crc_err))) { - if (len < 0) { - err = len; - goto release_firmware; - } - if (bytes < 0) { - /* If there are no more bytes left, we would normally - * expect to have terminated with len = 0 */ - lbs_pr_err("Firmware load wants more bytes " - "than we have to offer.\n"); - break; - } - if (crc_err) { - /* Previous transfer failed. */ - if (++num_crc_errs > MAX_MAIN_FW_LOAD_CRC_ERR) { - lbs_pr_err("Too many CRC errors encountered " - "in firmware load.\n"); - err = -EIO; - goto release_firmware; - } - } else { - /* Previous transfer succeeded. Advance counters. */ - bytes -= prev_len; - fw += prev_len; - } - if (bytes < len) { - memset(card->cmd_buffer, 0, len); - memcpy(card->cmd_buffer, fw, bytes); - } else - memcpy(card->cmd_buffer, fw, len); - - err = spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, 0); - if (err) - goto release_firmware; - err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, - card->cmd_buffer, len); - if (err) - goto release_firmware; - err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG , - IF_SPI_CIC_CMD_DOWNLOAD_OVER); - if (err) - goto release_firmware; - prev_len = len; - } - if (bytes > prev_len) { - lbs_pr_err("firmware load wants fewer bytes than " - "we have to offer.\n"); - } - - /* Confirm firmware download */ - err = spu_wait_for_u32(card, IF_SPI_SCRATCH_4_REG, - SUCCESSFUL_FW_DOWNLOAD_MAGIC); - if (err) { - lbs_pr_err("failed to confirm the firmware download\n"); - goto release_firmware; - } - -release_firmware: - release_firmware(firmware); - -out: - if (err) - lbs_pr_err("failed to load firmware (err=%d)\n", err); - lbs_deb_leave_args(LBS_DEB_SPI, "err %d", err); - return err; -} - -/* - * SPI Transfer Thread - * - * The SPI thread handles all SPI transfers, so there is no need for a lock. - */ - -/* Move a command from the card to the host */ -static int if_spi_c2h_cmd(struct if_spi_card *card) -{ - struct lbs_private *priv = card->priv; - unsigned long flags; - int err = 0; - u16 len; - u8 i; - - /* We need a buffer big enough to handle whatever people send to - * hw_host_to_card */ - BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_CMD_BUFFER_SIZE); - BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE < LBS_UPLD_SIZE); - - /* It's just annoying if the buffer size isn't a multiple of 4, because - * then we might have len < IF_SPI_CMD_BUF_SIZE but - * ALIGN(len, 4) > IF_SPI_CMD_BUF_SIZE */ - BUILD_BUG_ON(IF_SPI_CMD_BUF_SIZE % 4 != 0); - - lbs_deb_enter(LBS_DEB_SPI); - - /* How many bytes are there to read? */ - err = spu_read_u16(card, IF_SPI_SCRATCH_2_REG, &len); - if (err) - goto out; - if (!len) { - lbs_pr_err("%s: error: card has no data for host\n", - __func__); - err = -EINVAL; - goto out; - } else if (len > IF_SPI_CMD_BUF_SIZE) { - lbs_pr_err("%s: error: response packet too large: " - "%d bytes, but maximum is %d\n", - __func__, len, IF_SPI_CMD_BUF_SIZE); - err = -EINVAL; - goto out; - } - - /* Read the data from the WLAN module into our command buffer */ - err = spu_read(card, IF_SPI_CMD_RDWRPORT_REG, - card->cmd_buffer, ALIGN(len, 4)); - if (err) - goto out; - - spin_lock_irqsave(&priv->driver_lock, flags); - i = (priv->resp_idx == 0) ? 1 : 0; - BUG_ON(priv->resp_len[i]); - priv->resp_len[i] = len; - memcpy(priv->resp_buf[i], card->cmd_buffer, len); - lbs_notify_command_response(priv, i); - spin_unlock_irqrestore(&priv->driver_lock, flags); - -out: - if (err) - lbs_pr_err("%s: err=%d\n", __func__, err); - lbs_deb_leave(LBS_DEB_SPI); - return err; -} - -/* Move data from the card to the host */ -static int if_spi_c2h_data(struct if_spi_card *card) -{ - struct sk_buff *skb; - char *data; - u16 len; - int err = 0; - - lbs_deb_enter(LBS_DEB_SPI); - - /* How many bytes are there to read? */ - err = spu_read_u16(card, IF_SPI_SCRATCH_1_REG, &len); - if (err) - goto out; - if (!len) { - lbs_pr_err("%s: error: card has no data for host\n", - __func__); - err = -EINVAL; - goto out; - } else if (len > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE) { - lbs_pr_err("%s: error: card has %d bytes of data, but " - "our maximum skb size is %zu\n", - __func__, len, MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); - err = -EINVAL; - goto out; - } - - /* TODO: should we allocate a smaller skb if we have less data? */ - skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); - if (!skb) { - err = -ENOBUFS; - goto out; - } - skb_reserve(skb, IPFIELD_ALIGN_OFFSET); - data = skb_put(skb, len); - - /* Read the data from the WLAN module into our skb... */ - err = spu_read(card, IF_SPI_DATA_RDWRPORT_REG, data, ALIGN(len, 4)); - if (err) - goto free_skb; - - /* pass the SKB to libertas */ - err = lbs_process_rxed_packet(card->priv, skb); - if (err) - goto free_skb; - - /* success */ - goto out; - -free_skb: - dev_kfree_skb(skb); -out: - if (err) - lbs_pr_err("%s: err=%d\n", __func__, err); - lbs_deb_leave(LBS_DEB_SPI); - return err; -} - -/* Move data or a command from the host to the card. */ -static void if_spi_h2c(struct if_spi_card *card, - struct if_spi_packet *packet, int type) -{ - int err = 0; - u16 int_type, port_reg; - - switch (type) { - case MVMS_DAT: - int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER; - port_reg = IF_SPI_DATA_RDWRPORT_REG; - break; - case MVMS_CMD: - int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER; - port_reg = IF_SPI_CMD_RDWRPORT_REG; - break; - default: - lbs_pr_err("can't transfer buffer of type %d\n", type); - err = -EINVAL; - goto out; - } - - /* Write the data to the card */ - err = spu_write(card, port_reg, packet->buffer, packet->blen); - if (err) - goto out; - -out: - kfree(packet); - - if (err) - lbs_pr_err("%s: error %d\n", __func__, err); -} - -/* Inform the host about a card event */ -static void if_spi_e2h(struct if_spi_card *card) -{ - int err = 0; - u32 cause; - struct lbs_private *priv = card->priv; - - err = spu_read_u32(card, IF_SPI_SCRATCH_3_REG, &cause); - if (err) - goto out; - - /* re-enable the card event interrupt */ - spu_write_u16(card, IF_SPI_HOST_INT_STATUS_REG, - ~IF_SPI_HICU_CARD_EVENT); - - /* generate a card interrupt */ - spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, IF_SPI_CIC_HOST_EVENT); - - lbs_queue_event(priv, cause & 0xff); -out: - if (err) - lbs_pr_err("%s: error %d\n", __func__, err); -} - -static int lbs_spi_thread(void *data) -{ - int err; - struct if_spi_card *card = data; - u16 hiStatus; - unsigned long flags; - struct if_spi_packet *packet; - - while (1) { - /* Wait to be woken up by one of two things. First, our ISR - * could tell us that something happened on the WLAN. - * Secondly, libertas could call hw_host_to_card with more - * data, which we might be able to send. - */ - do { - err = down_interruptible(&card->spi_ready); - if (!card->run_thread) { - up(&card->spi_thread_terminated); - do_exit(0); - } - } while (err == EINTR); - - /* Read the host interrupt status register to see what we - * can do. */ - err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG, - &hiStatus); - if (err) { - lbs_pr_err("I/O error\n"); - goto err; - } - - if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) - err = if_spi_c2h_cmd(card); - if (err) - goto err; - if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) - err = if_spi_c2h_data(card); - if (err) - goto err; - - /* workaround: in PS mode, the card does not set the Command - * Download Ready bit, but it sets TX Download Ready. */ - if (hiStatus & IF_SPI_HIST_CMD_DOWNLOAD_RDY || - (card->priv->psstate != PS_STATE_FULL_POWER && - (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY))) { - /* This means two things. First of all, - * if there was a previous command sent, the card has - * successfully received it. - * Secondly, it is now ready to download another - * command. - */ - lbs_host_to_card_done(card->priv); - - /* Do we have any command packets from the host to - * send? */ - packet = NULL; - spin_lock_irqsave(&card->buffer_lock, flags); - if (!list_empty(&card->cmd_packet_list)) { - packet = (struct if_spi_packet *)(card-> - cmd_packet_list.next); - list_del(&packet->list); - } - spin_unlock_irqrestore(&card->buffer_lock, flags); - - if (packet) - if_spi_h2c(card, packet, MVMS_CMD); - } - if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) { - /* Do we have any data packets from the host to - * send? */ - packet = NULL; - spin_lock_irqsave(&card->buffer_lock, flags); - if (!list_empty(&card->data_packet_list)) { - packet = (struct if_spi_packet *)(card-> - data_packet_list.next); - list_del(&packet->list); - } - spin_unlock_irqrestore(&card->buffer_lock, flags); - - if (packet) - if_spi_h2c(card, packet, MVMS_DAT); - } - if (hiStatus & IF_SPI_HIST_CARD_EVENT) - if_spi_e2h(card); - -err: - if (err) - lbs_pr_err("%s: got error %d\n", __func__, err); - } -} - -/* Block until lbs_spi_thread thread has terminated */ -static void if_spi_terminate_spi_thread(struct if_spi_card *card) -{ - /* It would be nice to use kthread_stop here, but that function - * can't wake threads waiting for a semaphore. */ - card->run_thread = 0; - up(&card->spi_ready); - down(&card->spi_thread_terminated); -} - -/* - * Host to Card - * - * Called from Libertas to transfer some data to the WLAN device - * We can't sleep here. */ -static int if_spi_host_to_card(struct lbs_private *priv, - u8 type, u8 *buf, u16 nb) -{ - int err = 0; - unsigned long flags; - struct if_spi_card *card = priv->card; - struct if_spi_packet *packet; - u16 blen; - - lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb); - - if (nb == 0) { - lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb); - err = -EINVAL; - goto out; - } - blen = ALIGN(nb, 4); - packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC); - if (!packet) { - err = -ENOMEM; - goto out; - } - packet->blen = blen; - memcpy(packet->buffer, buf, nb); - memset(packet->buffer + nb, 0, blen - nb); - - switch (type) { - case MVMS_CMD: - priv->dnld_sent = DNLD_CMD_SENT; - spin_lock_irqsave(&card->buffer_lock, flags); - list_add_tail(&packet->list, &card->cmd_packet_list); - spin_unlock_irqrestore(&card->buffer_lock, flags); - break; - case MVMS_DAT: - priv->dnld_sent = DNLD_DATA_SENT; - spin_lock_irqsave(&card->buffer_lock, flags); - list_add_tail(&packet->list, &card->data_packet_list); - spin_unlock_irqrestore(&card->buffer_lock, flags); - break; - default: - lbs_pr_err("can't transfer buffer of type %d", type); - err = -EINVAL; - break; - } - - /* Wake up the spi thread */ - up(&card->spi_ready); -out: - lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err); - return err; -} - -/* - * Host Interrupts - * - * Service incoming interrupts from the WLAN device. We can't sleep here, so - * don't try to talk on the SPI bus, just wake up the SPI thread. - */ -static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id) -{ - struct if_spi_card *card = dev_id; - - up(&card->spi_ready); - return IRQ_HANDLED; -} - -/* - * SPI callbacks - */ - -static int if_spi_calculate_fw_names(u16 card_id, - char *helper_fw, char *main_fw) -{ - int i; - for (i = 0; i < ARRAY_SIZE(chip_id_to_device_name); ++i) { - if (card_id == chip_id_to_device_name[i].chip_id) - break; - } - if (i == ARRAY_SIZE(chip_id_to_device_name)) { - lbs_pr_err("Unsupported chip_id: 0x%02x\n", card_id); - return -EAFNOSUPPORT; - } - snprintf(helper_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d_hlp.bin", - chip_id_to_device_name[i].name); - snprintf(main_fw, IF_SPI_FW_NAME_MAX, "libertas/gspi%d.bin", - chip_id_to_device_name[i].name); - return 0; -} - -static int __devinit if_spi_probe(struct spi_device *spi) -{ - struct if_spi_card *card; - struct lbs_private *priv = NULL; - struct libertas_spi_platform_data *pdata = spi->dev.platform_data; - int err = 0; - u32 scratch; - struct sched_param param = { .sched_priority = 1 }; - - lbs_deb_enter(LBS_DEB_SPI); - - if (!pdata) { - err = -EINVAL; - goto out; - } - - if (pdata->setup) { - err = pdata->setup(spi); - if (err) - goto out; - } - - /* Allocate card structure to represent this specific device */ - card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL); - if (!card) { - err = -ENOMEM; - goto out; - } - spi_set_drvdata(spi, card); - card->pdata = pdata; - card->spi = spi; - card->prev_xfer_time = jiffies; - - sema_init(&card->spi_ready, 0); - sema_init(&card->spi_thread_terminated, 0); - INIT_LIST_HEAD(&card->cmd_packet_list); - INIT_LIST_HEAD(&card->data_packet_list); - spin_lock_init(&card->buffer_lock); - - /* Initialize the SPI Interface Unit */ - err = spu_init(card, pdata->use_dummy_writes); - if (err) - goto free_card; - err = spu_get_chip_revision(card, &card->card_id, &card->card_rev); - if (err) - goto free_card; - - /* Firmware load */ - err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch); - if (err) - goto free_card; - if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC) - lbs_deb_spi("Firmware is already loaded for " - "Marvell WLAN 802.11 adapter\n"); - else { - err = if_spi_calculate_fw_names(card->card_id, - card->helper_fw_name, card->main_fw_name); - if (err) - goto free_card; - - lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter " - "(chip_id = 0x%04x, chip_rev = 0x%02x) " - "attached to SPI bus_num %d, chip_select %d. " - "spi->max_speed_hz=%d\n", - card->card_id, card->card_rev, - spi->master->bus_num, spi->chip_select, - spi->max_speed_hz); - err = if_spi_prog_helper_firmware(card); - if (err) - goto free_card; - err = if_spi_prog_main_firmware(card); - if (err) - goto free_card; - lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n"); - } - - err = spu_set_interrupt_mode(card, 0, 1); - if (err) - goto free_card; - - /* Register our card with libertas. - * This will call alloc_etherdev */ - priv = lbs_add_card(card, &spi->dev); - if (!priv) { - err = -ENOMEM; - goto free_card; - } - card->priv = priv; - priv->card = card; - priv->hw_host_to_card = if_spi_host_to_card; - priv->fw_ready = 1; - - /* Initialize interrupt handling stuff. */ - card->run_thread = 1; - card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread"); - if (IS_ERR(card->spi_thread)) { - card->run_thread = 0; - err = PTR_ERR(card->spi_thread); - lbs_pr_err("error creating SPI thread: err=%d\n", err); - goto remove_card; - } - if (sched_setscheduler(card->spi_thread, SCHED_FIFO, ¶m)) - lbs_pr_err("Error setting scheduler, using default.\n"); - - err = request_irq(spi->irq, if_spi_host_interrupt, - IRQF_TRIGGER_FALLING, "libertas_spi", card); - if (err) { - lbs_pr_err("can't get host irq line-- request_irq failed\n"); - goto terminate_thread; - } - - /* Start the card. - * This will call register_netdev, and we'll start - * getting interrupts... */ - err = lbs_start_card(priv); - if (err) - goto release_irq; - - lbs_deb_spi("Finished initializing WLAN module.\n"); - - /* successful exit */ - goto out; - -release_irq: - free_irq(spi->irq, card); -terminate_thread: - if_spi_terminate_spi_thread(card); -remove_card: - lbs_remove_card(priv); /* will call free_netdev */ -free_card: - free_if_spi_card(card); -out: - lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err); - return err; -} - -static int __devexit libertas_spi_remove(struct spi_device *spi) -{ - struct if_spi_card *card = spi_get_drvdata(spi); - struct lbs_private *priv = card->priv; - - lbs_deb_spi("libertas_spi_remove\n"); - lbs_deb_enter(LBS_DEB_SPI); - - lbs_stop_card(priv); - lbs_remove_card(priv); /* will call free_netdev */ - - priv->surpriseremoved = 1; - free_irq(spi->irq, card); - if_spi_terminate_spi_thread(card); - if (card->pdata->teardown) - card->pdata->teardown(spi); - free_if_spi_card(card); - lbs_deb_leave(LBS_DEB_SPI); - return 0; -} - -static struct spi_driver libertas_spi_driver = { - .probe = if_spi_probe, - .remove = __devexit_p(libertas_spi_remove), - .driver = { - .name = "libertas_spi", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, -}; - -/* - * Module functions - */ - -static int __init if_spi_init_module(void) -{ - int ret = 0; - lbs_deb_enter(LBS_DEB_SPI); - printk(KERN_INFO "libertas_spi: Libertas SPI driver\n"); - ret = spi_register_driver(&libertas_spi_driver); - lbs_deb_leave(LBS_DEB_SPI); - return ret; -} - -static void __exit if_spi_exit_module(void) -{ - lbs_deb_enter(LBS_DEB_SPI); - spi_unregister_driver(&libertas_spi_driver); - lbs_deb_leave(LBS_DEB_SPI); -} - -module_init(if_spi_init_module); -module_exit(if_spi_exit_module); - -MODULE_DESCRIPTION("Libertas SPI WLAN Driver"); -MODULE_AUTHOR("Andrey Yurovsky , " - "Colin McCabe "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:libertas_spi"); diff --git a/drivers/net/wireless/libertas/if_spi.h b/drivers/net/wireless/libertas/if_spi.h deleted file mode 100644 index f87eec410848..000000000000 --- a/drivers/net/wireless/libertas/if_spi.h +++ /dev/null @@ -1,211 +0,0 @@ -/* - * linux/drivers/net/wireless/libertas/if_spi.c - * - * Driver for Marvell SPI WLAN cards. - * - * Copyright 2008 Analog Devices Inc. - * - * Authors: - * Andrey Yurovsky - * Colin McCabe - * - * 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. - */ - -#ifndef _LBS_IF_SPI_H_ -#define _LBS_IF_SPI_H_ - -#define IPFIELD_ALIGN_OFFSET 2 -#define IF_SPI_CMD_BUF_SIZE 2400 - -/***************** Firmware *****************/ - -#define IF_SPI_FW_NAME_MAX 30 - -struct chip_ident { - u16 chip_id; - u16 name; -}; - -#define MAX_MAIN_FW_LOAD_CRC_ERR 10 - -/* Chunk size when loading the helper firmware */ -#define HELPER_FW_LOAD_CHUNK_SZ 64 - -/* Value to write to indicate end of helper firmware dnld */ -#define FIRMWARE_DNLD_OK 0x0000 - -/* Value to check once the main firmware is downloaded */ -#define SUCCESSFUL_FW_DOWNLOAD_MAGIC 0x88888888 - -/***************** SPI Interface Unit *****************/ -/* Masks used in SPI register read/write operations */ -#define IF_SPI_READ_OPERATION_MASK 0x0 -#define IF_SPI_WRITE_OPERATION_MASK 0x8000 - -/* SPI register offsets. 4-byte aligned. */ -#define IF_SPI_DEVICEID_CTRL_REG 0x00 /* DeviceID controller reg */ -#define IF_SPI_IO_READBASE_REG 0x04 /* Read I/O base reg */ -#define IF_SPI_IO_WRITEBASE_REG 0x08 /* Write I/O base reg */ -#define IF_SPI_IO_RDWRPORT_REG 0x0C /* Read/Write I/O port reg */ - -#define IF_SPI_CMD_READBASE_REG 0x10 /* Read command base reg */ -#define IF_SPI_CMD_WRITEBASE_REG 0x14 /* Write command base reg */ -#define IF_SPI_CMD_RDWRPORT_REG 0x18 /* Read/Write command port reg */ - -#define IF_SPI_DATA_READBASE_REG 0x1C /* Read data base reg */ -#define IF_SPI_DATA_WRITEBASE_REG 0x20 /* Write data base reg */ -#define IF_SPI_DATA_RDWRPORT_REG 0x24 /* Read/Write data port reg */ - -#define IF_SPI_SCRATCH_1_REG 0x28 /* Scratch reg 1 */ -#define IF_SPI_SCRATCH_2_REG 0x2C /* Scratch reg 2 */ -#define IF_SPI_SCRATCH_3_REG 0x30 /* Scratch reg 3 */ -#define IF_SPI_SCRATCH_4_REG 0x34 /* Scratch reg 4 */ - -#define IF_SPI_TX_FRAME_SEQ_NUM_REG 0x38 /* Tx frame sequence number reg */ -#define IF_SPI_TX_FRAME_STATUS_REG 0x3C /* Tx frame status reg */ - -#define IF_SPI_HOST_INT_CTRL_REG 0x40 /* Host interrupt controller reg */ - -#define IF_SPI_CARD_INT_CAUSE_REG 0x44 /* Card interrupt cause reg */ -#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */ -#define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */ -#define IF_SPI_CARD_INT_STATUS_MASK_REG 0x50 /* Card interrupt status mask */ - -#define IF_SPI_CARD_INT_RESET_SELECT_REG 0x54 /* Card interrupt reset select */ - -#define IF_SPI_HOST_INT_CAUSE_REG 0x58 /* Host interrupt cause reg */ -#define IF_SPI_HOST_INT_STATUS_REG 0x5C /* Host interrupt status reg */ -#define IF_SPI_HOST_INT_EVENT_MASK_REG 0x60 /* Host interrupt event mask */ -#define IF_SPI_HOST_INT_STATUS_MASK_REG 0x64 /* Host interrupt status mask */ -#define IF_SPI_HOST_INT_RESET_SELECT_REG 0x68 /* Host interrupt reset select */ - -#define IF_SPI_DELAY_READ_REG 0x6C /* Delay read reg */ -#define IF_SPI_SPU_BUS_MODE_REG 0x70 /* SPU BUS mode reg */ - -/***************** IF_SPI_DEVICEID_CTRL_REG *****************/ -#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_ID(dc) ((dc & 0xffff0000)>>16) -#define IF_SPI_DEVICEID_CTRL_REG_TO_CARD_REV(dc) (dc & 0x000000ff) - -/***************** IF_SPI_HOST_INT_CTRL_REG *****************/ -/** Host Interrupt Control bit : Wake up */ -#define IF_SPI_HICT_WAKE_UP (1<<0) -/** Host Interrupt Control bit : WLAN ready */ -#define IF_SPI_HICT_WLAN_READY (1<<1) -/*#define IF_SPI_HICT_FIFO_FIRST_HALF_EMPTY (1<<2) */ -/*#define IF_SPI_HICT_FIFO_SECOND_HALF_EMPTY (1<<3) */ -/*#define IF_SPI_HICT_IRQSRC_WLAN (1<<4) */ -/** Host Interrupt Control bit : Tx auto download */ -#define IF_SPI_HICT_TX_DOWNLOAD_OVER_AUTO (1<<5) -/** Host Interrupt Control bit : Rx auto upload */ -#define IF_SPI_HICT_RX_UPLOAD_OVER_AUTO (1<<6) -/** Host Interrupt Control bit : Command auto download */ -#define IF_SPI_HICT_CMD_DOWNLOAD_OVER_AUTO (1<<7) -/** Host Interrupt Control bit : Command auto upload */ -#define IF_SPI_HICT_CMD_UPLOAD_OVER_AUTO (1<<8) - -/***************** IF_SPI_CARD_INT_CAUSE_REG *****************/ -/** Card Interrupt Case bit : Tx download over */ -#define IF_SPI_CIC_TX_DOWNLOAD_OVER (1<<0) -/** Card Interrupt Case bit : Rx upload over */ -#define IF_SPI_CIC_RX_UPLOAD_OVER (1<<1) -/** Card Interrupt Case bit : Command download over */ -#define IF_SPI_CIC_CMD_DOWNLOAD_OVER (1<<2) -/** Card Interrupt Case bit : Host event */ -#define IF_SPI_CIC_HOST_EVENT (1<<3) -/** Card Interrupt Case bit : Command upload over */ -#define IF_SPI_CIC_CMD_UPLOAD_OVER (1<<4) -/** Card Interrupt Case bit : Power down */ -#define IF_SPI_CIC_POWER_DOWN (1<<5) - -/***************** IF_SPI_CARD_INT_STATUS_REG *****************/ -#define IF_SPI_CIS_TX_DOWNLOAD_OVER (1<<0) -#define IF_SPI_CIS_RX_UPLOAD_OVER (1<<1) -#define IF_SPI_CIS_CMD_DOWNLOAD_OVER (1<<2) -#define IF_SPI_CIS_HOST_EVENT (1<<3) -#define IF_SPI_CIS_CMD_UPLOAD_OVER (1<<4) -#define IF_SPI_CIS_POWER_DOWN (1<<5) - -/***************** IF_SPI_HOST_INT_CAUSE_REG *****************/ -#define IF_SPI_HICU_TX_DOWNLOAD_RDY (1<<0) -#define IF_SPI_HICU_RX_UPLOAD_RDY (1<<1) -#define IF_SPI_HICU_CMD_DOWNLOAD_RDY (1<<2) -#define IF_SPI_HICU_CARD_EVENT (1<<3) -#define IF_SPI_HICU_CMD_UPLOAD_RDY (1<<4) -#define IF_SPI_HICU_IO_WR_FIFO_OVERFLOW (1<<5) -#define IF_SPI_HICU_IO_RD_FIFO_UNDERFLOW (1<<6) -#define IF_SPI_HICU_DATA_WR_FIFO_OVERFLOW (1<<7) -#define IF_SPI_HICU_DATA_RD_FIFO_UNDERFLOW (1<<8) -#define IF_SPI_HICU_CMD_WR_FIFO_OVERFLOW (1<<9) -#define IF_SPI_HICU_CMD_RD_FIFO_UNDERFLOW (1<<10) - -/***************** IF_SPI_HOST_INT_STATUS_REG *****************/ -/** Host Interrupt Status bit : Tx download ready */ -#define IF_SPI_HIST_TX_DOWNLOAD_RDY (1<<0) -/** Host Interrupt Status bit : Rx upload ready */ -#define IF_SPI_HIST_RX_UPLOAD_RDY (1<<1) -/** Host Interrupt Status bit : Command download ready */ -#define IF_SPI_HIST_CMD_DOWNLOAD_RDY (1<<2) -/** Host Interrupt Status bit : Card event */ -#define IF_SPI_HIST_CARD_EVENT (1<<3) -/** Host Interrupt Status bit : Command upload ready */ -#define IF_SPI_HIST_CMD_UPLOAD_RDY (1<<4) -/** Host Interrupt Status bit : I/O write FIFO overflow */ -#define IF_SPI_HIST_IO_WR_FIFO_OVERFLOW (1<<5) -/** Host Interrupt Status bit : I/O read FIFO underflow */ -#define IF_SPI_HIST_IO_RD_FIFO_UNDRFLOW (1<<6) -/** Host Interrupt Status bit : Data write FIFO overflow */ -#define IF_SPI_HIST_DATA_WR_FIFO_OVERFLOW (1<<7) -/** Host Interrupt Status bit : Data read FIFO underflow */ -#define IF_SPI_HIST_DATA_RD_FIFO_UNDERFLOW (1<<8) -/** Host Interrupt Status bit : Command write FIFO overflow */ -#define IF_SPI_HIST_CMD_WR_FIFO_OVERFLOW (1<<9) -/** Host Interrupt Status bit : Command read FIFO underflow */ -#define IF_SPI_HIST_CMD_RD_FIFO_UNDERFLOW (1<<10) - -/***************** IF_SPI_HOST_INT_STATUS_MASK_REG *****************/ -/** Host Interrupt Status Mask bit : Tx download ready */ -#define IF_SPI_HISM_TX_DOWNLOAD_RDY (1<<0) -/** Host Interrupt Status Mask bit : Rx upload ready */ -#define IF_SPI_HISM_RX_UPLOAD_RDY (1<<1) -/** Host Interrupt Status Mask bit : Command download ready */ -#define IF_SPI_HISM_CMD_DOWNLOAD_RDY (1<<2) -/** Host Interrupt Status Mask bit : Card event */ -#define IF_SPI_HISM_CARDEVENT (1<<3) -/** Host Interrupt Status Mask bit : Command upload ready */ -#define IF_SPI_HISM_CMD_UPLOAD_RDY (1<<4) -/** Host Interrupt Status Mask bit : I/O write FIFO overflow */ -#define IF_SPI_HISM_IO_WR_FIFO_OVERFLOW (1<<5) -/** Host Interrupt Status Mask bit : I/O read FIFO underflow */ -#define IF_SPI_HISM_IO_RD_FIFO_UNDERFLOW (1<<6) -/** Host Interrupt Status Mask bit : Data write FIFO overflow */ -#define IF_SPI_HISM_DATA_WR_FIFO_OVERFLOW (1<<7) -/** Host Interrupt Status Mask bit : Data write FIFO underflow */ -#define IF_SPI_HISM_DATA_RD_FIFO_UNDERFLOW (1<<8) -/** Host Interrupt Status Mask bit : Command write FIFO overflow */ -#define IF_SPI_HISM_CMD_WR_FIFO_OVERFLOW (1<<9) -/** Host Interrupt Status Mask bit : Command write FIFO underflow */ -#define IF_SPI_HISM_CMD_RD_FIFO_UNDERFLOW (1<<10) - -/***************** IF_SPI_SPU_BUS_MODE_REG *****************/ -/* SCK edge on which the WLAN module outputs data on MISO */ -#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_FALLING 0x8 -#define IF_SPI_BUS_MODE_SPI_CLOCK_PHASE_RISING 0x0 - -/* In a SPU read operation, there is a delay between writing the SPU - * register name and getting back data from the WLAN module. - * This can be specified in terms of nanoseconds or in terms of dummy - * clock cycles which the master must output before receiving a response. */ -#define IF_SPI_BUS_MODE_DELAY_METHOD_DUMMY_CLOCK 0x4 -#define IF_SPI_BUS_MODE_DELAY_METHOD_TIMED 0x0 - -/* Some different modes of SPI operation */ -#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_16_BIT_DATA 0x00 -#define IF_SPI_BUS_MODE_8_BIT_ADDRESS_32_BIT_DATA 0x01 -#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_16_BIT_DATA 0x02 -#define IF_SPI_BUS_MODE_16_BIT_ADDRESS_32_BIT_DATA 0x03 - -#endif diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c deleted file mode 100644 index 3fac4efa5ac8..000000000000 --- a/drivers/net/wireless/libertas/if_usb.c +++ /dev/null @@ -1,1112 +0,0 @@ -/** - * This file contains functions used in USB interface module. - */ -#include -#include -#include -#include -#include - -#ifdef CONFIG_OLPC -#include -#endif - -#define DRV_NAME "usb8xxx" - -#include "host.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "cmd.h" -#include "if_usb.h" - -#define INSANEDEBUG 0 -#define lbs_deb_usb2(...) do { if (INSANEDEBUG) lbs_deb_usbd(__VA_ARGS__); } while (0) - -#define MESSAGE_HEADER_LEN 4 - -static char *lbs_fw_name = "usb8388.bin"; -module_param_named(fw_name, lbs_fw_name, charp, 0644); - -static struct usb_device_id if_usb_table[] = { - /* Enter the device signature inside */ - { USB_DEVICE(0x1286, 0x2001) }, - { USB_DEVICE(0x05a3, 0x8388) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, if_usb_table); - -static void if_usb_receive(struct urb *urb); -static void if_usb_receive_fwload(struct urb *urb); -static int __if_usb_prog_firmware(struct if_usb_card *cardp, - const char *fwname, int cmd); -static int if_usb_prog_firmware(struct if_usb_card *cardp, - const char *fwname, int cmd); -static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, - uint8_t *payload, uint16_t nb); -static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, - uint16_t nb); -static void if_usb_free(struct if_usb_card *cardp); -static int if_usb_submit_rx_urb(struct if_usb_card *cardp); -static int if_usb_reset_device(struct if_usb_card *cardp); - -/* sysfs hooks */ - -/** - * Set function to write firmware to device's persistent memory - */ -static ssize_t if_usb_firmware_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct if_usb_card *cardp = priv->card; - int ret; - - ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_FW); - if (ret == 0) - return count; - - return ret; -} - -/** - * lbs_flash_fw attribute to be exported per ethX interface through sysfs - * (/sys/class/net/ethX/lbs_flash_fw). Use this like so to write firmware to - * the device's persistent memory: - * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_fw - */ -static DEVICE_ATTR(lbs_flash_fw, 0200, NULL, if_usb_firmware_set); - -/** - * Set function to write firmware to device's persistent memory - */ -static ssize_t if_usb_boot2_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct if_usb_card *cardp = priv->card; - int ret; - - ret = if_usb_prog_firmware(cardp, buf, BOOT_CMD_UPDATE_BOOT2); - if (ret == 0) - return count; - - return ret; -} - -/** - * lbs_flash_boot2 attribute to be exported per ethX interface through sysfs - * (/sys/class/net/ethX/lbs_flash_boot2). Use this like so to write firmware - * to the device's persistent memory: - * echo usb8388-5.126.0.p5.bin > /sys/class/net/ethX/lbs_flash_boot2 - */ -static DEVICE_ATTR(lbs_flash_boot2, 0200, NULL, if_usb_boot2_set); - -/** - * @brief call back function to handle the status of the URB - * @param urb pointer to urb structure - * @return N/A - */ -static void if_usb_write_bulk_callback(struct urb *urb) -{ - struct if_usb_card *cardp = (struct if_usb_card *) urb->context; - - /* handle the transmission complete validations */ - - if (urb->status == 0) { - struct lbs_private *priv = cardp->priv; - - lbs_deb_usb2(&urb->dev->dev, "URB status is successful\n"); - lbs_deb_usb2(&urb->dev->dev, "Actual length transmitted %d\n", - urb->actual_length); - - /* Boot commands such as UPDATE_FW and UPDATE_BOOT2 are not - * passed up to the lbs level. - */ - if (priv && priv->dnld_sent != DNLD_BOOTCMD_SENT) - lbs_host_to_card_done(priv); - } else { - /* print the failure status number for debug */ - lbs_pr_info("URB in failure status: %d\n", urb->status); - } - - return; -} - -/** - * @brief free tx/rx urb, skb and rx buffer - * @param cardp pointer if_usb_card - * @return N/A - */ -static void if_usb_free(struct if_usb_card *cardp) -{ - lbs_deb_enter(LBS_DEB_USB); - - /* Unlink tx & rx urb */ - usb_kill_urb(cardp->tx_urb); - usb_kill_urb(cardp->rx_urb); - - usb_free_urb(cardp->tx_urb); - cardp->tx_urb = NULL; - - usb_free_urb(cardp->rx_urb); - cardp->rx_urb = NULL; - - kfree(cardp->ep_out_buf); - cardp->ep_out_buf = NULL; - - lbs_deb_leave(LBS_DEB_USB); -} - -static void if_usb_setup_firmware(struct lbs_private *priv) -{ - struct if_usb_card *cardp = priv->card; - struct cmd_ds_set_boot2_ver b2_cmd; - struct cmd_ds_802_11_fw_wake_method wake_method; - - b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd)); - b2_cmd.action = 0; - b2_cmd.version = cardp->boot2_version; - - if (lbs_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) - lbs_deb_usb("Setting boot2 version failed\n"); - - priv->wol_gpio = 2; /* Wake via GPIO2... */ - priv->wol_gap = 20; /* ... after 20ms */ - lbs_host_sleep_cfg(priv, EHS_WAKE_ON_UNICAST_DATA, - (struct wol_config *) NULL); - - wake_method.hdr.size = cpu_to_le16(sizeof(wake_method)); - wake_method.action = cpu_to_le16(CMD_ACT_GET); - if (lbs_cmd_with_response(priv, CMD_802_11_FW_WAKE_METHOD, &wake_method)) { - lbs_pr_info("Firmware does not seem to support PS mode\n"); - priv->fwcapinfo &= ~FW_CAPINFO_PS; - } else { - if (le16_to_cpu(wake_method.method) == CMD_WAKE_METHOD_COMMAND_INT) { - lbs_deb_usb("Firmware seems to support PS with wake-via-command\n"); - } else { - /* The versions which boot up this way don't seem to - work even if we set it to the command interrupt */ - priv->fwcapinfo &= ~FW_CAPINFO_PS; - lbs_pr_info("Firmware doesn't wake via command interrupt; disabling PS mode\n"); - } - } -} - -static void if_usb_fw_timeo(unsigned long priv) -{ - struct if_usb_card *cardp = (void *)priv; - - if (cardp->fwdnldover) { - lbs_deb_usb("Download complete, no event. Assuming success\n"); - } else { - lbs_pr_err("Download timed out\n"); - cardp->surprise_removed = 1; - } - wake_up(&cardp->fw_wq); -} - -#ifdef CONFIG_OLPC -static void if_usb_reset_olpc_card(struct lbs_private *priv) -{ - printk(KERN_CRIT "Resetting OLPC wireless via EC...\n"); - olpc_ec_cmd(0x25, NULL, 0, NULL, 0); -} -#endif - -/** - * @brief sets the configuration values - * @param ifnum interface number - * @param id pointer to usb_device_id - * @return 0 on success, error code on failure - */ -static int if_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - struct lbs_private *priv; - struct if_usb_card *cardp; - int i; - - udev = interface_to_usbdev(intf); - - cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); - if (!cardp) { - lbs_pr_err("Out of memory allocating private data.\n"); - goto error; - } - - setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); - init_waitqueue_head(&cardp->fw_wq); - - cardp->udev = udev; - iface_desc = intf->cur_altsetting; - - lbs_deb_usbd(&udev->dev, "bcdUSB = 0x%X bDeviceClass = 0x%X" - " bDeviceSubClass = 0x%X, bDeviceProtocol = 0x%X\n", - le16_to_cpu(udev->descriptor.bcdUSB), - udev->descriptor.bDeviceClass, - udev->descriptor.bDeviceSubClass, - udev->descriptor.bDeviceProtocol); - - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_bulk_in(endpoint)) { - cardp->ep_in_size = le16_to_cpu(endpoint->wMaxPacketSize); - cardp->ep_in = usb_endpoint_num(endpoint); - - lbs_deb_usbd(&udev->dev, "in_endpoint = %d\n", cardp->ep_in); - lbs_deb_usbd(&udev->dev, "Bulk in size is %d\n", cardp->ep_in_size); - - } else if (usb_endpoint_is_bulk_out(endpoint)) { - cardp->ep_out_size = le16_to_cpu(endpoint->wMaxPacketSize); - cardp->ep_out = usb_endpoint_num(endpoint); - - lbs_deb_usbd(&udev->dev, "out_endpoint = %d\n", cardp->ep_out); - lbs_deb_usbd(&udev->dev, "Bulk out size is %d\n", cardp->ep_out_size); - } - } - if (!cardp->ep_out_size || !cardp->ep_in_size) { - lbs_deb_usbd(&udev->dev, "Endpoints not found\n"); - goto dealloc; - } - if (!(cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL))) { - lbs_deb_usbd(&udev->dev, "Rx URB allocation failed\n"); - goto dealloc; - } - if (!(cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL))) { - lbs_deb_usbd(&udev->dev, "Tx URB allocation failed\n"); - goto dealloc; - } - cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, GFP_KERNEL); - if (!cardp->ep_out_buf) { - lbs_deb_usbd(&udev->dev, "Could not allocate buffer\n"); - goto dealloc; - } - - /* Upload firmware */ - if (__if_usb_prog_firmware(cardp, lbs_fw_name, BOOT_CMD_FW_BY_USB)) { - lbs_deb_usbd(&udev->dev, "FW upload failed\n"); - goto err_prog_firmware; - } - - if (!(priv = lbs_add_card(cardp, &udev->dev))) - goto err_prog_firmware; - - cardp->priv = priv; - cardp->priv->fw_ready = 1; - - priv->hw_host_to_card = if_usb_host_to_card; -#ifdef CONFIG_OLPC - if (machine_is_olpc()) - priv->reset_card = if_usb_reset_olpc_card; -#endif - - cardp->boot2_version = udev->descriptor.bcdDevice; - - if_usb_submit_rx_urb(cardp); - - if (lbs_start_card(priv)) - goto err_start_card; - - if_usb_setup_firmware(priv); - - usb_get_dev(udev); - usb_set_intfdata(intf, cardp); - - if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_fw)) - lbs_pr_err("cannot register lbs_flash_fw attribute\n"); - - if (device_create_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2)) - lbs_pr_err("cannot register lbs_flash_boot2 attribute\n"); - - return 0; - -err_start_card: - lbs_remove_card(priv); -err_prog_firmware: - if_usb_reset_device(cardp); -dealloc: - if_usb_free(cardp); - -error: - return -ENOMEM; -} - -/** - * @brief free resource and cleanup - * @param intf USB interface structure - * @return N/A - */ -static void if_usb_disconnect(struct usb_interface *intf) -{ - struct if_usb_card *cardp = usb_get_intfdata(intf); - struct lbs_private *priv = (struct lbs_private *) cardp->priv; - - lbs_deb_enter(LBS_DEB_MAIN); - - device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_boot2); - device_remove_file(&priv->dev->dev, &dev_attr_lbs_flash_fw); - - cardp->surprise_removed = 1; - - if (priv) { - priv->surpriseremoved = 1; - lbs_stop_card(priv); - lbs_remove_card(priv); - } - - /* Unlink and free urb */ - if_usb_free(cardp); - - usb_set_intfdata(intf, NULL); - usb_put_dev(interface_to_usbdev(intf)); - - lbs_deb_leave(LBS_DEB_MAIN); -} - -/** - * @brief This function download FW - * @param priv pointer to struct lbs_private - * @return 0 - */ -static int if_usb_send_fw_pkt(struct if_usb_card *cardp) -{ - struct fwdata *fwdata = cardp->ep_out_buf; - const uint8_t *firmware = cardp->fw->data; - - /* If we got a CRC failure on the last block, back - up and retry it */ - if (!cardp->CRC_OK) { - cardp->totalbytes = cardp->fwlastblksent; - cardp->fwseqnum--; - } - - lbs_deb_usb2(&cardp->udev->dev, "totalbytes = %d\n", - cardp->totalbytes); - - /* struct fwdata (which we sent to the card) has an - extra __le32 field in between the header and the data, - which is not in the struct fwheader in the actual - firmware binary. Insert the seqnum in the middle... */ - memcpy(&fwdata->hdr, &firmware[cardp->totalbytes], - sizeof(struct fwheader)); - - cardp->fwlastblksent = cardp->totalbytes; - cardp->totalbytes += sizeof(struct fwheader); - - memcpy(fwdata->data, &firmware[cardp->totalbytes], - le32_to_cpu(fwdata->hdr.datalength)); - - lbs_deb_usb2(&cardp->udev->dev, "Data length = %d\n", - le32_to_cpu(fwdata->hdr.datalength)); - - fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum); - cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength); - - usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) + - le32_to_cpu(fwdata->hdr.datalength)); - - if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_DATA_TO_RECV)) { - lbs_deb_usb2(&cardp->udev->dev, "There are data to follow\n"); - lbs_deb_usb2(&cardp->udev->dev, "seqnum = %d totalbytes = %d\n", - cardp->fwseqnum, cardp->totalbytes); - } else if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) { - lbs_deb_usb2(&cardp->udev->dev, "Host has finished FW downloading\n"); - lbs_deb_usb2(&cardp->udev->dev, "Donwloading FW JUMP BLOCK\n"); - - cardp->fwfinalblk = 1; - } - - lbs_deb_usb2(&cardp->udev->dev, "Firmware download done; size %d\n", - cardp->totalbytes); - - return 0; -} - -static int if_usb_reset_device(struct if_usb_card *cardp) -{ - struct cmd_ds_command *cmd = cardp->ep_out_buf + 4; - int ret; - - lbs_deb_enter(LBS_DEB_USB); - - *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); - - cmd->command = cpu_to_le16(CMD_802_11_RESET); - cmd->size = cpu_to_le16(sizeof(struct cmd_header)); - cmd->result = cpu_to_le16(0); - cmd->seqnum = cpu_to_le16(0x5a5a); - usb_tx_block(cardp, cardp->ep_out_buf, 4 + sizeof(struct cmd_header)); - - msleep(100); - ret = usb_reset_device(cardp->udev); - msleep(100); - -#ifdef CONFIG_OLPC - if (ret && machine_is_olpc()) - if_usb_reset_olpc_card(NULL); -#endif - - lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); - - return ret; -} - -/** - * @brief This function transfer the data to the device. - * @param priv pointer to struct lbs_private - * @param payload pointer to payload data - * @param nb data length - * @return 0 or -1 - */ -static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, uint16_t nb) -{ - int ret = -1; - - /* check if device is removed */ - if (cardp->surprise_removed) { - lbs_deb_usbd(&cardp->udev->dev, "Device removed\n"); - goto tx_ret; - } - - usb_fill_bulk_urb(cardp->tx_urb, cardp->udev, - usb_sndbulkpipe(cardp->udev, - cardp->ep_out), - payload, nb, if_usb_write_bulk_callback, cardp); - - cardp->tx_urb->transfer_flags |= URB_ZERO_PACKET; - - if ((ret = usb_submit_urb(cardp->tx_urb, GFP_ATOMIC))) { - lbs_deb_usbd(&cardp->udev->dev, "usb_submit_urb failed: %d\n", ret); - ret = -1; - } else { - lbs_deb_usb2(&cardp->udev->dev, "usb_submit_urb success\n"); - ret = 0; - } - -tx_ret: - return ret; -} - -static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, - void (*callbackfn)(struct urb *urb)) -{ - struct sk_buff *skb; - int ret = -1; - - if (!(skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE))) { - lbs_pr_err("No free skb\n"); - goto rx_ret; - } - - cardp->rx_skb = skb; - - /* Fill the receive configuration URB and initialise the Rx call back */ - usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, - usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - skb->data + IPFIELD_ALIGN_OFFSET, - MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, - cardp); - - cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - - lbs_deb_usb2(&cardp->udev->dev, "Pointer for rx_urb %p\n", cardp->rx_urb); - if ((ret = usb_submit_urb(cardp->rx_urb, GFP_ATOMIC))) { - lbs_deb_usbd(&cardp->udev->dev, "Submit Rx URB failed: %d\n", ret); - kfree_skb(skb); - cardp->rx_skb = NULL; - ret = -1; - } else { - lbs_deb_usb2(&cardp->udev->dev, "Submit Rx URB success\n"); - ret = 0; - } - -rx_ret: - return ret; -} - -static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp) -{ - return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload); -} - -static int if_usb_submit_rx_urb(struct if_usb_card *cardp) -{ - return __if_usb_submit_rx_urb(cardp, &if_usb_receive); -} - -static void if_usb_receive_fwload(struct urb *urb) -{ - struct if_usb_card *cardp = urb->context; - struct sk_buff *skb = cardp->rx_skb; - struct fwsyncheader *syncfwheader; - struct bootcmdresp bootcmdresp; - - if (urb->status) { - lbs_deb_usbd(&cardp->udev->dev, - "URB status is failed during fw load\n"); - kfree_skb(skb); - return; - } - - if (cardp->fwdnldover) { - __le32 *tmp = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); - - if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && - tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) { - lbs_pr_info("Firmware ready event received\n"); - wake_up(&cardp->fw_wq); - } else { - lbs_deb_usb("Waiting for confirmation; got %x %x\n", - le32_to_cpu(tmp[0]), le32_to_cpu(tmp[1])); - if_usb_submit_rx_urb_fwload(cardp); - } - kfree_skb(skb); - return; - } - if (cardp->bootcmdresp <= 0) { - memcpy (&bootcmdresp, skb->data + IPFIELD_ALIGN_OFFSET, - sizeof(bootcmdresp)); - - if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { - kfree_skb(skb); - if_usb_submit_rx_urb_fwload(cardp); - cardp->bootcmdresp = BOOT_CMD_RESP_OK; - lbs_deb_usbd(&cardp->udev->dev, - "Received valid boot command response\n"); - return; - } - if (bootcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) { - if (bootcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) || - bootcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || - bootcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) { - if (!cardp->bootcmdresp) - lbs_pr_info("Firmware already seems alive; resetting\n"); - cardp->bootcmdresp = -1; - } else { - lbs_pr_info("boot cmd response wrong magic number (0x%x)\n", - le32_to_cpu(bootcmdresp.magic)); - } - } else if ((bootcmdresp.cmd != BOOT_CMD_FW_BY_USB) && - (bootcmdresp.cmd != BOOT_CMD_UPDATE_FW) && - (bootcmdresp.cmd != BOOT_CMD_UPDATE_BOOT2)) { - lbs_pr_info("boot cmd response cmd_tag error (%d)\n", - bootcmdresp.cmd); - } else if (bootcmdresp.result != BOOT_CMD_RESP_OK) { - lbs_pr_info("boot cmd response result error (%d)\n", - bootcmdresp.result); - } else { - cardp->bootcmdresp = 1; - lbs_deb_usbd(&cardp->udev->dev, - "Received valid boot command response\n"); - } - kfree_skb(skb); - if_usb_submit_rx_urb_fwload(cardp); - return; - } - - syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); - if (!syncfwheader) { - lbs_deb_usbd(&cardp->udev->dev, "Failure to allocate syncfwheader\n"); - kfree_skb(skb); - return; - } - - memcpy(syncfwheader, skb->data + IPFIELD_ALIGN_OFFSET, - sizeof(struct fwsyncheader)); - - if (!syncfwheader->cmd) { - lbs_deb_usb2(&cardp->udev->dev, "FW received Blk with correct CRC\n"); - lbs_deb_usb2(&cardp->udev->dev, "FW received Blk seqnum = %d\n", - le32_to_cpu(syncfwheader->seqnum)); - cardp->CRC_OK = 1; - } else { - lbs_deb_usbd(&cardp->udev->dev, "FW received Blk with CRC error\n"); - cardp->CRC_OK = 0; - } - - kfree_skb(skb); - - /* Give device 5s to either write firmware to its RAM or eeprom */ - mod_timer(&cardp->fw_timeout, jiffies + (HZ*5)); - - if (cardp->fwfinalblk) { - cardp->fwdnldover = 1; - goto exit; - } - - if_usb_send_fw_pkt(cardp); - - exit: - if_usb_submit_rx_urb_fwload(cardp); - - kfree(syncfwheader); - - return; -} - -#define MRVDRV_MIN_PKT_LEN 30 - -static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, - struct if_usb_card *cardp, - struct lbs_private *priv) -{ - if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN - || recvlength < MRVDRV_MIN_PKT_LEN) { - lbs_deb_usbd(&cardp->udev->dev, "Packet length is Invalid\n"); - kfree_skb(skb); - return; - } - - skb_reserve(skb, IPFIELD_ALIGN_OFFSET); - skb_put(skb, recvlength); - skb_pull(skb, MESSAGE_HEADER_LEN); - - lbs_process_rxed_packet(priv, skb); -} - -static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, - struct sk_buff *skb, - struct if_usb_card *cardp, - struct lbs_private *priv) -{ - u8 i; - - if (recvlength > LBS_CMD_BUFFER_SIZE) { - lbs_deb_usbd(&cardp->udev->dev, - "The receive buffer is too large\n"); - kfree_skb(skb); - return; - } - - BUG_ON(!in_interrupt()); - - spin_lock(&priv->driver_lock); - - i = (priv->resp_idx == 0) ? 1 : 0; - BUG_ON(priv->resp_len[i]); - priv->resp_len[i] = (recvlength - MESSAGE_HEADER_LEN); - memcpy(priv->resp_buf[i], recvbuff + MESSAGE_HEADER_LEN, - priv->resp_len[i]); - kfree_skb(skb); - lbs_notify_command_response(priv, i); - - spin_unlock(&priv->driver_lock); - - lbs_deb_usbd(&cardp->udev->dev, - "Wake up main thread to handle cmd response\n"); -} - -/** - * @brief This function reads of the packet into the upload buff, - * wake up the main thread and initialise the Rx callack. - * - * @param urb pointer to struct urb - * @return N/A - */ -static void if_usb_receive(struct urb *urb) -{ - struct if_usb_card *cardp = urb->context; - struct sk_buff *skb = cardp->rx_skb; - struct lbs_private *priv = cardp->priv; - int recvlength = urb->actual_length; - uint8_t *recvbuff = NULL; - uint32_t recvtype = 0; - __le32 *pkt = (__le32 *)(skb->data + IPFIELD_ALIGN_OFFSET); - uint32_t event; - - lbs_deb_enter(LBS_DEB_USB); - - if (recvlength) { - if (urb->status) { - lbs_deb_usbd(&cardp->udev->dev, "RX URB failed: %d\n", - urb->status); - kfree_skb(skb); - goto setup_for_next; - } - - recvbuff = skb->data + IPFIELD_ALIGN_OFFSET; - recvtype = le32_to_cpu(pkt[0]); - lbs_deb_usbd(&cardp->udev->dev, - "Recv length = 0x%x, Recv type = 0x%X\n", - recvlength, recvtype); - } else if (urb->status) { - kfree_skb(skb); - goto rx_exit; - } - - switch (recvtype) { - case CMD_TYPE_DATA: - process_cmdtypedata(recvlength, skb, cardp, priv); - break; - - case CMD_TYPE_REQUEST: - process_cmdrequest(recvlength, recvbuff, skb, cardp, priv); - break; - - case CMD_TYPE_INDICATION: - /* Event handling */ - event = le32_to_cpu(pkt[1]); - lbs_deb_usbd(&cardp->udev->dev, "**EVENT** 0x%X\n", event); - kfree_skb(skb); - - /* Icky undocumented magic special case */ - if (event & 0xffff0000) { - u32 trycount = (event & 0xffff0000) >> 16; - - lbs_send_tx_feedback(priv, trycount); - } else - lbs_queue_event(priv, event & 0xFF); - break; - - default: - lbs_deb_usbd(&cardp->udev->dev, "Unknown command type 0x%X\n", - recvtype); - kfree_skb(skb); - break; - } - -setup_for_next: - if_usb_submit_rx_urb(cardp); -rx_exit: - lbs_deb_leave(LBS_DEB_USB); -} - -/** - * @brief This function downloads data to FW - * @param priv pointer to struct lbs_private structure - * @param type type of data - * @param buf pointer to data buffer - * @param len number of bytes - * @return 0 or -1 - */ -static int if_usb_host_to_card(struct lbs_private *priv, uint8_t type, - uint8_t *payload, uint16_t nb) -{ - struct if_usb_card *cardp = priv->card; - - lbs_deb_usbd(&cardp->udev->dev,"*** type = %u\n", type); - lbs_deb_usbd(&cardp->udev->dev,"size after = %d\n", nb); - - if (type == MVMS_CMD) { - *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); - priv->dnld_sent = DNLD_CMD_SENT; - } else { - *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA); - priv->dnld_sent = DNLD_DATA_SENT; - } - - memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb); - - return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN); -} - -/** - * @brief This function issues Boot command to the Boot2 code - * @param ivalue 1:Boot from FW by USB-Download - * 2:Boot from FW in EEPROM - * @return 0 - */ -static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) -{ - struct bootcmd *bootcmd = cardp->ep_out_buf; - - /* Prepare command */ - bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER); - bootcmd->cmd = ivalue; - memset(bootcmd->pad, 0, sizeof(bootcmd->pad)); - - /* Issue command */ - usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd)); - - return 0; -} - - -/** - * @brief This function checks the validity of Boot2/FW image. - * - * @param data pointer to image - * len image length - * @return 0 or -1 - */ -static int check_fwfile_format(const uint8_t *data, uint32_t totlen) -{ - uint32_t bincmd, exit; - uint32_t blksize, offset, len; - int ret; - - ret = 1; - exit = len = 0; - - do { - struct fwheader *fwh = (void *)data; - - bincmd = le32_to_cpu(fwh->dnldcmd); - blksize = le32_to_cpu(fwh->datalength); - switch (bincmd) { - case FW_HAS_DATA_TO_RECV: - offset = sizeof(struct fwheader) + blksize; - data += offset; - len += offset; - if (len >= totlen) - exit = 1; - break; - case FW_HAS_LAST_BLOCK: - exit = 1; - ret = 0; - break; - default: - exit = 1; - break; - } - } while (!exit); - - if (ret) - lbs_pr_err("firmware file format check FAIL\n"); - else - lbs_deb_fw("firmware file format check PASS\n"); - - return ret; -} - - -/** -* @brief This function programs the firmware subject to cmd -* -* @param cardp the if_usb_card descriptor -* fwname firmware or boot2 image file name -* cmd either BOOT_CMD_FW_BY_USB, BOOT_CMD_UPDATE_FW, -* or BOOT_CMD_UPDATE_BOOT2. -* @return 0 or error code -*/ -static int if_usb_prog_firmware(struct if_usb_card *cardp, - const char *fwname, int cmd) -{ - struct lbs_private *priv = cardp->priv; - unsigned long flags, caps; - int ret; - - caps = priv->fwcapinfo; - if (((cmd == BOOT_CMD_UPDATE_FW) && !(caps & FW_CAPINFO_FIRMWARE_UPGRADE)) || - ((cmd == BOOT_CMD_UPDATE_BOOT2) && !(caps & FW_CAPINFO_BOOT2_UPGRADE))) - return -EOPNOTSUPP; - - /* Ensure main thread is idle. */ - spin_lock_irqsave(&priv->driver_lock, flags); - while (priv->cur_cmd != NULL || priv->dnld_sent != DNLD_RES_RECEIVED) { - spin_unlock_irqrestore(&priv->driver_lock, flags); - if (wait_event_interruptible(priv->waitq, - (priv->cur_cmd == NULL && - priv->dnld_sent == DNLD_RES_RECEIVED))) { - return -ERESTARTSYS; - } - spin_lock_irqsave(&priv->driver_lock, flags); - } - priv->dnld_sent = DNLD_BOOTCMD_SENT; - spin_unlock_irqrestore(&priv->driver_lock, flags); - - ret = __if_usb_prog_firmware(cardp, fwname, cmd); - - spin_lock_irqsave(&priv->driver_lock, flags); - priv->dnld_sent = DNLD_RES_RECEIVED; - spin_unlock_irqrestore(&priv->driver_lock, flags); - - wake_up_interruptible(&priv->waitq); - - return ret; -} - -static int __if_usb_prog_firmware(struct if_usb_card *cardp, - const char *fwname, int cmd) -{ - int i = 0; - static int reset_count = 10; - int ret = 0; - - lbs_deb_enter(LBS_DEB_USB); - - ret = request_firmware(&cardp->fw, fwname, &cardp->udev->dev); - if (ret < 0) { - lbs_pr_err("request_firmware() failed with %#x\n", ret); - lbs_pr_err("firmware %s not found\n", fwname); - goto done; - } - - if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) { - ret = -EINVAL; - goto release_fw; - } - - /* Cancel any pending usb business */ - usb_kill_urb(cardp->rx_urb); - usb_kill_urb(cardp->tx_urb); - - cardp->fwlastblksent = 0; - cardp->fwdnldover = 0; - cardp->totalbytes = 0; - cardp->fwfinalblk = 0; - cardp->bootcmdresp = 0; - -restart: - if (if_usb_submit_rx_urb_fwload(cardp) < 0) { - lbs_deb_usbd(&cardp->udev->dev, "URB submission is failed\n"); - ret = -EIO; - goto release_fw; - } - - cardp->bootcmdresp = 0; - do { - int j = 0; - i++; - if_usb_issue_boot_command(cardp, cmd); - /* wait for command response */ - do { - j++; - msleep_interruptible(100); - } while (cardp->bootcmdresp == 0 && j < 10); - } while (cardp->bootcmdresp == 0 && i < 5); - - if (cardp->bootcmdresp == BOOT_CMD_RESP_NOT_SUPPORTED) { - /* Return to normal operation */ - ret = -EOPNOTSUPP; - usb_kill_urb(cardp->rx_urb); - usb_kill_urb(cardp->tx_urb); - if (if_usb_submit_rx_urb(cardp) < 0) - ret = -EIO; - goto release_fw; - } else if (cardp->bootcmdresp <= 0) { - if (--reset_count >= 0) { - if_usb_reset_device(cardp); - goto restart; - } - ret = -EIO; - goto release_fw; - } - - i = 0; - - cardp->totalbytes = 0; - cardp->fwlastblksent = 0; - cardp->CRC_OK = 1; - cardp->fwdnldover = 0; - cardp->fwseqnum = -1; - cardp->totalbytes = 0; - cardp->fwfinalblk = 0; - - /* Send the first firmware packet... */ - if_usb_send_fw_pkt(cardp); - - /* ... and wait for the process to complete */ - wait_event_interruptible(cardp->fw_wq, cardp->surprise_removed || cardp->fwdnldover); - - del_timer_sync(&cardp->fw_timeout); - usb_kill_urb(cardp->rx_urb); - - if (!cardp->fwdnldover) { - lbs_pr_info("failed to load fw, resetting device!\n"); - if (--reset_count >= 0) { - if_usb_reset_device(cardp); - goto restart; - } - - lbs_pr_info("FW download failure, time = %d ms\n", i * 100); - ret = -EIO; - goto release_fw; - } - - release_fw: - release_firmware(cardp->fw); - cardp->fw = NULL; - - done: - lbs_deb_leave_args(LBS_DEB_USB, "ret %d", ret); - return ret; -} - - -#ifdef CONFIG_PM -static int if_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct if_usb_card *cardp = usb_get_intfdata(intf); - struct lbs_private *priv = cardp->priv; - int ret; - - lbs_deb_enter(LBS_DEB_USB); - - if (priv->psstate != PS_STATE_FULL_POWER) - return -1; - - ret = lbs_suspend(priv); - if (ret) - goto out; - - /* Unlink tx & rx urb */ - usb_kill_urb(cardp->tx_urb); - usb_kill_urb(cardp->rx_urb); - - out: - lbs_deb_leave(LBS_DEB_USB); - return ret; -} - -static int if_usb_resume(struct usb_interface *intf) -{ - struct if_usb_card *cardp = usb_get_intfdata(intf); - struct lbs_private *priv = cardp->priv; - - lbs_deb_enter(LBS_DEB_USB); - - if_usb_submit_rx_urb(cardp); - - lbs_resume(priv); - - lbs_deb_leave(LBS_DEB_USB); - return 0; -} -#else -#define if_usb_suspend NULL -#define if_usb_resume NULL -#endif - -static struct usb_driver if_usb_driver = { - .name = DRV_NAME, - .probe = if_usb_probe, - .disconnect = if_usb_disconnect, - .id_table = if_usb_table, - .suspend = if_usb_suspend, - .resume = if_usb_resume, - .reset_resume = if_usb_resume, -}; - -static int __init if_usb_init_module(void) -{ - int ret = 0; - - lbs_deb_enter(LBS_DEB_MAIN); - - ret = usb_register(&if_usb_driver); - - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); - return ret; -} - -static void __exit if_usb_exit_module(void) -{ - lbs_deb_enter(LBS_DEB_MAIN); - - usb_deregister(&if_usb_driver); - - lbs_deb_leave(LBS_DEB_MAIN); -} - -module_init(if_usb_init_module); -module_exit(if_usb_exit_module); - -MODULE_DESCRIPTION("8388 USB WLAN Driver"); -MODULE_AUTHOR("Marvell International Ltd. and Red Hat, Inc."); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas/if_usb.h b/drivers/net/wireless/libertas/if_usb.h deleted file mode 100644 index 5ba0aee0eb2f..000000000000 --- a/drivers/net/wireless/libertas/if_usb.h +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef _LBS_IF_USB_H -#define _LBS_IF_USB_H - -#include -#include - -struct lbs_private; - -/** - * This file contains definition for USB interface. - */ -#define CMD_TYPE_REQUEST 0xF00DFACE -#define CMD_TYPE_DATA 0xBEADC0DE -#define CMD_TYPE_INDICATION 0xBEEFFACE - -#define IPFIELD_ALIGN_OFFSET 2 - -#define BOOT_CMD_FW_BY_USB 0x01 -#define BOOT_CMD_FW_IN_EEPROM 0x02 -#define BOOT_CMD_UPDATE_BOOT2 0x03 -#define BOOT_CMD_UPDATE_FW 0x04 -#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */ - -struct bootcmd -{ - __le32 magic; - uint8_t cmd; - uint8_t pad[11]; -}; - -#define BOOT_CMD_RESP_OK 0x0001 -#define BOOT_CMD_RESP_FAIL 0x0000 -#define BOOT_CMD_RESP_NOT_SUPPORTED 0x0002 - -struct bootcmdresp -{ - __le32 magic; - uint8_t cmd; - uint8_t result; - uint8_t pad[2]; -}; - -/** USB card description structure*/ -struct if_usb_card { - struct usb_device *udev; - struct urb *rx_urb, *tx_urb; - struct lbs_private *priv; - - struct sk_buff *rx_skb; - - uint8_t ep_in; - uint8_t ep_out; - - /* bootcmdresp == 0 means command is pending - * bootcmdresp < 0 means error - * bootcmdresp > 0 is a BOOT_CMD_RESP_* from firmware - */ - int8_t bootcmdresp; - - int ep_in_size; - - void *ep_out_buf; - int ep_out_size; - - const struct firmware *fw; - struct timer_list fw_timeout; - wait_queue_head_t fw_wq; - uint32_t fwseqnum; - uint32_t totalbytes; - uint32_t fwlastblksent; - uint8_t CRC_OK; - uint8_t fwdnldover; - uint8_t fwfinalblk; - uint8_t surprise_removed; - - __le16 boot2_version; -}; - -/** fwheader */ -struct fwheader { - __le32 dnldcmd; - __le32 baseaddr; - __le32 datalength; - __le32 CRC; -}; - -#define FW_MAX_DATA_BLK_SIZE 600 -/** FWData */ -struct fwdata { - struct fwheader hdr; - __le32 seqnum; - uint8_t data[0]; -}; - -/** fwsyncheader */ -struct fwsyncheader { - __le32 cmd; - __le32 seqnum; -}; - -#define FW_HAS_DATA_TO_RECV 0x00000001 -#define FW_HAS_LAST_BLOCK 0x00000004 - - -#endif diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c deleted file mode 100644 index 87b4e497faa2..000000000000 --- a/drivers/net/wireless/libertas/main.c +++ /dev/null @@ -1,1715 +0,0 @@ -/** - * This file contains the major functions in WLAN - * driver. It includes init, exit, open, close and main - * thread etc.. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "dev.h" -#include "wext.h" -#include "debugfs.h" -#include "scan.h" -#include "assoc.h" -#include "cmd.h" - -#define DRIVER_RELEASE_VERSION "323.p0" -const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION -#ifdef DEBUG - "-dbg" -#endif - ""; - - -/* Module parameters */ -unsigned int lbs_debug; -EXPORT_SYMBOL_GPL(lbs_debug); -module_param_named(libertas_debug, lbs_debug, int, 0644); - - -/* This global structure is used to send the confirm_sleep command as - * fast as possible down to the firmware. */ -struct cmd_confirm_sleep confirm_sleep; - - -#define LBS_TX_PWR_DEFAULT 20 /*100mW */ -#define LBS_TX_PWR_US_DEFAULT 20 /*100mW */ -#define LBS_TX_PWR_JP_DEFAULT 16 /*50mW */ -#define LBS_TX_PWR_FR_DEFAULT 20 /*100mW */ -#define LBS_TX_PWR_EMEA_DEFAULT 20 /*100mW */ - -/* Format { channel, frequency (MHz), maxtxpower } */ -/* band: 'B/G', region: USA FCC/Canada IC */ -static struct chan_freq_power channel_freq_power_US_BG[] = { - {1, 2412, LBS_TX_PWR_US_DEFAULT}, - {2, 2417, LBS_TX_PWR_US_DEFAULT}, - {3, 2422, LBS_TX_PWR_US_DEFAULT}, - {4, 2427, LBS_TX_PWR_US_DEFAULT}, - {5, 2432, LBS_TX_PWR_US_DEFAULT}, - {6, 2437, LBS_TX_PWR_US_DEFAULT}, - {7, 2442, LBS_TX_PWR_US_DEFAULT}, - {8, 2447, LBS_TX_PWR_US_DEFAULT}, - {9, 2452, LBS_TX_PWR_US_DEFAULT}, - {10, 2457, LBS_TX_PWR_US_DEFAULT}, - {11, 2462, LBS_TX_PWR_US_DEFAULT} -}; - -/* band: 'B/G', region: Europe ETSI */ -static struct chan_freq_power channel_freq_power_EU_BG[] = { - {1, 2412, LBS_TX_PWR_EMEA_DEFAULT}, - {2, 2417, LBS_TX_PWR_EMEA_DEFAULT}, - {3, 2422, LBS_TX_PWR_EMEA_DEFAULT}, - {4, 2427, LBS_TX_PWR_EMEA_DEFAULT}, - {5, 2432, LBS_TX_PWR_EMEA_DEFAULT}, - {6, 2437, LBS_TX_PWR_EMEA_DEFAULT}, - {7, 2442, LBS_TX_PWR_EMEA_DEFAULT}, - {8, 2447, LBS_TX_PWR_EMEA_DEFAULT}, - {9, 2452, LBS_TX_PWR_EMEA_DEFAULT}, - {10, 2457, LBS_TX_PWR_EMEA_DEFAULT}, - {11, 2462, LBS_TX_PWR_EMEA_DEFAULT}, - {12, 2467, LBS_TX_PWR_EMEA_DEFAULT}, - {13, 2472, LBS_TX_PWR_EMEA_DEFAULT} -}; - -/* band: 'B/G', region: Spain */ -static struct chan_freq_power channel_freq_power_SPN_BG[] = { - {10, 2457, LBS_TX_PWR_DEFAULT}, - {11, 2462, LBS_TX_PWR_DEFAULT} -}; - -/* band: 'B/G', region: France */ -static struct chan_freq_power channel_freq_power_FR_BG[] = { - {10, 2457, LBS_TX_PWR_FR_DEFAULT}, - {11, 2462, LBS_TX_PWR_FR_DEFAULT}, - {12, 2467, LBS_TX_PWR_FR_DEFAULT}, - {13, 2472, LBS_TX_PWR_FR_DEFAULT} -}; - -/* band: 'B/G', region: Japan */ -static struct chan_freq_power channel_freq_power_JPN_BG[] = { - {1, 2412, LBS_TX_PWR_JP_DEFAULT}, - {2, 2417, LBS_TX_PWR_JP_DEFAULT}, - {3, 2422, LBS_TX_PWR_JP_DEFAULT}, - {4, 2427, LBS_TX_PWR_JP_DEFAULT}, - {5, 2432, LBS_TX_PWR_JP_DEFAULT}, - {6, 2437, LBS_TX_PWR_JP_DEFAULT}, - {7, 2442, LBS_TX_PWR_JP_DEFAULT}, - {8, 2447, LBS_TX_PWR_JP_DEFAULT}, - {9, 2452, LBS_TX_PWR_JP_DEFAULT}, - {10, 2457, LBS_TX_PWR_JP_DEFAULT}, - {11, 2462, LBS_TX_PWR_JP_DEFAULT}, - {12, 2467, LBS_TX_PWR_JP_DEFAULT}, - {13, 2472, LBS_TX_PWR_JP_DEFAULT}, - {14, 2484, LBS_TX_PWR_JP_DEFAULT} -}; - -/** - * the structure for channel, frequency and power - */ -struct region_cfp_table { - u8 region; - struct chan_freq_power *cfp_BG; - int cfp_no_BG; -}; - -/** - * the structure for the mapping between region and CFP - */ -static struct region_cfp_table region_cfp_table[] = { - {0x10, /*US FCC */ - channel_freq_power_US_BG, - ARRAY_SIZE(channel_freq_power_US_BG), - } - , - {0x20, /*CANADA IC */ - channel_freq_power_US_BG, - ARRAY_SIZE(channel_freq_power_US_BG), - } - , - {0x30, /*EU*/ channel_freq_power_EU_BG, - ARRAY_SIZE(channel_freq_power_EU_BG), - } - , - {0x31, /*SPAIN*/ channel_freq_power_SPN_BG, - ARRAY_SIZE(channel_freq_power_SPN_BG), - } - , - {0x32, /*FRANCE*/ channel_freq_power_FR_BG, - ARRAY_SIZE(channel_freq_power_FR_BG), - } - , - {0x40, /*JAPAN*/ channel_freq_power_JPN_BG, - ARRAY_SIZE(channel_freq_power_JPN_BG), - } - , -/*Add new region here */ -}; - -/** - * the table to keep region code - */ -u16 lbs_region_code_to_index[MRVDRV_MAX_REGION_CODE] = - { 0x10, 0x20, 0x30, 0x31, 0x32, 0x40 }; - -/** - * 802.11b/g supported bitrates (in 500Kb/s units) - */ -u8 lbs_bg_rates[MAX_RATES] = - { 0x02, 0x04, 0x0b, 0x16, 0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c, -0x00, 0x00 }; - -/** - * FW rate table. FW refers to rates by their index in this table, not by the - * rate value itself. Values of 0x00 are - * reserved positions. - */ -static u8 fw_data_rates[MAX_RATES] = - { 0x02, 0x04, 0x0B, 0x16, 0x00, 0x0C, 0x12, - 0x18, 0x24, 0x30, 0x48, 0x60, 0x6C, 0x00 -}; - -/** - * @brief use index to get the data rate - * - * @param idx The index of data rate - * @return data rate or 0 - */ -u32 lbs_fw_index_to_data_rate(u8 idx) -{ - if (idx >= sizeof(fw_data_rates)) - idx = 0; - return fw_data_rates[idx]; -} - -/** - * @brief use rate to get the index - * - * @param rate data rate - * @return index or 0 - */ -u8 lbs_data_rate_to_fw_index(u32 rate) -{ - u8 i; - - if (!rate) - return 0; - - for (i = 0; i < sizeof(fw_data_rates); i++) { - if (rate == fw_data_rates[i]) - return i; - } - return 0; -} - -/** - * Attributes exported through sysfs - */ - -/** - * @brief Get function for sysfs attribute anycast_mask - */ -static ssize_t lbs_anycast_get(struct device *dev, - struct device_attribute *attr, char * buf) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_access mesh_access; - int ret; - - memset(&mesh_access, 0, sizeof(mesh_access)); - - ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access); - if (ret) - return ret; - - return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0])); -} - -/** - * @brief Set function for sysfs attribute anycast_mask - */ -static ssize_t lbs_anycast_set(struct device *dev, - struct device_attribute *attr, const char * buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_access mesh_access; - uint32_t datum; - int ret; - - memset(&mesh_access, 0, sizeof(mesh_access)); - sscanf(buf, "%x", &datum); - mesh_access.data[0] = cpu_to_le32(datum); - - ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute prb_rsp_limit - */ -static ssize_t lbs_prb_rsp_limit_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_access mesh_access; - int ret; - u32 retry_limit; - - memset(&mesh_access, 0, sizeof(mesh_access)); - mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET); - - ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, - &mesh_access); - if (ret) - return ret; - - retry_limit = le32_to_cpu(mesh_access.data[1]); - return snprintf(buf, 10, "%d\n", retry_limit); -} - -/** - * @brief Set function for sysfs attribute prb_rsp_limit - */ -static ssize_t lbs_prb_rsp_limit_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_access mesh_access; - int ret; - unsigned long retry_limit; - - memset(&mesh_access, 0, sizeof(mesh_access)); - mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET); - - if (!strict_strtoul(buf, 10, &retry_limit)) - return -ENOTSUPP; - if (retry_limit > 15) - return -ENOTSUPP; - - mesh_access.data[1] = cpu_to_le32(retry_limit); - - ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT, - &mesh_access); - if (ret) - return ret; - - return strlen(buf); -} - -static int lbs_add_rtap(struct lbs_private *priv); -static void lbs_remove_rtap(struct lbs_private *priv); -static int lbs_add_mesh(struct lbs_private *priv); -static void lbs_remove_mesh(struct lbs_private *priv); - - -/** - * Get function for sysfs attribute rtap - */ -static ssize_t lbs_rtap_get(struct device *dev, - struct device_attribute *attr, char * buf) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - return snprintf(buf, 5, "0x%X\n", priv->monitormode); -} - -/** - * Set function for sysfs attribute rtap - */ -static ssize_t lbs_rtap_set(struct device *dev, - struct device_attribute *attr, const char * buf, size_t count) -{ - int monitor_mode; - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - - sscanf(buf, "%x", &monitor_mode); - if (monitor_mode) { - if (priv->monitormode == monitor_mode) - return strlen(buf); - if (!priv->monitormode) { - if (priv->infra_open || priv->mesh_open) - return -EBUSY; - if (priv->mode == IW_MODE_INFRA) - lbs_cmd_80211_deauthenticate(priv, - priv->curbssparams.bssid, - WLAN_REASON_DEAUTH_LEAVING); - else if (priv->mode == IW_MODE_ADHOC) - lbs_adhoc_stop(priv); - lbs_add_rtap(priv); - } - priv->monitormode = monitor_mode; - } else { - if (!priv->monitormode) - return strlen(buf); - priv->monitormode = 0; - lbs_remove_rtap(priv); - - if (priv->currenttxskb) { - dev_kfree_skb_any(priv->currenttxskb); - priv->currenttxskb = NULL; - } - - /* Wake queues, command thread, etc. */ - lbs_host_to_card_done(priv); - } - - lbs_prepare_and_send_command(priv, - CMD_802_11_MONITOR_MODE, CMD_ACT_SET, - CMD_OPTION_WAITFORRSP, 0, &priv->monitormode); - return strlen(buf); -} - -/** - * lbs_rtap attribute to be exported per ethX interface - * through sysfs (/sys/class/net/ethX/lbs_rtap) - */ -static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); - -/** - * Get function for sysfs attribute mesh - */ -static ssize_t lbs_mesh_get(struct device *dev, - struct device_attribute *attr, char * buf) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev); -} - -/** - * Set function for sysfs attribute mesh - */ -static ssize_t lbs_mesh_set(struct device *dev, - struct device_attribute *attr, const char * buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - int enable; - int ret, action = CMD_ACT_MESH_CONFIG_STOP; - - sscanf(buf, "%x", &enable); - enable = !!enable; - if (enable == !!priv->mesh_dev) - return count; - if (enable) - action = CMD_ACT_MESH_CONFIG_START; - ret = lbs_mesh_config(priv, action, priv->curbssparams.channel); - if (ret) - return ret; - - if (enable) - lbs_add_mesh(priv); - else - lbs_remove_mesh(priv); - - return count; -} - -/** - * lbs_mesh attribute to be exported per ethX interface - * through sysfs (/sys/class/net/ethX/lbs_mesh) - */ -static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set); - -/** - * anycast_mask attribute to be exported per mshX interface - * through sysfs (/sys/class/net/mshX/anycast_mask) - */ -static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set); - -/** - * prb_rsp_limit attribute to be exported per mshX interface - * through sysfs (/sys/class/net/mshX/prb_rsp_limit) - */ -static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get, - lbs_prb_rsp_limit_set); - -static struct attribute *lbs_mesh_sysfs_entries[] = { - &dev_attr_anycast_mask.attr, - &dev_attr_prb_rsp_limit.attr, - NULL, -}; - -static struct attribute_group lbs_mesh_attr_group = { - .attrs = lbs_mesh_sysfs_entries, -}; - -/** - * @brief This function opens the ethX or mshX interface - * - * @param dev A pointer to net_device structure - * @return 0 or -EBUSY if monitor mode active - */ -static int lbs_dev_open(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - - lbs_deb_enter(LBS_DEB_NET); - - spin_lock_irq(&priv->driver_lock); - - if (priv->monitormode) { - ret = -EBUSY; - goto out; - } - - if (dev == priv->mesh_dev) { - priv->mesh_open = 1; - priv->mesh_connect_status = LBS_CONNECTED; - netif_carrier_on(dev); - } else { - priv->infra_open = 1; - - if (priv->connect_status == LBS_CONNECTED) - netif_carrier_on(dev); - else - netif_carrier_off(dev); - } - - if (!priv->tx_pending_len) - netif_wake_queue(dev); - out: - - spin_unlock_irq(&priv->driver_lock); - lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); - return ret; -} - -/** - * @brief This function closes the mshX interface - * - * @param dev A pointer to net_device structure - * @return 0 - */ -static int lbs_mesh_stop(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_MESH); - spin_lock_irq(&priv->driver_lock); - - priv->mesh_open = 0; - priv->mesh_connect_status = LBS_DISCONNECTED; - - netif_stop_queue(dev); - netif_carrier_off(dev); - - spin_unlock_irq(&priv->driver_lock); - - schedule_work(&priv->mcast_work); - - lbs_deb_leave(LBS_DEB_MESH); - return 0; -} - -/** - * @brief This function closes the ethX interface - * - * @param dev A pointer to net_device structure - * @return 0 - */ -static int lbs_eth_stop(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_NET); - - spin_lock_irq(&priv->driver_lock); - priv->infra_open = 0; - netif_stop_queue(dev); - spin_unlock_irq(&priv->driver_lock); - - schedule_work(&priv->mcast_work); - - lbs_deb_leave(LBS_DEB_NET); - return 0; -} - -static void lbs_tx_timeout(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_TX); - - lbs_pr_err("tx watch dog timeout\n"); - - dev->trans_start = jiffies; - - if (priv->currenttxskb) - lbs_send_tx_feedback(priv, 0); - - /* XX: Shouldn't we also call into the hw-specific driver - to kick it somehow? */ - lbs_host_to_card_done(priv); - - /* More often than not, this actually happens because the - firmware has crapped itself -- rather than just a very - busy medium. So send a harmless command, and if/when - _that_ times out, we'll kick it in the head. */ - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - 0, 0, NULL); - - lbs_deb_leave(LBS_DEB_TX); -} - -void lbs_host_to_card_done(struct lbs_private *priv) -{ - unsigned long flags; - - lbs_deb_enter(LBS_DEB_THREAD); - - spin_lock_irqsave(&priv->driver_lock, flags); - - priv->dnld_sent = DNLD_RES_RECEIVED; - - /* Wake main thread if commands are pending */ - if (!priv->cur_cmd || priv->tx_pending_len > 0) - wake_up_interruptible(&priv->waitq); - - spin_unlock_irqrestore(&priv->driver_lock, flags); - lbs_deb_leave(LBS_DEB_THREAD); -} -EXPORT_SYMBOL_GPL(lbs_host_to_card_done); - -static int lbs_set_mac_address(struct net_device *dev, void *addr) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - struct sockaddr *phwaddr = addr; - struct cmd_ds_802_11_mac_address cmd; - - lbs_deb_enter(LBS_DEB_NET); - - /* In case it was called from the mesh device */ - dev = priv->dev; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN); - - ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd); - if (ret) { - lbs_deb_net("set MAC address failed\n"); - goto done; - } - - memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); - memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN); - if (priv->mesh_dev) - memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN); - -done: - lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); - return ret; -} - - -static inline int mac_in_list(unsigned char *list, int list_len, - unsigned char *mac) -{ - while (list_len) { - if (!memcmp(list, mac, ETH_ALEN)) - return 1; - list += ETH_ALEN; - list_len--; - } - return 0; -} - - -static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd, - struct net_device *dev, int nr_addrs) -{ - int i = nr_addrs; - struct dev_mc_list *mc_list; - - if ((dev->flags & (IFF_UP|IFF_MULTICAST)) != (IFF_UP|IFF_MULTICAST)) - return nr_addrs; - - netif_addr_lock_bh(dev); - for (mc_list = dev->mc_list; mc_list; mc_list = mc_list->next) { - if (mac_in_list(cmd->maclist, nr_addrs, mc_list->dmi_addr)) { - lbs_deb_net("mcast address %s:%pM skipped\n", dev->name, - mc_list->dmi_addr); - continue; - } - - if (i == MRVDRV_MAX_MULTICAST_LIST_SIZE) - break; - memcpy(&cmd->maclist[6*i], mc_list->dmi_addr, ETH_ALEN); - lbs_deb_net("mcast address %s:%pM added to filter\n", dev->name, - mc_list->dmi_addr); - i++; - } - netif_addr_unlock_bh(dev); - if (mc_list) - return -EOVERFLOW; - - return i; -} - -static void lbs_set_mcast_worker(struct work_struct *work) -{ - struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work); - struct cmd_ds_mac_multicast_adr mcast_cmd; - int dev_flags; - int nr_addrs; - int old_mac_control = priv->mac_control; - - lbs_deb_enter(LBS_DEB_NET); - - dev_flags = priv->dev->flags; - if (priv->mesh_dev) - dev_flags |= priv->mesh_dev->flags; - - if (dev_flags & IFF_PROMISC) { - priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; - priv->mac_control &= ~(CMD_ACT_MAC_ALL_MULTICAST_ENABLE | - CMD_ACT_MAC_MULTICAST_ENABLE); - goto out_set_mac_control; - } else if (dev_flags & IFF_ALLMULTI) { - do_allmulti: - priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; - priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | - CMD_ACT_MAC_MULTICAST_ENABLE); - goto out_set_mac_control; - } - - /* Once for priv->dev, again for priv->mesh_dev if it exists */ - nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->dev, 0); - if (nr_addrs >= 0 && priv->mesh_dev) - nr_addrs = lbs_add_mcast_addrs(&mcast_cmd, priv->mesh_dev, nr_addrs); - if (nr_addrs < 0) - goto do_allmulti; - - if (nr_addrs) { - int size = offsetof(struct cmd_ds_mac_multicast_adr, - maclist[6*nr_addrs]); - - mcast_cmd.action = cpu_to_le16(CMD_ACT_SET); - mcast_cmd.hdr.size = cpu_to_le16(size); - mcast_cmd.nr_of_adrs = cpu_to_le16(nr_addrs); - - lbs_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &mcast_cmd.hdr, size); - - priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; - } else - priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; - - priv->mac_control &= ~(CMD_ACT_MAC_PROMISCUOUS_ENABLE | - CMD_ACT_MAC_ALL_MULTICAST_ENABLE); - out_set_mac_control: - if (priv->mac_control != old_mac_control) - lbs_set_mac_control(priv); - - lbs_deb_leave(LBS_DEB_NET); -} - -static void lbs_set_multicast_list(struct net_device *dev) -{ - struct lbs_private *priv = dev->ml_priv; - - schedule_work(&priv->mcast_work); -} - -/** - * @brief This function handles the major jobs in the LBS driver. - * It handles all events generated by firmware, RX data received - * from firmware and TX data sent from kernel. - * - * @param data A pointer to lbs_thread structure - * @return 0 - */ -static int lbs_thread(void *data) -{ - struct net_device *dev = data; - struct lbs_private *priv = dev->ml_priv; - wait_queue_t wait; - - lbs_deb_enter(LBS_DEB_THREAD); - - init_waitqueue_entry(&wait, current); - - for (;;) { - int shouldsleep; - u8 resp_idx; - - lbs_deb_thread("1: currenttxskb %p, dnld_sent %d\n", - priv->currenttxskb, priv->dnld_sent); - - add_wait_queue(&priv->waitq, &wait); - set_current_state(TASK_INTERRUPTIBLE); - spin_lock_irq(&priv->driver_lock); - - if (kthread_should_stop()) - shouldsleep = 0; /* Bye */ - else if (priv->surpriseremoved) - shouldsleep = 1; /* We need to wait until we're _told_ to die */ - else if (priv->psstate == PS_STATE_SLEEP) - shouldsleep = 1; /* Sleep mode. Nothing we can do till it wakes */ - else if (priv->cmd_timed_out) - shouldsleep = 0; /* Command timed out. Recover */ - else if (!priv->fw_ready) - shouldsleep = 1; /* Firmware not ready. We're waiting for it */ - else if (priv->dnld_sent) - shouldsleep = 1; /* Something is en route to the device already */ - else if (priv->tx_pending_len > 0) - shouldsleep = 0; /* We've a packet to send */ - else if (priv->resp_len[priv->resp_idx]) - shouldsleep = 0; /* We have a command response */ - else if (priv->cur_cmd) - shouldsleep = 1; /* Can't send a command; one already running */ - else if (!list_empty(&priv->cmdpendingq)) - shouldsleep = 0; /* We have a command to send */ - else if (__kfifo_len(priv->event_fifo)) - shouldsleep = 0; /* We have an event to process */ - else - shouldsleep = 1; /* No command */ - - if (shouldsleep) { - lbs_deb_thread("sleeping, connect_status %d, " - "psmode %d, psstate %d\n", - priv->connect_status, - priv->psmode, priv->psstate); - spin_unlock_irq(&priv->driver_lock); - schedule(); - } else - spin_unlock_irq(&priv->driver_lock); - - lbs_deb_thread("2: currenttxskb %p, dnld_send %d\n", - priv->currenttxskb, priv->dnld_sent); - - set_current_state(TASK_RUNNING); - remove_wait_queue(&priv->waitq, &wait); - - lbs_deb_thread("3: currenttxskb %p, dnld_sent %d\n", - priv->currenttxskb, priv->dnld_sent); - - if (kthread_should_stop()) { - lbs_deb_thread("break from main thread\n"); - break; - } - - if (priv->surpriseremoved) { - lbs_deb_thread("adapter removed; waiting to die...\n"); - continue; - } - - lbs_deb_thread("4: currenttxskb %p, dnld_sent %d\n", - priv->currenttxskb, priv->dnld_sent); - - /* Process any pending command response */ - spin_lock_irq(&priv->driver_lock); - resp_idx = priv->resp_idx; - if (priv->resp_len[resp_idx]) { - spin_unlock_irq(&priv->driver_lock); - lbs_process_command_response(priv, - priv->resp_buf[resp_idx], - priv->resp_len[resp_idx]); - spin_lock_irq(&priv->driver_lock); - priv->resp_len[resp_idx] = 0; - } - spin_unlock_irq(&priv->driver_lock); - - /* command timeout stuff */ - if (priv->cmd_timed_out && priv->cur_cmd) { - struct cmd_ctrl_node *cmdnode = priv->cur_cmd; - - if (++priv->nr_retries > 3) { - lbs_pr_info("Excessive timeouts submitting " - "command 0x%04x\n", - le16_to_cpu(cmdnode->cmdbuf->command)); - lbs_complete_command(priv, cmdnode, -ETIMEDOUT); - priv->nr_retries = 0; - if (priv->reset_card) - priv->reset_card(priv); - } else { - priv->cur_cmd = NULL; - priv->dnld_sent = DNLD_RES_RECEIVED; - lbs_pr_info("requeueing command 0x%04x due " - "to timeout (#%d)\n", - le16_to_cpu(cmdnode->cmdbuf->command), - priv->nr_retries); - - /* Stick it back at the _top_ of the pending queue - for immediate resubmission */ - list_add(&cmdnode->list, &priv->cmdpendingq); - } - } - priv->cmd_timed_out = 0; - - /* Process hardware events, e.g. card removed, link lost */ - spin_lock_irq(&priv->driver_lock); - while (__kfifo_len(priv->event_fifo)) { - u32 event; - - __kfifo_get(priv->event_fifo, (unsigned char *) &event, - sizeof(event)); - spin_unlock_irq(&priv->driver_lock); - lbs_process_event(priv, event); - spin_lock_irq(&priv->driver_lock); - } - spin_unlock_irq(&priv->driver_lock); - - if (!priv->fw_ready) - continue; - - /* Check if we need to confirm Sleep Request received previously */ - if (priv->psstate == PS_STATE_PRE_SLEEP && - !priv->dnld_sent && !priv->cur_cmd) { - if (priv->connect_status == LBS_CONNECTED) { - lbs_deb_thread("pre-sleep, currenttxskb %p, " - "dnld_sent %d, cur_cmd %p\n", - priv->currenttxskb, priv->dnld_sent, - priv->cur_cmd); - - lbs_ps_confirm_sleep(priv); - } else { - /* workaround for firmware sending - * deauth/linkloss event immediately - * after sleep request; remove this - * after firmware fixes it - */ - priv->psstate = PS_STATE_AWAKE; - lbs_pr_alert("ignore PS_SleepConfirm in " - "non-connected state\n"); - } - } - - /* The PS state is changed during processing of Sleep Request - * event above - */ - if ((priv->psstate == PS_STATE_SLEEP) || - (priv->psstate == PS_STATE_PRE_SLEEP)) - continue; - - /* Execute the next command */ - if (!priv->dnld_sent && !priv->cur_cmd) - lbs_execute_next_command(priv); - - /* Wake-up command waiters which can't sleep in - * lbs_prepare_and_send_command - */ - if (!list_empty(&priv->cmdpendingq)) - wake_up_all(&priv->cmd_pending); - - spin_lock_irq(&priv->driver_lock); - if (!priv->dnld_sent && priv->tx_pending_len > 0) { - int ret = priv->hw_host_to_card(priv, MVMS_DAT, - priv->tx_pending_buf, - priv->tx_pending_len); - if (ret) { - lbs_deb_tx("host_to_card failed %d\n", ret); - priv->dnld_sent = DNLD_RES_RECEIVED; - } - priv->tx_pending_len = 0; - if (!priv->currenttxskb) { - /* We can wake the queues immediately if we aren't - waiting for TX feedback */ - if (priv->connect_status == LBS_CONNECTED) - netif_wake_queue(priv->dev); - if (priv->mesh_dev && - priv->mesh_connect_status == LBS_CONNECTED) - netif_wake_queue(priv->mesh_dev); - } - } - spin_unlock_irq(&priv->driver_lock); - } - - del_timer(&priv->command_timer); - wake_up_all(&priv->cmd_pending); - - lbs_deb_leave(LBS_DEB_THREAD); - return 0; -} - -static int lbs_suspend_callback(struct lbs_private *priv, unsigned long dummy, - struct cmd_header *cmd) -{ - lbs_deb_enter(LBS_DEB_FW); - - netif_device_detach(priv->dev); - if (priv->mesh_dev) - netif_device_detach(priv->mesh_dev); - - priv->fw_ready = 0; - lbs_deb_leave(LBS_DEB_FW); - return 0; -} - -int lbs_suspend(struct lbs_private *priv) -{ - struct cmd_header cmd; - int ret; - - lbs_deb_enter(LBS_DEB_FW); - - if (priv->wol_criteria == 0xffffffff) { - lbs_pr_info("Suspend attempt without configuring wake params!\n"); - return -EINVAL; - } - - memset(&cmd, 0, sizeof(cmd)); - - ret = __lbs_cmd(priv, CMD_802_11_HOST_SLEEP_ACTIVATE, &cmd, - sizeof(cmd), lbs_suspend_callback, 0); - if (ret) - lbs_pr_info("HOST_SLEEP_ACTIVATE failed: %d\n", ret); - - lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); - return ret; -} -EXPORT_SYMBOL_GPL(lbs_suspend); - -void lbs_resume(struct lbs_private *priv) -{ - lbs_deb_enter(LBS_DEB_FW); - - priv->fw_ready = 1; - - /* Firmware doesn't seem to give us RX packets any more - until we send it some command. Might as well update */ - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - 0, 0, NULL); - - netif_device_attach(priv->dev); - if (priv->mesh_dev) - netif_device_attach(priv->mesh_dev); - - lbs_deb_leave(LBS_DEB_FW); -} -EXPORT_SYMBOL_GPL(lbs_resume); - -/** - * @brief This function gets the HW spec from the firmware and sets - * some basic parameters. - * - * @param priv A pointer to struct lbs_private structure - * @return 0 or -1 - */ -static int lbs_setup_firmware(struct lbs_private *priv) -{ - int ret = -1; - s16 curlevel = 0, minlevel = 0, maxlevel = 0; - - lbs_deb_enter(LBS_DEB_FW); - - /* Read MAC address from firmware */ - memset(priv->current_addr, 0xff, ETH_ALEN); - ret = lbs_update_hw_spec(priv); - if (ret) - goto done; - - /* Read power levels if available */ - ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel); - if (ret == 0) { - priv->txpower_cur = curlevel; - priv->txpower_min = minlevel; - priv->txpower_max = maxlevel; - } - - lbs_set_mac_control(priv); -done: - lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret); - return ret; -} - -/** - * This function handles the timeout of command sending. - * It will re-send the same command again. - */ -static void command_timer_fn(unsigned long data) -{ - struct lbs_private *priv = (struct lbs_private *)data; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_CMD); - spin_lock_irqsave(&priv->driver_lock, flags); - - if (!priv->cur_cmd) - goto out; - - lbs_pr_info("command 0x%04x timed out\n", - le16_to_cpu(priv->cur_cmd->cmdbuf->command)); - - priv->cmd_timed_out = 1; - wake_up_interruptible(&priv->waitq); -out: - spin_unlock_irqrestore(&priv->driver_lock, flags); - lbs_deb_leave(LBS_DEB_CMD); -} - -static void lbs_sync_channel_worker(struct work_struct *work) -{ - struct lbs_private *priv = container_of(work, struct lbs_private, - sync_channel); - - lbs_deb_enter(LBS_DEB_MAIN); - if (lbs_update_channel(priv)) - lbs_pr_info("Channel synchronization failed."); - lbs_deb_leave(LBS_DEB_MAIN); -} - - -static int lbs_init_adapter(struct lbs_private *priv) -{ - size_t bufsize; - int i, ret = 0; - - lbs_deb_enter(LBS_DEB_MAIN); - - /* Allocate buffer to store the BSSID list */ - bufsize = MAX_NETWORK_COUNT * sizeof(struct bss_descriptor); - priv->networks = kzalloc(bufsize, GFP_KERNEL); - if (!priv->networks) { - lbs_pr_err("Out of memory allocating beacons\n"); - ret = -1; - goto out; - } - - /* Initialize scan result lists */ - INIT_LIST_HEAD(&priv->network_free_list); - INIT_LIST_HEAD(&priv->network_list); - for (i = 0; i < MAX_NETWORK_COUNT; i++) { - list_add_tail(&priv->networks[i].list, - &priv->network_free_list); - } - - memset(priv->current_addr, 0xff, ETH_ALEN); - - priv->connect_status = LBS_DISCONNECTED; - priv->mesh_connect_status = LBS_DISCONNECTED; - priv->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - priv->mode = IW_MODE_INFRA; - priv->curbssparams.channel = DEFAULT_AD_HOC_CHANNEL; - priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; - priv->radio_on = 1; - priv->enablehwauto = 1; - priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; - priv->psmode = LBS802_11POWERMODECAM; - priv->psstate = PS_STATE_FULL_POWER; - - mutex_init(&priv->lock); - - setup_timer(&priv->command_timer, command_timer_fn, - (unsigned long)priv); - - INIT_LIST_HEAD(&priv->cmdfreeq); - INIT_LIST_HEAD(&priv->cmdpendingq); - - spin_lock_init(&priv->driver_lock); - init_waitqueue_head(&priv->cmd_pending); - - /* Allocate the command buffers */ - if (lbs_allocate_cmd_buffer(priv)) { - lbs_pr_err("Out of memory allocating command buffers\n"); - ret = -ENOMEM; - goto out; - } - priv->resp_idx = 0; - priv->resp_len[0] = priv->resp_len[1] = 0; - - /* Create the event FIFO */ - priv->event_fifo = kfifo_alloc(sizeof(u32) * 16, GFP_KERNEL, NULL); - if (IS_ERR(priv->event_fifo)) { - lbs_pr_err("Out of memory allocating event FIFO buffer\n"); - ret = -ENOMEM; - goto out; - } - -out: - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); - - return ret; -} - -static void lbs_free_adapter(struct lbs_private *priv) -{ - lbs_deb_enter(LBS_DEB_MAIN); - - lbs_free_cmd_buffer(priv); - if (priv->event_fifo) - kfifo_free(priv->event_fifo); - del_timer(&priv->command_timer); - kfree(priv->networks); - priv->networks = NULL; - - lbs_deb_leave(LBS_DEB_MAIN); -} - -static const struct net_device_ops lbs_netdev_ops = { - .ndo_open = lbs_dev_open, - .ndo_stop = lbs_eth_stop, - .ndo_start_xmit = lbs_hard_start_xmit, - .ndo_set_mac_address = lbs_set_mac_address, - .ndo_tx_timeout = lbs_tx_timeout, - .ndo_set_multicast_list = lbs_set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -/** - * @brief This function adds the card. it will probe the - * card, allocate the lbs_priv and initialize the device. - * - * @param card A pointer to card - * @return A pointer to struct lbs_private structure - */ -struct lbs_private *lbs_add_card(void *card, struct device *dmdev) -{ - struct net_device *dev = NULL; - struct lbs_private *priv = NULL; - - lbs_deb_enter(LBS_DEB_MAIN); - - /* Allocate an Ethernet device and register it */ - dev = alloc_etherdev(sizeof(struct lbs_private)); - if (!dev) { - lbs_pr_err("init wlanX device failed\n"); - goto done; - } - priv = netdev_priv(dev); - dev->ml_priv = priv; - - if (lbs_init_adapter(priv)) { - lbs_pr_err("failed to initialize adapter structure.\n"); - goto err_init_adapter; - } - - priv->dev = dev; - priv->card = card; - priv->mesh_open = 0; - priv->infra_open = 0; - - /* Setup the OS Interface to our functions */ - dev->netdev_ops = &lbs_netdev_ops; - dev->watchdog_timeo = 5 * HZ; - dev->ethtool_ops = &lbs_ethtool_ops; -#ifdef WIRELESS_EXT - dev->wireless_handlers = &lbs_handler_def; -#endif - dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - - SET_NETDEV_DEV(dev, dmdev); - - priv->rtap_net_dev = NULL; - strcpy(dev->name, "wlan%d"); - - lbs_deb_thread("Starting main thread...\n"); - init_waitqueue_head(&priv->waitq); - priv->main_thread = kthread_run(lbs_thread, dev, "lbs_main"); - if (IS_ERR(priv->main_thread)) { - lbs_deb_thread("Error creating main thread.\n"); - goto err_init_adapter; - } - - priv->work_thread = create_singlethread_workqueue("lbs_worker"); - INIT_DELAYED_WORK(&priv->assoc_work, lbs_association_worker); - INIT_DELAYED_WORK(&priv->scan_work, lbs_scan_worker); - INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); - INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); - - sprintf(priv->mesh_ssid, "mesh"); - priv->mesh_ssid_len = 4; - - priv->wol_criteria = 0xffffffff; - priv->wol_gpio = 0xff; - - goto done; - -err_init_adapter: - lbs_free_adapter(priv); - free_netdev(dev); - priv = NULL; - -done: - lbs_deb_leave_args(LBS_DEB_MAIN, "priv %p", priv); - return priv; -} -EXPORT_SYMBOL_GPL(lbs_add_card); - - -void lbs_remove_card(struct lbs_private *priv) -{ - struct net_device *dev = priv->dev; - union iwreq_data wrqu; - - lbs_deb_enter(LBS_DEB_MAIN); - - lbs_remove_mesh(priv); - lbs_remove_rtap(priv); - - dev = priv->dev; - - cancel_delayed_work_sync(&priv->scan_work); - cancel_delayed_work_sync(&priv->assoc_work); - cancel_work_sync(&priv->mcast_work); - - /* worker thread destruction blocks on the in-flight command which - * should have been cleared already in lbs_stop_card(). - */ - lbs_deb_main("destroying worker thread\n"); - destroy_workqueue(priv->work_thread); - lbs_deb_main("done destroying worker thread\n"); - - if (priv->psmode == LBS802_11POWERMODEMAX_PSP) { - priv->psmode = LBS802_11POWERMODECAM; - lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); - } - - memset(wrqu.ap_addr.sa_data, 0xaa, ETH_ALEN); - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - wireless_send_event(priv->dev, SIOCGIWAP, &wrqu, NULL); - - /* Stop the thread servicing the interrupts */ - priv->surpriseremoved = 1; - kthread_stop(priv->main_thread); - - lbs_free_adapter(priv); - - priv->dev = NULL; - free_netdev(dev); - - lbs_deb_leave(LBS_DEB_MAIN); -} -EXPORT_SYMBOL_GPL(lbs_remove_card); - - -int lbs_start_card(struct lbs_private *priv) -{ - struct net_device *dev = priv->dev; - int ret = -1; - - lbs_deb_enter(LBS_DEB_MAIN); - - /* poke the firmware */ - ret = lbs_setup_firmware(priv); - if (ret) - goto done; - - /* init 802.11d */ - lbs_init_11d(priv); - - if (register_netdev(dev)) { - lbs_pr_err("cannot register ethX device\n"); - goto done; - } - - lbs_update_channel(priv); - - /* Check mesh FW version and appropriately send the mesh start - * command - */ - if (priv->mesh_fw_ver == MESH_FW_OLD) { - /* Enable mesh, if supported, and work out which TLV it uses. - 0x100 + 291 is an unofficial value used in 5.110.20.pXX - 0x100 + 37 is the official value used in 5.110.21.pXX - but we check them in that order because 20.pXX doesn't - give an error -- it just silently fails. */ - - /* 5.110.20.pXX firmware will fail the command if the channel - doesn't match the existing channel. But only if the TLV - is correct. If the channel is wrong, _BOTH_ versions will - give an error to 0x100+291, and allow 0x100+37 to succeed. - It's just that 5.110.20.pXX will not have done anything - useful */ - - priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; - if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->curbssparams.channel)) { - priv->mesh_tlv = TLV_TYPE_MESH_ID; - if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->curbssparams.channel)) - priv->mesh_tlv = 0; - } - } else if (priv->mesh_fw_ver == MESH_FW_NEW) { - /* 10.0.0.pXX new firmwares should succeed with TLV - * 0x100+37; Do not invoke command with old TLV. - */ - priv->mesh_tlv = TLV_TYPE_MESH_ID; - if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->curbssparams.channel)) - priv->mesh_tlv = 0; - } - if (priv->mesh_tlv) { - lbs_add_mesh(priv); - - if (device_create_file(&dev->dev, &dev_attr_lbs_mesh)) - lbs_pr_err("cannot register lbs_mesh attribute\n"); - - /* While rtap isn't related to mesh, only mesh-enabled - * firmware implements the rtap functionality via - * CMD_802_11_MONITOR_MODE. - */ - if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) - lbs_pr_err("cannot register lbs_rtap attribute\n"); - } - - lbs_debugfs_init_one(priv, dev); - - lbs_pr_info("%s: Marvell WLAN 802.11 adapter\n", dev->name); - - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); - return ret; -} -EXPORT_SYMBOL_GPL(lbs_start_card); - - -void lbs_stop_card(struct lbs_private *priv) -{ - struct net_device *dev; - struct cmd_ctrl_node *cmdnode; - unsigned long flags; - - lbs_deb_enter(LBS_DEB_MAIN); - - if (!priv) - goto out; - dev = priv->dev; - - netif_stop_queue(dev); - netif_carrier_off(dev); - - lbs_debugfs_remove_one(priv); - if (priv->mesh_tlv) { - device_remove_file(&dev->dev, &dev_attr_lbs_mesh); - device_remove_file(&dev->dev, &dev_attr_lbs_rtap); - } - - /* Delete the timeout of the currently processing command */ - del_timer_sync(&priv->command_timer); - - /* Flush pending command nodes */ - spin_lock_irqsave(&priv->driver_lock, flags); - lbs_deb_main("clearing pending commands\n"); - list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { - cmdnode->result = -ENOENT; - cmdnode->cmdwaitqwoken = 1; - wake_up_interruptible(&cmdnode->cmdwait_q); - } - - /* Flush the command the card is currently processing */ - if (priv->cur_cmd) { - lbs_deb_main("clearing current command\n"); - priv->cur_cmd->result = -ENOENT; - priv->cur_cmd->cmdwaitqwoken = 1; - wake_up_interruptible(&priv->cur_cmd->cmdwait_q); - } - lbs_deb_main("done clearing commands\n"); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - unregister_netdev(dev); - -out: - lbs_deb_leave(LBS_DEB_MAIN); -} -EXPORT_SYMBOL_GPL(lbs_stop_card); - - -static const struct net_device_ops mesh_netdev_ops = { - .ndo_open = lbs_dev_open, - .ndo_stop = lbs_mesh_stop, - .ndo_start_xmit = lbs_hard_start_xmit, - .ndo_set_mac_address = lbs_set_mac_address, - .ndo_set_multicast_list = lbs_set_multicast_list, -}; - -/** - * @brief This function adds mshX interface - * - * @param priv A pointer to the struct lbs_private structure - * @return 0 if successful, -X otherwise - */ -static int lbs_add_mesh(struct lbs_private *priv) -{ - struct net_device *mesh_dev = NULL; - int ret = 0; - - lbs_deb_enter(LBS_DEB_MESH); - - /* Allocate a virtual mesh device */ - if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) { - lbs_deb_mesh("init mshX device failed\n"); - ret = -ENOMEM; - goto done; - } - mesh_dev->ml_priv = priv; - priv->mesh_dev = mesh_dev; - - mesh_dev->netdev_ops = &mesh_netdev_ops; - mesh_dev->ethtool_ops = &lbs_ethtool_ops; - memcpy(mesh_dev->dev_addr, priv->dev->dev_addr, - sizeof(priv->dev->dev_addr)); - - SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent); - -#ifdef WIRELESS_EXT - mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def; -#endif - mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - /* Register virtual mesh interface */ - ret = register_netdev(mesh_dev); - if (ret) { - lbs_pr_err("cannot register mshX virtual interface\n"); - goto err_free; - } - - ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); - if (ret) - goto err_unregister; - - lbs_persist_config_init(mesh_dev); - - /* Everything successful */ - ret = 0; - goto done; - -err_unregister: - unregister_netdev(mesh_dev); - -err_free: - free_netdev(mesh_dev); - -done: - lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); - return ret; -} - -static void lbs_remove_mesh(struct lbs_private *priv) -{ - struct net_device *mesh_dev; - - - mesh_dev = priv->mesh_dev; - if (!mesh_dev) - return; - - lbs_deb_enter(LBS_DEB_MESH); - netif_stop_queue(mesh_dev); - netif_carrier_off(mesh_dev); - sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); - lbs_persist_config_remove(mesh_dev); - unregister_netdev(mesh_dev); - priv->mesh_dev = NULL; - free_netdev(mesh_dev); - lbs_deb_leave(LBS_DEB_MESH); -} - -/** - * @brief This function finds the CFP in - * region_cfp_table based on region and band parameter. - * - * @param region The region code - * @param band The band - * @param cfp_no A pointer to CFP number - * @return A pointer to CFP - */ -struct chan_freq_power *lbs_get_region_cfp_table(u8 region, int *cfp_no) -{ - int i, end; - - lbs_deb_enter(LBS_DEB_MAIN); - - end = ARRAY_SIZE(region_cfp_table); - - for (i = 0; i < end ; i++) { - lbs_deb_main("region_cfp_table[i].region=%d\n", - region_cfp_table[i].region); - if (region_cfp_table[i].region == region) { - *cfp_no = region_cfp_table[i].cfp_no_BG; - lbs_deb_leave(LBS_DEB_MAIN); - return region_cfp_table[i].cfp_BG; - } - } - - lbs_deb_leave_args(LBS_DEB_MAIN, "ret NULL"); - return NULL; -} - -int lbs_set_regiontable(struct lbs_private *priv, u8 region, u8 band) -{ - int ret = 0; - int i = 0; - - struct chan_freq_power *cfp; - int cfp_no; - - lbs_deb_enter(LBS_DEB_MAIN); - - memset(priv->region_channel, 0, sizeof(priv->region_channel)); - - cfp = lbs_get_region_cfp_table(region, &cfp_no); - if (cfp != NULL) { - priv->region_channel[i].nrcfp = cfp_no; - priv->region_channel[i].CFP = cfp; - } else { - lbs_deb_main("wrong region code %#x in band B/G\n", - region); - ret = -1; - goto out; - } - priv->region_channel[i].valid = 1; - priv->region_channel[i].region = region; - priv->region_channel[i].band = band; - i++; -out: - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); - return ret; -} - -void lbs_queue_event(struct lbs_private *priv, u32 event) -{ - unsigned long flags; - - lbs_deb_enter(LBS_DEB_THREAD); - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->psstate == PS_STATE_SLEEP) - priv->psstate = PS_STATE_AWAKE; - - __kfifo_put(priv->event_fifo, (unsigned char *) &event, sizeof(u32)); - - wake_up_interruptible(&priv->waitq); - - spin_unlock_irqrestore(&priv->driver_lock, flags); - lbs_deb_leave(LBS_DEB_THREAD); -} -EXPORT_SYMBOL_GPL(lbs_queue_event); - -void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx) -{ - lbs_deb_enter(LBS_DEB_THREAD); - - if (priv->psstate == PS_STATE_SLEEP) - priv->psstate = PS_STATE_AWAKE; - - /* Swap buffers by flipping the response index */ - BUG_ON(resp_idx > 1); - priv->resp_idx = resp_idx; - - wake_up_interruptible(&priv->waitq); - - lbs_deb_leave(LBS_DEB_THREAD); -} -EXPORT_SYMBOL_GPL(lbs_notify_command_response); - -static int __init lbs_init_module(void) -{ - lbs_deb_enter(LBS_DEB_MAIN); - memset(&confirm_sleep, 0, sizeof(confirm_sleep)); - confirm_sleep.hdr.command = cpu_to_le16(CMD_802_11_PS_MODE); - confirm_sleep.hdr.size = cpu_to_le16(sizeof(confirm_sleep)); - confirm_sleep.action = cpu_to_le16(CMD_SUBCMD_SLEEP_CONFIRMED); - lbs_debugfs_init(); - lbs_deb_leave(LBS_DEB_MAIN); - return 0; -} - -static void __exit lbs_exit_module(void) -{ - lbs_deb_enter(LBS_DEB_MAIN); - lbs_debugfs_remove(); - lbs_deb_leave(LBS_DEB_MAIN); -} - -/* - * rtap interface support fuctions - */ - -static int lbs_rtap_open(struct net_device *dev) -{ - /* Yes, _stop_ the queue. Because we don't support injection */ - lbs_deb_enter(LBS_DEB_MAIN); - netif_carrier_off(dev); - netif_stop_queue(dev); - lbs_deb_leave(LBS_DEB_LEAVE); - return 0; -} - -static int lbs_rtap_stop(struct net_device *dev) -{ - lbs_deb_enter(LBS_DEB_MAIN); - lbs_deb_leave(LBS_DEB_MAIN); - return 0; -} - -static netdev_tx_t lbs_rtap_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - netif_stop_queue(dev); - return NETDEV_TX_BUSY; -} - -static void lbs_remove_rtap(struct lbs_private *priv) -{ - lbs_deb_enter(LBS_DEB_MAIN); - if (priv->rtap_net_dev == NULL) - goto out; - unregister_netdev(priv->rtap_net_dev); - free_netdev(priv->rtap_net_dev); - priv->rtap_net_dev = NULL; -out: - lbs_deb_leave(LBS_DEB_MAIN); -} - -static const struct net_device_ops rtap_netdev_ops = { - .ndo_open = lbs_rtap_open, - .ndo_stop = lbs_rtap_stop, - .ndo_start_xmit = lbs_rtap_hard_start_xmit, -}; - -static int lbs_add_rtap(struct lbs_private *priv) -{ - int ret = 0; - struct net_device *rtap_dev; - - lbs_deb_enter(LBS_DEB_MAIN); - if (priv->rtap_net_dev) { - ret = -EPERM; - goto out; - } - - rtap_dev = alloc_netdev(0, "rtap%d", ether_setup); - if (rtap_dev == NULL) { - ret = -ENOMEM; - goto out; - } - - memcpy(rtap_dev->dev_addr, priv->current_addr, ETH_ALEN); - rtap_dev->type = ARPHRD_IEEE80211_RADIOTAP; - rtap_dev->netdev_ops = &rtap_netdev_ops; - rtap_dev->ml_priv = priv; - SET_NETDEV_DEV(rtap_dev, priv->dev->dev.parent); - - ret = register_netdev(rtap_dev); - if (ret) { - free_netdev(rtap_dev); - goto out; - } - priv->rtap_net_dev = rtap_dev; - -out: - lbs_deb_leave_args(LBS_DEB_MAIN, "ret %d", ret); - return ret; -} - -module_init(lbs_init_module); -module_exit(lbs_exit_module); - -MODULE_DESCRIPTION("Libertas WLAN Driver Library"); -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c deleted file mode 100644 index 18fe29faf99b..000000000000 --- a/drivers/net/wireless/libertas/persistcfg.c +++ /dev/null @@ -1,453 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "dev.h" -#include "wext.h" -#include "debugfs.h" -#include "scan.h" -#include "assoc.h" -#include "cmd.h" - -static int mesh_get_default_parameters(struct device *dev, - struct mrvl_mesh_defaults *defs) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_config cmd; - int ret; - - memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET, - CMD_TYPE_MESH_GET_DEFAULTS); - - if (ret) - return -EOPNOTSUPP; - - memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults)); - - return 0; -} - -/** - * @brief Get function for sysfs attribute bootflag - */ -static ssize_t bootflag_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mrvl_mesh_defaults defs; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag)); -} - -/** - * @brief Set function for sysfs attribute bootflag - */ -static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_config cmd; - uint32_t datum; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 1)) - return -EINVAL; - - *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum); - cmd.length = cpu_to_le16(sizeof(uint32_t)); - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_BOOTFLAG); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute boottime - */ -static ssize_t boottime_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mrvl_mesh_defaults defs; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - return snprintf(buf, 12, "%d\n", defs.boottime); -} - -/** - * @brief Set function for sysfs attribute boottime - */ -static ssize_t boottime_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_config cmd; - uint32_t datum; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) - return -EINVAL; - - /* A too small boot time will result in the device booting into - * standalone (no-host) mode before the host can take control of it, - * so the change will be hard to revert. This may be a desired - * feature (e.g to configure a very fast boot time for devices that - * will not be attached to a host), but dangerous. So I'm enforcing a - * lower limit of 20 seconds: remove and recompile the driver if this - * does not work for you. - */ - datum = (datum < 20) ? 20 : datum; - cmd.data[0] = datum; - cmd.length = cpu_to_le16(sizeof(uint8_t)); - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_BOOTTIME); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute channel - */ -static ssize_t channel_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mrvl_mesh_defaults defs; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel)); -} - -/** - * @brief Set function for sysfs attribute channel - */ -static ssize_t channel_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - struct cmd_ds_mesh_config cmd; - uint32_t datum; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if (ret != 1 || datum < 1 || datum > 11) - return -EINVAL; - - *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum); - cmd.length = cpu_to_le16(sizeof(uint16_t)); - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_DEF_CHANNEL); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute mesh_id - */ -static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct mrvl_mesh_defaults defs; - int maxlen; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - if (defs.meshie.val.mesh_id_len > IW_ESSID_MAX_SIZE) { - lbs_pr_err("inconsistent mesh ID length"); - defs.meshie.val.mesh_id_len = IW_ESSID_MAX_SIZE; - } - - /* SSID not null terminated: reserve room for \0 + \n */ - maxlen = defs.meshie.val.mesh_id_len + 2; - maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE; - - defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0'; - - return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id); -} - -/** - * @brief Set function for sysfs attribute mesh_id - */ -static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cmd_ds_mesh_config cmd; - struct mrvl_mesh_defaults defs; - struct mrvl_meshie *ie; - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - int len; - int ret; - - if (count < 2 || count > IW_ESSID_MAX_SIZE + 1) - return -EINVAL; - - memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config)); - ie = (struct mrvl_meshie *) &cmd.data[0]; - - /* fetch all other Information Element parameters */ - ret = mesh_get_default_parameters(dev, &defs); - - cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); - - /* transfer IE elements */ - memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); - - len = count - 1; - memcpy(ie->val.mesh_id, buf, len); - /* SSID len */ - ie->val.mesh_id_len = len; - /* IE len */ - ie->len = sizeof(struct mrvl_meshie_val) - IW_ESSID_MAX_SIZE + len; - - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_MESH_IE); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute protocol_id - */ -static ssize_t protocol_id_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mrvl_mesh_defaults defs; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id); -} - -/** - * @brief Set function for sysfs attribute protocol_id - */ -static ssize_t protocol_id_set(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct cmd_ds_mesh_config cmd; - struct mrvl_mesh_defaults defs; - struct mrvl_meshie *ie; - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - uint32_t datum; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) - return -EINVAL; - - /* fetch all other Information Element parameters */ - ret = mesh_get_default_parameters(dev, &defs); - - cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); - - /* transfer IE elements */ - ie = (struct mrvl_meshie *) &cmd.data[0]; - memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); - /* update protocol id */ - ie->val.active_protocol_id = datum; - - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_MESH_IE); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute metric_id - */ -static ssize_t metric_id_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mrvl_mesh_defaults defs; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id); -} - -/** - * @brief Set function for sysfs attribute metric_id - */ -static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cmd_ds_mesh_config cmd; - struct mrvl_mesh_defaults defs; - struct mrvl_meshie *ie; - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - uint32_t datum; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) - return -EINVAL; - - /* fetch all other Information Element parameters */ - ret = mesh_get_default_parameters(dev, &defs); - - cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); - - /* transfer IE elements */ - ie = (struct mrvl_meshie *) &cmd.data[0]; - memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); - /* update metric id */ - ie->val.active_metric_id = datum; - - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_MESH_IE); - if (ret) - return ret; - - return strlen(buf); -} - -/** - * @brief Get function for sysfs attribute capability - */ -static ssize_t capability_get(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct mrvl_mesh_defaults defs; - int ret; - - ret = mesh_get_default_parameters(dev, &defs); - - if (ret) - return ret; - - return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability); -} - -/** - * @brief Set function for sysfs attribute capability - */ -static ssize_t capability_set(struct device *dev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct cmd_ds_mesh_config cmd; - struct mrvl_mesh_defaults defs; - struct mrvl_meshie *ie; - struct lbs_private *priv = to_net_dev(dev)->ml_priv; - uint32_t datum; - int ret; - - memset(&cmd, 0, sizeof(cmd)); - ret = sscanf(buf, "%d", &datum); - if ((ret != 1) || (datum > 255)) - return -EINVAL; - - /* fetch all other Information Element parameters */ - ret = mesh_get_default_parameters(dev, &defs); - - cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie)); - - /* transfer IE elements */ - ie = (struct mrvl_meshie *) &cmd.data[0]; - memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie)); - /* update value */ - ie->val.mesh_capability = datum; - - ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET, - CMD_TYPE_MESH_SET_MESH_IE); - if (ret) - return ret; - - return strlen(buf); -} - - -static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set); -static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set); -static DEVICE_ATTR(channel, 0644, channel_get, channel_set); -static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set); -static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set); -static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set); -static DEVICE_ATTR(capability, 0644, capability_get, capability_set); - -static struct attribute *boot_opts_attrs[] = { - &dev_attr_bootflag.attr, - &dev_attr_boottime.attr, - &dev_attr_channel.attr, - NULL -}; - -static struct attribute_group boot_opts_group = { - .name = "boot_options", - .attrs = boot_opts_attrs, -}; - -static struct attribute *mesh_ie_attrs[] = { - &dev_attr_mesh_id.attr, - &dev_attr_protocol_id.attr, - &dev_attr_metric_id.attr, - &dev_attr_capability.attr, - NULL -}; - -static struct attribute_group mesh_ie_group = { - .name = "mesh_ie", - .attrs = mesh_ie_attrs, -}; - -void lbs_persist_config_init(struct net_device *dev) -{ - int ret; - ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group); - ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group); -} - -void lbs_persist_config_remove(struct net_device *dev) -{ - sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group); - sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group); -} diff --git a/drivers/net/wireless/libertas/radiotap.h b/drivers/net/wireless/libertas/radiotap.h deleted file mode 100644 index d16b26416e82..000000000000 --- a/drivers/net/wireless/libertas/radiotap.h +++ /dev/null @@ -1,44 +0,0 @@ -#include - -struct tx_radiotap_hdr { - struct ieee80211_radiotap_header hdr; - u8 rate; - u8 txpower; - u8 rts_retries; - u8 data_retries; -} __attribute__ ((packed)); - -#define TX_RADIOTAP_PRESENT ( \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_DBM_TX_POWER) | \ - (1 << IEEE80211_RADIOTAP_RTS_RETRIES) | \ - (1 << IEEE80211_RADIOTAP_DATA_RETRIES) | \ - 0) - -#define IEEE80211_FC_VERSION_MASK 0x0003 -#define IEEE80211_FC_TYPE_MASK 0x000c -#define IEEE80211_FC_TYPE_MGT 0x0000 -#define IEEE80211_FC_TYPE_CTL 0x0004 -#define IEEE80211_FC_TYPE_DATA 0x0008 -#define IEEE80211_FC_SUBTYPE_MASK 0x00f0 -#define IEEE80211_FC_TOFROMDS_MASK 0x0300 -#define IEEE80211_FC_TODS_MASK 0x0100 -#define IEEE80211_FC_FROMDS_MASK 0x0200 -#define IEEE80211_FC_NODS 0x0000 -#define IEEE80211_FC_TODS 0x0100 -#define IEEE80211_FC_FROMDS 0x0200 -#define IEEE80211_FC_DSTODS 0x0300 - -struct rx_radiotap_hdr { - struct ieee80211_radiotap_header hdr; - u8 flags; - u8 rate; - u8 antsignal; -} __attribute__ ((packed)); - -#define RX_RADIOTAP_PRESENT ( \ - (1 << IEEE80211_RADIOTAP_FLAGS) | \ - (1 << IEEE80211_RADIOTAP_RATE) | \ - (1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL) |\ - 0) - diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c deleted file mode 100644 index 65f02cc6752f..000000000000 --- a/drivers/net/wireless/libertas/rx.c +++ /dev/null @@ -1,383 +0,0 @@ -/** - * This file contains the handling of RX in wlan driver. - */ -#include -#include - -#include "hostcmd.h" -#include "radiotap.h" -#include "decl.h" -#include "dev.h" -#include "wext.h" - -struct eth803hdr { - u8 dest_addr[6]; - u8 src_addr[6]; - u16 h803_len; -} __attribute__ ((packed)); - -struct rfc1042hdr { - u8 llc_dsap; - u8 llc_ssap; - u8 llc_ctrl; - u8 snap_oui[3]; - u16 snap_type; -} __attribute__ ((packed)); - -struct rxpackethdr { - struct eth803hdr eth803_hdr; - struct rfc1042hdr rfc1042_hdr; -} __attribute__ ((packed)); - -struct rx80211packethdr { - struct rxpd rx_pd; - void *eth80211_hdr; -} __attribute__ ((packed)); - -static int process_rxed_802_11_packet(struct lbs_private *priv, - struct sk_buff *skb); - -/** - * @brief This function computes the avgSNR . - * - * @param priv A pointer to struct lbs_private structure - * @return avgSNR - */ -static u8 lbs_getavgsnr(struct lbs_private *priv) -{ - u8 i; - u16 temp = 0; - if (priv->numSNRNF == 0) - return 0; - for (i = 0; i < priv->numSNRNF; i++) - temp += priv->rawSNR[i]; - return (u8) (temp / priv->numSNRNF); - -} - -/** - * @brief This function computes the AvgNF - * - * @param priv A pointer to struct lbs_private structure - * @return AvgNF - */ -static u8 lbs_getavgnf(struct lbs_private *priv) -{ - u8 i; - u16 temp = 0; - if (priv->numSNRNF == 0) - return 0; - for (i = 0; i < priv->numSNRNF; i++) - temp += priv->rawNF[i]; - return (u8) (temp / priv->numSNRNF); - -} - -/** - * @brief This function save the raw SNR/NF to our internel buffer - * - * @param priv A pointer to struct lbs_private structure - * @param prxpd A pointer to rxpd structure of received packet - * @return n/a - */ -static void lbs_save_rawSNRNF(struct lbs_private *priv, struct rxpd *p_rx_pd) -{ - if (priv->numSNRNF < DEFAULT_DATA_AVG_FACTOR) - priv->numSNRNF++; - priv->rawSNR[priv->nextSNRNF] = p_rx_pd->snr; - priv->rawNF[priv->nextSNRNF] = p_rx_pd->nf; - priv->nextSNRNF++; - if (priv->nextSNRNF >= DEFAULT_DATA_AVG_FACTOR) - priv->nextSNRNF = 0; - return; -} - -/** - * @brief This function computes the RSSI in received packet. - * - * @param priv A pointer to struct lbs_private structure - * @param prxpd A pointer to rxpd structure of received packet - * @return n/a - */ -static void lbs_compute_rssi(struct lbs_private *priv, struct rxpd *p_rx_pd) -{ - - lbs_deb_enter(LBS_DEB_RX); - - lbs_deb_rx("rxpd: SNR %d, NF %d\n", p_rx_pd->snr, p_rx_pd->nf); - lbs_deb_rx("before computing SNR: SNR-avg = %d, NF-avg = %d\n", - priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, - priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); - - priv->SNR[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->snr; - priv->NF[TYPE_RXPD][TYPE_NOAVG] = p_rx_pd->nf; - lbs_save_rawSNRNF(priv, p_rx_pd); - - priv->SNR[TYPE_RXPD][TYPE_AVG] = lbs_getavgsnr(priv) * AVG_SCALE; - priv->NF[TYPE_RXPD][TYPE_AVG] = lbs_getavgnf(priv) * AVG_SCALE; - lbs_deb_rx("after computing SNR: SNR-avg = %d, NF-avg = %d\n", - priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, - priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); - - priv->RSSI[TYPE_RXPD][TYPE_NOAVG] = - CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_NOAVG], - priv->NF[TYPE_RXPD][TYPE_NOAVG]); - - priv->RSSI[TYPE_RXPD][TYPE_AVG] = - CAL_RSSI(priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE, - priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE); - - lbs_deb_leave(LBS_DEB_RX); -} - -/** - * @brief This function processes received packet and forwards it - * to kernel/upper layer - * - * @param priv A pointer to struct lbs_private - * @param skb A pointer to skb which includes the received packet - * @return 0 or -1 - */ -int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb) -{ - int ret = 0; - struct net_device *dev = priv->dev; - struct rxpackethdr *p_rx_pkt; - struct rxpd *p_rx_pd; - int hdrchop; - struct ethhdr *p_ethhdr; - const u8 rfc1042_eth_hdr[] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 }; - - lbs_deb_enter(LBS_DEB_RX); - - BUG_ON(!skb); - - skb->ip_summed = CHECKSUM_NONE; - - if (priv->monitormode) - return process_rxed_802_11_packet(priv, skb); - - p_rx_pd = (struct rxpd *) skb->data; - p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + - le32_to_cpu(p_rx_pd->pkt_ptr)); - if (priv->mesh_dev) { - if (priv->mesh_fw_ver == MESH_FW_OLD) { - if (p_rx_pd->rx_control & RxPD_MESH_FRAME) - dev = priv->mesh_dev; - } else if (priv->mesh_fw_ver == MESH_FW_NEW) { - if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID) - dev = priv->mesh_dev; - } - } - - lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, - min_t(unsigned int, skb->len, 100)); - - if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { - lbs_deb_rx("rx err: frame received with bad length\n"); - dev->stats.rx_length_errors++; - ret = 0; - dev_kfree_skb(skb); - goto done; - } - - lbs_deb_rx("rx data: skb->len - pkt_ptr = %d-%zd = %zd\n", - skb->len, (size_t)le32_to_cpu(p_rx_pd->pkt_ptr), - skb->len - (size_t)le32_to_cpu(p_rx_pd->pkt_ptr)); - - lbs_deb_hex(LBS_DEB_RX, "RX Data: Dest", p_rx_pkt->eth803_hdr.dest_addr, - sizeof(p_rx_pkt->eth803_hdr.dest_addr)); - lbs_deb_hex(LBS_DEB_RX, "RX Data: Src", p_rx_pkt->eth803_hdr.src_addr, - sizeof(p_rx_pkt->eth803_hdr.src_addr)); - - if (memcmp(&p_rx_pkt->rfc1042_hdr, - rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) { - /* - * Replace the 803 header and rfc1042 header (llc/snap) with an - * EthernetII header, keep the src/dst and snap_type (ethertype) - * - * The firmware only passes up SNAP frames converting - * all RX Data from 802.11 to 802.2/LLC/SNAP frames. - * - * To create the Ethernet II, just move the src, dst address right - * before the snap_type. - */ - p_ethhdr = (struct ethhdr *) - ((u8 *) & p_rx_pkt->eth803_hdr - + sizeof(p_rx_pkt->eth803_hdr) + sizeof(p_rx_pkt->rfc1042_hdr) - - sizeof(p_rx_pkt->eth803_hdr.dest_addr) - - sizeof(p_rx_pkt->eth803_hdr.src_addr) - - sizeof(p_rx_pkt->rfc1042_hdr.snap_type)); - - memcpy(p_ethhdr->h_source, p_rx_pkt->eth803_hdr.src_addr, - sizeof(p_ethhdr->h_source)); - memcpy(p_ethhdr->h_dest, p_rx_pkt->eth803_hdr.dest_addr, - sizeof(p_ethhdr->h_dest)); - - /* Chop off the rxpd + the excess memory from the 802.2/llc/snap header - * that was removed - */ - hdrchop = (u8 *)p_ethhdr - (u8 *)p_rx_pd; - } else { - lbs_deb_hex(LBS_DEB_RX, "RX Data: LLC/SNAP", - (u8 *) & p_rx_pkt->rfc1042_hdr, - sizeof(p_rx_pkt->rfc1042_hdr)); - - /* Chop off the rxpd */ - hdrchop = (u8 *)&p_rx_pkt->eth803_hdr - (u8 *)p_rx_pd; - } - - /* Chop off the leading header bytes so the skb points to the start of - * either the reconstructed EthII frame or the 802.2/llc/snap frame - */ - skb_pull(skb, hdrchop); - - /* Take the data rate from the rxpd structure - * only if the rate is auto - */ - if (priv->enablehwauto) - priv->cur_rate = lbs_fw_index_to_data_rate(p_rx_pd->rx_rate); - - lbs_compute_rssi(priv, p_rx_pd); - - lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); - dev->stats.rx_bytes += skb->len; - dev->stats.rx_packets++; - - skb->protocol = eth_type_trans(skb, dev); - if (in_interrupt()) - netif_rx(skb); - else - netif_rx_ni(skb); - - ret = 0; -done: - lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); - return ret; -} -EXPORT_SYMBOL_GPL(lbs_process_rxed_packet); - -/** - * @brief This function converts Tx/Rx rates from the Marvell WLAN format - * (see Table 2 in Section 3.1) to IEEE80211_RADIOTAP_RATE units (500 Kb/s) - * - * @param rate Input rate - * @return Output Rate (0 if invalid) - */ -static u8 convert_mv_rate_to_radiotap(u8 rate) -{ - switch (rate) { - case 0: /* 1 Mbps */ - return 2; - case 1: /* 2 Mbps */ - return 4; - case 2: /* 5.5 Mbps */ - return 11; - case 3: /* 11 Mbps */ - return 22; - /* case 4: reserved */ - case 5: /* 6 Mbps */ - return 12; - case 6: /* 9 Mbps */ - return 18; - case 7: /* 12 Mbps */ - return 24; - case 8: /* 18 Mbps */ - return 36; - case 9: /* 24 Mbps */ - return 48; - case 10: /* 36 Mbps */ - return 72; - case 11: /* 48 Mbps */ - return 96; - case 12: /* 54 Mbps */ - return 108; - } - lbs_pr_alert("Invalid Marvell WLAN rate %i\n", rate); - return 0; -} - -/** - * @brief This function processes a received 802.11 packet and forwards it - * to kernel/upper layer - * - * @param priv A pointer to struct lbs_private - * @param skb A pointer to skb which includes the received packet - * @return 0 or -1 - */ -static int process_rxed_802_11_packet(struct lbs_private *priv, - struct sk_buff *skb) -{ - int ret = 0; - struct net_device *dev = priv->dev; - struct rx80211packethdr *p_rx_pkt; - struct rxpd *prxpd; - struct rx_radiotap_hdr radiotap_hdr; - struct rx_radiotap_hdr *pradiotap_hdr; - - lbs_deb_enter(LBS_DEB_RX); - - p_rx_pkt = (struct rx80211packethdr *) skb->data; - prxpd = &p_rx_pkt->rx_pd; - - // lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, min(skb->len, 100)); - - if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) { - lbs_deb_rx("rx err: frame received with bad length\n"); - dev->stats.rx_length_errors++; - ret = -EINVAL; - kfree_skb(skb); - goto done; - } - - lbs_deb_rx("rx data: skb->len-sizeof(RxPd) = %d-%zd = %zd\n", - skb->len, sizeof(struct rxpd), skb->len - sizeof(struct rxpd)); - - /* create the exported radio header */ - - /* radiotap header */ - radiotap_hdr.hdr.it_version = 0; - /* XXX must check this value for pad */ - radiotap_hdr.hdr.it_pad = 0; - radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr)); - radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT); - radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate); - /* XXX must check no carryout */ - radiotap_hdr.antsignal = prxpd->snr + prxpd->nf; - - /* chop the rxpd */ - skb_pull(skb, sizeof(struct rxpd)); - - /* add space for the new radio header */ - if ((skb_headroom(skb) < sizeof(struct rx_radiotap_hdr)) && - pskb_expand_head(skb, sizeof(struct rx_radiotap_hdr), 0, GFP_ATOMIC)) { - lbs_pr_alert("%s: couldn't pskb_expand_head\n", __func__); - ret = -ENOMEM; - kfree_skb(skb); - goto done; - } - - pradiotap_hdr = (void *)skb_push(skb, sizeof(struct rx_radiotap_hdr)); - memcpy(pradiotap_hdr, &radiotap_hdr, sizeof(struct rx_radiotap_hdr)); - - /* Take the data rate from the rxpd structure - * only if the rate is auto - */ - if (priv->enablehwauto) - priv->cur_rate = lbs_fw_index_to_data_rate(prxpd->rx_rate); - - lbs_compute_rssi(priv, prxpd); - - lbs_deb_rx("rx data: size of actual packet %d\n", skb->len); - dev->stats.rx_bytes += skb->len; - dev->stats.rx_packets++; - - skb->protocol = eth_type_trans(skb, priv->rtap_net_dev); - netif_rx(skb); - - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_RX, "ret %d", ret); - return ret; -} diff --git a/drivers/net/wireless/libertas/scan.c b/drivers/net/wireless/libertas/scan.c deleted file mode 100644 index 06d66a171396..000000000000 --- a/drivers/net/wireless/libertas/scan.c +++ /dev/null @@ -1,1203 +0,0 @@ -/** - * Functions implementing wlan scan IOCTL and firmware command APIs - * - * IOCTL handlers as well as command preperation and response routines - * for sending scan commands to the firmware. - */ -#include -#include -#include -#include -#include -#include - -#include "host.h" -#include "decl.h" -#include "dev.h" -#include "scan.h" -#include "cmd.h" - -//! Approximate amount of data needed to pass a scan result back to iwlist -#define MAX_SCAN_CELL_SIZE (IW_EV_ADDR_LEN \ - + IW_ESSID_MAX_SIZE \ - + IW_EV_UINT_LEN \ - + IW_EV_FREQ_LEN \ - + IW_EV_QUAL_LEN \ - + IW_ESSID_MAX_SIZE \ - + IW_EV_PARAM_LEN \ - + 40) /* 40 for WPAIE */ - -//! Memory needed to store a max sized channel List TLV for a firmware scan -#define CHAN_TLV_MAX_SIZE (sizeof(struct mrvl_ie_header) \ - + (MRVDRV_MAX_CHANNELS_PER_SCAN \ - * sizeof(struct chanscanparamset))) - -//! Memory needed to store a max number/size SSID TLV for a firmware scan -#define SSID_TLV_MAX_SIZE (1 * sizeof(struct mrvl_ie_ssid_param_set)) - -//! Maximum memory needed for a cmd_ds_802_11_scan with all TLVs at max -#define MAX_SCAN_CFG_ALLOC (sizeof(struct cmd_ds_802_11_scan) \ - + CHAN_TLV_MAX_SIZE + SSID_TLV_MAX_SIZE) - -//! The maximum number of channels the firmware can scan per command -#define MRVDRV_MAX_CHANNELS_PER_SCAN 14 - -/** - * @brief Number of channels to scan per firmware scan command issuance. - * - * Number restricted to prevent hitting the limit on the amount of scan data - * returned in a single firmware scan command. - */ -#define MRVDRV_CHANNELS_PER_SCAN_CMD 4 - -//! Scan time specified in the channel TLV for each channel for passive scans -#define MRVDRV_PASSIVE_SCAN_CHAN_TIME 100 - -//! Scan time specified in the channel TLV for each channel for active scans -#define MRVDRV_ACTIVE_SCAN_CHAN_TIME 100 - -#define DEFAULT_MAX_SCAN_AGE (15 * HZ) - -static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, - struct cmd_header *resp); - -/*********************************************************************/ -/* */ -/* Misc helper functions */ -/* */ -/*********************************************************************/ - -/** - * @brief Unsets the MSB on basic rates - * - * Scan through an array and unset the MSB for basic data rates. - * - * @param rates buffer of data rates - * @param len size of buffer - */ -static void lbs_unset_basic_rate_flags(u8 *rates, size_t len) -{ - int i; - - for (i = 0; i < len; i++) - rates[i] &= 0x7f; -} - - -static inline void clear_bss_descriptor(struct bss_descriptor *bss) -{ - /* Don't blow away ->list, just BSS data */ - memset(bss, 0, offsetof(struct bss_descriptor, list)); -} - -/** - * @brief Compare two SSIDs - * - * @param ssid1 A pointer to ssid to compare - * @param ssid2 A pointer to ssid to compare - * - * @return 0: ssid is same, otherwise is different - */ -int lbs_ssid_cmp(uint8_t *ssid1, uint8_t ssid1_len, uint8_t *ssid2, - uint8_t ssid2_len) -{ - if (ssid1_len != ssid2_len) - return -1; - - return memcmp(ssid1, ssid2, ssid1_len); -} - -static inline int is_same_network(struct bss_descriptor *src, - struct bss_descriptor *dst) -{ - /* A network is only a duplicate if the channel, BSSID, and ESSID - * all match. We treat all with the same BSSID and channel - * as one network */ - return ((src->ssid_len == dst->ssid_len) && - (src->channel == dst->channel) && - !compare_ether_addr(src->bssid, dst->bssid) && - !memcmp(src->ssid, dst->ssid, src->ssid_len)); -} - - - - -/*********************************************************************/ -/* */ -/* Main scanning support */ -/* */ -/*********************************************************************/ - -/** - * @brief Create a channel list for the driver to scan based on region info - * - * Only used from lbs_scan_setup_scan_config() - * - * Use the driver region/band information to construct a comprehensive list - * of channels to scan. This routine is used for any scan that is not - * provided a specific channel list to scan. - * - * @param priv A pointer to struct lbs_private structure - * @param scanchanlist Output parameter: resulting channel list to scan - * - * @return void - */ -static int lbs_scan_create_channel_list(struct lbs_private *priv, - struct chanscanparamset *scanchanlist) -{ - struct region_channel *scanregion; - struct chan_freq_power *cfp; - int rgnidx; - int chanidx; - int nextchan; - uint8_t scantype; - - chanidx = 0; - - /* Set the default scan type to the user specified type, will later - * be changed to passive on a per channel basis if restricted by - * regulatory requirements (11d or 11h) - */ - scantype = CMD_SCAN_TYPE_ACTIVE; - - for (rgnidx = 0; rgnidx < ARRAY_SIZE(priv->region_channel); rgnidx++) { - if (priv->enable11d && (priv->connect_status != LBS_CONNECTED) - && (priv->mesh_connect_status != LBS_CONNECTED)) { - /* Scan all the supported chan for the first scan */ - if (!priv->universal_channel[rgnidx].valid) - continue; - scanregion = &priv->universal_channel[rgnidx]; - - /* clear the parsed_region_chan for the first scan */ - memset(&priv->parsed_region_chan, 0x00, - sizeof(priv->parsed_region_chan)); - } else { - if (!priv->region_channel[rgnidx].valid) - continue; - scanregion = &priv->region_channel[rgnidx]; - } - - for (nextchan = 0; nextchan < scanregion->nrcfp; nextchan++, chanidx++) { - struct chanscanparamset *chan = &scanchanlist[chanidx]; - - cfp = scanregion->CFP + nextchan; - - if (priv->enable11d) - scantype = lbs_get_scan_type_11d(cfp->channel, - &priv->parsed_region_chan); - - if (scanregion->band == BAND_B || scanregion->band == BAND_G) - chan->radiotype = CMD_SCAN_RADIO_TYPE_BG; - - if (scantype == CMD_SCAN_TYPE_PASSIVE) { - chan->maxscantime = cpu_to_le16(MRVDRV_PASSIVE_SCAN_CHAN_TIME); - chan->chanscanmode.passivescan = 1; - } else { - chan->maxscantime = cpu_to_le16(MRVDRV_ACTIVE_SCAN_CHAN_TIME); - chan->chanscanmode.passivescan = 0; - } - - chan->channumber = cfp->channel; - } - } - return chanidx; -} - -/* - * Add SSID TLV of the form: - * - * TLV-ID SSID 00 00 - * length 06 00 - * ssid 4d 4e 54 45 53 54 - */ -static int lbs_scan_add_ssid_tlv(struct lbs_private *priv, u8 *tlv) -{ - struct mrvl_ie_ssid_param_set *ssid_tlv = (void *)tlv; - - ssid_tlv->header.type = cpu_to_le16(TLV_TYPE_SSID); - ssid_tlv->header.len = cpu_to_le16(priv->scan_ssid_len); - memcpy(ssid_tlv->ssid, priv->scan_ssid, priv->scan_ssid_len); - return sizeof(ssid_tlv->header) + priv->scan_ssid_len; -} - -/* - * Add CHANLIST TLV of the form - * - * TLV-ID CHANLIST 01 01 - * length 5b 00 - * channel 1 00 01 00 00 00 64 00 - * radio type 00 - * channel 01 - * scan type 00 - * min scan time 00 00 - * max scan time 64 00 - * channel 2 00 02 00 00 00 64 00 - * channel 3 00 03 00 00 00 64 00 - * channel 4 00 04 00 00 00 64 00 - * channel 5 00 05 00 00 00 64 00 - * channel 6 00 06 00 00 00 64 00 - * channel 7 00 07 00 00 00 64 00 - * channel 8 00 08 00 00 00 64 00 - * channel 9 00 09 00 00 00 64 00 - * channel 10 00 0a 00 00 00 64 00 - * channel 11 00 0b 00 00 00 64 00 - * channel 12 00 0c 00 00 00 64 00 - * channel 13 00 0d 00 00 00 64 00 - * - */ -static int lbs_scan_add_chanlist_tlv(uint8_t *tlv, - struct chanscanparamset *chan_list, - int chan_count) -{ - size_t size = sizeof(struct chanscanparamset) *chan_count; - struct mrvl_ie_chanlist_param_set *chan_tlv = (void *)tlv; - - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - memcpy(chan_tlv->chanscanparam, chan_list, size); - chan_tlv->header.len = cpu_to_le16(size); - return sizeof(chan_tlv->header) + size; -} - -/* - * Add RATES TLV of the form - * - * TLV-ID RATES 01 00 - * length 0e 00 - * rates 82 84 8b 96 0c 12 18 24 30 48 60 6c - * - * The rates are in lbs_bg_rates[], but for the 802.11b - * rates the high bit isn't set. - */ -static int lbs_scan_add_rates_tlv(uint8_t *tlv) -{ - int i; - struct mrvl_ie_rates_param_set *rate_tlv = (void *)tlv; - - rate_tlv->header.type = cpu_to_le16(TLV_TYPE_RATES); - tlv += sizeof(rate_tlv->header); - for (i = 0; i < MAX_RATES; i++) { - *tlv = lbs_bg_rates[i]; - if (*tlv == 0) - break; - /* This code makes sure that the 802.11b rates (1 MBit/s, 2 - MBit/s, 5.5 MBit/s and 11 MBit/s get's the high bit set. - Note that the values are MBit/s * 2, to mark them as - basic rates so that the firmware likes it better */ - if (*tlv == 0x02 || *tlv == 0x04 || - *tlv == 0x0b || *tlv == 0x16) - *tlv |= 0x80; - tlv++; - } - rate_tlv->header.len = cpu_to_le16(i); - return sizeof(rate_tlv->header) + i; -} - -/* - * Generate the CMD_802_11_SCAN command with the proper tlv - * for a bunch of channels. - */ -static int lbs_do_scan(struct lbs_private *priv, uint8_t bsstype, - struct chanscanparamset *chan_list, int chan_count) -{ - int ret = -ENOMEM; - struct cmd_ds_802_11_scan *scan_cmd; - uint8_t *tlv; /* pointer into our current, growing TLV storage area */ - - lbs_deb_enter_args(LBS_DEB_SCAN, "bsstype %d, chanlist[].chan %d, chan_count %d", - bsstype, chan_list ? chan_list[0].channumber : -1, - chan_count); - - /* create the fixed part for scan command */ - scan_cmd = kzalloc(MAX_SCAN_CFG_ALLOC, GFP_KERNEL); - if (scan_cmd == NULL) - goto out; - - tlv = scan_cmd->tlvbuffer; - /* TODO: do we need to scan for a specific BSSID? - memcpy(scan_cmd->bssid, priv->scan_bssid, ETH_ALEN); */ - scan_cmd->bsstype = bsstype; - - /* add TLVs */ - if (priv->scan_ssid_len) - tlv += lbs_scan_add_ssid_tlv(priv, tlv); - if (chan_list && chan_count) - tlv += lbs_scan_add_chanlist_tlv(tlv, chan_list, chan_count); - tlv += lbs_scan_add_rates_tlv(tlv); - - /* This is the final data we are about to send */ - scan_cmd->hdr.size = cpu_to_le16(tlv - (uint8_t *)scan_cmd); - lbs_deb_hex(LBS_DEB_SCAN, "SCAN_CMD", (void *)scan_cmd, - sizeof(*scan_cmd)); - lbs_deb_hex(LBS_DEB_SCAN, "SCAN_TLV", scan_cmd->tlvbuffer, - tlv - scan_cmd->tlvbuffer); - - ret = __lbs_cmd(priv, CMD_802_11_SCAN, &scan_cmd->hdr, - le16_to_cpu(scan_cmd->hdr.size), - lbs_ret_80211_scan, 0); - -out: - kfree(scan_cmd); - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - -/** - * @brief Internal function used to start a scan based on an input config - * - * Use the input user scan configuration information when provided in - * order to send the appropriate scan commands to firmware to populate or - * update the internal driver scan table - * - * @param priv A pointer to struct lbs_private structure - * @param full_scan Do a full-scan (blocking) - * - * @return 0 or < 0 if error - */ -int lbs_scan_networks(struct lbs_private *priv, int full_scan) -{ - int ret = -ENOMEM; - struct chanscanparamset *chan_list; - struct chanscanparamset *curr_chans; - int chan_count; - uint8_t bsstype = CMD_BSS_TYPE_ANY; - int numchannels = MRVDRV_CHANNELS_PER_SCAN_CMD; - union iwreq_data wrqu; -#ifdef CONFIG_LIBERTAS_DEBUG - struct bss_descriptor *iter; - int i = 0; - DECLARE_SSID_BUF(ssid); -#endif - - lbs_deb_enter_args(LBS_DEB_SCAN, "full_scan %d", full_scan); - - /* Cancel any partial outstanding partial scans if this scan - * is a full scan. - */ - if (full_scan && delayed_work_pending(&priv->scan_work)) - cancel_delayed_work(&priv->scan_work); - - /* User-specified bsstype or channel list - TODO: this can be implemented if some user-space application - need the feature. Formerly, it was accessible from debugfs, - but then nowhere used. - if (user_cfg) { - if (user_cfg->bsstype) - bsstype = user_cfg->bsstype; - } */ - - lbs_deb_scan("numchannels %d, bsstype %d\n", numchannels, bsstype); - - /* Create list of channels to scan */ - chan_list = kzalloc(sizeof(struct chanscanparamset) * - LBS_IOCTL_USER_SCAN_CHAN_MAX, GFP_KERNEL); - if (!chan_list) { - lbs_pr_alert("SCAN: chan_list empty\n"); - goto out; - } - - /* We want to scan all channels */ - chan_count = lbs_scan_create_channel_list(priv, chan_list); - - netif_stop_queue(priv->dev); - if (priv->mesh_dev) - netif_stop_queue(priv->mesh_dev); - - /* Prepare to continue an interrupted scan */ - lbs_deb_scan("chan_count %d, scan_channel %d\n", - chan_count, priv->scan_channel); - curr_chans = chan_list; - /* advance channel list by already-scanned-channels */ - if (priv->scan_channel > 0) { - curr_chans += priv->scan_channel; - chan_count -= priv->scan_channel; - } - - /* Send scan command(s) - * numchannels contains the number of channels we should maximally scan - * chan_count is the total number of channels to scan - */ - - while (chan_count) { - int to_scan = min(numchannels, chan_count); - lbs_deb_scan("scanning %d of %d channels\n", - to_scan, chan_count); - ret = lbs_do_scan(priv, bsstype, curr_chans, - to_scan); - if (ret) { - lbs_pr_err("SCAN_CMD failed\n"); - goto out2; - } - curr_chans += to_scan; - chan_count -= to_scan; - - /* somehow schedule the next part of the scan */ - if (chan_count && !full_scan && - !priv->surpriseremoved) { - /* -1 marks just that we're currently scanning */ - if (priv->scan_channel < 0) - priv->scan_channel = to_scan; - else - priv->scan_channel += to_scan; - cancel_delayed_work(&priv->scan_work); - queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(300)); - /* skip over GIWSCAN event */ - goto out; - } - - } - memset(&wrqu, 0, sizeof(union iwreq_data)); - wireless_send_event(priv->dev, SIOCGIWSCAN, &wrqu, NULL); - -#ifdef CONFIG_LIBERTAS_DEBUG - /* Dump the scan table */ - mutex_lock(&priv->lock); - lbs_deb_scan("scan table:\n"); - list_for_each_entry(iter, &priv->network_list, list) - lbs_deb_scan("%02d: BSSID %pM, RSSI %d, SSID '%s'\n", - i++, iter->bssid, iter->rssi, - print_ssid(ssid, iter->ssid, iter->ssid_len)); - mutex_unlock(&priv->lock); -#endif - -out2: - priv->scan_channel = 0; - -out: - if (priv->connect_status == LBS_CONNECTED && !priv->tx_pending_len) - netif_wake_queue(priv->dev); - - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED) && - !priv->tx_pending_len) - netif_wake_queue(priv->mesh_dev); - - kfree(chan_list); - - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - -void lbs_scan_worker(struct work_struct *work) -{ - struct lbs_private *priv = - container_of(work, struct lbs_private, scan_work.work); - - lbs_deb_enter(LBS_DEB_SCAN); - lbs_scan_networks(priv, 0); - lbs_deb_leave(LBS_DEB_SCAN); -} - - -/*********************************************************************/ -/* */ -/* Result interpretation */ -/* */ -/*********************************************************************/ - -/** - * @brief Interpret a BSS scan response returned from the firmware - * - * Parse the various fixed fields and IEs passed back for a a BSS probe - * response or beacon from the scan command. Record information as needed - * in the scan table struct bss_descriptor for that entry. - * - * @param bss Output parameter: Pointer to the BSS Entry - * - * @return 0 or -1 - */ -static int lbs_process_bss(struct bss_descriptor *bss, - uint8_t **pbeaconinfo, int *bytesleft) -{ - struct ieee_ie_fh_param_set *fh; - struct ieee_ie_ds_param_set *ds; - struct ieee_ie_cf_param_set *cf; - struct ieee_ie_ibss_param_set *ibss; - DECLARE_SSID_BUF(ssid); - struct ieee_ie_country_info_set *pcountryinfo; - uint8_t *pos, *end, *p; - uint8_t n_ex_rates = 0, got_basic_rates = 0, n_basic_rates = 0; - uint16_t beaconsize = 0; - int ret; - - lbs_deb_enter(LBS_DEB_SCAN); - - if (*bytesleft >= sizeof(beaconsize)) { - /* Extract & convert beacon size from the command buffer */ - beaconsize = get_unaligned_le16(*pbeaconinfo); - *bytesleft -= sizeof(beaconsize); - *pbeaconinfo += sizeof(beaconsize); - } - - if (beaconsize == 0 || beaconsize > *bytesleft) { - *pbeaconinfo += *bytesleft; - *bytesleft = 0; - ret = -1; - goto done; - } - - /* Initialize the current working beacon pointer for this BSS iteration */ - pos = *pbeaconinfo; - end = pos + beaconsize; - - /* Advance the return beacon pointer past the current beacon */ - *pbeaconinfo += beaconsize; - *bytesleft -= beaconsize; - - memcpy(bss->bssid, pos, ETH_ALEN); - lbs_deb_scan("process_bss: BSSID %pM\n", bss->bssid); - pos += ETH_ALEN; - - if ((end - pos) < 12) { - lbs_deb_scan("process_bss: Not enough bytes left\n"); - ret = -1; - goto done; - } - - /* - * next 4 fields are RSSI, time stamp, beacon interval, - * and capability information - */ - - /* RSSI is 1 byte long */ - bss->rssi = *pos; - lbs_deb_scan("process_bss: RSSI %d\n", *pos); - pos++; - - /* time stamp is 8 bytes long */ - pos += 8; - - /* beacon interval is 2 bytes long */ - bss->beaconperiod = get_unaligned_le16(pos); - pos += 2; - - /* capability information is 2 bytes long */ - bss->capability = get_unaligned_le16(pos); - lbs_deb_scan("process_bss: capabilities 0x%04x\n", bss->capability); - pos += 2; - - if (bss->capability & WLAN_CAPABILITY_PRIVACY) - lbs_deb_scan("process_bss: WEP enabled\n"); - if (bss->capability & WLAN_CAPABILITY_IBSS) - bss->mode = IW_MODE_ADHOC; - else - bss->mode = IW_MODE_INFRA; - - /* rest of the current buffer are IE's */ - lbs_deb_scan("process_bss: IE len %zd\n", end - pos); - lbs_deb_hex(LBS_DEB_SCAN, "process_bss: IE info", pos, end - pos); - - /* process variable IE */ - while (pos <= end - 2) { - if (pos + pos[1] > end) { - lbs_deb_scan("process_bss: error in processing IE, " - "bytes left < IE length\n"); - break; - } - - switch (pos[0]) { - case WLAN_EID_SSID: - bss->ssid_len = min_t(int, IEEE80211_MAX_SSID_LEN, pos[1]); - memcpy(bss->ssid, pos + 2, bss->ssid_len); - lbs_deb_scan("got SSID IE: '%s', len %u\n", - print_ssid(ssid, bss->ssid, bss->ssid_len), - bss->ssid_len); - break; - - case WLAN_EID_SUPP_RATES: - n_basic_rates = min_t(uint8_t, MAX_RATES, pos[1]); - memcpy(bss->rates, pos + 2, n_basic_rates); - got_basic_rates = 1; - lbs_deb_scan("got RATES IE\n"); - break; - - case WLAN_EID_FH_PARAMS: - fh = (struct ieee_ie_fh_param_set *) pos; - memcpy(&bss->phy.fh, fh, sizeof(*fh)); - lbs_deb_scan("got FH IE\n"); - break; - - case WLAN_EID_DS_PARAMS: - ds = (struct ieee_ie_ds_param_set *) pos; - bss->channel = ds->channel; - memcpy(&bss->phy.ds, ds, sizeof(*ds)); - lbs_deb_scan("got DS IE, channel %d\n", bss->channel); - break; - - case WLAN_EID_CF_PARAMS: - cf = (struct ieee_ie_cf_param_set *) pos; - memcpy(&bss->ss.cf, cf, sizeof(*cf)); - lbs_deb_scan("got CF IE\n"); - break; - - case WLAN_EID_IBSS_PARAMS: - ibss = (struct ieee_ie_ibss_param_set *) pos; - bss->atimwindow = ibss->atimwindow; - memcpy(&bss->ss.ibss, ibss, sizeof(*ibss)); - lbs_deb_scan("got IBSS IE\n"); - break; - - case WLAN_EID_COUNTRY: - pcountryinfo = (struct ieee_ie_country_info_set *) pos; - lbs_deb_scan("got COUNTRY IE\n"); - if (pcountryinfo->header.len < sizeof(pcountryinfo->countrycode) - || pcountryinfo->header.len > 254) { - lbs_deb_scan("%s: 11D- Err CountryInfo len %d, min %zd, max 254\n", - __func__, - pcountryinfo->header.len, - sizeof(pcountryinfo->countrycode)); - ret = -1; - goto done; - } - - memcpy(&bss->countryinfo, pcountryinfo, - pcountryinfo->header.len + 2); - lbs_deb_hex(LBS_DEB_SCAN, "process_bss: 11d countryinfo", - (uint8_t *) pcountryinfo, - (int) (pcountryinfo->header.len + 2)); - break; - - case WLAN_EID_EXT_SUPP_RATES: - /* only process extended supported rate if data rate is - * already found. Data rate IE should come before - * extended supported rate IE - */ - lbs_deb_scan("got RATESEX IE\n"); - if (!got_basic_rates) { - lbs_deb_scan("... but ignoring it\n"); - break; - } - - n_ex_rates = pos[1]; - if (n_basic_rates + n_ex_rates > MAX_RATES) - n_ex_rates = MAX_RATES - n_basic_rates; - - p = bss->rates + n_basic_rates; - memcpy(p, pos + 2, n_ex_rates); - break; - - case WLAN_EID_GENERIC: - if (pos[1] >= 4 && - pos[2] == 0x00 && pos[3] == 0x50 && - pos[4] == 0xf2 && pos[5] == 0x01) { - bss->wpa_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN); - memcpy(bss->wpa_ie, pos, bss->wpa_ie_len); - lbs_deb_scan("got WPA IE\n"); - lbs_deb_hex(LBS_DEB_SCAN, "WPA IE", bss->wpa_ie, - bss->wpa_ie_len); - } else if (pos[1] >= MARVELL_MESH_IE_LENGTH && - pos[2] == 0x00 && pos[3] == 0x50 && - pos[4] == 0x43 && pos[5] == 0x04) { - lbs_deb_scan("got mesh IE\n"); - bss->mesh = 1; - } else { - lbs_deb_scan("got generic IE: %02x:%02x:%02x:%02x, len %d\n", - pos[2], pos[3], - pos[4], pos[5], - pos[1]); - } - break; - - case WLAN_EID_RSN: - lbs_deb_scan("got RSN IE\n"); - bss->rsn_ie_len = min(pos[1] + 2, MAX_WPA_IE_LEN); - memcpy(bss->rsn_ie, pos, bss->rsn_ie_len); - lbs_deb_hex(LBS_DEB_SCAN, "process_bss: RSN_IE", - bss->rsn_ie, bss->rsn_ie_len); - break; - - default: - lbs_deb_scan("got IE 0x%04x, len %d\n", - pos[0], pos[1]); - break; - } - - pos += pos[1] + 2; - } - - /* Timestamp */ - bss->last_scanned = jiffies; - lbs_unset_basic_rate_flags(bss->rates, sizeof(bss->rates)); - - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - -/** - * @brief Send a scan command for all available channels filtered on a spec - * - * Used in association code and from debugfs - * - * @param priv A pointer to struct lbs_private structure - * @param ssid A pointer to the SSID to scan for - * @param ssid_len Length of the SSID - * - * @return 0-success, otherwise fail - */ -int lbs_send_specific_ssid_scan(struct lbs_private *priv, uint8_t *ssid, - uint8_t ssid_len) -{ - DECLARE_SSID_BUF(ssid_buf); - int ret = 0; - - lbs_deb_enter_args(LBS_DEB_SCAN, "SSID '%s'\n", - print_ssid(ssid_buf, ssid, ssid_len)); - - if (!ssid_len) - goto out; - - memcpy(priv->scan_ssid, ssid, ssid_len); - priv->scan_ssid_len = ssid_len; - - lbs_scan_networks(priv, 1); - if (priv->surpriseremoved) { - ret = -1; - goto out; - } - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} - - - - -/*********************************************************************/ -/* */ -/* Support for Wireless Extensions */ -/* */ -/*********************************************************************/ - - -#define MAX_CUSTOM_LEN 64 - -static inline char *lbs_translate_scan(struct lbs_private *priv, - struct iw_request_info *info, - char *start, char *stop, - struct bss_descriptor *bss) -{ - struct chan_freq_power *cfp; - char *current_val; /* For rates */ - struct iw_event iwe; /* Temporary buffer */ - int j; -#define PERFECT_RSSI ((uint8_t)50) -#define WORST_RSSI ((uint8_t)0) -#define RSSI_DIFF ((uint8_t)(PERFECT_RSSI - WORST_RSSI)) - uint8_t rssi; - - lbs_deb_enter(LBS_DEB_SCAN); - - cfp = lbs_find_cfp_by_band_and_channel(priv, 0, bss->channel); - if (!cfp) { - lbs_deb_scan("Invalid channel number %d\n", bss->channel); - start = NULL; - goto out; - } - - /* First entry *MUST* be the BSSID */ - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, &bss->bssid, ETH_ALEN); - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN); - - /* SSID */ - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = min((uint32_t) bss->ssid_len, (uint32_t) IW_ESSID_MAX_SIZE); - start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); - - /* Mode */ - iwe.cmd = SIOCGIWMODE; - iwe.u.mode = bss->mode; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN); - - /* Frequency */ - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = (long)cfp->freq * 100000; - iwe.u.freq.e = 1; - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_FREQ_LEN); - - /* Add quality statistics */ - iwe.cmd = IWEVQUAL; - iwe.u.qual.updated = IW_QUAL_ALL_UPDATED; - iwe.u.qual.level = SCAN_RSSI(bss->rssi); - - rssi = iwe.u.qual.level - MRVDRV_NF_DEFAULT_SCAN_VALUE; - iwe.u.qual.qual = - (100 * RSSI_DIFF * RSSI_DIFF - (PERFECT_RSSI - rssi) * - (15 * (RSSI_DIFF) + 62 * (PERFECT_RSSI - rssi))) / - (RSSI_DIFF * RSSI_DIFF); - if (iwe.u.qual.qual > 100) - iwe.u.qual.qual = 100; - - if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { - iwe.u.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; - } else { - iwe.u.qual.noise = CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); - } - - /* Locally created ad-hoc BSSs won't have beacons if this is the - * only station in the adhoc network; so get signal strength - * from receive statistics. - */ - if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate - && !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len)) { - int snr, nf; - snr = priv->SNR[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; - nf = priv->NF[TYPE_RXPD][TYPE_AVG] / AVG_SCALE; - iwe.u.qual.level = CAL_RSSI(snr, nf); - } - start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN); - - /* Add encryption capability */ - iwe.cmd = SIOCGIWENCODE; - if (bss->capability & WLAN_CAPABILITY_PRIVACY) { - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - } else { - iwe.u.data.flags = IW_ENCODE_DISABLED; - } - iwe.u.data.length = 0; - start = iwe_stream_add_point(info, start, stop, &iwe, bss->ssid); - - current_val = start + iwe_stream_lcp_len(info); - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - iwe.u.bitrate.value = 0; - - for (j = 0; j < ARRAY_SIZE(bss->rates) && bss->rates[j]; j++) { - /* Bit rate given in 500 kb/s units */ - iwe.u.bitrate.value = bss->rates[j] * 500000; - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); - } - if ((bss->mode == IW_MODE_ADHOC) && priv->adhoccreate - && !lbs_ssid_cmp(priv->curbssparams.ssid, - priv->curbssparams.ssid_len, - bss->ssid, bss->ssid_len)) { - iwe.u.bitrate.value = 22 * 500000; - current_val = iwe_stream_add_value(info, start, current_val, - stop, &iwe, IW_EV_PARAM_LEN); - } - /* Check if we added any event */ - if ((current_val - start) > iwe_stream_lcp_len(info)) - start = current_val; - - memset(&iwe, 0, sizeof(iwe)); - if (bss->wpa_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, bss->wpa_ie, bss->wpa_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->wpa_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - memset(&iwe, 0, sizeof(iwe)); - if (bss->rsn_ie_len) { - char buf[MAX_WPA_IE_LEN]; - memcpy(buf, bss->rsn_ie, bss->rsn_ie_len); - iwe.cmd = IWEVGENIE; - iwe.u.data.length = bss->rsn_ie_len; - start = iwe_stream_add_point(info, start, stop, &iwe, buf); - } - - if (bss->mesh) { - char custom[MAX_CUSTOM_LEN]; - char *p = custom; - - iwe.cmd = IWEVCUSTOM; - p += snprintf(p, MAX_CUSTOM_LEN, "mesh-type: olpc"); - iwe.u.data.length = p - custom; - if (iwe.u.data.length) - start = iwe_stream_add_point(info, start, stop, - &iwe, custom); - } - -out: - lbs_deb_leave_args(LBS_DEB_SCAN, "start %p", start); - return start; -} - - -/** - * @brief Handle Scan Network ioctl - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param vwrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * - * @return 0 --success, otherwise fail - */ -int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - DECLARE_SSID_BUF(ssid); - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (!priv->radio_on) { - ret = -EINVAL; - goto out; - } - - if (!netif_running(dev)) { - ret = -ENETDOWN; - goto out; - } - - /* mac80211 does this: - struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->type != IEEE80211_IF_TYPE_xxx) { - ret = -EOPNOTSUPP; - goto out; - } - */ - - if (wrqu->data.length == sizeof(struct iw_scan_req) && - wrqu->data.flags & IW_SCAN_THIS_ESSID) { - struct iw_scan_req *req = (struct iw_scan_req *)extra; - priv->scan_ssid_len = req->essid_len; - memcpy(priv->scan_ssid, req->essid, priv->scan_ssid_len); - lbs_deb_wext("set_scan, essid '%s'\n", - print_ssid(ssid, priv->scan_ssid, priv->scan_ssid_len)); - } else { - priv->scan_ssid_len = 0; - } - - if (!delayed_work_pending(&priv->scan_work)) - queue_delayed_work(priv->work_thread, &priv->scan_work, - msecs_to_jiffies(50)); - /* set marker that currently a scan is taking place */ - priv->scan_channel = -1; - - if (priv->surpriseremoved) - ret = -EIO; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - - -/** - * @brief Handle Retrieve scan table ioctl - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param dwrq A pointer to iw_point structure - * @param extra A pointer to extra data buf - * - * @return 0 --success, otherwise fail - */ -int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ -#define SCAN_ITEM_SIZE 128 - struct lbs_private *priv = dev->ml_priv; - int err = 0; - char *ev = extra; - char *stop = ev + dwrq->length; - struct bss_descriptor *iter_bss; - struct bss_descriptor *safe; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* iwlist should wait until the current scan is finished */ - if (priv->scan_channel) - return -EAGAIN; - - /* Update RSSI if current BSS is a locally created ad-hoc BSS */ - if ((priv->mode == IW_MODE_ADHOC) && priv->adhoccreate) - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - CMD_OPTION_WAITFORRSP, 0, NULL); - - mutex_lock(&priv->lock); - list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { - char *next_ev; - unsigned long stale_time; - - if (stop - ev < SCAN_ITEM_SIZE) { - err = -E2BIG; - break; - } - - /* For mesh device, list only mesh networks */ - if (dev == priv->mesh_dev && !iter_bss->mesh) - continue; - - /* Prune old an old scan result */ - stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; - if (time_after(jiffies, stale_time)) { - list_move_tail(&iter_bss->list, &priv->network_free_list); - clear_bss_descriptor(iter_bss); - continue; - } - - /* Translate to WE format this entry */ - next_ev = lbs_translate_scan(priv, info, ev, stop, iter_bss); - if (next_ev == NULL) - continue; - ev = next_ev; - } - mutex_unlock(&priv->lock); - - dwrq->length = (ev - extra); - dwrq->flags = 0; - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", err); - return err; -} - - - - -/*********************************************************************/ -/* */ -/* Command execution */ -/* */ -/*********************************************************************/ - - -/** - * @brief This function handles the command response of scan - * - * Called from handle_cmd_response() in cmdrespc. - * - * The response buffer for the scan command has the following - * memory layout: - * - * .-----------------------------------------------------------. - * | header (4 * sizeof(u16)): Standard command response hdr | - * .-----------------------------------------------------------. - * | bufsize (u16) : sizeof the BSS Description data | - * .-----------------------------------------------------------. - * | NumOfSet (u8) : Number of BSS Descs returned | - * .-----------------------------------------------------------. - * | BSSDescription data (variable, size given in bufsize) | - * .-----------------------------------------------------------. - * | TLV data (variable, size calculated using header->size, | - * | bufsize and sizeof the fixed fields above) | - * .-----------------------------------------------------------. - * - * @param priv A pointer to struct lbs_private structure - * @param resp A pointer to cmd_ds_command - * - * @return 0 or -1 - */ -static int lbs_ret_80211_scan(struct lbs_private *priv, unsigned long dummy, - struct cmd_header *resp) -{ - struct cmd_ds_802_11_scan_rsp *scanresp = (void *)resp; - struct bss_descriptor *iter_bss; - struct bss_descriptor *safe; - uint8_t *bssinfo; - uint16_t scanrespsize; - int bytesleft; - int idx; - int tlvbufsize; - int ret; - - lbs_deb_enter(LBS_DEB_SCAN); - - /* Prune old entries from scan table */ - list_for_each_entry_safe (iter_bss, safe, &priv->network_list, list) { - unsigned long stale_time = iter_bss->last_scanned + DEFAULT_MAX_SCAN_AGE; - if (time_before(jiffies, stale_time)) - continue; - list_move_tail (&iter_bss->list, &priv->network_free_list); - clear_bss_descriptor(iter_bss); - } - - if (scanresp->nr_sets > MAX_NETWORK_COUNT) { - lbs_deb_scan("SCAN_RESP: too many scan results (%d, max %d)\n", - scanresp->nr_sets, MAX_NETWORK_COUNT); - ret = -1; - goto done; - } - - bytesleft = get_unaligned_le16(&scanresp->bssdescriptsize); - lbs_deb_scan("SCAN_RESP: bssdescriptsize %d\n", bytesleft); - - scanrespsize = le16_to_cpu(resp->size); - lbs_deb_scan("SCAN_RESP: scan results %d\n", scanresp->nr_sets); - - bssinfo = scanresp->bssdesc_and_tlvbuffer; - - /* The size of the TLV buffer is equal to the entire command response - * size (scanrespsize) minus the fixed fields (sizeof()'s), the - * BSS Descriptions (bssdescriptsize as bytesLef) and the command - * response header (S_DS_GEN) - */ - tlvbufsize = scanrespsize - (bytesleft + sizeof(scanresp->bssdescriptsize) - + sizeof(scanresp->nr_sets) - + S_DS_GEN); - - /* - * Process each scan response returned (scanresp->nr_sets). Save - * the information in the newbssentry and then insert into the - * driver scan table either as an update to an existing entry - * or as an addition at the end of the table - */ - for (idx = 0; idx < scanresp->nr_sets && bytesleft; idx++) { - struct bss_descriptor new; - struct bss_descriptor *found = NULL; - struct bss_descriptor *oldest = NULL; - - /* Process the data fields and IEs returned for this BSS */ - memset(&new, 0, sizeof (struct bss_descriptor)); - if (lbs_process_bss(&new, &bssinfo, &bytesleft) != 0) { - /* error parsing the scan response, skipped */ - lbs_deb_scan("SCAN_RESP: process_bss returned ERROR\n"); - continue; - } - - /* Try to find this bss in the scan table */ - list_for_each_entry (iter_bss, &priv->network_list, list) { - if (is_same_network(iter_bss, &new)) { - found = iter_bss; - break; - } - - if ((oldest == NULL) || - (iter_bss->last_scanned < oldest->last_scanned)) - oldest = iter_bss; - } - - if (found) { - /* found, clear it */ - clear_bss_descriptor(found); - } else if (!list_empty(&priv->network_free_list)) { - /* Pull one from the free list */ - found = list_entry(priv->network_free_list.next, - struct bss_descriptor, list); - list_move_tail(&found->list, &priv->network_list); - } else if (oldest) { - /* If there are no more slots, expire the oldest */ - found = oldest; - clear_bss_descriptor(found); - list_move_tail(&found->list, &priv->network_list); - } else { - continue; - } - - lbs_deb_scan("SCAN_RESP: BSSID %pM\n", new.bssid); - - /* Copy the locally created newbssentry to the scan table */ - memcpy(found, &new, offsetof(struct bss_descriptor, list)); - } - - ret = 0; - -done: - lbs_deb_leave_args(LBS_DEB_SCAN, "ret %d", ret); - return ret; -} diff --git a/drivers/net/wireless/libertas/scan.h b/drivers/net/wireless/libertas/scan.h deleted file mode 100644 index fab7d5d097fc..000000000000 --- a/drivers/net/wireless/libertas/scan.h +++ /dev/null @@ -1,33 +0,0 @@ -/** - * Interface for the wlan network scan routines - * - * Driver interface functions and type declarations for the scan module - * implemented in scan.c. - */ -#ifndef _LBS_SCAN_H -#define _LBS_SCAN_H - -#include - -#define MAX_NETWORK_COUNT 128 - -/** - * @brief Maximum number of channels that can be sent in a setuserscan ioctl - */ -#define LBS_IOCTL_USER_SCAN_CHAN_MAX 50 - -int lbs_ssid_cmp(u8 *ssid1, u8 ssid1_len, u8 *ssid2, u8 ssid2_len); - -int lbs_send_specific_ssid_scan(struct lbs_private *priv, u8 *ssid, - u8 ssid_len); - -int lbs_get_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra); -int lbs_set_scan(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra); - -int lbs_scan_networks(struct lbs_private *priv, int full_scan); - -void lbs_scan_worker(struct work_struct *work); - -#endif diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c deleted file mode 100644 index 8c3766a6e8e7..000000000000 --- a/drivers/net/wireless/libertas/tx.c +++ /dev/null @@ -1,209 +0,0 @@ -/** - * This file contains the handling of TX in wlan driver. - */ -#include -#include -#include - -#include "hostcmd.h" -#include "radiotap.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "wext.h" - -/** - * @brief This function converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE - * units (500 Kb/s) into Marvell WLAN format (see Table 8 in Section 3.2.1) - * - * @param rate Input rate - * @return Output Rate (0 if invalid) - */ -static u32 convert_radiotap_rate_to_mv(u8 rate) -{ - switch (rate) { - case 2: /* 1 Mbps */ - return 0 | (1 << 4); - case 4: /* 2 Mbps */ - return 1 | (1 << 4); - case 11: /* 5.5 Mbps */ - return 2 | (1 << 4); - case 22: /* 11 Mbps */ - return 3 | (1 << 4); - case 12: /* 6 Mbps */ - return 4 | (1 << 4); - case 18: /* 9 Mbps */ - return 5 | (1 << 4); - case 24: /* 12 Mbps */ - return 6 | (1 << 4); - case 36: /* 18 Mbps */ - return 7 | (1 << 4); - case 48: /* 24 Mbps */ - return 8 | (1 << 4); - case 72: /* 36 Mbps */ - return 9 | (1 << 4); - case 96: /* 48 Mbps */ - return 10 | (1 << 4); - case 108: /* 54 Mbps */ - return 11 | (1 << 4); - } - return 0; -} - -/** - * @brief This function checks the conditions and sends packet to IF - * layer if everything is ok. - * - * @param priv A pointer to struct lbs_private structure - * @param skb A pointer to skb which includes TX packet - * @return 0 or -1 - */ -netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned long flags; - struct lbs_private *priv = dev->ml_priv; - struct txpd *txpd; - char *p802x_hdr; - uint16_t pkt_len; - netdev_tx_t ret = NETDEV_TX_OK; - - lbs_deb_enter(LBS_DEB_TX); - - /* We need to protect against the queues being restarted before - we get round to stopping them */ - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->surpriseremoved) - goto free; - - if (!skb->len || (skb->len > MRVDRV_ETH_TX_PACKET_BUFFER_SIZE)) { - lbs_deb_tx("tx err: skb length %d 0 or > %zd\n", - skb->len, MRVDRV_ETH_TX_PACKET_BUFFER_SIZE); - /* We'll never manage to send this one; drop it and return 'OK' */ - - dev->stats.tx_dropped++; - dev->stats.tx_errors++; - goto free; - } - - - netif_stop_queue(priv->dev); - if (priv->mesh_dev) - netif_stop_queue(priv->mesh_dev); - - if (priv->tx_pending_len) { - /* This can happen if packets come in on the mesh and eth - device simultaneously -- there's no mutual exclusion on - hard_start_xmit() calls between devices. */ - lbs_deb_tx("Packet on %s while busy\n", dev->name); - ret = NETDEV_TX_BUSY; - goto unlock; - } - - priv->tx_pending_len = -1; - spin_unlock_irqrestore(&priv->driver_lock, flags); - - lbs_deb_hex(LBS_DEB_TX, "TX Data", skb->data, min_t(unsigned int, skb->len, 100)); - - txpd = (void *)priv->tx_pending_buf; - memset(txpd, 0, sizeof(struct txpd)); - - p802x_hdr = skb->data; - pkt_len = skb->len; - - if (dev == priv->rtap_net_dev) { - struct tx_radiotap_hdr *rtap_hdr = (void *)skb->data; - - /* set txpd fields from the radiotap header */ - txpd->tx_control = cpu_to_le32(convert_radiotap_rate_to_mv(rtap_hdr->rate)); - - /* skip the radiotap header */ - p802x_hdr += sizeof(*rtap_hdr); - pkt_len -= sizeof(*rtap_hdr); - - /* copy destination address from 802.11 header */ - memcpy(txpd->tx_dest_addr_high, p802x_hdr + 4, ETH_ALEN); - } else { - /* copy destination address from 802.3 header */ - memcpy(txpd->tx_dest_addr_high, p802x_hdr, ETH_ALEN); - } - - txpd->tx_packet_length = cpu_to_le16(pkt_len); - txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); - - if (dev == priv->mesh_dev) { - if (priv->mesh_fw_ver == MESH_FW_OLD) - txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME); - else if (priv->mesh_fw_ver == MESH_FW_NEW) - txpd->u.bss.bss_num = MESH_IFACE_ID; - } - - lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); - - lbs_deb_hex(LBS_DEB_TX, "Tx Data", (u8 *) p802x_hdr, le16_to_cpu(txpd->tx_packet_length)); - - memcpy(&txpd[1], p802x_hdr, le16_to_cpu(txpd->tx_packet_length)); - - spin_lock_irqsave(&priv->driver_lock, flags); - priv->tx_pending_len = pkt_len + sizeof(struct txpd); - - lbs_deb_tx("%s lined up packet\n", __func__); - - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - - dev->trans_start = jiffies; - - if (priv->monitormode) { - /* Keep the skb to echo it back once Tx feedback is - received from FW */ - skb_orphan(skb); - - /* Keep the skb around for when we get feedback */ - priv->currenttxskb = skb; - } else { - free: - dev_kfree_skb_any(skb); - } - unlock: - spin_unlock_irqrestore(&priv->driver_lock, flags); - wake_up(&priv->waitq); - - lbs_deb_leave_args(LBS_DEB_TX, "ret %d", ret); - return ret; -} - -/** - * @brief This function sends to the host the last transmitted packet, - * filling the radiotap headers with transmission information. - * - * @param priv A pointer to struct lbs_private structure - * @param status A 32 bit value containing transmission status. - * - * @returns void - */ -void lbs_send_tx_feedback(struct lbs_private *priv, u32 try_count) -{ - struct tx_radiotap_hdr *radiotap_hdr; - - if (!priv->monitormode || priv->currenttxskb == NULL) - return; - - radiotap_hdr = (struct tx_radiotap_hdr *)priv->currenttxskb->data; - - radiotap_hdr->data_retries = try_count ? - (1 + priv->txretrycount - try_count) : 0; - - priv->currenttxskb->protocol = eth_type_trans(priv->currenttxskb, - priv->rtap_net_dev); - netif_rx(priv->currenttxskb); - - priv->currenttxskb = NULL; - - if (priv->connect_status == LBS_CONNECTED) - netif_wake_queue(priv->dev); - - if (priv->mesh_dev && (priv->mesh_connect_status == LBS_CONNECTED)) - netif_wake_queue(priv->mesh_dev); -} -EXPORT_SYMBOL_GPL(lbs_send_tx_feedback); diff --git a/drivers/net/wireless/libertas/types.h b/drivers/net/wireless/libertas/types.h deleted file mode 100644 index 99905df65b25..000000000000 --- a/drivers/net/wireless/libertas/types.h +++ /dev/null @@ -1,266 +0,0 @@ -/** - * This header file contains definition for global types - */ -#ifndef _LBS_TYPES_H_ -#define _LBS_TYPES_H_ - -#include -#include -#include - -struct ieee_ie_header { - u8 id; - u8 len; -} __attribute__ ((packed)); - -struct ieee_ie_cf_param_set { - struct ieee_ie_header header; - - u8 cfpcnt; - u8 cfpperiod; - __le16 cfpmaxduration; - __le16 cfpdurationremaining; -} __attribute__ ((packed)); - - -struct ieee_ie_ibss_param_set { - struct ieee_ie_header header; - - __le16 atimwindow; -} __attribute__ ((packed)); - -union ieee_ss_param_set { - struct ieee_ie_cf_param_set cf; - struct ieee_ie_ibss_param_set ibss; -} __attribute__ ((packed)); - -struct ieee_ie_fh_param_set { - struct ieee_ie_header header; - - __le16 dwelltime; - u8 hopset; - u8 hoppattern; - u8 hopindex; -} __attribute__ ((packed)); - -struct ieee_ie_ds_param_set { - struct ieee_ie_header header; - - u8 channel; -} __attribute__ ((packed)); - -union ieee_phy_param_set { - struct ieee_ie_fh_param_set fh; - struct ieee_ie_ds_param_set ds; -} __attribute__ ((packed)); - -/** TLV type ID definition */ -#define PROPRIETARY_TLV_BASE_ID 0x0100 - -/* Terminating TLV type */ -#define MRVL_TERMINATE_TLV_ID 0xffff - -#define TLV_TYPE_SSID 0x0000 -#define TLV_TYPE_RATES 0x0001 -#define TLV_TYPE_PHY_FH 0x0002 -#define TLV_TYPE_PHY_DS 0x0003 -#define TLV_TYPE_CF 0x0004 -#define TLV_TYPE_IBSS 0x0006 - -#define TLV_TYPE_DOMAIN 0x0007 - -#define TLV_TYPE_POWER_CAPABILITY 0x0021 - -#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) -#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) -#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) -#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) -#define TLV_TYPE_SNR_LOW (PROPRIETARY_TLV_BASE_ID + 5) -#define TLV_TYPE_FAILCOUNT (PROPRIETARY_TLV_BASE_ID + 6) -#define TLV_TYPE_BCNMISS (PROPRIETARY_TLV_BASE_ID + 7) -#define TLV_TYPE_LED_GPIO (PROPRIETARY_TLV_BASE_ID + 8) -#define TLV_TYPE_LEDBEHAVIOR (PROPRIETARY_TLV_BASE_ID + 9) -#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) -#define TLV_TYPE_REASSOCAP (PROPRIETARY_TLV_BASE_ID + 11) -#define TLV_TYPE_POWER_TBL_2_4GHZ (PROPRIETARY_TLV_BASE_ID + 12) -#define TLV_TYPE_POWER_TBL_5GHZ (PROPRIETARY_TLV_BASE_ID + 13) -#define TLV_TYPE_BCASTPROBE (PROPRIETARY_TLV_BASE_ID + 14) -#define TLV_TYPE_NUMSSID_PROBE (PROPRIETARY_TLV_BASE_ID + 15) -#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) -#define TLV_TYPE_CRYPTO_DATA (PROPRIETARY_TLV_BASE_ID + 17) -#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) -#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) -#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) -#define TLV_TYPE_SNR_HIGH (PROPRIETARY_TLV_BASE_ID + 23) -#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) -#define TLV_TYPE_MESH_ID (PROPRIETARY_TLV_BASE_ID + 37) -#define TLV_TYPE_OLD_MESH_ID (PROPRIETARY_TLV_BASE_ID + 291) - -/** TLV related data structures*/ -struct mrvl_ie_header { - __le16 type; - __le16 len; -} __attribute__ ((packed)); - -struct mrvl_ie_data { - struct mrvl_ie_header header; - u8 Data[1]; -} __attribute__ ((packed)); - -struct mrvl_ie_rates_param_set { - struct mrvl_ie_header header; - u8 rates[1]; -} __attribute__ ((packed)); - -struct mrvl_ie_ssid_param_set { - struct mrvl_ie_header header; - u8 ssid[1]; -} __attribute__ ((packed)); - -struct mrvl_ie_wildcard_ssid_param_set { - struct mrvl_ie_header header; - u8 MaxSsidlength; - u8 ssid[1]; -} __attribute__ ((packed)); - -struct chanscanmode { -#ifdef __BIG_ENDIAN_BITFIELD - u8 reserved_2_7:6; - u8 disablechanfilt:1; - u8 passivescan:1; -#else - u8 passivescan:1; - u8 disablechanfilt:1; - u8 reserved_2_7:6; -#endif -} __attribute__ ((packed)); - -struct chanscanparamset { - u8 radiotype; - u8 channumber; - struct chanscanmode chanscanmode; - __le16 minscantime; - __le16 maxscantime; -} __attribute__ ((packed)); - -struct mrvl_ie_chanlist_param_set { - struct mrvl_ie_header header; - struct chanscanparamset chanscanparam[1]; -} __attribute__ ((packed)); - -struct mrvl_ie_cf_param_set { - struct mrvl_ie_header header; - u8 cfpcnt; - u8 cfpperiod; - __le16 cfpmaxduration; - __le16 cfpdurationremaining; -} __attribute__ ((packed)); - -struct mrvl_ie_ds_param_set { - struct mrvl_ie_header header; - u8 channel; -} __attribute__ ((packed)); - -struct mrvl_ie_rsn_param_set { - struct mrvl_ie_header header; - u8 rsnie[1]; -} __attribute__ ((packed)); - -struct mrvl_ie_tsf_timestamp { - struct mrvl_ie_header header; - __le64 tsftable[1]; -} __attribute__ ((packed)); - -/* v9 and later firmware only */ -struct mrvl_ie_auth_type { - struct mrvl_ie_header header; - __le16 auth; -} __attribute__ ((packed)); - -/** Local Power capability */ -struct mrvl_ie_power_capability { - struct mrvl_ie_header header; - s8 minpower; - s8 maxpower; -} __attribute__ ((packed)); - -/* used in CMD_802_11_SUBSCRIBE_EVENT for SNR, RSSI and Failure */ -struct mrvl_ie_thresholds { - struct mrvl_ie_header header; - u8 value; - u8 freq; -} __attribute__ ((packed)); - -struct mrvl_ie_beacons_missed { - struct mrvl_ie_header header; - u8 beaconmissed; - u8 reserved; -} __attribute__ ((packed)); - -struct mrvl_ie_num_probes { - struct mrvl_ie_header header; - __le16 numprobes; -} __attribute__ ((packed)); - -struct mrvl_ie_bcast_probe { - struct mrvl_ie_header header; - __le16 bcastprobe; -} __attribute__ ((packed)); - -struct mrvl_ie_num_ssid_probe { - struct mrvl_ie_header header; - __le16 numssidprobe; -} __attribute__ ((packed)); - -struct led_pin { - u8 led; - u8 pin; -} __attribute__ ((packed)); - -struct mrvl_ie_ledgpio { - struct mrvl_ie_header header; - struct led_pin ledpin[1]; -} __attribute__ ((packed)); - -struct led_bhv { - uint8_t firmwarestate; - uint8_t led; - uint8_t ledstate; - uint8_t ledarg; -} __attribute__ ((packed)); - - -struct mrvl_ie_ledbhv { - struct mrvl_ie_header header; - struct led_bhv ledbhv[1]; -} __attribute__ ((packed)); - -/* Meant to be packed as the value member of a struct ieee80211_info_element. - * Note that the len member of the ieee80211_info_element varies depending on - * the mesh_id_len */ -struct mrvl_meshie_val { - uint8_t oui[3]; - uint8_t type; - uint8_t subtype; - uint8_t version; - uint8_t active_protocol_id; - uint8_t active_metric_id; - uint8_t mesh_capability; - uint8_t mesh_id_len; - uint8_t mesh_id[IW_ESSID_MAX_SIZE]; -} __attribute__ ((packed)); - -struct mrvl_meshie { - u8 id, len; - struct mrvl_meshie_val val; -} __attribute__ ((packed)); - -struct mrvl_mesh_defaults { - __le32 bootflag; - uint8_t boottime; - uint8_t reserved; - __le16 channel; - struct mrvl_meshie meshie; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c deleted file mode 100644 index 10e3a442a56b..000000000000 --- a/drivers/net/wireless/libertas/wext.c +++ /dev/null @@ -1,2312 +0,0 @@ -/** - * This file contains ioctl functions - */ -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "host.h" -#include "radiotap.h" -#include "decl.h" -#include "defs.h" -#include "dev.h" -#include "wext.h" -#include "scan.h" -#include "assoc.h" -#include "cmd.h" - - -static inline void lbs_postpone_association_work(struct lbs_private *priv) -{ - if (priv->surpriseremoved) - return; - cancel_delayed_work(&priv->assoc_work); - queue_delayed_work(priv->work_thread, &priv->assoc_work, HZ / 2); -} - -static inline void lbs_do_association_work(struct lbs_private *priv) -{ - if (priv->surpriseremoved) - return; - cancel_delayed_work(&priv->assoc_work); - queue_delayed_work(priv->work_thread, &priv->assoc_work, 0); -} - -static inline void lbs_cancel_association_work(struct lbs_private *priv) -{ - cancel_delayed_work(&priv->assoc_work); - kfree(priv->pending_assoc_req); - priv->pending_assoc_req = NULL; -} - - -/** - * @brief Find the channel frequency power info with specific channel - * - * @param priv A pointer to struct lbs_private structure - * @param band it can be BAND_A, BAND_G or BAND_B - * @param channel the channel for looking - * @return A pointer to struct chan_freq_power structure or NULL if not find. - */ -struct chan_freq_power *lbs_find_cfp_by_band_and_channel( - struct lbs_private *priv, - u8 band, - u16 channel) -{ - struct chan_freq_power *cfp = NULL; - struct region_channel *rc; - int i, j; - - for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { - rc = &priv->region_channel[j]; - - if (priv->enable11d) - rc = &priv->universal_channel[j]; - if (!rc->valid || !rc->CFP) - continue; - if (rc->band != band) - continue; - for (i = 0; i < rc->nrcfp; i++) { - if (rc->CFP[i].channel == channel) { - cfp = &rc->CFP[i]; - break; - } - } - } - - if (!cfp && channel) - lbs_deb_wext("lbs_find_cfp_by_band_and_channel: can't find " - "cfp by band %d / channel %d\n", band, channel); - - return cfp; -} - -/** - * @brief Find the channel frequency power info with specific frequency - * - * @param priv A pointer to struct lbs_private structure - * @param band it can be BAND_A, BAND_G or BAND_B - * @param freq the frequency for looking - * @return A pointer to struct chan_freq_power structure or NULL if not find. - */ -static struct chan_freq_power *find_cfp_by_band_and_freq( - struct lbs_private *priv, - u8 band, - u32 freq) -{ - struct chan_freq_power *cfp = NULL; - struct region_channel *rc; - int i, j; - - for (j = 0; !cfp && (j < ARRAY_SIZE(priv->region_channel)); j++) { - rc = &priv->region_channel[j]; - - if (priv->enable11d) - rc = &priv->universal_channel[j]; - if (!rc->valid || !rc->CFP) - continue; - if (rc->band != band) - continue; - for (i = 0; i < rc->nrcfp; i++) { - if (rc->CFP[i].freq == freq) { - cfp = &rc->CFP[i]; - break; - } - } - } - - if (!cfp && freq) - lbs_deb_wext("find_cfp_by_band_and_freql: can't find cfp by " - "band %d / freq %d\n", band, freq); - - return cfp; -} - -/** - * @brief Copy active data rates based on adapter mode and status - * - * @param priv A pointer to struct lbs_private structure - * @param rate The buf to return the active rates - */ -static void copy_active_data_rates(struct lbs_private *priv, u8 *rates) -{ - lbs_deb_enter(LBS_DEB_WEXT); - - if ((priv->connect_status != LBS_CONNECTED) && - (priv->mesh_connect_status != LBS_CONNECTED)) - memcpy(rates, lbs_bg_rates, MAX_RATES); - else - memcpy(rates, priv->curbssparams.rates, MAX_RATES); - - lbs_deb_leave(LBS_DEB_WEXT); -} - -static int lbs_get_name(struct net_device *dev, struct iw_request_info *info, - char *cwrq, char *extra) -{ - - lbs_deb_enter(LBS_DEB_WEXT); - - /* We could add support for 802.11n here as needed. Jean II */ - snprintf(cwrq, IFNAMSIZ, "IEEE 802.11b/g"); - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_get_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - struct chan_freq_power *cfp; - - lbs_deb_enter(LBS_DEB_WEXT); - - cfp = lbs_find_cfp_by_band_and_channel(priv, 0, - priv->curbssparams.channel); - - if (!cfp) { - if (priv->curbssparams.channel) - lbs_deb_wext("invalid channel %d\n", - priv->curbssparams.channel); - return -EINVAL; - } - - fwrq->m = (long)cfp->freq * 100000; - fwrq->e = 1; - - lbs_deb_wext("freq %u\n", fwrq->m); - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_get_wap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (priv->connect_status == LBS_CONNECTED) { - memcpy(awrq->sa_data, priv->curbssparams.bssid, ETH_ALEN); - } else { - memset(awrq->sa_data, 0, ETH_ALEN); - } - awrq->sa_family = ARPHRD_ETHER; - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_set_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* - * Check the size of the string - */ - - if (dwrq->length > 16) { - return -E2BIG; - } - - mutex_lock(&priv->lock); - memset(priv->nodename, 0, sizeof(priv->nodename)); - memcpy(priv->nodename, extra, dwrq->length); - mutex_unlock(&priv->lock); - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - dwrq->length = strlen(priv->nodename); - memcpy(extra, priv->nodename, dwrq->length); - extra[dwrq->length] = '\0'; - - dwrq->flags = 1; /* active */ - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int mesh_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* Use nickname to indicate that mesh is on */ - - if (priv->mesh_connect_status == LBS_CONNECTED) { - strncpy(extra, "Mesh", 12); - extra[12] = '\0'; - dwrq->length = strlen(extra); - } - - else { - extra[0] = '\0'; - dwrq->length = 0; - } - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - u32 val = vwrq->value; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (vwrq->disabled) - val = MRVDRV_RTS_MAX_VALUE; - - if (val > MRVDRV_RTS_MAX_VALUE) /* min rts value is 0 */ - return -EINVAL; - - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, (u16) val); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - u16 val = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_RTS_THRESHOLD, &val); - if (ret) - goto out; - - vwrq->value = val; - vwrq->disabled = val > MRVDRV_RTS_MAX_VALUE; /* min rts value is 0 */ - vwrq->fixed = 1; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - u32 val = vwrq->value; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (vwrq->disabled) - val = MRVDRV_FRAG_MAX_VALUE; - - if (val < MRVDRV_FRAG_MIN_VALUE || val > MRVDRV_FRAG_MAX_VALUE) - return -EINVAL; - - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, (u16) val); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - u16 val = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_FRAG_THRESHOLD, &val); - if (ret) - goto out; - - vwrq->value = val; - vwrq->disabled = ((val < MRVDRV_FRAG_MIN_VALUE) - || (val > MRVDRV_FRAG_MAX_VALUE)); - vwrq->fixed = 1; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_mode(struct net_device *dev, - struct iw_request_info *info, u32 * uwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - *uwrq = priv->mode; - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int mesh_wlan_get_mode(struct net_device *dev, - struct iw_request_info *info, u32 * uwrq, - char *extra) -{ - lbs_deb_enter(LBS_DEB_WEXT); - - *uwrq = IW_MODE_REPEAT; - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_get_txpow(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - s16 curlevel = 0; - int ret = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (!priv->radio_on) { - lbs_deb_wext("tx power off\n"); - vwrq->value = 0; - vwrq->disabled = 1; - goto out; - } - - ret = lbs_get_tx_power(priv, &curlevel, NULL, NULL); - if (ret) - goto out; - - lbs_deb_wext("tx power level %d dbm\n", curlevel); - priv->txpower_cur = curlevel; - - vwrq->value = curlevel; - vwrq->fixed = 1; - vwrq->disabled = 0; - vwrq->flags = IW_TXPOW_DBM; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_set_retry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - u16 slimit = 0, llimit = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - if ((vwrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) - return -EOPNOTSUPP; - - /* The MAC has a 4-bit Total_Tx_Count register - Total_Tx_Count = 1 + Tx_Retry_Count */ -#define TX_RETRY_MIN 0 -#define TX_RETRY_MAX 14 - if (vwrq->value < TX_RETRY_MIN || vwrq->value > TX_RETRY_MAX) - return -EINVAL; - - /* Add 1 to convert retry count to try count */ - if (vwrq->flags & IW_RETRY_SHORT) - slimit = (u16) (vwrq->value + 1); - else if (vwrq->flags & IW_RETRY_LONG) - llimit = (u16) (vwrq->value + 1); - else - slimit = llimit = (u16) (vwrq->value + 1); /* set both */ - - if (llimit) { - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, - llimit); - if (ret) - goto out; - } - - if (slimit) { - /* txretrycount follows the short retry limit */ - priv->txretrycount = slimit; - ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, - slimit); - if (ret) - goto out; - } - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_retry(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - u16 val = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - vwrq->disabled = 0; - - if (vwrq->flags & IW_RETRY_LONG) { - ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_LONG_RETRY_LIMIT, &val); - if (ret) - goto out; - - /* Subtract 1 to convert try count to retry count */ - vwrq->value = val - 1; - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - } else { - ret = lbs_get_snmp_mib(priv, SNMP_MIB_OID_SHORT_RETRY_LIMIT, &val); - if (ret) - goto out; - - /* txretry count follows the short retry limit */ - priv->txretrycount = val; - /* Subtract 1 to convert try count to retry count */ - vwrq->value = val - 1; - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; - } - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static inline void sort_channels(struct iw_freq *freq, int num) -{ - int i, j; - struct iw_freq temp; - - for (i = 0; i < num; i++) - for (j = i + 1; j < num; j++) - if (freq[i].i > freq[j].i) { - temp.i = freq[i].i; - temp.m = freq[i].m; - - freq[i].i = freq[j].i; - freq[i].m = freq[j].m; - - freq[j].i = temp.i; - freq[j].m = temp.m; - } -} - -static int lbs_get_sense(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - //struct lbs_private *priv = dev->priv; - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - -#if 1 - - if (priv->connect_status == LBS_CONNECTED) - { - //if ((pm_onelevel_status == 0) && (wifi_ps_status == WIFI_PS_AWAKE)) - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, CMD_OPTION_WAITFORRSP, 0, NULL); - - /* Quality by RSSI */ - priv->wstats.qual.level = - CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], - priv->NF[TYPE_BEACON][TYPE_NOAVG]); - - if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) - { - priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; - } else { - priv->wstats.qual.noise = - CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); - } - //printk("signal level %d ", priv->wstats.qual.level); - //printk("noise %d ", priv->wstats.qual.noise); - vwrq->value = 100 -(priv->wstats.qual.level - priv->wstats.qual.noise); - //printk("rssi %d\n", vwrq->value); - //lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, 0, 0, NULL); - } - else - { - vwrq->value = 30; - } -#else - vwrq->value = 60; -#endif - - lbs_deb_leave(LBS_DEB_WEXT); - - return 1; -} - -/* data rate listing - MULTI_BANDS: - abg a b b/g - Infra G(12) A(8) B(4) G(12) - Adhoc A+B(12) A(8) B(4) B(4) - - non-MULTI_BANDS: - b b/g - Infra B(4) G(12) - Adhoc B(4) B(4) - */ -/** - * @brief Get Range Info - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param vwrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * @return 0 --success, otherwise fail - */ -static int lbs_get_range(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - int i, j; - struct lbs_private *priv = dev->ml_priv; - struct iw_range *range = (struct iw_range *)extra; - struct chan_freq_power *cfp; - u8 rates[MAX_RATES + 1]; - - u8 flag = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - dwrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - - range->min_nwid = 0; - range->max_nwid = 0; - - memset(rates, 0, sizeof(rates)); - copy_active_data_rates(priv, rates); - range->num_bitrates = strnlen(rates, IW_MAX_BITRATES); - for (i = 0; i < range->num_bitrates; i++) - range->bitrate[i] = rates[i] * 500000; - range->num_bitrates = i; - lbs_deb_wext("IW_MAX_BITRATES %d, num_bitrates %d\n", IW_MAX_BITRATES, - range->num_bitrates); - - range->num_frequency = 0; - - range->scan_capa = IW_SCAN_CAPA_ESSID; - - if (priv->enable11d && - (priv->connect_status == LBS_CONNECTED || - priv->mesh_connect_status == LBS_CONNECTED)) { - u8 chan_no; - u8 band; - - struct parsed_region_chan_11d *parsed_region_chan = - &priv->parsed_region_chan; - - if (parsed_region_chan == NULL) { - lbs_deb_wext("11d: parsed_region_chan is NULL\n"); - goto out; - } - band = parsed_region_chan->band; - lbs_deb_wext("band %d, nr_char %d\n", band, - parsed_region_chan->nr_chan); - - for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) - && (i < parsed_region_chan->nr_chan); i++) { - chan_no = parsed_region_chan->chanpwr[i].chan; - lbs_deb_wext("chan_no %d\n", chan_no); - range->freq[range->num_frequency].i = (long)chan_no; - range->freq[range->num_frequency].m = - (long)lbs_chan_2_freq(chan_no) * 100000; - range->freq[range->num_frequency].e = 1; - range->num_frequency++; - } - flag = 1; - } - if (!flag) { - for (j = 0; (range->num_frequency < IW_MAX_FREQUENCIES) - && (j < ARRAY_SIZE(priv->region_channel)); j++) { - cfp = priv->region_channel[j].CFP; - for (i = 0; (range->num_frequency < IW_MAX_FREQUENCIES) - && priv->region_channel[j].valid - && cfp - && (i < priv->region_channel[j].nrcfp); i++) { - range->freq[range->num_frequency].i = - (long)cfp->channel; - range->freq[range->num_frequency].m = - (long)cfp->freq * 100000; - range->freq[range->num_frequency].e = 1; - cfp++; - range->num_frequency++; - } - } - } - - lbs_deb_wext("IW_MAX_FREQUENCIES %d, num_frequency %d\n", - IW_MAX_FREQUENCIES, range->num_frequency); - - range->num_channels = range->num_frequency; - - sort_channels(&range->freq[0], range->num_frequency); - - /* - * Set an indication of the max TCP throughput in bit/s that we can - * expect using this interface - */ - if (i > 2) - range->throughput = 5000 * 1000; - else - range->throughput = 1500 * 1000; - - range->min_rts = MRVDRV_RTS_MIN_VALUE; - range->max_rts = MRVDRV_RTS_MAX_VALUE; - range->min_frag = MRVDRV_FRAG_MIN_VALUE; - range->max_frag = MRVDRV_FRAG_MAX_VALUE; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = 4; - - /* - * Right now we support only "iwconfig ethX power on|off" - */ - range->pm_capa = IW_POWER_ON; - - /* - * Minimum version we recommend - */ - range->we_version_source = 15; - - /* - * Version we are compiled with - */ - range->we_version_compiled = WIRELESS_EXT; - - range->retry_capa = IW_RETRY_LIMIT; - range->retry_flags = IW_RETRY_LIMIT | IW_RETRY_MAX; - - range->min_retry = TX_RETRY_MIN; - range->max_retry = TX_RETRY_MAX; - - /* - * Set the qual, level and noise range values - */ - range->max_qual.qual = 100; - range->max_qual.level = 0; - range->max_qual.noise = 0; - range->max_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - - range->avg_qual.qual = 70; - /* TODO: Find real 'good' to 'bad' threshold value for RSSI */ - range->avg_qual.level = 0; - range->avg_qual.noise = 0; - range->avg_qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - - range->sensitivity = 0; - - /* Setup the supported power level ranges */ - memset(range->txpower, 0, sizeof(range->txpower)); - range->txpower_capa = IW_TXPOW_DBM | IW_TXPOW_RANGE; - range->txpower[0] = priv->txpower_min; - range->txpower[1] = priv->txpower_max; - range->num_txpower = 2; - - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWAP) | - IW_EVENT_CAPA_MASK(SIOCGIWSCAN)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - - if (priv->fwcapinfo & FW_CAPINFO_WPA) { - range->enc_capa = IW_ENC_CAPA_WPA - | IW_ENC_CAPA_WPA2 - | IW_ENC_CAPA_CIPHER_TKIP - | IW_ENC_CAPA_CIPHER_CCMP; - } - -out: - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_set_power(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (!(priv->fwcapinfo & FW_CAPINFO_PS)) { - if (vwrq->disabled) - return 0; - else - return -EINVAL; - } - - /* PS is currently supported only in Infrastructure mode - * Remove this check if it is to be supported in IBSS mode also - */ - - if (vwrq->disabled) { - priv->psmode = LBS802_11POWERMODECAM; - if (priv->psstate != PS_STATE_FULL_POWER) { - lbs_ps_wakeup(priv, CMD_OPTION_WAITFORRSP); - } - - return 0; - } - - if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - lbs_deb_wext( - "setting power timeout is not supported\n"); - return -EINVAL; - } else if ((vwrq->flags & IW_POWER_TYPE) == IW_POWER_PERIOD) { - lbs_deb_wext("setting power period not supported\n"); - return -EINVAL; - } - - if (priv->psmode != LBS802_11POWERMODECAM) { - return 0; - } - - priv->psmode = LBS802_11POWERMODEMAX_PSP; - - if (priv->connect_status == LBS_CONNECTED) { - lbs_ps_sleep(priv, CMD_OPTION_WAITFORRSP); - } - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_get_power(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - vwrq->value = 0; - vwrq->flags = 0; - vwrq->disabled = priv->psmode == LBS802_11POWERMODECAM - || priv->connect_status == LBS_DISCONNECTED; - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static struct iw_statistics *lbs_get_wireless_stats(struct net_device *dev) -{ - enum { - POOR = 30, - FAIR = 60, - GOOD = 80, - VERY_GOOD = 90, - EXCELLENT = 95, - PERFECT = 100 - }; - struct lbs_private *priv = dev->ml_priv; - u32 rssi_qual; - u32 tx_qual; - u32 quality = 0; - int stats_valid = 0; - u8 rssi; - u32 tx_retries; - struct cmd_ds_802_11_get_log log; - - lbs_deb_enter(LBS_DEB_WEXT); - - priv->wstats.status = priv->mode; - - /* If we're not associated, all quality values are meaningless */ - if ((priv->connect_status != LBS_CONNECTED) && - (priv->mesh_connect_status != LBS_CONNECTED)) - goto out; - - /* Quality by RSSI */ - priv->wstats.qual.level = - CAL_RSSI(priv->SNR[TYPE_BEACON][TYPE_NOAVG], - priv->NF[TYPE_BEACON][TYPE_NOAVG]); - - if (priv->NF[TYPE_BEACON][TYPE_NOAVG] == 0) { - priv->wstats.qual.noise = MRVDRV_NF_DEFAULT_SCAN_VALUE; - } else { - priv->wstats.qual.noise = - CAL_NF(priv->NF[TYPE_BEACON][TYPE_NOAVG]); - } - - lbs_deb_wext("signal level %#x\n", priv->wstats.qual.level); - lbs_deb_wext("noise %#x\n", priv->wstats.qual.noise); - - rssi = priv->wstats.qual.level - priv->wstats.qual.noise; - if (rssi < 15) - rssi_qual = rssi * POOR / 10; - else if (rssi < 20) - rssi_qual = (rssi - 15) * (FAIR - POOR) / 5 + POOR; - else if (rssi < 30) - rssi_qual = (rssi - 20) * (GOOD - FAIR) / 5 + FAIR; - else if (rssi < 40) - rssi_qual = (rssi - 30) * (VERY_GOOD - GOOD) / - 10 + GOOD; - else - rssi_qual = (rssi - 40) * (PERFECT - VERY_GOOD) / - 10 + VERY_GOOD; - quality = rssi_qual; - - /* Quality by TX errors */ - priv->wstats.discard.retries = dev->stats.tx_errors; - - memset(&log, 0, sizeof(log)); - log.hdr.size = cpu_to_le16(sizeof(log)); - lbs_cmd_with_response(priv, CMD_802_11_GET_LOG, &log); - - tx_retries = le32_to_cpu(log.retry); - - if (tx_retries > 75) - tx_qual = (90 - tx_retries) * POOR / 15; - else if (tx_retries > 70) - tx_qual = (75 - tx_retries) * (FAIR - POOR) / 5 + POOR; - else if (tx_retries > 65) - tx_qual = (70 - tx_retries) * (GOOD - FAIR) / 5 + FAIR; - else if (tx_retries > 50) - tx_qual = (65 - tx_retries) * (VERY_GOOD - GOOD) / - 15 + GOOD; - else - tx_qual = (50 - tx_retries) * - (PERFECT - VERY_GOOD) / 50 + VERY_GOOD; - quality = min(quality, tx_qual); - - priv->wstats.discard.code = le32_to_cpu(log.wepundecryptable); - priv->wstats.discard.retries = tx_retries; - priv->wstats.discard.misc = le32_to_cpu(log.ackfailure); - - /* Calculate quality */ - priv->wstats.qual.qual = min_t(u8, quality, 100); - priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - stats_valid = 1; - - /* update stats asynchronously for future calls */ - lbs_prepare_and_send_command(priv, CMD_802_11_RSSI, 0, - 0, 0, NULL); -out: - if (!stats_valid) { - priv->wstats.miss.beacon = 0; - priv->wstats.discard.retries = 0; - priv->wstats.qual.qual = 0; - priv->wstats.qual.level = 0; - priv->wstats.qual.noise = 0; - priv->wstats.qual.updated = IW_QUAL_ALL_UPDATED; - priv->wstats.qual.updated |= IW_QUAL_NOISE_INVALID | - IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_INVALID; - } - - lbs_deb_leave(LBS_DEB_WEXT); - return &priv->wstats; - - -} - -static int lbs_set_freq(struct net_device *dev, struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - int ret = -EINVAL; - struct lbs_private *priv = dev->ml_priv; - struct chan_freq_power *cfp; - struct assoc_request * assoc_req; - - lbs_deb_enter(LBS_DEB_WEXT); - - mutex_lock(&priv->lock); - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - goto out; - } - - /* If setting by frequency, convert to a channel */ - if (fwrq->e == 1) { - long f = fwrq->m / 100000; - - cfp = find_cfp_by_band_and_freq(priv, 0, f); - if (!cfp) { - lbs_deb_wext("invalid freq %ld\n", f); - goto out; - } - - fwrq->e = 0; - fwrq->m = (int) cfp->channel; - } - - /* Setting by channel number */ - if (fwrq->m > 1000 || fwrq->e > 0) { - goto out; - } - - cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m); - if (!cfp) { - goto out; - } - - assoc_req->channel = fwrq->m; - ret = 0; - -out: - if (ret == 0) { - set_bit(ASSOC_FLAG_CHANNEL, &assoc_req->flags); - lbs_postpone_association_work(priv); - } else { - lbs_cancel_association_work(priv); - } - mutex_unlock(&priv->lock); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_mesh_set_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - struct chan_freq_power *cfp; - int ret = -EINVAL; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* If setting by frequency, convert to a channel */ - if (fwrq->e == 1) { - long f = fwrq->m / 100000; - - cfp = find_cfp_by_band_and_freq(priv, 0, f); - if (!cfp) { - lbs_deb_wext("invalid freq %ld\n", f); - goto out; - } - - fwrq->e = 0; - fwrq->m = (int) cfp->channel; - } - - /* Setting by channel number */ - if (fwrq->m > 1000 || fwrq->e > 0) { - goto out; - } - - cfp = lbs_find_cfp_by_band_and_channel(priv, 0, fwrq->m); - if (!cfp) { - goto out; - } - - if (fwrq->m != priv->curbssparams.channel) { - lbs_deb_wext("mesh channel change forces eth disconnect\n"); - if (priv->mode == IW_MODE_INFRA) - lbs_cmd_80211_deauthenticate(priv, - priv->curbssparams.bssid, - WLAN_REASON_DEAUTH_LEAVING); - else if (priv->mode == IW_MODE_ADHOC) - lbs_adhoc_stop(priv); - } - lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, fwrq->m); - lbs_update_channel(priv); - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_set_rate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - u8 new_rate = 0; - int ret = -EINVAL; - u8 rates[MAX_RATES + 1]; - - lbs_deb_enter(LBS_DEB_WEXT); - lbs_deb_wext("vwrq->value %d\n", vwrq->value); - lbs_deb_wext("vwrq->fixed %d\n", vwrq->fixed); - - if (vwrq->fixed && vwrq->value == -1) - goto out; - - /* Auto rate? */ - priv->enablehwauto = !vwrq->fixed; - - if (vwrq->value == -1) - priv->cur_rate = 0; - else { - if (vwrq->value % 100000) - goto out; - - new_rate = vwrq->value / 500000; - priv->cur_rate = new_rate; - /* the rest is only needed for lbs_set_data_rate() */ - memset(rates, 0, sizeof(rates)); - copy_active_data_rates(priv, rates); - if (!memchr(rates, new_rate, sizeof(rates))) { - lbs_pr_alert("fixed data rate 0x%X out of range\n", - new_rate); - goto out; - } - if (priv->fwrelease < 0x09000000) { - ret = lbs_set_power_adapt_cfg(priv, 0, - POW_ADAPT_DEFAULT_P0, - POW_ADAPT_DEFAULT_P1, - POW_ADAPT_DEFAULT_P2); - if (ret) - goto out; - } - ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, - TPC_DEFAULT_P2, 1); - if (ret) - goto out; - } - - /* Try the newer command first (Firmware Spec 5.1 and above) */ - ret = lbs_cmd_802_11_rate_adapt_rateset(priv, CMD_ACT_SET); - - /* Fallback to older version */ - if (ret) - ret = lbs_set_data_rate(priv, new_rate); - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_rate(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (priv->connect_status == LBS_CONNECTED) { - vwrq->value = priv->cur_rate * 500000; - - if (priv->enablehwauto) - vwrq->fixed = 0; - else - vwrq->fixed = 1; - - } else { - vwrq->fixed = 0; - vwrq->value = 0; - } - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_set_mode(struct net_device *dev, - struct iw_request_info *info, u32 * uwrq, char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - struct assoc_request * assoc_req; - - lbs_deb_enter(LBS_DEB_WEXT); - - if ( (*uwrq != IW_MODE_ADHOC) - && (*uwrq != IW_MODE_INFRA) - && (*uwrq != IW_MODE_AUTO)) { - lbs_deb_wext("Invalid mode: 0x%x\n", *uwrq); - ret = -EINVAL; - goto out; - } - - mutex_lock(&priv->lock); - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - lbs_cancel_association_work(priv); - } else { - assoc_req->mode = *uwrq; - set_bit(ASSOC_FLAG_MODE, &assoc_req->flags); - lbs_postpone_association_work(priv); - lbs_deb_wext("Switching to mode: 0x%x\n", *uwrq); - } - mutex_unlock(&priv->lock); - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - - -/** - * @brief Get Encryption key - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param vwrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * @return 0 --success, otherwise fail - */ -static int lbs_get_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, u8 * extra) -{ - struct lbs_private *priv = dev->ml_priv; - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - - lbs_deb_enter(LBS_DEB_WEXT); - - lbs_deb_wext("flags 0x%x, index %d, length %d, wep_tx_keyidx %d\n", - dwrq->flags, index, dwrq->length, priv->wep_tx_keyidx); - - dwrq->flags = 0; - - /* Authentication method */ - switch (priv->secinfo.auth_mode) { - case IW_AUTH_ALG_OPEN_SYSTEM: - dwrq->flags = IW_ENCODE_OPEN; - break; - - case IW_AUTH_ALG_SHARED_KEY: - case IW_AUTH_ALG_LEAP: - dwrq->flags = IW_ENCODE_RESTRICTED; - break; - default: - dwrq->flags = IW_ENCODE_DISABLED | IW_ENCODE_OPEN; - break; - } - - memset(extra, 0, 16); - - mutex_lock(&priv->lock); - - /* Default to returning current transmit key */ - if (index < 0) - index = priv->wep_tx_keyidx; - - if ((priv->wep_keys[index].len) && priv->secinfo.wep_enabled) { - memcpy(extra, priv->wep_keys[index].key, - priv->wep_keys[index].len); - dwrq->length = priv->wep_keys[index].len; - - dwrq->flags |= (index + 1); - /* Return WEP enabled */ - dwrq->flags &= ~IW_ENCODE_DISABLED; - } else if ((priv->secinfo.WPAenabled) - || (priv->secinfo.WPA2enabled)) { - /* return WPA enabled */ - dwrq->flags &= ~IW_ENCODE_DISABLED; - dwrq->flags |= IW_ENCODE_NOKEY; - } else { - dwrq->flags |= IW_ENCODE_DISABLED; - } - - mutex_unlock(&priv->lock); - - lbs_deb_wext("key: %02x:%02x:%02x:%02x:%02x:%02x, keylen %d\n", - extra[0], extra[1], extra[2], - extra[3], extra[4], extra[5], dwrq->length); - - lbs_deb_wext("return flags 0x%x\n", dwrq->flags); - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -/** - * @brief Set Encryption key (internal) - * - * @param priv A pointer to private card structure - * @param key_material A pointer to key material - * @param key_length length of key material - * @param index key index to set - * @param set_tx_key Force set TX key (1 = yes, 0 = no) - * @return 0 --success, otherwise fail - */ -static int lbs_set_wep_key(struct assoc_request *assoc_req, - const char *key_material, - u16 key_length, - u16 index, - int set_tx_key) -{ - int ret = 0; - struct enc_key *pkey; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* Paranoid validation of key index */ - if (index > 3) { - ret = -EINVAL; - goto out; - } - - /* validate max key length */ - if (key_length > KEY_LEN_WEP_104) { - ret = -EINVAL; - goto out; - } - - pkey = &assoc_req->wep_keys[index]; - - if (key_length > 0) { - memset(pkey, 0, sizeof(struct enc_key)); - pkey->type = KEY_TYPE_ID_WEP; - - /* Standardize the key length */ - pkey->len = (key_length > KEY_LEN_WEP_40) ? - KEY_LEN_WEP_104 : KEY_LEN_WEP_40; - memcpy(pkey->key, key_material, key_length); - } - - if (set_tx_key) { - /* Ensure the chosen key is valid */ - if (!pkey->len) { - lbs_deb_wext("key not set, so cannot enable it\n"); - ret = -EINVAL; - goto out; - } - assoc_req->wep_tx_keyidx = index; - } - - assoc_req->secinfo.wep_enabled = 1; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int validate_key_index(u16 def_index, u16 raw_index, - u16 *out_index, u16 *is_default) -{ - if (!out_index || !is_default) - return -EINVAL; - - /* Verify index if present, otherwise use default TX key index */ - if (raw_index > 0) { - if (raw_index > 4) - return -EINVAL; - *out_index = raw_index - 1; - } else { - *out_index = def_index; - *is_default = 1; - } - return 0; -} - -static void disable_wep(struct assoc_request *assoc_req) -{ - int i; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* Set Open System auth mode */ - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - - /* Clear WEP keys and mark WEP as disabled */ - assoc_req->secinfo.wep_enabled = 0; - for (i = 0; i < 4; i++) - assoc_req->wep_keys[i].len = 0; - - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); - set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); - - lbs_deb_leave(LBS_DEB_WEXT); -} - -static void disable_wpa(struct assoc_request *assoc_req) -{ - lbs_deb_enter(LBS_DEB_WEXT); - - memset(&assoc_req->wpa_mcast_key, 0, sizeof (struct enc_key)); - assoc_req->wpa_mcast_key.flags = KEY_INFO_WPA_MCAST; - set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - - memset(&assoc_req->wpa_unicast_key, 0, sizeof (struct enc_key)); - assoc_req->wpa_unicast_key.flags = KEY_INFO_WPA_UNICAST; - set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - - assoc_req->secinfo.WPAenabled = 0; - assoc_req->secinfo.WPA2enabled = 0; - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); - - lbs_deb_leave(LBS_DEB_WEXT); -} - -/** - * @brief Set Encryption key - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param vwrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * @return 0 --success, otherwise fail - */ -static int lbs_set_encode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - struct assoc_request * assoc_req; - u16 is_default = 0, index = 0, set_tx_key = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - mutex_lock(&priv->lock); - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - goto out; - } - - if (dwrq->flags & IW_ENCODE_DISABLED) { - disable_wep (assoc_req); - disable_wpa (assoc_req); - goto out; - } - - ret = validate_key_index(assoc_req->wep_tx_keyidx, - (dwrq->flags & IW_ENCODE_INDEX), - &index, &is_default); - if (ret) { - ret = -EINVAL; - goto out; - } - - /* If WEP isn't enabled, or if there is no key data but a valid - * index, set the TX key. - */ - if (!assoc_req->secinfo.wep_enabled || (dwrq->length == 0 && !is_default)) - set_tx_key = 1; - - ret = lbs_set_wep_key(assoc_req, extra, dwrq->length, index, set_tx_key); - if (ret) - goto out; - - if (dwrq->length) - set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); - if (set_tx_key) - set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); - - if (dwrq->flags & IW_ENCODE_RESTRICTED) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; - } else if (dwrq->flags & IW_ENCODE_OPEN) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - } - -out: - if (ret == 0) { - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); - lbs_postpone_association_work(priv); - } else { - lbs_cancel_association_work(priv); - } - mutex_unlock(&priv->lock); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -/** - * @brief Get Extended Encryption key (WPA/802.1x and WEP) - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param vwrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * @return 0 on success, otherwise failure - */ -static int lbs_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - int ret = -EINVAL; - struct lbs_private *priv = dev->ml_priv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int index, max_key_len; - - lbs_deb_enter(LBS_DEB_WEXT); - - max_key_len = dwrq->length - sizeof(*ext); - if (max_key_len < 0) - goto out; - - index = dwrq->flags & IW_ENCODE_INDEX; - if (index) { - if (index < 1 || index > 4) - goto out; - index--; - } else { - index = priv->wep_tx_keyidx; - } - - if (!(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) && - ext->alg != IW_ENCODE_ALG_WEP) { - if (index != 0 || priv->mode != IW_MODE_INFRA) - goto out; - } - - dwrq->flags = index + 1; - memset(ext, 0, sizeof(*ext)); - - if ( !priv->secinfo.wep_enabled - && !priv->secinfo.WPAenabled - && !priv->secinfo.WPA2enabled) { - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - dwrq->flags |= IW_ENCODE_DISABLED; - } else { - u8 *key = NULL; - - if ( priv->secinfo.wep_enabled - && !priv->secinfo.WPAenabled - && !priv->secinfo.WPA2enabled) { - /* WEP */ - ext->alg = IW_ENCODE_ALG_WEP; - ext->key_len = priv->wep_keys[index].len; - key = &priv->wep_keys[index].key[0]; - } else if ( !priv->secinfo.wep_enabled - && (priv->secinfo.WPAenabled || - priv->secinfo.WPA2enabled)) { - /* WPA */ - struct enc_key * pkey = NULL; - - if ( priv->wpa_mcast_key.len - && (priv->wpa_mcast_key.flags & KEY_INFO_WPA_ENABLED)) - pkey = &priv->wpa_mcast_key; - else if ( priv->wpa_unicast_key.len - && (priv->wpa_unicast_key.flags & KEY_INFO_WPA_ENABLED)) - pkey = &priv->wpa_unicast_key; - - if (pkey) { - if (pkey->type == KEY_TYPE_ID_AES) { - ext->alg = IW_ENCODE_ALG_CCMP; - } else { - ext->alg = IW_ENCODE_ALG_TKIP; - } - ext->key_len = pkey->len; - key = &pkey->key[0]; - } else { - ext->alg = IW_ENCODE_ALG_TKIP; - ext->key_len = 0; - } - } else { - goto out; - } - - if (ext->key_len > max_key_len) { - ret = -E2BIG; - goto out; - } - - if (ext->key_len) - memcpy(ext->key, key, ext->key_len); - else - dwrq->flags |= IW_ENCODE_NOKEY; - dwrq->flags |= IW_ENCODE_ENABLED; - } - ret = 0; - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -/** - * @brief Set Encryption key Extended (WPA/802.1x and WEP) - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param vwrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * @return 0 --success, otherwise fail - */ -static int lbs_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int alg = ext->alg; - struct assoc_request * assoc_req; - - lbs_deb_enter(LBS_DEB_WEXT); - - mutex_lock(&priv->lock); - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - goto out; - } - - if ((alg == IW_ENCODE_ALG_NONE) || (dwrq->flags & IW_ENCODE_DISABLED)) { - disable_wep (assoc_req); - disable_wpa (assoc_req); - } else if (alg == IW_ENCODE_ALG_WEP) { - u16 is_default = 0, index, set_tx_key = 0; - - ret = validate_key_index(assoc_req->wep_tx_keyidx, - (dwrq->flags & IW_ENCODE_INDEX), - &index, &is_default); - if (ret) - goto out; - - /* If WEP isn't enabled, or if there is no key data but a valid - * index, or if the set-TX-key flag was passed, set the TX key. - */ - if ( !assoc_req->secinfo.wep_enabled - || (dwrq->length == 0 && !is_default) - || (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)) - set_tx_key = 1; - - /* Copy key to driver */ - ret = lbs_set_wep_key(assoc_req, ext->key, ext->key_len, index, - set_tx_key); - if (ret) - goto out; - - if (dwrq->flags & IW_ENCODE_RESTRICTED) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; - } else if (dwrq->flags & IW_ENCODE_OPEN) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - } - - /* Mark the various WEP bits as modified */ - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); - if (dwrq->length) - set_bit(ASSOC_FLAG_WEP_KEYS, &assoc_req->flags); - if (set_tx_key) - set_bit(ASSOC_FLAG_WEP_TX_KEYIDX, &assoc_req->flags); - } else if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) { - struct enc_key * pkey; - - /* validate key length */ - if (((alg == IW_ENCODE_ALG_TKIP) - && (ext->key_len != KEY_LEN_WPA_TKIP)) - || ((alg == IW_ENCODE_ALG_CCMP) - && (ext->key_len != KEY_LEN_WPA_AES))) { - lbs_deb_wext("invalid size %d for key of alg " - "type %d\n", - ext->key_len, - alg); - ret = -EINVAL; - goto out; - } - - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - pkey = &assoc_req->wpa_mcast_key; - set_bit(ASSOC_FLAG_WPA_MCAST_KEY, &assoc_req->flags); - } else { - pkey = &assoc_req->wpa_unicast_key; - set_bit(ASSOC_FLAG_WPA_UCAST_KEY, &assoc_req->flags); - } - - memset(pkey, 0, sizeof (struct enc_key)); - memcpy(pkey->key, ext->key, ext->key_len); - pkey->len = ext->key_len; - if (pkey->len) - pkey->flags |= KEY_INFO_WPA_ENABLED; - - /* Do this after zeroing key structure */ - if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) { - pkey->flags |= KEY_INFO_WPA_MCAST; - } else { - pkey->flags |= KEY_INFO_WPA_UNICAST; - } - - if (alg == IW_ENCODE_ALG_TKIP) { - pkey->type = KEY_TYPE_ID_TKIP; - } else if (alg == IW_ENCODE_ALG_CCMP) { - pkey->type = KEY_TYPE_ID_AES; - } - - /* If WPA isn't enabled yet, do that now */ - if ( assoc_req->secinfo.WPAenabled == 0 - && assoc_req->secinfo.WPA2enabled == 0) { - assoc_req->secinfo.WPAenabled = 1; - assoc_req->secinfo.WPA2enabled = 1; - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); - } - - /* Only disable wep if necessary: can't waste time here. */ - if (priv->mac_control & CMD_ACT_MAC_WEP_ENABLE) - disable_wep(assoc_req); - } - -out: - if (ret == 0) { - /* 802.1x and WPA rekeying must happen as quickly as possible, - * especially during the 4-way handshake; thus if in - * infrastructure mode, and either (a) 802.1x is enabled or - * (b) WPA is being used, set the key right away. - */ - if (assoc_req->mode == IW_MODE_INFRA && - ((assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_802_1X) || - (assoc_req->secinfo.key_mgmt & IW_AUTH_KEY_MGMT_PSK) || - assoc_req->secinfo.WPAenabled || - assoc_req->secinfo.WPA2enabled)) { - lbs_do_association_work(priv); - } else - lbs_postpone_association_work(priv); - } else { - lbs_cancel_association_work(priv); - } - mutex_unlock(&priv->lock); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - - -static int lbs_set_genie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - struct assoc_request * assoc_req; - - lbs_deb_enter(LBS_DEB_WEXT); - - mutex_lock(&priv->lock); - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - goto out; - } - - if (dwrq->length > MAX_WPA_IE_LEN || - (dwrq->length && extra == NULL)) { - ret = -EINVAL; - goto out; - } - - if (dwrq->length) { - memcpy(&assoc_req->wpa_ie[0], extra, dwrq->length); - assoc_req->wpa_ie_len = dwrq->length; - } else { - memset(&assoc_req->wpa_ie[0], 0, sizeof(priv->wpa_ie)); - assoc_req->wpa_ie_len = 0; - } - -out: - if (ret == 0) { - set_bit(ASSOC_FLAG_WPA_IE, &assoc_req->flags); - lbs_postpone_association_work(priv); - } else { - lbs_cancel_association_work(priv); - } - mutex_unlock(&priv->lock); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_genie(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, - char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (priv->wpa_ie_len == 0) { - dwrq->length = 0; - goto out; - } - - if (dwrq->length < priv->wpa_ie_len) { - ret = -E2BIG; - goto out; - } - - dwrq->length = priv->wpa_ie_len; - memcpy(extra, &priv->wpa_ie[0], priv->wpa_ie_len); - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - - -static int lbs_set_auth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *dwrq, - char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - struct assoc_request * assoc_req; - int ret = 0; - int updated = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - mutex_lock(&priv->lock); - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - goto out; - } - - switch (dwrq->flags & IW_AUTH_INDEX) { - case IW_AUTH_PRIVACY_INVOKED: - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - case IW_AUTH_TKIP_COUNTERMEASURES: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_DROP_UNENCRYPTED: - /* - * libertas does not use these parameters - */ - break; - - case IW_AUTH_KEY_MGMT: - assoc_req->secinfo.key_mgmt = dwrq->value; - updated = 1; - break; - - case IW_AUTH_WPA_VERSION: - if (dwrq->value & IW_AUTH_WPA_VERSION_DISABLED) { - assoc_req->secinfo.WPAenabled = 0; - assoc_req->secinfo.WPA2enabled = 0; - disable_wpa (assoc_req); - } - if (dwrq->value & IW_AUTH_WPA_VERSION_WPA) { - assoc_req->secinfo.WPAenabled = 1; - assoc_req->secinfo.wep_enabled = 0; - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - } - if (dwrq->value & IW_AUTH_WPA_VERSION_WPA2) { - assoc_req->secinfo.WPA2enabled = 1; - assoc_req->secinfo.wep_enabled = 0; - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - } - updated = 1; - break; - - case IW_AUTH_80211_AUTH_ALG: - if (dwrq->value & IW_AUTH_ALG_SHARED_KEY) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_SHARED_KEY; - } else if (dwrq->value & IW_AUTH_ALG_OPEN_SYSTEM) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - } else if (dwrq->value & IW_AUTH_ALG_LEAP) { - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_LEAP; - } else { - ret = -EINVAL; - } - updated = 1; - break; - - case IW_AUTH_WPA_ENABLED: - if (dwrq->value) { - if (!assoc_req->secinfo.WPAenabled && - !assoc_req->secinfo.WPA2enabled) { - assoc_req->secinfo.WPAenabled = 1; - assoc_req->secinfo.WPA2enabled = 1; - assoc_req->secinfo.wep_enabled = 0; - assoc_req->secinfo.auth_mode = IW_AUTH_ALG_OPEN_SYSTEM; - } - } else { - assoc_req->secinfo.WPAenabled = 0; - assoc_req->secinfo.WPA2enabled = 0; - disable_wpa (assoc_req); - } - updated = 1; - break; - - default: - ret = -EOPNOTSUPP; - break; - } - -out: - if (ret == 0) { - if (updated) - set_bit(ASSOC_FLAG_SECINFO, &assoc_req->flags); - lbs_postpone_association_work(priv); - } else if (ret != -EOPNOTSUPP) { - lbs_cancel_association_work(priv); - } - mutex_unlock(&priv->lock); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_auth(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *dwrq, - char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - switch (dwrq->flags & IW_AUTH_INDEX) { - case IW_AUTH_KEY_MGMT: - dwrq->value = priv->secinfo.key_mgmt; - break; - - case IW_AUTH_WPA_VERSION: - dwrq->value = 0; - if (priv->secinfo.WPAenabled) - dwrq->value |= IW_AUTH_WPA_VERSION_WPA; - if (priv->secinfo.WPA2enabled) - dwrq->value |= IW_AUTH_WPA_VERSION_WPA2; - if (!dwrq->value) - dwrq->value |= IW_AUTH_WPA_VERSION_DISABLED; - break; - - case IW_AUTH_80211_AUTH_ALG: - dwrq->value = priv->secinfo.auth_mode; - break; - - case IW_AUTH_WPA_ENABLED: - if (priv->secinfo.WPAenabled && priv->secinfo.WPA2enabled) - dwrq->value = 1; - break; - - default: - ret = -EOPNOTSUPP; - } - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - - -static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - int ret = 0; - struct lbs_private *priv = dev->ml_priv; - s16 dbm = (s16) vwrq->value; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (vwrq->disabled) { - lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 0); - goto out; - } - - if (vwrq->fixed == 0) { - /* User requests automatic tx power control, however there are - * many auto tx settings. For now use firmware defaults until - * we come up with a good way to expose these to the user. */ - if (priv->fwrelease < 0x09000000) { - ret = lbs_set_power_adapt_cfg(priv, 1, - POW_ADAPT_DEFAULT_P0, - POW_ADAPT_DEFAULT_P1, - POW_ADAPT_DEFAULT_P2); - if (ret) - goto out; - } - ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, - TPC_DEFAULT_P2, 1); - if (ret) - goto out; - dbm = priv->txpower_max; - } else { - /* Userspace check in iwrange if it should use dBm or mW, - * therefore this should never happen... Jean II */ - if ((vwrq->flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { - ret = -EOPNOTSUPP; - goto out; - } - - /* Validate requested power level against firmware allowed - * levels */ - if (priv->txpower_min && (dbm < priv->txpower_min)) { - ret = -EINVAL; - goto out; - } - - if (priv->txpower_max && (dbm > priv->txpower_max)) { - ret = -EINVAL; - goto out; - } - if (priv->fwrelease < 0x09000000) { - ret = lbs_set_power_adapt_cfg(priv, 0, - POW_ADAPT_DEFAULT_P0, - POW_ADAPT_DEFAULT_P1, - POW_ADAPT_DEFAULT_P2); - if (ret) - goto out; - } - ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1, - TPC_DEFAULT_P2, 1); - if (ret) - goto out; - } - - /* If the radio was off, turn it on */ - if (!priv->radio_on) { - ret = lbs_set_radio(priv, RADIO_PREAMBLE_AUTO, 1); - if (ret) - goto out; - } - - lbs_deb_wext("txpower set %d dBm\n", dbm); - - ret = lbs_set_tx_power(priv, dbm); - -out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_get_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - /* - * Note : if dwrq->flags != 0, we should get the relevant SSID from - * the SSID list... - */ - - /* - * Get the current SSID - */ - if (priv->connect_status == LBS_CONNECTED) { - memcpy(extra, priv->curbssparams.ssid, - priv->curbssparams.ssid_len); - } else { - memset(extra, 0, 32); - } - /* - * If none, we may want to get the one that was set - */ - - dwrq->length = priv->curbssparams.ssid_len; - - dwrq->flags = 1; /* active */ - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_set_essid(struct net_device *dev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - u8 ssid[IW_ESSID_MAX_SIZE]; - u8 ssid_len = 0; - struct assoc_request * assoc_req; - int in_ssid_len = dwrq->length; - DECLARE_SSID_BUF(ssid_buf); - - lbs_deb_enter(LBS_DEB_WEXT); - - if (!priv->radio_on) { - ret = -EINVAL; - goto out; - } - - /* Check the size of the string */ - if (in_ssid_len > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - goto out; - } - - memset(&ssid, 0, sizeof(ssid)); - - if (!dwrq->flags || !in_ssid_len) { - /* "any" SSID requested; leave SSID blank */ - } else { - /* Specific SSID requested */ - memcpy(&ssid, extra, in_ssid_len); - ssid_len = in_ssid_len; - } - - if (!ssid_len) { - lbs_deb_wext("requested any SSID\n"); - } else { - lbs_deb_wext("requested SSID '%s'\n", - print_ssid(ssid_buf, ssid, ssid_len)); - } - -out: - mutex_lock(&priv->lock); - if (ret == 0) { - /* Get or create the current association request */ - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - ret = -ENOMEM; - } else { - /* Copy the SSID to the association request */ - memcpy(&assoc_req->ssid, &ssid, IW_ESSID_MAX_SIZE); - assoc_req->ssid_len = ssid_len; - set_bit(ASSOC_FLAG_SSID, &assoc_req->flags); - lbs_postpone_association_work(priv); - } - } - - /* Cancel the association request if there was an error */ - if (ret != 0) { - lbs_cancel_association_work(priv); - } - - mutex_unlock(&priv->lock); - - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -static int lbs_mesh_get_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - - lbs_deb_enter(LBS_DEB_WEXT); - - memcpy(extra, priv->mesh_ssid, priv->mesh_ssid_len); - - dwrq->length = priv->mesh_ssid_len; - - dwrq->flags = 1; /* active */ - - lbs_deb_leave(LBS_DEB_WEXT); - return 0; -} - -static int lbs_mesh_set_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - int ret = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (!priv->radio_on) { - ret = -EINVAL; - goto out; - } - - /* Check the size of the string */ - if (dwrq->length > IW_ESSID_MAX_SIZE) { - ret = -E2BIG; - goto out; - } - - if (!dwrq->flags || !dwrq->length) { - ret = -EINVAL; - goto out; - } else { - /* Specific SSID requested */ - memcpy(priv->mesh_ssid, extra, dwrq->length); - priv->mesh_ssid_len = dwrq->length; - } - - lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, - priv->curbssparams.channel); - out: - lbs_deb_leave_args(LBS_DEB_WEXT, "ret %d", ret); - return ret; -} - -/** - * @brief Connect to the AP or Ad-hoc Network with specific bssid - * - * @param dev A pointer to net_device structure - * @param info A pointer to iw_request_info structure - * @param awrq A pointer to iw_param structure - * @param extra A pointer to extra data buf - * @return 0 --success, otherwise fail - */ -static int lbs_set_wap(struct net_device *dev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - struct lbs_private *priv = dev->ml_priv; - struct assoc_request * assoc_req; - int ret = 0; - - lbs_deb_enter(LBS_DEB_WEXT); - - if (!priv->radio_on) - return -EINVAL; - - if (awrq->sa_family != ARPHRD_ETHER) - return -EINVAL; - - lbs_deb_wext("ASSOC: WAP: sa_data %pM\n", awrq->sa_data); - - mutex_lock(&priv->lock); - - /* Get or create the current association request */ - assoc_req = lbs_get_association_request(priv); - if (!assoc_req) { - lbs_cancel_association_work(priv); - ret = -ENOMEM; - } else { - /* Copy the BSSID to the association request */ - memcpy(&assoc_req->bssid, awrq->sa_data, ETH_ALEN); - set_bit(ASSOC_FLAG_BSSID, &assoc_req->flags); - lbs_postpone_association_work(priv); - } - - mutex_unlock(&priv->lock); - - return ret; -} - -/* - * iwconfig settable callbacks - */ -static const iw_handler lbs_handler[] = { - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) lbs_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) lbs_set_freq, /* SIOCSIWFREQ */ - (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */ - (iw_handler) lbs_set_mode, /* SIOCSIWMODE */ - (iw_handler) lbs_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) lbs_get_sense, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) lbs_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) lbs_set_wap, /* SIOCSIWAP */ - (iw_handler) lbs_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* SIOCSIWMLME */ - (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ - (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */ - (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */ - (iw_handler) lbs_set_essid, /* SIOCSIWESSID */ - (iw_handler) lbs_get_essid, /* SIOCGIWESSID */ - (iw_handler) lbs_set_nick, /* SIOCSIWNICKN */ - (iw_handler) lbs_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) lbs_set_rate, /* SIOCSIWRATE */ - (iw_handler) lbs_get_rate, /* SIOCGIWRATE */ - (iw_handler) lbs_set_rts, /* SIOCSIWRTS */ - (iw_handler) lbs_get_rts, /* SIOCGIWRTS */ - (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */ - (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */ - (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */ - (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */ - (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */ - (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */ - (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */ - (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */ - (iw_handler) lbs_set_power, /* SIOCSIWPOWER */ - (iw_handler) lbs_get_power, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */ - (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */ - (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */ - (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */ - (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */ - (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; - -static const iw_handler mesh_wlan_handler[] = { - (iw_handler) NULL, /* SIOCSIWCOMMIT */ - (iw_handler) lbs_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) lbs_mesh_set_freq, /* SIOCSIWFREQ */ - (iw_handler) lbs_get_freq, /* SIOCGIWFREQ */ - (iw_handler) NULL, /* SIOCSIWMODE */ - (iw_handler) mesh_wlan_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) lbs_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) NULL, /* SIOCSIWAP */ - (iw_handler) NULL, /* SIOCGIWAP */ - (iw_handler) NULL, /* SIOCSIWMLME */ - (iw_handler) NULL, /* SIOCGIWAPLIST - deprecated */ - (iw_handler) lbs_set_scan, /* SIOCSIWSCAN */ - (iw_handler) lbs_get_scan, /* SIOCGIWSCAN */ - (iw_handler) lbs_mesh_set_essid,/* SIOCSIWESSID */ - (iw_handler) lbs_mesh_get_essid,/* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) mesh_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) lbs_set_rate, /* SIOCSIWRATE */ - (iw_handler) lbs_get_rate, /* SIOCGIWRATE */ - (iw_handler) lbs_set_rts, /* SIOCSIWRTS */ - (iw_handler) lbs_get_rts, /* SIOCGIWRTS */ - (iw_handler) lbs_set_frag, /* SIOCSIWFRAG */ - (iw_handler) lbs_get_frag, /* SIOCGIWFRAG */ - (iw_handler) lbs_set_txpow, /* SIOCSIWTXPOW */ - (iw_handler) lbs_get_txpow, /* SIOCGIWTXPOW */ - (iw_handler) lbs_set_retry, /* SIOCSIWRETRY */ - (iw_handler) lbs_get_retry, /* SIOCGIWRETRY */ - (iw_handler) lbs_set_encode, /* SIOCSIWENCODE */ - (iw_handler) lbs_get_encode, /* SIOCGIWENCODE */ - (iw_handler) lbs_set_power, /* SIOCSIWPOWER */ - (iw_handler) lbs_get_power, /* SIOCGIWPOWER */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) lbs_set_genie, /* SIOCSIWGENIE */ - (iw_handler) lbs_get_genie, /* SIOCGIWGENIE */ - (iw_handler) lbs_set_auth, /* SIOCSIWAUTH */ - (iw_handler) lbs_get_auth, /* SIOCGIWAUTH */ - (iw_handler) lbs_set_encodeext,/* SIOCSIWENCODEEXT */ - (iw_handler) lbs_get_encodeext,/* SIOCGIWENCODEEXT */ - (iw_handler) NULL, /* SIOCSIWPMKSA */ -}; -struct iw_handler_def lbs_handler_def = { - .num_standard = ARRAY_SIZE(lbs_handler), - .standard = (iw_handler *) lbs_handler, - .get_wireless_stats = lbs_get_wireless_stats, -}; - -struct iw_handler_def mesh_handler_def = { - .num_standard = ARRAY_SIZE(mesh_wlan_handler), - .standard = (iw_handler *) mesh_wlan_handler, - .get_wireless_stats = lbs_get_wireless_stats, -}; diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h deleted file mode 100644 index 4c08db497606..000000000000 --- a/drivers/net/wireless/libertas/wext.h +++ /dev/null @@ -1,10 +0,0 @@ -/** - * This file contains definition for IOCTL call. - */ -#ifndef _LBS_WEXT_H_ -#define _LBS_WEXT_H_ - -extern struct iw_handler_def lbs_handler_def; -extern struct iw_handler_def mesh_handler_def; - -#endif diff --git a/drivers/net/wireless/libertas/wifi_power.c b/drivers/net/wireless/libertas/wifi_power.c deleted file mode 100644 index e56fbacbf9cd..000000000000 --- a/drivers/net/wireless/libertas/wifi_power.c +++ /dev/null @@ -1,110 +0,0 @@ -/* - * wifi_power.c - * - * Power control for WIFI module. - * - * There are Power supply and Power Up/Down controls for WIFI typically. - */ -#include -#include -#include - -#include "wifi_power.h" -#if (WIFI_GPIO_POWER_CONTROL == 1) -struct wifi_power power_gpio = -{ - POWER_USE_GPIO, POWER_GPIO_IOMUX, GPIOH7_HSADCCLK_SEL_NAME, - IOMUXB_GPIO1_D7, RK2818_PIN_PH7, GPIO_HIGH - -}; - -struct wifi_power power_save_gpio = -{ - 0, 0, 0, 0, 0, 0 -}; - -int wifi_gpio_operate(struct wifi_power *gpio, int flag) -{ - int sensitive; - - if (gpio->use_gpio == POWER_NOT_USE_GPIO) - return 0; - if (gpio->gpio_iomux == POWER_GPIO_IOMUX) - { - rk2818_mux_api_set(gpio->iomux_name, gpio->iomux_value); - } - - if (flag == GPIO_SWITCH_ON) - sensitive = gpio->sensi_level; - else - sensitive = 1 - gpio->sensi_level; - gpio_request(gpio->gpio_id, "wifi_power"); - gpio_direction_output(gpio->gpio_id,sensitive); - return 0; -} - - -int wifi_turn_on_card(void) -{ - - if (wifi_gpio_operate(&power_gpio, GPIO_SWITCH_ON) != 0) - { - printk("Couldn't set GPIO [ON] successfully for power supply.\n"); - return -1; - } - - return 0; -} - -int wifi_turn_off_card(void) -{ - - if (wifi_gpio_operate(&power_gpio, GPIO_SWITCH_OFF) != 0) - { - printk("Couldn't set GPIO [OFF] successfully for power supply.\n"); - return -1; - } - - return 0; -} - -int wifi_power_up_wifi(void) -{ - - if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_ON) != 0) - { - printk("Couldn't set GPIO [ON] successfully for power up.\n"); - return -1; - } - mdelay(5); - - if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_OFF) != 0) - { - printk("Couldn't set GPIO [ON] successfully for power up.\n"); - return -1; - } - msleep(150); - - if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_ON) != 0) - { - printk("Couldn't set GPIO [ON] successfully for power up.\n"); - return -1; - } - msleep(50); - - return 0; -} - -int wifi_power_down_wifi(void) -{ - if (wifi_gpio_operate(&power_save_gpio, GPIO_SWITCH_OFF) != 0) - { - printk("Couldn't set GPIO [OFF] successfully for power down.\n"); - return -1; - } - - return 0; -} - -#endif /* WIFI_GPIO_POWER_CONTROL */ - diff --git a/drivers/net/wireless/libertas/wifi_power.h b/drivers/net/wireless/libertas/wifi_power.h deleted file mode 100644 index d90a510ff15a..000000000000 --- a/drivers/net/wireless/libertas/wifi_power.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * wifi_power.h - * - * WIFI power control. - * - * Yongle Lai - */ - -#ifndef WIFI_POWER_H -#define WIFI_POWER_H - -#define WIFI_GPIO_POWER_CONTROL 1 - -#if (WIFI_GPIO_POWER_CONTROL == 1) - -#include -#include - -#define POWER_NOT_USE_GPIO 0 -#define POWER_USE_GPIO 1 - -#define POWER_GPIO_NOT_IOMUX 0 -#define POWER_GPIO_IOMUX 1 - -#define GPIO_SWITCH_OFF 0 -#define GPIO_SWITCH_ON 1 - -struct wifi_power -{ - u8 use_gpio; /* If uses GPIO to control wifi power supply. 0 - no, 1 - yes. */ - u8 gpio_iomux; /* If the GPIO is iomux. 0 - no, 1 - yes. */ - char *iomux_name; /* IOMUX name */ - u8 iomux_value; /* IOMUX value - which function is choosen. */ - u8 gpio_id; /* GPIO number */ - u8 sensi_level; /* GPIO sensitive level. */ -}; - -/* - * Power supply via control GPIO. - */ -#define POWER_VIA_GPIO 1 /* */ -#define POWER_GPIO_MUTEX 1 /* 1 - GPIO is a io mutexed IO */ -#define POWER_GPIO_MUTEX_NAME GPIOH6_IQ_SEL_NAME -#define POWER_GPIO_MUTEXT_VAL IOMUXB_GPIO1_D6 -#define POWER_GPIO_ID GPIOPortH_Pin6 -#define POWER_LEVEL_SENSITIVE GPIO_HIGH - -int wifi_turn_on_card(void); -int wifi_turn_off_card(void); -int wifi_power_up_wifi(void); -int wifi_power_down_wifi(void); -int wifi_power_reset(void); - -#endif /* WIFI_GPIO_POWER_CONTROL */ - -#endif /* WIFI_POWER_H */ diff --git a/drivers/net/wireless/libertas_tf/Makefile b/drivers/net/wireless/libertas_tf/Makefile deleted file mode 100644 index ff5544d6ac9d..000000000000 --- a/drivers/net/wireless/libertas_tf/Makefile +++ /dev/null @@ -1,6 +0,0 @@ -libertas_tf-objs := main.o cmd.o - -libertas_tf_usb-objs += if_usb.o - -obj-$(CONFIG_LIBERTAS_THINFIRM) += libertas_tf.o -obj-$(CONFIG_LIBERTAS_THINFIRM_USB) += libertas_tf_usb.o diff --git a/drivers/net/wireless/libertas_tf/cmd.c b/drivers/net/wireless/libertas_tf/cmd.c deleted file mode 100644 index 28790e03dc43..000000000000 --- a/drivers/net/wireless/libertas_tf/cmd.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (C) 2008, cozybit Inc. - * Copyright (C) 2003-2006, Marvell International Ltd. - * - * 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. - */ -#include "libertas_tf.h" - -static const struct channel_range channel_ranges[] = { - { LBTF_REGDOMAIN_US, 1, 12 }, - { LBTF_REGDOMAIN_CA, 1, 12 }, - { LBTF_REGDOMAIN_EU, 1, 14 }, - { LBTF_REGDOMAIN_JP, 1, 14 }, - { LBTF_REGDOMAIN_SP, 1, 14 }, - { LBTF_REGDOMAIN_FR, 1, 14 }, -}; - -static u16 lbtf_region_code_to_index[MRVDRV_MAX_REGION_CODE] = -{ - LBTF_REGDOMAIN_US, LBTF_REGDOMAIN_CA, LBTF_REGDOMAIN_EU, - LBTF_REGDOMAIN_SP, LBTF_REGDOMAIN_FR, LBTF_REGDOMAIN_JP, -}; - -static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv); - - -/** - * lbtf_cmd_copyback - Simple callback that copies response back into command - * - * @priv A pointer to struct lbtf_private structure - * @extra A pointer to the original command structure for which - * 'resp' is a response - * @resp A pointer to the command response - * - * Returns: 0 on success, error on failure - */ -int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra, - struct cmd_header *resp) -{ - struct cmd_header *buf = (void *)extra; - uint16_t copy_len; - - copy_len = min(le16_to_cpu(buf->size), le16_to_cpu(resp->size)); - memcpy(buf, resp, copy_len); - return 0; -} -EXPORT_SYMBOL_GPL(lbtf_cmd_copyback); - -#define CHAN_TO_IDX(chan) ((chan) - 1) - -static void lbtf_geo_init(struct lbtf_private *priv) -{ - const struct channel_range *range = channel_ranges; - u8 ch; - int i; - - for (i = 0; i < ARRAY_SIZE(channel_ranges); i++) - if (channel_ranges[i].regdomain == priv->regioncode) { - range = &channel_ranges[i]; - break; - } - - for (ch = priv->range.start; ch < priv->range.end; ch++) - priv->channels[CHAN_TO_IDX(ch)].flags = 0; -} - -/** - * lbtf_update_hw_spec: Updates the hardware details. - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: 0 on success, error on failure - */ -int lbtf_update_hw_spec(struct lbtf_private *priv) -{ - struct cmd_ds_get_hw_spec cmd; - int ret = -1; - u32 i; - - memset(&cmd, 0, sizeof(cmd)); - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - memcpy(cmd.permanentaddr, priv->current_addr, ETH_ALEN); - ret = lbtf_cmd_with_response(priv, CMD_GET_HW_SPEC, &cmd); - if (ret) - goto out; - - priv->fwcapinfo = le32_to_cpu(cmd.fwcapinfo); - - /* The firmware release is in an interesting format: the patch - * level is in the most significant nibble ... so fix that: */ - priv->fwrelease = le32_to_cpu(cmd.fwrelease); - priv->fwrelease = (priv->fwrelease << 8) | - (priv->fwrelease >> 24 & 0xff); - - printk(KERN_INFO "libertastf: %pM, fw %u.%u.%up%u, cap 0x%08x\n", - cmd.permanentaddr, - priv->fwrelease >> 24 & 0xff, - priv->fwrelease >> 16 & 0xff, - priv->fwrelease >> 8 & 0xff, - priv->fwrelease & 0xff, - priv->fwcapinfo); - - /* Clamp region code to 8-bit since FW spec indicates that it should - * only ever be 8-bit, even though the field size is 16-bit. Some - * firmware returns non-zero high 8 bits here. - */ - priv->regioncode = le16_to_cpu(cmd.regioncode) & 0xFF; - - for (i = 0; i < MRVDRV_MAX_REGION_CODE; i++) { - /* use the region code to search for the index */ - if (priv->regioncode == lbtf_region_code_to_index[i]) - break; - } - - /* if it's unidentified region code, use the default (USA) */ - if (i >= MRVDRV_MAX_REGION_CODE) - priv->regioncode = 0x10; - - if (priv->current_addr[0] == 0xff) - memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN); - - SET_IEEE80211_PERM_ADDR(priv->hw, priv->current_addr); - - lbtf_geo_init(priv); -out: - return ret; -} - -/** - * lbtf_set_channel: Set the radio channel - * - * @priv A pointer to struct lbtf_private structure - * @channel The desired channel, or 0 to clear a locked channel - * - * Returns: 0 on success, error on failure - */ -int lbtf_set_channel(struct lbtf_private *priv, u8 channel) -{ - struct cmd_ds_802_11_rf_channel cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_OPT_802_11_RF_CHANNEL_SET); - cmd.channel = cpu_to_le16(channel); - - return lbtf_cmd_with_response(priv, CMD_802_11_RF_CHANNEL, &cmd); -} - -int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon) -{ - struct cmd_ds_802_11_beacon_set cmd; - int size; - - if (beacon->len > MRVL_MAX_BCN_SIZE) - return -1; - size = sizeof(cmd) - sizeof(cmd.beacon) + beacon->len; - cmd.hdr.size = cpu_to_le16(size); - cmd.len = cpu_to_le16(beacon->len); - memcpy(cmd.beacon, (u8 *) beacon->data, beacon->len); - - lbtf_cmd_async(priv, CMD_802_11_BEACON_SET, &cmd.hdr, size); - return 0; -} - -int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable, - int beacon_int) { - struct cmd_ds_802_11_beacon_control cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - cmd.beacon_enable = cpu_to_le16(beacon_enable); - cmd.beacon_period = cpu_to_le16(beacon_int); - - lbtf_cmd_async(priv, CMD_802_11_BEACON_CTRL, &cmd.hdr, sizeof(cmd)); - return 0; -} - -static void lbtf_queue_cmd(struct lbtf_private *priv, - struct cmd_ctrl_node *cmdnode) -{ - unsigned long flags; - - if (!cmdnode) - return; - - if (!cmdnode->cmdbuf->size) - return; - - cmdnode->result = 0; - spin_lock_irqsave(&priv->driver_lock, flags); - list_add_tail(&cmdnode->list, &priv->cmdpendingq); - spin_unlock_irqrestore(&priv->driver_lock, flags); -} - -static void lbtf_submit_command(struct lbtf_private *priv, - struct cmd_ctrl_node *cmdnode) -{ - unsigned long flags; - struct cmd_header *cmd; - uint16_t cmdsize; - uint16_t command; - int timeo = 5 * HZ; - int ret; - - cmd = cmdnode->cmdbuf; - - spin_lock_irqsave(&priv->driver_lock, flags); - priv->cur_cmd = cmdnode; - cmdsize = le16_to_cpu(cmd->size); - command = le16_to_cpu(cmd->command); - ret = priv->hw_host_to_card(priv, MVMS_CMD, (u8 *) cmd, cmdsize); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - if (ret) - /* Let the timer kick in and retry, and potentially reset - the whole thing if the condition persists */ - timeo = HZ; - - /* Setup the timer after transmit command */ - mod_timer(&priv->command_timer, jiffies + timeo); -} - -/** - * This function inserts command node to cmdfreeq - * after cleans it. Requires priv->driver_lock held. - */ -static void __lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, - struct cmd_ctrl_node *cmdnode) -{ - if (!cmdnode) - return; - - cmdnode->callback = NULL; - cmdnode->callback_arg = 0; - - memset(cmdnode->cmdbuf, 0, LBS_CMD_BUFFER_SIZE); - - list_add_tail(&cmdnode->list, &priv->cmdfreeq); -} - -static void lbtf_cleanup_and_insert_cmd(struct lbtf_private *priv, - struct cmd_ctrl_node *ptempcmd) -{ - unsigned long flags; - - spin_lock_irqsave(&priv->driver_lock, flags); - __lbtf_cleanup_and_insert_cmd(priv, ptempcmd); - spin_unlock_irqrestore(&priv->driver_lock, flags); -} - -void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd, - int result) -{ - cmd->result = result; - cmd->cmdwaitqwoken = 1; - wake_up_interruptible(&cmd->cmdwait_q); - - if (!cmd->callback) - __lbtf_cleanup_and_insert_cmd(priv, cmd); - priv->cur_cmd = NULL; -} - -int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv) -{ - struct cmd_ds_mac_multicast_addr cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - - cmd.nr_of_adrs = cpu_to_le16((u16) priv->nr_of_multicastmacaddr); - memcpy(cmd.maclist, priv->multicastlist, - priv->nr_of_multicastmacaddr * ETH_ALEN); - - lbtf_cmd_async(priv, CMD_MAC_MULTICAST_ADR, &cmd.hdr, sizeof(cmd)); - return 0; -} - -void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode) -{ - struct cmd_ds_set_mode cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.mode = cpu_to_le16(mode); - lbtf_cmd_async(priv, CMD_802_11_SET_MODE, &cmd.hdr, sizeof(cmd)); -} - -void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid) -{ - struct cmd_ds_set_bssid cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.activate = activate ? 1 : 0; - if (activate) - memcpy(cmd.bssid, bssid, ETH_ALEN); - - lbtf_cmd_async(priv, CMD_802_11_SET_BSSID, &cmd.hdr, sizeof(cmd)); -} - -int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr) -{ - struct cmd_ds_802_11_mac_address cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - - memcpy(cmd.macadd, mac_addr, ETH_ALEN); - - lbtf_cmd_async(priv, CMD_802_11_MAC_ADDRESS, &cmd.hdr, sizeof(cmd)); - return 0; -} - -int lbtf_set_radio_control(struct lbtf_private *priv) -{ - int ret = 0; - struct cmd_ds_802_11_radio_control cmd; - - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(CMD_ACT_SET); - - switch (priv->preamble) { - case CMD_TYPE_SHORT_PREAMBLE: - cmd.control = cpu_to_le16(SET_SHORT_PREAMBLE); - break; - - case CMD_TYPE_LONG_PREAMBLE: - cmd.control = cpu_to_le16(SET_LONG_PREAMBLE); - break; - - case CMD_TYPE_AUTO_PREAMBLE: - default: - cmd.control = cpu_to_le16(SET_AUTO_PREAMBLE); - break; - } - - if (priv->radioon) - cmd.control |= cpu_to_le16(TURN_ON_RF); - else - cmd.control &= cpu_to_le16(~TURN_ON_RF); - - ret = lbtf_cmd_with_response(priv, CMD_802_11_RADIO_CONTROL, &cmd); - return ret; -} - -void lbtf_set_mac_control(struct lbtf_private *priv) -{ - struct cmd_ds_mac_control cmd; - cmd.hdr.size = cpu_to_le16(sizeof(cmd)); - cmd.action = cpu_to_le16(priv->mac_control); - cmd.reserved = 0; - - lbtf_cmd_async(priv, CMD_MAC_CONTROL, - &cmd.hdr, sizeof(cmd)); -} - -/** - * lbtf_allocate_cmd_buffer - Allocates cmd buffer, links it to free cmd queue - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: 0 on success. - */ -int lbtf_allocate_cmd_buffer(struct lbtf_private *priv) -{ - u32 bufsize; - u32 i; - struct cmd_ctrl_node *cmdarray; - - /* Allocate and initialize the command array */ - bufsize = sizeof(struct cmd_ctrl_node) * LBS_NUM_CMD_BUFFERS; - cmdarray = kzalloc(bufsize, GFP_KERNEL); - if (!cmdarray) - return -1; - priv->cmd_array = cmdarray; - - /* Allocate and initialize each command buffer in the command array */ - for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { - cmdarray[i].cmdbuf = kzalloc(LBS_CMD_BUFFER_SIZE, GFP_KERNEL); - if (!cmdarray[i].cmdbuf) - return -1; - } - - for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { - init_waitqueue_head(&cmdarray[i].cmdwait_q); - lbtf_cleanup_and_insert_cmd(priv, &cmdarray[i]); - } - return 0; -} - -/** - * lbtf_free_cmd_buffer - Frees the cmd buffer. - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: 0 - */ -int lbtf_free_cmd_buffer(struct lbtf_private *priv) -{ - struct cmd_ctrl_node *cmdarray; - unsigned int i; - - /* need to check if cmd array is allocated or not */ - if (priv->cmd_array == NULL) - return 0; - - cmdarray = priv->cmd_array; - - /* Release shared memory buffers */ - for (i = 0; i < LBS_NUM_CMD_BUFFERS; i++) { - kfree(cmdarray[i].cmdbuf); - cmdarray[i].cmdbuf = NULL; - } - - /* Release cmd_ctrl_node */ - kfree(priv->cmd_array); - priv->cmd_array = NULL; - - return 0; -} - -/** - * lbtf_get_cmd_ctrl_node - Gets free cmd node from free cmd queue. - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: pointer to a struct cmd_ctrl_node or NULL if none available. - */ -static struct cmd_ctrl_node *lbtf_get_cmd_ctrl_node(struct lbtf_private *priv) -{ - struct cmd_ctrl_node *tempnode; - unsigned long flags; - - if (!priv) - return NULL; - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (!list_empty(&priv->cmdfreeq)) { - tempnode = list_first_entry(&priv->cmdfreeq, - struct cmd_ctrl_node, list); - list_del(&tempnode->list); - } else - tempnode = NULL; - - spin_unlock_irqrestore(&priv->driver_lock, flags); - - return tempnode; -} - -/** - * lbtf_execute_next_command: execute next command in cmd pending queue. - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: 0 on success. - */ -int lbtf_execute_next_command(struct lbtf_private *priv) -{ - struct cmd_ctrl_node *cmdnode = NULL; - struct cmd_header *cmd; - unsigned long flags; - - /* Debug group is LBS_DEB_THREAD and not LBS_DEB_HOST, because the - * only caller to us is lbtf_thread() and we get even when a - * data packet is received */ - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->cur_cmd) { - spin_unlock_irqrestore(&priv->driver_lock, flags); - return -1; - } - - if (!list_empty(&priv->cmdpendingq)) { - cmdnode = list_first_entry(&priv->cmdpendingq, - struct cmd_ctrl_node, list); - } - - if (cmdnode) { - cmd = cmdnode->cmdbuf; - - list_del(&cmdnode->list); - spin_unlock_irqrestore(&priv->driver_lock, flags); - lbtf_submit_command(priv, cmdnode); - } else - spin_unlock_irqrestore(&priv->driver_lock, flags); - return 0; -} - -static struct cmd_ctrl_node *__lbtf_cmd_async(struct lbtf_private *priv, - uint16_t command, struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbtf_private *, unsigned long, - struct cmd_header *), - unsigned long callback_arg) -{ - struct cmd_ctrl_node *cmdnode; - - if (priv->surpriseremoved) - return ERR_PTR(-ENOENT); - - cmdnode = lbtf_get_cmd_ctrl_node(priv); - if (cmdnode == NULL) { - /* Wake up main thread to execute next command */ - queue_work(lbtf_wq, &priv->cmd_work); - return ERR_PTR(-ENOBUFS); - } - - cmdnode->callback = callback; - cmdnode->callback_arg = callback_arg; - - /* Copy the incoming command to the buffer */ - memcpy(cmdnode->cmdbuf, in_cmd, in_cmd_size); - - /* Set sequence number, clean result, move to buffer */ - priv->seqnum++; - cmdnode->cmdbuf->command = cpu_to_le16(command); - cmdnode->cmdbuf->size = cpu_to_le16(in_cmd_size); - cmdnode->cmdbuf->seqnum = cpu_to_le16(priv->seqnum); - cmdnode->cmdbuf->result = 0; - cmdnode->cmdwaitqwoken = 0; - lbtf_queue_cmd(priv, cmdnode); - queue_work(lbtf_wq, &priv->cmd_work); - - return cmdnode; -} - -void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size) -{ - __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, NULL, 0); -} - -int __lbtf_cmd(struct lbtf_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbtf_private *, - unsigned long, struct cmd_header *), - unsigned long callback_arg) -{ - struct cmd_ctrl_node *cmdnode; - unsigned long flags; - int ret = 0; - - cmdnode = __lbtf_cmd_async(priv, command, in_cmd, in_cmd_size, - callback, callback_arg); - if (IS_ERR(cmdnode)) - return PTR_ERR(cmdnode); - - might_sleep(); - ret = wait_event_interruptible(cmdnode->cmdwait_q, - cmdnode->cmdwaitqwoken); - if (ret) { - printk(KERN_DEBUG - "libertastf: command 0x%04x interrupted by signal", - command); - return ret; - } - - spin_lock_irqsave(&priv->driver_lock, flags); - ret = cmdnode->result; - if (ret) - printk(KERN_DEBUG "libertastf: command 0x%04x failed: %d\n", - command, ret); - - __lbtf_cleanup_and_insert_cmd(priv, cmdnode); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - return ret; -} -EXPORT_SYMBOL_GPL(__lbtf_cmd); - -/* Call holding driver_lock */ -void lbtf_cmd_response_rx(struct lbtf_private *priv) -{ - priv->cmd_response_rxed = 1; - queue_work(lbtf_wq, &priv->cmd_work); -} -EXPORT_SYMBOL_GPL(lbtf_cmd_response_rx); - -int lbtf_process_rx_command(struct lbtf_private *priv) -{ - uint16_t respcmd, curcmd; - struct cmd_header *resp; - int ret = 0; - unsigned long flags; - uint16_t result; - - mutex_lock(&priv->lock); - spin_lock_irqsave(&priv->driver_lock, flags); - - if (!priv->cur_cmd) { - ret = -1; - spin_unlock_irqrestore(&priv->driver_lock, flags); - goto done; - } - - resp = (void *)priv->cmd_resp_buff; - curcmd = le16_to_cpu(priv->cur_cmd->cmdbuf->command); - respcmd = le16_to_cpu(resp->command); - result = le16_to_cpu(resp->result); - - if (net_ratelimit()) - printk(KERN_DEBUG "libertastf: cmd response 0x%04x, seq %d, size %d\n", - respcmd, le16_to_cpu(resp->seqnum), - le16_to_cpu(resp->size)); - - if (resp->seqnum != priv->cur_cmd->cmdbuf->seqnum) { - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - if (respcmd != CMD_RET(curcmd)) { - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - - if (resp->result == cpu_to_le16(0x0004)) { - /* 0x0004 means -EAGAIN. Drop the response, let it time out - and be resubmitted */ - spin_unlock_irqrestore(&priv->driver_lock, flags); - ret = -1; - goto done; - } - - /* Now we got response from FW, cancel the command timer */ - del_timer(&priv->command_timer); - priv->cmd_timed_out = 0; - if (priv->nr_retries) - priv->nr_retries = 0; - - /* If the command is not successful, cleanup and return failure */ - if ((result != 0 || !(respcmd & 0x8000))) { - /* - * Handling errors here - */ - switch (respcmd) { - case CMD_RET(CMD_GET_HW_SPEC): - case CMD_RET(CMD_802_11_RESET): - printk(KERN_DEBUG "libertastf: reset failed\n"); - break; - - } - lbtf_complete_command(priv, priv->cur_cmd, result); - spin_unlock_irqrestore(&priv->driver_lock, flags); - - ret = -1; - goto done; - } - - spin_unlock_irqrestore(&priv->driver_lock, flags); - - if (priv->cur_cmd && priv->cur_cmd->callback) { - ret = priv->cur_cmd->callback(priv, priv->cur_cmd->callback_arg, - resp); - } - spin_lock_irqsave(&priv->driver_lock, flags); - - if (priv->cur_cmd) { - /* Clean up and Put current command back to cmdfreeq */ - lbtf_complete_command(priv, priv->cur_cmd, result); - } - spin_unlock_irqrestore(&priv->driver_lock, flags); - -done: - mutex_unlock(&priv->lock); - return ret; -} diff --git a/drivers/net/wireless/libertas_tf/if_usb.c b/drivers/net/wireless/libertas_tf/if_usb.c deleted file mode 100644 index 392337b37b1d..000000000000 --- a/drivers/net/wireless/libertas_tf/if_usb.c +++ /dev/null @@ -1,765 +0,0 @@ -/* - * Copyright (C) 2008, cozybit Inc. - * Copyright (C) 2003-2006, Marvell International Ltd. - * - * 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. - */ -#include -#include -#include -#include -#include - -#define DRV_NAME "lbtf_usb" - -#include "libertas_tf.h" -#include "if_usb.h" - -#define MESSAGE_HEADER_LEN 4 - -static char *lbtf_fw_name = "lbtf_usb.bin"; -module_param_named(fw_name, lbtf_fw_name, charp, 0644); - -static struct usb_device_id if_usb_table[] = { - /* Enter the device signature inside */ - { USB_DEVICE(0x1286, 0x2001) }, - { USB_DEVICE(0x05a3, 0x8388) }, - {} /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, if_usb_table); - -static void if_usb_receive(struct urb *urb); -static void if_usb_receive_fwload(struct urb *urb); -static int if_usb_prog_firmware(struct if_usb_card *cardp); -static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type, - uint8_t *payload, uint16_t nb); -static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, - uint16_t nb, u8 data); -static void if_usb_free(struct if_usb_card *cardp); -static int if_usb_submit_rx_urb(struct if_usb_card *cardp); -static int if_usb_reset_device(struct if_usb_card *cardp); - -/** - * if_usb_wrike_bulk_callback - call back to handle URB status - * - * @param urb pointer to urb structure - */ -static void if_usb_write_bulk_callback(struct urb *urb) -{ - if (urb->status != 0) - printk(KERN_INFO "libertastf: URB in failure status: %d\n", - urb->status); -} - -/** - * if_usb_free - free tx/rx urb, skb and rx buffer - * - * @param cardp pointer if_usb_card - */ -static void if_usb_free(struct if_usb_card *cardp) -{ - /* Unlink tx & rx urb */ - usb_kill_urb(cardp->tx_urb); - usb_kill_urb(cardp->rx_urb); - usb_kill_urb(cardp->cmd_urb); - - usb_free_urb(cardp->tx_urb); - cardp->tx_urb = NULL; - - usb_free_urb(cardp->rx_urb); - cardp->rx_urb = NULL; - - usb_free_urb(cardp->cmd_urb); - cardp->cmd_urb = NULL; - - kfree(cardp->ep_out_buf); - cardp->ep_out_buf = NULL; -} - -static void if_usb_setup_firmware(struct lbtf_private *priv) -{ - struct if_usb_card *cardp = priv->card; - struct cmd_ds_set_boot2_ver b2_cmd; - - if_usb_submit_rx_urb(cardp); - b2_cmd.hdr.size = cpu_to_le16(sizeof(b2_cmd)); - b2_cmd.action = 0; - b2_cmd.version = cardp->boot2_version; - - if (lbtf_cmd_with_response(priv, CMD_SET_BOOT2_VER, &b2_cmd)) - printk(KERN_INFO "libertastf: setting boot2 version failed\n"); -} - -static void if_usb_fw_timeo(unsigned long priv) -{ - struct if_usb_card *cardp = (void *)priv; - - if (!cardp->fwdnldover) - /* Download timed out */ - cardp->priv->surpriseremoved = 1; - wake_up(&cardp->fw_wq); -} - -/** - * if_usb_probe - sets the configuration values - * - * @ifnum interface number - * @id pointer to usb_device_id - * - * Returns: 0 on success, error code on failure - */ -static int if_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev; - struct usb_host_interface *iface_desc; - struct usb_endpoint_descriptor *endpoint; - struct lbtf_private *priv; - struct if_usb_card *cardp; - int i; - - udev = interface_to_usbdev(intf); - - cardp = kzalloc(sizeof(struct if_usb_card), GFP_KERNEL); - if (!cardp) - goto error; - - setup_timer(&cardp->fw_timeout, if_usb_fw_timeo, (unsigned long)cardp); - init_waitqueue_head(&cardp->fw_wq); - - cardp->udev = udev; - iface_desc = intf->cur_altsetting; - - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - endpoint = &iface_desc->endpoint[i].desc; - if (usb_endpoint_is_bulk_in(endpoint)) { - cardp->ep_in_size = - le16_to_cpu(endpoint->wMaxPacketSize); - cardp->ep_in = usb_endpoint_num(endpoint); - } else if (usb_endpoint_is_bulk_out(endpoint)) { - cardp->ep_out_size = - le16_to_cpu(endpoint->wMaxPacketSize); - cardp->ep_out = usb_endpoint_num(endpoint); - } - } - if (!cardp->ep_out_size || !cardp->ep_in_size) - /* Endpoints not found */ - goto dealloc; - - cardp->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!cardp->rx_urb) - goto dealloc; - - cardp->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!cardp->tx_urb) - goto dealloc; - - cardp->cmd_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!cardp->cmd_urb) - goto dealloc; - - cardp->ep_out_buf = kmalloc(MRVDRV_ETH_TX_PACKET_BUFFER_SIZE, - GFP_KERNEL); - if (!cardp->ep_out_buf) - goto dealloc; - - priv = lbtf_add_card(cardp, &udev->dev); - if (!priv) - goto dealloc; - - cardp->priv = priv; - - priv->hw_host_to_card = if_usb_host_to_card; - priv->hw_prog_firmware = if_usb_prog_firmware; - priv->hw_reset_device = if_usb_reset_device; - cardp->boot2_version = udev->descriptor.bcdDevice; - - usb_get_dev(udev); - usb_set_intfdata(intf, cardp); - - return 0; - -dealloc: - if_usb_free(cardp); -error: - return -ENOMEM; -} - -/** - * if_usb_disconnect - free resource and cleanup - * - * @intf USB interface structure - */ -static void if_usb_disconnect(struct usb_interface *intf) -{ - struct if_usb_card *cardp = usb_get_intfdata(intf); - struct lbtf_private *priv = (struct lbtf_private *) cardp->priv; - - if_usb_reset_device(cardp); - - if (priv) - lbtf_remove_card(priv); - - /* Unlink and free urb */ - if_usb_free(cardp); - - usb_set_intfdata(intf, NULL); - usb_put_dev(interface_to_usbdev(intf)); -} - -/** - * if_usb_send_fw_pkt - This function downloads the FW - * - * @priv pointer to struct lbtf_private - * - * Returns: 0 - */ -static int if_usb_send_fw_pkt(struct if_usb_card *cardp) -{ - struct fwdata *fwdata = cardp->ep_out_buf; - u8 *firmware = (u8 *) cardp->fw->data; - - /* If we got a CRC failure on the last block, back - up and retry it */ - if (!cardp->CRC_OK) { - cardp->totalbytes = cardp->fwlastblksent; - cardp->fwseqnum--; - } - - /* struct fwdata (which we sent to the card) has an - extra __le32 field in between the header and the data, - which is not in the struct fwheader in the actual - firmware binary. Insert the seqnum in the middle... */ - memcpy(&fwdata->hdr, &firmware[cardp->totalbytes], - sizeof(struct fwheader)); - - cardp->fwlastblksent = cardp->totalbytes; - cardp->totalbytes += sizeof(struct fwheader); - - memcpy(fwdata->data, &firmware[cardp->totalbytes], - le32_to_cpu(fwdata->hdr.datalength)); - - fwdata->seqnum = cpu_to_le32(++cardp->fwseqnum); - cardp->totalbytes += le32_to_cpu(fwdata->hdr.datalength); - - usb_tx_block(cardp, cardp->ep_out_buf, sizeof(struct fwdata) + - le32_to_cpu(fwdata->hdr.datalength), 0); - - if (fwdata->hdr.dnldcmd == cpu_to_le32(FW_HAS_LAST_BLOCK)) - /* Host has finished FW downloading - * Donwloading FW JUMP BLOCK - */ - cardp->fwfinalblk = 1; - - return 0; -} - -static int if_usb_reset_device(struct if_usb_card *cardp) -{ - struct cmd_ds_802_11_reset *cmd = cardp->ep_out_buf + 4; - int ret; - - *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); - - cmd->hdr.command = cpu_to_le16(CMD_802_11_RESET); - cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_802_11_reset)); - cmd->hdr.result = cpu_to_le16(0); - cmd->hdr.seqnum = cpu_to_le16(0x5a5a); - cmd->action = cpu_to_le16(CMD_ACT_HALT); - usb_tx_block(cardp, cardp->ep_out_buf, - 4 + sizeof(struct cmd_ds_802_11_reset), 0); - - msleep(100); - ret = usb_reset_device(cardp->udev); - msleep(100); - - return ret; -} -EXPORT_SYMBOL_GPL(if_usb_reset_device); - -/** - * usb_tx_block - transfer data to the device - * - * @priv pointer to struct lbtf_private - * @payload pointer to payload data - * @nb data length - * @data non-zero for data, zero for commands - * - * Returns: 0 on success, nonzero otherwise. - */ -static int usb_tx_block(struct if_usb_card *cardp, uint8_t *payload, - uint16_t nb, u8 data) -{ - struct urb *urb; - - /* check if device is removed */ - if (cardp->priv->surpriseremoved) - return -1; - - if (data) - urb = cardp->tx_urb; - else - urb = cardp->cmd_urb; - - usb_fill_bulk_urb(urb, cardp->udev, - usb_sndbulkpipe(cardp->udev, - cardp->ep_out), - payload, nb, if_usb_write_bulk_callback, cardp); - - urb->transfer_flags |= URB_ZERO_PACKET; - - if (usb_submit_urb(urb, GFP_ATOMIC)) - return -1; - return 0; -} - -static int __if_usb_submit_rx_urb(struct if_usb_card *cardp, - void (*callbackfn)(struct urb *urb)) -{ - struct sk_buff *skb; - - skb = dev_alloc_skb(MRVDRV_ETH_RX_PACKET_BUFFER_SIZE); - if (!skb) - return -1; - - cardp->rx_skb = skb; - - /* Fill the receive configuration URB and initialise the Rx call back */ - usb_fill_bulk_urb(cardp->rx_urb, cardp->udev, - usb_rcvbulkpipe(cardp->udev, cardp->ep_in), - skb_tail_pointer(skb), - MRVDRV_ETH_RX_PACKET_BUFFER_SIZE, callbackfn, cardp); - - cardp->rx_urb->transfer_flags |= URB_ZERO_PACKET; - - if (usb_submit_urb(cardp->rx_urb, GFP_ATOMIC)) { - kfree_skb(skb); - cardp->rx_skb = NULL; - return -1; - } else - return 0; -} - -static int if_usb_submit_rx_urb_fwload(struct if_usb_card *cardp) -{ - return __if_usb_submit_rx_urb(cardp, &if_usb_receive_fwload); -} - -static int if_usb_submit_rx_urb(struct if_usb_card *cardp) -{ - return __if_usb_submit_rx_urb(cardp, &if_usb_receive); -} - -static void if_usb_receive_fwload(struct urb *urb) -{ - struct if_usb_card *cardp = urb->context; - struct sk_buff *skb = cardp->rx_skb; - struct fwsyncheader *syncfwheader; - struct bootcmdresp bcmdresp; - - if (urb->status) { - kfree_skb(skb); - return; - } - - if (cardp->fwdnldover) { - __le32 *tmp = (__le32 *)(skb->data); - - if (tmp[0] == cpu_to_le32(CMD_TYPE_INDICATION) && - tmp[1] == cpu_to_le32(MACREG_INT_CODE_FIRMWARE_READY)) - /* Firmware ready event received */ - wake_up(&cardp->fw_wq); - else - if_usb_submit_rx_urb_fwload(cardp); - kfree_skb(skb); - return; - } - if (cardp->bootcmdresp <= 0) { - memcpy(&bcmdresp, skb->data, sizeof(bcmdresp)); - - if (le16_to_cpu(cardp->udev->descriptor.bcdDevice) < 0x3106) { - kfree_skb(skb); - if_usb_submit_rx_urb_fwload(cardp); - cardp->bootcmdresp = 1; - /* Received valid boot command response */ - return; - } - if (bcmdresp.magic != cpu_to_le32(BOOT_CMD_MAGIC_NUMBER)) { - if (bcmdresp.magic == cpu_to_le32(CMD_TYPE_REQUEST) || - bcmdresp.magic == cpu_to_le32(CMD_TYPE_DATA) || - bcmdresp.magic == cpu_to_le32(CMD_TYPE_INDICATION)) - cardp->bootcmdresp = -1; - } else if (bcmdresp.cmd == BOOT_CMD_FW_BY_USB && - bcmdresp.result == BOOT_CMD_RESP_OK) - cardp->bootcmdresp = 1; - - kfree_skb(skb); - if_usb_submit_rx_urb_fwload(cardp); - return; - } - - syncfwheader = kmalloc(sizeof(struct fwsyncheader), GFP_ATOMIC); - if (!syncfwheader) { - kfree_skb(skb); - return; - } - - memcpy(syncfwheader, skb->data, sizeof(struct fwsyncheader)); - - if (!syncfwheader->cmd) - cardp->CRC_OK = 1; - else - cardp->CRC_OK = 0; - kfree_skb(skb); - - /* reschedule timer for 200ms hence */ - mod_timer(&cardp->fw_timeout, jiffies + (HZ/5)); - - if (cardp->fwfinalblk) { - cardp->fwdnldover = 1; - goto exit; - } - - if_usb_send_fw_pkt(cardp); - - exit: - if_usb_submit_rx_urb_fwload(cardp); - - kfree(syncfwheader); - - return; -} - -#define MRVDRV_MIN_PKT_LEN 30 - -static inline void process_cmdtypedata(int recvlength, struct sk_buff *skb, - struct if_usb_card *cardp, - struct lbtf_private *priv) -{ - if (recvlength > MRVDRV_ETH_RX_PACKET_BUFFER_SIZE + MESSAGE_HEADER_LEN - || recvlength < MRVDRV_MIN_PKT_LEN) { - kfree_skb(skb); - return; - } - - skb_put(skb, recvlength); - skb_pull(skb, MESSAGE_HEADER_LEN); - lbtf_rx(priv, skb); -} - -static inline void process_cmdrequest(int recvlength, uint8_t *recvbuff, - struct sk_buff *skb, - struct if_usb_card *cardp, - struct lbtf_private *priv) -{ - if (recvlength > LBS_CMD_BUFFER_SIZE) { - kfree_skb(skb); - return; - } - - BUG_ON(!in_interrupt()); - - spin_lock(&priv->driver_lock); - memcpy(priv->cmd_resp_buff, recvbuff + MESSAGE_HEADER_LEN, - recvlength - MESSAGE_HEADER_LEN); - kfree_skb(skb); - lbtf_cmd_response_rx(priv); - spin_unlock(&priv->driver_lock); -} - -/** - * if_usb_receive - read data received from the device. - * - * @urb pointer to struct urb - */ -static void if_usb_receive(struct urb *urb) -{ - struct if_usb_card *cardp = urb->context; - struct sk_buff *skb = cardp->rx_skb; - struct lbtf_private *priv = cardp->priv; - int recvlength = urb->actual_length; - uint8_t *recvbuff = NULL; - uint32_t recvtype = 0; - __le32 *pkt = (__le32 *) skb->data; - - if (recvlength) { - if (urb->status) { - kfree_skb(skb); - goto setup_for_next; - } - - recvbuff = skb->data; - recvtype = le32_to_cpu(pkt[0]); - } else if (urb->status) { - kfree_skb(skb); - return; - } - - switch (recvtype) { - case CMD_TYPE_DATA: - process_cmdtypedata(recvlength, skb, cardp, priv); - break; - - case CMD_TYPE_REQUEST: - process_cmdrequest(recvlength, recvbuff, skb, cardp, priv); - break; - - case CMD_TYPE_INDICATION: - { - /* Event cause handling */ - u32 event_cause = le32_to_cpu(pkt[1]); - - /* Icky undocumented magic special case */ - if (event_cause & 0xffff0000) { - u16 tmp; - u8 retrycnt; - u8 failure; - - tmp = event_cause >> 16; - retrycnt = tmp & 0x00ff; - failure = (tmp & 0xff00) >> 8; - lbtf_send_tx_feedback(priv, retrycnt, failure); - } else if (event_cause == LBTF_EVENT_BCN_SENT) - lbtf_bcn_sent(priv); - else - printk(KERN_DEBUG - "Unsupported notification %d received\n", - event_cause); - kfree_skb(skb); - break; - } - default: - printk(KERN_DEBUG "libertastf: unknown command type 0x%X\n", - recvtype); - kfree_skb(skb); - break; - } - -setup_for_next: - if_usb_submit_rx_urb(cardp); -} - -/** - * if_usb_host_to_card - Download data to the device - * - * @priv pointer to struct lbtf_private structure - * @type type of data - * @buf pointer to data buffer - * @len number of bytes - * - * Returns: 0 on success, nonzero otherwise - */ -static int if_usb_host_to_card(struct lbtf_private *priv, uint8_t type, - uint8_t *payload, uint16_t nb) -{ - struct if_usb_card *cardp = priv->card; - u8 data = 0; - - if (type == MVMS_CMD) { - *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_REQUEST); - } else { - *(__le32 *)cardp->ep_out_buf = cpu_to_le32(CMD_TYPE_DATA); - data = 1; - } - - memcpy((cardp->ep_out_buf + MESSAGE_HEADER_LEN), payload, nb); - - return usb_tx_block(cardp, cardp->ep_out_buf, nb + MESSAGE_HEADER_LEN, - data); -} - -/** - * if_usb_issue_boot_command - Issue boot command to Boot2. - * - * @ivalue 1 boots from FW by USB-Download, 2 boots from FW in EEPROM. - * - * Returns: 0 - */ -static int if_usb_issue_boot_command(struct if_usb_card *cardp, int ivalue) -{ - struct bootcmd *bootcmd = cardp->ep_out_buf; - - /* Prepare command */ - bootcmd->magic = cpu_to_le32(BOOT_CMD_MAGIC_NUMBER); - bootcmd->cmd = ivalue; - memset(bootcmd->pad, 0, sizeof(bootcmd->pad)); - - /* Issue command */ - usb_tx_block(cardp, cardp->ep_out_buf, sizeof(*bootcmd), 0); - - return 0; -} - - -/** - * check_fwfile_format - Check the validity of Boot2/FW image. - * - * @data pointer to image - * @totlen image length - * - * Returns: 0 if the image is valid, nonzero otherwise. - */ -static int check_fwfile_format(const u8 *data, u32 totlen) -{ - u32 bincmd, exit; - u32 blksize, offset, len; - int ret; - - ret = 1; - exit = len = 0; - - do { - struct fwheader *fwh = (void *) data; - - bincmd = le32_to_cpu(fwh->dnldcmd); - blksize = le32_to_cpu(fwh->datalength); - switch (bincmd) { - case FW_HAS_DATA_TO_RECV: - offset = sizeof(struct fwheader) + blksize; - data += offset; - len += offset; - if (len >= totlen) - exit = 1; - break; - case FW_HAS_LAST_BLOCK: - exit = 1; - ret = 0; - break; - default: - exit = 1; - break; - } - } while (!exit); - - if (ret) - printk(KERN_INFO - "libertastf: firmware file format check failed\n"); - return ret; -} - - -static int if_usb_prog_firmware(struct if_usb_card *cardp) -{ - int i = 0; - static int reset_count = 10; - int ret = 0; - - ret = request_firmware(&cardp->fw, lbtf_fw_name, &cardp->udev->dev); - if (ret < 0) { - printk(KERN_INFO "libertastf: firmware %s not found\n", - lbtf_fw_name); - goto done; - } - - if (check_fwfile_format(cardp->fw->data, cardp->fw->size)) - goto release_fw; - -restart: - if (if_usb_submit_rx_urb_fwload(cardp) < 0) { - ret = -1; - goto release_fw; - } - - cardp->bootcmdresp = 0; - do { - int j = 0; - i++; - /* Issue Boot command = 1, Boot from Download-FW */ - if_usb_issue_boot_command(cardp, BOOT_CMD_FW_BY_USB); - /* wait for command response */ - do { - j++; - msleep_interruptible(100); - } while (cardp->bootcmdresp == 0 && j < 10); - } while (cardp->bootcmdresp == 0 && i < 5); - - if (cardp->bootcmdresp <= 0) { - if (--reset_count >= 0) { - if_usb_reset_device(cardp); - goto restart; - } - return -1; - } - - i = 0; - - cardp->totalbytes = 0; - cardp->fwlastblksent = 0; - cardp->CRC_OK = 1; - cardp->fwdnldover = 0; - cardp->fwseqnum = -1; - cardp->totalbytes = 0; - cardp->fwfinalblk = 0; - - /* Send the first firmware packet... */ - if_usb_send_fw_pkt(cardp); - - /* ... and wait for the process to complete */ - wait_event_interruptible(cardp->fw_wq, cardp->priv->surpriseremoved || - cardp->fwdnldover); - - del_timer_sync(&cardp->fw_timeout); - usb_kill_urb(cardp->rx_urb); - - if (!cardp->fwdnldover) { - printk(KERN_INFO "libertastf: failed to load fw," - " resetting device!\n"); - if (--reset_count >= 0) { - if_usb_reset_device(cardp); - goto restart; - } - - printk(KERN_INFO "libertastf: fw download failure\n"); - ret = -1; - goto release_fw; - } - - cardp->priv->fw_ready = 1; - - release_fw: - release_firmware(cardp->fw); - cardp->fw = NULL; - - if_usb_setup_firmware(cardp->priv); - - done: - return ret; -} -EXPORT_SYMBOL_GPL(if_usb_prog_firmware); - - -#define if_usb_suspend NULL -#define if_usb_resume NULL - -static struct usb_driver if_usb_driver = { - .name = DRV_NAME, - .probe = if_usb_probe, - .disconnect = if_usb_disconnect, - .id_table = if_usb_table, - .suspend = if_usb_suspend, - .resume = if_usb_resume, -}; - -static int __init if_usb_init_module(void) -{ - int ret = 0; - - ret = usb_register(&if_usb_driver); - return ret; -} - -static void __exit if_usb_exit_module(void) -{ - usb_deregister(&if_usb_driver); -} - -module_init(if_usb_init_module); -module_exit(if_usb_exit_module); - -MODULE_DESCRIPTION("8388 USB WLAN Thinfirm Driver"); -MODULE_AUTHOR("Cozybit Inc."); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/libertas_tf/if_usb.h b/drivers/net/wireless/libertas_tf/if_usb.h deleted file mode 100644 index 6fa5b3f59efe..000000000000 --- a/drivers/net/wireless/libertas_tf/if_usb.h +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2008, cozybit Inc. - * Copyright (C) 2003-2006, Marvell International Ltd. - * - * 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. - */ -#include -#include - -struct lbtf_private; - -/** - * This file contains definition for USB interface. - */ -#define CMD_TYPE_REQUEST 0xF00DFACE -#define CMD_TYPE_DATA 0xBEADC0DE -#define CMD_TYPE_INDICATION 0xBEEFFACE - -#define BOOT_CMD_FW_BY_USB 0x01 -#define BOOT_CMD_FW_IN_EEPROM 0x02 -#define BOOT_CMD_UPDATE_BOOT2 0x03 -#define BOOT_CMD_UPDATE_FW 0x04 -#define BOOT_CMD_MAGIC_NUMBER 0x4C56524D /* LVRM */ - -struct bootcmd { - __le32 magic; - uint8_t cmd; - uint8_t pad[11]; -}; - -#define BOOT_CMD_RESP_OK 0x0001 -#define BOOT_CMD_RESP_FAIL 0x0000 - -struct bootcmdresp { - __le32 magic; - uint8_t cmd; - uint8_t result; - uint8_t pad[2]; -}; - -/** USB card description structure*/ -struct if_usb_card { - struct usb_device *udev; - struct urb *rx_urb, *tx_urb, *cmd_urb; - struct lbtf_private *priv; - - struct sk_buff *rx_skb; - - uint8_t ep_in; - uint8_t ep_out; - - int8_t bootcmdresp; - - int ep_in_size; - - void *ep_out_buf; - int ep_out_size; - - const struct firmware *fw; - struct timer_list fw_timeout; - wait_queue_head_t fw_wq; - uint32_t fwseqnum; - uint32_t totalbytes; - uint32_t fwlastblksent; - uint8_t CRC_OK; - uint8_t fwdnldover; - uint8_t fwfinalblk; - - __le16 boot2_version; -}; - -/** fwheader */ -struct fwheader { - __le32 dnldcmd; - __le32 baseaddr; - __le32 datalength; - __le32 CRC; -}; - -#define FW_MAX_DATA_BLK_SIZE 600 -/** FWData */ -struct fwdata { - struct fwheader hdr; - __le32 seqnum; - uint8_t data[0]; -}; - -/** fwsyncheader */ -struct fwsyncheader { - __le32 cmd; - __le32 seqnum; -}; - -#define FW_HAS_DATA_TO_RECV 0x00000001 -#define FW_HAS_LAST_BLOCK 0x00000004 diff --git a/drivers/net/wireless/libertas_tf/libertas_tf.h b/drivers/net/wireless/libertas_tf/libertas_tf.h deleted file mode 100644 index 4cc42dd5a005..000000000000 --- a/drivers/net/wireless/libertas_tf/libertas_tf.h +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright (C) 2008, cozybit Inc. - * Copyright (C) 2007, Red Hat, Inc. - * Copyright (C) 2003-2006, Marvell International Ltd. - * - * 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. - */ -#include -#include -#include -#include - -#ifndef DRV_NAME -#define DRV_NAME "libertas_tf" -#endif - -#define MRVL_DEFAULT_RETRIES 9 -#define MRVL_PER_PACKET_RATE 0x10 -#define MRVL_MAX_BCN_SIZE 440 -#define CMD_OPTION_WAITFORRSP 0x0002 - -/* Return command are almost always the same as the host command, but with - * bit 15 set high. There are a few exceptions, though... - */ -#define CMD_RET(cmd) (0x8000 | cmd) - -/* Command codes */ -#define CMD_GET_HW_SPEC 0x0003 -#define CMD_802_11_RESET 0x0005 -#define CMD_MAC_MULTICAST_ADR 0x0010 -#define CMD_802_11_RADIO_CONTROL 0x001c -#define CMD_802_11_RF_CHANNEL 0x001d -#define CMD_802_11_RF_TX_POWER 0x001e -#define CMD_MAC_CONTROL 0x0028 -#define CMD_802_11_MAC_ADDRESS 0x004d -#define CMD_SET_BOOT2_VER 0x00a5 -#define CMD_802_11_BEACON_CTRL 0x00b0 -#define CMD_802_11_BEACON_SET 0x00cb -#define CMD_802_11_SET_MODE 0x00cc -#define CMD_802_11_SET_BSSID 0x00cd - -#define CMD_ACT_GET 0x0000 -#define CMD_ACT_SET 0x0001 - -/* Define action or option for CMD_802_11_RESET */ -#define CMD_ACT_HALT 0x0003 - -/* Define action or option for CMD_MAC_CONTROL */ -#define CMD_ACT_MAC_RX_ON 0x0001 -#define CMD_ACT_MAC_TX_ON 0x0002 -#define CMD_ACT_MAC_MULTICAST_ENABLE 0x0020 -#define CMD_ACT_MAC_BROADCAST_ENABLE 0x0040 -#define CMD_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 -#define CMD_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 - -/* Define action or option for CMD_802_11_RADIO_CONTROL */ -#define CMD_TYPE_AUTO_PREAMBLE 0x0001 -#define CMD_TYPE_SHORT_PREAMBLE 0x0002 -#define CMD_TYPE_LONG_PREAMBLE 0x0003 - -#define TURN_ON_RF 0x01 -#define RADIO_ON 0x01 -#define RADIO_OFF 0x00 - -#define SET_AUTO_PREAMBLE 0x05 -#define SET_SHORT_PREAMBLE 0x03 -#define SET_LONG_PREAMBLE 0x01 - -/* Define action or option for CMD_802_11_RF_CHANNEL */ -#define CMD_OPT_802_11_RF_CHANNEL_GET 0x00 -#define CMD_OPT_802_11_RF_CHANNEL_SET 0x01 - -/* Codes for CMD_802_11_SET_MODE */ -enum lbtf_mode { - LBTF_PASSIVE_MODE, - LBTF_STA_MODE, - LBTF_AP_MODE, -}; - -/** Card Event definition */ -#define MACREG_INT_CODE_FIRMWARE_READY 48 -/** Buffer Constants */ - -/* The size of SQ memory PPA, DPA are 8 DWORDs, that keep the physical -* addresses of TxPD buffers. Station has only 8 TxPD available, Whereas -* driver has more local TxPDs. Each TxPD on the host memory is associated -* with a Tx control node. The driver maintains 8 RxPD descriptors for -* station firmware to store Rx packet information. -* -* Current version of MAC has a 32x6 multicast address buffer. -* -* 802.11b can have up to 14 channels, the driver keeps the -* BSSID(MAC address) of each APs or Ad hoc stations it has sensed. -*/ - -#define MRVDRV_MAX_MULTICAST_LIST_SIZE 32 -#define LBS_NUM_CMD_BUFFERS 10 -#define LBS_CMD_BUFFER_SIZE (2 * 1024) -#define MRVDRV_MAX_CHANNEL_SIZE 14 -#define MRVDRV_SNAP_HEADER_LEN 8 - -#define LBS_UPLD_SIZE 2312 -#define DEV_NAME_LEN 32 - -/** Misc constants */ -/* This section defines 802.11 specific contants */ - -#define MRVDRV_MAX_REGION_CODE 6 -/** - * the table to keep region code - */ -#define LBTF_REGDOMAIN_US 0x10 -#define LBTF_REGDOMAIN_CA 0x20 -#define LBTF_REGDOMAIN_EU 0x30 -#define LBTF_REGDOMAIN_SP 0x31 -#define LBTF_REGDOMAIN_FR 0x32 -#define LBTF_REGDOMAIN_JP 0x40 - -#define SBI_EVENT_CAUSE_SHIFT 3 - -/** RxPD status */ - -#define MRVDRV_RXPD_STATUS_OK 0x0001 - - -/* This is for firmware specific length */ -#define EXTRA_LEN 36 - -#define MRVDRV_ETH_TX_PACKET_BUFFER_SIZE \ - (ETH_FRAME_LEN + sizeof(struct txpd) + EXTRA_LEN) - -#define MRVDRV_ETH_RX_PACKET_BUFFER_SIZE \ - (ETH_FRAME_LEN + sizeof(struct rxpd) \ - + MRVDRV_SNAP_HEADER_LEN + EXTRA_LEN) - -#define CMD_F_HOSTCMD (1 << 0) -#define FW_CAPINFO_WPA (1 << 0) - -#define RF_ANTENNA_1 0x1 -#define RF_ANTENNA_2 0x2 -#define RF_ANTENNA_AUTO 0xFFFF - -#define LBTF_EVENT_BCN_SENT 55 - -/** Global Variable Declaration */ -/** mv_ms_type */ -enum mv_ms_type { - MVMS_DAT = 0, - MVMS_CMD = 1, - MVMS_TXDONE = 2, - MVMS_EVENT -}; - -extern struct workqueue_struct *lbtf_wq; - -struct lbtf_private; - -struct lbtf_offset_value { - u32 offset; - u32 value; -}; - -struct channel_range { - u8 regdomain; - u8 start; - u8 end; /* exclusive (channel must be less than end) */ -}; - -struct if_usb_card; - -/** Private structure for the MV device */ -struct lbtf_private { - void *card; - struct ieee80211_hw *hw; - - /* Command response buffer */ - u8 cmd_resp_buff[LBS_UPLD_SIZE]; - /* Download sent: - bit0 1/0=data_sent/data_tx_done, - bit1 1/0=cmd_sent/cmd_tx_done, - all other bits reserved 0 */ - struct ieee80211_vif *vif; - - struct work_struct cmd_work; - struct work_struct tx_work; - /** Hardware access */ - int (*hw_host_to_card) (struct lbtf_private *priv, u8 type, u8 *payload, u16 nb); - int (*hw_prog_firmware) (struct if_usb_card *cardp); - int (*hw_reset_device) (struct if_usb_card *cardp); - - - /** Wlan adapter data structure*/ - /** STATUS variables */ - u32 fwrelease; - u32 fwcapinfo; - /* protected with big lock */ - - struct mutex lock; - - /** command-related variables */ - u16 seqnum; - /* protected by big lock */ - - struct cmd_ctrl_node *cmd_array; - /** Current command */ - struct cmd_ctrl_node *cur_cmd; - /** command Queues */ - /** Free command buffers */ - struct list_head cmdfreeq; - /** Pending command buffers */ - struct list_head cmdpendingq; - - /** spin locks */ - spinlock_t driver_lock; - - /** Timers */ - struct timer_list command_timer; - int nr_retries; - int cmd_timed_out; - - u8 cmd_response_rxed; - - /** capability Info used in Association, start, join */ - u16 capability; - - /** MAC address information */ - u8 current_addr[ETH_ALEN]; - u8 multicastlist[MRVDRV_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; - u32 nr_of_multicastmacaddr; - int cur_freq; - - struct sk_buff *skb_to_tx; - struct sk_buff *tx_skb; - - /** NIC Operation characteristics */ - u16 mac_control; - u16 regioncode; - struct channel_range range; - - u8 radioon; - u32 preamble; - - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_supported_band band; - struct lbtf_offset_value offsetvalue; - - u8 fw_ready; - u8 surpriseremoved; - struct sk_buff_head bc_ps_buf; -}; - -/* 802.11-related definitions */ - -/* TxPD descriptor */ -struct txpd { - /* Current Tx packet status */ - __le32 tx_status; - /* Tx control */ - __le32 tx_control; - __le32 tx_packet_location; - /* Tx packet length */ - __le16 tx_packet_length; - /* First 2 byte of destination MAC address */ - u8 tx_dest_addr_high[2]; - /* Last 4 byte of destination MAC address */ - u8 tx_dest_addr_low[4]; - /* Pkt Priority */ - u8 priority; - /* Pkt Trasnit Power control */ - u8 powermgmt; - /* Time the packet has been queued in the driver (units = 2ms) */ - u8 pktdelay_2ms; - /* reserved */ - u8 reserved1; -}; - -/* RxPD Descriptor */ -struct rxpd { - /* Current Rx packet status */ - __le16 status; - - /* SNR */ - u8 snr; - - /* Tx control */ - u8 rx_control; - - /* Pkt length */ - __le16 pkt_len; - - /* Noise Floor */ - u8 nf; - - /* Rx Packet Rate */ - u8 rx_rate; - - /* Pkt addr */ - __le32 pkt_ptr; - - /* Next Rx RxPD addr */ - __le32 next_rxpd_ptr; - - /* Pkt Priority */ - u8 priority; - u8 reserved[3]; -}; - -struct cmd_header { - __le16 command; - __le16 size; - __le16 seqnum; - __le16 result; -} __attribute__ ((packed)); - -struct cmd_ctrl_node { - struct list_head list; - int result; - /* command response */ - int (*callback)(struct lbtf_private *, - unsigned long, struct cmd_header *); - unsigned long callback_arg; - /* command data */ - struct cmd_header *cmdbuf; - /* wait queue */ - u16 cmdwaitqwoken; - wait_queue_head_t cmdwait_q; -}; - -/* - * Define data structure for CMD_GET_HW_SPEC - * This structure defines the response for the GET_HW_SPEC command - */ -struct cmd_ds_get_hw_spec { - struct cmd_header hdr; - - /* HW Interface version number */ - __le16 hwifversion; - /* HW version number */ - __le16 version; - /* Max number of TxPD FW can handle */ - __le16 nr_txpd; - /* Max no of Multicast address */ - __le16 nr_mcast_adr; - /* MAC address */ - u8 permanentaddr[6]; - - /* region Code */ - __le16 regioncode; - - /* Number of antenna used */ - __le16 nr_antenna; - - /* FW release number, example 0x01030304 = 2.3.4p1 */ - __le32 fwrelease; - - /* Base Address of TxPD queue */ - __le32 wcb_base; - /* Read Pointer of RxPd queue */ - __le32 rxpd_rdptr; - - /* Write Pointer of RxPd queue */ - __le32 rxpd_wrptr; - - /*FW/HW capability */ - __le32 fwcapinfo; -} __attribute__ ((packed)); - -struct cmd_ds_mac_control { - struct cmd_header hdr; - __le16 action; - u16 reserved; -}; - -struct cmd_ds_802_11_mac_address { - struct cmd_header hdr; - - __le16 action; - uint8_t macadd[ETH_ALEN]; -}; - -struct cmd_ds_mac_multicast_addr { - struct cmd_header hdr; - - __le16 action; - __le16 nr_of_adrs; - u8 maclist[ETH_ALEN * MRVDRV_MAX_MULTICAST_LIST_SIZE]; -}; - -struct cmd_ds_set_mode { - struct cmd_header hdr; - - __le16 mode; -}; - -struct cmd_ds_set_bssid { - struct cmd_header hdr; - - u8 bssid[6]; - u8 activate; -}; - -struct cmd_ds_802_11_radio_control { - struct cmd_header hdr; - - __le16 action; - __le16 control; -}; - - -struct cmd_ds_802_11_rf_channel { - struct cmd_header hdr; - - __le16 action; - __le16 channel; - __le16 rftype; /* unused */ - __le16 reserved; /* unused */ - u8 channellist[32]; /* unused */ -}; - -struct cmd_ds_set_boot2_ver { - struct cmd_header hdr; - - __le16 action; - __le16 version; -}; - -struct cmd_ds_802_11_reset { - struct cmd_header hdr; - - __le16 action; -}; - -struct cmd_ds_802_11_beacon_control { - struct cmd_header hdr; - - __le16 action; - __le16 beacon_enable; - __le16 beacon_period; -}; - -struct cmd_ds_802_11_beacon_set { - struct cmd_header hdr; - - __le16 len; - u8 beacon[MRVL_MAX_BCN_SIZE]; -}; - -struct lbtf_private; -struct cmd_ctrl_node; - -/** Function Prototype Declaration */ -void lbtf_set_mac_control(struct lbtf_private *priv); - -int lbtf_free_cmd_buffer(struct lbtf_private *priv); - -int lbtf_allocate_cmd_buffer(struct lbtf_private *priv); -int lbtf_execute_next_command(struct lbtf_private *priv); -int lbtf_set_radio_control(struct lbtf_private *priv); -int lbtf_update_hw_spec(struct lbtf_private *priv); -int lbtf_cmd_set_mac_multicast_addr(struct lbtf_private *priv); -void lbtf_set_mode(struct lbtf_private *priv, enum lbtf_mode mode); -void lbtf_set_bssid(struct lbtf_private *priv, bool activate, const u8 *bssid); -int lbtf_set_mac_address(struct lbtf_private *priv, uint8_t *mac_addr); - -int lbtf_set_channel(struct lbtf_private *priv, u8 channel); - -int lbtf_beacon_set(struct lbtf_private *priv, struct sk_buff *beacon); -int lbtf_beacon_ctrl(struct lbtf_private *priv, bool beacon_enable, - int beacon_int); - - -int lbtf_process_rx_command(struct lbtf_private *priv); -void lbtf_complete_command(struct lbtf_private *priv, struct cmd_ctrl_node *cmd, - int result); -void lbtf_cmd_response_rx(struct lbtf_private *priv); - -/* main.c */ -struct chan_freq_power *lbtf_get_region_cfp_table(u8 region, - int *cfp_no); -struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev); -int lbtf_remove_card(struct lbtf_private *priv); -int lbtf_start_card(struct lbtf_private *priv); -int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb); -void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail); -void lbtf_bcn_sent(struct lbtf_private *priv); - -/* support functions for cmd.c */ -/* lbtf_cmd() infers the size of the buffer to copy data back into, from - the size of the target of the pointer. Since the command to be sent - may often be smaller, that size is set in cmd->size by the caller.*/ -#define lbtf_cmd(priv, cmdnr, cmd, cb, cb_arg) ({ \ - uint16_t __sz = le16_to_cpu((cmd)->hdr.size); \ - (cmd)->hdr.size = cpu_to_le16(sizeof(*(cmd))); \ - __lbtf_cmd(priv, cmdnr, &(cmd)->hdr, __sz, cb, cb_arg); \ -}) - -#define lbtf_cmd_with_response(priv, cmdnr, cmd) \ - lbtf_cmd(priv, cmdnr, cmd, lbtf_cmd_copyback, (unsigned long) (cmd)) - -void lbtf_cmd_async(struct lbtf_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size); - -int __lbtf_cmd(struct lbtf_private *priv, uint16_t command, - struct cmd_header *in_cmd, int in_cmd_size, - int (*callback)(struct lbtf_private *, unsigned long, - struct cmd_header *), - unsigned long callback_arg); - -int lbtf_cmd_copyback(struct lbtf_private *priv, unsigned long extra, - struct cmd_header *resp); diff --git a/drivers/net/wireless/libertas_tf/main.c b/drivers/net/wireless/libertas_tf/main.c deleted file mode 100644 index 019431d2f8a9..000000000000 --- a/drivers/net/wireless/libertas_tf/main.c +++ /dev/null @@ -1,668 +0,0 @@ -/* - * Copyright (C) 2008, cozybit Inc. - * Copyright (C) 2003-2006, Marvell International Ltd. - * - * 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. - */ -#include "libertas_tf.h" -#include "linux/etherdevice.h" - -#define DRIVER_RELEASE_VERSION "004.p0" -/* thinfirm version: 5.132.X.pX */ -#define LBTF_FW_VER_MIN 0x05840300 -#define LBTF_FW_VER_MAX 0x0584ffff -#define QOS_CONTROL_LEN 2 - -static const char lbtf_driver_version[] = "THINFIRM-USB8388-" DRIVER_RELEASE_VERSION; -struct workqueue_struct *lbtf_wq; - -static const struct ieee80211_channel lbtf_channels[] = { - { .center_freq = 2412, .hw_value = 1 }, - { .center_freq = 2417, .hw_value = 2 }, - { .center_freq = 2422, .hw_value = 3 }, - { .center_freq = 2427, .hw_value = 4 }, - { .center_freq = 2432, .hw_value = 5 }, - { .center_freq = 2437, .hw_value = 6 }, - { .center_freq = 2442, .hw_value = 7 }, - { .center_freq = 2447, .hw_value = 8 }, - { .center_freq = 2452, .hw_value = 9 }, - { .center_freq = 2457, .hw_value = 10 }, - { .center_freq = 2462, .hw_value = 11 }, - { .center_freq = 2467, .hw_value = 12 }, - { .center_freq = 2472, .hw_value = 13 }, - { .center_freq = 2484, .hw_value = 14 }, -}; - -/* This table contains the hardware specific values for the modulation rates. */ -static const struct ieee80211_rate lbtf_rates[] = { - { .bitrate = 10, - .hw_value = 0, }, - { .bitrate = 20, - .hw_value = 1, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, - .hw_value = 2, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, - .hw_value = 3, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, - .hw_value = 5, - .flags = 0 }, - { .bitrate = 90, - .hw_value = 6, - .flags = 0 }, - { .bitrate = 120, - .hw_value = 7, - .flags = 0 }, - { .bitrate = 180, - .hw_value = 8, - .flags = 0 }, - { .bitrate = 240, - .hw_value = 9, - .flags = 0 }, - { .bitrate = 360, - .hw_value = 10, - .flags = 0 }, - { .bitrate = 480, - .hw_value = 11, - .flags = 0 }, - { .bitrate = 540, - .hw_value = 12, - .flags = 0 }, -}; - -static void lbtf_cmd_work(struct work_struct *work) -{ - struct lbtf_private *priv = container_of(work, struct lbtf_private, - cmd_work); - spin_lock_irq(&priv->driver_lock); - /* command response? */ - if (priv->cmd_response_rxed) { - priv->cmd_response_rxed = 0; - spin_unlock_irq(&priv->driver_lock); - lbtf_process_rx_command(priv); - spin_lock_irq(&priv->driver_lock); - } - - if (priv->cmd_timed_out && priv->cur_cmd) { - struct cmd_ctrl_node *cmdnode = priv->cur_cmd; - - if (++priv->nr_retries > 10) { - lbtf_complete_command(priv, cmdnode, - -ETIMEDOUT); - priv->nr_retries = 0; - } else { - priv->cur_cmd = NULL; - - /* Stick it back at the _top_ of the pending - * queue for immediate resubmission */ - list_add(&cmdnode->list, &priv->cmdpendingq); - } - } - priv->cmd_timed_out = 0; - spin_unlock_irq(&priv->driver_lock); - - if (!priv->fw_ready) - return; - /* Execute the next command */ - if (!priv->cur_cmd) - lbtf_execute_next_command(priv); -} - -/** - * lbtf_setup_firmware: initialize firmware. - * - * @priv A pointer to struct lbtf_private structure - * - * Returns: 0 on success. - */ -static int lbtf_setup_firmware(struct lbtf_private *priv) -{ - int ret = -1; - - /* - * Read priv address from HW - */ - memset(priv->current_addr, 0xff, ETH_ALEN); - ret = lbtf_update_hw_spec(priv); - if (ret) { - ret = -1; - goto done; - } - - lbtf_set_mac_control(priv); - lbtf_set_radio_control(priv); - - ret = 0; -done: - return ret; -} - -/** - * This function handles the timeout of command sending. - * It will re-send the same command again. - */ -static void command_timer_fn(unsigned long data) -{ - struct lbtf_private *priv = (struct lbtf_private *)data; - unsigned long flags; - - spin_lock_irqsave(&priv->driver_lock, flags); - - if (!priv->cur_cmd) { - printk(KERN_DEBUG "libertastf: command timer expired; " - "no pending command\n"); - goto out; - } - - printk(KERN_DEBUG "libertas: command %x timed out\n", - le16_to_cpu(priv->cur_cmd->cmdbuf->command)); - - priv->cmd_timed_out = 1; - queue_work(lbtf_wq, &priv->cmd_work); -out: - spin_unlock_irqrestore(&priv->driver_lock, flags); -} - -static int lbtf_init_adapter(struct lbtf_private *priv) -{ - memset(priv->current_addr, 0xff, ETH_ALEN); - mutex_init(&priv->lock); - - priv->vif = NULL; - setup_timer(&priv->command_timer, command_timer_fn, - (unsigned long)priv); - - INIT_LIST_HEAD(&priv->cmdfreeq); - INIT_LIST_HEAD(&priv->cmdpendingq); - - spin_lock_init(&priv->driver_lock); - - /* Allocate the command buffers */ - if (lbtf_allocate_cmd_buffer(priv)) - return -1; - - return 0; -} - -static void lbtf_free_adapter(struct lbtf_private *priv) -{ - lbtf_free_cmd_buffer(priv); - del_timer(&priv->command_timer); -} - -static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct lbtf_private *priv = hw->priv; - - priv->skb_to_tx = skb; - queue_work(lbtf_wq, &priv->tx_work); - /* - * queue will be restarted when we receive transmission feedback if - * there are no buffered multicast frames to send - */ - ieee80211_stop_queues(priv->hw); - return NETDEV_TX_OK; -} - -static void lbtf_tx_work(struct work_struct *work) -{ - struct lbtf_private *priv = container_of(work, struct lbtf_private, - tx_work); - unsigned int len; - struct ieee80211_tx_info *info; - struct txpd *txpd; - struct sk_buff *skb = NULL; - int err; - - if ((priv->vif->type == NL80211_IFTYPE_AP) && - (!skb_queue_empty(&priv->bc_ps_buf))) - skb = skb_dequeue(&priv->bc_ps_buf); - else if (priv->skb_to_tx) { - skb = priv->skb_to_tx; - priv->skb_to_tx = NULL; - } else - return; - - len = skb->len; - info = IEEE80211_SKB_CB(skb); - txpd = (struct txpd *) skb_push(skb, sizeof(struct txpd)); - - if (priv->surpriseremoved) { - dev_kfree_skb_any(skb); - return; - } - - memset(txpd, 0, sizeof(struct txpd)); - /* Activate per-packet rate selection */ - txpd->tx_control |= cpu_to_le32(MRVL_PER_PACKET_RATE | - ieee80211_get_tx_rate(priv->hw, info)->hw_value); - - /* copy destination address from 802.11 header */ - memcpy(txpd->tx_dest_addr_high, skb->data + sizeof(struct txpd) + 4, - ETH_ALEN); - txpd->tx_packet_length = cpu_to_le16(len); - txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); - BUG_ON(priv->tx_skb); - spin_lock_irq(&priv->driver_lock); - priv->tx_skb = skb; - err = priv->hw_host_to_card(priv, MVMS_DAT, skb->data, skb->len); - spin_unlock_irq(&priv->driver_lock); - if (err) { - dev_kfree_skb_any(skb); - priv->tx_skb = NULL; - } -} - -static int lbtf_op_start(struct ieee80211_hw *hw) -{ - struct lbtf_private *priv = hw->priv; - void *card = priv->card; - int ret = -1; - - if (!priv->fw_ready) - /* Upload firmware */ - if (priv->hw_prog_firmware(card)) - goto err_prog_firmware; - - /* poke the firmware */ - priv->capability = WLAN_CAPABILITY_SHORT_PREAMBLE; - priv->radioon = RADIO_ON; - priv->mac_control = CMD_ACT_MAC_RX_ON | CMD_ACT_MAC_TX_ON; - ret = lbtf_setup_firmware(priv); - if (ret) - goto err_prog_firmware; - - if ((priv->fwrelease < LBTF_FW_VER_MIN) || - (priv->fwrelease > LBTF_FW_VER_MAX)) { - ret = -1; - goto err_prog_firmware; - } - - printk(KERN_INFO "libertastf: Marvell WLAN 802.11 thinfirm adapter\n"); - return 0; - -err_prog_firmware: - priv->hw_reset_device(card); - return ret; -} - -static void lbtf_op_stop(struct ieee80211_hw *hw) -{ - struct lbtf_private *priv = hw->priv; - unsigned long flags; - struct sk_buff *skb; - - struct cmd_ctrl_node *cmdnode; - /* Flush pending command nodes */ - spin_lock_irqsave(&priv->driver_lock, flags); - list_for_each_entry(cmdnode, &priv->cmdpendingq, list) { - cmdnode->result = -ENOENT; - cmdnode->cmdwaitqwoken = 1; - wake_up_interruptible(&cmdnode->cmdwait_q); - } - - spin_unlock_irqrestore(&priv->driver_lock, flags); - cancel_work_sync(&priv->cmd_work); - cancel_work_sync(&priv->tx_work); - while ((skb = skb_dequeue(&priv->bc_ps_buf))) - dev_kfree_skb_any(skb); - priv->radioon = RADIO_OFF; - lbtf_set_radio_control(priv); - - return; -} - -static int lbtf_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct lbtf_private *priv = hw->priv; - if (priv->vif != NULL) - return -EOPNOTSUPP; - - priv->vif = conf->vif; - switch (conf->type) { - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_AP: - lbtf_set_mode(priv, LBTF_AP_MODE); - break; - case NL80211_IFTYPE_STATION: - lbtf_set_mode(priv, LBTF_STA_MODE); - break; - default: - priv->vif = NULL; - return -EOPNOTSUPP; - } - lbtf_set_mac_address(priv, (u8 *) conf->mac_addr); - return 0; -} - -static void lbtf_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct lbtf_private *priv = hw->priv; - - if (priv->vif->type == NL80211_IFTYPE_AP || - priv->vif->type == NL80211_IFTYPE_MESH_POINT) - lbtf_beacon_ctrl(priv, 0, 0); - lbtf_set_mode(priv, LBTF_PASSIVE_MODE); - lbtf_set_bssid(priv, 0, NULL); - priv->vif = NULL; -} - -static int lbtf_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct lbtf_private *priv = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - if (conf->channel->center_freq != priv->cur_freq) { - priv->cur_freq = conf->channel->center_freq; - lbtf_set_channel(priv, conf->channel->hw_value); - } - return 0; -} - -static u64 lbtf_op_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - struct lbtf_private *priv = hw->priv; - int i; - - if (!mc_count || mc_count > MRVDRV_MAX_MULTICAST_LIST_SIZE) - return mc_count; - - priv->nr_of_multicastmacaddr = mc_count; - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - memcpy(&priv->multicastlist[i], mclist->da_addr, - ETH_ALEN); - mclist = mclist->next; - } - - return mc_count; -} - -#define SUPPORTED_FIF_FLAGS (FIF_PROMISC_IN_BSS | FIF_ALLMULTI) -static void lbtf_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast) -{ - struct lbtf_private *priv = hw->priv; - int old_mac_control = priv->mac_control; - changed_flags &= SUPPORTED_FIF_FLAGS; - *new_flags &= SUPPORTED_FIF_FLAGS; - - if (!changed_flags) - return; - - if (*new_flags & (FIF_PROMISC_IN_BSS)) - priv->mac_control |= CMD_ACT_MAC_PROMISCUOUS_ENABLE; - else - priv->mac_control &= ~CMD_ACT_MAC_PROMISCUOUS_ENABLE; - if (*new_flags & (FIF_ALLMULTI) || - multicast > MRVDRV_MAX_MULTICAST_LIST_SIZE) { - priv->mac_control |= CMD_ACT_MAC_ALL_MULTICAST_ENABLE; - priv->mac_control &= ~CMD_ACT_MAC_MULTICAST_ENABLE; - } else if (multicast) { - priv->mac_control |= CMD_ACT_MAC_MULTICAST_ENABLE; - priv->mac_control &= ~CMD_ACT_MAC_ALL_MULTICAST_ENABLE; - lbtf_cmd_set_mac_multicast_addr(priv); - } else { - priv->mac_control &= ~(CMD_ACT_MAC_MULTICAST_ENABLE | - CMD_ACT_MAC_ALL_MULTICAST_ENABLE); - if (priv->nr_of_multicastmacaddr) { - priv->nr_of_multicastmacaddr = 0; - lbtf_cmd_set_mac_multicast_addr(priv); - } - } - - - if (priv->mac_control != old_mac_control) - lbtf_set_mac_control(priv); -} - -static void lbtf_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct lbtf_private *priv = hw->priv; - struct sk_buff *beacon; - - if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_INT)) { - switch (priv->vif->type) { - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - beacon = ieee80211_beacon_get(hw, vif); - if (beacon) { - lbtf_beacon_set(priv, beacon); - kfree_skb(beacon); - lbtf_beacon_ctrl(priv, 1, - bss_conf->beacon_int); - } - break; - default: - break; - } - } - - if (changes & BSS_CHANGED_BSSID) { - bool activate = !is_zero_ether_addr(bss_conf->bssid); - lbtf_set_bssid(priv, activate, bss_conf->bssid); - } - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - if (bss_conf->use_short_preamble) - priv->preamble = CMD_TYPE_SHORT_PREAMBLE; - else - priv->preamble = CMD_TYPE_LONG_PREAMBLE; - lbtf_set_radio_control(priv); - } -} - -static const struct ieee80211_ops lbtf_ops = { - .tx = lbtf_op_tx, - .start = lbtf_op_start, - .stop = lbtf_op_stop, - .add_interface = lbtf_op_add_interface, - .remove_interface = lbtf_op_remove_interface, - .config = lbtf_op_config, - .prepare_multicast = lbtf_op_prepare_multicast, - .configure_filter = lbtf_op_configure_filter, - .bss_info_changed = lbtf_op_bss_info_changed, -}; - -int lbtf_rx(struct lbtf_private *priv, struct sk_buff *skb) -{ - struct ieee80211_rx_status stats; - struct rxpd *prxpd; - int need_padding; - unsigned int flags; - struct ieee80211_hdr *hdr; - - prxpd = (struct rxpd *) skb->data; - - stats.flag = 0; - if (!(prxpd->status & cpu_to_le16(MRVDRV_RXPD_STATUS_OK))) - stats.flag |= RX_FLAG_FAILED_FCS_CRC; - stats.freq = priv->cur_freq; - stats.band = IEEE80211_BAND_2GHZ; - stats.signal = prxpd->snr; - stats.noise = prxpd->nf; - stats.qual = prxpd->snr - prxpd->nf; - /* Marvell rate index has a hole at value 4 */ - if (prxpd->rx_rate > 4) - --prxpd->rx_rate; - stats.rate_idx = prxpd->rx_rate; - skb_pull(skb, sizeof(struct rxpd)); - - hdr = (struct ieee80211_hdr *)skb->data; - flags = le32_to_cpu(*(__le32 *)(skb->data + 4)); - - need_padding = ieee80211_is_data_qos(hdr->frame_control); - need_padding ^= ieee80211_has_a4(hdr->frame_control); - need_padding ^= ieee80211_is_data_qos(hdr->frame_control) && - (*ieee80211_get_qos_ctl(hdr) & - IEEE80211_QOS_CONTROL_A_MSDU_PRESENT); - - if (need_padding) { - memmove(skb->data + 2, skb->data, skb->len); - skb_reserve(skb, 2); - } - - memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); - ieee80211_rx_irqsafe(priv->hw, skb); - return 0; -} -EXPORT_SYMBOL_GPL(lbtf_rx); - -/** - * lbtf_add_card: Add and initialize the card, no fw upload yet. - * - * @card A pointer to card - * - * Returns: pointer to struct lbtf_priv. - */ -struct lbtf_private *lbtf_add_card(void *card, struct device *dmdev) -{ - struct ieee80211_hw *hw; - struct lbtf_private *priv = NULL; - - hw = ieee80211_alloc_hw(sizeof(struct lbtf_private), &lbtf_ops); - if (!hw) - goto done; - - priv = hw->priv; - if (lbtf_init_adapter(priv)) - goto err_init_adapter; - - priv->hw = hw; - priv->card = card; - priv->tx_skb = NULL; - - hw->queues = 1; - hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING; - hw->extra_tx_headroom = sizeof(struct txpd); - memcpy(priv->channels, lbtf_channels, sizeof(lbtf_channels)); - memcpy(priv->rates, lbtf_rates, sizeof(lbtf_rates)); - priv->band.n_bitrates = ARRAY_SIZE(lbtf_rates); - priv->band.bitrates = priv->rates; - priv->band.n_channels = ARRAY_SIZE(lbtf_channels); - priv->band.channels = priv->channels; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - skb_queue_head_init(&priv->bc_ps_buf); - - SET_IEEE80211_DEV(hw, dmdev); - - INIT_WORK(&priv->cmd_work, lbtf_cmd_work); - INIT_WORK(&priv->tx_work, lbtf_tx_work); - if (ieee80211_register_hw(hw)) - goto err_init_adapter; - - goto done; - -err_init_adapter: - lbtf_free_adapter(priv); - ieee80211_free_hw(hw); - priv = NULL; - -done: - return priv; -} -EXPORT_SYMBOL_GPL(lbtf_add_card); - - -int lbtf_remove_card(struct lbtf_private *priv) -{ - struct ieee80211_hw *hw = priv->hw; - - priv->surpriseremoved = 1; - del_timer(&priv->command_timer); - lbtf_free_adapter(priv); - priv->hw = NULL; - ieee80211_unregister_hw(hw); - ieee80211_free_hw(hw); - - return 0; -} -EXPORT_SYMBOL_GPL(lbtf_remove_card); - -void lbtf_send_tx_feedback(struct lbtf_private *priv, u8 retrycnt, u8 fail) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(priv->tx_skb); - - ieee80211_tx_info_clear_status(info); - /* - * Commented out, otherwise we never go beyond 1Mbit/s using mac80211 - * default pid rc algorithm. - * - * info->status.retry_count = MRVL_DEFAULT_RETRIES - retrycnt; - */ - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && !fail) - info->flags |= IEEE80211_TX_STAT_ACK; - skb_pull(priv->tx_skb, sizeof(struct txpd)); - ieee80211_tx_status_irqsafe(priv->hw, priv->tx_skb); - priv->tx_skb = NULL; - if (!priv->skb_to_tx && skb_queue_empty(&priv->bc_ps_buf)) - ieee80211_wake_queues(priv->hw); - else - queue_work(lbtf_wq, &priv->tx_work); -} -EXPORT_SYMBOL_GPL(lbtf_send_tx_feedback); - -void lbtf_bcn_sent(struct lbtf_private *priv) -{ - struct sk_buff *skb = NULL; - - if (priv->vif->type != NL80211_IFTYPE_AP) - return; - - if (skb_queue_empty(&priv->bc_ps_buf)) { - bool tx_buff_bc = 0; - - while ((skb = ieee80211_get_buffered_bc(priv->hw, priv->vif))) { - skb_queue_tail(&priv->bc_ps_buf, skb); - tx_buff_bc = 1; - } - if (tx_buff_bc) { - ieee80211_stop_queues(priv->hw); - queue_work(lbtf_wq, &priv->tx_work); - } - } - - skb = ieee80211_beacon_get(priv->hw, priv->vif); - - if (skb) { - lbtf_beacon_set(priv, skb); - kfree_skb(skb); - } -} -EXPORT_SYMBOL_GPL(lbtf_bcn_sent); - -static int __init lbtf_init_module(void) -{ - lbtf_wq = create_workqueue("libertastf"); - if (lbtf_wq == NULL) { - printk(KERN_ERR "libertastf: couldn't create workqueue\n"); - return -ENOMEM; - } - return 0; -} - -static void __exit lbtf_exit_module(void) -{ - destroy_workqueue(lbtf_wq); -} - -module_init(lbtf_init_module); -module_exit(lbtf_exit_module); - -MODULE_DESCRIPTION("Libertas WLAN Thinfirm Driver Library"); -MODULE_AUTHOR("Cozybit Inc."); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c deleted file mode 100644 index 38cfd79e0590..000000000000 --- a/drivers/net/wireless/mac80211_hwsim.c +++ /dev/null @@ -1,1257 +0,0 @@ -/* - * mac80211_hwsim - software simulator of 802.11 radio(s) for mac80211 - * Copyright (c) 2008, Jouni Malinen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* - * TODO: - * - IBSS mode simulation (Beacon transmission with competition for "air time") - * - RX filtering based on filter configuration (data->rx_filter) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Jouni Malinen"); -MODULE_DESCRIPTION("Software simulator of 802.11 radio(s) for mac80211"); -MODULE_LICENSE("GPL"); - -static int radios = 2; -module_param(radios, int, 0444); -MODULE_PARM_DESC(radios, "Number of simulated radios"); - -/** - * enum hwsim_regtest - the type of regulatory tests we offer - * - * These are the different values you can use for the regtest - * module parameter. This is useful to help test world roaming - * and the driver regulatory_hint() call and combinations of these. - * If you want to do specific alpha2 regulatory domain tests simply - * use the userspace regulatory request as that will be respected as - * well without the need of this module parameter. This is designed - * only for testing the driver regulatory request, world roaming - * and all possible combinations. - * - * @HWSIM_REGTEST_DISABLED: No regulatory tests are performed, - * this is the default value. - * @HWSIM_REGTEST_DRIVER_REG_FOLLOW: Used for testing the driver regulatory - * hint, only one driver regulatory hint will be sent as such the - * secondary radios are expected to follow. - * @HWSIM_REGTEST_DRIVER_REG_ALL: Used for testing the driver regulatory - * request with all radios reporting the same regulatory domain. - * @HWSIM_REGTEST_DIFF_COUNTRY: Used for testing the drivers calling - * different regulatory domains requests. Expected behaviour is for - * an intersection to occur but each device will still use their - * respective regulatory requested domains. Subsequent radios will - * use the resulting intersection. - * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We acomplish - * this by using a custom beacon-capable regulatory domain for the first - * radio. All other device world roam. - * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory - * domain requests. All radios will adhere to this custom world regulatory - * domain. - * @HWSIM_REGTEST_CUSTOM_WORLD_2: Used for testing 2 custom world regulatory - * domain requests. The first radio will adhere to the first custom world - * regulatory domain, the second one to the second custom world regulatory - * domain. All other devices will world roam. - * @HWSIM_REGTEST_STRICT_FOLLOW_: Used for testing strict regulatory domain - * settings, only the first radio will send a regulatory domain request - * and use strict settings. The rest of the radios are expected to follow. - * @HWSIM_REGTEST_STRICT_ALL: Used for testing strict regulatory domain - * settings. All radios will adhere to this. - * @HWSIM_REGTEST_STRICT_AND_DRIVER_REG: Used for testing strict regulatory - * domain settings, combined with secondary driver regulatory domain - * settings. The first radio will get a strict regulatory domain setting - * using the first driver regulatory request and the second radio will use - * non-strict settings using the second driver regulatory request. All - * other devices should follow the intersection created between the - * first two. - * @HWSIM_REGTEST_ALL: Used for testing every possible mix. You will need - * at least 6 radios for a complete test. We will test in this order: - * 1 - driver custom world regulatory domain - * 2 - second custom world regulatory domain - * 3 - first driver regulatory domain request - * 4 - second driver regulatory domain request - * 5 - strict regulatory domain settings using the third driver regulatory - * domain request - * 6 and on - should follow the intersection of the 3rd, 4rth and 5th radio - * regulatory requests. - */ -enum hwsim_regtest { - HWSIM_REGTEST_DISABLED = 0, - HWSIM_REGTEST_DRIVER_REG_FOLLOW = 1, - HWSIM_REGTEST_DRIVER_REG_ALL = 2, - HWSIM_REGTEST_DIFF_COUNTRY = 3, - HWSIM_REGTEST_WORLD_ROAM = 4, - HWSIM_REGTEST_CUSTOM_WORLD = 5, - HWSIM_REGTEST_CUSTOM_WORLD_2 = 6, - HWSIM_REGTEST_STRICT_FOLLOW = 7, - HWSIM_REGTEST_STRICT_ALL = 8, - HWSIM_REGTEST_STRICT_AND_DRIVER_REG = 9, - HWSIM_REGTEST_ALL = 10, -}; - -/* Set to one of the HWSIM_REGTEST_* values above */ -static int regtest = HWSIM_REGTEST_DISABLED; -module_param(regtest, int, 0444); -MODULE_PARM_DESC(regtest, "The type of regulatory test we want to run"); - -static const char *hwsim_alpha2s[] = { - "FI", - "AL", - "US", - "DE", - "JP", - "AL", -}; - -static const struct ieee80211_regdomain hwsim_world_regdom_custom_01 = { - .n_reg_rules = 4, - .alpha2 = "99", - .reg_rules = { - REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), - REG_RULE(2484-10, 2484+10, 40, 0, 20, 0), - REG_RULE(5150-10, 5240+10, 40, 0, 30, 0), - REG_RULE(5745-10, 5825+10, 40, 0, 30, 0), - } -}; - -static const struct ieee80211_regdomain hwsim_world_regdom_custom_02 = { - .n_reg_rules = 2, - .alpha2 = "99", - .reg_rules = { - REG_RULE(2412-10, 2462+10, 40, 0, 20, 0), - REG_RULE(5725-10, 5850+10, 40, 0, 30, - NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS), - } -}; - -struct hwsim_vif_priv { - u32 magic; - u8 bssid[ETH_ALEN]; - bool assoc; - u16 aid; -}; - -#define HWSIM_VIF_MAGIC 0x69537748 - -static inline void hwsim_check_magic(struct ieee80211_vif *vif) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - WARN_ON(vp->magic != HWSIM_VIF_MAGIC); -} - -static inline void hwsim_set_magic(struct ieee80211_vif *vif) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - vp->magic = HWSIM_VIF_MAGIC; -} - -static inline void hwsim_clear_magic(struct ieee80211_vif *vif) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - vp->magic = 0; -} - -struct hwsim_sta_priv { - u32 magic; -}; - -#define HWSIM_STA_MAGIC 0x6d537748 - -static inline void hwsim_check_sta_magic(struct ieee80211_sta *sta) -{ - struct hwsim_sta_priv *sp = (void *)sta->drv_priv; - WARN_ON(sp->magic != HWSIM_STA_MAGIC); -} - -static inline void hwsim_set_sta_magic(struct ieee80211_sta *sta) -{ - struct hwsim_sta_priv *sp = (void *)sta->drv_priv; - sp->magic = HWSIM_STA_MAGIC; -} - -static inline void hwsim_clear_sta_magic(struct ieee80211_sta *sta) -{ - struct hwsim_sta_priv *sp = (void *)sta->drv_priv; - sp->magic = 0; -} - -static struct class *hwsim_class; - -static struct net_device *hwsim_mon; /* global monitor netdev */ - -#define CHAN2G(_freq) { \ - .band = IEEE80211_BAND_2GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_freq), \ - .max_power = 20, \ -} - -#define CHAN5G(_freq) { \ - .band = IEEE80211_BAND_5GHZ, \ - .center_freq = (_freq), \ - .hw_value = (_freq), \ - .max_power = 20, \ -} - -static const struct ieee80211_channel hwsim_channels_2ghz[] = { - CHAN2G(2412), /* Channel 1 */ - CHAN2G(2417), /* Channel 2 */ - CHAN2G(2422), /* Channel 3 */ - CHAN2G(2427), /* Channel 4 */ - CHAN2G(2432), /* Channel 5 */ - CHAN2G(2437), /* Channel 6 */ - CHAN2G(2442), /* Channel 7 */ - CHAN2G(2447), /* Channel 8 */ - CHAN2G(2452), /* Channel 9 */ - CHAN2G(2457), /* Channel 10 */ - CHAN2G(2462), /* Channel 11 */ - CHAN2G(2467), /* Channel 12 */ - CHAN2G(2472), /* Channel 13 */ - CHAN2G(2484), /* Channel 14 */ -}; - -static const struct ieee80211_channel hwsim_channels_5ghz[] = { - CHAN5G(5180), /* Channel 36 */ - CHAN5G(5200), /* Channel 40 */ - CHAN5G(5220), /* Channel 44 */ - CHAN5G(5240), /* Channel 48 */ - - CHAN5G(5260), /* Channel 52 */ - CHAN5G(5280), /* Channel 56 */ - CHAN5G(5300), /* Channel 60 */ - CHAN5G(5320), /* Channel 64 */ - - CHAN5G(5500), /* Channel 100 */ - CHAN5G(5520), /* Channel 104 */ - CHAN5G(5540), /* Channel 108 */ - CHAN5G(5560), /* Channel 112 */ - CHAN5G(5580), /* Channel 116 */ - CHAN5G(5600), /* Channel 120 */ - CHAN5G(5620), /* Channel 124 */ - CHAN5G(5640), /* Channel 128 */ - CHAN5G(5660), /* Channel 132 */ - CHAN5G(5680), /* Channel 136 */ - CHAN5G(5700), /* Channel 140 */ - - CHAN5G(5745), /* Channel 149 */ - CHAN5G(5765), /* Channel 153 */ - CHAN5G(5785), /* Channel 157 */ - CHAN5G(5805), /* Channel 161 */ - CHAN5G(5825), /* Channel 165 */ -}; - -static const struct ieee80211_rate hwsim_rates[] = { - { .bitrate = 10 }, - { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60 }, - { .bitrate = 90 }, - { .bitrate = 120 }, - { .bitrate = 180 }, - { .bitrate = 240 }, - { .bitrate = 360 }, - { .bitrate = 480 }, - { .bitrate = 540 } -}; - -static spinlock_t hwsim_radio_lock; -static struct list_head hwsim_radios; - -struct mac80211_hwsim_data { - struct list_head list; - struct ieee80211_hw *hw; - struct device *dev; - struct ieee80211_supported_band bands[2]; - struct ieee80211_channel channels_2ghz[ARRAY_SIZE(hwsim_channels_2ghz)]; - struct ieee80211_channel channels_5ghz[ARRAY_SIZE(hwsim_channels_5ghz)]; - struct ieee80211_rate rates[ARRAY_SIZE(hwsim_rates)]; - - struct ieee80211_channel *channel; - unsigned long beacon_int; /* in jiffies unit */ - unsigned int rx_filter; - int started; - struct timer_list beacon_timer; - enum ps_mode { - PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL - } ps; - bool ps_poll_pending; - struct dentry *debugfs; - struct dentry *debugfs_ps; - - /* - * Only radios in the same group can communicate together (the - * channel has to match too). Each bit represents a group. A - * radio can be in more then one group. - */ - u64 group; - struct dentry *debugfs_group; -}; - - -struct hwsim_radiotap_hdr { - struct ieee80211_radiotap_header hdr; - u8 rt_flags; - u8 rt_rate; - __le16 rt_channel; - __le16 rt_chbitmask; -} __attribute__ ((packed)); - - -static netdev_tx_t hwsim_mon_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - /* TODO: allow packet injection */ - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - - -static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw, - struct sk_buff *tx_skb) -{ - struct mac80211_hwsim_data *data = hw->priv; - struct sk_buff *skb; - struct hwsim_radiotap_hdr *hdr; - u16 flags; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_skb); - struct ieee80211_rate *txrate = ieee80211_get_tx_rate(hw, info); - - if (!netif_running(hwsim_mon)) - return; - - skb = skb_copy_expand(tx_skb, sizeof(*hdr), 0, GFP_ATOMIC); - if (skb == NULL) - return; - - hdr = (struct hwsim_radiotap_hdr *) skb_push(skb, sizeof(*hdr)); - hdr->hdr.it_version = PKTHDR_RADIOTAP_VERSION; - hdr->hdr.it_pad = 0; - hdr->hdr.it_len = cpu_to_le16(sizeof(*hdr)); - hdr->hdr.it_present = cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | - (1 << IEEE80211_RADIOTAP_RATE) | - (1 << IEEE80211_RADIOTAP_CHANNEL)); - hdr->rt_flags = 0; - hdr->rt_rate = txrate->bitrate / 5; - hdr->rt_channel = cpu_to_le16(data->channel->center_freq); - flags = IEEE80211_CHAN_2GHZ; - if (txrate->flags & IEEE80211_RATE_ERP_G) - flags |= IEEE80211_CHAN_OFDM; - else - flags |= IEEE80211_CHAN_CCK; - hdr->rt_chbitmask = cpu_to_le16(flags); - - skb->dev = hwsim_mon; - skb_set_mac_header(skb, 0); - skb->ip_summed = CHECKSUM_UNNECESSARY; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = htons(ETH_P_802_2); - memset(skb->cb, 0, sizeof(skb->cb)); - netif_rx(skb); -} - - -static bool hwsim_ps_rx_ok(struct mac80211_hwsim_data *data, - struct sk_buff *skb) -{ - switch (data->ps) { - case PS_DISABLED: - return true; - case PS_ENABLED: - return false; - case PS_AUTO_POLL: - /* TODO: accept (some) Beacons by default and other frames only - * if pending PS-Poll has been sent */ - return true; - case PS_MANUAL_POLL: - /* Allow unicast frames to own address if there is a pending - * PS-Poll */ - if (data->ps_poll_pending && - memcmp(data->hw->wiphy->perm_addr, skb->data + 4, - ETH_ALEN) == 0) { - data->ps_poll_pending = false; - return true; - } - return false; - } - - return true; -} - - -static bool mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, - struct sk_buff *skb) -{ - struct mac80211_hwsim_data *data = hw->priv, *data2; - bool ack = false; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_rx_status rx_status; - - memset(&rx_status, 0, sizeof(rx_status)); - /* TODO: set mactime */ - rx_status.freq = data->channel->center_freq; - rx_status.band = data->channel->band; - rx_status.rate_idx = info->control.rates[0].idx; - /* TODO: simulate real signal strength (and optional packet loss) */ - rx_status.signal = -50; - - if (data->ps != PS_DISABLED) - hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PM); - - /* release the skb's source info */ - skb_orphan(skb); - skb_dst_drop(skb); - skb->mark = 0; - secpath_reset(skb); - nf_reset(skb); - - /* Copy skb to all enabled radios that are on the current frequency */ - spin_lock(&hwsim_radio_lock); - list_for_each_entry(data2, &hwsim_radios, list) { - struct sk_buff *nskb; - - if (data == data2) - continue; - - if (!data2->started || !hwsim_ps_rx_ok(data2, skb) || - !data->channel || !data2->channel || - data->channel->center_freq != data2->channel->center_freq || - !(data->group & data2->group)) - continue; - - nskb = skb_copy(skb, GFP_ATOMIC); - if (nskb == NULL) - continue; - - if (memcmp(hdr->addr1, data2->hw->wiphy->perm_addr, - ETH_ALEN) == 0) - ack = true; - memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(data2->hw, nskb); - } - spin_unlock(&hwsim_radio_lock); - - return ack; -} - - -static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - bool ack; - struct ieee80211_tx_info *txi; - - mac80211_hwsim_monitor_rx(hw, skb); - - if (skb->len < 10) { - /* Should not happen; just a sanity check for addr1 use */ - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - ack = mac80211_hwsim_tx_frame(hw, skb); - - txi = IEEE80211_SKB_CB(skb); - - if (txi->control.vif) - hwsim_check_magic(txi->control.vif); - if (txi->control.sta) - hwsim_check_sta_magic(txi->control.sta); - - ieee80211_tx_info_clear_status(txi); - if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack) - txi->flags |= IEEE80211_TX_STAT_ACK; - ieee80211_tx_status_irqsafe(hw, skb); - return NETDEV_TX_OK; -} - - -static int mac80211_hwsim_start(struct ieee80211_hw *hw) -{ - struct mac80211_hwsim_data *data = hw->priv; - printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); - data->started = 1; - return 0; -} - - -static void mac80211_hwsim_stop(struct ieee80211_hw *hw) -{ - struct mac80211_hwsim_data *data = hw->priv; - data->started = 0; - del_timer(&data->beacon_timer); - printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); -} - - -static int mac80211_hwsim_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, conf->type, - conf->mac_addr); - hwsim_set_magic(conf->vif); - return 0; -} - - -static void mac80211_hwsim_remove_interface( - struct ieee80211_hw *hw, struct ieee80211_if_init_conf *conf) -{ - printk(KERN_DEBUG "%s:%s (type=%d mac_addr=%pM)\n", - wiphy_name(hw->wiphy), __func__, conf->type, - conf->mac_addr); - hwsim_check_magic(conf->vif); - hwsim_clear_magic(conf->vif); -} - - -static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac, - struct ieee80211_vif *vif) -{ - struct ieee80211_hw *hw = arg; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - - hwsim_check_magic(vif); - - if (vif->type != NL80211_IFTYPE_AP && - vif->type != NL80211_IFTYPE_MESH_POINT) - return; - - skb = ieee80211_beacon_get(hw, vif); - if (skb == NULL) - return; - info = IEEE80211_SKB_CB(skb); - - mac80211_hwsim_monitor_rx(hw, skb); - mac80211_hwsim_tx_frame(hw, skb); - dev_kfree_skb(skb); -} - - -static void mac80211_hwsim_beacon(unsigned long arg) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *) arg; - struct mac80211_hwsim_data *data = hw->priv; - - if (!data->started) - return; - - ieee80211_iterate_active_interfaces_atomic( - hw, mac80211_hwsim_beacon_tx, hw); - - data->beacon_timer.expires = jiffies + data->beacon_int; - add_timer(&data->beacon_timer); -} - - -static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) -{ - struct mac80211_hwsim_data *data = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - printk(KERN_DEBUG "%s:%s (freq=%d idle=%d ps=%d)\n", - wiphy_name(hw->wiphy), __func__, - conf->channel->center_freq, - !!(conf->flags & IEEE80211_CONF_IDLE), - !!(conf->flags & IEEE80211_CONF_PS)); - - data->channel = conf->channel; - if (!data->started || !data->beacon_int) - del_timer(&data->beacon_timer); - else - mod_timer(&data->beacon_timer, jiffies + data->beacon_int); - - return 0; -} - - -static void mac80211_hwsim_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags,u64 multicast) -{ - struct mac80211_hwsim_data *data = hw->priv; - - printk(KERN_DEBUG "%s:%s\n", wiphy_name(hw->wiphy), __func__); - - data->rx_filter = 0; - if (*total_flags & FIF_PROMISC_IN_BSS) - data->rx_filter |= FIF_PROMISC_IN_BSS; - if (*total_flags & FIF_ALLMULTI) - data->rx_filter |= FIF_ALLMULTI; - - *total_flags = data->rx_filter; -} - -static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - struct mac80211_hwsim_data *data = hw->priv; - - hwsim_check_magic(vif); - - printk(KERN_DEBUG "%s:%s(changed=0x%x)\n", - wiphy_name(hw->wiphy), __func__, changed); - - if (changed & BSS_CHANGED_BSSID) { - printk(KERN_DEBUG "%s:%s: BSSID changed: %pM\n", - wiphy_name(hw->wiphy), __func__, - info->bssid); - memcpy(vp->bssid, info->bssid, ETH_ALEN); - } - - if (changed & BSS_CHANGED_ASSOC) { - printk(KERN_DEBUG " %s: ASSOC: assoc=%d aid=%d\n", - wiphy_name(hw->wiphy), info->assoc, info->aid); - vp->assoc = info->assoc; - vp->aid = info->aid; - } - - if (changed & BSS_CHANGED_BEACON_INT) { - printk(KERN_DEBUG " %s: BCNINT: %d\n", - wiphy_name(hw->wiphy), info->beacon_int); - data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; - if (WARN_ON(!data->beacon_int)) - data->beacon_int = 1; - if (data->started) - mod_timer(&data->beacon_timer, - jiffies + data->beacon_int); - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - printk(KERN_DEBUG " %s: ERP_CTS_PROT: %d\n", - wiphy_name(hw->wiphy), info->use_cts_prot); - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - printk(KERN_DEBUG " %s: ERP_PREAMBLE: %d\n", - wiphy_name(hw->wiphy), info->use_short_preamble); - } - - if (changed & BSS_CHANGED_ERP_SLOT) { - printk(KERN_DEBUG " %s: ERP_SLOT: %d\n", - wiphy_name(hw->wiphy), info->use_short_slot); - } - - if (changed & BSS_CHANGED_HT) { - printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", - wiphy_name(hw->wiphy), - info->ht_operation_mode); - } - - if (changed & BSS_CHANGED_BASIC_RATES) { - printk(KERN_DEBUG " %s: BASIC_RATES: 0x%llx\n", - wiphy_name(hw->wiphy), - (unsigned long long) info->basic_rates); - } -} - -static void mac80211_hwsim_sta_notify(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - enum sta_notify_cmd cmd, - struct ieee80211_sta *sta) -{ - hwsim_check_magic(vif); - switch (cmd) { - case STA_NOTIFY_ADD: - hwsim_set_sta_magic(sta); - break; - case STA_NOTIFY_REMOVE: - hwsim_clear_sta_magic(sta); - break; - case STA_NOTIFY_SLEEP: - case STA_NOTIFY_AWAKE: - /* TODO: make good use of these flags */ - break; - } -} - -static int mac80211_hwsim_set_tim(struct ieee80211_hw *hw, - struct ieee80211_sta *sta, - bool set) -{ - hwsim_check_sta_magic(sta); - return 0; -} - -static int mac80211_hwsim_conf_tx( - struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - printk(KERN_DEBUG "%s:%s (queue=%d txop=%d cw_min=%d cw_max=%d " - "aifs=%d)\n", - wiphy_name(hw->wiphy), __func__, queue, - params->txop, params->cw_min, params->cw_max, params->aifs); - return 0; -} - -#ifdef CONFIG_NL80211_TESTMODE -/* - * This section contains example code for using netlink - * attributes with the testmode command in nl80211. - */ - -/* These enums need to be kept in sync with userspace */ -enum hwsim_testmode_attr { - __HWSIM_TM_ATTR_INVALID = 0, - HWSIM_TM_ATTR_CMD = 1, - HWSIM_TM_ATTR_PS = 2, - - /* keep last */ - __HWSIM_TM_ATTR_AFTER_LAST, - HWSIM_TM_ATTR_MAX = __HWSIM_TM_ATTR_AFTER_LAST - 1 -}; - -enum hwsim_testmode_cmd { - HWSIM_TM_CMD_SET_PS = 0, - HWSIM_TM_CMD_GET_PS = 1, -}; - -static const struct nla_policy hwsim_testmode_policy[HWSIM_TM_ATTR_MAX + 1] = { - [HWSIM_TM_ATTR_CMD] = { .type = NLA_U32 }, - [HWSIM_TM_ATTR_PS] = { .type = NLA_U32 }, -}; - -static int hwsim_fops_ps_write(void *dat, u64 val); - -static int mac80211_hwsim_testmode_cmd(struct ieee80211_hw *hw, - void *data, int len) -{ - struct mac80211_hwsim_data *hwsim = hw->priv; - struct nlattr *tb[HWSIM_TM_ATTR_MAX + 1]; - struct sk_buff *skb; - int err, ps; - - err = nla_parse(tb, HWSIM_TM_ATTR_MAX, data, len, - hwsim_testmode_policy); - if (err) - return err; - - if (!tb[HWSIM_TM_ATTR_CMD]) - return -EINVAL; - - switch (nla_get_u32(tb[HWSIM_TM_ATTR_CMD])) { - case HWSIM_TM_CMD_SET_PS: - if (!tb[HWSIM_TM_ATTR_PS]) - return -EINVAL; - ps = nla_get_u32(tb[HWSIM_TM_ATTR_PS]); - return hwsim_fops_ps_write(hwsim, ps); - case HWSIM_TM_CMD_GET_PS: - skb = cfg80211_testmode_alloc_reply_skb(hw->wiphy, - nla_total_size(sizeof(u32))); - if (!skb) - return -ENOMEM; - NLA_PUT_U32(skb, HWSIM_TM_ATTR_PS, hwsim->ps); - return cfg80211_testmode_reply(skb); - default: - return -EOPNOTSUPP; - } - - nla_put_failure: - kfree_skb(skb); - return -ENOBUFS; -} -#endif - -static const struct ieee80211_ops mac80211_hwsim_ops = -{ - .tx = mac80211_hwsim_tx, - .start = mac80211_hwsim_start, - .stop = mac80211_hwsim_stop, - .add_interface = mac80211_hwsim_add_interface, - .remove_interface = mac80211_hwsim_remove_interface, - .config = mac80211_hwsim_config, - .configure_filter = mac80211_hwsim_configure_filter, - .bss_info_changed = mac80211_hwsim_bss_info_changed, - .sta_notify = mac80211_hwsim_sta_notify, - .set_tim = mac80211_hwsim_set_tim, - .conf_tx = mac80211_hwsim_conf_tx, - CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) -}; - - -static void mac80211_hwsim_free(void) -{ - struct list_head tmplist, *i, *tmp; - struct mac80211_hwsim_data *data, *tmpdata; - - INIT_LIST_HEAD(&tmplist); - - spin_lock_bh(&hwsim_radio_lock); - list_for_each_safe(i, tmp, &hwsim_radios) - list_move(i, &tmplist); - spin_unlock_bh(&hwsim_radio_lock); - - list_for_each_entry_safe(data, tmpdata, &tmplist, list) { - debugfs_remove(data->debugfs_group); - debugfs_remove(data->debugfs_ps); - debugfs_remove(data->debugfs); - ieee80211_unregister_hw(data->hw); - device_unregister(data->dev); - ieee80211_free_hw(data->hw); - } - class_destroy(hwsim_class); -} - - -static struct device_driver mac80211_hwsim_driver = { - .name = "mac80211_hwsim" -}; - -static const struct net_device_ops hwsim_netdev_ops = { - .ndo_start_xmit = hwsim_mon_xmit, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -static void hwsim_mon_setup(struct net_device *dev) -{ - dev->netdev_ops = &hwsim_netdev_ops; - dev->destructor = free_netdev; - ether_setup(dev); - dev->tx_queue_len = 0; - dev->type = ARPHRD_IEEE80211_RADIOTAP; - memset(dev->dev_addr, 0, ETH_ALEN); - dev->dev_addr[0] = 0x12; -} - - -static void hwsim_send_ps_poll(void *dat, u8 *mac, struct ieee80211_vif *vif) -{ - struct mac80211_hwsim_data *data = dat; - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - struct sk_buff *skb; - struct ieee80211_pspoll *pspoll; - - if (!vp->assoc) - return; - - printk(KERN_DEBUG "%s:%s: send PS-Poll to %pM for aid %d\n", - wiphy_name(data->hw->wiphy), __func__, vp->bssid, vp->aid); - - skb = dev_alloc_skb(sizeof(*pspoll)); - if (!skb) - return; - pspoll = (void *) skb_put(skb, sizeof(*pspoll)); - pspoll->frame_control = cpu_to_le16(IEEE80211_FTYPE_CTL | - IEEE80211_STYPE_PSPOLL | - IEEE80211_FCTL_PM); - pspoll->aid = cpu_to_le16(0xc000 | vp->aid); - memcpy(pspoll->bssid, vp->bssid, ETH_ALEN); - memcpy(pspoll->ta, mac, ETH_ALEN); - if (!mac80211_hwsim_tx_frame(data->hw, skb)) - printk(KERN_DEBUG "%s: PS-Poll frame not ack'ed\n", __func__); - dev_kfree_skb(skb); -} - - -static void hwsim_send_nullfunc(struct mac80211_hwsim_data *data, u8 *mac, - struct ieee80211_vif *vif, int ps) -{ - struct hwsim_vif_priv *vp = (void *)vif->drv_priv; - struct sk_buff *skb; - struct ieee80211_hdr *hdr; - - if (!vp->assoc) - return; - - printk(KERN_DEBUG "%s:%s: send data::nullfunc to %pM ps=%d\n", - wiphy_name(data->hw->wiphy), __func__, vp->bssid, ps); - - skb = dev_alloc_skb(sizeof(*hdr)); - if (!skb) - return; - hdr = (void *) skb_put(skb, sizeof(*hdr) - ETH_ALEN); - hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC | - (ps ? IEEE80211_FCTL_PM : 0)); - hdr->duration_id = cpu_to_le16(0); - memcpy(hdr->addr1, vp->bssid, ETH_ALEN); - memcpy(hdr->addr2, mac, ETH_ALEN); - memcpy(hdr->addr3, vp->bssid, ETH_ALEN); - if (!mac80211_hwsim_tx_frame(data->hw, skb)) - printk(KERN_DEBUG "%s: nullfunc frame not ack'ed\n", __func__); - dev_kfree_skb(skb); -} - - -static void hwsim_send_nullfunc_ps(void *dat, u8 *mac, - struct ieee80211_vif *vif) -{ - struct mac80211_hwsim_data *data = dat; - hwsim_send_nullfunc(data, mac, vif, 1); -} - - -static void hwsim_send_nullfunc_no_ps(void *dat, u8 *mac, - struct ieee80211_vif *vif) -{ - struct mac80211_hwsim_data *data = dat; - hwsim_send_nullfunc(data, mac, vif, 0); -} - - -static int hwsim_fops_ps_read(void *dat, u64 *val) -{ - struct mac80211_hwsim_data *data = dat; - *val = data->ps; - return 0; -} - -static int hwsim_fops_ps_write(void *dat, u64 val) -{ - struct mac80211_hwsim_data *data = dat; - enum ps_mode old_ps; - - if (val != PS_DISABLED && val != PS_ENABLED && val != PS_AUTO_POLL && - val != PS_MANUAL_POLL) - return -EINVAL; - - old_ps = data->ps; - data->ps = val; - - if (val == PS_MANUAL_POLL) { - ieee80211_iterate_active_interfaces(data->hw, - hwsim_send_ps_poll, data); - data->ps_poll_pending = true; - } else if (old_ps == PS_DISABLED && val != PS_DISABLED) { - ieee80211_iterate_active_interfaces(data->hw, - hwsim_send_nullfunc_ps, - data); - } else if (old_ps != PS_DISABLED && val == PS_DISABLED) { - ieee80211_iterate_active_interfaces(data->hw, - hwsim_send_nullfunc_no_ps, - data); - } - - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write, - "%llu\n"); - - -static int hwsim_fops_group_read(void *dat, u64 *val) -{ - struct mac80211_hwsim_data *data = dat; - *val = data->group; - return 0; -} - -static int hwsim_fops_group_write(void *dat, u64 val) -{ - struct mac80211_hwsim_data *data = dat; - data->group = val; - return 0; -} - -DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_group, - hwsim_fops_group_read, hwsim_fops_group_write, - "%llx\n"); - -static int __init init_mac80211_hwsim(void) -{ - int i, err = 0; - u8 addr[ETH_ALEN]; - struct mac80211_hwsim_data *data; - struct ieee80211_hw *hw; - enum ieee80211_band band; - - if (radios < 1 || radios > 100) - return -EINVAL; - - spin_lock_init(&hwsim_radio_lock); - INIT_LIST_HEAD(&hwsim_radios); - - hwsim_class = class_create(THIS_MODULE, "mac80211_hwsim"); - if (IS_ERR(hwsim_class)) - return PTR_ERR(hwsim_class); - - memset(addr, 0, ETH_ALEN); - addr[0] = 0x02; - - for (i = 0; i < radios; i++) { - printk(KERN_DEBUG "mac80211_hwsim: Initializing radio %d\n", - i); - hw = ieee80211_alloc_hw(sizeof(*data), &mac80211_hwsim_ops); - if (!hw) { - printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw " - "failed\n"); - err = -ENOMEM; - goto failed; - } - data = hw->priv; - data->hw = hw; - - data->dev = device_create(hwsim_class, NULL, 0, hw, - "hwsim%d", i); - if (IS_ERR(data->dev)) { - printk(KERN_DEBUG - "mac80211_hwsim: device_create " - "failed (%ld)\n", PTR_ERR(data->dev)); - err = -ENOMEM; - goto failed_drvdata; - } - data->dev->driver = &mac80211_hwsim_driver; - - SET_IEEE80211_DEV(hw, data->dev); - addr[3] = i >> 8; - addr[4] = i; - SET_IEEE80211_PERM_ADDR(hw, addr); - - hw->channel_change_time = 1; - hw->queues = 4; - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT); - - hw->flags = IEEE80211_HW_MFP_CAPABLE | - IEEE80211_HW_SIGNAL_DBM; - - /* ask mac80211 to reserve space for magic */ - hw->vif_data_size = sizeof(struct hwsim_vif_priv); - hw->sta_data_size = sizeof(struct hwsim_sta_priv); - - memcpy(data->channels_2ghz, hwsim_channels_2ghz, - sizeof(hwsim_channels_2ghz)); - memcpy(data->channels_5ghz, hwsim_channels_5ghz, - sizeof(hwsim_channels_5ghz)); - memcpy(data->rates, hwsim_rates, sizeof(hwsim_rates)); - - for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) { - struct ieee80211_supported_band *sband = &data->bands[band]; - switch (band) { - case IEEE80211_BAND_2GHZ: - sband->channels = data->channels_2ghz; - sband->n_channels = - ARRAY_SIZE(hwsim_channels_2ghz); - break; - case IEEE80211_BAND_5GHZ: - sband->channels = data->channels_5ghz; - sband->n_channels = - ARRAY_SIZE(hwsim_channels_5ghz); - break; - default: - break; - } - - sband->bitrates = data->rates; - sband->n_bitrates = ARRAY_SIZE(hwsim_rates); - - sband->ht_cap.ht_supported = true; - sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_DSSSCCK40; - sband->ht_cap.ampdu_factor = 0x3; - sband->ht_cap.ampdu_density = 0x6; - memset(&sband->ht_cap.mcs, 0, - sizeof(sband->ht_cap.mcs)); - sband->ht_cap.mcs.rx_mask[0] = 0xff; - sband->ht_cap.mcs.rx_mask[1] = 0xff; - sband->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; - - hw->wiphy->bands[band] = sband; - } - /* By default all radios are belonging to the first group */ - data->group = 1; - - /* Work to be done prior to ieee80211_register_hw() */ - switch (regtest) { - case HWSIM_REGTEST_DISABLED: - case HWSIM_REGTEST_DRIVER_REG_FOLLOW: - case HWSIM_REGTEST_DRIVER_REG_ALL: - case HWSIM_REGTEST_DIFF_COUNTRY: - /* - * Nothing to be done for driver regulatory domain - * hints prior to ieee80211_register_hw() - */ - break; - case HWSIM_REGTEST_WORLD_ROAM: - if (i == 0) { - hw->wiphy->custom_regulatory = true; - wiphy_apply_custom_regulatory(hw->wiphy, - &hwsim_world_regdom_custom_01); - } - break; - case HWSIM_REGTEST_CUSTOM_WORLD: - hw->wiphy->custom_regulatory = true; - wiphy_apply_custom_regulatory(hw->wiphy, - &hwsim_world_regdom_custom_01); - break; - case HWSIM_REGTEST_CUSTOM_WORLD_2: - if (i == 0) { - hw->wiphy->custom_regulatory = true; - wiphy_apply_custom_regulatory(hw->wiphy, - &hwsim_world_regdom_custom_01); - } else if (i == 1) { - hw->wiphy->custom_regulatory = true; - wiphy_apply_custom_regulatory(hw->wiphy, - &hwsim_world_regdom_custom_02); - } - break; - case HWSIM_REGTEST_STRICT_ALL: - hw->wiphy->strict_regulatory = true; - break; - case HWSIM_REGTEST_STRICT_FOLLOW: - case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: - if (i == 0) - hw->wiphy->strict_regulatory = true; - break; - case HWSIM_REGTEST_ALL: - if (i == 0) { - hw->wiphy->custom_regulatory = true; - wiphy_apply_custom_regulatory(hw->wiphy, - &hwsim_world_regdom_custom_01); - } else if (i == 1) { - hw->wiphy->custom_regulatory = true; - wiphy_apply_custom_regulatory(hw->wiphy, - &hwsim_world_regdom_custom_02); - } else if (i == 4) - hw->wiphy->strict_regulatory = true; - break; - default: - break; - } - - /* give the regulatory workqueue a chance to run */ - if (regtest) - schedule_timeout_interruptible(1); - err = ieee80211_register_hw(hw); - if (err < 0) { - printk(KERN_DEBUG "mac80211_hwsim: " - "ieee80211_register_hw failed (%d)\n", err); - goto failed_hw; - } - - /* Work to be done after to ieee80211_register_hw() */ - switch (regtest) { - case HWSIM_REGTEST_WORLD_ROAM: - case HWSIM_REGTEST_DISABLED: - break; - case HWSIM_REGTEST_DRIVER_REG_FOLLOW: - if (!i) - regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); - break; - case HWSIM_REGTEST_DRIVER_REG_ALL: - case HWSIM_REGTEST_STRICT_ALL: - regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); - break; - case HWSIM_REGTEST_DIFF_COUNTRY: - if (i < ARRAY_SIZE(hwsim_alpha2s)) - regulatory_hint(hw->wiphy, hwsim_alpha2s[i]); - break; - case HWSIM_REGTEST_CUSTOM_WORLD: - case HWSIM_REGTEST_CUSTOM_WORLD_2: - /* - * Nothing to be done for custom world regulatory - * domains after to ieee80211_register_hw - */ - break; - case HWSIM_REGTEST_STRICT_FOLLOW: - if (i == 0) - regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); - break; - case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: - if (i == 0) - regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); - else if (i == 1) - regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); - break; - case HWSIM_REGTEST_ALL: - if (i == 2) - regulatory_hint(hw->wiphy, hwsim_alpha2s[0]); - else if (i == 3) - regulatory_hint(hw->wiphy, hwsim_alpha2s[1]); - else if (i == 4) - regulatory_hint(hw->wiphy, hwsim_alpha2s[2]); - break; - default: - break; - } - - printk(KERN_DEBUG "%s: hwaddr %pM registered\n", - wiphy_name(hw->wiphy), - hw->wiphy->perm_addr); - - data->debugfs = debugfs_create_dir("hwsim", - hw->wiphy->debugfsdir); - data->debugfs_ps = debugfs_create_file("ps", 0666, - data->debugfs, data, - &hwsim_fops_ps); - data->debugfs_group = debugfs_create_file("group", 0666, - data->debugfs, data, - &hwsim_fops_group); - - setup_timer(&data->beacon_timer, mac80211_hwsim_beacon, - (unsigned long) hw); - - list_add_tail(&data->list, &hwsim_radios); - } - - hwsim_mon = alloc_netdev(0, "hwsim%d", hwsim_mon_setup); - if (hwsim_mon == NULL) - goto failed; - - rtnl_lock(); - - err = dev_alloc_name(hwsim_mon, hwsim_mon->name); - if (err < 0) - goto failed_mon; - - - err = register_netdevice(hwsim_mon); - if (err < 0) - goto failed_mon; - - rtnl_unlock(); - - return 0; - -failed_mon: - rtnl_unlock(); - free_netdev(hwsim_mon); - mac80211_hwsim_free(); - return err; - -failed_hw: - device_unregister(data->dev); -failed_drvdata: - ieee80211_free_hw(hw); -failed: - mac80211_hwsim_free(); - return err; -} - - -static void __exit exit_mac80211_hwsim(void) -{ - printk(KERN_DEBUG "mac80211_hwsim: unregister radios\n"); - - mac80211_hwsim_free(); - unregister_netdev(hwsim_mon); -} - - -module_init(init_mac80211_hwsim); -module_exit(exit_mac80211_hwsim); diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c deleted file mode 100644 index 746532ebe5a8..000000000000 --- a/drivers/net/wireless/mwl8k.c +++ /dev/null @@ -1,3120 +0,0 @@ -/* - * drivers/net/wireless/mwl8k.c - * Driver for Marvell TOPDOG 802.11 Wireless cards - * - * Copyright (C) 2008-2009 Marvell Semiconductor Inc. - * - * This file is licensed under the terms of the GNU General Public - * License version 2. This program is licensed "as is" without any - * warranty of any kind, whether express or implied. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define MWL8K_DESC "Marvell TOPDOG(R) 802.11 Wireless Network Driver" -#define MWL8K_NAME KBUILD_MODNAME -#define MWL8K_VERSION "0.10" - -MODULE_DESCRIPTION(MWL8K_DESC); -MODULE_VERSION(MWL8K_VERSION); -MODULE_AUTHOR("Lennert Buytenhek "); -MODULE_LICENSE("GPL"); - -static DEFINE_PCI_DEVICE_TABLE(mwl8k_table) = { - { PCI_VDEVICE(MARVELL, 0x2a2b), .driver_data = 8687, }, - { PCI_VDEVICE(MARVELL, 0x2a30), .driver_data = 8687, }, - { } -}; -MODULE_DEVICE_TABLE(pci, mwl8k_table); - -/* Register definitions */ -#define MWL8K_HIU_GEN_PTR 0x00000c10 -#define MWL8K_MODE_STA 0x0000005a -#define MWL8K_MODE_AP 0x000000a5 -#define MWL8K_HIU_INT_CODE 0x00000c14 -#define MWL8K_FWSTA_READY 0xf0f1f2f4 -#define MWL8K_FWAP_READY 0xf1f2f4a5 -#define MWL8K_INT_CODE_CMD_FINISHED 0x00000005 -#define MWL8K_HIU_SCRATCH 0x00000c40 - -/* Host->device communications */ -#define MWL8K_HIU_H2A_INTERRUPT_EVENTS 0x00000c18 -#define MWL8K_HIU_H2A_INTERRUPT_STATUS 0x00000c1c -#define MWL8K_HIU_H2A_INTERRUPT_MASK 0x00000c20 -#define MWL8K_HIU_H2A_INTERRUPT_CLEAR_SEL 0x00000c24 -#define MWL8K_HIU_H2A_INTERRUPT_STATUS_MASK 0x00000c28 -#define MWL8K_H2A_INT_DUMMY (1 << 20) -#define MWL8K_H2A_INT_RESET (1 << 15) -#define MWL8K_H2A_INT_DOORBELL (1 << 1) -#define MWL8K_H2A_INT_PPA_READY (1 << 0) - -/* Device->host communications */ -#define MWL8K_HIU_A2H_INTERRUPT_EVENTS 0x00000c2c -#define MWL8K_HIU_A2H_INTERRUPT_STATUS 0x00000c30 -#define MWL8K_HIU_A2H_INTERRUPT_MASK 0x00000c34 -#define MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL 0x00000c38 -#define MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK 0x00000c3c -#define MWL8K_A2H_INT_DUMMY (1 << 20) -#define MWL8K_A2H_INT_CHNL_SWITCHED (1 << 11) -#define MWL8K_A2H_INT_QUEUE_EMPTY (1 << 10) -#define MWL8K_A2H_INT_RADAR_DETECT (1 << 7) -#define MWL8K_A2H_INT_RADIO_ON (1 << 6) -#define MWL8K_A2H_INT_RADIO_OFF (1 << 5) -#define MWL8K_A2H_INT_MAC_EVENT (1 << 3) -#define MWL8K_A2H_INT_OPC_DONE (1 << 2) -#define MWL8K_A2H_INT_RX_READY (1 << 1) -#define MWL8K_A2H_INT_TX_DONE (1 << 0) - -#define MWL8K_A2H_EVENTS (MWL8K_A2H_INT_DUMMY | \ - MWL8K_A2H_INT_CHNL_SWITCHED | \ - MWL8K_A2H_INT_QUEUE_EMPTY | \ - MWL8K_A2H_INT_RADAR_DETECT | \ - MWL8K_A2H_INT_RADIO_ON | \ - MWL8K_A2H_INT_RADIO_OFF | \ - MWL8K_A2H_INT_MAC_EVENT | \ - MWL8K_A2H_INT_OPC_DONE | \ - MWL8K_A2H_INT_RX_READY | \ - MWL8K_A2H_INT_TX_DONE) - -/* WME stream classes */ -#define WME_AC_BE 0 /* best effort */ -#define WME_AC_BK 1 /* background */ -#define WME_AC_VI 2 /* video */ -#define WME_AC_VO 3 /* voice */ - -#define MWL8K_RX_QUEUES 1 -#define MWL8K_TX_QUEUES 4 - -struct mwl8k_rx_queue { - int rx_desc_count; - - /* hw receives here */ - int rx_head; - - /* refill descs here */ - int rx_tail; - - struct mwl8k_rx_desc *rx_desc_area; - dma_addr_t rx_desc_dma; - struct sk_buff **rx_skb; -}; - -struct mwl8k_tx_queue { - /* hw transmits here */ - int tx_head; - - /* sw appends here */ - int tx_tail; - - struct ieee80211_tx_queue_stats tx_stats; - struct mwl8k_tx_desc *tx_desc_area; - dma_addr_t tx_desc_dma; - struct sk_buff **tx_skb; -}; - -/* Pointers to the firmware data and meta information about it. */ -struct mwl8k_firmware { - /* Microcode */ - struct firmware *ucode; - - /* Boot helper code */ - struct firmware *helper; -}; - -struct mwl8k_priv { - void __iomem *regs; - struct ieee80211_hw *hw; - - struct pci_dev *pdev; - u8 name[16]; - - /* firmware files and meta data */ - struct mwl8k_firmware fw; - u32 part_num; - - /* firmware access */ - struct mutex fw_mutex; - struct task_struct *fw_mutex_owner; - int fw_mutex_depth; - struct completion *tx_wait; - struct completion *hostcmd_wait; - - /* lock held over TX and TX reap */ - spinlock_t tx_lock; - - struct ieee80211_vif *vif; - - struct ieee80211_channel *current_channel; - - /* power management status cookie from firmware */ - u32 *cookie; - dma_addr_t cookie_dma; - - u16 num_mcaddrs; - u8 hw_rev; - u32 fw_rev; - - /* - * Running count of TX packets in flight, to avoid - * iterating over the transmit rings each time. - */ - int pending_tx_pkts; - - struct mwl8k_rx_queue rxq[MWL8K_RX_QUEUES]; - struct mwl8k_tx_queue txq[MWL8K_TX_QUEUES]; - - /* PHY parameters */ - struct ieee80211_supported_band band; - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - - bool radio_on; - bool radio_short_preamble; - bool wmm_enabled; - - /* XXX need to convert this to handle multiple interfaces */ - bool capture_beacon; - u8 capture_bssid[ETH_ALEN]; - struct sk_buff *beacon_skb; - - /* - * This FJ worker has to be global as it is scheduled from the - * RX handler. At this point we don't know which interface it - * belongs to until the list of bssids waiting to complete join - * is checked. - */ - struct work_struct finalize_join_worker; - - /* Tasklet to reclaim TX descriptors and buffers after tx */ - struct tasklet_struct tx_reclaim_task; - - /* Work thread to serialize configuration requests */ - struct workqueue_struct *config_wq; -}; - -/* Per interface specific private data */ -struct mwl8k_vif { - /* backpointer to parent config block */ - struct mwl8k_priv *priv; - - /* BSS config of AP or IBSS from mac80211*/ - struct ieee80211_bss_conf bss_info; - - /* BSSID of AP or IBSS */ - u8 bssid[ETH_ALEN]; - u8 mac_addr[ETH_ALEN]; - - /* - * Subset of supported legacy rates. - * Intersection of AP and STA supported rates. - */ - struct ieee80211_rate legacy_rates[12]; - - /* number of supported legacy rates */ - u8 legacy_nrates; - - /* Index into station database.Returned by update_sta_db call */ - u8 peer_id; - - /* Non AMPDU sequence number assigned by driver */ - u16 seqno; -}; - -#define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv)) - -static const struct ieee80211_channel mwl8k_channels[] = { - { .center_freq = 2412, .hw_value = 1, }, - { .center_freq = 2417, .hw_value = 2, }, - { .center_freq = 2422, .hw_value = 3, }, - { .center_freq = 2427, .hw_value = 4, }, - { .center_freq = 2432, .hw_value = 5, }, - { .center_freq = 2437, .hw_value = 6, }, - { .center_freq = 2442, .hw_value = 7, }, - { .center_freq = 2447, .hw_value = 8, }, - { .center_freq = 2452, .hw_value = 9, }, - { .center_freq = 2457, .hw_value = 10, }, - { .center_freq = 2462, .hw_value = 11, }, -}; - -static const struct ieee80211_rate mwl8k_rates[] = { - { .bitrate = 10, .hw_value = 2, }, - { .bitrate = 20, .hw_value = 4, }, - { .bitrate = 55, .hw_value = 11, }, - { .bitrate = 60, .hw_value = 12, }, - { .bitrate = 90, .hw_value = 18, }, - { .bitrate = 110, .hw_value = 22, }, - { .bitrate = 120, .hw_value = 24, }, - { .bitrate = 180, .hw_value = 36, }, - { .bitrate = 240, .hw_value = 48, }, - { .bitrate = 360, .hw_value = 72, }, - { .bitrate = 480, .hw_value = 96, }, - { .bitrate = 540, .hw_value = 108, }, -}; - -/* Set or get info from Firmware */ -#define MWL8K_CMD_SET 0x0001 -#define MWL8K_CMD_GET 0x0000 - -/* Firmware command codes */ -#define MWL8K_CMD_CODE_DNLD 0x0001 -#define MWL8K_CMD_GET_HW_SPEC 0x0003 -#define MWL8K_CMD_MAC_MULTICAST_ADR 0x0010 -#define MWL8K_CMD_GET_STAT 0x0014 -#define MWL8K_CMD_RADIO_CONTROL 0x001c -#define MWL8K_CMD_RF_TX_POWER 0x001e -#define MWL8K_CMD_SET_PRE_SCAN 0x0107 -#define MWL8K_CMD_SET_POST_SCAN 0x0108 -#define MWL8K_CMD_SET_RF_CHANNEL 0x010a -#define MWL8K_CMD_SET_AID 0x010d -#define MWL8K_CMD_SET_RATE 0x0110 -#define MWL8K_CMD_SET_FINALIZE_JOIN 0x0111 -#define MWL8K_CMD_RTS_THRESHOLD 0x0113 -#define MWL8K_CMD_SET_SLOT 0x0114 -#define MWL8K_CMD_SET_EDCA_PARAMS 0x0115 -#define MWL8K_CMD_SET_WMM_MODE 0x0123 -#define MWL8K_CMD_MIMO_CONFIG 0x0125 -#define MWL8K_CMD_USE_FIXED_RATE 0x0126 -#define MWL8K_CMD_ENABLE_SNIFFER 0x0150 -#define MWL8K_CMD_SET_RATEADAPT_MODE 0x0203 -#define MWL8K_CMD_UPDATE_STADB 0x1123 - -static const char *mwl8k_cmd_name(u16 cmd, char *buf, int bufsize) -{ -#define MWL8K_CMDNAME(x) case MWL8K_CMD_##x: do {\ - snprintf(buf, bufsize, "%s", #x);\ - return buf;\ - } while (0) - switch (cmd & ~0x8000) { - MWL8K_CMDNAME(CODE_DNLD); - MWL8K_CMDNAME(GET_HW_SPEC); - MWL8K_CMDNAME(MAC_MULTICAST_ADR); - MWL8K_CMDNAME(GET_STAT); - MWL8K_CMDNAME(RADIO_CONTROL); - MWL8K_CMDNAME(RF_TX_POWER); - MWL8K_CMDNAME(SET_PRE_SCAN); - MWL8K_CMDNAME(SET_POST_SCAN); - MWL8K_CMDNAME(SET_RF_CHANNEL); - MWL8K_CMDNAME(SET_AID); - MWL8K_CMDNAME(SET_RATE); - MWL8K_CMDNAME(SET_FINALIZE_JOIN); - MWL8K_CMDNAME(RTS_THRESHOLD); - MWL8K_CMDNAME(SET_SLOT); - MWL8K_CMDNAME(SET_EDCA_PARAMS); - MWL8K_CMDNAME(SET_WMM_MODE); - MWL8K_CMDNAME(MIMO_CONFIG); - MWL8K_CMDNAME(USE_FIXED_RATE); - MWL8K_CMDNAME(ENABLE_SNIFFER); - MWL8K_CMDNAME(SET_RATEADAPT_MODE); - MWL8K_CMDNAME(UPDATE_STADB); - default: - snprintf(buf, bufsize, "0x%x", cmd); - } -#undef MWL8K_CMDNAME - - return buf; -} - -/* Hardware and firmware reset */ -static void mwl8k_hw_reset(struct mwl8k_priv *priv) -{ - iowrite32(MWL8K_H2A_INT_RESET, - priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - iowrite32(MWL8K_H2A_INT_RESET, - priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - msleep(20); -} - -/* Release fw image */ -static void mwl8k_release_fw(struct firmware **fw) -{ - if (*fw == NULL) - return; - release_firmware(*fw); - *fw = NULL; -} - -static void mwl8k_release_firmware(struct mwl8k_priv *priv) -{ - mwl8k_release_fw(&priv->fw.ucode); - mwl8k_release_fw(&priv->fw.helper); -} - -/* Request fw image */ -static int mwl8k_request_fw(struct mwl8k_priv *priv, - const char *fname, struct firmware **fw) -{ - /* release current image */ - if (*fw != NULL) - mwl8k_release_fw(fw); - - return request_firmware((const struct firmware **)fw, - fname, &priv->pdev->dev); -} - -static int mwl8k_request_firmware(struct mwl8k_priv *priv, u32 part_num) -{ - u8 filename[64]; - int rc; - - priv->part_num = part_num; - - snprintf(filename, sizeof(filename), - "mwl8k/helper_%u.fw", priv->part_num); - - rc = mwl8k_request_fw(priv, filename, &priv->fw.helper); - if (rc) { - printk(KERN_ERR - "%s Error requesting helper firmware file %s\n", - pci_name(priv->pdev), filename); - return rc; - } - - snprintf(filename, sizeof(filename), - "mwl8k/fmimage_%u.fw", priv->part_num); - - rc = mwl8k_request_fw(priv, filename, &priv->fw.ucode); - if (rc) { - printk(KERN_ERR "%s Error requesting firmware file %s\n", - pci_name(priv->pdev), filename); - mwl8k_release_fw(&priv->fw.helper); - return rc; - } - - return 0; -} - -struct mwl8k_cmd_pkt { - __le16 code; - __le16 length; - __le16 seq_num; - __le16 result; - char payload[0]; -} __attribute__((packed)); - -/* - * Firmware loading. - */ -static int -mwl8k_send_fw_load_cmd(struct mwl8k_priv *priv, void *data, int length) -{ - void __iomem *regs = priv->regs; - dma_addr_t dma_addr; - int loops; - - dma_addr = pci_map_single(priv->pdev, data, length, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(priv->pdev, dma_addr)) - return -ENOMEM; - - iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); - iowrite32(0, regs + MWL8K_HIU_INT_CODE); - iowrite32(MWL8K_H2A_INT_DOORBELL, - regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - iowrite32(MWL8K_H2A_INT_DUMMY, - regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - - loops = 1000; - do { - u32 int_code; - - int_code = ioread32(regs + MWL8K_HIU_INT_CODE); - if (int_code == MWL8K_INT_CODE_CMD_FINISHED) { - iowrite32(0, regs + MWL8K_HIU_INT_CODE); - break; - } - - udelay(1); - } while (--loops); - - pci_unmap_single(priv->pdev, dma_addr, length, PCI_DMA_TODEVICE); - - return loops ? 0 : -ETIMEDOUT; -} - -static int mwl8k_load_fw_image(struct mwl8k_priv *priv, - const u8 *data, size_t length) -{ - struct mwl8k_cmd_pkt *cmd; - int done; - int rc = 0; - - cmd = kmalloc(sizeof(*cmd) + 256, GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->code = cpu_to_le16(MWL8K_CMD_CODE_DNLD); - cmd->seq_num = 0; - cmd->result = 0; - - done = 0; - while (length) { - int block_size = length > 256 ? 256 : length; - - memcpy(cmd->payload, data + done, block_size); - cmd->length = cpu_to_le16(block_size); - - rc = mwl8k_send_fw_load_cmd(priv, cmd, - sizeof(*cmd) + block_size); - if (rc) - break; - - done += block_size; - length -= block_size; - } - - if (!rc) { - cmd->length = 0; - rc = mwl8k_send_fw_load_cmd(priv, cmd, sizeof(*cmd)); - } - - kfree(cmd); - - return rc; -} - -static int mwl8k_feed_fw_image(struct mwl8k_priv *priv, - const u8 *data, size_t length) -{ - unsigned char *buffer; - int may_continue, rc = 0; - u32 done, prev_block_size; - - buffer = kmalloc(1024, GFP_KERNEL); - if (buffer == NULL) - return -ENOMEM; - - done = 0; - prev_block_size = 0; - may_continue = 1000; - while (may_continue > 0) { - u32 block_size; - - block_size = ioread32(priv->regs + MWL8K_HIU_SCRATCH); - if (block_size & 1) { - block_size &= ~1; - may_continue--; - } else { - done += prev_block_size; - length -= prev_block_size; - } - - if (block_size > 1024 || block_size > length) { - rc = -EOVERFLOW; - break; - } - - if (length == 0) { - rc = 0; - break; - } - - if (block_size == 0) { - rc = -EPROTO; - may_continue--; - udelay(1); - continue; - } - - prev_block_size = block_size; - memcpy(buffer, data + done, block_size); - - rc = mwl8k_send_fw_load_cmd(priv, buffer, block_size); - if (rc) - break; - } - - if (!rc && length != 0) - rc = -EREMOTEIO; - - kfree(buffer); - - return rc; -} - -static int mwl8k_load_firmware(struct mwl8k_priv *priv) -{ - int loops, rc; - - const u8 *ucode = priv->fw.ucode->data; - size_t ucode_len = priv->fw.ucode->size; - const u8 *helper = priv->fw.helper->data; - size_t helper_len = priv->fw.helper->size; - - if (!memcmp(ucode, "\x01\x00\x00\x00", 4)) { - rc = mwl8k_load_fw_image(priv, helper, helper_len); - if (rc) { - printk(KERN_ERR "%s: unable to load firmware " - "helper image\n", pci_name(priv->pdev)); - return rc; - } - msleep(1); - - rc = mwl8k_feed_fw_image(priv, ucode, ucode_len); - } else { - rc = mwl8k_load_fw_image(priv, ucode, ucode_len); - } - - if (rc) { - printk(KERN_ERR "%s: unable to load firmware data\n", - pci_name(priv->pdev)); - return rc; - } - - iowrite32(MWL8K_MODE_STA, priv->regs + MWL8K_HIU_GEN_PTR); - msleep(1); - - loops = 200000; - do { - if (ioread32(priv->regs + MWL8K_HIU_INT_CODE) - == MWL8K_FWSTA_READY) - break; - udelay(1); - } while (--loops); - - return loops ? 0 : -ETIMEDOUT; -} - - -/* - * Defines shared between transmission and reception. - */ -/* HT control fields for firmware */ -struct ewc_ht_info { - __le16 control1; - __le16 control2; - __le16 control3; -} __attribute__((packed)); - -/* Firmware Station database operations */ -#define MWL8K_STA_DB_ADD_ENTRY 0 -#define MWL8K_STA_DB_MODIFY_ENTRY 1 -#define MWL8K_STA_DB_DEL_ENTRY 2 -#define MWL8K_STA_DB_FLUSH 3 - -/* Peer Entry flags - used to define the type of the peer node */ -#define MWL8K_PEER_TYPE_ACCESSPOINT 2 - -#define MWL8K_IEEE_LEGACY_DATA_RATES 12 -#define MWL8K_MCS_BITMAP_SIZE 16 - -struct peer_capability_info { - /* Peer type - AP vs. STA. */ - __u8 peer_type; - - /* Basic 802.11 capabilities from assoc resp. */ - __le16 basic_caps; - - /* Set if peer supports 802.11n high throughput (HT). */ - __u8 ht_support; - - /* Valid if HT is supported. */ - __le16 ht_caps; - __u8 extended_ht_caps; - struct ewc_ht_info ewc_info; - - /* Legacy rate table. Intersection of our rates and peer rates. */ - __u8 legacy_rates[MWL8K_IEEE_LEGACY_DATA_RATES]; - - /* HT rate table. Intersection of our rates and peer rates. */ - __u8 ht_rates[MWL8K_MCS_BITMAP_SIZE]; - __u8 pad[16]; - - /* If set, interoperability mode, no proprietary extensions. */ - __u8 interop; - __u8 pad2; - __u8 station_id; - __le16 amsdu_enabled; -} __attribute__((packed)); - -/* Inline functions to manipulate QoS field in data descriptor. */ -static inline u16 mwl8k_qos_setbit_eosp(u16 qos) -{ - u16 val_mask = 1 << 4; - - /* End of Service Period Bit 4 */ - return qos | val_mask; -} - -static inline u16 mwl8k_qos_setbit_ack(u16 qos, u8 ack_policy) -{ - u16 val_mask = 0x3; - u8 shift = 5; - u16 qos_mask = ~(val_mask << shift); - - /* Ack Policy Bit 5-6 */ - return (qos & qos_mask) | ((ack_policy & val_mask) << shift); -} - -static inline u16 mwl8k_qos_setbit_amsdu(u16 qos) -{ - u16 val_mask = 1 << 7; - - /* AMSDU present Bit 7 */ - return qos | val_mask; -} - -static inline u16 mwl8k_qos_setbit_qlen(u16 qos, u8 len) -{ - u16 val_mask = 0xff; - u8 shift = 8; - u16 qos_mask = ~(val_mask << shift); - - /* Queue Length Bits 8-15 */ - return (qos & qos_mask) | ((len & val_mask) << shift); -} - -/* DMA header used by firmware and hardware. */ -struct mwl8k_dma_data { - __le16 fwlen; - struct ieee80211_hdr wh; -} __attribute__((packed)); - -/* Routines to add/remove DMA header from skb. */ -static inline void mwl8k_remove_dma_header(struct sk_buff *skb) -{ - struct mwl8k_dma_data *tr = (struct mwl8k_dma_data *)skb->data; - void *dst, *src = &tr->wh; - int hdrlen = ieee80211_hdrlen(tr->wh.frame_control); - u16 space = sizeof(struct mwl8k_dma_data) - hdrlen; - - dst = (void *)tr + space; - if (dst != src) { - memmove(dst, src, hdrlen); - skb_pull(skb, space); - } -} - -static inline void mwl8k_add_dma_header(struct sk_buff *skb) -{ - struct ieee80211_hdr *wh; - u32 hdrlen, pktlen; - struct mwl8k_dma_data *tr; - - wh = (struct ieee80211_hdr *)skb->data; - hdrlen = ieee80211_hdrlen(wh->frame_control); - pktlen = skb->len; - - /* - * Copy up/down the 802.11 header; the firmware requires - * we present a 2-byte payload length followed by a - * 4-address header (w/o QoS), followed (optionally) by - * any WEP/ExtIV header (but only filled in for CCMP). - */ - if (hdrlen != sizeof(struct mwl8k_dma_data)) - skb_push(skb, sizeof(struct mwl8k_dma_data) - hdrlen); - - tr = (struct mwl8k_dma_data *)skb->data; - if (wh != &tr->wh) - memmove(&tr->wh, wh, hdrlen); - - /* Clear addr4 */ - memset(tr->wh.addr4, 0, ETH_ALEN); - - /* - * Firmware length is the length of the fully formed "802.11 - * payload". That is, everything except for the 802.11 header. - * This includes all crypto material including the MIC. - */ - tr->fwlen = cpu_to_le16(pktlen - hdrlen); -} - - -/* - * Packet reception. - */ -#define MWL8K_RX_CTRL_OWNED_BY_HOST 0x02 - -struct mwl8k_rx_desc { - __le16 pkt_len; - __u8 link_quality; - __u8 noise_level; - __le32 pkt_phys_addr; - __le32 next_rx_desc_phys_addr; - __le16 qos_control; - __le16 rate_info; - __le32 pad0[4]; - __u8 rssi; - __u8 channel; - __le16 pad1; - __u8 rx_ctrl; - __u8 rx_status; - __u8 pad2[2]; -} __attribute__((packed)); - -#define MWL8K_RX_DESCS 256 -#define MWL8K_RX_MAXSZ 3800 - -static int mwl8k_rxq_init(struct ieee80211_hw *hw, int index) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_rx_queue *rxq = priv->rxq + index; - int size; - int i; - - rxq->rx_desc_count = 0; - rxq->rx_head = 0; - rxq->rx_tail = 0; - - size = MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc); - - rxq->rx_desc_area = - pci_alloc_consistent(priv->pdev, size, &rxq->rx_desc_dma); - if (rxq->rx_desc_area == NULL) { - printk(KERN_ERR "%s: failed to alloc RX descriptors\n", - priv->name); - return -ENOMEM; - } - memset(rxq->rx_desc_area, 0, size); - - rxq->rx_skb = kmalloc(MWL8K_RX_DESCS * - sizeof(*rxq->rx_skb), GFP_KERNEL); - if (rxq->rx_skb == NULL) { - printk(KERN_ERR "%s: failed to alloc RX skbuff list\n", - priv->name); - pci_free_consistent(priv->pdev, size, - rxq->rx_desc_area, rxq->rx_desc_dma); - return -ENOMEM; - } - memset(rxq->rx_skb, 0, MWL8K_RX_DESCS * sizeof(*rxq->rx_skb)); - - for (i = 0; i < MWL8K_RX_DESCS; i++) { - struct mwl8k_rx_desc *rx_desc; - int nexti; - - rx_desc = rxq->rx_desc_area + i; - nexti = (i + 1) % MWL8K_RX_DESCS; - - rx_desc->next_rx_desc_phys_addr = - cpu_to_le32(rxq->rx_desc_dma - + nexti * sizeof(*rx_desc)); - rx_desc->rx_ctrl = MWL8K_RX_CTRL_OWNED_BY_HOST; - } - - return 0; -} - -static int rxq_refill(struct ieee80211_hw *hw, int index, int limit) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_rx_queue *rxq = priv->rxq + index; - int refilled; - - refilled = 0; - while (rxq->rx_desc_count < MWL8K_RX_DESCS && limit--) { - struct sk_buff *skb; - int rx; - - skb = dev_alloc_skb(MWL8K_RX_MAXSZ); - if (skb == NULL) - break; - - rxq->rx_desc_count++; - - rx = rxq->rx_tail; - rxq->rx_tail = (rx + 1) % MWL8K_RX_DESCS; - - rxq->rx_desc_area[rx].pkt_phys_addr = - cpu_to_le32(pci_map_single(priv->pdev, skb->data, - MWL8K_RX_MAXSZ, DMA_FROM_DEVICE)); - - rxq->rx_desc_area[rx].pkt_len = cpu_to_le16(MWL8K_RX_MAXSZ); - rxq->rx_skb[rx] = skb; - wmb(); - rxq->rx_desc_area[rx].rx_ctrl = 0; - - refilled++; - } - - return refilled; -} - -/* Must be called only when the card's reception is completely halted */ -static void mwl8k_rxq_deinit(struct ieee80211_hw *hw, int index) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_rx_queue *rxq = priv->rxq + index; - int i; - - for (i = 0; i < MWL8K_RX_DESCS; i++) { - if (rxq->rx_skb[i] != NULL) { - unsigned long addr; - - addr = le32_to_cpu(rxq->rx_desc_area[i].pkt_phys_addr); - pci_unmap_single(priv->pdev, addr, MWL8K_RX_MAXSZ, - PCI_DMA_FROMDEVICE); - kfree_skb(rxq->rx_skb[i]); - rxq->rx_skb[i] = NULL; - } - } - - kfree(rxq->rx_skb); - rxq->rx_skb = NULL; - - pci_free_consistent(priv->pdev, - MWL8K_RX_DESCS * sizeof(struct mwl8k_rx_desc), - rxq->rx_desc_area, rxq->rx_desc_dma); - rxq->rx_desc_area = NULL; -} - - -/* - * Scan a list of BSSIDs to process for finalize join. - * Allows for extension to process multiple BSSIDs. - */ -static inline int -mwl8k_capture_bssid(struct mwl8k_priv *priv, struct ieee80211_hdr *wh) -{ - return priv->capture_beacon && - ieee80211_is_beacon(wh->frame_control) && - !compare_ether_addr(wh->addr3, priv->capture_bssid); -} - -static inline void mwl8k_save_beacon(struct mwl8k_priv *priv, - struct sk_buff *skb) -{ - priv->capture_beacon = false; - memset(priv->capture_bssid, 0, ETH_ALEN); - - /* - * Use GFP_ATOMIC as rxq_process is called from - * the primary interrupt handler, memory allocation call - * must not sleep. - */ - priv->beacon_skb = skb_copy(skb, GFP_ATOMIC); - if (priv->beacon_skb != NULL) - queue_work(priv->config_wq, - &priv->finalize_join_worker); -} - -static int rxq_process(struct ieee80211_hw *hw, int index, int limit) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_rx_queue *rxq = priv->rxq + index; - int processed; - - processed = 0; - while (rxq->rx_desc_count && limit--) { - struct mwl8k_rx_desc *rx_desc; - struct sk_buff *skb; - struct ieee80211_rx_status status; - unsigned long addr; - struct ieee80211_hdr *wh; - - rx_desc = rxq->rx_desc_area + rxq->rx_head; - if (!(rx_desc->rx_ctrl & MWL8K_RX_CTRL_OWNED_BY_HOST)) - break; - rmb(); - - skb = rxq->rx_skb[rxq->rx_head]; - if (skb == NULL) - break; - rxq->rx_skb[rxq->rx_head] = NULL; - - rxq->rx_head = (rxq->rx_head + 1) % MWL8K_RX_DESCS; - rxq->rx_desc_count--; - - addr = le32_to_cpu(rx_desc->pkt_phys_addr); - pci_unmap_single(priv->pdev, addr, - MWL8K_RX_MAXSZ, PCI_DMA_FROMDEVICE); - - skb_put(skb, le16_to_cpu(rx_desc->pkt_len)); - mwl8k_remove_dma_header(skb); - - wh = (struct ieee80211_hdr *)skb->data; - - /* - * Check for pending join operation. save a copy of - * the beacon and schedule a tasklet to send finalize - * join command to the firmware. - */ - if (mwl8k_capture_bssid(priv, wh)) - mwl8k_save_beacon(priv, skb); - - memset(&status, 0, sizeof(status)); - status.mactime = 0; - status.signal = -rx_desc->rssi; - status.noise = -rx_desc->noise_level; - status.qual = rx_desc->link_quality; - status.antenna = 1; - status.rate_idx = 1; - status.flag = 0; - status.band = IEEE80211_BAND_2GHZ; - status.freq = ieee80211_channel_to_frequency(rx_desc->channel); - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx_irqsafe(hw, skb); - - processed++; - } - - return processed; -} - - -/* - * Packet transmission. - */ - -/* Transmit queue assignment. */ -enum { - MWL8K_WME_AC_BK = 0, /* background access */ - MWL8K_WME_AC_BE = 1, /* best effort access */ - MWL8K_WME_AC_VI = 2, /* video access */ - MWL8K_WME_AC_VO = 3, /* voice access */ -}; - -/* Transmit packet ACK policy */ -#define MWL8K_TXD_ACK_POLICY_NORMAL 0 -#define MWL8K_TXD_ACK_POLICY_BLOCKACK 3 - -#define GET_TXQ(_ac) (\ - ((_ac) == WME_AC_VO) ? MWL8K_WME_AC_VO : \ - ((_ac) == WME_AC_VI) ? MWL8K_WME_AC_VI : \ - ((_ac) == WME_AC_BK) ? MWL8K_WME_AC_BK : \ - MWL8K_WME_AC_BE) - -#define MWL8K_TXD_STATUS_OK 0x00000001 -#define MWL8K_TXD_STATUS_OK_RETRY 0x00000002 -#define MWL8K_TXD_STATUS_OK_MORE_RETRY 0x00000004 -#define MWL8K_TXD_STATUS_MULTICAST_TX 0x00000008 -#define MWL8K_TXD_STATUS_FW_OWNED 0x80000000 - -struct mwl8k_tx_desc { - __le32 status; - __u8 data_rate; - __u8 tx_priority; - __le16 qos_control; - __le32 pkt_phys_addr; - __le16 pkt_len; - __u8 dest_MAC_addr[ETH_ALEN]; - __le32 next_tx_desc_phys_addr; - __le32 reserved; - __le16 rate_info; - __u8 peer_id; - __u8 tx_frag_cnt; -} __attribute__((packed)); - -#define MWL8K_TX_DESCS 128 - -static int mwl8k_txq_init(struct ieee80211_hw *hw, int index) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_tx_queue *txq = priv->txq + index; - int size; - int i; - - memset(&txq->tx_stats, 0, sizeof(struct ieee80211_tx_queue_stats)); - txq->tx_stats.limit = MWL8K_TX_DESCS; - txq->tx_head = 0; - txq->tx_tail = 0; - - size = MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc); - - txq->tx_desc_area = - pci_alloc_consistent(priv->pdev, size, &txq->tx_desc_dma); - if (txq->tx_desc_area == NULL) { - printk(KERN_ERR "%s: failed to alloc TX descriptors\n", - priv->name); - return -ENOMEM; - } - memset(txq->tx_desc_area, 0, size); - - txq->tx_skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->tx_skb), - GFP_KERNEL); - if (txq->tx_skb == NULL) { - printk(KERN_ERR "%s: failed to alloc TX skbuff list\n", - priv->name); - pci_free_consistent(priv->pdev, size, - txq->tx_desc_area, txq->tx_desc_dma); - return -ENOMEM; - } - memset(txq->tx_skb, 0, MWL8K_TX_DESCS * sizeof(*txq->tx_skb)); - - for (i = 0; i < MWL8K_TX_DESCS; i++) { - struct mwl8k_tx_desc *tx_desc; - int nexti; - - tx_desc = txq->tx_desc_area + i; - nexti = (i + 1) % MWL8K_TX_DESCS; - - tx_desc->status = 0; - tx_desc->next_tx_desc_phys_addr = - cpu_to_le32(txq->tx_desc_dma + - nexti * sizeof(*tx_desc)); - } - - return 0; -} - -static inline void mwl8k_tx_start(struct mwl8k_priv *priv) -{ - iowrite32(MWL8K_H2A_INT_PPA_READY, - priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - iowrite32(MWL8K_H2A_INT_DUMMY, - priv->regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - ioread32(priv->regs + MWL8K_HIU_INT_CODE); -} - -static inline int mwl8k_txq_busy(struct mwl8k_priv *priv) -{ - return priv->pending_tx_pkts; -} - -struct mwl8k_txq_info { - u32 fw_owned; - u32 drv_owned; - u32 unused; - u32 len; - u32 head; - u32 tail; -}; - -static int mwl8k_scan_tx_ring(struct mwl8k_priv *priv, - struct mwl8k_txq_info *txinfo) -{ - int count, desc, status; - struct mwl8k_tx_queue *txq; - struct mwl8k_tx_desc *tx_desc; - int ndescs = 0; - - memset(txinfo, 0, MWL8K_TX_QUEUES * sizeof(struct mwl8k_txq_info)); - - spin_lock_bh(&priv->tx_lock); - for (count = 0; count < MWL8K_TX_QUEUES; count++) { - txq = priv->txq + count; - txinfo[count].len = txq->tx_stats.len; - txinfo[count].head = txq->tx_head; - txinfo[count].tail = txq->tx_tail; - for (desc = 0; desc < MWL8K_TX_DESCS; desc++) { - tx_desc = txq->tx_desc_area + desc; - status = le32_to_cpu(tx_desc->status); - - if (status & MWL8K_TXD_STATUS_FW_OWNED) - txinfo[count].fw_owned++; - else - txinfo[count].drv_owned++; - - if (tx_desc->pkt_len == 0) - txinfo[count].unused++; - } - } - spin_unlock_bh(&priv->tx_lock); - - return ndescs; -} - -/* - * Must be called with hw->fw_mutex held and tx queues stopped. - */ -static int mwl8k_tx_wait_empty(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - DECLARE_COMPLETION_ONSTACK(cmd_wait); - u32 count; - unsigned long timeout; - - might_sleep(); - - spin_lock_bh(&priv->tx_lock); - count = mwl8k_txq_busy(priv); - if (count) { - priv->tx_wait = &cmd_wait; - if (priv->radio_on) - mwl8k_tx_start(priv); - } - spin_unlock_bh(&priv->tx_lock); - - if (count) { - struct mwl8k_txq_info txinfo[MWL8K_TX_QUEUES]; - int index; - int newcount; - - timeout = wait_for_completion_timeout(&cmd_wait, - msecs_to_jiffies(5000)); - if (timeout) - return 0; - - spin_lock_bh(&priv->tx_lock); - priv->tx_wait = NULL; - newcount = mwl8k_txq_busy(priv); - spin_unlock_bh(&priv->tx_lock); - - printk(KERN_ERR "%s(%u) TIMEDOUT:5000ms Pend:%u-->%u\n", - __func__, __LINE__, count, newcount); - - mwl8k_scan_tx_ring(priv, txinfo); - for (index = 0; index < MWL8K_TX_QUEUES; index++) - printk(KERN_ERR - "TXQ:%u L:%u H:%u T:%u FW:%u DRV:%u U:%u\n", - index, - txinfo[index].len, - txinfo[index].head, - txinfo[index].tail, - txinfo[index].fw_owned, - txinfo[index].drv_owned, - txinfo[index].unused); - - return -ETIMEDOUT; - } - - return 0; -} - -#define MWL8K_TXD_SUCCESS(status) \ - ((status) & (MWL8K_TXD_STATUS_OK | \ - MWL8K_TXD_STATUS_OK_RETRY | \ - MWL8K_TXD_STATUS_OK_MORE_RETRY)) - -static void mwl8k_txq_reclaim(struct ieee80211_hw *hw, int index, int force) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_tx_queue *txq = priv->txq + index; - int wake = 0; - - while (txq->tx_stats.len > 0) { - int tx; - struct mwl8k_tx_desc *tx_desc; - unsigned long addr; - int size; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - u32 status; - - tx = txq->tx_head; - tx_desc = txq->tx_desc_area + tx; - - status = le32_to_cpu(tx_desc->status); - - if (status & MWL8K_TXD_STATUS_FW_OWNED) { - if (!force) - break; - tx_desc->status &= - ~cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED); - } - - txq->tx_head = (tx + 1) % MWL8K_TX_DESCS; - BUG_ON(txq->tx_stats.len == 0); - txq->tx_stats.len--; - priv->pending_tx_pkts--; - - addr = le32_to_cpu(tx_desc->pkt_phys_addr); - size = le16_to_cpu(tx_desc->pkt_len); - skb = txq->tx_skb[tx]; - txq->tx_skb[tx] = NULL; - - BUG_ON(skb == NULL); - pci_unmap_single(priv->pdev, addr, size, PCI_DMA_TODEVICE); - - mwl8k_remove_dma_header(skb); - - /* Mark descriptor as unused */ - tx_desc->pkt_phys_addr = 0; - tx_desc->pkt_len = 0; - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - if (MWL8K_TXD_SUCCESS(status)) - info->flags |= IEEE80211_TX_STAT_ACK; - - ieee80211_tx_status_irqsafe(hw, skb); - - wake = 1; - } - - if (wake && priv->radio_on && !mutex_is_locked(&priv->fw_mutex)) - ieee80211_wake_queue(hw, index); -} - -/* must be called only when the card's transmit is completely halted */ -static void mwl8k_txq_deinit(struct ieee80211_hw *hw, int index) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_tx_queue *txq = priv->txq + index; - - mwl8k_txq_reclaim(hw, index, 1); - - kfree(txq->tx_skb); - txq->tx_skb = NULL; - - pci_free_consistent(priv->pdev, - MWL8K_TX_DESCS * sizeof(struct mwl8k_tx_desc), - txq->tx_desc_area, txq->tx_desc_dma); - txq->tx_desc_area = NULL; -} - -static int -mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb) -{ - struct mwl8k_priv *priv = hw->priv; - struct ieee80211_tx_info *tx_info; - struct mwl8k_vif *mwl8k_vif; - struct ieee80211_hdr *wh; - struct mwl8k_tx_queue *txq; - struct mwl8k_tx_desc *tx; - dma_addr_t dma; - u32 txstatus; - u8 txdatarate; - u16 qos; - - wh = (struct ieee80211_hdr *)skb->data; - if (ieee80211_is_data_qos(wh->frame_control)) - qos = le16_to_cpu(*((__le16 *)ieee80211_get_qos_ctl(wh))); - else - qos = 0; - - mwl8k_add_dma_header(skb); - wh = &((struct mwl8k_dma_data *)skb->data)->wh; - - tx_info = IEEE80211_SKB_CB(skb); - mwl8k_vif = MWL8K_VIF(tx_info->control.vif); - - if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { - u16 seqno = mwl8k_vif->seqno; - - wh->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - wh->seq_ctrl |= cpu_to_le16(seqno << 4); - mwl8k_vif->seqno = seqno++ % 4096; - } - - /* Setup firmware control bit fields for each frame type. */ - txstatus = 0; - txdatarate = 0; - if (ieee80211_is_mgmt(wh->frame_control) || - ieee80211_is_ctl(wh->frame_control)) { - txdatarate = 0; - qos = mwl8k_qos_setbit_eosp(qos); - /* Set Queue size to unspecified */ - qos = mwl8k_qos_setbit_qlen(qos, 0xff); - } else if (ieee80211_is_data(wh->frame_control)) { - txdatarate = 1; - if (is_multicast_ether_addr(wh->addr1)) - txstatus |= MWL8K_TXD_STATUS_MULTICAST_TX; - - /* Send pkt in an aggregate if AMPDU frame. */ - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_BLOCKACK); - else - qos = mwl8k_qos_setbit_ack(qos, - MWL8K_TXD_ACK_POLICY_NORMAL); - - if (qos & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT) - qos = mwl8k_qos_setbit_amsdu(qos); - } - - dma = pci_map_single(priv->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE); - - if (pci_dma_mapping_error(priv->pdev, dma)) { - printk(KERN_DEBUG "%s: failed to dma map skb, " - "dropping TX frame.\n", priv->name); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - spin_lock_bh(&priv->tx_lock); - - txq = priv->txq + index; - - BUG_ON(txq->tx_skb[txq->tx_tail] != NULL); - txq->tx_skb[txq->tx_tail] = skb; - - tx = txq->tx_desc_area + txq->tx_tail; - tx->data_rate = txdatarate; - tx->tx_priority = index; - tx->qos_control = cpu_to_le16(qos); - tx->pkt_phys_addr = cpu_to_le32(dma); - tx->pkt_len = cpu_to_le16(skb->len); - tx->rate_info = 0; - tx->peer_id = mwl8k_vif->peer_id; - wmb(); - tx->status = cpu_to_le32(MWL8K_TXD_STATUS_FW_OWNED | txstatus); - - txq->tx_stats.count++; - txq->tx_stats.len++; - priv->pending_tx_pkts++; - - txq->tx_tail++; - if (txq->tx_tail == MWL8K_TX_DESCS) - txq->tx_tail = 0; - - if (txq->tx_head == txq->tx_tail) - ieee80211_stop_queue(hw, index); - - mwl8k_tx_start(priv); - - spin_unlock_bh(&priv->tx_lock); - - return NETDEV_TX_OK; -} - - -/* - * Firmware access. - * - * We have the following requirements for issuing firmware commands: - * - Some commands require that the packet transmit path is idle when - * the command is issued. (For simplicity, we'll just quiesce the - * transmit path for every command.) - * - There are certain sequences of commands that need to be issued to - * the hardware sequentially, with no other intervening commands. - * - * This leads to an implementation of a "firmware lock" as a mutex that - * can be taken recursively, and which is taken by both the low-level - * command submission function (mwl8k_post_cmd) as well as any users of - * that function that require issuing of an atomic sequence of commands, - * and quiesces the transmit path whenever it's taken. - */ -static int mwl8k_fw_lock(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - - if (priv->fw_mutex_owner != current) { - int rc; - - mutex_lock(&priv->fw_mutex); - ieee80211_stop_queues(hw); - - rc = mwl8k_tx_wait_empty(hw); - if (rc) { - ieee80211_wake_queues(hw); - mutex_unlock(&priv->fw_mutex); - - return rc; - } - - priv->fw_mutex_owner = current; - } - - priv->fw_mutex_depth++; - - return 0; -} - -static void mwl8k_fw_unlock(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - - if (!--priv->fw_mutex_depth) { - ieee80211_wake_queues(hw); - priv->fw_mutex_owner = NULL; - mutex_unlock(&priv->fw_mutex); - } -} - - -/* - * Command processing. - */ - -/* Timeout firmware commands after 2000ms */ -#define MWL8K_CMD_TIMEOUT_MS 2000 - -static int mwl8k_post_cmd(struct ieee80211_hw *hw, struct mwl8k_cmd_pkt *cmd) -{ - DECLARE_COMPLETION_ONSTACK(cmd_wait); - struct mwl8k_priv *priv = hw->priv; - void __iomem *regs = priv->regs; - dma_addr_t dma_addr; - unsigned int dma_size; - int rc; - unsigned long timeout = 0; - u8 buf[32]; - - cmd->result = 0xFFFF; - dma_size = le16_to_cpu(cmd->length); - dma_addr = pci_map_single(priv->pdev, cmd, dma_size, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(priv->pdev, dma_addr)) - return -ENOMEM; - - rc = mwl8k_fw_lock(hw); - if (rc) { - pci_unmap_single(priv->pdev, dma_addr, dma_size, - PCI_DMA_BIDIRECTIONAL); - return rc; - } - - priv->hostcmd_wait = &cmd_wait; - iowrite32(dma_addr, regs + MWL8K_HIU_GEN_PTR); - iowrite32(MWL8K_H2A_INT_DOORBELL, - regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - iowrite32(MWL8K_H2A_INT_DUMMY, - regs + MWL8K_HIU_H2A_INTERRUPT_EVENTS); - - timeout = wait_for_completion_timeout(&cmd_wait, - msecs_to_jiffies(MWL8K_CMD_TIMEOUT_MS)); - - priv->hostcmd_wait = NULL; - - mwl8k_fw_unlock(hw); - - pci_unmap_single(priv->pdev, dma_addr, dma_size, - PCI_DMA_BIDIRECTIONAL); - - if (!timeout) { - printk(KERN_ERR "%s: Command %s timeout after %u ms\n", - priv->name, - mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), - MWL8K_CMD_TIMEOUT_MS); - rc = -ETIMEDOUT; - } else { - rc = cmd->result ? -EINVAL : 0; - if (rc) - printk(KERN_ERR "%s: Command %s error 0x%x\n", - priv->name, - mwl8k_cmd_name(cmd->code, buf, sizeof(buf)), - le16_to_cpu(cmd->result)); - } - - return rc; -} - -/* - * GET_HW_SPEC. - */ -struct mwl8k_cmd_get_hw_spec { - struct mwl8k_cmd_pkt header; - __u8 hw_rev; - __u8 host_interface; - __le16 num_mcaddrs; - __u8 perm_addr[ETH_ALEN]; - __le16 region_code; - __le32 fw_rev; - __le32 ps_cookie; - __le32 caps; - __u8 mcs_bitmap[16]; - __le32 rx_queue_ptr; - __le32 num_tx_queues; - __le32 tx_queue_ptrs[MWL8K_TX_QUEUES]; - __le32 caps2; - __le32 num_tx_desc_per_queue; - __le32 total_rx_desc; -} __attribute__((packed)); - -static int mwl8k_cmd_get_hw_spec(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_get_hw_spec *cmd; - int rc; - int i; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_HW_SPEC); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - memset(cmd->perm_addr, 0xff, sizeof(cmd->perm_addr)); - cmd->ps_cookie = cpu_to_le32(priv->cookie_dma); - cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rx_desc_dma); - cmd->num_tx_queues = cpu_to_le32(MWL8K_TX_QUEUES); - for (i = 0; i < MWL8K_TX_QUEUES; i++) - cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[i].tx_desc_dma); - cmd->num_tx_desc_per_queue = cpu_to_le32(MWL8K_TX_DESCS); - cmd->total_rx_desc = cpu_to_le32(MWL8K_RX_DESCS); - - rc = mwl8k_post_cmd(hw, &cmd->header); - - if (!rc) { - SET_IEEE80211_PERM_ADDR(hw, cmd->perm_addr); - priv->num_mcaddrs = le16_to_cpu(cmd->num_mcaddrs); - priv->fw_rev = le32_to_cpu(cmd->fw_rev); - priv->hw_rev = cmd->hw_rev; - } - - kfree(cmd); - return rc; -} - -/* - * CMD_MAC_MULTICAST_ADR. - */ -struct mwl8k_cmd_mac_multicast_adr { - struct mwl8k_cmd_pkt header; - __le16 action; - __le16 numaddr; - __u8 addr[0][ETH_ALEN]; -}; - -#define MWL8K_ENABLE_RX_MULTICAST 0x000F - -static struct mwl8k_cmd_pkt * -__mwl8k_cmd_mac_multicast_adr(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_mac_multicast_adr *cmd; - int size; - int i; - - if (mc_count > priv->num_mcaddrs) - mc_count = priv->num_mcaddrs; - - size = sizeof(*cmd) + mc_count * ETH_ALEN; - - cmd = kzalloc(size, GFP_ATOMIC); - if (cmd == NULL) - return NULL; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_MAC_MULTICAST_ADR); - cmd->header.length = cpu_to_le16(size); - cmd->action = cpu_to_le16(MWL8K_ENABLE_RX_MULTICAST); - cmd->numaddr = cpu_to_le16(mc_count); - - for (i = 0; i < mc_count && mclist; i++) { - if (mclist->da_addrlen != ETH_ALEN) { - kfree(cmd); - return NULL; - } - memcpy(cmd->addr[i], mclist->da_addr, ETH_ALEN); - mclist = mclist->next; - } - - return &cmd->header; -} - -/* - * CMD_802_11_GET_STAT. - */ -struct mwl8k_cmd_802_11_get_stat { - struct mwl8k_cmd_pkt header; - __le16 action; - __le32 stats[64]; -} __attribute__((packed)); - -#define MWL8K_STAT_ACK_FAILURE 9 -#define MWL8K_STAT_RTS_FAILURE 12 -#define MWL8K_STAT_FCS_ERROR 24 -#define MWL8K_STAT_RTS_SUCCESS 11 - -static int mwl8k_cmd_802_11_get_stat(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct mwl8k_cmd_802_11_get_stat *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_GET_STAT); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_GET); - - rc = mwl8k_post_cmd(hw, &cmd->header); - if (!rc) { - stats->dot11ACKFailureCount = - le32_to_cpu(cmd->stats[MWL8K_STAT_ACK_FAILURE]); - stats->dot11RTSFailureCount = - le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_FAILURE]); - stats->dot11FCSErrorCount = - le32_to_cpu(cmd->stats[MWL8K_STAT_FCS_ERROR]); - stats->dot11RTSSuccessCount = - le32_to_cpu(cmd->stats[MWL8K_STAT_RTS_SUCCESS]); - } - kfree(cmd); - - return rc; -} - -/* - * CMD_802_11_RADIO_CONTROL. - */ -struct mwl8k_cmd_802_11_radio_control { - struct mwl8k_cmd_pkt header; - __le16 action; - __le16 control; - __le16 radio_on; -} __attribute__((packed)); - -static int -mwl8k_cmd_802_11_radio_control(struct ieee80211_hw *hw, bool enable, bool force) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_802_11_radio_control *cmd; - int rc; - - if (enable == priv->radio_on && !force) - return 0; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_RADIO_CONTROL); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->control = cpu_to_le16(priv->radio_short_preamble ? 3 : 1); - cmd->radio_on = cpu_to_le16(enable ? 0x0001 : 0x0000); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - if (!rc) - priv->radio_on = enable; - - return rc; -} - -static int mwl8k_cmd_802_11_radio_disable(struct ieee80211_hw *hw) -{ - return mwl8k_cmd_802_11_radio_control(hw, 0, 0); -} - -static int mwl8k_cmd_802_11_radio_enable(struct ieee80211_hw *hw) -{ - return mwl8k_cmd_802_11_radio_control(hw, 1, 0); -} - -static int -mwl8k_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) -{ - struct mwl8k_priv *priv; - - if (hw == NULL || hw->priv == NULL) - return -EINVAL; - priv = hw->priv; - - priv->radio_short_preamble = short_preamble; - - return mwl8k_cmd_802_11_radio_control(hw, 1, 1); -} - -/* - * CMD_802_11_RF_TX_POWER. - */ -#define MWL8K_TX_POWER_LEVEL_TOTAL 8 - -struct mwl8k_cmd_802_11_rf_tx_power { - struct mwl8k_cmd_pkt header; - __le16 action; - __le16 support_level; - __le16 current_level; - __le16 reserved; - __le16 power_level_list[MWL8K_TX_POWER_LEVEL_TOTAL]; -} __attribute__((packed)); - -static int mwl8k_cmd_802_11_rf_tx_power(struct ieee80211_hw *hw, int dBm) -{ - struct mwl8k_cmd_802_11_rf_tx_power *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_RF_TX_POWER); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->support_level = cpu_to_le16(dBm); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_PRE_SCAN. - */ -struct mwl8k_cmd_set_pre_scan { - struct mwl8k_cmd_pkt header; -} __attribute__((packed)); - -static int mwl8k_cmd_set_pre_scan(struct ieee80211_hw *hw) -{ - struct mwl8k_cmd_set_pre_scan *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_PRE_SCAN); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_POST_SCAN. - */ -struct mwl8k_cmd_set_post_scan { - struct mwl8k_cmd_pkt header; - __le32 isibss; - __u8 bssid[ETH_ALEN]; -} __attribute__((packed)); - -static int -mwl8k_cmd_set_post_scan(struct ieee80211_hw *hw, __u8 *mac) -{ - struct mwl8k_cmd_set_post_scan *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_POST_SCAN); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->isibss = 0; - memcpy(cmd->bssid, mac, ETH_ALEN); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_RF_CHANNEL. - */ -struct mwl8k_cmd_set_rf_channel { - struct mwl8k_cmd_pkt header; - __le16 action; - __u8 current_channel; - __le32 channel_flags; -} __attribute__((packed)); - -static int mwl8k_cmd_set_rf_channel(struct ieee80211_hw *hw, - struct ieee80211_channel *channel) -{ - struct mwl8k_cmd_set_rf_channel *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RF_CHANNEL); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->current_channel = channel->hw_value; - if (channel->band == IEEE80211_BAND_2GHZ) - cmd->channel_flags = cpu_to_le32(0x00000081); - else - cmd->channel_flags = cpu_to_le32(0x00000000); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_SLOT. - */ -struct mwl8k_cmd_set_slot { - struct mwl8k_cmd_pkt header; - __le16 action; - __u8 short_slot; -} __attribute__((packed)); - -static int mwl8k_cmd_set_slot(struct ieee80211_hw *hw, bool short_slot_time) -{ - struct mwl8k_cmd_set_slot *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_SLOT); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->short_slot = short_slot_time; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_MIMO_CONFIG. - */ -struct mwl8k_cmd_mimo_config { - struct mwl8k_cmd_pkt header; - __le32 action; - __u8 rx_antenna_map; - __u8 tx_antenna_map; -} __attribute__((packed)); - -static int mwl8k_cmd_mimo_config(struct ieee80211_hw *hw, __u8 rx, __u8 tx) -{ - struct mwl8k_cmd_mimo_config *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_MIMO_CONFIG); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le32((u32)MWL8K_CMD_SET); - cmd->rx_antenna_map = rx; - cmd->tx_antenna_map = tx; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_ENABLE_SNIFFER. - */ -struct mwl8k_cmd_enable_sniffer { - struct mwl8k_cmd_pkt header; - __le32 action; -} __attribute__((packed)); - -static int mwl8k_enable_sniffer(struct ieee80211_hw *hw, bool enable) -{ - struct mwl8k_cmd_enable_sniffer *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_ENABLE_SNIFFER); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le32(!!enable); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_RATEADAPT_MODE. - */ -struct mwl8k_cmd_set_rate_adapt_mode { - struct mwl8k_cmd_pkt header; - __le16 action; - __le16 mode; -} __attribute__((packed)); - -static int mwl8k_cmd_setrateadaptmode(struct ieee80211_hw *hw, __u16 mode) -{ - struct mwl8k_cmd_set_rate_adapt_mode *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATEADAPT_MODE); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_CMD_SET); - cmd->mode = cpu_to_le16(mode); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_WMM_MODE. - */ -struct mwl8k_cmd_set_wmm { - struct mwl8k_cmd_pkt header; - __le16 action; -} __attribute__((packed)); - -static int mwl8k_set_wmm(struct ieee80211_hw *hw, bool enable) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_set_wmm *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_WMM_MODE); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(!!enable); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - if (!rc) - priv->wmm_enabled = enable; - - return rc; -} - -/* - * CMD_SET_RTS_THRESHOLD. - */ -struct mwl8k_cmd_rts_threshold { - struct mwl8k_cmd_pkt header; - __le16 action; - __le16 threshold; -} __attribute__((packed)); - -static int mwl8k_rts_threshold(struct ieee80211_hw *hw, - u16 action, u16 threshold) -{ - struct mwl8k_cmd_rts_threshold *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_RTS_THRESHOLD); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(action); - cmd->threshold = cpu_to_le16(threshold); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_EDCA_PARAMS. - */ -struct mwl8k_cmd_set_edca_params { - struct mwl8k_cmd_pkt header; - - /* See MWL8K_SET_EDCA_XXX below */ - __le16 action; - - /* TX opportunity in units of 32 us */ - __le16 txop; - - /* Log exponent of max contention period: 0...15*/ - __u8 log_cw_max; - - /* Log exponent of min contention period: 0...15 */ - __u8 log_cw_min; - - /* Adaptive interframe spacing in units of 32us */ - __u8 aifs; - - /* TX queue to configure */ - __u8 txq; -} __attribute__((packed)); - -#define MWL8K_SET_EDCA_CW 0x01 -#define MWL8K_SET_EDCA_TXOP 0x02 -#define MWL8K_SET_EDCA_AIFS 0x04 - -#define MWL8K_SET_EDCA_ALL (MWL8K_SET_EDCA_CW | \ - MWL8K_SET_EDCA_TXOP | \ - MWL8K_SET_EDCA_AIFS) - -static int -mwl8k_set_edca_params(struct ieee80211_hw *hw, __u8 qnum, - __u16 cw_min, __u16 cw_max, - __u8 aifs, __u16 txop) -{ - struct mwl8k_cmd_set_edca_params *cmd; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_EDCA_PARAMS); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->action = cpu_to_le16(MWL8K_SET_EDCA_ALL); - cmd->txop = cpu_to_le16(txop); - cmd->log_cw_max = (u8)ilog2(cw_max + 1); - cmd->log_cw_min = (u8)ilog2(cw_min + 1); - cmd->aifs = aifs; - cmd->txq = qnum; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_FINALIZE_JOIN. - */ - -/* FJ beacon buffer size is compiled into the firmware. */ -#define MWL8K_FJ_BEACON_MAXLEN 128 - -struct mwl8k_cmd_finalize_join { - struct mwl8k_cmd_pkt header; - __le32 sleep_interval; /* Number of beacon periods to sleep */ - __u8 beacon_data[MWL8K_FJ_BEACON_MAXLEN]; -} __attribute__((packed)); - -static int mwl8k_finalize_join(struct ieee80211_hw *hw, void *frame, - __u16 framelen, __u16 dtim) -{ - struct mwl8k_cmd_finalize_join *cmd; - struct ieee80211_mgmt *payload = frame; - u16 hdrlen; - u32 payload_len; - int rc; - - if (frame == NULL) - return -EINVAL; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_FINALIZE_JOIN); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->sleep_interval = cpu_to_le32(dtim ? dtim : 1); - - hdrlen = ieee80211_hdrlen(payload->frame_control); - - payload_len = framelen > hdrlen ? framelen - hdrlen : 0; - - /* XXX TBD Might just have to abort and return an error */ - if (payload_len > MWL8K_FJ_BEACON_MAXLEN) - printk(KERN_ERR "%s(): WARNING: Incomplete beacon " - "sent to firmware. Sz=%u MAX=%u\n", __func__, - payload_len, MWL8K_FJ_BEACON_MAXLEN); - - if (payload_len > MWL8K_FJ_BEACON_MAXLEN) - payload_len = MWL8K_FJ_BEACON_MAXLEN; - - if (payload && payload_len) - memcpy(cmd->beacon_data, &payload->u.beacon, payload_len); - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - return rc; -} - -/* - * CMD_UPDATE_STADB. - */ -struct mwl8k_cmd_update_sta_db { - struct mwl8k_cmd_pkt header; - - /* See STADB_ACTION_TYPE */ - __le32 action; - - /* Peer MAC address */ - __u8 peer_addr[ETH_ALEN]; - - __le32 reserved; - - /* Peer info - valid during add/update. */ - struct peer_capability_info peer_info; -} __attribute__((packed)); - -static int mwl8k_cmd_update_sta_db(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, __u32 action) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct ieee80211_bss_conf *info = &mv_vif->bss_info; - struct mwl8k_cmd_update_sta_db *cmd; - struct peer_capability_info *peer_info; - struct ieee80211_rate *bitrates = mv_vif->legacy_rates; - int rc; - __u8 count, *rates; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_STADB); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->action = cpu_to_le32(action); - peer_info = &cmd->peer_info; - memcpy(cmd->peer_addr, mv_vif->bssid, ETH_ALEN); - - switch (action) { - case MWL8K_STA_DB_ADD_ENTRY: - case MWL8K_STA_DB_MODIFY_ENTRY: - /* Build peer_info block */ - peer_info->peer_type = MWL8K_PEER_TYPE_ACCESSPOINT; - peer_info->basic_caps = cpu_to_le16(info->assoc_capability); - peer_info->interop = 1; - peer_info->amsdu_enabled = 0; - - rates = peer_info->legacy_rates; - for (count = 0; count < mv_vif->legacy_nrates; count++) - rates[count] = bitrates[count].hw_value; - - rc = mwl8k_post_cmd(hw, &cmd->header); - if (rc == 0) - mv_vif->peer_id = peer_info->station_id; - - break; - - case MWL8K_STA_DB_DEL_ENTRY: - case MWL8K_STA_DB_FLUSH: - default: - rc = mwl8k_post_cmd(hw, &cmd->header); - if (rc == 0) - mv_vif->peer_id = 0; - break; - } - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_AID. - */ -#define MWL8K_RATE_INDEX_MAX_ARRAY 14 - -#define MWL8K_FRAME_PROT_DISABLED 0x00 -#define MWL8K_FRAME_PROT_11G 0x07 -#define MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY 0x02 -#define MWL8K_FRAME_PROT_11N_HT_ALL 0x06 - -struct mwl8k_cmd_update_set_aid { - struct mwl8k_cmd_pkt header; - __le16 aid; - - /* AP's MAC address (BSSID) */ - __u8 bssid[ETH_ALEN]; - __le16 protection_mode; - __u8 supp_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; -} __attribute__((packed)); - -static int mwl8k_cmd_set_aid(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct ieee80211_bss_conf *info = &mv_vif->bss_info; - struct mwl8k_cmd_update_set_aid *cmd; - struct ieee80211_rate *bitrates = mv_vif->legacy_rates; - int count; - u16 prot_mode; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_AID); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - cmd->aid = cpu_to_le16(info->aid); - - memcpy(cmd->bssid, mv_vif->bssid, ETH_ALEN); - - if (info->use_cts_prot) { - prot_mode = MWL8K_FRAME_PROT_11G; - } else { - switch (info->ht_operation_mode & - IEEE80211_HT_OP_MODE_PROTECTION) { - case IEEE80211_HT_OP_MODE_PROTECTION_20MHZ: - prot_mode = MWL8K_FRAME_PROT_11N_HT_40MHZ_ONLY; - break; - case IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED: - prot_mode = MWL8K_FRAME_PROT_11N_HT_ALL; - break; - default: - prot_mode = MWL8K_FRAME_PROT_DISABLED; - break; - } - } - cmd->protection_mode = cpu_to_le16(prot_mode); - - for (count = 0; count < mv_vif->legacy_nrates; count++) - cmd->supp_rates[count] = bitrates[count].hw_value; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_SET_RATE. - */ -struct mwl8k_cmd_update_rateset { - struct mwl8k_cmd_pkt header; - __u8 legacy_rates[MWL8K_RATE_INDEX_MAX_ARRAY]; - - /* Bitmap for supported MCS codes. */ - __u8 mcs_set[MWL8K_IEEE_LEGACY_DATA_RATES]; - __u8 reserved[MWL8K_IEEE_LEGACY_DATA_RATES]; -} __attribute__((packed)); - -static int mwl8k_update_rateset(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct mwl8k_vif *mv_vif = MWL8K_VIF(vif); - struct mwl8k_cmd_update_rateset *cmd; - struct ieee80211_rate *bitrates = mv_vif->legacy_rates; - int count; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_SET_RATE); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - for (count = 0; count < mv_vif->legacy_nrates; count++) - cmd->legacy_rates[count] = bitrates[count].hw_value; - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - -/* - * CMD_USE_FIXED_RATE. - */ -#define MWL8K_RATE_TABLE_SIZE 8 -#define MWL8K_UCAST_RATE 0 -#define MWL8K_USE_AUTO_RATE 0x0002 - -struct mwl8k_rate_entry { - /* Set to 1 if HT rate, 0 if legacy. */ - __le32 is_ht_rate; - - /* Set to 1 to use retry_count field. */ - __le32 enable_retry; - - /* Specified legacy rate or MCS. */ - __le32 rate; - - /* Number of allowed retries. */ - __le32 retry_count; -} __attribute__((packed)); - -struct mwl8k_rate_table { - /* 1 to allow specified rate and below */ - __le32 allow_rate_drop; - __le32 num_rates; - struct mwl8k_rate_entry rate_entry[MWL8K_RATE_TABLE_SIZE]; -} __attribute__((packed)); - -struct mwl8k_cmd_use_fixed_rate { - struct mwl8k_cmd_pkt header; - __le32 action; - struct mwl8k_rate_table rate_table; - - /* Unicast, Broadcast or Multicast */ - __le32 rate_type; - __le32 reserved1; - __le32 reserved2; -} __attribute__((packed)); - -static int mwl8k_cmd_use_fixed_rate(struct ieee80211_hw *hw, - u32 action, u32 rate_type, struct mwl8k_rate_table *rate_table) -{ - struct mwl8k_cmd_use_fixed_rate *cmd; - int count; - int rc; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (cmd == NULL) - return -ENOMEM; - - cmd->header.code = cpu_to_le16(MWL8K_CMD_USE_FIXED_RATE); - cmd->header.length = cpu_to_le16(sizeof(*cmd)); - - cmd->action = cpu_to_le32(action); - cmd->rate_type = cpu_to_le32(rate_type); - - if (rate_table != NULL) { - /* Copy over each field manually so - * that bitflipping can be done - */ - cmd->rate_table.allow_rate_drop = - cpu_to_le32(rate_table->allow_rate_drop); - cmd->rate_table.num_rates = - cpu_to_le32(rate_table->num_rates); - - for (count = 0; count < rate_table->num_rates; count++) { - struct mwl8k_rate_entry *dst = - &cmd->rate_table.rate_entry[count]; - struct mwl8k_rate_entry *src = - &rate_table->rate_entry[count]; - - dst->is_ht_rate = cpu_to_le32(src->is_ht_rate); - dst->enable_retry = cpu_to_le32(src->enable_retry); - dst->rate = cpu_to_le32(src->rate); - dst->retry_count = cpu_to_le32(src->retry_count); - } - } - - rc = mwl8k_post_cmd(hw, &cmd->header); - kfree(cmd); - - return rc; -} - - -/* - * Interrupt handling. - */ -static irqreturn_t mwl8k_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *hw = dev_id; - struct mwl8k_priv *priv = hw->priv; - u32 status; - - status = ioread32(priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - iowrite32(~status, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - - if (!status) - return IRQ_NONE; - - if (status & MWL8K_A2H_INT_TX_DONE) - tasklet_schedule(&priv->tx_reclaim_task); - - if (status & MWL8K_A2H_INT_RX_READY) { - while (rxq_process(hw, 0, 1)) - rxq_refill(hw, 0, 1); - } - - if (status & MWL8K_A2H_INT_OPC_DONE) { - if (priv->hostcmd_wait != NULL) - complete(priv->hostcmd_wait); - } - - if (status & MWL8K_A2H_INT_QUEUE_EMPTY) { - if (!mutex_is_locked(&priv->fw_mutex) && - priv->radio_on && mwl8k_txq_busy(priv)) - mwl8k_tx_start(priv); - } - - return IRQ_HANDLED; -} - - -/* - * Core driver operations. - */ -static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct mwl8k_priv *priv = hw->priv; - int index = skb_get_queue_mapping(skb); - int rc; - - if (priv->current_channel == NULL) { - printk(KERN_DEBUG "%s: dropped TX frame since radio " - "disabled\n", priv->name); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - rc = mwl8k_txq_xmit(hw, index, skb); - - return rc; -} - -static int mwl8k_start(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - int rc; - - rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, - IRQF_SHARED, MWL8K_NAME, hw); - if (rc) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - priv->name); - return -EIO; - } - - /* Enable tx reclaim tasklet */ - tasklet_enable(&priv->tx_reclaim_task); - - /* Enable interrupts */ - iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - - rc = mwl8k_fw_lock(hw); - if (!rc) { - rc = mwl8k_cmd_802_11_radio_enable(hw); - - if (!rc) - rc = mwl8k_cmd_set_pre_scan(hw); - - if (!rc) - rc = mwl8k_cmd_set_post_scan(hw, - "\x00\x00\x00\x00\x00\x00"); - - if (!rc) - rc = mwl8k_cmd_setrateadaptmode(hw, 0); - - if (!rc) - rc = mwl8k_set_wmm(hw, 0); - - if (!rc) - rc = mwl8k_enable_sniffer(hw, 0); - - mwl8k_fw_unlock(hw); - } - - if (rc) { - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - free_irq(priv->pdev->irq, hw); - tasklet_disable(&priv->tx_reclaim_task); - } - - return rc; -} - -static void mwl8k_stop(struct ieee80211_hw *hw) -{ - struct mwl8k_priv *priv = hw->priv; - int i; - - mwl8k_cmd_802_11_radio_disable(hw); - - ieee80211_stop_queues(hw); - - /* Disable interrupts */ - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - free_irq(priv->pdev->irq, hw); - - /* Stop finalize join worker */ - cancel_work_sync(&priv->finalize_join_worker); - if (priv->beacon_skb != NULL) - dev_kfree_skb(priv->beacon_skb); - - /* Stop tx reclaim tasklet */ - tasklet_disable(&priv->tx_reclaim_task); - - /* Stop config thread */ - flush_workqueue(priv->config_wq); - - /* Return all skbs to mac80211 */ - for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, 1); -} - -static int mwl8k_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_vif *mwl8k_vif; - - /* - * We only support one active interface at a time. - */ - if (priv->vif != NULL) - return -EBUSY; - - /* - * We only support managed interfaces for now. - */ - if (conf->type != NL80211_IFTYPE_STATION) - return -EINVAL; - - /* Clean out driver private area */ - mwl8k_vif = MWL8K_VIF(conf->vif); - memset(mwl8k_vif, 0, sizeof(*mwl8k_vif)); - - /* Save the mac address */ - memcpy(mwl8k_vif->mac_addr, conf->mac_addr, ETH_ALEN); - - /* Back pointer to parent config block */ - mwl8k_vif->priv = priv; - - /* Setup initial PHY parameters */ - memcpy(mwl8k_vif->legacy_rates, - priv->rates, sizeof(mwl8k_vif->legacy_rates)); - mwl8k_vif->legacy_nrates = ARRAY_SIZE(priv->rates); - - /* Set Initial sequence number to zero */ - mwl8k_vif->seqno = 0; - - priv->vif = conf->vif; - priv->current_channel = NULL; - - return 0; -} - -static void mwl8k_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct mwl8k_priv *priv = hw->priv; - - if (priv->vif == NULL) - return; - - priv->vif = NULL; -} - -static int mwl8k_config(struct ieee80211_hw *hw, u32 changed) -{ - struct ieee80211_conf *conf = &hw->conf; - struct mwl8k_priv *priv = hw->priv; - int rc; - - if (conf->flags & IEEE80211_CONF_IDLE) { - mwl8k_cmd_802_11_radio_disable(hw); - priv->current_channel = NULL; - return 0; - } - - rc = mwl8k_fw_lock(hw); - if (rc) - return rc; - - rc = mwl8k_cmd_802_11_radio_enable(hw); - if (rc) - goto out; - - rc = mwl8k_cmd_set_rf_channel(hw, conf->channel); - if (rc) - goto out; - - priv->current_channel = conf->channel; - - if (conf->power_level > 18) - conf->power_level = 18; - rc = mwl8k_cmd_802_11_rf_tx_power(hw, conf->power_level); - if (rc) - goto out; - - if (mwl8k_cmd_mimo_config(hw, 0x7, 0x7)) - rc = -EINVAL; - -out: - mwl8k_fw_unlock(hw); - - return rc; -} - -static void mwl8k_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif); - int rc; - - if (changed & BSS_CHANGED_BSSID) - memcpy(mwl8k_vif->bssid, info->bssid, ETH_ALEN); - - if ((changed & BSS_CHANGED_ASSOC) == 0) - return; - - priv->capture_beacon = false; - - rc = mwl8k_fw_lock(hw); - if (rc) - return; - - if (info->assoc) { - memcpy(&mwl8k_vif->bss_info, info, - sizeof(struct ieee80211_bss_conf)); - - /* Install rates */ - rc = mwl8k_update_rateset(hw, vif); - if (rc) - goto out; - - /* Turn on rate adaptation */ - rc = mwl8k_cmd_use_fixed_rate(hw, MWL8K_USE_AUTO_RATE, - MWL8K_UCAST_RATE, NULL); - if (rc) - goto out; - - /* Set radio preamble */ - rc = mwl8k_set_radio_preamble(hw, info->use_short_preamble); - if (rc) - goto out; - - /* Set slot time */ - rc = mwl8k_cmd_set_slot(hw, info->use_short_slot); - if (rc) - goto out; - - /* Update peer rate info */ - rc = mwl8k_cmd_update_sta_db(hw, vif, - MWL8K_STA_DB_MODIFY_ENTRY); - if (rc) - goto out; - - /* Set AID */ - rc = mwl8k_cmd_set_aid(hw, vif); - if (rc) - goto out; - - /* - * Finalize the join. Tell rx handler to process - * next beacon from our BSSID. - */ - memcpy(priv->capture_bssid, mwl8k_vif->bssid, ETH_ALEN); - priv->capture_beacon = true; - } else { - rc = mwl8k_cmd_update_sta_db(hw, vif, MWL8K_STA_DB_DEL_ENTRY); - memset(&mwl8k_vif->bss_info, 0, - sizeof(struct ieee80211_bss_conf)); - memset(mwl8k_vif->bssid, 0, ETH_ALEN); - } - -out: - mwl8k_fw_unlock(hw); -} - -static u64 mwl8k_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - struct mwl8k_cmd_pkt *cmd; - - cmd = __mwl8k_cmd_mac_multicast_adr(hw, mc_count, mclist); - - return (unsigned long)cmd; -} - -static void mwl8k_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_cmd_pkt *multicast_adr_cmd; - - /* Clear unsupported feature flags */ - *total_flags &= FIF_BCN_PRBRESP_PROMISC; - - if (mwl8k_fw_lock(hw)) - return; - - if (changed_flags & FIF_BCN_PRBRESP_PROMISC) { - if (*total_flags & FIF_BCN_PRBRESP_PROMISC) - mwl8k_cmd_set_pre_scan(hw); - else { - u8 *bssid; - - bssid = "\x00\x00\x00\x00\x00\x00"; - if (priv->vif != NULL) - bssid = MWL8K_VIF(priv->vif)->bssid; - - mwl8k_cmd_set_post_scan(hw, bssid); - } - } - - multicast_adr_cmd = (void *)(unsigned long)multicast; - if (multicast_adr_cmd != NULL) { - mwl8k_post_cmd(hw, multicast_adr_cmd); - kfree(multicast_adr_cmd); - } - - mwl8k_fw_unlock(hw); -} - -static int mwl8k_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - return mwl8k_rts_threshold(hw, MWL8K_CMD_SET, value); -} - -static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct mwl8k_priv *priv = hw->priv; - int rc; - - rc = mwl8k_fw_lock(hw); - if (!rc) { - if (!priv->wmm_enabled) - rc = mwl8k_set_wmm(hw, 1); - - if (!rc) - rc = mwl8k_set_edca_params(hw, queue, - params->cw_min, - params->cw_max, - params->aifs, - params->txop); - - mwl8k_fw_unlock(hw); - } - - return rc; -} - -static int mwl8k_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct mwl8k_priv *priv = hw->priv; - struct mwl8k_tx_queue *txq; - int index; - - spin_lock_bh(&priv->tx_lock); - for (index = 0; index < MWL8K_TX_QUEUES; index++) { - txq = priv->txq + index; - memcpy(&stats[index], &txq->tx_stats, - sizeof(struct ieee80211_tx_queue_stats)); - } - spin_unlock_bh(&priv->tx_lock); - - return 0; -} - -static int mwl8k_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - return mwl8k_cmd_802_11_get_stat(hw, stats); -} - -static const struct ieee80211_ops mwl8k_ops = { - .tx = mwl8k_tx, - .start = mwl8k_start, - .stop = mwl8k_stop, - .add_interface = mwl8k_add_interface, - .remove_interface = mwl8k_remove_interface, - .config = mwl8k_config, - .bss_info_changed = mwl8k_bss_info_changed, - .prepare_multicast = mwl8k_prepare_multicast, - .configure_filter = mwl8k_configure_filter, - .set_rts_threshold = mwl8k_set_rts_threshold, - .conf_tx = mwl8k_conf_tx, - .get_tx_stats = mwl8k_get_tx_stats, - .get_stats = mwl8k_get_stats, -}; - -static void mwl8k_tx_reclaim_handler(unsigned long data) -{ - int i; - struct ieee80211_hw *hw = (struct ieee80211_hw *) data; - struct mwl8k_priv *priv = hw->priv; - - spin_lock_bh(&priv->tx_lock); - for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, 0); - - if (priv->tx_wait != NULL && mwl8k_txq_busy(priv) == 0) { - complete(priv->tx_wait); - priv->tx_wait = NULL; - } - spin_unlock_bh(&priv->tx_lock); -} - -static void mwl8k_finalize_join_worker(struct work_struct *work) -{ - struct mwl8k_priv *priv = - container_of(work, struct mwl8k_priv, finalize_join_worker); - struct sk_buff *skb = priv->beacon_skb; - u8 dtim = MWL8K_VIF(priv->vif)->bss_info.dtim_period; - - mwl8k_finalize_join(priv->hw, skb->data, skb->len, dtim); - dev_kfree_skb(skb); - - priv->beacon_skb = NULL; -} - -static int __devinit mwl8k_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - static int printed_version = 0; - struct ieee80211_hw *hw; - struct mwl8k_priv *priv; - int rc; - int i; - - if (!printed_version) { - printk(KERN_INFO "%s version %s\n", MWL8K_DESC, MWL8K_VERSION); - printed_version = 1; - } - - rc = pci_enable_device(pdev); - if (rc) { - printk(KERN_ERR "%s: Cannot enable new PCI device\n", - MWL8K_NAME); - return rc; - } - - rc = pci_request_regions(pdev, MWL8K_NAME); - if (rc) { - printk(KERN_ERR "%s: Cannot obtain PCI resources\n", - MWL8K_NAME); - return rc; - } - - pci_set_master(pdev); - - hw = ieee80211_alloc_hw(sizeof(*priv), &mwl8k_ops); - if (hw == NULL) { - printk(KERN_ERR "%s: ieee80211 alloc failed\n", MWL8K_NAME); - rc = -ENOMEM; - goto err_free_reg; - } - - priv = hw->priv; - priv->hw = hw; - priv->pdev = pdev; - priv->wmm_enabled = false; - priv->pending_tx_pkts = 0; - strncpy(priv->name, MWL8K_NAME, sizeof(priv->name)); - - SET_IEEE80211_DEV(hw, &pdev->dev); - pci_set_drvdata(pdev, hw); - - priv->regs = pci_iomap(pdev, 1, 0x10000); - if (priv->regs == NULL) { - printk(KERN_ERR "%s: Cannot map device memory\n", priv->name); - goto err_iounmap; - } - - memcpy(priv->channels, mwl8k_channels, sizeof(mwl8k_channels)); - priv->band.band = IEEE80211_BAND_2GHZ; - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(mwl8k_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = ARRAY_SIZE(mwl8k_rates); - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - - BUILD_BUG_ON(sizeof(priv->rates) != sizeof(mwl8k_rates)); - memcpy(priv->rates, mwl8k_rates, sizeof(mwl8k_rates)); - - /* - * Extra headroom is the size of the required DMA header - * minus the size of the smallest 802.11 frame (CTS frame). - */ - hw->extra_tx_headroom = - sizeof(struct mwl8k_dma_data) - sizeof(struct ieee80211_cts); - - hw->channel_change_time = 10; - - hw->queues = MWL8K_TX_QUEUES; - - hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - - /* Set rssi and noise values to dBm */ - hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_NOISE_DBM; - hw->vif_data_size = sizeof(struct mwl8k_vif); - priv->vif = NULL; - - /* Set default radio state and preamble */ - priv->radio_on = 0; - priv->radio_short_preamble = 0; - - /* Finalize join worker */ - INIT_WORK(&priv->finalize_join_worker, mwl8k_finalize_join_worker); - - /* TX reclaim tasklet */ - tasklet_init(&priv->tx_reclaim_task, - mwl8k_tx_reclaim_handler, (unsigned long)hw); - tasklet_disable(&priv->tx_reclaim_task); - - /* Config workthread */ - priv->config_wq = create_singlethread_workqueue("mwl8k_config"); - if (priv->config_wq == NULL) - goto err_iounmap; - - /* Power management cookie */ - priv->cookie = pci_alloc_consistent(priv->pdev, 4, &priv->cookie_dma); - if (priv->cookie == NULL) - goto err_iounmap; - - rc = mwl8k_rxq_init(hw, 0); - if (rc) - goto err_iounmap; - rxq_refill(hw, 0, INT_MAX); - - mutex_init(&priv->fw_mutex); - priv->fw_mutex_owner = NULL; - priv->fw_mutex_depth = 0; - priv->tx_wait = NULL; - priv->hostcmd_wait = NULL; - - spin_lock_init(&priv->tx_lock); - - for (i = 0; i < MWL8K_TX_QUEUES; i++) { - rc = mwl8k_txq_init(hw, i); - if (rc) - goto err_free_queues; - } - - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS); - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_CLEAR_SEL); - iowrite32(0xffffffff, priv->regs + MWL8K_HIU_A2H_INTERRUPT_STATUS_MASK); - - rc = request_irq(priv->pdev->irq, &mwl8k_interrupt, - IRQF_SHARED, MWL8K_NAME, hw); - if (rc) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - priv->name); - goto err_free_queues; - } - - /* Reset firmware and hardware */ - mwl8k_hw_reset(priv); - - /* Ask userland hotplug daemon for the device firmware */ - rc = mwl8k_request_firmware(priv, (u32)id->driver_data); - if (rc) { - printk(KERN_ERR "%s: Firmware files not found\n", priv->name); - goto err_free_irq; - } - - /* Load firmware into hardware */ - rc = mwl8k_load_firmware(priv); - if (rc) { - printk(KERN_ERR "%s: Cannot start firmware\n", priv->name); - goto err_stop_firmware; - } - - /* Reclaim memory once firmware is successfully loaded */ - mwl8k_release_firmware(priv); - - /* - * Temporarily enable interrupts. Initial firmware host - * commands use interrupts and avoids polling. Disable - * interrupts when done. - */ - iowrite32(MWL8K_A2H_EVENTS, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - - /* Get config data, mac addrs etc */ - rc = mwl8k_cmd_get_hw_spec(hw); - if (rc) { - printk(KERN_ERR "%s: Cannot initialise firmware\n", priv->name); - goto err_stop_firmware; - } - - /* Turn radio off */ - rc = mwl8k_cmd_802_11_radio_disable(hw); - if (rc) { - printk(KERN_ERR "%s: Cannot disable\n", priv->name); - goto err_stop_firmware; - } - - /* Disable interrupts */ - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - free_irq(priv->pdev->irq, hw); - - rc = ieee80211_register_hw(hw); - if (rc) { - printk(KERN_ERR "%s: Cannot register device\n", priv->name); - goto err_stop_firmware; - } - - printk(KERN_INFO "%s: 88w%u v%d, %pM, firmware version %u.%u.%u.%u\n", - wiphy_name(hw->wiphy), priv->part_num, priv->hw_rev, - hw->wiphy->perm_addr, - (priv->fw_rev >> 24) & 0xff, (priv->fw_rev >> 16) & 0xff, - (priv->fw_rev >> 8) & 0xff, priv->fw_rev & 0xff); - - return 0; - -err_stop_firmware: - mwl8k_hw_reset(priv); - mwl8k_release_firmware(priv); - -err_free_irq: - iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK); - free_irq(priv->pdev->irq, hw); - -err_free_queues: - for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_deinit(hw, i); - mwl8k_rxq_deinit(hw, 0); - -err_iounmap: - if (priv->cookie != NULL) - pci_free_consistent(priv->pdev, 4, - priv->cookie, priv->cookie_dma); - - if (priv->regs != NULL) - pci_iounmap(pdev, priv->regs); - - if (priv->config_wq != NULL) - destroy_workqueue(priv->config_wq); - - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(hw); - -err_free_reg: - pci_release_regions(pdev); - pci_disable_device(pdev); - - return rc; -} - -static void __devexit mwl8k_shutdown(struct pci_dev *pdev) -{ - printk(KERN_ERR "===>%s(%u)\n", __func__, __LINE__); -} - -static void __devexit mwl8k_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pdev); - struct mwl8k_priv *priv; - int i; - - if (hw == NULL) - return; - priv = hw->priv; - - ieee80211_stop_queues(hw); - - ieee80211_unregister_hw(hw); - - /* Remove tx reclaim tasklet */ - tasklet_kill(&priv->tx_reclaim_task); - - /* Stop config thread */ - destroy_workqueue(priv->config_wq); - - /* Stop hardware */ - mwl8k_hw_reset(priv); - - /* Return all skbs to mac80211 */ - for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_reclaim(hw, i, 1); - - for (i = 0; i < MWL8K_TX_QUEUES; i++) - mwl8k_txq_deinit(hw, i); - - mwl8k_rxq_deinit(hw, 0); - - pci_free_consistent(priv->pdev, 4, - priv->cookie, priv->cookie_dma); - - pci_iounmap(pdev, priv->regs); - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(hw); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -static struct pci_driver mwl8k_driver = { - .name = MWL8K_NAME, - .id_table = mwl8k_table, - .probe = mwl8k_probe, - .remove = __devexit_p(mwl8k_remove), - .shutdown = __devexit_p(mwl8k_shutdown), -}; - -static int __init mwl8k_init(void) -{ - return pci_register_driver(&mwl8k_driver); -} - -static void __exit mwl8k_exit(void) -{ - pci_unregister_driver(&mwl8k_driver); -} - -module_init(mwl8k_init); -module_exit(mwl8k_exit); diff --git a/drivers/net/wireless/netwave_cs.c b/drivers/net/wireless/netwave_cs.c deleted file mode 100644 index 9498b46c99a4..000000000000 --- a/drivers/net/wireless/netwave_cs.c +++ /dev/null @@ -1,1389 +0,0 @@ -/********************************************************************* - * - * Filename: netwave_cs.c - * Version: 0.4.1 - * Description: Netwave AirSurfer Wireless LAN PC Card driver - * Status: Experimental. - * Authors: John Markus Bjørndalen - * Dag Brattli - * David Hinds - * Created at: A long time ago! - * Modified at: Mon Nov 10 11:54:37 1997 - * Modified by: Dag Brattli - * - * Copyright (c) 1997 University of Tromsø, Norway - * - * Revision History: - * - * 08-Nov-97 15:14:47 John Markus Bjørndalen - * - Fixed some bugs in netwave_rx and cleaned it up a bit. - * (One of the bugs would have destroyed packets when receiving - * multiple packets per interrupt). - * - Cleaned up parts of newave_hw_xmit. - * - A few general cleanups. - * 24-Oct-97 13:17:36 Dag Brattli - * - Fixed netwave_rx receive function (got updated docs) - * Others: - * - Changed name from xircnw to netwave, take a look at - * http://www.netwave-wireless.com - * - Some reorganizing of the code - * - Removed possible race condition between interrupt handler and transmit - * function - * - Started to add wireless extensions, but still needs some coding - * - Added watchdog for better handling of transmission timeouts - * (hopefully this works better) - ********************************************************************/ - -/* To have statistics (just packets sent) define this */ -#undef NETWAVE_STATS - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define NETWAVE_REGOFF 0x8000 -/* The Netwave IO registers, offsets to iobase */ -#define NETWAVE_REG_COR 0x0 -#define NETWAVE_REG_CCSR 0x2 -#define NETWAVE_REG_ASR 0x4 -#define NETWAVE_REG_IMR 0xa -#define NETWAVE_REG_PMR 0xc -#define NETWAVE_REG_IOLOW 0x6 -#define NETWAVE_REG_IOHI 0x7 -#define NETWAVE_REG_IOCONTROL 0x8 -#define NETWAVE_REG_DATA 0xf -/* The Netwave Extended IO registers, offsets to RamBase */ -#define NETWAVE_EREG_ASCC 0x114 -#define NETWAVE_EREG_RSER 0x120 -#define NETWAVE_EREG_RSERW 0x124 -#define NETWAVE_EREG_TSER 0x130 -#define NETWAVE_EREG_TSERW 0x134 -#define NETWAVE_EREG_CB 0x100 -#define NETWAVE_EREG_SPCQ 0x154 -#define NETWAVE_EREG_SPU 0x155 -#define NETWAVE_EREG_LIF 0x14e -#define NETWAVE_EREG_ISPLQ 0x156 -#define NETWAVE_EREG_HHC 0x158 -#define NETWAVE_EREG_NI 0x16e -#define NETWAVE_EREG_MHS 0x16b -#define NETWAVE_EREG_TDP 0x140 -#define NETWAVE_EREG_RDP 0x150 -#define NETWAVE_EREG_PA 0x160 -#define NETWAVE_EREG_EC 0x180 -#define NETWAVE_EREG_CRBP 0x17a -#define NETWAVE_EREG_ARW 0x166 - -/* - * Commands used in the extended command buffer - * NETWAVE_EREG_CB (0x100-0x10F) - */ -#define NETWAVE_CMD_NOP 0x00 -#define NETWAVE_CMD_SRC 0x01 -#define NETWAVE_CMD_STC 0x02 -#define NETWAVE_CMD_AMA 0x03 -#define NETWAVE_CMD_DMA 0x04 -#define NETWAVE_CMD_SAMA 0x05 -#define NETWAVE_CMD_ER 0x06 -#define NETWAVE_CMD_DR 0x07 -#define NETWAVE_CMD_TL 0x08 -#define NETWAVE_CMD_SRP 0x09 -#define NETWAVE_CMD_SSK 0x0a -#define NETWAVE_CMD_SMD 0x0b -#define NETWAVE_CMD_SAPD 0x0c -#define NETWAVE_CMD_SSS 0x11 -/* End of Command marker */ -#define NETWAVE_CMD_EOC 0x00 - -/* ASR register bits */ -#define NETWAVE_ASR_RXRDY 0x80 -#define NETWAVE_ASR_TXBA 0x01 - -#define TX_TIMEOUT ((32*HZ)/100) - -static const unsigned int imrConfRFU1 = 0x10; /* RFU interrupt mask, keep high */ -static const unsigned int imrConfIENA = 0x02; /* Interrupt enable */ - -static const unsigned int corConfIENA = 0x01; /* Interrupt enable */ -static const unsigned int corConfLVLREQ = 0x40; /* Keep high */ - -static const unsigned int rxConfRxEna = 0x80; /* Receive Enable */ -static const unsigned int rxConfMAC = 0x20; /* MAC host receive mode*/ -static const unsigned int rxConfPro = 0x10; /* Promiscuous */ -static const unsigned int rxConfAMP = 0x08; /* Accept Multicast Packets */ -static const unsigned int rxConfBcast = 0x04; /* Accept Broadcast Packets */ - -static const unsigned int txConfTxEna = 0x80; /* Transmit Enable */ -static const unsigned int txConfMAC = 0x20; /* Host sends MAC mode */ -static const unsigned int txConfEUD = 0x10; /* Enable Uni-Data packets */ -static const unsigned int txConfKey = 0x02; /* Scramble data packets */ -static const unsigned int txConfLoop = 0x01; /* Loopback mode */ - -/* - All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args) -static char *version = -"netwave_cs.c 0.3.0 Thu Jul 17 14:36:02 1997 (John Markus Bjørndalen)\n"; -#else -#define DEBUG(n, args...) -#endif - -/*====================================================================*/ - -/* Parameters that can be set with 'insmod' */ - -/* Choose the domain, default is 0x100 */ -static u_int domain = 0x100; - -/* Scramble key, range from 0x0 to 0xffff. - * 0x0 is no scrambling. - */ -static u_int scramble_key = 0x0; - -/* Shared memory speed, in ns. The documentation states that - * the card should not be read faster than every 400ns. - * This timing should be provided by the HBA. If it becomes a - * problem, try setting mem_speed to 400. - */ -static int mem_speed; - -module_param(domain, int, 0); -module_param(scramble_key, int, 0); -module_param(mem_speed, int, 0); - -/*====================================================================*/ - -/* PCMCIA (Card Services) related functions */ -static void netwave_release(struct pcmcia_device *link); /* Card removal */ -static int netwave_pcmcia_config(struct pcmcia_device *arg); /* Runs after card - insertion */ -static void netwave_detach(struct pcmcia_device *p_dev); /* Destroy instance */ - -/* Hardware configuration */ -static void netwave_doreset(unsigned int iobase, u_char __iomem *ramBase); -static void netwave_reset(struct net_device *dev); - -/* Misc device stuff */ -static int netwave_open(struct net_device *dev); /* Open the device */ -static int netwave_close(struct net_device *dev); /* Close the device */ - -/* Packet transmission and Packet reception */ -static netdev_tx_t netwave_start_xmit( struct sk_buff *skb, - struct net_device *dev); -static int netwave_rx( struct net_device *dev); - -/* Interrupt routines */ -static irqreturn_t netwave_interrupt(int irq, void *dev_id); -static void netwave_watchdog(struct net_device *); - -/* Wireless extensions */ -static struct iw_statistics* netwave_get_wireless_stats(struct net_device *dev); - -static void set_multicast_list(struct net_device *dev); - -/* - A struct pcmcia_device structure has fields for most things that are needed - to keep track of a socket, but there will usually be some device - specific information that also needs to be kept track of. The - 'priv' pointer in a struct pcmcia_device structure can be used to point to - a device-specific private data structure, like this. - - A driver needs to provide a dev_node_t structure for each device - on a card. In some cases, there is only one device per card (for - example, ethernet cards, modems). In other cases, there may be - many actual or logical devices (SCSI adapters, memory cards with - multiple partitions). The dev_node_t structures need to be kept - in a linked list starting at the 'dev' field of a struct pcmcia_device - structure. We allocate them in the card's private data structure, - because they generally can't be allocated dynamically. -*/ - -static const struct iw_handler_def netwave_handler_def; - -#define SIOCGIPSNAP SIOCIWFIRSTPRIV + 1 /* Site Survey Snapshot */ - -#define MAX_ESA 10 - -typedef struct net_addr { - u_char addr48[6]; -} net_addr; - -struct site_survey { - u_short length; - u_char struct_revision; - u_char roaming_state; - - u_char sp_existsFlag; - u_char sp_link_quality; - u_char sp_max_link_quality; - u_char linkQualityGoodFairBoundary; - u_char linkQualityFairPoorBoundary; - u_char sp_utilization; - u_char sp_goodness; - u_char sp_hotheadcount; - u_char roaming_condition; - - net_addr sp; - u_char numAPs; - net_addr nearByAccessPoints[MAX_ESA]; -}; - -typedef struct netwave_private { - struct pcmcia_device *p_dev; - spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ - dev_node_t node; - u_char __iomem *ramBase; - int timeoutCounter; - int lastExec; - struct timer_list watchdog; /* To avoid blocking state */ - struct site_survey nss; - struct iw_statistics iw_stats; /* Wireless stats */ -} netwave_private; - -/* - * The Netwave card is little-endian, so won't work for big endian - * systems. - */ -static inline unsigned short get_uint16(u_char __iomem *staddr) -{ - return readw(staddr); /* Return only 16 bits */ -} - -static inline short get_int16(u_char __iomem * staddr) -{ - return readw(staddr); -} - -/* - * Wait until the WOC (Write Operation Complete) bit in the - * ASR (Adapter Status Register) is asserted. - * This should have aborted if it takes too long time. - */ -static inline void wait_WOC(unsigned int iobase) -{ - /* Spin lock */ - while ((inb(iobase + NETWAVE_REG_ASR) & 0x8) != 0x8) ; -} - -static void netwave_snapshot(netwave_private *priv, u_char __iomem *ramBase, - unsigned int iobase) { - u_short resultBuffer; - - /* if time since last snapshot is > 1 sec. (100 jiffies?) then take - * new snapshot, else return cached data. This is the recommended rate. - */ - if ( jiffies - priv->lastExec > 100) { - /* Take site survey snapshot */ - /*printk( KERN_DEBUG "Taking new snapshot. %ld\n", jiffies - - priv->lastExec); */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_SSS, ramBase + NETWAVE_EREG_CB + 0); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 1); - wait_WOC(iobase); - - /* Get result and copy to cach */ - resultBuffer = readw(ramBase + NETWAVE_EREG_CRBP); - copy_from_pc( &priv->nss, ramBase+resultBuffer, - sizeof(struct site_survey)); - } -} - -/* - * Function netwave_get_wireless_stats (dev) - * - * Wireless extensions statistics - * - */ -static struct iw_statistics *netwave_get_wireless_stats(struct net_device *dev) -{ - unsigned long flags; - unsigned int iobase = dev->base_addr; - netwave_private *priv = netdev_priv(dev); - u_char __iomem *ramBase = priv->ramBase; - struct iw_statistics* wstats; - - wstats = &priv->iw_stats; - - spin_lock_irqsave(&priv->spinlock, flags); - - netwave_snapshot( priv, ramBase, iobase); - - wstats->status = priv->nss.roaming_state; - wstats->qual.qual = readb( ramBase + NETWAVE_EREG_SPCQ); - wstats->qual.level = readb( ramBase + NETWAVE_EREG_ISPLQ); - wstats->qual.noise = readb( ramBase + NETWAVE_EREG_SPU) & 0x3f; - wstats->discard.nwid = 0L; - wstats->discard.code = 0L; - wstats->discard.misc = 0L; - - spin_unlock_irqrestore(&priv->spinlock, flags); - - return &priv->iw_stats; -} - -static const struct net_device_ops netwave_netdev_ops = { - .ndo_open = netwave_open, - .ndo_stop = netwave_close, - .ndo_start_xmit = netwave_start_xmit, - .ndo_set_multicast_list = set_multicast_list, - .ndo_tx_timeout = netwave_watchdog, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/* - * Function netwave_attach (void) - * - * Creates an "instance" of the driver, allocating local data - * structures for one device. The device is registered with Card - * Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a - * card insertion event. - */ -static int netwave_probe(struct pcmcia_device *link) -{ - struct net_device *dev; - netwave_private *priv; - - DEBUG(0, "netwave_attach()\n"); - - /* Initialize the struct pcmcia_device structure */ - dev = alloc_etherdev(sizeof(netwave_private)); - if (!dev) - return -ENOMEM; - priv = netdev_priv(dev); - priv->p_dev = link; - link->priv = dev; - - /* The io structure describes IO port mapping */ - link->io.NumPorts1 = 16; - link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - /* link->io.NumPorts2 = 16; - link->io.Attributes2 = IO_DATA_PATH_WIDTH_16; */ - link->io.IOAddrLines = 5; - - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = &netwave_interrupt; - - /* General socket configuration */ - link->conf.Attributes = CONF_ENABLE_IRQ; - link->conf.IntType = INT_MEMORY_AND_IO; - link->conf.ConfigIndex = 1; - - /* Netwave private struct init. link/dev/node already taken care of, - * other stuff zero'd - Jean II */ - spin_lock_init(&priv->spinlock); - - /* Netwave specific entries in the device structure */ - dev->netdev_ops = &netwave_netdev_ops; - /* wireless extensions */ - dev->wireless_handlers = &netwave_handler_def; - - dev->watchdog_timeo = TX_TIMEOUT; - - link->irq.Instance = dev; - - return netwave_pcmcia_config( link); -} /* netwave_attach */ - -/* - * Function netwave_detach (link) - * - * This deletes a driver "instance". The device is de-registered - * with Card Services. If it has been released, all local data - * structures are freed. Otherwise, the structures will be freed - * when the device is released. - */ -static void netwave_detach(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - DEBUG(0, "netwave_detach(0x%p)\n", link); - - netwave_release(link); - - if (link->dev_node) - unregister_netdev(dev); - - free_netdev(dev); -} /* netwave_detach */ - -/* - * Wireless Handler : get protocol name - */ -static int netwave_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - strcpy(wrqu->name, "Netwave"); - return 0; -} - -/* - * Wireless Handler : set Network ID - */ -static int netwave_set_nwid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long flags; - unsigned int iobase = dev->base_addr; - netwave_private *priv = netdev_priv(dev); - u_char __iomem *ramBase = priv->ramBase; - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&priv->spinlock, flags); - - if(!wrqu->nwid.disabled) { - domain = wrqu->nwid.value; - printk( KERN_DEBUG "Setting domain to 0x%x%02x\n", - (domain >> 8) & 0x01, domain & 0xff); - wait_WOC(iobase); - writeb(NETWAVE_CMD_SMD, ramBase + NETWAVE_EREG_CB + 0); - writeb( domain & 0xff, ramBase + NETWAVE_EREG_CB + 1); - writeb((domain >>8 ) & 0x01,ramBase + NETWAVE_EREG_CB+2); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3); - } - - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore(&priv->spinlock, flags); - - return 0; -} - -/* - * Wireless Handler : get Network ID - */ -static int netwave_get_nwid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - wrqu->nwid.value = domain; - wrqu->nwid.disabled = 0; - wrqu->nwid.fixed = 1; - return 0; -} - -/* - * Wireless Handler : set scramble key - */ -static int netwave_set_scramble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *key) -{ - unsigned long flags; - unsigned int iobase = dev->base_addr; - netwave_private *priv = netdev_priv(dev); - u_char __iomem *ramBase = priv->ramBase; - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&priv->spinlock, flags); - - scramble_key = (key[0] << 8) | key[1]; - wait_WOC(iobase); - writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0); - writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1); - writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3); - - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore(&priv->spinlock, flags); - - return 0; -} - -/* - * Wireless Handler : get scramble key - */ -static int netwave_get_scramble(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *key) -{ - key[1] = scramble_key & 0xff; - key[0] = (scramble_key>>8) & 0xff; - wrqu->encoding.flags = IW_ENCODE_ENABLED; - wrqu->encoding.length = 2; - return 0; -} - -/* - * Wireless Handler : get mode - */ -static int netwave_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - if(domain & 0x100) - wrqu->mode = IW_MODE_INFRA; - else - wrqu->mode = IW_MODE_ADHOC; - - return 0; -} - -/* - * Wireless Handler : get range info - */ -static int netwave_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct iw_range *range = (struct iw_range *) extra; - int ret = 0; - - /* Set the length (very important for backward compatibility) */ - wrqu->data.length = sizeof(struct iw_range); - - /* Set all the info we don't care or don't know about to zero */ - memset(range, 0, sizeof(struct iw_range)); - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 9; /* Nothing for us in v10 and v11 */ - - /* Set information in the range struct */ - range->throughput = 450 * 1000; /* don't argue on this ! */ - range->min_nwid = 0x0000; - range->max_nwid = 0x01FF; - - range->num_channels = range->num_frequency = 0; - - range->sensitivity = 0x3F; - range->max_qual.qual = 255; - range->max_qual.level = 255; - range->max_qual.noise = 0; - - range->num_bitrates = 1; - range->bitrate[0] = 1000000; /* 1 Mb/s */ - - range->encoding_size[0] = 2; /* 16 bits scrambling */ - range->num_encoding_sizes = 1; - range->max_encoding_tokens = 1; /* Only one key possible */ - - return ret; -} - -/* - * Wireless Private Handler : get snapshot - */ -static int netwave_get_snap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long flags; - unsigned int iobase = dev->base_addr; - netwave_private *priv = netdev_priv(dev); - u_char __iomem *ramBase = priv->ramBase; - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&priv->spinlock, flags); - - /* Take snapshot of environment */ - netwave_snapshot( priv, ramBase, iobase); - wrqu->data.length = priv->nss.length; - memcpy(extra, (u_char *) &priv->nss, sizeof( struct site_survey)); - - priv->lastExec = jiffies; - - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore(&priv->spinlock, flags); - - return(0); -} - -/* - * Structures to export the Wireless Handlers - * This is the stuff that are treated the wireless extensions (iwconfig) - */ - -static const struct iw_priv_args netwave_private_args[] = { -/*{ cmd, set_args, get_args, name } */ - { SIOCGIPSNAP, 0, - IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | sizeof(struct site_survey), - "getsitesurvey" }, -}; - -static const iw_handler netwave_handler[] = -{ - NULL, /* SIOCSIWNAME */ - netwave_get_name, /* SIOCGIWNAME */ - netwave_set_nwid, /* SIOCSIWNWID */ - netwave_get_nwid, /* SIOCGIWNWID */ - NULL, /* SIOCSIWFREQ */ - NULL, /* SIOCGIWFREQ */ - NULL, /* SIOCSIWMODE */ - netwave_get_mode, /* SIOCGIWMODE */ - NULL, /* SIOCSIWSENS */ - NULL, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - netwave_get_range, /* SIOCGIWRANGE */ - NULL, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - NULL, /* SIOCSIWSPY */ - NULL, /* SIOCGIWSPY */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWAP */ - NULL, /* SIOCGIWAP */ - NULL, /* -- hole -- */ - NULL, /* SIOCGIWAPLIST */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWESSID */ - NULL, /* SIOCGIWESSID */ - NULL, /* SIOCSIWNICKN */ - NULL, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWRATE */ - NULL, /* SIOCGIWRATE */ - NULL, /* SIOCSIWRTS */ - NULL, /* SIOCGIWRTS */ - NULL, /* SIOCSIWFRAG */ - NULL, /* SIOCGIWFRAG */ - NULL, /* SIOCSIWTXPOW */ - NULL, /* SIOCGIWTXPOW */ - NULL, /* SIOCSIWRETRY */ - NULL, /* SIOCGIWRETRY */ - netwave_set_scramble, /* SIOCSIWENCODE */ - netwave_get_scramble, /* SIOCGIWENCODE */ -}; - -static const iw_handler netwave_private_handler[] = -{ - NULL, /* SIOCIWFIRSTPRIV */ - netwave_get_snap, /* SIOCIWFIRSTPRIV + 1 */ -}; - -static const struct iw_handler_def netwave_handler_def = -{ - .num_standard = ARRAY_SIZE(netwave_handler), - .num_private = ARRAY_SIZE(netwave_private_handler), - .num_private_args = ARRAY_SIZE(netwave_private_args), - .standard = (iw_handler *) netwave_handler, - .private = (iw_handler *) netwave_private_handler, - .private_args = (struct iw_priv_args *) netwave_private_args, - .get_wireless_stats = netwave_get_wireless_stats, -}; - -/* - * Function netwave_pcmcia_config (link) - * - * netwave_pcmcia_config() is scheduled to run after a CARD_INSERTION - * event is received, to configure the PCMCIA socket, and to make the - * device available to the system. - * - */ - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -static int netwave_pcmcia_config(struct pcmcia_device *link) { - struct net_device *dev = link->priv; - netwave_private *priv = netdev_priv(dev); - int i, j, last_ret, last_fn; - win_req_t req; - memreq_t mem; - u_char __iomem *ramBase = NULL; - - DEBUG(0, "netwave_pcmcia_config(0x%p)\n", link); - - /* - * Try allocating IO ports. This tries a few fixed addresses. - * If you want, you can also read the card's config table to - * pick addresses -- see the serial driver for an example. - */ - for (i = j = 0x0; j < 0x400; j += 0x20) { - link->io.BasePort1 = j ^ 0x300; - i = pcmcia_request_io(link, &link->io); - if (i == 0) - break; - } - if (i != 0) { - cs_error(link, RequestIO, i); - goto failed; - } - - /* - * Now allocate an interrupt line. Note that this does not - * actually assign a handler to the interrupt. - */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping. - */ - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - - /* - * Allocate a 32K memory window. Note that the struct pcmcia_device - * structure provides space for one window handle -- if your - * device needs several windows, you'll need to keep track of - * the handles in your private data structure, dev->priv. - */ - DEBUG(1, "Setting mem speed of %d\n", mem_speed); - - req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_CM|WIN_ENABLE; - req.Base = 0; req.Size = 0x8000; - req.AccessSpeed = mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); - mem.CardOffset = 0x20000; mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); - - /* Store base address of the common window frame */ - ramBase = ioremap(req.Base, 0x8000); - priv->ramBase = ramBase; - - dev->irq = link->irq.AssignedIRQ; - dev->base_addr = link->io.BasePort1; - SET_NETDEV_DEV(dev, &handle_to_dev(link)); - - if (register_netdev(dev) != 0) { - printk(KERN_DEBUG "netwave_cs: register_netdev() failed\n"); - goto failed; - } - - strcpy(priv->node.dev_name, dev->name); - link->dev_node = &priv->node; - - /* Reset card before reading physical address */ - netwave_doreset(dev->base_addr, ramBase); - - /* Read the ethernet address and fill in the Netwave registers. */ - for (i = 0; i < 6; i++) - dev->dev_addr[i] = readb(ramBase + NETWAVE_EREG_PA + i); - - printk(KERN_INFO "%s: Netwave: port %#3lx, irq %d, mem %lx, " - "id %c%c, hw_addr %pM\n", - dev->name, dev->base_addr, dev->irq, - (u_long) ramBase, - (int) readb(ramBase+NETWAVE_EREG_NI), - (int) readb(ramBase+NETWAVE_EREG_NI+1), - dev->dev_addr); - - /* get revision words */ - printk(KERN_DEBUG "Netwave_reset: revision %04x %04x\n", - get_uint16(ramBase + NETWAVE_EREG_ARW), - get_uint16(ramBase + NETWAVE_EREG_ARW+2)); - return 0; - -cs_failed: - cs_error(link, last_fn, last_ret); -failed: - netwave_release(link); - return -ENODEV; -} /* netwave_pcmcia_config */ - -/* - * Function netwave_release (arg) - * - * After a card is removed, netwave_release() will unregister the net - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void netwave_release(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - netwave_private *priv = netdev_priv(dev); - - DEBUG(0, "netwave_release(0x%p)\n", link); - - pcmcia_disable_device(link); - if (link->win) - iounmap(priv->ramBase); -} - -static int netwave_suspend(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - if (link->open) - netif_device_detach(dev); - - return 0; -} - -static int netwave_resume(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - if (link->open) { - netwave_reset(dev); - netif_device_attach(dev); - } - - return 0; -} - - -/* - * Function netwave_doreset (ioBase, ramBase) - * - * Proper hardware reset of the card. - */ -static void netwave_doreset(unsigned int ioBase, u_char __iomem *ramBase) -{ - /* Reset card */ - wait_WOC(ioBase); - outb(0x80, ioBase + NETWAVE_REG_PMR); - writeb(0x08, ramBase + NETWAVE_EREG_ASCC); /* Bit 3 is WOC */ - outb(0x0, ioBase + NETWAVE_REG_PMR); /* release reset */ -} - -/* - * Function netwave_reset (dev) - * - * Reset and restore all of the netwave registers - */ -static void netwave_reset(struct net_device *dev) { - /* u_char state; */ - netwave_private *priv = netdev_priv(dev); - u_char __iomem *ramBase = priv->ramBase; - unsigned int iobase = dev->base_addr; - - DEBUG(0, "netwave_reset: Done with hardware reset\n"); - - priv->timeoutCounter = 0; - - /* Reset card */ - netwave_doreset(iobase, ramBase); - printk(KERN_DEBUG "netwave_reset: Done with hardware reset\n"); - - /* Write a NOP to check the card */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_NOP, ramBase + NETWAVE_EREG_CB + 0); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 1); - - /* Set receive conf */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_SRC, ramBase + NETWAVE_EREG_CB + 0); - writeb(rxConfRxEna + rxConfBcast, ramBase + NETWAVE_EREG_CB + 1); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 2); - - /* Set transmit conf */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_STC, ramBase + NETWAVE_EREG_CB + 0); - writeb(txConfTxEna, ramBase + NETWAVE_EREG_CB + 1); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 2); - - /* Now set the MU Domain */ - printk(KERN_DEBUG "Setting domain to 0x%x%02x\n", (domain >> 8) & 0x01, domain & 0xff); - wait_WOC(iobase); - writeb(NETWAVE_CMD_SMD, ramBase + NETWAVE_EREG_CB + 0); - writeb(domain & 0xff, ramBase + NETWAVE_EREG_CB + 1); - writeb((domain>>8) & 0x01, ramBase + NETWAVE_EREG_CB + 2); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3); - - /* Set scramble key */ - printk(KERN_DEBUG "Setting scramble key to 0x%x\n", scramble_key); - wait_WOC(iobase); - writeb(NETWAVE_CMD_SSK, ramBase + NETWAVE_EREG_CB + 0); - writeb(scramble_key & 0xff, ramBase + NETWAVE_EREG_CB + 1); - writeb((scramble_key>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3); - - /* Enable interrupts, bit 4 high to keep unused - * source from interrupting us, bit 2 high to - * set interrupt enable, 567 to enable TxDN, - * RxErr and RxRdy - */ - wait_WOC(iobase); - outb(imrConfIENA+imrConfRFU1, iobase + NETWAVE_REG_IMR); - - /* Hent 4 bytes fra 0x170. Skal vaere 0a,29,88,36 - * waitWOC - * skriv 80 til d000:3688 - * sjekk om det ble 80 - */ - - /* Enable Receiver */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_ER, ramBase + NETWAVE_EREG_CB + 0); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 1); - - /* Set the IENA bit in COR */ - wait_WOC(iobase); - outb(corConfIENA + corConfLVLREQ, iobase + NETWAVE_REG_COR); -} - -/* - * Function netwave_hw_xmit (data, len, dev) - */ -static int netwave_hw_xmit(unsigned char* data, int len, - struct net_device* dev) { - unsigned long flags; - unsigned int TxFreeList, - curBuff, - MaxData, - DataOffset; - int tmpcount; - - netwave_private *priv = netdev_priv(dev); - u_char __iomem * ramBase = priv->ramBase; - unsigned int iobase = dev->base_addr; - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&priv->spinlock, flags); - - /* Check if there are transmit buffers available */ - wait_WOC(iobase); - if ((inb(iobase+NETWAVE_REG_ASR) & NETWAVE_ASR_TXBA) == 0) { - /* No buffers available */ - printk(KERN_DEBUG "netwave_hw_xmit: %s - no xmit buffers available.\n", - dev->name); - spin_unlock_irqrestore(&priv->spinlock, flags); - return 1; - } - - dev->stats.tx_bytes += len; - - DEBUG(3, "Transmitting with SPCQ %x SPU %x LIF %x ISPLQ %x\n", - readb(ramBase + NETWAVE_EREG_SPCQ), - readb(ramBase + NETWAVE_EREG_SPU), - readb(ramBase + NETWAVE_EREG_LIF), - readb(ramBase + NETWAVE_EREG_ISPLQ)); - - /* Now try to insert it into the adapters free memory */ - wait_WOC(iobase); - TxFreeList = get_uint16(ramBase + NETWAVE_EREG_TDP); - MaxData = get_uint16(ramBase + NETWAVE_EREG_TDP+2); - DataOffset = get_uint16(ramBase + NETWAVE_EREG_TDP+4); - - DEBUG(3, "TxFreeList %x, MaxData %x, DataOffset %x\n", - TxFreeList, MaxData, DataOffset); - - /* Copy packet to the adapter fragment buffers */ - curBuff = TxFreeList; - tmpcount = 0; - while (tmpcount < len) { - int tmplen = len - tmpcount; - copy_to_pc(ramBase + curBuff + DataOffset, data + tmpcount, - (tmplen < MaxData) ? tmplen : MaxData); - tmpcount += MaxData; - - /* Advance to next buffer */ - curBuff = get_uint16(ramBase + curBuff); - } - - /* Now issue transmit list */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_TL, ramBase + NETWAVE_EREG_CB + 0); - writeb(len & 0xff, ramBase + NETWAVE_EREG_CB + 1); - writeb((len>>8) & 0xff, ramBase + NETWAVE_EREG_CB + 2); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 3); - - spin_unlock_irqrestore(&priv->spinlock, flags); - return 0; -} - -static netdev_tx_t netwave_start_xmit(struct sk_buff *skb, - struct net_device *dev) { - /* This flag indicate that the hardware can't perform a transmission. - * Theoritically, NET3 check it before sending a packet to the driver, - * but in fact it never do that and pool continuously. - * As the watchdog will abort too long transmissions, we are quite safe... - */ - - netif_stop_queue(dev); - - { - short length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN; - unsigned char* buf = skb->data; - - if (netwave_hw_xmit( buf, length, dev) == 1) { - /* Some error, let's make them call us another time? */ - netif_start_queue(dev); - } - dev->trans_start = jiffies; - } - dev_kfree_skb(skb); - - return NETDEV_TX_OK; -} /* netwave_start_xmit */ - -/* - * Function netwave_interrupt (irq, dev_id) - * - * This function is the interrupt handler for the Netwave card. This - * routine will be called whenever: - * 1. A packet is received. - * 2. A packet has successfully been transferred and the unit is - * ready to transmit another packet. - * 3. A command has completed execution. - */ -static irqreturn_t netwave_interrupt(int irq, void* dev_id) -{ - unsigned int iobase; - u_char __iomem *ramBase; - struct net_device *dev = (struct net_device *)dev_id; - struct netwave_private *priv = netdev_priv(dev); - struct pcmcia_device *link = priv->p_dev; - int i; - - if (!netif_device_present(dev)) - return IRQ_NONE; - - iobase = dev->base_addr; - ramBase = priv->ramBase; - - /* Now find what caused the interrupt, check while interrupts ready */ - for (i = 0; i < 10; i++) { - u_char status; - - wait_WOC(iobase); - if (!(inb(iobase+NETWAVE_REG_CCSR) & 0x02)) - break; /* None of the interrupt sources asserted (normal exit) */ - - status = inb(iobase + NETWAVE_REG_ASR); - - if (!pcmcia_dev_present(link)) { - DEBUG(1, "netwave_interrupt: Interrupt with status 0x%x " - "from removed or suspended card!\n", status); - break; - } - - /* RxRdy */ - if (status & 0x80) { - netwave_rx(dev); - /* wait_WOC(iobase); */ - /* RxRdy cannot be reset directly by the host */ - } - /* RxErr */ - if (status & 0x40) { - u_char rser; - - rser = readb(ramBase + NETWAVE_EREG_RSER); - - if (rser & 0x04) { - ++dev->stats.rx_dropped; - ++dev->stats.rx_crc_errors; - } - if (rser & 0x02) - ++dev->stats.rx_frame_errors; - - /* Clear the RxErr bit in RSER. RSER+4 is the - * write part. Also clear the RxCRC (0x04) and - * RxBig (0x02) bits if present */ - wait_WOC(iobase); - writeb(0x40 | (rser & 0x06), ramBase + NETWAVE_EREG_RSER + 4); - - /* Write bit 6 high to ASCC to clear RxErr in ASR, - * WOC must be set first! - */ - wait_WOC(iobase); - writeb(0x40, ramBase + NETWAVE_EREG_ASCC); - - /* Remember to count up dev->stats on error packets */ - ++dev->stats.rx_errors; - } - /* TxDN */ - if (status & 0x20) { - int txStatus; - - txStatus = readb(ramBase + NETWAVE_EREG_TSER); - DEBUG(3, "Transmit done. TSER = %x id %x\n", - txStatus, readb(ramBase + NETWAVE_EREG_TSER + 1)); - - if (txStatus & 0x20) { - /* Transmitting was okay, clear bits */ - wait_WOC(iobase); - writeb(0x2f, ramBase + NETWAVE_EREG_TSER + 4); - ++dev->stats.tx_packets; - } - - if (txStatus & 0xd0) { - if (txStatus & 0x80) { - ++dev->stats.collisions; /* Because of /proc/net/dev*/ - /* ++dev->stats.tx_aborted_errors; */ - /* printk("Collision. %ld\n", jiffies - dev->trans_start); */ - } - if (txStatus & 0x40) - ++dev->stats.tx_carrier_errors; - /* 0x80 TxGU Transmit giveup - nine times and no luck - * 0x40 TxNOAP No access point. Discarded packet. - * 0x10 TxErr Transmit error. Always set when - * TxGU and TxNOAP is set. (Those are the only ones - * to set TxErr). - */ - DEBUG(3, "netwave_interrupt: TxDN with error status %x\n", - txStatus); - - /* Clear out TxGU, TxNOAP, TxErr and TxTrys */ - wait_WOC(iobase); - writeb(0xdf & txStatus, ramBase+NETWAVE_EREG_TSER+4); - ++dev->stats.tx_errors; - } - DEBUG(3, "New status is TSER %x ASR %x\n", - readb(ramBase + NETWAVE_EREG_TSER), - inb(iobase + NETWAVE_REG_ASR)); - - netif_wake_queue(dev); - } - /* TxBA, this would trigger on all error packets received */ - /* if (status & 0x01) { - DEBUG(4, "Transmit buffers available, %x\n", status); - } - */ - } - /* Handled if we looped at least one time - Jean II */ - return IRQ_RETVAL(i); -} /* netwave_interrupt */ - -/* - * Function netwave_watchdog (a) - * - * Watchdog : when we start a transmission, we set a timer in the - * kernel. If the transmission complete, this timer is disabled. If - * it expire, we reset the card. - * - */ -static void netwave_watchdog(struct net_device *dev) { - - DEBUG(1, "%s: netwave_watchdog: watchdog timer expired\n", dev->name); - netwave_reset(dev); - dev->trans_start = jiffies; - netif_wake_queue(dev); -} /* netwave_watchdog */ - -static int netwave_rx(struct net_device *dev) -{ - netwave_private *priv = netdev_priv(dev); - u_char __iomem *ramBase = priv->ramBase; - unsigned int iobase = dev->base_addr; - u_char rxStatus; - struct sk_buff *skb = NULL; - unsigned int curBuffer, - rcvList; - int rcvLen; - int tmpcount = 0; - int dataCount, dataOffset; - int i; - u_char *ptr; - - DEBUG(3, "xinw_rx: Receiving ... \n"); - - /* Receive max 10 packets for now. */ - for (i = 0; i < 10; i++) { - /* Any packets? */ - wait_WOC(iobase); - rxStatus = readb(ramBase + NETWAVE_EREG_RSER); - if ( !( rxStatus & 0x80)) /* No more packets */ - break; - - /* Check if multicast/broadcast or other */ - /* multicast = (rxStatus & 0x20); */ - - /* The receive list pointer and length of the packet */ - wait_WOC(iobase); - rcvLen = get_int16( ramBase + NETWAVE_EREG_RDP); - rcvList = get_uint16( ramBase + NETWAVE_EREG_RDP + 2); - - if (rcvLen < 0) { - printk(KERN_DEBUG "netwave_rx: Receive packet with len %d\n", - rcvLen); - return 0; - } - - skb = dev_alloc_skb(rcvLen+5); - if (skb == NULL) { - DEBUG(1, "netwave_rx: Could not allocate an sk_buff of " - "length %d\n", rcvLen); - ++dev->stats.rx_dropped; - /* Tell the adapter to skip the packet */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_SRP, ramBase + NETWAVE_EREG_CB + 0); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 1); - return 0; - } - - skb_reserve( skb, 2); /* Align IP on 16 byte */ - skb_put( skb, rcvLen); - - /* Copy packet fragments to the skb data area */ - ptr = (u_char*) skb->data; - curBuffer = rcvList; - tmpcount = 0; - while ( tmpcount < rcvLen) { - /* Get length and offset of current buffer */ - dataCount = get_uint16( ramBase+curBuffer+2); - dataOffset = get_uint16( ramBase+curBuffer+4); - - copy_from_pc( ptr + tmpcount, - ramBase+curBuffer+dataOffset, dataCount); - - tmpcount += dataCount; - - /* Point to next buffer */ - curBuffer = get_uint16(ramBase + curBuffer); - } - - skb->protocol = eth_type_trans(skb,dev); - /* Queue packet for network layer */ - netif_rx(skb); - - dev->stats.rx_packets++; - dev->stats.rx_bytes += rcvLen; - - /* Got the packet, tell the adapter to skip it */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_SRP, ramBase + NETWAVE_EREG_CB + 0); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 1); - DEBUG(3, "Packet reception ok\n"); - } - return 0; -} - -static int netwave_open(struct net_device *dev) { - netwave_private *priv = netdev_priv(dev); - struct pcmcia_device *link = priv->p_dev; - - DEBUG(1, "netwave_open: starting.\n"); - - if (!pcmcia_dev_present(link)) - return -ENODEV; - - link->open++; - - netif_start_queue(dev); - netwave_reset(dev); - - return 0; -} - -static int netwave_close(struct net_device *dev) { - netwave_private *priv = netdev_priv(dev); - struct pcmcia_device *link = priv->p_dev; - - DEBUG(1, "netwave_close: finishing.\n"); - - link->open--; - netif_stop_queue(dev); - - return 0; -} - -static struct pcmcia_device_id netwave_ids[] = { - PCMCIA_DEVICE_PROD_ID12("Xircom", "CreditCard Netwave", 0x2e3ee845, 0x54e28a28), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, netwave_ids); - -static struct pcmcia_driver netwave_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "netwave_cs", - }, - .probe = netwave_probe, - .remove = netwave_detach, - .id_table = netwave_ids, - .suspend = netwave_suspend, - .resume = netwave_resume, -}; - -static int __init init_netwave_cs(void) -{ - return pcmcia_register_driver(&netwave_driver); -} - -static void __exit exit_netwave_cs(void) -{ - pcmcia_unregister_driver(&netwave_driver); -} - -module_init(init_netwave_cs); -module_exit(exit_netwave_cs); - -/* Set or clear the multicast filter for this adaptor. - num_addrs == -1 Promiscuous mode, receive all packets - num_addrs == 0 Normal mode, clear multicast list - num_addrs > 0 Multicast mode, receive normal and MC packets, and do - best-effort filtering. - */ -static void set_multicast_list(struct net_device *dev) -{ - unsigned int iobase = dev->base_addr; - netwave_private *priv = netdev_priv(dev); - u_char __iomem * ramBase = priv->ramBase; - u_char rcvMode = 0; - -#ifdef PCMCIA_DEBUG - if (pc_debug > 2) { - static int old; - if (old != dev->mc_count) { - old = dev->mc_count; - DEBUG(0, "%s: setting Rx mode to %d addresses.\n", - dev->name, dev->mc_count); - } - } -#endif - - if (dev->mc_count || (dev->flags & IFF_ALLMULTI)) { - /* Multicast Mode */ - rcvMode = rxConfRxEna + rxConfAMP + rxConfBcast; - } else if (dev->flags & IFF_PROMISC) { - /* Promiscous mode */ - rcvMode = rxConfRxEna + rxConfPro + rxConfAMP + rxConfBcast; - } else { - /* Normal mode */ - rcvMode = rxConfRxEna + rxConfBcast; - } - - /* printk("netwave set_multicast_list: rcvMode to %x\n", rcvMode);*/ - /* Now set receive mode */ - wait_WOC(iobase); - writeb(NETWAVE_CMD_SRC, ramBase + NETWAVE_EREG_CB + 0); - writeb(rcvMode, ramBase + NETWAVE_EREG_CB + 1); - writeb(NETWAVE_CMD_EOC, ramBase + NETWAVE_EREG_CB + 2); -} -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/orinoco/Kconfig b/drivers/net/wireless/orinoco/Kconfig deleted file mode 100644 index 83b635fd7784..000000000000 --- a/drivers/net/wireless/orinoco/Kconfig +++ /dev/null @@ -1,121 +0,0 @@ -config HERMES - tristate "Hermes chipset 802.11b support (Orinoco/Prism2/Symbol)" - depends on (PPC_PMAC || PCI || PCMCIA) && WLAN_80211 - depends on CFG80211 - select WIRELESS_EXT - select FW_LOADER - select CRYPTO - select CRYPTO_MICHAEL_MIC - ---help--- - A driver for 802.11b wireless cards based on the "Hermes" or - Intersil HFA384x (Prism 2) MAC controller. This includes the vast - majority of the PCMCIA 802.11b cards (which are nearly all rebadges) - - except for the Cisco/Aironet cards. Cards supported include the - Apple Airport (not a PCMCIA card), WavelanIEEE/Orinoco, - Cabletron/EnteraSys Roamabout, ELSA AirLancer, MELCO Buffalo, Avaya, - IBM High Rate Wireless, Farralon Syyline, Samsung MagicLAN, Netgear - MA401, LinkSys WPC-11, D-Link DWL-650, 3Com AirConnect, Intel - IPW2011, and Symbol Spectrum24 High Rate amongst others. - - This option includes the guts of the driver, but in order to - actually use a card you will also need to enable support for PCMCIA - Hermes cards, PLX9052 based PCI adaptors or the Apple Airport below. - - You will also very likely also need the Wireless Tools in order to - configure your card and that /etc/pcmcia/wireless.opts works : - - -config HERMES_CACHE_FW_ON_INIT - bool "Cache Hermes firmware on driver initialisation" - depends on HERMES - default y - ---help--- - Say Y to cache any firmware required by the Hermes drivers - on startup. The firmware will remain cached until the - driver is unloaded. The cache uses 64K of RAM. - - Otherwise load the firmware from userspace as required. In - this case the driver should be unloaded and restarted - whenever the firmware is changed. - - If you are not sure, say Y. - -config APPLE_AIRPORT - tristate "Apple Airport support (built-in)" - depends on PPC_PMAC && HERMES - help - Say Y here to support the Airport 802.11b wireless Ethernet hardware - built into the Macintosh iBook and other recent PowerPC-based - Macintosh machines. This is essentially a Lucent Orinoco card with - a non-standard interface. - - This driver does not support the Airport Extreme (802.11b/g). Use - the BCM43xx driver for Airport Extreme cards. - -config PLX_HERMES - tristate "Hermes in PLX9052 based PCI adaptor support (Netgear MA301 etc.)" - depends on PCI && HERMES - help - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in PLX9052 based PCI adaptors. These - adaptors are not a full PCMCIA controller but act as a more limited - PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that - 802.11b PCMCIA cards can be used in desktop machines. The Netgear - MA301 is such an adaptor. - -config TMD_HERMES - tristate "Hermes in TMD7160 based PCI adaptor support" - depends on PCI && HERMES - help - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in TMD7160 based PCI adaptors. These - adaptors are not a full PCMCIA controller but act as a more limited - PCI <-> PCMCIA bridge. Several vendors sell such adaptors so that - 802.11b PCMCIA cards can be used in desktop machines. - -config NORTEL_HERMES - tristate "Nortel emobility PCI adaptor support" - depends on PCI && HERMES - help - Enable support for PCMCIA cards supported by the "Hermes" (aka - orinoco) driver when used in Nortel emobility PCI adaptors. These - adaptors are not full PCMCIA controllers, but act as a more limited - PCI <-> PCMCIA bridge. - -config PCI_HERMES - tristate "Prism 2.5 PCI 802.11b adaptor support" - depends on PCI && HERMES - help - Enable support for PCI and mini-PCI 802.11b wireless NICs based on - the Prism 2.5 chipset. These are true PCI cards, not the 802.11b - PCMCIA cards bundled with PCI<->PCMCIA adaptors which are also - common. Some of the built-in wireless adaptors in laptops are of - this variety. - -config PCMCIA_HERMES - tristate "Hermes PCMCIA card support" - depends on PCMCIA && HERMES - ---help--- - A driver for "Hermes" chipset based PCMCIA wireless adaptors, such - as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ - EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and - others). It should also be usable on various Prism II based cards - such as the Linksys, D-Link and Farallon Skyline. It should also - work on Symbol cards such as the 3Com AirConnect and Ericsson WLAN. - - You will very likely need the Wireless Tools in order to - configure your card and that /etc/pcmcia/wireless.opts works: - . - -config PCMCIA_SPECTRUM - tristate "Symbol Spectrum24 Trilogy PCMCIA card support" - depends on PCMCIA && HERMES - ---help--- - - This is a driver for 802.11b cards using RAM-loadable Symbol - firmware, such as Symbol Wireless Networker LA4100, CompactFlash - cards by Socket Communications and Intel PRO/Wireless 2011B. - - This driver requires firmware download on startup. Utilities - for downloading Symbol firmware are available at - diff --git a/drivers/net/wireless/orinoco/Makefile b/drivers/net/wireless/orinoco/Makefile deleted file mode 100644 index 9abd6329bcbd..000000000000 --- a/drivers/net/wireless/orinoco/Makefile +++ /dev/null @@ -1,13 +0,0 @@ -# -# Makefile for the orinoco wireless device drivers. -# -orinoco-objs := main.o fw.o hw.o mic.o scan.o wext.o hermes_dld.o hermes.o cfg.o - -obj-$(CONFIG_HERMES) += orinoco.o -obj-$(CONFIG_PCMCIA_HERMES) += orinoco_cs.o -obj-$(CONFIG_APPLE_AIRPORT) += airport.o -obj-$(CONFIG_PLX_HERMES) += orinoco_plx.o -obj-$(CONFIG_PCI_HERMES) += orinoco_pci.o -obj-$(CONFIG_TMD_HERMES) += orinoco_tmd.o -obj-$(CONFIG_NORTEL_HERMES) += orinoco_nortel.o -obj-$(CONFIG_PCMCIA_SPECTRUM) += spectrum_cs.o diff --git a/drivers/net/wireless/orinoco/airport.c b/drivers/net/wireless/orinoco/airport.c deleted file mode 100644 index c60df2c1aca3..000000000000 --- a/drivers/net/wireless/orinoco/airport.c +++ /dev/null @@ -1,265 +0,0 @@ -/* airport.c - * - * A driver for "Hermes" chipset based Apple Airport wireless - * card. - * - * Copyright notice & release notes in file main.c - * - * Note specific to airport stub: - * - * 0.05 : first version of the new split driver - * 0.06 : fix possible hang on powerup, add sleep support - */ - -#define DRIVER_NAME "airport" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include - -#include "orinoco.h" - -#define AIRPORT_IO_LEN (0x1000) /* one page */ - -struct airport { - struct macio_dev *mdev; - void __iomem *vaddr; - unsigned int irq; - int irq_requested; - int ndev_registered; -}; - -static int -airport_suspend(struct macio_dev *mdev, pm_message_t state) -{ - struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev); - struct net_device *dev = priv->ndev; - struct airport *card = priv->card; - unsigned long flags; - int err; - - printk(KERN_DEBUG "%s: Airport entering sleep mode\n", dev->name); - - err = orinoco_lock(priv, &flags); - if (err) { - printk(KERN_ERR "%s: hw_unavailable on PBOOK_SLEEP_NOW\n", - dev->name); - return 0; - } - - orinoco_down(priv); - orinoco_unlock(priv, &flags); - - disable_irq(card->irq); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, - macio_get_of_node(mdev), 0, 0); - - return 0; -} - -static int -airport_resume(struct macio_dev *mdev) -{ - struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev); - struct net_device *dev = priv->ndev; - struct airport *card = priv->card; - unsigned long flags; - int err; - - printk(KERN_DEBUG "%s: Airport waking up\n", dev->name); - - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, - macio_get_of_node(mdev), 0, 1); - msleep(200); - - enable_irq(card->irq); - - spin_lock_irqsave(&priv->lock, flags); - err = orinoco_up(priv); - spin_unlock_irqrestore(&priv->lock, flags); - - return err; -} - -static int -airport_detach(struct macio_dev *mdev) -{ - struct orinoco_private *priv = dev_get_drvdata(&mdev->ofdev.dev); - struct airport *card = priv->card; - - if (card->ndev_registered) - orinoco_if_del(priv); - card->ndev_registered = 0; - - if (card->irq_requested) - free_irq(card->irq, priv); - card->irq_requested = 0; - - if (card->vaddr) - iounmap(card->vaddr); - card->vaddr = NULL; - - macio_release_resource(mdev, 0); - - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, - macio_get_of_node(mdev), 0, 0); - ssleep(1); - - macio_set_drvdata(mdev, NULL); - free_orinocodev(priv); - - return 0; -} - -static int airport_hard_reset(struct orinoco_private *priv) -{ - /* It would be nice to power cycle the Airport for a real hard - * reset, but for some reason although it appears to - * re-initialize properly, it falls in a screaming heap - * shortly afterwards. */ -#if 0 - struct airport *card = priv->card; - - /* Vitally important. If we don't do this it seems we get an - * interrupt somewhere during the power cycle, since - * hw_unavailable is already set it doesn't get ACKed, we get - * into an interrupt loop and the PMU decides to turn us - * off. */ - disable_irq(card->irq); - - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, - macio_get_of_node(card->mdev), 0, 0); - ssleep(1); - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, - macio_get_of_node(card->mdev), 0, 1); - ssleep(1); - - enable_irq(card->irq); - ssleep(1); -#endif - - return 0; -} - -static int -airport_attach(struct macio_dev *mdev, const struct of_device_id *match) -{ - struct orinoco_private *priv; - struct airport *card; - unsigned long phys_addr; - hermes_t *hw; - - if (macio_resource_count(mdev) < 1 || macio_irq_count(mdev) < 1) { - printk(KERN_ERR PFX "Wrong interrupt/addresses in OF tree\n"); - return -ENODEV; - } - - /* Allocate space for private device-specific data */ - priv = alloc_orinocodev(sizeof(*card), &mdev->ofdev.dev, - airport_hard_reset, NULL); - if (!priv) { - printk(KERN_ERR PFX "Cannot allocate network device\n"); - return -ENODEV; - } - card = priv->card; - - hw = &priv->hw; - card->mdev = mdev; - - if (macio_request_resource(mdev, 0, DRIVER_NAME)) { - printk(KERN_ERR PFX "can't request IO resource !\n"); - free_orinocodev(priv); - return -EBUSY; - } - - macio_set_drvdata(mdev, priv); - - /* Setup interrupts & base address */ - card->irq = macio_irq(mdev, 0); - phys_addr = macio_resource_start(mdev, 0); /* Physical address */ - printk(KERN_DEBUG PFX "Physical address %lx\n", phys_addr); - card->vaddr = ioremap(phys_addr, AIRPORT_IO_LEN); - if (!card->vaddr) { - printk(KERN_ERR PFX "ioremap() failed\n"); - goto failed; - } - - hermes_struct_init(hw, card->vaddr, HERMES_16BIT_REGSPACING); - - /* Power up card */ - pmac_call_feature(PMAC_FTR_AIRPORT_ENABLE, - macio_get_of_node(mdev), 0, 1); - ssleep(1); - - /* Reset it before we get the interrupt */ - hermes_init(hw); - - if (request_irq(card->irq, orinoco_interrupt, 0, DRIVER_NAME, priv)) { - printk(KERN_ERR PFX "Couldn't get IRQ %d\n", card->irq); - goto failed; - } - card->irq_requested = 1; - - /* Initialise the main driver */ - if (orinoco_init(priv) != 0) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto failed; - } - - /* Register an interface with the stack */ - if (orinoco_if_add(priv, phys_addr, card->irq) != 0) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto failed; - } - card->ndev_registered = 1; - return 0; - failed: - airport_detach(mdev); - return -ENODEV; -} /* airport_attach */ - - -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Benjamin Herrenschmidt )"; -MODULE_AUTHOR("Benjamin Herrenschmidt "); -MODULE_DESCRIPTION("Driver for the Apple Airport wireless card."); -MODULE_LICENSE("Dual MPL/GPL"); - -static struct of_device_id airport_match[] = -{ - { - .name = "radio", - }, - {}, -}; - -MODULE_DEVICE_TABLE(of, airport_match); - -static struct macio_driver airport_driver = { - .name = DRIVER_NAME, - .match_table = airport_match, - .probe = airport_attach, - .remove = airport_detach, - .suspend = airport_suspend, - .resume = airport_resume, -}; - -static int __init -init_airport(void) -{ - printk(KERN_DEBUG "%s\n", version); - - return macio_register_driver(&airport_driver); -} - -static void __exit -exit_airport(void) -{ - macio_unregister_driver(&airport_driver); -} - -module_init(init_airport); -module_exit(exit_airport); diff --git a/drivers/net/wireless/orinoco/cfg.c b/drivers/net/wireless/orinoco/cfg.c deleted file mode 100644 index 27f2d3342645..000000000000 --- a/drivers/net/wireless/orinoco/cfg.c +++ /dev/null @@ -1,203 +0,0 @@ -/* cfg80211 support - * - * See copyright notice in main.c - */ -#include -#include -#include "hw.h" -#include "main.h" -#include "orinoco.h" - -#include "cfg.h" - -/* Supported bitrates. Must agree with hw.c */ -static struct ieee80211_rate orinoco_rates[] = { - { .bitrate = 10 }, - { .bitrate = 20 }, - { .bitrate = 55 }, - { .bitrate = 110 }, -}; - -static const void * const orinoco_wiphy_privid = &orinoco_wiphy_privid; - -/* Called after orinoco_private is allocated. */ -void orinoco_wiphy_init(struct wiphy *wiphy) -{ - struct orinoco_private *priv = wiphy_priv(wiphy); - - wiphy->privid = orinoco_wiphy_privid; - - set_wiphy_dev(wiphy, priv->dev); -} - -/* Called after firmware is initialised */ -int orinoco_wiphy_register(struct wiphy *wiphy) -{ - struct orinoco_private *priv = wiphy_priv(wiphy); - int i, channels = 0; - - if (priv->firmware_type == FIRMWARE_TYPE_AGERE) - wiphy->max_scan_ssids = 1; - else - wiphy->max_scan_ssids = 0; - - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - - /* TODO: should we set if we only have demo ad-hoc? - * (priv->has_port3) - */ - if (priv->has_ibss) - wiphy->interface_modes |= BIT(NL80211_IFTYPE_ADHOC); - - if (!priv->broken_monitor || force_monitor) - wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); - - priv->band.bitrates = orinoco_rates; - priv->band.n_bitrates = ARRAY_SIZE(orinoco_rates); - - /* Only support channels allowed by the card EEPROM */ - for (i = 0; i < NUM_CHANNELS; i++) { - if (priv->channel_mask & (1 << i)) { - priv->channels[i].center_freq = - ieee80211_dsss_chan_to_freq(i+1); - channels++; - } - } - priv->band.channels = priv->channels; - priv->band.n_channels = channels; - - wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - - i = 0; - if (priv->has_wep) { - priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP40; - i++; - - if (priv->has_big_wep) { - priv->cipher_suites[i] = WLAN_CIPHER_SUITE_WEP104; - i++; - } - } - if (priv->has_wpa) { - priv->cipher_suites[i] = WLAN_CIPHER_SUITE_TKIP; - i++; - } - wiphy->cipher_suites = priv->cipher_suites; - wiphy->n_cipher_suites = i; - - wiphy->rts_threshold = priv->rts_thresh; - if (!priv->has_mwo) - wiphy->frag_threshold = priv->frag_thresh; - - return wiphy_register(wiphy); -} - -static int orinoco_change_vif(struct wiphy *wiphy, struct net_device *dev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct orinoco_private *priv = wiphy_priv(wiphy); - int err = 0; - unsigned long lock; - - if (orinoco_lock(priv, &lock) != 0) - return -EBUSY; - - switch (type) { - case NL80211_IFTYPE_ADHOC: - if (!priv->has_ibss && !priv->has_port3) - err = -EINVAL; - break; - - case NL80211_IFTYPE_STATION: - break; - - case NL80211_IFTYPE_MONITOR: - if (priv->broken_monitor && !force_monitor) { - printk(KERN_WARNING "%s: Monitor mode support is " - "buggy in this firmware, not enabling\n", - wiphy_name(wiphy)); - err = -EINVAL; - } - break; - - default: - err = -EINVAL; - } - - if (!err) { - priv->iw_mode = type; - set_port_type(priv); - err = orinoco_commit(priv); - } - - orinoco_unlock(priv, &lock); - - return err; -} - -static int orinoco_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) -{ - struct orinoco_private *priv = wiphy_priv(wiphy); - int err; - - if (!request) - return -EINVAL; - - if (priv->scan_request && priv->scan_request != request) - return -EBUSY; - - priv->scan_request = request; - - err = orinoco_hw_trigger_scan(priv, request->ssids); - - return err; -} - -static int orinoco_set_channel(struct wiphy *wiphy, - struct ieee80211_channel *chan, - enum nl80211_channel_type channel_type) -{ - struct orinoco_private *priv = wiphy_priv(wiphy); - int err = 0; - unsigned long flags; - int channel; - - if (!chan) - return -EINVAL; - - if (channel_type != NL80211_CHAN_NO_HT) - return -EINVAL; - - if (chan->band != IEEE80211_BAND_2GHZ) - return -EINVAL; - - channel = ieee80211_freq_to_dsss_chan(chan->center_freq); - - if ((channel < 1) || (channel > NUM_CHANNELS) || - !(priv->channel_mask & (1 << (channel-1)))) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->channel = channel; - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - /* Fast channel change - no commit if successful */ - hermes_t *hw = &priv->hw; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_SET_CHANNEL, - channel, NULL); - } - orinoco_unlock(priv, &flags); - - return err; -} - -const struct cfg80211_ops orinoco_cfg_ops = { - .change_virtual_intf = orinoco_change_vif, - .set_channel = orinoco_set_channel, - .scan = orinoco_scan, -}; diff --git a/drivers/net/wireless/orinoco/cfg.h b/drivers/net/wireless/orinoco/cfg.h deleted file mode 100644 index 3ddc96a06cd7..000000000000 --- a/drivers/net/wireless/orinoco/cfg.h +++ /dev/null @@ -1,15 +0,0 @@ -/* cfg80211 support. - * - * See copyright notice in main.c - */ -#ifndef ORINOCO_CFG_H -#define ORINOCO_CFG_H - -#include - -extern const struct cfg80211_ops orinoco_cfg_ops; - -void orinoco_wiphy_init(struct wiphy *wiphy); -int orinoco_wiphy_register(struct wiphy *wiphy); - -#endif /* ORINOCO_CFG_H */ diff --git a/drivers/net/wireless/orinoco/fw.c b/drivers/net/wireless/orinoco/fw.c deleted file mode 100644 index 1257250a1e22..000000000000 --- a/drivers/net/wireless/orinoco/fw.c +++ /dev/null @@ -1,383 +0,0 @@ -/* Firmware file reading and download helpers - * - * See copyright notice in main.c - */ -#include -#include -#include - -#include "hermes.h" -#include "hermes_dld.h" -#include "orinoco.h" - -#include "fw.h" - -/* End markers (for Symbol firmware only) */ -#define TEXT_END 0x1A /* End of text header */ - -struct fw_info { - char *pri_fw; - char *sta_fw; - char *ap_fw; - u32 pda_addr; - u16 pda_size; -}; - -static const struct fw_info orinoco_fw[] = { - { NULL, "agere_sta_fw.bin", "agere_ap_fw.bin", 0x00390000, 1000 }, - { NULL, "prism_sta_fw.bin", "prism_ap_fw.bin", 0, 1024 }, - { "symbol_sp24t_prim_fw", "symbol_sp24t_sec_fw", NULL, 0x00003100, 512 } -}; - -/* Structure used to access fields in FW - * Make sure LE decoding macros are used - */ -struct orinoco_fw_header { - char hdr_vers[6]; /* ASCII string for header version */ - __le16 headersize; /* Total length of header */ - __le32 entry_point; /* NIC entry point */ - __le32 blocks; /* Number of blocks to program */ - __le32 block_offset; /* Offset of block data from eof header */ - __le32 pdr_offset; /* Offset to PDR data from eof header */ - __le32 pri_offset; /* Offset to primary plug data */ - __le32 compat_offset; /* Offset to compatibility data*/ - char signature[0]; /* FW signature length headersize-20 */ -} __attribute__ ((packed)); - -/* Check the range of various header entries. Return a pointer to a - * description of the problem, or NULL if everything checks out. */ -static const char *validate_fw(const struct orinoco_fw_header *hdr, size_t len) -{ - u16 hdrsize; - - if (len < sizeof(*hdr)) - return "image too small"; - if (memcmp(hdr->hdr_vers, "HFW", 3) != 0) - return "format not recognised"; - - hdrsize = le16_to_cpu(hdr->headersize); - if (hdrsize > len) - return "bad headersize"; - if ((hdrsize + le32_to_cpu(hdr->block_offset)) > len) - return "bad block offset"; - if ((hdrsize + le32_to_cpu(hdr->pdr_offset)) > len) - return "bad PDR offset"; - if ((hdrsize + le32_to_cpu(hdr->pri_offset)) > len) - return "bad PRI offset"; - if ((hdrsize + le32_to_cpu(hdr->compat_offset)) > len) - return "bad compat offset"; - - /* TODO: consider adding a checksum or CRC to the firmware format */ - return NULL; -} - -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) -static inline const struct firmware * -orinoco_cached_fw_get(struct orinoco_private *priv, bool primary) -{ - if (primary) - return priv->cached_pri_fw; - else - return priv->cached_fw; -} -#else -#define orinoco_cached_fw_get(priv, primary) (NULL) -#endif - -/* Download either STA or AP firmware into the card. */ -static int -orinoco_dl_firmware(struct orinoco_private *priv, - const struct fw_info *fw, - int ap) -{ - /* Plug Data Area (PDA) */ - __le16 *pda; - - hermes_t *hw = &priv->hw; - const struct firmware *fw_entry; - const struct orinoco_fw_header *hdr; - const unsigned char *first_block; - const void *end; - const char *firmware; - const char *fw_err; - struct device *dev = priv->dev; - int err = 0; - - pda = kzalloc(fw->pda_size, GFP_KERNEL); - if (!pda) - return -ENOMEM; - - if (ap) - firmware = fw->ap_fw; - else - firmware = fw->sta_fw; - - dev_dbg(dev, "Attempting to download firmware %s\n", firmware); - - /* Read current plug data */ - err = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 0); - dev_dbg(dev, "Read PDA returned %d\n", err); - if (err) - goto free; - - if (!orinoco_cached_fw_get(priv, false)) { - err = request_firmware(&fw_entry, firmware, priv->dev); - - if (err) { - dev_err(dev, "Cannot find firmware %s\n", firmware); - err = -ENOENT; - goto free; - } - } else - fw_entry = orinoco_cached_fw_get(priv, false); - - hdr = (const struct orinoco_fw_header *) fw_entry->data; - - fw_err = validate_fw(hdr, fw_entry->size); - if (fw_err) { - dev_warn(dev, "Invalid firmware image detected (%s). " - "Aborting download\n", fw_err); - err = -EINVAL; - goto abort; - } - - /* Enable aux port to allow programming */ - err = hermesi_program_init(hw, le32_to_cpu(hdr->entry_point)); - dev_dbg(dev, "Program init returned %d\n", err); - if (err != 0) - goto abort; - - /* Program data */ - first_block = (fw_entry->data + - le16_to_cpu(hdr->headersize) + - le32_to_cpu(hdr->block_offset)); - end = fw_entry->data + fw_entry->size; - - err = hermes_program(hw, first_block, end); - dev_dbg(dev, "Program returned %d\n", err); - if (err != 0) - goto abort; - - /* Update production data */ - first_block = (fw_entry->data + - le16_to_cpu(hdr->headersize) + - le32_to_cpu(hdr->pdr_offset)); - - err = hermes_apply_pda_with_defaults(hw, first_block, end, pda, - &pda[fw->pda_size / sizeof(*pda)]); - dev_dbg(dev, "Apply PDA returned %d\n", err); - if (err) - goto abort; - - /* Tell card we've finished */ - err = hermesi_program_end(hw); - dev_dbg(dev, "Program end returned %d\n", err); - if (err != 0) - goto abort; - - /* Check if we're running */ - dev_dbg(dev, "hermes_present returned %d\n", hermes_present(hw)); - -abort: - /* If we requested the firmware, release it. */ - if (!orinoco_cached_fw_get(priv, false)) - release_firmware(fw_entry); - -free: - kfree(pda); - return err; -} - -/* - * Process a firmware image - stop the card, load the firmware, reset - * the card and make sure it responds. For the secondary firmware take - * care of the PDA - read it and then write it on top of the firmware. - */ -static int -symbol_dl_image(struct orinoco_private *priv, const struct fw_info *fw, - const unsigned char *image, const void *end, - int secondary) -{ - hermes_t *hw = &priv->hw; - int ret = 0; - const unsigned char *ptr; - const unsigned char *first_block; - - /* Plug Data Area (PDA) */ - __le16 *pda = NULL; - - /* Binary block begins after the 0x1A marker */ - ptr = image; - while (*ptr++ != TEXT_END); - first_block = ptr; - - /* Read the PDA from EEPROM */ - if (secondary) { - pda = kzalloc(fw->pda_size, GFP_KERNEL); - if (!pda) - return -ENOMEM; - - ret = hermes_read_pda(hw, pda, fw->pda_addr, fw->pda_size, 1); - if (ret) - goto free; - } - - /* Stop the firmware, so that it can be safely rewritten */ - if (priv->stop_fw) { - ret = priv->stop_fw(priv, 1); - if (ret) - goto free; - } - - /* Program the adapter with new firmware */ - ret = hermes_program(hw, first_block, end); - if (ret) - goto free; - - /* Write the PDA to the adapter */ - if (secondary) { - size_t len = hermes_blocks_length(first_block, end); - ptr = first_block + len; - ret = hermes_apply_pda(hw, ptr, end, pda, - &pda[fw->pda_size / sizeof(*pda)]); - kfree(pda); - if (ret) - return ret; - } - - /* Run the firmware */ - if (priv->stop_fw) { - ret = priv->stop_fw(priv, 0); - if (ret) - return ret; - } - - /* Reset hermes chip and make sure it responds */ - ret = hermes_init(hw); - - /* hermes_reset() should return 0 with the secondary firmware */ - if (secondary && ret != 0) - return -ENODEV; - - /* And this should work with any firmware */ - if (!hermes_present(hw)) - return -ENODEV; - - return 0; - -free: - kfree(pda); - return ret; -} - - -/* - * Download the firmware into the card, this also does a PCMCIA soft - * reset on the card, to make sure it's in a sane state. - */ -static int -symbol_dl_firmware(struct orinoco_private *priv, - const struct fw_info *fw) -{ - struct device *dev = priv->dev; - int ret; - const struct firmware *fw_entry; - - if (!orinoco_cached_fw_get(priv, true)) { - if (request_firmware(&fw_entry, fw->pri_fw, priv->dev) != 0) { - dev_err(dev, "Cannot find firmware: %s\n", fw->pri_fw); - return -ENOENT; - } - } else - fw_entry = orinoco_cached_fw_get(priv, true); - - /* Load primary firmware */ - ret = symbol_dl_image(priv, fw, fw_entry->data, - fw_entry->data + fw_entry->size, 0); - - if (!orinoco_cached_fw_get(priv, true)) - release_firmware(fw_entry); - if (ret) { - dev_err(dev, "Primary firmware download failed\n"); - return ret; - } - - if (!orinoco_cached_fw_get(priv, false)) { - if (request_firmware(&fw_entry, fw->sta_fw, priv->dev) != 0) { - dev_err(dev, "Cannot find firmware: %s\n", fw->sta_fw); - return -ENOENT; - } - } else - fw_entry = orinoco_cached_fw_get(priv, false); - - /* Load secondary firmware */ - ret = symbol_dl_image(priv, fw, fw_entry->data, - fw_entry->data + fw_entry->size, 1); - if (!orinoco_cached_fw_get(priv, false)) - release_firmware(fw_entry); - if (ret) { - dev_err(dev, "Secondary firmware download failed\n"); - } - - return ret; -} - -int orinoco_download(struct orinoco_private *priv) -{ - int err = 0; - /* Reload firmware */ - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - /* case FIRMWARE_TYPE_INTERSIL: */ - err = orinoco_dl_firmware(priv, - &orinoco_fw[priv->firmware_type], 0); - break; - - case FIRMWARE_TYPE_SYMBOL: - err = symbol_dl_firmware(priv, - &orinoco_fw[priv->firmware_type]); - break; - case FIRMWARE_TYPE_INTERSIL: - break; - } - /* TODO: if we fail we probably need to reinitialise - * the driver */ - - return err; -} - -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) -void orinoco_cache_fw(struct orinoco_private *priv, int ap) -{ - const struct firmware *fw_entry = NULL; - const char *pri_fw; - const char *fw; - - pri_fw = orinoco_fw[priv->firmware_type].pri_fw; - if (ap) - fw = orinoco_fw[priv->firmware_type].ap_fw; - else - fw = orinoco_fw[priv->firmware_type].sta_fw; - - if (pri_fw) { - if (request_firmware(&fw_entry, pri_fw, priv->dev) == 0) - priv->cached_pri_fw = fw_entry; - } - - if (fw) { - if (request_firmware(&fw_entry, fw, priv->dev) == 0) - priv->cached_fw = fw_entry; - } -} - -void orinoco_uncache_fw(struct orinoco_private *priv) -{ - if (priv->cached_pri_fw) - release_firmware(priv->cached_pri_fw); - if (priv->cached_fw) - release_firmware(priv->cached_fw); - - priv->cached_pri_fw = NULL; - priv->cached_fw = NULL; -} -#endif diff --git a/drivers/net/wireless/orinoco/fw.h b/drivers/net/wireless/orinoco/fw.h deleted file mode 100644 index 89fc26d25b06..000000000000 --- a/drivers/net/wireless/orinoco/fw.h +++ /dev/null @@ -1,21 +0,0 @@ -/* Firmware file reading and download helpers - * - * See copyright notice in main.c - */ -#ifndef _ORINOCO_FW_H_ -#define _ORINOCO_FW_H_ - -/* Forward declations */ -struct orinoco_private; - -int orinoco_download(struct orinoco_private *priv); - -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) -void orinoco_cache_fw(struct orinoco_private *priv, int ap); -void orinoco_uncache_fw(struct orinoco_private *priv); -#else -#define orinoco_cache_fw(priv, ap) do { } while(0) -#define orinoco_uncache_fw(priv) do { } while (0) -#endif - -#endif /* _ORINOCO_FW_H_ */ diff --git a/drivers/net/wireless/orinoco/hermes.c b/drivers/net/wireless/orinoco/hermes.c deleted file mode 100644 index 1a2fca76fd3c..000000000000 --- a/drivers/net/wireless/orinoco/hermes.c +++ /dev/null @@ -1,536 +0,0 @@ -/* hermes.c - * - * Driver core for the "Hermes" wireless MAC controller, as used in - * the Lucent Orinoco and Cabletron RoamAbout cards. It should also - * work on the hfa3841 and hfa3842 MAC controller chips used in the - * Prism II chipsets. - * - * This is not a complete driver, just low-level access routines for - * the MAC controller itself. - * - * Based on the prism2 driver from Absolute Value Systems' linux-wlan - * project, the Linux wvlan_cs driver, Lucent's HCF-Light - * (wvlan_hcf.c) library, and the NetBSD wireless driver (in no - * particular order). - * - * Copyright (C) 2000, David Gibson, Linuxcare Australia. - * (C) Copyright David Gibson, IBM Corp. 2001-2003. - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - */ - -#include -#include -#include -#include - -#include "hermes.h" - -/* These are maximum timeouts. Most often, card wil react much faster */ -#define CMD_BUSY_TIMEOUT (100) /* In iterations of ~1us */ -#define CMD_INIT_TIMEOUT (50000) /* in iterations of ~10us */ -#define CMD_COMPL_TIMEOUT (20000) /* in iterations of ~10us */ -#define ALLOC_COMPL_TIMEOUT (1000) /* in iterations of ~10us */ - -/* - * Debugging helpers - */ - -#define DMSG(stuff...) do {printk(KERN_DEBUG "hermes @ %p: " , hw->iobase); \ - printk(stuff); } while (0) - -#undef HERMES_DEBUG -#ifdef HERMES_DEBUG -#include - -#define DEBUG(lvl, stuff...) if ((lvl) <= HERMES_DEBUG) DMSG(stuff) - -#else /* ! HERMES_DEBUG */ - -#define DEBUG(lvl, stuff...) do { } while (0) - -#endif /* ! HERMES_DEBUG */ - - -/* - * Internal functions - */ - -/* Issue a command to the chip. Waiting for it to complete is the caller's - problem. - - Returns -EBUSY if the command register is busy, 0 on success. - - Callable from any context. -*/ -static int hermes_issue_cmd(hermes_t *hw, u16 cmd, u16 param0, - u16 param1, u16 param2) -{ - int k = CMD_BUSY_TIMEOUT; - u16 reg; - - /* First wait for the command register to unbusy */ - reg = hermes_read_regn(hw, CMD); - while ((reg & HERMES_CMD_BUSY) && k) { - k--; - udelay(1); - reg = hermes_read_regn(hw, CMD); - } - if (reg & HERMES_CMD_BUSY) - return -EBUSY; - - hermes_write_regn(hw, PARAM2, param2); - hermes_write_regn(hw, PARAM1, param1); - hermes_write_regn(hw, PARAM0, param0); - hermes_write_regn(hw, CMD, cmd); - - return 0; -} - -/* - * Function definitions - */ - -/* For doing cmds that wipe the magic constant in SWSUPPORT0 */ -int hermes_doicmd_wait(hermes_t *hw, u16 cmd, - u16 parm0, u16 parm1, u16 parm2, - struct hermes_response *resp) -{ - int err = 0; - int k; - u16 status, reg; - - err = hermes_issue_cmd(hw, cmd, parm0, parm1, parm2); - if (err) - return err; - - reg = hermes_read_regn(hw, EVSTAT); - k = CMD_INIT_TIMEOUT; - while ((!(reg & HERMES_EV_CMD)) && k) { - k--; - udelay(10); - reg = hermes_read_regn(hw, EVSTAT); - } - - hermes_write_regn(hw, SWSUPPORT0, HERMES_MAGIC); - - if (!hermes_present(hw)) { - DEBUG(0, "hermes @ 0x%x: Card removed during reset.\n", - hw->iobase); - err = -ENODEV; - goto out; - } - - if (!(reg & HERMES_EV_CMD)) { - printk(KERN_ERR "hermes @ %p: " - "Timeout waiting for card to reset (reg=0x%04x)!\n", - hw->iobase, reg); - err = -ETIMEDOUT; - goto out; - } - - status = hermes_read_regn(hw, STATUS); - if (resp) { - resp->status = status; - resp->resp0 = hermes_read_regn(hw, RESP0); - resp->resp1 = hermes_read_regn(hw, RESP1); - resp->resp2 = hermes_read_regn(hw, RESP2); - } - - hermes_write_regn(hw, EVACK, HERMES_EV_CMD); - - if (status & HERMES_STATUS_RESULT) - err = -EIO; -out: - return err; -} -EXPORT_SYMBOL(hermes_doicmd_wait); - -void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing) -{ - hw->iobase = address; - hw->reg_spacing = reg_spacing; - hw->inten = 0x0; -} -EXPORT_SYMBOL(hermes_struct_init); - -int hermes_init(hermes_t *hw) -{ - u16 reg; - int err = 0; - int k; - - /* We don't want to be interrupted while resetting the chipset */ - hw->inten = 0x0; - hermes_write_regn(hw, INTEN, 0); - hermes_write_regn(hw, EVACK, 0xffff); - - /* Normally it's a "can't happen" for the command register to - be busy when we go to issue a command because we are - serializing all commands. However we want to have some - chance of resetting the card even if it gets into a stupid - state, so we actually wait to see if the command register - will unbusy itself here. */ - k = CMD_BUSY_TIMEOUT; - reg = hermes_read_regn(hw, CMD); - while (k && (reg & HERMES_CMD_BUSY)) { - if (reg == 0xffff) /* Special case - the card has probably been - removed, so don't wait for the timeout */ - return -ENODEV; - - k--; - udelay(1); - reg = hermes_read_regn(hw, CMD); - } - - /* No need to explicitly handle the timeout - if we've timed - out hermes_issue_cmd() will probably return -EBUSY below */ - - /* According to the documentation, EVSTAT may contain - obsolete event occurrence information. We have to acknowledge - it by writing EVACK. */ - reg = hermes_read_regn(hw, EVSTAT); - hermes_write_regn(hw, EVACK, reg); - - /* We don't use hermes_docmd_wait here, because the reset wipes - the magic constant in SWSUPPORT0 away, and it gets confused */ - err = hermes_doicmd_wait(hw, HERMES_CMD_INIT, 0, 0, 0, NULL); - - return err; -} -EXPORT_SYMBOL(hermes_init); - -/* Issue a command to the chip, and (busy!) wait for it to - * complete. - * - * Returns: - * < 0 on internal error - * 0 on success - * > 0 on error returned by the firmware - * - * Callable from any context, but locking is your problem. */ -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, - struct hermes_response *resp) -{ - int err; - int k; - u16 reg; - u16 status; - - err = hermes_issue_cmd(hw, cmd, parm0, 0, 0); - if (err) { - if (!hermes_present(hw)) { - if (net_ratelimit()) - printk(KERN_WARNING "hermes @ %p: " - "Card removed while issuing command " - "0x%04x.\n", hw->iobase, cmd); - err = -ENODEV; - } else - if (net_ratelimit()) - printk(KERN_ERR "hermes @ %p: " - "Error %d issuing command 0x%04x.\n", - hw->iobase, err, cmd); - goto out; - } - - reg = hermes_read_regn(hw, EVSTAT); - k = CMD_COMPL_TIMEOUT; - while ((!(reg & HERMES_EV_CMD)) && k) { - k--; - udelay(10); - reg = hermes_read_regn(hw, EVSTAT); - } - - if (!hermes_present(hw)) { - printk(KERN_WARNING "hermes @ %p: Card removed " - "while waiting for command 0x%04x completion.\n", - hw->iobase, cmd); - err = -ENODEV; - goto out; - } - - if (!(reg & HERMES_EV_CMD)) { - printk(KERN_ERR "hermes @ %p: Timeout waiting for " - "command 0x%04x completion.\n", hw->iobase, cmd); - err = -ETIMEDOUT; - goto out; - } - - status = hermes_read_regn(hw, STATUS); - if (resp) { - resp->status = status; - resp->resp0 = hermes_read_regn(hw, RESP0); - resp->resp1 = hermes_read_regn(hw, RESP1); - resp->resp2 = hermes_read_regn(hw, RESP2); - } - - hermes_write_regn(hw, EVACK, HERMES_EV_CMD); - - if (status & HERMES_STATUS_RESULT) - err = -EIO; - - out: - return err; -} -EXPORT_SYMBOL(hermes_docmd_wait); - -int hermes_allocate(hermes_t *hw, u16 size, u16 *fid) -{ - int err = 0; - int k; - u16 reg; - - if ((size < HERMES_ALLOC_LEN_MIN) || (size > HERMES_ALLOC_LEN_MAX)) - return -EINVAL; - - err = hermes_docmd_wait(hw, HERMES_CMD_ALLOC, size, NULL); - if (err) - return err; - - reg = hermes_read_regn(hw, EVSTAT); - k = ALLOC_COMPL_TIMEOUT; - while ((!(reg & HERMES_EV_ALLOC)) && k) { - k--; - udelay(10); - reg = hermes_read_regn(hw, EVSTAT); - } - - if (!hermes_present(hw)) { - printk(KERN_WARNING "hermes @ %p: " - "Card removed waiting for frame allocation.\n", - hw->iobase); - return -ENODEV; - } - - if (!(reg & HERMES_EV_ALLOC)) { - printk(KERN_ERR "hermes @ %p: " - "Timeout waiting for frame allocation\n", - hw->iobase); - return -ETIMEDOUT; - } - - *fid = hermes_read_regn(hw, ALLOCFID); - hermes_write_regn(hw, EVACK, HERMES_EV_ALLOC); - - return 0; -} -EXPORT_SYMBOL(hermes_allocate); - -/* Set up a BAP to read a particular chunk of data from card's internal buffer. - * - * Returns: - * < 0 on internal failure (errno) - * 0 on success - * > 0 on error - * from firmware - * - * Callable from any context */ -static int hermes_bap_seek(hermes_t *hw, int bap, u16 id, u16 offset) -{ - int sreg = bap ? HERMES_SELECT1 : HERMES_SELECT0; - int oreg = bap ? HERMES_OFFSET1 : HERMES_OFFSET0; - int k; - u16 reg; - - /* Paranoia.. */ - if ((offset > HERMES_BAP_OFFSET_MAX) || (offset % 2)) - return -EINVAL; - - k = HERMES_BAP_BUSY_TIMEOUT; - reg = hermes_read_reg(hw, oreg); - while ((reg & HERMES_OFFSET_BUSY) && k) { - k--; - udelay(1); - reg = hermes_read_reg(hw, oreg); - } - - if (reg & HERMES_OFFSET_BUSY) - return -ETIMEDOUT; - - /* Now we actually set up the transfer */ - hermes_write_reg(hw, sreg, id); - hermes_write_reg(hw, oreg, offset); - - /* Wait for the BAP to be ready */ - k = HERMES_BAP_BUSY_TIMEOUT; - reg = hermes_read_reg(hw, oreg); - while ((reg & (HERMES_OFFSET_BUSY | HERMES_OFFSET_ERR)) && k) { - k--; - udelay(1); - reg = hermes_read_reg(hw, oreg); - } - - if (reg != offset) { - printk(KERN_ERR "hermes @ %p: BAP%d offset %s: " - "reg=0x%x id=0x%x offset=0x%x\n", hw->iobase, bap, - (reg & HERMES_OFFSET_BUSY) ? "timeout" : "error", - reg, id, offset); - - if (reg & HERMES_OFFSET_BUSY) - return -ETIMEDOUT; - - return -EIO; /* error or wrong offset */ - } - - return 0; -} - -/* Read a block of data from the chip's buffer, via the - * BAP. Synchronization/serialization is the caller's problem. len - * must be even. - * - * Returns: - * < 0 on internal failure (errno) - * 0 on success - * > 0 on error from firmware - */ -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, - u16 id, u16 offset) -{ - int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; - int err = 0; - - if ((len < 0) || (len % 2)) - return -EINVAL; - - err = hermes_bap_seek(hw, bap, id, offset); - if (err) - goto out; - - /* Actually do the transfer */ - hermes_read_words(hw, dreg, buf, len/2); - - out: - return err; -} -EXPORT_SYMBOL(hermes_bap_pread); - -/* Write a block of data to the chip's buffer, via the - * BAP. Synchronization/serialization is the caller's problem. - * - * Returns: - * < 0 on internal failure (errno) - * 0 on success - * > 0 on error from firmware - */ -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, - u16 id, u16 offset) -{ - int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; - int err = 0; - - if (len < 0) - return -EINVAL; - - err = hermes_bap_seek(hw, bap, id, offset); - if (err) - goto out; - - /* Actually do the transfer */ - hermes_write_bytes(hw, dreg, buf, len); - - out: - return err; -} -EXPORT_SYMBOL(hermes_bap_pwrite); - -/* Read a Length-Type-Value record from the card. - * - * If length is NULL, we ignore the length read from the card, and - * read the entire buffer regardless. This is useful because some of - * the configuration records appear to have incorrect lengths in - * practice. - * - * Callable from user or bh context. */ -int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned bufsize, - u16 *length, void *buf) -{ - int err = 0; - int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; - u16 rlength, rtype; - unsigned nwords; - - if (bufsize % 2) - return -EINVAL; - - err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS, rid, NULL); - if (err) - return err; - - err = hermes_bap_seek(hw, bap, rid, 0); - if (err) - return err; - - rlength = hermes_read_reg(hw, dreg); - - if (!rlength) - return -ENODATA; - - rtype = hermes_read_reg(hw, dreg); - - if (length) - *length = rlength; - - if (rtype != rid) - printk(KERN_WARNING "hermes @ %p: %s(): " - "rid (0x%04x) does not match type (0x%04x)\n", - hw->iobase, __func__, rid, rtype); - if (HERMES_RECLEN_TO_BYTES(rlength) > bufsize) - printk(KERN_WARNING "hermes @ %p: " - "Truncating LTV record from %d to %d bytes. " - "(rid=0x%04x, len=0x%04x)\n", hw->iobase, - HERMES_RECLEN_TO_BYTES(rlength), bufsize, rid, rlength); - - nwords = min((unsigned)rlength - 1, bufsize / 2); - hermes_read_words(hw, dreg, buf, nwords); - - return 0; -} -EXPORT_SYMBOL(hermes_read_ltv); - -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, - u16 length, const void *value) -{ - int dreg = bap ? HERMES_DATA1 : HERMES_DATA0; - int err = 0; - unsigned count; - - if (length == 0) - return -EINVAL; - - err = hermes_bap_seek(hw, bap, rid, 0); - if (err) - return err; - - hermes_write_reg(hw, dreg, length); - hermes_write_reg(hw, dreg, rid); - - count = length - 1; - - hermes_write_bytes(hw, dreg, value, count << 1); - - err = hermes_docmd_wait(hw, HERMES_CMD_ACCESS | HERMES_CMD_WRITE, - rid, NULL); - - return err; -} -EXPORT_SYMBOL(hermes_write_ltv); diff --git a/drivers/net/wireless/orinoco/hermes.h b/drivers/net/wireless/orinoco/hermes.h deleted file mode 100644 index 2dddbb597c4d..000000000000 --- a/drivers/net/wireless/orinoco/hermes.h +++ /dev/null @@ -1,499 +0,0 @@ -/* hermes.h - * - * Driver core for the "Hermes" wireless MAC controller, as used in - * the Lucent Orinoco and Cabletron RoamAbout cards. It should also - * work on the hfa3841 and hfa3842 MAC controller chips used in the - * Prism I & II chipsets. - * - * This is not a complete driver, just low-level access routines for - * the MAC controller itself. - * - * Based on the prism2 driver from Absolute Value Systems' linux-wlan - * project, the Linux wvlan_cs driver, Lucent's HCF-Light - * (wvlan_hcf.c) library, and the NetBSD wireless driver. - * - * Copyright (C) 2000, David Gibson, Linuxcare Australia. - * (C) Copyright David Gibson, IBM Corp. 2001-2003. - * - * Portions taken from hfa384x.h. - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - * - * This file distributed under the GPL, version 2. - */ - -#ifndef _HERMES_H -#define _HERMES_H - -/* Notes on locking: - * - * As a module of low level hardware access routines, there is no - * locking. Users of this module should ensure that they serialize - * access to the hermes_t structure, and to the hardware -*/ - -#include -#include - -/* - * Limits and constants - */ -#define HERMES_ALLOC_LEN_MIN (4) -#define HERMES_ALLOC_LEN_MAX (2400) -#define HERMES_LTV_LEN_MAX (34) -#define HERMES_BAP_DATALEN_MAX (4096) -#define HERMES_BAP_OFFSET_MAX (4096) -#define HERMES_PORTID_MAX (7) -#define HERMES_NUMPORTS_MAX (HERMES_PORTID_MAX+1) -#define HERMES_PDR_LEN_MAX (260) /* in bytes, from EK */ -#define HERMES_PDA_RECS_MAX (200) /* a guess */ -#define HERMES_PDA_LEN_MAX (1024) /* in bytes, from EK */ -#define HERMES_SCANRESULT_MAX (35) -#define HERMES_CHINFORESULT_MAX (8) -#define HERMES_MAX_MULTICAST (16) -#define HERMES_MAGIC (0x7d1f) - -/* - * Hermes register offsets - */ -#define HERMES_CMD (0x00) -#define HERMES_PARAM0 (0x02) -#define HERMES_PARAM1 (0x04) -#define HERMES_PARAM2 (0x06) -#define HERMES_STATUS (0x08) -#define HERMES_RESP0 (0x0A) -#define HERMES_RESP1 (0x0C) -#define HERMES_RESP2 (0x0E) -#define HERMES_INFOFID (0x10) -#define HERMES_RXFID (0x20) -#define HERMES_ALLOCFID (0x22) -#define HERMES_TXCOMPLFID (0x24) -#define HERMES_SELECT0 (0x18) -#define HERMES_OFFSET0 (0x1C) -#define HERMES_DATA0 (0x36) -#define HERMES_SELECT1 (0x1A) -#define HERMES_OFFSET1 (0x1E) -#define HERMES_DATA1 (0x38) -#define HERMES_EVSTAT (0x30) -#define HERMES_INTEN (0x32) -#define HERMES_EVACK (0x34) -#define HERMES_CONTROL (0x14) -#define HERMES_SWSUPPORT0 (0x28) -#define HERMES_SWSUPPORT1 (0x2A) -#define HERMES_SWSUPPORT2 (0x2C) -#define HERMES_AUXPAGE (0x3A) -#define HERMES_AUXOFFSET (0x3C) -#define HERMES_AUXDATA (0x3E) - -/* - * CMD register bitmasks - */ -#define HERMES_CMD_BUSY (0x8000) -#define HERMES_CMD_AINFO (0x7f00) -#define HERMES_CMD_MACPORT (0x0700) -#define HERMES_CMD_RECL (0x0100) -#define HERMES_CMD_WRITE (0x0100) -#define HERMES_CMD_PROGMODE (0x0300) -#define HERMES_CMD_CMDCODE (0x003f) - -/* - * STATUS register bitmasks - */ -#define HERMES_STATUS_RESULT (0x7f00) -#define HERMES_STATUS_CMDCODE (0x003f) - -/* - * OFFSET register bitmasks - */ -#define HERMES_OFFSET_BUSY (0x8000) -#define HERMES_OFFSET_ERR (0x4000) -#define HERMES_OFFSET_DATAOFF (0x0ffe) - -/* - * Event register bitmasks (INTEN, EVSTAT, EVACK) - */ -#define HERMES_EV_TICK (0x8000) -#define HERMES_EV_WTERR (0x4000) -#define HERMES_EV_INFDROP (0x2000) -#define HERMES_EV_INFO (0x0080) -#define HERMES_EV_DTIM (0x0020) -#define HERMES_EV_CMD (0x0010) -#define HERMES_EV_ALLOC (0x0008) -#define HERMES_EV_TXEXC (0x0004) -#define HERMES_EV_TX (0x0002) -#define HERMES_EV_RX (0x0001) - -/* - * Command codes - */ -/*--- Controller Commands ----------------------------*/ -#define HERMES_CMD_INIT (0x0000) -#define HERMES_CMD_ENABLE (0x0001) -#define HERMES_CMD_DISABLE (0x0002) -#define HERMES_CMD_DIAG (0x0003) - -/*--- Buffer Mgmt Commands ---------------------------*/ -#define HERMES_CMD_ALLOC (0x000A) -#define HERMES_CMD_TX (0x000B) - -/*--- Regulate Commands ------------------------------*/ -#define HERMES_CMD_NOTIFY (0x0010) -#define HERMES_CMD_INQUIRE (0x0011) - -/*--- Configure Commands -----------------------------*/ -#define HERMES_CMD_ACCESS (0x0021) -#define HERMES_CMD_DOWNLD (0x0022) - -/*--- Serial I/O Commands ----------------------------*/ -#define HERMES_CMD_READMIF (0x0030) -#define HERMES_CMD_WRITEMIF (0x0031) - -/*--- Debugging Commands -----------------------------*/ -#define HERMES_CMD_TEST (0x0038) - - -/* Test command arguments */ -#define HERMES_TEST_SET_CHANNEL 0x0800 -#define HERMES_TEST_MONITOR 0x0b00 -#define HERMES_TEST_STOP 0x0f00 - -/* Authentication algorithms */ -#define HERMES_AUTH_OPEN 1 -#define HERMES_AUTH_SHARED_KEY 2 - -/* WEP settings */ -#define HERMES_WEP_PRIVACY_INVOKED 0x0001 -#define HERMES_WEP_EXCL_UNENCRYPTED 0x0002 -#define HERMES_WEP_HOST_ENCRYPT 0x0010 -#define HERMES_WEP_HOST_DECRYPT 0x0080 - -/* Symbol hostscan options */ -#define HERMES_HOSTSCAN_SYMBOL_5SEC 0x0001 -#define HERMES_HOSTSCAN_SYMBOL_ONCE 0x0002 -#define HERMES_HOSTSCAN_SYMBOL_PASSIVE 0x0040 -#define HERMES_HOSTSCAN_SYMBOL_BCAST 0x0080 - -/* - * Frame structures and constants - */ - -#define HERMES_DESCRIPTOR_OFFSET 0 -#define HERMES_802_11_OFFSET (14) -#define HERMES_802_3_OFFSET (14+32) -#define HERMES_802_2_OFFSET (14+32+14) -#define HERMES_TXCNTL2_OFFSET (HERMES_802_3_OFFSET - 2) - -#define HERMES_RXSTAT_ERR (0x0003) -#define HERMES_RXSTAT_BADCRC (0x0001) -#define HERMES_RXSTAT_UNDECRYPTABLE (0x0002) -#define HERMES_RXSTAT_MIC (0x0010) /* Frame contains MIC */ -#define HERMES_RXSTAT_MACPORT (0x0700) -#define HERMES_RXSTAT_PCF (0x1000) /* Frame was received in CF period */ -#define HERMES_RXSTAT_MIC_KEY_ID (0x1800) /* MIC key used */ -#define HERMES_RXSTAT_MSGTYPE (0xE000) -#define HERMES_RXSTAT_1042 (0x2000) /* RFC-1042 frame */ -#define HERMES_RXSTAT_TUNNEL (0x4000) /* bridge-tunnel encoded frame */ -#define HERMES_RXSTAT_WMP (0x6000) /* Wavelan-II Management Protocol frame */ - -/* Shift amount for key ID in RXSTAT and TXCTRL */ -#define HERMES_MIC_KEY_ID_SHIFT 11 - -struct hermes_tx_descriptor { - __le16 status; - __le16 reserved1; - __le16 reserved2; - __le32 sw_support; - u8 retry_count; - u8 tx_rate; - __le16 tx_control; -} __attribute__ ((packed)); - -#define HERMES_TXSTAT_RETRYERR (0x0001) -#define HERMES_TXSTAT_AGEDERR (0x0002) -#define HERMES_TXSTAT_DISCON (0x0004) -#define HERMES_TXSTAT_FORMERR (0x0008) - -#define HERMES_TXCTRL_TX_OK (0x0002) /* ?? interrupt on Tx complete */ -#define HERMES_TXCTRL_TX_EX (0x0004) /* ?? interrupt on Tx exception */ -#define HERMES_TXCTRL_802_11 (0x0008) /* We supply 802.11 header */ -#define HERMES_TXCTRL_MIC (0x0010) /* 802.3 + TKIP */ -#define HERMES_TXCTRL_MIC_KEY_ID (0x1800) /* MIC Key ID mask */ -#define HERMES_TXCTRL_ALT_RTRY (0x0020) - -/* Inquiry constants and data types */ - -#define HERMES_INQ_TALLIES (0xF100) -#define HERMES_INQ_SCAN (0xF101) -#define HERMES_INQ_CHANNELINFO (0xF102) -#define HERMES_INQ_HOSTSCAN (0xF103) -#define HERMES_INQ_HOSTSCAN_SYMBOL (0xF104) -#define HERMES_INQ_LINKSTATUS (0xF200) -#define HERMES_INQ_SEC_STAT_AGERE (0xF202) - -struct hermes_tallies_frame { - __le16 TxUnicastFrames; - __le16 TxMulticastFrames; - __le16 TxFragments; - __le16 TxUnicastOctets; - __le16 TxMulticastOctets; - __le16 TxDeferredTransmissions; - __le16 TxSingleRetryFrames; - __le16 TxMultipleRetryFrames; - __le16 TxRetryLimitExceeded; - __le16 TxDiscards; - __le16 RxUnicastFrames; - __le16 RxMulticastFrames; - __le16 RxFragments; - __le16 RxUnicastOctets; - __le16 RxMulticastOctets; - __le16 RxFCSErrors; - __le16 RxDiscards_NoBuffer; - __le16 TxDiscardsWrongSA; - __le16 RxWEPUndecryptable; - __le16 RxMsgInMsgFragments; - __le16 RxMsgInBadMsgFragments; - /* Those last are probably not available in very old firmwares */ - __le16 RxDiscards_WEPICVError; - __le16 RxDiscards_WEPExcluded; -} __attribute__ ((packed)); - -/* Grabbed from wlan-ng - Thanks Mark... - Jean II - * This is the result of a scan inquiry command */ -/* Structure describing info about an Access Point */ -struct prism2_scan_apinfo { - __le16 channel; /* Channel where the AP sits */ - __le16 noise; /* Noise level */ - __le16 level; /* Signal level */ - u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ - __le16 beacon_interv; /* Beacon interval */ - __le16 capabilities; /* Capabilities */ - __le16 essid_len; /* ESSID length */ - u8 essid[32]; /* ESSID of the network */ - u8 rates[10]; /* Bit rate supported */ - __le16 proberesp_rate; /* Data rate of the response frame */ - __le16 atim; /* ATIM window time, Kus (hostscan only) */ -} __attribute__ ((packed)); - -/* Same stuff for the Lucent/Agere card. - * Thanks to h1kari - Jean II */ -struct agere_scan_apinfo { - __le16 channel; /* Channel where the AP sits */ - __le16 noise; /* Noise level */ - __le16 level; /* Signal level */ - u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ - __le16 beacon_interv; /* Beacon interval */ - __le16 capabilities; /* Capabilities */ - /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ - __le16 essid_len; /* ESSID length */ - u8 essid[32]; /* ESSID of the network */ -} __attribute__ ((packed)); - -/* Moustafa: Scan structure for Symbol cards */ -struct symbol_scan_apinfo { - u8 channel; /* Channel where the AP sits */ - u8 unknown1; /* 8 in 2.9x and 3.9x f/w, 0 otherwise */ - __le16 noise; /* Noise level */ - __le16 level; /* Signal level */ - u8 bssid[ETH_ALEN]; /* MAC address of the Access Point */ - __le16 beacon_interv; /* Beacon interval */ - __le16 capabilities; /* Capabilities */ - /* bits: 0-ess, 1-ibss, 4-privacy [wep] */ - __le16 essid_len; /* ESSID length */ - u8 essid[32]; /* ESSID of the network */ - __le16 rates[5]; /* Bit rate supported */ - __le16 basic_rates; /* Basic rates bitmask */ - u8 unknown2[6]; /* Always FF:FF:FF:FF:00:00 */ - u8 unknown3[8]; /* Always 0, appeared in f/w 3.91-68 */ -} __attribute__ ((packed)); - -union hermes_scan_info { - struct agere_scan_apinfo a; - struct prism2_scan_apinfo p; - struct symbol_scan_apinfo s; -}; - -/* Extended scan struct for HERMES_INQ_CHANNELINFO. - * wl_lkm calls this an ACS scan (Automatic Channel Select). - * Keep out of union hermes_scan_info because it is much bigger than - * the older scan structures. */ -struct agere_ext_scan_info { - __le16 reserved0; - - u8 noise; - u8 level; - u8 rx_flow; - u8 rate; - __le16 reserved1[2]; - - __le16 frame_control; - __le16 dur_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - __le16 sequence; - u8 addr4[ETH_ALEN]; - - __le16 data_length; - - /* Next 3 fields do not get filled in. */ - u8 daddr[ETH_ALEN]; - u8 saddr[ETH_ALEN]; - __le16 len_type; - - __le64 timestamp; - __le16 beacon_interval; - __le16 capabilities; - u8 data[0]; -} __attribute__ ((packed)); - -#define HERMES_LINKSTATUS_NOT_CONNECTED (0x0000) -#define HERMES_LINKSTATUS_CONNECTED (0x0001) -#define HERMES_LINKSTATUS_DISCONNECTED (0x0002) -#define HERMES_LINKSTATUS_AP_CHANGE (0x0003) -#define HERMES_LINKSTATUS_AP_OUT_OF_RANGE (0x0004) -#define HERMES_LINKSTATUS_AP_IN_RANGE (0x0005) -#define HERMES_LINKSTATUS_ASSOC_FAILED (0x0006) - -struct hermes_linkstatus { - __le16 linkstatus; /* Link status */ -} __attribute__ ((packed)); - -struct hermes_response { - u16 status, resp0, resp1, resp2; -}; - -/* "ID" structure - used for ESSID and station nickname */ -struct hermes_idstring { - __le16 len; - __le16 val[16]; -} __attribute__ ((packed)); - -struct hermes_multicast { - u8 addr[HERMES_MAX_MULTICAST][ETH_ALEN]; -} __attribute__ ((packed)); - -/* Timeouts */ -#define HERMES_BAP_BUSY_TIMEOUT (10000) /* In iterations of ~1us */ - -/* Basic control structure */ -typedef struct hermes { - void __iomem *iobase; - int reg_spacing; -#define HERMES_16BIT_REGSPACING 0 -#define HERMES_32BIT_REGSPACING 1 - u16 inten; /* Which interrupts should be enabled? */ -} hermes_t; - -/* Register access convenience macros */ -#define hermes_read_reg(hw, off) \ - (ioread16((hw)->iobase + ((off) << (hw)->reg_spacing))) -#define hermes_write_reg(hw, off, val) \ - (iowrite16((val), (hw)->iobase + ((off) << (hw)->reg_spacing))) -#define hermes_read_regn(hw, name) hermes_read_reg((hw), HERMES_##name) -#define hermes_write_regn(hw, name, val) \ - hermes_write_reg((hw), HERMES_##name, (val)) - -/* Function prototypes */ -void hermes_struct_init(hermes_t *hw, void __iomem *address, int reg_spacing); -int hermes_init(hermes_t *hw); -int hermes_docmd_wait(hermes_t *hw, u16 cmd, u16 parm0, - struct hermes_response *resp); -int hermes_doicmd_wait(hermes_t *hw, u16 cmd, - u16 parm0, u16 parm1, u16 parm2, - struct hermes_response *resp); -int hermes_allocate(hermes_t *hw, u16 size, u16 *fid); - -int hermes_bap_pread(hermes_t *hw, int bap, void *buf, int len, - u16 id, u16 offset); -int hermes_bap_pwrite(hermes_t *hw, int bap, const void *buf, int len, - u16 id, u16 offset); -int hermes_read_ltv(hermes_t *hw, int bap, u16 rid, unsigned buflen, - u16 *length, void *buf); -int hermes_write_ltv(hermes_t *hw, int bap, u16 rid, - u16 length, const void *value); - -/* Inline functions */ - -static inline int hermes_present(hermes_t *hw) -{ - return hermes_read_regn(hw, SWSUPPORT0) == HERMES_MAGIC; -} - -static inline void hermes_set_irqmask(hermes_t *hw, u16 events) -{ - hw->inten = events; - hermes_write_regn(hw, INTEN, events); -} - -static inline int hermes_enable_port(hermes_t *hw, int port) -{ - return hermes_docmd_wait(hw, HERMES_CMD_ENABLE | (port << 8), - 0, NULL); -} - -static inline int hermes_disable_port(hermes_t *hw, int port) -{ - return hermes_docmd_wait(hw, HERMES_CMD_DISABLE | (port << 8), - 0, NULL); -} - -/* Initiate an INQUIRE command (tallies or scan). The result will come as an - * information frame in __orinoco_ev_info() */ -static inline int hermes_inquire(hermes_t *hw, u16 rid) -{ - return hermes_docmd_wait(hw, HERMES_CMD_INQUIRE, rid, NULL); -} - -#define HERMES_BYTES_TO_RECLEN(n) ((((n)+1)/2) + 1) -#define HERMES_RECLEN_TO_BYTES(n) (((n)-1) * 2) - -/* Note that for the next two, the count is in 16-bit words, not bytes */ -static inline void hermes_read_words(struct hermes *hw, int off, - void *buf, unsigned count) -{ - off = off << hw->reg_spacing; - ioread16_rep(hw->iobase + off, buf, count); -} - -static inline void hermes_write_bytes(struct hermes *hw, int off, - const char *buf, unsigned count) -{ - off = off << hw->reg_spacing; - iowrite16_rep(hw->iobase + off, buf, count >> 1); - if (unlikely(count & 1)) - iowrite8(buf[count - 1], hw->iobase + off); -} - -static inline void hermes_clear_words(struct hermes *hw, int off, - unsigned count) -{ - unsigned i; - - off = off << hw->reg_spacing; - - for (i = 0; i < count; i++) - iowrite16(0, hw->iobase + off); -} - -#define HERMES_READ_RECORD(hw, bap, rid, buf) \ - (hermes_read_ltv((hw), (bap), (rid), sizeof(*buf), NULL, (buf))) -#define HERMES_WRITE_RECORD(hw, bap, rid, buf) \ - (hermes_write_ltv((hw), (bap), (rid), \ - HERMES_BYTES_TO_RECLEN(sizeof(*buf)), (buf))) - -static inline int hermes_read_wordrec(hermes_t *hw, int bap, u16 rid, u16 *word) -{ - __le16 rec; - int err; - - err = HERMES_READ_RECORD(hw, bap, rid, &rec); - *word = le16_to_cpu(rec); - return err; -} - -static inline int hermes_write_wordrec(hermes_t *hw, int bap, u16 rid, u16 word) -{ - __le16 rec = cpu_to_le16(word); - return HERMES_WRITE_RECORD(hw, bap, rid, &rec); -} - -#endif /* _HERMES_H */ diff --git a/drivers/net/wireless/orinoco/hermes_dld.c b/drivers/net/wireless/orinoco/hermes_dld.c deleted file mode 100644 index a3eefe109df4..000000000000 --- a/drivers/net/wireless/orinoco/hermes_dld.c +++ /dev/null @@ -1,702 +0,0 @@ -/* - * Hermes download helper. - * - * This helper: - * - is capable of writing to the volatile area of the hermes device - * - is currently not capable of writing to non-volatile areas - * - provide helpers to identify and update plugin data - * - is not capable of interpreting a fw image directly. That is up to - * the main card driver. - * - deals with Hermes I devices. It can probably be modified to deal - * with Hermes II devices - * - * Copyright (C) 2007, David Kilroy - * - * Plug data code slightly modified from spectrum_cs driver - * Copyright (C) 2002-2005 Pavel Roskin - * Portions based on information in wl_lkm_718 Agere driver - * COPYRIGHT (C) 2001-2004 by Agere Systems Inc. All Rights Reserved - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - */ - -#include -#include -#include "hermes.h" -#include "hermes_dld.h" - -#define PFX "hermes_dld: " - -/* - * AUX port access. To unlock the AUX port write the access keys to the - * PARAM0-2 registers, then write HERMES_AUX_ENABLE to the HERMES_CONTROL - * register. Then read it and make sure it's HERMES_AUX_ENABLED. - */ -#define HERMES_AUX_ENABLE 0x8000 /* Enable auxiliary port access */ -#define HERMES_AUX_DISABLE 0x4000 /* Disable to auxiliary port access */ -#define HERMES_AUX_ENABLED 0xC000 /* Auxiliary port is open */ -#define HERMES_AUX_DISABLED 0x0000 /* Auxiliary port is closed */ - -#define HERMES_AUX_PW0 0xFE01 -#define HERMES_AUX_PW1 0xDC23 -#define HERMES_AUX_PW2 0xBA45 - -/* HERMES_CMD_DOWNLD */ -#define HERMES_PROGRAM_DISABLE (0x0000 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_ENABLE_VOLATILE (0x0100 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_ENABLE_NON_VOLATILE (0x0200 | HERMES_CMD_DOWNLD) -#define HERMES_PROGRAM_NON_VOLATILE (0x0300 | HERMES_CMD_DOWNLD) - -/* End markers used in dblocks */ -#define PDI_END 0x00000000 /* End of PDA */ -#define BLOCK_END 0xFFFFFFFF /* Last image block */ -#define TEXT_END 0x1A /* End of text header */ - -/* Limit the amout we try to download in a single shot. - * Size is in bytes. - */ -#define MAX_DL_SIZE 1024 -#define LIMIT_PROGRAM_SIZE 0 - -/* - * The following structures have little-endian fields denoted by - * the leading underscore. Don't access them directly - use inline - * functions defined below. - */ - -/* - * The binary image to be downloaded consists of series of data blocks. - * Each block has the following structure. - */ -struct dblock { - __le32 addr; /* adapter address where to write the block */ - __le16 len; /* length of the data only, in bytes */ - char data[0]; /* data to be written */ -} __attribute__ ((packed)); - -/* - * Plug Data References are located in in the image after the last data - * block. They refer to areas in the adapter memory where the plug data - * items with matching ID should be written. - */ -struct pdr { - __le32 id; /* record ID */ - __le32 addr; /* adapter address where to write the data */ - __le32 len; /* expected length of the data, in bytes */ - char next[0]; /* next PDR starts here */ -} __attribute__ ((packed)); - -/* - * Plug Data Items are located in the EEPROM read from the adapter by - * primary firmware. They refer to the device-specific data that should - * be plugged into the secondary firmware. - */ -struct pdi { - __le16 len; /* length of ID and data, in words */ - __le16 id; /* record ID */ - char data[0]; /* plug data */ -} __attribute__ ((packed)); - -/*** FW data block access functions ***/ - -static inline u32 -dblock_addr(const struct dblock *blk) -{ - return le32_to_cpu(blk->addr); -} - -static inline u32 -dblock_len(const struct dblock *blk) -{ - return le16_to_cpu(blk->len); -} - -/*** PDR Access functions ***/ - -static inline u32 -pdr_id(const struct pdr *pdr) -{ - return le32_to_cpu(pdr->id); -} - -static inline u32 -pdr_addr(const struct pdr *pdr) -{ - return le32_to_cpu(pdr->addr); -} - -static inline u32 -pdr_len(const struct pdr *pdr) -{ - return le32_to_cpu(pdr->len); -} - -/*** PDI Access functions ***/ - -static inline u32 -pdi_id(const struct pdi *pdi) -{ - return le16_to_cpu(pdi->id); -} - -/* Return length of the data only, in bytes */ -static inline u32 -pdi_len(const struct pdi *pdi) -{ - return 2 * (le16_to_cpu(pdi->len) - 1); -} - -/*** Hermes AUX control ***/ - -static inline void -hermes_aux_setaddr(hermes_t *hw, u32 addr) -{ - hermes_write_reg(hw, HERMES_AUXPAGE, (u16) (addr >> 7)); - hermes_write_reg(hw, HERMES_AUXOFFSET, (u16) (addr & 0x7F)); -} - -static inline int -hermes_aux_control(hermes_t *hw, int enabled) -{ - int desired_state = enabled ? HERMES_AUX_ENABLED : HERMES_AUX_DISABLED; - int action = enabled ? HERMES_AUX_ENABLE : HERMES_AUX_DISABLE; - int i; - - /* Already open? */ - if (hermes_read_reg(hw, HERMES_CONTROL) == desired_state) - return 0; - - hermes_write_reg(hw, HERMES_PARAM0, HERMES_AUX_PW0); - hermes_write_reg(hw, HERMES_PARAM1, HERMES_AUX_PW1); - hermes_write_reg(hw, HERMES_PARAM2, HERMES_AUX_PW2); - hermes_write_reg(hw, HERMES_CONTROL, action); - - for (i = 0; i < 20; i++) { - udelay(10); - if (hermes_read_reg(hw, HERMES_CONTROL) == - desired_state) - return 0; - } - - return -EBUSY; -} - -/*** Plug Data Functions ***/ - -/* - * Scan PDR for the record with the specified RECORD_ID. - * If it's not found, return NULL. - */ -static const struct pdr * -hermes_find_pdr(const struct pdr *first_pdr, u32 record_id, const void *end) -{ - const struct pdr *pdr = first_pdr; - - end -= sizeof(struct pdr); - - while (((void *) pdr <= end) && - (pdr_id(pdr) != PDI_END)) { - /* - * PDR area is currently not terminated by PDI_END. - * It's followed by CRC records, which have the type - * field where PDR has length. The type can be 0 or 1. - */ - if (pdr_len(pdr) < 2) - return NULL; - - /* If the record ID matches, we are done */ - if (pdr_id(pdr) == record_id) - return pdr; - - pdr = (struct pdr *) pdr->next; - } - return NULL; -} - -/* Scan production data items for a particular entry */ -static const struct pdi * -hermes_find_pdi(const struct pdi *first_pdi, u32 record_id, const void *end) -{ - const struct pdi *pdi = first_pdi; - - end -= sizeof(struct pdi); - - while (((void *) pdi <= end) && - (pdi_id(pdi) != PDI_END)) { - - /* If the record ID matches, we are done */ - if (pdi_id(pdi) == record_id) - return pdi; - - pdi = (struct pdi *) &pdi->data[pdi_len(pdi)]; - } - return NULL; -} - -/* Process one Plug Data Item - find corresponding PDR and plug it */ -static int -hermes_plug_pdi(hermes_t *hw, const struct pdr *first_pdr, - const struct pdi *pdi, const void *pdr_end) -{ - const struct pdr *pdr; - - /* Find the PDR corresponding to this PDI */ - pdr = hermes_find_pdr(first_pdr, pdi_id(pdi), pdr_end); - - /* No match is found, safe to ignore */ - if (!pdr) - return 0; - - /* Lengths of the data in PDI and PDR must match */ - if (pdi_len(pdi) != pdr_len(pdr)) - return -EINVAL; - - /* do the actual plugging */ - hermes_aux_setaddr(hw, pdr_addr(pdr)); - hermes_write_bytes(hw, HERMES_AUXDATA, pdi->data, pdi_len(pdi)); - - return 0; -} - -/* Read PDA from the adapter */ -int hermes_read_pda(hermes_t *hw, - __le16 *pda, - u32 pda_addr, - u16 pda_len, - int use_eeprom) /* can we get this into hw? */ -{ - int ret; - u16 pda_size; - u16 data_len = pda_len; - __le16 *data = pda; - - if (use_eeprom) { - /* PDA of spectrum symbol is in eeprom */ - - /* Issue command to read EEPROM */ - ret = hermes_docmd_wait(hw, HERMES_CMD_READMIF, 0, NULL); - if (ret) - return ret; - } else { - /* wl_lkm does not include PDA size in the PDA area. - * We will pad the information into pda, so other routines - * don't have to be modified */ - pda[0] = cpu_to_le16(pda_len - 2); - /* Includes CFG_PROD_DATA but not itself */ - pda[1] = cpu_to_le16(0x0800); /* CFG_PROD_DATA */ - data_len = pda_len - 4; - data = pda + 2; - } - - /* Open auxiliary port */ - ret = hermes_aux_control(hw, 1); - pr_debug(PFX "AUX enable returned %d\n", ret); - if (ret) - return ret; - - /* read PDA from EEPROM */ - hermes_aux_setaddr(hw, pda_addr); - hermes_read_words(hw, HERMES_AUXDATA, data, data_len / 2); - - /* Close aux port */ - ret = hermes_aux_control(hw, 0); - pr_debug(PFX "AUX disable returned %d\n", ret); - - /* Check PDA length */ - pda_size = le16_to_cpu(pda[0]); - pr_debug(PFX "Actual PDA length %d, Max allowed %d\n", - pda_size, pda_len); - if (pda_size > pda_len) - return -EINVAL; - - return 0; -} - -/* Parse PDA and write the records into the adapter - * - * Attempt to write every records that is in the specified pda - * which also has a valid production data record for the firmware. - */ -int hermes_apply_pda(hermes_t *hw, - const char *first_pdr, - const void *pdr_end, - const __le16 *pda, - const void *pda_end) -{ - int ret; - const struct pdi *pdi; - const struct pdr *pdr; - - pdr = (const struct pdr *) first_pdr; - pda_end -= sizeof(struct pdi); - - /* Go through every PDI and plug them into the adapter */ - pdi = (const struct pdi *) (pda + 2); - while (((void *) pdi <= pda_end) && - (pdi_id(pdi) != PDI_END)) { - ret = hermes_plug_pdi(hw, pdr, pdi, pdr_end); - if (ret) - return ret; - - /* Increment to the next PDI */ - pdi = (const struct pdi *) &pdi->data[pdi_len(pdi)]; - } - return 0; -} - -/* Identify the total number of bytes in all blocks - * including the header data. - */ -size_t -hermes_blocks_length(const char *first_block, const void *end) -{ - const struct dblock *blk = (const struct dblock *) first_block; - int total_len = 0; - int len; - - end -= sizeof(*blk); - - /* Skip all blocks to locate Plug Data References - * (Spectrum CS) */ - while (((void *) blk <= end) && - (dblock_addr(blk) != BLOCK_END)) { - len = dblock_len(blk); - total_len += sizeof(*blk) + len; - blk = (struct dblock *) &blk->data[len]; - } - - return total_len; -} - -/*** Hermes programming ***/ - -/* About to start programming data (Hermes I) - * offset is the entry point - * - * Spectrum_cs' Symbol fw does not require this - * wl_lkm Agere fw does - * Don't know about intersil - */ -int hermesi_program_init(hermes_t *hw, u32 offset) -{ - int err; - - /* Disable interrupts?*/ - /*hw->inten = 0x0;*/ - /*hermes_write_regn(hw, INTEN, 0);*/ - /*hermes_set_irqmask(hw, 0);*/ - - /* Acknowledge any outstanding command */ - hermes_write_regn(hw, EVACK, 0xFFFF); - - /* Using doicmd_wait rather than docmd_wait */ - err = hermes_doicmd_wait(hw, - 0x0100 | HERMES_CMD_INIT, - 0, 0, 0, NULL); - if (err) - return err; - - err = hermes_doicmd_wait(hw, - 0x0000 | HERMES_CMD_INIT, - 0, 0, 0, NULL); - if (err) - return err; - - err = hermes_aux_control(hw, 1); - pr_debug(PFX "AUX enable returned %d\n", err); - - if (err) - return err; - - pr_debug(KERN_DEBUG PFX "Enabling volatile, EP 0x%08x\n", offset); - err = hermes_doicmd_wait(hw, - HERMES_PROGRAM_ENABLE_VOLATILE, - offset & 0xFFFFu, - offset >> 16, - 0, - NULL); - pr_debug(PFX "PROGRAM_ENABLE returned %d\n", err); - - return err; -} - -/* Done programming data (Hermes I) - * - * Spectrum_cs' Symbol fw does not require this - * wl_lkm Agere fw does - * Don't know about intersil - */ -int hermesi_program_end(hermes_t *hw) -{ - struct hermes_response resp; - int rc = 0; - int err; - - rc = hermes_docmd_wait(hw, HERMES_PROGRAM_DISABLE, 0, &resp); - - pr_debug(PFX "PROGRAM_DISABLE returned %d, " - "r0 0x%04x, r1 0x%04x, r2 0x%04x\n", - rc, resp.resp0, resp.resp1, resp.resp2); - - if ((rc == 0) && - ((resp.status & HERMES_STATUS_CMDCODE) != HERMES_CMD_DOWNLD)) - rc = -EIO; - - err = hermes_aux_control(hw, 0); - pr_debug(PFX "AUX disable returned %d\n", err); - - /* Acknowledge any outstanding command */ - hermes_write_regn(hw, EVACK, 0xFFFF); - - /* Reinitialise, ignoring return */ - (void) hermes_doicmd_wait(hw, 0x0000 | HERMES_CMD_INIT, - 0, 0, 0, NULL); - - return rc ? rc : err; -} - -/* Program the data blocks */ -int hermes_program(hermes_t *hw, const char *first_block, const void *end) -{ - const struct dblock *blk; - u32 blkaddr; - u32 blklen; -#if LIMIT_PROGRAM_SIZE - u32 addr; - u32 len; -#endif - - blk = (const struct dblock *) first_block; - - if ((void *) blk > (end - sizeof(*blk))) - return -EIO; - - blkaddr = dblock_addr(blk); - blklen = dblock_len(blk); - - while ((blkaddr != BLOCK_END) && - (((void *) blk + blklen) <= end)) { - pr_debug(PFX "Programming block of length %d " - "to address 0x%08x\n", blklen, blkaddr); - -#if !LIMIT_PROGRAM_SIZE - /* wl_lkm driver splits this into writes of 2000 bytes */ - hermes_aux_setaddr(hw, blkaddr); - hermes_write_bytes(hw, HERMES_AUXDATA, blk->data, - blklen); -#else - len = (blklen < MAX_DL_SIZE) ? blklen : MAX_DL_SIZE; - addr = blkaddr; - - while (addr < (blkaddr + blklen)) { - pr_debug(PFX "Programming subblock of length %d " - "to address 0x%08x. Data @ %p\n", - len, addr, &blk->data[addr - blkaddr]); - - hermes_aux_setaddr(hw, addr); - hermes_write_bytes(hw, HERMES_AUXDATA, - &blk->data[addr - blkaddr], - len); - - addr += len; - len = ((blkaddr + blklen - addr) < MAX_DL_SIZE) ? - (blkaddr + blklen - addr) : MAX_DL_SIZE; - } -#endif - blk = (const struct dblock *) &blk->data[blklen]; - - if ((void *) blk > (end - sizeof(*blk))) - return -EIO; - - blkaddr = dblock_addr(blk); - blklen = dblock_len(blk); - } - return 0; -} - -/*** Default plugging data for Hermes I ***/ -/* Values from wl_lkm_718/hcf/dhf.c */ - -#define DEFINE_DEFAULT_PDR(pid, length, data) \ -static const struct { \ - __le16 len; \ - __le16 id; \ - u8 val[length]; \ -} __attribute__ ((packed)) default_pdr_data_##pid = { \ - cpu_to_le16((sizeof(default_pdr_data_##pid)/ \ - sizeof(__le16)) - 1), \ - cpu_to_le16(pid), \ - data \ -} - -#define DEFAULT_PDR(pid) default_pdr_data_##pid - -/* HWIF Compatiblity */ -DEFINE_DEFAULT_PDR(0x0005, 10, "\x00\x00\x06\x00\x01\x00\x01\x00\x01\x00"); - -/* PPPPSign */ -DEFINE_DEFAULT_PDR(0x0108, 4, "\x00\x00\x00\x00"); - -/* PPPPProf */ -DEFINE_DEFAULT_PDR(0x0109, 10, "\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00"); - -/* Antenna diversity */ -DEFINE_DEFAULT_PDR(0x0150, 2, "\x00\x3F"); - -/* Modem VCO band Set-up */ -DEFINE_DEFAULT_PDR(0x0160, 28, - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00"); - -/* Modem Rx Gain Table Values */ -DEFINE_DEFAULT_PDR(0x0161, 256, - "\x3F\x01\x3F\01\x3F\x01\x3F\x01" - "\x3F\x01\x3F\01\x3F\x01\x3F\x01" - "\x3F\x01\x3F\01\x3F\x01\x3F\x01" - "\x3F\x01\x3F\01\x3F\x01\x3F\x01" - "\x3F\x01\x3E\01\x3E\x01\x3D\x01" - "\x3D\x01\x3C\01\x3C\x01\x3B\x01" - "\x3B\x01\x3A\01\x3A\x01\x39\x01" - "\x39\x01\x38\01\x38\x01\x37\x01" - "\x37\x01\x36\01\x36\x01\x35\x01" - "\x35\x01\x34\01\x34\x01\x33\x01" - "\x33\x01\x32\x01\x32\x01\x31\x01" - "\x31\x01\x30\x01\x30\x01\x7B\x01" - "\x7B\x01\x7A\x01\x7A\x01\x79\x01" - "\x79\x01\x78\x01\x78\x01\x77\x01" - "\x77\x01\x76\x01\x76\x01\x75\x01" - "\x75\x01\x74\x01\x74\x01\x73\x01" - "\x73\x01\x72\x01\x72\x01\x71\x01" - "\x71\x01\x70\x01\x70\x01\x68\x01" - "\x68\x01\x67\x01\x67\x01\x66\x01" - "\x66\x01\x65\x01\x65\x01\x57\x01" - "\x57\x01\x56\x01\x56\x01\x55\x01" - "\x55\x01\x54\x01\x54\x01\x53\x01" - "\x53\x01\x52\x01\x52\x01\x51\x01" - "\x51\x01\x50\x01\x50\x01\x48\x01" - "\x48\x01\x47\x01\x47\x01\x46\x01" - "\x46\x01\x45\x01\x45\x01\x44\x01" - "\x44\x01\x43\x01\x43\x01\x42\x01" - "\x42\x01\x41\x01\x41\x01\x40\x01" - "\x40\x01\x40\x01\x40\x01\x40\x01" - "\x40\x01\x40\x01\x40\x01\x40\x01" - "\x40\x01\x40\x01\x40\x01\x40\x01" - "\x40\x01\x40\x01\x40\x01\x40\x01"); - -/* Write PDA according to certain rules. - * - * For every production data record, look for a previous setting in - * the pda, and use that. - * - * For certain records, use defaults if they are not found in pda. - */ -int hermes_apply_pda_with_defaults(hermes_t *hw, - const char *first_pdr, - const void *pdr_end, - const __le16 *pda, - const void *pda_end) -{ - const struct pdr *pdr = (const struct pdr *) first_pdr; - const struct pdi *first_pdi = (const struct pdi *) &pda[2]; - const struct pdi *pdi; - const struct pdi *default_pdi = NULL; - const struct pdi *outdoor_pdi; - int record_id; - - pdr_end -= sizeof(struct pdr); - - while (((void *) pdr <= pdr_end) && - (pdr_id(pdr) != PDI_END)) { - /* - * For spectrum_cs firmwares, - * PDR area is currently not terminated by PDI_END. - * It's followed by CRC records, which have the type - * field where PDR has length. The type can be 0 or 1. - */ - if (pdr_len(pdr) < 2) - break; - record_id = pdr_id(pdr); - - pdi = hermes_find_pdi(first_pdi, record_id, pda_end); - if (pdi) - pr_debug(PFX "Found record 0x%04x at %p\n", - record_id, pdi); - - switch (record_id) { - case 0x110: /* Modem REFDAC values */ - case 0x120: /* Modem VGDAC values */ - outdoor_pdi = hermes_find_pdi(first_pdi, record_id + 1, - pda_end); - default_pdi = NULL; - if (outdoor_pdi) { - pdi = outdoor_pdi; - pr_debug(PFX - "Using outdoor record 0x%04x at %p\n", - record_id + 1, pdi); - } - break; - case 0x5: /* HWIF Compatiblity */ - default_pdi = (struct pdi *) &DEFAULT_PDR(0x0005); - break; - case 0x108: /* PPPPSign */ - default_pdi = (struct pdi *) &DEFAULT_PDR(0x0108); - break; - case 0x109: /* PPPPProf */ - default_pdi = (struct pdi *) &DEFAULT_PDR(0x0109); - break; - case 0x150: /* Antenna diversity */ - default_pdi = (struct pdi *) &DEFAULT_PDR(0x0150); - break; - case 0x160: /* Modem VCO band Set-up */ - default_pdi = (struct pdi *) &DEFAULT_PDR(0x0160); - break; - case 0x161: /* Modem Rx Gain Table Values */ - default_pdi = (struct pdi *) &DEFAULT_PDR(0x0161); - break; - default: - default_pdi = NULL; - break; - } - if (!pdi && default_pdi) { - /* Use default */ - pdi = default_pdi; - pr_debug(PFX "Using default record 0x%04x at %p\n", - record_id, pdi); - } - - if (pdi) { - /* Lengths of the data in PDI and PDR must match */ - if ((pdi_len(pdi) == pdr_len(pdr)) && - ((void *) pdi->data + pdi_len(pdi) < pda_end)) { - /* do the actual plugging */ - hermes_aux_setaddr(hw, pdr_addr(pdr)); - hermes_write_bytes(hw, HERMES_AUXDATA, - pdi->data, pdi_len(pdi)); - } - } - - pdr++; - } - return 0; -} diff --git a/drivers/net/wireless/orinoco/hermes_dld.h b/drivers/net/wireless/orinoco/hermes_dld.h deleted file mode 100644 index 583a5bcf9175..000000000000 --- a/drivers/net/wireless/orinoco/hermes_dld.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2007, David Kilroy - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - */ -#ifndef _HERMES_DLD_H -#define _HERMES_DLD_H - -#include "hermes.h" - -int hermesi_program_init(hermes_t *hw, u32 offset); -int hermesi_program_end(hermes_t *hw); -int hermes_program(hermes_t *hw, const char *first_block, const void *end); - -int hermes_read_pda(hermes_t *hw, - __le16 *pda, - u32 pda_addr, - u16 pda_len, - int use_eeprom); -int hermes_apply_pda(hermes_t *hw, - const char *first_pdr, - const void *pdr_end, - const __le16 *pda, - const void *pda_end); -int hermes_apply_pda_with_defaults(hermes_t *hw, - const char *first_pdr, - const void *pdr_end, - const __le16 *pda, - const void *pda_end); - -size_t hermes_blocks_length(const char *first_block, const void *end); - -#endif /* _HERMES_DLD_H */ diff --git a/drivers/net/wireless/orinoco/hermes_rid.h b/drivers/net/wireless/orinoco/hermes_rid.h deleted file mode 100644 index 42eb67dea1df..000000000000 --- a/drivers/net/wireless/orinoco/hermes_rid.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef _HERMES_RID_H -#define _HERMES_RID_H - -/* - * Configuration RIDs - */ -#define HERMES_RID_CNFPORTTYPE 0xFC00 -#define HERMES_RID_CNFOWNMACADDR 0xFC01 -#define HERMES_RID_CNFDESIREDSSID 0xFC02 -#define HERMES_RID_CNFOWNCHANNEL 0xFC03 -#define HERMES_RID_CNFOWNSSID 0xFC04 -#define HERMES_RID_CNFOWNATIMWINDOW 0xFC05 -#define HERMES_RID_CNFSYSTEMSCALE 0xFC06 -#define HERMES_RID_CNFMAXDATALEN 0xFC07 -#define HERMES_RID_CNFWDSADDRESS 0xFC08 -#define HERMES_RID_CNFPMENABLED 0xFC09 -#define HERMES_RID_CNFPMEPS 0xFC0A -#define HERMES_RID_CNFMULTICASTRECEIVE 0xFC0B -#define HERMES_RID_CNFMAXSLEEPDURATION 0xFC0C -#define HERMES_RID_CNFPMHOLDOVERDURATION 0xFC0D -#define HERMES_RID_CNFOWNNAME 0xFC0E -#define HERMES_RID_CNFOWNDTIMPERIOD 0xFC10 -#define HERMES_RID_CNFWDSADDRESS1 0xFC11 -#define HERMES_RID_CNFWDSADDRESS2 0xFC12 -#define HERMES_RID_CNFWDSADDRESS3 0xFC13 -#define HERMES_RID_CNFWDSADDRESS4 0xFC14 -#define HERMES_RID_CNFWDSADDRESS5 0xFC15 -#define HERMES_RID_CNFWDSADDRESS6 0xFC16 -#define HERMES_RID_CNFMULTICASTPMBUFFERING 0xFC17 -#define HERMES_RID_CNFWEPENABLED_AGERE 0xFC20 -#define HERMES_RID_CNFAUTHENTICATION_AGERE 0xFC21 -#define HERMES_RID_CNFMANDATORYBSSID_SYMBOL 0xFC21 -#define HERMES_RID_CNFDROPUNENCRYPTED 0xFC22 -#define HERMES_RID_CNFWEPDEFAULTKEYID 0xFC23 -#define HERMES_RID_CNFDEFAULTKEY0 0xFC24 -#define HERMES_RID_CNFDEFAULTKEY1 0xFC25 -#define HERMES_RID_CNFMWOROBUST_AGERE 0xFC25 -#define HERMES_RID_CNFDEFAULTKEY2 0xFC26 -#define HERMES_RID_CNFDEFAULTKEY3 0xFC27 -#define HERMES_RID_CNFWEPFLAGS_INTERSIL 0xFC28 -#define HERMES_RID_CNFWEPKEYMAPPINGTABLE 0xFC29 -#define HERMES_RID_CNFAUTHENTICATION 0xFC2A -#define HERMES_RID_CNFMAXASSOCSTA 0xFC2B -#define HERMES_RID_CNFKEYLENGTH_SYMBOL 0xFC2B -#define HERMES_RID_CNFTXCONTROL 0xFC2C -#define HERMES_RID_CNFROAMINGMODE 0xFC2D -#define HERMES_RID_CNFHOSTAUTHENTICATION 0xFC2E -#define HERMES_RID_CNFRCVCRCERROR 0xFC30 -#define HERMES_RID_CNFMMLIFE 0xFC31 -#define HERMES_RID_CNFALTRETRYCOUNT 0xFC32 -#define HERMES_RID_CNFBEACONINT 0xFC33 -#define HERMES_RID_CNFAPPCFINFO 0xFC34 -#define HERMES_RID_CNFSTAPCFINFO 0xFC35 -#define HERMES_RID_CNFPRIORITYQUSAGE 0xFC37 -#define HERMES_RID_CNFTIMCTRL 0xFC40 -#define HERMES_RID_CNFTHIRTY2TALLY 0xFC42 -#define HERMES_RID_CNFENHSECURITY 0xFC43 -#define HERMES_RID_CNFGROUPADDRESSES 0xFC80 -#define HERMES_RID_CNFCREATEIBSS 0xFC81 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD 0xFC82 -#define HERMES_RID_CNFRTSTHRESHOLD 0xFC83 -#define HERMES_RID_CNFTXRATECONTROL 0xFC84 -#define HERMES_RID_CNFPROMISCUOUSMODE 0xFC85 -#define HERMES_RID_CNFBASICRATES_SYMBOL 0xFC8A -#define HERMES_RID_CNFPREAMBLE_SYMBOL 0xFC8C -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD0 0xFC90 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD1 0xFC91 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD2 0xFC92 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD3 0xFC93 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD4 0xFC94 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD5 0xFC95 -#define HERMES_RID_CNFFRAGMENTATIONTHRESHOLD6 0xFC96 -#define HERMES_RID_CNFRTSTHRESHOLD0 0xFC97 -#define HERMES_RID_CNFRTSTHRESHOLD1 0xFC98 -#define HERMES_RID_CNFRTSTHRESHOLD2 0xFC99 -#define HERMES_RID_CNFRTSTHRESHOLD3 0xFC9A -#define HERMES_RID_CNFRTSTHRESHOLD4 0xFC9B -#define HERMES_RID_CNFRTSTHRESHOLD5 0xFC9C -#define HERMES_RID_CNFRTSTHRESHOLD6 0xFC9D -#define HERMES_RID_CNFHOSTSCAN_SYMBOL 0xFCAB -#define HERMES_RID_CNFSHORTPREAMBLE 0xFCB0 -#define HERMES_RID_CNFWEPKEYS_AGERE 0xFCB0 -#define HERMES_RID_CNFEXCLUDELONGPREAMBLE 0xFCB1 -#define HERMES_RID_CNFTXKEY_AGERE 0xFCB1 -#define HERMES_RID_CNFAUTHENTICATIONRSPTO 0xFCB2 -#define HERMES_RID_CNFSCANSSID_AGERE 0xFCB2 -#define HERMES_RID_CNFBASICRATES 0xFCB3 -#define HERMES_RID_CNFSUPPORTEDRATES 0xFCB4 -#define HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE 0xFCB4 -#define HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE 0xFCB5 -#define HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE 0xFCB6 -#define HERMES_RID_CNFADDMAPPEDTKIPKEY_AGERE 0xFCB7 -#define HERMES_RID_CNFREMMAPPEDTKIPKEY_AGERE 0xFCB8 -#define HERMES_RID_CNFSETWPACAPABILITIES_AGERE 0xFCB9 -#define HERMES_RID_CNFCACHEDPMKADDRESS 0xFCBA -#define HERMES_RID_CNFREMOVEPMKADDRESS 0xFCBB -#define HERMES_RID_CNFSCANCHANNELS2GHZ 0xFCC2 -#define HERMES_RID_CNFDISASSOCIATE 0xFCC8 -#define HERMES_RID_CNFTICKTIME 0xFCE0 -#define HERMES_RID_CNFSCANREQUEST 0xFCE1 -#define HERMES_RID_CNFJOINREQUEST 0xFCE2 -#define HERMES_RID_CNFAUTHENTICATESTATION 0xFCE3 -#define HERMES_RID_CNFCHANNELINFOREQUEST 0xFCE4 -#define HERMES_RID_CNFHOSTSCAN 0xFCE5 - -/* - * Information RIDs - */ -#define HERMES_RID_MAXLOADTIME 0xFD00 -#define HERMES_RID_DOWNLOADBUFFER 0xFD01 -#define HERMES_RID_PRIID 0xFD02 -#define HERMES_RID_PRISUPRANGE 0xFD03 -#define HERMES_RID_CFIACTRANGES 0xFD04 -#define HERMES_RID_NICSERNUM 0xFD0A -#define HERMES_RID_NICID 0xFD0B -#define HERMES_RID_MFISUPRANGE 0xFD0C -#define HERMES_RID_CFISUPRANGE 0xFD0D -#define HERMES_RID_CHANNELLIST 0xFD10 -#define HERMES_RID_REGULATORYDOMAINS 0xFD11 -#define HERMES_RID_TEMPTYPE 0xFD12 -#define HERMES_RID_CIS 0xFD13 -#define HERMES_RID_STAID 0xFD20 -#define HERMES_RID_STASUPRANGE 0xFD21 -#define HERMES_RID_MFIACTRANGES 0xFD22 -#define HERMES_RID_CFIACTRANGES2 0xFD23 -#define HERMES_RID_SECONDARYVERSION_SYMBOL 0xFD24 -#define HERMES_RID_PORTSTATUS 0xFD40 -#define HERMES_RID_CURRENTSSID 0xFD41 -#define HERMES_RID_CURRENTBSSID 0xFD42 -#define HERMES_RID_COMMSQUALITY 0xFD43 -#define HERMES_RID_CURRENTTXRATE 0xFD44 -#define HERMES_RID_CURRENTBEACONINTERVAL 0xFD45 -#define HERMES_RID_CURRENTSCALETHRESHOLDS 0xFD46 -#define HERMES_RID_PROTOCOLRSPTIME 0xFD47 -#define HERMES_RID_SHORTRETRYLIMIT 0xFD48 -#define HERMES_RID_LONGRETRYLIMIT 0xFD49 -#define HERMES_RID_MAXTRANSMITLIFETIME 0xFD4A -#define HERMES_RID_MAXRECEIVELIFETIME 0xFD4B -#define HERMES_RID_CFPOLLABLE 0xFD4C -#define HERMES_RID_AUTHENTICATIONALGORITHMS 0xFD4D -#define HERMES_RID_PRIVACYOPTIONIMPLEMENTED 0xFD4F -#define HERMES_RID_DBMCOMMSQUALITY_INTERSIL 0xFD51 -#define HERMES_RID_CURRENTTXRATE1 0xFD80 -#define HERMES_RID_CURRENTTXRATE2 0xFD81 -#define HERMES_RID_CURRENTTXRATE3 0xFD82 -#define HERMES_RID_CURRENTTXRATE4 0xFD83 -#define HERMES_RID_CURRENTTXRATE5 0xFD84 -#define HERMES_RID_CURRENTTXRATE6 0xFD85 -#define HERMES_RID_OWNMACADDR 0xFD86 -#define HERMES_RID_SCANRESULTSTABLE 0xFD88 -#define HERMES_RID_CURRENT_COUNTRY_INFO 0xFD89 -#define HERMES_RID_CURRENT_WPA_IE 0xFD8A -#define HERMES_RID_CURRENT_TKIP_IV 0xFD8B -#define HERMES_RID_CURRENT_ASSOC_REQ_INFO 0xFD8C -#define HERMES_RID_CURRENT_ASSOC_RESP_INFO 0xFD8D -#define HERMES_RID_TXQUEUEEMPTY 0xFD91 -#define HERMES_RID_PHYTYPE 0xFDC0 -#define HERMES_RID_CURRENTCHANNEL 0xFDC1 -#define HERMES_RID_CURRENTPOWERSTATE 0xFDC2 -#define HERMES_RID_CCAMODE 0xFDC3 -#define HERMES_RID_SUPPORTEDDATARATES 0xFDC6 -#define HERMES_RID_BUILDSEQ 0xFFFE -#define HERMES_RID_FWID 0xFFFF - -#endif diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c deleted file mode 100644 index 359652d35e63..000000000000 --- a/drivers/net/wireless/orinoco/hw.c +++ /dev/null @@ -1,1312 +0,0 @@ -/* Encapsulate basic setting changes and retrieval on Hermes hardware - * - * See copyright notice in main.c - */ -#include -#include -#include -#include -#include -#include -#include "hermes.h" -#include "hermes_rid.h" -#include "orinoco.h" - -#include "hw.h" - -#define SYMBOL_MAX_VER_LEN (14) - -/* Symbol firmware has a bug allocating buffers larger than this */ -#define TX_NICBUF_SIZE_BUG 1585 - -/********************************************************************/ -/* Data tables */ -/********************************************************************/ - -/* This tables gives the actual meanings of the bitrate IDs returned - * by the firmware. */ -static const struct { - int bitrate; /* in 100s of kilobits */ - int automatic; - u16 agere_txratectrl; - u16 intersil_txratectrl; -} bitrate_table[] = { - {110, 1, 3, 15}, /* Entry 0 is the default */ - {10, 0, 1, 1}, - {10, 1, 1, 1}, - {20, 0, 2, 2}, - {20, 1, 6, 3}, - {55, 0, 4, 4}, - {55, 1, 7, 7}, - {110, 0, 5, 8}, -}; -#define BITRATE_TABLE_SIZE ARRAY_SIZE(bitrate_table) - -/* Firmware version encoding */ -struct comp_id { - u16 id, variant, major, minor; -} __attribute__ ((packed)); - -static inline fwtype_t determine_firmware_type(struct comp_id *nic_id) -{ - if (nic_id->id < 0x8000) - return FIRMWARE_TYPE_AGERE; - else if (nic_id->id == 0x8000 && nic_id->major == 0) - return FIRMWARE_TYPE_SYMBOL; - else - return FIRMWARE_TYPE_INTERSIL; -} - -/* Set priv->firmware type, determine firmware properties - * This function can be called before we have registerred with netdev, - * so all errors go out with dev_* rather than printk - */ -int determine_fw_capabilities(struct orinoco_private *priv) -{ - struct device *dev = priv->dev; - hermes_t *hw = &priv->hw; - int err; - struct comp_id nic_id, sta_id; - unsigned int firmver; - char tmp[SYMBOL_MAX_VER_LEN+1] __attribute__((aligned(2))); - - /* Get the hardware version */ - err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_NICID, &nic_id); - if (err) { - dev_err(dev, "Cannot read hardware identity: error %d\n", - err); - return err; - } - - le16_to_cpus(&nic_id.id); - le16_to_cpus(&nic_id.variant); - le16_to_cpus(&nic_id.major); - le16_to_cpus(&nic_id.minor); - dev_info(dev, "Hardware identity %04x:%04x:%04x:%04x\n", - nic_id.id, nic_id.variant, nic_id.major, nic_id.minor); - - priv->firmware_type = determine_firmware_type(&nic_id); - - /* Get the firmware version */ - err = HERMES_READ_RECORD(hw, USER_BAP, HERMES_RID_STAID, &sta_id); - if (err) { - dev_err(dev, "Cannot read station identity: error %d\n", - err); - return err; - } - - le16_to_cpus(&sta_id.id); - le16_to_cpus(&sta_id.variant); - le16_to_cpus(&sta_id.major); - le16_to_cpus(&sta_id.minor); - dev_info(dev, "Station identity %04x:%04x:%04x:%04x\n", - sta_id.id, sta_id.variant, sta_id.major, sta_id.minor); - - switch (sta_id.id) { - case 0x15: - dev_err(dev, "Primary firmware is active\n"); - return -ENODEV; - case 0x14b: - dev_err(dev, "Tertiary firmware is active\n"); - return -ENODEV; - case 0x1f: /* Intersil, Agere, Symbol Spectrum24 */ - case 0x21: /* Symbol Spectrum24 Trilogy */ - break; - default: - dev_notice(dev, "Unknown station ID, please report\n"); - break; - } - - /* Default capabilities */ - priv->has_sensitivity = 1; - priv->has_mwo = 0; - priv->has_preamble = 0; - priv->has_port3 = 1; - priv->has_ibss = 1; - priv->has_wep = 0; - priv->has_big_wep = 0; - priv->has_alt_txcntl = 0; - priv->has_ext_scan = 0; - priv->has_wpa = 0; - priv->do_fw_download = 0; - - /* Determine capabilities from the firmware version */ - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - /* Lucent Wavelan IEEE, Lucent Orinoco, Cabletron RoamAbout, - ELSA, Melco, HP, IBM, Dell 1150, Compaq 110/210 */ - snprintf(priv->fw_name, sizeof(priv->fw_name) - 1, - "Lucent/Agere %d.%02d", sta_id.major, sta_id.minor); - - firmver = ((unsigned long)sta_id.major << 16) | sta_id.minor; - - priv->has_ibss = (firmver >= 0x60006); - priv->has_wep = (firmver >= 0x40020); - priv->has_big_wep = 1; /* FIXME: this is wrong - how do we tell - Gold cards from the others? */ - priv->has_mwo = (firmver >= 0x60000); - priv->has_pm = (firmver >= 0x40020); /* Don't work in 7.52 ? */ - priv->ibss_port = 1; - priv->has_hostscan = (firmver >= 0x8000a); - priv->do_fw_download = 1; - priv->broken_monitor = (firmver >= 0x80000); - priv->has_alt_txcntl = (firmver >= 0x90000); /* All 9.x ? */ - priv->has_ext_scan = (firmver >= 0x90000); /* All 9.x ? */ - priv->has_wpa = (firmver >= 0x9002a); - /* Tested with Agere firmware : - * 1.16 ; 4.08 ; 4.52 ; 6.04 ; 6.16 ; 7.28 => Jean II - * Tested CableTron firmware : 4.32 => Anton */ - break; - case FIRMWARE_TYPE_SYMBOL: - /* Symbol , 3Com AirConnect, Intel, Ericsson WLAN */ - /* Intel MAC : 00:02:B3:* */ - /* 3Com MAC : 00:50:DA:* */ - memset(tmp, 0, sizeof(tmp)); - /* Get the Symbol firmware version */ - err = hermes_read_ltv(hw, USER_BAP, - HERMES_RID_SECONDARYVERSION_SYMBOL, - SYMBOL_MAX_VER_LEN, NULL, &tmp); - if (err) { - dev_warn(dev, "Error %d reading Symbol firmware info. " - "Wildly guessing capabilities...\n", err); - firmver = 0; - tmp[0] = '\0'; - } else { - /* The firmware revision is a string, the format is - * something like : "V2.20-01". - * Quick and dirty parsing... - Jean II - */ - firmver = ((tmp[1] - '0') << 16) - | ((tmp[3] - '0') << 12) - | ((tmp[4] - '0') << 8) - | ((tmp[6] - '0') << 4) - | (tmp[7] - '0'); - - tmp[SYMBOL_MAX_VER_LEN] = '\0'; - } - - snprintf(priv->fw_name, sizeof(priv->fw_name) - 1, - "Symbol %s", tmp); - - priv->has_ibss = (firmver >= 0x20000); - priv->has_wep = (firmver >= 0x15012); - priv->has_big_wep = (firmver >= 0x20000); - priv->has_pm = (firmver >= 0x20000 && firmver < 0x22000) || - (firmver >= 0x29000 && firmver < 0x30000) || - firmver >= 0x31000; - priv->has_preamble = (firmver >= 0x20000); - priv->ibss_port = 4; - - /* Symbol firmware is found on various cards, but - * there has been no attempt to check firmware - * download on non-spectrum_cs based cards. - * - * Given that the Agere firmware download works - * differently, we should avoid doing a firmware - * download with the Symbol algorithm on non-spectrum - * cards. - * - * For now we can identify a spectrum_cs based card - * because it has a firmware reset function. - */ - priv->do_fw_download = (priv->stop_fw != NULL); - - priv->broken_disableport = (firmver == 0x25013) || - (firmver >= 0x30000 && firmver <= 0x31000); - priv->has_hostscan = (firmver >= 0x31001) || - (firmver >= 0x29057 && firmver < 0x30000); - /* Tested with Intel firmware : 0x20015 => Jean II */ - /* Tested with 3Com firmware : 0x15012 & 0x22001 => Jean II */ - break; - case FIRMWARE_TYPE_INTERSIL: - /* D-Link, Linksys, Adtron, ZoomAir, and many others... - * Samsung, Compaq 100/200 and Proxim are slightly - * different and less well tested */ - /* D-Link MAC : 00:40:05:* */ - /* Addtron MAC : 00:90:D1:* */ - snprintf(priv->fw_name, sizeof(priv->fw_name) - 1, - "Intersil %d.%d.%d", sta_id.major, sta_id.minor, - sta_id.variant); - - firmver = ((unsigned long)sta_id.major << 16) | - ((unsigned long)sta_id.minor << 8) | sta_id.variant; - - priv->has_ibss = (firmver >= 0x000700); /* FIXME */ - priv->has_big_wep = priv->has_wep = (firmver >= 0x000800); - priv->has_pm = (firmver >= 0x000700); - priv->has_hostscan = (firmver >= 0x010301); - - if (firmver >= 0x000800) - priv->ibss_port = 0; - else { - dev_notice(dev, "Intersil firmware earlier than v0.8.x" - " - several features not supported\n"); - priv->ibss_port = 1; - } - break; - } - dev_info(dev, "Firmware determined as %s\n", priv->fw_name); - - return 0; -} - -/* Read settings from EEPROM into our private structure. - * MAC address gets dropped into callers buffer - * Can be called before netdev registration. - */ -int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr) -{ - struct device *dev = priv->dev; - struct hermes_idstring nickbuf; - hermes_t *hw = &priv->hw; - int len; - int err; - u16 reclen; - - /* Get the MAC address */ - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, - ETH_ALEN, NULL, dev_addr); - if (err) { - dev_warn(dev, "Failed to read MAC address!\n"); - goto out; - } - - dev_dbg(dev, "MAC address %pM\n", dev_addr); - - /* Get the station name */ - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, - sizeof(nickbuf), &reclen, &nickbuf); - if (err) { - dev_err(dev, "failed to read station name\n"); - goto out; - } - if (nickbuf.len) - len = min(IW_ESSID_MAX_SIZE, (int)le16_to_cpu(nickbuf.len)); - else - len = min(IW_ESSID_MAX_SIZE, 2 * reclen); - memcpy(priv->nick, &nickbuf.val, len); - priv->nick[len] = '\0'; - - dev_dbg(dev, "Station name \"%s\"\n", priv->nick); - - /* Get allowed channels */ - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CHANNELLIST, - &priv->channel_mask); - if (err) { - dev_err(dev, "Failed to read channel list!\n"); - goto out; - } - - /* Get initial AP density */ - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFSYSTEMSCALE, - &priv->ap_density); - if (err || priv->ap_density < 1 || priv->ap_density > 3) - priv->has_sensitivity = 0; - - /* Get initial RTS threshold */ - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, - &priv->rts_thresh); - if (err) { - dev_err(dev, "Failed to read RTS threshold!\n"); - goto out; - } - - /* Get initial fragmentation settings */ - if (priv->has_mwo) - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMWOROBUST_AGERE, - &priv->mwo_robust); - else - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, - &priv->frag_thresh); - if (err) { - dev_err(dev, "Failed to read fragmentation settings!\n"); - goto out; - } - - /* Power management setup */ - if (priv->has_pm) { - priv->pm_on = 0; - priv->pm_mcast = 1; - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMAXSLEEPDURATION, - &priv->pm_period); - if (err) { - dev_err(dev, "Failed to read power management " - "period!\n"); - goto out; - } - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMHOLDOVERDURATION, - &priv->pm_timeout); - if (err) { - dev_err(dev, "Failed to read power management " - "timeout!\n"); - goto out; - } - } - - /* Preamble setup */ - if (priv->has_preamble) { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFPREAMBLE_SYMBOL, - &priv->preamble); - } - -out: - return err; -} - -/* Can be called before netdev registration */ -int orinoco_hw_allocate_fid(struct orinoco_private *priv) -{ - struct device *dev = priv->dev; - struct hermes *hw = &priv->hw; - int err; - - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - if (err == -EIO && priv->nicbuf_size > TX_NICBUF_SIZE_BUG) { - /* Try workaround for old Symbol firmware bug */ - priv->nicbuf_size = TX_NICBUF_SIZE_BUG; - err = hermes_allocate(hw, priv->nicbuf_size, &priv->txfid); - - dev_warn(dev, "Firmware ALLOC bug detected " - "(old Symbol firmware?). Work around %s\n", - err ? "failed!" : "ok."); - } - - return err; -} - -int orinoco_get_bitratemode(int bitrate, int automatic) -{ - int ratemode = -1; - int i; - - if ((bitrate != 10) && (bitrate != 20) && - (bitrate != 55) && (bitrate != 110)) - return ratemode; - - for (i = 0; i < BITRATE_TABLE_SIZE; i++) { - if ((bitrate_table[i].bitrate == bitrate) && - (bitrate_table[i].automatic == automatic)) { - ratemode = i; - break; - } - } - return ratemode; -} - -void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic) -{ - BUG_ON((ratemode < 0) || (ratemode >= BITRATE_TABLE_SIZE)); - - *bitrate = bitrate_table[ratemode].bitrate * 100000; - *automatic = bitrate_table[ratemode].automatic; -} - -int orinoco_hw_program_rids(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - struct wireless_dev *wdev = netdev_priv(dev); - hermes_t *hw = &priv->hw; - int err; - struct hermes_idstring idbuf; - - /* Set the MAC address */ - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNMACADDR, - HERMES_BYTES_TO_RECLEN(ETH_ALEN), dev->dev_addr); - if (err) { - printk(KERN_ERR "%s: Error %d setting MAC address\n", - dev->name, err); - return err; - } - - /* Set up the link mode */ - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFPORTTYPE, - priv->port_type); - if (err) { - printk(KERN_ERR "%s: Error %d setting port type\n", - dev->name, err); - return err; - } - /* Set the channel/frequency */ - if (priv->channel != 0 && priv->iw_mode != NL80211_IFTYPE_STATION) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFOWNCHANNEL, - priv->channel); - if (err) { - printk(KERN_ERR "%s: Error %d setting channel %d\n", - dev->name, err, priv->channel); - return err; - } - } - - if (priv->has_ibss) { - u16 createibss; - - if ((strlen(priv->desired_essid) == 0) && (priv->createibss)) { - printk(KERN_WARNING "%s: This firmware requires an " - "ESSID in IBSS-Ad-Hoc mode.\n", dev->name); - /* With wvlan_cs, in this case, we would crash. - * hopefully, this driver will behave better... - * Jean II */ - createibss = 0; - } else { - createibss = priv->createibss; - } - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFCREATEIBSS, - createibss); - if (err) { - printk(KERN_ERR "%s: Error %d setting CREATEIBSS\n", - dev->name, err); - return err; - } - } - - /* Set the desired BSSID */ - err = __orinoco_hw_set_wap(priv); - if (err) { - printk(KERN_ERR "%s: Error %d setting AP address\n", - dev->name, err); - return err; - } - - /* Set the desired ESSID */ - idbuf.len = cpu_to_le16(strlen(priv->desired_essid)); - memcpy(&idbuf.val, priv->desired_essid, sizeof(idbuf.val)); - /* WinXP wants partner to configure OWNSSID even in IBSS mode. (jimc) */ - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNSSID, - HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), - &idbuf); - if (err) { - printk(KERN_ERR "%s: Error %d setting OWNSSID\n", - dev->name, err); - return err; - } - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFDESIREDSSID, - HERMES_BYTES_TO_RECLEN(strlen(priv->desired_essid)+2), - &idbuf); - if (err) { - printk(KERN_ERR "%s: Error %d setting DESIREDSSID\n", - dev->name, err); - return err; - } - - /* Set the station name */ - idbuf.len = cpu_to_le16(strlen(priv->nick)); - memcpy(&idbuf.val, priv->nick, sizeof(idbuf.val)); - err = hermes_write_ltv(hw, USER_BAP, HERMES_RID_CNFOWNNAME, - HERMES_BYTES_TO_RECLEN(strlen(priv->nick)+2), - &idbuf); - if (err) { - printk(KERN_ERR "%s: Error %d setting nickname\n", - dev->name, err); - return err; - } - - /* Set AP density */ - if (priv->has_sensitivity) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFSYSTEMSCALE, - priv->ap_density); - if (err) { - printk(KERN_WARNING "%s: Error %d setting SYSTEMSCALE. " - "Disabling sensitivity control\n", - dev->name, err); - - priv->has_sensitivity = 0; - } - } - - /* Set RTS threshold */ - err = hermes_write_wordrec(hw, USER_BAP, HERMES_RID_CNFRTSTHRESHOLD, - priv->rts_thresh); - if (err) { - printk(KERN_ERR "%s: Error %d setting RTS threshold\n", - dev->name, err); - return err; - } - - /* Set fragmentation threshold or MWO robustness */ - if (priv->has_mwo) - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFMWOROBUST_AGERE, - priv->mwo_robust); - else - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, - priv->frag_thresh); - if (err) { - printk(KERN_ERR "%s: Error %d setting fragmentation\n", - dev->name, err); - return err; - } - - /* Set bitrate */ - err = __orinoco_hw_set_bitrate(priv); - if (err) { - printk(KERN_ERR "%s: Error %d setting bitrate\n", - dev->name, err); - return err; - } - - /* Set power management */ - if (priv->has_pm) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMENABLED, - priv->pm_on); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFMULTICASTRECEIVE, - priv->pm_mcast); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFMAXSLEEPDURATION, - priv->pm_period); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMHOLDOVERDURATION, - priv->pm_timeout); - if (err) { - printk(KERN_ERR "%s: Error %d setting up PM\n", - dev->name, err); - return err; - } - } - - /* Set preamble - only for Symbol so far... */ - if (priv->has_preamble) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPREAMBLE_SYMBOL, - priv->preamble); - if (err) { - printk(KERN_ERR "%s: Error %d setting preamble\n", - dev->name, err); - return err; - } - } - - /* Set up encryption */ - if (priv->has_wep || priv->has_wpa) { - err = __orinoco_hw_setup_enc(priv); - if (err) { - printk(KERN_ERR "%s: Error %d activating encryption\n", - dev->name, err); - return err; - } - } - - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - /* Enable monitor mode */ - dev->type = ARPHRD_IEEE80211; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_MONITOR, 0, NULL); - } else { - /* Disable monitor mode */ - dev->type = ARPHRD_ETHER; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_STOP, 0, NULL); - } - if (err) - return err; - - /* Reset promiscuity / multicast*/ - priv->promiscuous = 0; - priv->mc_count = 0; - - /* Record mode change */ - wdev->iftype = priv->iw_mode; - - return 0; -} - -/* Get tsc from the firmware */ -int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc) -{ - hermes_t *hw = &priv->hw; - int err = 0; - u8 tsc_arr[4][ORINOCO_SEQ_LEN]; - - if ((key < 0) || (key >= 4)) - return -EINVAL; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_TKIP_IV, - sizeof(tsc_arr), NULL, &tsc_arr); - if (!err) - memcpy(tsc, &tsc_arr[key][0], sizeof(tsc_arr[0])); - - return err; -} - -int __orinoco_hw_set_bitrate(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - int ratemode = priv->bitratemode; - int err = 0; - - if (ratemode >= BITRATE_TABLE_SIZE) { - printk(KERN_ERR "%s: BUG: Invalid bitrate mode %d\n", - priv->ndev->name, ratemode); - return -EINVAL; - } - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFTXRATECONTROL, - bitrate_table[ratemode].agere_txratectrl); - break; - case FIRMWARE_TYPE_INTERSIL: - case FIRMWARE_TYPE_SYMBOL: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFTXRATECONTROL, - bitrate_table[ratemode].intersil_txratectrl); - break; - default: - BUG(); - } - - return err; -} - -int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate) -{ - hermes_t *hw = &priv->hw; - int i; - int err = 0; - u16 val; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CURRENTTXRATE, &val); - if (err) - return err; - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: /* Lucent style rate */ - /* Note : in Lucent firmware, the return value of - * HERMES_RID_CURRENTTXRATE is the bitrate in Mb/s, - * and therefore is totally different from the - * encoding of HERMES_RID_CNFTXRATECONTROL. - * Don't forget that 6Mb/s is really 5.5Mb/s */ - if (val == 6) - *bitrate = 5500000; - else - *bitrate = val * 1000000; - break; - case FIRMWARE_TYPE_INTERSIL: /* Intersil style rate */ - case FIRMWARE_TYPE_SYMBOL: /* Symbol style rate */ - for (i = 0; i < BITRATE_TABLE_SIZE; i++) - if (bitrate_table[i].intersil_txratectrl == val) - break; - - if (i >= BITRATE_TABLE_SIZE) - printk(KERN_INFO "%s: Unable to determine current bitrate (0x%04hx)\n", - priv->ndev->name, val); - - *bitrate = bitrate_table[i].bitrate * 100000; - break; - default: - BUG(); - } - - return err; -} - -/* Set fixed AP address */ -int __orinoco_hw_set_wap(struct orinoco_private *priv) -{ - int roaming_flag; - int err = 0; - hermes_t *hw = &priv->hw; - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - /* not supported */ - break; - case FIRMWARE_TYPE_INTERSIL: - if (priv->bssid_fixed) - roaming_flag = 2; - else - roaming_flag = 1; - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFROAMINGMODE, - roaming_flag); - break; - case FIRMWARE_TYPE_SYMBOL: - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFMANDATORYBSSID_SYMBOL, - &priv->desired_bssid); - break; - } - return err; -} - -/* Change the WEP keys and/or the current keys. Can be called - * either from __orinoco_hw_setup_enc() or directly from - * orinoco_ioctl_setiwencode(). In the later case the association - * with the AP is not broken (if the firmware can handle it), - * which is needed for 802.1x implementations. */ -int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - int err = 0; - int i; - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - { - struct orinoco_key keys[ORINOCO_MAX_KEYS]; - - memset(&keys, 0, sizeof(keys)); - for (i = 0; i < ORINOCO_MAX_KEYS; i++) { - int len = min(priv->keys[i].key_len, - ORINOCO_MAX_KEY_SIZE); - memcpy(&keys[i].data, priv->keys[i].key, len); - if (len > SMALL_KEY_SIZE) - keys[i].len = cpu_to_le16(LARGE_KEY_SIZE); - else if (len > 0) - keys[i].len = cpu_to_le16(SMALL_KEY_SIZE); - else - keys[i].len = cpu_to_le16(0); - } - - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFWEPKEYS_AGERE, - &keys); - if (err) - return err; - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFTXKEY_AGERE, - priv->tx_key); - if (err) - return err; - break; - } - case FIRMWARE_TYPE_INTERSIL: - case FIRMWARE_TYPE_SYMBOL: - { - int keylen; - - /* Force uniform key length to work around - * firmware bugs */ - keylen = priv->keys[priv->tx_key].key_len; - - if (keylen > LARGE_KEY_SIZE) { - printk(KERN_ERR "%s: BUG: Key %d has oversize length %d.\n", - priv->ndev->name, priv->tx_key, keylen); - return -E2BIG; - } else if (keylen > SMALL_KEY_SIZE) - keylen = LARGE_KEY_SIZE; - else if (keylen > 0) - keylen = SMALL_KEY_SIZE; - else - keylen = 0; - - /* Write all 4 keys */ - for (i = 0; i < ORINOCO_MAX_KEYS; i++) { - u8 key[LARGE_KEY_SIZE] = { 0 }; - - memcpy(key, priv->keys[i].key, - priv->keys[i].key_len); - - err = hermes_write_ltv(hw, USER_BAP, - HERMES_RID_CNFDEFAULTKEY0 + i, - HERMES_BYTES_TO_RECLEN(keylen), - key); - if (err) - return err; - } - - /* Write the index of the key used in transmission */ - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFWEPDEFAULTKEYID, - priv->tx_key); - if (err) - return err; - } - break; - } - - return 0; -} - -int __orinoco_hw_setup_enc(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - int err = 0; - int master_wep_flag; - int auth_flag; - int enc_flag; - - /* Setup WEP keys */ - if (priv->encode_alg == ORINOCO_ALG_WEP) - __orinoco_hw_setup_wepkeys(priv); - - if (priv->wep_restrict) - auth_flag = HERMES_AUTH_SHARED_KEY; - else - auth_flag = HERMES_AUTH_OPEN; - - if (priv->wpa_enabled) - enc_flag = 2; - else if (priv->encode_alg == ORINOCO_ALG_WEP) - enc_flag = 1; - else - enc_flag = 0; - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: /* Agere style WEP */ - if (priv->encode_alg == ORINOCO_ALG_WEP) { - /* Enable the shared-key authentication. */ - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFAUTHENTICATION_AGERE, - auth_flag); - } - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFWEPENABLED_AGERE, - enc_flag); - if (err) - return err; - - if (priv->has_wpa) { - /* Set WPA key management */ - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFSETWPAAUTHMGMTSUITE_AGERE, - priv->key_mgmt); - if (err) - return err; - } - - break; - - case FIRMWARE_TYPE_INTERSIL: /* Intersil style WEP */ - case FIRMWARE_TYPE_SYMBOL: /* Symbol style WEP */ - if (priv->encode_alg == ORINOCO_ALG_WEP) { - if (priv->wep_restrict || - (priv->firmware_type == FIRMWARE_TYPE_SYMBOL)) - master_wep_flag = HERMES_WEP_PRIVACY_INVOKED | - HERMES_WEP_EXCL_UNENCRYPTED; - else - master_wep_flag = HERMES_WEP_PRIVACY_INVOKED; - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFAUTHENTICATION, - auth_flag); - if (err) - return err; - } else - master_wep_flag = 0; - - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) - master_wep_flag |= HERMES_WEP_HOST_DECRYPT; - - /* Master WEP setting : on/off */ - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFWEPFLAGS_INTERSIL, - master_wep_flag); - if (err) - return err; - - break; - } - - return 0; -} - -/* key must be 32 bytes, including the tx and rx MIC keys. - * rsc must be NULL or up to 8 bytes - * tsc must be NULL or up to 8 bytes - */ -int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, - int set_tx, u8 *key, u8 *rsc, size_t rsc_len, - u8 *tsc, size_t tsc_len) -{ - struct { - __le16 idx; - u8 rsc[ORINOCO_SEQ_LEN]; - u8 key[TKIP_KEYLEN]; - u8 tx_mic[MIC_KEYLEN]; - u8 rx_mic[MIC_KEYLEN]; - u8 tsc[ORINOCO_SEQ_LEN]; - } __attribute__ ((packed)) buf; - hermes_t *hw = &priv->hw; - int ret; - int err; - int k; - u16 xmitting; - - key_idx &= 0x3; - - if (set_tx) - key_idx |= 0x8000; - - buf.idx = cpu_to_le16(key_idx); - memcpy(buf.key, key, - sizeof(buf.key) + sizeof(buf.tx_mic) + sizeof(buf.rx_mic)); - - if (rsc_len > sizeof(buf.rsc)) - rsc_len = sizeof(buf.rsc); - - if (tsc_len > sizeof(buf.tsc)) - tsc_len = sizeof(buf.tsc); - - memset(buf.rsc, 0, sizeof(buf.rsc)); - memset(buf.tsc, 0, sizeof(buf.tsc)); - - if (rsc != NULL) - memcpy(buf.rsc, rsc, rsc_len); - - if (tsc != NULL) - memcpy(buf.tsc, tsc, tsc_len); - else - buf.tsc[4] = 0x10; - - /* Wait upto 100ms for tx queue to empty */ - for (k = 100; k > 0; k--) { - udelay(1000); - ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY, - &xmitting); - if (ret || !xmitting) - break; - } - - if (k == 0) - ret = -ETIMEDOUT; - - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFADDDEFAULTTKIPKEY_AGERE, - &buf); - - return ret ? ret : err; -} - -int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx) -{ - hermes_t *hw = &priv->hw; - int err; - - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFREMDEFAULTTKIPKEY_AGERE, - key_idx); - if (err) - printk(KERN_WARNING "%s: Error %d clearing TKIP key %d\n", - priv->ndev->name, err, key_idx); - return err; -} - -int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, - struct dev_addr_list *mc_list, - int mc_count, int promisc) -{ - hermes_t *hw = &priv->hw; - int err = 0; - - if (promisc != priv->promiscuous) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFPROMISCUOUSMODE, - promisc); - if (err) { - printk(KERN_ERR "%s: Error %d setting PROMISCUOUSMODE to 1.\n", - priv->ndev->name, err); - } else - priv->promiscuous = promisc; - } - - /* If we're not in promiscuous mode, then we need to set the - * group address if either we want to multicast, or if we were - * multicasting and want to stop */ - if (!promisc && (mc_count || priv->mc_count)) { - struct dev_mc_list *p = mc_list; - struct hermes_multicast mclist; - int i; - - for (i = 0; i < mc_count; i++) { - /* paranoia: is list shorter than mc_count? */ - BUG_ON(!p); - /* paranoia: bad address size in list? */ - BUG_ON(p->dmi_addrlen != ETH_ALEN); - - memcpy(mclist.addr[i], p->dmi_addr, ETH_ALEN); - p = p->next; - } - - if (p) - printk(KERN_WARNING "%s: Multicast list is " - "longer than mc_count\n", priv->ndev->name); - - err = hermes_write_ltv(hw, USER_BAP, - HERMES_RID_CNFGROUPADDRESSES, - HERMES_BYTES_TO_RECLEN(mc_count * ETH_ALEN), - &mclist); - if (err) - printk(KERN_ERR "%s: Error %d setting multicast list.\n", - priv->ndev->name, err); - else - priv->mc_count = mc_count; - } - return err; -} - -/* Return : < 0 -> error code ; >= 0 -> length */ -int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]) -{ - hermes_t *hw = &priv->hw; - int err = 0; - struct hermes_idstring essidbuf; - char *p = (char *)(&essidbuf.val); - int len; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (strlen(priv->desired_essid) > 0) { - /* We read the desired SSID from the hardware rather - than from priv->desired_essid, just in case the - firmware is allowed to change it on us. I'm not - sure about this */ - /* My guess is that the OWNSSID should always be whatever - * we set to the card, whereas CURRENT_SSID is the one that - * may change... - Jean II */ - u16 rid; - - *active = 1; - - rid = (priv->port_type == 3) ? HERMES_RID_CNFOWNSSID : - HERMES_RID_CNFDESIREDSSID; - - err = hermes_read_ltv(hw, USER_BAP, rid, sizeof(essidbuf), - NULL, &essidbuf); - if (err) - goto fail_unlock; - } else { - *active = 0; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTSSID, - sizeof(essidbuf), NULL, &essidbuf); - if (err) - goto fail_unlock; - } - - len = le16_to_cpu(essidbuf.len); - BUG_ON(len > IW_ESSID_MAX_SIZE); - - memset(buf, 0, IW_ESSID_MAX_SIZE); - memcpy(buf, p, len); - err = len; - - fail_unlock: - orinoco_unlock(priv, &flags); - - return err; -} - -int orinoco_hw_get_freq(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - int err = 0; - u16 channel; - int freq = 0; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_CURRENTCHANNEL, - &channel); - if (err) - goto out; - - /* Intersil firmware 1.3.5 returns 0 when the interface is down */ - if (channel == 0) { - err = -EBUSY; - goto out; - } - - if ((channel < 1) || (channel > NUM_CHANNELS)) { - printk(KERN_WARNING "%s: Channel out of range (%d)!\n", - priv->ndev->name, channel); - err = -EBUSY; - goto out; - - } - freq = ieee80211_dsss_chan_to_freq(channel); - - out: - orinoco_unlock(priv, &flags); - - if (err > 0) - err = -EBUSY; - return err ? err : freq; -} - -int orinoco_hw_get_bitratelist(struct orinoco_private *priv, - int *numrates, s32 *rates, int max) -{ - hermes_t *hw = &priv->hw; - struct hermes_idstring list; - unsigned char *p = (unsigned char *)&list.val; - int err = 0; - int num; - int i; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_SUPPORTEDDATARATES, - sizeof(list), NULL, &list); - orinoco_unlock(priv, &flags); - - if (err) - return err; - - num = le16_to_cpu(list.len); - *numrates = num; - num = min(num, max); - - for (i = 0; i < num; i++) - rates[i] = (p[i] & 0x7f) * 500000; /* convert to bps */ - - return 0; -} - -int orinoco_hw_trigger_scan(struct orinoco_private *priv, - const struct cfg80211_ssid *ssid) -{ - struct net_device *dev = priv->ndev; - hermes_t *hw = &priv->hw; - unsigned long flags; - int err = 0; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Scanning with port 0 disabled would fail */ - if (!netif_running(dev)) { - err = -ENETDOWN; - goto out; - } - - /* In monitor mode, the scan results are always empty. - * Probe responses are passed to the driver as received - * frames and could be processed in software. */ - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - err = -EOPNOTSUPP; - goto out; - } - - if (priv->has_hostscan) { - switch (priv->firmware_type) { - case FIRMWARE_TYPE_SYMBOL: - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFHOSTSCAN_SYMBOL, - HERMES_HOSTSCAN_SYMBOL_ONCE | - HERMES_HOSTSCAN_SYMBOL_BCAST); - break; - case FIRMWARE_TYPE_INTERSIL: { - __le16 req[3]; - - req[0] = cpu_to_le16(0x3fff); /* All channels */ - req[1] = cpu_to_le16(0x0001); /* rate 1 Mbps */ - req[2] = 0; /* Any ESSID */ - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFHOSTSCAN, &req); - break; - } - case FIRMWARE_TYPE_AGERE: - if (ssid->ssid_len > 0) { - struct hermes_idstring idbuf; - size_t len = ssid->ssid_len; - - idbuf.len = cpu_to_le16(len); - memcpy(idbuf.val, ssid->ssid, len); - - err = hermes_write_ltv(hw, USER_BAP, - HERMES_RID_CNFSCANSSID_AGERE, - HERMES_BYTES_TO_RECLEN(len + 2), - &idbuf); - } else - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFSCANSSID_AGERE, - 0); /* Any ESSID */ - if (err) - break; - - if (priv->has_ext_scan) { - err = hermes_write_wordrec(hw, USER_BAP, - HERMES_RID_CNFSCANCHANNELS2GHZ, - 0x7FFF); - if (err) - goto out; - - err = hermes_inquire(hw, - HERMES_INQ_CHANNELINFO); - } else - err = hermes_inquire(hw, HERMES_INQ_SCAN); - - break; - } - } else - err = hermes_inquire(hw, HERMES_INQ_SCAN); - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -/* Disassociate from node with BSSID addr */ -int orinoco_hw_disassociate(struct orinoco_private *priv, - u8 *addr, u16 reason_code) -{ - hermes_t *hw = &priv->hw; - int err; - - struct { - u8 addr[ETH_ALEN]; - __le16 reason_code; - } __attribute__ ((packed)) buf; - - /* Currently only supported by WPA enabled Agere fw */ - if (!priv->has_wpa) - return -EOPNOTSUPP; - - memcpy(buf.addr, addr, ETH_ALEN); - buf.reason_code = cpu_to_le16(reason_code); - err = HERMES_WRITE_RECORD(hw, USER_BAP, - HERMES_RID_CNFDISASSOCIATE, - &buf); - return err; -} - -int orinoco_hw_get_current_bssid(struct orinoco_private *priv, - u8 *addr) -{ - hermes_t *hw = &priv->hw; - int err; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, addr); - - return err; -} diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h deleted file mode 100644 index 8df6e8752be6..000000000000 --- a/drivers/net/wireless/orinoco/hw.h +++ /dev/null @@ -1,59 +0,0 @@ -/* Encapsulate basic setting changes on Hermes hardware - * - * See copyright notice in main.c - */ -#ifndef _ORINOCO_HW_H_ -#define _ORINOCO_HW_H_ - -#include -#include -#include - -/* Hardware BAPs */ -#define USER_BAP 0 -#define IRQ_BAP 1 - -/* WEP key sizes */ -#define SMALL_KEY_SIZE 5 -#define LARGE_KEY_SIZE 13 - -/* Number of supported channels */ -#define NUM_CHANNELS 14 - -/* Forward declarations */ -struct orinoco_private; -struct dev_addr_list; - -int determine_fw_capabilities(struct orinoco_private *priv); -int orinoco_hw_read_card_settings(struct orinoco_private *priv, u8 *dev_addr); -int orinoco_hw_allocate_fid(struct orinoco_private *priv); -int orinoco_get_bitratemode(int bitrate, int automatic); -void orinoco_get_ratemode_cfg(int ratemode, int *bitrate, int *automatic); - -int orinoco_hw_program_rids(struct orinoco_private *priv); -int orinoco_hw_get_tkip_iv(struct orinoco_private *priv, int key, u8 *tsc); -int __orinoco_hw_set_bitrate(struct orinoco_private *priv); -int orinoco_hw_get_act_bitrate(struct orinoco_private *priv, int *bitrate); -int __orinoco_hw_set_wap(struct orinoco_private *priv); -int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv); -int __orinoco_hw_setup_enc(struct orinoco_private *priv); -int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx, - int set_tx, u8 *key, u8 *rsc, size_t rsc_len, - u8 *tsc, size_t tsc_len); -int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx); -int __orinoco_hw_set_multicast_list(struct orinoco_private *priv, - struct dev_addr_list *mc_list, - int mc_count, int promisc); -int orinoco_hw_get_essid(struct orinoco_private *priv, int *active, - char buf[IW_ESSID_MAX_SIZE+1]); -int orinoco_hw_get_freq(struct orinoco_private *priv); -int orinoco_hw_get_bitratelist(struct orinoco_private *priv, - int *numrates, s32 *rates, int max); -int orinoco_hw_trigger_scan(struct orinoco_private *priv, - const struct cfg80211_ssid *ssid); -int orinoco_hw_disassociate(struct orinoco_private *priv, - u8 *addr, u16 reason_code); -int orinoco_hw_get_current_bssid(struct orinoco_private *priv, - u8 *addr); - -#endif /* _ORINOCO_HW_H_ */ diff --git a/drivers/net/wireless/orinoco/main.c b/drivers/net/wireless/orinoco/main.c deleted file mode 100644 index 7a32bcb0c037..000000000000 --- a/drivers/net/wireless/orinoco/main.c +++ /dev/null @@ -1,2393 +0,0 @@ -/* main.c - (formerly known as dldwd_cs.c, orinoco_cs.c and orinoco.c) - * - * A driver for Hermes or Prism 2 chipset based PCMCIA wireless - * adaptors, with Lucent/Agere, Intersil or Symbol firmware. - * - * Current maintainers (as of 29 September 2003) are: - * Pavel Roskin - * and David Gibson - * - * (C) Copyright David Gibson, IBM Corporation 2001-2003. - * Copyright (C) 2000 David Gibson, Linuxcare Australia. - * With some help from : - * Copyright (C) 2001 Jean Tourrilhes, HP Labs - * Copyright (C) 2001 Benjamin Herrenschmidt - * - * Based on dummy_cs.c 1.27 2000/06/12 21:27:25 - * - * Portions based on wvlan_cs.c 1.0.6, Copyright Andreas Neuhaus - * http://www.stud.fh-dortmund.de/~andy/wvlan/ - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * The initial developer of the original code is David A. Hinds - * . Portions created by David - * A. Hinds are Copyright (C) 1999 David A. Hinds. All Rights - * Reserved. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. */ - -/* - * TODO - * o Handle de-encapsulation within network layer, provide 802.11 - * headers (patch from Thomas 'Dent' Mirlacher) - * o Fix possible races in SPY handling. - * o Disconnect wireless extensions from fundamental configuration. - * o (maybe) Software WEP support (patch from Stano Meduna). - * o (maybe) Use multiple Tx buffers - driver handling queue - * rather than firmware. - */ - -/* Locking and synchronization: - * - * The basic principle is that everything is serialized through a - * single spinlock, priv->lock. The lock is used in user, bh and irq - * context, so when taken outside hardirq context it should always be - * taken with interrupts disabled. The lock protects both the - * hardware and the struct orinoco_private. - * - * Another flag, priv->hw_unavailable indicates that the hardware is - * unavailable for an extended period of time (e.g. suspended, or in - * the middle of a hard reset). This flag is protected by the - * spinlock. All code which touches the hardware should check the - * flag after taking the lock, and if it is set, give up on whatever - * they are doing and drop the lock again. The orinoco_lock() - * function handles this (it unlocks and returns -EBUSY if - * hw_unavailable is non-zero). - */ - -#define DRIVER_NAME "orinoco" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "hermes_rid.h" -#include "hermes_dld.h" -#include "hw.h" -#include "scan.h" -#include "mic.h" -#include "fw.h" -#include "wext.h" -#include "cfg.h" -#include "main.h" - -#include "orinoco.h" - -/********************************************************************/ -/* Module information */ -/********************************************************************/ - -MODULE_AUTHOR("Pavel Roskin & " - "David Gibson "); -MODULE_DESCRIPTION("Driver for Lucent Orinoco, Prism II based " - "and similar wireless cards"); -MODULE_LICENSE("Dual MPL/GPL"); - -/* Level of debugging. Used in the macros in orinoco.h */ -#ifdef ORINOCO_DEBUG -int orinoco_debug = ORINOCO_DEBUG; -EXPORT_SYMBOL(orinoco_debug); -module_param(orinoco_debug, int, 0644); -MODULE_PARM_DESC(orinoco_debug, "Debug level"); -#endif - -static int suppress_linkstatus; /* = 0 */ -module_param(suppress_linkstatus, bool, 0644); -MODULE_PARM_DESC(suppress_linkstatus, "Don't log link status changes"); - -static int ignore_disconnect; /* = 0 */ -module_param(ignore_disconnect, int, 0644); -MODULE_PARM_DESC(ignore_disconnect, - "Don't report lost link to the network layer"); - -int force_monitor; /* = 0 */ -module_param(force_monitor, int, 0644); -MODULE_PARM_DESC(force_monitor, "Allow monitor mode for all firmware versions"); - -/********************************************************************/ -/* Internal constants */ -/********************************************************************/ - -/* 802.2 LLC/SNAP header used for Ethernet encapsulation over 802.11 */ -static const u8 encaps_hdr[] = {0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00}; -#define ENCAPS_OVERHEAD (sizeof(encaps_hdr) + 2) - -#define ORINOCO_MIN_MTU 256 -#define ORINOCO_MAX_MTU (IEEE80211_MAX_DATA_LEN - ENCAPS_OVERHEAD) - -#define MAX_IRQLOOPS_PER_IRQ 10 -#define MAX_IRQLOOPS_PER_JIFFY (20000/HZ) /* Based on a guestimate of - * how many events the - * device could - * legitimately generate */ - -#define DUMMY_FID 0xFFFF - -/*#define MAX_MULTICAST(priv) (priv->firmware_type == FIRMWARE_TYPE_AGERE ? \ - HERMES_MAX_MULTICAST : 0)*/ -#define MAX_MULTICAST(priv) (HERMES_MAX_MULTICAST) - -#define ORINOCO_INTEN (HERMES_EV_RX | HERMES_EV_ALLOC \ - | HERMES_EV_TX | HERMES_EV_TXEXC \ - | HERMES_EV_WTERR | HERMES_EV_INFO \ - | HERMES_EV_INFDROP) - -static const struct ethtool_ops orinoco_ethtool_ops; - -/********************************************************************/ -/* Data types */ -/********************************************************************/ - -/* Beginning of the Tx descriptor, used in TxExc handling */ -struct hermes_txexc_data { - struct hermes_tx_descriptor desc; - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; -} __attribute__ ((packed)); - -/* Rx frame header except compatibility 802.3 header */ -struct hermes_rx_descriptor { - /* Control */ - __le16 status; - __le32 time; - u8 silence; - u8 signal; - u8 rate; - u8 rxflow; - __le32 reserved; - - /* 802.11 header */ - __le16 frame_ctl; - __le16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - __le16 seq_ctl; - u8 addr4[ETH_ALEN]; - - /* Data length */ - __le16 data_len; -} __attribute__ ((packed)); - -struct orinoco_rx_data { - struct hermes_rx_descriptor *desc; - struct sk_buff *skb; - struct list_head list; -}; - -struct orinoco_scan_data { - void *buf; - size_t len; - int type; - struct list_head list; -}; - -/********************************************************************/ -/* Function prototypes */ -/********************************************************************/ - -static int __orinoco_set_multicast_list(struct net_device *dev); -static int __orinoco_up(struct orinoco_private *priv); -static int __orinoco_down(struct orinoco_private *priv); -static int __orinoco_commit(struct orinoco_private *priv); - -/********************************************************************/ -/* Internal helper functions */ -/********************************************************************/ - -void set_port_type(struct orinoco_private *priv) -{ - switch (priv->iw_mode) { - case NL80211_IFTYPE_STATION: - priv->port_type = 1; - priv->createibss = 0; - break; - case NL80211_IFTYPE_ADHOC: - if (priv->prefer_port3) { - priv->port_type = 3; - priv->createibss = 0; - } else { - priv->port_type = priv->ibss_port; - priv->createibss = 1; - } - break; - case NL80211_IFTYPE_MONITOR: - priv->port_type = 3; - priv->createibss = 0; - break; - default: - printk(KERN_ERR "%s: Invalid priv->iw_mode in set_port_type()\n", - priv->ndev->name); - } -} - -/********************************************************************/ -/* Device methods */ -/********************************************************************/ - -static int orinoco_open(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - unsigned long flags; - int err; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = __orinoco_up(priv); - - if (!err) - priv->open = 1; - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_stop(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = 0; - - /* We mustn't use orinoco_lock() here, because we need to be - able to close the interface even if hw_unavailable is set - (e.g. as we're released after a PC Card removal) */ - spin_lock_irq(&priv->lock); - - priv->open = 0; - - err = __orinoco_down(priv); - - spin_unlock_irq(&priv->lock); - - return err; -} - -static struct net_device_stats *orinoco_get_stats(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - - return &priv->stats; -} - -static void orinoco_set_multicast_list(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) { - printk(KERN_DEBUG "%s: orinoco_set_multicast_list() " - "called when hw_unavailable\n", dev->name); - return; - } - - __orinoco_set_multicast_list(dev); - orinoco_unlock(priv, &flags); -} - -static int orinoco_change_mtu(struct net_device *dev, int new_mtu) -{ - struct orinoco_private *priv = ndev_priv(dev); - - if ((new_mtu < ORINOCO_MIN_MTU) || (new_mtu > ORINOCO_MAX_MTU)) - return -EINVAL; - - /* MTU + encapsulation + header length */ - if ((new_mtu + ENCAPS_OVERHEAD + sizeof(struct ieee80211_hdr)) > - (priv->nicbuf_size - ETH_HLEN)) - return -EINVAL; - - dev->mtu = new_mtu; - - return 0; -} - -/********************************************************************/ -/* Tx path */ -/********************************************************************/ - -static netdev_tx_t orinoco_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - struct orinoco_tkip_key *key; - hermes_t *hw = &priv->hw; - int err = 0; - u16 txfid = priv->txfid; - struct ethhdr *eh; - int tx_control; - unsigned long flags; - int do_mic; - - if (!netif_running(dev)) { - printk(KERN_ERR "%s: Tx on stopped device!\n", - dev->name); - return NETDEV_TX_BUSY; - } - - if (netif_queue_stopped(dev)) { - printk(KERN_DEBUG "%s: Tx while transmitter busy!\n", - dev->name); - return NETDEV_TX_BUSY; - } - - if (orinoco_lock(priv, &flags) != 0) { - printk(KERN_ERR "%s: orinoco_xmit() called while hw_unavailable\n", - dev->name); - return NETDEV_TX_BUSY; - } - - if (!netif_carrier_ok(dev) || - (priv->iw_mode == NL80211_IFTYPE_MONITOR)) { - /* Oops, the firmware hasn't established a connection, - silently drop the packet (this seems to be the - safest approach). */ - goto drop; - } - - /* Check packet length */ - if (skb->len < ETH_HLEN) - goto drop; - - key = (struct orinoco_tkip_key *) priv->keys[priv->tx_key].key; - - do_mic = ((priv->encode_alg == ORINOCO_ALG_TKIP) && - (key != NULL)); - - tx_control = HERMES_TXCTRL_TX_OK | HERMES_TXCTRL_TX_EX; - - if (do_mic) - tx_control |= (priv->tx_key << HERMES_MIC_KEY_ID_SHIFT) | - HERMES_TXCTRL_MIC; - - if (priv->has_alt_txcntl) { - /* WPA enabled firmwares have tx_cntl at the end of - * the 802.11 header. So write zeroed descriptor and - * 802.11 header at the same time - */ - char desc[HERMES_802_3_OFFSET]; - __le16 *txcntl = (__le16 *) &desc[HERMES_TXCNTL2_OFFSET]; - - memset(&desc, 0, sizeof(desc)); - - *txcntl = cpu_to_le16(tx_control); - err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), - txfid, 0); - if (err) { - if (net_ratelimit()) - printk(KERN_ERR "%s: Error %d writing Tx " - "descriptor to BAP\n", dev->name, err); - goto busy; - } - } else { - struct hermes_tx_descriptor desc; - - memset(&desc, 0, sizeof(desc)); - - desc.tx_control = cpu_to_le16(tx_control); - err = hermes_bap_pwrite(hw, USER_BAP, &desc, sizeof(desc), - txfid, 0); - if (err) { - if (net_ratelimit()) - printk(KERN_ERR "%s: Error %d writing Tx " - "descriptor to BAP\n", dev->name, err); - goto busy; - } - - /* Clear the 802.11 header and data length fields - some - * firmwares (e.g. Lucent/Agere 8.xx) appear to get confused - * if this isn't done. */ - hermes_clear_words(hw, HERMES_DATA0, - HERMES_802_3_OFFSET - HERMES_802_11_OFFSET); - } - - eh = (struct ethhdr *)skb->data; - - /* Encapsulate Ethernet-II frames */ - if (ntohs(eh->h_proto) > ETH_DATA_LEN) { /* Ethernet-II frame */ - struct header_struct { - struct ethhdr eth; /* 802.3 header */ - u8 encap[6]; /* 802.2 header */ - } __attribute__ ((packed)) hdr; - - /* Strip destination and source from the data */ - skb_pull(skb, 2 * ETH_ALEN); - - /* And move them to a separate header */ - memcpy(&hdr.eth, eh, 2 * ETH_ALEN); - hdr.eth.h_proto = htons(sizeof(encaps_hdr) + skb->len); - memcpy(hdr.encap, encaps_hdr, sizeof(encaps_hdr)); - - /* Insert the SNAP header */ - if (skb_headroom(skb) < sizeof(hdr)) { - printk(KERN_ERR - "%s: Not enough headroom for 802.2 headers %d\n", - dev->name, skb_headroom(skb)); - goto drop; - } - eh = (struct ethhdr *) skb_push(skb, sizeof(hdr)); - memcpy(eh, &hdr, sizeof(hdr)); - } - - err = hermes_bap_pwrite(hw, USER_BAP, skb->data, skb->len, - txfid, HERMES_802_3_OFFSET); - if (err) { - printk(KERN_ERR "%s: Error %d writing packet to BAP\n", - dev->name, err); - goto busy; - } - - /* Calculate Michael MIC */ - if (do_mic) { - u8 mic_buf[MICHAEL_MIC_LEN + 1]; - u8 *mic; - size_t offset; - size_t len; - - if (skb->len % 2) { - /* MIC start is on an odd boundary */ - mic_buf[0] = skb->data[skb->len - 1]; - mic = &mic_buf[1]; - offset = skb->len - 1; - len = MICHAEL_MIC_LEN + 1; - } else { - mic = &mic_buf[0]; - offset = skb->len; - len = MICHAEL_MIC_LEN; - } - - orinoco_mic(priv->tx_tfm_mic, key->tx_mic, - eh->h_dest, eh->h_source, 0 /* priority */, - skb->data + ETH_HLEN, skb->len - ETH_HLEN, mic); - - /* Write the MIC */ - err = hermes_bap_pwrite(hw, USER_BAP, &mic_buf[0], len, - txfid, HERMES_802_3_OFFSET + offset); - if (err) { - printk(KERN_ERR "%s: Error %d writing MIC to BAP\n", - dev->name, err); - goto busy; - } - } - - /* Finally, we actually initiate the send */ - netif_stop_queue(dev); - - err = hermes_docmd_wait(hw, HERMES_CMD_TX | HERMES_CMD_RECL, - txfid, NULL); - if (err) { - netif_start_queue(dev); - if (net_ratelimit()) - printk(KERN_ERR "%s: Error %d transmitting packet\n", - dev->name, err); - goto busy; - } - - dev->trans_start = jiffies; - stats->tx_bytes += HERMES_802_3_OFFSET + skb->len; - goto ok; - - drop: - stats->tx_errors++; - stats->tx_dropped++; - - ok: - orinoco_unlock(priv, &flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - - busy: - if (err == -EIO) - schedule_work(&priv->reset_work); - orinoco_unlock(priv, &flags); - return NETDEV_TX_BUSY; -} - -static void __orinoco_ev_alloc(struct net_device *dev, hermes_t *hw) -{ - struct orinoco_private *priv = ndev_priv(dev); - u16 fid = hermes_read_regn(hw, ALLOCFID); - - if (fid != priv->txfid) { - if (fid != DUMMY_FID) - printk(KERN_WARNING "%s: Allocate event on unexpected fid (%04X)\n", - dev->name, fid); - return; - } - - hermes_write_regn(hw, ALLOCFID, DUMMY_FID); -} - -static void __orinoco_ev_tx(struct net_device *dev, hermes_t *hw) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - - stats->tx_packets++; - - netif_wake_queue(dev); - - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); -} - -static void __orinoco_ev_txexc(struct net_device *dev, hermes_t *hw) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - u16 fid = hermes_read_regn(hw, TXCOMPLFID); - u16 status; - struct hermes_txexc_data hdr; - int err = 0; - - if (fid == DUMMY_FID) - return; /* Nothing's really happened */ - - /* Read part of the frame header - we need status and addr1 */ - err = hermes_bap_pread(hw, IRQ_BAP, &hdr, - sizeof(struct hermes_txexc_data), - fid, 0); - - hermes_write_regn(hw, TXCOMPLFID, DUMMY_FID); - stats->tx_errors++; - - if (err) { - printk(KERN_WARNING "%s: Unable to read descriptor on Tx error " - "(FID=%04X error %d)\n", - dev->name, fid, err); - return; - } - - DEBUG(1, "%s: Tx error, err %d (FID=%04X)\n", dev->name, - err, fid); - - /* We produce a TXDROP event only for retry or lifetime - * exceeded, because that's the only status that really mean - * that this particular node went away. - * Other errors means that *we* screwed up. - Jean II */ - status = le16_to_cpu(hdr.desc.status); - if (status & (HERMES_TXSTAT_RETRYERR | HERMES_TXSTAT_AGEDERR)) { - union iwreq_data wrqu; - - /* Copy 802.11 dest address. - * We use the 802.11 header because the frame may - * not be 802.3 or may be mangled... - * In Ad-Hoc mode, it will be the node address. - * In managed mode, it will be most likely the AP addr - * User space will figure out how to convert it to - * whatever it needs (IP address or else). - * - Jean II */ - memcpy(wrqu.addr.sa_data, hdr.addr1, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(dev, IWEVTXDROP, &wrqu, NULL); - } - - netif_wake_queue(dev); -} - -static void orinoco_tx_timeout(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - struct hermes *hw = &priv->hw; - - printk(KERN_WARNING "%s: Tx timeout! " - "ALLOCFID=%04x, TXCOMPLFID=%04x, EVSTAT=%04x\n", - dev->name, hermes_read_regn(hw, ALLOCFID), - hermes_read_regn(hw, TXCOMPLFID), hermes_read_regn(hw, EVSTAT)); - - stats->tx_errors++; - - schedule_work(&priv->reset_work); -} - -/********************************************************************/ -/* Rx path (data frames) */ -/********************************************************************/ - -/* Does the frame have a SNAP header indicating it should be - * de-encapsulated to Ethernet-II? */ -static inline int is_ethersnap(void *_hdr) -{ - u8 *hdr = _hdr; - - /* We de-encapsulate all packets which, a) have SNAP headers - * (i.e. SSAP=DSAP=0xaa and CTRL=0x3 in the 802.2 LLC header - * and where b) the OUI of the SNAP header is 00:00:00 or - * 00:00:f8 - we need both because different APs appear to use - * different OUIs for some reason */ - return (memcmp(hdr, &encaps_hdr, 5) == 0) - && ((hdr[5] == 0x00) || (hdr[5] == 0xf8)); -} - -static inline void orinoco_spy_gather(struct net_device *dev, u_char *mac, - int level, int noise) -{ - struct iw_quality wstats; - wstats.level = level - 0x95; - wstats.noise = noise - 0x95; - wstats.qual = (level > noise) ? (level - noise) : 0; - wstats.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - /* Update spy records */ - wireless_spy_update(dev, mac, &wstats); -} - -static void orinoco_stat_gather(struct net_device *dev, - struct sk_buff *skb, - struct hermes_rx_descriptor *desc) -{ - struct orinoco_private *priv = ndev_priv(dev); - - /* Using spy support with lots of Rx packets, like in an - * infrastructure (AP), will really slow down everything, because - * the MAC address must be compared to each entry of the spy list. - * If the user really asks for it (set some address in the - * spy list), we do it, but he will pay the price. - * Note that to get here, you need both WIRELESS_SPY - * compiled in AND some addresses in the list !!! - */ - /* Note : gcc will optimise the whole section away if - * WIRELESS_SPY is not defined... - Jean II */ - if (SPY_NUMBER(priv)) { - orinoco_spy_gather(dev, skb_mac_header(skb) + ETH_ALEN, - desc->signal, desc->silence); - } -} - -/* - * orinoco_rx_monitor - handle received monitor frames. - * - * Arguments: - * dev network device - * rxfid received FID - * desc rx descriptor of the frame - * - * Call context: interrupt - */ -static void orinoco_rx_monitor(struct net_device *dev, u16 rxfid, - struct hermes_rx_descriptor *desc) -{ - u32 hdrlen = 30; /* return full header by default */ - u32 datalen = 0; - u16 fc; - int err; - int len; - struct sk_buff *skb; - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - hermes_t *hw = &priv->hw; - - len = le16_to_cpu(desc->data_len); - - /* Determine the size of the header and the data */ - fc = le16_to_cpu(desc->frame_ctl); - switch (fc & IEEE80211_FCTL_FTYPE) { - case IEEE80211_FTYPE_DATA: - if ((fc & IEEE80211_FCTL_TODS) - && (fc & IEEE80211_FCTL_FROMDS)) - hdrlen = 30; - else - hdrlen = 24; - datalen = len; - break; - case IEEE80211_FTYPE_MGMT: - hdrlen = 24; - datalen = len; - break; - case IEEE80211_FTYPE_CTL: - switch (fc & IEEE80211_FCTL_STYPE) { - case IEEE80211_STYPE_PSPOLL: - case IEEE80211_STYPE_RTS: - case IEEE80211_STYPE_CFEND: - case IEEE80211_STYPE_CFENDACK: - hdrlen = 16; - break; - case IEEE80211_STYPE_CTS: - case IEEE80211_STYPE_ACK: - hdrlen = 10; - break; - } - break; - default: - /* Unknown frame type */ - break; - } - - /* sanity check the length */ - if (datalen > IEEE80211_MAX_DATA_LEN + 12) { - printk(KERN_DEBUG "%s: oversized monitor frame, " - "data length = %d\n", dev->name, datalen); - stats->rx_length_errors++; - goto update_stats; - } - - skb = dev_alloc_skb(hdrlen + datalen); - if (!skb) { - printk(KERN_WARNING "%s: Cannot allocate skb for monitor frame\n", - dev->name); - goto update_stats; - } - - /* Copy the 802.11 header to the skb */ - memcpy(skb_put(skb, hdrlen), &(desc->frame_ctl), hdrlen); - skb_reset_mac_header(skb); - - /* If any, copy the data from the card to the skb */ - if (datalen > 0) { - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, datalen), - ALIGN(datalen, 2), rxfid, - HERMES_802_2_OFFSET); - if (err) { - printk(KERN_ERR "%s: error %d reading monitor frame\n", - dev->name, err); - goto drop; - } - } - - skb->dev = dev; - skb->ip_summed = CHECKSUM_NONE; - skb->pkt_type = PACKET_OTHERHOST; - skb->protocol = cpu_to_be16(ETH_P_802_2); - - stats->rx_packets++; - stats->rx_bytes += skb->len; - - netif_rx(skb); - return; - - drop: - dev_kfree_skb_irq(skb); - update_stats: - stats->rx_errors++; - stats->rx_dropped++; -} - -static void __orinoco_ev_rx(struct net_device *dev, hermes_t *hw) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - struct iw_statistics *wstats = &priv->wstats; - struct sk_buff *skb = NULL; - u16 rxfid, status; - int length; - struct hermes_rx_descriptor *desc; - struct orinoco_rx_data *rx_data; - int err; - - desc = kmalloc(sizeof(*desc), GFP_ATOMIC); - if (!desc) { - printk(KERN_WARNING - "%s: Can't allocate space for RX descriptor\n", - dev->name); - goto update_stats; - } - - rxfid = hermes_read_regn(hw, RXFID); - - err = hermes_bap_pread(hw, IRQ_BAP, desc, sizeof(*desc), - rxfid, 0); - if (err) { - printk(KERN_ERR "%s: error %d reading Rx descriptor. " - "Frame dropped.\n", dev->name, err); - goto update_stats; - } - - status = le16_to_cpu(desc->status); - - if (status & HERMES_RXSTAT_BADCRC) { - DEBUG(1, "%s: Bad CRC on Rx. Frame dropped.\n", - dev->name); - stats->rx_crc_errors++; - goto update_stats; - } - - /* Handle frames in monitor mode */ - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - orinoco_rx_monitor(dev, rxfid, desc); - goto out; - } - - if (status & HERMES_RXSTAT_UNDECRYPTABLE) { - DEBUG(1, "%s: Undecryptable frame on Rx. Frame dropped.\n", - dev->name); - wstats->discard.code++; - goto update_stats; - } - - length = le16_to_cpu(desc->data_len); - - /* Sanity checks */ - if (length < 3) { /* No for even an 802.2 LLC header */ - /* At least on Symbol firmware with PCF we get quite a - lot of these legitimately - Poll frames with no - data. */ - goto out; - } - if (length > IEEE80211_MAX_DATA_LEN) { - printk(KERN_WARNING "%s: Oversized frame received (%d bytes)\n", - dev->name, length); - stats->rx_length_errors++; - goto update_stats; - } - - /* Payload size does not include Michael MIC. Increase payload - * size to read it together with the data. */ - if (status & HERMES_RXSTAT_MIC) - length += MICHAEL_MIC_LEN; - - /* We need space for the packet data itself, plus an ethernet - header, plus 2 bytes so we can align the IP header on a - 32bit boundary, plus 1 byte so we can read in odd length - packets from the card, which has an IO granularity of 16 - bits */ - skb = dev_alloc_skb(length+ETH_HLEN+2+1); - if (!skb) { - printk(KERN_WARNING "%s: Can't allocate skb for Rx\n", - dev->name); - goto update_stats; - } - - /* We'll prepend the header, so reserve space for it. The worst - case is no decapsulation, when 802.3 header is prepended and - nothing is removed. 2 is for aligning the IP header. */ - skb_reserve(skb, ETH_HLEN + 2); - - err = hermes_bap_pread(hw, IRQ_BAP, skb_put(skb, length), - ALIGN(length, 2), rxfid, - HERMES_802_2_OFFSET); - if (err) { - printk(KERN_ERR "%s: error %d reading frame. " - "Frame dropped.\n", dev->name, err); - goto drop; - } - - /* Add desc and skb to rx queue */ - rx_data = kzalloc(sizeof(*rx_data), GFP_ATOMIC); - if (!rx_data) { - printk(KERN_WARNING "%s: Can't allocate RX packet\n", - dev->name); - goto drop; - } - rx_data->desc = desc; - rx_data->skb = skb; - list_add_tail(&rx_data->list, &priv->rx_list); - tasklet_schedule(&priv->rx_tasklet); - - return; - -drop: - dev_kfree_skb_irq(skb); -update_stats: - stats->rx_errors++; - stats->rx_dropped++; -out: - kfree(desc); -} - -static void orinoco_rx(struct net_device *dev, - struct hermes_rx_descriptor *desc, - struct sk_buff *skb) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct net_device_stats *stats = &priv->stats; - u16 status, fc; - int length; - struct ethhdr *hdr; - - status = le16_to_cpu(desc->status); - length = le16_to_cpu(desc->data_len); - fc = le16_to_cpu(desc->frame_ctl); - - /* Calculate and check MIC */ - if (status & HERMES_RXSTAT_MIC) { - struct orinoco_tkip_key *key; - int key_id = ((status & HERMES_RXSTAT_MIC_KEY_ID) >> - HERMES_MIC_KEY_ID_SHIFT); - u8 mic[MICHAEL_MIC_LEN]; - u8 *rxmic; - u8 *src = (fc & IEEE80211_FCTL_FROMDS) ? - desc->addr3 : desc->addr2; - - /* Extract Michael MIC from payload */ - rxmic = skb->data + skb->len - MICHAEL_MIC_LEN; - - skb_trim(skb, skb->len - MICHAEL_MIC_LEN); - length -= MICHAEL_MIC_LEN; - - key = (struct orinoco_tkip_key *) priv->keys[key_id].key; - - if (!key) { - printk(KERN_WARNING "%s: Received encrypted frame from " - "%pM using key %i, but key is not installed\n", - dev->name, src, key_id); - goto drop; - } - - orinoco_mic(priv->rx_tfm_mic, key->rx_mic, desc->addr1, src, - 0, /* priority or QoS? */ - skb->data, skb->len, &mic[0]); - - if (memcmp(mic, rxmic, - MICHAEL_MIC_LEN)) { - union iwreq_data wrqu; - struct iw_michaelmicfailure wxmic; - - printk(KERN_WARNING "%s: " - "Invalid Michael MIC in data frame from %pM, " - "using key %i\n", - dev->name, src, key_id); - - /* TODO: update stats */ - - /* Notify userspace */ - memset(&wxmic, 0, sizeof(wxmic)); - wxmic.flags = key_id & IW_MICFAILURE_KEY_ID; - wxmic.flags |= (desc->addr1[0] & 1) ? - IW_MICFAILURE_GROUP : IW_MICFAILURE_PAIRWISE; - wxmic.src_addr.sa_family = ARPHRD_ETHER; - memcpy(wxmic.src_addr.sa_data, src, ETH_ALEN); - - (void) orinoco_hw_get_tkip_iv(priv, key_id, - &wxmic.tsc[0]); - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(wxmic); - wireless_send_event(dev, IWEVMICHAELMICFAILURE, &wrqu, - (char *) &wxmic); - - goto drop; - } - } - - /* Handle decapsulation - * In most cases, the firmware tell us about SNAP frames. - * For some reason, the SNAP frames sent by LinkSys APs - * are not properly recognised by most firmwares. - * So, check ourselves */ - if (length >= ENCAPS_OVERHEAD && - (((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_1042) || - ((status & HERMES_RXSTAT_MSGTYPE) == HERMES_RXSTAT_TUNNEL) || - is_ethersnap(skb->data))) { - /* These indicate a SNAP within 802.2 LLC within - 802.11 frame which we'll need to de-encapsulate to - the original EthernetII frame. */ - hdr = (struct ethhdr *)skb_push(skb, - ETH_HLEN - ENCAPS_OVERHEAD); - } else { - /* 802.3 frame - prepend 802.3 header as is */ - hdr = (struct ethhdr *)skb_push(skb, ETH_HLEN); - hdr->h_proto = htons(length); - } - memcpy(hdr->h_dest, desc->addr1, ETH_ALEN); - if (fc & IEEE80211_FCTL_FROMDS) - memcpy(hdr->h_source, desc->addr3, ETH_ALEN); - else - memcpy(hdr->h_source, desc->addr2, ETH_ALEN); - - skb->protocol = eth_type_trans(skb, dev); - skb->ip_summed = CHECKSUM_NONE; - if (fc & IEEE80211_FCTL_TODS) - skb->pkt_type = PACKET_OTHERHOST; - - /* Process the wireless stats if needed */ - orinoco_stat_gather(dev, skb, desc); - - /* Pass the packet to the networking stack */ - netif_rx(skb); - stats->rx_packets++; - stats->rx_bytes += length; - - return; - - drop: - dev_kfree_skb(skb); - stats->rx_errors++; - stats->rx_dropped++; -} - -static void orinoco_rx_isr_tasklet(unsigned long data) -{ - struct orinoco_private *priv = (struct orinoco_private *) data; - struct net_device *dev = priv->ndev; - struct orinoco_rx_data *rx_data, *temp; - struct hermes_rx_descriptor *desc; - struct sk_buff *skb; - unsigned long flags; - - /* orinoco_rx requires the driver lock, and we also need to - * protect priv->rx_list, so just hold the lock over the - * lot. - * - * If orinoco_lock fails, we've unplugged the card. In this - * case just abort. */ - if (orinoco_lock(priv, &flags) != 0) - return; - - /* extract desc and skb from queue */ - list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { - desc = rx_data->desc; - skb = rx_data->skb; - list_del(&rx_data->list); - kfree(rx_data); - - orinoco_rx(dev, desc, skb); - - kfree(desc); - } - - orinoco_unlock(priv, &flags); -} - -/********************************************************************/ -/* Rx path (info frames) */ -/********************************************************************/ - -static void print_linkstatus(struct net_device *dev, u16 status) -{ - char *s; - - if (suppress_linkstatus) - return; - - switch (status) { - case HERMES_LINKSTATUS_NOT_CONNECTED: - s = "Not Connected"; - break; - case HERMES_LINKSTATUS_CONNECTED: - s = "Connected"; - break; - case HERMES_LINKSTATUS_DISCONNECTED: - s = "Disconnected"; - break; - case HERMES_LINKSTATUS_AP_CHANGE: - s = "AP Changed"; - break; - case HERMES_LINKSTATUS_AP_OUT_OF_RANGE: - s = "AP Out of Range"; - break; - case HERMES_LINKSTATUS_AP_IN_RANGE: - s = "AP In Range"; - break; - case HERMES_LINKSTATUS_ASSOC_FAILED: - s = "Association Failed"; - break; - default: - s = "UNKNOWN"; - } - - printk(KERN_DEBUG "%s: New link status: %s (%04x)\n", - dev->name, s, status); -} - -/* Search scan results for requested BSSID, join it if found */ -static void orinoco_join_ap(struct work_struct *work) -{ - struct orinoco_private *priv = - container_of(work, struct orinoco_private, join_work); - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - int err; - unsigned long flags; - struct join_req { - u8 bssid[ETH_ALEN]; - __le16 channel; - } __attribute__ ((packed)) req; - const int atom_len = offsetof(struct prism2_scan_apinfo, atim); - struct prism2_scan_apinfo *atom = NULL; - int offset = 4; - int found = 0; - u8 *buf; - u16 len; - - /* Allocate buffer for scan results */ - buf = kmalloc(MAX_SCAN_LEN, GFP_KERNEL); - if (!buf) - return; - - if (orinoco_lock(priv, &flags) != 0) - goto fail_lock; - - /* Sanity checks in case user changed something in the meantime */ - if (!priv->bssid_fixed) - goto out; - - if (strlen(priv->desired_essid) == 0) - goto out; - - /* Read scan results from the firmware */ - err = hermes_read_ltv(hw, USER_BAP, - HERMES_RID_SCANRESULTSTABLE, - MAX_SCAN_LEN, &len, buf); - if (err) { - printk(KERN_ERR "%s: Cannot read scan results\n", - dev->name); - goto out; - } - - len = HERMES_RECLEN_TO_BYTES(len); - - /* Go through the scan results looking for the channel of the AP - * we were requested to join */ - for (; offset + atom_len <= len; offset += atom_len) { - atom = (struct prism2_scan_apinfo *) (buf + offset); - if (memcmp(&atom->bssid, priv->desired_bssid, ETH_ALEN) == 0) { - found = 1; - break; - } - } - - if (!found) { - DEBUG(1, "%s: Requested AP not found in scan results\n", - dev->name); - goto out; - } - - memcpy(req.bssid, priv->desired_bssid, ETH_ALEN); - req.channel = atom->channel; /* both are little-endian */ - err = HERMES_WRITE_RECORD(hw, USER_BAP, HERMES_RID_CNFJOINREQUEST, - &req); - if (err) - printk(KERN_ERR "%s: Error issuing join request\n", dev->name); - - out: - orinoco_unlock(priv, &flags); - - fail_lock: - kfree(buf); -} - -/* Send new BSSID to userspace */ -static void orinoco_send_bssid_wevent(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - union iwreq_data wrqu; - int err; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENTBSSID, - ETH_ALEN, NULL, wrqu.ap_addr.sa_data); - if (err != 0) - return; - - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(dev, SIOCGIWAP, &wrqu, NULL); -} - -static void orinoco_send_assocreqie_wevent(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - union iwreq_data wrqu; - int err; - u8 buf[88]; - u8 *ie; - - if (!priv->has_wpa) - return; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_REQ_INFO, - sizeof(buf), NULL, &buf); - if (err != 0) - return; - - ie = orinoco_get_wpa_ie(buf, sizeof(buf)); - if (ie) { - int rem = sizeof(buf) - (ie - &buf[0]); - wrqu.data.length = ie[1] + 2; - if (wrqu.data.length > rem) - wrqu.data.length = rem; - - if (wrqu.data.length) - /* Send event to user space */ - wireless_send_event(dev, IWEVASSOCREQIE, &wrqu, ie); - } -} - -static void orinoco_send_assocrespie_wevent(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - union iwreq_data wrqu; - int err; - u8 buf[88]; /* TODO: verify max size or IW_GENERIC_IE_MAX */ - u8 *ie; - - if (!priv->has_wpa) - return; - - err = hermes_read_ltv(hw, USER_BAP, HERMES_RID_CURRENT_ASSOC_RESP_INFO, - sizeof(buf), NULL, &buf); - if (err != 0) - return; - - ie = orinoco_get_wpa_ie(buf, sizeof(buf)); - if (ie) { - int rem = sizeof(buf) - (ie - &buf[0]); - wrqu.data.length = ie[1] + 2; - if (wrqu.data.length > rem) - wrqu.data.length = rem; - - if (wrqu.data.length) - /* Send event to user space */ - wireless_send_event(dev, IWEVASSOCRESPIE, &wrqu, ie); - } -} - -static void orinoco_send_wevents(struct work_struct *work) -{ - struct orinoco_private *priv = - container_of(work, struct orinoco_private, wevent_work); - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return; - - orinoco_send_assocreqie_wevent(priv); - orinoco_send_assocrespie_wevent(priv); - orinoco_send_bssid_wevent(priv); - - orinoco_unlock(priv, &flags); -} - -static void qbuf_scan(struct orinoco_private *priv, void *buf, - int len, int type) -{ - struct orinoco_scan_data *sd; - unsigned long flags; - - sd = kmalloc(sizeof(*sd), GFP_ATOMIC); - sd->buf = buf; - sd->len = len; - sd->type = type; - - spin_lock_irqsave(&priv->scan_lock, flags); - list_add_tail(&sd->list, &priv->scan_list); - spin_unlock_irqrestore(&priv->scan_lock, flags); - - schedule_work(&priv->process_scan); -} - -static void qabort_scan(struct orinoco_private *priv) -{ - struct orinoco_scan_data *sd; - unsigned long flags; - - sd = kmalloc(sizeof(*sd), GFP_ATOMIC); - sd->len = -1; /* Abort */ - - spin_lock_irqsave(&priv->scan_lock, flags); - list_add_tail(&sd->list, &priv->scan_list); - spin_unlock_irqrestore(&priv->scan_lock, flags); - - schedule_work(&priv->process_scan); -} - -static void orinoco_process_scan_results(struct work_struct *work) -{ - struct orinoco_private *priv = - container_of(work, struct orinoco_private, process_scan); - struct orinoco_scan_data *sd, *temp; - unsigned long flags; - void *buf; - int len; - int type; - - spin_lock_irqsave(&priv->scan_lock, flags); - list_for_each_entry_safe(sd, temp, &priv->scan_list, list) { - spin_unlock_irqrestore(&priv->scan_lock, flags); - - buf = sd->buf; - len = sd->len; - type = sd->type; - - list_del(&sd->list); - kfree(sd); - - if (len > 0) { - if (type == HERMES_INQ_CHANNELINFO) - orinoco_add_extscan_result(priv, buf, len); - else - orinoco_add_hostscan_results(priv, buf, len); - - kfree(buf); - } else if (priv->scan_request) { - /* Either abort or complete the scan */ - cfg80211_scan_done(priv->scan_request, (len < 0)); - priv->scan_request = NULL; - } - - spin_lock_irqsave(&priv->scan_lock, flags); - } - spin_unlock_irqrestore(&priv->scan_lock, flags); -} - -static void __orinoco_ev_info(struct net_device *dev, hermes_t *hw) -{ - struct orinoco_private *priv = ndev_priv(dev); - u16 infofid; - struct { - __le16 len; - __le16 type; - } __attribute__ ((packed)) info; - int len, type; - int err; - - /* This is an answer to an INQUIRE command that we did earlier, - * or an information "event" generated by the card - * The controller return to us a pseudo frame containing - * the information in question - Jean II */ - infofid = hermes_read_regn(hw, INFOFID); - - /* Read the info frame header - don't try too hard */ - err = hermes_bap_pread(hw, IRQ_BAP, &info, sizeof(info), - infofid, 0); - if (err) { - printk(KERN_ERR "%s: error %d reading info frame. " - "Frame dropped.\n", dev->name, err); - return; - } - - len = HERMES_RECLEN_TO_BYTES(le16_to_cpu(info.len)); - type = le16_to_cpu(info.type); - - switch (type) { - case HERMES_INQ_TALLIES: { - struct hermes_tallies_frame tallies; - struct iw_statistics *wstats = &priv->wstats; - - if (len > sizeof(tallies)) { - printk(KERN_WARNING "%s: Tallies frame too long (%d bytes)\n", - dev->name, len); - len = sizeof(tallies); - } - - err = hermes_bap_pread(hw, IRQ_BAP, &tallies, len, - infofid, sizeof(info)); - if (err) - break; - - /* Increment our various counters */ - /* wstats->discard.nwid - no wrong BSSID stuff */ - wstats->discard.code += - le16_to_cpu(tallies.RxWEPUndecryptable); - if (len == sizeof(tallies)) - wstats->discard.code += - le16_to_cpu(tallies.RxDiscards_WEPICVError) + - le16_to_cpu(tallies.RxDiscards_WEPExcluded); - wstats->discard.misc += - le16_to_cpu(tallies.TxDiscardsWrongSA); - wstats->discard.fragment += - le16_to_cpu(tallies.RxMsgInBadMsgFragments); - wstats->discard.retries += - le16_to_cpu(tallies.TxRetryLimitExceeded); - /* wstats->miss.beacon - no match */ - } - break; - case HERMES_INQ_LINKSTATUS: { - struct hermes_linkstatus linkstatus; - u16 newstatus; - int connected; - - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) - break; - - if (len != sizeof(linkstatus)) { - printk(KERN_WARNING "%s: Unexpected size for linkstatus frame (%d bytes)\n", - dev->name, len); - break; - } - - err = hermes_bap_pread(hw, IRQ_BAP, &linkstatus, len, - infofid, sizeof(info)); - if (err) - break; - newstatus = le16_to_cpu(linkstatus.linkstatus); - - /* Symbol firmware uses "out of range" to signal that - * the hostscan frame can be requested. */ - if (newstatus == HERMES_LINKSTATUS_AP_OUT_OF_RANGE && - priv->firmware_type == FIRMWARE_TYPE_SYMBOL && - priv->has_hostscan && priv->scan_request) { - hermes_inquire(hw, HERMES_INQ_HOSTSCAN_SYMBOL); - break; - } - - connected = (newstatus == HERMES_LINKSTATUS_CONNECTED) - || (newstatus == HERMES_LINKSTATUS_AP_CHANGE) - || (newstatus == HERMES_LINKSTATUS_AP_IN_RANGE); - - if (connected) - netif_carrier_on(dev); - else if (!ignore_disconnect) - netif_carrier_off(dev); - - if (newstatus != priv->last_linkstatus) { - priv->last_linkstatus = newstatus; - print_linkstatus(dev, newstatus); - /* The info frame contains only one word which is the - * status (see hermes.h). The status is pretty boring - * in itself, that's why we export the new BSSID... - * Jean II */ - schedule_work(&priv->wevent_work); - } - } - break; - case HERMES_INQ_SCAN: - if (!priv->scan_request && priv->bssid_fixed && - priv->firmware_type == FIRMWARE_TYPE_INTERSIL) { - schedule_work(&priv->join_work); - break; - } - /* fall through */ - case HERMES_INQ_HOSTSCAN: - case HERMES_INQ_HOSTSCAN_SYMBOL: { - /* Result of a scanning. Contains information about - * cells in the vicinity - Jean II */ - unsigned char *buf; - - /* Sanity check */ - if (len > 4096) { - printk(KERN_WARNING "%s: Scan results too large (%d bytes)\n", - dev->name, len); - qabort_scan(priv); - break; - } - - /* Allocate buffer for results */ - buf = kmalloc(len, GFP_ATOMIC); - if (buf == NULL) { - /* No memory, so can't printk()... */ - qabort_scan(priv); - break; - } - - /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) buf, len, - infofid, sizeof(info)); - if (err) { - kfree(buf); - qabort_scan(priv); - break; - } - -#ifdef ORINOCO_DEBUG - { - int i; - printk(KERN_DEBUG "Scan result [%02X", buf[0]); - for (i = 1; i < (len * 2); i++) - printk(":%02X", buf[i]); - printk("]\n"); - } -#endif /* ORINOCO_DEBUG */ - - qbuf_scan(priv, buf, len, type); - } - break; - case HERMES_INQ_CHANNELINFO: - { - struct agere_ext_scan_info *bss; - - if (!priv->scan_request) { - printk(KERN_DEBUG "%s: Got chaninfo without scan, " - "len=%d\n", dev->name, len); - break; - } - - /* An empty result indicates that the scan is complete */ - if (len == 0) { - qbuf_scan(priv, NULL, len, type); - break; - } - - /* Sanity check */ - else if (len < (offsetof(struct agere_ext_scan_info, - data) + 2)) { - /* Drop this result now so we don't have to - * keep checking later */ - printk(KERN_WARNING - "%s: Ext scan results too short (%d bytes)\n", - dev->name, len); - break; - } - - bss = kmalloc(len, GFP_ATOMIC); - if (bss == NULL) - break; - - /* Read scan data */ - err = hermes_bap_pread(hw, IRQ_BAP, (void *) bss, len, - infofid, sizeof(info)); - if (err) - kfree(bss); - else - qbuf_scan(priv, bss, len, type); - - break; - } - case HERMES_INQ_SEC_STAT_AGERE: - /* Security status (Agere specific) */ - /* Ignore this frame for now */ - if (priv->firmware_type == FIRMWARE_TYPE_AGERE) - break; - /* fall through */ - default: - printk(KERN_DEBUG "%s: Unknown information frame received: " - "type 0x%04x, length %d\n", dev->name, type, len); - /* We don't actually do anything about it */ - break; - } - - return; -} - -static void __orinoco_ev_infdrop(struct net_device *dev, hermes_t *hw) -{ - if (net_ratelimit()) - printk(KERN_DEBUG "%s: Information frame lost.\n", dev->name); -} - -/********************************************************************/ -/* Internal hardware control routines */ -/********************************************************************/ - -static int __orinoco_up(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - int err; - - netif_carrier_off(dev); /* just to make sure */ - - err = __orinoco_commit(priv); - if (err) { - printk(KERN_ERR "%s: Error %d configuring card\n", - dev->name, err); - return err; - } - - /* Fire things up again */ - hermes_set_irqmask(hw, ORINOCO_INTEN); - err = hermes_enable_port(hw, 0); - if (err) { - printk(KERN_ERR "%s: Error %d enabling MAC port\n", - dev->name, err); - return err; - } - - netif_start_queue(dev); - - return 0; -} - -static int __orinoco_down(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - int err; - - netif_stop_queue(dev); - - if (!priv->hw_unavailable) { - if (!priv->broken_disableport) { - err = hermes_disable_port(hw, 0); - if (err) { - /* Some firmwares (e.g. Intersil 1.3.x) seem - * to have problems disabling the port, oh - * well, too bad. */ - printk(KERN_WARNING "%s: Error %d disabling MAC port\n", - dev->name, err); - priv->broken_disableport = 1; - } - } - hermes_set_irqmask(hw, 0); - hermes_write_regn(hw, EVACK, 0xffff); - } - - /* firmware will have to reassociate */ - netif_carrier_off(dev); - priv->last_linkstatus = 0xffff; - - return 0; -} - -static int orinoco_reinit_firmware(struct orinoco_private *priv) -{ - struct hermes *hw = &priv->hw; - int err; - - err = hermes_init(hw); - if (priv->do_fw_download && !err) { - err = orinoco_download(priv); - if (err) - priv->do_fw_download = 0; - } - if (!err) - err = orinoco_hw_allocate_fid(priv); - - return err; -} - -static int -__orinoco_set_multicast_list(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = 0; - int promisc, mc_count; - - /* The Hermes doesn't seem to have an allmulti mode, so we go - * into promiscuous mode and let the upper levels deal. */ - if ((dev->flags & IFF_PROMISC) || (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > MAX_MULTICAST(priv))) { - promisc = 1; - mc_count = 0; - } else { - promisc = 0; - mc_count = dev->mc_count; - } - - err = __orinoco_hw_set_multicast_list(priv, dev->mc_list, mc_count, - promisc); - - return err; -} - -/* This must be called from user context, without locks held - use - * schedule_work() */ -void orinoco_reset(struct work_struct *work) -{ - struct orinoco_private *priv = - container_of(work, struct orinoco_private, reset_work); - struct net_device *dev = priv->ndev; - struct hermes *hw = &priv->hw; - int err; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - /* When the hardware becomes available again, whatever - * detects that is responsible for re-initializing - * it. So no need for anything further */ - return; - - netif_stop_queue(dev); - - /* Shut off interrupts. Depending on what state the hardware - * is in, this might not work, but we'll try anyway */ - hermes_set_irqmask(hw, 0); - hermes_write_regn(hw, EVACK, 0xffff); - - priv->hw_unavailable++; - priv->last_linkstatus = 0xffff; /* firmware will have to reassociate */ - netif_carrier_off(dev); - - orinoco_unlock(priv, &flags); - - /* Scanning support: Notify scan cancellation */ - if (priv->scan_request) { - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } - - if (priv->hard_reset) { - err = (*priv->hard_reset)(priv); - if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d " - "performing hard reset\n", dev->name, err); - goto disable; - } - } - - err = orinoco_reinit_firmware(priv); - if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d re-initializing firmware\n", - dev->name, err); - goto disable; - } - - /* This has to be called from user context */ - spin_lock_irq(&priv->lock); - - priv->hw_unavailable--; - - /* priv->open or priv->hw_unavailable might have changed while - * we dropped the lock */ - if (priv->open && (!priv->hw_unavailable)) { - err = __orinoco_up(priv); - if (err) { - printk(KERN_ERR "%s: orinoco_reset: Error %d reenabling card\n", - dev->name, err); - } else - dev->trans_start = jiffies; - } - - spin_unlock_irq(&priv->lock); - - return; - disable: - hermes_set_irqmask(hw, 0); - netif_device_detach(dev); - printk(KERN_ERR "%s: Device has been disabled!\n", dev->name); -} - -static int __orinoco_commit(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - int err = 0; - - err = orinoco_hw_program_rids(priv); - - /* FIXME: what about netif_tx_lock */ - (void) __orinoco_set_multicast_list(dev); - - return err; -} - -/* Ensures configuration changes are applied. May result in a reset. - * The caller should hold priv->lock - */ -int orinoco_commit(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - hermes_t *hw = &priv->hw; - int err; - - if (priv->broken_disableport) { - schedule_work(&priv->reset_work); - return 0; - } - - err = hermes_disable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to disable port " - "while reconfiguring card\n", dev->name); - priv->broken_disableport = 1; - goto out; - } - - err = __orinoco_commit(priv); - if (err) { - printk(KERN_WARNING "%s: Unable to reconfigure card\n", - dev->name); - goto out; - } - - err = hermes_enable_port(hw, 0); - if (err) { - printk(KERN_WARNING "%s: Unable to enable port while reconfiguring card\n", - dev->name); - goto out; - } - - out: - if (err) { - printk(KERN_WARNING "%s: Resetting instead...\n", dev->name); - schedule_work(&priv->reset_work); - err = 0; - } - return err; -} - -/********************************************************************/ -/* Interrupt handler */ -/********************************************************************/ - -static void __orinoco_ev_tick(struct net_device *dev, hermes_t *hw) -{ - printk(KERN_DEBUG "%s: TICK\n", dev->name); -} - -static void __orinoco_ev_wterr(struct net_device *dev, hermes_t *hw) -{ - /* This seems to happen a fair bit under load, but ignoring it - seems to work fine...*/ - printk(KERN_DEBUG "%s: MAC controller error (WTERR). Ignoring.\n", - dev->name); -} - -irqreturn_t orinoco_interrupt(int irq, void *dev_id) -{ - struct orinoco_private *priv = dev_id; - struct net_device *dev = priv->ndev; - hermes_t *hw = &priv->hw; - int count = MAX_IRQLOOPS_PER_IRQ; - u16 evstat, events; - /* These are used to detect a runaway interrupt situation. - * - * If we get more than MAX_IRQLOOPS_PER_JIFFY iterations in a jiffy, - * we panic and shut down the hardware - */ - /* jiffies value the last time we were called */ - static int last_irq_jiffy; /* = 0 */ - static int loops_this_jiffy; /* = 0 */ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) { - /* If hw is unavailable - we don't know if the irq was - * for us or not */ - return IRQ_HANDLED; - } - - evstat = hermes_read_regn(hw, EVSTAT); - events = evstat & hw->inten; - if (!events) { - orinoco_unlock(priv, &flags); - return IRQ_NONE; - } - - if (jiffies != last_irq_jiffy) - loops_this_jiffy = 0; - last_irq_jiffy = jiffies; - - while (events && count--) { - if (++loops_this_jiffy > MAX_IRQLOOPS_PER_JIFFY) { - printk(KERN_WARNING "%s: IRQ handler is looping too " - "much! Resetting.\n", dev->name); - /* Disable interrupts for now */ - hermes_set_irqmask(hw, 0); - schedule_work(&priv->reset_work); - break; - } - - /* Check the card hasn't been removed */ - if (!hermes_present(hw)) { - DEBUG(0, "orinoco_interrupt(): card removed\n"); - break; - } - - if (events & HERMES_EV_TICK) - __orinoco_ev_tick(dev, hw); - if (events & HERMES_EV_WTERR) - __orinoco_ev_wterr(dev, hw); - if (events & HERMES_EV_INFDROP) - __orinoco_ev_infdrop(dev, hw); - if (events & HERMES_EV_INFO) - __orinoco_ev_info(dev, hw); - if (events & HERMES_EV_RX) - __orinoco_ev_rx(dev, hw); - if (events & HERMES_EV_TXEXC) - __orinoco_ev_txexc(dev, hw); - if (events & HERMES_EV_TX) - __orinoco_ev_tx(dev, hw); - if (events & HERMES_EV_ALLOC) - __orinoco_ev_alloc(dev, hw); - - hermes_write_regn(hw, EVACK, evstat); - - evstat = hermes_read_regn(hw, EVSTAT); - events = evstat & hw->inten; - }; - - orinoco_unlock(priv, &flags); - return IRQ_HANDLED; -} -EXPORT_SYMBOL(orinoco_interrupt); - -/********************************************************************/ -/* Power management */ -/********************************************************************/ -#if defined(CONFIG_PM_SLEEP) && !defined(CONFIG_HERMES_CACHE_FW_ON_INIT) -static int orinoco_pm_notifier(struct notifier_block *notifier, - unsigned long pm_event, - void *unused) -{ - struct orinoco_private *priv = container_of(notifier, - struct orinoco_private, - pm_notifier); - - /* All we need to do is cache the firmware before suspend, and - * release it when we come out. - * - * Only need to do this if we're downloading firmware. */ - if (!priv->do_fw_download) - return NOTIFY_DONE; - - switch (pm_event) { - case PM_HIBERNATION_PREPARE: - case PM_SUSPEND_PREPARE: - orinoco_cache_fw(priv, 0); - break; - - case PM_POST_RESTORE: - /* Restore from hibernation failed. We need to clean - * up in exactly the same way, so fall through. */ - case PM_POST_HIBERNATION: - case PM_POST_SUSPEND: - orinoco_uncache_fw(priv); - break; - - case PM_RESTORE_PREPARE: - default: - break; - } - - return NOTIFY_DONE; -} - -static void orinoco_register_pm_notifier(struct orinoco_private *priv) -{ - priv->pm_notifier.notifier_call = orinoco_pm_notifier; - register_pm_notifier(&priv->pm_notifier); -} - -static void orinoco_unregister_pm_notifier(struct orinoco_private *priv) -{ - unregister_pm_notifier(&priv->pm_notifier); -} -#else /* !PM_SLEEP || HERMES_CACHE_FW_ON_INIT */ -#define orinoco_register_pm_notifier(priv) do { } while(0) -#define orinoco_unregister_pm_notifier(priv) do { } while(0) -#endif - -/********************************************************************/ -/* Initialization */ -/********************************************************************/ - -int orinoco_init(struct orinoco_private *priv) -{ - struct device *dev = priv->dev; - struct wiphy *wiphy = priv_to_wiphy(priv); - hermes_t *hw = &priv->hw; - int err = 0; - - /* No need to lock, the hw_unavailable flag is already set in - * alloc_orinocodev() */ - priv->nicbuf_size = IEEE80211_MAX_FRAME_LEN + ETH_HLEN; - - /* Initialize the firmware */ - err = hermes_init(hw); - if (err != 0) { - dev_err(dev, "Failed to initialize firmware (err = %d)\n", - err); - goto out; - } - - err = determine_fw_capabilities(priv); - if (err != 0) { - dev_err(dev, "Incompatible firmware, aborting\n"); - goto out; - } - - if (priv->do_fw_download) { -#ifdef CONFIG_HERMES_CACHE_FW_ON_INIT - orinoco_cache_fw(priv, 0); -#endif - - err = orinoco_download(priv); - if (err) - priv->do_fw_download = 0; - - /* Check firmware version again */ - err = determine_fw_capabilities(priv); - if (err != 0) { - dev_err(dev, "Incompatible firmware, aborting\n"); - goto out; - } - } - - if (priv->has_port3) - dev_info(dev, "Ad-hoc demo mode supported\n"); - if (priv->has_ibss) - dev_info(dev, "IEEE standard IBSS ad-hoc mode supported\n"); - if (priv->has_wep) - dev_info(dev, "WEP supported, %s-bit key\n", - priv->has_big_wep ? "104" : "40"); - if (priv->has_wpa) { - dev_info(dev, "WPA-PSK supported\n"); - if (orinoco_mic_init(priv)) { - dev_err(dev, "Failed to setup MIC crypto algorithm. " - "Disabling WPA support\n"); - priv->has_wpa = 0; - } - } - - err = orinoco_hw_read_card_settings(priv, wiphy->perm_addr); - if (err) - goto out; - - err = orinoco_hw_allocate_fid(priv); - if (err) { - dev_err(dev, "Failed to allocate NIC buffer!\n"); - goto out; - } - - /* Set up the default configuration */ - priv->iw_mode = NL80211_IFTYPE_STATION; - /* By default use IEEE/IBSS ad-hoc mode if we have it */ - priv->prefer_port3 = priv->has_port3 && (!priv->has_ibss); - set_port_type(priv); - priv->channel = 0; /* use firmware default */ - - priv->promiscuous = 0; - priv->encode_alg = ORINOCO_ALG_NONE; - priv->tx_key = 0; - priv->wpa_enabled = 0; - priv->tkip_cm_active = 0; - priv->key_mgmt = 0; - priv->wpa_ie_len = 0; - priv->wpa_ie = NULL; - - if (orinoco_wiphy_register(wiphy)) { - err = -ENODEV; - goto out; - } - - /* Make the hardware available, as long as it hasn't been - * removed elsewhere (e.g. by PCMCIA hot unplug) */ - spin_lock_irq(&priv->lock); - priv->hw_unavailable--; - spin_unlock_irq(&priv->lock); - - dev_dbg(dev, "Ready\n"); - - out: - return err; -} -EXPORT_SYMBOL(orinoco_init); - -static const struct net_device_ops orinoco_netdev_ops = { - .ndo_open = orinoco_open, - .ndo_stop = orinoco_stop, - .ndo_start_xmit = orinoco_xmit, - .ndo_set_multicast_list = orinoco_set_multicast_list, - .ndo_change_mtu = orinoco_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, - .ndo_tx_timeout = orinoco_tx_timeout, - .ndo_get_stats = orinoco_get_stats, -}; - -/* Allocate private data. - * - * This driver has a number of structures associated with it - * netdev - Net device structure for each network interface - * wiphy - structure associated with wireless phy - * wireless_dev (wdev) - structure for each wireless interface - * hw - structure for hermes chip info - * card - card specific structure for use by the card driver - * (airport, orinoco_cs) - * priv - orinoco private data - * device - generic linux device structure - * - * +---------+ +---------+ - * | wiphy | | netdev | - * | +-------+ | +-------+ - * | | priv | | | wdev | - * | | +-----+ +-+-------+ - * | | | hw | - * | +-+-----+ - * | | card | - * +-+-------+ - * - * priv has a link to netdev and device - * wdev has a link to wiphy - */ -struct orinoco_private -*alloc_orinocodev(int sizeof_card, - struct device *device, - int (*hard_reset)(struct orinoco_private *), - int (*stop_fw)(struct orinoco_private *, int)) -{ - struct orinoco_private *priv; - struct wiphy *wiphy; - - /* allocate wiphy - * NOTE: We only support a single virtual interface - * but this may change when monitor mode is added - */ - wiphy = wiphy_new(&orinoco_cfg_ops, - sizeof(struct orinoco_private) + sizeof_card); - if (!wiphy) - return NULL; - - priv = wiphy_priv(wiphy); - priv->dev = device; - - if (sizeof_card) - priv->card = (void *)((unsigned long)priv - + sizeof(struct orinoco_private)); - else - priv->card = NULL; - - orinoco_wiphy_init(wiphy); - -#ifdef WIRELESS_SPY - priv->wireless_data.spy_data = &priv->spy_data; -#endif - - /* Set up default callbacks */ - priv->hard_reset = hard_reset; - priv->stop_fw = stop_fw; - - spin_lock_init(&priv->lock); - priv->open = 0; - priv->hw_unavailable = 1; /* orinoco_init() must clear this - * before anything else touches the - * hardware */ - INIT_WORK(&priv->reset_work, orinoco_reset); - INIT_WORK(&priv->join_work, orinoco_join_ap); - INIT_WORK(&priv->wevent_work, orinoco_send_wevents); - - INIT_LIST_HEAD(&priv->rx_list); - tasklet_init(&priv->rx_tasklet, orinoco_rx_isr_tasklet, - (unsigned long) priv); - - spin_lock_init(&priv->scan_lock); - INIT_LIST_HEAD(&priv->scan_list); - INIT_WORK(&priv->process_scan, orinoco_process_scan_results); - - priv->last_linkstatus = 0xffff; - -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) - priv->cached_pri_fw = NULL; - priv->cached_fw = NULL; -#endif - - /* Register PM notifiers */ - orinoco_register_pm_notifier(priv); - - return priv; -} -EXPORT_SYMBOL(alloc_orinocodev); - -/* We can only support a single interface. We provide a separate - * function to set it up to distinguish between hardware - * initialisation and interface setup. - * - * The base_addr and irq parameters are passed on to netdev for use - * with SIOCGIFMAP. - */ -int orinoco_if_add(struct orinoco_private *priv, - unsigned long base_addr, - unsigned int irq) -{ - struct wiphy *wiphy = priv_to_wiphy(priv); - struct wireless_dev *wdev; - struct net_device *dev; - int ret; - - dev = alloc_etherdev(sizeof(struct wireless_dev)); - - if (!dev) - return -ENOMEM; - - /* Initialise wireless_dev */ - wdev = netdev_priv(dev); - wdev->wiphy = wiphy; - wdev->iftype = NL80211_IFTYPE_STATION; - - /* Setup / override net_device fields */ - dev->ieee80211_ptr = wdev; - dev->netdev_ops = &orinoco_netdev_ops; - dev->watchdog_timeo = HZ; /* 1 second timeout */ - dev->ethtool_ops = &orinoco_ethtool_ops; - dev->wireless_handlers = &orinoco_handler_def; -#ifdef WIRELESS_SPY - dev->wireless_data = &priv->wireless_data; -#endif - /* we use the default eth_mac_addr for setting the MAC addr */ - - /* Reserve space in skb for the SNAP header */ - dev->hard_header_len += ENCAPS_OVERHEAD; - - netif_carrier_off(dev); - - memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); - - dev->base_addr = base_addr; - dev->irq = irq; - - SET_NETDEV_DEV(dev, priv->dev); - ret = register_netdev(dev); - if (ret) - goto fail; - - priv->ndev = dev; - - /* Report what we've done */ - dev_dbg(priv->dev, "Registerred interface %s.\n", dev->name); - - return 0; - - fail: - free_netdev(dev); - return ret; -} -EXPORT_SYMBOL(orinoco_if_add); - -void orinoco_if_del(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - - unregister_netdev(dev); - free_netdev(dev); -} -EXPORT_SYMBOL(orinoco_if_del); - -void free_orinocodev(struct orinoco_private *priv) -{ - struct wiphy *wiphy = priv_to_wiphy(priv); - struct orinoco_rx_data *rx_data, *temp; - struct orinoco_scan_data *sd, *sdtemp; - - wiphy_unregister(wiphy); - - /* If the tasklet is scheduled when we call tasklet_kill it - * will run one final time. However the tasklet will only - * drain priv->rx_list if the hw is still available. */ - tasklet_kill(&priv->rx_tasklet); - - /* Explicitly drain priv->rx_list */ - list_for_each_entry_safe(rx_data, temp, &priv->rx_list, list) { - list_del(&rx_data->list); - - dev_kfree_skb(rx_data->skb); - kfree(rx_data->desc); - kfree(rx_data); - } - - cancel_work_sync(&priv->process_scan); - /* Explicitly drain priv->scan_list */ - list_for_each_entry_safe(sd, sdtemp, &priv->scan_list, list) { - list_del(&sd->list); - - if ((sd->len > 0) && sd->buf) - kfree(sd->buf); - kfree(sd); - } - - orinoco_unregister_pm_notifier(priv); - orinoco_uncache_fw(priv); - - priv->wpa_ie_len = 0; - kfree(priv->wpa_ie); - orinoco_mic_free(priv); - wiphy_free(wiphy); -} -EXPORT_SYMBOL(free_orinocodev); - -int orinoco_up(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - unsigned long flags; - int err; - - spin_lock_irqsave(&priv->lock, flags); - - err = orinoco_reinit_firmware(priv); - if (err) { - printk(KERN_ERR "%s: Error %d re-initializing firmware\n", - dev->name, err); - goto exit; - } - - netif_device_attach(dev); - priv->hw_unavailable--; - - if (priv->open && !priv->hw_unavailable) { - err = __orinoco_up(priv); - if (err) - printk(KERN_ERR "%s: Error %d restarting card\n", - dev->name, err); - } - -exit: - spin_unlock_irqrestore(&priv->lock, flags); - - return 0; -} -EXPORT_SYMBOL(orinoco_up); - -void orinoco_down(struct orinoco_private *priv) -{ - struct net_device *dev = priv->ndev; - unsigned long flags; - int err; - - spin_lock_irqsave(&priv->lock, flags); - err = __orinoco_down(priv); - if (err) - printk(KERN_WARNING "%s: Error %d downing interface\n", - dev->name, err); - - netif_device_detach(dev); - priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); -} -EXPORT_SYMBOL(orinoco_down); - -static void orinoco_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct orinoco_private *priv = ndev_priv(dev); - - strncpy(info->driver, DRIVER_NAME, sizeof(info->driver) - 1); - strncpy(info->version, DRIVER_VERSION, sizeof(info->version) - 1); - strncpy(info->fw_version, priv->fw_name, sizeof(info->fw_version) - 1); - if (dev->dev.parent) - strncpy(info->bus_info, dev_name(dev->dev.parent), - sizeof(info->bus_info) - 1); - else - snprintf(info->bus_info, sizeof(info->bus_info) - 1, - "PCMCIA %p", priv->hw.iobase); -} - -static const struct ethtool_ops orinoco_ethtool_ops = { - .get_drvinfo = orinoco_get_drvinfo, - .get_link = ethtool_op_get_link, -}; - -/********************************************************************/ -/* Module initialization */ -/********************************************************************/ - -/* Can't be declared "const" or the whole __initdata section will - * become const */ -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (David Gibson , " - "Pavel Roskin , et al)"; - -static int __init init_orinoco(void) -{ - printk(KERN_DEBUG "%s\n", version); - return 0; -} - -static void __exit exit_orinoco(void) -{ -} - -module_init(init_orinoco); -module_exit(exit_orinoco); diff --git a/drivers/net/wireless/orinoco/main.h b/drivers/net/wireless/orinoco/main.h deleted file mode 100644 index 21ab36cd76c7..000000000000 --- a/drivers/net/wireless/orinoco/main.h +++ /dev/null @@ -1,62 +0,0 @@ -/* Exports from main to helper modules - * - * See copyright notice in main.c - */ -#ifndef _ORINOCO_MAIN_H_ -#define _ORINOCO_MAIN_H_ - -#include -#include "orinoco.h" - -/********************************************************************/ -/* Compile time configuration and compatibility stuff */ -/********************************************************************/ - -/* We do this this way to avoid ifdefs in the actual code */ -#ifdef WIRELESS_SPY -#define SPY_NUMBER(priv) (priv->spy_data.spy_number) -#else -#define SPY_NUMBER(priv) 0 -#endif /* WIRELESS_SPY */ - -/********************************************************************/ - -/* Export module parameter */ -extern int force_monitor; - -/* Forward declarations */ -struct net_device; -struct work_struct; - -void set_port_type(struct orinoco_private *priv); -int orinoco_commit(struct orinoco_private *priv); -void orinoco_reset(struct work_struct *work); - -/* Information element helpers - find a home for these... */ -static inline u8 *orinoco_get_ie(u8 *data, size_t len, - enum ieee80211_eid eid) -{ - u8 *p = data; - while ((p + 2) < (data + len)) { - if (p[0] == eid) - return p; - p += p[1] + 2; - } - return NULL; -} - -#define WPA_OUI_TYPE "\x00\x50\xF2\x01" -#define WPA_SELECTOR_LEN 4 -static inline u8 *orinoco_get_wpa_ie(u8 *data, size_t len) -{ - u8 *p = data; - while ((p + 2 + WPA_SELECTOR_LEN) < (data + len)) { - if ((p[0] == WLAN_EID_GENERIC) && - (memcmp(&p[2], WPA_OUI_TYPE, WPA_SELECTOR_LEN) == 0)) - return p; - p += p[1] + 2; - } - return NULL; -} - -#endif /* _ORINOCO_MAIN_H_ */ diff --git a/drivers/net/wireless/orinoco/mic.c b/drivers/net/wireless/orinoco/mic.c deleted file mode 100644 index c03e7f54d1b8..000000000000 --- a/drivers/net/wireless/orinoco/mic.c +++ /dev/null @@ -1,79 +0,0 @@ -/* Orinoco MIC helpers - * - * See copyright notice in main.c - */ -#include -#include -#include -#include -#include - -#include "orinoco.h" -#include "mic.h" - -/********************************************************************/ -/* Michael MIC crypto setup */ -/********************************************************************/ -int orinoco_mic_init(struct orinoco_private *priv) -{ - priv->tx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); - if (IS_ERR(priv->tx_tfm_mic)) { - printk(KERN_DEBUG "orinoco_mic_init: could not allocate " - "crypto API michael_mic\n"); - priv->tx_tfm_mic = NULL; - return -ENOMEM; - } - - priv->rx_tfm_mic = crypto_alloc_hash("michael_mic", 0, 0); - if (IS_ERR(priv->rx_tfm_mic)) { - printk(KERN_DEBUG "orinoco_mic_init: could not allocate " - "crypto API michael_mic\n"); - priv->rx_tfm_mic = NULL; - return -ENOMEM; - } - - return 0; -} - -void orinoco_mic_free(struct orinoco_private *priv) -{ - if (priv->tx_tfm_mic) - crypto_free_hash(priv->tx_tfm_mic); - if (priv->rx_tfm_mic) - crypto_free_hash(priv->rx_tfm_mic); -} - -int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, - u8 *da, u8 *sa, u8 priority, - u8 *data, size_t data_len, u8 *mic) -{ - struct hash_desc desc; - struct scatterlist sg[2]; - u8 hdr[ETH_HLEN + 2]; /* size of header + padding */ - - if (tfm_michael == NULL) { - printk(KERN_WARNING "orinoco_mic: tfm_michael == NULL\n"); - return -1; - } - - /* Copy header into buffer. We need the padding on the end zeroed */ - memcpy(&hdr[0], da, ETH_ALEN); - memcpy(&hdr[ETH_ALEN], sa, ETH_ALEN); - hdr[ETH_ALEN*2] = priority; - hdr[ETH_ALEN*2+1] = 0; - hdr[ETH_ALEN*2+2] = 0; - hdr[ETH_ALEN*2+3] = 0; - - /* Use scatter gather to MIC header and data in one go */ - sg_init_table(sg, 2); - sg_set_buf(&sg[0], hdr, sizeof(hdr)); - sg_set_buf(&sg[1], data, data_len); - - if (crypto_hash_setkey(tfm_michael, key, MIC_KEYLEN)) - return -1; - - desc.tfm = tfm_michael; - desc.flags = 0; - return crypto_hash_digest(&desc, sg, data_len + sizeof(hdr), - mic); -} diff --git a/drivers/net/wireless/orinoco/mic.h b/drivers/net/wireless/orinoco/mic.h deleted file mode 100644 index 04d05bc566d6..000000000000 --- a/drivers/net/wireless/orinoco/mic.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Orinoco MIC helpers - * - * See copyright notice in main.c - */ -#ifndef _ORINOCO_MIC_H_ -#define _ORINOCO_MIC_H_ - -#include - -#define MICHAEL_MIC_LEN 8 - -/* Forward declarations */ -struct orinoco_private; -struct crypto_hash; - -int orinoco_mic_init(struct orinoco_private *priv); -void orinoco_mic_free(struct orinoco_private *priv); -int orinoco_mic(struct crypto_hash *tfm_michael, u8 *key, - u8 *da, u8 *sa, u8 priority, - u8 *data, size_t data_len, u8 *mic); - -#endif /* ORINOCO_MIC_H */ diff --git a/drivers/net/wireless/orinoco/orinoco.h b/drivers/net/wireless/orinoco/orinoco.h deleted file mode 100644 index 9ac6f1dda4b0..000000000000 --- a/drivers/net/wireless/orinoco/orinoco.h +++ /dev/null @@ -1,227 +0,0 @@ -/* orinoco.h - * - * Common definitions to all pieces of the various orinoco - * drivers - */ - -#ifndef _ORINOCO_H -#define _ORINOCO_H - -#define DRIVER_VERSION "0.15" - -#include -#include -#include -#include -#include -#include - -#include "hermes.h" - -/* To enable debug messages */ -/*#define ORINOCO_DEBUG 3*/ - -#define WIRELESS_SPY /* enable iwspy support */ - -#define MAX_SCAN_LEN 4096 - -#define ORINOCO_SEQ_LEN 8 -#define ORINOCO_MAX_KEY_SIZE 14 -#define ORINOCO_MAX_KEYS 4 - -struct orinoco_key { - __le16 len; /* always stored as little-endian */ - char data[ORINOCO_MAX_KEY_SIZE]; -} __attribute__ ((packed)); - -#define TKIP_KEYLEN 16 -#define MIC_KEYLEN 8 - -struct orinoco_tkip_key { - u8 tkip[TKIP_KEYLEN]; - u8 tx_mic[MIC_KEYLEN]; - u8 rx_mic[MIC_KEYLEN]; -}; - -enum orinoco_alg { - ORINOCO_ALG_NONE, - ORINOCO_ALG_WEP, - ORINOCO_ALG_TKIP -}; - -typedef enum { - FIRMWARE_TYPE_AGERE, - FIRMWARE_TYPE_INTERSIL, - FIRMWARE_TYPE_SYMBOL -} fwtype_t; - -struct firmware; - -struct orinoco_private { - void *card; /* Pointer to card dependent structure */ - struct device *dev; - int (*hard_reset)(struct orinoco_private *); - int (*stop_fw)(struct orinoco_private *, int); - - struct ieee80211_supported_band band; - struct ieee80211_channel channels[14]; - u32 cipher_suites[3]; - - /* Synchronisation stuff */ - spinlock_t lock; - int hw_unavailable; - struct work_struct reset_work; - - /* Interrupt tasklets */ - struct tasklet_struct rx_tasklet; - struct list_head rx_list; - - /* driver state */ - int open; - u16 last_linkstatus; - struct work_struct join_work; - struct work_struct wevent_work; - - /* Net device stuff */ - struct net_device *ndev; - struct net_device_stats stats; - struct iw_statistics wstats; - - /* Hardware control variables */ - hermes_t hw; - u16 txfid; - - /* Capabilities of the hardware/firmware */ - fwtype_t firmware_type; - char fw_name[32]; - int ibss_port; - int nicbuf_size; - u16 channel_mask; - - /* Boolean capabilities */ - unsigned int has_ibss:1; - unsigned int has_port3:1; - unsigned int has_wep:1; - unsigned int has_big_wep:1; - unsigned int has_mwo:1; - unsigned int has_pm:1; - unsigned int has_preamble:1; - unsigned int has_sensitivity:1; - unsigned int has_hostscan:1; - unsigned int has_alt_txcntl:1; - unsigned int has_ext_scan:1; - unsigned int has_wpa:1; - unsigned int do_fw_download:1; - unsigned int broken_disableport:1; - unsigned int broken_monitor:1; - unsigned int prefer_port3:1; - - /* Configuration paramaters */ - enum nl80211_iftype iw_mode; - enum orinoco_alg encode_alg; - u16 wep_restrict, tx_key; - struct key_params keys[ORINOCO_MAX_KEYS]; - - int bitratemode; - char nick[IW_ESSID_MAX_SIZE+1]; - char desired_essid[IW_ESSID_MAX_SIZE+1]; - char desired_bssid[ETH_ALEN]; - int bssid_fixed; - u16 frag_thresh, mwo_robust; - u16 channel; - u16 ap_density, rts_thresh; - u16 pm_on, pm_mcast, pm_period, pm_timeout; - u16 preamble; -#ifdef WIRELESS_SPY - struct iw_spy_data spy_data; /* iwspy support */ - struct iw_public_data wireless_data; -#endif - - /* Configuration dependent variables */ - int port_type, createibss; - int promiscuous, mc_count; - - /* Scanning support */ - struct cfg80211_scan_request *scan_request; - struct work_struct process_scan; - struct list_head scan_list; - spinlock_t scan_lock; /* protects the scan list */ - - /* WPA support */ - u8 *wpa_ie; - int wpa_ie_len; - - struct crypto_hash *rx_tfm_mic; - struct crypto_hash *tx_tfm_mic; - - unsigned int wpa_enabled:1; - unsigned int tkip_cm_active:1; - unsigned int key_mgmt:3; - -#if defined(CONFIG_HERMES_CACHE_FW_ON_INIT) || defined(CONFIG_PM_SLEEP) - /* Cached in memory firmware to use during ->resume. */ - const struct firmware *cached_pri_fw; - const struct firmware *cached_fw; -#endif - - struct notifier_block pm_notifier; -}; - -#ifdef ORINOCO_DEBUG -extern int orinoco_debug; -#define DEBUG(n, args...) do { \ - if (orinoco_debug > (n)) \ - printk(KERN_DEBUG args); \ -} while (0) -#else -#define DEBUG(n, args...) do { } while (0) -#endif /* ORINOCO_DEBUG */ - -/********************************************************************/ -/* Exported prototypes */ -/********************************************************************/ - -extern struct orinoco_private *alloc_orinocodev( - int sizeof_card, struct device *device, - int (*hard_reset)(struct orinoco_private *), - int (*stop_fw)(struct orinoco_private *, int)); -extern void free_orinocodev(struct orinoco_private *priv); -extern int orinoco_init(struct orinoco_private *priv); -extern int orinoco_if_add(struct orinoco_private *priv, - unsigned long base_addr, - unsigned int irq); -extern void orinoco_if_del(struct orinoco_private *priv); -extern int orinoco_up(struct orinoco_private *priv); -extern void orinoco_down(struct orinoco_private *priv); -extern irqreturn_t orinoco_interrupt(int irq, void *dev_id); - -/********************************************************************/ -/* Locking and synchronization functions */ -/********************************************************************/ - -static inline int orinoco_lock(struct orinoco_private *priv, - unsigned long *flags) -{ - spin_lock_irqsave(&priv->lock, *flags); - if (priv->hw_unavailable) { - DEBUG(1, "orinoco_lock() called with hw_unavailable (dev=%p)\n", - priv->ndev); - spin_unlock_irqrestore(&priv->lock, *flags); - return -EBUSY; - } - return 0; -} - -static inline void orinoco_unlock(struct orinoco_private *priv, - unsigned long *flags) -{ - spin_unlock_irqrestore(&priv->lock, *flags); -} - -/*** Navigate from net_device to orinoco_private ***/ -static inline struct orinoco_private *ndev_priv(struct net_device *dev) -{ - struct wireless_dev *wdev = netdev_priv(dev); - return wdev_priv(wdev); -} -#endif /* _ORINOCO_H */ diff --git a/drivers/net/wireless/orinoco/orinoco_cs.c b/drivers/net/wireless/orinoco/orinoco_cs.c deleted file mode 100644 index 38c1c9d2abb8..000000000000 --- a/drivers/net/wireless/orinoco/orinoco_cs.c +++ /dev/null @@ -1,499 +0,0 @@ -/* orinoco_cs.c (formerly known as dldwd_cs.c) - * - * A driver for "Hermes" chipset based PCMCIA wireless adaptors, such - * as the Lucent WavelanIEEE/Orinoco cards and their OEM (Cabletron/ - * EnteraSys RoamAbout 802.11, ELSA Airlancer, Melco Buffalo and others). - * It should also be usable on various Prism II based cards such as the - * Linksys, D-Link and Farallon Skyline. It should also work on Symbol - * cards such as the 3Com AirConnect and Ericsson WLAN. - * - * Copyright notice & release notes in file main.c - */ - -#define DRIVER_NAME "orinoco_cs" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "orinoco.h" - -/********************************************************************/ -/* Module stuff */ -/********************************************************************/ - -MODULE_AUTHOR("David Gibson "); -MODULE_DESCRIPTION("Driver for PCMCIA Lucent Orinoco," - " Prism II based and similar wireless cards"); -MODULE_LICENSE("Dual MPL/GPL"); - -/* Module parameters */ - -/* Some D-Link cards have buggy CIS. They do work at 5v properly, but - * don't have any CIS entry for it. This workaround it... */ -static int ignore_cis_vcc; /* = 0 */ -module_param(ignore_cis_vcc, int, 0); -MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); - -/********************************************************************/ -/* Data structures */ -/********************************************************************/ - -/* PCMCIA specific device information (goes in the card field of - * struct orinoco_private */ -struct orinoco_pccard { - struct pcmcia_device *p_dev; - dev_node_t node; - - /* Used to handle hard reset */ - /* yuck, we need this hack to work around the insanity of the - * PCMCIA layer */ - unsigned long hard_reset_in_progress; -}; - - -/********************************************************************/ -/* Function prototypes */ -/********************************************************************/ - -static int orinoco_cs_config(struct pcmcia_device *link); -static void orinoco_cs_release(struct pcmcia_device *link); -static void orinoco_cs_detach(struct pcmcia_device *p_dev); - -/********************************************************************/ -/* Device methods */ -/********************************************************************/ - -static int -orinoco_cs_hard_reset(struct orinoco_private *priv) -{ - struct orinoco_pccard *card = priv->card; - struct pcmcia_device *link = card->p_dev; - int err; - - /* We need atomic ops here, because we're not holding the lock */ - set_bit(0, &card->hard_reset_in_progress); - - err = pcmcia_reset_card(link->socket); - if (err) - return err; - - msleep(100); - clear_bit(0, &card->hard_reset_in_progress); - - return 0; -} - -/********************************************************************/ -/* PCMCIA stuff */ -/********************************************************************/ - -/* - * This creates an "instance" of the driver, allocating local data - * structures for one device. The device is registered with Card - * Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a card - * insertion event. */ -static int -orinoco_cs_probe(struct pcmcia_device *link) -{ - struct orinoco_private *priv; - struct orinoco_pccard *card; - - priv = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), - orinoco_cs_hard_reset, NULL); - if (!priv) - return -ENOMEM; - card = priv->card; - - /* Link both structures together */ - card->p_dev = link; - link->priv = priv; - - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = orinoco_interrupt; - link->irq.Instance = priv; - - /* General socket configuration defaults can go here. In this - * client, we assume very little, and rely on the CIS for - * almost everything. In most clients, many details (i.e., - * number, sizes, and attributes of IO windows) are fixed by - * the nature of the device, and can be hard-wired here. */ - link->conf.Attributes = 0; - link->conf.IntType = INT_MEMORY_AND_IO; - - return orinoco_cs_config(link); -} /* orinoco_cs_attach */ - -/* - * This deletes a driver "instance". The device is de-registered with - * Card Services. If it has been released, all local data structures - * are freed. Otherwise, the structures will be freed when the device - * is released. - */ -static void orinoco_cs_detach(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - - if (link->dev_node) - orinoco_if_del(priv); - - orinoco_cs_release(link); - - free_orinocodev(priv); -} /* orinoco_cs_detach */ - -/* - * orinoco_cs_config() is scheduled to run after a CARD_INSERTION - * event is received, to configure the PCMCIA socket, and to make the - * device available to the system. - */ - -#define CS_CHECK(fn, ret) do { \ - last_fn = (fn); \ - if ((last_ret = (ret)) != 0) \ - goto cs_failed; \ -} while (0) - -static int orinoco_cs_config_check(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) -{ - if (cfg->index == 0) - goto next_entry; - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { - DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", - __func__, vcc, - cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); - if (!ignore_cis_vcc) - goto next_entry; - } - } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { - DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", - __func__, vcc, - dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); - if (!ignore_cis_vcc) - goto next_entry; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = - cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; - else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = - dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; - - /* Do we need to allocate an interrupt? */ - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; - } - - /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) - goto next_entry; - } - return 0; - -next_entry: - pcmcia_disable_device(p_dev); - return -ENODEV; -}; - -static int -orinoco_cs_config(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - struct orinoco_pccard *card = priv->card; - hermes_t *hw = &priv->hw; - int last_fn, last_ret; - void __iomem *mem; - - /* - * In this loop, we scan the CIS for configuration table - * entries, each of which describes a valid card - * configuration, including voltage, IO window, memory window, - * and interrupt settings. - * - * We make no assumptions about the card to be configured: we - * use just the information available in the CIS. In an ideal - * world, this would work for any PCMCIA card, but it requires - * a complete and accurate CIS. In practice, a driver usually - * "knows" most of these things without consulting the CIS, - * and most client drivers will only use the CIS to fill in - * implementation-defined details. - */ - last_ret = pcmcia_loop_config(link, orinoco_cs_config_check, NULL); - if (last_ret) { - if (!ignore_cis_vcc) - printk(KERN_ERR PFX "GetNextTuple(): No matching " - "CIS configuration. Maybe you need the " - "ignore_cis_vcc=1 parameter.\n"); - cs_error(link, RequestIO, last_ret); - goto failed; - } - - /* - * Allocate an interrupt line. Note that this does not assign - * a handler to the interrupt, unless the 'Handler' member of - * the irq structure is initialized. - */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - - /* We initialize the hermes structure before completing PCMCIA - * configuration just in case the interrupt handler gets - * called. */ - mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); - if (!mem) - goto cs_failed; - - hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping, and putting the - * card and host interface into "Memory and IO" mode. - */ - CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link, &link->conf)); - - /* Ok, we have the configuration, prepare to register the netdev */ - card->node.major = card->node.minor = 0; - - /* Initialise the main driver */ - if (orinoco_init(priv) != 0) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto failed; - } - - /* Register an interface with the stack */ - if (orinoco_if_add(priv, link->io.BasePort1, - link->irq.AssignedIRQ) != 0) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto failed; - } - - /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev_node. */ - strcpy(card->node.dev_name, priv->ndev->name); - link->dev_node = &card->node; /* link->dev_node being non-NULL is also - * used to indicate that the - * net_device has been registered */ - return 0; - - cs_failed: - cs_error(link, last_fn, last_ret); - - failed: - orinoco_cs_release(link); - return -ENODEV; -} /* orinoco_cs_config */ - -/* - * After a card is removed, orinoco_cs_release() will unregister the - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void -orinoco_cs_release(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - unsigned long flags; - - /* We're committed to taking the device away now, so mark the - * hardware as unavailable */ - spin_lock_irqsave(&priv->lock, flags); - priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); - - pcmcia_disable_device(link); - if (priv->hw.iobase) - ioport_unmap(priv->hw.iobase); -} /* orinoco_cs_release */ - -static int orinoco_cs_suspend(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - struct orinoco_pccard *card = priv->card; - - /* This is probably racy, but I can't think of - a better way, short of rewriting the PCMCIA - layer to not suck :-( */ - if (!test_bit(0, &card->hard_reset_in_progress)) - orinoco_down(priv); - - return 0; -} - -static int orinoco_cs_resume(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - struct orinoco_pccard *card = priv->card; - int err = 0; - - if (!test_bit(0, &card->hard_reset_in_progress)) - err = orinoco_up(priv); - - return err; -} - - -/********************************************************************/ -/* Module initialization */ -/********************************************************************/ - -/* Can't be declared "const" or the whole __initdata section will - * become const */ -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (David Gibson , " - "Pavel Roskin , et al)"; - -static struct pcmcia_device_id orinoco_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7100), /* SonicWALL Long Range Wireless Card */ - PCMCIA_DEVICE_MANF_CARD(0x000b, 0x7300), /* Sohoware NCP110, Philips 802.11b */ - PCMCIA_DEVICE_MANF_CARD(0x0089, 0x0002), /* AnyPoint(TM) Wireless II PC Card */ - PCMCIA_DEVICE_MANF_CARD(0x0101, 0x0777), /* 3Com AirConnect PCI 777A */ - PCMCIA_DEVICE_MANF_CARD(0x0126, 0x8000), /* PROXIM RangeLAN-DS/LAN PC CARD */ - PCMCIA_DEVICE_MANF_CARD(0x0138, 0x0002), /* Compaq WL100 11 Mbps Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x0156, 0x0002), /* Lucent Orinoco and old Intersil */ - PCMCIA_DEVICE_MANF_CARD(0x016b, 0x0001), /* Ericsson WLAN Card C11 */ - PCMCIA_DEVICE_MANF_CARD(0x01eb, 0x080a), /* Nortel Networks eMobility 802.11 Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x01ff, 0x0008), /* Intermec MobileLAN 11Mbps 802.11b WLAN Card */ - PCMCIA_DEVICE_MANF_CARD(0x0250, 0x0002), /* Samsung SWL2000-N 11Mb/s WLAN Card */ - PCMCIA_DEVICE_MANF_CARD(0x0261, 0x0002), /* AirWay 802.11 Adapter (PCMCIA) */ - PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0001), /* ARtem Onair */ - PCMCIA_DEVICE_MANF_CARD(0x0268, 0x0003), /* ARtem Onair Comcard 11 */ - PCMCIA_DEVICE_MANF_CARD(0x026f, 0x0305), /* Buffalo WLI-PCM-S11 */ - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1612), /* Linksys WPC11 Version 2.5 */ - PCMCIA_DEVICE_MANF_CARD(0x0274, 0x1613), /* Linksys WPC11 Version 3 */ - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0002), /* Compaq HNW-100 11 Mbps Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x028a, 0x0673), /* Linksys WCF12 Wireless CompactFlash Card */ - PCMCIA_DEVICE_MANF_CARD(0x02aa, 0x0002), /* ASUS SpaceLink WL-100 */ - PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x0002), /* SpeedStream SS1021 Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x02ac, 0x3021), /* SpeedStream Wireless Adapter */ - PCMCIA_DEVICE_MANF_CARD(0x14ea, 0xb001), /* PLANEX RoadLannerWave GW-NS11H */ - PCMCIA_DEVICE_MANF_CARD(0x50c2, 0x7300), /* Airvast WN-100 */ - PCMCIA_DEVICE_MANF_CARD(0x9005, 0x0021), /* Adaptec Ultra Wireless ANW-8030 */ - PCMCIA_DEVICE_MANF_CARD(0xc001, 0x0008), /* CONTEC FLEXSCAN/FX-DDS110-PCC */ - PCMCIA_DEVICE_MANF_CARD(0xc250, 0x0002), /* Conceptronic CON11Cpro, EMTAC A2424i */ - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0002), /* Safeway 802.11b, ZCOMAX AirRunner/XI-300 */ - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0005), /* D-Link DCF660, Sandisk Connect SDWCFB-000 */ - PCMCIA_DEVICE_PROD_ID12(" ", "IEEE 802.11 Wireless LAN/PC Card", 0x3b6e20c8, 0xefccafe9), - PCMCIA_DEVICE_PROD_ID12("3Com", "3CRWE737A AirConnect Wireless LAN PC Card", 0x41240e5b, 0x56010af3), - PCMCIA_DEVICE_PROD_ID12("ACTIONTEC", "PRISM Wireless LAN PC Card", 0x393089da, 0xa71e69d5), - PCMCIA_DEVICE_PROD_ID12("Addtron", "AWP-100 Wireless PCMCIA", 0xe6ec52ce, 0x08649af2), - PCMCIA_DEVICE_PROD_ID123("AIRVAST", "IEEE 802.11b Wireless PCMCIA Card", "HFA3863", 0xea569531, 0x4bcb9645, 0x355cb092), - PCMCIA_DEVICE_PROD_ID12("Allied Telesyn", "AT-WCL452 Wireless PCMCIA Radio", 0x5cd01705, 0x4271660f), - PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11b_PC_CARD_25", 0x78fc06ee, 0xdb9aa842), - PCMCIA_DEVICE_PROD_ID12("ASUS", "802_11B_CF_CARD_25", 0x78fc06ee, 0x45a50c1e), - PCMCIA_DEVICE_PROD_ID12("Avaya Communication", "Avaya Wireless PC Card", 0xd8a43b78, 0x0d341169), - PCMCIA_DEVICE_PROD_ID12("BENQ", "AWL100 PCMCIA ADAPTER", 0x35dadc74, 0x01f7fedb), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-PCM-L11G", 0x2decece3, 0xf57ca4b3), - PCMCIA_DEVICE_PROD_ID12("BUFFALO", "WLI-CF-S11G", 0x2decece3, 0x82067c18), - PCMCIA_DEVICE_PROD_ID12("Cabletron", "RoamAbout 802.11 DS", 0x32d445f5, 0xedeffd90), - PCMCIA_DEVICE_PROD_ID12("Compaq", "WL200_11Mbps_Wireless_PCI_Card", 0x54f7c49c, 0x15a75e5b), - PCMCIA_DEVICE_PROD_ID123("corega", "WL PCCL-11", "ISL37300P", 0x0a21501a, 0x59868926, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCC-11", 0x5261440f, 0xa6405584), - PCMCIA_DEVICE_PROD_ID12("corega K.K.", "Wireless LAN PCCA-11", 0x5261440f, 0xdf6115f9), - PCMCIA_DEVICE_PROD_ID12("corega_K.K.", "Wireless_LAN_PCCB-11", 0x29e33311, 0xee7a27ae), - PCMCIA_DEVICE_PROD_ID12("D", "Link DRC-650 11Mbps WLAN Card", 0x71b18589, 0xf144e3ac), - PCMCIA_DEVICE_PROD_ID12("D", "Link DWL-650 11Mbps WLAN Card", 0x71b18589, 0xb6f1b0ab), - PCMCIA_DEVICE_PROD_ID12("D-Link Corporation", "D-Link DWL-650H 11Mbps WLAN Adapter", 0xef544d24, 0xcd8ea916), - PCMCIA_DEVICE_PROD_ID12("Digital Data Communications", "WPC-0100", 0xfdd73470, 0xe0b6f146), - PCMCIA_DEVICE_PROD_ID12("ELSA", "AirLancer MC-11", 0x4507a33a, 0xef54f0e3), - PCMCIA_DEVICE_PROD_ID12("HyperLink", "Wireless PC Card 11Mbps", 0x56cc3f1a, 0x0bcf220c), - PCMCIA_DEVICE_PROD_ID123("Instant Wireless ", " Network PC CARD", "Version 01.02", 0x11d901af, 0x6e9bd926, 0x4b74baa0), - PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless 2011 LAN PC Card", 0x816cc815, 0x07f58077), - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "HFA384x/IEEE", 0x74c5e40d, 0xdb472a18), - PCMCIA_DEVICE_PROD_ID12("INTERSIL", "I-GATE 11M PC Card / PC Card plus", 0x74c5e40d, 0x8304ff77), - PCMCIA_DEVICE_PROD_ID12("Intersil", "PRISM 2_5 PCMCIA ADAPTER", 0x4b801a17, 0x6345a0bf), - PCMCIA_DEVICE_PROD_ID123("Intersil", "PRISM Freedom PCMCIA Adapter", "ISL37100P", 0x4b801a17, 0xf222ec2d, 0x630d52b2), - PCMCIA_DEVICE_PROD_ID12("LeArtery", "SYNCBYAIR 11Mbps Wireless LAN PC Card", 0x7e3b326a, 0x49893e92), - PCMCIA_DEVICE_PROD_ID12("Linksys", "Wireless CompactFlash Card", 0x0733cc81, 0x0c52f395), - PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/IEEE", 0x23eb9949, 0xc562e72a), - PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11", 0x481e0094, 0x7360e410), - PCMCIA_DEVICE_PROD_ID12("MELCO", "WLI-PCM-L11G", 0x481e0094, 0xf57ca4b3), - PCMCIA_DEVICE_PROD_ID12("Microsoft", "Wireless Notebook Adapter MN-520", 0x5961bf85, 0x6eec8c01), - PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/IEEE", 0x24358cd4, 0xc562e72a), - PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401 Wireless PC", "Card", 0xa37434e9, 0x9762e8f1), - PCMCIA_DEVICE_PROD_ID12("NETGEAR MA401RA Wireless PC", "Card", 0x0306467f, 0x9762e8f1), - PCMCIA_DEVICE_PROD_ID12("Nortel Networks", "emobility 802.11 Wireless LAN PC Card", 0x2d617ea0, 0x88cd5767), - PCMCIA_DEVICE_PROD_ID12("OEM", "PRISM2 IEEE 802.11 PC-Card", 0xfea54c90, 0x48f2bdd6), - PCMCIA_DEVICE_PROD_ID12("OTC", "Wireless AirEZY 2411-PCC WLAN Card", 0x4ac44287, 0x235a6bed), - PCMCIA_DEVICE_PROD_ID123("PCMCIA", "11M WLAN Card v2.5", "ISL37300P", 0x281f1c5d, 0x6e440487, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-CF110", 0x209f40ab, 0xd9715264), - PCMCIA_DEVICE_PROD_ID12("PLANEX", "GeoWave/GW-NS110", 0x209f40ab, 0x46263178), - PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PC CARD HARMONY 80211B", 0xc6536a5e, 0x090c3cd9), - PCMCIA_DEVICE_PROD_ID12("PROXIM", "LAN PCI CARD HARMONY 80211B", 0xc6536a5e, 0x9f494e26), - PCMCIA_DEVICE_PROD_ID12("SAMSUNG", "11Mbps WLAN Card", 0x43d74cb4, 0x579bd91b), - PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2532W-B EliteConnect Wireless Adapter", 0xc4f8b18b, 0x196bd757), - PCMCIA_DEVICE_PROD_ID12("SMC", "SMC2632W", 0xc4f8b18b, 0x474a1f2a), - PCMCIA_DEVICE_PROD_ID12("Symbol Technologies", "LA4111 Spectrum24 Wireless LAN PC Card", 0x3f02b4d6, 0x3663cb0e), - PCMCIA_DEVICE_PROD_ID123("The Linksys Group, Inc.", "Instant Wireless Network PC Card", "ISL37300P", 0xa5f472c2, 0x590eb502, 0xc9049a39), - PCMCIA_DEVICE_PROD_ID12("ZoomAir 11Mbps High", "Rate wireless Networking", 0x273fe3db, 0x32a1eaee), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, orinoco_cs_ids); - -static struct pcmcia_driver orinoco_driver = { - .owner = THIS_MODULE, - .drv = { - .name = DRIVER_NAME, - }, - .probe = orinoco_cs_probe, - .remove = orinoco_cs_detach, - .id_table = orinoco_cs_ids, - .suspend = orinoco_cs_suspend, - .resume = orinoco_cs_resume, -}; - -static int __init -init_orinoco_cs(void) -{ - printk(KERN_DEBUG "%s\n", version); - - return pcmcia_register_driver(&orinoco_driver); -} - -static void __exit -exit_orinoco_cs(void) -{ - pcmcia_unregister_driver(&orinoco_driver); -} - -module_init(init_orinoco_cs); -module_exit(exit_orinoco_cs); diff --git a/drivers/net/wireless/orinoco/orinoco_nortel.c b/drivers/net/wireless/orinoco/orinoco_nortel.c deleted file mode 100644 index c13a4c383410..000000000000 --- a/drivers/net/wireless/orinoco/orinoco_nortel.c +++ /dev/null @@ -1,323 +0,0 @@ -/* orinoco_nortel.c - * - * Driver for Prism II devices which would usually be driven by orinoco_cs, - * but are connected to the PCI bus by a PCI-to-PCMCIA adapter used in - * Nortel emobility, Symbol LA-4113 and Symbol LA-4123. - * - * Copyright (C) 2002 Tobias Hoffmann - * (C) 2003 Christoph Jungegger - * - * Some of this code is borrowed from orinoco_plx.c - * Copyright (C) 2001 Daniel Barlow - * Some of this code is borrowed from orinoco_pci.c - * Copyright (C) 2001 Jean Tourrilhes - * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing - * has been copied from it. linux-wlan-ng-0.1.10 is originally : - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - */ - -#define DRIVER_NAME "orinoco_nortel" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include -#include - -#include "orinoco.h" -#include "orinoco_pci.h" - -#define COR_OFFSET (0xe0) /* COR attribute offset of Prism2 PC card */ -#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ - - -/* - * Do a soft reset of the card using the Configuration Option Register - * We need this to get going... - * This is the part of the code that is strongly inspired from wlan-ng - * - * Note bis : Don't try to access HERMES_CMD during the reset phase. - * It just won't work ! - */ -static int orinoco_nortel_cor_reset(struct orinoco_private *priv) -{ - struct orinoco_pci_card *card = priv->card; - - /* Assert the reset until the card notices */ - iowrite16(8, card->bridge_io + 2); - ioread16(card->attr_io + COR_OFFSET); - iowrite16(0x80, card->attr_io + COR_OFFSET); - mdelay(1); - - /* Give time for the card to recover from this hard effort */ - iowrite16(0, card->attr_io + COR_OFFSET); - iowrite16(0, card->attr_io + COR_OFFSET); - mdelay(1); - - /* Set COR as usual */ - iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); - iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); - mdelay(1); - - iowrite16(0x228, card->bridge_io + 2); - - return 0; -} - -static int orinoco_nortel_hw_init(struct orinoco_pci_card *card) -{ - int i; - u32 reg; - - /* Setup bridge */ - if (ioread16(card->bridge_io) & 1) { - printk(KERN_ERR PFX "brg1 answer1 wrong\n"); - return -EBUSY; - } - iowrite16(0x118, card->bridge_io + 2); - iowrite16(0x108, card->bridge_io + 2); - mdelay(30); - iowrite16(0x8, card->bridge_io + 2); - for (i = 0; i < 30; i++) { - mdelay(30); - if (ioread16(card->bridge_io) & 0x10) - break; - } - if (i == 30) { - printk(KERN_ERR PFX "brg1 timed out\n"); - return -EBUSY; - } - if (ioread16(card->attr_io + COR_OFFSET) & 1) { - printk(KERN_ERR PFX "brg2 answer1 wrong\n"); - return -EBUSY; - } - if (ioread16(card->attr_io + COR_OFFSET + 2) & 1) { - printk(KERN_ERR PFX "brg2 answer2 wrong\n"); - return -EBUSY; - } - if (ioread16(card->attr_io + COR_OFFSET + 4) & 1) { - printk(KERN_ERR PFX "brg2 answer3 wrong\n"); - return -EBUSY; - } - - /* Set the PCMCIA COR register */ - iowrite16(COR_VALUE, card->attr_io + COR_OFFSET); - mdelay(1); - reg = ioread16(card->attr_io + COR_OFFSET); - if (reg != COR_VALUE) { - printk(KERN_ERR PFX "Error setting COR value (reg=%x)\n", - reg); - return -EBUSY; - } - - /* Set LEDs */ - iowrite16(1, card->bridge_io + 10); - return 0; -} - -static int orinoco_nortel_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int err; - struct orinoco_private *priv; - struct orinoco_pci_card *card; - void __iomem *hermes_io, *bridge_io, *attr_io; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Cannot enable PCI device\n"); - return err; - } - - err = pci_request_regions(pdev, DRIVER_NAME); - if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); - goto fail_resources; - } - - bridge_io = pci_iomap(pdev, 0, 0); - if (!bridge_io) { - printk(KERN_ERR PFX "Cannot map bridge registers\n"); - err = -EIO; - goto fail_map_bridge; - } - - attr_io = pci_iomap(pdev, 1, 0); - if (!attr_io) { - printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); - err = -EIO; - goto fail_map_attr; - } - - hermes_io = pci_iomap(pdev, 2, 0); - if (!hermes_io) { - printk(KERN_ERR PFX "Cannot map chipset registers\n"); - err = -EIO; - goto fail_map_hermes; - } - - /* Allocate network device */ - priv = alloc_orinocodev(sizeof(*card), &pdev->dev, - orinoco_nortel_cor_reset, NULL); - if (!priv) { - printk(KERN_ERR PFX "Cannot allocate network device\n"); - err = -ENOMEM; - goto fail_alloc; - } - - card = priv->card; - card->bridge_io = bridge_io; - card->attr_io = attr_io; - - hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); - - err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, - DRIVER_NAME, priv); - if (err) { - printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); - err = -EBUSY; - goto fail_irq; - } - - err = orinoco_nortel_hw_init(card); - if (err) { - printk(KERN_ERR PFX "Hardware initialization failed\n"); - goto fail; - } - - err = orinoco_nortel_cor_reset(priv); - if (err) { - printk(KERN_ERR PFX "Initial reset failed\n"); - goto fail; - } - - err = orinoco_init(priv); - if (err) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto fail; - } - - err = orinoco_if_add(priv, 0, 0); - if (err) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto fail; - } - - pci_set_drvdata(pdev, priv); - - return 0; - - fail: - free_irq(pdev->irq, priv); - - fail_irq: - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - - fail_alloc: - pci_iounmap(pdev, hermes_io); - - fail_map_hermes: - pci_iounmap(pdev, attr_io); - - fail_map_attr: - pci_iounmap(pdev, bridge_io); - - fail_map_bridge: - pci_release_regions(pdev); - - fail_resources: - pci_disable_device(pdev); - - return err; -} - -static void __devexit orinoco_nortel_remove_one(struct pci_dev *pdev) -{ - struct orinoco_private *priv = pci_get_drvdata(pdev); - struct orinoco_pci_card *card = priv->card; - - /* Clear LEDs */ - iowrite16(0, card->bridge_io + 10); - - orinoco_if_del(priv); - free_irq(pdev->irq, priv); - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - pci_iounmap(pdev, priv->hw.iobase); - pci_iounmap(pdev, card->attr_io); - pci_iounmap(pdev, card->bridge_io); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -static struct pci_device_id orinoco_nortel_id_table[] = { - /* Nortel emobility PCI */ - {0x126c, 0x8030, PCI_ANY_ID, PCI_ANY_ID,}, - /* Symbol LA-4123 PCI */ - {0x1562, 0x0001, PCI_ANY_ID, PCI_ANY_ID,}, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, orinoco_nortel_id_table); - -static struct pci_driver orinoco_nortel_driver = { - .name = DRIVER_NAME, - .id_table = orinoco_nortel_id_table, - .probe = orinoco_nortel_init_one, - .remove = __devexit_p(orinoco_nortel_remove_one), - .suspend = orinoco_pci_suspend, - .resume = orinoco_pci_resume, -}; - -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Tobias Hoffmann & Christoph Jungegger )"; -MODULE_AUTHOR("Christoph Jungegger "); -MODULE_DESCRIPTION - ("Driver for wireless LAN cards using the Nortel PCI bridge"); -MODULE_LICENSE("Dual MPL/GPL"); - -static int __init orinoco_nortel_init(void) -{ - printk(KERN_DEBUG "%s\n", version); - return pci_register_driver(&orinoco_nortel_driver); -} - -static void __exit orinoco_nortel_exit(void) -{ - pci_unregister_driver(&orinoco_nortel_driver); -} - -module_init(orinoco_nortel_init); -module_exit(orinoco_nortel_exit); - -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/wireless/orinoco/orinoco_pci.c b/drivers/net/wireless/orinoco/orinoco_pci.c deleted file mode 100644 index fea7781948e7..000000000000 --- a/drivers/net/wireless/orinoco/orinoco_pci.c +++ /dev/null @@ -1,265 +0,0 @@ -/* orinoco_pci.c - * - * Driver for Prism 2.5/3 devices that have a direct PCI interface - * (i.e. these are not PCMCIA cards in a PCMCIA-to-PCI bridge). - * The card contains only one PCI region, which contains all the usual - * hermes registers, as well as the COR register. - * - * Current maintainers are: - * Pavel Roskin - * and David Gibson - * - * Some of this code is borrowed from orinoco_plx.c - * Copyright (C) 2001 Daniel Barlow - * Some of this code is "inspired" by linux-wlan-ng-0.1.10, but nothing - * has been copied from it. linux-wlan-ng-0.1.10 is originally : - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - * This file originally written by: - * Copyright (C) 2001 Jean Tourrilhes - * And is now maintained by: - * (C) Copyright David Gibson, IBM Corp. 2002-2003. - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - */ - -#define DRIVER_NAME "orinoco_pci" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include - -#include "orinoco.h" -#include "orinoco_pci.h" - -/* Offset of the COR register of the PCI card */ -#define HERMES_PCI_COR (0x26) - -/* Bitmask to reset the card */ -#define HERMES_PCI_COR_MASK (0x0080) - -/* Magic timeouts for doing the reset. - * Those times are straight from wlan-ng, and it is claimed that they - * are necessary. Alan will kill me. Take your time and grab a coffee. */ -#define HERMES_PCI_COR_ONT (250) /* ms */ -#define HERMES_PCI_COR_OFFT (500) /* ms */ -#define HERMES_PCI_COR_BUSYT (500) /* ms */ - -/* - * Do a soft reset of the card using the Configuration Option Register - * We need this to get going... - * This is the part of the code that is strongly inspired from wlan-ng - * - * Note : This code is done with irq enabled. This mean that many - * interrupts will occur while we are there. This is why we use the - * jiffies to regulate time instead of a straight mdelay(). Usually we - * need only around 245 iteration of the loop to do 250 ms delay. - * - * Note bis : Don't try to access HERMES_CMD during the reset phase. - * It just won't work ! - */ -static int orinoco_pci_cor_reset(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - unsigned long timeout; - u16 reg; - - /* Assert the reset until the card notices */ - hermes_write_regn(hw, PCI_COR, HERMES_PCI_COR_MASK); - mdelay(HERMES_PCI_COR_ONT); - - /* Give time for the card to recover from this hard effort */ - hermes_write_regn(hw, PCI_COR, 0x0000); - mdelay(HERMES_PCI_COR_OFFT); - - /* The card is ready when it's no longer busy */ - timeout = jiffies + (HERMES_PCI_COR_BUSYT * HZ / 1000); - reg = hermes_read_regn(hw, CMD); - while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { - mdelay(1); - reg = hermes_read_regn(hw, CMD); - } - - /* Still busy? */ - if (reg & HERMES_CMD_BUSY) { - printk(KERN_ERR PFX "Busy timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int orinoco_pci_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int err; - struct orinoco_private *priv; - struct orinoco_pci_card *card; - void __iomem *hermes_io; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Cannot enable PCI device\n"); - return err; - } - - err = pci_request_regions(pdev, DRIVER_NAME); - if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); - goto fail_resources; - } - - hermes_io = pci_iomap(pdev, 0, 0); - if (!hermes_io) { - printk(KERN_ERR PFX "Cannot remap chipset registers\n"); - err = -EIO; - goto fail_map_hermes; - } - - /* Allocate network device */ - priv = alloc_orinocodev(sizeof(*card), &pdev->dev, - orinoco_pci_cor_reset, NULL); - if (!priv) { - printk(KERN_ERR PFX "Cannot allocate network device\n"); - err = -ENOMEM; - goto fail_alloc; - } - - card = priv->card; - - hermes_struct_init(&priv->hw, hermes_io, HERMES_32BIT_REGSPACING); - - err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, - DRIVER_NAME, priv); - if (err) { - printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); - err = -EBUSY; - goto fail_irq; - } - - err = orinoco_pci_cor_reset(priv); - if (err) { - printk(KERN_ERR PFX "Initial reset failed\n"); - goto fail; - } - - err = orinoco_init(priv); - if (err) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto fail; - } - - err = orinoco_if_add(priv, 0, 0); - if (err) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto fail; - } - - pci_set_drvdata(pdev, priv); - - return 0; - - fail: - free_irq(pdev->irq, priv); - - fail_irq: - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - - fail_alloc: - pci_iounmap(pdev, hermes_io); - - fail_map_hermes: - pci_release_regions(pdev); - - fail_resources: - pci_disable_device(pdev); - - return err; -} - -static void __devexit orinoco_pci_remove_one(struct pci_dev *pdev) -{ - struct orinoco_private *priv = pci_get_drvdata(pdev); - - orinoco_if_del(priv); - free_irq(pdev->irq, priv); - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - pci_iounmap(pdev, priv->hw.iobase); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -static struct pci_device_id orinoco_pci_id_table[] = { - /* Intersil Prism 3 */ - {0x1260, 0x3872, PCI_ANY_ID, PCI_ANY_ID,}, - /* Intersil Prism 2.5 */ - {0x1260, 0x3873, PCI_ANY_ID, PCI_ANY_ID,}, - /* Samsung MagicLAN SWL-2210P */ - {0x167d, 0xa000, PCI_ANY_ID, PCI_ANY_ID,}, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, orinoco_pci_id_table); - -static struct pci_driver orinoco_pci_driver = { - .name = DRIVER_NAME, - .id_table = orinoco_pci_id_table, - .probe = orinoco_pci_init_one, - .remove = __devexit_p(orinoco_pci_remove_one), - .suspend = orinoco_pci_suspend, - .resume = orinoco_pci_resume, -}; - -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Pavel Roskin ," - " David Gibson &" - " Jean Tourrilhes )"; -MODULE_AUTHOR("Pavel Roskin &" - " David Gibson "); -MODULE_DESCRIPTION("Driver for wireless LAN cards using direct PCI interface"); -MODULE_LICENSE("Dual MPL/GPL"); - -static int __init orinoco_pci_init(void) -{ - printk(KERN_DEBUG "%s\n", version); - return pci_register_driver(&orinoco_pci_driver); -} - -static void __exit orinoco_pci_exit(void) -{ - pci_unregister_driver(&orinoco_pci_driver); -} - -module_init(orinoco_pci_init); -module_exit(orinoco_pci_exit); - -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/wireless/orinoco/orinoco_pci.h b/drivers/net/wireless/orinoco/orinoco_pci.h deleted file mode 100644 index ea7231af40a8..000000000000 --- a/drivers/net/wireless/orinoco/orinoco_pci.h +++ /dev/null @@ -1,68 +0,0 @@ -/* orinoco_pci.h - * - * Common code for all Orinoco drivers for PCI devices, including - * both native PCI and PCMCIA-to-PCI bridges. - * - * Copyright (C) 2005, Pavel Roskin. - * See main.c for license. - */ - -#ifndef _ORINOCO_PCI_H -#define _ORINOCO_PCI_H - -#include - -/* Driver specific data */ -struct orinoco_pci_card { - void __iomem *bridge_io; - void __iomem *attr_io; -}; - -#ifdef CONFIG_PM -static int orinoco_pci_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct orinoco_private *priv = pci_get_drvdata(pdev); - - orinoco_down(priv); - free_irq(pdev->irq, priv); - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, PCI_D3hot); - - return 0; -} - -static int orinoco_pci_resume(struct pci_dev *pdev) -{ - struct orinoco_private *priv = pci_get_drvdata(pdev); - struct net_device *dev = priv->ndev; - int err; - - pci_set_power_state(pdev, 0); - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s: pci_enable_device failed on resume\n", - dev->name); - return err; - } - pci_restore_state(pdev); - - err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, - dev->name, priv); - if (err) { - printk(KERN_ERR "%s: cannot re-allocate IRQ on resume\n", - dev->name); - pci_disable_device(pdev); - return -EBUSY; - } - - err = orinoco_up(priv); - - return err; -} -#else -#define orinoco_pci_suspend NULL -#define orinoco_pci_resume NULL -#endif - -#endif /* _ORINOCO_PCI_H */ diff --git a/drivers/net/wireless/orinoco/orinoco_plx.c b/drivers/net/wireless/orinoco/orinoco_plx.c deleted file mode 100644 index 3f2942a1e4f5..000000000000 --- a/drivers/net/wireless/orinoco/orinoco_plx.c +++ /dev/null @@ -1,370 +0,0 @@ -/* orinoco_plx.c - * - * Driver for Prism II devices which would usually be driven by orinoco_cs, - * but are connected to the PCI bus by a PLX9052. - * - * Current maintainers are: - * Pavel Roskin - * and David Gibson - * - * (C) Copyright David Gibson, IBM Corp. 2001-2003. - * Copyright (C) 2001 Daniel Barlow - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - * - * Here's the general details on how the PLX9052 adapter works: - * - * - Two PCI I/O address spaces, one 0x80 long which contains the - * PLX9052 registers, and one that's 0x40 long mapped to the PCMCIA - * slot I/O address space. - * - * - One PCI memory address space, mapped to the PCMCIA attribute space - * (containing the CIS). - * - * Using the later, you can read through the CIS data to make sure the - * card is compatible with the driver. Keep in mind that the PCMCIA - * spec specifies the CIS as the lower 8 bits of each word read from - * the CIS, so to read the bytes of the CIS, read every other byte - * (0,2,4,...). Passing that test, you need to enable the I/O address - * space on the PCMCIA card via the PCMCIA COR register. This is the - * first byte following the CIS. In my case (which may not have any - * relation to what's on the PRISM2 cards), COR was at offset 0x800 - * within the PCI memory space. Write 0x41 to the COR register to - * enable I/O mode and to select level triggered interrupts. To - * confirm you actually succeeded, read the COR register back and make - * sure it actually got set to 0x41, in case you have an unexpected - * card inserted. - * - * Following that, you can treat the second PCI I/O address space (the - * one that's not 0x80 in length) as the PCMCIA I/O space. - * - * Note that in the Eumitcom's source for their drivers, they register - * the interrupt as edge triggered when registering it with the - * Windows kernel. I don't recall how to register edge triggered on - * Linux (if it can be done at all). But in some experimentation, I - * don't see much operational difference between using either - * interrupt mode. Don't mess with the interrupt mode in the COR - * register though, as the PLX9052 wants level triggers with the way - * the serial EEPROM configures it on the WL11000. - * - * There's some other little quirks related to timing that I bumped - * into, but I don't recall right now. Also, there's two variants of - * the WL11000 I've seen, revision A1 and T2. These seem to differ - * slightly in the timings configured in the wait-state generator in - * the PLX9052. There have also been some comments from Eumitcom that - * cards shouldn't be hot swapped, apparently due to risk of cooking - * the PLX9052. I'm unsure why they believe this, as I can't see - * anything in the design that would really cause a problem, except - * for crashing drivers not written to expect it. And having developed - * drivers for the WL11000, I'd say it's quite tricky to write code - * that will successfully deal with a hot unplug. Very odd things - * happen on the I/O side of things. But anyway, be warned. Despite - * that, I've hot-swapped a number of times during debugging and - * driver development for various reasons (stuck WAIT# line after the - * radio card's firmware locks up). - */ - -#define DRIVER_NAME "orinoco_plx" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include -#include - -#include "orinoco.h" -#include "orinoco_pci.h" - -#define COR_OFFSET (0x3e0) /* COR attribute offset of Prism2 PC card */ -#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ -#define COR_RESET (0x80) /* reset bit in the COR register */ -#define PLX_RESET_TIME (500) /* milliseconds */ - -#define PLX_INTCSR 0x4c /* Interrupt Control & Status Register */ -#define PLX_INTCSR_INTEN (1<<6) /* Interrupt Enable bit */ - -/* - * Do a soft reset of the card using the Configuration Option Register - */ -static int orinoco_plx_cor_reset(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - struct orinoco_pci_card *card = priv->card; - unsigned long timeout; - u16 reg; - - iowrite8(COR_VALUE | COR_RESET, card->attr_io + COR_OFFSET); - mdelay(1); - - iowrite8(COR_VALUE, card->attr_io + COR_OFFSET); - mdelay(1); - - /* Just in case, wait more until the card is no longer busy */ - timeout = jiffies + (PLX_RESET_TIME * HZ / 1000); - reg = hermes_read_regn(hw, CMD); - while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { - mdelay(1); - reg = hermes_read_regn(hw, CMD); - } - - /* Still busy? */ - if (reg & HERMES_CMD_BUSY) { - printk(KERN_ERR PFX "Busy timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - -static int orinoco_plx_hw_init(struct orinoco_pci_card *card) -{ - int i; - u32 csr_reg; - static const u8 cis_magic[] = { - 0x01, 0x03, 0x00, 0x00, 0xff, 0x17, 0x04, 0x67 - }; - - printk(KERN_DEBUG PFX "CIS: "); - for (i = 0; i < 16; i++) - printk("%02X:", ioread8(card->attr_io + (i << 1))); - printk("\n"); - - /* Verify whether a supported PC card is present */ - /* FIXME: we probably need to be smarted about this */ - for (i = 0; i < sizeof(cis_magic); i++) { - if (cis_magic[i] != ioread8(card->attr_io + (i << 1))) { - printk(KERN_ERR PFX "The CIS value of Prism2 PC " - "card is unexpected\n"); - return -ENODEV; - } - } - - /* bjoern: We need to tell the card to enable interrupts, in - case the serial eprom didn't do this already. See the - PLX9052 data book, p8-1 and 8-24 for reference. */ - csr_reg = ioread32(card->bridge_io + PLX_INTCSR); - if (!(csr_reg & PLX_INTCSR_INTEN)) { - csr_reg |= PLX_INTCSR_INTEN; - iowrite32(csr_reg, card->bridge_io + PLX_INTCSR); - csr_reg = ioread32(card->bridge_io + PLX_INTCSR); - if (!(csr_reg & PLX_INTCSR_INTEN)) { - printk(KERN_ERR PFX "Cannot enable interrupts\n"); - return -EIO; - } - } - - return 0; -} - -static int orinoco_plx_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int err; - struct orinoco_private *priv; - struct orinoco_pci_card *card; - void __iomem *hermes_io, *attr_io, *bridge_io; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Cannot enable PCI device\n"); - return err; - } - - err = pci_request_regions(pdev, DRIVER_NAME); - if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); - goto fail_resources; - } - - bridge_io = pci_iomap(pdev, 1, 0); - if (!bridge_io) { - printk(KERN_ERR PFX "Cannot map bridge registers\n"); - err = -EIO; - goto fail_map_bridge; - } - - attr_io = pci_iomap(pdev, 2, 0); - if (!attr_io) { - printk(KERN_ERR PFX "Cannot map PCMCIA attributes\n"); - err = -EIO; - goto fail_map_attr; - } - - hermes_io = pci_iomap(pdev, 3, 0); - if (!hermes_io) { - printk(KERN_ERR PFX "Cannot map chipset registers\n"); - err = -EIO; - goto fail_map_hermes; - } - - /* Allocate network device */ - priv = alloc_orinocodev(sizeof(*card), &pdev->dev, - orinoco_plx_cor_reset, NULL); - if (!priv) { - printk(KERN_ERR PFX "Cannot allocate network device\n"); - err = -ENOMEM; - goto fail_alloc; - } - - card = priv->card; - card->bridge_io = bridge_io; - card->attr_io = attr_io; - - hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); - - err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, - DRIVER_NAME, priv); - if (err) { - printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); - err = -EBUSY; - goto fail_irq; - } - - err = orinoco_plx_hw_init(card); - if (err) { - printk(KERN_ERR PFX "Hardware initialization failed\n"); - goto fail; - } - - err = orinoco_plx_cor_reset(priv); - if (err) { - printk(KERN_ERR PFX "Initial reset failed\n"); - goto fail; - } - - err = orinoco_init(priv); - if (err) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto fail; - } - - err = orinoco_if_add(priv, 0, 0); - if (err) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto fail; - } - - pci_set_drvdata(pdev, priv); - - return 0; - - fail: - free_irq(pdev->irq, priv); - - fail_irq: - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - - fail_alloc: - pci_iounmap(pdev, hermes_io); - - fail_map_hermes: - pci_iounmap(pdev, attr_io); - - fail_map_attr: - pci_iounmap(pdev, bridge_io); - - fail_map_bridge: - pci_release_regions(pdev); - - fail_resources: - pci_disable_device(pdev); - - return err; -} - -static void __devexit orinoco_plx_remove_one(struct pci_dev *pdev) -{ - struct orinoco_private *priv = pci_get_drvdata(pdev); - struct orinoco_pci_card *card = priv->card; - - orinoco_if_del(priv); - free_irq(pdev->irq, priv); - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - pci_iounmap(pdev, priv->hw.iobase); - pci_iounmap(pdev, card->attr_io); - pci_iounmap(pdev, card->bridge_io); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -static struct pci_device_id orinoco_plx_id_table[] = { - {0x111a, 0x1023, PCI_ANY_ID, PCI_ANY_ID,}, /* Siemens SpeedStream SS1023 */ - {0x1385, 0x4100, PCI_ANY_ID, PCI_ANY_ID,}, /* Netgear MA301 */ - {0x15e8, 0x0130, PCI_ANY_ID, PCI_ANY_ID,}, /* Correga - does this work? */ - {0x1638, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* SMC EZConnect SMC2602W, - Eumitcom PCI WL11000, - Addtron AWA-100 */ - {0x16ab, 0x1100, PCI_ANY_ID, PCI_ANY_ID,}, /* Global Sun Tech GL24110P */ - {0x16ab, 0x1101, PCI_ANY_ID, PCI_ANY_ID,}, /* Reported working, but unknown */ - {0x16ab, 0x1102, PCI_ANY_ID, PCI_ANY_ID,}, /* Linksys WDT11 */ - {0x16ec, 0x3685, PCI_ANY_ID, PCI_ANY_ID,}, /* USR 2415 */ - {0xec80, 0xec00, PCI_ANY_ID, PCI_ANY_ID,}, /* Belkin F5D6000 tested by - Brendan W. McAdams */ - {0x10b7, 0x7770, PCI_ANY_ID, PCI_ANY_ID,}, /* 3Com AirConnect PCI tested by - Damien Persohn */ - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, orinoco_plx_id_table); - -static struct pci_driver orinoco_plx_driver = { - .name = DRIVER_NAME, - .id_table = orinoco_plx_id_table, - .probe = orinoco_plx_init_one, - .remove = __devexit_p(orinoco_plx_remove_one), - .suspend = orinoco_pci_suspend, - .resume = orinoco_pci_resume, -}; - -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Pavel Roskin ," - " David Gibson ," - " Daniel Barlow )"; -MODULE_AUTHOR("Daniel Barlow "); -MODULE_DESCRIPTION("Driver for wireless LAN cards using the PLX9052 PCI bridge"); -MODULE_LICENSE("Dual MPL/GPL"); - -static int __init orinoco_plx_init(void) -{ - printk(KERN_DEBUG "%s\n", version); - return pci_register_driver(&orinoco_plx_driver); -} - -static void __exit orinoco_plx_exit(void) -{ - pci_unregister_driver(&orinoco_plx_driver); -} - -module_init(orinoco_plx_init); -module_exit(orinoco_plx_exit); - -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/wireless/orinoco/orinoco_tmd.c b/drivers/net/wireless/orinoco/orinoco_tmd.c deleted file mode 100644 index d3452548cc71..000000000000 --- a/drivers/net/wireless/orinoco/orinoco_tmd.c +++ /dev/null @@ -1,248 +0,0 @@ -/* orinoco_tmd.c - * - * Driver for Prism II devices which would usually be driven by orinoco_cs, - * but are connected to the PCI bus by a TMD7160. - * - * Copyright (C) 2003 Joerg Dorchain - * based heavily upon orinoco_plx.c Copyright (C) 2001 Daniel Barlow - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License - * at http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See - * the License for the specific language governing rights and - * limitations under the License. - * - * Alternatively, the contents of this file may be used under the - * terms of the GNU General Public License version 2 (the "GPL"), in - * which case the provisions of the GPL are applicable instead of the - * above. If you wish to allow the use of your version of this file - * only under the terms of the GPL and not to allow others to use your - * version of this file under the MPL, indicate your decision by - * deleting the provisions above and replace them with the notice and - * other provisions required by the GPL. If you do not delete the - * provisions above, a recipient may use your version of this file - * under either the MPL or the GPL. - * - * The actual driving is done by main.c, this is just resource - * allocation stuff. - * - * This driver is modeled after the orinoco_plx driver. The main - * difference is that the TMD chip has only IO port ranges and doesn't - * provide access to the PCMCIA attribute space. - * - * Pheecom sells cards with the TMD chip as "ASIC version" - */ - -#define DRIVER_NAME "orinoco_tmd" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include -#include - -#include "orinoco.h" -#include "orinoco_pci.h" - -#define COR_VALUE (COR_LEVEL_REQ | COR_FUNC_ENA) /* Enable PC card with interrupt in level trigger */ -#define COR_RESET (0x80) /* reset bit in the COR register */ -#define TMD_RESET_TIME (500) /* milliseconds */ - -/* - * Do a soft reset of the card using the Configuration Option Register - */ -static int orinoco_tmd_cor_reset(struct orinoco_private *priv) -{ - hermes_t *hw = &priv->hw; - struct orinoco_pci_card *card = priv->card; - unsigned long timeout; - u16 reg; - - iowrite8(COR_VALUE | COR_RESET, card->bridge_io); - mdelay(1); - - iowrite8(COR_VALUE, card->bridge_io); - mdelay(1); - - /* Just in case, wait more until the card is no longer busy */ - timeout = jiffies + (TMD_RESET_TIME * HZ / 1000); - reg = hermes_read_regn(hw, CMD); - while (time_before(jiffies, timeout) && (reg & HERMES_CMD_BUSY)) { - mdelay(1); - reg = hermes_read_regn(hw, CMD); - } - - /* Still busy? */ - if (reg & HERMES_CMD_BUSY) { - printk(KERN_ERR PFX "Busy timeout\n"); - return -ETIMEDOUT; - } - - return 0; -} - - -static int orinoco_tmd_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - int err; - struct orinoco_private *priv; - struct orinoco_pci_card *card; - void __iomem *hermes_io, *bridge_io; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Cannot enable PCI device\n"); - return err; - } - - err = pci_request_regions(pdev, DRIVER_NAME); - if (err) { - printk(KERN_ERR PFX "Cannot obtain PCI resources\n"); - goto fail_resources; - } - - bridge_io = pci_iomap(pdev, 1, 0); - if (!bridge_io) { - printk(KERN_ERR PFX "Cannot map bridge registers\n"); - err = -EIO; - goto fail_map_bridge; - } - - hermes_io = pci_iomap(pdev, 2, 0); - if (!hermes_io) { - printk(KERN_ERR PFX "Cannot map chipset registers\n"); - err = -EIO; - goto fail_map_hermes; - } - - /* Allocate network device */ - priv = alloc_orinocodev(sizeof(*card), &pdev->dev, - orinoco_tmd_cor_reset, NULL); - if (!priv) { - printk(KERN_ERR PFX "Cannot allocate network device\n"); - err = -ENOMEM; - goto fail_alloc; - } - - card = priv->card; - card->bridge_io = bridge_io; - - hermes_struct_init(&priv->hw, hermes_io, HERMES_16BIT_REGSPACING); - - err = request_irq(pdev->irq, orinoco_interrupt, IRQF_SHARED, - DRIVER_NAME, priv); - if (err) { - printk(KERN_ERR PFX "Cannot allocate IRQ %d\n", pdev->irq); - err = -EBUSY; - goto fail_irq; - } - - err = orinoco_tmd_cor_reset(priv); - if (err) { - printk(KERN_ERR PFX "Initial reset failed\n"); - goto fail; - } - - err = orinoco_init(priv); - if (err) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto fail; - } - - err = orinoco_if_add(priv, 0, 0); - if (err) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto fail; - } - - pci_set_drvdata(pdev, priv); - - return 0; - - fail: - free_irq(pdev->irq, priv); - - fail_irq: - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - - fail_alloc: - pci_iounmap(pdev, hermes_io); - - fail_map_hermes: - pci_iounmap(pdev, bridge_io); - - fail_map_bridge: - pci_release_regions(pdev); - - fail_resources: - pci_disable_device(pdev); - - return err; -} - -static void __devexit orinoco_tmd_remove_one(struct pci_dev *pdev) -{ - struct orinoco_private *priv = pci_get_drvdata(pdev); - struct orinoco_pci_card *card = priv->card; - - orinoco_if_del(priv); - free_irq(pdev->irq, priv); - pci_set_drvdata(pdev, NULL); - free_orinocodev(priv); - pci_iounmap(pdev, priv->hw.iobase); - pci_iounmap(pdev, card->bridge_io); - pci_release_regions(pdev); - pci_disable_device(pdev); -} - -static struct pci_device_id orinoco_tmd_id_table[] = { - {0x15e8, 0x0131, PCI_ANY_ID, PCI_ANY_ID,}, /* NDC and OEMs, e.g. pheecom */ - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, orinoco_tmd_id_table); - -static struct pci_driver orinoco_tmd_driver = { - .name = DRIVER_NAME, - .id_table = orinoco_tmd_id_table, - .probe = orinoco_tmd_init_one, - .remove = __devexit_p(orinoco_tmd_remove_one), - .suspend = orinoco_pci_suspend, - .resume = orinoco_pci_resume, -}; - -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Joerg Dorchain )"; -MODULE_AUTHOR("Joerg Dorchain "); -MODULE_DESCRIPTION("Driver for wireless LAN cards using the TMD7160 PCI bridge"); -MODULE_LICENSE("Dual MPL/GPL"); - -static int __init orinoco_tmd_init(void) -{ - printk(KERN_DEBUG "%s\n", version); - return pci_register_driver(&orinoco_tmd_driver); -} - -static void __exit orinoco_tmd_exit(void) -{ - pci_unregister_driver(&orinoco_tmd_driver); -} - -module_init(orinoco_tmd_init); -module_exit(orinoco_tmd_exit); - -/* - * Local variables: - * c-indent-level: 8 - * c-basic-offset: 8 - * tab-width: 8 - * End: - */ diff --git a/drivers/net/wireless/orinoco/scan.c b/drivers/net/wireless/orinoco/scan.c deleted file mode 100644 index d2f10e9c2162..000000000000 --- a/drivers/net/wireless/orinoco/scan.c +++ /dev/null @@ -1,230 +0,0 @@ -/* Helpers for managing scan queues - * - * See copyright notice in main.c - */ - -#include -#include -#include -#include - -#include "hermes.h" -#include "orinoco.h" -#include "main.h" - -#include "scan.h" - -#define ZERO_DBM_OFFSET 0x95 -#define MAX_SIGNAL_LEVEL 0x8A -#define MIN_SIGNAL_LEVEL 0x2F - -#define SIGNAL_TO_DBM(x) \ - (clamp_t(s32, (x), MIN_SIGNAL_LEVEL, MAX_SIGNAL_LEVEL) \ - - ZERO_DBM_OFFSET) -#define SIGNAL_TO_MBM(x) (SIGNAL_TO_DBM(x) * 100) - -static int symbol_build_supp_rates(u8 *buf, const __le16 *rates) -{ - int i; - u8 rate; - - buf[0] = WLAN_EID_SUPP_RATES; - for (i = 0; i < 5; i++) { - rate = le16_to_cpu(rates[i]); - /* NULL terminated */ - if (rate == 0x0) - break; - buf[i + 2] = rate; - } - buf[1] = i; - - return i + 2; -} - -static int prism_build_supp_rates(u8 *buf, const u8 *rates) -{ - int i; - - buf[0] = WLAN_EID_SUPP_RATES; - for (i = 0; i < 8; i++) { - /* NULL terminated */ - if (rates[i] == 0x0) - break; - buf[i + 2] = rates[i]; - } - buf[1] = i; - - /* We might still have another 2 rates, which need to go in - * extended supported rates */ - if (i == 8 && rates[i] > 0) { - buf[10] = WLAN_EID_EXT_SUPP_RATES; - for (; i < 10; i++) { - /* NULL terminated */ - if (rates[i] == 0x0) - break; - buf[i + 2] = rates[i]; - } - buf[11] = i - 8; - } - - return (i < 8) ? i + 2 : i + 4; -} - -static void orinoco_add_hostscan_result(struct orinoco_private *priv, - const union hermes_scan_info *bss) -{ - struct wiphy *wiphy = priv_to_wiphy(priv); - struct ieee80211_channel *channel; - u8 *ie; - u8 ie_buf[46]; - u64 timestamp; - s32 signal; - u16 capability; - u16 beacon_interval; - int ie_len; - int freq; - int len; - - len = le16_to_cpu(bss->a.essid_len); - - /* Reconstruct SSID and bitrate IEs to pass up */ - ie_buf[0] = WLAN_EID_SSID; - ie_buf[1] = len; - memcpy(&ie_buf[2], bss->a.essid, len); - - ie = ie_buf + len + 2; - ie_len = ie_buf[1] + 2; - switch (priv->firmware_type) { - case FIRMWARE_TYPE_SYMBOL: - ie_len += symbol_build_supp_rates(ie, bss->s.rates); - break; - - case FIRMWARE_TYPE_INTERSIL: - ie_len += prism_build_supp_rates(ie, bss->p.rates); - break; - - case FIRMWARE_TYPE_AGERE: - default: - break; - } - - freq = ieee80211_dsss_chan_to_freq(le16_to_cpu(bss->a.channel)); - channel = ieee80211_get_channel(wiphy, freq); - timestamp = 0; - capability = le16_to_cpu(bss->a.capabilities); - beacon_interval = le16_to_cpu(bss->a.beacon_interv); - signal = SIGNAL_TO_MBM(le16_to_cpu(bss->a.level)); - - cfg80211_inform_bss(wiphy, channel, bss->a.bssid, timestamp, - capability, beacon_interval, ie_buf, ie_len, - signal, GFP_KERNEL); -} - -void orinoco_add_extscan_result(struct orinoco_private *priv, - struct agere_ext_scan_info *bss, - size_t len) -{ - struct wiphy *wiphy = priv_to_wiphy(priv); - struct ieee80211_channel *channel; - u8 *ie; - u64 timestamp; - s32 signal; - u16 capability; - u16 beacon_interval; - size_t ie_len; - int chan, freq; - - ie_len = len - sizeof(*bss); - ie = orinoco_get_ie(bss->data, ie_len, WLAN_EID_DS_PARAMS); - chan = ie ? ie[2] : 0; - freq = ieee80211_dsss_chan_to_freq(chan); - channel = ieee80211_get_channel(wiphy, freq); - - timestamp = le64_to_cpu(bss->timestamp); - capability = le16_to_cpu(bss->capabilities); - beacon_interval = le16_to_cpu(bss->beacon_interval); - ie = bss->data; - signal = SIGNAL_TO_MBM(bss->level); - - cfg80211_inform_bss(wiphy, channel, bss->bssid, timestamp, - capability, beacon_interval, ie, ie_len, - signal, GFP_KERNEL); -} - -void orinoco_add_hostscan_results(struct orinoco_private *priv, - unsigned char *buf, - size_t len) -{ - int offset; /* In the scan data */ - size_t atom_len; - bool abort = false; - - switch (priv->firmware_type) { - case FIRMWARE_TYPE_AGERE: - atom_len = sizeof(struct agere_scan_apinfo); - offset = 0; - break; - - case FIRMWARE_TYPE_SYMBOL: - /* Lack of documentation necessitates this hack. - * Different firmwares have 68 or 76 byte long atoms. - * We try modulo first. If the length divides by both, - * we check what would be the channel in the second - * frame for a 68-byte atom. 76-byte atoms have 0 there. - * Valid channel cannot be 0. */ - if (len % 76) - atom_len = 68; - else if (len % 68) - atom_len = 76; - else if (len >= 1292 && buf[68] == 0) - atom_len = 76; - else - atom_len = 68; - offset = 0; - break; - - case FIRMWARE_TYPE_INTERSIL: - offset = 4; - if (priv->has_hostscan) { - atom_len = le16_to_cpup((__le16 *)buf); - /* Sanity check for atom_len */ - if (atom_len < sizeof(struct prism2_scan_apinfo)) { - printk(KERN_ERR "%s: Invalid atom_len in scan " - "data: %zu\n", priv->ndev->name, - atom_len); - abort = true; - goto scan_abort; - } - } else - atom_len = offsetof(struct prism2_scan_apinfo, atim); - break; - - default: - abort = true; - goto scan_abort; - } - - /* Check that we got an whole number of atoms */ - if ((len - offset) % atom_len) { - printk(KERN_ERR "%s: Unexpected scan data length %zu, " - "atom_len %zu, offset %d\n", priv->ndev->name, len, - atom_len, offset); - abort = true; - goto scan_abort; - } - - /* Process the entries one by one */ - for (; offset + atom_len <= len; offset += atom_len) { - union hermes_scan_info *atom; - - atom = (union hermes_scan_info *) (buf + offset); - - orinoco_add_hostscan_result(priv, atom); - } - - scan_abort: - if (priv->scan_request) { - cfg80211_scan_done(priv->scan_request, abort); - priv->scan_request = NULL; - } -} diff --git a/drivers/net/wireless/orinoco/scan.h b/drivers/net/wireless/orinoco/scan.h deleted file mode 100644 index 2dc4e046dbdb..000000000000 --- a/drivers/net/wireless/orinoco/scan.h +++ /dev/null @@ -1,20 +0,0 @@ -/* Helpers for managing scan queues - * - * See copyright notice in main.c - */ -#ifndef _ORINOCO_SCAN_H_ -#define _ORINOCO_SCAN_H_ - -/* Forward declarations */ -struct orinoco_private; -struct agere_ext_scan_info; - -/* Add scan results */ -void orinoco_add_extscan_result(struct orinoco_private *priv, - struct agere_ext_scan_info *atom, - size_t len); -void orinoco_add_hostscan_results(struct orinoco_private *dev, - unsigned char *buf, - size_t len); - -#endif /* _ORINOCO_SCAN_H_ */ diff --git a/drivers/net/wireless/orinoco/spectrum_cs.c b/drivers/net/wireless/orinoco/spectrum_cs.c deleted file mode 100644 index c361310b885d..000000000000 --- a/drivers/net/wireless/orinoco/spectrum_cs.c +++ /dev/null @@ -1,487 +0,0 @@ -/* - * Driver for 802.11b cards using RAM-loadable Symbol firmware, such as - * Symbol Wireless Networker LA4137, CompactFlash cards by Socket - * Communications and Intel PRO/Wireless 2011B. - * - * The driver implements Symbol firmware download. The rest is handled - * in hermes.c and main.c. - * - * Utilities for downloading the Symbol firmware are available at - * http://sourceforge.net/projects/orinoco/ - * - * Copyright (C) 2002-2005 Pavel Roskin - * Portions based on orinoco_cs.c: - * Copyright (C) David Gibson, Linuxcare Australia - * Portions based on Spectrum24tDnld.c from original spectrum24 driver: - * Copyright (C) Symbol Technologies. - * - * See copyright notice in file main.c. - */ - -#define DRIVER_NAME "spectrum_cs" -#define PFX DRIVER_NAME ": " - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "orinoco.h" - -/********************************************************************/ -/* Module stuff */ -/********************************************************************/ - -MODULE_AUTHOR("Pavel Roskin "); -MODULE_DESCRIPTION("Driver for Symbol Spectrum24 Trilogy cards with firmware downloader"); -MODULE_LICENSE("Dual MPL/GPL"); - -/* Module parameters */ - -/* Some D-Link cards have buggy CIS. They do work at 5v properly, but - * don't have any CIS entry for it. This workaround it... */ -static int ignore_cis_vcc; /* = 0 */ -module_param(ignore_cis_vcc, int, 0); -MODULE_PARM_DESC(ignore_cis_vcc, "Allow voltage mismatch between card and socket"); - -/********************************************************************/ -/* Data structures */ -/********************************************************************/ - -/* PCMCIA specific device information (goes in the card field of - * struct orinoco_private */ -struct orinoco_pccard { - struct pcmcia_device *p_dev; - dev_node_t node; -}; - -/********************************************************************/ -/* Function prototypes */ -/********************************************************************/ - -static int spectrum_cs_config(struct pcmcia_device *link); -static void spectrum_cs_release(struct pcmcia_device *link); - -/* Constants for the CISREG_CCSR register */ -#define HCR_RUN 0x07 /* run firmware after reset */ -#define HCR_IDLE 0x0E /* don't run firmware after reset */ -#define HCR_MEM16 0x10 /* memory width bit, should be preserved */ - - -#define CS_CHECK(fn, ret) \ - do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -/* - * Reset the card using configuration registers COR and CCSR. - * If IDLE is 1, stop the firmware, so that it can be safely rewritten. - */ -static int -spectrum_reset(struct pcmcia_device *link, int idle) -{ - int last_ret, last_fn; - conf_reg_t reg; - u_int save_cor; - - /* Doing it if hardware is gone is guaranteed crash */ - if (!pcmcia_dev_present(link)) - return -ENODEV; - - /* Save original COR value */ - reg.Function = 0; - reg.Action = CS_READ; - reg.Offset = CISREG_COR; - CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); - save_cor = reg.Value; - - /* Soft-Reset card */ - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; - reg.Value = (save_cor | COR_SOFT_RESET); - CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); - udelay(1000); - - /* Read CCSR */ - reg.Action = CS_READ; - reg.Offset = CISREG_CCSR; - CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); - - /* - * Start or stop the firmware. Memory width bit should be - * preserved from the value we've just read. - */ - reg.Action = CS_WRITE; - reg.Offset = CISREG_CCSR; - reg.Value = (idle ? HCR_IDLE : HCR_RUN) | (reg.Value & HCR_MEM16); - CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); - udelay(1000); - - /* Restore original COR configuration index */ - reg.Action = CS_WRITE; - reg.Offset = CISREG_COR; - reg.Value = (save_cor & ~COR_SOFT_RESET); - CS_CHECK(AccessConfigurationRegister, - pcmcia_access_configuration_register(link, ®)); - udelay(1000); - return 0; - -cs_failed: - cs_error(link, last_fn, last_ret); - return -ENODEV; -} - -/********************************************************************/ -/* Device methods */ -/********************************************************************/ - -static int -spectrum_cs_hard_reset(struct orinoco_private *priv) -{ - struct orinoco_pccard *card = priv->card; - struct pcmcia_device *link = card->p_dev; - - /* Soft reset using COR and HCR */ - spectrum_reset(link, 0); - - return 0; -} - -static int -spectrum_cs_stop_firmware(struct orinoco_private *priv, int idle) -{ - struct orinoco_pccard *card = priv->card; - struct pcmcia_device *link = card->p_dev; - - return spectrum_reset(link, idle); -} - -/********************************************************************/ -/* PCMCIA stuff */ -/********************************************************************/ - -/* - * This creates an "instance" of the driver, allocating local data - * structures for one device. The device is registered with Card - * Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a card - * insertion event. */ -static int -spectrum_cs_probe(struct pcmcia_device *link) -{ - struct orinoco_private *priv; - struct orinoco_pccard *card; - - priv = alloc_orinocodev(sizeof(*card), &handle_to_dev(link), - spectrum_cs_hard_reset, - spectrum_cs_stop_firmware); - if (!priv) - return -ENOMEM; - card = priv->card; - - /* Link both structures together */ - card->p_dev = link; - link->priv = priv; - - /* Interrupt setup */ - link->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - link->irq.IRQInfo1 = IRQ_LEVEL_ID; - link->irq.Handler = orinoco_interrupt; - link->irq.Instance = priv; - - /* General socket configuration defaults can go here. In this - * client, we assume very little, and rely on the CIS for - * almost everything. In most clients, many details (i.e., - * number, sizes, and attributes of IO windows) are fixed by - * the nature of the device, and can be hard-wired here. */ - link->conf.Attributes = 0; - link->conf.IntType = INT_MEMORY_AND_IO; - - return spectrum_cs_config(link); -} /* spectrum_cs_attach */ - -/* - * This deletes a driver "instance". The device is de-registered with - * Card Services. If it has been released, all local data structures - * are freed. Otherwise, the structures will be freed when the device - * is released. - */ -static void spectrum_cs_detach(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - - if (link->dev_node) - orinoco_if_del(priv); - - spectrum_cs_release(link); - - free_orinocodev(priv); -} /* spectrum_cs_detach */ - -/* - * spectrum_cs_config() is scheduled to run after a CARD_INSERTION - * event is received, to configure the PCMCIA socket, and to make the - * device available to the system. - */ - -static int spectrum_cs_config_check(struct pcmcia_device *p_dev, - cistpl_cftable_entry_t *cfg, - cistpl_cftable_entry_t *dflt, - unsigned int vcc, - void *priv_data) -{ - if (cfg->index == 0) - goto next_entry; - - /* Use power settings for Vcc and Vpp if present */ - /* Note that the CIS values need to be rescaled */ - if (cfg->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != cfg->vcc.param[CISTPL_POWER_VNOM] / 10000) { - DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", - __func__, vcc, - cfg->vcc.param[CISTPL_POWER_VNOM] / 10000); - if (!ignore_cis_vcc) - goto next_entry; - } - } else if (dflt->vcc.present & (1 << CISTPL_POWER_VNOM)) { - if (vcc != dflt->vcc.param[CISTPL_POWER_VNOM] / 10000) { - DEBUG(2, "%s: Vcc mismatch (vcc = %d, CIS = %d)\n", - __func__, vcc, - dflt->vcc.param[CISTPL_POWER_VNOM] / 10000); - if (!ignore_cis_vcc) - goto next_entry; - } - } - - if (cfg->vpp1.present & (1 << CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = - cfg->vpp1.param[CISTPL_POWER_VNOM] / 10000; - else if (dflt->vpp1.present & (1 << CISTPL_POWER_VNOM)) - p_dev->conf.Vpp = - dflt->vpp1.param[CISTPL_POWER_VNOM] / 10000; - - /* Do we need to allocate an interrupt? */ - p_dev->conf.Attributes |= CONF_ENABLE_IRQ; - - /* IO window settings */ - p_dev->io.NumPorts1 = p_dev->io.NumPorts2 = 0; - if ((cfg->io.nwin > 0) || (dflt->io.nwin > 0)) { - cistpl_io_t *io = (cfg->io.nwin) ? &cfg->io : &dflt->io; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_AUTO; - if (!(io->flags & CISTPL_IO_8BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_16; - if (!(io->flags & CISTPL_IO_16BIT)) - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = io->flags & CISTPL_IO_LINES_MASK; - p_dev->io.BasePort1 = io->win[0].base; - p_dev->io.NumPorts1 = io->win[0].len; - if (io->nwin > 1) { - p_dev->io.Attributes2 = p_dev->io.Attributes1; - p_dev->io.BasePort2 = io->win[1].base; - p_dev->io.NumPorts2 = io->win[1].len; - } - - /* This reserves IO space but doesn't actually enable it */ - if (pcmcia_request_io(p_dev, &p_dev->io) != 0) - goto next_entry; - } - return 0; - -next_entry: - pcmcia_disable_device(p_dev); - return -ENODEV; -}; - -static int -spectrum_cs_config(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - struct orinoco_pccard *card = priv->card; - hermes_t *hw = &priv->hw; - int last_fn, last_ret; - void __iomem *mem; - - /* - * In this loop, we scan the CIS for configuration table - * entries, each of which describes a valid card - * configuration, including voltage, IO window, memory window, - * and interrupt settings. - * - * We make no assumptions about the card to be configured: we - * use just the information available in the CIS. In an ideal - * world, this would work for any PCMCIA card, but it requires - * a complete and accurate CIS. In practice, a driver usually - * "knows" most of these things without consulting the CIS, - * and most client drivers will only use the CIS to fill in - * implementation-defined details. - */ - last_ret = pcmcia_loop_config(link, spectrum_cs_config_check, NULL); - if (last_ret) { - if (!ignore_cis_vcc) - printk(KERN_ERR PFX "GetNextTuple(): No matching " - "CIS configuration. Maybe you need the " - "ignore_cis_vcc=1 parameter.\n"); - cs_error(link, RequestIO, last_ret); - goto failed; - } - - /* - * Allocate an interrupt line. Note that this does not assign - * a handler to the interrupt, unless the 'Handler' member of - * the irq structure is initialized. - */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - - /* We initialize the hermes structure before completing PCMCIA - * configuration just in case the interrupt handler gets - * called. */ - mem = ioport_map(link->io.BasePort1, link->io.NumPorts1); - if (!mem) - goto cs_failed; - - hermes_struct_init(hw, mem, HERMES_16BIT_REGSPACING); - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping, and putting the - * card and host interface into "Memory and IO" mode. - */ - CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link, &link->conf)); - - /* Ok, we have the configuration, prepare to register the netdev */ - card->node.major = card->node.minor = 0; - - /* Reset card */ - if (spectrum_cs_hard_reset(priv) != 0) - goto failed; - - /* Initialise the main driver */ - if (orinoco_init(priv) != 0) { - printk(KERN_ERR PFX "orinoco_init() failed\n"); - goto failed; - } - - /* Register an interface with the stack */ - if (orinoco_if_add(priv, link->io.BasePort1, - link->irq.AssignedIRQ) != 0) { - printk(KERN_ERR PFX "orinoco_if_add() failed\n"); - goto failed; - } - - /* At this point, the dev_node_t structure(s) needs to be - * initialized and arranged in a linked list at link->dev_node. */ - strcpy(card->node.dev_name, priv->ndev->name); - link->dev_node = &card->node; /* link->dev_node being non-NULL is also - * used to indicate that the - * net_device has been registered */ - return 0; - - cs_failed: - cs_error(link, last_fn, last_ret); - - failed: - spectrum_cs_release(link); - return -ENODEV; -} /* spectrum_cs_config */ - -/* - * After a card is removed, spectrum_cs_release() will unregister the - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void -spectrum_cs_release(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - unsigned long flags; - - /* We're committed to taking the device away now, so mark the - * hardware as unavailable */ - spin_lock_irqsave(&priv->lock, flags); - priv->hw_unavailable++; - spin_unlock_irqrestore(&priv->lock, flags); - - pcmcia_disable_device(link); - if (priv->hw.iobase) - ioport_unmap(priv->hw.iobase); -} /* spectrum_cs_release */ - - -static int -spectrum_cs_suspend(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - int err = 0; - - /* Mark the device as stopped, to block IO until later */ - orinoco_down(priv); - - return err; -} - -static int -spectrum_cs_resume(struct pcmcia_device *link) -{ - struct orinoco_private *priv = link->priv; - int err = orinoco_up(priv); - - return err; -} - - -/********************************************************************/ -/* Module initialization */ -/********************************************************************/ - -/* Can't be declared "const" or the whole __initdata section will - * become const */ -static char version[] __initdata = DRIVER_NAME " " DRIVER_VERSION - " (Pavel Roskin ," - " David Gibson , et al)"; - -static struct pcmcia_device_id spectrum_cs_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x026c, 0x0001), /* Symbol Spectrum24 LA4137 */ - PCMCIA_DEVICE_MANF_CARD(0x0104, 0x0001), /* Socket Communications CF */ - PCMCIA_DEVICE_PROD_ID12("Intel", "PRO/Wireless LAN PC Card", 0x816cc815, 0x6fbf459a), /* 2011B, not 2011 */ - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, spectrum_cs_ids); - -static struct pcmcia_driver orinoco_driver = { - .owner = THIS_MODULE, - .drv = { - .name = DRIVER_NAME, - }, - .probe = spectrum_cs_probe, - .remove = spectrum_cs_detach, - .suspend = spectrum_cs_suspend, - .resume = spectrum_cs_resume, - .id_table = spectrum_cs_ids, -}; - -static int __init -init_spectrum_cs(void) -{ - printk(KERN_DEBUG "%s\n", version); - - return pcmcia_register_driver(&orinoco_driver); -} - -static void __exit -exit_spectrum_cs(void) -{ - pcmcia_unregister_driver(&orinoco_driver); -} - -module_init(init_spectrum_cs); -module_exit(exit_spectrum_cs); diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c deleted file mode 100644 index 31ca241f7753..000000000000 --- a/drivers/net/wireless/orinoco/wext.c +++ /dev/null @@ -1,1574 +0,0 @@ -/* Wireless extensions support. - * - * See copyright notice in main.c - */ -#include -#include -#include -#include -#include -#include - -#include "hermes.h" -#include "hermes_rid.h" -#include "orinoco.h" - -#include "hw.h" -#include "mic.h" -#include "scan.h" -#include "main.h" - -#include "wext.h" - -#define MAX_RID_LEN 1024 - -/* Helper routine to record keys - * It is called under orinoco_lock so it may not sleep */ -static int orinoco_set_key(struct orinoco_private *priv, int index, - enum orinoco_alg alg, const u8 *key, int key_len, - const u8 *seq, int seq_len) -{ - kzfree(priv->keys[index].key); - kzfree(priv->keys[index].seq); - - if (key_len) { - priv->keys[index].key = kzalloc(key_len, GFP_ATOMIC); - if (!priv->keys[index].key) - goto nomem; - } else - priv->keys[index].key = NULL; - - if (seq_len) { - priv->keys[index].seq = kzalloc(seq_len, GFP_ATOMIC); - if (!priv->keys[index].seq) - goto free_key; - } else - priv->keys[index].seq = NULL; - - priv->keys[index].key_len = key_len; - priv->keys[index].seq_len = seq_len; - - if (key_len) - memcpy(priv->keys[index].key, key, key_len); - if (seq_len) - memcpy(priv->keys[index].seq, seq, seq_len); - - switch (alg) { - case ORINOCO_ALG_TKIP: - priv->keys[index].cipher = WLAN_CIPHER_SUITE_TKIP; - break; - - case ORINOCO_ALG_WEP: - priv->keys[index].cipher = (key_len > SMALL_KEY_SIZE) ? - WLAN_CIPHER_SUITE_WEP104 : WLAN_CIPHER_SUITE_WEP40; - break; - - case ORINOCO_ALG_NONE: - default: - priv->keys[index].cipher = 0; - break; - } - - return 0; - -free_key: - kfree(priv->keys[index].key); - priv->keys[index].key = NULL; - -nomem: - priv->keys[index].key_len = 0; - priv->keys[index].seq_len = 0; - priv->keys[index].cipher = 0; - - return -ENOMEM; -} - -static struct iw_statistics *orinoco_get_wireless_stats(struct net_device *dev) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - struct iw_statistics *wstats = &priv->wstats; - int err; - unsigned long flags; - - if (!netif_device_present(dev)) { - printk(KERN_WARNING "%s: get_wireless_stats() called while device not present\n", - dev->name); - return NULL; /* FIXME: Can we do better than this? */ - } - - /* If busy, return the old stats. Returning NULL may cause - * the interface to disappear from /proc/net/wireless */ - if (orinoco_lock(priv, &flags) != 0) - return wstats; - - /* We can't really wait for the tallies inquiry command to - * complete, so we just use the previous results and trigger - * a new tallies inquiry command for next time - Jean II */ - /* FIXME: Really we should wait for the inquiry to come back - - * as it is the stats we give don't make a whole lot of sense. - * Unfortunately, it's not clear how to do that within the - * wireless extensions framework: I think we're in user - * context, but a lock seems to be held by the time we get in - * here so we're not safe to sleep here. */ - hermes_inquire(hw, HERMES_INQ_TALLIES); - - if (priv->iw_mode == NL80211_IFTYPE_ADHOC) { - memset(&wstats->qual, 0, sizeof(wstats->qual)); - /* If a spy address is defined, we report stats of the - * first spy address - Jean II */ - if (SPY_NUMBER(priv)) { - wstats->qual.qual = priv->spy_data.spy_stat[0].qual; - wstats->qual.level = priv->spy_data.spy_stat[0].level; - wstats->qual.noise = priv->spy_data.spy_stat[0].noise; - wstats->qual.updated = - priv->spy_data.spy_stat[0].updated; - } - } else { - struct { - __le16 qual, signal, noise, unused; - } __attribute__ ((packed)) cq; - - err = HERMES_READ_RECORD(hw, USER_BAP, - HERMES_RID_COMMSQUALITY, &cq); - - if (!err) { - wstats->qual.qual = (int)le16_to_cpu(cq.qual); - wstats->qual.level = (int)le16_to_cpu(cq.signal) - 0x95; - wstats->qual.noise = (int)le16_to_cpu(cq.noise) - 0x95; - wstats->qual.updated = - IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - } - } - - orinoco_unlock(priv, &flags); - return wstats; -} - -/********************************************************************/ -/* Wireless extensions */ -/********************************************************************/ - -static int orinoco_ioctl_setwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - static const u8 off_addr[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - static const u8 any_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Enable automatic roaming - no sanity checks are needed */ - if (memcmp(&ap_addr->sa_data, off_addr, ETH_ALEN) == 0 || - memcmp(&ap_addr->sa_data, any_addr, ETH_ALEN) == 0) { - priv->bssid_fixed = 0; - memset(priv->desired_bssid, 0, ETH_ALEN); - - /* "off" means keep existing connection */ - if (ap_addr->sa_data[0] == 0) { - __orinoco_hw_set_wap(priv); - err = 0; - } - goto out; - } - - if (priv->firmware_type == FIRMWARE_TYPE_AGERE) { - printk(KERN_WARNING "%s: Lucent/Agere firmware doesn't " - "support manual roaming\n", - dev->name); - err = -EOPNOTSUPP; - goto out; - } - - if (priv->iw_mode != NL80211_IFTYPE_STATION) { - printk(KERN_WARNING "%s: Manual roaming supported only in " - "managed mode\n", dev->name); - err = -EOPNOTSUPP; - goto out; - } - - /* Intersil firmware hangs without Desired ESSID */ - if (priv->firmware_type == FIRMWARE_TYPE_INTERSIL && - strlen(priv->desired_essid) == 0) { - printk(KERN_WARNING "%s: Desired ESSID must be set for " - "manual roaming\n", dev->name); - err = -EOPNOTSUPP; - goto out; - } - - /* Finally, enable manual roaming */ - priv->bssid_fixed = 1; - memcpy(priv->desired_bssid, &ap_addr->sa_data, ETH_ALEN); - - out: - orinoco_unlock(priv, &flags); - return err; -} - -static int orinoco_ioctl_getwap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *ap_addr, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - - int err = 0; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - ap_addr->sa_family = ARPHRD_ETHER; - err = orinoco_hw_get_current_bssid(priv, ap_addr->sa_data); - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_setiwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *keybuf) -{ - struct orinoco_private *priv = ndev_priv(dev); - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - int setindex = priv->tx_key; - enum orinoco_alg encode_alg = priv->encode_alg; - int restricted = priv->wep_restrict; - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (!priv->has_wep) - return -EOPNOTSUPP; - - if (erq->pointer) { - /* We actually have a key to set - check its length */ - if (erq->length > LARGE_KEY_SIZE) - return -E2BIG; - - if ((erq->length > SMALL_KEY_SIZE) && !priv->has_big_wep) - return -E2BIG; - } - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Clear any TKIP key we have */ - if ((priv->has_wpa) && (priv->encode_alg == ORINOCO_ALG_TKIP)) - (void) orinoco_clear_tkip_key(priv, setindex); - - if (erq->length > 0) { - if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) - index = priv->tx_key; - - /* Switch on WEP if off */ - if (encode_alg != ORINOCO_ALG_WEP) { - setindex = index; - encode_alg = ORINOCO_ALG_WEP; - } - } else { - /* Important note : if the user do "iwconfig eth0 enc off", - * we will arrive there with an index of -1. This is valid - * but need to be taken care off... Jean II */ - if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) { - if ((index != -1) || (erq->flags == 0)) { - err = -EINVAL; - goto out; - } - } else { - /* Set the index : Check that the key is valid */ - if (priv->keys[index].key_len == 0) { - err = -EINVAL; - goto out; - } - setindex = index; - } - } - - if (erq->flags & IW_ENCODE_DISABLED) - encode_alg = ORINOCO_ALG_NONE; - if (erq->flags & IW_ENCODE_OPEN) - restricted = 0; - if (erq->flags & IW_ENCODE_RESTRICTED) - restricted = 1; - - if (erq->pointer && erq->length > 0) { - err = orinoco_set_key(priv, index, ORINOCO_ALG_WEP, keybuf, - erq->length, NULL, 0); - } - priv->tx_key = setindex; - - /* Try fast key change if connected and only keys are changed */ - if ((priv->encode_alg == encode_alg) && - (priv->wep_restrict == restricted) && - netif_carrier_ok(dev)) { - err = __orinoco_hw_setup_wepkeys(priv); - /* No need to commit if successful */ - goto out; - } - - priv->encode_alg = encode_alg; - priv->wep_restrict = restricted; - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getiwencode(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *keybuf) -{ - struct orinoco_private *priv = ndev_priv(dev); - int index = (erq->flags & IW_ENCODE_INDEX) - 1; - unsigned long flags; - - if (!priv->has_wep) - return -EOPNOTSUPP; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if ((index < 0) || (index >= ORINOCO_MAX_KEYS)) - index = priv->tx_key; - - erq->flags = 0; - if (!priv->encode_alg) - erq->flags |= IW_ENCODE_DISABLED; - erq->flags |= index + 1; - - if (priv->wep_restrict) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - erq->length = priv->keys[index].key_len; - - memcpy(keybuf, priv->keys[index].key, erq->length); - - orinoco_unlock(priv, &flags); - return 0; -} - -static int orinoco_ioctl_setessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *essidbuf) -{ - struct orinoco_private *priv = ndev_priv(dev); - unsigned long flags; - - /* Note : ESSID is ignored in Ad-Hoc demo mode, but we can set it - * anyway... - Jean II */ - - /* Hum... Should not use Wireless Extension constant (may change), - * should use our own... - Jean II */ - if (erq->length > IW_ESSID_MAX_SIZE) - return -E2BIG; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* NULL the string (for NULL termination & ESSID = ANY) - Jean II */ - memset(priv->desired_essid, 0, sizeof(priv->desired_essid)); - - /* If not ANY, get the new ESSID */ - if (erq->flags) - memcpy(priv->desired_essid, essidbuf, erq->length); - - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getessid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *erq, - char *essidbuf) -{ - struct orinoco_private *priv = ndev_priv(dev); - int active; - int err = 0; - unsigned long flags; - - if (netif_running(dev)) { - err = orinoco_hw_get_essid(priv, &active, essidbuf); - if (err < 0) - return err; - erq->length = err; - } else { - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - memcpy(essidbuf, priv->desired_essid, IW_ESSID_MAX_SIZE); - erq->length = strlen(priv->desired_essid); - orinoco_unlock(priv, &flags); - } - - erq->flags = 1; - - return 0; -} - -static int orinoco_ioctl_setfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *frq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int chan = -1; - unsigned long flags; - int err = -EINPROGRESS; /* Call commit handler */ - - /* In infrastructure mode the AP sets the channel */ - if (priv->iw_mode == NL80211_IFTYPE_STATION) - return -EBUSY; - - if ((frq->e == 0) && (frq->m <= 1000)) { - /* Setting by channel number */ - chan = frq->m; - } else { - /* Setting by frequency */ - int denom = 1; - int i; - - /* Calculate denominator to rescale to MHz */ - for (i = 0; i < (6 - frq->e); i++) - denom *= 10; - - chan = ieee80211_freq_to_dsss_chan(frq->m / denom); - } - - if ((chan < 1) || (chan > NUM_CHANNELS) || - !(priv->channel_mask & (1 << (chan-1)))) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->channel = chan; - if (priv->iw_mode == NL80211_IFTYPE_MONITOR) { - /* Fast channel change - no commit if successful */ - hermes_t *hw = &priv->hw; - err = hermes_docmd_wait(hw, HERMES_CMD_TEST | - HERMES_TEST_SET_CHANNEL, - chan, NULL); - } - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getfreq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *frq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int tmp; - - /* Locking done in there */ - tmp = orinoco_hw_get_freq(priv); - if (tmp < 0) - return tmp; - - frq->m = tmp * 100000; - frq->e = 1; - - return 0; -} - -static int orinoco_ioctl_getsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - u16 val; - int err; - unsigned long flags; - - if (!priv->has_sensitivity) - return -EOPNOTSUPP; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFSYSTEMSCALE, &val); - orinoco_unlock(priv, &flags); - - if (err) - return err; - - srq->value = val; - srq->fixed = 0; /* auto */ - - return 0; -} - -static int orinoco_ioctl_setsens(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *srq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int val = srq->value; - unsigned long flags; - - if (!priv->has_sensitivity) - return -EOPNOTSUPP; - - if ((val < 1) || (val > 3)) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - priv->ap_density = val; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_setrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int val = rrq->value; - unsigned long flags; - - if (rrq->disabled) - val = 2347; - - if ((val < 0) || (val > 2347)) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->rts_thresh = val; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getrts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - - rrq->value = priv->rts_thresh; - rrq->disabled = (rrq->value == 2347); - rrq->fixed = 1; - - return 0; -} - -static int orinoco_ioctl_setfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (priv->has_mwo) { - if (frq->disabled) - priv->mwo_robust = 0; - else { - if (frq->fixed) - printk(KERN_WARNING "%s: Fixed fragmentation " - "is not supported on this firmware. " - "Using MWO robust instead.\n", - dev->name); - priv->mwo_robust = 1; - } - } else { - if (frq->disabled) - priv->frag_thresh = 2346; - else { - if ((frq->value < 256) || (frq->value > 2346)) - err = -EINVAL; - else - /* must be even */ - priv->frag_thresh = frq->value & ~0x1; - } - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getfrag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *frq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - int err; - u16 val; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (priv->has_mwo) { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMWOROBUST_AGERE, - &val); - if (err) - val = 0; - - frq->value = val ? 2347 : 0; - frq->disabled = !val; - frq->fixed = 0; - } else { - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFFRAGMENTATIONTHRESHOLD, - &val); - if (err) - val = 0; - - frq->value = val; - frq->disabled = (val >= 2346); - frq->fixed = 1; - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_setrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int ratemode; - int bitrate; /* 100s of kilobits */ - unsigned long flags; - - /* As the user space doesn't know our highest rate, it uses -1 - * to ask us to set the highest rate. Test it using "iwconfig - * ethX rate auto" - Jean II */ - if (rrq->value == -1) - bitrate = 110; - else { - if (rrq->value % 100000) - return -EINVAL; - bitrate = rrq->value / 100000; - } - - ratemode = orinoco_get_bitratemode(bitrate, !rrq->fixed); - - if (ratemode == -1) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - priv->bitratemode = ratemode; - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; -} - -static int orinoco_ioctl_getrate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = 0; - int bitrate, automatic; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - orinoco_get_ratemode_cfg(priv->bitratemode, &bitrate, &automatic); - - /* If the interface is running we try to find more about the - current mode */ - if (netif_running(dev)) - err = orinoco_hw_get_act_bitrate(priv, &bitrate); - - orinoco_unlock(priv, &flags); - - rrq->value = bitrate; - rrq->fixed = !automatic; - rrq->disabled = 0; - - return err; -} - -static int orinoco_ioctl_setpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *prq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (prq->disabled) { - priv->pm_on = 0; - } else { - switch (prq->flags & IW_POWER_MODE) { - case IW_POWER_UNICAST_R: - priv->pm_mcast = 0; - priv->pm_on = 1; - break; - case IW_POWER_ALL_R: - priv->pm_mcast = 1; - priv->pm_on = 1; - break; - case IW_POWER_ON: - /* No flags : but we may have a value - Jean II */ - break; - default: - err = -EINVAL; - goto out; - } - - if (prq->flags & IW_POWER_TIMEOUT) { - priv->pm_on = 1; - priv->pm_timeout = prq->value / 1000; - } - if (prq->flags & IW_POWER_PERIOD) { - priv->pm_on = 1; - priv->pm_period = prq->value / 1000; - } - /* It's valid to not have a value if we are just toggling - * the flags... Jean II */ - if (!priv->pm_on) { - err = -EINVAL; - goto out; - } - } - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getpower(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *prq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - int err = 0; - u16 enable, period, timeout, mcast; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMENABLED, &enable); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMAXSLEEPDURATION, &period); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFPMHOLDOVERDURATION, &timeout); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, - HERMES_RID_CNFMULTICASTRECEIVE, &mcast); - if (err) - goto out; - - prq->disabled = !enable; - /* Note : by default, display the period */ - if ((prq->flags & IW_POWER_TYPE) == IW_POWER_TIMEOUT) { - prq->flags = IW_POWER_TIMEOUT; - prq->value = timeout * 1000; - } else { - prq->flags = IW_POWER_PERIOD; - prq->value = period * 1000; - } - if (mcast) - prq->flags |= IW_POWER_ALL_R; - else - prq->flags |= IW_POWER_UNICAST_R; - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_set_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, alg = ext->alg, set_key = 1; - unsigned long flags; - int err = -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - /* Determine and validate the key index */ - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if ((idx < 1) || (idx > 4)) - goto out; - idx--; - } else - idx = priv->tx_key; - - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; - - if (priv->has_wpa && (alg != IW_ENCODE_ALG_TKIP)) { - /* Clear any TKIP TX key we had */ - (void) orinoco_clear_tkip_key(priv, priv->tx_key); - } - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - priv->tx_key = idx; - set_key = ((alg == IW_ENCODE_ALG_TKIP) || - (ext->key_len > 0)) ? 1 : 0; - } - - if (set_key) { - /* Set the requested key first */ - switch (alg) { - case IW_ENCODE_ALG_NONE: - priv->encode_alg = ORINOCO_ALG_NONE; - err = orinoco_set_key(priv, idx, ORINOCO_ALG_NONE, - NULL, 0, NULL, 0); - break; - - case IW_ENCODE_ALG_WEP: - if (ext->key_len <= 0) - goto out; - - priv->encode_alg = ORINOCO_ALG_WEP; - err = orinoco_set_key(priv, idx, ORINOCO_ALG_WEP, - ext->key, ext->key_len, NULL, 0); - break; - - case IW_ENCODE_ALG_TKIP: - { - u8 *tkip_iv = NULL; - - if (!priv->has_wpa || - (ext->key_len > sizeof(struct orinoco_tkip_key))) - goto out; - - priv->encode_alg = ORINOCO_ALG_TKIP; - - if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) - tkip_iv = &ext->rx_seq[0]; - - err = orinoco_set_key(priv, idx, ORINOCO_ALG_TKIP, - ext->key, ext->key_len, tkip_iv, - ORINOCO_SEQ_LEN); - - err = __orinoco_hw_set_tkip_key(priv, idx, - ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY, - priv->keys[idx].key, - tkip_iv, ORINOCO_SEQ_LEN, NULL, 0); - if (err) - printk(KERN_ERR "%s: Error %d setting TKIP key" - "\n", dev->name, err); - - goto out; - } - default: - goto out; - } - } - err = -EINPROGRESS; - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_get_encodeext(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, max_key_len; - unsigned long flags; - int err; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = -EINVAL; - max_key_len = encoding->length - sizeof(*ext); - if (max_key_len < 0) - goto out; - - idx = encoding->flags & IW_ENCODE_INDEX; - if (idx) { - if ((idx < 1) || (idx > 4)) - goto out; - idx--; - } else - idx = priv->tx_key; - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - switch (priv->encode_alg) { - case ORINOCO_ALG_NONE: - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - encoding->flags |= IW_ENCODE_DISABLED; - break; - case ORINOCO_ALG_WEP: - ext->alg = IW_ENCODE_ALG_WEP; - ext->key_len = min(priv->keys[idx].key_len, max_key_len); - memcpy(ext->key, priv->keys[idx].key, ext->key_len); - encoding->flags |= IW_ENCODE_ENABLED; - break; - case ORINOCO_ALG_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; - ext->key_len = min(priv->keys[idx].key_len, max_key_len); - memcpy(ext->key, priv->keys[idx].key, ext->key_len); - encoding->flags |= IW_ENCODE_ENABLED; - break; - } - - err = 0; - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_set_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - struct iw_param *param = &wrqu->param; - unsigned long flags; - int ret = -EINPROGRESS; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_WPA_VERSION: - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - case IW_AUTH_PRIVACY_INVOKED: - case IW_AUTH_DROP_UNENCRYPTED: - /* - * orinoco does not use these parameters - */ - break; - - case IW_AUTH_KEY_MGMT: - /* wl_lkm implies value 2 == PSK for Hermes I - * which ties in with WEXT - * no other hints tho :( - */ - priv->key_mgmt = param->value; - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - /* When countermeasures are enabled, shut down the - * card; when disabled, re-enable the card. This must - * take effect immediately. - * - * TODO: Make sure that the EAPOL message is getting - * out before card disabled - */ - if (param->value) { - priv->tkip_cm_active = 1; - ret = hermes_enable_port(hw, 0); - } else { - priv->tkip_cm_active = 0; - ret = hermes_disable_port(hw, 0); - } - break; - - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_SHARED_KEY) - priv->wep_restrict = 1; - else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) - priv->wep_restrict = 0; - else - ret = -EINVAL; - break; - - case IW_AUTH_WPA_ENABLED: - if (priv->has_wpa) { - priv->wpa_enabled = param->value ? 1 : 0; - } else { - if (param->value) - ret = -EOPNOTSUPP; - /* else silently accept disable of WPA */ - priv->wpa_enabled = 0; - } - break; - - default: - ret = -EOPNOTSUPP; - } - - orinoco_unlock(priv, &flags); - return ret; -} - -static int orinoco_ioctl_get_auth(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct iw_param *param = &wrqu->param; - unsigned long flags; - int ret = 0; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_KEY_MGMT: - param->value = priv->key_mgmt; - break; - - case IW_AUTH_TKIP_COUNTERMEASURES: - param->value = priv->tkip_cm_active; - break; - - case IW_AUTH_80211_AUTH_ALG: - if (priv->wep_restrict) - param->value = IW_AUTH_ALG_SHARED_KEY; - else - param->value = IW_AUTH_ALG_OPEN_SYSTEM; - break; - - case IW_AUTH_WPA_ENABLED: - param->value = priv->wpa_enabled; - break; - - default: - ret = -EOPNOTSUPP; - } - - orinoco_unlock(priv, &flags); - return ret; -} - -static int orinoco_ioctl_set_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - u8 *buf; - unsigned long flags; - - /* cut off at IEEE80211_MAX_DATA_LEN */ - if ((wrqu->data.length > IEEE80211_MAX_DATA_LEN) || - (wrqu->data.length && (extra == NULL))) - return -EINVAL; - - if (wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_KERNEL); - if (buf == NULL) - return -ENOMEM; - - memcpy(buf, extra, wrqu->data.length); - } else - buf = NULL; - - if (orinoco_lock(priv, &flags) != 0) { - kfree(buf); - return -EBUSY; - } - - kfree(priv->wpa_ie); - priv->wpa_ie = buf; - priv->wpa_ie_len = wrqu->data.length; - - if (priv->wpa_ie) { - /* Looks like wl_lkm wants to check the auth alg, and - * somehow pass it to the firmware. - * Instead it just calls the key mgmt rid - * - we do this in set auth. - */ - } - - orinoco_unlock(priv, &flags); - return 0; -} - -static int orinoco_ioctl_get_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - unsigned long flags; - int err = 0; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if ((priv->wpa_ie_len == 0) || (priv->wpa_ie == NULL)) { - wrqu->data.length = 0; - goto out; - } - - if (wrqu->data.length < priv->wpa_ie_len) { - err = -E2BIG; - goto out; - } - - wrqu->data.length = priv->wpa_ie_len; - memcpy(extra, priv->wpa_ie, priv->wpa_ie_len); - -out: - orinoco_unlock(priv, &flags); - return err; -} - -static int orinoco_ioctl_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - struct iw_mlme *mlme = (struct iw_mlme *)extra; - unsigned long flags; - int ret = 0; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - /* silently ignore */ - break; - - case IW_MLME_DISASSOC: - - ret = orinoco_hw_disassociate(priv, mlme->addr.sa_data, - mlme->reason_code); - break; - - default: - ret = -EOPNOTSUPP; - } - - orinoco_unlock(priv, &flags); - return ret; -} - -static int orinoco_ioctl_getretry(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *rrq, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - int err = 0; - u16 short_limit, long_limit, lifetime; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_SHORTRETRYLIMIT, - &short_limit); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_LONGRETRYLIMIT, - &long_limit); - if (err) - goto out; - - err = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_MAXTRANSMITLIFETIME, - &lifetime); - if (err) - goto out; - - rrq->disabled = 0; /* Can't be disabled */ - - /* Note : by default, display the retry number */ - if ((rrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - rrq->flags = IW_RETRY_LIFETIME; - rrq->value = lifetime * 1000; /* ??? */ - } else { - /* By default, display the min number */ - if ((rrq->flags & IW_RETRY_LONG)) { - rrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - rrq->value = long_limit; - } else { - rrq->flags = IW_RETRY_LIMIT; - rrq->value = short_limit; - if (short_limit != long_limit) - rrq->flags |= IW_RETRY_SHORT; - } - } - - out: - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_reset(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (info->cmd == (SIOCIWFIRSTPRIV + 0x1)) { - printk(KERN_DEBUG "%s: Forcing reset!\n", dev->name); - - /* Firmware reset */ - orinoco_reset(&priv->reset_work); - } else { - printk(KERN_DEBUG "%s: Force scheduling reset!\n", dev->name); - - schedule_work(&priv->reset_work); - } - - return 0; -} - -static int orinoco_ioctl_setibssport(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) - -{ - struct orinoco_private *priv = ndev_priv(dev); - int val = *((int *) extra); - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - priv->ibss_port = val; - - /* Actually update the mode we are using */ - set_port_type(priv); - - orinoco_unlock(priv, &flags); - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getibssport(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int *val = (int *) extra; - - *val = priv->ibss_port; - return 0; -} - -static int orinoco_ioctl_setport3(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int val = *((int *) extra); - int err = 0; - unsigned long flags; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - switch (val) { - case 0: /* Try to do IEEE ad-hoc mode */ - if (!priv->has_ibss) { - err = -EINVAL; - break; - } - priv->prefer_port3 = 0; - - break; - - case 1: /* Try to do Lucent proprietary ad-hoc mode */ - if (!priv->has_port3) { - err = -EINVAL; - break; - } - priv->prefer_port3 = 1; - break; - - default: - err = -EINVAL; - } - - if (!err) { - /* Actually update the mode we are using */ - set_port_type(priv); - err = -EINPROGRESS; - } - - orinoco_unlock(priv, &flags); - - return err; -} - -static int orinoco_ioctl_getport3(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int *val = (int *) extra; - - *val = priv->prefer_port3; - return 0; -} - -static int orinoco_ioctl_setpreamble(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - unsigned long flags; - int val; - - if (!priv->has_preamble) - return -EOPNOTSUPP; - - /* 802.11b has recently defined some short preamble. - * Basically, the Phy header has been reduced in size. - * This increase performance, especially at high rates - * (the preamble is transmitted at 1Mb/s), unfortunately - * this give compatibility troubles... - Jean II */ - val = *((int *) extra); - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - if (val) - priv->preamble = 1; - else - priv->preamble = 0; - - orinoco_unlock(priv, &flags); - - return -EINPROGRESS; /* Call commit handler */ -} - -static int orinoco_ioctl_getpreamble(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - int *val = (int *) extra; - - if (!priv->has_preamble) - return -EOPNOTSUPP; - - *val = priv->preamble; - return 0; -} - -/* ioctl interface to hermes_read_ltv() - * To use with iwpriv, pass the RID as the token argument, e.g. - * iwpriv get_rid [0xfc00] - * At least Wireless Tools 25 is required to use iwpriv. - * For Wireless Tools 25 and 26 append "dummy" are the end. */ -static int orinoco_ioctl_getrid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *data, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - hermes_t *hw = &priv->hw; - int rid = data->flags; - u16 length; - int err; - unsigned long flags; - - /* It's a "get" function, but we don't want users to access the - * WEP key and other raw firmware data */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (rid < 0xfc00 || rid > 0xffff) - return -EINVAL; - - if (orinoco_lock(priv, &flags) != 0) - return -EBUSY; - - err = hermes_read_ltv(hw, USER_BAP, rid, MAX_RID_LEN, &length, - extra); - if (err) - goto out; - - data->length = min_t(u16, HERMES_RECLEN_TO_BYTES(length), - MAX_RID_LEN); - - out: - orinoco_unlock(priv, &flags); - return err; -} - - -/* Commit handler, called after set operations */ -static int orinoco_ioctl_commit(struct net_device *dev, - struct iw_request_info *info, - void *wrqu, - char *extra) -{ - struct orinoco_private *priv = ndev_priv(dev); - unsigned long flags; - int err = 0; - - if (!priv->open) - return 0; - - if (orinoco_lock(priv, &flags) != 0) - return err; - - err = orinoco_commit(priv); - - orinoco_unlock(priv, &flags); - return err; -} - -static const struct iw_priv_args orinoco_privtab[] = { - { SIOCIWFIRSTPRIV + 0x0, 0, 0, "force_reset" }, - { SIOCIWFIRSTPRIV + 0x1, 0, 0, "card_reset" }, - { SIOCIWFIRSTPRIV + 0x2, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_port3" }, - { SIOCIWFIRSTPRIV + 0x3, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_port3" }, - { SIOCIWFIRSTPRIV + 0x4, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_preamble" }, - { SIOCIWFIRSTPRIV + 0x5, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_preamble" }, - { SIOCIWFIRSTPRIV + 0x6, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - 0, "set_ibssport" }, - { SIOCIWFIRSTPRIV + 0x7, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_ibssport" }, - { SIOCIWFIRSTPRIV + 0x9, 0, IW_PRIV_TYPE_BYTE | MAX_RID_LEN, - "get_rid" }, -}; - - -/* - * Structures to export the Wireless Handlers - */ - -#define STD_IW_HANDLER(id, func) \ - [IW_IOCTL_IDX(id)] = (iw_handler) func -static const iw_handler orinoco_handler[] = { - STD_IW_HANDLER(SIOCSIWCOMMIT, orinoco_ioctl_commit), - STD_IW_HANDLER(SIOCGIWNAME, cfg80211_wext_giwname), - STD_IW_HANDLER(SIOCSIWFREQ, orinoco_ioctl_setfreq), - STD_IW_HANDLER(SIOCGIWFREQ, orinoco_ioctl_getfreq), - STD_IW_HANDLER(SIOCSIWMODE, cfg80211_wext_siwmode), - STD_IW_HANDLER(SIOCGIWMODE, cfg80211_wext_giwmode), - STD_IW_HANDLER(SIOCSIWSENS, orinoco_ioctl_setsens), - STD_IW_HANDLER(SIOCGIWSENS, orinoco_ioctl_getsens), - STD_IW_HANDLER(SIOCGIWRANGE, cfg80211_wext_giwrange), - STD_IW_HANDLER(SIOCSIWSPY, iw_handler_set_spy), - STD_IW_HANDLER(SIOCGIWSPY, iw_handler_get_spy), - STD_IW_HANDLER(SIOCSIWTHRSPY, iw_handler_set_thrspy), - STD_IW_HANDLER(SIOCGIWTHRSPY, iw_handler_get_thrspy), - STD_IW_HANDLER(SIOCSIWAP, orinoco_ioctl_setwap), - STD_IW_HANDLER(SIOCGIWAP, orinoco_ioctl_getwap), - STD_IW_HANDLER(SIOCSIWSCAN, cfg80211_wext_siwscan), - STD_IW_HANDLER(SIOCGIWSCAN, cfg80211_wext_giwscan), - STD_IW_HANDLER(SIOCSIWESSID, orinoco_ioctl_setessid), - STD_IW_HANDLER(SIOCGIWESSID, orinoco_ioctl_getessid), - STD_IW_HANDLER(SIOCSIWRATE, orinoco_ioctl_setrate), - STD_IW_HANDLER(SIOCGIWRATE, orinoco_ioctl_getrate), - STD_IW_HANDLER(SIOCSIWRTS, orinoco_ioctl_setrts), - STD_IW_HANDLER(SIOCGIWRTS, orinoco_ioctl_getrts), - STD_IW_HANDLER(SIOCSIWFRAG, orinoco_ioctl_setfrag), - STD_IW_HANDLER(SIOCGIWFRAG, orinoco_ioctl_getfrag), - STD_IW_HANDLER(SIOCGIWRETRY, orinoco_ioctl_getretry), - STD_IW_HANDLER(SIOCSIWENCODE, orinoco_ioctl_setiwencode), - STD_IW_HANDLER(SIOCGIWENCODE, orinoco_ioctl_getiwencode), - STD_IW_HANDLER(SIOCSIWPOWER, orinoco_ioctl_setpower), - STD_IW_HANDLER(SIOCGIWPOWER, orinoco_ioctl_getpower), - STD_IW_HANDLER(SIOCSIWGENIE, orinoco_ioctl_set_genie), - STD_IW_HANDLER(SIOCGIWGENIE, orinoco_ioctl_get_genie), - STD_IW_HANDLER(SIOCSIWMLME, orinoco_ioctl_set_mlme), - STD_IW_HANDLER(SIOCSIWAUTH, orinoco_ioctl_set_auth), - STD_IW_HANDLER(SIOCGIWAUTH, orinoco_ioctl_get_auth), - STD_IW_HANDLER(SIOCSIWENCODEEXT, orinoco_ioctl_set_encodeext), - STD_IW_HANDLER(SIOCGIWENCODEEXT, orinoco_ioctl_get_encodeext), -}; - - -/* - Added typecasting since we no longer use iwreq_data -- Moustafa - */ -static const iw_handler orinoco_private_handler[] = { - [0] = (iw_handler) orinoco_ioctl_reset, - [1] = (iw_handler) orinoco_ioctl_reset, - [2] = (iw_handler) orinoco_ioctl_setport3, - [3] = (iw_handler) orinoco_ioctl_getport3, - [4] = (iw_handler) orinoco_ioctl_setpreamble, - [5] = (iw_handler) orinoco_ioctl_getpreamble, - [6] = (iw_handler) orinoco_ioctl_setibssport, - [7] = (iw_handler) orinoco_ioctl_getibssport, - [9] = (iw_handler) orinoco_ioctl_getrid, -}; - -const struct iw_handler_def orinoco_handler_def = { - .num_standard = ARRAY_SIZE(orinoco_handler), - .num_private = ARRAY_SIZE(orinoco_private_handler), - .num_private_args = ARRAY_SIZE(orinoco_privtab), - .standard = orinoco_handler, - .private = orinoco_private_handler, - .private_args = orinoco_privtab, - .get_wireless_stats = orinoco_get_wireless_stats, -}; diff --git a/drivers/net/wireless/orinoco/wext.h b/drivers/net/wireless/orinoco/wext.h deleted file mode 100644 index 1479f4e26dde..000000000000 --- a/drivers/net/wireless/orinoco/wext.h +++ /dev/null @@ -1,13 +0,0 @@ -/* Wireless extensions support. - * - * See copyright notice in main.c - */ -#ifndef _ORINOCO_WEXT_H_ -#define _ORINOCO_WEXT_H_ - -#include - -/* Structure defining all our WEXT handlers */ -extern const struct iw_handler_def orinoco_handler_def; - -#endif /* _ORINOCO_WEXT_H_ */ diff --git a/drivers/net/wireless/p54/Kconfig b/drivers/net/wireless/p54/Kconfig deleted file mode 100644 index b45d6a4ed1e8..000000000000 --- a/drivers/net/wireless/p54/Kconfig +++ /dev/null @@ -1,54 +0,0 @@ -config P54_COMMON - tristate "Softmac Prism54 support" - depends on MAC80211 && WLAN_80211 && EXPERIMENTAL - select FW_LOADER - ---help--- - This is common code for isl38xx/stlc45xx based modules. - This module does nothing by itself - the USB/PCI/SPI front-ends - also need to be enabled in order to support any devices. - - These devices require softmac firmware which can be found at - http://prism54.org/ - - If you choose to build a module, it'll be called p54common. - -config P54_USB - tristate "Prism54 USB support" - depends on P54_COMMON && USB - select CRC32 - ---help--- - This driver is for USB isl38xx based wireless cards. - - These devices require softmac firmware which can be found at - http://prism54.org/ - - If you choose to build a module, it'll be called p54usb. - -config P54_PCI - tristate "Prism54 PCI support" - depends on P54_COMMON && PCI - ---help--- - This driver is for PCI isl38xx based wireless cards. - This driver supports most devices that are supported by the - fullmac prism54 driver plus many devices which are not - supported by the fullmac driver/firmware. - - This driver requires softmac firmware which can be found at - http://prism54.org/ - - If you choose to build a module, it'll be called p54pci. - -config P54_SPI - tristate "Prism54 SPI (stlc45xx) support" - depends on P54_COMMON && SPI_MASTER && GENERIC_HARDIRQS - ---help--- - This driver is for stlc4550 or stlc4560 based wireless chips. - This driver is experimental, untested and will probably only work on - Nokia's N800/N810 Portable Internet Tablet. - - If you choose to build a module, it'll be called p54spi. - -config P54_LEDS - bool - depends on P54_COMMON && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = P54_COMMON) - default y diff --git a/drivers/net/wireless/p54/Makefile b/drivers/net/wireless/p54/Makefile deleted file mode 100644 index b542e68f1781..000000000000 --- a/drivers/net/wireless/p54/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -p54common-objs := eeprom.o fwio.o txrx.o main.o -p54common-$(CONFIG_P54_LEDS) += led.o - -obj-$(CONFIG_P54_COMMON) += p54common.o -obj-$(CONFIG_P54_USB) += p54usb.o -obj-$(CONFIG_P54_PCI) += p54pci.o -obj-$(CONFIG_P54_SPI) += p54spi.o diff --git a/drivers/net/wireless/p54/eeprom.c b/drivers/net/wireless/p54/eeprom.c deleted file mode 100644 index 2c31eb4c21a2..000000000000 --- a/drivers/net/wireless/p54/eeprom.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * EEPROM parser code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007-2009, Christian Lamparter - * Copyright 2008, Johannes Berg - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - stlc45xx driver - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include - -#include "p54.h" -#include "eeprom.h" -#include "lmac.h" - -static struct ieee80211_rate p54_bgrates[] = { - { .bitrate = 10, .hw_value = 0, }, - { .bitrate = 20, .hw_value = 1, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, .hw_value = 2, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, .hw_value = 3, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -static struct ieee80211_rate p54_arates[] = { - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -#define CHAN_HAS_CAL BIT(0) -#define CHAN_HAS_LIMIT BIT(1) -#define CHAN_HAS_CURVE BIT(2) -#define CHAN_HAS_ALL (CHAN_HAS_CAL | CHAN_HAS_LIMIT | CHAN_HAS_CURVE) - -struct p54_channel_entry { - u16 freq; - u16 data; - int index; - enum ieee80211_band band; -}; - -struct p54_channel_list { - struct p54_channel_entry *channels; - size_t entries; - size_t max_entries; - size_t band_channel_num[IEEE80211_NUM_BANDS]; -}; - -static int p54_get_band_from_freq(u16 freq) -{ - /* FIXME: sync these values with the 802.11 spec */ - - if ((freq >= 2412) && (freq <= 2484)) - return IEEE80211_BAND_2GHZ; - - if ((freq >= 4920) && (freq <= 5825)) - return IEEE80211_BAND_5GHZ; - - return -1; -} - -static int p54_compare_channels(const void *_a, - const void *_b) -{ - const struct p54_channel_entry *a = _a; - const struct p54_channel_entry *b = _b; - - return a->index - b->index; -} - -static int p54_fill_band_bitrates(struct ieee80211_hw *dev, - struct ieee80211_supported_band *band_entry, - enum ieee80211_band band) -{ - /* TODO: generate rate array dynamically */ - - switch (band) { - case IEEE80211_BAND_2GHZ: - band_entry->bitrates = p54_bgrates; - band_entry->n_bitrates = ARRAY_SIZE(p54_bgrates); - break; - case IEEE80211_BAND_5GHZ: - band_entry->bitrates = p54_arates; - band_entry->n_bitrates = ARRAY_SIZE(p54_arates); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int p54_generate_band(struct ieee80211_hw *dev, - struct p54_channel_list *list, - enum ieee80211_band band) -{ - struct p54_common *priv = dev->priv; - struct ieee80211_supported_band *tmp, *old; - unsigned int i, j; - int ret = -ENOMEM; - - if ((!list->entries) || (!list->band_channel_num[band])) - return -EINVAL; - - tmp = kzalloc(sizeof(*tmp), GFP_KERNEL); - if (!tmp) - goto err_out; - - tmp->channels = kzalloc(sizeof(struct ieee80211_channel) * - list->band_channel_num[band], GFP_KERNEL); - if (!tmp->channels) - goto err_out; - - ret = p54_fill_band_bitrates(dev, tmp, band); - if (ret) - goto err_out; - - for (i = 0, j = 0; (j < list->band_channel_num[band]) && - (i < list->entries); i++) { - - if (list->channels[i].band != band) - continue; - - if (list->channels[i].data != CHAN_HAS_ALL) { - printk(KERN_ERR "%s:%s%s%s is/are missing for " - "channel:%d [%d MHz].\n", - wiphy_name(dev->wiphy), - (list->channels[i].data & CHAN_HAS_CAL ? "" : - " [iqauto calibration data]"), - (list->channels[i].data & CHAN_HAS_LIMIT ? "" : - " [output power limits]"), - (list->channels[i].data & CHAN_HAS_CURVE ? "" : - " [curve data]"), - list->channels[i].index, list->channels[i].freq); - continue; - } - - tmp->channels[j].band = list->channels[i].band; - tmp->channels[j].center_freq = list->channels[i].freq; - j++; - } - - if (j == 0) { - printk(KERN_ERR "%s: Disabling totally damaged %s band.\n", - wiphy_name(dev->wiphy), (band == IEEE80211_BAND_2GHZ) ? - "2 GHz" : "5 GHz"); - - ret = -ENODATA; - goto err_out; - } - - tmp->n_channels = j; - old = priv->band_table[band]; - priv->band_table[band] = tmp; - if (old) { - kfree(old->channels); - kfree(old); - } - - return 0; - -err_out: - if (tmp) { - kfree(tmp->channels); - kfree(tmp); - } - - return ret; -} - -static void p54_update_channel_param(struct p54_channel_list *list, - u16 freq, u16 data) -{ - int band, i; - - /* - * usually all lists in the eeprom are mostly sorted. - * so it's very likely that the entry we are looking for - * is right at the end of the list - */ - for (i = list->entries; i >= 0; i--) { - if (freq == list->channels[i].freq) { - list->channels[i].data |= data; - break; - } - } - - if ((i < 0) && (list->entries < list->max_entries)) { - /* entry does not exist yet. Initialize a new one. */ - band = p54_get_band_from_freq(freq); - - /* - * filter out frequencies which don't belong into - * any supported band. - */ - if (band < 0) - return ; - - i = list->entries++; - list->band_channel_num[band]++; - - list->channels[i].freq = freq; - list->channels[i].data = data; - list->channels[i].band = band; - list->channels[i].index = ieee80211_frequency_to_channel(freq); - /* TODO: parse output_limit and fill max_power */ - } -} - -static int p54_generate_channel_lists(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - struct p54_channel_list *list; - unsigned int i, j, max_channel_num; - int ret = 0; - u16 freq; - - if ((priv->iq_autocal_len != priv->curve_data->entries) || - (priv->iq_autocal_len != priv->output_limit->entries)) - printk(KERN_ERR "%s: Unsupported or damaged EEPROM detected. " - "You may not be able to use all channels.\n", - wiphy_name(dev->wiphy)); - - max_channel_num = max_t(unsigned int, priv->output_limit->entries, - priv->iq_autocal_len); - max_channel_num = max_t(unsigned int, max_channel_num, - priv->curve_data->entries); - - list = kzalloc(sizeof(*list), GFP_KERNEL); - if (!list) { - ret = -ENOMEM; - goto free; - } - - list->max_entries = max_channel_num; - list->channels = kzalloc(sizeof(struct p54_channel_entry) * - max_channel_num, GFP_KERNEL); - if (!list->channels) { - ret = -ENOMEM; - goto free; - } - - for (i = 0; i < max_channel_num; i++) { - if (i < priv->iq_autocal_len) { - freq = le16_to_cpu(priv->iq_autocal[i].freq); - p54_update_channel_param(list, freq, CHAN_HAS_CAL); - } - - if (i < priv->output_limit->entries) { - freq = le16_to_cpup((__le16 *) (i * - priv->output_limit->entry_size + - priv->output_limit->offset + - priv->output_limit->data)); - - p54_update_channel_param(list, freq, CHAN_HAS_LIMIT); - } - - if (i < priv->curve_data->entries) { - freq = le16_to_cpup((__le16 *) (i * - priv->curve_data->entry_size + - priv->curve_data->offset + - priv->curve_data->data)); - - p54_update_channel_param(list, freq, CHAN_HAS_CURVE); - } - } - - /* sort the list by the channel index */ - sort(list->channels, list->entries, sizeof(struct p54_channel_entry), - p54_compare_channels, NULL); - - for (i = 0, j = 0; i < IEEE80211_NUM_BANDS; i++) { - if (p54_generate_band(dev, list, i) == 0) - j++; - } - if (j == 0) { - /* no useable band available. */ - ret = -EINVAL; - } - -free: - if (list) { - kfree(list->channels); - kfree(list); - } - - return ret; -} - -static int p54_convert_rev0(struct ieee80211_hw *dev, - struct pda_pa_curve_data *curve_data) -{ - struct p54_common *priv = dev->priv; - struct p54_pa_curve_data_sample *dst; - struct pda_pa_curve_data_sample_rev0 *src; - size_t cd_len = sizeof(*curve_data) + - (curve_data->points_per_channel*sizeof(*dst) + 2) * - curve_data->channels; - unsigned int i, j; - void *source, *target; - - priv->curve_data = kmalloc(sizeof(*priv->curve_data) + cd_len, - GFP_KERNEL); - if (!priv->curve_data) - return -ENOMEM; - - priv->curve_data->entries = curve_data->channels; - priv->curve_data->entry_size = sizeof(__le16) + - sizeof(*dst) * curve_data->points_per_channel; - priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data); - priv->curve_data->len = cd_len; - memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data)); - source = curve_data->data; - target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data; - for (i = 0; i < curve_data->channels; i++) { - __le16 *freq = source; - source += sizeof(__le16); - *((__le16 *)target) = *freq; - target += sizeof(__le16); - for (j = 0; j < curve_data->points_per_channel; j++) { - dst = target; - src = source; - - dst->rf_power = src->rf_power; - dst->pa_detector = src->pa_detector; - dst->data_64qam = src->pcv; - /* "invent" the points for the other modulations */ -#define SUB(x, y) (u8)(((x) - (y)) > (x) ? 0 : (x) - (y)) - dst->data_16qam = SUB(src->pcv, 12); - dst->data_qpsk = SUB(dst->data_16qam, 12); - dst->data_bpsk = SUB(dst->data_qpsk, 12); - dst->data_barker = SUB(dst->data_bpsk, 14); -#undef SUB - target += sizeof(*dst); - source += sizeof(*src); - } - } - - return 0; -} - -static int p54_convert_rev1(struct ieee80211_hw *dev, - struct pda_pa_curve_data *curve_data) -{ - struct p54_common *priv = dev->priv; - struct p54_pa_curve_data_sample *dst; - struct pda_pa_curve_data_sample_rev1 *src; - size_t cd_len = sizeof(*curve_data) + - (curve_data->points_per_channel*sizeof(*dst) + 2) * - curve_data->channels; - unsigned int i, j; - void *source, *target; - - priv->curve_data = kzalloc(cd_len + sizeof(*priv->curve_data), - GFP_KERNEL); - if (!priv->curve_data) - return -ENOMEM; - - priv->curve_data->entries = curve_data->channels; - priv->curve_data->entry_size = sizeof(__le16) + - sizeof(*dst) * curve_data->points_per_channel; - priv->curve_data->offset = offsetof(struct pda_pa_curve_data, data); - priv->curve_data->len = cd_len; - memcpy(priv->curve_data->data, curve_data, sizeof(*curve_data)); - source = curve_data->data; - target = ((struct pda_pa_curve_data *) priv->curve_data->data)->data; - for (i = 0; i < curve_data->channels; i++) { - __le16 *freq = source; - source += sizeof(__le16); - *((__le16 *)target) = *freq; - target += sizeof(__le16); - for (j = 0; j < curve_data->points_per_channel; j++) { - memcpy(target, source, sizeof(*src)); - - target += sizeof(*dst); - source += sizeof(*src); - } - source++; - } - - return 0; -} - -static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2", - "Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" }; - -static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len, - u16 type) -{ - struct p54_common *priv = dev->priv; - int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0; - int entry_size = sizeof(struct pda_rssi_cal_entry) + offset; - int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2; - int i; - - if (len != (entry_size * num_entries)) { - printk(KERN_ERR "%s: unknown rssi calibration data packing " - " type:(%x) len:%d.\n", - wiphy_name(dev->wiphy), type, len); - - print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, - data, len); - - printk(KERN_ERR "%s: please report this issue.\n", - wiphy_name(dev->wiphy)); - return; - } - - for (i = 0; i < num_entries; i++) { - struct pda_rssi_cal_entry *cal = data + - (offset + i * entry_size); - priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul); - priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add); - } -} - -static void p54_parse_default_country(struct ieee80211_hw *dev, - void *data, int len) -{ - struct pda_country *country; - - if (len != sizeof(*country)) { - printk(KERN_ERR "%s: found possible invalid default country " - "eeprom entry. (entry size: %d)\n", - wiphy_name(dev->wiphy), len); - - print_hex_dump_bytes("country:", DUMP_PREFIX_NONE, - data, len); - - printk(KERN_ERR "%s: please report this issue.\n", - wiphy_name(dev->wiphy)); - return; - } - - country = (struct pda_country *) data; - if (country->flags == PDR_COUNTRY_CERT_CODE_PSEUDO) - regulatory_hint(dev->wiphy, country->alpha2); - else { - /* TODO: - * write a shared/common function that converts - * "Regulatory domain codes" (802.11-2007 14.8.2.2) - * into ISO/IEC 3166-1 alpha2 for regulatory_hint. - */ - } -} - -static int p54_convert_output_limits(struct ieee80211_hw *dev, - u8 *data, size_t len) -{ - struct p54_common *priv = dev->priv; - - if (len < 2) - return -EINVAL; - - if (data[0] != 0) { - printk(KERN_ERR "%s: unknown output power db revision:%x\n", - wiphy_name(dev->wiphy), data[0]); - return -EINVAL; - } - - if (2 + data[1] * sizeof(struct pda_channel_output_limit) > len) - return -EINVAL; - - priv->output_limit = kmalloc(data[1] * - sizeof(struct pda_channel_output_limit) + - sizeof(*priv->output_limit), GFP_KERNEL); - - if (!priv->output_limit) - return -ENOMEM; - - priv->output_limit->offset = 0; - priv->output_limit->entries = data[1]; - priv->output_limit->entry_size = - sizeof(struct pda_channel_output_limit); - priv->output_limit->len = priv->output_limit->entry_size * - priv->output_limit->entries + - priv->output_limit->offset; - - memcpy(priv->output_limit->data, &data[2], - data[1] * sizeof(struct pda_channel_output_limit)); - - return 0; -} - -static struct p54_cal_database *p54_convert_db(struct pda_custom_wrapper *src, - size_t total_len) -{ - struct p54_cal_database *dst; - size_t payload_len, entries, entry_size, offset; - - payload_len = le16_to_cpu(src->len); - entries = le16_to_cpu(src->entries); - entry_size = le16_to_cpu(src->entry_size); - offset = le16_to_cpu(src->offset); - if (((entries * entry_size + offset) != payload_len) || - (payload_len + sizeof(*src) != total_len)) - return NULL; - - dst = kmalloc(sizeof(*dst) + payload_len, GFP_KERNEL); - if (!dst) - return NULL; - - dst->entries = entries; - dst->entry_size = entry_size; - dst->offset = offset; - dst->len = payload_len; - - memcpy(dst->data, src->data, payload_len); - return dst; -} - -int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) -{ - struct p54_common *priv = dev->priv; - struct eeprom_pda_wrap *wrap; - struct pda_entry *entry; - unsigned int data_len, entry_len; - void *tmp; - int err; - u8 *end = (u8 *)eeprom + len; - u16 synth = 0; - - wrap = (struct eeprom_pda_wrap *) eeprom; - entry = (void *)wrap->data + le16_to_cpu(wrap->len); - - /* verify that at least the entry length/code fits */ - while ((u8 *)entry <= end - sizeof(*entry)) { - entry_len = le16_to_cpu(entry->len); - data_len = ((entry_len - 1) << 1); - - /* abort if entry exceeds whole structure */ - if ((u8 *)entry + sizeof(*entry) + data_len > end) - break; - - switch (le16_to_cpu(entry->code)) { - case PDR_MAC_ADDRESS: - if (data_len != ETH_ALEN) - break; - SET_IEEE80211_PERM_ADDR(dev, entry->data); - break; - case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS: - if (priv->output_limit) - break; - err = p54_convert_output_limits(dev, entry->data, - data_len); - if (err) - goto err; - break; - case PDR_PRISM_PA_CAL_CURVE_DATA: { - struct pda_pa_curve_data *curve_data = - (struct pda_pa_curve_data *)entry->data; - if (data_len < sizeof(*curve_data)) { - err = -EINVAL; - goto err; - } - - switch (curve_data->cal_method_rev) { - case 0: - err = p54_convert_rev0(dev, curve_data); - break; - case 1: - err = p54_convert_rev1(dev, curve_data); - break; - default: - printk(KERN_ERR "%s: unknown curve data " - "revision %d\n", - wiphy_name(dev->wiphy), - curve_data->cal_method_rev); - err = -ENODEV; - break; - } - if (err) - goto err; - } - break; - case PDR_PRISM_ZIF_TX_IQ_CALIBRATION: - priv->iq_autocal = kmalloc(data_len, GFP_KERNEL); - if (!priv->iq_autocal) { - err = -ENOMEM; - goto err; - } - - memcpy(priv->iq_autocal, entry->data, data_len); - priv->iq_autocal_len = data_len / sizeof(struct pda_iq_autocal_entry); - break; - case PDR_DEFAULT_COUNTRY: - p54_parse_default_country(dev, entry->data, data_len); - break; - case PDR_INTERFACE_LIST: - tmp = entry->data; - while ((u8 *)tmp < entry->data + data_len) { - struct exp_if *exp_if = tmp; - if (exp_if->if_id == cpu_to_le16(IF_ID_ISL39000)) - synth = le16_to_cpu(exp_if->variant); - tmp += sizeof(*exp_if); - } - break; - case PDR_HARDWARE_PLATFORM_COMPONENT_ID: - if (data_len < 2) - break; - priv->version = *(u8 *)(entry->data + 1); - break; - case PDR_RSSI_LINEAR_APPROXIMATION: - case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: - case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED: - p54_parse_rssical(dev, entry->data, data_len, - le16_to_cpu(entry->code)); - break; - case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: { - __le16 *src = (void *) entry->data; - s16 *dst = (void *) &priv->rssical_db; - int i; - - if (data_len != sizeof(priv->rssical_db)) { - err = -EINVAL; - goto err; - } - for (i = 0; i < sizeof(priv->rssical_db) / - sizeof(*src); i++) - *(dst++) = (s16) le16_to_cpu(*(src++)); - } - break; - case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: { - struct pda_custom_wrapper *pda = (void *) entry->data; - if (priv->output_limit || data_len < sizeof(*pda)) - break; - priv->output_limit = p54_convert_db(pda, data_len); - } - break; - case PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM: { - struct pda_custom_wrapper *pda = (void *) entry->data; - if (priv->curve_data || data_len < sizeof(*pda)) - break; - priv->curve_data = p54_convert_db(pda, data_len); - } - break; - case PDR_END: - /* make it overrun */ - entry_len = len; - break; - default: - break; - } - - entry = (void *)entry + (entry_len + 1)*2; - } - - if (!synth || !priv->iq_autocal || !priv->output_limit || - !priv->curve_data) { - printk(KERN_ERR "%s: not all required entries found in eeprom!\n", - wiphy_name(dev->wiphy)); - err = -EINVAL; - goto err; - } - - err = p54_generate_channel_lists(dev); - if (err) - goto err; - - priv->rxhw = synth & PDR_SYNTH_FRONTEND_MASK; - if (priv->rxhw == PDR_SYNTH_FRONTEND_XBOW) - p54_init_xbow_synth(priv); - if (!(synth & PDR_SYNTH_24_GHZ_DISABLED)) - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = - priv->band_table[IEEE80211_BAND_2GHZ]; - if (!(synth & PDR_SYNTH_5_GHZ_DISABLED)) - dev->wiphy->bands[IEEE80211_BAND_5GHZ] = - priv->band_table[IEEE80211_BAND_5GHZ]; - if ((synth & PDR_SYNTH_RX_DIV_MASK) == PDR_SYNTH_RX_DIV_SUPPORTED) - priv->rx_diversity_mask = 3; - if ((synth & PDR_SYNTH_TX_DIV_MASK) == PDR_SYNTH_TX_DIV_SUPPORTED) - priv->tx_diversity_mask = 3; - - if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { - u8 perm_addr[ETH_ALEN]; - - printk(KERN_WARNING "%s: Invalid hwaddr! Using randomly generated MAC addr\n", - wiphy_name(dev->wiphy)); - random_ether_addr(perm_addr); - SET_IEEE80211_PERM_ADDR(dev, perm_addr); - } - - printk(KERN_INFO "%s: hwaddr %pM, MAC:isl38%02x RF:%s\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, priv->version, - p54_rf_chips[priv->rxhw]); - - return 0; - -err: - kfree(priv->iq_autocal); - kfree(priv->output_limit); - kfree(priv->curve_data); - priv->iq_autocal = NULL; - priv->output_limit = NULL; - priv->curve_data = NULL; - - printk(KERN_ERR "%s: eeprom parse failed!\n", - wiphy_name(dev->wiphy)); - return err; -} -EXPORT_SYMBOL_GPL(p54_parse_eeprom); - -int p54_read_eeprom(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - size_t eeprom_size = 0x2020, offset = 0, blocksize, maxblocksize; - int ret = -ENOMEM; - void *eeprom; - - maxblocksize = EEPROM_READBACK_LEN; - if (priv->fw_var >= 0x509) - maxblocksize -= 0xc; - else - maxblocksize -= 0x4; - - eeprom = kzalloc(eeprom_size, GFP_KERNEL); - if (unlikely(!eeprom)) - goto free; - - while (eeprom_size) { - blocksize = min(eeprom_size, maxblocksize); - ret = p54_download_eeprom(priv, (void *) (eeprom + offset), - offset, blocksize); - if (unlikely(ret)) - goto free; - - offset += blocksize; - eeprom_size -= blocksize; - } - - ret = p54_parse_eeprom(dev, eeprom, offset); -free: - kfree(eeprom); - return ret; -} -EXPORT_SYMBOL_GPL(p54_read_eeprom); diff --git a/drivers/net/wireless/p54/eeprom.h b/drivers/net/wireless/p54/eeprom.h deleted file mode 100644 index 9051aef11249..000000000000 --- a/drivers/net/wireless/p54/eeprom.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * eeprom specific definitions for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007-2009, Christian Lamparter - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * - LMAC API interface header file for STLC4560 (lmac_longbow.h) - * Copyright (C) 2007 Conexant Systems, Inc. - * - * - islmvc driver - * Copyright (C) 2001 Intersil Americas Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef EEPROM_H -#define EEPROM_H - -/* PDA defines are Copyright (C) 2005 Nokia Corporation (taken from islsm_pda.h) */ - -struct pda_entry { - __le16 len; /* includes both code and data */ - __le16 code; - u8 data[0]; -} __packed; - -struct eeprom_pda_wrap { - __le32 magic; - __le16 pad; - __le16 len; - __le32 arm_opcode; - u8 data[0]; -} __packed; - -struct p54_iq_autocal_entry { - __le16 iq_param[4]; -} __packed; - -struct pda_iq_autocal_entry { - __le16 freq; - struct p54_iq_autocal_entry params; -} __packed; - -struct pda_channel_output_limit { - __le16 freq; - u8 val_bpsk; - u8 val_qpsk; - u8 val_16qam; - u8 val_64qam; - u8 rate_set_mask; - u8 rate_set_size; -} __packed; - -struct pda_pa_curve_data_sample_rev0 { - u8 rf_power; - u8 pa_detector; - u8 pcv; -} __packed; - -struct pda_pa_curve_data_sample_rev1 { - u8 rf_power; - u8 pa_detector; - u8 data_barker; - u8 data_bpsk; - u8 data_qpsk; - u8 data_16qam; - u8 data_64qam; -} __packed; - -struct pda_pa_curve_data { - u8 cal_method_rev; - u8 channels; - u8 points_per_channel; - u8 padding; - u8 data[0]; -} __packed; - -struct pda_rssi_cal_entry { - __le16 mul; - __le16 add; -} __packed; - -struct pda_country { - u8 regdomain; - u8 alpha2[2]; - u8 flags; -} __packed; - -struct pda_antenna_gain { - struct { - u8 gain_5GHz; /* 0.25 dBi units */ - u8 gain_2GHz; /* 0.25 dBi units */ - } __packed antenna[0]; -} __packed; - -struct pda_custom_wrapper { - __le16 entries; - __le16 entry_size; - __le16 offset; - __le16 len; - u8 data[0]; -} __packed; - -/* - * this defines the PDR codes used to build PDAs as defined in document - * number 553155. The current implementation mirrors version 1.1 of the - * document and lists only PDRs supported by the ARM platform. - */ - -/* common and choice range (0x0000 - 0x0fff) */ -#define PDR_END 0x0000 -#define PDR_MANUFACTURING_PART_NUMBER 0x0001 -#define PDR_PDA_VERSION 0x0002 -#define PDR_NIC_SERIAL_NUMBER 0x0003 -#define PDR_NIC_RAM_SIZE 0x0005 -#define PDR_RFMODEM_SUP_RANGE 0x0006 -#define PDR_PRISM_MAC_SUP_RANGE 0x0007 -#define PDR_NIC_ID 0x0008 - -#define PDR_MAC_ADDRESS 0x0101 -#define PDR_REGULATORY_DOMAIN_LIST 0x0103 /* obsolete */ -#define PDR_ALLOWED_CHAN_SET 0x0104 -#define PDR_DEFAULT_CHAN 0x0105 -#define PDR_TEMPERATURE_TYPE 0x0107 - -#define PDR_IFR_SETTING 0x0200 -#define PDR_RFR_SETTING 0x0201 -#define PDR_3861_BASELINE_REG_SETTINGS 0x0202 -#define PDR_3861_SHADOW_REG_SETTINGS 0x0203 -#define PDR_3861_IFRF_REG_SETTINGS 0x0204 - -#define PDR_3861_CHAN_CALIB_SET_POINTS 0x0300 -#define PDR_3861_CHAN_CALIB_INTEGRATOR 0x0301 - -#define PDR_3842_PRISM_II_NIC_CONFIG 0x0400 -#define PDR_PRISM_USB_ID 0x0401 -#define PDR_PRISM_PCI_ID 0x0402 -#define PDR_PRISM_PCI_IF_CONFIG 0x0403 -#define PDR_PRISM_PCI_PM_CONFIG 0x0404 - -#define PDR_3861_MF_TEST_CHAN_SET_POINTS 0x0900 -#define PDR_3861_MF_TEST_CHAN_INTEGRATORS 0x0901 - -/* ARM range (0x1000 - 0x1fff) */ -#define PDR_COUNTRY_INFORMATION 0x1000 /* obsolete */ -#define PDR_INTERFACE_LIST 0x1001 -#define PDR_HARDWARE_PLATFORM_COMPONENT_ID 0x1002 -#define PDR_OEM_NAME 0x1003 -#define PDR_PRODUCT_NAME 0x1004 -#define PDR_UTF8_OEM_NAME 0x1005 -#define PDR_UTF8_PRODUCT_NAME 0x1006 -#define PDR_COUNTRY_LIST 0x1007 -#define PDR_DEFAULT_COUNTRY 0x1008 - -#define PDR_ANTENNA_GAIN 0x1100 - -#define PDR_PRISM_INDIGO_PA_CALIBRATION_DATA 0x1901 -#define PDR_RSSI_LINEAR_APPROXIMATION 0x1902 -#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS 0x1903 -#define PDR_PRISM_PA_CAL_CURVE_DATA 0x1904 -#define PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND 0x1905 -#define PDR_PRISM_ZIF_TX_IQ_CALIBRATION 0x1906 -#define PDR_REGULATORY_POWER_LIMITS 0x1907 -#define PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED 0x1908 -#define PDR_RADIATED_TRANSMISSION_CORRECTION 0x1909 -#define PDR_PRISM_TX_IQ_CALIBRATION 0x190a - -/* reserved range (0x2000 - 0x7fff) */ - -/* customer range (0x8000 - 0xffff) */ -#define PDR_BASEBAND_REGISTERS 0x8000 -#define PDR_PER_CHANNEL_BASEBAND_REGISTERS 0x8001 - -/* used by our modificated eeprom image */ -#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM 0xDEAD -#define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM 0xBEEF -#define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM 0xB05D - -/* Interface Definitions */ -#define PDR_INTERFACE_ROLE_SERVER 0x0000 -#define PDR_INTERFACE_ROLE_CLIENT 0x0001 - -/* PDR definitions for default country & country list */ -#define PDR_COUNTRY_CERT_CODE 0x80 -#define PDR_COUNTRY_CERT_CODE_REAL 0x00 -#define PDR_COUNTRY_CERT_CODE_PSEUDO 0x80 -#define PDR_COUNTRY_CERT_BAND 0x40 -#define PDR_COUNTRY_CERT_BAND_2GHZ 0x00 -#define PDR_COUNTRY_CERT_BAND_5GHZ 0x40 -#define PDR_COUNTRY_CERT_IODOOR 0x30 -#define PDR_COUNTRY_CERT_IODOOR_BOTH 0x00 -#define PDR_COUNTRY_CERT_IODOOR_INDOOR 0x20 -#define PDR_COUNTRY_CERT_IODOOR_OUTDOOR 0x30 -#define PDR_COUNTRY_CERT_INDEX 0x0f - -/* Specific LMAC FW/HW variant definitions */ -#define PDR_SYNTH_FRONTEND_MASK 0x0007 -#define PDR_SYNTH_FRONTEND_DUETTE3 0x0001 -#define PDR_SYNTH_FRONTEND_DUETTE2 0x0002 -#define PDR_SYNTH_FRONTEND_FRISBEE 0x0003 -#define PDR_SYNTH_FRONTEND_XBOW 0x0004 -#define PDR_SYNTH_FRONTEND_LONGBOW 0x0005 -#define PDR_SYNTH_IQ_CAL_MASK 0x0018 -#define PDR_SYNTH_IQ_CAL_PA_DETECTOR 0x0000 -#define PDR_SYNTH_IQ_CAL_DISABLED 0x0008 -#define PDR_SYNTH_IQ_CAL_ZIF 0x0010 -#define PDR_SYNTH_FAA_SWITCH_MASK 0x0020 -#define PDR_SYNTH_FAA_SWITCH_ENABLED 0x0020 -#define PDR_SYNTH_24_GHZ_MASK 0x0040 -#define PDR_SYNTH_24_GHZ_DISABLED 0x0040 -#define PDR_SYNTH_5_GHZ_MASK 0x0080 -#define PDR_SYNTH_5_GHZ_DISABLED 0x0080 -#define PDR_SYNTH_RX_DIV_MASK 0x0100 -#define PDR_SYNTH_RX_DIV_SUPPORTED 0x0100 -#define PDR_SYNTH_TX_DIV_MASK 0x0200 -#define PDR_SYNTH_TX_DIV_SUPPORTED 0x0200 -#define PDR_SYNTH_ASM_MASK 0x0400 -#define PDR_SYNTH_ASM_XSWON 0x0400 - -#endif /* EEPROM_H */ diff --git a/drivers/net/wireless/p54/fwio.c b/drivers/net/wireless/p54/fwio.c deleted file mode 100644 index e7b9e9cb39f5..000000000000 --- a/drivers/net/wireless/p54/fwio.c +++ /dev/null @@ -1,716 +0,0 @@ -/* - * Firmware I/O code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007-2009, Christian Lamparter - * Copyright 2008, Johannes Berg - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - stlc45xx driver - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include - -#include "p54.h" -#include "eeprom.h" -#include "lmac.h" - -int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw) -{ - struct p54_common *priv = dev->priv; - struct exp_if *exp_if; - struct bootrec *bootrec; - u32 *data = (u32 *)fw->data; - u32 *end_data = (u32 *)fw->data + (fw->size >> 2); - u8 *fw_version = NULL; - size_t len; - int i; - int maxlen; - - if (priv->rx_start) - return 0; - - while (data < end_data && *data) - data++; - - while (data < end_data && !*data) - data++; - - bootrec = (struct bootrec *) data; - - while (bootrec->data <= end_data && (bootrec->data + - (len = le32_to_cpu(bootrec->len))) <= end_data) { - u32 code = le32_to_cpu(bootrec->code); - switch (code) { - case BR_CODE_COMPONENT_ID: - priv->fw_interface = be32_to_cpup((__be32 *) - bootrec->data); - switch (priv->fw_interface) { - case FW_LM86: - case FW_LM20: - case FW_LM87: { - char *iftype = (char *)bootrec->data; - printk(KERN_INFO "%s: p54 detected a LM%c%c " - "firmware\n", - wiphy_name(priv->hw->wiphy), - iftype[2], iftype[3]); - break; - } - case FW_FMAC: - default: - printk(KERN_ERR "%s: unsupported firmware\n", - wiphy_name(priv->hw->wiphy)); - return -ENODEV; - } - break; - case BR_CODE_COMPONENT_VERSION: - /* 24 bytes should be enough for all firmwares */ - if (strnlen((unsigned char *) bootrec->data, 24) < 24) - fw_version = (unsigned char *) bootrec->data; - break; - case BR_CODE_DESCR: { - struct bootrec_desc *desc = - (struct bootrec_desc *)bootrec->data; - priv->rx_start = le32_to_cpu(desc->rx_start); - /* FIXME add sanity checking */ - priv->rx_end = le32_to_cpu(desc->rx_end) - 0x3500; - priv->headroom = desc->headroom; - priv->tailroom = desc->tailroom; - priv->privacy_caps = desc->privacy_caps; - priv->rx_keycache_size = desc->rx_keycache_size; - if (le32_to_cpu(bootrec->len) == 11) - priv->rx_mtu = le16_to_cpu(desc->rx_mtu); - else - priv->rx_mtu = (size_t) - 0x620 - priv->tx_hdr_len; - maxlen = priv->tx_hdr_len + /* USB devices */ - sizeof(struct p54_rx_data) + - 4 + /* rx alignment */ - IEEE80211_MAX_FRAG_THRESHOLD; - if (priv->rx_mtu > maxlen && PAGE_SIZE == 4096) { - printk(KERN_INFO "p54: rx_mtu reduced from %d " - "to %d\n", priv->rx_mtu, maxlen); - priv->rx_mtu = maxlen; - } - break; - } - case BR_CODE_EXPOSED_IF: - exp_if = (struct exp_if *) bootrec->data; - for (i = 0; i < (len * sizeof(*exp_if) / 4); i++) - if (exp_if[i].if_id == cpu_to_le16(IF_ID_LMAC)) - priv->fw_var = le16_to_cpu(exp_if[i].variant); - break; - case BR_CODE_DEPENDENT_IF: - break; - case BR_CODE_END_OF_BRA: - case LEGACY_BR_CODE_END_OF_BRA: - end_data = NULL; - break; - default: - break; - } - bootrec = (struct bootrec *)&bootrec->data[len]; - } - - if (fw_version) - printk(KERN_INFO "%s: FW rev %s - Softmac protocol %x.%x\n", - wiphy_name(priv->hw->wiphy), fw_version, - priv->fw_var >> 8, priv->fw_var & 0xff); - - if (priv->fw_var < 0x500) - printk(KERN_INFO "%s: you are using an obsolete firmware. " - "visit http://wireless.kernel.org/en/users/Drivers/p54 " - "and grab one for \"kernel >= 2.6.28\"!\n", - wiphy_name(priv->hw->wiphy)); - - if (priv->fw_var >= 0x300) { - /* Firmware supports QoS, use it! */ - - if (priv->fw_var >= 0x500) { - priv->tx_stats[P54_QUEUE_AC_VO].limit = 16; - priv->tx_stats[P54_QUEUE_AC_VI].limit = 16; - priv->tx_stats[P54_QUEUE_AC_BE].limit = 16; - priv->tx_stats[P54_QUEUE_AC_BK].limit = 16; - } else { - priv->tx_stats[P54_QUEUE_AC_VO].limit = 3; - priv->tx_stats[P54_QUEUE_AC_VI].limit = 4; - priv->tx_stats[P54_QUEUE_AC_BE].limit = 3; - priv->tx_stats[P54_QUEUE_AC_BK].limit = 2; - } - priv->hw->queues = P54_QUEUE_AC_NUM; - } - - printk(KERN_INFO "%s: cryptographic accelerator " - "WEP:%s, TKIP:%s, CCMP:%s\n", wiphy_name(priv->hw->wiphy), - (priv->privacy_caps & BR_DESC_PRIV_CAP_WEP) ? "YES" : - "no", (priv->privacy_caps & (BR_DESC_PRIV_CAP_TKIP | - BR_DESC_PRIV_CAP_MICHAEL)) ? "YES" : "no", - (priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP) ? - "YES" : "no"); - - if (priv->rx_keycache_size) { - /* - * NOTE: - * - * The firmware provides at most 255 (0 - 254) slots - * for keys which are then used to offload decryption. - * As a result the 255 entry (aka 0xff) can be used - * safely by the driver to mark keys that didn't fit - * into the full cache. This trick saves us from - * keeping a extra list for uploaded keys. - */ - - priv->used_rxkeys = kzalloc(BITS_TO_LONGS( - priv->rx_keycache_size), GFP_KERNEL); - - if (!priv->used_rxkeys) - return -ENOMEM; - } - - return 0; -} -EXPORT_SYMBOL_GPL(p54_parse_firmware); - -static struct sk_buff *p54_alloc_skb(struct p54_common *priv, u16 hdr_flags, - u16 payload_len, u16 type, gfp_t memflags) -{ - struct p54_hdr *hdr; - struct sk_buff *skb; - size_t frame_len = sizeof(*hdr) + payload_len; - - if (frame_len > P54_MAX_CTRL_FRAME_LEN) - return NULL; - - if (unlikely(skb_queue_len(&priv->tx_pending) > 64)) - return NULL; - - skb = __dev_alloc_skb(priv->tx_hdr_len + frame_len, memflags); - if (!skb) - return NULL; - skb_reserve(skb, priv->tx_hdr_len); - - hdr = (struct p54_hdr *) skb_put(skb, sizeof(*hdr)); - hdr->flags = cpu_to_le16(hdr_flags); - hdr->len = cpu_to_le16(payload_len); - hdr->type = cpu_to_le16(type); - hdr->tries = hdr->rts_tries = 0; - return skb; -} - -int p54_download_eeprom(struct p54_common *priv, void *buf, - u16 offset, u16 len) -{ - struct p54_eeprom_lm86 *eeprom_hdr; - struct sk_buff *skb; - size_t eeprom_hdr_size; - int ret = 0; - - if (priv->fw_var >= 0x509) - eeprom_hdr_size = sizeof(*eeprom_hdr); - else - eeprom_hdr_size = 0x4; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, eeprom_hdr_size + - len, P54_CONTROL_TYPE_EEPROM_READBACK, - GFP_KERNEL); - if (unlikely(!skb)) - return -ENOMEM; - - mutex_lock(&priv->eeprom_mutex); - priv->eeprom = buf; - eeprom_hdr = (struct p54_eeprom_lm86 *) skb_put(skb, - eeprom_hdr_size + len); - - if (priv->fw_var < 0x509) { - eeprom_hdr->v1.offset = cpu_to_le16(offset); - eeprom_hdr->v1.len = cpu_to_le16(len); - } else { - eeprom_hdr->v2.offset = cpu_to_le32(offset); - eeprom_hdr->v2.len = cpu_to_le16(len); - eeprom_hdr->v2.magic2 = 0xf; - memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4); - } - - p54_tx(priv, skb); - - if (!wait_for_completion_interruptible_timeout( - &priv->eeprom_comp, HZ)) { - printk(KERN_ERR "%s: device does not respond!\n", - wiphy_name(priv->hw->wiphy)); - ret = -EBUSY; - } - priv->eeprom = NULL; - mutex_unlock(&priv->eeprom_mutex); - return ret; -} - -int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set) -{ - struct sk_buff *skb; - struct p54_tim *tim; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*tim), - P54_CONTROL_TYPE_TIM, GFP_ATOMIC); - if (unlikely(!skb)) - return -ENOMEM; - - tim = (struct p54_tim *) skb_put(skb, sizeof(*tim)); - tim->count = 1; - tim->entry[0] = cpu_to_le16(set ? (aid | 0x8000) : aid); - p54_tx(priv, skb); - return 0; -} - -int p54_sta_unlock(struct p54_common *priv, u8 *addr) -{ - struct sk_buff *skb; - struct p54_sta_unlock *sta; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*sta), - P54_CONTROL_TYPE_PSM_STA_UNLOCK, GFP_ATOMIC); - if (unlikely(!skb)) - return -ENOMEM; - - sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta)); - memcpy(sta->addr, addr, ETH_ALEN); - p54_tx(priv, skb); - return 0; -} - -int p54_tx_cancel(struct p54_common *priv, __le32 req_id) -{ - struct sk_buff *skb; - struct p54_txcancel *cancel; - u32 _req_id = le32_to_cpu(req_id); - - if (unlikely(_req_id < priv->rx_start || _req_id > priv->rx_end)) - return -EINVAL; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*cancel), - P54_CONTROL_TYPE_TXCANCEL, GFP_ATOMIC); - if (unlikely(!skb)) - return -ENOMEM; - - cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel)); - cancel->req_id = req_id; - p54_tx(priv, skb); - return 0; -} - -int p54_setup_mac(struct p54_common *priv) -{ - struct sk_buff *skb; - struct p54_setup_mac *setup; - u16 mode; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*setup), - P54_CONTROL_TYPE_SETUP, GFP_ATOMIC); - if (!skb) - return -ENOMEM; - - setup = (struct p54_setup_mac *) skb_put(skb, sizeof(*setup)); - if (!(priv->hw->conf.flags & IEEE80211_CONF_IDLE)) { - switch (priv->mode) { - case NL80211_IFTYPE_STATION: - mode = P54_FILTER_TYPE_STATION; - break; - case NL80211_IFTYPE_AP: - mode = P54_FILTER_TYPE_AP; - break; - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - mode = P54_FILTER_TYPE_IBSS; - break; - case NL80211_IFTYPE_MONITOR: - mode = P54_FILTER_TYPE_PROMISCUOUS; - break; - default: - mode = P54_FILTER_TYPE_HIBERNATE; - break; - } - - /* - * "TRANSPARENT and PROMISCUOUS are mutually exclusive" - * STSW45X0C LMAC API - page 12 - */ - if (((priv->filter_flags & FIF_PROMISC_IN_BSS) || - (priv->filter_flags & FIF_OTHER_BSS)) && - (mode != P54_FILTER_TYPE_PROMISCUOUS)) - mode |= P54_FILTER_TYPE_TRANSPARENT; - } else { - mode = P54_FILTER_TYPE_HIBERNATE; - } - - setup->mac_mode = cpu_to_le16(mode); - memcpy(setup->mac_addr, priv->mac_addr, ETH_ALEN); - memcpy(setup->bssid, priv->bssid, ETH_ALEN); - setup->rx_antenna = 2 & priv->rx_diversity_mask; /* automatic */ - setup->rx_align = 0; - if (priv->fw_var < 0x500) { - setup->v1.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); - memset(setup->v1.rts_rates, 0, 8); - setup->v1.rx_addr = cpu_to_le32(priv->rx_end); - setup->v1.max_rx = cpu_to_le16(priv->rx_mtu); - setup->v1.rxhw = cpu_to_le16(priv->rxhw); - setup->v1.wakeup_timer = cpu_to_le16(priv->wakeup_timer); - setup->v1.unalloc0 = cpu_to_le16(0); - } else { - setup->v2.rx_addr = cpu_to_le32(priv->rx_end); - setup->v2.max_rx = cpu_to_le16(priv->rx_mtu); - setup->v2.rxhw = cpu_to_le16(priv->rxhw); - setup->v2.timer = cpu_to_le16(priv->wakeup_timer); - setup->v2.truncate = cpu_to_le16(48896); - setup->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); - setup->v2.sbss_offset = 0; - setup->v2.mcast_window = 0; - setup->v2.rx_rssi_threshold = 0; - setup->v2.rx_ed_threshold = 0; - setup->v2.ref_clock = cpu_to_le32(644245094); - setup->v2.lpf_bandwidth = cpu_to_le16(65535); - setup->v2.osc_start_delay = cpu_to_le16(65535); - } - p54_tx(priv, skb); - return 0; -} - -int p54_scan(struct p54_common *priv, u16 mode, u16 dwell) -{ - struct sk_buff *skb; - struct p54_hdr *hdr; - struct p54_scan_head *head; - struct p54_iq_autocal_entry *iq_autocal; - union p54_scan_body_union *body; - struct p54_scan_tail_rate *rate; - struct pda_rssi_cal_entry *rssi; - unsigned int i; - void *entry; - int band = priv->hw->conf.channel->band; - __le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq); - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) + - 2 + sizeof(*iq_autocal) + sizeof(*body) + - sizeof(*rate) + 2 * sizeof(*rssi), - P54_CONTROL_TYPE_SCAN, GFP_ATOMIC); - if (!skb) - return -ENOMEM; - - head = (struct p54_scan_head *) skb_put(skb, sizeof(*head)); - memset(head->scan_params, 0, sizeof(head->scan_params)); - head->mode = cpu_to_le16(mode); - head->dwell = cpu_to_le16(dwell); - head->freq = freq; - - if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { - __le16 *pa_power_points = (__le16 *) skb_put(skb, 2); - *pa_power_points = cpu_to_le16(0x0c); - } - - iq_autocal = (void *) skb_put(skb, sizeof(*iq_autocal)); - for (i = 0; i < priv->iq_autocal_len; i++) { - if (priv->iq_autocal[i].freq != freq) - continue; - - memcpy(iq_autocal, &priv->iq_autocal[i].params, - sizeof(struct p54_iq_autocal_entry)); - break; - } - if (i == priv->iq_autocal_len) - goto err; - - if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) - body = (void *) skb_put(skb, sizeof(body->longbow)); - else - body = (void *) skb_put(skb, sizeof(body->normal)); - - for (i = 0; i < priv->output_limit->entries; i++) { - __le16 *entry_freq = (void *) (priv->output_limit->data + - priv->output_limit->entry_size * i); - - if (*entry_freq != freq) - continue; - - if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { - memcpy(&body->longbow.power_limits, - (void *) entry_freq + sizeof(__le16), - priv->output_limit->entry_size); - } else { - struct pda_channel_output_limit *limits = - (void *) entry_freq; - - body->normal.val_barker = 0x38; - body->normal.val_bpsk = body->normal.dup_bpsk = - limits->val_bpsk; - body->normal.val_qpsk = body->normal.dup_qpsk = - limits->val_qpsk; - body->normal.val_16qam = body->normal.dup_16qam = - limits->val_16qam; - body->normal.val_64qam = body->normal.dup_64qam = - limits->val_64qam; - } - break; - } - if (i == priv->output_limit->entries) - goto err; - - entry = (void *)(priv->curve_data->data + priv->curve_data->offset); - for (i = 0; i < priv->curve_data->entries; i++) { - if (*((__le16 *)entry) != freq) { - entry += priv->curve_data->entry_size; - continue; - } - - if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { - memcpy(&body->longbow.curve_data, - (void *) entry + sizeof(__le16), - priv->curve_data->entry_size); - } else { - struct p54_scan_body *chan = &body->normal; - struct pda_pa_curve_data *curve_data = - (void *) priv->curve_data->data; - - entry += sizeof(__le16); - chan->pa_points_per_curve = 8; - memset(chan->curve_data, 0, sizeof(*chan->curve_data)); - memcpy(chan->curve_data, entry, - sizeof(struct p54_pa_curve_data_sample) * - min((u8)8, curve_data->points_per_channel)); - } - break; - } - if (i == priv->curve_data->entries) - goto err; - - if ((priv->fw_var >= 0x500) && (priv->fw_var < 0x509)) { - rate = (void *) skb_put(skb, sizeof(*rate)); - rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); - for (i = 0; i < sizeof(rate->rts_rates); i++) - rate->rts_rates[i] = i; - } - - rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi)); - rssi->mul = cpu_to_le16(priv->rssical_db[band].mul); - rssi->add = cpu_to_le16(priv->rssical_db[band].add); - if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) { - /* Longbow frontend needs ever more */ - rssi = (void *) skb_put(skb, sizeof(*rssi)); - rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn); - rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2); - } - - if (priv->fw_var >= 0x509) { - rate = (void *) skb_put(skb, sizeof(*rate)); - rate->basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); - for (i = 0; i < sizeof(rate->rts_rates); i++) - rate->rts_rates[i] = i; - } - - hdr = (struct p54_hdr *) skb->data; - hdr->len = cpu_to_le16(skb->len - sizeof(*hdr)); - - p54_tx(priv, skb); - return 0; - -err: - printk(KERN_ERR "%s: frequency change to channel %d failed.\n", - wiphy_name(priv->hw->wiphy), ieee80211_frequency_to_channel( - priv->hw->conf.channel->center_freq)); - - dev_kfree_skb_any(skb); - return -EINVAL; -} - -int p54_set_leds(struct p54_common *priv) -{ - struct sk_buff *skb; - struct p54_led *led; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*led), - P54_CONTROL_TYPE_LED, GFP_ATOMIC); - if (unlikely(!skb)) - return -ENOMEM; - - led = (struct p54_led *) skb_put(skb, sizeof(*led)); - led->flags = cpu_to_le16(0x0003); - led->mask[0] = led->mask[1] = cpu_to_le16(priv->softled_state); - led->delay[0] = cpu_to_le16(1); - led->delay[1] = cpu_to_le16(0); - p54_tx(priv, skb); - return 0; -} - -int p54_set_edcf(struct p54_common *priv) -{ - struct sk_buff *skb; - struct p54_edcf *edcf; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf), - P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC); - if (unlikely(!skb)) - return -ENOMEM; - - edcf = (struct p54_edcf *)skb_put(skb, sizeof(*edcf)); - if (priv->use_short_slot) { - edcf->slottime = 9; - edcf->sifs = 0x10; - edcf->eofpad = 0x00; - } else { - edcf->slottime = 20; - edcf->sifs = 0x0a; - edcf->eofpad = 0x06; - } - /* (see prism54/isl_oid.h for further details) */ - edcf->frameburst = cpu_to_le16(0); - edcf->round_trip_delay = cpu_to_le16(0); - edcf->flags = 0; - memset(edcf->mapping, 0, sizeof(edcf->mapping)); - memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); - p54_tx(priv, skb); - return 0; -} - -int p54_set_ps(struct p54_common *priv) -{ - struct sk_buff *skb; - struct p54_psm *psm; - unsigned int i; - u16 mode; - - if (priv->hw->conf.flags & IEEE80211_CONF_PS && - !priv->powersave_override) - mode = P54_PSM | P54_PSM_BEACON_TIMEOUT | P54_PSM_DTIM | - P54_PSM_CHECKSUM | P54_PSM_MCBC; - else - mode = P54_PSM_CAM; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*psm), - P54_CONTROL_TYPE_PSM, GFP_ATOMIC); - if (!skb) - return -ENOMEM; - - psm = (struct p54_psm *)skb_put(skb, sizeof(*psm)); - psm->mode = cpu_to_le16(mode); - psm->aid = cpu_to_le16(priv->aid); - for (i = 0; i < ARRAY_SIZE(psm->intervals); i++) { - psm->intervals[i].interval = - cpu_to_le16(priv->hw->conf.listen_interval); - psm->intervals[i].periods = cpu_to_le16(1); - } - - psm->beacon_rssi_skip_max = 200; - psm->rssi_delta_threshold = 0; - psm->nr = 1; - psm->exclude[0] = WLAN_EID_TIM; - - p54_tx(priv, skb); - return 0; -} - -int p54_init_xbow_synth(struct p54_common *priv) -{ - struct sk_buff *skb; - struct p54_xbow_synth *xbow; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*xbow), - P54_CONTROL_TYPE_XBOW_SYNTH_CFG, GFP_KERNEL); - if (unlikely(!skb)) - return -ENOMEM; - - xbow = (struct p54_xbow_synth *)skb_put(skb, sizeof(*xbow)); - xbow->magic1 = cpu_to_le16(0x1); - xbow->magic2 = cpu_to_le16(0x2); - xbow->freq = cpu_to_le16(5390); - memset(xbow->padding, 0, sizeof(xbow->padding)); - p54_tx(priv, skb); - return 0; -} - -int p54_upload_key(struct p54_common *priv, u8 algo, int slot, u8 idx, u8 len, - u8 *addr, u8* key) -{ - struct sk_buff *skb; - struct p54_keycache *rxkey; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*rxkey), - P54_CONTROL_TYPE_RX_KEYCACHE, GFP_KERNEL); - if (unlikely(!skb)) - return -ENOMEM; - - rxkey = (struct p54_keycache *)skb_put(skb, sizeof(*rxkey)); - rxkey->entry = slot; - rxkey->key_id = idx; - rxkey->key_type = algo; - if (addr) - memcpy(rxkey->mac, addr, ETH_ALEN); - else - memset(rxkey->mac, ~0, ETH_ALEN); - - switch (algo) { - case P54_CRYPTO_WEP: - case P54_CRYPTO_AESCCMP: - rxkey->key_len = min_t(u8, 16, len); - memcpy(rxkey->key, key, rxkey->key_len); - break; - - case P54_CRYPTO_TKIPMICHAEL: - rxkey->key_len = 24; - memcpy(rxkey->key, key, 16); - memcpy(&(rxkey->key[16]), &(key - [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8); - break; - - case P54_CRYPTO_NONE: - rxkey->key_len = 0; - memset(rxkey->key, 0, sizeof(rxkey->key)); - break; - - default: - printk(KERN_ERR "%s: invalid cryptographic algorithm: %d\n", - wiphy_name(priv->hw->wiphy), algo); - dev_kfree_skb(skb); - return -EINVAL; - } - - p54_tx(priv, skb); - return 0; -} - -int p54_fetch_statistics(struct p54_common *priv) -{ - struct ieee80211_tx_info *txinfo; - struct p54_tx_info *p54info; - struct sk_buff *skb; - - skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL, - sizeof(struct p54_statistics), - P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL); - if (!skb) - return -ENOMEM; - - /* - * The statistic feedback causes some extra headaches here, if it - * is not to crash/corrupt the firmware data structures. - * - * Unlike all other Control Get OIDs we can not use helpers like - * skb_put to reserve the space for the data we're requesting. - * Instead the extra frame length -which will hold the results later- - * will only be told to the p54_assign_address, so that following - * frames won't be placed into the allegedly empty area. - */ - txinfo = IEEE80211_SKB_CB(skb); - p54info = (void *) txinfo->rate_driver_data; - p54info->extra_len = sizeof(struct p54_statistics); - - p54_tx(priv, skb); - return 0; -} diff --git a/drivers/net/wireless/p54/led.c b/drivers/net/wireless/p54/led.c deleted file mode 100644 index 9575ac033630..000000000000 --- a/drivers/net/wireless/p54/led.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Common code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007-2009, Christian Lamparter - * Copyright 2008, Johannes Berg - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - stlc45xx driver - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include -#ifdef CONFIG_P54_LEDS -#include -#endif /* CONFIG_P54_LEDS */ - -#include "p54.h" -#include "lmac.h" - -static void p54_update_leds(struct work_struct *work) -{ - struct p54_common *priv = container_of(work, struct p54_common, - led_work.work); - int err, i, tmp, blink_delay = 400; - bool rerun = false; - - /* Don't toggle the LED, when the device is down. */ - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) - return ; - - for (i = 0; i < ARRAY_SIZE(priv->leds); i++) - if (priv->leds[i].toggled) { - priv->softled_state |= BIT(i); - - tmp = 70 + 200 / (priv->leds[i].toggled); - if (tmp < blink_delay) - blink_delay = tmp; - - if (priv->leds[i].led_dev.brightness == LED_OFF) - rerun = true; - - priv->leds[i].toggled = - !!priv->leds[i].led_dev.brightness; - } else - priv->softled_state &= ~BIT(i); - - err = p54_set_leds(priv); - if (err && net_ratelimit()) - printk(KERN_ERR "%s: failed to update LEDs (%d).\n", - wiphy_name(priv->hw->wiphy), err); - - if (rerun) - ieee80211_queue_delayed_work(priv->hw, &priv->led_work, - msecs_to_jiffies(blink_delay)); -} - -static void p54_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct p54_led_dev *led = container_of(led_dev, struct p54_led_dev, - led_dev); - struct ieee80211_hw *dev = led->hw_dev; - struct p54_common *priv = dev->priv; - - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) - return ; - - if ((brightness) && (led->registered)) { - led->toggled++; - ieee80211_queue_delayed_work(priv->hw, &priv->led_work, HZ/10); - } -} - -static int p54_register_led(struct p54_common *priv, - unsigned int led_index, - char *name, char *trigger) -{ - struct p54_led_dev *led = &priv->leds[led_index]; - int err; - - if (led->registered) - return -EEXIST; - - snprintf(led->name, sizeof(led->name), "p54-%s::%s", - wiphy_name(priv->hw->wiphy), name); - led->hw_dev = priv->hw; - led->index = led_index; - led->led_dev.name = led->name; - led->led_dev.default_trigger = trigger; - led->led_dev.brightness_set = p54_led_brightness_set; - - err = led_classdev_register(wiphy_dev(priv->hw->wiphy), &led->led_dev); - if (err) - printk(KERN_ERR "%s: Failed to register %s LED.\n", - wiphy_name(priv->hw->wiphy), name); - else - led->registered = 1; - - return err; -} - -int p54_init_leds(struct p54_common *priv) -{ - int err; - - /* - * TODO: - * Figure out if the EEPROM contains some hints about the number - * of available/programmable LEDs of the device. - */ - - INIT_DELAYED_WORK(&priv->led_work, p54_update_leds); - - err = p54_register_led(priv, 0, "assoc", - ieee80211_get_assoc_led_name(priv->hw)); - if (err) - return err; - - err = p54_register_led(priv, 1, "tx", - ieee80211_get_tx_led_name(priv->hw)); - if (err) - return err; - - err = p54_register_led(priv, 2, "rx", - ieee80211_get_rx_led_name(priv->hw)); - if (err) - return err; - - err = p54_register_led(priv, 3, "radio", - ieee80211_get_radio_led_name(priv->hw)); - if (err) - return err; - - err = p54_set_leds(priv); - return err; -} - -void p54_unregister_leds(struct p54_common *priv) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(priv->leds); i++) { - if (priv->leds[i].registered) { - priv->leds[i].registered = false; - priv->leds[i].toggled = 0; - led_classdev_unregister(&priv->leds[i].led_dev); - } - } - - cancel_delayed_work_sync(&priv->led_work); -} diff --git a/drivers/net/wireless/p54/lmac.h b/drivers/net/wireless/p54/lmac.h deleted file mode 100644 index 04b63ec80fa4..000000000000 --- a/drivers/net/wireless/p54/lmac.h +++ /dev/null @@ -1,558 +0,0 @@ -/* - * LMAC Interface specific definitions for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007 - 2009, Christian Lamparter - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * - LMAC API interface header file for STLC4560 (lmac_longbow.h) - * Copyright (C) 2007 Conexant Systems, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef LMAC_H -#define LMAC_H - -enum p54_control_frame_types { - P54_CONTROL_TYPE_SETUP = 0, - P54_CONTROL_TYPE_SCAN, - P54_CONTROL_TYPE_TRAP, - P54_CONTROL_TYPE_DCFINIT, - P54_CONTROL_TYPE_RX_KEYCACHE, - P54_CONTROL_TYPE_TIM, - P54_CONTROL_TYPE_PSM, - P54_CONTROL_TYPE_TXCANCEL, - P54_CONTROL_TYPE_TXDONE, - P54_CONTROL_TYPE_BURST, - P54_CONTROL_TYPE_STAT_READBACK, - P54_CONTROL_TYPE_BBP, - P54_CONTROL_TYPE_EEPROM_READBACK, - P54_CONTROL_TYPE_LED, - P54_CONTROL_TYPE_GPIO, - P54_CONTROL_TYPE_TIMER, - P54_CONTROL_TYPE_MODULATION, - P54_CONTROL_TYPE_SYNTH_CONFIG, - P54_CONTROL_TYPE_DETECTOR_VALUE, - P54_CONTROL_TYPE_XBOW_SYNTH_CFG, - P54_CONTROL_TYPE_CCE_QUIET, - P54_CONTROL_TYPE_PSM_STA_UNLOCK, - P54_CONTROL_TYPE_PCS, - P54_CONTROL_TYPE_BT_BALANCER = 28, - P54_CONTROL_TYPE_GROUP_ADDRESS_TABLE = 30, - P54_CONTROL_TYPE_ARPTABLE = 31, - P54_CONTROL_TYPE_BT_OPTIONS = 35, -}; - -#define P54_HDR_FLAG_CONTROL BIT(15) -#define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0)) -#define P54_HDR_FLAG_DATA_ALIGN BIT(14) - -#define P54_HDR_FLAG_DATA_OUT_PROMISC BIT(0) -#define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1) -#define P54_HDR_FLAG_DATA_OUT_SEQNR BIT(2) -#define P54_HDR_FLAG_DATA_OUT_BIT3 BIT(3) -#define P54_HDR_FLAG_DATA_OUT_BURST BIT(4) -#define P54_HDR_FLAG_DATA_OUT_NOCANCEL BIT(5) -#define P54_HDR_FLAG_DATA_OUT_CLEARTIM BIT(6) -#define P54_HDR_FLAG_DATA_OUT_HITCHHIKE BIT(7) -#define P54_HDR_FLAG_DATA_OUT_COMPRESS BIT(8) -#define P54_HDR_FLAG_DATA_OUT_CONCAT BIT(9) -#define P54_HDR_FLAG_DATA_OUT_PCS_ACCEPT BIT(10) -#define P54_HDR_FLAG_DATA_OUT_WAITEOSP BIT(11) - -#define P54_HDR_FLAG_DATA_IN_FCS_GOOD BIT(0) -#define P54_HDR_FLAG_DATA_IN_MATCH_MAC BIT(1) -#define P54_HDR_FLAG_DATA_IN_MCBC BIT(2) -#define P54_HDR_FLAG_DATA_IN_BEACON BIT(3) -#define P54_HDR_FLAG_DATA_IN_MATCH_BSS BIT(4) -#define P54_HDR_FLAG_DATA_IN_BCAST_BSS BIT(5) -#define P54_HDR_FLAG_DATA_IN_DATA BIT(6) -#define P54_HDR_FLAG_DATA_IN_TRUNCATED BIT(7) -#define P54_HDR_FLAG_DATA_IN_BIT8 BIT(8) -#define P54_HDR_FLAG_DATA_IN_TRANSPARENT BIT(9) - -struct p54_hdr { - __le16 flags; - __le16 len; - __le32 req_id; - __le16 type; /* enum p54_control_frame_types */ - u8 rts_tries; - u8 tries; - u8 data[0]; -} __packed; - -#define GET_REQ_ID(skb) \ - (((struct p54_hdr *) ((struct sk_buff *) skb)->data)->req_id) \ - -#define FREE_AFTER_TX(skb) \ - ((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \ - flags) == cpu_to_le16(P54_HDR_FLAG_CONTROL_OPSET)) - -#define IS_DATA_FRAME(skb) \ - (!((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \ - flags) & cpu_to_le16(P54_HDR_FLAG_CONTROL))) - -#define GET_HW_QUEUE(skb) \ - (((struct p54_tx_data *)((struct p54_hdr *) \ - skb->data)->data)->hw_queue) - -/* - * shared interface ID definitions - * The interface ID is a unique identification of a specific interface. - * The following values are reserved: 0x0000, 0x0002, 0x0012, 0x0014, 0x0015 - */ -#define IF_ID_ISL36356A 0x0001 /* ISL36356A <-> Firmware */ -#define IF_ID_MVC 0x0003 /* MAC Virtual Coprocessor */ -#define IF_ID_DEBUG 0x0008 /* PolDebug Interface */ -#define IF_ID_PRODUCT 0x0009 -#define IF_ID_OEM 0x000a -#define IF_ID_PCI3877 0x000b /* 3877 <-> Host PCI */ -#define IF_ID_ISL37704C 0x000c /* ISL37704C <-> Fw */ -#define IF_ID_ISL39000 0x000f /* ISL39000 <-> Fw */ -#define IF_ID_ISL39300A 0x0010 /* ISL39300A <-> Fw */ -#define IF_ID_ISL37700_UAP 0x0016 /* ISL37700 uAP Fw <-> Fw */ -#define IF_ID_ISL39000_UAP 0x0017 /* ISL39000 uAP Fw <-> Fw */ -#define IF_ID_LMAC 0x001a /* Interface exposed by LMAC */ - -struct exp_if { - __le16 role; - __le16 if_id; - __le16 variant; - __le16 btm_compat; - __le16 top_compat; -} __packed; - -struct dep_if { - __le16 role; - __le16 if_id; - __le16 variant; -} __packed; - -/* driver <-> lmac definitions */ -struct p54_eeprom_lm86 { - union { - struct { - __le16 offset; - __le16 len; - u8 data[0]; - } __packed v1; - struct { - __le32 offset; - __le16 len; - u8 magic2; - u8 pad; - u8 magic[4]; - u8 data[0]; - } __packed v2; - } __packed; -} __packed; - -enum p54_rx_decrypt_status { - P54_DECRYPT_NONE = 0, - P54_DECRYPT_OK, - P54_DECRYPT_NOKEY, - P54_DECRYPT_NOMICHAEL, - P54_DECRYPT_NOCKIPMIC, - P54_DECRYPT_FAIL_WEP, - P54_DECRYPT_FAIL_TKIP, - P54_DECRYPT_FAIL_MICHAEL, - P54_DECRYPT_FAIL_CKIPKP, - P54_DECRYPT_FAIL_CKIPMIC, - P54_DECRYPT_FAIL_AESCCMP -}; - -struct p54_rx_data { - __le16 flags; - __le16 len; - __le16 freq; - u8 antenna; - u8 rate; - u8 rssi; - u8 quality; - u8 decrypt_status; - u8 rssi_raw; - __le32 tsf32; - __le32 unalloc0; - u8 align[0]; -} __packed; - -enum p54_trap_type { - P54_TRAP_SCAN = 0, - P54_TRAP_TIMER, - P54_TRAP_BEACON_TX, - P54_TRAP_FAA_RADIO_ON, - P54_TRAP_FAA_RADIO_OFF, - P54_TRAP_RADAR, - P54_TRAP_NO_BEACON, - P54_TRAP_TBTT, - P54_TRAP_SCO_ENTER, - P54_TRAP_SCO_EXIT -}; - -struct p54_trap { - __le16 event; - __le16 frequency; -} __packed; - -enum p54_frame_sent_status { - P54_TX_OK = 0, - P54_TX_FAILED, - P54_TX_PSM, - P54_TX_PSM_CANCELLED = 4 -}; - -struct p54_frame_sent { - u8 status; - u8 tries; - u8 ack_rssi; - u8 quality; - __le16 seq; - u8 antenna; - u8 padding; -} __packed; - -enum p54_tx_data_crypt { - P54_CRYPTO_NONE = 0, - P54_CRYPTO_WEP, - P54_CRYPTO_TKIP, - P54_CRYPTO_TKIPMICHAEL, - P54_CRYPTO_CCX_WEPMIC, - P54_CRYPTO_CCX_KPMIC, - P54_CRYPTO_CCX_KP, - P54_CRYPTO_AESCCMP -}; - -enum p54_tx_data_queue { - P54_QUEUE_BEACON = 0, - P54_QUEUE_FWSCAN = 1, - P54_QUEUE_MGMT = 2, - P54_QUEUE_CAB = 3, - P54_QUEUE_DATA = 4, - - P54_QUEUE_AC_NUM = 4, - P54_QUEUE_AC_VO = 4, - P54_QUEUE_AC_VI = 5, - P54_QUEUE_AC_BE = 6, - P54_QUEUE_AC_BK = 7, - - /* keep last */ - P54_QUEUE_NUM = 8, -}; - -#define IS_QOS_QUEUE(n) (n >= P54_QUEUE_DATA) - -struct p54_tx_data { - u8 rateset[8]; - u8 rts_rate_idx; - u8 crypt_offset; - u8 key_type; - u8 key_len; - u8 key[16]; - u8 hw_queue; - u8 backlog; - __le16 durations[4]; - u8 tx_antenna; - union { - struct { - u8 cts_rate; - __le16 output_power; - } __packed longbow; - struct { - u8 output_power; - u8 cts_rate; - u8 unalloc; - } __packed normal; - } __packed; - u8 unalloc2[2]; - u8 align[0]; -} __packed; - -/* unit is ms */ -#define P54_TX_FRAME_LIFETIME 2000 -#define P54_TX_TIMEOUT 4000 -#define P54_STATISTICS_UPDATE 5000 - -#define P54_FILTER_TYPE_NONE 0 -#define P54_FILTER_TYPE_STATION BIT(0) -#define P54_FILTER_TYPE_IBSS BIT(1) -#define P54_FILTER_TYPE_AP BIT(2) -#define P54_FILTER_TYPE_TRANSPARENT BIT(3) -#define P54_FILTER_TYPE_PROMISCUOUS BIT(4) -#define P54_FILTER_TYPE_HIBERNATE BIT(5) -#define P54_FILTER_TYPE_NOACK BIT(6) -#define P54_FILTER_TYPE_RX_DISABLED BIT(7) - -struct p54_setup_mac { - __le16 mac_mode; - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u8 rx_antenna; - u8 rx_align; - union { - struct { - __le32 basic_rate_mask; - u8 rts_rates[8]; - __le32 rx_addr; - __le16 max_rx; - __le16 rxhw; - __le16 wakeup_timer; - __le16 unalloc0; - } __packed v1; - struct { - __le32 rx_addr; - __le16 max_rx; - __le16 rxhw; - __le16 timer; - __le16 truncate; - __le32 basic_rate_mask; - u8 sbss_offset; - u8 mcast_window; - u8 rx_rssi_threshold; - u8 rx_ed_threshold; - __le32 ref_clock; - __le16 lpf_bandwidth; - __le16 osc_start_delay; - } __packed v2; - } __packed; -} __packed; - -#define P54_SETUP_V1_LEN 40 -#define P54_SETUP_V2_LEN (sizeof(struct p54_setup_mac)) - -#define P54_SCAN_EXIT BIT(0) -#define P54_SCAN_TRAP BIT(1) -#define P54_SCAN_ACTIVE BIT(2) -#define P54_SCAN_FILTER BIT(3) - -struct p54_scan_head { - __le16 mode; - __le16 dwell; - u8 scan_params[20]; - __le16 freq; -} __packed; - -struct p54_pa_curve_data_sample { - u8 rf_power; - u8 pa_detector; - u8 data_barker; - u8 data_bpsk; - u8 data_qpsk; - u8 data_16qam; - u8 data_64qam; - u8 padding; -} __packed; - -struct p54_scan_body { - u8 pa_points_per_curve; - u8 val_barker; - u8 val_bpsk; - u8 val_qpsk; - u8 val_16qam; - u8 val_64qam; - struct p54_pa_curve_data_sample curve_data[8]; - u8 dup_bpsk; - u8 dup_qpsk; - u8 dup_16qam; - u8 dup_64qam; -} __packed; - -/* - * Warning: Longbow's structures are bogus. - */ -struct p54_channel_output_limit_longbow { - __le16 rf_power_points[12]; -} __packed; - -struct p54_pa_curve_data_sample_longbow { - __le16 rf_power; - __le16 pa_detector; - struct { - __le16 data[4]; - } points[3] __packed; -} __packed; - -struct p54_scan_body_longbow { - struct p54_channel_output_limit_longbow power_limits; - struct p54_pa_curve_data_sample_longbow curve_data[8]; - __le16 unkn[6]; /* maybe more power_limits or rate_mask */ -} __packed; - -union p54_scan_body_union { - struct p54_scan_body normal; - struct p54_scan_body_longbow longbow; -} __packed; - -struct p54_scan_tail_rate { - __le32 basic_rate_mask; - u8 rts_rates[8]; -} __packed; - -struct p54_led { - __le16 flags; - __le16 mask[2]; - __le16 delay[2]; -} __packed; - -struct p54_edcf { - u8 flags; - u8 slottime; - u8 sifs; - u8 eofpad; - struct p54_edcf_queue_param queue[8]; - u8 mapping[4]; - __le16 frameburst; - __le16 round_trip_delay; -} __packed; - -struct p54_statistics { - __le32 rx_success; - __le32 rx_bad_fcs; - __le32 rx_abort; - __le32 rx_abort_phy; - __le32 rts_success; - __le32 rts_fail; - __le32 tsf32; - __le32 airtime; - __le32 noise; - __le32 sample_noise[8]; - __le32 sample_cca; - __le32 sample_tx; -} __packed; - -struct p54_xbow_synth { - __le16 magic1; - __le16 magic2; - __le16 freq; - u32 padding[5]; -} __packed; - -struct p54_timer { - __le32 interval; -} __packed; - -struct p54_keycache { - u8 entry; - u8 key_id; - u8 mac[ETH_ALEN]; - u8 padding[2]; - u8 key_type; - u8 key_len; - u8 key[24]; -} __packed; - -struct p54_burst { - u8 flags; - u8 queue; - u8 backlog; - u8 pad; - __le16 durations[32]; -} __packed; - -struct p54_psm_interval { - __le16 interval; - __le16 periods; -} __packed; - -#define P54_PSM_CAM 0 -#define P54_PSM BIT(0) -#define P54_PSM_DTIM BIT(1) -#define P54_PSM_MCBC BIT(2) -#define P54_PSM_CHECKSUM BIT(3) -#define P54_PSM_SKIP_MORE_DATA BIT(4) -#define P54_PSM_BEACON_TIMEOUT BIT(5) -#define P54_PSM_HFOSLEEP BIT(6) -#define P54_PSM_AUTOSWITCH_SLEEP BIT(7) -#define P54_PSM_LPIT BIT(8) -#define P54_PSM_BF_UCAST_SKIP BIT(9) -#define P54_PSM_BF_MCAST_SKIP BIT(10) - -struct p54_psm { - __le16 mode; - __le16 aid; - struct p54_psm_interval intervals[4]; - u8 beacon_rssi_skip_max; - u8 rssi_delta_threshold; - u8 nr; - u8 exclude[1]; -} __packed; - -#define MC_FILTER_ADDRESS_NUM 4 - -struct p54_group_address_table { - __le16 filter_enable; - __le16 num_address; - u8 mac_list[MC_FILTER_ADDRESS_NUM][ETH_ALEN]; -} __packed; - -struct p54_txcancel { - __le32 req_id; -} __packed; - -struct p54_sta_unlock { - u8 addr[ETH_ALEN]; - u16 padding; -} __packed; - -#define P54_TIM_CLEAR BIT(15) -struct p54_tim { - u8 count; - u8 padding[3]; - __le16 entry[8]; -} __packed; - -struct p54_cce_quiet { - __le32 period; -} __packed; - -struct p54_bt_balancer { - __le16 prio_thresh; - __le16 acl_thresh; -} __packed; - -struct p54_arp_table { - __le16 filter_enable; - u8 ipv4_addr[4]; -} __packed; - -/* LED control */ -int p54_set_leds(struct p54_common *priv); -int p54_init_leds(struct p54_common *priv); -void p54_unregister_leds(struct p54_common *priv); - -/* xmit functions */ -int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb); -int p54_tx_cancel(struct p54_common *priv, __le32 req_id); -void p54_tx(struct p54_common *priv, struct sk_buff *skb); - -/* synth/phy configuration */ -int p54_init_xbow_synth(struct p54_common *priv); -int p54_scan(struct p54_common *priv, u16 mode, u16 dwell); - -/* MAC */ -int p54_sta_unlock(struct p54_common *priv, u8 *addr); -int p54_update_beacon_tim(struct p54_common *priv, u16 aid, bool set); -int p54_setup_mac(struct p54_common *priv); -int p54_set_ps(struct p54_common *priv); -int p54_fetch_statistics(struct p54_common *priv); - -/* e/v DCF setup */ -int p54_set_edcf(struct p54_common *priv); - -/* cryptographic engine */ -int p54_upload_key(struct p54_common *priv, u8 algo, int slot, - u8 idx, u8 len, u8 *addr, u8* key); - -/* eeprom */ -int p54_download_eeprom(struct p54_common *priv, void *buf, - u16 offset, u16 len); - -/* utility */ -u8 *p54_find_ie(struct sk_buff *skb, u8 ie); - -#endif /* LMAC_H */ diff --git a/drivers/net/wireless/p54/main.c b/drivers/net/wireless/p54/main.c deleted file mode 100644 index 4d486bf9f725..000000000000 --- a/drivers/net/wireless/p54/main.c +++ /dev/null @@ -1,648 +0,0 @@ -/* - * mac80211 glue code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007-2009, Christian Lamparter - * Copyright 2008, Johannes Berg - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - stlc45xx driver - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include - -#include "p54.h" -#include "lmac.h" - -static int modparam_nohwcrypt; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); -MODULE_AUTHOR("Michael Wu "); -MODULE_DESCRIPTION("Softmac Prism54 common code"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54common"); - -static void p54_sta_notify(struct ieee80211_hw *dev, struct ieee80211_vif *vif, - enum sta_notify_cmd notify_cmd, - struct ieee80211_sta *sta) -{ - struct p54_common *priv = dev->priv; - switch (notify_cmd) { - case STA_NOTIFY_ADD: - case STA_NOTIFY_REMOVE: - /* - * Notify the firmware that we don't want or we don't - * need to buffer frames for this station anymore. - */ - - p54_sta_unlock(priv, sta->addr); - break; - case STA_NOTIFY_AWAKE: - /* update the firmware's filter table */ - p54_sta_unlock(priv, sta->addr); - break; - default: - break; - } -} - -static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, - bool set) -{ - struct p54_common *priv = dev->priv; - - return p54_update_beacon_tim(priv, sta->aid, set); -} - -u8 *p54_find_ie(struct sk_buff *skb, u8 ie) -{ - struct ieee80211_mgmt *mgmt = (void *)skb->data; - u8 *pos, *end; - - if (skb->len <= sizeof(mgmt)) - return NULL; - - pos = (u8 *)mgmt->u.beacon.variable; - end = skb->data + skb->len; - while (pos < end) { - if (pos + 2 + pos[1] > end) - return NULL; - - if (pos[0] == ie) - return pos; - - pos += 2 + pos[1]; - } - return NULL; -} - -static int p54_beacon_format_ie_tim(struct sk_buff *skb) -{ - /* - * the good excuse for this mess is ... the firmware. - * The dummy TIM MUST be at the end of the beacon frame, - * because it'll be overwritten! - */ - u8 *tim; - u8 dtim_len; - u8 dtim_period; - u8 *next; - - tim = p54_find_ie(skb, WLAN_EID_TIM); - if (!tim) - return 0; - - dtim_len = tim[1]; - dtim_period = tim[3]; - next = tim + 2 + dtim_len; - - if (dtim_len < 3) - return -EINVAL; - - memmove(tim, next, skb_tail_pointer(skb) - next); - tim = skb_tail_pointer(skb) - (dtim_len + 2); - - /* add the dummy at the end */ - tim[0] = WLAN_EID_TIM; - tim[1] = 3; - tim[2] = 0; - tim[3] = dtim_period; - tim[4] = 0; - - if (dtim_len > 3) - skb_trim(skb, skb->len - (dtim_len - 3)); - - return 0; -} - -static int p54_beacon_update(struct p54_common *priv, - struct ieee80211_vif *vif) -{ - struct sk_buff *beacon; - int ret; - - beacon = ieee80211_beacon_get(priv->hw, vif); - if (!beacon) - return -ENOMEM; - ret = p54_beacon_format_ie_tim(beacon); - if (ret) - return ret; - - /* - * During operation, the firmware takes care of beaconing. - * The driver only needs to upload a new beacon template, once - * the template was changed by the stack or userspace. - * - * LMAC API 3.2.2 also specifies that the driver does not need - * to cancel the old beacon template by hand, instead the firmware - * will release the previous one through the feedback mechanism. - */ - WARN_ON(p54_tx_80211(priv->hw, beacon)); - priv->tsf_high32 = 0; - priv->tsf_low32 = 0; - - return 0; -} - -static int p54_start(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int err; - - mutex_lock(&priv->conf_mutex); - err = priv->open(dev); - if (err) - goto out; - P54_SET_QUEUE(priv->qos_params[0], 0x0002, 0x0003, 0x0007, 47); - P54_SET_QUEUE(priv->qos_params[1], 0x0002, 0x0007, 0x000f, 94); - P54_SET_QUEUE(priv->qos_params[2], 0x0003, 0x000f, 0x03ff, 0); - P54_SET_QUEUE(priv->qos_params[3], 0x0007, 0x000f, 0x03ff, 0); - err = p54_set_edcf(priv); - if (err) - goto out; - - memset(priv->bssid, ~0, ETH_ALEN); - priv->mode = NL80211_IFTYPE_MONITOR; - err = p54_setup_mac(priv); - if (err) { - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - goto out; - } - - ieee80211_queue_delayed_work(dev, &priv->work, 0); - - priv->softled_state = 0; - err = p54_set_leds(priv); - -out: - mutex_unlock(&priv->conf_mutex); - return err; -} - -static void p54_stop(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - int i; - - mutex_lock(&priv->conf_mutex); - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - priv->softled_state = 0; - p54_set_leds(priv); - - cancel_delayed_work_sync(&priv->work); - - priv->stop(dev); - skb_queue_purge(&priv->tx_pending); - skb_queue_purge(&priv->tx_queue); - for (i = 0; i < P54_QUEUE_NUM; i++) { - priv->tx_stats[i].count = 0; - priv->tx_stats[i].len = 0; - } - - priv->beacon_req_id = cpu_to_le32(0); - priv->tsf_high32 = priv->tsf_low32 = 0; - mutex_unlock(&priv->conf_mutex); -} - -static int p54_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); - if (priv->mode != NL80211_IFTYPE_MONITOR) { - mutex_unlock(&priv->conf_mutex); - return -EOPNOTSUPP; - } - - priv->vif = conf->vif; - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - priv->mode = conf->type; - break; - default: - mutex_unlock(&priv->conf_mutex); - return -EOPNOTSUPP; - } - - memcpy(priv->mac_addr, conf->mac_addr, ETH_ALEN); - p54_setup_mac(priv); - mutex_unlock(&priv->conf_mutex); - return 0; -} - -static void p54_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); - priv->vif = NULL; - - /* - * LMAC API 3.2.2 states that any active beacon template must be - * canceled by the driver before attempting a mode transition. - */ - if (le32_to_cpu(priv->beacon_req_id) != 0) { - p54_tx_cancel(priv, priv->beacon_req_id); - wait_for_completion_interruptible_timeout(&priv->beacon_comp, HZ); - } - priv->mode = NL80211_IFTYPE_MONITOR; - memset(priv->mac_addr, 0, ETH_ALEN); - memset(priv->bssid, 0, ETH_ALEN); - p54_setup_mac(priv); - mutex_unlock(&priv->conf_mutex); -} - -static int p54_config(struct ieee80211_hw *dev, u32 changed) -{ - int ret = 0; - struct p54_common *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - - mutex_lock(&priv->conf_mutex); - if (changed & IEEE80211_CONF_CHANGE_POWER) - priv->output_power = conf->power_level << 2; - if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { - ret = p54_scan(priv, P54_SCAN_EXIT, 0); - if (ret) - goto out; - } - if (changed & IEEE80211_CONF_CHANGE_PS) { - ret = p54_set_ps(priv); - if (ret) - goto out; - } - if (changed & IEEE80211_CONF_CHANGE_IDLE) { - ret = p54_setup_mac(priv); - if (ret) - goto out; - } - -out: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void p54_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct p54_common *priv = dev->priv; - - *total_flags &= FIF_PROMISC_IN_BSS | - FIF_OTHER_BSS; - - priv->filter_flags = *total_flags; - - if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) - p54_setup_mac(priv); -} - -static int p54_conf_tx(struct ieee80211_hw *dev, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct p54_common *priv = dev->priv; - int ret; - - mutex_lock(&priv->conf_mutex); - if (queue < dev->queues) { - P54_SET_QUEUE(priv->qos_params[queue], params->aifs, - params->cw_min, params->cw_max, params->txop); - ret = p54_set_edcf(priv); - } else - ret = -EINVAL; - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void p54_work(struct work_struct *work) -{ - struct p54_common *priv = container_of(work, struct p54_common, - work.work); - - if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) - return ; - - /* - * TODO: walk through tx_queue and do the following tasks - * 1. initiate bursts. - * 2. cancel stuck frames / reset the device if necessary. - */ - - p54_fetch_statistics(priv); -} - -static int p54_get_stats(struct ieee80211_hw *dev, - struct ieee80211_low_level_stats *stats) -{ - struct p54_common *priv = dev->priv; - - memcpy(stats, &priv->stats, sizeof(*stats)); - return 0; -} - -static int p54_get_tx_stats(struct ieee80211_hw *dev, - struct ieee80211_tx_queue_stats *stats) -{ - struct p54_common *priv = dev->priv; - - memcpy(stats, &priv->tx_stats[P54_QUEUE_DATA], - sizeof(stats[0]) * dev->queues); - return 0; -} - -static void p54_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct p54_common *priv = dev->priv; - - mutex_lock(&priv->conf_mutex); - if (changed & BSS_CHANGED_BSSID) { - memcpy(priv->bssid, info->bssid, ETH_ALEN); - p54_setup_mac(priv); - } - - if (changed & BSS_CHANGED_BEACON) { - p54_scan(priv, P54_SCAN_EXIT, 0); - p54_setup_mac(priv); - p54_beacon_update(priv, vif); - p54_set_edcf(priv); - } - - if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_BEACON)) { - priv->use_short_slot = info->use_short_slot; - p54_set_edcf(priv); - } - if (changed & BSS_CHANGED_BASIC_RATES) { - if (dev->conf.channel->band == IEEE80211_BAND_5GHZ) - priv->basic_rate_mask = (info->basic_rates << 4); - else - priv->basic_rate_mask = info->basic_rates; - p54_setup_mac(priv); - if (priv->fw_var >= 0x500) - p54_scan(priv, P54_SCAN_EXIT, 0); - } - if (changed & BSS_CHANGED_ASSOC) { - if (info->assoc) { - priv->aid = info->aid; - priv->wakeup_timer = info->beacon_int * - info->dtim_period * 5; - p54_setup_mac(priv); - } else { - priv->wakeup_timer = 500; - priv->aid = 0; - } - } - - mutex_unlock(&priv->conf_mutex); -} - -static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct p54_common *priv = dev->priv; - int slot, ret = 0; - u8 algo = 0; - u8 *addr = NULL; - - if (modparam_nohwcrypt) - return -EOPNOTSUPP; - - mutex_lock(&priv->conf_mutex); - if (cmd == SET_KEY) { - switch (key->alg) { - case ALG_TKIP: - if (!(priv->privacy_caps & (BR_DESC_PRIV_CAP_MICHAEL | - BR_DESC_PRIV_CAP_TKIP))) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - algo = P54_CRYPTO_TKIPMICHAEL; - break; - case ALG_WEP: - if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_WEP)) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - algo = P54_CRYPTO_WEP; - break; - case ALG_CCMP: - if (!(priv->privacy_caps & BR_DESC_PRIV_CAP_AESCCMP)) { - ret = -EOPNOTSUPP; - goto out_unlock; - } - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - algo = P54_CRYPTO_AESCCMP; - break; - default: - ret = -EOPNOTSUPP; - goto out_unlock; - } - slot = bitmap_find_free_region(priv->used_rxkeys, - priv->rx_keycache_size, 0); - - if (slot < 0) { - /* - * The device supports the choosen algorithm, but the - * firmware does not provide enough key slots to store - * all of them. - * But encryption offload for outgoing frames is always - * possible, so we just pretend that the upload was - * successful and do the decryption in software. - */ - - /* mark the key as invalid. */ - key->hw_key_idx = 0xff; - goto out_unlock; - } - } else { - slot = key->hw_key_idx; - - if (slot == 0xff) { - /* This key was not uploaded into the rx key cache. */ - - goto out_unlock; - } - - bitmap_release_region(priv->used_rxkeys, slot, 0); - algo = 0; - } - - if (sta) - addr = sta->addr; - - ret = p54_upload_key(priv, algo, slot, key->keyidx, - key->keylen, addr, key->key); - if (ret) { - bitmap_release_region(priv->used_rxkeys, slot, 0); - ret = -EOPNOTSUPP; - goto out_unlock; - } - - key->hw_key_idx = slot; - -out_unlock: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static const struct ieee80211_ops p54_ops = { - .tx = p54_tx_80211, - .start = p54_start, - .stop = p54_stop, - .add_interface = p54_add_interface, - .remove_interface = p54_remove_interface, - .set_tim = p54_set_tim, - .sta_notify = p54_sta_notify, - .set_key = p54_set_key, - .config = p54_config, - .bss_info_changed = p54_bss_info_changed, - .configure_filter = p54_configure_filter, - .conf_tx = p54_conf_tx, - .get_stats = p54_get_stats, - .get_tx_stats = p54_get_tx_stats -}; - -struct ieee80211_hw *p54_init_common(size_t priv_data_len) -{ - struct ieee80211_hw *dev; - struct p54_common *priv; - - dev = ieee80211_alloc_hw(priv_data_len, &p54_ops); - if (!dev) - return NULL; - - priv = dev->priv; - priv->hw = dev; - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - priv->basic_rate_mask = 0x15f; - spin_lock_init(&priv->tx_stats_lock); - skb_queue_head_init(&priv->tx_queue); - skb_queue_head_init(&priv->tx_pending); - dev->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK | - IEEE80211_HW_BEACON_FILTER | - IEEE80211_HW_NOISE_DBM; - - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT); - - dev->channel_change_time = 1000; /* TODO: find actual value */ - priv->beacon_req_id = cpu_to_le32(0); - priv->tx_stats[P54_QUEUE_BEACON].limit = 1; - priv->tx_stats[P54_QUEUE_FWSCAN].limit = 1; - priv->tx_stats[P54_QUEUE_MGMT].limit = 3; - priv->tx_stats[P54_QUEUE_CAB].limit = 3; - priv->tx_stats[P54_QUEUE_DATA].limit = 5; - dev->queues = 1; - priv->noise = -94; - /* - * We support at most 8 tries no matter which rate they're at, - * we cannot support max_rates * max_rate_tries as we set it - * here, but setting it correctly to 4/2 or so would limit us - * artificially if the RC algorithm wants just two rates, so - * let's say 4/7, we'll redistribute it at TX time, see the - * comments there. - */ - dev->max_rates = 4; - dev->max_rate_tries = 7; - dev->extra_tx_headroom = sizeof(struct p54_hdr) + 4 + - sizeof(struct p54_tx_data); - - /* - * For now, disable PS by default because it affects - * link stability significantly. - */ - dev->wiphy->ps_default = false; - - mutex_init(&priv->conf_mutex); - mutex_init(&priv->eeprom_mutex); - init_completion(&priv->eeprom_comp); - init_completion(&priv->beacon_comp); - INIT_DELAYED_WORK(&priv->work, p54_work); - - return dev; -} -EXPORT_SYMBOL_GPL(p54_init_common); - -int p54_register_common(struct ieee80211_hw *dev, struct device *pdev) -{ - struct p54_common *priv = dev->priv; - int err; - - err = ieee80211_register_hw(dev); - if (err) { - dev_err(pdev, "Cannot register device (%d).\n", err); - return err; - } - -#ifdef CONFIG_P54_LEDS - err = p54_init_leds(priv); - if (err) - return err; -#endif /* CONFIG_P54_LEDS */ - - dev_info(pdev, "is registered as '%s'\n", wiphy_name(dev->wiphy)); - return 0; -} -EXPORT_SYMBOL_GPL(p54_register_common); - -void p54_free_common(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - unsigned int i; - - for (i = 0; i < IEEE80211_NUM_BANDS; i++) - kfree(priv->band_table[i]); - - kfree(priv->iq_autocal); - kfree(priv->output_limit); - kfree(priv->curve_data); - kfree(priv->used_rxkeys); - priv->iq_autocal = NULL; - priv->output_limit = NULL; - priv->curve_data = NULL; - priv->used_rxkeys = NULL; - ieee80211_free_hw(dev); -} -EXPORT_SYMBOL_GPL(p54_free_common); - -void p54_unregister_common(struct ieee80211_hw *dev) -{ - struct p54_common *priv = dev->priv; - -#ifdef CONFIG_P54_LEDS - p54_unregister_leds(priv); -#endif /* CONFIG_P54_LEDS */ - - ieee80211_unregister_hw(dev); - mutex_destroy(&priv->conf_mutex); - mutex_destroy(&priv->eeprom_mutex); -} -EXPORT_SYMBOL_GPL(p54_unregister_common); diff --git a/drivers/net/wireless/p54/net2280.h b/drivers/net/wireless/p54/net2280.h deleted file mode 100644 index 4915d9d54203..000000000000 --- a/drivers/net/wireless/p54/net2280.h +++ /dev/null @@ -1,452 +0,0 @@ -#ifndef NET2280_H -#define NET2280_H -/* - * NetChip 2280 high/full speed USB device controller. - * Unlike many such controllers, this one talks PCI. - */ - -/* - * Copyright (C) 2002 NetChip Technology, Inc. (http://www.netchip.com) - * Copyright (C) 2003 David Brownell - * - * 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 - */ - -/*-------------------------------------------------------------------------*/ - -/* NET2280 MEMORY MAPPED REGISTERS - * - * The register layout came from the chip documentation, and the bit - * number definitions were extracted from chip specification. - * - * Use the shift operator ('<<') to build bit masks, with readl/writel - * to access the registers through PCI. - */ - -/* main registers, BAR0 + 0x0000 */ -struct net2280_regs { - /* offset 0x0000 */ - __le32 devinit; -#define LOCAL_CLOCK_FREQUENCY 8 -#define FORCE_PCI_RESET 7 -#define PCI_ID 6 -#define PCI_ENABLE 5 -#define FIFO_SOFT_RESET 4 -#define CFG_SOFT_RESET 3 -#define PCI_SOFT_RESET 2 -#define USB_SOFT_RESET 1 -#define M8051_RESET 0 - __le32 eectl; -#define EEPROM_ADDRESS_WIDTH 23 -#define EEPROM_CHIP_SELECT_ACTIVE 22 -#define EEPROM_PRESENT 21 -#define EEPROM_VALID 20 -#define EEPROM_BUSY 19 -#define EEPROM_CHIP_SELECT_ENABLE 18 -#define EEPROM_BYTE_READ_START 17 -#define EEPROM_BYTE_WRITE_START 16 -#define EEPROM_READ_DATA 8 -#define EEPROM_WRITE_DATA 0 - __le32 eeclkfreq; - u32 _unused0; - /* offset 0x0010 */ - - __le32 pciirqenb0; /* interrupt PCI master ... */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - __le32 pciirqenb1; -#define PCI_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_TARGET_ABORT_ASSERTED_INTERRUPT_ENABLE 18 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - __le32 cpu_irqenb0; /* ... or onboard 8051 */ -#define SETUP_PACKET_INTERRUPT_ENABLE 7 -#define ENDPOINT_F_INTERRUPT_ENABLE 6 -#define ENDPOINT_E_INTERRUPT_ENABLE 5 -#define ENDPOINT_D_INTERRUPT_ENABLE 4 -#define ENDPOINT_C_INTERRUPT_ENABLE 3 -#define ENDPOINT_B_INTERRUPT_ENABLE 2 -#define ENDPOINT_A_INTERRUPT_ENABLE 1 -#define ENDPOINT_0_INTERRUPT_ENABLE 0 - __le32 cpu_irqenb1; -#define CPU_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - - /* offset 0x0020 */ - u32 _unused1; - __le32 usbirqenb1; -#define USB_INTERRUPT_ENABLE 31 -#define POWER_STATE_CHANGE_INTERRUPT_ENABLE 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT_ENABLE 26 -#define PCI_PARITY_ERROR_INTERRUPT_ENABLE 25 -#define PCI_INTA_INTERRUPT_ENABLE 24 -#define PCI_PME_INTERRUPT_ENABLE 23 -#define PCI_SERR_INTERRUPT_ENABLE 22 -#define PCI_PERR_INTERRUPT_ENABLE 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT_ENABLE 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT_ENABLE 19 -#define PCI_RETRY_ABORT_INTERRUPT_ENABLE 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT_ENABLE 16 -#define GPIO_INTERRUPT_ENABLE 13 -#define DMA_D_INTERRUPT_ENABLE 12 -#define DMA_C_INTERRUPT_ENABLE 11 -#define DMA_B_INTERRUPT_ENABLE 10 -#define DMA_A_INTERRUPT_ENABLE 9 -#define EEPROM_DONE_INTERRUPT_ENABLE 8 -#define VBUS_INTERRUPT_ENABLE 7 -#define CONTROL_STATUS_INTERRUPT_ENABLE 6 -#define ROOT_PORT_RESET_INTERRUPT_ENABLE 4 -#define SUSPEND_REQUEST_INTERRUPT_ENABLE 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE 2 -#define RESUME_INTERRUPT_ENABLE 1 -#define SOF_INTERRUPT_ENABLE 0 - __le32 irqstat0; -#define INTA_ASSERTED 12 -#define SETUP_PACKET_INTERRUPT 7 -#define ENDPOINT_F_INTERRUPT 6 -#define ENDPOINT_E_INTERRUPT 5 -#define ENDPOINT_D_INTERRUPT 4 -#define ENDPOINT_C_INTERRUPT 3 -#define ENDPOINT_B_INTERRUPT 2 -#define ENDPOINT_A_INTERRUPT 1 -#define ENDPOINT_0_INTERRUPT 0 - __le32 irqstat1; -#define POWER_STATE_CHANGE_INTERRUPT 27 -#define PCI_ARBITER_TIMEOUT_INTERRUPT 26 -#define PCI_PARITY_ERROR_INTERRUPT 25 -#define PCI_INTA_INTERRUPT 24 -#define PCI_PME_INTERRUPT 23 -#define PCI_SERR_INTERRUPT 22 -#define PCI_PERR_INTERRUPT 21 -#define PCI_MASTER_ABORT_RECEIVED_INTERRUPT 20 -#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 -#define PCI_RETRY_ABORT_INTERRUPT 17 -#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 -#define GPIO_INTERRUPT 13 -#define DMA_D_INTERRUPT 12 -#define DMA_C_INTERRUPT 11 -#define DMA_B_INTERRUPT 10 -#define DMA_A_INTERRUPT 9 -#define EEPROM_DONE_INTERRUPT 8 -#define VBUS_INTERRUPT 7 -#define CONTROL_STATUS_INTERRUPT 6 -#define ROOT_PORT_RESET_INTERRUPT 4 -#define SUSPEND_REQUEST_INTERRUPT 3 -#define SUSPEND_REQUEST_CHANGE_INTERRUPT 2 -#define RESUME_INTERRUPT 1 -#define SOF_INTERRUPT 0 - /* offset 0x0030 */ - __le32 idxaddr; - __le32 idxdata; - __le32 fifoctl; -#define PCI_BASE2_RANGE 16 -#define IGNORE_FIFO_AVAILABILITY 3 -#define PCI_BASE2_SELECT 2 -#define FIFO_CONFIGURATION_SELECT 0 - u32 _unused2; - /* offset 0x0040 */ - __le32 memaddr; -#define START 28 -#define DIRECTION 27 -#define FIFO_DIAGNOSTIC_SELECT 24 -#define MEMORY_ADDRESS 0 - __le32 memdata0; - __le32 memdata1; - u32 _unused3; - /* offset 0x0050 */ - __le32 gpioctl; -#define GPIO3_LED_SELECT 12 -#define GPIO3_INTERRUPT_ENABLE 11 -#define GPIO2_INTERRUPT_ENABLE 10 -#define GPIO1_INTERRUPT_ENABLE 9 -#define GPIO0_INTERRUPT_ENABLE 8 -#define GPIO3_OUTPUT_ENABLE 7 -#define GPIO2_OUTPUT_ENABLE 6 -#define GPIO1_OUTPUT_ENABLE 5 -#define GPIO0_OUTPUT_ENABLE 4 -#define GPIO3_DATA 3 -#define GPIO2_DATA 2 -#define GPIO1_DATA 1 -#define GPIO0_DATA 0 - __le32 gpiostat; -#define GPIO3_INTERRUPT 3 -#define GPIO2_INTERRUPT 2 -#define GPIO1_INTERRUPT 1 -#define GPIO0_INTERRUPT 0 -} __attribute__ ((packed)); - -/* usb control, BAR0 + 0x0080 */ -struct net2280_usb_regs { - /* offset 0x0080 */ - __le32 stdrsp; -#define STALL_UNSUPPORTED_REQUESTS 31 -#define SET_TEST_MODE 16 -#define GET_OTHER_SPEED_CONFIGURATION 15 -#define GET_DEVICE_QUALIFIER 14 -#define SET_ADDRESS 13 -#define ENDPOINT_SET_CLEAR_HALT 12 -#define DEVICE_SET_CLEAR_DEVICE_REMOTE_WAKEUP 11 -#define GET_STRING_DESCRIPTOR_2 10 -#define GET_STRING_DESCRIPTOR_1 9 -#define GET_STRING_DESCRIPTOR_0 8 -#define GET_SET_INTERFACE 6 -#define GET_SET_CONFIGURATION 5 -#define GET_CONFIGURATION_DESCRIPTOR 4 -#define GET_DEVICE_DESCRIPTOR 3 -#define GET_ENDPOINT_STATUS 2 -#define GET_INTERFACE_STATUS 1 -#define GET_DEVICE_STATUS 0 - __le32 prodvendid; -#define PRODUCT_ID 16 -#define VENDOR_ID 0 - __le32 relnum; - __le32 usbctl; -#define SERIAL_NUMBER_INDEX 16 -#define PRODUCT_ID_STRING_ENABLE 13 -#define VENDOR_ID_STRING_ENABLE 12 -#define USB_ROOT_PORT_WAKEUP_ENABLE 11 -#define VBUS_PIN 10 -#define TIMED_DISCONNECT 9 -#define SUSPEND_IMMEDIATELY 7 -#define SELF_POWERED_USB_DEVICE 6 -#define REMOTE_WAKEUP_SUPPORT 5 -#define PME_POLARITY 4 -#define USB_DETECT_ENABLE 3 -#define PME_WAKEUP_ENABLE 2 -#define DEVICE_REMOTE_WAKEUP_ENABLE 1 -#define SELF_POWERED_STATUS 0 - /* offset 0x0090 */ - __le32 usbstat; -#define HIGH_SPEED 7 -#define FULL_SPEED 6 -#define GENERATE_RESUME 5 -#define GENERATE_DEVICE_REMOTE_WAKEUP 4 - __le32 xcvrdiag; -#define FORCE_HIGH_SPEED_MODE 31 -#define FORCE_FULL_SPEED_MODE 30 -#define USB_TEST_MODE 24 -#define LINE_STATE 16 -#define TRANSCEIVER_OPERATION_MODE 2 -#define TRANSCEIVER_SELECT 1 -#define TERMINATION_SELECT 0 - __le32 setup0123; - __le32 setup4567; - /* offset 0x0090 */ - u32 _unused0; - __le32 ouraddr; -#define FORCE_IMMEDIATE 7 -#define OUR_USB_ADDRESS 0 - __le32 ourconfig; -} __attribute__ ((packed)); - -/* pci control, BAR0 + 0x0100 */ -struct net2280_pci_regs { - /* offset 0x0100 */ - __le32 pcimstctl; -#define PCI_ARBITER_PARK_SELECT 13 -#define PCI_MULTI LEVEL_ARBITER 12 -#define PCI_RETRY_ABORT_ENABLE 11 -#define DMA_MEMORY_WRITE_AND_INVALIDATE_ENABLE 10 -#define DMA_READ_MULTIPLE_ENABLE 9 -#define DMA_READ_LINE_ENABLE 8 -#define PCI_MASTER_COMMAND_SELECT 6 -#define MEM_READ_OR_WRITE 0 -#define IO_READ_OR_WRITE 1 -#define CFG_READ_OR_WRITE 2 -#define PCI_MASTER_START 5 -#define PCI_MASTER_READ_WRITE 4 -#define PCI_MASTER_WRITE 0 -#define PCI_MASTER_READ 1 -#define PCI_MASTER_BYTE_WRITE_ENABLES 0 - __le32 pcimstaddr; - __le32 pcimstdata; - __le32 pcimststat; -#define PCI_ARBITER_CLEAR 2 -#define PCI_EXTERNAL_ARBITER 1 -#define PCI_HOST_MODE 0 -} __attribute__ ((packed)); - -/* dma control, BAR0 + 0x0180 ... array of four structs like this, - * for channels 0..3. see also struct net2280_dma: descriptor - * that can be loaded into some of these registers. - */ -struct net2280_dma_regs { /* [11.7] */ - /* offset 0x0180, 0x01a0, 0x01c0, 0x01e0, */ - __le32 dmactl; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT_ENABLE 25 -#define DMA_CLEAR_COUNT_ENABLE 21 -#define DESCRIPTOR_POLLING_RATE 19 -#define POLL_CONTINUOUS 0 -#define POLL_1_USEC 1 -#define POLL_100_USEC 2 -#define POLL_1_MSEC 3 -#define DMA_VALID_BIT_POLLING_ENABLE 18 -#define DMA_VALID_BIT_ENABLE 17 -#define DMA_SCATTER_GATHER_ENABLE 16 -#define DMA_OUT_AUTO_START_ENABLE 4 -#define DMA_PREEMPT_ENABLE 3 -#define DMA_FIFO_VALIDATE 2 -#define DMA_ENABLE 1 -#define DMA_ADDRESS_HOLD 0 - __le32 dmastat; -#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 -#define DMA_TRANSACTION_DONE_INTERRUPT 24 -#define DMA_ABORT 1 -#define DMA_START 0 - u32 _unused0[2]; - /* offset 0x0190, 0x01b0, 0x01d0, 0x01f0, */ - __le32 dmacount; -#define VALID_BIT 31 -#define DMA_DIRECTION 30 -#define DMA_DONE_INTERRUPT_ENABLE 29 -#define END_OF_CHAIN 28 -#define DMA_BYTE_COUNT_MASK ((1<<24)-1) -#define DMA_BYTE_COUNT 0 - __le32 dmaaddr; - __le32 dmadesc; - u32 _unused1; -} __attribute__ ((packed)); - -/* dedicated endpoint registers, BAR0 + 0x0200 */ - -struct net2280_dep_regs { /* [11.8] */ - /* offset 0x0200, 0x0210, 0x220, 0x230, 0x240 */ - __le32 dep_cfg; - /* offset 0x0204, 0x0214, 0x224, 0x234, 0x244 */ - __le32 dep_rsp; - u32 _unused[2]; -} __attribute__ ((packed)); - -/* configurable endpoint registers, BAR0 + 0x0300 ... array of seven structs - * like this, for ep0 then the configurable endpoints A..F - * ep0 reserved for control; E and F have only 64 bytes of fifo - */ -struct net2280_ep_regs { /* [11.9] */ - /* offset 0x0300, 0x0320, 0x0340, 0x0360, 0x0380, 0x03a0, 0x03c0 */ - __le32 ep_cfg; -#define ENDPOINT_BYTE_COUNT 16 -#define ENDPOINT_ENABLE 10 -#define ENDPOINT_TYPE 8 -#define ENDPOINT_DIRECTION 7 -#define ENDPOINT_NUMBER 0 - __le32 ep_rsp; -#define SET_NAK_OUT_PACKETS 15 -#define SET_EP_HIDE_STATUS_PHASE 14 -#define SET_EP_FORCE_CRC_ERROR 13 -#define SET_INTERRUPT_MODE 12 -#define SET_CONTROL_STATUS_PHASE_HANDSHAKE 11 -#define SET_NAK_OUT_PACKETS_MODE 10 -#define SET_ENDPOINT_TOGGLE 9 -#define SET_ENDPOINT_HALT 8 -#define CLEAR_NAK_OUT_PACKETS 7 -#define CLEAR_EP_HIDE_STATUS_PHASE 6 -#define CLEAR_EP_FORCE_CRC_ERROR 5 -#define CLEAR_INTERRUPT_MODE 4 -#define CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE 3 -#define CLEAR_NAK_OUT_PACKETS_MODE 2 -#define CLEAR_ENDPOINT_TOGGLE 1 -#define CLEAR_ENDPOINT_HALT 0 - __le32 ep_irqenb; -#define SHORT_PACKET_OUT_DONE_INTERRUPT_ENABLE 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT_ENABLE 5 -#define DATA_PACKET_RECEIVED_INTERRUPT_ENABLE 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT_ENABLE 1 -#define DATA_IN_TOKEN_INTERRUPT_ENABLE 0 - __le32 ep_stat; -#define FIFO_VALID_COUNT 24 -#define HIGH_BANDWIDTH_OUT_TRANSACTION_PID 22 -#define TIMEOUT 21 -#define USB_STALL_SENT 20 -#define USB_IN_NAK_SENT 19 -#define USB_IN_ACK_RCVD 18 -#define USB_OUT_PING_NAK_SENT 17 -#define USB_OUT_ACK_SENT 16 -#define FIFO_OVERFLOW 13 -#define FIFO_UNDERFLOW 12 -#define FIFO_FULL 11 -#define FIFO_EMPTY 10 -#define FIFO_FLUSH 9 -#define SHORT_PACKET_OUT_DONE_INTERRUPT 6 -#define SHORT_PACKET_TRANSFERRED_INTERRUPT 5 -#define NAK_OUT_PACKETS 4 -#define DATA_PACKET_RECEIVED_INTERRUPT 3 -#define DATA_PACKET_TRANSMITTED_INTERRUPT 2 -#define DATA_OUT_PING_TOKEN_INTERRUPT 1 -#define DATA_IN_TOKEN_INTERRUPT 0 - /* offset 0x0310, 0x0330, 0x0350, 0x0370, 0x0390, 0x03b0, 0x03d0 */ - __le32 ep_avail; - __le32 ep_data; - u32 _unused0[2]; -} __attribute__ ((packed)); - -struct net2280_reg_write { - __le16 port; - __le32 addr; - __le32 val; -} __attribute__ ((packed)); - -struct net2280_reg_read { - __le16 port; - __le32 addr; -} __attribute__ ((packed)); -#endif /* NET2280_H */ diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h deleted file mode 100644 index 1afc39410e85..000000000000 --- a/drivers/net/wireless/p54/p54.h +++ /dev/null @@ -1,251 +0,0 @@ -/* - * Shared defines for all mac80211 Prism54 code - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef P54_H -#define P54_H - -#ifdef CONFIG_P54_LEDS -#include -#endif /* CONFIG_P54_LEDS */ - -#define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 - -#define BR_CODE_MIN 0x80000000 -#define BR_CODE_COMPONENT_ID 0x80000001 -#define BR_CODE_COMPONENT_VERSION 0x80000002 -#define BR_CODE_DEPENDENT_IF 0x80000003 -#define BR_CODE_EXPOSED_IF 0x80000004 -#define BR_CODE_DESCR 0x80000101 -#define BR_CODE_MAX 0x8FFFFFFF -#define BR_CODE_END_OF_BRA 0xFF0000FF -#define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF - -struct bootrec { - __le32 code; - __le32 len; - u32 data[10]; -} __packed; - -/* Interface role definitions */ -#define BR_INTERFACE_ROLE_SERVER 0x0000 -#define BR_INTERFACE_ROLE_CLIENT 0x8000 - -#define BR_DESC_PRIV_CAP_WEP BIT(0) -#define BR_DESC_PRIV_CAP_TKIP BIT(1) -#define BR_DESC_PRIV_CAP_MICHAEL BIT(2) -#define BR_DESC_PRIV_CAP_CCX_CP BIT(3) -#define BR_DESC_PRIV_CAP_CCX_MIC BIT(4) -#define BR_DESC_PRIV_CAP_AESCCMP BIT(5) - -struct bootrec_desc { - __le16 modes; - __le16 flags; - __le32 rx_start; - __le32 rx_end; - u8 headroom; - u8 tailroom; - u8 tx_queues; - u8 tx_depth; - u8 privacy_caps; - u8 rx_keycache_size; - u8 time_size; - u8 padding; - u8 rates[16]; - u8 padding2[4]; - __le16 rx_mtu; -} __packed; - -#define FW_FMAC 0x464d4143 -#define FW_LM86 0x4c4d3836 -#define FW_LM87 0x4c4d3837 -#define FW_LM20 0x4c4d3230 - -struct bootrec_comp_id { - __le32 fw_variant; -} __packed; - -struct bootrec_comp_ver { - char fw_version[24]; -} __packed; - -struct bootrec_end { - __le16 crc; - u8 padding[2]; - u8 md5[16]; -} __packed; - -/* provide 16 bytes for the transport back-end */ -#define P54_TX_INFO_DATA_SIZE 16 - -/* stored in ieee80211_tx_info's rate_driver_data */ -struct p54_tx_info { - u32 start_addr; - u32 end_addr; - union { - void *data[P54_TX_INFO_DATA_SIZE / sizeof(void *)]; - struct { - u32 extra_len; - }; - }; -}; - -#define P54_MAX_CTRL_FRAME_LEN 0x1000 - -#define P54_SET_QUEUE(queue, ai_fs, cw_min, cw_max, _txop) \ -do { \ - queue.aifs = cpu_to_le16(ai_fs); \ - queue.cwmin = cpu_to_le16(cw_min); \ - queue.cwmax = cpu_to_le16(cw_max); \ - queue.txop = cpu_to_le16(_txop); \ -} while (0) - -struct p54_edcf_queue_param { - __le16 aifs; - __le16 cwmin; - __le16 cwmax; - __le16 txop; -} __packed; - -struct p54_rssi_linear_approximation { - s16 mul; - s16 add; - s16 longbow_unkn; - s16 longbow_unk2; -}; - -struct p54_cal_database { - size_t entries; - size_t entry_size; - size_t offset; - size_t len; - u8 data[0]; -}; - -#define EEPROM_READBACK_LEN 0x3fc - -enum fw_state { - FW_STATE_OFF, - FW_STATE_BOOTING, - FW_STATE_READY, - FW_STATE_RESET, - FW_STATE_RESETTING, -}; - -#ifdef CONFIG_P54_LEDS - -#define P54_LED_MAX_NAME_LEN 31 - -struct p54_led_dev { - struct ieee80211_hw *hw_dev; - struct led_classdev led_dev; - char name[P54_LED_MAX_NAME_LEN + 1]; - - unsigned int toggled; - unsigned int index; - unsigned int registered; -}; - -#endif /* CONFIG_P54_LEDS */ - -struct p54_common { - struct ieee80211_hw *hw; - struct ieee80211_vif *vif; - void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb); - int (*open)(struct ieee80211_hw *dev); - void (*stop)(struct ieee80211_hw *dev); - struct sk_buff_head tx_pending; - struct sk_buff_head tx_queue; - struct mutex conf_mutex; - - /* memory management (as seen by the firmware) */ - u32 rx_start; - u32 rx_end; - u16 rx_mtu; - u8 headroom; - u8 tailroom; - - /* firmware/hardware info */ - unsigned int tx_hdr_len; - unsigned int fw_var; - unsigned int fw_interface; - u8 version; - - /* (e)DCF / QOS state */ - bool use_short_slot; - spinlock_t tx_stats_lock; - struct ieee80211_tx_queue_stats tx_stats[8]; - struct p54_edcf_queue_param qos_params[8]; - - /* Radio data */ - u16 rxhw; - u8 rx_diversity_mask; - u8 tx_diversity_mask; - unsigned int output_power; - int noise; - /* calibration, output power limit and rssi<->dBm conversation data */ - struct pda_iq_autocal_entry *iq_autocal; - unsigned int iq_autocal_len; - struct p54_cal_database *curve_data; - struct p54_cal_database *output_limit; - struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; - struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS]; - - /* BBP/MAC state */ - u8 mac_addr[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - u16 wakeup_timer; - unsigned int filter_flags; - int mode; - u32 tsf_low32, tsf_high32; - u32 basic_rate_mask; - u16 aid; - bool powersave_override; - __le32 beacon_req_id; - struct completion beacon_comp; - - /* cryptographic engine information */ - u8 privacy_caps; - u8 rx_keycache_size; - unsigned long *used_rxkeys; - - /* LED management */ -#ifdef CONFIG_P54_LEDS - struct p54_led_dev leds[4]; - struct delayed_work led_work; -#endif /* CONFIG_P54_LEDS */ - u16 softled_state; /* bit field of glowing LEDs */ - - /* statistics */ - struct ieee80211_low_level_stats stats; - struct delayed_work work; - - /* eeprom handling */ - void *eeprom; - struct completion eeprom_comp; - struct mutex eeprom_mutex; -}; - -/* interfaces for the drivers */ -int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb); -void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb); -int p54_parse_firmware(struct ieee80211_hw *dev, const struct firmware *fw); -int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len); -int p54_read_eeprom(struct ieee80211_hw *dev); - -struct ieee80211_hw *p54_init_common(size_t priv_data_len); -int p54_register_common(struct ieee80211_hw *dev, struct device *pdev); -void p54_free_common(struct ieee80211_hw *dev); - -void p54_unregister_common(struct ieee80211_hw *dev); - -#endif /* P54_H */ diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c deleted file mode 100644 index 3df13f590182..000000000000 --- a/drivers/net/wireless/p54/p54pci.c +++ /dev/null @@ -1,683 +0,0 @@ - -/* - * Linux device driver for PCI based Prism54 - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2008, Christian Lamparter - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "p54.h" -#include "lmac.h" -#include "p54pci.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_DESCRIPTION("Prism54 PCI wireless driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54pci"); -MODULE_FIRMWARE("isl3886pci"); - -static struct pci_device_id p54p_table[] __devinitdata = { - /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ - { PCI_DEVICE(0x1260, 0x3890) }, - /* 3COM 3CRWE154G72 Wireless LAN adapter */ - { PCI_DEVICE(0x10b7, 0x6001) }, - /* Intersil PRISM Indigo Wireless LAN adapter */ - { PCI_DEVICE(0x1260, 0x3877) }, - /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ - { PCI_DEVICE(0x1260, 0x3886) }, - /* Intersil PRISM Xbow Wireless LAN adapter (Symbol AP-300) */ - { PCI_DEVICE(0x1260, 0xffff) }, - { }, -}; - -MODULE_DEVICE_TABLE(pci, p54p_table); - -static int p54p_upload_firmware(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - __le32 reg; - int err; - __le32 *data; - u32 remains, left, device_addr; - - P54P_WRITE(int_enable, cpu_to_le32(0)); - P54P_READ(int_enable); - udelay(10); - - reg = P54P_READ(ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT); - P54P_WRITE(ctrl_stat, reg); - P54P_READ(ctrl_stat); - udelay(10); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - udelay(10); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - - /* wait for the firmware to reset properly */ - mdelay(10); - - err = p54_parse_firmware(dev, priv->firmware); - if (err) - return err; - - if (priv->common.fw_interface != FW_LM86) { - dev_err(&priv->pdev->dev, "wrong firmware, " - "please get a LM86(PCI) firmware a try again.\n"); - return -EINVAL; - } - - data = (__le32 *) priv->firmware->data; - remains = priv->firmware->size; - device_addr = ISL38XX_DEV_FIRMWARE_ADDR; - while (remains) { - u32 i = 0; - left = min((u32)0x1000, remains); - P54P_WRITE(direct_mem_base, cpu_to_le32(device_addr)); - P54P_READ(int_enable); - - device_addr += 0x1000; - while (i < left) { - P54P_WRITE(direct_mem_win[i], *data++); - i += sizeof(u32); - } - - remains -= left; - P54P_READ(int_enable); - } - - reg = P54P_READ(ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT); - P54P_WRITE(ctrl_stat, reg); - P54P_READ(ctrl_stat); - udelay(10); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - udelay(10); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54P_WRITE(ctrl_stat, reg); - wmb(); - udelay(10); - - /* wait for the firmware to boot properly */ - mdelay(100); - - return 0; -} - -static void p54p_refill_rx_ring(struct ieee80211_hw *dev, - int ring_index, struct p54p_desc *ring, u32 ring_limit, - struct sk_buff **rx_buf) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - u32 limit, idx, i; - - idx = le32_to_cpu(ring_control->host_idx[ring_index]); - limit = idx; - limit -= le32_to_cpu(ring_control->device_idx[ring_index]); - limit = ring_limit - limit; - - i = idx % ring_limit; - while (limit-- > 1) { - struct p54p_desc *desc = &ring[i]; - - if (!desc->host_addr) { - struct sk_buff *skb; - dma_addr_t mapping; - skb = dev_alloc_skb(priv->common.rx_mtu + 32); - if (!skb) - break; - - mapping = pci_map_single(priv->pdev, - skb_tail_pointer(skb), - priv->common.rx_mtu + 32, - PCI_DMA_FROMDEVICE); - - if (pci_dma_mapping_error(priv->pdev, mapping)) { - dev_kfree_skb_any(skb); - dev_err(&priv->pdev->dev, - "RX DMA Mapping error\n"); - break; - } - - desc->host_addr = cpu_to_le32(mapping); - desc->device_addr = 0; // FIXME: necessary? - desc->len = cpu_to_le16(priv->common.rx_mtu + 32); - desc->flags = 0; - rx_buf[i] = skb; - } - - i++; - idx++; - i %= ring_limit; - } - - wmb(); - ring_control->host_idx[ring_index] = cpu_to_le32(idx); -} - -static void p54p_check_rx_ring(struct ieee80211_hw *dev, u32 *index, - int ring_index, struct p54p_desc *ring, u32 ring_limit, - struct sk_buff **rx_buf) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - struct p54p_desc *desc; - u32 idx, i; - - i = (*index) % ring_limit; - (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]); - idx %= ring_limit; - while (i != idx) { - u16 len; - struct sk_buff *skb; - desc = &ring[i]; - len = le16_to_cpu(desc->len); - skb = rx_buf[i]; - - if (!skb) { - i++; - i %= ring_limit; - continue; - } - - if (unlikely(len > priv->common.rx_mtu)) { - if (net_ratelimit()) - dev_err(&priv->pdev->dev, "rx'd frame size " - "exceeds length threshold.\n"); - - len = priv->common.rx_mtu; - } - skb_put(skb, len); - - if (p54_rx(dev, skb)) { - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - priv->common.rx_mtu + 32, - PCI_DMA_FROMDEVICE); - rx_buf[i] = NULL; - desc->host_addr = 0; - } else { - skb_trim(skb, 0); - desc->len = cpu_to_le16(priv->common.rx_mtu + 32); - } - - i++; - i %= ring_limit; - } - - p54p_refill_rx_ring(dev, ring_index, ring, ring_limit, rx_buf); -} - -/* caller must hold priv->lock */ -static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, - int ring_index, struct p54p_desc *ring, u32 ring_limit, - void **tx_buf) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - struct p54p_desc *desc; - u32 idx, i; - - i = (*index) % ring_limit; - (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]); - idx %= ring_limit; - - while (i != idx) { - desc = &ring[i]; - if (tx_buf[i]) - if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) - p54_free_skb(dev, tx_buf[i]); - tx_buf[i] = NULL; - - pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), - le16_to_cpu(desc->len), PCI_DMA_TODEVICE); - - desc->host_addr = 0; - desc->device_addr = 0; - desc->len = 0; - desc->flags = 0; - - i++; - i %= ring_limit; - } -} - -static void p54p_rx_tasklet(unsigned long dev_id) -{ - struct ieee80211_hw *dev = (struct ieee80211_hw *)dev_id; - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - - p54p_check_rx_ring(dev, &priv->rx_idx_mgmt, 2, ring_control->rx_mgmt, - ARRAY_SIZE(ring_control->rx_mgmt), priv->rx_buf_mgmt); - - p54p_check_rx_ring(dev, &priv->rx_idx_data, 0, ring_control->rx_data, - ARRAY_SIZE(ring_control->rx_data), priv->rx_buf_data); - - wmb(); - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); -} - -static irqreturn_t p54p_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *dev = dev_id; - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - __le32 reg; - - spin_lock(&priv->lock); - reg = P54P_READ(int_ident); - if (unlikely(reg == cpu_to_le32(0xFFFFFFFF))) { - spin_unlock(&priv->lock); - return IRQ_HANDLED; - } - - P54P_WRITE(int_ack, reg); - - reg &= P54P_READ(int_enable); - - if (reg & cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)) { - p54p_check_tx_ring(dev, &priv->tx_idx_mgmt, - 3, ring_control->tx_mgmt, - ARRAY_SIZE(ring_control->tx_mgmt), - priv->tx_buf_mgmt); - - p54p_check_tx_ring(dev, &priv->tx_idx_data, - 1, ring_control->tx_data, - ARRAY_SIZE(ring_control->tx_data), - priv->tx_buf_data); - - tasklet_schedule(&priv->rx_tasklet); - - } else if (reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT)) - complete(&priv->boot_comp); - - spin_unlock(&priv->lock); - - return reg ? IRQ_HANDLED : IRQ_NONE; -} - -static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - unsigned long flags; - struct p54p_desc *desc; - dma_addr_t mapping; - u32 device_idx, idx, i; - - spin_lock_irqsave(&priv->lock, flags); - device_idx = le32_to_cpu(ring_control->device_idx[1]); - idx = le32_to_cpu(ring_control->host_idx[1]); - i = idx % ARRAY_SIZE(ring_control->tx_data); - - mapping = pci_map_single(priv->pdev, skb->data, skb->len, - PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(priv->pdev, mapping)) { - spin_unlock_irqrestore(&priv->lock, flags); - p54_free_skb(dev, skb); - dev_err(&priv->pdev->dev, "TX DMA mapping error\n"); - return ; - } - priv->tx_buf_data[i] = skb; - - desc = &ring_control->tx_data[i]; - desc->host_addr = cpu_to_le32(mapping); - desc->device_addr = ((struct p54_hdr *)skb->data)->req_id; - desc->len = cpu_to_le16(skb->len); - desc->flags = 0; - - wmb(); - ring_control->host_idx[1] = cpu_to_le32(idx + 1); - spin_unlock_irqrestore(&priv->lock, flags); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - P54P_READ(dev_int); -} - -static void p54p_stop(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - struct p54p_ring_control *ring_control = priv->ring_control; - unsigned int i; - struct p54p_desc *desc; - - tasklet_kill(&priv->rx_tasklet); - - P54P_WRITE(int_enable, cpu_to_le32(0)); - P54P_READ(int_enable); - udelay(10); - - free_irq(priv->pdev->irq, dev); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - - for (i = 0; i < ARRAY_SIZE(priv->rx_buf_data); i++) { - desc = &ring_control->rx_data[i]; - if (desc->host_addr) - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - priv->common.rx_mtu + 32, - PCI_DMA_FROMDEVICE); - kfree_skb(priv->rx_buf_data[i]); - priv->rx_buf_data[i] = NULL; - } - - for (i = 0; i < ARRAY_SIZE(priv->rx_buf_mgmt); i++) { - desc = &ring_control->rx_mgmt[i]; - if (desc->host_addr) - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - priv->common.rx_mtu + 32, - PCI_DMA_FROMDEVICE); - kfree_skb(priv->rx_buf_mgmt[i]); - priv->rx_buf_mgmt[i] = NULL; - } - - for (i = 0; i < ARRAY_SIZE(priv->tx_buf_data); i++) { - desc = &ring_control->tx_data[i]; - if (desc->host_addr) - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - le16_to_cpu(desc->len), - PCI_DMA_TODEVICE); - - p54_free_skb(dev, priv->tx_buf_data[i]); - priv->tx_buf_data[i] = NULL; - } - - for (i = 0; i < ARRAY_SIZE(priv->tx_buf_mgmt); i++) { - desc = &ring_control->tx_mgmt[i]; - if (desc->host_addr) - pci_unmap_single(priv->pdev, - le32_to_cpu(desc->host_addr), - le16_to_cpu(desc->len), - PCI_DMA_TODEVICE); - - p54_free_skb(dev, priv->tx_buf_mgmt[i]); - priv->tx_buf_mgmt[i] = NULL; - } - - memset(ring_control, 0, sizeof(*ring_control)); -} - -static int p54p_open(struct ieee80211_hw *dev) -{ - struct p54p_priv *priv = dev->priv; - int err; - - init_completion(&priv->boot_comp); - err = request_irq(priv->pdev->irq, &p54p_interrupt, - IRQF_SHARED, "p54pci", dev); - if (err) { - dev_err(&priv->pdev->dev, "failed to register IRQ handler\n"); - return err; - } - - memset(priv->ring_control, 0, sizeof(*priv->ring_control)); - err = p54p_upload_firmware(dev); - if (err) { - free_irq(priv->pdev->irq, dev); - return err; - } - priv->rx_idx_data = priv->tx_idx_data = 0; - priv->rx_idx_mgmt = priv->tx_idx_mgmt = 0; - - p54p_refill_rx_ring(dev, 0, priv->ring_control->rx_data, - ARRAY_SIZE(priv->ring_control->rx_data), priv->rx_buf_data); - - p54p_refill_rx_ring(dev, 2, priv->ring_control->rx_mgmt, - ARRAY_SIZE(priv->ring_control->rx_mgmt), priv->rx_buf_mgmt); - - P54P_WRITE(ring_control_base, cpu_to_le32(priv->ring_control_dma)); - P54P_READ(ring_control_base); - wmb(); - udelay(10); - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_INIT)); - P54P_READ(int_enable); - wmb(); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_RESET)); - P54P_READ(dev_int); - - if (!wait_for_completion_interruptible_timeout(&priv->boot_comp, HZ)) { - printk(KERN_ERR "%s: Cannot boot firmware!\n", - wiphy_name(dev->wiphy)); - p54p_stop(dev); - return -ETIMEDOUT; - } - - P54P_WRITE(int_enable, cpu_to_le32(ISL38XX_INT_IDENT_UPDATE)); - P54P_READ(int_enable); - wmb(); - udelay(10); - - P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); - P54P_READ(dev_int); - wmb(); - udelay(10); - - return 0; -} - -static int __devinit p54p_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct p54p_priv *priv; - struct ieee80211_hw *dev; - unsigned long mem_addr, mem_len; - int err; - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Cannot enable new PCI device\n"); - return err; - } - - mem_addr = pci_resource_start(pdev, 0); - mem_len = pci_resource_len(pdev, 0); - if (mem_len < sizeof(struct p54p_csr)) { - dev_err(&pdev->dev, "Too short PCI resources\n"); - goto err_disable_dev; - } - - err = pci_request_regions(pdev, "p54pci"); - if (err) { - dev_err(&pdev->dev, "Cannot obtain PCI resources\n"); - goto err_disable_dev; - } - - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) || - pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - dev_err(&pdev->dev, "No suitable DMA available\n"); - goto err_free_reg; - } - - pci_set_master(pdev); - pci_try_set_mwi(pdev); - - pci_write_config_byte(pdev, 0x40, 0); - pci_write_config_byte(pdev, 0x41, 0); - - dev = p54_init_common(sizeof(*priv)); - if (!dev) { - dev_err(&pdev->dev, "ieee80211 alloc failed\n"); - err = -ENOMEM; - goto err_free_reg; - } - - priv = dev->priv; - priv->pdev = pdev; - - SET_IEEE80211_DEV(dev, &pdev->dev); - pci_set_drvdata(pdev, dev); - - priv->map = ioremap(mem_addr, mem_len); - if (!priv->map) { - dev_err(&pdev->dev, "Cannot map device memory\n"); - err = -ENOMEM; - goto err_free_dev; - } - - priv->ring_control = pci_alloc_consistent(pdev, sizeof(*priv->ring_control), - &priv->ring_control_dma); - if (!priv->ring_control) { - dev_err(&pdev->dev, "Cannot allocate rings\n"); - err = -ENOMEM; - goto err_iounmap; - } - priv->common.open = p54p_open; - priv->common.stop = p54p_stop; - priv->common.tx = p54p_tx; - - spin_lock_init(&priv->lock); - tasklet_init(&priv->rx_tasklet, p54p_rx_tasklet, (unsigned long)dev); - - err = request_firmware(&priv->firmware, "isl3886pci", - &priv->pdev->dev); - if (err) { - dev_err(&pdev->dev, "Cannot find firmware (isl3886pci)\n"); - err = request_firmware(&priv->firmware, "isl3886", - &priv->pdev->dev); - if (err) - goto err_free_common; - } - - err = p54p_open(dev); - if (err) - goto err_free_common; - err = p54_read_eeprom(dev); - p54p_stop(dev); - if (err) - goto err_free_common; - - err = p54_register_common(dev, &pdev->dev); - if (err) - goto err_free_common; - - return 0; - - err_free_common: - release_firmware(priv->firmware); - pci_free_consistent(pdev, sizeof(*priv->ring_control), - priv->ring_control, priv->ring_control_dma); - - err_iounmap: - iounmap(priv->map); - - err_free_dev: - pci_set_drvdata(pdev, NULL); - p54_free_common(dev); - - err_free_reg: - pci_release_regions(pdev); - err_disable_dev: - pci_disable_device(pdev); - return err; -} - -static void __devexit p54p_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv; - - if (!dev) - return; - - p54_unregister_common(dev); - priv = dev->priv; - release_firmware(priv->firmware); - pci_free_consistent(pdev, sizeof(*priv->ring_control), - priv->ring_control, priv->ring_control_dma); - iounmap(priv->map); - pci_release_regions(pdev); - pci_disable_device(pdev); - p54_free_common(dev); -} - -#ifdef CONFIG_PM -static int p54p_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv = dev->priv; - - if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) { - ieee80211_stop_queues(dev); - p54p_stop(dev); - } - - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int p54p_resume(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct p54p_priv *priv = dev->priv; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) { - p54p_open(dev); - ieee80211_wake_queues(dev); - } - - return 0; -} -#endif /* CONFIG_PM */ - -static struct pci_driver p54p_driver = { - .name = "p54pci", - .id_table = p54p_table, - .probe = p54p_probe, - .remove = __devexit_p(p54p_remove), -#ifdef CONFIG_PM - .suspend = p54p_suspend, - .resume = p54p_resume, -#endif /* CONFIG_PM */ -}; - -static int __init p54p_init(void) -{ - return pci_register_driver(&p54p_driver); -} - -static void __exit p54p_exit(void) -{ - pci_unregister_driver(&p54p_driver); -} - -module_init(p54p_init); -module_exit(p54p_exit); diff --git a/drivers/net/wireless/p54/p54pci.h b/drivers/net/wireless/p54/p54pci.h deleted file mode 100644 index fbb683953fb2..000000000000 --- a/drivers/net/wireless/p54/p54pci.h +++ /dev/null @@ -1,110 +0,0 @@ -#ifndef P54PCI_H -#define P54PCI_H - -/* - * Defines for PCI based mac80211 Prism54 driver - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* Device Interrupt register bits */ -#define ISL38XX_DEV_INT_RESET 0x0001 -#define ISL38XX_DEV_INT_UPDATE 0x0002 -#define ISL38XX_DEV_INT_WAKEUP 0x0008 -#define ISL38XX_DEV_INT_SLEEP 0x0010 -#define ISL38XX_DEV_INT_ABORT 0x0020 -/* these two only used in USB */ -#define ISL38XX_DEV_INT_DATA 0x0040 -#define ISL38XX_DEV_INT_MGMT 0x0080 - -#define ISL38XX_DEV_INT_PCIUART_CTS 0x4000 -#define ISL38XX_DEV_INT_PCIUART_DR 0x8000 - -/* Interrupt Identification/Acknowledge/Enable register bits */ -#define ISL38XX_INT_IDENT_UPDATE 0x0002 -#define ISL38XX_INT_IDENT_INIT 0x0004 -#define ISL38XX_INT_IDENT_WAKEUP 0x0008 -#define ISL38XX_INT_IDENT_SLEEP 0x0010 -#define ISL38XX_INT_IDENT_PCIUART_CTS 0x4000 -#define ISL38XX_INT_IDENT_PCIUART_DR 0x8000 - -/* Control/Status register bits */ -#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 -#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 -#define ISL38XX_CTRL_STAT_RESET 0x10000000 -#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000 -#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000 -#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000 - -struct p54p_csr { - __le32 dev_int; - u8 unused_1[12]; - __le32 int_ident; - __le32 int_ack; - __le32 int_enable; - u8 unused_2[4]; - union { - __le32 ring_control_base; - __le32 gen_purp_com[2]; - }; - u8 unused_3[8]; - __le32 direct_mem_base; - u8 unused_4[44]; - __le32 dma_addr; - __le32 dma_len; - __le32 dma_ctrl; - u8 unused_5[12]; - __le32 ctrl_stat; - u8 unused_6[1924]; - u8 cardbus_cis[0x800]; - u8 direct_mem_win[0x1000]; -} __attribute__ ((packed)); - -/* usb backend only needs the register defines above */ -#ifndef P54USB_H -struct p54p_desc { - __le32 host_addr; - __le32 device_addr; - __le16 len; - __le16 flags; -} __attribute__ ((packed)); - -struct p54p_ring_control { - __le32 host_idx[4]; - __le32 device_idx[4]; - struct p54p_desc rx_data[8]; - struct p54p_desc tx_data[32]; - struct p54p_desc rx_mgmt[4]; - struct p54p_desc tx_mgmt[4]; -} __attribute__ ((packed)); - -#define P54P_READ(r) (__force __le32)__raw_readl(&priv->map->r) -#define P54P_WRITE(r, val) __raw_writel((__force u32)(__le32)(val), &priv->map->r) - -struct p54p_priv { - struct p54_common common; - struct pci_dev *pdev; - struct p54p_csr __iomem *map; - struct tasklet_struct rx_tasklet; - const struct firmware *firmware; - spinlock_t lock; - struct p54p_ring_control *ring_control; - dma_addr_t ring_control_dma; - u32 rx_idx_data, tx_idx_data; - u32 rx_idx_mgmt, tx_idx_mgmt; - struct sk_buff *rx_buf_data[8]; - struct sk_buff *rx_buf_mgmt[4]; - void *tx_buf_data[32]; - void *tx_buf_mgmt[4]; - struct completion boot_comp; -}; - -#endif /* P54USB_H */ -#endif /* P54PCI_H */ diff --git a/drivers/net/wireless/p54/p54spi.c b/drivers/net/wireless/p54/p54spi.c deleted file mode 100644 index afd26bf06649..000000000000 --- a/drivers/net/wireless/p54/p54spi.c +++ /dev/null @@ -1,734 +0,0 @@ -/* - * Copyright (C) 2008 Christian Lamparter - * Copyright 2008 Johannes Berg - * - * This driver is a port from stlc45xx: - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "p54spi.h" -#include "p54spi_eeprom.h" -#include "p54.h" - -#include "lmac.h" - -MODULE_FIRMWARE("3826.arm"); -MODULE_ALIAS("stlc45xx"); - -/* - * gpios should be handled in board files and provided via platform data, - * but because it's currently impossible for p54spi to have a header file - * in include/linux, let's use module paramaters for now - */ - -static int p54spi_gpio_power = 97; -module_param(p54spi_gpio_power, int, 0444); -MODULE_PARM_DESC(p54spi_gpio_power, "gpio number for power line"); - -static int p54spi_gpio_irq = 87; -module_param(p54spi_gpio_irq, int, 0444); -MODULE_PARM_DESC(p54spi_gpio_irq, "gpio number for irq line"); - -static void p54spi_spi_read(struct p54s_priv *priv, u8 address, - void *buf, size_t len) -{ - struct spi_transfer t[2]; - struct spi_message m; - __le16 addr; - - /* We first push the address */ - addr = cpu_to_le16(address << 8 | SPI_ADRS_READ_BIT_15); - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = &addr; - t[0].len = sizeof(addr); - spi_message_add_tail(&t[0], &m); - - t[1].rx_buf = buf; - t[1].len = len; - spi_message_add_tail(&t[1], &m); - - spi_sync(priv->spi, &m); -} - - -static void p54spi_spi_write(struct p54s_priv *priv, u8 address, - const void *buf, size_t len) -{ - struct spi_transfer t[3]; - struct spi_message m; - __le16 addr; - - /* We first push the address */ - addr = cpu_to_le16(address << 8); - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = &addr; - t[0].len = sizeof(addr); - spi_message_add_tail(&t[0], &m); - - t[1].tx_buf = buf; - t[1].len = len & ~1; - spi_message_add_tail(&t[1], &m); - - if (len % 2) { - __le16 last_word; - last_word = cpu_to_le16(((u8 *)buf)[len - 1]); - - t[2].tx_buf = &last_word; - t[2].len = sizeof(last_word); - spi_message_add_tail(&t[2], &m); - } - - spi_sync(priv->spi, &m); -} - -static u32 p54spi_read32(struct p54s_priv *priv, u8 addr) -{ - __le32 val; - - p54spi_spi_read(priv, addr, &val, sizeof(val)); - - return le32_to_cpu(val); -} - -static inline void p54spi_write16(struct p54s_priv *priv, u8 addr, __le16 val) -{ - p54spi_spi_write(priv, addr, &val, sizeof(val)); -} - -static inline void p54spi_write32(struct p54s_priv *priv, u8 addr, __le32 val) -{ - p54spi_spi_write(priv, addr, &val, sizeof(val)); -} - -static int p54spi_wait_bit(struct p54s_priv *priv, u16 reg, u32 bits) -{ - int i; - - for (i = 0; i < 2000; i++) { - u32 buffer = p54spi_read32(priv, reg); - if ((buffer & bits) == bits) - return 1; - } - return 0; -} - -static int p54spi_spi_write_dma(struct p54s_priv *priv, __le32 base, - const void *buf, size_t len) -{ - if (!p54spi_wait_bit(priv, SPI_ADRS_DMA_WRITE_CTRL, HOST_ALLOWED)) { - dev_err(&priv->spi->dev, "spi_write_dma not allowed " - "to DMA write.\n"); - return -EAGAIN; - } - - p54spi_write16(priv, SPI_ADRS_DMA_WRITE_CTRL, - cpu_to_le16(SPI_DMA_WRITE_CTRL_ENABLE)); - - p54spi_write16(priv, SPI_ADRS_DMA_WRITE_LEN, cpu_to_le16(len)); - p54spi_write32(priv, SPI_ADRS_DMA_WRITE_BASE, base); - p54spi_spi_write(priv, SPI_ADRS_DMA_DATA, buf, len); - return 0; -} - -static int p54spi_request_firmware(struct ieee80211_hw *dev) -{ - struct p54s_priv *priv = dev->priv; - int ret; - - /* FIXME: should driver use it's own struct device? */ - ret = request_firmware(&priv->firmware, "3826.arm", &priv->spi->dev); - - if (ret < 0) { - dev_err(&priv->spi->dev, "request_firmware() failed: %d", ret); - return ret; - } - - ret = p54_parse_firmware(dev, priv->firmware); - if (ret) { - release_firmware(priv->firmware); - return ret; - } - - return 0; -} - -static int p54spi_request_eeprom(struct ieee80211_hw *dev) -{ - struct p54s_priv *priv = dev->priv; - const struct firmware *eeprom; - int ret; - - /* - * allow users to customize their eeprom. - */ - - ret = request_firmware(&eeprom, "3826.eeprom", &priv->spi->dev); - if (ret < 0) { - dev_info(&priv->spi->dev, "loading default eeprom...\n"); - ret = p54_parse_eeprom(dev, (void *) p54spi_eeprom, - sizeof(p54spi_eeprom)); - } else { - dev_info(&priv->spi->dev, "loading user eeprom...\n"); - ret = p54_parse_eeprom(dev, (void *) eeprom->data, - (int)eeprom->size); - release_firmware(eeprom); - } - return ret; -} - -static int p54spi_upload_firmware(struct ieee80211_hw *dev) -{ - struct p54s_priv *priv = dev->priv; - unsigned long fw_len, _fw_len; - unsigned int offset = 0; - int err = 0; - u8 *fw; - - fw_len = priv->firmware->size; - fw = kmemdup(priv->firmware->data, fw_len, GFP_KERNEL); - if (!fw) - return -ENOMEM; - - /* stop the device */ - p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( - SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET | - SPI_CTRL_STAT_START_HALTED)); - - msleep(TARGET_BOOT_SLEEP); - - p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( - SPI_CTRL_STAT_HOST_OVERRIDE | - SPI_CTRL_STAT_START_HALTED)); - - msleep(TARGET_BOOT_SLEEP); - - while (fw_len > 0) { - _fw_len = min_t(long, fw_len, SPI_MAX_PACKET_SIZE); - - err = p54spi_spi_write_dma(priv, cpu_to_le32( - ISL38XX_DEV_FIRMWARE_ADDR + offset), - (fw + offset), _fw_len); - if (err < 0) - goto out; - - fw_len -= _fw_len; - offset += _fw_len; - } - - BUG_ON(fw_len != 0); - - /* enable host interrupts */ - p54spi_write32(priv, SPI_ADRS_HOST_INT_EN, - cpu_to_le32(SPI_HOST_INTS_DEFAULT)); - - /* boot the device */ - p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( - SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_HOST_RESET | - SPI_CTRL_STAT_RAM_BOOT)); - - msleep(TARGET_BOOT_SLEEP); - - p54spi_write16(priv, SPI_ADRS_DEV_CTRL_STAT, cpu_to_le16( - SPI_CTRL_STAT_HOST_OVERRIDE | SPI_CTRL_STAT_RAM_BOOT)); - msleep(TARGET_BOOT_SLEEP); - -out: - kfree(fw); - return err; -} - -static void p54spi_power_off(struct p54s_priv *priv) -{ - disable_irq(gpio_to_irq(p54spi_gpio_irq)); - gpio_set_value(p54spi_gpio_power, 0); -} - -static void p54spi_power_on(struct p54s_priv *priv) -{ - gpio_set_value(p54spi_gpio_power, 1); - enable_irq(gpio_to_irq(p54spi_gpio_irq)); - - /* - * need to wait a while before device can be accessed, the lenght - * is just a guess - */ - msleep(10); -} - -static inline void p54spi_int_ack(struct p54s_priv *priv, u32 val) -{ - p54spi_write32(priv, SPI_ADRS_HOST_INT_ACK, cpu_to_le32(val)); -} - -static int p54spi_wakeup(struct p54s_priv *priv) -{ - /* wake the chip */ - p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, - cpu_to_le32(SPI_TARGET_INT_WAKEUP)); - - /* And wait for the READY interrupt */ - if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, - SPI_HOST_INT_READY)) { - dev_err(&priv->spi->dev, "INT_READY timeout\n"); - return -EBUSY; - } - - p54spi_int_ack(priv, SPI_HOST_INT_READY); - return 0; -} - -static inline void p54spi_sleep(struct p54s_priv *priv) -{ - p54spi_write32(priv, SPI_ADRS_ARM_INTERRUPTS, - cpu_to_le32(SPI_TARGET_INT_SLEEP)); -} - -static void p54spi_int_ready(struct p54s_priv *priv) -{ - p54spi_write32(priv, SPI_ADRS_HOST_INT_EN, cpu_to_le32( - SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE)); - - switch (priv->fw_state) { - case FW_STATE_BOOTING: - priv->fw_state = FW_STATE_READY; - complete(&priv->fw_comp); - break; - case FW_STATE_RESETTING: - priv->fw_state = FW_STATE_READY; - /* TODO: reinitialize state */ - break; - default: - break; - } -} - -static int p54spi_rx(struct p54s_priv *priv) -{ - struct sk_buff *skb; - u16 len; - u16 rx_head[2]; -#define READAHEAD_SZ (sizeof(rx_head)-sizeof(u16)) - - if (p54spi_wakeup(priv) < 0) - return -EBUSY; - - /* Read data size and first data word in one SPI transaction - * This is workaround for firmware/DMA bug, - * when first data word gets lost under high load. - */ - p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, rx_head, sizeof(rx_head)); - len = rx_head[0]; - - if (len == 0) { - p54spi_sleep(priv); - dev_err(&priv->spi->dev, "rx request of zero bytes\n"); - return 0; - } - - /* Firmware may insert up to 4 padding bytes after the lmac header, - * but it does not amend the size of SPI data transfer. - * Such packets has correct data size in header, thus referencing - * past the end of allocated skb. Reserve extra 4 bytes for this case */ - skb = dev_alloc_skb(len + 4); - if (!skb) { - p54spi_sleep(priv); - dev_err(&priv->spi->dev, "could not alloc skb"); - return -ENOMEM; - } - - if (len <= READAHEAD_SZ) { - memcpy(skb_put(skb, len), rx_head + 1, len); - } else { - memcpy(skb_put(skb, READAHEAD_SZ), rx_head + 1, READAHEAD_SZ); - p54spi_spi_read(priv, SPI_ADRS_DMA_DATA, - skb_put(skb, len - READAHEAD_SZ), - len - READAHEAD_SZ); - } - p54spi_sleep(priv); - /* Put additional bytes to compensate for the possible - * alignment-caused truncation */ - skb_put(skb, 4); - - if (p54_rx(priv->hw, skb) == 0) - dev_kfree_skb(skb); - - return 0; -} - - -static irqreturn_t p54spi_interrupt(int irq, void *config) -{ - struct spi_device *spi = config; - struct p54s_priv *priv = dev_get_drvdata(&spi->dev); - - ieee80211_queue_work(priv->hw, &priv->work); - - return IRQ_HANDLED; -} - -static int p54spi_tx_frame(struct p54s_priv *priv, struct sk_buff *skb) -{ - struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - int ret = 0; - - if (p54spi_wakeup(priv) < 0) - return -EBUSY; - - ret = p54spi_spi_write_dma(priv, hdr->req_id, skb->data, skb->len); - if (ret < 0) - goto out; - - if (!p54spi_wait_bit(priv, SPI_ADRS_HOST_INTERRUPTS, - SPI_HOST_INT_WR_READY)) { - dev_err(&priv->spi->dev, "WR_READY timeout\n"); - ret = -EAGAIN; - goto out; - } - - p54spi_int_ack(priv, SPI_HOST_INT_WR_READY); - - if (FREE_AFTER_TX(skb)) - p54_free_skb(priv->hw, skb); -out: - p54spi_sleep(priv); - return ret; -} - -static int p54spi_wq_tx(struct p54s_priv *priv) -{ - struct p54s_tx_info *entry; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - struct p54_tx_info *minfo; - struct p54s_tx_info *dinfo; - unsigned long flags; - int ret = 0; - - spin_lock_irqsave(&priv->tx_lock, flags); - - while (!list_empty(&priv->tx_pending)) { - entry = list_entry(priv->tx_pending.next, - struct p54s_tx_info, tx_list); - - list_del_init(&entry->tx_list); - - spin_unlock_irqrestore(&priv->tx_lock, flags); - - dinfo = container_of((void *) entry, struct p54s_tx_info, - tx_list); - minfo = container_of((void *) dinfo, struct p54_tx_info, - data); - info = container_of((void *) minfo, struct ieee80211_tx_info, - rate_driver_data); - skb = container_of((void *) info, struct sk_buff, cb); - - ret = p54spi_tx_frame(priv, skb); - - if (ret < 0) { - p54_free_skb(priv->hw, skb); - return ret; - } - - spin_lock_irqsave(&priv->tx_lock, flags); - } - spin_unlock_irqrestore(&priv->tx_lock, flags); - return ret; -} - -static void p54spi_op_tx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54s_priv *priv = dev->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct p54_tx_info *mi = (struct p54_tx_info *) info->rate_driver_data; - struct p54s_tx_info *di = (struct p54s_tx_info *) mi->data; - unsigned long flags; - - BUILD_BUG_ON(sizeof(*di) > sizeof((mi->data))); - - spin_lock_irqsave(&priv->tx_lock, flags); - list_add_tail(&di->tx_list, &priv->tx_pending); - spin_unlock_irqrestore(&priv->tx_lock, flags); - - ieee80211_queue_work(priv->hw, &priv->work); -} - -static void p54spi_work(struct work_struct *work) -{ - struct p54s_priv *priv = container_of(work, struct p54s_priv, work); - u32 ints; - int ret; - - mutex_lock(&priv->mutex); - - if (priv->fw_state == FW_STATE_OFF) - goto out; - - ints = p54spi_read32(priv, SPI_ADRS_HOST_INTERRUPTS); - - if (ints & SPI_HOST_INT_READY) { - p54spi_int_ready(priv); - p54spi_int_ack(priv, SPI_HOST_INT_READY); - } - - if (priv->fw_state != FW_STATE_READY) - goto out; - - if (ints & SPI_HOST_INT_UPDATE) { - p54spi_int_ack(priv, SPI_HOST_INT_UPDATE); - ret = p54spi_rx(priv); - if (ret < 0) - goto out; - } - if (ints & SPI_HOST_INT_SW_UPDATE) { - p54spi_int_ack(priv, SPI_HOST_INT_SW_UPDATE); - ret = p54spi_rx(priv); - if (ret < 0) - goto out; - } - - ret = p54spi_wq_tx(priv); -out: - mutex_unlock(&priv->mutex); -} - -static int p54spi_op_start(struct ieee80211_hw *dev) -{ - struct p54s_priv *priv = dev->priv; - unsigned long timeout; - int ret = 0; - - if (mutex_lock_interruptible(&priv->mutex)) { - ret = -EINTR; - goto out; - } - - priv->fw_state = FW_STATE_BOOTING; - - p54spi_power_on(priv); - - ret = p54spi_upload_firmware(dev); - if (ret < 0) { - p54spi_power_off(priv); - goto out_unlock; - } - - mutex_unlock(&priv->mutex); - - timeout = msecs_to_jiffies(2000); - timeout = wait_for_completion_interruptible_timeout(&priv->fw_comp, - timeout); - if (!timeout) { - dev_err(&priv->spi->dev, "firmware boot failed"); - p54spi_power_off(priv); - ret = -1; - goto out; - } - - if (mutex_lock_interruptible(&priv->mutex)) { - ret = -EINTR; - p54spi_power_off(priv); - goto out; - } - - WARN_ON(priv->fw_state != FW_STATE_READY); - -out_unlock: - mutex_unlock(&priv->mutex); - -out: - return ret; -} - -static void p54spi_op_stop(struct ieee80211_hw *dev) -{ - struct p54s_priv *priv = dev->priv; - unsigned long flags; - - if (mutex_lock_interruptible(&priv->mutex)) { - /* FIXME: how to handle this error? */ - return; - } - - WARN_ON(priv->fw_state != FW_STATE_READY); - - cancel_work_sync(&priv->work); - - p54spi_power_off(priv); - spin_lock_irqsave(&priv->tx_lock, flags); - INIT_LIST_HEAD(&priv->tx_pending); - spin_unlock_irqrestore(&priv->tx_lock, flags); - - priv->fw_state = FW_STATE_OFF; - mutex_unlock(&priv->mutex); -} - -static int __devinit p54spi_probe(struct spi_device *spi) -{ - struct p54s_priv *priv = NULL; - struct ieee80211_hw *hw; - int ret = -EINVAL; - - hw = p54_init_common(sizeof(*priv)); - if (!hw) { - dev_err(&spi->dev, "could not alloc ieee80211_hw"); - return -ENOMEM; - } - - priv = hw->priv; - priv->hw = hw; - dev_set_drvdata(&spi->dev, priv); - priv->spi = spi; - - spi->bits_per_word = 16; - spi->max_speed_hz = 24000000; - - ret = spi_setup(spi); - if (ret < 0) { - dev_err(&priv->spi->dev, "spi_setup failed"); - goto err_free_common; - } - - ret = gpio_request(p54spi_gpio_power, "p54spi power"); - if (ret < 0) { - dev_err(&priv->spi->dev, "power GPIO request failed: %d", ret); - goto err_free_common; - } - - ret = gpio_request(p54spi_gpio_irq, "p54spi irq"); - if (ret < 0) { - dev_err(&priv->spi->dev, "irq GPIO request failed: %d", ret); - goto err_free_common; - } - - gpio_direction_output(p54spi_gpio_power, 0); - gpio_direction_input(p54spi_gpio_irq); - - ret = request_irq(gpio_to_irq(p54spi_gpio_irq), - p54spi_interrupt, IRQF_DISABLED, "p54spi", - priv->spi); - if (ret < 0) { - dev_err(&priv->spi->dev, "request_irq() failed"); - goto err_free_common; - } - - set_irq_type(gpio_to_irq(p54spi_gpio_irq), - IRQ_TYPE_EDGE_RISING); - - disable_irq(gpio_to_irq(p54spi_gpio_irq)); - - INIT_WORK(&priv->work, p54spi_work); - init_completion(&priv->fw_comp); - INIT_LIST_HEAD(&priv->tx_pending); - mutex_init(&priv->mutex); - SET_IEEE80211_DEV(hw, &spi->dev); - priv->common.open = p54spi_op_start; - priv->common.stop = p54spi_op_stop; - priv->common.tx = p54spi_op_tx; - - ret = p54spi_request_firmware(hw); - if (ret < 0) - goto err_free_common; - - ret = p54spi_request_eeprom(hw); - if (ret) - goto err_free_common; - - ret = p54_register_common(hw, &priv->spi->dev); - if (ret) - goto err_free_common; - - return 0; - -err_free_common: - p54_free_common(priv->hw); - return ret; -} - -static int __devexit p54spi_remove(struct spi_device *spi) -{ - struct p54s_priv *priv = dev_get_drvdata(&spi->dev); - - p54_unregister_common(priv->hw); - - free_irq(gpio_to_irq(p54spi_gpio_irq), spi); - - gpio_free(p54spi_gpio_power); - gpio_free(p54spi_gpio_irq); - release_firmware(priv->firmware); - - mutex_destroy(&priv->mutex); - - p54_free_common(priv->hw); - - return 0; -} - - -static struct spi_driver p54spi_driver = { - .driver = { - /* use cx3110x name because board-n800.c uses that for the - * SPI port */ - .name = "cx3110x", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = p54spi_probe, - .remove = __devexit_p(p54spi_remove), -}; - -static int __init p54spi_init(void) -{ - int ret; - - ret = spi_register_driver(&p54spi_driver); - if (ret < 0) { - printk(KERN_ERR "failed to register SPI driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit p54spi_exit(void) -{ - spi_unregister_driver(&p54spi_driver); -} - -module_init(p54spi_init); -module_exit(p54spi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Christian Lamparter "); -MODULE_ALIAS("spi:cx3110x"); diff --git a/drivers/net/wireless/p54/p54spi.h b/drivers/net/wireless/p54/p54spi.h deleted file mode 100644 index 7fbe8d8fc67c..000000000000 --- a/drivers/net/wireless/p54/p54spi.h +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2008 Christian Lamparter - * - * This driver is a port from stlc45xx: - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef P54SPI_H -#define P54SPI_H - -#include -#include -#include - -#include "p54.h" - -/* Bit 15 is read/write bit; ON = READ, OFF = WRITE */ -#define SPI_ADRS_READ_BIT_15 0x8000 - -#define SPI_ADRS_ARM_INTERRUPTS 0x00 -#define SPI_ADRS_ARM_INT_EN 0x04 - -#define SPI_ADRS_HOST_INTERRUPTS 0x08 -#define SPI_ADRS_HOST_INT_EN 0x0c -#define SPI_ADRS_HOST_INT_ACK 0x10 - -#define SPI_ADRS_GEN_PURP_1 0x14 -#define SPI_ADRS_GEN_PURP_2 0x18 - -#define SPI_ADRS_DEV_CTRL_STAT 0x26 /* high word */ - -#define SPI_ADRS_DMA_DATA 0x28 - -#define SPI_ADRS_DMA_WRITE_CTRL 0x2c -#define SPI_ADRS_DMA_WRITE_LEN 0x2e -#define SPI_ADRS_DMA_WRITE_BASE 0x30 - -#define SPI_ADRS_DMA_READ_CTRL 0x34 -#define SPI_ADRS_DMA_READ_LEN 0x36 -#define SPI_ADRS_DMA_READ_BASE 0x38 - -#define SPI_CTRL_STAT_HOST_OVERRIDE 0x8000 -#define SPI_CTRL_STAT_START_HALTED 0x4000 -#define SPI_CTRL_STAT_RAM_BOOT 0x2000 -#define SPI_CTRL_STAT_HOST_RESET 0x1000 -#define SPI_CTRL_STAT_HOST_CPU_EN 0x0800 - -#define SPI_DMA_WRITE_CTRL_ENABLE 0x0001 -#define SPI_DMA_READ_CTRL_ENABLE 0x0001 -#define HOST_ALLOWED (1 << 7) - -#define SPI_TIMEOUT 100 /* msec */ - -#define SPI_MAX_TX_PACKETS 32 - -#define SPI_MAX_PACKET_SIZE 32767 - -#define SPI_TARGET_INT_WAKEUP 0x00000001 -#define SPI_TARGET_INT_SLEEP 0x00000002 -#define SPI_TARGET_INT_RDDONE 0x00000004 - -#define SPI_TARGET_INT_CTS 0x00004000 -#define SPI_TARGET_INT_DR 0x00008000 - -#define SPI_HOST_INT_READY 0x00000001 -#define SPI_HOST_INT_WR_READY 0x00000002 -#define SPI_HOST_INT_SW_UPDATE 0x00000004 -#define SPI_HOST_INT_UPDATE 0x10000000 - -/* clear to send */ -#define SPI_HOST_INT_CR 0x00004000 - -/* data ready */ -#define SPI_HOST_INT_DR 0x00008000 - -#define SPI_HOST_INTS_DEFAULT \ - (SPI_HOST_INT_READY | SPI_HOST_INT_UPDATE | SPI_HOST_INT_SW_UPDATE) - -#define TARGET_BOOT_SLEEP 50 - -struct p54s_dma_regs { - __le16 cmd; - __le16 len; - __le32 addr; -} __attribute__ ((packed)); - -struct p54s_tx_info { - struct list_head tx_list; -}; - -struct p54s_priv { - /* p54_common has to be the first entry */ - struct p54_common common; - struct ieee80211_hw *hw; - struct spi_device *spi; - - struct work_struct work; - - struct mutex mutex; - struct completion fw_comp; - - spinlock_t tx_lock; - - /* protected by tx_lock */ - struct list_head tx_pending; - - enum fw_state fw_state; - const struct firmware *firmware; -}; - -#endif /* P54SPI_H */ diff --git a/drivers/net/wireless/p54/p54spi_eeprom.h b/drivers/net/wireless/p54/p54spi_eeprom.h deleted file mode 100644 index 1ea1050911d9..000000000000 --- a/drivers/net/wireless/p54/p54spi_eeprom.h +++ /dev/null @@ -1,678 +0,0 @@ -/* - * Copyright (C) 2003 Conexant Americas Inc. All Rights Reserved. - * Copyright (C) 2004, 2005, 2006 Nokia Corporation - * Copyright 2008 Johannes Berg - * Copyright 2008 Christian Lamparter - * - * based on: - * - cx3110x's pda.h from Nokia - * - cx3110-transfer.log by Johannes Berg - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef P54SPI_EEPROM_H -#define P54SPI_EEPROM_H - -static unsigned char p54spi_eeprom[] = { - -/* struct eeprom_pda_wrap */ -0x47, 0x4d, 0x55, 0xaa, /* magic */ -0x00, 0x00, /* pad */ -0x00, 0x00, /* eeprom_pda_data_wrap length */ -0x00, 0x00, 0x00, 0x00, /* arm opcode */ - -/* bogus MAC address */ -0x04, 0x00, 0x01, 0x01, /* PDR_MAC_ADDRESS */ - 0x00, 0x02, 0xee, 0xc0, 0xff, 0xee, - -/* struct bootrec_exp_if */ -0x06, 0x00, 0x01, 0x10, /* PDR_INTERFACE_LIST */ - 0x00, 0x00, /* role */ - 0x0f, 0x00, /* if_id */ - 0x85, 0x00, /* variant = Longbow RF, 2GHz */ - 0x01, 0x00, /* btm_compat */ - 0x1f, 0x00, /* top_compat */ - -0x03, 0x00, 0x02, 0x10, /* PDR_HARDWARE_PLATFORM_COMPONENT_ID */ - 0x03, 0x20, 0x00, 0x43, - -/* struct pda_country[6] */ -0x0d, 0x00, 0x07, 0x10, /* PDR_COUNTRY_LIST */ - 0x10, 0x00, 0x00, 0x00, - 0x20, 0x00, 0x00, 0x00, - 0x30, 0x00, 0x00, 0x00, - 0x31, 0x00, 0x00, 0x00, - 0x32, 0x00, 0x00, 0x00, - 0x40, 0x00, 0x00, 0x00, - -/* struct pda_country */ -0x03, 0x00, 0x08, 0x10, /* PDR_DEFAULT_COUNTRY */ - 0x30, 0x00, 0x00, 0x00, /* ETSI */ - -0x03, 0x00, 0x00, 0x11, /* PDR_ANTENNA_GAIN */ - 0x08, 0x08, 0x08, 0x08, - -0x09, 0x00, 0xad, 0xde, /* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */ - 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - -/* struct pda_custom_wrapper */ -0x10, 0x06, 0x5d, 0xb0, /* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */ - 0x0d, 0x00, 0xee, 0x00, /* 13 entries, 238 bytes per entry */ - 0x00, 0x00, 0x16, 0x0c, /* no offset, 3094 total len */ - /* 2412 MHz */ - 0x6c, 0x09, - 0x10, 0x01, 0x9a, 0x84, - 0xaa, 0x8a, 0xaa, 0x8a, 0xaa, 0x8a, 0xaa, 0x8a, - 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, - 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, 0x3c, 0xb6, - 0xf0, 0x00, 0x94, 0x6c, - 0x99, 0x82, 0x99, 0x82, 0x99, 0x82, 0x99, 0x82, - 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, - 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, 0x2b, 0xae, - 0xd0, 0x00, 0xaa, 0x5a, - 0x88, 0x7a, 0x88, 0x7a, 0x88, 0x7a, 0x88, 0x7a, - 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, - 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, 0x1a, 0xa6, - 0xa0, 0x00, 0xf3, 0x47, - 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, 0x6e, - 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, - 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, 0x00, 0x9a, - 0x50, 0x00, 0x59, 0x36, - 0x43, 0x5a, 0x43, 0x5a, 0x43, 0x5a, 0x43, 0x5a, - 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, - 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, 0xd5, 0x85, - 0x00, 0x00, 0xe4, 0x2d, - 0x18, 0x46, 0x18, 0x46, 0x18, 0x46, 0x18, 0x46, - 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, - 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, 0xaa, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2417 MHz */ - 0x71, 0x09, - 0x10, 0x01, 0xb9, 0x83, - 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, - 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, - 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, - 0xf0, 0x00, 0x2e, 0x6c, - 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, - 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, - 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, - 0xd0, 0x00, 0x8d, 0x5a, - 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, - 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, - 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, - 0xa0, 0x00, 0x0a, 0x48, - 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, - 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, - 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, - 0x50, 0x00, 0x7c, 0x36, - 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, - 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, - 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, - 0x00, 0x00, 0xf5, 0x2d, - 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, - 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, - 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2422 MHz */ - 0x76, 0x09, - 0x10, 0x01, 0xb9, 0x83, - 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, 0x7d, 0x8a, - 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, - 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, 0x0f, 0xb6, - 0xf0, 0x00, 0x2e, 0x6c, - 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, 0x68, 0x82, - 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, - 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, 0xfa, 0xad, - 0xd0, 0x00, 0x8d, 0x5a, - 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, 0x52, 0x7a, - 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, - 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, 0xe4, 0xa5, - 0xa0, 0x00, 0x0a, 0x48, - 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, 0x32, 0x6e, - 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, - 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, 0xc4, 0x99, - 0x50, 0x00, 0x7c, 0x36, - 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, 0xfc, 0x59, - 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, - 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, 0x8e, 0x85, - 0x00, 0x00, 0xf5, 0x2d, - 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, 0xc6, 0x45, - 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, - 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, 0x58, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2427 MHz */ - 0x7b, 0x09, - 0x10, 0x01, 0x48, 0x83, - 0x67, 0x8a, 0x67, 0x8a, 0x67, 0x8a, 0x67, 0x8a, - 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, - 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, 0xf9, 0xb5, - 0xf0, 0x00, 0xfb, 0x6b, - 0x50, 0x82, 0x50, 0x82, 0x50, 0x82, 0x50, 0x82, - 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, - 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, 0xe2, 0xad, - 0xd0, 0x00, 0x7e, 0x5a, - 0x38, 0x7a, 0x38, 0x7a, 0x38, 0x7a, 0x38, 0x7a, - 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, - 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, 0xca, 0xa5, - 0xa0, 0x00, 0x15, 0x48, - 0x14, 0x6e, 0x14, 0x6e, 0x14, 0x6e, 0x14, 0x6e, - 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, - 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, 0xa6, 0x99, - 0x50, 0x00, 0x8e, 0x36, - 0xd9, 0x59, 0xd9, 0x59, 0xd9, 0x59, 0xd9, 0x59, - 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, - 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, 0x6b, 0x85, - 0x00, 0x00, 0xfe, 0x2d, - 0x9d, 0x45, 0x9d, 0x45, 0x9d, 0x45, 0x9d, 0x45, - 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, - 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, 0x2f, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2432 MHz */ - 0x80, 0x09, - 0x10, 0x01, 0xd7, 0x82, - 0x51, 0x8a, 0x51, 0x8a, 0x51, 0x8a, 0x51, 0x8a, - 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, - 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, 0xe3, 0xb5, - 0xf0, 0x00, 0xc8, 0x6b, - 0x37, 0x82, 0x37, 0x82, 0x37, 0x82, 0x37, 0x82, - 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, - 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, 0xc9, 0xad, - 0xd0, 0x00, 0x6f, 0x5a, - 0x1d, 0x7a, 0x1d, 0x7a, 0x1d, 0x7a, 0x1d, 0x7a, - 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, - 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, 0xaf, 0xa5, - 0xa0, 0x00, 0x20, 0x48, - 0xf6, 0x6d, 0xf6, 0x6d, 0xf6, 0x6d, 0xf6, 0x6d, - 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, - 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, 0x88, 0x99, - 0x50, 0x00, 0x9f, 0x36, - 0xb5, 0x59, 0xb5, 0x59, 0xb5, 0x59, 0xb5, 0x59, - 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, - 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, 0x47, 0x85, - 0x00, 0x00, 0x06, 0x2e, - 0x74, 0x45, 0x74, 0x45, 0x74, 0x45, 0x74, 0x45, - 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, - 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, 0x06, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2437 MHz */ - 0x85, 0x09, - 0x10, 0x01, 0x67, 0x82, - 0x3a, 0x8a, 0x3a, 0x8a, 0x3a, 0x8a, 0x3a, 0x8a, - 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, - 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, 0xcc, 0xb5, - 0xf0, 0x00, 0x95, 0x6b, - 0x1f, 0x82, 0x1f, 0x82, 0x1f, 0x82, 0x1f, 0x82, - 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, - 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, 0xb1, 0xad, - 0xd0, 0x00, 0x61, 0x5a, - 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, 0x02, 0x7a, - 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, - 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, 0x94, 0xa5, - 0xa0, 0x00, 0x2c, 0x48, - 0xd8, 0x6d, 0xd8, 0x6d, 0xd8, 0x6d, 0xd8, 0x6d, - 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, - 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, 0x6a, 0x99, - 0x50, 0x00, 0xb1, 0x36, - 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, - 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, - 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, - 0x00, 0x00, 0x0f, 0x2e, - 0x4b, 0x45, 0x4b, 0x45, 0x4b, 0x45, 0x4b, 0x45, - 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, - 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, 0xdd, 0x70, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2442 MHz */ - 0x8a, 0x09, - 0x10, 0x01, 0xf6, 0x81, - 0x24, 0x8a, 0x24, 0x8a, 0x24, 0x8a, 0x24, 0x8a, - 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, - 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, 0xb6, 0xb5, - 0xf0, 0x00, 0x62, 0x6b, - 0x06, 0x82, 0x06, 0x82, 0x06, 0x82, 0x06, 0x82, - 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, - 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, 0x98, 0xad, - 0xd0, 0x00, 0x52, 0x5a, - 0xe7, 0x79, 0xe7, 0x79, 0xe7, 0x79, 0xe7, 0x79, - 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, - 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, 0x79, 0xa5, - 0xa0, 0x00, 0x37, 0x48, - 0xba, 0x6d, 0xba, 0x6d, 0xba, 0x6d, 0xba, 0x6d, - 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, - 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, 0x4c, 0x99, - 0x50, 0x00, 0xc2, 0x36, - 0x6e, 0x59, 0x6e, 0x59, 0x6e, 0x59, 0x6e, 0x59, - 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, - 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, 0x00, 0x85, - 0x00, 0x00, 0x17, 0x2e, - 0x22, 0x45, 0x22, 0x45, 0x22, 0x45, 0x22, 0x45, - 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, - 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, 0xb4, 0x70, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2447 MHz */ - 0x8f, 0x09, - 0x10, 0x01, 0x75, 0x83, - 0x61, 0x8a, 0x61, 0x8a, 0x61, 0x8a, 0x61, 0x8a, - 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, - 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, 0xf3, 0xb5, - 0xf0, 0x00, 0x4b, 0x6c, - 0x3f, 0x82, 0x3f, 0x82, 0x3f, 0x82, 0x3f, 0x82, - 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, - 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, 0xd1, 0xad, - 0xd0, 0x00, 0xda, 0x5a, - 0x1c, 0x7a, 0x1c, 0x7a, 0x1c, 0x7a, 0x1c, 0x7a, - 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, - 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, 0xae, 0xa5, - 0xa0, 0x00, 0x6d, 0x48, - 0xe9, 0x6d, 0xe9, 0x6d, 0xe9, 0x6d, 0xe9, 0x6d, - 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, - 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, 0x7b, 0x99, - 0x50, 0x00, 0xc6, 0x36, - 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, 0x92, 0x59, - 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, - 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, 0x24, 0x85, - 0x00, 0x00, 0x15, 0x2e, - 0x3c, 0x45, 0x3c, 0x45, 0x3c, 0x45, 0x3c, 0x45, - 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, - 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, 0xce, 0x70, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2452 MHz */ - 0x94, 0x09, - 0x10, 0x01, 0xf4, 0x84, - 0x9e, 0x8a, 0x9e, 0x8a, 0x9e, 0x8a, 0x9e, 0x8a, - 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, - 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, 0x30, 0xb6, - 0xf0, 0x00, 0x34, 0x6d, - 0x77, 0x82, 0x77, 0x82, 0x77, 0x82, 0x77, 0x82, - 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, - 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, 0x09, 0xae, - 0xd0, 0x00, 0x62, 0x5b, - 0x50, 0x7a, 0x50, 0x7a, 0x50, 0x7a, 0x50, 0x7a, - 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, - 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, 0xe2, 0xa5, - 0xa0, 0x00, 0xa2, 0x48, - 0x17, 0x6e, 0x17, 0x6e, 0x17, 0x6e, 0x17, 0x6e, - 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, - 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, 0xa9, 0x99, - 0x50, 0x00, 0xc9, 0x36, - 0xb7, 0x59, 0xb7, 0x59, 0xb7, 0x59, 0xb7, 0x59, - 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, - 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, 0x49, 0x85, - 0x00, 0x00, 0x12, 0x2e, - 0x57, 0x45, 0x57, 0x45, 0x57, 0x45, 0x57, 0x45, - 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, - 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, 0xe9, 0x70, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2452 MHz */ - 0x99, 0x09, - 0x10, 0x01, 0x74, 0x86, - 0xdb, 0x8a, 0xdb, 0x8a, 0xdb, 0x8a, 0xdb, 0x8a, - 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, - 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, 0x6d, 0xb6, - 0xf0, 0x00, 0x1e, 0x6e, - 0xb0, 0x82, 0xb0, 0x82, 0xb0, 0x82, 0xb0, 0x82, - 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, - 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, 0x42, 0xae, - 0xd0, 0x00, 0xeb, 0x5b, - 0x85, 0x7a, 0x85, 0x7a, 0x85, 0x7a, 0x85, 0x7a, - 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, - 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, 0x17, 0xa6, - 0xa0, 0x00, 0xd8, 0x48, - 0x46, 0x6e, 0x46, 0x6e, 0x46, 0x6e, 0x46, 0x6e, - 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, - 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, 0xd8, 0x99, - 0x50, 0x00, 0xcd, 0x36, - 0xdb, 0x59, 0xdb, 0x59, 0xdb, 0x59, 0xdb, 0x59, - 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, - 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, 0x6d, 0x85, - 0x00, 0x00, 0x10, 0x2e, - 0x71, 0x45, 0x71, 0x45, 0x71, 0x45, 0x71, 0x45, - 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, - 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, 0x03, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2557 MHz */ - 0x9e, 0x09, - 0x10, 0x01, 0xf3, 0x87, - 0x17, 0x8b, 0x17, 0x8b, 0x17, 0x8b, 0x17, 0x8b, - 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, - 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, 0xa9, 0xb6, - 0xf0, 0x00, 0x07, 0x6f, - 0xe9, 0x82, 0xe9, 0x82, 0xe9, 0x82, 0xe9, 0x82, - 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, - 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, 0x7b, 0xae, - 0xd0, 0x00, 0x73, 0x5c, - 0xba, 0x7a, 0xba, 0x7a, 0xba, 0x7a, 0xba, 0x7a, - 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, - 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, 0x4c, 0xa6, - 0xa0, 0x00, 0x0d, 0x49, - 0x74, 0x6e, 0x74, 0x6e, 0x74, 0x6e, 0x74, 0x6e, - 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, - 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, 0x06, 0x9a, - 0x50, 0x00, 0xd1, 0x36, - 0xff, 0x59, 0xff, 0x59, 0xff, 0x59, 0xff, 0x59, - 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, - 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, 0x91, 0x85, - 0x00, 0x00, 0x0e, 0x2e, - 0x8b, 0x45, 0x8b, 0x45, 0x8b, 0x45, 0x8b, 0x45, - 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, - 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, 0x1d, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2562 MHz */ - 0xa3, 0x09, - 0x10, 0x01, 0x72, 0x89, - 0x54, 0x8b, 0x54, 0x8b, 0x54, 0x8b, 0x54, 0x8b, - 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, - 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, 0xe6, 0xb6, - 0xf0, 0x00, 0xf0, 0x6f, - 0x21, 0x83, 0x21, 0x83, 0x21, 0x83, 0x21, 0x83, - 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, - 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, 0xb3, 0xae, - 0xd0, 0x00, 0xfb, 0x5c, - 0xee, 0x7a, 0xee, 0x7a, 0xee, 0x7a, 0xee, 0x7a, - 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, - 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, 0x80, 0xa6, - 0xa0, 0x00, 0x43, 0x49, - 0xa3, 0x6e, 0xa3, 0x6e, 0xa3, 0x6e, 0xa3, 0x6e, - 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, - 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, 0x35, 0x9a, - 0x50, 0x00, 0xd4, 0x36, - 0x24, 0x5a, 0x24, 0x5a, 0x24, 0x5a, 0x24, 0x5a, - 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, - 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, 0xb6, 0x85, - 0x00, 0x00, 0x0b, 0x2e, - 0xa6, 0x45, 0xa6, 0x45, 0xa6, 0x45, 0xa6, 0x45, - 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, - 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, 0x38, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - - /* 2572 MHz */ - 0xa8, 0x09, - 0x10, 0x01, 0xf1, 0x8a, - 0x91, 0x8b, 0x91, 0x8b, 0x91, 0x8b, 0x91, 0x8b, - 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, - 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, 0x23, 0xb7, - 0xf0, 0x00, 0xd9, 0x70, - 0x5a, 0x83, 0x5a, 0x83, 0x5a, 0x83, 0x5a, 0x83, - 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, - 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, 0xec, 0xae, - 0xd0, 0x00, 0x83, 0x5d, - 0x23, 0x7b, 0x23, 0x7b, 0x23, 0x7b, 0x23, 0x7b, - 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, - 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, 0xb5, 0xa6, - 0xa0, 0x00, 0x78, 0x49, - 0xd1, 0x6e, 0xd1, 0x6e, 0xd1, 0x6e, 0xd1, 0x6e, - 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, - 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, 0x63, 0x9a, - 0x50, 0x00, 0xd8, 0x36, - 0x48, 0x5a, 0x48, 0x5a, 0x48, 0x5a, 0x48, 0x5a, - 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, - 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, 0xda, 0x85, - 0x00, 0x00, 0x09, 0x2e, - 0xc0, 0x45, 0xc0, 0x45, 0xc0, 0x45, 0xc0, 0x45, - 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, - 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, 0x52, 0x71, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x80, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x06, 0x80, 0x80, 0x00, - -/* - * Not really sure if this is actually the power_limit database, - * it looks a bit "related" to PDR_PRISM_ZIF_TX_IQ_CALIBRATION - */ -/* struct pda_custom_wrapper */ -0xae, 0x00, 0xef, 0xbe, /* PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM */ - 0x0d, 0x00, 0x1a, 0x00, /* 13 entries, 26 bytes per entry */ - 0x00, 0x00, 0x52, 0x01, /* no offset, 338 bytes total */ - - /* 2412 MHz */ - 0x6c, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, 0xe0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2417 MHz */ - 0x71, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2422 MHz */ - 0x76, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2427 MHz */ - 0x7b, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2432 MHz */ - 0x80, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2437 MHz */ - 0x85, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2442 MHz */ - 0x8a, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2447 MHz */ - 0x8f, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2452 MHz */ - 0x94, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2457 MHz */ - 0x99, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2462 MHz */ - 0x9e, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2467 MHz */ - 0xa3, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - - /* 2472 MHz */ - 0xa8, 0x09, - 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, 0x10, 0x01, - 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, 0xf0, 0x00, - 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, 0xd0, 0x00, - -/* struct pda_iq_autocal_entry[13] */ -0x42, 0x00, 0x06, 0x19, /* PDR_PRISM_ZIF_TX_IQ_CALIBRATION */ - /* 2412 MHz */ - 0x6c, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2417 MHz */ - 0x71, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2422 MHz */ - 0x76, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2427 MHz */ - 0x7b, 0x09, 0x26, 0x00, 0xf8, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2432 MHz */ - 0x80, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2437 MHz */ - 0x85, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2442 MHz */ - 0x8a, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2447 MHz */ - 0x8f, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2452 MHz */ - 0x94, 0x09, 0x25, 0x00, 0xf7, 0xff, 0xf7, 0xff, 0xff, 0x00, - /* 2457 MHz */ - 0x99, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, - /* 2462 MHz */ - 0x9e, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, - /* 2467 MHz */ - 0xa3, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, - /* 2472 MHz */ - 0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01, - -0x02, 0x00, 0x00, 0x00, /* PDR_END */ - 0xa8, 0xf5 /* bogus data */ -}; - -#endif /* P54SPI_EEPROM_H */ - diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c deleted file mode 100644 index ab406c90172c..000000000000 --- a/drivers/net/wireless/p54/p54usb.c +++ /dev/null @@ -1,1085 +0,0 @@ - -/* - * Linux device driver for USB based Prism54 - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "p54.h" -#include "lmac.h" -#include "p54usb.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_DESCRIPTION("Prism54 USB wireless driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("prism54usb"); -MODULE_FIRMWARE("isl3886usb"); -MODULE_FIRMWARE("isl3887usb"); - -/* - * Note: - * - * Always update our wiki's device list (located at: - * http://wireless.kernel.org/en/users/Drivers/p54/devices ), - * whenever you add a new device. - */ - -static struct usb_device_id p54u_table[] __devinitdata = { - /* Version 1 devices (pci chip + net2280) */ - {USB_DEVICE(0x045e, 0x00c2)}, /* Microsoft MN-710 */ - {USB_DEVICE(0x0506, 0x0a11)}, /* 3COM 3CRWE254G72 */ - {USB_DEVICE(0x0707, 0xee06)}, /* SMC 2862W-G */ - {USB_DEVICE(0x07aa, 0x001c)}, /* Corega CG-WLUSB2GT */ - {USB_DEVICE(0x083a, 0x4501)}, /* Accton 802.11g WN4501 USB */ - {USB_DEVICE(0x083a, 0x4502)}, /* Siemens Gigaset USB Adapter */ - {USB_DEVICE(0x083a, 0x5501)}, /* Phillips CPWUA054 */ - {USB_DEVICE(0x0846, 0x4200)}, /* Netgear WG121 */ - {USB_DEVICE(0x0846, 0x4210)}, /* Netgear WG121 the second ? */ - {USB_DEVICE(0x0846, 0x4220)}, /* Netgear WG111 */ - {USB_DEVICE(0x09aa, 0x1000)}, /* Spinnaker Proto board */ - {USB_DEVICE(0x0cde, 0x0006)}, /* Medion 40900, Roper Europe */ - {USB_DEVICE(0x107b, 0x55f2)}, /* Gateway WGU-210 (Gemtek) */ - {USB_DEVICE(0x124a, 0x4023)}, /* Shuttle PN15, Airvast WM168g, IOGear GWU513 */ - {USB_DEVICE(0x1630, 0x0005)}, /* 2Wire 802.11g USB (v1) / Z-Com */ - {USB_DEVICE(0x1915, 0x2234)}, /* Linksys WUSB54G OEM */ - {USB_DEVICE(0x1915, 0x2235)}, /* Linksys WUSB54G Portable OEM */ - {USB_DEVICE(0x2001, 0x3701)}, /* DLink DWL-G120 Spinnaker */ - {USB_DEVICE(0x2001, 0x3703)}, /* DLink DWL-G122 */ - {USB_DEVICE(0x5041, 0x2234)}, /* Linksys WUSB54G */ - {USB_DEVICE(0x5041, 0x2235)}, /* Linksys WUSB54G Portable */ - - /* Version 2 devices (3887) */ - {USB_DEVICE(0x0471, 0x1230)}, /* Philips CPWUA054/00 */ - {USB_DEVICE(0x050d, 0x7050)}, /* Belkin F5D7050 ver 1000 */ - {USB_DEVICE(0x0572, 0x2000)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0572, 0x2002)}, /* Cohiba Proto board */ - {USB_DEVICE(0x06a9, 0x000e)}, /* Westell 802.11g USB (A90-211WG-01) */ - {USB_DEVICE(0x06b9, 0x0121)}, /* Thomson SpeedTouch 121g */ - {USB_DEVICE(0x0707, 0xee13)}, /* SMC 2862W-G version 2 */ - {USB_DEVICE(0x083a, 0x4521)}, /* Siemens Gigaset USB Adapter 54 version 2 */ - {USB_DEVICE(0x083a, 0xf503)}, /* Accton FD7050E ver 1010ec */ - {USB_DEVICE(0x0846, 0x4240)}, /* Netgear WG111 (v2) */ - {USB_DEVICE(0x0915, 0x2000)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0915, 0x2002)}, /* Cohiba Proto board */ - {USB_DEVICE(0x0baf, 0x0118)}, /* U.S. Robotics U5 802.11g Adapter*/ - {USB_DEVICE(0x0bf8, 0x1009)}, /* FUJITSU E-5400 USB D1700*/ - {USB_DEVICE(0x0cde, 0x0006)}, /* Medion MD40900 */ - {USB_DEVICE(0x0cde, 0x0008)}, /* Sagem XG703A */ - {USB_DEVICE(0x0cde, 0x0015)}, /* Zcomax XG-705A */ - {USB_DEVICE(0x0d8e, 0x3762)}, /* DLink DWL-G120 Cohiba */ - {USB_DEVICE(0x124a, 0x4025)}, /* IOGear GWU513 (GW3887IK chip) */ - {USB_DEVICE(0x1260, 0xee22)}, /* SMC 2862W-G version 2 */ - {USB_DEVICE(0x13b1, 0x000a)}, /* Linksys WUSB54G ver 2 */ - {USB_DEVICE(0x13B1, 0x000C)}, /* Linksys WUSB54AG */ - {USB_DEVICE(0x1413, 0x5400)}, /* Telsey 802.11g USB2.0 Adapter */ - {USB_DEVICE(0x1435, 0x0427)}, /* Inventel UR054G */ - {USB_DEVICE(0x1668, 0x1050)}, /* Actiontec 802UIG-1 */ - {USB_DEVICE(0x2001, 0x3704)}, /* DLink DWL-G122 rev A2 */ - {USB_DEVICE(0x413c, 0x5513)}, /* Dell WLA3310 USB Wireless Adapter */ - {USB_DEVICE(0x413c, 0x8102)}, /* Spinnaker DUT */ - {USB_DEVICE(0x413c, 0x8104)}, /* Cohiba Proto board */ - {} -}; - -MODULE_DEVICE_TABLE(usb, p54u_table); - -static const struct { - u32 intf; - enum p54u_hw_type type; - const char *fw; - const char *fw_legacy; - char hw[20]; -} p54u_fwlist[__NUM_P54U_HWTYPES] = { - { - .type = P54U_NET2280, - .intf = FW_LM86, - .fw = "isl3886usb", - .fw_legacy = "isl3890usb", - .hw = "ISL3886 + net2280", - }, - { - .type = P54U_3887, - .intf = FW_LM87, - .fw = "isl3887usb", - .fw_legacy = "isl3887usb_bare", - .hw = "ISL3887", - }, -}; - -static void p54u_rx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *) urb->context; - struct p54u_rx_info *info = (struct p54u_rx_info *)skb->cb; - struct ieee80211_hw *dev = info->dev; - struct p54u_priv *priv = dev->priv; - - skb_unlink(skb, &priv->rx_queue); - - if (unlikely(urb->status)) { - dev_kfree_skb_irq(skb); - return; - } - - skb_put(skb, urb->actual_length); - - if (priv->hw_type == P54U_NET2280) - skb_pull(skb, priv->common.tx_hdr_len); - if (priv->common.fw_interface == FW_LM87) { - skb_pull(skb, 4); - skb_put(skb, 4); - } - - if (p54_rx(dev, skb)) { - skb = dev_alloc_skb(priv->common.rx_mtu + 32); - if (unlikely(!skb)) { - /* TODO check rx queue length and refill *somewhere* */ - return; - } - - info = (struct p54u_rx_info *) skb->cb; - info->urb = urb; - info->dev = dev; - urb->transfer_buffer = skb_tail_pointer(skb); - urb->context = skb; - } else { - if (priv->hw_type == P54U_NET2280) - skb_push(skb, priv->common.tx_hdr_len); - if (priv->common.fw_interface == FW_LM87) { - skb_push(skb, 4); - skb_put(skb, 4); - } - skb_reset_tail_pointer(skb); - skb_trim(skb, 0); - urb->transfer_buffer = skb_tail_pointer(skb); - } - skb_queue_tail(&priv->rx_queue, skb); - usb_anchor_urb(urb, &priv->submitted); - if (usb_submit_urb(urb, GFP_ATOMIC)) { - skb_unlink(skb, &priv->rx_queue); - usb_unanchor_urb(urb); - dev_kfree_skb_irq(skb); - } -} - -static void p54u_tx_cb(struct urb *urb) -{ - struct sk_buff *skb = urb->context; - struct ieee80211_hw *dev = (struct ieee80211_hw *) - usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); - - p54_free_skb(dev, skb); -} - -static void p54u_tx_dummy_cb(struct urb *urb) { } - -static void p54u_free_urbs(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - usb_kill_anchored_urbs(&priv->submitted); -} - -static int p54u_init_urbs(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - struct urb *entry = NULL; - struct sk_buff *skb; - struct p54u_rx_info *info; - int ret = 0; - - while (skb_queue_len(&priv->rx_queue) < 32) { - skb = __dev_alloc_skb(priv->common.rx_mtu + 32, GFP_KERNEL); - if (!skb) { - ret = -ENOMEM; - goto err; - } - entry = usb_alloc_urb(0, GFP_KERNEL); - if (!entry) { - ret = -ENOMEM; - goto err; - } - - usb_fill_bulk_urb(entry, priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), - skb_tail_pointer(skb), - priv->common.rx_mtu + 32, p54u_rx_cb, skb); - info = (struct p54u_rx_info *) skb->cb; - info->urb = entry; - info->dev = dev; - skb_queue_tail(&priv->rx_queue, skb); - - usb_anchor_urb(entry, &priv->submitted); - ret = usb_submit_urb(entry, GFP_KERNEL); - if (ret) { - skb_unlink(skb, &priv->rx_queue); - usb_unanchor_urb(entry); - goto err; - } - usb_free_urb(entry); - entry = NULL; - } - - return 0; - - err: - usb_free_urb(entry); - kfree_skb(skb); - p54u_free_urbs(dev); - return ret; -} - -static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) -{ - u32 chk = 0; - - length >>= 2; - while (length--) { - chk ^= le32_to_cpu(*data++); - chk = (chk >> 5) ^ (chk << 3); - } - - return cpu_to_le32(chk); -} - -static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54u_priv *priv = dev->priv; - struct urb *data_urb; - struct lm87_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); - - data_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!data_urb) { - p54_free_skb(dev, skb); - return; - } - - hdr->chksum = p54u_lm87_chksum((__le32 *)skb->data, skb->len); - hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id; - - usb_fill_bulk_urb(data_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? - p54u_tx_cb : p54u_tx_dummy_cb, skb); - data_urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(data_urb, &priv->submitted); - if (usb_submit_urb(data_urb, GFP_ATOMIC)) { - usb_unanchor_urb(data_urb); - p54_free_skb(dev, skb); - } - usb_free_urb(data_urb); -} - -static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54u_priv *priv = dev->priv; - struct urb *int_urb = NULL, *data_urb = NULL; - struct net2280_tx_hdr *hdr = (void *)skb->data - sizeof(*hdr); - struct net2280_reg_write *reg = NULL; - int err = -ENOMEM; - - reg = kmalloc(sizeof(*reg), GFP_ATOMIC); - if (!reg) - goto out; - - int_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!int_urb) - goto out; - - data_urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!data_urb) - goto out; - - reg->port = cpu_to_le16(NET2280_DEV_U32); - reg->addr = cpu_to_le32(P54U_DEV_BASE); - reg->val = cpu_to_le32(ISL38XX_DEV_INT_DATA); - - memset(hdr, 0, sizeof(*hdr)); - hdr->len = cpu_to_le16(skb->len); - hdr->device_addr = ((struct p54_hdr *) skb->data)->req_id; - - usb_fill_bulk_urb(int_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), - p54u_tx_dummy_cb, dev); - - /* - * URB_FREE_BUFFER triggers a code path in the USB subsystem that will - * free what is inside the transfer_buffer after the last reference to - * the int_urb is dropped. - */ - int_urb->transfer_flags |= URB_FREE_BUFFER | URB_ZERO_PACKET; - reg = NULL; - - usb_fill_bulk_urb(data_urb, priv->udev, - usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), - hdr, skb->len + sizeof(*hdr), FREE_AFTER_TX(skb) ? - p54u_tx_cb : p54u_tx_dummy_cb, skb); - data_urb->transfer_flags |= URB_ZERO_PACKET; - - usb_anchor_urb(int_urb, &priv->submitted); - err = usb_submit_urb(int_urb, GFP_ATOMIC); - if (err) { - usb_unanchor_urb(int_urb); - goto out; - } - - usb_anchor_urb(data_urb, &priv->submitted); - err = usb_submit_urb(data_urb, GFP_ATOMIC); - if (err) { - usb_unanchor_urb(data_urb); - goto out; - } -out: - usb_free_urb(int_urb); - usb_free_urb(data_urb); - - if (err) { - kfree(reg); - p54_free_skb(dev, skb); - } -} - -static int p54u_write(struct p54u_priv *priv, - struct net2280_reg_write *buf, - enum net2280_op_type type, - __le32 addr, __le32 val) -{ - unsigned int ep; - int alen; - - if (type & 0x0800) - ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV); - else - ep = usb_sndbulkpipe(priv->udev, P54U_PIPE_BRG); - - buf->port = cpu_to_le16(type); - buf->addr = addr; - buf->val = val; - - return usb_bulk_msg(priv->udev, ep, buf, sizeof(*buf), &alen, 1000); -} - -static int p54u_read(struct p54u_priv *priv, void *buf, - enum net2280_op_type type, - __le32 addr, __le32 *val) -{ - struct net2280_reg_read *read = buf; - __le32 *reg = buf; - unsigned int ep; - int alen, err; - - if (type & 0x0800) - ep = P54U_PIPE_DEV; - else - ep = P54U_PIPE_BRG; - - read->port = cpu_to_le16(type); - read->addr = addr; - - err = usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep), - read, sizeof(*read), &alen, 1000); - if (err) - return err; - - err = usb_bulk_msg(priv->udev, usb_rcvbulkpipe(priv->udev, ep), - reg, sizeof(*reg), &alen, 1000); - if (err) - return err; - - *val = *reg; - return 0; -} - -static int p54u_bulk_msg(struct p54u_priv *priv, unsigned int ep, - void *data, size_t len) -{ - int alen; - return usb_bulk_msg(priv->udev, usb_sndbulkpipe(priv->udev, ep), - data, len, &alen, 2000); -} - -static int p54u_device_reset(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - int ret, lock = (priv->intf->condition != USB_INTERFACE_BINDING); - - if (lock) { - ret = usb_lock_device_for_reset(priv->udev, priv->intf); - if (ret < 0) { - dev_err(&priv->udev->dev, "(p54usb) unable to lock " - "device for reset (%d)!\n", ret); - return ret; - } - } - - ret = usb_reset_device(priv->udev); - if (lock) - usb_unlock_device(priv->udev); - - if (ret) - dev_err(&priv->udev->dev, "(p54usb) unable to reset " - "device (%d)!\n", ret); - - return ret; -} - -static const char p54u_romboot_3887[] = "~~~~"; -static int p54u_firmware_reset_3887(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - u8 *buf; - int ret; - - buf = kmalloc(4, GFP_KERNEL); - if (!buf) - return -ENOMEM; - memcpy(buf, p54u_romboot_3887, 4); - ret = p54u_bulk_msg(priv, P54U_PIPE_DATA, - buf, 4); - kfree(buf); - if (ret) - dev_err(&priv->udev->dev, "(p54usb) unable to jump to " - "boot ROM (%d)!\n", ret); - - return ret; -} - -static const char p54u_firmware_upload_3887[] = "<\r"; -static int p54u_upload_firmware_3887(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - int err, alen; - u8 carry = 0; - u8 *buf, *tmp; - const u8 *data; - unsigned int left, remains, block_size; - struct x2_header *hdr; - unsigned long timeout; - - err = p54u_firmware_reset_3887(dev); - if (err) - return err; - - tmp = buf = kmalloc(P54U_FW_BLOCK, GFP_KERNEL); - if (!buf) { - dev_err(&priv->udev->dev, "(p54usb) cannot allocate firmware" - "upload buffer!\n"); - return -ENOMEM; - } - - left = block_size = min((size_t)P54U_FW_BLOCK, priv->fw->size); - strcpy(buf, p54u_firmware_upload_3887); - left -= strlen(p54u_firmware_upload_3887); - tmp += strlen(p54u_firmware_upload_3887); - - data = priv->fw->data; - remains = priv->fw->size; - - hdr = (struct x2_header *)(buf + strlen(p54u_firmware_upload_3887)); - memcpy(hdr->signature, X2_SIGNATURE, X2_SIGNATURE_SIZE); - hdr->fw_load_addr = cpu_to_le32(ISL38XX_DEV_FIRMWARE_ADDR); - hdr->fw_length = cpu_to_le32(priv->fw->size); - hdr->crc = cpu_to_le32(~crc32_le(~0, (void *)&hdr->fw_load_addr, - sizeof(u32)*2)); - left -= sizeof(*hdr); - tmp += sizeof(*hdr); - - while (remains) { - while (left--) { - if (carry) { - *tmp++ = carry; - carry = 0; - remains--; - continue; - } - switch (*data) { - case '~': - *tmp++ = '}'; - carry = '^'; - break; - case '}': - *tmp++ = '}'; - carry = ']'; - break; - default: - *tmp++ = *data; - remains--; - break; - } - data++; - } - - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_size); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) firmware " - "upload failed!\n"); - goto err_upload_failed; - } - - tmp = buf; - left = block_size = min((unsigned int)P54U_FW_BLOCK, remains); - } - - *((__le32 *)buf) = cpu_to_le32(~crc32_le(~0, priv->fw->data, - priv->fw->size)); - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, sizeof(u32)); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n"); - goto err_upload_failed; - } - timeout = jiffies + msecs_to_jiffies(1000); - while (!(err = usb_bulk_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) { - if (alen > 2 && !memcmp(buf, "OK", 2)) - break; - - if (alen > 5 && !memcmp(buf, "ERROR", 5)) { - err = -EINVAL; - break; - } - - if (time_after(jiffies, timeout)) { - dev_err(&priv->udev->dev, "(p54usb) firmware boot " - "timed out!\n"); - err = -ETIMEDOUT; - break; - } - } - if (err) { - dev_err(&priv->udev->dev, "(p54usb) firmware upload failed!\n"); - goto err_upload_failed; - } - - buf[0] = 'g'; - buf[1] = '\r'; - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, 2); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) firmware boot failed!\n"); - goto err_upload_failed; - } - - timeout = jiffies + msecs_to_jiffies(1000); - while (!(err = usb_bulk_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_DATA), buf, 128, &alen, 1000))) { - if (alen > 0 && buf[0] == 'g') - break; - - if (time_after(jiffies, timeout)) { - err = -ETIMEDOUT; - break; - } - } - if (err) - goto err_upload_failed; - -err_upload_failed: - kfree(buf); - return err; -} - -static int p54u_upload_firmware_net2280(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - const struct p54p_csr *devreg = (const struct p54p_csr *) P54U_DEV_BASE; - int err, alen; - void *buf; - __le32 reg; - unsigned int remains, offset; - const u8 *data; - - buf = kmalloc(512, GFP_KERNEL); - if (!buf) { - dev_err(&priv->udev->dev, "(p54usb) firmware buffer " - "alloc failed!\n"); - return -ENOMEM; - } - -#define P54U_WRITE(type, addr, data) \ - do {\ - err = p54u_write(priv, buf, type,\ - cpu_to_le32((u32)(unsigned long)addr), data);\ - if (err) \ - goto fail;\ - } while (0) - -#define P54U_READ(type, addr) \ - do {\ - err = p54u_read(priv, buf, type,\ - cpu_to_le32((u32)(unsigned long)addr), ®);\ - if (err)\ - goto fail;\ - } while (0) - - /* power down net2280 bridge */ - P54U_READ(NET2280_BRG_U32, NET2280_GPIOCTL); - reg |= cpu_to_le32(P54U_BRG_POWER_DOWN); - reg &= cpu_to_le32(~P54U_BRG_POWER_UP); - P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg); - - mdelay(100); - - /* power up bridge */ - reg |= cpu_to_le32(P54U_BRG_POWER_UP); - reg &= cpu_to_le32(~P54U_BRG_POWER_DOWN); - P54U_WRITE(NET2280_BRG_U32, NET2280_GPIOCTL, reg); - - mdelay(100); - - P54U_WRITE(NET2280_BRG_U32, NET2280_DEVINIT, - cpu_to_le32(NET2280_CLK_30Mhz | - NET2280_PCI_ENABLE | - NET2280_PCI_SOFT_RESET)); - - mdelay(20); - - P54U_WRITE(NET2280_BRG_CFG_U16, PCI_COMMAND, - cpu_to_le32(PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER)); - - P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_0, - cpu_to_le32(NET2280_BASE)); - - P54U_READ(NET2280_BRG_CFG_U16, PCI_STATUS); - reg |= cpu_to_le32(PCI_STATUS_REC_MASTER_ABORT); - P54U_WRITE(NET2280_BRG_CFG_U16, PCI_STATUS, reg); - - // TODO: we really need this? - P54U_READ(NET2280_BRG_U32, NET2280_RELNUM); - - P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_RSP, - cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE)); - P54U_WRITE(NET2280_BRG_U32, NET2280_EPC_RSP, - cpu_to_le32(NET2280_CLEAR_NAK_OUT_PACKETS_MODE)); - - P54U_WRITE(NET2280_BRG_CFG_U32, PCI_BASE_ADDRESS_2, - cpu_to_le32(NET2280_BASE2)); - - /* finally done setting up the bridge */ - - P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | PCI_COMMAND, - cpu_to_le32(PCI_COMMAND_MEMORY | - PCI_COMMAND_MASTER)); - - P54U_WRITE(NET2280_DEV_CFG_U16, 0x10000 | 0x40 /* TRDY timeout */, 0); - P54U_WRITE(NET2280_DEV_CFG_U32, 0x10000 | PCI_BASE_ADDRESS_0, - cpu_to_le32(P54U_DEV_BASE)); - - P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0); - P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); - - /* do romboot */ - P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, 0); - - P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RAMBOOT); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(20); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(20); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(100); - - P54U_READ(NET2280_DEV_U32, &devreg->int_ident); - P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); - - /* finally, we can upload firmware now! */ - remains = priv->fw->size; - data = priv->fw->data; - offset = ISL38XX_DEV_FIRMWARE_ADDR; - - while (remains) { - unsigned int block_len = min(remains, (unsigned int)512); - memcpy(buf, data, block_len); - - err = p54u_bulk_msg(priv, P54U_PIPE_DATA, buf, block_len); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) firmware block " - "upload failed\n"); - goto fail; - } - - P54U_WRITE(NET2280_DEV_U32, &devreg->direct_mem_base, - cpu_to_le32(0xc0000f00)); - - P54U_WRITE(NET2280_DEV_U32, - 0x0020 | (unsigned long)&devreg->direct_mem_win, 0); - P54U_WRITE(NET2280_DEV_U32, - 0x0020 | (unsigned long)&devreg->direct_mem_win, - cpu_to_le32(1)); - - P54U_WRITE(NET2280_DEV_U32, - 0x0024 | (unsigned long)&devreg->direct_mem_win, - cpu_to_le32(block_len)); - P54U_WRITE(NET2280_DEV_U32, - 0x0028 | (unsigned long)&devreg->direct_mem_win, - cpu_to_le32(offset)); - - P54U_WRITE(NET2280_DEV_U32, &devreg->dma_addr, - cpu_to_le32(NET2280_EPA_FIFO_PCI_ADDR)); - P54U_WRITE(NET2280_DEV_U32, &devreg->dma_len, - cpu_to_le32(block_len >> 2)); - P54U_WRITE(NET2280_DEV_U32, &devreg->dma_ctrl, - cpu_to_le32(ISL38XX_DMA_MASTER_CONTROL_TRIGGER)); - - mdelay(10); - - P54U_READ(NET2280_DEV_U32, - 0x002C | (unsigned long)&devreg->direct_mem_win); - if (!(reg & cpu_to_le32(ISL38XX_DMA_STATUS_DONE)) || - !(reg & cpu_to_le32(ISL38XX_DMA_STATUS_READY))) { - dev_err(&priv->udev->dev, "(p54usb) firmware DMA " - "transfer failed\n"); - goto fail; - } - - P54U_WRITE(NET2280_BRG_U32, NET2280_EPA_STAT, - cpu_to_le32(NET2280_FIFO_FLUSH)); - - remains -= block_len; - data += block_len; - offset += block_len; - } - - /* do ramboot */ - P54U_READ(NET2280_DEV_U32, &devreg->ctrl_stat); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_CLKRUN); - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RAMBOOT); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(20); - - reg |= cpu_to_le32(ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - reg &= cpu_to_le32(~ISL38XX_CTRL_STAT_RESET); - P54U_WRITE(NET2280_DEV_U32, &devreg->ctrl_stat, reg); - - mdelay(100); - - P54U_READ(NET2280_DEV_U32, &devreg->int_ident); - P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); - - /* start up the firmware */ - P54U_WRITE(NET2280_DEV_U32, &devreg->int_enable, - cpu_to_le32(ISL38XX_INT_IDENT_INIT)); - - P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); - - P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT_ENABLE | - NET2280_USB_INTERRUPT_ENABLE)); - - P54U_WRITE(NET2280_DEV_U32, &devreg->dev_int, - cpu_to_le32(ISL38XX_DEV_INT_RESET)); - - err = usb_interrupt_msg(priv->udev, - usb_rcvbulkpipe(priv->udev, P54U_PIPE_INT), - buf, sizeof(__le32), &alen, 1000); - if (err || alen != sizeof(__le32)) - goto fail; - - P54U_READ(NET2280_DEV_U32, &devreg->int_ident); - P54U_WRITE(NET2280_DEV_U32, &devreg->int_ack, reg); - - if (!(reg & cpu_to_le32(ISL38XX_INT_IDENT_INIT))) - err = -EINVAL; - - P54U_WRITE(NET2280_BRG_U32, NET2280_USBIRQENB1, 0); - P54U_WRITE(NET2280_BRG_U32, NET2280_IRQSTAT1, - cpu_to_le32(NET2280_PCI_INTA_INTERRUPT)); - -#undef P54U_WRITE -#undef P54U_READ - -fail: - kfree(buf); - return err; -} - -static int p54u_load_firmware(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - int err, i; - - BUILD_BUG_ON(ARRAY_SIZE(p54u_fwlist) != __NUM_P54U_HWTYPES); - - for (i = 0; i < __NUM_P54U_HWTYPES; i++) - if (p54u_fwlist[i].type == priv->hw_type) - break; - - if (i == __NUM_P54U_HWTYPES) - return -EOPNOTSUPP; - - err = request_firmware(&priv->fw, p54u_fwlist[i].fw, &priv->udev->dev); - if (err) { - dev_err(&priv->udev->dev, "(p54usb) cannot load firmware %s " - "(%d)!\n", p54u_fwlist[i].fw, err); - - err = request_firmware(&priv->fw, p54u_fwlist[i].fw_legacy, - &priv->udev->dev); - if (err) - return err; - } - - err = p54_parse_firmware(dev, priv->fw); - if (err) - goto out; - - if (priv->common.fw_interface != p54u_fwlist[i].intf) { - dev_err(&priv->udev->dev, "wrong firmware, please get " - "a firmware for \"%s\" and try again.\n", - p54u_fwlist[i].hw); - err = -EINVAL; - } - -out: - if (err) - release_firmware(priv->fw); - - return err; -} - -static int p54u_open(struct ieee80211_hw *dev) -{ - struct p54u_priv *priv = dev->priv; - int err; - - err = p54u_init_urbs(dev); - if (err) { - return err; - } - - priv->common.open = p54u_init_urbs; - - return 0; -} - -static void p54u_stop(struct ieee80211_hw *dev) -{ - /* TODO: figure out how to reliably stop the 3887 and net2280 so - the hardware is still usable next time we want to start it. - until then, we just stop listening to the hardware.. */ - p54u_free_urbs(dev); - return; -} - -static int __devinit p54u_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct ieee80211_hw *dev; - struct p54u_priv *priv; - int err; - unsigned int i, recognized_pipes; - - dev = p54_init_common(sizeof(*priv)); - - if (!dev) { - dev_err(&udev->dev, "(p54usb) ieee80211 alloc failed\n"); - return -ENOMEM; - } - - priv = dev->priv; - priv->hw_type = P54U_INVALID_HW; - - SET_IEEE80211_DEV(dev, &intf->dev); - usb_set_intfdata(intf, dev); - priv->udev = udev; - priv->intf = intf; - skb_queue_head_init(&priv->rx_queue); - init_usb_anchor(&priv->submitted); - - usb_get_dev(udev); - - /* really lazy and simple way of figuring out if we're a 3887 */ - /* TODO: should just stick the identification in the device table */ - i = intf->altsetting->desc.bNumEndpoints; - recognized_pipes = 0; - while (i--) { - switch (intf->altsetting->endpoint[i].desc.bEndpointAddress) { - case P54U_PIPE_DATA: - case P54U_PIPE_MGMT: - case P54U_PIPE_BRG: - case P54U_PIPE_DEV: - case P54U_PIPE_DATA | USB_DIR_IN: - case P54U_PIPE_MGMT | USB_DIR_IN: - case P54U_PIPE_BRG | USB_DIR_IN: - case P54U_PIPE_DEV | USB_DIR_IN: - case P54U_PIPE_INT | USB_DIR_IN: - recognized_pipes++; - } - } - priv->common.open = p54u_open; - priv->common.stop = p54u_stop; - if (recognized_pipes < P54U_PIPE_NUMBER) { -#ifdef CONFIG_PM - /* ISL3887 needs a full reset on resume */ - udev->reset_resume = 1; -#endif /* CONFIG_PM */ - err = p54u_device_reset(dev); - - priv->hw_type = P54U_3887; - dev->extra_tx_headroom += sizeof(struct lm87_tx_hdr); - priv->common.tx_hdr_len = sizeof(struct lm87_tx_hdr); - priv->common.tx = p54u_tx_lm87; - priv->upload_fw = p54u_upload_firmware_3887; - } else { - priv->hw_type = P54U_NET2280; - dev->extra_tx_headroom += sizeof(struct net2280_tx_hdr); - priv->common.tx_hdr_len = sizeof(struct net2280_tx_hdr); - priv->common.tx = p54u_tx_net2280; - priv->upload_fw = p54u_upload_firmware_net2280; - } - err = p54u_load_firmware(dev); - if (err) - goto err_free_dev; - - err = priv->upload_fw(dev); - if (err) - goto err_free_fw; - - p54u_open(dev); - err = p54_read_eeprom(dev); - p54u_stop(dev); - if (err) - goto err_free_fw; - - err = p54_register_common(dev, &udev->dev); - if (err) - goto err_free_fw; - - return 0; - -err_free_fw: - release_firmware(priv->fw); - -err_free_dev: - p54_free_common(dev); - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - return err; -} - -static void __devexit p54u_disconnect(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - struct p54u_priv *priv; - - if (!dev) - return; - - p54_unregister_common(dev); - - priv = dev->priv; - usb_put_dev(interface_to_usbdev(intf)); - release_firmware(priv->fw); - p54_free_common(dev); -} - -static int p54u_pre_reset(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - - if (!dev) - return -ENODEV; - - p54u_stop(dev); - return 0; -} - -static int p54u_resume(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - struct p54u_priv *priv; - - if (!dev) - return -ENODEV; - - priv = dev->priv; - if (unlikely(!(priv->upload_fw && priv->fw))) - return 0; - - return priv->upload_fw(dev); -} - -static int p54u_post_reset(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - struct p54u_priv *priv; - int err; - - err = p54u_resume(intf); - if (err) - return err; - - /* reinitialize old device state */ - priv = dev->priv; - if (priv->common.mode != NL80211_IFTYPE_UNSPECIFIED) - ieee80211_restart_hw(dev); - - return 0; -} - -#ifdef CONFIG_PM - -static int p54u_suspend(struct usb_interface *intf, pm_message_t message) -{ - return p54u_pre_reset(intf); -} - -#endif /* CONFIG_PM */ - -static struct usb_driver p54u_driver = { - .name = "p54usb", - .id_table = p54u_table, - .probe = p54u_probe, - .disconnect = p54u_disconnect, - .pre_reset = p54u_pre_reset, - .post_reset = p54u_post_reset, -#ifdef CONFIG_PM - .suspend = p54u_suspend, - .resume = p54u_resume, - .reset_resume = p54u_resume, -#endif /* CONFIG_PM */ - .soft_unbind = 1, -}; - -static int __init p54u_init(void) -{ - return usb_register(&p54u_driver); -} - -static void __exit p54u_exit(void) -{ - usb_deregister(&p54u_driver); -} - -module_init(p54u_init); -module_exit(p54u_exit); diff --git a/drivers/net/wireless/p54/p54usb.h b/drivers/net/wireless/p54/p54usb.h deleted file mode 100644 index e935b79f7f75..000000000000 --- a/drivers/net/wireless/p54/p54usb.h +++ /dev/null @@ -1,148 +0,0 @@ -#ifndef P54USB_H -#define P54USB_H - -/* - * Defines for USB based mac80211 Prism54 driver - * - * Copyright (c) 2006, Michael Wu - * - * Based on the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -/* for isl3886 register definitions used on ver 1 devices */ -#include "p54pci.h" -#include "net2280.h" - -/* pci */ -#define NET2280_BASE 0x10000000 -#define NET2280_BASE2 0x20000000 - -/* gpio */ -#define P54U_BRG_POWER_UP (1 << GPIO0_DATA) -#define P54U_BRG_POWER_DOWN (1 << GPIO1_DATA) - -/* devinit */ -#define NET2280_CLK_4Mhz (15 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_CLK_30Mhz (2 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_CLK_60Mhz (1 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_CLK_STOP (0 << LOCAL_CLOCK_FREQUENCY) -#define NET2280_PCI_ENABLE (1 << PCI_ENABLE) -#define NET2280_PCI_SOFT_RESET (1 << PCI_SOFT_RESET) - -/* endpoints */ -#define NET2280_CLEAR_NAK_OUT_PACKETS_MODE (1 << CLEAR_NAK_OUT_PACKETS_MODE) -#define NET2280_FIFO_FLUSH (1 << FIFO_FLUSH) - -/* irq */ -#define NET2280_USB_INTERRUPT_ENABLE (1 << USB_INTERRUPT_ENABLE) -#define NET2280_PCI_INTA_INTERRUPT (1 << PCI_INTA_INTERRUPT) -#define NET2280_PCI_INTA_INTERRUPT_ENABLE (1 << PCI_INTA_INTERRUPT_ENABLE) - -/* registers */ -#define NET2280_DEVINIT 0x00 -#define NET2280_USBIRQENB1 0x24 -#define NET2280_IRQSTAT1 0x2c -#define NET2280_FIFOCTL 0x38 -#define NET2280_GPIOCTL 0x50 -#define NET2280_RELNUM 0x88 -#define NET2280_EPA_RSP 0x324 -#define NET2280_EPA_STAT 0x32c -#define NET2280_EPB_STAT 0x34c -#define NET2280_EPC_RSP 0x364 -#define NET2280_EPC_STAT 0x36c -#define NET2280_EPD_STAT 0x38c - -#define NET2280_EPA_CFG 0x320 -#define NET2280_EPB_CFG 0x340 -#define NET2280_EPC_CFG 0x360 -#define NET2280_EPD_CFG 0x380 -#define NET2280_EPE_CFG 0x3A0 -#define NET2280_EPF_CFG 0x3C0 -#define P54U_DEV_BASE 0x40000000 - -struct net2280_tx_hdr { - __le32 device_addr; - __le16 len; - __le16 follower; /* ? */ - u8 padding[8]; -} __attribute__((packed)); - -struct lm87_tx_hdr { - __le32 device_addr; - __le32 chksum; -} __attribute__((packed)); - -/* Some flags for the isl hardware registers controlling DMA inside the - * chip */ -#define ISL38XX_DMA_STATUS_DONE 0x00000001 -#define ISL38XX_DMA_STATUS_READY 0x00000002 -#define NET2280_EPA_FIFO_PCI_ADDR 0x20000000 -#define ISL38XX_DMA_MASTER_CONTROL_TRIGGER 0x00000004 - -enum net2280_op_type { - NET2280_BRG_U32 = 0x001F, - NET2280_BRG_CFG_U32 = 0x000F, - NET2280_BRG_CFG_U16 = 0x0003, - NET2280_DEV_U32 = 0x080F, - NET2280_DEV_CFG_U32 = 0x088F, - NET2280_DEV_CFG_U16 = 0x0883 -}; - -#define P54U_FW_BLOCK 2048 - -#define X2_SIGNATURE "x2 " -#define X2_SIGNATURE_SIZE 4 - -struct x2_header { - u8 signature[X2_SIGNATURE_SIZE]; - __le32 fw_load_addr; - __le32 fw_length; - __le32 crc; -} __attribute__((packed)); - -/* pipes 3 and 4 are not used by the driver */ -#define P54U_PIPE_NUMBER 9 - -enum p54u_pipe_addr { - P54U_PIPE_DATA = 0x01, - P54U_PIPE_MGMT = 0x02, - P54U_PIPE_3 = 0x03, - P54U_PIPE_4 = 0x04, - P54U_PIPE_BRG = 0x0d, - P54U_PIPE_DEV = 0x0e, - P54U_PIPE_INT = 0x0f -}; - -struct p54u_rx_info { - struct urb *urb; - struct ieee80211_hw *dev; -}; - -enum p54u_hw_type { - P54U_INVALID_HW, - P54U_NET2280, - P54U_3887, - - /* keep last */ - __NUM_P54U_HWTYPES, -}; - -struct p54u_priv { - struct p54_common common; - struct usb_device *udev; - struct usb_interface *intf; - int (*upload_fw)(struct ieee80211_hw *dev); - - enum p54u_hw_type hw_type; - spinlock_t lock; - struct sk_buff_head rx_queue; - struct usb_anchor submitted; - const struct firmware *fw; -}; - -#endif /* P54USB_H */ diff --git a/drivers/net/wireless/p54/txrx.c b/drivers/net/wireless/p54/txrx.c deleted file mode 100644 index 0edd7b493aa7..000000000000 --- a/drivers/net/wireless/p54/txrx.c +++ /dev/null @@ -1,869 +0,0 @@ -/* - * Common code for mac80211 Prism54 drivers - * - * Copyright (c) 2006, Michael Wu - * Copyright (c) 2007-2009, Christian Lamparter - * Copyright 2008, Johannes Berg - * - * Based on: - * - the islsm (softmac prism54) driver, which is: - * Copyright 2004-2006 Jean-Baptiste Note , et al. - * - stlc45xx driver - * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies). - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include - -#include "p54.h" -#include "lmac.h" - -#ifdef P54_MM_DEBUG -static void p54_dump_tx_queue(struct p54_common *priv) -{ - unsigned long flags; - struct ieee80211_tx_info *info; - struct p54_tx_info *range; - struct sk_buff *skb; - struct p54_hdr *hdr; - unsigned int i = 0; - u32 prev_addr; - u32 largest_hole = 0, free; - - spin_lock_irqsave(&priv->tx_queue.lock, flags); - printk(KERN_DEBUG "%s: / --- tx queue dump (%d entries) --- \n", - wiphy_name(priv->hw->wiphy), skb_queue_len(&priv->tx_queue)); - - prev_addr = priv->rx_start; - skb_queue_walk(&priv->tx_queue, skb) { - info = IEEE80211_SKB_CB(skb); - range = (void *) info->rate_driver_data; - hdr = (void *) skb->data; - - free = range->start_addr - prev_addr; - printk(KERN_DEBUG "%s: | [%02d] => [skb:%p skb_len:0x%04x " - "hdr:{flags:%02x len:%04x req_id:%04x type:%02x} " - "mem:{start:%04x end:%04x, free:%d}]\n", - wiphy_name(priv->hw->wiphy), i++, skb, skb->len, - le16_to_cpu(hdr->flags), le16_to_cpu(hdr->len), - le32_to_cpu(hdr->req_id), le16_to_cpu(hdr->type), - range->start_addr, range->end_addr, free); - - prev_addr = range->end_addr; - largest_hole = max(largest_hole, free); - } - free = priv->rx_end - prev_addr; - largest_hole = max(largest_hole, free); - printk(KERN_DEBUG "%s: \\ --- [free: %d], largest free block: %d ---\n", - wiphy_name(priv->hw->wiphy), free, largest_hole); - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); -} -#endif /* P54_MM_DEBUG */ - -/* - * So, the firmware is somewhat stupid and doesn't know what places in its - * memory incoming data should go to. By poking around in the firmware, we - * can find some unused memory to upload our packets to. However, data that we - * want the card to TX needs to stay intact until the card has told us that - * it is done with it. This function finds empty places we can upload to and - * marks allocated areas as reserved if necessary. p54_find_and_unlink_skb or - * p54_free_skb frees allocated areas. - */ -static int p54_assign_address(struct p54_common *priv, struct sk_buff *skb) -{ - struct sk_buff *entry, *target_skb = NULL; - struct ieee80211_tx_info *info; - struct p54_tx_info *range; - struct p54_hdr *data = (void *) skb->data; - unsigned long flags; - u32 last_addr = priv->rx_start; - u32 target_addr = priv->rx_start; - u16 len = priv->headroom + skb->len + priv->tailroom + 3; - - info = IEEE80211_SKB_CB(skb); - range = (void *) info->rate_driver_data; - len = (range->extra_len + len) & ~0x3; - - spin_lock_irqsave(&priv->tx_queue.lock, flags); - if (unlikely(skb_queue_len(&priv->tx_queue) == 32)) { - /* - * The tx_queue is now really full. - * - * TODO: check if the device has crashed and reset it. - */ - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - return -EBUSY; - } - - skb_queue_walk(&priv->tx_queue, entry) { - u32 hole_size; - info = IEEE80211_SKB_CB(entry); - range = (void *) info->rate_driver_data; - hole_size = range->start_addr - last_addr; - - if (!target_skb && hole_size >= len) { - target_skb = entry->prev; - hole_size -= len; - target_addr = last_addr; - break; - } - last_addr = range->end_addr; - } - if (unlikely(!target_skb)) { - if (priv->rx_end - last_addr >= len) { - target_skb = priv->tx_queue.prev; - if (!skb_queue_empty(&priv->tx_queue)) { - info = IEEE80211_SKB_CB(target_skb); - range = (void *)info->rate_driver_data; - target_addr = range->end_addr; - } - } else { - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - return -ENOSPC; - } - } - - info = IEEE80211_SKB_CB(skb); - range = (void *) info->rate_driver_data; - range->start_addr = target_addr; - range->end_addr = target_addr + len; - data->req_id = cpu_to_le32(target_addr + priv->headroom); - if (IS_DATA_FRAME(skb) && - unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) - priv->beacon_req_id = data->req_id; - - __skb_queue_after(&priv->tx_queue, target_skb, skb); - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - return 0; -} - -static void p54_tx_pending(struct p54_common *priv) -{ - struct sk_buff *skb; - int ret; - - skb = skb_dequeue(&priv->tx_pending); - if (unlikely(!skb)) - return ; - - ret = p54_assign_address(priv, skb); - if (unlikely(ret)) - skb_queue_head(&priv->tx_pending, skb); - else - priv->tx(priv->hw, skb); -} - -static void p54_wake_queues(struct p54_common *priv) -{ - unsigned long flags; - unsigned int i; - - if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) - return ; - - p54_tx_pending(priv); - - spin_lock_irqsave(&priv->tx_stats_lock, flags); - for (i = 0; i < priv->hw->queues; i++) { - if (priv->tx_stats[i + P54_QUEUE_DATA].len < - priv->tx_stats[i + P54_QUEUE_DATA].limit) - ieee80211_wake_queue(priv->hw, i); - } - spin_unlock_irqrestore(&priv->tx_stats_lock, flags); -} - -static int p54_tx_qos_accounting_alloc(struct p54_common *priv, - struct sk_buff *skb, - const u16 p54_queue) -{ - struct ieee80211_tx_queue_stats *queue; - unsigned long flags; - - if (WARN_ON(p54_queue >= P54_QUEUE_NUM)) - return -EINVAL; - - queue = &priv->tx_stats[p54_queue]; - - spin_lock_irqsave(&priv->tx_stats_lock, flags); - if (unlikely(queue->len >= queue->limit && IS_QOS_QUEUE(p54_queue))) { - spin_unlock_irqrestore(&priv->tx_stats_lock, flags); - return -ENOSPC; - } - - queue->len++; - queue->count++; - - if (unlikely(queue->len == queue->limit && IS_QOS_QUEUE(p54_queue))) { - u16 ac_queue = p54_queue - P54_QUEUE_DATA; - ieee80211_stop_queue(priv->hw, ac_queue); - } - - spin_unlock_irqrestore(&priv->tx_stats_lock, flags); - return 0; -} - -static void p54_tx_qos_accounting_free(struct p54_common *priv, - struct sk_buff *skb) -{ - if (IS_DATA_FRAME(skb)) { - unsigned long flags; - - spin_lock_irqsave(&priv->tx_stats_lock, flags); - priv->tx_stats[GET_HW_QUEUE(skb)].len--; - spin_unlock_irqrestore(&priv->tx_stats_lock, flags); - - if (unlikely(GET_HW_QUEUE(skb) == P54_QUEUE_BEACON)) { - if (priv->beacon_req_id == GET_REQ_ID(skb)) { - /* this is the active beacon set anymore */ - priv->beacon_req_id = 0; - } - complete(&priv->beacon_comp); - } - } - p54_wake_queues(priv); -} - -void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54_common *priv = dev->priv; - if (unlikely(!skb)) - return ; - - skb_unlink(skb, &priv->tx_queue); - p54_tx_qos_accounting_free(priv, skb); - dev_kfree_skb_any(skb); -} -EXPORT_SYMBOL_GPL(p54_free_skb); - -static struct sk_buff *p54_find_and_unlink_skb(struct p54_common *priv, - const __le32 req_id) -{ - struct sk_buff *entry; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_queue.lock, flags); - skb_queue_walk(&priv->tx_queue, entry) { - struct p54_hdr *hdr = (struct p54_hdr *) entry->data; - - if (hdr->req_id == req_id) { - __skb_unlink(entry, &priv->tx_queue); - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - p54_tx_qos_accounting_free(priv, entry); - return entry; - } - } - spin_unlock_irqrestore(&priv->tx_queue.lock, flags); - return NULL; -} - -void p54_tx(struct p54_common *priv, struct sk_buff *skb) -{ - skb_queue_tail(&priv->tx_pending, skb); - p54_tx_pending(priv); -} - -static int p54_rssi_to_dbm(struct p54_common *priv, int rssi) -{ - int band = priv->hw->conf.channel->band; - - if (priv->rxhw != 5) - return ((rssi * priv->rssical_db[band].mul) / 64 + - priv->rssical_db[band].add) / 4; - else - /* - * TODO: find the correct formula - */ - return ((rssi * priv->rssical_db[band].mul) / 64 + - priv->rssical_db[band].add) / 4; -} - -/* - * Even if the firmware is capable of dealing with incoming traffic, - * while dozing, we have to prepared in case mac80211 uses PS-POLL - * to retrieve outstanding frames from our AP. - * (see comment in net/mac80211/mlme.c @ line 1993) - */ -static void p54_pspoll_workaround(struct p54_common *priv, struct sk_buff *skb) -{ - struct ieee80211_hdr *hdr = (void *) skb->data; - struct ieee80211_tim_ie *tim_ie; - u8 *tim; - u8 tim_len; - bool new_psm; - - /* only beacons have a TIM IE */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - - if (!priv->aid) - return; - - /* only consider beacons from the associated BSSID */ - if (compare_ether_addr(hdr->addr3, priv->bssid)) - return; - - tim = p54_find_ie(skb, WLAN_EID_TIM); - if (!tim) - return; - - tim_len = tim[1]; - tim_ie = (struct ieee80211_tim_ie *) &tim[2]; - - new_psm = ieee80211_check_tim(tim_ie, tim_len, priv->aid); - if (new_psm != priv->powersave_override) { - priv->powersave_override = new_psm; - p54_set_ps(priv); - } -} - -static int p54_rx_data(struct p54_common *priv, struct sk_buff *skb) -{ - struct p54_rx_data *hdr = (struct p54_rx_data *) skb->data; - struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); - u16 freq = le16_to_cpu(hdr->freq); - size_t header_len = sizeof(*hdr); - u32 tsf32; - u8 rate = hdr->rate & 0xf; - - /* - * If the device is in a unspecified state we have to - * ignore all data frames. Else we could end up with a - * nasty crash. - */ - if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) - return 0; - - if (!(hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_IN_FCS_GOOD))) - return 0; - - if (hdr->decrypt_status == P54_DECRYPT_OK) - rx_status->flag |= RX_FLAG_DECRYPTED; - if ((hdr->decrypt_status == P54_DECRYPT_FAIL_MICHAEL) || - (hdr->decrypt_status == P54_DECRYPT_FAIL_TKIP)) - rx_status->flag |= RX_FLAG_MMIC_ERROR; - - rx_status->signal = p54_rssi_to_dbm(priv, hdr->rssi); - rx_status->noise = priv->noise; - if (hdr->rate & 0x10) - rx_status->flag |= RX_FLAG_SHORTPRE; - if (priv->hw->conf.channel->band == IEEE80211_BAND_5GHZ) - rx_status->rate_idx = (rate < 4) ? 0 : rate - 4; - else - rx_status->rate_idx = rate; - - rx_status->freq = freq; - rx_status->band = priv->hw->conf.channel->band; - rx_status->antenna = hdr->antenna; - - tsf32 = le32_to_cpu(hdr->tsf32); - if (tsf32 < priv->tsf_low32) - priv->tsf_high32++; - rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32; - priv->tsf_low32 = tsf32; - - rx_status->flag |= RX_FLAG_TSFT; - - if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) - header_len += hdr->align[0]; - - skb_pull(skb, header_len); - skb_trim(skb, le16_to_cpu(hdr->len)); - if (unlikely(priv->hw->conf.flags & IEEE80211_CONF_PS)) - p54_pspoll_workaround(priv, skb); - - ieee80211_rx_irqsafe(priv->hw, skb); - - ieee80211_queue_delayed_work(priv->hw, &priv->work, - msecs_to_jiffies(P54_STATISTICS_UPDATE)); - - return -1; -} - -static void p54_rx_frame_sent(struct p54_common *priv, struct sk_buff *skb) -{ - struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - struct p54_frame_sent *payload = (struct p54_frame_sent *) hdr->data; - struct ieee80211_tx_info *info; - struct p54_hdr *entry_hdr; - struct p54_tx_data *entry_data; - struct sk_buff *entry; - unsigned int pad = 0, frame_len; - int count, idx; - - entry = p54_find_and_unlink_skb(priv, hdr->req_id); - if (unlikely(!entry)) - return ; - - frame_len = entry->len; - info = IEEE80211_SKB_CB(entry); - entry_hdr = (struct p54_hdr *) entry->data; - entry_data = (struct p54_tx_data *) entry_hdr->data; - priv->stats.dot11ACKFailureCount += payload->tries - 1; - - /* - * Frames in P54_QUEUE_FWSCAN and P54_QUEUE_BEACON are - * generated by the driver. Therefore tx_status is bogus - * and we don't want to confuse the mac80211 stack. - */ - if (unlikely(entry_data->hw_queue < P54_QUEUE_FWSCAN)) { - dev_kfree_skb_any(entry); - return ; - } - - /* - * Clear manually, ieee80211_tx_info_clear_status would - * clear the counts too and we need them. - */ - memset(&info->status.ampdu_ack_len, 0, - sizeof(struct ieee80211_tx_info) - - offsetof(struct ieee80211_tx_info, status.ampdu_ack_len)); - BUILD_BUG_ON(offsetof(struct ieee80211_tx_info, - status.ampdu_ack_len) != 23); - - if (entry_hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN)) - pad = entry_data->align[0]; - - /* walk through the rates array and adjust the counts */ - count = payload->tries; - for (idx = 0; idx < 4; idx++) { - if (count >= info->status.rates[idx].count) { - count -= info->status.rates[idx].count; - } else if (count > 0) { - info->status.rates[idx].count = count; - count = 0; - } else { - info->status.rates[idx].idx = -1; - info->status.rates[idx].count = 0; - } - } - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - !(payload->status & P54_TX_FAILED)) - info->flags |= IEEE80211_TX_STAT_ACK; - if (payload->status & P54_TX_PSM_CANCELLED) - info->flags |= IEEE80211_TX_STAT_TX_FILTERED; - info->status.ack_signal = p54_rssi_to_dbm(priv, - (int)payload->ack_rssi); - - /* Undo all changes to the frame. */ - switch (entry_data->key_type) { - case P54_CRYPTO_TKIPMICHAEL: { - u8 *iv = (u8 *)(entry_data->align + pad + - entry_data->crypt_offset); - - /* Restore the original TKIP IV. */ - iv[2] = iv[0]; - iv[0] = iv[1]; - iv[1] = (iv[0] | 0x20) & 0x7f; /* WEPSeed - 8.3.2.2 */ - - frame_len -= 12; /* remove TKIP_MMIC + TKIP_ICV */ - break; - } - case P54_CRYPTO_AESCCMP: - frame_len -= 8; /* remove CCMP_MIC */ - break; - case P54_CRYPTO_WEP: - frame_len -= 4; /* remove WEP_ICV */ - break; - } - - skb_trim(entry, frame_len); - skb_pull(entry, sizeof(*hdr) + pad + sizeof(*entry_data)); - ieee80211_tx_status_irqsafe(priv->hw, entry); -} - -static void p54_rx_eeprom_readback(struct p54_common *priv, - struct sk_buff *skb) -{ - struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - struct p54_eeprom_lm86 *eeprom = (struct p54_eeprom_lm86 *) hdr->data; - struct sk_buff *tmp; - - if (!priv->eeprom) - return ; - - if (priv->fw_var >= 0x509) { - memcpy(priv->eeprom, eeprom->v2.data, - le16_to_cpu(eeprom->v2.len)); - } else { - memcpy(priv->eeprom, eeprom->v1.data, - le16_to_cpu(eeprom->v1.len)); - } - - priv->eeprom = NULL; - tmp = p54_find_and_unlink_skb(priv, hdr->req_id); - dev_kfree_skb_any(tmp); - complete(&priv->eeprom_comp); -} - -static void p54_rx_stats(struct p54_common *priv, struct sk_buff *skb) -{ - struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - struct p54_statistics *stats = (struct p54_statistics *) hdr->data; - struct sk_buff *tmp; - u32 tsf32; - - if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) - return ; - - tsf32 = le32_to_cpu(stats->tsf32); - if (tsf32 < priv->tsf_low32) - priv->tsf_high32++; - priv->tsf_low32 = tsf32; - - priv->stats.dot11RTSFailureCount = le32_to_cpu(stats->rts_fail); - priv->stats.dot11RTSSuccessCount = le32_to_cpu(stats->rts_success); - priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs); - - priv->noise = p54_rssi_to_dbm(priv, le32_to_cpu(stats->noise)); - - tmp = p54_find_and_unlink_skb(priv, hdr->req_id); - dev_kfree_skb_any(tmp); -} - -static void p54_rx_trap(struct p54_common *priv, struct sk_buff *skb) -{ - struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - struct p54_trap *trap = (struct p54_trap *) hdr->data; - u16 event = le16_to_cpu(trap->event); - u16 freq = le16_to_cpu(trap->frequency); - - switch (event) { - case P54_TRAP_BEACON_TX: - break; - case P54_TRAP_RADAR: - printk(KERN_INFO "%s: radar (freq:%d MHz)\n", - wiphy_name(priv->hw->wiphy), freq); - break; - case P54_TRAP_NO_BEACON: - if (priv->vif) - ieee80211_beacon_loss(priv->vif); - break; - case P54_TRAP_SCAN: - break; - case P54_TRAP_TBTT: - break; - case P54_TRAP_TIMER: - break; - case P54_TRAP_FAA_RADIO_OFF: - wiphy_rfkill_set_hw_state(priv->hw->wiphy, true); - break; - case P54_TRAP_FAA_RADIO_ON: - wiphy_rfkill_set_hw_state(priv->hw->wiphy, false); - break; - default: - printk(KERN_INFO "%s: received event:%x freq:%d\n", - wiphy_name(priv->hw->wiphy), event, freq); - break; - } -} - -static int p54_rx_control(struct p54_common *priv, struct sk_buff *skb) -{ - struct p54_hdr *hdr = (struct p54_hdr *) skb->data; - - switch (le16_to_cpu(hdr->type)) { - case P54_CONTROL_TYPE_TXDONE: - p54_rx_frame_sent(priv, skb); - break; - case P54_CONTROL_TYPE_TRAP: - p54_rx_trap(priv, skb); - break; - case P54_CONTROL_TYPE_BBP: - break; - case P54_CONTROL_TYPE_STAT_READBACK: - p54_rx_stats(priv, skb); - break; - case P54_CONTROL_TYPE_EEPROM_READBACK: - p54_rx_eeprom_readback(priv, skb); - break; - default: - printk(KERN_DEBUG "%s: not handling 0x%02x type control frame\n", - wiphy_name(priv->hw->wiphy), le16_to_cpu(hdr->type)); - break; - } - return 0; -} - -/* returns zero if skb can be reused */ -int p54_rx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54_common *priv = dev->priv; - u16 type = le16_to_cpu(*((__le16 *)skb->data)); - - if (type & P54_HDR_FLAG_CONTROL) - return p54_rx_control(priv, skb); - else - return p54_rx_data(priv, skb); -} -EXPORT_SYMBOL_GPL(p54_rx); - -static void p54_tx_80211_header(struct p54_common *priv, struct sk_buff *skb, - struct ieee80211_tx_info *info, u8 *queue, - u32 *extra_len, u16 *flags, u16 *aid, - bool *burst_possible) -{ - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - if (ieee80211_is_data_qos(hdr->frame_control)) - *burst_possible = true; - else - *burst_possible = false; - - if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) - *flags |= P54_HDR_FLAG_DATA_OUT_SEQNR; - - if (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE) - *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; - - if (info->flags & IEEE80211_TX_CTL_CLEAR_PS_FILT) - *flags |= P54_HDR_FLAG_DATA_OUT_NOCANCEL; - - *queue = skb_get_queue_mapping(skb) + P54_QUEUE_DATA; - - switch (priv->mode) { - case NL80211_IFTYPE_MONITOR: - /* - * We have to set P54_HDR_FLAG_DATA_OUT_PROMISC for - * every frame in promiscuous/monitor mode. - * see STSW45x0C LMAC API - page 12. - */ - *aid = 0; - *flags |= P54_HDR_FLAG_DATA_OUT_PROMISC; - break; - case NL80211_IFTYPE_STATION: - *aid = 1; - break; - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { - *aid = 0; - *queue = P54_QUEUE_CAB; - return; - } - - if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) { - if (ieee80211_is_probe_resp(hdr->frame_control)) { - *aid = 0; - *flags |= P54_HDR_FLAG_DATA_OUT_TIMESTAMP | - P54_HDR_FLAG_DATA_OUT_NOCANCEL; - return; - } else if (ieee80211_is_beacon(hdr->frame_control)) { - *aid = 0; - - if (info->flags & IEEE80211_TX_CTL_INJECTED) { - /* - * Injecting beacons on top of a AP is - * not a good idea... nevertheless, - * it should be doable. - */ - - return; - } - - *flags |= P54_HDR_FLAG_DATA_OUT_TIMESTAMP; - *queue = P54_QUEUE_BEACON; - *extra_len = IEEE80211_MAX_TIM_LEN; - return; - } - } - - if (info->control.sta) - *aid = info->control.sta->aid; - break; - } -} - -static u8 p54_convert_algo(enum ieee80211_key_alg alg) -{ - switch (alg) { - case ALG_WEP: - return P54_CRYPTO_WEP; - case ALG_TKIP: - return P54_CRYPTO_TKIPMICHAEL; - case ALG_CCMP: - return P54_CRYPTO_AESCCMP; - default: - return 0; - } -} - -int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct p54_common *priv = dev->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct p54_tx_info *p54info; - struct p54_hdr *hdr; - struct p54_tx_data *txhdr; - unsigned int padding, len, extra_len; - int i, j, ridx; - u16 hdr_flags = 0, aid = 0; - u8 rate, queue = 0, crypt_offset = 0; - u8 cts_rate = 0x20; - u8 rc_flags; - u8 calculated_tries[4]; - u8 nrates = 0, nremaining = 8; - bool burst_allowed = false; - - p54_tx_80211_header(priv, skb, info, &queue, &extra_len, - &hdr_flags, &aid, &burst_allowed); - - if (p54_tx_qos_accounting_alloc(priv, skb, queue)) { - if (!IS_QOS_QUEUE(queue)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } else { - return NETDEV_TX_BUSY; - } - } - - padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3; - len = skb->len; - - if (info->control.hw_key) { - crypt_offset = ieee80211_get_hdrlen_from_skb(skb); - if (info->control.hw_key->alg == ALG_TKIP) { - u8 *iv = (u8 *)(skb->data + crypt_offset); - /* - * The firmware excepts that the IV has to have - * this special format - */ - iv[1] = iv[0]; - iv[0] = iv[2]; - iv[2] = 0; - } - } - - txhdr = (struct p54_tx_data *) skb_push(skb, sizeof(*txhdr) + padding); - hdr = (struct p54_hdr *) skb_push(skb, sizeof(*hdr)); - - if (padding) - hdr_flags |= P54_HDR_FLAG_DATA_ALIGN; - hdr->type = cpu_to_le16(aid); - hdr->rts_tries = info->control.rates[0].count; - - /* - * we register the rates in perfect order, and - * RTS/CTS won't happen on 5 GHz - */ - cts_rate = info->control.rts_cts_rate_idx; - - memset(&txhdr->rateset, 0, sizeof(txhdr->rateset)); - - /* see how many rates got used */ - for (i = 0; i < dev->max_rates; i++) { - if (info->control.rates[i].idx < 0) - break; - nrates++; - } - - /* limit tries to 8/nrates per rate */ - for (i = 0; i < nrates; i++) { - /* - * The magic expression here is equivalent to 8/nrates for - * all values that matter, but avoids division and jumps. - * Note that nrates can only take the values 1 through 4. - */ - calculated_tries[i] = min_t(int, ((15 >> nrates) | 1) + 1, - info->control.rates[i].count); - nremaining -= calculated_tries[i]; - } - - /* if there are tries left, distribute from back to front */ - for (i = nrates - 1; nremaining > 0 && i >= 0; i--) { - int tmp = info->control.rates[i].count - calculated_tries[i]; - - if (tmp <= 0) - continue; - /* RC requested more tries at this rate */ - - tmp = min_t(int, tmp, nremaining); - calculated_tries[i] += tmp; - nremaining -= tmp; - } - - ridx = 0; - for (i = 0; i < nrates && ridx < 8; i++) { - /* we register the rates in perfect order */ - rate = info->control.rates[i].idx; - if (info->band == IEEE80211_BAND_5GHZ) - rate += 4; - - /* store the count we actually calculated for TX status */ - info->control.rates[i].count = calculated_tries[i]; - - rc_flags = info->control.rates[i].flags; - if (rc_flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) { - rate |= 0x10; - cts_rate |= 0x10; - } - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - burst_allowed = false; - rate |= 0x40; - } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - rate |= 0x20; - burst_allowed = false; - } - for (j = 0; j < calculated_tries[i] && ridx < 8; j++) { - txhdr->rateset[ridx] = rate; - ridx++; - } - } - - if (burst_allowed) - hdr_flags |= P54_HDR_FLAG_DATA_OUT_BURST; - - /* TODO: enable bursting */ - hdr->flags = cpu_to_le16(hdr_flags); - hdr->tries = ridx; - txhdr->rts_rate_idx = 0; - if (info->control.hw_key) { - txhdr->key_type = p54_convert_algo(info->control.hw_key->alg); - txhdr->key_len = min((u8)16, info->control.hw_key->keylen); - memcpy(txhdr->key, info->control.hw_key->key, txhdr->key_len); - if (info->control.hw_key->alg == ALG_TKIP) { - /* reserve space for the MIC key */ - len += 8; - memcpy(skb_put(skb, 8), &(info->control.hw_key->key - [NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY]), 8); - } - /* reserve some space for ICV */ - len += info->control.hw_key->icv_len; - memset(skb_put(skb, info->control.hw_key->icv_len), 0, - info->control.hw_key->icv_len); - } else { - txhdr->key_type = 0; - txhdr->key_len = 0; - } - txhdr->crypt_offset = crypt_offset; - txhdr->hw_queue = queue; - txhdr->backlog = priv->tx_stats[queue].len - 1; - memset(txhdr->durations, 0, sizeof(txhdr->durations)); - txhdr->tx_antenna = ((info->antenna_sel_tx == 0) ? - 2 : info->antenna_sel_tx - 1) & priv->tx_diversity_mask; - if (priv->rxhw == 5) { - txhdr->longbow.cts_rate = cts_rate; - txhdr->longbow.output_power = cpu_to_le16(priv->output_power); - } else { - txhdr->normal.output_power = priv->output_power; - txhdr->normal.cts_rate = cts_rate; - } - if (padding) - txhdr->align[0] = padding; - - hdr->len = cpu_to_le16(len); - /* modifies skb->cb and with it info, so must be last! */ - p54info = (void *) info->rate_driver_data; - p54info->extra_len = extra_len; - - p54_tx(priv, skb); - return NETDEV_TX_OK; -} diff --git a/drivers/net/wireless/prism54/Makefile b/drivers/net/wireless/prism54/Makefile deleted file mode 100644 index fad305c76737..000000000000 --- a/drivers/net/wireless/prism54/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $Id: Makefile.k26,v 1.7 2004/01/30 16:24:00 ajfa Exp $ - -prism54-objs := islpci_eth.o islpci_mgt.o \ - isl_38xx.o isl_ioctl.o islpci_dev.o \ - islpci_hotplug.o oid_mgt.o - -obj-$(CONFIG_PRISM54) += prism54.o - diff --git a/drivers/net/wireless/prism54/isl_38xx.c b/drivers/net/wireless/prism54/isl_38xx.c deleted file mode 100644 index 02fc67bccbd0..000000000000 --- a/drivers/net/wireless/prism54/isl_38xx.c +++ /dev/null @@ -1,256 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright (C) 2003-2004 Luis R. Rodriguez _ - * - * 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 - * - * 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 - * - */ - -#include -#include -#include - -#include -#include - -#include "prismcompat.h" -#include "isl_38xx.h" -#include "islpci_dev.h" -#include "islpci_mgt.h" - -/****************************************************************************** - Device Interface & Control functions -******************************************************************************/ - -/** - * isl38xx_disable_interrupts - disable all interrupts - * @device: pci memory base address - * - * Instructs the device to disable all interrupt reporting by asserting - * the IRQ line. New events may still show up in the interrupt identification - * register located at offset %ISL38XX_INT_IDENT_REG. - */ -void -isl38xx_disable_interrupts(void __iomem *device) -{ - isl38xx_w32_flush(device, 0x00000000, ISL38XX_INT_EN_REG); - udelay(ISL38XX_WRITEIO_DELAY); -} - -void -isl38xx_handle_sleep_request(isl38xx_control_block *control_block, - int *powerstate, void __iomem *device_base) -{ - /* device requests to go into sleep mode - * check whether the transmit queues for data and management are empty */ - if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ)) - /* data tx queue not empty */ - return; - - if (isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) - /* management tx queue not empty */ - return; - - /* check also whether received frames are pending */ - if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_DATA_LQ)) - /* data rx queue not empty */ - return; - - if (isl38xx_in_queue(control_block, ISL38XX_CB_RX_MGMTQ)) - /* management rx queue not empty */ - return; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "Device going to sleep mode\n"); -#endif - - /* all queues are empty, allow the device to go into sleep mode */ - *powerstate = ISL38XX_PSM_POWERSAVE_STATE; - - /* assert the Sleep interrupt in the Device Interrupt Register */ - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_SLEEP, - ISL38XX_DEV_INT_REG); - udelay(ISL38XX_WRITEIO_DELAY); -} - -void -isl38xx_handle_wakeup(isl38xx_control_block *control_block, - int *powerstate, void __iomem *device_base) -{ - /* device is in active state, update the powerstate flag */ - *powerstate = ISL38XX_PSM_ACTIVE_STATE; - - /* now check whether there are frames pending for the card */ - if (!isl38xx_in_queue(control_block, ISL38XX_CB_TX_DATA_LQ) - && !isl38xx_in_queue(control_block, ISL38XX_CB_TX_MGMTQ)) - return; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_ANYTHING, "Wake up handler trigger the device\n"); -#endif - - /* either data or management transmit queue has a frame pending - * trigger the device by setting the Update bit in the Device Int reg */ - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, - ISL38XX_DEV_INT_REG); - udelay(ISL38XX_WRITEIO_DELAY); -} - -void -isl38xx_trigger_device(int asleep, void __iomem *device_base) -{ - u32 reg; - -#if VERBOSE > SHOW_ERROR_MESSAGES - u32 counter = 0; - struct timeval current_time; - DEBUG(SHOW_FUNCTION_CALLS, "isl38xx trigger device\n"); -#endif - - /* check whether the device is in power save mode */ - if (asleep) { - /* device is in powersave, trigger the device for wakeup */ -#if VERBOSE > SHOW_ERROR_MESSAGES - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, "%08li.%08li Device wakeup triggered\n", - current_time.tv_sec, (long)current_time.tv_usec); - - DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, - readl(device_base + ISL38XX_CTRL_STAT_REG)); -#endif - - reg = readl(device_base + ISL38XX_INT_IDENT_REG); - if (reg == 0xabadface) { -#if VERBOSE > SHOW_ERROR_MESSAGES - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, - "%08li.%08li Device register abadface\n", - current_time.tv_sec, (long)current_time.tv_usec); -#endif - /* read the Device Status Register until Sleepmode bit is set */ - while (reg = readl(device_base + ISL38XX_CTRL_STAT_REG), - (reg & ISL38XX_CTRL_STAT_SLEEPMODE) == 0) { - udelay(ISL38XX_WRITEIO_DELAY); -#if VERBOSE > SHOW_ERROR_MESSAGES - counter++; -#endif - } - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, - readl(device_base + ISL38XX_CTRL_STAT_REG)); - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, - "%08li.%08li Device asleep counter %i\n", - current_time.tv_sec, (long)current_time.tv_usec, - counter); -#endif - } - /* assert the Wakeup interrupt in the Device Interrupt Register */ - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_WAKEUP, - ISL38XX_DEV_INT_REG); - -#if VERBOSE > SHOW_ERROR_MESSAGES - udelay(ISL38XX_WRITEIO_DELAY); - - /* perform another read on the Device Status Register */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - do_gettimeofday(¤t_time); - DEBUG(SHOW_TRACING, "%08li.%08li Device register read %08x\n", - current_time.tv_sec, (long)current_time.tv_usec, reg); -#endif - } else { - /* device is (still) awake */ -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "Device is in active state\n"); -#endif - /* trigger the device by setting the Update bit in the Device Int reg */ - - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_UPDATE, - ISL38XX_DEV_INT_REG); - } -} - -void -isl38xx_interface_reset(void __iomem *device_base, dma_addr_t host_address) -{ -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "isl38xx_interface_reset\n"); -#endif - - /* load the address of the control block in the device */ - isl38xx_w32_flush(device_base, host_address, ISL38XX_CTRL_BLK_BASE_REG); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the reset bit in the Device Interrupt Register */ - isl38xx_w32_flush(device_base, ISL38XX_DEV_INT_RESET, ISL38XX_DEV_INT_REG); - udelay(ISL38XX_WRITEIO_DELAY); - - /* enable the interrupt for detecting initialization */ - - /* Note: Do not enable other interrupts here. We want the - * device to have come up first 100% before allowing any other - * interrupts. */ - isl38xx_w32_flush(device_base, ISL38XX_INT_IDENT_INIT, ISL38XX_INT_EN_REG); - udelay(ISL38XX_WRITEIO_DELAY); /* allow complete full reset */ -} - -void -isl38xx_enable_common_interrupts(void __iomem *device_base) -{ - u32 reg; - - reg = ISL38XX_INT_IDENT_UPDATE | ISL38XX_INT_IDENT_SLEEP | - ISL38XX_INT_IDENT_WAKEUP; - isl38xx_w32_flush(device_base, reg, ISL38XX_INT_EN_REG); - udelay(ISL38XX_WRITEIO_DELAY); -} - -int -isl38xx_in_queue(isl38xx_control_block *cb, int queue) -{ - const s32 delta = (le32_to_cpu(cb->driver_curr_frag[queue]) - - le32_to_cpu(cb->device_curr_frag[queue])); - - /* determine the amount of fragments in the queue depending on the type - * of the queue, either transmit or receive */ - - BUG_ON(delta < 0); /* driver ptr must be ahead of device ptr */ - - switch (queue) { - /* send queues */ - case ISL38XX_CB_TX_MGMTQ: - BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); - - case ISL38XX_CB_TX_DATA_LQ: - case ISL38XX_CB_TX_DATA_HQ: - BUG_ON(delta > ISL38XX_CB_TX_QSIZE); - return delta; - - /* receive queues */ - case ISL38XX_CB_RX_MGMTQ: - BUG_ON(delta > ISL38XX_CB_MGMT_QSIZE); - return ISL38XX_CB_MGMT_QSIZE - delta; - - case ISL38XX_CB_RX_DATA_LQ: - case ISL38XX_CB_RX_DATA_HQ: - BUG_ON(delta > ISL38XX_CB_RX_QSIZE); - return ISL38XX_CB_RX_QSIZE - delta; - } - BUG(); - return 0; -} diff --git a/drivers/net/wireless/prism54/isl_38xx.h b/drivers/net/wireless/prism54/isl_38xx.h deleted file mode 100644 index 19c33d313734..000000000000 --- a/drivers/net/wireless/prism54/isl_38xx.h +++ /dev/null @@ -1,171 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * - * 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 - * - * 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 - * - */ - -#ifndef _ISL_38XX_H -#define _ISL_38XX_H - -#include -#include - -#define ISL38XX_CB_RX_QSIZE 8 -#define ISL38XX_CB_TX_QSIZE 32 - -/* ISL38XX Access Point Specific definitions */ -#define ISL38XX_MAX_WDS_LINKS 8 - -/* ISL38xx Client Specific definitions */ -#define ISL38XX_PSM_ACTIVE_STATE 0 -#define ISL38XX_PSM_POWERSAVE_STATE 1 - -/* ISL38XX Host Interface Definitions */ -#define ISL38XX_PCI_MEM_SIZE 0x02000 -#define ISL38XX_MEMORY_WINDOW_SIZE 0x01000 -#define ISL38XX_DEV_FIRMWARE_ADDRES 0x20000 -#define ISL38XX_WRITEIO_DELAY 10 /* in us */ -#define ISL38XX_RESET_DELAY 50 /* in ms */ -#define ISL38XX_WAIT_CYCLE 10 /* in 10ms */ -#define ISL38XX_MAX_WAIT_CYCLES 10 - -/* PCI Memory Area */ -#define ISL38XX_HARDWARE_REG 0x0000 -#define ISL38XX_CARDBUS_CIS 0x0800 -#define ISL38XX_DIRECT_MEM_WIN 0x1000 - -/* Hardware registers */ -#define ISL38XX_DEV_INT_REG 0x0000 -#define ISL38XX_INT_IDENT_REG 0x0010 -#define ISL38XX_INT_ACK_REG 0x0014 -#define ISL38XX_INT_EN_REG 0x0018 -#define ISL38XX_GEN_PURP_COM_REG_1 0x0020 -#define ISL38XX_GEN_PURP_COM_REG_2 0x0024 -#define ISL38XX_CTRL_BLK_BASE_REG ISL38XX_GEN_PURP_COM_REG_1 -#define ISL38XX_DIR_MEM_BASE_REG 0x0030 -#define ISL38XX_CTRL_STAT_REG 0x0078 - -/* High end mobos queue up pci writes, the following - * is used to "read" from after a write to force flush */ -#define ISL38XX_PCI_POSTING_FLUSH ISL38XX_INT_EN_REG - -/** - * isl38xx_w32_flush - PCI iomem write helper - * @base: (host) memory base address of the device - * @val: 32bit value (host order) to write - * @offset: byte offset into @base to write value to - * - * This helper takes care of writing a 32bit datum to the - * specified offset into the device's pci memory space, and making sure - * the pci memory buffers get flushed by performing one harmless read - * from the %ISL38XX_PCI_POSTING_FLUSH offset. - */ -static inline void -isl38xx_w32_flush(void __iomem *base, u32 val, unsigned long offset) -{ - writel(val, base + offset); - (void) readl(base + ISL38XX_PCI_POSTING_FLUSH); -} - -/* Device Interrupt register bits */ -#define ISL38XX_DEV_INT_RESET 0x0001 -#define ISL38XX_DEV_INT_UPDATE 0x0002 -#define ISL38XX_DEV_INT_WAKEUP 0x0008 -#define ISL38XX_DEV_INT_SLEEP 0x0010 - -/* Interrupt Identification/Acknowledge/Enable register bits */ -#define ISL38XX_INT_IDENT_UPDATE 0x0002 -#define ISL38XX_INT_IDENT_INIT 0x0004 -#define ISL38XX_INT_IDENT_WAKEUP 0x0008 -#define ISL38XX_INT_IDENT_SLEEP 0x0010 -#define ISL38XX_INT_SOURCES 0x001E - -/* Control/Status register bits */ -/* Looks like there are other meaningful bits - 0x20004400 seen in normal operation, - 0x200044db at 'timeout waiting for mgmt response' -*/ -#define ISL38XX_CTRL_STAT_SLEEPMODE 0x00000200 -#define ISL38XX_CTRL_STAT_CLKRUN 0x00800000 -#define ISL38XX_CTRL_STAT_RESET 0x10000000 -#define ISL38XX_CTRL_STAT_RAMBOOT 0x20000000 -#define ISL38XX_CTRL_STAT_STARTHALTED 0x40000000 -#define ISL38XX_CTRL_STAT_HOST_OVERRIDE 0x80000000 - -/* Control Block definitions */ -#define ISL38XX_CB_RX_DATA_LQ 0 -#define ISL38XX_CB_TX_DATA_LQ 1 -#define ISL38XX_CB_RX_DATA_HQ 2 -#define ISL38XX_CB_TX_DATA_HQ 3 -#define ISL38XX_CB_RX_MGMTQ 4 -#define ISL38XX_CB_TX_MGMTQ 5 -#define ISL38XX_CB_QCOUNT 6 -#define ISL38XX_CB_MGMT_QSIZE 4 -#define ISL38XX_MIN_QTHRESHOLD 4 /* fragments */ - -/* Memory Manager definitions */ -#define MGMT_FRAME_SIZE 1500 /* >= size struct obj_bsslist */ -#define MGMT_TX_FRAME_COUNT 24 /* max 4 + spare 4 + 8 init */ -#define MGMT_RX_FRAME_COUNT 24 /* 4*4 + spare 8 */ -#define MGMT_FRAME_COUNT (MGMT_TX_FRAME_COUNT + MGMT_RX_FRAME_COUNT) -#define CONTROL_BLOCK_SIZE 1024 /* should be enough */ -#define PSM_FRAME_SIZE 1536 -#define PSM_MINIMAL_STATION_COUNT 64 -#define PSM_FRAME_COUNT PSM_MINIMAL_STATION_COUNT -#define PSM_BUFFER_SIZE PSM_FRAME_SIZE * PSM_FRAME_COUNT -#define MAX_TRAP_RX_QUEUE 4 -#define HOST_MEM_BLOCK CONTROL_BLOCK_SIZE + PSM_BUFFER_SIZE - -/* Fragment package definitions */ -#define FRAGMENT_FLAG_MF 0x0001 -#define MAX_FRAGMENT_SIZE 1536 - -/* In monitor mode frames have a header. I don't know exactly how big those - * frame can be but I've never seen any frame bigger than 1584... : - */ -#define MAX_FRAGMENT_SIZE_RX 1600 - -typedef struct { - __le32 address; /* physical address on host */ - __le16 size; /* packet size */ - __le16 flags; /* set of bit-wise flags */ -} isl38xx_fragment; - -struct isl38xx_cb { - __le32 driver_curr_frag[ISL38XX_CB_QCOUNT]; - __le32 device_curr_frag[ISL38XX_CB_QCOUNT]; - isl38xx_fragment rx_data_low[ISL38XX_CB_RX_QSIZE]; - isl38xx_fragment tx_data_low[ISL38XX_CB_TX_QSIZE]; - isl38xx_fragment rx_data_high[ISL38XX_CB_RX_QSIZE]; - isl38xx_fragment tx_data_high[ISL38XX_CB_TX_QSIZE]; - isl38xx_fragment rx_data_mgmt[ISL38XX_CB_MGMT_QSIZE]; - isl38xx_fragment tx_data_mgmt[ISL38XX_CB_MGMT_QSIZE]; -}; - -typedef struct isl38xx_cb isl38xx_control_block; - -/* determine number of entries currently in queue */ -int isl38xx_in_queue(isl38xx_control_block *cb, int queue); - -void isl38xx_disable_interrupts(void __iomem *); -void isl38xx_enable_common_interrupts(void __iomem *); - -void isl38xx_handle_sleep_request(isl38xx_control_block *, int *, - void __iomem *); -void isl38xx_handle_wakeup(isl38xx_control_block *, int *, void __iomem *); -void isl38xx_trigger_device(int, void __iomem *); -void isl38xx_interface_reset(void __iomem *, dma_addr_t); - -#endif /* _ISL_38XX_H */ diff --git a/drivers/net/wireless/prism54/isl_ioctl.c b/drivers/net/wireless/prism54/isl_ioctl.c deleted file mode 100644 index bc08464d8323..000000000000 --- a/drivers/net/wireless/prism54/isl_ioctl.c +++ /dev/null @@ -1,3248 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * (C) 2003,2004 Aurelien Alleaume - * (C) 2003 Herbert Valerio Riedel - * (C) 2003 Luis R. Rodriguez - * - * 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 - * - * 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 - * - */ - -#include -#include -#include -#include -#include - -#include - -#include "prismcompat.h" -#include "isl_ioctl.h" -#include "islpci_mgt.h" -#include "isl_oid.h" /* additional types and defs for isl38xx fw */ -#include "oid_mgt.h" - -#include /* New driver API */ - -#define KEY_SIZE_WEP104 13 /* 104/128-bit WEP keys */ -#define KEY_SIZE_WEP40 5 /* 40/64-bit WEP keys */ -/* KEY_SIZE_TKIP should match isl_oid.h, struct obj_key.key[] size */ -#define KEY_SIZE_TKIP 32 /* TKIP keys */ - -static void prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, - u8 *wpa_ie, size_t wpa_ie_len); -static size_t prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie); -static int prism54_set_wpa(struct net_device *, struct iw_request_info *, - __u32 *, char *); - -/* In 500 kbps */ -static const unsigned char scan_rate_list[] = { 2, 4, 11, 22, - 12, 18, 24, 36, - 48, 72, 96, 108 }; - -/** - * prism54_mib_mode_helper - MIB change mode helper function - * @mib: the &struct islpci_mib object to modify - * @iw_mode: new mode (%IW_MODE_*) - * - * This is a helper function, hence it does not lock. Make sure - * caller deals with locking *if* necessary. This function sets the - * mode-dependent mib values and does the mapping of the Linux - * Wireless API modes to Device firmware modes. It also checks for - * correct valid Linux wireless modes. - */ -static int -prism54_mib_mode_helper(islpci_private *priv, u32 iw_mode) -{ - u32 config = INL_CONFIG_MANUALRUN; - u32 mode, bsstype; - - /* For now, just catch early the Repeater and Secondary modes here */ - if (iw_mode == IW_MODE_REPEAT || iw_mode == IW_MODE_SECOND) { - printk(KERN_DEBUG - "%s(): Sorry, Repeater mode and Secondary mode " - "are not yet supported by this driver.\n", __func__); - return -EINVAL; - } - - priv->iw_mode = iw_mode; - - switch (iw_mode) { - case IW_MODE_AUTO: - mode = INL_MODE_CLIENT; - bsstype = DOT11_BSSTYPE_ANY; - break; - case IW_MODE_ADHOC: - mode = INL_MODE_CLIENT; - bsstype = DOT11_BSSTYPE_IBSS; - break; - case IW_MODE_INFRA: - mode = INL_MODE_CLIENT; - bsstype = DOT11_BSSTYPE_INFRA; - break; - case IW_MODE_MASTER: - mode = INL_MODE_AP; - bsstype = DOT11_BSSTYPE_INFRA; - break; - case IW_MODE_MONITOR: - mode = INL_MODE_PROMISCUOUS; - bsstype = DOT11_BSSTYPE_ANY; - config |= INL_CONFIG_RXANNEX; - break; - default: - return -EINVAL; - } - - if (init_wds) - config |= INL_CONFIG_WDS; - mgt_set(priv, DOT11_OID_BSSTYPE, &bsstype); - mgt_set(priv, OID_INL_CONFIG, &config); - mgt_set(priv, OID_INL_MODE, &mode); - - return 0; -} - -/** - * prism54_mib_init - fill MIB cache with defaults - * - * this function initializes the struct given as @mib with defaults, - * of which many are retrieved from the global module parameter - * variables. - */ - -void -prism54_mib_init(islpci_private *priv) -{ - u32 channel, authen, wep, filter, dot1x, mlme, conformance, power, mode; - struct obj_buffer psm_buffer = { - .size = PSM_BUFFER_SIZE, - .addr = priv->device_psm_buffer - }; - - channel = CARD_DEFAULT_CHANNEL; - authen = CARD_DEFAULT_AUTHEN; - wep = CARD_DEFAULT_WEP; - filter = CARD_DEFAULT_FILTER; /* (0) Do not filter un-encrypted data */ - dot1x = CARD_DEFAULT_DOT1X; - mlme = CARD_DEFAULT_MLME_MODE; - conformance = CARD_DEFAULT_CONFORMANCE; - power = 127; - mode = CARD_DEFAULT_IW_MODE; - - mgt_set(priv, DOT11_OID_CHANNEL, &channel); - mgt_set(priv, DOT11_OID_AUTHENABLE, &authen); - mgt_set(priv, DOT11_OID_PRIVACYINVOKED, &wep); - mgt_set(priv, DOT11_OID_PSMBUFFER, &psm_buffer); - mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &filter); - mgt_set(priv, DOT11_OID_DOT1XENABLE, &dot1x); - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlme); - mgt_set(priv, OID_INL_DOT11D_CONFORMANCE, &conformance); - mgt_set(priv, OID_INL_OUTPUTPOWER, &power); - - /* This sets all of the mode-dependent values */ - prism54_mib_mode_helper(priv, mode); -} - -/* this will be executed outside of atomic context thanks to - * schedule_work(), thus we can as well use sleeping semaphore - * locking */ -void -prism54_update_stats(struct work_struct *work) -{ - islpci_private *priv = container_of(work, islpci_private, stats_work); - char *data; - int j; - struct obj_bss bss, *bss2; - union oid_res_t r; - - mutex_lock(&priv->stats_lock); - -/* Noise floor. - * I'm not sure if the unit is dBm. - * Note : If we are not connected, this value seems to be irrelevant. */ - - mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); - priv->local_iwstatistics.qual.noise = r.u; - -/* Get the rssi of the link. To do this we need to retrieve a bss. */ - - /* First get the MAC address of the AP we are associated with. */ - mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); - data = r.ptr; - - /* copy this MAC to the bss */ - memcpy(bss.address, data, 6); - kfree(data); - - /* now ask for the corresponding bss */ - j = mgt_get_request(priv, DOT11_OID_BSSFIND, 0, (void *) &bss, &r); - bss2 = r.ptr; - /* report the rssi and use it to calculate - * link quality through a signal-noise - * ratio */ - priv->local_iwstatistics.qual.level = bss2->rssi; - priv->local_iwstatistics.qual.qual = - bss2->rssi - priv->iwstatistics.qual.noise; - - kfree(bss2); - - /* report that the stats are new */ - priv->local_iwstatistics.qual.updated = 0x7; - -/* Rx : unable to decrypt the MPDU */ - mgt_get_request(priv, DOT11_OID_PRIVRXFAILED, 0, NULL, &r); - priv->local_iwstatistics.discard.code = r.u; - -/* Tx : Max MAC retries num reached */ - mgt_get_request(priv, DOT11_OID_MPDUTXFAILED, 0, NULL, &r); - priv->local_iwstatistics.discard.retries = r.u; - - mutex_unlock(&priv->stats_lock); - - return; -} - -struct iw_statistics * -prism54_get_wireless_stats(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - - /* If the stats are being updated return old data */ - if (mutex_trylock(&priv->stats_lock)) { - memcpy(&priv->iwstatistics, &priv->local_iwstatistics, - sizeof (struct iw_statistics)); - /* They won't be marked updated for the next time */ - priv->local_iwstatistics.qual.updated = 0; - mutex_unlock(&priv->stats_lock); - } else - priv->iwstatistics.qual.updated = 0; - - /* Update our wireless stats, but do not schedule to often - * (max 1 HZ) */ - if ((priv->stats_timestamp == 0) || - time_after(jiffies, priv->stats_timestamp + 1 * HZ)) { - schedule_work(&priv->stats_work); - priv->stats_timestamp = jiffies; - } - - return &priv->iwstatistics; -} - -static int -prism54_commit(struct net_device *ndev, struct iw_request_info *info, - char *cwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - /* simply re-set the last set SSID, this should commit most stuff */ - - /* Commit in Monitor mode is not necessary, also setting essid - * in Monitor mode does not make sense and isn't allowed for this - * device's firmware */ - if (priv->iw_mode != IW_MODE_MONITOR) - return mgt_set_request(priv, DOT11_OID_SSID, 0, NULL); - return 0; -} - -static int -prism54_get_name(struct net_device *ndev, struct iw_request_info *info, - char *cwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - char *capabilities; - union oid_res_t r; - int rvalue; - - if (islpci_get_state(priv) < PRV_STATE_INIT) { - strncpy(cwrq, "NOT READY!", IFNAMSIZ); - return 0; - } - rvalue = mgt_get_request(priv, OID_INL_PHYCAPABILITIES, 0, NULL, &r); - - switch (r.u) { - case INL_PHYCAP_5000MHZ: - capabilities = "IEEE 802.11a/b/g"; - break; - case INL_PHYCAP_FAA: - capabilities = "IEEE 802.11b/g - FAA Support"; - break; - case INL_PHYCAP_2400MHZ: - default: - capabilities = "IEEE 802.11b/g"; /* Default */ - break; - } - strncpy(cwrq, capabilities, IFNAMSIZ); - return rvalue; -} - -static int -prism54_set_freq(struct net_device *ndev, struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - int rvalue; - u32 c; - - if (fwrq->m < 1000) - /* we have a channel number */ - c = fwrq->m; - else - c = (fwrq->e == 1) ? channel_of_freq(fwrq->m / 100000) : 0; - - rvalue = c ? mgt_set_request(priv, DOT11_OID_CHANNEL, 0, &c) : -EINVAL; - - /* Call commit handler */ - return (rvalue ? rvalue : -EINPROGRESS); -} - -static int -prism54_get_freq(struct net_device *ndev, struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_CHANNEL, 0, NULL, &r); - fwrq->i = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_FREQUENCY, 0, NULL, &r); - fwrq->m = r.u; - fwrq->e = 3; - - return rvalue; -} - -static int -prism54_set_mode(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 mlmeautolevel = CARD_DEFAULT_MLME_MODE; - - /* Let's see if the user passed a valid Linux Wireless mode */ - if (*uwrq > IW_MODE_MONITOR || *uwrq < IW_MODE_AUTO) { - printk(KERN_DEBUG - "%s: %s() You passed a non-valid init_mode.\n", - priv->ndev->name, __func__); - return -EINVAL; - } - - down_write(&priv->mib_sem); - - if (prism54_mib_mode_helper(priv, *uwrq)) { - up_write(&priv->mib_sem); - return -EOPNOTSUPP; - } - - /* the ACL code needs an intermediate mlmeautolevel. The wpa stuff an - * extended one. - */ - if ((*uwrq == IW_MODE_MASTER) && (priv->acl.policy != MAC_POLICY_OPEN)) - mlmeautolevel = DOT11_MLME_INTERMEDIATE; - if (priv->wpa) - mlmeautolevel = DOT11_MLME_EXTENDED; - - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); - - if (mgt_commit(priv)) { - up_write(&priv->mib_sem); - return -EIO; - } - priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) - ? priv->monitor_type : ARPHRD_ETHER; - up_write(&priv->mib_sem); - - return 0; -} - -/* Use mib cache */ -static int -prism54_get_mode(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - BUG_ON((priv->iw_mode < IW_MODE_AUTO) || (priv->iw_mode > - IW_MODE_MONITOR)); - *uwrq = priv->iw_mode; - - return 0; -} - -/* we use DOT11_OID_EDTHRESHOLD. From what I guess the card will not try to - * emit data if (sensitivity > rssi - noise) (in dBm). - * prism54_set_sens does not seem to work. - */ - -static int -prism54_set_sens(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 sens; - - /* by default the card sets this to 20. */ - sens = vwrq->disabled ? 20 : vwrq->value; - - return mgt_set_request(priv, DOT11_OID_EDTHRESHOLD, 0, &sens); -} - -static int -prism54_get_sens(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_EDTHRESHOLD, 0, NULL, &r); - - vwrq->value = r.u; - vwrq->disabled = (vwrq->value == 0); - vwrq->fixed = 1; - - return rvalue; -} - -static int -prism54_get_range(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct iw_range *range = (struct iw_range *) extra; - islpci_private *priv = netdev_priv(ndev); - u8 *data; - int i, m, rvalue; - struct obj_frequencies *freq; - union oid_res_t r; - - memset(range, 0, sizeof (struct iw_range)); - dwrq->length = sizeof (struct iw_range); - - /* set the wireless extension version number */ - range->we_version_source = SUPPORTED_WIRELESS_EXT; - range->we_version_compiled = WIRELESS_EXT; - - /* Now the encoding capabilities */ - range->num_encoding_sizes = 3; - /* 64(40) bits WEP */ - range->encoding_size[0] = 5; - /* 128(104) bits WEP */ - range->encoding_size[1] = 13; - /* 256 bits for WPA-PSK */ - range->encoding_size[2] = 32; - /* 4 keys are allowed */ - range->max_encoding_tokens = 4; - - /* we don't know the quality range... */ - range->max_qual.level = 0; - range->max_qual.noise = 0; - range->max_qual.qual = 0; - /* these value describe an average quality. Needs more tweaking... */ - range->avg_qual.level = -80; /* -80 dBm */ - range->avg_qual.noise = 0; /* don't know what to put here */ - range->avg_qual.qual = 0; - - range->sensitivity = 200; - - /* retry limit capabilities */ - range->retry_capa = IW_RETRY_LIMIT | IW_RETRY_LIFETIME; - range->retry_flags = IW_RETRY_LIMIT; - range->r_time_flags = IW_RETRY_LIFETIME; - - /* I don't know the range. Put stupid things here */ - range->min_retry = 1; - range->max_retry = 65535; - range->min_r_time = 1024; - range->max_r_time = 65535 * 1024; - - /* txpower is supported in dBm's */ - range->txpower_capa = IW_TXPOW_DBM; - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_K_0 | - IW_EVENT_CAPA_MASK(SIOCGIWTHRSPY) | - IW_EVENT_CAPA_MASK(SIOCGIWAP)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - range->event_capa[4] = IW_EVENT_CAPA_MASK(IWEVCUSTOM); - - range->enc_capa = IW_ENC_CAPA_WPA | IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* Request the device for the supported frequencies - * not really relevant since some devices will report the 5 GHz band - * frequencies even if they don't support them. - */ - rvalue = - mgt_get_request(priv, DOT11_OID_SUPPORTEDFREQUENCIES, 0, NULL, &r); - freq = r.ptr; - - range->num_channels = freq->nr; - range->num_frequency = freq->nr; - - m = min(IW_MAX_FREQUENCIES, (int) freq->nr); - for (i = 0; i < m; i++) { - range->freq[i].m = freq->mhz[i]; - range->freq[i].e = 6; - range->freq[i].i = channel_of_freq(freq->mhz[i]); - } - kfree(freq); - - rvalue |= mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); - data = r.ptr; - - /* We got an array of char. It is NULL terminated. */ - i = 0; - while ((i < IW_MAX_BITRATES) && (*data != 0)) { - /* the result must be in bps. The card gives us 500Kbps */ - range->bitrate[i] = *data * 500000; - i++; - data++; - } - range->num_bitrates = i; - kfree(r.ptr); - - return rvalue; -} - -/* Set AP address*/ - -static int -prism54_set_wap(struct net_device *ndev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - char bssid[6]; - int rvalue; - - if (awrq->sa_family != ARPHRD_ETHER) - return -EINVAL; - - /* prepare the structure for the set object */ - memcpy(&bssid[0], awrq->sa_data, 6); - - /* set the bssid -- does this make sense when in AP mode? */ - rvalue = mgt_set_request(priv, DOT11_OID_BSSID, 0, &bssid); - - return (rvalue ? rvalue : -EINPROGRESS); /* Call commit handler */ -} - -/* get AP address*/ - -static int -prism54_get_wap(struct net_device *ndev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_BSSID, 0, NULL, &r); - memcpy(awrq->sa_data, r.ptr, 6); - awrq->sa_family = ARPHRD_ETHER; - kfree(r.ptr); - - return rvalue; -} - -static int -prism54_set_scan(struct net_device *dev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - /* hehe the device does this automagicaly */ - return 0; -} - -/* a little helper that will translate our data into a card independent - * format that the Wireless Tools will understand. This was inspired by - * the "Aironet driver for 4500 and 4800 series cards" (GPL) - */ - -static char * -prism54_translate_bss(struct net_device *ndev, struct iw_request_info *info, - char *current_ev, char *end_buf, struct obj_bss *bss, - char noise) -{ - struct iw_event iwe; /* Temporary buffer */ - short cap; - islpci_private *priv = netdev_priv(ndev); - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - - /* The first entry must be the MAC address */ - memcpy(iwe.u.ap_addr.sa_data, bss->address, 6); - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - iwe.cmd = SIOCGIWAP; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_ADDR_LEN); - - /* The following entries will be displayed in the same order we give them */ - - /* The ESSID. */ - iwe.u.data.length = bss->ssid.length; - iwe.u.data.flags = 1; - iwe.cmd = SIOCGIWESSID; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, bss->ssid.octets); - - /* Capabilities */ -#define CAP_ESS 0x01 -#define CAP_IBSS 0x02 -#define CAP_CRYPT 0x10 - - /* Mode */ - cap = bss->capinfo; - iwe.u.mode = 0; - if (cap & CAP_ESS) - iwe.u.mode = IW_MODE_MASTER; - else if (cap & CAP_IBSS) - iwe.u.mode = IW_MODE_ADHOC; - iwe.cmd = SIOCGIWMODE; - if (iwe.u.mode) - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_UINT_LEN); - - /* Encryption capability */ - if (cap & CAP_CRYPT) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - iwe.cmd = SIOCGIWENCODE; - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, NULL); - - /* Add frequency. (short) bss->channel is the frequency in MHz */ - iwe.u.freq.m = bss->channel; - iwe.u.freq.e = 6; - iwe.cmd = SIOCGIWFREQ; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_FREQ_LEN); - - /* Add quality statistics */ - iwe.u.qual.level = bss->rssi; - iwe.u.qual.noise = noise; - /* do a simple SNR for quality */ - iwe.u.qual.qual = bss->rssi - noise; - iwe.cmd = IWEVQUAL; - current_ev = iwe_stream_add_event(info, current_ev, end_buf, - &iwe, IW_EV_QUAL_LEN); - - /* Add WPA/RSN Information Element, if any */ - wpa_ie_len = prism54_wpa_bss_ie_get(priv, bss->address, wpa_ie); - if (wpa_ie_len > 0) { - iwe.cmd = IWEVGENIE; - iwe.u.data.length = min(wpa_ie_len, (size_t)MAX_WPA_IE_LEN); - current_ev = iwe_stream_add_point(info, current_ev, end_buf, - &iwe, wpa_ie); - } - /* Do the bitrates */ - { - char *current_val = current_ev + iwe_stream_lcp_len(info); - int i; - int mask; - - iwe.cmd = SIOCGIWRATE; - /* Those two flags are ignored... */ - iwe.u.bitrate.fixed = iwe.u.bitrate.disabled = 0; - - /* Parse the bitmask */ - mask = 0x1; - for(i = 0; i < sizeof(scan_rate_list); i++) { - if(bss->rates & mask) { - iwe.u.bitrate.value = (scan_rate_list[i] * 500000); - current_val = iwe_stream_add_value( - info, current_ev, current_val, - end_buf, &iwe, IW_EV_PARAM_LEN); - } - mask <<= 1; - } - /* Check if we added any event */ - if ((current_val - current_ev) > iwe_stream_lcp_len(info)) - current_ev = current_val; - } - - return current_ev; -} - -static int -prism54_get_scan(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - int i, rvalue; - struct obj_bsslist *bsslist; - u32 noise = 0; - char *current_ev = extra; - union oid_res_t r; - - if (islpci_get_state(priv) < PRV_STATE_INIT) { - /* device is not ready, fail gently */ - dwrq->length = 0; - return 0; - } - - /* first get the noise value. We will use it to report the link quality */ - rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); - noise = r.u; - - /* Ask the device for a list of known bss. - * The old API, using SIOCGIWAPLIST, had a hard limit of IW_MAX_AP=64. - * The new API, using SIOCGIWSCAN, is only limited by the buffer size. - * WE-14->WE-16, the buffer is limited to IW_SCAN_MAX_DATA bytes. - * Starting with WE-17, the buffer can be as big as needed. - * But the device won't repport anything if you change the value - * of IWMAX_BSS=24. */ - - rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); - bsslist = r.ptr; - - /* ok now, scan the list and translate its info */ - for (i = 0; i < (int) bsslist->nr; i++) { - current_ev = prism54_translate_bss(ndev, info, current_ev, - extra + dwrq->length, - &(bsslist->bsslist[i]), - noise); - - /* Check if there is space for one more entry */ - if((extra + dwrq->length - current_ev) <= IW_EV_ADDR_LEN) { - /* Ask user space to try again with a bigger buffer */ - rvalue = -E2BIG; - break; - } - } - - kfree(bsslist); - dwrq->length = (current_ev - extra); - dwrq->flags = 0; /* todo */ - - return rvalue; -} - -static int -prism54_set_essid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct obj_ssid essid; - - memset(essid.octets, 0, 33); - - /* Check if we were asked for `any' */ - if (dwrq->flags && dwrq->length) { - if (dwrq->length > 32) - return -E2BIG; - essid.length = dwrq->length; - memcpy(essid.octets, extra, dwrq->length); - } else - essid.length = 0; - - if (priv->iw_mode != IW_MODE_MONITOR) - return mgt_set_request(priv, DOT11_OID_SSID, 0, &essid); - - /* If in monitor mode, just save to mib */ - mgt_set(priv, DOT11_OID_SSID, &essid); - return 0; - -} - -static int -prism54_get_essid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct obj_ssid *essid; - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_SSID, 0, NULL, &r); - essid = r.ptr; - - if (essid->length) { - dwrq->flags = 1; /* set ESSID to ON for Wireless Extensions */ - /* if it is too big, trunk it */ - dwrq->length = min((u8)IW_ESSID_MAX_SIZE, essid->length); - } else { - dwrq->flags = 0; - dwrq->length = 0; - } - essid->octets[essid->length] = '\0'; - memcpy(extra, essid->octets, dwrq->length); - kfree(essid); - - return rvalue; -} - -/* Provides no functionality, just completes the ioctl. In essence this is a - * just a cosmetic ioctl. - */ -static int -prism54_set_nick(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - if (dwrq->length > IW_ESSID_MAX_SIZE) - return -E2BIG; - - down_write(&priv->mib_sem); - memset(priv->nickname, 0, sizeof (priv->nickname)); - memcpy(priv->nickname, extra, dwrq->length); - up_write(&priv->mib_sem); - - return 0; -} - -static int -prism54_get_nick(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - dwrq->length = 0; - - down_read(&priv->mib_sem); - dwrq->length = strlen(priv->nickname); - memcpy(extra, priv->nickname, dwrq->length); - up_read(&priv->mib_sem); - - return 0; -} - -/* Set the allowed Bitrates */ - -static int -prism54_set_rate(struct net_device *ndev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - - islpci_private *priv = netdev_priv(ndev); - u32 rate, profile; - char *data; - int ret, i; - union oid_res_t r; - - if (vwrq->value == -1) { - /* auto mode. No limit. */ - profile = 1; - return mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); - } - - ret = mgt_get_request(priv, DOT11_OID_SUPPORTEDRATES, 0, NULL, &r); - if (ret) { - kfree(r.ptr); - return ret; - } - - rate = (u32) (vwrq->value / 500000); - data = r.ptr; - i = 0; - - while (data[i]) { - if (rate && (data[i] == rate)) { - break; - } - if (vwrq->value == i) { - break; - } - data[i] |= 0x80; - i++; - } - - if (!data[i]) { - kfree(r.ptr); - return -EINVAL; - } - - data[i] |= 0x80; - data[i + 1] = 0; - - /* Now, check if we want a fixed or auto value */ - if (vwrq->fixed) { - data[0] = data[i]; - data[1] = 0; - } - -/* - i = 0; - printk("prism54 rate: "); - while(data[i]) { - printk("%u ", data[i]); - i++; - } - printk("0\n"); -*/ - profile = -1; - ret = mgt_set_request(priv, DOT11_OID_PROFILES, 0, &profile); - ret |= mgt_set_request(priv, DOT11_OID_EXTENDEDRATES, 0, data); - ret |= mgt_set_request(priv, DOT11_OID_RATES, 0, data); - - kfree(r.ptr); - - return ret; -} - -/* Get the current bit rate */ -static int -prism54_get_rate(struct net_device *ndev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - int rvalue; - char *data; - union oid_res_t r; - - /* Get the current bit rate */ - if ((rvalue = mgt_get_request(priv, GEN_OID_LINKSTATE, 0, NULL, &r))) - return rvalue; - vwrq->value = r.u * 500000; - - /* request the device for the enabled rates */ - rvalue = mgt_get_request(priv, DOT11_OID_RATES, 0, NULL, &r); - if (rvalue) { - kfree(r.ptr); - return rvalue; - } - data = r.ptr; - vwrq->fixed = (data[0] != 0) && (data[1] == 0); - kfree(r.ptr); - - return 0; -} - -static int -prism54_set_rts(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - return mgt_set_request(priv, DOT11_OID_RTSTHRESH, 0, &vwrq->value); -} - -static int -prism54_get_rts(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - /* get the rts threshold */ - rvalue = mgt_get_request(priv, DOT11_OID_RTSTHRESH, 0, NULL, &r); - vwrq->value = r.u; - - return rvalue; -} - -static int -prism54_set_frag(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - return mgt_set_request(priv, DOT11_OID_FRAGTHRESH, 0, &vwrq->value); -} - -static int -prism54_get_frag(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, DOT11_OID_FRAGTHRESH, 0, NULL, &r); - vwrq->value = r.u; - - return rvalue; -} - -/* Here we have (min,max) = max retries for (small frames, big frames). Where - * big frame <=> bigger than the rts threshold - * small frame <=> smaller than the rts threshold - * This is not really the behavior expected by the wireless tool but it seems - * to be a common behavior in other drivers. - */ - -static int -prism54_set_retry(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 slimit = 0, llimit = 0; /* short and long limit */ - u32 lifetime = 0; - int rvalue = 0; - - if (vwrq->disabled) - /* we cannot disable this feature */ - return -EINVAL; - - if (vwrq->flags & IW_RETRY_LIMIT) { - if (vwrq->flags & IW_RETRY_SHORT) - slimit = vwrq->value; - else if (vwrq->flags & IW_RETRY_LONG) - llimit = vwrq->value; - else { - /* we are asked to set both */ - slimit = vwrq->value; - llimit = vwrq->value; - } - } - if (vwrq->flags & IW_RETRY_LIFETIME) - /* Wireless tools use us unit while the device uses 1024 us unit */ - lifetime = vwrq->value / 1024; - - /* now set what is requested */ - if (slimit) - rvalue = - mgt_set_request(priv, DOT11_OID_SHORTRETRIES, 0, &slimit); - if (llimit) - rvalue |= - mgt_set_request(priv, DOT11_OID_LONGRETRIES, 0, &llimit); - if (lifetime) - rvalue |= - mgt_set_request(priv, DOT11_OID_MAXTXLIFETIME, 0, - &lifetime); - return rvalue; -} - -static int -prism54_get_retry(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue = 0; - vwrq->disabled = 0; /* It cannot be disabled */ - - if ((vwrq->flags & IW_RETRY_TYPE) == IW_RETRY_LIFETIME) { - /* we are asked for the life time */ - rvalue = - mgt_get_request(priv, DOT11_OID_MAXTXLIFETIME, 0, NULL, &r); - vwrq->value = r.u * 1024; - vwrq->flags = IW_RETRY_LIFETIME; - } else if ((vwrq->flags & IW_RETRY_LONG)) { - /* we are asked for the long retry limit */ - rvalue |= - mgt_get_request(priv, DOT11_OID_LONGRETRIES, 0, NULL, &r); - vwrq->value = r.u; - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - } else { - /* default. get the short retry limit */ - rvalue |= - mgt_get_request(priv, DOT11_OID_SHORTRETRIES, 0, NULL, &r); - vwrq->value = r.u; - vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; - } - - return rvalue; -} - -static int -prism54_set_encode(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - int rvalue = 0, force = 0; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; - union oid_res_t r; - - /* with the new API, it's impossible to get a NULL pointer. - * New version of iwconfig set the IW_ENCODE_NOKEY flag - * when no key is given, but older versions don't. */ - - if (dwrq->length > 0) { - /* we have a key to set */ - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - int current_index; - struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; - - /* get the current key index */ - rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - current_index = r.u; - /* Verify that the key is not marked as invalid */ - if (!(dwrq->flags & IW_ENCODE_NOKEY)) { - if (dwrq->length > KEY_SIZE_TKIP) { - /* User-provided key data too big */ - return -EINVAL; - } - if (dwrq->length > KEY_SIZE_WEP104) { - /* WPA-PSK TKIP */ - key.type = DOT11_PRIV_TKIP; - key.length = KEY_SIZE_TKIP; - } else if (dwrq->length > KEY_SIZE_WEP40) { - /* WEP 104/128 */ - key.length = KEY_SIZE_WEP104; - } else { - /* WEP 40/64 */ - key.length = KEY_SIZE_WEP40; - } - memset(key.key, 0, sizeof (key.key)); - memcpy(key.key, extra, dwrq->length); - - if ((index < 0) || (index > 3)) - /* no index provided use the current one */ - index = current_index; - - /* now send the key to the card */ - rvalue |= - mgt_set_request(priv, DOT11_OID_DEFKEYX, index, - &key); - } - /* - * If a valid key is set, encryption should be enabled - * (user may turn it off later). - * This is also how "iwconfig ethX key on" works - */ - if ((index == current_index) && (key.length > 0)) - force = 1; - } else { - int index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - if ((index >= 0) && (index <= 3)) { - /* we want to set the key index */ - rvalue |= - mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, - &index); - } else { - if (!(dwrq->flags & IW_ENCODE_MODE)) { - /* we cannot do anything. Complain. */ - return -EINVAL; - } - } - } - /* now read the flags */ - if (dwrq->flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, - * authen = DOT11_AUTH_OS; - * invoke = 0; - * exunencrypt = 0; */ - } - if (dwrq->flags & IW_ENCODE_OPEN) - /* Encode but accept non-encoded packets. No auth */ - invoke = 1; - if ((dwrq->flags & IW_ENCODE_RESTRICTED) || force) { - /* Refuse non-encoded packets. Auth */ - authen = DOT11_AUTH_BOTH; - invoke = 1; - exunencrypt = 1; - } - /* do the change if requested */ - if ((dwrq->flags & IW_ENCODE_MODE) || force) { - rvalue |= - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - rvalue |= - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); - rvalue |= - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, - &exunencrypt); - } - return rvalue; -} - -static int -prism54_get_encode(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct obj_key *key; - u32 devindex, index = (dwrq->flags & IW_ENCODE_INDEX) - 1; - u32 authen = 0, invoke = 0, exunencrypt = 0; - int rvalue; - union oid_res_t r; - - /* first get the flags */ - rvalue = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - authen = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - invoke = r.u; - rvalue |= mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - exunencrypt = r.u; - - if (invoke && (authen == DOT11_AUTH_BOTH) && exunencrypt) - dwrq->flags = IW_ENCODE_RESTRICTED; - else if ((authen == DOT11_AUTH_OS) && !exunencrypt) { - if (invoke) - dwrq->flags = IW_ENCODE_OPEN; - else - dwrq->flags = IW_ENCODE_DISABLED; - } else - /* The card should not work in this state */ - dwrq->flags = 0; - - /* get the current device key index */ - rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - devindex = r.u; - /* Now get the key, return it */ - if (index == -1 || index > 3) - /* no index provided, use the current one */ - index = devindex; - rvalue |= mgt_get_request(priv, DOT11_OID_DEFKEYX, index, NULL, &r); - key = r.ptr; - dwrq->length = key->length; - memcpy(extra, key->key, dwrq->length); - kfree(key); - /* return the used key index */ - dwrq->flags |= devindex + 1; - - return rvalue; -} - -static int -prism54_get_txpower(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - union oid_res_t r; - int rvalue; - - rvalue = mgt_get_request(priv, OID_INL_OUTPUTPOWER, 0, NULL, &r); - /* intersil firmware operates in 0.25 dBm (1/4 dBm) */ - vwrq->value = (s32) r.u / 4; - vwrq->fixed = 1; - /* radio is not turned of - * btw: how is possible to turn off only the radio - */ - vwrq->disabled = 0; - - return rvalue; -} - -static int -prism54_set_txpower(struct net_device *ndev, struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - s32 u = vwrq->value; - - /* intersil firmware operates in 0.25 dBm (1/4) */ - u *= 4; - if (vwrq->disabled) { - /* don't know how to disable radio */ - printk(KERN_DEBUG - "%s: %s() disabling radio is not yet supported.\n", - priv->ndev->name, __func__); - return -ENOTSUPP; - } else if (vwrq->fixed) - /* currently only fixed value is supported */ - return mgt_set_request(priv, OID_INL_OUTPUTPOWER, 0, &u); - else { - printk(KERN_DEBUG - "%s: %s() auto power will be implemented later.\n", - priv->ndev->name, __func__); - return -ENOTSUPP; - } -} - -static int prism54_set_genie(struct net_device *ndev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - int alen, ret = 0; - struct obj_attachment *attach; - - if (data->length > MAX_WPA_IE_LEN || - (data->length && extra == NULL)) - return -EINVAL; - - memcpy(priv->wpa_ie, extra, data->length); - priv->wpa_ie_len = data->length; - - alen = sizeof(*attach) + priv->wpa_ie_len; - attach = kzalloc(alen, GFP_KERNEL); - if (attach == NULL) - return -ENOMEM; - -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_REASSOC_REQ 2 - - /* Note: endianness is covered by mgt_set_varlen */ - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_ASSOC_REQ << 4); - attach->id = -1; - attach->size = priv->wpa_ie_len; - memcpy(attach->data, extra, priv->wpa_ie_len); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, - priv->wpa_ie_len); - if (ret == 0) { - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_REASSOC_REQ << 4); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, - priv->wpa_ie_len); - if (ret == 0) - printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", - ndev->name); - } - - kfree(attach); - return ret; -} - - -static int prism54_get_genie(struct net_device *ndev, - struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - int len = priv->wpa_ie_len; - - if (len <= 0) { - data->length = 0; - return 0; - } - - if (data->length < len) - return -E2BIG; - - data->length = len; - memcpy(extra, priv->wpa_ie, len); - - return 0; -} - -static int prism54_set_auth(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct iw_param *param = &wrqu->param; - u32 mlmelevel = 0, authen = 0, dot1x = 0; - u32 exunencrypt = 0, privinvoked = 0, wpa = 0; - u32 old_wpa; - int ret = 0; - union oid_res_t r; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* first get the flags */ - down_write(&priv->mib_sem); - wpa = old_wpa = priv->wpa; - up_write(&priv->mib_sem); - ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - authen = r.u; - ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - privinvoked = r.u; - ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - exunencrypt = r.u; - ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r); - dot1x = r.u; - ret = mgt_get_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, NULL, &r); - mlmelevel = r.u; - - if (ret < 0) - goto out; - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - break; - - case IW_AUTH_WPA_ENABLED: - /* Do the same thing as IW_AUTH_WPA_VERSION */ - if (param->value) { - wpa = 1; - privinvoked = 1; /* For privacy invoked */ - exunencrypt = 1; /* Filter out all unencrypted frames */ - dot1x = 0x01; /* To enable eap filter */ - mlmelevel = DOT11_MLME_EXTENDED; - authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ - } else { - wpa = 0; - privinvoked = 0; - exunencrypt = 0; /* Do not filter un-encrypted data */ - dot1x = 0; - mlmelevel = DOT11_MLME_AUTO; - } - break; - - case IW_AUTH_WPA_VERSION: - if (param->value & IW_AUTH_WPA_VERSION_DISABLED) { - wpa = 0; - privinvoked = 0; - exunencrypt = 0; /* Do not filter un-encrypted data */ - dot1x = 0; - mlmelevel = DOT11_MLME_AUTO; - } else { - if (param->value & IW_AUTH_WPA_VERSION_WPA) - wpa = 1; - else if (param->value & IW_AUTH_WPA_VERSION_WPA2) - wpa = 2; - privinvoked = 1; /* For privacy invoked */ - exunencrypt = 1; /* Filter out all unencrypted frames */ - dot1x = 0x01; /* To enable eap filter */ - mlmelevel = DOT11_MLME_EXTENDED; - authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ - } - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - /* dot1x should be the opposite of RX_UNENCRYPTED_EAPOL; - * turn off dot1x when allowing receipt of unencrypted EAPOL - * frames, turn on dot1x when receipt should be disallowed - */ - dot1x = param->value ? 0 : 0x01; - break; - - case IW_AUTH_PRIVACY_INVOKED: - privinvoked = param->value ? 1 : 0; - break; - - case IW_AUTH_DROP_UNENCRYPTED: - exunencrypt = param->value ? 1 : 0; - break; - - case IW_AUTH_80211_AUTH_ALG: - if (param->value & IW_AUTH_ALG_SHARED_KEY) { - /* Only WEP uses _SK and _BOTH */ - if (wpa > 0) { - ret = -EINVAL; - goto out; - } - authen = DOT11_AUTH_SK; - } else if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) { - authen = DOT11_AUTH_OS; - } else { - ret = -EINVAL; - goto out; - } - break; - - default: - return -EOPNOTSUPP; - } - - /* Set all the values */ - down_write(&priv->mib_sem); - priv->wpa = wpa; - up_write(&priv->mib_sem); - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &privinvoked); - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &exunencrypt); - mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); - mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlmelevel); - -out: - return ret; -} - -static int prism54_get_auth(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct iw_param *param = &wrqu->param; - u32 wpa = 0; - int ret = 0; - union oid_res_t r; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* first get the flags */ - down_write(&priv->mib_sem); - wpa = priv->wpa; - up_write(&priv->mib_sem); - - switch (param->flags & IW_AUTH_INDEX) { - case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: - case IW_AUTH_KEY_MGMT: - /* - * wpa_supplicant will control these internally - */ - ret = -EOPNOTSUPP; - break; - - case IW_AUTH_WPA_VERSION: - switch (wpa) { - case 1: - param->value = IW_AUTH_WPA_VERSION_WPA; - break; - case 2: - param->value = IW_AUTH_WPA_VERSION_WPA2; - break; - case 0: - default: - param->value = IW_AUTH_WPA_VERSION_DISABLED; - break; - } - break; - - case IW_AUTH_DROP_UNENCRYPTED: - ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - if (ret >= 0) - param->value = r.u > 0 ? 1 : 0; - break; - - case IW_AUTH_80211_AUTH_ALG: - ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - if (ret >= 0) { - switch (r.u) { - case DOT11_AUTH_OS: - param->value = IW_AUTH_ALG_OPEN_SYSTEM; - break; - case DOT11_AUTH_BOTH: - case DOT11_AUTH_SK: - param->value = IW_AUTH_ALG_SHARED_KEY; - case DOT11_AUTH_NONE: - default: - param->value = 0; - break; - } - } - break; - - case IW_AUTH_WPA_ENABLED: - param->value = wpa > 0 ? 1 : 0; - break; - - case IW_AUTH_RX_UNENCRYPTED_EAPOL: - ret = mgt_get_request(priv, DOT11_OID_DOT1XENABLE, 0, NULL, &r); - if (ret >= 0) - param->value = r.u > 0 ? 1 : 0; - break; - - case IW_AUTH_PRIVACY_INVOKED: - ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - if (ret >= 0) - param->value = r.u > 0 ? 1 : 0; - break; - - default: - return -EOPNOTSUPP; - } - return ret; -} - -static int prism54_set_encodeext(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, alg = ext->alg, set_key = 1; - union oid_res_t r; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; - int ret = 0; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* Determine and validate the key index */ - idx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if (idx) { - if (idx < 0 || idx > 3) - return -EINVAL; - } else { - ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - if (ret < 0) - goto out; - idx = r.u; - } - - if (encoding->flags & IW_ENCODE_DISABLED) - alg = IW_ENCODE_ALG_NONE; - - if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) { - /* Only set transmit key index here, actual - * key is set below if needed. - */ - ret = mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, &idx); - set_key = ext->key_len > 0 ? 1 : 0; - } - - if (set_key) { - struct obj_key key = { DOT11_PRIV_WEP, 0, "" }; - switch (alg) { - case IW_ENCODE_ALG_NONE: - break; - case IW_ENCODE_ALG_WEP: - if (ext->key_len > KEY_SIZE_WEP104) { - ret = -EINVAL; - goto out; - } - if (ext->key_len > KEY_SIZE_WEP40) - key.length = KEY_SIZE_WEP104; - else - key.length = KEY_SIZE_WEP40; - break; - case IW_ENCODE_ALG_TKIP: - if (ext->key_len > KEY_SIZE_TKIP) { - ret = -EINVAL; - goto out; - } - key.type = DOT11_PRIV_TKIP; - key.length = KEY_SIZE_TKIP; - break; - default: - return -EINVAL; - } - - if (key.length) { - memset(key.key, 0, sizeof(key.key)); - memcpy(key.key, ext->key, ext->key_len); - ret = mgt_set_request(priv, DOT11_OID_DEFKEYX, idx, - &key); - if (ret < 0) - goto out; - } - } - - /* Read the flags */ - if (encoding->flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, - * authen = DOT11_AUTH_OS; - * invoke = 0; - * exunencrypt = 0; */ - } - if (encoding->flags & IW_ENCODE_OPEN) { - /* Encode but accept non-encoded packets. No auth */ - invoke = 1; - } - if (encoding->flags & IW_ENCODE_RESTRICTED) { - /* Refuse non-encoded packets. Auth */ - authen = DOT11_AUTH_BOTH; - invoke = 1; - exunencrypt = 1; - } - - /* do the change if requested */ - if (encoding->flags & IW_ENCODE_MODE) { - ret = mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, - &authen); - ret = mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, - &invoke); - ret = mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, - &exunencrypt); - } - -out: - return ret; -} - - -static int prism54_get_encodeext(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct iw_point *encoding = &wrqu->encoding; - struct iw_encode_ext *ext = (struct iw_encode_ext *)extra; - int idx, max_key_len; - union oid_res_t r; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0, wpa = 0; - int ret = 0; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - /* first get the flags */ - ret = mgt_get_request(priv, DOT11_OID_AUTHENABLE, 0, NULL, &r); - authen = r.u; - ret = mgt_get_request(priv, DOT11_OID_PRIVACYINVOKED, 0, NULL, &r); - invoke = r.u; - ret = mgt_get_request(priv, DOT11_OID_EXUNENCRYPTED, 0, NULL, &r); - exunencrypt = r.u; - if (ret < 0) - goto out; - - max_key_len = encoding->length - sizeof(*ext); - if (max_key_len < 0) - return -EINVAL; - - idx = (encoding->flags & IW_ENCODE_INDEX) - 1; - if (idx) { - if (idx < 0 || idx > 3) - return -EINVAL; - } else { - ret = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - if (ret < 0) - goto out; - idx = r.u; - } - - encoding->flags = idx + 1; - memset(ext, 0, sizeof(*ext)); - - switch (authen) { - case DOT11_AUTH_BOTH: - case DOT11_AUTH_SK: - wrqu->encoding.flags |= IW_ENCODE_RESTRICTED; - case DOT11_AUTH_OS: - default: - wrqu->encoding.flags |= IW_ENCODE_OPEN; - break; - } - - down_write(&priv->mib_sem); - wpa = priv->wpa; - up_write(&priv->mib_sem); - - if (authen == DOT11_AUTH_OS && !exunencrypt && !invoke && !wpa) { - /* No encryption */ - ext->alg = IW_ENCODE_ALG_NONE; - ext->key_len = 0; - wrqu->encoding.flags |= IW_ENCODE_DISABLED; - } else { - struct obj_key *key; - - ret = mgt_get_request(priv, DOT11_OID_DEFKEYX, idx, NULL, &r); - if (ret < 0) - goto out; - key = r.ptr; - if (max_key_len < key->length) { - ret = -E2BIG; - goto out; - } - memcpy(ext->key, key->key, key->length); - ext->key_len = key->length; - - switch (key->type) { - case DOT11_PRIV_TKIP: - ext->alg = IW_ENCODE_ALG_TKIP; - break; - default: - case DOT11_PRIV_WEP: - ext->alg = IW_ENCODE_ALG_WEP; - break; - } - wrqu->encoding.flags |= IW_ENCODE_ENABLED; - } - -out: - return ret; -} - - -static int -prism54_reset(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_reset(netdev_priv(ndev), 0); - - return 0; -} - -static int -prism54_get_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - union oid_res_t r; - int rvalue; - enum oid_num_t n = dwrq->flags; - - rvalue = mgt_get_request(netdev_priv(ndev), n, 0, NULL, &r); - dwrq->length = mgt_response_to_str(n, &r, extra); - if ((isl_oid[n].flags & OID_FLAG_TYPE) != OID_TYPE_U32) - kfree(r.ptr); - return rvalue; -} - -static int -prism54_set_u32(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - u32 oid = uwrq[0], u = uwrq[1]; - - return mgt_set_request(netdev_priv(ndev), oid, 0, &u); -} - -static int -prism54_set_raw(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - u32 oid = dwrq->flags; - - return mgt_set_request(netdev_priv(ndev), oid, 0, extra); -} - -void -prism54_acl_init(struct islpci_acl *acl) -{ - mutex_init(&acl->lock); - INIT_LIST_HEAD(&acl->mac_list); - acl->size = 0; - acl->policy = MAC_POLICY_OPEN; -} - -static void -prism54_clear_mac(struct islpci_acl *acl) -{ - struct list_head *ptr, *next; - struct mac_entry *entry; - - mutex_lock(&acl->lock); - - if (acl->size == 0) { - mutex_unlock(&acl->lock); - return; - } - - for (ptr = acl->mac_list.next, next = ptr->next; - ptr != &acl->mac_list; ptr = next, next = ptr->next) { - entry = list_entry(ptr, struct mac_entry, _list); - list_del(ptr); - kfree(entry); - } - acl->size = 0; - mutex_unlock(&acl->lock); -} - -void -prism54_acl_clean(struct islpci_acl *acl) -{ - prism54_clear_mac(acl); -} - -static int -prism54_add_mac(struct net_device *ndev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_acl *acl = &priv->acl; - struct mac_entry *entry; - struct sockaddr *addr = (struct sockaddr *) extra; - - if (addr->sa_family != ARPHRD_ETHER) - return -EOPNOTSUPP; - - entry = kmalloc(sizeof (struct mac_entry), GFP_KERNEL); - if (entry == NULL) - return -ENOMEM; - - memcpy(entry->addr, addr->sa_data, ETH_ALEN); - - if (mutex_lock_interruptible(&acl->lock)) { - kfree(entry); - return -ERESTARTSYS; - } - list_add_tail(&entry->_list, &acl->mac_list); - acl->size++; - mutex_unlock(&acl->lock); - - return 0; -} - -static int -prism54_del_mac(struct net_device *ndev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_acl *acl = &priv->acl; - struct mac_entry *entry; - struct sockaddr *addr = (struct sockaddr *) extra; - - if (addr->sa_family != ARPHRD_ETHER) - return -EOPNOTSUPP; - - if (mutex_lock_interruptible(&acl->lock)) - return -ERESTARTSYS; - list_for_each_entry(entry, &acl->mac_list, _list) { - if (memcmp(entry->addr, addr->sa_data, ETH_ALEN) == 0) { - list_del(&entry->_list); - acl->size--; - kfree(entry); - mutex_unlock(&acl->lock); - return 0; - } - } - mutex_unlock(&acl->lock); - return -EINVAL; -} - -static int -prism54_get_mac(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_acl *acl = &priv->acl; - struct mac_entry *entry; - struct sockaddr *dst = (struct sockaddr *) extra; - - dwrq->length = 0; - - if (mutex_lock_interruptible(&acl->lock)) - return -ERESTARTSYS; - - list_for_each_entry(entry, &acl->mac_list, _list) { - memcpy(dst->sa_data, entry->addr, ETH_ALEN); - dst->sa_family = ARPHRD_ETHER; - dwrq->length++; - dst++; - } - mutex_unlock(&acl->lock); - return 0; -} - -/* Setting policy also clears the MAC acl, even if we don't change the defaut - * policy - */ - -static int -prism54_set_policy(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_acl *acl = &priv->acl; - u32 mlmeautolevel; - - prism54_clear_mac(acl); - - if ((*uwrq < MAC_POLICY_OPEN) || (*uwrq > MAC_POLICY_REJECT)) - return -EINVAL; - - down_write(&priv->mib_sem); - - acl->policy = *uwrq; - - /* the ACL code needs an intermediate mlmeautolevel */ - if ((priv->iw_mode == IW_MODE_MASTER) && - (acl->policy != MAC_POLICY_OPEN)) - mlmeautolevel = DOT11_MLME_INTERMEDIATE; - else - mlmeautolevel = CARD_DEFAULT_MLME_MODE; - if (priv->wpa) - mlmeautolevel = DOT11_MLME_EXTENDED; - mgt_set(priv, DOT11_OID_MLMEAUTOLEVEL, &mlmeautolevel); - /* restart the card with our new policy */ - if (mgt_commit(priv)) { - up_write(&priv->mib_sem); - return -EIO; - } - up_write(&priv->mib_sem); - - return 0; -} - -static int -prism54_get_policy(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_acl *acl = &priv->acl; - - *uwrq = acl->policy; - - return 0; -} - -/* Return 1 only if client should be accepted. */ - -static int -prism54_mac_accept(struct islpci_acl *acl, char *mac) -{ - struct mac_entry *entry; - int res = 0; - - if (mutex_lock_interruptible(&acl->lock)) - return -ERESTARTSYS; - - if (acl->policy == MAC_POLICY_OPEN) { - mutex_unlock(&acl->lock); - return 1; - } - - list_for_each_entry(entry, &acl->mac_list, _list) { - if (memcmp(entry->addr, mac, ETH_ALEN) == 0) { - res = 1; - break; - } - } - res = (acl->policy == MAC_POLICY_ACCEPT) ? !res : res; - mutex_unlock(&acl->lock); - - return res; -} - -static int -prism54_kick_all(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct obj_mlme *mlme; - int rvalue; - - mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL); - if (mlme == NULL) - return -ENOMEM; - - /* Tell the card to kick every client */ - mlme->id = 0; - rvalue = - mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); - kfree(mlme); - - return rvalue; -} - -static int -prism54_kick_mac(struct net_device *ndev, struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - struct obj_mlme *mlme; - struct sockaddr *addr = (struct sockaddr *) extra; - int rvalue; - - if (addr->sa_family != ARPHRD_ETHER) - return -EOPNOTSUPP; - - mlme = kmalloc(sizeof (struct obj_mlme), GFP_KERNEL); - if (mlme == NULL) - return -ENOMEM; - - /* Tell the card to only kick the corresponding bastard */ - memcpy(mlme->address, addr->sa_data, ETH_ALEN); - mlme->id = -1; - rvalue = - mgt_set_request(netdev_priv(ndev), DOT11_OID_DISASSOCIATE, 0, mlme); - - kfree(mlme); - - return rvalue; -} - -/* Translate a TRAP oid into a wireless event. Called in islpci_mgt_receive. */ - -static void -format_event(islpci_private *priv, char *dest, const char *str, - const struct obj_mlme *mlme, u16 *length, int error) -{ - int n = snprintf(dest, IW_CUSTOM_MAX, - "%s %s %pM %s (%2.2X)", - str, - ((priv->iw_mode == IW_MODE_MASTER) ? "from" : "to"), - mlme->address, - (error ? (mlme->code ? " : REJECTED " : " : ACCEPTED ") - : ""), mlme->code); - BUG_ON(n > IW_CUSTOM_MAX); - *length = n; -} - -static void -send_formatted_event(islpci_private *priv, const char *str, - const struct obj_mlme *mlme, int error) -{ - union iwreq_data wrqu; - char *memptr; - - memptr = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); - if (!memptr) - return; - wrqu.data.pointer = memptr; - wrqu.data.length = 0; - format_event(priv, memptr, str, mlme, &wrqu.data.length, - error); - wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, memptr); - kfree(memptr); -} - -static void -send_simple_event(islpci_private *priv, const char *str) -{ - union iwreq_data wrqu; - char *memptr; - int n = strlen(str); - - memptr = kmalloc(IW_CUSTOM_MAX, GFP_KERNEL); - if (!memptr) - return; - BUG_ON(n > IW_CUSTOM_MAX); - wrqu.data.pointer = memptr; - wrqu.data.length = n; - strcpy(memptr, str); - wireless_send_event(priv->ndev, IWEVCUSTOM, &wrqu, memptr); - kfree(memptr); -} - -static void -link_changed(struct net_device *ndev, u32 bitrate) -{ - islpci_private *priv = netdev_priv(ndev); - - if (bitrate) { - netif_carrier_on(ndev); - if (priv->iw_mode == IW_MODE_INFRA) { - union iwreq_data uwrq; - prism54_get_wap(ndev, NULL, (struct sockaddr *) &uwrq, - NULL); - wireless_send_event(ndev, SIOCGIWAP, &uwrq, NULL); - } else - send_simple_event(netdev_priv(ndev), - "Link established"); - } else { - netif_carrier_off(ndev); - send_simple_event(netdev_priv(ndev), "Link lost"); - } -} - -/* Beacon/ProbeResp payload header */ -struct ieee80211_beacon_phdr { - u8 timestamp[8]; - u16 beacon_int; - u16 capab_info; -} __attribute__ ((packed)); - -#define WLAN_EID_GENERIC 0xdd -static u8 wpa_oid[4] = { 0x00, 0x50, 0xf2, 1 }; - -static void -prism54_wpa_bss_ie_add(islpci_private *priv, u8 *bssid, - u8 *wpa_ie, size_t wpa_ie_len) -{ - struct list_head *ptr; - struct islpci_bss_wpa_ie *bss = NULL; - - if (wpa_ie_len > MAX_WPA_IE_LEN) - wpa_ie_len = MAX_WPA_IE_LEN; - - mutex_lock(&priv->wpa_lock); - - /* try to use existing entry */ - list_for_each(ptr, &priv->bss_wpa_list) { - bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) { - list_move(&bss->list, &priv->bss_wpa_list); - break; - } - bss = NULL; - } - - if (bss == NULL) { - /* add a new BSS entry; if max number of entries is already - * reached, replace the least recently updated */ - if (priv->num_bss_wpa >= MAX_BSS_WPA_IE_COUNT) { - bss = list_entry(priv->bss_wpa_list.prev, - struct islpci_bss_wpa_ie, list); - list_del(&bss->list); - } else { - bss = kzalloc(sizeof (*bss), GFP_ATOMIC); - if (bss != NULL) - priv->num_bss_wpa++; - } - if (bss != NULL) { - memcpy(bss->bssid, bssid, ETH_ALEN); - list_add(&bss->list, &priv->bss_wpa_list); - } - } - - if (bss != NULL) { - memcpy(bss->wpa_ie, wpa_ie, wpa_ie_len); - bss->wpa_ie_len = wpa_ie_len; - bss->last_update = jiffies; - } else { - printk(KERN_DEBUG "Failed to add BSS WPA entry for " - "%pM\n", bssid); - } - - /* expire old entries from WPA list */ - while (priv->num_bss_wpa > 0) { - bss = list_entry(priv->bss_wpa_list.prev, - struct islpci_bss_wpa_ie, list); - if (!time_after(jiffies, bss->last_update + 60 * HZ)) - break; - - list_del(&bss->list); - priv->num_bss_wpa--; - kfree(bss); - } - - mutex_unlock(&priv->wpa_lock); -} - -static size_t -prism54_wpa_bss_ie_get(islpci_private *priv, u8 *bssid, u8 *wpa_ie) -{ - struct list_head *ptr; - struct islpci_bss_wpa_ie *bss = NULL; - size_t len = 0; - - mutex_lock(&priv->wpa_lock); - - list_for_each(ptr, &priv->bss_wpa_list) { - bss = list_entry(ptr, struct islpci_bss_wpa_ie, list); - if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) - break; - bss = NULL; - } - if (bss) { - len = bss->wpa_ie_len; - memcpy(wpa_ie, bss->wpa_ie, len); - } - mutex_unlock(&priv->wpa_lock); - - return len; -} - -void -prism54_wpa_bss_ie_init(islpci_private *priv) -{ - INIT_LIST_HEAD(&priv->bss_wpa_list); - mutex_init(&priv->wpa_lock); -} - -void -prism54_wpa_bss_ie_clean(islpci_private *priv) -{ - struct islpci_bss_wpa_ie *bss, *n; - - list_for_each_entry_safe(bss, n, &priv->bss_wpa_list, list) { - kfree(bss); - } -} - -static void -prism54_process_bss_data(islpci_private *priv, u32 oid, u8 *addr, - u8 *payload, size_t len) -{ - struct ieee80211_beacon_phdr *hdr; - u8 *pos, *end; - - if (!priv->wpa) - return; - - hdr = (struct ieee80211_beacon_phdr *) payload; - pos = (u8 *) (hdr + 1); - end = payload + len; - while (pos < end) { - if (pos + 2 + pos[1] > end) { - printk(KERN_DEBUG "Parsing Beacon/ProbeResp failed " - "for %pM\n", addr); - return; - } - if (pos[0] == WLAN_EID_GENERIC && pos[1] >= 4 && - memcmp(pos + 2, wpa_oid, 4) == 0) { - prism54_wpa_bss_ie_add(priv, addr, pos, pos[1] + 2); - return; - } - pos += 2 + pos[1]; - } -} - -static void -handle_request(islpci_private *priv, struct obj_mlme *mlme, enum oid_num_t oid) -{ - if (((mlme->state == DOT11_STATE_AUTHING) || - (mlme->state == DOT11_STATE_ASSOCING)) - && mgt_mlme_answer(priv)) { - /* Someone is requesting auth and we must respond. Just send back - * the trap with error code set accordingly. - */ - mlme->code = prism54_mac_accept(&priv->acl, - mlme->address) ? 0 : 1; - mgt_set_request(priv, oid, 0, mlme); - } -} - -static int -prism54_process_trap_helper(islpci_private *priv, enum oid_num_t oid, - char *data) -{ - struct obj_mlme *mlme = (struct obj_mlme *) data; - struct obj_mlmeex *mlmeex = (struct obj_mlmeex *) data; - struct obj_mlmeex *confirm; - u8 wpa_ie[MAX_WPA_IE_LEN]; - int wpa_ie_len; - size_t len = 0; /* u16, better? */ - u8 *payload = NULL, *pos = NULL; - int ret; - - /* I think all trapable objects are listed here. - * Some oids have a EX version. The difference is that they are emitted - * in DOT11_MLME_EXTENDED mode (set with DOT11_OID_MLMEAUTOLEVEL) - * with more info. - * The few events already defined by the wireless tools are not really - * suited. We use the more flexible custom event facility. - */ - - if (oid >= DOT11_OID_BEACON) { - len = mlmeex->size; - payload = pos = mlmeex->data; - } - - /* I fear prism54_process_bss_data won't work with big endian data */ - if ((oid == DOT11_OID_BEACON) || (oid == DOT11_OID_PROBE)) - prism54_process_bss_data(priv, oid, mlmeex->address, - payload, len); - - mgt_le_to_cpu(isl_oid[oid].flags & OID_FLAG_TYPE, (void *) mlme); - - switch (oid) { - - case GEN_OID_LINKSTATE: - link_changed(priv->ndev, (u32) *data); - break; - - case DOT11_OID_MICFAILURE: - send_simple_event(priv, "Mic failure"); - break; - - case DOT11_OID_DEAUTHENTICATE: - send_formatted_event(priv, "DeAuthenticate request", mlme, 0); - break; - - case DOT11_OID_AUTHENTICATE: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Authenticate request", mlme, 1); - break; - - case DOT11_OID_DISASSOCIATE: - send_formatted_event(priv, "Disassociate request", mlme, 0); - break; - - case DOT11_OID_ASSOCIATE: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Associate request", mlme, 1); - break; - - case DOT11_OID_REASSOCIATE: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "ReAssociate request", mlme, 1); - break; - - case DOT11_OID_BEACON: - send_formatted_event(priv, - "Received a beacon from an unkown AP", - mlme, 0); - break; - - case DOT11_OID_PROBE: - /* we received a probe from a client. */ - send_formatted_event(priv, "Received a probe from client", mlme, - 0); - break; - - /* Note : "mlme" is actually a "struct obj_mlmeex *" here, but this - * is backward compatible layout-wise with "struct obj_mlme". - */ - - case DOT11_OID_DEAUTHENTICATEEX: - send_formatted_event(priv, "DeAuthenticate request", mlme, 0); - break; - - case DOT11_OID_AUTHENTICATEEX: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Authenticate request (ex)", mlme, 1); - - if (priv->iw_mode != IW_MODE_MASTER - && mlmeex->state != DOT11_STATE_AUTHING) - break; - - confirm = kmalloc(sizeof(struct obj_mlmeex) + 6, GFP_ATOMIC); - - if (!confirm) - break; - - memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - printk(KERN_DEBUG "Authenticate from: address:\t%pM\n", - mlmeex->address); - confirm->id = -1; /* or mlmeex->id ? */ - confirm->state = 0; /* not used */ - confirm->code = 0; - confirm->size = 6; - confirm->data[0] = 0x00; - confirm->data[1] = 0x00; - confirm->data[2] = 0x02; - confirm->data[3] = 0x00; - confirm->data[4] = 0x00; - confirm->data[5] = 0x00; - - ret = mgt_set_varlen(priv, DOT11_OID_ASSOCIATEEX, confirm, 6); - - kfree(confirm); - if (ret) - return ret; - break; - - case DOT11_OID_DISASSOCIATEEX: - send_formatted_event(priv, "Disassociate request (ex)", mlme, 0); - break; - - case DOT11_OID_ASSOCIATEEX: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Associate request (ex)", mlme, 1); - - if (priv->iw_mode != IW_MODE_MASTER - && mlmeex->state != DOT11_STATE_ASSOCING) - break; - - confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); - - if (!confirm) - break; - - memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - - confirm->id = ((struct obj_mlmeex *)mlme)->id; - confirm->state = 0; /* not used */ - confirm->code = 0; - - wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie); - - if (!wpa_ie_len) { - printk(KERN_DEBUG "No WPA IE found from address:\t%pM\n", - mlmeex->address); - kfree(confirm); - break; - } - - confirm->size = wpa_ie_len; - memcpy(&confirm->data, wpa_ie, wpa_ie_len); - - mgt_set_varlen(priv, oid, confirm, wpa_ie_len); - - kfree(confirm); - - break; - - case DOT11_OID_REASSOCIATEEX: - handle_request(priv, mlme, oid); - send_formatted_event(priv, "Reassociate request (ex)", mlme, 1); - - if (priv->iw_mode != IW_MODE_MASTER - && mlmeex->state != DOT11_STATE_ASSOCING) - break; - - confirm = kmalloc(sizeof(struct obj_mlmeex), GFP_ATOMIC); - - if (!confirm) - break; - - memcpy(&confirm->address, mlmeex->address, ETH_ALEN); - - confirm->id = mlmeex->id; - confirm->state = 0; /* not used */ - confirm->code = 0; - - wpa_ie_len = prism54_wpa_bss_ie_get(priv, mlmeex->address, wpa_ie); - - if (!wpa_ie_len) { - printk(KERN_DEBUG "No WPA IE found from address:\t%pM\n", - mlmeex->address); - kfree(confirm); - break; - } - - confirm->size = wpa_ie_len; - memcpy(&confirm->data, wpa_ie, wpa_ie_len); - - mgt_set_varlen(priv, oid, confirm, wpa_ie_len); - - kfree(confirm); - - break; - - default: - return -EINVAL; - } - - return 0; -} - -/* - * Process a device trap. This is called via schedule_work(), outside of - * interrupt context, no locks held. - */ -void -prism54_process_trap(struct work_struct *work) -{ - struct islpci_mgmtframe *frame = - container_of(work, struct islpci_mgmtframe, ws); - struct net_device *ndev = frame->ndev; - enum oid_num_t n = mgt_oidtonum(frame->header->oid); - - if (n != OID_NUM_LAST) - prism54_process_trap_helper(netdev_priv(ndev), n, frame->data); - islpci_mgt_release(frame); -} - -int -prism54_set_mac_address(struct net_device *ndev, void *addr) -{ - islpci_private *priv = netdev_priv(ndev); - int ret; - - if (ndev->addr_len != 6) - return -EINVAL; - ret = mgt_set_request(priv, GEN_OID_MACADDRESS, 0, - &((struct sockaddr *) addr)->sa_data); - if (!ret) - memcpy(priv->ndev->dev_addr, - &((struct sockaddr *) addr)->sa_data, 6); - - return ret; -} - -/* Note: currently, use hostapd ioctl from the Host AP driver for WPA - * support. This is to be replaced with Linux wireless extensions once they - * get WPA support. */ - -/* Note II: please leave all this together as it will be easier to remove later, - * once wireless extensions add WPA support -mcgrof */ - -/* PRISM54_HOSTAPD ioctl() cmd: */ -enum { - PRISM2_SET_ENCRYPTION = 6, - PRISM2_HOSTAPD_SET_GENERIC_ELEMENT = 12, - PRISM2_HOSTAPD_MLME = 13, - PRISM2_HOSTAPD_SCAN_REQ = 14, -}; - -#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 -#define PRISM54_HOSTAPD SIOCIWFIRSTPRIV+25 -#define PRISM54_DROP_UNENCRYPTED SIOCIWFIRSTPRIV+26 - -#define PRISM2_HOSTAPD_MAX_BUF_SIZE 1024 -#define PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN \ - offsetof(struct prism2_hostapd_param, u.generic_elem.data) - -/* Maximum length for algorithm names (-1 for nul termination) - * used in ioctl() */ -#define HOSTAP_CRYPT_ALG_NAME_LEN 16 - -struct prism2_hostapd_param { - u32 cmd; - u8 sta_addr[ETH_ALEN]; - union { - struct { - u8 alg[HOSTAP_CRYPT_ALG_NAME_LEN]; - u32 flags; - u32 err; - u8 idx; - u8 seq[8]; /* sequence counter (set: RX, get: TX) */ - u16 key_len; - u8 key[0]; - } crypt; - struct { - u8 len; - u8 data[0]; - } generic_elem; - struct { -#define MLME_STA_DEAUTH 0 -#define MLME_STA_DISASSOC 1 - u16 cmd; - u16 reason_code; - } mlme; - struct { - u8 ssid_len; - u8 ssid[32]; - } scan_req; - } u; -}; - - -static int -prism2_ioctl_set_encryption(struct net_device *dev, - struct prism2_hostapd_param *param, - int param_len) -{ - islpci_private *priv = netdev_priv(dev); - int rvalue = 0, force = 0; - int authen = DOT11_AUTH_OS, invoke = 0, exunencrypt = 0; - union oid_res_t r; - - /* with the new API, it's impossible to get a NULL pointer. - * New version of iwconfig set the IW_ENCODE_NOKEY flag - * when no key is given, but older versions don't. */ - - if (param->u.crypt.key_len > 0) { - /* we have a key to set */ - int index = param->u.crypt.idx; - int current_index; - struct obj_key key = { DOT11_PRIV_TKIP, 0, "" }; - - /* get the current key index */ - rvalue = mgt_get_request(priv, DOT11_OID_DEFKEYID, 0, NULL, &r); - current_index = r.u; - /* Verify that the key is not marked as invalid */ - if (!(param->u.crypt.flags & IW_ENCODE_NOKEY)) { - key.length = param->u.crypt.key_len > sizeof (param->u.crypt.key) ? - sizeof (param->u.crypt.key) : param->u.crypt.key_len; - memcpy(key.key, param->u.crypt.key, key.length); - if (key.length == 32) - /* we want WPA-PSK */ - key.type = DOT11_PRIV_TKIP; - if ((index < 0) || (index > 3)) - /* no index provided use the current one */ - index = current_index; - - /* now send the key to the card */ - rvalue |= - mgt_set_request(priv, DOT11_OID_DEFKEYX, index, - &key); - } - /* - * If a valid key is set, encryption should be enabled - * (user may turn it off later). - * This is also how "iwconfig ethX key on" works - */ - if ((index == current_index) && (key.length > 0)) - force = 1; - } else { - int index = (param->u.crypt.flags & IW_ENCODE_INDEX) - 1; - if ((index >= 0) && (index <= 3)) { - /* we want to set the key index */ - rvalue |= - mgt_set_request(priv, DOT11_OID_DEFKEYID, 0, - &index); - } else { - if (!(param->u.crypt.flags & IW_ENCODE_MODE)) { - /* we cannot do anything. Complain. */ - return -EINVAL; - } - } - } - /* now read the flags */ - if (param->u.crypt.flags & IW_ENCODE_DISABLED) { - /* Encoding disabled, - * authen = DOT11_AUTH_OS; - * invoke = 0; - * exunencrypt = 0; */ - } - if (param->u.crypt.flags & IW_ENCODE_OPEN) - /* Encode but accept non-encoded packets. No auth */ - invoke = 1; - if ((param->u.crypt.flags & IW_ENCODE_RESTRICTED) || force) { - /* Refuse non-encoded packets. Auth */ - authen = DOT11_AUTH_BOTH; - invoke = 1; - exunencrypt = 1; - } - /* do the change if requested */ - if ((param->u.crypt.flags & IW_ENCODE_MODE) || force) { - rvalue |= - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - rvalue |= - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &invoke); - rvalue |= - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, - &exunencrypt); - } - return rvalue; -} - -static int -prism2_ioctl_set_generic_element(struct net_device *ndev, - struct prism2_hostapd_param *param, - int param_len) -{ - islpci_private *priv = netdev_priv(ndev); - int max_len, len, alen, ret=0; - struct obj_attachment *attach; - - len = param->u.generic_elem.len; - max_len = param_len - PRISM2_HOSTAPD_GENERIC_ELEMENT_HDR_LEN; - if (max_len < 0 || max_len < len) - return -EINVAL; - - alen = sizeof(*attach) + len; - attach = kzalloc(alen, GFP_KERNEL); - if (attach == NULL) - return -ENOMEM; - -#define WLAN_FC_TYPE_MGMT 0 -#define WLAN_FC_STYPE_ASSOC_REQ 0 -#define WLAN_FC_STYPE_REASSOC_REQ 2 - - /* Note: endianness is covered by mgt_set_varlen */ - - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_ASSOC_REQ << 4); - attach->id = -1; - attach->size = len; - memcpy(attach->data, param->u.generic_elem.data, len); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); - - if (ret == 0) { - attach->type = (WLAN_FC_TYPE_MGMT << 2) | - (WLAN_FC_STYPE_REASSOC_REQ << 4); - - ret = mgt_set_varlen(priv, DOT11_OID_ATTACHMENT, attach, len); - - if (ret == 0) - printk(KERN_DEBUG "%s: WPA IE Attachment was set\n", - ndev->name); - } - - kfree(attach); - return ret; - -} - -static int -prism2_ioctl_mlme(struct net_device *dev, struct prism2_hostapd_param *param) -{ - return -EOPNOTSUPP; -} - -static int -prism2_ioctl_scan_req(struct net_device *ndev, - struct prism2_hostapd_param *param) -{ - islpci_private *priv = netdev_priv(ndev); - struct iw_request_info info; - int i, rvalue; - struct obj_bsslist *bsslist; - u32 noise = 0; - char *extra = ""; - char *current_ev = "foo"; - union oid_res_t r; - - if (islpci_get_state(priv) < PRV_STATE_INIT) { - /* device is not ready, fail gently */ - return 0; - } - - /* first get the noise value. We will use it to report the link quality */ - rvalue = mgt_get_request(priv, DOT11_OID_NOISEFLOOR, 0, NULL, &r); - noise = r.u; - - /* Ask the device for a list of known bss. We can report at most - * IW_MAX_AP=64 to the range struct. But the device won't repport anything - * if you change the value of IWMAX_BSS=24. - */ - rvalue |= mgt_get_request(priv, DOT11_OID_BSSLIST, 0, NULL, &r); - bsslist = r.ptr; - - info.cmd = PRISM54_HOSTAPD; - info.flags = 0; - - /* ok now, scan the list and translate its info */ - for (i = 0; i < min(IW_MAX_AP, (int) bsslist->nr); i++) - current_ev = prism54_translate_bss(ndev, &info, current_ev, - extra + IW_SCAN_MAX_DATA, - &(bsslist->bsslist[i]), - noise); - kfree(bsslist); - - return rvalue; -} - -static int -prism54_hostapd(struct net_device *ndev, struct iw_point *p) -{ - struct prism2_hostapd_param *param; - int ret = 0; - u32 uwrq; - - printk(KERN_DEBUG "prism54_hostapd - len=%d\n", p->length); - if (p->length < sizeof(struct prism2_hostapd_param) || - p->length > PRISM2_HOSTAPD_MAX_BUF_SIZE || !p->pointer) - return -EINVAL; - - param = kmalloc(p->length, GFP_KERNEL); - if (param == NULL) - return -ENOMEM; - - if (copy_from_user(param, p->pointer, p->length)) { - kfree(param); - return -EFAULT; - } - - switch (param->cmd) { - case PRISM2_SET_ENCRYPTION: - printk(KERN_DEBUG "%s: Caught WPA supplicant set encryption request\n", - ndev->name); - ret = prism2_ioctl_set_encryption(ndev, param, p->length); - break; - case PRISM2_HOSTAPD_SET_GENERIC_ELEMENT: - printk(KERN_DEBUG "%s: Caught WPA supplicant set WPA IE request\n", - ndev->name); - ret = prism2_ioctl_set_generic_element(ndev, param, - p->length); - break; - case PRISM2_HOSTAPD_MLME: - printk(KERN_DEBUG "%s: Caught WPA supplicant MLME request\n", - ndev->name); - ret = prism2_ioctl_mlme(ndev, param); - break; - case PRISM2_HOSTAPD_SCAN_REQ: - printk(KERN_DEBUG "%s: Caught WPA supplicant scan request\n", - ndev->name); - ret = prism2_ioctl_scan_req(ndev, param); - break; - case PRISM54_SET_WPA: - printk(KERN_DEBUG "%s: Caught WPA supplicant wpa init request\n", - ndev->name); - uwrq = 1; - ret = prism54_set_wpa(ndev, NULL, &uwrq, NULL); - break; - case PRISM54_DROP_UNENCRYPTED: - printk(KERN_DEBUG "%s: Caught WPA drop unencrypted request\n", - ndev->name); -#if 0 - uwrq = 0x01; - mgt_set(priv, DOT11_OID_EXUNENCRYPTED, &uwrq); - down_write(&priv->mib_sem); - mgt_commit(priv); - up_write(&priv->mib_sem); -#endif - /* Not necessary, as set_wpa does it, should we just do it here though? */ - ret = 0; - break; - default: - printk(KERN_DEBUG "%s: Caught a WPA supplicant request that is not supported\n", - ndev->name); - ret = -EOPNOTSUPP; - break; - } - - if (ret == 0 && copy_to_user(p->pointer, param, p->length)) - ret = -EFAULT; - - kfree(param); - - return ret; -} - -static int -prism54_set_wpa(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 mlme, authen, dot1x, filter, wep; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - wep = 1; /* For privacy invoked */ - filter = 1; /* Filter out all unencrypted frames */ - dot1x = 0x01; /* To enable eap filter */ - mlme = DOT11_MLME_EXTENDED; - authen = DOT11_AUTH_OS; /* Only WEP uses _SK and _BOTH */ - - down_write(&priv->mib_sem); - priv->wpa = *uwrq; - - switch (priv->wpa) { - default: - case 0: /* Clears/disables WPA and friends */ - wep = 0; - filter = 0; /* Do not filter un-encrypted data */ - dot1x = 0; - mlme = DOT11_MLME_AUTO; - printk("%s: Disabling WPA\n", ndev->name); - break; - case 2: - case 1: /* WPA */ - printk("%s: Enabling WPA\n", ndev->name); - break; - } - up_write(&priv->mib_sem); - - mgt_set_request(priv, DOT11_OID_AUTHENABLE, 0, &authen); - mgt_set_request(priv, DOT11_OID_PRIVACYINVOKED, 0, &wep); - mgt_set_request(priv, DOT11_OID_EXUNENCRYPTED, 0, &filter); - mgt_set_request(priv, DOT11_OID_DOT1XENABLE, 0, &dot1x); - mgt_set_request(priv, DOT11_OID_MLMEAUTOLEVEL, 0, &mlme); - - return 0; -} - -static int -prism54_get_wpa(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - *uwrq = priv->wpa; - return 0; -} - -static int -prism54_set_prismhdr(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - priv->monitor_type = - (*uwrq ? ARPHRD_IEEE80211_PRISM : ARPHRD_IEEE80211); - if (priv->iw_mode == IW_MODE_MONITOR) - priv->ndev->type = priv->monitor_type; - - return 0; -} - -static int -prism54_get_prismhdr(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - *uwrq = (priv->monitor_type == ARPHRD_IEEE80211_PRISM); - return 0; -} - -static int -prism54_debug_oid(struct net_device *ndev, struct iw_request_info *info, - __u32 * uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - - priv->priv_oid = *uwrq; - printk("%s: oid 0x%08X\n", ndev->name, *uwrq); - - return 0; -} - -static int -prism54_debug_get_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_mgmtframe *response; - int ret = -EIO; - - printk("%s: get_oid 0x%08X\n", ndev->name, priv->priv_oid); - data->length = 0; - - if (islpci_get_state(priv) >= PRV_STATE_INIT) { - ret = - islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, - priv->priv_oid, extra, 256, - &response); - printk("%s: ret: %i\n", ndev->name, ret); - if (ret || !response - || response->header->operation == PIMFOR_OP_ERROR) { - if (response) { - islpci_mgt_release(response); - } - printk("%s: EIO\n", ndev->name); - ret = -EIO; - } - if (!ret) { - data->length = response->header->length; - memcpy(extra, response->data, data->length); - islpci_mgt_release(response); - printk("%s: len: %i\n", ndev->name, data->length); - } - } - - return ret; -} - -static int -prism54_debug_set_oid(struct net_device *ndev, struct iw_request_info *info, - struct iw_point *data, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - struct islpci_mgmtframe *response; - int ret = 0, response_op = PIMFOR_OP_ERROR; - - printk("%s: set_oid 0x%08X\tlen: %d\n", ndev->name, priv->priv_oid, - data->length); - - if (islpci_get_state(priv) >= PRV_STATE_INIT) { - ret = - islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, - priv->priv_oid, extra, data->length, - &response); - printk("%s: ret: %i\n", ndev->name, ret); - if (ret || !response - || response->header->operation == PIMFOR_OP_ERROR) { - if (response) { - islpci_mgt_release(response); - } - printk("%s: EIO\n", ndev->name); - ret = -EIO; - } - if (!ret) { - response_op = response->header->operation; - printk("%s: response_op: %i\n", ndev->name, - response_op); - islpci_mgt_release(response); - } - } - - return (ret ? ret : -EINPROGRESS); -} - -static int -prism54_set_spy(struct net_device *ndev, - struct iw_request_info *info, - union iwreq_data *uwrq, char *extra) -{ - islpci_private *priv = netdev_priv(ndev); - u32 u; - enum oid_num_t oid = OID_INL_CONFIG; - - down_write(&priv->mib_sem); - mgt_get(priv, OID_INL_CONFIG, &u); - - if ((uwrq->data.length == 0) && (priv->spy_data.spy_number > 0)) - /* disable spy */ - u &= ~INL_CONFIG_RXANNEX; - else if ((uwrq->data.length > 0) && (priv->spy_data.spy_number == 0)) - /* enable spy */ - u |= INL_CONFIG_RXANNEX; - - mgt_set(priv, OID_INL_CONFIG, &u); - mgt_commit_list(priv, &oid, 1); - up_write(&priv->mib_sem); - - return iw_handler_set_spy(ndev, info, uwrq, extra); -} - -static const iw_handler prism54_handler[] = { - (iw_handler) prism54_commit, /* SIOCSIWCOMMIT */ - (iw_handler) prism54_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) prism54_set_freq, /* SIOCSIWFREQ */ - (iw_handler) prism54_get_freq, /* SIOCGIWFREQ */ - (iw_handler) prism54_set_mode, /* SIOCSIWMODE */ - (iw_handler) prism54_get_mode, /* SIOCGIWMODE */ - (iw_handler) prism54_set_sens, /* SIOCSIWSENS */ - (iw_handler) prism54_get_sens, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) prism54_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - prism54_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - (iw_handler) prism54_set_wap, /* SIOCSIWAP */ - (iw_handler) prism54_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST deprecated */ - (iw_handler) prism54_set_scan, /* SIOCSIWSCAN */ - (iw_handler) prism54_get_scan, /* SIOCGIWSCAN */ - (iw_handler) prism54_set_essid, /* SIOCSIWESSID */ - (iw_handler) prism54_get_essid, /* SIOCGIWESSID */ - (iw_handler) prism54_set_nick, /* SIOCSIWNICKN */ - (iw_handler) prism54_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) prism54_set_rate, /* SIOCSIWRATE */ - (iw_handler) prism54_get_rate, /* SIOCGIWRATE */ - (iw_handler) prism54_set_rts, /* SIOCSIWRTS */ - (iw_handler) prism54_get_rts, /* SIOCGIWRTS */ - (iw_handler) prism54_set_frag, /* SIOCSIWFRAG */ - (iw_handler) prism54_get_frag, /* SIOCGIWFRAG */ - (iw_handler) prism54_set_txpower, /* SIOCSIWTXPOW */ - (iw_handler) prism54_get_txpower, /* SIOCGIWTXPOW */ - (iw_handler) prism54_set_retry, /* SIOCSIWRETRY */ - (iw_handler) prism54_get_retry, /* SIOCGIWRETRY */ - (iw_handler) prism54_set_encode, /* SIOCSIWENCODE */ - (iw_handler) prism54_get_encode, /* SIOCGIWENCODE */ - (iw_handler) NULL, /* SIOCSIWPOWER */ - (iw_handler) NULL, /* SIOCGIWPOWER */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - (iw_handler) prism54_set_genie, /* SIOCSIWGENIE */ - (iw_handler) prism54_get_genie, /* SIOCGIWGENIE */ - (iw_handler) prism54_set_auth, /* SIOCSIWAUTH */ - (iw_handler) prism54_get_auth, /* SIOCGIWAUTH */ - (iw_handler) prism54_set_encodeext, /* SIOCSIWENCODEEXT */ - (iw_handler) prism54_get_encodeext, /* SIOCGIWENCODEEXT */ - NULL, /* SIOCSIWPMKSA */ -}; - -/* The low order bit identify a SET (0) or a GET (1) ioctl. */ - -#define PRISM54_RESET SIOCIWFIRSTPRIV -#define PRISM54_GET_POLICY SIOCIWFIRSTPRIV+1 -#define PRISM54_SET_POLICY SIOCIWFIRSTPRIV+2 -#define PRISM54_GET_MAC SIOCIWFIRSTPRIV+3 -#define PRISM54_ADD_MAC SIOCIWFIRSTPRIV+4 - -#define PRISM54_DEL_MAC SIOCIWFIRSTPRIV+6 - -#define PRISM54_KICK_MAC SIOCIWFIRSTPRIV+8 - -#define PRISM54_KICK_ALL SIOCIWFIRSTPRIV+10 - -#define PRISM54_GET_WPA SIOCIWFIRSTPRIV+11 -#define PRISM54_SET_WPA SIOCIWFIRSTPRIV+12 - -#define PRISM54_DBG_OID SIOCIWFIRSTPRIV+14 -#define PRISM54_DBG_GET_OID SIOCIWFIRSTPRIV+15 -#define PRISM54_DBG_SET_OID SIOCIWFIRSTPRIV+16 - -#define PRISM54_GET_OID SIOCIWFIRSTPRIV+17 -#define PRISM54_SET_OID_U32 SIOCIWFIRSTPRIV+18 -#define PRISM54_SET_OID_STR SIOCIWFIRSTPRIV+20 -#define PRISM54_SET_OID_ADDR SIOCIWFIRSTPRIV+22 - -#define PRISM54_GET_PRISMHDR SIOCIWFIRSTPRIV+23 -#define PRISM54_SET_PRISMHDR SIOCIWFIRSTPRIV+24 - -#define IWPRIV_SET_U32(n,x) { n, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } -#define IWPRIV_SET_SSID(n,x) { n, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } -#define IWPRIV_SET_ADDR(n,x) { n, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, "s_"x } -#define IWPRIV_GET(n,x) { n, 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, "g_"x } - -#define IWPRIV_U32(n,x) IWPRIV_SET_U32(n,x), IWPRIV_GET(n,x) -#define IWPRIV_SSID(n,x) IWPRIV_SET_SSID(n,x), IWPRIV_GET(n,x) -#define IWPRIV_ADDR(n,x) IWPRIV_SET_ADDR(n,x), IWPRIV_GET(n,x) - -/* Note : limited to 128 private ioctls (wireless tools 26) */ - -static const struct iw_priv_args prism54_private_args[] = { -/*{ cmd, set_args, get_args, name } */ - {PRISM54_RESET, 0, 0, "reset"}, - {PRISM54_GET_PRISMHDR, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_prismhdr"}, - {PRISM54_SET_PRISMHDR, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, - "set_prismhdr"}, - {PRISM54_GET_POLICY, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "getPolicy"}, - {PRISM54_SET_POLICY, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, - "setPolicy"}, - {PRISM54_GET_MAC, 0, IW_PRIV_TYPE_ADDR | 64, "getMac"}, - {PRISM54_ADD_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, - "addMac"}, - {PRISM54_DEL_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, - "delMac"}, - {PRISM54_KICK_MAC, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, - "kickMac"}, - {PRISM54_KICK_ALL, 0, 0, "kickAll"}, - {PRISM54_GET_WPA, 0, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - "get_wpa"}, - {PRISM54_SET_WPA, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, - "set_wpa"}, - {PRISM54_DBG_OID, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, - "dbg_oid"}, - {PRISM54_DBG_GET_OID, 0, IW_PRIV_TYPE_BYTE | 256, "dbg_get_oid"}, - {PRISM54_DBG_SET_OID, IW_PRIV_TYPE_BYTE | 256, 0, "dbg_set_oid"}, - /* --- sub-ioctls handlers --- */ - {PRISM54_GET_OID, - 0, IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | PRIV_STR_SIZE, ""}, - {PRISM54_SET_OID_U32, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, ""}, - {PRISM54_SET_OID_STR, - IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | 1, 0, ""}, - {PRISM54_SET_OID_ADDR, - IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, 0, ""}, - /* --- sub-ioctls definitions --- */ - IWPRIV_ADDR(GEN_OID_MACADDRESS, "addr"), - IWPRIV_GET(GEN_OID_LINKSTATE, "linkstate"), - IWPRIV_U32(DOT11_OID_BSSTYPE, "bsstype"), - IWPRIV_ADDR(DOT11_OID_BSSID, "bssid"), - IWPRIV_U32(DOT11_OID_STATE, "state"), - IWPRIV_U32(DOT11_OID_AID, "aid"), - - IWPRIV_SSID(DOT11_OID_SSIDOVERRIDE, "ssidoverride"), - - IWPRIV_U32(DOT11_OID_MEDIUMLIMIT, "medlimit"), - IWPRIV_U32(DOT11_OID_BEACONPERIOD, "beacon"), - IWPRIV_U32(DOT11_OID_DTIMPERIOD, "dtimperiod"), - - IWPRIV_U32(DOT11_OID_AUTHENABLE, "authenable"), - IWPRIV_U32(DOT11_OID_PRIVACYINVOKED, "privinvok"), - IWPRIV_U32(DOT11_OID_EXUNENCRYPTED, "exunencrypt"), - - IWPRIV_U32(DOT11_OID_REKEYTHRESHOLD, "rekeythresh"), - - IWPRIV_U32(DOT11_OID_MAXTXLIFETIME, "maxtxlife"), - IWPRIV_U32(DOT11_OID_MAXRXLIFETIME, "maxrxlife"), - IWPRIV_U32(DOT11_OID_ALOFT_FIXEDRATE, "fixedrate"), - IWPRIV_U32(DOT11_OID_MAXFRAMEBURST, "frameburst"), - IWPRIV_U32(DOT11_OID_PSM, "psm"), - - IWPRIV_U32(DOT11_OID_BRIDGELOCAL, "bridge"), - IWPRIV_U32(DOT11_OID_CLIENTS, "clients"), - IWPRIV_U32(DOT11_OID_CLIENTSASSOCIATED, "clientassoc"), - IWPRIV_U32(DOT11_OID_DOT1XENABLE, "dot1xenable"), - IWPRIV_U32(DOT11_OID_ANTENNARX, "rxant"), - IWPRIV_U32(DOT11_OID_ANTENNATX, "txant"), - IWPRIV_U32(DOT11_OID_ANTENNADIVERSITY, "antdivers"), - IWPRIV_U32(DOT11_OID_EDTHRESHOLD, "edthresh"), - IWPRIV_U32(DOT11_OID_PREAMBLESETTINGS, "preamble"), - IWPRIV_GET(DOT11_OID_RATES, "rates"), - IWPRIV_U32(DOT11_OID_OUTPUTPOWER, ".11outpower"), - IWPRIV_GET(DOT11_OID_SUPPORTEDRATES, "supprates"), - IWPRIV_GET(DOT11_OID_SUPPORTEDFREQUENCIES, "suppfreq"), - - IWPRIV_U32(DOT11_OID_NOISEFLOOR, "noisefloor"), - IWPRIV_GET(DOT11_OID_FREQUENCYACTIVITY, "freqactivity"), - IWPRIV_U32(DOT11_OID_NONERPPROTECTION, "nonerpprotec"), - IWPRIV_U32(DOT11_OID_PROFILES, "profile"), - IWPRIV_GET(DOT11_OID_EXTENDEDRATES, "extrates"), - IWPRIV_U32(DOT11_OID_MLMEAUTOLEVEL, "mlmelevel"), - - IWPRIV_GET(DOT11_OID_BSSS, "bsss"), - IWPRIV_GET(DOT11_OID_BSSLIST, "bsslist"), - IWPRIV_U32(OID_INL_MODE, "mode"), - IWPRIV_U32(OID_INL_CONFIG, "config"), - IWPRIV_U32(OID_INL_DOT11D_CONFORMANCE, ".11dconform"), - IWPRIV_GET(OID_INL_PHYCAPABILITIES, "phycapa"), - IWPRIV_U32(OID_INL_OUTPUTPOWER, "outpower"), -}; - -static const iw_handler prism54_private_handler[] = { - (iw_handler) prism54_reset, - (iw_handler) prism54_get_policy, - (iw_handler) prism54_set_policy, - (iw_handler) prism54_get_mac, - (iw_handler) prism54_add_mac, - (iw_handler) NULL, - (iw_handler) prism54_del_mac, - (iw_handler) NULL, - (iw_handler) prism54_kick_mac, - (iw_handler) NULL, - (iw_handler) prism54_kick_all, - (iw_handler) prism54_get_wpa, - (iw_handler) prism54_set_wpa, - (iw_handler) NULL, - (iw_handler) prism54_debug_oid, - (iw_handler) prism54_debug_get_oid, - (iw_handler) prism54_debug_set_oid, - (iw_handler) prism54_get_oid, - (iw_handler) prism54_set_u32, - (iw_handler) NULL, - (iw_handler) prism54_set_raw, - (iw_handler) NULL, - (iw_handler) prism54_set_raw, - (iw_handler) prism54_get_prismhdr, - (iw_handler) prism54_set_prismhdr, -}; - -const struct iw_handler_def prism54_handler_def = { - .num_standard = ARRAY_SIZE(prism54_handler), - .num_private = ARRAY_SIZE(prism54_private_handler), - .num_private_args = ARRAY_SIZE(prism54_private_args), - .standard = (iw_handler *) prism54_handler, - .private = (iw_handler *) prism54_private_handler, - .private_args = (struct iw_priv_args *) prism54_private_args, - .get_wireless_stats = prism54_get_wireless_stats, -}; - -/* For wpa_supplicant */ - -int -prism54_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) -{ - struct iwreq *wrq = (struct iwreq *) rq; - int ret = -1; - switch (cmd) { - case PRISM54_HOSTAPD: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - ret = prism54_hostapd(ndev, &wrq->u.data); - return ret; - } - return -EOPNOTSUPP; -} diff --git a/drivers/net/wireless/prism54/isl_ioctl.h b/drivers/net/wireless/prism54/isl_ioctl.h deleted file mode 100644 index bcfbfb9281d2..000000000000 --- a/drivers/net/wireless/prism54/isl_ioctl.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * (C) 2003 Aurelien Alleaume - * (C) 2003 Luis R. Rodriguez - * - * 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 - * - * 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 - * - */ - -#ifndef _ISL_IOCTL_H -#define _ISL_IOCTL_H - -#include "islpci_mgt.h" -#include "islpci_dev.h" - -#include /* New driver API */ - -#define SUPPORTED_WIRELESS_EXT 19 - -void prism54_mib_init(islpci_private *); - -struct iw_statistics *prism54_get_wireless_stats(struct net_device *); -void prism54_update_stats(struct work_struct *); - -void prism54_acl_init(struct islpci_acl *); -void prism54_acl_clean(struct islpci_acl *); - -void prism54_process_trap(struct work_struct *); - -void prism54_wpa_bss_ie_init(islpci_private *priv); -void prism54_wpa_bss_ie_clean(islpci_private *priv); - -int prism54_set_mac_address(struct net_device *, void *); - -int prism54_ioctl(struct net_device *, struct ifreq *, int); - -extern const struct iw_handler_def prism54_handler_def; - -#endif /* _ISL_IOCTL_H */ diff --git a/drivers/net/wireless/prism54/isl_oid.h b/drivers/net/wireless/prism54/isl_oid.h deleted file mode 100644 index b7534c2869c8..000000000000 --- a/drivers/net/wireless/prism54/isl_oid.h +++ /dev/null @@ -1,505 +0,0 @@ -/* - * Copyright (C) 2003 Herbert Valerio Riedel - * Copyright (C) 2004 Luis R. Rodriguez - * Copyright (C) 2004 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#if !defined(_ISL_OID_H) -#define _ISL_OID_H - -/* - * MIB related constant and structure definitions for communicating - * with the device firmware - */ - -struct obj_ssid { - u8 length; - char octets[33]; -} __attribute__ ((packed)); - -struct obj_key { - u8 type; /* dot11_priv_t */ - u8 length; - char key[32]; -} __attribute__ ((packed)); - -struct obj_mlme { - u8 address[6]; - u16 id; - u16 state; - u16 code; -} __attribute__ ((packed)); - -struct obj_mlmeex { - u8 address[6]; - u16 id; - u16 state; - u16 code; - u16 size; - u8 data[0]; -} __attribute__ ((packed)); - -struct obj_buffer { - u32 size; - u32 addr; /* 32bit bus address */ -} __attribute__ ((packed)); - -struct obj_bss { - u8 address[6]; - int:16; /* padding */ - - char state; - char reserved; - short age; - - char quality; - char rssi; - - struct obj_ssid ssid; - short channel; - char beacon_period; - char dtim_period; - short capinfo; - short rates; - short basic_rates; - int:16; /* padding */ -} __attribute__ ((packed)); - -struct obj_bsslist { - u32 nr; - struct obj_bss bsslist[0]; -} __attribute__ ((packed)); - -struct obj_frequencies { - u16 nr; - u16 mhz[0]; -} __attribute__ ((packed)); - -struct obj_attachment { - char type; - char reserved; - short id; - short size; - char data[0]; -} __attribute__((packed)); - -/* - * in case everything's ok, the inlined function below will be - * optimized away by the compiler... - */ -static inline void -__bug_on_wrong_struct_sizes(void) -{ - BUILD_BUG_ON(sizeof (struct obj_ssid) != 34); - BUILD_BUG_ON(sizeof (struct obj_key) != 34); - BUILD_BUG_ON(sizeof (struct obj_mlme) != 12); - BUILD_BUG_ON(sizeof (struct obj_mlmeex) != 14); - BUILD_BUG_ON(sizeof (struct obj_buffer) != 8); - BUILD_BUG_ON(sizeof (struct obj_bss) != 60); - BUILD_BUG_ON(sizeof (struct obj_bsslist) != 4); - BUILD_BUG_ON(sizeof (struct obj_frequencies) != 2); -} - -enum dot11_state_t { - DOT11_STATE_NONE = 0, - DOT11_STATE_AUTHING = 1, - DOT11_STATE_AUTH = 2, - DOT11_STATE_ASSOCING = 3, - - DOT11_STATE_ASSOC = 5, - DOT11_STATE_IBSS = 6, - DOT11_STATE_WDS = 7 -}; - -enum dot11_bsstype_t { - DOT11_BSSTYPE_NONE = 0, - DOT11_BSSTYPE_INFRA = 1, - DOT11_BSSTYPE_IBSS = 2, - DOT11_BSSTYPE_ANY = 3 -}; - -enum dot11_auth_t { - DOT11_AUTH_NONE = 0, - DOT11_AUTH_OS = 1, - DOT11_AUTH_SK = 2, - DOT11_AUTH_BOTH = 3 -}; - -enum dot11_mlme_t { - DOT11_MLME_AUTO = 0, - DOT11_MLME_INTERMEDIATE = 1, - DOT11_MLME_EXTENDED = 2 -}; - -enum dot11_priv_t { - DOT11_PRIV_WEP = 0, - DOT11_PRIV_TKIP = 1 -}; - -/* Prism "Nitro" / Frameburst / "Packet Frame Grouping" - * Value is in microseconds. Represents the # microseconds - * the firmware will take to group frames before sending out then out - * together with a CSMA contention. Without this all frames are - * sent with a CSMA contention. - * Bibliography: - * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Papers/Packet.Frame.Grouping.html - */ -enum dot11_maxframeburst_t { - /* Values for DOT11_OID_MAXFRAMEBURST */ - DOT11_MAXFRAMEBURST_OFF = 0, /* Card firmware default */ - DOT11_MAXFRAMEBURST_MIXED_SAFE = 650, /* 802.11 a,b,g safe */ - DOT11_MAXFRAMEBURST_IDEAL = 1300, /* Theoretical ideal level */ - DOT11_MAXFRAMEBURST_MAX = 5000, /* Use this as max, - * Note: firmware allows for greater values. This is a - * recommended max. I'll update this as I find - * out what the real MAX is. Also note that you don't necessarily - * get better results with a greater value here. - */ -}; - -/* Support for 802.11 long and short frame preambles. - * Long preamble uses 128-bit sync field, 8-bit CRC - * Short preamble uses 56-bit sync field, 16-bit CRC - * - * 802.11a -- not sure, both optionally ? - * 802.11b supports long and optionally short - * 802.11g supports both */ -enum dot11_preamblesettings_t { - DOT11_PREAMBLESETTING_LONG = 0, - /* Allows *only* long 802.11 preambles */ - DOT11_PREAMBLESETTING_SHORT = 1, - /* Allows *only* short 802.11 preambles */ - DOT11_PREAMBLESETTING_DYNAMIC = 2 - /* AutomatiGically set */ -}; - -/* Support for 802.11 slot timing (time between packets). - * - * Long uses 802.11a slot timing (9 usec ?) - * Short uses 802.11b slot timing (20 use ?) */ -enum dot11_slotsettings_t { - DOT11_SLOTSETTINGS_LONG = 0, - /* Allows *only* long 802.11b slot timing */ - DOT11_SLOTSETTINGS_SHORT = 1, - /* Allows *only* long 802.11a slot timing */ - DOT11_SLOTSETTINGS_DYNAMIC = 2 - /* AutomatiGically set */ -}; - -/* All you need to know, ERP is "Extended Rate PHY". - * An Extended Rate PHY (ERP) STA or AP shall support three different - * preamble and header formats: - * Long preamble (refer to above) - * Short preamble (refer to above) - * OFDM preamble ( ? ) - * - * I'm assuming here Protection tells the AP - * to be careful, a STA which cannot handle the long pre-amble - * has joined. - */ -enum do11_nonerpstatus_t { - DOT11_ERPSTAT_NONEPRESENT = 0, - DOT11_ERPSTAT_USEPROTECTION = 1 -}; - -/* (ERP is "Extended Rate PHY") Way to read NONERP is NON-ERP-* - * The key here is DOT11 NON ERP NEVER protects against - * NON ERP STA's. You *don't* want this unless - * you know what you are doing. It means you will only - * get Extended Rate capabilities */ -enum dot11_nonerpprotection_t { - DOT11_NONERP_NEVER = 0, - DOT11_NONERP_ALWAYS = 1, - DOT11_NONERP_DYNAMIC = 2 -}; - -/* Preset OID configuration for 802.11 modes - * Note: DOT11_OID_CW[MIN|MAX] hold the values of the - * DCS MIN|MAX backoff used */ -enum dot11_profile_t { /* And set/allowed values */ - /* Allowed values for DOT11_OID_PROFILES */ - DOT11_PROFILE_B_ONLY = 0, - /* DOT11_OID_RATES: 1, 2, 5.5, 11Mbps - * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC - * DOT11_OID_CWMIN: 31 - * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC - * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_LONG - */ - DOT11_PROFILE_MIXED_G_WIFI = 1, - /* DOT11_OID_RATES: 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54Mbs - * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_DYNAMIC - * DOT11_OID_CWMIN: 15 - * DOT11_OID_NONEPROTECTION: DOT11_NOERP_DYNAMIC - * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_DYNAMIC - */ - DOT11_PROFILE_MIXED_LONG = 2, /* "Long range" */ - /* Same as Profile MIXED_G_WIFI */ - DOT11_PROFILE_G_ONLY = 3, - /* Same as Profile MIXED_G_WIFI */ - DOT11_PROFILE_TEST = 4, - /* Same as Profile MIXED_G_WIFI except: - * DOT11_OID_PREAMBLESETTINGS: DOT11_PREAMBLESETTING_SHORT - * DOT11_OID_NONEPROTECTION: DOT11_NOERP_NEVER - * DOT11_OID_SLOTSETTINGS: DOT11_SLOTSETTINGS_SHORT - */ - DOT11_PROFILE_B_WIFI = 5, - /* Same as Profile B_ONLY */ - DOT11_PROFILE_A_ONLY = 6, - /* Same as Profile MIXED_G_WIFI except: - * DOT11_OID_RATES: 6, 9, 12, 18, 24, 36, 48, 54Mbs - */ - DOT11_PROFILE_MIXED_SHORT = 7 - /* Same as MIXED_G_WIFI */ -}; - - -/* The dot11d conformance level configures the 802.11d conformance levels. - * The following conformance levels exist:*/ -enum oid_inl_conformance_t { - OID_INL_CONFORMANCE_NONE = 0, /* Perform active scanning */ - OID_INL_CONFORMANCE_STRICT = 1, /* Strictly adhere to 802.11d */ - OID_INL_CONFORMANCE_FLEXIBLE = 2, /* Use passed 802.11d info to - * determine channel AND/OR just make assumption that active - * channels are valid channels */ -}; - -enum oid_inl_mode_t { - INL_MODE_NONE = -1, - INL_MODE_PROMISCUOUS = 0, - INL_MODE_CLIENT = 1, - INL_MODE_AP = 2, - INL_MODE_SNIFFER = 3 -}; - -enum oid_inl_config_t { - INL_CONFIG_NOTHING = 0x00, - INL_CONFIG_MANUALRUN = 0x01, - INL_CONFIG_FRAMETRAP = 0x02, - INL_CONFIG_RXANNEX = 0x04, - INL_CONFIG_TXANNEX = 0x08, - INL_CONFIG_WDS = 0x10 -}; - -enum oid_inl_phycap_t { - INL_PHYCAP_2400MHZ = 1, - INL_PHYCAP_5000MHZ = 2, - INL_PHYCAP_FAA = 0x80000000, /* Means card supports the FAA switch */ -}; - - -enum oid_num_t { - GEN_OID_MACADDRESS = 0, - GEN_OID_LINKSTATE, - GEN_OID_WATCHDOG, - GEN_OID_MIBOP, - GEN_OID_OPTIONS, - GEN_OID_LEDCONFIG, - - /* 802.11 */ - DOT11_OID_BSSTYPE, - DOT11_OID_BSSID, - DOT11_OID_SSID, - DOT11_OID_STATE, - DOT11_OID_AID, - DOT11_OID_COUNTRYSTRING, - DOT11_OID_SSIDOVERRIDE, - - DOT11_OID_MEDIUMLIMIT, - DOT11_OID_BEACONPERIOD, - DOT11_OID_DTIMPERIOD, - DOT11_OID_ATIMWINDOW, - DOT11_OID_LISTENINTERVAL, - DOT11_OID_CFPPERIOD, - DOT11_OID_CFPDURATION, - - DOT11_OID_AUTHENABLE, - DOT11_OID_PRIVACYINVOKED, - DOT11_OID_EXUNENCRYPTED, - DOT11_OID_DEFKEYID, - DOT11_OID_DEFKEYX, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ - DOT11_OID_STAKEY, - DOT11_OID_REKEYTHRESHOLD, - DOT11_OID_STASC, - - DOT11_OID_PRIVTXREJECTED, - DOT11_OID_PRIVRXPLAIN, - DOT11_OID_PRIVRXFAILED, - DOT11_OID_PRIVRXNOKEY, - - DOT11_OID_RTSTHRESH, - DOT11_OID_FRAGTHRESH, - DOT11_OID_SHORTRETRIES, - DOT11_OID_LONGRETRIES, - DOT11_OID_MAXTXLIFETIME, - DOT11_OID_MAXRXLIFETIME, - DOT11_OID_AUTHRESPTIMEOUT, - DOT11_OID_ASSOCRESPTIMEOUT, - - DOT11_OID_ALOFT_TABLE, - DOT11_OID_ALOFT_CTRL_TABLE, - DOT11_OID_ALOFT_RETREAT, - DOT11_OID_ALOFT_PROGRESS, - DOT11_OID_ALOFT_FIXEDRATE, - DOT11_OID_ALOFT_RSSIGRAPH, - DOT11_OID_ALOFT_CONFIG, - - DOT11_OID_VDCFX, - DOT11_OID_MAXFRAMEBURST, - - DOT11_OID_PSM, - DOT11_OID_CAMTIMEOUT, - DOT11_OID_RECEIVEDTIMS, - DOT11_OID_ROAMPREFERENCE, - - DOT11_OID_BRIDGELOCAL, - DOT11_OID_CLIENTS, - DOT11_OID_CLIENTSASSOCIATED, - DOT11_OID_CLIENTX, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ - - DOT11_OID_CLIENTFIND, - DOT11_OID_WDSLINKADD, - DOT11_OID_WDSLINKREMOVE, - DOT11_OID_EAPAUTHSTA, - DOT11_OID_EAPUNAUTHSTA, - DOT11_OID_DOT1XENABLE, - DOT11_OID_MICFAILURE, - DOT11_OID_REKEYINDICATE, - - DOT11_OID_MPDUTXSUCCESSFUL, - DOT11_OID_MPDUTXONERETRY, - DOT11_OID_MPDUTXMULTIPLERETRIES, - DOT11_OID_MPDUTXFAILED, - DOT11_OID_MPDURXSUCCESSFUL, - DOT11_OID_MPDURXDUPS, - DOT11_OID_RTSSUCCESSFUL, - DOT11_OID_RTSFAILED, - DOT11_OID_ACKFAILED, - DOT11_OID_FRAMERECEIVES, - DOT11_OID_FRAMEERRORS, - DOT11_OID_FRAMEABORTS, - DOT11_OID_FRAMEABORTSPHY, - - DOT11_OID_SLOTTIME, - DOT11_OID_CWMIN, /* MIN DCS backoff */ - DOT11_OID_CWMAX, /* MAX DCS backoff */ - DOT11_OID_ACKWINDOW, - DOT11_OID_ANTENNARX, - DOT11_OID_ANTENNATX, - DOT11_OID_ANTENNADIVERSITY, - DOT11_OID_CHANNEL, - DOT11_OID_EDTHRESHOLD, - DOT11_OID_PREAMBLESETTINGS, - DOT11_OID_RATES, - DOT11_OID_CCAMODESUPPORTED, - DOT11_OID_CCAMODE, - DOT11_OID_RSSIVECTOR, - DOT11_OID_OUTPUTPOWERTABLE, - DOT11_OID_OUTPUTPOWER, - DOT11_OID_SUPPORTEDRATES, - DOT11_OID_FREQUENCY, - DOT11_OID_SUPPORTEDFREQUENCIES, - DOT11_OID_NOISEFLOOR, - DOT11_OID_FREQUENCYACTIVITY, - DOT11_OID_IQCALIBRATIONTABLE, - DOT11_OID_NONERPPROTECTION, - DOT11_OID_SLOTSETTINGS, - DOT11_OID_NONERPTIMEOUT, - DOT11_OID_PROFILES, - DOT11_OID_EXTENDEDRATES, - - DOT11_OID_DEAUTHENTICATE, - DOT11_OID_AUTHENTICATE, - DOT11_OID_DISASSOCIATE, - DOT11_OID_ASSOCIATE, - DOT11_OID_SCAN, - DOT11_OID_BEACON, - DOT11_OID_PROBE, - DOT11_OID_DEAUTHENTICATEEX, - DOT11_OID_AUTHENTICATEEX, - DOT11_OID_DISASSOCIATEEX, - DOT11_OID_ASSOCIATEEX, - DOT11_OID_REASSOCIATE, - DOT11_OID_REASSOCIATEEX, - - DOT11_OID_NONERPSTATUS, - - DOT11_OID_STATIMEOUT, - DOT11_OID_MLMEAUTOLEVEL, - DOT11_OID_BSSTIMEOUT, - DOT11_OID_ATTACHMENT, - DOT11_OID_PSMBUFFER, - - DOT11_OID_BSSS, - DOT11_OID_BSSX, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */ - DOT11_OID_BSSFIND, - DOT11_OID_BSSLIST, - - OID_INL_TUNNEL, - OID_INL_MEMADDR, - OID_INL_MEMORY, - OID_INL_MODE, - OID_INL_COMPONENT_NR, - OID_INL_VERSION, - OID_INL_INTERFACE_ID, - OID_INL_COMPONENT_ID, - OID_INL_CONFIG, - OID_INL_DOT11D_CONFORMANCE, - OID_INL_PHYCAPABILITIES, - OID_INL_OUTPUTPOWER, - - OID_NUM_LAST -}; - -#define OID_FLAG_CACHED 0x80 -#define OID_FLAG_TYPE 0x7f - -#define OID_TYPE_U32 0x01 -#define OID_TYPE_SSID 0x02 -#define OID_TYPE_KEY 0x03 -#define OID_TYPE_BUFFER 0x04 -#define OID_TYPE_BSS 0x05 -#define OID_TYPE_BSSLIST 0x06 -#define OID_TYPE_FREQUENCIES 0x07 -#define OID_TYPE_MLME 0x08 -#define OID_TYPE_MLMEEX 0x09 -#define OID_TYPE_ADDR 0x0A -#define OID_TYPE_RAW 0x0B -#define OID_TYPE_ATTACH 0x0C - -/* OID_TYPE_MLMEEX is special because of a variable size field when sending. - * Not yet implemented (not used in driver anyway). - */ - -struct oid_t { - enum oid_num_t oid; - short range; /* to define a range of oid */ - short size; /* max size of the associated data */ - char flags; -}; - -union oid_res_t { - void *ptr; - u32 u; -}; - -#define IWMAX_BITRATES 20 -#define IWMAX_BSS 24 -#define IWMAX_FREQ 30 -#define PRIV_STR_SIZE 1024 - -#endif /* !defined(_ISL_OID_H) */ -/* EOF */ diff --git a/drivers/net/wireless/prism54/islpci_dev.c b/drivers/net/wireless/prism54/islpci_dev.c deleted file mode 100644 index 2505be56ae39..000000000000 --- a/drivers/net/wireless/prism54/islpci_dev.c +++ /dev/null @@ -1,958 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright (C) 2003 Herbert Valerio Riedel - * Copyright (C) 2003 Luis R. Rodriguez - * - * 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 - * - * 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 - * - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "prismcompat.h" -#include "isl_38xx.h" -#include "isl_ioctl.h" -#include "islpci_dev.h" -#include "islpci_mgt.h" -#include "islpci_eth.h" -#include "oid_mgt.h" - -#define ISL3877_IMAGE_FILE "isl3877" -#define ISL3886_IMAGE_FILE "isl3886" -#define ISL3890_IMAGE_FILE "isl3890" - -static int prism54_bring_down(islpci_private *); -static int islpci_alloc_memory(islpci_private *); - -/* Temporary dummy MAC address to use until firmware is loaded. - * The idea there is that some tools (such as nameif) may query - * the MAC address before the netdev is 'open'. By using a valid - * OUI prefix, they can process the netdev properly. - * Of course, this is not the final/real MAC address. It doesn't - * matter, as you are suppose to be able to change it anytime via - * ndev->set_mac_address. Jean II */ -static const unsigned char dummy_mac[6] = { 0x00, 0x30, 0xB4, 0x00, 0x00, 0x00 }; - -static int -isl_upload_firmware(islpci_private *priv) -{ - u32 reg, rc; - void __iomem *device_base = priv->device_base; - - /* clear the RAMBoot and the Reset bit */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~ISL38XX_CTRL_STAT_RESET; - reg &= ~ISL38XX_CTRL_STAT_RAMBOOT; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the Reset bit without reading the register ! */ - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the Reset bit */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - - /* wait a while for the device to reboot */ - mdelay(50); - - { - const struct firmware *fw_entry = NULL; - long fw_len; - const u32 *fw_ptr; - - rc = request_firmware(&fw_entry, priv->firmware, PRISM_FW_PDEV); - if (rc) { - printk(KERN_ERR - "%s: request_firmware() failed for '%s'\n", - "prism54", priv->firmware); - return rc; - } - /* prepare the Direct Memory Base register */ - reg = ISL38XX_DEV_FIRMWARE_ADDRES; - - fw_ptr = (u32 *) fw_entry->data; - fw_len = fw_entry->size; - - if (fw_len % 4) { - printk(KERN_ERR - "%s: firmware '%s' size is not multiple of 32bit, aborting!\n", - "prism54", priv->firmware); - release_firmware(fw_entry); - return -EILSEQ; /* Illegal byte sequence */; - } - - while (fw_len > 0) { - long _fw_len = - (fw_len > - ISL38XX_MEMORY_WINDOW_SIZE) ? - ISL38XX_MEMORY_WINDOW_SIZE : fw_len; - u32 __iomem *dev_fw_ptr = device_base + ISL38XX_DIRECT_MEM_WIN; - - /* set the card's base address for writing the data */ - isl38xx_w32_flush(device_base, reg, - ISL38XX_DIR_MEM_BASE_REG); - wmb(); /* be paranoid */ - - /* increment the write address for next iteration */ - reg += _fw_len; - fw_len -= _fw_len; - - /* write the data to the Direct Memory Window 32bit-wise */ - /* memcpy_toio() doesn't guarantee 32bit writes :-| */ - while (_fw_len > 0) { - /* use non-swapping writel() */ - __raw_writel(*fw_ptr, dev_fw_ptr); - fw_ptr++, dev_fw_ptr++; - _fw_len -= 4; - } - - /* flush PCI posting */ - (void) readl(device_base + ISL38XX_PCI_POSTING_FLUSH); - wmb(); /* be paranoid again */ - - BUG_ON(_fw_len != 0); - } - - BUG_ON(fw_len != 0); - - /* Firmware version is at offset 40 (also for "newmac") */ - printk(KERN_DEBUG "%s: firmware version: %.8s\n", - priv->ndev->name, fw_entry->data + 40); - - release_firmware(fw_entry); - } - - /* now reset the device - * clear the Reset & ClkRun bit, set the RAMBoot bit */ - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~ISL38XX_CTRL_STAT_CLKRUN; - reg &= ~ISL38XX_CTRL_STAT_RESET; - reg |= ISL38XX_CTRL_STAT_RAMBOOT; - isl38xx_w32_flush(device_base, reg, ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* set the reset bit latches the host override and RAMBoot bits - * into the device for operation when the reset bit is reset */ - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - /* don't do flush PCI posting here! */ - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the reset bit should start the whole circus */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - /* don't do flush PCI posting here! */ - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - return 0; -} - -/****************************************************************************** - Device Interrupt Handler -******************************************************************************/ - -irqreturn_t -islpci_interrupt(int irq, void *config) -{ - u32 reg; - islpci_private *priv = config; - struct net_device *ndev = priv->ndev; - void __iomem *device = priv->device_base; - int powerstate = ISL38XX_PSM_POWERSAVE_STATE; - - /* lock the interrupt handler */ - spin_lock(&priv->slock); - - /* received an interrupt request on a shared IRQ line - * first check whether the device is in sleep mode */ - reg = readl(device + ISL38XX_CTRL_STAT_REG); - if (reg & ISL38XX_CTRL_STAT_SLEEPMODE) - /* device is in sleep mode, IRQ was generated by someone else */ - { -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); -#endif - spin_unlock(&priv->slock); - return IRQ_NONE; - } - - - /* check whether there is any source of interrupt on the device */ - reg = readl(device + ISL38XX_INT_IDENT_REG); - - /* also check the contents of the Interrupt Enable Register, because this - * will filter out interrupt sources from other devices on the same irq ! */ - reg &= readl(device + ISL38XX_INT_EN_REG); - reg &= ISL38XX_INT_SOURCES; - - if (reg != 0) { - if (islpci_get_state(priv) != PRV_STATE_SLEEP) - powerstate = ISL38XX_PSM_ACTIVE_STATE; - - /* reset the request bits in the Identification register */ - isl38xx_w32_flush(device, reg, ISL38XX_INT_ACK_REG); - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, - "IRQ: Identification register 0x%p 0x%x \n", device, reg); -#endif - - /* check for each bit in the register separately */ - if (reg & ISL38XX_INT_IDENT_UPDATE) { -#if VERBOSE > SHOW_ERROR_MESSAGES - /* Queue has been updated */ - DEBUG(SHOW_TRACING, "IRQ: Update flag \n"); - - DEBUG(SHOW_QUEUE_INDEXES, - "CB drv Qs: [%i][%i][%i][%i][%i][%i]\n", - le32_to_cpu(priv->control_block-> - driver_curr_frag[0]), - le32_to_cpu(priv->control_block-> - driver_curr_frag[1]), - le32_to_cpu(priv->control_block-> - driver_curr_frag[2]), - le32_to_cpu(priv->control_block-> - driver_curr_frag[3]), - le32_to_cpu(priv->control_block-> - driver_curr_frag[4]), - le32_to_cpu(priv->control_block-> - driver_curr_frag[5]) - ); - - DEBUG(SHOW_QUEUE_INDEXES, - "CB dev Qs: [%i][%i][%i][%i][%i][%i]\n", - le32_to_cpu(priv->control_block-> - device_curr_frag[0]), - le32_to_cpu(priv->control_block-> - device_curr_frag[1]), - le32_to_cpu(priv->control_block-> - device_curr_frag[2]), - le32_to_cpu(priv->control_block-> - device_curr_frag[3]), - le32_to_cpu(priv->control_block-> - device_curr_frag[4]), - le32_to_cpu(priv->control_block-> - device_curr_frag[5]) - ); -#endif - - /* cleanup the data low transmit queue */ - islpci_eth_cleanup_transmit(priv, priv->control_block); - - /* device is in active state, update the - * powerstate flag if necessary */ - powerstate = ISL38XX_PSM_ACTIVE_STATE; - - /* check all three queues in priority order - * call the PIMFOR receive function until the - * queue is empty */ - if (isl38xx_in_queue(priv->control_block, - ISL38XX_CB_RX_MGMTQ) != 0) { -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "Received frame in Management Queue\n"); -#endif - islpci_mgt_receive(ndev); - - islpci_mgt_cleanup_transmit(ndev); - - /* Refill slots in receive queue */ - islpci_mgmt_rx_fill(ndev); - - /* no need to trigger the device, next - islpci_mgt_transaction does it */ - } - - while (isl38xx_in_queue(priv->control_block, - ISL38XX_CB_RX_DATA_LQ) != 0) { -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "Received frame in Data Low Queue \n"); -#endif - islpci_eth_receive(priv); - } - - /* check whether the data transmit queues were full */ - if (priv->data_low_tx_full) { - /* check whether the transmit is not full anymore */ - if (ISL38XX_CB_TX_QSIZE - - isl38xx_in_queue(priv->control_block, - ISL38XX_CB_TX_DATA_LQ) >= - ISL38XX_MIN_QTHRESHOLD) { - /* nope, the driver is ready for more network frames */ - netif_wake_queue(priv->ndev); - - /* reset the full flag */ - priv->data_low_tx_full = 0; - } - } - } - - if (reg & ISL38XX_INT_IDENT_INIT) { - /* Device has been initialized */ -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "IRQ: Init flag, device initialized \n"); -#endif - wake_up(&priv->reset_done); - } - - if (reg & ISL38XX_INT_IDENT_SLEEP) { - /* Device intends to move to powersave state */ -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "IRQ: Sleep flag \n"); -#endif - isl38xx_handle_sleep_request(priv->control_block, - &powerstate, - priv->device_base); - } - - if (reg & ISL38XX_INT_IDENT_WAKEUP) { - /* Device has been woken up to active state */ -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "IRQ: Wakeup flag \n"); -#endif - - isl38xx_handle_wakeup(priv->control_block, - &powerstate, priv->device_base); - } - } else { -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "Assuming someone else called the IRQ\n"); -#endif - spin_unlock(&priv->slock); - return IRQ_NONE; - } - - /* sleep -> ready */ - if (islpci_get_state(priv) == PRV_STATE_SLEEP - && powerstate == ISL38XX_PSM_ACTIVE_STATE) - islpci_set_state(priv, PRV_STATE_READY); - - /* !sleep -> sleep */ - if (islpci_get_state(priv) != PRV_STATE_SLEEP - && powerstate == ISL38XX_PSM_POWERSAVE_STATE) - islpci_set_state(priv, PRV_STATE_SLEEP); - - /* unlock the interrupt handler */ - spin_unlock(&priv->slock); - - return IRQ_HANDLED; -} - -/****************************************************************************** - Network Interface Control & Statistical functions -******************************************************************************/ -static int -islpci_open(struct net_device *ndev) -{ - u32 rc; - islpci_private *priv = netdev_priv(ndev); - - /* reset data structures, upload firmware and reset device */ - rc = islpci_reset(priv,1); - if (rc) { - prism54_bring_down(priv); - return rc; /* Returns informative message */ - } - - netif_start_queue(ndev); - - /* Turn off carrier if in STA or Ad-hoc mode. It will be turned on - * once the firmware receives a trap of being associated - * (GEN_OID_LINKSTATE). In other modes (AP or WDS or monitor) we - * should just leave the carrier on as its expected the firmware - * won't send us a trigger. */ - if (priv->iw_mode == IW_MODE_INFRA || priv->iw_mode == IW_MODE_ADHOC) - netif_carrier_off(ndev); - else - netif_carrier_on(ndev); - - return 0; -} - -static int -islpci_close(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - - printk(KERN_DEBUG "%s: islpci_close ()\n", ndev->name); - - netif_stop_queue(ndev); - - return prism54_bring_down(priv); -} - -static int -prism54_bring_down(islpci_private *priv) -{ - void __iomem *device_base = priv->device_base; - u32 reg; - /* we are going to shutdown the device */ - islpci_set_state(priv, PRV_STATE_PREBOOT); - - /* disable all device interrupts in case they weren't */ - isl38xx_disable_interrupts(priv->device_base); - - /* For safety reasons, we may want to ensure that no DMA transfer is - * currently in progress by emptying the TX and RX queues. */ - - /* wait until interrupts have finished executing on other CPUs */ - synchronize_irq(priv->pdev->irq); - - reg = readl(device_base + ISL38XX_CTRL_STAT_REG); - reg &= ~(ISL38XX_CTRL_STAT_RESET | ISL38XX_CTRL_STAT_RAMBOOT); - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - reg |= ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - udelay(ISL38XX_WRITEIO_DELAY); - - /* clear the Reset bit */ - reg &= ~ISL38XX_CTRL_STAT_RESET; - writel(reg, device_base + ISL38XX_CTRL_STAT_REG); - wmb(); - - /* wait a while for the device to reset */ - schedule_timeout_uninterruptible(msecs_to_jiffies(50)); - - return 0; -} - -static int -islpci_upload_fw(islpci_private *priv) -{ - islpci_state_t old_state; - u32 rc; - - old_state = islpci_set_state(priv, PRV_STATE_BOOT); - - printk(KERN_DEBUG "%s: uploading firmware...\n", priv->ndev->name); - - rc = isl_upload_firmware(priv); - if (rc) { - /* error uploading the firmware */ - printk(KERN_ERR "%s: could not upload firmware ('%s')\n", - priv->ndev->name, priv->firmware); - - islpci_set_state(priv, old_state); - return rc; - } - - printk(KERN_DEBUG "%s: firmware upload complete\n", - priv->ndev->name); - - islpci_set_state(priv, PRV_STATE_POSTBOOT); - - return 0; -} - -static int -islpci_reset_if(islpci_private *priv) -{ - long remaining; - int result = -ETIME; - int count; - - DEFINE_WAIT(wait); - prepare_to_wait(&priv->reset_done, &wait, TASK_UNINTERRUPTIBLE); - - /* now the last step is to reset the interface */ - isl38xx_interface_reset(priv->device_base, priv->device_host_address); - islpci_set_state(priv, PRV_STATE_PREINIT); - - for(count = 0; count < 2 && result; count++) { - /* The software reset acknowledge needs about 220 msec here. - * Be conservative and wait for up to one second. */ - - remaining = schedule_timeout_uninterruptible(HZ); - - if(remaining > 0) { - result = 0; - break; - } - - /* If we're here it's because our IRQ hasn't yet gone through. - * Retry a bit more... - */ - printk(KERN_ERR "%s: no 'reset complete' IRQ seen - retrying\n", - priv->ndev->name); - } - - finish_wait(&priv->reset_done, &wait); - - if (result) { - printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name); - return result; - } - - islpci_set_state(priv, PRV_STATE_INIT); - - /* Now that the device is 100% up, let's allow - * for the other interrupts -- - * NOTE: this is not *yet* true since we've only allowed the - * INIT interrupt on the IRQ line. We can perhaps poll - * the IRQ line until we know for sure the reset went through */ - isl38xx_enable_common_interrupts(priv->device_base); - - down_write(&priv->mib_sem); - result = mgt_commit(priv); - if (result) { - printk(KERN_ERR "%s: interface reset failure\n", priv->ndev->name); - up_write(&priv->mib_sem); - return result; - } - up_write(&priv->mib_sem); - - islpci_set_state(priv, PRV_STATE_READY); - - printk(KERN_DEBUG "%s: interface reset complete\n", priv->ndev->name); - return 0; -} - -int -islpci_reset(islpci_private *priv, int reload_firmware) -{ - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; - unsigned counter; - int rc; - - if (reload_firmware) - islpci_set_state(priv, PRV_STATE_PREBOOT); - else - islpci_set_state(priv, PRV_STATE_POSTBOOT); - - printk(KERN_DEBUG "%s: resetting device...\n", priv->ndev->name); - - /* disable all device interrupts in case they weren't */ - isl38xx_disable_interrupts(priv->device_base); - - /* flush all management queues */ - priv->index_mgmt_tx = 0; - priv->index_mgmt_rx = 0; - - /* clear the indexes in the frame pointer */ - for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) { - cb->driver_curr_frag[counter] = cpu_to_le32(0); - cb->device_curr_frag[counter] = cpu_to_le32(0); - } - - /* reset the mgmt receive queue */ - for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { - isl38xx_fragment *frag = &cb->rx_data_mgmt[counter]; - frag->size = cpu_to_le16(MGMT_FRAME_SIZE); - frag->flags = 0; - frag->address = cpu_to_le32(priv->mgmt_rx[counter].pci_addr); - } - - for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { - cb->rx_data_low[counter].address = - cpu_to_le32((u32) priv->pci_map_rx_address[counter]); - } - - /* since the receive queues are filled with empty fragments, now we can - * set the corresponding indexes in the Control Block */ - priv->control_block->driver_curr_frag[ISL38XX_CB_RX_DATA_LQ] = - cpu_to_le32(ISL38XX_CB_RX_QSIZE); - priv->control_block->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = - cpu_to_le32(ISL38XX_CB_MGMT_QSIZE); - - /* reset the remaining real index registers and full flags */ - priv->free_data_rx = 0; - priv->free_data_tx = 0; - priv->data_low_tx_full = 0; - - if (reload_firmware) { /* Should we load the firmware ? */ - /* now that the data structures are cleaned up, upload - * firmware and reset interface */ - rc = islpci_upload_fw(priv); - if (rc) { - printk(KERN_ERR "%s: islpci_reset: failure\n", - priv->ndev->name); - return rc; - } - } - - /* finally reset interface */ - rc = islpci_reset_if(priv); - if (rc) - printk(KERN_ERR "prism54: Your card/socket may be faulty, or IRQ line too busy :(\n"); - return rc; -} - -/****************************************************************************** - Network device configuration functions -******************************************************************************/ -static int -islpci_alloc_memory(islpci_private *priv) -{ - int counter; - -#if VERBOSE > SHOW_ERROR_MESSAGES - printk(KERN_DEBUG "islpci_alloc_memory\n"); -#endif - - /* remap the PCI device base address to accessable */ - if (!(priv->device_base = - ioremap(pci_resource_start(priv->pdev, 0), - ISL38XX_PCI_MEM_SIZE))) { - /* error in remapping the PCI device memory address range */ - printk(KERN_ERR "PCI memory remapping failed \n"); - return -1; - } - - /* memory layout for consistent DMA region: - * - * Area 1: Control Block for the device interface - * Area 2: Power Save Mode Buffer for temporary frame storage. Be aware that - * the number of supported stations in the AP determines the minimal - * size of the buffer ! - */ - - /* perform the allocation */ - priv->driver_mem_address = pci_alloc_consistent(priv->pdev, - HOST_MEM_BLOCK, - &priv-> - device_host_address); - - if (!priv->driver_mem_address) { - /* error allocating the block of PCI memory */ - printk(KERN_ERR "%s: could not allocate DMA memory, aborting!", - "prism54"); - return -1; - } - - /* assign the Control Block to the first address of the allocated area */ - priv->control_block = - (isl38xx_control_block *) priv->driver_mem_address; - - /* set the Power Save Buffer pointer directly behind the CB */ - priv->device_psm_buffer = - priv->device_host_address + CONTROL_BLOCK_SIZE; - - /* make sure all buffer pointers are initialized */ - for (counter = 0; counter < ISL38XX_CB_QCOUNT; counter++) { - priv->control_block->driver_curr_frag[counter] = cpu_to_le32(0); - priv->control_block->device_curr_frag[counter] = cpu_to_le32(0); - } - - priv->index_mgmt_rx = 0; - memset(priv->mgmt_rx, 0, sizeof(priv->mgmt_rx)); - memset(priv->mgmt_tx, 0, sizeof(priv->mgmt_tx)); - - /* allocate rx queue for management frames */ - if (islpci_mgmt_rx_fill(priv->ndev) < 0) - goto out_free; - - /* now get the data rx skb's */ - memset(priv->data_low_rx, 0, sizeof (priv->data_low_rx)); - memset(priv->pci_map_rx_address, 0, sizeof (priv->pci_map_rx_address)); - - for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { - struct sk_buff *skb; - - /* allocate an sk_buff for received data frames storage - * each frame on receive size consists of 1 fragment - * include any required allignment operations */ - if (!(skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2))) { - /* error allocating an sk_buff structure elements */ - printk(KERN_ERR "Error allocating skb.\n"); - skb = NULL; - goto out_free; - } - skb_reserve(skb, (4 - (long) skb->data) & 0x03); - /* add the new allocated sk_buff to the buffer array */ - priv->data_low_rx[counter] = skb; - - /* map the allocated skb data area to pci */ - priv->pci_map_rx_address[counter] = - pci_map_single(priv->pdev, (void *) skb->data, - MAX_FRAGMENT_SIZE_RX + 2, - PCI_DMA_FROMDEVICE); - if (!priv->pci_map_rx_address[counter]) { - /* error mapping the buffer to device - accessable memory address */ - printk(KERN_ERR "failed to map skb DMA'able\n"); - goto out_free; - } - } - - prism54_acl_init(&priv->acl); - prism54_wpa_bss_ie_init(priv); - if (mgt_init(priv)) - goto out_free; - - return 0; - out_free: - islpci_free_memory(priv); - return -1; -} - -int -islpci_free_memory(islpci_private *priv) -{ - int counter; - - if (priv->device_base) - iounmap(priv->device_base); - priv->device_base = NULL; - - /* free consistent DMA area... */ - if (priv->driver_mem_address) - pci_free_consistent(priv->pdev, HOST_MEM_BLOCK, - priv->driver_mem_address, - priv->device_host_address); - - /* clear some dangling pointers */ - priv->driver_mem_address = NULL; - priv->device_host_address = 0; - priv->device_psm_buffer = 0; - priv->control_block = NULL; - - /* clean up mgmt rx buffers */ - for (counter = 0; counter < ISL38XX_CB_MGMT_QSIZE; counter++) { - struct islpci_membuf *buf = &priv->mgmt_rx[counter]; - if (buf->pci_addr) - pci_unmap_single(priv->pdev, buf->pci_addr, - buf->size, PCI_DMA_FROMDEVICE); - buf->pci_addr = 0; - kfree(buf->mem); - buf->size = 0; - buf->mem = NULL; - } - - /* clean up data rx buffers */ - for (counter = 0; counter < ISL38XX_CB_RX_QSIZE; counter++) { - if (priv->pci_map_rx_address[counter]) - pci_unmap_single(priv->pdev, - priv->pci_map_rx_address[counter], - MAX_FRAGMENT_SIZE_RX + 2, - PCI_DMA_FROMDEVICE); - priv->pci_map_rx_address[counter] = 0; - - if (priv->data_low_rx[counter]) - dev_kfree_skb(priv->data_low_rx[counter]); - priv->data_low_rx[counter] = NULL; - } - - /* Free the acces control list and the WPA list */ - prism54_acl_clean(&priv->acl); - prism54_wpa_bss_ie_clean(priv); - mgt_clean(priv); - - return 0; -} - -#if 0 -static void -islpci_set_multicast_list(struct net_device *dev) -{ - /* put device into promisc mode and let network layer handle it */ -} -#endif - -static void islpci_ethtool_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, DRV_NAME); - strcpy(info->version, DRV_VERSION); -} - -static const struct ethtool_ops islpci_ethtool_ops = { - .get_drvinfo = islpci_ethtool_get_drvinfo, -}; - -static const struct net_device_ops islpci_netdev_ops = { - .ndo_open = islpci_open, - .ndo_stop = islpci_close, - .ndo_do_ioctl = prism54_ioctl, - .ndo_start_xmit = islpci_eth_transmit, - .ndo_tx_timeout = islpci_eth_tx_timeout, - .ndo_set_mac_address = prism54_set_mac_address, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -struct net_device * -islpci_setup(struct pci_dev *pdev) -{ - islpci_private *priv; - struct net_device *ndev = alloc_etherdev(sizeof (islpci_private)); - - if (!ndev) - return ndev; - - pci_set_drvdata(pdev, ndev); -#if defined(SET_NETDEV_DEV) - SET_NETDEV_DEV(ndev, &pdev->dev); -#endif - - /* setup the structure members */ - ndev->base_addr = pci_resource_start(pdev, 0); - ndev->irq = pdev->irq; - - /* initialize the function pointers */ - ndev->netdev_ops = &islpci_netdev_ops; - ndev->wireless_handlers = &prism54_handler_def; - ndev->ethtool_ops = &islpci_ethtool_ops; - - /* ndev->set_multicast_list = &islpci_set_multicast_list; */ - ndev->addr_len = ETH_ALEN; - /* Get a non-zero dummy MAC address for nameif. Jean II */ - memcpy(ndev->dev_addr, dummy_mac, 6); - - ndev->watchdog_timeo = ISLPCI_TX_TIMEOUT; - - /* allocate a private device structure to the network device */ - priv = netdev_priv(ndev); - priv->ndev = ndev; - priv->pdev = pdev; - priv->monitor_type = ARPHRD_IEEE80211; - priv->ndev->type = (priv->iw_mode == IW_MODE_MONITOR) ? - priv->monitor_type : ARPHRD_ETHER; - - /* Add pointers to enable iwspy support. */ - priv->wireless_data.spy_data = &priv->spy_data; - ndev->wireless_data = &priv->wireless_data; - - /* save the start and end address of the PCI memory area */ - ndev->mem_start = (unsigned long) priv->device_base; - ndev->mem_end = ndev->mem_start + ISL38XX_PCI_MEM_SIZE; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "PCI Memory remapped to 0x%p\n", priv->device_base); -#endif - - init_waitqueue_head(&priv->reset_done); - - /* init the queue read locks, process wait counter */ - mutex_init(&priv->mgmt_lock); - priv->mgmt_received = NULL; - init_waitqueue_head(&priv->mgmt_wqueue); - mutex_init(&priv->stats_lock); - spin_lock_init(&priv->slock); - - /* init state machine with off#1 state */ - priv->state = PRV_STATE_OFF; - priv->state_off = 1; - - /* initialize workqueue's */ - INIT_WORK(&priv->stats_work, prism54_update_stats); - priv->stats_timestamp = 0; - - INIT_WORK(&priv->reset_task, islpci_do_reset_and_wake); - priv->reset_task_pending = 0; - - /* allocate various memory areas */ - if (islpci_alloc_memory(priv)) - goto do_free_netdev; - - /* select the firmware file depending on the device id */ - switch (pdev->device) { - case 0x3877: - strcpy(priv->firmware, ISL3877_IMAGE_FILE); - break; - - case 0x3886: - strcpy(priv->firmware, ISL3886_IMAGE_FILE); - break; - - default: - strcpy(priv->firmware, ISL3890_IMAGE_FILE); - break; - } - - if (register_netdev(ndev)) { - DEBUG(SHOW_ERROR_MESSAGES, - "ERROR: register_netdev() failed \n"); - goto do_islpci_free_memory; - } - - return ndev; - - do_islpci_free_memory: - islpci_free_memory(priv); - do_free_netdev: - pci_set_drvdata(pdev, NULL); - free_netdev(ndev); - priv = NULL; - return NULL; -} - -islpci_state_t -islpci_set_state(islpci_private *priv, islpci_state_t new_state) -{ - islpci_state_t old_state; - - /* lock */ - old_state = priv->state; - - /* this means either a race condition or some serious error in - * the driver code */ - switch (new_state) { - case PRV_STATE_OFF: - priv->state_off++; - default: - priv->state = new_state; - break; - - case PRV_STATE_PREBOOT: - /* there are actually many off-states, enumerated by - * state_off */ - if (old_state == PRV_STATE_OFF) - priv->state_off--; - - /* only if hw_unavailable is zero now it means we either - * were in off#1 state, or came here from - * somewhere else */ - if (!priv->state_off) - priv->state = new_state; - break; - }; -#if 0 - printk(KERN_DEBUG "%s: state transition %d -> %d (off#%d)\n", - priv->ndev->name, old_state, new_state, priv->state_off); -#endif - - /* invariants */ - BUG_ON(priv->state_off < 0); - BUG_ON(priv->state_off && (priv->state != PRV_STATE_OFF)); - BUG_ON(!priv->state_off && (priv->state == PRV_STATE_OFF)); - - /* unlock */ - return old_state; -} diff --git a/drivers/net/wireless/prism54/islpci_dev.h b/drivers/net/wireless/prism54/islpci_dev.h deleted file mode 100644 index c4d0f19b7cbc..000000000000 --- a/drivers/net/wireless/prism54/islpci_dev.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright (C) 2003 Herbert Valerio Riedel - * Copyright (C) 2003 Luis R. Rodriguez - * Copyright (C) 2003 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#ifndef _ISLPCI_DEV_H -#define _ISLPCI_DEV_H - -#include -#include -#include -#include -#include - -#include "isl_38xx.h" -#include "isl_oid.h" -#include "islpci_mgt.h" - -/* some states might not be superflous and may be removed when - design is finalized (hvr) */ -typedef enum { - PRV_STATE_OFF = 0, /* this means hw_unavailable is != 0 */ - PRV_STATE_PREBOOT, /* we are in a pre-boot state (empty RAM) */ - PRV_STATE_BOOT, /* boot state (fw upload, run fw) */ - PRV_STATE_POSTBOOT, /* after boot state, need reset now */ - PRV_STATE_PREINIT, /* pre-init state */ - PRV_STATE_INIT, /* init state (restore MIB backup to device) */ - PRV_STATE_READY, /* driver&device are in operational state */ - PRV_STATE_SLEEP /* device in sleep mode */ -} islpci_state_t; - -/* ACL using MAC address */ -struct mac_entry { - struct list_head _list; - char addr[ETH_ALEN]; -}; - -struct islpci_acl { - enum { MAC_POLICY_OPEN=0, MAC_POLICY_ACCEPT=1, MAC_POLICY_REJECT=2 } policy; - struct list_head mac_list; /* a list of mac_entry */ - int size; /* size of queue */ - struct mutex lock; /* accessed in ioctls and trap_work */ -}; - -struct islpci_membuf { - int size; /* size of memory */ - void *mem; /* address of memory as seen by CPU */ - dma_addr_t pci_addr; /* address of memory as seen by device */ -}; - -#define MAX_BSS_WPA_IE_COUNT 64 -#define MAX_WPA_IE_LEN 64 -struct islpci_bss_wpa_ie { - struct list_head list; - unsigned long last_update; - u8 bssid[ETH_ALEN]; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - -}; - -typedef struct { - spinlock_t slock; /* generic spinlock; */ - - u32 priv_oid; - - /* our mib cache */ - u32 iw_mode; - struct rw_semaphore mib_sem; - void **mib; - char nickname[IW_ESSID_MAX_SIZE+1]; - - /* Take care of the wireless stats */ - struct work_struct stats_work; - struct mutex stats_lock; - /* remember when we last updated the stats */ - unsigned long stats_timestamp; - /* The first is accessed under semaphore locking. - * The second is the clean one we return to iwconfig. - */ - struct iw_statistics local_iwstatistics; - struct iw_statistics iwstatistics; - - struct iw_spy_data spy_data; /* iwspy support */ - - struct iw_public_data wireless_data; - - int monitor_type; /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_PRISM */ - - struct islpci_acl acl; - - /* PCI bus allocation & configuration members */ - struct pci_dev *pdev; /* PCI structure information */ - char firmware[33]; - - void __iomem *device_base; /* ioremapped device base address */ - - /* consistent DMA region */ - void *driver_mem_address; /* base DMA address */ - dma_addr_t device_host_address; /* base DMA address (bus address) */ - dma_addr_t device_psm_buffer; /* host memory for PSM buffering (bus address) */ - - /* our network_device structure */ - struct net_device *ndev; - - /* device queue interface members */ - struct isl38xx_cb *control_block; /* device control block - (== driver_mem_address!) */ - - /* Each queue has three indexes: - * free/index_mgmt/data_rx/tx (called index, see below), - * driver_curr_frag, and device_curr_frag (in the control block) - * All indexes are ever-increasing, but interpreted modulo the - * device queue size when used. - * index <= device_curr_frag <= driver_curr_frag at all times - * For rx queues, [index, device_curr_frag) contains fragments - * that the interrupt processing needs to handle (owned by driver). - * [device_curr_frag, driver_curr_frag) is the free space in the - * rx queue, waiting for data (owned by device). The driver - * increments driver_curr_frag to indicate to the device that more - * buffers are available. - * If device_curr_frag == driver_curr_frag, no more rx buffers are - * available, and the rx DMA engine of the device is halted. - * For tx queues, [index, device_curr_frag) contains fragments - * where tx is done; they need to be freed (owned by driver). - * [device_curr_frag, driver_curr_frag) contains the frames - * that are being transferred (owned by device). The driver - * increments driver_curr_frag to indicate that more tx work - * needs to be done. - */ - u32 index_mgmt_rx; /* real index mgmt rx queue */ - u32 index_mgmt_tx; /* read index mgmt tx queue */ - u32 free_data_rx; /* free pointer data rx queue */ - u32 free_data_tx; /* free pointer data tx queue */ - u32 data_low_tx_full; /* full detected flag */ - - /* frame memory buffers for the device queues */ - struct islpci_membuf mgmt_tx[ISL38XX_CB_MGMT_QSIZE]; - struct islpci_membuf mgmt_rx[ISL38XX_CB_MGMT_QSIZE]; - struct sk_buff *data_low_tx[ISL38XX_CB_TX_QSIZE]; - struct sk_buff *data_low_rx[ISL38XX_CB_RX_QSIZE]; - dma_addr_t pci_map_tx_address[ISL38XX_CB_TX_QSIZE]; - dma_addr_t pci_map_rx_address[ISL38XX_CB_RX_QSIZE]; - - /* wait for a reset interrupt */ - wait_queue_head_t reset_done; - - /* used by islpci_mgt_transaction */ - struct mutex mgmt_lock; /* serialize access to mailbox and wqueue */ - struct islpci_mgmtframe *mgmt_received; /* mbox for incoming frame */ - wait_queue_head_t mgmt_wqueue; /* waitqueue for mbox */ - - /* state machine */ - islpci_state_t state; - int state_off; /* enumeration of off-state, if 0 then - * we're not in any off-state */ - - /* WPA stuff */ - int wpa; /* WPA mode enabled */ - struct list_head bss_wpa_list; - int num_bss_wpa; - struct mutex wpa_lock; - u8 wpa_ie[MAX_WPA_IE_LEN]; - size_t wpa_ie_len; - - struct work_struct reset_task; - int reset_task_pending; -} islpci_private; - -static inline islpci_state_t -islpci_get_state(islpci_private *priv) -{ - /* lock */ - return priv->state; - /* unlock */ -} - -islpci_state_t islpci_set_state(islpci_private *priv, islpci_state_t new_state); - -#define ISLPCI_TX_TIMEOUT (2*HZ) - -irqreturn_t islpci_interrupt(int, void *); - -int prism54_post_setup(islpci_private *, int); -int islpci_reset(islpci_private *, int); - -static inline void -islpci_trigger(islpci_private *priv) -{ - isl38xx_trigger_device(islpci_get_state(priv) == PRV_STATE_SLEEP, - priv->device_base); -} - -int islpci_free_memory(islpci_private *); -struct net_device *islpci_setup(struct pci_dev *); - -#define DRV_NAME "prism54" -#define DRV_VERSION "1.2" - -#endif /* _ISLPCI_DEV_H */ diff --git a/drivers/net/wireless/prism54/islpci_eth.c b/drivers/net/wireless/prism54/islpci_eth.c deleted file mode 100644 index 872b64783e78..000000000000 --- a/drivers/net/wireless/prism54/islpci_eth.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright (C) 2004 Aurelien Alleaume - * 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 - * - * 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 - * - */ - -#include - -#include -#include -#include -#include -#include -#include - -#include "prismcompat.h" -#include "isl_38xx.h" -#include "islpci_eth.h" -#include "islpci_mgt.h" -#include "oid_mgt.h" - -/****************************************************************************** - Network Interface functions -******************************************************************************/ -void -islpci_eth_cleanup_transmit(islpci_private *priv, - isl38xx_control_block *control_block) -{ - struct sk_buff *skb; - u32 index; - - /* compare the control block read pointer with the free pointer */ - while (priv->free_data_tx != - le32_to_cpu(control_block-> - device_curr_frag[ISL38XX_CB_TX_DATA_LQ])) { - /* read the index of the first fragment to be freed */ - index = priv->free_data_tx % ISL38XX_CB_TX_QSIZE; - - /* check for holes in the arrays caused by multi fragment frames - * searching for the last fragment of a frame */ - if (priv->pci_map_tx_address[index]) { - /* entry is the last fragment of a frame - * free the skb structure and unmap pci memory */ - skb = priv->data_low_tx[index]; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "cleanup skb %p skb->data %p skb->len %u truesize %u\n ", - skb, skb->data, skb->len, skb->truesize); -#endif - - pci_unmap_single(priv->pdev, - priv->pci_map_tx_address[index], - skb->len, PCI_DMA_TODEVICE); - dev_kfree_skb_irq(skb); - skb = NULL; - } - /* increment the free data low queue pointer */ - priv->free_data_tx++; - } -} - -netdev_tx_t -islpci_eth_transmit(struct sk_buff *skb, struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = priv->control_block; - u32 index; - dma_addr_t pci_map_address; - int frame_size; - isl38xx_fragment *fragment; - int offset; - struct sk_buff *newskb; - int newskb_offset; - unsigned long flags; - unsigned char wds_mac[6]; - u32 curr_frag; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_transmit \n"); -#endif - - /* lock the driver code */ - spin_lock_irqsave(&priv->slock, flags); - - /* check whether the destination queue has enough fragments for the frame */ - curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ]); - if (unlikely(curr_frag - priv->free_data_tx >= ISL38XX_CB_TX_QSIZE)) { - printk(KERN_ERR "%s: transmit device queue full when awake\n", - ndev->name); - netif_stop_queue(ndev); - - /* trigger the device */ - isl38xx_w32_flush(priv->device_base, ISL38XX_DEV_INT_UPDATE, - ISL38XX_DEV_INT_REG); - udelay(ISL38XX_WRITEIO_DELAY); - goto drop_free; - } - /* Check alignment and WDS frame formatting. The start of the packet should - * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes - * and add WDS address information */ - if (likely(((long) skb->data & 0x03) | init_wds)) { - /* get the number of bytes to add and re-allign */ - offset = (4 - (long) skb->data) & 0x03; - offset += init_wds ? 6 : 0; - - /* check whether the current skb can be used */ - if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { - unsigned char *src = skb->data; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "skb offset %i wds %i\n", offset, - init_wds); -#endif - - /* align the buffer on 4-byte boundary */ - skb_reserve(skb, (4 - (long) skb->data) & 0x03); - if (init_wds) { - /* wds requires an additional address field of 6 bytes */ - skb_put(skb, 6); -#ifdef ISLPCI_ETH_DEBUG - printk("islpci_eth_transmit:wds_mac\n"); -#endif - memmove(skb->data + 6, src, skb->len); - skb_copy_to_linear_data(skb, wds_mac, 6); - } else { - memmove(skb->data, src, skb->len); - } - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "memmove %p %p %i \n", skb->data, - src, skb->len); -#endif - } else { - newskb = - dev_alloc_skb(init_wds ? skb->len + 6 : skb->len); - if (unlikely(newskb == NULL)) { - printk(KERN_ERR "%s: Cannot allocate skb\n", - ndev->name); - goto drop_free; - } - newskb_offset = (4 - (long) newskb->data) & 0x03; - - /* Check if newskb->data is aligned */ - if (newskb_offset) - skb_reserve(newskb, newskb_offset); - - skb_put(newskb, init_wds ? skb->len + 6 : skb->len); - if (init_wds) { - skb_copy_from_linear_data(skb, - newskb->data + 6, - skb->len); - skb_copy_to_linear_data(newskb, wds_mac, 6); -#ifdef ISLPCI_ETH_DEBUG - printk("islpci_eth_transmit:wds_mac\n"); -#endif - } else - skb_copy_from_linear_data(skb, newskb->data, - skb->len); - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "memcpy %p %p %i wds %i\n", - newskb->data, skb->data, skb->len, init_wds); -#endif - - newskb->dev = skb->dev; - dev_kfree_skb_irq(skb); - skb = newskb; - } - } - /* display the buffer contents for debugging */ -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_BUFFER_CONTENTS, "\ntx %p ", skb->data); - display_buffer((char *) skb->data, skb->len); -#endif - - /* map the skb buffer to pci memory for DMA operation */ - pci_map_address = pci_map_single(priv->pdev, - (void *) skb->data, skb->len, - PCI_DMA_TODEVICE); - if (unlikely(pci_map_address == 0)) { - printk(KERN_WARNING "%s: cannot map buffer to PCI\n", - ndev->name); - goto drop_free; - } - /* Place the fragment in the control block structure. */ - index = curr_frag % ISL38XX_CB_TX_QSIZE; - fragment = &cb->tx_data_low[index]; - - priv->pci_map_tx_address[index] = pci_map_address; - /* store the skb address for future freeing */ - priv->data_low_tx[index] = skb; - /* set the proper fragment start address and size information */ - frame_size = skb->len; - fragment->size = cpu_to_le16(frame_size); - fragment->flags = cpu_to_le16(0); /* set to 1 if more fragments */ - fragment->address = cpu_to_le32(pci_map_address); - curr_frag++; - - /* The fragment address in the control block must have been - * written before announcing the frame buffer to device. */ - wmb(); - cb->driver_curr_frag[ISL38XX_CB_TX_DATA_LQ] = cpu_to_le32(curr_frag); - - if (curr_frag - priv->free_data_tx + ISL38XX_MIN_QTHRESHOLD - > ISL38XX_CB_TX_QSIZE) { - /* stop sends from upper layers */ - netif_stop_queue(ndev); - - /* set the full flag for the transmission queue */ - priv->data_low_tx_full = 1; - } - - /* set the transmission time */ - ndev->trans_start = jiffies; - ndev->stats.tx_packets++; - ndev->stats.tx_bytes += skb->len; - - /* trigger the device */ - islpci_trigger(priv); - - /* unlock the driver code */ - spin_unlock_irqrestore(&priv->slock, flags); - - return NETDEV_TX_OK; - - drop_free: - ndev->stats.tx_dropped++; - spin_unlock_irqrestore(&priv->slock, flags); - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -static inline int -islpci_monitor_rx(islpci_private *priv, struct sk_buff **skb) -{ - /* The card reports full 802.11 packets but with a 20 bytes - * header and without the FCS. But there a is a bit that - * indicates if the packet is corrupted :-) */ - struct rfmon_header *hdr = (struct rfmon_header *) (*skb)->data; - - if (hdr->flags & 0x01) - /* This one is bad. Drop it ! */ - return -1; - if (priv->ndev->type == ARPHRD_IEEE80211_PRISM) { - struct avs_80211_1_header *avs; - /* extract the relevant data from the header */ - u32 clock = le32_to_cpu(hdr->clock); - u8 rate = hdr->rate; - u16 freq = le16_to_cpu(hdr->freq); - u8 rssi = hdr->rssi; - - skb_pull(*skb, sizeof (struct rfmon_header)); - - if (skb_headroom(*skb) < sizeof (struct avs_80211_1_header)) { - struct sk_buff *newskb = skb_copy_expand(*skb, - sizeof (struct - avs_80211_1_header), - 0, GFP_ATOMIC); - if (newskb) { - dev_kfree_skb_irq(*skb); - *skb = newskb; - } else - return -1; - /* This behavior is not very subtile... */ - } - - /* make room for the new header and fill it. */ - avs = - (struct avs_80211_1_header *) skb_push(*skb, - sizeof (struct - avs_80211_1_header)); - - avs->version = cpu_to_be32(P80211CAPTURE_VERSION); - avs->length = cpu_to_be32(sizeof (struct avs_80211_1_header)); - avs->mactime = cpu_to_be64(clock); - avs->hosttime = cpu_to_be64(jiffies); - avs->phytype = cpu_to_be32(6); /*OFDM: 6 for (g), 8 for (a) */ - avs->channel = cpu_to_be32(channel_of_freq(freq)); - avs->datarate = cpu_to_be32(rate * 5); - avs->antenna = cpu_to_be32(0); /*unknown */ - avs->priority = cpu_to_be32(0); /*unknown */ - avs->ssi_type = cpu_to_be32(3); /*2: dBm, 3: raw RSSI */ - avs->ssi_signal = cpu_to_be32(rssi & 0x7f); - avs->ssi_noise = cpu_to_be32(priv->local_iwstatistics.qual.noise); /*better than 'undefined', I assume */ - avs->preamble = cpu_to_be32(0); /*unknown */ - avs->encoding = cpu_to_be32(0); /*unknown */ - } else - skb_pull(*skb, sizeof (struct rfmon_header)); - - (*skb)->protocol = htons(ETH_P_802_2); - skb_reset_mac_header(*skb); - (*skb)->pkt_type = PACKET_OTHERHOST; - - return 0; -} - -int -islpci_eth_receive(islpci_private *priv) -{ - struct net_device *ndev = priv->ndev; - isl38xx_control_block *control_block = priv->control_block; - struct sk_buff *skb; - u16 size; - u32 index, offset; - unsigned char *src; - int discard = 0; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_eth_receive \n"); -#endif - - /* the device has written an Ethernet frame in the data area - * of the sk_buff without updating the structure, do it now */ - index = priv->free_data_rx % ISL38XX_CB_RX_QSIZE; - size = le16_to_cpu(control_block->rx_data_low[index].size); - skb = priv->data_low_rx[index]; - offset = ((unsigned long) - le32_to_cpu(control_block->rx_data_low[index].address) - - (unsigned long) skb->data) & 3; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "frq->addr %x skb->data %p skb->len %u offset %u truesize %u\n ", - control_block->rx_data_low[priv->free_data_rx].address, skb->data, - skb->len, offset, skb->truesize); -#endif - - /* delete the streaming DMA mapping before processing the skb */ - pci_unmap_single(priv->pdev, - priv->pci_map_rx_address[index], - MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE); - - /* update the skb structure and allign the buffer */ - skb_put(skb, size); - if (offset) { - /* shift the buffer allocation offset bytes to get the right frame */ - skb_pull(skb, 2); - skb_put(skb, 2); - } -#if VERBOSE > SHOW_ERROR_MESSAGES - /* display the buffer contents for debugging */ - DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data); - display_buffer((char *) skb->data, skb->len); -#endif - - /* check whether WDS is enabled and whether the data frame is a WDS frame */ - - if (init_wds) { - /* WDS enabled, check for the wds address on the first 6 bytes of the buffer */ - src = skb->data + 6; - memmove(skb->data, src, skb->len - 6); - skb_trim(skb, skb->len - 6); - } -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "Fragment size %i in skb at %p\n", size, skb); - DEBUG(SHOW_TRACING, "Skb data at %p, length %i\n", skb->data, skb->len); - - /* display the buffer contents for debugging */ - DEBUG(SHOW_BUFFER_CONTENTS, "\nrx %p ", skb->data); - display_buffer((char *) skb->data, skb->len); -#endif - /* take care of monitor mode and spy monitoring. */ - if (unlikely(priv->iw_mode == IW_MODE_MONITOR)) { - skb->dev = ndev; - discard = islpci_monitor_rx(priv, &skb); - } else { - if (unlikely(skb->data[2 * ETH_ALEN] == 0)) { - /* The packet has a rx_annex. Read it for spy monitoring, Then - * remove it, while keeping the 2 leading MAC addr. - */ - struct iw_quality wstats; - struct rx_annex_header *annex = - (struct rx_annex_header *) skb->data; - wstats.level = annex->rfmon.rssi; - /* The noise value can be a bit outdated if nobody's - * reading wireless stats... */ - wstats.noise = priv->local_iwstatistics.qual.noise; - wstats.qual = wstats.level - wstats.noise; - wstats.updated = 0x07; - /* Update spy records */ - wireless_spy_update(ndev, annex->addr2, &wstats); - - skb_copy_from_linear_data(skb, - (skb->data + - sizeof(struct rfmon_header)), - 2 * ETH_ALEN); - skb_pull(skb, sizeof (struct rfmon_header)); - } - skb->protocol = eth_type_trans(skb, ndev); - } - skb->ip_summed = CHECKSUM_NONE; - ndev->stats.rx_packets++; - ndev->stats.rx_bytes += size; - - /* deliver the skb to the network layer */ -#ifdef ISLPCI_ETH_DEBUG - printk - ("islpci_eth_receive:netif_rx %2.2X %2.2X %2.2X %2.2X %2.2X %2.2X\n", - skb->data[0], skb->data[1], skb->data[2], skb->data[3], - skb->data[4], skb->data[5]); -#endif - if (unlikely(discard)) { - dev_kfree_skb_irq(skb); - skb = NULL; - } else - netif_rx(skb); - - /* increment the read index for the rx data low queue */ - priv->free_data_rx++; - - /* add one or more sk_buff structures */ - while (index = - le32_to_cpu(control_block-> - driver_curr_frag[ISL38XX_CB_RX_DATA_LQ]), - index - priv->free_data_rx < ISL38XX_CB_RX_QSIZE) { - /* allocate an sk_buff for received data frames storage - * include any required allignment operations */ - skb = dev_alloc_skb(MAX_FRAGMENT_SIZE_RX + 2); - if (unlikely(skb == NULL)) { - /* error allocating an sk_buff structure elements */ - DEBUG(SHOW_ERROR_MESSAGES, "Error allocating skb \n"); - break; - } - skb_reserve(skb, (4 - (long) skb->data) & 0x03); - /* store the new skb structure pointer */ - index = index % ISL38XX_CB_RX_QSIZE; - priv->data_low_rx[index] = skb; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, - "new alloc skb %p skb->data %p skb->len %u index %u truesize %u\n ", - skb, skb->data, skb->len, index, skb->truesize); -#endif - - /* set the streaming DMA mapping for proper PCI bus operation */ - priv->pci_map_rx_address[index] = - pci_map_single(priv->pdev, (void *) skb->data, - MAX_FRAGMENT_SIZE_RX + 2, - PCI_DMA_FROMDEVICE); - if (unlikely(!priv->pci_map_rx_address[index])) { - /* error mapping the buffer to device accessable memory address */ - DEBUG(SHOW_ERROR_MESSAGES, - "Error mapping DMA address\n"); - - /* free the skbuf structure before aborting */ - dev_kfree_skb_irq((struct sk_buff *) skb); - skb = NULL; - break; - } - /* update the fragment address */ - control_block->rx_data_low[index].address = - cpu_to_le32((u32)priv->pci_map_rx_address[index]); - wmb(); - - /* increment the driver read pointer */ - le32_add_cpu(&control_block-> - driver_curr_frag[ISL38XX_CB_RX_DATA_LQ], 1); - } - - /* trigger the device */ - islpci_trigger(priv); - - return 0; -} - -void -islpci_do_reset_and_wake(struct work_struct *work) -{ - islpci_private *priv = container_of(work, islpci_private, reset_task); - - islpci_reset(priv, 1); - priv->reset_task_pending = 0; - smp_wmb(); - netif_wake_queue(priv->ndev); -} - -void -islpci_eth_tx_timeout(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - - /* increment the transmit error counter */ - ndev->stats.tx_errors++; - - if (!priv->reset_task_pending) { - printk(KERN_WARNING - "%s: tx_timeout, scheduling reset", ndev->name); - netif_stop_queue(ndev); - priv->reset_task_pending = 1; - schedule_work(&priv->reset_task); - } else { - printk(KERN_WARNING - "%s: tx_timeout, waiting for reset", ndev->name); - } -} diff --git a/drivers/net/wireless/prism54/islpci_eth.h b/drivers/net/wireless/prism54/islpci_eth.h deleted file mode 100644 index 54f9a4b7bf9b..000000000000 --- a/drivers/net/wireless/prism54/islpci_eth.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * - * 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 - * - * 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 - * - */ - -#ifndef _ISLPCI_ETH_H -#define _ISLPCI_ETH_H - -#include "isl_38xx.h" -#include "islpci_dev.h" - -struct rfmon_header { - __le16 unk0; /* = 0x0000 */ - __le16 length; /* = 0x1400 */ - __le32 clock; /* 1MHz clock */ - u8 flags; - u8 unk1; - u8 rate; - u8 unk2; - __le16 freq; - __le16 unk3; - u8 rssi; - u8 padding[3]; -} __attribute__ ((packed)); - -struct rx_annex_header { - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - struct rfmon_header rfmon; -} __attribute__ ((packed)); - -/* wlan-ng (and hopefully others) AVS header, version one. Fields in - * network byte order. */ -#define P80211CAPTURE_VERSION 0x80211001 - -struct avs_80211_1_header { - __be32 version; - __be32 length; - __be64 mactime; - __be64 hosttime; - __be32 phytype; - __be32 channel; - __be32 datarate; - __be32 antenna; - __be32 priority; - __be32 ssi_type; - __be32 ssi_signal; - __be32 ssi_noise; - __be32 preamble; - __be32 encoding; -}; - -void islpci_eth_cleanup_transmit(islpci_private *, isl38xx_control_block *); -netdev_tx_t islpci_eth_transmit(struct sk_buff *, struct net_device *); -int islpci_eth_receive(islpci_private *); -void islpci_eth_tx_timeout(struct net_device *); -void islpci_do_reset_and_wake(struct work_struct *); - -#endif /* _ISL_GEN_H */ diff --git a/drivers/net/wireless/prism54/islpci_hotplug.c b/drivers/net/wireless/prism54/islpci_hotplug.c deleted file mode 100644 index 83d366258c81..000000000000 --- a/drivers/net/wireless/prism54/islpci_hotplug.c +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright (C) 2003 Herbert Valerio Riedel - * - * 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 - * - * 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 - * - */ - -#include -#include -#include -#include /* For __init, __exit */ -#include - -#include "prismcompat.h" -#include "islpci_dev.h" -#include "islpci_mgt.h" /* for pc_debug */ -#include "isl_oid.h" - -MODULE_AUTHOR("[Intersil] R.Bastings and W.Termorshuizen, The prism54.org Development Team "); -MODULE_DESCRIPTION("The Prism54 802.11 Wireless LAN adapter"); -MODULE_LICENSE("GPL"); - -static int init_pcitm = 0; -module_param(init_pcitm, int, 0); - -/* In this order: vendor, device, subvendor, subdevice, class, class_mask, - * driver_data - * If you have an update for this please contact prism54-devel@prism54.org - * The latest list can be found at http://prism54.org/supported_cards.php */ -static const struct pci_device_id prism54_id_tbl[] = { - /* Intersil PRISM Duette/Prism GT Wireless LAN adapter */ - { - 0x1260, 0x3890, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 - }, - - /* 3COM 3CRWE154G72 Wireless LAN adapter */ - { - PCI_VDEVICE(3COM, 0x6001), 0 - }, - - /* Intersil PRISM Indigo Wireless LAN adapter */ - { - 0x1260, 0x3877, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 - }, - - /* Intersil PRISM Javelin/Xbow Wireless LAN adapter */ - { - 0x1260, 0x3886, - PCI_ANY_ID, PCI_ANY_ID, - 0, 0, 0 - }, - - /* End of list */ - {0,0,0,0,0,0,0} -}; - -/* register the device with the Hotplug facilities of the kernel */ -MODULE_DEVICE_TABLE(pci, prism54_id_tbl); - -static int prism54_probe(struct pci_dev *, const struct pci_device_id *); -static void prism54_remove(struct pci_dev *); -static int prism54_suspend(struct pci_dev *, pm_message_t state); -static int prism54_resume(struct pci_dev *); - -static struct pci_driver prism54_driver = { - .name = DRV_NAME, - .id_table = prism54_id_tbl, - .probe = prism54_probe, - .remove = prism54_remove, - .suspend = prism54_suspend, - .resume = prism54_resume, -}; - -/****************************************************************************** - Module initialization functions -******************************************************************************/ - -static int -prism54_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct net_device *ndev; - u8 latency_tmr; - u32 mem_addr; - islpci_private *priv; - int rvalue; - - /* Enable the pci device */ - if (pci_enable_device(pdev)) { - printk(KERN_ERR "%s: pci_enable_device() failed.\n", DRV_NAME); - return -ENODEV; - } - - /* check whether the latency timer is set correctly */ - pci_read_config_byte(pdev, PCI_LATENCY_TIMER, &latency_tmr); -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "latency timer: %x\n", latency_tmr); -#endif - if (latency_tmr < PCIDEVICE_LATENCY_TIMER_MIN) { - /* set the latency timer */ - pci_write_config_byte(pdev, PCI_LATENCY_TIMER, - PCIDEVICE_LATENCY_TIMER_VAL); - } - - /* enable PCI DMA */ - if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) { - printk(KERN_ERR "%s: 32-bit PCI DMA not supported", DRV_NAME); - goto do_pci_disable_device; - } - - /* 0x40 is the programmable timer to configure the response timeout (TRDY_TIMEOUT) - * 0x41 is the programmable timer to configure the retry timeout (RETRY_TIMEOUT) - * The RETRY_TIMEOUT is used to set the number of retries that the core, as a - * Master, will perform before abandoning a cycle. The default value for - * RETRY_TIMEOUT is 0x80, which far exceeds the PCI 2.1 requirement for new - * devices. A write of zero to the RETRY_TIMEOUT register disables this - * function to allow use with any non-compliant legacy devices that may - * execute more retries. - * - * Writing zero to both these two registers will disable both timeouts and - * *can* solve problems caused by devices that are slow to respond. - * Make this configurable - MSW - */ - if ( init_pcitm >= 0 ) { - pci_write_config_byte(pdev, 0x40, (u8)init_pcitm); - pci_write_config_byte(pdev, 0x41, (u8)init_pcitm); - } else { - printk(KERN_INFO "PCI TRDY/RETRY unchanged\n"); - } - - /* request the pci device I/O regions */ - rvalue = pci_request_regions(pdev, DRV_NAME); - if (rvalue) { - printk(KERN_ERR "%s: pci_request_regions failure (rc=%d)\n", - DRV_NAME, rvalue); - goto do_pci_disable_device; - } - - /* check if the memory window is indeed set */ - rvalue = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &mem_addr); - if (rvalue || !mem_addr) { - printk(KERN_ERR "%s: PCI device memory region not configured; fix your BIOS or CardBus bridge/drivers\n", - DRV_NAME); - goto do_pci_release_regions; - } - - /* enable PCI bus-mastering */ - DEBUG(SHOW_TRACING, "%s: pci_set_master(pdev)\n", DRV_NAME); - pci_set_master(pdev); - - /* enable MWI */ - pci_try_set_mwi(pdev); - - /* setup the network device interface and its structure */ - if (!(ndev = islpci_setup(pdev))) { - /* error configuring the driver as a network device */ - printk(KERN_ERR "%s: could not configure network device\n", - DRV_NAME); - goto do_pci_clear_mwi; - } - - priv = netdev_priv(ndev); - islpci_set_state(priv, PRV_STATE_PREBOOT); /* we are attempting to boot */ - - /* card is in unknown state yet, might have some interrupts pending */ - isl38xx_disable_interrupts(priv->device_base); - - /* request for the interrupt before uploading the firmware */ - rvalue = request_irq(pdev->irq, &islpci_interrupt, - IRQF_SHARED, ndev->name, priv); - - if (rvalue) { - /* error, could not hook the handler to the irq */ - printk(KERN_ERR "%s: could not install IRQ handler\n", - ndev->name); - goto do_unregister_netdev; - } - - /* firmware upload is triggered in islpci_open */ - - return 0; - - do_unregister_netdev: - unregister_netdev(ndev); - islpci_free_memory(priv); - pci_set_drvdata(pdev, NULL); - free_netdev(ndev); - priv = NULL; - do_pci_clear_mwi: - pci_clear_mwi(pdev); - do_pci_release_regions: - pci_release_regions(pdev); - do_pci_disable_device: - pci_disable_device(pdev); - return -EIO; -} - -/* set by cleanup_module */ -static volatile int __in_cleanup_module = 0; - -/* this one removes one(!!) instance only */ -static void -prism54_remove(struct pci_dev *pdev) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; - BUG_ON(!priv); - - if (!__in_cleanup_module) { - printk(KERN_DEBUG "%s: hot unplug detected\n", ndev->name); - islpci_set_state(priv, PRV_STATE_OFF); - } - - printk(KERN_DEBUG "%s: removing device\n", ndev->name); - - unregister_netdev(ndev); - - /* free the interrupt request */ - - if (islpci_get_state(priv) != PRV_STATE_OFF) { - isl38xx_disable_interrupts(priv->device_base); - islpci_set_state(priv, PRV_STATE_OFF); - /* This bellow causes a lockup at rmmod time. It might be - * because some interrupts still linger after rmmod time, - * see bug #17 */ - /* pci_set_power_state(pdev, 3);*/ /* try to power-off */ - } - - free_irq(pdev->irq, priv); - - /* free the PCI memory and unmap the remapped page */ - islpci_free_memory(priv); - - pci_set_drvdata(pdev, NULL); - free_netdev(ndev); - priv = NULL; - - pci_clear_mwi(pdev); - - pci_release_regions(pdev); - - pci_disable_device(pdev); -} - -static int -prism54_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; - BUG_ON(!priv); - - - pci_save_state(pdev); - - /* tell the device not to trigger interrupts for now... */ - isl38xx_disable_interrupts(priv->device_base); - - /* from now on assume the hardware was already powered down - and don't touch it anymore */ - islpci_set_state(priv, PRV_STATE_OFF); - - netif_stop_queue(ndev); - netif_device_detach(ndev); - - return 0; -} - -static int -prism54_resume(struct pci_dev *pdev) -{ - struct net_device *ndev = pci_get_drvdata(pdev); - islpci_private *priv = ndev ? netdev_priv(ndev) : NULL; - int err; - - BUG_ON(!priv); - - printk(KERN_NOTICE "%s: got resume request\n", ndev->name); - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s: pci_enable_device failed on resume\n", - ndev->name); - return err; - } - - pci_restore_state(pdev); - - /* alright let's go into the PREBOOT state */ - islpci_reset(priv, 1); - - netif_device_attach(ndev); - netif_start_queue(ndev); - - return 0; -} - -static int __init -prism54_module_init(void) -{ - printk(KERN_INFO "Loaded %s driver, version %s\n", - DRV_NAME, DRV_VERSION); - - __bug_on_wrong_struct_sizes (); - - return pci_register_driver(&prism54_driver); -} - -/* by the time prism54_module_exit() terminates, as a postcondition - * all instances will have been destroyed by calls to - * prism54_remove() */ -static void __exit -prism54_module_exit(void) -{ - __in_cleanup_module = 1; - - pci_unregister_driver(&prism54_driver); - - printk(KERN_INFO "Unloaded %s driver\n", DRV_NAME); - - __in_cleanup_module = 0; -} - -/* register entry points */ -module_init(prism54_module_init); -module_exit(prism54_module_exit); -/* EOF */ diff --git a/drivers/net/wireless/prism54/islpci_mgt.c b/drivers/net/wireless/prism54/islpci_mgt.c deleted file mode 100644 index 69d2f882fd06..000000000000 --- a/drivers/net/wireless/prism54/islpci_mgt.c +++ /dev/null @@ -1,511 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright 2004 Jens Maurer - * - * 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 - * - * 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 - * - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include "prismcompat.h" -#include "isl_38xx.h" -#include "islpci_mgt.h" -#include "isl_oid.h" /* additional types and defs for isl38xx fw */ -#include "isl_ioctl.h" - -#include - -/****************************************************************************** - Global variable definition section -******************************************************************************/ -int pc_debug = VERBOSE; -module_param(pc_debug, int, 0); - -/****************************************************************************** - Driver general functions -******************************************************************************/ -#if VERBOSE > SHOW_ERROR_MESSAGES -void -display_buffer(char *buffer, int length) -{ - if ((pc_debug & SHOW_BUFFER_CONTENTS) == 0) - return; - - while (length > 0) { - printk("[%02x]", *buffer & 255); - length--; - buffer++; - } - - printk("\n"); -} -#endif - -/***************************************************************************** - Queue handling for management frames -******************************************************************************/ - -/* - * Helper function to create a PIMFOR management frame header. - */ -static void -pimfor_encode_header(int operation, u32 oid, u32 length, pimfor_header_t *h) -{ - h->version = PIMFOR_VERSION; - h->operation = operation; - h->device_id = PIMFOR_DEV_ID_MHLI_MIB; - h->flags = 0; - h->oid = cpu_to_be32(oid); - h->length = cpu_to_be32(length); -} - -/* - * Helper function to analyze a PIMFOR management frame header. - */ -static pimfor_header_t * -pimfor_decode_header(void *data, int len) -{ - pimfor_header_t *h = data; - - while ((void *) h < data + len) { - if (h->flags & PIMFOR_FLAG_LITTLE_ENDIAN) { - le32_to_cpus(&h->oid); - le32_to_cpus(&h->length); - } else { - be32_to_cpus(&h->oid); - be32_to_cpus(&h->length); - } - if (h->oid != OID_INL_TUNNEL) - return h; - h++; - } - return NULL; -} - -/* - * Fill the receive queue for management frames with fresh buffers. - */ -int -islpci_mgmt_rx_fill(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; - u32 curr = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ]); - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgmt_rx_fill \n"); -#endif - - while (curr - priv->index_mgmt_rx < ISL38XX_CB_MGMT_QSIZE) { - u32 index = curr % ISL38XX_CB_MGMT_QSIZE; - struct islpci_membuf *buf = &priv->mgmt_rx[index]; - isl38xx_fragment *frag = &cb->rx_data_mgmt[index]; - - if (buf->mem == NULL) { - buf->mem = kmalloc(MGMT_FRAME_SIZE, GFP_ATOMIC); - if (!buf->mem) { - printk(KERN_WARNING - "Error allocating management frame.\n"); - return -ENOMEM; - } - buf->size = MGMT_FRAME_SIZE; - } - if (buf->pci_addr == 0) { - buf->pci_addr = pci_map_single(priv->pdev, buf->mem, - MGMT_FRAME_SIZE, - PCI_DMA_FROMDEVICE); - if (!buf->pci_addr) { - printk(KERN_WARNING - "Failed to make memory DMA'able.\n"); - return -ENOMEM; - } - } - - /* be safe: always reset control block information */ - frag->size = cpu_to_le16(MGMT_FRAME_SIZE); - frag->flags = 0; - frag->address = cpu_to_le32(buf->pci_addr); - curr++; - - /* The fragment address in the control block must have - * been written before announcing the frame buffer to - * device */ - wmb(); - cb->driver_curr_frag[ISL38XX_CB_RX_MGMTQ] = cpu_to_le32(curr); - } - return 0; -} - -/* - * Create and transmit a management frame using "operation" and "oid", - * with arguments data/length. - * We either return an error and free the frame, or we return 0 and - * islpci_mgt_cleanup_transmit() frees the frame in the tx-done - * interrupt. - */ -static int -islpci_mgt_transmit(struct net_device *ndev, int operation, unsigned long oid, - void *data, int length) -{ - islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; - void *p; - int err = -EINVAL; - unsigned long flags; - isl38xx_fragment *frag; - struct islpci_membuf buf; - u32 curr_frag; - int index; - int frag_len = length + PIMFOR_HEADER_SIZE; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_transmit\n"); -#endif - - if (frag_len > MGMT_FRAME_SIZE) { - printk(KERN_DEBUG "%s: mgmt frame too large %d\n", - ndev->name, frag_len); - goto error; - } - - err = -ENOMEM; - p = buf.mem = kmalloc(frag_len, GFP_KERNEL); - if (!buf.mem) { - printk(KERN_DEBUG "%s: cannot allocate mgmt frame\n", - ndev->name); - goto error; - } - buf.size = frag_len; - - /* create the header directly in the fragment data area */ - pimfor_encode_header(operation, oid, length, (pimfor_header_t *) p); - p += PIMFOR_HEADER_SIZE; - - if (data) - memcpy(p, data, length); - else - memset(p, 0, length); - -#if VERBOSE > SHOW_ERROR_MESSAGES - { - pimfor_header_t *h = buf.mem; - DEBUG(SHOW_PIMFOR_FRAMES, - "PIMFOR: op %i, oid 0x%08lx, device %i, flags 0x%x length 0x%x \n", - h->operation, oid, h->device_id, h->flags, length); - - /* display the buffer contents for debugging */ - display_buffer((char *) h, sizeof (pimfor_header_t)); - display_buffer(p, length); - } -#endif - - err = -ENOMEM; - buf.pci_addr = pci_map_single(priv->pdev, buf.mem, frag_len, - PCI_DMA_TODEVICE); - if (!buf.pci_addr) { - printk(KERN_WARNING "%s: cannot map PCI memory for mgmt\n", - ndev->name); - goto error_free; - } - - /* Protect the control block modifications against interrupts. */ - spin_lock_irqsave(&priv->slock, flags); - curr_frag = le32_to_cpu(cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ]); - if (curr_frag - priv->index_mgmt_tx >= ISL38XX_CB_MGMT_QSIZE) { - printk(KERN_WARNING "%s: mgmt tx queue is still full\n", - ndev->name); - goto error_unlock; - } - - /* commit the frame to the tx device queue */ - index = curr_frag % ISL38XX_CB_MGMT_QSIZE; - priv->mgmt_tx[index] = buf; - frag = &cb->tx_data_mgmt[index]; - frag->size = cpu_to_le16(frag_len); - frag->flags = 0; /* for any other than the last fragment, set to 1 */ - frag->address = cpu_to_le32(buf.pci_addr); - - /* The fragment address in the control block must have - * been written before announcing the frame buffer to - * device */ - wmb(); - cb->driver_curr_frag[ISL38XX_CB_TX_MGMTQ] = cpu_to_le32(curr_frag + 1); - spin_unlock_irqrestore(&priv->slock, flags); - - /* trigger the device */ - islpci_trigger(priv); - return 0; - - error_unlock: - spin_unlock_irqrestore(&priv->slock, flags); - error_free: - kfree(buf.mem); - error: - return err; -} - -/* - * Receive a management frame from the device. - * This can be an arbitrary number of traps, and at most one response - * frame for a previous request sent via islpci_mgt_transmit(). - */ -int -islpci_mgt_receive(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = - (isl38xx_control_block *) priv->control_block; - u32 curr_frag; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_receive \n"); -#endif - - /* Only once per interrupt, determine fragment range to - * process. This avoids an endless loop (i.e. lockup) if - * frames come in faster than we can process them. */ - curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_RX_MGMTQ]); - barrier(); - - for (; priv->index_mgmt_rx < curr_frag; priv->index_mgmt_rx++) { - pimfor_header_t *header; - u32 index = priv->index_mgmt_rx % ISL38XX_CB_MGMT_QSIZE; - struct islpci_membuf *buf = &priv->mgmt_rx[index]; - u16 frag_len; - int size; - struct islpci_mgmtframe *frame; - - /* I have no idea (and no documentation) if flags != 0 - * is possible. Drop the frame, reuse the buffer. */ - if (le16_to_cpu(cb->rx_data_mgmt[index].flags) != 0) { - printk(KERN_WARNING "%s: unknown flags 0x%04x\n", - ndev->name, - le16_to_cpu(cb->rx_data_mgmt[index].flags)); - continue; - } - - /* The device only returns the size of the header(s) here. */ - frag_len = le16_to_cpu(cb->rx_data_mgmt[index].size); - - /* - * We appear to have no way to tell the device the - * size of a receive buffer. Thus, if this check - * triggers, we likely have kernel heap corruption. */ - if (frag_len > MGMT_FRAME_SIZE) { - printk(KERN_WARNING - "%s: Bogus packet size of %d (%#x).\n", - ndev->name, frag_len, frag_len); - frag_len = MGMT_FRAME_SIZE; - } - - /* Ensure the results of device DMA are visible to the CPU. */ - pci_dma_sync_single_for_cpu(priv->pdev, buf->pci_addr, - buf->size, PCI_DMA_FROMDEVICE); - - /* Perform endianess conversion for PIMFOR header in-place. */ - header = pimfor_decode_header(buf->mem, frag_len); - if (!header) { - printk(KERN_WARNING "%s: no PIMFOR header found\n", - ndev->name); - continue; - } - - /* The device ID from the PIMFOR packet received from - * the MVC is always 0. We forward a sensible device_id. - * Not that anyone upstream would care... */ - header->device_id = priv->ndev->ifindex; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_PIMFOR_FRAMES, - "PIMFOR: op %i, oid 0x%08x, device %i, flags 0x%x length 0x%x \n", - header->operation, header->oid, header->device_id, - header->flags, header->length); - - /* display the buffer contents for debugging */ - display_buffer((char *) header, PIMFOR_HEADER_SIZE); - display_buffer((char *) header + PIMFOR_HEADER_SIZE, - header->length); -#endif - - /* nobody sends these */ - if (header->flags & PIMFOR_FLAG_APPLIC_ORIGIN) { - printk(KERN_DEBUG - "%s: errant PIMFOR application frame\n", - ndev->name); - continue; - } - - /* Determine frame size, skipping OID_INL_TUNNEL headers. */ - size = PIMFOR_HEADER_SIZE + header->length; - frame = kmalloc(sizeof (struct islpci_mgmtframe) + size, - GFP_ATOMIC); - if (!frame) { - printk(KERN_WARNING - "%s: Out of memory, cannot handle oid 0x%08x\n", - ndev->name, header->oid); - continue; - } - frame->ndev = ndev; - memcpy(&frame->buf, header, size); - frame->header = (pimfor_header_t *) frame->buf; - frame->data = frame->buf + PIMFOR_HEADER_SIZE; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_PIMFOR_FRAMES, - "frame: header: %p, data: %p, size: %d\n", - frame->header, frame->data, size); -#endif - - if (header->operation == PIMFOR_OP_TRAP) { -#if VERBOSE > SHOW_ERROR_MESSAGES - printk(KERN_DEBUG - "TRAP: oid 0x%x, device %i, flags 0x%x length %i\n", - header->oid, header->device_id, header->flags, - header->length); -#endif - - /* Create work to handle trap out of interrupt - * context. */ - INIT_WORK(&frame->ws, prism54_process_trap); - schedule_work(&frame->ws); - - } else { - /* Signal the one waiting process that a response - * has been received. */ - if ((frame = xchg(&priv->mgmt_received, frame)) != NULL) { - printk(KERN_WARNING - "%s: mgmt response not collected\n", - ndev->name); - kfree(frame); - } -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_TRACING, "Wake up Mgmt Queue\n"); -#endif - wake_up(&priv->mgmt_wqueue); - } - - } - - return 0; -} - -/* - * Cleanup the transmit queue by freeing all frames handled by the device. - */ -void -islpci_mgt_cleanup_transmit(struct net_device *ndev) -{ - islpci_private *priv = netdev_priv(ndev); - isl38xx_control_block *cb = /* volatile not needed */ - (isl38xx_control_block *) priv->control_block; - u32 curr_frag; - -#if VERBOSE > SHOW_ERROR_MESSAGES - DEBUG(SHOW_FUNCTION_CALLS, "islpci_mgt_cleanup_transmit\n"); -#endif - - /* Only once per cleanup, determine fragment range to - * process. This avoids an endless loop (i.e. lockup) if - * the device became confused, incrementing device_curr_frag - * rapidly. */ - curr_frag = le32_to_cpu(cb->device_curr_frag[ISL38XX_CB_TX_MGMTQ]); - barrier(); - - for (; priv->index_mgmt_tx < curr_frag; priv->index_mgmt_tx++) { - int index = priv->index_mgmt_tx % ISL38XX_CB_MGMT_QSIZE; - struct islpci_membuf *buf = &priv->mgmt_tx[index]; - pci_unmap_single(priv->pdev, buf->pci_addr, buf->size, - PCI_DMA_TODEVICE); - buf->pci_addr = 0; - kfree(buf->mem); - buf->mem = NULL; - buf->size = 0; - } -} - -/* - * Perform one request-response transaction to the device. - */ -int -islpci_mgt_transaction(struct net_device *ndev, - int operation, unsigned long oid, - void *senddata, int sendlen, - struct islpci_mgmtframe **recvframe) -{ - islpci_private *priv = netdev_priv(ndev); - const long wait_cycle_jiffies = msecs_to_jiffies(ISL38XX_WAIT_CYCLE * 10); - long timeout_left = ISL38XX_MAX_WAIT_CYCLES * wait_cycle_jiffies; - int err; - DEFINE_WAIT(wait); - - *recvframe = NULL; - - if (mutex_lock_interruptible(&priv->mgmt_lock)) - return -ERESTARTSYS; - - prepare_to_wait(&priv->mgmt_wqueue, &wait, TASK_UNINTERRUPTIBLE); - err = islpci_mgt_transmit(ndev, operation, oid, senddata, sendlen); - if (err) - goto out; - - err = -ETIMEDOUT; - while (timeout_left > 0) { - int timeleft; - struct islpci_mgmtframe *frame; - - timeleft = schedule_timeout_uninterruptible(wait_cycle_jiffies); - frame = xchg(&priv->mgmt_received, NULL); - if (frame) { - if (frame->header->oid == oid) { - *recvframe = frame; - err = 0; - goto out; - } else { - printk(KERN_DEBUG - "%s: expecting oid 0x%x, received 0x%x.\n", - ndev->name, (unsigned int) oid, - frame->header->oid); - kfree(frame); - frame = NULL; - } - } - if (timeleft == 0) { - printk(KERN_DEBUG - "%s: timeout waiting for mgmt response %lu, " - "triggering device\n", - ndev->name, timeout_left); - islpci_trigger(priv); - } - timeout_left += timeleft - wait_cycle_jiffies; - } - printk(KERN_WARNING "%s: timeout waiting for mgmt response\n", - ndev->name); - - /* TODO: we should reset the device here */ - out: - finish_wait(&priv->mgmt_wqueue, &wait); - mutex_unlock(&priv->mgmt_lock); - return err; -} - diff --git a/drivers/net/wireless/prism54/islpci_mgt.h b/drivers/net/wireless/prism54/islpci_mgt.h deleted file mode 100644 index 87a1734663da..000000000000 --- a/drivers/net/wireless/prism54/islpci_mgt.h +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (C) 2002 Intersil Americas Inc. - * Copyright (C) 2003 Luis R. Rodriguez - * - * 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 - * - * 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 - * - */ - -#ifndef _ISLPCI_MGT_H -#define _ISLPCI_MGT_H - -#include -#include - -/* - * Function definitions - */ - -#define K_DEBUG(f, m, args...) do { if(f & m) printk(KERN_DEBUG args); } while(0) -#define DEBUG(f, args...) K_DEBUG(f, pc_debug, args) - -extern int pc_debug; -#define init_wds 0 /* help compiler optimize away dead code */ - - -/* General driver definitions */ -#define PCIDEVICE_LATENCY_TIMER_MIN 0x40 -#define PCIDEVICE_LATENCY_TIMER_VAL 0x50 - -/* Debugging verbose definitions */ -#define SHOW_NOTHING 0x00 /* overrules everything */ -#define SHOW_ANYTHING 0xFF -#define SHOW_ERROR_MESSAGES 0x01 -#define SHOW_TRAPS 0x02 -#define SHOW_FUNCTION_CALLS 0x04 -#define SHOW_TRACING 0x08 -#define SHOW_QUEUE_INDEXES 0x10 -#define SHOW_PIMFOR_FRAMES 0x20 -#define SHOW_BUFFER_CONTENTS 0x40 -#define VERBOSE 0x01 - -/* Default card definitions */ -#define CARD_DEFAULT_CHANNEL 6 -#define CARD_DEFAULT_MODE INL_MODE_CLIENT -#define CARD_DEFAULT_IW_MODE IW_MODE_INFRA -#define CARD_DEFAULT_BSSTYPE DOT11_BSSTYPE_INFRA -#define CARD_DEFAULT_CLIENT_SSID "" -#define CARD_DEFAULT_AP_SSID "default" -#define CARD_DEFAULT_KEY1 "default_key_1" -#define CARD_DEFAULT_KEY2 "default_key_2" -#define CARD_DEFAULT_KEY3 "default_key_3" -#define CARD_DEFAULT_KEY4 "default_key_4" -#define CARD_DEFAULT_WEP 0 -#define CARD_DEFAULT_FILTER 0 -#define CARD_DEFAULT_WDS 0 -#define CARD_DEFAULT_AUTHEN DOT11_AUTH_OS -#define CARD_DEFAULT_DOT1X 0 -#define CARD_DEFAULT_MLME_MODE DOT11_MLME_AUTO -#define CARD_DEFAULT_CONFORMANCE OID_INL_CONFORMANCE_NONE -#define CARD_DEFAULT_PROFILE DOT11_PROFILE_MIXED_G_WIFI -#define CARD_DEFAULT_MAXFRAMEBURST DOT11_MAXFRAMEBURST_MIXED_SAFE - -/* PIMFOR package definitions */ -#define PIMFOR_ETHERTYPE 0x8828 -#define PIMFOR_HEADER_SIZE 12 -#define PIMFOR_VERSION 1 -#define PIMFOR_OP_GET 0 -#define PIMFOR_OP_SET 1 -#define PIMFOR_OP_RESPONSE 2 -#define PIMFOR_OP_ERROR 3 -#define PIMFOR_OP_TRAP 4 -#define PIMFOR_OP_RESERVED 5 /* till 255 */ -#define PIMFOR_DEV_ID_MHLI_MIB 0 -#define PIMFOR_FLAG_APPLIC_ORIGIN 0x01 -#define PIMFOR_FLAG_LITTLE_ENDIAN 0x02 - -void display_buffer(char *, int); - -/* - * Type definition section - * - * the structure defines only the header allowing copyless - * frame handling - */ -typedef struct { - u8 version; - u8 operation; - u32 oid; - u8 device_id; - u8 flags; - u32 length; -} __attribute__ ((packed)) -pimfor_header_t; - -/* A received and interrupt-processed management frame, either for - * schedule_work(prism54_process_trap) or for priv->mgmt_received, - * processed by islpci_mgt_transaction(). */ -struct islpci_mgmtframe { - struct net_device *ndev; /* pointer to network device */ - pimfor_header_t *header; /* payload header, points into buf */ - void *data; /* payload ex header, points into buf */ - struct work_struct ws; /* argument for schedule_work() */ - char buf[0]; /* fragment buffer */ -}; - -int -islpci_mgt_receive(struct net_device *ndev); - -int -islpci_mgmt_rx_fill(struct net_device *ndev); - -void -islpci_mgt_cleanup_transmit(struct net_device *ndev); - -int -islpci_mgt_transaction(struct net_device *ndev, - int operation, unsigned long oid, - void *senddata, int sendlen, - struct islpci_mgmtframe **recvframe); - -static inline void -islpci_mgt_release(struct islpci_mgmtframe *frame) -{ - kfree(frame); -} - -#endif /* _ISLPCI_MGT_H */ diff --git a/drivers/net/wireless/prism54/oid_mgt.c b/drivers/net/wireless/prism54/oid_mgt.c deleted file mode 100644 index 1187e6112a64..000000000000 --- a/drivers/net/wireless/prism54/oid_mgt.c +++ /dev/null @@ -1,904 +0,0 @@ -/* - * Copyright (C) 2003,2004 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#include - -#include "prismcompat.h" -#include "islpci_dev.h" -#include "islpci_mgt.h" -#include "isl_oid.h" -#include "oid_mgt.h" -#include "isl_ioctl.h" - -/* to convert between channel and freq */ -static const int frequency_list_bg[] = { 2412, 2417, 2422, 2427, 2432, - 2437, 2442, 2447, 2452, 2457, 2462, 2467, 2472, 2484 -}; - -int -channel_of_freq(int f) -{ - int c = 0; - - if ((f >= 2412) && (f <= 2484)) { - while ((c < 14) && (f != frequency_list_bg[c])) - c++; - return (c >= 14) ? 0 : ++c; - } else if ((f >= (int) 5000) && (f <= (int) 6000)) { - return ( (f - 5000) / 5 ); - } else - return 0; -} - -#define OID_STRUCT(name,oid,s,t) [name] = {oid, 0, sizeof(s), t} -#define OID_STRUCT_C(name,oid,s,t) OID_STRUCT(name,oid,s,t | OID_FLAG_CACHED) -#define OID_U32(name,oid) OID_STRUCT(name,oid,u32,OID_TYPE_U32) -#define OID_U32_C(name,oid) OID_STRUCT_C(name,oid,u32,OID_TYPE_U32) -#define OID_STRUCT_MLME(name,oid) OID_STRUCT(name,oid,struct obj_mlme,OID_TYPE_MLME) -#define OID_STRUCT_MLMEEX(name,oid) OID_STRUCT(name,oid,struct obj_mlmeex,OID_TYPE_MLMEEX) - -#define OID_UNKNOWN(name,oid) OID_STRUCT(name,oid,0,0) - -struct oid_t isl_oid[] = { - OID_STRUCT(GEN_OID_MACADDRESS, 0x00000000, u8[6], OID_TYPE_ADDR), - OID_U32(GEN_OID_LINKSTATE, 0x00000001), - OID_UNKNOWN(GEN_OID_WATCHDOG, 0x00000002), - OID_UNKNOWN(GEN_OID_MIBOP, 0x00000003), - OID_UNKNOWN(GEN_OID_OPTIONS, 0x00000004), - OID_UNKNOWN(GEN_OID_LEDCONFIG, 0x00000005), - - /* 802.11 */ - OID_U32_C(DOT11_OID_BSSTYPE, 0x10000000), - OID_STRUCT_C(DOT11_OID_BSSID, 0x10000001, u8[6], OID_TYPE_RAW), - OID_STRUCT_C(DOT11_OID_SSID, 0x10000002, struct obj_ssid, - OID_TYPE_SSID), - OID_U32(DOT11_OID_STATE, 0x10000003), - OID_U32(DOT11_OID_AID, 0x10000004), - OID_STRUCT(DOT11_OID_COUNTRYSTRING, 0x10000005, u8[4], OID_TYPE_RAW), - OID_STRUCT_C(DOT11_OID_SSIDOVERRIDE, 0x10000006, struct obj_ssid, - OID_TYPE_SSID), - - OID_U32(DOT11_OID_MEDIUMLIMIT, 0x11000000), - OID_U32_C(DOT11_OID_BEACONPERIOD, 0x11000001), - OID_U32(DOT11_OID_DTIMPERIOD, 0x11000002), - OID_U32(DOT11_OID_ATIMWINDOW, 0x11000003), - OID_U32(DOT11_OID_LISTENINTERVAL, 0x11000004), - OID_U32(DOT11_OID_CFPPERIOD, 0x11000005), - OID_U32(DOT11_OID_CFPDURATION, 0x11000006), - - OID_U32_C(DOT11_OID_AUTHENABLE, 0x12000000), - OID_U32_C(DOT11_OID_PRIVACYINVOKED, 0x12000001), - OID_U32_C(DOT11_OID_EXUNENCRYPTED, 0x12000002), - OID_U32_C(DOT11_OID_DEFKEYID, 0x12000003), - [DOT11_OID_DEFKEYX] = {0x12000004, 3, sizeof (struct obj_key), - OID_FLAG_CACHED | OID_TYPE_KEY}, /* DOT11_OID_DEFKEY1,...DOT11_OID_DEFKEY4 */ - OID_UNKNOWN(DOT11_OID_STAKEY, 0x12000008), - OID_U32(DOT11_OID_REKEYTHRESHOLD, 0x12000009), - OID_UNKNOWN(DOT11_OID_STASC, 0x1200000a), - - OID_U32(DOT11_OID_PRIVTXREJECTED, 0x1a000000), - OID_U32(DOT11_OID_PRIVRXPLAIN, 0x1a000001), - OID_U32(DOT11_OID_PRIVRXFAILED, 0x1a000002), - OID_U32(DOT11_OID_PRIVRXNOKEY, 0x1a000003), - - OID_U32_C(DOT11_OID_RTSTHRESH, 0x13000000), - OID_U32_C(DOT11_OID_FRAGTHRESH, 0x13000001), - OID_U32_C(DOT11_OID_SHORTRETRIES, 0x13000002), - OID_U32_C(DOT11_OID_LONGRETRIES, 0x13000003), - OID_U32_C(DOT11_OID_MAXTXLIFETIME, 0x13000004), - OID_U32(DOT11_OID_MAXRXLIFETIME, 0x13000005), - OID_U32(DOT11_OID_AUTHRESPTIMEOUT, 0x13000006), - OID_U32(DOT11_OID_ASSOCRESPTIMEOUT, 0x13000007), - - OID_UNKNOWN(DOT11_OID_ALOFT_TABLE, 0x1d000000), - OID_UNKNOWN(DOT11_OID_ALOFT_CTRL_TABLE, 0x1d000001), - OID_UNKNOWN(DOT11_OID_ALOFT_RETREAT, 0x1d000002), - OID_UNKNOWN(DOT11_OID_ALOFT_PROGRESS, 0x1d000003), - OID_U32(DOT11_OID_ALOFT_FIXEDRATE, 0x1d000004), - OID_UNKNOWN(DOT11_OID_ALOFT_RSSIGRAPH, 0x1d000005), - OID_UNKNOWN(DOT11_OID_ALOFT_CONFIG, 0x1d000006), - - [DOT11_OID_VDCFX] = {0x1b000000, 7, 0, 0}, - OID_U32(DOT11_OID_MAXFRAMEBURST, 0x1b000008), - - OID_U32(DOT11_OID_PSM, 0x14000000), - OID_U32(DOT11_OID_CAMTIMEOUT, 0x14000001), - OID_U32(DOT11_OID_RECEIVEDTIMS, 0x14000002), - OID_U32(DOT11_OID_ROAMPREFERENCE, 0x14000003), - - OID_U32(DOT11_OID_BRIDGELOCAL, 0x15000000), - OID_U32(DOT11_OID_CLIENTS, 0x15000001), - OID_U32(DOT11_OID_CLIENTSASSOCIATED, 0x15000002), - [DOT11_OID_CLIENTX] = {0x15000003, 2006, 0, 0}, /* DOT11_OID_CLIENTX,...DOT11_OID_CLIENT2007 */ - - OID_STRUCT(DOT11_OID_CLIENTFIND, 0x150007DB, u8[6], OID_TYPE_ADDR), - OID_STRUCT(DOT11_OID_WDSLINKADD, 0x150007DC, u8[6], OID_TYPE_ADDR), - OID_STRUCT(DOT11_OID_WDSLINKREMOVE, 0x150007DD, u8[6], OID_TYPE_ADDR), - OID_STRUCT(DOT11_OID_EAPAUTHSTA, 0x150007DE, u8[6], OID_TYPE_ADDR), - OID_STRUCT(DOT11_OID_EAPUNAUTHSTA, 0x150007DF, u8[6], OID_TYPE_ADDR), - OID_U32_C(DOT11_OID_DOT1XENABLE, 0x150007E0), - OID_UNKNOWN(DOT11_OID_MICFAILURE, 0x150007E1), - OID_UNKNOWN(DOT11_OID_REKEYINDICATE, 0x150007E2), - - OID_U32(DOT11_OID_MPDUTXSUCCESSFUL, 0x16000000), - OID_U32(DOT11_OID_MPDUTXONERETRY, 0x16000001), - OID_U32(DOT11_OID_MPDUTXMULTIPLERETRIES, 0x16000002), - OID_U32(DOT11_OID_MPDUTXFAILED, 0x16000003), - OID_U32(DOT11_OID_MPDURXSUCCESSFUL, 0x16000004), - OID_U32(DOT11_OID_MPDURXDUPS, 0x16000005), - OID_U32(DOT11_OID_RTSSUCCESSFUL, 0x16000006), - OID_U32(DOT11_OID_RTSFAILED, 0x16000007), - OID_U32(DOT11_OID_ACKFAILED, 0x16000008), - OID_U32(DOT11_OID_FRAMERECEIVES, 0x16000009), - OID_U32(DOT11_OID_FRAMEERRORS, 0x1600000A), - OID_U32(DOT11_OID_FRAMEABORTS, 0x1600000B), - OID_U32(DOT11_OID_FRAMEABORTSPHY, 0x1600000C), - - OID_U32(DOT11_OID_SLOTTIME, 0x17000000), - OID_U32(DOT11_OID_CWMIN, 0x17000001), - OID_U32(DOT11_OID_CWMAX, 0x17000002), - OID_U32(DOT11_OID_ACKWINDOW, 0x17000003), - OID_U32(DOT11_OID_ANTENNARX, 0x17000004), - OID_U32(DOT11_OID_ANTENNATX, 0x17000005), - OID_U32(DOT11_OID_ANTENNADIVERSITY, 0x17000006), - OID_U32_C(DOT11_OID_CHANNEL, 0x17000007), - OID_U32_C(DOT11_OID_EDTHRESHOLD, 0x17000008), - OID_U32(DOT11_OID_PREAMBLESETTINGS, 0x17000009), - OID_STRUCT(DOT11_OID_RATES, 0x1700000A, u8[IWMAX_BITRATES + 1], - OID_TYPE_RAW), - OID_U32(DOT11_OID_CCAMODESUPPORTED, 0x1700000B), - OID_U32(DOT11_OID_CCAMODE, 0x1700000C), - OID_UNKNOWN(DOT11_OID_RSSIVECTOR, 0x1700000D), - OID_UNKNOWN(DOT11_OID_OUTPUTPOWERTABLE, 0x1700000E), - OID_U32(DOT11_OID_OUTPUTPOWER, 0x1700000F), - OID_STRUCT(DOT11_OID_SUPPORTEDRATES, 0x17000010, - u8[IWMAX_BITRATES + 1], OID_TYPE_RAW), - OID_U32_C(DOT11_OID_FREQUENCY, 0x17000011), - [DOT11_OID_SUPPORTEDFREQUENCIES] = - {0x17000012, 0, sizeof (struct obj_frequencies) - + sizeof (u16) * IWMAX_FREQ, OID_TYPE_FREQUENCIES}, - - OID_U32(DOT11_OID_NOISEFLOOR, 0x17000013), - OID_STRUCT(DOT11_OID_FREQUENCYACTIVITY, 0x17000014, u8[IWMAX_FREQ + 1], - OID_TYPE_RAW), - OID_UNKNOWN(DOT11_OID_IQCALIBRATIONTABLE, 0x17000015), - OID_U32(DOT11_OID_NONERPPROTECTION, 0x17000016), - OID_U32(DOT11_OID_SLOTSETTINGS, 0x17000017), - OID_U32(DOT11_OID_NONERPTIMEOUT, 0x17000018), - OID_U32(DOT11_OID_PROFILES, 0x17000019), - OID_STRUCT(DOT11_OID_EXTENDEDRATES, 0x17000020, - u8[IWMAX_BITRATES + 1], OID_TYPE_RAW), - - OID_STRUCT_MLME(DOT11_OID_DEAUTHENTICATE, 0x18000000), - OID_STRUCT_MLME(DOT11_OID_AUTHENTICATE, 0x18000001), - OID_STRUCT_MLME(DOT11_OID_DISASSOCIATE, 0x18000002), - OID_STRUCT_MLME(DOT11_OID_ASSOCIATE, 0x18000003), - OID_UNKNOWN(DOT11_OID_SCAN, 0x18000004), - OID_STRUCT_MLMEEX(DOT11_OID_BEACON, 0x18000005), - OID_STRUCT_MLMEEX(DOT11_OID_PROBE, 0x18000006), - OID_STRUCT_MLMEEX(DOT11_OID_DEAUTHENTICATEEX, 0x18000007), - OID_STRUCT_MLMEEX(DOT11_OID_AUTHENTICATEEX, 0x18000008), - OID_STRUCT_MLMEEX(DOT11_OID_DISASSOCIATEEX, 0x18000009), - OID_STRUCT_MLMEEX(DOT11_OID_ASSOCIATEEX, 0x1800000A), - OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATE, 0x1800000B), - OID_STRUCT_MLMEEX(DOT11_OID_REASSOCIATEEX, 0x1800000C), - - OID_U32(DOT11_OID_NONERPSTATUS, 0x1E000000), - - OID_U32(DOT11_OID_STATIMEOUT, 0x19000000), - OID_U32_C(DOT11_OID_MLMEAUTOLEVEL, 0x19000001), - OID_U32(DOT11_OID_BSSTIMEOUT, 0x19000002), - [DOT11_OID_ATTACHMENT] = {0x19000003, 0, - sizeof(struct obj_attachment), OID_TYPE_ATTACH}, - OID_STRUCT_C(DOT11_OID_PSMBUFFER, 0x19000004, struct obj_buffer, - OID_TYPE_BUFFER), - - OID_U32(DOT11_OID_BSSS, 0x1C000000), - [DOT11_OID_BSSX] = {0x1C000001, 63, sizeof (struct obj_bss), - OID_TYPE_BSS}, /*DOT11_OID_BSS1,...,DOT11_OID_BSS64 */ - OID_STRUCT(DOT11_OID_BSSFIND, 0x1C000042, struct obj_bss, OID_TYPE_BSS), - [DOT11_OID_BSSLIST] = {0x1C000043, 0, sizeof (struct - obj_bsslist) + - sizeof (struct obj_bss[IWMAX_BSS]), - OID_TYPE_BSSLIST}, - - OID_UNKNOWN(OID_INL_TUNNEL, 0xFF020000), - OID_UNKNOWN(OID_INL_MEMADDR, 0xFF020001), - OID_UNKNOWN(OID_INL_MEMORY, 0xFF020002), - OID_U32_C(OID_INL_MODE, 0xFF020003), - OID_UNKNOWN(OID_INL_COMPONENT_NR, 0xFF020004), - OID_STRUCT(OID_INL_VERSION, 0xFF020005, u8[8], OID_TYPE_RAW), - OID_UNKNOWN(OID_INL_INTERFACE_ID, 0xFF020006), - OID_UNKNOWN(OID_INL_COMPONENT_ID, 0xFF020007), - OID_U32_C(OID_INL_CONFIG, 0xFF020008), - OID_U32_C(OID_INL_DOT11D_CONFORMANCE, 0xFF02000C), - OID_U32(OID_INL_PHYCAPABILITIES, 0xFF02000D), - OID_U32_C(OID_INL_OUTPUTPOWER, 0xFF02000F), - -}; - -int -mgt_init(islpci_private *priv) -{ - int i; - - priv->mib = kcalloc(OID_NUM_LAST, sizeof (void *), GFP_KERNEL); - if (!priv->mib) - return -ENOMEM; - - /* Alloc the cache */ - for (i = 0; i < OID_NUM_LAST; i++) { - if (isl_oid[i].flags & OID_FLAG_CACHED) { - priv->mib[i] = kzalloc(isl_oid[i].size * - (isl_oid[i].range + 1), - GFP_KERNEL); - if (!priv->mib[i]) - return -ENOMEM; - } else - priv->mib[i] = NULL; - } - - init_rwsem(&priv->mib_sem); - prism54_mib_init(priv); - - return 0; -} - -void -mgt_clean(islpci_private *priv) -{ - int i; - - if (!priv->mib) - return; - for (i = 0; i < OID_NUM_LAST; i++) { - kfree(priv->mib[i]); - priv->mib[i] = NULL; - } - kfree(priv->mib); - priv->mib = NULL; -} - -void -mgt_le_to_cpu(int type, void *data) -{ - switch (type) { - case OID_TYPE_U32: - *(u32 *) data = le32_to_cpu(*(u32 *) data); - break; - case OID_TYPE_BUFFER:{ - struct obj_buffer *buff = data; - buff->size = le32_to_cpu(buff->size); - buff->addr = le32_to_cpu(buff->addr); - break; - } - case OID_TYPE_BSS:{ - struct obj_bss *bss = data; - bss->age = le16_to_cpu(bss->age); - bss->channel = le16_to_cpu(bss->channel); - bss->capinfo = le16_to_cpu(bss->capinfo); - bss->rates = le16_to_cpu(bss->rates); - bss->basic_rates = le16_to_cpu(bss->basic_rates); - break; - } - case OID_TYPE_BSSLIST:{ - struct obj_bsslist *list = data; - int i; - list->nr = le32_to_cpu(list->nr); - for (i = 0; i < list->nr; i++) - mgt_le_to_cpu(OID_TYPE_BSS, &list->bsslist[i]); - break; - } - case OID_TYPE_FREQUENCIES:{ - struct obj_frequencies *freq = data; - int i; - freq->nr = le16_to_cpu(freq->nr); - for (i = 0; i < freq->nr; i++) - freq->mhz[i] = le16_to_cpu(freq->mhz[i]); - break; - } - case OID_TYPE_MLME:{ - struct obj_mlme *mlme = data; - mlme->id = le16_to_cpu(mlme->id); - mlme->state = le16_to_cpu(mlme->state); - mlme->code = le16_to_cpu(mlme->code); - break; - } - case OID_TYPE_MLMEEX:{ - struct obj_mlmeex *mlme = data; - mlme->id = le16_to_cpu(mlme->id); - mlme->state = le16_to_cpu(mlme->state); - mlme->code = le16_to_cpu(mlme->code); - mlme->size = le16_to_cpu(mlme->size); - break; - } - case OID_TYPE_ATTACH:{ - struct obj_attachment *attach = data; - attach->id = le16_to_cpu(attach->id); - attach->size = le16_to_cpu(attach->size); - break; - } - case OID_TYPE_SSID: - case OID_TYPE_KEY: - case OID_TYPE_ADDR: - case OID_TYPE_RAW: - break; - default: - BUG(); - } -} - -static void -mgt_cpu_to_le(int type, void *data) -{ - switch (type) { - case OID_TYPE_U32: - *(u32 *) data = cpu_to_le32(*(u32 *) data); - break; - case OID_TYPE_BUFFER:{ - struct obj_buffer *buff = data; - buff->size = cpu_to_le32(buff->size); - buff->addr = cpu_to_le32(buff->addr); - break; - } - case OID_TYPE_BSS:{ - struct obj_bss *bss = data; - bss->age = cpu_to_le16(bss->age); - bss->channel = cpu_to_le16(bss->channel); - bss->capinfo = cpu_to_le16(bss->capinfo); - bss->rates = cpu_to_le16(bss->rates); - bss->basic_rates = cpu_to_le16(bss->basic_rates); - break; - } - case OID_TYPE_BSSLIST:{ - struct obj_bsslist *list = data; - int i; - list->nr = cpu_to_le32(list->nr); - for (i = 0; i < list->nr; i++) - mgt_cpu_to_le(OID_TYPE_BSS, &list->bsslist[i]); - break; - } - case OID_TYPE_FREQUENCIES:{ - struct obj_frequencies *freq = data; - int i; - freq->nr = cpu_to_le16(freq->nr); - for (i = 0; i < freq->nr; i++) - freq->mhz[i] = cpu_to_le16(freq->mhz[i]); - break; - } - case OID_TYPE_MLME:{ - struct obj_mlme *mlme = data; - mlme->id = cpu_to_le16(mlme->id); - mlme->state = cpu_to_le16(mlme->state); - mlme->code = cpu_to_le16(mlme->code); - break; - } - case OID_TYPE_MLMEEX:{ - struct obj_mlmeex *mlme = data; - mlme->id = cpu_to_le16(mlme->id); - mlme->state = cpu_to_le16(mlme->state); - mlme->code = cpu_to_le16(mlme->code); - mlme->size = cpu_to_le16(mlme->size); - break; - } - case OID_TYPE_ATTACH:{ - struct obj_attachment *attach = data; - attach->id = cpu_to_le16(attach->id); - attach->size = cpu_to_le16(attach->size); - break; - } - case OID_TYPE_SSID: - case OID_TYPE_KEY: - case OID_TYPE_ADDR: - case OID_TYPE_RAW: - break; - default: - BUG(); - } -} - -/* Note : data is modified during this function */ - -int -mgt_set_request(islpci_private *priv, enum oid_num_t n, int extra, void *data) -{ - int ret = 0; - struct islpci_mgmtframe *response = NULL; - int response_op = PIMFOR_OP_ERROR; - int dlen; - void *cache, *_data = data; - u32 oid; - - BUG_ON(OID_NUM_LAST <= n); - BUG_ON(extra > isl_oid[n].range); - - if (!priv->mib) - /* memory has been freed */ - return -1; - - dlen = isl_oid[n].size; - cache = priv->mib[n]; - cache += (cache ? extra * dlen : 0); - oid = isl_oid[n].oid + extra; - - if (_data == NULL) - /* we are requested to re-set a cached value */ - _data = cache; - else - mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, _data); - /* If we are going to write to the cache, we don't want anyone to read - * it -> acquire write lock. - * Else we could acquire a read lock to be sure we don't bother the - * commit process (which takes a write lock). But I'm not sure if it's - * needed. - */ - if (cache) - down_write(&priv->mib_sem); - - if (islpci_get_state(priv) >= PRV_STATE_READY) { - ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, - _data, dlen, &response); - if (!ret) { - response_op = response->header->operation; - islpci_mgt_release(response); - } - if (ret || response_op == PIMFOR_OP_ERROR) - ret = -EIO; - } else if (!cache) - ret = -EIO; - - if (cache) { - if (!ret && data) - memcpy(cache, _data, dlen); - up_write(&priv->mib_sem); - } - - /* re-set given data to what it was */ - if (data) - mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data); - - return ret; -} - -/* None of these are cached */ -int -mgt_set_varlen(islpci_private *priv, enum oid_num_t n, void *data, int extra_len) -{ - int ret = 0; - struct islpci_mgmtframe *response; - int response_op = PIMFOR_OP_ERROR; - int dlen; - u32 oid; - - BUG_ON(OID_NUM_LAST <= n); - - dlen = isl_oid[n].size; - oid = isl_oid[n].oid; - - mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, data); - - if (islpci_get_state(priv) >= PRV_STATE_READY) { - ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, oid, - data, dlen + extra_len, &response); - if (!ret) { - response_op = response->header->operation; - islpci_mgt_release(response); - } - if (ret || response_op == PIMFOR_OP_ERROR) - ret = -EIO; - } else - ret = -EIO; - - /* re-set given data to what it was */ - if (data) - mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, data); - - return ret; -} - -int -mgt_get_request(islpci_private *priv, enum oid_num_t n, int extra, void *data, - union oid_res_t *res) -{ - - int ret = -EIO; - int reslen = 0; - struct islpci_mgmtframe *response = NULL; - - int dlen; - void *cache, *_res = NULL; - u32 oid; - - BUG_ON(OID_NUM_LAST <= n); - BUG_ON(extra > isl_oid[n].range); - - res->ptr = NULL; - - if (!priv->mib) - /* memory has been freed */ - return -1; - - dlen = isl_oid[n].size; - cache = priv->mib[n]; - cache += cache ? extra * dlen : 0; - oid = isl_oid[n].oid + extra; - reslen = dlen; - - if (cache) - down_read(&priv->mib_sem); - - if (islpci_get_state(priv) >= PRV_STATE_READY) { - ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, - oid, data, dlen, &response); - if (ret || !response || - response->header->operation == PIMFOR_OP_ERROR) { - if (response) - islpci_mgt_release(response); - ret = -EIO; - } - if (!ret) { - _res = response->data; - reslen = response->header->length; - } - } else if (cache) { - _res = cache; - ret = 0; - } - if ((isl_oid[n].flags & OID_FLAG_TYPE) == OID_TYPE_U32) - res->u = ret ? 0 : le32_to_cpu(*(u32 *) _res); - else { - res->ptr = kmalloc(reslen, GFP_KERNEL); - BUG_ON(res->ptr == NULL); - if (ret) - memset(res->ptr, 0, reslen); - else { - memcpy(res->ptr, _res, reslen); - mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, - res->ptr); - } - } - if (cache) - up_read(&priv->mib_sem); - - if (response && !ret) - islpci_mgt_release(response); - - if (reslen > isl_oid[n].size) - printk(KERN_DEBUG - "mgt_get_request(0x%x): received data length was bigger " - "than expected (%d > %d). Memory is probably corrupted...", - oid, reslen, isl_oid[n].size); - - return ret; -} - -/* lock outside */ -int -mgt_commit_list(islpci_private *priv, enum oid_num_t *l, int n) -{ - int i, ret = 0; - struct islpci_mgmtframe *response; - - for (i = 0; i < n; i++) { - struct oid_t *t = &(isl_oid[l[i]]); - void *data = priv->mib[l[i]]; - int j = 0; - u32 oid = t->oid; - BUG_ON(data == NULL); - while (j <= t->range) { - int r = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_SET, - oid, data, t->size, - &response); - if (response) { - r |= (response->header->operation == PIMFOR_OP_ERROR); - islpci_mgt_release(response); - } - if (r) - printk(KERN_ERR "%s: mgt_commit_list: failure. " - "oid=%08x err=%d\n", - priv->ndev->name, oid, r); - ret |= r; - j++; - oid++; - data += t->size; - } - } - return ret; -} - -/* Lock outside */ - -void -mgt_set(islpci_private *priv, enum oid_num_t n, void *data) -{ - BUG_ON(OID_NUM_LAST <= n); - BUG_ON(priv->mib[n] == NULL); - - memcpy(priv->mib[n], data, isl_oid[n].size); - mgt_cpu_to_le(isl_oid[n].flags & OID_FLAG_TYPE, priv->mib[n]); -} - -void -mgt_get(islpci_private *priv, enum oid_num_t n, void *res) -{ - BUG_ON(OID_NUM_LAST <= n); - BUG_ON(priv->mib[n] == NULL); - BUG_ON(res == NULL); - - memcpy(res, priv->mib[n], isl_oid[n].size); - mgt_le_to_cpu(isl_oid[n].flags & OID_FLAG_TYPE, res); -} - -/* Commits the cache. Lock outside. */ - -static enum oid_num_t commit_part1[] = { - OID_INL_CONFIG, - OID_INL_MODE, - DOT11_OID_BSSTYPE, - DOT11_OID_CHANNEL, - DOT11_OID_MLMEAUTOLEVEL -}; - -static enum oid_num_t commit_part2[] = { - DOT11_OID_SSID, - DOT11_OID_PSMBUFFER, - DOT11_OID_AUTHENABLE, - DOT11_OID_PRIVACYINVOKED, - DOT11_OID_EXUNENCRYPTED, - DOT11_OID_DEFKEYX, /* MULTIPLE */ - DOT11_OID_DEFKEYID, - DOT11_OID_DOT1XENABLE, - OID_INL_DOT11D_CONFORMANCE, - /* Do not initialize this - fw < 1.0.4.3 rejects it - OID_INL_OUTPUTPOWER, - */ -}; - -/* update the MAC addr. */ -static int -mgt_update_addr(islpci_private *priv) -{ - struct islpci_mgmtframe *res; - int ret; - - ret = islpci_mgt_transaction(priv->ndev, PIMFOR_OP_GET, - isl_oid[GEN_OID_MACADDRESS].oid, NULL, - isl_oid[GEN_OID_MACADDRESS].size, &res); - - if ((ret == 0) && res && (res->header->operation != PIMFOR_OP_ERROR)) - memcpy(priv->ndev->dev_addr, res->data, 6); - else - ret = -EIO; - if (res) - islpci_mgt_release(res); - - if (ret) - printk(KERN_ERR "%s: mgt_update_addr: failure\n", priv->ndev->name); - return ret; -} - -#define VEC_SIZE(a) ARRAY_SIZE(a) - -int -mgt_commit(islpci_private *priv) -{ - int rvalue; - enum oid_num_t u; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return 0; - - rvalue = mgt_commit_list(priv, commit_part1, VEC_SIZE(commit_part1)); - - if (priv->iw_mode != IW_MODE_MONITOR) - rvalue |= mgt_commit_list(priv, commit_part2, VEC_SIZE(commit_part2)); - - u = OID_INL_MODE; - rvalue |= mgt_commit_list(priv, &u, 1); - rvalue |= mgt_update_addr(priv); - - if (rvalue) { - /* some request have failed. The device might be in an - incoherent state. We should reset it ! */ - printk(KERN_DEBUG "%s: mgt_commit: failure\n", priv->ndev->name); - } - return rvalue; -} - -/* The following OIDs need to be "unlatched": - * - * MEDIUMLIMIT,BEACONPERIOD,DTIMPERIOD,ATIMWINDOW,LISTENINTERVAL - * FREQUENCY,EXTENDEDRATES. - * - * The way to do this is to set ESSID. Note though that they may get - * unlatch before though by setting another OID. */ -#if 0 -void -mgt_unlatch_all(islpci_private *priv) -{ - u32 u; - int rvalue = 0; - - if (islpci_get_state(priv) < PRV_STATE_INIT) - return; - - u = DOT11_OID_SSID; - rvalue = mgt_commit_list(priv, &u, 1); - /* Necessary if in MANUAL RUN mode? */ -#if 0 - u = OID_INL_MODE; - rvalue |= mgt_commit_list(priv, &u, 1); - - u = DOT11_OID_MLMEAUTOLEVEL; - rvalue |= mgt_commit_list(priv, &u, 1); - - u = OID_INL_MODE; - rvalue |= mgt_commit_list(priv, &u, 1); -#endif - - if (rvalue) - printk(KERN_DEBUG "%s: Unlatching OIDs failed\n", priv->ndev->name); -} -#endif - -/* This will tell you if you are allowed to answer a mlme(ex) request .*/ - -int -mgt_mlme_answer(islpci_private *priv) -{ - u32 mlmeautolevel; - /* Acquire a read lock because if we are in a mode change, it's - * possible to answer true, while the card is leaving master to managed - * mode. Answering to a mlme in this situation could hang the card. - */ - down_read(&priv->mib_sem); - mlmeautolevel = - le32_to_cpu(*(u32 *) priv->mib[DOT11_OID_MLMEAUTOLEVEL]); - up_read(&priv->mib_sem); - - return ((priv->iw_mode == IW_MODE_MASTER) && - (mlmeautolevel >= DOT11_MLME_INTERMEDIATE)); -} - -enum oid_num_t -mgt_oidtonum(u32 oid) -{ - int i; - - for (i = 0; i < OID_NUM_LAST; i++) - if (isl_oid[i].oid == oid) - return i; - - printk(KERN_DEBUG "looking for an unknown oid 0x%x", oid); - - return OID_NUM_LAST; -} - -int -mgt_response_to_str(enum oid_num_t n, union oid_res_t *r, char *str) -{ - switch (isl_oid[n].flags & OID_FLAG_TYPE) { - case OID_TYPE_U32: - return snprintf(str, PRIV_STR_SIZE, "%u\n", r->u); - break; - case OID_TYPE_BUFFER:{ - struct obj_buffer *buff = r->ptr; - return snprintf(str, PRIV_STR_SIZE, - "size=%u\naddr=0x%X\n", buff->size, - buff->addr); - } - break; - case OID_TYPE_BSS:{ - struct obj_bss *bss = r->ptr; - return snprintf(str, PRIV_STR_SIZE, - "age=%u\nchannel=%u\n" - "capinfo=0x%X\nrates=0x%X\n" - "basic_rates=0x%X\n", bss->age, - bss->channel, bss->capinfo, - bss->rates, bss->basic_rates); - } - break; - case OID_TYPE_BSSLIST:{ - struct obj_bsslist *list = r->ptr; - int i, k; - k = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", list->nr); - for (i = 0; i < list->nr; i++) - k += snprintf(str + k, PRIV_STR_SIZE - k, - "bss[%u] : \nage=%u\nchannel=%u\n" - "capinfo=0x%X\nrates=0x%X\n" - "basic_rates=0x%X\n", - i, list->bsslist[i].age, - list->bsslist[i].channel, - list->bsslist[i].capinfo, - list->bsslist[i].rates, - list->bsslist[i].basic_rates); - return k; - } - break; - case OID_TYPE_FREQUENCIES:{ - struct obj_frequencies *freq = r->ptr; - int i, t; - printk("nr : %u\n", freq->nr); - t = snprintf(str, PRIV_STR_SIZE, "nr=%u\n", freq->nr); - for (i = 0; i < freq->nr; i++) - t += snprintf(str + t, PRIV_STR_SIZE - t, - "mhz[%u]=%u\n", i, freq->mhz[i]); - return t; - } - break; - case OID_TYPE_MLME:{ - struct obj_mlme *mlme = r->ptr; - return snprintf(str, PRIV_STR_SIZE, - "id=0x%X\nstate=0x%X\ncode=0x%X\n", - mlme->id, mlme->state, mlme->code); - } - break; - case OID_TYPE_MLMEEX:{ - struct obj_mlmeex *mlme = r->ptr; - return snprintf(str, PRIV_STR_SIZE, - "id=0x%X\nstate=0x%X\n" - "code=0x%X\nsize=0x%X\n", mlme->id, - mlme->state, mlme->code, mlme->size); - } - break; - case OID_TYPE_ATTACH:{ - struct obj_attachment *attach = r->ptr; - return snprintf(str, PRIV_STR_SIZE, - "id=%d\nsize=%d\n", - attach->id, - attach->size); - } - break; - case OID_TYPE_SSID:{ - struct obj_ssid *ssid = r->ptr; - return snprintf(str, PRIV_STR_SIZE, - "length=%u\noctets=%.*s\n", - ssid->length, ssid->length, - ssid->octets); - } - break; - case OID_TYPE_KEY:{ - struct obj_key *key = r->ptr; - int t, i; - t = snprintf(str, PRIV_STR_SIZE, - "type=0x%X\nlength=0x%X\nkey=0x", - key->type, key->length); - for (i = 0; i < key->length; i++) - t += snprintf(str + t, PRIV_STR_SIZE - t, - "%02X:", key->key[i]); - t += snprintf(str + t, PRIV_STR_SIZE - t, "\n"); - return t; - } - break; - case OID_TYPE_RAW: - case OID_TYPE_ADDR:{ - unsigned char *buff = r->ptr; - int t, i; - t = snprintf(str, PRIV_STR_SIZE, "hex data="); - for (i = 0; i < isl_oid[n].size; i++) - t += snprintf(str + t, PRIV_STR_SIZE - t, - "%02X:", buff[i]); - t += snprintf(str + t, PRIV_STR_SIZE - t, "\n"); - return t; - } - break; - default: - BUG(); - } - return 0; -} diff --git a/drivers/net/wireless/prism54/oid_mgt.h b/drivers/net/wireless/prism54/oid_mgt.h deleted file mode 100644 index 92c8a2d4acd8..000000000000 --- a/drivers/net/wireless/prism54/oid_mgt.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2003 Aurelien Alleaume - * - * 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 - * - * 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 - * - */ - -#if !defined(_OID_MGT_H) -#define _OID_MGT_H - -#include "isl_oid.h" -#include "islpci_dev.h" - -extern struct oid_t isl_oid[]; - -int mgt_init(islpci_private *); - -void mgt_clean(islpci_private *); - -/* I don't know where to put these 2 */ -extern const int frequency_list_a[]; -int channel_of_freq(int); - -void mgt_le_to_cpu(int, void *); - -int mgt_set_request(islpci_private *, enum oid_num_t, int, void *); -int mgt_set_varlen(islpci_private *, enum oid_num_t, void *, int); - - -int mgt_get_request(islpci_private *, enum oid_num_t, int, void *, - union oid_res_t *); - -int mgt_commit_list(islpci_private *, enum oid_num_t *, int); - -void mgt_set(islpci_private *, enum oid_num_t, void *); - -void mgt_get(islpci_private *, enum oid_num_t, void *); - -int mgt_commit(islpci_private *); - -int mgt_mlme_answer(islpci_private *); - -enum oid_num_t mgt_oidtonum(u32 oid); - -int mgt_response_to_str(enum oid_num_t, union oid_res_t *, char *); - -#endif /* !defined(_OID_MGT_H) */ -/* EOF */ diff --git a/drivers/net/wireless/prism54/prismcompat.h b/drivers/net/wireless/prism54/prismcompat.h deleted file mode 100644 index aa1d1747784f..000000000000 --- a/drivers/net/wireless/prism54/prismcompat.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * (C) 2004 Margit Schubert-While - * - * 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 - * - * 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 - * - */ - -/* - * Compatibility header file to aid support of different kernel versions - */ - -#ifdef PRISM54_COMPAT24 -#include "prismcompat24.h" -#else /* PRISM54_COMPAT24 */ - -#ifndef _PRISM_COMPAT_H -#define _PRISM_COMPAT_H - -#include -#include -#include -#include -#include - -#ifndef __iomem -#define __iomem -#endif - -#define PRISM_FW_PDEV &priv->pdev->dev - -#endif /* _PRISM_COMPAT_H */ -#endif /* PRISM54_COMPAT24 */ diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c deleted file mode 100644 index 1c88c2ea59aa..000000000000 --- a/drivers/net/wireless/ray_cs.c +++ /dev/null @@ -1,2983 +0,0 @@ -/*============================================================================= - * - * A PCMCIA client driver for the Raylink wireless LAN card. - * The starting point for this module was the skeleton.c in the - * PCMCIA 2.9.12 package written by David Hinds, dahinds@users.sourceforge.net - * - * - * Copyright (c) 1998 Corey Thomas (corey@world.std.com) - * - * This driver is free software; you can redistribute it and/or modify - * it under the terms of version 2 only of the GNU General Public License as - * published by the Free Software Foundation. - * - * It 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 - * - * Changes: - * Arnaldo Carvalho de Melo - 08/08/2000 - * - reorganize kmallocs in ray_attach, checking all for failure - * and releasing the previous allocations if one fails - * - * Daniele Bellucci - 07/10/2003 - * - Audit copy_to_user in ioctl(SIOCGIWESSID) - * -=============================================================================*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -/* Warning : these stuff will slow down the driver... */ -#define WIRELESS_SPY /* Enable spying addresses */ -/* Definitions we need for spy */ -typedef struct iw_statistics iw_stats; -typedef u_char mac_addr[ETH_ALEN]; /* Hardware address */ - -#include "rayctl.h" -#include "ray_cs.h" - -/* All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If - you do not define PCMCIA_DEBUG at all, all the debug code will be - left out. If you compile with PCMCIA_DEBUG=0, the debug code will - be present but disabled -- but it can then be enabled for specific - modules at load time with a 'pc_debug=#' option to insmod. -*/ - -#ifdef RAYLINK_DEBUG -#define PCMCIA_DEBUG RAYLINK_DEBUG -#endif -#ifdef PCMCIA_DEBUG -static int ray_debug; -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -/* #define DEBUG(n, args...) if (pc_debug>(n)) printk(KERN_DEBUG args); */ -#define DEBUG(n, args...) if (pc_debug > (n)) printk(args); -#else -#define DEBUG(n, args...) -#endif -/** Prototypes based on PCMCIA skeleton driver *******************************/ -static int ray_config(struct pcmcia_device *link); -static void ray_release(struct pcmcia_device *link); -static void ray_detach(struct pcmcia_device *p_dev); - -/***** Prototypes indicated by device structure ******************************/ -static int ray_dev_close(struct net_device *dev); -static int ray_dev_config(struct net_device *dev, struct ifmap *map); -static struct net_device_stats *ray_get_stats(struct net_device *dev); -static int ray_dev_init(struct net_device *dev); - -static const struct ethtool_ops netdev_ethtool_ops; - -static int ray_open(struct net_device *dev); -static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb, - struct net_device *dev); -static void set_multicast_list(struct net_device *dev); -static void ray_update_multi_list(struct net_device *dev, int all); -static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, - unsigned char *data, int len); -static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, - UCHAR msg_type, unsigned char *data); -static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len); -static iw_stats *ray_get_wireless_stats(struct net_device *dev); -static const struct iw_handler_def ray_handler_def; - -/***** Prototypes for raylink functions **************************************/ -static int asc_to_int(char a); -static void authenticate(ray_dev_t *local); -static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type); -static void authenticate_timeout(u_long); -static int get_free_ccs(ray_dev_t *local); -static int get_free_tx_ccs(ray_dev_t *local); -static void init_startup_params(ray_dev_t *local); -static int parse_addr(char *in_str, UCHAR *out); -static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, UCHAR type); -static int ray_init(struct net_device *dev); -static int interrupt_ecf(ray_dev_t *local, int ccs); -static void ray_reset(struct net_device *dev); -static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, int len); -static void verify_dl_startup(u_long); - -/* Prototypes for interrpt time functions **********************************/ -static irqreturn_t ray_interrupt(int reg, void *dev_id); -static void clear_interrupt(ray_dev_t *local); -static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len); -static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, int len); -static void ray_rx(struct net_device *dev, ray_dev_t *local, struct rcs __iomem *prcs); -static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs); -static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len); -static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len); -static void associate(ray_dev_t *local); - -/* Card command functions */ -static int dl_startup_params(struct net_device *dev); -static void join_net(u_long local); -static void start_net(u_long local); -/* void start_net(ray_dev_t *local); */ - -/*===========================================================================*/ -/* Parameters that can be set with 'insmod' */ - -/* ADHOC=0, Infrastructure=1 */ -static int net_type = ADHOC; - -/* Hop dwell time in Kus (1024 us units defined by 802.11) */ -static int hop_dwell = 128; - -/* Beacon period in Kus */ -static int beacon_period = 256; - -/* power save mode (0 = off, 1 = save power) */ -static int psm; - -/* String for network's Extended Service Set ID. 32 Characters max */ -static char *essid; - -/* Default to encapsulation unless translation requested */ -static int translate = 1; - -static int country = USA; - -static int sniffer; - -static int bc; - -/* 48 bit physical card address if overriding card's real physical - * address is required. Since IEEE 802.11 addresses are 48 bits - * like ethernet, an int can't be used, so a string is used. To - * allow use of addresses starting with a decimal digit, the first - * character must be a letter and will be ignored. This letter is - * followed by up to 12 hex digits which are the address. If less - * than 12 digits are used, the address will be left filled with 0's. - * Note that bit 0 of the first byte is the broadcast bit, and evil - * things will happen if it is not 0 in a card address. - */ -static char *phy_addr = NULL; - - -/* A struct pcmcia_device structure has fields for most things that are needed - to keep track of a socket, but there will usually be some device - specific information that also needs to be kept track of. The - 'priv' pointer in a struct pcmcia_device structure can be used to point to - a device-specific private data structure, like this. -*/ -static unsigned int ray_mem_speed = 500; - -/* WARNING: THIS DRIVER IS NOT CAPABLE OF HANDLING MULTIPLE DEVICES! */ -static struct pcmcia_device *this_device = NULL; - -MODULE_AUTHOR("Corey Thomas "); -MODULE_DESCRIPTION("Raylink/WebGear wireless LAN driver"); -MODULE_LICENSE("GPL"); - -module_param(net_type, int, 0); -module_param(hop_dwell, int, 0); -module_param(beacon_period, int, 0); -module_param(psm, int, 0); -module_param(essid, charp, 0); -module_param(translate, int, 0); -module_param(country, int, 0); -module_param(sniffer, int, 0); -module_param(bc, int, 0); -module_param(phy_addr, charp, 0); -module_param(ray_mem_speed, int, 0); - -static UCHAR b5_default_startup_parms[] = { - 0, 0, /* Adhoc station */ - 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, /* Active scan, CA Mode */ - 0, 0, 0, 0, 0, 0, /* No default MAC addr */ - 0x7f, 0xff, /* Frag threshold */ - 0x00, 0x80, /* Hop time 128 Kus */ - 0x01, 0x00, /* Beacon period 256 Kus */ - 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout */ - 0x1d, 0x82, 0x4e, /* SIFS, DIFS, PIFS */ - 0x7f, 0xff, /* RTS threshold */ - 0x04, 0xe2, 0x38, 0xA4, /* scan_dwell, max_scan_dwell */ - 0x05, /* assoc resp timeout thresh */ - 0x08, 0x02, 0x08, /* adhoc, infra, super cycle max */ - 0, /* Promiscuous mode */ - 0x0c, 0x0bd, /* Unique word */ - 0x32, /* Slot time */ - 0xff, 0xff, /* roam-low snr, low snr count */ - 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ - 0x01, 0x0b, 0x4f, /* USA, hop pattern, hop pat length */ -/* b4 - b5 differences start here */ - 0x00, 0x3f, /* CW max */ - 0x00, 0x0f, /* CW min */ - 0x04, 0x08, /* Noise gain, limit offset */ - 0x28, 0x28, /* det rssi, med busy offsets */ - 7, /* det sync thresh */ - 0, 2, 2, /* test mode, min, max */ - 0, /* allow broadcast SSID probe resp */ - 0, 0, /* privacy must start, can join */ - 2, 0, 0, 0, 0, 0, 0, 0 /* basic rate set */ -}; - -static UCHAR b4_default_startup_parms[] = { - 0, 0, /* Adhoc station */ - 'L', 'I', 'N', 'U', 'X', 0, 0, 0, /* 32 char ESSID */ - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 1, 0, /* Active scan, CA Mode */ - 0, 0, 0, 0, 0, 0, /* No default MAC addr */ - 0x7f, 0xff, /* Frag threshold */ - 0x02, 0x00, /* Hop time */ - 0x00, 0x01, /* Beacon period */ - 0x01, 0x07, 0xa3, /* DTIM, retries, ack timeout */ - 0x1d, 0x82, 0xce, /* SIFS, DIFS, PIFS */ - 0x7f, 0xff, /* RTS threshold */ - 0xfb, 0x1e, 0xc7, 0x5c, /* scan_dwell, max_scan_dwell */ - 0x05, /* assoc resp timeout thresh */ - 0x04, 0x02, 0x4, /* adhoc, infra, super cycle max */ - 0, /* Promiscuous mode */ - 0x0c, 0x0bd, /* Unique word */ - 0x4e, /* Slot time (TBD seems wrong) */ - 0xff, 0xff, /* roam-low snr, low snr count */ - 0x05, 0xff, /* Infra, adhoc missed bcn thresh */ - 0x01, 0x0b, 0x4e, /* USA, hop pattern, hop pat length */ -/* b4 - b5 differences start here */ - 0x3f, 0x0f, /* CW max, min */ - 0x04, 0x08, /* Noise gain, limit offset */ - 0x28, 0x28, /* det rssi, med busy offsets */ - 7, /* det sync thresh */ - 0, 2, 2 /* test mode, min, max */ -}; - -/*===========================================================================*/ -static unsigned char eth2_llc[] = { 0xaa, 0xaa, 3, 0, 0, 0 }; - -static char hop_pattern_length[] = { 1, - USA_HOP_MOD, EUROPE_HOP_MOD, - JAPAN_HOP_MOD, KOREA_HOP_MOD, - SPAIN_HOP_MOD, FRANCE_HOP_MOD, - ISRAEL_HOP_MOD, AUSTRALIA_HOP_MOD, - JAPAN_TEST_HOP_MOD -}; - -static char rcsid[] = - "Raylink/WebGear wireless LAN - Corey "; - -static const struct net_device_ops ray_netdev_ops = { - .ndo_init = ray_dev_init, - .ndo_open = ray_open, - .ndo_stop = ray_dev_close, - .ndo_start_xmit = ray_dev_start_xmit, - .ndo_set_config = ray_dev_config, - .ndo_get_stats = ray_get_stats, - .ndo_set_multicast_list = set_multicast_list, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/*============================================================================= - ray_attach() creates an "instance" of the driver, allocating - local data structures for one device. The device is registered - with Card Services. - The dev_link structure is initialized, but we don't actually - configure the card at this point -- we wait until we receive a - card insertion event. -=============================================================================*/ -static int ray_probe(struct pcmcia_device *p_dev) -{ - ray_dev_t *local; - struct net_device *dev; - - DEBUG(1, "ray_attach()\n"); - - /* Allocate space for private device-specific data */ - dev = alloc_etherdev(sizeof(ray_dev_t)); - if (!dev) - goto fail_alloc_dev; - - local = netdev_priv(dev); - local->finder = p_dev; - - /* The io structure describes IO port mapping. None used here */ - p_dev->io.NumPorts1 = 0; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 5; - - /* Interrupt setup. For PCMCIA, driver takes what's given */ - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - p_dev->irq.Handler = &ray_interrupt; - - /* General socket configuration */ - p_dev->conf.Attributes = CONF_ENABLE_IRQ; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - p_dev->conf.ConfigIndex = 1; - - p_dev->priv = dev; - p_dev->irq.Instance = dev; - - local->finder = p_dev; - local->card_status = CARD_INSERTED; - local->authentication_state = UNAUTHENTICATED; - local->num_multi = 0; - DEBUG(2, "ray_attach p_dev = %p, dev = %p, local = %p, intr = %p\n", - p_dev, dev, local, &ray_interrupt); - - /* Raylink entries in the device structure */ - dev->netdev_ops = &ray_netdev_ops; - SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); - dev->wireless_handlers = &ray_handler_def; -#ifdef WIRELESS_SPY - local->wireless_data.spy_data = &local->spy_data; - dev->wireless_data = &local->wireless_data; -#endif /* WIRELESS_SPY */ - - - DEBUG(2, "ray_cs ray_attach calling ether_setup.)\n"); - netif_stop_queue(dev); - - init_timer(&local->timer); - - this_device = p_dev; - return ray_config(p_dev); - -fail_alloc_dev: - return -ENOMEM; -} /* ray_attach */ - -/*============================================================================= - This deletes a driver "instance". The device is de-registered - with Card Services. If it has been released, all local data - structures are freed. Otherwise, the structures will be freed - when the device is released. -=============================================================================*/ -static void ray_detach(struct pcmcia_device *link) -{ - struct net_device *dev; - ray_dev_t *local; - - DEBUG(1, "ray_detach(0x%p)\n", link); - - this_device = NULL; - dev = link->priv; - - ray_release(link); - - local = netdev_priv(dev); - del_timer(&local->timer); - - if (link->priv) { - if (link->dev_node) - unregister_netdev(dev); - free_netdev(dev); - } - DEBUG(2, "ray_cs ray_detach ending\n"); -} /* ray_detach */ - -/*============================================================================= - ray_config() is run after a CARD_INSERTION event - is received, to configure the PCMCIA socket, and to make the - ethernet device available to the system. -=============================================================================*/ -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) -#define MAX_TUPLE_SIZE 128 -static int ray_config(struct pcmcia_device *link) -{ - int last_fn = 0, last_ret = 0; - int i; - win_req_t req; - memreq_t mem; - struct net_device *dev = (struct net_device *)link->priv; - ray_dev_t *local = netdev_priv(dev); - - DEBUG(1, "ray_config(0x%p)\n", link); - - /* Determine card type and firmware version */ - printk(KERN_INFO "ray_cs Detected: %s%s%s%s\n", - link->prod_id[0] ? link->prod_id[0] : " ", - link->prod_id[1] ? link->prod_id[1] : " ", - link->prod_id[2] ? link->prod_id[2] : " ", - link->prod_id[3] ? link->prod_id[3] : " "); - - /* Now allocate an interrupt line. Note that this does not - actually assign a handler to the interrupt. - */ - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - dev->irq = link->irq.AssignedIRQ; - - /* This actually configures the PCMCIA socket -- setting up - the I/O windows and the interrupt mapping. - */ - CS_CHECK(RequestConfiguration, - pcmcia_request_configuration(link, &link->conf)); - -/*** Set up 32k window for shared memory (transmit and control) ************/ - req.Attributes = - WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; - req.Base = 0; - req.Size = 0x8000; - req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, pcmcia_request_window(&link, &req, &link->win)); - mem.CardOffset = 0x0000; - mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(link->win, &mem)); - local->sram = ioremap(req.Base, req.Size); - -/*** Set up 16k window for shared memory (receive buffer) ***************/ - req.Attributes = - WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_CM | WIN_ENABLE | WIN_USE_WAIT; - req.Base = 0; - req.Size = 0x4000; - req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, - pcmcia_request_window(&link, &req, &local->rmem_handle)); - mem.CardOffset = 0x8000; - mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->rmem_handle, &mem)); - local->rmem = ioremap(req.Base, req.Size); - -/*** Set up window for attribute memory ***********************************/ - req.Attributes = - WIN_DATA_WIDTH_8 | WIN_MEMORY_TYPE_AM | WIN_ENABLE | WIN_USE_WAIT; - req.Base = 0; - req.Size = 0x1000; - req.AccessSpeed = ray_mem_speed; - CS_CHECK(RequestWindow, - pcmcia_request_window(&link, &req, &local->amem_handle)); - mem.CardOffset = 0x0000; - mem.Page = 0; - CS_CHECK(MapMemPage, pcmcia_map_mem_page(local->amem_handle, &mem)); - local->amem = ioremap(req.Base, req.Size); - - DEBUG(3, "ray_config sram=%p\n", local->sram); - DEBUG(3, "ray_config rmem=%p\n", local->rmem); - DEBUG(3, "ray_config amem=%p\n", local->amem); - if (ray_init(dev) < 0) { - ray_release(link); - return -ENODEV; - } - - SET_NETDEV_DEV(dev, &handle_to_dev(link)); - i = register_netdev(dev); - if (i != 0) { - printk("ray_config register_netdev() failed\n"); - ray_release(link); - return i; - } - - strcpy(local->node.dev_name, dev->name); - link->dev_node = &local->node; - - printk(KERN_INFO "%s: RayLink, irq %d, hw_addr %pM\n", - dev->name, dev->irq, dev->dev_addr); - - return 0; - -cs_failed: - cs_error(link, last_fn, last_ret); - - ray_release(link); - return -ENODEV; -} /* ray_config */ - -static inline struct ccs __iomem *ccs_base(ray_dev_t *dev) -{ - return dev->sram + CCS_BASE; -} - -static inline struct rcs __iomem *rcs_base(ray_dev_t *dev) -{ - /* - * This looks nonsensical, since there is a separate - * RCS_BASE. But the difference between a "struct rcs" - * and a "struct ccs" ends up being in the _index_ off - * the base, so the base pointer is the same for both - * ccs/rcs. - */ - return dev->sram + CCS_BASE; -} - -/*===========================================================================*/ -static int ray_init(struct net_device *dev) -{ - int i; - UCHAR *p; - struct ccs __iomem *pccs; - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - DEBUG(1, "ray_init(0x%p)\n", dev); - if (!(pcmcia_dev_present(link))) { - DEBUG(0, "ray_init - device not present\n"); - return -1; - } - - local->net_type = net_type; - local->sta_type = TYPE_STA; - - /* Copy the startup results to local memory */ - memcpy_fromio(&local->startup_res, local->sram + ECF_TO_HOST_BASE, - sizeof(struct startup_res_6)); - - /* Check Power up test status and get mac address from card */ - if (local->startup_res.startup_word != 0x80) { - printk(KERN_INFO "ray_init ERROR card status = %2x\n", - local->startup_res.startup_word); - local->card_status = CARD_INIT_ERROR; - return -1; - } - - local->fw_ver = local->startup_res.firmware_version[0]; - local->fw_bld = local->startup_res.firmware_version[1]; - local->fw_var = local->startup_res.firmware_version[2]; - DEBUG(1, "ray_init firmware version %d.%d \n", local->fw_ver, - local->fw_bld); - - local->tib_length = 0x20; - if ((local->fw_ver == 5) && (local->fw_bld >= 30)) - local->tib_length = local->startup_res.tib_length; - DEBUG(2, "ray_init tib_length = 0x%02x\n", local->tib_length); - /* Initialize CCS's to buffer free state */ - pccs = ccs_base(local); - for (i = 0; i < NUMBER_OF_CCS; i++) { - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - } - init_startup_params(local); - - /* copy mac address to startup parameters */ - if (parse_addr(phy_addr, local->sparm.b4.a_mac_addr)) { - p = local->sparm.b4.a_mac_addr; - } else { - memcpy(&local->sparm.b4.a_mac_addr, - &local->startup_res.station_addr, ADDRLEN); - p = local->sparm.b4.a_mac_addr; - } - - clear_interrupt(local); /* Clear any interrupt from the card */ - local->card_status = CARD_AWAITING_PARAM; - DEBUG(2, "ray_init ending\n"); - return 0; -} /* ray_init */ - -/*===========================================================================*/ -/* Download startup parameters to the card and command it to read them */ -static int dl_startup_params(struct net_device *dev) -{ - int ccsindex; - ray_dev_t *local = netdev_priv(dev); - struct ccs __iomem *pccs; - struct pcmcia_device *link = local->finder; - - DEBUG(1, "dl_startup_params entered\n"); - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs dl_startup_params - device not present\n"); - return -1; - } - - /* Copy parameters to host to ECF area */ - if (local->fw_ver == 0x55) - memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b4, - sizeof(struct b4_startup_params)); - else - memcpy_toio(local->sram + HOST_TO_ECF_BASE, &local->sparm.b5, - sizeof(struct b5_startup_params)); - - /* Fill in the CCS fields for the ECF */ - if ((ccsindex = get_free_ccs(local)) < 0) - return -1; - local->dl_param_ccs = ccsindex; - pccs = ccs_base(local) + ccsindex; - writeb(CCS_DOWNLOAD_STARTUP_PARAMS, &pccs->cmd); - DEBUG(2, "dl_startup_params start ccsindex = %d\n", - local->dl_param_ccs); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - printk(KERN_INFO "ray dl_startup_params failed - " - "ECF not ready for intr\n"); - local->card_status = CARD_DL_PARAM_ERROR; - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return -2; - } - local->card_status = CARD_DL_PARAM; - /* Start kernel timer to wait for dl startup to complete. */ - local->timer.expires = jiffies + HZ / 2; - local->timer.data = (long)local; - local->timer.function = &verify_dl_startup; - add_timer(&local->timer); - DEBUG(2, - "ray_cs dl_startup_params started timer for verify_dl_startup\n"); - return 0; -} /* dl_startup_params */ - -/*===========================================================================*/ -static void init_startup_params(ray_dev_t *local) -{ - int i; - - if (country > JAPAN_TEST) - country = USA; - else if (country < USA) - country = USA; - /* structure for hop time and beacon period is defined here using - * New 802.11D6.1 format. Card firmware is still using old format - * until version 6. - * Before After - * a_hop_time ms byte a_hop_time ms byte - * a_hop_time 2s byte a_hop_time ls byte - * a_hop_time ls byte a_beacon_period ms byte - * a_beacon_period a_beacon_period ls byte - * - * a_hop_time = uS a_hop_time = KuS - * a_beacon_period = hops a_beacon_period = KuS - *//* 64ms = 010000 */ - if (local->fw_ver == 0x55) { - memcpy((UCHAR *) &local->sparm.b4, b4_default_startup_parms, - sizeof(struct b4_startup_params)); - /* Translate sane kus input values to old build 4/5 format */ - /* i = hop time in uS truncated to 3 bytes */ - i = (hop_dwell * 1024) & 0xffffff; - local->sparm.b4.a_hop_time[0] = (i >> 16) & 0xff; - local->sparm.b4.a_hop_time[1] = (i >> 8) & 0xff; - local->sparm.b4.a_beacon_period[0] = 0; - local->sparm.b4.a_beacon_period[1] = - ((beacon_period / hop_dwell) - 1) & 0xff; - local->sparm.b4.a_curr_country_code = country; - local->sparm.b4.a_hop_pattern_length = - hop_pattern_length[(int)country] - 1; - if (bc) { - local->sparm.b4.a_ack_timeout = 0x50; - local->sparm.b4.a_sifs = 0x3f; - } - } else { /* Version 5 uses real kus values */ - memcpy((UCHAR *) &local->sparm.b5, b5_default_startup_parms, - sizeof(struct b5_startup_params)); - - local->sparm.b5.a_hop_time[0] = (hop_dwell >> 8) & 0xff; - local->sparm.b5.a_hop_time[1] = hop_dwell & 0xff; - local->sparm.b5.a_beacon_period[0] = - (beacon_period >> 8) & 0xff; - local->sparm.b5.a_beacon_period[1] = beacon_period & 0xff; - if (psm) - local->sparm.b5.a_power_mgt_state = 1; - local->sparm.b5.a_curr_country_code = country; - local->sparm.b5.a_hop_pattern_length = - hop_pattern_length[(int)country]; - } - - local->sparm.b4.a_network_type = net_type & 0x01; - local->sparm.b4.a_acting_as_ap_status = TYPE_STA; - - if (essid != NULL) - strncpy(local->sparm.b4.a_current_ess_id, essid, ESSID_SIZE); -} /* init_startup_params */ - -/*===========================================================================*/ -static void verify_dl_startup(u_long data) -{ - ray_dev_t *local = (ray_dev_t *) data; - struct ccs __iomem *pccs = ccs_base(local) + local->dl_param_ccs; - UCHAR status; - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs verify_dl_startup - device not present\n"); - return; - } -#ifdef PCMCIA_DEBUG - if (pc_debug > 2) { - int i; - printk(KERN_DEBUG - "verify_dl_startup parameters sent via ccs %d:\n", - local->dl_param_ccs); - for (i = 0; i < sizeof(struct b5_startup_params); i++) { - printk(" %2x", - (unsigned int)readb(local->sram + - HOST_TO_ECF_BASE + i)); - } - printk("\n"); - } -#endif - - status = readb(&pccs->buffer_status); - if (status != CCS_BUFFER_FREE) { - printk(KERN_INFO - "Download startup params failed. Status = %d\n", - status); - local->card_status = CARD_DL_PARAM_ERROR; - return; - } - if (local->sparm.b4.a_network_type == ADHOC) - start_net((u_long) local); - else - join_net((u_long) local); - - return; -} /* end verify_dl_startup */ - -/*===========================================================================*/ -/* Command card to start a network */ -static void start_net(u_long data) -{ - ray_dev_t *local = (ray_dev_t *) data; - struct ccs __iomem *pccs; - int ccsindex; - struct pcmcia_device *link = local->finder; - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs start_net - device not present\n"); - return; - } - /* Fill in the CCS fields for the ECF */ - if ((ccsindex = get_free_ccs(local)) < 0) - return; - pccs = ccs_base(local) + ccsindex; - writeb(CCS_START_NETWORK, &pccs->cmd); - writeb(0, &pccs->var.start_network.update_param); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1, "ray start net failed - card not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return; - } - local->card_status = CARD_DOING_ACQ; - return; -} /* end start_net */ - -/*===========================================================================*/ -/* Command card to join a network */ -static void join_net(u_long data) -{ - ray_dev_t *local = (ray_dev_t *) data; - - struct ccs __iomem *pccs; - int ccsindex; - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs join_net - device not present\n"); - return; - } - /* Fill in the CCS fields for the ECF */ - if ((ccsindex = get_free_ccs(local)) < 0) - return; - pccs = ccs_base(local) + ccsindex; - writeb(CCS_JOIN_NETWORK, &pccs->cmd); - writeb(0, &pccs->var.join_network.update_param); - writeb(0, &pccs->var.join_network.net_initiated); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1, "ray join net failed - card not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return; - } - local->card_status = CARD_DOING_ACQ; - return; -} - -/*============================================================================ - After a card is removed, ray_release() will unregister the net - device, and release the PCMCIA configuration. If the device is - still open, this will be postponed until it is closed. -=============================================================================*/ -static void ray_release(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - ray_dev_t *local = netdev_priv(dev); - int i; - - DEBUG(1, "ray_release(0x%p)\n", link); - - del_timer(&local->timer); - - iounmap(local->sram); - iounmap(local->rmem); - iounmap(local->amem); - /* Do bother checking to see if these succeed or not */ - i = pcmcia_release_window(local->amem_handle); - if (i != 0) - DEBUG(0, "ReleaseWindow(local->amem) ret = %x\n", i); - i = pcmcia_release_window(local->rmem_handle); - if (i != 0) - DEBUG(0, "ReleaseWindow(local->rmem) ret = %x\n", i); - pcmcia_disable_device(link); - - DEBUG(2, "ray_release ending\n"); -} - -static int ray_suspend(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - if (link->open) - netif_device_detach(dev); - - return 0; -} - -static int ray_resume(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - if (link->open) { - ray_reset(dev); - netif_device_attach(dev); - } - - return 0; -} - -/*===========================================================================*/ -static int ray_dev_init(struct net_device *dev) -{ -#ifdef RAY_IMMEDIATE_INIT - int i; -#endif /* RAY_IMMEDIATE_INIT */ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - - DEBUG(1, "ray_dev_init(dev=%p)\n", dev); - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_dev_init - device not present\n"); - return -1; - } -#ifdef RAY_IMMEDIATE_INIT - /* Download startup parameters */ - if ((i = dl_startup_params(dev)) < 0) { - printk(KERN_INFO "ray_dev_init dl_startup_params failed - " - "returns 0x%x\n", i); - return -1; - } -#else /* RAY_IMMEDIATE_INIT */ - /* Postpone the card init so that we can still configure the card, - * for example using the Wireless Extensions. The init will happen - * in ray_open() - Jean II */ - DEBUG(1, - "ray_dev_init: postponing card init to ray_open() ; Status = %d\n", - local->card_status); -#endif /* RAY_IMMEDIATE_INIT */ - - /* copy mac and broadcast addresses to linux device */ - memcpy(dev->dev_addr, &local->sparm.b4.a_mac_addr, ADDRLEN); - memset(dev->broadcast, 0xff, ETH_ALEN); - - DEBUG(2, "ray_dev_init ending\n"); - return 0; -} - -/*===========================================================================*/ -static int ray_dev_config(struct net_device *dev, struct ifmap *map) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - /* Dummy routine to satisfy device structure */ - DEBUG(1, "ray_dev_config(dev=%p,ifmap=%p)\n", dev, map); - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_dev_config - device not present\n"); - return -1; - } - - return 0; -} - -/*===========================================================================*/ -static netdev_tx_t ray_dev_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - short length = skb->len; - - if (!pcmcia_dev_present(link)) { - DEBUG(2, "ray_dev_start_xmit - device not present\n"); - dev_kfree_skb(skb); - return NETDEV_TX_OK; - } - - DEBUG(3, "ray_dev_start_xmit(skb=%p, dev=%p)\n", skb, dev); - if (local->authentication_state == NEED_TO_AUTH) { - DEBUG(0, "ray_cs Sending authentication request.\n"); - if (!build_auth_frame(local, local->auth_id, OPEN_AUTH_REQUEST)) { - local->authentication_state = AUTHENTICATED; - netif_stop_queue(dev); - return NETDEV_TX_BUSY; - } - } - - if (length < ETH_ZLEN) { - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - length = ETH_ZLEN; - } - switch (ray_hw_xmit(skb->data, length, dev, DATA_TYPE)) { - case XMIT_NO_CCS: - case XMIT_NEED_AUTH: - netif_stop_queue(dev); - return NETDEV_TX_BUSY; - case XMIT_NO_INTR: - case XMIT_MSG_BAD: - case XMIT_OK: - default: - dev->trans_start = jiffies; - dev_kfree_skb(skb); - } - - return NETDEV_TX_OK; -} /* ray_dev_start_xmit */ - -/*===========================================================================*/ -static int ray_hw_xmit(unsigned char *data, int len, struct net_device *dev, - UCHAR msg_type) -{ - ray_dev_t *local = netdev_priv(dev); - struct ccs __iomem *pccs; - int ccsindex; - int offset; - struct tx_msg __iomem *ptx; /* Address of xmit buffer in PC space */ - short int addr; /* Address of xmit buffer in card space */ - - DEBUG(3, "ray_hw_xmit(data=%p, len=%d, dev=%p)\n", data, len, dev); - if (len + TX_HEADER_LENGTH > TX_BUF_SIZE) { - printk(KERN_INFO "ray_hw_xmit packet too large: %d bytes\n", - len); - return XMIT_MSG_BAD; - } - switch (ccsindex = get_free_tx_ccs(local)) { - case ECCSBUSY: - DEBUG(2, "ray_hw_xmit tx_ccs table busy\n"); - case ECCSFULL: - DEBUG(2, "ray_hw_xmit No free tx ccs\n"); - case ECARDGONE: - netif_stop_queue(dev); - return XMIT_NO_CCS; - default: - break; - } - addr = TX_BUF_BASE + (ccsindex << 11); - - if (msg_type == DATA_TYPE) { - local->stats.tx_bytes += len; - local->stats.tx_packets++; - } - - ptx = local->sram + addr; - - ray_build_header(local, ptx, msg_type, data); - if (translate) { - offset = translate_frame(local, ptx, data, len); - } else { /* Encapsulate frame */ - /* TBD TIB length will move address of ptx->var */ - memcpy_toio(&ptx->var, data, len); - offset = 0; - } - - /* fill in the CCS */ - pccs = ccs_base(local) + ccsindex; - len += TX_HEADER_LENGTH + offset; - writeb(CCS_TX_REQUEST, &pccs->cmd); - writeb(addr >> 8, &pccs->var.tx_request.tx_data_ptr[0]); - writeb(local->tib_length, &pccs->var.tx_request.tx_data_ptr[1]); - writeb(len >> 8, &pccs->var.tx_request.tx_data_length[0]); - writeb(len & 0xff, &pccs->var.tx_request.tx_data_length[1]); -/* TBD still need psm_cam? */ - writeb(PSM_CAM, &pccs->var.tx_request.pow_sav_mode); - writeb(local->net_default_tx_rate, &pccs->var.tx_request.tx_rate); - writeb(0, &pccs->var.tx_request.antenna); - DEBUG(3, "ray_hw_xmit default_tx_rate = 0x%x\n", - local->net_default_tx_rate); - - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(2, "ray_hw_xmit failed - ECF not ready for intr\n"); -/* TBD very inefficient to copy packet to buffer, and then not - send it, but the alternative is to queue the messages and that - won't be done for a while. Maybe set tbusy until a CCS is free? -*/ - writeb(CCS_BUFFER_FREE, &pccs->buffer_status); - return XMIT_NO_INTR; - } - return XMIT_OK; -} /* end ray_hw_xmit */ - -/*===========================================================================*/ -static int translate_frame(ray_dev_t *local, struct tx_msg __iomem *ptx, - unsigned char *data, int len) -{ - __be16 proto = ((struct ethhdr *)data)->h_proto; - if (ntohs(proto) >= 1536) { /* DIX II ethernet frame */ - DEBUG(3, "ray_cs translate_frame DIX II\n"); - /* Copy LLC header to card buffer */ - memcpy_toio(&ptx->var, eth2_llc, sizeof(eth2_llc)); - memcpy_toio(((void __iomem *)&ptx->var) + sizeof(eth2_llc), - (UCHAR *) &proto, 2); - if (proto == htons(ETH_P_AARP) || proto == htons(ETH_P_IPX)) { - /* This is the selective translation table, only 2 entries */ - writeb(0xf8, - &((struct snaphdr_t __iomem *)ptx->var)->org[3]); - } - /* Copy body of ethernet packet without ethernet header */ - memcpy_toio((void __iomem *)&ptx->var + - sizeof(struct snaphdr_t), data + ETH_HLEN, - len - ETH_HLEN); - return (int)sizeof(struct snaphdr_t) - ETH_HLEN; - } else { /* already 802 type, and proto is length */ - DEBUG(3, "ray_cs translate_frame 802\n"); - if (proto == htons(0xffff)) { /* evil netware IPX 802.3 without LLC */ - DEBUG(3, "ray_cs translate_frame evil IPX\n"); - memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); - return 0 - ETH_HLEN; - } - memcpy_toio(&ptx->var, data + ETH_HLEN, len - ETH_HLEN); - return 0 - ETH_HLEN; - } - /* TBD do other frame types */ -} /* end translate_frame */ - -/*===========================================================================*/ -static void ray_build_header(ray_dev_t *local, struct tx_msg __iomem *ptx, - UCHAR msg_type, unsigned char *data) -{ - writeb(PROTOCOL_VER | msg_type, &ptx->mac.frame_ctl_1); -/*** IEEE 802.11 Address field assignments ************* - TODS FROMDS addr_1 addr_2 addr_3 addr_4 -Adhoc 0 0 dest src (terminal) BSSID N/A -AP to Terminal 0 1 dest AP(BSSID) source N/A -Terminal to AP 1 0 AP(BSSID) src (terminal) dest N/A -AP to AP 1 1 dest AP src AP dest source -*******************************************************/ - if (local->net_type == ADHOC) { - writeb(0, &ptx->mac.frame_ctl_2); - memcpy_toio(ptx->mac.addr_1, ((struct ethhdr *)data)->h_dest, - 2 * ADDRLEN); - memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); - } else { /* infrastructure */ - - if (local->sparm.b4.a_acting_as_ap_status) { - writeb(FC2_FROM_DS, &ptx->mac.frame_ctl_2); - memcpy_toio(ptx->mac.addr_1, - ((struct ethhdr *)data)->h_dest, ADDRLEN); - memcpy_toio(ptx->mac.addr_2, local->bss_id, 6); - memcpy_toio(ptx->mac.addr_3, - ((struct ethhdr *)data)->h_source, ADDRLEN); - } else { /* Terminal */ - - writeb(FC2_TO_DS, &ptx->mac.frame_ctl_2); - memcpy_toio(ptx->mac.addr_1, local->bss_id, ADDRLEN); - memcpy_toio(ptx->mac.addr_2, - ((struct ethhdr *)data)->h_source, ADDRLEN); - memcpy_toio(ptx->mac.addr_3, - ((struct ethhdr *)data)->h_dest, ADDRLEN); - } - } -} /* end encapsulate_frame */ - -/*===========================================================================*/ - -static void netdev_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - strcpy(info->driver, "ray_cs"); -} - -static const struct ethtool_ops netdev_ethtool_ops = { - .get_drvinfo = netdev_get_drvinfo, -}; - -/*====================================================================*/ - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get protocol name - */ -static int ray_get_name(struct net_device *dev, - struct iw_request_info *info, char *cwrq, char *extra) -{ - strcpy(cwrq, "IEEE 802.11-FH"); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set frequency - */ -static int ray_set_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - - /* Reject if card is already initialised */ - if (local->card_status != CARD_AWAITING_PARAM) - return -EBUSY; - - /* Setting by channel number */ - if ((fwrq->m > USA_HOP_MOD) || (fwrq->e > 0)) - err = -EOPNOTSUPP; - else - local->sparm.b5.a_hop_pattern = fwrq->m; - - return err; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get frequency - */ -static int ray_get_freq(struct net_device *dev, - struct iw_request_info *info, - struct iw_freq *fwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - fwrq->m = local->sparm.b5.a_hop_pattern; - fwrq->e = 0; - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set ESSID - */ -static int ray_set_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - /* Reject if card is already initialised */ - if (local->card_status != CARD_AWAITING_PARAM) - return -EBUSY; - - /* Check if we asked for `any' */ - if (dwrq->flags == 0) { - /* Corey : can you do that ? */ - return -EOPNOTSUPP; - } else { - /* Check the size of the string */ - if (dwrq->length > IW_ESSID_MAX_SIZE) { - return -E2BIG; - } - - /* Set the ESSID in the card */ - memset(local->sparm.b5.a_current_ess_id, 0, IW_ESSID_MAX_SIZE); - memcpy(local->sparm.b5.a_current_ess_id, extra, dwrq->length); - } - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get ESSID - */ -static int ray_get_essid(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - /* Get the essid that was set */ - memcpy(extra, local->sparm.b5.a_current_ess_id, IW_ESSID_MAX_SIZE); - - /* Push it out ! */ - dwrq->length = strlen(extra); - dwrq->flags = 1; /* active */ - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get AP address - */ -static int ray_get_wap(struct net_device *dev, - struct iw_request_info *info, - struct sockaddr *awrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - memcpy(awrq->sa_data, local->bss_id, ETH_ALEN); - awrq->sa_family = ARPHRD_ETHER; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Bit-Rate - */ -static int ray_set_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - /* Reject if card is already initialised */ - if (local->card_status != CARD_AWAITING_PARAM) - return -EBUSY; - - /* Check if rate is in range */ - if ((vwrq->value != 1000000) && (vwrq->value != 2000000)) - return -EINVAL; - - /* Hack for 1.5 Mb/s instead of 2 Mb/s */ - if ((local->fw_ver == 0x55) && /* Please check */ - (vwrq->value == 2000000)) - local->net_default_tx_rate = 3; - else - local->net_default_tx_rate = vwrq->value / 500000; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Bit-Rate - */ -static int ray_get_rate(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - if (local->net_default_tx_rate == 3) - vwrq->value = 2000000; /* Hum... */ - else - vwrq->value = local->net_default_tx_rate * 500000; - vwrq->fixed = 0; /* We are in auto mode */ - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set RTS threshold - */ -static int ray_set_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - int rthr = vwrq->value; - - /* Reject if card is already initialised */ - if (local->card_status != CARD_AWAITING_PARAM) - return -EBUSY; - - /* if(wrq->u.rts.fixed == 0) we should complain */ - if (vwrq->disabled) - rthr = 32767; - else { - if ((rthr < 0) || (rthr > 2347)) /* What's the max packet size ??? */ - return -EINVAL; - } - local->sparm.b5.a_rts_threshold[0] = (rthr >> 8) & 0xFF; - local->sparm.b5.a_rts_threshold[1] = rthr & 0xFF; - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get RTS threshold - */ -static int ray_get_rts(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - vwrq->value = (local->sparm.b5.a_rts_threshold[0] << 8) - + local->sparm.b5.a_rts_threshold[1]; - vwrq->disabled = (vwrq->value == 32767); - vwrq->fixed = 1; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Fragmentation threshold - */ -static int ray_set_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - int fthr = vwrq->value; - - /* Reject if card is already initialised */ - if (local->card_status != CARD_AWAITING_PARAM) - return -EBUSY; - - /* if(wrq->u.frag.fixed == 0) should complain */ - if (vwrq->disabled) - fthr = 32767; - else { - if ((fthr < 256) || (fthr > 2347)) /* To check out ! */ - return -EINVAL; - } - local->sparm.b5.a_frag_threshold[0] = (fthr >> 8) & 0xFF; - local->sparm.b5.a_frag_threshold[1] = fthr & 0xFF; - - return -EINPROGRESS; /* Call commit handler */ -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Fragmentation threshold - */ -static int ray_get_frag(struct net_device *dev, - struct iw_request_info *info, - struct iw_param *vwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - vwrq->value = (local->sparm.b5.a_frag_threshold[0] << 8) - + local->sparm.b5.a_frag_threshold[1]; - vwrq->disabled = (vwrq->value == 32767); - vwrq->fixed = 1; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set Mode of Operation - */ -static int ray_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *uwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - int err = -EINPROGRESS; /* Call commit handler */ - char card_mode = 1; - - /* Reject if card is already initialised */ - if (local->card_status != CARD_AWAITING_PARAM) - return -EBUSY; - - switch (*uwrq) { - case IW_MODE_ADHOC: - card_mode = 0; - /* Fall through */ - case IW_MODE_INFRA: - local->sparm.b5.a_network_type = card_mode; - break; - default: - err = -EINVAL; - } - - return err; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get Mode of Operation - */ -static int ray_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *uwrq, char *extra) -{ - ray_dev_t *local = netdev_priv(dev); - - if (local->sparm.b5.a_network_type) - *uwrq = IW_MODE_INFRA; - else - *uwrq = IW_MODE_ADHOC; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get range info - */ -static int ray_get_range(struct net_device *dev, - struct iw_request_info *info, - struct iw_point *dwrq, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - - memset((char *)range, 0, sizeof(struct iw_range)); - - /* Set the length (very important for backward compatibility) */ - dwrq->length = sizeof(struct iw_range); - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 9; - - /* Set information in the range struct */ - range->throughput = 1.1 * 1000 * 1000; /* Put the right number here */ - range->num_channels = hop_pattern_length[(int)country]; - range->num_frequency = 0; - range->max_qual.qual = 0; - range->max_qual.level = 255; /* What's the correct value ? */ - range->max_qual.noise = 255; /* Idem */ - range->num_bitrates = 2; - range->bitrate[0] = 1000000; /* 1 Mb/s */ - range->bitrate[1] = 2000000; /* 2 Mb/s */ - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : set framing mode - */ -static int ray_set_framing(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - translate = *(extra); /* Set framing mode */ - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get framing mode - */ -static int ray_get_framing(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - *(extra) = translate; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get country - */ -static int ray_get_country(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - *(extra) = country; - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Commit handler : called after a bunch of SET operations - */ -static int ray_commit(struct net_device *dev, struct iw_request_info *info, /* NULL */ - void *zwrq, /* NULL */ - char *extra) -{ /* NULL */ - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Stats handler : return Wireless Stats - */ -static iw_stats *ray_get_wireless_stats(struct net_device *dev) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - struct status __iomem *p = local->sram + STATUS_BASE; - - local->wstats.status = local->card_status; -#ifdef WIRELESS_SPY - if ((local->spy_data.spy_number > 0) - && (local->sparm.b5.a_network_type == 0)) { - /* Get it from the first node in spy list */ - local->wstats.qual.qual = local->spy_data.spy_stat[0].qual; - local->wstats.qual.level = local->spy_data.spy_stat[0].level; - local->wstats.qual.noise = local->spy_data.spy_stat[0].noise; - local->wstats.qual.updated = - local->spy_data.spy_stat[0].updated; - } -#endif /* WIRELESS_SPY */ - - if (pcmcia_dev_present(link)) { - local->wstats.qual.noise = readb(&p->rxnoise); - local->wstats.qual.updated |= 4; - } - - return &local->wstats; -} /* end ray_get_wireless_stats */ - -/*------------------------------------------------------------------*/ -/* - * Structures to export the Wireless Handlers - */ - -static const iw_handler ray_handler[] = { - [SIOCSIWCOMMIT - SIOCIWFIRST] = (iw_handler) ray_commit, - [SIOCGIWNAME - SIOCIWFIRST] = (iw_handler) ray_get_name, - [SIOCSIWFREQ - SIOCIWFIRST] = (iw_handler) ray_set_freq, - [SIOCGIWFREQ - SIOCIWFIRST] = (iw_handler) ray_get_freq, - [SIOCSIWMODE - SIOCIWFIRST] = (iw_handler) ray_set_mode, - [SIOCGIWMODE - SIOCIWFIRST] = (iw_handler) ray_get_mode, - [SIOCGIWRANGE - SIOCIWFIRST] = (iw_handler) ray_get_range, -#ifdef WIRELESS_SPY - [SIOCSIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_spy, - [SIOCGIWSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_spy, - [SIOCSIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_set_thrspy, - [SIOCGIWTHRSPY - SIOCIWFIRST] = (iw_handler) iw_handler_get_thrspy, -#endif /* WIRELESS_SPY */ - [SIOCGIWAP - SIOCIWFIRST] = (iw_handler) ray_get_wap, - [SIOCSIWESSID - SIOCIWFIRST] = (iw_handler) ray_set_essid, - [SIOCGIWESSID - SIOCIWFIRST] = (iw_handler) ray_get_essid, - [SIOCSIWRATE - SIOCIWFIRST] = (iw_handler) ray_set_rate, - [SIOCGIWRATE - SIOCIWFIRST] = (iw_handler) ray_get_rate, - [SIOCSIWRTS - SIOCIWFIRST] = (iw_handler) ray_set_rts, - [SIOCGIWRTS - SIOCIWFIRST] = (iw_handler) ray_get_rts, - [SIOCSIWFRAG - SIOCIWFIRST] = (iw_handler) ray_set_frag, - [SIOCGIWFRAG - SIOCIWFIRST] = (iw_handler) ray_get_frag, -}; - -#define SIOCSIPFRAMING SIOCIWFIRSTPRIV /* Set framing mode */ -#define SIOCGIPFRAMING SIOCIWFIRSTPRIV + 1 /* Get framing mode */ -#define SIOCGIPCOUNTRY SIOCIWFIRSTPRIV + 3 /* Get country code */ - -static const iw_handler ray_private_handler[] = { - [0] = (iw_handler) ray_set_framing, - [1] = (iw_handler) ray_get_framing, - [3] = (iw_handler) ray_get_country, -}; - -static const struct iw_priv_args ray_private_args[] = { -/* cmd, set_args, get_args, name */ - {SIOCSIPFRAMING, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, - "set_framing"}, - {SIOCGIPFRAMING, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, - "get_framing"}, - {SIOCGIPCOUNTRY, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, - "get_country"}, -}; - -static const struct iw_handler_def ray_handler_def = { - .num_standard = ARRAY_SIZE(ray_handler), - .num_private = ARRAY_SIZE(ray_private_handler), - .num_private_args = ARRAY_SIZE(ray_private_args), - .standard = ray_handler, - .private = ray_private_handler, - .private_args = ray_private_args, - .get_wireless_stats = ray_get_wireless_stats, -}; - -/*===========================================================================*/ -static int ray_open(struct net_device *dev) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link; - link = local->finder; - - DEBUG(1, "ray_open('%s')\n", dev->name); - - if (link->open == 0) - local->num_multi = 0; - link->open++; - - /* If the card is not started, time to start it ! - Jean II */ - if (local->card_status == CARD_AWAITING_PARAM) { - int i; - - DEBUG(1, "ray_open: doing init now !\n"); - - /* Download startup parameters */ - if ((i = dl_startup_params(dev)) < 0) { - printk(KERN_INFO - "ray_dev_init dl_startup_params failed - " - "returns 0x%x\n", i); - return -1; - } - } - - if (sniffer) - netif_stop_queue(dev); - else - netif_start_queue(dev); - - DEBUG(2, "ray_open ending\n"); - return 0; -} /* end ray_open */ - -/*===========================================================================*/ -static int ray_dev_close(struct net_device *dev) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link; - link = local->finder; - - DEBUG(1, "ray_dev_close('%s')\n", dev->name); - - link->open--; - netif_stop_queue(dev); - - /* In here, we should stop the hardware (stop card from beeing active) - * and set local->card_status to CARD_AWAITING_PARAM, so that while the - * card is closed we can chage its configuration. - * Probably also need a COR reset to get sane state - Jean II */ - - return 0; -} /* end ray_dev_close */ - -/*===========================================================================*/ -static void ray_reset(struct net_device *dev) -{ - DEBUG(1, "ray_reset entered\n"); - return; -} - -/*===========================================================================*/ -/* Cause a firmware interrupt if it is ready for one */ -/* Return nonzero if not ready */ -static int interrupt_ecf(ray_dev_t *local, int ccs) -{ - int i = 50; - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs interrupt_ecf - device not present\n"); - return -1; - } - DEBUG(2, "interrupt_ecf(local=%p, ccs = 0x%x\n", local, ccs); - - while (i && - (readb(local->amem + CIS_OFFSET + ECF_INTR_OFFSET) & - ECF_INTR_SET)) - i--; - if (i == 0) { - DEBUG(2, "ray_cs interrupt_ecf card not ready for interrupt\n"); - return -1; - } - /* Fill the mailbox, then kick the card */ - writeb(ccs, local->sram + SCB_BASE); - writeb(ECF_INTR_SET, local->amem + CIS_OFFSET + ECF_INTR_OFFSET); - return 0; -} /* interrupt_ecf */ - -/*===========================================================================*/ -/* Get next free transmit CCS */ -/* Return - index of current tx ccs */ -static int get_free_tx_ccs(ray_dev_t *local) -{ - int i; - struct ccs __iomem *pccs = ccs_base(local); - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs get_free_tx_ccs - device not present\n"); - return ECARDGONE; - } - - if (test_and_set_bit(0, &local->tx_ccs_lock)) { - DEBUG(1, "ray_cs tx_ccs_lock busy\n"); - return ECCSBUSY; - } - - for (i = 0; i < NUMBER_OF_TX_CCS; i++) { - if (readb(&(pccs + i)->buffer_status) == CCS_BUFFER_FREE) { - writeb(CCS_BUFFER_BUSY, &(pccs + i)->buffer_status); - writeb(CCS_END_LIST, &(pccs + i)->link); - local->tx_ccs_lock = 0; - return i; - } - } - local->tx_ccs_lock = 0; - DEBUG(2, "ray_cs ERROR no free tx CCS for raylink card\n"); - return ECCSFULL; -} /* get_free_tx_ccs */ - -/*===========================================================================*/ -/* Get next free CCS */ -/* Return - index of current ccs */ -static int get_free_ccs(ray_dev_t *local) -{ - int i; - struct ccs __iomem *pccs = ccs_base(local); - struct pcmcia_device *link = local->finder; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs get_free_ccs - device not present\n"); - return ECARDGONE; - } - if (test_and_set_bit(0, &local->ccs_lock)) { - DEBUG(1, "ray_cs ccs_lock busy\n"); - return ECCSBUSY; - } - - for (i = NUMBER_OF_TX_CCS; i < NUMBER_OF_CCS; i++) { - if (readb(&(pccs + i)->buffer_status) == CCS_BUFFER_FREE) { - writeb(CCS_BUFFER_BUSY, &(pccs + i)->buffer_status); - writeb(CCS_END_LIST, &(pccs + i)->link); - local->ccs_lock = 0; - return i; - } - } - local->ccs_lock = 0; - DEBUG(1, "ray_cs ERROR no free CCS for raylink card\n"); - return ECCSFULL; -} /* get_free_ccs */ - -/*===========================================================================*/ -static void authenticate_timeout(u_long data) -{ - ray_dev_t *local = (ray_dev_t *) data; - del_timer(&local->timer); - printk(KERN_INFO "ray_cs Authentication with access point failed" - " - timeout\n"); - join_net((u_long) local); -} - -/*===========================================================================*/ -static int asc_to_int(char a) -{ - if (a < '0') - return -1; - if (a <= '9') - return (a - '0'); - if (a < 'A') - return -1; - if (a <= 'F') - return (10 + a - 'A'); - if (a < 'a') - return -1; - if (a <= 'f') - return (10 + a - 'a'); - return -1; -} - -/*===========================================================================*/ -static int parse_addr(char *in_str, UCHAR *out) -{ - int len; - int i, j, k; - int status; - - if (in_str == NULL) - return 0; - if ((len = strlen(in_str)) < 2) - return 0; - memset(out, 0, ADDRLEN); - - status = 1; - j = len - 1; - if (j > 12) - j = 12; - i = 5; - - while (j > 0) { - if ((k = asc_to_int(in_str[j--])) != -1) - out[i] = k; - else - return 0; - - if (j == 0) - break; - if ((k = asc_to_int(in_str[j--])) != -1) - out[i] += k << 4; - else - return 0; - if (!i--) - break; - } - return status; -} - -/*===========================================================================*/ -static struct net_device_stats *ray_get_stats(struct net_device *dev) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - struct status __iomem *p = local->sram + STATUS_BASE; - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs net_device_stats - device not present\n"); - return &local->stats; - } - if (readb(&p->mrx_overflow_for_host)) { - local->stats.rx_over_errors += swab16(readw(&p->mrx_overflow)); - writeb(0, &p->mrx_overflow); - writeb(0, &p->mrx_overflow_for_host); - } - if (readb(&p->mrx_checksum_error_for_host)) { - local->stats.rx_crc_errors += - swab16(readw(&p->mrx_checksum_error)); - writeb(0, &p->mrx_checksum_error); - writeb(0, &p->mrx_checksum_error_for_host); - } - if (readb(&p->rx_hec_error_for_host)) { - local->stats.rx_frame_errors += swab16(readw(&p->rx_hec_error)); - writeb(0, &p->rx_hec_error); - writeb(0, &p->rx_hec_error_for_host); - } - return &local->stats; -} - -/*===========================================================================*/ -static void ray_update_parm(struct net_device *dev, UCHAR objid, UCHAR *value, - int len) -{ - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - int ccsindex; - int i; - struct ccs __iomem *pccs; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_update_parm - device not present\n"); - return; - } - - if ((ccsindex = get_free_ccs(local)) < 0) { - DEBUG(0, "ray_update_parm - No free ccs\n"); - return; - } - pccs = ccs_base(local) + ccsindex; - writeb(CCS_UPDATE_PARAMS, &pccs->cmd); - writeb(objid, &pccs->var.update_param.object_id); - writeb(1, &pccs->var.update_param.number_objects); - writeb(0, &pccs->var.update_param.failure_cause); - for (i = 0; i < len; i++) { - writeb(value[i], local->sram + HOST_TO_ECF_BASE); - } - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(0, "ray_cs associate failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - } -} - -/*===========================================================================*/ -static void ray_update_multi_list(struct net_device *dev, int all) -{ - struct dev_mc_list *dmi, **dmip; - int ccsindex; - struct ccs __iomem *pccs; - int i = 0; - ray_dev_t *local = netdev_priv(dev); - struct pcmcia_device *link = local->finder; - void __iomem *p = local->sram + HOST_TO_ECF_BASE; - - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_update_multi_list - device not present\n"); - return; - } else - DEBUG(2, "ray_update_multi_list(%p)\n", dev); - if ((ccsindex = get_free_ccs(local)) < 0) { - DEBUG(1, "ray_update_multi - No free ccs\n"); - return; - } - pccs = ccs_base(local) + ccsindex; - writeb(CCS_UPDATE_MULTICAST_LIST, &pccs->cmd); - - if (all) { - writeb(0xff, &pccs->var); - local->num_multi = 0xff; - } else { - /* Copy the kernel's list of MC addresses to card */ - for (dmip = &dev->mc_list; (dmi = *dmip) != NULL; - dmip = &dmi->next) { - memcpy_toio(p, dmi->dmi_addr, ETH_ALEN); - DEBUG(1, - "ray_update_multi add addr %02x%02x%02x%02x%02x%02x\n", - dmi->dmi_addr[0], dmi->dmi_addr[1], - dmi->dmi_addr[2], dmi->dmi_addr[3], - dmi->dmi_addr[4], dmi->dmi_addr[5]); - p += ETH_ALEN; - i++; - } - if (i > 256 / ADDRLEN) - i = 256 / ADDRLEN; - writeb((UCHAR) i, &pccs->var); - DEBUG(1, "ray_cs update_multi %d addresses in list\n", i); - /* Interrupt the firmware to process the command */ - local->num_multi = i; - } - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1, - "ray_cs update_multi failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - } -} /* end ray_update_multi_list */ - -/*===========================================================================*/ -static void set_multicast_list(struct net_device *dev) -{ - ray_dev_t *local = netdev_priv(dev); - UCHAR promisc; - - DEBUG(2, "ray_cs set_multicast_list(%p)\n", dev); - - if (dev->flags & IFF_PROMISC) { - if (local->sparm.b5.a_promiscuous_mode == 0) { - DEBUG(1, "ray_cs set_multicast_list promisc on\n"); - local->sparm.b5.a_promiscuous_mode = 1; - promisc = 1; - ray_update_parm(dev, OBJID_promiscuous_mode, - &promisc, sizeof(promisc)); - } - } else { - if (local->sparm.b5.a_promiscuous_mode == 1) { - DEBUG(1, "ray_cs set_multicast_list promisc off\n"); - local->sparm.b5.a_promiscuous_mode = 0; - promisc = 0; - ray_update_parm(dev, OBJID_promiscuous_mode, - &promisc, sizeof(promisc)); - } - } - - if (dev->flags & IFF_ALLMULTI) - ray_update_multi_list(dev, 1); - else { - if (local->num_multi != dev->mc_count) - ray_update_multi_list(dev, 0); - } -} /* end set_multicast_list */ - -/*============================================================================= - * All routines below here are run at interrupt time. -=============================================================================*/ -static irqreturn_t ray_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = (struct net_device *)dev_id; - struct pcmcia_device *link; - ray_dev_t *local; - struct ccs __iomem *pccs; - struct rcs __iomem *prcs; - UCHAR rcsindex; - UCHAR tmp; - UCHAR cmd; - UCHAR status; - - if (dev == NULL) /* Note that we want interrupts with dev->start == 0 */ - return IRQ_NONE; - - DEBUG(4, "ray_cs: interrupt for *dev=%p\n", dev); - - local = netdev_priv(dev); - link = (struct pcmcia_device *)local->finder; - if (!pcmcia_dev_present(link)) { - DEBUG(2, - "ray_cs interrupt from device not present or suspended.\n"); - return IRQ_NONE; - } - rcsindex = readb(&((struct scb __iomem *)(local->sram))->rcs_index); - - if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { - DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", rcsindex); - clear_interrupt(local); - return IRQ_HANDLED; - } - if (rcsindex < NUMBER_OF_CCS) { /* If it's a returned CCS */ - pccs = ccs_base(local) + rcsindex; - cmd = readb(&pccs->cmd); - status = readb(&pccs->buffer_status); - switch (cmd) { - case CCS_DOWNLOAD_STARTUP_PARAMS: /* Happens in firmware someday */ - del_timer(&local->timer); - if (status == CCS_COMMAND_COMPLETE) { - DEBUG(1, - "ray_cs interrupt download_startup_parameters OK\n"); - } else { - DEBUG(1, - "ray_cs interrupt download_startup_parameters fail\n"); - } - break; - case CCS_UPDATE_PARAMS: - DEBUG(1, "ray_cs interrupt update params done\n"); - if (status != CCS_COMMAND_COMPLETE) { - tmp = - readb(&pccs->var.update_param. - failure_cause); - DEBUG(0, - "ray_cs interrupt update params failed - reason %d\n", - tmp); - } - break; - case CCS_REPORT_PARAMS: - DEBUG(1, "ray_cs interrupt report params done\n"); - break; - case CCS_UPDATE_MULTICAST_LIST: /* Note that this CCS isn't returned */ - DEBUG(1, - "ray_cs interrupt CCS Update Multicast List done\n"); - break; - case CCS_UPDATE_POWER_SAVINGS_MODE: - DEBUG(1, - "ray_cs interrupt update power save mode done\n"); - break; - case CCS_START_NETWORK: - case CCS_JOIN_NETWORK: - if (status == CCS_COMMAND_COMPLETE) { - if (readb - (&pccs->var.start_network.net_initiated) == - 1) { - DEBUG(0, - "ray_cs interrupt network \"%s\" started\n", - local->sparm.b4.a_current_ess_id); - } else { - DEBUG(0, - "ray_cs interrupt network \"%s\" joined\n", - local->sparm.b4.a_current_ess_id); - } - memcpy_fromio(&local->bss_id, - pccs->var.start_network.bssid, - ADDRLEN); - - if (local->fw_ver == 0x55) - local->net_default_tx_rate = 3; - else - local->net_default_tx_rate = - readb(&pccs->var.start_network. - net_default_tx_rate); - local->encryption = - readb(&pccs->var.start_network.encryption); - if (!sniffer && (local->net_type == INFRA) - && !(local->sparm.b4.a_acting_as_ap_status)) { - authenticate(local); - } - local->card_status = CARD_ACQ_COMPLETE; - } else { - local->card_status = CARD_ACQ_FAILED; - - del_timer(&local->timer); - local->timer.expires = jiffies + HZ * 5; - local->timer.data = (long)local; - if (status == CCS_START_NETWORK) { - DEBUG(0, - "ray_cs interrupt network \"%s\" start failed\n", - local->sparm.b4.a_current_ess_id); - local->timer.function = &start_net; - } else { - DEBUG(0, - "ray_cs interrupt network \"%s\" join failed\n", - local->sparm.b4.a_current_ess_id); - local->timer.function = &join_net; - } - add_timer(&local->timer); - } - break; - case CCS_START_ASSOCIATION: - if (status == CCS_COMMAND_COMPLETE) { - local->card_status = CARD_ASSOC_COMPLETE; - DEBUG(0, "ray_cs association successful\n"); - } else { - DEBUG(0, "ray_cs association failed,\n"); - local->card_status = CARD_ASSOC_FAILED; - join_net((u_long) local); - } - break; - case CCS_TX_REQUEST: - if (status == CCS_COMMAND_COMPLETE) { - DEBUG(3, - "ray_cs interrupt tx request complete\n"); - } else { - DEBUG(1, - "ray_cs interrupt tx request failed\n"); - } - if (!sniffer) - netif_start_queue(dev); - netif_wake_queue(dev); - break; - case CCS_TEST_MEMORY: - DEBUG(1, "ray_cs interrupt mem test done\n"); - break; - case CCS_SHUTDOWN: - DEBUG(1, - "ray_cs interrupt Unexpected CCS returned - Shutdown\n"); - break; - case CCS_DUMP_MEMORY: - DEBUG(1, "ray_cs interrupt dump memory done\n"); - break; - case CCS_START_TIMER: - DEBUG(2, - "ray_cs interrupt DING - raylink timer expired\n"); - break; - default: - DEBUG(1, - "ray_cs interrupt Unexpected CCS 0x%x returned 0x%x\n", - rcsindex, cmd); - } - writeb(CCS_BUFFER_FREE, &pccs->buffer_status); - } else { /* It's an RCS */ - - prcs = rcs_base(local) + rcsindex; - - switch (readb(&prcs->interrupt_id)) { - case PROCESS_RX_PACKET: - ray_rx(dev, local, prcs); - break; - case REJOIN_NET_COMPLETE: - DEBUG(1, "ray_cs interrupt rejoin net complete\n"); - local->card_status = CARD_ACQ_COMPLETE; - /* do we need to clear tx buffers CCS's? */ - if (local->sparm.b4.a_network_type == ADHOC) { - if (!sniffer) - netif_start_queue(dev); - } else { - memcpy_fromio(&local->bss_id, - prcs->var.rejoin_net_complete. - bssid, ADDRLEN); - DEBUG(1, - "ray_cs new BSSID = %02x%02x%02x%02x%02x%02x\n", - local->bss_id[0], local->bss_id[1], - local->bss_id[2], local->bss_id[3], - local->bss_id[4], local->bss_id[5]); - if (!sniffer) - authenticate(local); - } - break; - case ROAMING_INITIATED: - DEBUG(1, "ray_cs interrupt roaming initiated\n"); - netif_stop_queue(dev); - local->card_status = CARD_DOING_ACQ; - break; - case JAPAN_CALL_SIGN_RXD: - DEBUG(1, "ray_cs interrupt japan call sign rx\n"); - break; - default: - DEBUG(1, - "ray_cs Unexpected interrupt for RCS 0x%x cmd = 0x%x\n", - rcsindex, - (unsigned int)readb(&prcs->interrupt_id)); - break; - } - writeb(CCS_BUFFER_FREE, &prcs->buffer_status); - } - clear_interrupt(local); - return IRQ_HANDLED; -} /* ray_interrupt */ - -/*===========================================================================*/ -static void ray_rx(struct net_device *dev, ray_dev_t *local, - struct rcs __iomem *prcs) -{ - int rx_len; - unsigned int pkt_addr; - void __iomem *pmsg; - DEBUG(4, "ray_rx process rx packet\n"); - - /* Calculate address of packet within Rx buffer */ - pkt_addr = ((readb(&prcs->var.rx_packet.rx_data_ptr[0]) << 8) - + readb(&prcs->var.rx_packet.rx_data_ptr[1])) & RX_BUFF_END; - /* Length of first packet fragment */ - rx_len = (readb(&prcs->var.rx_packet.rx_data_length[0]) << 8) - + readb(&prcs->var.rx_packet.rx_data_length[1]); - - local->last_rsl = readb(&prcs->var.rx_packet.rx_sig_lev); - pmsg = local->rmem + pkt_addr; - switch (readb(pmsg)) { - case DATA_TYPE: - DEBUG(4, "ray_rx data type\n"); - rx_data(dev, prcs, pkt_addr, rx_len); - break; - case AUTHENTIC_TYPE: - DEBUG(4, "ray_rx authentic type\n"); - if (sniffer) - rx_data(dev, prcs, pkt_addr, rx_len); - else - rx_authenticate(local, prcs, pkt_addr, rx_len); - break; - case DEAUTHENTIC_TYPE: - DEBUG(4, "ray_rx deauth type\n"); - if (sniffer) - rx_data(dev, prcs, pkt_addr, rx_len); - else - rx_deauthenticate(local, prcs, pkt_addr, rx_len); - break; - case NULL_MSG_TYPE: - DEBUG(3, "ray_cs rx NULL msg\n"); - break; - case BEACON_TYPE: - DEBUG(4, "ray_rx beacon type\n"); - if (sniffer) - rx_data(dev, prcs, pkt_addr, rx_len); - - copy_from_rx_buff(local, (UCHAR *) &local->last_bcn, pkt_addr, - rx_len < sizeof(struct beacon_rx) ? - rx_len : sizeof(struct beacon_rx)); - - local->beacon_rxed = 1; - /* Get the statistics so the card counters never overflow */ - ray_get_stats(dev); - break; - default: - DEBUG(0, "ray_cs unknown pkt type %2x\n", - (unsigned int)readb(pmsg)); - break; - } - -} /* end ray_rx */ - -/*===========================================================================*/ -static void rx_data(struct net_device *dev, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len) -{ - struct sk_buff *skb = NULL; - struct rcs __iomem *prcslink = prcs; - ray_dev_t *local = netdev_priv(dev); - UCHAR *rx_ptr; - int total_len; - int tmp; -#ifdef WIRELESS_SPY - int siglev = local->last_rsl; - u_char linksrcaddr[ETH_ALEN]; /* Other end of the wireless link */ -#endif - - if (!sniffer) { - if (translate) { -/* TBD length needs fixing for translated header */ - if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || - rx_len > - (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + - FCS_LEN)) { - DEBUG(0, - "ray_cs invalid packet length %d received \n", - rx_len); - return; - } - } else { /* encapsulated ethernet */ - - if (rx_len < (ETH_HLEN + RX_MAC_HEADER_LENGTH) || - rx_len > - (dev->mtu + RX_MAC_HEADER_LENGTH + ETH_HLEN + - FCS_LEN)) { - DEBUG(0, - "ray_cs invalid packet length %d received \n", - rx_len); - return; - } - } - } - DEBUG(4, "ray_cs rx_data packet\n"); - /* If fragmented packet, verify sizes of fragments add up */ - if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { - DEBUG(1, "ray_cs rx'ed fragment\n"); - tmp = (readb(&prcs->var.rx_packet.totalpacketlength[0]) << 8) - + readb(&prcs->var.rx_packet.totalpacketlength[1]); - total_len = tmp; - prcslink = prcs; - do { - tmp -= - (readb(&prcslink->var.rx_packet.rx_data_length[0]) - << 8) - + readb(&prcslink->var.rx_packet.rx_data_length[1]); - if (readb(&prcslink->var.rx_packet.next_frag_rcs_index) - == 0xFF || tmp < 0) - break; - prcslink = rcs_base(local) - + readb(&prcslink->link_field); - } while (1); - - if (tmp < 0) { - DEBUG(0, - "ray_cs rx_data fragment lengths don't add up\n"); - local->stats.rx_dropped++; - release_frag_chain(local, prcs); - return; - } - } else { /* Single unfragmented packet */ - total_len = rx_len; - } - - skb = dev_alloc_skb(total_len + 5); - if (skb == NULL) { - DEBUG(0, "ray_cs rx_data could not allocate skb\n"); - local->stats.rx_dropped++; - if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) - release_frag_chain(local, prcs); - return; - } - skb_reserve(skb, 2); /* Align IP on 16 byte (TBD check this) */ - - DEBUG(4, "ray_cs rx_data total_len = %x, rx_len = %x\n", total_len, - rx_len); - -/************************/ - /* Reserve enough room for the whole damn packet. */ - rx_ptr = skb_put(skb, total_len); - /* Copy the whole packet to sk_buff */ - rx_ptr += - copy_from_rx_buff(local, rx_ptr, pkt_addr & RX_BUFF_END, rx_len); - /* Get source address */ -#ifdef WIRELESS_SPY - skb_copy_from_linear_data_offset(skb, - offsetof(struct mac_header, addr_2), - linksrcaddr, ETH_ALEN); -#endif - /* Now, deal with encapsulation/translation/sniffer */ - if (!sniffer) { - if (!translate) { - /* Encapsulated ethernet, so just lop off 802.11 MAC header */ -/* TBD reserve skb_reserve( skb, RX_MAC_HEADER_LENGTH); */ - skb_pull(skb, RX_MAC_HEADER_LENGTH); - } else { - /* Do translation */ - untranslate(local, skb, total_len); - } - } else { /* sniffer mode, so just pass whole packet */ - }; - -/************************/ - /* Now pick up the rest of the fragments if any */ - tmp = 17; - if (readb(&prcs->var.rx_packet.next_frag_rcs_index) != 0xFF) { - prcslink = prcs; - DEBUG(1, "ray_cs rx_data in fragment loop\n"); - do { - prcslink = rcs_base(local) - + - readb(&prcslink->var.rx_packet.next_frag_rcs_index); - rx_len = - ((readb(&prcslink->var.rx_packet.rx_data_length[0]) - << 8) - + - readb(&prcslink->var.rx_packet.rx_data_length[1])) - & RX_BUFF_END; - pkt_addr = - ((readb(&prcslink->var.rx_packet.rx_data_ptr[0]) << - 8) - + readb(&prcslink->var.rx_packet.rx_data_ptr[1])) - & RX_BUFF_END; - - rx_ptr += - copy_from_rx_buff(local, rx_ptr, pkt_addr, rx_len); - - } while (tmp-- && - readb(&prcslink->var.rx_packet.next_frag_rcs_index) != - 0xFF); - release_frag_chain(local, prcs); - } - - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - local->stats.rx_packets++; - local->stats.rx_bytes += total_len; - - /* Gather signal strength per address */ -#ifdef WIRELESS_SPY - /* For the Access Point or the node having started the ad-hoc net - * note : ad-hoc work only in some specific configurations, but we - * kludge in ray_get_wireless_stats... */ - if (!memcmp(linksrcaddr, local->bss_id, ETH_ALEN)) { - /* Update statistics */ - /*local->wstats.qual.qual = none ? */ - local->wstats.qual.level = siglev; - /*local->wstats.qual.noise = none ? */ - local->wstats.qual.updated = 0x2; - } - /* Now, update the spy stuff */ - { - struct iw_quality wstats; - wstats.level = siglev; - /* wstats.noise = none ? */ - /* wstats.qual = none ? */ - wstats.updated = 0x2; - /* Update spy records */ - wireless_spy_update(dev, linksrcaddr, &wstats); - } -#endif /* WIRELESS_SPY */ -} /* end rx_data */ - -/*===========================================================================*/ -static void untranslate(ray_dev_t *local, struct sk_buff *skb, int len) -{ - snaphdr_t *psnap = (snaphdr_t *) (skb->data + RX_MAC_HEADER_LENGTH); - struct ieee80211_hdr *pmac = (struct ieee80211_hdr *)skb->data; - __be16 type = *(__be16 *) psnap->ethertype; - int delta; - struct ethhdr *peth; - UCHAR srcaddr[ADDRLEN]; - UCHAR destaddr[ADDRLEN]; - static UCHAR org_bridge[3] = { 0, 0, 0xf8 }; - static UCHAR org_1042[3] = { 0, 0, 0 }; - - memcpy(destaddr, ieee80211_get_DA(pmac), ADDRLEN); - memcpy(srcaddr, ieee80211_get_SA(pmac), ADDRLEN); - -#ifdef PCMCIA_DEBUG - if (pc_debug > 3) { - print_hex_dump(KERN_DEBUG, "skb->data before untranslate: ", - DUMP_PREFIX_NONE, 16, 1, - skb->data, 64, true); - printk(KERN_DEBUG - "type = %08x, xsap = %02x%02x%02x, org = %02x02x02x\n", - ntohs(type), psnap->dsap, psnap->ssap, psnap->ctrl, - psnap->org[0], psnap->org[1], psnap->org[2]); - printk(KERN_DEBUG "untranslate skb->data = %p\n", skb->data); - } -#endif - - if (psnap->dsap != 0xaa || psnap->ssap != 0xaa || psnap->ctrl != 3) { - /* not a snap type so leave it alone */ - DEBUG(3, "ray_cs untranslate NOT SNAP %02x %02x %02x\n", - psnap->dsap, psnap->ssap, psnap->ctrl); - - delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = htons(len - RX_MAC_HEADER_LENGTH); - } else { /* Its a SNAP */ - if (memcmp(psnap->org, org_bridge, 3) == 0) { - /* EtherII and nuke the LLC */ - DEBUG(3, "ray_cs untranslate Bridge encap\n"); - delta = RX_MAC_HEADER_LENGTH - + sizeof(struct snaphdr_t) - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = type; - } else if (memcmp(psnap->org, org_1042, 3) == 0) { - switch (ntohs(type)) { - case ETH_P_IPX: - case ETH_P_AARP: - DEBUG(3, "ray_cs untranslate RFC IPX/AARP\n"); - delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = - htons(len - RX_MAC_HEADER_LENGTH); - break; - default: - DEBUG(3, "ray_cs untranslate RFC default\n"); - delta = RX_MAC_HEADER_LENGTH + - sizeof(struct snaphdr_t) - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = type; - break; - } - } else { - printk("ray_cs untranslate very confused by packet\n"); - delta = RX_MAC_HEADER_LENGTH - ETH_HLEN; - peth = (struct ethhdr *)(skb->data + delta); - peth->h_proto = type; - } - } -/* TBD reserve skb_reserve(skb, delta); */ - skb_pull(skb, delta); - DEBUG(3, "untranslate after skb_pull(%d), skb->data = %p\n", delta, - skb->data); - memcpy(peth->h_dest, destaddr, ADDRLEN); - memcpy(peth->h_source, srcaddr, ADDRLEN); -#ifdef PCMCIA_DEBUG - if (pc_debug > 3) { - int i; - printk(KERN_DEBUG "skb->data after untranslate:"); - for (i = 0; i < 64; i++) - printk("%02x ", skb->data[i]); - printk("\n"); - } -#endif -} /* end untranslate */ - -/*===========================================================================*/ -/* Copy data from circular receive buffer to PC memory. - * dest = destination address in PC memory - * pkt_addr = source address in receive buffer - * len = length of packet to copy - */ -static int copy_from_rx_buff(ray_dev_t *local, UCHAR *dest, int pkt_addr, - int length) -{ - int wrap_bytes = (pkt_addr + length) - (RX_BUFF_END + 1); - if (wrap_bytes <= 0) { - memcpy_fromio(dest, local->rmem + pkt_addr, length); - } else { /* Packet wrapped in circular buffer */ - - memcpy_fromio(dest, local->rmem + pkt_addr, - length - wrap_bytes); - memcpy_fromio(dest + length - wrap_bytes, local->rmem, - wrap_bytes); - } - return length; -} - -/*===========================================================================*/ -static void release_frag_chain(ray_dev_t *local, struct rcs __iomem *prcs) -{ - struct rcs __iomem *prcslink = prcs; - int tmp = 17; - unsigned rcsindex = readb(&prcs->var.rx_packet.next_frag_rcs_index); - - while (tmp--) { - writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); - if (rcsindex >= (NUMBER_OF_CCS + NUMBER_OF_RCS)) { - DEBUG(1, "ray_cs interrupt bad rcsindex = 0x%x\n", - rcsindex); - break; - } - prcslink = rcs_base(local) + rcsindex; - rcsindex = readb(&prcslink->var.rx_packet.next_frag_rcs_index); - } - writeb(CCS_BUFFER_FREE, &prcslink->buffer_status); -} - -/*===========================================================================*/ -static void authenticate(ray_dev_t *local) -{ - struct pcmcia_device *link = local->finder; - DEBUG(0, "ray_cs Starting authentication.\n"); - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs authenticate - device not present\n"); - return; - } - - del_timer(&local->timer); - if (build_auth_frame(local, local->bss_id, OPEN_AUTH_REQUEST)) { - local->timer.function = &join_net; - } else { - local->timer.function = &authenticate_timeout; - } - local->timer.expires = jiffies + HZ * 2; - local->timer.data = (long)local; - add_timer(&local->timer); - local->authentication_state = AWAITING_RESPONSE; -} /* end authenticate */ - -/*===========================================================================*/ -static void rx_authenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len) -{ - UCHAR buff[256]; - struct rx_msg *msg = (struct rx_msg *)buff; - - del_timer(&local->timer); - - copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); - /* if we are trying to get authenticated */ - if (local->sparm.b4.a_network_type == ADHOC) { - DEBUG(1, "ray_cs rx_auth var= %02x %02x %02x %02x %02x %02x\n", - msg->var[0], msg->var[1], msg->var[2], msg->var[3], - msg->var[4], msg->var[5]); - if (msg->var[2] == 1) { - DEBUG(0, "ray_cs Sending authentication response.\n"); - if (!build_auth_frame - (local, msg->mac.addr_2, OPEN_AUTH_RESPONSE)) { - local->authentication_state = NEED_TO_AUTH; - memcpy(local->auth_id, msg->mac.addr_2, - ADDRLEN); - } - } - } else { /* Infrastructure network */ - - if (local->authentication_state == AWAITING_RESPONSE) { - /* Verify authentication sequence #2 and success */ - if (msg->var[2] == 2) { - if ((msg->var[3] | msg->var[4]) == 0) { - DEBUG(1, "Authentication successful\n"); - local->card_status = CARD_AUTH_COMPLETE; - associate(local); - local->authentication_state = - AUTHENTICATED; - } else { - DEBUG(0, "Authentication refused\n"); - local->card_status = CARD_AUTH_REFUSED; - join_net((u_long) local); - local->authentication_state = - UNAUTHENTICATED; - } - } - } - } - -} /* end rx_authenticate */ - -/*===========================================================================*/ -static void associate(ray_dev_t *local) -{ - struct ccs __iomem *pccs; - struct pcmcia_device *link = local->finder; - struct net_device *dev = link->priv; - int ccsindex; - if (!(pcmcia_dev_present(link))) { - DEBUG(2, "ray_cs associate - device not present\n"); - return; - } - /* If no tx buffers available, return */ - if ((ccsindex = get_free_ccs(local)) < 0) { -/* TBD should never be here but... what if we are? */ - DEBUG(1, "ray_cs associate - No free ccs\n"); - return; - } - DEBUG(1, "ray_cs Starting association with access point\n"); - pccs = ccs_base(local) + ccsindex; - /* fill in the CCS */ - writeb(CCS_START_ASSOCIATION, &pccs->cmd); - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1, "ray_cs associate failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - - del_timer(&local->timer); - local->timer.expires = jiffies + HZ * 2; - local->timer.data = (long)local; - local->timer.function = &join_net; - add_timer(&local->timer); - local->card_status = CARD_ASSOC_FAILED; - return; - } - if (!sniffer) - netif_start_queue(dev); - -} /* end associate */ - -/*===========================================================================*/ -static void rx_deauthenticate(ray_dev_t *local, struct rcs __iomem *prcs, - unsigned int pkt_addr, int rx_len) -{ -/* UCHAR buff[256]; - struct rx_msg *msg = (struct rx_msg *)buff; -*/ - DEBUG(0, "Deauthentication frame received\n"); - local->authentication_state = UNAUTHENTICATED; - /* Need to reauthenticate or rejoin depending on reason code */ -/* copy_from_rx_buff(local, buff, pkt_addr, rx_len & 0xff); - */ -} - -/*===========================================================================*/ -static void clear_interrupt(ray_dev_t *local) -{ - writeb(0, local->amem + CIS_OFFSET + HCS_INTR_OFFSET); -} - -/*===========================================================================*/ -#ifdef CONFIG_PROC_FS -#define MAXDATA (PAGE_SIZE - 80) - -static char *card_status[] = { - "Card inserted - uninitialized", /* 0 */ - "Card not downloaded", /* 1 */ - "Waiting for download parameters", /* 2 */ - "Card doing acquisition", /* 3 */ - "Acquisition complete", /* 4 */ - "Authentication complete", /* 5 */ - "Association complete", /* 6 */ - "???", "???", "???", "???", /* 7 8 9 10 undefined */ - "Card init error", /* 11 */ - "Download parameters error", /* 12 */ - "???", /* 13 */ - "Acquisition failed", /* 14 */ - "Authentication refused", /* 15 */ - "Association failed" /* 16 */ -}; - -static char *nettype[] = { "Adhoc", "Infra " }; -static char *framing[] = { "Encapsulation", "Translation" } - -; -/*===========================================================================*/ -static int ray_cs_proc_show(struct seq_file *m, void *v) -{ -/* Print current values which are not available via other means - * eg ifconfig - */ - int i; - struct pcmcia_device *link; - struct net_device *dev; - ray_dev_t *local; - UCHAR *p; - struct freq_hop_element *pfh; - UCHAR c[33]; - - link = this_device; - if (!link) - return 0; - dev = (struct net_device *)link->priv; - if (!dev) - return 0; - local = netdev_priv(dev); - if (!local) - return 0; - - seq_puts(m, "Raylink Wireless LAN driver status\n"); - seq_printf(m, "%s\n", rcsid); - /* build 4 does not report version, and field is 0x55 after memtest */ - seq_puts(m, "Firmware version = "); - if (local->fw_ver == 0x55) - seq_puts(m, "4 - Use dump_cis for more details\n"); - else - seq_printf(m, "%2d.%02d.%02d\n", - local->fw_ver, local->fw_bld, local->fw_var); - - for (i = 0; i < 32; i++) - c[i] = local->sparm.b5.a_current_ess_id[i]; - c[32] = 0; - seq_printf(m, "%s network ESSID = \"%s\"\n", - nettype[local->sparm.b5.a_network_type], c); - - p = local->bss_id; - seq_printf(m, "BSSID = %pM\n", p); - - seq_printf(m, "Country code = %d\n", - local->sparm.b5.a_curr_country_code); - - i = local->card_status; - if (i < 0) - i = 10; - if (i > 16) - i = 10; - seq_printf(m, "Card status = %s\n", card_status[i]); - - seq_printf(m, "Framing mode = %s\n", framing[translate]); - - seq_printf(m, "Last pkt signal lvl = %d\n", local->last_rsl); - - if (local->beacon_rxed) { - /* Pull some fields out of last beacon received */ - seq_printf(m, "Beacon Interval = %d Kus\n", - local->last_bcn.beacon_intvl[0] - + 256 * local->last_bcn.beacon_intvl[1]); - - p = local->last_bcn.elements; - if (p[0] == C_ESSID_ELEMENT_ID) - p += p[1] + 2; - else { - seq_printf(m, - "Parse beacon failed at essid element id = %d\n", - p[0]); - return 0; - } - - if (p[0] == C_SUPPORTED_RATES_ELEMENT_ID) { - seq_puts(m, "Supported rate codes = "); - for (i = 2; i < p[1] + 2; i++) - seq_printf(m, "0x%02x ", p[i]); - seq_putc(m, '\n'); - p += p[1] + 2; - } else { - seq_puts(m, "Parse beacon failed at rates element\n"); - return 0; - } - - if (p[0] == C_FH_PARAM_SET_ELEMENT_ID) { - pfh = (struct freq_hop_element *)p; - seq_printf(m, "Hop dwell = %d Kus\n", - pfh->dwell_time[0] + - 256 * pfh->dwell_time[1]); - seq_printf(m, "Hop set = %d \n", - pfh->hop_set); - seq_printf(m, "Hop pattern = %d \n", - pfh->hop_pattern); - seq_printf(m, "Hop index = %d \n", - pfh->hop_index); - p += p[1] + 2; - } else { - seq_puts(m, - "Parse beacon failed at FH param element\n"); - return 0; - } - } else { - seq_puts(m, "No beacons received\n"); - } - return 0; -} - -static int ray_cs_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, ray_cs_proc_show, NULL); -} - -static const struct file_operations ray_cs_proc_fops = { - .owner = THIS_MODULE, - .open = ray_cs_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif -/*===========================================================================*/ -static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type) -{ - int addr; - struct ccs __iomem *pccs; - struct tx_msg __iomem *ptx; - int ccsindex; - - /* If no tx buffers available, return */ - if ((ccsindex = get_free_tx_ccs(local)) < 0) { - DEBUG(1, "ray_cs send authenticate - No free tx ccs\n"); - return -1; - } - - pccs = ccs_base(local) + ccsindex; - - /* Address in card space */ - addr = TX_BUF_BASE + (ccsindex << 11); - /* fill in the CCS */ - writeb(CCS_TX_REQUEST, &pccs->cmd); - writeb(addr >> 8, pccs->var.tx_request.tx_data_ptr); - writeb(0x20, pccs->var.tx_request.tx_data_ptr + 1); - writeb(TX_AUTHENTICATE_LENGTH_MSB, pccs->var.tx_request.tx_data_length); - writeb(TX_AUTHENTICATE_LENGTH_LSB, - pccs->var.tx_request.tx_data_length + 1); - writeb(0, &pccs->var.tx_request.pow_sav_mode); - - ptx = local->sram + addr; - /* fill in the mac header */ - writeb(PROTOCOL_VER | AUTHENTIC_TYPE, &ptx->mac.frame_ctl_1); - writeb(0, &ptx->mac.frame_ctl_2); - - memcpy_toio(ptx->mac.addr_1, dest, ADDRLEN); - memcpy_toio(ptx->mac.addr_2, local->sparm.b4.a_mac_addr, ADDRLEN); - memcpy_toio(ptx->mac.addr_3, local->bss_id, ADDRLEN); - - /* Fill in msg body with protocol 00 00, sequence 01 00 ,status 00 00 */ - memset_io(ptx->var, 0, 6); - writeb(auth_type & 0xff, ptx->var + 2); - - /* Interrupt the firmware to process the command */ - if (interrupt_ecf(local, ccsindex)) { - DEBUG(1, - "ray_cs send authentication request failed - ECF not ready for intr\n"); - writeb(CCS_BUFFER_FREE, &(pccs++)->buffer_status); - return -1; - } - return 0; -} /* End build_auth_frame */ - -/*===========================================================================*/ -#ifdef CONFIG_PROC_FS -static void raycs_write(const char *name, write_proc_t *w, void *data) -{ - struct proc_dir_entry *entry = - create_proc_entry(name, S_IFREG | S_IWUSR, NULL); - if (entry) { - entry->write_proc = w; - entry->data = data; - } -} - -static int write_essid(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - static char proc_essid[33]; - unsigned int len = count; - - if (len > 32) - len = 32; - memset(proc_essid, 0, 33); - if (copy_from_user(proc_essid, buffer, len)) - return -EFAULT; - essid = proc_essid; - return count; -} - -static int write_int(struct file *file, const char __user *buffer, - unsigned long count, void *data) -{ - static char proc_number[10]; - char *p; - int nr, len; - - if (!count) - return 0; - - if (count > 9) - return -EINVAL; - if (copy_from_user(proc_number, buffer, count)) - return -EFAULT; - p = proc_number; - nr = 0; - len = count; - do { - unsigned int c = *p - '0'; - if (c > 9) - return -EINVAL; - nr = nr * 10 + c; - p++; - } while (--len); - *(int *)data = nr; - return count; -} -#endif - -static struct pcmcia_device_id ray_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0x01a6, 0x0000), - PCMCIA_DEVICE_NULL, -}; - -MODULE_DEVICE_TABLE(pcmcia, ray_ids); - -static struct pcmcia_driver ray_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "ray_cs", - }, - .probe = ray_probe, - .remove = ray_detach, - .id_table = ray_ids, - .suspend = ray_suspend, - .resume = ray_resume, -}; - -static int __init init_ray_cs(void) -{ - int rc; - - DEBUG(1, "%s\n", rcsid); - rc = pcmcia_register_driver(&ray_driver); - DEBUG(1, "raylink init_module register_pcmcia_driver returns 0x%x\n", - rc); - -#ifdef CONFIG_PROC_FS - proc_mkdir("driver/ray_cs", NULL); - - proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); - raycs_write("driver/ray_cs/essid", write_essid, NULL); - raycs_write("driver/ray_cs/net_type", write_int, &net_type); - raycs_write("driver/ray_cs/translate", write_int, &translate); -#endif - if (translate != 0) - translate = 1; - return 0; -} /* init_ray_cs */ - -/*===========================================================================*/ - -static void __exit exit_ray_cs(void) -{ - DEBUG(0, "ray_cs: cleanup_module\n"); - -#ifdef CONFIG_PROC_FS - remove_proc_entry("driver/ray_cs/ray_cs", NULL); - remove_proc_entry("driver/ray_cs/essid", NULL); - remove_proc_entry("driver/ray_cs/net_type", NULL); - remove_proc_entry("driver/ray_cs/translate", NULL); - remove_proc_entry("driver/ray_cs", NULL); -#endif - - pcmcia_unregister_driver(&ray_driver); -} /* exit_ray_cs */ - -module_init(init_ray_cs); -module_exit(exit_ray_cs); - -/*===========================================================================*/ diff --git a/drivers/net/wireless/ray_cs.h b/drivers/net/wireless/ray_cs.h deleted file mode 100644 index 1e23b7f4cca7..000000000000 --- a/drivers/net/wireless/ray_cs.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Raytheon wireless LAN PCMCIA card driver for Linux - A PCMCIA client driver for the Raylink wireless network card - Written by Corey Thomas -*/ - -#ifndef RAYLINK_H - -struct beacon_rx { - struct mac_header mac; - UCHAR timestamp[8]; - UCHAR beacon_intvl[2]; - UCHAR capability[2]; - UCHAR elements[sizeof(struct essid_element) - + sizeof(struct rates_element) - + sizeof(struct freq_hop_element) - + sizeof(struct japan_call_sign_element) - + sizeof(struct tim_element)]; -}; - -/* Return values for get_free{,_tx}_ccs */ -#define ECCSFULL (-1) -#define ECCSBUSY (-2) -#define ECARDGONE (-3) - -typedef struct ray_dev_t { - int card_status; - int authentication_state; - dev_node_t node; - window_handle_t amem_handle; /* handle to window for attribute memory */ - window_handle_t rmem_handle; /* handle to window for rx buffer on card */ - void __iomem *sram; /* pointer to beginning of shared RAM */ - void __iomem *amem; /* pointer to attribute mem window */ - void __iomem *rmem; /* pointer to receive buffer window */ - struct pcmcia_device *finder; /* pointer back to struct pcmcia_device for card */ - struct timer_list timer; - unsigned long tx_ccs_lock; - unsigned long ccs_lock; - int dl_param_ccs; - union { - struct b4_startup_params b4; - struct b5_startup_params b5; - } sparm; - int timeout_flag; - UCHAR supported_rates[8]; - UCHAR japan_call_sign[12]; - struct startup_res_6 startup_res; - int num_multi; - /* Network parameters from start/join */ - UCHAR bss_id[6]; - UCHAR auth_id[6]; - UCHAR net_default_tx_rate; - UCHAR encryption; - struct net_device_stats stats; - - UCHAR net_type; - UCHAR sta_type; - UCHAR fw_ver; - UCHAR fw_bld; - UCHAR fw_var; - UCHAR ASIC_version; - UCHAR assoc_id[2]; - UCHAR tib_length; - UCHAR last_rsl; - int beacon_rxed; - struct beacon_rx last_bcn; - iw_stats wstats; /* Wireless specific stats */ -#ifdef WIRELESS_SPY - struct iw_spy_data spy_data; - struct iw_public_data wireless_data; -#endif /* WIRELESS_SPY */ - -} ray_dev_t; -/*****************************************************************************/ - -#endif /* RAYLINK_H */ diff --git a/drivers/net/wireless/rayctl.h b/drivers/net/wireless/rayctl.h deleted file mode 100644 index 49d9b267bc0f..000000000000 --- a/drivers/net/wireless/rayctl.h +++ /dev/null @@ -1,732 +0,0 @@ -#ifndef RAYLINK_H - -typedef unsigned char UCHAR; - -/****** IEEE 802.11 constants ************************************************/ -#define ADDRLEN 6 -/* Frame control 1 bit fields */ -#define PROTOCOL_VER 0x00 -#define DATA_TYPE 0x08 -#define ASSOC_REQ_TYPE 0x00 -#define ASSOC_RESP_TYPE 0x10 -#define REASSOC_REQ_TYPE 0x20 -#define REASSOC_RESP_TYPE 0x30 -#define NULL_MSG_TYPE 0x48 -#define BEACON_TYPE 0x80 -#define DISASSOC_TYPE 0xA0 -#define PSPOLL_TYPE 0xA4 -#define AUTHENTIC_TYPE 0xB0 -#define DEAUTHENTIC_TYPE 0xC0 -/* Frame control 2 bit fields */ -#define FC2_TO_DS 0x01 -#define FC2_FROM_DS 0x02 -#define FC2_MORE_FRAG 0x04 -#define FC2_RETRY 0x08 -#define FC2_PSM 0x10 -#define FC2_MORE_DATA 0x20 -#define FC2_WEP 0x40 -#define FC2_ORDER 0x80 -/*****************************************************************************/ -/* 802.11 element ID's and lengths */ -#define C_BP_CAPABILITY_ESS 0x01 -#define C_BP_CAPABILITY_IBSS 0x02 -#define C_BP_CAPABILITY_CF_POLLABLE 0x04 -#define C_BP_CAPABILITY_CF_POLL_REQUEST 0x08 -#define C_BP_CAPABILITY_PRIVACY 0x10 - -#define C_ESSID_ELEMENT_ID 0 -#define C_ESSID_ELEMENT_MAX_LENGTH 32 - -#define C_SUPPORTED_RATES_ELEMENT_ID 1 -#define C_SUPPORTED_RATES_ELEMENT_LENGTH 2 - -#define C_FH_PARAM_SET_ELEMENT_ID 2 -#define C_FH_PARAM_SET_ELEMENT_LNGTH 5 - -#define C_CF_PARAM_SET_ELEMENT_ID 4 -#define C_CF_PARAM_SET_ELEMENT_LNGTH 6 - -#define C_TIM_ELEMENT_ID 5 -#define C_TIM_BITMAP_LENGTH 251 -#define C_TIM_BMCAST_BIT 0x01 - -#define C_IBSS_ELEMENT_ID 6 -#define C_IBSS_ELEMENT_LENGTH 2 - -#define C_JAPAN_CALL_SIGN_ELEMENT_ID 51 -#define C_JAPAN_CALL_SIGN_ELEMENT_LNGTH 12 - -#define C_DISASSOC_REASON_CODE_LEN 2 -#define C_DISASSOC_REASON_CODE_DEFAULT 8 - -#define C_CRC_LEN 4 -#define C_NUM_SUPPORTED_RATES 8 -/****** IEEE 802.11 mac header for type data packets *************************/ -struct mac_header { - UCHAR frame_ctl_1; - UCHAR frame_ctl_2; - UCHAR duration_lsb; - UCHAR duration_msb; - UCHAR addr_1[ADDRLEN]; - UCHAR addr_2[ADDRLEN]; - UCHAR addr_3[ADDRLEN]; - UCHAR seq_frag_num[2]; -/* UCHAR addr_4[ADDRLEN]; *//* only present for AP to AP (TO DS and FROM DS */ -}; -/****** IEEE 802.11 frame element structures *********************************/ -struct essid_element -{ - UCHAR id; - UCHAR length; - UCHAR text[C_ESSID_ELEMENT_MAX_LENGTH]; -}; -struct rates_element -{ - UCHAR id; - UCHAR length; - UCHAR value[8]; -}; -struct freq_hop_element -{ - UCHAR id; - UCHAR length; - UCHAR dwell_time[2]; - UCHAR hop_set; - UCHAR hop_pattern; - UCHAR hop_index; -}; -struct tim_element -{ - UCHAR id; - UCHAR length; - UCHAR dtim_count; - UCHAR dtim_period; - UCHAR bitmap_control; - UCHAR tim[C_TIM_BITMAP_LENGTH]; -}; -struct ibss_element -{ - UCHAR id; - UCHAR length; - UCHAR atim_window[2]; -}; -struct japan_call_sign_element -{ - UCHAR id; - UCHAR length; - UCHAR call_sign[12]; -}; -/****** Beacon message structures ********************************************/ -/* .elements is a large lump of max size because elements are variable size */ -struct infra_beacon -{ - UCHAR timestamp[8]; - UCHAR beacon_intvl[2]; - UCHAR capability[2]; - UCHAR elements[sizeof(struct essid_element) - + sizeof(struct rates_element) - + sizeof(struct freq_hop_element) - + sizeof(struct japan_call_sign_element) - + sizeof(struct tim_element)]; -}; -struct adhoc_beacon -{ - UCHAR timestamp[8]; - UCHAR beacon_intvl[2]; - UCHAR capability[2]; - UCHAR elements[sizeof(struct essid_element) - + sizeof(struct rates_element) - + sizeof(struct freq_hop_element) - + sizeof(struct japan_call_sign_element) - + sizeof(struct ibss_element)]; -}; -/*****************************************************************************/ -/*****************************************************************************/ -/* #define C_MAC_HDR_2_WEP 0x40 */ -/* TX/RX CCS constants */ -#define TX_HEADER_LENGTH 0x1C -#define RX_MAC_HEADER_LENGTH 0x18 -#define TX_AUTHENTICATE_LENGTH (TX_HEADER_LENGTH + 6) -#define TX_AUTHENTICATE_LENGTH_MSB (TX_AUTHENTICATE_LENGTH >> 8) -#define TX_AUTHENTICATE_LENGTH_LSB (TX_AUTHENTICATE_LENGTH & 0xff) -#define TX_DEAUTHENTICATE_LENGTH (TX_HEADER_LENGTH + 2) -#define TX_DEAUTHENTICATE_LENGTH_MSB (TX_AUTHENTICATE_LENGTH >> 8) -#define TX_DEAUTHENTICATE_LENGTH_LSB (TX_AUTHENTICATE_LENGTH & 0xff) -#define FCS_LEN 4 - -#define ADHOC 0 -#define INFRA 1 - -#define TYPE_STA 0 -#define TYPE_AP 1 - -#define PASSIVE_SCAN 1 -#define ACTIVE_SCAN 1 - -#define PSM_CAM 0 - -/* Country codes */ -#define USA 1 -#define EUROPE 2 -#define JAPAN 3 -#define KOREA 4 -#define SPAIN 5 -#define FRANCE 6 -#define ISRAEL 7 -#define AUSTRALIA 8 -#define JAPAN_TEST 9 - -/* Hop pattern lengths */ -#define USA_HOP_MOD 79 -#define EUROPE_HOP_MOD 79 -#define JAPAN_HOP_MOD 23 -#define KOREA_HOP_MOD 23 -#define SPAIN_HOP_MOD 27 -#define FRANCE_HOP_MOD 35 -#define ISRAEL_HOP_MOD 35 -#define AUSTRALIA_HOP_MOD 47 -#define JAPAN_TEST_HOP_MOD 23 - -#define ESSID_SIZE 32 -/**********************************************************************/ -/* CIS Register Constants */ -#define CIS_OFFSET 0x0f00 -/* Configuration Option Register (0x0F00) */ -#define COR_OFFSET 0x00 -#define COR_SOFT_RESET 0x80 -#define COR_LEVEL_IRQ 0x40 -#define COR_CONFIG_NUM 0x01 -#define COR_DEFAULT (COR_LEVEL_IRQ | COR_CONFIG_NUM) - -/* Card Configuration and Status Register (0x0F01) */ -#define CCSR_OFFSET 0x01 -#define CCSR_HOST_INTR_PENDING 0x01 -#define CCSR_POWER_DOWN 0x04 - -/* HCS Interrupt Register (0x0F05) */ -#define HCS_INTR_OFFSET 0x05 -/* #define HCS_INTR_OFFSET 0x0A */ -#define HCS_INTR_CLEAR 0x00 - -/* ECF Interrupt Register (0x0F06) */ -#define ECF_INTR_OFFSET 0x06 -/* #define ECF_INTR_OFFSET 0x0C */ -#define ECF_INTR_SET 0x01 - -/* Authorization Register 0 (0x0F08) */ -#define AUTH_0_ON 0x57 - -/* Authorization Register 1 (0x0F09) */ -#define AUTH_1_ON 0x82 - -/* Program Mode Register (0x0F0A) */ -#define PC2PM 0x02 -#define PC2CAL 0x10 -#define PC2MLSE 0x20 - -/* PC Test Mode Register (0x0F0B) */ -#define PC_TEST_MODE 0x08 - -/* Frequency Control Word (0x0F10) */ -/* Range 0x02 - 0xA6 */ - -/* Test Mode Control 1-4 (0x0F14 - 0x0F17) */ - -/**********************************************************************/ - -/* Shared RAM Area */ -#define SCB_BASE 0x0000 -#define STATUS_BASE 0x0100 -#define HOST_TO_ECF_BASE 0x0200 -#define ECF_TO_HOST_BASE 0x0300 -#define CCS_BASE 0x0400 -#define RCS_BASE 0x0800 -#define INFRA_TIM_BASE 0x0C00 -#define SSID_LIST_BASE 0x0D00 -#define TX_BUF_BASE 0x1000 -#define RX_BUF_BASE 0x8000 - -#define NUMBER_OF_CCS 64 -#define NUMBER_OF_RCS 64 -/*#define NUMBER_OF_TX_CCS 14 */ -#define NUMBER_OF_TX_CCS 14 - -#define TX_BUF_SIZE (2048 - sizeof(struct tx_msg)) -#define RX_BUFF_END 0x3FFF -/* Values for buffer_status */ -#define CCS_BUFFER_FREE 0 -#define CCS_BUFFER_BUSY 1 -#define CCS_COMMAND_COMPLETE 2 -#define CCS_COMMAND_FAILED 3 - -/* Values for cmd */ -#define CCS_DOWNLOAD_STARTUP_PARAMS 1 -#define CCS_UPDATE_PARAMS 2 -#define CCS_REPORT_PARAMS 3 -#define CCS_UPDATE_MULTICAST_LIST 4 -#define CCS_UPDATE_POWER_SAVINGS_MODE 5 -#define CCS_START_NETWORK 6 -#define CCS_JOIN_NETWORK 7 -#define CCS_START_ASSOCIATION 8 -#define CCS_TX_REQUEST 9 -#define CCS_TEST_MEMORY 0xa -#define CCS_SHUTDOWN 0xb -#define CCS_DUMP_MEMORY 0xc -#define CCS_START_TIMER 0xe -#define CCS_LAST_CMD CCS_START_TIMER - -/* Values for link field */ -#define CCS_END_LIST 0xff - -/* values for buffer_status field */ -#define RCS_BUFFER_FREE 0 -#define RCS_BUFFER_BUSY 1 -#define RCS_COMPLETE 2 -#define RCS_FAILED 3 -#define RCS_BUFFER_RELEASE 0xFF - -/* values for interrupt_id field */ -#define PROCESS_RX_PACKET 0x80 /* */ -#define REJOIN_NET_COMPLETE 0x81 /* RCS ID: Rejoin Net Complete */ -#define ROAMING_INITIATED 0x82 /* RCS ID: Roaming Initiated */ -#define JAPAN_CALL_SIGN_RXD 0x83 /* RCS ID: New Japan Call Sign */ - -/*****************************************************************************/ -/* Memory types for dump memory command */ -#define C_MEM_PROG 0 -#define C_MEM_XDATA 1 -#define C_MEM_SFR 2 -#define C_MEM_IDATA 3 - -/*** Return values for hw_xmit **********/ -#define XMIT_OK (0) -#define XMIT_MSG_BAD (-1) -#define XMIT_NO_CCS (-2) -#define XMIT_NO_INTR (-3) -#define XMIT_NEED_AUTH (-4) - -/*** Values for card status */ -#define CARD_INSERTED (0) - -#define CARD_AWAITING_PARAM (1) -#define CARD_INIT_ERROR (11) - -#define CARD_DL_PARAM (2) -#define CARD_DL_PARAM_ERROR (12) - -#define CARD_DOING_ACQ (3) - -#define CARD_ACQ_COMPLETE (4) -#define CARD_ACQ_FAILED (14) - -#define CARD_AUTH_COMPLETE (5) -#define CARD_AUTH_REFUSED (15) - -#define CARD_ASSOC_COMPLETE (6) -#define CARD_ASSOC_FAILED (16) - -/*** Values for authentication_state ***********************************/ -#define UNAUTHENTICATED (0) -#define AWAITING_RESPONSE (1) -#define AUTHENTICATED (2) -#define NEED_TO_AUTH (3) - -/*** Values for authentication type ************************************/ -#define OPEN_AUTH_REQUEST (1) -#define OPEN_AUTH_RESPONSE (2) -#define BROADCAST_DEAUTH (0xc0) -/*** Values for timer functions ****************************************/ -#define TODO_NOTHING (0) -#define TODO_VERIFY_DL_START (-1) -#define TODO_START_NET (-2) -#define TODO_JOIN_NET (-3) -#define TODO_AUTHENTICATE_TIMEOUT (-4) -#define TODO_SEND_CCS (-5) -/***********************************************************************/ -/* Parameter passing structure for update/report parameter CCS's */ -struct object_id { - void *object_addr; - unsigned char object_length; -}; - -#define OBJID_network_type 0 -#define OBJID_acting_as_ap_status 1 -#define OBJID_current_ess_id 2 -#define OBJID_scanning_mode 3 -#define OBJID_power_mgt_state 4 -#define OBJID_mac_address 5 -#define OBJID_frag_threshold 6 -#define OBJID_hop_time 7 -#define OBJID_beacon_period 8 -#define OBJID_dtim_period 9 -#define OBJID_retry_max 10 -#define OBJID_ack_timeout 11 -#define OBJID_sifs 12 -#define OBJID_difs 13 -#define OBJID_pifs 14 -#define OBJID_rts_threshold 15 -#define OBJID_scan_dwell_time 16 -#define OBJID_max_scan_dwell_time 17 -#define OBJID_assoc_resp_timeout 18 -#define OBJID_adhoc_scan_cycle_max 19 -#define OBJID_infra_scan_cycle_max 20 -#define OBJID_infra_super_cycle_max 21 -#define OBJID_promiscuous_mode 22 -#define OBJID_unique_word 23 -#define OBJID_slot_time 24 -#define OBJID_roaming_low_snr 25 -#define OBJID_low_snr_count_thresh 26 -#define OBJID_infra_missed_bcn 27 -#define OBJID_adhoc_missed_bcn 28 -#define OBJID_curr_country_code 29 -#define OBJID_hop_pattern 30 -#define OBJID_reserved 31 -#define OBJID_cw_max_msb 32 -#define OBJID_cw_min_msb 33 -#define OBJID_noise_filter_gain 34 -#define OBJID_noise_limit_offset 35 -#define OBJID_det_rssi_thresh_offset 36 -#define OBJID_med_busy_thresh_offset 37 -#define OBJID_det_sync_thresh 38 -#define OBJID_test_mode 39 -#define OBJID_test_min_chan_num 40 -#define OBJID_test_max_chan_num 41 -#define OBJID_allow_bcast_ID_prbrsp 42 -#define OBJID_privacy_must_start 43 -#define OBJID_privacy_can_join 44 -#define OBJID_basic_rate_set 45 - -/**** Configuration/Status/Control Area ***************************/ -/* System Control Block (SCB) Area - * Located at Shared RAM offset 0 - */ -struct scb { - UCHAR ccs_index; - UCHAR rcs_index; -}; - -/****** Status area at Shared RAM offset 0x0100 ******************************/ -struct status { - UCHAR mrx_overflow_for_host; /* 0=ECF may write, 1=host may write*/ - UCHAR mrx_checksum_error_for_host; /* 0=ECF may write, 1=host may write*/ - UCHAR rx_hec_error_for_host; /* 0=ECF may write, 1=host may write*/ - UCHAR reserved1; - short mrx_overflow; /* ECF increments on rx overflow */ - short mrx_checksum_error; /* ECF increments on rx CRC error */ - short rx_hec_error; /* ECF incs on mac header CRC error */ - UCHAR rxnoise; /* Average RSL measurement */ -}; - -/****** Host-to-ECF Data Area at Shared RAM offset 0x200 *********************/ -struct host_to_ecf_area { - -}; - -/****** ECF-to-Host Data Area at Shared RAM offset 0x0300 ********************/ -struct startup_res_518 { - UCHAR startup_word; - UCHAR station_addr[ADDRLEN]; - UCHAR calc_prog_chksum; - UCHAR calc_cis_chksum; - UCHAR ecf_spare[7]; - UCHAR japan_call_sign[12]; -}; - -struct startup_res_6 { - UCHAR startup_word; - UCHAR station_addr[ADDRLEN]; - UCHAR reserved; - UCHAR supp_rates[8]; - UCHAR japan_call_sign[12]; - UCHAR calc_prog_chksum; - UCHAR calc_cis_chksum; - UCHAR firmware_version[3]; - UCHAR asic_version; - UCHAR tib_length; -}; - -struct start_join_net_params { - UCHAR net_type; - UCHAR ssid[ESSID_SIZE]; - UCHAR reserved; - UCHAR privacy_can_join; -}; - -/****** Command Control Structure area at Shared ram offset 0x0400 ***********/ -/* Structures for command specific parameters (ccs.var) */ -struct update_param_cmd { - UCHAR object_id; - UCHAR number_objects; - UCHAR failure_cause; -}; -struct report_param_cmd { - UCHAR object_id; - UCHAR number_objects; - UCHAR failure_cause; - UCHAR length; -}; -struct start_network_cmd { - UCHAR update_param; - UCHAR bssid[ADDRLEN]; - UCHAR net_initiated; - UCHAR net_default_tx_rate; - UCHAR encryption; -}; -struct join_network_cmd { - UCHAR update_param; - UCHAR bssid[ADDRLEN]; - UCHAR net_initiated; - UCHAR net_default_tx_rate; - UCHAR encryption; -}; -struct tx_requested_cmd { - - UCHAR tx_data_ptr[2]; - UCHAR tx_data_length[2]; - UCHAR host_reserved[2]; - UCHAR reserved[3]; - UCHAR tx_rate; - UCHAR pow_sav_mode; - UCHAR retries; - UCHAR antenna; -}; -struct tx_requested_cmd_4 { - - UCHAR tx_data_ptr[2]; - UCHAR tx_data_length[2]; - UCHAR dest_addr[ADDRLEN]; - UCHAR pow_sav_mode; - UCHAR retries; - UCHAR station_id; -}; -struct memory_dump_cmd { - UCHAR memory_type; - UCHAR memory_ptr[2]; - UCHAR length; -}; -struct update_association_cmd { - UCHAR status; - UCHAR aid[2]; -}; -struct start_timer_cmd { - UCHAR duration[2]; -}; - -struct ccs { - UCHAR buffer_status; /* 0 = buffer free, 1 = buffer busy */ - /* 2 = command complete, 3 = failed */ - UCHAR cmd; /* command to ECF */ - UCHAR link; /* link to next CCS, FF=end of list */ - /* command specific parameters */ - union { - char reserved[13]; - struct update_param_cmd update_param; - struct report_param_cmd report_param; - UCHAR nummulticast; - UCHAR mode; - struct start_network_cmd start_network; - struct join_network_cmd join_network; - struct tx_requested_cmd tx_request; - struct memory_dump_cmd memory_dump; - struct update_association_cmd update_assoc; - struct start_timer_cmd start_timer; - } var; -}; - -/*****************************************************************************/ -/* Transmit buffer structures */ -struct tib_structure { - UCHAR ccs_index; - UCHAR psm; - UCHAR pass_fail; - UCHAR retry_count; - UCHAR max_retries; - UCHAR frags_remaining; - UCHAR no_rb; - UCHAR rts_reqd; - UCHAR csma_tx_cntrl_2; - UCHAR sifs_tx_cntrl_2; - UCHAR tx_dma_addr_1[2]; - UCHAR tx_dma_addr_2[2]; - UCHAR var_dur_2mhz[2]; - UCHAR var_dur_1mhz[2]; - UCHAR max_dur_2mhz[2]; - UCHAR max_dur_1mhz[2]; - UCHAR hdr_len; - UCHAR max_frag_len[2]; - UCHAR var_len[2]; - UCHAR phy_hdr_4; - UCHAR mac_hdr_1; - UCHAR mac_hdr_2; - UCHAR sid[2]; -}; - -struct phy_header { - UCHAR sfd[2]; - UCHAR hdr_3; - UCHAR hdr_4; -}; -struct rx_msg { - struct mac_header mac; - UCHAR var[1]; -}; - -struct tx_msg { - struct tib_structure tib; - struct phy_header phy; - struct mac_header mac; - UCHAR var[1]; -}; - -/****** ECF Receive Control Stucture (RCS) Area at Shared RAM offset 0x0800 */ -/* Structures for command specific parameters (rcs.var) */ -struct rx_packet_cmd { - UCHAR rx_data_ptr[2]; - UCHAR rx_data_length[2]; - UCHAR rx_sig_lev; - UCHAR next_frag_rcs_index; - UCHAR totalpacketlength[2]; -}; -struct rejoin_net_cmplt_cmd { - UCHAR reserved; - UCHAR bssid[ADDRLEN]; -}; -struct japan_call_sign_rxd { - UCHAR rxd_call_sign[8]; - UCHAR reserved[5]; -}; - -struct rcs { - UCHAR buffer_status; - UCHAR interrupt_id; - UCHAR link_field; - /* command specific parameters */ - union { - UCHAR reserved[13]; - struct rx_packet_cmd rx_packet; - struct rejoin_net_cmplt_cmd rejoin_net_complete; - struct japan_call_sign_rxd japan_call_sign; - } var; -}; - -/****** Startup parameter structures for both versions of firmware ***********/ -struct b4_startup_params { - UCHAR a_network_type; /* C_ADHOC, C_INFRA */ - UCHAR a_acting_as_ap_status; /* C_TYPE_STA, C_TYPE_AP */ - UCHAR a_current_ess_id[ESSID_SIZE]; /* Null terminated unless 32 long */ - UCHAR a_scanning_mode; /* passive 0, active 1 */ - UCHAR a_power_mgt_state; /* CAM 0, */ - UCHAR a_mac_addr[ADDRLEN]; /* */ - UCHAR a_frag_threshold[2]; /* 512 */ - UCHAR a_hop_time[2]; /* 16k * 2**n, n=0-4 in Kus */ - UCHAR a_beacon_period[2]; /* n * a_hop_time in Kus */ - UCHAR a_dtim_period; /* in beacons */ - UCHAR a_retry_max; /* */ - UCHAR a_ack_timeout; /* */ - UCHAR a_sifs; /* */ - UCHAR a_difs; /* */ - UCHAR a_pifs; /* */ - UCHAR a_rts_threshold[2]; /* */ - UCHAR a_scan_dwell_time[2]; /* */ - UCHAR a_max_scan_dwell_time[2]; /* */ - UCHAR a_assoc_resp_timeout_thresh; /* */ - UCHAR a_adhoc_scan_cycle_max; /* */ - UCHAR a_infra_scan_cycle_max; /* */ - UCHAR a_infra_super_scan_cycle_max; /* */ - UCHAR a_promiscuous_mode; /* */ - UCHAR a_unique_word[2]; /* */ - UCHAR a_slot_time; /* */ - UCHAR a_roaming_low_snr_thresh; /* */ - UCHAR a_low_snr_count_thresh; /* */ - UCHAR a_infra_missed_bcn_thresh; /* */ - UCHAR a_adhoc_missed_bcn_thresh; /* */ - UCHAR a_curr_country_code; /* C_USA */ - UCHAR a_hop_pattern; /* */ - UCHAR a_hop_pattern_length; /* */ -/* b4 - b5 differences start here */ - UCHAR a_cw_max; /* */ - UCHAR a_cw_min; /* */ - UCHAR a_noise_filter_gain; /* */ - UCHAR a_noise_limit_offset; /* */ - UCHAR a_det_rssi_thresh_offset; /* */ - UCHAR a_med_busy_thresh_offset; /* */ - UCHAR a_det_sync_thresh; /* */ - UCHAR a_test_mode; /* */ - UCHAR a_test_min_chan_num; /* */ - UCHAR a_test_max_chan_num; /* */ - UCHAR a_rx_tx_delay; /* */ - UCHAR a_current_bss_id[ADDRLEN]; /* */ - UCHAR a_hop_set; /* */ -}; -struct b5_startup_params { - UCHAR a_network_type; /* C_ADHOC, C_INFRA */ - UCHAR a_acting_as_ap_status; /* C_TYPE_STA, C_TYPE_AP */ - UCHAR a_current_ess_id[ESSID_SIZE]; /* Null terminated unless 32 long */ - UCHAR a_scanning_mode; /* passive 0, active 1 */ - UCHAR a_power_mgt_state; /* CAM 0, */ - UCHAR a_mac_addr[ADDRLEN]; /* */ - UCHAR a_frag_threshold[2]; /* 512 */ - UCHAR a_hop_time[2]; /* 16k * 2**n, n=0-4 in Kus */ - UCHAR a_beacon_period[2]; /* n * a_hop_time in Kus */ - UCHAR a_dtim_period; /* in beacons */ - UCHAR a_retry_max; /* 4 */ - UCHAR a_ack_timeout; /* */ - UCHAR a_sifs; /* */ - UCHAR a_difs; /* */ - UCHAR a_pifs; /* */ - UCHAR a_rts_threshold[2]; /* */ - UCHAR a_scan_dwell_time[2]; /* */ - UCHAR a_max_scan_dwell_time[2]; /* */ - UCHAR a_assoc_resp_timeout_thresh; /* */ - UCHAR a_adhoc_scan_cycle_max; /* */ - UCHAR a_infra_scan_cycle_max; /* */ - UCHAR a_infra_super_scan_cycle_max; /* */ - UCHAR a_promiscuous_mode; /* */ - UCHAR a_unique_word[2]; /* */ - UCHAR a_slot_time; /* */ - UCHAR a_roaming_low_snr_thresh; /* */ - UCHAR a_low_snr_count_thresh; /* */ - UCHAR a_infra_missed_bcn_thresh; /* */ - UCHAR a_adhoc_missed_bcn_thresh; /* */ - UCHAR a_curr_country_code; /* C_USA */ - UCHAR a_hop_pattern; /* */ - UCHAR a_hop_pattern_length; /* */ -/* b4 - b5 differences start here */ - UCHAR a_cw_max[2]; /* */ - UCHAR a_cw_min[2]; /* */ - UCHAR a_noise_filter_gain; /* */ - UCHAR a_noise_limit_offset; /* */ - UCHAR a_det_rssi_thresh_offset; /* */ - UCHAR a_med_busy_thresh_offset; /* */ - UCHAR a_det_sync_thresh; /* */ - UCHAR a_test_mode; /* */ - UCHAR a_test_min_chan_num; /* */ - UCHAR a_test_max_chan_num; /* */ - UCHAR a_allow_bcast_SSID_probe_rsp; - UCHAR a_privacy_must_start; - UCHAR a_privacy_can_join; - UCHAR a_basic_rate_set[8]; -}; - -/*****************************************************************************/ -#define RAY_IOCG_PARMS (SIOCDEVPRIVATE) -#define RAY_IOCS_PARMS (SIOCDEVPRIVATE + 1) -#define RAY_DO_CMD (SIOCDEVPRIVATE + 2) - -/****** ethernet <-> 802.11 translation **************************************/ -typedef struct snaphdr_t -{ - UCHAR dsap; - UCHAR ssap; - UCHAR ctrl; - UCHAR org[3]; - UCHAR ethertype[2]; -} snaphdr_t; - -#define BRIDGE_ENCAP 0xf80000 -#define RFC1042_ENCAP 0 -#define SNAP_ID 0x0003aaaa -#define RAY_IPX_TYPE 0x8137 -#define APPLEARP_TYPE 0x80f3 -/*****************************************************************************/ -#endif /* #ifndef RAYLINK_H */ diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c deleted file mode 100644 index 2ecbedb26e15..000000000000 --- a/drivers/net/wireless/rndis_wlan.c +++ /dev/null @@ -1,3062 +0,0 @@ -/* - * Driver for RNDIS based wireless USB devices. - * - * Copyright (C) 2007 by Bjorge Dijkstra - * Copyright (C) 2008-2009 by Jussi Kivilinna - * - * 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 - * - * Portions of this file are based on NDISwrapper project, - * Copyright (C) 2003-2005 Pontus Fuchs, Giridhar Pemmasani - * http://ndiswrapper.sourceforge.net/ - */ - -// #define DEBUG // error path messages, extra info -// #define VERBOSE // more; success messages - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -/* NOTE: All these are settings for Broadcom chipset */ -static char modparam_country[4] = "EU"; -module_param_string(country, modparam_country, 4, 0444); -MODULE_PARM_DESC(country, "Country code (ISO 3166-1 alpha-2), default: EU"); - -static int modparam_frameburst = 1; -module_param_named(frameburst, modparam_frameburst, int, 0444); -MODULE_PARM_DESC(frameburst, "enable frame bursting (default: on)"); - -static int modparam_afterburner = 0; -module_param_named(afterburner, modparam_afterburner, int, 0444); -MODULE_PARM_DESC(afterburner, - "enable afterburner aka '125 High Speed Mode' (default: off)"); - -static int modparam_power_save = 0; -module_param_named(power_save, modparam_power_save, int, 0444); -MODULE_PARM_DESC(power_save, - "set power save mode: 0=off, 1=on, 2=fast (default: off)"); - -static int modparam_power_output = 3; -module_param_named(power_output, modparam_power_output, int, 0444); -MODULE_PARM_DESC(power_output, - "set power output: 0=25%, 1=50%, 2=75%, 3=100% (default: 100%)"); - -static int modparam_roamtrigger = -70; -module_param_named(roamtrigger, modparam_roamtrigger, int, 0444); -MODULE_PARM_DESC(roamtrigger, - "set roaming dBm trigger: -80=optimize for distance, " - "-60=bandwidth (default: -70)"); - -static int modparam_roamdelta = 1; -module_param_named(roamdelta, modparam_roamdelta, int, 0444); -MODULE_PARM_DESC(roamdelta, - "set roaming tendency: 0=aggressive, 1=moderate, " - "2=conservative (default: moderate)"); - -static int modparam_workaround_interval; -module_param_named(workaround_interval, modparam_workaround_interval, - int, 0444); -MODULE_PARM_DESC(workaround_interval, - "set stall workaround interval in msecs (0=disabled) (default: 0)"); - - -/* various RNDIS OID defs */ -#define OID_GEN_LINK_SPEED cpu_to_le32(0x00010107) -#define OID_GEN_RNDIS_CONFIG_PARAMETER cpu_to_le32(0x0001021b) - -#define OID_GEN_XMIT_OK cpu_to_le32(0x00020101) -#define OID_GEN_RCV_OK cpu_to_le32(0x00020102) -#define OID_GEN_XMIT_ERROR cpu_to_le32(0x00020103) -#define OID_GEN_RCV_ERROR cpu_to_le32(0x00020104) -#define OID_GEN_RCV_NO_BUFFER cpu_to_le32(0x00020105) - -#define OID_802_3_CURRENT_ADDRESS cpu_to_le32(0x01010102) -#define OID_802_3_MULTICAST_LIST cpu_to_le32(0x01010103) -#define OID_802_3_MAXIMUM_LIST_SIZE cpu_to_le32(0x01010104) - -#define OID_802_11_BSSID cpu_to_le32(0x0d010101) -#define OID_802_11_SSID cpu_to_le32(0x0d010102) -#define OID_802_11_INFRASTRUCTURE_MODE cpu_to_le32(0x0d010108) -#define OID_802_11_ADD_WEP cpu_to_le32(0x0d010113) -#define OID_802_11_REMOVE_WEP cpu_to_le32(0x0d010114) -#define OID_802_11_DISASSOCIATE cpu_to_le32(0x0d010115) -#define OID_802_11_AUTHENTICATION_MODE cpu_to_le32(0x0d010118) -#define OID_802_11_PRIVACY_FILTER cpu_to_le32(0x0d010119) -#define OID_802_11_BSSID_LIST_SCAN cpu_to_le32(0x0d01011a) -#define OID_802_11_ENCRYPTION_STATUS cpu_to_le32(0x0d01011b) -#define OID_802_11_ADD_KEY cpu_to_le32(0x0d01011d) -#define OID_802_11_REMOVE_KEY cpu_to_le32(0x0d01011e) -#define OID_802_11_ASSOCIATION_INFORMATION cpu_to_le32(0x0d01011f) -#define OID_802_11_PMKID cpu_to_le32(0x0d010123) -#define OID_802_11_NETWORK_TYPES_SUPPORTED cpu_to_le32(0x0d010203) -#define OID_802_11_NETWORK_TYPE_IN_USE cpu_to_le32(0x0d010204) -#define OID_802_11_TX_POWER_LEVEL cpu_to_le32(0x0d010205) -#define OID_802_11_RSSI cpu_to_le32(0x0d010206) -#define OID_802_11_RSSI_TRIGGER cpu_to_le32(0x0d010207) -#define OID_802_11_FRAGMENTATION_THRESHOLD cpu_to_le32(0x0d010209) -#define OID_802_11_RTS_THRESHOLD cpu_to_le32(0x0d01020a) -#define OID_802_11_SUPPORTED_RATES cpu_to_le32(0x0d01020e) -#define OID_802_11_CONFIGURATION cpu_to_le32(0x0d010211) -#define OID_802_11_BSSID_LIST cpu_to_le32(0x0d010217) - - -/* Typical noise/maximum signal level values taken from ndiswrapper iw_ndis.h */ -#define WL_NOISE -96 /* typical noise level in dBm */ -#define WL_SIGMAX -32 /* typical maximum signal level in dBm */ - - -/* Assume that Broadcom 4320 (only chipset at time of writing known to be - * based on wireless rndis) has default txpower of 13dBm. - * This value is from Linksys WUSB54GSC User Guide, Appendix F: Specifications. - * 100% : 20 mW ~ 13dBm - * 75% : 15 mW ~ 12dBm - * 50% : 10 mW ~ 10dBm - * 25% : 5 mW ~ 7dBm - */ -#define BCM4320_DEFAULT_TXPOWER_DBM_100 13 -#define BCM4320_DEFAULT_TXPOWER_DBM_75 12 -#define BCM4320_DEFAULT_TXPOWER_DBM_50 10 -#define BCM4320_DEFAULT_TXPOWER_DBM_25 7 - - -/* codes for "status" field of completion messages */ -#define RNDIS_STATUS_ADAPTER_NOT_READY cpu_to_le32(0xc0010011) -#define RNDIS_STATUS_ADAPTER_NOT_OPEN cpu_to_le32(0xc0010012) - - -/* NDIS data structures. Taken from wpa_supplicant driver_ndis.c - * slightly modified for datatype endianess, etc - */ -#define NDIS_802_11_LENGTH_SSID 32 -#define NDIS_802_11_LENGTH_RATES 8 -#define NDIS_802_11_LENGTH_RATES_EX 16 - -enum ndis_80211_net_type { - NDIS_80211_TYPE_FREQ_HOP, - NDIS_80211_TYPE_DIRECT_SEQ, - NDIS_80211_TYPE_OFDM_A, - NDIS_80211_TYPE_OFDM_G -}; - -enum ndis_80211_net_infra { - NDIS_80211_INFRA_ADHOC, - NDIS_80211_INFRA_INFRA, - NDIS_80211_INFRA_AUTO_UNKNOWN -}; - -enum ndis_80211_auth_mode { - NDIS_80211_AUTH_OPEN, - NDIS_80211_AUTH_SHARED, - NDIS_80211_AUTH_AUTO_SWITCH, - NDIS_80211_AUTH_WPA, - NDIS_80211_AUTH_WPA_PSK, - NDIS_80211_AUTH_WPA_NONE, - NDIS_80211_AUTH_WPA2, - NDIS_80211_AUTH_WPA2_PSK -}; - -enum ndis_80211_encr_status { - NDIS_80211_ENCR_WEP_ENABLED, - NDIS_80211_ENCR_DISABLED, - NDIS_80211_ENCR_WEP_KEY_ABSENT, - NDIS_80211_ENCR_NOT_SUPPORTED, - NDIS_80211_ENCR_TKIP_ENABLED, - NDIS_80211_ENCR_TKIP_KEY_ABSENT, - NDIS_80211_ENCR_CCMP_ENABLED, - NDIS_80211_ENCR_CCMP_KEY_ABSENT -}; - -enum ndis_80211_priv_filter { - NDIS_80211_PRIV_ACCEPT_ALL, - NDIS_80211_PRIV_8021X_WEP -}; - -enum ndis_80211_status_type { - NDIS_80211_STATUSTYPE_AUTHENTICATION, - NDIS_80211_STATUSTYPE_MEDIASTREAMMODE, - NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST, - NDIS_80211_STATUSTYPE_RADIOSTATE, -}; - -enum ndis_80211_media_stream_mode { - NDIS_80211_MEDIA_STREAM_OFF, - NDIS_80211_MEDIA_STREAM_ON -}; - -enum ndis_80211_radio_status { - NDIS_80211_RADIO_STATUS_ON, - NDIS_80211_RADIO_STATUS_HARDWARE_OFF, - NDIS_80211_RADIO_STATUS_SOFTWARE_OFF, -}; - -enum ndis_80211_addkey_bits { - NDIS_80211_ADDKEY_8021X_AUTH = cpu_to_le32(1 << 28), - NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ = cpu_to_le32(1 << 29), - NDIS_80211_ADDKEY_PAIRWISE_KEY = cpu_to_le32(1 << 30), - NDIS_80211_ADDKEY_TRANSMIT_KEY = cpu_to_le32(1 << 31) -}; - -enum ndis_80211_addwep_bits { - NDIS_80211_ADDWEP_PERCLIENT_KEY = cpu_to_le32(1 << 30), - NDIS_80211_ADDWEP_TRANSMIT_KEY = cpu_to_le32(1 << 31) -}; - -struct ndis_80211_auth_request { - __le32 length; - u8 bssid[6]; - u8 padding[2]; - __le32 flags; -} __attribute__((packed)); - -struct ndis_80211_pmkid_candidate { - u8 bssid[6]; - u8 padding[2]; - __le32 flags; -} __attribute__((packed)); - -struct ndis_80211_pmkid_cand_list { - __le32 version; - __le32 num_candidates; - struct ndis_80211_pmkid_candidate candidate_list[0]; -} __attribute__((packed)); - -struct ndis_80211_status_indication { - __le32 status_type; - union { - __le32 media_stream_mode; - __le32 radio_status; - struct ndis_80211_auth_request auth_request[0]; - struct ndis_80211_pmkid_cand_list cand_list; - } u; -} __attribute__((packed)); - -struct ndis_80211_ssid { - __le32 length; - u8 essid[NDIS_802_11_LENGTH_SSID]; -} __attribute__((packed)); - -struct ndis_80211_conf_freq_hop { - __le32 length; - __le32 hop_pattern; - __le32 hop_set; - __le32 dwell_time; -} __attribute__((packed)); - -struct ndis_80211_conf { - __le32 length; - __le32 beacon_period; - __le32 atim_window; - __le32 ds_config; - struct ndis_80211_conf_freq_hop fh_config; -} __attribute__((packed)); - -struct ndis_80211_bssid_ex { - __le32 length; - u8 mac[6]; - u8 padding[2]; - struct ndis_80211_ssid ssid; - __le32 privacy; - __le32 rssi; - __le32 net_type; - struct ndis_80211_conf config; - __le32 net_infra; - u8 rates[NDIS_802_11_LENGTH_RATES_EX]; - __le32 ie_length; - u8 ies[0]; -} __attribute__((packed)); - -struct ndis_80211_bssid_list_ex { - __le32 num_items; - struct ndis_80211_bssid_ex bssid[0]; -} __attribute__((packed)); - -struct ndis_80211_fixed_ies { - u8 timestamp[8]; - __le16 beacon_interval; - __le16 capabilities; -} __attribute__((packed)); - -struct ndis_80211_wep_key { - __le32 size; - __le32 index; - __le32 length; - u8 material[32]; -} __attribute__((packed)); - -struct ndis_80211_key { - __le32 size; - __le32 index; - __le32 length; - u8 bssid[6]; - u8 padding[6]; - u8 rsc[8]; - u8 material[32]; -} __attribute__((packed)); - -struct ndis_80211_remove_key { - __le32 size; - __le32 index; - u8 bssid[6]; - u8 padding[2]; -} __attribute__((packed)); - -struct ndis_config_param { - __le32 name_offs; - __le32 name_length; - __le32 type; - __le32 value_offs; - __le32 value_length; -} __attribute__((packed)); - -struct ndis_80211_assoc_info { - __le32 length; - __le16 req_ies; - struct req_ie { - __le16 capa; - __le16 listen_interval; - u8 cur_ap_address[6]; - } req_ie; - __le32 req_ie_length; - __le32 offset_req_ies; - __le16 resp_ies; - struct resp_ie { - __le16 capa; - __le16 status_code; - __le16 assoc_id; - } resp_ie; - __le32 resp_ie_length; - __le32 offset_resp_ies; -} __attribute__((packed)); - -/* - * private data - */ -#define NET_TYPE_11FB 0 - -#define CAP_MODE_80211A 1 -#define CAP_MODE_80211B 2 -#define CAP_MODE_80211G 4 -#define CAP_MODE_MASK 7 - -#define WORK_LINK_UP (1<<0) -#define WORK_LINK_DOWN (1<<1) -#define WORK_SET_MULTICAST_LIST (1<<2) - -#define RNDIS_WLAN_ALG_NONE 0 -#define RNDIS_WLAN_ALG_WEP (1<<0) -#define RNDIS_WLAN_ALG_TKIP (1<<1) -#define RNDIS_WLAN_ALG_CCMP (1<<2) - -#define RNDIS_WLAN_KEY_MGMT_NONE 0 -#define RNDIS_WLAN_KEY_MGMT_802_1X (1<<0) -#define RNDIS_WLAN_KEY_MGMT_PSK (1<<1) - -#define COMMAND_BUFFER_SIZE (CONTROL_BUFFER_SIZE + sizeof(struct rndis_set)) - -static const struct ieee80211_channel rndis_channels[] = { - { .center_freq = 2412 }, - { .center_freq = 2417 }, - { .center_freq = 2422 }, - { .center_freq = 2427 }, - { .center_freq = 2432 }, - { .center_freq = 2437 }, - { .center_freq = 2442 }, - { .center_freq = 2447 }, - { .center_freq = 2452 }, - { .center_freq = 2457 }, - { .center_freq = 2462 }, - { .center_freq = 2467 }, - { .center_freq = 2472 }, - { .center_freq = 2484 }, -}; - -static const struct ieee80211_rate rndis_rates[] = { - { .bitrate = 10 }, - { .bitrate = 20, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60 }, - { .bitrate = 90 }, - { .bitrate = 120 }, - { .bitrate = 180 }, - { .bitrate = 240 }, - { .bitrate = 360 }, - { .bitrate = 480 }, - { .bitrate = 540 } -}; - -static const u32 rndis_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, -}; - -struct rndis_wlan_encr_key { - int len; - u32 cipher; - u8 material[32]; - u8 bssid[ETH_ALEN]; - bool pairwise; - bool tx_key; -}; - -/* RNDIS device private data */ -struct rndis_wlan_private { - struct usbnet *usbdev; - - struct wireless_dev wdev; - - struct cfg80211_scan_request *scan_request; - - struct workqueue_struct *workqueue; - struct delayed_work dev_poller_work; - struct delayed_work scan_work; - struct work_struct work; - struct mutex command_lock; - unsigned long work_pending; - int last_qual; - - struct ieee80211_supported_band band; - struct ieee80211_channel channels[ARRAY_SIZE(rndis_channels)]; - struct ieee80211_rate rates[ARRAY_SIZE(rndis_rates)]; - u32 cipher_suites[ARRAY_SIZE(rndis_cipher_suites)]; - - int caps; - int multicast_size; - - /* module parameters */ - char param_country[4]; - int param_frameburst; - int param_afterburner; - int param_power_save; - int param_power_output; - int param_roamtrigger; - int param_roamdelta; - u32 param_workaround_interval; - - /* hardware state */ - bool radio_on; - int infra_mode; - bool connected; - u8 bssid[ETH_ALEN]; - struct ndis_80211_ssid essid; - __le32 current_command_oid; - - /* encryption stuff */ - int encr_tx_key_index; - struct rndis_wlan_encr_key encr_keys[4]; - enum nl80211_auth_type wpa_auth_type; - int wpa_version; - int wpa_keymgmt; - int wpa_ie_len; - u8 *wpa_ie; - int wpa_cipher_pair; - int wpa_cipher_group; - - u8 command_buffer[COMMAND_BUFFER_SIZE]; -}; - -/* - * cfg80211 ops - */ -static int rndis_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params); - -static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request); - -static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed); - -static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, - int dbm); -static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm); - -static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme); - -static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code); - -static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params); - -static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev); - -static int rndis_set_channel(struct wiphy *wiphy, - struct ieee80211_channel *chan, enum nl80211_channel_type channel_type); - -static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, const u8 *mac_addr, - struct key_params *params); - -static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, const u8 *mac_addr); - -static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index); - -static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_info *sinfo); - -static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, - int idx, u8 *mac, struct station_info *sinfo); - -static struct cfg80211_ops rndis_config_ops = { - .change_virtual_intf = rndis_change_virtual_intf, - .scan = rndis_scan, - .set_wiphy_params = rndis_set_wiphy_params, - .set_tx_power = rndis_set_tx_power, - .get_tx_power = rndis_get_tx_power, - .connect = rndis_connect, - .disconnect = rndis_disconnect, - .join_ibss = rndis_join_ibss, - .leave_ibss = rndis_leave_ibss, - .set_channel = rndis_set_channel, - .add_key = rndis_add_key, - .del_key = rndis_del_key, - .set_default_key = rndis_set_default_key, - .get_station = rndis_get_station, - .dump_station = rndis_dump_station, -}; - -static void *rndis_wiphy_privid = &rndis_wiphy_privid; - - -static struct rndis_wlan_private *get_rndis_wlan_priv(struct usbnet *dev) -{ - return (struct rndis_wlan_private *)dev->driver_priv; -} - -static u32 get_bcm4320_power_dbm(struct rndis_wlan_private *priv) -{ - switch (priv->param_power_output) { - default: - case 3: - return BCM4320_DEFAULT_TXPOWER_DBM_100; - case 2: - return BCM4320_DEFAULT_TXPOWER_DBM_75; - case 1: - return BCM4320_DEFAULT_TXPOWER_DBM_50; - case 0: - return BCM4320_DEFAULT_TXPOWER_DBM_25; - } -} - -static bool is_wpa_key(struct rndis_wlan_private *priv, int idx) -{ - int cipher = priv->encr_keys[idx].cipher; - - return (cipher == WLAN_CIPHER_SUITE_CCMP || - cipher == WLAN_CIPHER_SUITE_TKIP); -} - -static int rndis_cipher_to_alg(u32 cipher) -{ - switch (cipher) { - default: - return RNDIS_WLAN_ALG_NONE; - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - return RNDIS_WLAN_ALG_WEP; - case WLAN_CIPHER_SUITE_TKIP: - return RNDIS_WLAN_ALG_TKIP; - case WLAN_CIPHER_SUITE_CCMP: - return RNDIS_WLAN_ALG_CCMP; - } -} - -static int rndis_akm_suite_to_key_mgmt(u32 akm_suite) -{ - switch (akm_suite) { - default: - return RNDIS_WLAN_KEY_MGMT_NONE; - case WLAN_AKM_SUITE_8021X: - return RNDIS_WLAN_KEY_MGMT_802_1X; - case WLAN_AKM_SUITE_PSK: - return RNDIS_WLAN_KEY_MGMT_PSK; - } -} - -#ifdef DEBUG -static const char *oid_to_string(__le32 oid) -{ - switch (oid) { -#define OID_STR(oid) case oid: return(#oid) - /* from rndis_host.h */ - OID_STR(OID_802_3_PERMANENT_ADDRESS); - OID_STR(OID_GEN_MAXIMUM_FRAME_SIZE); - OID_STR(OID_GEN_CURRENT_PACKET_FILTER); - OID_STR(OID_GEN_PHYSICAL_MEDIUM); - - /* from rndis_wlan.c */ - OID_STR(OID_GEN_LINK_SPEED); - OID_STR(OID_GEN_RNDIS_CONFIG_PARAMETER); - - OID_STR(OID_GEN_XMIT_OK); - OID_STR(OID_GEN_RCV_OK); - OID_STR(OID_GEN_XMIT_ERROR); - OID_STR(OID_GEN_RCV_ERROR); - OID_STR(OID_GEN_RCV_NO_BUFFER); - - OID_STR(OID_802_3_CURRENT_ADDRESS); - OID_STR(OID_802_3_MULTICAST_LIST); - OID_STR(OID_802_3_MAXIMUM_LIST_SIZE); - - OID_STR(OID_802_11_BSSID); - OID_STR(OID_802_11_SSID); - OID_STR(OID_802_11_INFRASTRUCTURE_MODE); - OID_STR(OID_802_11_ADD_WEP); - OID_STR(OID_802_11_REMOVE_WEP); - OID_STR(OID_802_11_DISASSOCIATE); - OID_STR(OID_802_11_AUTHENTICATION_MODE); - OID_STR(OID_802_11_PRIVACY_FILTER); - OID_STR(OID_802_11_BSSID_LIST_SCAN); - OID_STR(OID_802_11_ENCRYPTION_STATUS); - OID_STR(OID_802_11_ADD_KEY); - OID_STR(OID_802_11_REMOVE_KEY); - OID_STR(OID_802_11_ASSOCIATION_INFORMATION); - OID_STR(OID_802_11_PMKID); - OID_STR(OID_802_11_NETWORK_TYPES_SUPPORTED); - OID_STR(OID_802_11_NETWORK_TYPE_IN_USE); - OID_STR(OID_802_11_TX_POWER_LEVEL); - OID_STR(OID_802_11_RSSI); - OID_STR(OID_802_11_RSSI_TRIGGER); - OID_STR(OID_802_11_FRAGMENTATION_THRESHOLD); - OID_STR(OID_802_11_RTS_THRESHOLD); - OID_STR(OID_802_11_SUPPORTED_RATES); - OID_STR(OID_802_11_CONFIGURATION); - OID_STR(OID_802_11_BSSID_LIST); -#undef OID_STR - } - - return "?"; -} -#else -static const char *oid_to_string(__le32 oid) -{ - return "?"; -} -#endif - -/* translate error code */ -static int rndis_error_status(__le32 rndis_status) -{ - int ret = -EINVAL; - switch (rndis_status) { - case RNDIS_STATUS_SUCCESS: - ret = 0; - break; - case RNDIS_STATUS_FAILURE: - case RNDIS_STATUS_INVALID_DATA: - ret = -EINVAL; - break; - case RNDIS_STATUS_NOT_SUPPORTED: - ret = -EOPNOTSUPP; - break; - case RNDIS_STATUS_ADAPTER_NOT_READY: - case RNDIS_STATUS_ADAPTER_NOT_OPEN: - ret = -EBUSY; - break; - } - return ret; -} - -static int rndis_query_oid(struct usbnet *dev, __le32 oid, void *data, int *len) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); - union { - void *buf; - struct rndis_msg_hdr *header; - struct rndis_query *get; - struct rndis_query_c *get_c; - } u; - int ret, buflen; - - buflen = *len + sizeof(*u.get); - if (buflen < CONTROL_BUFFER_SIZE) - buflen = CONTROL_BUFFER_SIZE; - - if (buflen > COMMAND_BUFFER_SIZE) { - u.buf = kmalloc(buflen, GFP_KERNEL); - if (!u.buf) - return -ENOMEM; - } else { - u.buf = priv->command_buffer; - } - - mutex_lock(&priv->command_lock); - - memset(u.get, 0, sizeof *u.get); - u.get->msg_type = RNDIS_MSG_QUERY; - u.get->msg_len = cpu_to_le32(sizeof *u.get); - u.get->oid = oid; - - priv->current_command_oid = oid; - ret = rndis_command(dev, u.header, buflen); - priv->current_command_oid = 0; - if (ret < 0) - devdbg(dev, "rndis_query_oid(%s): rndis_command() failed, %d " - "(%08x)", oid_to_string(oid), ret, - le32_to_cpu(u.get_c->status)); - - if (ret == 0) { - memcpy(data, u.buf + le32_to_cpu(u.get_c->offset) + 8, *len); - - ret = le32_to_cpu(u.get_c->len); - if (ret > *len) - *len = ret; - - ret = rndis_error_status(u.get_c->status); - if (ret < 0) - devdbg(dev, "rndis_query_oid(%s): device returned " - "error, 0x%08x (%d)", oid_to_string(oid), - le32_to_cpu(u.get_c->status), ret); - } - - mutex_unlock(&priv->command_lock); - - if (u.buf != priv->command_buffer) - kfree(u.buf); - return ret; -} - -static int rndis_set_oid(struct usbnet *dev, __le32 oid, void *data, int len) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(dev); - union { - void *buf; - struct rndis_msg_hdr *header; - struct rndis_set *set; - struct rndis_set_c *set_c; - } u; - int ret, buflen; - - buflen = len + sizeof(*u.set); - if (buflen < CONTROL_BUFFER_SIZE) - buflen = CONTROL_BUFFER_SIZE; - - if (buflen > COMMAND_BUFFER_SIZE) { - u.buf = kmalloc(buflen, GFP_KERNEL); - if (!u.buf) - return -ENOMEM; - } else { - u.buf = priv->command_buffer; - } - - mutex_lock(&priv->command_lock); - - memset(u.set, 0, sizeof *u.set); - u.set->msg_type = RNDIS_MSG_SET; - u.set->msg_len = cpu_to_le32(sizeof(*u.set) + len); - u.set->oid = oid; - u.set->len = cpu_to_le32(len); - u.set->offset = cpu_to_le32(sizeof(*u.set) - 8); - u.set->handle = cpu_to_le32(0); - memcpy(u.buf + sizeof(*u.set), data, len); - - priv->current_command_oid = oid; - ret = rndis_command(dev, u.header, buflen); - priv->current_command_oid = 0; - if (ret < 0) - devdbg(dev, "rndis_set_oid(%s): rndis_command() failed, %d " - "(%08x)", oid_to_string(oid), ret, - le32_to_cpu(u.set_c->status)); - - if (ret == 0) { - ret = rndis_error_status(u.set_c->status); - - if (ret < 0) - devdbg(dev, "rndis_set_oid(%s): device returned error, " - "0x%08x (%d)", oid_to_string(oid), - le32_to_cpu(u.set_c->status), ret); - } - - mutex_unlock(&priv->command_lock); - - if (u.buf != priv->command_buffer) - kfree(u.buf); - return ret; -} - -static int rndis_reset(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct rndis_reset *reset; - int ret; - - mutex_lock(&priv->command_lock); - - reset = (void *)priv->command_buffer; - memset(reset, 0, sizeof(*reset)); - reset->msg_type = RNDIS_MSG_RESET; - reset->msg_len = cpu_to_le32(sizeof(*reset)); - priv->current_command_oid = 0; - ret = rndis_command(usbdev, (void *)reset, CONTROL_BUFFER_SIZE); - - mutex_unlock(&priv->command_lock); - - if (ret < 0) - return ret; - return 0; -} - -/* - * Specs say that we can only set config parameters only soon after device - * initialization. - * value_type: 0 = u32, 2 = unicode string - */ -static int rndis_set_config_parameter(struct usbnet *dev, char *param, - int value_type, void *value) -{ - struct ndis_config_param *infobuf; - int value_len, info_len, param_len, ret, i; - __le16 *unibuf; - __le32 *dst_value; - - if (value_type == 0) - value_len = sizeof(__le32); - else if (value_type == 2) - value_len = strlen(value) * sizeof(__le16); - else - return -EINVAL; - - param_len = strlen(param) * sizeof(__le16); - info_len = sizeof(*infobuf) + param_len + value_len; - -#ifdef DEBUG - info_len += 12; -#endif - infobuf = kmalloc(info_len, GFP_KERNEL); - if (!infobuf) - return -ENOMEM; - -#ifdef DEBUG - info_len -= 12; - /* extra 12 bytes are for padding (debug output) */ - memset(infobuf, 0xCC, info_len + 12); -#endif - - if (value_type == 2) - devdbg(dev, "setting config parameter: %s, value: %s", - param, (u8 *)value); - else - devdbg(dev, "setting config parameter: %s, value: %d", - param, *(u32 *)value); - - infobuf->name_offs = cpu_to_le32(sizeof(*infobuf)); - infobuf->name_length = cpu_to_le32(param_len); - infobuf->type = cpu_to_le32(value_type); - infobuf->value_offs = cpu_to_le32(sizeof(*infobuf) + param_len); - infobuf->value_length = cpu_to_le32(value_len); - - /* simple string to unicode string conversion */ - unibuf = (void *)infobuf + sizeof(*infobuf); - for (i = 0; i < param_len / sizeof(__le16); i++) - unibuf[i] = cpu_to_le16(param[i]); - - if (value_type == 2) { - unibuf = (void *)infobuf + sizeof(*infobuf) + param_len; - for (i = 0; i < value_len / sizeof(__le16); i++) - unibuf[i] = cpu_to_le16(((u8 *)value)[i]); - } else { - dst_value = (void *)infobuf + sizeof(*infobuf) + param_len; - *dst_value = cpu_to_le32(*(u32 *)value); - } - -#ifdef DEBUG - devdbg(dev, "info buffer (len: %d):", info_len); - for (i = 0; i < info_len; i += 12) { - u32 *tmp = (u32 *)((u8 *)infobuf + i); - devdbg(dev, "%08X:%08X:%08X", - cpu_to_be32(tmp[0]), - cpu_to_be32(tmp[1]), - cpu_to_be32(tmp[2])); - } -#endif - - ret = rndis_set_oid(dev, OID_GEN_RNDIS_CONFIG_PARAMETER, - infobuf, info_len); - if (ret != 0) - devdbg(dev, "setting rndis config parameter failed, %d.", ret); - - kfree(infobuf); - return ret; -} - -static int rndis_set_config_parameter_str(struct usbnet *dev, - char *param, char *value) -{ - return rndis_set_config_parameter(dev, param, 2, value); -} - -/* - * data conversion functions - */ -static int level_to_qual(int level) -{ - int qual = 100 * (level - WL_NOISE) / (WL_SIGMAX - WL_NOISE); - return qual >= 0 ? (qual <= 100 ? qual : 100) : 0; -} - -/* - * common functions - */ -static int set_infra_mode(struct usbnet *usbdev, int mode); -static void restore_keys(struct usbnet *usbdev); -static int rndis_check_bssid_list(struct usbnet *usbdev); - -static int set_essid(struct usbnet *usbdev, struct ndis_80211_ssid *ssid) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - int ret; - - ret = rndis_set_oid(usbdev, OID_802_11_SSID, ssid, sizeof(*ssid)); - if (ret < 0) { - devwarn(usbdev, "setting SSID failed (%08X)", ret); - return ret; - } - if (ret == 0) { - memcpy(&priv->essid, ssid, sizeof(priv->essid)); - priv->radio_on = true; - devdbg(usbdev, "set_essid: radio_on = true"); - } - - return ret; -} - -static int set_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) -{ - int ret; - - ret = rndis_set_oid(usbdev, OID_802_11_BSSID, bssid, ETH_ALEN); - if (ret < 0) { - devwarn(usbdev, "setting BSSID[%pM] failed (%08X)", bssid, ret); - return ret; - } - - return ret; -} - -static int clear_bssid(struct usbnet *usbdev) -{ - u8 broadcast_mac[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - - return set_bssid(usbdev, broadcast_mac); -} - -static int get_bssid(struct usbnet *usbdev, u8 bssid[ETH_ALEN]) -{ - int ret, len; - - len = ETH_ALEN; - ret = rndis_query_oid(usbdev, OID_802_11_BSSID, bssid, &len); - - if (ret != 0) - memset(bssid, 0, ETH_ALEN); - - return ret; -} - -static int get_association_info(struct usbnet *usbdev, - struct ndis_80211_assoc_info *info, int len) -{ - return rndis_query_oid(usbdev, OID_802_11_ASSOCIATION_INFORMATION, - info, &len); -} - -static bool is_associated(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - u8 bssid[ETH_ALEN]; - int ret; - - if (!priv->radio_on) - return false; - - ret = get_bssid(usbdev, bssid); - - return (ret == 0 && !is_zero_ether_addr(bssid)); -} - -static int disassociate(struct usbnet *usbdev, bool reset_ssid) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ndis_80211_ssid ssid; - int i, ret = 0; - - if (priv->radio_on) { - ret = rndis_set_oid(usbdev, OID_802_11_DISASSOCIATE, NULL, 0); - if (ret == 0) { - priv->radio_on = false; - devdbg(usbdev, "disassociate: radio_on = false"); - - if (reset_ssid) - msleep(100); - } - } - - /* disassociate causes radio to be turned off; if reset_ssid - * is given, set random ssid to enable radio */ - if (reset_ssid) { - /* Set device to infrastructure mode so we don't get ad-hoc - * 'media connect' indications with the random ssid. - */ - set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA); - - ssid.length = cpu_to_le32(sizeof(ssid.essid)); - get_random_bytes(&ssid.essid[2], sizeof(ssid.essid)-2); - ssid.essid[0] = 0x1; - ssid.essid[1] = 0xff; - for (i = 2; i < sizeof(ssid.essid); i++) - ssid.essid[i] = 0x1 + (ssid.essid[i] * 0xfe / 0xff); - ret = set_essid(usbdev, &ssid); - } - return ret; -} - -static int set_auth_mode(struct usbnet *usbdev, u32 wpa_version, - enum nl80211_auth_type auth_type, int keymgmt) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - __le32 tmp; - int auth_mode, ret; - - devdbg(usbdev, "set_auth_mode: wpa_version=0x%x authalg=0x%x " - "keymgmt=0x%x", wpa_version, auth_type, keymgmt); - - if (wpa_version & NL80211_WPA_VERSION_2) { - if (keymgmt & RNDIS_WLAN_KEY_MGMT_802_1X) - auth_mode = NDIS_80211_AUTH_WPA2; - else - auth_mode = NDIS_80211_AUTH_WPA2_PSK; - } else if (wpa_version & NL80211_WPA_VERSION_1) { - if (keymgmt & RNDIS_WLAN_KEY_MGMT_802_1X) - auth_mode = NDIS_80211_AUTH_WPA; - else if (keymgmt & RNDIS_WLAN_KEY_MGMT_PSK) - auth_mode = NDIS_80211_AUTH_WPA_PSK; - else - auth_mode = NDIS_80211_AUTH_WPA_NONE; - } else if (auth_type == NL80211_AUTHTYPE_SHARED_KEY) - auth_mode = NDIS_80211_AUTH_SHARED; - else if (auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) - auth_mode = NDIS_80211_AUTH_OPEN; - else if (auth_type == NL80211_AUTHTYPE_AUTOMATIC) - auth_mode = NDIS_80211_AUTH_AUTO_SWITCH; - else - return -ENOTSUPP; - - tmp = cpu_to_le32(auth_mode); - ret = rndis_set_oid(usbdev, OID_802_11_AUTHENTICATION_MODE, &tmp, - sizeof(tmp)); - if (ret != 0) { - devwarn(usbdev, "setting auth mode failed (%08X)", ret); - return ret; - } - - priv->wpa_version = wpa_version; - priv->wpa_auth_type = auth_type; - priv->wpa_keymgmt = keymgmt; - - return 0; -} - -static int set_priv_filter(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - __le32 tmp; - - devdbg(usbdev, "set_priv_filter: wpa_version=0x%x", priv->wpa_version); - - if (priv->wpa_version & NL80211_WPA_VERSION_2 || - priv->wpa_version & NL80211_WPA_VERSION_1) - tmp = cpu_to_le32(NDIS_80211_PRIV_8021X_WEP); - else - tmp = cpu_to_le32(NDIS_80211_PRIV_ACCEPT_ALL); - - return rndis_set_oid(usbdev, OID_802_11_PRIVACY_FILTER, &tmp, - sizeof(tmp)); -} - -static int set_encr_mode(struct usbnet *usbdev, int pairwise, int groupwise) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - __le32 tmp; - int encr_mode, ret; - - devdbg(usbdev, "set_encr_mode: cipher_pair=0x%x cipher_group=0x%x", - pairwise, groupwise); - - if (pairwise & RNDIS_WLAN_ALG_CCMP) - encr_mode = NDIS_80211_ENCR_CCMP_ENABLED; - else if (pairwise & RNDIS_WLAN_ALG_TKIP) - encr_mode = NDIS_80211_ENCR_TKIP_ENABLED; - else if (pairwise & RNDIS_WLAN_ALG_WEP) - encr_mode = NDIS_80211_ENCR_WEP_ENABLED; - else if (groupwise & RNDIS_WLAN_ALG_CCMP) - encr_mode = NDIS_80211_ENCR_CCMP_ENABLED; - else if (groupwise & RNDIS_WLAN_ALG_TKIP) - encr_mode = NDIS_80211_ENCR_TKIP_ENABLED; - else - encr_mode = NDIS_80211_ENCR_DISABLED; - - tmp = cpu_to_le32(encr_mode); - ret = rndis_set_oid(usbdev, OID_802_11_ENCRYPTION_STATUS, &tmp, - sizeof(tmp)); - if (ret != 0) { - devwarn(usbdev, "setting encr mode failed (%08X)", ret); - return ret; - } - - priv->wpa_cipher_pair = pairwise; - priv->wpa_cipher_group = groupwise; - return 0; -} - -static int set_infra_mode(struct usbnet *usbdev, int mode) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - __le32 tmp; - int ret; - - devdbg(usbdev, "set_infra_mode: infra_mode=0x%x", priv->infra_mode); - - tmp = cpu_to_le32(mode); - ret = rndis_set_oid(usbdev, OID_802_11_INFRASTRUCTURE_MODE, &tmp, - sizeof(tmp)); - if (ret != 0) { - devwarn(usbdev, "setting infra mode failed (%08X)", ret); - return ret; - } - - /* NDIS drivers clear keys when infrastructure mode is - * changed. But Linux tools assume otherwise. So set the - * keys */ - restore_keys(usbdev); - - priv->infra_mode = mode; - return 0; -} - -static int set_rts_threshold(struct usbnet *usbdev, u32 rts_threshold) -{ - __le32 tmp; - - devdbg(usbdev, "set_rts_threshold %i", rts_threshold); - - if (rts_threshold < 0 || rts_threshold > 2347) - rts_threshold = 2347; - - tmp = cpu_to_le32(rts_threshold); - return rndis_set_oid(usbdev, OID_802_11_RTS_THRESHOLD, &tmp, - sizeof(tmp)); -} - -static int set_frag_threshold(struct usbnet *usbdev, u32 frag_threshold) -{ - __le32 tmp; - - devdbg(usbdev, "set_frag_threshold %i", frag_threshold); - - if (frag_threshold < 256 || frag_threshold > 2346) - frag_threshold = 2346; - - tmp = cpu_to_le32(frag_threshold); - return rndis_set_oid(usbdev, OID_802_11_FRAGMENTATION_THRESHOLD, &tmp, - sizeof(tmp)); -} - -static void set_default_iw_params(struct usbnet *usbdev) -{ - set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA); - set_auth_mode(usbdev, 0, NL80211_AUTHTYPE_OPEN_SYSTEM, - RNDIS_WLAN_KEY_MGMT_NONE); - set_priv_filter(usbdev); - set_encr_mode(usbdev, RNDIS_WLAN_ALG_NONE, RNDIS_WLAN_ALG_NONE); -} - -static int deauthenticate(struct usbnet *usbdev) -{ - int ret; - - ret = disassociate(usbdev, true); - set_default_iw_params(usbdev); - return ret; -} - -static int set_channel(struct usbnet *usbdev, int channel) -{ - struct ndis_80211_conf config; - unsigned int dsconfig; - int len, ret; - - devdbg(usbdev, "set_channel(%d)", channel); - - /* this OID is valid only when not associated */ - if (is_associated(usbdev)) - return 0; - - dsconfig = ieee80211_dsss_chan_to_freq(channel) * 1000; - - len = sizeof(config); - ret = rndis_query_oid(usbdev, OID_802_11_CONFIGURATION, &config, &len); - if (ret < 0) { - devdbg(usbdev, "set_channel: querying configuration failed"); - return ret; - } - - config.ds_config = cpu_to_le32(dsconfig); - ret = rndis_set_oid(usbdev, OID_802_11_CONFIGURATION, &config, - sizeof(config)); - - devdbg(usbdev, "set_channel: %d -> %d", channel, ret); - - return ret; -} - -/* index must be 0 - N, as per NDIS */ -static int add_wep_key(struct usbnet *usbdev, const u8 *key, int key_len, - int index) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ndis_80211_wep_key ndis_key; - u32 cipher; - int ret; - - devdbg(usbdev, "add_wep_key(idx: %d, len: %d)", index, key_len); - - if ((key_len != 5 && key_len != 13) || index < 0 || index > 3) - return -EINVAL; - - if (key_len == 5) - cipher = WLAN_CIPHER_SUITE_WEP40; - else - cipher = WLAN_CIPHER_SUITE_WEP104; - - memset(&ndis_key, 0, sizeof(ndis_key)); - - ndis_key.size = cpu_to_le32(sizeof(ndis_key)); - ndis_key.length = cpu_to_le32(key_len); - ndis_key.index = cpu_to_le32(index); - memcpy(&ndis_key.material, key, key_len); - - if (index == priv->encr_tx_key_index) { - ndis_key.index |= NDIS_80211_ADDWEP_TRANSMIT_KEY; - ret = set_encr_mode(usbdev, RNDIS_WLAN_ALG_WEP, - RNDIS_WLAN_ALG_NONE); - if (ret) - devwarn(usbdev, "encryption couldn't be enabled (%08X)", - ret); - } - - ret = rndis_set_oid(usbdev, OID_802_11_ADD_WEP, &ndis_key, - sizeof(ndis_key)); - if (ret != 0) { - devwarn(usbdev, "adding encryption key %d failed (%08X)", - index+1, ret); - return ret; - } - - priv->encr_keys[index].len = key_len; - priv->encr_keys[index].cipher = cipher; - memcpy(&priv->encr_keys[index].material, key, key_len); - memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN); - - return 0; -} - -static int add_wpa_key(struct usbnet *usbdev, const u8 *key, int key_len, - int index, const u8 *addr, const u8 *rx_seq, - int seq_len, u32 cipher, __le32 flags) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ndis_80211_key ndis_key; - bool is_addr_ok; - int ret; - - if (index < 0 || index >= 4) { - devdbg(usbdev, "add_wpa_key: index out of range (%i)", index); - return -EINVAL; - } - if (key_len > sizeof(ndis_key.material) || key_len < 0) { - devdbg(usbdev, "add_wpa_key: key length out of range (%i)", - key_len); - return -EINVAL; - } - if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) { - if (!rx_seq || seq_len <= 0) { - devdbg(usbdev, "add_wpa_key: recv seq flag without" - "buffer"); - return -EINVAL; - } - if (rx_seq && seq_len > sizeof(ndis_key.rsc)) { - devdbg(usbdev, "add_wpa_key: too big recv seq buffer"); - return -EINVAL; - } - } - - is_addr_ok = addr && !is_zero_ether_addr(addr) && - !is_broadcast_ether_addr(addr); - if ((flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) && !is_addr_ok) { - devdbg(usbdev, "add_wpa_key: pairwise but bssid invalid (%pM)", - addr); - return -EINVAL; - } - - devdbg(usbdev, "add_wpa_key(%i): flags:%i%i%i", index, - !!(flags & NDIS_80211_ADDKEY_TRANSMIT_KEY), - !!(flags & NDIS_80211_ADDKEY_PAIRWISE_KEY), - !!(flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ)); - - memset(&ndis_key, 0, sizeof(ndis_key)); - - ndis_key.size = cpu_to_le32(sizeof(ndis_key) - - sizeof(ndis_key.material) + key_len); - ndis_key.length = cpu_to_le32(key_len); - ndis_key.index = cpu_to_le32(index) | flags; - - if (cipher == WLAN_CIPHER_SUITE_TKIP && key_len == 32) { - /* wpa_supplicant gives us the Michael MIC RX/TX keys in - * different order than NDIS spec, so swap the order here. */ - memcpy(ndis_key.material, key, 16); - memcpy(ndis_key.material + 16, key + 24, 8); - memcpy(ndis_key.material + 24, key + 16, 8); - } else - memcpy(ndis_key.material, key, key_len); - - if (flags & NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ) - memcpy(ndis_key.rsc, rx_seq, seq_len); - - if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) { - /* pairwise key */ - memcpy(ndis_key.bssid, addr, ETH_ALEN); - } else { - /* group key */ - if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) - memset(ndis_key.bssid, 0xff, ETH_ALEN); - else - get_bssid(usbdev, ndis_key.bssid); - } - - ret = rndis_set_oid(usbdev, OID_802_11_ADD_KEY, &ndis_key, - le32_to_cpu(ndis_key.size)); - devdbg(usbdev, "add_wpa_key: OID_802_11_ADD_KEY -> %08X", ret); - if (ret != 0) - return ret; - - memset(&priv->encr_keys[index], 0, sizeof(priv->encr_keys[index])); - priv->encr_keys[index].len = key_len; - priv->encr_keys[index].cipher = cipher; - memcpy(&priv->encr_keys[index].material, key, key_len); - if (flags & NDIS_80211_ADDKEY_PAIRWISE_KEY) - memcpy(&priv->encr_keys[index].bssid, ndis_key.bssid, ETH_ALEN); - else - memset(&priv->encr_keys[index].bssid, 0xff, ETH_ALEN); - - if (flags & NDIS_80211_ADDKEY_TRANSMIT_KEY) - priv->encr_tx_key_index = index; - - return 0; -} - -static int restore_key(struct usbnet *usbdev, int key_idx) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct rndis_wlan_encr_key key; - - if (is_wpa_key(priv, key_idx)) - return 0; - - key = priv->encr_keys[key_idx]; - - devdbg(usbdev, "restore_key: %i:%i", key_idx, key.len); - - if (key.len == 0) - return 0; - - return add_wep_key(usbdev, key.material, key.len, key_idx); -} - -static void restore_keys(struct usbnet *usbdev) -{ - int i; - - for (i = 0; i < 4; i++) - restore_key(usbdev, i); -} - -static void clear_key(struct rndis_wlan_private *priv, int idx) -{ - memset(&priv->encr_keys[idx], 0, sizeof(priv->encr_keys[idx])); -} - -/* remove_key is for both wep and wpa */ -static int remove_key(struct usbnet *usbdev, int index, const u8 *bssid) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ndis_80211_remove_key remove_key; - __le32 keyindex; - bool is_wpa; - int ret; - - if (priv->encr_keys[index].len == 0) - return 0; - - is_wpa = is_wpa_key(priv, index); - - devdbg(usbdev, "remove_key: %i:%s:%i", index, is_wpa ? "wpa" : "wep", - priv->encr_keys[index].len); - - clear_key(priv, index); - - if (is_wpa) { - remove_key.size = cpu_to_le32(sizeof(remove_key)); - remove_key.index = cpu_to_le32(index); - if (bssid) { - /* pairwise key */ - if (!is_broadcast_ether_addr(bssid)) - remove_key.index |= - NDIS_80211_ADDKEY_PAIRWISE_KEY; - memcpy(remove_key.bssid, bssid, - sizeof(remove_key.bssid)); - } else - memset(remove_key.bssid, 0xff, - sizeof(remove_key.bssid)); - - ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_KEY, &remove_key, - sizeof(remove_key)); - if (ret != 0) - return ret; - } else { - keyindex = cpu_to_le32(index); - ret = rndis_set_oid(usbdev, OID_802_11_REMOVE_WEP, &keyindex, - sizeof(keyindex)); - if (ret != 0) { - devwarn(usbdev, - "removing encryption key %d failed (%08X)", - index, ret); - return ret; - } - } - - /* if it is transmit key, disable encryption */ - if (index == priv->encr_tx_key_index) - set_encr_mode(usbdev, RNDIS_WLAN_ALG_NONE, RNDIS_WLAN_ALG_NONE); - - return 0; -} - -static void set_multicast_list(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct dev_mc_list *mclist; - __le32 filter; - int ret, i, size; - char *buf; - - filter = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; - - if (usbdev->net->flags & IFF_PROMISC) { - filter |= RNDIS_PACKET_TYPE_PROMISCUOUS | - RNDIS_PACKET_TYPE_ALL_LOCAL; - } else if (usbdev->net->flags & IFF_ALLMULTI || - usbdev->net->mc_count > priv->multicast_size) { - filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; - } else if (usbdev->net->mc_count > 0) { - size = min(priv->multicast_size, usbdev->net->mc_count); - buf = kmalloc(size * ETH_ALEN, GFP_KERNEL); - if (!buf) { - devwarn(usbdev, - "couldn't alloc %d bytes of memory", - size * ETH_ALEN); - return; - } - - mclist = usbdev->net->mc_list; - for (i = 0; i < size && mclist; mclist = mclist->next) { - if (mclist->dmi_addrlen != ETH_ALEN) - continue; - - memcpy(buf + i * ETH_ALEN, mclist->dmi_addr, ETH_ALEN); - i++; - } - - ret = rndis_set_oid(usbdev, OID_802_3_MULTICAST_LIST, buf, - i * ETH_ALEN); - if (ret == 0 && i > 0) - filter |= RNDIS_PACKET_TYPE_MULTICAST; - else - filter |= RNDIS_PACKET_TYPE_ALL_MULTICAST; - - devdbg(usbdev, "OID_802_3_MULTICAST_LIST(%d, max: %d) -> %d", - i, priv->multicast_size, ret); - - kfree(buf); - } - - ret = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, - sizeof(filter)); - if (ret < 0) { - devwarn(usbdev, "couldn't set packet filter: %08x", - le32_to_cpu(filter)); - } - - devdbg(usbdev, "OID_GEN_CURRENT_PACKET_FILTER(%08x) -> %d", - le32_to_cpu(filter), ret); -} - -/* - * cfg80211 ops - */ -static int rndis_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - int mode; - - switch (type) { - case NL80211_IFTYPE_ADHOC: - mode = NDIS_80211_INFRA_ADHOC; - break; - case NL80211_IFTYPE_STATION: - mode = NDIS_80211_INFRA_INFRA; - break; - default: - return -EINVAL; - } - - priv->wdev.iftype = type; - - return set_infra_mode(usbdev, mode); -} - -static int rndis_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - int err; - - if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { - err = set_frag_threshold(usbdev, wiphy->frag_threshold); - if (err < 0) - return err; - } - - if (changed & WIPHY_PARAM_RTS_THRESHOLD) { - err = set_rts_threshold(usbdev, wiphy->rts_threshold); - if (err < 0) - return err; - } - - return 0; -} - -static int rndis_set_tx_power(struct wiphy *wiphy, enum tx_power_setting type, - int dbm) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - devdbg(usbdev, "rndis_set_tx_power type:0x%x dbm:%i", type, dbm); - - /* Device doesn't support changing txpower after initialization, only - * turn off/on radio. Support 'auto' mode and setting same dBm that is - * currently used. - */ - if (type == TX_POWER_AUTOMATIC || dbm == get_bcm4320_power_dbm(priv)) { - if (!priv->radio_on) - disassociate(usbdev, true); /* turn on radio */ - - return 0; - } - - return -ENOTSUPP; -} - -static int rndis_get_tx_power(struct wiphy *wiphy, int *dbm) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - *dbm = get_bcm4320_power_dbm(priv); - - devdbg(usbdev, "rndis_get_tx_power dbm:%i", *dbm); - - return 0; -} - -#define SCAN_DELAY_JIFFIES (6 * HZ) -static int rndis_scan(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_scan_request *request) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - int ret; - __le32 tmp; - - devdbg(usbdev, "cfg80211.scan"); - - /* Get current bssid list from device before new scan, as new scan - * clears internal bssid list. - */ - rndis_check_bssid_list(usbdev); - - if (!request) - return -EINVAL; - - if (priv->scan_request && priv->scan_request != request) - return -EBUSY; - - priv->scan_request = request; - - tmp = cpu_to_le32(1); - ret = rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, - sizeof(tmp)); - if (ret == 0) { - /* Wait before retrieving scan results from device */ - queue_delayed_work(priv->workqueue, &priv->scan_work, - SCAN_DELAY_JIFFIES); - } - - return ret; -} - -static struct cfg80211_bss *rndis_bss_info_update(struct usbnet *usbdev, - struct ndis_80211_bssid_ex *bssid) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ieee80211_channel *channel; - s32 signal; - u64 timestamp; - u16 capability; - u16 beacon_interval; - struct ndis_80211_fixed_ies *fixed; - int ie_len, bssid_len; - u8 *ie; - - devdbg(usbdev, " found bssid: '%.32s' [%pM]", bssid->ssid.essid, - bssid->mac); - - /* parse bssid structure */ - bssid_len = le32_to_cpu(bssid->length); - - if (bssid_len < sizeof(struct ndis_80211_bssid_ex) + - sizeof(struct ndis_80211_fixed_ies)) - return NULL; - - fixed = (struct ndis_80211_fixed_ies *)bssid->ies; - - ie = (void *)(bssid->ies + sizeof(struct ndis_80211_fixed_ies)); - ie_len = min(bssid_len - (int)sizeof(*bssid), - (int)le32_to_cpu(bssid->ie_length)); - ie_len -= sizeof(struct ndis_80211_fixed_ies); - if (ie_len < 0) - return NULL; - - /* extract data for cfg80211_inform_bss */ - channel = ieee80211_get_channel(priv->wdev.wiphy, - KHZ_TO_MHZ(le32_to_cpu(bssid->config.ds_config))); - if (!channel) - return NULL; - - signal = level_to_qual(le32_to_cpu(bssid->rssi)); - timestamp = le64_to_cpu(*(__le64 *)fixed->timestamp); - capability = le16_to_cpu(fixed->capabilities); - beacon_interval = le16_to_cpu(fixed->beacon_interval); - - return cfg80211_inform_bss(priv->wdev.wiphy, channel, bssid->mac, - timestamp, capability, beacon_interval, ie, ie_len, signal, - GFP_KERNEL); -} - -static int rndis_check_bssid_list(struct usbnet *usbdev) -{ - void *buf = NULL; - struct ndis_80211_bssid_list_ex *bssid_list; - struct ndis_80211_bssid_ex *bssid; - int ret = -EINVAL, len, count, bssid_len; - bool resized = false; - - devdbg(usbdev, "check_bssid_list"); - - len = CONTROL_BUFFER_SIZE; -resize_buf: - buf = kmalloc(len, GFP_KERNEL); - if (!buf) { - ret = -ENOMEM; - goto out; - } - - ret = rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); - if (ret != 0) - goto out; - - if (!resized && len > CONTROL_BUFFER_SIZE) { - resized = true; - kfree(buf); - goto resize_buf; - } - - bssid_list = buf; - bssid = bssid_list->bssid; - bssid_len = le32_to_cpu(bssid->length); - count = le32_to_cpu(bssid_list->num_items); - devdbg(usbdev, "check_bssid_list: %d BSSIDs found (buflen: %d)", count, - len); - - while (count && ((void *)bssid + bssid_len) <= (buf + len)) { - rndis_bss_info_update(usbdev, bssid); - - bssid = (void *)bssid + bssid_len; - bssid_len = le32_to_cpu(bssid->length); - count--; - } - -out: - kfree(buf); - return ret; -} - -static void rndis_get_scan_results(struct work_struct *work) -{ - struct rndis_wlan_private *priv = - container_of(work, struct rndis_wlan_private, scan_work.work); - struct usbnet *usbdev = priv->usbdev; - int ret; - - devdbg(usbdev, "get_scan_results"); - - if (!priv->scan_request) - return; - - ret = rndis_check_bssid_list(usbdev); - - cfg80211_scan_done(priv->scan_request, ret < 0); - - priv->scan_request = NULL; -} - -static int rndis_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - struct ieee80211_channel *channel = sme->channel; - struct ndis_80211_ssid ssid; - int pairwise = RNDIS_WLAN_ALG_NONE; - int groupwise = RNDIS_WLAN_ALG_NONE; - int keymgmt = RNDIS_WLAN_KEY_MGMT_NONE; - int length, i, ret, chan = -1; - - if (channel) - chan = ieee80211_frequency_to_channel(channel->center_freq); - - groupwise = rndis_cipher_to_alg(sme->crypto.cipher_group); - for (i = 0; i < sme->crypto.n_ciphers_pairwise; i++) - pairwise |= - rndis_cipher_to_alg(sme->crypto.ciphers_pairwise[i]); - - if (sme->crypto.n_ciphers_pairwise > 0 && - pairwise == RNDIS_WLAN_ALG_NONE) { - deverr(usbdev, "Unsupported pairwise cipher"); - return -ENOTSUPP; - } - - for (i = 0; i < sme->crypto.n_akm_suites; i++) - keymgmt |= - rndis_akm_suite_to_key_mgmt(sme->crypto.akm_suites[i]); - - if (sme->crypto.n_akm_suites > 0 && - keymgmt == RNDIS_WLAN_KEY_MGMT_NONE) { - deverr(usbdev, "Invalid keymgmt"); - return -ENOTSUPP; - } - - devdbg(usbdev, "cfg80211.connect('%.32s':[%pM]:%d:[%d,0x%x:0x%x]:[0x%x:" - "0x%x]:0x%x)", sme->ssid, sme->bssid, chan, - sme->privacy, sme->crypto.wpa_versions, sme->auth_type, - groupwise, pairwise, keymgmt); - - if (is_associated(usbdev)) - disassociate(usbdev, false); - - ret = set_infra_mode(usbdev, NDIS_80211_INFRA_INFRA); - if (ret < 0) { - devdbg(usbdev, "connect: set_infra_mode failed, %d", ret); - goto err_turn_radio_on; - } - - ret = set_auth_mode(usbdev, sme->crypto.wpa_versions, sme->auth_type, - keymgmt); - if (ret < 0) { - devdbg(usbdev, "connect: set_auth_mode failed, %d", ret); - goto err_turn_radio_on; - } - - set_priv_filter(usbdev); - - ret = set_encr_mode(usbdev, pairwise, groupwise); - if (ret < 0) { - devdbg(usbdev, "connect: set_encr_mode failed, %d", ret); - goto err_turn_radio_on; - } - - if (channel) { - ret = set_channel(usbdev, chan); - if (ret < 0) { - devdbg(usbdev, "connect: set_channel failed, %d", ret); - goto err_turn_radio_on; - } - } - - if (sme->key && ((groupwise | pairwise) & RNDIS_WLAN_ALG_WEP)) { - priv->encr_tx_key_index = sme->key_idx; - ret = add_wep_key(usbdev, sme->key, sme->key_len, sme->key_idx); - if (ret < 0) { - devdbg(usbdev, "connect: add_wep_key failed, %d " - "(%d, %d)", ret, sme->key_len, sme->key_idx); - goto err_turn_radio_on; - } - } - - if (sme->bssid && !is_zero_ether_addr(sme->bssid) && - !is_broadcast_ether_addr(sme->bssid)) { - ret = set_bssid(usbdev, sme->bssid); - if (ret < 0) { - devdbg(usbdev, "connect: set_bssid failed, %d", ret); - goto err_turn_radio_on; - } - } else - clear_bssid(usbdev); - - length = sme->ssid_len; - if (length > NDIS_802_11_LENGTH_SSID) - length = NDIS_802_11_LENGTH_SSID; - - memset(&ssid, 0, sizeof(ssid)); - ssid.length = cpu_to_le32(length); - memcpy(ssid.essid, sme->ssid, length); - - /* Pause and purge rx queue, so we don't pass packets before - * 'media connect'-indication. - */ - usbnet_pause_rx(usbdev); - usbnet_purge_paused_rxq(usbdev); - - ret = set_essid(usbdev, &ssid); - if (ret < 0) - devdbg(usbdev, "connect: set_essid failed, %d", ret); - return ret; - -err_turn_radio_on: - disassociate(usbdev, true); - - return ret; -} - -static int rndis_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - devdbg(usbdev, "cfg80211.disconnect(%d)", reason_code); - - priv->connected = false; - memset(priv->bssid, 0, ETH_ALEN); - - return deauthenticate(usbdev); -} - -static int rndis_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - struct ieee80211_channel *channel = params->channel; - struct ndis_80211_ssid ssid; - enum nl80211_auth_type auth_type; - int ret, alg, length, chan = -1; - - if (channel) - chan = ieee80211_frequency_to_channel(channel->center_freq); - - /* TODO: How to handle ad-hoc encryption? - * connect() has *key, join_ibss() doesn't. RNDIS requires key to be - * pre-shared for encryption (open/shared/wpa), is key set before - * join_ibss? Which auth_type to use (not in params)? What about WPA? - */ - if (params->privacy) { - auth_type = NL80211_AUTHTYPE_SHARED_KEY; - alg = RNDIS_WLAN_ALG_WEP; - } else { - auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - alg = RNDIS_WLAN_ALG_NONE; - } - - devdbg(usbdev, "cfg80211.join_ibss('%.32s':[%pM]:%d:%d)", params->ssid, - params->bssid, chan, params->privacy); - - if (is_associated(usbdev)) - disassociate(usbdev, false); - - ret = set_infra_mode(usbdev, NDIS_80211_INFRA_ADHOC); - if (ret < 0) { - devdbg(usbdev, "join_ibss: set_infra_mode failed, %d", ret); - goto err_turn_radio_on; - } - - ret = set_auth_mode(usbdev, 0, auth_type, RNDIS_WLAN_KEY_MGMT_NONE); - if (ret < 0) { - devdbg(usbdev, "join_ibss: set_auth_mode failed, %d", ret); - goto err_turn_radio_on; - } - - set_priv_filter(usbdev); - - ret = set_encr_mode(usbdev, alg, RNDIS_WLAN_ALG_NONE); - if (ret < 0) { - devdbg(usbdev, "join_ibss: set_encr_mode failed, %d", ret); - goto err_turn_radio_on; - } - - if (channel) { - ret = set_channel(usbdev, chan); - if (ret < 0) { - devdbg(usbdev, "join_ibss: set_channel failed, %d", - ret); - goto err_turn_radio_on; - } - } - - if (params->bssid && !is_zero_ether_addr(params->bssid) && - !is_broadcast_ether_addr(params->bssid)) { - ret = set_bssid(usbdev, params->bssid); - if (ret < 0) { - devdbg(usbdev, "join_ibss: set_bssid failed, %d", ret); - goto err_turn_radio_on; - } - } else - clear_bssid(usbdev); - - length = params->ssid_len; - if (length > NDIS_802_11_LENGTH_SSID) - length = NDIS_802_11_LENGTH_SSID; - - memset(&ssid, 0, sizeof(ssid)); - ssid.length = cpu_to_le32(length); - memcpy(ssid.essid, params->ssid, length); - - /* Don't need to pause rx queue for ad-hoc. */ - usbnet_purge_paused_rxq(usbdev); - usbnet_resume_rx(usbdev); - - ret = set_essid(usbdev, &ssid); - if (ret < 0) - devdbg(usbdev, "join_ibss: set_essid failed, %d", ret); - return ret; - -err_turn_radio_on: - disassociate(usbdev, true); - - return ret; -} - -static int rndis_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - devdbg(usbdev, "cfg80211.leave_ibss()"); - - priv->connected = false; - memset(priv->bssid, 0, ETH_ALEN); - - return deauthenticate(usbdev); -} - -static int rndis_set_channel(struct wiphy *wiphy, - struct ieee80211_channel *chan, enum nl80211_channel_type channel_type) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - return set_channel(usbdev, - ieee80211_frequency_to_channel(chan->center_freq)); -} - -static int rndis_add_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, const u8 *mac_addr, - struct key_params *params) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - __le32 flags; - - devdbg(usbdev, "rndis_add_key(%i, %pM, %08x)", key_index, mac_addr, - params->cipher); - - switch (params->cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - return add_wep_key(usbdev, params->key, params->key_len, - key_index); - case WLAN_CIPHER_SUITE_TKIP: - case WLAN_CIPHER_SUITE_CCMP: - flags = 0; - - if (params->seq && params->seq_len > 0) - flags |= NDIS_80211_ADDKEY_SET_INIT_RECV_SEQ; - if (mac_addr) - flags |= NDIS_80211_ADDKEY_PAIRWISE_KEY | - NDIS_80211_ADDKEY_TRANSMIT_KEY; - - return add_wpa_key(usbdev, params->key, params->key_len, - key_index, mac_addr, params->seq, - params->seq_len, params->cipher, flags); - default: - devdbg(usbdev, "rndis_add_key: unsupported cipher %08x", - params->cipher); - return -ENOTSUPP; - } -} - -static int rndis_del_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, const u8 *mac_addr) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - devdbg(usbdev, "rndis_del_key(%i, %pM)", key_index, mac_addr); - - return remove_key(usbdev, key_index, mac_addr); -} - -static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - struct rndis_wlan_encr_key key; - - devdbg(usbdev, "rndis_set_default_key(%i)", key_index); - - priv->encr_tx_key_index = key_index; - - key = priv->encr_keys[key_index]; - - return add_wep_key(usbdev, key.material, key.len, key_index); -} - -static void rndis_fill_station_info(struct usbnet *usbdev, - struct station_info *sinfo) -{ - __le32 linkspeed, rssi; - int ret, len; - - memset(sinfo, 0, sizeof(*sinfo)); - - len = sizeof(linkspeed); - ret = rndis_query_oid(usbdev, OID_GEN_LINK_SPEED, &linkspeed, &len); - if (ret == 0) { - sinfo->txrate.legacy = le32_to_cpu(linkspeed) / 1000; - sinfo->filled |= STATION_INFO_TX_BITRATE; - } - - len = sizeof(rssi); - ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); - if (ret == 0) { - sinfo->signal = level_to_qual(le32_to_cpu(rssi)); - sinfo->filled |= STATION_INFO_SIGNAL; - } -} - -static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev, - u8 *mac, struct station_info *sinfo) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - if (compare_ether_addr(priv->bssid, mac)) - return -ENOENT; - - rndis_fill_station_info(usbdev, sinfo); - - return 0; -} - -static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev, - int idx, u8 *mac, struct station_info *sinfo) -{ - struct rndis_wlan_private *priv = wiphy_priv(wiphy); - struct usbnet *usbdev = priv->usbdev; - - if (idx != 0) - return -ENOENT; - - memcpy(mac, priv->bssid, ETH_ALEN); - - rndis_fill_station_info(usbdev, sinfo); - - return 0; -} - -/* - * workers, indication handlers, device poller - */ -static void rndis_wlan_do_link_up_work(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct ndis_80211_assoc_info *info; - u8 assoc_buf[sizeof(*info) + IW_CUSTOM_MAX + 32]; - u8 bssid[ETH_ALEN]; - int resp_ie_len, req_ie_len; - u8 *req_ie, *resp_ie; - int ret, offset; - bool roamed = false; - - if (priv->infra_mode == NDIS_80211_INFRA_INFRA && priv->connected) { - /* received media connect indication while connected, either - * device reassociated with same AP or roamed to new. */ - roamed = true; - } - - req_ie_len = 0; - resp_ie_len = 0; - req_ie = NULL; - resp_ie = NULL; - - if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { - memset(assoc_buf, 0, sizeof(assoc_buf)); - info = (void *)assoc_buf; - - /* Get association info IEs from device and send them back to - * userspace. */ - ret = get_association_info(usbdev, info, sizeof(assoc_buf)); - if (!ret) { - req_ie_len = le32_to_cpu(info->req_ie_length); - if (req_ie_len > 0) { - offset = le32_to_cpu(info->offset_req_ies); - req_ie = (u8 *)info + offset; - } - - resp_ie_len = le32_to_cpu(info->resp_ie_length); - if (resp_ie_len > 0) { - offset = le32_to_cpu(info->offset_resp_ies); - resp_ie = (u8 *)info + offset; - } - } - } else if (WARN_ON(priv->infra_mode != NDIS_80211_INFRA_ADHOC)) - return; - - ret = get_bssid(usbdev, bssid); - if (ret < 0) - memset(bssid, 0, sizeof(bssid)); - - devdbg(usbdev, "link up work: [%pM] %s", bssid, roamed ? "roamed" : ""); - - /* Internal bss list in device always contains at least the currently - * connected bss and we can get it to cfg80211 with - * rndis_check_bssid_list(). - * NOTE: This is true for Broadcom chip, but not mentioned in RNDIS - * spec. - */ - rndis_check_bssid_list(usbdev); - - if (priv->infra_mode == NDIS_80211_INFRA_INFRA) { - if (!roamed) - cfg80211_connect_result(usbdev->net, bssid, req_ie, - req_ie_len, resp_ie, - resp_ie_len, 0, GFP_KERNEL); - else - cfg80211_roamed(usbdev->net, bssid, req_ie, req_ie_len, - resp_ie, resp_ie_len, GFP_KERNEL); - } else if (priv->infra_mode == NDIS_80211_INFRA_ADHOC) - cfg80211_ibss_joined(usbdev->net, bssid, GFP_KERNEL); - - priv->connected = true; - memcpy(priv->bssid, bssid, ETH_ALEN); - - usbnet_resume_rx(usbdev); - netif_carrier_on(usbdev->net); -} - -static void rndis_wlan_do_link_down_work(struct usbnet *usbdev) -{ - union iwreq_data evt; - - netif_carrier_off(usbdev->net); - - evt.data.flags = 0; - evt.data.length = 0; - memset(evt.ap_addr.sa_data, 0, ETH_ALEN); - wireless_send_event(usbdev->net, SIOCGIWAP, &evt, NULL); -} - -static void rndis_wlan_worker(struct work_struct *work) -{ - struct rndis_wlan_private *priv = - container_of(work, struct rndis_wlan_private, work); - struct usbnet *usbdev = priv->usbdev; - - if (test_and_clear_bit(WORK_LINK_UP, &priv->work_pending)) - rndis_wlan_do_link_up_work(usbdev); - - if (test_and_clear_bit(WORK_LINK_DOWN, &priv->work_pending)) - rndis_wlan_do_link_down_work(usbdev); - - if (test_and_clear_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) - set_multicast_list(usbdev); -} - -static void rndis_wlan_set_multicast_list(struct net_device *dev) -{ - struct usbnet *usbdev = netdev_priv(dev); - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - - if (test_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending)) - return; - - set_bit(WORK_SET_MULTICAST_LIST, &priv->work_pending); - queue_work(priv->workqueue, &priv->work); -} - -static void rndis_wlan_auth_indication(struct usbnet *usbdev, - struct ndis_80211_status_indication *indication, - int len) -{ - u8 *buf; - const char *type; - int flags, buflen, key_id; - bool pairwise_error, group_error; - struct ndis_80211_auth_request *auth_req; - enum nl80211_key_type key_type; - - /* must have at least one array entry */ - if (len < offsetof(struct ndis_80211_status_indication, u) + - sizeof(struct ndis_80211_auth_request)) { - devinfo(usbdev, "authentication indication: " - "too short message (%i)", len); - return; - } - - buf = (void *)&indication->u.auth_request[0]; - buflen = len - offsetof(struct ndis_80211_status_indication, u); - - while (buflen >= sizeof(*auth_req)) { - auth_req = (void *)buf; - type = "unknown"; - flags = le32_to_cpu(auth_req->flags); - pairwise_error = false; - group_error = false; - - if (flags & 0x1) - type = "reauth request"; - if (flags & 0x2) - type = "key update request"; - if (flags & 0x6) { - pairwise_error = true; - type = "pairwise_error"; - } - if (flags & 0xe) { - group_error = true; - type = "group_error"; - } - - devinfo(usbdev, "authentication indication: %s (0x%08x)", type, - le32_to_cpu(auth_req->flags)); - - if (pairwise_error) { - key_type = NL80211_KEYTYPE_PAIRWISE; - key_id = -1; - - cfg80211_michael_mic_failure(usbdev->net, - auth_req->bssid, - key_type, key_id, NULL, - GFP_KERNEL); - } - - if (group_error) { - key_type = NL80211_KEYTYPE_GROUP; - key_id = -1; - - cfg80211_michael_mic_failure(usbdev->net, - auth_req->bssid, - key_type, key_id, NULL, - GFP_KERNEL); - } - - buflen -= le32_to_cpu(auth_req->length); - buf += le32_to_cpu(auth_req->length); - } -} - -static void rndis_wlan_pmkid_cand_list_indication(struct usbnet *usbdev, - struct ndis_80211_status_indication *indication, - int len) -{ - struct ndis_80211_pmkid_cand_list *cand_list; - int list_len, expected_len, i; - - if (len < offsetof(struct ndis_80211_status_indication, u) + - sizeof(struct ndis_80211_pmkid_cand_list)) { - devinfo(usbdev, "pmkid candidate list indication: " - "too short message (%i)", len); - return; - } - - list_len = le32_to_cpu(indication->u.cand_list.num_candidates) * - sizeof(struct ndis_80211_pmkid_candidate); - expected_len = sizeof(struct ndis_80211_pmkid_cand_list) + list_len + - offsetof(struct ndis_80211_status_indication, u); - - if (len < expected_len) { - devinfo(usbdev, "pmkid candidate list indication: " - "list larger than buffer (%i < %i)", - len, expected_len); - return; - } - - cand_list = &indication->u.cand_list; - - devinfo(usbdev, "pmkid candidate list indication: " - "version %i, candidates %i", - le32_to_cpu(cand_list->version), - le32_to_cpu(cand_list->num_candidates)); - - if (le32_to_cpu(cand_list->version) != 1) - return; - - for (i = 0; i < le32_to_cpu(cand_list->num_candidates); i++) { - struct ndis_80211_pmkid_candidate *cand = - &cand_list->candidate_list[i]; - - devdbg(usbdev, "cand[%i]: flags: 0x%08x, bssid: %pM", - i, le32_to_cpu(cand->flags), cand->bssid); - -#if 0 - struct iw_pmkid_cand pcand; - union iwreq_data wrqu; - - memset(&pcand, 0, sizeof(pcand)); - if (le32_to_cpu(cand->flags) & 0x01) - pcand.flags |= IW_PMKID_CAND_PREAUTH; - pcand.index = i; - memcpy(pcand.bssid.sa_data, cand->bssid, ETH_ALEN); - - memset(&wrqu, 0, sizeof(wrqu)); - wrqu.data.length = sizeof(pcand); - wireless_send_event(usbdev->net, IWEVPMKIDCAND, &wrqu, - (u8 *)&pcand); -#endif - } -} - -static void rndis_wlan_media_specific_indication(struct usbnet *usbdev, - struct rndis_indicate *msg, int buflen) -{ - struct ndis_80211_status_indication *indication; - int len, offset; - - offset = offsetof(struct rndis_indicate, status) + - le32_to_cpu(msg->offset); - len = le32_to_cpu(msg->length); - - if (len < 8) { - devinfo(usbdev, "media specific indication, " - "ignore too short message (%i < 8)", len); - return; - } - - if (offset + len > buflen) { - devinfo(usbdev, "media specific indication, " - "too large to fit to buffer (%i > %i)", - offset + len, buflen); - return; - } - - indication = (void *)((u8 *)msg + offset); - - switch (le32_to_cpu(indication->status_type)) { - case NDIS_80211_STATUSTYPE_RADIOSTATE: - devinfo(usbdev, "radio state indication: %i", - le32_to_cpu(indication->u.radio_status)); - return; - - case NDIS_80211_STATUSTYPE_MEDIASTREAMMODE: - devinfo(usbdev, "media stream mode indication: %i", - le32_to_cpu(indication->u.media_stream_mode)); - return; - - case NDIS_80211_STATUSTYPE_AUTHENTICATION: - rndis_wlan_auth_indication(usbdev, indication, len); - return; - - case NDIS_80211_STATUSTYPE_PMKID_CANDIDATELIST: - rndis_wlan_pmkid_cand_list_indication(usbdev, indication, len); - return; - - default: - devinfo(usbdev, "media specific indication: " - "unknown status type 0x%08x", - le32_to_cpu(indication->status_type)); - } -} - -static void rndis_wlan_indication(struct usbnet *usbdev, void *ind, int buflen) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - struct rndis_indicate *msg = ind; - - switch (msg->status) { - case RNDIS_STATUS_MEDIA_CONNECT: - if (priv->current_command_oid == OID_802_11_ADD_KEY) { - /* OID_802_11_ADD_KEY causes sometimes extra - * "media connect" indications which confuses driver - * and userspace to think that device is - * roaming/reassociating when it isn't. - */ - devdbg(usbdev, "ignored OID_802_11_ADD_KEY triggered " - "'media connect'"); - return; - } - - usbnet_pause_rx(usbdev); - - devinfo(usbdev, "media connect"); - - /* queue work to avoid recursive calls into rndis_command */ - set_bit(WORK_LINK_UP, &priv->work_pending); - queue_work(priv->workqueue, &priv->work); - break; - - case RNDIS_STATUS_MEDIA_DISCONNECT: - devinfo(usbdev, "media disconnect"); - - /* queue work to avoid recursive calls into rndis_command */ - set_bit(WORK_LINK_DOWN, &priv->work_pending); - queue_work(priv->workqueue, &priv->work); - break; - - case RNDIS_STATUS_MEDIA_SPECIFIC_INDICATION: - rndis_wlan_media_specific_indication(usbdev, msg, buflen); - break; - - default: - devinfo(usbdev, "indication: 0x%08x", - le32_to_cpu(msg->status)); - break; - } -} - -static int rndis_wlan_get_caps(struct usbnet *usbdev) -{ - struct { - __le32 num_items; - __le32 items[8]; - } networks_supported; - int len, retval, i, n; - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - - /* determine supported modes */ - len = sizeof(networks_supported); - retval = rndis_query_oid(usbdev, OID_802_11_NETWORK_TYPES_SUPPORTED, - &networks_supported, &len); - if (retval >= 0) { - n = le32_to_cpu(networks_supported.num_items); - if (n > 8) - n = 8; - for (i = 0; i < n; i++) { - switch (le32_to_cpu(networks_supported.items[i])) { - case NDIS_80211_TYPE_FREQ_HOP: - case NDIS_80211_TYPE_DIRECT_SEQ: - priv->caps |= CAP_MODE_80211B; - break; - case NDIS_80211_TYPE_OFDM_A: - priv->caps |= CAP_MODE_80211A; - break; - case NDIS_80211_TYPE_OFDM_G: - priv->caps |= CAP_MODE_80211G; - break; - } - } - } - - return retval; -} - -#define DEVICE_POLLER_JIFFIES (HZ) -static void rndis_device_poller(struct work_struct *work) -{ - struct rndis_wlan_private *priv = - container_of(work, struct rndis_wlan_private, - dev_poller_work.work); - struct usbnet *usbdev = priv->usbdev; - __le32 rssi, tmp; - int len, ret, j; - int update_jiffies = DEVICE_POLLER_JIFFIES; - void *buf; - - /* Only check/do workaround when connected. Calling is_associated() - * also polls device with rndis_command() and catches for media link - * indications. - */ - if (!is_associated(usbdev)) - goto end; - - len = sizeof(rssi); - ret = rndis_query_oid(usbdev, OID_802_11_RSSI, &rssi, &len); - if (ret == 0) - priv->last_qual = level_to_qual(le32_to_cpu(rssi)); - - devdbg(usbdev, "dev-poller: OID_802_11_RSSI -> %d, rssi:%d, qual: %d", - ret, le32_to_cpu(rssi), level_to_qual(le32_to_cpu(rssi))); - - /* Workaround transfer stalls on poor quality links. - * TODO: find right way to fix these stalls (as stalls do not happen - * with ndiswrapper/windows driver). */ - if (priv->param_workaround_interval > 0 && priv->last_qual <= 25) { - /* Decrease stats worker interval to catch stalls. - * faster. Faster than 400-500ms causes packet loss, - * Slower doesn't catch stalls fast enough. - */ - j = msecs_to_jiffies(priv->param_workaround_interval); - if (j > DEVICE_POLLER_JIFFIES) - j = DEVICE_POLLER_JIFFIES; - else if (j <= 0) - j = 1; - update_jiffies = j; - - /* Send scan OID. Use of both OIDs is required to get device - * working. - */ - tmp = cpu_to_le32(1); - rndis_set_oid(usbdev, OID_802_11_BSSID_LIST_SCAN, &tmp, - sizeof(tmp)); - - len = CONTROL_BUFFER_SIZE; - buf = kmalloc(len, GFP_KERNEL); - if (!buf) - goto end; - - rndis_query_oid(usbdev, OID_802_11_BSSID_LIST, buf, &len); - kfree(buf); - } - -end: - if (update_jiffies >= HZ) - update_jiffies = round_jiffies_relative(update_jiffies); - else { - j = round_jiffies_relative(update_jiffies); - if (abs(j - update_jiffies) <= 10) - update_jiffies = j; - } - - queue_delayed_work(priv->workqueue, &priv->dev_poller_work, - update_jiffies); -} - -/* - * driver/device initialization - */ -static int bcm4320a_early_init(struct usbnet *usbdev) -{ - /* bcm4320a doesn't handle configuration parameters well. Try - * set any and you get partially zeroed mac and broken device. - */ - - return 0; -} - -static int bcm4320b_early_init(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - char buf[8]; - - /* Early initialization settings, setting these won't have effect - * if called after generic_rndis_bind(). - */ - - priv->param_country[0] = modparam_country[0]; - priv->param_country[1] = modparam_country[1]; - priv->param_country[2] = 0; - priv->param_frameburst = modparam_frameburst; - priv->param_afterburner = modparam_afterburner; - priv->param_power_save = modparam_power_save; - priv->param_power_output = modparam_power_output; - priv->param_roamtrigger = modparam_roamtrigger; - priv->param_roamdelta = modparam_roamdelta; - - priv->param_country[0] = toupper(priv->param_country[0]); - priv->param_country[1] = toupper(priv->param_country[1]); - /* doesn't support EU as country code, use FI instead */ - if (!strcmp(priv->param_country, "EU")) - strcpy(priv->param_country, "FI"); - - if (priv->param_power_save < 0) - priv->param_power_save = 0; - else if (priv->param_power_save > 2) - priv->param_power_save = 2; - - if (priv->param_power_output < 0) - priv->param_power_output = 0; - else if (priv->param_power_output > 3) - priv->param_power_output = 3; - - if (priv->param_roamtrigger < -80) - priv->param_roamtrigger = -80; - else if (priv->param_roamtrigger > -60) - priv->param_roamtrigger = -60; - - if (priv->param_roamdelta < 0) - priv->param_roamdelta = 0; - else if (priv->param_roamdelta > 2) - priv->param_roamdelta = 2; - - if (modparam_workaround_interval < 0) - priv->param_workaround_interval = 500; - else - priv->param_workaround_interval = modparam_workaround_interval; - - rndis_set_config_parameter_str(usbdev, "Country", priv->param_country); - rndis_set_config_parameter_str(usbdev, "FrameBursting", - priv->param_frameburst ? "1" : "0"); - rndis_set_config_parameter_str(usbdev, "Afterburner", - priv->param_afterburner ? "1" : "0"); - sprintf(buf, "%d", priv->param_power_save); - rndis_set_config_parameter_str(usbdev, "PowerSaveMode", buf); - sprintf(buf, "%d", priv->param_power_output); - rndis_set_config_parameter_str(usbdev, "PwrOut", buf); - sprintf(buf, "%d", priv->param_roamtrigger); - rndis_set_config_parameter_str(usbdev, "RoamTrigger", buf); - sprintf(buf, "%d", priv->param_roamdelta); - rndis_set_config_parameter_str(usbdev, "RoamDelta", buf); - - return 0; -} - -/* same as rndis_netdev_ops but with local multicast handler */ -static const struct net_device_ops rndis_wlan_netdev_ops = { - .ndo_open = usbnet_open, - .ndo_stop = usbnet_stop, - .ndo_start_xmit = usbnet_start_xmit, - .ndo_tx_timeout = usbnet_tx_timeout, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_multicast_list = rndis_wlan_set_multicast_list, -}; - -static int rndis_wlan_bind(struct usbnet *usbdev, struct usb_interface *intf) -{ - struct wiphy *wiphy; - struct rndis_wlan_private *priv; - int retval, len; - __le32 tmp; - - /* allocate wiphy and rndis private data - * NOTE: We only support a single virtual interface, so wiphy - * and wireless_dev are somewhat synonymous for this device. - */ - wiphy = wiphy_new(&rndis_config_ops, sizeof(struct rndis_wlan_private)); - if (!wiphy) - return -ENOMEM; - - priv = wiphy_priv(wiphy); - usbdev->net->ieee80211_ptr = &priv->wdev; - priv->wdev.wiphy = wiphy; - priv->wdev.iftype = NL80211_IFTYPE_STATION; - - /* These have to be initialized before calling generic_rndis_bind(). - * Otherwise we'll be in big trouble in rndis_wlan_early_init(). - */ - usbdev->driver_priv = priv; - priv->usbdev = usbdev; - - mutex_init(&priv->command_lock); - - /* because rndis_command() sleeps we need to use workqueue */ - priv->workqueue = create_singlethread_workqueue("rndis_wlan"); - INIT_WORK(&priv->work, rndis_wlan_worker); - INIT_DELAYED_WORK(&priv->dev_poller_work, rndis_device_poller); - INIT_DELAYED_WORK(&priv->scan_work, rndis_get_scan_results); - - /* try bind rndis_host */ - retval = generic_rndis_bind(usbdev, intf, FLAG_RNDIS_PHYM_WIRELESS); - if (retval < 0) - goto fail; - - /* generic_rndis_bind set packet filter to multicast_all+ - * promisc mode which doesn't work well for our devices (device - * picks up rssi to closest station instead of to access point). - * - * rndis_host wants to avoid all OID as much as possible - * so do promisc/multicast handling in rndis_wlan. - */ - usbdev->net->netdev_ops = &rndis_wlan_netdev_ops; - - tmp = RNDIS_PACKET_TYPE_DIRECTED | RNDIS_PACKET_TYPE_BROADCAST; - retval = rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &tmp, - sizeof(tmp)); - - len = sizeof(tmp); - retval = rndis_query_oid(usbdev, OID_802_3_MAXIMUM_LIST_SIZE, &tmp, - &len); - priv->multicast_size = le32_to_cpu(tmp); - if (retval < 0 || priv->multicast_size < 0) - priv->multicast_size = 0; - if (priv->multicast_size > 0) - usbdev->net->flags |= IFF_MULTICAST; - else - usbdev->net->flags &= ~IFF_MULTICAST; - - /* fill-out wiphy structure and register w/ cfg80211 */ - memcpy(wiphy->perm_addr, usbdev->net->dev_addr, ETH_ALEN); - wiphy->privid = rndis_wiphy_privid; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) - | BIT(NL80211_IFTYPE_ADHOC); - wiphy->max_scan_ssids = 1; - - /* TODO: fill-out band/encr information based on priv->caps */ - rndis_wlan_get_caps(usbdev); - - memcpy(priv->channels, rndis_channels, sizeof(rndis_channels)); - memcpy(priv->rates, rndis_rates, sizeof(rndis_rates)); - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(rndis_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = ARRAY_SIZE(rndis_rates); - wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; - - memcpy(priv->cipher_suites, rndis_cipher_suites, - sizeof(rndis_cipher_suites)); - wiphy->cipher_suites = priv->cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(rndis_cipher_suites); - - set_wiphy_dev(wiphy, &usbdev->udev->dev); - - if (wiphy_register(wiphy)) { - retval = -ENODEV; - goto fail; - } - - set_default_iw_params(usbdev); - - /* set default rts/frag */ - rndis_set_wiphy_params(wiphy, - WIPHY_PARAM_FRAG_THRESHOLD | WIPHY_PARAM_RTS_THRESHOLD); - - /* turn radio on */ - priv->radio_on = true; - disassociate(usbdev, true); - netif_carrier_off(usbdev->net); - - return 0; - -fail: - cancel_delayed_work_sync(&priv->dev_poller_work); - cancel_delayed_work_sync(&priv->scan_work); - cancel_work_sync(&priv->work); - flush_workqueue(priv->workqueue); - destroy_workqueue(priv->workqueue); - - wiphy_free(wiphy); - return retval; -} - -static void rndis_wlan_unbind(struct usbnet *usbdev, struct usb_interface *intf) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - - /* turn radio off */ - disassociate(usbdev, false); - - cancel_delayed_work_sync(&priv->dev_poller_work); - cancel_delayed_work_sync(&priv->scan_work); - cancel_work_sync(&priv->work); - flush_workqueue(priv->workqueue); - destroy_workqueue(priv->workqueue); - - if (priv && priv->wpa_ie_len) - kfree(priv->wpa_ie); - - rndis_unbind(usbdev, intf); - - wiphy_unregister(priv->wdev.wiphy); - wiphy_free(priv->wdev.wiphy); -} - -static int rndis_wlan_reset(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - int retval; - - devdbg(usbdev, "rndis_wlan_reset"); - - retval = rndis_reset(usbdev); - if (retval) - devwarn(usbdev, "rndis_reset() failed: %d", retval); - - /* rndis_reset cleared multicast list, so restore here. - (set_multicast_list() also turns on current packet filter) */ - set_multicast_list(usbdev); - - queue_delayed_work(priv->workqueue, &priv->dev_poller_work, - round_jiffies_relative(DEVICE_POLLER_JIFFIES)); - - return deauthenticate(usbdev); -} - -static int rndis_wlan_stop(struct usbnet *usbdev) -{ - struct rndis_wlan_private *priv = get_rndis_wlan_priv(usbdev); - int retval; - __le32 filter; - - devdbg(usbdev, "rndis_wlan_stop"); - - retval = disassociate(usbdev, false); - - priv->work_pending = 0; - cancel_delayed_work_sync(&priv->dev_poller_work); - cancel_delayed_work_sync(&priv->scan_work); - cancel_work_sync(&priv->work); - flush_workqueue(priv->workqueue); - - if (priv->scan_request) { - cfg80211_scan_done(priv->scan_request, true); - priv->scan_request = NULL; - } - - /* Set current packet filter zero to block receiving data packets from - device. */ - filter = 0; - rndis_set_oid(usbdev, OID_GEN_CURRENT_PACKET_FILTER, &filter, - sizeof(filter)); - - return retval; -} - -static const struct driver_info bcm4320b_info = { - .description = "Wireless RNDIS device, BCM4320b based", - .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | - FLAG_AVOID_UNLINK_URBS, - .bind = rndis_wlan_bind, - .unbind = rndis_wlan_unbind, - .status = rndis_status, - .rx_fixup = rndis_rx_fixup, - .tx_fixup = rndis_tx_fixup, - .reset = rndis_wlan_reset, - .stop = rndis_wlan_stop, - .early_init = bcm4320b_early_init, - .indication = rndis_wlan_indication, -}; - -static const struct driver_info bcm4320a_info = { - .description = "Wireless RNDIS device, BCM4320a based", - .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | - FLAG_AVOID_UNLINK_URBS, - .bind = rndis_wlan_bind, - .unbind = rndis_wlan_unbind, - .status = rndis_status, - .rx_fixup = rndis_rx_fixup, - .tx_fixup = rndis_tx_fixup, - .reset = rndis_wlan_reset, - .stop = rndis_wlan_stop, - .early_init = bcm4320a_early_init, - .indication = rndis_wlan_indication, -}; - -static const struct driver_info rndis_wlan_info = { - .description = "Wireless RNDIS device", - .flags = FLAG_WLAN | FLAG_FRAMING_RN | FLAG_NO_SETINT | - FLAG_AVOID_UNLINK_URBS, - .bind = rndis_wlan_bind, - .unbind = rndis_wlan_unbind, - .status = rndis_status, - .rx_fixup = rndis_rx_fixup, - .tx_fixup = rndis_tx_fixup, - .reset = rndis_wlan_reset, - .stop = rndis_wlan_stop, - .early_init = bcm4320a_early_init, - .indication = rndis_wlan_indication, -}; - -/*-------------------------------------------------------------------------*/ - -static const struct usb_device_id products [] = { -#define RNDIS_MASTER_INTERFACE \ - .bInterfaceClass = USB_CLASS_COMM, \ - .bInterfaceSubClass = 2 /* ACM */, \ - .bInterfaceProtocol = 0x0ff - -/* INF driver for these devices have DriverVer >= 4.xx.xx.xx and many custom - * parameters available. Chipset marked as 'BCM4320SKFBG' in NDISwrapper-wiki. - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0411, - .idProduct = 0x00bc, /* Buffalo WLI-U2-KG125S */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0baf, - .idProduct = 0x011b, /* U.S. Robotics USR5421 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x050d, - .idProduct = 0x011b, /* Belkin F5D7051 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x1799, /* Belkin has two vendor ids */ - .idProduct = 0x011b, /* Belkin F5D7051 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x13b1, - .idProduct = 0x0014, /* Linksys WUSB54GSv2 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x13b1, - .idProduct = 0x0026, /* Linksys WUSB54GSC */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0b05, - .idProduct = 0x1717, /* Asus WL169gE */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0a5c, - .idProduct = 0xd11b, /* Eminent EM4045 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x1690, - .idProduct = 0x0715, /* BT Voyager 1055 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320b_info, -}, -/* These devices have DriverVer < 4.xx.xx.xx and do not have any custom - * parameters available, hardware probably contain older firmware version with - * no way of updating. Chipset marked as 'BCM4320????' in NDISwrapper-wiki. - */ -{ - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x13b1, - .idProduct = 0x000e, /* Linksys WUSB54GSv1 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320a_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0baf, - .idProduct = 0x0111, /* U.S. Robotics USR5420 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320a_info, -}, { - .match_flags = USB_DEVICE_ID_MATCH_INT_INFO - | USB_DEVICE_ID_MATCH_DEVICE, - .idVendor = 0x0411, - .idProduct = 0x004b, /* BUFFALO WLI-USB-G54 */ - RNDIS_MASTER_INTERFACE, - .driver_info = (unsigned long) &bcm4320a_info, -}, -/* Generic Wireless RNDIS devices that we don't have exact - * idVendor/idProduct/chip yet. - */ -{ - /* RNDIS is MSFT's un-official variant of CDC ACM */ - USB_INTERFACE_INFO(USB_CLASS_COMM, 2 /* ACM */, 0x0ff), - .driver_info = (unsigned long) &rndis_wlan_info, -}, { - /* "ActiveSync" is an undocumented variant of RNDIS, used in WM5 */ - USB_INTERFACE_INFO(USB_CLASS_MISC, 1, 1), - .driver_info = (unsigned long) &rndis_wlan_info, -}, - { }, // END -}; -MODULE_DEVICE_TABLE(usb, products); - -static struct usb_driver rndis_wlan_driver = { - .name = "rndis_wlan", - .id_table = products, - .probe = usbnet_probe, - .disconnect = usbnet_disconnect, - .suspend = usbnet_suspend, - .resume = usbnet_resume, -}; - -static int __init rndis_wlan_init(void) -{ - return usb_register(&rndis_wlan_driver); -} -module_init(rndis_wlan_init); - -static void __exit rndis_wlan_exit(void) -{ - usb_deregister(&rndis_wlan_driver); -} -module_exit(rndis_wlan_exit); - -MODULE_AUTHOR("Bjorge Dijkstra"); -MODULE_AUTHOR("Jussi Kivilinna"); -MODULE_DESCRIPTION("Driver for RNDIS based USB Wireless adapters"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig deleted file mode 100644 index ed1f997e3521..000000000000 --- a/drivers/net/wireless/rt2x00/Kconfig +++ /dev/null @@ -1,136 +0,0 @@ -menuconfig RT2X00 - tristate "Ralink driver support" - depends on MAC80211 && WLAN_80211 - ---help--- - This will enable the support for the Ralink drivers, - developed in the rt2x00 project . - - These drivers make use of the mac80211 stack. - - When building one of the individual drivers, the rt2x00 library - will also be created. That library (when the driver is built as - a module) will be called rt2x00lib. - - Additionally PCI and USB libraries will also be build depending - on the types of drivers being selected, these libraries will be - called rt2x00pci and rt2x00usb. - -if RT2X00 - -config RT2400PCI - tristate "Ralink rt2400 (PCI/PCMCIA) support" - depends on PCI - select RT2X00_LIB_PCI - select EEPROM_93CX6 - ---help--- - This adds support for rt2400 wireless chipset family. - Supported chips: RT2460. - - When compiled as a module, this driver will be called rt2400pci. - -config RT2500PCI - tristate "Ralink rt2500 (PCI/PCMCIA) support" - depends on PCI - select RT2X00_LIB_PCI - select EEPROM_93CX6 - ---help--- - This adds support for rt2500 wireless chipset family. - Supported chips: RT2560. - - When compiled as a module, this driver will be called rt2500pci. - -config RT61PCI - tristate "Ralink rt2501/rt61 (PCI/PCMCIA) support" - depends on PCI - select RT2X00_LIB_PCI - select RT2X00_LIB_FIRMWARE - select RT2X00_LIB_CRYPTO - select CRC_ITU_T - select EEPROM_93CX6 - ---help--- - This adds support for rt2501 wireless chipset family. - Supported chips: RT2561, RT2561S & RT2661. - - When compiled as a module, this driver will be called rt61pci. - -config RT2500USB - tristate "Ralink rt2500 (USB) support" - depends on USB - select RT2X00_LIB_USB - select RT2X00_LIB_CRYPTO - ---help--- - This adds support for rt2500 wireless chipset family. - Supported chips: RT2571 & RT2572. - - When compiled as a module, this driver will be called rt2500usb. - -config RT73USB - tristate "Ralink rt2501/rt73 (USB) support" - depends on USB - select RT2X00_LIB_USB - select RT2X00_LIB_FIRMWARE - select RT2X00_LIB_CRYPTO - select CRC_ITU_T - ---help--- - This adds support for rt2501 wireless chipset family. - Supported chips: RT2571W, RT2573 & RT2671. - - When compiled as a module, this driver will be called rt73usb. - -config RT2800USB - tristate "Ralink rt2800 (USB) support" - depends on USB && EXPERIMENTAL - select RT2X00_LIB_USB - select RT2X00_LIB_HT - select RT2X00_LIB_FIRMWARE - select RT2X00_LIB_CRYPTO - select CRC_CCITT - ---help--- - This adds experimental support for rt2800 wireless chipset family. - Supported chips: RT2770, RT2870 & RT3070. - - When compiled as a module, this driver will be called "rt2800usb.ko". - -config RT2X00_LIB_PCI - tristate - select RT2X00_LIB - -config RT2X00_LIB_USB - tristate - select RT2X00_LIB - -config RT2X00_LIB - tristate - -config RT2X00_LIB_HT - boolean - -config RT2X00_LIB_FIRMWARE - boolean - select FW_LOADER - -config RT2X00_LIB_CRYPTO - boolean - -config RT2X00_LIB_LEDS - boolean - default y if (RT2X00_LIB=y && LEDS_CLASS=y) || (RT2X00_LIB=m && LEDS_CLASS!=n) - -comment "rt2x00 leds support disabled due to modularized LEDS_CLASS and built-in rt2x00" - depends on RT2X00_LIB=y && LEDS_CLASS=m - -config RT2X00_LIB_DEBUGFS - bool "Ralink debugfs support" - depends on RT2X00_LIB && MAC80211_DEBUGFS - ---help--- - Enable creation of debugfs files for the rt2x00 drivers. - These debugfs files support both reading and writing of the - most important register types of the rt2x00 hardware. - -config RT2X00_DEBUG - bool "Ralink debug output" - depends on RT2X00_LIB - ---help--- - Enable debugging output for all rt2x00 modules - -endif diff --git a/drivers/net/wireless/rt2x00/Makefile b/drivers/net/wireless/rt2x00/Makefile deleted file mode 100644 index 13043ea97667..000000000000 --- a/drivers/net/wireless/rt2x00/Makefile +++ /dev/null @@ -1,20 +0,0 @@ -rt2x00lib-y += rt2x00dev.o -rt2x00lib-y += rt2x00mac.o -rt2x00lib-y += rt2x00config.o -rt2x00lib-y += rt2x00queue.o -rt2x00lib-y += rt2x00link.o -rt2x00lib-$(CONFIG_RT2X00_LIB_DEBUGFS) += rt2x00debug.o -rt2x00lib-$(CONFIG_RT2X00_LIB_CRYPTO) += rt2x00crypto.o -rt2x00lib-$(CONFIG_RT2X00_LIB_FIRMWARE) += rt2x00firmware.o -rt2x00lib-$(CONFIG_RT2X00_LIB_LEDS) += rt2x00leds.o -rt2x00lib-$(CONFIG_RT2X00_LIB_HT) += rt2x00ht.o - -obj-$(CONFIG_RT2X00_LIB) += rt2x00lib.o -obj-$(CONFIG_RT2X00_LIB_PCI) += rt2x00pci.o -obj-$(CONFIG_RT2X00_LIB_USB) += rt2x00usb.o -obj-$(CONFIG_RT2400PCI) += rt2400pci.o -obj-$(CONFIG_RT2500PCI) += rt2500pci.o -obj-$(CONFIG_RT61PCI) += rt61pci.o -obj-$(CONFIG_RT2500USB) += rt2500usb.o -obj-$(CONFIG_RT73USB) += rt73usb.o -obj-$(CONFIG_RT2800USB) += rt2800usb.o diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c deleted file mode 100644 index 798f625e38f7..000000000000 --- a/drivers/net/wireless/rt2x00/rt2400pci.c +++ /dev/null @@ -1,1677 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2400pci - Abstract: rt2400pci device specific routines. - Supported chipsets: RT2460. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00pci.h" -#include "rt2400pci.h" - -/* - * Register access. - * All access to the CSR registers will go through the methods - * rt2x00pci_register_read and rt2x00pci_register_write. - * BBP and RF register require indirect register access, - * and use the CSR registers BBPCSR and RFCSR to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - */ -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) - -static void rt2400pci_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBPCSR_VALUE, value); - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); - - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2400pci_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); - - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - - WAIT_FOR_BBP(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, BBPCSR_VALUE); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2400pci_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RFCSR_VALUE, value); - rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); - rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); - rt2x00_set_field32(®, RFCSR_BUSY, 1); - - rt2x00pci_register_write(rt2x00dev, RFCSR, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2400pci_eepromregister_read(struct eeprom_93cx6 *eeprom) -{ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR21, ®); - - eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); - eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); - eeprom->reg_data_clock = - !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK); - eeprom->reg_chip_select = - !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT); -} - -static void rt2400pci_eepromregister_write(struct eeprom_93cx6 *eeprom) -{ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg = 0; - - rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in); - rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out); - rt2x00_set_field32(®, CSR21_EEPROM_DATA_CLOCK, - !!eeprom->reg_data_clock); - rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, - !!eeprom->reg_chip_select); - - rt2x00pci_register_write(rt2x00dev, CSR21, reg); -} - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -static const struct rt2x00debug rt2400pci_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = rt2x00pci_register_read, - .write = rt2x00pci_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u32), - .word_count = CSR_REG_SIZE / sizeof(u32), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt2400pci_bbp_read, - .write = rt2400pci_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt2400pci_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -static int rt2400pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); - return rt2x00_get_field32(reg, GPIOCSR_BIT0); -} - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt2400pci_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - u32 reg; - - rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); - - if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) - rt2x00_set_field32(®, LEDCSR_LINK, enabled); - else if (led->type == LED_TYPE_ACTIVITY) - rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); - - rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); -} - -static int rt2400pci_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u32 reg; - - rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); - rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); - rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); - rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); - - return 0; -} - -static void rt2400pci_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt2400pci_brightness_set; - led->led_dev.blink_set = rt2400pci_blink_set; - led->flags = LED_INITIALIZED; -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ -static void rt2400pci_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u32 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * since there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_CRC, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(filter_flags & FIF_PROMISC_IN_BSS) && - !rt2x00dev->intf_ap_count); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - -static void rt2400pci_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags) -{ - unsigned int bcn_preload; - u32 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Enable beacon config - */ - bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); - rt2x00_set_field32(®, CSR14_TBCN, 1); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - } - - if (flags & CONFIG_UPDATE_MAC) - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, - conf->mac, sizeof(conf->mac)); - - if (flags & CONFIG_UPDATE_BSSID) - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, - conf->bssid, sizeof(conf->bssid)); -} - -static void rt2400pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) -{ - int preamble_mask; - u32 reg; - - /* - * When short preamble is enabled, we should set bit 0x08 - */ - preamble_mask = erp->short_preamble << 3; - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x1ff); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0x13a); - rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); - rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); - rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); - rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); - rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); - rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); - rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); - rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); - rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); - rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); - rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); - rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); - rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); - - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); - - rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, CSR12, reg); - - rt2x00pci_register_read(rt2x00dev, CSR18, ®); - rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); - rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); - rt2x00pci_register_write(rt2x00dev, CSR18, reg); - - rt2x00pci_register_read(rt2x00dev, CSR19, ®); - rt2x00_set_field32(®, CSR19_DIFS, erp->difs); - rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); - rt2x00pci_register_write(rt2x00dev, CSR19, reg); -} - -static void rt2400pci_config_ant(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r1; - u8 r4; - - /* - * We should never come here because rt2x00lib is supposed - * to catch this and send us the correct antenna explicitely. - */ - BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || - ant->tx == ANTENNA_SW_DIVERSITY); - - rt2400pci_bbp_read(rt2x00dev, 4, &r4); - rt2400pci_bbp_read(rt2x00dev, 1, &r1); - - /* - * Configure the TX antenna. - */ - switch (ant->tx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 1); - break; - case ANTENNA_A: - rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 0); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r1, BBP_R1_TX_ANTENNA, 2); - break; - } - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 1); - break; - case ANTENNA_A: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 0); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA, 2); - break; - } - - rt2400pci_bbp_write(rt2x00dev, 4, r4); - rt2400pci_bbp_write(rt2x00dev, 1, r1); -} - -static void rt2400pci_config_channel(struct rt2x00_dev *rt2x00dev, - struct rf_channel *rf) -{ - /* - * Switch on tuning bits. - */ - rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); - rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); - - rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); - rt2400pci_rf_write(rt2x00dev, 2, rf->rf2); - rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); - - /* - * RF2420 chipset don't need any additional actions. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2420)) - return; - - /* - * For the RT2421 chipsets we need to write an invalid - * reference clock rate to activate auto_tune. - * After that we set the value back to the correct channel. - */ - rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); - rt2400pci_rf_write(rt2x00dev, 2, 0x000c2a32); - rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); - - msleep(1); - - rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); - rt2400pci_rf_write(rt2x00dev, 2, rf->rf2); - rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); - - msleep(1); - - /* - * Switch off tuning bits. - */ - rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); - rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0); - - rt2400pci_rf_write(rt2x00dev, 1, rf->rf1); - rt2400pci_rf_write(rt2x00dev, 3, rf->rf3); - - /* - * Clear false CRC during channel switch. - */ - rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); -} - -static void rt2400pci_config_txpower(struct rt2x00_dev *rt2x00dev, int txpower) -{ - rt2400pci_bbp_write(rt2x00dev, 3, TXPOWER_TO_DEV(txpower)); -} - -static void rt2400pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_LONG_RETRY, - libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, CSR11_SHORT_RETRY, - libconf->conf->short_frame_max_tx_count); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); -} - -static void rt2400pci_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u32 reg; - - if (state == STATE_SLEEP) { - rt2x00pci_register_read(rt2x00dev, CSR20, ®); - rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, - (rt2x00dev->beacon_int - 20) * 16); - rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, - libconf->conf->listen_interval - 1); - - /* We must first disable autowake before it can be enabled */ - rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); - rt2x00pci_register_write(rt2x00dev, CSR20, reg); - - rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); - rt2x00pci_register_write(rt2x00dev, CSR20, reg); - } - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); -} - -static void rt2400pci_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2400pci_config_channel(rt2x00dev, &libconf->rf); - if (flags & IEEE80211_CONF_CHANGE_POWER) - rt2400pci_config_txpower(rt2x00dev, - libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt2400pci_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt2400pci_config_ps(rt2x00dev, libconf); -} - -static void rt2400pci_config_cw(struct rt2x00_dev *rt2x00dev, - const int cw_min, const int cw_max) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_CWMIN, cw_min); - rt2x00_set_field32(®, CSR11_CWMAX, cw_max); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); -} - -/* - * Link tuning - */ -static void rt2400pci_link_stats(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u32 reg; - u8 bbp; - - /* - * Update FCS error count from register. - */ - rt2x00pci_register_read(rt2x00dev, CNT0, ®); - qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); - - /* - * Update False CCA count from register. - */ - rt2400pci_bbp_read(rt2x00dev, 39, &bbp); - qual->false_cca = bbp; -} - -static inline void rt2400pci_set_vgc(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, u8 vgc_level) -{ - rt2400pci_bbp_write(rt2x00dev, 13, vgc_level); - qual->vgc_level = vgc_level; - qual->vgc_level_reg = vgc_level; -} - -static void rt2400pci_reset_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - rt2400pci_set_vgc(rt2x00dev, qual, 0x08); -} - -static void rt2400pci_link_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count) -{ - /* - * The link tuner should not run longer then 60 seconds, - * and should run once every 2 seconds. - */ - if (count > 60 || !(count & 1)) - return; - - /* - * Base r13 link tuning on the false cca count. - */ - if ((qual->false_cca > 512) && (qual->vgc_level < 0x20)) - rt2400pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level); - else if ((qual->false_cca < 100) && (qual->vgc_level > 0x08)) - rt2400pci_set_vgc(rt2x00dev, qual, --qual->vgc_level); -} - -/* - * Initialization functions. - */ -static bool rt2400pci_get_entry_state(struct queue_entry *entry) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - u32 word; - - if (entry->queue->qid == QID_RX) { - rt2x00_desc_read(entry_priv->desc, 0, &word); - - return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); - } else { - rt2x00_desc_read(entry_priv->desc, 0, &word); - - return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || - rt2x00_get_field32(word, TXD_W0_VALID)); - } -} - -static void rt2400pci_clear_entry(struct queue_entry *entry) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; - - if (entry->queue->qid == QID_RX) { - rt2x00_desc_read(entry_priv->desc, 2, &word); - rt2x00_set_field32(&word, RXD_W2_BUFFER_LENGTH, entry->skb->len); - rt2x00_desc_write(entry_priv->desc, 2, word); - - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); - - rt2x00_desc_read(entry_priv->desc, 0, &word); - rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(entry_priv->desc, 0, word); - } else { - rt2x00_desc_read(entry_priv->desc, 0, &word); - rt2x00_set_field32(&word, TXD_W0_VALID, 0); - rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(entry_priv->desc, 0, word); - } -} - -static int rt2400pci_init_queues(struct rt2x00_dev *rt2x00dev) -{ - struct queue_entry_priv_pci *entry_priv; - u32 reg; - - /* - * Initialize registers. - */ - rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); - rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); - rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); - rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); - rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); - rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); - - entry_priv = rt2x00dev->tx[1].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); - - entry_priv = rt2x00dev->tx[0].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); - - entry_priv = rt2x00dev->bcn[1].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); - - entry_priv = rt2x00dev->bcn[0].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); - - rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); - rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); - rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); - - entry_priv = rt2x00dev->rx->entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); - - return 0; -} - -static int rt2400pci_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); - rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); - rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00023f20); - rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); - - rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); - rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); - rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); - rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); - rt2x00pci_register_write(rt2x00dev, TIMECSR, reg); - - rt2x00pci_register_read(rt2x00dev, CSR9, ®); - rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, - (rt2x00dev->rx->data_size / 128)); - rt2x00pci_register_write(rt2x00dev, CSR9, reg); - - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); - rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); - rt2x00_set_field32(®, CSR14_TBCN, 0); - rt2x00_set_field32(®, CSR14_TCFP, 0); - rt2x00_set_field32(®, CSR14_TATIMW, 0); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); - rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - rt2x00pci_register_write(rt2x00dev, CNT3, 0x3f080000); - - rt2x00pci_register_read(rt2x00dev, ARCSR0, ®); - rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA0, 133); - rt2x00_set_field32(®, ARCSR0_AR_BBP_ID0, 134); - rt2x00_set_field32(®, ARCSR0_AR_BBP_DATA1, 136); - rt2x00_set_field32(®, ARCSR0_AR_BBP_ID1, 135); - rt2x00pci_register_write(rt2x00dev, ARCSR0, reg); - - rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); - rt2x00_set_field32(®, RXCSR3_BBP_ID0, 3); /* Tx power.*/ - rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, RXCSR3_BBP_ID1, 32); /* Signal */ - rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, RXCSR3_BBP_ID2, 36); /* Rssi */ - rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); - rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); - - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00217223); - rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); - - rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); - rt2x00_set_field32(®, MACCSR2_DELAY, 64); - rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 154); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 154); - rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg); - - rt2x00pci_register_read(rt2x00dev, CSR1, ®); - rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); - rt2x00_set_field32(®, CSR1_BBP_RESET, 0); - rt2x00_set_field32(®, CSR1_HOST_READY, 0); - rt2x00pci_register_write(rt2x00dev, CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, CSR1, ®); - rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); - rt2x00_set_field32(®, CSR1_HOST_READY, 1); - rt2x00pci_register_write(rt2x00dev, CSR1, reg); - - /* - * We must clear the FCS and FIFO error count. - * These registers are cleared on read, - * so we may pass a useless variable to store the value. - */ - rt2x00pci_register_read(rt2x00dev, CNT0, ®); - rt2x00pci_register_read(rt2x00dev, CNT4, ®); - - return 0; -} - -static int rt2400pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2400pci_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -static int rt2400pci_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 reg_id; - u8 value; - - if (unlikely(rt2400pci_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt2400pci_bbp_write(rt2x00dev, 1, 0x00); - rt2400pci_bbp_write(rt2x00dev, 3, 0x27); - rt2400pci_bbp_write(rt2x00dev, 4, 0x08); - rt2400pci_bbp_write(rt2x00dev, 10, 0x0f); - rt2400pci_bbp_write(rt2x00dev, 15, 0x72); - rt2400pci_bbp_write(rt2x00dev, 16, 0x74); - rt2400pci_bbp_write(rt2x00dev, 17, 0x20); - rt2400pci_bbp_write(rt2x00dev, 18, 0x72); - rt2400pci_bbp_write(rt2x00dev, 19, 0x0b); - rt2400pci_bbp_write(rt2x00dev, 20, 0x00); - rt2400pci_bbp_write(rt2x00dev, 28, 0x11); - rt2400pci_bbp_write(rt2x00dev, 29, 0x04); - rt2400pci_bbp_write(rt2x00dev, 30, 0x21); - rt2400pci_bbp_write(rt2x00dev, 31, 0x00); - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt2400pci_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} - -/* - * Device state switch handlers. - */ -static void rt2400pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - -static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int mask = (state == STATE_RADIO_IRQ_OFF); - u32 reg; - - /* - * When interrupts are being enabled, the interrupt registers - * should clear the register to assure a clean state. - */ - if (state == STATE_RADIO_IRQ_ON) { - rt2x00pci_register_read(rt2x00dev, CSR7, ®); - rt2x00pci_register_write(rt2x00dev, CSR7, reg); - } - - /* - * Only toggle the interrupts bits we are going to use. - * Non-checked interrupt bits are disabled by default. - */ - rt2x00pci_register_read(rt2x00dev, CSR8, ®); - rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); - rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); - rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); - rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); - rt2x00_set_field32(®, CSR8_RXDONE, mask); - rt2x00pci_register_write(rt2x00dev, CSR8, reg); -} - -static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Initialize all registers. - */ - if (unlikely(rt2400pci_init_queues(rt2x00dev) || - rt2400pci_init_registers(rt2x00dev) || - rt2400pci_init_bbp(rt2x00dev))) - return -EIO; - - return 0; -} - -static void rt2400pci_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Disable power - */ - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); -} - -static int rt2400pci_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - unsigned int i; - char put_to_sleep; - char bbp_state; - char rf_state; - - put_to_sleep = (state != STATE_AWAKE); - - rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); - rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); - rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); - rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); - rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); - rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); - - /* - * Device is not guaranteed to be in the requested state yet. - * We must wait until the register indicates that the - * device has entered the correct state. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); - bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE); - rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE); - if (bbp_state == state && rf_state == state) - return 0; - msleep(10); - } - - return -EBUSY; -} - -static int rt2400pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int retval = 0; - - switch (state) { - case STATE_RADIO_ON: - retval = rt2400pci_enable_radio(rt2x00dev); - break; - case STATE_RADIO_OFF: - rt2400pci_disable_radio(rt2x00dev); - break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2400pci_toggle_rx(rt2x00dev, state); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: - rt2400pci_toggle_irq(rt2x00dev, state); - break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2400pci_set_state(rt2x00dev, state); - break; - default: - retval = -ENOTSUPP; - break; - } - - if (unlikely(retval)) - ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", - state, retval); - - return retval; -} - -/* - * TX descriptor initialization - */ -static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; - __le32 *txd = skbdesc->desc; - u32 word; - - /* - * Start writing the descriptor words. - */ - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_BUFFER_LENGTH, skb->len); - rt2x00_set_field32(&word, TXD_W2_DATABYTE_COUNT, skb->len); - rt2x00_desc_write(txd, 2, word); - - rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1); - rt2x00_desc_write(txd, 3, word); - - rt2x00_desc_read(txd, 4, &word); - rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1); - rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1); - rt2x00_desc_write(txd, 4, word); - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); - rt2x00_set_field32(&word, TXD_W0_VALID, 1); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, - test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); - rt2x00_desc_write(txd, 0, word); -} - -/* - * TX data initialization - */ -static void rt2400pci_write_beacon(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; - u32 reg; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - /* - * Replace rt2x00lib allocated descriptor with the - * pointer to the _real_ hardware descriptor. - * After that, map the beacon to DMA and update the - * descriptor. - */ - memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry_priv->desc; - - rt2x00queue_map_txskb(rt2x00dev, entry->skb); - - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); -} - -static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue == QID_BEACON) { - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - } - return; - } - - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue == QID_ATIM)); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2400pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) -{ - u32 reg; - - if (qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - } else { - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - } -} - -/* - * RX control handlers - */ -static void rt2400pci_fill_rxdone(struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - u32 word0; - u32 word2; - u32 word3; - u32 word4; - u64 tsf; - u32 rx_low; - u32 rx_high; - - rt2x00_desc_read(entry_priv->desc, 0, &word0); - rt2x00_desc_read(entry_priv->desc, 2, &word2); - rt2x00_desc_read(entry_priv->desc, 3, &word3); - rt2x00_desc_read(entry_priv->desc, 4, &word4); - - if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; - - /* - * We only get the lower 32bits from the timestamp, - * to get the full 64bits we must complement it with - * the timestamp from get_tsf(). - * Note that when a wraparound of the lower 32bits - * has occurred between the frame arrival and the get_tsf() - * call, we must decrease the higher 32bits with 1 to get - * to correct value. - */ - tsf = rt2x00dev->ops->hw->get_tsf(rt2x00dev->hw); - rx_low = rt2x00_get_field32(word4, RXD_W4_RX_END_TIME); - rx_high = upper_32_bits(tsf); - - if ((u32)tsf <= rx_low) - rx_high--; - - /* - * Obtain the status about this packet. - * The signal is the PLCP value, and needs to be stripped - * of the preamble bit (0x08). - */ - rxdesc->timestamp = ((u64)rx_high << 32) | rx_low; - rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL) & ~0x08; - rxdesc->rssi = rt2x00_get_field32(word2, RXD_W3_RSSI) - - entry->queue->rt2x00dev->rssi_offset; - rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - - rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; - if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) - rxdesc->dev_flags |= RXDONE_MY_BSS; -} - -/* - * Interrupt functions. - */ -static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue_idx) -{ - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - struct queue_entry_priv_pci *entry_priv; - struct queue_entry *entry; - struct txdone_entry_desc txdesc; - u32 word; - - while (!rt2x00queue_empty(queue)) { - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - entry_priv = entry->priv_data; - rt2x00_desc_read(entry_priv->desc, 0, &word); - - if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || - !rt2x00_get_field32(word, TXD_W0_VALID)) - break; - - /* - * Obtain the status about this packet. - */ - txdesc.flags = 0; - switch (rt2x00_get_field32(word, TXD_W0_RESULT)) { - case 0: /* Success */ - case 1: /* Success with retry */ - __set_bit(TXDONE_SUCCESS, &txdesc.flags); - break; - case 2: /* Failure, excessive retries */ - __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); - /* Don't break, this is a failed frame! */ - default: /* Failure */ - __set_bit(TXDONE_FAILURE, &txdesc.flags); - } - txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - - rt2x00lib_txdone(entry, &txdesc); - } -} - -static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance) -{ - struct rt2x00_dev *rt2x00dev = dev_instance; - u32 reg; - - /* - * Get the interrupt sources & saved to local variable. - * Write register value back to clear pending interrupts. - */ - rt2x00pci_register_read(rt2x00dev, CSR7, ®); - rt2x00pci_register_write(rt2x00dev, CSR7, reg); - - if (!reg) - return IRQ_NONE; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return IRQ_HANDLED; - - /* - * Handle interrupts, walk through all bits - * and run the tasks, the bits are checked in order of - * priority. - */ - - /* - * 1 - Beacon timer expired interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) - rt2x00lib_beacondone(rt2x00dev); - - /* - * 2 - Rx ring done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_RXDONE)) - rt2x00pci_rxdone(rt2x00dev); - - /* - * 3 - Atim ring transmit done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) - rt2400pci_txdone(rt2x00dev, QID_ATIM); - - /* - * 4 - Priority ring transmit done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) - rt2400pci_txdone(rt2x00dev, QID_AC_BE); - - /* - * 5 - Tx ring transmit done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) - rt2400pci_txdone(rt2x00dev, QID_AC_BK); - - return IRQ_HANDLED; -} - -/* - * Device probe functions. - */ -static int rt2400pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ - struct eeprom_93cx6 eeprom; - u32 reg; - u16 word; - u8 *mac; - - rt2x00pci_register_read(rt2x00dev, CSR21, ®); - - eeprom.data = rt2x00dev; - eeprom.register_read = rt2400pci_eepromregister_read; - eeprom.register_write = rt2400pci_eepromregister_write; - eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? - PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; - eeprom.reg_data_in = 0; - eeprom.reg_data_out = 0; - eeprom.reg_data_clock = 0; - eeprom.reg_chip_select = 0; - - eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, - EEPROM_SIZE / sizeof(u16)); - - /* - * Start validation of the data that has been read. - */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - if (!is_valid_ether_addr(mac)) { - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %pM\n", mac); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); - if (word == 0xffff) { - ERROR(rt2x00dev, "Invalid EEPROM data detected.\n"); - return -EINVAL; - } - - return 0; -} - -static int rt2400pci_init_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u16 value; - u16 eeprom; - - /* - * Read EEPROM word for configuration. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Identify RF chipset. - */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - - if (!rt2x00_rf(&rt2x00dev->chip, RF2420) && - !rt2x00_rf(&rt2x00dev->chip, RF2421)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); - return -ENODEV; - } - - /* - * Identify default antenna configuration. - */ - rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); - - /* - * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead. - * I am not 100% sure about this, but the legacy drivers do not - * indicate antenna swapping in software is required when - * diversity is enabled. - */ - if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) - rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; - if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) - rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; - - /* - * Store led mode, for correct led behaviour. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - - rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY || - value == LED_MODE_DEFAULT || - value == LED_MODE_ASUS) - rt2400pci_init_led(rt2x00dev, &rt2x00dev->led_qual, - LED_TYPE_ACTIVITY); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - /* - * Detect if this device has an hardware controlled radio. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); - - /* - * Check if the BBP tuning should be enabled. - */ - if (!rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_AGCVGC_TUNING)) - __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); - - return 0; -} - -/* - * RF value list for RF2420 & RF2421 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_b[] = { - { 1, 0x00022058, 0x000c1fda, 0x00000101, 0 }, - { 2, 0x00022058, 0x000c1fee, 0x00000101, 0 }, - { 3, 0x00022058, 0x000c2002, 0x00000101, 0 }, - { 4, 0x00022058, 0x000c2016, 0x00000101, 0 }, - { 5, 0x00022058, 0x000c202a, 0x00000101, 0 }, - { 6, 0x00022058, 0x000c203e, 0x00000101, 0 }, - { 7, 0x00022058, 0x000c2052, 0x00000101, 0 }, - { 8, 0x00022058, 0x000c2066, 0x00000101, 0 }, - { 9, 0x00022058, 0x000c207a, 0x00000101, 0 }, - { 10, 0x00022058, 0x000c208e, 0x00000101, 0 }, - { 11, 0x00022058, 0x000c20a2, 0x00000101, 0 }, - { 12, 0x00022058, 0x000c20b6, 0x00000101, 0 }, - { 13, 0x00022058, 0x000c20ca, 0x00000101, 0 }, - { 14, 0x00022058, 0x000c20fa, 0x00000101, 0 }, -}; - -static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - struct channel_info *info; - char *tx_power; - unsigned int i; - - /* - * Initialize all hw fields. - */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; - rt2x00dev->hw->extra_tx_headroom = 0; - - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); - SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, - EEPROM_MAC_ADDR_0)); - - /* - * Initialize hw_mode information. - */ - spec->supported_bands = SUPPORT_BAND_2GHZ; - spec->supported_rates = SUPPORT_RATE_CCK; - - spec->num_channels = ARRAY_SIZE(rf_vals_b); - spec->channels = rf_vals_b; - - /* - * Create channel information array - */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - spec->channels_info = info; - - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - - return 0; -} - -static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Allocate eeprom data. - */ - retval = rt2400pci_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt2400pci_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt2400pci_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device requires the atim queue and DMA-mapped skbs. - */ - __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; -} - -/* - * IEEE80211 stack callback functions. - */ -static int rt2400pci_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - /* - * We don't support variating cw_min and cw_max variables - * per queue. So by default we only configure the TX queue, - * and ignore all other configurations. - */ - if (queue != 0) - return -EINVAL; - - if (rt2x00mac_conf_tx(hw, queue, params)) - return -EINVAL; - - /* - * Write configuration to register. - */ - rt2400pci_config_cw(rt2x00dev, - rt2x00dev->tx->cw_min, rt2x00dev->tx->cw_max); - - return 0; -} - -static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u64 tsf; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR17, ®); - tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; - rt2x00pci_register_read(rt2x00dev, CSR16, ®); - tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); - - return tsf; -} - -static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR15, ®); - return rt2x00_get_field32(reg, CSR15_BEACON_SENT); -} - -static const struct ieee80211_ops rt2400pci_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .get_stats = rt2x00mac_get_stats, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2400pci_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .get_tsf = rt2400pci_get_tsf, - .tx_last_beacon = rt2400pci_tx_last_beacon, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; - -static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = { - .irq_handler = rt2400pci_interrupt, - .probe_hw = rt2400pci_probe_hw, - .initialize = rt2x00pci_initialize, - .uninitialize = rt2x00pci_uninitialize, - .get_entry_state = rt2400pci_get_entry_state, - .clear_entry = rt2400pci_clear_entry, - .set_device_state = rt2400pci_set_device_state, - .rfkill_poll = rt2400pci_rfkill_poll, - .link_stats = rt2400pci_link_stats, - .reset_tuner = rt2400pci_reset_tuner, - .link_tuner = rt2400pci_link_tuner, - .write_tx_desc = rt2400pci_write_tx_desc, - .write_tx_data = rt2x00pci_write_tx_data, - .write_beacon = rt2400pci_write_beacon, - .kick_tx_queue = rt2400pci_kick_tx_queue, - .kill_tx_queue = rt2400pci_kill_tx_queue, - .fill_rxdone = rt2400pci_fill_rxdone, - .config_filter = rt2400pci_config_filter, - .config_intf = rt2400pci_config_intf, - .config_erp = rt2400pci_config_erp, - .config_ant = rt2400pci_config_ant, - .config = rt2400pci_config, -}; - -static const struct data_queue_desc rt2400pci_queue_rx = { - .entry_num = RX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2400pci_queue_tx = { - .entry_num = TX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2400pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2400pci_queue_atim = { - .entry_num = ATIM_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct rt2x00_ops rt2400pci_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 1, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt2400pci_queue_rx, - .tx = &rt2400pci_queue_tx, - .bcn = &rt2400pci_queue_bcn, - .atim = &rt2400pci_queue_atim, - .lib = &rt2400pci_rt2x00_ops, - .hw = &rt2400pci_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2400pci_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * RT2400pci module information. - */ -static struct pci_device_id rt2400pci_device_table[] = { - { PCI_DEVICE(0x1814, 0x0101), PCI_DEVICE_DATA(&rt2400pci_ops) }, - { 0, } -}; - -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Ralink RT2400 PCI & PCMCIA Wireless LAN driver."); -MODULE_SUPPORTED_DEVICE("Ralink RT2460 PCI & PCMCIA chipset based cards"); -MODULE_DEVICE_TABLE(pci, rt2400pci_device_table); -MODULE_LICENSE("GPL"); - -static struct pci_driver rt2400pci_driver = { - .name = KBUILD_MODNAME, - .id_table = rt2400pci_device_table, - .probe = rt2x00pci_probe, - .remove = __devexit_p(rt2x00pci_remove), - .suspend = rt2x00pci_suspend, - .resume = rt2x00pci_resume, -}; - -static int __init rt2400pci_init(void) -{ - return pci_register_driver(&rt2400pci_driver); -} - -static void __exit rt2400pci_exit(void) -{ - pci_unregister_driver(&rt2400pci_driver); -} - -module_init(rt2400pci_init); -module_exit(rt2400pci_exit); diff --git a/drivers/net/wireless/rt2x00/rt2400pci.h b/drivers/net/wireless/rt2x00/rt2400pci.h deleted file mode 100644 index ccd644104ad1..000000000000 --- a/drivers/net/wireless/rt2x00/rt2400pci.h +++ /dev/null @@ -1,952 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2400pci - Abstract: Data structures and registers for the rt2400pci module. - Supported chipsets: RT2460. - */ - -#ifndef RT2400PCI_H -#define RT2400PCI_H - -/* - * RF chip defines. - */ -#define RF2420 0x0000 -#define RF2421 0x0001 - -/* - * Signal information. - * Defaul offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 100 - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x0000 -#define CSR_REG_SIZE 0x014c -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0100 -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0020 -#define RF_BASE 0x0004 -#define RF_SIZE 0x000c - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 2 - -/* - * Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * CSR0: ASIC revision number. - */ -#define CSR0 0x0000 - -/* - * CSR1: System control register. - * SOFT_RESET: Software reset, 1: reset, 0: normal. - * BBP_RESET: Hardware reset, 1: reset, 0, release. - * HOST_READY: Host ready after initialization. - */ -#define CSR1 0x0004 -#define CSR1_SOFT_RESET FIELD32(0x00000001) -#define CSR1_BBP_RESET FIELD32(0x00000002) -#define CSR1_HOST_READY FIELD32(0x00000004) - -/* - * CSR2: System admin status register (invalid). - */ -#define CSR2 0x0008 - -/* - * CSR3: STA MAC address register 0. - */ -#define CSR3 0x000c -#define CSR3_BYTE0 FIELD32(0x000000ff) -#define CSR3_BYTE1 FIELD32(0x0000ff00) -#define CSR3_BYTE2 FIELD32(0x00ff0000) -#define CSR3_BYTE3 FIELD32(0xff000000) - -/* - * CSR4: STA MAC address register 1. - */ -#define CSR4 0x0010 -#define CSR4_BYTE4 FIELD32(0x000000ff) -#define CSR4_BYTE5 FIELD32(0x0000ff00) - -/* - * CSR5: BSSID register 0. - */ -#define CSR5 0x0014 -#define CSR5_BYTE0 FIELD32(0x000000ff) -#define CSR5_BYTE1 FIELD32(0x0000ff00) -#define CSR5_BYTE2 FIELD32(0x00ff0000) -#define CSR5_BYTE3 FIELD32(0xff000000) - -/* - * CSR6: BSSID register 1. - */ -#define CSR6 0x0018 -#define CSR6_BYTE4 FIELD32(0x000000ff) -#define CSR6_BYTE5 FIELD32(0x0000ff00) - -/* - * CSR7: Interrupt source register. - * Write 1 to clear interrupt. - * TBCN_EXPIRE: Beacon timer expired interrupt. - * TWAKE_EXPIRE: Wakeup timer expired interrupt. - * TATIMW_EXPIRE: Timer of atim window expired interrupt. - * TXDONE_TXRING: Tx ring transmit done interrupt. - * TXDONE_ATIMRING: Atim ring transmit done interrupt. - * TXDONE_PRIORING: Priority ring transmit done interrupt. - * RXDONE: Receive done interrupt. - */ -#define CSR7 0x001c -#define CSR7_TBCN_EXPIRE FIELD32(0x00000001) -#define CSR7_TWAKE_EXPIRE FIELD32(0x00000002) -#define CSR7_TATIMW_EXPIRE FIELD32(0x00000004) -#define CSR7_TXDONE_TXRING FIELD32(0x00000008) -#define CSR7_TXDONE_ATIMRING FIELD32(0x00000010) -#define CSR7_TXDONE_PRIORING FIELD32(0x00000020) -#define CSR7_RXDONE FIELD32(0x00000040) - -/* - * CSR8: Interrupt mask register. - * Write 1 to mask interrupt. - * TBCN_EXPIRE: Beacon timer expired interrupt. - * TWAKE_EXPIRE: Wakeup timer expired interrupt. - * TATIMW_EXPIRE: Timer of atim window expired interrupt. - * TXDONE_TXRING: Tx ring transmit done interrupt. - * TXDONE_ATIMRING: Atim ring transmit done interrupt. - * TXDONE_PRIORING: Priority ring transmit done interrupt. - * RXDONE: Receive done interrupt. - */ -#define CSR8 0x0020 -#define CSR8_TBCN_EXPIRE FIELD32(0x00000001) -#define CSR8_TWAKE_EXPIRE FIELD32(0x00000002) -#define CSR8_TATIMW_EXPIRE FIELD32(0x00000004) -#define CSR8_TXDONE_TXRING FIELD32(0x00000008) -#define CSR8_TXDONE_ATIMRING FIELD32(0x00000010) -#define CSR8_TXDONE_PRIORING FIELD32(0x00000020) -#define CSR8_RXDONE FIELD32(0x00000040) - -/* - * CSR9: Maximum frame length register. - * MAX_FRAME_UNIT: Maximum frame length in 128b unit, default: 12. - */ -#define CSR9 0x0024 -#define CSR9_MAX_FRAME_UNIT FIELD32(0x00000f80) - -/* - * CSR11: Back-off control register. - * CWMIN: CWmin. Default cwmin is 31 (2^5 - 1). - * CWMAX: CWmax. Default cwmax is 1023 (2^10 - 1). - * SLOT_TIME: Slot time, default is 20us for 802.11b. - * LONG_RETRY: Long retry count. - * SHORT_RETRY: Short retry count. - */ -#define CSR11 0x002c -#define CSR11_CWMIN FIELD32(0x0000000f) -#define CSR11_CWMAX FIELD32(0x000000f0) -#define CSR11_SLOT_TIME FIELD32(0x00001f00) -#define CSR11_LONG_RETRY FIELD32(0x00ff0000) -#define CSR11_SHORT_RETRY FIELD32(0xff000000) - -/* - * CSR12: Synchronization configuration register 0. - * All units in 1/16 TU. - * BEACON_INTERVAL: Beacon interval, default is 100 TU. - * CFPMAX_DURATION: Cfp maximum duration, default is 100 TU. - */ -#define CSR12 0x0030 -#define CSR12_BEACON_INTERVAL FIELD32(0x0000ffff) -#define CSR12_CFP_MAX_DURATION FIELD32(0xffff0000) - -/* - * CSR13: Synchronization configuration register 1. - * All units in 1/16 TU. - * ATIMW_DURATION: Atim window duration. - * CFP_PERIOD: Cfp period, default is 0 TU. - */ -#define CSR13 0x0034 -#define CSR13_ATIMW_DURATION FIELD32(0x0000ffff) -#define CSR13_CFP_PERIOD FIELD32(0x00ff0000) - -/* - * CSR14: Synchronization control register. - * TSF_COUNT: Enable tsf auto counting. - * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode. - * TBCN: Enable tbcn with reload value. - * TCFP: Enable tcfp & cfp / cp switching. - * TATIMW: Enable tatimw & atim window switching. - * BEACON_GEN: Enable beacon generator. - * CFP_COUNT_PRELOAD: Cfp count preload value. - * TBCM_PRELOAD: Tbcn preload value in units of 64us. - */ -#define CSR14 0x0038 -#define CSR14_TSF_COUNT FIELD32(0x00000001) -#define CSR14_TSF_SYNC FIELD32(0x00000006) -#define CSR14_TBCN FIELD32(0x00000008) -#define CSR14_TCFP FIELD32(0x00000010) -#define CSR14_TATIMW FIELD32(0x00000020) -#define CSR14_BEACON_GEN FIELD32(0x00000040) -#define CSR14_CFP_COUNT_PRELOAD FIELD32(0x0000ff00) -#define CSR14_TBCM_PRELOAD FIELD32(0xffff0000) - -/* - * CSR15: Synchronization status register. - * CFP: ASIC is in contention-free period. - * ATIMW: ASIC is in ATIM window. - * BEACON_SENT: Beacon is send. - */ -#define CSR15 0x003c -#define CSR15_CFP FIELD32(0x00000001) -#define CSR15_ATIMW FIELD32(0x00000002) -#define CSR15_BEACON_SENT FIELD32(0x00000004) - -/* - * CSR16: TSF timer register 0. - */ -#define CSR16 0x0040 -#define CSR16_LOW_TSFTIMER FIELD32(0xffffffff) - -/* - * CSR17: TSF timer register 1. - */ -#define CSR17 0x0044 -#define CSR17_HIGH_TSFTIMER FIELD32(0xffffffff) - -/* - * CSR18: IFS timer register 0. - * SIFS: Sifs, default is 10 us. - * PIFS: Pifs, default is 30 us. - */ -#define CSR18 0x0048 -#define CSR18_SIFS FIELD32(0x0000ffff) -#define CSR18_PIFS FIELD32(0xffff0000) - -/* - * CSR19: IFS timer register 1. - * DIFS: Difs, default is 50 us. - * EIFS: Eifs, default is 364 us. - */ -#define CSR19 0x004c -#define CSR19_DIFS FIELD32(0x0000ffff) -#define CSR19_EIFS FIELD32(0xffff0000) - -/* - * CSR20: Wakeup timer register. - * DELAY_AFTER_TBCN: Delay after tbcn expired in units of 1/16 TU. - * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup. - * AUTOWAKE: Enable auto wakeup / sleep mechanism. - */ -#define CSR20 0x0050 -#define CSR20_DELAY_AFTER_TBCN FIELD32(0x0000ffff) -#define CSR20_TBCN_BEFORE_WAKEUP FIELD32(0x00ff0000) -#define CSR20_AUTOWAKE FIELD32(0x01000000) - -/* - * CSR21: EEPROM control register. - * RELOAD: Write 1 to reload eeprom content. - * TYPE_93C46: 1: 93c46, 0:93c66. - */ -#define CSR21 0x0054 -#define CSR21_RELOAD FIELD32(0x00000001) -#define CSR21_EEPROM_DATA_CLOCK FIELD32(0x00000002) -#define CSR21_EEPROM_CHIP_SELECT FIELD32(0x00000004) -#define CSR21_EEPROM_DATA_IN FIELD32(0x00000008) -#define CSR21_EEPROM_DATA_OUT FIELD32(0x00000010) -#define CSR21_TYPE_93C46 FIELD32(0x00000020) - -/* - * CSR22: CFP control register. - * CFP_DURATION_REMAIN: Cfp duration remain, in units of TU. - * RELOAD_CFP_DURATION: Write 1 to reload cfp duration remain. - */ -#define CSR22 0x0058 -#define CSR22_CFP_DURATION_REMAIN FIELD32(0x0000ffff) -#define CSR22_RELOAD_CFP_DURATION FIELD32(0x00010000) - -/* - * Transmit related CSRs. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * TXCSR0: TX Control Register. - * KICK_TX: Kick tx ring. - * KICK_ATIM: Kick atim ring. - * KICK_PRIO: Kick priority ring. - * ABORT: Abort all transmit related ring operation. - */ -#define TXCSR0 0x0060 -#define TXCSR0_KICK_TX FIELD32(0x00000001) -#define TXCSR0_KICK_ATIM FIELD32(0x00000002) -#define TXCSR0_KICK_PRIO FIELD32(0x00000004) -#define TXCSR0_ABORT FIELD32(0x00000008) - -/* - * TXCSR1: TX Configuration Register. - * ACK_TIMEOUT: Ack timeout, default = sifs + 2*slottime + acktime @ 1mbps. - * ACK_CONSUME_TIME: Ack consume time, default = sifs + acktime @ 1mbps. - * TSF_OFFSET: Insert tsf offset. - * AUTORESPONDER: Enable auto responder which include ack & cts. - */ -#define TXCSR1 0x0064 -#define TXCSR1_ACK_TIMEOUT FIELD32(0x000001ff) -#define TXCSR1_ACK_CONSUME_TIME FIELD32(0x0003fe00) -#define TXCSR1_TSF_OFFSET FIELD32(0x00fc0000) -#define TXCSR1_AUTORESPONDER FIELD32(0x01000000) - -/* - * TXCSR2: Tx descriptor configuration register. - * TXD_SIZE: Tx descriptor size, default is 48. - * NUM_TXD: Number of tx entries in ring. - * NUM_ATIM: Number of atim entries in ring. - * NUM_PRIO: Number of priority entries in ring. - */ -#define TXCSR2 0x0068 -#define TXCSR2_TXD_SIZE FIELD32(0x000000ff) -#define TXCSR2_NUM_TXD FIELD32(0x0000ff00) -#define TXCSR2_NUM_ATIM FIELD32(0x00ff0000) -#define TXCSR2_NUM_PRIO FIELD32(0xff000000) - -/* - * TXCSR3: TX Ring Base address register. - */ -#define TXCSR3 0x006c -#define TXCSR3_TX_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR4: TX Atim Ring Base address register. - */ -#define TXCSR4 0x0070 -#define TXCSR4_ATIM_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR5: TX Prio Ring Base address register. - */ -#define TXCSR5 0x0074 -#define TXCSR5_PRIO_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR6: Beacon Base address register. - */ -#define TXCSR6 0x0078 -#define TXCSR6_BEACON_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR7: Auto responder control register. - * AR_POWERMANAGEMENT: Auto responder power management bit. - */ -#define TXCSR7 0x007c -#define TXCSR7_AR_POWERMANAGEMENT FIELD32(0x00000001) - -/* - * Receive related CSRs. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * RXCSR0: RX Control Register. - * DISABLE_RX: Disable rx engine. - * DROP_CRC: Drop crc error. - * DROP_PHYSICAL: Drop physical error. - * DROP_CONTROL: Drop control frame. - * DROP_NOT_TO_ME: Drop not to me unicast frame. - * DROP_TODS: Drop frame tods bit is true. - * DROP_VERSION_ERROR: Drop version error frame. - * PASS_CRC: Pass all packets with crc attached. - */ -#define RXCSR0 0x0080 -#define RXCSR0_DISABLE_RX FIELD32(0x00000001) -#define RXCSR0_DROP_CRC FIELD32(0x00000002) -#define RXCSR0_DROP_PHYSICAL FIELD32(0x00000004) -#define RXCSR0_DROP_CONTROL FIELD32(0x00000008) -#define RXCSR0_DROP_NOT_TO_ME FIELD32(0x00000010) -#define RXCSR0_DROP_TODS FIELD32(0x00000020) -#define RXCSR0_DROP_VERSION_ERROR FIELD32(0x00000040) -#define RXCSR0_PASS_CRC FIELD32(0x00000080) - -/* - * RXCSR1: RX descriptor configuration register. - * RXD_SIZE: Rx descriptor size, default is 32b. - * NUM_RXD: Number of rx entries in ring. - */ -#define RXCSR1 0x0084 -#define RXCSR1_RXD_SIZE FIELD32(0x000000ff) -#define RXCSR1_NUM_RXD FIELD32(0x0000ff00) - -/* - * RXCSR2: RX Ring base address register. - */ -#define RXCSR2 0x0088 -#define RXCSR2_RX_RING_REGISTER FIELD32(0xffffffff) - -/* - * RXCSR3: BBP ID register for Rx operation. - * BBP_ID#: BBP register # id. - * BBP_ID#_VALID: BBP register # id is valid or not. - */ -#define RXCSR3 0x0090 -#define RXCSR3_BBP_ID0 FIELD32(0x0000007f) -#define RXCSR3_BBP_ID0_VALID FIELD32(0x00000080) -#define RXCSR3_BBP_ID1 FIELD32(0x00007f00) -#define RXCSR3_BBP_ID1_VALID FIELD32(0x00008000) -#define RXCSR3_BBP_ID2 FIELD32(0x007f0000) -#define RXCSR3_BBP_ID2_VALID FIELD32(0x00800000) -#define RXCSR3_BBP_ID3 FIELD32(0x7f000000) -#define RXCSR3_BBP_ID3_VALID FIELD32(0x80000000) - -/* - * RXCSR4: BBP ID register for Rx operation. - * BBP_ID#: BBP register # id. - * BBP_ID#_VALID: BBP register # id is valid or not. - */ -#define RXCSR4 0x0094 -#define RXCSR4_BBP_ID4 FIELD32(0x0000007f) -#define RXCSR4_BBP_ID4_VALID FIELD32(0x00000080) -#define RXCSR4_BBP_ID5 FIELD32(0x00007f00) -#define RXCSR4_BBP_ID5_VALID FIELD32(0x00008000) - -/* - * ARCSR0: Auto Responder PLCP config register 0. - * ARCSR0_AR_BBP_DATA#: Auto responder BBP register # data. - * ARCSR0_AR_BBP_ID#: Auto responder BBP register # Id. - */ -#define ARCSR0 0x0098 -#define ARCSR0_AR_BBP_DATA0 FIELD32(0x000000ff) -#define ARCSR0_AR_BBP_ID0 FIELD32(0x0000ff00) -#define ARCSR0_AR_BBP_DATA1 FIELD32(0x00ff0000) -#define ARCSR0_AR_BBP_ID1 FIELD32(0xff000000) - -/* - * ARCSR1: Auto Responder PLCP config register 1. - * ARCSR0_AR_BBP_DATA#: Auto responder BBP register # data. - * ARCSR0_AR_BBP_ID#: Auto responder BBP register # Id. - */ -#define ARCSR1 0x009c -#define ARCSR1_AR_BBP_DATA2 FIELD32(0x000000ff) -#define ARCSR1_AR_BBP_ID2 FIELD32(0x0000ff00) -#define ARCSR1_AR_BBP_DATA3 FIELD32(0x00ff0000) -#define ARCSR1_AR_BBP_ID3 FIELD32(0xff000000) - -/* - * Miscellaneous Registers. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * PCICSR: PCI control register. - * BIG_ENDIAN: 1: big endian, 0: little endian. - * RX_TRESHOLD: Rx threshold in dw to start pci access - * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw. - * TX_TRESHOLD: Tx threshold in dw to start pci access - * 0: 0dw (default), 1: 1dw, 2: 4dw, 3: forward. - * BURST_LENTH: Pci burst length 0: 4dw (default, 1: 8dw, 2: 16dw, 3:32dw. - * ENABLE_CLK: Enable clk_run, pci clock can't going down to non-operational. - */ -#define PCICSR 0x008c -#define PCICSR_BIG_ENDIAN FIELD32(0x00000001) -#define PCICSR_RX_TRESHOLD FIELD32(0x00000006) -#define PCICSR_TX_TRESHOLD FIELD32(0x00000018) -#define PCICSR_BURST_LENTH FIELD32(0x00000060) -#define PCICSR_ENABLE_CLK FIELD32(0x00000080) - -/* - * CNT0: FCS error count. - * FCS_ERROR: FCS error count, cleared when read. - */ -#define CNT0 0x00a0 -#define CNT0_FCS_ERROR FIELD32(0x0000ffff) - -/* - * Statistic Register. - * CNT1: PLCP error count. - * CNT2: Long error count. - * CNT3: CCA false alarm count. - * CNT4: Rx FIFO overflow count. - * CNT5: Tx FIFO underrun count. - */ -#define TIMECSR2 0x00a8 -#define CNT1 0x00ac -#define CNT2 0x00b0 -#define TIMECSR3 0x00b4 -#define CNT3 0x00b8 -#define CNT4 0x00bc -#define CNT5 0x00c0 - -/* - * Baseband Control Register. - */ - -/* - * PWRCSR0: Power mode configuration register. - */ -#define PWRCSR0 0x00c4 - -/* - * Power state transition time registers. - */ -#define PSCSR0 0x00c8 -#define PSCSR1 0x00cc -#define PSCSR2 0x00d0 -#define PSCSR3 0x00d4 - -/* - * PWRCSR1: Manual power control / status register. - * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake. - * SET_STATE: Set state. Write 1 to trigger, self cleared. - * BBP_DESIRE_STATE: BBP desired state. - * RF_DESIRE_STATE: RF desired state. - * BBP_CURR_STATE: BBP current state. - * RF_CURR_STATE: RF current state. - * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared. - */ -#define PWRCSR1 0x00d8 -#define PWRCSR1_SET_STATE FIELD32(0x00000001) -#define PWRCSR1_BBP_DESIRE_STATE FIELD32(0x00000006) -#define PWRCSR1_RF_DESIRE_STATE FIELD32(0x00000018) -#define PWRCSR1_BBP_CURR_STATE FIELD32(0x00000060) -#define PWRCSR1_RF_CURR_STATE FIELD32(0x00000180) -#define PWRCSR1_PUT_TO_SLEEP FIELD32(0x00000200) - -/* - * TIMECSR: Timer control register. - * US_COUNT: 1 us timer count in units of clock cycles. - * US_64_COUNT: 64 us timer count in units of 1 us timer. - * BEACON_EXPECT: Beacon expect window. - */ -#define TIMECSR 0x00dc -#define TIMECSR_US_COUNT FIELD32(0x000000ff) -#define TIMECSR_US_64_COUNT FIELD32(0x0000ff00) -#define TIMECSR_BEACON_EXPECT FIELD32(0x00070000) - -/* - * MACCSR0: MAC configuration register 0. - */ -#define MACCSR0 0x00e0 - -/* - * MACCSR1: MAC configuration register 1. - * KICK_RX: Kick one-shot rx in one-shot rx mode. - * ONESHOT_RXMODE: Enable one-shot rx mode for debugging. - * BBPRX_RESET_MODE: Ralink bbp rx reset mode. - * AUTO_TXBBP: Auto tx logic access bbp control register. - * AUTO_RXBBP: Auto rx logic access bbp control register. - * LOOPBACK: Loopback mode. 0: normal, 1: internal, 2: external, 3:rsvd. - * INTERSIL_IF: Intersil if calibration pin. - */ -#define MACCSR1 0x00e4 -#define MACCSR1_KICK_RX FIELD32(0x00000001) -#define MACCSR1_ONESHOT_RXMODE FIELD32(0x00000002) -#define MACCSR1_BBPRX_RESET_MODE FIELD32(0x00000004) -#define MACCSR1_AUTO_TXBBP FIELD32(0x00000008) -#define MACCSR1_AUTO_RXBBP FIELD32(0x00000010) -#define MACCSR1_LOOPBACK FIELD32(0x00000060) -#define MACCSR1_INTERSIL_IF FIELD32(0x00000080) - -/* - * RALINKCSR: Ralink Rx auto-reset BBCR. - * AR_BBP_DATA#: Auto reset BBP register # data. - * AR_BBP_ID#: Auto reset BBP register # id. - */ -#define RALINKCSR 0x00e8 -#define RALINKCSR_AR_BBP_DATA0 FIELD32(0x000000ff) -#define RALINKCSR_AR_BBP_ID0 FIELD32(0x0000ff00) -#define RALINKCSR_AR_BBP_DATA1 FIELD32(0x00ff0000) -#define RALINKCSR_AR_BBP_ID1 FIELD32(0xff000000) - -/* - * BCNCSR: Beacon interval control register. - * CHANGE: Write one to change beacon interval. - * DELTATIME: The delta time value. - * NUM_BEACON: Number of beacon according to mode. - * MODE: Please refer to asic specs. - * PLUS: Plus or minus delta time value. - */ -#define BCNCSR 0x00ec -#define BCNCSR_CHANGE FIELD32(0x00000001) -#define BCNCSR_DELTATIME FIELD32(0x0000001e) -#define BCNCSR_NUM_BEACON FIELD32(0x00001fe0) -#define BCNCSR_MODE FIELD32(0x00006000) -#define BCNCSR_PLUS FIELD32(0x00008000) - -/* - * BBP / RF / IF Control Register. - */ - -/* - * BBPCSR: BBP serial control register. - * VALUE: Register value to program into BBP. - * REGNUM: Selected BBP register. - * BUSY: 1: asic is busy execute BBP programming. - * WRITE_CONTROL: 1: write BBP, 0: read BBP. - */ -#define BBPCSR 0x00f0 -#define BBPCSR_VALUE FIELD32(0x000000ff) -#define BBPCSR_REGNUM FIELD32(0x00007f00) -#define BBPCSR_BUSY FIELD32(0x00008000) -#define BBPCSR_WRITE_CONTROL FIELD32(0x00010000) - -/* - * RFCSR: RF serial control register. - * VALUE: Register value + id to program into rf/if. - * NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22). - * IF_SELECT: Chip to program: 0: rf, 1: if. - * PLL_LD: Rf pll_ld status. - * BUSY: 1: asic is busy execute rf programming. - */ -#define RFCSR 0x00f4 -#define RFCSR_VALUE FIELD32(0x00ffffff) -#define RFCSR_NUMBER_OF_BITS FIELD32(0x1f000000) -#define RFCSR_IF_SELECT FIELD32(0x20000000) -#define RFCSR_PLL_LD FIELD32(0x40000000) -#define RFCSR_BUSY FIELD32(0x80000000) - -/* - * LEDCSR: LED control register. - * ON_PERIOD: On period, default 70ms. - * OFF_PERIOD: Off period, default 30ms. - * LINK: 0: linkoff, 1: linkup. - * ACTIVITY: 0: idle, 1: active. - */ -#define LEDCSR 0x00f8 -#define LEDCSR_ON_PERIOD FIELD32(0x000000ff) -#define LEDCSR_OFF_PERIOD FIELD32(0x0000ff00) -#define LEDCSR_LINK FIELD32(0x00010000) -#define LEDCSR_ACTIVITY FIELD32(0x00020000) - -/* - * ASIC pointer information. - * RXPTR: Current RX ring address. - * TXPTR: Current Tx ring address. - * PRIPTR: Current Priority ring address. - * ATIMPTR: Current ATIM ring address. - */ -#define RXPTR 0x0100 -#define TXPTR 0x0104 -#define PRIPTR 0x0108 -#define ATIMPTR 0x010c - -/* - * GPIO and others. - */ - -/* - * GPIOCSR: GPIO control register. - */ -#define GPIOCSR 0x0120 -#define GPIOCSR_BIT0 FIELD32(0x00000001) -#define GPIOCSR_BIT1 FIELD32(0x00000002) -#define GPIOCSR_BIT2 FIELD32(0x00000004) -#define GPIOCSR_BIT3 FIELD32(0x00000008) -#define GPIOCSR_BIT4 FIELD32(0x00000010) -#define GPIOCSR_BIT5 FIELD32(0x00000020) -#define GPIOCSR_BIT6 FIELD32(0x00000040) -#define GPIOCSR_BIT7 FIELD32(0x00000080) - -/* - * BBPPCSR: BBP Pin control register. - */ -#define BBPPCSR 0x0124 - -/* - * BCNCSR1: Tx BEACON offset time control register. - * PRELOAD: Beacon timer offset in units of usec. - */ -#define BCNCSR1 0x0130 -#define BCNCSR1_PRELOAD FIELD32(0x0000ffff) - -/* - * MACCSR2: TX_PE to RX_PE turn-around time control register - * DELAY: RX_PE low width, in units of pci clock cycle. - */ -#define MACCSR2 0x0134 -#define MACCSR2_DELAY FIELD32(0x000000ff) - -/* - * ARCSR2: 1 Mbps ACK/CTS PLCP. - */ -#define ARCSR2 0x013c -#define ARCSR2_SIGNAL FIELD32(0x000000ff) -#define ARCSR2_SERVICE FIELD32(0x0000ff00) -#define ARCSR2_LENGTH_LOW FIELD32(0x00ff0000) -#define ARCSR2_LENGTH FIELD32(0xffff0000) - -/* - * ARCSR3: 2 Mbps ACK/CTS PLCP. - */ -#define ARCSR3 0x0140 -#define ARCSR3_SIGNAL FIELD32(0x000000ff) -#define ARCSR3_SERVICE FIELD32(0x0000ff00) -#define ARCSR3_LENGTH FIELD32(0xffff0000) - -/* - * ARCSR4: 5.5 Mbps ACK/CTS PLCP. - */ -#define ARCSR4 0x0144 -#define ARCSR4_SIGNAL FIELD32(0x000000ff) -#define ARCSR4_SERVICE FIELD32(0x0000ff00) -#define ARCSR4_LENGTH FIELD32(0xffff0000) - -/* - * ARCSR5: 11 Mbps ACK/CTS PLCP. - */ -#define ARCSR5 0x0148 -#define ARCSR5_SIGNAL FIELD32(0x000000ff) -#define ARCSR5_SERVICE FIELD32(0x0000ff00) -#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 1 - */ -#define RF1_TUNER FIELD32(0x00020000) - -/* - * RF 3 - */ -#define RF3_TUNER FIELD32(0x00000100) -#define RF3_TXPOWER FIELD32(0x00003e00) - -/* - * EEPROM content. - * The wordsize of the EEPROM is 16 bits. - */ - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM antenna. - * ANTENNA_NUM: Number of antenna's. - * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * RF_TYPE: Rf_type of this adapter. - * LED_MODE: 0: default, 1: TX/RX activity,2: Single (ignore link), 3: rsvd. - * RX_AGCVGC: 0: disable, 1:enable BBP R13 tuning. - * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0. - */ -#define EEPROM_ANTENNA 0x0b -#define EEPROM_ANTENNA_NUM FIELD16(0x0003) -#define EEPROM_ANTENNA_TX_DEFAULT FIELD16(0x000c) -#define EEPROM_ANTENNA_RX_DEFAULT FIELD16(0x0030) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0040) -#define EEPROM_ANTENNA_LED_MODE FIELD16(0x0180) -#define EEPROM_ANTENNA_RX_AGCVGC_TUNING FIELD16(0x0200) -#define EEPROM_ANTENNA_HARDWARE_RADIO FIELD16(0x0400) - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x0c -#define EEPROM_BBP_SIZE 7 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * EEPROM TXPOWER - */ -#define EEPROM_TXPOWER_START 0x13 -#define EEPROM_TXPOWER_SIZE 7 -#define EEPROM_TXPOWER_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_2 FIELD16(0xff00) - -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE ( 8 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 8 * sizeof(__le32) ) - -/* - * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. - */ - -/* - * Word0 - */ -#define TXD_W0_OWNER_NIC FIELD32(0x00000001) -#define TXD_W0_VALID FIELD32(0x00000002) -#define TXD_W0_RESULT FIELD32(0x0000001c) -#define TXD_W0_RETRY_COUNT FIELD32(0x000000e0) -#define TXD_W0_MORE_FRAG FIELD32(0x00000100) -#define TXD_W0_ACK FIELD32(0x00000200) -#define TXD_W0_TIMESTAMP FIELD32(0x00000400) -#define TXD_W0_RTS FIELD32(0x00000800) -#define TXD_W0_IFS FIELD32(0x00006000) -#define TXD_W0_RETRY_MODE FIELD32(0x00008000) -#define TXD_W0_AGC FIELD32(0x00ff0000) -#define TXD_W0_R2 FIELD32(0xff000000) - -/* - * Word1 - */ -#define TXD_W1_BUFFER_ADDRESS FIELD32(0xffffffff) - -/* - * Word2 - */ -#define TXD_W2_BUFFER_LENGTH FIELD32(0x0000ffff) -#define TXD_W2_DATABYTE_COUNT FIELD32(0xffff0000) - -/* - * Word3 & 4: PLCP information - * The PLCP values should be treated as if they were BBP values. - */ -#define TXD_W3_PLCP_SIGNAL FIELD32(0x000000ff) -#define TXD_W3_PLCP_SIGNAL_REGNUM FIELD32(0x00007f00) -#define TXD_W3_PLCP_SIGNAL_BUSY FIELD32(0x00008000) -#define TXD_W3_PLCP_SERVICE FIELD32(0x00ff0000) -#define TXD_W3_PLCP_SERVICE_REGNUM FIELD32(0x7f000000) -#define TXD_W3_PLCP_SERVICE_BUSY FIELD32(0x80000000) - -#define TXD_W4_PLCP_LENGTH_LOW FIELD32(0x000000ff) -#define TXD_W3_PLCP_LENGTH_LOW_REGNUM FIELD32(0x00007f00) -#define TXD_W3_PLCP_LENGTH_LOW_BUSY FIELD32(0x00008000) -#define TXD_W4_PLCP_LENGTH_HIGH FIELD32(0x00ff0000) -#define TXD_W3_PLCP_LENGTH_HIGH_REGNUM FIELD32(0x7f000000) -#define TXD_W3_PLCP_LENGTH_HIGH_BUSY FIELD32(0x80000000) - -/* - * Word5 - */ -#define TXD_W5_BBCR4 FIELD32(0x0000ffff) -#define TXD_W5_AGC_REG FIELD32(0x007f0000) -#define TXD_W5_AGC_REG_VALID FIELD32(0x00800000) -#define TXD_W5_XXX_REG FIELD32(0x7f000000) -#define TXD_W5_XXX_REG_VALID FIELD32(0x80000000) - -/* - * Word6 - */ -#define TXD_W6_SK_BUFF FIELD32(0xffffffff) - -/* - * Word7 - */ -#define TXD_W7_RESERVED FIELD32(0xffffffff) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - */ -#define RXD_W0_OWNER_NIC FIELD32(0x00000001) -#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000002) -#define RXD_W0_MULTICAST FIELD32(0x00000004) -#define RXD_W0_BROADCAST FIELD32(0x00000008) -#define RXD_W0_MY_BSS FIELD32(0x00000010) -#define RXD_W0_CRC_ERROR FIELD32(0x00000020) -#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080) -#define RXD_W0_DATABYTE_COUNT FIELD32(0xffff0000) - -/* - * Word1 - */ -#define RXD_W1_BUFFER_ADDRESS FIELD32(0xffffffff) - -/* - * Word2 - */ -#define RXD_W2_BUFFER_LENGTH FIELD32(0x0000ffff) -#define RXD_W2_BBR0 FIELD32(0x00ff0000) -#define RXD_W2_SIGNAL FIELD32(0xff000000) - -/* - * Word3 - */ -#define RXD_W3_RSSI FIELD32(0x000000ff) -#define RXD_W3_BBR3 FIELD32(0x0000ff00) -#define RXD_W3_BBR4 FIELD32(0x00ff0000) -#define RXD_W3_BBR5 FIELD32(0xff000000) - -/* - * Word4 - */ -#define RXD_W4_RX_END_TIME FIELD32(0xffffffff) - -/* - * Word5 & 6 & 7: Reserved - */ -#define RXD_W5_RESERVED FIELD32(0xffffffff) -#define RXD_W6_RESERVED FIELD32(0xffffffff) -#define RXD_W7_RESERVED FIELD32(0xffffffff) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - * NOTE: Logics in rt2400pci for txpower are reversed - * compared to the other rt2x00 drivers. A higher txpower - * value means that the txpower must be lowered. This is - * important when converting the value coming from the - * mac80211 stack to the rt2400 acceptable value. - */ -#define MIN_TXPOWER 31 -#define MAX_TXPOWER 62 -#define DEFAULT_TXPOWER 39 - -#define __CLAMP_TX(__txpower) \ - clamp_t(char, (__txpower), MIN_TXPOWER, MAX_TXPOWER) - -#define TXPOWER_FROM_DEV(__txpower) \ - ((__CLAMP_TX(__txpower) - MAX_TXPOWER) + MIN_TXPOWER) - -#define TXPOWER_TO_DEV(__txpower) \ - MAX_TXPOWER - (__CLAMP_TX(__txpower) - MIN_TXPOWER) - -#endif /* RT2400PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c deleted file mode 100644 index 2e872ac69826..000000000000 --- a/drivers/net/wireless/rt2x00/rt2500pci.c +++ /dev/null @@ -1,1976 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2500pci - Abstract: rt2500pci device specific routines. - Supported chipsets: RT2560. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00pci.h" -#include "rt2500pci.h" - -/* - * Register access. - * All access to the CSR registers will go through the methods - * rt2x00pci_register_read and rt2x00pci_register_write. - * BBP and RF register require indirect register access, - * and use the CSR registers BBPCSR and RFCSR to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - */ -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), BBPCSR, BBPCSR_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), RFCSR, RFCSR_BUSY, (__reg)) - -static void rt2500pci_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBPCSR_VALUE, value); - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 1); - - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2500pci_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBPCSR_REGNUM, word); - rt2x00_set_field32(®, BBPCSR_BUSY, 1); - rt2x00_set_field32(®, BBPCSR_WRITE_CONTROL, 0); - - rt2x00pci_register_write(rt2x00dev, BBPCSR, reg); - - WAIT_FOR_BBP(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, BBPCSR_VALUE); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2500pci_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RFCSR_VALUE, value); - rt2x00_set_field32(®, RFCSR_NUMBER_OF_BITS, 20); - rt2x00_set_field32(®, RFCSR_IF_SELECT, 0); - rt2x00_set_field32(®, RFCSR_BUSY, 1); - - rt2x00pci_register_write(rt2x00dev, RFCSR, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2500pci_eepromregister_read(struct eeprom_93cx6 *eeprom) -{ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR21, ®); - - eeprom->reg_data_in = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_IN); - eeprom->reg_data_out = !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_OUT); - eeprom->reg_data_clock = - !!rt2x00_get_field32(reg, CSR21_EEPROM_DATA_CLOCK); - eeprom->reg_chip_select = - !!rt2x00_get_field32(reg, CSR21_EEPROM_CHIP_SELECT); -} - -static void rt2500pci_eepromregister_write(struct eeprom_93cx6 *eeprom) -{ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg = 0; - - rt2x00_set_field32(®, CSR21_EEPROM_DATA_IN, !!eeprom->reg_data_in); - rt2x00_set_field32(®, CSR21_EEPROM_DATA_OUT, !!eeprom->reg_data_out); - rt2x00_set_field32(®, CSR21_EEPROM_DATA_CLOCK, - !!eeprom->reg_data_clock); - rt2x00_set_field32(®, CSR21_EEPROM_CHIP_SELECT, - !!eeprom->reg_chip_select); - - rt2x00pci_register_write(rt2x00dev, CSR21, reg); -} - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -static const struct rt2x00debug rt2500pci_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = rt2x00pci_register_read, - .write = rt2x00pci_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u32), - .word_count = CSR_REG_SIZE / sizeof(u32), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt2500pci_bbp_read, - .write = rt2500pci_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt2500pci_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -static int rt2500pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, GPIOCSR, ®); - return rt2x00_get_field32(reg, GPIOCSR_BIT0); -} - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt2500pci_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - u32 reg; - - rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); - - if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) - rt2x00_set_field32(®, LEDCSR_LINK, enabled); - else if (led->type == LED_TYPE_ACTIVITY) - rt2x00_set_field32(®, LEDCSR_ACTIVITY, enabled); - - rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); -} - -static int rt2500pci_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u32 reg; - - rt2x00pci_register_read(led->rt2x00dev, LEDCSR, ®); - rt2x00_set_field32(®, LEDCSR_ON_PERIOD, *delay_on); - rt2x00_set_field32(®, LEDCSR_OFF_PERIOD, *delay_off); - rt2x00pci_register_write(led->rt2x00dev, LEDCSR, reg); - - return 0; -} - -static void rt2500pci_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt2500pci_brightness_set; - led->led_dev.blink_set = rt2500pci_blink_set; - led->flags = LED_INITIALIZED; -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ -static void rt2500pci_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u32 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DROP_CRC, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_PHYSICAL, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RXCSR0_DROP_CONTROL, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RXCSR0_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RXCSR0_DROP_TODS, - !(filter_flags & FIF_PROMISC_IN_BSS) && - !rt2x00dev->intf_ap_count); - rt2x00_set_field32(®, RXCSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, RXCSR0_DROP_MCAST, - !(filter_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, RXCSR0_DROP_BCAST, 0); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - -static void rt2500pci_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags) -{ - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); - unsigned int bcn_preload; - u32 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Enable beacon config - */ - bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); - rt2x00pci_register_read(rt2x00dev, BCNCSR1, ®); - rt2x00_set_field32(®, BCNCSR1_PRELOAD, bcn_preload); - rt2x00_set_field32(®, BCNCSR1_BEACON_CWMIN, queue->cw_min); - rt2x00pci_register_write(rt2x00dev, BCNCSR1, reg); - - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TSF_SYNC, conf->sync); - rt2x00_set_field32(®, CSR14_TBCN, 1); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - } - - if (flags & CONFIG_UPDATE_MAC) - rt2x00pci_register_multiwrite(rt2x00dev, CSR3, - conf->mac, sizeof(conf->mac)); - - if (flags & CONFIG_UPDATE_BSSID) - rt2x00pci_register_multiwrite(rt2x00dev, CSR5, - conf->bssid, sizeof(conf->bssid)); -} - -static void rt2500pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) -{ - int preamble_mask; - u32 reg; - - /* - * When short preamble is enabled, we should set bit 0x08 - */ - preamble_mask = erp->short_preamble << 3; - - rt2x00pci_register_read(rt2x00dev, TXCSR1, ®); - rt2x00_set_field32(®, TXCSR1_ACK_TIMEOUT, 0x162); - rt2x00_set_field32(®, TXCSR1_ACK_CONSUME_TIME, 0xa2); - rt2x00_set_field32(®, TXCSR1_TSF_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(®, TXCSR1_AUTORESPONDER, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR2, ®); - rt2x00_set_field32(®, ARCSR2_SIGNAL, 0x00); - rt2x00_set_field32(®, ARCSR2_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 10)); - rt2x00pci_register_write(rt2x00dev, ARCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR3, ®); - rt2x00_set_field32(®, ARCSR3_SIGNAL, 0x01 | preamble_mask); - rt2x00_set_field32(®, ARCSR3_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 20)); - rt2x00pci_register_write(rt2x00dev, ARCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR4, ®); - rt2x00_set_field32(®, ARCSR4_SIGNAL, 0x02 | preamble_mask); - rt2x00_set_field32(®, ARCSR4_SERVICE, 0x04); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 55)); - rt2x00pci_register_write(rt2x00dev, ARCSR4, reg); - - rt2x00pci_register_read(rt2x00dev, ARCSR5, ®); - rt2x00_set_field32(®, ARCSR5_SIGNAL, 0x03 | preamble_mask); - rt2x00_set_field32(®, ARCSR5_SERVICE, 0x84); - rt2x00_set_field32(®, ARCSR2_LENGTH, GET_DURATION(ACK_SIZE, 110)); - rt2x00pci_register_write(rt2x00dev, ARCSR5, reg); - - rt2x00pci_register_write(rt2x00dev, ARCSR1, erp->basic_rates); - - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_SLOT_TIME, erp->slot_time); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); - - rt2x00pci_register_read(rt2x00dev, CSR12, ®); - rt2x00_set_field32(®, CSR12_BEACON_INTERVAL, erp->beacon_int * 16); - rt2x00_set_field32(®, CSR12_CFP_MAX_DURATION, erp->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, CSR12, reg); - - rt2x00pci_register_read(rt2x00dev, CSR18, ®); - rt2x00_set_field32(®, CSR18_SIFS, erp->sifs); - rt2x00_set_field32(®, CSR18_PIFS, erp->pifs); - rt2x00pci_register_write(rt2x00dev, CSR18, reg); - - rt2x00pci_register_read(rt2x00dev, CSR19, ®); - rt2x00_set_field32(®, CSR19_DIFS, erp->difs); - rt2x00_set_field32(®, CSR19_EIFS, erp->eifs); - rt2x00pci_register_write(rt2x00dev, CSR19, reg); -} - -static void rt2500pci_config_ant(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u32 reg; - u8 r14; - u8 r2; - - /* - * We should never come here because rt2x00lib is supposed - * to catch this and send us the correct antenna explicitely. - */ - BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || - ant->tx == ANTENNA_SW_DIVERSITY); - - rt2x00pci_register_read(rt2x00dev, BBPCSR1, ®); - rt2500pci_bbp_read(rt2x00dev, 14, &r14); - rt2500pci_bbp_read(rt2x00dev, 2, &r2); - - /* - * Configure the TX antenna. - */ - switch (ant->tx) { - case ANTENNA_A: - rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); - rt2x00_set_field32(®, BBPCSR1_CCK, 0); - rt2x00_set_field32(®, BBPCSR1_OFDM, 0); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); - rt2x00_set_field32(®, BBPCSR1_CCK, 2); - rt2x00_set_field32(®, BBPCSR1_OFDM, 2); - break; - } - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_A: - rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); - break; - } - - /* - * RT2525E and RT5222 need to flip TX I/Q - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || - rt2x00_rf(&rt2x00dev->chip, RF5222)) { - rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); - rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 1); - rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 1); - - /* - * RT2525E does not need RX I/Q Flip. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) - rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); - } else { - rt2x00_set_field32(®, BBPCSR1_CCK_FLIP, 0); - rt2x00_set_field32(®, BBPCSR1_OFDM_FLIP, 0); - } - - rt2x00pci_register_write(rt2x00dev, BBPCSR1, reg); - rt2500pci_bbp_write(rt2x00dev, 14, r14); - rt2500pci_bbp_write(rt2x00dev, 2, r2); -} - -static void rt2500pci_config_channel(struct rt2x00_dev *rt2x00dev, - struct rf_channel *rf, const int txpower) -{ - u8 r70; - - /* - * Set TXpower. - */ - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - - /* - * Switch on tuning bits. - * For RT2523 devices we do not need to update the R1 register. - */ - if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) - rt2x00_set_field32(&rf->rf1, RF1_TUNER, 1); - rt2x00_set_field32(&rf->rf3, RF3_TUNER, 1); - - /* - * For RT2525 we should first set the channel to half band higher. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { - static const u32 vals[] = { - 0x00080cbe, 0x00080d02, 0x00080d06, 0x00080d0a, - 0x00080d0e, 0x00080d12, 0x00080d16, 0x00080d1a, - 0x00080d1e, 0x00080d22, 0x00080d26, 0x00080d2a, - 0x00080d2e, 0x00080d3a - }; - - rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); - rt2500pci_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); - rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); - if (rf->rf4) - rt2500pci_rf_write(rt2x00dev, 4, rf->rf4); - } - - rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); - rt2500pci_rf_write(rt2x00dev, 2, rf->rf2); - rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); - if (rf->rf4) - rt2500pci_rf_write(rt2x00dev, 4, rf->rf4); - - /* - * Channel 14 requires the Japan filter bit to be set. - */ - r70 = 0x46; - rt2x00_set_field8(&r70, BBP_R70_JAPAN_FILTER, rf->channel == 14); - rt2500pci_bbp_write(rt2x00dev, 70, r70); - - msleep(1); - - /* - * Switch off tuning bits. - * For RT2523 devices we do not need to update the R1 register. - */ - if (!rt2x00_rf(&rt2x00dev->chip, RF2523)) { - rt2x00_set_field32(&rf->rf1, RF1_TUNER, 0); - rt2500pci_rf_write(rt2x00dev, 1, rf->rf1); - } - - rt2x00_set_field32(&rf->rf3, RF3_TUNER, 0); - rt2500pci_rf_write(rt2x00dev, 3, rf->rf3); - - /* - * Clear false CRC during channel switch. - */ - rt2x00pci_register_read(rt2x00dev, CNT0, &rf->rf1); -} - -static void rt2500pci_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - u32 rf3; - - rt2x00_rf_read(rt2x00dev, 3, &rf3); - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - rt2500pci_rf_write(rt2x00dev, 3, rf3); -} - -static void rt2500pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_LONG_RETRY, - libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, CSR11_SHORT_RETRY, - libconf->conf->short_frame_max_tx_count); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); -} - -static void rt2500pci_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u32 reg; - - if (state == STATE_SLEEP) { - rt2x00pci_register_read(rt2x00dev, CSR20, ®); - rt2x00_set_field32(®, CSR20_DELAY_AFTER_TBCN, - (rt2x00dev->beacon_int - 20) * 16); - rt2x00_set_field32(®, CSR20_TBCN_BEFORE_WAKEUP, - libconf->conf->listen_interval - 1); - - /* We must first disable autowake before it can be enabled */ - rt2x00_set_field32(®, CSR20_AUTOWAKE, 0); - rt2x00pci_register_write(rt2x00dev, CSR20, reg); - - rt2x00_set_field32(®, CSR20_AUTOWAKE, 1); - rt2x00pci_register_write(rt2x00dev, CSR20, reg); - } - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); -} - -static void rt2500pci_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2500pci_config_channel(rt2x00dev, &libconf->rf, - libconf->conf->power_level); - if ((flags & IEEE80211_CONF_CHANGE_POWER) && - !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) - rt2500pci_config_txpower(rt2x00dev, - libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt2500pci_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt2500pci_config_ps(rt2x00dev, libconf); -} - -/* - * Link tuning - */ -static void rt2500pci_link_stats(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u32 reg; - - /* - * Update FCS error count from register. - */ - rt2x00pci_register_read(rt2x00dev, CNT0, ®); - qual->rx_failed = rt2x00_get_field32(reg, CNT0_FCS_ERROR); - - /* - * Update False CCA count from register. - */ - rt2x00pci_register_read(rt2x00dev, CNT3, ®); - qual->false_cca = rt2x00_get_field32(reg, CNT3_FALSE_CCA); -} - -static inline void rt2500pci_set_vgc(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, u8 vgc_level) -{ - if (qual->vgc_level_reg != vgc_level) { - rt2500pci_bbp_write(rt2x00dev, 17, vgc_level); - qual->vgc_level_reg = vgc_level; - } -} - -static void rt2500pci_reset_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - rt2500pci_set_vgc(rt2x00dev, qual, 0x48); -} - -static void rt2500pci_link_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count) -{ - /* - * To prevent collisions with MAC ASIC on chipsets - * up to version C the link tuning should halt after 20 - * seconds while being associated. - */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D && - rt2x00dev->intf_associated && count > 20) - return; - - /* - * Chipset versions C and lower should directly continue - * to the dynamic CCA tuning. Chipset version D and higher - * should go straight to dynamic CCA tuning when they - * are not associated. - */ - if (rt2x00_rev(&rt2x00dev->chip) < RT2560_VERSION_D || - !rt2x00dev->intf_associated) - goto dynamic_cca_tune; - - /* - * A too low RSSI will cause too much false CCA which will - * then corrupt the R17 tuning. To remidy this the tuning should - * be stopped (While making sure the R17 value will not exceed limits) - */ - if (qual->rssi < -80 && count > 20) { - if (qual->vgc_level_reg >= 0x41) - rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); - return; - } - - /* - * Special big-R17 for short distance - */ - if (qual->rssi >= -58) { - rt2500pci_set_vgc(rt2x00dev, qual, 0x50); - return; - } - - /* - * Special mid-R17 for middle distance - */ - if (qual->rssi >= -74) { - rt2500pci_set_vgc(rt2x00dev, qual, 0x41); - return; - } - - /* - * Leave short or middle distance condition, restore r17 - * to the dynamic tuning range. - */ - if (qual->vgc_level_reg >= 0x41) { - rt2500pci_set_vgc(rt2x00dev, qual, qual->vgc_level); - return; - } - -dynamic_cca_tune: - - /* - * R17 is inside the dynamic tuning range, - * start tuning the link based on the false cca counter. - */ - if (qual->false_cca > 512 && qual->vgc_level_reg < 0x40) { - rt2500pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level_reg); - qual->vgc_level = qual->vgc_level_reg; - } else if (qual->false_cca < 100 && qual->vgc_level_reg > 0x32) { - rt2500pci_set_vgc(rt2x00dev, qual, --qual->vgc_level_reg); - qual->vgc_level = qual->vgc_level_reg; - } -} - -/* - * Initialization functions. - */ -static bool rt2500pci_get_entry_state(struct queue_entry *entry) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - u32 word; - - if (entry->queue->qid == QID_RX) { - rt2x00_desc_read(entry_priv->desc, 0, &word); - - return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); - } else { - rt2x00_desc_read(entry_priv->desc, 0, &word); - - return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || - rt2x00_get_field32(word, TXD_W0_VALID)); - } -} - -static void rt2500pci_clear_entry(struct queue_entry *entry) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; - - if (entry->queue->qid == QID_RX) { - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, RXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); - - rt2x00_desc_read(entry_priv->desc, 0, &word); - rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(entry_priv->desc, 0, word); - } else { - rt2x00_desc_read(entry_priv->desc, 0, &word); - rt2x00_set_field32(&word, TXD_W0_VALID, 0); - rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(entry_priv->desc, 0, word); - } -} - -static int rt2500pci_init_queues(struct rt2x00_dev *rt2x00dev) -{ - struct queue_entry_priv_pci *entry_priv; - u32 reg; - - /* - * Initialize registers. - */ - rt2x00pci_register_read(rt2x00dev, TXCSR2, ®); - rt2x00_set_field32(®, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size); - rt2x00_set_field32(®, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit); - rt2x00_set_field32(®, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit); - rt2x00_set_field32(®, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit); - rt2x00pci_register_write(rt2x00dev, TXCSR2, reg); - - entry_priv = rt2x00dev->tx[1].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR3, ®); - rt2x00_set_field32(®, TXCSR3_TX_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR3, reg); - - entry_priv = rt2x00dev->tx[0].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR5, ®); - rt2x00_set_field32(®, TXCSR5_PRIO_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR5, reg); - - entry_priv = rt2x00dev->bcn[1].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR4, ®); - rt2x00_set_field32(®, TXCSR4_ATIM_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR4, reg); - - entry_priv = rt2x00dev->bcn[0].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, TXCSR6, ®); - rt2x00_set_field32(®, TXCSR6_BEACON_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, TXCSR6, reg); - - rt2x00pci_register_read(rt2x00dev, RXCSR1, ®); - rt2x00_set_field32(®, RXCSR1_RXD_SIZE, rt2x00dev->rx->desc_size); - rt2x00_set_field32(®, RXCSR1_NUM_RXD, rt2x00dev->rx->limit); - rt2x00pci_register_write(rt2x00dev, RXCSR1, reg); - - entry_priv = rt2x00dev->rx->entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, RXCSR2, ®); - rt2x00_set_field32(®, RXCSR2_RX_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, RXCSR2, reg); - - return 0; -} - -static int rt2500pci_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_write(rt2x00dev, PSCSR0, 0x00020002); - rt2x00pci_register_write(rt2x00dev, PSCSR1, 0x00000002); - rt2x00pci_register_write(rt2x00dev, PSCSR2, 0x00020002); - rt2x00pci_register_write(rt2x00dev, PSCSR3, 0x00000002); - - rt2x00pci_register_read(rt2x00dev, TIMECSR, ®); - rt2x00_set_field32(®, TIMECSR_US_COUNT, 33); - rt2x00_set_field32(®, TIMECSR_US_64_COUNT, 63); - rt2x00_set_field32(®, TIMECSR_BEACON_EXPECT, 0); - rt2x00pci_register_write(rt2x00dev, TIMECSR, reg); - - rt2x00pci_register_read(rt2x00dev, CSR9, ®); - rt2x00_set_field32(®, CSR9_MAX_FRAME_UNIT, - rt2x00dev->rx->data_size / 128); - rt2x00pci_register_write(rt2x00dev, CSR9, reg); - - /* - * Always use CWmin and CWmax set in descriptor. - */ - rt2x00pci_register_read(rt2x00dev, CSR11, ®); - rt2x00_set_field32(®, CSR11_CW_SELECT, 0); - rt2x00pci_register_write(rt2x00dev, CSR11, reg); - - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_TSF_COUNT, 0); - rt2x00_set_field32(®, CSR14_TSF_SYNC, 0); - rt2x00_set_field32(®, CSR14_TBCN, 0); - rt2x00_set_field32(®, CSR14_TCFP, 0); - rt2x00_set_field32(®, CSR14_TATIMW, 0); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00_set_field32(®, CSR14_CFP_COUNT_PRELOAD, 0); - rt2x00_set_field32(®, CSR14_TBCM_PRELOAD, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - rt2x00pci_register_write(rt2x00dev, CNT3, 0); - - rt2x00pci_register_read(rt2x00dev, TXCSR8, ®); - rt2x00_set_field32(®, TXCSR8_BBP_ID0, 10); - rt2x00_set_field32(®, TXCSR8_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXCSR8_BBP_ID1, 11); - rt2x00_set_field32(®, TXCSR8_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXCSR8_BBP_ID2, 13); - rt2x00_set_field32(®, TXCSR8_BBP_ID2_VALID, 1); - rt2x00_set_field32(®, TXCSR8_BBP_ID3, 12); - rt2x00_set_field32(®, TXCSR8_BBP_ID3_VALID, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR8, reg); - - rt2x00pci_register_read(rt2x00dev, ARTCSR0, ®); - rt2x00_set_field32(®, ARTCSR0_ACK_CTS_1MBS, 112); - rt2x00_set_field32(®, ARTCSR0_ACK_CTS_2MBS, 56); - rt2x00_set_field32(®, ARTCSR0_ACK_CTS_5_5MBS, 20); - rt2x00_set_field32(®, ARTCSR0_ACK_CTS_11MBS, 10); - rt2x00pci_register_write(rt2x00dev, ARTCSR0, reg); - - rt2x00pci_register_read(rt2x00dev, ARTCSR1, ®); - rt2x00_set_field32(®, ARTCSR1_ACK_CTS_6MBS, 45); - rt2x00_set_field32(®, ARTCSR1_ACK_CTS_9MBS, 37); - rt2x00_set_field32(®, ARTCSR1_ACK_CTS_12MBS, 33); - rt2x00_set_field32(®, ARTCSR1_ACK_CTS_18MBS, 29); - rt2x00pci_register_write(rt2x00dev, ARTCSR1, reg); - - rt2x00pci_register_read(rt2x00dev, ARTCSR2, ®); - rt2x00_set_field32(®, ARTCSR2_ACK_CTS_24MBS, 29); - rt2x00_set_field32(®, ARTCSR2_ACK_CTS_36MBS, 25); - rt2x00_set_field32(®, ARTCSR2_ACK_CTS_48MBS, 25); - rt2x00_set_field32(®, ARTCSR2_ACK_CTS_54MBS, 25); - rt2x00pci_register_write(rt2x00dev, ARTCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, RXCSR3, ®); - rt2x00_set_field32(®, RXCSR3_BBP_ID0, 47); /* CCK Signal */ - rt2x00_set_field32(®, RXCSR3_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, RXCSR3_BBP_ID1, 51); /* Rssi */ - rt2x00_set_field32(®, RXCSR3_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, RXCSR3_BBP_ID2, 42); /* OFDM Rate */ - rt2x00_set_field32(®, RXCSR3_BBP_ID2_VALID, 1); - rt2x00_set_field32(®, RXCSR3_BBP_ID3, 51); /* RSSI */ - rt2x00_set_field32(®, RXCSR3_BBP_ID3_VALID, 1); - rt2x00pci_register_write(rt2x00dev, RXCSR3, reg); - - rt2x00pci_register_read(rt2x00dev, PCICSR, ®); - rt2x00_set_field32(®, PCICSR_BIG_ENDIAN, 0); - rt2x00_set_field32(®, PCICSR_RX_TRESHOLD, 0); - rt2x00_set_field32(®, PCICSR_TX_TRESHOLD, 3); - rt2x00_set_field32(®, PCICSR_BURST_LENTH, 1); - rt2x00_set_field32(®, PCICSR_ENABLE_CLK, 1); - rt2x00_set_field32(®, PCICSR_READ_MULTIPLE, 1); - rt2x00_set_field32(®, PCICSR_WRITE_INVALID, 1); - rt2x00pci_register_write(rt2x00dev, PCICSR, reg); - - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0x3f3b3100); - - rt2x00pci_register_write(rt2x00dev, GPIOCSR, 0x0000ff00); - rt2x00pci_register_write(rt2x00dev, TESTCSR, 0x000000f0); - - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00pci_register_write(rt2x00dev, MACCSR0, 0x00213223); - rt2x00pci_register_write(rt2x00dev, MACCSR1, 0x00235518); - - rt2x00pci_register_read(rt2x00dev, MACCSR2, ®); - rt2x00_set_field32(®, MACCSR2_DELAY, 64); - rt2x00pci_register_write(rt2x00dev, MACCSR2, reg); - - rt2x00pci_register_read(rt2x00dev, RALINKCSR, ®); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA0, 17); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID0, 26); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID0, 1); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_DATA1, 0); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_ID1, 26); - rt2x00_set_field32(®, RALINKCSR_AR_BBP_VALID1, 1); - rt2x00pci_register_write(rt2x00dev, RALINKCSR, reg); - - rt2x00pci_register_write(rt2x00dev, BBPCSR1, 0x82188200); - - rt2x00pci_register_write(rt2x00dev, TXACKCSR0, 0x00000020); - - rt2x00pci_register_read(rt2x00dev, CSR1, ®); - rt2x00_set_field32(®, CSR1_SOFT_RESET, 1); - rt2x00_set_field32(®, CSR1_BBP_RESET, 0); - rt2x00_set_field32(®, CSR1_HOST_READY, 0); - rt2x00pci_register_write(rt2x00dev, CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, CSR1, ®); - rt2x00_set_field32(®, CSR1_SOFT_RESET, 0); - rt2x00_set_field32(®, CSR1_HOST_READY, 1); - rt2x00pci_register_write(rt2x00dev, CSR1, reg); - - /* - * We must clear the FCS and FIFO error count. - * These registers are cleared on read, - * so we may pass a useless variable to store the value. - */ - rt2x00pci_register_read(rt2x00dev, CNT0, ®); - rt2x00pci_register_read(rt2x00dev, CNT4, ®); - - return 0; -} - -static int rt2500pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500pci_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -static int rt2500pci_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 reg_id; - u8 value; - - if (unlikely(rt2500pci_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt2500pci_bbp_write(rt2x00dev, 3, 0x02); - rt2500pci_bbp_write(rt2x00dev, 4, 0x19); - rt2500pci_bbp_write(rt2x00dev, 14, 0x1c); - rt2500pci_bbp_write(rt2x00dev, 15, 0x30); - rt2500pci_bbp_write(rt2x00dev, 16, 0xac); - rt2500pci_bbp_write(rt2x00dev, 18, 0x18); - rt2500pci_bbp_write(rt2x00dev, 19, 0xff); - rt2500pci_bbp_write(rt2x00dev, 20, 0x1e); - rt2500pci_bbp_write(rt2x00dev, 21, 0x08); - rt2500pci_bbp_write(rt2x00dev, 22, 0x08); - rt2500pci_bbp_write(rt2x00dev, 23, 0x08); - rt2500pci_bbp_write(rt2x00dev, 24, 0x70); - rt2500pci_bbp_write(rt2x00dev, 25, 0x40); - rt2500pci_bbp_write(rt2x00dev, 26, 0x08); - rt2500pci_bbp_write(rt2x00dev, 27, 0x23); - rt2500pci_bbp_write(rt2x00dev, 30, 0x10); - rt2500pci_bbp_write(rt2x00dev, 31, 0x2b); - rt2500pci_bbp_write(rt2x00dev, 32, 0xb9); - rt2500pci_bbp_write(rt2x00dev, 34, 0x12); - rt2500pci_bbp_write(rt2x00dev, 35, 0x50); - rt2500pci_bbp_write(rt2x00dev, 39, 0xc4); - rt2500pci_bbp_write(rt2x00dev, 40, 0x02); - rt2500pci_bbp_write(rt2x00dev, 41, 0x60); - rt2500pci_bbp_write(rt2x00dev, 53, 0x10); - rt2500pci_bbp_write(rt2x00dev, 54, 0x18); - rt2500pci_bbp_write(rt2x00dev, 56, 0x08); - rt2500pci_bbp_write(rt2x00dev, 57, 0x10); - rt2500pci_bbp_write(rt2x00dev, 58, 0x08); - rt2500pci_bbp_write(rt2x00dev, 61, 0x6d); - rt2500pci_bbp_write(rt2x00dev, 62, 0x10); - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt2500pci_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} - -/* - * Device state switch handlers. - */ -static void rt2500pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, RXCSR0, ®); - rt2x00_set_field32(®, RXCSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); -} - -static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int mask = (state == STATE_RADIO_IRQ_OFF); - u32 reg; - - /* - * When interrupts are being enabled, the interrupt registers - * should clear the register to assure a clean state. - */ - if (state == STATE_RADIO_IRQ_ON) { - rt2x00pci_register_read(rt2x00dev, CSR7, ®); - rt2x00pci_register_write(rt2x00dev, CSR7, reg); - } - - /* - * Only toggle the interrupts bits we are going to use. - * Non-checked interrupt bits are disabled by default. - */ - rt2x00pci_register_read(rt2x00dev, CSR8, ®); - rt2x00_set_field32(®, CSR8_TBCN_EXPIRE, mask); - rt2x00_set_field32(®, CSR8_TXDONE_TXRING, mask); - rt2x00_set_field32(®, CSR8_TXDONE_ATIMRING, mask); - rt2x00_set_field32(®, CSR8_TXDONE_PRIORING, mask); - rt2x00_set_field32(®, CSR8_RXDONE, mask); - rt2x00pci_register_write(rt2x00dev, CSR8, reg); -} - -static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Initialize all registers. - */ - if (unlikely(rt2500pci_init_queues(rt2x00dev) || - rt2500pci_init_registers(rt2x00dev) || - rt2500pci_init_bbp(rt2x00dev))) - return -EIO; - - return 0; -} - -static void rt2500pci_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Disable power - */ - rt2x00pci_register_write(rt2x00dev, PWRCSR0, 0); -} - -static int rt2500pci_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - unsigned int i; - char put_to_sleep; - char bbp_state; - char rf_state; - - put_to_sleep = (state != STATE_AWAKE); - - rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); - rt2x00_set_field32(®, PWRCSR1_SET_STATE, 1); - rt2x00_set_field32(®, PWRCSR1_BBP_DESIRE_STATE, state); - rt2x00_set_field32(®, PWRCSR1_RF_DESIRE_STATE, state); - rt2x00_set_field32(®, PWRCSR1_PUT_TO_SLEEP, put_to_sleep); - rt2x00pci_register_write(rt2x00dev, PWRCSR1, reg); - - /* - * Device is not guaranteed to be in the requested state yet. - * We must wait until the register indicates that the - * device has entered the correct state. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, PWRCSR1, ®); - bbp_state = rt2x00_get_field32(reg, PWRCSR1_BBP_CURR_STATE); - rf_state = rt2x00_get_field32(reg, PWRCSR1_RF_CURR_STATE); - if (bbp_state == state && rf_state == state) - return 0; - msleep(10); - } - - return -EBUSY; -} - -static int rt2500pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int retval = 0; - - switch (state) { - case STATE_RADIO_ON: - retval = rt2500pci_enable_radio(rt2x00dev); - break; - case STATE_RADIO_OFF: - rt2500pci_disable_radio(rt2x00dev); - break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2500pci_toggle_rx(rt2x00dev, state); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: - rt2500pci_toggle_irq(rt2x00dev, state); - break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2500pci_set_state(rt2x00dev, state); - break; - default: - retval = -ENOTSUPP; - break; - } - - if (unlikely(retval)) - ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", - state, retval); - - return retval; -} - -/* - * TX descriptor initialization - */ -static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - struct queue_entry_priv_pci *entry_priv = skbdesc->entry->priv_data; - __le32 *txd = skbdesc->desc; - u32 word; - - /* - * Start writing the descriptor words. - */ - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field32(&word, TXD_W2_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W2_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W2_CWMAX, txdesc->cw_max); - rt2x00_desc_write(txd, 2, word); - - rt2x00_desc_read(txd, 3, &word); - rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal); - rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low); - rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high); - rt2x00_desc_write(txd, 3, word); - - rt2x00_desc_read(txd, 10, &word); - rt2x00_set_field32(&word, TXD_W10_RTS, - test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)); - rt2x00_desc_write(txd, 10, word); - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); - rt2x00_set_field32(&word, TXD_W0_VALID, 1); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_OFDM, - (txdesc->rate_mode == RATE_MODE_OFDM)); - rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, - test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); - rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, CIPHER_NONE); - rt2x00_desc_write(txd, 0, word); -} - -/* - * TX data initialization - */ -static void rt2500pci_write_beacon(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; - u32 reg; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - - /* - * Replace rt2x00lib allocated descriptor with the - * pointer to the _real_ hardware descriptor. - * After that, map the beacon to DMA and update the - * descriptor. - */ - memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry_priv->desc; - - rt2x00queue_map_txskb(rt2x00dev, entry->skb); - - rt2x00_desc_read(entry_priv->desc, 1, &word); - rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 1, word); -} - -static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue == QID_BEACON) { - rt2x00pci_register_read(rt2x00dev, CSR14, ®); - if (!rt2x00_get_field32(reg, CSR14_BEACON_GEN)) { - rt2x00_set_field32(®, CSR14_TSF_COUNT, 1); - rt2x00_set_field32(®, CSR14_TBCN, 1); - rt2x00_set_field32(®, CSR14_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, CSR14, reg); - } - return; - } - - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_KICK_PRIO, (queue == QID_AC_BE)); - rt2x00_set_field32(®, TXCSR0_KICK_TX, (queue == QID_AC_BK)); - rt2x00_set_field32(®, TXCSR0_KICK_ATIM, (queue == QID_ATIM)); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); -} - -static void rt2500pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) -{ - u32 reg; - - if (qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, CSR14, 0); - } else { - rt2x00pci_register_read(rt2x00dev, TXCSR0, ®); - rt2x00_set_field32(®, TXCSR0_ABORT, 1); - rt2x00pci_register_write(rt2x00dev, TXCSR0, reg); - } -} - -/* - * RX control handlers - */ -static void rt2500pci_fill_rxdone(struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - u32 word0; - u32 word2; - - rt2x00_desc_read(entry_priv->desc, 0, &word0); - rt2x00_desc_read(entry_priv->desc, 2, &word2); - - if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; - - /* - * Obtain the status about this packet. - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 100kbit/s. - */ - rxdesc->signal = rt2x00_get_field32(word2, RXD_W2_SIGNAL); - rxdesc->rssi = rt2x00_get_field32(word2, RXD_W2_RSSI) - - entry->queue->rt2x00dev->rssi_offset; - rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - - if (rt2x00_get_field32(word0, RXD_W0_OFDM)) - rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; - else - rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; - if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) - rxdesc->dev_flags |= RXDONE_MY_BSS; -} - -/* - * Interrupt functions. - */ -static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue_idx) -{ - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - struct queue_entry_priv_pci *entry_priv; - struct queue_entry *entry; - struct txdone_entry_desc txdesc; - u32 word; - - while (!rt2x00queue_empty(queue)) { - entry = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - entry_priv = entry->priv_data; - rt2x00_desc_read(entry_priv->desc, 0, &word); - - if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || - !rt2x00_get_field32(word, TXD_W0_VALID)) - break; - - /* - * Obtain the status about this packet. - */ - txdesc.flags = 0; - switch (rt2x00_get_field32(word, TXD_W0_RESULT)) { - case 0: /* Success */ - case 1: /* Success with retry */ - __set_bit(TXDONE_SUCCESS, &txdesc.flags); - break; - case 2: /* Failure, excessive retries */ - __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); - /* Don't break, this is a failed frame! */ - default: /* Failure */ - __set_bit(TXDONE_FAILURE, &txdesc.flags); - } - txdesc.retry = rt2x00_get_field32(word, TXD_W0_RETRY_COUNT); - - rt2x00lib_txdone(entry, &txdesc); - } -} - -static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance) -{ - struct rt2x00_dev *rt2x00dev = dev_instance; - u32 reg; - - /* - * Get the interrupt sources & saved to local variable. - * Write register value back to clear pending interrupts. - */ - rt2x00pci_register_read(rt2x00dev, CSR7, ®); - rt2x00pci_register_write(rt2x00dev, CSR7, reg); - - if (!reg) - return IRQ_NONE; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return IRQ_HANDLED; - - /* - * Handle interrupts, walk through all bits - * and run the tasks, the bits are checked in order of - * priority. - */ - - /* - * 1 - Beacon timer expired interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE)) - rt2x00lib_beacondone(rt2x00dev); - - /* - * 2 - Rx ring done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_RXDONE)) - rt2x00pci_rxdone(rt2x00dev); - - /* - * 3 - Atim ring transmit done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING)) - rt2500pci_txdone(rt2x00dev, QID_ATIM); - - /* - * 4 - Priority ring transmit done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING)) - rt2500pci_txdone(rt2x00dev, QID_AC_BE); - - /* - * 5 - Tx ring transmit done interrupt. - */ - if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) - rt2500pci_txdone(rt2x00dev, QID_AC_BK); - - return IRQ_HANDLED; -} - -/* - * Device probe functions. - */ -static int rt2500pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ - struct eeprom_93cx6 eeprom; - u32 reg; - u16 word; - u8 *mac; - - rt2x00pci_register_read(rt2x00dev, CSR21, ®); - - eeprom.data = rt2x00dev; - eeprom.register_read = rt2500pci_eepromregister_read; - eeprom.register_write = rt2500pci_eepromregister_write; - eeprom.width = rt2x00_get_field32(reg, CSR21_TYPE_93C46) ? - PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; - eeprom.reg_data_in = 0; - eeprom.reg_data_out = 0; - eeprom.reg_data_clock = 0; - eeprom.reg_chip_select = 0; - - eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, - EEPROM_SIZE / sizeof(u16)); - - /* - * Start validation of the data that has been read. - */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - if (!is_valid_ether_addr(mac)) { - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %pM\n", mac); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, - ANTENNA_SW_DIVERSITY); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, - ANTENNA_SW_DIVERSITY); - rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, - LED_MODE_DEFAULT); - rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); - EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0); - rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); - EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI, - DEFAULT_RSSI_OFFSET); - rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); - EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word); - } - - return 0; -} - -static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u16 value; - u16 eeprom; - - /* - * Read EEPROM word for configuration. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Identify RF chipset. - */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2x00pci_register_read(rt2x00dev, CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - - if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && - !rt2x00_rf(&rt2x00dev->chip, RF2523) && - !rt2x00_rf(&rt2x00dev->chip, RF2524) && - !rt2x00_rf(&rt2x00dev->chip, RF2525) && - !rt2x00_rf(&rt2x00dev->chip, RF2525E) && - !rt2x00_rf(&rt2x00dev->chip, RF5222)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); - return -ENODEV; - } - - /* - * Identify default antenna configuration. - */ - rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); - - /* - * Store led mode, for correct led behaviour. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - - rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY || - value == LED_MODE_DEFAULT || - value == LED_MODE_ASUS) - rt2500pci_init_led(rt2x00dev, &rt2x00dev->led_qual, - LED_TYPE_ACTIVITY); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - /* - * Detect if this device has an hardware controlled radio. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); - - /* - * Check if the BBP tuning should be enabled. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - - if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) - __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); - - /* - * Read the RSSI <-> dBm offset information. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom); - rt2x00dev->rssi_offset = - rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); - - return 0; -} - -/* - * RF value list for RF2522 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2522[] = { - { 1, 0x00002050, 0x000c1fda, 0x00000101, 0 }, - { 2, 0x00002050, 0x000c1fee, 0x00000101, 0 }, - { 3, 0x00002050, 0x000c2002, 0x00000101, 0 }, - { 4, 0x00002050, 0x000c2016, 0x00000101, 0 }, - { 5, 0x00002050, 0x000c202a, 0x00000101, 0 }, - { 6, 0x00002050, 0x000c203e, 0x00000101, 0 }, - { 7, 0x00002050, 0x000c2052, 0x00000101, 0 }, - { 8, 0x00002050, 0x000c2066, 0x00000101, 0 }, - { 9, 0x00002050, 0x000c207a, 0x00000101, 0 }, - { 10, 0x00002050, 0x000c208e, 0x00000101, 0 }, - { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 }, - { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 }, - { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 }, - { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 }, -}; - -/* - * RF value list for RF2523 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2523[] = { - { 1, 0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b }, - { 2, 0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b }, - { 3, 0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b }, - { 4, 0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b }, - { 5, 0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b }, - { 6, 0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b }, - { 7, 0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b }, - { 8, 0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b }, - { 9, 0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b }, - { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b }, - { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b }, - { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b }, - { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b }, - { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 }, -}; - -/* - * RF value list for RF2524 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2524[] = { - { 1, 0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b }, - { 2, 0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b }, - { 3, 0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b }, - { 4, 0x00032020, 0x00000caa, 0x00000101, 0x00000a1b }, - { 5, 0x00032020, 0x00000cae, 0x00000101, 0x00000a1b }, - { 6, 0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b }, - { 7, 0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b }, - { 8, 0x00032020, 0x00000cba, 0x00000101, 0x00000a1b }, - { 9, 0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b }, - { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b }, - { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b }, - { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b }, - { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b }, - { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 }, -}; - -/* - * RF value list for RF2525 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2525[] = { - { 1, 0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b }, - { 2, 0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b }, - { 3, 0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b }, - { 4, 0x00022020, 0x00080caa, 0x00060111, 0x00000a1b }, - { 5, 0x00022020, 0x00080cae, 0x00060111, 0x00000a1b }, - { 6, 0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b }, - { 7, 0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b }, - { 8, 0x00022020, 0x00080cba, 0x00060111, 0x00000a1b }, - { 9, 0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b }, - { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b }, - { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b }, - { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b }, - { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b }, - { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 }, -}; - -/* - * RF value list for RF2525e - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2525e[] = { - { 1, 0x00022020, 0x00081136, 0x00060111, 0x00000a0b }, - { 2, 0x00022020, 0x0008113a, 0x00060111, 0x00000a0b }, - { 3, 0x00022020, 0x0008113e, 0x00060111, 0x00000a0b }, - { 4, 0x00022020, 0x00081182, 0x00060111, 0x00000a0b }, - { 5, 0x00022020, 0x00081186, 0x00060111, 0x00000a0b }, - { 6, 0x00022020, 0x0008118a, 0x00060111, 0x00000a0b }, - { 7, 0x00022020, 0x0008118e, 0x00060111, 0x00000a0b }, - { 8, 0x00022020, 0x00081192, 0x00060111, 0x00000a0b }, - { 9, 0x00022020, 0x00081196, 0x00060111, 0x00000a0b }, - { 10, 0x00022020, 0x0008119a, 0x00060111, 0x00000a0b }, - { 11, 0x00022020, 0x0008119e, 0x00060111, 0x00000a0b }, - { 12, 0x00022020, 0x000811a2, 0x00060111, 0x00000a0b }, - { 13, 0x00022020, 0x000811a6, 0x00060111, 0x00000a0b }, - { 14, 0x00022020, 0x000811ae, 0x00060111, 0x00000a1b }, -}; - -/* - * RF value list for RF5222 - * Supports: 2.4 GHz & 5.2 GHz - */ -static const struct rf_channel rf_vals_5222[] = { - { 1, 0x00022020, 0x00001136, 0x00000101, 0x00000a0b }, - { 2, 0x00022020, 0x0000113a, 0x00000101, 0x00000a0b }, - { 3, 0x00022020, 0x0000113e, 0x00000101, 0x00000a0b }, - { 4, 0x00022020, 0x00001182, 0x00000101, 0x00000a0b }, - { 5, 0x00022020, 0x00001186, 0x00000101, 0x00000a0b }, - { 6, 0x00022020, 0x0000118a, 0x00000101, 0x00000a0b }, - { 7, 0x00022020, 0x0000118e, 0x00000101, 0x00000a0b }, - { 8, 0x00022020, 0x00001192, 0x00000101, 0x00000a0b }, - { 9, 0x00022020, 0x00001196, 0x00000101, 0x00000a0b }, - { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b }, - { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b }, - { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b }, - { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b }, - { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f }, - { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f }, - { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f }, - { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f }, - { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f }, - { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f }, - { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f }, - { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f }, - - /* 802.11 HyperLan 2 */ - { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f }, - { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f }, - { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f }, - { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f }, - { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f }, - { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f }, - { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f }, - { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f }, - { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f }, - { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f }, - - /* 802.11 UNII */ - { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f }, - { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 }, - { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 }, - { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 }, - { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 }, -}; - -static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - struct channel_info *info; - char *tx_power; - unsigned int i; - - /* - * Initialize all hw fields. - */ - rt2x00dev->hw->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; - - rt2x00dev->hw->extra_tx_headroom = 0; - - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); - SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, - EEPROM_MAC_ADDR_0)); - - /* - * Initialize hw_mode information. - */ - spec->supported_bands = SUPPORT_BAND_2GHZ; - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); - spec->channels = rf_vals_bg_2522; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); - spec->channels = rf_vals_bg_2523; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); - spec->channels = rf_vals_bg_2524; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); - spec->channels = rf_vals_bg_2525; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); - spec->channels = rf_vals_bg_2525e; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { - spec->supported_bands |= SUPPORT_BAND_5GHZ; - spec->num_channels = ARRAY_SIZE(rf_vals_5222); - spec->channels = rf_vals_5222; - } - - /* - * Create channel information array - */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - spec->channels_info = info; - - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - - if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = DEFAULT_TXPOWER; - } - - return 0; -} - -static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Allocate eeprom data. - */ - retval = rt2500pci_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt2500pci_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt2500pci_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device requires the atim queue and DMA-mapped skbs. - */ - __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; -} - -/* - * IEEE80211 stack callback functions. - */ -static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u64 tsf; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR17, ®); - tsf = (u64) rt2x00_get_field32(reg, CSR17_HIGH_TSFTIMER) << 32; - rt2x00pci_register_read(rt2x00dev, CSR16, ®); - tsf |= rt2x00_get_field32(reg, CSR16_LOW_TSFTIMER); - - return tsf; -} - -static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, CSR15, ®); - return rt2x00_get_field32(reg, CSR15_BEACON_SENT); -} - -static const struct ieee80211_ops rt2500pci_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .get_stats = rt2x00mac_get_stats, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2x00mac_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .get_tsf = rt2500pci_get_tsf, - .tx_last_beacon = rt2500pci_tx_last_beacon, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; - -static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = { - .irq_handler = rt2500pci_interrupt, - .probe_hw = rt2500pci_probe_hw, - .initialize = rt2x00pci_initialize, - .uninitialize = rt2x00pci_uninitialize, - .get_entry_state = rt2500pci_get_entry_state, - .clear_entry = rt2500pci_clear_entry, - .set_device_state = rt2500pci_set_device_state, - .rfkill_poll = rt2500pci_rfkill_poll, - .link_stats = rt2500pci_link_stats, - .reset_tuner = rt2500pci_reset_tuner, - .link_tuner = rt2500pci_link_tuner, - .write_tx_desc = rt2500pci_write_tx_desc, - .write_tx_data = rt2x00pci_write_tx_data, - .write_beacon = rt2500pci_write_beacon, - .kick_tx_queue = rt2500pci_kick_tx_queue, - .kill_tx_queue = rt2500pci_kill_tx_queue, - .fill_rxdone = rt2500pci_fill_rxdone, - .config_filter = rt2500pci_config_filter, - .config_intf = rt2500pci_config_intf, - .config_erp = rt2500pci_config_erp, - .config_ant = rt2500pci_config_ant, - .config = rt2500pci_config, -}; - -static const struct data_queue_desc rt2500pci_queue_rx = { - .entry_num = RX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2500pci_queue_tx = { - .entry_num = TX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2500pci_queue_bcn = { - .entry_num = BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt2500pci_queue_atim = { - .entry_num = ATIM_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct rt2x00_ops rt2500pci_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 1, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt2500pci_queue_rx, - .tx = &rt2500pci_queue_tx, - .bcn = &rt2500pci_queue_bcn, - .atim = &rt2500pci_queue_atim, - .lib = &rt2500pci_rt2x00_ops, - .hw = &rt2500pci_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500pci_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * RT2500pci module information. - */ -static struct pci_device_id rt2500pci_device_table[] = { - { PCI_DEVICE(0x1814, 0x0201), PCI_DEVICE_DATA(&rt2500pci_ops) }, - { 0, } -}; - -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Ralink RT2500 PCI & PCMCIA Wireless LAN driver."); -MODULE_SUPPORTED_DEVICE("Ralink RT2560 PCI & PCMCIA chipset based cards"); -MODULE_DEVICE_TABLE(pci, rt2500pci_device_table); -MODULE_LICENSE("GPL"); - -static struct pci_driver rt2500pci_driver = { - .name = KBUILD_MODNAME, - .id_table = rt2500pci_device_table, - .probe = rt2x00pci_probe, - .remove = __devexit_p(rt2x00pci_remove), - .suspend = rt2x00pci_suspend, - .resume = rt2x00pci_resume, -}; - -static int __init rt2500pci_init(void) -{ - return pci_register_driver(&rt2500pci_driver); -} - -static void __exit rt2500pci_exit(void) -{ - pci_unregister_driver(&rt2500pci_driver); -} - -module_init(rt2500pci_init); -module_exit(rt2500pci_exit); diff --git a/drivers/net/wireless/rt2x00/rt2500pci.h b/drivers/net/wireless/rt2x00/rt2500pci.h deleted file mode 100644 index 54d37957883c..000000000000 --- a/drivers/net/wireless/rt2x00/rt2500pci.h +++ /dev/null @@ -1,1234 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2500pci - Abstract: Data structures and registers for the rt2500pci module. - Supported chipsets: RT2560. - */ - -#ifndef RT2500PCI_H -#define RT2500PCI_H - -/* - * RF chip defines. - */ -#define RF2522 0x0000 -#define RF2523 0x0001 -#define RF2524 0x0002 -#define RF2525 0x0003 -#define RF2525E 0x0004 -#define RF5222 0x0010 - -/* - * RT2560 version - */ -#define RT2560_VERSION_B 2 -#define RT2560_VERSION_C 3 -#define RT2560_VERSION_D 4 - -/* - * Signal information. - * Defaul offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 121 - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x0000 -#define CSR_REG_SIZE 0x0174 -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0200 -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0040 -#define RF_BASE 0x0004 -#define RF_SIZE 0x0010 - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 2 - -/* - * Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * CSR0: ASIC revision number. - */ -#define CSR0 0x0000 - -/* - * CSR1: System control register. - * SOFT_RESET: Software reset, 1: reset, 0: normal. - * BBP_RESET: Hardware reset, 1: reset, 0, release. - * HOST_READY: Host ready after initialization. - */ -#define CSR1 0x0004 -#define CSR1_SOFT_RESET FIELD32(0x00000001) -#define CSR1_BBP_RESET FIELD32(0x00000002) -#define CSR1_HOST_READY FIELD32(0x00000004) - -/* - * CSR2: System admin status register (invalid). - */ -#define CSR2 0x0008 - -/* - * CSR3: STA MAC address register 0. - */ -#define CSR3 0x000c -#define CSR3_BYTE0 FIELD32(0x000000ff) -#define CSR3_BYTE1 FIELD32(0x0000ff00) -#define CSR3_BYTE2 FIELD32(0x00ff0000) -#define CSR3_BYTE3 FIELD32(0xff000000) - -/* - * CSR4: STA MAC address register 1. - */ -#define CSR4 0x0010 -#define CSR4_BYTE4 FIELD32(0x000000ff) -#define CSR4_BYTE5 FIELD32(0x0000ff00) - -/* - * CSR5: BSSID register 0. - */ -#define CSR5 0x0014 -#define CSR5_BYTE0 FIELD32(0x000000ff) -#define CSR5_BYTE1 FIELD32(0x0000ff00) -#define CSR5_BYTE2 FIELD32(0x00ff0000) -#define CSR5_BYTE3 FIELD32(0xff000000) - -/* - * CSR6: BSSID register 1. - */ -#define CSR6 0x0018 -#define CSR6_BYTE4 FIELD32(0x000000ff) -#define CSR6_BYTE5 FIELD32(0x0000ff00) - -/* - * CSR7: Interrupt source register. - * Write 1 to clear. - * TBCN_EXPIRE: Beacon timer expired interrupt. - * TWAKE_EXPIRE: Wakeup timer expired interrupt. - * TATIMW_EXPIRE: Timer of atim window expired interrupt. - * TXDONE_TXRING: Tx ring transmit done interrupt. - * TXDONE_ATIMRING: Atim ring transmit done interrupt. - * TXDONE_PRIORING: Priority ring transmit done interrupt. - * RXDONE: Receive done interrupt. - * DECRYPTION_DONE: Decryption done interrupt. - * ENCRYPTION_DONE: Encryption done interrupt. - * UART1_TX_TRESHOLD: UART1 TX reaches threshold. - * UART1_RX_TRESHOLD: UART1 RX reaches threshold. - * UART1_IDLE_TRESHOLD: UART1 IDLE over threshold. - * UART1_TX_BUFF_ERROR: UART1 TX buffer error. - * UART1_RX_BUFF_ERROR: UART1 RX buffer error. - * UART2_TX_TRESHOLD: UART2 TX reaches threshold. - * UART2_RX_TRESHOLD: UART2 RX reaches threshold. - * UART2_IDLE_TRESHOLD: UART2 IDLE over threshold. - * UART2_TX_BUFF_ERROR: UART2 TX buffer error. - * UART2_RX_BUFF_ERROR: UART2 RX buffer error. - * TIMER_CSR3_EXPIRE: TIMECSR3 timer expired (802.1H quiet period). - - */ -#define CSR7 0x001c -#define CSR7_TBCN_EXPIRE FIELD32(0x00000001) -#define CSR7_TWAKE_EXPIRE FIELD32(0x00000002) -#define CSR7_TATIMW_EXPIRE FIELD32(0x00000004) -#define CSR7_TXDONE_TXRING FIELD32(0x00000008) -#define CSR7_TXDONE_ATIMRING FIELD32(0x00000010) -#define CSR7_TXDONE_PRIORING FIELD32(0x00000020) -#define CSR7_RXDONE FIELD32(0x00000040) -#define CSR7_DECRYPTION_DONE FIELD32(0x00000080) -#define CSR7_ENCRYPTION_DONE FIELD32(0x00000100) -#define CSR7_UART1_TX_TRESHOLD FIELD32(0x00000200) -#define CSR7_UART1_RX_TRESHOLD FIELD32(0x00000400) -#define CSR7_UART1_IDLE_TRESHOLD FIELD32(0x00000800) -#define CSR7_UART1_TX_BUFF_ERROR FIELD32(0x00001000) -#define CSR7_UART1_RX_BUFF_ERROR FIELD32(0x00002000) -#define CSR7_UART2_TX_TRESHOLD FIELD32(0x00004000) -#define CSR7_UART2_RX_TRESHOLD FIELD32(0x00008000) -#define CSR7_UART2_IDLE_TRESHOLD FIELD32(0x00010000) -#define CSR7_UART2_TX_BUFF_ERROR FIELD32(0x00020000) -#define CSR7_UART2_RX_BUFF_ERROR FIELD32(0x00040000) -#define CSR7_TIMER_CSR3_EXPIRE FIELD32(0x00080000) - -/* - * CSR8: Interrupt mask register. - * Write 1 to mask interrupt. - * TBCN_EXPIRE: Beacon timer expired interrupt. - * TWAKE_EXPIRE: Wakeup timer expired interrupt. - * TATIMW_EXPIRE: Timer of atim window expired interrupt. - * TXDONE_TXRING: Tx ring transmit done interrupt. - * TXDONE_ATIMRING: Atim ring transmit done interrupt. - * TXDONE_PRIORING: Priority ring transmit done interrupt. - * RXDONE: Receive done interrupt. - * DECRYPTION_DONE: Decryption done interrupt. - * ENCRYPTION_DONE: Encryption done interrupt. - * UART1_TX_TRESHOLD: UART1 TX reaches threshold. - * UART1_RX_TRESHOLD: UART1 RX reaches threshold. - * UART1_IDLE_TRESHOLD: UART1 IDLE over threshold. - * UART1_TX_BUFF_ERROR: UART1 TX buffer error. - * UART1_RX_BUFF_ERROR: UART1 RX buffer error. - * UART2_TX_TRESHOLD: UART2 TX reaches threshold. - * UART2_RX_TRESHOLD: UART2 RX reaches threshold. - * UART2_IDLE_TRESHOLD: UART2 IDLE over threshold. - * UART2_TX_BUFF_ERROR: UART2 TX buffer error. - * UART2_RX_BUFF_ERROR: UART2 RX buffer error. - * TIMER_CSR3_EXPIRE: TIMECSR3 timer expired (802.1H quiet period). - */ -#define CSR8 0x0020 -#define CSR8_TBCN_EXPIRE FIELD32(0x00000001) -#define CSR8_TWAKE_EXPIRE FIELD32(0x00000002) -#define CSR8_TATIMW_EXPIRE FIELD32(0x00000004) -#define CSR8_TXDONE_TXRING FIELD32(0x00000008) -#define CSR8_TXDONE_ATIMRING FIELD32(0x00000010) -#define CSR8_TXDONE_PRIORING FIELD32(0x00000020) -#define CSR8_RXDONE FIELD32(0x00000040) -#define CSR8_DECRYPTION_DONE FIELD32(0x00000080) -#define CSR8_ENCRYPTION_DONE FIELD32(0x00000100) -#define CSR8_UART1_TX_TRESHOLD FIELD32(0x00000200) -#define CSR8_UART1_RX_TRESHOLD FIELD32(0x00000400) -#define CSR8_UART1_IDLE_TRESHOLD FIELD32(0x00000800) -#define CSR8_UART1_TX_BUFF_ERROR FIELD32(0x00001000) -#define CSR8_UART1_RX_BUFF_ERROR FIELD32(0x00002000) -#define CSR8_UART2_TX_TRESHOLD FIELD32(0x00004000) -#define CSR8_UART2_RX_TRESHOLD FIELD32(0x00008000) -#define CSR8_UART2_IDLE_TRESHOLD FIELD32(0x00010000) -#define CSR8_UART2_TX_BUFF_ERROR FIELD32(0x00020000) -#define CSR8_UART2_RX_BUFF_ERROR FIELD32(0x00040000) -#define CSR8_TIMER_CSR3_EXPIRE FIELD32(0x00080000) - -/* - * CSR9: Maximum frame length register. - * MAX_FRAME_UNIT: Maximum frame length in 128b unit, default: 12. - */ -#define CSR9 0x0024 -#define CSR9_MAX_FRAME_UNIT FIELD32(0x00000f80) - -/* - * SECCSR0: WEP control register. - * KICK_DECRYPT: Kick decryption engine, self-clear. - * ONE_SHOT: 0: ring mode, 1: One shot only mode. - * DESC_ADDRESS: Descriptor physical address of frame. - */ -#define SECCSR0 0x0028 -#define SECCSR0_KICK_DECRYPT FIELD32(0x00000001) -#define SECCSR0_ONE_SHOT FIELD32(0x00000002) -#define SECCSR0_DESC_ADDRESS FIELD32(0xfffffffc) - -/* - * CSR11: Back-off control register. - * CWMIN: CWmin. Default cwmin is 31 (2^5 - 1). - * CWMAX: CWmax. Default cwmax is 1023 (2^10 - 1). - * SLOT_TIME: Slot time, default is 20us for 802.11b - * CW_SELECT: CWmin/CWmax selection, 1: Register, 0: TXD. - * LONG_RETRY: Long retry count. - * SHORT_RETRY: Short retry count. - */ -#define CSR11 0x002c -#define CSR11_CWMIN FIELD32(0x0000000f) -#define CSR11_CWMAX FIELD32(0x000000f0) -#define CSR11_SLOT_TIME FIELD32(0x00001f00) -#define CSR11_CW_SELECT FIELD32(0x00002000) -#define CSR11_LONG_RETRY FIELD32(0x00ff0000) -#define CSR11_SHORT_RETRY FIELD32(0xff000000) - -/* - * CSR12: Synchronization configuration register 0. - * All units in 1/16 TU. - * BEACON_INTERVAL: Beacon interval, default is 100 TU. - * CFP_MAX_DURATION: Cfp maximum duration, default is 100 TU. - */ -#define CSR12 0x0030 -#define CSR12_BEACON_INTERVAL FIELD32(0x0000ffff) -#define CSR12_CFP_MAX_DURATION FIELD32(0xffff0000) - -/* - * CSR13: Synchronization configuration register 1. - * All units in 1/16 TU. - * ATIMW_DURATION: Atim window duration. - * CFP_PERIOD: Cfp period, default is 0 TU. - */ -#define CSR13 0x0034 -#define CSR13_ATIMW_DURATION FIELD32(0x0000ffff) -#define CSR13_CFP_PERIOD FIELD32(0x00ff0000) - -/* - * CSR14: Synchronization control register. - * TSF_COUNT: Enable tsf auto counting. - * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode. - * TBCN: Enable tbcn with reload value. - * TCFP: Enable tcfp & cfp / cp switching. - * TATIMW: Enable tatimw & atim window switching. - * BEACON_GEN: Enable beacon generator. - * CFP_COUNT_PRELOAD: Cfp count preload value. - * TBCM_PRELOAD: Tbcn preload value in units of 64us. - */ -#define CSR14 0x0038 -#define CSR14_TSF_COUNT FIELD32(0x00000001) -#define CSR14_TSF_SYNC FIELD32(0x00000006) -#define CSR14_TBCN FIELD32(0x00000008) -#define CSR14_TCFP FIELD32(0x00000010) -#define CSR14_TATIMW FIELD32(0x00000020) -#define CSR14_BEACON_GEN FIELD32(0x00000040) -#define CSR14_CFP_COUNT_PRELOAD FIELD32(0x0000ff00) -#define CSR14_TBCM_PRELOAD FIELD32(0xffff0000) - -/* - * CSR15: Synchronization status register. - * CFP: ASIC is in contention-free period. - * ATIMW: ASIC is in ATIM window. - * BEACON_SENT: Beacon is send. - */ -#define CSR15 0x003c -#define CSR15_CFP FIELD32(0x00000001) -#define CSR15_ATIMW FIELD32(0x00000002) -#define CSR15_BEACON_SENT FIELD32(0x00000004) - -/* - * CSR16: TSF timer register 0. - */ -#define CSR16 0x0040 -#define CSR16_LOW_TSFTIMER FIELD32(0xffffffff) - -/* - * CSR17: TSF timer register 1. - */ -#define CSR17 0x0044 -#define CSR17_HIGH_TSFTIMER FIELD32(0xffffffff) - -/* - * CSR18: IFS timer register 0. - * SIFS: Sifs, default is 10 us. - * PIFS: Pifs, default is 30 us. - */ -#define CSR18 0x0048 -#define CSR18_SIFS FIELD32(0x000001ff) -#define CSR18_PIFS FIELD32(0x001f0000) - -/* - * CSR19: IFS timer register 1. - * DIFS: Difs, default is 50 us. - * EIFS: Eifs, default is 364 us. - */ -#define CSR19 0x004c -#define CSR19_DIFS FIELD32(0x0000ffff) -#define CSR19_EIFS FIELD32(0xffff0000) - -/* - * CSR20: Wakeup timer register. - * DELAY_AFTER_TBCN: Delay after tbcn expired in units of 1/16 TU. - * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup. - * AUTOWAKE: Enable auto wakeup / sleep mechanism. - */ -#define CSR20 0x0050 -#define CSR20_DELAY_AFTER_TBCN FIELD32(0x0000ffff) -#define CSR20_TBCN_BEFORE_WAKEUP FIELD32(0x00ff0000) -#define CSR20_AUTOWAKE FIELD32(0x01000000) - -/* - * CSR21: EEPROM control register. - * RELOAD: Write 1 to reload eeprom content. - * TYPE_93C46: 1: 93c46, 0:93c66. - */ -#define CSR21 0x0054 -#define CSR21_RELOAD FIELD32(0x00000001) -#define CSR21_EEPROM_DATA_CLOCK FIELD32(0x00000002) -#define CSR21_EEPROM_CHIP_SELECT FIELD32(0x00000004) -#define CSR21_EEPROM_DATA_IN FIELD32(0x00000008) -#define CSR21_EEPROM_DATA_OUT FIELD32(0x00000010) -#define CSR21_TYPE_93C46 FIELD32(0x00000020) - -/* - * CSR22: CFP control register. - * CFP_DURATION_REMAIN: Cfp duration remain, in units of TU. - * RELOAD_CFP_DURATION: Write 1 to reload cfp duration remain. - */ -#define CSR22 0x0058 -#define CSR22_CFP_DURATION_REMAIN FIELD32(0x0000ffff) -#define CSR22_RELOAD_CFP_DURATION FIELD32(0x00010000) - -/* - * Transmit related CSRs. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * TXCSR0: TX Control Register. - * KICK_TX: Kick tx ring. - * KICK_ATIM: Kick atim ring. - * KICK_PRIO: Kick priority ring. - * ABORT: Abort all transmit related ring operation. - */ -#define TXCSR0 0x0060 -#define TXCSR0_KICK_TX FIELD32(0x00000001) -#define TXCSR0_KICK_ATIM FIELD32(0x00000002) -#define TXCSR0_KICK_PRIO FIELD32(0x00000004) -#define TXCSR0_ABORT FIELD32(0x00000008) - -/* - * TXCSR1: TX Configuration Register. - * ACK_TIMEOUT: Ack timeout, default = sifs + 2*slottime + acktime @ 1mbps. - * ACK_CONSUME_TIME: Ack consume time, default = sifs + acktime @ 1mbps. - * TSF_OFFSET: Insert tsf offset. - * AUTORESPONDER: Enable auto responder which include ack & cts. - */ -#define TXCSR1 0x0064 -#define TXCSR1_ACK_TIMEOUT FIELD32(0x000001ff) -#define TXCSR1_ACK_CONSUME_TIME FIELD32(0x0003fe00) -#define TXCSR1_TSF_OFFSET FIELD32(0x00fc0000) -#define TXCSR1_AUTORESPONDER FIELD32(0x01000000) - -/* - * TXCSR2: Tx descriptor configuration register. - * TXD_SIZE: Tx descriptor size, default is 48. - * NUM_TXD: Number of tx entries in ring. - * NUM_ATIM: Number of atim entries in ring. - * NUM_PRIO: Number of priority entries in ring. - */ -#define TXCSR2 0x0068 -#define TXCSR2_TXD_SIZE FIELD32(0x000000ff) -#define TXCSR2_NUM_TXD FIELD32(0x0000ff00) -#define TXCSR2_NUM_ATIM FIELD32(0x00ff0000) -#define TXCSR2_NUM_PRIO FIELD32(0xff000000) - -/* - * TXCSR3: TX Ring Base address register. - */ -#define TXCSR3 0x006c -#define TXCSR3_TX_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR4: TX Atim Ring Base address register. - */ -#define TXCSR4 0x0070 -#define TXCSR4_ATIM_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR5: TX Prio Ring Base address register. - */ -#define TXCSR5 0x0074 -#define TXCSR5_PRIO_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR6: Beacon Base address register. - */ -#define TXCSR6 0x0078 -#define TXCSR6_BEACON_RING_REGISTER FIELD32(0xffffffff) - -/* - * TXCSR7: Auto responder control register. - * AR_POWERMANAGEMENT: Auto responder power management bit. - */ -#define TXCSR7 0x007c -#define TXCSR7_AR_POWERMANAGEMENT FIELD32(0x00000001) - -/* - * TXCSR8: CCK Tx BBP register. - */ -#define TXCSR8 0x0098 -#define TXCSR8_BBP_ID0 FIELD32(0x0000007f) -#define TXCSR8_BBP_ID0_VALID FIELD32(0x00000080) -#define TXCSR8_BBP_ID1 FIELD32(0x00007f00) -#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 - * OFDM_SIGNAL: BBP rate field address for OFDM. - * OFDM_SERVICE: BBP service field address for OFDM. - * OFDM_LENGTH_LOW: BBP length low byte address for OFDM. - * OFDM_LENGTH_HIGH: BBP length high byte address for OFDM. - */ -#define TXCSR9 0x0094 -#define TXCSR9_OFDM_RATE FIELD32(0x000000ff) -#define TXCSR9_OFDM_SERVICE FIELD32(0x0000ff00) -#define TXCSR9_OFDM_LENGTH_LOW FIELD32(0x00ff0000) -#define TXCSR9_OFDM_LENGTH_HIGH FIELD32(0xff000000) - -/* - * Receive related CSRs. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * RXCSR0: RX Control Register. - * DISABLE_RX: Disable rx engine. - * DROP_CRC: Drop crc error. - * DROP_PHYSICAL: Drop physical error. - * DROP_CONTROL: Drop control frame. - * DROP_NOT_TO_ME: Drop not to me unicast frame. - * DROP_TODS: Drop frame tods bit is true. - * DROP_VERSION_ERROR: Drop version error frame. - * PASS_CRC: Pass all packets with crc attached. - * PASS_CRC: Pass all packets with crc attached. - * PASS_PLCP: Pass all packets with 4 bytes PLCP attached. - * DROP_MCAST: Drop multicast frames. - * DROP_BCAST: Drop broadcast frames. - * ENABLE_QOS: Accept QOS data frame and parse QOS field. - */ -#define RXCSR0 0x0080 -#define RXCSR0_DISABLE_RX FIELD32(0x00000001) -#define RXCSR0_DROP_CRC FIELD32(0x00000002) -#define RXCSR0_DROP_PHYSICAL FIELD32(0x00000004) -#define RXCSR0_DROP_CONTROL FIELD32(0x00000008) -#define RXCSR0_DROP_NOT_TO_ME FIELD32(0x00000010) -#define RXCSR0_DROP_TODS FIELD32(0x00000020) -#define RXCSR0_DROP_VERSION_ERROR FIELD32(0x00000040) -#define RXCSR0_PASS_CRC FIELD32(0x00000080) -#define RXCSR0_PASS_PLCP FIELD32(0x00000100) -#define RXCSR0_DROP_MCAST FIELD32(0x00000200) -#define RXCSR0_DROP_BCAST FIELD32(0x00000400) -#define RXCSR0_ENABLE_QOS FIELD32(0x00000800) - -/* - * RXCSR1: RX descriptor configuration register. - * RXD_SIZE: Rx descriptor size, default is 32b. - * NUM_RXD: Number of rx entries in ring. - */ -#define RXCSR1 0x0084 -#define RXCSR1_RXD_SIZE FIELD32(0x000000ff) -#define RXCSR1_NUM_RXD FIELD32(0x0000ff00) - -/* - * RXCSR2: RX Ring base address register. - */ -#define RXCSR2 0x0088 -#define RXCSR2_RX_RING_REGISTER FIELD32(0xffffffff) - -/* - * RXCSR3: BBP ID register for Rx operation. - * BBP_ID#: BBP register # id. - * BBP_ID#_VALID: BBP register # id is valid or not. - */ -#define RXCSR3 0x0090 -#define RXCSR3_BBP_ID0 FIELD32(0x0000007f) -#define RXCSR3_BBP_ID0_VALID FIELD32(0x00000080) -#define RXCSR3_BBP_ID1 FIELD32(0x00007f00) -#define RXCSR3_BBP_ID1_VALID FIELD32(0x00008000) -#define RXCSR3_BBP_ID2 FIELD32(0x007f0000) -#define RXCSR3_BBP_ID2_VALID FIELD32(0x00800000) -#define RXCSR3_BBP_ID3 FIELD32(0x7f000000) -#define RXCSR3_BBP_ID3_VALID FIELD32(0x80000000) - -/* - * ARCSR1: Auto Responder PLCP config register 1. - * AR_BBP_DATA#: Auto responder BBP register # data. - * AR_BBP_ID#: Auto responder BBP register # Id. - */ -#define ARCSR1 0x009c -#define ARCSR1_AR_BBP_DATA2 FIELD32(0x000000ff) -#define ARCSR1_AR_BBP_ID2 FIELD32(0x0000ff00) -#define ARCSR1_AR_BBP_DATA3 FIELD32(0x00ff0000) -#define ARCSR1_AR_BBP_ID3 FIELD32(0xff000000) - -/* - * Miscellaneous Registers. - * Some values are set in TU, whereas 1 TU == 1024 us. - - */ - -/* - * PCICSR: PCI control register. - * BIG_ENDIAN: 1: big endian, 0: little endian. - * RX_TRESHOLD: Rx threshold in dw to start pci access - * 0: 16dw (default), 1: 8dw, 2: 4dw, 3: 32dw. - * TX_TRESHOLD: Tx threshold in dw to start pci access - * 0: 0dw (default), 1: 1dw, 2: 4dw, 3: forward. - * BURST_LENTH: Pci burst length 0: 4dw (default, 1: 8dw, 2: 16dw, 3:32dw. - * ENABLE_CLK: Enable clk_run, pci clock can't going down to non-operational. - * READ_MULTIPLE: Enable memory read multiple. - * WRITE_INVALID: Enable memory write & invalid. - */ -#define PCICSR 0x008c -#define PCICSR_BIG_ENDIAN FIELD32(0x00000001) -#define PCICSR_RX_TRESHOLD FIELD32(0x00000006) -#define PCICSR_TX_TRESHOLD FIELD32(0x00000018) -#define PCICSR_BURST_LENTH FIELD32(0x00000060) -#define PCICSR_ENABLE_CLK FIELD32(0x00000080) -#define PCICSR_READ_MULTIPLE FIELD32(0x00000100) -#define PCICSR_WRITE_INVALID FIELD32(0x00000200) - -/* - * CNT0: FCS error count. - * FCS_ERROR: FCS error count, cleared when read. - */ -#define CNT0 0x00a0 -#define CNT0_FCS_ERROR FIELD32(0x0000ffff) - -/* - * Statistic Register. - * CNT1: PLCP error count. - * CNT2: Long error count. - */ -#define TIMECSR2 0x00a8 -#define CNT1 0x00ac -#define CNT2 0x00b0 -#define TIMECSR3 0x00b4 - -/* - * CNT3: CCA false alarm count. - */ -#define CNT3 0x00b8 -#define CNT3_FALSE_CCA FIELD32(0x0000ffff) - -/* - * Statistic Register. - * CNT4: Rx FIFO overflow count. - * CNT5: Tx FIFO underrun count. - */ -#define CNT4 0x00bc -#define CNT5 0x00c0 - -/* - * Baseband Control Register. - */ - -/* - * PWRCSR0: Power mode configuration register. - */ -#define PWRCSR0 0x00c4 - -/* - * Power state transition time registers. - */ -#define PSCSR0 0x00c8 -#define PSCSR1 0x00cc -#define PSCSR2 0x00d0 -#define PSCSR3 0x00d4 - -/* - * PWRCSR1: Manual power control / status register. - * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake. - * SET_STATE: Set state. Write 1 to trigger, self cleared. - * BBP_DESIRE_STATE: BBP desired state. - * RF_DESIRE_STATE: RF desired state. - * BBP_CURR_STATE: BBP current state. - * RF_CURR_STATE: RF current state. - * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared. - */ -#define PWRCSR1 0x00d8 -#define PWRCSR1_SET_STATE FIELD32(0x00000001) -#define PWRCSR1_BBP_DESIRE_STATE FIELD32(0x00000006) -#define PWRCSR1_RF_DESIRE_STATE FIELD32(0x00000018) -#define PWRCSR1_BBP_CURR_STATE FIELD32(0x00000060) -#define PWRCSR1_RF_CURR_STATE FIELD32(0x00000180) -#define PWRCSR1_PUT_TO_SLEEP FIELD32(0x00000200) - -/* - * TIMECSR: Timer control register. - * US_COUNT: 1 us timer count in units of clock cycles. - * US_64_COUNT: 64 us timer count in units of 1 us timer. - * BEACON_EXPECT: Beacon expect window. - */ -#define TIMECSR 0x00dc -#define TIMECSR_US_COUNT FIELD32(0x000000ff) -#define TIMECSR_US_64_COUNT FIELD32(0x0000ff00) -#define TIMECSR_BEACON_EXPECT FIELD32(0x00070000) - -/* - * MACCSR0: MAC configuration register 0. - */ -#define MACCSR0 0x00e0 - -/* - * MACCSR1: MAC configuration register 1. - * KICK_RX: Kick one-shot rx in one-shot rx mode. - * ONESHOT_RXMODE: Enable one-shot rx mode for debugging. - * BBPRX_RESET_MODE: Ralink bbp rx reset mode. - * AUTO_TXBBP: Auto tx logic access bbp control register. - * AUTO_RXBBP: Auto rx logic access bbp control register. - * LOOPBACK: Loopback mode. 0: normal, 1: internal, 2: external, 3:rsvd. - * INTERSIL_IF: Intersil if calibration pin. - */ -#define MACCSR1 0x00e4 -#define MACCSR1_KICK_RX FIELD32(0x00000001) -#define MACCSR1_ONESHOT_RXMODE FIELD32(0x00000002) -#define MACCSR1_BBPRX_RESET_MODE FIELD32(0x00000004) -#define MACCSR1_AUTO_TXBBP FIELD32(0x00000008) -#define MACCSR1_AUTO_RXBBP FIELD32(0x00000010) -#define MACCSR1_LOOPBACK FIELD32(0x00000060) -#define MACCSR1_INTERSIL_IF FIELD32(0x00000080) - -/* - * RALINKCSR: Ralink Rx auto-reset BBCR. - * AR_BBP_DATA#: Auto reset BBP register # data. - * AR_BBP_ID#: Auto reset BBP register # id. - */ -#define RALINKCSR 0x00e8 -#define RALINKCSR_AR_BBP_DATA0 FIELD32(0x000000ff) -#define RALINKCSR_AR_BBP_ID0 FIELD32(0x00007f00) -#define RALINKCSR_AR_BBP_VALID0 FIELD32(0x00008000) -#define RALINKCSR_AR_BBP_DATA1 FIELD32(0x00ff0000) -#define RALINKCSR_AR_BBP_ID1 FIELD32(0x7f000000) -#define RALINKCSR_AR_BBP_VALID1 FIELD32(0x80000000) - -/* - * BCNCSR: Beacon interval control register. - * CHANGE: Write one to change beacon interval. - * DELTATIME: The delta time value. - * NUM_BEACON: Number of beacon according to mode. - * MODE: Please refer to asic specs. - * PLUS: Plus or minus delta time value. - */ -#define BCNCSR 0x00ec -#define BCNCSR_CHANGE FIELD32(0x00000001) -#define BCNCSR_DELTATIME FIELD32(0x0000001e) -#define BCNCSR_NUM_BEACON FIELD32(0x00001fe0) -#define BCNCSR_MODE FIELD32(0x00006000) -#define BCNCSR_PLUS FIELD32(0x00008000) - -/* - * BBP / RF / IF Control Register. - */ - -/* - * BBPCSR: BBP serial control register. - * VALUE: Register value to program into BBP. - * REGNUM: Selected BBP register. - * BUSY: 1: asic is busy execute BBP programming. - * WRITE_CONTROL: 1: write BBP, 0: read BBP. - */ -#define BBPCSR 0x00f0 -#define BBPCSR_VALUE FIELD32(0x000000ff) -#define BBPCSR_REGNUM FIELD32(0x00007f00) -#define BBPCSR_BUSY FIELD32(0x00008000) -#define BBPCSR_WRITE_CONTROL FIELD32(0x00010000) - -/* - * RFCSR: RF serial control register. - * VALUE: Register value + id to program into rf/if. - * NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22). - * IF_SELECT: Chip to program: 0: rf, 1: if. - * PLL_LD: Rf pll_ld status. - * BUSY: 1: asic is busy execute rf programming. - */ -#define RFCSR 0x00f4 -#define RFCSR_VALUE FIELD32(0x00ffffff) -#define RFCSR_NUMBER_OF_BITS FIELD32(0x1f000000) -#define RFCSR_IF_SELECT FIELD32(0x20000000) -#define RFCSR_PLL_LD FIELD32(0x40000000) -#define RFCSR_BUSY FIELD32(0x80000000) - -/* - * LEDCSR: LED control register. - * ON_PERIOD: On period, default 70ms. - * OFF_PERIOD: Off period, default 30ms. - * LINK: 0: linkoff, 1: linkup. - * ACTIVITY: 0: idle, 1: active. - * LINK_POLARITY: 0: active low, 1: active high. - * ACTIVITY_POLARITY: 0: active low, 1: active high. - * LED_DEFAULT: LED state for "enable" 0: ON, 1: OFF. - */ -#define LEDCSR 0x00f8 -#define LEDCSR_ON_PERIOD FIELD32(0x000000ff) -#define LEDCSR_OFF_PERIOD FIELD32(0x0000ff00) -#define LEDCSR_LINK FIELD32(0x00010000) -#define LEDCSR_ACTIVITY FIELD32(0x00020000) -#define LEDCSR_LINK_POLARITY FIELD32(0x00040000) -#define LEDCSR_ACTIVITY_POLARITY FIELD32(0x00080000) -#define LEDCSR_LED_DEFAULT FIELD32(0x00100000) - -/* - * SECCSR3: AES control register. - */ -#define SECCSR3 0x00fc - -/* - * ASIC pointer information. - * RXPTR: Current RX ring address. - * TXPTR: Current Tx ring address. - * PRIPTR: Current Priority ring address. - * ATIMPTR: Current ATIM ring address. - */ -#define RXPTR 0x0100 -#define TXPTR 0x0104 -#define PRIPTR 0x0108 -#define ATIMPTR 0x010c - -/* - * TXACKCSR0: TX ACK timeout. - */ -#define TXACKCSR0 0x0110 - -/* - * ACK timeout count registers. - * ACKCNT0: TX ACK timeout count. - * ACKCNT1: RX ACK timeout count. - */ -#define ACKCNT0 0x0114 -#define ACKCNT1 0x0118 - -/* - * GPIO and others. - */ - -/* - * GPIOCSR: GPIO control register. - */ -#define GPIOCSR 0x0120 -#define GPIOCSR_BIT0 FIELD32(0x00000001) -#define GPIOCSR_BIT1 FIELD32(0x00000002) -#define GPIOCSR_BIT2 FIELD32(0x00000004) -#define GPIOCSR_BIT3 FIELD32(0x00000008) -#define GPIOCSR_BIT4 FIELD32(0x00000010) -#define GPIOCSR_BIT5 FIELD32(0x00000020) -#define GPIOCSR_BIT6 FIELD32(0x00000040) -#define GPIOCSR_BIT7 FIELD32(0x00000080) -#define GPIOCSR_DIR0 FIELD32(0x00000100) -#define GPIOCSR_DIR1 FIELD32(0x00000200) -#define GPIOCSR_DIR2 FIELD32(0x00000400) -#define GPIOCSR_DIR3 FIELD32(0x00000800) -#define GPIOCSR_DIR4 FIELD32(0x00001000) -#define GPIOCSR_DIR5 FIELD32(0x00002000) -#define GPIOCSR_DIR6 FIELD32(0x00004000) -#define GPIOCSR_DIR7 FIELD32(0x00008000) - -/* - * FIFO pointer registers. - * FIFOCSR0: TX FIFO pointer. - * FIFOCSR1: RX FIFO pointer. - */ -#define FIFOCSR0 0x0128 -#define FIFOCSR1 0x012c - -/* - * BCNCSR1: Tx BEACON offset time control register. - * PRELOAD: Beacon timer offset in units of usec. - * BEACON_CWMIN: 2^CwMin. - */ -#define BCNCSR1 0x0130 -#define BCNCSR1_PRELOAD FIELD32(0x0000ffff) -#define BCNCSR1_BEACON_CWMIN FIELD32(0x000f0000) - -/* - * MACCSR2: TX_PE to RX_PE turn-around time control register - * DELAY: RX_PE low width, in units of pci clock cycle. - */ -#define MACCSR2 0x0134 -#define MACCSR2_DELAY FIELD32(0x000000ff) - -/* - * TESTCSR: TEST mode selection register. - */ -#define TESTCSR 0x0138 - -/* - * ARCSR2: 1 Mbps ACK/CTS PLCP. - */ -#define ARCSR2 0x013c -#define ARCSR2_SIGNAL FIELD32(0x000000ff) -#define ARCSR2_SERVICE FIELD32(0x0000ff00) -#define ARCSR2_LENGTH FIELD32(0xffff0000) - -/* - * ARCSR3: 2 Mbps ACK/CTS PLCP. - */ -#define ARCSR3 0x0140 -#define ARCSR3_SIGNAL FIELD32(0x000000ff) -#define ARCSR3_SERVICE FIELD32(0x0000ff00) -#define ARCSR3_LENGTH FIELD32(0xffff0000) - -/* - * ARCSR4: 5.5 Mbps ACK/CTS PLCP. - */ -#define ARCSR4 0x0144 -#define ARCSR4_SIGNAL FIELD32(0x000000ff) -#define ARCSR4_SERVICE FIELD32(0x0000ff00) -#define ARCSR4_LENGTH FIELD32(0xffff0000) - -/* - * ARCSR5: 11 Mbps ACK/CTS PLCP. - */ -#define ARCSR5 0x0148 -#define ARCSR5_SIGNAL FIELD32(0x000000ff) -#define ARCSR5_SERVICE FIELD32(0x0000ff00) -#define ARCSR5_LENGTH FIELD32(0xffff0000) - -/* - * ARTCSR0: CCK ACK/CTS payload consumed time for 1/2/5.5/11 mbps. - */ -#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_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_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: WEP control register. - * KICK_ENCRYPT: Kick encryption engine, self-clear. - * ONE_SHOT: 0: ring mode, 1: One shot only mode. - * DESC_ADDRESS: Descriptor physical address of frame. - */ -#define SECCSR1 0x0158 -#define SECCSR1_KICK_ENCRYPT FIELD32(0x00000001) -#define SECCSR1_ONE_SHOT FIELD32(0x00000002) -#define SECCSR1_DESC_ADDRESS FIELD32(0xfffffffc) - -/* - * BBPCSR1: BBP TX configuration. - */ -#define BBPCSR1 0x015c -#define BBPCSR1_CCK FIELD32(0x00000003) -#define BBPCSR1_CCK_FLIP FIELD32(0x00000004) -#define BBPCSR1_OFDM FIELD32(0x00030000) -#define BBPCSR1_OFDM_FLIP FIELD32(0x00040000) - -/* - * Dual band configuration registers. - * DBANDCSR0: Dual band configuration register 0. - * DBANDCSR1: Dual band configuration register 1. - */ -#define DBANDCSR0 0x0160 -#define DBANDCSR1 0x0164 - -/* - * BBPPCSR: BBP Pin control register. - */ -#define BBPPCSR 0x0168 - -/* - * MAC special debug mode selection registers. - * DBGSEL0: MAC special debug mode selection register 0. - * DBGSEL1: MAC special debug mode selection register 1. - */ -#define DBGSEL0 0x016c -#define DBGSEL1 0x0170 - -/* - * BISTCSR: BBP BIST register. - */ -#define BISTCSR 0x0174 - -/* - * Multicast filter registers. - * MCAST0: Multicast filter register 0. - * MCAST1: Multicast filter register 1. - */ -#define MCAST0 0x0178 -#define MCAST1 0x017c - -/* - * UART registers. - * UARTCSR0: UART1 TX register. - * UARTCSR1: UART1 RX register. - * UARTCSR3: UART1 frame control register. - * UARTCSR4: UART1 buffer control register. - * UART2CSR0: UART2 TX register. - * UART2CSR1: UART2 RX register. - * UART2CSR3: UART2 frame control register. - * UART2CSR4: UART2 buffer control register. - */ -#define UARTCSR0 0x0180 -#define UARTCSR1 0x0184 -#define UARTCSR3 0x0188 -#define UARTCSR4 0x018c -#define UART2CSR0 0x0190 -#define UART2CSR1 0x0194 -#define UART2CSR3 0x0198 -#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 1 - */ -#define RF1_TUNER FIELD32(0x00020000) - -/* - * RF 3 - */ -#define RF3_TUNER FIELD32(0x00000100) -#define RF3_TXPOWER FIELD32(0x00003e00) - -/* - * EEPROM content. - * The wordsize of the EEPROM is 16 bits. - */ - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM antenna. - * ANTENNA_NUM: Number of antenna's. - * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * LED_MODE: 0: default, 1: TX/RX activity,2: Single (ignore link), 3: rsvd. - * DYN_TXAGC: Dynamic TX AGC control. - * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0. - * RF_TYPE: Rf_type of this adapter. - */ -#define EEPROM_ANTENNA 0x10 -#define EEPROM_ANTENNA_NUM FIELD16(0x0003) -#define EEPROM_ANTENNA_TX_DEFAULT FIELD16(0x000c) -#define EEPROM_ANTENNA_RX_DEFAULT FIELD16(0x0030) -#define EEPROM_ANTENNA_LED_MODE FIELD16(0x01c0) -#define EEPROM_ANTENNA_DYN_TXAGC FIELD16(0x0200) -#define EEPROM_ANTENNA_HARDWARE_RADIO FIELD16(0x0400) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0xf800) - -/* - * EEPROM NIC config. - * CARDBUS_ACCEL: 0: enable, 1: disable. - * DYN_BBP_TUNE: 0: enable, 1: disable. - * CCK_TX_POWER: CCK TX power compensation. - */ -#define EEPROM_NIC 0x11 -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0001) -#define EEPROM_NIC_DYN_BBP_TUNE FIELD16(0x0002) -#define EEPROM_NIC_CCK_TX_POWER FIELD16(0x000c) - -/* - * EEPROM geography. - * GEO: Default geography setting for device. - */ -#define EEPROM_GEOGRAPHY 0x12 -#define EEPROM_GEOGRAPHY_GEO FIELD16(0x0f00) - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x13 -#define EEPROM_BBP_SIZE 16 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * EEPROM TXPOWER - */ -#define EEPROM_TXPOWER_START 0x23 -#define EEPROM_TXPOWER_SIZE 7 -#define EEPROM_TXPOWER_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_2 FIELD16(0xff00) - -/* - * RSSI <-> dBm offset calibration - */ -#define EEPROM_CALIBRATE_OFFSET 0x3e -#define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff) - -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE ( 11 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 11 * sizeof(__le32) ) - -/* - * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. - */ - -/* - * Word0 - */ -#define TXD_W0_OWNER_NIC FIELD32(0x00000001) -#define TXD_W0_VALID FIELD32(0x00000002) -#define TXD_W0_RESULT FIELD32(0x0000001c) -#define TXD_W0_RETRY_COUNT FIELD32(0x000000e0) -#define TXD_W0_MORE_FRAG FIELD32(0x00000100) -#define TXD_W0_ACK FIELD32(0x00000200) -#define TXD_W0_TIMESTAMP FIELD32(0x00000400) -#define TXD_W0_OFDM FIELD32(0x00000800) -#define TXD_W0_CIPHER_OWNER FIELD32(0x00001000) -#define TXD_W0_IFS FIELD32(0x00006000) -#define TXD_W0_RETRY_MODE FIELD32(0x00008000) -#define TXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define TXD_W0_CIPHER_ALG FIELD32(0xe0000000) - -/* - * Word1 - */ -#define TXD_W1_BUFFER_ADDRESS FIELD32(0xffffffff) - -/* - * Word2 - */ -#define TXD_W2_IV_OFFSET FIELD32(0x0000003f) -#define TXD_W2_AIFS FIELD32(0x000000c0) -#define TXD_W2_CWMIN FIELD32(0x00000f00) -#define TXD_W2_CWMAX FIELD32(0x0000f000) - -/* - * Word3: PLCP information - */ -#define TXD_W3_PLCP_SIGNAL FIELD32(0x000000ff) -#define TXD_W3_PLCP_SERVICE FIELD32(0x0000ff00) -#define TXD_W3_PLCP_LENGTH_LOW FIELD32(0x00ff0000) -#define TXD_W3_PLCP_LENGTH_HIGH FIELD32(0xff000000) - -/* - * Word4 - */ -#define TXD_W4_IV FIELD32(0xffffffff) - -/* - * Word5 - */ -#define TXD_W5_EIV FIELD32(0xffffffff) - -/* - * Word6-9: Key - */ -#define TXD_W6_KEY FIELD32(0xffffffff) -#define TXD_W7_KEY FIELD32(0xffffffff) -#define TXD_W8_KEY FIELD32(0xffffffff) -#define TXD_W9_KEY FIELD32(0xffffffff) - -/* - * Word10 - */ -#define TXD_W10_RTS FIELD32(0x00000001) -#define TXD_W10_TX_RATE FIELD32(0x000000fe) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - */ -#define RXD_W0_OWNER_NIC FIELD32(0x00000001) -#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000002) -#define RXD_W0_MULTICAST FIELD32(0x00000004) -#define RXD_W0_BROADCAST FIELD32(0x00000008) -#define RXD_W0_MY_BSS FIELD32(0x00000010) -#define RXD_W0_CRC_ERROR FIELD32(0x00000020) -#define RXD_W0_OFDM FIELD32(0x00000040) -#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080) -#define RXD_W0_CIPHER_OWNER FIELD32(0x00000100) -#define RXD_W0_ICV_ERROR FIELD32(0x00000200) -#define RXD_W0_IV_OFFSET FIELD32(0x0000fc00) -#define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define RXD_W0_CIPHER_ALG FIELD32(0xe0000000) - -/* - * Word1 - */ -#define RXD_W1_BUFFER_ADDRESS FIELD32(0xffffffff) - -/* - * Word2 - */ -#define RXD_W2_SIGNAL FIELD32(0x000000ff) -#define RXD_W2_RSSI FIELD32(0x0000ff00) -#define RXD_W2_TA FIELD32(0xffff0000) - -/* - * Word3 - */ -#define RXD_W3_TA FIELD32(0xffffffff) - -/* - * Word4 - */ -#define RXD_W4_IV FIELD32(0xffffffff) - -/* - * Word5 - */ -#define RXD_W5_EIV FIELD32(0xffffffff) - -/* - * Word6-9: Key - */ -#define RXD_W6_KEY FIELD32(0xffffffff) -#define RXD_W7_KEY FIELD32(0xffffffff) -#define RXD_W8_KEY FIELD32(0xffffffff) -#define RXD_W9_KEY FIELD32(0xffffffff) - -/* - * Word10 - */ -#define RXD_W10_DROP FIELD32(0x00000001) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - */ -#define MIN_TXPOWER 0 -#define MAX_TXPOWER 31 -#define DEFAULT_TXPOWER 24 - -#define TXPOWER_FROM_DEV(__txpower) \ - (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) - -#endif /* RT2500PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c deleted file mode 100644 index 22dd6d9e2981..000000000000 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ /dev/null @@ -1,2063 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2500usb - Abstract: rt2500usb device specific routines. - Supported chipsets: RT2570. - */ - -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00usb.h" -#include "rt2500usb.h" - -/* - * Allow hardware encryption to be disabled. - */ -static int modparam_nohwcrypt = 0; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -/* - * Register access. - * All access to the CSR registers will go through the methods - * rt2500usb_register_read and rt2500usb_register_write. - * BBP and RF register require indirect register access, - * and use the CSR registers BBPCSR and RFCSR to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - * If the csr_mutex is already held then the _lock variants must - * be used instead. - */ -static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u16 *value) -{ - __le16 reg; - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); - *value = le16_to_cpu(reg); -} - -static inline void rt2500usb_register_read_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u16 *value) -{ - __le16 reg; - rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); - *value = le16_to_cpu(reg); -} - -static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u16 length) -{ - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - value, length, - REGISTER_TIMEOUT16(length)); -} - -static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u16 value) -{ - __le16 reg = cpu_to_le16(value); - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); -} - -static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u16 value) -{ - __le16 reg = cpu_to_le16(value); - rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); -} - -static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u16 length) -{ - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - value, length, - REGISTER_TIMEOUT16(length)); -} - -static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - struct rt2x00_field16 field, - u16 *reg) -{ - unsigned int i; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read_lock(rt2x00dev, offset, reg); - if (!rt2x00_get_field16(*reg, field)) - return 1; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "Indirect register access failed: " - "offset=0x%.08x, value=0x%.08x\n", offset, *reg); - *reg = ~0; - - return 0; -} - -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2500usb_regbusy_read((__dev), PHY_CSR8, PHY_CSR8_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2500usb_regbusy_read((__dev), PHY_CSR10, PHY_CSR10_RF_BUSY, (__reg)) - -static void rt2500usb_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u16 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field16(®, PHY_CSR7_DATA, value); - rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); - rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 0); - - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2500usb_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u16 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field16(®, PHY_CSR7_REG_ID, word); - rt2x00_set_field16(®, PHY_CSR7_READ_CONTROL, 1); - - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR7, reg); - - if (WAIT_FOR_BBP(rt2x00dev, ®)) - rt2500usb_register_read_lock(rt2x00dev, PHY_CSR7, ®); - } - - *value = rt2x00_get_field16(reg, PHY_CSR7_DATA); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2500usb_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u16 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field16(®, PHY_CSR9_RF_VALUE, value); - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR9, reg); - - reg = 0; - rt2x00_set_field16(®, PHY_CSR10_RF_VALUE, value >> 16); - rt2x00_set_field16(®, PHY_CSR10_RF_NUMBER_OF_BITS, 20); - rt2x00_set_field16(®, PHY_CSR10_RF_IF_SELECT, 0); - rt2x00_set_field16(®, PHY_CSR10_RF_BUSY, 1); - - rt2500usb_register_write_lock(rt2x00dev, PHY_CSR10, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -static void _rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 *value) -{ - rt2500usb_register_read(rt2x00dev, offset, (u16 *)value); -} - -static void _rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 value) -{ - rt2500usb_register_write(rt2x00dev, offset, value); -} - -static const struct rt2x00debug rt2500usb_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = _rt2500usb_register_read, - .write = _rt2500usb_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u16), - .word_count = CSR_REG_SIZE / sizeof(u16), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt2500usb_bbp_read, - .write = rt2500usb_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt2500usb_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, MAC_CSR19, ®); - return rt2x00_get_field32(reg, MAC_CSR19_BIT7); -} - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt2500usb_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - u16 reg; - - rt2500usb_register_read(led->rt2x00dev, MAC_CSR20, ®); - - if (led->type == LED_TYPE_RADIO || led->type == LED_TYPE_ASSOC) - rt2x00_set_field16(®, MAC_CSR20_LINK, enabled); - else if (led->type == LED_TYPE_ACTIVITY) - rt2x00_set_field16(®, MAC_CSR20_ACTIVITY, enabled); - - rt2500usb_register_write(led->rt2x00dev, MAC_CSR20, reg); -} - -static int rt2500usb_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u16 reg; - - rt2500usb_register_read(led->rt2x00dev, MAC_CSR21, ®); - rt2x00_set_field16(®, MAC_CSR21_ON_PERIOD, *delay_on); - rt2x00_set_field16(®, MAC_CSR21_OFF_PERIOD, *delay_off); - rt2500usb_register_write(led->rt2x00dev, MAC_CSR21, reg); - - return 0; -} - -static void rt2500usb_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt2500usb_brightness_set; - led->led_dev.blink_set = rt2500usb_blink_set; - led->flags = LED_INITIALIZED; -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ - -/* - * rt2500usb does not differentiate between shared and pairwise - * keys, so we should use the same function for both key types. - */ -static int rt2500usb_config_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - int timeout; - u32 mask; - u16 reg; - - if (crypto->cmd == SET_KEY) { - /* - * Pairwise key will always be entry 0, but this - * could collide with a shared key on the same - * position... - */ - mask = TXRX_CSR0_KEY_ID.bit_mask; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); - reg &= mask; - - if (reg && reg == mask) - return -ENOSPC; - - reg = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); - - key->hw_key_idx += reg ? ffz(reg) : 0; - - /* - * The encryption key doesn't fit within the CSR cache, - * this means we should allocate it seperately and use - * rt2x00usb_vendor_request() to send the key to the hardware. - */ - reg = KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(crypto->key)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, reg, - crypto->key, - sizeof(crypto->key), - timeout); - - /* - * The driver does not support the IV/EIV generation - * in hardware. However it demands the data to be provided - * both seperately as well as inside the frame. - * We already provided the CONFIG_CRYPTO_COPY_IV to rt2x00lib - * to ensure rt2x00lib will not strip the data from the - * frame after the copy, now we must tell mac80211 - * to generate the IV/EIV data. - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; - } - - /* - * TXRX_CSR0_KEY_ID contains only single-bit fields to indicate - * a particular key is valid. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field16(®, TXRX_CSR0_ALGORITHM, crypto->cipher); - rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); - - mask = rt2x00_get_field16(reg, TXRX_CSR0_KEY_ID); - if (crypto->cmd == SET_KEY) - mask |= 1 << key->hw_key_idx; - else if (crypto->cmd == DISABLE_KEY) - mask &= ~(1 << key->hw_key_idx); - rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, mask); - rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); - - return 0; -} - -static void rt2500usb_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u16 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CRC, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_PHYSICAL, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_CONTROL, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_TODS, - !(filter_flags & FIF_PROMISC_IN_BSS) && - !rt2x00dev->intf_ap_count); - rt2x00_set_field16(®, TXRX_CSR2_DROP_VERSION_ERROR, 1); - rt2x00_set_field16(®, TXRX_CSR2_DROP_MULTICAST, - !(filter_flags & FIF_ALLMULTI)); - rt2x00_set_field16(®, TXRX_CSR2_DROP_BROADCAST, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} - -static void rt2500usb_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags) -{ - unsigned int bcn_preload; - u16 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Enable beacon config - */ - bcn_preload = PREAMBLE + GET_DURATION(IEEE80211_HEADER, 20); - rt2500usb_register_read(rt2x00dev, TXRX_CSR20, ®); - rt2x00_set_field16(®, TXRX_CSR20_OFFSET, bcn_preload >> 6); - rt2x00_set_field16(®, TXRX_CSR20_BCN_EXPECT_WINDOW, - 2 * (conf->type != NL80211_IFTYPE_STATION)); - rt2500usb_register_write(rt2x00dev, TXRX_CSR20, reg); - - /* - * Enable synchronisation. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_OFFSET, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, conf->sync); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - } - - if (flags & CONFIG_UPDATE_MAC) - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR2, conf->mac, - (3 * sizeof(__le16))); - - if (flags & CONFIG_UPDATE_BSSID) - rt2500usb_register_multiwrite(rt2x00dev, MAC_CSR5, conf->bssid, - (3 * sizeof(__le16))); -} - -static void rt2500usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR10, ®); - rt2x00_set_field16(®, TXRX_CSR10_AUTORESPOND_PREAMBLE, - !!erp->short_preamble); - rt2500usb_register_write(rt2x00dev, TXRX_CSR10, reg); - - rt2500usb_register_write(rt2x00dev, TXRX_CSR11, erp->basic_rates); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR18, ®); - rt2x00_set_field16(®, TXRX_CSR18_INTERVAL, erp->beacon_int * 4); - rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg); - - rt2500usb_register_write(rt2x00dev, MAC_CSR10, erp->slot_time); - rt2500usb_register_write(rt2x00dev, MAC_CSR11, erp->sifs); - rt2500usb_register_write(rt2x00dev, MAC_CSR12, erp->eifs); -} - -static void rt2500usb_config_ant(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r2; - u8 r14; - u16 csr5; - u16 csr6; - - /* - * We should never come here because rt2x00lib is supposed - * to catch this and send us the correct antenna explicitely. - */ - BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || - ant->tx == ANTENNA_SW_DIVERSITY); - - rt2500usb_bbp_read(rt2x00dev, 2, &r2); - rt2500usb_bbp_read(rt2x00dev, 14, &r14); - rt2500usb_register_read(rt2x00dev, PHY_CSR5, &csr5); - rt2500usb_register_read(rt2x00dev, PHY_CSR6, &csr6); - - /* - * Configure the TX antenna. - */ - switch (ant->tx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 1); - rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 1); - rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 1); - break; - case ANTENNA_A: - rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 0); - rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 0); - rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 0); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r2, BBP_R2_TX_ANTENNA, 2); - rt2x00_set_field16(&csr5, PHY_CSR5_CCK, 2); - rt2x00_set_field16(&csr6, PHY_CSR6_OFDM, 2); - break; - } - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 1); - break; - case ANTENNA_A: - rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 0); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r14, BBP_R14_RX_ANTENNA, 2); - break; - } - - /* - * RT2525E and RT5222 need to flip TX I/Q - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E) || - rt2x00_rf(&rt2x00dev->chip, RF5222)) { - rt2x00_set_field8(&r2, BBP_R2_TX_IQ_FLIP, 1); - rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 1); - rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 1); - - /* - * RT2525E does not need RX I/Q Flip. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) - rt2x00_set_field8(&r14, BBP_R14_RX_IQ_FLIP, 0); - } else { - rt2x00_set_field16(&csr5, PHY_CSR5_CCK_FLIP, 0); - rt2x00_set_field16(&csr6, PHY_CSR6_OFDM_FLIP, 0); - } - - rt2500usb_bbp_write(rt2x00dev, 2, r2); - rt2500usb_bbp_write(rt2x00dev, 14, r14); - rt2500usb_register_write(rt2x00dev, PHY_CSR5, csr5); - rt2500usb_register_write(rt2x00dev, PHY_CSR6, csr6); -} - -static void rt2500usb_config_channel(struct rt2x00_dev *rt2x00dev, - struct rf_channel *rf, const int txpower) -{ - /* - * Set TXpower. - */ - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - - /* - * For RT2525E we should first set the channel to half band higher. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { - static const u32 vals[] = { - 0x000008aa, 0x000008ae, 0x000008ae, 0x000008b2, - 0x000008b2, 0x000008b6, 0x000008b6, 0x000008ba, - 0x000008ba, 0x000008be, 0x000008b7, 0x00000902, - 0x00000902, 0x00000906 - }; - - rt2500usb_rf_write(rt2x00dev, 2, vals[rf->channel - 1]); - if (rf->rf4) - rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); - } - - rt2500usb_rf_write(rt2x00dev, 1, rf->rf1); - rt2500usb_rf_write(rt2x00dev, 2, rf->rf2); - rt2500usb_rf_write(rt2x00dev, 3, rf->rf3); - if (rf->rf4) - rt2500usb_rf_write(rt2x00dev, 4, rf->rf4); -} - -static void rt2500usb_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - u32 rf3; - - rt2x00_rf_read(rt2x00dev, 3, &rf3); - rt2x00_set_field32(&rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - rt2500usb_rf_write(rt2x00dev, 3, rf3); -} - -static void rt2500usb_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u16 reg; - - if (state == STATE_SLEEP) { - rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); - rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, - rt2x00dev->beacon_int - 20); - rt2x00_set_field16(®, MAC_CSR18_BEACONS_BEFORE_WAKEUP, - libconf->conf->listen_interval - 1); - - /* We must first disable autowake before it can be enabled */ - rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 0); - rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); - - rt2x00_set_field16(®, MAC_CSR18_AUTO_WAKE, 1); - rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); - } - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); -} - -static void rt2500usb_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2500usb_config_channel(rt2x00dev, &libconf->rf, - libconf->conf->power_level); - if ((flags & IEEE80211_CONF_CHANGE_POWER) && - !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) - rt2500usb_config_txpower(rt2x00dev, - libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt2500usb_config_ps(rt2x00dev, libconf); -} - -/* - * Link tuning - */ -static void rt2500usb_link_stats(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u16 reg; - - /* - * Update FCS error count from register. - */ - rt2500usb_register_read(rt2x00dev, STA_CSR0, ®); - qual->rx_failed = rt2x00_get_field16(reg, STA_CSR0_FCS_ERROR); - - /* - * Update False CCA count from register. - */ - rt2500usb_register_read(rt2x00dev, STA_CSR3, ®); - qual->false_cca = rt2x00_get_field16(reg, STA_CSR3_FALSE_CCA_ERROR); -} - -static void rt2500usb_reset_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u16 eeprom; - u16 value; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R24_LOW); - rt2500usb_bbp_write(rt2x00dev, 24, value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R25_LOW); - rt2500usb_bbp_write(rt2x00dev, 25, value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_R61_LOW); - rt2500usb_bbp_write(rt2x00dev, 61, value); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_BBPTUNE_VGCUPPER); - rt2500usb_bbp_write(rt2x00dev, 17, value); - - qual->vgc_level = value; -} - -/* - * NOTE: This function is directly ported from legacy driver, but - * despite it being declared it was never called. Although link tuning - * sounds like a good idea, and usually works well for the other drivers, - * it does _not_ work with rt2500usb. Enabling this function will result - * in TX capabilities only until association kicks in. Immediately - * after the successful association all TX frames will be kept in the - * hardware queue and never transmitted. - */ -#if 0 -static void rt2500usb_link_tuner(struct rt2x00_dev *rt2x00dev) -{ - int rssi = rt2x00_get_link_rssi(&rt2x00dev->link); - u16 bbp_thresh; - u16 vgc_bound; - u16 sens; - u16 r24; - u16 r25; - u16 r61; - u16 r17_sens; - u8 r17; - u8 up_bound; - u8 low_bound; - - /* - * Read current r17 value, as well as the sensitivity values - * for the r17 register. - */ - rt2500usb_bbp_read(rt2x00dev, 17, &r17); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &r17_sens); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &vgc_bound); - up_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCUPPER); - low_bound = rt2x00_get_field16(vgc_bound, EEPROM_BBPTUNE_VGCLOWER); - - /* - * If we are not associated, we should go straight to the - * dynamic CCA tuning. - */ - if (!rt2x00dev->intf_associated) - goto dynamic_cca_tune; - - /* - * Determine the BBP tuning threshold and correctly - * set BBP 24, 25 and 61. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &bbp_thresh); - bbp_thresh = rt2x00_get_field16(bbp_thresh, EEPROM_BBPTUNE_THRESHOLD); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &r24); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &r25); - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &r61); - - if ((rssi + bbp_thresh) > 0) { - r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_HIGH); - r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_HIGH); - r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_HIGH); - } else { - r24 = rt2x00_get_field16(r24, EEPROM_BBPTUNE_R24_LOW); - r25 = rt2x00_get_field16(r25, EEPROM_BBPTUNE_R25_LOW); - r61 = rt2x00_get_field16(r61, EEPROM_BBPTUNE_R61_LOW); - } - - rt2500usb_bbp_write(rt2x00dev, 24, r24); - rt2500usb_bbp_write(rt2x00dev, 25, r25); - rt2500usb_bbp_write(rt2x00dev, 61, r61); - - /* - * A too low RSSI will cause too much false CCA which will - * then corrupt the R17 tuning. To remidy this the tuning should - * be stopped (While making sure the R17 value will not exceed limits) - */ - if (rssi >= -40) { - if (r17 != 0x60) - rt2500usb_bbp_write(rt2x00dev, 17, 0x60); - return; - } - - /* - * Special big-R17 for short distance - */ - if (rssi >= -58) { - sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_LOW); - if (r17 != sens) - rt2500usb_bbp_write(rt2x00dev, 17, sens); - return; - } - - /* - * Special mid-R17 for middle distance - */ - if (rssi >= -74) { - sens = rt2x00_get_field16(r17_sens, EEPROM_BBPTUNE_R17_HIGH); - if (r17 != sens) - rt2500usb_bbp_write(rt2x00dev, 17, sens); - return; - } - - /* - * Leave short or middle distance condition, restore r17 - * to the dynamic tuning range. - */ - low_bound = 0x32; - if (rssi < -77) - up_bound -= (-77 - rssi); - - if (up_bound < low_bound) - up_bound = low_bound; - - if (r17 > up_bound) { - rt2500usb_bbp_write(rt2x00dev, 17, up_bound); - rt2x00dev->link.vgc_level = up_bound; - return; - } - -dynamic_cca_tune: - - /* - * R17 is inside the dynamic tuning range, - * start tuning the link based on the false cca counter. - */ - if (rt2x00dev->link.qual.false_cca > 512 && r17 < up_bound) { - rt2500usb_bbp_write(rt2x00dev, 17, ++r17); - rt2x00dev->link.vgc_level = r17; - } else if (rt2x00dev->link.qual.false_cca < 100 && r17 > low_bound) { - rt2500usb_bbp_write(rt2x00dev, 17, --r17); - rt2x00dev->link.vgc_level = r17; - } -} -#else -#define rt2500usb_link_tuner NULL -#endif - -/* - * Initialization functions. - */ -static int rt2500usb_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u16 reg; - - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0x0001, - USB_MODE_TEST, REGISTER_TIMEOUT); - rt2x00usb_vendor_request_sw(rt2x00dev, USB_SINGLE_WRITE, 0x0308, - 0x00f0, REGISTER_TIMEOUT); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, 1); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); - - rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x1111); - rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x1e11); - - rt2500usb_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 1); - rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 1); - rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); - rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2500usb_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 0); - rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 0); - rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 0); - rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR5, ®); - rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0, 13); - rt2x00_set_field16(®, TXRX_CSR5_BBP_ID0_VALID, 1); - rt2x00_set_field16(®, TXRX_CSR5_BBP_ID1, 12); - rt2x00_set_field16(®, TXRX_CSR5_BBP_ID1_VALID, 1); - rt2500usb_register_write(rt2x00dev, TXRX_CSR5, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR6, ®); - rt2x00_set_field16(®, TXRX_CSR6_BBP_ID0, 10); - rt2x00_set_field16(®, TXRX_CSR6_BBP_ID0_VALID, 1); - rt2x00_set_field16(®, TXRX_CSR6_BBP_ID1, 11); - rt2x00_set_field16(®, TXRX_CSR6_BBP_ID1_VALID, 1); - rt2500usb_register_write(rt2x00dev, TXRX_CSR6, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR7, ®); - rt2x00_set_field16(®, TXRX_CSR7_BBP_ID0, 7); - rt2x00_set_field16(®, TXRX_CSR7_BBP_ID0_VALID, 1); - rt2x00_set_field16(®, TXRX_CSR7_BBP_ID1, 6); - rt2x00_set_field16(®, TXRX_CSR7_BBP_ID1_VALID, 1); - rt2500usb_register_write(rt2x00dev, TXRX_CSR7, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR8, ®); - rt2x00_set_field16(®, TXRX_CSR8_BBP_ID0, 5); - rt2x00_set_field16(®, TXRX_CSR8_BBP_ID0_VALID, 1); - rt2x00_set_field16(®, TXRX_CSR8_BBP_ID1, 0); - rt2x00_set_field16(®, TXRX_CSR8_BBP_ID1_VALID, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR8, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 0); - rt2x00_set_field16(®, TXRX_CSR19_TSF_SYNC, 0); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 0); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - - rt2500usb_register_write(rt2x00dev, TXRX_CSR21, 0xe78f); - rt2500usb_register_write(rt2x00dev, MAC_CSR9, 0xff1d); - - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2500usb_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field16(®, MAC_CSR1_SOFT_RESET, 0); - rt2x00_set_field16(®, MAC_CSR1_BBP_RESET, 0); - rt2x00_set_field16(®, MAC_CSR1_HOST_READY, 1); - rt2500usb_register_write(rt2x00dev, MAC_CSR1, reg); - - if (rt2x00_rev(&rt2x00dev->chip) >= RT2570_VERSION_C) { - rt2500usb_register_read(rt2x00dev, PHY_CSR2, ®); - rt2x00_set_field16(®, PHY_CSR2_LNA, 0); - } else { - reg = 0; - rt2x00_set_field16(®, PHY_CSR2_LNA, 1); - rt2x00_set_field16(®, PHY_CSR2_LNA_MODE, 3); - } - rt2500usb_register_write(rt2x00dev, PHY_CSR2, reg); - - rt2500usb_register_write(rt2x00dev, MAC_CSR11, 0x0002); - rt2500usb_register_write(rt2x00dev, MAC_CSR22, 0x0053); - rt2500usb_register_write(rt2x00dev, MAC_CSR15, 0x01ee); - rt2500usb_register_write(rt2x00dev, MAC_CSR16, 0x0000); - - rt2500usb_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field16(®, MAC_CSR8_MAX_FRAME_UNIT, - rt2x00dev->rx->data_size); - rt2500usb_register_write(rt2x00dev, MAC_CSR8, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field16(®, TXRX_CSR0_IV_OFFSET, IEEE80211_HEADER); - rt2x00_set_field16(®, TXRX_CSR0_KEY_ID, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2500usb_register_read(rt2x00dev, MAC_CSR18, ®); - rt2x00_set_field16(®, MAC_CSR18_DELAY_AFTER_BEACON, 90); - rt2500usb_register_write(rt2x00dev, MAC_CSR18, reg); - - rt2500usb_register_read(rt2x00dev, PHY_CSR4, ®); - rt2x00_set_field16(®, PHY_CSR4_LOW_RF_LE, 1); - rt2500usb_register_write(rt2x00dev, PHY_CSR4, reg); - - rt2500usb_register_read(rt2x00dev, TXRX_CSR1, ®); - rt2x00_set_field16(®, TXRX_CSR1_AUTO_SEQUENCE, 1); - rt2500usb_register_write(rt2x00dev, TXRX_CSR1, reg); - - return 0; -} - -static int rt2500usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -static int rt2500usb_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 value; - u8 reg_id; - - if (unlikely(rt2500usb_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt2500usb_bbp_write(rt2x00dev, 3, 0x02); - rt2500usb_bbp_write(rt2x00dev, 4, 0x19); - rt2500usb_bbp_write(rt2x00dev, 14, 0x1c); - rt2500usb_bbp_write(rt2x00dev, 15, 0x30); - rt2500usb_bbp_write(rt2x00dev, 16, 0xac); - rt2500usb_bbp_write(rt2x00dev, 18, 0x18); - rt2500usb_bbp_write(rt2x00dev, 19, 0xff); - rt2500usb_bbp_write(rt2x00dev, 20, 0x1e); - rt2500usb_bbp_write(rt2x00dev, 21, 0x08); - rt2500usb_bbp_write(rt2x00dev, 22, 0x08); - rt2500usb_bbp_write(rt2x00dev, 23, 0x08); - rt2500usb_bbp_write(rt2x00dev, 24, 0x80); - rt2500usb_bbp_write(rt2x00dev, 25, 0x50); - rt2500usb_bbp_write(rt2x00dev, 26, 0x08); - rt2500usb_bbp_write(rt2x00dev, 27, 0x23); - rt2500usb_bbp_write(rt2x00dev, 30, 0x10); - rt2500usb_bbp_write(rt2x00dev, 31, 0x2b); - rt2500usb_bbp_write(rt2x00dev, 32, 0xb9); - rt2500usb_bbp_write(rt2x00dev, 34, 0x12); - rt2500usb_bbp_write(rt2x00dev, 35, 0x50); - rt2500usb_bbp_write(rt2x00dev, 39, 0xc4); - rt2500usb_bbp_write(rt2x00dev, 40, 0x02); - rt2500usb_bbp_write(rt2x00dev, 41, 0x60); - rt2500usb_bbp_write(rt2x00dev, 53, 0x10); - rt2500usb_bbp_write(rt2x00dev, 54, 0x18); - rt2500usb_bbp_write(rt2x00dev, 56, 0x08); - rt2500usb_bbp_write(rt2x00dev, 57, 0x10); - rt2500usb_bbp_write(rt2x00dev, 58, 0x08); - rt2500usb_bbp_write(rt2x00dev, 61, 0x60); - rt2500usb_bbp_write(rt2x00dev, 62, 0x10); - rt2500usb_bbp_write(rt2x00dev, 75, 0xff); - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt2500usb_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} - -/* - * Device state switch handlers. - */ -static void rt2500usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u16 reg; - - rt2500usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field16(®, TXRX_CSR2_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2500usb_register_write(rt2x00dev, TXRX_CSR2, reg); -} - -static int rt2500usb_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Initialize all registers. - */ - if (unlikely(rt2500usb_init_registers(rt2x00dev) || - rt2500usb_init_bbp(rt2x00dev))) - return -EIO; - - return 0; -} - -static void rt2500usb_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - rt2500usb_register_write(rt2x00dev, MAC_CSR13, 0x2121); - rt2500usb_register_write(rt2x00dev, MAC_CSR14, 0x2121); - - /* - * Disable synchronisation. - */ - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, 0); - - rt2x00usb_disable_radio(rt2x00dev); -} - -static int rt2500usb_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u16 reg; - u16 reg2; - unsigned int i; - char put_to_sleep; - char bbp_state; - char rf_state; - - put_to_sleep = (state != STATE_AWAKE); - - reg = 0; - rt2x00_set_field16(®, MAC_CSR17_BBP_DESIRE_STATE, state); - rt2x00_set_field16(®, MAC_CSR17_RF_DESIRE_STATE, state); - rt2x00_set_field16(®, MAC_CSR17_PUT_TO_SLEEP, put_to_sleep); - rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg); - rt2x00_set_field16(®, MAC_CSR17_SET_STATE, 1); - rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg); - - /* - * Device is not guaranteed to be in the requested state yet. - * We must wait until the register indicates that the - * device has entered the correct state. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2500usb_register_read(rt2x00dev, MAC_CSR17, ®2); - bbp_state = rt2x00_get_field16(reg2, MAC_CSR17_BBP_CURR_STATE); - rf_state = rt2x00_get_field16(reg2, MAC_CSR17_RF_CURR_STATE); - if (bbp_state == state && rf_state == state) - return 0; - rt2500usb_register_write(rt2x00dev, MAC_CSR17, reg); - msleep(30); - } - - return -EBUSY; -} - -static int rt2500usb_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int retval = 0; - - switch (state) { - case STATE_RADIO_ON: - retval = rt2500usb_enable_radio(rt2x00dev); - break; - case STATE_RADIO_OFF: - rt2500usb_disable_radio(rt2x00dev); - break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2500usb_toggle_rx(rt2x00dev, state); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: - /* No support, but no error either */ - break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2500usb_set_state(rt2x00dev, state); - break; - default: - retval = -ENOTSUPP; - break; - } - - if (unlikely(retval)) - ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", - state, retval); - - return retval; -} - -/* - * TX descriptor initialization - */ -static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; - u32 word; - - /* - * Start writing the descriptor words. - */ - rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); - rt2x00_set_field32(&word, TXD_W1_AIFS, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); - rt2x00_desc_write(txd, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); - rt2x00_desc_write(txd, 2, word); - - if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { - _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); - _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); - } - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_RETRY_LIMIT, txdesc->retry_limit); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_OFDM, - (txdesc->rate_mode == RATE_MODE_OFDM)); - rt2x00_set_field32(&word, TXD_W0_NEW_SEQ, - test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); - rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher); - rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx); - rt2x00_desc_write(txd, 0, word); -} - -/* - * TX data initialization - */ -static void rt2500usb_beacondone(struct urb *urb); - -static void rt2500usb_write_beacon(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); - struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - int pipe = usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint); - int length; - u16 reg; - - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry->skb->data; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - - /* - * USB devices cannot blindly pass the skb->len as the - * length of the data to usb_fill_bulk_urb. Pass the skb - * to the driver to determine what the length should be. - */ - length = rt2x00dev->ops->lib->get_tx_data_len(entry); - - usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe, - entry->skb->data, length, rt2500usb_beacondone, - entry); - - /* - * 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. - */ - bcn_priv->guardian_data = 0; - usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe, - &bcn_priv->guardian_data, 1, rt2500usb_beacondone, - entry); - - /* - * Send out the guardian byte. - */ - usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC); -} - -static int rt2500usb_get_tx_data_len(struct queue_entry *entry) -{ - int length; - - /* - * The length _must_ be a multiple of 2, - * but it must _not_ be a multiple of the USB packet size. - */ - length = roundup(entry->skb->len, 2); - length += (2 * !(length % entry->queue->usb_maxpacket)); - - return length; -} - -static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u16 reg, reg0; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - rt2500usb_register_read(rt2x00dev, TXRX_CSR19, ®); - if (!rt2x00_get_field16(reg, TXRX_CSR19_BEACON_GEN)) { - rt2x00_set_field16(®, TXRX_CSR19_TSF_COUNT, 1); - rt2x00_set_field16(®, TXRX_CSR19_TBCN, 1); - reg0 = reg; - rt2x00_set_field16(®, TXRX_CSR19_BEACON_GEN, 1); - /* - * Beacon generation will fail initially. - * To prevent this we need to change the TXRX_CSR19 - * register several times (reg0 is the same as reg - * except for TXRX_CSR19_BEACON_GEN, which is 0 in reg0 - * and 1 in reg). - */ - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg0); - rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg); - } -} - -/* - * RX control handlers - */ -static void rt2500usb_fill_rxdone(struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - __le32 *rxd = - (__le32 *)(entry->skb->data + - (entry_priv->urb->actual_length - - entry->queue->desc_size)); - u32 word0; - u32 word1; - - /* - * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of - * frame data in rt2x00usb. - */ - memcpy(skbdesc->desc, rxd, skbdesc->desc_len); - rxd = (__le32 *)skbdesc->desc; - - /* - * It is now safe to read the descriptor on all architectures. - */ - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 1, &word1); - - if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - if (rt2x00_get_field32(word0, RXD_W0_PHYSICAL_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_PLCP_CRC; - - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = rt2x00_get_field32(word0, RXD_W0_CIPHER); - if (rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR)) - rxdesc->cipher_status = RX_CRYPTO_FAIL_KEY; - } - - if (rxdesc->cipher != CIPHER_NONE) { - _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]); - _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]); - rxdesc->dev_flags |= RXDONE_CRYPTO_IV; - - /* ICV is located at the end of frame */ - - rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; - if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) - rxdesc->flags |= RX_FLAG_DECRYPTED; - else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) - rxdesc->flags |= RX_FLAG_MMIC_ERROR; - } - - /* - * Obtain the status about this packet. - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 100kbit/s. - */ - rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - rxdesc->rssi = - rt2x00_get_field32(word1, RXD_W1_RSSI) - rt2x00dev->rssi_offset; - rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - - if (rt2x00_get_field32(word0, RXD_W0_OFDM)) - rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; - else - rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; - if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) - rxdesc->dev_flags |= RXDONE_MY_BSS; - - /* - * Adjust the skb memory window to the frame boundaries. - */ - skb_trim(entry->skb, rxdesc->size); -} - -/* - * Interrupt functions. - */ -static void rt2500usb_beacondone(struct urb *urb) -{ - struct queue_entry *entry = (struct queue_entry *)urb->context; - struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &entry->queue->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 (bcn_priv->guardian_urb == urb) { - usb_submit_urb(bcn_priv->urb, GFP_ATOMIC); - } else if (bcn_priv->urb == urb) { - dev_kfree_skb(entry->skb); - entry->skb = NULL; - } -} - -/* - * Device probe functions. - */ -static int rt2500usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u16 word; - u8 *mac; - u8 bbp; - - rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); - - /* - * Start validation of the data that has been read. - */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - if (!is_valid_ether_addr(mac)) { - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %pM\n", mac); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, - ANTENNA_SW_DIVERSITY); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, - ANTENNA_SW_DIVERSITY); - rt2x00_set_field16(&word, EEPROM_ANTENNA_LED_MODE, - LED_MODE_DEFAULT); - rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2522); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); - EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DYN_BBP_TUNE, 0); - rt2x00_set_field16(&word, EEPROM_NIC_CCK_TX_POWER, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); - EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_CALIBRATE_OFFSET_RSSI, - DEFAULT_RSSI_OFFSET); - rt2x00_eeprom_write(rt2x00dev, EEPROM_CALIBRATE_OFFSET, word); - EEPROM(rt2x00dev, "Calibrate offset: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_THRESHOLD, 45); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE, word); - EEPROM(rt2x00dev, "BBPtune: 0x%04x\n", word); - } - - /* - * Switch lower vgc bound to current BBP R17 value, - * lower the value a bit for better quality. - */ - rt2500usb_bbp_read(rt2x00dev, 17, &bbp); - bbp -= 6; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_VGC, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCUPPER, 0x40); - rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); - EEPROM(rt2x00dev, "BBPtune vgc: 0x%04x\n", word); - } else { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_VGCLOWER, bbp); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_VGC, word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R17, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_LOW, 0x48); - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R17_HIGH, 0x41); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R17, word); - EEPROM(rt2x00dev, "BBPtune r17: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R24, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_LOW, 0x40); - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R24_HIGH, 0x80); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R24, word); - EEPROM(rt2x00dev, "BBPtune r24: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R25, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_LOW, 0x40); - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R25_HIGH, 0x50); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R25, word); - EEPROM(rt2x00dev, "BBPtune r25: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBPTUNE_R61, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_LOW, 0x60); - rt2x00_set_field16(&word, EEPROM_BBPTUNE_R61_HIGH, 0x6d); - rt2x00_eeprom_write(rt2x00dev, EEPROM_BBPTUNE_R61, word); - EEPROM(rt2x00dev, "BBPtune r61: 0x%04x\n", word); - } - - return 0; -} - -static int rt2500usb_init_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u16 reg; - u16 value; - u16 eeprom; - - /* - * Read EEPROM word for configuration. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Identify RF chipset. - */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2500usb_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2570, value, reg); - - if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0) || - rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { - - ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); - return -ENODEV; - } - - if (!rt2x00_rf(&rt2x00dev->chip, RF2522) && - !rt2x00_rf(&rt2x00dev->chip, RF2523) && - !rt2x00_rf(&rt2x00dev->chip, RF2524) && - !rt2x00_rf(&rt2x00dev->chip, RF2525) && - !rt2x00_rf(&rt2x00dev->chip, RF2525E) && - !rt2x00_rf(&rt2x00dev->chip, RF5222)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); - return -ENODEV; - } - - /* - * Identify default antenna configuration. - */ - rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); - - /* - * When the eeprom indicates SW_DIVERSITY use HW_DIVERSITY instead. - * I am not 100% sure about this, but the legacy drivers do not - * indicate antenna swapping in software is required when - * diversity is enabled. - */ - if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) - rt2x00dev->default_ant.tx = ANTENNA_HW_DIVERSITY; - if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) - rt2x00dev->default_ant.rx = ANTENNA_HW_DIVERSITY; - - /* - * Store led mode, for correct led behaviour. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_LED_MODE); - - rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - if (value == LED_MODE_TXRX_ACTIVITY || - value == LED_MODE_DEFAULT || - value == LED_MODE_ASUS) - rt2500usb_init_led(rt2x00dev, &rt2x00dev->led_qual, - LED_TYPE_ACTIVITY); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - /* - * Detect if this device has an hardware controlled radio. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); - - /* - * Check if the BBP tuning should be disabled. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_DYN_BBP_TUNE)) - __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); - - /* - * Read the RSSI <-> dBm offset information. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_CALIBRATE_OFFSET, &eeprom); - rt2x00dev->rssi_offset = - rt2x00_get_field16(eeprom, EEPROM_CALIBRATE_OFFSET_RSSI); - - return 0; -} - -/* - * RF value list for RF2522 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2522[] = { - { 1, 0x00002050, 0x000c1fda, 0x00000101, 0 }, - { 2, 0x00002050, 0x000c1fee, 0x00000101, 0 }, - { 3, 0x00002050, 0x000c2002, 0x00000101, 0 }, - { 4, 0x00002050, 0x000c2016, 0x00000101, 0 }, - { 5, 0x00002050, 0x000c202a, 0x00000101, 0 }, - { 6, 0x00002050, 0x000c203e, 0x00000101, 0 }, - { 7, 0x00002050, 0x000c2052, 0x00000101, 0 }, - { 8, 0x00002050, 0x000c2066, 0x00000101, 0 }, - { 9, 0x00002050, 0x000c207a, 0x00000101, 0 }, - { 10, 0x00002050, 0x000c208e, 0x00000101, 0 }, - { 11, 0x00002050, 0x000c20a2, 0x00000101, 0 }, - { 12, 0x00002050, 0x000c20b6, 0x00000101, 0 }, - { 13, 0x00002050, 0x000c20ca, 0x00000101, 0 }, - { 14, 0x00002050, 0x000c20fa, 0x00000101, 0 }, -}; - -/* - * RF value list for RF2523 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2523[] = { - { 1, 0x00022010, 0x00000c9e, 0x000e0111, 0x00000a1b }, - { 2, 0x00022010, 0x00000ca2, 0x000e0111, 0x00000a1b }, - { 3, 0x00022010, 0x00000ca6, 0x000e0111, 0x00000a1b }, - { 4, 0x00022010, 0x00000caa, 0x000e0111, 0x00000a1b }, - { 5, 0x00022010, 0x00000cae, 0x000e0111, 0x00000a1b }, - { 6, 0x00022010, 0x00000cb2, 0x000e0111, 0x00000a1b }, - { 7, 0x00022010, 0x00000cb6, 0x000e0111, 0x00000a1b }, - { 8, 0x00022010, 0x00000cba, 0x000e0111, 0x00000a1b }, - { 9, 0x00022010, 0x00000cbe, 0x000e0111, 0x00000a1b }, - { 10, 0x00022010, 0x00000d02, 0x000e0111, 0x00000a1b }, - { 11, 0x00022010, 0x00000d06, 0x000e0111, 0x00000a1b }, - { 12, 0x00022010, 0x00000d0a, 0x000e0111, 0x00000a1b }, - { 13, 0x00022010, 0x00000d0e, 0x000e0111, 0x00000a1b }, - { 14, 0x00022010, 0x00000d1a, 0x000e0111, 0x00000a03 }, -}; - -/* - * RF value list for RF2524 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2524[] = { - { 1, 0x00032020, 0x00000c9e, 0x00000101, 0x00000a1b }, - { 2, 0x00032020, 0x00000ca2, 0x00000101, 0x00000a1b }, - { 3, 0x00032020, 0x00000ca6, 0x00000101, 0x00000a1b }, - { 4, 0x00032020, 0x00000caa, 0x00000101, 0x00000a1b }, - { 5, 0x00032020, 0x00000cae, 0x00000101, 0x00000a1b }, - { 6, 0x00032020, 0x00000cb2, 0x00000101, 0x00000a1b }, - { 7, 0x00032020, 0x00000cb6, 0x00000101, 0x00000a1b }, - { 8, 0x00032020, 0x00000cba, 0x00000101, 0x00000a1b }, - { 9, 0x00032020, 0x00000cbe, 0x00000101, 0x00000a1b }, - { 10, 0x00032020, 0x00000d02, 0x00000101, 0x00000a1b }, - { 11, 0x00032020, 0x00000d06, 0x00000101, 0x00000a1b }, - { 12, 0x00032020, 0x00000d0a, 0x00000101, 0x00000a1b }, - { 13, 0x00032020, 0x00000d0e, 0x00000101, 0x00000a1b }, - { 14, 0x00032020, 0x00000d1a, 0x00000101, 0x00000a03 }, -}; - -/* - * RF value list for RF2525 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2525[] = { - { 1, 0x00022020, 0x00080c9e, 0x00060111, 0x00000a1b }, - { 2, 0x00022020, 0x00080ca2, 0x00060111, 0x00000a1b }, - { 3, 0x00022020, 0x00080ca6, 0x00060111, 0x00000a1b }, - { 4, 0x00022020, 0x00080caa, 0x00060111, 0x00000a1b }, - { 5, 0x00022020, 0x00080cae, 0x00060111, 0x00000a1b }, - { 6, 0x00022020, 0x00080cb2, 0x00060111, 0x00000a1b }, - { 7, 0x00022020, 0x00080cb6, 0x00060111, 0x00000a1b }, - { 8, 0x00022020, 0x00080cba, 0x00060111, 0x00000a1b }, - { 9, 0x00022020, 0x00080cbe, 0x00060111, 0x00000a1b }, - { 10, 0x00022020, 0x00080d02, 0x00060111, 0x00000a1b }, - { 11, 0x00022020, 0x00080d06, 0x00060111, 0x00000a1b }, - { 12, 0x00022020, 0x00080d0a, 0x00060111, 0x00000a1b }, - { 13, 0x00022020, 0x00080d0e, 0x00060111, 0x00000a1b }, - { 14, 0x00022020, 0x00080d1a, 0x00060111, 0x00000a03 }, -}; - -/* - * RF value list for RF2525e - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2525e[] = { - { 1, 0x00022010, 0x0000089a, 0x00060111, 0x00000e1b }, - { 2, 0x00022010, 0x0000089e, 0x00060111, 0x00000e07 }, - { 3, 0x00022010, 0x0000089e, 0x00060111, 0x00000e1b }, - { 4, 0x00022010, 0x000008a2, 0x00060111, 0x00000e07 }, - { 5, 0x00022010, 0x000008a2, 0x00060111, 0x00000e1b }, - { 6, 0x00022010, 0x000008a6, 0x00060111, 0x00000e07 }, - { 7, 0x00022010, 0x000008a6, 0x00060111, 0x00000e1b }, - { 8, 0x00022010, 0x000008aa, 0x00060111, 0x00000e07 }, - { 9, 0x00022010, 0x000008aa, 0x00060111, 0x00000e1b }, - { 10, 0x00022010, 0x000008ae, 0x00060111, 0x00000e07 }, - { 11, 0x00022010, 0x000008ae, 0x00060111, 0x00000e1b }, - { 12, 0x00022010, 0x000008b2, 0x00060111, 0x00000e07 }, - { 13, 0x00022010, 0x000008b2, 0x00060111, 0x00000e1b }, - { 14, 0x00022010, 0x000008b6, 0x00060111, 0x00000e23 }, -}; - -/* - * RF value list for RF5222 - * Supports: 2.4 GHz & 5.2 GHz - */ -static const struct rf_channel rf_vals_5222[] = { - { 1, 0x00022020, 0x00001136, 0x00000101, 0x00000a0b }, - { 2, 0x00022020, 0x0000113a, 0x00000101, 0x00000a0b }, - { 3, 0x00022020, 0x0000113e, 0x00000101, 0x00000a0b }, - { 4, 0x00022020, 0x00001182, 0x00000101, 0x00000a0b }, - { 5, 0x00022020, 0x00001186, 0x00000101, 0x00000a0b }, - { 6, 0x00022020, 0x0000118a, 0x00000101, 0x00000a0b }, - { 7, 0x00022020, 0x0000118e, 0x00000101, 0x00000a0b }, - { 8, 0x00022020, 0x00001192, 0x00000101, 0x00000a0b }, - { 9, 0x00022020, 0x00001196, 0x00000101, 0x00000a0b }, - { 10, 0x00022020, 0x0000119a, 0x00000101, 0x00000a0b }, - { 11, 0x00022020, 0x0000119e, 0x00000101, 0x00000a0b }, - { 12, 0x00022020, 0x000011a2, 0x00000101, 0x00000a0b }, - { 13, 0x00022020, 0x000011a6, 0x00000101, 0x00000a0b }, - { 14, 0x00022020, 0x000011ae, 0x00000101, 0x00000a1b }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x00022010, 0x00018896, 0x00000101, 0x00000a1f }, - { 40, 0x00022010, 0x0001889a, 0x00000101, 0x00000a1f }, - { 44, 0x00022010, 0x0001889e, 0x00000101, 0x00000a1f }, - { 48, 0x00022010, 0x000188a2, 0x00000101, 0x00000a1f }, - { 52, 0x00022010, 0x000188a6, 0x00000101, 0x00000a1f }, - { 66, 0x00022010, 0x000188aa, 0x00000101, 0x00000a1f }, - { 60, 0x00022010, 0x000188ae, 0x00000101, 0x00000a1f }, - { 64, 0x00022010, 0x000188b2, 0x00000101, 0x00000a1f }, - - /* 802.11 HyperLan 2 */ - { 100, 0x00022010, 0x00008802, 0x00000101, 0x00000a0f }, - { 104, 0x00022010, 0x00008806, 0x00000101, 0x00000a0f }, - { 108, 0x00022010, 0x0000880a, 0x00000101, 0x00000a0f }, - { 112, 0x00022010, 0x0000880e, 0x00000101, 0x00000a0f }, - { 116, 0x00022010, 0x00008812, 0x00000101, 0x00000a0f }, - { 120, 0x00022010, 0x00008816, 0x00000101, 0x00000a0f }, - { 124, 0x00022010, 0x0000881a, 0x00000101, 0x00000a0f }, - { 128, 0x00022010, 0x0000881e, 0x00000101, 0x00000a0f }, - { 132, 0x00022010, 0x00008822, 0x00000101, 0x00000a0f }, - { 136, 0x00022010, 0x00008826, 0x00000101, 0x00000a0f }, - - /* 802.11 UNII */ - { 140, 0x00022010, 0x0000882a, 0x00000101, 0x00000a0f }, - { 149, 0x00022020, 0x000090a6, 0x00000101, 0x00000a07 }, - { 153, 0x00022020, 0x000090ae, 0x00000101, 0x00000a07 }, - { 157, 0x00022020, 0x000090b6, 0x00000101, 0x00000a07 }, - { 161, 0x00022020, 0x000090be, 0x00000101, 0x00000a07 }, -}; - -static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - struct channel_info *info; - char *tx_power; - unsigned int i; - - /* - * Initialize all hw fields. - */ - rt2x00dev->hw->flags = - IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; - - rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; - - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); - SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, - EEPROM_MAC_ADDR_0)); - - /* - * Initialize hw_mode information. - */ - spec->supported_bands = SUPPORT_BAND_2GHZ; - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - - if (rt2x00_rf(&rt2x00dev->chip, RF2522)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2522); - spec->channels = rf_vals_bg_2522; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2523)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2523); - spec->channels = rf_vals_bg_2523; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2524)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2524); - spec->channels = rf_vals_bg_2524; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525); - spec->channels = rf_vals_bg_2525; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2525E)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2525e); - spec->channels = rf_vals_bg_2525e; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5222)) { - spec->supported_bands |= SUPPORT_BAND_5GHZ; - spec->num_channels = ARRAY_SIZE(rf_vals_5222); - spec->channels = rf_vals_5222; - } - - /* - * Create channel information array - */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - spec->channels_info = info; - - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - - if (spec->num_channels > 14) { - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = DEFAULT_TXPOWER; - } - - return 0; -} - -static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Allocate eeprom data. - */ - retval = rt2500usb_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt2500usb_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt2500usb_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device requires the atim queue - */ - __set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags); - if (!modparam_nohwcrypt) { - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags); - } - __set_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; -} - -static const struct ieee80211_ops rt2500usb_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2x00mac_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; - -static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = { - .probe_hw = rt2500usb_probe_hw, - .initialize = rt2x00usb_initialize, - .uninitialize = rt2x00usb_uninitialize, - .clear_entry = rt2x00usb_clear_entry, - .set_device_state = rt2500usb_set_device_state, - .rfkill_poll = rt2500usb_rfkill_poll, - .link_stats = rt2500usb_link_stats, - .reset_tuner = rt2500usb_reset_tuner, - .link_tuner = rt2500usb_link_tuner, - .write_tx_desc = rt2500usb_write_tx_desc, - .write_tx_data = rt2x00usb_write_tx_data, - .write_beacon = rt2500usb_write_beacon, - .get_tx_data_len = rt2500usb_get_tx_data_len, - .kick_tx_queue = rt2500usb_kick_tx_queue, - .kill_tx_queue = rt2x00usb_kill_tx_queue, - .fill_rxdone = rt2500usb_fill_rxdone, - .config_shared_key = rt2500usb_config_key, - .config_pairwise_key = rt2500usb_config_key, - .config_filter = rt2500usb_config_filter, - .config_intf = rt2500usb_config_intf, - .config_erp = rt2500usb_config_erp, - .config_ant = rt2500usb_config_ant, - .config = rt2500usb_config, -}; - -static const struct data_queue_desc rt2500usb_queue_rx = { - .entry_num = RX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt2500usb_queue_tx = { - .entry_num = TX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt2500usb_queue_bcn = { - .entry_num = BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb_bcn), -}; - -static const struct data_queue_desc rt2500usb_queue_atim = { - .entry_num = ATIM_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct rt2x00_ops rt2500usb_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 1, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt2500usb_queue_rx, - .tx = &rt2500usb_queue_tx, - .bcn = &rt2500usb_queue_bcn, - .atim = &rt2500usb_queue_atim, - .lib = &rt2500usb_rt2x00_ops, - .hw = &rt2500usb_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2500usb_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * rt2500usb module information. - */ -static struct usb_device_id rt2500usb_device_table[] = { - /* ASUS */ - { USB_DEVICE(0x0b05, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0b05, 0x1707), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Belkin */ - { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x050d, 0x7051), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Cisco Systems */ - { USB_DEVICE(0x13b1, 0x000d), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x13b1, 0x0011), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x13b1, 0x001a), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* CNet */ - { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c02), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* D-LINK */ - { USB_DEVICE(0x2001, 0x3c00), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Gigabyte */ - { USB_DEVICE(0x1044, 0x8001), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x1044, 0x8007), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Hercules */ - { USB_DEVICE(0x06f8, 0xe000), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Melco */ - { USB_DEVICE(0x0411, 0x005e), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x0066), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x0067), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x008b), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0411, 0x0097), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* MSI */ - { USB_DEVICE(0x0db0, 0x6861), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0db0, 0x6865), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x0db0, 0x6869), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Ralink */ - { USB_DEVICE(0x148f, 0x1706), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x148f, 0x2570), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt2500usb_ops) }, - { USB_DEVICE(0x148f, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Sagem */ - { USB_DEVICE(0x079b, 0x004b), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Siemens */ - { USB_DEVICE(0x0681, 0x3c06), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* SMC */ - { USB_DEVICE(0x0707, 0xee13), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Spairon */ - { USB_DEVICE(0x114b, 0x0110), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* SURECOM */ - { USB_DEVICE(0x0769, 0x11f3), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Trust */ - { USB_DEVICE(0x0eb0, 0x9020), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* VTech */ - { USB_DEVICE(0x0f88, 0x3012), USB_DEVICE_DATA(&rt2500usb_ops) }, - /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0260), USB_DEVICE_DATA(&rt2500usb_ops) }, - { 0, } -}; - -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Ralink RT2500 USB Wireless LAN driver."); -MODULE_SUPPORTED_DEVICE("Ralink RT2570 USB chipset based cards"); -MODULE_DEVICE_TABLE(usb, rt2500usb_device_table); -MODULE_LICENSE("GPL"); - -static struct usb_driver rt2500usb_driver = { - .name = KBUILD_MODNAME, - .id_table = rt2500usb_device_table, - .probe = rt2x00usb_probe, - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -}; - -static int __init rt2500usb_init(void) -{ - return usb_register(&rt2500usb_driver); -} - -static void __exit rt2500usb_exit(void) -{ - usb_deregister(&rt2500usb_driver); -} - -module_init(rt2500usb_init); -module_exit(rt2500usb_exit); diff --git a/drivers/net/wireless/rt2x00/rt2500usb.h b/drivers/net/wireless/rt2x00/rt2500usb.h deleted file mode 100644 index b01edca42583..000000000000 --- a/drivers/net/wireless/rt2x00/rt2500usb.h +++ /dev/null @@ -1,847 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2500usb - Abstract: Data structures and registers for the rt2500usb module. - Supported chipsets: RT2570. - */ - -#ifndef RT2500USB_H -#define RT2500USB_H - -/* - * RF chip defines. - */ -#define RF2522 0x0000 -#define RF2523 0x0001 -#define RF2524 0x0002 -#define RF2525 0x0003 -#define RF2525E 0x0005 -#define RF5222 0x0010 - -/* - * RT2570 version - */ -#define RT2570_VERSION_B 2 -#define RT2570_VERSION_C 3 -#define RT2570_VERSION_D 4 - -/* - * Signal information. - * Defaul offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 120 - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x0400 -#define CSR_REG_SIZE 0x0100 -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x006a -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0060 -#define RF_BASE 0x0004 -#define RF_SIZE 0x0010 - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 2 - -/* - * Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * MAC_CSR0: ASIC revision number. - */ -#define MAC_CSR0 0x0400 - -/* - * 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_SOFT_RESET FIELD16(0x00000001) -#define MAC_CSR1_BBP_RESET FIELD16(0x00000002) -#define MAC_CSR1_HOST_READY FIELD16(0x00000004) - -/* - * MAC_CSR2: STA MAC register 0. - */ -#define MAC_CSR2 0x0404 -#define MAC_CSR2_BYTE0 FIELD16(0x00ff) -#define MAC_CSR2_BYTE1 FIELD16(0xff00) - -/* - * MAC_CSR3: STA MAC register 1. - */ -#define MAC_CSR3 0x0406 -#define MAC_CSR3_BYTE2 FIELD16(0x00ff) -#define MAC_CSR3_BYTE3 FIELD16(0xff00) - -/* - * MAC_CSR4: STA MAC register 2. - */ -#define MAC_CSR4 0X0408 -#define MAC_CSR4_BYTE4 FIELD16(0x00ff) -#define MAC_CSR4_BYTE5 FIELD16(0xff00) - -/* - * MAC_CSR5: BSSID register 0. - */ -#define MAC_CSR5 0x040a -#define MAC_CSR5_BYTE0 FIELD16(0x00ff) -#define MAC_CSR5_BYTE1 FIELD16(0xff00) - -/* - * MAC_CSR6: BSSID register 1. - */ -#define MAC_CSR6 0x040c -#define MAC_CSR6_BYTE2 FIELD16(0x00ff) -#define MAC_CSR6_BYTE3 FIELD16(0xff00) - -/* - * MAC_CSR7: BSSID register 2. - */ -#define MAC_CSR7 0x040e -#define MAC_CSR7_BYTE4 FIELD16(0x00ff) -#define MAC_CSR7_BYTE5 FIELD16(0xff00) - -/* - * MAC_CSR8: Max frame length. - */ -#define MAC_CSR8 0x0410 -#define MAC_CSR8_MAX_FRAME_UNIT FIELD16(0x0fff) - -/* - * Misc MAC_CSR registers. - * MAC_CSR9: Timer control. - * MAC_CSR10: Slot time. - * MAC_CSR11: SIFS. - * MAC_CSR12: EIFS. - * MAC_CSR13: Power mode0. - * MAC_CSR14: Power mode1. - * MAC_CSR15: Power saving transition0 - * MAC_CSR16: Power saving transition1 - */ -#define MAC_CSR9 0x0412 -#define MAC_CSR10 0x0414 -#define MAC_CSR11 0x0416 -#define MAC_CSR12 0x0418 -#define MAC_CSR13 0x041a -#define MAC_CSR14 0x041c -#define MAC_CSR15 0x041e -#define MAC_CSR16 0x0420 - -/* - * MAC_CSR17: Manual power control / status register. - * Allowed state: 0 deep_sleep, 1: sleep, 2: standby, 3: awake. - * SET_STATE: Set state. Write 1 to trigger, self cleared. - * BBP_DESIRE_STATE: BBP desired state. - * RF_DESIRE_STATE: RF desired state. - * BBP_CURRENT_STATE: BBP current state. - * RF_CURRENT_STATE: RF current state. - * PUT_TO_SLEEP: Put to sleep. Write 1 to trigger, self cleared. - */ -#define MAC_CSR17 0x0422 -#define MAC_CSR17_SET_STATE FIELD16(0x0001) -#define MAC_CSR17_BBP_DESIRE_STATE FIELD16(0x0006) -#define MAC_CSR17_RF_DESIRE_STATE FIELD16(0x0018) -#define MAC_CSR17_BBP_CURR_STATE FIELD16(0x0060) -#define MAC_CSR17_RF_CURR_STATE FIELD16(0x0180) -#define MAC_CSR17_PUT_TO_SLEEP FIELD16(0x0200) - -/* - * MAC_CSR18: Wakeup timer register. - * DELAY_AFTER_BEACON: Delay after Tbcn expired in units of 1/16 TU. - * BEACONS_BEFORE_WAKEUP: Number of beacon before wakeup. - * AUTO_WAKE: Enable auto wakeup / sleep mechanism. - */ -#define MAC_CSR18 0x0424 -#define MAC_CSR18_DELAY_AFTER_BEACON FIELD16(0x00ff) -#define MAC_CSR18_BEACONS_BEFORE_WAKEUP FIELD16(0x7f00) -#define MAC_CSR18_AUTO_WAKE FIELD16(0x8000) - -/* - * MAC_CSR19: GPIO control register. - */ -#define MAC_CSR19 0x0426 -#define MAC_CSR19_BIT0 FIELD32(0x0001) -#define MAC_CSR19_BIT1 FIELD32(0x0002) -#define MAC_CSR19_BIT2 FIELD32(0x0004) -#define MAC_CSR19_BIT3 FIELD32(0x0008) -#define MAC_CSR19_BIT4 FIELD32(0x0010) -#define MAC_CSR19_BIT5 FIELD32(0x0020) -#define MAC_CSR19_BIT6 FIELD32(0x0040) -#define MAC_CSR19_BIT7 FIELD32(0x0080) - -/* - * MAC_CSR20: LED control register. - * ACTIVITY: 0: idle, 1: active. - * LINK: 0: linkoff, 1: linkup. - * ACTIVITY_POLARITY: 0: active low, 1: active high. - */ -#define MAC_CSR20 0x0428 -#define MAC_CSR20_ACTIVITY FIELD16(0x0001) -#define MAC_CSR20_LINK FIELD16(0x0002) -#define MAC_CSR20_ACTIVITY_POLARITY FIELD16(0x0004) - -/* - * MAC_CSR21: LED control register. - * ON_PERIOD: On period, default 70ms. - * OFF_PERIOD: Off period, default 30ms. - */ -#define MAC_CSR21 0x042a -#define MAC_CSR21_ON_PERIOD FIELD16(0x00ff) -#define MAC_CSR21_OFF_PERIOD FIELD16(0xff00) - -/* - * MAC_CSR22: Collision window control register. - */ -#define MAC_CSR22 0x042c - -/* - * Transmit related CSRs. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * TXRX_CSR0: Security control register. - */ -#define TXRX_CSR0 0x0440 -#define TXRX_CSR0_ALGORITHM FIELD16(0x0007) -#define TXRX_CSR0_IV_OFFSET FIELD16(0x01f8) -#define TXRX_CSR0_KEY_ID FIELD16(0x1e00) - -/* - * TXRX_CSR1: TX configuration. - * ACK_TIMEOUT: ACK Timeout in unit of 1-us. - * TSF_OFFSET: TSF offset in MAC header. - * AUTO_SEQUENCE: Let ASIC control frame sequence number. - */ -#define TXRX_CSR1 0x0442 -#define TXRX_CSR1_ACK_TIMEOUT FIELD16(0x00ff) -#define TXRX_CSR1_TSF_OFFSET FIELD16(0x7f00) -#define TXRX_CSR1_AUTO_SEQUENCE FIELD16(0x8000) - -/* - * TXRX_CSR2: RX control. - * DISABLE_RX: Disable rx engine. - * DROP_CRC: Drop crc error. - * DROP_PHYSICAL: Drop physical error. - * DROP_CONTROL: Drop control frame. - * DROP_NOT_TO_ME: Drop not to me unicast frame. - * DROP_TODS: Drop frame tods bit is true. - * DROP_VERSION_ERROR: Drop version error frame. - * DROP_MCAST: Drop multicast frames. - * DROP_BCAST: Drop broadcast frames. - */ -#define TXRX_CSR2 0x0444 -#define TXRX_CSR2_DISABLE_RX FIELD16(0x0001) -#define TXRX_CSR2_DROP_CRC FIELD16(0x0002) -#define TXRX_CSR2_DROP_PHYSICAL FIELD16(0x0004) -#define TXRX_CSR2_DROP_CONTROL FIELD16(0x0008) -#define TXRX_CSR2_DROP_NOT_TO_ME FIELD16(0x0010) -#define TXRX_CSR2_DROP_TODS FIELD16(0x0020) -#define TXRX_CSR2_DROP_VERSION_ERROR FIELD16(0x0040) -#define TXRX_CSR2_DROP_MULTICAST FIELD16(0x0200) -#define TXRX_CSR2_DROP_BROADCAST FIELD16(0x0400) - -/* - * RX BBP ID registers - * TXRX_CSR3: CCK RX BBP ID. - * TXRX_CSR4: OFDM RX BBP ID. - */ -#define TXRX_CSR3 0x0446 -#define TXRX_CSR4 0x0448 - -/* - * TXRX_CSR5: CCK TX BBP ID0. - */ -#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_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_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_CSR8: OFDM TX BBP ID1. - */ -#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. - */ -#define TXRX_CSR9 0x0452 - -/* - * TXRX_CSR10: Auto responder control. - */ -#define TXRX_CSR10 0x0454 -#define TXRX_CSR10_AUTORESPOND_PREAMBLE FIELD16(0x0004) - -/* - * TXRX_CSR11: Auto responder basic rate. - */ -#define TXRX_CSR11 0x0456 - -/* - * ACK/CTS time registers. - */ -#define TXRX_CSR12 0x0458 -#define TXRX_CSR13 0x045a -#define TXRX_CSR14 0x045c -#define TXRX_CSR15 0x045e -#define TXRX_CSR16 0x0460 -#define TXRX_CSR17 0x0462 - -/* - * TXRX_CSR18: Synchronization control register. - */ -#define TXRX_CSR18 0x0464 -#define TXRX_CSR18_OFFSET FIELD16(0x000f) -#define TXRX_CSR18_INTERVAL FIELD16(0xfff0) - -/* - * TXRX_CSR19: Synchronization control register. - * TSF_COUNT: Enable TSF auto counting. - * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode. - * TBCN: Enable Tbcn with reload value. - * BEACON_GEN: Enable beacon generator. - */ -#define TXRX_CSR19 0x0466 -#define TXRX_CSR19_TSF_COUNT FIELD16(0x0001) -#define TXRX_CSR19_TSF_SYNC FIELD16(0x0006) -#define TXRX_CSR19_TBCN FIELD16(0x0008) -#define TXRX_CSR19_BEACON_GEN FIELD16(0x0010) - -/* - * TXRX_CSR20: Tx BEACON offset time control register. - * OFFSET: In units of usec. - * BCN_EXPECT_WINDOW: Default: 2^CWmin - */ -#define TXRX_CSR20 0x0468 -#define TXRX_CSR20_OFFSET FIELD16(0x1fff) -#define TXRX_CSR20_BCN_EXPECT_WINDOW FIELD16(0xe000) - -/* - * TXRX_CSR21 - */ -#define TXRX_CSR21 0x046a - -/* - * Encryption related CSRs. - * - */ - -/* - * SEC_CSR0: Shared key 0, word 0 - * SEC_CSR1: Shared key 0, word 1 - * SEC_CSR2: Shared key 0, word 2 - * SEC_CSR3: Shared key 0, word 3 - * SEC_CSR4: Shared key 0, word 4 - * SEC_CSR5: Shared key 0, word 5 - * SEC_CSR6: Shared key 0, word 6 - * SEC_CSR7: Shared key 0, word 7 - */ -#define SEC_CSR0 0x0480 -#define SEC_CSR1 0x0482 -#define SEC_CSR2 0x0484 -#define SEC_CSR3 0x0486 -#define SEC_CSR4 0x0488 -#define SEC_CSR5 0x048a -#define SEC_CSR6 0x048c -#define SEC_CSR7 0x048e - -/* - * SEC_CSR8: Shared key 1, word 0 - * SEC_CSR9: Shared key 1, word 1 - * SEC_CSR10: Shared key 1, word 2 - * SEC_CSR11: Shared key 1, word 3 - * SEC_CSR12: Shared key 1, word 4 - * SEC_CSR13: Shared key 1, word 5 - * SEC_CSR14: Shared key 1, word 6 - * SEC_CSR15: Shared key 1, word 7 - */ -#define SEC_CSR8 0x0490 -#define SEC_CSR9 0x0492 -#define SEC_CSR10 0x0494 -#define SEC_CSR11 0x0496 -#define SEC_CSR12 0x0498 -#define SEC_CSR13 0x049a -#define SEC_CSR14 0x049c -#define SEC_CSR15 0x049e - -/* - * SEC_CSR16: Shared key 2, word 0 - * SEC_CSR17: Shared key 2, word 1 - * SEC_CSR18: Shared key 2, word 2 - * SEC_CSR19: Shared key 2, word 3 - * SEC_CSR20: Shared key 2, word 4 - * SEC_CSR21: Shared key 2, word 5 - * SEC_CSR22: Shared key 2, word 6 - * SEC_CSR23: Shared key 2, word 7 - */ -#define SEC_CSR16 0x04a0 -#define SEC_CSR17 0x04a2 -#define SEC_CSR18 0X04A4 -#define SEC_CSR19 0x04a6 -#define SEC_CSR20 0x04a8 -#define SEC_CSR21 0x04aa -#define SEC_CSR22 0x04ac -#define SEC_CSR23 0x04ae - -/* - * SEC_CSR24: Shared key 3, word 0 - * SEC_CSR25: Shared key 3, word 1 - * SEC_CSR26: Shared key 3, word 2 - * SEC_CSR27: Shared key 3, word 3 - * SEC_CSR28: Shared key 3, word 4 - * SEC_CSR29: Shared key 3, word 5 - * SEC_CSR30: Shared key 3, word 6 - * SEC_CSR31: Shared key 3, word 7 - */ -#define SEC_CSR24 0x04b0 -#define SEC_CSR25 0x04b2 -#define SEC_CSR26 0x04b4 -#define SEC_CSR27 0x04b6 -#define SEC_CSR28 0x04b8 -#define SEC_CSR29 0x04ba -#define SEC_CSR30 0x04bc -#define SEC_CSR31 0x04be - -#define KEY_ENTRY(__idx) \ - ( SEC_CSR0 + ((__idx) * 16) ) - -/* - * PHY control registers. - */ - -/* - * PHY_CSR0: RF switching timing control. - */ -#define PHY_CSR0 0x04c0 - -/* - * PHY_CSR1: TX PA configuration. - */ -#define PHY_CSR1 0x04c2 - -/* - * MAC configuration registers. - */ - -/* - * PHY_CSR2: TX MAC configuration. - * NOTE: Both register fields are complete dummy, - * documentation and legacy drivers are unclear un - * what this register means or what fields exists. - */ -#define PHY_CSR2 0x04c4 -#define PHY_CSR2_LNA FIELD16(0x0002) -#define PHY_CSR2_LNA_MODE FIELD16(0x3000) - -/* - * PHY_CSR3: RX MAC configuration. - */ -#define PHY_CSR3 0x04c6 - -/* - * PHY_CSR4: Interface configuration. - */ -#define PHY_CSR4 0x04c8 -#define PHY_CSR4_LOW_RF_LE FIELD16(0x0001) - -/* - * BBP pre-TX registers. - * PHY_CSR5: BBP pre-TX CCK. - */ -#define PHY_CSR5 0x04ca -#define PHY_CSR5_CCK FIELD16(0x0003) -#define PHY_CSR5_CCK_FLIP FIELD16(0x0004) - -/* - * BBP pre-TX registers. - * PHY_CSR6: BBP pre-TX OFDM. - */ -#define PHY_CSR6 0x04cc -#define PHY_CSR6_OFDM FIELD16(0x0003) -#define PHY_CSR6_OFDM_FLIP FIELD16(0x0004) - -/* - * PHY_CSR7: BBP access register 0. - * BBP_DATA: BBP data. - * BBP_REG_ID: BBP register ID. - * BBP_READ_CONTROL: 0: write, 1: read. - */ -#define PHY_CSR7 0x04ce -#define PHY_CSR7_DATA FIELD16(0x00ff) -#define PHY_CSR7_REG_ID FIELD16(0x7f00) -#define PHY_CSR7_READ_CONTROL FIELD16(0x8000) - -/* - * PHY_CSR8: BBP access register 1. - * BBP_BUSY: ASIC is busy execute BBP programming. - */ -#define PHY_CSR8 0x04d0 -#define PHY_CSR8_BUSY FIELD16(0x0001) - -/* - * PHY_CSR9: RF access register. - * RF_VALUE: Register value + id to program into rf/if. - */ -#define PHY_CSR9 0x04d2 -#define PHY_CSR9_RF_VALUE FIELD16(0xffff) - -/* - * PHY_CSR10: RF access register. - * RF_VALUE: Register value + id to program into rf/if. - * RF_NUMBER_OF_BITS: Number of bits used in value (i:20, rfmd:22). - * RF_IF_SELECT: Chip to program: 0: rf, 1: if. - * RF_PLL_LD: Rf pll_ld status. - * RF_BUSY: 1: asic is busy execute rf programming. - */ -#define PHY_CSR10 0x04d4 -#define PHY_CSR10_RF_VALUE FIELD16(0x00ff) -#define PHY_CSR10_RF_NUMBER_OF_BITS FIELD16(0x1f00) -#define PHY_CSR10_RF_IF_SELECT FIELD16(0x2000) -#define PHY_CSR10_RF_PLL_LD FIELD16(0x4000) -#define PHY_CSR10_RF_BUSY FIELD16(0x8000) - -/* - * STA_CSR0: FCS error count. - * FCS_ERROR: FCS error count, cleared when read. - */ -#define STA_CSR0 0x04e0 -#define STA_CSR0_FCS_ERROR FIELD16(0xffff) - -/* - * STA_CSR1: PLCP error count. - */ -#define STA_CSR1 0x04e2 - -/* - * STA_CSR2: LONG error count. - */ -#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_FALSE_CCA_ERROR FIELD16(0xffff) - -/* - * STA_CSR4: RX FIFO overflow. - */ -#define STA_CSR4 0x04e8 - -/* - * STA_CSR5: Beacon sent counter. - */ -#define STA_CSR5 0x04ea - -/* - * Statistics registers - */ -#define STA_CSR6 0x04ec -#define STA_CSR7 0x04ee -#define STA_CSR8 0x04f0 -#define STA_CSR9 0x04f2 -#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 1 - */ -#define RF1_TUNER FIELD32(0x00020000) - -/* - * RF 3 - */ -#define RF3_TUNER FIELD32(0x00000100) -#define RF3_TXPOWER FIELD32(0x00003e00) - -/* - * EEPROM contents. - */ - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM antenna. - * ANTENNA_NUM: Number of antenna's. - * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * LED_MODE: 0: default, 1: TX/RX activity, 2: Single (ignore link), 3: rsvd. - * DYN_TXAGC: Dynamic TX AGC control. - * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0. - * RF_TYPE: Rf_type of this adapter. - */ -#define EEPROM_ANTENNA 0x000b -#define EEPROM_ANTENNA_NUM FIELD16(0x0003) -#define EEPROM_ANTENNA_TX_DEFAULT FIELD16(0x000c) -#define EEPROM_ANTENNA_RX_DEFAULT FIELD16(0x0030) -#define EEPROM_ANTENNA_LED_MODE FIELD16(0x01c0) -#define EEPROM_ANTENNA_DYN_TXAGC FIELD16(0x0200) -#define EEPROM_ANTENNA_HARDWARE_RADIO FIELD16(0x0400) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0xf800) - -/* - * EEPROM NIC config. - * CARDBUS_ACCEL: 0: enable, 1: disable. - * DYN_BBP_TUNE: 0: enable, 1: disable. - * CCK_TX_POWER: CCK TX power compensation. - */ -#define EEPROM_NIC 0x000c -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0001) -#define EEPROM_NIC_DYN_BBP_TUNE FIELD16(0x0002) -#define EEPROM_NIC_CCK_TX_POWER FIELD16(0x000c) - -/* - * EEPROM geography. - * GEO: Default geography setting for device. - */ -#define EEPROM_GEOGRAPHY 0x000d -#define EEPROM_GEOGRAPHY_GEO FIELD16(0x0f00) - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x000e -#define EEPROM_BBP_SIZE 16 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * EEPROM TXPOWER - */ -#define EEPROM_TXPOWER_START 0x001e -#define EEPROM_TXPOWER_SIZE 7 -#define EEPROM_TXPOWER_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_2 FIELD16(0xff00) - -/* - * EEPROM Tuning threshold - */ -#define EEPROM_BBPTUNE 0x0030 -#define EEPROM_BBPTUNE_THRESHOLD FIELD16(0x00ff) - -/* - * EEPROM BBP R24 Tuning. - */ -#define EEPROM_BBPTUNE_R24 0x0031 -#define EEPROM_BBPTUNE_R24_LOW FIELD16(0x00ff) -#define EEPROM_BBPTUNE_R24_HIGH FIELD16(0xff00) - -/* - * EEPROM BBP R25 Tuning. - */ -#define EEPROM_BBPTUNE_R25 0x0032 -#define EEPROM_BBPTUNE_R25_LOW FIELD16(0x00ff) -#define EEPROM_BBPTUNE_R25_HIGH FIELD16(0xff00) - -/* - * EEPROM BBP R24 Tuning. - */ -#define EEPROM_BBPTUNE_R61 0x0033 -#define EEPROM_BBPTUNE_R61_LOW FIELD16(0x00ff) -#define EEPROM_BBPTUNE_R61_HIGH FIELD16(0xff00) - -/* - * EEPROM BBP VGC Tuning. - */ -#define EEPROM_BBPTUNE_VGC 0x0034 -#define EEPROM_BBPTUNE_VGCUPPER FIELD16(0x00ff) -#define EEPROM_BBPTUNE_VGCLOWER FIELD16(0xff00) - -/* - * EEPROM BBP R17 Tuning. - */ -#define EEPROM_BBPTUNE_R17 0x0035 -#define EEPROM_BBPTUNE_R17_LOW FIELD16(0x00ff) -#define EEPROM_BBPTUNE_R17_HIGH FIELD16(0xff00) - -/* - * RSSI <-> dBm offset calibration - */ -#define EEPROM_CALIBRATE_OFFSET 0x0036 -#define EEPROM_CALIBRATE_OFFSET_RSSI FIELD16(0x00ff) - -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE ( 5 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 4 * sizeof(__le32) ) - -/* - * TX descriptor format for TX, PRIO, ATIM and Beacon Ring. - */ - -/* - * Word0 - */ -#define TXD_W0_PACKET_ID FIELD32(0x0000000f) -#define TXD_W0_RETRY_LIMIT FIELD32(0x000000f0) -#define TXD_W0_MORE_FRAG FIELD32(0x00000100) -#define TXD_W0_ACK FIELD32(0x00000200) -#define TXD_W0_TIMESTAMP FIELD32(0x00000400) -#define TXD_W0_OFDM FIELD32(0x00000800) -#define TXD_W0_NEW_SEQ FIELD32(0x00001000) -#define TXD_W0_IFS FIELD32(0x00006000) -#define TXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define TXD_W0_CIPHER FIELD32(0x20000000) -#define TXD_W0_KEY_ID FIELD32(0xc0000000) - -/* - * Word1 - */ -#define TXD_W1_IV_OFFSET FIELD32(0x0000003f) -#define TXD_W1_AIFS FIELD32(0x000000c0) -#define TXD_W1_CWMIN FIELD32(0x00000f00) -#define TXD_W1_CWMAX FIELD32(0x0000f000) - -/* - * Word2: PLCP information - */ -#define TXD_W2_PLCP_SIGNAL FIELD32(0x000000ff) -#define TXD_W2_PLCP_SERVICE FIELD32(0x0000ff00) -#define TXD_W2_PLCP_LENGTH_LOW FIELD32(0x00ff0000) -#define TXD_W2_PLCP_LENGTH_HIGH FIELD32(0xff000000) - -/* - * Word3 - */ -#define TXD_W3_IV FIELD32(0xffffffff) - -/* - * Word4 - */ -#define TXD_W4_EIV FIELD32(0xffffffff) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - */ -#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000002) -#define RXD_W0_MULTICAST FIELD32(0x00000004) -#define RXD_W0_BROADCAST FIELD32(0x00000008) -#define RXD_W0_MY_BSS FIELD32(0x00000010) -#define RXD_W0_CRC_ERROR FIELD32(0x00000020) -#define RXD_W0_OFDM FIELD32(0x00000040) -#define RXD_W0_PHYSICAL_ERROR FIELD32(0x00000080) -#define RXD_W0_CIPHER FIELD32(0x00000100) -#define RXD_W0_CIPHER_ERROR FIELD32(0x00000200) -#define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) - -/* - * Word1 - */ -#define RXD_W1_RSSI FIELD32(0x000000ff) -#define RXD_W1_SIGNAL FIELD32(0x0000ff00) - -/* - * Word2 - */ -#define RXD_W2_IV FIELD32(0xffffffff) - -/* - * Word3 - */ -#define RXD_W3_EIV FIELD32(0xffffffff) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - */ -#define MIN_TXPOWER 0 -#define MAX_TXPOWER 31 -#define DEFAULT_TXPOWER 24 - -#define TXPOWER_FROM_DEV(__txpower) \ - (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) - -#endif /* RT2500USB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c deleted file mode 100644 index 9fe770f7d7bb..000000000000 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ /dev/null @@ -1,3077 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the - Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - Module: rt2800usb - Abstract: rt2800usb device specific routines. - Supported chipsets: RT2800U. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00usb.h" -#include "rt2800usb.h" - -/* - * Allow hardware encryption to be disabled. - */ -static int modparam_nohwcrypt = 1; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -/* - * Register access. - * All access to the CSR registers will go through the methods - * rt2x00usb_register_read and rt2x00usb_register_write. - * BBP and RF register require indirect register access, - * and use the CSR registers BBPCSR and RFCSR to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - * The _lock versions must be used if you already hold the csr_mutex - */ -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2x00usb_regbusy_read((__dev), BBP_CSR_CFG, BBP_CSR_CFG_BUSY, (__reg)) -#define WAIT_FOR_RFCSR(__dev, __reg) \ - rt2x00usb_regbusy_read((__dev), RF_CSR_CFG, RF_CSR_CFG_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2x00usb_regbusy_read((__dev), RF_CSR_CFG0, RF_CSR_CFG0_BUSY, (__reg)) -#define WAIT_FOR_MCU(__dev, __reg) \ - rt2x00usb_regbusy_read((__dev), H2M_MAILBOX_CSR, \ - H2M_MAILBOX_CSR_OWNER, (__reg)) - -static void rt2800usb_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBP_CSR_CFG_VALUE, value); - rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); - rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 0); - - rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800usb_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, BBP_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, BBP_CSR_CFG_BUSY, 1); - rt2x00_set_field32(®, BBP_CSR_CFG_READ_CONTROL, 1); - - rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); - - WAIT_FOR_BBP(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, BBP_CSR_CFG_VALUE); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800usb_rfcsr_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RFCSR becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RF_CSR_CFG_DATA, value); - rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 1); - rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); - - rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800usb_rfcsr_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RFCSR becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_RFCSR(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RF_CSR_CFG_REGNUM, word); - rt2x00_set_field32(®, RF_CSR_CFG_WRITE, 0); - rt2x00_set_field32(®, RF_CSR_CFG_BUSY, 1); - - rt2x00usb_register_write_lock(rt2x00dev, BBP_CSR_CFG, reg); - - WAIT_FOR_RFCSR(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, RF_CSR_CFG_DATA); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800usb_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, RF_CSR_CFG0_REG_VALUE_BW, value); - rt2x00_set_field32(®, RF_CSR_CFG0_STANDBYMODE, 0); - rt2x00_set_field32(®, RF_CSR_CFG0_SEL, 0); - rt2x00_set_field32(®, RF_CSR_CFG0_BUSY, 1); - - rt2x00usb_register_write_lock(rt2x00dev, RF_CSR_CFG0, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt2800usb_mcu_request(struct rt2x00_dev *rt2x00dev, - const u8 command, const u8 token, - const u8 arg0, const u8 arg1) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the MCU becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_MCU(rt2x00dev, ®)) { - rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); - rt2x00usb_register_write_lock(rt2x00dev, H2M_MAILBOX_CSR, reg); - - reg = 0; - rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); - rt2x00usb_register_write_lock(rt2x00dev, HOST_CMD_CSR, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -static const struct rt2x00debug rt2800usb_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = rt2x00usb_register_read, - .write = rt2x00usb_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u32), - .word_count = CSR_REG_SIZE / sizeof(u32), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt2800usb_bbp_read, - .write = rt2800usb_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt2800usb_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -static int rt2800usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, ®); - return rt2x00_get_field32(reg, GPIO_CTRL_CFG_BIT2); -} - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt2800usb_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); - unsigned int polarity = - rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, - EEPROM_FREQ_LED_POLARITY); - unsigned int ledmode = - rt2x00_get_field16(led->rt2x00dev->led_mcu_reg, - EEPROM_FREQ_LED_MODE); - - if (led->type == LED_TYPE_RADIO) { - rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? 0x20 : 0); - } else if (led->type == LED_TYPE_ASSOC) { - rt2800usb_mcu_request(led->rt2x00dev, MCU_LED, 0xff, ledmode, - enabled ? (bg_mode ? 0x60 : 0xa0) : 0x20); - } else if (led->type == LED_TYPE_QUALITY) { - /* - * The brightness is divided into 6 levels (0 - 5), - * The specs tell us the following levels: - * 0, 1 ,3, 7, 15, 31 - * to determine the level in a simple way we can simply - * work with bitshifting: - * (1 << level) - 1 - */ - rt2800usb_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, - (1 << brightness / (LED_FULL / 6)) - 1, - polarity); - } -} - -static int rt2800usb_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u32 reg; - - rt2x00usb_register_read(led->rt2x00dev, LED_CFG, ®); - rt2x00_set_field32(®, LED_CFG_ON_PERIOD, *delay_on); - rt2x00_set_field32(®, LED_CFG_OFF_PERIOD, *delay_off); - rt2x00_set_field32(®, LED_CFG_SLOW_BLINK_PERIOD, 3); - rt2x00_set_field32(®, LED_CFG_R_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_G_LED_MODE, 12); - rt2x00_set_field32(®, LED_CFG_Y_LED_MODE, 3); - rt2x00_set_field32(®, LED_CFG_LED_POLAR, 1); - rt2x00usb_register_write(led->rt2x00dev, LED_CFG, reg); - - return 0; -} - -static void rt2800usb_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt2800usb_brightness_set; - led->led_dev.blink_set = rt2800usb_blink_set; - led->flags = LED_INITIALIZED; -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ -static void rt2800usb_config_wcid_attr(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct mac_wcid_entry wcid_entry; - struct mac_iveiv_entry iveiv_entry; - u32 offset; - u32 reg; - - offset = MAC_WCID_ATTR_ENTRY(key->hw_key_idx); - - rt2x00usb_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_KEYTAB, - !!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_CIPHER, - (crypto->cmd == SET_KEY) * crypto->cipher); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_BSS_IDX, - (crypto->cmd == SET_KEY) * crypto->bssidx); - rt2x00_set_field32(®, MAC_WCID_ATTRIBUTE_RX_WIUDF, crypto->cipher); - rt2x00usb_register_write(rt2x00dev, offset, reg); - - offset = MAC_IVEIV_ENTRY(key->hw_key_idx); - - memset(&iveiv_entry, 0, sizeof(iveiv_entry)); - if ((crypto->cipher == CIPHER_TKIP) || - (crypto->cipher == CIPHER_TKIP_NO_MIC) || - (crypto->cipher == CIPHER_AES)) - iveiv_entry.iv[3] |= 0x20; - iveiv_entry.iv[3] |= key->keyidx << 6; - rt2x00usb_register_multiwrite(rt2x00dev, offset, - &iveiv_entry, sizeof(iveiv_entry)); - - offset = MAC_WCID_ENTRY(key->hw_key_idx); - - memset(&wcid_entry, 0, sizeof(wcid_entry)); - if (crypto->cmd == SET_KEY) - memcpy(&wcid_entry, crypto->address, ETH_ALEN); - rt2x00usb_register_multiwrite(rt2x00dev, offset, - &wcid_entry, sizeof(wcid_entry)); -} - -static int rt2800usb_config_shared_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_key_entry key_entry; - struct rt2x00_field32 field; - int timeout; - u32 offset; - u32 reg; - - if (crypto->cmd == SET_KEY) { - key->hw_key_idx = (4 * crypto->bssidx) + key->keyidx; - - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - offset = SHARED_KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - offset, &key_entry, - sizeof(key_entry), - timeout); - } - - /* - * The cipher types are stored over multiple registers - * starting with SHARED_KEY_MODE_BASE each word will have - * 32 bits and contains the cipher types for 2 bssidx each. - * Using the correct defines correctly will cause overhead, - * so just calculate the correct offset. - */ - field.bit_offset = 4 * (key->hw_key_idx % 8); - field.bit_mask = 0x7 << field.bit_offset; - - offset = SHARED_KEY_MODE_ENTRY(key->hw_key_idx / 8); - - rt2x00usb_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, field, - (crypto->cmd == SET_KEY) * crypto->cipher); - rt2x00usb_register_write(rt2x00dev, offset, reg); - - /* - * Update WCID information - */ - rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); - - return 0; -} - -static int rt2800usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_key_entry key_entry; - int timeout; - u32 offset; - - if (crypto->cmd == SET_KEY) { - /* - * 1 pairwise key is possible per AID, this means that the AID - * equals our hw_key_idx. Make sure the WCID starts _after_ the - * last possible shared key entry. - */ - if (crypto->aid > (256 - 32)) - return -ENOSPC; - - key->hw_key_idx = 32 + crypto->aid; - - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - offset = PAIRWISE_KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - offset, &key_entry, - sizeof(key_entry), - timeout); - } - - /* - * Update WCID information - */ - rt2800usb_config_wcid_attr(rt2x00dev, crypto, key); - - return 0; -} - -static void rt2800usb_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u32 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00usb_register_read(rt2x00dev, RX_FILTER_CFG, ®); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CRC_ERROR, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PHY_ERROR, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_NOT_MY_BSSD, 0); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_VER_ERROR, 1); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_MULTICAST, - !(filter_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BROADCAST, 0); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_DUPLICATE, 1); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END_ACK, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CF_END, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_ACK, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CTS, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_RTS, - !(filter_flags & FIF_CONTROL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_PSPOLL, - !(filter_flags & FIF_PSPOLL)); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BA, 1); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_BAR, 0); - rt2x00_set_field32(®, RX_FILTER_CFG_DROP_CNTL, - !(filter_flags & FIF_CONTROL)); - rt2x00usb_register_write(rt2x00dev, RX_FILTER_CFG, reg); -} - -static void rt2800usb_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags) -{ - unsigned int beacon_base; - u32 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2x00usb_register_write(rt2x00dev, beacon_base, 0); - - /* - * Enable synchronisation. - */ - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, conf->sync); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); - } - - if (flags & CONFIG_UPDATE_MAC) { - reg = le32_to_cpu(conf->mac[1]); - rt2x00_set_field32(®, MAC_ADDR_DW1_UNICAST_TO_ME_MASK, 0xff); - conf->mac[1] = cpu_to_le32(reg); - - rt2x00usb_register_multiwrite(rt2x00dev, MAC_ADDR_DW0, - conf->mac, sizeof(conf->mac)); - } - - if (flags & CONFIG_UPDATE_BSSID) { - reg = le32_to_cpu(conf->bssid[1]); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_ID_MASK, 0); - rt2x00_set_field32(®, MAC_BSSID_DW1_BSS_BCN_NUM, 0); - conf->bssid[1] = cpu_to_le32(reg); - - rt2x00usb_register_multiwrite(rt2x00dev, MAC_BSSID_DW0, - conf->bssid, sizeof(conf->bssid)); - } -} - -static void rt2800usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_RX_ACK_TIMEOUT, 0x20); - rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); - rt2x00_set_field32(®, AUTO_RSP_CFG_BAC_ACK_POLICY, - !!erp->short_preamble); - rt2x00_set_field32(®, AUTO_RSP_CFG_AR_PREAMBLE, - !!erp->short_preamble); - rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, - erp->cts_protection ? 2 : 0); - rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); - - rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, - erp->basic_rates); - rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); - - rt2x00usb_register_read(rt2x00dev, BKOFF_SLOT_CFG, ®); - rt2x00_set_field32(®, BKOFF_SLOT_CFG_SLOT_TIME, erp->slot_time); - rt2x00_set_field32(®, BKOFF_SLOT_CFG_CC_DELAY_TIME, 2); - rt2x00usb_register_write(rt2x00dev, BKOFF_SLOT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, XIFS_TIME_CFG, ®); - rt2x00_set_field32(®, XIFS_TIME_CFG_CCKM_SIFS_TIME, erp->sifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_SIFS_TIME, erp->sifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_OFDM_XIFS_TIME, 4); - rt2x00_set_field32(®, XIFS_TIME_CFG_EIFS, erp->eifs); - rt2x00_set_field32(®, XIFS_TIME_CFG_BB_RXEND_ENABLE, 1); - rt2x00usb_register_write(rt2x00dev, XIFS_TIME_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); -} - -static void rt2800usb_config_ant(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r1; - u8 r3; - - rt2800usb_bbp_read(rt2x00dev, 1, &r1); - rt2800usb_bbp_read(rt2x00dev, 3, &r3); - - /* - * Configure the TX antenna. - */ - switch ((int)ant->tx) { - case 1: - rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0); - break; - case 2: - rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 2); - break; - case 3: - /* Do nothing */ - break; - } - - /* - * Configure the RX antenna. - */ - switch ((int)ant->rx) { - case 1: - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0); - break; - case 2: - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 1); - break; - case 3: - rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 2); - break; - } - - rt2800usb_bbp_write(rt2x00dev, 3, r3); - rt2800usb_bbp_write(rt2x00dev, 1, r1); -} - -static void rt2800usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u16 eeprom; - short lna_gain; - - if (libconf->rf.channel <= 14) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_BG); - } else if (libconf->rf.channel <= 64) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_LNA_A0); - } else if (libconf->rf.channel <= 128) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_BG2_LNA_A1); - } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &eeprom); - lna_gain = rt2x00_get_field16(eeprom, EEPROM_RSSI_A2_LNA_A2); - } - - rt2x00dev->lna_gain = lna_gain; -} - -static void rt2800usb_config_channel_rt2x(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) -{ - rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - - if (rt2x00dev->default_ant.tx == 1) - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1); - - if (rt2x00dev->default_ant.rx == 1) { - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX1, 1); - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); - } else if (rt2x00dev->default_ant.rx == 2) - rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1); - - if (rf->channel > 14) { - /* - * When TX power is below 0, we should increase it by 7 to - * make it a positive value (Minumum value is -7). - * However this means that values between 0 and 7 have - * double meaning, and we should set a 7DBm boost flag. - */ - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, - (info->tx_power1 >= 0)); - - if (info->tx_power1 < 0) - info->tx_power1 += 7; - - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power1)); - - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, - (info->tx_power2 >= 0)); - - if (info->tx_power2 < 0) - info->tx_power2 += 7; - - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, - TXPOWER_A_TO_DEV(info->tx_power2)); - } else { - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power1)); - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, - TXPOWER_G_TO_DEV(info->tx_power2)); - } - - rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); - - rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); - rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); - rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(200); - - rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); - rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); - rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); - rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(200); - - rt2800usb_rf_write(rt2x00dev, 1, rf->rf1); - rt2800usb_rf_write(rt2x00dev, 2, rf->rf2); - rt2800usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt2800usb_rf_write(rt2x00dev, 4, rf->rf4); -} - -static void rt2800usb_config_channel_rt3x(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) -{ - u8 rfcsr; - - rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf1); - rt2800usb_rfcsr_write(rt2x00dev, 2, rf->rf3); - - rt2800usb_rfcsr_read(rt2x00dev, 6, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR6_R, rf->rf2); - rt2800usb_rfcsr_write(rt2x00dev, 6, rfcsr); - - rt2800usb_rfcsr_read(rt2x00dev, 12, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, - TXPOWER_G_TO_DEV(info->tx_power1)); - rt2800usb_rfcsr_write(rt2x00dev, 12, rfcsr); - - rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR23_FREQ_OFFSET, rt2x00dev->freq_offset); - rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); - - rt2800usb_rfcsr_write(rt2x00dev, 24, - rt2x00dev->calibration[conf_is_ht40(conf)]); - - rt2800usb_rfcsr_read(rt2x00dev, 23, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR7_RF_TUNING, 1); - rt2800usb_rfcsr_write(rt2x00dev, 23, rfcsr); -} - -static void rt2800usb_config_channel(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - struct rf_channel *rf, - struct channel_info *info) -{ - u32 reg; - unsigned int tx_pin; - u8 bbp; - - if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) - rt2800usb_config_channel_rt2x(rt2x00dev, conf, rf, info); - else - rt2800usb_config_channel_rt3x(rt2x00dev, conf, rf, info); - - /* - * Change BBP settings - */ - rt2800usb_bbp_write(rt2x00dev, 62, 0x37 - rt2x00dev->lna_gain); - rt2800usb_bbp_write(rt2x00dev, 63, 0x37 - rt2x00dev->lna_gain); - rt2800usb_bbp_write(rt2x00dev, 64, 0x37 - rt2x00dev->lna_gain); - rt2800usb_bbp_write(rt2x00dev, 86, 0); - - if (rf->channel <= 14) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { - rt2800usb_bbp_write(rt2x00dev, 82, 0x62); - rt2800usb_bbp_write(rt2x00dev, 75, 0x46); - } else { - rt2800usb_bbp_write(rt2x00dev, 82, 0x84); - rt2800usb_bbp_write(rt2x00dev, 75, 0x50); - } - } else { - rt2800usb_bbp_write(rt2x00dev, 82, 0xf2); - - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) - rt2800usb_bbp_write(rt2x00dev, 75, 0x46); - else - rt2800usb_bbp_write(rt2x00dev, 75, 0x50); - } - - rt2x00usb_register_read(rt2x00dev, TX_BAND_CFG, ®); - rt2x00_set_field32(®, TX_BAND_CFG_HT40_PLUS, conf_is_ht40_plus(conf)); - rt2x00_set_field32(®, TX_BAND_CFG_A, rf->channel > 14); - rt2x00_set_field32(®, TX_BAND_CFG_BG, rf->channel <= 14); - rt2x00usb_register_write(rt2x00dev, TX_BAND_CFG, reg); - - tx_pin = 0; - - /* Turn on unused PA or LNA when not using 1T or 1R */ - if (rt2x00dev->default_ant.tx != 1) { - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A1_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G1_EN, 1); - } - - /* Turn on unused PA or LNA when not using 1T or 1R */ - if (rt2x00dev->default_ant.rx != 1) { - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A1_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G1_EN, 1); - } - - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_A0_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_LNA_PE_G0_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_RFTR_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_TRSW_EN, 1); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_G0_EN, rf->channel <= 14); - rt2x00_set_field32(&tx_pin, TX_PIN_CFG_PA_PE_A0_EN, rf->channel > 14); - - rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, tx_pin); - - rt2800usb_bbp_read(rt2x00dev, 4, &bbp); - rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * conf_is_ht40(conf)); - rt2800usb_bbp_write(rt2x00dev, 4, bbp); - - rt2800usb_bbp_read(rt2x00dev, 3, &bbp); - rt2x00_set_field8(&bbp, BBP3_HT40_PLUS, conf_is_ht40_plus(conf)); - rt2800usb_bbp_write(rt2x00dev, 3, bbp); - - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { - if (conf_is_ht40(conf)) { - rt2800usb_bbp_write(rt2x00dev, 69, 0x1a); - rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); - rt2800usb_bbp_write(rt2x00dev, 73, 0x16); - } else { - rt2800usb_bbp_write(rt2x00dev, 69, 0x16); - rt2800usb_bbp_write(rt2x00dev, 70, 0x08); - rt2800usb_bbp_write(rt2x00dev, 73, 0x11); - } - } - - msleep(1); -} - -static void rt2800usb_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - u32 reg; - u32 value = TXPOWER_G_TO_DEV(txpower); - u8 r1; - - rt2800usb_bbp_read(rt2x00dev, 1, &r1); - rt2x00_set_field8(®, BBP1_TX_POWER, 0); - rt2800usb_bbp_write(rt2x00dev, 1, r1); - - rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_0, ®); - rt2x00_set_field32(®, TX_PWR_CFG_0_1MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_2MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_55MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_11MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_6MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_9MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_12MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_0_18MBS, value); - rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_0, reg); - - rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_1, ®); - rt2x00_set_field32(®, TX_PWR_CFG_1_24MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_36MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_48MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_54MBS, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS0, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS1, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS2, value); - rt2x00_set_field32(®, TX_PWR_CFG_1_MCS3, value); - rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_1, reg); - - rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_2, ®); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS4, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS5, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS6, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS7, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS8, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS9, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS10, value); - rt2x00_set_field32(®, TX_PWR_CFG_2_MCS11, value); - rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_2, reg); - - rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_3, ®); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS12, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS13, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS14, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_MCS15, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN1, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN2, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN3, value); - rt2x00_set_field32(®, TX_PWR_CFG_3_UKNOWN4, value); - rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_3, reg); - - rt2x00usb_register_read(rt2x00dev, TX_PWR_CFG_4, ®); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN5, value); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN6, value); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN7, value); - rt2x00_set_field32(®, TX_PWR_CFG_4_UKNOWN8, value); - rt2x00usb_register_write(rt2x00dev, TX_PWR_CFG_4, reg); -} - -static void rt2800usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TX_RTY_CFG, ®); - rt2x00_set_field32(®, TX_RTY_CFG_SHORT_RTY_LIMIT, - libconf->conf->short_frame_max_tx_count); - rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_LIMIT, - libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, TX_RTY_CFG_LONG_RTY_THRE, 2000); - rt2x00_set_field32(®, TX_RTY_CFG_NON_AGG_RTY_MODE, 0); - rt2x00_set_field32(®, TX_RTY_CFG_AGG_RTY_MODE, 0); - rt2x00_set_field32(®, TX_RTY_CFG_TX_AUTO_FB_ENABLE, 1); - rt2x00usb_register_write(rt2x00dev, TX_RTY_CFG, reg); -} - -static void rt2800usb_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u32 reg; - - if (state == STATE_SLEEP) { - rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, 0); - - rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 5); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, - libconf->conf->listen_interval - 1); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 1); - rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - } else { - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - - rt2x00usb_register_read(rt2x00dev, AUTOWAKEUP_CFG, ®); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTO_LEAD_TIME, 0); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE, 0); - rt2x00_set_field32(®, AUTOWAKEUP_CFG_AUTOWAKE, 0); - rt2x00usb_register_write(rt2x00dev, AUTOWAKEUP_CFG, reg); - } -} - -static void rt2800usb_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - /* Always recalculate LNA gain before changing configuration */ - rt2800usb_config_lna_gain(rt2x00dev, libconf); - - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2800usb_config_channel(rt2x00dev, libconf->conf, - &libconf->rf, &libconf->channel); - if (flags & IEEE80211_CONF_CHANGE_POWER) - rt2800usb_config_txpower(rt2x00dev, libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt2800usb_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt2800usb_config_ps(rt2x00dev, libconf); -} - -/* - * Link tuning - */ -static void rt2800usb_link_stats(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u32 reg; - - /* - * Update FCS error count from register. - */ - rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); - qual->rx_failed = rt2x00_get_field32(reg, RX_STA_CNT0_CRC_ERR); -} - -static u8 rt2800usb_get_default_vgc(struct rt2x00_dev *rt2x00dev) -{ - if (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ) { - if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) - return 0x1c + (2 * rt2x00dev->lna_gain); - else - return 0x2e + rt2x00dev->lna_gain; - } - - if (!test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags)) - return 0x32 + (rt2x00dev->lna_gain * 5) / 3; - else - return 0x3a + (rt2x00dev->lna_gain * 5) / 3; -} - -static inline void rt2800usb_set_vgc(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, u8 vgc_level) -{ - if (qual->vgc_level != vgc_level) { - rt2800usb_bbp_write(rt2x00dev, 66, vgc_level); - qual->vgc_level = vgc_level; - qual->vgc_level_reg = vgc_level; - } -} - -static void rt2800usb_reset_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - rt2800usb_set_vgc(rt2x00dev, qual, - rt2800usb_get_default_vgc(rt2x00dev)); -} - -static void rt2800usb_link_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count) -{ - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) - return; - - /* - * When RSSI is better then -80 increase VGC level with 0x10 - */ - rt2800usb_set_vgc(rt2x00dev, qual, - rt2800usb_get_default_vgc(rt2x00dev) + - ((qual->rssi > -80) * 0x10)); -} - -/* - * Firmware functions - */ -static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) -{ - return FIRMWARE_RT2870; -} - -static bool rt2800usb_check_crc(const u8 *data, const size_t len) -{ - u16 fw_crc; - u16 crc; - - /* - * The last 2 bytes in the firmware array are the crc checksum itself, - * this means that we should never pass those 2 bytes to the crc - * algorithm. - */ - fw_crc = (data[len - 2] << 8 | data[len - 1]); - - /* - * Use the crc ccitt algorithm. - * This will return the same value as the legacy driver which - * used bit ordering reversion on the both the firmware bytes - * before input input as well as on the final output. - * Obviously using crc ccitt directly is much more efficient. - */ - crc = crc_ccitt(~0, data, len - 2); - - /* - * There is a small difference between the crc-itu-t + bitrev and - * the crc-ccitt crc calculation. In the latter method the 2 bytes - * will be swapped, use swab16 to convert the crc to the correct - * value. - */ - crc = swab16(crc); - - return fw_crc == crc; -} - -static int rt2800usb_check_firmware(struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len) -{ - u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; - size_t offset = 0; - - /* - * Firmware files: - * There are 2 variations of the rt2870 firmware. - * a) size: 4kb - * b) size: 8kb - * Note that (b) contains 2 seperate firmware blobs of 4k - * within the file. The first blob is the same firmware as (a), - * but the second blob is for the additional chipsets. - */ - if (len != 4096 && len != 8192) - return FW_BAD_LENGTH; - - /* - * Check if we need the upper 4kb firmware data or not. - */ - if ((len == 4096) && - (chipset != 0x2860) && - (chipset != 0x2872) && - (chipset != 0x3070)) - return FW_BAD_VERSION; - - /* - * 8kb firmware files must be checked as if it were - * 2 seperate firmware files. - */ - while (offset < len) { - if (!rt2800usb_check_crc(data + offset, 4096)) - return FW_BAD_CRC; - - offset += 4096; - } - - return FW_OK; -} - -static int rt2800usb_load_firmware(struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len) -{ - unsigned int i; - int status; - u32 reg; - u32 offset; - u32 length; - u16 chipset = (rt2x00_rev(&rt2x00dev->chip) >> 16) & 0xffff; - - /* - * Check which section of the firmware we need. - */ - if ((chipset == 0x2860) || - (chipset == 0x2872) || - (chipset == 0x3070)) { - offset = 0; - length = 4096; - } else { - offset = 4096; - length = 4096; - } - - /* - * Wait for stable hardware. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg && reg != ~0) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "Unstable hardware.\n"); - return -EBUSY; - } - - /* - * Write firmware to device. - */ - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - FIRMWARE_IMAGE_BASE, - data + offset, length, - REGISTER_TIMEOUT32(length)); - - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0); - - /* - * Send firmware request to device to load firmware, - * we need to specify a long timeout time. - */ - status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, - 0, USB_MODE_FIRMWARE, - REGISTER_TIMEOUT_FIRMWARE); - if (status < 0) { - ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); - return status; - } - - msleep(10); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - - /* - * Send signal to firmware during boot time. - */ - rt2800usb_mcu_request(rt2x00dev, MCU_BOOT_SIGNAL, 0xff, 0, 0); - - if ((chipset == 0x3070) || - (chipset == 0x3071) || - (chipset == 0x3572)) { - udelay(200); - rt2800usb_mcu_request(rt2x00dev, MCU_CURRENT, 0, 0, 0); - udelay(10); - } - - /* - * Wait for device to stabilize. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); - if (rt2x00_get_field32(reg, PBF_SYS_CTRL_READY)) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "PBF system register not ready.\n"); - return -EBUSY; - } - - /* - * Initialize firmware. - */ - rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - msleep(1); - - return 0; -} - -/* - * Initialization functions. - */ -static int rt2800usb_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - unsigned int i; - - /* - * Wait untill BBP and RF are ready. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg && reg != ~0) - break; - msleep(1); - } - - if (i == REGISTER_BUSY_COUNT) { - ERROR(rt2x00dev, "Unstable hardware.\n"); - return -EBUSY; - } - - rt2x00usb_register_read(rt2x00dev, PBF_SYS_CTRL, ®); - rt2x00usb_register_write(rt2x00dev, PBF_SYS_CTRL, reg & ~0x00002000); - - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_CSR, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_RESET_BBP, 1); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, 0x00000000); - - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, - USB_MODE_RESET, REGISTER_TIMEOUT); - - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); - - rt2x00usb_register_read(rt2x00dev, BCN_OFFSET0, ®); - rt2x00_set_field32(®, BCN_OFFSET0_BCN0, 0xe0); /* 0x3800 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN1, 0xe8); /* 0x3a00 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN2, 0xf0); /* 0x3c00 */ - rt2x00_set_field32(®, BCN_OFFSET0_BCN3, 0xf8); /* 0x3e00 */ - rt2x00usb_register_write(rt2x00dev, BCN_OFFSET0, reg); - - rt2x00usb_register_read(rt2x00dev, BCN_OFFSET1, ®); - rt2x00_set_field32(®, BCN_OFFSET1_BCN4, 0xc8); /* 0x3200 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN5, 0xd0); /* 0x3400 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN6, 0x77); /* 0x1dc0 */ - rt2x00_set_field32(®, BCN_OFFSET1_BCN7, 0x6f); /* 0x1bc0 */ - rt2x00usb_register_write(rt2x00dev, BCN_OFFSET1, reg); - - rt2x00usb_register_write(rt2x00dev, LEGACY_BASIC_RATE, 0x0000013f); - rt2x00usb_register_write(rt2x00dev, HT_BASIC_RATE, 0x00008003); - - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0x00000000); - - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_INTERVAL, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_SYNC, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2x00_set_field32(®, BCN_TIME_CFG_TX_TIME_COMPENSATE, 0); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { - rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400); - rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000); - rt2x00usb_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000); - } else { - rt2x00usb_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000); - rt2x00usb_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606); - } - - rt2x00usb_register_read(rt2x00dev, TX_LINK_CFG, ®); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB_LIFETIME, 32); - rt2x00_set_field32(®, TX_LINK_CFG_MFB_ENABLE, 0); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_UMFS_ENABLE, 0); - rt2x00_set_field32(®, TX_LINK_CFG_TX_MRQ_EN, 0); - rt2x00_set_field32(®, TX_LINK_CFG_TX_RDG_EN, 0); - rt2x00_set_field32(®, TX_LINK_CFG_TX_CF_ACK_EN, 1); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFB, 0); - rt2x00_set_field32(®, TX_LINK_CFG_REMOTE_MFS, 0); - rt2x00usb_register_write(rt2x00dev, TX_LINK_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, TX_TIMEOUT_CFG, ®); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_MPDU_LIFETIME, 9); - rt2x00_set_field32(®, TX_TIMEOUT_CFG_TX_OP_TIMEOUT, 10); - rt2x00usb_register_write(rt2x00dev, TX_TIMEOUT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, MAX_LEN_CFG, ®); - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_MPDU, AGGREGATION_SIZE); - if (rt2x00_rev(&rt2x00dev->chip) >= RT2880E_VERSION && - rt2x00_rev(&rt2x00dev->chip) < RT3070_VERSION) - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 2); - else - rt2x00_set_field32(®, MAX_LEN_CFG_MAX_PSDU, 1); - rt2x00_set_field32(®, MAX_LEN_CFG_MIN_PSDU, 0); - rt2x00_set_field32(®, MAX_LEN_CFG_MIN_MPDU, 0); - rt2x00usb_register_write(rt2x00dev, MAX_LEN_CFG, reg); - - rt2x00usb_register_write(rt2x00dev, PBF_MAX_PCNT, 0x1f3fbf9f); - - rt2x00usb_register_read(rt2x00dev, AUTO_RSP_CFG, ®); - rt2x00_set_field32(®, AUTO_RSP_CFG_AUTORESPONDER, 1); - rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MMODE, 0); - rt2x00_set_field32(®, AUTO_RSP_CFG_CTS_40_MREF, 0); - rt2x00_set_field32(®, AUTO_RSP_CFG_DUAL_CTS_EN, 0); - rt2x00_set_field32(®, AUTO_RSP_CFG_ACK_CTS_PSM_BIT, 0); - rt2x00usb_register_write(rt2x00dev, AUTO_RSP_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_RATE, 8); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, CCK_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, CCK_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_RATE, 8); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, OFDM_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, OFDM_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); - rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_RATE, 0x4004); - rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, MM20_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_MM40, 0); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, MM20_PROT_CFG_TX_OP_ALLOW_GF40, 0); - rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_RATE, 0x4084); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, MM40_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, MM40_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); - rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_RATE, 0x4004); - rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, GF20_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_MM40, 0); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, GF20_PROT_CFG_TX_OP_ALLOW_GF40, 0); - rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); - rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_RATE, 0x4084); - rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_CTRL, 0); - rt2x00_set_field32(®, GF40_PROT_CFG_PROTECT_NAV, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_CCK, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_OFDM, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM20, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_MM40, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF20, 1); - rt2x00_set_field32(®, GF40_PROT_CFG_TX_OP_ALLOW_GF40, 1); - rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); - - rt2x00usb_register_write(rt2x00dev, PBF_CFG, 0xf40006); - - rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_DMA_BUSY, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_DMA_BUSY, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_WP_DMA_BURST_SIZE, 3); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_BIG_ENDIAN, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_RX_HDR_SCATTER, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_HDR_SEG_LEN, 0); - rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - rt2x00usb_register_write(rt2x00dev, TXOP_CTRL_CFG, 0x0000583f); - rt2x00usb_register_write(rt2x00dev, TXOP_HLDR_ET, 0x00000002); - - rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); - rt2x00_set_field32(®, TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT, 32); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, - IEEE80211_MAX_RTS_THRESHOLD); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_FBK_EN, 0); - rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); - - rt2x00usb_register_write(rt2x00dev, EXP_ACK_TIME, 0x002400ca); - rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003); - - /* - * ASIC will keep garbage value after boot, clear encryption keys. - */ - for (i = 0; i < 4; i++) - rt2x00usb_register_write(rt2x00dev, - SHARED_KEY_MODE_ENTRY(i), 0); - - for (i = 0; i < 256; i++) { - u32 wcid[2] = { 0xffffffff, 0x00ffffff }; - rt2x00usb_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i), - wcid, sizeof(wcid)); - - rt2x00usb_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1); - rt2x00usb_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0); - } - - /* - * Clear all beacons - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE4, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE5, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE6, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE7, 0); - - rt2x00usb_register_read(rt2x00dev, USB_CYC_CFG, ®); - rt2x00_set_field32(®, USB_CYC_CFG_CLOCK_CYCLE, 30); - rt2x00usb_register_write(rt2x00dev, USB_CYC_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG0, ®); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS0FBK, 0); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS1FBK, 0); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS2FBK, 1); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS3FBK, 2); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS4FBK, 3); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS5FBK, 4); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS6FBK, 5); - rt2x00_set_field32(®, HT_FBK_CFG0_HTMCS7FBK, 6); - rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG0, reg); - - rt2x00usb_register_read(rt2x00dev, HT_FBK_CFG1, ®); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS8FBK, 8); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS9FBK, 8); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS10FBK, 9); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS11FBK, 10); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS12FBK, 11); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS13FBK, 12); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS14FBK, 13); - rt2x00_set_field32(®, HT_FBK_CFG1_HTMCS15FBK, 14); - rt2x00usb_register_write(rt2x00dev, HT_FBK_CFG1, reg); - - rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG0, ®); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS0FBK, 8); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS1FBK, 8); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS2FBK, 9); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS3FBK, 10); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS4FBK, 11); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS5FBK, 12); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS6FBK, 13); - rt2x00_set_field32(®, LG_FBK_CFG0_OFDMMCS7FBK, 14); - rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG0, reg); - - rt2x00usb_register_read(rt2x00dev, LG_FBK_CFG1, ®); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS0FBK, 0); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS1FBK, 0); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS2FBK, 1); - rt2x00_set_field32(®, LG_FBK_CFG0_CCKMCS3FBK, 2); - rt2x00usb_register_write(rt2x00dev, LG_FBK_CFG1, reg); - - /* - * We must clear the error counters. - * These registers are cleared on read, - * so we may pass a useless variable to store the value. - */ - rt2x00usb_register_read(rt2x00dev, RX_STA_CNT0, ®); - rt2x00usb_register_read(rt2x00dev, RX_STA_CNT1, ®); - rt2x00usb_register_read(rt2x00dev, RX_STA_CNT2, ®); - rt2x00usb_register_read(rt2x00dev, TX_STA_CNT0, ®); - rt2x00usb_register_read(rt2x00dev, TX_STA_CNT1, ®); - rt2x00usb_register_read(rt2x00dev, TX_STA_CNT2, ®); - - return 0; -} - -static int rt2800usb_wait_bbp_rf_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read(rt2x00dev, MAC_STATUS_CFG, ®); - if (!rt2x00_get_field32(reg, MAC_STATUS_CFG_BBP_RF_BUSY)) - return 0; - - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP/RF register access failed, aborting.\n"); - return -EACCES; -} - -static int rt2800usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - /* - * BBP was enabled after firmware was loaded, - * but we need to reactivate it now. - */ - rt2x00usb_register_write(rt2x00dev, H2M_BBP_AGENT, 0); - rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - msleep(1); - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2800usb_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -static int rt2800usb_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 reg_id; - u8 value; - - if (unlikely(rt2800usb_wait_bbp_rf_ready(rt2x00dev) || - rt2800usb_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt2800usb_bbp_write(rt2x00dev, 65, 0x2c); - rt2800usb_bbp_write(rt2x00dev, 66, 0x38); - rt2800usb_bbp_write(rt2x00dev, 69, 0x12); - rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); - rt2800usb_bbp_write(rt2x00dev, 73, 0x10); - rt2800usb_bbp_write(rt2x00dev, 81, 0x37); - rt2800usb_bbp_write(rt2x00dev, 82, 0x62); - rt2800usb_bbp_write(rt2x00dev, 83, 0x6a); - rt2800usb_bbp_write(rt2x00dev, 84, 0x99); - rt2800usb_bbp_write(rt2x00dev, 86, 0x00); - rt2800usb_bbp_write(rt2x00dev, 91, 0x04); - rt2800usb_bbp_write(rt2x00dev, 92, 0x00); - rt2800usb_bbp_write(rt2x00dev, 103, 0x00); - rt2800usb_bbp_write(rt2x00dev, 105, 0x05); - - if (rt2x00_rev(&rt2x00dev->chip) == RT2860C_VERSION) { - rt2800usb_bbp_write(rt2x00dev, 69, 0x16); - rt2800usb_bbp_write(rt2x00dev, 73, 0x12); - } - - if (rt2x00_rev(&rt2x00dev->chip) > RT2860D_VERSION) { - rt2800usb_bbp_write(rt2x00dev, 84, 0x19); - } - - if (rt2x00_rev(&rt2x00dev->chip) == RT3070_VERSION) { - rt2800usb_bbp_write(rt2x00dev, 70, 0x0a); - rt2800usb_bbp_write(rt2x00dev, 84, 0x99); - rt2800usb_bbp_write(rt2x00dev, 105, 0x05); - } - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt2800usb_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} - -static u8 rt2800usb_init_rx_filter(struct rt2x00_dev *rt2x00dev, - bool bw40, u8 rfcsr24, u8 filter_target) -{ - unsigned int i; - u8 bbp; - u8 rfcsr; - u8 passband; - u8 stopband; - u8 overtuned = 0; - - rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); - - rt2800usb_bbp_read(rt2x00dev, 4, &bbp); - rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40); - rt2800usb_bbp_write(rt2x00dev, 4, bbp); - - rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1); - rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); - - /* - * Set power & frequency of passband test tone - */ - rt2800usb_bbp_write(rt2x00dev, 24, 0); - - for (i = 0; i < 100; i++) { - rt2800usb_bbp_write(rt2x00dev, 25, 0x90); - msleep(1); - - rt2800usb_bbp_read(rt2x00dev, 55, &passband); - if (passband) - break; - } - - /* - * Set power & frequency of stopband test tone - */ - rt2800usb_bbp_write(rt2x00dev, 24, 0x06); - - for (i = 0; i < 100; i++) { - rt2800usb_bbp_write(rt2x00dev, 25, 0x90); - msleep(1); - - rt2800usb_bbp_read(rt2x00dev, 55, &stopband); - - if ((passband - stopband) <= filter_target) { - rfcsr24++; - overtuned += ((passband - stopband) == filter_target); - } else - break; - - rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); - } - - rfcsr24 -= !!overtuned; - - rt2800usb_rfcsr_write(rt2x00dev, 24, rfcsr24); - return rfcsr24; -} - -static int rt2800usb_init_rfcsr(struct rt2x00_dev *rt2x00dev) -{ - u8 rfcsr; - u8 bbp; - - if (rt2x00_rev(&rt2x00dev->chip) != RT3070_VERSION) - return 0; - - /* - * Init RF calibration. - */ - rt2800usb_rfcsr_read(rt2x00dev, 30, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1); - rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); - msleep(1); - rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0); - rt2800usb_rfcsr_write(rt2x00dev, 30, rfcsr); - - rt2800usb_rfcsr_write(rt2x00dev, 4, 0x40); - rt2800usb_rfcsr_write(rt2x00dev, 5, 0x03); - rt2800usb_rfcsr_write(rt2x00dev, 6, 0x02); - rt2800usb_rfcsr_write(rt2x00dev, 7, 0x70); - rt2800usb_rfcsr_write(rt2x00dev, 9, 0x0f); - rt2800usb_rfcsr_write(rt2x00dev, 10, 0x71); - rt2800usb_rfcsr_write(rt2x00dev, 11, 0x21); - rt2800usb_rfcsr_write(rt2x00dev, 12, 0x7b); - rt2800usb_rfcsr_write(rt2x00dev, 14, 0x90); - rt2800usb_rfcsr_write(rt2x00dev, 15, 0x58); - rt2800usb_rfcsr_write(rt2x00dev, 16, 0xb3); - rt2800usb_rfcsr_write(rt2x00dev, 17, 0x92); - rt2800usb_rfcsr_write(rt2x00dev, 18, 0x2c); - rt2800usb_rfcsr_write(rt2x00dev, 19, 0x02); - rt2800usb_rfcsr_write(rt2x00dev, 20, 0xba); - rt2800usb_rfcsr_write(rt2x00dev, 21, 0xdb); - rt2800usb_rfcsr_write(rt2x00dev, 24, 0x16); - rt2800usb_rfcsr_write(rt2x00dev, 25, 0x01); - rt2800usb_rfcsr_write(rt2x00dev, 27, 0x03); - rt2800usb_rfcsr_write(rt2x00dev, 29, 0x1f); - - /* - * Set RX Filter calibration for 20MHz and 40MHz - */ - rt2x00dev->calibration[0] = - rt2800usb_init_rx_filter(rt2x00dev, false, 0x07, 0x16); - rt2x00dev->calibration[1] = - rt2800usb_init_rx_filter(rt2x00dev, true, 0x27, 0x19); - - /* - * Set back to initial state - */ - rt2800usb_bbp_write(rt2x00dev, 24, 0); - - rt2800usb_rfcsr_read(rt2x00dev, 22, &rfcsr); - rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0); - rt2800usb_rfcsr_write(rt2x00dev, 22, rfcsr); - - /* - * set BBP back to BW20 - */ - rt2800usb_bbp_read(rt2x00dev, 4, &bbp); - rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0); - rt2800usb_bbp_write(rt2x00dev, 4, bbp); - - return 0; -} - -/* - * Device state switch handlers. - */ -static void rt2800usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, - (state == STATE_RADIO_RX_ON) || - (state == STATE_RADIO_RX_ON_LINK)); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); -} - -static int rt2800usb_wait_wpdma_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u32 reg; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - if (!rt2x00_get_field32(reg, WPDMA_GLO_CFG_TX_DMA_BUSY) && - !rt2x00_get_field32(reg, WPDMA_GLO_CFG_RX_DMA_BUSY)) - return 0; - - msleep(1); - } - - ERROR(rt2x00dev, "WPDMA TX/RX busy, aborting.\n"); - return -EACCES; -} - -static int rt2800usb_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u16 word; - - /* - * Initialize all registers. - */ - if (unlikely(rt2800usb_wait_wpdma_ready(rt2x00dev) || - rt2800usb_init_registers(rt2x00dev) || - rt2800usb_init_bbp(rt2x00dev) || - rt2800usb_init_rfcsr(rt2x00dev))) - return -EIO; - - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - udelay(50); - - rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_TX_WRITEBACK_DONE, 1); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 1); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 1); - rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - - rt2x00usb_register_read(rt2x00dev, USB_DMA_CFG, ®); - rt2x00_set_field32(®, USB_DMA_CFG_PHY_CLEAR, 0); - /* Don't use bulk in aggregation when working with USB 1.1 */ - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_EN, - (rt2x00dev->rx->usb_maxpacket == 512)); - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_TIMEOUT, 128); - /* - * Total room for RX frames in kilobytes, PBF might still exceed - * this limit so reduce the number to prevent errors. - */ - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_AGG_LIMIT, - ((RX_ENTRIES * DATA_FRAME_SIZE) / 1024) - 3); - rt2x00_set_field32(®, USB_DMA_CFG_RX_BULK_EN, 1); - rt2x00_set_field32(®, USB_DMA_CFG_TX_BULK_EN, 1); - rt2x00usb_register_write(rt2x00dev, USB_DMA_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, MAC_SYS_CTRL, ®); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_TX, 1); - rt2x00_set_field32(®, MAC_SYS_CTRL_ENABLE_RX, 1); - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, reg); - - /* - * Initialize LED control - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED1, &word); - rt2800usb_mcu_request(rt2x00dev, MCU_LED_1, 0xff, - word & 0xff, (word >> 8) & 0xff); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED2, &word); - rt2800usb_mcu_request(rt2x00dev, MCU_LED_2, 0xff, - word & 0xff, (word >> 8) & 0xff); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED3, &word); - rt2800usb_mcu_request(rt2x00dev, MCU_LED_3, 0xff, - word & 0xff, (word >> 8) & 0xff); - - return 0; -} - -static void rt2800usb_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, WPDMA_GLO_CFG, ®); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_TX_DMA, 0); - rt2x00_set_field32(®, WPDMA_GLO_CFG_ENABLE_RX_DMA, 0); - rt2x00usb_register_write(rt2x00dev, WPDMA_GLO_CFG, reg); - - rt2x00usb_register_write(rt2x00dev, MAC_SYS_CTRL, 0); - rt2x00usb_register_write(rt2x00dev, PWR_PIN_CFG, 0); - rt2x00usb_register_write(rt2x00dev, TX_PIN_CFG, 0); - - /* Wait for DMA, ignore error */ - rt2800usb_wait_wpdma_ready(rt2x00dev); - - rt2x00usb_disable_radio(rt2x00dev); -} - -static int rt2800usb_set_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - if (state == STATE_AWAKE) - rt2800usb_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); - else - rt2800usb_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 2); - - return 0; -} - -static int rt2800usb_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int retval = 0; - - switch (state) { - case STATE_RADIO_ON: - /* - * Before the radio can be enabled, the device first has - * to be woken up. After that it needs a bit of time - * to be fully awake and then the radio can be enabled. - */ - rt2800usb_set_state(rt2x00dev, STATE_AWAKE); - msleep(1); - retval = rt2800usb_enable_radio(rt2x00dev); - break; - case STATE_RADIO_OFF: - /* - * After the radio has been disabled, the device should - * be put to sleep for powersaving. - */ - rt2800usb_disable_radio(rt2x00dev); - rt2800usb_set_state(rt2x00dev, STATE_SLEEP); - break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt2800usb_toggle_rx(rt2x00dev, state); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: - /* No support, but no error either */ - break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt2800usb_set_state(rt2x00dev, state); - break; - default: - retval = -ENOTSUPP; - break; - } - - if (unlikely(retval)) - ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", - state, retval); - - return retval; -} - -/* - * TX descriptor initialization - */ -static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txi = skbdesc->desc; - __le32 *txwi = &txi[TXINFO_DESC_SIZE / sizeof(__le32)]; - u32 word; - - /* - * Initialize TX Info descriptor - */ - rt2x00_desc_read(txwi, 0, &word); - rt2x00_set_field32(&word, TXWI_W0_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MIMO_PS, 0); - rt2x00_set_field32(&word, TXWI_W0_CF_ACK, 0); - rt2x00_set_field32(&word, TXWI_W0_TS, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_AMPDU, - test_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY, txdesc->mpdu_density); - rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->ifs); - rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs); - rt2x00_set_field32(&word, TXWI_W0_BW, - test_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_SHORT_GI, - test_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W0_STBC, txdesc->stbc); - rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode); - rt2x00_desc_write(txwi, 0, word); - - rt2x00_desc_read(txwi, 1, &word); - rt2x00_set_field32(&word, TXWI_W1_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W1_NSEQ, - test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); - rt2x00_set_field32(&word, TXWI_W1_BW_WIN_SIZE, txdesc->ba_size); - rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID, - test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ? - txdesc->key_idx : 0xff); - rt2x00_set_field32(&word, TXWI_W1_MPDU_TOTAL_BYTE_COUNT, - skb->len - txdesc->l2pad); - rt2x00_set_field32(&word, TXWI_W1_PACKETID, - skbdesc->entry->queue->qid + 1); - rt2x00_desc_write(txwi, 1, word); - - /* - * Always write 0 to IV/EIV fields, hardware will insert the IV - * from the IVEIV register when TXINFO_W0_WIV is set to 0. - * When TXINFO_W0_WIV is set to 1 it will use the IV data - * from the descriptor. The TXWI_W1_WIRELESS_CLI_ID indicates which - * crypto entry in the registers should be used to encrypt the frame. - */ - _rt2x00_desc_write(txwi, 2, 0 /* skbdesc->iv[0] */); - _rt2x00_desc_write(txwi, 3, 0 /* skbdesc->iv[1] */); - - /* - * Initialize TX descriptor - */ - rt2x00_desc_read(txi, 0, &word); - rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN, - skb->len + TXWI_DESC_SIZE); - rt2x00_set_field32(&word, TXINFO_W0_WIV, - !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags)); - rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2); - rt2x00_set_field32(&word, TXINFO_W0_SW_USE_LAST_ROUND, 0); - rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_NEXT_VALID, 0); - rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_BURST, - test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_desc_write(txi, 0, word); -} - -/* - * TX data initialization - */ -static void rt2800usb_write_beacon(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - unsigned int beacon_base; - u32 reg; - - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry->skb->data; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 0); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); - - /* - * Write entire beacon with descriptor to register. - */ - beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, beacon_base, - entry->skb->data, entry->skb->len, - REGISTER_TIMEOUT32(entry->skb->len)); - - /* - * Clean up the beacon skb. - */ - dev_kfree_skb(entry->skb); - entry->skb = NULL; -} - -static int rt2800usb_get_tx_data_len(struct queue_entry *entry) -{ - int length; - - /* - * The length _must_ include 4 bytes padding, - * it should always be multiple of 4, - * but it must _not_ be a multiple of the USB packet size. - */ - length = roundup(entry->skb->len + 4, 4); - length += (4 * !(length % entry->queue->usb_maxpacket)); - - return length; -} - -static void rt2800usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - rt2x00usb_register_read(rt2x00dev, BCN_TIME_CFG, ®); - if (!rt2x00_get_field32(reg, BCN_TIME_CFG_BEACON_GEN)) { - rt2x00_set_field32(®, BCN_TIME_CFG_TSF_TICKING, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, 1); - rt2x00_set_field32(®, BCN_TIME_CFG_BEACON_GEN, 1); - rt2x00usb_register_write(rt2x00dev, BCN_TIME_CFG, reg); - } -} - -/* - * RX control handlers - */ -static void rt2800usb_fill_rxdone(struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - __le32 *rxd = (__le32 *)entry->skb->data; - __le32 *rxwi; - u32 rxd0; - u32 rxwi0; - u32 rxwi1; - u32 rxwi2; - u32 rxwi3; - - /* - * Copy descriptor to the skbdesc->desc buffer, making it safe from - * moving of frame data in rt2x00usb. - */ - memcpy(skbdesc->desc, rxd, skbdesc->desc_len); - rxd = (__le32 *)skbdesc->desc; - rxwi = &rxd[RXD_DESC_SIZE / sizeof(__le32)]; - - /* - * It is now safe to read the descriptor on all architectures. - */ - rt2x00_desc_read(rxd, 0, &rxd0); - rt2x00_desc_read(rxwi, 0, &rxwi0); - rt2x00_desc_read(rxwi, 1, &rxwi1); - rt2x00_desc_read(rxwi, 2, &rxwi2); - rt2x00_desc_read(rxwi, 3, &rxwi3); - - if (rt2x00_get_field32(rxd0, RXD_W0_CRC_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = rt2x00_get_field32(rxwi0, RXWI_W0_UDF); - rxdesc->cipher_status = - rt2x00_get_field32(rxd0, RXD_W0_CIPHER_ERROR); - } - - if (rt2x00_get_field32(rxd0, RXD_W0_DECRYPTED)) { - /* - * Hardware has stripped IV/EIV data from 802.11 frame during - * decryption. Unfortunately the descriptor doesn't contain - * any fields with the EIV/IV data either, so they can't - * be restored by rt2x00lib. - */ - rxdesc->flags |= RX_FLAG_IV_STRIPPED; - - if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) - rxdesc->flags |= RX_FLAG_DECRYPTED; - else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) - rxdesc->flags |= RX_FLAG_MMIC_ERROR; - } - - if (rt2x00_get_field32(rxd0, RXD_W0_MY_BSS)) - rxdesc->dev_flags |= RXDONE_MY_BSS; - - if (rt2x00_get_field32(rxd0, RXD_W0_L2PAD)) { - rxdesc->dev_flags |= RXDONE_L2PAD; - skbdesc->flags |= SKBDESC_L2_PADDED; - } - - if (rt2x00_get_field32(rxwi1, RXWI_W1_SHORT_GI)) - rxdesc->flags |= RX_FLAG_SHORT_GI; - - if (rt2x00_get_field32(rxwi1, RXWI_W1_BW)) - rxdesc->flags |= RX_FLAG_40MHZ; - - /* - * Detect RX rate, always use MCS as signal type. - */ - rxdesc->dev_flags |= RXDONE_SIGNAL_MCS; - rxdesc->rate_mode = rt2x00_get_field32(rxwi1, RXWI_W1_PHYMODE); - rxdesc->signal = rt2x00_get_field32(rxwi1, RXWI_W1_MCS); - - /* - * Mask of 0x8 bit to remove the short preamble flag. - */ - if (rxdesc->rate_mode == RATE_MODE_CCK) - rxdesc->signal &= ~0x8; - - rxdesc->rssi = - (rt2x00_get_field32(rxwi2, RXWI_W2_RSSI0) + - rt2x00_get_field32(rxwi2, RXWI_W2_RSSI1)) / 2; - - rxdesc->noise = - (rt2x00_get_field32(rxwi3, RXWI_W3_SNR0) + - rt2x00_get_field32(rxwi3, RXWI_W3_SNR1)) / 2; - - rxdesc->size = rt2x00_get_field32(rxwi0, RXWI_W0_MPDU_TOTAL_BYTE_COUNT); - - /* - * Remove RXWI descriptor from start of buffer. - */ - skb_pull(entry->skb, skbdesc->desc_len); - skb_trim(entry->skb, rxdesc->size); -} - -/* - * Device probe functions. - */ -static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u16 word; - u8 *mac; - u8 default_lna_gain; - - rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); - - /* - * Start validation of the data that has been read. - */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - if (!is_valid_ether_addr(mac)) { - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %pM\n", mac); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TXPATH, 1); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF2820); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); - EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } else if (rt2x00_rev(&rt2x00dev->chip) < RT2883_VERSION) { - /* - * There is a max of 2 RX streams for RT2870 series - */ - if (rt2x00_get_field16(word, EEPROM_ANTENNA_RXPATH) > 2) - rt2x00_set_field16(&word, EEPROM_ANTENNA_RXPATH, 2); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_HW_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_NIC_DYNAMIC_TX_AGC, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_SB_A, 0); - rt2x00_set_field16(&word, EEPROM_NIC_WPS_PBC, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_BW40M_A, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); - EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); - if ((word & 0x00ff) == 0x00ff) { - rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); - rt2x00_set_field16(&word, EEPROM_FREQ_LED_MODE, - LED_MODE_TXRX_ACTIVITY); - rt2x00_set_field16(&word, EEPROM_FREQ_LED_POLARITY, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED1, 0x5555); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED2, 0x2221); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED3, 0xa9f8); - EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); - } - - /* - * During the LNA validation we are going to use - * lna0 as correct value. Note that EEPROM_LNA - * is never validated. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_LNA, &word); - default_lna_gain = rt2x00_get_field16(word, EEPROM_LNA_A0); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG, &word); - if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET0)) > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET0, 0); - if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG_OFFSET1)) > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_BG_OFFSET1, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG, word); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_BG2, &word); - if (abs(rt2x00_get_field16(word, EEPROM_RSSI_BG2_OFFSET2)) > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_BG2_OFFSET2, 0); - if (rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0x00 || - rt2x00_get_field16(word, EEPROM_RSSI_BG2_LNA_A1) == 0xff) - rt2x00_set_field16(&word, EEPROM_RSSI_BG2_LNA_A1, - default_lna_gain); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_BG2, word); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A, &word); - if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET0)) > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET0, 0); - if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A_OFFSET1)) > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_A_OFFSET1, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A, word); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_A2, &word); - if (abs(rt2x00_get_field16(word, EEPROM_RSSI_A2_OFFSET2)) > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_A2_OFFSET2, 0); - if (rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0x00 || - rt2x00_get_field16(word, EEPROM_RSSI_A2_LNA_A2) == 0xff) - rt2x00_set_field16(&word, EEPROM_RSSI_A2_LNA_A2, - default_lna_gain); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); - - return 0; -} - -static int rt2800usb_init_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u16 value; - u16 eeprom; - - /* - * Read EEPROM word for configuration. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Identify RF chipset. - */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2870, value, reg); - - /* - * The check for rt2860 is not a typo, some rt2870 hardware - * identifies itself as rt2860 in the CSR register. - */ - if (!rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28600000) && - !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28700000) && - !rt2x00_check_rev(&rt2x00dev->chip, 0xfff00000, 0x28800000) && - !rt2x00_check_rev(&rt2x00dev->chip, 0xffff0000, 0x30700000)) { - ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); - return -ENODEV; - } - - if (!rt2x00_rf(&rt2x00dev->chip, RF2820) && - !rt2x00_rf(&rt2x00dev->chip, RF2850) && - !rt2x00_rf(&rt2x00dev->chip, RF2720) && - !rt2x00_rf(&rt2x00dev->chip, RF2750) && - !rt2x00_rf(&rt2x00dev->chip, RF3020) && - !rt2x00_rf(&rt2x00dev->chip, RF2020)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); - return -ENODEV; - } - - /* - * Identify default antenna configuration. - */ - rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH); - rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH); - - /* - * Read frequency offset and RF programming sequence. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); - rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); - - /* - * Read external LNA informations. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) - __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) - __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); - - /* - * Detect if this device has an hardware controlled radio. - */ - if (rt2x00_get_field16(eeprom, EEPROM_NIC_HW_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); - - /* - * Store led settings, for correct led behaviour. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); - rt2800usb_init_led(rt2x00dev, &rt2x00dev->led_qual, LED_TYPE_QUALITY); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, - &rt2x00dev->led_mcu_reg); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - return 0; -} - -/* - * RF value list for rt2870 - * Supports: 2.4 GHz (all) & 5.2 GHz (RF2850 & RF2750) - */ -static const struct rf_channel rf_vals[] = { - { 1, 0x18402ecc, 0x184c0786, 0x1816b455, 0x1800510b }, - { 2, 0x18402ecc, 0x184c0786, 0x18168a55, 0x1800519f }, - { 3, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800518b }, - { 4, 0x18402ecc, 0x184c078a, 0x18168a55, 0x1800519f }, - { 5, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800518b }, - { 6, 0x18402ecc, 0x184c078e, 0x18168a55, 0x1800519f }, - { 7, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800518b }, - { 8, 0x18402ecc, 0x184c0792, 0x18168a55, 0x1800519f }, - { 9, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800518b }, - { 10, 0x18402ecc, 0x184c0796, 0x18168a55, 0x1800519f }, - { 11, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800518b }, - { 12, 0x18402ecc, 0x184c079a, 0x18168a55, 0x1800519f }, - { 13, 0x18402ecc, 0x184c079e, 0x18168a55, 0x1800518b }, - { 14, 0x18402ecc, 0x184c07a2, 0x18168a55, 0x18005193 }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x18402ecc, 0x184c099a, 0x18158a55, 0x180ed1a3 }, - { 38, 0x18402ecc, 0x184c099e, 0x18158a55, 0x180ed193 }, - { 40, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed183 }, - { 44, 0x18402ec8, 0x184c0682, 0x18158a55, 0x180ed1a3 }, - { 46, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed18b }, - { 48, 0x18402ec8, 0x184c0686, 0x18158a55, 0x180ed19b }, - { 52, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed193 }, - { 54, 0x18402ec8, 0x184c068a, 0x18158a55, 0x180ed1a3 }, - { 56, 0x18402ec8, 0x184c068e, 0x18158a55, 0x180ed18b }, - { 60, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed183 }, - { 62, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed193 }, - { 64, 0x18402ec8, 0x184c0692, 0x18158a55, 0x180ed1a3 }, - - /* 802.11 HyperLan 2 */ - { 100, 0x18402ec8, 0x184c06b2, 0x18178a55, 0x180ed783 }, - { 102, 0x18402ec8, 0x184c06b2, 0x18578a55, 0x180ed793 }, - { 104, 0x18402ec8, 0x185c06b2, 0x18578a55, 0x180ed1a3 }, - { 108, 0x18402ecc, 0x185c0a32, 0x18578a55, 0x180ed193 }, - { 110, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed183 }, - { 112, 0x18402ecc, 0x184c0a36, 0x18178a55, 0x180ed19b }, - { 116, 0x18402ecc, 0x184c0a3a, 0x18178a55, 0x180ed1a3 }, - { 118, 0x18402ecc, 0x184c0a3e, 0x18178a55, 0x180ed193 }, - { 120, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed183 }, - { 124, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed193 }, - { 126, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed15b }, - { 128, 0x18402ec4, 0x184c0382, 0x18178a55, 0x180ed1a3 }, - { 132, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed18b }, - { 134, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed193 }, - { 136, 0x18402ec4, 0x184c0386, 0x18178a55, 0x180ed19b }, - { 140, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed183 }, - - /* 802.11 UNII */ - { 149, 0x18402ec4, 0x184c038a, 0x18178a55, 0x180ed1a7 }, - { 151, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed187 }, - { 153, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed18f }, - { 157, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed19f }, - { 159, 0x18402ec4, 0x184c038e, 0x18178a55, 0x180ed1a7 }, - { 161, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed187 }, - { 165, 0x18402ec4, 0x184c0392, 0x18178a55, 0x180ed197 }, - { 167, 0x18402ec4, 0x184c03d2, 0x18179855, 0x1815531f }, - { 169, 0x18402ec4, 0x184c03d2, 0x18179855, 0x18155327 }, - { 171, 0x18402ec4, 0x184c03d6, 0x18179855, 0x18155307 }, - { 173, 0x18402ec4, 0x184c03d6, 0x18179855, 0x1815530f }, - - /* 802.11 Japan */ - { 184, 0x15002ccc, 0x1500491e, 0x1509be55, 0x150c0a0b }, - { 188, 0x15002ccc, 0x15004922, 0x1509be55, 0x150c0a13 }, - { 192, 0x15002ccc, 0x15004926, 0x1509be55, 0x150c0a1b }, - { 196, 0x15002ccc, 0x1500492a, 0x1509be55, 0x150c0a23 }, - { 208, 0x15002ccc, 0x1500493a, 0x1509be55, 0x150c0a13 }, - { 212, 0x15002ccc, 0x1500493e, 0x1509be55, 0x150c0a1b }, - { 216, 0x15002ccc, 0x15004982, 0x1509be55, 0x150c0a23 }, -}; - -/* - * RF value list for rt3070 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_3070[] = { - {1, 241, 2, 2 }, - {2, 241, 2, 7 }, - {3, 242, 2, 2 }, - {4, 242, 2, 7 }, - {5, 243, 2, 2 }, - {6, 243, 2, 7 }, - {7, 244, 2, 2 }, - {8, 244, 2, 7 }, - {9, 245, 2, 2 }, - {10, 245, 2, 7 }, - {11, 246, 2, 2 }, - {12, 246, 2, 7 }, - {13, 247, 2, 2 }, - {14, 248, 2, 4 }, -}; - -static int rt2800usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - struct channel_info *info; - char *tx_power1; - char *tx_power2; - unsigned int i; - u16 eeprom; - - /* - * Initialize all hw fields. - */ - rt2x00dev->hw->flags = - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; - rt2x00dev->hw->extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE; - - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); - SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, - EEPROM_MAC_ADDR_0)); - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Initialize HT information. - */ - spec->ht.ht_supported = true; - spec->ht.cap = - IEEE80211_HT_CAP_SUP_WIDTH_20_40 | - IEEE80211_HT_CAP_GRN_FLD | - IEEE80211_HT_CAP_SGI_20 | - IEEE80211_HT_CAP_SGI_40 | - IEEE80211_HT_CAP_TX_STBC | - IEEE80211_HT_CAP_RX_STBC | - IEEE80211_HT_CAP_PSMP_SUPPORT; - spec->ht.ampdu_factor = 3; - spec->ht.ampdu_density = 4; - spec->ht.mcs.tx_params = - IEEE80211_HT_MCS_TX_DEFINED | - IEEE80211_HT_MCS_TX_RX_DIFF | - ((rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TXPATH) - 1) << - IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT); - - switch (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RXPATH)) { - case 3: - spec->ht.mcs.rx_mask[2] = 0xff; - case 2: - spec->ht.mcs.rx_mask[1] = 0xff; - case 1: - spec->ht.mcs.rx_mask[0] = 0xff; - spec->ht.mcs.rx_mask[4] = 0x1; /* MCS32 */ - break; - } - - /* - * Initialize hw_mode information. - */ - spec->supported_bands = SUPPORT_BAND_2GHZ; - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - - if (rt2x00_rf(&rt2x00dev->chip, RF2820) || - rt2x00_rf(&rt2x00dev->chip, RF2720)) { - spec->num_channels = 14; - spec->channels = rf_vals; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2850) || - rt2x00_rf(&rt2x00dev->chip, RF2750)) { - spec->supported_bands |= SUPPORT_BAND_5GHZ; - spec->num_channels = ARRAY_SIZE(rf_vals); - spec->channels = rf_vals; - } else if (rt2x00_rf(&rt2x00dev->chip, RF3020) || - rt2x00_rf(&rt2x00dev->chip, RF2020)) { - spec->num_channels = ARRAY_SIZE(rf_vals_3070); - spec->channels = rf_vals_3070; - } - - /* - * Create channel information array - */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - spec->channels_info = info; - - tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); - tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); - - for (i = 0; i < 14; i++) { - info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); - info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); - } - - if (spec->num_channels > 14) { - tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); - tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); - - for (i = 14; i < spec->num_channels; i++) { - info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); - info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); - } - } - - return 0; -} - -static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Allocate eeprom data. - */ - retval = rt2800usb_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt2800usb_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt2800usb_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device has multiple filters for control frames - * and has a separate filter for PS Poll frames. - */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); - __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); - - /* - * This device requires firmware. - */ - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags); - if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; -} - -/* - * IEEE80211 stack callback functions. - */ -static void rt2800usb_get_tkip_seq(struct ieee80211_hw *hw, u8 hw_key_idx, - u32 *iv32, u16 *iv16) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct mac_iveiv_entry iveiv_entry; - u32 offset; - - offset = MAC_IVEIV_ENTRY(hw_key_idx); - rt2x00usb_register_multiread(rt2x00dev, offset, - &iveiv_entry, sizeof(iveiv_entry)); - - memcpy(&iveiv_entry.iv[0], iv16, sizeof(iv16)); - memcpy(&iveiv_entry.iv[4], iv32, sizeof(iv32)); -} - -static int rt2800usb_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u32 reg; - bool enabled = (value < IEEE80211_MAX_RTS_THRESHOLD); - - rt2x00usb_register_read(rt2x00dev, TX_RTS_CFG, ®); - rt2x00_set_field32(®, TX_RTS_CFG_RTS_THRES, value); - rt2x00usb_register_write(rt2x00dev, TX_RTS_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, CCK_PROT_CFG, ®); - rt2x00_set_field32(®, CCK_PROT_CFG_RTS_TH_EN, enabled); - rt2x00usb_register_write(rt2x00dev, CCK_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, OFDM_PROT_CFG, ®); - rt2x00_set_field32(®, OFDM_PROT_CFG_RTS_TH_EN, enabled); - rt2x00usb_register_write(rt2x00dev, OFDM_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, MM20_PROT_CFG, ®); - rt2x00_set_field32(®, MM20_PROT_CFG_RTS_TH_EN, enabled); - rt2x00usb_register_write(rt2x00dev, MM20_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, MM40_PROT_CFG, ®); - rt2x00_set_field32(®, MM40_PROT_CFG_RTS_TH_EN, enabled); - rt2x00usb_register_write(rt2x00dev, MM40_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, GF20_PROT_CFG, ®); - rt2x00_set_field32(®, GF20_PROT_CFG_RTS_TH_EN, enabled); - rt2x00usb_register_write(rt2x00dev, GF20_PROT_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, GF40_PROT_CFG, ®); - rt2x00_set_field32(®, GF40_PROT_CFG_RTS_TH_EN, enabled); - rt2x00usb_register_write(rt2x00dev, GF40_PROT_CFG, reg); - - return 0; -} - -static int rt2800usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, - const struct ieee80211_tx_queue_params *params) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_queue *queue; - struct rt2x00_field32 field; - int retval; - u32 reg; - u32 offset; - - /* - * First pass the configuration through rt2x00lib, that will - * update the queue settings and validate the input. After that - * we are free to update the registers based on the value - * in the queue parameter. - */ - retval = rt2x00mac_conf_tx(hw, queue_idx, params); - if (retval) - return retval; - - /* - * We only need to perform additional register initialization - * for WMM queues/ - */ - if (queue_idx >= 4) - return 0; - - queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - - /* Update WMM TXOP register */ - offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2))); - field.bit_offset = (queue_idx & 1) * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00usb_register_write(rt2x00dev, offset, reg); - - /* Update WMM registers */ - field.bit_offset = queue_idx * 4; - field.bit_mask = 0xf << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, WMM_AIFSN_CFG, ®); - rt2x00_set_field32(®, field, queue->aifs); - rt2x00usb_register_write(rt2x00dev, WMM_AIFSN_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, WMM_CWMIN_CFG, ®); - rt2x00_set_field32(®, field, queue->cw_min); - rt2x00usb_register_write(rt2x00dev, WMM_CWMIN_CFG, reg); - - rt2x00usb_register_read(rt2x00dev, WMM_CWMAX_CFG, ®); - rt2x00_set_field32(®, field, queue->cw_max); - rt2x00usb_register_write(rt2x00dev, WMM_CWMAX_CFG, reg); - - /* Update EDCA registers */ - offset = EDCA_AC0_CFG + (sizeof(u32) * queue_idx); - - rt2x00usb_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, EDCA_AC0_CFG_TX_OP, queue->txop); - rt2x00_set_field32(®, EDCA_AC0_CFG_AIFSN, queue->aifs); - rt2x00_set_field32(®, EDCA_AC0_CFG_CWMIN, queue->cw_min); - rt2x00_set_field32(®, EDCA_AC0_CFG_CWMAX, queue->cw_max); - rt2x00usb_register_write(rt2x00dev, offset, reg); - - return 0; -} - -static u64 rt2800usb_get_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u64 tsf; - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW1, ®); - tsf = (u64) rt2x00_get_field32(reg, TSF_TIMER_DW1_HIGH_WORD) << 32; - rt2x00usb_register_read(rt2x00dev, TSF_TIMER_DW0, ®); - tsf |= rt2x00_get_field32(reg, TSF_TIMER_DW0_LOW_WORD); - - return tsf; -} - -static const struct ieee80211_ops rt2800usb_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, - .get_tkip_seq = rt2800usb_get_tkip_seq, - .set_rts_threshold = rt2800usb_set_rts_threshold, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt2800usb_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .get_tsf = rt2800usb_get_tsf, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; - -static const struct rt2x00lib_ops rt2800usb_rt2x00_ops = { - .probe_hw = rt2800usb_probe_hw, - .get_firmware_name = rt2800usb_get_firmware_name, - .check_firmware = rt2800usb_check_firmware, - .load_firmware = rt2800usb_load_firmware, - .initialize = rt2x00usb_initialize, - .uninitialize = rt2x00usb_uninitialize, - .clear_entry = rt2x00usb_clear_entry, - .set_device_state = rt2800usb_set_device_state, - .rfkill_poll = rt2800usb_rfkill_poll, - .link_stats = rt2800usb_link_stats, - .reset_tuner = rt2800usb_reset_tuner, - .link_tuner = rt2800usb_link_tuner, - .write_tx_desc = rt2800usb_write_tx_desc, - .write_tx_data = rt2x00usb_write_tx_data, - .write_beacon = rt2800usb_write_beacon, - .get_tx_data_len = rt2800usb_get_tx_data_len, - .kick_tx_queue = rt2800usb_kick_tx_queue, - .kill_tx_queue = rt2x00usb_kill_tx_queue, - .fill_rxdone = rt2800usb_fill_rxdone, - .config_shared_key = rt2800usb_config_shared_key, - .config_pairwise_key = rt2800usb_config_pairwise_key, - .config_filter = rt2800usb_config_filter, - .config_intf = rt2800usb_config_intf, - .config_erp = rt2800usb_config_erp, - .config_ant = rt2800usb_config_ant, - .config = rt2800usb_config, -}; - -static const struct data_queue_desc rt2800usb_queue_rx = { - .entry_num = RX_ENTRIES, - .data_size = AGGREGATION_SIZE, - .desc_size = RXD_DESC_SIZE + RXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt2800usb_queue_tx = { - .entry_num = TX_ENTRIES, - .data_size = AGGREGATION_SIZE, - .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt2800usb_queue_bcn = { - .entry_num = 8 * BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXINFO_DESC_SIZE + TXWI_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct rt2x00_ops rt2800usb_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 8, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt2800usb_queue_rx, - .tx = &rt2800usb_queue_tx, - .bcn = &rt2800usb_queue_bcn, - .lib = &rt2800usb_rt2x00_ops, - .hw = &rt2800usb_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt2800usb_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * rt2800usb module information. - */ -static struct usb_device_id rt2800usb_device_table[] = { - /* Abocom */ - { USB_DEVICE(0x07b8, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07b8, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1482, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AirTies */ - { USB_DEVICE(0x1eda, 0x2310), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Amigo */ - { USB_DEVICE(0x0e0b, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e0b, 0x9041), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Amit */ - { USB_DEVICE(0x15c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* ASUS */ - { USB_DEVICE(0x0b05, 0x1731), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* AzureWave */ - { USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Belkin */ - { USB_DEVICE(0x050d, 0x8053), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x805c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x815c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x050d, 0x825a), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Buffalo */ - { USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0411, 0x012e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c08), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c12), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c23), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c25), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c27), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x14b2, 0x3c28), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Corega */ - { USB_DEVICE(0x07aa, 0x002f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07aa, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x18c5, 0x0008), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x18c5, 0x0012), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c09), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c0f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c11), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Edimax */ - { USB_DEVICE(0x7392, 0x7711), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x7392, 0x7717), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x7392, 0x7718), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Encore */ - { USB_DEVICE(0x203d, 0x1480), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* EnGenius */ - { USB_DEVICE(0X1740, 0x9701), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9702), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9703), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9705), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9706), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x9801), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Gigabyte */ - { USB_DEVICE(0x1044, 0x800b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1044, 0x800c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1044, 0x800d), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Hawking */ - { USB_DEVICE(0x0e66, 0x0001), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0003), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x0009), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0e66, 0x000b), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* I-O DATA */ - { USB_DEVICE(0x04bb, 0x0945), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* LevelOne */ - { USB_DEVICE(0x1740, 0x0605), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1740, 0x0615), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Linksys */ - { USB_DEVICE(0x1737, 0x0070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1737, 0x0077), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Logitec */ - { USB_DEVICE(0x0789, 0x0162), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0163), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0789, 0x0164), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Motorola */ - { USB_DEVICE(0x100d, 0x9031), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x100d, 0x9032), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Ovislink */ - { USB_DEVICE(0x1b75, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Pegatron */ - { USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Philips */ - { USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Planex */ - { USB_DEVICE(0x2019, 0xed06), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x2019, 0xab25), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Qcom */ - { USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Quanta */ - { USB_DEVICE(0x1a32, 0x0304), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Ralink */ - { USB_DEVICE(0x0db0, 0x3820), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0db0, 0x6899), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2770), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x2870), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3070), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3071), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3072), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Samsung */ - { USB_DEVICE(0x04e8, 0x2018), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Siemens */ - { USB_DEVICE(0x129b, 0x1828), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0017), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x002d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0039), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003b), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003c), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003d), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003e), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x003f), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0040), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0df6, 0x0042), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* SMC */ - { USB_DEVICE(0x083a, 0x6618), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7511), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x7522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0x8522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa512), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xa618), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xb522), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x083a, 0xc522), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Sparklan */ - { USB_DEVICE(0x15a9, 0x0006), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Sweex */ - { USB_DEVICE(0x177f, 0x0153), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x177f, 0x0302), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x177f, 0x0313), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* U-Media*/ - { USB_DEVICE(0x157e, 0x300e), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* ZCOM */ - { USB_DEVICE(0x0cde, 0x0022), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0cde, 0x0025), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Zinwell */ - { USB_DEVICE(0x5a57, 0x0280), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0282), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x0283), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x5a57, 0x5257), USB_DEVICE_DATA(&rt2800usb_ops) }, - /* Zyxel */ - { USB_DEVICE(0x0586, 0x3416), USB_DEVICE_DATA(&rt2800usb_ops) }, - { USB_DEVICE(0x0586, 0x341a), USB_DEVICE_DATA(&rt2800usb_ops) }, - { 0, } -}; - -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Ralink RT2800 USB Wireless LAN driver."); -MODULE_SUPPORTED_DEVICE("Ralink RT2870 USB chipset based cards"); -MODULE_DEVICE_TABLE(usb, rt2800usb_device_table); -MODULE_FIRMWARE(FIRMWARE_RT2870); -MODULE_LICENSE("GPL"); - -static struct usb_driver rt2800usb_driver = { - .name = KBUILD_MODNAME, - .id_table = rt2800usb_device_table, - .probe = rt2x00usb_probe, - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -}; - -static int __init rt2800usb_init(void) -{ - return usb_register(&rt2800usb_driver); -} - -static void __exit rt2800usb_exit(void) -{ - usb_deregister(&rt2800usb_driver); -} - -module_init(rt2800usb_init); -module_exit(rt2800usb_exit); diff --git a/drivers/net/wireless/rt2x00/rt2800usb.h b/drivers/net/wireless/rt2x00/rt2800usb.h deleted file mode 100644 index 4d9991c9a51c..000000000000 --- a/drivers/net/wireless/rt2x00/rt2800usb.h +++ /dev/null @@ -1,1951 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the - Free Software Foundation, Inc., - 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -/* - Module: rt2800usb - Abstract: Data structures and registers for the rt2800usb module. - Supported chipsets: RT2800U. - */ - -#ifndef RT2800USB_H -#define RT2800USB_H - -/* - * RF chip defines. - * - * RF2820 2.4G 2T3R - * RF2850 2.4G/5G 2T3R - * RF2720 2.4G 1T2R - * RF2750 2.4G/5G 1T2R - * RF3020 2.4G 1T1R - * RF2020 2.4G B/G - * RF3021 2.4G 1T2R - * RF3022 2.4G 2T2R - * RF3052 2.4G 2T2R - */ -#define RF2820 0x0001 -#define RF2850 0x0002 -#define RF2720 0x0003 -#define RF2750 0x0004 -#define RF3020 0x0005 -#define RF2020 0x0006 -#define RF3021 0x0007 -#define RF3022 0x0008 -#define RF3052 0x0009 - -/* - * RT2870 version - */ -#define RT2860C_VERSION 0x28600100 -#define RT2860D_VERSION 0x28600101 -#define RT2880E_VERSION 0x28720200 -#define RT2883_VERSION 0x28830300 -#define RT3070_VERSION 0x30700200 - -/* - * Signal information. - * Defaul offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 120 /* FIXME */ - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x1000 -#define CSR_REG_SIZE 0x0800 -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0110 -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0080 -#define RF_BASE 0x0004 -#define RF_SIZE 0x0010 - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 4 - -/* - * USB registers. - */ - -/* - * HOST-MCU shared memory - */ -#define HOST_CMD_CSR 0x0404 -#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x000000ff) - -/* - * INT_SOURCE_CSR: Interrupt source register. - * Write one to clear corresponding bit. - * TX_FIFO_STATUS: FIFO Statistics is full, sw should read 0x171c - */ -#define INT_SOURCE_CSR 0x0200 -#define INT_SOURCE_CSR_RXDELAYINT FIELD32(0x00000001) -#define INT_SOURCE_CSR_TXDELAYINT FIELD32(0x00000002) -#define INT_SOURCE_CSR_RX_DONE FIELD32(0x00000004) -#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00000008) -#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00000010) -#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00000020) -#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00000040) -#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00000080) -#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00000100) -#define INT_SOURCE_CSR_MCU_COMMAND FIELD32(0x00000200) -#define INT_SOURCE_CSR_RXTX_COHERENT FIELD32(0x00000400) -#define INT_SOURCE_CSR_TBTT FIELD32(0x00000800) -#define INT_SOURCE_CSR_PRE_TBTT FIELD32(0x00001000) -#define INT_SOURCE_CSR_TX_FIFO_STATUS FIELD32(0x00002000) -#define INT_SOURCE_CSR_AUTO_WAKEUP FIELD32(0x00004000) -#define INT_SOURCE_CSR_GPTIMER FIELD32(0x00008000) -#define INT_SOURCE_CSR_RX_COHERENT FIELD32(0x00010000) -#define INT_SOURCE_CSR_TX_COHERENT FIELD32(0x00020000) - -/* - * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. - */ -#define INT_MASK_CSR 0x0204 -#define INT_MASK_CSR_RXDELAYINT FIELD32(0x00000001) -#define INT_MASK_CSR_TXDELAYINT FIELD32(0x00000002) -#define INT_MASK_CSR_RX_DONE FIELD32(0x00000004) -#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00000008) -#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00000010) -#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00000020) -#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00000040) -#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00000080) -#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00000100) -#define INT_MASK_CSR_MCU_COMMAND FIELD32(0x00000200) -#define INT_MASK_CSR_RXTX_COHERENT FIELD32(0x00000400) -#define INT_MASK_CSR_TBTT FIELD32(0x00000800) -#define INT_MASK_CSR_PRE_TBTT FIELD32(0x00001000) -#define INT_MASK_CSR_TX_FIFO_STATUS FIELD32(0x00002000) -#define INT_MASK_CSR_AUTO_WAKEUP FIELD32(0x00004000) -#define INT_MASK_CSR_GPTIMER FIELD32(0x00008000) -#define INT_MASK_CSR_RX_COHERENT FIELD32(0x00010000) -#define INT_MASK_CSR_TX_COHERENT FIELD32(0x00020000) - -/* - * WPDMA_GLO_CFG - */ -#define WPDMA_GLO_CFG 0x0208 -#define WPDMA_GLO_CFG_ENABLE_TX_DMA FIELD32(0x00000001) -#define WPDMA_GLO_CFG_TX_DMA_BUSY FIELD32(0x00000002) -#define WPDMA_GLO_CFG_ENABLE_RX_DMA FIELD32(0x00000004) -#define WPDMA_GLO_CFG_RX_DMA_BUSY FIELD32(0x00000008) -#define WPDMA_GLO_CFG_WP_DMA_BURST_SIZE FIELD32(0x00000030) -#define WPDMA_GLO_CFG_TX_WRITEBACK_DONE FIELD32(0x00000040) -#define WPDMA_GLO_CFG_BIG_ENDIAN FIELD32(0x00000080) -#define WPDMA_GLO_CFG_RX_HDR_SCATTER FIELD32(0x0000ff00) -#define WPDMA_GLO_CFG_HDR_SEG_LEN FIELD32(0xffff0000) - -/* - * WPDMA_RST_IDX - */ -#define WPDMA_RST_IDX 0x020c -#define WPDMA_RST_IDX_DTX_IDX0 FIELD32(0x00000001) -#define WPDMA_RST_IDX_DTX_IDX1 FIELD32(0x00000002) -#define WPDMA_RST_IDX_DTX_IDX2 FIELD32(0x00000004) -#define WPDMA_RST_IDX_DTX_IDX3 FIELD32(0x00000008) -#define WPDMA_RST_IDX_DTX_IDX4 FIELD32(0x00000010) -#define WPDMA_RST_IDX_DTX_IDX5 FIELD32(0x00000020) -#define WPDMA_RST_IDX_DRX_IDX0 FIELD32(0x00010000) - -/* - * DELAY_INT_CFG - */ -#define DELAY_INT_CFG 0x0210 -#define DELAY_INT_CFG_RXMAX_PTIME FIELD32(0x000000ff) -#define DELAY_INT_CFG_RXMAX_PINT FIELD32(0x00007f00) -#define DELAY_INT_CFG_RXDLY_INT_EN FIELD32(0x00008000) -#define DELAY_INT_CFG_TXMAX_PTIME FIELD32(0x00ff0000) -#define DELAY_INT_CFG_TXMAX_PINT FIELD32(0x7f000000) -#define DELAY_INT_CFG_TXDLY_INT_EN FIELD32(0x80000000) - -/* - * WMM_AIFSN_CFG: Aifsn for each EDCA AC - * AIFSN0: AC_BE - * AIFSN1: AC_BK - * AIFSN1: AC_VI - * AIFSN1: AC_VO - */ -#define WMM_AIFSN_CFG 0x0214 -#define WMM_AIFSN_CFG_AIFSN0 FIELD32(0x0000000f) -#define WMM_AIFSN_CFG_AIFSN1 FIELD32(0x000000f0) -#define WMM_AIFSN_CFG_AIFSN2 FIELD32(0x00000f00) -#define WMM_AIFSN_CFG_AIFSN3 FIELD32(0x0000f000) - -/* - * WMM_CWMIN_CSR: CWmin for each EDCA AC - * CWMIN0: AC_BE - * CWMIN1: AC_BK - * CWMIN1: AC_VI - * CWMIN1: AC_VO - */ -#define WMM_CWMIN_CFG 0x0218 -#define WMM_CWMIN_CFG_CWMIN0 FIELD32(0x0000000f) -#define WMM_CWMIN_CFG_CWMIN1 FIELD32(0x000000f0) -#define WMM_CWMIN_CFG_CWMIN2 FIELD32(0x00000f00) -#define WMM_CWMIN_CFG_CWMIN3 FIELD32(0x0000f000) - -/* - * WMM_CWMAX_CSR: CWmax for each EDCA AC - * CWMAX0: AC_BE - * CWMAX1: AC_BK - * CWMAX1: AC_VI - * CWMAX1: AC_VO - */ -#define WMM_CWMAX_CFG 0x021c -#define WMM_CWMAX_CFG_CWMAX0 FIELD32(0x0000000f) -#define WMM_CWMAX_CFG_CWMAX1 FIELD32(0x000000f0) -#define WMM_CWMAX_CFG_CWMAX2 FIELD32(0x00000f00) -#define WMM_CWMAX_CFG_CWMAX3 FIELD32(0x0000f000) - -/* - * AC_TXOP0: AC_BK/AC_BE TXOP register - * AC0TXOP: AC_BK in unit of 32us - * AC1TXOP: AC_BE in unit of 32us - */ -#define WMM_TXOP0_CFG 0x0220 -#define WMM_TXOP0_CFG_AC0TXOP FIELD32(0x0000ffff) -#define WMM_TXOP0_CFG_AC1TXOP FIELD32(0xffff0000) - -/* - * AC_TXOP1: AC_VO/AC_VI TXOP register - * AC2TXOP: AC_VI in unit of 32us - * AC3TXOP: AC_VO in unit of 32us - */ -#define WMM_TXOP1_CFG 0x0224 -#define WMM_TXOP1_CFG_AC2TXOP FIELD32(0x0000ffff) -#define WMM_TXOP1_CFG_AC3TXOP FIELD32(0xffff0000) - -/* - * GPIO_CTRL_CFG: - */ -#define GPIO_CTRL_CFG 0x0228 -#define GPIO_CTRL_CFG_BIT0 FIELD32(0x00000001) -#define GPIO_CTRL_CFG_BIT1 FIELD32(0x00000002) -#define GPIO_CTRL_CFG_BIT2 FIELD32(0x00000004) -#define GPIO_CTRL_CFG_BIT3 FIELD32(0x00000008) -#define GPIO_CTRL_CFG_BIT4 FIELD32(0x00000010) -#define GPIO_CTRL_CFG_BIT5 FIELD32(0x00000020) -#define GPIO_CTRL_CFG_BIT6 FIELD32(0x00000040) -#define GPIO_CTRL_CFG_BIT7 FIELD32(0x00000080) -#define GPIO_CTRL_CFG_BIT8 FIELD32(0x00000100) - -/* - * MCU_CMD_CFG - */ -#define MCU_CMD_CFG 0x022c - -/* - * AC_BK register offsets - */ -#define TX_BASE_PTR0 0x0230 -#define TX_MAX_CNT0 0x0234 -#define TX_CTX_IDX0 0x0238 -#define TX_DTX_IDX0 0x023c - -/* - * AC_BE register offsets - */ -#define TX_BASE_PTR1 0x0240 -#define TX_MAX_CNT1 0x0244 -#define TX_CTX_IDX1 0x0248 -#define TX_DTX_IDX1 0x024c - -/* - * AC_VI register offsets - */ -#define TX_BASE_PTR2 0x0250 -#define TX_MAX_CNT2 0x0254 -#define TX_CTX_IDX2 0x0258 -#define TX_DTX_IDX2 0x025c - -/* - * AC_VO register offsets - */ -#define TX_BASE_PTR3 0x0260 -#define TX_MAX_CNT3 0x0264 -#define TX_CTX_IDX3 0x0268 -#define TX_DTX_IDX3 0x026c - -/* - * HCCA register offsets - */ -#define TX_BASE_PTR4 0x0270 -#define TX_MAX_CNT4 0x0274 -#define TX_CTX_IDX4 0x0278 -#define TX_DTX_IDX4 0x027c - -/* - * MGMT register offsets - */ -#define TX_BASE_PTR5 0x0280 -#define TX_MAX_CNT5 0x0284 -#define TX_CTX_IDX5 0x0288 -#define TX_DTX_IDX5 0x028c - -/* - * RX register offsets - */ -#define RX_BASE_PTR 0x0290 -#define RX_MAX_CNT 0x0294 -#define RX_CRX_IDX 0x0298 -#define RX_DRX_IDX 0x029c - -/* - * USB_DMA_CFG - * RX_BULK_AGG_TIMEOUT: Rx Bulk Aggregation TimeOut in unit of 33ns. - * RX_BULK_AGG_LIMIT: Rx Bulk Aggregation Limit in unit of 256 bytes. - * PHY_CLEAR: phy watch dog enable. - * TX_CLEAR: Clear USB DMA TX path. - * TXOP_HALT: Halt TXOP count down when TX buffer is full. - * RX_BULK_AGG_EN: Enable Rx Bulk Aggregation. - * RX_BULK_EN: Enable USB DMA Rx. - * TX_BULK_EN: Enable USB DMA Tx. - * EP_OUT_VALID: OUT endpoint data valid. - * RX_BUSY: USB DMA RX FSM busy. - * TX_BUSY: USB DMA TX FSM busy. - */ -#define USB_DMA_CFG 0x02a0 -#define USB_DMA_CFG_RX_BULK_AGG_TIMEOUT FIELD32(0x000000ff) -#define USB_DMA_CFG_RX_BULK_AGG_LIMIT FIELD32(0x0000ff00) -#define USB_DMA_CFG_PHY_CLEAR FIELD32(0x00010000) -#define USB_DMA_CFG_TX_CLEAR FIELD32(0x00080000) -#define USB_DMA_CFG_TXOP_HALT FIELD32(0x00100000) -#define USB_DMA_CFG_RX_BULK_AGG_EN FIELD32(0x00200000) -#define USB_DMA_CFG_RX_BULK_EN FIELD32(0x00400000) -#define USB_DMA_CFG_TX_BULK_EN FIELD32(0x00800000) -#define USB_DMA_CFG_EP_OUT_VALID FIELD32(0x3f000000) -#define USB_DMA_CFG_RX_BUSY FIELD32(0x40000000) -#define USB_DMA_CFG_TX_BUSY FIELD32(0x80000000) - -/* - * USB_CYC_CFG - */ -#define USB_CYC_CFG 0x02a4 -#define USB_CYC_CFG_CLOCK_CYCLE FIELD32(0x000000ff) - -/* - * PBF_SYS_CTRL - * HOST_RAM_WRITE: enable Host program ram write selection - */ -#define PBF_SYS_CTRL 0x0400 -#define PBF_SYS_CTRL_READY FIELD32(0x00000080) -#define PBF_SYS_CTRL_HOST_RAM_WRITE FIELD32(0x00010000) - -/* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. - */ -#define PBF_CFG 0x0408 -#define PBF_MAX_PCNT 0x040c -#define PBF_CTRL 0x0410 -#define PBF_INT_STA 0x0414 -#define PBF_INT_ENA 0x0418 - -/* - * BCN_OFFSET0: - */ -#define BCN_OFFSET0 0x042c -#define BCN_OFFSET0_BCN0 FIELD32(0x000000ff) -#define BCN_OFFSET0_BCN1 FIELD32(0x0000ff00) -#define BCN_OFFSET0_BCN2 FIELD32(0x00ff0000) -#define BCN_OFFSET0_BCN3 FIELD32(0xff000000) - -/* - * BCN_OFFSET1: - */ -#define BCN_OFFSET1 0x0430 -#define BCN_OFFSET1_BCN4 FIELD32(0x000000ff) -#define BCN_OFFSET1_BCN5 FIELD32(0x0000ff00) -#define BCN_OFFSET1_BCN6 FIELD32(0x00ff0000) -#define BCN_OFFSET1_BCN7 FIELD32(0xff000000) - -/* - * PBF registers - * Most are for debug. Driver doesn't touch PBF register. - */ -#define TXRXQ_PCNT 0x0438 -#define PBF_DBG 0x043c - -/* - * RF registers - */ -#define RF_CSR_CFG 0x0500 -#define RF_CSR_CFG_DATA FIELD32(0x000000ff) -#define RF_CSR_CFG_REGNUM FIELD32(0x00001f00) -#define RF_CSR_CFG_WRITE FIELD32(0x00010000) -#define RF_CSR_CFG_BUSY FIELD32(0x00020000) - -/* - * MAC Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * MAC_CSR0: ASIC revision number. - * ASIC_REV: 0 - * ASIC_VER: 2870 - */ -#define MAC_CSR0 0x1000 -#define MAC_CSR0_ASIC_REV FIELD32(0x0000ffff) -#define MAC_CSR0_ASIC_VER FIELD32(0xffff0000) - -/* - * MAC_SYS_CTRL: - */ -#define MAC_SYS_CTRL 0x1004 -#define MAC_SYS_CTRL_RESET_CSR FIELD32(0x00000001) -#define MAC_SYS_CTRL_RESET_BBP FIELD32(0x00000002) -#define MAC_SYS_CTRL_ENABLE_TX FIELD32(0x00000004) -#define MAC_SYS_CTRL_ENABLE_RX FIELD32(0x00000008) -#define MAC_SYS_CTRL_CONTINUOUS_TX FIELD32(0x00000010) -#define MAC_SYS_CTRL_LOOPBACK FIELD32(0x00000020) -#define MAC_SYS_CTRL_WLAN_HALT FIELD32(0x00000040) -#define MAC_SYS_CTRL_RX_TIMESTAMP FIELD32(0x00000080) - -/* - * MAC_ADDR_DW0: STA MAC register 0 - */ -#define MAC_ADDR_DW0 0x1008 -#define MAC_ADDR_DW0_BYTE0 FIELD32(0x000000ff) -#define MAC_ADDR_DW0_BYTE1 FIELD32(0x0000ff00) -#define MAC_ADDR_DW0_BYTE2 FIELD32(0x00ff0000) -#define MAC_ADDR_DW0_BYTE3 FIELD32(0xff000000) - -/* - * MAC_ADDR_DW1: STA MAC register 1 - * UNICAST_TO_ME_MASK: - * Used to mask off bits from byte 5 of the MAC address - * to determine the UNICAST_TO_ME bit for RX frames. - * The full mask is complemented by BSS_ID_MASK: - * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK - */ -#define MAC_ADDR_DW1 0x100c -#define MAC_ADDR_DW1_BYTE4 FIELD32(0x000000ff) -#define MAC_ADDR_DW1_BYTE5 FIELD32(0x0000ff00) -#define MAC_ADDR_DW1_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) - -/* - * MAC_BSSID_DW0: BSSID register 0 - */ -#define MAC_BSSID_DW0 0x1010 -#define MAC_BSSID_DW0_BYTE0 FIELD32(0x000000ff) -#define MAC_BSSID_DW0_BYTE1 FIELD32(0x0000ff00) -#define MAC_BSSID_DW0_BYTE2 FIELD32(0x00ff0000) -#define MAC_BSSID_DW0_BYTE3 FIELD32(0xff000000) - -/* - * MAC_BSSID_DW1: BSSID register 1 - * BSS_ID_MASK: - * 0: 1-BSSID mode (BSS index = 0) - * 1: 2-BSSID mode (BSS index: Byte5, bit 0) - * 2: 4-BSSID mode (BSS index: byte5, bit 0 - 1) - * 3: 8-BSSID mode (BSS index: byte5, bit 0 - 2) - * This mask is used to mask off bits 0, 1 and 2 of byte 5 of the - * BSSID. This will make sure that those bits will be ignored - * when determining the MY_BSS of RX frames. - */ -#define MAC_BSSID_DW1 0x1014 -#define MAC_BSSID_DW1_BYTE4 FIELD32(0x000000ff) -#define MAC_BSSID_DW1_BYTE5 FIELD32(0x0000ff00) -#define MAC_BSSID_DW1_BSS_ID_MASK FIELD32(0x00030000) -#define MAC_BSSID_DW1_BSS_BCN_NUM FIELD32(0x001c0000) - -/* - * MAX_LEN_CFG: Maximum frame length register. - * MAX_MPDU: rt2860b max 16k bytes - * MAX_PSDU: Maximum PSDU length - * (power factor) 0:2^13, 1:2^14, 2:2^15, 3:2^16 - */ -#define MAX_LEN_CFG 0x1018 -#define MAX_LEN_CFG_MAX_MPDU FIELD32(0x00000fff) -#define MAX_LEN_CFG_MAX_PSDU FIELD32(0x00003000) -#define MAX_LEN_CFG_MIN_PSDU FIELD32(0x0000c000) -#define MAX_LEN_CFG_MIN_MPDU FIELD32(0x000f0000) - -/* - * BBP_CSR_CFG: BBP serial control register - * VALUE: Register value to program into BBP - * REG_NUM: Selected BBP register - * READ_CONTROL: 0 write BBP, 1 read BBP - * BUSY: ASIC is busy executing BBP commands - * BBP_PAR_DUR: 0 4 MAC clocks, 1 8 MAC clocks - * BBP_RW_MODE: 0 serial, 1 paralell - */ -#define BBP_CSR_CFG 0x101c -#define BBP_CSR_CFG_VALUE FIELD32(0x000000ff) -#define BBP_CSR_CFG_REGNUM FIELD32(0x0000ff00) -#define BBP_CSR_CFG_READ_CONTROL FIELD32(0x00010000) -#define BBP_CSR_CFG_BUSY FIELD32(0x00020000) -#define BBP_CSR_CFG_BBP_PAR_DUR FIELD32(0x00040000) -#define BBP_CSR_CFG_BBP_RW_MODE FIELD32(0x00080000) - -/* - * RF_CSR_CFG0: RF control register - * REGID_AND_VALUE: Register value to program into RF - * BITWIDTH: Selected RF register - * STANDBYMODE: 0 high when standby, 1 low when standby - * SEL: 0 RF_LE0 activate, 1 RF_LE1 activate - * BUSY: ASIC is busy executing RF commands - */ -#define RF_CSR_CFG0 0x1020 -#define RF_CSR_CFG0_REGID_AND_VALUE FIELD32(0x00ffffff) -#define RF_CSR_CFG0_BITWIDTH FIELD32(0x1f000000) -#define RF_CSR_CFG0_REG_VALUE_BW FIELD32(0x1fffffff) -#define RF_CSR_CFG0_STANDBYMODE FIELD32(0x20000000) -#define RF_CSR_CFG0_SEL FIELD32(0x40000000) -#define RF_CSR_CFG0_BUSY FIELD32(0x80000000) - -/* - * RF_CSR_CFG1: RF control register - * REGID_AND_VALUE: Register value to program into RF - * RFGAP: Gap between BB_CONTROL_RF and RF_LE - * 0: 3 system clock cycle (37.5usec) - * 1: 5 system clock cycle (62.5usec) - */ -#define RF_CSR_CFG1 0x1024 -#define RF_CSR_CFG1_REGID_AND_VALUE FIELD32(0x00ffffff) -#define RF_CSR_CFG1_RFGAP FIELD32(0x1f000000) - -/* - * RF_CSR_CFG2: RF control register - * VALUE: Register value to program into RF - * RFGAP: Gap between BB_CONTROL_RF and RF_LE - * 0: 3 system clock cycle (37.5usec) - * 1: 5 system clock cycle (62.5usec) - */ -#define RF_CSR_CFG2 0x1028 -#define RF_CSR_CFG2_VALUE FIELD32(0x00ffffff) - -/* - * LED_CFG: LED control - * color LED's: - * 0: off - * 1: blinking upon TX2 - * 2: periodic slow blinking - * 3: always on - * LED polarity: - * 0: active low - * 1: active high - */ -#define LED_CFG 0x102c -#define LED_CFG_ON_PERIOD FIELD32(0x000000ff) -#define LED_CFG_OFF_PERIOD FIELD32(0x0000ff00) -#define LED_CFG_SLOW_BLINK_PERIOD FIELD32(0x003f0000) -#define LED_CFG_R_LED_MODE FIELD32(0x03000000) -#define LED_CFG_G_LED_MODE FIELD32(0x0c000000) -#define LED_CFG_Y_LED_MODE FIELD32(0x30000000) -#define LED_CFG_LED_POLAR FIELD32(0x40000000) - -/* - * XIFS_TIME_CFG: MAC timing - * CCKM_SIFS_TIME: unit 1us. Applied after CCK RX/TX - * OFDM_SIFS_TIME: unit 1us. Applied after OFDM RX/TX - * OFDM_XIFS_TIME: unit 1us. Applied after OFDM RX - * when MAC doesn't reference BBP signal BBRXEND - * EIFS: unit 1us - * BB_RXEND_ENABLE: reference RXEND signal to begin XIFS defer - * - */ -#define XIFS_TIME_CFG 0x1100 -#define XIFS_TIME_CFG_CCKM_SIFS_TIME FIELD32(0x000000ff) -#define XIFS_TIME_CFG_OFDM_SIFS_TIME FIELD32(0x0000ff00) -#define XIFS_TIME_CFG_OFDM_XIFS_TIME FIELD32(0x000f0000) -#define XIFS_TIME_CFG_EIFS FIELD32(0x1ff00000) -#define XIFS_TIME_CFG_BB_RXEND_ENABLE FIELD32(0x20000000) - -/* - * BKOFF_SLOT_CFG: - */ -#define BKOFF_SLOT_CFG 0x1104 -#define BKOFF_SLOT_CFG_SLOT_TIME FIELD32(0x000000ff) -#define BKOFF_SLOT_CFG_CC_DELAY_TIME FIELD32(0x0000ff00) - -/* - * NAV_TIME_CFG: - */ -#define NAV_TIME_CFG 0x1108 -#define NAV_TIME_CFG_SIFS FIELD32(0x000000ff) -#define NAV_TIME_CFG_SLOT_TIME FIELD32(0x0000ff00) -#define NAV_TIME_CFG_EIFS FIELD32(0x01ff0000) -#define NAV_TIME_ZERO_SIFS FIELD32(0x02000000) - -/* - * CH_TIME_CFG: count as channel busy - */ -#define CH_TIME_CFG 0x110c - -/* - * PBF_LIFE_TIMER: TX/RX MPDU timestamp timer (free run) Unit: 1us - */ -#define PBF_LIFE_TIMER 0x1110 - -/* - * BCN_TIME_CFG: - * BEACON_INTERVAL: in unit of 1/16 TU - * TSF_TICKING: Enable TSF auto counting - * TSF_SYNC: Enable TSF sync, 00: disable, 01: infra mode, 10: ad-hoc mode - * BEACON_GEN: Enable beacon generator - */ -#define BCN_TIME_CFG 0x1114 -#define BCN_TIME_CFG_BEACON_INTERVAL FIELD32(0x0000ffff) -#define BCN_TIME_CFG_TSF_TICKING FIELD32(0x00010000) -#define BCN_TIME_CFG_TSF_SYNC FIELD32(0x00060000) -#define BCN_TIME_CFG_TBTT_ENABLE FIELD32(0x00080000) -#define BCN_TIME_CFG_BEACON_GEN FIELD32(0x00100000) -#define BCN_TIME_CFG_TX_TIME_COMPENSATE FIELD32(0xf0000000) - -/* - * TBTT_SYNC_CFG: - */ -#define TBTT_SYNC_CFG 0x1118 - -/* - * TSF_TIMER_DW0: Local lsb TSF timer, read-only - */ -#define TSF_TIMER_DW0 0x111c -#define TSF_TIMER_DW0_LOW_WORD FIELD32(0xffffffff) - -/* - * TSF_TIMER_DW1: Local msb TSF timer, read-only - */ -#define TSF_TIMER_DW1 0x1120 -#define TSF_TIMER_DW1_HIGH_WORD FIELD32(0xffffffff) - -/* - * TBTT_TIMER: TImer remains till next TBTT, read-only - */ -#define TBTT_TIMER 0x1124 - -/* - * INT_TIMER_CFG: - */ -#define INT_TIMER_CFG 0x1128 - -/* - * INT_TIMER_EN: GP-timer and pre-tbtt Int enable - */ -#define INT_TIMER_EN 0x112c - -/* - * CH_IDLE_STA: channel idle time - */ -#define CH_IDLE_STA 0x1130 - -/* - * CH_BUSY_STA: channel busy time - */ -#define CH_BUSY_STA 0x1134 - -/* - * MAC_STATUS_CFG: - * BBP_RF_BUSY: When set to 0, BBP and RF are stable. - * if 1 or higher one of the 2 registers is busy. - */ -#define MAC_STATUS_CFG 0x1200 -#define MAC_STATUS_CFG_BBP_RF_BUSY FIELD32(0x00000003) - -/* - * PWR_PIN_CFG: - */ -#define PWR_PIN_CFG 0x1204 - -/* - * AUTOWAKEUP_CFG: Manual power control / status register - * TBCN_BEFORE_WAKE: ForceWake has high privilege than PutToSleep when both set - * AUTOWAKE: 0:sleep, 1:awake - */ -#define AUTOWAKEUP_CFG 0x1208 -#define AUTOWAKEUP_CFG_AUTO_LEAD_TIME FIELD32(0x000000ff) -#define AUTOWAKEUP_CFG_TBCN_BEFORE_WAKE FIELD32(0x00007f00) -#define AUTOWAKEUP_CFG_AUTOWAKE FIELD32(0x00008000) - -/* - * EDCA_AC0_CFG: - */ -#define EDCA_AC0_CFG 0x1300 -#define EDCA_AC0_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC0_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC0_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC0_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_AC1_CFG: - */ -#define EDCA_AC1_CFG 0x1304 -#define EDCA_AC1_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC1_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC1_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC1_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_AC2_CFG: - */ -#define EDCA_AC2_CFG 0x1308 -#define EDCA_AC2_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC2_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC2_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC2_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_AC3_CFG: - */ -#define EDCA_AC3_CFG 0x130c -#define EDCA_AC3_CFG_TX_OP FIELD32(0x000000ff) -#define EDCA_AC3_CFG_AIFSN FIELD32(0x00000f00) -#define EDCA_AC3_CFG_CWMIN FIELD32(0x0000f000) -#define EDCA_AC3_CFG_CWMAX FIELD32(0x000f0000) - -/* - * EDCA_TID_AC_MAP: - */ -#define EDCA_TID_AC_MAP 0x1310 - -/* - * TX_PWR_CFG_0: - */ -#define TX_PWR_CFG_0 0x1314 -#define TX_PWR_CFG_0_1MBS FIELD32(0x0000000f) -#define TX_PWR_CFG_0_2MBS FIELD32(0x000000f0) -#define TX_PWR_CFG_0_55MBS FIELD32(0x00000f00) -#define TX_PWR_CFG_0_11MBS FIELD32(0x0000f000) -#define TX_PWR_CFG_0_6MBS FIELD32(0x000f0000) -#define TX_PWR_CFG_0_9MBS FIELD32(0x00f00000) -#define TX_PWR_CFG_0_12MBS FIELD32(0x0f000000) -#define TX_PWR_CFG_0_18MBS FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_1: - */ -#define TX_PWR_CFG_1 0x1318 -#define TX_PWR_CFG_1_24MBS FIELD32(0x0000000f) -#define TX_PWR_CFG_1_36MBS FIELD32(0x000000f0) -#define TX_PWR_CFG_1_48MBS FIELD32(0x00000f00) -#define TX_PWR_CFG_1_54MBS FIELD32(0x0000f000) -#define TX_PWR_CFG_1_MCS0 FIELD32(0x000f0000) -#define TX_PWR_CFG_1_MCS1 FIELD32(0x00f00000) -#define TX_PWR_CFG_1_MCS2 FIELD32(0x0f000000) -#define TX_PWR_CFG_1_MCS3 FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_2: - */ -#define TX_PWR_CFG_2 0x131c -#define TX_PWR_CFG_2_MCS4 FIELD32(0x0000000f) -#define TX_PWR_CFG_2_MCS5 FIELD32(0x000000f0) -#define TX_PWR_CFG_2_MCS6 FIELD32(0x00000f00) -#define TX_PWR_CFG_2_MCS7 FIELD32(0x0000f000) -#define TX_PWR_CFG_2_MCS8 FIELD32(0x000f0000) -#define TX_PWR_CFG_2_MCS9 FIELD32(0x00f00000) -#define TX_PWR_CFG_2_MCS10 FIELD32(0x0f000000) -#define TX_PWR_CFG_2_MCS11 FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_3: - */ -#define TX_PWR_CFG_3 0x1320 -#define TX_PWR_CFG_3_MCS12 FIELD32(0x0000000f) -#define TX_PWR_CFG_3_MCS13 FIELD32(0x000000f0) -#define TX_PWR_CFG_3_MCS14 FIELD32(0x00000f00) -#define TX_PWR_CFG_3_MCS15 FIELD32(0x0000f000) -#define TX_PWR_CFG_3_UKNOWN1 FIELD32(0x000f0000) -#define TX_PWR_CFG_3_UKNOWN2 FIELD32(0x00f00000) -#define TX_PWR_CFG_3_UKNOWN3 FIELD32(0x0f000000) -#define TX_PWR_CFG_3_UKNOWN4 FIELD32(0xf0000000) - -/* - * TX_PWR_CFG_4: - */ -#define TX_PWR_CFG_4 0x1324 -#define TX_PWR_CFG_4_UKNOWN5 FIELD32(0x0000000f) -#define TX_PWR_CFG_4_UKNOWN6 FIELD32(0x000000f0) -#define TX_PWR_CFG_4_UKNOWN7 FIELD32(0x00000f00) -#define TX_PWR_CFG_4_UKNOWN8 FIELD32(0x0000f000) - -/* - * TX_PIN_CFG: - */ -#define TX_PIN_CFG 0x1328 -#define TX_PIN_CFG_PA_PE_A0_EN FIELD32(0x00000001) -#define TX_PIN_CFG_PA_PE_G0_EN FIELD32(0x00000002) -#define TX_PIN_CFG_PA_PE_A1_EN FIELD32(0x00000004) -#define TX_PIN_CFG_PA_PE_G1_EN FIELD32(0x00000008) -#define TX_PIN_CFG_PA_PE_A0_POL FIELD32(0x00000010) -#define TX_PIN_CFG_PA_PE_G0_POL FIELD32(0x00000020) -#define TX_PIN_CFG_PA_PE_A1_POL FIELD32(0x00000040) -#define TX_PIN_CFG_PA_PE_G1_POL FIELD32(0x00000080) -#define TX_PIN_CFG_LNA_PE_A0_EN FIELD32(0x00000100) -#define TX_PIN_CFG_LNA_PE_G0_EN FIELD32(0x00000200) -#define TX_PIN_CFG_LNA_PE_A1_EN FIELD32(0x00000400) -#define TX_PIN_CFG_LNA_PE_G1_EN FIELD32(0x00000800) -#define TX_PIN_CFG_LNA_PE_A0_POL FIELD32(0x00001000) -#define TX_PIN_CFG_LNA_PE_G0_POL FIELD32(0x00002000) -#define TX_PIN_CFG_LNA_PE_A1_POL FIELD32(0x00004000) -#define TX_PIN_CFG_LNA_PE_G1_POL FIELD32(0x00008000) -#define TX_PIN_CFG_RFTR_EN FIELD32(0x00010000) -#define TX_PIN_CFG_RFTR_POL FIELD32(0x00020000) -#define TX_PIN_CFG_TRSW_EN FIELD32(0x00040000) -#define TX_PIN_CFG_TRSW_POL FIELD32(0x00080000) - -/* - * TX_BAND_CFG: 0x1 use upper 20MHz, 0x0 use lower 20MHz - */ -#define TX_BAND_CFG 0x132c -#define TX_BAND_CFG_HT40_PLUS FIELD32(0x00000001) -#define TX_BAND_CFG_A FIELD32(0x00000002) -#define TX_BAND_CFG_BG FIELD32(0x00000004) - -/* - * TX_SW_CFG0: - */ -#define TX_SW_CFG0 0x1330 - -/* - * TX_SW_CFG1: - */ -#define TX_SW_CFG1 0x1334 - -/* - * TX_SW_CFG2: - */ -#define TX_SW_CFG2 0x1338 - -/* - * TXOP_THRES_CFG: - */ -#define TXOP_THRES_CFG 0x133c - -/* - * TXOP_CTRL_CFG: - */ -#define TXOP_CTRL_CFG 0x1340 - -/* - * TX_RTS_CFG: - * RTS_THRES: unit:byte - * RTS_FBK_EN: enable rts rate fallback - */ -#define TX_RTS_CFG 0x1344 -#define TX_RTS_CFG_AUTO_RTS_RETRY_LIMIT FIELD32(0x000000ff) -#define TX_RTS_CFG_RTS_THRES FIELD32(0x00ffff00) -#define TX_RTS_CFG_RTS_FBK_EN FIELD32(0x01000000) - -/* - * TX_TIMEOUT_CFG: - * MPDU_LIFETIME: expiration time = 2^(9+MPDU LIFE TIME) us - * RX_ACK_TIMEOUT: unit:slot. Used for TX procedure - * TX_OP_TIMEOUT: TXOP timeout value for TXOP truncation. - * it is recommended that: - * (SLOT_TIME) > (TX_OP_TIMEOUT) > (RX_ACK_TIMEOUT) - */ -#define TX_TIMEOUT_CFG 0x1348 -#define TX_TIMEOUT_CFG_MPDU_LIFETIME FIELD32(0x000000f0) -#define TX_TIMEOUT_CFG_RX_ACK_TIMEOUT FIELD32(0x0000ff00) -#define TX_TIMEOUT_CFG_TX_OP_TIMEOUT FIELD32(0x00ff0000) - -/* - * TX_RTY_CFG: - * SHORT_RTY_LIMIT: short retry limit - * LONG_RTY_LIMIT: long retry limit - * LONG_RTY_THRE: Long retry threshoold - * NON_AGG_RTY_MODE: Non-Aggregate MPDU retry mode - * 0:expired by retry limit, 1: expired by mpdu life timer - * AGG_RTY_MODE: Aggregate MPDU retry mode - * 0:expired by retry limit, 1: expired by mpdu life timer - * TX_AUTO_FB_ENABLE: Tx retry PHY rate auto fallback enable - */ -#define TX_RTY_CFG 0x134c -#define TX_RTY_CFG_SHORT_RTY_LIMIT FIELD32(0x000000ff) -#define TX_RTY_CFG_LONG_RTY_LIMIT FIELD32(0x0000ff00) -#define TX_RTY_CFG_LONG_RTY_THRE FIELD32(0x0fff0000) -#define TX_RTY_CFG_NON_AGG_RTY_MODE FIELD32(0x10000000) -#define TX_RTY_CFG_AGG_RTY_MODE FIELD32(0x20000000) -#define TX_RTY_CFG_TX_AUTO_FB_ENABLE FIELD32(0x40000000) - -/* - * TX_LINK_CFG: - * REMOTE_MFB_LIFETIME: remote MFB life time. unit: 32us - * MFB_ENABLE: TX apply remote MFB 1:enable - * REMOTE_UMFS_ENABLE: remote unsolicit MFB enable - * 0: not apply remote remote unsolicit (MFS=7) - * TX_MRQ_EN: MCS request TX enable - * TX_RDG_EN: RDG TX enable - * TX_CF_ACK_EN: Piggyback CF-ACK enable - * REMOTE_MFB: remote MCS feedback - * REMOTE_MFS: remote MCS feedback sequence number - */ -#define TX_LINK_CFG 0x1350 -#define TX_LINK_CFG_REMOTE_MFB_LIFETIME FIELD32(0x000000ff) -#define TX_LINK_CFG_MFB_ENABLE FIELD32(0x00000100) -#define TX_LINK_CFG_REMOTE_UMFS_ENABLE FIELD32(0x00000200) -#define TX_LINK_CFG_TX_MRQ_EN FIELD32(0x00000400) -#define TX_LINK_CFG_TX_RDG_EN FIELD32(0x00000800) -#define TX_LINK_CFG_TX_CF_ACK_EN FIELD32(0x00001000) -#define TX_LINK_CFG_REMOTE_MFB FIELD32(0x00ff0000) -#define TX_LINK_CFG_REMOTE_MFS FIELD32(0xff000000) - -/* - * HT_FBK_CFG0: - */ -#define HT_FBK_CFG0 0x1354 -#define HT_FBK_CFG0_HTMCS0FBK FIELD32(0x0000000f) -#define HT_FBK_CFG0_HTMCS1FBK FIELD32(0x000000f0) -#define HT_FBK_CFG0_HTMCS2FBK FIELD32(0x00000f00) -#define HT_FBK_CFG0_HTMCS3FBK FIELD32(0x0000f000) -#define HT_FBK_CFG0_HTMCS4FBK FIELD32(0x000f0000) -#define HT_FBK_CFG0_HTMCS5FBK FIELD32(0x00f00000) -#define HT_FBK_CFG0_HTMCS6FBK FIELD32(0x0f000000) -#define HT_FBK_CFG0_HTMCS7FBK FIELD32(0xf0000000) - -/* - * HT_FBK_CFG1: - */ -#define HT_FBK_CFG1 0x1358 -#define HT_FBK_CFG1_HTMCS8FBK FIELD32(0x0000000f) -#define HT_FBK_CFG1_HTMCS9FBK FIELD32(0x000000f0) -#define HT_FBK_CFG1_HTMCS10FBK FIELD32(0x00000f00) -#define HT_FBK_CFG1_HTMCS11FBK FIELD32(0x0000f000) -#define HT_FBK_CFG1_HTMCS12FBK FIELD32(0x000f0000) -#define HT_FBK_CFG1_HTMCS13FBK FIELD32(0x00f00000) -#define HT_FBK_CFG1_HTMCS14FBK FIELD32(0x0f000000) -#define HT_FBK_CFG1_HTMCS15FBK FIELD32(0xf0000000) - -/* - * LG_FBK_CFG0: - */ -#define LG_FBK_CFG0 0x135c -#define LG_FBK_CFG0_OFDMMCS0FBK FIELD32(0x0000000f) -#define LG_FBK_CFG0_OFDMMCS1FBK FIELD32(0x000000f0) -#define LG_FBK_CFG0_OFDMMCS2FBK FIELD32(0x00000f00) -#define LG_FBK_CFG0_OFDMMCS3FBK FIELD32(0x0000f000) -#define LG_FBK_CFG0_OFDMMCS4FBK FIELD32(0x000f0000) -#define LG_FBK_CFG0_OFDMMCS5FBK FIELD32(0x00f00000) -#define LG_FBK_CFG0_OFDMMCS6FBK FIELD32(0x0f000000) -#define LG_FBK_CFG0_OFDMMCS7FBK FIELD32(0xf0000000) - -/* - * LG_FBK_CFG1: - */ -#define LG_FBK_CFG1 0x1360 -#define LG_FBK_CFG0_CCKMCS0FBK FIELD32(0x0000000f) -#define LG_FBK_CFG0_CCKMCS1FBK FIELD32(0x000000f0) -#define LG_FBK_CFG0_CCKMCS2FBK FIELD32(0x00000f00) -#define LG_FBK_CFG0_CCKMCS3FBK FIELD32(0x0000f000) - -/* - * CCK_PROT_CFG: CCK Protection - * PROTECT_RATE: Protection control frame rate for CCK TX(RTS/CTS/CFEnd) - * PROTECT_CTRL: Protection control frame type for CCK TX - * 0:none, 1:RTS/CTS, 2:CTS-to-self - * PROTECT_NAV: TXOP protection type for CCK TX - * 0:none, 1:ShortNAVprotect, 2:LongNAVProtect - * TX_OP_ALLOW_CCK: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_OFDM: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_MM20: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_MM40: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_GF20: CCK TXOP allowance, 0:disallow - * TX_OP_ALLOW_GF40: CCK TXOP allowance, 0:disallow - * RTS_TH_EN: RTS threshold enable on CCK TX - */ -#define CCK_PROT_CFG 0x1364 -#define CCK_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define CCK_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define CCK_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define CCK_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define CCK_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define CCK_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define CCK_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define CCK_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define CCK_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define CCK_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * OFDM_PROT_CFG: OFDM Protection - */ -#define OFDM_PROT_CFG 0x1368 -#define OFDM_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define OFDM_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define OFDM_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define OFDM_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define OFDM_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * MM20_PROT_CFG: MM20 Protection - */ -#define MM20_PROT_CFG 0x136c -#define MM20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define MM20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define MM20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define MM20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define MM20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define MM20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define MM20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define MM20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define MM20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define MM20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * MM40_PROT_CFG: MM40 Protection - */ -#define MM40_PROT_CFG 0x1370 -#define MM40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define MM40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define MM40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define MM40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define MM40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define MM40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define MM40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define MM40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define MM40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define MM40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * GF20_PROT_CFG: GF20 Protection - */ -#define GF20_PROT_CFG 0x1374 -#define GF20_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define GF20_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define GF20_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define GF20_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define GF20_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define GF20_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define GF20_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define GF20_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define GF20_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define GF20_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * GF40_PROT_CFG: GF40 Protection - */ -#define GF40_PROT_CFG 0x1378 -#define GF40_PROT_CFG_PROTECT_RATE FIELD32(0x0000ffff) -#define GF40_PROT_CFG_PROTECT_CTRL FIELD32(0x00030000) -#define GF40_PROT_CFG_PROTECT_NAV FIELD32(0x000c0000) -#define GF40_PROT_CFG_TX_OP_ALLOW_CCK FIELD32(0x00100000) -#define GF40_PROT_CFG_TX_OP_ALLOW_OFDM FIELD32(0x00200000) -#define GF40_PROT_CFG_TX_OP_ALLOW_MM20 FIELD32(0x00400000) -#define GF40_PROT_CFG_TX_OP_ALLOW_MM40 FIELD32(0x00800000) -#define GF40_PROT_CFG_TX_OP_ALLOW_GF20 FIELD32(0x01000000) -#define GF40_PROT_CFG_TX_OP_ALLOW_GF40 FIELD32(0x02000000) -#define GF40_PROT_CFG_RTS_TH_EN FIELD32(0x04000000) - -/* - * EXP_CTS_TIME: - */ -#define EXP_CTS_TIME 0x137c - -/* - * EXP_ACK_TIME: - */ -#define EXP_ACK_TIME 0x1380 - -/* - * RX_FILTER_CFG: RX configuration register. - */ -#define RX_FILTER_CFG 0x1400 -#define RX_FILTER_CFG_DROP_CRC_ERROR FIELD32(0x00000001) -#define RX_FILTER_CFG_DROP_PHY_ERROR FIELD32(0x00000002) -#define RX_FILTER_CFG_DROP_NOT_TO_ME FIELD32(0x00000004) -#define RX_FILTER_CFG_DROP_NOT_MY_BSSD FIELD32(0x00000008) -#define RX_FILTER_CFG_DROP_VER_ERROR FIELD32(0x00000010) -#define RX_FILTER_CFG_DROP_MULTICAST FIELD32(0x00000020) -#define RX_FILTER_CFG_DROP_BROADCAST FIELD32(0x00000040) -#define RX_FILTER_CFG_DROP_DUPLICATE FIELD32(0x00000080) -#define RX_FILTER_CFG_DROP_CF_END_ACK FIELD32(0x00000100) -#define RX_FILTER_CFG_DROP_CF_END FIELD32(0x00000200) -#define RX_FILTER_CFG_DROP_ACK FIELD32(0x00000400) -#define RX_FILTER_CFG_DROP_CTS FIELD32(0x00000800) -#define RX_FILTER_CFG_DROP_RTS FIELD32(0x00001000) -#define RX_FILTER_CFG_DROP_PSPOLL FIELD32(0x00002000) -#define RX_FILTER_CFG_DROP_BA FIELD32(0x00004000) -#define RX_FILTER_CFG_DROP_BAR FIELD32(0x00008000) -#define RX_FILTER_CFG_DROP_CNTL FIELD32(0x00010000) - -/* - * AUTO_RSP_CFG: - * AUTORESPONDER: 0: disable, 1: enable - * BAC_ACK_POLICY: 0:long, 1:short preamble - * CTS_40_MMODE: Response CTS 40MHz duplicate mode - * CTS_40_MREF: Response CTS 40MHz duplicate mode - * AR_PREAMBLE: Auto responder preamble 0:long, 1:short preamble - * DUAL_CTS_EN: Power bit value in control frame - * ACK_CTS_PSM_BIT:Power bit value in control frame - */ -#define AUTO_RSP_CFG 0x1404 -#define AUTO_RSP_CFG_AUTORESPONDER FIELD32(0x00000001) -#define AUTO_RSP_CFG_BAC_ACK_POLICY FIELD32(0x00000002) -#define AUTO_RSP_CFG_CTS_40_MMODE FIELD32(0x00000004) -#define AUTO_RSP_CFG_CTS_40_MREF FIELD32(0x00000008) -#define AUTO_RSP_CFG_AR_PREAMBLE FIELD32(0x00000010) -#define AUTO_RSP_CFG_DUAL_CTS_EN FIELD32(0x00000040) -#define AUTO_RSP_CFG_ACK_CTS_PSM_BIT FIELD32(0x00000080) - -/* - * LEGACY_BASIC_RATE: - */ -#define LEGACY_BASIC_RATE 0x1408 - -/* - * HT_BASIC_RATE: - */ -#define HT_BASIC_RATE 0x140c - -/* - * HT_CTRL_CFG: - */ -#define HT_CTRL_CFG 0x1410 - -/* - * SIFS_COST_CFG: - */ -#define SIFS_COST_CFG 0x1414 - -/* - * RX_PARSER_CFG: - * Set NAV for all received frames - */ -#define RX_PARSER_CFG 0x1418 - -/* - * TX_SEC_CNT0: - */ -#define TX_SEC_CNT0 0x1500 - -/* - * RX_SEC_CNT0: - */ -#define RX_SEC_CNT0 0x1504 - -/* - * CCMP_FC_MUTE: - */ -#define CCMP_FC_MUTE 0x1508 - -/* - * TXOP_HLDR_ADDR0: - */ -#define TXOP_HLDR_ADDR0 0x1600 - -/* - * TXOP_HLDR_ADDR1: - */ -#define TXOP_HLDR_ADDR1 0x1604 - -/* - * TXOP_HLDR_ET: - */ -#define TXOP_HLDR_ET 0x1608 - -/* - * QOS_CFPOLL_RA_DW0: - */ -#define QOS_CFPOLL_RA_DW0 0x160c - -/* - * QOS_CFPOLL_RA_DW1: - */ -#define QOS_CFPOLL_RA_DW1 0x1610 - -/* - * QOS_CFPOLL_QC: - */ -#define QOS_CFPOLL_QC 0x1614 - -/* - * RX_STA_CNT0: RX PLCP error count & RX CRC error count - */ -#define RX_STA_CNT0 0x1700 -#define RX_STA_CNT0_CRC_ERR FIELD32(0x0000ffff) -#define RX_STA_CNT0_PHY_ERR FIELD32(0xffff0000) - -/* - * RX_STA_CNT1: RX False CCA count & RX LONG frame count - */ -#define RX_STA_CNT1 0x1704 -#define RX_STA_CNT1_FALSE_CCA FIELD32(0x0000ffff) -#define RX_STA_CNT1_PLCP_ERR FIELD32(0xffff0000) - -/* - * RX_STA_CNT2: - */ -#define RX_STA_CNT2 0x1708 -#define RX_STA_CNT2_RX_DUPLI_COUNT FIELD32(0x0000ffff) -#define RX_STA_CNT2_RX_FIFO_OVERFLOW FIELD32(0xffff0000) - -/* - * TX_STA_CNT0: TX Beacon count - */ -#define TX_STA_CNT0 0x170c -#define TX_STA_CNT0_TX_FAIL_COUNT FIELD32(0x0000ffff) -#define TX_STA_CNT0_TX_BEACON_COUNT FIELD32(0xffff0000) - -/* - * TX_STA_CNT1: TX tx count - */ -#define TX_STA_CNT1 0x1710 -#define TX_STA_CNT1_TX_SUCCESS FIELD32(0x0000ffff) -#define TX_STA_CNT1_TX_RETRANSMIT FIELD32(0xffff0000) - -/* - * TX_STA_CNT2: TX tx count - */ -#define TX_STA_CNT2 0x1714 -#define TX_STA_CNT2_TX_ZERO_LEN_COUNT FIELD32(0x0000ffff) -#define TX_STA_CNT2_TX_UNDER_FLOW_COUNT FIELD32(0xffff0000) - -/* - * TX_STA_FIFO: TX Result for specific PID status fifo register - */ -#define TX_STA_FIFO 0x1718 -#define TX_STA_FIFO_VALID FIELD32(0x00000001) -#define TX_STA_FIFO_PID_TYPE FIELD32(0x0000001e) -#define TX_STA_FIFO_TX_SUCCESS FIELD32(0x00000020) -#define TX_STA_FIFO_TX_AGGRE FIELD32(0x00000040) -#define TX_STA_FIFO_TX_ACK_REQUIRED FIELD32(0x00000080) -#define TX_STA_FIFO_WCID FIELD32(0x0000ff00) -#define TX_STA_FIFO_SUCCESS_RATE FIELD32(0xffff0000) - -/* - * TX_AGG_CNT: Debug counter - */ -#define TX_AGG_CNT 0x171c -#define TX_AGG_CNT_NON_AGG_TX_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT_AGG_TX_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT0: - */ -#define TX_AGG_CNT0 0x1720 -#define TX_AGG_CNT0_AGG_SIZE_1_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT0_AGG_SIZE_2_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT1: - */ -#define TX_AGG_CNT1 0x1724 -#define TX_AGG_CNT1_AGG_SIZE_3_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT1_AGG_SIZE_4_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT2: - */ -#define TX_AGG_CNT2 0x1728 -#define TX_AGG_CNT2_AGG_SIZE_5_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT2_AGG_SIZE_6_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT3: - */ -#define TX_AGG_CNT3 0x172c -#define TX_AGG_CNT3_AGG_SIZE_7_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT3_AGG_SIZE_8_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT4: - */ -#define TX_AGG_CNT4 0x1730 -#define TX_AGG_CNT4_AGG_SIZE_9_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT4_AGG_SIZE_10_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT5: - */ -#define TX_AGG_CNT5 0x1734 -#define TX_AGG_CNT5_AGG_SIZE_11_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT5_AGG_SIZE_12_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT6: - */ -#define TX_AGG_CNT6 0x1738 -#define TX_AGG_CNT6_AGG_SIZE_13_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT6_AGG_SIZE_14_COUNT FIELD32(0xffff0000) - -/* - * TX_AGG_CNT7: - */ -#define TX_AGG_CNT7 0x173c -#define TX_AGG_CNT7_AGG_SIZE_15_COUNT FIELD32(0x0000ffff) -#define TX_AGG_CNT7_AGG_SIZE_16_COUNT FIELD32(0xffff0000) - -/* - * MPDU_DENSITY_CNT: - * TX_ZERO_DEL: TX zero length delimiter count - * RX_ZERO_DEL: RX zero length delimiter count - */ -#define MPDU_DENSITY_CNT 0x1740 -#define MPDU_DENSITY_CNT_TX_ZERO_DEL FIELD32(0x0000ffff) -#define MPDU_DENSITY_CNT_RX_ZERO_DEL FIELD32(0xffff0000) - -/* - * Security key table memory. - * MAC_WCID_BASE: 8-bytes (use only 6 bytes) * 256 entry - * PAIRWISE_KEY_TABLE_BASE: 32-byte * 256 entry - * MAC_IVEIV_TABLE_BASE: 8-byte * 256-entry - * MAC_WCID_ATTRIBUTE_BASE: 4-byte * 256-entry - * SHARED_KEY_TABLE_BASE: 32 bytes * 32-entry - * SHARED_KEY_MODE_BASE: 4 bits * 32-entry - */ -#define MAC_WCID_BASE 0x1800 -#define PAIRWISE_KEY_TABLE_BASE 0x4000 -#define MAC_IVEIV_TABLE_BASE 0x6000 -#define MAC_WCID_ATTRIBUTE_BASE 0x6800 -#define SHARED_KEY_TABLE_BASE 0x6c00 -#define SHARED_KEY_MODE_BASE 0x7000 - -#define MAC_WCID_ENTRY(__idx) \ - ( MAC_WCID_BASE + ((__idx) * sizeof(struct mac_wcid_entry)) ) -#define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) -#define MAC_IVEIV_ENTRY(__idx) \ - ( MAC_IVEIV_TABLE_BASE + ((__idx) & sizeof(struct mac_iveiv_entry)) ) -#define MAC_WCID_ATTR_ENTRY(__idx) \ - ( MAC_WCID_ATTRIBUTE_BASE + ((__idx) * sizeof(u32)) ) -#define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + ((__idx) * sizeof(struct hw_key_entry)) ) -#define SHARED_KEY_MODE_ENTRY(__idx) \ - ( SHARED_KEY_MODE_BASE + ((__idx) * sizeof(u32)) ) - -struct mac_wcid_entry { - u8 mac[6]; - u8 reserved[2]; -} __attribute__ ((packed)); - -struct hw_key_entry { - u8 key[16]; - u8 tx_mic[8]; - u8 rx_mic[8]; -} __attribute__ ((packed)); - -struct mac_iveiv_entry { - u8 iv[8]; -} __attribute__ ((packed)); - -/* - * MAC_WCID_ATTRIBUTE: - */ -#define MAC_WCID_ATTRIBUTE_KEYTAB FIELD32(0x00000001) -#define MAC_WCID_ATTRIBUTE_CIPHER FIELD32(0x0000000e) -#define MAC_WCID_ATTRIBUTE_BSS_IDX FIELD32(0x00000070) -#define MAC_WCID_ATTRIBUTE_RX_WIUDF FIELD32(0x00000380) - -/* - * SHARED_KEY_MODE: - */ -#define SHARED_KEY_MODE_BSS0_KEY0 FIELD32(0x00000007) -#define SHARED_KEY_MODE_BSS0_KEY1 FIELD32(0x00000070) -#define SHARED_KEY_MODE_BSS0_KEY2 FIELD32(0x00000700) -#define SHARED_KEY_MODE_BSS0_KEY3 FIELD32(0x00007000) -#define SHARED_KEY_MODE_BSS1_KEY0 FIELD32(0x00070000) -#define SHARED_KEY_MODE_BSS1_KEY1 FIELD32(0x00700000) -#define SHARED_KEY_MODE_BSS1_KEY2 FIELD32(0x07000000) -#define SHARED_KEY_MODE_BSS1_KEY3 FIELD32(0x70000000) - -/* - * HOST-MCU communication - */ - -/* - * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. - */ -#define H2M_MAILBOX_CSR 0x7010 -#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) -#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) -#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) -#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) - -/* - * H2M_MAILBOX_CID: - */ -#define H2M_MAILBOX_CID 0x7014 -#define H2M_MAILBOX_CID_CMD0 FIELD32(0x000000ff) -#define H2M_MAILBOX_CID_CMD1 FIELD32(0x0000ff00) -#define H2M_MAILBOX_CID_CMD2 FIELD32(0x00ff0000) -#define H2M_MAILBOX_CID_CMD3 FIELD32(0xff000000) - -/* - * H2M_MAILBOX_STATUS: - */ -#define H2M_MAILBOX_STATUS 0x701c - -/* - * H2M_INT_SRC: - */ -#define H2M_INT_SRC 0x7024 - -/* - * H2M_BBP_AGENT: - */ -#define H2M_BBP_AGENT 0x7028 - -/* - * MCU_LEDCS: LED control for MCU Mailbox. - */ -#define MCU_LEDCS_LED_MODE FIELD8(0x1f) -#define MCU_LEDCS_POLARITY FIELD8(0x01) - -/* - * HW_CS_CTS_BASE: - * Carrier-sense CTS frame base address. - * It's where mac stores carrier-sense frame for carrier-sense function. - */ -#define HW_CS_CTS_BASE 0x7700 - -/* - * HW_DFS_CTS_BASE: - * FS CTS frame base address. It's where mac stores CTS frame for DFS. - */ -#define HW_DFS_CTS_BASE 0x7780 - -/* - * TXRX control registers - base address 0x3000 - */ - -/* - * TXRX_CSR1: - * rt2860b UNKNOWN reg use R/O Reg Addr 0x77d0 first.. - */ -#define TXRX_CSR1 0x77d0 - -/* - * HW_DEBUG_SETTING_BASE: - * since NULL frame won't be that long (256 byte) - * We steal 16 tail bytes to save debugging settings - */ -#define HW_DEBUG_SETTING_BASE 0x77f0 -#define HW_DEBUG_SETTING_BASE2 0x7770 - -/* - * HW_BEACON_BASE - * In order to support maximum 8 MBSS and its maximum length - * is 512 bytes for each beacon - * Three section discontinue memory segments will be used. - * 1. The original region for BCN 0~3 - * 2. Extract memory from FCE table for BCN 4~5 - * 3. Extract memory from Pair-wise key table for BCN 6~7 - * It occupied those memory of wcid 238~253 for BCN 6 - * and wcid 222~237 for BCN 7 - * - * IMPORTANT NOTE: Not sure why legacy driver does this, - * but HW_BEACON_BASE7 is 0x0200 bytes below HW_BEACON_BASE6. - */ -#define HW_BEACON_BASE0 0x7800 -#define HW_BEACON_BASE1 0x7a00 -#define HW_BEACON_BASE2 0x7c00 -#define HW_BEACON_BASE3 0x7e00 -#define HW_BEACON_BASE4 0x7200 -#define HW_BEACON_BASE5 0x7400 -#define HW_BEACON_BASE6 0x5dc0 -#define HW_BEACON_BASE7 0x5bc0 - -#define HW_BEACON_OFFSET(__index) \ - ( ((__index) < 4) ? ( HW_BEACON_BASE0 + (__index * 0x0200) ) : \ - (((__index) < 6) ? ( HW_BEACON_BASE4 + ((__index - 4) * 0x0200) ) : \ - (HW_BEACON_BASE6 - ((__index - 6) * 0x0200))) ) - -/* - * 8051 firmware image. - */ -#define FIRMWARE_RT2870 "rt2870.bin" -#define FIRMWARE_IMAGE_BASE 0x3000 - -/* - * BBP registers. - * The wordsize of the BBP is 8 bits. - */ - -/* - * BBP 1: TX Antenna - */ -#define BBP1_TX_POWER FIELD8(0x07) -#define BBP1_TX_ANTENNA FIELD8(0x18) - -/* - * BBP 3: RX Antenna - */ -#define BBP3_RX_ANTENNA FIELD8(0x18) -#define BBP3_HT40_PLUS FIELD8(0x20) - -/* - * BBP 4: Bandwidth - */ -#define BBP4_TX_BF FIELD8(0x01) -#define BBP4_BANDWIDTH FIELD8(0x18) - -/* - * RFCSR registers - * The wordsize of the RFCSR is 8 bits. - */ - -/* - * RFCSR 6: - */ -#define RFCSR6_R FIELD8(0x03) - -/* - * RFCSR 7: - */ -#define RFCSR7_RF_TUNING FIELD8(0x01) - -/* - * RFCSR 12: - */ -#define RFCSR12_TX_POWER FIELD8(0x1f) - -/* - * RFCSR 22: - */ -#define RFCSR22_BASEBAND_LOOPBACK FIELD8(0x01) - -/* - * RFCSR 23: - */ -#define RFCSR23_FREQ_OFFSET FIELD8(0x7f) - -/* - * RFCSR 30: - */ -#define RFCSR30_RF_CALIBRATION FIELD8(0x80) - -/* - * RF registers - */ - -/* - * RF 2 - */ -#define RF2_ANTENNA_RX2 FIELD32(0x00000040) -#define RF2_ANTENNA_TX1 FIELD32(0x00004000) -#define RF2_ANTENNA_RX1 FIELD32(0x00020000) - -/* - * RF 3 - */ -#define RF3_TXPOWER_G FIELD32(0x00003e00) -#define RF3_TXPOWER_A_7DBM_BOOST FIELD32(0x00000200) -#define RF3_TXPOWER_A FIELD32(0x00003c00) - -/* - * RF 4 - */ -#define RF4_TXPOWER_G FIELD32(0x000007c0) -#define RF4_TXPOWER_A_7DBM_BOOST FIELD32(0x00000040) -#define RF4_TXPOWER_A FIELD32(0x00000780) -#define RF4_FREQ_OFFSET FIELD32(0x001f8000) -#define RF4_HT40 FIELD32(0x00200000) - -/* - * EEPROM content. - * The wordsize of the EEPROM is 16 bits. - */ - -/* - * EEPROM Version - */ -#define EEPROM_VERSION 0x0001 -#define EEPROM_VERSION_FAE FIELD16(0x00ff) -#define EEPROM_VERSION_VERSION FIELD16(0xff00) - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM ANTENNA config - * RXPATH: 1: 1R, 2: 2R, 3: 3R - * TXPATH: 1: 1T, 2: 2T - */ -#define EEPROM_ANTENNA 0x001a -#define EEPROM_ANTENNA_RXPATH FIELD16(0x000f) -#define EEPROM_ANTENNA_TXPATH FIELD16(0x00f0) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0x0f00) - -/* - * EEPROM NIC config - * CARDBUS_ACCEL: 0 - enable, 1 - disable - */ -#define EEPROM_NIC 0x001b -#define EEPROM_NIC_HW_RADIO FIELD16(0x0001) -#define EEPROM_NIC_DYNAMIC_TX_AGC FIELD16(0x0002) -#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0004) -#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0008) -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0010) -#define EEPROM_NIC_BW40M_SB_BG FIELD16(0x0020) -#define EEPROM_NIC_BW40M_SB_A FIELD16(0x0040) -#define EEPROM_NIC_WPS_PBC FIELD16(0x0080) -#define EEPROM_NIC_BW40M_BG FIELD16(0x0100) -#define EEPROM_NIC_BW40M_A FIELD16(0x0200) - -/* - * EEPROM frequency - */ -#define EEPROM_FREQ 0x001d -#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) -#define EEPROM_FREQ_LED_MODE FIELD16(0x7f00) -#define EEPROM_FREQ_LED_POLARITY FIELD16(0x1000) - -/* - * EEPROM LED - * POLARITY_RDY_G: Polarity RDY_G setting. - * POLARITY_RDY_A: Polarity RDY_A setting. - * POLARITY_ACT: Polarity ACT setting. - * POLARITY_GPIO_0: Polarity GPIO0 setting. - * POLARITY_GPIO_1: Polarity GPIO1 setting. - * POLARITY_GPIO_2: Polarity GPIO2 setting. - * POLARITY_GPIO_3: Polarity GPIO3 setting. - * POLARITY_GPIO_4: Polarity GPIO4 setting. - * LED_MODE: Led mode. - */ -#define EEPROM_LED1 0x001e -#define EEPROM_LED2 0x001f -#define EEPROM_LED3 0x0020 -#define EEPROM_LED_POLARITY_RDY_BG FIELD16(0x0001) -#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) -#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) -#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) -#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) -#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) -#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) -#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) -#define EEPROM_LED_LED_MODE FIELD16(0x1f00) - -/* - * EEPROM LNA - */ -#define EEPROM_LNA 0x0022 -#define EEPROM_LNA_BG FIELD16(0x00ff) -#define EEPROM_LNA_A0 FIELD16(0xff00) - -/* - * EEPROM RSSI BG offset - */ -#define EEPROM_RSSI_BG 0x0023 -#define EEPROM_RSSI_BG_OFFSET0 FIELD16(0x00ff) -#define EEPROM_RSSI_BG_OFFSET1 FIELD16(0xff00) - -/* - * EEPROM RSSI BG2 offset - */ -#define EEPROM_RSSI_BG2 0x0024 -#define EEPROM_RSSI_BG2_OFFSET2 FIELD16(0x00ff) -#define EEPROM_RSSI_BG2_LNA_A1 FIELD16(0xff00) - -/* - * EEPROM RSSI A offset - */ -#define EEPROM_RSSI_A 0x0025 -#define EEPROM_RSSI_A_OFFSET0 FIELD16(0x00ff) -#define EEPROM_RSSI_A_OFFSET1 FIELD16(0xff00) - -/* - * EEPROM RSSI A2 offset - */ -#define EEPROM_RSSI_A2 0x0026 -#define EEPROM_RSSI_A2_OFFSET2 FIELD16(0x00ff) -#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) - -/* - * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. - * This is delta in 40MHZ. - * VALUE: Tx Power dalta value (MAX=4) - * TYPE: 1: Plus the delta value, 0: minus the delta value - * TXPOWER: Enable: - */ -#define EEPROM_TXPOWER_DELTA 0x0028 -#define EEPROM_TXPOWER_DELTA_VALUE FIELD16(0x003f) -#define EEPROM_TXPOWER_DELTA_TYPE FIELD16(0x0040) -#define EEPROM_TXPOWER_DELTA_TXPOWER FIELD16(0x0080) - -/* - * EEPROM TXPOWER 802.11BG - */ -#define EEPROM_TXPOWER_BG1 0x0029 -#define EEPROM_TXPOWER_BG2 0x0030 -#define EEPROM_TXPOWER_BG_SIZE 7 -#define EEPROM_TXPOWER_BG_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_BG_2 FIELD16(0xff00) - -/* - * EEPROM TXPOWER 802.11A - */ -#define EEPROM_TXPOWER_A1 0x003c -#define EEPROM_TXPOWER_A2 0x0053 -#define EEPROM_TXPOWER_A_SIZE 6 -#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) - -/* - * EEPROM TXpower byrate: 20MHZ power - */ -#define EEPROM_TXPOWER_BYRATE 0x006f - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x0078 -#define EEPROM_BBP_SIZE 16 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * MCU mailbox commands. - */ -#define MCU_SLEEP 0x30 -#define MCU_WAKEUP 0x31 -#define MCU_RADIO_OFF 0x35 -#define MCU_CURRENT 0x36 -#define MCU_LED 0x50 -#define MCU_LED_STRENGTH 0x51 -#define MCU_LED_1 0x52 -#define MCU_LED_2 0x53 -#define MCU_LED_3 0x54 -#define MCU_RADAR 0x60 -#define MCU_BOOT_SIGNAL 0x72 -#define MCU_BBP_SIGNAL 0x80 -#define MCU_POWER_SAVE 0x83 - -/* - * MCU mailbox tokens - */ -#define TOKEN_WAKUP 3 - -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE ( 4 * sizeof(__le32) ) -#define TXINFO_DESC_SIZE ( 1 * sizeof(__le32) ) -#define TXWI_DESC_SIZE ( 4 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 1 * sizeof(__le32) ) -#define RXWI_DESC_SIZE ( 4 * sizeof(__le32) ) - -/* - * TX descriptor format for TX, PRIO and Beacon Ring. - */ - -/* - * Word0 - */ -#define TXD_W0_SD_PTR0 FIELD32(0xffffffff) - -/* - * Word1 - */ -#define TXD_W1_SD_LEN1 FIELD32(0x00003fff) -#define TXD_W1_LAST_SEC1 FIELD32(0x00004000) -#define TXD_W1_BURST FIELD32(0x00008000) -#define TXD_W1_SD_LEN0 FIELD32(0x3fff0000) -#define TXD_W1_LAST_SEC0 FIELD32(0x40000000) -#define TXD_W1_DMA_DONE FIELD32(0x80000000) - -/* - * Word2 - */ -#define TXD_W2_SD_PTR1 FIELD32(0xffffffff) - -/* - * Word3 - * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI - * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. - * 0:MGMT, 1:HCCA 2:EDCA - */ -#define TXD_W3_WIV FIELD32(0x01000000) -#define TXD_W3_QSEL FIELD32(0x06000000) -#define TXD_W3_TCO FIELD32(0x20000000) -#define TXD_W3_UCO FIELD32(0x40000000) -#define TXD_W3_ICO FIELD32(0x80000000) - -/* - * TX Info structure - */ - -/* - * Word0 - * WIV: Wireless Info Valid. 1: Driver filled WI, 0: DMA needs to copy WI - * QSEL: Select on-chip FIFO ID for 2nd-stage output scheduler. - * 0:MGMT, 1:HCCA 2:EDCA - * USB_DMA_NEXT_VALID: Used ONLY in USB bulk Aggregation, NextValid - * DMA_TX_BURST: used ONLY in USB bulk Aggregation. - * Force USB DMA transmit frame from current selected endpoint - */ -#define TXINFO_W0_USB_DMA_TX_PKT_LEN FIELD32(0x0000ffff) -#define TXINFO_W0_WIV FIELD32(0x01000000) -#define TXINFO_W0_QSEL FIELD32(0x06000000) -#define TXINFO_W0_SW_USE_LAST_ROUND FIELD32(0x08000000) -#define TXINFO_W0_USB_DMA_NEXT_VALID FIELD32(0x40000000) -#define TXINFO_W0_USB_DMA_TX_BURST FIELD32(0x80000000) - -/* - * TX WI structure - */ - -/* - * Word0 - * FRAG: 1 To inform TKIP engine this is a fragment. - * MIMO_PS: The remote peer is in dynamic MIMO-PS mode - * TX_OP: 0:HT TXOP rule , 1:PIFS TX ,2:Backoff, 3:sifs - * BW: Channel bandwidth 20MHz or 40 MHz - * STBC: 1: STBC support MCS =0-7, 2,3 : RESERVED - */ -#define TXWI_W0_FRAG FIELD32(0x00000001) -#define TXWI_W0_MIMO_PS FIELD32(0x00000002) -#define TXWI_W0_CF_ACK FIELD32(0x00000004) -#define TXWI_W0_TS FIELD32(0x00000008) -#define TXWI_W0_AMPDU FIELD32(0x00000010) -#define TXWI_W0_MPDU_DENSITY FIELD32(0x000000e0) -#define TXWI_W0_TX_OP FIELD32(0x00000300) -#define TXWI_W0_MCS FIELD32(0x007f0000) -#define TXWI_W0_BW FIELD32(0x00800000) -#define TXWI_W0_SHORT_GI FIELD32(0x01000000) -#define TXWI_W0_STBC FIELD32(0x06000000) -#define TXWI_W0_IFS FIELD32(0x08000000) -#define TXWI_W0_PHYMODE FIELD32(0xc0000000) - -/* - * Word1 - */ -#define TXWI_W1_ACK FIELD32(0x00000001) -#define TXWI_W1_NSEQ FIELD32(0x00000002) -#define TXWI_W1_BW_WIN_SIZE FIELD32(0x000000fc) -#define TXWI_W1_WIRELESS_CLI_ID FIELD32(0x0000ff00) -#define TXWI_W1_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) -#define TXWI_W1_PACKETID FIELD32(0xf0000000) - -/* - * Word2 - */ -#define TXWI_W2_IV FIELD32(0xffffffff) - -/* - * Word3 - */ -#define TXWI_W3_EIV FIELD32(0xffffffff) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - * UNICAST_TO_ME: This RX frame is unicast to me. - * MULTICAST: This is a multicast frame. - * BROADCAST: This is a broadcast frame. - * MY_BSS: this frame belongs to the same BSSID. - * CRC_ERROR: CRC error. - * CIPHER_ERROR: 0: decryption okay, 1:ICV error, 2:MIC error, 3:KEY not valid. - * AMSDU: rx with 802.3 header, not 802.11 header. - */ - -#define RXD_W0_BA FIELD32(0x00000001) -#define RXD_W0_DATA FIELD32(0x00000002) -#define RXD_W0_NULLDATA FIELD32(0x00000004) -#define RXD_W0_FRAG FIELD32(0x00000008) -#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000010) -#define RXD_W0_MULTICAST FIELD32(0x00000020) -#define RXD_W0_BROADCAST FIELD32(0x00000040) -#define RXD_W0_MY_BSS FIELD32(0x00000080) -#define RXD_W0_CRC_ERROR FIELD32(0x00000100) -#define RXD_W0_CIPHER_ERROR FIELD32(0x00000600) -#define RXD_W0_AMSDU FIELD32(0x00000800) -#define RXD_W0_HTC FIELD32(0x00001000) -#define RXD_W0_RSSI FIELD32(0x00002000) -#define RXD_W0_L2PAD FIELD32(0x00004000) -#define RXD_W0_AMPDU FIELD32(0x00008000) -#define RXD_W0_DECRYPTED FIELD32(0x00010000) -#define RXD_W0_PLCP_RSSI FIELD32(0x00020000) -#define RXD_W0_CIPHER_ALG FIELD32(0x00040000) -#define RXD_W0_LAST_AMSDU FIELD32(0x00080000) -#define RXD_W0_PLCP_SIGNAL FIELD32(0xfff00000) - -/* - * RX WI structure - */ - -/* - * Word0 - */ -#define RXWI_W0_WIRELESS_CLI_ID FIELD32(0x000000ff) -#define RXWI_W0_KEY_INDEX FIELD32(0x00000300) -#define RXWI_W0_BSSID FIELD32(0x00001c00) -#define RXWI_W0_UDF FIELD32(0x0000e000) -#define RXWI_W0_MPDU_TOTAL_BYTE_COUNT FIELD32(0x0fff0000) -#define RXWI_W0_TID FIELD32(0xf0000000) - -/* - * Word1 - */ -#define RXWI_W1_FRAG FIELD32(0x0000000f) -#define RXWI_W1_SEQUENCE FIELD32(0x0000fff0) -#define RXWI_W1_MCS FIELD32(0x007f0000) -#define RXWI_W1_BW FIELD32(0x00800000) -#define RXWI_W1_SHORT_GI FIELD32(0x01000000) -#define RXWI_W1_STBC FIELD32(0x06000000) -#define RXWI_W1_PHYMODE FIELD32(0xc0000000) - -/* - * Word2 - */ -#define RXWI_W2_RSSI0 FIELD32(0x000000ff) -#define RXWI_W2_RSSI1 FIELD32(0x0000ff00) -#define RXWI_W2_RSSI2 FIELD32(0x00ff0000) - -/* - * Word3 - */ -#define RXWI_W3_SNR0 FIELD32(0x000000ff) -#define RXWI_W3_SNR1 FIELD32(0x0000ff00) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - */ -#define MIN_G_TXPOWER 0 -#define MIN_A_TXPOWER -7 -#define MAX_G_TXPOWER 31 -#define MAX_A_TXPOWER 15 -#define DEFAULT_TXPOWER 5 - -#define TXPOWER_G_FROM_DEV(__txpower) \ - ((__txpower) > MAX_G_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_G_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_G_TXPOWER, MAX_G_TXPOWER) - -#define TXPOWER_A_FROM_DEV(__txpower) \ - ((__txpower) > MAX_A_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_A_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER) - -#endif /* RT2800USB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h deleted file mode 100644 index 27bc6b7fbfde..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ /dev/null @@ -1,1006 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 global information. - */ - -#ifndef RT2X00_H -#define RT2X00_H - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "rt2x00debug.h" -#include "rt2x00leds.h" -#include "rt2x00reg.h" -#include "rt2x00queue.h" - -/* - * Module information. - */ -#define DRV_VERSION "2.3.0" -#define DRV_PROJECT "http://rt2x00.serialmonkey.com" - -/* - * Debug definitions. - * Debug output has to be enabled during compile time. - */ -#define DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, __args...) \ - printk(__kernlvl "%s -> %s: %s - " __msg, \ - wiphy_name((__dev)->hw->wiphy), __func__, __lvl, ##__args) - -#define DEBUG_PRINTK_PROBE(__kernlvl, __lvl, __msg, __args...) \ - printk(__kernlvl "%s -> %s: %s - " __msg, \ - KBUILD_MODNAME, __func__, __lvl, ##__args) - -#ifdef CONFIG_RT2X00_DEBUG -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, __kernlvl, __lvl, __msg, ##__args); -#else -#define DEBUG_PRINTK(__dev, __kernlvl, __lvl, __msg, __args...) \ - do { } while (0) -#endif /* CONFIG_RT2X00_DEBUG */ - -/* - * Various debug levels. - * The debug levels PANIC and ERROR both indicate serious problems, - * for this reason they should never be ignored. - * The special ERROR_PROBE message is for messages that are generated - * when the rt2x00_dev is not yet initialized. - */ -#define PANIC(__dev, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, KERN_CRIT, "Panic", __msg, ##__args) -#define ERROR(__dev, __msg, __args...) \ - DEBUG_PRINTK_MSG(__dev, KERN_ERR, "Error", __msg, ##__args) -#define ERROR_PROBE(__msg, __args...) \ - DEBUG_PRINTK_PROBE(KERN_ERR, "Error", __msg, ##__args) -#define WARNING(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_WARNING, "Warning", __msg, ##__args) -#define NOTICE(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_NOTICE, "Notice", __msg, ##__args) -#define INFO(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_INFO, "Info", __msg, ##__args) -#define DEBUG(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_DEBUG, "Debug", __msg, ##__args) -#define EEPROM(__dev, __msg, __args...) \ - DEBUG_PRINTK(__dev, KERN_DEBUG, "EEPROM recovery", __msg, ##__args) - -/* - * Duration calculations - * The rate variable passed is: 100kbs. - * To convert from bytes to bits we multiply size with 8, - * then the size is multiplied with 10 to make the - * real rate -> rate argument correction. - */ -#define GET_DURATION(__size, __rate) (((__size) * 8 * 10) / (__rate)) -#define GET_DURATION_RES(__size, __rate)(((__size) * 8 * 10) % (__rate)) - -/* - * Determine the alignment requirement, - * to make sure the 802.11 payload is padded to a 4-byte boundrary - * we must determine the address of the payload and calculate the - * amount of bytes needed to move the data. - */ -#define ALIGN_SIZE(__skb, __header) \ - ( ((unsigned long)((__skb)->data + (__header))) & 3 ) - -/* - * Standard timing and size defines. - * These values should follow the ieee80211 specifications. - */ -#define ACK_SIZE 14 -#define IEEE80211_HEADER 24 -#define PLCP 48 -#define BEACON 100 -#define PREAMBLE 144 -#define SHORT_PREAMBLE 72 -#define SLOT_TIME 20 -#define SHORT_SLOT_TIME 9 -#define SIFS 10 -#define PIFS ( SIFS + SLOT_TIME ) -#define SHORT_PIFS ( SIFS + SHORT_SLOT_TIME ) -#define DIFS ( PIFS + SLOT_TIME ) -#define SHORT_DIFS ( SHORT_PIFS + SHORT_SLOT_TIME ) -#define EIFS ( SIFS + DIFS + \ - GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) -#define SHORT_EIFS ( SIFS + SHORT_DIFS + \ - GET_DURATION(IEEE80211_HEADER + ACK_SIZE, 10) ) - -/* - * Structure for average calculation - * The avg field contains the actual average value, - * but avg_weight is internally used during calculations - * to prevent rounding errors. - */ -struct avg_val { - int avg; - int avg_weight; -}; - -/* - * Chipset identification - * The chipset on the device is composed of a RT and RF chip. - * The chipset combination is important for determining device capabilities. - */ -struct rt2x00_chip { - u16 rt; -#define RT2460 0x0101 -#define RT2560 0x0201 -#define RT2570 0x1201 -#define RT2561s 0x0301 /* Turbo */ -#define RT2561 0x0302 -#define RT2661 0x0401 -#define RT2571 0x1300 -#define RT2870 0x1600 - - u16 rf; - u32 rev; -}; - -/* - * RF register values that belong to a particular channel. - */ -struct rf_channel { - int channel; - u32 rf1; - u32 rf2; - u32 rf3; - u32 rf4; -}; - -/* - * Channel information structure - */ -struct channel_info { - unsigned int flags; -#define GEOGRAPHY_ALLOWED 0x00000001 - - short tx_power1; - short tx_power2; -}; - -/* - * Antenna setup values. - */ -struct antenna_setup { - enum antenna rx; - enum antenna tx; -}; - -/* - * Quality statistics about the currently active link. - */ -struct link_qual { - /* - * Statistics required for Link tuning by driver - * The rssi value is provided by rt2x00lib during the - * link_tuner() callback function. - * The false_cca field is filled during the link_stats() - * callback function and could be used during the - * link_tuner() callback function. - */ - int rssi; - int false_cca; - - /* - * VGC levels - * Hardware driver will tune the VGC level during each call - * to the link_tuner() callback function. This vgc_level is - * is determined based on the link quality statistics like - * average RSSI and the false CCA count. - * - * In some cases the drivers need to differentiate between - * the currently "desired" VGC level and the level configured - * in the hardware. The latter is important to reduce the - * number of BBP register reads to reduce register access - * overhead. For this reason we store both values here. - */ - u8 vgc_level; - u8 vgc_level_reg; - - /* - * Statistics required for Signal quality calculation. - * These fields might be changed during the link_stats() - * callback function. - */ - int rx_success; - int rx_failed; - int tx_success; - int tx_failed; -}; - -/* - * Antenna settings about the currently active link. - */ -struct link_ant { - /* - * Antenna flags - */ - unsigned int flags; -#define ANTENNA_RX_DIVERSITY 0x00000001 -#define ANTENNA_TX_DIVERSITY 0x00000002 -#define ANTENNA_MODE_SAMPLE 0x00000004 - - /* - * Currently active TX/RX antenna setup. - * When software diversity is used, this will indicate - * which antenna is actually used at this time. - */ - struct antenna_setup active; - - /* - * RSSI history information for the antenna. - * Used to determine when to switch antenna - * when using software diversity. - */ - int rssi_history; - - /* - * Current RSSI average of the currently active antenna. - * Similar to the avg_rssi in the link_qual structure - * this value is updated by using the walking average. - */ - struct avg_val rssi_ant; -}; - -/* - * To optimize the quality of the link we need to store - * the quality of received frames and periodically - * optimize the link. - */ -struct link { - /* - * Link tuner counter - * The number of times the link has been tuned - * since the radio has been switched on. - */ - u32 count; - - /* - * Quality measurement values. - */ - struct link_qual qual; - - /* - * TX/RX antenna setup. - */ - struct link_ant ant; - - /* - * Currently active average RSSI value - */ - struct avg_val avg_rssi; - - /* - * Currently precalculated percentages of successful - * TX and RX frames. - */ - int rx_percentage; - int tx_percentage; - - /* - * Work structure for scheduling periodic link tuning. - */ - struct delayed_work work; -}; - -/* - * Interface structure - * Per interface configuration details, this structure - * is allocated as the private data for ieee80211_vif. - */ -struct rt2x00_intf { - /* - * All fields within the rt2x00_intf structure - * must be protected with a spinlock. - */ - spinlock_t lock; - - /* - * MAC of the device. - */ - u8 mac[ETH_ALEN]; - - /* - * BBSID of the AP to associate with. - */ - u8 bssid[ETH_ALEN]; - - /* - * beacon->skb must be protected with the mutex. - */ - struct mutex beacon_skb_mutex; - - /* - * Entry in the beacon queue which belongs to - * this interface. Each interface has its own - * dedicated beacon entry. - */ - struct queue_entry *beacon; - - /* - * Actions that needed rescheduling. - */ - unsigned int delayed_flags; -#define DELAYED_UPDATE_BEACON 0x00000001 - - /* - * Software sequence counter, this is only required - * for hardware which doesn't support hardware - * sequence counting. - */ - spinlock_t seqlock; - u16 seqno; -}; - -static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif) -{ - return (struct rt2x00_intf *)vif->drv_priv; -} - -/** - * struct hw_mode_spec: Hardware specifications structure - * - * Details about the supported modes, rates and channels - * of a particular chipset. This is used by rt2x00lib - * to build the ieee80211_hw_mode array for mac80211. - * - * @supported_bands: Bitmask contained the supported bands (2.4GHz, 5.2GHz). - * @supported_rates: Rate types which are supported (CCK, OFDM). - * @num_channels: Number of supported channels. This is used as array size - * for @tx_power_a, @tx_power_bg and @channels. - * @channels: Device/chipset specific channel values (See &struct rf_channel). - * @channels_info: Additional information for channels (See &struct channel_info). - * @ht: Driver HT Capabilities (See &ieee80211_sta_ht_cap). - */ -struct hw_mode_spec { - unsigned int supported_bands; -#define SUPPORT_BAND_2GHZ 0x00000001 -#define SUPPORT_BAND_5GHZ 0x00000002 - - unsigned int supported_rates; -#define SUPPORT_RATE_CCK 0x00000001 -#define SUPPORT_RATE_OFDM 0x00000002 - - unsigned int num_channels; - const struct rf_channel *channels; - const struct channel_info *channels_info; - - struct ieee80211_sta_ht_cap ht; -}; - -/* - * Configuration structure wrapper around the - * mac80211 configuration structure. - * When mac80211 configures the driver, rt2x00lib - * can precalculate values which are equal for all - * rt2x00 drivers. Those values can be stored in here. - */ -struct rt2x00lib_conf { - struct ieee80211_conf *conf; - - struct rf_channel rf; - struct channel_info channel; -}; - -/* - * Configuration structure for erp settings. - */ -struct rt2x00lib_erp { - int short_preamble; - int cts_protection; - - u32 basic_rates; - - int slot_time; - - short sifs; - short pifs; - short difs; - short eifs; - - u16 beacon_int; -}; - -/* - * Configuration structure for hardware encryption. - */ -struct rt2x00lib_crypto { - enum cipher cipher; - - enum set_key_cmd cmd; - const u8 *address; - - u32 bssidx; - u32 aid; - - u8 key[16]; - u8 tx_mic[8]; - u8 rx_mic[8]; -}; - -/* - * Configuration structure wrapper around the - * rt2x00 interface configuration handler. - */ -struct rt2x00intf_conf { - /* - * Interface type - */ - enum nl80211_iftype type; - - /* - * TSF sync value, this is dependant on the operation type. - */ - enum tsf_sync sync; - - /* - * 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. - */ - __le32 mac[2]; - __le32 bssid[2]; -}; - -/* - * rt2x00lib callback functions. - */ -struct rt2x00lib_ops { - /* - * Interrupt handlers. - */ - irq_handler_t irq_handler; - - /* - * Device init handlers. - */ - int (*probe_hw) (struct rt2x00_dev *rt2x00dev); - char *(*get_firmware_name) (struct rt2x00_dev *rt2x00dev); - int (*check_firmware) (struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len); - int (*load_firmware) (struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len); - - /* - * Device initialization/deinitialization handlers. - */ - int (*initialize) (struct rt2x00_dev *rt2x00dev); - void (*uninitialize) (struct rt2x00_dev *rt2x00dev); - - /* - * queue initialization handlers - */ - bool (*get_entry_state) (struct queue_entry *entry); - void (*clear_entry) (struct queue_entry *entry); - - /* - * Radio control handlers. - */ - int (*set_device_state) (struct rt2x00_dev *rt2x00dev, - enum dev_state state); - int (*rfkill_poll) (struct rt2x00_dev *rt2x00dev); - void (*link_stats) (struct rt2x00_dev *rt2x00dev, - struct link_qual *qual); - void (*reset_tuner) (struct rt2x00_dev *rt2x00dev, - struct link_qual *qual); - void (*link_tuner) (struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count); - - /* - * TX control handlers - */ - void (*write_tx_desc) (struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc); - int (*write_tx_data) (struct queue_entry *entry); - void (*write_beacon) (struct queue_entry *entry); - int (*get_tx_data_len) (struct queue_entry *entry); - void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); - void (*kill_tx_queue) (struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); - - /* - * RX control handlers - */ - void (*fill_rxdone) (struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc); - - /* - * Configuration handlers. - */ - int (*config_shared_key) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key); - int (*config_pairwise_key) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key); - void (*config_filter) (struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags); - void (*config_intf) (struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags); -#define CONFIG_UPDATE_TYPE ( 1 << 1 ) -#define CONFIG_UPDATE_MAC ( 1 << 2 ) -#define CONFIG_UPDATE_BSSID ( 1 << 3 ) - - void (*config_erp) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp); - void (*config_ant) (struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant); - void (*config) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int changed_flags); -}; - -/* - * rt2x00 driver callback operation structure. - */ -struct rt2x00_ops { - const char *name; - const unsigned int max_sta_intf; - const unsigned int max_ap_intf; - const unsigned int eeprom_size; - const unsigned int rf_size; - const unsigned int tx_queues; - const struct data_queue_desc *rx; - const struct data_queue_desc *tx; - const struct data_queue_desc *bcn; - const struct data_queue_desc *atim; - const struct rt2x00lib_ops *lib; - const struct ieee80211_ops *hw; -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - const struct rt2x00debug *debugfs; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * rt2x00 device flags - */ -enum rt2x00_flags { - /* - * Device state flags - */ - DEVICE_STATE_PRESENT, - DEVICE_STATE_REGISTERED_HW, - DEVICE_STATE_INITIALIZED, - DEVICE_STATE_STARTED, - DEVICE_STATE_ENABLED_RADIO, - - /* - * Driver requirements - */ - DRIVER_REQUIRE_FIRMWARE, - DRIVER_REQUIRE_BEACON_GUARD, - DRIVER_REQUIRE_ATIM_QUEUE, - DRIVER_REQUIRE_DMA, - DRIVER_REQUIRE_COPY_IV, - DRIVER_REQUIRE_L2PAD, - - /* - * Driver features - */ - CONFIG_SUPPORT_HW_BUTTON, - CONFIG_SUPPORT_HW_CRYPTO, - DRIVER_SUPPORT_CONTROL_FILTERS, - DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, - - /* - * Driver configuration - */ - CONFIG_FRAME_TYPE, - CONFIG_RF_SEQUENCE, - CONFIG_EXTERNAL_LNA_A, - CONFIG_EXTERNAL_LNA_BG, - CONFIG_DOUBLE_ANTENNA, - CONFIG_DISABLE_LINK_TUNING, - CONFIG_CHANNEL_HT40, -}; - -/* - * rt2x00 device structure. - */ -struct rt2x00_dev { - /* - * Device structure. - * The structure stored in here depends on the - * system bus (PCI or USB). - * When accessing this variable, the rt2x00dev_{pci,usb} - * macros should be used for correct typecasting. - */ - struct device *dev; - - /* - * Callback functions. - */ - const struct rt2x00_ops *ops; - - /* - * IEEE80211 control structure. - */ - struct ieee80211_hw *hw; - struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS]; - enum ieee80211_band curr_band; - - /* - * If enabled, the debugfs interface structures - * required for deregistration of debugfs. - */ -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - struct rt2x00debug_intf *debugfs_intf; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - - /* - * LED structure for changing the LED status - * by mac8011 or the kernel. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - struct rt2x00_led led_radio; - struct rt2x00_led led_assoc; - struct rt2x00_led led_qual; - u16 led_mcu_reg; -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - /* - * Device flags. - * In these flags the current status and some - * of the device capabilities are stored. - */ - unsigned long flags; - - /* - * Device information, Bus IRQ and name (PCI, SoC) - */ - int irq; - const char *name; - - /* - * Chipset identification. - */ - struct rt2x00_chip chip; - - /* - * hw capability specifications. - */ - struct hw_mode_spec spec; - - /* - * This is the default TX/RX antenna setup as indicated - * by the device's EEPROM. - */ - struct antenna_setup default_ant; - - /* - * Register pointers - * csr.base: CSR base register address. (PCI) - * csr.cache: CSR cache for usb_control_msg. (USB) - */ - union csr { - void __iomem *base; - void *cache; - } csr; - - /* - * Mutex to protect register accesses. - * For PCI and USB devices it protects against concurrent indirect - * register access (BBP, RF, MCU) since accessing those - * registers require multiple calls to the CSR registers. - * For USB devices it also protects the csr_cache since that - * field is used for normal CSR access and it cannot support - * multiple callers simultaneously. - */ - struct mutex csr_mutex; - - /* - * Current packet filter configuration for the device. - * This contains all currently active FIF_* flags send - * to us by mac80211 during configure_filter(). - */ - unsigned int packet_filter; - - /* - * Interface details: - * - Open ap interface count. - * - Open sta interface count. - * - Association count. - */ - unsigned int intf_ap_count; - unsigned int intf_sta_count; - unsigned int intf_associated; - - /* - * Link quality - */ - struct link link; - - /* - * EEPROM data. - */ - __le16 *eeprom; - - /* - * Active RF register values. - * These are stored here so we don't need - * to read the rf registers and can directly - * use this value instead. - * This field should be accessed by using - * rt2x00_rf_read() and rt2x00_rf_write(). - */ - u32 *rf; - - /* - * LNA gain - */ - short lna_gain; - - /* - * Current TX power value. - */ - u16 tx_power; - - /* - * Current retry values. - */ - u8 short_retry; - u8 long_retry; - - /* - * Rssi <-> Dbm offset - */ - u8 rssi_offset; - - /* - * Frequency offset (for rt61pci & rt73usb). - */ - u8 freq_offset; - - /* - * Calibration information (for rt2800usb & rt2800pci). - * [0] -> BW20 - * [1] -> BW40 - */ - u8 calibration[2]; - - /* - * Beacon interval. - */ - u16 beacon_int; - - /* - * Low level statistics which will have - * to be kept up to date while device is running. - */ - struct ieee80211_low_level_stats low_level_stats; - - /* - * RX configuration information. - */ - struct ieee80211_rx_status rx_status; - - /* - * Scheduled work. - * NOTE: intf_work will use ieee80211_iterate_active_interfaces() - * which means it cannot be placed on the hw->workqueue - * due to RTNL locking requirements. - */ - struct work_struct intf_work; - - /* - * Data queue arrays for RX, TX and Beacon. - * The Beacon array also contains the Atim queue - * if that is supported by the device. - */ - unsigned int data_queues; - struct data_queue *rx; - struct data_queue *tx; - struct data_queue *bcn; - - /* - * Firmware image. - */ - const struct firmware *fw; -}; - -/* - * Generic RF access. - * The RF is being accessed by word index. - */ -static inline void rt2x00_rf_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u32 *data) -{ - BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); - *data = rt2x00dev->rf[word - 1]; -} - -static inline void rt2x00_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u32 data) -{ - BUG_ON(word < 1 || word > rt2x00dev->ops->rf_size / sizeof(u32)); - rt2x00dev->rf[word - 1] = data; -} - -/* - * Generic EEPROM access. - * The EEPROM is being accessed by word index. - */ -static inline void *rt2x00_eeprom_addr(struct rt2x00_dev *rt2x00dev, - const unsigned int word) -{ - return (void *)&rt2x00dev->eeprom[word]; -} - -static inline void rt2x00_eeprom_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u16 *data) -{ - *data = le16_to_cpu(rt2x00dev->eeprom[word]); -} - -static inline void rt2x00_eeprom_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u16 data) -{ - rt2x00dev->eeprom[word] = cpu_to_le16(data); -} - -/* - * Chipset handlers - */ -static inline void rt2x00_set_chip(struct rt2x00_dev *rt2x00dev, - const u16 rt, const u16 rf, const u32 rev) -{ - INFO(rt2x00dev, - "Chipset detected - rt: %04x, rf: %04x, rev: %08x.\n", - rt, rf, rev); - - rt2x00dev->chip.rt = rt; - rt2x00dev->chip.rf = rf; - rt2x00dev->chip.rev = rev; -} - -static inline void rt2x00_set_chip_rt(struct rt2x00_dev *rt2x00dev, - const u16 rt) -{ - rt2x00dev->chip.rt = rt; -} - -static inline void rt2x00_set_chip_rf(struct rt2x00_dev *rt2x00dev, - const u16 rf, const u32 rev) -{ - rt2x00_set_chip(rt2x00dev, rt2x00dev->chip.rt, rf, rev); -} - -static inline char rt2x00_rt(const struct rt2x00_chip *chipset, const u16 chip) -{ - return (chipset->rt == chip); -} - -static inline char rt2x00_rf(const struct rt2x00_chip *chipset, const u16 chip) -{ - return (chipset->rf == chip); -} - -static inline u32 rt2x00_rev(const struct rt2x00_chip *chipset) -{ - return chipset->rev; -} - -static inline bool rt2x00_check_rev(const struct rt2x00_chip *chipset, - const u32 mask, const u32 rev) -{ - return ((chipset->rev & mask) == rev); -} - -/** - * rt2x00queue_map_txskb - Map a skb into DMA for TX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to map. - */ -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** - * rt2x00queue_get_queue - Convert queue index to queue pointer - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @queue: rt2x00 queue index (see &enum data_queue_qid). - */ -struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue); - -/** - * rt2x00queue_get_entry - Get queue entry where the given index points to. - * @queue: Pointer to &struct data_queue from where we obtain the entry. - * @index: Index identifier for obtaining the correct index. - */ -struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, - enum queue_index index); - -/* - * Interrupt context handlers. - */ -void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_txdone(struct queue_entry *entry, - struct txdone_entry_desc *txdesc); -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); - -/* - * mac80211 handlers. - */ -int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb); -int rt2x00mac_start(struct ieee80211_hw *hw); -void rt2x00mac_stop(struct ieee80211_hw *hw); -int rt2x00mac_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf); -int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed); -void rt2x00mac_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast); -int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - bool set); -#ifdef CONFIG_RT2X00_LIB_CRYPTO -int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key); -#else -#define rt2x00mac_set_key NULL -#endif /* CONFIG_RT2X00_LIB_CRYPTO */ -int rt2x00mac_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats); -int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats); -void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes); -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue, - const struct ieee80211_tx_queue_params *params); -void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw); - -/* - * Driver allocation handlers. - */ -int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev); -#ifdef CONFIG_PM -int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state); -int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev); -#endif /* CONFIG_PM */ - -#endif /* RT2X00_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00config.c b/drivers/net/wireless/rt2x00/rt2x00config.c deleted file mode 100644 index 40a201e2e151..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00config.c +++ /dev/null @@ -1,212 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - enum nl80211_iftype type, - const u8 *mac, const u8 *bssid) -{ - struct rt2x00intf_conf conf; - unsigned int flags = 0; - - conf.type = type; - - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_WDS: - conf.sync = TSF_SYNC_BEACON; - break; - case NL80211_IFTYPE_STATION: - conf.sync = TSF_SYNC_INFRA; - break; - default: - conf.sync = TSF_SYNC_NONE; - break; - } - - /* - * Note that when NULL is passed as address 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. - */ - memset(&conf.mac, 0, sizeof(conf.mac)); - if (mac) - memcpy(&conf.mac, mac, ETH_ALEN); - - memset(&conf.bssid, 0, sizeof(conf.bssid)); - if (bssid) - memcpy(&conf.bssid, bssid, ETH_ALEN); - - flags |= CONFIG_UPDATE_TYPE; - if (mac || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) - flags |= CONFIG_UPDATE_MAC; - if (bssid || (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count)) - flags |= CONFIG_UPDATE_BSSID; - - rt2x00dev->ops->lib->config_intf(rt2x00dev, intf, &conf, flags); -} - -void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct ieee80211_bss_conf *bss_conf) -{ - struct rt2x00lib_erp erp; - - memset(&erp, 0, sizeof(erp)); - - erp.short_preamble = bss_conf->use_short_preamble; - erp.cts_protection = bss_conf->use_cts_prot; - - erp.slot_time = bss_conf->use_short_slot ? SHORT_SLOT_TIME : SLOT_TIME; - erp.sifs = SIFS; - erp.pifs = bss_conf->use_short_slot ? SHORT_PIFS : PIFS; - erp.difs = bss_conf->use_short_slot ? SHORT_DIFS : DIFS; - erp.eifs = bss_conf->use_short_slot ? SHORT_EIFS : EIFS; - - erp.basic_rates = bss_conf->basic_rates; - erp.beacon_int = bss_conf->beacon_int; - - /* Update global beacon interval time, this is needed for PS support */ - rt2x00dev->beacon_int = bss_conf->beacon_int; - - rt2x00dev->ops->lib->config_erp(rt2x00dev, &erp); -} - -static inline -enum antenna rt2x00lib_config_antenna_check(enum antenna current_ant, - enum antenna default_ant) -{ - if (current_ant != ANTENNA_SW_DIVERSITY) - return current_ant; - return (default_ant != ANTENNA_SW_DIVERSITY) ? default_ant : ANTENNA_B; -} - -void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, - struct antenna_setup config) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - struct antenna_setup *def = &rt2x00dev->default_ant; - struct antenna_setup *active = &rt2x00dev->link.ant.active; - - /* - * Failsafe: Make sure we are not sending the - * ANTENNA_SW_DIVERSITY state to the driver. - * If that happens, fallback to hardware defaults, - * or our own default. - * If diversity handling is active for a particular antenna, - * we shouldn't overwrite that antenna. - * The calls to rt2x00lib_config_antenna_check() - * might have caused that we restore back to the already - * active setting. If that has happened we can quit. - */ - if (!(ant->flags & ANTENNA_RX_DIVERSITY)) - config.rx = rt2x00lib_config_antenna_check(config.rx, def->rx); - else - config.rx = active->rx; - - if (!(ant->flags & ANTENNA_TX_DIVERSITY)) - config.tx = rt2x00lib_config_antenna_check(config.tx, def->tx); - else - config.tx = active->tx; - - if (config.rx == active->rx && config.tx == active->tx) - return; - - /* - * Antenna setup changes require the RX to be disabled, - * else the changes will be ignored by the device. - */ - if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF_LINK); - - /* - * Write new antenna setup to device and reset the link tuner. - * The latter is required since we need to recalibrate the - * noise-sensitivity ratio for the new setup. - */ - rt2x00dev->ops->lib->config_ant(rt2x00dev, &config); - - rt2x00link_reset_tuner(rt2x00dev, true); - - memcpy(active, &config, sizeof(config)); - - if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON_LINK); -} - -void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - unsigned int ieee80211_flags) -{ - struct rt2x00lib_conf libconf; - - memset(&libconf, 0, sizeof(libconf)); - - libconf.conf = conf; - - if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) { - if (conf_is_ht40(conf)) - __set_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); - else - __clear_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags); - - memcpy(&libconf.rf, - &rt2x00dev->spec.channels[conf->channel->hw_value], - sizeof(libconf.rf)); - - memcpy(&libconf.channel, - &rt2x00dev->spec.channels_info[conf->channel->hw_value], - sizeof(libconf.channel)); - } - - /* - * Start configuration. - */ - rt2x00dev->ops->lib->config(rt2x00dev, &libconf, ieee80211_flags); - - /* - * Some configuration changes affect the link quality - * which means we need to reset the link tuner. - */ - if (ieee80211_flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt2x00link_reset_tuner(rt2x00dev, false); - - rt2x00dev->curr_band = conf->channel->band; - rt2x00dev->tx_power = conf->power_level; - rt2x00dev->short_retry = conf->short_frame_max_tx_count; - rt2x00dev->long_retry = conf->long_frame_max_tx_count; - - rt2x00dev->rx_status.band = conf->channel->band; - rt2x00dev->rx_status.freq = conf->channel->center_freq; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00crypto.c b/drivers/net/wireless/rt2x00/rt2x00crypto.c deleted file mode 100644 index de36837dcf86..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00crypto.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 crypto specific routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) -{ - switch (key->alg) { - case ALG_WEP: - if (key->keylen == WLAN_KEY_LEN_WEP40) - return CIPHER_WEP64; - else - return CIPHER_WEP128; - case ALG_TKIP: - return CIPHER_TKIP; - case ALG_CCMP: - return CIPHER_AES; - default: - return CIPHER_NONE; - } -} - -void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_key_conf *hw_key = tx_info->control.hw_key; - - if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !hw_key) - return; - - __set_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags); - - txdesc->cipher = rt2x00crypto_key_to_cipher(hw_key); - - if (hw_key->flags & IEEE80211_KEY_FLAG_PAIRWISE) - __set_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags); - - txdesc->key_idx = hw_key->hw_key_idx; - txdesc->iv_offset = txdesc->header_length; - txdesc->iv_len = hw_key->iv_len; - - if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) - __set_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags); - - if (!(hw_key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) - __set_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags); -} - -unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_key_conf *key = tx_info->control.hw_key; - unsigned int overhead = 0; - - if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags) || !key) - return overhead; - - /* - * Extend frame length to include IV/EIV/ICV/MMIC, - * note that these lengths should only be added when - * mac80211 does not generate it. - */ - overhead += key->icv_len; - - if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_IV)) - overhead += key->iv_len; - - if (!(key->flags & IEEE80211_KEY_FLAG_GENERATE_MMIC)) { - if (key->alg == ALG_TKIP) - overhead += 8; - } - - return overhead; -} - -void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - - if (unlikely(!txdesc->iv_len)) - return; - - /* Copy IV/EIV data */ - memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len); -} - -void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - - if (unlikely(!txdesc->iv_len)) - return; - - /* Copy IV/EIV data */ - memcpy(skbdesc->iv, skb->data + txdesc->iv_offset, txdesc->iv_len); - - /* Move ieee80211 header */ - memmove(skb->data + txdesc->iv_len, skb->data, txdesc->iv_offset); - - /* Pull buffer to correct size */ - skb_pull(skb, txdesc->iv_len); - - /* IV/EIV data has officially been stripped */ - skbdesc->flags |= SKBDESC_IV_STRIPPED; -} - -void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - const unsigned int iv_len = - ((!!(skbdesc->iv[0])) * 4) + ((!!(skbdesc->iv[1])) * 4); - - if (!(skbdesc->flags & SKBDESC_IV_STRIPPED)) - return; - - skb_push(skb, iv_len); - - /* Move ieee80211 header */ - memmove(skb->data, skb->data + iv_len, header_length); - - /* Copy IV/EIV data */ - memcpy(skb->data + header_length, skbdesc->iv, iv_len); - - /* IV/EIV data has returned into the frame */ - skbdesc->flags &= ~SKBDESC_IV_STRIPPED; -} - -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, - unsigned int header_length, - struct rxdone_entry_desc *rxdesc) -{ - unsigned int payload_len = rxdesc->size - header_length; - unsigned int align = ALIGN_SIZE(skb, header_length); - unsigned int iv_len; - unsigned int icv_len; - unsigned int transfer = 0; - - /* - * WEP64/WEP128: Provides IV & ICV - * TKIP: Provides IV/EIV & ICV - * AES: Provies IV/EIV & ICV - */ - switch (rxdesc->cipher) { - case CIPHER_WEP64: - case CIPHER_WEP128: - iv_len = 4; - icv_len = 4; - break; - case CIPHER_TKIP: - iv_len = 8; - icv_len = 4; - break; - case CIPHER_AES: - iv_len = 8; - icv_len = 8; - break; - default: - /* Unsupport type */ - return; - } - - /* - * Make room for new data. There are 2 possibilities - * either the alignment is already present between - * the 802.11 header and payload. In that case we - * we have to move the header less then the iv_len - * since we can use the already available l2pad bytes - * for the iv data. - * When the alignment must be added manually we must - * move the header more then iv_len since we must - * make room for the payload move as well. - */ - if (rxdesc->dev_flags & RXDONE_L2PAD) { - skb_push(skb, iv_len - align); - skb_put(skb, icv_len); - - /* Move ieee80211 header */ - memmove(skb->data + transfer, - skb->data + transfer + (iv_len - align), - header_length); - transfer += header_length; - } else { - skb_push(skb, iv_len + align); - if (align < icv_len) - skb_put(skb, icv_len - align); - else if (align > icv_len) - skb_trim(skb, rxdesc->size + iv_len + icv_len); - - /* Move ieee80211 header */ - memmove(skb->data + transfer, - skb->data + transfer + iv_len + align, - header_length); - transfer += header_length; - } - - /* Copy IV/EIV data */ - memcpy(skb->data + transfer, rxdesc->iv, iv_len); - transfer += iv_len; - - /* - * Move payload for alignment purposes. Note that - * this is only needed when no l2 padding is present. - */ - if (!(rxdesc->dev_flags & RXDONE_L2PAD)) { - memmove(skb->data + transfer, - skb->data + transfer + align, - payload_len); - } - - /* - * NOTE: Always count the payload as transfered, - * even when alignment was set to zero. This is required - * for determining the correct offset for the ICV data. - */ - transfer += payload_len; - - /* - * Copy ICV data - * AES appends 8 bytes, we can't fill the upper - * 4 bytes, but mac80211 doesn't care about what - * we provide here anyway and strips it immediately. - */ - memcpy(skb->data + transfer, &rxdesc->icv, 4); - transfer += icv_len; - - /* IV/EIV/ICV has been inserted into frame */ - rxdesc->size = transfer; - rxdesc->flags &= ~RX_FLAG_IV_STRIPPED; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.c b/drivers/net/wireless/rt2x00/rt2x00debug.c deleted file mode 100644 index 68bc9bb1dbf9..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00debug.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 debugfs specific routines. - */ - -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" -#include "rt2x00dump.h" - -#define MAX_LINE_LENGTH 64 - -struct rt2x00debug_crypto { - unsigned long success; - unsigned long icv_error; - unsigned long mic_error; - unsigned long key_error; -}; - -struct rt2x00debug_intf { - /* - * Pointer to driver structure where - * this debugfs entry belongs to. - */ - struct rt2x00_dev *rt2x00dev; - - /* - * Reference to the rt2x00debug structure - * which can be used to communicate with - * the registers. - */ - const struct rt2x00debug *debug; - - /* - * Debugfs entries for: - * - driver folder - * - driver file - * - chipset file - * - device flags file - * - register folder - * - csr offset/value files - * - eeprom offset/value files - * - bbp offset/value files - * - rf offset/value files - * - queue folder - * - frame dump file - * - queue stats file - * - crypto stats file - */ - struct dentry *driver_folder; - struct dentry *driver_entry; - struct dentry *chipset_entry; - struct dentry *dev_flags; - struct dentry *register_folder; - struct dentry *csr_off_entry; - struct dentry *csr_val_entry; - struct dentry *eeprom_off_entry; - struct dentry *eeprom_val_entry; - struct dentry *bbp_off_entry; - struct dentry *bbp_val_entry; - struct dentry *rf_off_entry; - struct dentry *rf_val_entry; - struct dentry *queue_folder; - struct dentry *queue_frame_dump_entry; - struct dentry *queue_stats_entry; - struct dentry *crypto_stats_entry; - - /* - * The frame dump file only allows a single reader, - * so we need to store the current state here. - */ - unsigned long frame_dump_flags; -#define FRAME_DUMP_FILE_OPEN 1 - - /* - * We queue each frame before dumping it to the user, - * per read command we will pass a single skb structure - * so we should be prepared to queue multiple sk buffers - * before sending it to userspace. - */ - struct sk_buff_head frame_dump_skbqueue; - wait_queue_head_t frame_dump_waitqueue; - - /* - * HW crypto statistics. - * All statistics are stored seperately per cipher type. - */ - struct rt2x00debug_crypto crypto_stats[CIPHER_MAX]; - - /* - * Driver and chipset files will use a data buffer - * that has been created in advance. This will simplify - * the code since we can use the debugfs functions. - */ - struct debugfs_blob_wrapper driver_blob; - struct debugfs_blob_wrapper chipset_blob; - - /* - * Requested offset for each register type. - */ - unsigned int offset_csr; - unsigned int offset_eeprom; - unsigned int offset_bbp; - unsigned int offset_rf; -}; - -void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, - struct rxdone_entry_desc *rxdesc) -{ - struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; - enum cipher cipher = rxdesc->cipher; - enum rx_crypto status = rxdesc->cipher_status; - - if (cipher == CIPHER_TKIP_NO_MIC) - cipher = CIPHER_TKIP; - if (cipher == CIPHER_NONE || cipher >= CIPHER_MAX) - return; - - /* Remove CIPHER_NONE index */ - cipher--; - - intf->crypto_stats[cipher].success += (status == RX_CRYPTO_SUCCESS); - intf->crypto_stats[cipher].icv_error += (status == RX_CRYPTO_FAIL_ICV); - intf->crypto_stats[cipher].mic_error += (status == RX_CRYPTO_FAIL_MIC); - intf->crypto_stats[cipher].key_error += (status == RX_CRYPTO_FAIL_KEY); -} - -void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, - enum rt2x00_dump_type type, struct sk_buff *skb) -{ - struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; - struct skb_frame_desc *desc = get_skb_frame_desc(skb); - struct sk_buff *skbcopy; - struct rt2x00dump_hdr *dump_hdr; - struct timeval timestamp; - - do_gettimeofday(×tamp); - - if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) - return; - - if (skb_queue_len(&intf->frame_dump_skbqueue) > 20) { - DEBUG(rt2x00dev, "txrx dump queue length exceeded.\n"); - return; - } - - skbcopy = alloc_skb(sizeof(*dump_hdr) + desc->desc_len + skb->len, - GFP_ATOMIC); - if (!skbcopy) { - DEBUG(rt2x00dev, "Failed to copy skb for dump.\n"); - return; - } - - dump_hdr = (struct rt2x00dump_hdr *)skb_put(skbcopy, sizeof(*dump_hdr)); - dump_hdr->version = cpu_to_le32(DUMP_HEADER_VERSION); - dump_hdr->header_length = cpu_to_le32(sizeof(*dump_hdr)); - dump_hdr->desc_length = cpu_to_le32(desc->desc_len); - dump_hdr->data_length = cpu_to_le32(skb->len); - dump_hdr->chip_rt = cpu_to_le16(rt2x00dev->chip.rt); - dump_hdr->chip_rf = cpu_to_le16(rt2x00dev->chip.rf); - dump_hdr->chip_rev = cpu_to_le32(rt2x00dev->chip.rev); - dump_hdr->type = cpu_to_le16(type); - dump_hdr->queue_index = desc->entry->queue->qid; - dump_hdr->entry_index = desc->entry->entry_idx; - dump_hdr->timestamp_sec = cpu_to_le32(timestamp.tv_sec); - dump_hdr->timestamp_usec = cpu_to_le32(timestamp.tv_usec); - - memcpy(skb_put(skbcopy, desc->desc_len), desc->desc, desc->desc_len); - memcpy(skb_put(skbcopy, skb->len), skb->data, skb->len); - - skb_queue_tail(&intf->frame_dump_skbqueue, skbcopy); - wake_up_interruptible(&intf->frame_dump_waitqueue); - - /* - * Verify that the file has not been closed while we were working. - */ - if (!test_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) - skb_queue_purge(&intf->frame_dump_skbqueue); -} - -static int rt2x00debug_file_open(struct inode *inode, struct file *file) -{ - struct rt2x00debug_intf *intf = inode->i_private; - - file->private_data = inode->i_private; - - if (!try_module_get(intf->debug->owner)) - return -EBUSY; - - return 0; -} - -static int rt2x00debug_file_release(struct inode *inode, struct file *file) -{ - struct rt2x00debug_intf *intf = file->private_data; - - module_put(intf->debug->owner); - - return 0; -} - -static int rt2x00debug_open_queue_dump(struct inode *inode, struct file *file) -{ - struct rt2x00debug_intf *intf = inode->i_private; - int retval; - - retval = rt2x00debug_file_open(inode, file); - if (retval) - return retval; - - if (test_and_set_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags)) { - rt2x00debug_file_release(inode, file); - return -EBUSY; - } - - return 0; -} - -static int rt2x00debug_release_queue_dump(struct inode *inode, struct file *file) -{ - struct rt2x00debug_intf *intf = inode->i_private; - - skb_queue_purge(&intf->frame_dump_skbqueue); - - clear_bit(FRAME_DUMP_FILE_OPEN, &intf->frame_dump_flags); - - return rt2x00debug_file_release(inode, file); -} - -static ssize_t rt2x00debug_read_queue_dump(struct file *file, - char __user *buf, - size_t length, - loff_t *offset) -{ - struct rt2x00debug_intf *intf = file->private_data; - struct sk_buff *skb; - size_t status; - int retval; - - if (file->f_flags & O_NONBLOCK) - return -EAGAIN; - - retval = - wait_event_interruptible(intf->frame_dump_waitqueue, - (skb = - skb_dequeue(&intf->frame_dump_skbqueue))); - if (retval) - return retval; - - status = min((size_t)skb->len, length); - if (copy_to_user(buf, skb->data, status)) { - status = -EFAULT; - goto exit; - } - - *offset += status; - -exit: - kfree_skb(skb); - - return status; -} - -static unsigned int rt2x00debug_poll_queue_dump(struct file *file, - poll_table *wait) -{ - struct rt2x00debug_intf *intf = file->private_data; - - poll_wait(file, &intf->frame_dump_waitqueue, wait); - - if (!skb_queue_empty(&intf->frame_dump_skbqueue)) - return POLLOUT | POLLWRNORM; - - return 0; -} - -static const struct file_operations rt2x00debug_fop_queue_dump = { - .owner = THIS_MODULE, - .read = rt2x00debug_read_queue_dump, - .poll = rt2x00debug_poll_queue_dump, - .open = rt2x00debug_open_queue_dump, - .release = rt2x00debug_release_queue_dump, -}; - -static ssize_t rt2x00debug_read_queue_stats(struct file *file, - char __user *buf, - size_t length, - loff_t *offset) -{ - struct rt2x00debug_intf *intf = file->private_data; - struct data_queue *queue; - unsigned long irqflags; - unsigned int lines = 1 + intf->rt2x00dev->data_queues; - size_t size; - char *data; - char *temp; - - if (*offset) - return 0; - - data = kzalloc(lines * MAX_LINE_LENGTH, GFP_KERNEL); - if (!data) - return -ENOMEM; - - temp = data + - sprintf(data, "qid\tcount\tlimit\tlength\tindex\tdone\tcrypto\n"); - - queue_for_each(intf->rt2x00dev, queue) { - spin_lock_irqsave(&queue->lock, irqflags); - - temp += sprintf(temp, "%d\t%d\t%d\t%d\t%d\t%d\t%d\n", queue->qid, - queue->count, queue->limit, queue->length, - queue->index[Q_INDEX], - queue->index[Q_INDEX_DONE], - queue->index[Q_INDEX_CRYPTO]); - - spin_unlock_irqrestore(&queue->lock, irqflags); - } - - size = strlen(data); - size = min(size, length); - - if (copy_to_user(buf, data, size)) { - kfree(data); - return -EFAULT; - } - - kfree(data); - - *offset += size; - return size; -} - -static const struct file_operations rt2x00debug_fop_queue_stats = { - .owner = THIS_MODULE, - .read = rt2x00debug_read_queue_stats, - .open = rt2x00debug_file_open, - .release = rt2x00debug_file_release, -}; - -#ifdef CONFIG_RT2X00_LIB_CRYPTO -static ssize_t rt2x00debug_read_crypto_stats(struct file *file, - char __user *buf, - size_t length, - loff_t *offset) -{ - struct rt2x00debug_intf *intf = file->private_data; - char *name[] = { "WEP64", "WEP128", "TKIP", "AES" }; - char *data; - char *temp; - size_t size; - unsigned int i; - - if (*offset) - return 0; - - data = kzalloc((1 + CIPHER_MAX) * MAX_LINE_LENGTH, GFP_KERNEL); - if (!data) - return -ENOMEM; - - temp = data; - temp += sprintf(data, "cipher\tsuccess\ticv err\tmic err\tkey err\n"); - - for (i = 0; i < CIPHER_MAX; i++) { - temp += sprintf(temp, "%s\t%lu\t%lu\t%lu\t%lu\n", name[i], - intf->crypto_stats[i].success, - intf->crypto_stats[i].icv_error, - intf->crypto_stats[i].mic_error, - intf->crypto_stats[i].key_error); - } - - size = strlen(data); - size = min(size, length); - - if (copy_to_user(buf, data, size)) { - kfree(data); - return -EFAULT; - } - - kfree(data); - - *offset += size; - return size; -} - -static const struct file_operations rt2x00debug_fop_crypto_stats = { - .owner = THIS_MODULE, - .read = rt2x00debug_read_crypto_stats, - .open = rt2x00debug_file_open, - .release = rt2x00debug_file_release, -}; -#endif - -#define RT2X00DEBUGFS_OPS_READ(__name, __format, __type) \ -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; \ - const struct rt2x00debug *debug = intf->debug; \ - char line[16]; \ - size_t size; \ - unsigned int index = intf->offset_##__name; \ - __type value; \ - \ - if (*offset) \ - return 0; \ - \ - if (index >= debug->__name.word_count) \ - return -EINVAL; \ - \ - index += (debug->__name.word_base / \ - debug->__name.word_size); \ - \ - if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \ - index *= debug->__name.word_size; \ - \ - debug->__name.read(intf->rt2x00dev, index, &value); \ - \ - size = sprintf(line, __format, value); \ - \ - if (copy_to_user(buf, line, size)) \ - return -EFAULT; \ - \ - *offset += size; \ - return size; \ -} - -#define RT2X00DEBUGFS_OPS_WRITE(__name, __type) \ -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; \ - const struct rt2x00debug *debug = intf->debug; \ - char line[16]; \ - size_t size; \ - unsigned int index = intf->offset_##__name; \ - __type value; \ - \ - if (*offset) \ - return 0; \ - \ - if (index >= debug->__name.word_count) \ - return -EINVAL; \ - \ - if (copy_from_user(line, buf, length)) \ - return -EFAULT; \ - \ - size = strlen(line); \ - value = simple_strtoul(line, NULL, 0); \ - \ - index += (debug->__name.word_base / \ - debug->__name.word_size); \ - \ - if (debug->__name.flags & RT2X00DEBUGFS_OFFSET) \ - index *= debug->__name.word_size; \ - \ - debug->__name.write(intf->rt2x00dev, index, value); \ - \ - *offset += size; \ - return size; \ -} - -#define RT2X00DEBUGFS_OPS(__name, __format, __type) \ -RT2X00DEBUGFS_OPS_READ(__name, __format, __type); \ -RT2X00DEBUGFS_OPS_WRITE(__name, __type); \ - \ -static const struct file_operations rt2x00debug_fop_##__name = {\ - .owner = THIS_MODULE, \ - .read = rt2x00debug_read_##__name, \ - .write = rt2x00debug_write_##__name, \ - .open = rt2x00debug_file_open, \ - .release = rt2x00debug_file_release, \ -}; - -RT2X00DEBUGFS_OPS(csr, "0x%.8x\n", u32); -RT2X00DEBUGFS_OPS(eeprom, "0x%.4x\n", u16); -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, - struct rt2x00debug_intf - *intf, - struct debugfs_blob_wrapper - *blob) -{ - char *data; - - data = kzalloc(3 * MAX_LINE_LENGTH, GFP_KERNEL); - if (!data) - return NULL; - - blob->data = data; - data += sprintf(data, "driver:\t%s\n", intf->rt2x00dev->ops->name); - data += sprintf(data, "version:\t%s\n", DRV_VERSION); - data += sprintf(data, "compiled:\t%s %s\n", __DATE__, __TIME__); - blob->size = strlen(blob->data); - - return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); -} - -static struct dentry *rt2x00debug_create_file_chipset(const char *name, - struct rt2x00debug_intf - *intf, - struct - debugfs_blob_wrapper - *blob) -{ - const struct rt2x00debug *debug = intf->debug; - char *data; - - data = kzalloc(8 * MAX_LINE_LENGTH, GFP_KERNEL); - if (!data) - return NULL; - - blob->data = data; - data += sprintf(data, "rt chip:\t%04x\n", intf->rt2x00dev->chip.rt); - data += sprintf(data, "rf chip:\t%04x\n", intf->rt2x00dev->chip.rf); - data += sprintf(data, "revision:\t%08x\n", intf->rt2x00dev->chip.rev); - data += sprintf(data, "\n"); - data += sprintf(data, "register\tbase\twords\twordsize\n"); - data += sprintf(data, "csr\t%d\t%d\t%d\n", - debug->csr.word_base, - debug->csr.word_count, - debug->csr.word_size); - data += sprintf(data, "eeprom\t%d\t%d\t%d\n", - debug->eeprom.word_base, - debug->eeprom.word_count, - debug->eeprom.word_size); - data += sprintf(data, "bbp\t%d\t%d\t%d\n", - debug->bbp.word_base, - debug->bbp.word_count, - debug->bbp.word_size); - data += sprintf(data, "rf\t%d\t%d\t%d\n", - debug->rf.word_base, - debug->rf.word_count, - debug->rf.word_size); - blob->size = strlen(blob->data); - - return debugfs_create_blob(name, S_IRUSR, intf->driver_folder, blob); -} - -void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) -{ - const struct rt2x00debug *debug = rt2x00dev->ops->debugfs; - struct rt2x00debug_intf *intf; - - intf = kzalloc(sizeof(struct rt2x00debug_intf), GFP_KERNEL); - if (!intf) { - ERROR(rt2x00dev, "Failed to allocate debug handler.\n"); - return; - } - - intf->debug = debug; - intf->rt2x00dev = rt2x00dev; - rt2x00dev->debugfs_intf = intf; - - intf->driver_folder = - debugfs_create_dir(intf->rt2x00dev->ops->name, - rt2x00dev->hw->wiphy->debugfsdir); - if (IS_ERR(intf->driver_folder) || !intf->driver_folder) - goto exit; - - intf->driver_entry = - rt2x00debug_create_file_driver("driver", intf, &intf->driver_blob); - if (IS_ERR(intf->driver_entry) || !intf->driver_entry) - goto exit; - - intf->chipset_entry = - rt2x00debug_create_file_chipset("chipset", - intf, &intf->chipset_blob); - if (IS_ERR(intf->chipset_entry) || !intf->chipset_entry) - goto exit; - - intf->dev_flags = debugfs_create_file("dev_flags", S_IRUSR, - intf->driver_folder, intf, - &rt2x00debug_fop_dev_flags); - if (IS_ERR(intf->dev_flags) || !intf->dev_flags) - goto exit; - - intf->register_folder = - debugfs_create_dir("register", intf->driver_folder); - if (IS_ERR(intf->register_folder) || !intf->register_folder) - goto exit; - -#define RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(__intf, __name) \ -({ \ - (__intf)->__name##_off_entry = \ - debugfs_create_u32(__stringify(__name) "_offset", \ - S_IRUSR | S_IWUSR, \ - (__intf)->register_folder, \ - &(__intf)->offset_##__name); \ - if (IS_ERR((__intf)->__name##_off_entry) \ - || !(__intf)->__name##_off_entry) \ - goto exit; \ - \ - (__intf)->__name##_val_entry = \ - debugfs_create_file(__stringify(__name) "_value", \ - S_IRUSR | S_IWUSR, \ - (__intf)->register_folder, \ - (__intf), &rt2x00debug_fop_##__name);\ - if (IS_ERR((__intf)->__name##_val_entry) \ - || !(__intf)->__name##_val_entry) \ - goto exit; \ -}) - - RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, csr); - RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, eeprom); - RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, bbp); - RT2X00DEBUGFS_CREATE_REGISTER_ENTRY(intf, rf); - -#undef RT2X00DEBUGFS_CREATE_REGISTER_ENTRY - - intf->queue_folder = - debugfs_create_dir("queue", intf->driver_folder); - if (IS_ERR(intf->queue_folder) || !intf->queue_folder) - goto exit; - - intf->queue_frame_dump_entry = - debugfs_create_file("dump", S_IRUSR, intf->queue_folder, - intf, &rt2x00debug_fop_queue_dump); - if (IS_ERR(intf->queue_frame_dump_entry) - || !intf->queue_frame_dump_entry) - goto exit; - - skb_queue_head_init(&intf->frame_dump_skbqueue); - init_waitqueue_head(&intf->frame_dump_waitqueue); - - intf->queue_stats_entry = - debugfs_create_file("queue", S_IRUSR, intf->queue_folder, - intf, &rt2x00debug_fop_queue_stats); - -#ifdef CONFIG_RT2X00_LIB_CRYPTO - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) - intf->crypto_stats_entry = - debugfs_create_file("crypto", S_IRUGO, intf->queue_folder, - intf, &rt2x00debug_fop_crypto_stats); -#endif - - return; - -exit: - rt2x00debug_deregister(rt2x00dev); - ERROR(rt2x00dev, "Failed to register debug handler.\n"); - - return; -} - -void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) -{ - struct rt2x00debug_intf *intf = rt2x00dev->debugfs_intf; - - if (unlikely(!intf)) - return; - - skb_queue_purge(&intf->frame_dump_skbqueue); - -#ifdef CONFIG_RT2X00_LIB_CRYPTO - debugfs_remove(intf->crypto_stats_entry); -#endif - debugfs_remove(intf->queue_stats_entry); - debugfs_remove(intf->queue_frame_dump_entry); - debugfs_remove(intf->queue_folder); - debugfs_remove(intf->rf_val_entry); - debugfs_remove(intf->rf_off_entry); - debugfs_remove(intf->bbp_val_entry); - debugfs_remove(intf->bbp_off_entry); - debugfs_remove(intf->eeprom_val_entry); - debugfs_remove(intf->eeprom_off_entry); - debugfs_remove(intf->csr_val_entry); - debugfs_remove(intf->csr_off_entry); - debugfs_remove(intf->register_folder); - debugfs_remove(intf->dev_flags); - debugfs_remove(intf->chipset_entry); - debugfs_remove(intf->driver_entry); - debugfs_remove(intf->driver_folder); - kfree(intf->chipset_blob.data); - kfree(intf->driver_blob.data); - kfree(intf); - - rt2x00dev->debugfs_intf = NULL; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00debug.h b/drivers/net/wireless/rt2x00/rt2x00debug.h deleted file mode 100644 index 035cbc98c593..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00debug.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00debug - Abstract: Data structures for the rt2x00debug. - */ - -#ifndef RT2X00DEBUG_H -#define RT2X00DEBUG_H - -struct rt2x00_dev; - -/** - * enum rt2x00debugfs_entry_flags: Flags for debugfs registry entry - * - * @RT2X00DEBUGFS_OFFSET: rt2x00lib should pass the register offset - * as argument when using the callback function read()/write() - */ -enum rt2x00debugfs_entry_flags { - RT2X00DEBUGFS_OFFSET = (1 << 0), -}; - -#define RT2X00DEBUGFS_REGISTER_ENTRY(__name, __type) \ -struct reg##__name { \ - void (*read)(struct rt2x00_dev *rt2x00dev, \ - const unsigned int word, __type *data); \ - void (*write)(struct rt2x00_dev *rt2x00dev, \ - const unsigned int word, __type data); \ - \ - unsigned int flags; \ - \ - unsigned int word_base; \ - unsigned int word_size; \ - unsigned int word_count; \ -} __name - -struct rt2x00debug { - /* - * Reference to the modules structure. - */ - struct module *owner; - - /* - * Register access entries. - */ - RT2X00DEBUGFS_REGISTER_ENTRY(csr, u32); - RT2X00DEBUGFS_REGISTER_ENTRY(eeprom, u16); - RT2X00DEBUGFS_REGISTER_ENTRY(bbp, u8); - RT2X00DEBUGFS_REGISTER_ENTRY(rf, u32); -}; - -#endif /* RT2X00DEBUG_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c deleted file mode 100644 index 73bbec58341e..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ /dev/null @@ -1,997 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 device routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -/* - * Radio control handlers. - */ -int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - int status; - - /* - * Don't enable the radio twice. - * And check if the hardware button has been disabled. - */ - if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return 0; - - /* - * Initialize all data queues. - */ - rt2x00queue_init_queues(rt2x00dev); - - /* - * Enable radio. - */ - status = - rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_ON); - if (status) - return status; - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_ON); - - rt2x00leds_led_radio(rt2x00dev, true); - rt2x00led_led_activity(rt2x00dev, true); - - set_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags); - - /* - * Enable RX. - */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - - /* - * Start the TX queues. - */ - ieee80211_wake_queues(rt2x00dev->hw); - - return 0; -} - -void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - if (!test_and_clear_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - /* - * Stop the TX queues in mac80211. - */ - ieee80211_stop_queues(rt2x00dev->hw); - rt2x00queue_stop_queues(rt2x00dev); - - /* - * Disable RX. - */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); - - /* - * Disable radio. - */ - rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_OFF); - rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_RADIO_IRQ_OFF); - rt2x00led_led_activity(rt2x00dev, false); - rt2x00leds_led_radio(rt2x00dev, false); -} - -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state) -{ - /* - * When we are disabling the RX, we should also stop the link tuner. - */ - if (state == STATE_RADIO_RX_OFF) - rt2x00link_stop_tuner(rt2x00dev); - - rt2x00dev->ops->lib->set_device_state(rt2x00dev, state); - - /* - * When we are enabling the RX, we should also start the link tuner. - */ - if (state == STATE_RADIO_RX_ON) - rt2x00link_start_tuner(rt2x00dev); -} - -static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct rt2x00_dev *rt2x00dev = data; - struct rt2x00_intf *intf = vif_to_intf(vif); - int delayed_flags; - - /* - * Copy all data we need during this action under the protection - * of a spinlock. Otherwise race conditions might occur which results - * into an invalid configuration. - */ - spin_lock(&intf->lock); - - delayed_flags = intf->delayed_flags; - intf->delayed_flags = 0; - - spin_unlock(&intf->lock); - - /* - * It is possible the radio was disabled while the work had been - * scheduled. If that happens we should return here immediately, - * note that in the spinlock protected area above the delayed_flags - * have been cleared correctly. - */ - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - if (delayed_flags & DELAYED_UPDATE_BEACON) - rt2x00queue_update_beacon(rt2x00dev, vif, true); -} - -static void rt2x00lib_intf_scheduled(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, intf_work); - - /* - * Iterate over each interface and perform the - * requested configurations. - */ - ieee80211_iterate_active_interfaces(rt2x00dev->hw, - rt2x00lib_intf_scheduled_iter, - rt2x00dev); -} - -/* - * Interrupt context handlers. - */ -static void rt2x00lib_beacondone_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct rt2x00_intf *intf = vif_to_intf(vif); - - if (vif->type != NL80211_IFTYPE_AP && - vif->type != NL80211_IFTYPE_ADHOC && - vif->type != NL80211_IFTYPE_MESH_POINT && - vif->type != NL80211_IFTYPE_WDS) - return; - - spin_lock(&intf->lock); - intf->delayed_flags |= DELAYED_UPDATE_BEACON; - spin_unlock(&intf->lock); -} - -void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) -{ - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw, - rt2x00lib_beacondone_iter, - rt2x00dev); - - ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->intf_work); -} -EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); - -void rt2x00lib_txdone(struct queue_entry *entry, - struct txdone_entry_desc *txdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); - unsigned int header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - u8 rate_idx, rate_flags, retry_rates; - unsigned int i; - bool success; - - /* - * Unmap the skb. - */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); - - /* - * Remove L2 padding which was added during - */ - if (test_bit(DRIVER_REQUIRE_L2PAD, &rt2x00dev->flags)) - rt2x00queue_remove_l2pad(entry->skb, header_length); - - /* - * If the IV/EIV data was stripped from the frame before it was - * passed to the hardware, we should now reinsert it again because - * mac80211 will expect the the same data to be present it the - * frame as it was passed to us. - */ - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) - rt2x00crypto_tx_insert_iv(entry->skb, header_length); - - /* - * Send frame to debugfs immediately, after this call is completed - * we are going to overwrite the skb->cb array. - */ - rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb); - - /* - * Determine if the frame has been successfully transmitted. - */ - success = - test_bit(TXDONE_SUCCESS, &txdesc->flags) || - test_bit(TXDONE_UNKNOWN, &txdesc->flags) || - test_bit(TXDONE_FALLBACK, &txdesc->flags); - - /* - * Update TX statistics. - */ - rt2x00dev->link.qual.tx_success += success; - rt2x00dev->link.qual.tx_failed += !success; - - rate_idx = skbdesc->tx_rate_idx; - rate_flags = skbdesc->tx_rate_flags; - retry_rates = test_bit(TXDONE_FALLBACK, &txdesc->flags) ? - (txdesc->retry + 1) : 1; - - /* - * Initialize TX status - */ - memset(&tx_info->status, 0, sizeof(tx_info->status)); - tx_info->status.ack_signal = 0; - - /* - * Frame was send with retries, hardware tried - * different rates to send out the frame, at each - * retry it lowered the rate 1 step. - */ - for (i = 0; i < retry_rates && i < IEEE80211_TX_MAX_RATES; i++) { - tx_info->status.rates[i].idx = rate_idx - i; - tx_info->status.rates[i].flags = rate_flags; - tx_info->status.rates[i].count = 1; - } - if (i < (IEEE80211_TX_MAX_RATES - 1)) - tx_info->status.rates[i].idx = -1; /* terminate */ - - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (success) - tx_info->flags |= IEEE80211_TX_STAT_ACK; - else - rt2x00dev->low_level_stats.dot11ACKFailureCount++; - } - - if (rate_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - if (success) - rt2x00dev->low_level_stats.dot11RTSSuccessCount++; - else - rt2x00dev->low_level_stats.dot11RTSFailureCount++; - } - - /* - * Only send the status report to mac80211 when TX status was - * requested by it. If this was a extra frame coming through - * a mac80211 library call (RTS/CTS) then we should not send the - * status report back. - */ - if (tx_info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS) - ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); - else - dev_kfree_skb_irq(entry->skb); - - /* - * Make this entry available for reuse. - */ - entry->skb = NULL; - entry->flags = 0; - - rt2x00dev->ops->lib->clear_entry(entry); - - clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); - - /* - * If the data queue was below the threshold before the txdone - * handler we must make sure the packet queue in the mac80211 stack - * is reenabled when the txdone handler has finished. - */ - if (!rt2x00queue_threshold(entry->queue)) - ieee80211_wake_queue(rt2x00dev->hw, qid); -} -EXPORT_SYMBOL_GPL(rt2x00lib_txdone); - -static int rt2x00lib_rxdone_read_signal(struct rt2x00_dev *rt2x00dev, - struct rxdone_entry_desc *rxdesc) -{ - struct ieee80211_supported_band *sband; - const struct rt2x00_rate *rate; - unsigned int i; - int signal; - int type; - - /* - * For non-HT rates the MCS value needs to contain the - * actually used rate modulation (CCK or OFDM). - */ - if (rxdesc->dev_flags & RXDONE_SIGNAL_MCS) - signal = RATE_MCS(rxdesc->rate_mode, rxdesc->signal); - else - signal = rxdesc->signal; - - type = (rxdesc->dev_flags & RXDONE_SIGNAL_MASK); - - sband = &rt2x00dev->bands[rt2x00dev->curr_band]; - for (i = 0; i < sband->n_bitrates; i++) { - rate = rt2x00_get_rate(sband->bitrates[i].hw_value); - - if (((type == RXDONE_SIGNAL_PLCP) && - (rate->plcp == signal)) || - ((type == RXDONE_SIGNAL_BITRATE) && - (rate->bitrate == signal)) || - ((type == RXDONE_SIGNAL_MCS) && - (rate->mcs == signal))) { - return i; - } - } - - WARNING(rt2x00dev, "Frame received with unrecognized signal, " - "signal=0x%.4x, type=%d.\n", signal, type); - return 0; -} - -void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry) -{ - struct rxdone_entry_desc rxdesc; - struct sk_buff *skb; - struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; - unsigned int header_length; - int rate_idx; - /* - * Allocate a new sk_buffer. If no new buffer available, drop the - * received frame and reuse the existing buffer. - */ - skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); - if (!skb) - return; - - /* - * Unmap the skb. - */ - rt2x00queue_unmap_skb(rt2x00dev, entry->skb); - - /* - * Extract the RXD details. - */ - memset(&rxdesc, 0, sizeof(rxdesc)); - rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); - - /* Trim buffer to correct size */ - skb_trim(entry->skb, rxdesc.size); - - /* - * The data behind the ieee80211 header must be - * aligned on a 4 byte boundary. - */ - header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - - /* - * Hardware might have stripped the IV/EIV/ICV data, - * in that case it is possible that the data was - * provided seperately (through hardware descriptor) - * in which case we should reinsert the data into the frame. - */ - if ((rxdesc.dev_flags & RXDONE_CRYPTO_IV) && - (rxdesc.flags & RX_FLAG_IV_STRIPPED)) - rt2x00crypto_rx_insert_iv(entry->skb, header_length, - &rxdesc); - else if (rxdesc.dev_flags & RXDONE_L2PAD) - rt2x00queue_remove_l2pad(entry->skb, header_length); - else - rt2x00queue_align_payload(entry->skb, header_length); - - /* - * Check if the frame was received using HT. In that case, - * the rate is the MCS index and should be passed to mac80211 - * directly. Otherwise we need to translate the signal to - * the correct bitrate index. - */ - if (rxdesc.rate_mode == RATE_MODE_CCK || - rxdesc.rate_mode == RATE_MODE_OFDM) { - rate_idx = rt2x00lib_rxdone_read_signal(rt2x00dev, &rxdesc); - } else { - rxdesc.flags |= RX_FLAG_HT; - rate_idx = rxdesc.signal; - } - - /* - * Update extra components - */ - rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); - rt2x00debug_update_crypto(rt2x00dev, &rxdesc); - - rx_status->mactime = rxdesc.timestamp; - rx_status->rate_idx = rate_idx; - rx_status->qual = rt2x00link_calculate_signal(rt2x00dev, rxdesc.rssi); - rx_status->signal = rxdesc.rssi; - rx_status->noise = rxdesc.noise; - rx_status->flag = rxdesc.flags; - rx_status->antenna = rt2x00dev->link.ant.active.rx; - - /* - * Send frame to mac80211 & debugfs. - * mac80211 will clean up the skb structure. - */ - rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); - memcpy(IEEE80211_SKB_RXCB(entry->skb), rx_status, sizeof(*rx_status)); - ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb); - - /* - * Replace the skb with the freshly allocated one. - */ - entry->skb = skb; - entry->flags = 0; - - rt2x00dev->ops->lib->clear_entry(entry); - - rt2x00queue_index_inc(entry->queue, Q_INDEX); -} -EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); - -/* - * Driver initialization handlers. - */ -const struct rt2x00_rate rt2x00_supported_rates[12] = { - { - .flags = DEV_RATE_CCK, - .bitrate = 10, - .ratemask = BIT(0), - .plcp = 0x00, - .mcs = RATE_MCS(RATE_MODE_CCK, 0), - }, - { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, - .bitrate = 20, - .ratemask = BIT(1), - .plcp = 0x01, - .mcs = RATE_MCS(RATE_MODE_CCK, 1), - }, - { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, - .bitrate = 55, - .ratemask = BIT(2), - .plcp = 0x02, - .mcs = RATE_MCS(RATE_MODE_CCK, 2), - }, - { - .flags = DEV_RATE_CCK | DEV_RATE_SHORT_PREAMBLE, - .bitrate = 110, - .ratemask = BIT(3), - .plcp = 0x03, - .mcs = RATE_MCS(RATE_MODE_CCK, 3), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 60, - .ratemask = BIT(4), - .plcp = 0x0b, - .mcs = RATE_MCS(RATE_MODE_OFDM, 0), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 90, - .ratemask = BIT(5), - .plcp = 0x0f, - .mcs = RATE_MCS(RATE_MODE_OFDM, 1), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 120, - .ratemask = BIT(6), - .plcp = 0x0a, - .mcs = RATE_MCS(RATE_MODE_OFDM, 2), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 180, - .ratemask = BIT(7), - .plcp = 0x0e, - .mcs = RATE_MCS(RATE_MODE_OFDM, 3), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 240, - .ratemask = BIT(8), - .plcp = 0x09, - .mcs = RATE_MCS(RATE_MODE_OFDM, 4), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 360, - .ratemask = BIT(9), - .plcp = 0x0d, - .mcs = RATE_MCS(RATE_MODE_OFDM, 5), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 480, - .ratemask = BIT(10), - .plcp = 0x08, - .mcs = RATE_MCS(RATE_MODE_OFDM, 6), - }, - { - .flags = DEV_RATE_OFDM, - .bitrate = 540, - .ratemask = BIT(11), - .plcp = 0x0c, - .mcs = RATE_MCS(RATE_MODE_OFDM, 7), - }, -}; - -static void rt2x00lib_channel(struct ieee80211_channel *entry, - const int channel, const int tx_power, - const int value) -{ - entry->center_freq = ieee80211_channel_to_frequency(channel); - entry->hw_value = value; - entry->max_power = tx_power; - entry->max_antenna_gain = 0xff; -} - -static void rt2x00lib_rate(struct ieee80211_rate *entry, - const u16 index, const struct rt2x00_rate *rate) -{ - entry->flags = 0; - entry->bitrate = rate->bitrate; - entry->hw_value =index; - entry->hw_value_short = index; - - if (rate->flags & DEV_RATE_SHORT_PREAMBLE) - entry->flags |= IEEE80211_RATE_SHORT_PREAMBLE; -} - -static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev, - struct hw_mode_spec *spec) -{ - struct ieee80211_hw *hw = rt2x00dev->hw; - struct ieee80211_channel *channels; - struct ieee80211_rate *rates; - unsigned int num_rates; - unsigned int i; - - num_rates = 0; - if (spec->supported_rates & SUPPORT_RATE_CCK) - num_rates += 4; - if (spec->supported_rates & SUPPORT_RATE_OFDM) - num_rates += 8; - - channels = kzalloc(sizeof(*channels) * spec->num_channels, GFP_KERNEL); - if (!channels) - return -ENOMEM; - - rates = kzalloc(sizeof(*rates) * num_rates, GFP_KERNEL); - if (!rates) - goto exit_free_channels; - - /* - * Initialize Rate list. - */ - for (i = 0; i < num_rates; i++) - rt2x00lib_rate(&rates[i], i, rt2x00_get_rate(i)); - - /* - * Initialize Channel list. - */ - for (i = 0; i < spec->num_channels; i++) { - rt2x00lib_channel(&channels[i], - spec->channels[i].channel, - spec->channels_info[i].tx_power1, i); - } - - /* - * Intitialize 802.11b, 802.11g - * Rates: CCK, OFDM. - * Channels: 2.4 GHz - */ - if (spec->supported_bands & SUPPORT_BAND_2GHZ) { - rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_channels = 14; - rt2x00dev->bands[IEEE80211_BAND_2GHZ].n_bitrates = num_rates; - rt2x00dev->bands[IEEE80211_BAND_2GHZ].channels = channels; - rt2x00dev->bands[IEEE80211_BAND_2GHZ].bitrates = rates; - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = - &rt2x00dev->bands[IEEE80211_BAND_2GHZ]; - memcpy(&rt2x00dev->bands[IEEE80211_BAND_2GHZ].ht_cap, - &spec->ht, sizeof(spec->ht)); - } - - /* - * Intitialize 802.11a - * Rates: OFDM. - * Channels: OFDM, UNII, HiperLAN2. - */ - if (spec->supported_bands & SUPPORT_BAND_5GHZ) { - rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_channels = - spec->num_channels - 14; - rt2x00dev->bands[IEEE80211_BAND_5GHZ].n_bitrates = - num_rates - 4; - rt2x00dev->bands[IEEE80211_BAND_5GHZ].channels = &channels[14]; - rt2x00dev->bands[IEEE80211_BAND_5GHZ].bitrates = &rates[4]; - hw->wiphy->bands[IEEE80211_BAND_5GHZ] = - &rt2x00dev->bands[IEEE80211_BAND_5GHZ]; - memcpy(&rt2x00dev->bands[IEEE80211_BAND_5GHZ].ht_cap, - &spec->ht, sizeof(spec->ht)); - } - - return 0; - - exit_free_channels: - kfree(channels); - ERROR(rt2x00dev, "Allocation ieee80211 modes failed.\n"); - return -ENOMEM; -} - -static void rt2x00lib_remove_hw(struct rt2x00_dev *rt2x00dev) -{ - if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags)) - ieee80211_unregister_hw(rt2x00dev->hw); - - if (likely(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ])) { - kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->channels); - kfree(rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ]->bitrates); - rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; - rt2x00dev->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - } - - kfree(rt2x00dev->spec.channels_info); -} - -static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - int status; - - if (test_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags)) - return 0; - - /* - * Initialize HW modes. - */ - status = rt2x00lib_probe_hw_modes(rt2x00dev, spec); - if (status) - return status; - - /* - * Initialize HW fields. - */ - rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues; - - /* - * Register HW. - */ - status = ieee80211_register_hw(rt2x00dev->hw); - if (status) - return status; - - set_bit(DEVICE_STATE_REGISTERED_HW, &rt2x00dev->flags); - - return 0; -} - -/* - * Initialization/uninitialization handlers. - */ -static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev) -{ - if (!test_and_clear_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags)) - return; - - /* - * Unregister extra components. - */ - rt2x00rfkill_unregister(rt2x00dev); - - /* - * Allow the HW to uninitialize. - */ - rt2x00dev->ops->lib->uninitialize(rt2x00dev); - - /* - * Free allocated queue entries. - */ - rt2x00queue_uninitialize(rt2x00dev); -} - -static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev) -{ - int status; - - if (test_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags)) - return 0; - - /* - * Allocate all queue entries. - */ - status = rt2x00queue_initialize(rt2x00dev); - if (status) - return status; - - /* - * Initialize the device. - */ - status = rt2x00dev->ops->lib->initialize(rt2x00dev); - if (status) { - rt2x00queue_uninitialize(rt2x00dev); - return status; - } - - set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags); - - /* - * Register the extra components. - */ - rt2x00rfkill_register(rt2x00dev); - - return 0; -} - -int rt2x00lib_start(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - if (test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return 0; - - /* - * If this is the first interface which is added, - * we should load the firmware now. - */ - retval = rt2x00lib_load_firmware(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize the device. - */ - retval = rt2x00lib_initialize(rt2x00dev); - if (retval) - return retval; - - rt2x00dev->intf_ap_count = 0; - rt2x00dev->intf_sta_count = 0; - rt2x00dev->intf_associated = 0; - - /* Enable the radio */ - retval = rt2x00lib_enable_radio(rt2x00dev); - if (retval) { - rt2x00queue_uninitialize(rt2x00dev); - return retval; - } - - set_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags); - - return 0; -} - -void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev) -{ - if (!test_and_clear_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return; - - /* - * Perhaps we can add something smarter here, - * but for now just disabling the radio should do. - */ - rt2x00lib_disable_radio(rt2x00dev); - - rt2x00dev->intf_ap_count = 0; - rt2x00dev->intf_sta_count = 0; - rt2x00dev->intf_associated = 0; -} - -/* - * driver allocation handlers. - */ -int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) -{ - int retval = -ENOMEM; - - mutex_init(&rt2x00dev->csr_mutex); - - set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - - /* - * Make room for rt2x00_intf inside the per-interface - * structure ieee80211_vif. - */ - rt2x00dev->hw->vif_data_size = sizeof(struct rt2x00_intf); - - /* - * Determine which operating modes are supported, all modes - * which require beaconing, depend on the availability of - * beacon entries. - */ - rt2x00dev->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - if (rt2x00dev->ops->bcn->entry_num > 0) - rt2x00dev->hw->wiphy->interface_modes |= - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_AP) | - BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_WDS); - - /* - * Let the driver probe the device to detect the capabilities. - */ - retval = rt2x00dev->ops->lib->probe_hw(rt2x00dev); - if (retval) { - ERROR(rt2x00dev, "Failed to allocate device.\n"); - goto exit; - } - - /* - * Initialize configuration work. - */ - INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled); - - /* - * Allocate queue array. - */ - retval = rt2x00queue_allocate(rt2x00dev); - if (retval) - goto exit; - - /* - * Initialize ieee80211 structure. - */ - retval = rt2x00lib_probe_hw(rt2x00dev); - if (retval) { - ERROR(rt2x00dev, "Failed to initialize hw.\n"); - goto exit; - } - - /* - * Register extra components. - */ - rt2x00link_register(rt2x00dev); - rt2x00leds_register(rt2x00dev); - rt2x00debug_register(rt2x00dev); - - return 0; - -exit: - rt2x00lib_remove_dev(rt2x00dev); - - return retval; -} -EXPORT_SYMBOL_GPL(rt2x00lib_probe_dev); - -void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev) -{ - clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - - /* - * Disable radio. - */ - rt2x00lib_disable_radio(rt2x00dev); - - /* - * Stop all work. - */ - cancel_work_sync(&rt2x00dev->intf_work); - - /* - * Uninitialize device. - */ - rt2x00lib_uninitialize(rt2x00dev); - - /* - * Free extra components - */ - rt2x00debug_deregister(rt2x00dev); - rt2x00leds_unregister(rt2x00dev); - - /* - * Free ieee80211_hw memory. - */ - rt2x00lib_remove_hw(rt2x00dev); - - /* - * Free firmware image. - */ - rt2x00lib_free_firmware(rt2x00dev); - - /* - * Free queue structures. - */ - rt2x00queue_free(rt2x00dev); -} -EXPORT_SYMBOL_GPL(rt2x00lib_remove_dev); - -/* - * Device state handlers - */ -#ifdef CONFIG_PM -int rt2x00lib_suspend(struct rt2x00_dev *rt2x00dev, pm_message_t state) -{ - NOTICE(rt2x00dev, "Going to sleep.\n"); - - /* - * Prevent mac80211 from accessing driver while suspended. - */ - if (!test_and_clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return 0; - - /* - * Cleanup as much as possible. - */ - rt2x00lib_uninitialize(rt2x00dev); - - /* - * Suspend/disable extra components. - */ - rt2x00leds_suspend(rt2x00dev); - rt2x00debug_deregister(rt2x00dev); - - /* - * Set device mode to sleep for power management, - * on some hardware this call seems to consistently fail. - * From the specifications it is hard to tell why it fails, - * and if this is a "bad thing". - * Overall it is safe to just ignore the failure and - * continue suspending. The only downside is that the - * device will not be in optimal power save mode, but with - * the radio and the other components already disabled the - * device is as good as disabled. - */ - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_SLEEP)) - WARNING(rt2x00dev, "Device failed to enter sleep state, " - "continue suspending.\n"); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00lib_suspend); - -int rt2x00lib_resume(struct rt2x00_dev *rt2x00dev) -{ - NOTICE(rt2x00dev, "Waking up.\n"); - - /* - * Restore/enable extra components. - */ - rt2x00debug_register(rt2x00dev); - rt2x00leds_resume(rt2x00dev); - - /* - * We are ready again to receive requests from mac80211. - */ - set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00lib_resume); -#endif /* CONFIG_PM */ - -/* - * rt2x00lib module information. - */ -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 library"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00dump.h b/drivers/net/wireless/rt2x00/rt2x00dump.h deleted file mode 100644 index fdedb5122928..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00dump.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00dump - Abstract: Data structures for the rt2x00debug & userspace. - */ - -#ifndef RT2X00DUMP_H -#define RT2X00DUMP_H - -/** - * DOC: Introduction - * - * This header is intended to be exported to userspace, - * to make the structures and enumerations available to userspace - * applications. This means that all data types should be exportable. - * - * When rt2x00 is compiled with debugfs support enabled, - * it is possible to capture all data coming in and out of the device - * by reading the frame dump file. This file can have only a single reader. - * The following frames will be reported: - * - All incoming frames (rx) - * - All outgoing frames (tx, including beacon and atim) - * - All completed frames (txdone including atim) - * - * The data is send to the file using the following format: - * - * [rt2x00dump header][hardware descriptor][ieee802.11 frame] - * - * rt2x00dump header: The description of the dumped frame, as well as - * additional information usefull for debugging. See &rt2x00dump_hdr. - * hardware descriptor: Descriptor that was used to receive or transmit - * the frame. - * ieee802.11 frame: The actual frame that was received or transmitted. - */ - -/** - * enum rt2x00_dump_type - Frame type - * - * These values are used for the @type member of &rt2x00dump_hdr. - * @DUMP_FRAME_RXDONE: This frame has been received by the hardware. - * @DUMP_FRAME_TX: This frame is queued for transmission to the hardware. - * @DUMP_FRAME_TXDONE: This frame indicates the device has handled - * the tx event which has either succeeded or failed. A frame - * with this type should also have been reported with as a - * %DUMP_FRAME_TX frame. - */ -enum rt2x00_dump_type { - DUMP_FRAME_RXDONE = 1, - DUMP_FRAME_TX = 2, - DUMP_FRAME_TXDONE = 3, -}; - -/** - * struct rt2x00dump_hdr - Dump frame header - * - * Each frame dumped to the debugfs file starts with this header - * attached. This header contains the description of the actual - * frame which was dumped. - * - * New fields inside the structure must be appended to the end of - * the structure. This way userspace tools compiled for earlier - * header versions can still correctly handle the frame dump - * (although they will not handle all data passed to them in the dump). - * - * @version: Header version should always be set to %DUMP_HEADER_VERSION. - * This field must be checked by userspace to determine if it can - * handle this frame. - * @header_length: The length of the &rt2x00dump_hdr structure. This is - * used for compatibility reasons so userspace can easily determine - * the location of the next field in the dump. - * @desc_length: The length of the device descriptor. - * @data_length: The length of the frame data (including the ieee802.11 header. - * @chip_rt: RT chipset - * @chip_rf: RF chipset - * @chip_rev: Chipset revision - * @type: The frame type (&rt2x00_dump_type) - * @queue_index: The index number of the data queue. - * @entry_index: The index number of the entry inside the data queue. - * @timestamp_sec: Timestamp - seconds - * @timestamp_usec: Timestamp - microseconds - */ -struct rt2x00dump_hdr { - __le32 version; -#define DUMP_HEADER_VERSION 2 - - __le32 header_length; - __le32 desc_length; - __le32 data_length; - - __le16 chip_rt; - __le16 chip_rf; - __le32 chip_rev; - - __le16 type; - __u8 queue_index; - __u8 entry_index; - - __le32 timestamp_sec; - __le32 timestamp_usec; -}; - -#endif /* RT2X00DUMP_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00firmware.c b/drivers/net/wireless/rt2x00/rt2x00firmware.c deleted file mode 100644 index d2deea2f2679..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00firmware.c +++ /dev/null @@ -1,127 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 firmware loading routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -static int rt2x00lib_request_firmware(struct rt2x00_dev *rt2x00dev) -{ - struct device *device = wiphy_dev(rt2x00dev->hw->wiphy); - const struct firmware *fw; - char *fw_name; - int retval; - - /* - * 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) { - ERROR(rt2x00dev, "Failed to read Firmware.\n"); - return -ENOENT; - } - - INFO(rt2x00dev, "Firmware detected - version: %d.%d.\n", - fw->data[fw->size - 4], fw->data[fw->size - 3]); - - retval = rt2x00dev->ops->lib->check_firmware(rt2x00dev, fw->data, fw->size); - switch (retval) { - case FW_OK: - break; - case FW_BAD_CRC: - ERROR(rt2x00dev, "Firmware checksum error.\n"); - goto exit; - case FW_BAD_LENGTH: - ERROR(rt2x00dev, - "Invalid firmware file length (len=%zu)\n", fw->size); - goto exit; - case FW_BAD_VERSION: - ERROR(rt2x00dev, - "Current firmware does not support detected chipset.\n"); - goto exit; - }; - - rt2x00dev->fw = fw; - - return 0; - -exit: - release_firmware(fw); - - return -ENOENT; -} - -int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - if (!test_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags)) - return 0; - - if (!rt2x00dev->fw) { - retval = rt2x00lib_request_firmware(rt2x00dev); - if (retval) - return retval; - } - - /* - * Send firmware to the device. - */ - retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev, - rt2x00dev->fw->data, - rt2x00dev->fw->size); - - /* - * When the firmware is uploaded to the hardware the LED - * association status might have been triggered, for correct - * LED handling it should now be reset. - */ - rt2x00leds_led_assoc(rt2x00dev, false); - - return retval; -} - -void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) -{ - release_firmware(rt2x00dev->fw); - rt2x00dev->fw = NULL; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00ht.c b/drivers/net/wireless/rt2x00/rt2x00ht.c deleted file mode 100644 index e3cec839e540..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00ht.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 HT specific routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; - - if (tx_info->control.sta) - txdesc->mpdu_density = - tx_info->control.sta->ht_cap.ampdu_density; - else - txdesc->mpdu_density = 0; - - txdesc->ba_size = 7; /* FIXME: What value is needed? */ - txdesc->stbc = 0; /* FIXME: What value is needed? */ - - txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs); - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txdesc->mcs |= 0x08; - - /* - * Convert flags - */ - if (tx_info->flags & IEEE80211_TX_CTL_AMPDU) - __set_bit(ENTRY_TXD_HT_AMPDU, &txdesc->flags); - - /* - * Determine HT Mix/Greenfield rate mode - */ - if (txrate->flags & IEEE80211_TX_RC_MCS) - txdesc->rate_mode = RATE_MODE_HT_MIX; - if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD) - txdesc->rate_mode = RATE_MODE_HT_GREENFIELD; - if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) - __set_bit(ENTRY_TXD_HT_BW_40, &txdesc->flags); - if (txrate->flags & IEEE80211_TX_RC_SHORT_GI) - __set_bit(ENTRY_TXD_HT_SHORT_GI, &txdesc->flags); -} diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.c b/drivers/net/wireless/rt2x00/rt2x00leds.c deleted file mode 100644 index 49671fed91d7..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00leds.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 led specific routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi) -{ - struct rt2x00_led *led = &rt2x00dev->led_qual; - unsigned int brightness; - - if ((led->type != LED_TYPE_QUALITY) || !(led->flags & LED_REGISTERED)) - return; - - /* - * Led handling requires a positive value for the rssi, - * to do that correctly we need to add the correction. - */ - rssi += rt2x00dev->rssi_offset; - - /* - * Get the rssi level, this is used to convert the rssi - * to a LED value inside the range LED_OFF - LED_FULL. - */ - if (rssi <= 30) - rssi = 0; - else if (rssi <= 39) - rssi = 1; - else if (rssi <= 49) - rssi = 2; - else if (rssi <= 53) - rssi = 3; - else if (rssi <= 63) - rssi = 4; - else - rssi = 5; - - /* - * Note that we must _not_ send LED_OFF since the driver - * is going to calculate the value and might use it in a - * division. - */ - brightness = ((LED_FULL / 6) * rssi) + 1; - if (brightness != led->led_dev.brightness) { - led->led_dev.brightness_set(&led->led_dev, brightness); - led->led_dev.brightness = brightness; - } -} - -static void rt2x00led_led_simple(struct rt2x00_led *led, bool enabled) -{ - unsigned int brightness = enabled ? LED_FULL : LED_OFF; - - if (!(led->flags & LED_REGISTERED)) - return; - - led->led_dev.brightness_set(&led->led_dev, brightness); - led->led_dev.brightness = brightness; -} - -void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled) -{ - if (rt2x00dev->led_qual.type == LED_TYPE_ACTIVITY) - rt2x00led_led_simple(&rt2x00dev->led_qual, enabled); -} - -void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled) -{ - if (rt2x00dev->led_assoc.type == LED_TYPE_ASSOC) - rt2x00led_led_simple(&rt2x00dev->led_assoc, enabled); -} - -void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled) -{ - if (rt2x00dev->led_radio.type == LED_TYPE_RADIO) - rt2x00led_led_simple(&rt2x00dev->led_radio, enabled); -} - -static int rt2x00leds_register_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - const char *name) -{ - struct device *device = wiphy_dev(rt2x00dev->hw->wiphy); - int retval; - - led->led_dev.name = name; - led->led_dev.brightness = LED_OFF; - - retval = led_classdev_register(device, &led->led_dev); - if (retval) { - ERROR(rt2x00dev, "Failed to register led handler.\n"); - return retval; - } - - led->flags |= LED_REGISTERED; - - return 0; -} - -void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) -{ - char dev_name[16]; - char name[32]; - int retval; - unsigned long on_period; - unsigned long off_period; - - snprintf(dev_name, sizeof(dev_name), "%s-%s", - rt2x00dev->ops->name, wiphy_name(rt2x00dev->hw->wiphy)); - - if (rt2x00dev->led_radio.flags & LED_INITIALIZED) { - snprintf(name, sizeof(name), "%s::radio", dev_name); - - retval = rt2x00leds_register_led(rt2x00dev, - &rt2x00dev->led_radio, - name); - if (retval) - goto exit_fail; - } - - if (rt2x00dev->led_assoc.flags & LED_INITIALIZED) { - snprintf(name, sizeof(name), "%s::assoc", dev_name); - - retval = rt2x00leds_register_led(rt2x00dev, - &rt2x00dev->led_assoc, - name); - if (retval) - goto exit_fail; - } - - if (rt2x00dev->led_qual.flags & LED_INITIALIZED) { - snprintf(name, sizeof(name), "%s::quality", dev_name); - - retval = rt2x00leds_register_led(rt2x00dev, - &rt2x00dev->led_qual, - name); - if (retval) - goto exit_fail; - } - - /* - * Initialize blink time to default value: - * On period: 70ms - * Off period: 30ms - */ - if (rt2x00dev->led_radio.led_dev.blink_set) { - on_period = 70; - off_period = 30; - rt2x00dev->led_radio.led_dev.blink_set( - &rt2x00dev->led_radio.led_dev, &on_period, &off_period); - } - - return; - -exit_fail: - rt2x00leds_unregister(rt2x00dev); -} - -static void rt2x00leds_unregister_led(struct rt2x00_led *led) -{ - led_classdev_unregister(&led->led_dev); - - /* - * This might look weird, but when we are unregistering while - * suspended the led is already off, and since we haven't - * fully resumed yet, access to the device might not be - * possible yet. - */ - if (!(led->led_dev.flags & LED_SUSPENDED)) - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - - led->flags &= ~LED_REGISTERED; -} - -void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) -{ - if (rt2x00dev->led_qual.flags & LED_REGISTERED) - rt2x00leds_unregister_led(&rt2x00dev->led_qual); - if (rt2x00dev->led_assoc.flags & LED_REGISTERED) - rt2x00leds_unregister_led(&rt2x00dev->led_assoc); - if (rt2x00dev->led_radio.flags & LED_REGISTERED) - rt2x00leds_unregister_led(&rt2x00dev->led_radio); -} - -static inline void rt2x00leds_suspend_led(struct rt2x00_led *led) -{ - led_classdev_suspend(&led->led_dev); - - /* This shouldn't be needed, but just to be safe */ - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - led->led_dev.brightness = LED_OFF; -} - -void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) -{ - if (rt2x00dev->led_qual.flags & LED_REGISTERED) - rt2x00leds_suspend_led(&rt2x00dev->led_qual); - if (rt2x00dev->led_assoc.flags & LED_REGISTERED) - rt2x00leds_suspend_led(&rt2x00dev->led_assoc); - if (rt2x00dev->led_radio.flags & LED_REGISTERED) - rt2x00leds_suspend_led(&rt2x00dev->led_radio); -} - -static inline void rt2x00leds_resume_led(struct rt2x00_led *led) -{ - led_classdev_resume(&led->led_dev); - - /* Device might have enabled the LEDS during resume */ - led->led_dev.brightness_set(&led->led_dev, LED_OFF); - led->led_dev.brightness = LED_OFF; -} - -void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) -{ - if (rt2x00dev->led_radio.flags & LED_REGISTERED) - rt2x00leds_resume_led(&rt2x00dev->led_radio); - if (rt2x00dev->led_assoc.flags & LED_REGISTERED) - rt2x00leds_resume_led(&rt2x00dev->led_assoc); - if (rt2x00dev->led_qual.flags & LED_REGISTERED) - rt2x00leds_resume_led(&rt2x00dev->led_qual); -} diff --git a/drivers/net/wireless/rt2x00/rt2x00leds.h b/drivers/net/wireless/rt2x00/rt2x00leds.h deleted file mode 100644 index 1046977e6a12..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00leds.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 led datastructures and routines - */ - -#ifndef RT2X00LEDS_H -#define RT2X00LEDS_H - -enum led_type { - LED_TYPE_RADIO, - LED_TYPE_ASSOC, - LED_TYPE_ACTIVITY, - LED_TYPE_QUALITY, -}; - -#ifdef CONFIG_RT2X00_LIB_LEDS - -struct rt2x00_led { - struct rt2x00_dev *rt2x00dev; - struct led_classdev led_dev; - - enum led_type type; - unsigned int flags; -#define LED_INITIALIZED ( 1 << 0 ) -#define LED_REGISTERED ( 1 << 1 ) -}; - -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -#endif /* RT2X00LEDS_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00lib.h b/drivers/net/wireless/rt2x00/rt2x00lib.h deleted file mode 100644 index 567f029a8cda..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00lib.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: Data structures and definitions for the rt2x00lib module. - */ - -#ifndef RT2X00LIB_H -#define RT2X00LIB_H - -#include "rt2x00dump.h" - -/* - * Interval defines - */ -#define LINK_TUNE_INTERVAL round_jiffies_relative(HZ) - -/* - * rt2x00_rate: Per rate device information - */ -struct rt2x00_rate { - unsigned short flags; -#define DEV_RATE_CCK 0x0001 -#define DEV_RATE_OFDM 0x0002 -#define DEV_RATE_SHORT_PREAMBLE 0x0004 - - unsigned short bitrate; /* In 100kbit/s */ - unsigned short ratemask; - - unsigned short plcp; - unsigned short mcs; -}; - -extern const struct rt2x00_rate rt2x00_supported_rates[12]; - -static inline const struct rt2x00_rate *rt2x00_get_rate(const u16 hw_value) -{ - return &rt2x00_supported_rates[hw_value & 0xff]; -} - -#define RATE_MCS(__mode, __mcs) \ - ( (((__mode) & 0x00ff) << 8) | ((__mcs) & 0x00ff) ) - -static inline int rt2x00_get_rate_mcs(const u16 mcs_value) -{ - return (mcs_value & 0x00ff); -} - -/* - * Radio control handlers. - */ -int rt2x00lib_enable_radio(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_disable_radio(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_toggle_rx(struct rt2x00_dev *rt2x00dev, enum dev_state state); - -/* - * Initialization handlers. - */ -int rt2x00lib_start(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_stop(struct rt2x00_dev *rt2x00dev); - -/* - * Configuration handlers. - */ -void rt2x00lib_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - enum nl80211_iftype type, - const u8 *mac, const u8 *bssid); -void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct ieee80211_bss_conf *conf); -void rt2x00lib_config_antenna(struct rt2x00_dev *rt2x00dev, - struct antenna_setup ant); -void rt2x00lib_config(struct rt2x00_dev *rt2x00dev, - struct ieee80211_conf *conf, - const unsigned int changed_flags); - -/** - * DOC: Queue handlers - */ - -/** - * rt2x00queue_alloc_rxskb - allocate a skb for RX purposes. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @queue: The queue for which the skb will be applicable. - */ -struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry); - -/** - * rt2x00queue_unmap_skb - Unmap a skb from DMA. - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to unmap. - */ -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** - * rt2x00queue_free_skb - free a skb - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: The skb to free. - */ -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb); - -/** - * rt2x00queue_align_frame - Align 802.11 frame to 4-byte boundary - * @skb: The skb to align - * - * Align the start of the 802.11 frame to a 4-byte boundary, this could - * mean the payload is not aligned properly though. - */ -void rt2x00queue_align_frame(struct sk_buff *skb); - -/** - * rt2x00queue_align_payload - Align 802.11 payload to 4-byte boundary - * @skb: The skb to align - * @header_length: Length of 802.11 header - * - * Align the 802.11 payload to a 4-byte boundary, this could - * mean the header is not aligned properly though. - */ -void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length); - -/** - * rt2x00queue_insert_l2pad - Align 802.11 header & payload to 4-byte boundary - * @skb: The skb to align - * @header_length: Length of 802.11 header - * - * Apply L2 padding to align both header and payload to 4-byte boundary - */ -void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length); - -/** - * rt2x00queue_insert_l2pad - Remove L2 padding from 802.11 frame - * @skb: The skb to align - * @header_length: Length of 802.11 header - * - * Remove L2 padding used to align both header and payload to 4-byte boundary, - * by removing the L2 padding the header will no longer be 4-byte aligned. - */ -void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length); - -/** - * rt2x00queue_write_tx_frame - Write TX frame to hardware - * @queue: Queue over which the frame should be send - * @skb: The skb to send - */ -int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb); - -/** - * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @vif: Interface for which the beacon should be updated. - * @enable_beacon: Enable beaconing - */ -int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif, - const bool enable_beacon); - -/** - * rt2x00queue_index_inc - Index incrementation function - * @queue: Queue (&struct data_queue) to perform the action on. - * @index: Index type (&enum queue_index) to perform the action on. - * - * This function will increase the requested index on the queue, - * it will grab the appropriate locks and handle queue overflow events by - * resetting the index to the start of the queue. - */ -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index); - -/** - * rt2x00queue_stop_queues - Halt all data queues - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * This function will loop through all available queues to stop - * any pending outgoing frames. - */ -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00queue_init_queues - Initialize all data queues - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * This function will loop through all available queues to clear all - * index numbers and set the queue entry to the correct initialization - * state. - */ -void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev); - -int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev); -void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev); -int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev); -void rt2x00queue_free(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00link_update_stats - Update link statistics from RX frame - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @skb: Received frame - * @rxdesc: Received frame descriptor - * - * Update link statistics based on the information from the - * received frame descriptor. - */ -void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct rxdone_entry_desc *rxdesc); - -/** - * rt2x00link_calculate_signal - Calculate signal quality - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @rssi: RX Frame RSSI - * - * Calculate the signal quality of a frame based on the rssi - * measured during the receiving of the frame and the global - * link quality statistics measured since the start of the - * link tuning. The result is a value between 0 and 100 which - * is an indication of the signal quality. - */ -int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi); - -/** - * rt2x00link_start_tuner - Start periodic link tuner work - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * This start the link tuner periodic work, this work will - * be executed periodically until &rt2x00link_stop_tuner has - * been called. - */ -void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00link_stop_tuner - Stop periodic link tuner work - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * After this function completed the link tuner will not - * be running until &rt2x00link_start_tuner is called. - */ -void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00link_reset_tuner - Reset periodic link tuner work - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * @antenna: Should the antenna tuning also be reset - * - * The VGC limit configured in the hardware will be reset to 0 - * which forces the driver to rediscover the correct value for - * the current association. This is needed when configuration - * options have changed which could drastically change the - * SNR level or link quality (i.e. changing the antenna setting). - * - * Resetting the link tuner will also cause the periodic work counter - * to be reset. Any driver which has a fixed limit on the number - * of rounds the link tuner is supposed to work will accept the - * tuner actions again if this limit was previously reached. - * - * If @antenna is set to true a the software antenna diversity - * tuning will also be reset. - */ -void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna); - -/** - * rt2x00link_register - Initialize link tuning functionality - * @rt2x00dev: Pointer to &struct rt2x00_dev. - * - * Initialize work structure and all link tuning related - * parameters. This will not start the link tuning process itself. - */ -void rt2x00link_register(struct rt2x00_dev *rt2x00dev); - -/* - * Firmware handlers. - */ -#ifdef CONFIG_RT2X00_LIB_FIRMWARE -int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev); -void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev); -#else -static inline int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev) -{ - return 0; -} -static inline void rt2x00lib_free_firmware(struct rt2x00_dev *rt2x00dev) -{ -} -#endif /* CONFIG_RT2X00_LIB_FIRMWARE */ - -/* - * Debugfs handlers. - */ -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -void rt2x00debug_register(struct rt2x00_dev *rt2x00dev); -void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev); -void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, - enum rt2x00_dump_type type, struct sk_buff *skb); -void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, - struct rxdone_entry_desc *rxdesc); -#else -static inline void rt2x00debug_register(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00debug_deregister(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, - enum rt2x00_dump_type type, - struct sk_buff *skb) -{ -} - -static inline void rt2x00debug_update_crypto(struct rt2x00_dev *rt2x00dev, - struct rxdone_entry_desc *rxdesc) -{ -} -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -/* - * Crypto handlers. - */ -#ifdef CONFIG_RT2X00_LIB_CRYPTO -enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key); -void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc); -unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb); -void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, - struct txentry_desc *txdesc); -void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, - struct txentry_desc *txdesc); -void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, unsigned int header_length); -void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, - unsigned int header_length, - struct rxdone_entry_desc *rxdesc); -#else -static inline enum cipher rt2x00crypto_key_to_cipher(struct ieee80211_key_conf *key) -{ - return CIPHER_NONE; -} - -static inline void rt2x00crypto_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ -} - -static inline unsigned int rt2x00crypto_tx_overhead(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb) -{ - return 0; -} - -static inline void rt2x00crypto_tx_copy_iv(struct sk_buff *skb, - struct txentry_desc *txdesc) -{ -} - -static inline void rt2x00crypto_tx_remove_iv(struct sk_buff *skb, - struct txentry_desc *txdesc) -{ -} - -static inline void rt2x00crypto_tx_insert_iv(struct sk_buff *skb, - unsigned int header_length) -{ -} - -static inline void rt2x00crypto_rx_insert_iv(struct sk_buff *skb, - unsigned int header_length, - struct rxdone_entry_desc *rxdesc) -{ -} -#endif /* CONFIG_RT2X00_LIB_CRYPTO */ - -/* - * HT handlers. - */ -#ifdef CONFIG_RT2X00_LIB_HT -void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate); -#else -static inline void rt2x00ht_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate) -{ -} -#endif /* CONFIG_RT2X00_LIB_HT */ - -/* - * RFkill handlers. - */ -static inline void rt2x00rfkill_register(struct rt2x00_dev *rt2x00dev) -{ - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) - wiphy_rfkill_start_polling(rt2x00dev->hw->wiphy); -} - -static inline void rt2x00rfkill_unregister(struct rt2x00_dev *rt2x00dev) -{ - if (test_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags)) - wiphy_rfkill_stop_polling(rt2x00dev->hw->wiphy); -} - -/* - * LED handlers - */ -#ifdef CONFIG_RT2X00_LIB_LEDS -void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, int rssi); -void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, bool enabled); -void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, bool enabled); -void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, bool enabled); -void rt2x00leds_register(struct rt2x00_dev *rt2x00dev); -void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev); -void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev); -void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev); -#else -static inline void rt2x00leds_led_quality(struct rt2x00_dev *rt2x00dev, - int rssi) -{ -} - -static inline void rt2x00led_led_activity(struct rt2x00_dev *rt2x00dev, - bool enabled) -{ -} - -static inline void rt2x00leds_led_assoc(struct rt2x00_dev *rt2x00dev, - bool enabled) -{ -} - -static inline void rt2x00leds_led_radio(struct rt2x00_dev *rt2x00dev, - bool enabled) -{ -} - -static inline void rt2x00leds_register(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00leds_unregister(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00leds_suspend(struct rt2x00_dev *rt2x00dev) -{ -} - -static inline void rt2x00leds_resume(struct rt2x00_dev *rt2x00dev) -{ -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -#endif /* RT2X00LIB_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00link.c b/drivers/net/wireless/rt2x00/rt2x00link.c deleted file mode 100644 index c708d0be9155..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00link.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 link tuning routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -/* - * When we lack RSSI information return something less then -80 to - * tell the driver to tune the device to maximum sensitivity. - */ -#define DEFAULT_RSSI -128 - -/* - * When no TX/RX percentage could be calculated due to lack of - * frames on the air, we fallback to a percentage of 50%. - * This will assure we will get at least get some decent value - * when the link tuner starts. - * The value will be dropped and overwritten with the correct (measured) - * value anyway during the first run of the link tuner. - */ -#define DEFAULT_PERCENTAGE 50 - -/* - * Small helper macro for percentage calculation - * This is a very simple macro with the only catch that it will - * produce a default value in case no total value was provided. - */ -#define PERCENTAGE(__value, __total) \ - ( (__total) ? (((__value) * 100) / (__total)) : (DEFAULT_PERCENTAGE) ) - -/* - * Helper struct and macro to work with moving/walking averages. - * When adding a value to the average value the following calculation - * is needed: - * - * avg_rssi = ((avg_rssi * 7) + rssi) / 8; - * - * The advantage of this approach is that we only need 1 variable - * to store the average in (No need for a count and a total). - * But more importantly, normal average values will over time - * move less and less towards newly added values this results - * that with link tuning, the device can have a very good RSSI - * for a few minutes but when the device is moved away from the AP - * the average will not decrease fast enough to compensate. - * The walking average compensates this and will move towards - * the new values correctly allowing a effective link tuning, - * the speed of the average moving towards other values depends - * on the value for the number of samples. The higher the number - * of samples, the slower the average will move. - * We use two variables to keep track of the average value to - * compensate for the rounding errors. This can be a significant - * error (>5dBm) if the factor is too low. - */ -#define AVG_SAMPLES 8 -#define AVG_FACTOR 1000 -#define MOVING_AVERAGE(__avg, __val) \ -({ \ - struct avg_val __new; \ - __new.avg_weight = \ - (__avg).avg_weight ? \ - ((((__avg).avg_weight * ((AVG_SAMPLES) - 1)) + \ - ((__val) * (AVG_FACTOR))) / \ - (AVG_SAMPLES) ) : \ - ((__val) * (AVG_FACTOR)); \ - __new.avg = __new.avg_weight / (AVG_FACTOR); \ - __new; \ -}) - -/* - * For calculating the Signal quality we have determined - * the total number of success and failed RX and TX frames. - * With the addition of the average RSSI value we can determine - * the link quality using the following algorithm: - * - * rssi_percentage = (avg_rssi * 100) / rssi_offset - * rx_percentage = (rx_success * 100) / rx_total - * tx_percentage = (tx_success * 100) / tx_total - * avg_signal = ((WEIGHT_RSSI * avg_rssi) + - * (WEIGHT_TX * tx_percentage) + - * (WEIGHT_RX * rx_percentage)) / 100 - * - * This value should then be checked to not be greater then 100. - * This means the values of WEIGHT_RSSI, WEIGHT_RX, WEIGHT_TX must - * sum up to 100 as well. - */ -#define WEIGHT_RSSI 20 -#define WEIGHT_RX 40 -#define WEIGHT_TX 40 - -static int rt2x00link_antenna_get_link_rssi(struct rt2x00_dev *rt2x00dev) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - - if (ant->rssi_ant.avg && rt2x00dev->link.qual.rx_success) - return ant->rssi_ant.avg; - return DEFAULT_RSSI; -} - -static int rt2x00link_antenna_get_rssi_history(struct rt2x00_dev *rt2x00dev) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - - if (ant->rssi_history) - return ant->rssi_history; - return DEFAULT_RSSI; -} - -static void rt2x00link_antenna_update_rssi_history(struct rt2x00_dev *rt2x00dev, - int rssi) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - ant->rssi_history = rssi; -} - -static void rt2x00link_antenna_reset(struct rt2x00_dev *rt2x00dev) -{ - rt2x00dev->link.ant.rssi_ant.avg = 0; - rt2x00dev->link.ant.rssi_ant.avg_weight = 0; -} - -static void rt2x00lib_antenna_diversity_sample(struct rt2x00_dev *rt2x00dev) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - struct antenna_setup new_ant; - int other_antenna; - - int sample_current = rt2x00link_antenna_get_link_rssi(rt2x00dev); - int sample_other = rt2x00link_antenna_get_rssi_history(rt2x00dev); - - memcpy(&new_ant, &ant->active, sizeof(new_ant)); - - /* - * We are done sampling. Now we should evaluate the results. - */ - ant->flags &= ~ANTENNA_MODE_SAMPLE; - - /* - * During the last period we have sampled the RSSI - * from both antennas. It now is time to determine - * which antenna demonstrated the best performance. - * When we are already on the antenna with the best - * performance, just create a good starting point - * for the history and we are done. - */ - if (sample_current >= sample_other) { - rt2x00link_antenna_update_rssi_history(rt2x00dev, - sample_current); - return; - } - - other_antenna = (ant->active.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; - - if (ant->flags & ANTENNA_RX_DIVERSITY) - new_ant.rx = other_antenna; - - if (ant->flags & ANTENNA_TX_DIVERSITY) - new_ant.tx = other_antenna; - - rt2x00lib_config_antenna(rt2x00dev, new_ant); -} - -static void rt2x00lib_antenna_diversity_eval(struct rt2x00_dev *rt2x00dev) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - struct antenna_setup new_ant; - int rssi_curr; - int rssi_old; - - memcpy(&new_ant, &ant->active, sizeof(new_ant)); - - /* - * Get current RSSI value along with the historical value, - * after that update the history with the current value. - */ - rssi_curr = rt2x00link_antenna_get_link_rssi(rt2x00dev); - rssi_old = rt2x00link_antenna_get_rssi_history(rt2x00dev); - rt2x00link_antenna_update_rssi_history(rt2x00dev, rssi_curr); - - /* - * Legacy driver indicates that we should swap antenna's - * when the difference in RSSI is greater that 5. This - * also should be done when the RSSI was actually better - * then the previous sample. - * When the difference exceeds the threshold we should - * sample the rssi from the other antenna to make a valid - * comparison between the 2 antennas. - */ - if (abs(rssi_curr - rssi_old) < 5) - return; - - ant->flags |= ANTENNA_MODE_SAMPLE; - - if (ant->flags & ANTENNA_RX_DIVERSITY) - new_ant.rx = (new_ant.rx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; - - if (ant->flags & ANTENNA_TX_DIVERSITY) - new_ant.tx = (new_ant.tx == ANTENNA_A) ? ANTENNA_B : ANTENNA_A; - - rt2x00lib_config_antenna(rt2x00dev, new_ant); -} - -static bool rt2x00lib_antenna_diversity(struct rt2x00_dev *rt2x00dev) -{ - struct link_ant *ant = &rt2x00dev->link.ant; - unsigned int flags = ant->flags; - - /* - * Determine if software diversity is enabled for - * either the TX or RX antenna (or both). - * Always perform this check since within the link - * tuner interval the configuration might have changed. - */ - flags &= ~ANTENNA_RX_DIVERSITY; - flags &= ~ANTENNA_TX_DIVERSITY; - - if (rt2x00dev->default_ant.rx == ANTENNA_SW_DIVERSITY) - flags |= ANTENNA_RX_DIVERSITY; - if (rt2x00dev->default_ant.tx == ANTENNA_SW_DIVERSITY) - flags |= ANTENNA_TX_DIVERSITY; - - if (!(ant->flags & ANTENNA_RX_DIVERSITY) && - !(ant->flags & ANTENNA_TX_DIVERSITY)) { - ant->flags = 0; - return true; - } - - /* Update flags */ - ant->flags = flags; - - /* - * If we have only sampled the data over the last period - * we should now harvest the data. Otherwise just evaluate - * the data. The latter should only be performed once - * every 2 seconds. - */ - if (ant->flags & ANTENNA_MODE_SAMPLE) { - rt2x00lib_antenna_diversity_sample(rt2x00dev); - return true; - } else if (rt2x00dev->link.count & 1) { - rt2x00lib_antenna_diversity_eval(rt2x00dev); - return true; - } - - return false; -} - -void rt2x00link_update_stats(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct rxdone_entry_desc *rxdesc) -{ - struct link *link = &rt2x00dev->link; - struct link_qual *qual = &rt2x00dev->link.qual; - struct link_ant *ant = &rt2x00dev->link.ant; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; - - /* - * Frame was received successfully since non-succesfull - * frames would have been dropped by the hardware. - */ - qual->rx_success++; - - /* - * We are only interested in quality statistics from - * beacons which came from the BSS which we are - * associated with. - */ - if (!ieee80211_is_beacon(hdr->frame_control) || - !(rxdesc->dev_flags & RXDONE_MY_BSS)) - return; - - /* - * Update global RSSI - */ - link->avg_rssi = MOVING_AVERAGE(link->avg_rssi, rxdesc->rssi); - - /* - * Update antenna RSSI - */ - ant->rssi_ant = MOVING_AVERAGE(ant->rssi_ant, rxdesc->rssi); -} - -static void rt2x00link_precalculate_signal(struct rt2x00_dev *rt2x00dev) -{ - struct link *link = &rt2x00dev->link; - struct link_qual *qual = &rt2x00dev->link.qual; - - link->rx_percentage = - PERCENTAGE(qual->rx_success, qual->rx_failed + qual->rx_success); - link->tx_percentage = - PERCENTAGE(qual->tx_success, qual->tx_failed + qual->tx_success); -} - -int rt2x00link_calculate_signal(struct rt2x00_dev *rt2x00dev, int rssi) -{ - struct link *link = &rt2x00dev->link; - int rssi_percentage = 0; - int signal; - - /* - * We need a positive value for the RSSI. - */ - if (rssi < 0) - rssi += rt2x00dev->rssi_offset; - - /* - * Calculate the different percentages, - * which will be used for the signal. - */ - rssi_percentage = PERCENTAGE(rssi, rt2x00dev->rssi_offset); - - /* - * Add the individual percentages and use the WEIGHT - * defines to calculate the current link signal. - */ - signal = ((WEIGHT_RSSI * rssi_percentage) + - (WEIGHT_TX * link->tx_percentage) + - (WEIGHT_RX * link->rx_percentage)) / 100; - - return max_t(int, signal, 100); -} - -void rt2x00link_start_tuner(struct rt2x00_dev *rt2x00dev) -{ - struct link *link = &rt2x00dev->link; - - /* - * Link tuning should only be performed when - * an active sta or master interface exists. - * Single monitor mode interfaces should never have - * work with link tuners. - */ - if (!rt2x00dev->intf_ap_count && !rt2x00dev->intf_sta_count) - return; - - link->rx_percentage = DEFAULT_PERCENTAGE; - link->tx_percentage = DEFAULT_PERCENTAGE; - - rt2x00link_reset_tuner(rt2x00dev, false); - - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->work, LINK_TUNE_INTERVAL); -} - -void rt2x00link_stop_tuner(struct rt2x00_dev *rt2x00dev) -{ - cancel_delayed_work_sync(&rt2x00dev->link.work); -} - -void rt2x00link_reset_tuner(struct rt2x00_dev *rt2x00dev, bool antenna) -{ - struct link_qual *qual = &rt2x00dev->link.qual; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - /* - * Reset link information. - * Both the currently active vgc level as well as - * the link tuner counter should be reset. Resetting - * the counter is important for devices where the - * device should only perform link tuning during the - * first minute after being enabled. - */ - rt2x00dev->link.count = 0; - memset(qual, 0, sizeof(*qual)); - - /* - * Reset the link tuner. - */ - rt2x00dev->ops->lib->reset_tuner(rt2x00dev, qual); - - if (antenna) - rt2x00link_antenna_reset(rt2x00dev); -} - -static void rt2x00link_reset_qual(struct rt2x00_dev *rt2x00dev) -{ - struct link_qual *qual = &rt2x00dev->link.qual; - - qual->rx_success = 0; - qual->rx_failed = 0; - qual->tx_success = 0; - qual->tx_failed = 0; -} - -static void rt2x00link_tuner(struct work_struct *work) -{ - struct rt2x00_dev *rt2x00dev = - container_of(work, struct rt2x00_dev, link.work.work); - struct link *link = &rt2x00dev->link; - struct link_qual *qual = &rt2x00dev->link.qual; - - /* - * When the radio is shutting down we should - * immediately cease all link tuning. - */ - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return; - - /* - * Update statistics. - */ - rt2x00dev->ops->lib->link_stats(rt2x00dev, qual); - rt2x00dev->low_level_stats.dot11FCSErrorCount += qual->rx_failed; - - /* - * Update quality RSSI for link tuning, - * when we have received some frames and we managed to - * collect the RSSI data we could use this. Otherwise we - * must fallback to the default RSSI value. - */ - if (!link->avg_rssi.avg || !qual->rx_success) - qual->rssi = DEFAULT_RSSI; - else - qual->rssi = link->avg_rssi.avg; - - /* - * Only perform the link tuning when Link tuning - * has been enabled (This could have been disabled from the EEPROM). - */ - if (!test_bit(CONFIG_DISABLE_LINK_TUNING, &rt2x00dev->flags)) - rt2x00dev->ops->lib->link_tuner(rt2x00dev, qual, link->count); - - /* - * Precalculate a portion of the link signal which is - * in based on the tx/rx success/failure counters. - */ - rt2x00link_precalculate_signal(rt2x00dev); - - /* - * Send a signal to the led to update the led signal strength. - */ - rt2x00leds_led_quality(rt2x00dev, qual->rssi); - - /* - * Evaluate antenna setup, make this the last step when - * rt2x00lib_antenna_diversity made changes the quality - * statistics will be reset. - */ - if (rt2x00lib_antenna_diversity(rt2x00dev)) - rt2x00link_reset_qual(rt2x00dev); - - /* - * Increase tuner counter, and reschedule the next link tuner run. - */ - link->count++; - - if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - ieee80211_queue_delayed_work(rt2x00dev->hw, - &link->work, LINK_TUNE_INTERVAL); -} - -void rt2x00link_register(struct rt2x00_dev *rt2x00dev) -{ - INIT_DELAYED_WORK(&rt2x00dev->link.work, rt2x00link_tuner); -} diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c deleted file mode 100644 index 929b85f34f38..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00mac - Abstract: rt2x00 generic mac80211 routines. - */ - -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -static int rt2x00mac_tx_rts_cts(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, - struct sk_buff *frag_skb) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(frag_skb); - struct ieee80211_tx_info *rts_info; - struct sk_buff *skb; - unsigned int data_length; - int retval = 0; - - if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - data_length = sizeof(struct ieee80211_cts); - else - data_length = sizeof(struct ieee80211_rts); - - skb = dev_alloc_skb(data_length + rt2x00dev->hw->extra_tx_headroom); - if (unlikely(!skb)) { - WARNING(rt2x00dev, "Failed to create RTS/CTS frame.\n"); - return -ENOMEM; - } - - skb_reserve(skb, rt2x00dev->hw->extra_tx_headroom); - skb_put(skb, data_length); - - /* - * Copy TX information over from original frame to - * RTS/CTS frame. Note that we set the no encryption flag - * since we don't want this frame to be encrypted. - * RTS frames should be acked, while CTS-to-self frames - * should not. The ready for TX flag is cleared to prevent - * it being automatically send when the descriptor is - * written to the hardware. - */ - memcpy(skb->cb, frag_skb->cb, sizeof(skb->cb)); - rts_info = IEEE80211_SKB_CB(skb); - rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_RTS_CTS; - rts_info->control.rates[0].flags &= ~IEEE80211_TX_RC_USE_CTS_PROTECT; - rts_info->flags &= ~IEEE80211_TX_CTL_REQ_TX_STATUS; - - if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - rts_info->flags |= IEEE80211_TX_CTL_NO_ACK; - else - rts_info->flags &= ~IEEE80211_TX_CTL_NO_ACK; - - /* Disable hardware encryption */ - rts_info->control.hw_key = NULL; - - /* - * RTS/CTS frame should use the length of the frame plus any - * encryption overhead that will be added by the hardware. - */ - data_length += rt2x00crypto_tx_overhead(rt2x00dev, skb); - - if (tx_info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - ieee80211_ctstoself_get(rt2x00dev->hw, tx_info->control.vif, - frag_skb->data, data_length, tx_info, - (struct ieee80211_cts *)(skb->data)); - else - ieee80211_rts_get(rt2x00dev->hw, tx_info->control.vif, - frag_skb->data, data_length, tx_info, - (struct ieee80211_rts *)(skb->data)); - - retval = rt2x00queue_write_tx_frame(queue, skb); - if (retval) { - dev_kfree_skb_any(skb); - WARNING(rt2x00dev, "Failed to send RTS/CTS frame.\n"); - } - - return retval; -} - -int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); - struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data; - enum data_queue_qid qid = skb_get_queue_mapping(skb); - struct data_queue *queue; - 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_STATE_PRESENT, &rt2x00dev->flags)) - goto exit_fail; - - /* - * Determine which queue to put packet on. - */ - if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM && - test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) - queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM); - else - queue = rt2x00queue_get_queue(rt2x00dev, qid); - if (unlikely(!queue)) { - ERROR(rt2x00dev, - "Attempt to send packet over invalid queue %d.\n" - "Please file bug report to %s.\n", qid, DRV_PROJECT); - goto exit_fail; - } - - /* - * If CTS/RTS is required. create and queue that frame first. - * Make sure we have at least enough entries available to send - * this CTS/RTS frame as well as the data frame. - * Note that when the driver has set the set_rts_threshold() - * callback function it doesn't need software generation of - * either RTS or CTS-to-self frame and handles everything - * inside the hardware. - */ - frame_control = le16_to_cpu(ieee80211hdr->frame_control); - if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | - IEEE80211_TX_RC_USE_CTS_PROTECT)) && - !rt2x00dev->ops->hw->set_rts_threshold) { - if (rt2x00queue_available(queue) <= 1) - goto exit_fail; - - if (rt2x00mac_tx_rts_cts(rt2x00dev, queue, skb)) - goto exit_fail; - } - - if (rt2x00queue_write_tx_frame(queue, skb)) - goto exit_fail; - - if (rt2x00queue_threshold(queue)) - ieee80211_stop_queue(rt2x00dev->hw, qid); - - return NETDEV_TX_OK; - - exit_fail: - ieee80211_stop_queue(rt2x00dev->hw, qid); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} -EXPORT_SYMBOL_GPL(rt2x00mac_tx); - -int rt2x00mac_start(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return 0; - - return rt2x00lib_start(rt2x00dev); -} -EXPORT_SYMBOL_GPL(rt2x00mac_start); - -void rt2x00mac_stop(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return; - - rt2x00lib_stop(rt2x00dev); -} -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 rt2x00_intf *intf = vif_to_intf(conf->vif); - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON); - struct queue_entry *entry = NULL; - unsigned int i; - - /* - * Don't allow interfaces to be added - * the device has disappeared. - */ - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - !test_bit(DEVICE_STATE_STARTED, &rt2x00dev->flags)) - return -ENODEV; - - switch (conf->type) { - case NL80211_IFTYPE_AP: - /* - * We don't support mixed combinations of - * sta and ap interfaces. - */ - if (rt2x00dev->intf_sta_count) - return -ENOBUFS; - - /* - * Check if we exceeded the maximum amount - * of supported interfaces. - */ - if (rt2x00dev->intf_ap_count >= rt2x00dev->ops->max_ap_intf) - return -ENOBUFS; - - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_WDS: - /* - * We don't support mixed combinations of - * sta and ap interfaces. - */ - if (rt2x00dev->intf_ap_count) - return -ENOBUFS; - - /* - * Check if we exceeded the maximum amount - * of supported interfaces. - */ - if (rt2x00dev->intf_sta_count >= rt2x00dev->ops->max_sta_intf) - return -ENOBUFS; - - break; - default: - return -EINVAL; - } - - /* - * Loop through all beacon queues to find a free - * entry. Since there are as much beacon entries - * as the maximum interfaces, this search shouldn't - * fail. - */ - for (i = 0; i < queue->limit; i++) { - entry = &queue->entries[i]; - if (!test_and_set_bit(ENTRY_BCN_ASSIGNED, &entry->flags)) - break; - } - - if (unlikely(i == queue->limit)) - return -ENOBUFS; - - /* - * We are now absolutely sure the interface can be created, - * increase interface count and start initialization. - */ - - if (conf->type == NL80211_IFTYPE_AP) - rt2x00dev->intf_ap_count++; - else - rt2x00dev->intf_sta_count++; - - spin_lock_init(&intf->lock); - spin_lock_init(&intf->seqlock); - mutex_init(&intf->beacon_skb_mutex); - intf->beacon = entry; - - if (conf->type == NL80211_IFTYPE_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_intf(rt2x00dev, intf, conf->type, intf->mac, NULL); - - /* - * Some filters depend on the current working mode. We can force - * an update during the next configure_filter() run by mac80211 by - * resetting the current packet_filter state. - */ - rt2x00dev->packet_filter = 0; - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_add_interface); - -void rt2x00mac_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(conf->vif); - - /* - * Don't allow interfaces to be remove while - * either the device has disappeared or when - * no interface is present. - */ - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags) || - (conf->type == NL80211_IFTYPE_AP && !rt2x00dev->intf_ap_count) || - (conf->type != NL80211_IFTYPE_AP && !rt2x00dev->intf_sta_count)) - return; - - if (conf->type == NL80211_IFTYPE_AP) - rt2x00dev->intf_ap_count--; - else - rt2x00dev->intf_sta_count--; - - /* - * Release beacon entry so it is available for - * new interfaces again. - */ - clear_bit(ENTRY_BCN_ASSIGNED, &intf->beacon->flags); - - /* - * Make sure the bssid and mac address registers - * are cleared to prevent false ACKing of frames. - */ - rt2x00lib_config_intf(rt2x00dev, intf, - NL80211_IFTYPE_UNSPECIFIED, NULL, NULL); -} -EXPORT_SYMBOL_GPL(rt2x00mac_remove_interface); - -int rt2x00mac_config(struct ieee80211_hw *hw, u32 changed) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - - /* - * mac80211 might be calling this function while we are trying - * to remove the device or perhaps suspending it. - */ - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return 0; - - /* - * Some configuration parameters (e.g. channel and antenna values) can - * only be set when the radio is enabled, but do require the RX to - * be off. - */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_OFF); - - /* - * When we've just turned on the radio, we want to reprogram - * everything to ensure a consistent state - */ - rt2x00lib_config(rt2x00dev, conf, changed); - - /* - * After the radio has been enabled we need to configure - * the antenna to the default settings. rt2x00lib_config_antenna() - * should determine if any action should be taken based on - * checking if diversity has been enabled or no antenna changes - * have been made since the last configuration change. - */ - rt2x00lib_config_antenna(rt2x00dev, rt2x00dev->default_ant); - - /* Turn RX back on */ - rt2x00lib_toggle_rx(rt2x00dev, STATE_RADIO_RX_ON); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_config); - -void rt2x00mac_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - /* - * Mask off any flags we are going to ignore - * from the total_flags field. - */ - *total_flags &= - FIF_ALLMULTI | - FIF_FCSFAIL | - FIF_PLCPFAIL | - FIF_CONTROL | - FIF_PSPOLL | - FIF_OTHER_BSS | - FIF_PROMISC_IN_BSS; - - /* - * Apply some rules to the filters: - * - Some filters imply different filters to be set. - * - Some things we can't filter out at all. - * - Multicast filter seems to kill broadcast traffic so never use it. - */ - *total_flags |= FIF_ALLMULTI; - if (*total_flags & FIF_OTHER_BSS || - *total_flags & FIF_PROMISC_IN_BSS) - *total_flags |= FIF_PROMISC_IN_BSS | FIF_OTHER_BSS; - - /* - * If the device has a single filter for all control frames, - * FIF_CONTROL and FIF_PSPOLL flags imply each other. - * And if the device has more than one filter for control frames - * of different types, but has no a separate filter for PS Poll frames, - * FIF_CONTROL flag implies FIF_PSPOLL. - */ - if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags)) { - if (*total_flags & FIF_CONTROL || *total_flags & FIF_PSPOLL) - *total_flags |= FIF_CONTROL | FIF_PSPOLL; - } - if (!test_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags)) { - if (*total_flags & FIF_CONTROL) - *total_flags |= FIF_PSPOLL; - } - - /* - * Check if there is any work left for us. - */ - if (rt2x00dev->packet_filter == *total_flags) - return; - rt2x00dev->packet_filter = *total_flags; - - rt2x00dev->ops->lib->config_filter(rt2x00dev, *total_flags); -} -EXPORT_SYMBOL_GPL(rt2x00mac_configure_filter); - -int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta, - bool set) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - rt2x00lib_beacondone(rt2x00dev); - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_set_tim); - -#ifdef CONFIG_RT2X00_LIB_CRYPTO -static void memcpy_tkip(struct rt2x00lib_crypto *crypto, u8 *key, u8 key_len) -{ - if (key_len > NL80211_TKIP_DATA_OFFSET_ENCR_KEY) - memcpy(&crypto->key, - &key[NL80211_TKIP_DATA_OFFSET_ENCR_KEY], - sizeof(crypto->key)); - - if (key_len > NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY) - memcpy(&crypto->tx_mic, - &key[NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY], - sizeof(crypto->tx_mic)); - - if (key_len > NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY) - memcpy(&crypto->rx_mic, - &key[NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY], - sizeof(crypto->rx_mic)); -} - -int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(vif); - int (*set_key) (struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key); - struct rt2x00lib_crypto crypto; - static const u8 bcast_addr[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, }; - - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return 0; - else if (!test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) - return -EOPNOTSUPP; - else if (key->keylen > 32) - return -ENOSPC; - - memset(&crypto, 0, sizeof(crypto)); - - /* - * When in STA mode, bssidx is always 0 otherwise local_address[5] - * contains the bss number, see BSS_ID_MASK comments for details. - */ - if (rt2x00dev->intf_sta_count) - crypto.bssidx = 0; - else - crypto.bssidx = intf->mac[5] & (rt2x00dev->ops->max_ap_intf - 1); - - crypto.cipher = rt2x00crypto_key_to_cipher(key); - if (crypto.cipher == CIPHER_NONE) - return -EOPNOTSUPP; - - crypto.cmd = cmd; - - if (sta) { - /* some drivers need the AID */ - crypto.aid = sta->aid; - crypto.address = sta->addr; - } else - crypto.address = bcast_addr; - - if (crypto.cipher == CIPHER_TKIP) - memcpy_tkip(&crypto, &key->key[0], key->keylen); - else - memcpy(&crypto.key, &key->key[0], key->keylen); - /* - * Each BSS has a maximum of 4 shared keys. - * Shared key index values: - * 0) BSS0 key0 - * 1) BSS0 key1 - * ... - * 4) BSS1 key0 - * ... - * 8) BSS2 key0 - * ... - * Both pairwise as shared key indeces are determined by - * driver. This is required because the hardware requires - * keys to be assigned in correct order (When key 1 is - * provided but key 0 is not, then the key is not found - * by the hardware during RX). - */ - if (cmd == SET_KEY) - key->hw_key_idx = 0; - - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) - set_key = rt2x00dev->ops->lib->config_pairwise_key; - else - set_key = rt2x00dev->ops->lib->config_shared_key; - - if (!set_key) - return -EOPNOTSUPP; - - return set_key(rt2x00dev, &crypto, key); -} -EXPORT_SYMBOL_GPL(rt2x00mac_set_key); -#endif /* CONFIG_RT2X00_LIB_CRYPTO */ - -int rt2x00mac_get_stats(struct ieee80211_hw *hw, - struct ieee80211_low_level_stats *stats) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - - /* - * The dot11ACKFailureCount, dot11RTSFailureCount and - * dot11RTSSuccessCount are updated in interrupt time. - * dot11FCSErrorCount is updated in the link tuner. - */ - memcpy(stats, &rt2x00dev->low_level_stats, sizeof(*stats)); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_get_stats); - -int rt2x00mac_get_tx_stats(struct ieee80211_hw *hw, - struct ieee80211_tx_queue_stats *stats) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - unsigned int i; - - for (i = 0; i < rt2x00dev->ops->tx_queues; i++) { - stats[i].len = rt2x00dev->tx[i].length; - stats[i].limit = rt2x00dev->tx[i].limit; - stats[i].count = rt2x00dev->tx[i].count; - } - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_get_tx_stats); - -void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct rt2x00_intf *intf = vif_to_intf(vif); - int update_bssid = 0; - - /* - * mac80211 might be calling this function while we are trying - * to remove the device or perhaps suspending it. - */ - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return; - - spin_lock(&intf->lock); - - /* - * conf->bssid can be NULL if coming from the internal - * beacon update routine. - */ - if (changes & BSS_CHANGED_BSSID) { - update_bssid = 1; - memcpy(&intf->bssid, bss_conf->bssid, ETH_ALEN); - } - - spin_unlock(&intf->lock); - - /* - * Call rt2x00_config_intf() outside of the spinlock context since - * the call will sleep for USB drivers. By using the ieee80211_if_conf - * values as arguments we make keep access to rt2x00_intf thread safe - * even without the lock. - */ - if (changes & BSS_CHANGED_BSSID) - rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL, - update_bssid ? bss_conf->bssid : NULL); - - /* - * Update the beacon. - */ - if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED)) - rt2x00queue_update_beacon(rt2x00dev, vif, - bss_conf->enable_beacon); - - /* - * When the association status has changed we must reset the link - * tuner counter. This is because some drivers determine if they - * should perform link tuning based on the number of seconds - * while associated or not associated. - */ - if (changes & BSS_CHANGED_ASSOC) { - rt2x00dev->link.count = 0; - - if (bss_conf->assoc) - rt2x00dev->intf_associated++; - else - rt2x00dev->intf_associated--; - - rt2x00leds_led_assoc(rt2x00dev, !!rt2x00dev->intf_associated); - } - - /* - * When the erp information has changed, we should perform - * additional configuration steps. For all other changes we are done. - */ - if (changes & ~(BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) - rt2x00lib_config_erp(rt2x00dev, intf, bss_conf); -} -EXPORT_SYMBOL_GPL(rt2x00mac_bss_info_changed); - -int rt2x00mac_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, - const struct ieee80211_tx_queue_params *params) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_queue *queue; - - queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - if (unlikely(!queue)) - return -EINVAL; - - /* - * The passed variables are stored as real value ((2^n)-1). - * Ralink registers require to know the bit number 'n'. - */ - if (params->cw_min > 0) - queue->cw_min = fls(params->cw_min); - else - queue->cw_min = 5; /* cw_min: 2^5 = 32. */ - - if (params->cw_max > 0) - queue->cw_max = fls(params->cw_max); - else - queue->cw_max = 10; /* cw_min: 2^10 = 1024. */ - - queue->aifs = params->aifs; - queue->txop = params->txop; - - INFO(rt2x00dev, - "Configured TX queue %d - CWmin: %d, CWmax: %d, Aifs: %d, TXop: %d.\n", - queue_idx, queue->cw_min, queue->cw_max, queue->aifs, queue->txop); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00mac_conf_tx); - -void rt2x00mac_rfkill_poll(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - bool active = !!rt2x00dev->ops->lib->rfkill_poll(rt2x00dev); - - wiphy_rfkill_set_hw_state(hw->wiphy, !active); -} -EXPORT_SYMBOL_GPL(rt2x00mac_rfkill_poll); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c deleted file mode 100644 index cdd5154bd4c0..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00pci.c +++ /dev/null @@ -1,409 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00pci - Abstract: rt2x00 generic pci device routines. - */ - -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00pci.h" - -/* - * Register access. - */ -int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const struct rt2x00_field32 field, - u32 *reg) -{ - unsigned int i; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, offset, reg); - if (!rt2x00_get_field32(*reg, field)) - return 1; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "Indirect register access failed: " - "offset=0x%.08x, value=0x%.08x\n", offset, *reg); - *reg = ~0; - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00pci_regbusy_read); - -/* - * TX data handlers. - */ -int rt2x00pci_write_tx_data(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc; - - /* - * This should not happen, we already checked the entry - * was ours. When the hardware disagrees there has been - * a queue corruption! - */ - if (unlikely(rt2x00dev->ops->lib->get_entry_state(entry))) { - ERROR(rt2x00dev, - "Corrupt queue %d, accessing entry which is not ours.\n" - "Please file bug report to %s.\n", - entry->queue->qid, DRV_PROJECT); - return -EINVAL; - } - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(entry->skb); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = entry->queue->desc_size; - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00pci_write_tx_data); - -/* - * TX/RX data handlers. - */ -void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue = rt2x00dev->rx; - struct queue_entry *entry; - struct queue_entry_priv_pci *entry_priv; - struct skb_frame_desc *skbdesc; - - while (1) { - entry = rt2x00queue_get_entry(queue, Q_INDEX); - entry_priv = entry->priv_data; - - if (rt2x00dev->ops->lib->get_entry_state(entry)) - break; - - /* - * Fill in desc fields of the skb descriptor - */ - skbdesc = get_skb_frame_desc(entry->skb); - skbdesc->desc = entry_priv->desc; - skbdesc->desc_len = entry->queue->desc_size; - - /* - * Send the frame to rt2x00lib for further processing. - */ - rt2x00lib_rxdone(rt2x00dev, entry); - } -} -EXPORT_SYMBOL_GPL(rt2x00pci_rxdone); - -/* - * Device initialization handlers. - */ -static int rt2x00pci_alloc_queue_dma(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - struct queue_entry_priv_pci *entry_priv; - void *addr; - dma_addr_t dma; - unsigned int i; - - /* - * Allocate DMA memory for descriptor and buffer. - */ - addr = dma_alloc_coherent(rt2x00dev->dev, - queue->limit * queue->desc_size, - &dma, GFP_KERNEL | GFP_DMA); - if (!addr) - return -ENOMEM; - - memset(addr, 0, queue->limit * queue->desc_size); - - /* - * Initialize all queue entries to contain valid addresses. - */ - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - entry_priv->desc = addr + i * queue->desc_size; - entry_priv->desc_dma = dma + i * queue->desc_size; - } - - return 0; -} - -static void rt2x00pci_free_queue_dma(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - struct queue_entry_priv_pci *entry_priv = - queue->entries[0].priv_data; - - if (entry_priv->desc) - dma_free_coherent(rt2x00dev->dev, - queue->limit * queue->desc_size, - entry_priv->desc, entry_priv->desc_dma); - entry_priv->desc = NULL; -} - -int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - int status; - - /* - * Allocate DMA - */ - queue_for_each(rt2x00dev, queue) { - status = rt2x00pci_alloc_queue_dma(rt2x00dev, queue); - if (status) - goto exit; - } - - /* - * Register interrupt handler. - */ - status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler, - IRQF_SHARED, rt2x00dev->name, rt2x00dev); - if (status) { - ERROR(rt2x00dev, "IRQ %d allocation failed (error %d).\n", - rt2x00dev->irq, status); - goto exit; - } - - return 0; - -exit: - queue_for_each(rt2x00dev, queue) - rt2x00pci_free_queue_dma(rt2x00dev, queue); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00pci_initialize); - -void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - /* - * Free irq line. - */ - free_irq(to_pci_dev(rt2x00dev->dev)->irq, rt2x00dev); - - /* - * Free DMA - */ - queue_for_each(rt2x00dev, queue) - rt2x00pci_free_queue_dma(rt2x00dev, queue); -} -EXPORT_SYMBOL_GPL(rt2x00pci_uninitialize); - -/* - * PCI driver handlers. - */ -static void rt2x00pci_free_reg(struct rt2x00_dev *rt2x00dev) -{ - kfree(rt2x00dev->rf); - rt2x00dev->rf = NULL; - - kfree(rt2x00dev->eeprom); - rt2x00dev->eeprom = NULL; - - if (rt2x00dev->csr.base) { - iounmap(rt2x00dev->csr.base); - rt2x00dev->csr.base = NULL; - } -} - -static int rt2x00pci_alloc_reg(struct rt2x00_dev *rt2x00dev) -{ - struct pci_dev *pci_dev = to_pci_dev(rt2x00dev->dev); - - rt2x00dev->csr.base = pci_ioremap_bar(pci_dev, 0); - if (!rt2x00dev->csr.base) - 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) -{ - struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_data; - struct ieee80211_hw *hw; - struct rt2x00_dev *rt2x00dev; - int retval; - u16 chip; - - retval = pci_request_regions(pci_dev, pci_name(pci_dev)); - if (retval) { - ERROR_PROBE("PCI request regions failed.\n"); - return retval; - } - - retval = pci_enable_device(pci_dev); - if (retval) { - ERROR_PROBE("Enable device failed.\n"); - goto exit_release_regions; - } - - pci_set_master(pci_dev); - - if (pci_set_mwi(pci_dev)) - ERROR_PROBE("MWI not available.\n"); - - if (dma_set_mask(&pci_dev->dev, DMA_BIT_MASK(32))) { - ERROR_PROBE("PCI DMA not supported.\n"); - retval = -EIO; - goto exit_disable_device; - } - - hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); - if (!hw) { - ERROR_PROBE("Failed to allocate hardware.\n"); - retval = -ENOMEM; - goto exit_disable_device; - } - - pci_set_drvdata(pci_dev, hw); - - rt2x00dev = hw->priv; - rt2x00dev->dev = &pci_dev->dev; - rt2x00dev->ops = ops; - rt2x00dev->hw = hw; - rt2x00dev->irq = pci_dev->irq; - rt2x00dev->name = pci_name(pci_dev); - - /* - * Determine RT chipset by reading PCI header. - */ - pci_read_config_word(pci_dev, PCI_DEVICE_ID, &chip); - rt2x00_set_chip_rt(rt2x00dev, chip); - - retval = rt2x00pci_alloc_reg(rt2x00dev); - if (retval) - goto exit_free_device; - - retval = rt2x00lib_probe_dev(rt2x00dev); - if (retval) - goto exit_free_reg; - - return 0; - -exit_free_reg: - rt2x00pci_free_reg(rt2x00dev); - -exit_free_device: - ieee80211_free_hw(hw); - -exit_disable_device: - if (retval != -EBUSY) - pci_disable_device(pci_dev); - -exit_release_regions: - pci_release_regions(pci_dev); - - pci_set_drvdata(pci_dev, NULL); - - return retval; -} -EXPORT_SYMBOL_GPL(rt2x00pci_probe); - -void rt2x00pci_remove(struct pci_dev *pci_dev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); - struct rt2x00_dev *rt2x00dev = hw->priv; - - /* - * Free all allocated data. - */ - rt2x00lib_remove_dev(rt2x00dev); - rt2x00pci_free_reg(rt2x00dev); - ieee80211_free_hw(hw); - - /* - * Free the PCI device data. - */ - pci_set_drvdata(pci_dev, NULL); - pci_disable_device(pci_dev); - pci_release_regions(pci_dev); -} -EXPORT_SYMBOL_GPL(rt2x00pci_remove); - -#ifdef CONFIG_PM -int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); - struct rt2x00_dev *rt2x00dev = hw->priv; - int retval; - - retval = rt2x00lib_suspend(rt2x00dev, state); - if (retval) - return retval; - - pci_save_state(pci_dev); - pci_disable_device(pci_dev); - return pci_set_power_state(pci_dev, pci_choose_state(pci_dev, state)); -} -EXPORT_SYMBOL_GPL(rt2x00pci_suspend); - -int rt2x00pci_resume(struct pci_dev *pci_dev) -{ - struct ieee80211_hw *hw = pci_get_drvdata(pci_dev); - struct rt2x00_dev *rt2x00dev = hw->priv; - - if (pci_set_power_state(pci_dev, PCI_D0) || - pci_enable_device(pci_dev) || - pci_restore_state(pci_dev)) { - ERROR(rt2x00dev, "Failed to resume device.\n"); - return -EIO; - } - - return rt2x00lib_resume(rt2x00dev); -} -EXPORT_SYMBOL_GPL(rt2x00pci_resume); -#endif /* CONFIG_PM */ - -/* - * rt2x00pci module information. - */ -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 pci library"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h deleted file mode 100644 index 15a12487e04b..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00pci.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00pci - Abstract: Data structures for the rt2x00pci module. - */ - -#ifndef RT2X00PCI_H -#define RT2X00PCI_H - -#include - -/* - * This variable should be used with the - * pci_driver structure initialization. - */ -#define PCI_DEVICE_DATA(__ops) .driver_data = (kernel_ulong_t)(__ops) - -/* - * Register defines. - * Some registers require multiple attempts before success, - * in those cases REGISTER_BUSY_COUNT attempts should be - * taken with a REGISTER_BUSY_DELAY interval. - */ -#define REGISTER_BUSY_COUNT 5 -#define REGISTER_BUSY_DELAY 100 - -/* - * Register access. - */ -static inline void rt2x00pci_register_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 *value) -{ - *value = readl(rt2x00dev->csr.base + offset); -} - -static inline void -rt2x00pci_register_multiread(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u16 length) -{ - memcpy_fromio(value, rt2x00dev->csr.base + offset, length); -} - -static inline void rt2x00pci_register_write(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 value) -{ - writel(value, rt2x00dev->csr.base + offset); -} - -static inline void -rt2x00pci_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const void *value, const u16 length) -{ - memcpy_toio(rt2x00dev->csr.base + offset, value, length); -} - -/** - * rt2x00pci_regbusy_read - Read from register with busy check - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @field: Field to check if register is busy - * @reg: Pointer to where register contents should be stored - * - * This function will read the given register, and checks if the - * register is busy. If it is, it will sleep for a couple of - * microseconds before reading the register again. If the register - * is not read after a certain timeout, this function will return - * FALSE. - */ -int rt2x00pci_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - const struct rt2x00_field32 field, - u32 *reg); - -/** - * rt2x00pci_write_tx_data - Initialize data for TX operation - * @entry: The entry where the frame is located - * - * This function will initialize the DMA and skb descriptor - * to prepare the entry for the actual TX operation. - */ -int rt2x00pci_write_tx_data(struct queue_entry *entry); - -/** - * struct queue_entry_priv_pci: Per entry PCI specific information - * - * @desc: Pointer to device descriptor - * @desc_dma: DMA pointer to &desc. - * @data: Pointer to device's entry memory. - * @data_dma: DMA pointer to &data. - */ -struct queue_entry_priv_pci { - __le32 *desc; - dma_addr_t desc_dma; -}; - -/** - * rt2x00pci_rxdone - Handle RX done events - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - */ -void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev); - -/* - * Device initialization handlers. - */ -int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev); -void rt2x00pci_uninitialize(struct rt2x00_dev *rt2x00dev); - -/* - * PCI driver handlers. - */ -int rt2x00pci_probe(struct pci_dev *pci_dev, const struct pci_device_id *id); -void rt2x00pci_remove(struct pci_dev *pci_dev); -#ifdef CONFIG_PM -int rt2x00pci_suspend(struct pci_dev *pci_dev, pm_message_t state); -int rt2x00pci_resume(struct pci_dev *pci_dev); -#else -#define rt2x00pci_suspend NULL -#define rt2x00pci_resume NULL -#endif /* CONFIG_PM */ - -#endif /* RT2X00PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c deleted file mode 100644 index 577029efe320..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ /dev/null @@ -1,921 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 queue specific routines. - */ - -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00lib.h" - -struct sk_buff *rt2x00queue_alloc_rxskb(struct rt2x00_dev *rt2x00dev, - struct queue_entry *entry) -{ - struct sk_buff *skb; - struct skb_frame_desc *skbdesc; - unsigned int frame_size; - unsigned int head_size = 0; - unsigned int tail_size = 0; - - /* - * The frame size includes descriptor size, because the - * hardware directly receive the frame into the skbuffer. - */ - frame_size = entry->queue->data_size + entry->queue->desc_size; - - /* - * The payload should be aligned to a 4-byte boundary, - * this means we need at least 3 bytes for moving the frame - * into the correct offset. - */ - head_size = 4; - - /* - * For IV/EIV/ICV assembly we must make sure there is - * at least 8 bytes bytes available in headroom for IV/EIV - * and 8 bytes for ICV data as tailroon. - */ - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - head_size += 8; - tail_size += 8; - } - - /* - * Allocate skbuffer. - */ - skb = dev_alloc_skb(frame_size + head_size + tail_size); - if (!skb) - return NULL; - - /* - * Make sure we not have a frame with the requested bytes - * available in the head and tail. - */ - skb_reserve(skb, head_size); - skb_put(skb, frame_size); - - /* - * Populate skbdesc. - */ - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->entry = entry; - - if (test_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags)) { - skbdesc->skb_dma = dma_map_single(rt2x00dev->dev, - skb->data, - skb->len, - DMA_FROM_DEVICE); - skbdesc->flags |= SKBDESC_DMA_MAPPED_RX; - } - - return skb; -} - -void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - - /* - * If device has requested headroom, we should make sure that - * is also mapped to the DMA so it can be used for transfering - * additional descriptor information to the hardware. - */ - skb_push(skb, rt2x00dev->hw->extra_tx_headroom); - - skbdesc->skb_dma = - dma_map_single(rt2x00dev->dev, skb->data, skb->len, DMA_TO_DEVICE); - - /* - * Restore data pointer to original location again. - */ - skb_pull(skb, rt2x00dev->hw->extra_tx_headroom); - - skbdesc->flags |= SKBDESC_DMA_MAPPED_TX; -} -EXPORT_SYMBOL_GPL(rt2x00queue_map_txskb); - -void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - - if (skbdesc->flags & SKBDESC_DMA_MAPPED_RX) { - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, skb->len, - DMA_FROM_DEVICE); - skbdesc->flags &= ~SKBDESC_DMA_MAPPED_RX; - } - - if (skbdesc->flags & SKBDESC_DMA_MAPPED_TX) { - /* - * Add headroom to the skb length, it has been removed - * by the driver, but it was actually mapped to DMA. - */ - dma_unmap_single(rt2x00dev->dev, skbdesc->skb_dma, - skb->len + rt2x00dev->hw->extra_tx_headroom, - DMA_TO_DEVICE); - skbdesc->flags &= ~SKBDESC_DMA_MAPPED_TX; - } -} - -void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb) -{ - if (!skb) - return; - - rt2x00queue_unmap_skb(rt2x00dev, skb); - dev_kfree_skb_any(skb); -} - -void rt2x00queue_align_frame(struct sk_buff *skb) -{ - unsigned int frame_length = skb->len; - unsigned int align = ALIGN_SIZE(skb, 0); - - if (!align) - return; - - skb_push(skb, align); - memmove(skb->data, skb->data + align, frame_length); - skb_trim(skb, frame_length); -} - -void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_lengt) -{ - unsigned int frame_length = skb->len; - unsigned int align = ALIGN_SIZE(skb, header_lengt); - - if (!align) - return; - - skb_push(skb, align); - memmove(skb->data, skb->data + align, frame_length); - skb_trim(skb, frame_length); -} - -void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int frame_length = skb->len; - unsigned int header_align = ALIGN_SIZE(skb, 0); - unsigned int payload_align = ALIGN_SIZE(skb, header_length); - unsigned int l2pad = 4 - (payload_align - header_align); - - if (header_align == payload_align) { - /* - * Both header and payload must be moved the same - * amount of bytes to align them properly. This means - * we don't use the L2 padding but just move the entire - * frame. - */ - rt2x00queue_align_frame(skb); - } else if (!payload_align) { - /* - * Simple L2 padding, only the header needs to be moved, - * the payload is already properly aligned. - */ - skb_push(skb, header_align); - memmove(skb->data, skb->data + header_align, frame_length); - skbdesc->flags |= SKBDESC_L2_PADDED; - } else { - /* - * - * Complicated L2 padding, both header and payload need - * to be moved. By default we only move to the start - * of the buffer, so our header alignment needs to be - * increased if there is not enough room for the header - * to be moved. - */ - if (payload_align > header_align) - header_align += 4; - - skb_push(skb, header_align); - memmove(skb->data, skb->data + header_align, header_length); - memmove(skb->data + header_length + l2pad, - skb->data + header_length + l2pad + header_align, - frame_length - header_length); - skbdesc->flags |= SKBDESC_L2_PADDED; - } -} - -void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - unsigned int l2pad = 4 - (header_length & 3); - - if (!l2pad || (skbdesc->flags & SKBDESC_L2_PADDED)) - return; - - memmove(skb->data + l2pad, skb->data, header_length); - skb_pull(skb, l2pad); -} - -static void rt2x00queue_create_tx_descriptor_seq(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif); - unsigned long irqflags; - - if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) || - unlikely(!tx_info->control.vif)) - return; - - /* - * Hardware should insert sequence counter. - * FIXME: We insert a software sequence counter first for - * hardware that doesn't support hardware sequence counting. - * - * This is wrong because beacons are not getting sequence - * numbers assigned properly. - * - * A secondary problem exists for drivers that cannot toggle - * sequence counting per-frame, since those will override the - * sequence counter given by mac80211. - */ - spin_lock_irqsave(&intf->seqlock, irqflags); - - if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags)) - intf->seqno += 0x10; - hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); - hdr->seq_ctrl |= cpu_to_le16(intf->seqno); - - spin_unlock_irqrestore(&intf->seqlock, irqflags); - - __set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags); -} - -static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry, - struct txentry_desc *txdesc, - const struct rt2x00_rate *hwrate) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0]; - unsigned int data_length; - unsigned int duration; - unsigned int residual; - - /* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */ - data_length = entry->skb->len + 4; - data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb); - - /* - * PLCP setup - * Length calculation depends on OFDM/CCK rate. - */ - txdesc->signal = hwrate->plcp; - txdesc->service = 0x04; - - if (hwrate->flags & DEV_RATE_OFDM) { - txdesc->length_high = (data_length >> 6) & 0x3f; - txdesc->length_low = data_length & 0x3f; - } else { - /* - * Convert length to microseconds. - */ - residual = GET_DURATION_RES(data_length, hwrate->bitrate); - duration = GET_DURATION(data_length, hwrate->bitrate); - - if (residual != 0) { - duration++; - - /* - * Check if we need to set the Length Extension - */ - if (hwrate->bitrate == 110 && residual <= 30) - txdesc->service |= 0x80; - } - - txdesc->length_high = (duration >> 8) & 0xff; - txdesc->length_low = duration & 0xff; - - /* - * When preamble is enabled we should set the - * preamble bit for the signal. - */ - if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - txdesc->signal |= 0x08; - } -} - -static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data; - struct ieee80211_rate *rate = - ieee80211_get_tx_rate(rt2x00dev->hw, tx_info); - const struct rt2x00_rate *hwrate; - - memset(txdesc, 0, sizeof(*txdesc)); - - /* - * Initialize information from queue - */ - txdesc->queue = entry->queue->qid; - txdesc->cw_min = entry->queue->cw_min; - txdesc->cw_max = entry->queue->cw_max; - txdesc->aifs = entry->queue->aifs; - - /* - * Header and alignment information. - */ - txdesc->header_length = ieee80211_get_hdrlen_from_skb(entry->skb); - txdesc->l2pad = ALIGN_SIZE(entry->skb, txdesc->header_length); - - /* - * Check whether this frame is to be acked. - */ - if (!(tx_info->flags & IEEE80211_TX_CTL_NO_ACK)) - __set_bit(ENTRY_TXD_ACK, &txdesc->flags); - - /* - * Check if this is a RTS/CTS frame - */ - if (ieee80211_is_rts(hdr->frame_control) || - ieee80211_is_cts(hdr->frame_control)) { - __set_bit(ENTRY_TXD_BURST, &txdesc->flags); - if (ieee80211_is_rts(hdr->frame_control)) - __set_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags); - else - __set_bit(ENTRY_TXD_CTS_FRAME, &txdesc->flags); - if (tx_info->control.rts_cts_rate_idx >= 0) - rate = - ieee80211_get_rts_cts_rate(rt2x00dev->hw, tx_info); - } - - /* - * Determine retry information. - */ - txdesc->retry_limit = tx_info->control.rates[0].count - 1; - if (txdesc->retry_limit >= rt2x00dev->long_retry) - __set_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags); - - /* - * Check if more fragments are pending - */ - if (ieee80211_has_morefrags(hdr->frame_control) || - (tx_info->flags & IEEE80211_TX_CTL_MORE_FRAMES)) { - __set_bit(ENTRY_TXD_BURST, &txdesc->flags); - __set_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags); - } - - /* - * Beacons and probe responses require the tsf timestamp - * to be inserted into the frame. - */ - if (ieee80211_is_beacon(hdr->frame_control) || - ieee80211_is_probe_resp(hdr->frame_control)) - __set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags); - - /* - * Determine with what IFS priority this frame should be send. - * Set ifs to IFS_SIFS when the this is not the first fragment, - * or this fragment came after RTS/CTS. - */ - if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) && - !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) { - __set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags); - txdesc->ifs = IFS_BACKOFF; - } else - txdesc->ifs = IFS_SIFS; - - /* - * Determine rate modulation. - */ - hwrate = rt2x00_get_rate(rate->hw_value); - txdesc->rate_mode = RATE_MODE_CCK; - if (hwrate->flags & DEV_RATE_OFDM) - txdesc->rate_mode = RATE_MODE_OFDM; - - /* - * Apply TX descriptor handling by components - */ - rt2x00crypto_create_tx_descriptor(entry, txdesc); - rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate); - rt2x00queue_create_tx_descriptor_seq(entry, txdesc); - rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate); -} - -static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry, - struct txentry_desc *txdesc) -{ - struct data_queue *queue = entry->queue; - struct rt2x00_dev *rt2x00dev = queue->rt2x00dev; - - rt2x00dev->ops->lib->write_tx_desc(rt2x00dev, entry->skb, txdesc); - - /* - * All processing on the frame has been completed, this means - * it is now ready to be dumped to userspace through debugfs. - */ - rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TX, entry->skb); - - /* - * Check if we need to kick the queue, there are however a few rules - * 1) Don't kick beacon queue - * 2) Don't kick unless this is the last in frame in a burst. - * When the burst flag is set, this frame is always followed - * by another frame which in some way are related to eachother. - * This is true for fragments, RTS or CTS-to-self frames. - * 3) Rule 2 can be broken when the available entries - * in the queue are less then a certain threshold. - */ - if (entry->queue->qid == QID_BEACON) - return; - - if (rt2x00queue_threshold(queue) || - !test_bit(ENTRY_TXD_BURST, &txdesc->flags)) - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid); -} - -int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb) -{ - struct ieee80211_tx_info *tx_info; - struct queue_entry *entry = rt2x00queue_get_entry(queue, Q_INDEX); - struct txentry_desc txdesc; - struct skb_frame_desc *skbdesc; - u8 rate_idx, rate_flags; - - if (unlikely(rt2x00queue_full(queue))) - return -ENOBUFS; - - if (test_and_set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) { - ERROR(queue->rt2x00dev, - "Arrived at non-free entry in the non-full queue %d.\n" - "Please file bug report to %s.\n", - queue->qid, DRV_PROJECT); - return -EINVAL; - } - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - entry->skb = skb; - rt2x00queue_create_tx_descriptor(entry, &txdesc); - - /* - * All information is retrieved from the skb->cb array, - * now we should claim ownership of the driver part of that - * array, preserving the bitrate index and flags. - */ - tx_info = IEEE80211_SKB_CB(skb); - rate_idx = tx_info->control.rates[0].idx; - rate_flags = tx_info->control.rates[0].flags; - skbdesc = get_skb_frame_desc(skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->entry = entry; - skbdesc->tx_rate_idx = rate_idx; - skbdesc->tx_rate_flags = rate_flags; - - /* - * When hardware encryption is supported, and this frame - * is to be encrypted, we should strip the IV/EIV data from - * the frame so we can provide it to the driver seperately. - */ - if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc.flags) && - !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc.flags)) { - if (test_bit(DRIVER_REQUIRE_COPY_IV, &queue->rt2x00dev->flags)) - rt2x00crypto_tx_copy_iv(skb, &txdesc); - else - rt2x00crypto_tx_remove_iv(skb, &txdesc); - } - - /* - * When DMA allocation is required we should guarentee to the - * driver that the DMA is aligned to a 4-byte boundary. - * However some drivers require L2 padding to pad the payload - * rather then the header. This could be a requirement for - * PCI and USB devices, while header alignment only is valid - * for PCI devices. - */ - if (test_bit(DRIVER_REQUIRE_L2PAD, &queue->rt2x00dev->flags)) - rt2x00queue_insert_l2pad(entry->skb, txdesc.header_length); - else if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) - rt2x00queue_align_frame(entry->skb); - - /* - * It could be possible that the queue was corrupted and this - * call failed. Since we always return NETDEV_TX_OK to mac80211, - * this frame will simply be dropped. - */ - if (unlikely(queue->rt2x00dev->ops->lib->write_tx_data(entry))) { - clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - entry->skb = NULL; - return -EIO; - } - - if (test_bit(DRIVER_REQUIRE_DMA, &queue->rt2x00dev->flags)) - rt2x00queue_map_txskb(queue->rt2x00dev, skb); - - set_bit(ENTRY_DATA_PENDING, &entry->flags); - - rt2x00queue_index_inc(queue, Q_INDEX); - rt2x00queue_write_tx_descriptor(entry, &txdesc); - - return 0; -} - -int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev, - struct ieee80211_vif *vif, - const bool enable_beacon) -{ - struct rt2x00_intf *intf = vif_to_intf(vif); - struct skb_frame_desc *skbdesc; - struct txentry_desc txdesc; - __le32 desc[16]; - - if (unlikely(!intf->beacon)) - return -ENOBUFS; - - mutex_lock(&intf->beacon_skb_mutex); - - /* - * Clean up the beacon skb. - */ - rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb); - intf->beacon->skb = NULL; - - if (!enable_beacon) { - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_BEACON); - mutex_unlock(&intf->beacon_skb_mutex); - return 0; - } - - intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif); - if (!intf->beacon->skb) { - mutex_unlock(&intf->beacon_skb_mutex); - return -ENOMEM; - } - - /* - * Copy all TX descriptor information into txdesc, - * after that we are free to use the skb->cb array - * for our information. - */ - rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc); - - /* - * For the descriptor we use a local array from where the - * driver can move it to the correct location required for - * the hardware. - */ - memset(desc, 0, sizeof(desc)); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(intf->beacon->skb); - memset(skbdesc, 0, sizeof(*skbdesc)); - skbdesc->desc = desc; - skbdesc->desc_len = intf->beacon->queue->desc_size; - skbdesc->entry = intf->beacon; - - /* - * Write TX descriptor into reserved room in front of the beacon. - */ - rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc); - - /* - * Send beacon to hardware. - * Also enable beacon generation, which might have been disabled - * by the driver during the config_beacon() callback function. - */ - rt2x00dev->ops->lib->write_beacon(intf->beacon); - rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON); - - mutex_unlock(&intf->beacon_skb_mutex); - - return 0; -} - -struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - - if (queue == QID_RX) - return rt2x00dev->rx; - - if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx) - return &rt2x00dev->tx[queue]; - - if (!rt2x00dev->bcn) - return NULL; - - if (queue == QID_BEACON) - return &rt2x00dev->bcn[0]; - else if (queue == QID_ATIM && atim) - return &rt2x00dev->bcn[1]; - - return NULL; -} -EXPORT_SYMBOL_GPL(rt2x00queue_get_queue); - -struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue, - enum queue_index index) -{ - struct queue_entry *entry; - unsigned long irqflags; - - if (unlikely(index >= Q_INDEX_MAX)) { - ERROR(queue->rt2x00dev, - "Entry requested from invalid index type (%d)\n", index); - return NULL; - } - - spin_lock_irqsave(&queue->lock, irqflags); - - entry = &queue->entries[queue->index[index]]; - - spin_unlock_irqrestore(&queue->lock, irqflags); - - return entry; -} -EXPORT_SYMBOL_GPL(rt2x00queue_get_entry); - -void rt2x00queue_index_inc(struct data_queue *queue, enum queue_index index) -{ - unsigned long irqflags; - - if (unlikely(index >= Q_INDEX_MAX)) { - ERROR(queue->rt2x00dev, - "Index change on invalid index type (%d)\n", index); - return; - } - - spin_lock_irqsave(&queue->lock, irqflags); - - queue->index[index]++; - if (queue->index[index] >= queue->limit) - queue->index[index] = 0; - - if (index == Q_INDEX) { - queue->length++; - } else if (index == Q_INDEX_DONE) { - queue->length--; - queue->count++; - } - - spin_unlock_irqrestore(&queue->lock, irqflags); -} - -static void rt2x00queue_reset(struct data_queue *queue) -{ - unsigned long irqflags; - - spin_lock_irqsave(&queue->lock, irqflags); - - queue->count = 0; - queue->length = 0; - memset(queue->index, 0, sizeof(queue->index)); - - spin_unlock_irqrestore(&queue->lock, irqflags); -} - -void rt2x00queue_stop_queues(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - txall_queue_for_each(rt2x00dev, queue) - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, queue->qid); -} - -void rt2x00queue_init_queues(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - unsigned int i; - - queue_for_each(rt2x00dev, queue) { - rt2x00queue_reset(queue); - - for (i = 0; i < queue->limit; i++) { - queue->entries[i].flags = 0; - - rt2x00dev->ops->lib->clear_entry(&queue->entries[i]); - } - } -} - -static int rt2x00queue_alloc_entries(struct data_queue *queue, - const struct data_queue_desc *qdesc) -{ - struct queue_entry *entries; - unsigned int entry_size; - unsigned int i; - - rt2x00queue_reset(queue); - - queue->limit = qdesc->entry_num; - queue->threshold = DIV_ROUND_UP(qdesc->entry_num, 10); - queue->data_size = qdesc->data_size; - queue->desc_size = qdesc->desc_size; - - /* - * Allocate all queue entries. - */ - entry_size = sizeof(*entries) + qdesc->priv_size; - entries = kzalloc(queue->limit * entry_size, GFP_KERNEL); - if (!entries) - return -ENOMEM; - -#define QUEUE_ENTRY_PRIV_OFFSET(__base, __index, __limit, __esize, __psize) \ - ( ((char *)(__base)) + ((__limit) * (__esize)) + \ - ((__index) * (__psize)) ) - - for (i = 0; i < queue->limit; i++) { - entries[i].flags = 0; - entries[i].queue = queue; - entries[i].skb = NULL; - entries[i].entry_idx = i; - entries[i].priv_data = - QUEUE_ENTRY_PRIV_OFFSET(entries, i, queue->limit, - sizeof(*entries), qdesc->priv_size); - } - -#undef QUEUE_ENTRY_PRIV_OFFSET - - queue->entries = entries; - - return 0; -} - -static void rt2x00queue_free_skbs(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - unsigned int i; - - if (!queue->entries) - return; - - for (i = 0; i < queue->limit; i++) { - if (queue->entries[i].skb) - rt2x00queue_free_skb(rt2x00dev, queue->entries[i].skb); - } -} - -static int rt2x00queue_alloc_rxskbs(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - unsigned int i; - struct sk_buff *skb; - - for (i = 0; i < queue->limit; i++) { - skb = rt2x00queue_alloc_rxskb(rt2x00dev, &queue->entries[i]); - if (!skb) - return -ENOMEM; - queue->entries[i].skb = skb; - } - - return 0; -} - -int rt2x00queue_initialize(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - int status; - - status = rt2x00queue_alloc_entries(rt2x00dev->rx, rt2x00dev->ops->rx); - if (status) - goto exit; - - tx_queue_for_each(rt2x00dev, queue) { - status = rt2x00queue_alloc_entries(queue, rt2x00dev->ops->tx); - if (status) - goto exit; - } - - status = rt2x00queue_alloc_entries(rt2x00dev->bcn, rt2x00dev->ops->bcn); - if (status) - goto exit; - - if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) { - status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1], - rt2x00dev->ops->atim); - if (status) - goto exit; - } - - status = rt2x00queue_alloc_rxskbs(rt2x00dev, rt2x00dev->rx); - if (status) - goto exit; - - return 0; - -exit: - ERROR(rt2x00dev, "Queue entries allocation failed.\n"); - - rt2x00queue_uninitialize(rt2x00dev); - - return status; -} - -void rt2x00queue_uninitialize(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - rt2x00queue_free_skbs(rt2x00dev, rt2x00dev->rx); - - queue_for_each(rt2x00dev, queue) { - kfree(queue->entries); - queue->entries = NULL; - } -} - -static void rt2x00queue_init(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue, enum data_queue_qid qid) -{ - spin_lock_init(&queue->lock); - - queue->rt2x00dev = rt2x00dev; - queue->qid = qid; - queue->txop = 0; - queue->aifs = 2; - queue->cw_min = 5; - queue->cw_max = 10; -} - -int rt2x00queue_allocate(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - enum data_queue_qid qid; - unsigned int req_atim = - !!test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags); - - /* - * We need the following queues: - * RX: 1 - * TX: ops->tx_queues - * Beacon: 1 - * Atim: 1 (if required) - */ - rt2x00dev->data_queues = 2 + rt2x00dev->ops->tx_queues + req_atim; - - queue = kzalloc(rt2x00dev->data_queues * sizeof(*queue), GFP_KERNEL); - if (!queue) { - ERROR(rt2x00dev, "Queue allocation failed.\n"); - return -ENOMEM; - } - - /* - * Initialize pointers - */ - rt2x00dev->rx = queue; - rt2x00dev->tx = &queue[1]; - rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues]; - - /* - * Initialize queue parameters. - * RX: qid = QID_RX - * TX: qid = QID_AC_BE + index - * TX: cw_min: 2^5 = 32. - * TX: cw_max: 2^10 = 1024. - * BCN: qid = QID_BEACON - * ATIM: qid = QID_ATIM - */ - rt2x00queue_init(rt2x00dev, rt2x00dev->rx, QID_RX); - - qid = QID_AC_BE; - tx_queue_for_each(rt2x00dev, queue) - rt2x00queue_init(rt2x00dev, queue, qid++); - - rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_BEACON); - if (req_atim) - rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_ATIM); - - return 0; -} - -void rt2x00queue_free(struct rt2x00_dev *rt2x00dev) -{ - kfree(rt2x00dev->rx); - rt2x00dev->rx = NULL; - rt2x00dev->tx = NULL; - rt2x00dev->bcn = NULL; -} diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.h b/drivers/net/wireless/rt2x00/rt2x00queue.h deleted file mode 100644 index a5591fb2b191..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00queue.h +++ /dev/null @@ -1,639 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 queue datastructures and routines - */ - -#ifndef RT2X00QUEUE_H -#define RT2X00QUEUE_H - -#include - -/** - * DOC: Entry frame size - * - * Ralink PCI devices demand the Frame size to be a multiple of 128 bytes, - * for USB devices this restriction does not apply, but the value of - * 2432 makes sense since it is big enough to contain the maximum fragment - * size according to the ieee802.11 specs. - * The aggregation size depends on support from the driver, but should - * be something around 3840 bytes. - */ -#define DATA_FRAME_SIZE 2432 -#define MGMT_FRAME_SIZE 256 -#define AGGREGATION_SIZE 3840 - -/** - * DOC: Number of entries per queue - * - * Under normal load without fragmentation, 12 entries are sufficient - * without the queue being filled up to the maximum. When using fragmentation - * and the queue threshold code, we need to add some additional margins to - * make sure the queue will never (or only under extreme load) fill up - * completely. - * Since we don't use preallocated DMA, having a large number of queue entries - * will have minimal impact on the memory requirements for the queue. - */ -#define RX_ENTRIES 24 -#define TX_ENTRIES 24 -#define BEACON_ENTRIES 1 -#define ATIM_ENTRIES 8 - -/** - * enum data_queue_qid: Queue identification - * - * @QID_AC_BE: AC BE queue - * @QID_AC_BK: AC BK queue - * @QID_AC_VI: AC VI queue - * @QID_AC_VO: AC VO queue - * @QID_HCCA: HCCA queue - * @QID_MGMT: MGMT queue (prio queue) - * @QID_RX: RX queue - * @QID_OTHER: None of the above (don't use, only present for completeness) - * @QID_BEACON: Beacon queue (value unspecified, don't send it to device) - * @QID_ATIM: Atim queue (value unspeficied, don't send it to device) - */ -enum data_queue_qid { - QID_AC_BE = 0, - QID_AC_BK = 1, - QID_AC_VI = 2, - QID_AC_VO = 3, - QID_HCCA = 4, - QID_MGMT = 13, - QID_RX = 14, - QID_OTHER = 15, - QID_BEACON, - QID_ATIM, -}; - -/** - * enum skb_frame_desc_flags: Flags for &struct skb_frame_desc - * - * @SKBDESC_DMA_MAPPED_RX: &skb_dma field has been mapped for RX - * @SKBDESC_DMA_MAPPED_TX: &skb_dma field has been mapped for TX - * @SKBDESC_IV_STRIPPED: Frame contained a IV/EIV provided by - * mac80211 but was stripped for processing by the driver. - * @SKBDESC_L2_PADDED: Payload has been padded for 4-byte alignment, - * the padded bytes are located between header and payload. - */ -enum skb_frame_desc_flags { - SKBDESC_DMA_MAPPED_RX = 1 << 0, - SKBDESC_DMA_MAPPED_TX = 1 << 1, - SKBDESC_IV_STRIPPED = 1 << 2, - SKBDESC_L2_PADDED = 1 << 3 -}; - -/** - * struct skb_frame_desc: Descriptor information for the skb buffer - * - * This structure is placed over the driver_data array, this means that - * this structure should not exceed the size of that array (40 bytes). - * - * @flags: Frame flags, see &enum skb_frame_desc_flags. - * @desc_len: Length of the frame descriptor. - * @tx_rate_idx: the index of the TX rate, used for TX status reporting - * @tx_rate_flags: the TX rate flags, used for TX status reporting - * @desc: Pointer to descriptor part of the frame. - * Note that this pointer could point to something outside - * of the scope of the skb->data pointer. - * @iv: IV/EIV data used during encryption/decryption. - * @skb_dma: (PCI-only) the DMA address associated with the sk buffer. - * @entry: The entry to which this sk buffer belongs. - */ -struct skb_frame_desc { - u8 flags; - - u8 desc_len; - u8 tx_rate_idx; - u8 tx_rate_flags; - - void *desc; - - __le32 iv[2]; - - dma_addr_t skb_dma; - - struct queue_entry *entry; -}; - -/** - * get_skb_frame_desc - Obtain the rt2x00 frame descriptor from a sk_buff. - * @skb: &struct sk_buff from where we obtain the &struct skb_frame_desc - */ -static inline struct skb_frame_desc* get_skb_frame_desc(struct sk_buff *skb) -{ - BUILD_BUG_ON(sizeof(struct skb_frame_desc) > - IEEE80211_TX_INFO_DRIVER_DATA_SIZE); - return (struct skb_frame_desc *)&IEEE80211_SKB_CB(skb)->driver_data; -} - -/** - * enum rxdone_entry_desc_flags: Flags for &struct rxdone_entry_desc - * - * @RXDONE_SIGNAL_PLCP: Signal field contains the plcp value. - * @RXDONE_SIGNAL_BITRATE: Signal field contains the bitrate value. - * @RXDONE_SIGNAL_MCS: Signal field contains the mcs value. - * @RXDONE_MY_BSS: Does this frame originate from device's BSS. - * @RXDONE_CRYPTO_IV: Driver provided IV/EIV data. - * @RXDONE_CRYPTO_ICV: Driver provided ICV data. - * @RXDONE_L2PAD: 802.11 payload has been padded to 4-byte boundary. - */ -enum rxdone_entry_desc_flags { - RXDONE_SIGNAL_PLCP = BIT(0), - RXDONE_SIGNAL_BITRATE = BIT(1), - RXDONE_SIGNAL_MCS = BIT(2), - RXDONE_MY_BSS = BIT(3), - RXDONE_CRYPTO_IV = BIT(4), - RXDONE_CRYPTO_ICV = BIT(5), - RXDONE_L2PAD = BIT(6), -}; - -/** - * RXDONE_SIGNAL_MASK - Define to mask off all &rxdone_entry_desc_flags flags - * except for the RXDONE_SIGNAL_* flags. This is useful to convert the dev_flags - * from &rxdone_entry_desc to a signal value type. - */ -#define RXDONE_SIGNAL_MASK \ - ( RXDONE_SIGNAL_PLCP | RXDONE_SIGNAL_BITRATE | RXDONE_SIGNAL_MCS ) - -/** - * struct rxdone_entry_desc: RX Entry descriptor - * - * Summary of information that has been read from the RX frame descriptor. - * - * @timestamp: RX Timestamp - * @signal: Signal of the received frame. - * @rssi: RSSI of the received frame. - * @noise: Measured noise during frame reception. - * @size: Data size of the received frame. - * @flags: MAC80211 receive flags (See &enum mac80211_rx_flags). - * @dev_flags: Ralink receive flags (See &enum rxdone_entry_desc_flags). - * @rate_mode: Rate mode (See @enum rate_modulation). - * @cipher: Cipher type used during decryption. - * @cipher_status: Decryption status. - * @iv: IV/EIV data used during decryption. - * @icv: ICV data used during decryption. - */ -struct rxdone_entry_desc { - u64 timestamp; - int signal; - int rssi; - int noise; - int size; - int flags; - int dev_flags; - u16 rate_mode; - u8 cipher; - u8 cipher_status; - - __le32 iv[2]; - __le32 icv; -}; - -/** - * enum txdone_entry_desc_flags: Flags for &struct txdone_entry_desc - * - * @TXDONE_UNKNOWN: Hardware could not determine success of transmission. - * @TXDONE_SUCCESS: Frame was successfully send - * @TXDONE_FALLBACK: Frame was successfully send using a fallback rate. - * @TXDONE_FAILURE: Frame was not successfully send - * @TXDONE_EXCESSIVE_RETRY: In addition to &TXDONE_FAILURE, the - * frame transmission failed due to excessive retries. - */ -enum txdone_entry_desc_flags { - TXDONE_UNKNOWN, - TXDONE_SUCCESS, - TXDONE_FALLBACK, - TXDONE_FAILURE, - TXDONE_EXCESSIVE_RETRY, -}; - -/** - * struct txdone_entry_desc: TX done entry descriptor - * - * Summary of information that has been read from the TX frame descriptor - * after the device is done with transmission. - * - * @flags: TX done flags (See &enum txdone_entry_desc_flags). - * @retry: Retry count. - */ -struct txdone_entry_desc { - unsigned long flags; - int retry; -}; - -/** - * enum txentry_desc_flags: Status flags for TX entry descriptor - * - * @ENTRY_TXD_RTS_FRAME: This frame is a RTS frame. - * @ENTRY_TXD_CTS_FRAME: This frame is a CTS-to-self frame. - * @ENTRY_TXD_GENERATE_SEQ: This frame requires sequence counter. - * @ENTRY_TXD_FIRST_FRAGMENT: This is the first frame. - * @ENTRY_TXD_MORE_FRAG: This frame is followed by another fragment. - * @ENTRY_TXD_REQ_TIMESTAMP: Require timestamp to be inserted. - * @ENTRY_TXD_BURST: This frame belongs to the same burst event. - * @ENTRY_TXD_ACK: An ACK is required for this frame. - * @ENTRY_TXD_RETRY_MODE: When set, the long retry count is used. - * @ENTRY_TXD_ENCRYPT: This frame should be encrypted. - * @ENTRY_TXD_ENCRYPT_PAIRWISE: Use pairwise key table (instead of shared). - * @ENTRY_TXD_ENCRYPT_IV: Generate IV/EIV in hardware. - * @ENTRY_TXD_ENCRYPT_MMIC: Generate MIC in hardware. - * @ENTRY_TXD_HT_AMPDU: This frame is part of an AMPDU. - * @ENTRY_TXD_HT_BW_40: Use 40MHz Bandwidth. - * @ENTRY_TXD_HT_SHORT_GI: Use short GI. - */ -enum txentry_desc_flags { - ENTRY_TXD_RTS_FRAME, - ENTRY_TXD_CTS_FRAME, - ENTRY_TXD_GENERATE_SEQ, - ENTRY_TXD_FIRST_FRAGMENT, - ENTRY_TXD_MORE_FRAG, - ENTRY_TXD_REQ_TIMESTAMP, - ENTRY_TXD_BURST, - ENTRY_TXD_ACK, - ENTRY_TXD_RETRY_MODE, - ENTRY_TXD_ENCRYPT, - ENTRY_TXD_ENCRYPT_PAIRWISE, - ENTRY_TXD_ENCRYPT_IV, - ENTRY_TXD_ENCRYPT_MMIC, - ENTRY_TXD_HT_AMPDU, - ENTRY_TXD_HT_BW_40, - ENTRY_TXD_HT_SHORT_GI, -}; - -/** - * struct txentry_desc: TX Entry descriptor - * - * Summary of information for the frame descriptor before sending a TX frame. - * - * @flags: Descriptor flags (See &enum queue_entry_flags). - * @queue: Queue identification (See &enum data_queue_qid). - * @header_length: Length of 802.11 header. - * @l2pad: Amount of padding to align 802.11 payload to 4-byte boundrary. - * @length_high: PLCP length high word. - * @length_low: PLCP length low word. - * @signal: PLCP signal. - * @service: PLCP service. - * @msc: MCS. - * @stbc: STBC. - * @ba_size: BA size. - * @rate_mode: Rate mode (See @enum rate_modulation). - * @mpdu_density: MDPU density. - * @retry_limit: Max number of retries. - * @aifs: AIFS value. - * @ifs: IFS value. - * @cw_min: cwmin value. - * @cw_max: cwmax value. - * @cipher: Cipher type used for encryption. - * @key_idx: Key index used for encryption. - * @iv_offset: Position where IV should be inserted by hardware. - * @iv_len: Length of IV data. - */ -struct txentry_desc { - unsigned long flags; - - enum data_queue_qid queue; - - u16 header_length; - u16 l2pad; - - u16 length_high; - u16 length_low; - u16 signal; - u16 service; - - u16 mcs; - u16 stbc; - u16 ba_size; - u16 rate_mode; - u16 mpdu_density; - - short retry_limit; - short aifs; - short ifs; - short cw_min; - short cw_max; - - enum cipher cipher; - u16 key_idx; - u16 iv_offset; - u16 iv_len; -}; - -/** - * enum queue_entry_flags: Status flags for queue entry - * - * @ENTRY_BCN_ASSIGNED: This entry has been assigned to an interface. - * As long as this bit is set, this entry may only be touched - * through the interface structure. - * @ENTRY_OWNER_DEVICE_DATA: This entry is owned by the device for data - * transfer (either TX or RX depending on the queue). The entry should - * only be touched after the device has signaled it is done with it. - * @ENTRY_OWNER_DEVICE_CRYPTO: This entry is owned by the device for data - * encryption or decryption. The entry should only be touched after - * the device has signaled it is done with it. - * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting - * for the signal to start sending. - */ -enum queue_entry_flags { - ENTRY_BCN_ASSIGNED, - ENTRY_OWNER_DEVICE_DATA, - ENTRY_OWNER_DEVICE_CRYPTO, - ENTRY_DATA_PENDING, -}; - -/** - * struct queue_entry: Entry inside the &struct data_queue - * - * @flags: Entry flags, see &enum queue_entry_flags. - * @queue: The data queue (&struct data_queue) to which this entry belongs. - * @skb: The buffer which is currently being transmitted (for TX queue), - * or used to directly recieve data in (for RX queue). - * @entry_idx: The entry index number. - * @priv_data: Private data belonging to this queue entry. The pointer - * points to data specific to a particular driver and queue type. - */ -struct queue_entry { - unsigned long flags; - - struct data_queue *queue; - - struct sk_buff *skb; - - unsigned int entry_idx; - - void *priv_data; -}; - -/** - * enum queue_index: Queue index type - * - * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is - * owned by the hardware then the queue is considered to be full. - * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by - * the hardware and for which we need to run the txdone handler. If this - * entry is not owned by the hardware the queue is considered to be empty. - * @Q_INDEX_CRYPTO: Index pointer to the next entry which encryption/decription - * will be completed by the hardware next. - * @Q_INDEX_MAX: Keep last, used in &struct data_queue to determine the size - * of the index array. - */ -enum queue_index { - Q_INDEX, - Q_INDEX_DONE, - Q_INDEX_CRYPTO, - Q_INDEX_MAX, -}; - -/** - * struct data_queue: Data queue - * - * @rt2x00dev: Pointer to main &struct rt2x00dev where this queue belongs to. - * @entries: Base address of the &struct queue_entry which are - * part of this queue. - * @qid: The queue identification, see &enum data_queue_qid. - * @lock: Spinlock to protect index handling. Whenever @index, @index_done or - * @index_crypt needs to be changed this lock should be grabbed to prevent - * index corruption due to concurrency. - * @count: Number of frames handled in the queue. - * @limit: Maximum number of entries in the queue. - * @threshold: Minimum number of free entries before queue is kicked by force. - * @length: Number of frames in queue. - * @index: Index pointers to entry positions in the queue, - * use &enum queue_index to get a specific index field. - * @txop: maximum burst time. - * @aifs: The aifs value for outgoing frames (field ignored in RX queue). - * @cw_min: The cw min value for outgoing frames (field ignored in RX queue). - * @cw_max: The cw max value for outgoing frames (field ignored in RX queue). - * @data_size: Maximum data size for the frames in this queue. - * @desc_size: Hardware descriptor size for the data in this queue. - * @usb_endpoint: Device endpoint used for communication (USB only) - * @usb_maxpacket: Max packet size for given endpoint (USB only) - */ -struct data_queue { - struct rt2x00_dev *rt2x00dev; - struct queue_entry *entries; - - enum data_queue_qid qid; - - spinlock_t lock; - unsigned int count; - unsigned short limit; - unsigned short threshold; - unsigned short length; - unsigned short index[Q_INDEX_MAX]; - - unsigned short txop; - unsigned short aifs; - unsigned short cw_min; - unsigned short cw_max; - - unsigned short data_size; - unsigned short desc_size; - - unsigned short usb_endpoint; - unsigned short usb_maxpacket; -}; - -/** - * struct data_queue_desc: Data queue description - * - * The information in this structure is used by drivers - * to inform rt2x00lib about the creation of the data queue. - * - * @entry_num: Maximum number of entries for a queue. - * @data_size: Maximum data size for the frames in this queue. - * @desc_size: Hardware descriptor size for the data in this queue. - * @priv_size: Size of per-queue_entry private data. - */ -struct data_queue_desc { - unsigned short entry_num; - unsigned short data_size; - unsigned short desc_size; - unsigned short priv_size; -}; - -/** - * queue_end - Return pointer to the last queue (HELPER MACRO). - * @__dev: Pointer to &struct rt2x00_dev - * - * Using the base rx pointer and the maximum number of available queues, - * this macro will return the address of 1 position beyond the end of the - * queues array. - */ -#define queue_end(__dev) \ - &(__dev)->rx[(__dev)->data_queues] - -/** - * tx_queue_end - Return pointer to the last TX queue (HELPER MACRO). - * @__dev: Pointer to &struct rt2x00_dev - * - * Using the base tx pointer and the maximum number of available TX - * queues, this macro will return the address of 1 position beyond - * the end of the TX queue array. - */ -#define tx_queue_end(__dev) \ - &(__dev)->tx[(__dev)->ops->tx_queues] - -/** - * queue_next - Return pointer to next queue in list (HELPER MACRO). - * @__queue: Current queue for which we need the next queue - * - * Using the current queue address we take the address directly - * after the queue to take the next queue. Note that this macro - * should be used carefully since it does not protect against - * moving past the end of the list. (See macros &queue_end and - * &tx_queue_end for determining the end of the queue). - */ -#define queue_next(__queue) \ - &(__queue)[1] - -/** - * queue_loop - Loop through the queues within a specific range (HELPER MACRO). - * @__entry: Pointer where the current queue entry will be stored in. - * @__start: Start queue pointer. - * @__end: End queue pointer. - * - * This macro will loop through all queues between &__start and &__end. - */ -#define queue_loop(__entry, __start, __end) \ - for ((__entry) = (__start); \ - prefetch(queue_next(__entry)), (__entry) != (__end);\ - (__entry) = queue_next(__entry)) - -/** - * queue_for_each - Loop through all queues - * @__dev: Pointer to &struct rt2x00_dev - * @__entry: Pointer where the current queue entry will be stored in. - * - * This macro will loop through all available queues. - */ -#define queue_for_each(__dev, __entry) \ - queue_loop(__entry, (__dev)->rx, queue_end(__dev)) - -/** - * tx_queue_for_each - Loop through the TX queues - * @__dev: Pointer to &struct rt2x00_dev - * @__entry: Pointer where the current queue entry will be stored in. - * - * This macro will loop through all TX related queues excluding - * the Beacon and Atim queues. - */ -#define tx_queue_for_each(__dev, __entry) \ - queue_loop(__entry, (__dev)->tx, tx_queue_end(__dev)) - -/** - * txall_queue_for_each - Loop through all TX related queues - * @__dev: Pointer to &struct rt2x00_dev - * @__entry: Pointer where the current queue entry will be stored in. - * - * This macro will loop through all TX related queues including - * the Beacon and Atim queues. - */ -#define txall_queue_for_each(__dev, __entry) \ - queue_loop(__entry, (__dev)->tx, queue_end(__dev)) - -/** - * rt2x00queue_empty - Check if the queue is empty. - * @queue: Queue to check if empty. - */ -static inline int rt2x00queue_empty(struct data_queue *queue) -{ - return queue->length == 0; -} - -/** - * rt2x00queue_full - Check if the queue is full. - * @queue: Queue to check if full. - */ -static inline int rt2x00queue_full(struct data_queue *queue) -{ - return queue->length == queue->limit; -} - -/** - * rt2x00queue_free - Check the number of available entries in queue. - * @queue: Queue to check. - */ -static inline int rt2x00queue_available(struct data_queue *queue) -{ - return queue->limit - queue->length; -} - -/** - * rt2x00queue_threshold - Check if the queue is below threshold - * @queue: Queue to check. - */ -static inline int rt2x00queue_threshold(struct data_queue *queue) -{ - return rt2x00queue_available(queue) < queue->threshold; -} - -/** - * _rt2x00_desc_read - Read a word from the hardware descriptor. - * @desc: Base descriptor address - * @word: Word index from where the descriptor should be read. - * @value: Address where the descriptor value should be written into. - */ -static inline void _rt2x00_desc_read(__le32 *desc, const u8 word, __le32 *value) -{ - *value = desc[word]; -} - -/** - * rt2x00_desc_read - Read a word from the hardware descriptor, this - * function will take care of the byte ordering. - * @desc: Base descriptor address - * @word: Word index from where the descriptor should be read. - * @value: Address where the descriptor value should be written into. - */ -static inline void rt2x00_desc_read(__le32 *desc, const u8 word, u32 *value) -{ - __le32 tmp; - _rt2x00_desc_read(desc, word, &tmp); - *value = le32_to_cpu(tmp); -} - -/** - * rt2x00_desc_write - write a word to the hardware descriptor, this - * function will take care of the byte ordering. - * @desc: Base descriptor address - * @word: Word index from where the descriptor should be written. - * @value: Value that should be written into the descriptor. - */ -static inline void _rt2x00_desc_write(__le32 *desc, const u8 word, __le32 value) -{ - desc[word] = value; -} - -/** - * rt2x00_desc_write - write a word to the hardware descriptor. - * @desc: Base descriptor address - * @word: Word index from where the descriptor should be written. - * @value: Value that should be written into the descriptor. - */ -static inline void rt2x00_desc_write(__le32 *desc, const u8 word, u32 value) -{ - _rt2x00_desc_write(desc, word, cpu_to_le32(value)); -} - -#endif /* RT2X00QUEUE_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00reg.h b/drivers/net/wireless/rt2x00/rt2x00reg.h deleted file mode 100644 index 983e52e127a7..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00reg.h +++ /dev/null @@ -1,272 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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 - -/* - * RX crypto status - */ -enum rx_crypto { - RX_CRYPTO_SUCCESS = 0, - RX_CRYPTO_FAIL_ICV = 1, - RX_CRYPTO_FAIL_MIC = 2, - RX_CRYPTO_FAIL_KEY = 3, -}; - -/* - * 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_RX_ON_LINK, - STATE_RADIO_RX_OFF_LINK, - 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, /* Don't send to device */ - -/* - * Max cipher type. - * Note that CIPHER_NONE isn't counted, and CKIP64 and CKIP128 - * are excluded due to limitations in mac80211. - */ - CIPHER_MAX = 4, -}; - -/* - * Rate modulations - */ -enum rate_modulation { - RATE_MODE_CCK = 0, - RATE_MODE_OFDM = 1, - RATE_MODE_HT_MIX = 2, - RATE_MODE_HT_GREENFIELD = 3, -}; - -/* - * Firmware validation error codes - */ -enum firmware_errors { - FW_OK, - FW_BAD_CRC, - FW_BAD_LENGTH, - FW_BAD_VERSION, -}; - -/* - * 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. - * Note that we cannot use the is_power_of_2() function since this - * check must be done at compile-time. - */ -#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(1LU + (x) + low_bit_mask(x)) - -/* - * Macros to find first set bit in a variable. - * These macros behave the same as the __ffs() functions but - * the most important difference that this is done during - * compile-time rather then run-time. - */ -#define compile_ffs2(__x) \ - __builtin_choose_expr(((__x) & 0x1), 0, 1) - -#define compile_ffs4(__x) \ - __builtin_choose_expr(((__x) & 0x3), \ - (compile_ffs2((__x))), \ - (compile_ffs2((__x) >> 2) + 2)) - -#define compile_ffs8(__x) \ - __builtin_choose_expr(((__x) & 0xf), \ - (compile_ffs4((__x))), \ - (compile_ffs4((__x) >> 4) + 4)) - -#define compile_ffs16(__x) \ - __builtin_choose_expr(((__x) & 0xff), \ - (compile_ffs8((__x))), \ - (compile_ffs8((__x) >> 8) + 8)) - -#define compile_ffs32(__x) \ - __builtin_choose_expr(((__x) & 0xffff), \ - (compile_ffs16((__x))), \ - (compile_ffs16((__x) >> 16) + 16)) - -/* - * This macro will check the requirements for the FIELD{8,16,32} macros - * The mask should be a constant non-zero contiguous set of bits which - * does not exceed the given typelimit. - */ -#define FIELD_CHECK(__mask, __type) \ - BUILD_BUG_ON(!(__mask) || \ - !is_valid_mask(__mask) || \ - (__mask) != (__type)(__mask)) \ - -#define FIELD8(__mask) \ -({ \ - FIELD_CHECK(__mask, u8); \ - (struct rt2x00_field8) { \ - compile_ffs8(__mask), (__mask) \ - }; \ -}) - -#define FIELD16(__mask) \ -({ \ - FIELD_CHECK(__mask, u16); \ - (struct rt2x00_field16) { \ - compile_ffs16(__mask), (__mask) \ - }; \ -}) - -#define FIELD32(__mask) \ -({ \ - FIELD_CHECK(__mask, u32); \ - (struct rt2x00_field32) { \ - compile_ffs32(__mask), (__mask) \ - }; \ -}) - -#define SET_FIELD(__reg, __type, __field, __value)\ -({ \ - typecheck(__type, __field); \ - *(__reg) &= ~((__field).bit_mask); \ - *(__reg) |= ((__value) << \ - ((__field).bit_offset)) & \ - ((__field).bit_mask); \ -}) - -#define GET_FIELD(__reg, __type, __field) \ -({ \ - typecheck(__type, __field); \ - ((__reg) & ((__field).bit_mask)) >> \ - ((__field).bit_offset); \ -}) - -#define rt2x00_set_field32(__reg, __field, __value) \ - SET_FIELD(__reg, struct rt2x00_field32, __field, __value) -#define rt2x00_get_field32(__reg, __field) \ - GET_FIELD(__reg, struct rt2x00_field32, __field) - -#define rt2x00_set_field16(__reg, __field, __value) \ - SET_FIELD(__reg, struct rt2x00_field16, __field, __value) -#define rt2x00_get_field16(__reg, __field) \ - GET_FIELD(__reg, struct rt2x00_field16, __field) - -#define rt2x00_set_field8(__reg, __field, __value) \ - SET_FIELD(__reg, struct rt2x00_field8, __field, __value) -#define rt2x00_get_field8(__reg, __field) \ - GET_FIELD(__reg, struct rt2x00_field8, __field) - -#endif /* RT2X00REG_H */ diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c deleted file mode 100644 index f02b48a90593..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ /dev/null @@ -1,739 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00usb - Abstract: rt2x00 generic usb device routines. - */ - -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00usb.h" - -/* - * Interfacing with the HW. - */ -int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, const u16 value, - void *buffer, const u16 buffer_length, - const int timeout) -{ - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); - int status; - unsigned int i; - unsigned int pipe = - (requesttype == USB_VENDOR_REQUEST_IN) ? - usb_rcvctrlpipe(usb_dev, 0) : usb_sndctrlpipe(usb_dev, 0); - - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return -ENODEV; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - status = usb_control_msg(usb_dev, pipe, request, requesttype, - value, offset, buffer, buffer_length, - timeout); - if (status >= 0) - return 0; - - /* - * Check for errors - * -ENODEV: Device has disappeared, no point continuing. - * All other errors: Try again. - */ - else if (status == -ENODEV) { - clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); - break; - } - } - - ERROR(rt2x00dev, - "Vendor Request 0x%02x failed for offset 0x%04x with error %d.\n", - request, offset, status); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request); - -int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, void *buffer, - const u16 buffer_length, const int timeout) -{ - int status; - - BUG_ON(!mutex_is_locked(&rt2x00dev->csr_mutex)); - - /* - * Check for Cache availability. - */ - if (unlikely(!rt2x00dev->csr.cache || buffer_length > CSR_CACHE_SIZE)) { - ERROR(rt2x00dev, "CSR cache not available.\n"); - return -ENOMEM; - } - - 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_vendor_req_buff_lock); - -int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, void *buffer, - const u16 buffer_length, const int timeout) -{ - int status; - - mutex_lock(&rt2x00dev->csr_mutex); - - status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, - requesttype, offset, buffer, - buffer_length, timeout); - - mutex_unlock(&rt2x00dev->csr_mutex); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_buff); - -int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, const void *buffer, - const u16 buffer_length, - const int timeout) -{ - int status = 0; - unsigned char *tb; - u16 off, len, bsize; - - mutex_lock(&rt2x00dev->csr_mutex); - - tb = (char *)buffer; - off = offset; - len = buffer_length; - while (len && !status) { - bsize = min_t(u16, CSR_CACHE_SIZE, len); - status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, - requesttype, off, tb, - bsize, timeout); - - tb += bsize; - len -= bsize; - off += bsize; - } - - mutex_unlock(&rt2x00dev->csr_mutex); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00usb_vendor_request_large_buff); - -int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - struct rt2x00_field32 field, - u32 *reg) -{ - unsigned int i; - - if (!test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags)) - return -ENODEV; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read_lock(rt2x00dev, offset, reg); - if (!rt2x00_get_field32(*reg, field)) - return 1; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "Indirect register access failed: " - "offset=0x%.08x, value=0x%.08x\n", offset, *reg); - *reg = ~0; - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00usb_regbusy_read); - -/* - * TX data handlers. - */ -static void rt2x00usb_interrupt_txdone(struct urb *urb) -{ - struct queue_entry *entry = (struct queue_entry *)urb->context; - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct txdone_entry_desc txdesc; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; - - /* - * Obtain the status about this packet. - * Note that when the status is 0 it does not mean the - * frame was send out correctly. It only means the frame - * was succesfully pushed to the hardware, we have no - * way to determine the transmission status right now. - * (Only indirectly by looking at the failed TX counters - * in the register). - */ - txdesc.flags = 0; - if (!urb->status) - __set_bit(TXDONE_UNKNOWN, &txdesc.flags); - else - __set_bit(TXDONE_FAILURE, &txdesc.flags); - txdesc.retry = 0; - - rt2x00lib_txdone(entry, &txdesc); -} - -int rt2x00usb_write_tx_data(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev); - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc; - u32 length; - - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memset(entry->skb->data, 0, entry->queue->desc_size); - - /* - * Fill in skb descriptor - */ - skbdesc = get_skb_frame_desc(entry->skb); - skbdesc->desc = entry->skb->data; - skbdesc->desc_len = entry->queue->desc_size; - - /* - * USB devices cannot blindly pass the skb->len as the - * length of the data to usb_fill_bulk_urb. Pass the skb - * to the driver to determine what the length should be. - */ - length = rt2x00dev->ops->lib->get_tx_data_len(entry); - - usb_fill_bulk_urb(entry_priv->urb, usb_dev, - usb_sndbulkpipe(usb_dev, entry->queue->usb_endpoint), - entry->skb->data, length, - rt2x00usb_interrupt_txdone, entry); - - /* - * Make sure the skb->data pointer points to the frame, not the - * descriptor. - */ - skb_pull(entry->skb, entry->queue->desc_size); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00usb_write_tx_data); - -static inline void rt2x00usb_kick_tx_entry(struct queue_entry *entry) -{ - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - - if (test_and_clear_bit(ENTRY_DATA_PENDING, &entry->flags)) - usb_submit_urb(entry_priv->urb, GFP_ATOMIC); -} - -void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) -{ - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); - unsigned long irqflags; - unsigned int index; - unsigned int index_done; - unsigned int i; - - /* - * Only protect the range we are going to loop over, - * if during our loop a extra entry is set to pending - * it should not be kicked during this run, since it - * is part of another TX operation. - */ - spin_lock_irqsave(&queue->lock, irqflags); - index = queue->index[Q_INDEX]; - index_done = queue->index[Q_INDEX_DONE]; - spin_unlock_irqrestore(&queue->lock, irqflags); - - /* - * Start from the TX done pointer, this guarentees that we will - * send out all frames in the correct order. - */ - if (index_done < index) { - for (i = index_done; i < index; i++) - rt2x00usb_kick_tx_entry(&queue->entries[i]); - } else { - for (i = index_done; i < queue->limit; i++) - rt2x00usb_kick_tx_entry(&queue->entries[i]); - - for (i = 0; i < index; i++) - rt2x00usb_kick_tx_entry(&queue->entries[i]); - } -} -EXPORT_SYMBOL_GPL(rt2x00usb_kick_tx_queue); - -void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) -{ - struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, qid); - struct queue_entry_priv_usb *entry_priv; - struct queue_entry_priv_usb_bcn *bcn_priv; - unsigned int i; - bool kill_guard; - - /* - * When killing the beacon queue, we must also kill - * the beacon guard byte. - */ - kill_guard = - (qid == QID_BEACON) && - (test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)); - - /* - * Cancel all entries. - */ - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - usb_kill_urb(entry_priv->urb); - - /* - * Kill guardian urb (if required by driver). - */ - if (kill_guard) { - bcn_priv = queue->entries[i].priv_data; - usb_kill_urb(bcn_priv->guardian_urb); - } - } -} -EXPORT_SYMBOL_GPL(rt2x00usb_kill_tx_queue); - -/* - * RX data handlers. - */ -static void rt2x00usb_interrupt_rxdone(struct urb *urb) -{ - struct queue_entry *entry = (struct queue_entry *)urb->context; - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u8 rxd[32]; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags) || - !test_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags)) - return; - - /* - * Check if the received data is simply too small - * to be actually valid, or if the urb is signaling - * a problem. - */ - if (urb->actual_length < entry->queue->desc_size || urb->status) { - set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - usb_submit_urb(urb, GFP_ATOMIC); - return; - } - - /* - * Fill in desc fields of the skb descriptor - */ - skbdesc->desc = rxd; - skbdesc->desc_len = entry->queue->desc_size; - - /* - * Send the frame to rt2x00lib for further processing. - */ - rt2x00lib_rxdone(rt2x00dev, entry); -} - -/* - * Radio handlers - */ -void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - rt2x00usb_vendor_request_sw(rt2x00dev, USB_RX_CONTROL, 0, 0, - REGISTER_TIMEOUT); - - /* - * The USB version of kill_tx_queue also works - * on the RX queue. - */ - rt2x00dev->ops->lib->kill_tx_queue(rt2x00dev, QID_RX); -} -EXPORT_SYMBOL_GPL(rt2x00usb_disable_radio); - -/* - * Device initialization handlers. - */ -void rt2x00usb_clear_entry(struct queue_entry *entry) -{ - struct usb_device *usb_dev = - to_usb_device_intf(entry->queue->rt2x00dev->dev); - struct queue_entry_priv_usb *entry_priv = entry->priv_data; - int pipe; - - if (entry->queue->qid == QID_RX) { - pipe = usb_rcvbulkpipe(usb_dev, entry->queue->usb_endpoint); - usb_fill_bulk_urb(entry_priv->urb, usb_dev, pipe, - entry->skb->data, entry->skb->len, - rt2x00usb_interrupt_rxdone, entry); - - set_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); - usb_submit_urb(entry_priv->urb, GFP_ATOMIC); - } else { - entry->flags = 0; - } -} -EXPORT_SYMBOL_GPL(rt2x00usb_clear_entry); - -static void rt2x00usb_assign_endpoint(struct data_queue *queue, - struct usb_endpoint_descriptor *ep_desc) -{ - struct usb_device *usb_dev = to_usb_device_intf(queue->rt2x00dev->dev); - int pipe; - - queue->usb_endpoint = usb_endpoint_num(ep_desc); - - if (queue->qid == QID_RX) { - pipe = usb_rcvbulkpipe(usb_dev, queue->usb_endpoint); - queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 0); - } else { - pipe = usb_sndbulkpipe(usb_dev, queue->usb_endpoint); - queue->usb_maxpacket = usb_maxpacket(usb_dev, pipe, 1); - } - - if (!queue->usb_maxpacket) - queue->usb_maxpacket = 1; -} - -static int rt2x00usb_find_endpoints(struct rt2x00_dev *rt2x00dev) -{ - struct usb_interface *intf = to_usb_interface(rt2x00dev->dev); - struct usb_host_interface *intf_desc = intf->cur_altsetting; - struct usb_endpoint_descriptor *ep_desc; - struct data_queue *queue = rt2x00dev->tx; - struct usb_endpoint_descriptor *tx_ep_desc = NULL; - unsigned int i; - - /* - * Walk through all available endpoints to search for "bulk in" - * and "bulk out" endpoints. When we find such endpoints collect - * the information we need from the descriptor and assign it - * to the queue. - */ - for (i = 0; i < intf_desc->desc.bNumEndpoints; i++) { - ep_desc = &intf_desc->endpoint[i].desc; - - if (usb_endpoint_is_bulk_in(ep_desc)) { - rt2x00usb_assign_endpoint(rt2x00dev->rx, ep_desc); - } else if (usb_endpoint_is_bulk_out(ep_desc) && - (queue != queue_end(rt2x00dev))) { - rt2x00usb_assign_endpoint(queue, ep_desc); - queue = queue_next(queue); - - tx_ep_desc = ep_desc; - } - } - - /* - * At least 1 endpoint for RX and 1 endpoint for TX must be available. - */ - if (!rt2x00dev->rx->usb_endpoint || !rt2x00dev->tx->usb_endpoint) { - ERROR(rt2x00dev, "Bulk-in/Bulk-out endpoints not found\n"); - return -EPIPE; - } - - /* - * It might be possible not all queues have a dedicated endpoint. - * Loop through all TX queues and copy the endpoint information - * which we have gathered from already assigned endpoints. - */ - txall_queue_for_each(rt2x00dev, queue) { - if (!queue->usb_endpoint) - rt2x00usb_assign_endpoint(queue, tx_ep_desc); - } - - return 0; -} - -static int rt2x00usb_alloc_urb(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - struct queue_entry_priv_usb *entry_priv; - struct queue_entry_priv_usb_bcn *bcn_priv; - unsigned int i; - - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - entry_priv->urb = usb_alloc_urb(0, GFP_KERNEL); - if (!entry_priv->urb) - return -ENOMEM; - } - - /* - * If this is not the beacon queue or - * no guardian byte was required for the beacon, - * then we are done. - */ - if (rt2x00dev->bcn != queue || - !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) - return 0; - - for (i = 0; i < queue->limit; i++) { - bcn_priv = queue->entries[i].priv_data; - bcn_priv->guardian_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!bcn_priv->guardian_urb) - return -ENOMEM; - } - - return 0; -} - -static void rt2x00usb_free_urb(struct rt2x00_dev *rt2x00dev, - struct data_queue *queue) -{ - struct queue_entry_priv_usb *entry_priv; - struct queue_entry_priv_usb_bcn *bcn_priv; - unsigned int i; - - if (!queue->entries) - return; - - for (i = 0; i < queue->limit; i++) { - entry_priv = queue->entries[i].priv_data; - usb_kill_urb(entry_priv->urb); - usb_free_urb(entry_priv->urb); - } - - /* - * If this is not the beacon queue or - * no guardian byte was required for the beacon, - * then we are done. - */ - if (rt2x00dev->bcn != queue || - !test_bit(DRIVER_REQUIRE_BEACON_GUARD, &rt2x00dev->flags)) - return; - - for (i = 0; i < queue->limit; i++) { - bcn_priv = queue->entries[i].priv_data; - usb_kill_urb(bcn_priv->guardian_urb); - usb_free_urb(bcn_priv->guardian_urb); - } -} - -int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - int status; - - /* - * Find endpoints for each queue - */ - status = rt2x00usb_find_endpoints(rt2x00dev); - if (status) - goto exit; - - /* - * Allocate DMA - */ - queue_for_each(rt2x00dev, queue) { - status = rt2x00usb_alloc_urb(rt2x00dev, queue); - if (status) - goto exit; - } - - return 0; - -exit: - rt2x00usb_uninitialize(rt2x00dev); - - return status; -} -EXPORT_SYMBOL_GPL(rt2x00usb_initialize); - -void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - - queue_for_each(rt2x00dev, queue) - rt2x00usb_free_urb(rt2x00dev, queue); -} -EXPORT_SYMBOL_GPL(rt2x00usb_uninitialize); - -/* - * 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, - const struct usb_device_id *id) -{ - struct usb_device *usb_dev = interface_to_usbdev(usb_intf); - struct rt2x00_ops *ops = (struct rt2x00_ops *)id->driver_info; - struct ieee80211_hw *hw; - struct rt2x00_dev *rt2x00dev; - int retval; - - usb_dev = usb_get_dev(usb_dev); - - hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw); - if (!hw) { - ERROR_PROBE("Failed to allocate hardware.\n"); - retval = -ENOMEM; - goto exit_put_device; - } - - usb_set_intfdata(usb_intf, hw); - - rt2x00dev = hw->priv; - rt2x00dev->dev = &usb_intf->dev; - rt2x00dev->ops = ops; - rt2x00dev->hw = hw; - - retval = rt2x00usb_alloc_reg(rt2x00dev); - if (retval) - goto exit_free_device; - - retval = rt2x00lib_probe_dev(rt2x00dev); - if (retval) - goto exit_free_reg; - - return 0; - -exit_free_reg: - rt2x00usb_free_reg(rt2x00dev); - -exit_free_device: - ieee80211_free_hw(hw); - -exit_put_device: - usb_put_dev(usb_dev); - - usb_set_intfdata(usb_intf, NULL); - - return retval; -} -EXPORT_SYMBOL_GPL(rt2x00usb_probe); - -void rt2x00usb_disconnect(struct usb_interface *usb_intf) -{ - struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); - struct rt2x00_dev *rt2x00dev = hw->priv; - - /* - * Free all allocated data. - */ - rt2x00lib_remove_dev(rt2x00dev); - rt2x00usb_free_reg(rt2x00dev); - ieee80211_free_hw(hw); - - /* - * Free the USB device data. - */ - usb_set_intfdata(usb_intf, NULL); - usb_put_dev(interface_to_usbdev(usb_intf)); -} -EXPORT_SYMBOL_GPL(rt2x00usb_disconnect); - -#ifdef CONFIG_PM -int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state) -{ - struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); - struct rt2x00_dev *rt2x00dev = hw->priv; - int retval; - - retval = rt2x00lib_suspend(rt2x00dev, state); - if (retval) - return retval; - - /* - * Decrease usbdev refcount. - */ - usb_put_dev(interface_to_usbdev(usb_intf)); - - return 0; -} -EXPORT_SYMBOL_GPL(rt2x00usb_suspend); - -int rt2x00usb_resume(struct usb_interface *usb_intf) -{ - struct ieee80211_hw *hw = usb_get_intfdata(usb_intf); - struct rt2x00_dev *rt2x00dev = hw->priv; - - usb_get_dev(interface_to_usbdev(usb_intf)); - - return rt2x00lib_resume(rt2x00dev); -} -EXPORT_SYMBOL_GPL(rt2x00usb_resume); -#endif /* CONFIG_PM */ - -/* - * rt2x00usb module information. - */ -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("rt2x00 usb library"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h deleted file mode 100644 index bd2d59c85f1b..000000000000 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ /dev/null @@ -1,454 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt2x00usb - Abstract: Data structures for the rt2x00usb module. - */ - -#ifndef RT2X00USB_H -#define RT2X00USB_H - -#define to_usb_device_intf(d) \ -({ \ - struct usb_interface *intf = to_usb_interface(d); \ - interface_to_usbdev(intf); \ -}) - -/* - * This variable should be used with the - * usb_driver structure initialization. - */ -#define USB_DEVICE_DATA(__ops) .driver_info = (kernel_ulong_t)(__ops) - -/* - * Register defines. - * Some registers require multiple attempts before success, - * in those cases REGISTER_BUSY_COUNT attempts should be - * taken with a REGISTER_BUSY_DELAY interval. - * For USB vendor requests we need to pass a timeout - * time in ms, for this we use the REGISTER_TIMEOUT, - * however when loading firmware a higher value is - * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE. - */ -#define REGISTER_BUSY_COUNT 5 -#define REGISTER_BUSY_DELAY 100 -#define REGISTER_TIMEOUT 500 -#define REGISTER_TIMEOUT_FIRMWARE 1000 - -/** - * REGISTER_TIMEOUT16 - Determine the timeout for 16bit register access - * @__datalen: Data length - */ -#define REGISTER_TIMEOUT16(__datalen) \ - ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u16)) ) - -/** - * REGISTER_TIMEOUT32 - Determine the timeout for 32bit register access - * @__datalen: Data length - */ -#define REGISTER_TIMEOUT32(__datalen) \ - ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u32)) ) - -/* - * Cache size - */ -#define CSR_CACHE_SIZE 64 - -/* - * USB request types. - */ -#define USB_VENDOR_REQUEST ( USB_TYPE_VENDOR | USB_RECIP_DEVICE ) -#define USB_VENDOR_REQUEST_IN ( USB_DIR_IN | USB_VENDOR_REQUEST ) -#define USB_VENDOR_REQUEST_OUT ( USB_DIR_OUT | USB_VENDOR_REQUEST ) - -/** - * enum rt2x00usb_vendor_request: USB vendor commands. - */ -enum rt2x00usb_vendor_request { - USB_DEVICE_MODE = 1, - USB_SINGLE_WRITE = 2, - USB_SINGLE_READ = 3, - USB_MULTI_WRITE = 6, - USB_MULTI_READ = 7, - USB_EEPROM_WRITE = 8, - USB_EEPROM_READ = 9, - USB_LED_CONTROL = 10, /* RT73USB */ - USB_RX_CONTROL = 12, -}; - -/** - * enum rt2x00usb_mode_offset: Device modes offset. - */ -enum rt2x00usb_mode_offset { - USB_MODE_RESET = 1, - USB_MODE_UNPLUG = 2, - USB_MODE_FUNCTION = 3, - USB_MODE_TEST = 4, - USB_MODE_SLEEP = 7, /* RT73USB */ - USB_MODE_FIRMWARE = 8, /* RT73USB */ - USB_MODE_WAKEUP = 9, /* RT73USB */ -}; - -/** - * rt2x00usb_vendor_request - Send register command to device - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @requesttype: Request type &USB_VENDOR_REQUEST_* - * @offset: Register offset to perform action on - * @value: Value to write to device - * @buffer: Buffer where information will be read/written to by device - * @buffer_length: Size of &buffer - * @timeout: Operation timeout - * - * This is the main function to communicate with the device, - * the &buffer argument _must_ either be NULL or point to - * a buffer allocated by kmalloc. Failure to do so can lead - * to unexpected behavior depending on the architecture. - */ -int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, const u16 value, - void *buffer, const u16 buffer_length, - const int timeout); - -/** - * rt2x00usb_vendor_request_buff - Send register command to device (buffered) - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @requesttype: Request type &USB_VENDOR_REQUEST_* - * @offset: Register offset to perform action on - * @buffer: Buffer where information will be read/written to by device - * @buffer_length: Size of &buffer - * @timeout: Operation timeout - * - * 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(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, void *buffer, - const u16 buffer_length, const int timeout); - -/** - * rt2x00usb_vendor_request_buff - Send register command to device (buffered) - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @requesttype: Request type &USB_VENDOR_REQUEST_* - * @offset: Register offset to perform action on - * @buffer: Buffer where information will be read/written to by device - * @buffer_length: Size of &buffer - * @timeout: Operation timeout - * - * A version of &rt2x00usb_vendor_request_buff which must be called - * if the usb_cache_mutex is already held. - */ -int rt2x00usb_vendor_req_buff_lock(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, void *buffer, - const u16 buffer_length, const int timeout); - -/** - * rt2x00usb_vendor_request_large_buff - Send register command to device (buffered) - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @requesttype: Request type &USB_VENDOR_REQUEST_* - * @offset: Register start offset to perform action on - * @buffer: Buffer where information will be read/written to by device - * @buffer_length: Size of &buffer - * @timeout: Operation timeout - * - * This function is used to transfer register data in blocks larger - * then CSR_CACHE_SIZE. Use for firmware upload, keys and beacons. - */ -int rt2x00usb_vendor_request_large_buff(struct rt2x00_dev *rt2x00dev, - const u8 request, const u8 requesttype, - const u16 offset, const void *buffer, - const u16 buffer_length, - const int timeout); - -/** - * rt2x00usb_vendor_request_sw - Send single register command to device - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @request: USB vendor command (See &enum rt2x00usb_vendor_request) - * @offset: Register offset to perform action on - * @value: Value to write to device - * @timeout: Operation 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(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); -} - -/** - * rt2x00usb_eeprom_read - Read eeprom from device - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @eeprom: Pointer to eeprom array to store the information in - * @length: Number of bytes to read from the eeprom - * - * 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(struct rt2x00_dev *rt2x00dev, - __le16 *eeprom, const u16 length) -{ - return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, - USB_VENDOR_REQUEST_IN, 0, 0, - eeprom, length, - REGISTER_TIMEOUT16(length)); -} - -/** - * rt2x00usb_regbusy_read - Read 32bit register word - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @value: Pointer to where register contents should be stored - * - * This function is a simple wrapper for 32bit register access - * through rt2x00usb_vendor_request_buff(). - */ -static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 *value) -{ - __le32 reg; - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); - *value = le32_to_cpu(reg); -} - -/** - * rt2x00usb_register_read_lock - Read 32bit register word - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @value: Pointer to where register contents should be stored - * - * This function is a simple wrapper for 32bit register access - * through rt2x00usb_vendor_req_buff_lock(). - */ -static inline void rt2x00usb_register_read_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 *value) -{ - __le32 reg; - rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); - *value = le32_to_cpu(reg); -} - -/** - * rt2x00usb_register_multiread - Read 32bit register words - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @value: Pointer to where register contents should be stored - * @length: Length of the data - * - * This function is a simple wrapper for 32bit register access - * through rt2x00usb_vendor_request_buff(). - */ -static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length) -{ - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, - USB_VENDOR_REQUEST_IN, offset, - value, length, - REGISTER_TIMEOUT32(length)); -} - -/** - * rt2x00usb_register_write - Write 32bit register word - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @value: Data which should be written - * - * This function is a simple wrapper for 32bit register access - * through rt2x00usb_vendor_request_buff(). - */ -static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 value) -{ - __le32 reg = cpu_to_le32(value); - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); -} - -/** - * rt2x00usb_register_write_lock - Write 32bit register word - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @value: Data which should be written - * - * This function is a simple wrapper for 32bit register access - * through rt2x00usb_vendor_req_buff_lock(). - */ -static inline void rt2x00usb_register_write_lock(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - u32 value) -{ - __le32 reg = cpu_to_le32(value); - rt2x00usb_vendor_req_buff_lock(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - ®, sizeof(reg), REGISTER_TIMEOUT); -} - -/** - * rt2x00usb_register_multiwrite - Write 32bit register words - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @value: Data which should be written - * @length: Length of the data - * - * This function is a simple wrapper for 32bit register access - * through rt2x00usb_vendor_request_buff(). - */ -static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - void *value, const u32 length) -{ - rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, offset, - value, length, - REGISTER_TIMEOUT32(length)); -} - -/** - * rt2x00usb_regbusy_read - Read from register with busy check - * @rt2x00dev: Device pointer, see &struct rt2x00_dev. - * @offset: Register offset - * @field: Field to check if register is busy - * @reg: Pointer to where register contents should be stored - * - * This function will read the given register, and checks if the - * register is busy. If it is, it will sleep for a couple of - * microseconds before reading the register again. If the register - * is not read after a certain timeout, this function will return - * FALSE. - */ -int rt2x00usb_regbusy_read(struct rt2x00_dev *rt2x00dev, - const unsigned int offset, - struct rt2x00_field32 field, - u32 *reg); - -/* - * Radio handlers - */ -void rt2x00usb_disable_radio(struct rt2x00_dev *rt2x00dev); - -/** - * rt2x00usb_write_tx_data - Initialize URB for TX operation - * @entry: The entry where the frame is located - * - * This function will initialize the URB and skb descriptor - * to prepare the entry for the actual TX operation. - */ -int rt2x00usb_write_tx_data(struct queue_entry *entry); - -/** - * struct queue_entry_priv_usb: Per entry USB specific information - * - * @urb: Urb structure used for device communication. - */ -struct queue_entry_priv_usb { - struct urb *urb; -}; - -/** - * struct queue_entry_priv_usb_bcn: Per TX entry USB specific information - * - * The first section should match &struct queue_entry_priv_usb exactly. - * rt2500usb can use this structure to send a guardian byte when working - * with beacons. - * - * @urb: Urb structure used for device communication. - * @guardian_data: Set to 0, used for sending the guardian data. - * @guardian_urb: Urb structure used to send the guardian data. - */ -struct queue_entry_priv_usb_bcn { - struct urb *urb; - - unsigned int guardian_data; - struct urb *guardian_urb; -}; - -/** - * rt2x00usb_kick_tx_queue - Kick data queue - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @qid: Data queue to kick - * - * This will walk through all entries of the queue and push all pending - * frames to the hardware as a single burst. - */ -void rt2x00usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid); - -/** - * rt2x00usb_kill_tx_queue - Kill data queue - * @rt2x00dev: Pointer to &struct rt2x00_dev - * @qid: Data queue to kill - * - * This will walk through all entries of the queue and kill all - * previously kicked frames before they can be send. - */ -void rt2x00usb_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid); - -/* - * Device initialization handlers. - */ -void rt2x00usb_clear_entry(struct queue_entry *entry); -int rt2x00usb_initialize(struct rt2x00_dev *rt2x00dev); -void rt2x00usb_uninitialize(struct rt2x00_dev *rt2x00dev); - -/* - * USB driver handlers. - */ -int rt2x00usb_probe(struct usb_interface *usb_intf, - const struct usb_device_id *id); -void rt2x00usb_disconnect(struct usb_interface *usb_intf); -#ifdef CONFIG_PM -int rt2x00usb_suspend(struct usb_interface *usb_intf, pm_message_t state); -int rt2x00usb_resume(struct usb_interface *usb_intf); -#else -#define rt2x00usb_suspend NULL -#define rt2x00usb_resume NULL -#endif /* CONFIG_PM */ - -#endif /* RT2X00USB_H */ diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c deleted file mode 100644 index 9a6ceb4e28d8..000000000000 --- a/drivers/net/wireless/rt2x00/rt61pci.c +++ /dev/null @@ -1,2855 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt61pci - Abstract: rt61pci device specific routines. - Supported chipsets: RT2561, RT2561s, RT2661. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00pci.h" -#include "rt61pci.h" - -/* - * Allow hardware encryption to be disabled. - */ -static int modparam_nohwcrypt = 0; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -/* - * Register access. - * BBP and RF register require indirect register access, - * and use the CSR registers PHY_CSR3 and PHY_CSR4 to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - */ -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) -#define WAIT_FOR_MCU(__dev, __reg) \ - rt2x00pci_regbusy_read((__dev), H2M_MAILBOX_CSR, \ - H2M_MAILBOX_CSR_OWNER, (__reg)) - -static void rt61pci_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_VALUE, value); - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - - rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt61pci_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); - - rt2x00pci_register_write(rt2x00dev, PHY_CSR3, reg); - - WAIT_FOR_BBP(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt61pci_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, PHY_CSR4_VALUE, value); - rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, 21); - rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); - rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); - - rt2x00pci_register_write(rt2x00dev, PHY_CSR4, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt61pci_mcu_request(struct rt2x00_dev *rt2x00dev, - const u8 command, const u8 token, - const u8 arg0, const u8 arg1) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the MCU becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_MCU(rt2x00dev, ®)) { - rt2x00_set_field32(®, H2M_MAILBOX_CSR_OWNER, 1); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_CMD_TOKEN, token); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG0, arg0); - rt2x00_set_field32(®, H2M_MAILBOX_CSR_ARG1, arg1); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, HOST_CMD_CSR, ®); - rt2x00_set_field32(®, HOST_CMD_CSR_HOST_COMMAND, command); - rt2x00_set_field32(®, HOST_CMD_CSR_INTERRUPT_MCU, 1); - rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); - -} - -static void rt61pci_eepromregister_read(struct eeprom_93cx6 *eeprom) -{ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); - - eeprom->reg_data_in = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_IN); - eeprom->reg_data_out = !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_OUT); - eeprom->reg_data_clock = - !!rt2x00_get_field32(reg, E2PROM_CSR_DATA_CLOCK); - eeprom->reg_chip_select = - !!rt2x00_get_field32(reg, E2PROM_CSR_CHIP_SELECT); -} - -static void rt61pci_eepromregister_write(struct eeprom_93cx6 *eeprom) -{ - struct rt2x00_dev *rt2x00dev = eeprom->data; - u32 reg = 0; - - rt2x00_set_field32(®, E2PROM_CSR_DATA_IN, !!eeprom->reg_data_in); - rt2x00_set_field32(®, E2PROM_CSR_DATA_OUT, !!eeprom->reg_data_out); - rt2x00_set_field32(®, E2PROM_CSR_DATA_CLOCK, - !!eeprom->reg_data_clock); - rt2x00_set_field32(®, E2PROM_CSR_CHIP_SELECT, - !!eeprom->reg_chip_select); - - rt2x00pci_register_write(rt2x00dev, E2PROM_CSR, reg); -} - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -static const struct rt2x00debug rt61pci_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = rt2x00pci_register_read, - .write = rt2x00pci_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u32), - .word_count = CSR_REG_SIZE / sizeof(u32), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt61pci_bbp_read, - .write = rt61pci_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt61pci_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -static int rt61pci_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - return rt2x00_get_field32(reg, MAC_CSR13_BIT5); -} - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt61pci_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - unsigned int a_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); - unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); - - if (led->type == LED_TYPE_RADIO) { - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MCU_LEDCS_RADIO_STATUS, enabled); - - rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, - (led->rt2x00dev->led_mcu_reg & 0xff), - ((led->rt2x00dev->led_mcu_reg >> 8))); - } else if (led->type == LED_TYPE_ASSOC) { - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MCU_LEDCS_LINK_BG_STATUS, bg_mode); - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MCU_LEDCS_LINK_A_STATUS, a_mode); - - rt61pci_mcu_request(led->rt2x00dev, MCU_LED, 0xff, - (led->rt2x00dev->led_mcu_reg & 0xff), - ((led->rt2x00dev->led_mcu_reg >> 8))); - } else if (led->type == LED_TYPE_QUALITY) { - /* - * The brightness is divided into 6 levels (0 - 5), - * this means we need to convert the brightness - * argument into the matching level within that range. - */ - rt61pci_mcu_request(led->rt2x00dev, MCU_LED_STRENGTH, 0xff, - brightness / (LED_FULL / 6), 0); - } -} - -static int rt61pci_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u32 reg; - - rt2x00pci_register_read(led->rt2x00dev, MAC_CSR14, ®); - rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); - rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); - rt2x00pci_register_write(led->rt2x00dev, MAC_CSR14, reg); - - return 0; -} - -static void rt61pci_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt61pci_brightness_set; - led->led_dev.blink_set = rt61pci_blink_set; - led->flags = LED_INITIALIZED; -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ -static int rt61pci_config_shared_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_key_entry key_entry; - struct rt2x00_field32 field; - u32 mask; - u32 reg; - - if (crypto->cmd == SET_KEY) { - /* - * rt2x00lib can't determine the correct free - * key_idx for shared keys. We have 1 register - * with key valid bits. The goal is simple, read - * the register, if that is full we have no slots - * left. - * Note that each BSS is allowed to have up to 4 - * shared keys, so put a mask over the allowed - * entries. - */ - mask = (0xf << crypto->bssidx); - - rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); - reg &= mask; - - if (reg && reg == mask) - return -ENOSPC; - - key->hw_key_idx += reg ? ffz(reg) : 0; - - /* - * Upload key to hardware - */ - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - reg = SHARED_KEY_ENTRY(key->hw_key_idx); - rt2x00pci_register_multiwrite(rt2x00dev, reg, - &key_entry, sizeof(key_entry)); - - /* - * The cipher types are stored over 2 registers. - * bssidx 0 and 1 keys are stored in SEC_CSR1 and - * bssidx 1 and 2 keys are stored in SEC_CSR5. - * Using the correct defines correctly will cause overhead, - * so just calculate the correct offset. - */ - if (key->hw_key_idx < 8) { - field.bit_offset = (3 * key->hw_key_idx); - field.bit_mask = 0x7 << field.bit_offset; - - rt2x00pci_register_read(rt2x00dev, SEC_CSR1, ®); - rt2x00_set_field32(®, field, crypto->cipher); - rt2x00pci_register_write(rt2x00dev, SEC_CSR1, reg); - } else { - field.bit_offset = (3 * (key->hw_key_idx - 8)); - field.bit_mask = 0x7 << field.bit_offset; - - rt2x00pci_register_read(rt2x00dev, SEC_CSR5, ®); - rt2x00_set_field32(®, field, crypto->cipher); - rt2x00pci_register_write(rt2x00dev, SEC_CSR5, reg); - } - - /* - * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 - * to generate the IV/EIV data. - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } - - /* - * SEC_CSR0 contains only single-bit fields to indicate - * a particular key is valid. Because using the FIELD32() - * defines directly will cause a lot of overhead we use - * a calculation to determine the correct bit directly. - */ - mask = 1 << key->hw_key_idx; - - rt2x00pci_register_read(rt2x00dev, SEC_CSR0, ®); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00pci_register_write(rt2x00dev, SEC_CSR0, reg); - - return 0; -} - -static int rt61pci_config_pairwise_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_pairwise_ta_entry addr_entry; - struct hw_key_entry key_entry; - u32 mask; - u32 reg; - - if (crypto->cmd == SET_KEY) { - /* - * rt2x00lib can't determine the correct free - * key_idx for pairwise keys. We have 2 registers - * with key valid bits. The goal is simple, read - * the first register, if that is full move to - * the next register. - * When both registers are full, we drop the key, - * otherwise we use the first invalid entry. - */ - rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); - if (reg && reg == ~0) { - key->hw_key_idx = 32; - rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); - if (reg && reg == ~0) - return -ENOSPC; - } - - key->hw_key_idx += reg ? ffz(reg) : 0; - - /* - * Upload key to hardware - */ - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - memset(&addr_entry, 0, sizeof(addr_entry)); - memcpy(&addr_entry, crypto->address, ETH_ALEN); - addr_entry.cipher = crypto->cipher; - - reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); - rt2x00pci_register_multiwrite(rt2x00dev, reg, - &key_entry, sizeof(key_entry)); - - reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); - rt2x00pci_register_multiwrite(rt2x00dev, reg, - &addr_entry, sizeof(addr_entry)); - - /* - * Enable pairwise lookup table for given BSS idx, - * without this received frames will not be decrypted - * by the hardware. - */ - rt2x00pci_register_read(rt2x00dev, SEC_CSR4, ®); - reg |= (1 << crypto->bssidx); - rt2x00pci_register_write(rt2x00dev, SEC_CSR4, reg); - - /* - * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 - * to generate the IV/EIV data. - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } - - /* - * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate - * a particular key is valid. Because using the FIELD32() - * defines directly will cause a lot of overhead we use - * a calculation to determine the correct bit directly. - */ - if (key->hw_key_idx < 32) { - mask = 1 << key->hw_key_idx; - - rt2x00pci_register_read(rt2x00dev, SEC_CSR2, ®); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00pci_register_write(rt2x00dev, SEC_CSR2, reg); - } else { - mask = 1 << (key->hw_key_idx - 32); - - rt2x00pci_register_read(rt2x00dev, SEC_CSR3, ®); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00pci_register_write(rt2x00dev, SEC_CSR3, reg); - } - - return 0; -} - -static void rt61pci_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u32 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, - !(filter_flags & (FIF_CONTROL | FIF_PSPOLL))); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(filter_flags & FIF_PROMISC_IN_BSS) && - !rt2x00dev->intf_ap_count); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, - !(filter_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, - !(filter_flags & FIF_CONTROL)); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} - -static void rt61pci_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags) -{ - unsigned int beacon_base; - u32 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2x00pci_register_write(rt2x00dev, beacon_base, 0); - - /* - * Enable synchronisation. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - } - - if (flags & CONFIG_UPDATE_MAC) { - reg = le32_to_cpu(conf->mac[1]); - rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - conf->mac[1] = cpu_to_le32(reg); - - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR2, - conf->mac, sizeof(conf->mac)); - } - - if (flags & CONFIG_UPDATE_BSSID) { - reg = le32_to_cpu(conf->bssid[1]); - rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); - conf->bssid[1] = cpu_to_le32(reg); - - rt2x00pci_register_multiwrite(rt2x00dev, MAC_CSR4, - conf->bssid, sizeof(conf->bssid)); - } -} - -static void rt61pci_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32); - rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!erp->short_preamble); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); - - rt2x00pci_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); - rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); - rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); - rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); - rt2x00pci_register_write(rt2x00dev, MAC_CSR8, reg); -} - -static void rt61pci_config_antenna_5x(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r3; - u8 r4; - u8 r77; - - rt61pci_bbp_read(rt2x00dev, 3, &r3); - rt61pci_bbp_read(rt2x00dev, 4, &r4); - rt61pci_bbp_read(rt2x00dev, 77, &r77); - - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, - rt2x00_rf(&rt2x00dev->chip, RF5325)); - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ)); - break; - case ANTENNA_A: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - else - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - else - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - break; - } - - rt61pci_bbp_write(rt2x00dev, 77, r77); - rt61pci_bbp_write(rt2x00dev, 3, r3); - rt61pci_bbp_write(rt2x00dev, 4, r4); -} - -static void rt61pci_config_antenna_2x(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r3; - u8 r4; - u8 r77; - - rt61pci_bbp_read(rt2x00dev, 3, &r3); - rt61pci_bbp_read(rt2x00dev, 4, &r4); - rt61pci_bbp_read(rt2x00dev, 77, &r77); - - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, - rt2x00_rf(&rt2x00dev->chip, RF2529)); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); - break; - case ANTENNA_A: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - break; - } - - rt61pci_bbp_write(rt2x00dev, 77, r77); - rt61pci_bbp_write(rt2x00dev, 3, r3); - rt61pci_bbp_write(rt2x00dev, 4, r4); -} - -static void rt61pci_config_antenna_2529_rx(struct rt2x00_dev *rt2x00dev, - const int p1, const int p2) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, MAC_CSR13, ®); - - rt2x00_set_field32(®, MAC_CSR13_BIT4, p1); - rt2x00_set_field32(®, MAC_CSR13_BIT12, 0); - - rt2x00_set_field32(®, MAC_CSR13_BIT3, !p2); - rt2x00_set_field32(®, MAC_CSR13_BIT11, 0); - - rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg); -} - -static void rt61pci_config_antenna_2529(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r3; - u8 r4; - u8 r77; - - rt61pci_bbp_read(rt2x00dev, 3, &r3); - rt61pci_bbp_read(rt2x00dev, 4, &r4); - rt61pci_bbp_read(rt2x00dev, 77, &r77); - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_A: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - rt61pci_config_antenna_2529_rx(rt2x00dev, 0, 0); - break; - case ANTENNA_HW_DIVERSITY: - /* - * FIXME: Antenna selection for the rf 2529 is very confusing - * in the legacy driver. Just default to antenna B until the - * legacy code can be properly translated into rt2x00 code. - */ - case ANTENNA_B: - default: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - rt61pci_config_antenna_2529_rx(rt2x00dev, 1, 1); - break; - } - - rt61pci_bbp_write(rt2x00dev, 77, r77); - rt61pci_bbp_write(rt2x00dev, 3, r3); - rt61pci_bbp_write(rt2x00dev, 4, r4); -} - -struct antenna_sel { - u8 word; - /* - * value[0] -> non-LNA - * value[1] -> LNA - */ - u8 value[2]; -}; - -static const struct antenna_sel antenna_sel_a[] = { - { 96, { 0x58, 0x78 } }, - { 104, { 0x38, 0x48 } }, - { 75, { 0xfe, 0x80 } }, - { 86, { 0xfe, 0x80 } }, - { 88, { 0xfe, 0x80 } }, - { 35, { 0x60, 0x60 } }, - { 97, { 0x58, 0x58 } }, - { 98, { 0x58, 0x58 } }, -}; - -static const struct antenna_sel antenna_sel_bg[] = { - { 96, { 0x48, 0x68 } }, - { 104, { 0x2c, 0x3c } }, - { 75, { 0xfe, 0x80 } }, - { 86, { 0xfe, 0x80 } }, - { 88, { 0xfe, 0x80 } }, - { 35, { 0x50, 0x50 } }, - { 97, { 0x48, 0x48 } }, - { 98, { 0x48, 0x48 } }, -}; - -static void rt61pci_config_ant(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - const struct antenna_sel *sel; - unsigned int lna; - unsigned int i; - u32 reg; - - /* - * We should never come here because rt2x00lib is supposed - * to catch this and send us the correct antenna explicitely. - */ - BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || - ant->tx == ANTENNA_SW_DIVERSITY); - - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { - sel = antenna_sel_a; - lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - } else { - sel = antenna_sel_bg; - lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); - } - - for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) - rt61pci_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); - - rt2x00pci_register_read(rt2x00dev, PHY_CSR0, ®); - - rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); - rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); - - rt2x00pci_register_write(rt2x00dev, PHY_CSR0, reg); - - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF5325)) - rt61pci_config_antenna_5x(rt2x00dev, ant); - else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) - rt61pci_config_antenna_2x(rt2x00dev, ant); - else if (rt2x00_rf(&rt2x00dev->chip, RF2529)) { - if (test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) - rt61pci_config_antenna_2x(rt2x00dev, ant); - else - rt61pci_config_antenna_2529(rt2x00dev, ant); - } -} - -static void rt61pci_config_lna_gain(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u16 eeprom; - short lna_gain = 0; - - if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) - lna_gain += 14; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); - lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); - } else { - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) - lna_gain += 14; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); - lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1); - } - - rt2x00dev->lna_gain = lna_gain; -} - -static void rt61pci_config_channel(struct rt2x00_dev *rt2x00dev, - struct rf_channel *rf, const int txpower) -{ - u8 r3; - u8 r94; - u8 smart; - - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - - smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)); - - rt61pci_bbp_read(rt2x00dev, 3, &r3); - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); - rt61pci_bbp_write(rt2x00dev, 3, r3); - - r94 = 6; - if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94)) - r94 += txpower - MAX_TXPOWER; - else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94)) - r94 += txpower; - rt61pci_bbp_write(rt2x00dev, 94, r94); - - rt61pci_rf_write(rt2x00dev, 1, rf->rf1); - rt61pci_rf_write(rt2x00dev, 2, rf->rf2); - rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt61pci_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(200); - - rt61pci_rf_write(rt2x00dev, 1, rf->rf1); - rt61pci_rf_write(rt2x00dev, 2, rf->rf2); - rt61pci_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); - rt61pci_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(200); - - rt61pci_rf_write(rt2x00dev, 1, rf->rf1); - rt61pci_rf_write(rt2x00dev, 2, rf->rf2); - rt61pci_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt61pci_rf_write(rt2x00dev, 4, rf->rf4); - - msleep(1); -} - -static void rt61pci_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - struct rf_channel rf; - - rt2x00_rf_read(rt2x00dev, 1, &rf.rf1); - rt2x00_rf_read(rt2x00dev, 2, &rf.rf2); - rt2x00_rf_read(rt2x00dev, 3, &rf.rf3); - rt2x00_rf_read(rt2x00dev, 4, &rf.rf4); - - rt61pci_config_channel(rt2x00dev, &rf, txpower); -} - -static void rt61pci_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, - libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, - libconf->conf->short_frame_max_tx_count); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR4, reg); -} - -static void rt61pci_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u32 reg; - - if (state == STATE_SLEEP) { - rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); - rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, - rt2x00dev->beacon_int - 10); - rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, - libconf->conf->listen_interval - 1); - rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); - - /* We must first disable autowake before it can be enabled */ - rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); - rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); - - rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); - rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); - - rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000005); - rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x0000001c); - rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000060); - - rt61pci_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0, 0); - } else { - rt2x00pci_register_read(rt2x00dev, MAC_CSR11, ®); - rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); - rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); - rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); - rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); - rt2x00pci_register_write(rt2x00dev, MAC_CSR11, reg); - - rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); - rt2x00pci_register_write(rt2x00dev, IO_CNTL_CSR, 0x00000018); - rt2x00pci_register_write(rt2x00dev, PCI_USEC_CSR, 0x00000020); - - rt61pci_mcu_request(rt2x00dev, MCU_WAKEUP, 0xff, 0, 0); - } -} - -static void rt61pci_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - /* Always recalculate LNA gain before changing configuration */ - rt61pci_config_lna_gain(rt2x00dev, libconf); - - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt61pci_config_channel(rt2x00dev, &libconf->rf, - libconf->conf->power_level); - if ((flags & IEEE80211_CONF_CHANGE_POWER) && - !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) - rt61pci_config_txpower(rt2x00dev, libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt61pci_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt61pci_config_ps(rt2x00dev, libconf); -} - -/* - * Link tuning - */ -static void rt61pci_link_stats(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u32 reg; - - /* - * Update FCS error count from register. - */ - rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); - qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); - - /* - * Update False CCA count from register. - */ - rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); - qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); -} - -static inline void rt61pci_set_vgc(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, u8 vgc_level) -{ - if (qual->vgc_level != vgc_level) { - rt61pci_bbp_write(rt2x00dev, 17, vgc_level); - qual->vgc_level = vgc_level; - qual->vgc_level_reg = vgc_level; - } -} - -static void rt61pci_reset_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - rt61pci_set_vgc(rt2x00dev, qual, 0x20); -} - -static void rt61pci_link_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count) -{ - u8 up_bound; - u8 low_bound; - - /* - * Determine r17 bounds. - */ - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { - low_bound = 0x28; - up_bound = 0x48; - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { - low_bound += 0x10; - up_bound += 0x10; - } - } else { - low_bound = 0x20; - up_bound = 0x40; - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { - low_bound += 0x10; - up_bound += 0x10; - } - } - - /* - * If we are not associated, we should go straight to the - * dynamic CCA tuning. - */ - if (!rt2x00dev->intf_associated) - goto dynamic_cca_tune; - - /* - * Special big-R17 for very short distance - */ - if (qual->rssi >= -35) { - rt61pci_set_vgc(rt2x00dev, qual, 0x60); - return; - } - - /* - * Special big-R17 for short distance - */ - if (qual->rssi >= -58) { - rt61pci_set_vgc(rt2x00dev, qual, up_bound); - return; - } - - /* - * Special big-R17 for middle-short distance - */ - if (qual->rssi >= -66) { - rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x10); - return; - } - - /* - * Special mid-R17 for middle distance - */ - if (qual->rssi >= -74) { - rt61pci_set_vgc(rt2x00dev, qual, low_bound + 0x08); - return; - } - - /* - * Special case: Change up_bound based on the rssi. - * Lower up_bound when rssi is weaker then -74 dBm. - */ - up_bound -= 2 * (-74 - qual->rssi); - if (low_bound > up_bound) - up_bound = low_bound; - - if (qual->vgc_level > up_bound) { - rt61pci_set_vgc(rt2x00dev, qual, up_bound); - return; - } - -dynamic_cca_tune: - - /* - * r17 does not yet exceed upper limit, continue and base - * the r17 tuning on the false CCA count. - */ - if ((qual->false_cca > 512) && (qual->vgc_level < up_bound)) - rt61pci_set_vgc(rt2x00dev, qual, ++qual->vgc_level); - else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound)) - rt61pci_set_vgc(rt2x00dev, qual, --qual->vgc_level); -} - -/* - * Firmware functions - */ -static char *rt61pci_get_firmware_name(struct rt2x00_dev *rt2x00dev) -{ - char *fw_name; - - switch (rt2x00dev->chip.rt) { - case RT2561: - fw_name = FIRMWARE_RT2561; - break; - case RT2561s: - fw_name = FIRMWARE_RT2561s; - break; - case RT2661: - fw_name = FIRMWARE_RT2661; - break; - default: - fw_name = NULL; - break; - } - - return fw_name; -} - -static int rt61pci_check_firmware(struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len) -{ - u16 fw_crc; - u16 crc; - - /* - * Only support 8kb firmware files. - */ - if (len != 8192) - return FW_BAD_LENGTH; - - /* - * The last 2 bytes in the firmware array are the crc checksum itself, - * this means that we should never pass those 2 bytes to the crc - * algorithm. - */ - fw_crc = (data[len - 2] << 8 | data[len - 1]); - - /* - * Use the crc itu-t algorithm. - */ - crc = crc_itu_t(0, data, len - 2); - crc = crc_itu_t_byte(crc, 0); - crc = crc_itu_t_byte(crc, 0); - - return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; -} - -static int rt61pci_load_firmware(struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len) -{ - int i; - u32 reg; - - /* - * Wait for stable hardware. - */ - for (i = 0; i < 100; i++) { - rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg) - break; - msleep(1); - } - - if (!reg) { - ERROR(rt2x00dev, "Unstable hardware.\n"); - return -EBUSY; - } - - /* - * Prepare MCU and mailbox for firmware loading. - */ - reg = 0; - rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); - rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); - rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); - rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CSR, 0); - rt2x00pci_register_write(rt2x00dev, HOST_CMD_CSR, 0); - - /* - * Write firmware to device. - */ - reg = 0; - rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 1); - rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 1); - rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); - - rt2x00pci_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE, - data, len); - - rt2x00_set_field32(®, MCU_CNTL_CSR_SELECT_BANK, 0); - rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); - - rt2x00_set_field32(®, MCU_CNTL_CSR_RESET, 0); - rt2x00pci_register_write(rt2x00dev, MCU_CNTL_CSR, reg); - - for (i = 0; i < 100; i++) { - rt2x00pci_register_read(rt2x00dev, MCU_CNTL_CSR, ®); - if (rt2x00_get_field32(reg, MCU_CNTL_CSR_READY)) - break; - msleep(1); - } - - if (i == 100) { - ERROR(rt2x00dev, "MCU Control register not ready.\n"); - return -EBUSY; - } - - /* - * Hardware needs another millisecond before it is ready. - */ - msleep(1); - - /* - * Reset MAC and BBP registers. - */ - reg = 0; - rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); - rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); - rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); - rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); - rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); - rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); - - return 0; -} - -/* - * Initialization functions. - */ -static bool rt61pci_get_entry_state(struct queue_entry *entry) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - u32 word; - - if (entry->queue->qid == QID_RX) { - rt2x00_desc_read(entry_priv->desc, 0, &word); - - return rt2x00_get_field32(word, RXD_W0_OWNER_NIC); - } else { - rt2x00_desc_read(entry_priv->desc, 0, &word); - - return (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || - rt2x00_get_field32(word, TXD_W0_VALID)); - } -} - -static void rt61pci_clear_entry(struct queue_entry *entry) -{ - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - u32 word; - - if (entry->queue->qid == QID_RX) { - rt2x00_desc_read(entry_priv->desc, 5, &word); - rt2x00_set_field32(&word, RXD_W5_BUFFER_PHYSICAL_ADDRESS, - skbdesc->skb_dma); - rt2x00_desc_write(entry_priv->desc, 5, word); - - rt2x00_desc_read(entry_priv->desc, 0, &word); - rt2x00_set_field32(&word, RXD_W0_OWNER_NIC, 1); - rt2x00_desc_write(entry_priv->desc, 0, word); - } else { - rt2x00_desc_read(entry_priv->desc, 0, &word); - rt2x00_set_field32(&word, TXD_W0_VALID, 0); - rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 0); - rt2x00_desc_write(entry_priv->desc, 0, word); - } -} - -static int rt61pci_init_queues(struct rt2x00_dev *rt2x00dev) -{ - struct queue_entry_priv_pci *entry_priv; - u32 reg; - - /* - * Initialize registers. - */ - rt2x00pci_register_read(rt2x00dev, TX_RING_CSR0, ®); - rt2x00_set_field32(®, TX_RING_CSR0_AC0_RING_SIZE, - rt2x00dev->tx[0].limit); - rt2x00_set_field32(®, TX_RING_CSR0_AC1_RING_SIZE, - rt2x00dev->tx[1].limit); - rt2x00_set_field32(®, TX_RING_CSR0_AC2_RING_SIZE, - rt2x00dev->tx[2].limit); - rt2x00_set_field32(®, TX_RING_CSR0_AC3_RING_SIZE, - rt2x00dev->tx[3].limit); - rt2x00pci_register_write(rt2x00dev, TX_RING_CSR0, reg); - - rt2x00pci_register_read(rt2x00dev, TX_RING_CSR1, ®); - rt2x00_set_field32(®, TX_RING_CSR1_TXD_SIZE, - rt2x00dev->tx[0].desc_size / 4); - rt2x00pci_register_write(rt2x00dev, TX_RING_CSR1, reg); - - entry_priv = rt2x00dev->tx[0].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, AC0_BASE_CSR, ®); - rt2x00_set_field32(®, AC0_BASE_CSR_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, AC0_BASE_CSR, reg); - - entry_priv = rt2x00dev->tx[1].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, AC1_BASE_CSR, ®); - rt2x00_set_field32(®, AC1_BASE_CSR_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, AC1_BASE_CSR, reg); - - entry_priv = rt2x00dev->tx[2].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, AC2_BASE_CSR, ®); - rt2x00_set_field32(®, AC2_BASE_CSR_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, AC2_BASE_CSR, reg); - - entry_priv = rt2x00dev->tx[3].entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, AC3_BASE_CSR, ®); - rt2x00_set_field32(®, AC3_BASE_CSR_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, AC3_BASE_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, RX_RING_CSR, ®); - rt2x00_set_field32(®, RX_RING_CSR_RING_SIZE, rt2x00dev->rx->limit); - rt2x00_set_field32(®, RX_RING_CSR_RXD_SIZE, - rt2x00dev->rx->desc_size / 4); - rt2x00_set_field32(®, RX_RING_CSR_RXD_WRITEBACK_SIZE, 4); - rt2x00pci_register_write(rt2x00dev, RX_RING_CSR, reg); - - entry_priv = rt2x00dev->rx->entries[0].priv_data; - rt2x00pci_register_read(rt2x00dev, RX_BASE_CSR, ®); - rt2x00_set_field32(®, RX_BASE_CSR_RING_REGISTER, - entry_priv->desc_dma); - rt2x00pci_register_write(rt2x00dev, RX_BASE_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, TX_DMA_DST_CSR, ®); - rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC0, 2); - rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC1, 2); - rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC2, 2); - rt2x00_set_field32(®, TX_DMA_DST_CSR_DEST_AC3, 2); - rt2x00pci_register_write(rt2x00dev, TX_DMA_DST_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, LOAD_TX_RING_CSR, ®); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC0, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC1, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC2, 1); - rt2x00_set_field32(®, LOAD_TX_RING_CSR_LOAD_TXD_AC3, 1); - rt2x00pci_register_write(rt2x00dev, LOAD_TX_RING_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); - rt2x00_set_field32(®, RX_CNTL_CSR_LOAD_RXD, 1); - rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); - - return 0; -} - -static int rt61pci_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); - rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR1, ®); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR1, reg); - - /* - * CCK TXD BBP registers - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2, 11); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR2, reg); - - /* - * OFDM TXD BBP registers - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR3, ®); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR3, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR7, ®); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR7, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR8, ®); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR8, reg); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - - rt2x00pci_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); - - rt2x00pci_register_write(rt2x00dev, MAC_CSR6, 0x00000fff); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); - rt2x00pci_register_write(rt2x00dev, MAC_CSR9, reg); - - rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x0000071c); - - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00pci_register_write(rt2x00dev, MAC_CSR13, 0x0000e000); - - /* - * Invalidate all Shared Keys (SEC_CSR0), - * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) - */ - rt2x00pci_register_write(rt2x00dev, SEC_CSR0, 0x00000000); - rt2x00pci_register_write(rt2x00dev, SEC_CSR1, 0x00000000); - rt2x00pci_register_write(rt2x00dev, SEC_CSR5, 0x00000000); - - rt2x00pci_register_write(rt2x00dev, PHY_CSR1, 0x000023b0); - rt2x00pci_register_write(rt2x00dev, PHY_CSR5, 0x060a100c); - rt2x00pci_register_write(rt2x00dev, PHY_CSR6, 0x00080606); - rt2x00pci_register_write(rt2x00dev, PHY_CSR7, 0x00000a08); - - rt2x00pci_register_write(rt2x00dev, PCI_CFG_CSR, 0x28ca4404); - - rt2x00pci_register_write(rt2x00dev, TEST_MODE_CSR, 0x00000200); - - rt2x00pci_register_write(rt2x00dev, M2H_CMD_DONE_CSR, 0xffffffff); - - /* - * Clear all beacons - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2x00pci_register_write(rt2x00dev, HW_BEACON_BASE3, 0); - - /* - * We must clear the error counters. - * These registers are cleared on read, - * so we may pass a useless variable to store the value. - */ - rt2x00pci_register_read(rt2x00dev, STA_CSR0, ®); - rt2x00pci_register_read(rt2x00dev, STA_CSR1, ®); - rt2x00pci_register_read(rt2x00dev, STA_CSR2, ®); - - /* - * Reset MAC and BBP registers. - */ - rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); - rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); - rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); - rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); - rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); - rt2x00pci_register_write(rt2x00dev, MAC_CSR1, reg); - - return 0; -} - -static int rt61pci_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt61pci_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -static int rt61pci_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 reg_id; - u8 value; - - if (unlikely(rt61pci_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt61pci_bbp_write(rt2x00dev, 3, 0x00); - rt61pci_bbp_write(rt2x00dev, 15, 0x30); - rt61pci_bbp_write(rt2x00dev, 21, 0xc8); - rt61pci_bbp_write(rt2x00dev, 22, 0x38); - rt61pci_bbp_write(rt2x00dev, 23, 0x06); - rt61pci_bbp_write(rt2x00dev, 24, 0xfe); - rt61pci_bbp_write(rt2x00dev, 25, 0x0a); - rt61pci_bbp_write(rt2x00dev, 26, 0x0d); - rt61pci_bbp_write(rt2x00dev, 34, 0x12); - rt61pci_bbp_write(rt2x00dev, 37, 0x07); - rt61pci_bbp_write(rt2x00dev, 39, 0xf8); - rt61pci_bbp_write(rt2x00dev, 41, 0x60); - rt61pci_bbp_write(rt2x00dev, 53, 0x10); - rt61pci_bbp_write(rt2x00dev, 54, 0x18); - rt61pci_bbp_write(rt2x00dev, 60, 0x10); - rt61pci_bbp_write(rt2x00dev, 61, 0x04); - rt61pci_bbp_write(rt2x00dev, 62, 0x04); - rt61pci_bbp_write(rt2x00dev, 75, 0xfe); - rt61pci_bbp_write(rt2x00dev, 86, 0xfe); - rt61pci_bbp_write(rt2x00dev, 88, 0xfe); - rt61pci_bbp_write(rt2x00dev, 90, 0x0f); - rt61pci_bbp_write(rt2x00dev, 99, 0x00); - rt61pci_bbp_write(rt2x00dev, 102, 0x16); - rt61pci_bbp_write(rt2x00dev, 107, 0x04); - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt61pci_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} - -/* - * Device state switch handlers. - */ -static void rt61pci_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); -} - -static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int mask = (state == STATE_RADIO_IRQ_OFF); - u32 reg; - - /* - * When interrupts are being enabled, the interrupt registers - * should clear the register to assure a clean state. - */ - if (state == STATE_RADIO_IRQ_ON) { - rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®); - rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); - } - - /* - * Only toggle the interrupts bits we are going to use. - * Non-checked interrupt bits are disabled by default. - */ - rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, ®); - rt2x00_set_field32(®, INT_MASK_CSR_TXDONE, mask); - rt2x00_set_field32(®, INT_MASK_CSR_RXDONE, mask); - rt2x00_set_field32(®, INT_MASK_CSR_ENABLE_MITIGATION, mask); - rt2x00_set_field32(®, INT_MASK_CSR_MITIGATION_PERIOD, 0xff); - rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, ®); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_0, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_1, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_2, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_3, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_4, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_5, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_6, mask); - rt2x00_set_field32(®, MCU_INT_MASK_CSR_7, mask); - rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg); -} - -static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - /* - * Initialize all registers. - */ - if (unlikely(rt61pci_init_queues(rt2x00dev) || - rt61pci_init_registers(rt2x00dev) || - rt61pci_init_bbp(rt2x00dev))) - return -EIO; - - /* - * Enable RX. - */ - rt2x00pci_register_read(rt2x00dev, RX_CNTL_CSR, ®); - rt2x00_set_field32(®, RX_CNTL_CSR_ENABLE_RX_DMA, 1); - rt2x00pci_register_write(rt2x00dev, RX_CNTL_CSR, reg); - - return 0; -} - -static void rt61pci_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Disable power - */ - rt2x00pci_register_write(rt2x00dev, MAC_CSR10, 0x00001818); -} - -static int rt61pci_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) -{ - u32 reg; - unsigned int i; - char put_to_sleep; - - put_to_sleep = (state != STATE_AWAKE); - - rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); - rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); - rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); - rt2x00pci_register_write(rt2x00dev, MAC_CSR12, reg); - - /* - * Device is not guaranteed to be in the requested state yet. - * We must wait until the register indicates that the - * device has entered the correct state. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00pci_register_read(rt2x00dev, MAC_CSR12, ®); - state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); - if (state == !put_to_sleep) - return 0; - msleep(10); - } - - return -EBUSY; -} - -static int rt61pci_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int retval = 0; - - switch (state) { - case STATE_RADIO_ON: - retval = rt61pci_enable_radio(rt2x00dev); - break; - case STATE_RADIO_OFF: - rt61pci_disable_radio(rt2x00dev); - break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt61pci_toggle_rx(rt2x00dev, state); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: - rt61pci_toggle_irq(rt2x00dev, state); - break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt61pci_set_state(rt2x00dev, state); - break; - default: - retval = -ENOTSUPP; - break; - } - - if (unlikely(retval)) - ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", - state, retval); - - return retval; -} - -/* - * TX descriptor initialization - */ -static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; - u32 word; - - /* - * Start writing the descriptor words. - */ - rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); - rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); - rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, - test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W1_BUFFER_COUNT, 1); - rt2x00_desc_write(txd, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); - rt2x00_desc_write(txd, 2, word); - - if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { - _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); - _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); - } - - rt2x00_desc_read(txd, 5, &word); - rt2x00_set_field32(&word, TXD_W5_PID_TYPE, skbdesc->entry->queue->qid); - rt2x00_set_field32(&word, TXD_W5_PID_SUBTYPE, - skbdesc->entry->entry_idx); - rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(rt2x00dev->tx_power)); - rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); - rt2x00_desc_write(txd, 5, word); - - rt2x00_desc_read(txd, 6, &word); - rt2x00_set_field32(&word, TXD_W6_BUFFER_PHYSICAL_ADDRESS, - skbdesc->skb_dma); - rt2x00_desc_write(txd, 6, word); - - if (skbdesc->desc_len > TXINFO_SIZE) { - rt2x00_desc_read(txd, 11, &word); - rt2x00_set_field32(&word, TXD_W11_BUFFER_LENGTH0, skb->len); - rt2x00_desc_write(txd, 11, word); - } - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_OWNER_NIC, 1); - rt2x00_set_field32(&word, TXD_W0_VALID, 1); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_OFDM, - (txdesc->rate_mode == RATE_MODE_OFDM)); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, - test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, - test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, - test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); - rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); - rt2x00_desc_write(txd, 0, word); -} - -/* - * TX data initialization - */ -static void rt61pci_write_beacon(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - unsigned int beacon_base; - u32 reg; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - - /* - * Write entire beacon with descriptor to register. - */ - beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00pci_register_multiwrite(rt2x00dev, - beacon_base, - skbdesc->desc, skbdesc->desc_len); - rt2x00pci_register_multiwrite(rt2x00dev, - beacon_base + skbdesc->desc_len, - entry->skb->data, entry->skb->len); - - /* - * Clean up beacon skb. - */ - dev_kfree_skb_any(entry->skb); - entry->skb = NULL; -} - -static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue == QID_BEACON) { - /* - * For Wi-Fi faily generated beacons between participating - * stations. Set TBTT phase adaptive adjustment step to 8us. - */ - rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, ®); - if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg); - } - return; - } - - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC0, (queue == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC1, (queue == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC2, (queue == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_KICK_TX_AC3, (queue == QID_AC_VO)); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} - -static void rt61pci_kill_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid qid) -{ - u32 reg; - - if (qid == QID_BEACON) { - rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, 0); - return; - } - - rt2x00pci_register_read(rt2x00dev, TX_CNTL_CSR, ®); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC0, (qid == QID_AC_BE)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC1, (qid == QID_AC_BK)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC2, (qid == QID_AC_VI)); - rt2x00_set_field32(®, TX_CNTL_CSR_ABORT_TX_AC3, (qid == QID_AC_VO)); - rt2x00pci_register_write(rt2x00dev, TX_CNTL_CSR, reg); -} - -/* - * RX control handlers - */ -static int rt61pci_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) -{ - u8 offset = rt2x00dev->lna_gain; - u8 lna; - - lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA); - switch (lna) { - case 3: - offset += 90; - break; - case 2: - offset += 74; - break; - case 1: - offset += 64; - break; - default: - return 0; - } - - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { - if (lna == 3 || lna == 2) - offset += 10; - } - - return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; -} - -static void rt61pci_fill_rxdone(struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct queue_entry_priv_pci *entry_priv = entry->priv_data; - u32 word0; - u32 word1; - - rt2x00_desc_read(entry_priv->desc, 0, &word0); - rt2x00_desc_read(entry_priv->desc, 1, &word1); - - if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); - rxdesc->cipher_status = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); - } - - if (rxdesc->cipher != CIPHER_NONE) { - _rt2x00_desc_read(entry_priv->desc, 2, &rxdesc->iv[0]); - _rt2x00_desc_read(entry_priv->desc, 3, &rxdesc->iv[1]); - rxdesc->dev_flags |= RXDONE_CRYPTO_IV; - - _rt2x00_desc_read(entry_priv->desc, 4, &rxdesc->icv); - rxdesc->dev_flags |= RXDONE_CRYPTO_ICV; - - /* - * Hardware has stripped IV/EIV data from 802.11 frame during - * decryption. It has provided the data seperately but rt2x00lib - * should decide if it should be reinserted. - */ - rxdesc->flags |= RX_FLAG_IV_STRIPPED; - - /* - * FIXME: Legacy driver indicates that the frame does - * contain the Michael Mic. Unfortunately, in rt2x00 - * the MIC seems to be missing completely... - */ - rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; - - if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) - rxdesc->flags |= RX_FLAG_DECRYPTED; - else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) - rxdesc->flags |= RX_FLAG_MMIC_ERROR; - } - - /* - * Obtain the status about this packet. - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 100kbit/s. - */ - rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - rxdesc->rssi = rt61pci_agc_to_rssi(rt2x00dev, word1); - rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - - if (rt2x00_get_field32(word0, RXD_W0_OFDM)) - rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; - else - rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; - if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) - rxdesc->dev_flags |= RXDONE_MY_BSS; -} - -/* - * Interrupt functions. - */ -static void rt61pci_txdone(struct rt2x00_dev *rt2x00dev) -{ - struct data_queue *queue; - struct queue_entry *entry; - struct queue_entry *entry_done; - struct queue_entry_priv_pci *entry_priv; - struct txdone_entry_desc txdesc; - u32 word; - u32 reg; - u32 old_reg; - int type; - int index; - - /* - * During each loop we will compare the freshly read - * STA_CSR4 register value with the value read from - * the previous loop. If the 2 values are equal then - * we should stop processing because the chance it - * quite big that the device has been unplugged and - * we risk going into an endless loop. - */ - old_reg = 0; - - while (1) { - rt2x00pci_register_read(rt2x00dev, STA_CSR4, ®); - if (!rt2x00_get_field32(reg, STA_CSR4_VALID)) - break; - - if (old_reg == reg) - break; - old_reg = reg; - - /* - * Skip this entry when it contains an invalid - * queue identication number. - */ - type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE); - queue = rt2x00queue_get_queue(rt2x00dev, type); - if (unlikely(!queue)) - continue; - - /* - * Skip this entry when it contains an invalid - * index number. - */ - index = rt2x00_get_field32(reg, STA_CSR4_PID_SUBTYPE); - if (unlikely(index >= queue->limit)) - continue; - - entry = &queue->entries[index]; - entry_priv = entry->priv_data; - rt2x00_desc_read(entry_priv->desc, 0, &word); - - if (rt2x00_get_field32(word, TXD_W0_OWNER_NIC) || - !rt2x00_get_field32(word, TXD_W0_VALID)) - return; - - entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - while (entry != entry_done) { - /* Catch up. - * Just report any entries we missed as failed. - */ - WARNING(rt2x00dev, - "TX status report missed for entry %d\n", - entry_done->entry_idx); - - txdesc.flags = 0; - __set_bit(TXDONE_UNKNOWN, &txdesc.flags); - txdesc.retry = 0; - - rt2x00lib_txdone(entry_done, &txdesc); - entry_done = rt2x00queue_get_entry(queue, Q_INDEX_DONE); - } - - /* - * Obtain the status about this packet. - */ - txdesc.flags = 0; - switch (rt2x00_get_field32(reg, STA_CSR4_TX_RESULT)) { - case 0: /* Success, maybe with retry */ - __set_bit(TXDONE_SUCCESS, &txdesc.flags); - break; - case 6: /* Failure, excessive retries */ - __set_bit(TXDONE_EXCESSIVE_RETRY, &txdesc.flags); - /* Don't break, this is a failed frame! */ - default: /* Failure */ - __set_bit(TXDONE_FAILURE, &txdesc.flags); - } - txdesc.retry = rt2x00_get_field32(reg, STA_CSR4_RETRY_COUNT); - - rt2x00lib_txdone(entry, &txdesc); - } -} - -static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) -{ - struct rt2x00_dev *rt2x00dev = dev_instance; - u32 reg_mcu; - u32 reg; - - /* - * Get the interrupt sources & saved to local variable. - * Write register value back to clear pending interrupts. - */ - rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, ®_mcu); - rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg_mcu); - - rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, ®); - rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); - - if (!reg && !reg_mcu) - return IRQ_NONE; - - if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) - return IRQ_HANDLED; - - /* - * Handle interrupts, walk through all bits - * and run the tasks, the bits are checked in order of - * priority. - */ - - /* - * 1 - Rx ring done interrupt. - */ - if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE)) - rt2x00pci_rxdone(rt2x00dev); - - /* - * 2 - Tx ring done interrupt. - */ - if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE)) - rt61pci_txdone(rt2x00dev); - - /* - * 3 - Handle MCU command done. - */ - if (reg_mcu) - rt2x00pci_register_write(rt2x00dev, - M2H_CMD_DONE_CSR, 0xffffffff); - - return IRQ_HANDLED; -} - -/* - * Device probe functions. - */ -static int rt61pci_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ - struct eeprom_93cx6 eeprom; - u32 reg; - u16 word; - u8 *mac; - s8 value; - - rt2x00pci_register_read(rt2x00dev, E2PROM_CSR, ®); - - eeprom.data = rt2x00dev; - eeprom.register_read = rt61pci_eepromregister_read; - eeprom.register_write = rt61pci_eepromregister_write; - eeprom.width = rt2x00_get_field32(reg, E2PROM_CSR_TYPE_93C46) ? - PCI_EEPROM_WIDTH_93C46 : PCI_EEPROM_WIDTH_93C66; - eeprom.reg_data_in = 0; - eeprom.reg_data_out = 0; - eeprom.reg_data_clock = 0; - eeprom.reg_chip_select = 0; - - eeprom_93cx6_multiread(&eeprom, EEPROM_BASE, rt2x00dev->eeprom, - EEPROM_SIZE / sizeof(u16)); - - /* - * Start validation of the data that has been read. - */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - if (!is_valid_ether_addr(mac)) { - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %pM\n", mac); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, - ANTENNA_B); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, - ANTENNA_B); - rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5225); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); - EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_ENABLE_DIVERSITY, 0); - rt2x00_set_field16(&word, EEPROM_NIC_TX_DIVERSITY, 0); - rt2x00_set_field16(&word, EEPROM_NIC_RX_FIXED, 0); - rt2x00_set_field16(&word, EEPROM_NIC_TX_FIXED, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_BG, 0); - rt2x00_set_field16(&word, EEPROM_NIC_CARDBUS_ACCEL, 0); - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA_A, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); - EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_LED_LED_MODE, - LED_MODE_DEFAULT); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word); - EEPROM(rt2x00dev, "Led: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); - rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); - EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0); - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word); - EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word); - } else { - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0); - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0); - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); - EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word); - } else { - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0); - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); - } - - return 0; -} - -static int rt61pci_init_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u16 value; - u16 eeprom; - - /* - * Read EEPROM word for configuration. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Identify RF chipset. - */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2x00pci_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip_rf(rt2x00dev, value, reg); - - if (!rt2x00_rf(&rt2x00dev->chip, RF5225) && - !rt2x00_rf(&rt2x00dev->chip, RF5325) && - !rt2x00_rf(&rt2x00dev->chip, RF2527) && - !rt2x00_rf(&rt2x00dev->chip, RF2529)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); - return -ENODEV; - } - - /* - * Determine number of antennas. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_NUM) == 2) - __set_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags); - - /* - * Identify default antenna configuration. - */ - rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); - - /* - * Read the Frame type. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) - __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); - - /* - * Detect if this device has an hardware controlled radio. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); - - /* - * Read frequency offset and RF programming sequence. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); - if (rt2x00_get_field16(eeprom, EEPROM_FREQ_SEQ)) - __set_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags); - - rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); - - /* - * Read external LNA informations. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_A)) - __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA_BG)) - __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); - - /* - * When working with a RF2529 chip without double antenna - * the antenna settings should be gathered from the NIC - * eeprom word. - */ - if (rt2x00_rf(&rt2x00dev->chip, RF2529) && - !test_bit(CONFIG_DOUBLE_ANTENNA, &rt2x00dev->flags)) { - rt2x00dev->default_ant.rx = - ANTENNA_A + rt2x00_get_field16(eeprom, EEPROM_NIC_RX_FIXED); - rt2x00dev->default_ant.tx = - ANTENNA_B - rt2x00_get_field16(eeprom, EEPROM_NIC_TX_FIXED); - - if (rt2x00_get_field16(eeprom, EEPROM_NIC_TX_DIVERSITY)) - rt2x00dev->default_ant.tx = ANTENNA_SW_DIVERSITY; - if (rt2x00_get_field16(eeprom, EEPROM_NIC_ENABLE_DIVERSITY)) - rt2x00dev->default_ant.rx = ANTENNA_SW_DIVERSITY; - } - - /* - * Store led settings, for correct led behaviour. - * If the eeprom value is invalid, - * switch to default led mode. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - value = rt2x00_get_field16(eeprom, EEPROM_LED_LED_MODE); - - rt61pci_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - rt61pci_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); - if (value == LED_MODE_SIGNAL_STRENGTH) - rt61pci_init_led(rt2x00dev, &rt2x00dev->led_qual, - LED_TYPE_QUALITY); - - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_0)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_1)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_2)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_3)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_4)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_RDY_G)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_RDY_A)); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - return 0; -} - -/* - * RF value list for RF5225 & RF5325 - * Supports: 2.4 GHz & 5.2 GHz, rf_sequence disabled - */ -static const struct rf_channel rf_vals_noseq[] = { - { 1, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b }, - { 2, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f }, - { 3, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b }, - { 4, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f }, - { 5, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b }, - { 6, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f }, - { 7, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b }, - { 8, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f }, - { 9, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b }, - { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f }, - { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b }, - { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f }, - { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b }, - { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 }, - { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 }, - { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b }, - { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 }, - { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b }, - { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 }, - { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 }, - { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b }, - - /* 802.11 HyperLan 2 */ - { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 }, - { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b }, - { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 }, - { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b }, - { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 }, - { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 }, - { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b }, - { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 }, - { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b }, - { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 }, - - /* 802.11 UNII */ - { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 }, - { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f }, - { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 }, - { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 }, - { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f }, - { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 }, - - /* MMAC(Japan)J52 ch 34,38,42,46 */ - { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b }, - { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 }, - { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b }, - { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 }, -}; - -/* - * RF value list for RF5225 & RF5325 - * Supports: 2.4 GHz & 5.2 GHz, rf_sequence enabled - */ -static const struct rf_channel rf_vals_seq[] = { - { 1, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b }, - { 2, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f }, - { 3, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b }, - { 4, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f }, - { 5, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b }, - { 6, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f }, - { 7, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b }, - { 8, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f }, - { 9, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b }, - { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f }, - { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b }, - { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f }, - { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b }, - { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x00002cd4, 0x0004481a, 0x00098455, 0x000c0a03 }, - { 40, 0x00002cd0, 0x00044682, 0x00098455, 0x000c0a03 }, - { 44, 0x00002cd0, 0x00044686, 0x00098455, 0x000c0a1b }, - { 48, 0x00002cd0, 0x0004468e, 0x00098655, 0x000c0a0b }, - { 52, 0x00002cd0, 0x00044692, 0x00098855, 0x000c0a23 }, - { 56, 0x00002cd0, 0x0004469a, 0x00098c55, 0x000c0a13 }, - { 60, 0x00002cd0, 0x000446a2, 0x00098e55, 0x000c0a03 }, - { 64, 0x00002cd0, 0x000446a6, 0x00099255, 0x000c0a1b }, - - /* 802.11 HyperLan 2 */ - { 100, 0x00002cd4, 0x0004489a, 0x000b9855, 0x000c0a03 }, - { 104, 0x00002cd4, 0x000448a2, 0x000b9855, 0x000c0a03 }, - { 108, 0x00002cd4, 0x000448aa, 0x000b9855, 0x000c0a03 }, - { 112, 0x00002cd4, 0x000448b2, 0x000b9a55, 0x000c0a03 }, - { 116, 0x00002cd4, 0x000448ba, 0x000b9a55, 0x000c0a03 }, - { 120, 0x00002cd0, 0x00044702, 0x000b9a55, 0x000c0a03 }, - { 124, 0x00002cd0, 0x00044706, 0x000b9a55, 0x000c0a1b }, - { 128, 0x00002cd0, 0x0004470e, 0x000b9c55, 0x000c0a0b }, - { 132, 0x00002cd0, 0x00044712, 0x000b9c55, 0x000c0a23 }, - { 136, 0x00002cd0, 0x0004471a, 0x000b9e55, 0x000c0a13 }, - - /* 802.11 UNII */ - { 140, 0x00002cd0, 0x00044722, 0x000b9e55, 0x000c0a03 }, - { 149, 0x00002cd0, 0x0004472e, 0x000ba255, 0x000c0a1b }, - { 153, 0x00002cd0, 0x00044736, 0x000ba255, 0x000c0a0b }, - { 157, 0x00002cd4, 0x0004490a, 0x000ba255, 0x000c0a17 }, - { 161, 0x00002cd4, 0x00044912, 0x000ba255, 0x000c0a17 }, - { 165, 0x00002cd4, 0x0004491a, 0x000ba255, 0x000c0a17 }, - - /* MMAC(Japan)J52 ch 34,38,42,46 */ - { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000c0a0b }, - { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000c0a13 }, - { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000c0a1b }, - { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000c0a23 }, -}; - -static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - struct channel_info *info; - char *tx_power; - unsigned int i; - - /* - * Disable powersaving as default. - */ - rt2x00dev->hw->wiphy->ps_default = false; - - /* - * Initialize all hw fields. - */ - rt2x00dev->hw->flags = - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; - rt2x00dev->hw->extra_tx_headroom = 0; - - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); - SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, - EEPROM_MAC_ADDR_0)); - - /* - * Initialize hw_mode information. - */ - spec->supported_bands = SUPPORT_BAND_2GHZ; - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - - if (!test_bit(CONFIG_RF_SEQUENCE, &rt2x00dev->flags)) { - spec->num_channels = 14; - spec->channels = rf_vals_noseq; - } else { - spec->num_channels = 14; - spec->channels = rf_vals_seq; - } - - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF5325)) { - spec->supported_bands |= SUPPORT_BAND_5GHZ; - spec->num_channels = ARRAY_SIZE(rf_vals_seq); - } - - /* - * Create channel information array - */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - spec->channels_info = info; - - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - - if (spec->num_channels > 14) { - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - } - - return 0; -} - -static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Disable power saving. - */ - rt2x00pci_register_write(rt2x00dev, SOFT_RESET_CSR, 0x00000007); - - /* - * Allocate eeprom data. - */ - retval = rt61pci_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt61pci_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt61pci_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device has multiple filters for control frames, - * but has no a separate filter for PS Poll frames. - */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); - - /* - * This device requires firmware and DMA mapped skbs. - */ - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - __set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags); - if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; -} - -/* - * IEEE80211 stack callback functions. - */ -static int rt61pci_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, - const struct ieee80211_tx_queue_params *params) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_queue *queue; - struct rt2x00_field32 field; - int retval; - u32 reg; - u32 offset; - - /* - * First pass the configuration through rt2x00lib, that will - * update the queue settings and validate the input. After that - * we are free to update the registers based on the value - * in the queue parameter. - */ - retval = rt2x00mac_conf_tx(hw, queue_idx, params); - if (retval) - return retval; - - /* - * We only need to perform additional register initialization - * for WMM queues/ - */ - if (queue_idx >= 4) - return 0; - - queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - - /* Update WMM TXOP register */ - offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2))); - field.bit_offset = (queue_idx & 1) * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00pci_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00pci_register_write(rt2x00dev, offset, reg); - - /* Update WMM registers */ - field.bit_offset = queue_idx * 4; - field.bit_mask = 0xf << field.bit_offset; - - rt2x00pci_register_read(rt2x00dev, AIFSN_CSR, ®); - rt2x00_set_field32(®, field, queue->aifs); - rt2x00pci_register_write(rt2x00dev, AIFSN_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, CWMIN_CSR, ®); - rt2x00_set_field32(®, field, queue->cw_min); - rt2x00pci_register_write(rt2x00dev, CWMIN_CSR, reg); - - rt2x00pci_register_read(rt2x00dev, CWMAX_CSR, ®); - rt2x00_set_field32(®, field, queue->cw_max); - rt2x00pci_register_write(rt2x00dev, CWMAX_CSR, reg); - - return 0; -} - -static u64 rt61pci_get_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u64 tsf; - u32 reg; - - rt2x00pci_register_read(rt2x00dev, TXRX_CSR13, ®); - tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; - rt2x00pci_register_read(rt2x00dev, TXRX_CSR12, ®); - tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); - - return tsf; -} - -static const struct ieee80211_ops rt61pci_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt61pci_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .get_tsf = rt61pci_get_tsf, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; - -static const struct rt2x00lib_ops rt61pci_rt2x00_ops = { - .irq_handler = rt61pci_interrupt, - .probe_hw = rt61pci_probe_hw, - .get_firmware_name = rt61pci_get_firmware_name, - .check_firmware = rt61pci_check_firmware, - .load_firmware = rt61pci_load_firmware, - .initialize = rt2x00pci_initialize, - .uninitialize = rt2x00pci_uninitialize, - .get_entry_state = rt61pci_get_entry_state, - .clear_entry = rt61pci_clear_entry, - .set_device_state = rt61pci_set_device_state, - .rfkill_poll = rt61pci_rfkill_poll, - .link_stats = rt61pci_link_stats, - .reset_tuner = rt61pci_reset_tuner, - .link_tuner = rt61pci_link_tuner, - .write_tx_desc = rt61pci_write_tx_desc, - .write_tx_data = rt2x00pci_write_tx_data, - .write_beacon = rt61pci_write_beacon, - .kick_tx_queue = rt61pci_kick_tx_queue, - .kill_tx_queue = rt61pci_kill_tx_queue, - .fill_rxdone = rt61pci_fill_rxdone, - .config_shared_key = rt61pci_config_shared_key, - .config_pairwise_key = rt61pci_config_pairwise_key, - .config_filter = rt61pci_config_filter, - .config_intf = rt61pci_config_intf, - .config_erp = rt61pci_config_erp, - .config_ant = rt61pci_config_ant, - .config = rt61pci_config, -}; - -static const struct data_queue_desc rt61pci_queue_rx = { - .entry_num = RX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt61pci_queue_tx = { - .entry_num = TX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct data_queue_desc rt61pci_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, - .data_size = 0, /* No DMA required for beacons */ - .desc_size = TXINFO_SIZE, - .priv_size = sizeof(struct queue_entry_priv_pci), -}; - -static const struct rt2x00_ops rt61pci_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 4, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt61pci_queue_rx, - .tx = &rt61pci_queue_tx, - .bcn = &rt61pci_queue_bcn, - .lib = &rt61pci_rt2x00_ops, - .hw = &rt61pci_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt61pci_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * RT61pci module information. - */ -static struct pci_device_id rt61pci_device_table[] = { - /* RT2561s */ - { PCI_DEVICE(0x1814, 0x0301), PCI_DEVICE_DATA(&rt61pci_ops) }, - /* RT2561 v2 */ - { PCI_DEVICE(0x1814, 0x0302), PCI_DEVICE_DATA(&rt61pci_ops) }, - /* RT2661 */ - { PCI_DEVICE(0x1814, 0x0401), PCI_DEVICE_DATA(&rt61pci_ops) }, - { 0, } -}; - -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Ralink RT61 PCI & PCMCIA Wireless LAN driver."); -MODULE_SUPPORTED_DEVICE("Ralink RT2561, RT2561s & RT2661 " - "PCI & PCMCIA chipset based cards"); -MODULE_DEVICE_TABLE(pci, rt61pci_device_table); -MODULE_FIRMWARE(FIRMWARE_RT2561); -MODULE_FIRMWARE(FIRMWARE_RT2561s); -MODULE_FIRMWARE(FIRMWARE_RT2661); -MODULE_LICENSE("GPL"); - -static struct pci_driver rt61pci_driver = { - .name = KBUILD_MODNAME, - .id_table = rt61pci_device_table, - .probe = rt2x00pci_probe, - .remove = __devexit_p(rt2x00pci_remove), - .suspend = rt2x00pci_suspend, - .resume = rt2x00pci_resume, -}; - -static int __init rt61pci_init(void) -{ - return pci_register_driver(&rt61pci_driver); -} - -static void __exit rt61pci_exit(void) -{ - pci_unregister_driver(&rt61pci_driver); -} - -module_init(rt61pci_init); -module_exit(rt61pci_exit); diff --git a/drivers/net/wireless/rt2x00/rt61pci.h b/drivers/net/wireless/rt2x00/rt61pci.h deleted file mode 100644 index 93eb699165cc..000000000000 --- a/drivers/net/wireless/rt2x00/rt61pci.h +++ /dev/null @@ -1,1492 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt61pci - Abstract: Data structures and registers for the rt61pci module. - Supported chipsets: RT2561, RT2561s, RT2661. - */ - -#ifndef RT61PCI_H -#define RT61PCI_H - -/* - * RF chip defines. - */ -#define RF5225 0x0001 -#define RF5325 0x0002 -#define RF2527 0x0003 -#define RF2529 0x0004 - -/* - * Signal information. - * Defaul offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 120 - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x3000 -#define CSR_REG_SIZE 0x04b0 -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0100 -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0080 -#define RF_BASE 0x0004 -#define RF_SIZE 0x0010 - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 4 - -/* - * PCI registers. - */ - -/* - * HOST_CMD_CSR: For HOST to interrupt embedded processor - */ -#define HOST_CMD_CSR 0x0008 -#define HOST_CMD_CSR_HOST_COMMAND FIELD32(0x0000007f) -#define HOST_CMD_CSR_INTERRUPT_MCU FIELD32(0x00000080) - -/* - * MCU_CNTL_CSR - * SELECT_BANK: Select 8051 program bank. - * RESET: Enable 8051 reset state. - * READY: Ready state for 8051. - */ -#define MCU_CNTL_CSR 0x000c -#define MCU_CNTL_CSR_SELECT_BANK FIELD32(0x00000001) -#define MCU_CNTL_CSR_RESET FIELD32(0x00000002) -#define MCU_CNTL_CSR_READY FIELD32(0x00000004) - -/* - * SOFT_RESET_CSR - * FORCE_CLOCK_ON: Host force MAC clock ON - */ -#define SOFT_RESET_CSR 0x0010 -#define SOFT_RESET_CSR_FORCE_CLOCK_ON FIELD32(0x00000002) - -/* - * MCU_INT_SOURCE_CSR: MCU interrupt source/mask register. - */ -#define MCU_INT_SOURCE_CSR 0x0014 -#define MCU_INT_SOURCE_CSR_0 FIELD32(0x00000001) -#define MCU_INT_SOURCE_CSR_1 FIELD32(0x00000002) -#define MCU_INT_SOURCE_CSR_2 FIELD32(0x00000004) -#define MCU_INT_SOURCE_CSR_3 FIELD32(0x00000008) -#define MCU_INT_SOURCE_CSR_4 FIELD32(0x00000010) -#define MCU_INT_SOURCE_CSR_5 FIELD32(0x00000020) -#define MCU_INT_SOURCE_CSR_6 FIELD32(0x00000040) -#define MCU_INT_SOURCE_CSR_7 FIELD32(0x00000080) -#define MCU_INT_SOURCE_CSR_TWAKEUP FIELD32(0x00000100) -#define MCU_INT_SOURCE_CSR_TBTT_EXPIRE FIELD32(0x00000200) - -/* - * MCU_INT_MASK_CSR: MCU interrupt source/mask register. - */ -#define MCU_INT_MASK_CSR 0x0018 -#define MCU_INT_MASK_CSR_0 FIELD32(0x00000001) -#define MCU_INT_MASK_CSR_1 FIELD32(0x00000002) -#define MCU_INT_MASK_CSR_2 FIELD32(0x00000004) -#define MCU_INT_MASK_CSR_3 FIELD32(0x00000008) -#define MCU_INT_MASK_CSR_4 FIELD32(0x00000010) -#define MCU_INT_MASK_CSR_5 FIELD32(0x00000020) -#define MCU_INT_MASK_CSR_6 FIELD32(0x00000040) -#define MCU_INT_MASK_CSR_7 FIELD32(0x00000080) -#define MCU_INT_MASK_CSR_TWAKEUP FIELD32(0x00000100) -#define MCU_INT_MASK_CSR_TBTT_EXPIRE FIELD32(0x00000200) - -/* - * PCI_USEC_CSR - */ -#define PCI_USEC_CSR 0x001c - -/* - * Security key table memory. - * 16 entries 32-byte for shared key table - * 64 entries 32-byte for pairwise key table - * 64 entries 8-byte for pairwise ta key table - */ -#define SHARED_KEY_TABLE_BASE 0x1000 -#define PAIRWISE_KEY_TABLE_BASE 0x1200 -#define PAIRWISE_TA_TABLE_BASE 0x1a00 - -#define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) -#define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) -#define PAIRWISE_TA_ENTRY(__idx) \ - ( PAIRWISE_TA_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_pairwise_ta_entry)) ) - -struct hw_key_entry { - u8 key[16]; - u8 tx_mic[8]; - u8 rx_mic[8]; -} __attribute__ ((packed)); - -struct hw_pairwise_ta_entry { - u8 address[6]; - u8 cipher; - u8 reserved; -} __attribute__ ((packed)); - -/* - * Other on-chip shared memory space. - */ -#define HW_CIS_BASE 0x2000 -#define HW_NULL_BASE 0x2b00 - -/* - * Since NULL frame won't be that long (256 byte), - * We steal 16 tail bytes to save debugging settings. - */ -#define HW_DEBUG_SETTING_BASE 0x2bf0 - -/* - * On-chip BEACON frame space. - */ -#define HW_BEACON_BASE0 0x2c00 -#define HW_BEACON_BASE1 0x2d00 -#define HW_BEACON_BASE2 0x2e00 -#define HW_BEACON_BASE3 0x2f00 - -#define HW_BEACON_OFFSET(__index) \ - ( HW_BEACON_BASE0 + (__index * 0x0100) ) - -/* - * HOST-MCU shared memory. - */ - -/* - * H2M_MAILBOX_CSR: Host-to-MCU Mailbox. - */ -#define H2M_MAILBOX_CSR 0x2100 -#define H2M_MAILBOX_CSR_ARG0 FIELD32(0x000000ff) -#define H2M_MAILBOX_CSR_ARG1 FIELD32(0x0000ff00) -#define H2M_MAILBOX_CSR_CMD_TOKEN FIELD32(0x00ff0000) -#define H2M_MAILBOX_CSR_OWNER FIELD32(0xff000000) - -/* - * MCU_LEDCS: LED control for MCU Mailbox. - */ -#define MCU_LEDCS_LED_MODE FIELD16(0x001f) -#define MCU_LEDCS_RADIO_STATUS FIELD16(0x0020) -#define MCU_LEDCS_LINK_BG_STATUS FIELD16(0x0040) -#define MCU_LEDCS_LINK_A_STATUS FIELD16(0x0080) -#define MCU_LEDCS_POLARITY_GPIO_0 FIELD16(0x0100) -#define MCU_LEDCS_POLARITY_GPIO_1 FIELD16(0x0200) -#define MCU_LEDCS_POLARITY_GPIO_2 FIELD16(0x0400) -#define MCU_LEDCS_POLARITY_GPIO_3 FIELD16(0x0800) -#define MCU_LEDCS_POLARITY_GPIO_4 FIELD16(0x1000) -#define MCU_LEDCS_POLARITY_ACT FIELD16(0x2000) -#define MCU_LEDCS_POLARITY_READY_BG FIELD16(0x4000) -#define MCU_LEDCS_POLARITY_READY_A FIELD16(0x8000) - -/* - * M2H_CMD_DONE_CSR. - */ -#define M2H_CMD_DONE_CSR 0x2104 - -/* - * MCU_TXOP_ARRAY_BASE. - */ -#define MCU_TXOP_ARRAY_BASE 0x2110 - -/* - * MAC Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * MAC_CSR0: ASIC revision number. - */ -#define MAC_CSR0 0x3000 - -/* - * MAC_CSR1: System control register. - * SOFT_RESET: Software reset bit, 1: reset, 0: normal. - * BBP_RESET: Hardware reset BBP. - * HOST_READY: Host is ready after initialization, 1: ready. - */ -#define MAC_CSR1 0x3004 -#define MAC_CSR1_SOFT_RESET FIELD32(0x00000001) -#define MAC_CSR1_BBP_RESET FIELD32(0x00000002) -#define MAC_CSR1_HOST_READY FIELD32(0x00000004) - -/* - * MAC_CSR2: STA MAC register 0. - */ -#define MAC_CSR2 0x3008 -#define MAC_CSR2_BYTE0 FIELD32(0x000000ff) -#define MAC_CSR2_BYTE1 FIELD32(0x0000ff00) -#define MAC_CSR2_BYTE2 FIELD32(0x00ff0000) -#define MAC_CSR2_BYTE3 FIELD32(0xff000000) - -/* - * MAC_CSR3: STA MAC register 1. - * UNICAST_TO_ME_MASK: - * Used to mask off bits from byte 5 of the MAC address - * to determine the UNICAST_TO_ME bit for RX frames. - * The full mask is complemented by BSS_ID_MASK: - * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK - */ -#define MAC_CSR3 0x300c -#define MAC_CSR3_BYTE4 FIELD32(0x000000ff) -#define MAC_CSR3_BYTE5 FIELD32(0x0000ff00) -#define MAC_CSR3_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) - -/* - * MAC_CSR4: BSSID register 0. - */ -#define MAC_CSR4 0x3010 -#define MAC_CSR4_BYTE0 FIELD32(0x000000ff) -#define MAC_CSR4_BYTE1 FIELD32(0x0000ff00) -#define MAC_CSR4_BYTE2 FIELD32(0x00ff0000) -#define MAC_CSR4_BYTE3 FIELD32(0xff000000) - -/* - * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: - * This mask is used to mask off bits 0 and 1 of byte 5 of the - * BSSID. This will make sure that those bits will be ignored - * when determining the MY_BSS of RX frames. - * 0: 1-BSSID mode (BSS index = 0) - * 1: 2-BSSID mode (BSS index: Byte5, bit 0) - * 2: 2-BSSID mode (BSS index: byte5, bit 1) - * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) - */ -#define MAC_CSR5 0x3014 -#define MAC_CSR5_BYTE4 FIELD32(0x000000ff) -#define MAC_CSR5_BYTE5 FIELD32(0x0000ff00) -#define MAC_CSR5_BSS_ID_MASK FIELD32(0x00ff0000) - -/* - * MAC_CSR6: Maximum frame length register. - */ -#define MAC_CSR6 0x3018 -#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x00000fff) - -/* - * MAC_CSR7: Reserved - */ -#define MAC_CSR7 0x301c - -/* - * MAC_CSR8: SIFS/EIFS register. - * All units are in US. - */ -#define MAC_CSR8 0x3020 -#define MAC_CSR8_SIFS FIELD32(0x000000ff) -#define MAC_CSR8_SIFS_AFTER_RX_OFDM FIELD32(0x0000ff00) -#define MAC_CSR8_EIFS FIELD32(0xffff0000) - -/* - * MAC_CSR9: Back-Off control register. - * SLOT_TIME: Slot time, default is 20us for 802.11BG. - * CWMIN: Bit for Cwmin. default Cwmin is 31 (2^5 - 1). - * CWMAX: Bit for Cwmax, default Cwmax is 1023 (2^10 - 1). - * CW_SELECT: 1: CWmin/Cwmax select from register, 0:select from TxD. - */ -#define MAC_CSR9 0x3024 -#define MAC_CSR9_SLOT_TIME FIELD32(0x000000ff) -#define MAC_CSR9_CWMIN FIELD32(0x00000f00) -#define MAC_CSR9_CWMAX FIELD32(0x0000f000) -#define MAC_CSR9_CW_SELECT FIELD32(0x00010000) - -/* - * MAC_CSR10: Power state configuration. - */ -#define MAC_CSR10 0x3028 - -/* - * MAC_CSR11: Power saving transition time register. - * DELAY_AFTER_TBCN: Delay after Tbcn expired in units of TU. - * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup. - * WAKEUP_LATENCY: In unit of TU. - */ -#define MAC_CSR11 0x302c -#define MAC_CSR11_DELAY_AFTER_TBCN FIELD32(0x000000ff) -#define MAC_CSR11_TBCN_BEFORE_WAKEUP FIELD32(0x00007f00) -#define MAC_CSR11_AUTOWAKE FIELD32(0x00008000) -#define MAC_CSR11_WAKEUP_LATENCY FIELD32(0x000f0000) - -/* - * MAC_CSR12: Manual power control / status register (merge CSR20 & PWRCSR1). - * CURRENT_STATE: 0:sleep, 1:awake. - * FORCE_WAKEUP: This has higher priority than PUT_TO_SLEEP. - * BBP_CURRENT_STATE: 0: BBP sleep, 1: BBP awake. - */ -#define MAC_CSR12 0x3030 -#define MAC_CSR12_CURRENT_STATE FIELD32(0x00000001) -#define MAC_CSR12_PUT_TO_SLEEP FIELD32(0x00000002) -#define MAC_CSR12_FORCE_WAKEUP FIELD32(0x00000004) -#define MAC_CSR12_BBP_CURRENT_STATE FIELD32(0x00000008) - -/* - * MAC_CSR13: GPIO. - */ -#define MAC_CSR13 0x3034 -#define MAC_CSR13_BIT0 FIELD32(0x00000001) -#define MAC_CSR13_BIT1 FIELD32(0x00000002) -#define MAC_CSR13_BIT2 FIELD32(0x00000004) -#define MAC_CSR13_BIT3 FIELD32(0x00000008) -#define MAC_CSR13_BIT4 FIELD32(0x00000010) -#define MAC_CSR13_BIT5 FIELD32(0x00000020) -#define MAC_CSR13_BIT6 FIELD32(0x00000040) -#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. - * ON_PERIOD: On period, default 70ms. - * OFF_PERIOD: Off period, default 30ms. - * HW_LED: HW TX activity, 1: normal OFF, 0: normal ON. - * SW_LED: s/w LED, 1: ON, 0: OFF. - * HW_LED_POLARITY: 0: active low, 1: active high. - */ -#define MAC_CSR14 0x3038 -#define MAC_CSR14_ON_PERIOD FIELD32(0x000000ff) -#define MAC_CSR14_OFF_PERIOD FIELD32(0x0000ff00) -#define MAC_CSR14_HW_LED FIELD32(0x00010000) -#define MAC_CSR14_SW_LED FIELD32(0x00020000) -#define MAC_CSR14_HW_LED_POLARITY FIELD32(0x00040000) -#define MAC_CSR14_SW_LED2 FIELD32(0x00080000) - -/* - * MAC_CSR15: NAV control. - */ -#define MAC_CSR15 0x303c - -/* - * TXRX control registers. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * TXRX_CSR0: TX/RX configuration register. - * TSF_OFFSET: Default is 24. - * AUTO_TX_SEQ: 1: ASIC auto replace sequence nr in outgoing frame. - * DISABLE_RX: Disable Rx engine. - * DROP_CRC: Drop CRC error. - * DROP_PHYSICAL: Drop physical error. - * DROP_CONTROL: Drop control frame. - * DROP_NOT_TO_ME: Drop not to me unicast frame. - * DROP_TO_DS: Drop fram ToDs bit is true. - * DROP_VERSION_ERROR: Drop version error frame. - * DROP_MULTICAST: Drop multicast frames. - * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. - */ -#define TXRX_CSR0 0x3040 -#define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) -#define TXRX_CSR0_TSF_OFFSET FIELD32(0x00007e00) -#define TXRX_CSR0_AUTO_TX_SEQ FIELD32(0x00008000) -#define TXRX_CSR0_DISABLE_RX FIELD32(0x00010000) -#define TXRX_CSR0_DROP_CRC FIELD32(0x00020000) -#define TXRX_CSR0_DROP_PHYSICAL FIELD32(0x00040000) -#define TXRX_CSR0_DROP_CONTROL FIELD32(0x00080000) -#define TXRX_CSR0_DROP_NOT_TO_ME FIELD32(0x00100000) -#define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) -#define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) -#define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) -#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000) -#define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) -#define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) - -/* - * TXRX_CSR1 - */ -#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 - */ -#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 - */ -#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. - * AUTORESPOND_PREAMBLE: 0:long, 1:short preamble. - * OFDM_TX_RATE_DOWN: 1:enable. - * OFDM_TX_RATE_STEP: 0:1-step, 1: 2-step, 2:3-step, 3:4-step. - * OFDM_TX_FALLBACK_CCK: 0: Fallback to OFDM 6M only, 1: Fallback to CCK 1M,2M. - */ -#define TXRX_CSR4 0x3050 -#define TXRX_CSR4_TX_ACK_TIMEOUT FIELD32(0x000000ff) -#define TXRX_CSR4_CNTL_ACK_POLICY FIELD32(0x00000700) -#define TXRX_CSR4_ACK_CTS_PSM FIELD32(0x00010000) -#define TXRX_CSR4_AUTORESPOND_ENABLE FIELD32(0x00020000) -#define TXRX_CSR4_AUTORESPOND_PREAMBLE FIELD32(0x00040000) -#define TXRX_CSR4_OFDM_TX_RATE_DOWN FIELD32(0x00080000) -#define TXRX_CSR4_OFDM_TX_RATE_STEP FIELD32(0x00300000) -#define TXRX_CSR4_OFDM_TX_FALLBACK_CCK FIELD32(0x00400000) -#define TXRX_CSR4_LONG_RETRY_LIMIT FIELD32(0x0f000000) -#define TXRX_CSR4_SHORT_RETRY_LIMIT FIELD32(0xf0000000) - -/* - * TXRX_CSR5 - */ -#define TXRX_CSR5 0x3054 - -/* - * TXRX_CSR6: ACK/CTS payload consumed time - */ -#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_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_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. - * BEACON_INTERVAL: In unit of 1/16 TU. - * TSF_TICKING: Enable TSF auto counting. - * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode. - * BEACON_GEN: Enable beacon generator. - */ -#define TXRX_CSR9 0x3064 -#define TXRX_CSR9_BEACON_INTERVAL FIELD32(0x0000ffff) -#define TXRX_CSR9_TSF_TICKING FIELD32(0x00010000) -#define TXRX_CSR9_TSF_SYNC FIELD32(0x00060000) -#define TXRX_CSR9_TBTT_ENABLE FIELD32(0x00080000) -#define TXRX_CSR9_BEACON_GEN FIELD32(0x00100000) -#define TXRX_CSR9_TIMESTAMP_COMPENSATE FIELD32(0xff000000) - -/* - * TXRX_CSR10: BEACON alignment. - */ -#define TXRX_CSR10 0x3068 - -/* - * TXRX_CSR11: AES mask. - */ -#define TXRX_CSR11 0x306c - -/* - * TXRX_CSR12: TSF low 32. - */ -#define TXRX_CSR12 0x3070 -#define TXRX_CSR12_LOW_TSFTIMER FIELD32(0xffffffff) - -/* - * TXRX_CSR13: TSF high 32. - */ -#define TXRX_CSR13 0x3074 -#define TXRX_CSR13_HIGH_TSFTIMER FIELD32(0xffffffff) - -/* - * TXRX_CSR14: TBTT timer. - */ -#define TXRX_CSR14 0x3078 - -/* - * TXRX_CSR15: TKIP MIC priority byte "AND" mask. - */ -#define TXRX_CSR15 0x307c - -/* - * PHY control registers. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * PHY_CSR0: RF/PS control. - */ -#define PHY_CSR0 0x3080 -#define PHY_CSR0_PA_PE_BG FIELD32(0x00010000) -#define PHY_CSR0_PA_PE_A FIELD32(0x00020000) - -/* - * PHY_CSR1 - */ -#define PHY_CSR1 0x3084 - -/* - * PHY_CSR2: Pre-TX BBP control. - */ -#define PHY_CSR2 0x3088 - -/* - * PHY_CSR3: BBP serial control register. - * VALUE: Register value to program into BBP. - * REG_NUM: Selected BBP register. - * READ_CONTROL: 0: Write BBP, 1: Read BBP. - * BUSY: 1: ASIC is busy execute BBP programming. - */ -#define PHY_CSR3 0x308c -#define PHY_CSR3_VALUE FIELD32(0x000000ff) -#define PHY_CSR3_REGNUM FIELD32(0x00007f00) -#define PHY_CSR3_READ_CONTROL FIELD32(0x00008000) -#define PHY_CSR3_BUSY FIELD32(0x00010000) - -/* - * PHY_CSR4: RF serial control register - * VALUE: Register value (include register id) serial out to RF/IF chip. - * NUMBER_OF_BITS: Number of bits used in RFRegValue (I:20, RFMD:22). - * IF_SELECT: 1: select IF to program, 0: select RF to program. - * PLL_LD: RF PLL_LD status. - * BUSY: 1: ASIC is busy execute RF programming. - */ -#define PHY_CSR4 0x3090 -#define PHY_CSR4_VALUE FIELD32(0x00ffffff) -#define PHY_CSR4_NUMBER_OF_BITS FIELD32(0x1f000000) -#define PHY_CSR4_IF_SELECT FIELD32(0x20000000) -#define PHY_CSR4_PLL_LD FIELD32(0x40000000) -#define PHY_CSR4_BUSY FIELD32(0x80000000) - -/* - * PHY_CSR5: RX to TX signal switch timing control. - */ -#define PHY_CSR5 0x3094 -#define PHY_CSR5_IQ_FLIP FIELD32(0x00000004) - -/* - * PHY_CSR6: TX to RX signal timing control. - */ -#define PHY_CSR6 0x3098 -#define PHY_CSR6_IQ_FLIP FIELD32(0x00000004) - -/* - * PHY_CSR7: TX DAC switching timing control. - */ -#define PHY_CSR7 0x309c - -/* - * Security control register. - */ - -/* - * SEC_CSR0: Shared key table control. - */ -#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. - */ -#define SEC_CSR1 0x30a4 -#define SEC_CSR1_BSS0_KEY0_CIPHER_ALG FIELD32(0x00000007) -#define SEC_CSR1_BSS0_KEY1_CIPHER_ALG FIELD32(0x00000070) -#define SEC_CSR1_BSS0_KEY2_CIPHER_ALG FIELD32(0x00000700) -#define SEC_CSR1_BSS0_KEY3_CIPHER_ALG FIELD32(0x00007000) -#define SEC_CSR1_BSS1_KEY0_CIPHER_ALG FIELD32(0x00070000) -#define SEC_CSR1_BSS1_KEY1_CIPHER_ALG FIELD32(0x00700000) -#define SEC_CSR1_BSS1_KEY2_CIPHER_ALG FIELD32(0x07000000) -#define SEC_CSR1_BSS1_KEY3_CIPHER_ALG FIELD32(0x70000000) - -/* - * Pairwise key table valid bitmap registers. - * SEC_CSR2: pairwise key table valid bitmap 0. - * SEC_CSR3: pairwise key table valid bitmap 1. - */ -#define SEC_CSR2 0x30a8 -#define SEC_CSR3 0x30ac - -/* - * SEC_CSR4: Pairwise key table lookup control. - */ -#define SEC_CSR4 0x30b0 -#define SEC_CSR4_ENABLE_BSS0 FIELD32(0x00000001) -#define SEC_CSR4_ENABLE_BSS1 FIELD32(0x00000002) -#define SEC_CSR4_ENABLE_BSS2 FIELD32(0x00000004) -#define SEC_CSR4_ENABLE_BSS3 FIELD32(0x00000008) - -/* - * SEC_CSR5: shared key table security mode register. - */ -#define SEC_CSR5 0x30b4 -#define SEC_CSR5_BSS2_KEY0_CIPHER_ALG FIELD32(0x00000007) -#define SEC_CSR5_BSS2_KEY1_CIPHER_ALG FIELD32(0x00000070) -#define SEC_CSR5_BSS2_KEY2_CIPHER_ALG FIELD32(0x00000700) -#define SEC_CSR5_BSS2_KEY3_CIPHER_ALG FIELD32(0x00007000) -#define SEC_CSR5_BSS3_KEY0_CIPHER_ALG FIELD32(0x00070000) -#define SEC_CSR5_BSS3_KEY1_CIPHER_ALG FIELD32(0x00700000) -#define SEC_CSR5_BSS3_KEY2_CIPHER_ALG FIELD32(0x07000000) -#define SEC_CSR5_BSS3_KEY3_CIPHER_ALG FIELD32(0x70000000) - -/* - * STA control registers. - */ - -/* - * STA_CSR0: RX PLCP error count & RX FCS error count. - */ -#define STA_CSR0 0x30c0 -#define STA_CSR0_FCS_ERROR FIELD32(0x0000ffff) -#define STA_CSR0_PLCP_ERROR FIELD32(0xffff0000) - -/* - * STA_CSR1: RX False CCA count & RX LONG frame count. - */ -#define STA_CSR1 0x30c4 -#define STA_CSR1_PHYSICAL_ERROR FIELD32(0x0000ffff) -#define STA_CSR1_FALSE_CCA_ERROR FIELD32(0xffff0000) - -/* - * STA_CSR2: TX Beacon count and RX FIFO overflow count. - */ -#define STA_CSR2 0x30c8 -#define STA_CSR2_RX_FIFO_OVERFLOW_COUNT FIELD32(0x0000ffff) -#define STA_CSR2_RX_OVERFLOW_COUNT FIELD32(0xffff0000) - -/* - * STA_CSR3: TX Beacon count. - */ -#define STA_CSR3 0x30cc -#define STA_CSR3_TX_BEACON_COUNT FIELD32(0x0000ffff) - -/* - * STA_CSR4: TX Result status register. - * VALID: 1:This register contains a valid TX result. - */ -#define STA_CSR4 0x30d0 -#define STA_CSR4_VALID FIELD32(0x00000001) -#define STA_CSR4_TX_RESULT FIELD32(0x0000000e) -#define STA_CSR4_RETRY_COUNT FIELD32(0x000000f0) -#define STA_CSR4_PID_SUBTYPE FIELD32(0x00001f00) -#define STA_CSR4_PID_TYPE FIELD32(0x0000e000) -#define STA_CSR4_TXRATE FIELD32(0x000f0000) - -/* - * QOS control registers. - */ - -/* - * QOS_CSR0: TXOP holder MAC address register. - */ -#define QOS_CSR0 0x30e0 -#define QOS_CSR0_BYTE0 FIELD32(0x000000ff) -#define QOS_CSR0_BYTE1 FIELD32(0x0000ff00) -#define QOS_CSR0_BYTE2 FIELD32(0x00ff0000) -#define QOS_CSR0_BYTE3 FIELD32(0xff000000) - -/* - * QOS_CSR1: TXOP holder MAC address register. - */ -#define QOS_CSR1 0x30e4 -#define QOS_CSR1_BYTE4 FIELD32(0x000000ff) -#define QOS_CSR1_BYTE5 FIELD32(0x0000ff00) - -/* - * QOS_CSR2: TXOP holder timeout register. - */ -#define QOS_CSR2 0x30e8 - -/* - * RX QOS-CFPOLL MAC address register. - * QOS_CSR3: RX QOS-CFPOLL MAC address 0. - * QOS_CSR4: RX QOS-CFPOLL MAC address 1. - */ -#define QOS_CSR3 0x30ec -#define QOS_CSR4 0x30f0 - -/* - * QOS_CSR5: "QosControl" field of the RX QOS-CFPOLL. - */ -#define QOS_CSR5 0x30f4 - -/* - * Host DMA registers. - */ - -/* - * AC0_BASE_CSR: AC_BK base address. - */ -#define AC0_BASE_CSR 0x3400 -#define AC0_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) - -/* - * AC1_BASE_CSR: AC_BE base address. - */ -#define AC1_BASE_CSR 0x3404 -#define AC1_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) - -/* - * AC2_BASE_CSR: AC_VI base address. - */ -#define AC2_BASE_CSR 0x3408 -#define AC2_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) - -/* - * AC3_BASE_CSR: AC_VO base address. - */ -#define AC3_BASE_CSR 0x340c -#define AC3_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) - -/* - * MGMT_BASE_CSR: MGMT ring base address. - */ -#define MGMT_BASE_CSR 0x3410 -#define MGMT_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) - -/* - * TX_RING_CSR0: TX Ring size for AC_BK, AC_BE, AC_VI, AC_VO. - */ -#define TX_RING_CSR0 0x3418 -#define TX_RING_CSR0_AC0_RING_SIZE FIELD32(0x000000ff) -#define TX_RING_CSR0_AC1_RING_SIZE FIELD32(0x0000ff00) -#define TX_RING_CSR0_AC2_RING_SIZE FIELD32(0x00ff0000) -#define TX_RING_CSR0_AC3_RING_SIZE FIELD32(0xff000000) - -/* - * TX_RING_CSR1: TX Ring size for MGMT Ring, HCCA Ring - * TXD_SIZE: In unit of 32-bit. - */ -#define TX_RING_CSR1 0x341c -#define TX_RING_CSR1_MGMT_RING_SIZE FIELD32(0x000000ff) -#define TX_RING_CSR1_HCCA_RING_SIZE FIELD32(0x0000ff00) -#define TX_RING_CSR1_TXD_SIZE FIELD32(0x003f0000) - -/* - * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. - */ -#define AIFSN_CSR 0x3420 -#define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f) -#define AIFSN_CSR_AIFSN1 FIELD32(0x000000f0) -#define AIFSN_CSR_AIFSN2 FIELD32(0x00000f00) -#define AIFSN_CSR_AIFSN3 FIELD32(0x0000f000) - -/* - * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. - */ -#define CWMIN_CSR 0x3424 -#define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f) -#define CWMIN_CSR_CWMIN1 FIELD32(0x000000f0) -#define CWMIN_CSR_CWMIN2 FIELD32(0x00000f00) -#define CWMIN_CSR_CWMIN3 FIELD32(0x0000f000) - -/* - * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. - */ -#define CWMAX_CSR 0x3428 -#define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f) -#define CWMAX_CSR_CWMAX1 FIELD32(0x000000f0) -#define CWMAX_CSR_CWMAX2 FIELD32(0x00000f00) -#define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000) - -/* - * 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_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. - * KICK_TX_AC0: For AC_BK. - * KICK_TX_AC1: For AC_BE. - * KICK_TX_AC2: For AC_VI. - * KICK_TX_AC3: For AC_VO. - * ABORT_TX_AC0: For AC_BK. - * ABORT_TX_AC1: For AC_BE. - * ABORT_TX_AC2: For AC_VI. - * ABORT_TX_AC3: For AC_VO. - */ -#define TX_CNTL_CSR 0x3430 -#define TX_CNTL_CSR_KICK_TX_AC0 FIELD32(0x00000001) -#define TX_CNTL_CSR_KICK_TX_AC1 FIELD32(0x00000002) -#define TX_CNTL_CSR_KICK_TX_AC2 FIELD32(0x00000004) -#define TX_CNTL_CSR_KICK_TX_AC3 FIELD32(0x00000008) -#define TX_CNTL_CSR_KICK_TX_MGMT FIELD32(0x00000010) -#define TX_CNTL_CSR_ABORT_TX_AC0 FIELD32(0x00010000) -#define TX_CNTL_CSR_ABORT_TX_AC1 FIELD32(0x00020000) -#define TX_CNTL_CSR_ABORT_TX_AC2 FIELD32(0x00040000) -#define TX_CNTL_CSR_ABORT_TX_AC3 FIELD32(0x00080000) -#define TX_CNTL_CSR_ABORT_TX_MGMT FIELD32(0x00100000) - -/* - * LOAD_TX_RING_CSR: Load RX desriptor - */ -#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. - */ -#define AC0_TXPTR_CSR 0x3438 -#define AC1_TXPTR_CSR 0x343c -#define AC2_TXPTR_CSR 0x3440 -#define AC3_TXPTR_CSR 0x3444 -#define MGMT_TXPTR_CSR 0x3448 - -/* - * RX_BASE_CSR - */ -#define RX_BASE_CSR 0x3450 -#define RX_BASE_CSR_RING_REGISTER FIELD32(0xffffffff) - -/* - * RX_RING_CSR. - * RXD_SIZE: In unit of 32-bit. - */ -#define RX_RING_CSR 0x3454 -#define RX_RING_CSR_RING_SIZE FIELD32(0x000000ff) -#define RX_RING_CSR_RXD_SIZE FIELD32(0x00003f00) -#define RX_RING_CSR_RXD_WRITEBACK_SIZE FIELD32(0x00070000) - -/* - * RX_CNTL_CSR - */ -#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. - */ -#define RXPTR_CSR 0x345c - -/* - * PCI_CFG_CSR - */ -#define PCI_CFG_CSR 0x3460 - -/* - * BUF_FORMAT_CSR - */ -#define BUF_FORMAT_CSR 0x3464 - -/* - * INT_SOURCE_CSR: Interrupt source register. - * Write one to clear corresponding bit. - */ -#define INT_SOURCE_CSR 0x3468 -#define INT_SOURCE_CSR_TXDONE FIELD32(0x00000001) -#define INT_SOURCE_CSR_RXDONE FIELD32(0x00000002) -#define INT_SOURCE_CSR_BEACON_DONE FIELD32(0x00000004) -#define INT_SOURCE_CSR_TX_ABORT_DONE FIELD32(0x00000010) -#define INT_SOURCE_CSR_AC0_DMA_DONE FIELD32(0x00010000) -#define INT_SOURCE_CSR_AC1_DMA_DONE FIELD32(0x00020000) -#define INT_SOURCE_CSR_AC2_DMA_DONE FIELD32(0x00040000) -#define INT_SOURCE_CSR_AC3_DMA_DONE FIELD32(0x00080000) -#define INT_SOURCE_CSR_MGMT_DMA_DONE FIELD32(0x00100000) -#define INT_SOURCE_CSR_HCCA_DMA_DONE FIELD32(0x00200000) - -/* - * INT_MASK_CSR: Interrupt MASK register. 1: the interrupt is mask OFF. - * MITIGATION_PERIOD: Interrupt mitigation in unit of 32 PCI clock. - */ -#define INT_MASK_CSR 0x346c -#define INT_MASK_CSR_TXDONE FIELD32(0x00000001) -#define INT_MASK_CSR_RXDONE FIELD32(0x00000002) -#define INT_MASK_CSR_BEACON_DONE FIELD32(0x00000004) -#define INT_MASK_CSR_TX_ABORT_DONE FIELD32(0x00000010) -#define INT_MASK_CSR_ENABLE_MITIGATION FIELD32(0x00000080) -#define INT_MASK_CSR_MITIGATION_PERIOD FIELD32(0x0000ff00) -#define INT_MASK_CSR_AC0_DMA_DONE FIELD32(0x00010000) -#define INT_MASK_CSR_AC1_DMA_DONE FIELD32(0x00020000) -#define INT_MASK_CSR_AC2_DMA_DONE FIELD32(0x00040000) -#define INT_MASK_CSR_AC3_DMA_DONE FIELD32(0x00080000) -#define INT_MASK_CSR_MGMT_DMA_DONE FIELD32(0x00100000) -#define INT_MASK_CSR_HCCA_DMA_DONE FIELD32(0x00200000) - -/* - * E2PROM_CSR: EEPROM control register. - * RELOAD: Write 1 to reload eeprom content. - * TYPE_93C46: 1: 93c46, 0:93c66. - * LOAD_STATUS: 1:loading, 0:done. - */ -#define E2PROM_CSR 0x3470 -#define E2PROM_CSR_RELOAD FIELD32(0x00000001) -#define E2PROM_CSR_DATA_CLOCK FIELD32(0x00000002) -#define E2PROM_CSR_CHIP_SELECT FIELD32(0x00000004) -#define E2PROM_CSR_DATA_IN FIELD32(0x00000008) -#define E2PROM_CSR_DATA_OUT FIELD32(0x00000010) -#define E2PROM_CSR_TYPE_93C46 FIELD32(0x00000020) -#define E2PROM_CSR_LOAD_STATUS FIELD32(0x00000040) - -/* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. - */ -#define AC_TXOP_CSR0 0x3474 -#define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff) -#define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000) - -/* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. - */ -#define AC_TXOP_CSR1 0x3478 -#define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) -#define AC_TXOP_CSR1_AC3_TX_OP FIELD32(0xffff0000) - -/* - * DMA_STATUS_CSR - */ -#define DMA_STATUS_CSR 0x3480 - -/* - * TEST_MODE_CSR - */ -#define TEST_MODE_CSR 0x3484 - -/* - * UART0_TX_CSR - */ -#define UART0_TX_CSR 0x3488 - -/* - * UART0_RX_CSR - */ -#define UART0_RX_CSR 0x348c - -/* - * UART0_FRAME_CSR - */ -#define UART0_FRAME_CSR 0x3490 - -/* - * UART0_BUFFER_CSR - */ -#define UART0_BUFFER_CSR 0x3494 - -/* - * IO_CNTL_CSR - * RF_PS: Set RF interface value to power save - */ -#define IO_CNTL_CSR 0x3498 -#define IO_CNTL_CSR_RF_PS FIELD32(0x00000004) - -/* - * UART_INT_SOURCE_CSR - */ -#define UART_INT_SOURCE_CSR 0x34a8 - -/* - * UART_INT_MASK_CSR - */ -#define UART_INT_MASK_CSR 0x34ac - -/* - * PBF_QUEUE_CSR - */ -#define PBF_QUEUE_CSR 0x34b0 - -/* - * Firmware DMA registers. - * Firmware DMA registers are dedicated for MCU usage - * and should not be touched by host driver. - * Therefore we skip the definition of these registers. - */ -#define FW_TX_BASE_CSR 0x34c0 -#define FW_TX_START_CSR 0x34c4 -#define FW_TX_LAST_CSR 0x34c8 -#define FW_MODE_CNTL_CSR 0x34cc -#define FW_TXPTR_CSR 0x34d0 - -/* - * 8051 firmware image. - */ -#define FIRMWARE_RT2561 "rt2561.bin" -#define FIRMWARE_RT2561s "rt2561s.bin" -#define FIRMWARE_RT2661 "rt2661.bin" -#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) - */ - -/* - * ANTENNA_CONTROL semantics (guessed): - * 0x1: Software controlled antenna switching (fixed or SW diversity) - * 0x2: Hardware diversity. - */ -#define BBP_R4_RX_ANTENNA_CONTROL FIELD8(0x03) -#define BBP_R4_RX_FRAME_END FIELD8(0x20) - -/* - * R77 - */ -#define BBP_R77_RX_ANTENNA FIELD8(0x03) - -/* - * RF registers - */ - -/* - * RF 3 - */ -#define RF3_TXPOWER FIELD32(0x00003e00) - -/* - * RF 4 - */ -#define RF4_FREQ_OFFSET FIELD32(0x0003f000) - -/* - * EEPROM content. - * The wordsize of the EEPROM is 16 bits. - */ - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM antenna. - * ANTENNA_NUM: Number of antenna's. - * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only. - * DYN_TXAGC: Dynamic TX AGC control. - * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0. - * RF_TYPE: Rf_type of this adapter. - */ -#define EEPROM_ANTENNA 0x0010 -#define EEPROM_ANTENNA_NUM FIELD16(0x0003) -#define EEPROM_ANTENNA_TX_DEFAULT FIELD16(0x000c) -#define EEPROM_ANTENNA_RX_DEFAULT FIELD16(0x0030) -#define EEPROM_ANTENNA_FRAME_TYPE FIELD16(0x0040) -#define EEPROM_ANTENNA_DYN_TXAGC FIELD16(0x0200) -#define EEPROM_ANTENNA_HARDWARE_RADIO FIELD16(0x0400) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0xf800) - -/* - * EEPROM NIC config. - * ENABLE_DIVERSITY: 1:enable, 0:disable. - * EXTERNAL_LNA_BG: External LNA enable for 2.4G. - * CARDBUS_ACCEL: 0:enable, 1:disable. - * EXTERNAL_LNA_A: External LNA enable for 5G. - */ -#define EEPROM_NIC 0x0011 -#define EEPROM_NIC_ENABLE_DIVERSITY FIELD16(0x0001) -#define EEPROM_NIC_TX_DIVERSITY FIELD16(0x0002) -#define EEPROM_NIC_RX_FIXED FIELD16(0x0004) -#define EEPROM_NIC_TX_FIXED FIELD16(0x0008) -#define EEPROM_NIC_EXTERNAL_LNA_BG FIELD16(0x0010) -#define EEPROM_NIC_CARDBUS_ACCEL FIELD16(0x0020) -#define EEPROM_NIC_EXTERNAL_LNA_A FIELD16(0x0040) - -/* - * EEPROM geography. - * GEO_A: Default geographical setting for 5GHz band - * GEO: Default geographical setting. - */ -#define EEPROM_GEOGRAPHY 0x0012 -#define EEPROM_GEOGRAPHY_GEO_A FIELD16(0x00ff) -#define EEPROM_GEOGRAPHY_GEO FIELD16(0xff00) - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x0013 -#define EEPROM_BBP_SIZE 16 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * EEPROM TXPOWER 802.11G - */ -#define EEPROM_TXPOWER_G_START 0x0023 -#define EEPROM_TXPOWER_G_SIZE 7 -#define EEPROM_TXPOWER_G_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_G_2 FIELD16(0xff00) - -/* - * EEPROM Frequency - */ -#define EEPROM_FREQ 0x002f -#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) -#define EEPROM_FREQ_SEQ_MASK FIELD16(0xff00) -#define EEPROM_FREQ_SEQ FIELD16(0x0300) - -/* - * EEPROM LED. - * POLARITY_RDY_G: Polarity RDY_G setting. - * POLARITY_RDY_A: Polarity RDY_A setting. - * POLARITY_ACT: Polarity ACT setting. - * POLARITY_GPIO_0: Polarity GPIO0 setting. - * POLARITY_GPIO_1: Polarity GPIO1 setting. - * POLARITY_GPIO_2: Polarity GPIO2 setting. - * POLARITY_GPIO_3: Polarity GPIO3 setting. - * POLARITY_GPIO_4: Polarity GPIO4 setting. - * LED_MODE: Led mode. - */ -#define EEPROM_LED 0x0030 -#define EEPROM_LED_POLARITY_RDY_G FIELD16(0x0001) -#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) -#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) -#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) -#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) -#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) -#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) -#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) -#define EEPROM_LED_LED_MODE FIELD16(0x1f00) - -/* - * EEPROM TXPOWER 802.11A - */ -#define EEPROM_TXPOWER_A_START 0x0031 -#define EEPROM_TXPOWER_A_SIZE 12 -#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) - -/* - * EEPROM RSSI offset 802.11BG - */ -#define EEPROM_RSSI_OFFSET_BG 0x004d -#define EEPROM_RSSI_OFFSET_BG_1 FIELD16(0x00ff) -#define EEPROM_RSSI_OFFSET_BG_2 FIELD16(0xff00) - -/* - * EEPROM RSSI offset 802.11A - */ -#define EEPROM_RSSI_OFFSET_A 0x004e -#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff) -#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00) - -/* - * MCU mailbox commands. - */ -#define MCU_SLEEP 0x30 -#define MCU_WAKEUP 0x31 -#define MCU_LED 0x50 -#define MCU_LED_STRENGTH 0x52 - -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE ( 16 * sizeof(__le32) ) -#define TXINFO_SIZE ( 6 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 16 * sizeof(__le32) ) - -/* - * TX descriptor format for TX, PRIO and Beacon Ring. - */ - -/* - * Word0 - * TKIP_MIC: ASIC appends TKIP MIC if TKIP is used. - * KEY_TABLE: Use per-client pairwise KEY table. - * KEY_INDEX: - * Key index (0~31) to the pairwise KEY table. - * 0~3 to shared KEY table 0 (BSS0). - * 4~7 to shared KEY table 1 (BSS1). - * 8~11 to shared KEY table 2 (BSS2). - * 12~15 to shared KEY table 3 (BSS3). - * BURST: Next frame belongs to same "burst" event. - */ -#define TXD_W0_OWNER_NIC FIELD32(0x00000001) -#define TXD_W0_VALID FIELD32(0x00000002) -#define TXD_W0_MORE_FRAG FIELD32(0x00000004) -#define TXD_W0_ACK FIELD32(0x00000008) -#define TXD_W0_TIMESTAMP FIELD32(0x00000010) -#define TXD_W0_OFDM FIELD32(0x00000020) -#define TXD_W0_IFS FIELD32(0x00000040) -#define TXD_W0_RETRY_MODE FIELD32(0x00000080) -#define TXD_W0_TKIP_MIC FIELD32(0x00000100) -#define TXD_W0_KEY_TABLE FIELD32(0x00000200) -#define TXD_W0_KEY_INDEX FIELD32(0x0000fc00) -#define TXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define TXD_W0_BURST FIELD32(0x10000000) -#define TXD_W0_CIPHER_ALG FIELD32(0xe0000000) - -/* - * Word1 - * HOST_Q_ID: EDCA/HCCA queue ID. - * HW_SEQUENCE: MAC overwrites the frame sequence number. - * BUFFER_COUNT: Number of buffers in this TXD. - */ -#define TXD_W1_HOST_Q_ID FIELD32(0x0000000f) -#define TXD_W1_AIFSN FIELD32(0x000000f0) -#define TXD_W1_CWMIN FIELD32(0x00000f00) -#define TXD_W1_CWMAX FIELD32(0x0000f000) -#define TXD_W1_IV_OFFSET FIELD32(0x003f0000) -#define TXD_W1_PIGGY_BACK FIELD32(0x01000000) -#define TXD_W1_HW_SEQUENCE FIELD32(0x10000000) -#define TXD_W1_BUFFER_COUNT FIELD32(0xe0000000) - -/* - * Word2: PLCP information - */ -#define TXD_W2_PLCP_SIGNAL FIELD32(0x000000ff) -#define TXD_W2_PLCP_SERVICE FIELD32(0x0000ff00) -#define TXD_W2_PLCP_LENGTH_LOW FIELD32(0x00ff0000) -#define TXD_W2_PLCP_LENGTH_HIGH FIELD32(0xff000000) - -/* - * Word3 - */ -#define TXD_W3_IV FIELD32(0xffffffff) - -/* - * Word4 - */ -#define TXD_W4_EIV FIELD32(0xffffffff) - -/* - * Word5 - * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field). - * TXD_W5_PID_SUBTYPE: Driver assigned packet ID index for txdone handler. - * TXD_W5_PID_TYPE: Driver assigned packet ID type for txdone handler. - * WAITING_DMA_DONE_INT: TXD been filled with data - * and waiting for TxDoneISR housekeeping. - */ -#define TXD_W5_FRAME_OFFSET FIELD32(0x000000ff) -#define TXD_W5_PID_SUBTYPE FIELD32(0x00001f00) -#define TXD_W5_PID_TYPE FIELD32(0x0000e000) -#define TXD_W5_TX_POWER FIELD32(0x00ff0000) -#define TXD_W5_WAITING_DMA_DONE_INT FIELD32(0x01000000) - -/* - * the above 24-byte is called TXINFO and will be DMAed to MAC block - * through TXFIFO. MAC block use this TXINFO to control the transmission - * behavior of this frame. - * The following fields are not used by MAC block. - * They are used by DMA block and HOST driver only. - * Once a frame has been DMA to ASIC, all the following fields are useless - * to ASIC. - */ - -/* - * Word6-10: Buffer physical address - */ -#define TXD_W6_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff) -#define TXD_W7_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff) -#define TXD_W8_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff) -#define TXD_W9_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff) -#define TXD_W10_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff) - -/* - * Word11-13: Buffer length - */ -#define TXD_W11_BUFFER_LENGTH0 FIELD32(0x00000fff) -#define TXD_W11_BUFFER_LENGTH1 FIELD32(0x0fff0000) -#define TXD_W12_BUFFER_LENGTH2 FIELD32(0x00000fff) -#define TXD_W12_BUFFER_LENGTH3 FIELD32(0x0fff0000) -#define TXD_W13_BUFFER_LENGTH4 FIELD32(0x00000fff) - -/* - * Word14 - */ -#define TXD_W14_SK_BUFFER FIELD32(0xffffffff) - -/* - * Word15 - */ -#define TXD_W15_NEXT_SK_BUFFER FIELD32(0xffffffff) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - * CIPHER_ERROR: 1:ICV error, 2:MIC error, 3:invalid key. - * KEY_INDEX: Decryption key actually used. - */ -#define RXD_W0_OWNER_NIC FIELD32(0x00000001) -#define RXD_W0_DROP FIELD32(0x00000002) -#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000004) -#define RXD_W0_MULTICAST FIELD32(0x00000008) -#define RXD_W0_BROADCAST FIELD32(0x00000010) -#define RXD_W0_MY_BSS FIELD32(0x00000020) -#define RXD_W0_CRC_ERROR FIELD32(0x00000040) -#define RXD_W0_OFDM FIELD32(0x00000080) -#define RXD_W0_CIPHER_ERROR FIELD32(0x00000300) -#define RXD_W0_KEY_INDEX FIELD32(0x0000fc00) -#define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define RXD_W0_CIPHER_ALG FIELD32(0xe0000000) - -/* - * Word1 - * SIGNAL: RX raw data rate reported by BBP. - */ -#define RXD_W1_SIGNAL FIELD32(0x000000ff) -#define RXD_W1_RSSI_AGC FIELD32(0x00001f00) -#define RXD_W1_RSSI_LNA FIELD32(0x00006000) -#define RXD_W1_FRAME_OFFSET FIELD32(0x7f000000) - -/* - * Word2 - * IV: Received IV of originally encrypted. - */ -#define RXD_W2_IV FIELD32(0xffffffff) - -/* - * Word3 - * EIV: Received EIV of originally encrypted. - */ -#define RXD_W3_EIV FIELD32(0xffffffff) - -/* - * Word4 - * ICV: Received ICV of originally encrypted. - * NOTE: This is a guess, the official definition is "reserved" - */ -#define RXD_W4_ICV FIELD32(0xffffffff) - -/* - * the above 20-byte is called RXINFO and will be DMAed to MAC RX block - * and passed to the HOST driver. - * The following fields are for DMA block and HOST usage only. - * Can't be touched by ASIC MAC block. - */ - -/* - * Word5 - */ -#define RXD_W5_BUFFER_PHYSICAL_ADDRESS FIELD32(0xffffffff) - -/* - * Word6-15: Reserved - */ -#define RXD_W6_RESERVED FIELD32(0xffffffff) -#define RXD_W7_RESERVED FIELD32(0xffffffff) -#define RXD_W8_RESERVED FIELD32(0xffffffff) -#define RXD_W9_RESERVED FIELD32(0xffffffff) -#define RXD_W10_RESERVED FIELD32(0xffffffff) -#define RXD_W11_RESERVED FIELD32(0xffffffff) -#define RXD_W12_RESERVED FIELD32(0xffffffff) -#define RXD_W13_RESERVED FIELD32(0xffffffff) -#define RXD_W14_RESERVED FIELD32(0xffffffff) -#define RXD_W15_RESERVED FIELD32(0xffffffff) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - */ -#define MIN_TXPOWER 0 -#define MAX_TXPOWER 31 -#define DEFAULT_TXPOWER 24 - -#define TXPOWER_FROM_DEV(__txpower) \ - (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) - -#endif /* RT61PCI_H */ diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c deleted file mode 100644 index 14e7bb210075..000000000000 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ /dev/null @@ -1,2463 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt73usb - Abstract: rt73usb device specific routines. - Supported chipsets: rt2571W & rt2671. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "rt2x00.h" -#include "rt2x00usb.h" -#include "rt73usb.h" - -/* - * Allow hardware encryption to be disabled. - */ -static int modparam_nohwcrypt = 0; -module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO); -MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption."); - -/* - * Register access. - * All access to the CSR registers will go through the methods - * rt2x00usb_register_read and rt2x00usb_register_write. - * BBP and RF register require indirect register access, - * and use the CSR registers BBPCSR and RFCSR to achieve this. - * These indirect registers work with busy bits, - * and we will try maximal REGISTER_BUSY_COUNT times to access - * the register while taking a REGISTER_BUSY_DELAY us delay - * between each attampt. When the busy bit is still set at that time, - * the access attempt is considered to have failed, - * and we will print an error. - * The _lock versions must be used if you already hold the csr_mutex - */ -#define WAIT_FOR_BBP(__dev, __reg) \ - rt2x00usb_regbusy_read((__dev), PHY_CSR3, PHY_CSR3_BUSY, (__reg)) -#define WAIT_FOR_RF(__dev, __reg) \ - rt2x00usb_regbusy_read((__dev), PHY_CSR4, PHY_CSR4_BUSY, (__reg)) - -static void rt73usb_bbp_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u8 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_VALUE, value); - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 0); - - rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt73usb_bbp_read(struct rt2x00_dev *rt2x00dev, - const unsigned int word, u8 *value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the BBP becomes available, afterwards we - * can safely write the read request into the register. - * After the data has been written, we wait until hardware - * returns the correct value, if at any time the register - * doesn't become available in time, reg will be 0xffffffff - * which means we return 0xff to the caller. - */ - if (WAIT_FOR_BBP(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, PHY_CSR3_REGNUM, word); - rt2x00_set_field32(®, PHY_CSR3_BUSY, 1); - rt2x00_set_field32(®, PHY_CSR3_READ_CONTROL, 1); - - rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR3, reg); - - WAIT_FOR_BBP(rt2x00dev, ®); - } - - *value = rt2x00_get_field32(reg, PHY_CSR3_VALUE); - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -static void rt73usb_rf_write(struct rt2x00_dev *rt2x00dev, - const unsigned int word, const u32 value) -{ - u32 reg; - - mutex_lock(&rt2x00dev->csr_mutex); - - /* - * Wait until the RF becomes available, afterwards we - * can safely write the new data into the register. - */ - if (WAIT_FOR_RF(rt2x00dev, ®)) { - reg = 0; - rt2x00_set_field32(®, PHY_CSR4_VALUE, value); - /* - * RF5225 and RF2527 contain 21 bits per RF register value, - * all others contain 20 bits. - */ - rt2x00_set_field32(®, PHY_CSR4_NUMBER_OF_BITS, - 20 + (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527))); - rt2x00_set_field32(®, PHY_CSR4_IF_SELECT, 0); - rt2x00_set_field32(®, PHY_CSR4_BUSY, 1); - - rt2x00usb_register_write_lock(rt2x00dev, PHY_CSR4, reg); - rt2x00_rf_write(rt2x00dev, word, value); - } - - mutex_unlock(&rt2x00dev->csr_mutex); -} - -#ifdef CONFIG_RT2X00_LIB_DEBUGFS -static const struct rt2x00debug rt73usb_rt2x00debug = { - .owner = THIS_MODULE, - .csr = { - .read = rt2x00usb_register_read, - .write = rt2x00usb_register_write, - .flags = RT2X00DEBUGFS_OFFSET, - .word_base = CSR_REG_BASE, - .word_size = sizeof(u32), - .word_count = CSR_REG_SIZE / sizeof(u32), - }, - .eeprom = { - .read = rt2x00_eeprom_read, - .write = rt2x00_eeprom_write, - .word_base = EEPROM_BASE, - .word_size = sizeof(u16), - .word_count = EEPROM_SIZE / sizeof(u16), - }, - .bbp = { - .read = rt73usb_bbp_read, - .write = rt73usb_bbp_write, - .word_base = BBP_BASE, - .word_size = sizeof(u8), - .word_count = BBP_SIZE / sizeof(u8), - }, - .rf = { - .read = rt2x00_rf_read, - .write = rt73usb_rf_write, - .word_base = RF_BASE, - .word_size = sizeof(u32), - .word_count = RF_SIZE / sizeof(u32), - }, -}; -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ - -static int rt73usb_rfkill_poll(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, MAC_CSR13, ®); - return rt2x00_get_field32(reg, MAC_CSR13_BIT7); -} - -#ifdef CONFIG_RT2X00_LIB_LEDS -static void rt73usb_brightness_set(struct led_classdev *led_cdev, - enum led_brightness brightness) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - unsigned int enabled = brightness != LED_OFF; - unsigned int a_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_5GHZ); - unsigned int bg_mode = - (enabled && led->rt2x00dev->curr_band == IEEE80211_BAND_2GHZ); - - if (led->type == LED_TYPE_RADIO) { - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MCU_LEDCS_RADIO_STATUS, enabled); - - rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, - 0, led->rt2x00dev->led_mcu_reg, - REGISTER_TIMEOUT); - } else if (led->type == LED_TYPE_ASSOC) { - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MCU_LEDCS_LINK_BG_STATUS, bg_mode); - rt2x00_set_field16(&led->rt2x00dev->led_mcu_reg, - MCU_LEDCS_LINK_A_STATUS, a_mode); - - rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, - 0, led->rt2x00dev->led_mcu_reg, - REGISTER_TIMEOUT); - } else if (led->type == LED_TYPE_QUALITY) { - /* - * The brightness is divided into 6 levels (0 - 5), - * this means we need to convert the brightness - * argument into the matching level within that range. - */ - rt2x00usb_vendor_request_sw(led->rt2x00dev, USB_LED_CONTROL, - brightness / (LED_FULL / 6), - led->rt2x00dev->led_mcu_reg, - REGISTER_TIMEOUT); - } -} - -static int rt73usb_blink_set(struct led_classdev *led_cdev, - unsigned long *delay_on, - unsigned long *delay_off) -{ - struct rt2x00_led *led = - container_of(led_cdev, struct rt2x00_led, led_dev); - u32 reg; - - rt2x00usb_register_read(led->rt2x00dev, MAC_CSR14, ®); - rt2x00_set_field32(®, MAC_CSR14_ON_PERIOD, *delay_on); - rt2x00_set_field32(®, MAC_CSR14_OFF_PERIOD, *delay_off); - rt2x00usb_register_write(led->rt2x00dev, MAC_CSR14, reg); - - return 0; -} - -static void rt73usb_init_led(struct rt2x00_dev *rt2x00dev, - struct rt2x00_led *led, - enum led_type type) -{ - led->rt2x00dev = rt2x00dev; - led->type = type; - led->led_dev.brightness_set = rt73usb_brightness_set; - led->led_dev.blink_set = rt73usb_blink_set; - led->flags = LED_INITIALIZED; -} -#endif /* CONFIG_RT2X00_LIB_LEDS */ - -/* - * Configuration handlers. - */ -static int rt73usb_config_shared_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_key_entry key_entry; - struct rt2x00_field32 field; - int timeout; - u32 mask; - u32 reg; - - if (crypto->cmd == SET_KEY) { - /* - * rt2x00lib can't determine the correct free - * key_idx for shared keys. We have 1 register - * with key valid bits. The goal is simple, read - * the register, if that is full we have no slots - * left. - * Note that each BSS is allowed to have up to 4 - * shared keys, so put a mask over the allowed - * entries. - */ - mask = (0xf << crypto->bssidx); - - rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®); - reg &= mask; - - if (reg && reg == mask) - return -ENOSPC; - - key->hw_key_idx += reg ? ffz(reg) : 0; - - /* - * Upload key to hardware - */ - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - reg = SHARED_KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, reg, - &key_entry, - sizeof(key_entry), - timeout); - - /* - * The cipher types are stored over 2 registers. - * bssidx 0 and 1 keys are stored in SEC_CSR1 and - * bssidx 1 and 2 keys are stored in SEC_CSR5. - * Using the correct defines correctly will cause overhead, - * so just calculate the correct offset. - */ - if (key->hw_key_idx < 8) { - field.bit_offset = (3 * key->hw_key_idx); - field.bit_mask = 0x7 << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, SEC_CSR1, ®); - rt2x00_set_field32(®, field, crypto->cipher); - rt2x00usb_register_write(rt2x00dev, SEC_CSR1, reg); - } else { - field.bit_offset = (3 * (key->hw_key_idx - 8)); - field.bit_mask = 0x7 << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, SEC_CSR5, ®); - rt2x00_set_field32(®, field, crypto->cipher); - rt2x00usb_register_write(rt2x00dev, SEC_CSR5, reg); - } - - /* - * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 - * to generate the IV/EIV data. - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } - - /* - * SEC_CSR0 contains only single-bit fields to indicate - * a particular key is valid. Because using the FIELD32() - * defines directly will cause a lot of overhead we use - * a calculation to determine the correct bit directly. - */ - mask = 1 << key->hw_key_idx; - - rt2x00usb_register_read(rt2x00dev, SEC_CSR0, ®); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00usb_register_write(rt2x00dev, SEC_CSR0, reg); - - return 0; -} - -static int rt73usb_config_pairwise_key(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_crypto *crypto, - struct ieee80211_key_conf *key) -{ - struct hw_pairwise_ta_entry addr_entry; - struct hw_key_entry key_entry; - int timeout; - u32 mask; - u32 reg; - - if (crypto->cmd == SET_KEY) { - /* - * rt2x00lib can't determine the correct free - * key_idx for pairwise keys. We have 2 registers - * with key valid bits. The goal is simple, read - * the first register, if that is full move to - * the next register. - * When both registers are full, we drop the key, - * otherwise we use the first invalid entry. - */ - rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®); - if (reg && reg == ~0) { - key->hw_key_idx = 32; - rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®); - if (reg && reg == ~0) - return -ENOSPC; - } - - key->hw_key_idx += reg ? ffz(reg) : 0; - - /* - * Upload key to hardware - */ - memcpy(key_entry.key, crypto->key, - sizeof(key_entry.key)); - memcpy(key_entry.tx_mic, crypto->tx_mic, - sizeof(key_entry.tx_mic)); - memcpy(key_entry.rx_mic, crypto->rx_mic, - sizeof(key_entry.rx_mic)); - - reg = PAIRWISE_KEY_ENTRY(key->hw_key_idx); - timeout = REGISTER_TIMEOUT32(sizeof(key_entry)); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, reg, - &key_entry, - sizeof(key_entry), - timeout); - - /* - * Send the address and cipher type to the hardware register. - * This data fits within the CSR cache size, so we can use - * rt2x00usb_register_multiwrite() directly. - */ - memset(&addr_entry, 0, sizeof(addr_entry)); - memcpy(&addr_entry, crypto->address, ETH_ALEN); - addr_entry.cipher = crypto->cipher; - - reg = PAIRWISE_TA_ENTRY(key->hw_key_idx); - rt2x00usb_register_multiwrite(rt2x00dev, reg, - &addr_entry, sizeof(addr_entry)); - - /* - * Enable pairwise lookup table for given BSS idx, - * without this received frames will not be decrypted - * by the hardware. - */ - rt2x00usb_register_read(rt2x00dev, SEC_CSR4, ®); - reg |= (1 << crypto->bssidx); - rt2x00usb_register_write(rt2x00dev, SEC_CSR4, reg); - - /* - * The driver does not support the IV/EIV generation - * in hardware. However it doesn't support the IV/EIV - * inside the ieee80211 frame either, but requires it - * to be provided seperately for the descriptor. - * rt2x00lib will cut the IV/EIV data out of all frames - * given to us by mac80211, but we must tell mac80211 - * to generate the IV/EIV data. - */ - key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - } - - /* - * SEC_CSR2 and SEC_CSR3 contain only single-bit fields to indicate - * a particular key is valid. Because using the FIELD32() - * defines directly will cause a lot of overhead we use - * a calculation to determine the correct bit directly. - */ - if (key->hw_key_idx < 32) { - mask = 1 << key->hw_key_idx; - - rt2x00usb_register_read(rt2x00dev, SEC_CSR2, ®); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00usb_register_write(rt2x00dev, SEC_CSR2, reg); - } else { - mask = 1 << (key->hw_key_idx - 32); - - rt2x00usb_register_read(rt2x00dev, SEC_CSR3, ®); - if (crypto->cmd == SET_KEY) - reg |= mask; - else if (crypto->cmd == DISABLE_KEY) - reg &= ~mask; - rt2x00usb_register_write(rt2x00dev, SEC_CSR3, reg); - } - - return 0; -} - -static void rt73usb_config_filter(struct rt2x00_dev *rt2x00dev, - const unsigned int filter_flags) -{ - u32 reg; - - /* - * Start configuration steps. - * Note that the version error will always be dropped - * and broadcast frames will always be accepted since - * there is no filter for it at this time. - */ - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CRC, - !(filter_flags & FIF_FCSFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_PHYSICAL, - !(filter_flags & FIF_PLCPFAIL)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_CONTROL, - !(filter_flags & (FIF_CONTROL | FIF_PSPOLL))); - rt2x00_set_field32(®, TXRX_CSR0_DROP_NOT_TO_ME, - !(filter_flags & FIF_PROMISC_IN_BSS)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_TO_DS, - !(filter_flags & FIF_PROMISC_IN_BSS) && - !rt2x00dev->intf_ap_count); - rt2x00_set_field32(®, TXRX_CSR0_DROP_VERSION_ERROR, 1); - rt2x00_set_field32(®, TXRX_CSR0_DROP_MULTICAST, - !(filter_flags & FIF_ALLMULTI)); - rt2x00_set_field32(®, TXRX_CSR0_DROP_BROADCAST, 0); - rt2x00_set_field32(®, TXRX_CSR0_DROP_ACK_CTS, - !(filter_flags & FIF_CONTROL)); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} - -static void rt73usb_config_intf(struct rt2x00_dev *rt2x00dev, - struct rt2x00_intf *intf, - struct rt2x00intf_conf *conf, - const unsigned int flags) -{ - unsigned int beacon_base; - u32 reg; - - if (flags & CONFIG_UPDATE_TYPE) { - /* - * Clear current synchronisation setup. - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx); - rt2x00usb_register_write(rt2x00dev, beacon_base, 0); - - /* - * Enable synchronisation. - */ - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, conf->sync); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - } - - if (flags & CONFIG_UPDATE_MAC) { - reg = le32_to_cpu(conf->mac[1]); - rt2x00_set_field32(®, MAC_CSR3_UNICAST_TO_ME_MASK, 0xff); - conf->mac[1] = cpu_to_le32(reg); - - rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR2, - conf->mac, sizeof(conf->mac)); - } - - if (flags & CONFIG_UPDATE_BSSID) { - reg = le32_to_cpu(conf->bssid[1]); - rt2x00_set_field32(®, MAC_CSR5_BSS_ID_MASK, 3); - conf->bssid[1] = cpu_to_le32(reg); - - rt2x00usb_register_multiwrite(rt2x00dev, MAC_CSR4, - conf->bssid, sizeof(conf->bssid)); - } -} - -static void rt73usb_config_erp(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_erp *erp) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_RX_ACK_TIMEOUT, 0x32); - rt2x00_set_field32(®, TXRX_CSR0_TSF_OFFSET, IEEE80211_HEADER); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR4_AUTORESPOND_PREAMBLE, - !!erp->short_preamble); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); - - rt2x00usb_register_write(rt2x00dev, TXRX_CSR5, erp->basic_rates); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, - erp->beacon_int * 16); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_SLOT_TIME, erp->slot_time); - rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR8, ®); - rt2x00_set_field32(®, MAC_CSR8_SIFS, erp->sifs); - rt2x00_set_field32(®, MAC_CSR8_SIFS_AFTER_RX_OFDM, 3); - rt2x00_set_field32(®, MAC_CSR8_EIFS, erp->eifs); - rt2x00usb_register_write(rt2x00dev, MAC_CSR8, reg); -} - -static void rt73usb_config_antenna_5x(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r3; - u8 r4; - u8 r77; - u8 temp; - - rt73usb_bbp_read(rt2x00dev, 3, &r3); - rt73usb_bbp_read(rt2x00dev, 4, &r4); - rt73usb_bbp_read(rt2x00dev, 77, &r77); - - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); - temp = !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags) - && (rt2x00dev->curr_band != IEEE80211_BAND_5GHZ); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, temp); - break; - case ANTENNA_A: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - else - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, 0); - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - else - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - break; - } - - rt73usb_bbp_write(rt2x00dev, 77, r77); - rt73usb_bbp_write(rt2x00dev, 3, r3); - rt73usb_bbp_write(rt2x00dev, 4, r4); -} - -static void rt73usb_config_antenna_2x(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - u8 r3; - u8 r4; - u8 r77; - - rt73usb_bbp_read(rt2x00dev, 3, &r3); - rt73usb_bbp_read(rt2x00dev, 4, &r4); - rt73usb_bbp_read(rt2x00dev, 77, &r77); - - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, 0); - rt2x00_set_field8(&r4, BBP_R4_RX_FRAME_END, - !test_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags)); - - /* - * Configure the RX antenna. - */ - switch (ant->rx) { - case ANTENNA_HW_DIVERSITY: - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 2); - break; - case ANTENNA_A: - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 3); - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - break; - case ANTENNA_B: - default: - rt2x00_set_field8(&r77, BBP_R77_RX_ANTENNA, 0); - rt2x00_set_field8(&r4, BBP_R4_RX_ANTENNA_CONTROL, 1); - break; - } - - rt73usb_bbp_write(rt2x00dev, 77, r77); - rt73usb_bbp_write(rt2x00dev, 3, r3); - rt73usb_bbp_write(rt2x00dev, 4, r4); -} - -struct antenna_sel { - u8 word; - /* - * value[0] -> non-LNA - * value[1] -> LNA - */ - u8 value[2]; -}; - -static const struct antenna_sel antenna_sel_a[] = { - { 96, { 0x58, 0x78 } }, - { 104, { 0x38, 0x48 } }, - { 75, { 0xfe, 0x80 } }, - { 86, { 0xfe, 0x80 } }, - { 88, { 0xfe, 0x80 } }, - { 35, { 0x60, 0x60 } }, - { 97, { 0x58, 0x58 } }, - { 98, { 0x58, 0x58 } }, -}; - -static const struct antenna_sel antenna_sel_bg[] = { - { 96, { 0x48, 0x68 } }, - { 104, { 0x2c, 0x3c } }, - { 75, { 0xfe, 0x80 } }, - { 86, { 0xfe, 0x80 } }, - { 88, { 0xfe, 0x80 } }, - { 35, { 0x50, 0x50 } }, - { 97, { 0x48, 0x48 } }, - { 98, { 0x48, 0x48 } }, -}; - -static void rt73usb_config_ant(struct rt2x00_dev *rt2x00dev, - struct antenna_setup *ant) -{ - const struct antenna_sel *sel; - unsigned int lna; - unsigned int i; - u32 reg; - - /* - * We should never come here because rt2x00lib is supposed - * to catch this and send us the correct antenna explicitely. - */ - BUG_ON(ant->rx == ANTENNA_SW_DIVERSITY || - ant->tx == ANTENNA_SW_DIVERSITY); - - if (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ) { - sel = antenna_sel_a; - lna = test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - } else { - sel = antenna_sel_bg; - lna = test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); - } - - for (i = 0; i < ARRAY_SIZE(antenna_sel_a); i++) - rt73usb_bbp_write(rt2x00dev, sel[i].word, sel[i].value[lna]); - - rt2x00usb_register_read(rt2x00dev, PHY_CSR0, ®); - - rt2x00_set_field32(®, PHY_CSR0_PA_PE_BG, - (rt2x00dev->curr_band == IEEE80211_BAND_2GHZ)); - rt2x00_set_field32(®, PHY_CSR0_PA_PE_A, - (rt2x00dev->curr_band == IEEE80211_BAND_5GHZ)); - - rt2x00usb_register_write(rt2x00dev, PHY_CSR0, reg); - - if (rt2x00_rf(&rt2x00dev->chip, RF5226) || - rt2x00_rf(&rt2x00dev->chip, RF5225)) - rt73usb_config_antenna_5x(rt2x00dev, ant); - else if (rt2x00_rf(&rt2x00dev->chip, RF2528) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) - rt73usb_config_antenna_2x(rt2x00dev, ant); -} - -static void rt73usb_config_lna_gain(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u16 eeprom; - short lna_gain = 0; - - if (libconf->conf->channel->band == IEEE80211_BAND_2GHZ) { - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) - lna_gain += 14; - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &eeprom); - lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_BG_1); - } else { - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &eeprom); - lna_gain -= rt2x00_get_field16(eeprom, EEPROM_RSSI_OFFSET_A_1); - } - - rt2x00dev->lna_gain = lna_gain; -} - -static void rt73usb_config_channel(struct rt2x00_dev *rt2x00dev, - struct rf_channel *rf, const int txpower) -{ - u8 r3; - u8 r94; - u8 smart; - - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER, TXPOWER_TO_DEV(txpower)); - rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset); - - smart = !(rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)); - - rt73usb_bbp_read(rt2x00dev, 3, &r3); - rt2x00_set_field8(&r3, BBP_R3_SMART_MODE, smart); - rt73usb_bbp_write(rt2x00dev, 3, r3); - - r94 = 6; - if (txpower > MAX_TXPOWER && txpower <= (MAX_TXPOWER + r94)) - r94 += txpower - MAX_TXPOWER; - else if (txpower < MIN_TXPOWER && txpower >= (MIN_TXPOWER - r94)) - r94 += txpower; - rt73usb_bbp_write(rt2x00dev, 94, r94); - - rt73usb_rf_write(rt2x00dev, 1, rf->rf1); - rt73usb_rf_write(rt2x00dev, 2, rf->rf2); - rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt73usb_rf_write(rt2x00dev, 4, rf->rf4); - - rt73usb_rf_write(rt2x00dev, 1, rf->rf1); - rt73usb_rf_write(rt2x00dev, 2, rf->rf2); - rt73usb_rf_write(rt2x00dev, 3, rf->rf3 | 0x00000004); - rt73usb_rf_write(rt2x00dev, 4, rf->rf4); - - rt73usb_rf_write(rt2x00dev, 1, rf->rf1); - rt73usb_rf_write(rt2x00dev, 2, rf->rf2); - rt73usb_rf_write(rt2x00dev, 3, rf->rf3 & ~0x00000004); - rt73usb_rf_write(rt2x00dev, 4, rf->rf4); - - udelay(10); -} - -static void rt73usb_config_txpower(struct rt2x00_dev *rt2x00dev, - const int txpower) -{ - struct rf_channel rf; - - rt2x00_rf_read(rt2x00dev, 1, &rf.rf1); - rt2x00_rf_read(rt2x00dev, 2, &rf.rf2); - rt2x00_rf_read(rt2x00dev, 3, &rf.rf3); - rt2x00_rf_read(rt2x00dev, 4, &rf.rf4); - - rt73usb_config_channel(rt2x00dev, &rf, txpower); -} - -static void rt73usb_config_retry_limit(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR4, ®); - rt2x00_set_field32(®, TXRX_CSR4_LONG_RETRY_LIMIT, - libconf->conf->long_frame_max_tx_count); - rt2x00_set_field32(®, TXRX_CSR4_SHORT_RETRY_LIMIT, - libconf->conf->short_frame_max_tx_count); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR4, reg); -} - -static void rt73usb_config_ps(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf) -{ - enum dev_state state = - (libconf->conf->flags & IEEE80211_CONF_PS) ? - STATE_SLEEP : STATE_AWAKE; - u32 reg; - - if (state == STATE_SLEEP) { - rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); - rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, - rt2x00dev->beacon_int - 10); - rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, - libconf->conf->listen_interval - 1); - rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 5); - - /* We must first disable autowake before it can be enabled */ - rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); - rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); - - rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 1); - rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); - - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, - USB_MODE_SLEEP, REGISTER_TIMEOUT); - } else { - rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, 0, - USB_MODE_WAKEUP, REGISTER_TIMEOUT); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR11, ®); - rt2x00_set_field32(®, MAC_CSR11_DELAY_AFTER_TBCN, 0); - rt2x00_set_field32(®, MAC_CSR11_TBCN_BEFORE_WAKEUP, 0); - rt2x00_set_field32(®, MAC_CSR11_AUTOWAKE, 0); - rt2x00_set_field32(®, MAC_CSR11_WAKEUP_LATENCY, 0); - rt2x00usb_register_write(rt2x00dev, MAC_CSR11, reg); - } -} - -static void rt73usb_config(struct rt2x00_dev *rt2x00dev, - struct rt2x00lib_conf *libconf, - const unsigned int flags) -{ - /* Always recalculate LNA gain before changing configuration */ - rt73usb_config_lna_gain(rt2x00dev, libconf); - - if (flags & IEEE80211_CONF_CHANGE_CHANNEL) - rt73usb_config_channel(rt2x00dev, &libconf->rf, - libconf->conf->power_level); - if ((flags & IEEE80211_CONF_CHANGE_POWER) && - !(flags & IEEE80211_CONF_CHANGE_CHANNEL)) - rt73usb_config_txpower(rt2x00dev, libconf->conf->power_level); - if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS) - rt73usb_config_retry_limit(rt2x00dev, libconf); - if (flags & IEEE80211_CONF_CHANGE_PS) - rt73usb_config_ps(rt2x00dev, libconf); -} - -/* - * Link tuning - */ -static void rt73usb_link_stats(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - u32 reg; - - /* - * Update FCS error count from register. - */ - rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®); - qual->rx_failed = rt2x00_get_field32(reg, STA_CSR0_FCS_ERROR); - - /* - * Update False CCA count from register. - */ - rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®); - qual->false_cca = rt2x00_get_field32(reg, STA_CSR1_FALSE_CCA_ERROR); -} - -static inline void rt73usb_set_vgc(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, u8 vgc_level) -{ - if (qual->vgc_level != vgc_level) { - rt73usb_bbp_write(rt2x00dev, 17, vgc_level); - qual->vgc_level = vgc_level; - qual->vgc_level_reg = vgc_level; - } -} - -static void rt73usb_reset_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual) -{ - rt73usb_set_vgc(rt2x00dev, qual, 0x20); -} - -static void rt73usb_link_tuner(struct rt2x00_dev *rt2x00dev, - struct link_qual *qual, const u32 count) -{ - u8 up_bound; - u8 low_bound; - - /* - * Determine r17 bounds. - */ - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { - low_bound = 0x28; - up_bound = 0x48; - - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { - low_bound += 0x10; - up_bound += 0x10; - } - } else { - if (qual->rssi > -82) { - low_bound = 0x1c; - up_bound = 0x40; - } else if (qual->rssi > -84) { - low_bound = 0x1c; - up_bound = 0x20; - } else { - low_bound = 0x1c; - up_bound = 0x1c; - } - - if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) { - low_bound += 0x14; - up_bound += 0x10; - } - } - - /* - * If we are not associated, we should go straight to the - * dynamic CCA tuning. - */ - if (!rt2x00dev->intf_associated) - goto dynamic_cca_tune; - - /* - * Special big-R17 for very short distance - */ - if (qual->rssi > -35) { - rt73usb_set_vgc(rt2x00dev, qual, 0x60); - return; - } - - /* - * Special big-R17 for short distance - */ - if (qual->rssi >= -58) { - rt73usb_set_vgc(rt2x00dev, qual, up_bound); - return; - } - - /* - * Special big-R17 for middle-short distance - */ - if (qual->rssi >= -66) { - rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x10); - return; - } - - /* - * Special mid-R17 for middle distance - */ - if (qual->rssi >= -74) { - rt73usb_set_vgc(rt2x00dev, qual, low_bound + 0x08); - return; - } - - /* - * Special case: Change up_bound based on the rssi. - * Lower up_bound when rssi is weaker then -74 dBm. - */ - up_bound -= 2 * (-74 - qual->rssi); - if (low_bound > up_bound) - up_bound = low_bound; - - if (qual->vgc_level > up_bound) { - rt73usb_set_vgc(rt2x00dev, qual, up_bound); - return; - } - -dynamic_cca_tune: - - /* - * r17 does not yet exceed upper limit, continue and base - * the r17 tuning on the false CCA count. - */ - if ((qual->false_cca > 512) && (qual->vgc_level < up_bound)) - rt73usb_set_vgc(rt2x00dev, qual, - min_t(u8, qual->vgc_level + 4, up_bound)); - else if ((qual->false_cca < 100) && (qual->vgc_level > low_bound)) - rt73usb_set_vgc(rt2x00dev, qual, - max_t(u8, qual->vgc_level - 4, low_bound)); -} - -/* - * Firmware functions - */ -static char *rt73usb_get_firmware_name(struct rt2x00_dev *rt2x00dev) -{ - return FIRMWARE_RT2571; -} - -static int rt73usb_check_firmware(struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len) -{ - u16 fw_crc; - u16 crc; - - /* - * Only support 2kb firmware files. - */ - if (len != 2048) - return FW_BAD_LENGTH; - - /* - * The last 2 bytes in the firmware array are the crc checksum itself, - * this means that we should never pass those 2 bytes to the crc - * algorithm. - */ - fw_crc = (data[len - 2] << 8 | data[len - 1]); - - /* - * Use the crc itu-t algorithm. - */ - crc = crc_itu_t(0, data, len - 2); - crc = crc_itu_t_byte(crc, 0); - crc = crc_itu_t_byte(crc, 0); - - return (fw_crc == crc) ? FW_OK : FW_BAD_CRC; -} - -static int rt73usb_load_firmware(struct rt2x00_dev *rt2x00dev, - const u8 *data, const size_t len) -{ - unsigned int i; - int status; - u32 reg; - - /* - * Wait for stable hardware. - */ - for (i = 0; i < 100; i++) { - rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); - if (reg) - break; - msleep(1); - } - - if (!reg) { - ERROR(rt2x00dev, "Unstable hardware.\n"); - return -EBUSY; - } - - /* - * Write firmware to device. - */ - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, - FIRMWARE_IMAGE_BASE, - data, len, - REGISTER_TIMEOUT32(len)); - - /* - * Send firmware request to device to load firmware, - * we need to specify a long timeout time. - */ - status = rt2x00usb_vendor_request_sw(rt2x00dev, USB_DEVICE_MODE, - 0, USB_MODE_FIRMWARE, - REGISTER_TIMEOUT_FIRMWARE); - if (status < 0) { - ERROR(rt2x00dev, "Failed to write Firmware to device.\n"); - return status; - } - - return 0; -} - -/* - * Initialization functions. - */ -static int rt73usb_init_registers(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_AUTO_TX_SEQ, 1); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, 0); - rt2x00_set_field32(®, TXRX_CSR0_TX_WITHOUT_WAITING, 0); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR1, ®); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0, 47); /* CCK Signal */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1, 30); /* Rssi */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2, 42); /* OFDM Rate */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID2_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3, 30); /* Rssi */ - rt2x00_set_field32(®, TXRX_CSR1_BBP_ID3_VALID, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR1, reg); - - /* - * CCK TXD BBP registers - */ - rt2x00usb_register_read(rt2x00dev, TXRX_CSR2, ®); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0, 13); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1, 12); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2, 11); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID2_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3, 10); - rt2x00_set_field32(®, TXRX_CSR2_BBP_ID3_VALID, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR2, reg); - - /* - * OFDM TXD BBP registers - */ - rt2x00usb_register_read(rt2x00dev, TXRX_CSR3, ®); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0, 7); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID0_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1, 6); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID1_VALID, 1); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2, 5); - rt2x00_set_field32(®, TXRX_CSR3_BBP_ID2_VALID, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR3, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR7, ®); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_6MBS, 59); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_9MBS, 53); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_12MBS, 49); - rt2x00_set_field32(®, TXRX_CSR7_ACK_CTS_18MBS, 46); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR7, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR8, ®); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_24MBS, 44); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_36MBS, 42); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_48MBS, 42); - rt2x00_set_field32(®, TXRX_CSR8_ACK_CTS_54MBS, 42); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR8, reg); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_INTERVAL, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 0); - rt2x00_set_field32(®, TXRX_CSR9_TSF_SYNC, 0); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 0); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00_set_field32(®, TXRX_CSR9_TIMESTAMP_COMPENSATE, 0); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - - rt2x00usb_register_write(rt2x00dev, TXRX_CSR15, 0x0000000f); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR6, ®); - rt2x00_set_field32(®, MAC_CSR6_MAX_FRAME_UNIT, 0xfff); - rt2x00usb_register_write(rt2x00dev, MAC_CSR6, reg); - - rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00000718); - - if (rt2x00dev->ops->lib->set_device_state(rt2x00dev, STATE_AWAKE)) - return -EBUSY; - - rt2x00usb_register_write(rt2x00dev, MAC_CSR13, 0x00007f00); - - /* - * Invalidate all Shared Keys (SEC_CSR0), - * and clear the Shared key Cipher algorithms (SEC_CSR1 & SEC_CSR5) - */ - rt2x00usb_register_write(rt2x00dev, SEC_CSR0, 0x00000000); - rt2x00usb_register_write(rt2x00dev, SEC_CSR1, 0x00000000); - rt2x00usb_register_write(rt2x00dev, SEC_CSR5, 0x00000000); - - reg = 0x000023b0; - if (rt2x00_rf(&rt2x00dev->chip, RF5225) || - rt2x00_rf(&rt2x00dev->chip, RF2527)) - rt2x00_set_field32(®, PHY_CSR1_RF_RPI, 1); - rt2x00usb_register_write(rt2x00dev, PHY_CSR1, reg); - - rt2x00usb_register_write(rt2x00dev, PHY_CSR5, 0x00040a06); - rt2x00usb_register_write(rt2x00dev, PHY_CSR6, 0x00080606); - rt2x00usb_register_write(rt2x00dev, PHY_CSR7, 0x00000408); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR9, ®); - rt2x00_set_field32(®, MAC_CSR9_CW_SELECT, 0); - rt2x00usb_register_write(rt2x00dev, MAC_CSR9, reg); - - /* - * Clear all beacons - * For the Beacon base registers we only need to clear - * the first byte since that byte contains the VALID and OWNER - * bits which (when set to 0) will invalidate the entire beacon. - */ - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE0, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE1, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE2, 0); - rt2x00usb_register_write(rt2x00dev, HW_BEACON_BASE3, 0); - - /* - * We must clear the error counters. - * These registers are cleared on read, - * so we may pass a useless variable to store the value. - */ - rt2x00usb_register_read(rt2x00dev, STA_CSR0, ®); - rt2x00usb_register_read(rt2x00dev, STA_CSR1, ®); - rt2x00usb_register_read(rt2x00dev, STA_CSR2, ®); - - /* - * Reset MAC and BBP registers. - */ - rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 1); - rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 1); - rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_SOFT_RESET, 0); - rt2x00_set_field32(®, MAC_CSR1_BBP_RESET, 0); - rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR1, ®); - rt2x00_set_field32(®, MAC_CSR1_HOST_READY, 1); - rt2x00usb_register_write(rt2x00dev, MAC_CSR1, reg); - - return 0; -} - -static int rt73usb_wait_bbp_ready(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u8 value; - - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt73usb_bbp_read(rt2x00dev, 0, &value); - if ((value != 0xff) && (value != 0x00)) - return 0; - udelay(REGISTER_BUSY_DELAY); - } - - ERROR(rt2x00dev, "BBP register access failed, aborting.\n"); - return -EACCES; -} - -static int rt73usb_init_bbp(struct rt2x00_dev *rt2x00dev) -{ - unsigned int i; - u16 eeprom; - u8 reg_id; - u8 value; - - if (unlikely(rt73usb_wait_bbp_ready(rt2x00dev))) - return -EACCES; - - rt73usb_bbp_write(rt2x00dev, 3, 0x80); - rt73usb_bbp_write(rt2x00dev, 15, 0x30); - rt73usb_bbp_write(rt2x00dev, 21, 0xc8); - rt73usb_bbp_write(rt2x00dev, 22, 0x38); - rt73usb_bbp_write(rt2x00dev, 23, 0x06); - rt73usb_bbp_write(rt2x00dev, 24, 0xfe); - rt73usb_bbp_write(rt2x00dev, 25, 0x0a); - rt73usb_bbp_write(rt2x00dev, 26, 0x0d); - rt73usb_bbp_write(rt2x00dev, 32, 0x0b); - rt73usb_bbp_write(rt2x00dev, 34, 0x12); - rt73usb_bbp_write(rt2x00dev, 37, 0x07); - rt73usb_bbp_write(rt2x00dev, 39, 0xf8); - rt73usb_bbp_write(rt2x00dev, 41, 0x60); - rt73usb_bbp_write(rt2x00dev, 53, 0x10); - rt73usb_bbp_write(rt2x00dev, 54, 0x18); - rt73usb_bbp_write(rt2x00dev, 60, 0x10); - rt73usb_bbp_write(rt2x00dev, 61, 0x04); - rt73usb_bbp_write(rt2x00dev, 62, 0x04); - rt73usb_bbp_write(rt2x00dev, 75, 0xfe); - rt73usb_bbp_write(rt2x00dev, 86, 0xfe); - rt73usb_bbp_write(rt2x00dev, 88, 0xfe); - rt73usb_bbp_write(rt2x00dev, 90, 0x0f); - rt73usb_bbp_write(rt2x00dev, 99, 0x00); - rt73usb_bbp_write(rt2x00dev, 102, 0x16); - rt73usb_bbp_write(rt2x00dev, 107, 0x04); - - for (i = 0; i < EEPROM_BBP_SIZE; i++) { - rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom); - - if (eeprom != 0xffff && eeprom != 0x0000) { - reg_id = rt2x00_get_field16(eeprom, EEPROM_BBP_REG_ID); - value = rt2x00_get_field16(eeprom, EEPROM_BBP_VALUE); - rt73usb_bbp_write(rt2x00dev, reg_id, value); - } - } - - return 0; -} - -/* - * Device state switch handlers. - */ -static void rt73usb_toggle_rx(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR0, ®); - rt2x00_set_field32(®, TXRX_CSR0_DISABLE_RX, - (state == STATE_RADIO_RX_OFF) || - (state == STATE_RADIO_RX_OFF_LINK)); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR0, reg); -} - -static int rt73usb_enable_radio(struct rt2x00_dev *rt2x00dev) -{ - /* - * Initialize all registers. - */ - if (unlikely(rt73usb_init_registers(rt2x00dev) || - rt73usb_init_bbp(rt2x00dev))) - return -EIO; - - return 0; -} - -static void rt73usb_disable_radio(struct rt2x00_dev *rt2x00dev) -{ - rt2x00usb_register_write(rt2x00dev, MAC_CSR10, 0x00001818); - - /* - * Disable synchronisation. - */ - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, 0); - - rt2x00usb_disable_radio(rt2x00dev); -} - -static int rt73usb_set_state(struct rt2x00_dev *rt2x00dev, enum dev_state state) -{ - u32 reg; - unsigned int i; - char put_to_sleep; - - put_to_sleep = (state != STATE_AWAKE); - - rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); - rt2x00_set_field32(®, MAC_CSR12_FORCE_WAKEUP, !put_to_sleep); - rt2x00_set_field32(®, MAC_CSR12_PUT_TO_SLEEP, put_to_sleep); - rt2x00usb_register_write(rt2x00dev, MAC_CSR12, reg); - - /* - * Device is not guaranteed to be in the requested state yet. - * We must wait until the register indicates that the - * device has entered the correct state. - */ - for (i = 0; i < REGISTER_BUSY_COUNT; i++) { - rt2x00usb_register_read(rt2x00dev, MAC_CSR12, ®); - state = rt2x00_get_field32(reg, MAC_CSR12_BBP_CURRENT_STATE); - if (state == !put_to_sleep) - return 0; - msleep(10); - } - - return -EBUSY; -} - -static int rt73usb_set_device_state(struct rt2x00_dev *rt2x00dev, - enum dev_state state) -{ - int retval = 0; - - switch (state) { - case STATE_RADIO_ON: - retval = rt73usb_enable_radio(rt2x00dev); - break; - case STATE_RADIO_OFF: - rt73usb_disable_radio(rt2x00dev); - break; - case STATE_RADIO_RX_ON: - case STATE_RADIO_RX_ON_LINK: - case STATE_RADIO_RX_OFF: - case STATE_RADIO_RX_OFF_LINK: - rt73usb_toggle_rx(rt2x00dev, state); - break; - case STATE_RADIO_IRQ_ON: - case STATE_RADIO_IRQ_OFF: - /* No support, but no error either */ - break; - case STATE_DEEP_SLEEP: - case STATE_SLEEP: - case STATE_STANDBY: - case STATE_AWAKE: - retval = rt73usb_set_state(rt2x00dev, state); - break; - default: - retval = -ENOTSUPP; - break; - } - - if (unlikely(retval)) - ERROR(rt2x00dev, "Device failed to enter state %d (%d).\n", - state, retval); - - return retval; -} - -/* - * TX descriptor initialization - */ -static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev, - struct sk_buff *skb, - struct txentry_desc *txdesc) -{ - struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); - __le32 *txd = skbdesc->desc; - u32 word; - - /* - * Start writing the descriptor words. - */ - rt2x00_desc_read(txd, 1, &word); - rt2x00_set_field32(&word, TXD_W1_HOST_Q_ID, txdesc->queue); - rt2x00_set_field32(&word, TXD_W1_AIFSN, txdesc->aifs); - rt2x00_set_field32(&word, TXD_W1_CWMIN, txdesc->cw_min); - rt2x00_set_field32(&word, TXD_W1_CWMAX, txdesc->cw_max); - rt2x00_set_field32(&word, TXD_W1_IV_OFFSET, txdesc->iv_offset); - rt2x00_set_field32(&word, TXD_W1_HW_SEQUENCE, - test_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags)); - rt2x00_desc_write(txd, 1, word); - - rt2x00_desc_read(txd, 2, &word); - rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal); - rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low); - rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high); - rt2x00_desc_write(txd, 2, word); - - if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) { - _rt2x00_desc_write(txd, 3, skbdesc->iv[0]); - _rt2x00_desc_write(txd, 4, skbdesc->iv[1]); - } - - rt2x00_desc_read(txd, 5, &word); - rt2x00_set_field32(&word, TXD_W5_TX_POWER, - TXPOWER_TO_DEV(rt2x00dev->tx_power)); - rt2x00_set_field32(&word, TXD_W5_WAITING_DMA_DONE_INT, 1); - rt2x00_desc_write(txd, 5, word); - - rt2x00_desc_read(txd, 0, &word); - rt2x00_set_field32(&word, TXD_W0_BURST, - test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_VALID, 1); - rt2x00_set_field32(&word, TXD_W0_MORE_FRAG, - test_bit(ENTRY_TXD_MORE_FRAG, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_ACK, - test_bit(ENTRY_TXD_ACK, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TIMESTAMP, - test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_OFDM, - (txdesc->rate_mode == RATE_MODE_OFDM)); - rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs); - rt2x00_set_field32(&word, TXD_W0_RETRY_MODE, - test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_TKIP_MIC, - test_bit(ENTRY_TXD_ENCRYPT_MMIC, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_KEY_TABLE, - test_bit(ENTRY_TXD_ENCRYPT_PAIRWISE, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_KEY_INDEX, txdesc->key_idx); - rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, skb->len); - rt2x00_set_field32(&word, TXD_W0_BURST2, - test_bit(ENTRY_TXD_BURST, &txdesc->flags)); - rt2x00_set_field32(&word, TXD_W0_CIPHER_ALG, txdesc->cipher); - rt2x00_desc_write(txd, 0, word); -} - -/* - * TX data initialization - */ -static void rt73usb_write_beacon(struct queue_entry *entry) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - unsigned int beacon_base; - u32 reg; - - /* - * Add the descriptor in front of the skb. - */ - skb_push(entry->skb, entry->queue->desc_size); - memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len); - skbdesc->desc = entry->skb->data; - - /* - * Disable beaconing while we are reloading the beacon data, - * otherwise we might be sending out invalid data. - */ - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 0); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - - /* - * Write entire beacon with descriptor to register. - */ - beacon_base = HW_BEACON_OFFSET(entry->entry_idx); - rt2x00usb_vendor_request_large_buff(rt2x00dev, USB_MULTI_WRITE, - USB_VENDOR_REQUEST_OUT, beacon_base, - entry->skb->data, entry->skb->len, - REGISTER_TIMEOUT32(entry->skb->len)); - - /* - * Clean up the beacon skb. - */ - dev_kfree_skb(entry->skb); - entry->skb = NULL; -} - -static int rt73usb_get_tx_data_len(struct queue_entry *entry) -{ - int length; - - /* - * The length _must_ be a multiple of 4, - * but it must _not_ be a multiple of the USB packet size. - */ - length = roundup(entry->skb->len, 4); - length += (4 * !(length % entry->queue->usb_maxpacket)); - - return length; -} - -static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev, - const enum data_queue_qid queue) -{ - u32 reg; - - if (queue != QID_BEACON) { - rt2x00usb_kick_tx_queue(rt2x00dev, queue); - return; - } - - /* - * For Wi-Fi faily generated beacons between participating stations. - * Set TBTT phase adaptive adjustment step to 8us (default 16us) - */ - rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008); - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, ®); - if (!rt2x00_get_field32(reg, TXRX_CSR9_BEACON_GEN)) { - rt2x00_set_field32(®, TXRX_CSR9_TSF_TICKING, 1); - rt2x00_set_field32(®, TXRX_CSR9_TBTT_ENABLE, 1); - rt2x00_set_field32(®, TXRX_CSR9_BEACON_GEN, 1); - rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg); - } -} - -/* - * RX control handlers - */ -static int rt73usb_agc_to_rssi(struct rt2x00_dev *rt2x00dev, int rxd_w1) -{ - u8 offset = rt2x00dev->lna_gain; - u8 lna; - - lna = rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_LNA); - switch (lna) { - case 3: - offset += 90; - break; - case 2: - offset += 74; - break; - case 1: - offset += 64; - break; - default: - return 0; - } - - if (rt2x00dev->rx_status.band == IEEE80211_BAND_5GHZ) { - if (test_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags)) { - if (lna == 3 || lna == 2) - offset += 10; - } else { - if (lna == 3) - offset += 6; - else if (lna == 2) - offset += 8; - } - } - - return rt2x00_get_field32(rxd_w1, RXD_W1_RSSI_AGC) * 2 - offset; -} - -static void rt73usb_fill_rxdone(struct queue_entry *entry, - struct rxdone_entry_desc *rxdesc) -{ - struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; - struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb); - __le32 *rxd = (__le32 *)entry->skb->data; - u32 word0; - u32 word1; - - /* - * Copy descriptor to the skbdesc->desc buffer, making it safe from moving of - * frame data in rt2x00usb. - */ - memcpy(skbdesc->desc, rxd, skbdesc->desc_len); - rxd = (__le32 *)skbdesc->desc; - - /* - * It is now safe to read the descriptor on all architectures. - */ - rt2x00_desc_read(rxd, 0, &word0); - rt2x00_desc_read(rxd, 1, &word1); - - if (rt2x00_get_field32(word0, RXD_W0_CRC_ERROR)) - rxdesc->flags |= RX_FLAG_FAILED_FCS_CRC; - - if (test_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags)) { - rxdesc->cipher = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ALG); - rxdesc->cipher_status = - rt2x00_get_field32(word0, RXD_W0_CIPHER_ERROR); - } - - if (rxdesc->cipher != CIPHER_NONE) { - _rt2x00_desc_read(rxd, 2, &rxdesc->iv[0]); - _rt2x00_desc_read(rxd, 3, &rxdesc->iv[1]); - rxdesc->dev_flags |= RXDONE_CRYPTO_IV; - - _rt2x00_desc_read(rxd, 4, &rxdesc->icv); - rxdesc->dev_flags |= RXDONE_CRYPTO_ICV; - - /* - * Hardware has stripped IV/EIV data from 802.11 frame during - * decryption. It has provided the data seperately but rt2x00lib - * should decide if it should be reinserted. - */ - rxdesc->flags |= RX_FLAG_IV_STRIPPED; - - /* - * FIXME: Legacy driver indicates that the frame does - * contain the Michael Mic. Unfortunately, in rt2x00 - * the MIC seems to be missing completely... - */ - rxdesc->flags |= RX_FLAG_MMIC_STRIPPED; - - if (rxdesc->cipher_status == RX_CRYPTO_SUCCESS) - rxdesc->flags |= RX_FLAG_DECRYPTED; - else if (rxdesc->cipher_status == RX_CRYPTO_FAIL_MIC) - rxdesc->flags |= RX_FLAG_MMIC_ERROR; - } - - /* - * Obtain the status about this packet. - * When frame was received with an OFDM bitrate, - * the signal is the PLCP value. If it was received with - * a CCK bitrate the signal is the rate in 100kbit/s. - */ - rxdesc->signal = rt2x00_get_field32(word1, RXD_W1_SIGNAL); - rxdesc->rssi = rt73usb_agc_to_rssi(rt2x00dev, word1); - rxdesc->size = rt2x00_get_field32(word0, RXD_W0_DATABYTE_COUNT); - - if (rt2x00_get_field32(word0, RXD_W0_OFDM)) - rxdesc->dev_flags |= RXDONE_SIGNAL_PLCP; - else - rxdesc->dev_flags |= RXDONE_SIGNAL_BITRATE; - if (rt2x00_get_field32(word0, RXD_W0_MY_BSS)) - rxdesc->dev_flags |= RXDONE_MY_BSS; - - /* - * Set skb pointers, and update frame information. - */ - skb_pull(entry->skb, entry->queue->desc_size); - skb_trim(entry->skb, rxdesc->size); -} - -/* - * Device probe functions. - */ -static int rt73usb_validate_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u16 word; - u8 *mac; - s8 value; - - rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom, EEPROM_SIZE); - - /* - * Start validation of the data that has been read. - */ - mac = rt2x00_eeprom_addr(rt2x00dev, EEPROM_MAC_ADDR_0); - if (!is_valid_ether_addr(mac)) { - random_ether_addr(mac); - EEPROM(rt2x00dev, "MAC: %pM\n", mac); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_ANTENNA_NUM, 2); - rt2x00_set_field16(&word, EEPROM_ANTENNA_TX_DEFAULT, - ANTENNA_B); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RX_DEFAULT, - ANTENNA_B); - rt2x00_set_field16(&word, EEPROM_ANTENNA_FRAME_TYPE, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_DYN_TXAGC, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_HARDWARE_RADIO, 0); - rt2x00_set_field16(&word, EEPROM_ANTENNA_RF_TYPE, RF5226); - rt2x00_eeprom_write(rt2x00dev, EEPROM_ANTENNA, word); - EEPROM(rt2x00dev, "Antenna: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_NIC_EXTERNAL_LNA, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_NIC, word); - EEPROM(rt2x00dev, "NIC: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_G, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_RDY_A, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_ACT, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_0, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_1, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_2, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_3, 0); - rt2x00_set_field16(&word, EEPROM_LED_POLARITY_GPIO_4, 0); - rt2x00_set_field16(&word, EEPROM_LED_LED_MODE, - LED_MODE_DEFAULT); - rt2x00_eeprom_write(rt2x00dev, EEPROM_LED, word); - EEPROM(rt2x00dev, "Led: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_FREQ_OFFSET, 0); - rt2x00_set_field16(&word, EEPROM_FREQ_SEQ, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_FREQ, word); - EEPROM(rt2x00dev, "Freq: 0x%04x\n", word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_BG, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0); - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word); - EEPROM(rt2x00dev, "RSSI OFFSET BG: 0x%04x\n", word); - } else { - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_1); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_1, 0); - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_BG_2); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_BG_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_BG, word); - } - - rt2x00_eeprom_read(rt2x00dev, EEPROM_RSSI_OFFSET_A, &word); - if (word == 0xffff) { - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0); - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); - EEPROM(rt2x00dev, "RSSI OFFSET A: 0x%04x\n", word); - } else { - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_1); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_1, 0); - value = rt2x00_get_field16(word, EEPROM_RSSI_OFFSET_A_2); - if (value < -10 || value > 10) - rt2x00_set_field16(&word, EEPROM_RSSI_OFFSET_A_2, 0); - rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_OFFSET_A, word); - } - - return 0; -} - -static int rt73usb_init_eeprom(struct rt2x00_dev *rt2x00dev) -{ - u32 reg; - u16 value; - u16 eeprom; - - /* - * Read EEPROM word for configuration. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_ANTENNA, &eeprom); - - /* - * Identify RF chipset. - */ - value = rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RF_TYPE); - rt2x00usb_register_read(rt2x00dev, MAC_CSR0, ®); - rt2x00_set_chip(rt2x00dev, RT2571, value, reg); - - if (!rt2x00_check_rev(&rt2x00dev->chip, 0x000ffff0, 0x25730) || - rt2x00_check_rev(&rt2x00dev->chip, 0x0000000f, 0)) { - ERROR(rt2x00dev, "Invalid RT chipset detected.\n"); - return -ENODEV; - } - - if (!rt2x00_rf(&rt2x00dev->chip, RF5226) && - !rt2x00_rf(&rt2x00dev->chip, RF2528) && - !rt2x00_rf(&rt2x00dev->chip, RF5225) && - !rt2x00_rf(&rt2x00dev->chip, RF2527)) { - ERROR(rt2x00dev, "Invalid RF chipset detected.\n"); - return -ENODEV; - } - - /* - * Identify default antenna configuration. - */ - rt2x00dev->default_ant.tx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_TX_DEFAULT); - rt2x00dev->default_ant.rx = - rt2x00_get_field16(eeprom, EEPROM_ANTENNA_RX_DEFAULT); - - /* - * Read the Frame type. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_FRAME_TYPE)) - __set_bit(CONFIG_FRAME_TYPE, &rt2x00dev->flags); - - /* - * Detect if this device has an hardware controlled radio. - */ - if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) - __set_bit(CONFIG_SUPPORT_HW_BUTTON, &rt2x00dev->flags); - - /* - * Read frequency offset. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &eeprom); - rt2x00dev->freq_offset = rt2x00_get_field16(eeprom, EEPROM_FREQ_OFFSET); - - /* - * Read external LNA informations. - */ - rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC, &eeprom); - - if (rt2x00_get_field16(eeprom, EEPROM_NIC_EXTERNAL_LNA)) { - __set_bit(CONFIG_EXTERNAL_LNA_A, &rt2x00dev->flags); - __set_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags); - } - - /* - * Store led settings, for correct led behaviour. - */ -#ifdef CONFIG_RT2X00_LIB_LEDS - rt2x00_eeprom_read(rt2x00dev, EEPROM_LED, &eeprom); - - rt73usb_init_led(rt2x00dev, &rt2x00dev->led_radio, LED_TYPE_RADIO); - rt73usb_init_led(rt2x00dev, &rt2x00dev->led_assoc, LED_TYPE_ASSOC); - if (value == LED_MODE_SIGNAL_STRENGTH) - rt73usb_init_led(rt2x00dev, &rt2x00dev->led_qual, - LED_TYPE_QUALITY); - - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_LED_MODE, value); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_0, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_0)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_1, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_1)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_2, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_2)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_3, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_3)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_GPIO_4, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_GPIO_4)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_ACT, - rt2x00_get_field16(eeprom, EEPROM_LED_POLARITY_ACT)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_BG, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_RDY_G)); - rt2x00_set_field16(&rt2x00dev->led_mcu_reg, MCU_LEDCS_POLARITY_READY_A, - rt2x00_get_field16(eeprom, - EEPROM_LED_POLARITY_RDY_A)); -#endif /* CONFIG_RT2X00_LIB_LEDS */ - - return 0; -} - -/* - * RF value list for RF2528 - * Supports: 2.4 GHz - */ -static const struct rf_channel rf_vals_bg_2528[] = { - { 1, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b }, - { 2, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f }, - { 3, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b }, - { 4, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f }, - { 5, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b }, - { 6, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f }, - { 7, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b }, - { 8, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f }, - { 9, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b }, - { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f }, - { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b }, - { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f }, - { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b }, - { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 }, -}; - -/* - * RF value list for RF5226 - * Supports: 2.4 GHz & 5.2 GHz - */ -static const struct rf_channel rf_vals_5226[] = { - { 1, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea0b }, - { 2, 0x00002c0c, 0x00000786, 0x00068255, 0x000fea1f }, - { 3, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea0b }, - { 4, 0x00002c0c, 0x0000078a, 0x00068255, 0x000fea1f }, - { 5, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea0b }, - { 6, 0x00002c0c, 0x0000078e, 0x00068255, 0x000fea1f }, - { 7, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea0b }, - { 8, 0x00002c0c, 0x00000792, 0x00068255, 0x000fea1f }, - { 9, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea0b }, - { 10, 0x00002c0c, 0x00000796, 0x00068255, 0x000fea1f }, - { 11, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea0b }, - { 12, 0x00002c0c, 0x0000079a, 0x00068255, 0x000fea1f }, - { 13, 0x00002c0c, 0x0000079e, 0x00068255, 0x000fea0b }, - { 14, 0x00002c0c, 0x000007a2, 0x00068255, 0x000fea13 }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x00002c0c, 0x0000099a, 0x00098255, 0x000fea23 }, - { 40, 0x00002c0c, 0x000009a2, 0x00098255, 0x000fea03 }, - { 44, 0x00002c0c, 0x000009a6, 0x00098255, 0x000fea0b }, - { 48, 0x00002c0c, 0x000009aa, 0x00098255, 0x000fea13 }, - { 52, 0x00002c0c, 0x000009ae, 0x00098255, 0x000fea1b }, - { 56, 0x00002c0c, 0x000009b2, 0x00098255, 0x000fea23 }, - { 60, 0x00002c0c, 0x000009ba, 0x00098255, 0x000fea03 }, - { 64, 0x00002c0c, 0x000009be, 0x00098255, 0x000fea0b }, - - /* 802.11 HyperLan 2 */ - { 100, 0x00002c0c, 0x00000a2a, 0x000b8255, 0x000fea03 }, - { 104, 0x00002c0c, 0x00000a2e, 0x000b8255, 0x000fea0b }, - { 108, 0x00002c0c, 0x00000a32, 0x000b8255, 0x000fea13 }, - { 112, 0x00002c0c, 0x00000a36, 0x000b8255, 0x000fea1b }, - { 116, 0x00002c0c, 0x00000a3a, 0x000b8255, 0x000fea23 }, - { 120, 0x00002c0c, 0x00000a82, 0x000b8255, 0x000fea03 }, - { 124, 0x00002c0c, 0x00000a86, 0x000b8255, 0x000fea0b }, - { 128, 0x00002c0c, 0x00000a8a, 0x000b8255, 0x000fea13 }, - { 132, 0x00002c0c, 0x00000a8e, 0x000b8255, 0x000fea1b }, - { 136, 0x00002c0c, 0x00000a92, 0x000b8255, 0x000fea23 }, - - /* 802.11 UNII */ - { 140, 0x00002c0c, 0x00000a9a, 0x000b8255, 0x000fea03 }, - { 149, 0x00002c0c, 0x00000aa2, 0x000b8255, 0x000fea1f }, - { 153, 0x00002c0c, 0x00000aa6, 0x000b8255, 0x000fea27 }, - { 157, 0x00002c0c, 0x00000aae, 0x000b8255, 0x000fea07 }, - { 161, 0x00002c0c, 0x00000ab2, 0x000b8255, 0x000fea0f }, - { 165, 0x00002c0c, 0x00000ab6, 0x000b8255, 0x000fea17 }, - - /* MMAC(Japan)J52 ch 34,38,42,46 */ - { 34, 0x00002c0c, 0x0008099a, 0x000da255, 0x000d3a0b }, - { 38, 0x00002c0c, 0x0008099e, 0x000da255, 0x000d3a13 }, - { 42, 0x00002c0c, 0x000809a2, 0x000da255, 0x000d3a1b }, - { 46, 0x00002c0c, 0x000809a6, 0x000da255, 0x000d3a23 }, -}; - -/* - * RF value list for RF5225 & RF2527 - * Supports: 2.4 GHz & 5.2 GHz - */ -static const struct rf_channel rf_vals_5225_2527[] = { - { 1, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa0b }, - { 2, 0x00002ccc, 0x00004786, 0x00068455, 0x000ffa1f }, - { 3, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa0b }, - { 4, 0x00002ccc, 0x0000478a, 0x00068455, 0x000ffa1f }, - { 5, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa0b }, - { 6, 0x00002ccc, 0x0000478e, 0x00068455, 0x000ffa1f }, - { 7, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa0b }, - { 8, 0x00002ccc, 0x00004792, 0x00068455, 0x000ffa1f }, - { 9, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa0b }, - { 10, 0x00002ccc, 0x00004796, 0x00068455, 0x000ffa1f }, - { 11, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa0b }, - { 12, 0x00002ccc, 0x0000479a, 0x00068455, 0x000ffa1f }, - { 13, 0x00002ccc, 0x0000479e, 0x00068455, 0x000ffa0b }, - { 14, 0x00002ccc, 0x000047a2, 0x00068455, 0x000ffa13 }, - - /* 802.11 UNI / HyperLan 2 */ - { 36, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa23 }, - { 40, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa03 }, - { 44, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa0b }, - { 48, 0x00002ccc, 0x000049aa, 0x0009be55, 0x000ffa13 }, - { 52, 0x00002ccc, 0x000049ae, 0x0009ae55, 0x000ffa1b }, - { 56, 0x00002ccc, 0x000049b2, 0x0009ae55, 0x000ffa23 }, - { 60, 0x00002ccc, 0x000049ba, 0x0009ae55, 0x000ffa03 }, - { 64, 0x00002ccc, 0x000049be, 0x0009ae55, 0x000ffa0b }, - - /* 802.11 HyperLan 2 */ - { 100, 0x00002ccc, 0x00004a2a, 0x000bae55, 0x000ffa03 }, - { 104, 0x00002ccc, 0x00004a2e, 0x000bae55, 0x000ffa0b }, - { 108, 0x00002ccc, 0x00004a32, 0x000bae55, 0x000ffa13 }, - { 112, 0x00002ccc, 0x00004a36, 0x000bae55, 0x000ffa1b }, - { 116, 0x00002ccc, 0x00004a3a, 0x000bbe55, 0x000ffa23 }, - { 120, 0x00002ccc, 0x00004a82, 0x000bbe55, 0x000ffa03 }, - { 124, 0x00002ccc, 0x00004a86, 0x000bbe55, 0x000ffa0b }, - { 128, 0x00002ccc, 0x00004a8a, 0x000bbe55, 0x000ffa13 }, - { 132, 0x00002ccc, 0x00004a8e, 0x000bbe55, 0x000ffa1b }, - { 136, 0x00002ccc, 0x00004a92, 0x000bbe55, 0x000ffa23 }, - - /* 802.11 UNII */ - { 140, 0x00002ccc, 0x00004a9a, 0x000bbe55, 0x000ffa03 }, - { 149, 0x00002ccc, 0x00004aa2, 0x000bbe55, 0x000ffa1f }, - { 153, 0x00002ccc, 0x00004aa6, 0x000bbe55, 0x000ffa27 }, - { 157, 0x00002ccc, 0x00004aae, 0x000bbe55, 0x000ffa07 }, - { 161, 0x00002ccc, 0x00004ab2, 0x000bbe55, 0x000ffa0f }, - { 165, 0x00002ccc, 0x00004ab6, 0x000bbe55, 0x000ffa17 }, - - /* MMAC(Japan)J52 ch 34,38,42,46 */ - { 34, 0x00002ccc, 0x0000499a, 0x0009be55, 0x000ffa0b }, - { 38, 0x00002ccc, 0x0000499e, 0x0009be55, 0x000ffa13 }, - { 42, 0x00002ccc, 0x000049a2, 0x0009be55, 0x000ffa1b }, - { 46, 0x00002ccc, 0x000049a6, 0x0009be55, 0x000ffa23 }, -}; - - -static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev) -{ - struct hw_mode_spec *spec = &rt2x00dev->spec; - struct channel_info *info; - char *tx_power; - unsigned int i; - - /* - * Initialize all hw fields. - */ - rt2x00dev->hw->flags = - IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_SUPPORTS_PS | - IEEE80211_HW_PS_NULLFUNC_STACK; - rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE; - - SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); - SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, - rt2x00_eeprom_addr(rt2x00dev, - EEPROM_MAC_ADDR_0)); - - /* - * Initialize hw_mode information. - */ - spec->supported_bands = SUPPORT_BAND_2GHZ; - spec->supported_rates = SUPPORT_RATE_CCK | SUPPORT_RATE_OFDM; - - if (rt2x00_rf(&rt2x00dev->chip, RF2528)) { - spec->num_channels = ARRAY_SIZE(rf_vals_bg_2528); - spec->channels = rf_vals_bg_2528; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5226)) { - spec->supported_bands |= SUPPORT_BAND_5GHZ; - spec->num_channels = ARRAY_SIZE(rf_vals_5226); - spec->channels = rf_vals_5226; - } else if (rt2x00_rf(&rt2x00dev->chip, RF2527)) { - spec->num_channels = 14; - spec->channels = rf_vals_5225_2527; - } else if (rt2x00_rf(&rt2x00dev->chip, RF5225)) { - spec->supported_bands |= SUPPORT_BAND_5GHZ; - spec->num_channels = ARRAY_SIZE(rf_vals_5225_2527); - spec->channels = rf_vals_5225_2527; - } - - /* - * Create channel information array - */ - info = kzalloc(spec->num_channels * sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; - - spec->channels_info = info; - - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); - for (i = 0; i < 14; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - - if (spec->num_channels > 14) { - tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); - for (i = 14; i < spec->num_channels; i++) - info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); - } - - return 0; -} - -static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev) -{ - int retval; - - /* - * Allocate eeprom data. - */ - retval = rt73usb_validate_eeprom(rt2x00dev); - if (retval) - return retval; - - retval = rt73usb_init_eeprom(rt2x00dev); - if (retval) - return retval; - - /* - * Initialize hw specifications. - */ - retval = rt73usb_probe_hw_mode(rt2x00dev); - if (retval) - return retval; - - /* - * This device has multiple filters for control frames, - * but has no a separate filter for PS Poll frames. - */ - __set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags); - - /* - * This device requires firmware. - */ - __set_bit(DRIVER_REQUIRE_FIRMWARE, &rt2x00dev->flags); - if (!modparam_nohwcrypt) - __set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags); - - /* - * Set the rssi offset. - */ - rt2x00dev->rssi_offset = DEFAULT_RSSI_OFFSET; - - return 0; -} - -/* - * IEEE80211 stack callback functions. - */ -static int rt73usb_conf_tx(struct ieee80211_hw *hw, u16 queue_idx, - const struct ieee80211_tx_queue_params *params) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - struct data_queue *queue; - struct rt2x00_field32 field; - int retval; - u32 reg; - u32 offset; - - /* - * First pass the configuration through rt2x00lib, that will - * update the queue settings and validate the input. After that - * we are free to update the registers based on the value - * in the queue parameter. - */ - retval = rt2x00mac_conf_tx(hw, queue_idx, params); - if (retval) - return retval; - - /* - * We only need to perform additional register initialization - * for WMM queues/ - */ - if (queue_idx >= 4) - return 0; - - queue = rt2x00queue_get_queue(rt2x00dev, queue_idx); - - /* Update WMM TXOP register */ - offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2))); - field.bit_offset = (queue_idx & 1) * 16; - field.bit_mask = 0xffff << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, offset, ®); - rt2x00_set_field32(®, field, queue->txop); - rt2x00usb_register_write(rt2x00dev, offset, reg); - - /* Update WMM registers */ - field.bit_offset = queue_idx * 4; - field.bit_mask = 0xf << field.bit_offset; - - rt2x00usb_register_read(rt2x00dev, AIFSN_CSR, ®); - rt2x00_set_field32(®, field, queue->aifs); - rt2x00usb_register_write(rt2x00dev, AIFSN_CSR, reg); - - rt2x00usb_register_read(rt2x00dev, CWMIN_CSR, ®); - rt2x00_set_field32(®, field, queue->cw_min); - rt2x00usb_register_write(rt2x00dev, CWMIN_CSR, reg); - - rt2x00usb_register_read(rt2x00dev, CWMAX_CSR, ®); - rt2x00_set_field32(®, field, queue->cw_max); - rt2x00usb_register_write(rt2x00dev, CWMAX_CSR, reg); - - return 0; -} - -static u64 rt73usb_get_tsf(struct ieee80211_hw *hw) -{ - struct rt2x00_dev *rt2x00dev = hw->priv; - u64 tsf; - u32 reg; - - rt2x00usb_register_read(rt2x00dev, TXRX_CSR13, ®); - tsf = (u64) rt2x00_get_field32(reg, TXRX_CSR13_HIGH_TSFTIMER) << 32; - rt2x00usb_register_read(rt2x00dev, TXRX_CSR12, ®); - tsf |= rt2x00_get_field32(reg, TXRX_CSR12_LOW_TSFTIMER); - - return tsf; -} - -static const struct ieee80211_ops rt73usb_mac80211_ops = { - .tx = rt2x00mac_tx, - .start = rt2x00mac_start, - .stop = rt2x00mac_stop, - .add_interface = rt2x00mac_add_interface, - .remove_interface = rt2x00mac_remove_interface, - .config = rt2x00mac_config, - .configure_filter = rt2x00mac_configure_filter, - .set_tim = rt2x00mac_set_tim, - .set_key = rt2x00mac_set_key, - .get_stats = rt2x00mac_get_stats, - .bss_info_changed = rt2x00mac_bss_info_changed, - .conf_tx = rt73usb_conf_tx, - .get_tx_stats = rt2x00mac_get_tx_stats, - .get_tsf = rt73usb_get_tsf, - .rfkill_poll = rt2x00mac_rfkill_poll, -}; - -static const struct rt2x00lib_ops rt73usb_rt2x00_ops = { - .probe_hw = rt73usb_probe_hw, - .get_firmware_name = rt73usb_get_firmware_name, - .check_firmware = rt73usb_check_firmware, - .load_firmware = rt73usb_load_firmware, - .initialize = rt2x00usb_initialize, - .uninitialize = rt2x00usb_uninitialize, - .clear_entry = rt2x00usb_clear_entry, - .set_device_state = rt73usb_set_device_state, - .rfkill_poll = rt73usb_rfkill_poll, - .link_stats = rt73usb_link_stats, - .reset_tuner = rt73usb_reset_tuner, - .link_tuner = rt73usb_link_tuner, - .write_tx_desc = rt73usb_write_tx_desc, - .write_tx_data = rt2x00usb_write_tx_data, - .write_beacon = rt73usb_write_beacon, - .get_tx_data_len = rt73usb_get_tx_data_len, - .kick_tx_queue = rt73usb_kick_tx_queue, - .kill_tx_queue = rt2x00usb_kill_tx_queue, - .fill_rxdone = rt73usb_fill_rxdone, - .config_shared_key = rt73usb_config_shared_key, - .config_pairwise_key = rt73usb_config_pairwise_key, - .config_filter = rt73usb_config_filter, - .config_intf = rt73usb_config_intf, - .config_erp = rt73usb_config_erp, - .config_ant = rt73usb_config_ant, - .config = rt73usb_config, -}; - -static const struct data_queue_desc rt73usb_queue_rx = { - .entry_num = RX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = RXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt73usb_queue_tx = { - .entry_num = TX_ENTRIES, - .data_size = DATA_FRAME_SIZE, - .desc_size = TXD_DESC_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct data_queue_desc rt73usb_queue_bcn = { - .entry_num = 4 * BEACON_ENTRIES, - .data_size = MGMT_FRAME_SIZE, - .desc_size = TXINFO_SIZE, - .priv_size = sizeof(struct queue_entry_priv_usb), -}; - -static const struct rt2x00_ops rt73usb_ops = { - .name = KBUILD_MODNAME, - .max_sta_intf = 1, - .max_ap_intf = 4, - .eeprom_size = EEPROM_SIZE, - .rf_size = RF_SIZE, - .tx_queues = NUM_TX_QUEUES, - .rx = &rt73usb_queue_rx, - .tx = &rt73usb_queue_tx, - .bcn = &rt73usb_queue_bcn, - .lib = &rt73usb_rt2x00_ops, - .hw = &rt73usb_mac80211_ops, -#ifdef CONFIG_RT2X00_LIB_DEBUGFS - .debugfs = &rt73usb_rt2x00debug, -#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ -}; - -/* - * rt73usb module information. - */ -static struct usb_device_id rt73usb_device_table[] = { - /* AboCom */ - { USB_DEVICE(0x07b8, 0xb21b), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21c), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21d), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21e), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07b8, 0xb21f), USB_DEVICE_DATA(&rt73usb_ops) }, - /* AL */ - { USB_DEVICE(0x14b2, 0x3c10), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Amigo */ - { USB_DEVICE(0x148f, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0eb0, 0x9021), USB_DEVICE_DATA(&rt73usb_ops) }, - /* AMIT */ - { USB_DEVICE(0x18c5, 0x0002), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Askey */ - { USB_DEVICE(0x1690, 0x0722), USB_DEVICE_DATA(&rt73usb_ops) }, - /* ASUS */ - { USB_DEVICE(0x0b05, 0x1723), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0b05, 0x1724), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Belkin */ - { USB_DEVICE(0x050d, 0x7050), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x050d, 0x705a), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x050d, 0x905b), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x050d, 0x905c), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Billionton */ - { USB_DEVICE(0x1631, 0xc019), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x08dd, 0x0120), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Buffalo */ - { USB_DEVICE(0x0411, 0x00d8), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x00f4), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x0116), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0411, 0x0119), USB_DEVICE_DATA(&rt73usb_ops) }, - /* CNet */ - { USB_DEVICE(0x1371, 0x9022), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x1371, 0x9032), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Conceptronic */ - { USB_DEVICE(0x14b2, 0x3c22), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Corega */ - { USB_DEVICE(0x07aa, 0x002e), USB_DEVICE_DATA(&rt73usb_ops) }, - /* D-Link */ - { USB_DEVICE(0x07d1, 0x3c03), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c04), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c06), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x07d1, 0x3c07), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Edimax */ - { USB_DEVICE(0x7392, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x7392, 0x7618), USB_DEVICE_DATA(&rt73usb_ops) }, - /* EnGenius */ - { USB_DEVICE(0x1740, 0x3701), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Gemtek */ - { USB_DEVICE(0x15a9, 0x0004), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Gigabyte */ - { USB_DEVICE(0x1044, 0x8008), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x1044, 0x800a), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Huawei-3Com */ - { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Hercules */ - { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Linksys */ - { USB_DEVICE(0x13b1, 0x0020), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x13b1, 0x0023), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x13b1, 0x0028), USB_DEVICE_DATA(&rt73usb_ops) }, - /* MSI */ - { USB_DEVICE(0x0db0, 0x4600), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0x6877), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0x6874), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0xa861), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0db0, 0xa874), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Ovislink */ - { USB_DEVICE(0x1b75, 0x7318), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Ralink */ - { USB_DEVICE(0x04bb, 0x093d), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x148f, 0x2573), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x148f, 0x2671), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Qcom */ - { USB_DEVICE(0x18e8, 0x6196), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x18e8, 0x6229), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x18e8, 0x6238), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Samsung */ - { USB_DEVICE(0x04e8, 0x4471), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Senao */ - { USB_DEVICE(0x1740, 0x7100), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Sitecom */ - { USB_DEVICE(0x0df6, 0x0024), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x0027), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x002f), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x90ac), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x0df6, 0x9712), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Surecom */ - { USB_DEVICE(0x0769, 0x31f3), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Tilgin */ - { USB_DEVICE(0x6933, 0x5001), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Philips */ - { USB_DEVICE(0x0471, 0x200a), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Planex */ - { USB_DEVICE(0x2019, 0xab01), USB_DEVICE_DATA(&rt73usb_ops) }, - { USB_DEVICE(0x2019, 0xab50), USB_DEVICE_DATA(&rt73usb_ops) }, - /* WideTell */ - { USB_DEVICE(0x7167, 0x3840), USB_DEVICE_DATA(&rt73usb_ops) }, - /* Zcom */ - { USB_DEVICE(0x0cde, 0x001c), USB_DEVICE_DATA(&rt73usb_ops) }, - /* ZyXEL */ - { USB_DEVICE(0x0586, 0x3415), USB_DEVICE_DATA(&rt73usb_ops) }, - { 0, } -}; - -MODULE_AUTHOR(DRV_PROJECT); -MODULE_VERSION(DRV_VERSION); -MODULE_DESCRIPTION("Ralink RT73 USB Wireless LAN driver."); -MODULE_SUPPORTED_DEVICE("Ralink RT2571W & RT2671 USB chipset based cards"); -MODULE_DEVICE_TABLE(usb, rt73usb_device_table); -MODULE_FIRMWARE(FIRMWARE_RT2571); -MODULE_LICENSE("GPL"); - -static struct usb_driver rt73usb_driver = { - .name = KBUILD_MODNAME, - .id_table = rt73usb_device_table, - .probe = rt2x00usb_probe, - .disconnect = rt2x00usb_disconnect, - .suspend = rt2x00usb_suspend, - .resume = rt2x00usb_resume, -}; - -static int __init rt73usb_init(void) -{ - return usb_register(&rt73usb_driver); -} - -static void __exit rt73usb_exit(void) -{ - usb_deregister(&rt73usb_driver); -} - -module_init(rt73usb_init); -module_exit(rt73usb_exit); diff --git a/drivers/net/wireless/rt2x00/rt73usb.h b/drivers/net/wireless/rt2x00/rt73usb.h deleted file mode 100644 index 81fe0be51c42..000000000000 --- a/drivers/net/wireless/rt2x00/rt73usb.h +++ /dev/null @@ -1,1074 +0,0 @@ -/* - Copyright (C) 2004 - 2009 rt2x00 SourceForge Project - - - 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: rt73usb - Abstract: Data structures and registers for the rt73usb module. - Supported chipsets: rt2571W & rt2671. - */ - -#ifndef RT73USB_H -#define RT73USB_H - -/* - * RF chip defines. - */ -#define RF5226 0x0001 -#define RF2528 0x0002 -#define RF5225 0x0003 -#define RF2527 0x0004 - -/* - * Signal information. - * Defaul offset is required for RSSI <-> dBm conversion. - */ -#define DEFAULT_RSSI_OFFSET 120 - -/* - * Register layout information. - */ -#define CSR_REG_BASE 0x3000 -#define CSR_REG_SIZE 0x04b0 -#define EEPROM_BASE 0x0000 -#define EEPROM_SIZE 0x0100 -#define BBP_BASE 0x0000 -#define BBP_SIZE 0x0080 -#define RF_BASE 0x0004 -#define RF_SIZE 0x0010 - -/* - * Number of TX queues. - */ -#define NUM_TX_QUEUES 4 - -/* - * USB registers. - */ - -/* - * MCU_LEDCS: LED control for MCU Mailbox. - */ -#define MCU_LEDCS_LED_MODE FIELD16(0x001f) -#define MCU_LEDCS_RADIO_STATUS FIELD16(0x0020) -#define MCU_LEDCS_LINK_BG_STATUS FIELD16(0x0040) -#define MCU_LEDCS_LINK_A_STATUS FIELD16(0x0080) -#define MCU_LEDCS_POLARITY_GPIO_0 FIELD16(0x0100) -#define MCU_LEDCS_POLARITY_GPIO_1 FIELD16(0x0200) -#define MCU_LEDCS_POLARITY_GPIO_2 FIELD16(0x0400) -#define MCU_LEDCS_POLARITY_GPIO_3 FIELD16(0x0800) -#define MCU_LEDCS_POLARITY_GPIO_4 FIELD16(0x1000) -#define MCU_LEDCS_POLARITY_ACT FIELD16(0x2000) -#define MCU_LEDCS_POLARITY_READY_BG FIELD16(0x4000) -#define MCU_LEDCS_POLARITY_READY_A FIELD16(0x8000) - -/* - * 8051 firmware image. - */ -#define FIRMWARE_RT2571 "rt73.bin" -#define FIRMWARE_IMAGE_BASE 0x0800 - -/* - * Security key table memory. - * 16 entries 32-byte for shared key table - * 64 entries 32-byte for pairwise key table - * 64 entries 8-byte for pairwise ta key table - */ -#define SHARED_KEY_TABLE_BASE 0x1000 -#define PAIRWISE_KEY_TABLE_BASE 0x1200 -#define PAIRWISE_TA_TABLE_BASE 0x1a00 - -#define SHARED_KEY_ENTRY(__idx) \ - ( SHARED_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) -#define PAIRWISE_KEY_ENTRY(__idx) \ - ( PAIRWISE_KEY_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_key_entry)) ) -#define PAIRWISE_TA_ENTRY(__idx) \ - ( PAIRWISE_TA_TABLE_BASE + \ - ((__idx) * sizeof(struct hw_pairwise_ta_entry)) ) - -struct hw_key_entry { - u8 key[16]; - u8 tx_mic[8]; - u8 rx_mic[8]; -} __attribute__ ((packed)); - -struct hw_pairwise_ta_entry { - u8 address[6]; - u8 cipher; - u8 reserved; -} __attribute__ ((packed)); - -/* - * Since NULL frame won't be that long (256 byte), - * We steal 16 tail bytes to save debugging settings. - */ -#define HW_DEBUG_SETTING_BASE 0x2bf0 - -/* - * On-chip BEACON frame space. - */ -#define HW_BEACON_BASE0 0x2400 -#define HW_BEACON_BASE1 0x2500 -#define HW_BEACON_BASE2 0x2600 -#define HW_BEACON_BASE3 0x2700 - -#define HW_BEACON_OFFSET(__index) \ - ( HW_BEACON_BASE0 + (__index * 0x0100) ) - -/* - * MAC Control/Status Registers(CSR). - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * MAC_CSR0: ASIC revision number. - */ -#define MAC_CSR0 0x3000 - -/* - * MAC_CSR1: System control register. - * SOFT_RESET: Software reset bit, 1: reset, 0: normal. - * BBP_RESET: Hardware reset BBP. - * HOST_READY: Host is ready after initialization, 1: ready. - */ -#define MAC_CSR1 0x3004 -#define MAC_CSR1_SOFT_RESET FIELD32(0x00000001) -#define MAC_CSR1_BBP_RESET FIELD32(0x00000002) -#define MAC_CSR1_HOST_READY FIELD32(0x00000004) - -/* - * MAC_CSR2: STA MAC register 0. - */ -#define MAC_CSR2 0x3008 -#define MAC_CSR2_BYTE0 FIELD32(0x000000ff) -#define MAC_CSR2_BYTE1 FIELD32(0x0000ff00) -#define MAC_CSR2_BYTE2 FIELD32(0x00ff0000) -#define MAC_CSR2_BYTE3 FIELD32(0xff000000) - -/* - * MAC_CSR3: STA MAC register 1. - * UNICAST_TO_ME_MASK: - * Used to mask off bits from byte 5 of the MAC address - * to determine the UNICAST_TO_ME bit for RX frames. - * The full mask is complemented by BSS_ID_MASK: - * MASK = BSS_ID_MASK & UNICAST_TO_ME_MASK - */ -#define MAC_CSR3 0x300c -#define MAC_CSR3_BYTE4 FIELD32(0x000000ff) -#define MAC_CSR3_BYTE5 FIELD32(0x0000ff00) -#define MAC_CSR3_UNICAST_TO_ME_MASK FIELD32(0x00ff0000) - -/* - * MAC_CSR4: BSSID register 0. - */ -#define MAC_CSR4 0x3010 -#define MAC_CSR4_BYTE0 FIELD32(0x000000ff) -#define MAC_CSR4_BYTE1 FIELD32(0x0000ff00) -#define MAC_CSR4_BYTE2 FIELD32(0x00ff0000) -#define MAC_CSR4_BYTE3 FIELD32(0xff000000) - -/* - * MAC_CSR5: BSSID register 1. - * BSS_ID_MASK: - * This mask is used to mask off bits 0 and 1 of byte 5 of the - * BSSID. This will make sure that those bits will be ignored - * when determining the MY_BSS of RX frames. - * 0: 1-BSSID mode (BSS index = 0) - * 1: 2-BSSID mode (BSS index: Byte5, bit 0) - * 2: 2-BSSID mode (BSS index: byte5, bit 1) - * 3: 4-BSSID mode (BSS index: byte5, bit 0 - 1) - */ -#define MAC_CSR5 0x3014 -#define MAC_CSR5_BYTE4 FIELD32(0x000000ff) -#define MAC_CSR5_BYTE5 FIELD32(0x0000ff00) -#define MAC_CSR5_BSS_ID_MASK FIELD32(0x00ff0000) - -/* - * MAC_CSR6: Maximum frame length register. - */ -#define MAC_CSR6 0x3018 -#define MAC_CSR6_MAX_FRAME_UNIT FIELD32(0x00000fff) - -/* - * MAC_CSR7: Reserved - */ -#define MAC_CSR7 0x301c - -/* - * MAC_CSR8: SIFS/EIFS register. - * All units are in US. - */ -#define MAC_CSR8 0x3020 -#define MAC_CSR8_SIFS FIELD32(0x000000ff) -#define MAC_CSR8_SIFS_AFTER_RX_OFDM FIELD32(0x0000ff00) -#define MAC_CSR8_EIFS FIELD32(0xffff0000) - -/* - * MAC_CSR9: Back-Off control register. - * SLOT_TIME: Slot time, default is 20us for 802.11BG. - * CWMIN: Bit for Cwmin. default Cwmin is 31 (2^5 - 1). - * CWMAX: Bit for Cwmax, default Cwmax is 1023 (2^10 - 1). - * CW_SELECT: 1: CWmin/Cwmax select from register, 0:select from TxD. - */ -#define MAC_CSR9 0x3024 -#define MAC_CSR9_SLOT_TIME FIELD32(0x000000ff) -#define MAC_CSR9_CWMIN FIELD32(0x00000f00) -#define MAC_CSR9_CWMAX FIELD32(0x0000f000) -#define MAC_CSR9_CW_SELECT FIELD32(0x00010000) - -/* - * MAC_CSR10: Power state configuration. - */ -#define MAC_CSR10 0x3028 - -/* - * MAC_CSR11: Power saving transition time register. - * DELAY_AFTER_TBCN: Delay after Tbcn expired in units of TU. - * TBCN_BEFORE_WAKEUP: Number of beacon before wakeup. - * WAKEUP_LATENCY: In unit of TU. - */ -#define MAC_CSR11 0x302c -#define MAC_CSR11_DELAY_AFTER_TBCN FIELD32(0x000000ff) -#define MAC_CSR11_TBCN_BEFORE_WAKEUP FIELD32(0x00007f00) -#define MAC_CSR11_AUTOWAKE FIELD32(0x00008000) -#define MAC_CSR11_WAKEUP_LATENCY FIELD32(0x000f0000) - -/* - * MAC_CSR12: Manual power control / status register (merge CSR20 & PWRCSR1). - * CURRENT_STATE: 0:sleep, 1:awake. - * FORCE_WAKEUP: This has higher priority than PUT_TO_SLEEP. - * BBP_CURRENT_STATE: 0: BBP sleep, 1: BBP awake. - */ -#define MAC_CSR12 0x3030 -#define MAC_CSR12_CURRENT_STATE FIELD32(0x00000001) -#define MAC_CSR12_PUT_TO_SLEEP FIELD32(0x00000002) -#define MAC_CSR12_FORCE_WAKEUP FIELD32(0x00000004) -#define MAC_CSR12_BBP_CURRENT_STATE FIELD32(0x00000008) - -/* - * MAC_CSR13: GPIO. - */ -#define MAC_CSR13 0x3034 -#define MAC_CSR13_BIT0 FIELD32(0x00000001) -#define MAC_CSR13_BIT1 FIELD32(0x00000002) -#define MAC_CSR13_BIT2 FIELD32(0x00000004) -#define MAC_CSR13_BIT3 FIELD32(0x00000008) -#define MAC_CSR13_BIT4 FIELD32(0x00000010) -#define MAC_CSR13_BIT5 FIELD32(0x00000020) -#define MAC_CSR13_BIT6 FIELD32(0x00000040) -#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. - * ON_PERIOD: On period, default 70ms. - * OFF_PERIOD: Off period, default 30ms. - * HW_LED: HW TX activity, 1: normal OFF, 0: normal ON. - * SW_LED: s/w LED, 1: ON, 0: OFF. - * HW_LED_POLARITY: 0: active low, 1: active high. - */ -#define MAC_CSR14 0x3038 -#define MAC_CSR14_ON_PERIOD FIELD32(0x000000ff) -#define MAC_CSR14_OFF_PERIOD FIELD32(0x0000ff00) -#define MAC_CSR14_HW_LED FIELD32(0x00010000) -#define MAC_CSR14_SW_LED FIELD32(0x00020000) -#define MAC_CSR14_HW_LED_POLARITY FIELD32(0x00040000) -#define MAC_CSR14_SW_LED2 FIELD32(0x00080000) - -/* - * MAC_CSR15: NAV control. - */ -#define MAC_CSR15 0x303c - -/* - * TXRX control registers. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * TXRX_CSR0: TX/RX configuration register. - * TSF_OFFSET: Default is 24. - * AUTO_TX_SEQ: 1: ASIC auto replace sequence nr in outgoing frame. - * DISABLE_RX: Disable Rx engine. - * DROP_CRC: Drop CRC error. - * DROP_PHYSICAL: Drop physical error. - * DROP_CONTROL: Drop control frame. - * DROP_NOT_TO_ME: Drop not to me unicast frame. - * DROP_TO_DS: Drop fram ToDs bit is true. - * DROP_VERSION_ERROR: Drop version error frame. - * DROP_MULTICAST: Drop multicast frames. - * DROP_BORADCAST: Drop broadcast frames. - * ROP_ACK_CTS: Drop received ACK and CTS. - */ -#define TXRX_CSR0 0x3040 -#define TXRX_CSR0_RX_ACK_TIMEOUT FIELD32(0x000001ff) -#define TXRX_CSR0_TSF_OFFSET FIELD32(0x00007e00) -#define TXRX_CSR0_AUTO_TX_SEQ FIELD32(0x00008000) -#define TXRX_CSR0_DISABLE_RX FIELD32(0x00010000) -#define TXRX_CSR0_DROP_CRC FIELD32(0x00020000) -#define TXRX_CSR0_DROP_PHYSICAL FIELD32(0x00040000) -#define TXRX_CSR0_DROP_CONTROL FIELD32(0x00080000) -#define TXRX_CSR0_DROP_NOT_TO_ME FIELD32(0x00100000) -#define TXRX_CSR0_DROP_TO_DS FIELD32(0x00200000) -#define TXRX_CSR0_DROP_VERSION_ERROR FIELD32(0x00400000) -#define TXRX_CSR0_DROP_MULTICAST FIELD32(0x00800000) -#define TXRX_CSR0_DROP_BROADCAST FIELD32(0x01000000) -#define TXRX_CSR0_DROP_ACK_CTS FIELD32(0x02000000) -#define TXRX_CSR0_TX_WITHOUT_WAITING FIELD32(0x04000000) - -/* - * TXRX_CSR1 - */ -#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 - */ -#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 - */ -#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. - * AUTORESPOND_PREAMBLE: 0:long, 1:short preamble. - * OFDM_TX_RATE_DOWN: 1:enable. - * OFDM_TX_RATE_STEP: 0:1-step, 1: 2-step, 2:3-step, 3:4-step. - * OFDM_TX_FALLBACK_CCK: 0: Fallback to OFDM 6M only, 1: Fallback to CCK 1M,2M. - */ -#define TXRX_CSR4 0x3050 -#define TXRX_CSR4_TX_ACK_TIMEOUT FIELD32(0x000000ff) -#define TXRX_CSR4_CNTL_ACK_POLICY FIELD32(0x00000700) -#define TXRX_CSR4_ACK_CTS_PSM FIELD32(0x00010000) -#define TXRX_CSR4_AUTORESPOND_ENABLE FIELD32(0x00020000) -#define TXRX_CSR4_AUTORESPOND_PREAMBLE FIELD32(0x00040000) -#define TXRX_CSR4_OFDM_TX_RATE_DOWN FIELD32(0x00080000) -#define TXRX_CSR4_OFDM_TX_RATE_STEP FIELD32(0x00300000) -#define TXRX_CSR4_OFDM_TX_FALLBACK_CCK FIELD32(0x00400000) -#define TXRX_CSR4_LONG_RETRY_LIMIT FIELD32(0x0f000000) -#define TXRX_CSR4_SHORT_RETRY_LIMIT FIELD32(0xf0000000) - -/* - * TXRX_CSR5 - */ -#define TXRX_CSR5 0x3054 - -/* - * TXRX_CSR6: ACK/CTS payload consumed time - */ -#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_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_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. - * BEACON_INTERVAL: In unit of 1/16 TU. - * TSF_TICKING: Enable TSF auto counting. - * TSF_SYNC: Tsf sync, 0: disable, 1: infra, 2: ad-hoc/master mode. - * BEACON_GEN: Enable beacon generator. - */ -#define TXRX_CSR9 0x3064 -#define TXRX_CSR9_BEACON_INTERVAL FIELD32(0x0000ffff) -#define TXRX_CSR9_TSF_TICKING FIELD32(0x00010000) -#define TXRX_CSR9_TSF_SYNC FIELD32(0x00060000) -#define TXRX_CSR9_TBTT_ENABLE FIELD32(0x00080000) -#define TXRX_CSR9_BEACON_GEN FIELD32(0x00100000) -#define TXRX_CSR9_TIMESTAMP_COMPENSATE FIELD32(0xff000000) - -/* - * TXRX_CSR10: BEACON alignment. - */ -#define TXRX_CSR10 0x3068 - -/* - * TXRX_CSR11: AES mask. - */ -#define TXRX_CSR11 0x306c - -/* - * TXRX_CSR12: TSF low 32. - */ -#define TXRX_CSR12 0x3070 -#define TXRX_CSR12_LOW_TSFTIMER FIELD32(0xffffffff) - -/* - * TXRX_CSR13: TSF high 32. - */ -#define TXRX_CSR13 0x3074 -#define TXRX_CSR13_HIGH_TSFTIMER FIELD32(0xffffffff) - -/* - * TXRX_CSR14: TBTT timer. - */ -#define TXRX_CSR14 0x3078 - -/* - * TXRX_CSR15: TKIP MIC priority byte "AND" mask. - */ -#define TXRX_CSR15 0x307c - -/* - * PHY control registers. - * Some values are set in TU, whereas 1 TU == 1024 us. - */ - -/* - * PHY_CSR0: RF/PS control. - */ -#define PHY_CSR0 0x3080 -#define PHY_CSR0_PA_PE_BG FIELD32(0x00010000) -#define PHY_CSR0_PA_PE_A FIELD32(0x00020000) - -/* - * PHY_CSR1 - */ -#define PHY_CSR1 0x3084 -#define PHY_CSR1_RF_RPI FIELD32(0x00010000) - -/* - * PHY_CSR2: Pre-TX BBP control. - */ -#define PHY_CSR2 0x3088 - -/* - * PHY_CSR3: BBP serial control register. - * VALUE: Register value to program into BBP. - * REG_NUM: Selected BBP register. - * READ_CONTROL: 0: Write BBP, 1: Read BBP. - * BUSY: 1: ASIC is busy execute BBP programming. - */ -#define PHY_CSR3 0x308c -#define PHY_CSR3_VALUE FIELD32(0x000000ff) -#define PHY_CSR3_REGNUM FIELD32(0x00007f00) -#define PHY_CSR3_READ_CONTROL FIELD32(0x00008000) -#define PHY_CSR3_BUSY FIELD32(0x00010000) - -/* - * PHY_CSR4: RF serial control register - * VALUE: Register value (include register id) serial out to RF/IF chip. - * NUMBER_OF_BITS: Number of bits used in RFRegValue (I:20, RFMD:22). - * IF_SELECT: 1: select IF to program, 0: select RF to program. - * PLL_LD: RF PLL_LD status. - * BUSY: 1: ASIC is busy execute RF programming. - */ -#define PHY_CSR4 0x3090 -#define PHY_CSR4_VALUE FIELD32(0x00ffffff) -#define PHY_CSR4_NUMBER_OF_BITS FIELD32(0x1f000000) -#define PHY_CSR4_IF_SELECT FIELD32(0x20000000) -#define PHY_CSR4_PLL_LD FIELD32(0x40000000) -#define PHY_CSR4_BUSY FIELD32(0x80000000) - -/* - * PHY_CSR5: RX to TX signal switch timing control. - */ -#define PHY_CSR5 0x3094 -#define PHY_CSR5_IQ_FLIP FIELD32(0x00000004) - -/* - * PHY_CSR6: TX to RX signal timing control. - */ -#define PHY_CSR6 0x3098 -#define PHY_CSR6_IQ_FLIP FIELD32(0x00000004) - -/* - * PHY_CSR7: TX DAC switching timing control. - */ -#define PHY_CSR7 0x309c - -/* - * Security control register. - */ - -/* - * SEC_CSR0: Shared key table control. - */ -#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. - */ -#define SEC_CSR1 0x30a4 -#define SEC_CSR1_BSS0_KEY0_CIPHER_ALG FIELD32(0x00000007) -#define SEC_CSR1_BSS0_KEY1_CIPHER_ALG FIELD32(0x00000070) -#define SEC_CSR1_BSS0_KEY2_CIPHER_ALG FIELD32(0x00000700) -#define SEC_CSR1_BSS0_KEY3_CIPHER_ALG FIELD32(0x00007000) -#define SEC_CSR1_BSS1_KEY0_CIPHER_ALG FIELD32(0x00070000) -#define SEC_CSR1_BSS1_KEY1_CIPHER_ALG FIELD32(0x00700000) -#define SEC_CSR1_BSS1_KEY2_CIPHER_ALG FIELD32(0x07000000) -#define SEC_CSR1_BSS1_KEY3_CIPHER_ALG FIELD32(0x70000000) - -/* - * Pairwise key table valid bitmap registers. - * SEC_CSR2: pairwise key table valid bitmap 0. - * SEC_CSR3: pairwise key table valid bitmap 1. - */ -#define SEC_CSR2 0x30a8 -#define SEC_CSR3 0x30ac - -/* - * SEC_CSR4: Pairwise key table lookup control. - */ -#define SEC_CSR4 0x30b0 -#define SEC_CSR4_ENABLE_BSS0 FIELD32(0x00000001) -#define SEC_CSR4_ENABLE_BSS1 FIELD32(0x00000002) -#define SEC_CSR4_ENABLE_BSS2 FIELD32(0x00000004) -#define SEC_CSR4_ENABLE_BSS3 FIELD32(0x00000008) - -/* - * SEC_CSR5: shared key table security mode register. - */ -#define SEC_CSR5 0x30b4 -#define SEC_CSR5_BSS2_KEY0_CIPHER_ALG FIELD32(0x00000007) -#define SEC_CSR5_BSS2_KEY1_CIPHER_ALG FIELD32(0x00000070) -#define SEC_CSR5_BSS2_KEY2_CIPHER_ALG FIELD32(0x00000700) -#define SEC_CSR5_BSS2_KEY3_CIPHER_ALG FIELD32(0x00007000) -#define SEC_CSR5_BSS3_KEY0_CIPHER_ALG FIELD32(0x00070000) -#define SEC_CSR5_BSS3_KEY1_CIPHER_ALG FIELD32(0x00700000) -#define SEC_CSR5_BSS3_KEY2_CIPHER_ALG FIELD32(0x07000000) -#define SEC_CSR5_BSS3_KEY3_CIPHER_ALG FIELD32(0x70000000) - -/* - * STA control registers. - */ - -/* - * STA_CSR0: RX PLCP error count & RX FCS error count. - */ -#define STA_CSR0 0x30c0 -#define STA_CSR0_FCS_ERROR FIELD32(0x0000ffff) -#define STA_CSR0_PLCP_ERROR FIELD32(0xffff0000) - -/* - * STA_CSR1: RX False CCA count & RX LONG frame count. - */ -#define STA_CSR1 0x30c4 -#define STA_CSR1_PHYSICAL_ERROR FIELD32(0x0000ffff) -#define STA_CSR1_FALSE_CCA_ERROR FIELD32(0xffff0000) - -/* - * STA_CSR2: TX Beacon count and RX FIFO overflow count. - */ -#define STA_CSR2 0x30c8 -#define STA_CSR2_RX_FIFO_OVERFLOW_COUNT FIELD32(0x0000ffff) -#define STA_CSR2_RX_OVERFLOW_COUNT FIELD32(0xffff0000) - -/* - * STA_CSR3: TX Beacon count. - */ -#define STA_CSR3 0x30cc -#define STA_CSR3_TX_BEACON_COUNT FIELD32(0x0000ffff) - -/* - * STA_CSR4: TX Retry count. - */ -#define STA_CSR4 0x30d0 -#define STA_CSR4_TX_NO_RETRY_COUNT FIELD32(0x0000ffff) -#define STA_CSR4_TX_ONE_RETRY_COUNT FIELD32(0xffff0000) - -/* - * STA_CSR5: TX Retry count. - */ -#define STA_CSR5 0x30d4 -#define STA_CSR4_TX_MULTI_RETRY_COUNT FIELD32(0x0000ffff) -#define STA_CSR4_TX_RETRY_FAIL_COUNT FIELD32(0xffff0000) - -/* - * QOS control registers. - */ - -/* - * QOS_CSR1: TXOP holder MAC address register. - */ -#define QOS_CSR1 0x30e4 -#define QOS_CSR1_BYTE4 FIELD32(0x000000ff) -#define QOS_CSR1_BYTE5 FIELD32(0x0000ff00) - -/* - * QOS_CSR2: TXOP holder timeout register. - */ -#define QOS_CSR2 0x30e8 - -/* - * RX QOS-CFPOLL MAC address register. - * QOS_CSR3: RX QOS-CFPOLL MAC address 0. - * QOS_CSR4: RX QOS-CFPOLL MAC address 1. - */ -#define QOS_CSR3 0x30ec -#define QOS_CSR4 0x30f0 - -/* - * QOS_CSR5: "QosControl" field of the RX QOS-CFPOLL. - */ -#define QOS_CSR5 0x30f4 - -/* - * WMM Scheduler Register - */ - -/* - * AIFSN_CSR: AIFSN for each EDCA AC. - * AIFSN0: For AC_BK. - * AIFSN1: For AC_BE. - * AIFSN2: For AC_VI. - * AIFSN3: For AC_VO. - */ -#define AIFSN_CSR 0x0400 -#define AIFSN_CSR_AIFSN0 FIELD32(0x0000000f) -#define AIFSN_CSR_AIFSN1 FIELD32(0x000000f0) -#define AIFSN_CSR_AIFSN2 FIELD32(0x00000f00) -#define AIFSN_CSR_AIFSN3 FIELD32(0x0000f000) - -/* - * CWMIN_CSR: CWmin for each EDCA AC. - * CWMIN0: For AC_BK. - * CWMIN1: For AC_BE. - * CWMIN2: For AC_VI. - * CWMIN3: For AC_VO. - */ -#define CWMIN_CSR 0x0404 -#define CWMIN_CSR_CWMIN0 FIELD32(0x0000000f) -#define CWMIN_CSR_CWMIN1 FIELD32(0x000000f0) -#define CWMIN_CSR_CWMIN2 FIELD32(0x00000f00) -#define CWMIN_CSR_CWMIN3 FIELD32(0x0000f000) - -/* - * CWMAX_CSR: CWmax for each EDCA AC. - * CWMAX0: For AC_BK. - * CWMAX1: For AC_BE. - * CWMAX2: For AC_VI. - * CWMAX3: For AC_VO. - */ -#define CWMAX_CSR 0x0408 -#define CWMAX_CSR_CWMAX0 FIELD32(0x0000000f) -#define CWMAX_CSR_CWMAX1 FIELD32(0x000000f0) -#define CWMAX_CSR_CWMAX2 FIELD32(0x00000f00) -#define CWMAX_CSR_CWMAX3 FIELD32(0x0000f000) - -/* - * AC_TXOP_CSR0: AC_BK/AC_BE TXOP register. - * AC0_TX_OP: For AC_BK, in unit of 32us. - * AC1_TX_OP: For AC_BE, in unit of 32us. - */ -#define AC_TXOP_CSR0 0x040c -#define AC_TXOP_CSR0_AC0_TX_OP FIELD32(0x0000ffff) -#define AC_TXOP_CSR0_AC1_TX_OP FIELD32(0xffff0000) - -/* - * AC_TXOP_CSR1: AC_VO/AC_VI TXOP register. - * AC2_TX_OP: For AC_VI, in unit of 32us. - * AC3_TX_OP: For AC_VO, in unit of 32us. - */ -#define AC_TXOP_CSR1 0x0410 -#define AC_TXOP_CSR1_AC2_TX_OP FIELD32(0x0000ffff) -#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) - */ - -/* - * ANTENNA_CONTROL semantics (guessed): - * 0x1: Software controlled antenna switching (fixed or SW diversity) - * 0x2: Hardware diversity. - */ -#define BBP_R4_RX_ANTENNA_CONTROL FIELD8(0x03) -#define BBP_R4_RX_FRAME_END FIELD8(0x20) - -/* - * R77 - */ -#define BBP_R77_RX_ANTENNA FIELD8(0x03) - -/* - * RF registers - */ - -/* - * RF 3 - */ -#define RF3_TXPOWER FIELD32(0x00003e00) - -/* - * RF 4 - */ -#define RF4_FREQ_OFFSET FIELD32(0x0003f000) - -/* - * EEPROM content. - * The wordsize of the EEPROM is 16 bits. - */ - -/* - * HW MAC address. - */ -#define EEPROM_MAC_ADDR_0 0x0002 -#define EEPROM_MAC_ADDR_BYTE0 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE1 FIELD16(0xff00) -#define EEPROM_MAC_ADDR1 0x0003 -#define EEPROM_MAC_ADDR_BYTE2 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE3 FIELD16(0xff00) -#define EEPROM_MAC_ADDR_2 0x0004 -#define EEPROM_MAC_ADDR_BYTE4 FIELD16(0x00ff) -#define EEPROM_MAC_ADDR_BYTE5 FIELD16(0xff00) - -/* - * EEPROM antenna. - * ANTENNA_NUM: Number of antennas. - * TX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * RX_DEFAULT: Default antenna 0: diversity, 1: A, 2: B. - * FRAME_TYPE: 0: DPDT , 1: SPDT , noted this bit is valid for g only. - * DYN_TXAGC: Dynamic TX AGC control. - * HARDWARE_RADIO: 1: Hardware controlled radio. Read GPIO0. - * RF_TYPE: Rf_type of this adapter. - */ -#define EEPROM_ANTENNA 0x0010 -#define EEPROM_ANTENNA_NUM FIELD16(0x0003) -#define EEPROM_ANTENNA_TX_DEFAULT FIELD16(0x000c) -#define EEPROM_ANTENNA_RX_DEFAULT FIELD16(0x0030) -#define EEPROM_ANTENNA_FRAME_TYPE FIELD16(0x0040) -#define EEPROM_ANTENNA_DYN_TXAGC FIELD16(0x0200) -#define EEPROM_ANTENNA_HARDWARE_RADIO FIELD16(0x0400) -#define EEPROM_ANTENNA_RF_TYPE FIELD16(0xf800) - -/* - * EEPROM NIC config. - * EXTERNAL_LNA: External LNA. - */ -#define EEPROM_NIC 0x0011 -#define EEPROM_NIC_EXTERNAL_LNA FIELD16(0x0010) - -/* - * EEPROM geography. - * GEO_A: Default geographical setting for 5GHz band - * GEO: Default geographical setting. - */ -#define EEPROM_GEOGRAPHY 0x0012 -#define EEPROM_GEOGRAPHY_GEO_A FIELD16(0x00ff) -#define EEPROM_GEOGRAPHY_GEO FIELD16(0xff00) - -/* - * EEPROM BBP. - */ -#define EEPROM_BBP_START 0x0013 -#define EEPROM_BBP_SIZE 16 -#define EEPROM_BBP_VALUE FIELD16(0x00ff) -#define EEPROM_BBP_REG_ID FIELD16(0xff00) - -/* - * EEPROM TXPOWER 802.11G - */ -#define EEPROM_TXPOWER_G_START 0x0023 -#define EEPROM_TXPOWER_G_SIZE 7 -#define EEPROM_TXPOWER_G_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_G_2 FIELD16(0xff00) - -/* - * EEPROM Frequency - */ -#define EEPROM_FREQ 0x002f -#define EEPROM_FREQ_OFFSET FIELD16(0x00ff) -#define EEPROM_FREQ_SEQ_MASK FIELD16(0xff00) -#define EEPROM_FREQ_SEQ FIELD16(0x0300) - -/* - * EEPROM LED. - * POLARITY_RDY_G: Polarity RDY_G setting. - * POLARITY_RDY_A: Polarity RDY_A setting. - * POLARITY_ACT: Polarity ACT setting. - * POLARITY_GPIO_0: Polarity GPIO0 setting. - * POLARITY_GPIO_1: Polarity GPIO1 setting. - * POLARITY_GPIO_2: Polarity GPIO2 setting. - * POLARITY_GPIO_3: Polarity GPIO3 setting. - * POLARITY_GPIO_4: Polarity GPIO4 setting. - * LED_MODE: Led mode. - */ -#define EEPROM_LED 0x0030 -#define EEPROM_LED_POLARITY_RDY_G FIELD16(0x0001) -#define EEPROM_LED_POLARITY_RDY_A FIELD16(0x0002) -#define EEPROM_LED_POLARITY_ACT FIELD16(0x0004) -#define EEPROM_LED_POLARITY_GPIO_0 FIELD16(0x0008) -#define EEPROM_LED_POLARITY_GPIO_1 FIELD16(0x0010) -#define EEPROM_LED_POLARITY_GPIO_2 FIELD16(0x0020) -#define EEPROM_LED_POLARITY_GPIO_3 FIELD16(0x0040) -#define EEPROM_LED_POLARITY_GPIO_4 FIELD16(0x0080) -#define EEPROM_LED_LED_MODE FIELD16(0x1f00) - -/* - * EEPROM TXPOWER 802.11A - */ -#define EEPROM_TXPOWER_A_START 0x0031 -#define EEPROM_TXPOWER_A_SIZE 12 -#define EEPROM_TXPOWER_A_1 FIELD16(0x00ff) -#define EEPROM_TXPOWER_A_2 FIELD16(0xff00) - -/* - * EEPROM RSSI offset 802.11BG - */ -#define EEPROM_RSSI_OFFSET_BG 0x004d -#define EEPROM_RSSI_OFFSET_BG_1 FIELD16(0x00ff) -#define EEPROM_RSSI_OFFSET_BG_2 FIELD16(0xff00) - -/* - * EEPROM RSSI offset 802.11A - */ -#define EEPROM_RSSI_OFFSET_A 0x004e -#define EEPROM_RSSI_OFFSET_A_1 FIELD16(0x00ff) -#define EEPROM_RSSI_OFFSET_A_2 FIELD16(0xff00) - -/* - * DMA descriptor defines. - */ -#define TXD_DESC_SIZE ( 6 * sizeof(__le32) ) -#define TXINFO_SIZE ( 6 * sizeof(__le32) ) -#define RXD_DESC_SIZE ( 6 * sizeof(__le32) ) - -/* - * TX descriptor format for TX, PRIO and Beacon Ring. - */ - -/* - * Word0 - * BURST: Next frame belongs to same "burst" event. - * TKIP_MIC: ASIC appends TKIP MIC if TKIP is used. - * KEY_TABLE: Use per-client pairwise KEY table. - * KEY_INDEX: - * Key index (0~31) to the pairwise KEY table. - * 0~3 to shared KEY table 0 (BSS0). - * 4~7 to shared KEY table 1 (BSS1). - * 8~11 to shared KEY table 2 (BSS2). - * 12~15 to shared KEY table 3 (BSS3). - * BURST2: For backward compatibility, set to same value as BURST. - */ -#define TXD_W0_BURST FIELD32(0x00000001) -#define TXD_W0_VALID FIELD32(0x00000002) -#define TXD_W0_MORE_FRAG FIELD32(0x00000004) -#define TXD_W0_ACK FIELD32(0x00000008) -#define TXD_W0_TIMESTAMP FIELD32(0x00000010) -#define TXD_W0_OFDM FIELD32(0x00000020) -#define TXD_W0_IFS FIELD32(0x00000040) -#define TXD_W0_RETRY_MODE FIELD32(0x00000080) -#define TXD_W0_TKIP_MIC FIELD32(0x00000100) -#define TXD_W0_KEY_TABLE FIELD32(0x00000200) -#define TXD_W0_KEY_INDEX FIELD32(0x0000fc00) -#define TXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define TXD_W0_BURST2 FIELD32(0x10000000) -#define TXD_W0_CIPHER_ALG FIELD32(0xe0000000) - -/* - * Word1 - * HOST_Q_ID: EDCA/HCCA queue ID. - * HW_SEQUENCE: MAC overwrites the frame sequence number. - * BUFFER_COUNT: Number of buffers in this TXD. - */ -#define TXD_W1_HOST_Q_ID FIELD32(0x0000000f) -#define TXD_W1_AIFSN FIELD32(0x000000f0) -#define TXD_W1_CWMIN FIELD32(0x00000f00) -#define TXD_W1_CWMAX FIELD32(0x0000f000) -#define TXD_W1_IV_OFFSET FIELD32(0x003f0000) -#define TXD_W1_HW_SEQUENCE FIELD32(0x10000000) -#define TXD_W1_BUFFER_COUNT FIELD32(0xe0000000) - -/* - * Word2: PLCP information - */ -#define TXD_W2_PLCP_SIGNAL FIELD32(0x000000ff) -#define TXD_W2_PLCP_SERVICE FIELD32(0x0000ff00) -#define TXD_W2_PLCP_LENGTH_LOW FIELD32(0x00ff0000) -#define TXD_W2_PLCP_LENGTH_HIGH FIELD32(0xff000000) - -/* - * Word3 - */ -#define TXD_W3_IV FIELD32(0xffffffff) - -/* - * Word4 - */ -#define TXD_W4_EIV FIELD32(0xffffffff) - -/* - * Word5 - * FRAME_OFFSET: Frame start offset inside ASIC TXFIFO (after TXINFO field). - * PACKET_ID: Driver assigned packet ID to categorize TXResult in interrupt. - * WAITING_DMA_DONE_INT: TXD been filled with data - * and waiting for TxDoneISR housekeeping. - */ -#define TXD_W5_FRAME_OFFSET FIELD32(0x000000ff) -#define TXD_W5_PACKET_ID FIELD32(0x0000ff00) -#define TXD_W5_TX_POWER FIELD32(0x00ff0000) -#define TXD_W5_WAITING_DMA_DONE_INT FIELD32(0x01000000) - -/* - * RX descriptor format for RX Ring. - */ - -/* - * Word0 - * CIPHER_ERROR: 1:ICV error, 2:MIC error, 3:invalid key. - * KEY_INDEX: Decryption key actually used. - */ -#define RXD_W0_OWNER_NIC FIELD32(0x00000001) -#define RXD_W0_DROP FIELD32(0x00000002) -#define RXD_W0_UNICAST_TO_ME FIELD32(0x00000004) -#define RXD_W0_MULTICAST FIELD32(0x00000008) -#define RXD_W0_BROADCAST FIELD32(0x00000010) -#define RXD_W0_MY_BSS FIELD32(0x00000020) -#define RXD_W0_CRC_ERROR FIELD32(0x00000040) -#define RXD_W0_OFDM FIELD32(0x00000080) -#define RXD_W0_CIPHER_ERROR FIELD32(0x00000300) -#define RXD_W0_KEY_INDEX FIELD32(0x0000fc00) -#define RXD_W0_DATABYTE_COUNT FIELD32(0x0fff0000) -#define RXD_W0_CIPHER_ALG FIELD32(0xe0000000) - -/* - * WORD1 - * SIGNAL: RX raw data rate reported by BBP. - * RSSI: RSSI reported by BBP. - */ -#define RXD_W1_SIGNAL FIELD32(0x000000ff) -#define RXD_W1_RSSI_AGC FIELD32(0x00001f00) -#define RXD_W1_RSSI_LNA FIELD32(0x00006000) -#define RXD_W1_FRAME_OFFSET FIELD32(0x7f000000) - -/* - * Word2 - * IV: Received IV of originally encrypted. - */ -#define RXD_W2_IV FIELD32(0xffffffff) - -/* - * Word3 - * EIV: Received EIV of originally encrypted. - */ -#define RXD_W3_EIV FIELD32(0xffffffff) - -/* - * Word4 - * ICV: Received ICV of originally encrypted. - * NOTE: This is a guess, the official definition is "reserved" - */ -#define RXD_W4_ICV FIELD32(0xffffffff) - -/* - * the above 20-byte is called RXINFO and will be DMAed to MAC RX block - * and passed to the HOST driver. - * The following fields are for DMA block and HOST usage only. - * Can't be touched by ASIC MAC block. - */ - -/* - * Word5 - */ -#define RXD_W5_RESERVED FIELD32(0xffffffff) - -/* - * Macros for converting txpower from EEPROM to mac80211 value - * and from mac80211 value to register value. - */ -#define MIN_TXPOWER 0 -#define MAX_TXPOWER 31 -#define DEFAULT_TXPOWER 24 - -#define TXPOWER_FROM_DEV(__txpower) \ - (((u8)(__txpower)) > MAX_TXPOWER) ? DEFAULT_TXPOWER : (__txpower) - -#define TXPOWER_TO_DEV(__txpower) \ - clamp_t(char, __txpower, MIN_TXPOWER, MAX_TXPOWER) - -#endif /* RT73USB_H */ diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile deleted file mode 100644 index 93cbfbedb46d..000000000000 --- a/drivers/net/wireless/rtl818x/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o -rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o rtl8187_rfkill.o - -obj-$(CONFIG_RTL8180) += rtl8180.o -obj-$(CONFIG_RTL8187) += rtl8187.o - - diff --git a/drivers/net/wireless/rtl818x/rtl8180.h b/drivers/net/wireless/rtl818x/rtl8180.h deleted file mode 100644 index 8721282a8185..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef RTL8180_H -#define RTL8180_H - -#include "rtl818x.h" - -#define MAX_RX_SIZE IEEE80211_MAX_RTS_THRESHOLD - -#define RF_PARAM_ANALOGPHY (1 << 0) -#define RF_PARAM_ANTBDEFAULT (1 << 1) -#define RF_PARAM_CARRIERSENSE1 (1 << 2) -#define RF_PARAM_CARRIERSENSE2 (1 << 3) - -#define BB_ANTATTEN_CHAN14 0x0C -#define BB_ANTENNA_B 0x40 - -#define BB_HOST_BANG (1 << 30) -#define BB_HOST_BANG_EN (1 << 2) -#define BB_HOST_BANG_CLK (1 << 1) -#define BB_HOST_BANG_DATA 1 - -#define ANAPARAM_TXDACOFF_SHIFT 27 -#define ANAPARAM_PWR0_SHIFT 28 -#define ANAPARAM_PWR0_MASK (0x07 << ANAPARAM_PWR0_SHIFT) -#define ANAPARAM_PWR1_SHIFT 20 -#define ANAPARAM_PWR1_MASK (0x7F << ANAPARAM_PWR1_SHIFT) - -struct rtl8180_tx_desc { - __le32 flags; - __le16 rts_duration; - __le16 plcp_len; - __le32 tx_buf; - __le32 frame_len; - __le32 next_tx_desc; - u8 cw; - u8 retry_limit; - u8 agc; - u8 flags2; - u32 reserved[2]; -} __attribute__ ((packed)); - -struct rtl8180_rx_desc { - __le32 flags; - __le32 flags2; - union { - __le32 rx_buf; - __le64 tsft; - }; -} __attribute__ ((packed)); - -struct rtl8180_tx_ring { - struct rtl8180_tx_desc *desc; - dma_addr_t dma; - unsigned int idx; - unsigned int entries; - struct sk_buff_head queue; -}; - -struct rtl8180_priv { - /* common between rtl818x drivers */ - struct rtl818x_csr __iomem *map; - const struct rtl818x_rf_ops *rf; - struct ieee80211_vif *vif; - int mode; - - /* rtl8180 driver specific */ - spinlock_t lock; - struct rtl8180_rx_desc *rx_ring; - dma_addr_t rx_ring_dma; - unsigned int rx_idx; - struct sk_buff *rx_buf[32]; - struct rtl8180_tx_ring tx_ring[4]; - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_supported_band band; - struct pci_dev *pdev; - u32 rx_conf; - - int r8185; - u32 anaparam; - u16 rfparam; - u8 csthreshold; -}; - -void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); -void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam); - -static inline u8 rtl818x_ioread8(struct rtl8180_priv *priv, u8 __iomem *addr) -{ - return ioread8(addr); -} - -static inline u16 rtl818x_ioread16(struct rtl8180_priv *priv, __le16 __iomem *addr) -{ - return ioread16(addr); -} - -static inline u32 rtl818x_ioread32(struct rtl8180_priv *priv, __le32 __iomem *addr) -{ - return ioread32(addr); -} - -static inline void rtl818x_iowrite8(struct rtl8180_priv *priv, - u8 __iomem *addr, u8 val) -{ - iowrite8(val, addr); -} - -static inline void rtl818x_iowrite16(struct rtl8180_priv *priv, - __le16 __iomem *addr, u16 val) -{ - iowrite16(val, addr); -} - -static inline void rtl818x_iowrite32(struct rtl8180_priv *priv, - __le32 __iomem *addr, u32 val) -{ - iowrite32(val, addr); -} - -#endif /* RTL8180_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_dev.c b/drivers/net/wireless/rtl818x/rtl8180_dev.c deleted file mode 100644 index c6ca7ee16e84..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_dev.c +++ /dev/null @@ -1,1098 +0,0 @@ - -/* - * Linux device driver for RTL8180 / RTL8185 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8180 driver, which is: - * Copyright 2004-2005 Andrea Merello , et al. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8180_rtl8225.h" -#include "rtl8180_sa2400.h" -#include "rtl8180_max2820.h" -#include "rtl8180_grf5101.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_AUTHOR("Andrea Merello "); -MODULE_DESCRIPTION("RTL8180 / RTL8185 PCI wireless driver"); -MODULE_LICENSE("GPL"); - -static struct pci_device_id rtl8180_table[] __devinitdata = { - /* rtl8185 */ - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8185) }, - { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x700f) }, - { PCI_DEVICE(PCI_VENDOR_ID_BELKIN, 0x701f) }, - - /* rtl8180 */ - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8180) }, - { PCI_DEVICE(0x1799, 0x6001) }, - { PCI_DEVICE(0x1799, 0x6020) }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x3300) }, - { } -}; - -MODULE_DEVICE_TABLE(pci, rtl8180_table); - -static const struct ieee80211_rate rtl818x_rates[] = { - { .bitrate = 10, .hw_value = 0, }, - { .bitrate = 20, .hw_value = 1, }, - { .bitrate = 55, .hw_value = 2, }, - { .bitrate = 110, .hw_value = 3, }, - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -static const struct ieee80211_channel rtl818x_channels[] = { - { .center_freq = 2412 }, - { .center_freq = 2417 }, - { .center_freq = 2422 }, - { .center_freq = 2427 }, - { .center_freq = 2432 }, - { .center_freq = 2437 }, - { .center_freq = 2442 }, - { .center_freq = 2447 }, - { .center_freq = 2452 }, - { .center_freq = 2457 }, - { .center_freq = 2462 }, - { .center_freq = 2467 }, - { .center_freq = 2472 }, - { .center_freq = 2484 }, -}; - - - - -void rtl8180_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - int i = 10; - u32 buf; - - buf = (data << 8) | addr; - - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf | 0x80); - while (i--) { - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->PHY[0], buf); - if (rtl818x_ioread8(priv, &priv->map->PHY[2]) == (data & 0xFF)) - return; - } -} - -static void rtl8180_handle_rx(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - unsigned int count = 32; - - while (count--) { - struct rtl8180_rx_desc *entry = &priv->rx_ring[priv->rx_idx]; - struct sk_buff *skb = priv->rx_buf[priv->rx_idx]; - u32 flags = le32_to_cpu(entry->flags); - - if (flags & RTL818X_RX_DESC_FLAG_OWN) - return; - - if (unlikely(flags & (RTL818X_RX_DESC_FLAG_DMA_FAIL | - RTL818X_RX_DESC_FLAG_FOF | - RTL818X_RX_DESC_FLAG_RX_ERR))) - goto done; - else { - u32 flags2 = le32_to_cpu(entry->flags2); - struct ieee80211_rx_status rx_status = {0}; - struct sk_buff *new_skb = dev_alloc_skb(MAX_RX_SIZE); - - if (unlikely(!new_skb)) - goto done; - - pci_unmap_single(priv->pdev, - *((dma_addr_t *)skb->cb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - skb_put(skb, flags & 0xFFF); - - rx_status.antenna = (flags2 >> 15) & 1; - /* TODO: improve signal/rssi reporting */ - rx_status.qual = flags2 & 0xFF; - rx_status.signal = (flags2 >> 8) & 0x7F; - /* XXX: is this correct? */ - rx_status.rate_idx = (flags >> 20) & 0xF; - rx_status.freq = dev->conf.channel->center_freq; - rx_status.band = dev->conf.channel->band; - rx_status.mactime = le64_to_cpu(entry->tsft); - rx_status.flag |= RX_FLAG_TSFT; - if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(dev, skb); - - skb = new_skb; - priv->rx_buf[priv->rx_idx] = skb; - *((dma_addr_t *) skb->cb) = - pci_map_single(priv->pdev, skb_tail_pointer(skb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - } - - done: - entry->rx_buf = cpu_to_le32(*((dma_addr_t *)skb->cb)); - entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | - MAX_RX_SIZE); - if (priv->rx_idx == 31) - entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); - priv->rx_idx = (priv->rx_idx + 1) % 32; - } -} - -static void rtl8180_handle_tx(struct ieee80211_hw *dev, unsigned int prio) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - u32 flags = le32_to_cpu(entry->flags); - - if (flags & RTL818X_TX_DESC_FLAG_OWN) - return; - - ring->idx = (ring->idx + 1) % ring->entries; - skb = __skb_dequeue(&ring->queue); - pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), - skb->len, PCI_DMA_TODEVICE); - - info = IEEE80211_SKB_CB(skb); - ieee80211_tx_info_clear_status(info); - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (flags & RTL818X_TX_DESC_FLAG_TX_OK)) - info->flags |= IEEE80211_TX_STAT_ACK; - - info->status.rates[0].count = (flags & 0xFF) + 1; - info->status.rates[1].idx = -1; - - ieee80211_tx_status_irqsafe(dev, skb); - if (ring->entries - skb_queue_len(&ring->queue) == 2) - ieee80211_wake_queue(dev, prio); - } -} - -static irqreturn_t rtl8180_interrupt(int irq, void *dev_id) -{ - struct ieee80211_hw *dev = dev_id; - struct rtl8180_priv *priv = dev->priv; - u16 reg; - - spin_lock(&priv->lock); - reg = rtl818x_ioread16(priv, &priv->map->INT_STATUS); - if (unlikely(reg == 0xFFFF)) { - spin_unlock(&priv->lock); - return IRQ_HANDLED; - } - - rtl818x_iowrite16(priv, &priv->map->INT_STATUS, reg); - - if (reg & (RTL818X_INT_TXB_OK | RTL818X_INT_TXB_ERR)) - rtl8180_handle_tx(dev, 3); - - if (reg & (RTL818X_INT_TXH_OK | RTL818X_INT_TXH_ERR)) - rtl8180_handle_tx(dev, 2); - - if (reg & (RTL818X_INT_TXN_OK | RTL818X_INT_TXN_ERR)) - rtl8180_handle_tx(dev, 1); - - if (reg & (RTL818X_INT_TXL_OK | RTL818X_INT_TXL_ERR)) - rtl8180_handle_tx(dev, 0); - - if (reg & (RTL818X_INT_RX_OK | RTL818X_INT_RX_ERR)) - rtl8180_handle_rx(dev); - - spin_unlock(&priv->lock); - - return IRQ_HANDLED; -} - -static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring; - struct rtl8180_tx_desc *entry; - unsigned long flags; - unsigned int idx, prio; - dma_addr_t mapping; - u32 tx_flags; - u8 rc_flags; - u16 plcp_len = 0; - __le16 rts_duration = 0; - - prio = skb_get_queue_mapping(skb); - ring = &priv->tx_ring[prio]; - - mapping = pci_map_single(priv->pdev, skb->data, - skb->len, PCI_DMA_TODEVICE); - - tx_flags = RTL818X_TX_DESC_FLAG_OWN | RTL818X_TX_DESC_FLAG_FS | - RTL818X_TX_DESC_FLAG_LS | - (ieee80211_get_tx_rate(dev, info)->hw_value << 24) | - skb->len; - - if (priv->r8185) - tx_flags |= RTL818X_TX_DESC_FLAG_DMA | - RTL818X_TX_DESC_FLAG_NO_ENC; - - rc_flags = info->control.rates[0].flags; - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) { - tx_flags |= RTL818X_TX_DESC_FLAG_RTS; - tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - tx_flags |= RTL818X_TX_DESC_FLAG_CTS; - tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } - - if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) - rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len, - info); - - if (!priv->r8185) { - unsigned int remainder; - - plcp_len = DIV_ROUND_UP(16 * (skb->len + 4), - (ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10); - remainder = (16 * (skb->len + 4)) % - ((ieee80211_get_tx_rate(dev, info)->bitrate * 2) / 10); - if (remainder <= 6) - plcp_len |= 1 << 15; - } - - spin_lock_irqsave(&priv->lock, flags); - idx = (ring->idx + skb_queue_len(&ring->queue)) % ring->entries; - entry = &ring->desc[idx]; - - entry->rts_duration = rts_duration; - entry->plcp_len = cpu_to_le16(plcp_len); - entry->tx_buf = cpu_to_le32(mapping); - entry->frame_len = cpu_to_le32(skb->len); - entry->flags2 = info->control.rates[1].idx >= 0 ? - ieee80211_get_alt_retry_rate(dev, info, 0)->bitrate << 4 : 0; - entry->retry_limit = info->control.rates[0].count; - entry->flags = cpu_to_le32(tx_flags); - __skb_queue_tail(&ring->queue, skb); - if (ring->entries - skb_queue_len(&ring->queue) < 2) - ieee80211_stop_queue(dev, skb_get_queue_mapping(skb)); - spin_unlock_irqrestore(&priv->lock, flags); - - rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4))); - - return 0; -} - -void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam) -{ - u8 reg; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, anaparam); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); -} - -static int rtl8180_init_hw(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg; - - rtl818x_iowrite8(priv, &priv->map->CMD, 0); - rtl818x_ioread8(priv, &priv->map->CMD); - msleep(10); - - /* reset */ - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - rtl818x_ioread8(priv, &priv->map->CMD); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= (1 << 1); - reg |= RTL818X_CMD_RESET; - rtl818x_iowrite8(priv, &priv->map->CMD, RTL818X_CMD_RESET); - rtl818x_ioread8(priv, &priv->map->CMD); - msleep(200); - - /* check success of reset */ - if (rtl818x_ioread8(priv, &priv->map->CMD) & RTL818X_CMD_RESET) { - printk(KERN_ERR "%s: reset timeout!\n", wiphy_name(dev->wiphy)); - return -ETIMEDOUT; - } - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); - rtl818x_ioread8(priv, &priv->map->CMD); - msleep(200); - - if (rtl818x_ioread8(priv, &priv->map->CONFIG3) & (1 << 3)) { - /* For cardbus */ - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= 1 << 1; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - reg = rtl818x_ioread16(priv, &priv->map->FEMR); - reg |= (1 << 15) | (1 << 14) | (1 << 4); - rtl818x_iowrite16(priv, &priv->map->FEMR, reg); - } - - rtl818x_iowrite8(priv, &priv->map->MSR, 0); - - if (!priv->r8185) - rtl8180_set_anaparam(priv, priv->anaparam); - - rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); - rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma); - rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma); - rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma); - rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma); - - /* TODO: necessary? specs indicate not */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); - rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg & ~(1 << 3)); - if (priv->r8185) { - reg = rtl818x_ioread8(priv, &priv->map->CONFIG2); - rtl818x_iowrite8(priv, &priv->map->CONFIG2, reg | (1 << 4)); - } - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - /* TODO: set CONFIG5 for calibrating AGC on rtl8180 + philips radio? */ - - /* TODO: turn off hw wep on rtl8180 */ - - rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); - - if (priv->r8185) { - rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0x81); - rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); - - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); - - /* TODO: set ClkRun enable? necessary? */ - reg = rtl818x_ioread8(priv, &priv->map->GP_ENABLE); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, reg & ~(1 << 6)); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | (1 << 2)); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - } else { - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x1); - rtl818x_iowrite8(priv, &priv->map->SECURITY, 0); - - rtl818x_iowrite8(priv, &priv->map->PHY_DELAY, 0x6); - rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, 0x4C); - } - - priv->rf->init(dev); - if (priv->r8185) - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); - return 0; -} - -static int rtl8180_init_rx_ring(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_rx_desc *entry; - int i; - - priv->rx_ring = pci_alloc_consistent(priv->pdev, - sizeof(*priv->rx_ring) * 32, - &priv->rx_ring_dma); - - if (!priv->rx_ring || (unsigned long)priv->rx_ring & 0xFF) { - printk(KERN_ERR "%s: Cannot allocate RX ring\n", - wiphy_name(dev->wiphy)); - return -ENOMEM; - } - - memset(priv->rx_ring, 0, sizeof(*priv->rx_ring) * 32); - priv->rx_idx = 0; - - for (i = 0; i < 32; i++) { - struct sk_buff *skb = dev_alloc_skb(MAX_RX_SIZE); - dma_addr_t *mapping; - entry = &priv->rx_ring[i]; - if (!skb) - return 0; - - priv->rx_buf[i] = skb; - mapping = (dma_addr_t *)skb->cb; - *mapping = pci_map_single(priv->pdev, skb_tail_pointer(skb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - entry->rx_buf = cpu_to_le32(*mapping); - entry->flags = cpu_to_le32(RTL818X_RX_DESC_FLAG_OWN | - MAX_RX_SIZE); - } - entry->flags |= cpu_to_le32(RTL818X_RX_DESC_FLAG_EOR); - return 0; -} - -static void rtl8180_free_rx_ring(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - for (i = 0; i < 32; i++) { - struct sk_buff *skb = priv->rx_buf[i]; - if (!skb) - continue; - - pci_unmap_single(priv->pdev, - *((dma_addr_t *)skb->cb), - MAX_RX_SIZE, PCI_DMA_FROMDEVICE); - kfree_skb(skb); - } - - pci_free_consistent(priv->pdev, sizeof(*priv->rx_ring) * 32, - priv->rx_ring, priv->rx_ring_dma); - priv->rx_ring = NULL; -} - -static int rtl8180_init_tx_ring(struct ieee80211_hw *dev, - unsigned int prio, unsigned int entries) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_desc *ring; - dma_addr_t dma; - int i; - - ring = pci_alloc_consistent(priv->pdev, sizeof(*ring) * entries, &dma); - if (!ring || (unsigned long)ring & 0xFF) { - printk(KERN_ERR "%s: Cannot allocate TX ring (prio = %d)\n", - wiphy_name(dev->wiphy), prio); - return -ENOMEM; - } - - memset(ring, 0, sizeof(*ring)*entries); - priv->tx_ring[prio].desc = ring; - priv->tx_ring[prio].dma = dma; - priv->tx_ring[prio].idx = 0; - priv->tx_ring[prio].entries = entries; - skb_queue_head_init(&priv->tx_ring[prio].queue); - - for (i = 0; i < entries; i++) - ring[i].next_tx_desc = - cpu_to_le32((u32)dma + ((i + 1) % entries) * sizeof(*ring)); - - return 0; -} - -static void rtl8180_free_tx_ring(struct ieee80211_hw *dev, unsigned int prio) -{ - struct rtl8180_priv *priv = dev->priv; - struct rtl8180_tx_ring *ring = &priv->tx_ring[prio]; - - while (skb_queue_len(&ring->queue)) { - struct rtl8180_tx_desc *entry = &ring->desc[ring->idx]; - struct sk_buff *skb = __skb_dequeue(&ring->queue); - - pci_unmap_single(priv->pdev, le32_to_cpu(entry->tx_buf), - skb->len, PCI_DMA_TODEVICE); - kfree_skb(skb); - ring->idx = (ring->idx + 1) % ring->entries; - } - - pci_free_consistent(priv->pdev, sizeof(*ring->desc)*ring->entries, - ring->desc, ring->dma); - ring->desc = NULL; -} - -static int rtl8180_start(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int ret, i; - u32 reg; - - ret = rtl8180_init_rx_ring(dev); - if (ret) - return ret; - - for (i = 0; i < 4; i++) - if ((ret = rtl8180_init_tx_ring(dev, i, 16))) - goto err_free_rings; - - ret = rtl8180_init_hw(dev); - if (ret) - goto err_free_rings; - - rtl818x_iowrite32(priv, &priv->map->RDSAR, priv->rx_ring_dma); - rtl818x_iowrite32(priv, &priv->map->TBDA, priv->tx_ring[3].dma); - rtl818x_iowrite32(priv, &priv->map->THPDA, priv->tx_ring[2].dma); - rtl818x_iowrite32(priv, &priv->map->TNPDA, priv->tx_ring[1].dma); - rtl818x_iowrite32(priv, &priv->map->TLPDA, priv->tx_ring[0].dma); - - ret = request_irq(priv->pdev->irq, &rtl8180_interrupt, - IRQF_SHARED, KBUILD_MODNAME, dev); - if (ret) { - printk(KERN_ERR "%s: failed to register IRQ handler\n", - wiphy_name(dev->wiphy)); - goto err_free_rings; - } - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); - - rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); - rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); - - reg = RTL818X_RX_CONF_ONLYERLPKT | - RTL818X_RX_CONF_RX_AUTORESETPHY | - RTL818X_RX_CONF_MGMT | - RTL818X_RX_CONF_DATA | - (7 << 8 /* MAX RX DMA */) | - RTL818X_RX_CONF_BROADCAST | - RTL818X_RX_CONF_NICMAC; - - if (priv->r8185) - reg |= RTL818X_RX_CONF_CSDM1 | RTL818X_RX_CONF_CSDM2; - else { - reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE1) - ? RTL818X_RX_CONF_CSDM1 : 0; - reg |= (priv->rfparam & RF_PARAM_CARRIERSENSE2) - ? RTL818X_RX_CONF_CSDM2 : 0; - } - - priv->rx_conf = reg; - rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); - - if (priv->r8185) { - reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); - reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT; - reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; - rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; - reg |= RTL818X_TX_AGC_CTL_FEEDBACK_ANT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); - - /* disable early TX */ - rtl818x_iowrite8(priv, (u8 __iomem *)priv->map + 0xec, 0x3f); - } - - reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); - reg |= (6 << 21 /* MAX TX DMA */) | - RTL818X_TX_CONF_NO_ICV; - - if (priv->r8185) - reg &= ~RTL818X_TX_CONF_PROBE_DTS; - else - reg &= ~RTL818X_TX_CONF_HW_SEQNUM; - - /* different meaning, same value on both rtl8185 and rtl8180 */ - reg &= ~RTL818X_TX_CONF_SAT_HWPLCP; - - rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg |= RTL818X_CMD_RX_ENABLE; - reg |= RTL818X_CMD_TX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - priv->mode = NL80211_IFTYPE_MONITOR; - return 0; - - err_free_rings: - rtl8180_free_rx_ring(dev); - for (i = 0; i < 4; i++) - if (priv->tx_ring[i].desc) - rtl8180_free_tx_ring(dev, i); - - return ret; -} - -static void rtl8180_stop(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u8 reg; - int i; - - priv->mode = NL80211_IFTYPE_UNSPECIFIED; - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= ~RTL818X_CMD_TX_ENABLE; - reg &= ~RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - priv->rf->stop(dev); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); - rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - free_irq(priv->pdev->irq, dev); - - rtl8180_free_rx_ring(dev); - for (i = 0; i < 4; i++) - rtl8180_free_tx_ring(dev, i); -} - -static int rtl8180_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - - if (priv->mode != NL80211_IFTYPE_MONITOR) - return -EOPNOTSUPP; - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - priv->mode = conf->type; - break; - default: - return -EOPNOTSUPP; - } - - priv->vif = conf->vif; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite32(priv, (__le32 __iomem *)&priv->map->MAC[0], - le32_to_cpu(*(__le32 *)conf->mac_addr)); - rtl818x_iowrite16(priv, (__le16 __iomem *)&priv->map->MAC[4], - le16_to_cpu(*(__le16 *)(conf->mac_addr + 4))); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - return 0; -} - -static void rtl8180_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - priv->mode = NL80211_IFTYPE_MONITOR; - priv->vif = NULL; -} - -static int rtl8180_config(struct ieee80211_hw *dev, u32 changed) -{ - struct rtl8180_priv *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - - priv->rf->set_chan(dev, conf); - - return 0; -} - -static void rtl8180_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - if (changed & BSS_CHANGED_BSSID) { - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], - info->bssid[i]); - - if (is_valid_ether_addr(info->bssid)) - rtl818x_iowrite8(priv, &priv->map->MSR, - RTL818X_MSR_INFRA); - else - rtl818x_iowrite8(priv, &priv->map->MSR, - RTL818X_MSR_NO_LINK); - } - - if (changed & BSS_CHANGED_ERP_SLOT && priv->rf->conf_erp) - priv->rf->conf_erp(dev, info); -} - -static u64 rtl8180_prepare_multicast(struct ieee80211_hw *dev, int mc_count, - struct dev_addr_list *mc_list) -{ - return mc_count; -} - -static void rtl8180_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct rtl8180_priv *priv = dev->priv; - - if (changed_flags & FIF_FCSFAIL) - priv->rx_conf ^= RTL818X_RX_CONF_FCS; - if (changed_flags & FIF_CONTROL) - priv->rx_conf ^= RTL818X_RX_CONF_CTRL; - if (changed_flags & FIF_OTHER_BSS) - priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - if (*total_flags & FIF_ALLMULTI || multicast > 0) - priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; - else - priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; - - *total_flags = 0; - - if (priv->rx_conf & RTL818X_RX_CONF_FCS) - *total_flags |= FIF_FCSFAIL; - if (priv->rx_conf & RTL818X_RX_CONF_CTRL) - *total_flags |= FIF_CONTROL; - if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) - *total_flags |= FIF_OTHER_BSS; - if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) - *total_flags |= FIF_ALLMULTI; - - rtl818x_iowrite32(priv, &priv->map->RX_CONF, priv->rx_conf); -} - -static const struct ieee80211_ops rtl8180_ops = { - .tx = rtl8180_tx, - .start = rtl8180_start, - .stop = rtl8180_stop, - .add_interface = rtl8180_add_interface, - .remove_interface = rtl8180_remove_interface, - .config = rtl8180_config, - .bss_info_changed = rtl8180_bss_info_changed, - .prepare_multicast = rtl8180_prepare_multicast, - .configure_filter = rtl8180_configure_filter, -}; - -static void rtl8180_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct ieee80211_hw *dev = eeprom->data; - struct rtl8180_priv *priv = dev->priv; - u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - - eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; - eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; - eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; - eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; -} - -static void rtl8180_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct ieee80211_hw *dev = eeprom->data; - struct rtl8180_priv *priv = dev->priv; - u8 reg = 2 << 6; - - if (eeprom->reg_data_in) - reg |= RTL818X_EEPROM_CMD_WRITE; - if (eeprom->reg_data_out) - reg |= RTL818X_EEPROM_CMD_READ; - if (eeprom->reg_data_clock) - reg |= RTL818X_EEPROM_CMD_CK; - if (eeprom->reg_chip_select) - reg |= RTL818X_EEPROM_CMD_CS; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); -} - -static int __devinit rtl8180_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - struct ieee80211_hw *dev; - struct rtl8180_priv *priv; - unsigned long mem_addr, mem_len; - unsigned int io_addr, io_len; - int err, i; - struct eeprom_93cx6 eeprom; - const char *chip_name, *rf_name = NULL; - u32 reg; - u16 eeprom_val; - - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR "%s (rtl8180): Cannot enable new PCI device\n", - pci_name(pdev)); - return err; - } - - err = pci_request_regions(pdev, KBUILD_MODNAME); - if (err) { - printk(KERN_ERR "%s (rtl8180): Cannot obtain PCI resources\n", - pci_name(pdev)); - return err; - } - - io_addr = pci_resource_start(pdev, 0); - io_len = pci_resource_len(pdev, 0); - mem_addr = pci_resource_start(pdev, 1); - mem_len = pci_resource_len(pdev, 1); - - if (mem_len < sizeof(struct rtl818x_csr) || - io_len < sizeof(struct rtl818x_csr)) { - printk(KERN_ERR "%s (rtl8180): Too short PCI resources\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_free_reg; - } - - if ((err = pci_set_dma_mask(pdev, 0xFFFFFF00ULL)) || - (err = pci_set_consistent_dma_mask(pdev, 0xFFFFFF00ULL))) { - printk(KERN_ERR "%s (rtl8180): No suitable DMA available\n", - pci_name(pdev)); - goto err_free_reg; - } - - pci_set_master(pdev); - - dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8180_ops); - if (!dev) { - printk(KERN_ERR "%s (rtl8180): ieee80211 alloc failed\n", - pci_name(pdev)); - err = -ENOMEM; - goto err_free_reg; - } - - priv = dev->priv; - priv->pdev = pdev; - - dev->max_rates = 2; - SET_IEEE80211_DEV(dev, &pdev->dev); - pci_set_drvdata(pdev, dev); - - priv->map = pci_iomap(pdev, 1, mem_len); - if (!priv->map) - priv->map = pci_iomap(pdev, 0, io_len); - - if (!priv->map) { - printk(KERN_ERR "%s (rtl8180): Cannot map device memory\n", - pci_name(pdev)); - goto err_free_dev; - } - - BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); - BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); - - memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); - memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - - priv->band.band = IEEE80211_BAND_2GHZ; - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = 4; - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - - dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_UNSPEC; - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - dev->queues = 1; - dev->max_signal = 65; - - reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); - reg &= RTL818X_TX_CONF_HWVER_MASK; - switch (reg) { - case RTL818X_TX_CONF_R8180_ABCD: - chip_name = "RTL8180"; - break; - case RTL818X_TX_CONF_R8180_F: - chip_name = "RTL8180vF"; - break; - case RTL818X_TX_CONF_R8185_ABC: - chip_name = "RTL8185"; - break; - case RTL818X_TX_CONF_R8185_D: - chip_name = "RTL8185vD"; - break; - default: - printk(KERN_ERR "%s (rtl8180): Unknown chip! (0x%x)\n", - pci_name(pdev), reg >> 25); - goto err_iounmap; - } - - priv->r8185 = reg & RTL818X_TX_CONF_R8185_ABC; - if (priv->r8185) { - priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); - pci_try_set_mwi(pdev); - } - - eeprom.data = dev; - eeprom.register_read = rtl8180_eeprom_register_read; - eeprom.register_write = rtl8180_eeprom_register_write; - if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) - eeprom.width = PCI_EEPROM_WIDTH_93C66; - else - eeprom.width = PCI_EEPROM_WIDTH_93C46; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_PROGRAM); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - eeprom_93cx6_read(&eeprom, 0x06, &eeprom_val); - eeprom_val &= 0xFF; - switch (eeprom_val) { - case 1: rf_name = "Intersil"; - break; - case 2: rf_name = "RFMD"; - break; - case 3: priv->rf = &sa2400_rf_ops; - break; - case 4: priv->rf = &max2820_rf_ops; - break; - case 5: priv->rf = &grf5101_rf_ops; - break; - case 9: priv->rf = rtl8180_detect_rf(dev); - break; - case 10: - rf_name = "RTL8255"; - break; - default: - printk(KERN_ERR "%s (rtl8180): Unknown RF! (0x%x)\n", - pci_name(pdev), eeprom_val); - goto err_iounmap; - } - - if (!priv->rf) { - printk(KERN_ERR "%s (rtl8180): %s RF frontend not supported!\n", - pci_name(pdev), rf_name); - goto err_iounmap; - } - - eeprom_93cx6_read(&eeprom, 0x17, &eeprom_val); - priv->csthreshold = eeprom_val >> 8; - if (!priv->r8185) { - __le32 anaparam; - eeprom_93cx6_multiread(&eeprom, 0xD, (__le16 *)&anaparam, 2); - priv->anaparam = le32_to_cpu(anaparam); - eeprom_93cx6_read(&eeprom, 0x19, &priv->rfparam); - } - - eeprom_93cx6_multiread(&eeprom, 0x7, (__le16 *)dev->wiphy->perm_addr, 3); - if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { - printk(KERN_WARNING "%s (rtl8180): Invalid hwaddr! Using" - " randomly generated MAC addr\n", pci_name(pdev)); - random_ether_addr(dev->wiphy->perm_addr); - } - - /* CCK TX power */ - for (i = 0; i < 14; i += 2) { - u16 txpwr; - eeprom_93cx6_read(&eeprom, 0x10 + (i >> 1), &txpwr); - priv->channels[i].hw_value = txpwr & 0xFF; - priv->channels[i + 1].hw_value = txpwr >> 8; - } - - /* OFDM TX power */ - if (priv->r8185) { - for (i = 0; i < 14; i += 2) { - u16 txpwr; - eeprom_93cx6_read(&eeprom, 0x20 + (i >> 1), &txpwr); - priv->channels[i].hw_value |= (txpwr & 0xFF) << 8; - priv->channels[i + 1].hw_value |= txpwr & 0xFF00; - } - } - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - spin_lock_init(&priv->lock); - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "%s (rtl8180): Cannot register device\n", - pci_name(pdev)); - goto err_iounmap; - } - - printk(KERN_INFO "%s: hwaddr %pM, %s + %s\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - chip_name, priv->rf->name); - - return 0; - - err_iounmap: - iounmap(priv->map); - - err_free_dev: - pci_set_drvdata(pdev, NULL); - ieee80211_free_hw(dev); - - err_free_reg: - pci_release_regions(pdev); - pci_disable_device(pdev); - return err; -} - -static void __devexit rtl8180_remove(struct pci_dev *pdev) -{ - struct ieee80211_hw *dev = pci_get_drvdata(pdev); - struct rtl8180_priv *priv; - - if (!dev) - return; - - ieee80211_unregister_hw(dev); - - priv = dev->priv; - - pci_iounmap(pdev, priv->map); - pci_release_regions(pdev); - pci_disable_device(pdev); - ieee80211_free_hw(dev); -} - -#ifdef CONFIG_PM -static int rtl8180_suspend(struct pci_dev *pdev, pm_message_t state) -{ - pci_save_state(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - return 0; -} - -static int rtl8180_resume(struct pci_dev *pdev) -{ - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8180_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8180_table, - .probe = rtl8180_probe, - .remove = __devexit_p(rtl8180_remove), -#ifdef CONFIG_PM - .suspend = rtl8180_suspend, - .resume = rtl8180_resume, -#endif /* CONFIG_PM */ -}; - -static int __init rtl8180_init(void) -{ - return pci_register_driver(&rtl8180_driver); -} - -static void __exit rtl8180_exit(void) -{ - pci_unregister_driver(&rtl8180_driver); -} - -module_init(rtl8180_init); -module_exit(rtl8180_exit); diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c b/drivers/net/wireless/rtl818x/rtl8180_grf5101.c deleted file mode 100644 index 947ee55f18b2..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.c +++ /dev/null @@ -1,180 +0,0 @@ - -/* - * Radio tuning for GCT GRF5101 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8180_grf5101.h" - -static const int grf5101_encode[] = { - 0x0, 0x8, 0x4, 0xC, - 0x2, 0xA, 0x6, 0xE, - 0x1, 0x9, 0x5, 0xD, - 0x3, 0xB, 0x7, 0xF -}; - -static void write_grf5101(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - u32 phy_config; - - phy_config = grf5101_encode[(data >> 8) & 0xF]; - phy_config |= grf5101_encode[(data >> 4) & 0xF] << 4; - phy_config |= grf5101_encode[data & 0xF] << 8; - phy_config |= grf5101_encode[(addr >> 1) & 0xF] << 12; - phy_config |= (addr & 1) << 16; - phy_config |= grf5101_encode[(data & 0xf000) >> 12] << 24; - - /* MAC will bang bits to the chip */ - phy_config |= 0x90000000; - - rtl818x_iowrite32(priv, - (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); - - msleep(3); -} - -static void grf5101_write_phy_antenna(struct ieee80211_hw *dev, short chan) -{ - struct rtl8180_priv *priv = dev->priv; - u8 ant = GRF5101_ANTENNA; - - if (priv->rfparam & RF_PARAM_ANTBDEFAULT) - ant |= BB_ANTENNA_B; - - if (chan == 14) - ant |= BB_ANTATTEN_CHAN14; - - rtl8180_write_phy(dev, 0x10, ant); -} - -static void grf5101_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; - u32 chan = channel - 1; - - /* set TX power */ - write_grf5101(dev, 0x15, 0x0); - write_grf5101(dev, 0x06, txpw); - write_grf5101(dev, 0x15, 0x10); - write_grf5101(dev, 0x15, 0x0); - - /* set frequency */ - write_grf5101(dev, 0x07, 0x0); - write_grf5101(dev, 0x0B, chan); - write_grf5101(dev, 0x07, 0x1000); - - grf5101_write_phy_antenna(dev, channel); -} - -static void grf5101_rf_stop(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u32 anaparam; - - anaparam = priv->anaparam; - anaparam &= 0x000fffff; - anaparam |= 0x3f900000; - rtl8180_set_anaparam(priv, anaparam); - - write_grf5101(dev, 0x07, 0x0); - write_grf5101(dev, 0x1f, 0x45); - write_grf5101(dev, 0x1f, 0x5); - write_grf5101(dev, 0x00, 0x8e4); -} - -static void grf5101_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - rtl8180_set_anaparam(priv, priv->anaparam); - - write_grf5101(dev, 0x1f, 0x0); - write_grf5101(dev, 0x1f, 0x0); - write_grf5101(dev, 0x1f, 0x40); - write_grf5101(dev, 0x1f, 0x60); - write_grf5101(dev, 0x1f, 0x61); - write_grf5101(dev, 0x1f, 0x61); - write_grf5101(dev, 0x00, 0xae4); - write_grf5101(dev, 0x1f, 0x1); - write_grf5101(dev, 0x1f, 0x41); - write_grf5101(dev, 0x1f, 0x61); - - write_grf5101(dev, 0x01, 0x1a23); - write_grf5101(dev, 0x02, 0x4971); - write_grf5101(dev, 0x03, 0x41de); - write_grf5101(dev, 0x04, 0x2d80); - write_grf5101(dev, 0x05, 0x68ff); /* 0x61ff original value */ - write_grf5101(dev, 0x06, 0x0); - write_grf5101(dev, 0x07, 0x0); - write_grf5101(dev, 0x08, 0x7533); - write_grf5101(dev, 0x09, 0xc401); - write_grf5101(dev, 0x0a, 0x0); - write_grf5101(dev, 0x0c, 0x1c7); - write_grf5101(dev, 0x0d, 0x29d3); - write_grf5101(dev, 0x0e, 0x2e8); - write_grf5101(dev, 0x10, 0x192); - write_grf5101(dev, 0x11, 0x248); - write_grf5101(dev, 0x12, 0x0); - write_grf5101(dev, 0x13, 0x20c4); - write_grf5101(dev, 0x14, 0xf4fc); - write_grf5101(dev, 0x15, 0x0); - write_grf5101(dev, 0x16, 0x1500); - - write_grf5101(dev, 0x07, 0x1000); - - /* baseband configuration */ - rtl8180_write_phy(dev, 0, 0xa8); - rtl8180_write_phy(dev, 3, 0x0); - rtl8180_write_phy(dev, 4, 0xc0); - rtl8180_write_phy(dev, 5, 0x90); - rtl8180_write_phy(dev, 6, 0x1e); - rtl8180_write_phy(dev, 7, 0x64); - - grf5101_write_phy_antenna(dev, 1); - - rtl8180_write_phy(dev, 0x11, 0x88); - - if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & - RTL818X_CONFIG2_ANTENNA_DIV) - rtl8180_write_phy(dev, 0x12, 0xc0); /* enable ant diversity */ - else - rtl8180_write_phy(dev, 0x12, 0x40); /* disable ant diversity */ - - rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold); - - rtl8180_write_phy(dev, 0x19, 0x0); - rtl8180_write_phy(dev, 0x1a, 0xa0); - rtl8180_write_phy(dev, 0x1b, 0x44); -} - -const struct rtl818x_rf_ops grf5101_rf_ops = { - .name = "GCT", - .init = grf5101_rf_init, - .stop = grf5101_rf_stop, - .set_chan = grf5101_rf_set_channel -}; diff --git a/drivers/net/wireless/rtl818x/rtl8180_grf5101.h b/drivers/net/wireless/rtl818x/rtl8180_grf5101.h deleted file mode 100644 index 76647111bcff..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_grf5101.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RTL8180_GRF5101_H -#define RTL8180_GRF5101_H - -/* - * Radio tuning for GCT GRF5101 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define GRF5101_ANTENNA 0xA3 - -extern const struct rtl818x_rf_ops grf5101_rf_ops; - -#endif /* RTL8180_GRF5101_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.c b/drivers/net/wireless/rtl818x/rtl8180_max2820.c deleted file mode 100644 index 6c825fd7f3b6..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_max2820.c +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Radio tuning for Maxim max2820 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8180_max2820.h" - -static const u32 max2820_chan[] = { - 12, /* CH 1 */ - 17, - 22, - 27, - 32, - 37, - 42, - 47, - 52, - 57, - 62, - 67, - 72, - 84, /* CH 14 */ -}; - -static void write_max2820(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - u32 phy_config; - - phy_config = 0x90 + (data & 0xf); - phy_config <<= 16; - phy_config += addr; - phy_config <<= 8; - phy_config += (data >> 4) & 0xff; - - rtl818x_iowrite32(priv, - (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); - - msleep(1); -} - -static void max2820_write_phy_antenna(struct ieee80211_hw *dev, short chan) -{ - struct rtl8180_priv *priv = dev->priv; - u8 ant; - - ant = MAXIM_ANTENNA; - if (priv->rfparam & RF_PARAM_ANTBDEFAULT) - ant |= BB_ANTENNA_B; - if (chan == 14) - ant |= BB_ANTATTEN_CHAN14; - - rtl8180_write_phy(dev, 0x10, ant); -} - -static void max2820_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int channel = conf ? - ieee80211_frequency_to_channel(conf->channel->center_freq) : 1; - unsigned int chan_idx = channel - 1; - u32 txpw = priv->channels[chan_idx].hw_value & 0xFF; - u32 chan = max2820_chan[chan_idx]; - - /* While philips SA2400 drive the PA bias from - * sa2400, for MAXIM we do this directly from BB */ - rtl8180_write_phy(dev, 3, txpw); - - max2820_write_phy_antenna(dev, channel); - write_max2820(dev, 3, chan); -} - -static void max2820_rf_stop(struct ieee80211_hw *dev) -{ - rtl8180_write_phy(dev, 3, 0x8); - write_max2820(dev, 1, 0); -} - - -static void max2820_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - - /* MAXIM from netbsd driver */ - write_max2820(dev, 0, 0x007); /* test mode as indicated in datasheet */ - write_max2820(dev, 1, 0x01e); /* enable register */ - write_max2820(dev, 2, 0x001); /* synt register */ - - max2820_rf_set_channel(dev, NULL); - - write_max2820(dev, 4, 0x313); /* rx register */ - - /* PA is driven directly by the BB, we keep the MAXIM bias - * at the highest value in case that setting it to lower - * values may introduce some further attenuation somewhere.. - */ - write_max2820(dev, 5, 0x00f); - - /* baseband configuration */ - rtl8180_write_phy(dev, 0, 0x88); /* sys1 */ - rtl8180_write_phy(dev, 3, 0x08); /* txagc */ - rtl8180_write_phy(dev, 4, 0xf8); /* lnadet */ - rtl8180_write_phy(dev, 5, 0x90); /* ifagcinit */ - rtl8180_write_phy(dev, 6, 0x1a); /* ifagclimit */ - rtl8180_write_phy(dev, 7, 0x64); /* ifagcdet */ - - max2820_write_phy_antenna(dev, 1); - - rtl8180_write_phy(dev, 0x11, 0x88); /* trl */ - - if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & - RTL818X_CONFIG2_ANTENNA_DIV) - rtl8180_write_phy(dev, 0x12, 0xc7); - else - rtl8180_write_phy(dev, 0x12, 0x47); - - rtl8180_write_phy(dev, 0x13, 0x9b); - - rtl8180_write_phy(dev, 0x19, 0x0); /* CHESTLIM */ - rtl8180_write_phy(dev, 0x1a, 0x9f); /* CHSQLIM */ - - max2820_rf_set_channel(dev, NULL); -} - -const struct rtl818x_rf_ops max2820_rf_ops = { - .name = "Maxim", - .init = max2820_rf_init, - .stop = max2820_rf_stop, - .set_chan = max2820_rf_set_channel -}; diff --git a/drivers/net/wireless/rtl818x/rtl8180_max2820.h b/drivers/net/wireless/rtl818x/rtl8180_max2820.h deleted file mode 100644 index 61cf6d1e7d57..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_max2820.h +++ /dev/null @@ -1,28 +0,0 @@ -#ifndef RTL8180_MAX2820_H -#define RTL8180_MAX2820_H - -/* - * Radio tuning for Maxim max2820 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define MAXIM_ANTENNA 0xb3 - -extern const struct rtl818x_rf_ops max2820_rf_ops; - -#endif /* RTL8180_MAX2820_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c deleted file mode 100644 index 4d2be0d9672b..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.c +++ /dev/null @@ -1,788 +0,0 @@ - -/* - * Radio tuning for RTL8225 on RTL8180 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8180 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8180_rtl8225.h" - -static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg80, reg84, reg82; - u32 bangdata; - int i; - - bangdata = (data << 4) | (addr & 0xf); - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); - - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7 | 0x400); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - for (i = 15; i >= 0; i--) { - u16 reg = reg80 | !!(bangdata & (1 << i)); - - if (i & 1) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - - if (!(i & 1)) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x400); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); -} - -static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg80, reg82, reg84, out; - int i; - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect) | 0x400; - - reg80 &= ~0xF; - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(4); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(5); - - for (i = 4; i >= 0; i--) { - u16 reg = reg80 | ((addr >> i) & 1); - - if (!(i & 1)) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(1); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - if (i & 1) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(1); - } - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x000E); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x040E); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - out = 0; - for (i = 11; i >= 0; i--) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(1); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) - out |= 1 << i; - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 2)); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - udelay(2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); - - return out; -} - -static const u16 rtl8225bcd_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, - 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb -}; - -static const u8 rtl8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, - 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, - 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, - 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, - 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -}; - -static const u8 rtl8225_gain[] = { - 0x23, 0x88, 0x7c, 0xa5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xb5, /* -82dbm */ - 0x23, 0x88, 0x7c, 0xc5, /* -82dbm */ - 0x33, 0x80, 0x79, 0xc5, /* -78dbm */ - 0x43, 0x78, 0x76, 0xc5, /* -74dbm */ - 0x53, 0x60, 0x73, 0xc5, /* -70dbm */ - 0x63, 0x58, 0x70, 0xc5, /* -66dbm */ -}; - -static const u8 rtl8225_threshold[] = { - 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd -}; - -static const u8 rtl8225_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static const u8 rtl8225_tx_power_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static const u8 rtl8225_tx_power_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225_tx_power_ofdm[] = { - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static const u32 rtl8225_chan[] = { - 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, - 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 -}; - -static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8180_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - u32 reg; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xFF; - ofdm_power = priv->channels[channel - 1].hw_value >> 8; - - cck_power = min(cck_power, (u8)35); - ofdm_power = min(ofdm_power, (u8)35); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); - - if (channel == 14) - tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; - else - tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - msleep(1); /* FIXME: optional? */ - - /* anaparam2 on */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225_tx_gain_cck_ofdm[ofdm_power/6] >> 1); - - tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; - - rtl8225_write_phy_ofdm(dev, 5, *tmp); - rtl8225_write_phy_ofdm(dev, 7, *tmp); - - msleep(1); -} - -static void rtl8225_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON); - - /* host_pci_init */ - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - msleep(200); /* FIXME: ehh?? */ - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6)); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); - - /* TODO: check if we need really to change BRSR to do RF config */ - rtl818x_ioread16(priv, &priv->map->BRSR); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); - rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl8225_write(dev, 0x0, 0x067); - rtl8225_write(dev, 0x1, 0xFE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x8BE); - rtl8225_write(dev, 0x5, 0xBF0); /* TODO: minipci */ - rtl8225_write(dev, 0x6, 0xAE6); - rtl8225_write(dev, 0x7, rtl8225_chan[0]); - rtl8225_write(dev, 0x8, 0x01F); - rtl8225_write(dev, 0x9, 0x334); - rtl8225_write(dev, 0xA, 0xFD4); - rtl8225_write(dev, 0xB, 0x391); - rtl8225_write(dev, 0xC, 0x050); - rtl8225_write(dev, 0xD, 0x6DB); - rtl8225_write(dev, 0xE, 0x029); - rtl8225_write(dev, 0xF, 0x914); msleep(1); - - rtl8225_write(dev, 0x2, 0xC4D); msleep(100); - - rtl8225_write(dev, 0x0, 0x127); - - for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); - } - - rtl8225_write(dev, 0x0, 0x027); - rtl8225_write(dev, 0x0, 0x22F); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - msleep(1); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - msleep(1); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x06, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x08, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x11, 0x03); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); - rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); - rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); - rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); - rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1); - rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); - rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8d); msleep(1); - rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); - rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); - rtl8225_write_phy_cck(dev, 0x44, 0x1f); msleep(1); - rtl8225_write_phy_cck(dev, 0x45, 0x1e); msleep(1); - rtl8225_write_phy_cck(dev, 0x46, 0x1a); msleep(1); - rtl8225_write_phy_cck(dev, 0x47, 0x15); msleep(1); - rtl8225_write_phy_cck(dev, 0x48, 0x10); msleep(1); - rtl8225_write_phy_cck(dev, 0x49, 0x0a); msleep(1); - rtl8225_write_phy_cck(dev, 0x4a, 0x05); msleep(1); - rtl8225_write_phy_cck(dev, 0x4b, 0x02); msleep(1); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); - - rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); msleep(1); - - rtl8225_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - rtl8225_write(dev, 0x0c, 0x50); - /* set OFDM initial gain */ - rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[4 * 4]); - rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[4 * 4 + 1]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[4 * 4 + 2]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[4 * 4 + 3]); - /* set CCK threshold */ - rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[0]); -} - -static const u8 rtl8225z2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225z2_tx_power_cck_B[] = { - 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x04 -}; - -static const u8 rtl8225z2_tx_power_cck_A[] = { - 0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04 -}; - -static const u8 rtl8225z2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04 -}; - -static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8180_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xFF; - ofdm_power = priv->channels[channel - 1].hw_value >> 8; - - if (channel == 14) - tmp = rtl8225z2_tx_power_cck_ch14; - else if (cck_power == 12) - tmp = rtl8225z2_tx_power_cck_B; - else if (cck_power == 13) - tmp = rtl8225z2_tx_power_cck_A; - else - tmp = rtl8225z2_tx_power_cck; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - cck_power = min(cck_power, (u8)35); - if (cck_power == 13 || cck_power == 14) - cck_power = 12; - if (cck_power >= 15) - cck_power -= 2; - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, cck_power); - rtl818x_ioread8(priv, &priv->map->TX_GAIN_CCK); - msleep(1); - - ofdm_power = min(ofdm_power, (u8)35); - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, ofdm_power); - - rtl8225_write_phy_ofdm(dev, 2, 0x62); - rtl8225_write_phy_ofdm(dev, 5, 0x00); - rtl8225_write_phy_ofdm(dev, 6, 0x40); - rtl8225_write_phy_ofdm(dev, 7, 0x00); - rtl8225_write_phy_ofdm(dev, 8, 0x40); - - msleep(1); -} - -static const u16 rtl8225z2_rxgain[] = { - 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0008, 0x0009, - 0x000a, 0x000b, 0x0102, 0x0103, 0x0104, 0x0105, 0x0140, 0x0141, - 0x0142, 0x0143, 0x0144, 0x0145, 0x0180, 0x0181, 0x0182, 0x0183, - 0x0184, 0x0185, 0x0188, 0x0189, 0x018a, 0x018b, 0x0243, 0x0244, - 0x0245, 0x0280, 0x0281, 0x0282, 0x0283, 0x0284, 0x0285, 0x0288, - 0x0289, 0x028a, 0x028b, 0x028c, 0x0342, 0x0343, 0x0344, 0x0345, - 0x0380, 0x0381, 0x0382, 0x0383, 0x0384, 0x0385, 0x0388, 0x0389, - 0x038a, 0x038b, 0x038c, 0x038d, 0x0390, 0x0391, 0x0392, 0x0393, - 0x0394, 0x0395, 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, - 0x03a0, 0x03a1, 0x03a2, 0x03a3, 0x03a4, 0x03a5, 0x03a8, 0x03a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static void rtl8225z2_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - int i; - - rtl8180_set_anaparam(priv, RTL8225_ANAPARAM_ON); - - /* host_pci_init */ - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - msleep(200); /* FIXME: ehh?? */ - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0xFF & ~(1 << 6)); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00088008); - - /* TODO: check if we need really to change BRSR to do RF config */ - rtl818x_ioread16(priv, &priv->map->BRSR); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); - rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - rtl8225_write(dev, 0x0, 0x0B7); msleep(1); - rtl8225_write(dev, 0x1, 0xEE0); msleep(1); - rtl8225_write(dev, 0x2, 0x44D); msleep(1); - rtl8225_write(dev, 0x3, 0x441); msleep(1); - rtl8225_write(dev, 0x4, 0x8C3); msleep(1); - rtl8225_write(dev, 0x5, 0xC72); msleep(1); - rtl8225_write(dev, 0x6, 0x0E6); msleep(1); - rtl8225_write(dev, 0x7, 0x82A); msleep(1); - rtl8225_write(dev, 0x8, 0x03F); msleep(1); - rtl8225_write(dev, 0x9, 0x335); msleep(1); - rtl8225_write(dev, 0xa, 0x9D4); msleep(1); - rtl8225_write(dev, 0xb, 0x7BB); msleep(1); - rtl8225_write(dev, 0xc, 0x850); msleep(1); - rtl8225_write(dev, 0xd, 0xCDF); msleep(1); - rtl8225_write(dev, 0xe, 0x02B); msleep(1); - rtl8225_write(dev, 0xf, 0x114); msleep(100); - - if (!(rtl8225_read(dev, 6) & (1 << 7))) { - rtl8225_write(dev, 0x02, 0x0C4D); - msleep(200); - rtl8225_write(dev, 0x02, 0x044D); - msleep(100); - /* TODO: readd calibration failure message when the calibration - check works */ - } - - rtl8225_write(dev, 0x0, 0x1B7); - rtl8225_write(dev, 0x3, 0x002); - rtl8225_write(dev, 0x5, 0x004); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); - } - - rtl8225_write(dev, 0x0, 0x0B7); msleep(100); - rtl8225_write(dev, 0x2, 0xC4D); - - msleep(200); - rtl8225_write(dev, 0x2, 0x44D); - msleep(100); - - rtl8225_write(dev, 0x00, 0x2BF); - rtl8225_write(dev, 0xFF, 0xFFFF); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - msleep(1); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - msleep(1); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x02, 0x62); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x06, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x08, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x11, 0x06); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x11); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1e, 0xb3); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x21, 0x27); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x23, 0x80); msleep(1); /* FIXME: not needed? */ - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x25, 0x20); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); msleep(1); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); msleep(1); - rtl8225_write_phy_cck(dev, 0x03, 0x20); msleep(1); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); msleep(1); - rtl8225_write_phy_cck(dev, 0x05, 0x12); msleep(1); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); msleep(1); - rtl8225_write_phy_cck(dev, 0x07, 0x78); msleep(1); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); msleep(1); - rtl8225_write_phy_cck(dev, 0x10, 0x93); msleep(1); - rtl8225_write_phy_cck(dev, 0x11, 0x88); msleep(1); - rtl8225_write_phy_cck(dev, 0x12, 0x47); msleep(1); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8a); msleep(1); - rtl8225_write_phy_cck(dev, 0x42, 0x15); msleep(1); - rtl8225_write_phy_cck(dev, 0x43, 0x18); msleep(1); - rtl8225_write_phy_cck(dev, 0x44, 0x36); msleep(1); - rtl8225_write_phy_cck(dev, 0x45, 0x35); msleep(1); - rtl8225_write_phy_cck(dev, 0x46, 0x2e); msleep(1); - rtl8225_write_phy_cck(dev, 0x47, 0x25); msleep(1); - rtl8225_write_phy_cck(dev, 0x48, 0x1c); msleep(1); - rtl8225_write_phy_cck(dev, 0x49, 0x12); msleep(1); - rtl8225_write_phy_cck(dev, 0x4a, 0x09); msleep(1); - rtl8225_write_phy_cck(dev, 0x4b, 0x04); msleep(1); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); msleep(1); - - rtl818x_iowrite8(priv, (u8 __iomem *)((void __iomem *)priv->map + 0x5B), 0x0D); msleep(1); - - rtl8225z2_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); msleep(1); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); msleep(1); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 __iomem *)((void __iomem *)priv->map + 0x94), 0x15c00002); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); -} - -static void rtl8225_rf_stop(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u8 reg; - - rtl8225_write(dev, 0x4, 0x1f); msleep(1); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); -} - -static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int chan = ieee80211_frequency_to_channel(conf->channel->center_freq); - - if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, chan); - else - rtl8225z2_rf_set_tx_power(dev, chan); - - rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); - msleep(10); -} - -static void rtl8225_rf_conf_erp(struct ieee80211_hw *dev, - struct ieee80211_bss_conf *info) -{ - struct rtl8180_priv *priv = dev->priv; - - if (info->use_short_slot) { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); - rtl818x_iowrite8(priv, &priv->map->EIFS, 81); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0x73); - } else { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x44); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); - rtl818x_iowrite8(priv, &priv->map->EIFS, 81); - rtl818x_iowrite8(priv, &priv->map->CW_VAL, 0xa5); - } -} - -static const struct rtl818x_rf_ops rtl8225_ops = { - .name = "rtl8225", - .init = rtl8225_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel, - .conf_erp = rtl8225_rf_conf_erp, -}; - -static const struct rtl818x_rf_ops rtl8225z2_ops = { - .name = "rtl8225z2", - .init = rtl8225z2_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel, - .conf_erp = rtl8225_rf_conf_erp, -}; - -const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u16 reg8, reg9; - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x0488); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - msleep(100); - - rtl8225_write(dev, 0, 0x1B7); - - reg8 = rtl8225_read(dev, 8); - reg9 = rtl8225_read(dev, 9); - - rtl8225_write(dev, 0, 0x0B7); - - if (reg8 != 0x588 || reg9 != 0x700) - return &rtl8225_ops; - - return &rtl8225z2_ops; -} diff --git a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h deleted file mode 100644 index 310013a2d726..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_rtl8225.h +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef RTL8180_RTL8225_H -#define RTL8180_RTL8225_H - -#define RTL8225_ANAPARAM_ON 0xa0000b59 -#define RTL8225_ANAPARAM2_ON 0x860dec11 -#define RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8225_ANAPARAM2_OFF 0x840dec11 - -const struct rtl818x_rf_ops * rtl8180_detect_rf(struct ieee80211_hw *); - -static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, - u8 addr, u8 data) -{ - rtl8180_write_phy(dev, addr, data); -} - -static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, - u8 addr, u8 data) -{ - rtl8180_write_phy(dev, addr, data | 0x10000); -} - -#endif /* RTL8180_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c b/drivers/net/wireless/rtl818x/rtl8180_sa2400.c deleted file mode 100644 index cea4e0ccb92d..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.c +++ /dev/null @@ -1,202 +0,0 @@ - -/* - * Radio tuning for Philips SA2400 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include - -#include "rtl8180.h" -#include "rtl8180_sa2400.h" - -static const u32 sa2400_chan[] = { - 0x00096c, /* ch1 */ - 0x080970, - 0x100974, - 0x180978, - 0x000980, - 0x080984, - 0x100988, - 0x18098c, - 0x000994, - 0x080998, - 0x10099c, - 0x1809a0, - 0x0009a8, - 0x0009b4, /* ch 14 */ -}; - -static void write_sa2400(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8180_priv *priv = dev->priv; - u32 phy_config; - - /* MAC will bang bits to the sa2400. sw 3-wire is NOT used */ - phy_config = 0xb0000000; - - phy_config |= ((u32)(addr & 0xf)) << 24; - phy_config |= data & 0xffffff; - - rtl818x_iowrite32(priv, - (__le32 __iomem *) &priv->map->RFPinsOutput, phy_config); - - msleep(3); -} - -static void sa2400_write_phy_antenna(struct ieee80211_hw *dev, short chan) -{ - struct rtl8180_priv *priv = dev->priv; - u8 ant = SA2400_ANTENNA; - - if (priv->rfparam & RF_PARAM_ANTBDEFAULT) - ant |= BB_ANTENNA_B; - - if (chan == 14) - ant |= BB_ANTATTEN_CHAN14; - - rtl8180_write_phy(dev, 0x10, ant); - -} - -static void sa2400_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8180_priv *priv = dev->priv; - int channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - u32 txpw = priv->channels[channel - 1].hw_value & 0xFF; - u32 chan = sa2400_chan[channel - 1]; - - write_sa2400(dev, 7, txpw); - - sa2400_write_phy_antenna(dev, channel); - - write_sa2400(dev, 0, chan); - write_sa2400(dev, 1, 0xbb50); - write_sa2400(dev, 2, 0x80); - write_sa2400(dev, 3, 0); -} - -static void sa2400_rf_stop(struct ieee80211_hw *dev) -{ - write_sa2400(dev, 4, 0); -} - -static void sa2400_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8180_priv *priv = dev->priv; - u32 anaparam, txconf; - u8 firdac; - int analogphy = priv->rfparam & RF_PARAM_ANALOGPHY; - - anaparam = priv->anaparam; - anaparam &= ~(1 << ANAPARAM_TXDACOFF_SHIFT); - anaparam &= ~ANAPARAM_PWR1_MASK; - anaparam &= ~ANAPARAM_PWR0_MASK; - - if (analogphy) { - anaparam |= SA2400_ANA_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT; - firdac = 0; - } else { - anaparam |= (SA2400_DIG_ANAPARAM_PWR1_ON << ANAPARAM_PWR1_SHIFT); - anaparam |= (SA2400_ANAPARAM_PWR0_ON << ANAPARAM_PWR0_SHIFT); - firdac = 1 << SA2400_REG4_FIRDAC_SHIFT; - } - - rtl8180_set_anaparam(priv, anaparam); - - write_sa2400(dev, 0, sa2400_chan[0]); - write_sa2400(dev, 1, 0xbb50); - write_sa2400(dev, 2, 0x80); - write_sa2400(dev, 3, 0); - write_sa2400(dev, 4, 0x19340 | firdac); - write_sa2400(dev, 5, 0x1dfb | (SA2400_MAX_SENS - 54) << 15); - write_sa2400(dev, 4, 0x19348 | firdac); /* calibrate VCO */ - - if (!analogphy) - write_sa2400(dev, 4, 0x1938c); /*???*/ - - write_sa2400(dev, 4, 0x19340 | firdac); - - write_sa2400(dev, 0, sa2400_chan[0]); - write_sa2400(dev, 1, 0xbb50); - write_sa2400(dev, 2, 0x80); - write_sa2400(dev, 3, 0); - write_sa2400(dev, 4, 0x19344 | firdac); /* calibrate filter */ - - /* new from rtl8180 embedded driver (rtl8181 project) */ - write_sa2400(dev, 6, 0x13ff | (1 << 23)); /* MANRX */ - write_sa2400(dev, 8, 0); /* VCO */ - - if (analogphy) { - rtl8180_set_anaparam(priv, anaparam | - (1 << ANAPARAM_TXDACOFF_SHIFT)); - - txconf = rtl818x_ioread32(priv, &priv->map->TX_CONF); - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - txconf | RTL818X_TX_CONF_LOOPBACK_CONT); - - write_sa2400(dev, 4, 0x19341); /* calibrates DC */ - - /* a 5us sleep is required here, - * we rely on the 3ms delay introduced in write_sa2400 */ - write_sa2400(dev, 4, 0x19345); - - /* a 20us sleep is required here, - * we rely on the 3ms delay introduced in write_sa2400 */ - - rtl818x_iowrite32(priv, &priv->map->TX_CONF, txconf); - - rtl8180_set_anaparam(priv, anaparam); - } - /* end new code */ - - write_sa2400(dev, 4, 0x19341 | firdac); /* RTX MODE */ - - /* baseband configuration */ - rtl8180_write_phy(dev, 0, 0x98); - rtl8180_write_phy(dev, 3, 0x38); - rtl8180_write_phy(dev, 4, 0xe0); - rtl8180_write_phy(dev, 5, 0x90); - rtl8180_write_phy(dev, 6, 0x1a); - rtl8180_write_phy(dev, 7, 0x64); - - sa2400_write_phy_antenna(dev, 1); - - rtl8180_write_phy(dev, 0x11, 0x80); - - if (rtl818x_ioread8(priv, &priv->map->CONFIG2) & - RTL818X_CONFIG2_ANTENNA_DIV) - rtl8180_write_phy(dev, 0x12, 0xc7); /* enable ant diversity */ - else - rtl8180_write_phy(dev, 0x12, 0x47); /* disable ant diversity */ - - rtl8180_write_phy(dev, 0x13, 0x90 | priv->csthreshold); - - rtl8180_write_phy(dev, 0x19, 0x0); - rtl8180_write_phy(dev, 0x1a, 0xa0); -} - -const struct rtl818x_rf_ops sa2400_rf_ops = { - .name = "Philips", - .init = sa2400_rf_init, - .stop = sa2400_rf_stop, - .set_chan = sa2400_rf_set_channel -}; diff --git a/drivers/net/wireless/rtl818x/rtl8180_sa2400.h b/drivers/net/wireless/rtl818x/rtl8180_sa2400.h deleted file mode 100644 index a4aaa0d413f1..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8180_sa2400.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef RTL8180_SA2400_H -#define RTL8180_SA2400_H - -/* - * Radio tuning for Philips SA2400 on RTL8180 - * - * Copyright 2007 Andrea Merello - * - * Code from the BSD driver and the rtl8181 project have been - * very useful to understand certain things - * - * I want to thanks the Authors of such projects and the Ndiswrapper - * project Authors. - * - * A special Big Thanks also is for all people who donated me cards, - * making possible the creation of the original rtl8180 driver - * from which this code is derived! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define SA2400_ANTENNA 0x91 -#define SA2400_DIG_ANAPARAM_PWR1_ON 0x8 -#define SA2400_ANA_ANAPARAM_PWR1_ON 0x28 -#define SA2400_ANAPARAM_PWR0_ON 0x3 - -/* RX sensitivity in dbm */ -#define SA2400_MAX_SENS 85 - -#define SA2400_REG4_FIRDAC_SHIFT 7 - -extern const struct rtl818x_rf_ops sa2400_rf_ops; - -#endif /* RTL8180_SA2400_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h deleted file mode 100644 index 99406bf381ca..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187.h +++ /dev/null @@ -1,271 +0,0 @@ -/* - * Definitions for RTL8187 hardware - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187_H -#define RTL8187_H - -#include "rtl818x.h" -#include "rtl8187_leds.h" - -#define RTL8187_EEPROM_TXPWR_BASE 0x05 -#define RTL8187_EEPROM_MAC_ADDR 0x07 -#define RTL8187_EEPROM_TXPWR_CHAN_1 0x16 /* 3 channels */ -#define RTL8187_EEPROM_TXPWR_CHAN_6 0x1B /* 2 channels */ -#define RTL8187_EEPROM_TXPWR_CHAN_4 0x3D /* 2 channels */ -#define RTL8187_EEPROM_SELECT_GPIO 0x3B - -#define RTL8187_REQT_READ 0xC0 -#define RTL8187_REQT_WRITE 0x40 -#define RTL8187_REQ_GET_REG 0x05 -#define RTL8187_REQ_SET_REG 0x05 - -#define RTL8187_MAX_RX 0x9C4 - -#define RFKILL_MASK_8187_89_97 0x2 -#define RFKILL_MASK_8198 0x4 - -struct rtl8187_rx_info { - struct urb *urb; - struct ieee80211_hw *dev; -}; - -struct rtl8187_rx_hdr { - __le32 flags; - u8 noise; - u8 signal; - u8 agc; - u8 reserved; - __le64 mac_time; -} __attribute__((packed)); - -struct rtl8187b_rx_hdr { - __le32 flags; - __le64 mac_time; - u8 sq; - u8 rssi; - u8 agc; - u8 flags2; - __le16 snr_long2end; - s8 pwdb_g12; - u8 fot; -} __attribute__((packed)); - -/* {rtl8187,rtl8187b}_tx_info is in skb */ - -struct rtl8187_tx_hdr { - __le32 flags; - __le16 rts_duration; - __le16 len; - __le32 retry; -} __attribute__((packed)); - -struct rtl8187b_tx_hdr { - __le32 flags; - __le16 rts_duration; - __le16 len; - __le32 unused_1; - __le16 unused_2; - __le16 tx_duration; - __le32 unused_3; - __le32 retry; - __le32 unused_4[2]; -} __attribute__((packed)); - -enum { - DEVICE_RTL8187, - DEVICE_RTL8187B -}; - -struct rtl8187_priv { - /* common between rtl818x drivers */ - struct rtl818x_csr *map; - const struct rtl818x_rf_ops *rf; - struct ieee80211_vif *vif; - int mode; - /* The mutex protects the TX loopback state. - * Any attempt to set channels concurrently locks the device. - */ - struct mutex conf_mutex; - - /* rtl8187 specific */ - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_supported_band band; - struct usb_device *udev; - u32 rx_conf; - struct usb_anchor anchored; - struct delayed_work work; - struct ieee80211_hw *dev; -#ifdef CONFIG_RTL8187_LEDS - struct rtl8187_led led_tx; - struct rtl8187_led led_rx; - struct delayed_work led_on; - struct delayed_work led_off; -#endif - u16 txpwr_base; - u8 asic_rev; - u8 is_rtl8187b; - enum { - RTL8187BvB, - RTL8187BvD, - RTL8187BvE - } hw_rev; - struct sk_buff_head rx_queue; - u8 signal; - u8 quality; - u8 noise; - u8 slot_time; - u8 aifsn[4]; - u8 rfkill_mask; - struct { - __le64 buf; - struct sk_buff_head queue; - } b_tx_status; /* This queue is used by both -b and non-b devices */ - struct mutex io_mutex; - union { - u8 bits8; - __le16 bits16; - __le32 bits32; - } *io_dmabuf; - bool rfkill_off; -}; - -void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data); - -static inline u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv, - u8 *addr, u8 idx) -{ - u8 val; - - mutex_lock(&priv->io_mutex); - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); - - val = priv->io_dmabuf->bits8; - mutex_unlock(&priv->io_mutex); - - return val; -} - -static inline u8 rtl818x_ioread8(struct rtl8187_priv *priv, u8 *addr) -{ - return rtl818x_ioread8_idx(priv, addr, 0); -} - -static inline u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv, - __le16 *addr, u8 idx) -{ - __le16 val; - - mutex_lock(&priv->io_mutex); - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); - - val = priv->io_dmabuf->bits16; - mutex_unlock(&priv->io_mutex); - - return le16_to_cpu(val); -} - -static inline u16 rtl818x_ioread16(struct rtl8187_priv *priv, __le16 *addr) -{ - return rtl818x_ioread16_idx(priv, addr, 0); -} - -static inline u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv, - __le32 *addr, u8 idx) -{ - __le32 val; - - mutex_lock(&priv->io_mutex); - usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0), - RTL8187_REQ_GET_REG, RTL8187_REQT_READ, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); - - val = priv->io_dmabuf->bits32; - mutex_unlock(&priv->io_mutex); - - return le32_to_cpu(val); -} - -static inline u32 rtl818x_ioread32(struct rtl8187_priv *priv, __le32 *addr) -{ - return rtl818x_ioread32_idx(priv, addr, 0); -} - -static inline void rtl818x_iowrite8_idx(struct rtl8187_priv *priv, - u8 *addr, u8 val, u8 idx) -{ - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits8 = val; - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits8, sizeof(val), HZ / 2); - - mutex_unlock(&priv->io_mutex); -} - -static inline void rtl818x_iowrite8(struct rtl8187_priv *priv, u8 *addr, u8 val) -{ - rtl818x_iowrite8_idx(priv, addr, val, 0); -} - -static inline void rtl818x_iowrite16_idx(struct rtl8187_priv *priv, - __le16 *addr, u16 val, u8 idx) -{ - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits16 = cpu_to_le16(val); - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits16, sizeof(val), HZ / 2); - - mutex_unlock(&priv->io_mutex); -} - -static inline void rtl818x_iowrite16(struct rtl8187_priv *priv, __le16 *addr, - u16 val) -{ - rtl818x_iowrite16_idx(priv, addr, val, 0); -} - -static inline void rtl818x_iowrite32_idx(struct rtl8187_priv *priv, - __le32 *addr, u32 val, u8 idx) -{ - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits32 = cpu_to_le32(val); - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - (unsigned long)addr, idx & 0x03, - &priv->io_dmabuf->bits32, sizeof(val), HZ / 2); - - mutex_unlock(&priv->io_mutex); -} - -static inline void rtl818x_iowrite32(struct rtl8187_priv *priv, __le32 *addr, - u32 val) -{ - rtl818x_iowrite32_idx(priv, addr, val, 0); -} - -#endif /* RTL8187_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c deleted file mode 100644 index 9921147edc29..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ /dev/null @@ -1,1589 +0,0 @@ -/* - * Linux device driver for RTL8187 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * The driver was extended to the RTL8187B in 2008 by: - * Herton Ronaldo Krzesinski - * Hin-Tak Leung - * Larry Finger - * - * Magic delays and register offsets below are taken from the original - * r8187 driver sources. Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include - -#include "rtl8187.h" -#include "rtl8187_rtl8225.h" -#ifdef CONFIG_RTL8187_LEDS -#include "rtl8187_leds.h" -#endif -#include "rtl8187_rfkill.h" - -MODULE_AUTHOR("Michael Wu "); -MODULE_AUTHOR("Andrea Merello "); -MODULE_AUTHOR("Herton Ronaldo Krzesinski "); -MODULE_AUTHOR("Hin-Tak Leung "); -MODULE_AUTHOR("Larry Finger "); -MODULE_DESCRIPTION("RTL8187/RTL8187B USB wireless driver"); -MODULE_LICENSE("GPL"); - -static struct usb_device_id rtl8187_table[] __devinitdata = { - /* Asus */ - {USB_DEVICE(0x0b05, 0x171d), .driver_info = DEVICE_RTL8187}, - /* Belkin */ - {USB_DEVICE(0x050d, 0x705e), .driver_info = DEVICE_RTL8187B}, - /* Realtek */ - {USB_DEVICE(0x0bda, 0x8187), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0bda, 0x8189), .driver_info = DEVICE_RTL8187B}, - {USB_DEVICE(0x0bda, 0x8197), .driver_info = DEVICE_RTL8187B}, - {USB_DEVICE(0x0bda, 0x8198), .driver_info = DEVICE_RTL8187B}, - /* Surecom */ - {USB_DEVICE(0x0769, 0x11F2), .driver_info = DEVICE_RTL8187}, - /* Logitech */ - {USB_DEVICE(0x0789, 0x010C), .driver_info = DEVICE_RTL8187}, - /* Netgear */ - {USB_DEVICE(0x0846, 0x6100), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0846, 0x6a00), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0846, 0x4260), .driver_info = DEVICE_RTL8187B}, - /* HP */ - {USB_DEVICE(0x03f0, 0xca02), .driver_info = DEVICE_RTL8187}, - /* Sitecom */ - {USB_DEVICE(0x0df6, 0x000d), .driver_info = DEVICE_RTL8187}, - {USB_DEVICE(0x0df6, 0x0028), .driver_info = DEVICE_RTL8187B}, - {USB_DEVICE(0x0df6, 0x0029), .driver_info = DEVICE_RTL8187B}, - /* Sphairon Access Systems GmbH */ - {USB_DEVICE(0x114B, 0x0150), .driver_info = DEVICE_RTL8187}, - /* Dick Smith Electronics */ - {USB_DEVICE(0x1371, 0x9401), .driver_info = DEVICE_RTL8187}, - /* Abocom */ - {USB_DEVICE(0x13d1, 0xabe6), .driver_info = DEVICE_RTL8187}, - /* Qcom */ - {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, - /* AirLive */ - {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, - /* Linksys */ - {USB_DEVICE(0x1737, 0x0073), .driver_info = DEVICE_RTL8187B}, - {} -}; - -MODULE_DEVICE_TABLE(usb, rtl8187_table); - -static const struct ieee80211_rate rtl818x_rates[] = { - { .bitrate = 10, .hw_value = 0, }, - { .bitrate = 20, .hw_value = 1, }, - { .bitrate = 55, .hw_value = 2, }, - { .bitrate = 110, .hw_value = 3, }, - { .bitrate = 60, .hw_value = 4, }, - { .bitrate = 90, .hw_value = 5, }, - { .bitrate = 120, .hw_value = 6, }, - { .bitrate = 180, .hw_value = 7, }, - { .bitrate = 240, .hw_value = 8, }, - { .bitrate = 360, .hw_value = 9, }, - { .bitrate = 480, .hw_value = 10, }, - { .bitrate = 540, .hw_value = 11, }, -}; - -static const struct ieee80211_channel rtl818x_channels[] = { - { .center_freq = 2412 }, - { .center_freq = 2417 }, - { .center_freq = 2422 }, - { .center_freq = 2427 }, - { .center_freq = 2432 }, - { .center_freq = 2437 }, - { .center_freq = 2442 }, - { .center_freq = 2447 }, - { .center_freq = 2452 }, - { .center_freq = 2457 }, - { .center_freq = 2462 }, - { .center_freq = 2467 }, - { .center_freq = 2472 }, - { .center_freq = 2484 }, -}; - -static void rtl8187_iowrite_async_cb(struct urb *urb) -{ - kfree(urb->context); -} - -static void rtl8187_iowrite_async(struct rtl8187_priv *priv, __le16 addr, - void *data, u16 len) -{ - struct usb_ctrlrequest *dr; - struct urb *urb; - struct rtl8187_async_write_data { - u8 data[4]; - struct usb_ctrlrequest dr; - } *buf; - int rc; - - buf = kmalloc(sizeof(*buf), GFP_ATOMIC); - if (!buf) - return; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(buf); - return; - } - - dr = &buf->dr; - - dr->bRequestType = RTL8187_REQT_WRITE; - dr->bRequest = RTL8187_REQ_SET_REG; - dr->wValue = addr; - dr->wIndex = 0; - dr->wLength = cpu_to_le16(len); - - memcpy(buf, data, len); - - usb_fill_control_urb(urb, priv->udev, usb_sndctrlpipe(priv->udev, 0), - (unsigned char *)dr, buf, len, - rtl8187_iowrite_async_cb, buf); - usb_anchor_urb(urb, &priv->anchored); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) { - kfree(buf); - usb_unanchor_urb(urb); - } - usb_free_urb(urb); -} - -static inline void rtl818x_iowrite32_async(struct rtl8187_priv *priv, - __le32 *addr, u32 val) -{ - __le32 buf = cpu_to_le32(val); - - rtl8187_iowrite_async(priv, cpu_to_le16((unsigned long)addr), - &buf, sizeof(buf)); -} - -void rtl8187_write_phy(struct ieee80211_hw *dev, u8 addr, u32 data) -{ - struct rtl8187_priv *priv = dev->priv; - - data <<= 8; - data |= addr | 0x80; - - rtl818x_iowrite8(priv, &priv->map->PHY[3], (data >> 24) & 0xFF); - rtl818x_iowrite8(priv, &priv->map->PHY[2], (data >> 16) & 0xFF); - rtl818x_iowrite8(priv, &priv->map->PHY[1], (data >> 8) & 0xFF); - rtl818x_iowrite8(priv, &priv->map->PHY[0], data & 0xFF); -} - -static void rtl8187_tx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *)urb->context; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->rate_driver_data[0]; - struct rtl8187_priv *priv = hw->priv; - - skb_pull(skb, priv->is_rtl8187b ? sizeof(struct rtl8187b_tx_hdr) : - sizeof(struct rtl8187_tx_hdr)); - ieee80211_tx_info_clear_status(info); - - if (!(urb->status) && !(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (priv->is_rtl8187b) { - skb_queue_tail(&priv->b_tx_status.queue, skb); - - /* queue is "full", discard last items */ - while (skb_queue_len(&priv->b_tx_status.queue) > 5) { - struct sk_buff *old_skb; - - dev_dbg(&priv->udev->dev, - "transmit status queue full\n"); - - old_skb = skb_dequeue(&priv->b_tx_status.queue); - ieee80211_tx_status_irqsafe(hw, old_skb); - } - return; - } else { - info->flags |= IEEE80211_TX_STAT_ACK; - } - } - if (priv->is_rtl8187b) - ieee80211_tx_status_irqsafe(hw, skb); - else { - /* Retry information for the RTI8187 is only available by - * reading a register in the device. We are in interrupt mode - * here, thus queue the skb and finish on a work queue. */ - skb_queue_tail(&priv->b_tx_status.queue, skb); - ieee80211_queue_delayed_work(hw, &priv->work, 0); - } -} - -static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) -{ - struct rtl8187_priv *priv = dev->priv; - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - unsigned int ep; - void *buf; - struct urb *urb; - __le16 rts_dur = 0; - u32 flags; - int rc; - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree_skb(skb); - return NETDEV_TX_OK; - } - - flags = skb->len; - flags |= RTL818X_TX_DESC_FLAG_NO_ENC; - - flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24; - if (ieee80211_has_morefrags(((struct ieee80211_hdr *)skb->data)->frame_control)) - flags |= RTL818X_TX_DESC_FLAG_MOREFRAG; - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) { - flags |= RTL818X_TX_DESC_FLAG_RTS; - flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - rts_dur = ieee80211_rts_duration(dev, priv->vif, - skb->len, info); - } else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) { - flags |= RTL818X_TX_DESC_FLAG_CTS; - flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19; - } - - if (!priv->is_rtl8187b) { - struct rtl8187_tx_hdr *hdr = - (struct rtl8187_tx_hdr *)skb_push(skb, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->len = 0; - hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); - buf = hdr; - - ep = 2; - } else { - /* fc needs to be calculated before skb_push() */ - unsigned int epmap[4] = { 6, 7, 5, 4 }; - struct ieee80211_hdr *tx_hdr = - (struct ieee80211_hdr *)(skb->data); - u16 fc = le16_to_cpu(tx_hdr->frame_control); - - struct rtl8187b_tx_hdr *hdr = - (struct rtl8187b_tx_hdr *)skb_push(skb, sizeof(*hdr)); - struct ieee80211_rate *txrate = - ieee80211_get_tx_rate(dev, info); - memset(hdr, 0, sizeof(*hdr)); - hdr->flags = cpu_to_le32(flags); - hdr->rts_duration = rts_dur; - hdr->retry = cpu_to_le32((info->control.rates[0].count - 1) << 8); - hdr->tx_duration = - ieee80211_generic_frame_duration(dev, priv->vif, - skb->len, txrate); - buf = hdr; - - if ((fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_MGMT) - ep = 12; - else - ep = epmap[skb_get_queue_mapping(skb)]; - } - - info->rate_driver_data[0] = dev; - info->rate_driver_data[1] = urb; - - usb_fill_bulk_urb(urb, priv->udev, usb_sndbulkpipe(priv->udev, ep), - buf, skb->len, rtl8187_tx_cb, skb); - urb->transfer_flags |= URB_ZERO_PACKET; - usb_anchor_urb(urb, &priv->anchored); - rc = usb_submit_urb(urb, GFP_ATOMIC); - if (rc < 0) { - usb_unanchor_urb(urb); - kfree_skb(skb); - } - usb_free_urb(urb); - - return NETDEV_TX_OK; -} - -static void rtl8187_rx_cb(struct urb *urb) -{ - struct sk_buff *skb = (struct sk_buff *)urb->context; - struct rtl8187_rx_info *info = (struct rtl8187_rx_info *)skb->cb; - struct ieee80211_hw *dev = info->dev; - struct rtl8187_priv *priv = dev->priv; - struct ieee80211_rx_status rx_status = { 0 }; - int rate, signal; - u32 flags; - u32 quality; - unsigned long f; - - spin_lock_irqsave(&priv->rx_queue.lock, f); - __skb_unlink(skb, &priv->rx_queue); - spin_unlock_irqrestore(&priv->rx_queue.lock, f); - skb_put(skb, urb->actual_length); - - if (unlikely(urb->status)) { - dev_kfree_skb_irq(skb); - return; - } - - if (!priv->is_rtl8187b) { - struct rtl8187_rx_hdr *hdr = - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); - flags = le32_to_cpu(hdr->flags); - /* As with the RTL8187B below, the AGC is used to calculate - * signal strength and quality. In this case, the scaling - * constants are derived from the output of p54usb. - */ - quality = 130 - ((41 * hdr->agc) >> 6); - signal = -4 - ((27 * hdr->agc) >> 6); - rx_status.antenna = (hdr->signal >> 7) & 1; - rx_status.mactime = le64_to_cpu(hdr->mac_time); - } else { - struct rtl8187b_rx_hdr *hdr = - (typeof(hdr))(skb_tail_pointer(skb) - sizeof(*hdr)); - /* The Realtek datasheet for the RTL8187B shows that the RX - * header contains the following quantities: signal quality, - * RSSI, AGC, the received power in dB, and the measured SNR. - * In testing, none of these quantities show qualitative - * agreement with AP signal strength, except for the AGC, - * which is inversely proportional to the strength of the - * signal. In the following, the quality and signal strength - * are derived from the AGC. The arbitrary scaling constants - * are chosen to make the results close to the values obtained - * for a BCM4312 using b43 as the driver. The noise is ignored - * for now. - */ - flags = le32_to_cpu(hdr->flags); - quality = 170 - hdr->agc; - signal = 14 - hdr->agc / 2; - rx_status.antenna = (hdr->rssi >> 7) & 1; - rx_status.mactime = le64_to_cpu(hdr->mac_time); - } - - if (quality > 100) - quality = 100; - rx_status.qual = quality; - priv->quality = quality; - rx_status.signal = signal; - priv->signal = signal; - rate = (flags >> 20) & 0xF; - skb_trim(skb, flags & 0x0FFF); - rx_status.rate_idx = rate; - rx_status.freq = dev->conf.channel->center_freq; - rx_status.band = dev->conf.channel->band; - rx_status.flag |= RX_FLAG_TSFT; - if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR) - rx_status.flag |= RX_FLAG_FAILED_FCS_CRC; - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx_irqsafe(dev, skb); - - skb = dev_alloc_skb(RTL8187_MAX_RX); - if (unlikely(!skb)) { - /* TODO check rx queue length and refill *somewhere* */ - return; - } - - info = (struct rtl8187_rx_info *)skb->cb; - info->urb = urb; - info->dev = dev; - urb->transfer_buffer = skb_tail_pointer(skb); - urb->context = skb; - skb_queue_tail(&priv->rx_queue, skb); - - usb_anchor_urb(urb, &priv->anchored); - if (usb_submit_urb(urb, GFP_ATOMIC)) { - usb_unanchor_urb(urb); - skb_unlink(skb, &priv->rx_queue); - dev_kfree_skb_irq(skb); - } -} - -static int rtl8187_init_urbs(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - struct urb *entry = NULL; - struct sk_buff *skb; - struct rtl8187_rx_info *info; - int ret = 0; - - while (skb_queue_len(&priv->rx_queue) < 16) { - skb = __dev_alloc_skb(RTL8187_MAX_RX, GFP_KERNEL); - if (!skb) { - ret = -ENOMEM; - goto err; - } - entry = usb_alloc_urb(0, GFP_KERNEL); - if (!entry) { - ret = -ENOMEM; - goto err; - } - usb_fill_bulk_urb(entry, priv->udev, - usb_rcvbulkpipe(priv->udev, - priv->is_rtl8187b ? 3 : 1), - skb_tail_pointer(skb), - RTL8187_MAX_RX, rtl8187_rx_cb, skb); - info = (struct rtl8187_rx_info *)skb->cb; - info->urb = entry; - info->dev = dev; - skb_queue_tail(&priv->rx_queue, skb); - usb_anchor_urb(entry, &priv->anchored); - ret = usb_submit_urb(entry, GFP_KERNEL); - if (ret) { - skb_unlink(skb, &priv->rx_queue); - usb_unanchor_urb(entry); - goto err; - } - usb_free_urb(entry); - } - return ret; - -err: - usb_free_urb(entry); - kfree_skb(skb); - usb_kill_anchored_urbs(&priv->anchored); - return ret; -} - -static void rtl8187b_status_cb(struct urb *urb) -{ - struct ieee80211_hw *hw = (struct ieee80211_hw *)urb->context; - struct rtl8187_priv *priv = hw->priv; - u64 val; - unsigned int cmd_type; - - if (unlikely(urb->status)) - return; - - /* - * Read from status buffer: - * - * bits [30:31] = cmd type: - * - 0 indicates tx beacon interrupt - * - 1 indicates tx close descriptor - * - * In the case of tx beacon interrupt: - * [0:9] = Last Beacon CW - * [10:29] = reserved - * [30:31] = 00b - * [32:63] = Last Beacon TSF - * - * If it's tx close descriptor: - * [0:7] = Packet Retry Count - * [8:14] = RTS Retry Count - * [15] = TOK - * [16:27] = Sequence No - * [28] = LS - * [29] = FS - * [30:31] = 01b - * [32:47] = unused (reserved?) - * [48:63] = MAC Used Time - */ - val = le64_to_cpu(priv->b_tx_status.buf); - - cmd_type = (val >> 30) & 0x3; - if (cmd_type == 1) { - unsigned int pkt_rc, seq_no; - bool tok; - struct sk_buff *skb; - struct ieee80211_hdr *ieee80211hdr; - unsigned long flags; - - pkt_rc = val & 0xFF; - tok = val & (1 << 15); - seq_no = (val >> 16) & 0xFFF; - - spin_lock_irqsave(&priv->b_tx_status.queue.lock, flags); - skb_queue_reverse_walk(&priv->b_tx_status.queue, skb) { - ieee80211hdr = (struct ieee80211_hdr *)skb->data; - - /* - * While testing, it was discovered that the seq_no - * doesn't actually contains the sequence number. - * Instead of returning just the 12 bits of sequence - * number, hardware is returning entire sequence control - * (fragment number plus sequence number) in a 12 bit - * only field overflowing after some time. As a - * workaround, just consider the lower bits, and expect - * it's unlikely we wrongly ack some sent data - */ - if ((le16_to_cpu(ieee80211hdr->seq_ctrl) - & 0xFFF) == seq_no) - break; - } - if (skb != (struct sk_buff *) &priv->b_tx_status.queue) { - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - __skb_unlink(skb, &priv->b_tx_status.queue); - if (tok) - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.rates[0].count = pkt_rc + 1; - - ieee80211_tx_status_irqsafe(hw, skb); - } - spin_unlock_irqrestore(&priv->b_tx_status.queue.lock, flags); - } - - usb_anchor_urb(urb, &priv->anchored); - if (usb_submit_urb(urb, GFP_ATOMIC)) - usb_unanchor_urb(urb); -} - -static int rtl8187b_init_status_urb(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - struct urb *entry; - int ret = 0; - - entry = usb_alloc_urb(0, GFP_KERNEL); - if (!entry) - return -ENOMEM; - - usb_fill_bulk_urb(entry, priv->udev, usb_rcvbulkpipe(priv->udev, 9), - &priv->b_tx_status.buf, sizeof(priv->b_tx_status.buf), - rtl8187b_status_cb, dev); - - usb_anchor_urb(entry, &priv->anchored); - ret = usb_submit_urb(entry, GFP_KERNEL); - if (ret) - usb_unanchor_urb(entry); - usb_free_urb(entry); - - return ret; -} - -static int rtl8187_cmd_reset(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - u8 reg; - int i; - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= (1 << 1); - reg |= RTL818X_CMD_RESET; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - i = 10; - do { - msleep(2); - if (!(rtl818x_ioread8(priv, &priv->map->CMD) & - RTL818X_CMD_RESET)) - break; - } while (--i); - - if (!i) { - printk(KERN_ERR "%s: Reset timeout!\n", wiphy_name(dev->wiphy)); - return -ETIMEDOUT; - } - - /* reload registers from eeprom */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_LOAD); - - i = 10; - do { - msleep(4); - if (!(rtl818x_ioread8(priv, &priv->map->EEPROM_CMD) & - RTL818X_EEPROM_CMD_CONFIG)) - break; - } while (--i); - - if (!i) { - printk(KERN_ERR "%s: eeprom reset timeout!\n", - wiphy_name(dev->wiphy)); - return -ETIMEDOUT; - } - - return 0; -} - -static int rtl8187_init_hw(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - u8 reg; - int res; - - /* reset */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | - RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & - ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - msleep(200); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x10); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x11); - rtl818x_iowrite8(priv, (u8 *)0xFE18, 0x00); - msleep(200); - - res = rtl8187_cmd_reset(dev); - if (res) - return res; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - /* setup card */ - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0); - - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 1); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - - rtl818x_iowrite16(priv, (__le16 *)0xFFF4, 0xFFFF); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); - reg &= 0x3F; - reg |= 0x80; - rtl818x_iowrite8(priv, &priv->map->CONFIG1, reg); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite32(priv, &priv->map->INT_TIMEOUT, 0); - rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - rtl818x_iowrite8(priv, &priv->map->RATE_FALLBACK, 0); - - // TODO: set RESP_RATE and BRSR properly - rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (8 << 4) | 0); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); - - /* host_usb_init */ - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0); - reg = rtl818x_ioread8(priv, (u8 *)0xFE53); - rtl818x_iowrite8(priv, (u8 *)0xFE53, reg | (1 << 7)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, (4 << 8)); - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x20); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x80); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x80); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x80); - msleep(100); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x000a8008); - rtl818x_iowrite16(priv, &priv->map->BRSR, 0xFFFF); - rtl818x_iowrite32(priv, &priv->map->RF_PARA, 0x00100044); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, 0x44); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FF7); - msleep(100); - - priv->rf->init(dev); - - rtl818x_iowrite16(priv, &priv->map->BRSR, 0x01F3); - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1; - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); - rtl818x_iowrite16(priv, (__le16 *)0xFFFE, 0x10); - rtl818x_iowrite8(priv, &priv->map->TALLY_SEL, 0x80); - rtl818x_iowrite8(priv, (u8 *)0xFFFF, 0x60); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - - return 0; -} - -static const u8 rtl8187b_reg_table[][3] = { - {0xF0, 0x32, 0}, {0xF1, 0x32, 0}, {0xF2, 0x00, 0}, {0xF3, 0x00, 0}, - {0xF4, 0x32, 0}, {0xF5, 0x43, 0}, {0xF6, 0x00, 0}, {0xF7, 0x00, 0}, - {0xF8, 0x46, 0}, {0xF9, 0xA4, 0}, {0xFA, 0x00, 0}, {0xFB, 0x00, 0}, - {0xFC, 0x96, 0}, {0xFD, 0xA4, 0}, {0xFE, 0x00, 0}, {0xFF, 0x00, 0}, - - {0x58, 0x4B, 1}, {0x59, 0x00, 1}, {0x5A, 0x4B, 1}, {0x5B, 0x00, 1}, - {0x60, 0x4B, 1}, {0x61, 0x09, 1}, {0x62, 0x4B, 1}, {0x63, 0x09, 1}, - {0xCE, 0x0F, 1}, {0xCF, 0x00, 1}, {0xE0, 0xFF, 1}, {0xE1, 0x0F, 1}, - {0xE2, 0x00, 1}, {0xF0, 0x4E, 1}, {0xF1, 0x01, 1}, {0xF2, 0x02, 1}, - {0xF3, 0x03, 1}, {0xF4, 0x04, 1}, {0xF5, 0x05, 1}, {0xF6, 0x06, 1}, - {0xF7, 0x07, 1}, {0xF8, 0x08, 1}, - - {0x4E, 0x00, 2}, {0x0C, 0x04, 2}, {0x21, 0x61, 2}, {0x22, 0x68, 2}, - {0x23, 0x6F, 2}, {0x24, 0x76, 2}, {0x25, 0x7D, 2}, {0x26, 0x84, 2}, - {0x27, 0x8D, 2}, {0x4D, 0x08, 2}, {0x50, 0x05, 2}, {0x51, 0xF5, 2}, - {0x52, 0x04, 2}, {0x53, 0xA0, 2}, {0x54, 0x1F, 2}, {0x55, 0x23, 2}, - {0x56, 0x45, 2}, {0x57, 0x67, 2}, {0x58, 0x08, 2}, {0x59, 0x08, 2}, - {0x5A, 0x08, 2}, {0x5B, 0x08, 2}, {0x60, 0x08, 2}, {0x61, 0x08, 2}, - {0x62, 0x08, 2}, {0x63, 0x08, 2}, {0x64, 0xCF, 2}, {0x72, 0x56, 2}, - {0x73, 0x9A, 2}, - - {0x34, 0xF0, 0}, {0x35, 0x0F, 0}, {0x5B, 0x40, 0}, {0x84, 0x88, 0}, - {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, - {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, - {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, - {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2}, - - {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0}, - {0x8F, 0x00, 0} -}; - -static int rtl8187b_init_hw(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int res, i; - u8 reg; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187B_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187B_RTL8225_ANAPARAM_ON); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, - RTL8187B_RTL8225_ANAPARAM3_ON); - - rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10); - reg = rtl818x_ioread8(priv, (u8 *)0xFF62); - rtl818x_iowrite8(priv, (u8 *)0xFF62, reg & ~(1 << 5)); - rtl818x_iowrite8(priv, (u8 *)0xFF62, reg | (1 << 5)); - - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg &= ~RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - - res = rtl8187_cmd_reset(dev); - if (res) - return res; - - rtl818x_iowrite16(priv, (__le16 *)0xFF2D, 0x0FFF); - reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); - reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; - rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg |= RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT | - RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); - - rtl818x_iowrite16_idx(priv, (__le16 *)0xFFE0, 0x0FFF, 1); - - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFFD4, 0xFFFF, 1); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG1); - rtl818x_iowrite8(priv, &priv->map->CONFIG1, (reg & 0x3F) | 0x80); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite8(priv, &priv->map->WPA_CONF, 0); - for (i = 0; i < ARRAY_SIZE(rtl8187b_reg_table); i++) { - rtl818x_iowrite8_idx(priv, - (u8 *)(uintptr_t) - (rtl8187b_reg_table[i][0] | 0xFF00), - rtl8187b_reg_table[i][1], - rtl8187b_reg_table[i][2]); - } - - rtl818x_iowrite16(priv, &priv->map->TID_AC_MAP, 0xFA50); - rtl818x_iowrite16(priv, &priv->map->INT_MIG, 0); - - rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF0, 0, 1); - rtl818x_iowrite32_idx(priv, (__le32 *)0xFFF4, 0, 1); - rtl818x_iowrite8_idx(priv, (u8 *)0xFFF8, 0, 1); - - rtl818x_iowrite32(priv, &priv->map->RF_TIMING, 0x00004001); - - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x569A, 2); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - reg |= RTL818X_CONFIG3_ANAPARAM_WRITE; - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, - RTL818X_EEPROM_CMD_NORMAL); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x0480); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, 0x2488); - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, 0x1FFF); - msleep(100); - - priv->rf->init(dev); - - reg = RTL818X_CMD_TX_ENABLE | RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); - - rtl818x_iowrite8(priv, (u8 *)0xFE41, 0xF4); - rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x00); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); - rtl818x_iowrite8(priv, (u8 *)0xFE40, 0x0F); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x00); - rtl818x_iowrite8(priv, (u8 *)0xFE42, 0x01); - - reg = rtl818x_ioread8(priv, (u8 *)0xFFDB); - rtl818x_iowrite8(priv, (u8 *)0xFFDB, reg | (1 << 2)); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF72, 0x59FA, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF74, 0x59D2, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF76, 0x59D2, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF78, 0x19FA, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7A, 0x19FA, 3); - rtl818x_iowrite16_idx(priv, (__le16 *)0xFF7C, 0x00D0, 3); - rtl818x_iowrite8(priv, (u8 *)0xFF61, 0); - rtl818x_iowrite8_idx(priv, (u8 *)0xFF80, 0x0F, 1); - rtl818x_iowrite8_idx(priv, (u8 *)0xFF83, 0x03, 1); - rtl818x_iowrite8(priv, (u8 *)0xFFDA, 0x10); - rtl818x_iowrite8_idx(priv, (u8 *)0xFF4D, 0x08, 2); - - rtl818x_iowrite32(priv, &priv->map->HSSI_PARA, 0x0600321B); - - rtl818x_iowrite16_idx(priv, (__le16 *)0xFFEC, 0x0800, 1); - - priv->slot_time = 0x9; - priv->aifsn[0] = 2; /* AIFSN[AC_VO] */ - priv->aifsn[1] = 2; /* AIFSN[AC_VI] */ - priv->aifsn[2] = 7; /* AIFSN[AC_BK] */ - priv->aifsn[3] = 3; /* AIFSN[AC_BE] */ - rtl818x_iowrite8(priv, &priv->map->ACM_CONTROL, 0); - - /* ENEDCA flag must always be set, transmit issues? */ - rtl818x_iowrite8(priv, &priv->map->MSR, RTL818X_MSR_ENEDCA); - - return 0; -} - -static void rtl8187_work(struct work_struct *work) -{ - /* The RTL8187 returns the retry count through register 0xFFFA. In - * addition, it appears to be a cumulative retry count, not the - * value for the current TX packet. When multiple TX entries are - * queued, the retry count will be valid for the last one in the queue. - * The "error" should not matter for purposes of rate setting. */ - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - work.work); - struct ieee80211_tx_info *info; - struct ieee80211_hw *dev = priv->dev; - static u16 retry; - u16 tmp; - - mutex_lock(&priv->conf_mutex); - tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA); - while (skb_queue_len(&priv->b_tx_status.queue) > 0) { - struct sk_buff *old_skb; - - old_skb = skb_dequeue(&priv->b_tx_status.queue); - info = IEEE80211_SKB_CB(old_skb); - info->status.rates[0].count = tmp - retry + 1; - ieee80211_tx_status_irqsafe(dev, old_skb); - } - retry = tmp; - mutex_unlock(&priv->conf_mutex); -} - -static int rtl8187_start(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - u32 reg; - int ret; - - mutex_lock(&priv->conf_mutex); - - ret = (!priv->is_rtl8187b) ? rtl8187_init_hw(dev) : - rtl8187b_init_hw(dev); - if (ret) - goto rtl8187_start_exit; - - init_usb_anchor(&priv->anchored); - priv->dev = dev; - - if (priv->is_rtl8187b) { - reg = RTL818X_RX_CONF_MGMT | - RTL818X_RX_CONF_DATA | - RTL818X_RX_CONF_BROADCAST | - RTL818X_RX_CONF_NICMAC | - RTL818X_RX_CONF_BSSID | - (7 << 13 /* RX FIFO threshold NONE */) | - (7 << 10 /* MAX RX DMA */) | - RTL818X_RX_CONF_RX_AUTORESETPHY | - RTL818X_RX_CONF_ONLYERLPKT | - RTL818X_RX_CONF_MULTICAST; - priv->rx_conf = reg; - rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); - - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - RTL818X_TX_CONF_HW_SEQNUM | - RTL818X_TX_CONF_DISREQQSIZE | - (7 << 8 /* short retry limit */) | - (7 << 0 /* long retry limit */) | - (7 << 21 /* MAX TX DMA */)); - rtl8187_init_urbs(dev); - rtl8187b_init_status_urb(dev); - goto rtl8187_start_exit; - } - - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0xFFFF); - - rtl818x_iowrite32(priv, &priv->map->MAR[0], ~0); - rtl818x_iowrite32(priv, &priv->map->MAR[1], ~0); - - rtl8187_init_urbs(dev); - - reg = RTL818X_RX_CONF_ONLYERLPKT | - RTL818X_RX_CONF_RX_AUTORESETPHY | - RTL818X_RX_CONF_BSSID | - RTL818X_RX_CONF_MGMT | - RTL818X_RX_CONF_DATA | - (7 << 13 /* RX FIFO threshold NONE */) | - (7 << 10 /* MAX RX DMA */) | - RTL818X_RX_CONF_BROADCAST | - RTL818X_RX_CONF_NICMAC; - - priv->rx_conf = reg; - rtl818x_iowrite32(priv, &priv->map->RX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->CW_CONF); - reg &= ~RTL818X_CW_CONF_PERPACKET_CW_SHIFT; - reg |= RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT; - rtl818x_iowrite8(priv, &priv->map->CW_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->TX_AGC_CTL); - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT; - reg &= ~RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT; - reg &= ~RTL818X_TX_AGC_CTL_FEEDBACK_ANT; - rtl818x_iowrite8(priv, &priv->map->TX_AGC_CTL, reg); - - reg = RTL818X_TX_CONF_CW_MIN | - (7 << 21 /* MAX TX DMA */) | - RTL818X_TX_CONF_NO_ICV; - rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg |= RTL818X_CMD_TX_ENABLE; - reg |= RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - INIT_DELAYED_WORK(&priv->work, rtl8187_work); - -rtl8187_start_exit: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void rtl8187_stop(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - struct sk_buff *skb; - u32 reg; - - mutex_lock(&priv->conf_mutex); - rtl818x_iowrite16(priv, &priv->map->INT_MASK, 0); - - reg = rtl818x_ioread8(priv, &priv->map->CMD); - reg &= ~RTL818X_CMD_TX_ENABLE; - reg &= ~RTL818X_CMD_RX_ENABLE; - rtl818x_iowrite8(priv, &priv->map->CMD, reg); - - priv->rf->stop(dev); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG4); - rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - while ((skb = skb_dequeue(&priv->b_tx_status.queue))) - dev_kfree_skb_any(skb); - - usb_kill_anchored_urbs(&priv->anchored); - mutex_unlock(&priv->conf_mutex); - - if (!priv->is_rtl8187b) - cancel_delayed_work_sync(&priv->work); -} - -static int rtl8187_add_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - int ret = -EOPNOTSUPP; - - mutex_lock(&priv->conf_mutex); - if (priv->mode != NL80211_IFTYPE_MONITOR) - goto exit; - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - priv->mode = conf->type; - break; - default: - goto exit; - } - - ret = 0; - priv->vif = conf->vif; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->MAC[i], - ((u8 *)conf->mac_addr)[i]); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - -exit: - mutex_unlock(&priv->conf_mutex); - return ret; -} - -static void rtl8187_remove_interface(struct ieee80211_hw *dev, - struct ieee80211_if_init_conf *conf) -{ - struct rtl8187_priv *priv = dev->priv; - mutex_lock(&priv->conf_mutex); - priv->mode = NL80211_IFTYPE_MONITOR; - priv->vif = NULL; - mutex_unlock(&priv->conf_mutex); -} - -static int rtl8187_config(struct ieee80211_hw *dev, u32 changed) -{ - struct rtl8187_priv *priv = dev->priv; - struct ieee80211_conf *conf = &dev->conf; - u32 reg; - - mutex_lock(&priv->conf_mutex); - reg = rtl818x_ioread32(priv, &priv->map->TX_CONF); - /* Enable TX loopback on MAC level to avoid TX during channel - * changes, as this has be seen to causes problems and the - * card will stop work until next reset - */ - rtl818x_iowrite32(priv, &priv->map->TX_CONF, - reg | RTL818X_TX_CONF_LOOPBACK_MAC); - priv->rf->set_chan(dev, conf); - msleep(10); - rtl818x_iowrite32(priv, &priv->map->TX_CONF, reg); - - rtl818x_iowrite16(priv, &priv->map->ATIM_WND, 2); - rtl818x_iowrite16(priv, &priv->map->ATIMTR_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL, 100); - rtl818x_iowrite16(priv, &priv->map->BEACON_INTERVAL_TIME, 100); - mutex_unlock(&priv->conf_mutex); - return 0; -} - -/* - * With 8187B, AC_*_PARAM clashes with FEMR definition in struct rtl818x_csr for - * example. Thus we have to use raw values for AC_*_PARAM register addresses. - */ -static __le32 *rtl8187b_ac_addr[4] = { - (__le32 *) 0xFFF0, /* AC_VO */ - (__le32 *) 0xFFF4, /* AC_VI */ - (__le32 *) 0xFFFC, /* AC_BK */ - (__le32 *) 0xFFF8, /* AC_BE */ -}; - -#define SIFS_TIME 0xa - -static void rtl8187_conf_erp(struct rtl8187_priv *priv, bool use_short_slot, - bool use_short_preamble) -{ - if (priv->is_rtl8187b) { - u8 difs, eifs; - u16 ack_timeout; - int queue; - - if (use_short_slot) { - priv->slot_time = 0x9; - difs = 0x1c; - eifs = 0x53; - } else { - priv->slot_time = 0x14; - difs = 0x32; - eifs = 0x5b; - } - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - rtl818x_iowrite8(priv, &priv->map->SLOT, priv->slot_time); - rtl818x_iowrite8(priv, &priv->map->DIFS, difs); - - /* - * BRSR+1 on 8187B is in fact EIFS register - * Value in units of 4 us - */ - rtl818x_iowrite8(priv, (u8 *)&priv->map->BRSR + 1, eifs); - - /* - * For 8187B, CARRIER_SENSE_COUNTER is in fact ack timeout - * register. In units of 4 us like eifs register - * ack_timeout = ack duration + plcp + difs + preamble - */ - ack_timeout = 112 + 48 + difs; - if (use_short_preamble) - ack_timeout += 72; - else - ack_timeout += 144; - rtl818x_iowrite8(priv, &priv->map->CARRIER_SENSE_COUNTER, - DIV_ROUND_UP(ack_timeout, 4)); - - for (queue = 0; queue < 4; queue++) - rtl818x_iowrite8(priv, (u8 *) rtl8187b_ac_addr[queue], - priv->aifsn[queue] * priv->slot_time + - SIFS_TIME); - } else { - rtl818x_iowrite8(priv, &priv->map->SIFS, 0x22); - if (use_short_slot) { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x9); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x14); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x14); - } else { - rtl818x_iowrite8(priv, &priv->map->SLOT, 0x14); - rtl818x_iowrite8(priv, &priv->map->DIFS, 0x24); - rtl818x_iowrite8(priv, &priv->map->EIFS, 91 - 0x24); - } - } -} - -static void rtl8187_bss_info_changed(struct ieee80211_hw *dev, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *info, - u32 changed) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - u8 reg; - - if (changed & BSS_CHANGED_BSSID) { - mutex_lock(&priv->conf_mutex); - for (i = 0; i < ETH_ALEN; i++) - rtl818x_iowrite8(priv, &priv->map->BSSID[i], - info->bssid[i]); - - if (priv->is_rtl8187b) - reg = RTL818X_MSR_ENEDCA; - else - reg = 0; - - if (is_valid_ether_addr(info->bssid)) { - reg |= RTL818X_MSR_INFRA; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } else { - reg |= RTL818X_MSR_NO_LINK; - rtl818x_iowrite8(priv, &priv->map->MSR, reg); - } - - mutex_unlock(&priv->conf_mutex); - } - - if (changed & (BSS_CHANGED_ERP_SLOT | BSS_CHANGED_ERP_PREAMBLE)) - rtl8187_conf_erp(priv, info->use_short_slot, - info->use_short_preamble); -} - -static u64 rtl8187_prepare_multicast(struct ieee80211_hw *dev, - int mc_count, struct dev_addr_list *mc_list) -{ - return mc_count; -} - -static void rtl8187_configure_filter(struct ieee80211_hw *dev, - unsigned int changed_flags, - unsigned int *total_flags, - u64 multicast) -{ - struct rtl8187_priv *priv = dev->priv; - - if (changed_flags & FIF_FCSFAIL) - priv->rx_conf ^= RTL818X_RX_CONF_FCS; - if (changed_flags & FIF_CONTROL) - priv->rx_conf ^= RTL818X_RX_CONF_CTRL; - if (changed_flags & FIF_OTHER_BSS) - priv->rx_conf ^= RTL818X_RX_CONF_MONITOR; - if (*total_flags & FIF_ALLMULTI || multicast > 0) - priv->rx_conf |= RTL818X_RX_CONF_MULTICAST; - else - priv->rx_conf &= ~RTL818X_RX_CONF_MULTICAST; - - *total_flags = 0; - - if (priv->rx_conf & RTL818X_RX_CONF_FCS) - *total_flags |= FIF_FCSFAIL; - if (priv->rx_conf & RTL818X_RX_CONF_CTRL) - *total_flags |= FIF_CONTROL; - if (priv->rx_conf & RTL818X_RX_CONF_MONITOR) - *total_flags |= FIF_OTHER_BSS; - if (priv->rx_conf & RTL818X_RX_CONF_MULTICAST) - *total_flags |= FIF_ALLMULTI; - - rtl818x_iowrite32_async(priv, &priv->map->RX_CONF, priv->rx_conf); -} - -static int rtl8187_conf_tx(struct ieee80211_hw *dev, u16 queue, - const struct ieee80211_tx_queue_params *params) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cw_min, cw_max; - - if (queue > 3) - return -EINVAL; - - cw_min = fls(params->cw_min); - cw_max = fls(params->cw_max); - - if (priv->is_rtl8187b) { - priv->aifsn[queue] = params->aifs; - - /* - * This is the structure of AC_*_PARAM registers in 8187B: - * - TXOP limit field, bit offset = 16 - * - ECWmax, bit offset = 12 - * - ECWmin, bit offset = 8 - * - AIFS, bit offset = 0 - */ - rtl818x_iowrite32(priv, rtl8187b_ac_addr[queue], - (params->txop << 16) | (cw_max << 12) | - (cw_min << 8) | (params->aifs * - priv->slot_time + SIFS_TIME)); - } else { - if (queue != 0) - return -EINVAL; - - rtl818x_iowrite8(priv, &priv->map->CW_VAL, - cw_min | (cw_max << 4)); - } - return 0; -} - -static const struct ieee80211_ops rtl8187_ops = { - .tx = rtl8187_tx, - .start = rtl8187_start, - .stop = rtl8187_stop, - .add_interface = rtl8187_add_interface, - .remove_interface = rtl8187_remove_interface, - .config = rtl8187_config, - .bss_info_changed = rtl8187_bss_info_changed, - .prepare_multicast = rtl8187_prepare_multicast, - .configure_filter = rtl8187_configure_filter, - .conf_tx = rtl8187_conf_tx, - .rfkill_poll = rtl8187_rfkill_poll -}; - -static void rtl8187_eeprom_register_read(struct eeprom_93cx6 *eeprom) -{ - struct ieee80211_hw *dev = eeprom->data; - struct rtl8187_priv *priv = dev->priv; - u8 reg = rtl818x_ioread8(priv, &priv->map->EEPROM_CMD); - - eeprom->reg_data_in = reg & RTL818X_EEPROM_CMD_WRITE; - eeprom->reg_data_out = reg & RTL818X_EEPROM_CMD_READ; - eeprom->reg_data_clock = reg & RTL818X_EEPROM_CMD_CK; - eeprom->reg_chip_select = reg & RTL818X_EEPROM_CMD_CS; -} - -static void rtl8187_eeprom_register_write(struct eeprom_93cx6 *eeprom) -{ - struct ieee80211_hw *dev = eeprom->data; - struct rtl8187_priv *priv = dev->priv; - u8 reg = RTL818X_EEPROM_CMD_PROGRAM; - - if (eeprom->reg_data_in) - reg |= RTL818X_EEPROM_CMD_WRITE; - if (eeprom->reg_data_out) - reg |= RTL818X_EEPROM_CMD_READ; - if (eeprom->reg_data_clock) - reg |= RTL818X_EEPROM_CMD_CK; - if (eeprom->reg_chip_select) - reg |= RTL818X_EEPROM_CMD_CS; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, reg); - udelay(10); -} - -static int __devinit rtl8187_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct ieee80211_hw *dev; - struct rtl8187_priv *priv; - struct eeprom_93cx6 eeprom; - struct ieee80211_channel *channel; - const char *chip_name; - u16 txpwr, reg; - u16 product_id = le16_to_cpu(udev->descriptor.idProduct); - int err, i; - - dev = ieee80211_alloc_hw(sizeof(*priv), &rtl8187_ops); - if (!dev) { - printk(KERN_ERR "rtl8187: ieee80211 alloc failed\n"); - return -ENOMEM; - } - - priv = dev->priv; - priv->is_rtl8187b = (id->driver_info == DEVICE_RTL8187B); - - /* allocate "DMA aware" buffer for register accesses */ - priv->io_dmabuf = kmalloc(sizeof(*priv->io_dmabuf), GFP_KERNEL); - if (!priv->io_dmabuf) { - err = -ENOMEM; - goto err_free_dev; - } - mutex_init(&priv->io_mutex); - - SET_IEEE80211_DEV(dev, &intf->dev); - usb_set_intfdata(intf, dev); - priv->udev = udev; - - usb_get_dev(udev); - - skb_queue_head_init(&priv->rx_queue); - - BUILD_BUG_ON(sizeof(priv->channels) != sizeof(rtl818x_channels)); - BUILD_BUG_ON(sizeof(priv->rates) != sizeof(rtl818x_rates)); - - memcpy(priv->channels, rtl818x_channels, sizeof(rtl818x_channels)); - memcpy(priv->rates, rtl818x_rates, sizeof(rtl818x_rates)); - priv->map = (struct rtl818x_csr *)0xFF00; - - priv->band.band = IEEE80211_BAND_2GHZ; - priv->band.channels = priv->channels; - priv->band.n_channels = ARRAY_SIZE(rtl818x_channels); - priv->band.bitrates = priv->rates; - priv->band.n_bitrates = ARRAY_SIZE(rtl818x_rates); - dev->wiphy->bands[IEEE80211_BAND_2GHZ] = &priv->band; - - - priv->mode = NL80211_IFTYPE_MONITOR; - dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING | - IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_RX_INCLUDES_FCS; - - eeprom.data = dev; - eeprom.register_read = rtl8187_eeprom_register_read; - eeprom.register_write = rtl8187_eeprom_register_write; - if (rtl818x_ioread32(priv, &priv->map->RX_CONF) & (1 << 6)) - eeprom.width = PCI_EEPROM_WIDTH_93C66; - else - eeprom.width = PCI_EEPROM_WIDTH_93C46; - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - udelay(10); - - eeprom_93cx6_multiread(&eeprom, RTL8187_EEPROM_MAC_ADDR, - (__le16 __force *)dev->wiphy->perm_addr, 3); - if (!is_valid_ether_addr(dev->wiphy->perm_addr)) { - printk(KERN_WARNING "rtl8187: Invalid hwaddr! Using randomly " - "generated MAC address\n"); - random_ether_addr(dev->wiphy->perm_addr); - } - - channel = priv->channels; - for (i = 0; i < 3; i++) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_1 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_4 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_BASE, - &priv->txpwr_base); - - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~1; - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg | 1); - /* 0 means asic B-cut, we should use SW 3 wire - * bit-by-bit banging for radio. 1 means we can use - * USB specific request to write radio registers */ - priv->asic_rev = rtl818x_ioread8(priv, (u8 *)0xFFFE) & 0x3; - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - if (!priv->is_rtl8187b) { - u32 reg32; - reg32 = rtl818x_ioread32(priv, &priv->map->TX_CONF); - reg32 &= RTL818X_TX_CONF_HWVER_MASK; - switch (reg32) { - case RTL818X_TX_CONF_R8187vD_B: - /* Some RTL8187B devices have a USB ID of 0x8187 - * detect them here */ - chip_name = "RTL8187BvB(early)"; - priv->is_rtl8187b = 1; - priv->hw_rev = RTL8187BvB; - break; - case RTL818X_TX_CONF_R8187vD: - chip_name = "RTL8187vD"; - break; - default: - chip_name = "RTL8187vB (default)"; - } - } else { - /* - * Force USB request to write radio registers for 8187B, Realtek - * only uses it in their sources - */ - /*if (priv->asic_rev == 0) { - printk(KERN_WARNING "rtl8187: Forcing use of USB " - "requests to write to radio registers\n"); - priv->asic_rev = 1; - }*/ - switch (rtl818x_ioread8(priv, (u8 *)0xFFE1)) { - case RTL818X_R8187B_B: - chip_name = "RTL8187BvB"; - priv->hw_rev = RTL8187BvB; - break; - case RTL818X_R8187B_D: - chip_name = "RTL8187BvD"; - priv->hw_rev = RTL8187BvD; - break; - case RTL818X_R8187B_E: - chip_name = "RTL8187BvE"; - priv->hw_rev = RTL8187BvE; - break; - default: - chip_name = "RTL8187BvB (default)"; - priv->hw_rev = RTL8187BvB; - } - } - - if (!priv->is_rtl8187b) { - for (i = 0; i < 2; i++) { - eeprom_93cx6_read(&eeprom, - RTL8187_EEPROM_TXPWR_CHAN_6 + i, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - } else { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_TXPWR_CHAN_6, - &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x0A, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - - eeprom_93cx6_read(&eeprom, 0x1C, &txpwr); - (*channel++).hw_value = txpwr & 0xFF; - (*channel++).hw_value = txpwr >> 8; - } - /* Handle the differing rfkill GPIO bit in different models */ - priv->rfkill_mask = RFKILL_MASK_8187_89_97; - if (product_id == 0x8197 || product_id == 0x8198) { - eeprom_93cx6_read(&eeprom, RTL8187_EEPROM_SELECT_GPIO, ®); - if (reg & 0xFF00) - priv->rfkill_mask = RFKILL_MASK_8198; - } - - /* - * XXX: Once this driver supports anything that requires - * beacons it must implement IEEE80211_TX_CTL_ASSIGN_SEQ. - */ - dev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - - if ((id->driver_info == DEVICE_RTL8187) && priv->is_rtl8187b) - printk(KERN_INFO "rtl8187: inconsistency between id with OEM" - " info!\n"); - - priv->rf = rtl8187_detect_rf(dev); - dev->extra_tx_headroom = (!priv->is_rtl8187b) ? - sizeof(struct rtl8187_tx_hdr) : - sizeof(struct rtl8187b_tx_hdr); - if (!priv->is_rtl8187b) - dev->queues = 1; - else - dev->queues = 4; - - err = ieee80211_register_hw(dev); - if (err) { - printk(KERN_ERR "rtl8187: Cannot register device\n"); - goto err_free_dmabuf; - } - mutex_init(&priv->conf_mutex); - skb_queue_head_init(&priv->b_tx_status.queue); - - printk(KERN_INFO "%s: hwaddr %pM, %s V%d + %s, rfkill mask %d\n", - wiphy_name(dev->wiphy), dev->wiphy->perm_addr, - chip_name, priv->asic_rev, priv->rf->name, priv->rfkill_mask); - -#ifdef CONFIG_RTL8187_LEDS - eeprom_93cx6_read(&eeprom, 0x3F, ®); - reg &= 0xFF; - rtl8187_leds_init(dev, reg); -#endif - rtl8187_rfkill_init(dev); - - return 0; - - err_free_dmabuf: - kfree(priv->io_dmabuf); - err_free_dev: - ieee80211_free_hw(dev); - usb_set_intfdata(intf, NULL); - usb_put_dev(udev); - return err; -} - -static void __devexit rtl8187_disconnect(struct usb_interface *intf) -{ - struct ieee80211_hw *dev = usb_get_intfdata(intf); - struct rtl8187_priv *priv; - - if (!dev) - return; - -#ifdef CONFIG_RTL8187_LEDS - rtl8187_leds_exit(dev); -#endif - rtl8187_rfkill_exit(dev); - ieee80211_unregister_hw(dev); - - priv = dev->priv; - usb_reset_device(priv->udev); - usb_put_dev(interface_to_usbdev(intf)); - kfree(priv->io_dmabuf); - ieee80211_free_hw(dev); -} - -static struct usb_driver rtl8187_driver = { - .name = KBUILD_MODNAME, - .id_table = rtl8187_table, - .probe = rtl8187_probe, - .disconnect = __devexit_p(rtl8187_disconnect), -}; - -static int __init rtl8187_init(void) -{ - return usb_register(&rtl8187_driver); -} - -static void __exit rtl8187_exit(void) -{ - usb_deregister(&rtl8187_driver); -} - -module_init(rtl8187_init); -module_exit(rtl8187_exit); diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c deleted file mode 100644 index cf8a4a40fdf6..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.c +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Linux LED driver for RTL8187 - * - * Copyright 2009 Larry Finger - * - * Based on the LED handling in the r8187 driver, which is: - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifdef CONFIG_RTL8187_LEDS - -#include -#include -#include - -#include "rtl8187.h" -#include "rtl8187_leds.h" - -static void led_turn_on(struct work_struct *work) -{ - /* As this routine does read/write operations on the hardware, it must - * be run from a work queue. - */ - u8 reg; - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - led_on.work); - struct rtl8187_led *led = &priv->led_tx; - - /* Don't change the LED, when the device is down. */ - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) - return ; - - /* Skip if the LED is not registered. */ - if (!led->dev) - return; - mutex_lock(&priv->conf_mutex); - switch (led->ledpin) { - case LED_PIN_GPIO0: - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00); - break; - case LED_PIN_LED0: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_LED1: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_HW: - default: - break; - } - mutex_unlock(&priv->conf_mutex); -} - -static void led_turn_off(struct work_struct *work) -{ - /* As this routine does read/write operations on the hardware, it must - * be run from a work queue. - */ - u8 reg; - struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv, - led_off.work); - struct rtl8187_led *led = &priv->led_tx; - - /* Don't change the LED, when the device is down. */ - if (priv->mode == NL80211_IFTYPE_UNSPECIFIED) - return ; - - /* Skip if the LED is not registered. */ - if (!led->dev) - return; - mutex_lock(&priv->conf_mutex); - switch (led->ledpin) { - case LED_PIN_GPIO0: - rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01); - rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01); - break; - case LED_PIN_LED0: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_LED1: - reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5); - rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg); - break; - case LED_PIN_HW: - default: - break; - } - mutex_unlock(&priv->conf_mutex); -} - -/* Callback from the LED subsystem. */ -static void rtl8187_led_brightness_set(struct led_classdev *led_dev, - enum led_brightness brightness) -{ - struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led, - led_dev); - struct ieee80211_hw *hw = led->dev; - struct rtl8187_priv *priv = hw->priv; - - if (brightness == LED_OFF) { - ieee80211_queue_delayed_work(hw, &priv->led_off, 0); - /* The LED is off for 1/20 sec so that it just blinks. */ - ieee80211_queue_delayed_work(hw, &priv->led_on, HZ / 20); - } else - ieee80211_queue_delayed_work(hw, &priv->led_on, 0); -} - -static int rtl8187_register_led(struct ieee80211_hw *dev, - struct rtl8187_led *led, const char *name, - const char *default_trigger, u8 ledpin) -{ - int err; - struct rtl8187_priv *priv = dev->priv; - - if (led->dev) - return -EEXIST; - if (!default_trigger) - return -EINVAL; - led->dev = dev; - led->ledpin = ledpin; - strncpy(led->name, name, sizeof(led->name)); - - led->led_dev.name = led->name; - led->led_dev.default_trigger = default_trigger; - led->led_dev.brightness_set = rtl8187_led_brightness_set; - - err = led_classdev_register(&priv->udev->dev, &led->led_dev); - if (err) { - printk(KERN_INFO "LEDs: Failed to register %s\n", name); - led->dev = NULL; - return err; - } - return 0; -} - -static void rtl8187_unregister_led(struct rtl8187_led *led) -{ - led_classdev_unregister(&led->led_dev); - led->dev = NULL; -} - -void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid) -{ - struct rtl8187_priv *priv = dev->priv; - char name[RTL8187_LED_MAX_NAME_LEN + 1]; - u8 ledpin; - int err; - - /* According to the vendor driver, the LED operation depends on the - * customer ID encoded in the EEPROM - */ - printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid); - switch (custid) { - case EEPROM_CID_RSVD0: - case EEPROM_CID_RSVD1: - case EEPROM_CID_SERCOMM_PS: - case EEPROM_CID_QMI: - case EEPROM_CID_DELL: - case EEPROM_CID_TOSHIBA: - ledpin = LED_PIN_GPIO0; - break; - case EEPROM_CID_ALPHA0: - ledpin = LED_PIN_LED0; - break; - case EEPROM_CID_HW: - ledpin = LED_PIN_HW; - break; - default: - ledpin = LED_PIN_GPIO0; - } - - INIT_DELAYED_WORK(&priv->led_on, led_turn_on); - INIT_DELAYED_WORK(&priv->led_off, led_turn_off); - - snprintf(name, sizeof(name), - "rtl8187-%s::tx", wiphy_name(dev->wiphy)); - err = rtl8187_register_led(dev, &priv->led_tx, name, - ieee80211_get_tx_led_name(dev), ledpin); - if (err) - goto error; - snprintf(name, sizeof(name), - "rtl8187-%s::rx", wiphy_name(dev->wiphy)); - err = rtl8187_register_led(dev, &priv->led_rx, name, - ieee80211_get_rx_led_name(dev), ledpin); - if (!err) { - ieee80211_queue_delayed_work(dev, &priv->led_on, 0); - return; - } - /* registration of RX LED failed - unregister TX */ - rtl8187_unregister_led(&priv->led_tx); -error: - /* If registration of either failed, cancel delayed work */ - cancel_delayed_work_sync(&priv->led_off); - cancel_delayed_work_sync(&priv->led_on); -} - -void rtl8187_leds_exit(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - - /* turn the LED off before exiting */ - ieee80211_queue_delayed_work(dev, &priv->led_off, 0); - rtl8187_unregister_led(&priv->led_rx); - rtl8187_unregister_led(&priv->led_tx); - cancel_delayed_work_sync(&priv->led_off); - cancel_delayed_work_sync(&priv->led_on); -} -#endif /* def CONFIG_RTL8187_LED */ - diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h deleted file mode 100644 index a0332027aead..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_leds.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Definitions for RTL8187 leds - * - * Copyright 2009 Larry Finger - * - * Based on the LED handling in the r8187 driver, which is: - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187_LED_H -#define RTL8187_LED_H - -#ifdef CONFIG_RTL8187_LEDS - -#define RTL8187_LED_MAX_NAME_LEN 21 - -#include -#include - -enum { - LED_PIN_LED0, - LED_PIN_LED1, - LED_PIN_GPIO0, - LED_PIN_HW -}; - -enum { - EEPROM_CID_RSVD0 = 0x00, - EEPROM_CID_RSVD1 = 0xFF, - EEPROM_CID_ALPHA0 = 0x01, - EEPROM_CID_SERCOMM_PS = 0x02, - EEPROM_CID_HW = 0x03, - EEPROM_CID_TOSHIBA = 0x04, - EEPROM_CID_QMI = 0x07, - EEPROM_CID_DELL = 0x08 -}; - -struct rtl8187_led { - struct ieee80211_hw *dev; - /* The LED class device */ - struct led_classdev led_dev; - /* The pin/method used to control the led */ - u8 ledpin; - /* The unique name string for this LED device. */ - char name[RTL8187_LED_MAX_NAME_LEN + 1]; -}; - -void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code); -void rtl8187_leds_exit(struct ieee80211_hw *dev); - -#endif /* def CONFIG_RTL8187_LED */ - -#endif /* RTL8187_LED_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c b/drivers/net/wireless/rtl818x/rtl8187_rfkill.c deleted file mode 100644 index 03555e1e0cab..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Linux RFKILL support for RTL8187 - * - * Copyright (c) 2009 Herton Ronaldo Krzesinski - * - * Based on the RFKILL handling in the r8187 driver, which is: - * Copyright (c) Realtek Semiconductor Corp. All rights reserved. - * - * Thanks to Realtek for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8187.h" -#include "rtl8187_rfkill.h" - -static bool rtl8187_is_radio_enabled(struct rtl8187_priv *priv) -{ - u8 gpio; - - gpio = rtl818x_ioread8(priv, &priv->map->GPIO0); - rtl818x_iowrite8(priv, &priv->map->GPIO0, gpio & ~priv->rfkill_mask); - gpio = rtl818x_ioread8(priv, &priv->map->GPIO1); - - return gpio & priv->rfkill_mask; -} - -void rtl8187_rfkill_init(struct ieee80211_hw *hw) -{ - struct rtl8187_priv *priv = hw->priv; - - priv->rfkill_off = rtl8187_is_radio_enabled(priv); - printk(KERN_INFO "rtl8187: wireless switch is %s\n", - priv->rfkill_off ? "on" : "off"); - wiphy_rfkill_set_hw_state(hw->wiphy, !priv->rfkill_off); - wiphy_rfkill_start_polling(hw->wiphy); -} - -void rtl8187_rfkill_poll(struct ieee80211_hw *hw) -{ - bool enabled; - struct rtl8187_priv *priv = hw->priv; - - mutex_lock(&priv->conf_mutex); - enabled = rtl8187_is_radio_enabled(priv); - if (unlikely(enabled != priv->rfkill_off)) { - priv->rfkill_off = enabled; - printk(KERN_INFO "rtl8187: wireless radio switch turned %s\n", - enabled ? "on" : "off"); - wiphy_rfkill_set_hw_state(hw->wiphy, !enabled); - } - mutex_unlock(&priv->conf_mutex); -} - -void rtl8187_rfkill_exit(struct ieee80211_hw *hw) -{ - wiphy_rfkill_stop_polling(hw->wiphy); -} diff --git a/drivers/net/wireless/rtl818x/rtl8187_rfkill.h b/drivers/net/wireless/rtl818x/rtl8187_rfkill.h deleted file mode 100644 index e12575e96d11..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_rfkill.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RTL8187_RFKILL_H -#define RTL8187_RFKILL_H - -void rtl8187_rfkill_init(struct ieee80211_hw *hw); -void rtl8187_rfkill_poll(struct ieee80211_hw *hw); -void rtl8187_rfkill_exit(struct ieee80211_hw *hw); - -#endif /* RTL8187_RFKILL_H */ diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c deleted file mode 100644 index a09819386a1e..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.c +++ /dev/null @@ -1,983 +0,0 @@ -/* - * Radio tuning for RTL8225 on RTL8187 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * Magic delays, register offsets, and phy value tables below are - * taken from the original r8187 driver sources. Thanks to Realtek - * for their support! - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include - -#include "rtl8187.h" -#include "rtl8187_rtl8225.h" - -static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data) -{ - struct rtl8187_priv *priv = dev->priv; - u16 reg80, reg84, reg82; - u32 bangdata; - int i; - - bangdata = (data << 4) | (addr & 0xf); - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3; - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7); - - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - udelay(10); - - for (i = 15; i >= 0; i--) { - u16 reg = reg80 | (bangdata & (1 << i)) >> i; - - if (i & 1) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1)); - - if (!(i & 1)) - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); -} - -static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data) -{ - struct rtl8187_priv *priv = dev->priv; - u16 reg80, reg82, reg84; - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - - reg80 &= ~(0x3 << 2); - reg84 &= ~0xF; - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - udelay(10); - - mutex_lock(&priv->io_mutex); - - priv->io_dmabuf->bits16 = data; - usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0), - RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE, - addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data), - HZ / 2); - - mutex_unlock(&priv->io_mutex); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(10); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); -} - -static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data) -{ - struct rtl8187_priv *priv = dev->priv; - - if (priv->asic_rev) - rtl8225_write_8051(dev, addr, cpu_to_le16(data)); - else - rtl8225_write_bitbang(dev, addr, data); -} - -static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr) -{ - struct rtl8187_priv *priv = dev->priv; - u16 reg80, reg82, reg84, out; - int i; - - reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput); - reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable); - reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect); - - reg80 &= ~0xF; - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F); - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2)); - udelay(4); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80); - udelay(5); - - for (i = 4; i >= 0; i--) { - u16 reg = reg80 | ((addr >> i) & 1); - - if (!(i & 1)) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - udelay(1); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg | (1 << 1)); - udelay(2); - - if (i & 1) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg); - udelay(1); - } - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(2); - - out = 0; - for (i = 11; i >= 0; i--) { - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(1); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 1)); - udelay(2); - - if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1)) - out |= 1 << i; - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3)); - udelay(2); - } - - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, - reg80 | (1 << 3) | (1 << 2)); - udelay(2); - - rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82); - rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84); - rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0); - - return out; -} - -static const u16 rtl8225bcd_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3, - 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb -}; - -static const u8 rtl8225_agc[] = { - 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, - 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96, - 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e, - 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86, - 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e, - 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e, - 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26, - 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e, - 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, - 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e, - 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06, - 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 -}; - -static const u8 rtl8225_gain[] = { - 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */ - 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */ - 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */ - 0x33, 0x80, 0x79, 0xc5, /* -78dBm */ - 0x43, 0x78, 0x76, 0xc5, /* -74dBm */ - 0x53, 0x60, 0x73, 0xc5, /* -70dBm */ - 0x63, 0x58, 0x70, 0xc5, /* -66dBm */ -}; - -static const u8 rtl8225_threshold[] = { - 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd -}; - -static const u8 rtl8225_tx_gain_cck_ofdm[] = { - 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e -}; - -static const u8 rtl8225_tx_power_cck[] = { - 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02, - 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02, - 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02, - 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03 -}; - -static const u8 rtl8225_tx_power_cck_ch14[] = { - 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00, - 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00, - 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00, - 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00, - 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00, - 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225_tx_power_ofdm[] = { - 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4 -}; - -static const u32 rtl8225_chan[] = { - 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c, - 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72 -}; - -static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - u32 reg; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xF; - ofdm_power = priv->channels[channel - 1].hw_value >> 4; - - cck_power = min(cck_power, (u8)11); - if (ofdm_power > (u8)15) - ofdm_power = 25; - else - ofdm_power += 10; - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1); - - if (channel == 14) - tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8]; - else - tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8]; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - msleep(1); // FIXME: optional? - - /* anaparam2 on */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl8225_write_phy_ofdm(dev, 2, 0x42); - rtl8225_write_phy_ofdm(dev, 6, 0x00); - rtl8225_write_phy_ofdm(dev, 8, 0x00); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1); - - tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6]; - - rtl8225_write_phy_ofdm(dev, 5, *tmp); - rtl8225_write_phy_ofdm(dev, 7, *tmp); - - msleep(1); -} - -static void rtl8225_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - - rtl8225_write(dev, 0x0, 0x067); - rtl8225_write(dev, 0x1, 0xFE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x486); - rtl8225_write(dev, 0x5, 0xBC0); - rtl8225_write(dev, 0x6, 0xAE6); - rtl8225_write(dev, 0x7, 0x82A); - rtl8225_write(dev, 0x8, 0x01F); - rtl8225_write(dev, 0x9, 0x334); - rtl8225_write(dev, 0xA, 0xFD4); - rtl8225_write(dev, 0xB, 0x391); - rtl8225_write(dev, 0xC, 0x050); - rtl8225_write(dev, 0xD, 0x6DB); - rtl8225_write(dev, 0xE, 0x029); - rtl8225_write(dev, 0xF, 0x914); msleep(100); - - rtl8225_write(dev, 0x2, 0xC4D); msleep(200); - rtl8225_write(dev, 0x2, 0x44D); msleep(200); - - if (!(rtl8225_read(dev, 6) & (1 << 7))) { - rtl8225_write(dev, 0x02, 0x0c4d); - msleep(200); - rtl8225_write(dev, 0x02, 0x044d); - msleep(100); - if (!(rtl8225_read(dev, 6) & (1 << 7))) - printk(KERN_WARNING "%s: RF Calibration Failed! %x\n", - wiphy_name(dev->wiphy), rtl8225_read(dev, 6)); - } - - rtl8225_write(dev, 0x0, 0x127); - - for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]); - } - - rtl8225_write(dev, 0x0, 0x027); - rtl8225_write(dev, 0x0, 0x22F); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); - rtl8225_write_phy_ofdm(dev, 0x02, 0x42); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); - rtl8225_write_phy_ofdm(dev, 0x06, 0x40); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); - rtl8225_write_phy_ofdm(dev, 0x08, 0x40); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x09); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); - rtl8225_write_phy_ofdm(dev, 0x11, 0x06); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x76); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); - rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); - rtl8225_write_phy_ofdm(dev, 0x21, 0x27); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); - rtl8225_write_phy_ofdm(dev, 0x25, 0x20); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); - - rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); - rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); - rtl8225_write_phy_cck(dev, 0x03, 0x20); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); - rtl8225_write_phy_cck(dev, 0x05, 0x12); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); - rtl8225_write_phy_cck(dev, 0x07, 0x78); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); - rtl8225_write_phy_cck(dev, 0x10, 0x9b); - rtl8225_write_phy_cck(dev, 0x11, 0x88); - rtl8225_write_phy_cck(dev, 0x12, 0x47); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8d); - rtl8225_write_phy_cck(dev, 0x42, 0x15); - rtl8225_write_phy_cck(dev, 0x43, 0x18); - rtl8225_write_phy_cck(dev, 0x44, 0x1f); - rtl8225_write_phy_cck(dev, 0x45, 0x1e); - rtl8225_write_phy_cck(dev, 0x46, 0x1a); - rtl8225_write_phy_cck(dev, 0x47, 0x15); - rtl8225_write_phy_cck(dev, 0x48, 0x10); - rtl8225_write_phy_cck(dev, 0x49, 0x0a); - rtl8225_write_phy_cck(dev, 0x4a, 0x05); - rtl8225_write_phy_cck(dev, 0x4b, 0x02); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); - - rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D); - - rtl8225_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); - - /* set sensitivity */ - rtl8225_write(dev, 0x0c, 0x50); - rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]); - rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]); - rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]); -} - -static const u8 rtl8225z2_agc[] = { - 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f, - 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37, - 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, - 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07, - 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, - 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28, - 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d, - 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, - 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31 -}; -static const u8 rtl8225z2_ofdm[] = { - 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60, - 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00, - 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26, - 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3, - 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f, - 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00, - 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e, - 0x6d, 0x3c, 0xfb, 0x07 -}; - -static const u8 rtl8225z2_tx_power_cck_ch14[] = { - 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00, - 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00 -}; - -static const u8 rtl8225z2_tx_power_cck[] = { - 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04, - 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03, - 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03, - 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 -}; - -static const u8 rtl8225z2_tx_power_ofdm[] = { - 0x42, 0x00, 0x40, 0x00, 0x40 -}; - -static const u8 rtl8225z2_tx_gain_cck_ofdm[] = { - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, - 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, - 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, - 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, - 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23 -}; - -static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - u32 reg; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xF; - ofdm_power = priv->channels[channel - 1].hw_value >> 4; - - cck_power = min(cck_power, (u8)15); - cck_power += priv->txpwr_base & 0xF; - cck_power = min(cck_power, (u8)35); - - if (ofdm_power > (u8)15) - ofdm_power = 25; - else - ofdm_power += 10; - ofdm_power += priv->txpwr_base >> 4; - ofdm_power = min(ofdm_power, (u8)35); - - if (channel == 14) - tmp = rtl8225z2_tx_power_cck_ch14; - else - tmp = rtl8225z2_tx_power_cck; - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225z2_tx_gain_cck_ofdm[cck_power]); - msleep(1); - - /* anaparam2 on */ - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_ON); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, - reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); - - rtl8225_write_phy_ofdm(dev, 2, 0x42); - rtl8225_write_phy_ofdm(dev, 5, 0x00); - rtl8225_write_phy_ofdm(dev, 6, 0x40); - rtl8225_write_phy_ofdm(dev, 7, 0x00); - rtl8225_write_phy_ofdm(dev, 8, 0x40); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225z2_tx_gain_cck_ofdm[ofdm_power]); - msleep(1); -} - -static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel) -{ - struct rtl8187_priv *priv = dev->priv; - u8 cck_power, ofdm_power; - const u8 *tmp; - int i; - - cck_power = priv->channels[channel - 1].hw_value & 0xF; - ofdm_power = priv->channels[channel - 1].hw_value >> 4; - - if (cck_power > 15) - cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22; - else - cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7; - cck_power += priv->txpwr_base & 0xF; - cck_power = min(cck_power, (u8)35); - - if (ofdm_power > 15) - ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25; - else - ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10; - ofdm_power += (priv->txpwr_base >> 4) & 0xF; - ofdm_power = min(ofdm_power, (u8)35); - - if (channel == 14) - tmp = rtl8225z2_tx_power_cck_ch14; - else - tmp = rtl8225z2_tx_power_cck; - - if (priv->hw_rev == RTL8187BvB) { - if (cck_power <= 6) - ; /* do nothing */ - else if (cck_power <= 11) - tmp += 8; - else - tmp += 16; - } else { - if (cck_power <= 5) - ; /* do nothing */ - else if (cck_power <= 11) - tmp += 8; - else if (cck_power <= 17) - tmp += 16; - else - tmp += 24; - } - - for (i = 0; i < 8; i++) - rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, - rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1); - msleep(1); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, - rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1); - if (priv->hw_rev == RTL8187BvB) { - if (ofdm_power <= 11) { - rtl8225_write_phy_ofdm(dev, 0x87, 0x60); - rtl8225_write_phy_ofdm(dev, 0x89, 0x60); - } else { - rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); - rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); - } - } else { - if (ofdm_power <= 11) { - rtl8225_write_phy_ofdm(dev, 0x87, 0x5c); - rtl8225_write_phy_ofdm(dev, 0x89, 0x5c); - } else if (ofdm_power <= 17) { - rtl8225_write_phy_ofdm(dev, 0x87, 0x54); - rtl8225_write_phy_ofdm(dev, 0x89, 0x54); - } else { - rtl8225_write_phy_ofdm(dev, 0x87, 0x50); - rtl8225_write_phy_ofdm(dev, 0x89, 0x50); - } - } - msleep(1); -} - -static const u16 rtl8225z2_rxgain[] = { - 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409, - 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541, - 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583, - 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644, - 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688, - 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745, - 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789, - 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793, - 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d, - 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9, - 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3, - 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb -}; - -static const u8 rtl8225z2_gain_bg[] = { - 0x23, 0x15, 0xa5, /* -82-1dBm */ - 0x23, 0x15, 0xb5, /* -82-2dBm */ - 0x23, 0x15, 0xc5, /* -82-3dBm */ - 0x33, 0x15, 0xc5, /* -78dBm */ - 0x43, 0x15, 0xc5, /* -74dBm */ - 0x53, 0x15, 0xc5, /* -70dBm */ - 0x63, 0x15, 0xc5 /* -66dBm */ -}; - -static void rtl8225z2_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - - rtl8225_write(dev, 0x0, 0x2BF); - rtl8225_write(dev, 0x1, 0xEE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x8C3); - rtl8225_write(dev, 0x5, 0xC72); - rtl8225_write(dev, 0x6, 0x0E6); - rtl8225_write(dev, 0x7, 0x82A); - rtl8225_write(dev, 0x8, 0x03F); - rtl8225_write(dev, 0x9, 0x335); - rtl8225_write(dev, 0xa, 0x9D4); - rtl8225_write(dev, 0xb, 0x7BB); - rtl8225_write(dev, 0xc, 0x850); - rtl8225_write(dev, 0xd, 0xCDF); - rtl8225_write(dev, 0xe, 0x02B); - rtl8225_write(dev, 0xf, 0x114); - msleep(100); - - rtl8225_write(dev, 0x0, 0x1B7); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); - } - - rtl8225_write(dev, 0x3, 0x080); - rtl8225_write(dev, 0x5, 0x004); - rtl8225_write(dev, 0x0, 0x0B7); - rtl8225_write(dev, 0x2, 0xc4D); - - msleep(200); - rtl8225_write(dev, 0x2, 0x44D); - msleep(100); - - if (!(rtl8225_read(dev, 6) & (1 << 7))) { - rtl8225_write(dev, 0x02, 0x0C4D); - msleep(200); - rtl8225_write(dev, 0x02, 0x044D); - msleep(100); - if (!(rtl8225_read(dev, 6) & (1 << 7))) - printk(KERN_WARNING "%s: RF Calibration Failed! %x\n", - wiphy_name(dev->wiphy), rtl8225_read(dev, 6)); - } - - msleep(200); - - rtl8225_write(dev, 0x0, 0x2BF); - - for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]); - rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i); - } - - msleep(1); - - rtl8225_write_phy_ofdm(dev, 0x00, 0x01); - rtl8225_write_phy_ofdm(dev, 0x01, 0x02); - rtl8225_write_phy_ofdm(dev, 0x02, 0x42); - rtl8225_write_phy_ofdm(dev, 0x03, 0x00); - rtl8225_write_phy_ofdm(dev, 0x04, 0x00); - rtl8225_write_phy_ofdm(dev, 0x05, 0x00); - rtl8225_write_phy_ofdm(dev, 0x06, 0x40); - rtl8225_write_phy_ofdm(dev, 0x07, 0x00); - rtl8225_write_phy_ofdm(dev, 0x08, 0x40); - rtl8225_write_phy_ofdm(dev, 0x09, 0xfe); - rtl8225_write_phy_ofdm(dev, 0x0a, 0x08); - rtl8225_write_phy_ofdm(dev, 0x0b, 0x80); - rtl8225_write_phy_ofdm(dev, 0x0c, 0x01); - rtl8225_write_phy_ofdm(dev, 0x0d, 0x43); - rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3); - rtl8225_write_phy_ofdm(dev, 0x0f, 0x38); - rtl8225_write_phy_ofdm(dev, 0x10, 0x84); - rtl8225_write_phy_ofdm(dev, 0x11, 0x07); - rtl8225_write_phy_ofdm(dev, 0x12, 0x20); - rtl8225_write_phy_ofdm(dev, 0x13, 0x20); - rtl8225_write_phy_ofdm(dev, 0x14, 0x00); - rtl8225_write_phy_ofdm(dev, 0x15, 0x40); - rtl8225_write_phy_ofdm(dev, 0x16, 0x00); - rtl8225_write_phy_ofdm(dev, 0x17, 0x40); - rtl8225_write_phy_ofdm(dev, 0x18, 0xef); - rtl8225_write_phy_ofdm(dev, 0x19, 0x19); - rtl8225_write_phy_ofdm(dev, 0x1a, 0x20); - rtl8225_write_phy_ofdm(dev, 0x1b, 0x15); - rtl8225_write_phy_ofdm(dev, 0x1c, 0x04); - rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5); - rtl8225_write_phy_ofdm(dev, 0x1e, 0x95); - rtl8225_write_phy_ofdm(dev, 0x1f, 0x75); - rtl8225_write_phy_ofdm(dev, 0x20, 0x1f); - rtl8225_write_phy_ofdm(dev, 0x21, 0x17); - rtl8225_write_phy_ofdm(dev, 0x22, 0x16); - rtl8225_write_phy_ofdm(dev, 0x23, 0x80); - rtl8225_write_phy_ofdm(dev, 0x24, 0x46); - rtl8225_write_phy_ofdm(dev, 0x25, 0x00); - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); - rtl8225_write_phy_ofdm(dev, 0x27, 0x88); - - rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]); - rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]); - rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]); - rtl8225_write_phy_ofdm(dev, 0x21, 0x37); - - rtl8225_write_phy_cck(dev, 0x00, 0x98); - rtl8225_write_phy_cck(dev, 0x03, 0x20); - rtl8225_write_phy_cck(dev, 0x04, 0x7e); - rtl8225_write_phy_cck(dev, 0x05, 0x12); - rtl8225_write_phy_cck(dev, 0x06, 0xfc); - rtl8225_write_phy_cck(dev, 0x07, 0x78); - rtl8225_write_phy_cck(dev, 0x08, 0x2e); - rtl8225_write_phy_cck(dev, 0x10, 0x9b); - rtl8225_write_phy_cck(dev, 0x11, 0x88); - rtl8225_write_phy_cck(dev, 0x12, 0x47); - rtl8225_write_phy_cck(dev, 0x13, 0xd0); - rtl8225_write_phy_cck(dev, 0x19, 0x00); - rtl8225_write_phy_cck(dev, 0x1a, 0xa0); - rtl8225_write_phy_cck(dev, 0x1b, 0x08); - rtl8225_write_phy_cck(dev, 0x40, 0x86); - rtl8225_write_phy_cck(dev, 0x41, 0x8d); - rtl8225_write_phy_cck(dev, 0x42, 0x15); - rtl8225_write_phy_cck(dev, 0x43, 0x18); - rtl8225_write_phy_cck(dev, 0x44, 0x36); - rtl8225_write_phy_cck(dev, 0x45, 0x35); - rtl8225_write_phy_cck(dev, 0x46, 0x2e); - rtl8225_write_phy_cck(dev, 0x47, 0x25); - rtl8225_write_phy_cck(dev, 0x48, 0x1c); - rtl8225_write_phy_cck(dev, 0x49, 0x12); - rtl8225_write_phy_cck(dev, 0x4a, 0x09); - rtl8225_write_phy_cck(dev, 0x4b, 0x04); - rtl8225_write_phy_cck(dev, 0x4c, 0x05); - - rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1); - - rtl8225z2_rf_set_tx_power(dev, 1); - - /* RX antenna default to A */ - rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */ - rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */ - - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */ - msleep(1); - rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002); -} - -static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev) -{ - struct rtl8187_priv *priv = dev->priv; - int i; - - rtl8225_write(dev, 0x0, 0x0B7); - rtl8225_write(dev, 0x1, 0xEE0); - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x3, 0x441); - rtl8225_write(dev, 0x4, 0x8C3); - rtl8225_write(dev, 0x5, 0xC72); - rtl8225_write(dev, 0x6, 0x0E6); - rtl8225_write(dev, 0x7, 0x82A); - rtl8225_write(dev, 0x8, 0x03F); - rtl8225_write(dev, 0x9, 0x335); - rtl8225_write(dev, 0xa, 0x9D4); - rtl8225_write(dev, 0xb, 0x7BB); - rtl8225_write(dev, 0xc, 0x850); - rtl8225_write(dev, 0xd, 0xCDF); - rtl8225_write(dev, 0xe, 0x02B); - rtl8225_write(dev, 0xf, 0x114); - - rtl8225_write(dev, 0x0, 0x1B7); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) { - rtl8225_write(dev, 0x1, i + 1); - rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]); - } - - rtl8225_write(dev, 0x3, 0x080); - rtl8225_write(dev, 0x5, 0x004); - rtl8225_write(dev, 0x0, 0x0B7); - - rtl8225_write(dev, 0x2, 0xC4D); - - rtl8225_write(dev, 0x2, 0x44D); - rtl8225_write(dev, 0x0, 0x2BF); - - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03); - rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07); - rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); - - rtl8225_write_phy_ofdm(dev, 0x80, 0x12); - for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) { - rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]); - rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i); - rtl8225_write_phy_ofdm(dev, 0xE, 0); - } - rtl8225_write_phy_ofdm(dev, 0x80, 0x10); - - for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++) - rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]); - - rtl8225_write_phy_ofdm(dev, 0x97, 0x46); - rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6); - rtl8225_write_phy_ofdm(dev, 0x85, 0xfc); - rtl8225_write_phy_cck(dev, 0xc1, 0x88); -} - -static void rtl8225_rf_stop(struct ieee80211_hw *dev) -{ - u8 reg; - struct rtl8187_priv *priv = dev->priv; - - rtl8225_write(dev, 0x4, 0x1f); - - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG); - reg = rtl818x_ioread8(priv, &priv->map->CONFIG3); - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE); - if (!priv->is_rtl8187b) { - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187_RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187_RTL8225_ANAPARAM_OFF); - } else { - rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, - RTL8187B_RTL8225_ANAPARAM2_OFF); - rtl818x_iowrite32(priv, &priv->map->ANAPARAM, - RTL8187B_RTL8225_ANAPARAM_OFF); - rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, - RTL8187B_RTL8225_ANAPARAM3_OFF); - } - rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE); - rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); -} - -static void rtl8225_rf_set_channel(struct ieee80211_hw *dev, - struct ieee80211_conf *conf) -{ - struct rtl8187_priv *priv = dev->priv; - int chan = ieee80211_frequency_to_channel(conf->channel->center_freq); - - if (priv->rf->init == rtl8225_rf_init) - rtl8225_rf_set_tx_power(dev, chan); - else if (priv->rf->init == rtl8225z2_rf_init) - rtl8225z2_rf_set_tx_power(dev, chan); - else - rtl8225z2_b_rf_set_tx_power(dev, chan); - - rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]); - msleep(10); -} - -static const struct rtl818x_rf_ops rtl8225_ops = { - .name = "rtl8225", - .init = rtl8225_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel -}; - -static const struct rtl818x_rf_ops rtl8225z2_ops = { - .name = "rtl8225z2", - .init = rtl8225z2_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel -}; - -static const struct rtl818x_rf_ops rtl8225z2_b_ops = { - .name = "rtl8225z2", - .init = rtl8225z2_b_rf_init, - .stop = rtl8225_rf_stop, - .set_chan = rtl8225_rf_set_channel -}; - -const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev) -{ - u16 reg8, reg9; - struct rtl8187_priv *priv = dev->priv; - - if (!priv->is_rtl8187b) { - rtl8225_write(dev, 0, 0x1B7); - - reg8 = rtl8225_read(dev, 8); - reg9 = rtl8225_read(dev, 9); - - rtl8225_write(dev, 0, 0x0B7); - - if (reg8 != 0x588 || reg9 != 0x700) - return &rtl8225_ops; - - return &rtl8225z2_ops; - } else - return &rtl8225z2_b_ops; -} diff --git a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h b/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h deleted file mode 100644 index 20c5b6ead0f6..000000000000 --- a/drivers/net/wireless/rtl818x/rtl8187_rtl8225.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Radio tuning definitions for RTL8225 on RTL8187 - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL8187_RTL8225_H -#define RTL8187_RTL8225_H - -#define RTL8187_RTL8225_ANAPARAM_ON 0xa0000a59 -#define RTL8187_RTL8225_ANAPARAM2_ON 0x860c7312 -#define RTL8187_RTL8225_ANAPARAM_OFF 0xa00beb59 -#define RTL8187_RTL8225_ANAPARAM2_OFF 0x840dec11 - -#define RTL8187B_RTL8225_ANAPARAM_ON 0x45090658 -#define RTL8187B_RTL8225_ANAPARAM2_ON 0x727f3f52 -#define RTL8187B_RTL8225_ANAPARAM3_ON 0x00 -#define RTL8187B_RTL8225_ANAPARAM_OFF 0x55480658 -#define RTL8187B_RTL8225_ANAPARAM2_OFF 0x72003f50 -#define RTL8187B_RTL8225_ANAPARAM3_OFF 0x00 - -const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *); - -static inline void rtl8225_write_phy_ofdm(struct ieee80211_hw *dev, - u8 addr, u32 data) -{ - rtl8187_write_phy(dev, addr, data); -} - -static inline void rtl8225_write_phy_cck(struct ieee80211_hw *dev, - u8 addr, u32 data) -{ - rtl8187_write_phy(dev, addr, data | 0x10000); -} - -#endif /* RTL8187_RTL8225_H */ diff --git a/drivers/net/wireless/rtl818x/rtl818x.h b/drivers/net/wireless/rtl818x/rtl818x.h deleted file mode 100644 index 8522490d2e29..000000000000 --- a/drivers/net/wireless/rtl818x/rtl818x.h +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Definitions for RTL818x hardware - * - * Copyright 2007 Michael Wu - * Copyright 2007 Andrea Merello - * - * Based on the r8187 driver, which is: - * Copyright 2005 Andrea Merello , et al. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#ifndef RTL818X_H -#define RTL818X_H - -struct rtl818x_csr { - u8 MAC[6]; - u8 reserved_0[2]; - __le32 MAR[2]; - u8 RX_FIFO_COUNT; - u8 reserved_1; - u8 TX_FIFO_COUNT; - u8 BQREQ; - u8 reserved_2[4]; - __le32 TSFT[2]; - __le32 TLPDA; - __le32 TNPDA; - __le32 THPDA; - __le16 BRSR; - u8 BSSID[6]; - u8 RESP_RATE; - u8 EIFS; - u8 reserved_3[1]; - u8 CMD; -#define RTL818X_CMD_TX_ENABLE (1 << 2) -#define RTL818X_CMD_RX_ENABLE (1 << 3) -#define RTL818X_CMD_RESET (1 << 4) - u8 reserved_4[4]; - __le16 INT_MASK; - __le16 INT_STATUS; -#define RTL818X_INT_RX_OK (1 << 0) -#define RTL818X_INT_RX_ERR (1 << 1) -#define RTL818X_INT_TXL_OK (1 << 2) -#define RTL818X_INT_TXL_ERR (1 << 3) -#define RTL818X_INT_RX_DU (1 << 4) -#define RTL818X_INT_RX_FO (1 << 5) -#define RTL818X_INT_TXN_OK (1 << 6) -#define RTL818X_INT_TXN_ERR (1 << 7) -#define RTL818X_INT_TXH_OK (1 << 8) -#define RTL818X_INT_TXH_ERR (1 << 9) -#define RTL818X_INT_TXB_OK (1 << 10) -#define RTL818X_INT_TXB_ERR (1 << 11) -#define RTL818X_INT_ATIM (1 << 12) -#define RTL818X_INT_BEACON (1 << 13) -#define RTL818X_INT_TIME_OUT (1 << 14) -#define RTL818X_INT_TX_FO (1 << 15) - __le32 TX_CONF; -#define RTL818X_TX_CONF_LOOPBACK_MAC (1 << 17) -#define RTL818X_TX_CONF_LOOPBACK_CONT (3 << 17) -#define RTL818X_TX_CONF_NO_ICV (1 << 19) -#define RTL818X_TX_CONF_DISCW (1 << 20) -#define RTL818X_TX_CONF_SAT_HWPLCP (1 << 24) -#define RTL818X_TX_CONF_R8180_ABCD (2 << 25) -#define RTL818X_TX_CONF_R8180_F (3 << 25) -#define RTL818X_TX_CONF_R8185_ABC (4 << 25) -#define RTL818X_TX_CONF_R8185_D (5 << 25) -#define RTL818X_TX_CONF_R8187vD (5 << 25) -#define RTL818X_TX_CONF_R8187vD_B (6 << 25) -#define RTL818X_TX_CONF_HWVER_MASK (7 << 25) -#define RTL818X_TX_CONF_DISREQQSIZE (1 << 28) -#define RTL818X_TX_CONF_PROBE_DTS (1 << 29) -#define RTL818X_TX_CONF_HW_SEQNUM (1 << 30) -#define RTL818X_TX_CONF_CW_MIN (1 << 31) - __le32 RX_CONF; -#define RTL818X_RX_CONF_MONITOR (1 << 0) -#define RTL818X_RX_CONF_NICMAC (1 << 1) -#define RTL818X_RX_CONF_MULTICAST (1 << 2) -#define RTL818X_RX_CONF_BROADCAST (1 << 3) -#define RTL818X_RX_CONF_FCS (1 << 5) -#define RTL818X_RX_CONF_DATA (1 << 18) -#define RTL818X_RX_CONF_CTRL (1 << 19) -#define RTL818X_RX_CONF_MGMT (1 << 20) -#define RTL818X_RX_CONF_ADDR3 (1 << 21) -#define RTL818X_RX_CONF_PM (1 << 22) -#define RTL818X_RX_CONF_BSSID (1 << 23) -#define RTL818X_RX_CONF_RX_AUTORESETPHY (1 << 28) -#define RTL818X_RX_CONF_CSDM1 (1 << 29) -#define RTL818X_RX_CONF_CSDM2 (1 << 30) -#define RTL818X_RX_CONF_ONLYERLPKT (1 << 31) - __le32 INT_TIMEOUT; - __le32 TBDA; - u8 EEPROM_CMD; -#define RTL818X_EEPROM_CMD_READ (1 << 0) -#define RTL818X_EEPROM_CMD_WRITE (1 << 1) -#define RTL818X_EEPROM_CMD_CK (1 << 2) -#define RTL818X_EEPROM_CMD_CS (1 << 3) -#define RTL818X_EEPROM_CMD_NORMAL (0 << 6) -#define RTL818X_EEPROM_CMD_LOAD (1 << 6) -#define RTL818X_EEPROM_CMD_PROGRAM (2 << 6) -#define RTL818X_EEPROM_CMD_CONFIG (3 << 6) - u8 CONFIG0; - u8 CONFIG1; - u8 CONFIG2; -#define RTL818X_CONFIG2_ANTENNA_DIV (1 << 6) - __le32 ANAPARAM; - u8 MSR; -#define RTL818X_MSR_NO_LINK (0 << 2) -#define RTL818X_MSR_ADHOC (1 << 2) -#define RTL818X_MSR_INFRA (2 << 2) -#define RTL818X_MSR_MASTER (3 << 2) -#define RTL818X_MSR_ENEDCA (4 << 2) - u8 CONFIG3; -#define RTL818X_CONFIG3_ANAPARAM_WRITE (1 << 6) -#define RTL818X_CONFIG3_GNT_SELECT (1 << 7) - u8 CONFIG4; -#define RTL818X_CONFIG4_POWEROFF (1 << 6) -#define RTL818X_CONFIG4_VCOOFF (1 << 7) - u8 TESTR; - u8 reserved_9[2]; - u8 PGSELECT; - u8 SECURITY; - __le32 ANAPARAM2; - u8 reserved_10[12]; - __le16 BEACON_INTERVAL; - __le16 ATIM_WND; - __le16 BEACON_INTERVAL_TIME; - __le16 ATIMTR_INTERVAL; - u8 PHY_DELAY; - u8 CARRIER_SENSE_COUNTER; - u8 reserved_11[2]; - u8 PHY[4]; - __le16 RFPinsOutput; - __le16 RFPinsEnable; - __le16 RFPinsSelect; - __le16 RFPinsInput; - __le32 RF_PARA; - __le32 RF_TIMING; - u8 GP_ENABLE; - u8 GPIO0; - u8 GPIO1; - u8 reserved_12; - __le32 HSSI_PARA; - u8 reserved_13[4]; - u8 TX_AGC_CTL; -#define RTL818X_TX_AGC_CTL_PERPACKET_GAIN_SHIFT (1 << 0) -#define RTL818X_TX_AGC_CTL_PERPACKET_ANTSEL_SHIFT (1 << 1) -#define RTL818X_TX_AGC_CTL_FEEDBACK_ANT (1 << 2) - u8 TX_GAIN_CCK; - u8 TX_GAIN_OFDM; - u8 TX_ANTENNA; - u8 reserved_14[16]; - u8 WPA_CONF; - u8 reserved_15[3]; - u8 SIFS; - u8 DIFS; - u8 SLOT; - u8 reserved_16[5]; - u8 CW_CONF; -#define RTL818X_CW_CONF_PERPACKET_CW_SHIFT (1 << 0) -#define RTL818X_CW_CONF_PERPACKET_RETRY_SHIFT (1 << 1) - u8 CW_VAL; - u8 RATE_FALLBACK; -#define RTL818X_RATE_FALLBACK_ENABLE (1 << 7) - u8 ACM_CONTROL; - u8 reserved_17[24]; - u8 CONFIG5; - u8 TX_DMA_POLLING; - u8 reserved_18[2]; - __le16 CWR; - u8 RETRY_CTR; - u8 reserved_19[3]; - __le16 INT_MIG; -/* RTL818X_R8187B_*: magic numbers from ioregisters */ -#define RTL818X_R8187B_B 0 -#define RTL818X_R8187B_D 1 -#define RTL818X_R8187B_E 2 - __le32 RDSAR; - __le16 TID_AC_MAP; - u8 reserved_20[4]; - u8 ANAPARAM3; - u8 reserved_21[5]; - __le16 FEMR; - u8 reserved_22[4]; - __le16 TALLY_CNT; - u8 TALLY_SEL; -} __attribute__((packed)); - -struct rtl818x_rf_ops { - char *name; - void (*init)(struct ieee80211_hw *); - void (*stop)(struct ieee80211_hw *); - void (*set_chan)(struct ieee80211_hw *, struct ieee80211_conf *); - void (*conf_erp)(struct ieee80211_hw *, struct ieee80211_bss_conf *); -}; - -/** - * enum rtl818x_tx_desc_flags - Tx/Rx flags are common between RTL818X chips - * - * @RTL818X_TX_DESC_FLAG_NO_ENC: Disable hardware based encryption. - * @RTL818X_TX_DESC_FLAG_TX_OK: TX frame was ACKed. - * @RTL818X_TX_DESC_FLAG_SPLCP: Use short preamble. - * @RTL818X_TX_DESC_FLAG_MOREFRAG: More fragments follow. - * @RTL818X_TX_DESC_FLAG_CTS: Use CTS-to-self protection. - * @RTL818X_TX_DESC_FLAG_RTS: Use RTS/CTS protection. - * @RTL818X_TX_DESC_FLAG_LS: Last segment of the frame. - * @RTL818X_TX_DESC_FLAG_FS: First segment of the frame. - */ -enum rtl818x_tx_desc_flags { - RTL818X_TX_DESC_FLAG_NO_ENC = (1 << 15), - RTL818X_TX_DESC_FLAG_TX_OK = (1 << 15), - RTL818X_TX_DESC_FLAG_SPLCP = (1 << 16), - RTL818X_TX_DESC_FLAG_RX_UNDER = (1 << 16), - RTL818X_TX_DESC_FLAG_MOREFRAG = (1 << 17), - RTL818X_TX_DESC_FLAG_CTS = (1 << 18), - RTL818X_TX_DESC_FLAG_RTS = (1 << 23), - RTL818X_TX_DESC_FLAG_LS = (1 << 28), - RTL818X_TX_DESC_FLAG_FS = (1 << 29), - RTL818X_TX_DESC_FLAG_DMA = (1 << 30), - RTL818X_TX_DESC_FLAG_OWN = (1 << 31) -}; - -enum rtl818x_rx_desc_flags { - RTL818X_RX_DESC_FLAG_ICV_ERR = (1 << 12), - RTL818X_RX_DESC_FLAG_CRC32_ERR = (1 << 13), - RTL818X_RX_DESC_FLAG_PM = (1 << 14), - RTL818X_RX_DESC_FLAG_RX_ERR = (1 << 15), - RTL818X_RX_DESC_FLAG_BCAST = (1 << 16), - RTL818X_RX_DESC_FLAG_PAM = (1 << 17), - RTL818X_RX_DESC_FLAG_MCAST = (1 << 18), - RTL818X_RX_DESC_FLAG_QOS = (1 << 19), /* RTL8187(B) only */ - RTL818X_RX_DESC_FLAG_TRSW = (1 << 24), /* RTL8187(B) only */ - RTL818X_RX_DESC_FLAG_SPLCP = (1 << 25), - RTL818X_RX_DESC_FLAG_FOF = (1 << 26), - RTL818X_RX_DESC_FLAG_DMA_FAIL = (1 << 27), - RTL818X_RX_DESC_FLAG_LS = (1 << 28), - RTL818X_RX_DESC_FLAG_FS = (1 << 29), - RTL818X_RX_DESC_FLAG_EOR = (1 << 30), - RTL818X_RX_DESC_FLAG_OWN = (1 << 31) -}; - -#endif /* RTL818X_H */ diff --git a/drivers/net/wireless/strip.c b/drivers/net/wireless/strip.c deleted file mode 100644 index ea6a87c19319..000000000000 --- a/drivers/net/wireless/strip.c +++ /dev/null @@ -1,2805 +0,0 @@ -/* - * Copyright 1996 The Board of Trustees of The Leland Stanford - * Junior University. All Rights Reserved. - * - * Permission to use, copy, modify, and distribute this - * software and its documentation for any purpose and without - * fee is hereby granted, provided that the above copyright - * notice appear in all copies. Stanford University - * makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without - * express or implied warranty. - * - * strip.c This module implements Starmode Radio IP (STRIP) - * for kernel-based devices like TTY. It interfaces between a - * raw TTY, and the kernel's INET protocol layers (via DDI). - * - * Version: @(#)strip.c 1.3 July 1997 - * - * Author: Stuart Cheshire - * - * Fixes: v0.9 12th Feb 1996 (SC) - * New byte stuffing (2+6 run-length encoding) - * New watchdog timer task - * New Protocol key (SIP0) - * - * v0.9.1 3rd March 1996 (SC) - * Changed to dynamic device allocation -- no more compile - * time (or boot time) limit on the number of STRIP devices. - * - * v0.9.2 13th March 1996 (SC) - * Uses arp cache lookups (but doesn't send arp packets yet) - * - * v0.9.3 17th April 1996 (SC) - * Fixed bug where STR_ERROR flag was getting set unneccessarily - * (causing otherwise good packets to be unneccessarily dropped) - * - * v0.9.4 27th April 1996 (SC) - * First attempt at using "&COMMAND" Starmode AT commands - * - * v0.9.5 29th May 1996 (SC) - * First attempt at sending (unicast) ARP packets - * - * v0.9.6 5th June 1996 (Elliot) - * Put "message level" tags in every "printk" statement - * - * v0.9.7 13th June 1996 (laik) - * Added support for the /proc fs - * - * v0.9.8 July 1996 (Mema) - * Added packet logging - * - * v1.0 November 1996 (SC) - * Fixed (severe) memory leaks in the /proc fs code - * Fixed race conditions in the logging code - * - * v1.1 January 1997 (SC) - * Deleted packet logging (use tcpdump instead) - * Added support for Metricom Firmware v204 features - * (like message checksums) - * - * v1.2 January 1997 (SC) - * Put portables list back in - * - * v1.3 July 1997 (SC) - * Made STRIP driver set the radio's baud rate automatically. - * It is no longer necessarily to manually set the radio's - * rate permanently to 115200 -- the driver handles setting - * the rate automatically. - */ - -#ifdef MODULE -static const char StripVersion[] = "1.3A-STUART.CHESHIRE-MODULAR"; -#else -static const char StripVersion[] = "1.3A-STUART.CHESHIRE"; -#endif - -#define TICKLE_TIMERS 0 -#define EXT_COUNTERS 1 - - -/************************************************************************/ -/* Header files */ - -#include -#include -#include -#include -#include -#include - -# include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -/************************************************************************/ -/* Useful structures and definitions */ - -/* - * A MetricomKey identifies the protocol being carried inside a Metricom - * Starmode packet. - */ - -typedef union { - __u8 c[4]; - __u32 l; -} MetricomKey; - -/* - * An IP address can be viewed as four bytes in memory (which is what it is) or as - * a single 32-bit long (which is convenient for assignment, equality testing etc.) - */ - -typedef union { - __u8 b[4]; - __u32 l; -} IPaddr; - -/* - * A MetricomAddressString is used to hold a printable representation of - * a Metricom address. - */ - -typedef struct { - __u8 c[24]; -} MetricomAddressString; - -/* Encapsulation can expand packet of size x to 65/64x + 1 - * Sent packet looks like "*
*" - * 1 1 1-18 1 4 ? 1 - * eg. *0000-1234*SIP0 - * We allow 31 bytes for the stars, the key, the address and the s - */ -#define STRIP_ENCAP_SIZE(X) (32 + (X)*65L/64L) - -/* - * A STRIP_Header is never really sent over the radio, but making a dummy - * header for internal use within the kernel that looks like an Ethernet - * header makes certain other software happier. For example, tcpdump - * already understands Ethernet headers. - */ - -typedef struct { - MetricomAddress dst_addr; /* Destination address, e.g. "0000-1234" */ - MetricomAddress src_addr; /* Source address, e.g. "0000-5678" */ - unsigned short protocol; /* The protocol type, using Ethernet codes */ -} STRIP_Header; - -typedef struct { - char c[60]; -} MetricomNode; - -#define NODE_TABLE_SIZE 32 -typedef struct { - struct timeval timestamp; - int num_nodes; - MetricomNode node[NODE_TABLE_SIZE]; -} MetricomNodeTable; - -enum { FALSE = 0, TRUE = 1 }; - -/* - * Holds the radio's firmware version. - */ -typedef struct { - char c[50]; -} FirmwareVersion; - -/* - * Holds the radio's serial number. - */ -typedef struct { - char c[18]; -} SerialNumber; - -/* - * Holds the radio's battery voltage. - */ -typedef struct { - char c[11]; -} BatteryVoltage; - -typedef struct { - char c[8]; -} char8; - -enum { - NoStructure = 0, /* Really old firmware */ - StructuredMessages = 1, /* Parsable AT response msgs */ - ChecksummedMessages = 2 /* Parsable AT response msgs with checksums */ -}; - -struct strip { - int magic; - /* - * These are pointers to the malloc()ed frame buffers. - */ - - unsigned char *rx_buff; /* buffer for received IP packet */ - unsigned char *sx_buff; /* buffer for received serial data */ - int sx_count; /* received serial data counter */ - int sx_size; /* Serial buffer size */ - unsigned char *tx_buff; /* transmitter buffer */ - unsigned char *tx_head; /* pointer to next byte to XMIT */ - int tx_left; /* bytes left in XMIT queue */ - int tx_size; /* Serial buffer size */ - - /* - * STRIP interface statistics. - */ - - unsigned long rx_packets; /* inbound frames counter */ - unsigned long tx_packets; /* outbound frames counter */ - unsigned long rx_errors; /* Parity, etc. errors */ - unsigned long tx_errors; /* Planned stuff */ - unsigned long rx_dropped; /* No memory for skb */ - unsigned long tx_dropped; /* When MTU change */ - unsigned long rx_over_errors; /* Frame bigger than STRIP buf. */ - - unsigned long pps_timer; /* Timer to determine pps */ - unsigned long rx_pps_count; /* Counter to determine pps */ - unsigned long tx_pps_count; /* Counter to determine pps */ - unsigned long sx_pps_count; /* Counter to determine pps */ - unsigned long rx_average_pps; /* rx packets per second * 8 */ - unsigned long tx_average_pps; /* tx packets per second * 8 */ - unsigned long sx_average_pps; /* sent packets per second * 8 */ - -#ifdef EXT_COUNTERS - unsigned long rx_bytes; /* total received bytes */ - unsigned long tx_bytes; /* total received bytes */ - unsigned long rx_rbytes; /* bytes thru radio i/f */ - unsigned long tx_rbytes; /* bytes thru radio i/f */ - unsigned long rx_sbytes; /* tot bytes thru serial i/f */ - unsigned long tx_sbytes; /* tot bytes thru serial i/f */ - unsigned long rx_ebytes; /* tot stat/err bytes */ - unsigned long tx_ebytes; /* tot stat/err bytes */ -#endif - - /* - * Internal variables. - */ - - struct list_head list; /* Linked list of devices */ - - int discard; /* Set if serial error */ - int working; /* Is radio working correctly? */ - int firmware_level; /* Message structuring level */ - int next_command; /* Next periodic command */ - unsigned int user_baud; /* The user-selected baud rate */ - int mtu; /* Our mtu (to spot changes!) */ - long watchdog_doprobe; /* Next time to test the radio */ - long watchdog_doreset; /* Time to do next reset */ - long gratuitous_arp; /* Time to send next ARP refresh */ - long arp_interval; /* Next ARP interval */ - struct timer_list idle_timer; /* For periodic wakeup calls */ - MetricomAddress true_dev_addr; /* True address of radio */ - int manual_dev_addr; /* Hack: See note below */ - - FirmwareVersion firmware_version; /* The radio's firmware version */ - SerialNumber serial_number; /* The radio's serial number */ - BatteryVoltage battery_voltage; /* The radio's battery voltage */ - - /* - * Other useful structures. - */ - - struct tty_struct *tty; /* ptr to TTY structure */ - struct net_device *dev; /* Our device structure */ - - /* - * Neighbour radio records - */ - - MetricomNodeTable portables; - MetricomNodeTable poletops; -}; - -/* - * Note: manual_dev_addr hack - * - * It is not possible to change the hardware address of a Metricom radio, - * or to send packets with a user-specified hardware source address, thus - * trying to manually set a hardware source address is a questionable - * thing to do. However, if the user *does* manually set the hardware - * source address of a STRIP interface, then the kernel will believe it, - * and use it in certain places. For example, the hardware address listed - * by ifconfig will be the manual address, not the true one. - * (Both addresses are listed in /proc/net/strip.) - * Also, ARP packets will be sent out giving the user-specified address as - * the source address, not the real address. This is dangerous, because - * it means you won't receive any replies -- the ARP replies will go to - * the specified address, which will be some other radio. The case where - * this is useful is when that other radio is also connected to the same - * machine. This allows you to connect a pair of radios to one machine, - * and to use one exclusively for inbound traffic, and the other - * exclusively for outbound traffic. Pretty neat, huh? - * - * Here's the full procedure to set this up: - * - * 1. "slattach" two interfaces, e.g. st0 for outgoing packets, - * and st1 for incoming packets - * - * 2. "ifconfig" st0 (outbound radio) to have the hardware address - * which is the real hardware address of st1 (inbound radio). - * Now when it sends out packets, it will masquerade as st1, and - * replies will be sent to that radio, which is exactly what we want. - * - * 3. Set the route table entry ("route add default ..." or - * "route add -net ...", as appropriate) to send packets via the st0 - * interface (outbound radio). Do not add any route which sends packets - * out via the st1 interface -- that radio is for inbound traffic only. - * - * 4. "ifconfig" st1 (inbound radio) to have hardware address zero. - * This tells the STRIP driver to "shut down" that interface and not - * send any packets through it. In particular, it stops sending the - * periodic gratuitous ARP packets that a STRIP interface normally sends. - * Also, when packets arrive on that interface, it will search the - * interface list to see if there is another interface who's manual - * hardware address matches its own real address (i.e. st0 in this - * example) and if so it will transfer ownership of the skbuff to - * that interface, so that it looks to the kernel as if the packet - * arrived on that interface. This is necessary because when the - * kernel sends an ARP packet on st0, it expects to get a reply on - * st0, and if it sees the reply come from st1 then it will ignore - * it (to be accurate, it puts the entry in the ARP table, but - * labelled in such a way that st0 can't use it). - * - * Thanks to Petros Maniatis for coming up with the idea of splitting - * inbound and outbound traffic between two interfaces, which turned - * out to be really easy to implement, even if it is a bit of a hack. - * - * Having set a manual address on an interface, you can restore it - * to automatic operation (where the address is automatically kept - * consistent with the real address of the radio) by setting a manual - * address of all ones, e.g. "ifconfig st0 hw strip FFFFFFFFFFFF" - * This 'turns off' manual override mode for the device address. - * - * Note: The IEEE 802 headers reported in tcpdump will show the *real* - * radio addresses the packets were sent and received from, so that you - * can see what is really going on with packets, and which interfaces - * they are really going through. - */ - - -/************************************************************************/ -/* Constants */ - -/* - * CommandString1 works on all radios - * Other CommandStrings are only used with firmware that provides structured responses. - * - * ats319=1 Enables Info message for node additions and deletions - * ats319=2 Enables Info message for a new best node - * ats319=4 Enables checksums - * ats319=8 Enables ACK messages - */ - -static const int MaxCommandStringLength = 32; -static const int CompatibilityCommand = 1; - -static const char CommandString0[] = "*&COMMAND*ATS319=7"; /* Turn on checksums & info messages */ -static const char CommandString1[] = "*&COMMAND*ATS305?"; /* Query radio name */ -static const char CommandString2[] = "*&COMMAND*ATS325?"; /* Query battery voltage */ -static const char CommandString3[] = "*&COMMAND*ATS300?"; /* Query version information */ -static const char CommandString4[] = "*&COMMAND*ATS311?"; /* Query poletop list */ -static const char CommandString5[] = "*&COMMAND*AT~LA"; /* Query portables list */ -typedef struct { - const char *string; - long length; -} StringDescriptor; - -static const StringDescriptor CommandString[] = { - {CommandString0, sizeof(CommandString0) - 1}, - {CommandString1, sizeof(CommandString1) - 1}, - {CommandString2, sizeof(CommandString2) - 1}, - {CommandString3, sizeof(CommandString3) - 1}, - {CommandString4, sizeof(CommandString4) - 1}, - {CommandString5, sizeof(CommandString5) - 1} -}; - -#define GOT_ALL_RADIO_INFO(S) \ - ((S)->firmware_version.c[0] && \ - (S)->battery_voltage.c[0] && \ - memcmp(&(S)->true_dev_addr, zero_address.c, sizeof(zero_address))) - -static const char hextable[16] = "0123456789ABCDEF"; - -static const MetricomAddress zero_address; -static const MetricomAddress broadcast_address = - { {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF} }; - -static const MetricomKey SIP0Key = { "SIP0" }; -static const MetricomKey ARP0Key = { "ARP0" }; -static const MetricomKey ATR_Key = { "ATR " }; -static const MetricomKey ACK_Key = { "ACK_" }; -static const MetricomKey INF_Key = { "INF_" }; -static const MetricomKey ERR_Key = { "ERR_" }; - -static const long MaxARPInterval = 60 * HZ; /* One minute */ - -/* - * Maximum Starmode packet length is 1183 bytes. Allowing 4 bytes for - * protocol key, 4 bytes for checksum, one byte for CR, and 65/64 expansion - * for STRIP encoding, that translates to a maximum payload MTU of 1155. - * Note: A standard NFS 1K data packet is a total of 0x480 (1152) bytes - * long, including IP header, UDP header, and NFS header. Setting the STRIP - * MTU to 1152 allows us to send default sized NFS packets without fragmentation. - */ -static const unsigned short MAX_SEND_MTU = 1152; -static const unsigned short MAX_RECV_MTU = 1500; /* Hoping for Ethernet sized packets in the future! */ -static const unsigned short DEFAULT_STRIP_MTU = 1152; -static const int STRIP_MAGIC = 0x5303; -static const long LongTime = 0x7FFFFFFF; - -/************************************************************************/ -/* Global variables */ - -static LIST_HEAD(strip_list); -static DEFINE_SPINLOCK(strip_lock); - -/************************************************************************/ -/* Macros */ - -/* Returns TRUE if text T begins with prefix P */ -#define has_prefix(T,L,P) (((L) >= sizeof(P)-1) && !strncmp((T), (P), sizeof(P)-1)) - -/* Returns TRUE if text T of length L is equal to string S */ -#define text_equal(T,L,S) (((L) == sizeof(S)-1) && !strncmp((T), (S), sizeof(S)-1)) - -#define READHEX(X) ((X)>='0' && (X)<='9' ? (X)-'0' : \ - (X)>='a' && (X)<='f' ? (X)-'a'+10 : \ - (X)>='A' && (X)<='F' ? (X)-'A'+10 : 0 ) - -#define READHEX16(X) ((__u16)(READHEX(X))) - -#define READDEC(X) ((X)>='0' && (X)<='9' ? (X)-'0' : 0) - -#define ARRAY_END(X) (&((X)[ARRAY_SIZE(X)])) - -#define JIFFIE_TO_SEC(X) ((X) / HZ) - - -/************************************************************************/ -/* Utility routines */ - -static int arp_query(unsigned char *haddr, u32 paddr, - struct net_device *dev) -{ - struct neighbour *neighbor_entry; - int ret = 0; - - neighbor_entry = neigh_lookup(&arp_tbl, &paddr, dev); - - if (neighbor_entry != NULL) { - neighbor_entry->used = jiffies; - if (neighbor_entry->nud_state & NUD_VALID) { - memcpy(haddr, neighbor_entry->ha, dev->addr_len); - ret = 1; - } - neigh_release(neighbor_entry); - } - return ret; -} - -static void DumpData(char *msg, struct strip *strip_info, __u8 * ptr, - __u8 * end) -{ - static const int MAX_DumpData = 80; - __u8 pkt_text[MAX_DumpData], *p = pkt_text; - - *p++ = '\"'; - - while (ptr < end && p < &pkt_text[MAX_DumpData - 4]) { - if (*ptr == '\\') { - *p++ = '\\'; - *p++ = '\\'; - } else { - if (*ptr >= 32 && *ptr <= 126) { - *p++ = *ptr; - } else { - sprintf(p, "\\%02X", *ptr); - p += 3; - } - } - ptr++; - } - - if (ptr == end) - *p++ = '\"'; - *p++ = 0; - - printk(KERN_INFO "%s: %-13s%s\n", strip_info->dev->name, msg, pkt_text); -} - - -/************************************************************************/ -/* Byte stuffing/unstuffing routines */ - -/* Stuffing scheme: - * 00 Unused (reserved character) - * 01-3F Run of 2-64 different characters - * 40-7F Run of 1-64 different characters plus a single zero at the end - * 80-BF Run of 1-64 of the same character - * C0-FF Run of 1-64 zeroes (ASCII 0) - */ - -typedef enum { - Stuff_Diff = 0x00, - Stuff_DiffZero = 0x40, - Stuff_Same = 0x80, - Stuff_Zero = 0xC0, - Stuff_NoCode = 0xFF, /* Special code, meaning no code selected */ - - Stuff_CodeMask = 0xC0, - Stuff_CountMask = 0x3F, - Stuff_MaxCount = 0x3F, - Stuff_Magic = 0x0D /* The value we are eliminating */ -} StuffingCode; - -/* StuffData encodes the data starting at "src" for "length" bytes. - * It writes it to the buffer pointed to by "dst" (which must be at least - * as long as 1 + 65/64 of the input length). The output may be up to 1.6% - * larger than the input for pathological input, but will usually be smaller. - * StuffData returns the new value of the dst pointer as its result. - * "code_ptr_ptr" points to a "__u8 *" which is used to hold encoding state - * between calls, allowing an encoded packet to be incrementally built up - * from small parts. On the first call, the "__u8 *" pointed to should be - * initialized to NULL; between subsequent calls the calling routine should - * leave the value alone and simply pass it back unchanged so that the - * encoder can recover its current state. - */ - -#define StuffData_FinishBlock(X) \ -(*code_ptr = (X) ^ Stuff_Magic, code = Stuff_NoCode) - -static __u8 *StuffData(__u8 * src, __u32 length, __u8 * dst, - __u8 ** code_ptr_ptr) -{ - __u8 *end = src + length; - __u8 *code_ptr = *code_ptr_ptr; - __u8 code = Stuff_NoCode, count = 0; - - if (!length) - return (dst); - - if (code_ptr) { - /* - * Recover state from last call, if applicable - */ - code = (*code_ptr ^ Stuff_Magic) & Stuff_CodeMask; - count = (*code_ptr ^ Stuff_Magic) & Stuff_CountMask; - } - - while (src < end) { - switch (code) { - /* Stuff_NoCode: If no current code, select one */ - case Stuff_NoCode: - /* Record where we're going to put this code */ - code_ptr = dst++; - count = 0; /* Reset the count (zero means one instance) */ - /* Tentatively start a new block */ - if (*src == 0) { - code = Stuff_Zero; - src++; - } else { - code = Stuff_Same; - *dst++ = *src++ ^ Stuff_Magic; - } - /* Note: We optimistically assume run of same -- */ - /* which will be fixed later in Stuff_Same */ - /* if it turns out not to be true. */ - break; - - /* Stuff_Zero: We already have at least one zero encoded */ - case Stuff_Zero: - /* If another zero, count it, else finish this code block */ - if (*src == 0) { - count++; - src++; - } else { - StuffData_FinishBlock(Stuff_Zero + count); - } - break; - - /* Stuff_Same: We already have at least one byte encoded */ - case Stuff_Same: - /* If another one the same, count it */ - if ((*src ^ Stuff_Magic) == code_ptr[1]) { - count++; - src++; - break; - } - /* else, this byte does not match this block. */ - /* If we already have two or more bytes encoded, finish this code block */ - if (count) { - StuffData_FinishBlock(Stuff_Same + count); - break; - } - /* else, we only have one so far, so switch to Stuff_Diff code */ - code = Stuff_Diff; - /* and fall through to Stuff_Diff case below - * Note cunning cleverness here: case Stuff_Diff compares - * the current character with the previous two to see if it - * has a run of three the same. Won't this be an error if - * there aren't two previous characters stored to compare with? - * No. Because we know the current character is *not* the same - * as the previous one, the first test below will necessarily - * fail and the send half of the "if" won't be executed. - */ - - /* Stuff_Diff: We have at least two *different* bytes encoded */ - case Stuff_Diff: - /* If this is a zero, must encode a Stuff_DiffZero, and begin a new block */ - if (*src == 0) { - StuffData_FinishBlock(Stuff_DiffZero + - count); - } - /* else, if we have three in a row, it is worth starting a Stuff_Same block */ - else if ((*src ^ Stuff_Magic) == dst[-1] - && dst[-1] == dst[-2]) { - /* Back off the last two characters we encoded */ - code += count - 2; - /* Note: "Stuff_Diff + 0" is an illegal code */ - if (code == Stuff_Diff + 0) { - code = Stuff_Same + 0; - } - StuffData_FinishBlock(code); - code_ptr = dst - 2; - /* dst[-1] already holds the correct value */ - count = 2; /* 2 means three bytes encoded */ - code = Stuff_Same; - } - /* else, another different byte, so add it to the block */ - else { - *dst++ = *src ^ Stuff_Magic; - count++; - } - src++; /* Consume the byte */ - break; - } - if (count == Stuff_MaxCount) { - StuffData_FinishBlock(code + count); - } - } - if (code == Stuff_NoCode) { - *code_ptr_ptr = NULL; - } else { - *code_ptr_ptr = code_ptr; - StuffData_FinishBlock(code + count); - } - return (dst); -} - -/* - * UnStuffData decodes the data at "src", up to (but not including) "end". - * It writes the decoded data into the buffer pointed to by "dst", up to a - * maximum of "dst_length", and returns the new value of "src" so that a - * follow-on call can read more data, continuing from where the first left off. - * - * There are three types of results: - * 1. The source data runs out before extracting "dst_length" bytes: - * UnStuffData returns NULL to indicate failure. - * 2. The source data produces exactly "dst_length" bytes: - * UnStuffData returns new_src = end to indicate that all bytes were consumed. - * 3. "dst_length" bytes are extracted, with more remaining. - * UnStuffData returns new_src < end to indicate that there are more bytes - * to be read. - * - * Note: The decoding may be destructive, in that it may alter the source - * data in the process of decoding it (this is necessary to allow a follow-on - * call to resume correctly). - */ - -static __u8 *UnStuffData(__u8 * src, __u8 * end, __u8 * dst, - __u32 dst_length) -{ - __u8 *dst_end = dst + dst_length; - /* Sanity check */ - if (!src || !end || !dst || !dst_length) - return (NULL); - while (src < end && dst < dst_end) { - int count = (*src ^ Stuff_Magic) & Stuff_CountMask; - switch ((*src ^ Stuff_Magic) & Stuff_CodeMask) { - case Stuff_Diff: - if (src + 1 + count >= end) - return (NULL); - do { - *dst++ = *++src ^ Stuff_Magic; - } - while (--count >= 0 && dst < dst_end); - if (count < 0) - src += 1; - else { - if (count == 0) - *src = Stuff_Same ^ Stuff_Magic; - else - *src = - (Stuff_Diff + - count) ^ Stuff_Magic; - } - break; - case Stuff_DiffZero: - if (src + 1 + count >= end) - return (NULL); - do { - *dst++ = *++src ^ Stuff_Magic; - } - while (--count >= 0 && dst < dst_end); - if (count < 0) - *src = Stuff_Zero ^ Stuff_Magic; - else - *src = - (Stuff_DiffZero + count) ^ Stuff_Magic; - break; - case Stuff_Same: - if (src + 1 >= end) - return (NULL); - do { - *dst++ = src[1] ^ Stuff_Magic; - } - while (--count >= 0 && dst < dst_end); - if (count < 0) - src += 2; - else - *src = (Stuff_Same + count) ^ Stuff_Magic; - break; - case Stuff_Zero: - do { - *dst++ = 0; - } - while (--count >= 0 && dst < dst_end); - if (count < 0) - src += 1; - else - *src = (Stuff_Zero + count) ^ Stuff_Magic; - break; - } - } - if (dst < dst_end) - return (NULL); - else - return (src); -} - - -/************************************************************************/ -/* General routines for STRIP */ - -/* - * set_baud sets the baud rate to the rate defined by baudcode - */ -static void set_baud(struct tty_struct *tty, speed_t baudrate) -{ - struct ktermios old_termios; - - mutex_lock(&tty->termios_mutex); - old_termios =*(tty->termios); - tty_encode_baud_rate(tty, baudrate, baudrate); - tty->ops->set_termios(tty, &old_termios); - mutex_unlock(&tty->termios_mutex); -} - -/* - * Convert a string to a Metricom Address. - */ - -#define IS_RADIO_ADDRESS(p) ( \ - isdigit((p)[0]) && isdigit((p)[1]) && isdigit((p)[2]) && isdigit((p)[3]) && \ - (p)[4] == '-' && \ - isdigit((p)[5]) && isdigit((p)[6]) && isdigit((p)[7]) && isdigit((p)[8]) ) - -static int string_to_radio_address(MetricomAddress * addr, __u8 * p) -{ - if (!IS_RADIO_ADDRESS(p)) - return (1); - addr->c[0] = 0; - addr->c[1] = 0; - addr->c[2] = READHEX(p[0]) << 4 | READHEX(p[1]); - addr->c[3] = READHEX(p[2]) << 4 | READHEX(p[3]); - addr->c[4] = READHEX(p[5]) << 4 | READHEX(p[6]); - addr->c[5] = READHEX(p[7]) << 4 | READHEX(p[8]); - return (0); -} - -/* - * Convert a Metricom Address to a string. - */ - -static __u8 *radio_address_to_string(const MetricomAddress * addr, - MetricomAddressString * p) -{ - sprintf(p->c, "%02X%02X-%02X%02X", addr->c[2], addr->c[3], - addr->c[4], addr->c[5]); - return (p->c); -} - -/* - * Note: Must make sure sx_size is big enough to receive a stuffed - * MAX_RECV_MTU packet. Additionally, we also want to ensure that it's - * big enough to receive a large radio neighbour list (currently 4K). - */ - -static int allocate_buffers(struct strip *strip_info, int mtu) -{ - struct net_device *dev = strip_info->dev; - int sx_size = max_t(int, STRIP_ENCAP_SIZE(MAX_RECV_MTU), 4096); - int tx_size = STRIP_ENCAP_SIZE(mtu) + MaxCommandStringLength; - __u8 *r = kmalloc(MAX_RECV_MTU, GFP_ATOMIC); - __u8 *s = kmalloc(sx_size, GFP_ATOMIC); - __u8 *t = kmalloc(tx_size, GFP_ATOMIC); - if (r && s && t) { - strip_info->rx_buff = r; - strip_info->sx_buff = s; - strip_info->tx_buff = t; - strip_info->sx_size = sx_size; - strip_info->tx_size = tx_size; - strip_info->mtu = dev->mtu = mtu; - return (1); - } - kfree(r); - kfree(s); - kfree(t); - return (0); -} - -/* - * MTU has been changed by the IP layer. - * We could be in - * an upcall from the tty driver, or in an ip packet queue. - */ -static int strip_change_mtu(struct net_device *dev, int new_mtu) -{ - struct strip *strip_info = netdev_priv(dev); - int old_mtu = strip_info->mtu; - unsigned char *orbuff = strip_info->rx_buff; - unsigned char *osbuff = strip_info->sx_buff; - unsigned char *otbuff = strip_info->tx_buff; - - if (new_mtu > MAX_SEND_MTU) { - printk(KERN_ERR - "%s: MTU exceeds maximum allowable (%d), MTU change cancelled.\n", - strip_info->dev->name, MAX_SEND_MTU); - return -EINVAL; - } - - spin_lock_bh(&strip_lock); - if (!allocate_buffers(strip_info, new_mtu)) { - printk(KERN_ERR "%s: unable to grow strip buffers, MTU change cancelled.\n", - strip_info->dev->name); - spin_unlock_bh(&strip_lock); - return -ENOMEM; - } - - if (strip_info->sx_count) { - if (strip_info->sx_count <= strip_info->sx_size) - memcpy(strip_info->sx_buff, osbuff, - strip_info->sx_count); - else { - strip_info->discard = strip_info->sx_count; - strip_info->rx_over_errors++; - } - } - - if (strip_info->tx_left) { - if (strip_info->tx_left <= strip_info->tx_size) - memcpy(strip_info->tx_buff, strip_info->tx_head, - strip_info->tx_left); - else { - strip_info->tx_left = 0; - strip_info->tx_dropped++; - } - } - strip_info->tx_head = strip_info->tx_buff; - spin_unlock_bh(&strip_lock); - - printk(KERN_NOTICE "%s: strip MTU changed fom %d to %d.\n", - strip_info->dev->name, old_mtu, strip_info->mtu); - - kfree(orbuff); - kfree(osbuff); - kfree(otbuff); - return 0; -} - -static void strip_unlock(struct strip *strip_info) -{ - /* - * Set the timer to go off in one second. - */ - strip_info->idle_timer.expires = jiffies + 1 * HZ; - add_timer(&strip_info->idle_timer); - netif_wake_queue(strip_info->dev); -} - - - -/* - * If the time is in the near future, time_delta prints the number of - * seconds to go into the buffer and returns the address of the buffer. - * If the time is not in the near future, it returns the address of the - * string "Not scheduled" The buffer must be long enough to contain the - * ascii representation of the number plus 9 charactes for the " seconds" - * and the null character. - */ -#ifdef CONFIG_PROC_FS -static char *time_delta(char buffer[], long time) -{ - time -= jiffies; - if (time > LongTime / 2) - return ("Not scheduled"); - if (time < 0) - time = 0; /* Don't print negative times */ - sprintf(buffer, "%ld seconds", time / HZ); - return (buffer); -} - -/* get Nth element of the linked list */ -static struct strip *strip_get_idx(loff_t pos) -{ - struct strip *str; - int i = 0; - - list_for_each_entry_rcu(str, &strip_list, list) { - if (pos == i) - return str; - ++i; - } - return NULL; -} - -static void *strip_seq_start(struct seq_file *seq, loff_t *pos) - __acquires(RCU) -{ - rcu_read_lock(); - return *pos ? strip_get_idx(*pos - 1) : SEQ_START_TOKEN; -} - -static void *strip_seq_next(struct seq_file *seq, void *v, loff_t *pos) -{ - struct list_head *l; - struct strip *s; - - ++*pos; - if (v == SEQ_START_TOKEN) - return strip_get_idx(1); - - s = v; - l = &s->list; - list_for_each_continue_rcu(l, &strip_list) { - return list_entry(l, struct strip, list); - } - return NULL; -} - -static void strip_seq_stop(struct seq_file *seq, void *v) - __releases(RCU) -{ - rcu_read_unlock(); -} - -static void strip_seq_neighbours(struct seq_file *seq, - const MetricomNodeTable * table, - const char *title) -{ - /* We wrap this in a do/while loop, so if the table changes */ - /* while we're reading it, we just go around and try again. */ - struct timeval t; - - do { - int i; - t = table->timestamp; - if (table->num_nodes) - seq_printf(seq, "\n %s\n", title); - for (i = 0; i < table->num_nodes; i++) { - MetricomNode node; - - spin_lock_bh(&strip_lock); - node = table->node[i]; - spin_unlock_bh(&strip_lock); - seq_printf(seq, " %s\n", node.c); - } - } while (table->timestamp.tv_sec != t.tv_sec - || table->timestamp.tv_usec != t.tv_usec); -} - -/* - * This function prints radio status information via the seq_file - * interface. The interface takes care of buffer size and over - * run issues. - * - * The buffer in seq_file is PAGESIZE (4K) - * so this routine should never print more or it will get truncated. - * With the maximum of 32 portables and 32 poletops - * reported, the routine outputs 3107 bytes into the buffer. - */ -static void strip_seq_status_info(struct seq_file *seq, - const struct strip *strip_info) -{ - char temp[32]; - MetricomAddressString addr_string; - - /* First, we must copy all of our data to a safe place, */ - /* in case a serial interrupt comes in and changes it. */ - int tx_left = strip_info->tx_left; - unsigned long rx_average_pps = strip_info->rx_average_pps; - unsigned long tx_average_pps = strip_info->tx_average_pps; - unsigned long sx_average_pps = strip_info->sx_average_pps; - int working = strip_info->working; - int firmware_level = strip_info->firmware_level; - long watchdog_doprobe = strip_info->watchdog_doprobe; - long watchdog_doreset = strip_info->watchdog_doreset; - long gratuitous_arp = strip_info->gratuitous_arp; - long arp_interval = strip_info->arp_interval; - FirmwareVersion firmware_version = strip_info->firmware_version; - SerialNumber serial_number = strip_info->serial_number; - BatteryVoltage battery_voltage = strip_info->battery_voltage; - char *if_name = strip_info->dev->name; - MetricomAddress true_dev_addr = strip_info->true_dev_addr; - MetricomAddress dev_dev_addr = - *(MetricomAddress *) strip_info->dev->dev_addr; - int manual_dev_addr = strip_info->manual_dev_addr; -#ifdef EXT_COUNTERS - unsigned long rx_bytes = strip_info->rx_bytes; - unsigned long tx_bytes = strip_info->tx_bytes; - unsigned long rx_rbytes = strip_info->rx_rbytes; - unsigned long tx_rbytes = strip_info->tx_rbytes; - unsigned long rx_sbytes = strip_info->rx_sbytes; - unsigned long tx_sbytes = strip_info->tx_sbytes; - unsigned long rx_ebytes = strip_info->rx_ebytes; - unsigned long tx_ebytes = strip_info->tx_ebytes; -#endif - - seq_printf(seq, "\nInterface name\t\t%s\n", if_name); - seq_printf(seq, " Radio working:\t\t%s\n", working ? "Yes" : "No"); - radio_address_to_string(&true_dev_addr, &addr_string); - seq_printf(seq, " Radio address:\t\t%s\n", addr_string.c); - if (manual_dev_addr) { - radio_address_to_string(&dev_dev_addr, &addr_string); - seq_printf(seq, " Device address:\t%s\n", addr_string.c); - } - seq_printf(seq, " Firmware version:\t%s", !working ? "Unknown" : - !firmware_level ? "Should be upgraded" : - firmware_version.c); - if (firmware_level >= ChecksummedMessages) - seq_printf(seq, " (Checksums Enabled)"); - seq_printf(seq, "\n"); - seq_printf(seq, " Serial number:\t\t%s\n", serial_number.c); - seq_printf(seq, " Battery voltage:\t%s\n", battery_voltage.c); - seq_printf(seq, " Transmit queue (bytes):%d\n", tx_left); - seq_printf(seq, " Receive packet rate: %ld packets per second\n", - rx_average_pps / 8); - seq_printf(seq, " Transmit packet rate: %ld packets per second\n", - tx_average_pps / 8); - seq_printf(seq, " Sent packet rate: %ld packets per second\n", - sx_average_pps / 8); - seq_printf(seq, " Next watchdog probe:\t%s\n", - time_delta(temp, watchdog_doprobe)); - seq_printf(seq, " Next watchdog reset:\t%s\n", - time_delta(temp, watchdog_doreset)); - seq_printf(seq, " Next gratuitous ARP:\t"); - - if (!memcmp - (strip_info->dev->dev_addr, zero_address.c, - sizeof(zero_address))) - seq_printf(seq, "Disabled\n"); - else { - seq_printf(seq, "%s\n", time_delta(temp, gratuitous_arp)); - seq_printf(seq, " Next ARP interval:\t%ld seconds\n", - JIFFIE_TO_SEC(arp_interval)); - } - - if (working) { -#ifdef EXT_COUNTERS - seq_printf(seq, "\n"); - seq_printf(seq, - " Total bytes: \trx:\t%lu\ttx:\t%lu\n", - rx_bytes, tx_bytes); - seq_printf(seq, - " thru radio: \trx:\t%lu\ttx:\t%lu\n", - rx_rbytes, tx_rbytes); - seq_printf(seq, - " thru serial port: \trx:\t%lu\ttx:\t%lu\n", - rx_sbytes, tx_sbytes); - seq_printf(seq, - " Total stat/err bytes:\trx:\t%lu\ttx:\t%lu\n", - rx_ebytes, tx_ebytes); -#endif - strip_seq_neighbours(seq, &strip_info->poletops, - "Poletops:"); - strip_seq_neighbours(seq, &strip_info->portables, - "Portables:"); - } -} - -/* - * This function is exports status information from the STRIP driver through - * the /proc file system. - */ -static int strip_seq_show(struct seq_file *seq, void *v) -{ - if (v == SEQ_START_TOKEN) - seq_printf(seq, "strip_version: %s\n", StripVersion); - else - strip_seq_status_info(seq, (const struct strip *)v); - return 0; -} - - -static const struct seq_operations strip_seq_ops = { - .start = strip_seq_start, - .next = strip_seq_next, - .stop = strip_seq_stop, - .show = strip_seq_show, -}; - -static int strip_seq_open(struct inode *inode, struct file *file) -{ - return seq_open(file, &strip_seq_ops); -} - -static const struct file_operations strip_seq_fops = { - .owner = THIS_MODULE, - .open = strip_seq_open, - .read = seq_read, - .llseek = seq_lseek, - .release = seq_release, -}; -#endif - - - -/************************************************************************/ -/* Sending routines */ - -static void ResetRadio(struct strip *strip_info) -{ - struct tty_struct *tty = strip_info->tty; - static const char init[] = "ate0q1dt**starmode\r**"; - StringDescriptor s = { init, sizeof(init) - 1 }; - - /* - * If the radio isn't working anymore, - * we should clear the old status information. - */ - if (strip_info->working) { - printk(KERN_INFO "%s: No response: Resetting radio.\n", - strip_info->dev->name); - strip_info->firmware_version.c[0] = '\0'; - strip_info->serial_number.c[0] = '\0'; - strip_info->battery_voltage.c[0] = '\0'; - strip_info->portables.num_nodes = 0; - do_gettimeofday(&strip_info->portables.timestamp); - strip_info->poletops.num_nodes = 0; - do_gettimeofday(&strip_info->poletops.timestamp); - } - - strip_info->pps_timer = jiffies; - strip_info->rx_pps_count = 0; - strip_info->tx_pps_count = 0; - strip_info->sx_pps_count = 0; - strip_info->rx_average_pps = 0; - strip_info->tx_average_pps = 0; - strip_info->sx_average_pps = 0; - - /* Mark radio address as unknown */ - *(MetricomAddress *) & strip_info->true_dev_addr = zero_address; - if (!strip_info->manual_dev_addr) - *(MetricomAddress *) strip_info->dev->dev_addr = - zero_address; - strip_info->working = FALSE; - strip_info->firmware_level = NoStructure; - strip_info->next_command = CompatibilityCommand; - strip_info->watchdog_doprobe = jiffies + 10 * HZ; - strip_info->watchdog_doreset = jiffies + 1 * HZ; - - /* If the user has selected a baud rate above 38.4 see what magic we have to do */ - if (strip_info->user_baud > 38400) { - /* - * Subtle stuff: Pay attention :-) - * If the serial port is currently at the user's selected (>38.4) rate, - * then we temporarily switch to 19.2 and issue the ATS304 command - * to tell the radio to switch to the user's selected rate. - * If the serial port is not currently at that rate, that means we just - * issued the ATS304 command last time through, so this time we restore - * the user's selected rate and issue the normal starmode reset string. - */ - if (strip_info->user_baud == tty_get_baud_rate(tty)) { - static const char b0[] = "ate0q1s304=57600\r"; - static const char b1[] = "ate0q1s304=115200\r"; - static const StringDescriptor baudstring[2] = - { {b0, sizeof(b0) - 1} - , {b1, sizeof(b1) - 1} - }; - set_baud(tty, 19200); - if (strip_info->user_baud == 57600) - s = baudstring[0]; - else if (strip_info->user_baud == 115200) - s = baudstring[1]; - else - s = baudstring[1]; /* For now */ - } else - set_baud(tty, strip_info->user_baud); - } - - tty->ops->write(tty, s.string, s.length); -#ifdef EXT_COUNTERS - strip_info->tx_ebytes += s.length; -#endif -} - -/* - * Called by the driver when there's room for more data. If we have - * more packets to send, we send them here. - */ - -static void strip_write_some_more(struct tty_struct *tty) -{ - struct strip *strip_info = tty->disc_data; - - /* First make sure we're connected. */ - if (!strip_info || strip_info->magic != STRIP_MAGIC || - !netif_running(strip_info->dev)) - return; - - if (strip_info->tx_left > 0) { - int num_written = - tty->ops->write(tty, strip_info->tx_head, - strip_info->tx_left); - strip_info->tx_left -= num_written; - strip_info->tx_head += num_written; -#ifdef EXT_COUNTERS - strip_info->tx_sbytes += num_written; -#endif - } else { /* Else start transmission of another packet */ - - clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); - strip_unlock(strip_info); - } -} - -static __u8 *add_checksum(__u8 * buffer, __u8 * end) -{ - __u16 sum = 0; - __u8 *p = buffer; - while (p < end) - sum += *p++; - end[3] = hextable[sum & 0xF]; - sum >>= 4; - end[2] = hextable[sum & 0xF]; - sum >>= 4; - end[1] = hextable[sum & 0xF]; - sum >>= 4; - end[0] = hextable[sum & 0xF]; - return (end + 4); -} - -static unsigned char *strip_make_packet(unsigned char *buffer, - struct strip *strip_info, - struct sk_buff *skb) -{ - __u8 *ptr = buffer; - __u8 *stuffstate = NULL; - STRIP_Header *header = (STRIP_Header *) skb->data; - MetricomAddress haddr = header->dst_addr; - int len = skb->len - sizeof(STRIP_Header); - MetricomKey key; - - /*HexDump("strip_make_packet", strip_info, skb->data, skb->data + skb->len); */ - - if (header->protocol == htons(ETH_P_IP)) - key = SIP0Key; - else if (header->protocol == htons(ETH_P_ARP)) - key = ARP0Key; - else { - printk(KERN_ERR - "%s: strip_make_packet: Unknown packet type 0x%04X\n", - strip_info->dev->name, ntohs(header->protocol)); - return (NULL); - } - - if (len > strip_info->mtu) { - printk(KERN_ERR - "%s: Dropping oversized transmit packet: %d bytes\n", - strip_info->dev->name, len); - return (NULL); - } - - /* - * If we're sending to ourselves, discard the packet. - * (Metricom radios choke if they try to send a packet to their own address.) - */ - if (!memcmp(haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) { - printk(KERN_ERR "%s: Dropping packet addressed to self\n", - strip_info->dev->name); - return (NULL); - } - - /* - * If this is a broadcast packet, send it to our designated Metricom - * 'broadcast hub' radio (First byte of address being 0xFF means broadcast) - */ - if (haddr.c[0] == 0xFF) { - __be32 brd = 0; - struct in_device *in_dev; - - rcu_read_lock(); - in_dev = __in_dev_get_rcu(strip_info->dev); - if (in_dev == NULL) { - rcu_read_unlock(); - return NULL; - } - if (in_dev->ifa_list) - brd = in_dev->ifa_list->ifa_broadcast; - rcu_read_unlock(); - - /* arp_query returns 1 if it succeeds in looking up the address, 0 if it fails */ - if (!arp_query(haddr.c, brd, strip_info->dev)) { - printk(KERN_ERR - "%s: Unable to send packet (no broadcast hub configured)\n", - strip_info->dev->name); - return (NULL); - } - /* - * If we are the broadcast hub, don't bother sending to ourselves. - * (Metricom radios choke if they try to send a packet to their own address.) - */ - if (!memcmp - (haddr.c, strip_info->true_dev_addr.c, sizeof(haddr))) - return (NULL); - } - - *ptr++ = 0x0D; - *ptr++ = '*'; - *ptr++ = hextable[haddr.c[2] >> 4]; - *ptr++ = hextable[haddr.c[2] & 0xF]; - *ptr++ = hextable[haddr.c[3] >> 4]; - *ptr++ = hextable[haddr.c[3] & 0xF]; - *ptr++ = '-'; - *ptr++ = hextable[haddr.c[4] >> 4]; - *ptr++ = hextable[haddr.c[4] & 0xF]; - *ptr++ = hextable[haddr.c[5] >> 4]; - *ptr++ = hextable[haddr.c[5] & 0xF]; - *ptr++ = '*'; - *ptr++ = key.c[0]; - *ptr++ = key.c[1]; - *ptr++ = key.c[2]; - *ptr++ = key.c[3]; - - ptr = - StuffData(skb->data + sizeof(STRIP_Header), len, ptr, - &stuffstate); - - if (strip_info->firmware_level >= ChecksummedMessages) - ptr = add_checksum(buffer + 1, ptr); - - *ptr++ = 0x0D; - return (ptr); -} - -static void strip_send(struct strip *strip_info, struct sk_buff *skb) -{ - MetricomAddress haddr; - unsigned char *ptr = strip_info->tx_buff; - int doreset = (long) jiffies - strip_info->watchdog_doreset >= 0; - int doprobe = (long) jiffies - strip_info->watchdog_doprobe >= 0 - && !doreset; - __be32 addr, brd; - - /* - * 1. If we have a packet, encapsulate it and put it in the buffer - */ - if (skb) { - char *newptr = strip_make_packet(ptr, strip_info, skb); - strip_info->tx_pps_count++; - if (!newptr) - strip_info->tx_dropped++; - else { - ptr = newptr; - strip_info->sx_pps_count++; - strip_info->tx_packets++; /* Count another successful packet */ -#ifdef EXT_COUNTERS - strip_info->tx_bytes += skb->len; - strip_info->tx_rbytes += ptr - strip_info->tx_buff; -#endif - /*DumpData("Sending:", strip_info, strip_info->tx_buff, ptr); */ - /*HexDump("Sending", strip_info, strip_info->tx_buff, ptr); */ - } - } - - /* - * 2. If it is time for another tickle, tack it on, after the packet - */ - if (doprobe) { - StringDescriptor ts = CommandString[strip_info->next_command]; -#if TICKLE_TIMERS - { - struct timeval tv; - do_gettimeofday(&tv); - printk(KERN_INFO "**** Sending tickle string %d at %02d.%06d\n", - strip_info->next_command, tv.tv_sec % 100, - tv.tv_usec); - } -#endif - if (ptr == strip_info->tx_buff) - *ptr++ = 0x0D; - - *ptr++ = '*'; /* First send "**" to provoke an error message */ - *ptr++ = '*'; - - /* Then add the command */ - memcpy(ptr, ts.string, ts.length); - - /* Add a checksum ? */ - if (strip_info->firmware_level < ChecksummedMessages) - ptr += ts.length; - else - ptr = add_checksum(ptr, ptr + ts.length); - - *ptr++ = 0x0D; /* Terminate the command with a */ - - /* Cycle to next periodic command? */ - if (strip_info->firmware_level >= StructuredMessages) - if (++strip_info->next_command >= - ARRAY_SIZE(CommandString)) - strip_info->next_command = 0; -#ifdef EXT_COUNTERS - strip_info->tx_ebytes += ts.length; -#endif - strip_info->watchdog_doprobe = jiffies + 10 * HZ; - strip_info->watchdog_doreset = jiffies + 1 * HZ; - /*printk(KERN_INFO "%s: Routine radio test.\n", strip_info->dev->name); */ - } - - /* - * 3. Set up the strip_info ready to send the data (if any). - */ - strip_info->tx_head = strip_info->tx_buff; - strip_info->tx_left = ptr - strip_info->tx_buff; - set_bit(TTY_DO_WRITE_WAKEUP, &strip_info->tty->flags); - /* - * 4. Debugging check to make sure we're not overflowing the buffer. - */ - if (strip_info->tx_size - strip_info->tx_left < 20) - printk(KERN_ERR "%s: Sending%5d bytes;%5d bytes free.\n", - strip_info->dev->name, strip_info->tx_left, - strip_info->tx_size - strip_info->tx_left); - - /* - * 5. If watchdog has expired, reset the radio. Note: if there's data waiting in - * the buffer, strip_write_some_more will send it after the reset has finished - */ - if (doreset) { - ResetRadio(strip_info); - return; - } - - if (1) { - struct in_device *in_dev; - - brd = addr = 0; - rcu_read_lock(); - in_dev = __in_dev_get_rcu(strip_info->dev); - if (in_dev) { - if (in_dev->ifa_list) { - brd = in_dev->ifa_list->ifa_broadcast; - addr = in_dev->ifa_list->ifa_local; - } - } - rcu_read_unlock(); - } - - - /* - * 6. If it is time for a periodic ARP, queue one up to be sent. - * We only do this if: - * 1. The radio is working - * 2. It's time to send another periodic ARP - * 3. We really know what our address is (and it is not manually set to zero) - * 4. We have a designated broadcast address configured - * If we queue up an ARP packet when we don't have a designated broadcast - * address configured, then the packet will just have to be discarded in - * strip_make_packet. This is not fatal, but it causes misleading information - * to be displayed in tcpdump. tcpdump will report that periodic APRs are - * being sent, when in fact they are not, because they are all being dropped - * in the strip_make_packet routine. - */ - if (strip_info->working - && (long) jiffies - strip_info->gratuitous_arp >= 0 - && memcmp(strip_info->dev->dev_addr, zero_address.c, - sizeof(zero_address)) - && arp_query(haddr.c, brd, strip_info->dev)) { - /*printk(KERN_INFO "%s: Sending gratuitous ARP with interval %ld\n", - strip_info->dev->name, strip_info->arp_interval / HZ); */ - strip_info->gratuitous_arp = - jiffies + strip_info->arp_interval; - strip_info->arp_interval *= 2; - if (strip_info->arp_interval > MaxARPInterval) - strip_info->arp_interval = MaxARPInterval; - if (addr) - arp_send(ARPOP_REPLY, ETH_P_ARP, addr, /* Target address of ARP packet is our address */ - strip_info->dev, /* Device to send packet on */ - addr, /* Source IP address this ARP packet comes from */ - NULL, /* Destination HW address is NULL (broadcast it) */ - strip_info->dev->dev_addr, /* Source HW address is our HW address */ - strip_info->dev->dev_addr); /* Target HW address is our HW address (redundant) */ - } - - /* - * 7. All ready. Start the transmission - */ - strip_write_some_more(strip_info->tty); -} - -/* Encapsulate a datagram and kick it into a TTY queue. */ -static netdev_tx_t strip_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct strip *strip_info = netdev_priv(dev); - - if (!netif_running(dev)) { - printk(KERN_ERR "%s: xmit call when iface is down\n", - dev->name); - return NETDEV_TX_BUSY; - } - - netif_stop_queue(dev); - - del_timer(&strip_info->idle_timer); - - - if (time_after(jiffies, strip_info->pps_timer + HZ)) { - unsigned long t = jiffies - strip_info->pps_timer; - unsigned long rx_pps_count = - DIV_ROUND_CLOSEST(strip_info->rx_pps_count*HZ*8, t); - unsigned long tx_pps_count = - DIV_ROUND_CLOSEST(strip_info->tx_pps_count*HZ*8, t); - unsigned long sx_pps_count = - DIV_ROUND_CLOSEST(strip_info->sx_pps_count*HZ*8, t); - - strip_info->pps_timer = jiffies; - strip_info->rx_pps_count = 0; - strip_info->tx_pps_count = 0; - strip_info->sx_pps_count = 0; - - strip_info->rx_average_pps = (strip_info->rx_average_pps + rx_pps_count + 1) / 2; - strip_info->tx_average_pps = (strip_info->tx_average_pps + tx_pps_count + 1) / 2; - strip_info->sx_average_pps = (strip_info->sx_average_pps + sx_pps_count + 1) / 2; - - if (rx_pps_count / 8 >= 10) - printk(KERN_INFO "%s: WARNING: Receiving %ld packets per second.\n", - strip_info->dev->name, rx_pps_count / 8); - if (tx_pps_count / 8 >= 10) - printk(KERN_INFO "%s: WARNING: Tx %ld packets per second.\n", - strip_info->dev->name, tx_pps_count / 8); - if (sx_pps_count / 8 >= 10) - printk(KERN_INFO "%s: WARNING: Sending %ld packets per second.\n", - strip_info->dev->name, sx_pps_count / 8); - } - - spin_lock_bh(&strip_lock); - - strip_send(strip_info, skb); - - spin_unlock_bh(&strip_lock); - - if (skb) - dev_kfree_skb(skb); - return NETDEV_TX_OK; -} - -/* - * IdleTask periodically calls strip_xmit, so even when we have no IP packets - * to send for an extended period of time, the watchdog processing still gets - * done to ensure that the radio stays in Starmode - */ - -static void strip_IdleTask(unsigned long parameter) -{ - strip_xmit(NULL, (struct net_device *) parameter); -} - -/* - * Create the MAC header for an arbitrary protocol layer - * - * saddr!=NULL means use this specific address (n/a for Metricom) - * saddr==NULL means use default device source address - * daddr!=NULL means use this destination address - * daddr==NULL means leave destination address alone - * (e.g. unresolved arp -- kernel will call - * rebuild_header later to fill in the address) - */ - -static int strip_header(struct sk_buff *skb, struct net_device *dev, - unsigned short type, const void *daddr, - const void *saddr, unsigned len) -{ - struct strip *strip_info = netdev_priv(dev); - STRIP_Header *header = (STRIP_Header *) skb_push(skb, sizeof(STRIP_Header)); - - /*printk(KERN_INFO "%s: strip_header 0x%04X %s\n", dev->name, type, - type == ETH_P_IP ? "IP" : type == ETH_P_ARP ? "ARP" : ""); */ - - header->src_addr = strip_info->true_dev_addr; - header->protocol = htons(type); - - /*HexDump("strip_header", netdev_priv(dev), skb->data, skb->data + skb->len); */ - - if (!daddr) - return (-dev->hard_header_len); - - header->dst_addr = *(MetricomAddress *) daddr; - return (dev->hard_header_len); -} - -/* - * Rebuild the MAC header. This is called after an ARP - * (or in future other address resolution) has completed on this - * sk_buff. We now let ARP fill in the other fields. - * I think this should return zero if packet is ready to send, - * or non-zero if it needs more time to do an address lookup - */ - -static int strip_rebuild_header(struct sk_buff *skb) -{ -#ifdef CONFIG_INET - STRIP_Header *header = (STRIP_Header *) skb->data; - - /* Arp find returns zero if if knows the address, */ - /* or if it doesn't know the address it sends an ARP packet and returns non-zero */ - return arp_find(header->dst_addr.c, skb) ? 1 : 0; -#else - return 0; -#endif -} - - -/************************************************************************/ -/* Receiving routines */ - -/* - * This function parses the response to the ATS300? command, - * extracting the radio version and serial number. - */ -static void get_radio_version(struct strip *strip_info, __u8 * ptr, __u8 * end) -{ - __u8 *p, *value_begin, *value_end; - int len; - - /* Determine the beginning of the second line of the payload */ - p = ptr; - while (p < end && *p != 10) - p++; - if (p >= end) - return; - p++; - value_begin = p; - - /* Determine the end of line */ - while (p < end && *p != 10) - p++; - if (p >= end) - return; - value_end = p; - p++; - - len = value_end - value_begin; - len = min_t(int, len, sizeof(FirmwareVersion) - 1); - if (strip_info->firmware_version.c[0] == 0) - printk(KERN_INFO "%s: Radio Firmware: %.*s\n", - strip_info->dev->name, len, value_begin); - sprintf(strip_info->firmware_version.c, "%.*s", len, value_begin); - - /* Look for the first colon */ - while (p < end && *p != ':') - p++; - if (p >= end) - return; - /* Skip over the space */ - p += 2; - len = sizeof(SerialNumber) - 1; - if (p + len <= end) { - sprintf(strip_info->serial_number.c, "%.*s", len, p); - } else { - printk(KERN_DEBUG - "STRIP: radio serial number shorter (%zd) than expected (%d)\n", - end - p, len); - } -} - -/* - * This function parses the response to the ATS325? command, - * extracting the radio battery voltage. - */ -static void get_radio_voltage(struct strip *strip_info, __u8 * ptr, __u8 * end) -{ - int len; - - len = sizeof(BatteryVoltage) - 1; - if (ptr + len <= end) { - sprintf(strip_info->battery_voltage.c, "%.*s", len, ptr); - } else { - printk(KERN_DEBUG - "STRIP: radio voltage string shorter (%zd) than expected (%d)\n", - end - ptr, len); - } -} - -/* - * This function parses the responses to the AT~LA and ATS311 commands, - * which list the radio's neighbours. - */ -static void get_radio_neighbours(MetricomNodeTable * table, __u8 * ptr, __u8 * end) -{ - table->num_nodes = 0; - while (ptr < end && table->num_nodes < NODE_TABLE_SIZE) { - MetricomNode *node = &table->node[table->num_nodes++]; - char *dst = node->c, *limit = dst + sizeof(*node) - 1; - while (ptr < end && *ptr <= 32) - ptr++; - while (ptr < end && dst < limit && *ptr != 10) - *dst++ = *ptr++; - *dst++ = 0; - while (ptr < end && ptr[-1] != 10) - ptr++; - } - do_gettimeofday(&table->timestamp); -} - -static int get_radio_address(struct strip *strip_info, __u8 * p) -{ - MetricomAddress addr; - - if (string_to_radio_address(&addr, p)) - return (1); - - /* See if our radio address has changed */ - if (memcmp(strip_info->true_dev_addr.c, addr.c, sizeof(addr))) { - MetricomAddressString addr_string; - radio_address_to_string(&addr, &addr_string); - printk(KERN_INFO "%s: Radio address = %s\n", - strip_info->dev->name, addr_string.c); - strip_info->true_dev_addr = addr; - if (!strip_info->manual_dev_addr) - *(MetricomAddress *) strip_info->dev->dev_addr = - addr; - /* Give the radio a few seconds to get its head straight, then send an arp */ - strip_info->gratuitous_arp = jiffies + 15 * HZ; - strip_info->arp_interval = 1 * HZ; - } - return (0); -} - -static int verify_checksum(struct strip *strip_info) -{ - __u8 *p = strip_info->sx_buff; - __u8 *end = strip_info->sx_buff + strip_info->sx_count - 4; - u_short sum = - (READHEX16(end[0]) << 12) | (READHEX16(end[1]) << 8) | - (READHEX16(end[2]) << 4) | (READHEX16(end[3])); - while (p < end) - sum -= *p++; - if (sum == 0 && strip_info->firmware_level == StructuredMessages) { - strip_info->firmware_level = ChecksummedMessages; - printk(KERN_INFO "%s: Radio provides message checksums\n", - strip_info->dev->name); - } - return (sum == 0); -} - -static void RecvErr(char *msg, struct strip *strip_info) -{ - __u8 *ptr = strip_info->sx_buff; - __u8 *end = strip_info->sx_buff + strip_info->sx_count; - DumpData(msg, strip_info, ptr, end); - strip_info->rx_errors++; -} - -static void RecvErr_Message(struct strip *strip_info, __u8 * sendername, - const __u8 * msg, u_long len) -{ - if (has_prefix(msg, len, "001")) { /* Not in StarMode! */ - RecvErr("Error Msg:", strip_info); - printk(KERN_INFO "%s: Radio %s is not in StarMode\n", - strip_info->dev->name, sendername); - } - - else if (has_prefix(msg, len, "002")) { /* Remap handle */ - /* We ignore "Remap handle" messages for now */ - } - - else if (has_prefix(msg, len, "003")) { /* Can't resolve name */ - RecvErr("Error Msg:", strip_info); - printk(KERN_INFO "%s: Destination radio name is unknown\n", - strip_info->dev->name); - } - - else if (has_prefix(msg, len, "004")) { /* Name too small or missing */ - strip_info->watchdog_doreset = jiffies + LongTime; -#if TICKLE_TIMERS - { - struct timeval tv; - do_gettimeofday(&tv); - printk(KERN_INFO - "**** Got ERR_004 response at %02d.%06d\n", - tv.tv_sec % 100, tv.tv_usec); - } -#endif - if (!strip_info->working) { - strip_info->working = TRUE; - printk(KERN_INFO "%s: Radio now in starmode\n", - strip_info->dev->name); - /* - * If the radio has just entered a working state, we should do our first - * probe ASAP, so that we find out our radio address etc. without delay. - */ - strip_info->watchdog_doprobe = jiffies; - } - if (strip_info->firmware_level == NoStructure && sendername) { - strip_info->firmware_level = StructuredMessages; - strip_info->next_command = 0; /* Try to enable checksums ASAP */ - printk(KERN_INFO - "%s: Radio provides structured messages\n", - strip_info->dev->name); - } - if (strip_info->firmware_level >= StructuredMessages) { - /* - * If this message has a valid checksum on the end, then the call to verify_checksum - * will elevate the firmware_level to ChecksummedMessages for us. (The actual return - * code from verify_checksum is ignored here.) - */ - verify_checksum(strip_info); - /* - * If the radio has structured messages but we don't yet have all our information about it, - * we should do probes without delay, until we have gathered all the information - */ - if (!GOT_ALL_RADIO_INFO(strip_info)) - strip_info->watchdog_doprobe = jiffies; - } - } - - else if (has_prefix(msg, len, "005")) /* Bad count specification */ - RecvErr("Error Msg:", strip_info); - - else if (has_prefix(msg, len, "006")) /* Header too big */ - RecvErr("Error Msg:", strip_info); - - else if (has_prefix(msg, len, "007")) { /* Body too big */ - RecvErr("Error Msg:", strip_info); - printk(KERN_ERR - "%s: Error! Packet size too big for radio.\n", - strip_info->dev->name); - } - - else if (has_prefix(msg, len, "008")) { /* Bad character in name */ - RecvErr("Error Msg:", strip_info); - printk(KERN_ERR - "%s: Radio name contains illegal character\n", - strip_info->dev->name); - } - - else if (has_prefix(msg, len, "009")) /* No count or line terminator */ - RecvErr("Error Msg:", strip_info); - - else if (has_prefix(msg, len, "010")) /* Invalid checksum */ - RecvErr("Error Msg:", strip_info); - - else if (has_prefix(msg, len, "011")) /* Checksum didn't match */ - RecvErr("Error Msg:", strip_info); - - else if (has_prefix(msg, len, "012")) /* Failed to transmit packet */ - RecvErr("Error Msg:", strip_info); - - else - RecvErr("Error Msg:", strip_info); -} - -static void process_AT_response(struct strip *strip_info, __u8 * ptr, - __u8 * end) -{ - u_long len; - __u8 *p = ptr; - while (p < end && p[-1] != 10) - p++; /* Skip past first newline character */ - /* Now ptr points to the AT command, and p points to the text of the response. */ - len = p - ptr; - -#if TICKLE_TIMERS - { - struct timeval tv; - do_gettimeofday(&tv); - printk(KERN_INFO "**** Got AT response %.7s at %02d.%06d\n", - ptr, tv.tv_sec % 100, tv.tv_usec); - } -#endif - - if (has_prefix(ptr, len, "ATS300?")) - get_radio_version(strip_info, p, end); - else if (has_prefix(ptr, len, "ATS305?")) - get_radio_address(strip_info, p); - else if (has_prefix(ptr, len, "ATS311?")) - get_radio_neighbours(&strip_info->poletops, p, end); - else if (has_prefix(ptr, len, "ATS319=7")) - verify_checksum(strip_info); - else if (has_prefix(ptr, len, "ATS325?")) - get_radio_voltage(strip_info, p, end); - else if (has_prefix(ptr, len, "AT~LA")) - get_radio_neighbours(&strip_info->portables, p, end); - else - RecvErr("Unknown AT Response:", strip_info); -} - -static void process_ACK(struct strip *strip_info, __u8 * ptr, __u8 * end) -{ - /* Currently we don't do anything with ACKs from the radio */ -} - -static void process_Info(struct strip *strip_info, __u8 * ptr, __u8 * end) -{ - if (ptr + 16 > end) - RecvErr("Bad Info Msg:", strip_info); -} - -static struct net_device *get_strip_dev(struct strip *strip_info) -{ - /* If our hardware address is *manually set* to zero, and we know our */ - /* real radio hardware address, try to find another strip device that has been */ - /* manually set to that address that we can 'transfer ownership' of this packet to */ - if (strip_info->manual_dev_addr && - !memcmp(strip_info->dev->dev_addr, zero_address.c, - sizeof(zero_address)) - && memcmp(&strip_info->true_dev_addr, zero_address.c, - sizeof(zero_address))) { - struct net_device *dev; - read_lock_bh(&dev_base_lock); - for_each_netdev(&init_net, dev) { - if (dev->type == strip_info->dev->type && - !memcmp(dev->dev_addr, - &strip_info->true_dev_addr, - sizeof(MetricomAddress))) { - printk(KERN_INFO - "%s: Transferred packet ownership to %s.\n", - strip_info->dev->name, dev->name); - read_unlock_bh(&dev_base_lock); - return (dev); - } - } - read_unlock_bh(&dev_base_lock); - } - return (strip_info->dev); -} - -/* - * Send one completely decapsulated datagram to the next layer. - */ - -static void deliver_packet(struct strip *strip_info, STRIP_Header * header, - __u16 packetlen) -{ - struct sk_buff *skb = dev_alloc_skb(sizeof(STRIP_Header) + packetlen); - if (!skb) { - printk(KERN_ERR "%s: memory squeeze, dropping packet.\n", - strip_info->dev->name); - strip_info->rx_dropped++; - } else { - memcpy(skb_put(skb, sizeof(STRIP_Header)), header, - sizeof(STRIP_Header)); - memcpy(skb_put(skb, packetlen), strip_info->rx_buff, - packetlen); - skb->dev = get_strip_dev(strip_info); - skb->protocol = header->protocol; - skb_reset_mac_header(skb); - - /* Having put a fake header on the front of the sk_buff for the */ - /* benefit of tools like tcpdump, skb_pull now 'consumes' that */ - /* fake header before we hand the packet up to the next layer. */ - skb_pull(skb, sizeof(STRIP_Header)); - - /* Finally, hand the packet up to the next layer (e.g. IP or ARP, etc.) */ - strip_info->rx_packets++; - strip_info->rx_pps_count++; -#ifdef EXT_COUNTERS - strip_info->rx_bytes += packetlen; -#endif - netif_rx(skb); - } -} - -static void process_IP_packet(struct strip *strip_info, - STRIP_Header * header, __u8 * ptr, - __u8 * end) -{ - __u16 packetlen; - - /* Decode start of the IP packet header */ - ptr = UnStuffData(ptr, end, strip_info->rx_buff, 4); - if (!ptr) { - RecvErr("IP Packet too short", strip_info); - return; - } - - packetlen = ((__u16) strip_info->rx_buff[2] << 8) | strip_info->rx_buff[3]; - - if (packetlen > MAX_RECV_MTU) { - printk(KERN_INFO "%s: Dropping oversized received IP packet: %d bytes\n", - strip_info->dev->name, packetlen); - strip_info->rx_dropped++; - return; - } - - /*printk(KERN_INFO "%s: Got %d byte IP packet\n", strip_info->dev->name, packetlen); */ - - /* Decode remainder of the IP packet */ - ptr = - UnStuffData(ptr, end, strip_info->rx_buff + 4, packetlen - 4); - if (!ptr) { - RecvErr("IP Packet too short", strip_info); - return; - } - - if (ptr < end) { - RecvErr("IP Packet too long", strip_info); - return; - } - - header->protocol = htons(ETH_P_IP); - - deliver_packet(strip_info, header, packetlen); -} - -static void process_ARP_packet(struct strip *strip_info, - STRIP_Header * header, __u8 * ptr, - __u8 * end) -{ - __u16 packetlen; - struct arphdr *arphdr = (struct arphdr *) strip_info->rx_buff; - - /* Decode start of the ARP packet */ - ptr = UnStuffData(ptr, end, strip_info->rx_buff, 8); - if (!ptr) { - RecvErr("ARP Packet too short", strip_info); - return; - } - - packetlen = 8 + (arphdr->ar_hln + arphdr->ar_pln) * 2; - - if (packetlen > MAX_RECV_MTU) { - printk(KERN_INFO - "%s: Dropping oversized received ARP packet: %d bytes\n", - strip_info->dev->name, packetlen); - strip_info->rx_dropped++; - return; - } - - /*printk(KERN_INFO "%s: Got %d byte ARP %s\n", - strip_info->dev->name, packetlen, - ntohs(arphdr->ar_op) == ARPOP_REQUEST ? "request" : "reply"); */ - - /* Decode remainder of the ARP packet */ - ptr = - UnStuffData(ptr, end, strip_info->rx_buff + 8, packetlen - 8); - if (!ptr) { - RecvErr("ARP Packet too short", strip_info); - return; - } - - if (ptr < end) { - RecvErr("ARP Packet too long", strip_info); - return; - } - - header->protocol = htons(ETH_P_ARP); - - deliver_packet(strip_info, header, packetlen); -} - -/* - * process_text_message processes a -terminated block of data received - * from the radio that doesn't begin with a '*' character. All normal - * Starmode communication messages with the radio begin with a '*', - * so any text that does not indicates a serial port error, a radio that - * is in Hayes command mode instead of Starmode, or a radio with really - * old firmware that doesn't frame its Starmode responses properly. - */ -static void process_text_message(struct strip *strip_info) -{ - __u8 *msg = strip_info->sx_buff; - int len = strip_info->sx_count; - - /* Check for anything that looks like it might be our radio name */ - /* (This is here for backwards compatibility with old firmware) */ - if (len == 9 && get_radio_address(strip_info, msg) == 0) - return; - - if (text_equal(msg, len, "OK")) - return; /* Ignore 'OK' responses from prior commands */ - if (text_equal(msg, len, "ERROR")) - return; /* Ignore 'ERROR' messages */ - if (has_prefix(msg, len, "ate0q1")) - return; /* Ignore character echo back from the radio */ - - /* Catch other error messages */ - /* (This is here for backwards compatibility with old firmware) */ - if (has_prefix(msg, len, "ERR_")) { - RecvErr_Message(strip_info, NULL, &msg[4], len - 4); - return; - } - - RecvErr("No initial *", strip_info); -} - -/* - * process_message processes a -terminated block of data received - * from the radio. If the radio is not in Starmode or has old firmware, - * it may be a line of text in response to an AT command. Ideally, with - * a current radio that's properly in Starmode, all data received should - * be properly framed and checksummed radio message blocks, containing - * either a starmode packet, or a other communication from the radio - * firmware, like "INF_" Info messages and &COMMAND responses. - */ -static void process_message(struct strip *strip_info) -{ - STRIP_Header header = { zero_address, zero_address, 0 }; - __u8 *ptr = strip_info->sx_buff; - __u8 *end = strip_info->sx_buff + strip_info->sx_count; - __u8 sendername[32], *sptr = sendername; - MetricomKey key; - - /*HexDump("Receiving", strip_info, ptr, end); */ - - /* Check for start of address marker, and then skip over it */ - if (*ptr == '*') - ptr++; - else { - process_text_message(strip_info); - return; - } - - /* Copy out the return address */ - while (ptr < end && *ptr != '*' - && sptr < ARRAY_END(sendername) - 1) - *sptr++ = *ptr++; - *sptr = 0; /* Null terminate the sender name */ - - /* Check for end of address marker, and skip over it */ - if (ptr >= end || *ptr != '*') { - RecvErr("No second *", strip_info); - return; - } - ptr++; /* Skip the second '*' */ - - /* If the sender name is "&COMMAND", ignore this 'packet' */ - /* (This is here for backwards compatibility with old firmware) */ - if (!strcmp(sendername, "&COMMAND")) { - strip_info->firmware_level = NoStructure; - strip_info->next_command = CompatibilityCommand; - return; - } - - if (ptr + 4 > end) { - RecvErr("No proto key", strip_info); - return; - } - - /* Get the protocol key out of the buffer */ - key.c[0] = *ptr++; - key.c[1] = *ptr++; - key.c[2] = *ptr++; - key.c[3] = *ptr++; - - /* If we're using checksums, verify the checksum at the end of the packet */ - if (strip_info->firmware_level >= ChecksummedMessages) { - end -= 4; /* Chop the last four bytes off the packet (they're the checksum) */ - if (ptr > end) { - RecvErr("Missing Checksum", strip_info); - return; - } - if (!verify_checksum(strip_info)) { - RecvErr("Bad Checksum", strip_info); - return; - } - } - - /*printk(KERN_INFO "%s: Got packet from \"%s\".\n", strip_info->dev->name, sendername); */ - - /* - * Fill in (pseudo) source and destination addresses in the packet. - * We assume that the destination address was our address (the radio does not - * tell us this). If the radio supplies a source address, then we use it. - */ - header.dst_addr = strip_info->true_dev_addr; - string_to_radio_address(&header.src_addr, sendername); - -#ifdef EXT_COUNTERS - if (key.l == SIP0Key.l) { - strip_info->rx_rbytes += (end - ptr); - process_IP_packet(strip_info, &header, ptr, end); - } else if (key.l == ARP0Key.l) { - strip_info->rx_rbytes += (end - ptr); - process_ARP_packet(strip_info, &header, ptr, end); - } else if (key.l == ATR_Key.l) { - strip_info->rx_ebytes += (end - ptr); - process_AT_response(strip_info, ptr, end); - } else if (key.l == ACK_Key.l) { - strip_info->rx_ebytes += (end - ptr); - process_ACK(strip_info, ptr, end); - } else if (key.l == INF_Key.l) { - strip_info->rx_ebytes += (end - ptr); - process_Info(strip_info, ptr, end); - } else if (key.l == ERR_Key.l) { - strip_info->rx_ebytes += (end - ptr); - RecvErr_Message(strip_info, sendername, ptr, end - ptr); - } else - RecvErr("Unrecognized protocol key", strip_info); -#else - if (key.l == SIP0Key.l) - process_IP_packet(strip_info, &header, ptr, end); - else if (key.l == ARP0Key.l) - process_ARP_packet(strip_info, &header, ptr, end); - else if (key.l == ATR_Key.l) - process_AT_response(strip_info, ptr, end); - else if (key.l == ACK_Key.l) - process_ACK(strip_info, ptr, end); - else if (key.l == INF_Key.l) - process_Info(strip_info, ptr, end); - else if (key.l == ERR_Key.l) - RecvErr_Message(strip_info, sendername, ptr, end - ptr); - else - RecvErr("Unrecognized protocol key", strip_info); -#endif -} - -#define TTYERROR(X) ((X) == TTY_BREAK ? "Break" : \ - (X) == TTY_FRAME ? "Framing Error" : \ - (X) == TTY_PARITY ? "Parity Error" : \ - (X) == TTY_OVERRUN ? "Hardware Overrun" : "Unknown Error") - -/* - * Handle the 'receiver data ready' interrupt. - * This function is called by the 'tty_io' module in the kernel when - * a block of STRIP data has been received, which can now be decapsulated - * and sent on to some IP layer for further processing. - */ - -static void strip_receive_buf(struct tty_struct *tty, const unsigned char *cp, - char *fp, int count) -{ - struct strip *strip_info = tty->disc_data; - const unsigned char *end = cp + count; - - if (!strip_info || strip_info->magic != STRIP_MAGIC - || !netif_running(strip_info->dev)) - return; - - spin_lock_bh(&strip_lock); -#if 0 - { - struct timeval tv; - do_gettimeofday(&tv); - printk(KERN_INFO - "**** strip_receive_buf: %3d bytes at %02d.%06d\n", - count, tv.tv_sec % 100, tv.tv_usec); - } -#endif - -#ifdef EXT_COUNTERS - strip_info->rx_sbytes += count; -#endif - - /* Read the characters out of the buffer */ - while (cp < end) { - if (fp && *fp) - printk(KERN_INFO "%s: %s on serial port\n", - strip_info->dev->name, TTYERROR(*fp)); - if (fp && *fp++ && !strip_info->discard) { /* If there's a serial error, record it */ - /* If we have some characters in the buffer, discard them */ - strip_info->discard = strip_info->sx_count; - strip_info->rx_errors++; - } - - /* Leading control characters (CR, NL, Tab, etc.) are ignored */ - if (strip_info->sx_count > 0 || *cp >= ' ') { - if (*cp == 0x0D) { /* If end of packet, decide what to do with it */ - if (strip_info->sx_count > 3000) - printk(KERN_INFO - "%s: Cut a %d byte packet (%zd bytes remaining)%s\n", - strip_info->dev->name, - strip_info->sx_count, - end - cp - 1, - strip_info-> - discard ? " (discarded)" : - ""); - if (strip_info->sx_count > - strip_info->sx_size) { - strip_info->rx_over_errors++; - printk(KERN_INFO - "%s: sx_buff overflow (%d bytes total)\n", - strip_info->dev->name, - strip_info->sx_count); - } else if (strip_info->discard) - printk(KERN_INFO - "%s: Discarding bad packet (%d/%d)\n", - strip_info->dev->name, - strip_info->discard, - strip_info->sx_count); - else - process_message(strip_info); - strip_info->discard = 0; - strip_info->sx_count = 0; - } else { - /* Make sure we have space in the buffer */ - if (strip_info->sx_count < - strip_info->sx_size) - strip_info->sx_buff[strip_info-> - sx_count] = - *cp; - strip_info->sx_count++; - } - } - cp++; - } - spin_unlock_bh(&strip_lock); -} - - -/************************************************************************/ -/* General control routines */ - -static int set_mac_address(struct strip *strip_info, - MetricomAddress * addr) -{ - /* - * We're using a manually specified address if the address is set - * to anything other than all ones. Setting the address to all ones - * disables manual mode and goes back to automatic address determination - * (tracking the true address that the radio has). - */ - strip_info->manual_dev_addr = - memcmp(addr->c, broadcast_address.c, - sizeof(broadcast_address)); - if (strip_info->manual_dev_addr) - *(MetricomAddress *) strip_info->dev->dev_addr = *addr; - else - *(MetricomAddress *) strip_info->dev->dev_addr = - strip_info->true_dev_addr; - return 0; -} - -static int strip_set_mac_address(struct net_device *dev, void *addr) -{ - struct strip *strip_info = netdev_priv(dev); - struct sockaddr *sa = addr; - printk(KERN_INFO "%s: strip_set_dev_mac_address called\n", dev->name); - set_mac_address(strip_info, (MetricomAddress *) sa->sa_data); - return 0; -} - -static struct net_device_stats *strip_get_stats(struct net_device *dev) -{ - struct strip *strip_info = netdev_priv(dev); - static struct net_device_stats stats; - - memset(&stats, 0, sizeof(struct net_device_stats)); - - stats.rx_packets = strip_info->rx_packets; - stats.tx_packets = strip_info->tx_packets; - stats.rx_dropped = strip_info->rx_dropped; - stats.tx_dropped = strip_info->tx_dropped; - stats.tx_errors = strip_info->tx_errors; - stats.rx_errors = strip_info->rx_errors; - stats.rx_over_errors = strip_info->rx_over_errors; - return (&stats); -} - - -/************************************************************************/ -/* Opening and closing */ - -/* - * Here's the order things happen: - * When the user runs "slattach -p strip ..." - * 1. The TTY module calls strip_open;; - * 2. strip_open calls strip_alloc - * 3. strip_alloc calls register_netdev - * 4. register_netdev calls strip_dev_init - * 5. then strip_open finishes setting up the strip_info - * - * When the user runs "ifconfig st up address netmask ..." - * 6. strip_open_low gets called - * - * When the user runs "ifconfig st down" - * 7. strip_close_low gets called - * - * When the user kills the slattach process - * 8. strip_close gets called - * 9. strip_close calls dev_close - * 10. if the device is still up, then dev_close calls strip_close_low - * 11. strip_close calls strip_free - */ - -/* Open the low-level part of the STRIP channel. Easy! */ - -static int strip_open_low(struct net_device *dev) -{ - struct strip *strip_info = netdev_priv(dev); - - if (strip_info->tty == NULL) - return (-ENODEV); - - if (!allocate_buffers(strip_info, dev->mtu)) - return (-ENOMEM); - - strip_info->sx_count = 0; - strip_info->tx_left = 0; - - strip_info->discard = 0; - strip_info->working = FALSE; - strip_info->firmware_level = NoStructure; - strip_info->next_command = CompatibilityCommand; - strip_info->user_baud = tty_get_baud_rate(strip_info->tty); - - printk(KERN_INFO "%s: Initializing Radio.\n", - strip_info->dev->name); - ResetRadio(strip_info); - strip_info->idle_timer.expires = jiffies + 1 * HZ; - add_timer(&strip_info->idle_timer); - netif_wake_queue(dev); - return (0); -} - - -/* - * Close the low-level part of the STRIP channel. Easy! - */ - -static int strip_close_low(struct net_device *dev) -{ - struct strip *strip_info = netdev_priv(dev); - - if (strip_info->tty == NULL) - return -EBUSY; - clear_bit(TTY_DO_WRITE_WAKEUP, &strip_info->tty->flags); - netif_stop_queue(dev); - - /* - * Free all STRIP frame buffers. - */ - kfree(strip_info->rx_buff); - strip_info->rx_buff = NULL; - kfree(strip_info->sx_buff); - strip_info->sx_buff = NULL; - kfree(strip_info->tx_buff); - strip_info->tx_buff = NULL; - - del_timer(&strip_info->idle_timer); - return 0; -} - -static const struct header_ops strip_header_ops = { - .create = strip_header, - .rebuild = strip_rebuild_header, -}; - - -static const struct net_device_ops strip_netdev_ops = { - .ndo_open = strip_open_low, - .ndo_stop = strip_close_low, - .ndo_start_xmit = strip_xmit, - .ndo_set_mac_address = strip_set_mac_address, - .ndo_get_stats = strip_get_stats, - .ndo_change_mtu = strip_change_mtu, -}; - -/* - * This routine is called by DDI when the - * (dynamically assigned) device is registered - */ - -static void strip_dev_setup(struct net_device *dev) -{ - /* - * Finish setting up the DEVICE info. - */ - - dev->trans_start = 0; - dev->tx_queue_len = 30; /* Drop after 30 frames queued */ - - dev->flags = 0; - dev->mtu = DEFAULT_STRIP_MTU; - dev->type = ARPHRD_METRICOM; /* dtang */ - dev->hard_header_len = sizeof(STRIP_Header); - /* - * netdev_priv(dev) Already holds a pointer to our struct strip - */ - - *(MetricomAddress *)dev->broadcast = broadcast_address; - dev->dev_addr[0] = 0; - dev->addr_len = sizeof(MetricomAddress); - - dev->header_ops = &strip_header_ops, - dev->netdev_ops = &strip_netdev_ops; -} - -/* - * Free a STRIP channel. - */ - -static void strip_free(struct strip *strip_info) -{ - spin_lock_bh(&strip_lock); - list_del_rcu(&strip_info->list); - spin_unlock_bh(&strip_lock); - - strip_info->magic = 0; - - free_netdev(strip_info->dev); -} - - -/* - * Allocate a new free STRIP channel - */ -static struct strip *strip_alloc(void) -{ - struct list_head *n; - struct net_device *dev; - struct strip *strip_info; - - dev = alloc_netdev(sizeof(struct strip), "st%d", - strip_dev_setup); - - if (!dev) - return NULL; /* If no more memory, return */ - - - strip_info = netdev_priv(dev); - strip_info->dev = dev; - - strip_info->magic = STRIP_MAGIC; - strip_info->tty = NULL; - - strip_info->gratuitous_arp = jiffies + LongTime; - strip_info->arp_interval = 0; - init_timer(&strip_info->idle_timer); - strip_info->idle_timer.data = (long) dev; - strip_info->idle_timer.function = strip_IdleTask; - - - spin_lock_bh(&strip_lock); - rescan: - /* - * Search the list to find where to put our new entry - * (and in the process decide what channel number it is - * going to be) - */ - list_for_each(n, &strip_list) { - struct strip *s = hlist_entry(n, struct strip, list); - - if (s->dev->base_addr == dev->base_addr) { - ++dev->base_addr; - goto rescan; - } - } - - sprintf(dev->name, "st%ld", dev->base_addr); - - list_add_tail_rcu(&strip_info->list, &strip_list); - spin_unlock_bh(&strip_lock); - - return strip_info; -} - -/* - * Open the high-level part of the STRIP channel. - * This function is called by the TTY module when the - * STRIP line discipline is called for. Because we are - * sure the tty line exists, we only have to link it to - * a free STRIP channel... - */ - -static int strip_open(struct tty_struct *tty) -{ - struct strip *strip_info = tty->disc_data; - - /* - * First make sure we're not already connected. - */ - - if (strip_info && strip_info->magic == STRIP_MAGIC) - return -EEXIST; - - /* - * We need a write method. - */ - - if (tty->ops->write == NULL || tty->ops->set_termios == NULL) - return -EOPNOTSUPP; - - /* - * OK. Find a free STRIP channel to use. - */ - if ((strip_info = strip_alloc()) == NULL) - return -ENFILE; - - /* - * Register our newly created device so it can be ifconfig'd - * strip_dev_init() will be called as a side-effect - */ - - if (register_netdev(strip_info->dev) != 0) { - printk(KERN_ERR "strip: register_netdev() failed.\n"); - strip_free(strip_info); - return -ENFILE; - } - - strip_info->tty = tty; - tty->disc_data = strip_info; - tty->receive_room = 65536; - - tty_driver_flush_buffer(tty); - - /* - * Restore default settings - */ - - strip_info->dev->type = ARPHRD_METRICOM; /* dtang */ - - /* - * Set tty options - */ - - tty->termios->c_iflag |= IGNBRK | IGNPAR; /* Ignore breaks and parity errors. */ - tty->termios->c_cflag |= CLOCAL; /* Ignore modem control signals. */ - tty->termios->c_cflag &= ~HUPCL; /* Don't close on hup */ - - printk(KERN_INFO "STRIP: device \"%s\" activated\n", - strip_info->dev->name); - - /* - * Done. We have linked the TTY line to a channel. - */ - return (strip_info->dev->base_addr); -} - -/* - * Close down a STRIP channel. - * This means flushing out any pending queues, and then restoring the - * TTY line discipline to what it was before it got hooked to STRIP - * (which usually is TTY again). - */ - -static void strip_close(struct tty_struct *tty) -{ - struct strip *strip_info = tty->disc_data; - - /* - * First make sure we're connected. - */ - - if (!strip_info || strip_info->magic != STRIP_MAGIC) - return; - - unregister_netdev(strip_info->dev); - - tty->disc_data = NULL; - strip_info->tty = NULL; - printk(KERN_INFO "STRIP: device \"%s\" closed down\n", - strip_info->dev->name); - strip_free(strip_info); - tty->disc_data = NULL; -} - - -/************************************************************************/ -/* Perform I/O control calls on an active STRIP channel. */ - -static int strip_ioctl(struct tty_struct *tty, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct strip *strip_info = tty->disc_data; - - /* - * First make sure we're connected. - */ - - if (!strip_info || strip_info->magic != STRIP_MAGIC) - return -EINVAL; - - switch (cmd) { - case SIOCGIFNAME: - if(copy_to_user((void __user *) arg, strip_info->dev->name, strlen(strip_info->dev->name) + 1)) - return -EFAULT; - break; - case SIOCSIFHWADDR: - { - MetricomAddress addr; - //printk(KERN_INFO "%s: SIOCSIFHWADDR\n", strip_info->dev->name); - if(copy_from_user(&addr, (void __user *) arg, sizeof(MetricomAddress))) - return -EFAULT; - return set_mac_address(strip_info, &addr); - } - default: - return tty_mode_ioctl(tty, file, cmd, arg); - break; - } - return 0; -} - - -/************************************************************************/ -/* Initialization */ - -static struct tty_ldisc_ops strip_ldisc = { - .magic = TTY_LDISC_MAGIC, - .name = "strip", - .owner = THIS_MODULE, - .open = strip_open, - .close = strip_close, - .ioctl = strip_ioctl, - .receive_buf = strip_receive_buf, - .write_wakeup = strip_write_some_more, -}; - -/* - * Initialize the STRIP driver. - * This routine is called at boot time, to bootstrap the multi-channel - * STRIP driver - */ - -static char signon[] __initdata = - KERN_INFO "STRIP: Version %s (unlimited channels)\n"; - -static int __init strip_init_driver(void) -{ - int status; - - printk(signon, StripVersion); - - - /* - * Fill in our line protocol discipline, and register it - */ - if ((status = tty_register_ldisc(N_STRIP, &strip_ldisc))) - printk(KERN_ERR "STRIP: can't register line discipline (err = %d)\n", - status); - - /* - * Register the status file with /proc - */ - proc_net_fops_create(&init_net, "strip", S_IFREG | S_IRUGO, &strip_seq_fops); - - return status; -} - -module_init(strip_init_driver); - -static const char signoff[] __exitdata = - KERN_INFO "STRIP: Module Unloaded\n"; - -static void __exit strip_exit_driver(void) -{ - int i; - struct list_head *p,*n; - - /* module ref count rules assure that all entries are unregistered */ - list_for_each_safe(p, n, &strip_list) { - struct strip *s = list_entry(p, struct strip, list); - strip_free(s); - } - - /* Unregister with the /proc/net file here. */ - proc_net_remove(&init_net, "strip"); - - if ((i = tty_unregister_ldisc(N_STRIP))) - printk(KERN_ERR "STRIP: can't unregister line discipline (err = %d)\n", i); - - printk(signoff); -} - -module_exit(strip_exit_driver); - -MODULE_AUTHOR("Stuart Cheshire "); -MODULE_DESCRIPTION("Starmode Radio IP (STRIP) Device Driver"); -MODULE_LICENSE("Dual BSD/GPL"); - -MODULE_SUPPORTED_DEVICE("Starmode Radio IP (STRIP) modem"); diff --git a/drivers/net/wireless/wavelan.c b/drivers/net/wireless/wavelan.c deleted file mode 100644 index d634b2da3b84..000000000000 --- a/drivers/net/wireless/wavelan.c +++ /dev/null @@ -1,4383 +0,0 @@ -/* - * WaveLAN ISA driver - * - * Jean II - HPLB '96 - * - * Reorganisation and extension of the driver. - * Original copyright follows (also see the end of this file). - * See wavelan.p.h for details. - * - * - * - * AT&T GIS (nee NCR) WaveLAN card: - * An Ethernet-like radio transceiver - * controlled by an Intel 82586 coprocessor. - */ - -#include "wavelan.p.h" /* Private header */ - -/************************* MISC SUBROUTINES **************************/ -/* - * Subroutines which won't fit in one of the following category - * (WaveLAN modem or i82586) - */ - -/*------------------------------------------------------------------*/ -/* - * Translate irq number to PSA irq parameter - */ -static u8 wv_irq_to_psa(int irq) -{ - if (irq < 0 || irq >= ARRAY_SIZE(irqvals)) - return 0; - - return irqvals[irq]; -} - -/*------------------------------------------------------------------*/ -/* - * Translate PSA irq parameter to irq number - */ -static int __init wv_psa_to_irq(u8 irqval) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(irqvals); i++) - if (irqvals[i] == irqval) - return i; - - return -1; -} - -/********************* HOST ADAPTER SUBROUTINES *********************/ -/* - * Useful subroutines to manage the WaveLAN ISA interface - * - * One major difference with the PCMCIA hardware (except the port mapping) - * is that we have to keep the state of the Host Control Register - * because of the interrupt enable & bus size flags. - */ - -/*------------------------------------------------------------------*/ -/* - * Read from card's Host Adaptor Status Register. - */ -static inline u16 hasr_read(unsigned long ioaddr) -{ - return (inw(HASR(ioaddr))); -} /* hasr_read */ - -/*------------------------------------------------------------------*/ -/* - * Write to card's Host Adapter Command Register. - */ -static inline void hacr_write(unsigned long ioaddr, u16 hacr) -{ - outw(hacr, HACR(ioaddr)); -} /* hacr_write */ - -/*------------------------------------------------------------------*/ -/* - * Write to card's Host Adapter Command Register. Include a delay for - * those times when it is needed. - */ -static void hacr_write_slow(unsigned long ioaddr, u16 hacr) -{ - hacr_write(ioaddr, hacr); - /* delay might only be needed sometimes */ - mdelay(1); -} /* hacr_write_slow */ - -/*------------------------------------------------------------------*/ -/* - * Set the channel attention bit. - */ -static inline void set_chan_attn(unsigned long ioaddr, u16 hacr) -{ - hacr_write(ioaddr, hacr | HACR_CA); -} /* set_chan_attn */ - -/*------------------------------------------------------------------*/ -/* - * Reset, and then set host adaptor into default mode. - */ -static inline void wv_hacr_reset(unsigned long ioaddr) -{ - hacr_write_slow(ioaddr, HACR_RESET); - hacr_write(ioaddr, HACR_DEFAULT); -} /* wv_hacr_reset */ - -/*------------------------------------------------------------------*/ -/* - * Set the I/O transfer over the ISA bus to 8-bit mode - */ -static inline void wv_16_off(unsigned long ioaddr, u16 hacr) -{ - hacr &= ~HACR_16BITS; - hacr_write(ioaddr, hacr); -} /* wv_16_off */ - -/*------------------------------------------------------------------*/ -/* - * Set the I/O transfer over the ISA bus to 8-bit mode - */ -static inline void wv_16_on(unsigned long ioaddr, u16 hacr) -{ - hacr |= HACR_16BITS; - hacr_write(ioaddr, hacr); -} /* wv_16_on */ - -/*------------------------------------------------------------------*/ -/* - * Disable interrupts on the WaveLAN hardware. - * (called by wv_82586_stop()) - */ -static inline void wv_ints_off(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - - lp->hacr &= ~HACR_INTRON; - hacr_write(ioaddr, lp->hacr); -} /* wv_ints_off */ - -/*------------------------------------------------------------------*/ -/* - * Enable interrupts on the WaveLAN hardware. - * (called by wv_hw_reset()) - */ -static inline void wv_ints_on(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - - lp->hacr |= HACR_INTRON; - hacr_write(ioaddr, lp->hacr); -} /* wv_ints_on */ - -/******************* MODEM MANAGEMENT SUBROUTINES *******************/ -/* - * Useful subroutines to manage the modem of the WaveLAN - */ - -/*------------------------------------------------------------------*/ -/* - * Read the Parameter Storage Area from the WaveLAN card's memory - */ -/* - * Read bytes from the PSA. - */ -static void psa_read(unsigned long ioaddr, u16 hacr, int o, /* offset in PSA */ - u8 * b, /* buffer to fill */ - int n) -{ /* size to read */ - wv_16_off(ioaddr, hacr); - - while (n-- > 0) { - outw(o, PIOR2(ioaddr)); - o++; - *b++ = inb(PIOP2(ioaddr)); - } - - wv_16_on(ioaddr, hacr); -} /* psa_read */ - -/*------------------------------------------------------------------*/ -/* - * Write the Parameter Storage Area to the WaveLAN card's memory. - */ -static void psa_write(unsigned long ioaddr, u16 hacr, int o, /* Offset in PSA */ - u8 * b, /* Buffer in memory */ - int n) -{ /* Length of buffer */ - int count = 0; - - wv_16_off(ioaddr, hacr); - - while (n-- > 0) { - outw(o, PIOR2(ioaddr)); - o++; - - outb(*b, PIOP2(ioaddr)); - b++; - - /* Wait for the memory to finish its write cycle */ - count = 0; - while ((count++ < 100) && - (hasr_read(ioaddr) & HASR_PSA_BUSY)) mdelay(1); - } - - wv_16_on(ioaddr, hacr); -} /* psa_write */ - -#ifdef SET_PSA_CRC -/*------------------------------------------------------------------*/ -/* - * Calculate the PSA CRC - * Thanks to Valster, Nico for the code - * NOTE: By specifying a length including the CRC position the - * returned value should be zero. (i.e. a correct checksum in the PSA) - * - * The Windows drivers don't use the CRC, but the AP and the PtP tool - * depend on it. - */ -static u16 psa_crc(u8 * psa, /* The PSA */ - int size) -{ /* Number of short for CRC */ - int byte_cnt; /* Loop on the PSA */ - u16 crc_bytes = 0; /* Data in the PSA */ - int bit_cnt; /* Loop on the bits of the short */ - - for (byte_cnt = 0; byte_cnt < size; byte_cnt++) { - crc_bytes ^= psa[byte_cnt]; /* Its an xor */ - - for (bit_cnt = 1; bit_cnt < 9; bit_cnt++) { - if (crc_bytes & 0x0001) - crc_bytes = (crc_bytes >> 1) ^ 0xA001; - else - crc_bytes >>= 1; - } - } - - return crc_bytes; -} /* psa_crc */ -#endif /* SET_PSA_CRC */ - -/*------------------------------------------------------------------*/ -/* - * update the checksum field in the Wavelan's PSA - */ -static void update_psa_checksum(struct net_device * dev, unsigned long ioaddr, u16 hacr) -{ -#ifdef SET_PSA_CRC - psa_t psa; - u16 crc; - - /* read the parameter storage area */ - psa_read(ioaddr, hacr, 0, (unsigned char *) &psa, sizeof(psa)); - - /* update the checksum */ - crc = psa_crc((unsigned char *) &psa, - sizeof(psa) - sizeof(psa.psa_crc[0]) - - sizeof(psa.psa_crc[1]) - - sizeof(psa.psa_crc_status)); - - psa.psa_crc[0] = crc & 0xFF; - psa.psa_crc[1] = (crc & 0xFF00) >> 8; - - /* Write it ! */ - psa_write(ioaddr, hacr, (char *) &psa.psa_crc - (char *) &psa, - (unsigned char *) &psa.psa_crc, 2); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n", - dev->name, psa.psa_crc[0], psa.psa_crc[1]); - - /* Check again (luxury !) */ - crc = psa_crc((unsigned char *) &psa, - sizeof(psa) - sizeof(psa.psa_crc_status)); - - if (crc != 0) - printk(KERN_WARNING - "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", - dev->name); -#endif /* DEBUG_IOCTL_INFO */ -#endif /* SET_PSA_CRC */ -} /* update_psa_checksum */ - -/*------------------------------------------------------------------*/ -/* - * Write 1 byte to the MMC. - */ -static void mmc_out(unsigned long ioaddr, u16 o, u8 d) -{ - int count = 0; - - /* Wait for MMC to go idle */ - while ((count++ < 100) && (inw(HASR(ioaddr)) & HASR_MMC_BUSY)) - udelay(10); - - outw((u16) (((u16) d << 8) | (o << 1) | 1), MMCR(ioaddr)); -} - -/*------------------------------------------------------------------*/ -/* - * Routine to write bytes to the Modem Management Controller. - * We start at the end because it is the way it should be! - */ -static void mmc_write(unsigned long ioaddr, u8 o, u8 * b, int n) -{ - o += n; - b += n; - - while (n-- > 0) - mmc_out(ioaddr, --o, *(--b)); -} /* mmc_write */ - -/*------------------------------------------------------------------*/ -/* - * Read a byte from the MMC. - * Optimised version for 1 byte, avoid using memory. - */ -static u8 mmc_in(unsigned long ioaddr, u16 o) -{ - int count = 0; - - while ((count++ < 100) && (inw(HASR(ioaddr)) & HASR_MMC_BUSY)) - udelay(10); - outw(o << 1, MMCR(ioaddr)); - - while ((count++ < 100) && (inw(HASR(ioaddr)) & HASR_MMC_BUSY)) - udelay(10); - return (u8) (inw(MMCR(ioaddr)) >> 8); -} - -/*------------------------------------------------------------------*/ -/* - * Routine to read bytes from the Modem Management Controller. - * The implementation is complicated by a lack of address lines, - * which prevents decoding of the low-order bit. - * (code has just been moved in the above function) - * We start at the end because it is the way it should be! - */ -static inline void mmc_read(unsigned long ioaddr, u8 o, u8 * b, int n) -{ - o += n; - b += n; - - while (n-- > 0) - *(--b) = mmc_in(ioaddr, --o); -} /* mmc_read */ - -/*------------------------------------------------------------------*/ -/* - * Get the type of encryption available. - */ -static inline int mmc_encr(unsigned long ioaddr) -{ /* I/O port of the card */ - int temp; - - temp = mmc_in(ioaddr, mmroff(0, mmr_des_avail)); - if ((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES)) - return 0; - else - return temp; -} - -/*------------------------------------------------------------------*/ -/* - * Wait for the frequency EEPROM to complete a command. - * I hope this one will be optimally inlined. - */ -static inline void fee_wait(unsigned long ioaddr, /* I/O port of the card */ - int delay, /* Base delay to wait for */ - int number) -{ /* Number of time to wait */ - int count = 0; /* Wait only a limited time */ - - while ((count++ < number) && - (mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - MMR_FEE_STATUS_BUSY)) udelay(delay); -} - -/*------------------------------------------------------------------*/ -/* - * Read bytes from the Frequency EEPROM (frequency select cards). - */ -static void fee_read(unsigned long ioaddr, /* I/O port of the card */ - u16 o, /* destination offset */ - u16 * b, /* data buffer */ - int n) -{ /* number of registers */ - b += n; /* Position at the end of the area */ - - /* Write the address */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); - - /* Loop on all buffer */ - while (n-- > 0) { - /* Write the read command */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ); - - /* Wait until EEPROM is ready (should be quick). */ - fee_wait(ioaddr, 10, 100); - - /* Read the value. */ - *--b = ((mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)) << 8) | - mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); - } -} - - -/*------------------------------------------------------------------*/ -/* - * Write bytes from the Frequency EEPROM (frequency select cards). - * This is a bit complicated, because the frequency EEPROM has to - * be unprotected and the write enabled. - * Jean II - */ -static void fee_write(unsigned long ioaddr, /* I/O port of the card */ - u16 o, /* destination offset */ - u16 * b, /* data buffer */ - int n) -{ /* number of registers */ - b += n; /* Position at the end of the area. */ - -#ifdef EEPROM_IS_PROTECTED /* disabled */ -#ifdef DOESNT_SEEM_TO_WORK /* disabled */ - /* Ask to read the protected register */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD); - - fee_wait(ioaddr, 10, 100); - - /* Read the protected register. */ - printk("Protected 2: %02X-%02X\n", - mmc_in(ioaddr, mmroff(0, mmr_fee_data_h)), - mmc_in(ioaddr, mmroff(0, mmr_fee_data_l))); -#endif /* DOESNT_SEEM_TO_WORK */ - - /* Enable protected register. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN); - - fee_wait(ioaddr, 10, 100); - - /* Unprotect area. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); -#ifdef DOESNT_SEEM_TO_WORK /* disabled */ - /* or use: */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR); -#endif /* DOESNT_SEEM_TO_WORK */ - - fee_wait(ioaddr, 10, 100); -#endif /* EEPROM_IS_PROTECTED */ - - /* Write enable. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN); - - fee_wait(ioaddr, 10, 100); - - /* Write the EEPROM address. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), o + n - 1); - - /* Loop on all buffer */ - while (n-- > 0) { - /* Write the value. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_data_h), (*--b) >> 8); - mmc_out(ioaddr, mmwoff(0, mmw_fee_data_l), *b & 0xFF); - - /* Write the write command. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_WRITE); - - /* WaveLAN documentation says to wait at least 10 ms for EEBUSY = 0 */ - mdelay(10); - fee_wait(ioaddr, 10, 100); - } - - /* Write disable. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS); - - fee_wait(ioaddr, 10, 100); - -#ifdef EEPROM_IS_PROTECTED /* disabled */ - /* Reprotect EEPROM. */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x00); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); - - fee_wait(ioaddr, 10, 100); -#endif /* EEPROM_IS_PROTECTED */ -} - -/************************ I82586 SUBROUTINES *************************/ -/* - * Useful subroutines to manage the Ethernet controller - */ - -/*------------------------------------------------------------------*/ -/* - * Read bytes from the on-board RAM. - * Why does inlining this function make it fail? - */ -static /*inline */ void obram_read(unsigned long ioaddr, - u16 o, u8 * b, int n) -{ - outw(o, PIOR1(ioaddr)); - insw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1); -} - -/*------------------------------------------------------------------*/ -/* - * Write bytes to the on-board RAM. - */ -static inline void obram_write(unsigned long ioaddr, u16 o, u8 * b, int n) -{ - outw(o, PIOR1(ioaddr)); - outsw(PIOP1(ioaddr), (unsigned short *) b, (n + 1) >> 1); -} - -/*------------------------------------------------------------------*/ -/* - * Acknowledge the reading of the status issued by the i82586. - */ -static void wv_ack(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - u16 scb_cs; - int i; - - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - scb_cs &= SCB_ST_INT; - - if (scb_cs == 0) - return; - - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(10); - } - udelay(100); - -#ifdef DEBUG_CONFIG_ERROR - if (i <= 0) - printk(KERN_INFO - "%s: wv_ack(): board not accepting command.\n", - dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * Set channel attention bit and busy wait until command has - * completed, then acknowledge completion of the command. - */ -static int wv_synchronous_cmd(struct net_device * dev, const char *str) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - u16 scb_cmd; - ach_t cb; - int i; - - scb_cmd = SCB_CMD_CUC & SCB_CMD_CUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cmd, sizeof(scb_cmd)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) { - obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb, - sizeof(cb)); - if (cb.ac_status & AC_SFLD_C) - break; - - udelay(10); - } - udelay(100); - - if (i <= 0 || !(cb.ac_status & AC_SFLD_OK)) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: %s failed; status = 0x%x\n", - dev->name, str, cb.ac_status); -#endif -#ifdef DEBUG_I82586_SHOW - wv_scb_show(ioaddr); -#endif - return -1; - } - - /* Ack the status */ - wv_ack(dev); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Configuration commands completion interrupt. - * Check if done, and if OK. - */ -static int -wv_config_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) -{ - unsigned short mcs_addr; - unsigned short status; - int ret; - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wv_config_complete()\n", dev->name); -#endif - - mcs_addr = lp->tx_first_in_use + sizeof(ac_tx_t) + sizeof(ac_nop_t) - + sizeof(tbd_t) + sizeof(ac_cfg_t) + sizeof(ac_ias_t); - - /* Read the status of the last command (set mc list). */ - obram_read(ioaddr, acoff(mcs_addr, ac_status), - (unsigned char *) &status, sizeof(status)); - - /* If not completed -> exit */ - if ((status & AC_SFLD_C) == 0) - ret = 0; /* Not ready to be scrapped */ - else { -#ifdef DEBUG_CONFIG_ERROR - unsigned short cfg_addr; - unsigned short ias_addr; - - /* Check mc_config command */ - if ((status & AC_SFLD_OK) != AC_SFLD_OK) - printk(KERN_INFO - "%s: wv_config_complete(): set_multicast_address failed; status = 0x%x\n", - dev->name, status); - - /* check ia-config command */ - ias_addr = mcs_addr - sizeof(ac_ias_t); - obram_read(ioaddr, acoff(ias_addr, ac_status), - (unsigned char *) &status, sizeof(status)); - if ((status & AC_SFLD_OK) != AC_SFLD_OK) - printk(KERN_INFO - "%s: wv_config_complete(): set_MAC_address failed; status = 0x%x\n", - dev->name, status); - - /* Check config command. */ - cfg_addr = ias_addr - sizeof(ac_cfg_t); - obram_read(ioaddr, acoff(cfg_addr, ac_status), - (unsigned char *) &status, sizeof(status)); - if ((status & AC_SFLD_OK) != AC_SFLD_OK) - printk(KERN_INFO - "%s: wv_config_complete(): configure failed; status = 0x%x\n", - dev->name, status); -#endif /* DEBUG_CONFIG_ERROR */ - - ret = 1; /* Ready to be scrapped */ - } - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wv_config_complete() - %d\n", dev->name, - ret); -#endif - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Command completion interrupt. - * Reclaim as many freed tx buffers as we can. - * (called in wavelan_interrupt()). - * Note : the spinlock is already grabbed for us. - */ -static int wv_complete(struct net_device * dev, unsigned long ioaddr, net_local * lp) -{ - int nreaped = 0; - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wv_complete()\n", dev->name); -#endif - - /* Loop on all the transmit buffers */ - while (lp->tx_first_in_use != I82586NULL) { - unsigned short tx_status; - - /* Read the first transmit buffer */ - obram_read(ioaddr, acoff(lp->tx_first_in_use, ac_status), - (unsigned char *) &tx_status, - sizeof(tx_status)); - - /* If not completed -> exit */ - if ((tx_status & AC_SFLD_C) == 0) - break; - - /* Hack for reconfiguration */ - if (tx_status == 0xFFFF) - if (!wv_config_complete(dev, ioaddr, lp)) - break; /* Not completed */ - - /* We now remove this buffer */ - nreaped++; - --lp->tx_n_in_use; - -/* -if (lp->tx_n_in_use > 0) - printk("%c", "0123456789abcdefghijk"[lp->tx_n_in_use]); -*/ - - /* Was it the last one? */ - if (lp->tx_n_in_use <= 0) - lp->tx_first_in_use = I82586NULL; - else { - /* Next one in the chain */ - lp->tx_first_in_use += TXBLOCKZ; - if (lp->tx_first_in_use >= - OFFSET_CU + - NTXBLOCKS * TXBLOCKZ) lp->tx_first_in_use -= - NTXBLOCKS * TXBLOCKZ; - } - - /* Hack for reconfiguration */ - if (tx_status == 0xFFFF) - continue; - - /* Now, check status of the finished command */ - if (tx_status & AC_SFLD_OK) { - int ncollisions; - - dev->stats.tx_packets++; - ncollisions = tx_status & AC_SFLD_MAXCOL; - dev->stats.collisions += ncollisions; -#ifdef DEBUG_TX_INFO - if (ncollisions > 0) - printk(KERN_DEBUG - "%s: wv_complete(): tx completed after %d collisions.\n", - dev->name, ncollisions); -#endif - } else { - dev->stats.tx_errors++; - if (tx_status & AC_SFLD_S10) { - dev->stats.tx_carrier_errors++; -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG - "%s: wv_complete(): tx error: no CS.\n", - dev->name); -#endif - } - if (tx_status & AC_SFLD_S9) { - dev->stats.tx_carrier_errors++; -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG - "%s: wv_complete(): tx error: lost CTS.\n", - dev->name); -#endif - } - if (tx_status & AC_SFLD_S8) { - dev->stats.tx_fifo_errors++; -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG - "%s: wv_complete(): tx error: slow DMA.\n", - dev->name); -#endif - } - if (tx_status & AC_SFLD_S6) { - dev->stats.tx_heartbeat_errors++; -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG - "%s: wv_complete(): tx error: heart beat.\n", - dev->name); -#endif - } - if (tx_status & AC_SFLD_S5) { - dev->stats.tx_aborted_errors++; -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG - "%s: wv_complete(): tx error: too many collisions.\n", - dev->name); -#endif - } - } - -#ifdef DEBUG_TX_INFO - printk(KERN_DEBUG - "%s: wv_complete(): tx completed, tx_status 0x%04x\n", - dev->name, tx_status); -#endif - } - -#ifdef DEBUG_INTERRUPT_INFO - if (nreaped > 1) - printk(KERN_DEBUG "%s: wv_complete(): reaped %d\n", - dev->name, nreaped); -#endif - - /* - * Inform upper layers. - */ - if (lp->tx_n_in_use < NTXBLOCKS - 1) { - netif_wake_queue(dev); - } -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wv_complete()\n", dev->name); -#endif - return nreaped; -} - -/*------------------------------------------------------------------*/ -/* - * Reconfigure the i82586, or at least ask for it. - * Because wv_82586_config uses a transmission buffer, we must do it - * when we are sure that there is one left, so we do it now - * or in wavelan_packet_xmit() (I can't find any better place, - * wavelan_interrupt is not an option), so you may experience - * delays sometimes. - */ -static void wv_82586_reconfig(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - - /* Arm the flag, will be cleard in wv_82586_config() */ - lp->reconfig_82586 = 1; - - /* Check if we can do it now ! */ - if((netif_running(dev)) && !(netif_queue_stopped(dev))) { - spin_lock_irqsave(&lp->spinlock, flags); - /* May fail */ - wv_82586_config(dev); - spin_unlock_irqrestore(&lp->spinlock, flags); - } - else { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG - "%s: wv_82586_reconfig(): delayed (state = %lX)\n", - dev->name, dev->state); -#endif - } -} - -/********************* DEBUG & INFO SUBROUTINES *********************/ -/* - * This routine is used in the code to show information for debugging. - * Most of the time, it dumps the contents of hardware structures. - */ - -#ifdef DEBUG_PSA_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted contents of the Parameter Storage Area. - */ -static void wv_psa_show(psa_t * p) -{ - printk(KERN_DEBUG "##### WaveLAN PSA contents: #####\n"); - printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n", - p->psa_io_base_addr_1, - p->psa_io_base_addr_2, - p->psa_io_base_addr_3, p->psa_io_base_addr_4); - printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n", - p->psa_rem_boot_addr_1, - p->psa_rem_boot_addr_2, p->psa_rem_boot_addr_3); - printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params); - printk("psa_int_req_no: %d\n", p->psa_int_req_no); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_unused0[]: %pM\n", p->psa_unused0); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "psa_univ_mac_addr[]: %pM\n", p->psa_univ_mac_addr); - printk(KERN_DEBUG "psa_local_mac_addr[]: %pM\n", p->psa_local_mac_addr); - printk(KERN_DEBUG "psa_univ_local_sel: %d, ", - p->psa_univ_local_sel); - printk("psa_comp_number: %d, ", p->psa_comp_number); - printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set); - printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ", - p->psa_feature_select); - printk("psa_subband/decay_update_prm: %d\n", p->psa_subband); - printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr); - printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay); - printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], - p->psa_nwid[1]); - printk("psa_nwid_select: %d\n", p->psa_nwid_select); - printk(KERN_DEBUG "psa_encryption_select: %d, ", - p->psa_encryption_select); - printk - ("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - p->psa_encryption_key[0], p->psa_encryption_key[1], - p->psa_encryption_key[2], p->psa_encryption_key[3], - p->psa_encryption_key[4], p->psa_encryption_key[5], - p->psa_encryption_key[6], p->psa_encryption_key[7]); - printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width); - printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ", - p->psa_call_code[0]); - printk - ("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - p->psa_call_code[0], p->psa_call_code[1], p->psa_call_code[2], - p->psa_call_code[3], p->psa_call_code[4], p->psa_call_code[5], - p->psa_call_code[6], p->psa_call_code[7]); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X\n", - p->psa_reserved[0], - p->psa_reserved[1]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); - printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); - printk("psa_crc_status: 0x%02x\n", p->psa_crc_status); -} /* wv_psa_show */ -#endif /* DEBUG_PSA_SHOW */ - -#ifdef DEBUG_MMC_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the Modem Management Controller. - * This function needs to be completed. - */ -static void wv_mmc_show(struct net_device * dev) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); - mmr_t m; - - /* Basic check */ - if (hasr_read(ioaddr) & HASR_NO_CLK) { - printk(KERN_WARNING - "%s: wv_mmc_show: modem not connected\n", - dev->name); - return; - } - - /* Read the mmc */ - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); - mmc_read(ioaddr, 0, (u8 *) & m, sizeof(m)); - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); - - /* Don't forget to update statistics */ - lp->wstats.discard.nwid += - (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; - - printk(KERN_DEBUG "##### WaveLAN modem status registers: #####\n"); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG - "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - m.mmr_unused0[0], m.mmr_unused0[1], m.mmr_unused0[2], - m.mmr_unused0[3], m.mmr_unused0[4], m.mmr_unused0[5], - m.mmr_unused0[6], m.mmr_unused0[7]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n", - m.mmr_des_avail, m.mmr_des_status); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n", - m.mmr_unused1[0], - m.mmr_unused1[1], - m.mmr_unused1[2], m.mmr_unused1[3], m.mmr_unused1[4]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n", - m.mmr_dce_status, - (m. - mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? - "energy detected," : "", - (m. - mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? - "loop test indicated," : "", - (m. - mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? - "transmitter on," : "", - (m. - mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? - "jabber timer expired," : ""); - printk(KERN_DEBUG "Dsp ID: %02X\n", m.mmr_dsp_id); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n", - m.mmr_unused2[0], m.mmr_unused2[1]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n", - (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l, - (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); - printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n", - m.mmr_thr_pre_set & MMR_THR_PRE_SET, - (m. - mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : - "below"); - printk(KERN_DEBUG "signal_lvl: %d [%s], ", - m.mmr_signal_lvl & MMR_SIGNAL_LVL, - (m. - mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : - "no new msg"); - printk("silence_lvl: %d [%s], ", - m.mmr_silence_lvl & MMR_SILENCE_LVL, - (m. - mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : - "no new update"); - printk("sgnl_qual: 0x%x [%s]\n", m.mmr_sgnl_qual & MMR_SGNL_QUAL, - (m. - mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : - "Antenna 0"); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l); -#endif /* DEBUG_SHOW_UNUSED */ -} /* wv_mmc_show */ -#endif /* DEBUG_MMC_SHOW */ - -#ifdef DEBUG_I82586_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the last block of the i82586 memory. - */ -static void wv_scb_show(unsigned long ioaddr) -{ - scb_t scb; - - obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, - sizeof(scb)); - - printk(KERN_DEBUG "##### WaveLAN system control block: #####\n"); - - printk(KERN_DEBUG "status: "); - printk("stat 0x%x[%s%s%s%s] ", - (scb. - scb_status & (SCB_ST_CX | SCB_ST_FR | SCB_ST_CNA | - SCB_ST_RNR)) >> 12, - (scb. - scb_status & SCB_ST_CX) ? "command completion interrupt," : - "", (scb.scb_status & SCB_ST_FR) ? "frame received," : "", - (scb. - scb_status & SCB_ST_CNA) ? "command unit not active," : "", - (scb. - scb_status & SCB_ST_RNR) ? "receiving unit not ready," : - ""); - printk("cus 0x%x[%s%s%s] ", (scb.scb_status & SCB_ST_CUS) >> 8, - ((scb.scb_status & SCB_ST_CUS) == - SCB_ST_CUS_IDLE) ? "idle" : "", - ((scb.scb_status & SCB_ST_CUS) == - SCB_ST_CUS_SUSP) ? "suspended" : "", - ((scb.scb_status & SCB_ST_CUS) == - SCB_ST_CUS_ACTV) ? "active" : ""); - printk("rus 0x%x[%s%s%s%s]\n", (scb.scb_status & SCB_ST_RUS) >> 4, - ((scb.scb_status & SCB_ST_RUS) == - SCB_ST_RUS_IDLE) ? "idle" : "", - ((scb.scb_status & SCB_ST_RUS) == - SCB_ST_RUS_SUSP) ? "suspended" : "", - ((scb.scb_status & SCB_ST_RUS) == - SCB_ST_RUS_NRES) ? "no resources" : "", - ((scb.scb_status & SCB_ST_RUS) == - SCB_ST_RUS_RDY) ? "ready" : ""); - - printk(KERN_DEBUG "command: "); - printk("ack 0x%x[%s%s%s%s] ", - (scb. - scb_command & (SCB_CMD_ACK_CX | SCB_CMD_ACK_FR | - SCB_CMD_ACK_CNA | SCB_CMD_ACK_RNR)) >> 12, - (scb. - scb_command & SCB_CMD_ACK_CX) ? "ack cmd completion," : "", - (scb. - scb_command & SCB_CMD_ACK_FR) ? "ack frame received," : "", - (scb. - scb_command & SCB_CMD_ACK_CNA) ? "ack CU not active," : "", - (scb. - scb_command & SCB_CMD_ACK_RNR) ? "ack RU not ready," : ""); - printk("cuc 0x%x[%s%s%s%s%s] ", - (scb.scb_command & SCB_CMD_CUC) >> 8, - ((scb.scb_command & SCB_CMD_CUC) == - SCB_CMD_CUC_NOP) ? "nop" : "", - ((scb.scb_command & SCB_CMD_CUC) == - SCB_CMD_CUC_GO) ? "start cbl_offset" : "", - ((scb.scb_command & SCB_CMD_CUC) == - SCB_CMD_CUC_RES) ? "resume execution" : "", - ((scb.scb_command & SCB_CMD_CUC) == - SCB_CMD_CUC_SUS) ? "suspend execution" : "", - ((scb.scb_command & SCB_CMD_CUC) == - SCB_CMD_CUC_ABT) ? "abort execution" : ""); - printk("ruc 0x%x[%s%s%s%s%s]\n", - (scb.scb_command & SCB_CMD_RUC) >> 4, - ((scb.scb_command & SCB_CMD_RUC) == - SCB_CMD_RUC_NOP) ? "nop" : "", - ((scb.scb_command & SCB_CMD_RUC) == - SCB_CMD_RUC_GO) ? "start rfa_offset" : "", - ((scb.scb_command & SCB_CMD_RUC) == - SCB_CMD_RUC_RES) ? "resume reception" : "", - ((scb.scb_command & SCB_CMD_RUC) == - SCB_CMD_RUC_SUS) ? "suspend reception" : "", - ((scb.scb_command & SCB_CMD_RUC) == - SCB_CMD_RUC_ABT) ? "abort reception" : ""); - - printk(KERN_DEBUG "cbl_offset 0x%x ", scb.scb_cbl_offset); - printk("rfa_offset 0x%x\n", scb.scb_rfa_offset); - - printk(KERN_DEBUG "crcerrs %d ", scb.scb_crcerrs); - printk("alnerrs %d ", scb.scb_alnerrs); - printk("rscerrs %d ", scb.scb_rscerrs); - printk("ovrnerrs %d\n", scb.scb_ovrnerrs); -} - -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the i82586's receive unit. - */ -static void wv_ru_show(struct net_device * dev) -{ - printk(KERN_DEBUG - "##### WaveLAN i82586 receiver unit status: #####\n"); - printk(KERN_DEBUG "ru:"); - /* - * Not implemented yet - */ - printk("\n"); -} /* wv_ru_show */ - -/*------------------------------------------------------------------*/ -/* - * Display info about one control block of the i82586 memory. - */ -static void wv_cu_show_one(struct net_device * dev, net_local * lp, int i, u16 p) -{ - unsigned long ioaddr; - ac_tx_t actx; - - ioaddr = dev->base_addr; - - printk("%d: 0x%x:", i, p); - - obram_read(ioaddr, p, (unsigned char *) &actx, sizeof(actx)); - printk(" status=0x%x,", actx.tx_h.ac_status); - printk(" command=0x%x,", actx.tx_h.ac_command); - - /* - { - tbd_t tbd; - - obram_read(ioaddr, actx.tx_tbd_offset, (unsigned char *)&tbd, sizeof(tbd)); - printk(" tbd_status=0x%x,", tbd.tbd_status); - } - */ - - printk("|"); -} - -/*------------------------------------------------------------------*/ -/* - * Print status of the command unit of the i82586. - */ -static void wv_cu_show(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned int i; - u16 p; - - printk(KERN_DEBUG - "##### WaveLAN i82586 command unit status: #####\n"); - - printk(KERN_DEBUG); - for (i = 0, p = lp->tx_first_in_use; i < NTXBLOCKS; i++) { - wv_cu_show_one(dev, lp, i, p); - - p += TXBLOCKZ; - if (p >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - p -= NTXBLOCKS * TXBLOCKZ; - } - printk("\n"); -} -#endif /* DEBUG_I82586_SHOW */ - -#ifdef DEBUG_DEVICE_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the WaveLAN PCMCIA device driver. - */ -static void wv_dev_show(struct net_device * dev) -{ - printk(KERN_DEBUG "dev:"); - printk(" state=%lX,", dev->state); - printk(" trans_start=%ld,", dev->trans_start); - printk(" flags=0x%x,", dev->flags); - printk("\n"); -} /* wv_dev_show */ - -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the WaveLAN PCMCIA device driver's - * private information. - */ -static void wv_local_show(struct net_device * dev) -{ - net_local *lp; - - lp = netdev_priv(dev); - - printk(KERN_DEBUG "local:"); - printk(" tx_n_in_use=%d,", lp->tx_n_in_use); - printk(" hacr=0x%x,", lp->hacr); - printk(" rx_head=0x%x,", lp->rx_head); - printk(" rx_last=0x%x,", lp->rx_last); - printk(" tx_first_free=0x%x,", lp->tx_first_free); - printk(" tx_first_in_use=0x%x,", lp->tx_first_in_use); - printk("\n"); -} /* wv_local_show */ -#endif /* DEBUG_DEVICE_SHOW */ - -#if defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) -/*------------------------------------------------------------------*/ -/* - * Dump packet header (and content if necessary) on the screen - */ -static inline void wv_packet_info(u8 * p, /* Packet to dump */ - int length, /* Length of the packet */ - char *msg1, /* Name of the device */ - char *msg2) -{ /* Name of the function */ - int i; - int maxi; - - printk(KERN_DEBUG - "%s: %s(): dest %pM, length %d\n", - msg1, msg2, p, length); - printk(KERN_DEBUG - "%s: %s(): src %pM, type 0x%02X%02X\n", - msg1, msg2, &p[6], p[12], p[13]); - -#ifdef DEBUG_PACKET_DUMP - - printk(KERN_DEBUG "data=\""); - - if ((maxi = length) > DEBUG_PACKET_DUMP) - maxi = DEBUG_PACKET_DUMP; - for (i = 14; i < maxi; i++) - if (p[i] >= ' ' && p[i] <= '~') - printk(" %c", p[i]); - else - printk("%02X", p[i]); - if (maxi < length) - printk(".."); - printk("\"\n"); - printk(KERN_DEBUG "\n"); -#endif /* DEBUG_PACKET_DUMP */ -} -#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */ - -/*------------------------------------------------------------------*/ -/* - * This is the information which is displayed by the driver at startup. - * There are lots of flags for configuring it to your liking. - */ -static void wv_init_info(struct net_device * dev) -{ - short ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - - /* Read the parameter storage area */ - psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); - -#ifdef DEBUG_PSA_SHOW - wv_psa_show(&psa); -#endif -#ifdef DEBUG_MMC_SHOW - wv_mmc_show(dev); -#endif -#ifdef DEBUG_I82586_SHOW - wv_cu_show(dev); -#endif - -#ifdef DEBUG_BASIC_SHOW - /* Now, let's go for the basic stuff. */ - printk(KERN_NOTICE "%s: WaveLAN at %#x, %pM, IRQ %d", - dev->name, ioaddr, dev->dev_addr, dev->irq); - - /* Print current network ID. */ - if (psa.psa_nwid_select) - printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], - psa.psa_nwid[1]); - else - printk(", nwid off"); - - /* If 2.00 card */ - if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { - unsigned short freq; - - /* Ask the EEPROM to read the frequency from the first area. */ - fee_read(ioaddr, 0x00, &freq, 1); - - /* Print frequency */ - printk(", 2.00, %ld", (freq >> 6) + 2400L); - - /* Hack! */ - if (freq & 0x20) - printk(".5"); - } else { - printk(", PC"); - switch (psa.psa_comp_number) { - case PSA_COMP_PC_AT_915: - case PSA_COMP_PC_AT_2400: - printk("-AT"); - break; - case PSA_COMP_PC_MC_915: - case PSA_COMP_PC_MC_2400: - printk("-MC"); - break; - case PSA_COMP_PCMCIA_915: - printk("MCIA"); - break; - default: - printk("?"); - } - printk(", "); - switch (psa.psa_subband) { - case PSA_SUBBAND_915: - printk("915"); - break; - case PSA_SUBBAND_2425: - printk("2425"); - break; - case PSA_SUBBAND_2460: - printk("2460"); - break; - case PSA_SUBBAND_2484: - printk("2484"); - break; - case PSA_SUBBAND_2430_5: - printk("2430.5"); - break; - default: - printk("?"); - } - } - - printk(" MHz\n"); -#endif /* DEBUG_BASIC_SHOW */ - -#ifdef DEBUG_VERSION_SHOW - /* Print version information */ - printk(KERN_NOTICE "%s", version); -#endif -} /* wv_init_info */ - -/********************* IOCTL, STATS & RECONFIG *********************/ -/* - * We found here routines that are called by Linux on different - * occasions after the configuration and not for transmitting data - * These may be called when the user use ifconfig, /proc/net/dev - * or wireless extensions - */ - - -/*------------------------------------------------------------------*/ -/* - * Set or clear the multicast filter for this adaptor. - * num_addrs == -1 Promiscuous mode, receive all packets - * num_addrs == 0 Normal mode, clear multicast list - * num_addrs > 0 Multicast mode, receive normal and MC packets, - * and do best-effort filtering. - */ -static void wavelan_set_multicast_list(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", - dev->name); -#endif - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG - "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n", - dev->name, dev->flags, dev->mc_count); -#endif - - /* Are we asking for promiscuous mode, - * or all multicast addresses (we don't have that!) - * or too many multicast addresses for the hardware filter? */ - if ((dev->flags & IFF_PROMISC) || - (dev->flags & IFF_ALLMULTI) || - (dev->mc_count > I82586_MAX_MULTICAST_ADDRESSES)) { - /* - * Enable promiscuous mode: receive all packets. - */ - if (!lp->promiscuous) { - lp->promiscuous = 1; - lp->mc_count = 0; - - wv_82586_reconfig(dev); - } - } else - /* Are there multicast addresses to send? */ - if (dev->mc_list != (struct dev_mc_list *) NULL) { - /* - * Disable promiscuous mode, but receive all packets - * in multicast list - */ -#ifdef MULTICAST_AVOID - if (lp->promiscuous || (dev->mc_count != lp->mc_count)) -#endif - { - lp->promiscuous = 0; - lp->mc_count = dev->mc_count; - - wv_82586_reconfig(dev); - } - } else { - /* - * Switch to normal mode: disable promiscuous mode and - * clear the multicast list. - */ - if (lp->promiscuous || lp->mc_count == 0) { - lp->promiscuous = 0; - lp->mc_count = 0; - - wv_82586_reconfig(dev); - } - } -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", - dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * This function doesn't exist. - * (Note : it was a nice way to test the reconfigure stuff...) - */ -#ifdef SET_MAC_ADDRESS -static int wavelan_set_mac_address(struct net_device * dev, void *addr) -{ - struct sockaddr *mac = addr; - - /* Copy the address. */ - memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE); - - /* Reconfigure the beast. */ - wv_82586_reconfig(dev); - - return 0; -} -#endif /* SET_MAC_ADDRESS */ - - -/*------------------------------------------------------------------*/ -/* - * Frequency setting (for hardware capable of it) - * It's a bit complicated and you don't really want to look into it. - * (called in wavelan_ioctl) - */ -static int wv_set_frequency(unsigned long ioaddr, /* I/O port of the card */ - iw_freq * frequency) -{ - const int BAND_NUM = 10; /* Number of bands */ - long freq = 0L; /* offset to 2.4 GHz in .5 MHz */ -#ifdef DEBUG_IOCTL_INFO - int i; -#endif - - /* Setting by frequency */ - /* Theoretically, you may set any frequency between - * the two limits with a 0.5 MHz precision. In practice, - * I don't want you to have trouble with local regulations. - */ - if ((frequency->e == 1) && - (frequency->m >= (int) 2.412e8) - && (frequency->m <= (int) 2.487e8)) { - freq = ((frequency->m / 10000) - 24000L) / 5; - } - - /* Setting by channel (same as wfreqsel) */ - /* Warning: each channel is 22 MHz wide, so some of the channels - * will interfere. */ - if ((frequency->e == 0) && (frequency->m < BAND_NUM)) { - /* Get frequency offset. */ - freq = channel_bands[frequency->m] >> 1; - } - - /* Verify that the frequency is allowed. */ - if (freq != 0L) { - u16 table[10]; /* Authorized frequency table */ - - /* Read the frequency table. */ - fee_read(ioaddr, 0x71, table, 10); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Frequency table: "); - for (i = 0; i < 10; i++) { - printk(" %04X", table[i]); - } - printk("\n"); -#endif - - /* Look in the table to see whether the frequency is allowed. */ - if (!(table[9 - ((freq - 24) / 16)] & - (1 << ((freq - 24) % 16)))) return -EINVAL; /* not allowed */ - } else - return -EINVAL; - - /* if we get a usable frequency */ - if (freq != 0L) { - unsigned short area[16]; - unsigned short dac[2]; - unsigned short area_verify[16]; - unsigned short dac_verify[2]; - /* Corresponding gain (in the power adjust value table) - * See AT&T WaveLAN Data Manual, REF 407-024689/E, page 3-8 - * and WCIN062D.DOC, page 6.2.9. */ - unsigned short power_limit[] = { 40, 80, 120, 160, 0 }; - int power_band = 0; /* Selected band */ - unsigned short power_adjust; /* Correct value */ - - /* Search for the gain. */ - power_band = 0; - while ((freq > power_limit[power_band]) && - (power_limit[++power_band] != 0)); - - /* Read the first area. */ - fee_read(ioaddr, 0x00, area, 16); - - /* Read the DAC. */ - fee_read(ioaddr, 0x60, dac, 2); - - /* Read the new power adjust value. */ - fee_read(ioaddr, 0x6B - (power_band >> 1), &power_adjust, - 1); - if (power_band & 0x1) - power_adjust >>= 8; - else - power_adjust &= 0xFF; - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); - for (i = 0; i < 16; i++) { - printk(" %04X", area[i]); - } - printk("\n"); - - printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", - dac[0], dac[1]); -#endif - - /* Frequency offset (for info only) */ - area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F); - - /* Receiver Principle main divider coefficient */ - area[3] = (freq >> 1) + 2400L - 352L; - area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - - /* Transmitter Main divider coefficient */ - area[13] = (freq >> 1) + 2400L; - area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - - /* Other parts of the area are flags, bit streams or unused. */ - - /* Set the value in the DAC. */ - dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80); - dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF); - - /* Write the first area. */ - fee_write(ioaddr, 0x00, area, 16); - - /* Write the DAC. */ - fee_write(ioaddr, 0x60, dac, 2); - - /* We now should verify here that the writing of the EEPROM went OK. */ - - /* Reread the first area. */ - fee_read(ioaddr, 0x00, area_verify, 16); - - /* Reread the DAC. */ - fee_read(ioaddr, 0x60, dac_verify, 2); - - /* Compare. */ - if (memcmp(area, area_verify, 16 * 2) || - memcmp(dac, dac_verify, 2 * 2)) { -#ifdef DEBUG_IOCTL_ERROR - printk(KERN_INFO - "WaveLAN: wv_set_frequency: unable to write new frequency to EEPROM(?).\n"); -#endif - return -EOPNOTSUPP; - } - - /* We must download the frequency parameters to the - * synthesizers (from the EEPROM - area 1) - * Note: as the EEPROM is automatically decremented, we set the end - * if the area... */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x0F); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); - - /* Wait until the download is finished. */ - fee_wait(ioaddr, 100, 100); - - /* We must now download the power adjust value (gain) to - * the synthesizers (from the EEPROM - area 7 - DAC). */ - mmc_out(ioaddr, mmwoff(0, mmw_fee_addr), 0x61); - mmc_out(ioaddr, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); - - /* Wait for the download to finish. */ - fee_wait(ioaddr, 100, 100); - -#ifdef DEBUG_IOCTL_INFO - /* Verification of what we have done */ - - printk(KERN_DEBUG "WaveLAN EEPROM Area 1: "); - for (i = 0; i < 16; i++) { - printk(" %04X", area_verify[i]); - } - printk("\n"); - - printk(KERN_DEBUG "WaveLAN EEPROM DAC: %04X %04X\n", - dac_verify[0], dac_verify[1]); -#endif - - return 0; - } else - return -EINVAL; /* Bah, never get there... */ -} - -/*------------------------------------------------------------------*/ -/* - * Give the list of available frequencies. - */ -static int wv_frequency_list(unsigned long ioaddr, /* I/O port of the card */ - iw_freq * list, /* List of frequencies to fill */ - int max) -{ /* Maximum number of frequencies */ - u16 table[10]; /* Authorized frequency table */ - long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */ - int i; /* index in the table */ - int c = 0; /* Channel number */ - - /* Read the frequency table. */ - fee_read(ioaddr, 0x71 /* frequency table */ , table, 10); - - /* Check all frequencies. */ - i = 0; - for (freq = 0; freq < 150; freq++) - /* Look in the table if the frequency is allowed */ - if (table[9 - (freq / 16)] & (1 << (freq % 16))) { - /* Compute approximate channel number */ - while ((c < ARRAY_SIZE(channel_bands)) && - (((channel_bands[c] >> 1) - 24) < freq)) - c++; - list[i].i = c; /* Set the list index */ - - /* put in the list */ - list[i].m = (((freq + 24) * 5) + 24000L) * 10000; - list[i++].e = 1; - - /* Check number. */ - if (i >= max) - return (i); - } - - return (i); -} - -#ifdef IW_WIRELESS_SPY -/*------------------------------------------------------------------*/ -/* - * Gather wireless spy statistics: for each packet, compare the source - * address with our list, and if they match, get the statistics. - * Sorry, but this function really needs the wireless extensions. - */ -static inline void wl_spy_gather(struct net_device * dev, - u8 * mac, /* MAC address */ - u8 * stats) /* Statistics to gather */ -{ - struct iw_quality wstats; - - wstats.qual = stats[2] & MMR_SGNL_QUAL; - wstats.level = stats[0] & MMR_SIGNAL_LVL; - wstats.noise = stats[1] & MMR_SILENCE_LVL; - wstats.updated = 0x7; - - /* Update spy records */ - wireless_spy_update(dev, mac, &wstats); -} -#endif /* IW_WIRELESS_SPY */ - -#ifdef HISTOGRAM -/*------------------------------------------------------------------*/ -/* - * This function calculates a histogram of the signal level. - * As the noise is quite constant, it's like doing it on the SNR. - * We have defined a set of interval (lp->his_range), and each time - * the level goes in that interval, we increment the count (lp->his_sum). - * With this histogram you may detect if one WaveLAN is really weak, - * or you may also calculate the mean and standard deviation of the level. - */ -static inline void wl_his_gather(struct net_device * dev, u8 * stats) -{ /* Statistics to gather */ - net_local *lp = netdev_priv(dev); - u8 level = stats[0] & MMR_SIGNAL_LVL; - int i; - - /* Find the correct interval. */ - i = 0; - while ((i < (lp->his_number - 1)) - && (level >= lp->his_range[i++])); - - /* Increment interval counter. */ - (lp->his_sum[i])++; -} -#endif /* HISTOGRAM */ - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get protocol name - */ -static int wavelan_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - strcpy(wrqu->name, "WaveLAN"); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set NWID - */ -static int wavelan_set_nwid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - mm_t m; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Set NWID in WaveLAN. */ - if (!wrqu->nwid.disabled) { - /* Set NWID in psa */ - psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8; - psa.psa_nwid[1] = wrqu->nwid.value & 0xFF; - psa.psa_nwid_select = 0x01; - psa_write(ioaddr, lp->hacr, - (char *) psa.psa_nwid - (char *) &psa, - (unsigned char *) psa.psa_nwid, 3); - - /* Set NWID in mmc. */ - m.w.mmw_netw_id_l = psa.psa_nwid[1]; - m.w.mmw_netw_id_h = psa.psa_nwid[0]; - mmc_write(ioaddr, - (char *) &m.w.mmw_netw_id_l - - (char *) &m, - (unsigned char *) &m.w.mmw_netw_id_l, 2); - mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), 0x00); - } else { - /* Disable NWID in the psa. */ - psa.psa_nwid_select = 0x00; - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_nwid_select - - (char *) &psa, - (unsigned char *) &psa.psa_nwid_select, - 1); - - /* Disable NWID in the mmc (no filtering). */ - mmc_out(ioaddr, mmwoff(0, mmw_loopt_sel), - MMW_LOOPT_SEL_DIS_NWID); - } - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get NWID - */ -static int wavelan_get_nwid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Read the NWID. */ - psa_read(ioaddr, lp->hacr, - (char *) psa.psa_nwid - (char *) &psa, - (unsigned char *) psa.psa_nwid, 3); - wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; - wrqu->nwid.disabled = !(psa.psa_nwid_select); - wrqu->nwid.fixed = 1; /* Superfluous */ - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set frequency - */ -static int wavelan_set_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - unsigned long flags; - int ret; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ - if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - ret = wv_set_frequency(ioaddr, &(wrqu->freq)); - else - ret = -EOPNOTSUPP; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get frequency - */ -static int wavelan_get_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). - * Does it work for everybody, especially old cards? */ - if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { - unsigned short freq; - - /* Ask the EEPROM to read the frequency from the first area. */ - fee_read(ioaddr, 0x00, &freq, 1); - wrqu->freq.m = ((freq >> 5) * 5 + 24000L) * 10000; - wrqu->freq.e = 1; - } else { - psa_read(ioaddr, lp->hacr, - (char *) &psa.psa_subband - (char *) &psa, - (unsigned char *) &psa.psa_subband, 1); - - if (psa.psa_subband <= 4) { - wrqu->freq.m = fixed_bands[psa.psa_subband]; - wrqu->freq.e = (psa.psa_subband != 0); - } else - ret = -EOPNOTSUPP; - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set level threshold - */ -static int wavelan_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Set the level threshold. */ - /* We should complain loudly if wrqu->sens.fixed = 0, because we - * can't set auto mode... */ - psa.psa_thr_pre_set = wrqu->sens.value & 0x3F; - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_thr_pre_set - (char *) &psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - mmc_out(ioaddr, mmwoff(0, mmw_thr_pre_set), - psa.psa_thr_pre_set); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get level threshold - */ -static int wavelan_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Read the level threshold. */ - psa_read(ioaddr, lp->hacr, - (char *) &psa.psa_thr_pre_set - (char *) &psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - wrqu->sens.value = psa.psa_thr_pre_set & 0x3F; - wrqu->sens.fixed = 1; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set encryption key - */ -static int wavelan_set_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - unsigned long flags; - psa_t psa; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check if capable of encryption */ - if (!mmc_encr(ioaddr)) { - ret = -EOPNOTSUPP; - } - - /* Check the size of the key */ - if((wrqu->encoding.length != 8) && (wrqu->encoding.length != 0)) { - ret = -EINVAL; - } - - if(!ret) { - /* Basic checking... */ - if (wrqu->encoding.length == 8) { - /* Copy the key in the driver */ - memcpy(psa.psa_encryption_key, extra, - wrqu->encoding.length); - psa.psa_encryption_select = 1; - - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_encryption_select - - (char *) &psa, - (unsigned char *) &psa. - psa_encryption_select, 8 + 1); - - mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), - MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE); - mmc_write(ioaddr, mmwoff(0, mmw_encr_key), - (unsigned char *) &psa. - psa_encryption_key, 8); - } - - /* disable encryption */ - if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { - psa.psa_encryption_select = 0; - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_encryption_select - - (char *) &psa, - (unsigned char *) &psa. - psa_encryption_select, 1); - - mmc_out(ioaddr, mmwoff(0, mmw_encr_enable), 0); - } - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get encryption key - */ -static int wavelan_get_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check if encryption is available */ - if (!mmc_encr(ioaddr)) { - ret = -EOPNOTSUPP; - } else { - /* Read the encryption key */ - psa_read(ioaddr, lp->hacr, - (char *) &psa.psa_encryption_select - - (char *) &psa, - (unsigned char *) &psa. - psa_encryption_select, 1 + 8); - - /* encryption is enabled ? */ - if (psa.psa_encryption_select) - wrqu->encoding.flags = IW_ENCODE_ENABLED; - else - wrqu->encoding.flags = IW_ENCODE_DISABLED; - wrqu->encoding.flags |= mmc_encr(ioaddr); - - /* Copy the key to the user buffer */ - wrqu->encoding.length = 8; - memcpy(extra, psa.psa_encryption_key, wrqu->encoding.length); - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get range info - */ -static int wavelan_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - struct iw_range *range = (struct iw_range *) extra; - unsigned long flags; - int ret = 0; - - /* Set the length (very important for backward compatibility) */ - wrqu->data.length = sizeof(struct iw_range); - - /* Set all the info we don't care or don't know about to zero */ - memset(range, 0, sizeof(struct iw_range)); - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 9; - - /* Set information in the range struct. */ - range->throughput = 1.6 * 1000 * 1000; /* don't argue on this ! */ - range->min_nwid = 0x0000; - range->max_nwid = 0xFFFF; - - range->sensitivity = 0x3F; - range->max_qual.qual = MMR_SGNL_QUAL; - range->max_qual.level = MMR_SIGNAL_LVL; - range->max_qual.noise = MMR_SILENCE_LVL; - range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */ - /* Need to get better values for those two */ - range->avg_qual.level = 30; - range->avg_qual.noise = 8; - - range->num_bitrates = 1; - range->bitrate[0] = 2000000; /* 2 Mb/s */ - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) | - IW_EVENT_CAPA_MASK(0x8B04)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ - if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { - range->num_channels = 10; - range->num_frequency = wv_frequency_list(ioaddr, range->freq, - IW_MAX_FREQUENCIES); - } else - range->num_channels = range->num_frequency = 0; - - /* Encryption supported ? */ - if (mmc_encr(ioaddr)) { - range->encoding_size[0] = 8; /* DES = 64 bits key */ - range->num_encoding_sizes = 1; - range->max_encoding_tokens = 1; /* Only one key possible */ - } else { - range->num_encoding_sizes = 0; - range->max_encoding_tokens = 0; - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : set quality threshold - */ -static int wavelan_set_qthr(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - psa.psa_quality_thr = *(extra) & 0x0F; - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_quality_thr - (char *) &psa, - (unsigned char *) &psa.psa_quality_thr, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); - mmc_out(ioaddr, mmwoff(0, mmw_quality_thr), - psa.psa_quality_thr); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get quality threshold - */ -static int wavelan_get_qthr(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); /* lp is not unused */ - psa_t psa; - unsigned long flags; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - psa_read(ioaddr, lp->hacr, - (char *) &psa.psa_quality_thr - (char *) &psa, - (unsigned char *) &psa.psa_quality_thr, 1); - *(extra) = psa.psa_quality_thr & 0x0F; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return 0; -} - -#ifdef HISTOGRAM -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : set histogram - */ -static int wavelan_set_histo(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); /* lp is not unused */ - - /* Check the number of intervals. */ - if (wrqu->data.length > 16) { - return(-E2BIG); - } - - /* Disable histo while we copy the addresses. - * As we don't disable interrupts, we need to do this */ - lp->his_number = 0; - - /* Are there ranges to copy? */ - if (wrqu->data.length > 0) { - /* Copy interval ranges to the driver */ - memcpy(lp->his_range, extra, wrqu->data.length); - - { - int i; - printk(KERN_DEBUG "Histo :"); - for(i = 0; i < wrqu->data.length; i++) - printk(" %d", lp->his_range[i]); - printk("\n"); - } - - /* Reset result structure. */ - memset(lp->his_sum, 0x00, sizeof(long) * 16); - } - - /* Now we can set the number of ranges */ - lp->his_number = wrqu->data.length; - - return(0); -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get histogram - */ -static int wavelan_get_histo(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); /* lp is not unused */ - - /* Set the number of intervals. */ - wrqu->data.length = lp->his_number; - - /* Give back the distribution statistics */ - if(lp->his_number > 0) - memcpy(extra, lp->his_sum, sizeof(long) * lp->his_number); - - return(0); -} -#endif /* HISTOGRAM */ - -/*------------------------------------------------------------------*/ -/* - * Structures to export the Wireless Handlers - */ - -static const iw_handler wavelan_handler[] = -{ - NULL, /* SIOCSIWNAME */ - wavelan_get_name, /* SIOCGIWNAME */ - wavelan_set_nwid, /* SIOCSIWNWID */ - wavelan_get_nwid, /* SIOCGIWNWID */ - wavelan_set_freq, /* SIOCSIWFREQ */ - wavelan_get_freq, /* SIOCGIWFREQ */ - NULL, /* SIOCSIWMODE */ - NULL, /* SIOCGIWMODE */ - wavelan_set_sens, /* SIOCSIWSENS */ - wavelan_get_sens, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - wavelan_get_range, /* SIOCGIWRANGE */ - NULL, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ - NULL, /* SIOCSIWAP */ - NULL, /* SIOCGIWAP */ - NULL, /* -- hole -- */ - NULL, /* SIOCGIWAPLIST */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWESSID */ - NULL, /* SIOCGIWESSID */ - NULL, /* SIOCSIWNICKN */ - NULL, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWRATE */ - NULL, /* SIOCGIWRATE */ - NULL, /* SIOCSIWRTS */ - NULL, /* SIOCGIWRTS */ - NULL, /* SIOCSIWFRAG */ - NULL, /* SIOCGIWFRAG */ - NULL, /* SIOCSIWTXPOW */ - NULL, /* SIOCGIWTXPOW */ - NULL, /* SIOCSIWRETRY */ - NULL, /* SIOCGIWRETRY */ - /* Bummer ! Why those are only at the end ??? */ - wavelan_set_encode, /* SIOCSIWENCODE */ - wavelan_get_encode, /* SIOCGIWENCODE */ -}; - -static const iw_handler wavelan_private_handler[] = -{ - wavelan_set_qthr, /* SIOCIWFIRSTPRIV */ - wavelan_get_qthr, /* SIOCIWFIRSTPRIV + 1 */ -#ifdef HISTOGRAM - wavelan_set_histo, /* SIOCIWFIRSTPRIV + 2 */ - wavelan_get_histo, /* SIOCIWFIRSTPRIV + 3 */ -#endif /* HISTOGRAM */ -}; - -static const struct iw_priv_args wavelan_private_args[] = { -/*{ cmd, set_args, get_args, name } */ - { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" }, - { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" }, - { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" }, - { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, -}; - -static const struct iw_handler_def wavelan_handler_def = -{ - .num_standard = ARRAY_SIZE(wavelan_handler), - .num_private = ARRAY_SIZE(wavelan_private_handler), - .num_private_args = ARRAY_SIZE(wavelan_private_args), - .standard = wavelan_handler, - .private = wavelan_private_handler, - .private_args = wavelan_private_args, - .get_wireless_stats = wavelan_get_wireless_stats, -}; - -/*------------------------------------------------------------------*/ -/* - * Get wireless statistics. - * Called by /proc/net/wireless - */ -static iw_stats *wavelan_get_wireless_stats(struct net_device * dev) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); - mmr_t m; - iw_stats *wstats; - unsigned long flags; - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", - dev->name); -#endif - - /* Check */ - if (lp == (net_local *) NULL) - return (iw_stats *) NULL; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - wstats = &lp->wstats; - - /* Get data from the mmc. */ - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); - - mmc_read(ioaddr, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1); - mmc_read(ioaddr, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, - 2); - mmc_read(ioaddr, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, - 4); - - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); - - /* Copy data to wireless stuff. */ - wstats->status = m.mmr_dce_status & MMR_DCE_STATUS; - wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL; - wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL; - wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL; - wstats->qual.updated = (((m. mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) - | ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) - | ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5)); - wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; - wstats->discard.code = 0L; - wstats->discard.misc = 0L; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", - dev->name); -#endif - return &lp->wstats; -} - -/************************* PACKET RECEPTION *************************/ -/* - * This part deals with receiving the packets. - * The interrupt handler gets an interrupt when a packet has been - * successfully received and calls this part. - */ - -/*------------------------------------------------------------------*/ -/* - * This routine does the actual copying of data (including the Ethernet - * header structure) from the WaveLAN card to an sk_buff chain that - * will be passed up to the network interface layer. NOTE: we - * currently don't handle trailer protocols (neither does the rest of - * the network interface), so if that is needed, it will (at least in - * part) be added here. The contents of the receive ring buffer are - * copied to a message chain that is then passed to the kernel. - * - * Note: if any errors occur, the packet is "dropped on the floor". - * (called by wv_packet_rcv()) - */ -static void -wv_packet_read(struct net_device * dev, u16 buf_off, int sksize) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - struct sk_buff *skb; - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n", - dev->name, buf_off, sksize); -#endif - - /* Allocate buffer for the data */ - if ((skb = dev_alloc_skb(sksize)) == (struct sk_buff *) NULL) { -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO - "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC).\n", - dev->name, sksize); -#endif - dev->stats.rx_dropped++; - return; - } - - /* Copy the packet to the buffer. */ - obram_read(ioaddr, buf_off, skb_put(skb, sksize), sksize); - skb->protocol = eth_type_trans(skb, dev); - -#ifdef DEBUG_RX_INFO - wv_packet_info(skb_mac_header(skb), sksize, dev->name, - "wv_packet_read"); -#endif /* DEBUG_RX_INFO */ - - /* Statistics-gathering and associated stuff. - * It seem a bit messy with all the define, but it's really - * simple... */ - if ( -#ifdef IW_WIRELESS_SPY /* defined in iw_handler.h */ - (lp->spy_data.spy_number > 0) || -#endif /* IW_WIRELESS_SPY */ -#ifdef HISTOGRAM - (lp->his_number > 0) || -#endif /* HISTOGRAM */ - 0) { - u8 stats[3]; /* signal level, noise level, signal quality */ - - /* Read signal level, silence level and signal quality bytes */ - /* Note: in the PCMCIA hardware, these are part of the frame. - * It seems that for the ISA hardware, it's nowhere to be - * found in the frame, so I'm obliged to do this (it has a - * side effect on /proc/net/wireless). - * Any ideas? - */ - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 1); - mmc_read(ioaddr, mmroff(0, mmr_signal_lvl), stats, 3); - mmc_out(ioaddr, mmwoff(0, mmw_freeze), 0); - -#ifdef DEBUG_RX_INFO - printk(KERN_DEBUG - "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n", - dev->name, stats[0] & 0x3F, stats[1] & 0x3F, - stats[2] & 0x0F); -#endif - - /* Spying stuff */ -#ifdef IW_WIRELESS_SPY - wl_spy_gather(dev, skb_mac_header(skb) + WAVELAN_ADDR_SIZE, - stats); -#endif /* IW_WIRELESS_SPY */ -#ifdef HISTOGRAM - wl_his_gather(dev, stats); -#endif /* HISTOGRAM */ - } - - /* - * Hand the packet to the network module. - */ - netif_rx(skb); - - /* Keep statistics up to date */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += sksize; - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * Transfer as many packets as we can - * from the device RAM. - * (called in wavelan_interrupt()). - * Note : the spinlock is already grabbed for us. - */ -static void wv_receive(struct net_device * dev) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); - fd_t fd; - rbd_t rbd; - int nreaped = 0; - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: ->wv_receive()\n", dev->name); -#endif - - /* Loop on each received packet. */ - for (;;) { - obram_read(ioaddr, lp->rx_head, (unsigned char *) &fd, - sizeof(fd)); - - /* Note about the status : - * It start up to be 0 (the value we set). Then, when the RU - * grab the buffer to prepare for reception, it sets the - * FD_STATUS_B flag. When the RU has finished receiving the - * frame, it clears FD_STATUS_B, set FD_STATUS_C to indicate - * completion and set the other flags to indicate the eventual - * errors. FD_STATUS_OK indicates that the reception was OK. - */ - - /* If the current frame is not complete, we have reached the end. */ - if ((fd.fd_status & FD_STATUS_C) != FD_STATUS_C) - break; /* This is how we exit the loop. */ - - nreaped++; - - /* Check whether frame was correctly received. */ - if ((fd.fd_status & FD_STATUS_OK) == FD_STATUS_OK) { - /* Does the frame contain a pointer to the data? Let's check. */ - if (fd.fd_rbd_offset != I82586NULL) { - /* Read the receive buffer descriptor */ - obram_read(ioaddr, fd.fd_rbd_offset, - (unsigned char *) &rbd, - sizeof(rbd)); - -#ifdef DEBUG_RX_ERROR - if ((rbd.rbd_status & RBD_STATUS_EOF) != - RBD_STATUS_EOF) printk(KERN_INFO - "%s: wv_receive(): missing EOF flag.\n", - dev->name); - - if ((rbd.rbd_status & RBD_STATUS_F) != - RBD_STATUS_F) printk(KERN_INFO - "%s: wv_receive(): missing F flag.\n", - dev->name); -#endif /* DEBUG_RX_ERROR */ - - /* Read the packet and transmit to Linux */ - wv_packet_read(dev, rbd.rbd_bufl, - rbd. - rbd_status & - RBD_STATUS_ACNT); - } -#ifdef DEBUG_RX_ERROR - else /* if frame has no data */ - printk(KERN_INFO - "%s: wv_receive(): frame has no data.\n", - dev->name); -#endif - } else { /* If reception was no successful */ - - dev->stats.rx_errors++; - -#ifdef DEBUG_RX_INFO - printk(KERN_DEBUG - "%s: wv_receive(): frame not received successfully (%X).\n", - dev->name, fd.fd_status); -#endif - -#ifdef DEBUG_RX_ERROR - if ((fd.fd_status & FD_STATUS_S6) != 0) - printk(KERN_INFO - "%s: wv_receive(): no EOF flag.\n", - dev->name); -#endif - - if ((fd.fd_status & FD_STATUS_S7) != 0) { - dev->stats.rx_length_errors++; -#ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG - "%s: wv_receive(): frame too short.\n", - dev->name); -#endif - } - - if ((fd.fd_status & FD_STATUS_S8) != 0) { - dev->stats.rx_over_errors++; -#ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG - "%s: wv_receive(): rx DMA overrun.\n", - dev->name); -#endif - } - - if ((fd.fd_status & FD_STATUS_S9) != 0) { - dev->stats.rx_fifo_errors++; -#ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG - "%s: wv_receive(): ran out of resources.\n", - dev->name); -#endif - } - - if ((fd.fd_status & FD_STATUS_S10) != 0) { - dev->stats.rx_frame_errors++; -#ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG - "%s: wv_receive(): alignment error.\n", - dev->name); -#endif - } - - if ((fd.fd_status & FD_STATUS_S11) != 0) { - dev->stats.rx_crc_errors++; -#ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG - "%s: wv_receive(): CRC error.\n", - dev->name); -#endif - } - } - - fd.fd_status = 0; - obram_write(ioaddr, fdoff(lp->rx_head, fd_status), - (unsigned char *) &fd.fd_status, - sizeof(fd.fd_status)); - - fd.fd_command = FD_COMMAND_EL; - obram_write(ioaddr, fdoff(lp->rx_head, fd_command), - (unsigned char *) &fd.fd_command, - sizeof(fd.fd_command)); - - fd.fd_command = 0; - obram_write(ioaddr, fdoff(lp->rx_last, fd_command), - (unsigned char *) &fd.fd_command, - sizeof(fd.fd_command)); - - lp->rx_last = lp->rx_head; - lp->rx_head = fd.fd_link_offset; - } /* for(;;) -> loop on all frames */ - -#ifdef DEBUG_RX_INFO - if (nreaped > 1) - printk(KERN_DEBUG "%s: wv_receive(): reaped %d\n", - dev->name, nreaped); -#endif -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: <-wv_receive()\n", dev->name); -#endif -} - -/*********************** PACKET TRANSMISSION ***********************/ -/* - * This part deals with sending packets through the WaveLAN. - * - */ - -/*------------------------------------------------------------------*/ -/* - * This routine fills in the appropriate registers and memory - * locations on the WaveLAN card and starts the card off on - * the transmit. - * - * The principle: - * Each block contains a transmit command, a NOP command, - * a transmit block descriptor and a buffer. - * The CU read the transmit block which point to the tbd, - * read the tbd and the content of the buffer. - * When it has finish with it, it goes to the next command - * which in our case is the NOP. The NOP points on itself, - * so the CU stop here. - * When we add the next block, we modify the previous nop - * to make it point on the new tx command. - * Simple, isn't it ? - * - * (called in wavelan_packet_xmit()) - */ -static int wv_packet_write(struct net_device * dev, void *buf, short length) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - unsigned short txblock; - unsigned short txpred; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short buf_addr; - ac_tx_t tx; - ac_nop_t nop; - tbd_t tbd; - int clen = length; - unsigned long flags; - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, - length); -#endif - - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check nothing bad has happened */ - if (lp->tx_n_in_use == (NTXBLOCKS - 1)) { -#ifdef DEBUG_TX_ERROR - printk(KERN_INFO "%s: wv_packet_write(): Tx queue full.\n", - dev->name); -#endif - spin_unlock_irqrestore(&lp->spinlock, flags); - return 1; - } - - /* Calculate addresses of next block and previous block. */ - txblock = lp->tx_first_free; - txpred = txblock - TXBLOCKZ; - if (txpred < OFFSET_CU) - txpred += NTXBLOCKS * TXBLOCKZ; - lp->tx_first_free += TXBLOCKZ; - if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; - - lp->tx_n_in_use++; - - /* Calculate addresses of the different parts of the block. */ - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - buf_addr = tbd_addr + sizeof(tbd); - - /* - * Transmit command - */ - tx.tx_h.ac_status = 0; - obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), - (unsigned char *) &tx.tx_h.ac_status, - sizeof(tx.tx_h.ac_status)); - - /* - * NOP command - */ - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *) &nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* - * Transmit buffer descriptor - */ - tbd.tbd_status = TBD_STATUS_EOF | (TBD_STATUS_ACNT & clen); - tbd.tbd_next_bd_offset = I82586NULL; - tbd.tbd_bufl = buf_addr; - tbd.tbd_bufh = 0; - obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, sizeof(tbd)); - - /* - * Data - */ - obram_write(ioaddr, buf_addr, buf, length); - - /* - * Overwrite the predecessor NOP link - * so that it points to this txblock. - */ - nop_addr = txpred + sizeof(tx); - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *) &nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = txblock; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* Make sure the watchdog will keep quiet for a while */ - dev->trans_start = jiffies; - - /* Keep stats up to date. */ - dev->stats.tx_bytes += length; - - if (lp->tx_first_in_use == I82586NULL) - lp->tx_first_in_use = txblock; - - if (lp->tx_n_in_use < NTXBLOCKS - 1) - netif_wake_queue(dev); - - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_TX_INFO - wv_packet_info((u8 *) buf, length, dev->name, - "wv_packet_write"); -#endif /* DEBUG_TX_INFO */ - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name); -#endif - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * This routine is called when we want to send a packet (NET3 callback) - * In this routine, we check if the harware is ready to accept - * the packet. We also prevent reentrance. Then we call the function - * to send the packet. - */ -static netdev_tx_t wavelan_packet_xmit(struct sk_buff *skb, - struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - char data[ETH_ZLEN]; - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, - (unsigned) skb); -#endif - - /* - * Block a timer-based transmit from overlapping. - * In other words, prevent reentering this routine. - */ - netif_stop_queue(dev); - - /* If somebody has asked to reconfigure the controller, - * we can do it now. - */ - if (lp->reconfig_82586) { - spin_lock_irqsave(&lp->spinlock, flags); - wv_82586_config(dev); - spin_unlock_irqrestore(&lp->spinlock, flags); - /* Check that we can continue */ - if (lp->tx_n_in_use == (NTXBLOCKS - 1)) - return NETDEV_TX_BUSY; - } - - /* Do we need some padding? */ - /* Note : on wireless the propagation time is in the order of 1us, - * and we don't have the Ethernet specific requirement of beeing - * able to detect collisions, therefore in theory we don't really - * need to pad. Jean II */ - if (skb->len < ETH_ZLEN) { - memset(data, 0, ETH_ZLEN); - skb_copy_from_linear_data(skb, data, skb->len); - /* Write packet on the card */ - if(wv_packet_write(dev, data, ETH_ZLEN)) - return NETDEV_TX_BUSY; /* We failed */ - } - else if(wv_packet_write(dev, skb->data, skb->len)) - return NETDEV_TX_BUSY; /* We failed */ - - - dev_kfree_skb(skb); - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); -#endif - return NETDEV_TX_OK; -} - -/*********************** HARDWARE CONFIGURATION ***********************/ -/* - * This part does the real job of starting and configuring the hardware. - */ - -/*--------------------------------------------------------------------*/ -/* - * Routine to initialize the Modem Management Controller. - * (called by wv_hw_reset()) - */ -static int wv_mmc_init(struct net_device * dev) -{ - unsigned long ioaddr = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - mmw_t m; - int configured; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name); -#endif - - /* Read the parameter storage area. */ - psa_read(ioaddr, lp->hacr, 0, (unsigned char *) &psa, sizeof(psa)); - -#ifdef USE_PSA_CONFIG - configured = psa.psa_conf_status & 1; -#else - configured = 0; -#endif - - /* Is the PSA is not configured */ - if (!configured) { - /* User will be able to configure NWID later (with iwconfig). */ - psa.psa_nwid[0] = 0; - psa.psa_nwid[1] = 0; - - /* no NWID checking since NWID is not set */ - psa.psa_nwid_select = 0; - - /* Disable encryption */ - psa.psa_encryption_select = 0; - - /* Set to standard values: - * 0x04 for AT, - * 0x01 for MCA, - * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document) - */ - if (psa.psa_comp_number & 1) - psa.psa_thr_pre_set = 0x01; - else - psa.psa_thr_pre_set = 0x04; - psa.psa_quality_thr = 0x03; - - /* It is configured */ - psa.psa_conf_status |= 1; - -#ifdef USE_PSA_CONFIG - /* Write the psa. */ - psa_write(ioaddr, lp->hacr, - (char *) psa.psa_nwid - (char *) &psa, - (unsigned char *) psa.psa_nwid, 4); - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_thr_pre_set - (char *) &psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_quality_thr - (char *) &psa, - (unsigned char *) &psa.psa_quality_thr, 1); - psa_write(ioaddr, lp->hacr, - (char *) &psa.psa_conf_status - (char *) &psa, - (unsigned char *) &psa.psa_conf_status, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, lp->hacr); -#endif - } - - /* Zero the mmc structure. */ - memset(&m, 0x00, sizeof(m)); - - /* Copy PSA info to the mmc. */ - m.mmw_netw_id_l = psa.psa_nwid[1]; - m.mmw_netw_id_h = psa.psa_nwid[0]; - - if (psa.psa_nwid_select & 1) - m.mmw_loopt_sel = 0x00; - else - m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID; - - memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, - sizeof(m.mmw_encr_key)); - - if (psa.psa_encryption_select) - m.mmw_encr_enable = - MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE; - else - m.mmw_encr_enable = 0; - - m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F; - m.mmw_quality_thr = psa.psa_quality_thr & 0x0F; - - /* - * Set default modem control parameters. - * See NCR document 407-0024326 Rev. A. - */ - m.mmw_jabber_enable = 0x01; - m.mmw_freeze = 0; - m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; - m.mmw_ifs = 0x20; - m.mmw_mod_delay = 0x04; - m.mmw_jam_time = 0x38; - - m.mmw_des_io_invert = 0; - m.mmw_decay_prm = 0; - m.mmw_decay_updat_prm = 0; - - /* Write all info to MMC. */ - mmc_write(ioaddr, 0, (u8 *) & m, sizeof(m)); - - /* The following code starts the modem of the 2.00 frequency - * selectable cards at power on. It's not strictly needed for the - * following boots. - * The original patch was by Joe Finney for the PCMCIA driver, but - * I've cleaned it up a bit and added documentation. - * Thanks to Loeke Brederveld from Lucent for the info. - */ - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * Does it work for everybody, especially old cards? */ - /* Note: WFREQSEL verifies that it is able to read a sensible - * frequency from EEPROM (address 0x00) and that MMR_FEE_STATUS_ID - * is 0xA (Xilinx version) or 0xB (Ariadne version). - * My test is more crude but does work. */ - if (!(mmc_in(ioaddr, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { - /* We must download the frequency parameters to the - * synthesizers (from the EEPROM - area 1) - * Note: as the EEPROM is automatically decremented, we set the end - * if the area... */ - m.mmw_fee_addr = 0x0F; - m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; - mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m, - (unsigned char *) &m.mmw_fee_ctrl, 2); - - /* Wait until the download is finished. */ - fee_wait(ioaddr, 100, 100); - -#ifdef DEBUG_CONFIG_INFO - /* The frequency was in the last word downloaded. */ - mmc_read(ioaddr, (char *) &m.mmw_fee_data_l - (char *) &m, - (unsigned char *) &m.mmw_fee_data_l, 2); - - /* Print some info for the user. */ - printk(KERN_DEBUG - "%s: WaveLAN 2.00 recognised (frequency select). Current frequency = %ld\n", - dev->name, - ((m. - mmw_fee_data_h << 4) | (m.mmw_fee_data_l >> 4)) * - 5 / 2 + 24000L); -#endif - - /* We must now download the power adjust value (gain) to - * the synthesizers (from the EEPROM - area 7 - DAC). */ - m.mmw_fee_addr = 0x61; - m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; - mmc_write(ioaddr, (char *) &m.mmw_fee_ctrl - (char *) &m, - (unsigned char *) &m.mmw_fee_ctrl, 2); - - /* Wait until the download is finished. */ - } - /* if 2.00 card */ -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Construct the fd and rbd structures. - * Start the receive unit. - * (called by wv_hw_reset()) - */ -static int wv_ru_start(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - u16 scb_cs; - fd_t fd; - rbd_t rbd; - u16 rx; - u16 rx_next; - int i; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name); -#endif - - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - if ((scb_cs & SCB_ST_RUS) == SCB_ST_RUS_RDY) - return 0; - - lp->rx_head = OFFSET_RU; - - for (i = 0, rx = lp->rx_head; i < NRXBLOCKS; i++, rx = rx_next) { - rx_next = - (i == NRXBLOCKS - 1) ? lp->rx_head : rx + RXBLOCKZ; - - fd.fd_status = 0; - fd.fd_command = (i == NRXBLOCKS - 1) ? FD_COMMAND_EL : 0; - fd.fd_link_offset = rx_next; - fd.fd_rbd_offset = rx + sizeof(fd); - obram_write(ioaddr, rx, (unsigned char *) &fd, sizeof(fd)); - - rbd.rbd_status = 0; - rbd.rbd_next_rbd_offset = I82586NULL; - rbd.rbd_bufl = rx + sizeof(fd) + sizeof(rbd); - rbd.rbd_bufh = 0; - rbd.rbd_el_size = RBD_EL | (RBD_SIZE & MAXDATAZ); - obram_write(ioaddr, rx + sizeof(fd), - (unsigned char *) &rbd, sizeof(rbd)); - - lp->rx_last = rx; - } - - obram_write(ioaddr, scboff(OFFSET_SCB, scb_rfa_offset), - (unsigned char *) &lp->rx_head, sizeof(lp->rx_head)); - - scb_cs = SCB_CMD_RUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(10); - } - - if (i <= 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wavelan_ru_start(): board not accepting command.\n", - dev->name); -#endif - return -1; - } -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Initialise the transmit blocks. - * Start the command unit executing the NOP - * self-loop of the first transmit block. - * - * Here we create the list of send buffers used to transmit packets - * between the PC and the command unit. For each buffer, we create a - * buffer descriptor (pointing on the buffer), a transmit command - * (pointing to the buffer descriptor) and a NOP command. - * The transmit command is linked to the NOP, and the NOP to itself. - * When we will have finished executing the transmit command, we will - * then loop on the NOP. By releasing the NOP link to a new command, - * we may send another buffer. - * - * (called by wv_hw_reset()) - */ -static int wv_cu_start(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - int i; - u16 txblock; - u16 first_nop; - u16 scb_cs; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_cu_start()\n", dev->name); -#endif - - lp->tx_first_free = OFFSET_CU; - lp->tx_first_in_use = I82586NULL; - - for (i = 0, txblock = OFFSET_CU; - i < NTXBLOCKS; i++, txblock += TXBLOCKZ) { - ac_tx_t tx; - ac_nop_t nop; - tbd_t tbd; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short buf_addr; - - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - buf_addr = tbd_addr + sizeof(tbd); - - tx.tx_h.ac_status = 0; - tx.tx_h.ac_command = acmd_transmit | AC_CFLD_I; - tx.tx_h.ac_link = nop_addr; - tx.tx_tbd_offset = tbd_addr; - obram_write(ioaddr, tx_addr, (unsigned char *) &tx, - sizeof(tx)); - - nop.nop_h.ac_status = 0; - nop.nop_h.ac_command = acmd_nop; - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, nop_addr, (unsigned char *) &nop, - sizeof(nop)); - - tbd.tbd_status = TBD_STATUS_EOF; - tbd.tbd_next_bd_offset = I82586NULL; - tbd.tbd_bufl = buf_addr; - tbd.tbd_bufh = 0; - obram_write(ioaddr, tbd_addr, (unsigned char *) &tbd, - sizeof(tbd)); - } - - first_nop = - OFFSET_CU + (NTXBLOCKS - 1) * TXBLOCKZ + sizeof(ac_tx_t); - obram_write(ioaddr, scboff(OFFSET_SCB, scb_cbl_offset), - (unsigned char *) &first_nop, sizeof(first_nop)); - - scb_cs = SCB_CMD_CUC_GO; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - - set_chan_attn(ioaddr, lp->hacr); - - for (i = 1000; i > 0; i--) { - obram_read(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cs, sizeof(scb_cs)); - if (scb_cs == 0) - break; - - udelay(10); - } - - if (i <= 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wavelan_cu_start(): board not accepting command.\n", - dev->name); -#endif - return -1; - } - - lp->tx_n_in_use = 0; - netif_start_queue(dev); -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_cu_start()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * This routine does a standard configuration of the WaveLAN - * controller (i82586). - * - * It initialises the scp, iscp and scb structure - * The first two are just pointers to the next. - * The last one is used for basic configuration and for basic - * communication (interrupt status). - * - * (called by wv_hw_reset()) - */ -static int wv_82586_start(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - scp_t scp; /* system configuration pointer */ - iscp_t iscp; /* intermediate scp */ - scb_t scb; /* system control block */ - ach_t cb; /* Action command header */ - u8 zeroes[512]; - int i; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82586_start()\n", dev->name); -#endif - - /* - * Clear the onboard RAM. - */ - memset(&zeroes[0], 0x00, sizeof(zeroes)); - for (i = 0; i < I82586_MEMZ; i += sizeof(zeroes)) - obram_write(ioaddr, i, &zeroes[0], sizeof(zeroes)); - - /* - * Construct the command unit structures: - * scp, iscp, scb, cb. - */ - memset(&scp, 0x00, sizeof(scp)); - scp.scp_sysbus = SCP_SY_16BBUS; - scp.scp_iscpl = OFFSET_ISCP; - obram_write(ioaddr, OFFSET_SCP, (unsigned char *) &scp, - sizeof(scp)); - - memset(&iscp, 0x00, sizeof(iscp)); - iscp.iscp_busy = 1; - iscp.iscp_offset = OFFSET_SCB; - obram_write(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, - sizeof(iscp)); - - /* Our first command is to reset the i82586. */ - memset(&scb, 0x00, sizeof(scb)); - scb.scb_command = SCB_CMD_RESET; - scb.scb_cbl_offset = OFFSET_CU; - scb.scb_rfa_offset = OFFSET_RU; - obram_write(ioaddr, OFFSET_SCB, (unsigned char *) &scb, - sizeof(scb)); - - set_chan_attn(ioaddr, lp->hacr); - - /* Wait for command to finish. */ - for (i = 1000; i > 0; i--) { - obram_read(ioaddr, OFFSET_ISCP, (unsigned char *) &iscp, - sizeof(iscp)); - - if (iscp.iscp_busy == (unsigned short) 0) - break; - - udelay(10); - } - - if (i <= 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wv_82586_start(): iscp_busy timeout.\n", - dev->name); -#endif - return -1; - } - - /* Check command completion. */ - for (i = 15; i > 0; i--) { - obram_read(ioaddr, OFFSET_SCB, (unsigned char *) &scb, - sizeof(scb)); - - if (scb.scb_status == (SCB_ST_CX | SCB_ST_CNA)) - break; - - udelay(10); - } - - if (i <= 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wv_82586_start(): status: expected 0x%02x, got 0x%02x.\n", - dev->name, SCB_ST_CX | SCB_ST_CNA, scb.scb_status); -#endif - return -1; - } - - wv_ack(dev); - - /* Set the action command header. */ - memset(&cb, 0x00, sizeof(cb)); - cb.ac_command = AC_CFLD_EL | (AC_CFLD_CMD & acmd_diagnose); - cb.ac_link = OFFSET_CU; - obram_write(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb)); - - if (wv_synchronous_cmd(dev, "diag()") == -1) - return -1; - - obram_read(ioaddr, OFFSET_CU, (unsigned char *) &cb, sizeof(cb)); - if (cb.ac_status & AC_SFLD_FAIL) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wv_82586_start(): i82586 Self Test failed.\n", - dev->name); -#endif - return -1; - } -#ifdef DEBUG_I82586_SHOW - wv_scb_show(ioaddr); -#endif - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82586_start()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * This routine does a standard configuration of the WaveLAN - * controller (i82586). - * - * This routine is a violent hack. We use the first free transmit block - * to make our configuration. In the buffer area, we create the three - * configuration commands (linked). We make the previous NOP point to - * the beginning of the buffer instead of the tx command. After, we go - * as usual to the NOP command. - * Note that only the last command (mc_set) will generate an interrupt. - * - * (called by wv_hw_reset(), wv_82586_reconfig(), wavelan_packet_xmit()) - */ -static void wv_82586_config(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - unsigned short txblock; - unsigned short txpred; - unsigned short tx_addr; - unsigned short nop_addr; - unsigned short tbd_addr; - unsigned short cfg_addr; - unsigned short ias_addr; - unsigned short mcs_addr; - ac_tx_t tx; - ac_nop_t nop; - ac_cfg_t cfg; /* Configure action */ - ac_ias_t ias; /* IA-setup action */ - ac_mcs_t mcs; /* Multicast setup */ - struct dev_mc_list *dmi; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82586_config()\n", dev->name); -#endif - - /* Check nothing bad has happened */ - if (lp->tx_n_in_use == (NTXBLOCKS - 1)) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO "%s: wv_82586_config(): Tx queue full.\n", - dev->name); -#endif - return; - } - - /* Calculate addresses of next block and previous block. */ - txblock = lp->tx_first_free; - txpred = txblock - TXBLOCKZ; - if (txpred < OFFSET_CU) - txpred += NTXBLOCKS * TXBLOCKZ; - lp->tx_first_free += TXBLOCKZ; - if (lp->tx_first_free >= OFFSET_CU + NTXBLOCKS * TXBLOCKZ) - lp->tx_first_free -= NTXBLOCKS * TXBLOCKZ; - - lp->tx_n_in_use++; - - /* Calculate addresses of the different parts of the block. */ - tx_addr = txblock; - nop_addr = tx_addr + sizeof(tx); - tbd_addr = nop_addr + sizeof(nop); - cfg_addr = tbd_addr + sizeof(tbd_t); /* beginning of the buffer */ - ias_addr = cfg_addr + sizeof(cfg); - mcs_addr = ias_addr + sizeof(ias); - - /* - * Transmit command - */ - tx.tx_h.ac_status = 0xFFFF; /* Fake completion value */ - obram_write(ioaddr, toff(ac_tx_t, tx_addr, tx_h.ac_status), - (unsigned char *) &tx.tx_h.ac_status, - sizeof(tx.tx_h.ac_status)); - - /* - * NOP command - */ - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *) &nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = nop_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* Create a configure action. */ - memset(&cfg, 0x00, sizeof(cfg)); - - /* - * For Linux we invert AC_CFG_ALOC() so as to conform - * to the way that net packets reach us from above. - * (See also ac_tx_t.) - * - * Updated from Wavelan Manual WCIN085B - */ - cfg.cfg_byte_cnt = - AC_CFG_BYTE_CNT(sizeof(ac_cfg_t) - sizeof(ach_t)); - cfg.cfg_fifolim = AC_CFG_FIFOLIM(4); - cfg.cfg_byte8 = AC_CFG_SAV_BF(1) | AC_CFG_SRDY(0); - cfg.cfg_byte9 = AC_CFG_ELPBCK(0) | - AC_CFG_ILPBCK(0) | - AC_CFG_PRELEN(AC_CFG_PLEN_2) | - AC_CFG_ALOC(1) | AC_CFG_ADDRLEN(WAVELAN_ADDR_SIZE); - cfg.cfg_byte10 = AC_CFG_BOFMET(1) | - AC_CFG_ACR(6) | AC_CFG_LINPRIO(0); - cfg.cfg_ifs = 0x20; - cfg.cfg_slotl = 0x0C; - cfg.cfg_byte13 = AC_CFG_RETRYNUM(15) | AC_CFG_SLTTMHI(0); - cfg.cfg_byte14 = AC_CFG_FLGPAD(0) | - AC_CFG_BTSTF(0) | - AC_CFG_CRC16(0) | - AC_CFG_NCRC(0) | - AC_CFG_TNCRS(1) | - AC_CFG_MANCH(0) | - AC_CFG_BCDIS(0) | AC_CFG_PRM(lp->promiscuous); - cfg.cfg_byte15 = AC_CFG_ICDS(0) | - AC_CFG_CDTF(0) | AC_CFG_ICSS(0) | AC_CFG_CSTF(0); -/* - cfg.cfg_min_frm_len = AC_CFG_MNFRM(64); -*/ - cfg.cfg_min_frm_len = AC_CFG_MNFRM(8); - - cfg.cfg_h.ac_command = (AC_CFLD_CMD & acmd_configure); - cfg.cfg_h.ac_link = ias_addr; - obram_write(ioaddr, cfg_addr, (unsigned char *) &cfg, sizeof(cfg)); - - /* Set up the MAC address */ - memset(&ias, 0x00, sizeof(ias)); - ias.ias_h.ac_command = (AC_CFLD_CMD & acmd_ia_setup); - ias.ias_h.ac_link = mcs_addr; - memcpy(&ias.ias_addr[0], (unsigned char *) &dev->dev_addr[0], - sizeof(ias.ias_addr)); - obram_write(ioaddr, ias_addr, (unsigned char *) &ias, sizeof(ias)); - - /* Initialize adapter's Ethernet multicast addresses */ - memset(&mcs, 0x00, sizeof(mcs)); - mcs.mcs_h.ac_command = AC_CFLD_I | (AC_CFLD_CMD & acmd_mc_setup); - mcs.mcs_h.ac_link = nop_addr; - mcs.mcs_cnt = WAVELAN_ADDR_SIZE * lp->mc_count; - obram_write(ioaddr, mcs_addr, (unsigned char *) &mcs, sizeof(mcs)); - - /* Any address to set? */ - if (lp->mc_count) { - for (dmi = dev->mc_list; dmi; dmi = dmi->next) - outsw(PIOP1(ioaddr), (u16 *) dmi->dmi_addr, - WAVELAN_ADDR_SIZE >> 1); - -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG - "%s: wv_82586_config(): set %d multicast addresses:\n", - dev->name, lp->mc_count); - for (dmi = dev->mc_list; dmi; dmi = dmi->next) - printk(KERN_DEBUG " %pM\n", dmi->dmi_addr); -#endif - } - - /* - * Overwrite the predecessor NOP link - * so that it points to the configure action. - */ - nop_addr = txpred + sizeof(tx); - nop.nop_h.ac_status = 0; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_status), - (unsigned char *) &nop.nop_h.ac_status, - sizeof(nop.nop_h.ac_status)); - nop.nop_h.ac_link = cfg_addr; - obram_write(ioaddr, toff(ac_nop_t, nop_addr, nop_h.ac_link), - (unsigned char *) &nop.nop_h.ac_link, - sizeof(nop.nop_h.ac_link)); - - /* Job done, clear the flag */ - lp->reconfig_82586 = 0; - - if (lp->tx_first_in_use == I82586NULL) - lp->tx_first_in_use = txblock; - - if (lp->tx_n_in_use == (NTXBLOCKS - 1)) - netif_stop_queue(dev); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82586_config()\n", dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * This routine, called by wavelan_close(), gracefully stops the - * WaveLAN controller (i82586). - * (called by wavelan_close()) - */ -static void wv_82586_stop(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - u16 scb_cmd; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82586_stop()\n", dev->name); -#endif - - /* Suspend both command unit and receive unit. */ - scb_cmd = - (SCB_CMD_CUC & SCB_CMD_CUC_SUS) | (SCB_CMD_RUC & - SCB_CMD_RUC_SUS); - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &scb_cmd, sizeof(scb_cmd)); - set_chan_attn(ioaddr, lp->hacr); - - /* No more interrupts */ - wv_ints_off(dev); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82586_stop()\n", dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * Totally reset the WaveLAN and restart it. - * Performs the following actions: - * 1. A power reset (reset DMA) - * 2. Initialize the radio modem (using wv_mmc_init) - * 3. Reset & Configure LAN controller (using wv_82586_start) - * 4. Start the LAN controller's command unit - * 5. Start the LAN controller's receive unit - * (called by wavelan_interrupt(), wavelan_watchdog() & wavelan_open()) - */ -static int wv_hw_reset(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long ioaddr = dev->base_addr; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_hw_reset(dev=0x%x)\n", dev->name, - (unsigned int) dev); -#endif - - /* Increase the number of resets done. */ - lp->nresets++; - - wv_hacr_reset(ioaddr); - lp->hacr = HACR_DEFAULT; - - if ((wv_mmc_init(dev) < 0) || (wv_82586_start(dev) < 0)) - return -1; - - /* Enable the card to send interrupts. */ - wv_ints_on(dev); - - /* Start card functions */ - if (wv_cu_start(dev) < 0) - return -1; - - /* Setup the controller and parameters */ - wv_82586_config(dev); - - /* Finish configuration with the receive unit */ - if (wv_ru_start(dev) < 0) - return -1; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Check if there is a WaveLAN at the specific base address. - * As a side effect, this reads the MAC address. - * (called in wavelan_probe() and init_module()) - */ -static int wv_check_ioaddr(unsigned long ioaddr, u8 * mac) -{ - int i; /* Loop counter */ - - /* Check if the base address if available. */ - if (!request_region(ioaddr, sizeof(ha_t), "wavelan probe")) - return -EBUSY; /* ioaddr already used */ - - /* Reset host interface */ - wv_hacr_reset(ioaddr); - - /* Read the MAC address from the parameter storage area. */ - psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_univ_mac_addr), - mac, 6); - - release_region(ioaddr, sizeof(ha_t)); - - /* - * Check the first three octets of the address for the manufacturer's code. - * Note: if this can't find your WaveLAN card, you've got a - * non-NCR/AT&T/Lucent ISA card. See wavelan.p.h for detail on - * how to configure your card. - */ - for (i = 0; i < ARRAY_SIZE(MAC_ADDRESSES); i++) - if ((mac[0] == MAC_ADDRESSES[i][0]) && - (mac[1] == MAC_ADDRESSES[i][1]) && - (mac[2] == MAC_ADDRESSES[i][2])) - return 0; - -#ifdef DEBUG_CONFIG_INFO - printk(KERN_WARNING - "WaveLAN (0x%3X): your MAC address might be %02X:%02X:%02X.\n", - ioaddr, mac[0], mac[1], mac[2]); -#endif - return -ENODEV; -} - -/************************ INTERRUPT HANDLING ************************/ - -/* - * This function is the interrupt handler for the WaveLAN card. This - * routine will be called whenever: - */ -static irqreturn_t wavelan_interrupt(int irq, void *dev_id) -{ - struct net_device *dev; - unsigned long ioaddr; - net_local *lp; - u16 hasr; - u16 status; - u16 ack_cmd; - - dev = dev_id; - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name); -#endif - - lp = netdev_priv(dev); - ioaddr = dev->base_addr; - -#ifdef DEBUG_INTERRUPT_INFO - /* Check state of our spinlock */ - if(spin_is_locked(&lp->spinlock)) - printk(KERN_DEBUG - "%s: wavelan_interrupt(): spinlock is already locked !!!\n", - dev->name); -#endif - - /* Prevent reentrancy. We need to do that because we may have - * multiple interrupt handler running concurrently. - * It is safe because interrupts are disabled before acquiring - * the spinlock. */ - spin_lock(&lp->spinlock); - - /* We always had spurious interrupts at startup, but lately I - * saw them comming *between* the request_irq() and the - * spin_lock_irqsave() in wavelan_open(), so the spinlock - * protection is no enough. - * So, we also check lp->hacr that will tell us is we enabled - * irqs or not (see wv_ints_on()). - * We can't use netif_running(dev) because we depend on the - * proper processing of the irq generated during the config. */ - - /* Which interrupt it is ? */ - hasr = hasr_read(ioaddr); - -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_INFO - "%s: wavelan_interrupt(): hasr 0x%04x; hacr 0x%04x.\n", - dev->name, hasr, lp->hacr); -#endif - - /* Check modem interrupt */ - if ((hasr & HASR_MMC_INTR) && (lp->hacr & HACR_MMC_INT_ENABLE)) { - u8 dce_status; - - /* - * Interrupt from the modem management controller. - * This will clear it -- ignored for now. - */ - mmc_read(ioaddr, mmroff(0, mmr_dce_status), &dce_status, - sizeof(dce_status)); - -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO - "%s: wavelan_interrupt(): unexpected mmc interrupt: status 0x%04x.\n", - dev->name, dce_status); -#endif - } - - /* Check if not controller interrupt */ - if (((hasr & HASR_82586_INTR) == 0) || - ((lp->hacr & HACR_82586_INT_ENABLE) == 0)) { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO - "%s: wavelan_interrupt(): interrupt not coming from i82586 - hasr 0x%04x.\n", - dev->name, hasr); -#endif - spin_unlock (&lp->spinlock); - return IRQ_NONE; - } - - /* Read interrupt data. */ - obram_read(ioaddr, scboff(OFFSET_SCB, scb_status), - (unsigned char *) &status, sizeof(status)); - - /* - * Acknowledge the interrupt(s). - */ - ack_cmd = status & SCB_ST_INT; - obram_write(ioaddr, scboff(OFFSET_SCB, scb_command), - (unsigned char *) &ack_cmd, sizeof(ack_cmd)); - set_chan_attn(ioaddr, lp->hacr); - -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wavelan_interrupt(): status 0x%04x.\n", - dev->name, status); -#endif - - /* Command completed. */ - if ((status & SCB_ST_CX) == SCB_ST_CX) { -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG - "%s: wavelan_interrupt(): command completed.\n", - dev->name); -#endif - wv_complete(dev, ioaddr, lp); - } - - /* Frame received. */ - if ((status & SCB_ST_FR) == SCB_ST_FR) { -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG - "%s: wavelan_interrupt(): received packet.\n", - dev->name); -#endif - wv_receive(dev); - } - - /* Check the state of the command unit. */ - if (((status & SCB_ST_CNA) == SCB_ST_CNA) || - (((status & SCB_ST_CUS) != SCB_ST_CUS_ACTV) && - (netif_running(dev)))) { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO - "%s: wavelan_interrupt(): CU inactive -- restarting\n", - dev->name); -#endif - wv_hw_reset(dev); - } - - /* Check the state of the command unit. */ - if (((status & SCB_ST_RNR) == SCB_ST_RNR) || - (((status & SCB_ST_RUS) != SCB_ST_RUS_RDY) && - (netif_running(dev)))) { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO - "%s: wavelan_interrupt(): RU not ready -- restarting\n", - dev->name); -#endif - wv_hw_reset(dev); - } - - /* Release spinlock */ - spin_unlock (&lp->spinlock); - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); -#endif - return IRQ_HANDLED; -} - -/*------------------------------------------------------------------*/ -/* - * Watchdog: when we start a transmission, a timer is set for us in the - * kernel. If the transmission completes, this timer is disabled. If - * the timer expires, we are called and we try to unlock the hardware. - */ -static void wavelan_watchdog(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - u_long ioaddr = dev->base_addr; - unsigned long flags; - unsigned int nreaped; - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name); -#endif - -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n", - dev->name); -#endif - - /* Check that we came here for something */ - if (lp->tx_n_in_use <= 0) { - return; - } - - spin_lock_irqsave(&lp->spinlock, flags); - - /* Try to see if some buffers are not free (in case we missed - * an interrupt */ - nreaped = wv_complete(dev, ioaddr, lp); - -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG - "%s: wavelan_watchdog(): %d reaped, %d remain.\n", - dev->name, nreaped, lp->tx_n_in_use); -#endif - -#ifdef DEBUG_PSA_SHOW - { - psa_t psa; - psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); - wv_psa_show(&psa); - } -#endif -#ifdef DEBUG_MMC_SHOW - wv_mmc_show(dev); -#endif -#ifdef DEBUG_I82586_SHOW - wv_cu_show(dev); -#endif - - /* If no buffer has been freed */ - if (nreaped == 0) { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO - "%s: wavelan_watchdog(): cleanup failed, trying reset\n", - dev->name); -#endif - wv_hw_reset(dev); - } - - /* At this point, we should have some free Tx buffer ;-) */ - if (lp->tx_n_in_use < NTXBLOCKS - 1) - netif_wake_queue(dev); - - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name); -#endif -} - -/********************* CONFIGURATION CALLBACKS *********************/ -/* - * Here are the functions called by the Linux networking code (NET3) - * for initialization, configuration and deinstallations of the - * WaveLAN ISA hardware. - */ - -/*------------------------------------------------------------------*/ -/* - * Configure and start up the WaveLAN PCMCIA adaptor. - * Called by NET3 when it "opens" the device. - */ -static int wavelan_open(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name, - (unsigned int) dev); -#endif - - /* Check irq */ - if (dev->irq == 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_open(): no IRQ\n", - dev->name); -#endif - return -ENXIO; - } - - if (request_irq(dev->irq, &wavelan_interrupt, 0, "WaveLAN", dev) != 0) - { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING "%s: wavelan_open(): invalid IRQ\n", - dev->name); -#endif - return -EAGAIN; - } - - spin_lock_irqsave(&lp->spinlock, flags); - - if (wv_hw_reset(dev) != -1) { - netif_start_queue(dev); - } else { - free_irq(dev->irq, dev); -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wavelan_open(): impossible to start the card\n", - dev->name); -#endif - spin_unlock_irqrestore(&lp->spinlock, flags); - return -EAGAIN; - } - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Shut down the WaveLAN ISA card. - * Called by NET3 when it "closes" the device. - */ -static int wavelan_close(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name, - (unsigned int) dev); -#endif - - netif_stop_queue(dev); - - /* - * Flush the Tx and disable Rx. - */ - spin_lock_irqsave(&lp->spinlock, flags); - wv_82586_stop(dev); - spin_unlock_irqrestore(&lp->spinlock, flags); - - free_irq(dev->irq, dev); - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name); -#endif - return 0; -} - -static const struct net_device_ops wavelan_netdev_ops = { - .ndo_open = wavelan_open, - .ndo_stop = wavelan_close, - .ndo_start_xmit = wavelan_packet_xmit, - .ndo_set_multicast_list = wavelan_set_multicast_list, - .ndo_tx_timeout = wavelan_watchdog, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, -#ifdef SET_MAC_ADDRESS - .ndo_set_mac_address = wavelan_set_mac_address -#else - .ndo_set_mac_address = eth_mac_addr, -#endif -}; - - -/*------------------------------------------------------------------*/ -/* - * Probe an I/O address, and if the WaveLAN is there configure the - * device structure - * (called by wavelan_probe() and via init_module()). - */ -static int __init wavelan_config(struct net_device *dev, unsigned short ioaddr) -{ - u8 irq_mask; - int irq; - net_local *lp; - mac_addr mac; - int err; - - if (!request_region(ioaddr, sizeof(ha_t), "wavelan")) - return -EADDRINUSE; - - err = wv_check_ioaddr(ioaddr, mac); - if (err) - goto out; - - memcpy(dev->dev_addr, mac, 6); - - dev->base_addr = ioaddr; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_config(dev=0x%x, ioaddr=0x%lx)\n", - dev->name, (unsigned int) dev, ioaddr); -#endif - - /* Check IRQ argument on command line. */ - if (dev->irq != 0) { - irq_mask = wv_irq_to_psa(dev->irq); - - if (irq_mask == 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING - "%s: wavelan_config(): invalid IRQ %d ignored.\n", - dev->name, dev->irq); -#endif - dev->irq = 0; - } else { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG - "%s: wavelan_config(): changing IRQ to %d\n", - dev->name, dev->irq); -#endif - psa_write(ioaddr, HACR_DEFAULT, - psaoff(0, psa_int_req_no), &irq_mask, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev, ioaddr, HACR_DEFAULT); - wv_hacr_reset(ioaddr); - } - } - - psa_read(ioaddr, HACR_DEFAULT, psaoff(0, psa_int_req_no), - &irq_mask, 1); - if ((irq = wv_psa_to_irq(irq_mask)) == -1) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_INFO - "%s: wavelan_config(): could not wavelan_map_irq(%d).\n", - dev->name, irq_mask); -#endif - err = -EAGAIN; - goto out; - } - - dev->irq = irq; - - dev->mem_start = 0x0000; - dev->mem_end = 0x0000; - dev->if_port = 0; - - /* Initialize device structures */ - memset(netdev_priv(dev), 0, sizeof(net_local)); - lp = netdev_priv(dev); - - /* Back link to the device structure. */ - lp->dev = dev; - /* Add the device at the beginning of the linked list. */ - lp->next = wavelan_list; - wavelan_list = lp; - - lp->hacr = HACR_DEFAULT; - - /* Multicast stuff */ - lp->promiscuous = 0; - lp->mc_count = 0; - - /* Init spinlock */ - spin_lock_init(&lp->spinlock); - - dev->netdev_ops = &wavelan_netdev_ops; - dev->watchdog_timeo = WATCHDOG_JIFFIES; - dev->wireless_handlers = &wavelan_handler_def; - lp->wireless_data.spy_data = &lp->spy_data; - dev->wireless_data = &lp->wireless_data; - - dev->mtu = WAVELAN_MTU; - - /* Display nice information. */ - wv_init_info(dev); - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_config()\n", dev->name); -#endif - return 0; -out: - release_region(ioaddr, sizeof(ha_t)); - return err; -} - -/*------------------------------------------------------------------*/ -/* - * Check for a network adaptor of this type. Return '0' iff one - * exists. There seem to be different interpretations of - * the initial value of dev->base_addr. - * We follow the example in drivers/net/ne.c. - * (called in "Space.c") - */ -struct net_device * __init wavelan_probe(int unit) -{ - struct net_device *dev; - short base_addr; - int def_irq; - int i; - int r = 0; - - /* compile-time check the sizes of structures */ - BUILD_BUG_ON(sizeof(psa_t) != PSA_SIZE); - BUILD_BUG_ON(sizeof(mmw_t) != MMW_SIZE); - BUILD_BUG_ON(sizeof(mmr_t) != MMR_SIZE); - BUILD_BUG_ON(sizeof(ha_t) != HA_SIZE); - - dev = alloc_etherdev(sizeof(net_local)); - if (!dev) - return ERR_PTR(-ENOMEM); - - sprintf(dev->name, "eth%d", unit); - netdev_boot_setup_check(dev); - base_addr = dev->base_addr; - def_irq = dev->irq; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG - "%s: ->wavelan_probe(dev=%p (base_addr=0x%x))\n", - dev->name, dev, (unsigned int) dev->base_addr); -#endif - - /* Don't probe at all. */ - if (base_addr < 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING - "%s: wavelan_probe(): invalid base address\n", - dev->name); -#endif - r = -ENXIO; - } else if (base_addr > 0x100) { /* Check a single specified location. */ - r = wavelan_config(dev, base_addr); -#ifdef DEBUG_CONFIG_INFO - if (r != 0) - printk(KERN_DEBUG - "%s: wavelan_probe(): no device at specified base address (0x%X) or address already in use\n", - dev->name, base_addr); -#endif - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_probe()\n", dev->name); -#endif - } else { /* Scan all possible addresses of the WaveLAN hardware. */ - for (i = 0; i < ARRAY_SIZE(iobase); i++) { - dev->irq = def_irq; - if (wavelan_config(dev, iobase[i]) == 0) { -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG - "%s: <-wavelan_probe()\n", - dev->name); -#endif - break; - } - } - if (i == ARRAY_SIZE(iobase)) - r = -ENODEV; - } - if (r) - goto out; - r = register_netdev(dev); - if (r) - goto out1; - return dev; -out1: - release_region(dev->base_addr, sizeof(ha_t)); - wavelan_list = wavelan_list->next; -out: - free_netdev(dev); - return ERR_PTR(r); -} - -/****************************** MODULE ******************************/ -/* - * Module entry point: insertion and removal - */ - -#ifdef MODULE -/*------------------------------------------------------------------*/ -/* - * Insertion of the module - * I'm now quite proud of the multi-device support. - */ -int __init init_module(void) -{ - int ret = -EIO; /* Return error if no cards found */ - int i; - -#ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "-> init_module()\n"); -#endif - - /* If probing is asked */ - if (io[0] == 0) { -#ifdef DEBUG_CONFIG_ERROR - printk(KERN_WARNING - "WaveLAN init_module(): doing device probing (bad !)\n"); - printk(KERN_WARNING - "Specify base addresses while loading module to correct the problem\n"); -#endif - - /* Copy the basic set of address to be probed. */ - for (i = 0; i < ARRAY_SIZE(iobase); i++) - io[i] = iobase[i]; - } - - - /* Loop on all possible base addresses. */ - for (i = 0; i < ARRAY_SIZE(io) && io[i] != 0; i++) { - struct net_device *dev = alloc_etherdev(sizeof(net_local)); - if (!dev) - break; - if (name[i]) - strcpy(dev->name, name[i]); /* Copy name */ - dev->base_addr = io[i]; - dev->irq = irq[i]; - - /* Check if there is something at this base address. */ - if (wavelan_config(dev, io[i]) == 0) { - if (register_netdev(dev) != 0) { - release_region(dev->base_addr, sizeof(ha_t)); - wavelan_list = wavelan_list->next; - } else { - ret = 0; - continue; - } - } - free_netdev(dev); - } - -#ifdef DEBUG_CONFIG_ERROR - if (!wavelan_list) - printk(KERN_WARNING - "WaveLAN init_module(): no device found\n"); -#endif - -#ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "<- init_module()\n"); -#endif - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Removal of the module - */ -void cleanup_module(void) -{ -#ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "-> cleanup_module()\n"); -#endif - - /* Loop on all devices and release them. */ - while (wavelan_list) { - struct net_device *dev = wavelan_list->dev; - -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG - "%s: cleanup_module(): removing device at 0x%x\n", - dev->name, (unsigned int) dev); -#endif - unregister_netdev(dev); - - release_region(dev->base_addr, sizeof(ha_t)); - wavelan_list = wavelan_list->next; - - free_netdev(dev); - } - -#ifdef DEBUG_MODULE_TRACE - printk(KERN_DEBUG "<- cleanup_module()\n"); -#endif -} -#endif /* MODULE */ -MODULE_LICENSE("GPL"); - -/* - * This software may only be used and distributed - * according to the terms of the GNU General Public License. - * - * This software was developed as a component of the - * Linux operating system. - * It is based on other device drivers and information - * either written or supplied by: - * Ajay Bakre (bakre@paul.rutgers.edu), - * Donald Becker (becker@scyld.com), - * Loeke Brederveld (Loeke.Brederveld@Utrecht.NCR.com), - * Anders Klemets (klemets@it.kth.se), - * Vladimir V. Kolpakov (w@stier.koenig.ru), - * Marc Meertens (Marc.Meertens@Utrecht.NCR.com), - * Pauline Middelink (middelin@polyware.iaf.nl), - * Robert Morris (rtm@das.harvard.edu), - * Jean Tourrilhes (jt@hplb.hpl.hp.com), - * Girish Welling (welling@paul.rutgers.edu), - * - * Thanks go also to: - * James Ashton (jaa101@syseng.anu.edu.au), - * Alan Cox (alan@lxorguk.ukuu.org.uk), - * Allan Creighton (allanc@cs.usyd.edu.au), - * Matthew Geier (matthew@cs.usyd.edu.au), - * Remo di Giovanni (remo@cs.usyd.edu.au), - * Eckhard Grah (grah@wrcs1.urz.uni-wuppertal.de), - * Vipul Gupta (vgupta@cs.binghamton.edu), - * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), - * Tim Nicholson (tim@cs.usyd.edu.au), - * Ian Parkin (ian@cs.usyd.edu.au), - * John Rosenberg (johnr@cs.usyd.edu.au), - * George Rossi (george@phm.gov.au), - * Arthur Scott (arthur@cs.usyd.edu.au), - * Peter Storey, - * for their assistance and advice. - * - * Please send bug reports, updates, comments to: - * - * Bruce Janson Email: bruce@cs.usyd.edu.au - * Basser Department of Computer Science Phone: +61-2-9351-3423 - * University of Sydney, N.S.W., 2006, AUSTRALIA Fax: +61-2-9351-3838 - */ diff --git a/drivers/net/wireless/wavelan.h b/drivers/net/wireless/wavelan.h deleted file mode 100644 index 9ab360558ffd..000000000000 --- a/drivers/net/wireless/wavelan.h +++ /dev/null @@ -1,370 +0,0 @@ -/* - * WaveLAN ISA driver - * - * Jean II - HPLB '96 - * - * Reorganisation and extension of the driver. - * Original copyright follows. See wavelan.p.h for details. - * - * This file contains the declarations for the WaveLAN hardware. Note that - * the WaveLAN ISA includes a i82586 controller (see definitions in - * file i82586.h). - * - * The main difference between the ISA hardware and the PCMCIA one is - * the Ethernet controller (i82586 instead of i82593). - * The i82586 allows multiple transmit buffers. The PSA needs to be accessed - * through the host interface. - */ - -#ifndef _WAVELAN_H -#define _WAVELAN_H - -/************************** MAGIC NUMBERS ***************************/ - -/* Detection of the WaveLAN card is done by reading the MAC - * address from the card and checking it. If you have a non-AT&T - * product (OEM, like DEC RoamAbout, Digital Ocean, or Epson), - * you might need to modify this part to accommodate your hardware. - */ -static const char MAC_ADDRESSES[][3] = -{ - { 0x08, 0x00, 0x0E }, /* AT&T WaveLAN (standard) & DEC RoamAbout */ - { 0x08, 0x00, 0x6A }, /* AT&T WaveLAN (alternate) */ - { 0x00, 0x00, 0xE1 }, /* Hitachi Wavelan */ - { 0x00, 0x60, 0x1D } /* Lucent Wavelan (another one) */ - /* Add your card here and send me the patch! */ -}; - -#define WAVELAN_ADDR_SIZE 6 /* Size of a MAC address */ - -#define WAVELAN_MTU 1500 /* Maximum size of WaveLAN packet */ - -#define MAXDATAZ (WAVELAN_ADDR_SIZE + WAVELAN_ADDR_SIZE + 2 + WAVELAN_MTU) - -/* - * Constants used to convert channels to frequencies - */ - -/* Frequency available in the 2.0 modem, in units of 250 kHz - * (as read in the offset register of the dac area). - * Used to map channel numbers used by `wfreqsel' to frequencies - */ -static const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8, - 0xD0, 0xF0, 0xF8, 0x150 }; - -/* Frequencies of the 1.0 modem (fixed frequencies). - * Use to map the PSA `subband' to a frequency - * Note : all frequencies apart from the first one need to be multiplied by 10 - */ -static const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 }; - - - -/*************************** PC INTERFACE ****************************/ - -/* - * Host Adaptor structure. - * (base is board port address). - */ -typedef union hacs_u hacs_u; -union hacs_u -{ - unsigned short hu_command; /* Command register */ -#define HACR_RESET 0x0001 /* Reset board */ -#define HACR_CA 0x0002 /* Set Channel Attention for 82586 */ -#define HACR_16BITS 0x0004 /* 16-bit operation (0 => 8bits) */ -#define HACR_OUT0 0x0008 /* General purpose output pin 0 */ - /* not used - must be 1 */ -#define HACR_OUT1 0x0010 /* General purpose output pin 1 */ - /* not used - must be 1 */ -#define HACR_82586_INT_ENABLE 0x0020 /* Enable 82586 interrupts */ -#define HACR_MMC_INT_ENABLE 0x0040 /* Enable MMC interrupts */ -#define HACR_INTR_CLR_ENABLE 0x0080 /* Enable interrupt status read/clear */ - unsigned short hu_status; /* Status Register */ -#define HASR_82586_INTR 0x0001 /* Interrupt request from 82586 */ -#define HASR_MMC_INTR 0x0002 /* Interrupt request from MMC */ -#define HASR_MMC_BUSY 0x0004 /* MMC busy indication */ -#define HASR_PSA_BUSY 0x0008 /* LAN parameter storage area busy */ -} __attribute__ ((packed)); - -typedef struct ha_t ha_t; -struct ha_t -{ - hacs_u ha_cs; /* Command and status registers */ -#define ha_command ha_cs.hu_command -#define ha_status ha_cs.hu_status - unsigned short ha_mmcr; /* Modem Management Ctrl Register */ - unsigned short ha_pior0; /* Program I/O Address Register Port 0 */ - unsigned short ha_piop0; /* Program I/O Port 0 */ - unsigned short ha_pior1; /* Program I/O Address Register Port 1 */ - unsigned short ha_piop1; /* Program I/O Port 1 */ - unsigned short ha_pior2; /* Program I/O Address Register Port 2 */ - unsigned short ha_piop2; /* Program I/O Port 2 */ -}; - -#define HA_SIZE 16 - -#define hoff(p,f) (unsigned short)((void *)(&((ha_t *)((void *)0 + (p)))->f) - (void *)0) -#define HACR(p) hoff(p, ha_command) -#define HASR(p) hoff(p, ha_status) -#define MMCR(p) hoff(p, ha_mmcr) -#define PIOR0(p) hoff(p, ha_pior0) -#define PIOP0(p) hoff(p, ha_piop0) -#define PIOR1(p) hoff(p, ha_pior1) -#define PIOP1(p) hoff(p, ha_piop1) -#define PIOR2(p) hoff(p, ha_pior2) -#define PIOP2(p) hoff(p, ha_piop2) - -/* - * Program I/O Mode Register values. - */ -#define STATIC_PIO 0 /* Mode 1: static mode */ - /* RAM access ??? */ -#define AUTOINCR_PIO 1 /* Mode 2: auto increment mode */ - /* RAM access ??? */ -#define AUTODECR_PIO 2 /* Mode 3: auto decrement mode */ - /* RAM access ??? */ -#define PARAM_ACCESS_PIO 3 /* Mode 4: LAN parameter access mode */ - /* Parameter access. */ -#define PIO_MASK 3 /* register mask */ -#define PIOM(cmd,piono) ((u_short)cmd << 10 << (piono * 2)) - -#define HACR_DEFAULT (HACR_OUT0 | HACR_OUT1 | HACR_16BITS | PIOM(STATIC_PIO, 0) | PIOM(AUTOINCR_PIO, 1) | PIOM(PARAM_ACCESS_PIO, 2)) -#define HACR_INTRON (HACR_82586_INT_ENABLE | HACR_MMC_INT_ENABLE | HACR_INTR_CLR_ENABLE) - -/************************** MEMORY LAYOUT **************************/ - -/* - * Onboard 64 k RAM layout. - * (Offsets from 0x0000.) - */ -#define OFFSET_RU 0x0000 /* 75% memory */ -#define OFFSET_CU 0xC000 /* 25% memory */ -#define OFFSET_SCB (OFFSET_ISCP - sizeof(scb_t)) -#define OFFSET_ISCP (OFFSET_SCP - sizeof(iscp_t)) -#define OFFSET_SCP I82586_SCP_ADDR - -#define RXBLOCKZ (sizeof(fd_t) + sizeof(rbd_t) + MAXDATAZ) -#define TXBLOCKZ (sizeof(ac_tx_t) + sizeof(ac_nop_t) + sizeof(tbd_t) + MAXDATAZ) - -#define NRXBLOCKS ((OFFSET_CU - OFFSET_RU) / RXBLOCKZ) -#define NTXBLOCKS ((OFFSET_SCB - OFFSET_CU) / TXBLOCKZ) - -/********************** PARAMETER STORAGE AREA **********************/ - -/* - * Parameter Storage Area (PSA). - */ -typedef struct psa_t psa_t; -struct psa_t -{ - unsigned char psa_io_base_addr_1; /* [0x00] Base address 1 ??? */ - unsigned char psa_io_base_addr_2; /* [0x01] Base address 2 */ - unsigned char psa_io_base_addr_3; /* [0x02] Base address 3 */ - unsigned char psa_io_base_addr_4; /* [0x03] Base address 4 */ - unsigned char psa_rem_boot_addr_1; /* [0x04] Remote Boot Address 1 */ - unsigned char psa_rem_boot_addr_2; /* [0x05] Remote Boot Address 2 */ - unsigned char psa_rem_boot_addr_3; /* [0x06] Remote Boot Address 3 */ - unsigned char psa_holi_params; /* [0x07] HOst Lan Interface (HOLI) Parameters */ - unsigned char psa_int_req_no; /* [0x08] Interrupt Request Line */ - unsigned char psa_unused0[7]; /* [0x09-0x0F] unused */ - - unsigned char psa_univ_mac_addr[WAVELAN_ADDR_SIZE]; /* [0x10-0x15] Universal (factory) MAC Address */ - unsigned char psa_local_mac_addr[WAVELAN_ADDR_SIZE]; /* [0x16-1B] Local MAC Address */ - unsigned char psa_univ_local_sel; /* [0x1C] Universal Local Selection */ -#define PSA_UNIVERSAL 0 /* Universal (factory) */ -#define PSA_LOCAL 1 /* Local */ - unsigned char psa_comp_number; /* [0x1D] Compatibility Number: */ -#define PSA_COMP_PC_AT_915 0 /* PC-AT 915 MHz */ -#define PSA_COMP_PC_MC_915 1 /* PC-MC 915 MHz */ -#define PSA_COMP_PC_AT_2400 2 /* PC-AT 2.4 GHz */ -#define PSA_COMP_PC_MC_2400 3 /* PC-MC 2.4 GHz */ -#define PSA_COMP_PCMCIA_915 4 /* PCMCIA 915 MHz or 2.0 */ - unsigned char psa_thr_pre_set; /* [0x1E] Modem Threshold Preset */ - unsigned char psa_feature_select; /* [0x1F] Call code required (1=on) */ -#define PSA_FEATURE_CALL_CODE 0x01 /* Call code required (Japan) */ - unsigned char psa_subband; /* [0x20] Subband */ -#define PSA_SUBBAND_915 0 /* 915 MHz or 2.0 */ -#define PSA_SUBBAND_2425 1 /* 2425 MHz */ -#define PSA_SUBBAND_2460 2 /* 2460 MHz */ -#define PSA_SUBBAND_2484 3 /* 2484 MHz */ -#define PSA_SUBBAND_2430_5 4 /* 2430.5 MHz */ - unsigned char psa_quality_thr; /* [0x21] Modem Quality Threshold */ - unsigned char psa_mod_delay; /* [0x22] Modem Delay (?) (reserved) */ - unsigned char psa_nwid[2]; /* [0x23-0x24] Network ID */ - unsigned char psa_nwid_select; /* [0x25] Network ID Select On/Off */ - unsigned char psa_encryption_select; /* [0x26] Encryption On/Off */ - unsigned char psa_encryption_key[8]; /* [0x27-0x2E] Encryption Key */ - unsigned char psa_databus_width; /* [0x2F] AT bus width select 8/16 */ - unsigned char psa_call_code[8]; /* [0x30-0x37] (Japan) Call Code */ - unsigned char psa_nwid_prefix[2]; /* [0x38-0x39] Roaming domain */ - unsigned char psa_reserved[2]; /* [0x3A-0x3B] Reserved - fixed 00 */ - unsigned char psa_conf_status; /* [0x3C] Conf Status, bit 0=1:config*/ - unsigned char psa_crc[2]; /* [0x3D] CRC-16 over PSA */ - unsigned char psa_crc_status; /* [0x3F] CRC Valid Flag */ -}; - -#define PSA_SIZE 64 - -/* Calculate offset of a field in the above structure. - * Warning: only even addresses are used. */ -#define psaoff(p,f) ((unsigned short) ((void *)(&((psa_t *) ((void *) NULL + (p)))->f) - (void *) NULL)) - -/******************** MODEM MANAGEMENT INTERFACE ********************/ - -/* - * Modem Management Controller (MMC) write structure. - */ -typedef struct mmw_t mmw_t; -struct mmw_t -{ - unsigned char mmw_encr_key[8]; /* encryption key */ - unsigned char mmw_encr_enable; /* Enable or disable encryption. */ -#define MMW_ENCR_ENABLE_MODE 0x02 /* mode of security option */ -#define MMW_ENCR_ENABLE_EN 0x01 /* Enable security option. */ - unsigned char mmw_unused0[1]; /* unused */ - unsigned char mmw_des_io_invert; /* encryption option */ -#define MMW_DES_IO_INVERT_RES 0x0F /* reserved */ -#define MMW_DES_IO_INVERT_CTRL 0xF0 /* control (?) (set to 0) */ - unsigned char mmw_unused1[5]; /* unused */ - unsigned char mmw_loopt_sel; /* looptest selection */ -#define MMW_LOOPT_SEL_DIS_NWID 0x40 /* Disable NWID filtering. */ -#define MMW_LOOPT_SEL_INT 0x20 /* Activate Attention Request. */ -#define MMW_LOOPT_SEL_LS 0x10 /* looptest, no collision avoidance */ -#define MMW_LOOPT_SEL_LT3A 0x08 /* looptest 3a */ -#define MMW_LOOPT_SEL_LT3B 0x04 /* looptest 3b */ -#define MMW_LOOPT_SEL_LT3C 0x02 /* looptest 3c */ -#define MMW_LOOPT_SEL_LT3D 0x01 /* looptest 3d */ - unsigned char mmw_jabber_enable; /* jabber timer enable */ - /* Abort transmissions > 200 ms */ - unsigned char mmw_freeze; /* freeze or unfreeze signal level */ - /* 0 : signal level & qual updated for every new message, 1 : frozen */ - unsigned char mmw_anten_sel; /* antenna selection */ -#define MMW_ANTEN_SEL_SEL 0x01 /* direct antenna selection */ -#define MMW_ANTEN_SEL_ALG_EN 0x02 /* antenna selection algo. enable */ - unsigned char mmw_ifs; /* inter frame spacing */ - /* min time between transmission in bit periods (.5 us) - bit 0 ignored */ - unsigned char mmw_mod_delay; /* modem delay (synchro) */ - unsigned char mmw_jam_time; /* jamming time (after collision) */ - unsigned char mmw_unused2[1]; /* unused */ - unsigned char mmw_thr_pre_set; /* level threshold preset */ - /* Discard all packet with signal < this value (4) */ - unsigned char mmw_decay_prm; /* decay parameters */ - unsigned char mmw_decay_updat_prm; /* decay update parameters */ - unsigned char mmw_quality_thr; /* quality (z-quotient) threshold */ - /* Discard all packet with quality < this value (3) */ - unsigned char mmw_netw_id_l; /* NWID low order byte */ - unsigned char mmw_netw_id_h; /* NWID high order byte */ - /* Network ID or Domain : create virtual net on the air */ - - /* 2.0 Hardware extension - frequency selection support */ - unsigned char mmw_mode_select; /* for analog tests (set to 0) */ - unsigned char mmw_unused3[1]; /* unused */ - unsigned char mmw_fee_ctrl; /* frequency EEPROM control */ -#define MMW_FEE_CTRL_PRE 0x10 /* Enable protected instructions. */ -#define MMW_FEE_CTRL_DWLD 0x08 /* Download EEPROM to mmc. */ -#define MMW_FEE_CTRL_CMD 0x07 /* EEPROM commands: */ -#define MMW_FEE_CTRL_READ 0x06 /* Read */ -#define MMW_FEE_CTRL_WREN 0x04 /* Write enable */ -#define MMW_FEE_CTRL_WRITE 0x05 /* Write data to address. */ -#define MMW_FEE_CTRL_WRALL 0x04 /* Write data to all addresses. */ -#define MMW_FEE_CTRL_WDS 0x04 /* Write disable */ -#define MMW_FEE_CTRL_PRREAD 0x16 /* Read addr from protect register */ -#define MMW_FEE_CTRL_PREN 0x14 /* Protect register enable */ -#define MMW_FEE_CTRL_PRCLEAR 0x17 /* Unprotect all registers. */ -#define MMW_FEE_CTRL_PRWRITE 0x15 /* Write address in protect register */ -#define MMW_FEE_CTRL_PRDS 0x14 /* Protect register disable */ - /* Never issue the PRDS command: it's irreversible! */ - - unsigned char mmw_fee_addr; /* EEPROM address */ -#define MMW_FEE_ADDR_CHANNEL 0xF0 /* Select the channel. */ -#define MMW_FEE_ADDR_OFFSET 0x0F /* Offset in channel data */ -#define MMW_FEE_ADDR_EN 0xC0 /* FEE_CTRL enable operations */ -#define MMW_FEE_ADDR_DS 0x00 /* FEE_CTRL disable operations */ -#define MMW_FEE_ADDR_ALL 0x40 /* FEE_CTRL all operations */ -#define MMW_FEE_ADDR_CLEAR 0xFF /* FEE_CTRL clear operations */ - - unsigned char mmw_fee_data_l; /* Write data to EEPROM. */ - unsigned char mmw_fee_data_h; /* high octet */ - unsigned char mmw_ext_ant; /* Setting for external antenna */ -#define MMW_EXT_ANT_EXTANT 0x01 /* Select external antenna */ -#define MMW_EXT_ANT_POL 0x02 /* Polarity of the antenna */ -#define MMW_EXT_ANT_INTERNAL 0x00 /* Internal antenna */ -#define MMW_EXT_ANT_EXTERNAL 0x03 /* External antenna */ -#define MMW_EXT_ANT_IQ_TEST 0x1C /* IQ test pattern (set to 0) */ -} __attribute__ ((packed)); - -#define MMW_SIZE 37 - -#define mmwoff(p,f) (unsigned short)((void *)(&((mmw_t *)((void *)0 + (p)))->f) - (void *)0) - -/* - * Modem Management Controller (MMC) read structure. - */ -typedef struct mmr_t mmr_t; -struct mmr_t -{ - unsigned char mmr_unused0[8]; /* unused */ - unsigned char mmr_des_status; /* encryption status */ - unsigned char mmr_des_avail; /* encryption available (0x55 read) */ -#define MMR_DES_AVAIL_DES 0x55 /* DES available */ -#define MMR_DES_AVAIL_AES 0x33 /* AES (AT&T) available */ - unsigned char mmr_des_io_invert; /* des I/O invert register */ - unsigned char mmr_unused1[5]; /* unused */ - unsigned char mmr_dce_status; /* DCE status */ -#define MMR_DCE_STATUS_RX_BUSY 0x01 /* receiver busy */ -#define MMR_DCE_STATUS_LOOPT_IND 0x02 /* loop test indicated */ -#define MMR_DCE_STATUS_TX_BUSY 0x04 /* transmitter on */ -#define MMR_DCE_STATUS_JBR_EXPIRED 0x08 /* jabber timer expired */ -#define MMR_DCE_STATUS 0x0F /* mask to get the bits */ - unsigned char mmr_dsp_id; /* DSP ID (AA = Daedalus rev A) */ - unsigned char mmr_unused2[2]; /* unused */ - unsigned char mmr_correct_nwid_l; /* # of correct NWIDs rxd (low) */ - unsigned char mmr_correct_nwid_h; /* # of correct NWIDs rxd (high) */ - /* Warning: read high-order octet first! */ - unsigned char mmr_wrong_nwid_l; /* # of wrong NWIDs rxd (low) */ - unsigned char mmr_wrong_nwid_h; /* # of wrong NWIDs rxd (high) */ - unsigned char mmr_thr_pre_set; /* level threshold preset */ -#define MMR_THR_PRE_SET 0x3F /* level threshold preset */ -#define MMR_THR_PRE_SET_CUR 0x80 /* Current signal above it */ - unsigned char mmr_signal_lvl; /* signal level */ -#define MMR_SIGNAL_LVL 0x3F /* signal level */ -#define MMR_SIGNAL_LVL_VALID 0x80 /* Updated since last read */ - unsigned char mmr_silence_lvl; /* silence level (noise) */ -#define MMR_SILENCE_LVL 0x3F /* silence level */ -#define MMR_SILENCE_LVL_VALID 0x80 /* Updated since last read */ - unsigned char mmr_sgnl_qual; /* signal quality */ -#define MMR_SGNL_QUAL 0x0F /* signal quality */ -#define MMR_SGNL_QUAL_ANT 0x80 /* current antenna used */ - unsigned char mmr_netw_id_l; /* NWID low order byte (?) */ - unsigned char mmr_unused3[3]; /* unused */ - - /* 2.0 Hardware extension - frequency selection support */ - unsigned char mmr_fee_status; /* Status of frequency EEPROM */ -#define MMR_FEE_STATUS_ID 0xF0 /* Modem revision ID */ -#define MMR_FEE_STATUS_DWLD 0x08 /* Download in progress */ -#define MMR_FEE_STATUS_BUSY 0x04 /* EEPROM busy */ - unsigned char mmr_unused4[1]; /* unused */ - unsigned char mmr_fee_data_l; /* Read data from EEPROM (low) */ - unsigned char mmr_fee_data_h; /* Read data from EEPROM (high) */ -} __attribute__ ((packed)); - -#define MMR_SIZE 36 - -#define mmroff(p,f) (unsigned short)((void *)(&((mmr_t *)((void *)0 + (p)))->f) - (void *)0) - -/* Make the two above structures one */ -typedef union mm_t -{ - struct mmw_t w; /* Write to the mmc */ - struct mmr_t r; /* Read from the mmc */ -} mm_t; - -#endif /* _WAVELAN_H */ - -/* - * This software may only be used and distributed - * according to the terms of the GNU General Public License. - * - * For more details, see wavelan.c. - */ diff --git a/drivers/net/wireless/wavelan.p.h b/drivers/net/wireless/wavelan.p.h deleted file mode 100644 index dbe8de6e5f52..000000000000 --- a/drivers/net/wireless/wavelan.p.h +++ /dev/null @@ -1,696 +0,0 @@ -/* - * WaveLAN ISA driver - * - * Jean II - HPLB '96 - * - * Reorganisation and extension of the driver. - * - * This file contains all definitions and declarations necessary for the - * WaveLAN ISA driver. This file is a private header, so it should - * be included only in wavelan.c! - */ - -#ifndef WAVELAN_P_H -#define WAVELAN_P_H - -/************************** DOCUMENTATION ***************************/ -/* - * This driver provides a Linux interface to the WaveLAN ISA hardware. - * The WaveLAN is a product of Lucent (http://www.wavelan.com/). - * This division was formerly part of NCR and then AT&T. - * WaveLANs are also distributed by DEC (RoamAbout DS) and Digital Ocean. - * - * To learn how to use this driver, read the NET3 HOWTO. - * If you want to exploit the many other functionalities, read the comments - * in the code. - * - * This driver is the result of the effort of many people (see below). - */ - -/* ------------------------ SPECIFIC NOTES ------------------------ */ -/* - * Web page - * -------- - * I try to maintain a web page with the Wireless LAN Howto at : - * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Wavelan.html - * - * SMP - * --- - * We now are SMP compliant (I eventually fixed the remaining bugs). - * The driver has been tested on a dual P6-150 and survived my usual - * set of torture tests. - * Anyway, I spent enough time chasing interrupt re-entrancy during - * errors or reconfigure, and I designed the locked/unlocked sections - * of the driver with great care, and with the recent addition of - * the spinlock (thanks to the new API), we should be quite close to - * the truth. - * The SMP/IRQ locking is quite coarse and conservative (i.e. not fast), - * but better safe than sorry (especially at 2 Mb/s ;-). - * - * I have also looked into disabling only our interrupt on the card - * (via HACR) instead of all interrupts in the processor (via cli), - * so that other driver are not impacted, and it look like it's - * possible, but it's very tricky to do right (full of races). As - * the gain would be mostly for SMP systems, it can wait... - * - * Debugging and options - * --------------------- - * You will find below a set of '#define" allowing a very fine control - * on the driver behaviour and the debug messages printed. - * The main options are : - * o SET_PSA_CRC, to have your card correctly recognised by - * an access point and the Point-to-Point diagnostic tool. - * o USE_PSA_CONFIG, to read configuration from the PSA (EEprom) - * (otherwise we always start afresh with some defaults) - * - * wavelan.o is too darned big - * --------------------------- - * That's true! There is a very simple way to reduce the driver - * object by 33%! Comment out the following line: - * #include - * Other compile options can also reduce the size of it... - * - * MAC address and hardware detection: - * ----------------------------------- - * The detection code for the WaveLAN checks that the first three - * octets of the MAC address fit the company code. This type of - * detection works well for AT&T cards (because the AT&T code is - * hardcoded in wavelan.h), but of course will fail for other - * manufacturers. - * - * If you are sure that your card is derived from the WaveLAN, - * here is the way to configure it: - * 1) Get your MAC address - * a) With your card utilities (wfreqsel, instconf, etc.) - * b) With the driver: - * o compile the kernel with DEBUG_CONFIG_INFO enabled - * o Boot and look the card messages - * 2) Set your MAC code (3 octets) in MAC_ADDRESSES[][3] (wavelan.h) - * 3) Compile and verify - * 4) Send me the MAC code. I will include it in the next version. - * - */ - -/* --------------------- WIRELESS EXTENSIONS --------------------- */ -/* - * This driver is the first to support "wireless extensions". - * This set of extensions provides a standard way to control the wireless - * characteristics of the hardware. Applications such as mobile IP may - * take advantage of it. - * - * It might be a good idea as well to fetch the wireless tools to - * configure the device and play a bit. - */ - -/* ---------------------------- FILES ---------------------------- */ -/* - * wavelan.c: actual code for the driver: C functions - * - * wavelan.p.h: private header: local types and variables for driver - * - * wavelan.h: description of the hardware interface and structs - * - * i82586.h: description of the Ethernet controller - */ - -/* --------------------------- HISTORY --------------------------- */ -/* - * This is based on information in the drivers' headers. It may not be - * accurate, and I guarantee only my best effort. - * - * The history of the WaveLAN drivers is as complicated as the history of - * the WaveLAN itself (NCR -> AT&T -> Lucent). - * - * It all started with Anders Klemets - * writing a WaveLAN ISA driver for the Mach microkernel. Girish - * Welling had also worked on it. - * Keith Moore modified this for the PCMCIA hardware. - * - * Robert Morris ported these two drivers to BSDI - * and added specific PCMCIA support (there is currently no equivalent - * of the PCMCIA package under BSD). - * - * Jim Binkley ported both BSDI drivers to FreeBSD. - * - * Bruce Janson ported the BSDI ISA driver to Linux. - * - * Anthony D. Joseph started to modify Bruce's driver - * (with help of the BSDI PCMCIA driver) for PCMCIA. - * Yunzhou Li finished this work. - * Joe Finney patched the driver to start - * 2.00 cards correctly (2.4 GHz with frequency selection). - * David Hinds integrated the whole in his - * PCMCIA package (and bug corrections). - * - * I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some - * patches to the PCMCIA driver. Later, I added code in the ISA driver - * for Wireless Extensions and full support of frequency selection - * cards. Then, I did the same to the PCMCIA driver, and did some - * reorganisation. Finally, I came back to the ISA driver to - * upgrade it at the same level as the PCMCIA one and reorganise - * the code. - * Loeke Brederveld from Lucent has given me - * much needed information on the WaveLAN hardware. - */ - -/* The original copyrights and literature mention others' names and - * credits. I don't know what their part in this development was. - */ - -/* By the way, for the copyright and legal stuff: - * almost everybody wrote code under the GNU or BSD license (or similar), - * and want their original copyright to remain somewhere in the - * code (for myself, I go with the GPL). - * Nobody wants to take responsibility for anything, except the fame. - */ - -/* --------------------------- CREDITS --------------------------- */ -/* - * This software was developed as a component of the - * Linux operating system. - * It is based on other device drivers and information - * either written or supplied by: - * Ajay Bakre , - * Donald Becker , - * Loeke Brederveld , - * Brent Elphick , - * Anders Klemets , - * Vladimir V. Kolpakov , - * Marc Meertens , - * Pauline Middelink , - * Robert Morris , - * Jean Tourrilhes , - * Girish Welling , - * Clark Woodworth - * Yongguang Zhang - * - * Thanks go also to: - * James Ashton , - * Alan Cox , - * Allan Creighton , - * Matthew Geier , - * Remo di Giovanni , - * Eckhard Grah , - * Vipul Gupta , - * Mark Hagan , - * Tim Nicholson , - * Ian Parkin , - * John Rosenberg , - * George Rossi , - * Arthur Scott , - * Stanislav Sinyagin - * and Peter Storey for their assistance and advice. - * - * Additional Credits: - * - * My development has been done initially under Debian 1.1 (Linux 2.0.x) - * and now under Debian 2.2, initially with an HP Vectra XP/60, and now - * an HP Vectra XP/90. - * - */ - -/* ------------------------- IMPROVEMENTS ------------------------- */ -/* - * I proudly present: - * - * Changes made in first pre-release: - * ---------------------------------- - * - reorganisation of the code, function name change - * - creation of private header (wavelan.p.h) - * - reorganised debug messages - * - more comments, history, etc. - * - mmc_init: configure the PSA if not done - * - mmc_init: correct default value of level threshold for PCMCIA - * - mmc_init: 2.00 detection better code for 2.00 initialization - * - better info at startup - * - IRQ setting (note: this setting is permanent) - * - watchdog: change strategy (and solve module removal problems) - * - add wireless extensions (ioctl and get_wireless_stats) - * get/set nwid/frequency on fly, info for /proc/net/wireless - * - more wireless extensions: SETSPY and GETSPY - * - make wireless extensions optional - * - private ioctl to set/get quality and level threshold, histogram - * - remove /proc/net/wavelan - * - suppress useless stuff from lp (net_local) - * - kernel 2.1 support (copy_to/from_user instead of memcpy_to/fromfs) - * - add message level (debug stuff in /var/adm/debug and errors not - * displayed at console and still in /var/adm/messages) - * - multi device support - * - start fixing the probe (init code) - * - more inlines - * - man page - * - many other minor details and cleanups - * - * Changes made in second pre-release: - * ----------------------------------- - * - clean up init code (probe and module init) - * - better multiple device support (module) - * - name assignment (module) - * - * Changes made in third pre-release: - * ---------------------------------- - * - be more conservative on timers - * - preliminary support for multicast (I still lack some details) - * - * Changes made in fourth pre-release: - * ----------------------------------- - * - multicast (revisited and finished) - * - avoid reset in set_multicast_list (a really big hack) - * if somebody could apply this code for other i82586 based drivers - * - share onboard memory 75% RU and 25% CU (instead of 50/50) - * - * Changes made for release in 2.1.15: - * ----------------------------------- - * - change the detection code for multi manufacturer code support - * - * Changes made for release in 2.1.17: - * ----------------------------------- - * - update to wireless extensions changes - * - silly bug in card initial configuration (psa_conf_status) - * - * Changes made for release in 2.1.27 & 2.0.30: - * -------------------------------------------- - * - small bug in debug code (probably not the last one...) - * - remove extern keyword for wavelan_probe() - * - level threshold is now a standard wireless extension (version 4 !) - * - modules parameters types (new module interface) - * - * Changes made for release in 2.1.36: - * ----------------------------------- - * - byte count stats (courtesy of David Hinds) - * - remove dev_tint stuff (courtesy of David Hinds) - * - encryption setting from Brent Elphick (thanks a lot!) - * - 'ioaddr' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin) - * - * Other changes (not by me) : - * ------------------------- - * - Spelling and gramar "rectification". - * - * Changes made for release in 2.0.37 & 2.2.2 : - * ------------------------------------------ - * - Correct status in /proc/net/wireless - * - Set PSA CRC to make PtP diagnostic tool happy (Bob Gray) - * - Module init code don't fail if we found at least one card in - * the address list (Karlis Peisenieks) - * - Missing parenthesis (Christopher Peterson) - * - Correct i82586 configuration parameters - * - Encryption initialisation bug (Robert McCormack) - * - New mac addresses detected in the probe - * - Increase watchdog for busy environments - * - * Changes made for release in 2.0.38 & 2.2.7 : - * ------------------------------------------ - * - Correct the reception logic to better report errors and avoid - * sending bogus packet up the stack - * - Delay RU config to avoid corrupting first received packet - * - Change config completion code (to actually check something) - * - Avoid reading out of bound in skbuf to transmit - * - Rectify a lot of (useless) debugging code - * - Change the way to `#ifdef SET_PSA_CRC' - * - * Changes made for release in 2.2.11 & 2.3.13 : - * ------------------------------------------- - * - Change e-mail and web page addresses - * - Watchdog timer is now correctly expressed in HZ, not in jiffies - * - Add channel number to the list of frequencies in range - * - Add the (short) list of bit-rates in range - * - Developp a new sensitivity... (sens.value & sens.fixed) - * - * Changes made for release in 2.2.14 & 2.3.23 : - * ------------------------------------------- - * - Fix check for root permission (break instead of exit) - * - New nwid & encoding setting (Wireless Extension 9) - * - * Changes made for release in 2.3.49 : - * ---------------------------------- - * - Indentation reformating (Alan) - * - Update to new network API (softnet - 2.3.43) : - * o replace dev->tbusy (Alan) - * o replace dev->tstart (Alan) - * o remove dev->interrupt (Alan) - * o add SMP locking via spinlock in splxx (me) - * o add spinlock in interrupt handler (me) - * o use kernel watchdog instead of ours (me) - * o increase watchdog timeout (kernel is more sensitive) (me) - * o verify that all the changes make sense and work (me) - * - Fixup a potential gotcha when reconfiguring and thighten a bit - * the interactions with Tx queue. - * - * Changes made for release in 2.4.0 : - * --------------------------------- - * - Fix spinlock stupid bugs that I left in. The driver is now SMP - * compliant and doesn't lockup at startup. - * - * Changes made for release in 2.5.2 : - * --------------------------------- - * - Use new driver API for Wireless Extensions : - * o got rid of wavelan_ioctl() - * o use a bunch of iw_handler instead - * - * Changes made for release in 2.5.35 : - * ---------------------------------- - * - Set dev->trans_start to avoid filling the logs - * - Handle better spurious/bogus interrupt - * - Avoid deadlocks in mmc_out()/mmc_in() - * - * Wishes & dreams: - * ---------------- - * - roaming (see Pcmcia driver) - */ - -/***************************** INCLUDES *****************************/ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* Wireless extensions */ -#include /* Wireless handlers */ - -/* WaveLAN declarations */ -#include "i82586.h" -#include "wavelan.h" - -/************************** DRIVER OPTIONS **************************/ -/* - * `#define' or `#undef' the following constant to change the behaviour - * of the driver... - */ -#undef SET_PSA_CRC /* Calculate and set the CRC on PSA (slower) */ -#define USE_PSA_CONFIG /* Use info from the PSA. */ -#undef EEPROM_IS_PROTECTED /* doesn't seem to be necessary */ -#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical). */ -#undef SET_MAC_ADDRESS /* Experimental */ - -/* Warning: this stuff will slow down the driver. */ -#define WIRELESS_SPY /* Enable spying addresses. */ -#undef HISTOGRAM /* Enable histogram of signal level. */ - -/****************************** DEBUG ******************************/ - -#undef DEBUG_MODULE_TRACE /* module insertion/removal */ -#undef DEBUG_CALLBACK_TRACE /* calls made by Linux */ -#undef DEBUG_INTERRUPT_TRACE /* calls to handler */ -#undef DEBUG_INTERRUPT_INFO /* type of interrupt and so on */ -#define DEBUG_INTERRUPT_ERROR /* problems */ -#undef DEBUG_CONFIG_TRACE /* Trace the config functions. */ -#undef DEBUG_CONFIG_INFO /* what's going on */ -#define DEBUG_CONFIG_ERROR /* errors on configuration */ -#undef DEBUG_TX_TRACE /* transmission calls */ -#undef DEBUG_TX_INFO /* header of the transmitted packet */ -#undef DEBUG_TX_FAIL /* Normal failure conditions */ -#define DEBUG_TX_ERROR /* Unexpected conditions */ -#undef DEBUG_RX_TRACE /* transmission calls */ -#undef DEBUG_RX_INFO /* header of the received packet */ -#undef DEBUG_RX_FAIL /* Normal failure conditions */ -#define DEBUG_RX_ERROR /* Unexpected conditions */ - -#undef DEBUG_PACKET_DUMP /* Dump packet on the screen if defined to 32. */ -#undef DEBUG_IOCTL_TRACE /* misc. call by Linux */ -#undef DEBUG_IOCTL_INFO /* various debugging info */ -#define DEBUG_IOCTL_ERROR /* what's going wrong */ -#define DEBUG_BASIC_SHOW /* Show basic startup info. */ -#undef DEBUG_VERSION_SHOW /* Print version info. */ -#undef DEBUG_PSA_SHOW /* Dump PSA to screen. */ -#undef DEBUG_MMC_SHOW /* Dump mmc to screen. */ -#undef DEBUG_SHOW_UNUSED /* Show unused fields too. */ -#undef DEBUG_I82586_SHOW /* Show i82586 status. */ -#undef DEBUG_DEVICE_SHOW /* Show device parameters. */ - -/************************ CONSTANTS & MACROS ************************/ - -#ifdef DEBUG_VERSION_SHOW -static const char *version = "wavelan.c : v24 (SMP + wireless extensions) 11/12/01\n"; -#endif - -/* Watchdog temporisation */ -#define WATCHDOG_JIFFIES (512*HZ/100) - -/* ------------------------ PRIVATE IOCTL ------------------------ */ - -#define SIOCSIPQTHR SIOCIWFIRSTPRIV /* Set quality threshold */ -#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1 /* Get quality threshold */ - -#define SIOCSIPHISTO SIOCIWFIRSTPRIV + 2 /* Set histogram ranges */ -#define SIOCGIPHISTO SIOCIWFIRSTPRIV + 3 /* Get histogram values */ - -/****************************** TYPES ******************************/ - -/* Shortcuts */ -typedef struct iw_statistics iw_stats; -typedef struct iw_quality iw_qual; -typedef struct iw_freq iw_freq;typedef struct net_local net_local; -typedef struct timer_list timer_list; - -/* Basic types */ -typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ - -/* - * Static specific data for the interface. - * - * For each network interface, Linux keeps data in two structures: "device" - * keeps the generic data (same format for everybody) and "net_local" keeps - * additional specific data. - */ -struct net_local -{ - net_local * next; /* linked list of the devices */ - struct net_device * dev; /* reverse link */ - spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ - int nresets; /* number of hardware resets */ - u_char reconfig_82586; /* We need to reconfigure the controller. */ - u_char promiscuous; /* promiscuous mode */ - int mc_count; /* number of multicast addresses */ - u_short hacr; /* current host interface state */ - - int tx_n_in_use; - u_short rx_head; - u_short rx_last; - u_short tx_first_free; - u_short tx_first_in_use; - - iw_stats wstats; /* Wireless-specific statistics */ - - struct iw_spy_data spy_data; - struct iw_public_data wireless_data; - -#ifdef HISTOGRAM - int his_number; /* number of intervals */ - u_char his_range[16]; /* boundaries of interval ]n-1; n] */ - u_long his_sum[16]; /* sum in interval */ -#endif /* HISTOGRAM */ -}; - -/**************************** PROTOTYPES ****************************/ - -/* ----------------------- MISC. SUBROUTINES ------------------------ */ -static u_char - wv_irq_to_psa(int); -static int - wv_psa_to_irq(u_char); -/* ------------------- HOST ADAPTER SUBROUTINES ------------------- */ -static inline u_short /* data */ - hasr_read(u_long); /* Read the host interface: base address */ -static inline void - hacr_write(u_long, /* Write to host interface: base address */ - u_short), /* data */ - hacr_write_slow(u_long, - u_short), - set_chan_attn(u_long, /* ioaddr */ - u_short), /* hacr */ - wv_hacr_reset(u_long), /* ioaddr */ - wv_16_off(u_long, /* ioaddr */ - u_short), /* hacr */ - wv_16_on(u_long, /* ioaddr */ - u_short), /* hacr */ - wv_ints_off(struct net_device *), - wv_ints_on(struct net_device *); -/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ -static void - psa_read(u_long, /* Read the Parameter Storage Area. */ - u_short, /* hacr */ - int, /* offset in PSA */ - u_char *, /* buffer to fill */ - int), /* size to read */ - psa_write(u_long, /* Write to the PSA. */ - u_short, /* hacr */ - int, /* offset in PSA */ - u_char *, /* buffer in memory */ - int); /* length of buffer */ -static inline void - mmc_out(u_long, /* Write 1 byte to the Modem Manag Control. */ - u_short, - u_char), - mmc_write(u_long, /* Write n bytes to the MMC. */ - u_char, - u_char *, - int); -static inline u_char /* Read 1 byte from the MMC. */ - mmc_in(u_long, - u_short); -static inline void - mmc_read(u_long, /* Read n bytes from the MMC. */ - u_char, - u_char *, - int), - fee_wait(u_long, /* Wait for frequency EEPROM: base address */ - int, /* base delay to wait for */ - int); /* time to wait */ -static void - fee_read(u_long, /* Read the frequency EEPROM: base address */ - u_short, /* destination offset */ - u_short *, /* data buffer */ - int); /* number of registers */ -/* ---------------------- I82586 SUBROUTINES ----------------------- */ -static /*inline*/ void - obram_read(u_long, /* ioaddr */ - u_short, /* o */ - u_char *, /* b */ - int); /* n */ -static inline void - obram_write(u_long, /* ioaddr */ - u_short, /* o */ - u_char *, /* b */ - int); /* n */ -static void - wv_ack(struct net_device *); -static inline int - wv_synchronous_cmd(struct net_device *, - const char *), - wv_config_complete(struct net_device *, - u_long, - net_local *); -static int - wv_complete(struct net_device *, - u_long, - net_local *); -static inline void - wv_82586_reconfig(struct net_device *); -/* ------------------- DEBUG & INFO SUBROUTINES ------------------- */ -#ifdef DEBUG_I82586_SHOW -static void - wv_scb_show(unsigned short); -#endif -static inline void - wv_init_info(struct net_device *); /* display startup info */ -/* ------------------- IOCTL, STATS & RECONFIG ------------------- */ -static iw_stats * - wavelan_get_wireless_stats(struct net_device *); -static void - wavelan_set_multicast_list(struct net_device *); -/* ----------------------- PACKET RECEPTION ----------------------- */ -static inline void - wv_packet_read(struct net_device *, /* Read a packet from a frame. */ - u_short, - int), - wv_receive(struct net_device *); /* Read all packets waiting. */ -/* --------------------- PACKET TRANSMISSION --------------------- */ -static inline int - wv_packet_write(struct net_device *, /* Write a packet to the Tx buffer. */ - void *, - short); -static netdev_tx_t - wavelan_packet_xmit(struct sk_buff *, /* Send a packet. */ - struct net_device *); -/* -------------------- HARDWARE CONFIGURATION -------------------- */ -static inline int - wv_mmc_init(struct net_device *), /* Initialize the modem. */ - wv_ru_start(struct net_device *), /* Start the i82586 receiver unit. */ - wv_cu_start(struct net_device *), /* Start the i82586 command unit. */ - wv_82586_start(struct net_device *); /* Start the i82586. */ -static void - wv_82586_config(struct net_device *); /* Configure the i82586. */ -static inline void - wv_82586_stop(struct net_device *); -static int - wv_hw_reset(struct net_device *), /* Reset the WaveLAN hardware. */ - wv_check_ioaddr(u_long, /* ioaddr */ - u_char *); /* mac address (read) */ -/* ---------------------- INTERRUPT HANDLING ---------------------- */ -static irqreturn_t - wavelan_interrupt(int, /* interrupt handler */ - void *); -static void - wavelan_watchdog(struct net_device *); /* transmission watchdog */ -/* ------------------- CONFIGURATION CALLBACKS ------------------- */ -static int - wavelan_open(struct net_device *), /* Open the device. */ - wavelan_close(struct net_device *), /* Close the device. */ - wavelan_config(struct net_device *, unsigned short);/* Configure one device. */ -extern struct net_device *wavelan_probe(int unit); /* See Space.c. */ - -/**************************** VARIABLES ****************************/ - -/* - * This is the root of the linked list of WaveLAN drivers - * It is use to verify that we don't reuse the same base address - * for two different drivers and to clean up when removing the module. - */ -static net_local * wavelan_list = (net_local *) NULL; - -/* - * This table is used to translate the PSA value to IRQ number - * and vice versa. - */ -static u_char irqvals[] = -{ - 0, 0, 0, 0x01, - 0x02, 0x04, 0, 0x08, - 0, 0, 0x10, 0x20, - 0x40, 0, 0, 0x80, -}; - -/* - * Table of the available I/O addresses (base addresses) for WaveLAN - */ -static unsigned short iobase[] = -{ -#if 0 - /* Leave out 0x3C0 for now -- seems to clash with some video - * controllers. - * Leave out the others too -- we will always use 0x390 and leave - * 0x300 for the Ethernet device. - * Jean II: 0x3E0 is fine as well. - */ - 0x300, 0x390, 0x3E0, 0x3C0 -#endif /* 0 */ - 0x390, 0x3E0 -}; - -#ifdef MODULE -/* Parameters set by insmod */ -static int io[4]; -static int irq[4]; -static char *name[4]; -module_param_array(io, int, NULL, 0); -module_param_array(irq, int, NULL, 0); -module_param_array(name, charp, NULL, 0); - -MODULE_PARM_DESC(io, "WaveLAN I/O base address(es),required"); -MODULE_PARM_DESC(irq, "WaveLAN IRQ number(s)"); -MODULE_PARM_DESC(name, "WaveLAN interface neme(s)"); -#endif /* MODULE */ - -#endif /* WAVELAN_P_H */ diff --git a/drivers/net/wireless/wavelan_cs.c b/drivers/net/wireless/wavelan_cs.c deleted file mode 100644 index 431a20ec6db6..000000000000 --- a/drivers/net/wireless/wavelan_cs.c +++ /dev/null @@ -1,4635 +0,0 @@ -/* - * Wavelan Pcmcia driver - * - * Jean II - HPLB '96 - * - * Reorganisation and extension of the driver. - * Original copyright follow. See wavelan_cs.p.h for details. - * - * This code is derived from Anthony D. Joseph's code and all the changes here - * are also under the original copyright below. - * - * This code supports version 2.00 of WaveLAN/PCMCIA cards (2.4GHz), and - * can work on Linux 2.0.36 with support of David Hinds' PCMCIA Card Services - * - * Joe Finney (joe@comp.lancs.ac.uk) at Lancaster University in UK added - * critical code in the routine to initialize the Modem Management Controller. - * - * Thanks to Alan Cox and Bruce Janson for their advice. - * - * -- Yunzhou Li (scip4166@nus.sg) - * -#ifdef WAVELAN_ROAMING - * Roaming support added 07/22/98 by Justin Seger (jseger@media.mit.edu) - * based on patch by Joe Finney from Lancaster University. -#endif - * - * Lucent (formerly AT&T GIS, formerly NCR) WaveLAN PCMCIA card: An - * Ethernet-like radio transceiver controlled by an Intel 82593 coprocessor. - * - * A non-shared memory PCMCIA ethernet driver for linux - * - * ISA version modified to support PCMCIA by Anthony Joseph (adj@lcs.mit.edu) - * - * - * Joseph O'Sullivan & John Langford (josullvn@cs.cmu.edu & jcl@cs.cmu.edu) - * - * Apr 2 '98 made changes to bring the i82593 control/int handling in line - * with offical specs... - * - **************************************************************************** - * Copyright 1995 - * Anthony D. Joseph - * Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this program - * for any purpose and without fee is hereby granted, provided - * that this copyright and permission notice appear on all copies - * and supporting documentation, the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * program without specific prior permission, and notice be given - * in supporting documentation that copying and distribution is - * by permission of M.I.T. M.I.T. makes no representations about - * the suitability of this software for any purpose. It is pro- - * vided "as is" without express or implied warranty. - **************************************************************************** - * - */ - -/* Do *NOT* add other headers here, you are guaranteed to be wrong - Jean II */ -#include "wavelan_cs.p.h" /* Private header */ - -#ifdef WAVELAN_ROAMING -static void wl_cell_expiry(unsigned long data); -static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp); -static void wv_nwid_filter(unsigned char mode, net_local *lp); -#endif /* WAVELAN_ROAMING */ - -/************************* MISC SUBROUTINES **************************/ -/* - * Subroutines which won't fit in one of the following category - * (wavelan modem or i82593) - */ - -/******************* MODEM MANAGEMENT SUBROUTINES *******************/ -/* - * Useful subroutines to manage the modem of the wavelan - */ - -/*------------------------------------------------------------------*/ -/* - * Read from card's Host Adaptor Status Register. - */ -static inline u_char -hasr_read(u_long base) -{ - return(inb(HASR(base))); -} /* hasr_read */ - -/*------------------------------------------------------------------*/ -/* - * Write to card's Host Adapter Command Register. - */ -static inline void -hacr_write(u_long base, - u_char hacr) -{ - outb(hacr, HACR(base)); -} /* hacr_write */ - -/*------------------------------------------------------------------*/ -/* - * Write to card's Host Adapter Command Register. Include a delay for - * those times when it is needed. - */ -static void -hacr_write_slow(u_long base, - u_char hacr) -{ - hacr_write(base, hacr); - /* delay might only be needed sometimes */ - mdelay(1); -} /* hacr_write_slow */ - -/*------------------------------------------------------------------*/ -/* - * Read the Parameter Storage Area from the WaveLAN card's memory - */ -static void -psa_read(struct net_device * dev, - int o, /* offset in PSA */ - u_char * b, /* buffer to fill */ - int n) /* size to read */ -{ - net_local *lp = netdev_priv(dev); - u_char __iomem *ptr = lp->mem + PSA_ADDR + (o << 1); - - while(n-- > 0) - { - *b++ = readb(ptr); - /* Due to a lack of address decode pins, the WaveLAN PCMCIA card - * only supports reading even memory addresses. That means the - * increment here MUST be two. - * Because of that, we can't use memcpy_fromio()... - */ - ptr += 2; - } -} /* psa_read */ - -/*------------------------------------------------------------------*/ -/* - * Write the Parameter Storage Area to the WaveLAN card's memory - */ -static void -psa_write(struct net_device * dev, - int o, /* Offset in psa */ - u_char * b, /* Buffer in memory */ - int n) /* Length of buffer */ -{ - net_local *lp = netdev_priv(dev); - u_char __iomem *ptr = lp->mem + PSA_ADDR + (o << 1); - int count = 0; - unsigned int base = dev->base_addr; - /* As there seem to have no flag PSA_BUSY as in the ISA model, we are - * oblige to verify this address to know when the PSA is ready... */ - volatile u_char __iomem *verify = lp->mem + PSA_ADDR + - (psaoff(0, psa_comp_number) << 1); - - /* Authorize writing to PSA */ - hacr_write(base, HACR_PWR_STAT | HACR_ROM_WEN); - - while(n-- > 0) - { - /* write to PSA */ - writeb(*b++, ptr); - ptr += 2; - - /* I don't have the spec, so I don't know what the correct - * sequence to write is. This hack seem to work for me... */ - count = 0; - while((readb(verify) != PSA_COMP_PCMCIA_915) && (count++ < 100)) - mdelay(1); - } - - /* Put the host interface back in standard state */ - hacr_write(base, HACR_DEFAULT); -} /* psa_write */ - -#ifdef SET_PSA_CRC -/*------------------------------------------------------------------*/ -/* - * Calculate the PSA CRC - * Thanks to Valster, Nico for the code - * NOTE: By specifying a length including the CRC position the - * returned value should be zero. (i.e. a correct checksum in the PSA) - * - * The Windows drivers don't use the CRC, but the AP and the PtP tool - * depend on it. - */ -static u_short -psa_crc(unsigned char * psa, /* The PSA */ - int size) /* Number of short for CRC */ -{ - int byte_cnt; /* Loop on the PSA */ - u_short crc_bytes = 0; /* Data in the PSA */ - int bit_cnt; /* Loop on the bits of the short */ - - for(byte_cnt = 0; byte_cnt < size; byte_cnt++ ) - { - crc_bytes ^= psa[byte_cnt]; /* Its an xor */ - - for(bit_cnt = 1; bit_cnt < 9; bit_cnt++ ) - { - if(crc_bytes & 0x0001) - crc_bytes = (crc_bytes >> 1) ^ 0xA001; - else - crc_bytes >>= 1 ; - } - } - - return crc_bytes; -} /* psa_crc */ -#endif /* SET_PSA_CRC */ - -/*------------------------------------------------------------------*/ -/* - * update the checksum field in the Wavelan's PSA - */ -static void -update_psa_checksum(struct net_device * dev) -{ -#ifdef SET_PSA_CRC - psa_t psa; - u_short crc; - - /* read the parameter storage area */ - psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); - - /* update the checksum */ - crc = psa_crc((unsigned char *) &psa, - sizeof(psa) - sizeof(psa.psa_crc[0]) - sizeof(psa.psa_crc[1]) - - sizeof(psa.psa_crc_status)); - - psa.psa_crc[0] = crc & 0xFF; - psa.psa_crc[1] = (crc & 0xFF00) >> 8; - - /* Write it ! */ - psa_write(dev, (char *)&psa.psa_crc - (char *)&psa, - (unsigned char *)&psa.psa_crc, 2); - -#ifdef DEBUG_IOCTL_INFO - printk (KERN_DEBUG "%s: update_psa_checksum(): crc = 0x%02x%02x\n", - dev->name, psa.psa_crc[0], psa.psa_crc[1]); - - /* Check again (luxury !) */ - crc = psa_crc((unsigned char *) &psa, - sizeof(psa) - sizeof(psa.psa_crc_status)); - - if(crc != 0) - printk(KERN_WARNING "%s: update_psa_checksum(): CRC does not agree with PSA data (even after recalculating)\n", dev->name); -#endif /* DEBUG_IOCTL_INFO */ -#endif /* SET_PSA_CRC */ -} /* update_psa_checksum */ - -/*------------------------------------------------------------------*/ -/* - * Write 1 byte to the MMC. - */ -static void -mmc_out(u_long base, - u_short o, - u_char d) -{ - int count = 0; - - /* Wait for MMC to go idle */ - while((count++ < 100) && (inb(HASR(base)) & HASR_MMI_BUSY)) - udelay(10); - - outb((u_char)((o << 1) | MMR_MMI_WR), MMR(base)); - outb(d, MMD(base)); -} - -/*------------------------------------------------------------------*/ -/* - * Routine to write bytes to the Modem Management Controller. - * We start by the end because it is the way it should be ! - */ -static void -mmc_write(u_long base, - u_char o, - u_char * b, - int n) -{ - o += n; - b += n; - - while(n-- > 0 ) - mmc_out(base, --o, *(--b)); -} /* mmc_write */ - -/*------------------------------------------------------------------*/ -/* - * Read 1 byte from the MMC. - * Optimised version for 1 byte, avoid using memory... - */ -static u_char -mmc_in(u_long base, - u_short o) -{ - int count = 0; - - while((count++ < 100) && (inb(HASR(base)) & HASR_MMI_BUSY)) - udelay(10); - outb(o << 1, MMR(base)); /* Set the read address */ - - outb(0, MMD(base)); /* Required dummy write */ - - while((count++ < 100) && (inb(HASR(base)) & HASR_MMI_BUSY)) - udelay(10); - return (u_char) (inb(MMD(base))); /* Now do the actual read */ -} - -/*------------------------------------------------------------------*/ -/* - * Routine to read bytes from the Modem Management Controller. - * The implementation is complicated by a lack of address lines, - * which prevents decoding of the low-order bit. - * (code has just been moved in the above function) - * We start by the end because it is the way it should be ! - */ -static void -mmc_read(u_long base, - u_char o, - u_char * b, - int n) -{ - o += n; - b += n; - - while(n-- > 0) - *(--b) = mmc_in(base, --o); -} /* mmc_read */ - -/*------------------------------------------------------------------*/ -/* - * Get the type of encryption available... - */ -static inline int -mmc_encr(u_long base) /* i/o port of the card */ -{ - int temp; - - temp = mmc_in(base, mmroff(0, mmr_des_avail)); - if((temp != MMR_DES_AVAIL_DES) && (temp != MMR_DES_AVAIL_AES)) - return 0; - else - return temp; -} - -/*------------------------------------------------------------------*/ -/* - * Wait for the frequency EEprom to complete a command... - */ -static void -fee_wait(u_long base, /* i/o port of the card */ - int delay, /* Base delay to wait for */ - int number) /* Number of time to wait */ -{ - int count = 0; /* Wait only a limited time */ - - while((count++ < number) && - (mmc_in(base, mmroff(0, mmr_fee_status)) & MMR_FEE_STATUS_BUSY)) - udelay(delay); -} - -/*------------------------------------------------------------------*/ -/* - * Read bytes from the Frequency EEprom (frequency select cards). - */ -static void -fee_read(u_long base, /* i/o port of the card */ - u_short o, /* destination offset */ - u_short * b, /* data buffer */ - int n) /* number of registers */ -{ - b += n; /* Position at the end of the area */ - - /* Write the address */ - mmc_out(base, mmwoff(0, mmw_fee_addr), o + n - 1); - - /* Loop on all buffer */ - while(n-- > 0) - { - /* Write the read command */ - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_READ); - - /* Wait until EEprom is ready (should be quick !) */ - fee_wait(base, 10, 100); - - /* Read the value */ - *--b = ((mmc_in(base, mmroff(0, mmr_fee_data_h)) << 8) | - mmc_in(base, mmroff(0, mmr_fee_data_l))); - } -} - - -/*------------------------------------------------------------------*/ -/* - * Write bytes from the Frequency EEprom (frequency select cards). - * This is a bit complicated, because the frequency eeprom has to - * be unprotected and the write enabled. - * Jean II - */ -static void -fee_write(u_long base, /* i/o port of the card */ - u_short o, /* destination offset */ - u_short * b, /* data buffer */ - int n) /* number of registers */ -{ - b += n; /* Position at the end of the area */ - -#ifdef EEPROM_IS_PROTECTED /* disabled */ -#ifdef DOESNT_SEEM_TO_WORK /* disabled */ - /* Ask to read the protected register */ - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRREAD); - - fee_wait(base, 10, 100); - - /* Read the protected register */ - printk("Protected 2 : %02X-%02X\n", - mmc_in(base, mmroff(0, mmr_fee_data_h)), - mmc_in(base, mmroff(0, mmr_fee_data_l))); -#endif /* DOESNT_SEEM_TO_WORK */ - - /* Enable protected register */ - mmc_out(base, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PREN); - - fee_wait(base, 10, 100); - - /* Unprotect area */ - mmc_out(base, mmwoff(0, mmw_fee_addr), o + n); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); -#ifdef DOESNT_SEEM_TO_WORK /* disabled */ - /* Or use : */ - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRCLEAR); -#endif /* DOESNT_SEEM_TO_WORK */ - - fee_wait(base, 10, 100); -#endif /* EEPROM_IS_PROTECTED */ - - /* Write enable */ - mmc_out(base, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_EN); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WREN); - - fee_wait(base, 10, 100); - - /* Write the EEprom address */ - mmc_out(base, mmwoff(0, mmw_fee_addr), o + n - 1); - - /* Loop on all buffer */ - while(n-- > 0) - { - /* Write the value */ - mmc_out(base, mmwoff(0, mmw_fee_data_h), (*--b) >> 8); - mmc_out(base, mmwoff(0, mmw_fee_data_l), *b & 0xFF); - - /* Write the write command */ - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WRITE); - - /* Wavelan doc says : wait at least 10 ms for EEBUSY = 0 */ - mdelay(10); - fee_wait(base, 10, 100); - } - - /* Write disable */ - mmc_out(base, mmwoff(0, mmw_fee_addr), MMW_FEE_ADDR_DS); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_WDS); - - fee_wait(base, 10, 100); - -#ifdef EEPROM_IS_PROTECTED /* disabled */ - /* Reprotect EEprom */ - mmc_out(base, mmwoff(0, mmw_fee_addr), 0x00); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), MMW_FEE_CTRL_PRWRITE); - - fee_wait(base, 10, 100); -#endif /* EEPROM_IS_PROTECTED */ -} - -/******************* WaveLAN Roaming routines... ********************/ - -#ifdef WAVELAN_ROAMING /* Conditional compile, see wavelan_cs.h */ - -static unsigned char WAVELAN_BEACON_ADDRESS[] = {0x09,0x00,0x0e,0x20,0x03,0x00}; - -static void wv_roam_init(struct net_device *dev) -{ - net_local *lp= netdev_priv(dev); - - /* Do not remove this unless you have a good reason */ - printk(KERN_NOTICE "%s: Warning, you have enabled roaming on" - " device %s !\n", dev->name, dev->name); - printk(KERN_NOTICE "Roaming is currently an experimental unsupported feature" - " of the Wavelan driver.\n"); - printk(KERN_NOTICE "It may work, but may also make the driver behave in" - " erratic ways or crash.\n"); - - lp->wavepoint_table.head=NULL; /* Initialise WavePoint table */ - lp->wavepoint_table.num_wavepoints=0; - lp->wavepoint_table.locked=0; - lp->curr_point=NULL; /* No default WavePoint */ - lp->cell_search=0; - - lp->cell_timer.data=(long)lp; /* Start cell expiry timer */ - lp->cell_timer.function=wl_cell_expiry; - lp->cell_timer.expires=jiffies+CELL_TIMEOUT; - add_timer(&lp->cell_timer); - - wv_nwid_filter(NWID_PROMISC,lp) ; /* Enter NWID promiscuous mode */ - /* to build up a good WavePoint */ - /* table... */ - printk(KERN_DEBUG "WaveLAN: Roaming enabled on device %s\n",dev->name); -} - -static void wv_roam_cleanup(struct net_device *dev) -{ - wavepoint_history *ptr,*old_ptr; - net_local *lp= netdev_priv(dev); - - printk(KERN_DEBUG "WaveLAN: Roaming Disabled on device %s\n",dev->name); - - /* Fixme : maybe we should check that the timer exist before deleting it */ - del_timer(&lp->cell_timer); /* Remove cell expiry timer */ - ptr=lp->wavepoint_table.head; /* Clear device's WavePoint table */ - while(ptr!=NULL) - { - old_ptr=ptr; - ptr=ptr->next; - wl_del_wavepoint(old_ptr,lp); - } -} - -/* Enable/Disable NWID promiscuous mode on a given device */ -static void wv_nwid_filter(unsigned char mode, net_local *lp) -{ - mm_t m; - unsigned long flags; - -#ifdef WAVELAN_ROAMING_DEBUG - printk(KERN_DEBUG "WaveLAN: NWID promisc %s, device %s\n",(mode==NWID_PROMISC) ? "on" : "off", lp->dev->name); -#endif - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&lp->spinlock, flags); - - m.w.mmw_loopt_sel = (mode==NWID_PROMISC) ? MMW_LOOPT_SEL_DIS_NWID : 0x00; - mmc_write(lp->dev->base_addr, (char *)&m.w.mmw_loopt_sel - (char *)&m, (unsigned char *)&m.w.mmw_loopt_sel, 1); - - if(mode==NWID_PROMISC) - lp->cell_search=1; - else - lp->cell_search=0; - - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore(&lp->spinlock, flags); -} - -/* Find a record in the WavePoint table matching a given NWID */ -static wavepoint_history *wl_roam_check(unsigned short nwid, net_local *lp) -{ - wavepoint_history *ptr=lp->wavepoint_table.head; - - while(ptr!=NULL){ - if(ptr->nwid==nwid) - return ptr; - ptr=ptr->next; - } - return NULL; -} - -/* Create a new wavepoint table entry */ -static wavepoint_history *wl_new_wavepoint(unsigned short nwid, unsigned char seq, net_local* lp) -{ - wavepoint_history *new_wavepoint; - -#ifdef WAVELAN_ROAMING_DEBUG - printk(KERN_DEBUG "WaveLAN: New Wavepoint, NWID:%.4X\n",nwid); -#endif - - if(lp->wavepoint_table.num_wavepoints==MAX_WAVEPOINTS) - return NULL; - - new_wavepoint = kmalloc(sizeof(wavepoint_history),GFP_ATOMIC); - if(new_wavepoint==NULL) - return NULL; - - new_wavepoint->nwid=nwid; /* New WavePoints NWID */ - new_wavepoint->average_fast=0; /* Running Averages..*/ - new_wavepoint->average_slow=0; - new_wavepoint->qualptr=0; /* Start of ringbuffer */ - new_wavepoint->last_seq=seq-1; /* Last sequence no.seen */ - memset(new_wavepoint->sigqual,0,WAVEPOINT_HISTORY);/* Empty ringbuffer */ - - new_wavepoint->next=lp->wavepoint_table.head;/* Add to wavepoint table */ - new_wavepoint->prev=NULL; - - if(lp->wavepoint_table.head!=NULL) - lp->wavepoint_table.head->prev=new_wavepoint; - - lp->wavepoint_table.head=new_wavepoint; - - lp->wavepoint_table.num_wavepoints++; /* no. of visible wavepoints */ - - return new_wavepoint; -} - -/* Remove a wavepoint entry from WavePoint table */ -static void wl_del_wavepoint(wavepoint_history *wavepoint, struct net_local *lp) -{ - if(wavepoint==NULL) - return; - - if(lp->curr_point==wavepoint) - lp->curr_point=NULL; - - if(wavepoint->prev!=NULL) - wavepoint->prev->next=wavepoint->next; - - if(wavepoint->next!=NULL) - wavepoint->next->prev=wavepoint->prev; - - if(lp->wavepoint_table.head==wavepoint) - lp->wavepoint_table.head=wavepoint->next; - - lp->wavepoint_table.num_wavepoints--; - kfree(wavepoint); -} - -/* Timer callback function - checks WavePoint table for stale entries */ -static void wl_cell_expiry(unsigned long data) -{ - net_local *lp=(net_local *)data; - wavepoint_history *wavepoint=lp->wavepoint_table.head,*old_point; - -#if WAVELAN_ROAMING_DEBUG > 1 - printk(KERN_DEBUG "WaveLAN: Wavepoint timeout, dev %s\n",lp->dev->name); -#endif - - if(lp->wavepoint_table.locked) - { -#if WAVELAN_ROAMING_DEBUG > 1 - printk(KERN_DEBUG "WaveLAN: Wavepoint table locked...\n"); -#endif - - lp->cell_timer.expires=jiffies+1; /* If table in use, come back later */ - add_timer(&lp->cell_timer); - return; - } - - while(wavepoint!=NULL) - { - if(time_after(jiffies, wavepoint->last_seen + CELL_TIMEOUT)) - { -#ifdef WAVELAN_ROAMING_DEBUG - printk(KERN_DEBUG "WaveLAN: Bye bye %.4X\n",wavepoint->nwid); -#endif - - old_point=wavepoint; - wavepoint=wavepoint->next; - wl_del_wavepoint(old_point,lp); - } - else - wavepoint=wavepoint->next; - } - lp->cell_timer.expires=jiffies+CELL_TIMEOUT; - add_timer(&lp->cell_timer); -} - -/* Update SNR history of a wavepoint */ -static void wl_update_history(wavepoint_history *wavepoint, unsigned char sigqual, unsigned char seq) -{ - int i=0,num_missed=0,ptr=0; - int average_fast=0,average_slow=0; - - num_missed=(seq-wavepoint->last_seq)%WAVEPOINT_HISTORY;/* Have we missed - any beacons? */ - if(num_missed) - for(i=0;isigqual[wavepoint->qualptr++]=0; /* If so, enter them as 0's */ - wavepoint->qualptr %=WAVEPOINT_HISTORY; /* in the ringbuffer. */ - } - wavepoint->last_seen=jiffies; /* Add beacon to history */ - wavepoint->last_seq=seq; - wavepoint->sigqual[wavepoint->qualptr++]=sigqual; - wavepoint->qualptr %=WAVEPOINT_HISTORY; - ptr=(wavepoint->qualptr-WAVEPOINT_FAST_HISTORY+WAVEPOINT_HISTORY)%WAVEPOINT_HISTORY; - - for(i=0;isigqual[ptr++]; - ptr %=WAVEPOINT_HISTORY; - } - - average_slow=average_fast; - for(i=WAVEPOINT_FAST_HISTORY;isigqual[ptr++]; - ptr %=WAVEPOINT_HISTORY; - } - - wavepoint->average_fast=average_fast/WAVEPOINT_FAST_HISTORY; - wavepoint->average_slow=average_slow/WAVEPOINT_HISTORY; -} - -/* Perform a handover to a new WavePoint */ -static void wv_roam_handover(wavepoint_history *wavepoint, net_local *lp) -{ - unsigned int base = lp->dev->base_addr; - mm_t m; - unsigned long flags; - - if(wavepoint==lp->curr_point) /* Sanity check... */ - { - wv_nwid_filter(!NWID_PROMISC,lp); - return; - } - -#ifdef WAVELAN_ROAMING_DEBUG - printk(KERN_DEBUG "WaveLAN: Doing handover to %.4X, dev %s\n",wavepoint->nwid,lp->dev->name); -#endif - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&lp->spinlock, flags); - - m.w.mmw_netw_id_l = wavepoint->nwid & 0xFF; - m.w.mmw_netw_id_h = (wavepoint->nwid & 0xFF00) >> 8; - - mmc_write(base, (char *)&m.w.mmw_netw_id_l - (char *)&m, (unsigned char *)&m.w.mmw_netw_id_l, 2); - - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - wv_nwid_filter(!NWID_PROMISC,lp); - lp->curr_point=wavepoint; -} - -/* Called when a WavePoint beacon is received */ -static void wl_roam_gather(struct net_device * dev, - u_char * hdr, /* Beacon header */ - u_char * stats) /* SNR, Signal quality - of packet */ -{ - wavepoint_beacon *beacon= (wavepoint_beacon *)hdr; /* Rcvd. Beacon */ - unsigned short nwid=ntohs(beacon->nwid); - unsigned short sigqual=stats[2] & MMR_SGNL_QUAL; /* SNR of beacon */ - wavepoint_history *wavepoint=NULL; /* WavePoint table entry */ - net_local *lp = netdev_priv(dev); /* Device info */ - -#ifdef I_NEED_THIS_FEATURE - /* Some people don't need this, some other may need it */ - nwid=nwid^ntohs(beacon->domain_id); -#endif - -#if WAVELAN_ROAMING_DEBUG > 1 - printk(KERN_DEBUG "WaveLAN: beacon, dev %s:\n",dev->name); - printk(KERN_DEBUG "Domain: %.4X NWID: %.4X SigQual=%d\n",ntohs(beacon->domain_id),nwid,sigqual); -#endif - - lp->wavepoint_table.locked=1; /* */ - - wavepoint=wl_roam_check(nwid,lp); /* Find WavePoint table entry */ - if(wavepoint==NULL) /* If no entry, Create a new one... */ - { - wavepoint=wl_new_wavepoint(nwid,beacon->seq,lp); - if(wavepoint==NULL) - goto out; - } - if(lp->curr_point==NULL) /* If this is the only WavePoint, */ - wv_roam_handover(wavepoint, lp); /* Jump on it! */ - - wl_update_history(wavepoint, sigqual, beacon->seq); /* Update SNR history - stats. */ - - if(lp->curr_point->average_slow < SEARCH_THRESH_LOW) /* If our current */ - if(!lp->cell_search) /* WavePoint is getting faint, */ - wv_nwid_filter(NWID_PROMISC,lp); /* start looking for a new one */ - - if(wavepoint->average_slow > - lp->curr_point->average_slow + WAVELAN_ROAMING_DELTA) - wv_roam_handover(wavepoint, lp); /* Handover to a better WavePoint */ - - if(lp->curr_point->average_slow > SEARCH_THRESH_HIGH) /* If our SNR is */ - if(lp->cell_search) /* getting better, drop out of cell search mode */ - wv_nwid_filter(!NWID_PROMISC,lp); - -out: - lp->wavepoint_table.locked=0; /* :-) */ -} - -/* Test this MAC frame a WavePoint beacon */ -static inline int WAVELAN_BEACON(unsigned char *data) -{ - wavepoint_beacon *beacon= (wavepoint_beacon *)data; - static const wavepoint_beacon beacon_template={0xaa,0xaa,0x03,0x08,0x00,0x0e,0x20,0x03,0x00}; - - if(memcmp(beacon,&beacon_template,9)==0) - return 1; - else - return 0; -} -#endif /* WAVELAN_ROAMING */ - -/************************ I82593 SUBROUTINES *************************/ -/* - * Useful subroutines to manage the Ethernet controller - */ - -/*------------------------------------------------------------------*/ -/* - * Routine to synchronously send a command to the i82593 chip. - * Should be called with interrupts disabled. - * (called by wv_packet_write(), wv_ru_stop(), wv_ru_start(), - * wv_82593_config() & wv_diag()) - */ -static int -wv_82593_cmd(struct net_device * dev, - char * str, - int cmd, - int result) -{ - unsigned int base = dev->base_addr; - int status; - int wait_completed; - long spin; - - /* Spin until the chip finishes executing its current command (if any) */ - spin = 1000; - do - { - /* Time calibration of the loop */ - udelay(10); - - /* Read the interrupt register */ - outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); - status = inb(LCSR(base)); - } - while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0)); - - /* If the interrupt hasn't been posted */ - if (spin < 0) { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "wv_82593_cmd: %s timeout (previous command), status 0x%02x\n", - str, status); -#endif - return(FALSE); - } - - /* Issue the command to the controller */ - outb(cmd, LCCR(base)); - - /* If we don't have to check the result of the command - * Note : this mean that the irq handler will deal with that */ - if(result == SR0_NO_RESULT) - return(TRUE); - - /* We are waiting for command completion */ - wait_completed = TRUE; - - /* Busy wait while the LAN controller executes the command. */ - spin = 1000; - do - { - /* Time calibration of the loop */ - udelay(10); - - /* Read the interrupt register */ - outb(CR0_STATUS_0 | OP0_NOP, LCCR(base)); - status = inb(LCSR(base)); - - /* Check if there was an interrupt posted */ - if((status & SR0_INTERRUPT)) - { - /* Acknowledge the interrupt */ - outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); - - /* Check if interrupt is a command completion */ - if(((status & SR0_BOTH_RX_TX) != SR0_BOTH_RX_TX) && - ((status & SR0_BOTH_RX_TX) != 0x0) && - !(status & SR0_RECEPTION)) - { - /* Signal command completion */ - wait_completed = FALSE; - } - else - { - /* Note : Rx interrupts will be handled later, because we can - * handle multiple Rx packets at once */ -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_INFO "wv_82593_cmd: not our interrupt\n"); -#endif - } - } - } - while(wait_completed && (spin-- > 0)); - - /* If the interrupt hasn't be posted */ - if(wait_completed) - { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "wv_82593_cmd: %s timeout, status 0x%02x\n", - str, status); -#endif - return(FALSE); - } - - /* Check the return code returned by the card (see above) against - * the expected return code provided by the caller */ - if((status & SR0_EVENT_MASK) != result) - { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "wv_82593_cmd: %s failed, status = 0x%x\n", - str, status); -#endif - return(FALSE); - } - - return(TRUE); -} /* wv_82593_cmd */ - -/*------------------------------------------------------------------*/ -/* - * This routine does a 593 op-code number 7, and obtains the diagnose - * status for the WaveLAN. - */ -static inline int -wv_diag(struct net_device * dev) -{ - return(wv_82593_cmd(dev, "wv_diag(): diagnose", - OP0_DIAGNOSE, SR0_DIAGNOSE_PASSED)); -} /* wv_diag */ - -/*------------------------------------------------------------------*/ -/* - * Routine to read len bytes from the i82593's ring buffer, starting at - * chip address addr. The results read from the chip are stored in buf. - * The return value is the address to use for next the call. - */ -static int -read_ringbuf(struct net_device * dev, - int addr, - char * buf, - int len) -{ - unsigned int base = dev->base_addr; - int ring_ptr = addr; - int chunk_len; - char * buf_ptr = buf; - - /* Get all the buffer */ - while(len > 0) - { - /* Position the Program I/O Register at the ring buffer pointer */ - outb(ring_ptr & 0xff, PIORL(base)); - outb(((ring_ptr >> 8) & PIORH_MASK), PIORH(base)); - - /* First, determine how much we can read without wrapping around the - ring buffer */ - if((addr + len) < (RX_BASE + RX_SIZE)) - chunk_len = len; - else - chunk_len = RX_BASE + RX_SIZE - addr; - insb(PIOP(base), buf_ptr, chunk_len); - buf_ptr += chunk_len; - len -= chunk_len; - ring_ptr = (ring_ptr - RX_BASE + chunk_len) % RX_SIZE + RX_BASE; - } - return(ring_ptr); -} /* read_ringbuf */ - -/*------------------------------------------------------------------*/ -/* - * Reconfigure the i82593, or at least ask for it... - * Because wv_82593_config use the transmission buffer, we must do it - * when we are sure that there is no transmission, so we do it now - * or in wavelan_packet_xmit() (I can't find any better place, - * wavelan_interrupt is not an option...), so you may experience - * some delay sometime... - */ -static void -wv_82593_reconfig(struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - struct pcmcia_device * link = lp->link; - unsigned long flags; - - /* Arm the flag, will be cleard in wv_82593_config() */ - lp->reconfig_82593 = TRUE; - - /* Check if we can do it now ! */ - if((link->open) && (netif_running(dev)) && !(netif_queue_stopped(dev))) - { - spin_lock_irqsave(&lp->spinlock, flags); /* Disable interrupts */ - wv_82593_config(dev); - spin_unlock_irqrestore(&lp->spinlock, flags); /* Re-enable interrupts */ - } - else - { -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG - "%s: wv_82593_reconfig(): delayed (state = %lX, link = %d)\n", - dev->name, dev->state, link->open); -#endif - } -} - -/********************* DEBUG & INFO SUBROUTINES *********************/ -/* - * This routines are used in the code to show debug informations. - * Most of the time, it dump the content of hardware structures... - */ - -#ifdef DEBUG_PSA_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted contents of the Parameter Storage Area. - */ -static void -wv_psa_show(psa_t * p) -{ - printk(KERN_DEBUG "##### wavelan psa contents: #####\n"); - printk(KERN_DEBUG "psa_io_base_addr_1: 0x%02X %02X %02X %02X\n", - p->psa_io_base_addr_1, - p->psa_io_base_addr_2, - p->psa_io_base_addr_3, - p->psa_io_base_addr_4); - printk(KERN_DEBUG "psa_rem_boot_addr_1: 0x%02X %02X %02X\n", - p->psa_rem_boot_addr_1, - p->psa_rem_boot_addr_2, - p->psa_rem_boot_addr_3); - printk(KERN_DEBUG "psa_holi_params: 0x%02x, ", p->psa_holi_params); - printk("psa_int_req_no: %d\n", p->psa_int_req_no); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_unused0[]: %pM\n", p->psa_unused0); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "psa_univ_mac_addr[]: %pM\n", p->psa_univ_mac_addr); - printk(KERN_DEBUG "psa_local_mac_addr[]: %pM\n", p->psa_local_mac_addr); - printk(KERN_DEBUG "psa_univ_local_sel: %d, ", p->psa_univ_local_sel); - printk("psa_comp_number: %d, ", p->psa_comp_number); - printk("psa_thr_pre_set: 0x%02x\n", p->psa_thr_pre_set); - printk(KERN_DEBUG "psa_feature_select/decay_prm: 0x%02x, ", - p->psa_feature_select); - printk("psa_subband/decay_update_prm: %d\n", p->psa_subband); - printk(KERN_DEBUG "psa_quality_thr: 0x%02x, ", p->psa_quality_thr); - printk("psa_mod_delay: 0x%02x\n", p->psa_mod_delay); - printk(KERN_DEBUG "psa_nwid: 0x%02x%02x, ", p->psa_nwid[0], p->psa_nwid[1]); - printk("psa_nwid_select: %d\n", p->psa_nwid_select); - printk(KERN_DEBUG "psa_encryption_select: %d, ", p->psa_encryption_select); - printk("psa_encryption_key[]: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n", - p->psa_encryption_key[0], - p->psa_encryption_key[1], - p->psa_encryption_key[2], - p->psa_encryption_key[3], - p->psa_encryption_key[4], - p->psa_encryption_key[5], - p->psa_encryption_key[6], - p->psa_encryption_key[7]); - printk(KERN_DEBUG "psa_databus_width: %d\n", p->psa_databus_width); - printk(KERN_DEBUG "psa_call_code/auto_squelch: 0x%02x, ", - p->psa_call_code[0]); - printk("psa_call_code[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - p->psa_call_code[0], - p->psa_call_code[1], - p->psa_call_code[2], - p->psa_call_code[3], - p->psa_call_code[4], - p->psa_call_code[5], - p->psa_call_code[6], - p->psa_call_code[7]); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "psa_reserved[]: %02X:%02X\n", - p->psa_reserved[0], - p->psa_reserved[1]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "psa_conf_status: %d, ", p->psa_conf_status); - printk("psa_crc: 0x%02x%02x, ", p->psa_crc[0], p->psa_crc[1]); - printk("psa_crc_status: 0x%02x\n", p->psa_crc_status); -} /* wv_psa_show */ -#endif /* DEBUG_PSA_SHOW */ - -#ifdef DEBUG_MMC_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the Modem Management Controller. - * This function need to be completed... - */ -static void -wv_mmc_show(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - net_local * lp = netdev_priv(dev); - mmr_t m; - - /* Basic check */ - if(hasr_read(base) & HASR_NO_CLK) - { - printk(KERN_WARNING "%s: wv_mmc_show: modem not connected\n", - dev->name); - return; - } - - spin_lock_irqsave(&lp->spinlock, flags); - - /* Read the mmc */ - mmc_out(base, mmwoff(0, mmw_freeze), 1); - mmc_read(base, 0, (u_char *)&m, sizeof(m)); - mmc_out(base, mmwoff(0, mmw_freeze), 0); - - /* Don't forget to update statistics */ - lp->wstats.discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; - - spin_unlock_irqrestore(&lp->spinlock, flags); - - printk(KERN_DEBUG "##### wavelan modem status registers: #####\n"); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused0[]: %02X:%02X:%02X:%02X:%02X:%02X:%02X:%02X\n", - m.mmr_unused0[0], - m.mmr_unused0[1], - m.mmr_unused0[2], - m.mmr_unused0[3], - m.mmr_unused0[4], - m.mmr_unused0[5], - m.mmr_unused0[6], - m.mmr_unused0[7]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "Encryption algorithm: %02X - Status: %02X\n", - m.mmr_des_avail, m.mmr_des_status); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused1[]: %02X:%02X:%02X:%02X:%02X\n", - m.mmr_unused1[0], - m.mmr_unused1[1], - m.mmr_unused1[2], - m.mmr_unused1[3], - m.mmr_unused1[4]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "dce_status: 0x%x [%s%s%s%s]\n", - m.mmr_dce_status, - (m.mmr_dce_status & MMR_DCE_STATUS_RX_BUSY) ? "energy detected,":"", - (m.mmr_dce_status & MMR_DCE_STATUS_LOOPT_IND) ? - "loop test indicated," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_TX_BUSY) ? "transmitter on," : "", - (m.mmr_dce_status & MMR_DCE_STATUS_JBR_EXPIRED) ? - "jabber timer expired," : ""); - printk(KERN_DEBUG "Dsp ID: %02X\n", - m.mmr_dsp_id); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "mmc_unused2[]: %02X:%02X\n", - m.mmr_unused2[0], - m.mmr_unused2[1]); -#endif /* DEBUG_SHOW_UNUSED */ - printk(KERN_DEBUG "# correct_nwid: %d, # wrong_nwid: %d\n", - (m.mmr_correct_nwid_h << 8) | m.mmr_correct_nwid_l, - (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l); - printk(KERN_DEBUG "thr_pre_set: 0x%x [current signal %s]\n", - m.mmr_thr_pre_set & MMR_THR_PRE_SET, - (m.mmr_thr_pre_set & MMR_THR_PRE_SET_CUR) ? "above" : "below"); - printk(KERN_DEBUG "signal_lvl: %d [%s], ", - m.mmr_signal_lvl & MMR_SIGNAL_LVL, - (m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) ? "new msg" : "no new msg"); - printk("silence_lvl: %d [%s], ", m.mmr_silence_lvl & MMR_SILENCE_LVL, - (m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) ? "update done" : "no new update"); - printk("sgnl_qual: 0x%x [%s]\n", m.mmr_sgnl_qual & MMR_SGNL_QUAL, - (m.mmr_sgnl_qual & MMR_SGNL_QUAL_ANT) ? "Antenna 1" : "Antenna 0"); -#ifdef DEBUG_SHOW_UNUSED - printk(KERN_DEBUG "netw_id_l: %x\n", m.mmr_netw_id_l); -#endif /* DEBUG_SHOW_UNUSED */ -} /* wv_mmc_show */ -#endif /* DEBUG_MMC_SHOW */ - -#ifdef DEBUG_I82593_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the i82593's receive unit. - */ -static void -wv_ru_show(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - - printk(KERN_DEBUG "##### wavelan i82593 receiver status: #####\n"); - printk(KERN_DEBUG "ru: rfp %d stop %d", lp->rfp, lp->stop); - /* - * Not implemented yet... - */ - printk("\n"); -} /* wv_ru_show */ -#endif /* DEBUG_I82593_SHOW */ - -#ifdef DEBUG_DEVICE_SHOW -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the WaveLAN PCMCIA device driver. - */ -static void -wv_dev_show(struct net_device * dev) -{ - printk(KERN_DEBUG "dev:"); - printk(" state=%lX,", dev->state); - printk(" trans_start=%ld,", dev->trans_start); - printk(" flags=0x%x,", dev->flags); - printk("\n"); -} /* wv_dev_show */ - -/*------------------------------------------------------------------*/ -/* - * Print the formatted status of the WaveLAN PCMCIA device driver's - * private information. - */ -static void -wv_local_show(struct net_device * dev) -{ - net_local *lp = netdev_priv(dev); - - printk(KERN_DEBUG "local:"); - /* - * Not implemented yet... - */ - printk("\n"); -} /* wv_local_show */ -#endif /* DEBUG_DEVICE_SHOW */ - -#if defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) -/*------------------------------------------------------------------*/ -/* - * Dump packet header (and content if necessary) on the screen - */ -static void -wv_packet_info(u_char * p, /* Packet to dump */ - int length, /* Length of the packet */ - char * msg1, /* Name of the device */ - char * msg2) /* Name of the function */ -{ - int i; - int maxi; - - printk(KERN_DEBUG "%s: %s(): dest %pM, length %d\n", - msg1, msg2, p, length); - printk(KERN_DEBUG "%s: %s(): src %pM, type 0x%02X%02X\n", - msg1, msg2, &p[6], p[12], p[13]); - -#ifdef DEBUG_PACKET_DUMP - - printk(KERN_DEBUG "data=\""); - - if((maxi = length) > DEBUG_PACKET_DUMP) - maxi = DEBUG_PACKET_DUMP; - for(i = 14; i < maxi; i++) - if(p[i] >= ' ' && p[i] <= '~') - printk(" %c", p[i]); - else - printk("%02X", p[i]); - if(maxi < length) - printk(".."); - printk("\"\n"); - printk(KERN_DEBUG "\n"); -#endif /* DEBUG_PACKET_DUMP */ -} -#endif /* defined(DEBUG_RX_INFO) || defined(DEBUG_TX_INFO) */ - -/*------------------------------------------------------------------*/ -/* - * This is the information which is displayed by the driver at startup - * There is a lot of flag to configure it at your will... - */ -static void -wv_init_info(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - psa_t psa; - - /* Read the parameter storage area */ - psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); - -#ifdef DEBUG_PSA_SHOW - wv_psa_show(&psa); -#endif -#ifdef DEBUG_MMC_SHOW - wv_mmc_show(dev); -#endif -#ifdef DEBUG_I82593_SHOW - wv_ru_show(dev); -#endif - -#ifdef DEBUG_BASIC_SHOW - /* Now, let's go for the basic stuff */ - printk(KERN_NOTICE "%s: WaveLAN: port %#x, irq %d, hw_addr %pM", - dev->name, base, dev->irq, dev->dev_addr); - - /* Print current network id */ - if(psa.psa_nwid_select) - printk(", nwid 0x%02X-%02X", psa.psa_nwid[0], psa.psa_nwid[1]); - else - printk(", nwid off"); - - /* If 2.00 card */ - if(!(mmc_in(base, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - { - unsigned short freq; - - /* Ask the EEprom to read the frequency from the first area */ - fee_read(base, 0x00 /* 1st area - frequency... */, - &freq, 1); - - /* Print frequency */ - printk(", 2.00, %ld", (freq >> 6) + 2400L); - - /* Hack !!! */ - if(freq & 0x20) - printk(".5"); - } - else - { - printk(", PCMCIA, "); - switch (psa.psa_subband) - { - case PSA_SUBBAND_915: - printk("915"); - break; - case PSA_SUBBAND_2425: - printk("2425"); - break; - case PSA_SUBBAND_2460: - printk("2460"); - break; - case PSA_SUBBAND_2484: - printk("2484"); - break; - case PSA_SUBBAND_2430_5: - printk("2430.5"); - break; - default: - printk("unknown"); - } - } - - printk(" MHz\n"); -#endif /* DEBUG_BASIC_SHOW */ - -#ifdef DEBUG_VERSION_SHOW - /* Print version information */ - printk(KERN_NOTICE "%s", version); -#endif -} /* wv_init_info */ - -/********************* IOCTL, STATS & RECONFIG *********************/ -/* - * We found here routines that are called by Linux on differents - * occasions after the configuration and not for transmitting data - * These may be called when the user use ifconfig, /proc/net/dev - * or wireless extensions - */ - - -/*------------------------------------------------------------------*/ -/* - * Set or clear the multicast filter for this adaptor. - * num_addrs == -1 Promiscuous mode, receive all packets - * num_addrs == 0 Normal mode, clear multicast list - * num_addrs > 0 Multicast mode, receive normal and MC packets, - * and do best-effort filtering. - */ - -static void -wavelan_set_multicast_list(struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_set_multicast_list()\n", dev->name); -#endif - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "%s: wavelan_set_multicast_list(): setting Rx mode %02X to %d addresses.\n", - dev->name, dev->flags, dev->mc_count); -#endif - - if(dev->flags & IFF_PROMISC) - { - /* - * Enable promiscuous mode: receive all packets. - */ - if(!lp->promiscuous) - { - lp->promiscuous = 1; - lp->allmulticast = 0; - lp->mc_count = 0; - - wv_82593_reconfig(dev); - } - } - else - /* If all multicast addresses - * or too much multicast addresses for the hardware filter */ - if((dev->flags & IFF_ALLMULTI) || - (dev->mc_count > I82593_MAX_MULTICAST_ADDRESSES)) - { - /* - * Disable promiscuous mode, but active the all multicast mode - */ - if(!lp->allmulticast) - { - lp->promiscuous = 0; - lp->allmulticast = 1; - lp->mc_count = 0; - - wv_82593_reconfig(dev); - } - } - else - /* If there is some multicast addresses to send */ - if(dev->mc_list != (struct dev_mc_list *) NULL) - { - /* - * Disable promiscuous mode, but receive all packets - * in multicast list - */ -#ifdef MULTICAST_AVOID - if(lp->promiscuous || lp->allmulticast || - (dev->mc_count != lp->mc_count)) -#endif - { - lp->promiscuous = 0; - lp->allmulticast = 0; - lp->mc_count = dev->mc_count; - - wv_82593_reconfig(dev); - } - } - else - { - /* - * Switch to normal mode: disable promiscuous mode and - * clear the multicast list. - */ - if(lp->promiscuous || lp->mc_count == 0) - { - lp->promiscuous = 0; - lp->allmulticast = 0; - lp->mc_count = 0; - - wv_82593_reconfig(dev); - } - } -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_set_multicast_list()\n", dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * This function doesn't exist... - * (Note : it was a nice way to test the reconfigure stuff...) - */ -#ifdef SET_MAC_ADDRESS -static int -wavelan_set_mac_address(struct net_device * dev, - void * addr) -{ - struct sockaddr * mac = addr; - - /* Copy the address */ - memcpy(dev->dev_addr, mac->sa_data, WAVELAN_ADDR_SIZE); - - /* Reconfig the beast */ - wv_82593_reconfig(dev); - - return 0; -} -#endif /* SET_MAC_ADDRESS */ - - -/*------------------------------------------------------------------*/ -/* - * Frequency setting (for hardware able of it) - * It's a bit complicated and you don't really want to look into it... - */ -static int -wv_set_frequency(u_long base, /* i/o port of the card */ - iw_freq * frequency) -{ - const int BAND_NUM = 10; /* Number of bands */ - long freq = 0L; /* offset to 2.4 GHz in .5 MHz */ -#ifdef DEBUG_IOCTL_INFO - int i; -#endif - - /* Setting by frequency */ - /* Theoritically, you may set any frequency between - * the two limits with a 0.5 MHz precision. In practice, - * I don't want you to have trouble with local - * regulations... */ - if((frequency->e == 1) && - (frequency->m >= (int) 2.412e8) && (frequency->m <= (int) 2.487e8)) - { - freq = ((frequency->m / 10000) - 24000L) / 5; - } - - /* Setting by channel (same as wfreqsel) */ - /* Warning : each channel is 22MHz wide, so some of the channels - * will interfere... */ - if((frequency->e == 0) && - (frequency->m >= 0) && (frequency->m < BAND_NUM)) - { - /* Get frequency offset. */ - freq = channel_bands[frequency->m] >> 1; - } - - /* Verify if the frequency is allowed */ - if(freq != 0L) - { - u_short table[10]; /* Authorized frequency table */ - - /* Read the frequency table */ - fee_read(base, 0x71 /* frequency table */, - table, 10); - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Frequency table :"); - for(i = 0; i < 10; i++) - { - printk(" %04X", - table[i]); - } - printk("\n"); -#endif - - /* Look in the table if the frequency is allowed */ - if(!(table[9 - ((freq - 24) / 16)] & - (1 << ((freq - 24) % 16)))) - return -EINVAL; /* not allowed */ - } - else - return -EINVAL; - - /* If we get a usable frequency */ - if(freq != 0L) - { - unsigned short area[16]; - unsigned short dac[2]; - unsigned short area_verify[16]; - unsigned short dac_verify[2]; - /* Corresponding gain (in the power adjust value table) - * see AT&T Wavelan Data Manual, REF 407-024689/E, page 3-8 - * & WCIN062D.DOC, page 6.2.9 */ - unsigned short power_limit[] = { 40, 80, 120, 160, 0 }; - int power_band = 0; /* Selected band */ - unsigned short power_adjust; /* Correct value */ - - /* Search for the gain */ - power_band = 0; - while((freq > power_limit[power_band]) && - (power_limit[++power_band] != 0)) - ; - - /* Read the first area */ - fee_read(base, 0x00, - area, 16); - - /* Read the DAC */ - fee_read(base, 0x60, - dac, 2); - - /* Read the new power adjust value */ - fee_read(base, 0x6B - (power_band >> 1), - &power_adjust, 1); - if(power_band & 0x1) - power_adjust >>= 8; - else - power_adjust &= 0xFF; - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Wavelan EEprom Area 1 :"); - for(i = 0; i < 16; i++) - { - printk(" %04X", - area[i]); - } - printk("\n"); - - printk(KERN_DEBUG "Wavelan EEprom DAC : %04X %04X\n", - dac[0], dac[1]); -#endif - - /* Frequency offset (for info only...) */ - area[0] = ((freq << 5) & 0xFFE0) | (area[0] & 0x1F); - - /* Receiver Principle main divider coefficient */ - area[3] = (freq >> 1) + 2400L - 352L; - area[2] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - - /* Transmitter Main divider coefficient */ - area[13] = (freq >> 1) + 2400L; - area[12] = ((freq & 0x1) << 4) | (area[2] & 0xFFEF); - - /* Others part of the area are flags, bit streams or unused... */ - - /* Set the value in the DAC */ - dac[1] = ((power_adjust >> 1) & 0x7F) | (dac[1] & 0xFF80); - dac[0] = ((power_adjust & 0x1) << 4) | (dac[0] & 0xFFEF); - - /* Write the first area */ - fee_write(base, 0x00, - area, 16); - - /* Write the DAC */ - fee_write(base, 0x60, - dac, 2); - - /* We now should verify here that the EEprom writing was ok */ - - /* ReRead the first area */ - fee_read(base, 0x00, - area_verify, 16); - - /* ReRead the DAC */ - fee_read(base, 0x60, - dac_verify, 2); - - /* Compare */ - if(memcmp(area, area_verify, 16 * 2) || - memcmp(dac, dac_verify, 2 * 2)) - { -#ifdef DEBUG_IOCTL_ERROR - printk(KERN_INFO "Wavelan: wv_set_frequency : unable to write new frequency to EEprom (?)\n"); -#endif - return -EOPNOTSUPP; - } - - /* We must download the frequency parameters to the - * synthetisers (from the EEprom - area 1) - * Note : as the EEprom is auto decremented, we set the end - * if the area... */ - mmc_out(base, mmwoff(0, mmw_fee_addr), 0x0F); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); - - /* Wait until the download is finished */ - fee_wait(base, 100, 100); - - /* We must now download the power adjust value (gain) to - * the synthetisers (from the EEprom - area 7 - DAC) */ - mmc_out(base, mmwoff(0, mmw_fee_addr), 0x61); - mmc_out(base, mmwoff(0, mmw_fee_ctrl), - MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD); - - /* Wait until the download is finished */ - fee_wait(base, 100, 100); - -#ifdef DEBUG_IOCTL_INFO - /* Verification of what we have done... */ - - printk(KERN_DEBUG "Wavelan EEprom Area 1 :"); - for(i = 0; i < 16; i++) - { - printk(" %04X", - area_verify[i]); - } - printk("\n"); - - printk(KERN_DEBUG "Wavelan EEprom DAC : %04X %04X\n", - dac_verify[0], dac_verify[1]); -#endif - - return 0; - } - else - return -EINVAL; /* Bah, never get there... */ -} - -/*------------------------------------------------------------------*/ -/* - * Give the list of available frequencies - */ -static int -wv_frequency_list(u_long base, /* i/o port of the card */ - iw_freq * list, /* List of frequency to fill */ - int max) /* Maximum number of frequencies */ -{ - u_short table[10]; /* Authorized frequency table */ - long freq = 0L; /* offset to 2.4 GHz in .5 MHz + 12 MHz */ - int i; /* index in the table */ - const int BAND_NUM = 10; /* Number of bands */ - int c = 0; /* Channel number */ - - /* Read the frequency table */ - fee_read(base, 0x71 /* frequency table */, - table, 10); - - /* Look all frequencies */ - i = 0; - for(freq = 0; freq < 150; freq++) - /* Look in the table if the frequency is allowed */ - if(table[9 - (freq / 16)] & (1 << (freq % 16))) - { - /* Compute approximate channel number */ - while((((channel_bands[c] >> 1) - 24) < freq) && - (c < BAND_NUM)) - c++; - list[i].i = c; /* Set the list index */ - - /* put in the list */ - list[i].m = (((freq + 24) * 5) + 24000L) * 10000; - list[i++].e = 1; - - /* Check number */ - if(i >= max) - return(i); - } - - return(i); -} - -#ifdef IW_WIRELESS_SPY -/*------------------------------------------------------------------*/ -/* - * Gather wireless spy statistics : for each packet, compare the source - * address with out list, and if match, get the stats... - * Sorry, but this function really need wireless extensions... - */ -static inline void -wl_spy_gather(struct net_device * dev, - u_char * mac, /* MAC address */ - u_char * stats) /* Statistics to gather */ -{ - struct iw_quality wstats; - - wstats.qual = stats[2] & MMR_SGNL_QUAL; - wstats.level = stats[0] & MMR_SIGNAL_LVL; - wstats.noise = stats[1] & MMR_SILENCE_LVL; - wstats.updated = 0x7; - - /* Update spy records */ - wireless_spy_update(dev, mac, &wstats); -} -#endif /* IW_WIRELESS_SPY */ - -#ifdef HISTOGRAM -/*------------------------------------------------------------------*/ -/* - * This function calculate an histogram on the signal level. - * As the noise is quite constant, it's like doing it on the SNR. - * We have defined a set of interval (lp->his_range), and each time - * the level goes in that interval, we increment the count (lp->his_sum). - * With this histogram you may detect if one wavelan is really weak, - * or you may also calculate the mean and standard deviation of the level... - */ -static inline void -wl_his_gather(struct net_device * dev, - u_char * stats) /* Statistics to gather */ -{ - net_local * lp = netdev_priv(dev); - u_char level = stats[0] & MMR_SIGNAL_LVL; - int i; - - /* Find the correct interval */ - i = 0; - while((i < (lp->his_number - 1)) && (level >= lp->his_range[i++])) - ; - - /* Increment interval counter */ - (lp->his_sum[i])++; -} -#endif /* HISTOGRAM */ - -static void wl_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - strncpy(info->driver, "wavelan_cs", sizeof(info->driver)-1); -} - -static const struct ethtool_ops ops = { - .get_drvinfo = wl_get_drvinfo -}; - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get protocol name - */ -static int wavelan_get_name(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - strcpy(wrqu->name, "WaveLAN"); - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set NWID - */ -static int wavelan_set_nwid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - mm_t m; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Set NWID in WaveLAN. */ - if (!wrqu->nwid.disabled) { - /* Set NWID in psa */ - psa.psa_nwid[0] = (wrqu->nwid.value & 0xFF00) >> 8; - psa.psa_nwid[1] = wrqu->nwid.value & 0xFF; - psa.psa_nwid_select = 0x01; - psa_write(dev, - (char *) psa.psa_nwid - (char *) &psa, - (unsigned char *) psa.psa_nwid, 3); - - /* Set NWID in mmc. */ - m.w.mmw_netw_id_l = psa.psa_nwid[1]; - m.w.mmw_netw_id_h = psa.psa_nwid[0]; - mmc_write(base, - (char *) &m.w.mmw_netw_id_l - - (char *) &m, - (unsigned char *) &m.w.mmw_netw_id_l, 2); - mmc_out(base, mmwoff(0, mmw_loopt_sel), 0x00); - } else { - /* Disable NWID in the psa. */ - psa.psa_nwid_select = 0x00; - psa_write(dev, - (char *) &psa.psa_nwid_select - - (char *) &psa, - (unsigned char *) &psa.psa_nwid_select, - 1); - - /* Disable NWID in the mmc (no filtering). */ - mmc_out(base, mmwoff(0, mmw_loopt_sel), - MMW_LOOPT_SEL_DIS_NWID); - } - /* update the Wavelan checksum */ - update_psa_checksum(dev); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get NWID - */ -static int wavelan_get_nwid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Read the NWID. */ - psa_read(dev, - (char *) psa.psa_nwid - (char *) &psa, - (unsigned char *) psa.psa_nwid, 3); - wrqu->nwid.value = (psa.psa_nwid[0] << 8) + psa.psa_nwid[1]; - wrqu->nwid.disabled = !(psa.psa_nwid_select); - wrqu->nwid.fixed = 1; /* Superfluous */ - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set frequency - */ -static int wavelan_set_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - unsigned long flags; - int ret; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ - if (!(mmc_in(base, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - ret = wv_set_frequency(base, &(wrqu->freq)); - else - ret = -EOPNOTSUPP; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get frequency - */ -static int wavelan_get_freq(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). - * Does it work for everybody, especially old cards? */ - if (!(mmc_in(base, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { - unsigned short freq; - - /* Ask the EEPROM to read the frequency from the first area. */ - fee_read(base, 0x00, &freq, 1); - wrqu->freq.m = ((freq >> 5) * 5 + 24000L) * 10000; - wrqu->freq.e = 1; - } else { - psa_read(dev, - (char *) &psa.psa_subband - (char *) &psa, - (unsigned char *) &psa.psa_subband, 1); - - if (psa.psa_subband <= 4) { - wrqu->freq.m = fixed_bands[psa.psa_subband]; - wrqu->freq.e = (psa.psa_subband != 0); - } else - ret = -EOPNOTSUPP; - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set level threshold - */ -static int wavelan_set_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Set the level threshold. */ - /* We should complain loudly if wrqu->sens.fixed = 0, because we - * can't set auto mode... */ - psa.psa_thr_pre_set = wrqu->sens.value & 0x3F; - psa_write(dev, - (char *) &psa.psa_thr_pre_set - (char *) &psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev); - mmc_out(base, mmwoff(0, mmw_thr_pre_set), - psa.psa_thr_pre_set); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get level threshold - */ -static int wavelan_get_sens(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Read the level threshold. */ - psa_read(dev, - (char *) &psa.psa_thr_pre_set - (char *) &psa, - (unsigned char *) &psa.psa_thr_pre_set, 1); - wrqu->sens.value = psa.psa_thr_pre_set & 0x3F; - wrqu->sens.fixed = 1; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set encryption key - */ -static int wavelan_set_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - unsigned long flags; - psa_t psa; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check if capable of encryption */ - if (!mmc_encr(base)) { - ret = -EOPNOTSUPP; - } - - /* Check the size of the key */ - if((wrqu->encoding.length != 8) && (wrqu->encoding.length != 0)) { - ret = -EINVAL; - } - - if(!ret) { - /* Basic checking... */ - if (wrqu->encoding.length == 8) { - /* Copy the key in the driver */ - memcpy(psa.psa_encryption_key, extra, - wrqu->encoding.length); - psa.psa_encryption_select = 1; - - psa_write(dev, - (char *) &psa.psa_encryption_select - - (char *) &psa, - (unsigned char *) &psa. - psa_encryption_select, 8 + 1); - - mmc_out(base, mmwoff(0, mmw_encr_enable), - MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE); - mmc_write(base, mmwoff(0, mmw_encr_key), - (unsigned char *) &psa. - psa_encryption_key, 8); - } - - /* disable encryption */ - if (wrqu->encoding.flags & IW_ENCODE_DISABLED) { - psa.psa_encryption_select = 0; - psa_write(dev, - (char *) &psa.psa_encryption_select - - (char *) &psa, - (unsigned char *) &psa. - psa_encryption_select, 1); - - mmc_out(base, mmwoff(0, mmw_encr_enable), 0); - } - /* update the Wavelan checksum */ - update_psa_checksum(dev); - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get encryption key - */ -static int wavelan_get_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check if encryption is available */ - if (!mmc_encr(base)) { - ret = -EOPNOTSUPP; - } else { - /* Read the encryption key */ - psa_read(dev, - (char *) &psa.psa_encryption_select - - (char *) &psa, - (unsigned char *) &psa. - psa_encryption_select, 1 + 8); - - /* encryption is enabled ? */ - if (psa.psa_encryption_select) - wrqu->encoding.flags = IW_ENCODE_ENABLED; - else - wrqu->encoding.flags = IW_ENCODE_DISABLED; - wrqu->encoding.flags |= mmc_encr(base); - - /* Copy the key to the user buffer */ - wrqu->encoding.length = 8; - memcpy(extra, psa.psa_encryption_key, wrqu->encoding.length); - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -#ifdef WAVELAN_ROAMING_EXT -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set ESSID (domain) - */ -static int wavelan_set_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check if disable */ - if(wrqu->data.flags == 0) - lp->filter_domains = 0; - else { - char essid[IW_ESSID_MAX_SIZE + 1]; - char * endp; - - /* Terminate the string */ - memcpy(essid, extra, wrqu->data.length); - essid[IW_ESSID_MAX_SIZE] = '\0'; - -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "SetEssid : ``%s''\n", essid); -#endif /* DEBUG_IOCTL_INFO */ - - /* Convert to a number (note : Wavelan specific) */ - lp->domain_id = simple_strtoul(essid, &endp, 16); - /* Has it worked ? */ - if(endp > essid) - lp->filter_domains = 1; - else { - lp->filter_domains = 0; - ret = -EINVAL; - } - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get ESSID (domain) - */ -static int wavelan_get_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - - /* Is the domain ID active ? */ - wrqu->data.flags = lp->filter_domains; - - /* Copy Domain ID into a string (Wavelan specific) */ - /* Sound crazy, be we can't have a snprintf in the kernel !!! */ - sprintf(extra, "%lX", lp->domain_id); - extra[IW_ESSID_MAX_SIZE] = '\0'; - - /* Set the length */ - wrqu->data.length = strlen(extra); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set AP address - */ -static int wavelan_set_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ -#ifdef DEBUG_IOCTL_INFO - printk(KERN_DEBUG "Set AP to : %pM\n", wrqu->ap_addr.sa_data); -#endif /* DEBUG_IOCTL_INFO */ - - return -EOPNOTSUPP; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get AP address - */ -static int wavelan_get_wap(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - /* Should get the real McCoy instead of own Ethernet address */ - memcpy(wrqu->ap_addr.sa_data, dev->dev_addr, WAVELAN_ADDR_SIZE); - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - - return -EOPNOTSUPP; -} -#endif /* WAVELAN_ROAMING_EXT */ - -#ifdef WAVELAN_ROAMING -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : set mode - */ -static int wavelan_set_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - int ret = 0; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Check mode */ - switch(wrqu->mode) { - case IW_MODE_ADHOC: - if(do_roaming) { - wv_roam_cleanup(dev); - do_roaming = 0; - } - break; - case IW_MODE_INFRA: - if(!do_roaming) { - wv_roam_init(dev); - do_roaming = 1; - } - break; - default: - ret = -EINVAL; - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get mode - */ -static int wavelan_get_mode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - if(do_roaming) - wrqu->mode = IW_MODE_INFRA; - else - wrqu->mode = IW_MODE_ADHOC; - - return 0; -} -#endif /* WAVELAN_ROAMING */ - -/*------------------------------------------------------------------*/ -/* - * Wireless Handler : get range info - */ -static int wavelan_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - struct iw_range *range = (struct iw_range *) extra; - unsigned long flags; - int ret = 0; - - /* Set the length (very important for backward compatibility) */ - wrqu->data.length = sizeof(struct iw_range); - - /* Set all the info we don't care or don't know about to zero */ - memset(range, 0, sizeof(struct iw_range)); - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 9; - - /* Set information in the range struct. */ - range->throughput = 1.4 * 1000 * 1000; /* don't argue on this ! */ - range->min_nwid = 0x0000; - range->max_nwid = 0xFFFF; - - range->sensitivity = 0x3F; - range->max_qual.qual = MMR_SGNL_QUAL; - range->max_qual.level = MMR_SIGNAL_LVL; - range->max_qual.noise = MMR_SILENCE_LVL; - range->avg_qual.qual = MMR_SGNL_QUAL; /* Always max */ - /* Need to get better values for those two */ - range->avg_qual.level = 30; - range->avg_qual.noise = 8; - - range->num_bitrates = 1; - range->bitrate[0] = 2000000; /* 2 Mb/s */ - - /* Event capability (kernel + driver) */ - range->event_capa[0] = (IW_EVENT_CAPA_MASK(0x8B02) | - IW_EVENT_CAPA_MASK(0x8B04) | - IW_EVENT_CAPA_MASK(0x8B06)); - range->event_capa[1] = IW_EVENT_CAPA_K_1; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable). */ - if (!(mmc_in(base, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) { - range->num_channels = 10; - range->num_frequency = wv_frequency_list(base, range->freq, - IW_MAX_FREQUENCIES); - } else - range->num_channels = range->num_frequency = 0; - - /* Encryption supported ? */ - if (mmc_encr(base)) { - range->encoding_size[0] = 8; /* DES = 64 bits key */ - range->num_encoding_sizes = 1; - range->max_encoding_tokens = 1; /* Only one key possible */ - } else { - range->num_encoding_sizes = 0; - range->max_encoding_tokens = 0; - } - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return ret; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : set quality threshold - */ -static int wavelan_set_qthr(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - unsigned int base = dev->base_addr; - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - psa.psa_quality_thr = *(extra) & 0x0F; - psa_write(dev, - (char *) &psa.psa_quality_thr - (char *) &psa, - (unsigned char *) &psa.psa_quality_thr, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev); - mmc_out(base, mmwoff(0, mmw_quality_thr), - psa.psa_quality_thr); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get quality threshold - */ -static int wavelan_get_qthr(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - psa_t psa; - unsigned long flags; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - psa_read(dev, - (char *) &psa.psa_quality_thr - (char *) &psa, - (unsigned char *) &psa.psa_quality_thr, 1); - *(extra) = psa.psa_quality_thr & 0x0F; - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return 0; -} - -#ifdef WAVELAN_ROAMING -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : set roaming - */ -static int wavelan_set_roam(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - unsigned long flags; - - /* Disable interrupts and save flags. */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Note : should check if user == root */ - if(do_roaming && (*extra)==0) - wv_roam_cleanup(dev); - else if(do_roaming==0 && (*extra)!=0) - wv_roam_init(dev); - - do_roaming = (*extra); - - /* Enable interrupts and restore flags. */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get quality threshold - */ -static int wavelan_get_roam(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - *(extra) = do_roaming; - - return 0; -} -#endif /* WAVELAN_ROAMING */ - -#ifdef HISTOGRAM -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : set histogram - */ -static int wavelan_set_histo(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - - /* Check the number of intervals. */ - if (wrqu->data.length > 16) { - return(-E2BIG); - } - - /* Disable histo while we copy the addresses. - * As we don't disable interrupts, we need to do this */ - lp->his_number = 0; - - /* Are there ranges to copy? */ - if (wrqu->data.length > 0) { - /* Copy interval ranges to the driver */ - memcpy(lp->his_range, extra, wrqu->data.length); - - { - int i; - printk(KERN_DEBUG "Histo :"); - for(i = 0; i < wrqu->data.length; i++) - printk(" %d", lp->his_range[i]); - printk("\n"); - } - - /* Reset result structure. */ - memset(lp->his_sum, 0x00, sizeof(long) * 16); - } - - /* Now we can set the number of ranges */ - lp->his_number = wrqu->data.length; - - return(0); -} - -/*------------------------------------------------------------------*/ -/* - * Wireless Private Handler : get histogram - */ -static int wavelan_get_histo(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - net_local *lp = netdev_priv(dev); - - /* Set the number of intervals. */ - wrqu->data.length = lp->his_number; - - /* Give back the distribution statistics */ - if(lp->his_number > 0) - memcpy(extra, lp->his_sum, sizeof(long) * lp->his_number); - - return(0); -} -#endif /* HISTOGRAM */ - -/*------------------------------------------------------------------*/ -/* - * Structures to export the Wireless Handlers - */ - -static const struct iw_priv_args wavelan_private_args[] = { -/*{ cmd, set_args, get_args, name } */ - { SIOCSIPQTHR, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setqualthr" }, - { SIOCGIPQTHR, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getqualthr" }, - { SIOCSIPROAM, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, 0, "setroam" }, - { SIOCGIPROAM, 0, IW_PRIV_TYPE_BYTE | IW_PRIV_SIZE_FIXED | 1, "getroam" }, - { SIOCSIPHISTO, IW_PRIV_TYPE_BYTE | 16, 0, "sethisto" }, - { SIOCGIPHISTO, 0, IW_PRIV_TYPE_INT | 16, "gethisto" }, -}; - -static const iw_handler wavelan_handler[] = -{ - NULL, /* SIOCSIWNAME */ - wavelan_get_name, /* SIOCGIWNAME */ - wavelan_set_nwid, /* SIOCSIWNWID */ - wavelan_get_nwid, /* SIOCGIWNWID */ - wavelan_set_freq, /* SIOCSIWFREQ */ - wavelan_get_freq, /* SIOCGIWFREQ */ -#ifdef WAVELAN_ROAMING - wavelan_set_mode, /* SIOCSIWMODE */ - wavelan_get_mode, /* SIOCGIWMODE */ -#else /* WAVELAN_ROAMING */ - NULL, /* SIOCSIWMODE */ - NULL, /* SIOCGIWMODE */ -#endif /* WAVELAN_ROAMING */ - wavelan_set_sens, /* SIOCSIWSENS */ - wavelan_get_sens, /* SIOCGIWSENS */ - NULL, /* SIOCSIWRANGE */ - wavelan_get_range, /* SIOCGIWRANGE */ - NULL, /* SIOCSIWPRIV */ - NULL, /* SIOCGIWPRIV */ - NULL, /* SIOCSIWSTATS */ - NULL, /* SIOCGIWSTATS */ - iw_handler_set_spy, /* SIOCSIWSPY */ - iw_handler_get_spy, /* SIOCGIWSPY */ - iw_handler_set_thrspy, /* SIOCSIWTHRSPY */ - iw_handler_get_thrspy, /* SIOCGIWTHRSPY */ -#ifdef WAVELAN_ROAMING_EXT - wavelan_set_wap, /* SIOCSIWAP */ - wavelan_get_wap, /* SIOCGIWAP */ - NULL, /* -- hole -- */ - NULL, /* SIOCGIWAPLIST */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - wavelan_set_essid, /* SIOCSIWESSID */ - wavelan_get_essid, /* SIOCGIWESSID */ -#else /* WAVELAN_ROAMING_EXT */ - NULL, /* SIOCSIWAP */ - NULL, /* SIOCGIWAP */ - NULL, /* -- hole -- */ - NULL, /* SIOCGIWAPLIST */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWESSID */ - NULL, /* SIOCGIWESSID */ -#endif /* WAVELAN_ROAMING_EXT */ - NULL, /* SIOCSIWNICKN */ - NULL, /* SIOCGIWNICKN */ - NULL, /* -- hole -- */ - NULL, /* -- hole -- */ - NULL, /* SIOCSIWRATE */ - NULL, /* SIOCGIWRATE */ - NULL, /* SIOCSIWRTS */ - NULL, /* SIOCGIWRTS */ - NULL, /* SIOCSIWFRAG */ - NULL, /* SIOCGIWFRAG */ - NULL, /* SIOCSIWTXPOW */ - NULL, /* SIOCGIWTXPOW */ - NULL, /* SIOCSIWRETRY */ - NULL, /* SIOCGIWRETRY */ - wavelan_set_encode, /* SIOCSIWENCODE */ - wavelan_get_encode, /* SIOCGIWENCODE */ -}; - -static const iw_handler wavelan_private_handler[] = -{ - wavelan_set_qthr, /* SIOCIWFIRSTPRIV */ - wavelan_get_qthr, /* SIOCIWFIRSTPRIV + 1 */ -#ifdef WAVELAN_ROAMING - wavelan_set_roam, /* SIOCIWFIRSTPRIV + 2 */ - wavelan_get_roam, /* SIOCIWFIRSTPRIV + 3 */ -#else /* WAVELAN_ROAMING */ - NULL, /* SIOCIWFIRSTPRIV + 2 */ - NULL, /* SIOCIWFIRSTPRIV + 3 */ -#endif /* WAVELAN_ROAMING */ -#ifdef HISTOGRAM - wavelan_set_histo, /* SIOCIWFIRSTPRIV + 4 */ - wavelan_get_histo, /* SIOCIWFIRSTPRIV + 5 */ -#endif /* HISTOGRAM */ -}; - -static const struct iw_handler_def wavelan_handler_def = -{ - .num_standard = ARRAY_SIZE(wavelan_handler), - .num_private = ARRAY_SIZE(wavelan_private_handler), - .num_private_args = ARRAY_SIZE(wavelan_private_args), - .standard = wavelan_handler, - .private = wavelan_private_handler, - .private_args = wavelan_private_args, - .get_wireless_stats = wavelan_get_wireless_stats, -}; - -/*------------------------------------------------------------------*/ -/* - * Get wireless statistics - * Called by /proc/net/wireless... - */ -static iw_stats * -wavelan_get_wireless_stats(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - net_local * lp = netdev_priv(dev); - mmr_t m; - iw_stats * wstats; - unsigned long flags; - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: ->wavelan_get_wireless_stats()\n", dev->name); -#endif - - /* Disable interrupts & save flags */ - spin_lock_irqsave(&lp->spinlock, flags); - - wstats = &lp->wstats; - - /* Get data from the mmc */ - mmc_out(base, mmwoff(0, mmw_freeze), 1); - - mmc_read(base, mmroff(0, mmr_dce_status), &m.mmr_dce_status, 1); - mmc_read(base, mmroff(0, mmr_wrong_nwid_l), &m.mmr_wrong_nwid_l, 2); - mmc_read(base, mmroff(0, mmr_thr_pre_set), &m.mmr_thr_pre_set, 4); - - mmc_out(base, mmwoff(0, mmw_freeze), 0); - - /* Copy data to wireless stuff */ - wstats->status = m.mmr_dce_status & MMR_DCE_STATUS; - wstats->qual.qual = m.mmr_sgnl_qual & MMR_SGNL_QUAL; - wstats->qual.level = m.mmr_signal_lvl & MMR_SIGNAL_LVL; - wstats->qual.noise = m.mmr_silence_lvl & MMR_SILENCE_LVL; - wstats->qual.updated = (((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 7) | - ((m.mmr_signal_lvl & MMR_SIGNAL_LVL_VALID) >> 6) | - ((m.mmr_silence_lvl & MMR_SILENCE_LVL_VALID) >> 5)); - wstats->discard.nwid += (m.mmr_wrong_nwid_h << 8) | m.mmr_wrong_nwid_l; - wstats->discard.code = 0L; - wstats->discard.misc = 0L; - - /* ReEnable interrupts & restore flags */ - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_IOCTL_TRACE - printk(KERN_DEBUG "%s: <-wavelan_get_wireless_stats()\n", dev->name); -#endif - return &lp->wstats; -} - -/************************* PACKET RECEPTION *************************/ -/* - * This part deal with receiving the packets. - * The interrupt handler get an interrupt when a packet has been - * successfully received and called this part... - */ - -/*------------------------------------------------------------------*/ -/* - * Calculate the starting address of the frame pointed to by the receive - * frame pointer and verify that the frame seem correct - * (called by wv_packet_rcv()) - */ -static int -wv_start_of_frame(struct net_device * dev, - int rfp, /* end of frame */ - int wrap) /* start of buffer */ -{ - unsigned int base = dev->base_addr; - int rp; - int len; - - rp = (rfp - 5 + RX_SIZE) % RX_SIZE; - outb(rp & 0xff, PIORL(base)); - outb(((rp >> 8) & PIORH_MASK), PIORH(base)); - len = inb(PIOP(base)); - len |= inb(PIOP(base)) << 8; - - /* Sanity checks on size */ - /* Frame too big */ - if(len > MAXDATAZ + 100) - { -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_start_of_frame: Received frame too large, rfp %d len 0x%x\n", - dev->name, rfp, len); -#endif - return(-1); - } - - /* Frame too short */ - if(len < 7) - { -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_start_of_frame: Received null frame, rfp %d len 0x%x\n", - dev->name, rfp, len); -#endif - return(-1); - } - - /* Wrap around buffer */ - if(len > ((wrap - (rfp - len) + RX_SIZE) % RX_SIZE)) /* magic formula ! */ - { -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_start_of_frame: wrap around buffer, wrap %d rfp %d len 0x%x\n", - dev->name, wrap, rfp, len); -#endif - return(-1); - } - - return((rp - len + RX_SIZE) % RX_SIZE); -} /* wv_start_of_frame */ - -/*------------------------------------------------------------------*/ -/* - * This routine does the actual copy of data (including the ethernet - * header structure) from the WaveLAN card to an sk_buff chain that - * will be passed up to the network interface layer. NOTE: We - * currently don't handle trailer protocols (neither does the rest of - * the network interface), so if that is needed, it will (at least in - * part) be added here. The contents of the receive ring buffer are - * copied to a message chain that is then passed to the kernel. - * - * Note: if any errors occur, the packet is "dropped on the floor" - * (called by wv_packet_rcv()) - */ -static void -wv_packet_read(struct net_device * dev, - int fd_p, - int sksize) -{ - net_local * lp = netdev_priv(dev); - struct sk_buff * skb; - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_read(0x%X, %d)\n", - dev->name, fd_p, sksize); -#endif - - /* Allocate some buffer for the new packet */ - if((skb = dev_alloc_skb(sksize+2)) == (struct sk_buff *) NULL) - { -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "%s: wv_packet_read(): could not alloc_skb(%d, GFP_ATOMIC)\n", - dev->name, sksize); -#endif - dev->stats.rx_dropped++; - /* - * Not only do we want to return here, but we also need to drop the - * packet on the floor to clear the interrupt. - */ - return; - } - - skb_reserve(skb, 2); - fd_p = read_ringbuf(dev, fd_p, (char *) skb_put(skb, sksize), sksize); - skb->protocol = eth_type_trans(skb, dev); - -#ifdef DEBUG_RX_INFO - wv_packet_info(skb_mac_header(skb), sksize, dev->name, "wv_packet_read"); -#endif /* DEBUG_RX_INFO */ - - /* Statistics gathering & stuff associated. - * It seem a bit messy with all the define, but it's really simple... */ - if( -#ifdef IW_WIRELESS_SPY - (lp->spy_data.spy_number > 0) || -#endif /* IW_WIRELESS_SPY */ -#ifdef HISTOGRAM - (lp->his_number > 0) || -#endif /* HISTOGRAM */ -#ifdef WAVELAN_ROAMING - (do_roaming) || -#endif /* WAVELAN_ROAMING */ - 0) - { - u_char stats[3]; /* Signal level, Noise level, Signal quality */ - - /* read signal level, silence level and signal quality bytes */ - fd_p = read_ringbuf(dev, (fd_p + 4) % RX_SIZE + RX_BASE, - stats, 3); -#ifdef DEBUG_RX_INFO - printk(KERN_DEBUG "%s: wv_packet_read(): Signal level %d/63, Silence level %d/63, signal quality %d/16\n", - dev->name, stats[0] & 0x3F, stats[1] & 0x3F, stats[2] & 0x0F); -#endif - -#ifdef WAVELAN_ROAMING - if(do_roaming) - if(WAVELAN_BEACON(skb->data)) - wl_roam_gather(dev, skb->data, stats); -#endif /* WAVELAN_ROAMING */ - -#ifdef WIRELESS_SPY - wl_spy_gather(dev, skb_mac_header(skb) + WAVELAN_ADDR_SIZE, stats); -#endif /* WIRELESS_SPY */ -#ifdef HISTOGRAM - wl_his_gather(dev, stats); -#endif /* HISTOGRAM */ - } - - /* - * Hand the packet to the Network Module - */ - netif_rx(skb); - - /* Keep stats up to date */ - dev->stats.rx_packets++; - dev->stats.rx_bytes += sksize; - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_read()\n", dev->name); -#endif - return; -} - -/*------------------------------------------------------------------*/ -/* - * This routine is called by the interrupt handler to initiate a - * packet transfer from the card to the network interface layer above - * this driver. This routine checks if a buffer has been successfully - * received by the WaveLAN card. If so, the routine wv_packet_read is - * called to do the actual transfer of the card's data including the - * ethernet header into a packet consisting of an sk_buff chain. - * (called by wavelan_interrupt()) - * Note : the spinlock is already grabbed for us and irq are disabled. - */ -static void -wv_packet_rcv(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - net_local * lp = netdev_priv(dev); - int newrfp; - int rp; - int len; - int f_start; - int status; - int i593_rfp; - int stat_ptr; - u_char c[4]; - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_rcv()\n", dev->name); -#endif - - /* Get the new receive frame pointer from the i82593 chip */ - outb(CR0_STATUS_2 | OP0_NOP, LCCR(base)); - i593_rfp = inb(LCSR(base)); - i593_rfp |= inb(LCSR(base)) << 8; - i593_rfp %= RX_SIZE; - - /* Get the new receive frame pointer from the WaveLAN card. - * It is 3 bytes more than the increment of the i82593 receive - * frame pointer, for each packet. This is because it includes the - * 3 roaming bytes added by the mmc. - */ - newrfp = inb(RPLL(base)); - newrfp |= inb(RPLH(base)) << 8; - newrfp %= RX_SIZE; - -#ifdef DEBUG_RX_INFO - printk(KERN_DEBUG "%s: wv_packet_rcv(): i593_rfp %d stop %d newrfp %d lp->rfp %d\n", - dev->name, i593_rfp, lp->stop, newrfp, lp->rfp); -#endif - -#ifdef DEBUG_RX_ERROR - /* If no new frame pointer... */ - if(lp->overrunning || newrfp == lp->rfp) - printk(KERN_INFO "%s: wv_packet_rcv(): no new frame: i593_rfp %d stop %d newrfp %d lp->rfp %d\n", - dev->name, i593_rfp, lp->stop, newrfp, lp->rfp); -#endif - - /* Read all frames (packets) received */ - while(newrfp != lp->rfp) - { - /* A frame is composed of the packet, followed by a status word, - * the length of the frame (word) and the mmc info (SNR & qual). - * It's because the length is at the end that we can only scan - * frames backward. */ - - /* Find the first frame by skipping backwards over the frames */ - rp = newrfp; /* End of last frame */ - while(((f_start = wv_start_of_frame(dev, rp, newrfp)) != lp->rfp) && - (f_start != -1)) - rp = f_start; - - /* If we had a problem */ - if(f_start == -1) - { -#ifdef DEBUG_RX_ERROR - printk(KERN_INFO "wavelan_cs: cannot find start of frame "); - printk(" i593_rfp %d stop %d newrfp %d lp->rfp %d\n", - i593_rfp, lp->stop, newrfp, lp->rfp); -#endif - lp->rfp = rp; /* Get to the last usable frame */ - continue; - } - - /* f_start point to the beggining of the first frame received - * and rp to the beggining of the next one */ - - /* Read status & length of the frame */ - stat_ptr = (rp - 7 + RX_SIZE) % RX_SIZE; - stat_ptr = read_ringbuf(dev, stat_ptr, c, 4); - status = c[0] | (c[1] << 8); - len = c[2] | (c[3] << 8); - - /* Check status */ - if((status & RX_RCV_OK) != RX_RCV_OK) - { - dev->stats.rx_errors++; - if(status & RX_NO_SFD) - dev->stats.rx_frame_errors++; - if(status & RX_CRC_ERR) - dev->stats.rx_crc_errors++; - if(status & RX_OVRRUN) - dev->stats.rx_over_errors++; - -#ifdef DEBUG_RX_FAIL - printk(KERN_DEBUG "%s: wv_packet_rcv(): packet not received ok, status = 0x%x\n", - dev->name, status); -#endif - } - else - /* Read the packet and transmit to Linux */ - wv_packet_read(dev, f_start, len - 2); - - /* One frame has been processed, skip it */ - lp->rfp = rp; - } - - /* - * Update the frame stop register, but set it to less than - * the full 8K to allow space for 3 bytes of signal strength - * per packet. - */ - lp->stop = (i593_rfp + RX_SIZE - ((RX_SIZE / 64) * 3)) % RX_SIZE; - outb(OP0_SWIT_TO_PORT_1 | CR0_CHNL, LCCR(base)); - outb(CR1_STOP_REG_UPDATE | (lp->stop >> RX_SIZE_SHIFT), LCCR(base)); - outb(OP1_SWIT_TO_PORT_0, LCCR(base)); - -#ifdef DEBUG_RX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_rcv()\n", dev->name); -#endif -} - -/*********************** PACKET TRANSMISSION ***********************/ -/* - * This part deal with sending packet through the wavelan - * We copy the packet to the send buffer and then issue the send - * command to the i82593. The result of this operation will be - * checked in wavelan_interrupt() - */ - -/*------------------------------------------------------------------*/ -/* - * This routine fills in the appropriate registers and memory - * locations on the WaveLAN card and starts the card off on - * the transmit. - * (called in wavelan_packet_xmit()) - */ -static void -wv_packet_write(struct net_device * dev, - void * buf, - short length) -{ - net_local * lp = netdev_priv(dev); - unsigned int base = dev->base_addr; - unsigned long flags; - int clen = length; - register u_short xmtdata_base = TX_BASE; - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wv_packet_write(%d)\n", dev->name, length); -#endif - - spin_lock_irqsave(&lp->spinlock, flags); - - /* Write the length of data buffer followed by the buffer */ - outb(xmtdata_base & 0xff, PIORL(base)); - outb(((xmtdata_base >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); - outb(clen & 0xff, PIOP(base)); /* lsb */ - outb(clen >> 8, PIOP(base)); /* msb */ - - /* Send the data */ - outsb(PIOP(base), buf, clen); - - /* Indicate end of transmit chain */ - outb(OP0_NOP, PIOP(base)); - /* josullvn@cs.cmu.edu: need to send a second NOP for alignment... */ - outb(OP0_NOP, PIOP(base)); - - /* Reset the transmit DMA pointer */ - hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET); - hacr_write(base, HACR_DEFAULT); - /* Send the transmit command */ - wv_82593_cmd(dev, "wv_packet_write(): transmit", - OP0_TRANSMIT, SR0_NO_RESULT); - - /* Make sure the watchdog will keep quiet for a while */ - dev->trans_start = jiffies; - - /* Keep stats up to date */ - dev->stats.tx_bytes += length; - - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_TX_INFO - wv_packet_info((u_char *) buf, length, dev->name, "wv_packet_write"); -#endif /* DEBUG_TX_INFO */ - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wv_packet_write()\n", dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * This routine is called when we want to send a packet (NET3 callback) - * In this routine, we check if the harware is ready to accept - * the packet. We also prevent reentrance. Then, we call the function - * to send the packet... - */ -static netdev_tx_t -wavelan_packet_xmit(struct sk_buff * skb, - struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - unsigned long flags; - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: ->wavelan_packet_xmit(0x%X)\n", dev->name, - (unsigned) skb); -#endif - - /* - * Block a timer-based transmit from overlapping a previous transmit. - * In other words, prevent reentering this routine. - */ - netif_stop_queue(dev); - - /* If somebody has asked to reconfigure the controller, - * we can do it now */ - if(lp->reconfig_82593) - { - spin_lock_irqsave(&lp->spinlock, flags); /* Disable interrupts */ - wv_82593_config(dev); - spin_unlock_irqrestore(&lp->spinlock, flags); /* Re-enable interrupts */ - /* Note : the configure procedure was totally synchronous, - * so the Tx buffer is now free */ - } - - /* Check if we need some padding */ - /* Note : on wireless the propagation time is in the order of 1us, - * and we don't have the Ethernet specific requirement of beeing - * able to detect collisions, therefore in theory we don't really - * need to pad. Jean II */ - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - - wv_packet_write(dev, skb->data, skb->len); - - dev_kfree_skb(skb); - -#ifdef DEBUG_TX_TRACE - printk(KERN_DEBUG "%s: <-wavelan_packet_xmit()\n", dev->name); -#endif - return NETDEV_TX_OK; -} - -/********************** HARDWARE CONFIGURATION **********************/ -/* - * This part do the real job of starting and configuring the hardware. - */ - -/*------------------------------------------------------------------*/ -/* - * Routine to initialize the Modem Management Controller. - * (called by wv_hw_config()) - */ -static int -wv_mmc_init(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - psa_t psa; - mmw_t m; - int configured; - int i; /* Loop counter */ - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_mmc_init()\n", dev->name); -#endif - - /* Read the parameter storage area */ - psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); - - /* - * Check the first three octets of the MAC addr for the manufacturer's code. - * Note: If you get the error message below, you've got a - * non-NCR/AT&T/Lucent PCMCIA cards, see wavelan_cs.h for detail on - * how to configure your card... - */ - for (i = 0; i < ARRAY_SIZE(MAC_ADDRESSES); i++) - if ((psa.psa_univ_mac_addr[0] == MAC_ADDRESSES[i][0]) && - (psa.psa_univ_mac_addr[1] == MAC_ADDRESSES[i][1]) && - (psa.psa_univ_mac_addr[2] == MAC_ADDRESSES[i][2])) - break; - - /* If we have not found it... */ - if (i == ARRAY_SIZE(MAC_ADDRESSES)) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wv_mmc_init(): Invalid MAC address: %02X:%02X:%02X:...\n", - dev->name, psa.psa_univ_mac_addr[0], - psa.psa_univ_mac_addr[1], psa.psa_univ_mac_addr[2]); -#endif - return FALSE; - } - - /* Get the MAC address */ - memcpy(&dev->dev_addr[0], &psa.psa_univ_mac_addr[0], WAVELAN_ADDR_SIZE); - -#ifdef USE_PSA_CONFIG - configured = psa.psa_conf_status & 1; -#else - configured = 0; -#endif - - /* Is the PSA is not configured */ - if(!configured) - { - /* User will be able to configure NWID after (with iwconfig) */ - psa.psa_nwid[0] = 0; - psa.psa_nwid[1] = 0; - - /* As NWID is not set : no NWID checking */ - psa.psa_nwid_select = 0; - - /* Disable encryption */ - psa.psa_encryption_select = 0; - - /* Set to standard values - * 0x04 for AT, - * 0x01 for MCA, - * 0x04 for PCMCIA and 2.00 card (AT&T 407-024689/E document) - */ - if (psa.psa_comp_number & 1) - psa.psa_thr_pre_set = 0x01; - else - psa.psa_thr_pre_set = 0x04; - psa.psa_quality_thr = 0x03; - - /* It is configured */ - psa.psa_conf_status |= 1; - -#ifdef USE_PSA_CONFIG - /* Write the psa */ - psa_write(dev, (char *)psa.psa_nwid - (char *)&psa, - (unsigned char *)psa.psa_nwid, 4); - psa_write(dev, (char *)&psa.psa_thr_pre_set - (char *)&psa, - (unsigned char *)&psa.psa_thr_pre_set, 1); - psa_write(dev, (char *)&psa.psa_quality_thr - (char *)&psa, - (unsigned char *)&psa.psa_quality_thr, 1); - psa_write(dev, (char *)&psa.psa_conf_status - (char *)&psa, - (unsigned char *)&psa.psa_conf_status, 1); - /* update the Wavelan checksum */ - update_psa_checksum(dev); -#endif /* USE_PSA_CONFIG */ - } - - /* Zero the mmc structure */ - memset(&m, 0x00, sizeof(m)); - - /* Copy PSA info to the mmc */ - m.mmw_netw_id_l = psa.psa_nwid[1]; - m.mmw_netw_id_h = psa.psa_nwid[0]; - - if(psa.psa_nwid_select & 1) - m.mmw_loopt_sel = 0x00; - else - m.mmw_loopt_sel = MMW_LOOPT_SEL_DIS_NWID; - - memcpy(&m.mmw_encr_key, &psa.psa_encryption_key, - sizeof(m.mmw_encr_key)); - - if(psa.psa_encryption_select) - m.mmw_encr_enable = MMW_ENCR_ENABLE_EN | MMW_ENCR_ENABLE_MODE; - else - m.mmw_encr_enable = 0; - - m.mmw_thr_pre_set = psa.psa_thr_pre_set & 0x3F; - m.mmw_quality_thr = psa.psa_quality_thr & 0x0F; - - /* - * Set default modem control parameters. - * See NCR document 407-0024326 Rev. A. - */ - m.mmw_jabber_enable = 0x01; - m.mmw_anten_sel = MMW_ANTEN_SEL_ALG_EN; - m.mmw_ifs = 0x20; - m.mmw_mod_delay = 0x04; - m.mmw_jam_time = 0x38; - - m.mmw_des_io_invert = 0; - m.mmw_freeze = 0; - m.mmw_decay_prm = 0; - m.mmw_decay_updat_prm = 0; - - /* Write all info to mmc */ - mmc_write(base, 0, (u_char *)&m, sizeof(m)); - - /* The following code start the modem of the 2.00 frequency - * selectable cards at power on. It's not strictly needed for the - * following boots... - * The original patch was by Joe Finney for the PCMCIA driver, but - * I've cleaned it a bit and add documentation. - * Thanks to Loeke Brederveld from Lucent for the info. - */ - - /* Attempt to recognise 2.00 cards (2.4 GHz frequency selectable) - * (does it work for everybody ? - especially old cards...) */ - /* Note : WFREQSEL verify that it is able to read from EEprom - * a sensible frequency (address 0x00) + that MMR_FEE_STATUS_ID - * is 0xA (Xilinx version) or 0xB (Ariadne version). - * My test is more crude but do work... */ - if(!(mmc_in(base, mmroff(0, mmr_fee_status)) & - (MMR_FEE_STATUS_DWLD | MMR_FEE_STATUS_BUSY))) - { - /* We must download the frequency parameters to the - * synthetisers (from the EEprom - area 1) - * Note : as the EEprom is auto decremented, we set the end - * if the area... */ - m.mmw_fee_addr = 0x0F; - m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; - mmc_write(base, (char *)&m.mmw_fee_ctrl - (char *)&m, - (unsigned char *)&m.mmw_fee_ctrl, 2); - - /* Wait until the download is finished */ - fee_wait(base, 100, 100); - -#ifdef DEBUG_CONFIG_INFO - /* The frequency was in the last word downloaded... */ - mmc_read(base, (char *)&m.mmw_fee_data_l - (char *)&m, - (unsigned char *)&m.mmw_fee_data_l, 2); - - /* Print some info for the user */ - printk(KERN_DEBUG "%s: Wavelan 2.00 recognised (frequency select) : Current frequency = %ld\n", - dev->name, - ((m.mmw_fee_data_h << 4) | - (m.mmw_fee_data_l >> 4)) * 5 / 2 + 24000L); -#endif - - /* We must now download the power adjust value (gain) to - * the synthetisers (from the EEprom - area 7 - DAC) */ - m.mmw_fee_addr = 0x61; - m.mmw_fee_ctrl = MMW_FEE_CTRL_READ | MMW_FEE_CTRL_DWLD; - mmc_write(base, (char *)&m.mmw_fee_ctrl - (char *)&m, - (unsigned char *)&m.mmw_fee_ctrl, 2); - - /* Wait until the download is finished */ - } /* if 2.00 card */ - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_mmc_init()\n", dev->name); -#endif - return TRUE; -} - -/*------------------------------------------------------------------*/ -/* - * Routine to gracefully turn off reception, and wait for any commands - * to complete. - * (called in wv_ru_start() and wavelan_close() and wavelan_event()) - */ -static int -wv_ru_stop(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - net_local * lp = netdev_priv(dev); - unsigned long flags; - int status; - int spin; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_ru_stop()\n", dev->name); -#endif - - spin_lock_irqsave(&lp->spinlock, flags); - - /* First, send the LAN controller a stop receive command */ - wv_82593_cmd(dev, "wv_graceful_shutdown(): stop-rcv", - OP0_STOP_RCV, SR0_NO_RESULT); - - /* Then, spin until the receive unit goes idle */ - spin = 300; - do - { - udelay(10); - outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); - status = inb(LCSR(base)); - } - while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_IDLE) && (spin-- > 0)); - - /* Now, spin until the chip finishes executing its current command */ - do - { - udelay(10); - outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); - status = inb(LCSR(base)); - } - while(((status & SR3_EXEC_STATE_MASK) != SR3_EXEC_IDLE) && (spin-- > 0)); - - spin_unlock_irqrestore(&lp->spinlock, flags); - - /* If there was a problem */ - if(spin <= 0) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_INFO "%s: wv_ru_stop(): The chip doesn't want to stop...\n", - dev->name); -#endif - return FALSE; - } - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_ru_stop()\n", dev->name); -#endif - return TRUE; -} /* wv_ru_stop */ - -/*------------------------------------------------------------------*/ -/* - * This routine starts the receive unit running. First, it checks if - * the card is actually ready. Then the card is instructed to receive - * packets again. - * (called in wv_hw_reset() & wavelan_open()) - */ -static int -wv_ru_start(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - net_local * lp = netdev_priv(dev); - unsigned long flags; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_ru_start()\n", dev->name); -#endif - - /* - * We need to start from a quiescent state. To do so, we could check - * if the card is already running, but instead we just try to shut - * it down. First, we disable reception (in case it was already enabled). - */ - if(!wv_ru_stop(dev)) - return FALSE; - - spin_lock_irqsave(&lp->spinlock, flags); - - /* Now we know that no command is being executed. */ - - /* Set the receive frame pointer and stop pointer */ - lp->rfp = 0; - outb(OP0_SWIT_TO_PORT_1 | CR0_CHNL, LCCR(base)); - - /* Reset ring management. This sets the receive frame pointer to 1 */ - outb(OP1_RESET_RING_MNGMT, LCCR(base)); - -#if 0 - /* XXX the i82593 manual page 6-4 seems to indicate that the stop register - should be set as below */ - /* outb(CR1_STOP_REG_UPDATE|((RX_SIZE - 0x40)>> RX_SIZE_SHIFT),LCCR(base));*/ -#elif 0 - /* but I set it 0 instead */ - lp->stop = 0; -#else - /* but I set it to 3 bytes per packet less than 8K */ - lp->stop = (0 + RX_SIZE - ((RX_SIZE / 64) * 3)) % RX_SIZE; -#endif - outb(CR1_STOP_REG_UPDATE | (lp->stop >> RX_SIZE_SHIFT), LCCR(base)); - outb(OP1_INT_ENABLE, LCCR(base)); - outb(OP1_SWIT_TO_PORT_0, LCCR(base)); - - /* Reset receive DMA pointer */ - hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET); - hacr_write_slow(base, HACR_DEFAULT); - - /* Receive DMA on channel 1 */ - wv_82593_cmd(dev, "wv_ru_start(): rcv-enable", - CR0_CHNL | OP0_RCV_ENABLE, SR0_NO_RESULT); - -#ifdef DEBUG_I82593_SHOW - { - int status; - int opri; - int spin = 10000; - - /* spin until the chip starts receiving */ - do - { - outb(OP0_NOP | CR0_STATUS_3, LCCR(base)); - status = inb(LCSR(base)); - if(spin-- <= 0) - break; - } - while(((status & SR3_RCV_STATE_MASK) != SR3_RCV_ACTIVE) && - ((status & SR3_RCV_STATE_MASK) != SR3_RCV_READY)); - printk(KERN_DEBUG "rcv status is 0x%x [i:%d]\n", - (status & SR3_RCV_STATE_MASK), i); - } -#endif - - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_ru_start()\n", dev->name); -#endif - return TRUE; -} - -/*------------------------------------------------------------------*/ -/* - * This routine does a standard config of the WaveLAN controller (i82593). - * In the ISA driver, this is integrated in wavelan_hardware_reset() - * (called by wv_hw_config(), wv_82593_reconfig() & wavelan_packet_xmit()) - */ -static int -wv_82593_config(struct net_device * dev) -{ - unsigned int base = dev->base_addr; - net_local * lp = netdev_priv(dev); - struct i82593_conf_block cfblk; - int ret = TRUE; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_82593_config()\n", dev->name); -#endif - - /* Create & fill i82593 config block - * - * Now conform to Wavelan document WCIN085B - */ - memset(&cfblk, 0x00, sizeof(struct i82593_conf_block)); - cfblk.d6mod = FALSE; /* Run in i82593 advanced mode */ - cfblk.fifo_limit = 5; /* = 56 B rx and 40 B tx fifo thresholds */ - cfblk.forgnesi = FALSE; /* 0=82C501, 1=AMD7992B compatibility */ - cfblk.fifo_32 = 1; - cfblk.throttle_enb = FALSE; - cfblk.contin = TRUE; /* enable continuous mode */ - cfblk.cntrxint = FALSE; /* enable continuous mode receive interrupts */ - cfblk.addr_len = WAVELAN_ADDR_SIZE; - cfblk.acloc = TRUE; /* Disable source addr insertion by i82593 */ - cfblk.preamb_len = 0; /* 2 bytes preamble (SFD) */ - cfblk.loopback = FALSE; - cfblk.lin_prio = 0; /* conform to 802.3 backoff algorithm */ - cfblk.exp_prio = 5; /* conform to 802.3 backoff algorithm */ - cfblk.bof_met = 1; /* conform to 802.3 backoff algorithm */ - cfblk.ifrm_spc = 0x20 >> 4; /* 32 bit times interframe spacing */ - cfblk.slottim_low = 0x20 >> 5; /* 32 bit times slot time */ - cfblk.slottim_hi = 0x0; - cfblk.max_retr = 15; - cfblk.prmisc = ((lp->promiscuous) ? TRUE: FALSE); /* Promiscuous mode */ - cfblk.bc_dis = FALSE; /* Enable broadcast reception */ - cfblk.crs_1 = TRUE; /* Transmit without carrier sense */ - cfblk.nocrc_ins = FALSE; /* i82593 generates CRC */ - cfblk.crc_1632 = FALSE; /* 32-bit Autodin-II CRC */ - cfblk.crs_cdt = FALSE; /* CD not to be interpreted as CS */ - cfblk.cs_filter = 0; /* CS is recognized immediately */ - cfblk.crs_src = FALSE; /* External carrier sense */ - cfblk.cd_filter = 0; /* CD is recognized immediately */ - cfblk.min_fr_len = ETH_ZLEN >> 2; /* Minimum frame length 64 bytes */ - cfblk.lng_typ = FALSE; /* Length field > 1500 = type field */ - cfblk.lng_fld = TRUE; /* Disable 802.3 length field check */ - cfblk.rxcrc_xf = TRUE; /* Don't transfer CRC to memory */ - cfblk.artx = TRUE; /* Disable automatic retransmission */ - cfblk.sarec = TRUE; /* Disable source addr trig of CD */ - cfblk.tx_jabber = TRUE; /* Disable jabber jam sequence */ - cfblk.hash_1 = FALSE; /* Use bits 0-5 in mc address hash */ - cfblk.lbpkpol = TRUE; /* Loopback pin active high */ - cfblk.fdx = FALSE; /* Disable full duplex operation */ - cfblk.dummy_6 = 0x3f; /* all ones */ - cfblk.mult_ia = FALSE; /* No multiple individual addresses */ - cfblk.dis_bof = FALSE; /* Disable the backoff algorithm ?! */ - cfblk.dummy_1 = TRUE; /* set to 1 */ - cfblk.tx_ifs_retrig = 3; /* Hmm... Disabled */ -#ifdef MULTICAST_ALL - cfblk.mc_all = (lp->allmulticast ? TRUE: FALSE); /* Allow all multicasts */ -#else - cfblk.mc_all = FALSE; /* No multicast all mode */ -#endif - cfblk.rcv_mon = 0; /* Monitor mode disabled */ - cfblk.frag_acpt = TRUE; /* Do not accept fragments */ - cfblk.tstrttrs = FALSE; /* No start transmission threshold */ - cfblk.fretx = TRUE; /* FIFO automatic retransmission */ - cfblk.syncrqs = FALSE; /* Synchronous DRQ deassertion... */ - cfblk.sttlen = TRUE; /* 6 byte status registers */ - cfblk.rx_eop = TRUE; /* Signal EOP on packet reception */ - cfblk.tx_eop = TRUE; /* Signal EOP on packet transmission */ - cfblk.rbuf_size = RX_SIZE>>11; /* Set receive buffer size */ - cfblk.rcvstop = TRUE; /* Enable Receive Stop Register */ - -#ifdef DEBUG_I82593_SHOW - print_hex_dump(KERN_DEBUG, "wavelan_cs: config block: ", DUMP_PREFIX_NONE, - 16, 1, &cfblk, sizeof(struct i82593_conf_block), false); -#endif - - /* Copy the config block to the i82593 */ - outb(TX_BASE & 0xff, PIORL(base)); - outb(((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); - outb(sizeof(struct i82593_conf_block) & 0xff, PIOP(base)); /* lsb */ - outb(sizeof(struct i82593_conf_block) >> 8, PIOP(base)); /* msb */ - outsb(PIOP(base), (char *) &cfblk, sizeof(struct i82593_conf_block)); - - /* reset transmit DMA pointer */ - hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET); - hacr_write(base, HACR_DEFAULT); - if(!wv_82593_cmd(dev, "wv_82593_config(): configure", - OP0_CONFIGURE, SR0_CONFIGURE_DONE)) - ret = FALSE; - - /* Initialize adapter's ethernet MAC address */ - outb(TX_BASE & 0xff, PIORL(base)); - outb(((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); - outb(WAVELAN_ADDR_SIZE, PIOP(base)); /* byte count lsb */ - outb(0, PIOP(base)); /* byte count msb */ - outsb(PIOP(base), &dev->dev_addr[0], WAVELAN_ADDR_SIZE); - - /* reset transmit DMA pointer */ - hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET); - hacr_write(base, HACR_DEFAULT); - if(!wv_82593_cmd(dev, "wv_82593_config(): ia-setup", - OP0_IA_SETUP, SR0_IA_SETUP_DONE)) - ret = FALSE; - -#ifdef WAVELAN_ROAMING - /* If roaming is enabled, join the "Beacon Request" multicast group... */ - /* But only if it's not in there already! */ - if(do_roaming) - dev_mc_add(dev,WAVELAN_BEACON_ADDRESS, WAVELAN_ADDR_SIZE, 1); -#endif /* WAVELAN_ROAMING */ - - /* If any multicast address to set */ - if(lp->mc_count) - { - struct dev_mc_list * dmi; - int addrs_len = WAVELAN_ADDR_SIZE * lp->mc_count; - -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wv_hw_config(): set %d multicast addresses:\n", - dev->name, lp->mc_count); - for(dmi=dev->mc_list; dmi; dmi=dmi->next) - printk(KERN_DEBUG " %pM\n", dmi->dmi_addr); -#endif - - /* Initialize adapter's ethernet multicast addresses */ - outb(TX_BASE & 0xff, PIORL(base)); - outb(((TX_BASE >> 8) & PIORH_MASK) | PIORH_SEL_TX, PIORH(base)); - outb(addrs_len & 0xff, PIOP(base)); /* byte count lsb */ - outb((addrs_len >> 8), PIOP(base)); /* byte count msb */ - for(dmi=dev->mc_list; dmi; dmi=dmi->next) - outsb(PIOP(base), dmi->dmi_addr, dmi->dmi_addrlen); - - /* reset transmit DMA pointer */ - hacr_write_slow(base, HACR_PWR_STAT | HACR_TX_DMA_RESET); - hacr_write(base, HACR_DEFAULT); - if(!wv_82593_cmd(dev, "wv_82593_config(): mc-setup", - OP0_MC_SETUP, SR0_MC_SETUP_DONE)) - ret = FALSE; - lp->mc_count = dev->mc_count; /* remember to avoid repeated reset */ - } - - /* Job done, clear the flag */ - lp->reconfig_82593 = FALSE; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_82593_config()\n", dev->name); -#endif - return(ret); -} - -/*------------------------------------------------------------------*/ -/* - * Read the Access Configuration Register, perform a software reset, - * and then re-enable the card's software. - * - * If I understand correctly : reset the pcmcia interface of the - * wavelan. - * (called by wv_config()) - */ -static int -wv_pcmcia_reset(struct net_device * dev) -{ - int i; - conf_reg_t reg = { 0, CS_READ, CISREG_COR, 0 }; - struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_pcmcia_reset()\n", dev->name); -#endif - - i = pcmcia_access_configuration_register(link, ®); - if (i != 0) - { - cs_error(link, AccessConfigurationRegister, i); - return FALSE; - } - -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wavelan_pcmcia_reset(): Config reg is 0x%x\n", - dev->name, (u_int) reg.Value); -#endif - - reg.Action = CS_WRITE; - reg.Value = reg.Value | COR_SW_RESET; - i = pcmcia_access_configuration_register(link, ®); - if (i != 0) - { - cs_error(link, AccessConfigurationRegister, i); - return FALSE; - } - - reg.Action = CS_WRITE; - reg.Value = COR_LEVEL_IRQ | COR_CONFIG; - i = pcmcia_access_configuration_register(link, ®); - if (i != 0) - { - cs_error(link, AccessConfigurationRegister, i); - return FALSE; - } - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_pcmcia_reset()\n", dev->name); -#endif - return TRUE; -} - -/*------------------------------------------------------------------*/ -/* - * wavelan_hw_config() is called after a CARD_INSERTION event is - * received, to configure the wavelan hardware. - * Note that the reception will be enabled in wavelan->open(), so the - * device is configured but idle... - * Performs the following actions: - * 1. A pcmcia software reset (using wv_pcmcia_reset()) - * 2. A power reset (reset DMA) - * 3. Reset the LAN controller - * 4. Initialize the radio modem (using wv_mmc_init) - * 5. Configure LAN controller (using wv_82593_config) - * 6. Perform a diagnostic on the LAN controller - * (called by wavelan_event() & wv_hw_reset()) - */ -static int -wv_hw_config(struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - unsigned int base = dev->base_addr; - unsigned long flags; - int ret = FALSE; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_hw_config()\n", dev->name); -#endif - - /* compile-time check the sizes of structures */ - BUILD_BUG_ON(sizeof(psa_t) != PSA_SIZE); - BUILD_BUG_ON(sizeof(mmw_t) != MMW_SIZE); - BUILD_BUG_ON(sizeof(mmr_t) != MMR_SIZE); - - /* Reset the pcmcia interface */ - if(wv_pcmcia_reset(dev) == FALSE) - return FALSE; - - /* Disable interrupts */ - spin_lock_irqsave(&lp->spinlock, flags); - - /* Disguised goto ;-) */ - do - { - /* Power UP the module + reset the modem + reset host adapter - * (in fact, reset DMA channels) */ - hacr_write_slow(base, HACR_RESET); - hacr_write(base, HACR_DEFAULT); - - /* Check if the module has been powered up... */ - if(hasr_read(base) & HASR_NO_CLK) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wv_hw_config(): modem not connected or not a wavelan card\n", - dev->name); -#endif - break; - } - - /* initialize the modem */ - if(wv_mmc_init(dev) == FALSE) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wv_hw_config(): Can't configure the modem\n", - dev->name); -#endif - break; - } - - /* reset the LAN controller (i82593) */ - outb(OP0_RESET, LCCR(base)); - mdelay(1); /* A bit crude ! */ - - /* Initialize the LAN controller */ - if(wv_82593_config(dev) == FALSE) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_INFO "%s: wv_hw_config(): i82593 init failed\n", - dev->name); -#endif - break; - } - - /* Diagnostic */ - if(wv_diag(dev) == FALSE) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_INFO "%s: wv_hw_config(): i82593 diagnostic failed\n", - dev->name); -#endif - break; - } - - /* - * insert code for loopback test here - */ - - /* The device is now configured */ - lp->configured = 1; - ret = TRUE; - } - while(0); - - /* Re-enable interrupts */ - spin_unlock_irqrestore(&lp->spinlock, flags); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_hw_config()\n", dev->name); -#endif - return(ret); -} - -/*------------------------------------------------------------------*/ -/* - * Totally reset the wavelan and restart it. - * Performs the following actions: - * 1. Call wv_hw_config() - * 2. Start the LAN controller's receive unit - * (called by wavelan_event(), wavelan_watchdog() and wavelan_open()) - */ -static void -wv_hw_reset(struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: ->wv_hw_reset()\n", dev->name); -#endif - - lp->nresets++; - lp->configured = 0; - - /* Call wv_hw_config() for most of the reset & init stuff */ - if(wv_hw_config(dev) == FALSE) - return; - - /* start receive unit */ - wv_ru_start(dev); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <-wv_hw_reset()\n", dev->name); -#endif -} - -/*------------------------------------------------------------------*/ -/* - * wv_pcmcia_config() is called after a CARD_INSERTION event is - * received, to configure the PCMCIA socket, and to make the ethernet - * device available to the system. - * (called by wavelan_event()) - */ -static int -wv_pcmcia_config(struct pcmcia_device * link) -{ - struct net_device * dev = (struct net_device *) link->priv; - int i; - win_req_t req; - memreq_t mem; - net_local * lp = netdev_priv(dev); - - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "->wv_pcmcia_config(0x%p)\n", link); -#endif - - do - { - i = pcmcia_request_io(link, &link->io); - if (i != 0) - { - cs_error(link, RequestIO, i); - break; - } - - /* - * Now allocate an interrupt line. Note that this does not - * actually assign a handler to the interrupt. - */ - i = pcmcia_request_irq(link, &link->irq); - if (i != 0) - { - cs_error(link, RequestIRQ, i); - break; - } - - /* - * This actually configures the PCMCIA socket -- setting up - * the I/O windows and the interrupt mapping. - */ - link->conf.ConfigIndex = 1; - i = pcmcia_request_configuration(link, &link->conf); - if (i != 0) - { - cs_error(link, RequestConfiguration, i); - break; - } - - /* - * Allocate a small memory window. Note that the struct pcmcia_device - * structure provides space for one window handle -- if your - * device needs several windows, you'll need to keep track of - * the handles in your private data structure, link->priv. - */ - req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE; - req.Base = req.Size = 0; - req.AccessSpeed = mem_speed; - i = pcmcia_request_window(&link, &req, &link->win); - if (i != 0) - { - cs_error(link, RequestWindow, i); - break; - } - - lp->mem = ioremap(req.Base, req.Size); - dev->mem_start = (u_long)lp->mem; - dev->mem_end = dev->mem_start + req.Size; - - mem.CardOffset = 0; mem.Page = 0; - i = pcmcia_map_mem_page(link->win, &mem); - if (i != 0) - { - cs_error(link, MapMemPage, i); - break; - } - - /* Feed device with this info... */ - dev->irq = link->irq.AssignedIRQ; - dev->base_addr = link->io.BasePort1; - netif_start_queue(dev); - -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "wv_pcmcia_config: MEMSTART %p IRQ %d IOPORT 0x%x\n", - lp->mem, dev->irq, (u_int) dev->base_addr); -#endif - - SET_NETDEV_DEV(dev, &handle_to_dev(link)); - i = register_netdev(dev); - if(i != 0) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_INFO "wv_pcmcia_config(): register_netdev() failed\n"); -#endif - break; - } - } - while(0); /* Humm... Disguised goto !!! */ - - /* If any step failed, release any partially configured state */ - if(i != 0) - { - wv_pcmcia_release(link); - return FALSE; - } - - strcpy(((net_local *) netdev_priv(dev))->node.dev_name, dev->name); - link->dev_node = &((net_local *) netdev_priv(dev))->node; - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "<-wv_pcmcia_config()\n"); -#endif - return TRUE; -} - -/*------------------------------------------------------------------*/ -/* - * After a card is removed, wv_pcmcia_release() will unregister the net - * device, and release the PCMCIA configuration. If the device is - * still open, this will be postponed until it is closed. - */ -static void -wv_pcmcia_release(struct pcmcia_device *link) -{ - struct net_device * dev = (struct net_device *) link->priv; - net_local * lp = netdev_priv(dev); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: -> wv_pcmcia_release(0x%p)\n", dev->name, link); -#endif - - iounmap(lp->mem); - pcmcia_disable_device(link); - -#ifdef DEBUG_CONFIG_TRACE - printk(KERN_DEBUG "%s: <- wv_pcmcia_release()\n", dev->name); -#endif -} - -/************************ INTERRUPT HANDLING ************************/ - -/* - * This function is the interrupt handler for the WaveLAN card. This - * routine will be called whenever: - * 1. A packet is received. - * 2. A packet has successfully been transferred and the unit is - * ready to transmit another packet. - * 3. A command has completed execution. - */ -static irqreturn_t -wavelan_interrupt(int irq, - void * dev_id) -{ - struct net_device * dev = dev_id; - net_local * lp; - unsigned int base; - int status0; - u_int tx_status; - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wavelan_interrupt()\n", dev->name); -#endif - - lp = netdev_priv(dev); - base = dev->base_addr; - -#ifdef DEBUG_INTERRUPT_INFO - /* Check state of our spinlock (it should be cleared) */ - if(spin_is_locked(&lp->spinlock)) - printk(KERN_DEBUG - "%s: wavelan_interrupt(): spinlock is already locked !!!\n", - dev->name); -#endif - - /* Prevent reentrancy. We need to do that because we may have - * multiple interrupt handler running concurently. - * It is safe because interrupts are disabled before aquiring - * the spinlock. */ - spin_lock(&lp->spinlock); - - /* Treat all pending interrupts */ - while(1) - { - /* ---------------- INTERRUPT CHECKING ---------------- */ - /* - * Look for the interrupt and verify the validity - */ - outb(CR0_STATUS_0 | OP0_NOP, LCCR(base)); - status0 = inb(LCSR(base)); - -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "status0 0x%x [%s => 0x%x]", status0, - (status0&SR0_INTERRUPT)?"int":"no int",status0&~SR0_INTERRUPT); - if(status0&SR0_INTERRUPT) - { - printk(" [%s => %d]\n", (status0 & SR0_CHNL) ? "chnl" : - ((status0 & SR0_EXECUTION) ? "cmd" : - ((status0 & SR0_RECEPTION) ? "recv" : "unknown")), - (status0 & SR0_EVENT_MASK)); - } - else - printk("\n"); -#endif - - /* Return if no actual interrupt from i82593 (normal exit) */ - if(!(status0 & SR0_INTERRUPT)) - break; - - /* If interrupt is both Rx and Tx or none... - * This code in fact is there to catch the spurious interrupt - * when you remove the wavelan pcmcia card from the socket */ - if(((status0 & SR0_BOTH_RX_TX) == SR0_BOTH_RX_TX) || - ((status0 & SR0_BOTH_RX_TX) == 0x0)) - { -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_INFO "%s: wv_interrupt(): bogus interrupt (or from dead card) : %X\n", - dev->name, status0); -#endif - /* Acknowledge the interrupt */ - outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); - break; - } - - /* ----------------- RECEIVING PACKET ----------------- */ - /* - * When the wavelan signal the reception of a new packet, - * we call wv_packet_rcv() to copy if from the buffer and - * send it to NET3 - */ - if(status0 & SR0_RECEPTION) - { -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wv_interrupt(): receive\n", dev->name); -#endif - - if((status0 & SR0_EVENT_MASK) == SR0_STOP_REG_HIT) - { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wv_interrupt(): receive buffer overflow\n", - dev->name); -#endif - dev->stats.rx_over_errors++; - lp->overrunning = 1; - } - - /* Get the packet */ - wv_packet_rcv(dev); - lp->overrunning = 0; - - /* Acknowledge the interrupt */ - outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); - continue; - } - - /* ---------------- COMMAND COMPLETION ---------------- */ - /* - * Interrupts issued when the i82593 has completed a command. - * Most likely : transmission done - */ - - /* If a transmission has been done */ - if((status0 & SR0_EVENT_MASK) == SR0_TRANSMIT_DONE || - (status0 & SR0_EVENT_MASK) == SR0_RETRANSMIT_DONE || - (status0 & SR0_EVENT_MASK) == SR0_TRANSMIT_NO_CRC_DONE) - { -#ifdef DEBUG_TX_ERROR - if((status0 & SR0_EVENT_MASK) == SR0_TRANSMIT_NO_CRC_DONE) - printk(KERN_INFO "%s: wv_interrupt(): packet transmitted without CRC.\n", - dev->name); -#endif - - /* Get transmission status */ - tx_status = inb(LCSR(base)); - tx_status |= (inb(LCSR(base)) << 8); -#ifdef DEBUG_INTERRUPT_INFO - printk(KERN_DEBUG "%s: wv_interrupt(): transmission done\n", - dev->name); - { - u_int rcv_bytes; - u_char status3; - rcv_bytes = inb(LCSR(base)); - rcv_bytes |= (inb(LCSR(base)) << 8); - status3 = inb(LCSR(base)); - printk(KERN_DEBUG "tx_status 0x%02x rcv_bytes 0x%02x status3 0x%x\n", - tx_status, rcv_bytes, (u_int) status3); - } -#endif - /* Check for possible errors */ - if((tx_status & TX_OK) != TX_OK) - { - dev->stats.tx_errors++; - - if(tx_status & TX_FRTL) - { -#ifdef DEBUG_TX_ERROR - printk(KERN_INFO "%s: wv_interrupt(): frame too long\n", - dev->name); -#endif - } - if(tx_status & TX_UND_RUN) - { -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_interrupt(): DMA underrun\n", - dev->name); -#endif - dev->stats.tx_aborted_errors++; - } - if(tx_status & TX_LOST_CTS) - { -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_interrupt(): no CTS\n", dev->name); -#endif - dev->stats.tx_carrier_errors++; - } - if(tx_status & TX_LOST_CRS) - { -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_interrupt(): no carrier\n", - dev->name); -#endif - dev->stats.tx_carrier_errors++; - } - if(tx_status & TX_HRT_BEAT) - { -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_interrupt(): heart beat\n", dev->name); -#endif - dev->stats.tx_heartbeat_errors++; - } - if(tx_status & TX_DEFER) - { -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_interrupt(): channel jammed\n", - dev->name); -#endif - } - /* Ignore late collisions since they're more likely to happen - * here (the WaveLAN design prevents the LAN controller from - * receiving while it is transmitting). We take action only when - * the maximum retransmit attempts is exceeded. - */ - if(tx_status & TX_COLL) - { - if(tx_status & TX_MAX_COL) - { -#ifdef DEBUG_TX_FAIL - printk(KERN_DEBUG "%s: wv_interrupt(): channel congestion\n", - dev->name); -#endif - if(!(tx_status & TX_NCOL_MASK)) - { - dev->stats.collisions += 0x10; - } - } - } - } /* if(!(tx_status & TX_OK)) */ - - dev->stats.collisions += (tx_status & TX_NCOL_MASK); - dev->stats.tx_packets++; - - netif_wake_queue(dev); - outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ - } - else /* if interrupt = transmit done or retransmit done */ - { -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "wavelan_cs: unknown interrupt, status0 = %02x\n", - status0); -#endif - outb(CR0_INT_ACK | OP0_NOP, LCCR(base)); /* Acknowledge the interrupt */ - } - } /* while(1) */ - - spin_unlock(&lp->spinlock); - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wavelan_interrupt()\n", dev->name); -#endif - - /* We always return IRQ_HANDLED, because we will receive empty - * interrupts under normal operations. Anyway, it doesn't matter - * as we are dealing with an ISA interrupt that can't be shared. - * - * Explanation : under heavy receive, the following happens : - * ->wavelan_interrupt() - * (status0 & SR0_INTERRUPT) != 0 - * ->wv_packet_rcv() - * (status0 & SR0_INTERRUPT) != 0 - * ->wv_packet_rcv() - * (status0 & SR0_INTERRUPT) == 0 // i.e. no more event - * <-wavelan_interrupt() - * ->wavelan_interrupt() - * (status0 & SR0_INTERRUPT) == 0 // i.e. empty interrupt - * <-wavelan_interrupt() - * Jean II */ - return IRQ_HANDLED; -} /* wv_interrupt */ - -/*------------------------------------------------------------------*/ -/* - * Watchdog: when we start a transmission, a timer is set for us in the - * kernel. If the transmission completes, this timer is disabled. If - * the timer expires, we are called and we try to unlock the hardware. - * - * Note : This watchdog is move clever than the one in the ISA driver, - * because it try to abort the current command before reseting - * everything... - * On the other hand, it's a bit simpler, because we don't have to - * deal with the multiple Tx buffers... - */ -static void -wavelan_watchdog(struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - unsigned int base = dev->base_addr; - unsigned long flags; - int aborted = FALSE; - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: ->wavelan_watchdog()\n", dev->name); -#endif - -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_watchdog: watchdog timer expired\n", - dev->name); -#endif - - spin_lock_irqsave(&lp->spinlock, flags); - - /* Ask to abort the current command */ - outb(OP0_ABORT, LCCR(base)); - - /* Wait for the end of the command (a bit hackish) */ - if(wv_82593_cmd(dev, "wavelan_watchdog(): abort", - OP0_NOP | CR0_STATUS_3, SR0_EXECUTION_ABORTED)) - aborted = TRUE; - - /* Release spinlock here so that wv_hw_reset() can grab it */ - spin_unlock_irqrestore(&lp->spinlock, flags); - - /* Check if we were successful in aborting it */ - if(!aborted) - { - /* It seem that it wasn't enough */ -#ifdef DEBUG_INTERRUPT_ERROR - printk(KERN_INFO "%s: wavelan_watchdog: abort failed, trying reset\n", - dev->name); -#endif - wv_hw_reset(dev); - } - -#ifdef DEBUG_PSA_SHOW - { - psa_t psa; - psa_read(dev, 0, (unsigned char *) &psa, sizeof(psa)); - wv_psa_show(&psa); - } -#endif -#ifdef DEBUG_MMC_SHOW - wv_mmc_show(dev); -#endif -#ifdef DEBUG_I82593_SHOW - wv_ru_show(dev); -#endif - - /* We are no more waiting for something... */ - netif_wake_queue(dev); - -#ifdef DEBUG_INTERRUPT_TRACE - printk(KERN_DEBUG "%s: <-wavelan_watchdog()\n", dev->name); -#endif -} - -/********************* CONFIGURATION CALLBACKS *********************/ -/* - * Here are the functions called by the pcmcia package (cardmgr) and - * linux networking (NET3) for initialization, configuration and - * deinstallations of the Wavelan Pcmcia Hardware. - */ - -/*------------------------------------------------------------------*/ -/* - * Configure and start up the WaveLAN PCMCIA adaptor. - * Called by NET3 when it "open" the device. - */ -static int -wavelan_open(struct net_device * dev) -{ - net_local * lp = netdev_priv(dev); - struct pcmcia_device * link = lp->link; - unsigned int base = dev->base_addr; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_open(dev=0x%x)\n", dev->name, - (unsigned int) dev); -#endif - - /* Check if the modem is powered up (wavelan_close() power it down */ - if(hasr_read(base) & HASR_NO_CLK) - { - /* Power up (power up time is 250us) */ - hacr_write(base, HACR_DEFAULT); - - /* Check if the module has been powered up... */ - if(hasr_read(base) & HASR_NO_CLK) - { -#ifdef DEBUG_CONFIG_ERRORS - printk(KERN_WARNING "%s: wavelan_open(): modem not connected\n", - dev->name); -#endif - return FALSE; - } - } - - /* Start reception and declare the driver ready */ - if(!lp->configured) - return FALSE; - if(!wv_ru_start(dev)) - wv_hw_reset(dev); /* If problem : reset */ - netif_start_queue(dev); - - /* Mark the device as used */ - link->open++; - -#ifdef WAVELAN_ROAMING - if(do_roaming) - wv_roam_init(dev); -#endif /* WAVELAN_ROAMING */ - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_open()\n", dev->name); -#endif - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * Shutdown the WaveLAN PCMCIA adaptor. - * Called by NET3 when it "close" the device. - */ -static int -wavelan_close(struct net_device * dev) -{ - struct pcmcia_device * link = ((net_local *)netdev_priv(dev))->link; - unsigned int base = dev->base_addr; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: ->wavelan_close(dev=0x%x)\n", dev->name, - (unsigned int) dev); -#endif - - /* If the device isn't open, then nothing to do */ - if(!link->open) - { -#ifdef DEBUG_CONFIG_INFO - printk(KERN_DEBUG "%s: wavelan_close(): device not open\n", dev->name); -#endif - return 0; - } - -#ifdef WAVELAN_ROAMING - /* Cleanup of roaming stuff... */ - if(do_roaming) - wv_roam_cleanup(dev); -#endif /* WAVELAN_ROAMING */ - - link->open--; - - /* If the card is still present */ - if(netif_running(dev)) - { - netif_stop_queue(dev); - - /* Stop receiving new messages and wait end of transmission */ - wv_ru_stop(dev); - - /* Power down the module */ - hacr_write(base, HACR_DEFAULT & (~HACR_PWR_STAT)); - } - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "%s: <-wavelan_close()\n", dev->name); -#endif - return 0; -} - -static const struct net_device_ops wavelan_netdev_ops = { - .ndo_open = wavelan_open, - .ndo_stop = wavelan_close, - .ndo_start_xmit = wavelan_packet_xmit, - .ndo_set_multicast_list = wavelan_set_multicast_list, -#ifdef SET_MAC_ADDRESS - .ndo_set_mac_address = wavelan_set_mac_address, -#endif - .ndo_tx_timeout = wavelan_watchdog, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -/*------------------------------------------------------------------*/ -/* - * wavelan_attach() creates an "instance" of the driver, allocating - * local data structures for one device (one interface). The device - * is registered with Card Services. - * - * The dev_link structure is initialized, but we don't actually - * configure the card at this point -- we wait until we receive a - * card insertion event. - */ -static int -wavelan_probe(struct pcmcia_device *p_dev) -{ - struct net_device * dev; /* Interface generic data */ - net_local * lp; /* Interface specific data */ - int ret; - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "-> wavelan_attach()\n"); -#endif - - /* The io structure describes IO port mapping */ - p_dev->io.NumPorts1 = 8; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 3; - - /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - p_dev->irq.Handler = wavelan_interrupt; - - /* General socket configuration */ - p_dev->conf.Attributes = CONF_ENABLE_IRQ; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - - /* Allocate the generic data structure */ - dev = alloc_etherdev(sizeof(net_local)); - if (!dev) - return -ENOMEM; - - p_dev->priv = p_dev->irq.Instance = dev; - - lp = netdev_priv(dev); - - /* Init specific data */ - lp->configured = 0; - lp->reconfig_82593 = FALSE; - lp->nresets = 0; - /* Multicast stuff */ - lp->promiscuous = 0; - lp->allmulticast = 0; - lp->mc_count = 0; - - /* Init spinlock */ - spin_lock_init(&lp->spinlock); - - /* back links */ - lp->dev = dev; - - /* wavelan NET3 callbacks */ - dev->netdev_ops = &wavelan_netdev_ops; - dev->watchdog_timeo = WATCHDOG_JIFFIES; - SET_ETHTOOL_OPS(dev, &ops); - - dev->wireless_handlers = &wavelan_handler_def; - lp->wireless_data.spy_data = &lp->spy_data; - dev->wireless_data = &lp->wireless_data; - - /* Other specific data */ - dev->mtu = WAVELAN_MTU; - - ret = wv_pcmcia_config(p_dev); - if (ret) - return ret; - - ret = wv_hw_config(dev); - if (ret) { - dev->irq = 0; - pcmcia_disable_device(p_dev); - return ret; - } - - wv_init_info(dev); - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "<- wavelan_attach()\n"); -#endif - - return 0; -} - -/*------------------------------------------------------------------*/ -/* - * This deletes a driver "instance". The device is de-registered with - * Card Services. If it has been released, all local data structures - * are freed. Otherwise, the structures will be freed when the device - * is released. - */ -static void -wavelan_detach(struct pcmcia_device *link) -{ -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "-> wavelan_detach(0x%p)\n", link); -#endif - - /* Some others haven't done their job : give them another chance */ - wv_pcmcia_release(link); - - /* Free pieces */ - if(link->priv) - { - struct net_device * dev = (struct net_device *) link->priv; - - /* Remove ourselves from the kernel list of ethernet devices */ - /* Warning : can't be called from interrupt, timer or wavelan_close() */ - if (link->dev_node) - unregister_netdev(dev); - link->dev_node = NULL; - ((net_local *)netdev_priv(dev))->link = NULL; - ((net_local *)netdev_priv(dev))->dev = NULL; - free_netdev(dev); - } - -#ifdef DEBUG_CALLBACK_TRACE - printk(KERN_DEBUG "<- wavelan_detach()\n"); -#endif -} - -static int wavelan_suspend(struct pcmcia_device *link) -{ - struct net_device * dev = (struct net_device *) link->priv; - - /* NB: wavelan_close will be called, but too late, so we are - * obliged to close nicely the wavelan here. David, could you - * close the device before suspending them ? And, by the way, - * could you, on resume, add a "route add -net ..." after the - * ifconfig up ? Thanks... */ - - /* Stop receiving new messages and wait end of transmission */ - wv_ru_stop(dev); - - if (link->open) - netif_device_detach(dev); - - /* Power down the module */ - hacr_write(dev->base_addr, HACR_DEFAULT & (~HACR_PWR_STAT)); - - return 0; -} - -static int wavelan_resume(struct pcmcia_device *link) -{ - struct net_device * dev = (struct net_device *) link->priv; - - if (link->open) { - wv_hw_reset(dev); - netif_device_attach(dev); - } - - return 0; -} - - -static struct pcmcia_device_id wavelan_ids[] = { - PCMCIA_DEVICE_PROD_ID12("AT&T","WaveLAN/PCMCIA", 0xe7c5affd, 0x1bc50975), - PCMCIA_DEVICE_PROD_ID12("Digital", "RoamAbout/DS", 0x9999ab35, 0x00d05e06), - PCMCIA_DEVICE_PROD_ID12("Lucent Technologies", "WaveLAN/PCMCIA", 0x23eb9949, 0x1bc50975), - PCMCIA_DEVICE_PROD_ID12("NCR", "WaveLAN/PCMCIA", 0x24358cd4, 0x1bc50975), - PCMCIA_DEVICE_NULL, -}; -MODULE_DEVICE_TABLE(pcmcia, wavelan_ids); - -static struct pcmcia_driver wavelan_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "wavelan_cs", - }, - .probe = wavelan_probe, - .remove = wavelan_detach, - .id_table = wavelan_ids, - .suspend = wavelan_suspend, - .resume = wavelan_resume, -}; - -static int __init -init_wavelan_cs(void) -{ - return pcmcia_register_driver(&wavelan_driver); -} - -static void __exit -exit_wavelan_cs(void) -{ - pcmcia_unregister_driver(&wavelan_driver); -} - -module_init(init_wavelan_cs); -module_exit(exit_wavelan_cs); diff --git a/drivers/net/wireless/wavelan_cs.h b/drivers/net/wireless/wavelan_cs.h deleted file mode 100644 index 2e4bfe4147c6..000000000000 --- a/drivers/net/wireless/wavelan_cs.h +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Wavelan Pcmcia driver - * - * Jean II - HPLB '96 - * - * Reorganization and extension of the driver. - * Original copyright follow. See wavelan_cs.h for details. - * - * This file contain the declarations of the Wavelan hardware. Note that - * the Pcmcia Wavelan include a i82593 controller (see definitions in - * file i82593.h). - * - * The main difference between the pcmcia hardware and the ISA one is - * the Ethernet Controller (i82593 instead of i82586). The i82593 allow - * only one send buffer. The PSA (Parameter Storage Area : EEprom for - * permanent storage of various info) is memory mapped, but not the - * MMI (Modem Management Interface). - */ - -/* - * Definitions for the AT&T GIS (formerly NCR) WaveLAN PCMCIA card: - * An Ethernet-like radio transceiver controlled by an Intel 82593 - * coprocessor. - * - * - **************************************************************************** - * Copyright 1995 - * Anthony D. Joseph - * Massachusetts Institute of Technology - * - * Permission to use, copy, modify, and distribute this program - * for any purpose and without fee is hereby granted, provided - * that this copyright and permission notice appear on all copies - * and supporting documentation, the name of M.I.T. not be used - * in advertising or publicity pertaining to distribution of the - * program without specific prior permission, and notice be given - * in supporting documentation that copying and distribution is - * by permission of M.I.T. M.I.T. makes no representations about - * the suitability of this software for any purpose. It is pro- - * vided "as is" without express or implied warranty. - **************************************************************************** - * - * - * Credits: - * Special thanks to Jan Hoogendoorn of AT&T GIS Utrecht for - * providing extremely useful information about WaveLAN PCMCIA hardware - * - * This driver is based upon several other drivers, in particular: - * David Hinds' Linux driver for the PCMCIA 3c589 ethernet adapter - * Bruce Janson's Linux driver for the AT-bus WaveLAN adapter - * Anders Klemets' PCMCIA WaveLAN adapter driver - * Robert Morris' BSDI driver for the PCMCIA WaveLAN adapter - */ - -#ifndef _WAVELAN_CS_H -#define _WAVELAN_CS_H - -/************************** MAGIC NUMBERS ***************************/ - -/* The detection of the wavelan card is made by reading the MAC address - * from the card and checking it. If you have a non AT&T product (OEM, - * like DEC RoamAbout, or Digital Ocean, Epson, ...), you must modify this - * part to accommodate your hardware... - */ -static const unsigned char MAC_ADDRESSES[][3] = -{ - { 0x08, 0x00, 0x0E }, /* AT&T Wavelan (standard) & DEC RoamAbout */ - { 0x08, 0x00, 0x6A }, /* AT&T Wavelan (alternate) */ - { 0x00, 0x00, 0xE1 }, /* Hitachi Wavelan */ - { 0x00, 0x60, 0x1D } /* Lucent Wavelan (another one) */ - /* Add your card here and send me the patch ! */ -}; - -/* - * Constants used to convert channels to frequencies - */ - -/* Frequency available in the 2.0 modem, in units of 250 kHz - * (as read in the offset register of the dac area). - * Used to map channel numbers used by `wfreqsel' to frequencies - */ -static const short channel_bands[] = { 0x30, 0x58, 0x64, 0x7A, 0x80, 0xA8, - 0xD0, 0xF0, 0xF8, 0x150 }; - -/* Frequencies of the 1.0 modem (fixed frequencies). - * Use to map the PSA `subband' to a frequency - * Note : all frequencies apart from the first one need to be multiplied by 10 - */ -static const int fixed_bands[] = { 915e6, 2.425e8, 2.46e8, 2.484e8, 2.4305e8 }; - - -/*************************** PC INTERFACE ****************************/ - -/* WaveLAN host interface definitions */ - -#define LCCR(base) (base) /* LAN Controller Command Register */ -#define LCSR(base) (base) /* LAN Controller Status Register */ -#define HACR(base) (base+0x1) /* Host Adapter Command Register */ -#define HASR(base) (base+0x1) /* Host Adapter Status Register */ -#define PIORL(base) (base+0x2) /* Program I/O Register Low */ -#define RPLL(base) (base+0x2) /* Receive Pointer Latched Low */ -#define PIORH(base) (base+0x3) /* Program I/O Register High */ -#define RPLH(base) (base+0x3) /* Receive Pointer Latched High */ -#define PIOP(base) (base+0x4) /* Program I/O Port */ -#define MMR(base) (base+0x6) /* MMI Address Register */ -#define MMD(base) (base+0x7) /* MMI Data Register */ - -/* Host Adaptor Command Register bit definitions */ - -#define HACR_LOF (1 << 3) /* Lock Out Flag, toggle every 250ms */ -#define HACR_PWR_STAT (1 << 4) /* Power State, 1=active, 0=sleep */ -#define HACR_TX_DMA_RESET (1 << 5) /* Reset transmit DMA ptr on high */ -#define HACR_RX_DMA_RESET (1 << 6) /* Reset receive DMA ptr on high */ -#define HACR_ROM_WEN (1 << 7) /* EEPROM write enabled when true */ - -#define HACR_RESET (HACR_TX_DMA_RESET | HACR_RX_DMA_RESET) -#define HACR_DEFAULT (HACR_PWR_STAT) - -/* Host Adapter Status Register bit definitions */ - -#define HASR_MMI_BUSY (1 << 2) /* MMI is busy when true */ -#define HASR_LOF (1 << 3) /* Lock out flag status */ -#define HASR_NO_CLK (1 << 4) /* active when modem not connected */ - -/* Miscellaneous bit definitions */ - -#define PIORH_SEL_TX (1 << 5) /* PIOR points to 0=rx/1=tx buffer */ -#define MMR_MMI_WR (1 << 0) /* Next MMI cycle is 0=read, 1=write */ -#define PIORH_MASK 0x1f /* only low 5 bits are significant */ -#define RPLH_MASK 0x1f /* only low 5 bits are significant */ -#define MMI_ADDR_MASK 0x7e /* Bits 1-6 of MMR are significant */ - -/* Attribute Memory map */ - -#define CIS_ADDR 0x0000 /* Card Information Status Register */ -#define PSA_ADDR 0x0e00 /* Parameter Storage Area address */ -#define EEPROM_ADDR 0x1000 /* EEPROM address (unused ?) */ -#define COR_ADDR 0x4000 /* Configuration Option Register */ - -/* Configuration Option Register bit definitions */ - -#define COR_CONFIG (1 << 0) /* Config Index, 0 when unconfigured */ -#define COR_SW_RESET (1 << 7) /* Software Reset on true */ -#define COR_LEVEL_IRQ (1 << 6) /* Level IRQ */ - -/* Local Memory map */ - -#define RX_BASE 0x0000 /* Receive memory, 8 kB */ -#define TX_BASE 0x2000 /* Transmit memory, 2 kB */ -#define UNUSED_BASE 0x2800 /* Unused, 22 kB */ -#define RX_SIZE (TX_BASE-RX_BASE) /* Size of receive area */ -#define RX_SIZE_SHIFT 6 /* Bits to shift in stop register */ - -#define TRUE 1 -#define FALSE 0 - -#define MOD_ENAL 1 -#define MOD_PROM 2 - -/* Size of a MAC address */ -#define WAVELAN_ADDR_SIZE 6 - -/* Maximum size of Wavelan packet */ -#define WAVELAN_MTU 1500 - -#define MAXDATAZ (6 + 6 + 2 + WAVELAN_MTU) - -/********************** PARAMETER STORAGE AREA **********************/ - -/* - * Parameter Storage Area (PSA). - */ -typedef struct psa_t psa_t; -struct psa_t -{ - /* For the PCMCIA Adapter, locations 0x00-0x0F are unused and fixed at 00 */ - unsigned char psa_io_base_addr_1; /* [0x00] Base address 1 ??? */ - unsigned char psa_io_base_addr_2; /* [0x01] Base address 2 */ - unsigned char psa_io_base_addr_3; /* [0x02] Base address 3 */ - unsigned char psa_io_base_addr_4; /* [0x03] Base address 4 */ - unsigned char psa_rem_boot_addr_1; /* [0x04] Remote Boot Address 1 */ - unsigned char psa_rem_boot_addr_2; /* [0x05] Remote Boot Address 2 */ - unsigned char psa_rem_boot_addr_3; /* [0x06] Remote Boot Address 3 */ - unsigned char psa_holi_params; /* [0x07] HOst Lan Interface (HOLI) Parameters */ - unsigned char psa_int_req_no; /* [0x08] Interrupt Request Line */ - unsigned char psa_unused0[7]; /* [0x09-0x0F] unused */ - - unsigned char psa_univ_mac_addr[WAVELAN_ADDR_SIZE]; /* [0x10-0x15] Universal (factory) MAC Address */ - unsigned char psa_local_mac_addr[WAVELAN_ADDR_SIZE]; /* [0x16-1B] Local MAC Address */ - unsigned char psa_univ_local_sel; /* [0x1C] Universal Local Selection */ -#define PSA_UNIVERSAL 0 /* Universal (factory) */ -#define PSA_LOCAL 1 /* Local */ - unsigned char psa_comp_number; /* [0x1D] Compatability Number: */ -#define PSA_COMP_PC_AT_915 0 /* PC-AT 915 MHz */ -#define PSA_COMP_PC_MC_915 1 /* PC-MC 915 MHz */ -#define PSA_COMP_PC_AT_2400 2 /* PC-AT 2.4 GHz */ -#define PSA_COMP_PC_MC_2400 3 /* PC-MC 2.4 GHz */ -#define PSA_COMP_PCMCIA_915 4 /* PCMCIA 915 MHz or 2.0 */ - unsigned char psa_thr_pre_set; /* [0x1E] Modem Threshold Preset */ - unsigned char psa_feature_select; /* [0x1F] Call code required (1=on) */ -#define PSA_FEATURE_CALL_CODE 0x01 /* Call code required (Japan) */ - unsigned char psa_subband; /* [0x20] Subband */ -#define PSA_SUBBAND_915 0 /* 915 MHz or 2.0 */ -#define PSA_SUBBAND_2425 1 /* 2425 MHz */ -#define PSA_SUBBAND_2460 2 /* 2460 MHz */ -#define PSA_SUBBAND_2484 3 /* 2484 MHz */ -#define PSA_SUBBAND_2430_5 4 /* 2430.5 MHz */ - unsigned char psa_quality_thr; /* [0x21] Modem Quality Threshold */ - unsigned char psa_mod_delay; /* [0x22] Modem Delay ??? (reserved) */ - unsigned char psa_nwid[2]; /* [0x23-0x24] Network ID */ - unsigned char psa_nwid_select; /* [0x25] Network ID Select On Off */ - unsigned char psa_encryption_select; /* [0x26] Encryption On Off */ - unsigned char psa_encryption_key[8]; /* [0x27-0x2E] Encryption Key */ - unsigned char psa_databus_width; /* [0x2F] AT bus width select 8/16 */ - unsigned char psa_call_code[8]; /* [0x30-0x37] (Japan) Call Code */ - unsigned char psa_nwid_prefix[2]; /* [0x38-0x39] Roaming domain */ - unsigned char psa_reserved[2]; /* [0x3A-0x3B] Reserved - fixed 00 */ - unsigned char psa_conf_status; /* [0x3C] Conf Status, bit 0=1:config*/ - unsigned char psa_crc[2]; /* [0x3D] CRC-16 over PSA */ - unsigned char psa_crc_status; /* [0x3F] CRC Valid Flag */ -}; - -/* Size for structure checking (if padding is correct) */ -#define PSA_SIZE 64 - -/* Calculate offset of a field in the above structure - * Warning : only even addresses are used */ -#define psaoff(p,f) ((unsigned short) ((void *)(&((psa_t *) ((void *) NULL + (p)))->f) - (void *) NULL)) - -/******************** MODEM MANAGEMENT INTERFACE ********************/ - -/* - * Modem Management Controller (MMC) write structure. - */ -typedef struct mmw_t mmw_t; -struct mmw_t -{ - unsigned char mmw_encr_key[8]; /* encryption key */ - unsigned char mmw_encr_enable; /* enable/disable encryption */ -#define MMW_ENCR_ENABLE_MODE 0x02 /* Mode of security option */ -#define MMW_ENCR_ENABLE_EN 0x01 /* Enable security option */ - unsigned char mmw_unused0[1]; /* unused */ - unsigned char mmw_des_io_invert; /* Encryption option */ -#define MMW_DES_IO_INVERT_RES 0x0F /* Reserved */ -#define MMW_DES_IO_INVERT_CTRL 0xF0 /* Control ??? (set to 0) */ - unsigned char mmw_unused1[5]; /* unused */ - unsigned char mmw_loopt_sel; /* looptest selection */ -#define MMW_LOOPT_SEL_DIS_NWID 0x40 /* disable NWID filtering */ -#define MMW_LOOPT_SEL_INT 0x20 /* activate Attention Request */ -#define MMW_LOOPT_SEL_LS 0x10 /* looptest w/o collision avoidance */ -#define MMW_LOOPT_SEL_LT3A 0x08 /* looptest 3a */ -#define MMW_LOOPT_SEL_LT3B 0x04 /* looptest 3b */ -#define MMW_LOOPT_SEL_LT3C 0x02 /* looptest 3c */ -#define MMW_LOOPT_SEL_LT3D 0x01 /* looptest 3d */ - unsigned char mmw_jabber_enable; /* jabber timer enable */ - /* Abort transmissions > 200 ms */ - unsigned char mmw_freeze; /* freeze / unfreeeze signal level */ - /* 0 : signal level & qual updated for every new message, 1 : frozen */ - unsigned char mmw_anten_sel; /* antenna selection */ -#define MMW_ANTEN_SEL_SEL 0x01 /* direct antenna selection */ -#define MMW_ANTEN_SEL_ALG_EN 0x02 /* antenna selection algo. enable */ - unsigned char mmw_ifs; /* inter frame spacing */ - /* min time between transmission in bit periods (.5 us) - bit 0 ignored */ - unsigned char mmw_mod_delay; /* modem delay (synchro) */ - unsigned char mmw_jam_time; /* jamming time (after collision) */ - unsigned char mmw_unused2[1]; /* unused */ - unsigned char mmw_thr_pre_set; /* level threshold preset */ - /* Discard all packet with signal < this value (4) */ - unsigned char mmw_decay_prm; /* decay parameters */ - unsigned char mmw_decay_updat_prm; /* decay update parameterz */ - unsigned char mmw_quality_thr; /* quality (z-quotient) threshold */ - /* Discard all packet with quality < this value (3) */ - unsigned char mmw_netw_id_l; /* NWID low order byte */ - unsigned char mmw_netw_id_h; /* NWID high order byte */ - /* Network ID or Domain : create virtual net on the air */ - - /* 2.0 Hardware extension - frequency selection support */ - unsigned char mmw_mode_select; /* for analog tests (set to 0) */ - unsigned char mmw_unused3[1]; /* unused */ - unsigned char mmw_fee_ctrl; /* frequency eeprom control */ -#define MMW_FEE_CTRL_PRE 0x10 /* Enable protected instructions */ -#define MMW_FEE_CTRL_DWLD 0x08 /* Download eeprom to mmc */ -#define MMW_FEE_CTRL_CMD 0x07 /* EEprom commands : */ -#define MMW_FEE_CTRL_READ 0x06 /* Read */ -#define MMW_FEE_CTRL_WREN 0x04 /* Write enable */ -#define MMW_FEE_CTRL_WRITE 0x05 /* Write data to address */ -#define MMW_FEE_CTRL_WRALL 0x04 /* Write data to all addresses */ -#define MMW_FEE_CTRL_WDS 0x04 /* Write disable */ -#define MMW_FEE_CTRL_PRREAD 0x16 /* Read addr from protect register */ -#define MMW_FEE_CTRL_PREN 0x14 /* Protect register enable */ -#define MMW_FEE_CTRL_PRCLEAR 0x17 /* Unprotect all registers */ -#define MMW_FEE_CTRL_PRWRITE 0x15 /* Write addr in protect register */ -#define MMW_FEE_CTRL_PRDS 0x14 /* Protect register disable */ - /* Never issue this command (PRDS) : it's irreversible !!! */ - - unsigned char mmw_fee_addr; /* EEprom address */ -#define MMW_FEE_ADDR_CHANNEL 0xF0 /* Select the channel */ -#define MMW_FEE_ADDR_OFFSET 0x0F /* Offset in channel data */ -#define MMW_FEE_ADDR_EN 0xC0 /* FEE_CTRL enable operations */ -#define MMW_FEE_ADDR_DS 0x00 /* FEE_CTRL disable operations */ -#define MMW_FEE_ADDR_ALL 0x40 /* FEE_CTRL all operations */ -#define MMW_FEE_ADDR_CLEAR 0xFF /* FEE_CTRL clear operations */ - - unsigned char mmw_fee_data_l; /* Write data to EEprom */ - unsigned char mmw_fee_data_h; /* high octet */ - unsigned char mmw_ext_ant; /* Setting for external antenna */ -#define MMW_EXT_ANT_EXTANT 0x01 /* Select external antenna */ -#define MMW_EXT_ANT_POL 0x02 /* Polarity of the antenna */ -#define MMW_EXT_ANT_INTERNAL 0x00 /* Internal antenna */ -#define MMW_EXT_ANT_EXTERNAL 0x03 /* External antenna */ -#define MMW_EXT_ANT_IQ_TEST 0x1C /* IQ test pattern (set to 0) */ -} __attribute__((packed)); - -/* Size for structure checking (if padding is correct) */ -#define MMW_SIZE 37 - -/* Calculate offset of a field in the above structure */ -#define mmwoff(p,f) (unsigned short)((void *)(&((mmw_t *)((void *)0 + (p)))->f) - (void *)0) - - -/* - * Modem Management Controller (MMC) read structure. - */ -typedef struct mmr_t mmr_t; -struct mmr_t -{ - unsigned char mmr_unused0[8]; /* unused */ - unsigned char mmr_des_status; /* encryption status */ - unsigned char mmr_des_avail; /* encryption available (0x55 read) */ -#define MMR_DES_AVAIL_DES 0x55 /* DES available */ -#define MMR_DES_AVAIL_AES 0x33 /* AES (AT&T) available */ - unsigned char mmr_des_io_invert; /* des I/O invert register */ - unsigned char mmr_unused1[5]; /* unused */ - unsigned char mmr_dce_status; /* DCE status */ -#define MMR_DCE_STATUS_RX_BUSY 0x01 /* receiver busy */ -#define MMR_DCE_STATUS_LOOPT_IND 0x02 /* loop test indicated */ -#define MMR_DCE_STATUS_TX_BUSY 0x04 /* transmitter on */ -#define MMR_DCE_STATUS_JBR_EXPIRED 0x08 /* jabber timer expired */ -#define MMR_DCE_STATUS 0x0F /* mask to get the bits */ - unsigned char mmr_dsp_id; /* DSP id (AA = Daedalus rev A) */ - unsigned char mmr_unused2[2]; /* unused */ - unsigned char mmr_correct_nwid_l; /* # of correct NWID's rxd (low) */ - unsigned char mmr_correct_nwid_h; /* # of correct NWID's rxd (high) */ - /* Warning : Read high order octet first !!! */ - unsigned char mmr_wrong_nwid_l; /* # of wrong NWID's rxd (low) */ - unsigned char mmr_wrong_nwid_h; /* # of wrong NWID's rxd (high) */ - unsigned char mmr_thr_pre_set; /* level threshold preset */ -#define MMR_THR_PRE_SET 0x3F /* level threshold preset */ -#define MMR_THR_PRE_SET_CUR 0x80 /* Current signal above it */ - unsigned char mmr_signal_lvl; /* signal level */ -#define MMR_SIGNAL_LVL 0x3F /* signal level */ -#define MMR_SIGNAL_LVL_VALID 0x80 /* Updated since last read */ - unsigned char mmr_silence_lvl; /* silence level (noise) */ -#define MMR_SILENCE_LVL 0x3F /* silence level */ -#define MMR_SILENCE_LVL_VALID 0x80 /* Updated since last read */ - unsigned char mmr_sgnl_qual; /* signal quality */ -#define MMR_SGNL_QUAL 0x0F /* signal quality */ -#define MMR_SGNL_QUAL_ANT 0x80 /* current antenna used */ - unsigned char mmr_netw_id_l; /* NWID low order byte ??? */ - unsigned char mmr_unused3[3]; /* unused */ - - /* 2.0 Hardware extension - frequency selection support */ - unsigned char mmr_fee_status; /* Status of frequency eeprom */ -#define MMR_FEE_STATUS_ID 0xF0 /* Modem revision id */ -#define MMR_FEE_STATUS_DWLD 0x08 /* Download in progress */ -#define MMR_FEE_STATUS_BUSY 0x04 /* EEprom busy */ - unsigned char mmr_unused4[1]; /* unused */ - unsigned char mmr_fee_data_l; /* Read data from eeprom (low) */ - unsigned char mmr_fee_data_h; /* Read data from eeprom (high) */ -}; - -/* Size for structure checking (if padding is correct) */ -#define MMR_SIZE 36 - -/* Calculate offset of a field in the above structure */ -#define mmroff(p,f) (unsigned short)((void *)(&((mmr_t *)((void *)0 + (p)))->f) - (void *)0) - - -/* Make the two above structures one */ -typedef union mm_t -{ - struct mmw_t w; /* Write to the mmc */ - struct mmr_t r; /* Read from the mmc */ -} mm_t; - -#endif /* _WAVELAN_CS_H */ diff --git a/drivers/net/wireless/wavelan_cs.p.h b/drivers/net/wireless/wavelan_cs.p.h deleted file mode 100644 index 81d91531c4f9..000000000000 --- a/drivers/net/wireless/wavelan_cs.p.h +++ /dev/null @@ -1,766 +0,0 @@ -/* - * Wavelan Pcmcia driver - * - * Jean II - HPLB '96 - * - * Reorganisation and extension of the driver. - * - * This file contain all definition and declarations necessary for the - * wavelan pcmcia driver. This file is a private header, so it should - * be included only on wavelan_cs.c !!! - */ - -#ifndef WAVELAN_CS_P_H -#define WAVELAN_CS_P_H - -/************************** DOCUMENTATION **************************/ -/* - * This driver provide a Linux interface to the Wavelan Pcmcia hardware - * The Wavelan is a product of Lucent (http://www.wavelan.com/). - * This division was formerly part of NCR and then AT&T. - * Wavelan are also distributed by DEC (RoamAbout DS)... - * - * To know how to use this driver, read the PCMCIA HOWTO. - * If you want to exploit the many other fonctionalities, look comments - * in the code... - * - * This driver is the result of the effort of many peoples (see below). - */ - -/* ------------------------ SPECIFIC NOTES ------------------------ */ -/* - * Web page - * -------- - * I try to maintain a web page with the Wireless LAN Howto at : - * http://www.hpl.hp.com/personal/Jean_Tourrilhes/Linux/Wavelan.html - * - * SMP - * --- - * We now are SMP compliant (I eventually fixed the remaining bugs). - * The driver has been tested on a dual P6-150 and survived my usual - * set of torture tests. - * Anyway, I spent enough time chasing interrupt re-entrancy during - * errors or reconfigure, and I designed the locked/unlocked sections - * of the driver with great care, and with the recent addition of - * the spinlock (thanks to the new API), we should be quite close to - * the truth. - * The SMP/IRQ locking is quite coarse and conservative (i.e. not fast), - * but better safe than sorry (especially at 2 Mb/s ;-). - * - * I have also looked into disabling only our interrupt on the card - * (via HACR) instead of all interrupts in the processor (via cli), - * so that other driver are not impacted, and it look like it's - * possible, but it's very tricky to do right (full of races). As - * the gain would be mostly for SMP systems, it can wait... - * - * Debugging and options - * --------------------- - * You will find below a set of '#define" allowing a very fine control - * on the driver behaviour and the debug messages printed. - * The main options are : - * o WAVELAN_ROAMING, for the experimental roaming support. - * o SET_PSA_CRC, to have your card correctly recognised by - * an access point and the Point-to-Point diagnostic tool. - * o USE_PSA_CONFIG, to read configuration from the PSA (EEprom) - * (otherwise we always start afresh with some defaults) - * - * wavelan_cs.o is darn too big - * ------------------------- - * That's true ! There is a very simple way to reduce the driver - * object by 33% (yes !). Comment out the following line : - * #include - * Other compile options can also reduce the size of it... - * - * MAC address and hardware detection : - * ---------------------------------- - * The detection code of the wavelan chech that the first 3 - * octets of the MAC address fit the company code. This type of - * detection work well for AT&T cards (because the AT&T code is - * hardcoded in wavelan_cs.h), but of course will fail for other - * manufacturer. - * - * If you are sure that your card is derived from the wavelan, - * here is the way to configure it : - * 1) Get your MAC address - * a) With your card utilities (wfreqsel, instconf, ...) - * b) With the driver : - * o compile the kernel with DEBUG_CONFIG_INFO enabled - * o Boot and look the card messages - * 2) Set your MAC code (3 octets) in MAC_ADDRESSES[][3] (wavelan_cs.h) - * 3) Compile & verify - * 4) Send me the MAC code - I will include it in the next version... - * - */ - -/* --------------------- WIRELESS EXTENSIONS --------------------- */ -/* - * This driver is the first one to support "wireless extensions". - * This set of extensions provide you some way to control the wireless - * caracteristics of the hardware in a standard way and support for - * applications for taking advantage of it (like Mobile IP). - * - * It might be a good idea as well to fetch the wireless tools to - * configure the device and play a bit. - */ - -/* ---------------------------- FILES ---------------------------- */ -/* - * wavelan_cs.c : The actual code for the driver - C functions - * - * wavelan_cs.p.h : Private header : local types / vars for the driver - * - * wavelan_cs.h : Description of the hardware interface & structs - * - * i82593.h : Description if the Ethernet controller - */ - -/* --------------------------- HISTORY --------------------------- */ -/* - * The history of the Wavelan drivers is as complicated as history of - * the Wavelan itself (NCR -> AT&T -> Lucent). - * - * All started with Anders Klemets , - * writing a Wavelan ISA driver for the MACH microkernel. Girish - * Welling had also worked on it. - * Keith Moore modify this for the Pcmcia hardware. - * - * Robert Morris port these two drivers to BSDI - * and add specific Pcmcia support (there is currently no equivalent - * of the PCMCIA package under BSD...). - * - * Jim Binkley port both BSDI drivers to FreeBSD. - * - * Bruce Janson port the BSDI ISA driver to Linux. - * - * Anthony D. Joseph started modify Bruce driver - * (with help of the BSDI PCMCIA driver) for PCMCIA. - * Yunzhou Li finished is work. - * Joe Finney patched the driver to start - * correctly 2.00 cards (2.4 GHz with frequency selection). - * David Hinds integrated the whole in his - * Pcmcia package (+ bug corrections). - * - * I (Jean Tourrilhes - jt@hplb.hpl.hp.com) then started to make some - * patchs to the Pcmcia driver. After, I added code in the ISA driver - * for Wireless Extensions and full support of frequency selection - * cards. Now, I'm doing the same to the Pcmcia driver + some - * reorganisation. - * Loeke Brederveld from Lucent has given me - * much needed informations on the Wavelan hardware. - */ - -/* By the way : for the copyright & legal stuff : - * Almost everybody wrote code under GNU or BSD license (or alike), - * and want that their original copyright remain somewhere in the - * code (for myself, I go with the GPL). - * Nobody want to take responsibility for anything, except the fame... - */ - -/* --------------------------- CREDITS --------------------------- */ -/* - * Credits: - * Special thanks to Jan Hoogendoorn of AT&T GIS Utrecht and - * Loeke Brederveld of Lucent for providing extremely useful - * information about WaveLAN PCMCIA hardware - * - * This driver is based upon several other drivers, in particular: - * David Hinds' Linux driver for the PCMCIA 3c589 ethernet adapter - * Bruce Janson's Linux driver for the AT-bus WaveLAN adapter - * Anders Klemets' PCMCIA WaveLAN adapter driver - * Robert Morris' BSDI driver for the PCMCIA WaveLAN adapter - * - * Additional Credits: - * - * This software was originally developed under Linux 1.2.3 - * (Slackware 2.0 distribution). - * And then under Linux 2.0.x (Debian 1.1 -> 2.2 - pcmcia 2.8.18+) - * with an HP OmniBook 4000 and then a 5500. - * - * It is based on other device drivers and information either written - * or supplied by: - * James Ashton (jaa101@syseng.anu.edu.au), - * Ajay Bakre (bakre@paul.rutgers.edu), - * Donald Becker (becker@super.org), - * Jim Binkley , - * Loeke Brederveld , - * Allan Creighton (allanc@cs.su.oz.au), - * Brent Elphick , - * Joe Finney , - * Matthew Geier (matthew@cs.su.oz.au), - * Remo di Giovanni (remo@cs.su.oz.au), - * Mark Hagan (mhagan@wtcpost.daytonoh.NCR.COM), - * David Hinds , - * Jan Hoogendoorn (c/o marteijn@lucent.com), - * Bruce Janson , - * Anthony D. Joseph , - * Anders Klemets (klemets@paul.rutgers.edu), - * Yunzhou Li , - * Marc Meertens (mmeertens@lucent.com), - * Keith Moore, - * Robert Morris (rtm@das.harvard.edu), - * Ian Parkin (ian@cs.su.oz.au), - * John Rosenberg (johnr@cs.su.oz.au), - * George Rossi (george@phm.gov.au), - * Arthur Scott (arthur@cs.su.oz.au), - * Stanislav Sinyagin - * Peter Storey, - * Jean Tourrilhes , - * Girish Welling (welling@paul.rutgers.edu) - * Clark Woodworth - * Yongguang Zhang ... - */ - -/* ------------------------- IMPROVEMENTS ------------------------- */ -/* - * I proudly present : - * - * Changes made in 2.8.22 : - * ---------------------- - * - improved wv_set_multicast_list - * - catch spurious interrupt - * - correct release of the device - * - * Changes mades in release : - * ------------------------ - * - Reorganisation of the code, function name change - * - Creation of private header (wavelan_cs.h) - * - Reorganised debug messages - * - More comments, history, ... - * - Configure earlier (in "insert" instead of "open") - * and do things only once - * - mmc_init : configure the PSA if not done - * - mmc_init : 2.00 detection better code for 2.00 init - * - better info at startup - * - Correct a HUGE bug (volatile & uncalibrated busy loop) - * in wv_82593_cmd => config speedup - * - Stop receiving & power down on close (and power up on open) - * use "ifconfig down" & "ifconfig up ; route add -net ..." - * - Send packets : add watchdog instead of pooling - * - Receive : check frame wrap around & try to recover some frames - * - wavelan_set_multicast_list : avoid reset - * - add wireless extensions (ioctl & get_wireless_stats) - * get/set nwid/frequency on fly, info for /proc/net/wireless - * - Suppress useless stuff from lp (net_local), but add link - * - More inlines - * - Lot of others minor details & cleanups - * - * Changes made in second release : - * ------------------------------ - * - Optimise wv_85893_reconfig stuff, fix potential problems - * - Change error values for ioctl - * - Non blocking wv_ru_stop() + call wv_reset() in case of problems - * - Remove development printk from wavelan_watchdog() - * - Remove of the watchdog to wavelan_close instead of wavelan_release - * fix potential problems... - * - Start debugging suspend stuff (but it's still a bit weird) - * - Debug & optimize dump header/packet in Rx & Tx (debug) - * - Use "readb" and "writeb" to be kernel 2.1 compliant - * - Better handling of bogus interrupts - * - Wireless extension : SETSPY and GETSPY - * - Remove old stuff (stats - for those needing it, just ask me...) - * - Make wireless extensions optional - * - * Changes made in third release : - * ----------------------------- - * - cleanups & typos - * - modif wireless ext (spy -> only one pointer) - * - new private ioctl to set/get quality & level threshold - * - Init : correct default value of level threshold for pcmcia - * - kill watchdog in hw_reset - * - more 2.1 support (copy_to/from_user instead of memcpy_to/fromfs) - * - Add message level (debug stuff in /var/adm/debug & errors not - * displayed at console and still in /var/adm/messages) - * - * Changes made in fourth release : - * ------------------------------ - * - multicast support (yes !) thanks to Yongguang Zhang. - * - * Changes made in fifth release (2.9.0) : - * ------------------------------------- - * - Revisited multicast code (it was mostly wrong). - * - protect code in wv_82593_reconfig with dev->tbusy (oups !) - * - * Changes made in sixth release (2.9.1a) : - * -------------------------------------- - * - Change the detection code for multi manufacturer code support - * - Correct bug (hang kernel) in init when we were "rejecting" a card - * - * Changes made in seventh release (2.9.1b) : - * ---------------------------------------- - * - Update to wireless extensions changes - * - Silly bug in card initial configuration (psa_conf_status) - * - * Changes made in eigth release : - * ----------------------------- - * - Small bug in debug code (probably not the last one...) - * - 1.2.13 support (thanks to Clark Woodworth) - * - * Changes made for release in 2.9.2b : - * ---------------------------------- - * - Level threshold is now a standard wireless extension (version 4 !) - * - modules parameters types for kernel > 2.1.17 - * - updated man page - * - Others cleanup from David Hinds - * - * Changes made for release in 2.9.5 : - * --------------------------------- - * - byte count stats (courtesy of David Hinds) - * - Remove dev_tint stuff (courtesy of David Hinds) - * - Others cleanup from David Hinds - * - Encryption setting from Brent Elphick (thanks a lot !) - * - 'base' to 'u_long' for the Alpha (thanks to Stanislav Sinyagin) - * - * Changes made for release in 2.9.6 : - * --------------------------------- - * - fix bug : no longuer disable watchdog in case of bogus interrupt - * - increase timeout in config code for picky hardware - * - mask unused bits in status (Wireless Extensions) - * - * Changes integrated by Justin Seger & David Hinds : - * ----------------------------------------------------------------- - * - Roaming "hack" from Joe Finney - * - PSA CRC code from Bob Gray - * - Better initialisation of the i82593 controller - * from Joseph K. O'Sullivan - * - * Changes made for release in 3.0.10 : - * ---------------------------------- - * - Fix eject "hang" of the driver under 2.2.X : - * o create wv_flush_stale_links() - * o Rename wavelan_release to wv_pcmcia_release & move up - * o move unregister_netdev to wavelan_detach() - * o wavelan_release() no longer call wavelan_detach() - * o Suppress "release" timer - * o Other cleanups & fixes - * - New MAC address in the probe - * - Reorg PSA_CRC code (endian neutral & cleaner) - * - Correct initialisation of the i82593 from Lucent manual - * - Put back the watchdog, with larger timeout - * - TRANSMIT_NO_CRC is a "normal" error, so recover from it - * from Derrick J Brashear - * - Better handling of TX and RX normal failure conditions - * - #ifdef out all the roaming code - * - Add ESSID & "AP current address" ioctl stubs - * - General cleanup of the code - * - * Changes made for release in 3.0.13 : - * ---------------------------------- - * - Re-enable compilation of roaming code by default, but with - * do_roaming = 0 - * - Nuke `nwid=nwid^ntohs(beacon->domain_id)' in wl_roam_gather - * at the demand of John Carol Langford - * - Introduced WAVELAN_ROAMING_EXT for incomplete ESSID stuff. - * - * Changes made for release in 3.0.15 : - * ---------------------------------- - * - Change e-mail and web page addresses - * - Watchdog timer is now correctly expressed in HZ, not in jiffies - * - Add channel number to the list of frequencies in range - * - Add the (short) list of bit-rates in range - * - Developp a new sensitivity... (sens.value & sens.fixed) - * - * Changes made for release in 3.1.2 : - * --------------------------------- - * - Fix check for root permission (break instead of exit) - * - New nwid & encoding setting (Wireless Extension 9) - * - * Changes made for release in 3.1.12 : - * ---------------------------------- - * - reworked wv_82593_cmd to avoid using the IRQ handler and doing - * ugly things with interrupts. - * - Add IRQ protection in 82593_config/ru_start/ru_stop/watchdog - * - Update to new network API (softnet - 2.3.43) : - * o replace dev->tbusy (David + me) - * o replace dev->tstart (David + me) - * o remove dev->interrupt (David) - * o add SMP locking via spinlock in splxx (me) - * o add spinlock in interrupt handler (me) - * o use kernel watchdog instead of ours (me) - * o verify that all the changes make sense and work (me) - * - Re-sync kernel/pcmcia versions (not much actually) - * - A few other cleanups (David & me)... - * - * Changes made for release in 3.1.22 : - * ---------------------------------- - * - Check that SMP works, remove annoying log message - * - * Changes made for release in 3.1.24 : - * ---------------------------------- - * - Fix unfrequent card lockup when watchdog was reseting the hardware : - * o control first busy loop in wv_82593_cmd() - * o Extend spinlock protection in wv_hw_config() - * - * Changes made for release in 3.1.33 : - * ---------------------------------- - * - Optional use new driver API for Wireless Extensions : - * o got rid of wavelan_ioctl() - * o use a bunch of iw_handler instead - * - * Changes made for release in 3.2.1 : - * --------------------------------- - * - Set dev->trans_start to avoid filling the logs - * (and generating useless abort commands) - * - Avoid deadlocks in mmc_out()/mmc_in() - * - * Wishes & dreams: - * ---------------- - * - Cleanup and integrate the roaming code - * (std debug, set DomainID, decay avg and co...) - */ - -/***************************** INCLUDES *****************************/ - -/* Linux headers that we need */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include /* Wireless extensions */ -#include /* New driver API */ - -/* Pcmcia headers that we need */ -#include -#include -#include -#include -#include - -/* Wavelan declarations */ -#include "i82593.h" /* Definitions for the Intel chip */ - -#include "wavelan_cs.h" /* Others bits of the hardware */ - -/************************** DRIVER OPTIONS **************************/ -/* - * `#define' or `#undef' the following constant to change the behaviour - * of the driver... - */ -#define WAVELAN_ROAMING /* Include experimental roaming code */ -#undef WAVELAN_ROAMING_EXT /* Enable roaming wireless extensions */ -#undef SET_PSA_CRC /* Set the CRC in PSA (slower) */ -#define USE_PSA_CONFIG /* Use info from the PSA */ -#undef EEPROM_IS_PROTECTED /* Doesn't seem to be necessary */ -#define MULTICAST_AVOID /* Avoid extra multicast (I'm sceptical) */ -#undef SET_MAC_ADDRESS /* Experimental */ - -/* Warning : these stuff will slow down the driver... */ -#define WIRELESS_SPY /* Enable spying addresses */ -#undef HISTOGRAM /* Enable histogram of sig level... */ - -/****************************** DEBUG ******************************/ - -#undef DEBUG_MODULE_TRACE /* Module insertion/removal */ -#undef DEBUG_CALLBACK_TRACE /* Calls made by Linux */ -#undef DEBUG_INTERRUPT_TRACE /* Calls to handler */ -#undef DEBUG_INTERRUPT_INFO /* type of interrupt & so on */ -#define DEBUG_INTERRUPT_ERROR /* problems */ -#undef DEBUG_CONFIG_TRACE /* Trace the config functions */ -#undef DEBUG_CONFIG_INFO /* What's going on... */ -#define DEBUG_CONFIG_ERRORS /* Errors on configuration */ -#undef DEBUG_TX_TRACE /* Transmission calls */ -#undef DEBUG_TX_INFO /* Header of the transmitted packet */ -#undef DEBUG_TX_FAIL /* Normal failure conditions */ -#define DEBUG_TX_ERROR /* Unexpected conditions */ -#undef DEBUG_RX_TRACE /* Transmission calls */ -#undef DEBUG_RX_INFO /* Header of the transmitted packet */ -#undef DEBUG_RX_FAIL /* Normal failure conditions */ -#define DEBUG_RX_ERROR /* Unexpected conditions */ -#undef DEBUG_PACKET_DUMP /* Dump packet on the screen */ -#undef DEBUG_IOCTL_TRACE /* Misc call by Linux */ -#undef DEBUG_IOCTL_INFO /* Various debug info */ -#define DEBUG_IOCTL_ERROR /* What's going wrong */ -#define DEBUG_BASIC_SHOW /* Show basic startup info */ -#undef DEBUG_VERSION_SHOW /* Print version info */ -#undef DEBUG_PSA_SHOW /* Dump psa to screen */ -#undef DEBUG_MMC_SHOW /* Dump mmc to screen */ -#undef DEBUG_SHOW_UNUSED /* Show also unused fields */ -#undef DEBUG_I82593_SHOW /* Show i82593 status */ -#undef DEBUG_DEVICE_SHOW /* Show device parameters */ - -/************************ CONSTANTS & MACROS ************************/ - -#ifdef DEBUG_VERSION_SHOW -static const char *version = "wavelan_cs.c : v24 (SMP + wireless extensions) 11/1/02\n"; -#endif - -/* Watchdog temporisation */ -#define WATCHDOG_JIFFIES (256*HZ/100) - -/* Fix a bug in some old wireless extension definitions */ -#ifndef IW_ESSID_MAX_SIZE -#define IW_ESSID_MAX_SIZE 32 -#endif - -/* ------------------------ PRIVATE IOCTL ------------------------ */ - -#define SIOCSIPQTHR SIOCIWFIRSTPRIV /* Set quality threshold */ -#define SIOCGIPQTHR SIOCIWFIRSTPRIV + 1 /* Get quality threshold */ -#define SIOCSIPROAM SIOCIWFIRSTPRIV + 2 /* Set roaming state */ -#define SIOCGIPROAM SIOCIWFIRSTPRIV + 3 /* Get roaming state */ - -#define SIOCSIPHISTO SIOCIWFIRSTPRIV + 4 /* Set histogram ranges */ -#define SIOCGIPHISTO SIOCIWFIRSTPRIV + 5 /* Get histogram values */ - -/*************************** WaveLAN Roaming **************************/ -#ifdef WAVELAN_ROAMING /* Conditional compile, see above in options */ - -#define WAVELAN_ROAMING_DEBUG 0 /* 1 = Trace of handover decisions */ - /* 2 = Info on each beacon rcvd... */ -#define MAX_WAVEPOINTS 7 /* Max visible at one time */ -#define WAVEPOINT_HISTORY 5 /* SNR sample history slow search */ -#define WAVEPOINT_FAST_HISTORY 2 /* SNR sample history fast search */ -#define SEARCH_THRESH_LOW 10 /* SNR to enter cell search */ -#define SEARCH_THRESH_HIGH 13 /* SNR to leave cell search */ -#define WAVELAN_ROAMING_DELTA 1 /* Hysteresis value (+/- SNR) */ -#define CELL_TIMEOUT 2*HZ /* in jiffies */ - -#define FAST_CELL_SEARCH 1 /* Boolean values... */ -#define NWID_PROMISC 1 /* for code clarity. */ - -typedef struct wavepoint_beacon -{ - unsigned char dsap, /* Unused */ - ssap, /* Unused */ - ctrl, /* Unused */ - O,U,I, /* Unused */ - spec_id1, /* Unused */ - spec_id2, /* Unused */ - pdu_type, /* Unused */ - seq; /* WavePoint beacon sequence number */ - __be16 domain_id, /* WavePoint Domain ID */ - nwid; /* WavePoint NWID */ -} wavepoint_beacon; - -typedef struct wavepoint_history -{ - unsigned short nwid; /* WavePoint's NWID */ - int average_slow; /* SNR running average */ - int average_fast; /* SNR running average */ - unsigned char sigqual[WAVEPOINT_HISTORY]; /* Ringbuffer of recent SNR's */ - unsigned char qualptr; /* Index into ringbuffer */ - unsigned char last_seq; /* Last seq. no seen for WavePoint */ - struct wavepoint_history *next; /* Next WavePoint in table */ - struct wavepoint_history *prev; /* Previous WavePoint in table */ - unsigned long last_seen; /* Time of last beacon recvd, jiffies */ -} wavepoint_history; - -struct wavepoint_table -{ - wavepoint_history *head; /* Start of ringbuffer */ - int num_wavepoints; /* No. of WavePoints visible */ - unsigned char locked; /* Table lock */ -}; - -#endif /* WAVELAN_ROAMING */ - -/****************************** TYPES ******************************/ - -/* Shortcuts */ -typedef struct iw_statistics iw_stats; -typedef struct iw_quality iw_qual; -typedef struct iw_freq iw_freq; -typedef struct net_local net_local; -typedef struct timer_list timer_list; - -/* Basic types */ -typedef u_char mac_addr[WAVELAN_ADDR_SIZE]; /* Hardware address */ - -/* - * Static specific data for the interface. - * - * For each network interface, Linux keep data in two structure. "device" - * keep the generic data (same format for everybody) and "net_local" keep - * the additional specific data. - */ -struct net_local -{ - dev_node_t node; /* ???? What is this stuff ???? */ - struct net_device * dev; /* Reverse link... */ - spinlock_t spinlock; /* Serialize access to the hardware (SMP) */ - struct pcmcia_device * link; /* pcmcia structure */ - int nresets; /* Number of hw resets */ - u_char configured; /* If it is configured */ - u_char reconfig_82593; /* Need to reconfigure the controller */ - u_char promiscuous; /* Promiscuous mode */ - u_char allmulticast; /* All Multicast mode */ - int mc_count; /* Number of multicast addresses */ - - int stop; /* Current i82593 Stop Hit Register */ - int rfp; /* Last DMA machine receive pointer */ - int overrunning; /* Receiver overrun flag */ - - iw_stats wstats; /* Wireless specific stats */ - - struct iw_spy_data spy_data; - struct iw_public_data wireless_data; - -#ifdef HISTOGRAM - int his_number; /* Number of intervals */ - u_char his_range[16]; /* Boundaries of interval ]n-1; n] */ - u_long his_sum[16]; /* Sum in interval */ -#endif /* HISTOGRAM */ -#ifdef WAVELAN_ROAMING - u_long domain_id; /* Domain ID we lock on for roaming */ - int filter_domains; /* Check Domain ID of beacon found */ - struct wavepoint_table wavepoint_table; /* Table of visible WavePoints*/ - wavepoint_history * curr_point; /* Current wavepoint */ - int cell_search; /* Searching for new cell? */ - struct timer_list cell_timer; /* Garbage collection */ -#endif /* WAVELAN_ROAMING */ - void __iomem *mem; -}; - -/* ----------------- MODEM MANAGEMENT SUBROUTINES ----------------- */ -static inline u_char /* data */ - hasr_read(u_long); /* Read the host interface : base address */ -static void - hacr_write(u_long, /* Write to host interface : base address */ - u_char), /* data */ - hacr_write_slow(u_long, - u_char); -static void - psa_read(struct net_device *, /* Read the Parameter Storage Area */ - int, /* offset in PSA */ - u_char *, /* buffer to fill */ - int), /* size to read */ - psa_write(struct net_device *, /* Write to the PSA */ - int, /* Offset in psa */ - u_char *, /* Buffer in memory */ - int); /* Length of buffer */ -static void - mmc_out(u_long, /* Write 1 byte to the Modem Manag Control */ - u_short, - u_char), - mmc_write(u_long, /* Write n bytes to the MMC */ - u_char, - u_char *, - int); -static u_char /* Read 1 byte from the MMC */ - mmc_in(u_long, - u_short); -static void - mmc_read(u_long, /* Read n bytes from the MMC */ - u_char, - u_char *, - int), - fee_wait(u_long, /* Wait for frequency EEprom : base address */ - int, /* Base delay to wait for */ - int); /* Number of time to wait */ -static void - fee_read(u_long, /* Read the frequency EEprom : base address */ - u_short, /* destination offset */ - u_short *, /* data buffer */ - int); /* number of registers */ -/* ---------------------- I82593 SUBROUTINES ----------------------- */ -static int - wv_82593_cmd(struct net_device *, /* synchronously send a command to i82593 */ - char *, - int, - int); -static inline int - wv_diag(struct net_device *); /* Diagnostique the i82593 */ -static int - read_ringbuf(struct net_device *, /* Read a receive buffer */ - int, - char *, - int); -static void - wv_82593_reconfig(struct net_device *); /* Reconfigure the controller */ -/* ------------------- DEBUG & INFO SUBROUTINES ------------------- */ -static void - wv_init_info(struct net_device *); /* display startup info */ -/* ------------------- IOCTL, STATS & RECONFIG ------------------- */ -static iw_stats * - wavelan_get_wireless_stats(struct net_device *); -/* ----------------------- PACKET RECEPTION ----------------------- */ -static int - wv_start_of_frame(struct net_device *, /* Seek beggining of current frame */ - int, /* end of frame */ - int); /* start of buffer */ -static void - wv_packet_read(struct net_device *, /* Read a packet from a frame */ - int, - int), - wv_packet_rcv(struct net_device *); /* Read all packets waiting */ -/* --------------------- PACKET TRANSMISSION --------------------- */ -static void - wv_packet_write(struct net_device *, /* Write a packet to the Tx buffer */ - void *, - short); -static netdev_tx_t - wavelan_packet_xmit(struct sk_buff *, /* Send a packet */ - struct net_device *); -/* -------------------- HARDWARE CONFIGURATION -------------------- */ -static int - wv_mmc_init(struct net_device *); /* Initialize the modem */ -static int - wv_ru_stop(struct net_device *), /* Stop the i82593 receiver unit */ - wv_ru_start(struct net_device *); /* Start the i82593 receiver unit */ -static int - wv_82593_config(struct net_device *); /* Configure the i82593 */ -static int - wv_pcmcia_reset(struct net_device *); /* Reset the pcmcia interface */ -static int - wv_hw_config(struct net_device *); /* Reset & configure the whole hardware */ -static void - wv_hw_reset(struct net_device *); /* Same, + start receiver unit */ -static int - wv_pcmcia_config(struct pcmcia_device *); /* Configure the pcmcia interface */ -static void - wv_pcmcia_release(struct pcmcia_device *);/* Remove a device */ -/* ---------------------- INTERRUPT HANDLING ---------------------- */ -static irqreturn_t - wavelan_interrupt(int, /* Interrupt handler */ - void *); -static void - wavelan_watchdog(struct net_device *); /* Transmission watchdog */ -/* ------------------- CONFIGURATION CALLBACKS ------------------- */ -static int - wavelan_open(struct net_device *), /* Open the device */ - wavelan_close(struct net_device *); /* Close the device */ -static void - wavelan_detach(struct pcmcia_device *p_dev); /* Destroy a removed device */ - -/**************************** VARIABLES ****************************/ - -/* - * Parameters that can be set with 'insmod' - * The exact syntax is 'insmod wavelan_cs.o =' - */ - -/* Shared memory speed, in ns */ -static int mem_speed = 0; - -/* New module interface */ -module_param(mem_speed, int, 0); - -#ifdef WAVELAN_ROAMING /* Conditional compile, see above in options */ -/* Enable roaming mode ? No ! Please keep this to 0 */ -static int do_roaming = 0; -module_param(do_roaming, bool, 0); -#endif /* WAVELAN_ROAMING */ - -MODULE_LICENSE("GPL"); - -#endif /* WAVELAN_CS_P_H */ - diff --git a/drivers/net/wireless/wl12xx/Kconfig b/drivers/net/wireless/wl12xx/Kconfig deleted file mode 100644 index 88060e117541..000000000000 --- a/drivers/net/wireless/wl12xx/Kconfig +++ /dev/null @@ -1,52 +0,0 @@ -menuconfig WL12XX - tristate "TI wl12xx driver support" - depends on MAC80211 && WLAN_80211 && EXPERIMENTAL - ---help--- - This will enable TI wl12xx driver support. The drivers make - use of the mac80211 stack. - -config WL1251 - tristate "TI wl1251 support" - depends on WL12XX && GENERIC_HARDIRQS - select FW_LOADER - select CRC7 - ---help--- - This module adds support for wireless adapters based on - TI wl1251 chipset. - - If you choose to build a module, it'll be called wl1251. Say - N if unsure. - -config WL1251_SPI - tristate "TI wl1251 SPI support" - depends on WL1251 && SPI_MASTER - ---help--- - This module adds support for the SPI interface of adapters using - TI wl1251 chipset. Select this if your platform is using - the SPI bus. - - If you choose to build a module, it'll be called wl1251_spi. - Say N if unsure. - -config WL1251_SDIO - tristate "TI wl1251 SDIO support" - depends on WL1251 && MMC - ---help--- - This module adds support for the SDIO interface of adapters using - TI wl1251 chipset. Select this if your platform is using - the SDIO bus. - - If you choose to build a module, it'll be called - wl1251_sdio. Say N if unsure. - -config WL1271 - tristate "TI wl1271 support" - depends on WL12XX && SPI_MASTER && GENERIC_HARDIRQS - select FW_LOADER - select CRC7 - ---help--- - This module adds support for wireless adapters based on the - TI wl1271 chipset. - - If you choose to build a module, it'll be called wl1271. Say N if - unsure. diff --git a/drivers/net/wireless/wl12xx/Makefile b/drivers/net/wireless/wl12xx/Makefile deleted file mode 100644 index 62e37ad01cc0..000000000000 --- a/drivers/net/wireless/wl12xx/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -wl1251-objs = wl1251_main.o wl1251_event.o \ - wl1251_tx.o wl1251_rx.o wl1251_ps.o wl1251_cmd.o \ - wl1251_acx.o wl1251_boot.o wl1251_init.o \ - wl1251_debugfs.o wl1251_io.o - -obj-$(CONFIG_WL1251) += wl1251.o -obj-$(CONFIG_WL1251_SPI) += wl1251_spi.o -obj-$(CONFIG_WL1251_SDIO) += wl1251_sdio.o - -wl1271-objs = wl1271_main.o wl1271_spi.o wl1271_cmd.o \ - wl1271_event.o wl1271_tx.o wl1271_rx.o \ - wl1271_ps.o wl1271_acx.o wl1271_boot.o \ - wl1271_init.o wl1271_debugfs.o -obj-$(CONFIG_WL1271) += wl1271.o diff --git a/drivers/net/wireless/wl12xx/wl1251.h b/drivers/net/wireless/wl12xx/wl1251.h deleted file mode 100644 index 998e4b6252bd..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251.h +++ /dev/null @@ -1,424 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_H__ -#define __WL1251_H__ - -#include -#include -#include -#include - -#define DRIVER_NAME "wl1251" -#define DRIVER_PREFIX DRIVER_NAME ": " - -enum { - DEBUG_NONE = 0, - DEBUG_IRQ = BIT(0), - DEBUG_SPI = BIT(1), - DEBUG_BOOT = BIT(2), - DEBUG_MAILBOX = BIT(3), - DEBUG_NETLINK = BIT(4), - DEBUG_EVENT = BIT(5), - DEBUG_TX = BIT(6), - DEBUG_RX = BIT(7), - DEBUG_SCAN = BIT(8), - DEBUG_CRYPT = BIT(9), - DEBUG_PSM = BIT(10), - DEBUG_MAC80211 = BIT(11), - DEBUG_CMD = BIT(12), - DEBUG_ACX = BIT(13), - DEBUG_ALL = ~0, -}; - -#define DEBUG_LEVEL (DEBUG_NONE) - -#define DEBUG_DUMP_LIMIT 1024 - -#define wl1251_error(fmt, arg...) \ - printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) - -#define wl1251_warning(fmt, arg...) \ - printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) - -#define wl1251_notice(fmt, arg...) \ - printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1251_info(fmt, arg...) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1251_debug(level, fmt, arg...) \ - do { \ - if (level & DEBUG_LEVEL) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ - } while (0) - -#define wl1251_dump(level, prefix, buf, len) \ - do { \ - if (level & DEBUG_LEVEL) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - 0); \ - } while (0) - -#define wl1251_dump_ascii(level, prefix, buf, len) \ - do { \ - if (level & DEBUG_LEVEL) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - true); \ - } while (0) - -#define WL1251_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ - CFG_BSSID_FILTER_EN) - -#define WL1251_DEFAULT_RX_FILTER (CFG_RX_PRSP_EN | \ - CFG_RX_MGMT_EN | \ - CFG_RX_DATA_EN | \ - CFG_RX_CTL_EN | \ - CFG_RX_BCN_EN | \ - CFG_RX_AUTH_EN | \ - CFG_RX_ASSOC_EN) - -#define WL1251_BUSY_WORD_LEN 8 - -struct boot_attr { - u32 radio_type; - u8 mac_clock; - u8 arm_clock; - int firmware_debug; - u32 minor; - u32 major; - u32 bugfix; -}; - -enum wl1251_state { - WL1251_STATE_OFF, - WL1251_STATE_ON, - WL1251_STATE_PLT, -}; - -enum wl1251_partition_type { - PART_DOWN, - PART_WORK, - PART_DRPW, - - PART_TABLE_LEN -}; - -struct wl1251_partition { - u32 size; - u32 start; -}; - -struct wl1251_partition_set { - struct wl1251_partition mem; - struct wl1251_partition reg; -}; - -struct wl1251; - -struct wl1251_stats { - struct acx_statistics *fw_stats; - unsigned long fw_stats_update; - - unsigned int retry_count; - unsigned int excessive_retries; -}; - -struct wl1251_debugfs { - struct dentry *rootdir; - struct dentry *fw_statistics; - - struct dentry *tx_internal_desc_overflow; - - struct dentry *rx_out_of_mem; - struct dentry *rx_hdr_overflow; - struct dentry *rx_hw_stuck; - struct dentry *rx_dropped; - struct dentry *rx_fcs_err; - struct dentry *rx_xfr_hint_trig; - struct dentry *rx_path_reset; - struct dentry *rx_reset_counter; - - struct dentry *dma_rx_requested; - struct dentry *dma_rx_errors; - struct dentry *dma_tx_requested; - struct dentry *dma_tx_errors; - - struct dentry *isr_cmd_cmplt; - struct dentry *isr_fiqs; - struct dentry *isr_rx_headers; - struct dentry *isr_rx_mem_overflow; - struct dentry *isr_rx_rdys; - struct dentry *isr_irqs; - struct dentry *isr_tx_procs; - struct dentry *isr_decrypt_done; - struct dentry *isr_dma0_done; - struct dentry *isr_dma1_done; - struct dentry *isr_tx_exch_complete; - struct dentry *isr_commands; - struct dentry *isr_rx_procs; - struct dentry *isr_hw_pm_mode_changes; - struct dentry *isr_host_acknowledges; - struct dentry *isr_pci_pm; - struct dentry *isr_wakeups; - struct dentry *isr_low_rssi; - - struct dentry *wep_addr_key_count; - struct dentry *wep_default_key_count; - /* skipping wep.reserved */ - struct dentry *wep_key_not_found; - struct dentry *wep_decrypt_fail; - struct dentry *wep_packets; - struct dentry *wep_interrupt; - - struct dentry *pwr_ps_enter; - struct dentry *pwr_elp_enter; - struct dentry *pwr_missing_bcns; - struct dentry *pwr_wake_on_host; - struct dentry *pwr_wake_on_timer_exp; - struct dentry *pwr_tx_with_ps; - struct dentry *pwr_tx_without_ps; - struct dentry *pwr_rcvd_beacons; - struct dentry *pwr_power_save_off; - struct dentry *pwr_enable_ps; - struct dentry *pwr_disable_ps; - struct dentry *pwr_fix_tsf_ps; - /* skipping cont_miss_bcns_spread for now */ - struct dentry *pwr_rcvd_awake_beacons; - - struct dentry *mic_rx_pkts; - struct dentry *mic_calc_failure; - - struct dentry *aes_encrypt_fail; - struct dentry *aes_decrypt_fail; - struct dentry *aes_encrypt_packets; - struct dentry *aes_decrypt_packets; - struct dentry *aes_encrypt_interrupt; - struct dentry *aes_decrypt_interrupt; - - struct dentry *event_heart_beat; - struct dentry *event_calibration; - struct dentry *event_rx_mismatch; - struct dentry *event_rx_mem_empty; - struct dentry *event_rx_pool; - struct dentry *event_oom_late; - struct dentry *event_phy_transmit_error; - struct dentry *event_tx_stuck; - - struct dentry *ps_pspoll_timeouts; - struct dentry *ps_upsd_timeouts; - struct dentry *ps_upsd_max_sptime; - struct dentry *ps_upsd_max_apturn; - struct dentry *ps_pspoll_max_apturn; - struct dentry *ps_pspoll_utilization; - struct dentry *ps_upsd_utilization; - - struct dentry *rxpipe_rx_prep_beacon_drop; - struct dentry *rxpipe_descr_host_int_trig_rx_data; - struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data; - struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data; - struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; - - struct dentry *tx_queue_len; - - struct dentry *retry_count; - struct dentry *excessive_retries; -}; - -struct wl1251_if_operations { - void (*read)(struct wl1251 *wl, int addr, void *buf, size_t len); - void (*write)(struct wl1251 *wl, int addr, void *buf, size_t len); - void (*reset)(struct wl1251 *wl); - void (*enable_irq)(struct wl1251 *wl); - void (*disable_irq)(struct wl1251 *wl); -}; - -struct wl1251 { - struct ieee80211_hw *hw; - bool mac80211_registered; - - void *if_priv; - const struct wl1251_if_operations *if_ops; - - void (*set_power)(bool enable); - int irq; - - enum wl1251_state state; - struct mutex mutex; - - int physical_mem_addr; - int physical_reg_addr; - int virtual_mem_addr; - int virtual_reg_addr; - - int cmd_box_addr; - int event_box_addr; - struct boot_attr boot_attr; - - u8 *fw; - size_t fw_len; - u8 *nvs; - size_t nvs_len; - - u8 bssid[ETH_ALEN]; - u8 mac_addr[ETH_ALEN]; - u8 bss_type; - u8 listen_int; - int channel; - - void *target_mem_map; - struct acx_data_path_params_resp *data_path; - - /* Number of TX packets transferred to the FW, modulo 16 */ - u32 data_in_count; - - /* Frames scheduled for transmission, not handled yet */ - struct sk_buff_head tx_queue; - bool tx_queue_stopped; - - struct work_struct tx_work; - struct work_struct filter_work; - - /* Pending TX frames */ - struct sk_buff *tx_frames[16]; - - /* - * Index pointing to the next TX complete entry - * in the cyclic XT complete array we get from - * the FW. - */ - u32 next_tx_complete; - - /* FW Rx counter */ - u32 rx_counter; - - /* Rx frames handled */ - u32 rx_handled; - - /* Current double buffer */ - u32 rx_current_buffer; - u32 rx_last_id; - - /* The target interrupt mask */ - u32 intr_mask; - struct work_struct irq_work; - - /* The mbox event mask */ - u32 event_mask; - - /* Mailbox pointers */ - u32 mbox_ptr[2]; - - /* Are we currently scanning */ - bool scanning; - - /* Our association ID */ - u16 aid; - - /* Default key (for WEP) */ - u32 default_key; - - unsigned int tx_mgmt_frm_rate; - unsigned int tx_mgmt_frm_mod; - - unsigned int rx_config; - unsigned int rx_filter; - - /* is firmware in elp mode */ - bool elp; - - /* we can be in psm, but not in elp, we have to differentiate */ - bool psm; - - /* PSM mode requested */ - bool psm_requested; - - u16 beacon_int; - u8 dtim_period; - - /* in dBm */ - int power_level; - - struct wl1251_stats stats; - struct wl1251_debugfs debugfs; - - u32 buffer_32; - u32 buffer_cmd; - u8 buffer_busyword[WL1251_BUSY_WORD_LEN]; - struct wl1251_rx_descriptor *rx_descriptor; - - u32 chip_id; - char fw_ver[21]; -}; - -int wl1251_plt_start(struct wl1251 *wl); -int wl1251_plt_stop(struct wl1251 *wl); - -struct ieee80211_hw *wl1251_alloc_hw(void); -int wl1251_free_hw(struct wl1251 *wl); -int wl1251_init_ieee80211(struct wl1251 *wl); -void wl1251_enable_interrupts(struct wl1251 *wl); -void wl1251_disable_interrupts(struct wl1251 *wl); - -#define DEFAULT_HW_GEN_MODULATION_TYPE CCK_LONG /* Long Preamble */ -#define DEFAULT_HW_GEN_TX_RATE RATE_2MBPS -#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ - -#define WL1251_DEFAULT_POWER_LEVEL 20 - -#define WL1251_TX_QUEUE_MAX_LENGTH 20 - -#define WL1251_DEFAULT_BEACON_INT 100 -#define WL1251_DEFAULT_DTIM_PERIOD 1 - -#define WL1251_DEFAULT_CHANNEL 0 - -#define CHIP_ID_1251_PG10 (0x7010101) -#define CHIP_ID_1251_PG11 (0x7020101) -#define CHIP_ID_1251_PG12 (0x7030101) -#define CHIP_ID_1271_PG10 (0x4030101) -#define CHIP_ID_1271_PG20 (0x4030111) - -#define WL1251_FW_NAME "wl1251-fw.bin" -#define WL1251_NVS_NAME "wl1251-nvs.bin" - -#define WL1251_POWER_ON_SLEEP 10 /* in miliseconds */ - -#define WL1251_PART_DOWN_MEM_START 0x0 -#define WL1251_PART_DOWN_MEM_SIZE 0x16800 -#define WL1251_PART_DOWN_REG_START REGISTERS_BASE -#define WL1251_PART_DOWN_REG_SIZE REGISTERS_DOWN_SIZE - -#define WL1251_PART_WORK_MEM_START 0x28000 -#define WL1251_PART_WORK_MEM_SIZE 0x14000 -#define WL1251_PART_WORK_REG_START REGISTERS_BASE -#define WL1251_PART_WORK_REG_SIZE REGISTERS_WORK_SIZE - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.c b/drivers/net/wireless/wl12xx/wl1251_acx.c deleted file mode 100644 index 10b26c4532c9..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_acx.c +++ /dev/null @@ -1,918 +0,0 @@ -#include "wl1251_acx.h" - -#include -#include - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_cmd.h" -#include "wl1251_ps.h" - -int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, - u8 mgt_rate, u8 mgt_mod) -{ - struct acx_fw_gen_frame_rates *rates; - int ret; - - wl1251_debug(DEBUG_ACX, "acx frame rates"); - - rates = kzalloc(sizeof(*rates), GFP_KERNEL); - if (!rates) { - ret = -ENOMEM; - goto out; - } - - rates->tx_ctrl_frame_rate = ctrl_rate; - rates->tx_ctrl_frame_mod = ctrl_mod; - rates->tx_mgt_frame_rate = mgt_rate; - rates->tx_mgt_frame_mod = mgt_mod; - - ret = wl1251_cmd_configure(wl, ACX_FW_GEN_FRAME_RATES, - rates, sizeof(*rates)); - if (ret < 0) { - wl1251_error("Failed to set FW rates and modulation"); - goto out; - } - -out: - kfree(rates); - return ret; -} - - -int wl1251_acx_station_id(struct wl1251 *wl) -{ - struct acx_dot11_station_id *mac; - int ret, i; - - wl1251_debug(DEBUG_ACX, "acx dot11_station_id"); - - mac = kzalloc(sizeof(*mac), GFP_KERNEL); - if (!mac) { - ret = -ENOMEM; - goto out; - } - - for (i = 0; i < ETH_ALEN; i++) - mac->mac[i] = wl->mac_addr[ETH_ALEN - 1 - i]; - - ret = wl1251_cmd_configure(wl, DOT11_STATION_ID, mac, sizeof(*mac)); - if (ret < 0) - goto out; - -out: - kfree(mac); - return ret; -} - -int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id) -{ - struct acx_dot11_default_key *default_key; - int ret; - - wl1251_debug(DEBUG_ACX, "acx dot11_default_key (%d)", key_id); - - default_key = kzalloc(sizeof(*default_key), GFP_KERNEL); - if (!default_key) { - ret = -ENOMEM; - goto out; - } - - default_key->id = key_id; - - ret = wl1251_cmd_configure(wl, DOT11_DEFAULT_KEY, - default_key, sizeof(*default_key)); - if (ret < 0) { - wl1251_error("Couldn't set default key"); - goto out; - } - - wl->default_key = key_id; - -out: - kfree(default_key); - return ret; -} - -int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, - u8 listen_interval) -{ - struct acx_wake_up_condition *wake_up; - int ret; - - wl1251_debug(DEBUG_ACX, "acx wake up conditions"); - - wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); - if (!wake_up) { - ret = -ENOMEM; - goto out; - } - - wake_up->wake_up_event = wake_up_event; - wake_up->listen_interval = listen_interval; - - ret = wl1251_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, - wake_up, sizeof(*wake_up)); - if (ret < 0) { - wl1251_warning("could not set wake up conditions: %d", ret); - goto out; - } - -out: - kfree(wake_up); - return ret; -} - -int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth) -{ - struct acx_sleep_auth *auth; - int ret; - - wl1251_debug(DEBUG_ACX, "acx sleep auth"); - - auth = kzalloc(sizeof(*auth), GFP_KERNEL); - if (!auth) { - ret = -ENOMEM; - goto out; - } - - auth->sleep_auth = sleep_auth; - - ret = wl1251_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); - if (ret < 0) - return ret; - -out: - kfree(auth); - return ret; -} - -int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len) -{ - struct acx_revision *rev; - int ret; - - wl1251_debug(DEBUG_ACX, "acx fw rev"); - - rev = kzalloc(sizeof(*rev), GFP_KERNEL); - if (!rev) { - ret = -ENOMEM; - goto out; - } - - ret = wl1251_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); - if (ret < 0) { - wl1251_warning("ACX_FW_REV interrogate failed"); - goto out; - } - - /* be careful with the buffer sizes */ - strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); - - /* - * if the firmware version string is exactly - * sizeof(rev->fw_version) long or fw_len is less than - * sizeof(rev->fw_version) it won't be null terminated - */ - buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; - -out: - kfree(rev); - return ret; -} - -int wl1251_acx_tx_power(struct wl1251 *wl, int power) -{ - struct acx_current_tx_power *acx; - int ret; - - wl1251_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); - - if (power < 0 || power > 25) - return -EINVAL; - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->current_tx_power = power * 10; - - ret = wl1251_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); - if (ret < 0) { - wl1251_warning("configure of tx power failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1251_acx_feature_cfg(struct wl1251 *wl) -{ - struct acx_feature_config *feature; - int ret; - - wl1251_debug(DEBUG_ACX, "acx feature cfg"); - - feature = kzalloc(sizeof(*feature), GFP_KERNEL); - if (!feature) { - ret = -ENOMEM; - goto out; - } - - /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ - feature->data_flow_options = 0; - feature->options = 0; - - ret = wl1251_cmd_configure(wl, ACX_FEATURE_CFG, - feature, sizeof(*feature)); - if (ret < 0) { - wl1251_error("Couldn't set HW encryption"); - goto out; - } - -out: - kfree(feature); - return ret; -} - -int wl1251_acx_mem_map(struct wl1251 *wl, struct acx_header *mem_map, - size_t len) -{ - int ret; - - wl1251_debug(DEBUG_ACX, "acx mem map"); - - ret = wl1251_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_acx_data_path_params(struct wl1251 *wl, - struct acx_data_path_params_resp *resp) -{ - struct acx_data_path_params *params; - int ret; - - wl1251_debug(DEBUG_ACX, "acx data path params"); - - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) { - ret = -ENOMEM; - goto out; - } - - params->rx_packet_ring_chunk_size = DP_RX_PACKET_RING_CHUNK_SIZE; - params->tx_packet_ring_chunk_size = DP_TX_PACKET_RING_CHUNK_SIZE; - - params->rx_packet_ring_chunk_num = DP_RX_PACKET_RING_CHUNK_NUM; - params->tx_packet_ring_chunk_num = DP_TX_PACKET_RING_CHUNK_NUM; - - params->tx_complete_threshold = 1; - - params->tx_complete_ring_depth = FW_TX_CMPLT_BLOCK_SIZE; - - params->tx_complete_timeout = DP_TX_COMPLETE_TIME_OUT; - - ret = wl1251_cmd_configure(wl, ACX_DATA_PATH_PARAMS, - params, sizeof(*params)); - if (ret < 0) - goto out; - - /* FIXME: shouldn't this be ACX_DATA_PATH_RESP_PARAMS? */ - ret = wl1251_cmd_interrogate(wl, ACX_DATA_PATH_PARAMS, - resp, sizeof(*resp)); - - if (ret < 0) { - wl1251_warning("failed to read data path parameters: %d", ret); - goto out; - } else if (resp->header.cmd.status != CMD_STATUS_SUCCESS) { - wl1251_warning("data path parameter acx status failed"); - ret = -EIO; - goto out; - } - -out: - kfree(params); - return ret; -} - -int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time) -{ - struct acx_rx_msdu_lifetime *acx; - int ret; - - wl1251_debug(DEBUG_ACX, "acx rx msdu life time"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->lifetime = life_time; - ret = wl1251_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, - acx, sizeof(*acx)); - if (ret < 0) { - wl1251_warning("failed to set rx msdu life time: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter) -{ - struct acx_rx_config *rx_config; - int ret; - - wl1251_debug(DEBUG_ACX, "acx rx config"); - - rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); - if (!rx_config) { - ret = -ENOMEM; - goto out; - } - - rx_config->config_options = config; - rx_config->filter_options = filter; - - ret = wl1251_cmd_configure(wl, ACX_RX_CFG, - rx_config, sizeof(*rx_config)); - if (ret < 0) { - wl1251_warning("failed to set rx config: %d", ret); - goto out; - } - -out: - kfree(rx_config); - return ret; -} - -int wl1251_acx_pd_threshold(struct wl1251 *wl) -{ - struct acx_packet_detection *pd; - int ret; - - wl1251_debug(DEBUG_ACX, "acx data pd threshold"); - - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - /* FIXME: threshold value not set */ - - ret = wl1251_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); - if (ret < 0) { - wl1251_warning("failed to set pd threshold: %d", ret); - goto out; - } - -out: - kfree(pd); - return 0; -} - -int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time) -{ - struct acx_slot *slot; - int ret; - - wl1251_debug(DEBUG_ACX, "acx slot"); - - slot = kzalloc(sizeof(*slot), GFP_KERNEL); - if (!slot) { - ret = -ENOMEM; - goto out; - } - - slot->wone_index = STATION_WONE_INDEX; - slot->slot_time = slot_time; - - ret = wl1251_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot)); - if (ret < 0) { - wl1251_warning("failed to set slot time: %d", ret); - goto out; - } - -out: - kfree(slot); - return ret; -} - -int wl1251_acx_group_address_tbl(struct wl1251 *wl) -{ - struct acx_dot11_grp_addr_tbl *acx; - int ret; - - wl1251_debug(DEBUG_ACX, "acx group address tbl"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - /* MAC filtering */ - acx->enabled = 0; - acx->num_groups = 0; - memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); - - ret = wl1251_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, - acx, sizeof(*acx)); - if (ret < 0) { - wl1251_warning("failed to set group addr table: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1251_acx_service_period_timeout(struct wl1251 *wl) -{ - struct acx_rx_timeout *rx_timeout; - int ret; - - rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); - if (!rx_timeout) { - ret = -ENOMEM; - goto out; - } - - wl1251_debug(DEBUG_ACX, "acx service period timeout"); - - rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; - rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF; - - ret = wl1251_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, - rx_timeout, sizeof(*rx_timeout)); - if (ret < 0) { - wl1251_warning("failed to set service period timeout: %d", - ret); - goto out; - } - -out: - kfree(rx_timeout); - return ret; -} - -int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold) -{ - struct acx_rts_threshold *rts; - int ret; - - wl1251_debug(DEBUG_ACX, "acx rts threshold"); - - rts = kzalloc(sizeof(*rts), GFP_KERNEL); - if (!rts) { - ret = -ENOMEM; - goto out; - } - - rts->threshold = rts_threshold; - - ret = wl1251_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); - if (ret < 0) { - wl1251_warning("failed to set rts threshold: %d", ret); - goto out; - } - -out: - kfree(rts); - return ret; -} - -int wl1251_acx_beacon_filter_opt(struct wl1251 *wl) -{ - struct acx_beacon_filter_option *beacon_filter; - int ret; - - wl1251_debug(DEBUG_ACX, "acx beacon filter opt"); - - beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); - if (!beacon_filter) { - ret = -ENOMEM; - goto out; - } - - beacon_filter->enable = 0; - beacon_filter->max_num_beacons = 0; - - ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_OPT, - beacon_filter, sizeof(*beacon_filter)); - if (ret < 0) { - wl1251_warning("failed to set beacon filter opt: %d", ret); - goto out; - } - -out: - kfree(beacon_filter); - return ret; -} - -int wl1251_acx_beacon_filter_table(struct wl1251 *wl) -{ - struct acx_beacon_filter_ie_table *ie_table; - int ret; - - wl1251_debug(DEBUG_ACX, "acx beacon filter table"); - - ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); - if (!ie_table) { - ret = -ENOMEM; - goto out; - } - - ie_table->num_ie = 0; - memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); - - ret = wl1251_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, - ie_table, sizeof(*ie_table)); - if (ret < 0) { - wl1251_warning("failed to set beacon filter table: %d", ret); - goto out; - } - -out: - kfree(ie_table); - return ret; -} - -int wl1251_acx_sg_enable(struct wl1251 *wl) -{ - struct acx_bt_wlan_coex *pta; - int ret; - - wl1251_debug(DEBUG_ACX, "acx sg enable"); - - pta = kzalloc(sizeof(*pta), GFP_KERNEL); - if (!pta) { - ret = -ENOMEM; - goto out; - } - - pta->enable = SG_ENABLE; - - ret = wl1251_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); - if (ret < 0) { - wl1251_warning("failed to set softgemini enable: %d", ret); - goto out; - } - -out: - kfree(pta); - return ret; -} - -int wl1251_acx_sg_cfg(struct wl1251 *wl) -{ - struct acx_bt_wlan_coex_param *param; - int ret; - - wl1251_debug(DEBUG_ACX, "acx sg cfg"); - - param = kzalloc(sizeof(*param), GFP_KERNEL); - if (!param) { - ret = -ENOMEM; - goto out; - } - - /* BT-WLAN coext parameters */ - param->min_rate = RATE_INDEX_24MBPS; - param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; - param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; - param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; - param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; - param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; - param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; - param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; - param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; - param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; - param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; - param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; - param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; - param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; - param->antenna_type = PTA_ANTENNA_TYPE_DEF; - param->signal_type = PTA_SIGNALING_TYPE_DEF; - param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; - param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; - param->max_cts = PTA_MAX_NUM_CTS_DEF; - param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; - param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; - param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; - param->wlan_elp_hp = PTA_ELP_HP_DEF; - param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; - param->ack_mode_dual_ant = PTA_ACK_MODE_DEF; - param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF; - param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; - param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; - - ret = wl1251_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); - if (ret < 0) { - wl1251_warning("failed to set sg config: %d", ret); - goto out; - } - -out: - kfree(param); - return ret; -} - -int wl1251_acx_cca_threshold(struct wl1251 *wl) -{ - struct acx_energy_detection *detection; - int ret; - - wl1251_debug(DEBUG_ACX, "acx cca threshold"); - - detection = kzalloc(sizeof(*detection), GFP_KERNEL); - if (!detection) { - ret = -ENOMEM; - goto out; - } - - detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; - detection->tx_energy_detection = 0; - - ret = wl1251_cmd_configure(wl, ACX_CCA_THRESHOLD, - detection, sizeof(*detection)); - if (ret < 0) { - wl1251_warning("failed to set cca threshold: %d", ret); - return ret; - } - -out: - kfree(detection); - return ret; -} - -int wl1251_acx_bcn_dtim_options(struct wl1251 *wl) -{ - struct acx_beacon_broadcast *bb; - int ret; - - wl1251_debug(DEBUG_ACX, "acx bcn dtim options"); - - bb = kzalloc(sizeof(*bb), GFP_KERNEL); - if (!bb) { - ret = -ENOMEM; - goto out; - } - - bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; - bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; - bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; - bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; - - ret = wl1251_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); - if (ret < 0) { - wl1251_warning("failed to set rx config: %d", ret); - goto out; - } - -out: - kfree(bb); - return ret; -} - -int wl1251_acx_aid(struct wl1251 *wl, u16 aid) -{ - struct acx_aid *acx_aid; - int ret; - - wl1251_debug(DEBUG_ACX, "acx aid"); - - acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); - if (!acx_aid) { - ret = -ENOMEM; - goto out; - } - - acx_aid->aid = aid; - - ret = wl1251_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); - if (ret < 0) { - wl1251_warning("failed to set aid: %d", ret); - goto out; - } - -out: - kfree(acx_aid); - return ret; -} - -int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask) -{ - struct acx_event_mask *mask; - int ret; - - wl1251_debug(DEBUG_ACX, "acx event mbox mask"); - - mask = kzalloc(sizeof(*mask), GFP_KERNEL); - if (!mask) { - ret = -ENOMEM; - goto out; - } - - /* high event mask is unused */ - mask->high_event_mask = 0xffffffff; - - mask->event_mask = event_mask; - - ret = wl1251_cmd_configure(wl, ACX_EVENT_MBOX_MASK, - mask, sizeof(*mask)); - if (ret < 0) { - wl1251_warning("failed to set acx_event_mbox_mask: %d", ret); - goto out; - } - -out: - kfree(mask); - return ret; -} - -int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble) -{ - struct acx_preamble *acx; - int ret; - - wl1251_debug(DEBUG_ACX, "acx_set_preamble"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->preamble = preamble; - - ret = wl1251_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); - if (ret < 0) { - wl1251_warning("Setting of preamble failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1251_acx_cts_protect(struct wl1251 *wl, - enum acx_ctsprotect_type ctsprotect) -{ - struct acx_ctsprotect *acx; - int ret; - - wl1251_debug(DEBUG_ACX, "acx_set_ctsprotect"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->ctsprotect = ctsprotect; - - ret = wl1251_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); - if (ret < 0) { - wl1251_warning("Setting of ctsprotect failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime) -{ - struct acx_tsf_info *tsf_info; - int ret; - - tsf_info = kzalloc(sizeof(*tsf_info), GFP_KERNEL); - if (!tsf_info) { - ret = -ENOMEM; - goto out; - } - - ret = wl1251_cmd_interrogate(wl, ACX_TSF_INFO, - tsf_info, sizeof(*tsf_info)); - if (ret < 0) { - wl1251_warning("ACX_FW_REV interrogate failed"); - goto out; - } - - *mactime = tsf_info->current_tsf_lsb | - (tsf_info->current_tsf_msb << 31); - -out: - kfree(tsf_info); - return ret; -} - -int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats) -{ - int ret; - - wl1251_debug(DEBUG_ACX, "acx statistics"); - - ret = wl1251_cmd_interrogate(wl, ACX_STATISTICS, stats, - sizeof(*stats)); - if (ret < 0) { - wl1251_warning("acx statistics failed: %d", ret); - return -ENOMEM; - } - - return 0; -} - -int wl1251_acx_rate_policies(struct wl1251 *wl) -{ - struct acx_rate_policy *acx; - int ret = 0; - - wl1251_debug(DEBUG_ACX, "acx rate policies"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } - - /* configure one default (one-size-fits-all) rate class */ - acx->rate_class_cnt = 1; - acx->rate_class[0].enabled_rates = ACX_RATE_MASK_UNSPECIFIED; - acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; - acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; - acx->rate_class[0].aflags = 0; - - ret = wl1251_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); - if (ret < 0) { - wl1251_warning("Setting of rate policies failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1251_acx_mem_cfg(struct wl1251 *wl) -{ - struct wl1251_acx_config_memory *mem_conf; - int ret, i; - - wl1251_debug(DEBUG_ACX, "acx mem cfg"); - - mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); - if (!mem_conf) { - ret = -ENOMEM; - goto out; - } - - /* memory config */ - mem_conf->mem_config.num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); - mem_conf->mem_config.rx_mem_block_num = 35; - mem_conf->mem_config.tx_min_mem_block_num = 64; - mem_conf->mem_config.num_tx_queues = MAX_TX_QUEUES; - mem_conf->mem_config.host_if_options = HOSTIF_PKT_RING; - mem_conf->mem_config.num_ssid_profiles = 1; - mem_conf->mem_config.debug_buffer_size = - cpu_to_le16(TRACE_BUFFER_MAX_SIZE); - - /* RX queue config */ - mem_conf->rx_queue_config.dma_address = 0; - mem_conf->rx_queue_config.num_descs = ACX_RX_DESC_DEF; - mem_conf->rx_queue_config.priority = DEFAULT_RXQ_PRIORITY; - mem_conf->rx_queue_config.type = DEFAULT_RXQ_TYPE; - - /* TX queue config */ - for (i = 0; i < MAX_TX_QUEUES; i++) { - mem_conf->tx_queue_config[i].num_descs = ACX_TX_DESC_DEF; - mem_conf->tx_queue_config[i].attributes = i; - } - - ret = wl1251_cmd_configure(wl, ACX_MEM_CFG, mem_conf, - sizeof(*mem_conf)); - if (ret < 0) { - wl1251_warning("wl1251 mem config failed: %d", ret); - goto out; - } - -out: - kfree(mem_conf); - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1251_acx.h b/drivers/net/wireless/wl12xx/wl1251_acx.h deleted file mode 100644 index cafb91459504..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_acx.h +++ /dev/null @@ -1,1292 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_ACX_H__ -#define __WL1251_ACX_H__ - -#include "wl1251.h" -#include "wl1251_cmd.h" - -/* Target's information element */ -struct acx_header { - struct wl1251_cmd_header cmd; - - /* acx (or information element) header */ - u16 id; - - /* payload length (not including headers */ - u16 len; -}; - -struct acx_error_counter { - struct acx_header header; - - /* The number of PLCP errors since the last time this */ - /* information element was interrogated. This field is */ - /* automatically cleared when it is interrogated.*/ - u32 PLCP_error; - - /* The number of FCS errors since the last time this */ - /* information element was interrogated. This field is */ - /* automatically cleared when it is interrogated.*/ - u32 FCS_error; - - /* The number of MPDUs without PLCP header errors received*/ - /* since the last time this information element was interrogated. */ - /* This field is automatically cleared when it is interrogated.*/ - u32 valid_frame; - - /* the number of missed sequence numbers in the squentially */ - /* values of frames seq numbers */ - u32 seq_num_miss; -} __attribute__ ((packed)); - -struct acx_revision { - struct acx_header header; - - /* - * The WiLink firmware version, an ASCII string x.x.x.x, - * that uniquely identifies the current firmware. - * The left most digit is incremented each time a - * significant change is made to the firmware, such as - * code redesign or new platform support. - * The second digit is incremented when major enhancements - * are added or major fixes are made. - * The third digit is incremented for each GA release. - * The fourth digit is incremented for each build. - * The first two digits identify a firmware release version, - * in other words, a unique set of features. - * The first three digits identify a GA release. - */ - char fw_version[20]; - - /* - * This 4 byte field specifies the WiLink hardware version. - * bits 0 - 15: Reserved. - * bits 16 - 23: Version ID - The WiLink version ID - * (1 = first spin, 2 = second spin, and so on). - * bits 24 - 31: Chip ID - The WiLink chip ID. - */ - u32 hw_version; -} __attribute__ ((packed)); - -enum wl1251_psm_mode { - /* Active mode */ - WL1251_PSM_CAM = 0, - - /* Power save mode */ - WL1251_PSM_PS = 1, - - /* Extreme low power */ - WL1251_PSM_ELP = 2, -}; - -struct acx_sleep_auth { - struct acx_header header; - - /* The sleep level authorization of the device. */ - /* 0 - Always active*/ - /* 1 - Power down mode: light / fast sleep*/ - /* 2 - ELP mode: Deep / Max sleep*/ - u8 sleep_auth; - u8 padding[3]; -} __attribute__ ((packed)); - -enum { - HOSTIF_PCI_MASTER_HOST_INDIRECT, - HOSTIF_PCI_MASTER_HOST_DIRECT, - HOSTIF_SLAVE, - HOSTIF_PKT_RING, - HOSTIF_DONTCARE = 0xFF -}; - -#define DEFAULT_UCAST_PRIORITY 0 -#define DEFAULT_RX_Q_PRIORITY 0 -#define DEFAULT_NUM_STATIONS 1 -#define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */ -#define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */ -#define TRACE_BUFFER_MAX_SIZE 256 - -#define DP_RX_PACKET_RING_CHUNK_SIZE 1600 -#define DP_TX_PACKET_RING_CHUNK_SIZE 1600 -#define DP_RX_PACKET_RING_CHUNK_NUM 2 -#define DP_TX_PACKET_RING_CHUNK_NUM 2 -#define DP_TX_COMPLETE_TIME_OUT 20 -#define FW_TX_CMPLT_BLOCK_SIZE 16 - -struct acx_data_path_params { - struct acx_header header; - - u16 rx_packet_ring_chunk_size; - u16 tx_packet_ring_chunk_size; - - u8 rx_packet_ring_chunk_num; - u8 tx_packet_ring_chunk_num; - - /* - * Maximum number of packets that can be gathered - * in the TX complete ring before an interrupt - * is generated. - */ - u8 tx_complete_threshold; - - /* Number of pending TX complete entries in cyclic ring.*/ - u8 tx_complete_ring_depth; - - /* - * Max num microseconds since a packet enters the TX - * complete ring until an interrupt is generated. - */ - u32 tx_complete_timeout; -} __attribute__ ((packed)); - - -struct acx_data_path_params_resp { - struct acx_header header; - - u16 rx_packet_ring_chunk_size; - u16 tx_packet_ring_chunk_size; - - u8 rx_packet_ring_chunk_num; - u8 tx_packet_ring_chunk_num; - - u8 pad[2]; - - u32 rx_packet_ring_addr; - u32 tx_packet_ring_addr; - - u32 rx_control_addr; - u32 tx_control_addr; - - u32 tx_complete_addr; -} __attribute__ ((packed)); - -#define TX_MSDU_LIFETIME_MIN 0 -#define TX_MSDU_LIFETIME_MAX 3000 -#define TX_MSDU_LIFETIME_DEF 512 -#define RX_MSDU_LIFETIME_MIN 0 -#define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF -#define RX_MSDU_LIFETIME_DEF 512000 - -struct acx_rx_msdu_lifetime { - struct acx_header header; - - /* - * The maximum amount of time, in TU, before the - * firmware discards the MSDU. - */ - u32 lifetime; -} __attribute__ ((packed)); - -/* - * RX Config Options Table - * Bit Definition - * === ========== - * 31:14 Reserved - * 13 Copy RX Status - when set, write three receive status words - * to top of rx'd MPDUs. - * When cleared, do not write three status words (added rev 1.5) - * 12 Reserved - * 11 RX Complete upon FCS error - when set, give rx complete - * interrupt for FCS errors, after the rx filtering, e.g. unicast - * frames not to us with FCS error will not generate an interrupt. - * 10 SSID Filter Enable - When set, the WiLink discards all beacon, - * probe request, and probe response frames with an SSID that does - * not match the SSID specified by the host in the START/JOIN - * command. - * When clear, the WiLink receives frames with any SSID. - * 9 Broadcast Filter Enable - When set, the WiLink discards all - * broadcast frames. When clear, the WiLink receives all received - * broadcast frames. - * 8:6 Reserved - * 5 BSSID Filter Enable - When set, the WiLink discards any frames - * with a BSSID that does not match the BSSID specified by the - * host. - * When clear, the WiLink receives frames from any BSSID. - * 4 MAC Addr Filter - When set, the WiLink discards any frames - * with a destination address that does not match the MAC address - * of the adaptor. - * When clear, the WiLink receives frames destined to any MAC - * address. - * 3 Promiscuous - When set, the WiLink receives all valid frames - * (i.e., all frames that pass the FCS check). - * When clear, only frames that pass the other filters specified - * are received. - * 2 FCS - When set, the WiLink includes the FCS with the received - * frame. - * When cleared, the FCS is discarded. - * 1 PLCP header - When set, write all data from baseband to frame - * buffer including PHY header. - * 0 Reserved - Always equal to 0. - * - * RX Filter Options Table - * Bit Definition - * === ========== - * 31:12 Reserved - Always equal to 0. - * 11 Association - When set, the WiLink receives all association - * related frames (association request/response, reassocation - * request/response, and disassociation). When clear, these frames - * are discarded. - * 10 Auth/De auth - When set, the WiLink receives all authentication - * and de-authentication frames. When clear, these frames are - * discarded. - * 9 Beacon - When set, the WiLink receives all beacon frames. - * When clear, these frames are discarded. - * 8 Contention Free - When set, the WiLink receives all contention - * free frames. - * When clear, these frames are discarded. - * 7 Control - When set, the WiLink receives all control frames. - * When clear, these frames are discarded. - * 6 Data - When set, the WiLink receives all data frames. - * When clear, these frames are discarded. - * 5 FCS Error - When set, the WiLink receives frames that have FCS - * errors. - * When clear, these frames are discarded. - * 4 Management - When set, the WiLink receives all management - * frames. - * When clear, these frames are discarded. - * 3 Probe Request - When set, the WiLink receives all probe request - * frames. - * When clear, these frames are discarded. - * 2 Probe Response - When set, the WiLink receives all probe - * response frames. - * When clear, these frames are discarded. - * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK - * frames. - * When clear, these frames are discarded. - * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames - * that have reserved frame types and sub types as defined by the - * 802.11 specification. - * When clear, these frames are discarded. - */ -struct acx_rx_config { - struct acx_header header; - - u32 config_options; - u32 filter_options; -} __attribute__ ((packed)); - -enum { - QOS_AC_BE = 0, - QOS_AC_BK, - QOS_AC_VI, - QOS_AC_VO, - QOS_HIGHEST_AC_INDEX = QOS_AC_VO, -}; - -#define MAX_NUM_OF_AC (QOS_HIGHEST_AC_INDEX+1) -#define FIRST_AC_INDEX QOS_AC_BE -#define MAX_NUM_OF_802_1d_TAGS 8 -#define AC_PARAMS_MAX_TSID 15 -#define MAX_APSD_CONF 0xffff - -#define QOS_TX_HIGH_MIN (0) -#define QOS_TX_HIGH_MAX (100) - -#define QOS_TX_HIGH_BK_DEF (25) -#define QOS_TX_HIGH_BE_DEF (35) -#define QOS_TX_HIGH_VI_DEF (35) -#define QOS_TX_HIGH_VO_DEF (35) - -#define QOS_TX_LOW_BK_DEF (15) -#define QOS_TX_LOW_BE_DEF (25) -#define QOS_TX_LOW_VI_DEF (25) -#define QOS_TX_LOW_VO_DEF (25) - -struct acx_tx_queue_qos_config { - struct acx_header header; - - u8 qid; - u8 pad[3]; - - /* Max number of blocks allowd in the queue */ - u16 high_threshold; - - /* Lowest memory blocks guaranteed for this queue */ - u16 low_threshold; -} __attribute__ ((packed)); - -struct acx_packet_detection { - struct acx_header header; - - u32 threshold; -} __attribute__ ((packed)); - - -enum acx_slot_type { - SLOT_TIME_LONG = 0, - SLOT_TIME_SHORT = 1, - DEFAULT_SLOT_TIME = SLOT_TIME_SHORT, - MAX_SLOT_TIMES = 0xFF -}; - -#define STATION_WONE_INDEX 0 - -struct acx_slot { - struct acx_header header; - - u8 wone_index; /* Reserved */ - u8 slot_time; - u8 reserved[6]; -} __attribute__ ((packed)); - - -#define ADDRESS_GROUP_MAX (8) -#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) - -struct acx_dot11_grp_addr_tbl { - struct acx_header header; - - u8 enabled; - u8 num_groups; - u8 pad[2]; - u8 mac_table[ADDRESS_GROUP_MAX_LEN]; -} __attribute__ ((packed)); - - -#define RX_TIMEOUT_PS_POLL_MIN 0 -#define RX_TIMEOUT_PS_POLL_MAX (200000) -#define RX_TIMEOUT_PS_POLL_DEF (15) -#define RX_TIMEOUT_UPSD_MIN 0 -#define RX_TIMEOUT_UPSD_MAX (200000) -#define RX_TIMEOUT_UPSD_DEF (15) - -struct acx_rx_timeout { - struct acx_header header; - - /* - * The longest time the STA will wait to receive - * traffic from the AP after a PS-poll has been - * transmitted. - */ - u16 ps_poll_timeout; - - /* - * The longest time the STA will wait to receive - * traffic from the AP after a frame has been sent - * from an UPSD enabled queue. - */ - u16 upsd_timeout; -} __attribute__ ((packed)); - -#define RTS_THRESHOLD_MIN 0 -#define RTS_THRESHOLD_MAX 4096 -#define RTS_THRESHOLD_DEF 2347 - -struct acx_rts_threshold { - struct acx_header header; - - u16 threshold; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_beacon_filter_option { - struct acx_header header; - - u8 enable; - - /* - * The number of beacons without the unicast TIM - * bit set that the firmware buffers before - * signaling the host about ready frames. - * When set to 0 and the filter is enabled, beacons - * without the unicast TIM bit set are dropped. - */ - u8 max_num_beacons; - u8 pad[2]; -} __attribute__ ((packed)); - -/* - * ACXBeaconFilterEntry (not 221) - * Byte Offset Size (Bytes) Definition - * =========== ============ ========== - * 0 1 IE identifier - * 1 1 Treatment bit mask - * - * ACXBeaconFilterEntry (221) - * Byte Offset Size (Bytes) Definition - * =========== ============ ========== - * 0 1 IE identifier - * 1 1 Treatment bit mask - * 2 3 OUI - * 5 1 Type - * 6 2 Version - * - * - * Treatment bit mask - The information element handling: - * bit 0 - The information element is compared and transferred - * in case of change. - * bit 1 - The information element is transferred to the host - * with each appearance or disappearance. - * Note that both bits can be set at the same time. - */ -#define BEACON_FILTER_TABLE_MAX_IE_NUM (32) -#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6) -#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE (2) -#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6) -#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \ - BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \ - (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ - BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) - -struct acx_beacon_filter_ie_table { - struct acx_header header; - - u8 num_ie; - u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; - u8 pad[3]; -} __attribute__ ((packed)); - -enum { - SG_ENABLE = 0, - SG_DISABLE, - SG_SENSE_NO_ACTIVITY, - SG_SENSE_ACTIVE -}; - -struct acx_bt_wlan_coex { - struct acx_header header; - - /* - * 0 -> PTA enabled - * 1 -> PTA disabled - * 2 -> sense no active mode, i.e. - * an interrupt is sent upon - * BT activity. - * 3 -> PTA is switched on in response - * to the interrupt sending. - */ - u8 enable; - u8 pad[3]; -} __attribute__ ((packed)); - -#define PTA_ANTENNA_TYPE_DEF (0) -#define PTA_BT_HP_MAXTIME_DEF (2000) -#define PTA_WLAN_HP_MAX_TIME_DEF (5000) -#define PTA_SENSE_DISABLE_TIMER_DEF (1350) -#define PTA_PROTECTIVE_RX_TIME_DEF (1500) -#define PTA_PROTECTIVE_TX_TIME_DEF (1500) -#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) -#define PTA_SIGNALING_TYPE_DEF (1) -#define PTA_AFH_LEVERAGE_ON_DEF (0) -#define PTA_NUMBER_QUIET_CYCLE_DEF (0) -#define PTA_MAX_NUM_CTS_DEF (3) -#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) -#define PTA_NUMBER_OF_BT_PACKETS_DEF (2) -#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) -#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) -#define PTA_CYCLE_TIME_FAST_DEF (8700) -#define PTA_RX_FOR_AVALANCHE_DEF (5) -#define PTA_ELP_HP_DEF (0) -#define PTA_ANTI_STARVE_PERIOD_DEF (500) -#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) -#define PTA_ALLOW_PA_SD_DEF (1) -#define PTA_TIME_BEFORE_BEACON_DEF (6300) -#define PTA_HPDM_MAX_TIME_DEF (1600) -#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) -#define PTA_AUTO_MODE_NO_CTS_DEF (0) -#define PTA_BT_HP_RESPECTED_DEF (3) -#define PTA_WLAN_RX_MIN_RATE_DEF (24) -#define PTA_ACK_MODE_DEF (1) - -struct acx_bt_wlan_coex_param { - struct acx_header header; - - /* - * The minimum rate of a received WLAN packet in the STA, - * during protective mode, of which a new BT-HP request - * during this Rx will always be respected and gain the antenna. - */ - u32 min_rate; - - /* Max time the BT HP will be respected. */ - u16 bt_hp_max_time; - - /* Max time the WLAN HP will be respected. */ - u16 wlan_hp_max_time; - - /* - * The time between the last BT activity - * and the moment when the sense mode returns - * to SENSE_INACTIVE. - */ - u16 sense_disable_timer; - - /* Time before the next BT HP instance */ - u16 rx_time_bt_hp; - u16 tx_time_bt_hp; - - /* range: 10-20000 default: 1500 */ - u16 rx_time_bt_hp_fast; - u16 tx_time_bt_hp_fast; - - /* range: 2000-65535 default: 8700 */ - u16 wlan_cycle_fast; - - /* range: 0 - 15000 (Msec) default: 1000 */ - u16 bt_anti_starvation_period; - - /* range 400-10000(Usec) default: 3000 */ - u16 next_bt_lp_packet; - - /* Deafult: worst case for BT DH5 traffic */ - u16 wake_up_beacon; - - /* range: 0-50000(Usec) default: 1050 */ - u16 hp_dm_max_guard_time; - - /* - * This is to prevent both BT & WLAN antenna - * starvation. - * Range: 100-50000(Usec) default:2550 - */ - u16 next_wlan_packet; - - /* 0 -> shared antenna */ - u8 antenna_type; - - /* - * 0 -> TI legacy - * 1 -> Palau - */ - u8 signal_type; - - /* - * BT AFH status - * 0 -> no AFH - * 1 -> from dedicated GPIO - * 2 -> AFH on (from host) - */ - u8 afh_leverage_on; - - /* - * The number of cycles during which no - * TX will be sent after 1 cycle of RX - * transaction in protective mode - */ - u8 quiet_cycle_num; - - /* - * The maximum number of CTSs that will - * be sent for receiving RX packet in - * protective mode - */ - u8 max_cts; - - /* - * The number of WLAN packets - * transferred in common mode before - * switching to BT. - */ - u8 wlan_packets_num; - - /* - * The number of BT packets - * transferred in common mode before - * switching to WLAN. - */ - u8 bt_packets_num; - - /* range: 1-255 default: 5 */ - u8 missed_rx_avalanche; - - /* range: 0-1 default: 1 */ - u8 wlan_elp_hp; - - /* range: 0 - 15 default: 4 */ - u8 bt_anti_starvation_cycles; - - u8 ack_mode_dual_ant; - - /* - * Allow PA_SD assertion/de-assertion - * during enabled BT activity. - */ - u8 pa_sd_enable; - - /* - * Enable/Disable PTA in auto mode: - * Support Both Active & P.S modes - */ - u8 pta_auto_mode_enable; - - /* range: 0 - 20 default: 1 */ - u8 bt_hp_respected_num; -} __attribute__ ((packed)); - -#define CCA_THRSH_ENABLE_ENERGY_D 0x140A -#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF - -struct acx_energy_detection { - struct acx_header header; - - /* The RX Clear Channel Assessment threshold in the PHY */ - u16 rx_cca_threshold; - u8 tx_energy_detection; - u8 pad; -} __attribute__ ((packed)); - -#define BCN_RX_TIMEOUT_DEF_VALUE 10000 -#define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000 -#define RX_BROADCAST_IN_PS_DEF_VALUE 1 -#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4 - -struct acx_beacon_broadcast { - struct acx_header header; - - u16 beacon_rx_timeout; - u16 broadcast_timeout; - - /* Enables receiving of broadcast packets in PS mode */ - u8 rx_broadcast_in_ps; - - /* Consecutive PS Poll failures before updating the host */ - u8 ps_poll_threshold; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_event_mask { - struct acx_header header; - - u32 event_mask; - u32 high_event_mask; /* Unused */ -} __attribute__ ((packed)); - -#define CFG_RX_FCS BIT(2) -#define CFG_RX_ALL_GOOD BIT(3) -#define CFG_UNI_FILTER_EN BIT(4) -#define CFG_BSSID_FILTER_EN BIT(5) -#define CFG_MC_FILTER_EN BIT(6) -#define CFG_MC_ADDR0_EN BIT(7) -#define CFG_MC_ADDR1_EN BIT(8) -#define CFG_BC_REJECT_EN BIT(9) -#define CFG_SSID_FILTER_EN BIT(10) -#define CFG_RX_INT_FCS_ERROR BIT(11) -#define CFG_RX_INT_ENCRYPTED BIT(12) -#define CFG_RX_WR_RX_STATUS BIT(13) -#define CFG_RX_FILTER_NULTI BIT(14) -#define CFG_RX_RESERVE BIT(15) -#define CFG_RX_TIMESTAMP_TSF BIT(16) - -#define CFG_RX_RSV_EN BIT(0) -#define CFG_RX_RCTS_ACK BIT(1) -#define CFG_RX_PRSP_EN BIT(2) -#define CFG_RX_PREQ_EN BIT(3) -#define CFG_RX_MGMT_EN BIT(4) -#define CFG_RX_FCS_ERROR BIT(5) -#define CFG_RX_DATA_EN BIT(6) -#define CFG_RX_CTL_EN BIT(7) -#define CFG_RX_CF_EN BIT(8) -#define CFG_RX_BCN_EN BIT(9) -#define CFG_RX_AUTH_EN BIT(10) -#define CFG_RX_ASSOC_EN BIT(11) - -#define SCAN_PASSIVE BIT(0) -#define SCAN_5GHZ_BAND BIT(1) -#define SCAN_TRIGGERED BIT(2) -#define SCAN_PRIORITY_HIGH BIT(3) - -struct acx_fw_gen_frame_rates { - struct acx_header header; - - u8 tx_ctrl_frame_rate; /* RATE_* */ - u8 tx_ctrl_frame_mod; /* CCK_* or PBCC_* */ - u8 tx_mgt_frame_rate; - u8 tx_mgt_frame_mod; -} __attribute__ ((packed)); - -/* STA MAC */ -struct acx_dot11_station_id { - struct acx_header header; - - u8 mac[ETH_ALEN]; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_feature_config { - struct acx_header header; - - u32 options; - u32 data_flow_options; -} __attribute__ ((packed)); - -struct acx_current_tx_power { - struct acx_header header; - - u8 current_tx_power; - u8 padding[3]; -} __attribute__ ((packed)); - -struct acx_dot11_default_key { - struct acx_header header; - - u8 id; - u8 pad[3]; -} __attribute__ ((packed)); - -struct acx_tsf_info { - struct acx_header header; - - u32 current_tsf_msb; - u32 current_tsf_lsb; - u32 last_TBTT_msb; - u32 last_TBTT_lsb; - u8 last_dtim_count; - u8 pad[3]; -} __attribute__ ((packed)); - -enum acx_wake_up_event { - WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ - WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ - WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */ - WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */ - WAKE_UP_EVENT_BITS_MASK = 0x0F -}; - -struct acx_wake_up_condition { - struct acx_header header; - - u8 wake_up_event; /* Only one bit can be set */ - u8 listen_interval; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_aid { - struct acx_header header; - - /* - * To be set when associated with an AP. - */ - u16 aid; - u8 pad[2]; -} __attribute__ ((packed)); - -enum acx_preamble_type { - ACX_PREAMBLE_LONG = 0, - ACX_PREAMBLE_SHORT = 1 -}; - -struct acx_preamble { - struct acx_header header; - - /* - * When set, the WiLink transmits the frames with a short preamble and - * when cleared, the WiLink transmits the frames with a long preamble. - */ - u8 preamble; - u8 padding[3]; -} __attribute__ ((packed)); - -enum acx_ctsprotect_type { - CTSPROTECT_DISABLE = 0, - CTSPROTECT_ENABLE = 1 -}; - -struct acx_ctsprotect { - struct acx_header header; - u8 ctsprotect; - u8 padding[3]; -} __attribute__ ((packed)); - -struct acx_tx_statistics { - u32 internal_desc_overflow; -} __attribute__ ((packed)); - -struct acx_rx_statistics { - u32 out_of_mem; - u32 hdr_overflow; - u32 hw_stuck; - u32 dropped; - u32 fcs_err; - u32 xfr_hint_trig; - u32 path_reset; - u32 reset_counter; -} __attribute__ ((packed)); - -struct acx_dma_statistics { - u32 rx_requested; - u32 rx_errors; - u32 tx_requested; - u32 tx_errors; -} __attribute__ ((packed)); - -struct acx_isr_statistics { - /* host command complete */ - u32 cmd_cmplt; - - /* fiqisr() */ - u32 fiqs; - - /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ - u32 rx_headers; - - /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ - u32 rx_completes; - - /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ - u32 rx_mem_overflow; - - /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ - u32 rx_rdys; - - /* irqisr() */ - u32 irqs; - - /* (INT_STS_ND & INT_TRIG_TX_PROC) */ - u32 tx_procs; - - /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ - u32 decrypt_done; - - /* (INT_STS_ND & INT_TRIG_DMA0) */ - u32 dma0_done; - - /* (INT_STS_ND & INT_TRIG_DMA1) */ - u32 dma1_done; - - /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ - u32 tx_exch_complete; - - /* (INT_STS_ND & INT_TRIG_COMMAND) */ - u32 commands; - - /* (INT_STS_ND & INT_TRIG_RX_PROC) */ - u32 rx_procs; - - /* (INT_STS_ND & INT_TRIG_PM_802) */ - u32 hw_pm_mode_changes; - - /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ - u32 host_acknowledges; - - /* (INT_STS_ND & INT_TRIG_PM_PCI) */ - u32 pci_pm; - - /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ - u32 wakeups; - - /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ - u32 low_rssi; -} __attribute__ ((packed)); - -struct acx_wep_statistics { - /* WEP address keys configured */ - u32 addr_key_count; - - /* default keys configured */ - u32 default_key_count; - - u32 reserved; - - /* number of times that WEP key not found on lookup */ - u32 key_not_found; - - /* number of times that WEP key decryption failed */ - u32 decrypt_fail; - - /* WEP packets decrypted */ - u32 packets; - - /* WEP decrypt interrupts */ - u32 interrupt; -} __attribute__ ((packed)); - -#define ACX_MISSED_BEACONS_SPREAD 10 - -struct acx_pwr_statistics { - /* the amount of enters into power save mode (both PD & ELP) */ - u32 ps_enter; - - /* the amount of enters into ELP mode */ - u32 elp_enter; - - /* the amount of missing beacon interrupts to the host */ - u32 missing_bcns; - - /* the amount of wake on host-access times */ - u32 wake_on_host; - - /* the amount of wake on timer-expire */ - u32 wake_on_timer_exp; - - /* the number of packets that were transmitted with PS bit set */ - u32 tx_with_ps; - - /* the number of packets that were transmitted with PS bit clear */ - u32 tx_without_ps; - - /* the number of received beacons */ - u32 rcvd_beacons; - - /* the number of entering into PowerOn (power save off) */ - u32 power_save_off; - - /* the number of entries into power save mode */ - u16 enable_ps; - - /* - * the number of exits from power save, not including failed PS - * transitions - */ - u16 disable_ps; - - /* - * the number of times the TSF counter was adjusted because - * of drift - */ - u32 fix_tsf_ps; - - /* Gives statistics about the spread continuous missed beacons. - * The 16 LSB are dedicated for the PS mode. - * The 16 MSB are dedicated for the PS mode. - * cont_miss_bcns_spread[0] - single missed beacon. - * cont_miss_bcns_spread[1] - two continuous missed beacons. - * cont_miss_bcns_spread[2] - three continuous missed beacons. - * ... - * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. - */ - u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; - - /* the number of beacons in awake mode */ - u32 rcvd_awake_beacons; -} __attribute__ ((packed)); - -struct acx_mic_statistics { - u32 rx_pkts; - u32 calc_failure; -} __attribute__ ((packed)); - -struct acx_aes_statistics { - u32 encrypt_fail; - u32 decrypt_fail; - u32 encrypt_packets; - u32 decrypt_packets; - u32 encrypt_interrupt; - u32 decrypt_interrupt; -} __attribute__ ((packed)); - -struct acx_event_statistics { - u32 heart_beat; - u32 calibration; - u32 rx_mismatch; - u32 rx_mem_empty; - u32 rx_pool; - u32 oom_late; - u32 phy_transmit_error; - u32 tx_stuck; -} __attribute__ ((packed)); - -struct acx_ps_statistics { - u32 pspoll_timeouts; - u32 upsd_timeouts; - u32 upsd_max_sptime; - u32 upsd_max_apturn; - u32 pspoll_max_apturn; - u32 pspoll_utilization; - u32 upsd_utilization; -} __attribute__ ((packed)); - -struct acx_rxpipe_statistics { - u32 rx_prep_beacon_drop; - u32 descr_host_int_trig_rx_data; - u32 beacon_buffer_thres_host_int_trig_rx_data; - u32 missed_beacon_host_int_trig_rx_data; - u32 tx_xfr_host_int_trig_rx_data; -} __attribute__ ((packed)); - -struct acx_statistics { - struct acx_header header; - - struct acx_tx_statistics tx; - struct acx_rx_statistics rx; - struct acx_dma_statistics dma; - struct acx_isr_statistics isr; - struct acx_wep_statistics wep; - struct acx_pwr_statistics pwr; - struct acx_aes_statistics aes; - struct acx_mic_statistics mic; - struct acx_event_statistics event; - struct acx_ps_statistics ps; - struct acx_rxpipe_statistics rxpipe; -} __attribute__ ((packed)); - -#define ACX_MAX_RATE_CLASSES 8 -#define ACX_RATE_MASK_UNSPECIFIED 0 -#define ACX_RATE_RETRY_LIMIT 10 - -struct acx_rate_class { - u32 enabled_rates; - u8 short_retry_limit; - u8 long_retry_limit; - u8 aflags; - u8 reserved; -}; - -struct acx_rate_policy { - struct acx_header header; - - u32 rate_class_cnt; - struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES]; -} __attribute__ ((packed)); - -struct wl1251_acx_memory { - __le16 num_stations; /* number of STAs to be supported. */ - u16 reserved_1; - - /* - * Nmber of memory buffers for the RX mem pool. - * The actual number may be less if there are - * not enough blocks left for the minimum num - * of TX ones. - */ - u8 rx_mem_block_num; - u8 reserved_2; - u8 num_tx_queues; /* From 1 to 16 */ - u8 host_if_options; /* HOST_IF* */ - u8 tx_min_mem_block_num; - u8 num_ssid_profiles; - __le16 debug_buffer_size; -} __attribute__ ((packed)); - - -#define ACX_RX_DESC_MIN 1 -#define ACX_RX_DESC_MAX 127 -#define ACX_RX_DESC_DEF 32 -struct wl1251_acx_rx_queue_config { - u8 num_descs; - u8 pad; - u8 type; - u8 priority; - __le32 dma_address; -} __attribute__ ((packed)); - -#define ACX_TX_DESC_MIN 1 -#define ACX_TX_DESC_MAX 127 -#define ACX_TX_DESC_DEF 16 -struct wl1251_acx_tx_queue_config { - u8 num_descs; - u8 pad[2]; - u8 attributes; -} __attribute__ ((packed)); - -#define MAX_TX_QUEUE_CONFIGS 5 -#define MAX_TX_QUEUES 4 -struct wl1251_acx_config_memory { - struct acx_header header; - - struct wl1251_acx_memory mem_config; - struct wl1251_acx_rx_queue_config rx_queue_config; - struct wl1251_acx_tx_queue_config tx_queue_config[MAX_TX_QUEUE_CONFIGS]; -} __attribute__ ((packed)); - -struct wl1251_acx_mem_map { - struct acx_header header; - - void *code_start; - void *code_end; - - void *wep_defkey_start; - void *wep_defkey_end; - - void *sta_table_start; - void *sta_table_end; - - void *packet_template_start; - void *packet_template_end; - - void *queue_memory_start; - void *queue_memory_end; - - void *packet_memory_pool_start; - void *packet_memory_pool_end; - - void *debug_buffer1_start; - void *debug_buffer1_end; - - void *debug_buffer2_start; - void *debug_buffer2_end; - - /* Number of blocks FW allocated for TX packets */ - u32 num_tx_mem_blocks; - - /* Number of blocks FW allocated for RX packets */ - u32 num_rx_mem_blocks; -} __attribute__ ((packed)); - -/************************************************************************* - - Host Interrupt Register (WiLink -> Host) - -**************************************************************************/ - -/* RX packet is ready in Xfer buffer #0 */ -#define WL1251_ACX_INTR_RX0_DATA BIT(0) - -/* TX result(s) are in the TX complete buffer */ -#define WL1251_ACX_INTR_TX_RESULT BIT(1) - -/* OBSOLETE */ -#define WL1251_ACX_INTR_TX_XFR BIT(2) - -/* RX packet is ready in Xfer buffer #1 */ -#define WL1251_ACX_INTR_RX1_DATA BIT(3) - -/* Event was entered to Event MBOX #A */ -#define WL1251_ACX_INTR_EVENT_A BIT(4) - -/* Event was entered to Event MBOX #B */ -#define WL1251_ACX_INTR_EVENT_B BIT(5) - -/* OBSOLETE */ -#define WL1251_ACX_INTR_WAKE_ON_HOST BIT(6) - -/* Trace meassge on MBOX #A */ -#define WL1251_ACX_INTR_TRACE_A BIT(7) - -/* Trace meassge on MBOX #B */ -#define WL1251_ACX_INTR_TRACE_B BIT(8) - -/* Command processing completion */ -#define WL1251_ACX_INTR_CMD_COMPLETE BIT(9) - -/* Init sequence is done */ -#define WL1251_ACX_INTR_INIT_COMPLETE BIT(14) - -#define WL1251_ACX_INTR_ALL 0xFFFFFFFF - -enum { - ACX_WAKE_UP_CONDITIONS = 0x0002, - ACX_MEM_CFG = 0x0003, - ACX_SLOT = 0x0004, - ACX_QUEUE_HEAD = 0x0005, /* for MASTER mode only */ - ACX_AC_CFG = 0x0007, - ACX_MEM_MAP = 0x0008, - ACX_AID = 0x000A, - ACX_RADIO_PARAM = 0x000B, /* Not used */ - ACX_CFG = 0x000C, /* Not used */ - ACX_FW_REV = 0x000D, - ACX_MEDIUM_USAGE = 0x000F, - ACX_RX_CFG = 0x0010, - ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ - ACX_BSS_IN_PS = 0x0012, /* for AP only */ - ACX_STATISTICS = 0x0013, /* Debug API */ - ACX_FEATURE_CFG = 0x0015, - ACX_MISC_CFG = 0x0017, /* Not used */ - ACX_TID_CFG = 0x001A, - ACX_BEACON_FILTER_OPT = 0x001F, - ACX_LOW_RSSI = 0x0020, - ACX_NOISE_HIST = 0x0021, - ACX_HDK_VERSION = 0x0022, /* ??? */ - ACX_PD_THRESHOLD = 0x0023, - ACX_DATA_PATH_PARAMS = 0x0024, /* WO */ - ACX_DATA_PATH_RESP_PARAMS = 0x0024, /* RO */ - ACX_CCA_THRESHOLD = 0x0025, - ACX_EVENT_MBOX_MASK = 0x0026, -#ifdef FW_RUNNING_AS_AP - ACX_DTIM_PERIOD = 0x0027, /* for AP only */ -#else - ACX_WR_TBTT_AND_DTIM = 0x0027, /* STA only */ -#endif - ACX_ACI_OPTION_CFG = 0x0029, /* OBSOLETE (for 1251)*/ - ACX_GPIO_CFG = 0x002A, /* Not used */ - ACX_GPIO_SET = 0x002B, /* Not used */ - ACX_PM_CFG = 0x002C, /* To Be Documented */ - ACX_CONN_MONIT_PARAMS = 0x002D, - ACX_AVERAGE_RSSI = 0x002E, /* Not used */ - ACX_CONS_TX_FAILURE = 0x002F, - ACX_BCN_DTIM_OPTIONS = 0x0031, - ACX_SG_ENABLE = 0x0032, - ACX_SG_CFG = 0x0033, - ACX_ANTENNA_DIVERSITY_CFG = 0x0035, /* To Be Documented */ - ACX_LOW_SNR = 0x0037, /* To Be Documented */ - ACX_BEACON_FILTER_TABLE = 0x0038, - ACX_ARP_IP_FILTER = 0x0039, - ACX_ROAMING_STATISTICS_TBL = 0x003B, - ACX_RATE_POLICY = 0x003D, - ACX_CTS_PROTECTION = 0x003E, - ACX_SLEEP_AUTH = 0x003F, - ACX_PREAMBLE_TYPE = 0x0040, - ACX_ERROR_CNT = 0x0041, - ACX_FW_GEN_FRAME_RATES = 0x0042, - ACX_IBSS_FILTER = 0x0044, - ACX_SERVICE_PERIOD_TIMEOUT = 0x0045, - ACX_TSF_INFO = 0x0046, - ACX_CONFIG_PS_WMM = 0x0049, - ACX_ENABLE_RX_DATA_FILTER = 0x004A, - ACX_SET_RX_DATA_FILTER = 0x004B, - ACX_GET_DATA_FILTER_STATISTICS = 0x004C, - ACX_POWER_LEVEL_TABLE = 0x004D, - ACX_BET_ENABLE = 0x0050, - DOT11_STATION_ID = 0x1001, - DOT11_RX_MSDU_LIFE_TIME = 0x1004, - DOT11_CUR_TX_PWR = 0x100D, - DOT11_DEFAULT_KEY = 0x1010, - DOT11_RX_DOT11_MODE = 0x1012, - DOT11_RTS_THRESHOLD = 0x1013, - DOT11_GROUP_ADDRESS_TBL = 0x1014, - - MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, - - MAX_IE = 0xFFFF -}; - - -int wl1251_acx_frame_rates(struct wl1251 *wl, u8 ctrl_rate, u8 ctrl_mod, - u8 mgt_rate, u8 mgt_mod); -int wl1251_acx_station_id(struct wl1251 *wl); -int wl1251_acx_default_key(struct wl1251 *wl, u8 key_id); -int wl1251_acx_wake_up_conditions(struct wl1251 *wl, u8 wake_up_event, - u8 listen_interval); -int wl1251_acx_sleep_auth(struct wl1251 *wl, u8 sleep_auth); -int wl1251_acx_fw_version(struct wl1251 *wl, char *buf, size_t len); -int wl1251_acx_tx_power(struct wl1251 *wl, int power); -int wl1251_acx_feature_cfg(struct wl1251 *wl); -int wl1251_acx_mem_map(struct wl1251 *wl, - struct acx_header *mem_map, size_t len); -int wl1251_acx_data_path_params(struct wl1251 *wl, - struct acx_data_path_params_resp *data_path); -int wl1251_acx_rx_msdu_life_time(struct wl1251 *wl, u32 life_time); -int wl1251_acx_rx_config(struct wl1251 *wl, u32 config, u32 filter); -int wl1251_acx_pd_threshold(struct wl1251 *wl); -int wl1251_acx_slot(struct wl1251 *wl, enum acx_slot_type slot_time); -int wl1251_acx_group_address_tbl(struct wl1251 *wl); -int wl1251_acx_service_period_timeout(struct wl1251 *wl); -int wl1251_acx_rts_threshold(struct wl1251 *wl, u16 rts_threshold); -int wl1251_acx_beacon_filter_opt(struct wl1251 *wl); -int wl1251_acx_beacon_filter_table(struct wl1251 *wl); -int wl1251_acx_sg_enable(struct wl1251 *wl); -int wl1251_acx_sg_cfg(struct wl1251 *wl); -int wl1251_acx_cca_threshold(struct wl1251 *wl); -int wl1251_acx_bcn_dtim_options(struct wl1251 *wl); -int wl1251_acx_aid(struct wl1251 *wl, u16 aid); -int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask); -int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble); -int wl1251_acx_cts_protect(struct wl1251 *wl, - enum acx_ctsprotect_type ctsprotect); -int wl1251_acx_statistics(struct wl1251 *wl, struct acx_statistics *stats); -int wl1251_acx_tsf_info(struct wl1251 *wl, u64 *mactime); -int wl1251_acx_rate_policies(struct wl1251 *wl); -int wl1251_acx_mem_cfg(struct wl1251 *wl); - -#endif /* __WL1251_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.c b/drivers/net/wireless/wl12xx/wl1251_boot.c deleted file mode 100644 index 452d748e42c6..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_boot.c +++ /dev/null @@ -1,530 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include - -#include "wl1251_reg.h" -#include "wl1251_boot.h" -#include "wl1251_io.h" -#include "wl1251_spi.h" -#include "wl1251_event.h" -#include "wl1251_acx.h" - -void wl1251_boot_target_enable_interrupts(struct wl1251 *wl) -{ - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); - wl1251_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL); -} - -int wl1251_boot_soft_reset(struct wl1251 *wl) -{ - unsigned long timeout; - u32 boot_data; - - /* perform soft reset */ - wl1251_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); - - /* SOFT_RESET is self clearing */ - timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); - while (1) { - boot_data = wl1251_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); - wl1251_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); - if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) - break; - - if (time_after(jiffies, timeout)) { - /* 1.2 check pWhalBus->uSelfClearTime if the - * timeout was reached */ - wl1251_error("soft reset timeout"); - return -1; - } - - udelay(SOFT_RESET_STALL_TIME); - } - - /* disable Rx/Tx */ - wl1251_reg_write32(wl, ENABLE, 0x0); - - /* disable auto calibration on start*/ - wl1251_reg_write32(wl, SPARE_A2, 0xffff); - - return 0; -} - -int wl1251_boot_init_seq(struct wl1251 *wl) -{ - u32 scr_pad6, init_data, tmp, elp_cmd, ref_freq; - - /* - * col #1: INTEGER_DIVIDER - * col #2: FRACTIONAL_DIVIDER - * col #3: ATTN_BB - * col #4: ALPHA_BB - * col #5: STOP_TIME_BB - * col #6: BB_PLL_LOOP_FILTER - */ - static const u32 LUT[REF_FREQ_NUM][LUT_PARAM_NUM] = { - - { 83, 87381, 0xB, 5, 0xF00, 3}, /* REF_FREQ_19_2*/ - { 61, 141154, 0xB, 5, 0x1450, 2}, /* REF_FREQ_26_0*/ - { 41, 174763, 0xC, 6, 0x2D00, 1}, /* REF_FREQ_38_4*/ - { 40, 0, 0xC, 6, 0x2EE0, 1}, /* REF_FREQ_40_0*/ - { 47, 162280, 0xC, 6, 0x2760, 1} /* REF_FREQ_33_6 */ - }; - - /* read NVS params */ - scr_pad6 = wl1251_reg_read32(wl, SCR_PAD6); - wl1251_debug(DEBUG_BOOT, "scr_pad6 0x%x", scr_pad6); - - /* read ELP_CMD */ - elp_cmd = wl1251_reg_read32(wl, ELP_CMD); - wl1251_debug(DEBUG_BOOT, "elp_cmd 0x%x", elp_cmd); - - /* set the BB calibration time to be 300 usec (PLL_CAL_TIME) */ - ref_freq = scr_pad6 & 0x000000FF; - wl1251_debug(DEBUG_BOOT, "ref_freq 0x%x", ref_freq); - - wl1251_reg_write32(wl, PLL_CAL_TIME, 0x9); - - /* - * PG 1.2: set the clock buffer time to be 210 usec (CLK_BUF_TIME) - */ - wl1251_reg_write32(wl, CLK_BUF_TIME, 0x6); - - /* - * set the clock detect feature to work in the restart wu procedure - * (ELP_CFG_MODE[14]) and Select the clock source type - * (ELP_CFG_MODE[13:12]) - */ - tmp = ((scr_pad6 & 0x0000FF00) << 4) | 0x00004000; - wl1251_reg_write32(wl, ELP_CFG_MODE, tmp); - - /* PG 1.2: enable the BB PLL fix. Enable the PLL_LIMP_CLK_EN_CMD */ - elp_cmd |= 0x00000040; - wl1251_reg_write32(wl, ELP_CMD, elp_cmd); - - /* PG 1.2: Set the BB PLL stable time to be 1000usec - * (PLL_STABLE_TIME) */ - wl1251_reg_write32(wl, CFG_PLL_SYNC_CNT, 0x20); - - /* PG 1.2: read clock request time */ - init_data = wl1251_reg_read32(wl, CLK_REQ_TIME); - - /* - * PG 1.2: set the clock request time to be ref_clk_settling_time - - * 1ms = 4ms - */ - if (init_data > 0x21) - tmp = init_data - 0x21; - else - tmp = 0; - wl1251_reg_write32(wl, CLK_REQ_TIME, tmp); - - /* set BB PLL configurations in RF AFE */ - wl1251_reg_write32(wl, 0x003058cc, 0x4B5); - - /* set RF_AFE_REG_5 */ - wl1251_reg_write32(wl, 0x003058d4, 0x50); - - /* set RF_AFE_CTRL_REG_2 */ - wl1251_reg_write32(wl, 0x00305948, 0x11c001); - - /* - * change RF PLL and BB PLL divider for VCO clock and adjust VCO - * bais current(RF_AFE_REG_13) - */ - wl1251_reg_write32(wl, 0x003058f4, 0x1e); - - /* set BB PLL configurations */ - tmp = LUT[ref_freq][LUT_PARAM_INTEGER_DIVIDER] | 0x00017000; - wl1251_reg_write32(wl, 0x00305840, tmp); - - /* set fractional divider according to Appendix C-BB PLL - * Calculations - */ - tmp = LUT[ref_freq][LUT_PARAM_FRACTIONAL_DIVIDER]; - wl1251_reg_write32(wl, 0x00305844, tmp); - - /* set the initial data for the sigma delta */ - wl1251_reg_write32(wl, 0x00305848, 0x3039); - - /* - * set the accumulator attenuation value, calibration loop1 - * (alpha), calibration loop2 (beta), calibration loop3 (gamma) and - * the VCO gain - */ - tmp = (LUT[ref_freq][LUT_PARAM_ATTN_BB] << 16) | - (LUT[ref_freq][LUT_PARAM_ALPHA_BB] << 12) | 0x1; - wl1251_reg_write32(wl, 0x00305854, tmp); - - /* - * set the calibration stop time after holdoff time expires and set - * settling time HOLD_OFF_TIME_BB - */ - tmp = LUT[ref_freq][LUT_PARAM_STOP_TIME_BB] | 0x000A0000; - wl1251_reg_write32(wl, 0x00305858, tmp); - - /* - * set BB PLL Loop filter capacitor3- BB_C3[2:0] and set BB PLL - * constant leakage current to linearize PFD to 0uA - - * BB_ILOOPF[7:3] - */ - tmp = LUT[ref_freq][LUT_PARAM_BB_PLL_LOOP_FILTER] | 0x00000030; - wl1251_reg_write32(wl, 0x003058f8, tmp); - - /* - * set regulator output voltage for n divider to - * 1.35-BB_REFDIV[1:0], set charge pump current- BB_CPGAIN[4:2], - * set BB PLL Loop filter capacitor2- BB_C2[7:5], set gain of BB - * PLL auto-call to normal mode- BB_CALGAIN_3DB[8] - */ - wl1251_reg_write32(wl, 0x003058f0, 0x29); - - /* enable restart wakeup sequence (ELP_CMD[0]) */ - wl1251_reg_write32(wl, ELP_CMD, elp_cmd | 0x1); - - /* restart sequence completed */ - udelay(2000); - - return 0; -} - -static void wl1251_boot_set_ecpu_ctrl(struct wl1251 *wl, u32 flag) -{ - u32 cpu_ctrl; - - /* 10.5.0 run the firmware (I) */ - cpu_ctrl = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL); - - /* 10.5.1 run the firmware (II) */ - cpu_ctrl &= ~flag; - wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); -} - -int wl1251_boot_run_firmware(struct wl1251 *wl) -{ - int loop, ret; - u32 chip_id, interrupt; - - wl1251_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); - - chip_id = wl1251_reg_read32(wl, CHIP_ID_B); - - wl1251_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); - - if (chip_id != wl->chip_id) { - wl1251_error("chip id doesn't match after firmware boot"); - return -EIO; - } - - /* wait for init to complete */ - loop = 0; - while (loop++ < INIT_LOOP) { - udelay(INIT_LOOP_DELAY); - interrupt = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - - if (interrupt == 0xffffffff) { - wl1251_error("error reading hardware complete " - "init indication"); - return -EIO; - } - /* check that ACX_INTR_INIT_COMPLETE is enabled */ - else if (interrupt & WL1251_ACX_INTR_INIT_COMPLETE) { - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1251_ACX_INTR_INIT_COMPLETE); - break; - } - } - - if (loop >= INIT_LOOP) { - wl1251_error("timeout waiting for the hardware to " - "complete initialization"); - return -EIO; - } - - /* get hardware config command mail box */ - wl->cmd_box_addr = wl1251_reg_read32(wl, REG_COMMAND_MAILBOX_PTR); - - /* get hardware config event mail box */ - wl->event_box_addr = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); - - /* set the working partition to its "running" mode offset */ - wl1251_set_partition(wl, WL1251_PART_WORK_MEM_START, - WL1251_PART_WORK_MEM_SIZE, - WL1251_PART_WORK_REG_START, - WL1251_PART_WORK_REG_SIZE); - - wl1251_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", - wl->cmd_box_addr, wl->event_box_addr); - - wl1251_acx_fw_version(wl, wl->fw_ver, sizeof(wl->fw_ver)); - - /* - * in case of full asynchronous mode the firmware event must be - * ready to receive event from the command mailbox - */ - - /* enable gpio interrupts */ - wl1251_enable_interrupts(wl); - - /* Enable target's interrupts */ - wl->intr_mask = WL1251_ACX_INTR_RX0_DATA | - WL1251_ACX_INTR_RX1_DATA | - WL1251_ACX_INTR_TX_RESULT | - WL1251_ACX_INTR_EVENT_A | - WL1251_ACX_INTR_EVENT_B | - WL1251_ACX_INTR_INIT_COMPLETE; - wl1251_boot_target_enable_interrupts(wl); - - /* unmask all mbox events */ - wl->event_mask = 0xffffffff; - - ret = wl1251_event_unmask(wl); - if (ret < 0) { - wl1251_error("EVENT mask setting failed"); - return ret; - } - - wl1251_event_mbox_config(wl); - - /* firmware startup completed */ - return 0; -} - -static int wl1251_boot_upload_firmware(struct wl1251 *wl) -{ - int addr, chunk_num, partition_limit; - size_t fw_data_len; - u8 *p; - - /* whal_FwCtrl_LoadFwImageSm() */ - - wl1251_debug(DEBUG_BOOT, "chip id before fw upload: 0x%x", - wl1251_reg_read32(wl, CHIP_ID_B)); - - /* 10.0 check firmware length and set partition */ - fw_data_len = (wl->fw[4] << 24) | (wl->fw[5] << 16) | - (wl->fw[6] << 8) | (wl->fw[7]); - - wl1251_debug(DEBUG_BOOT, "fw_data_len %zu chunk_size %d", fw_data_len, - CHUNK_SIZE); - - if ((fw_data_len % 4) != 0) { - wl1251_error("firmware length not multiple of four"); - return -EIO; - } - - wl1251_set_partition(wl, WL1251_PART_DOWN_MEM_START, - WL1251_PART_DOWN_MEM_SIZE, - WL1251_PART_DOWN_REG_START, - WL1251_PART_DOWN_REG_SIZE); - - /* 10.1 set partition limit and chunk num */ - chunk_num = 0; - partition_limit = WL1251_PART_DOWN_MEM_SIZE; - - while (chunk_num < fw_data_len / CHUNK_SIZE) { - /* 10.2 update partition, if needed */ - addr = WL1251_PART_DOWN_MEM_START + - (chunk_num + 2) * CHUNK_SIZE; - if (addr > partition_limit) { - addr = WL1251_PART_DOWN_MEM_START + - chunk_num * CHUNK_SIZE; - partition_limit = chunk_num * CHUNK_SIZE + - WL1251_PART_DOWN_MEM_SIZE; - wl1251_set_partition(wl, - addr, - WL1251_PART_DOWN_MEM_SIZE, - WL1251_PART_DOWN_REG_START, - WL1251_PART_DOWN_REG_SIZE); - } - - /* 10.3 upload the chunk */ - addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; - p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; - wl1251_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", - p, addr); - wl1251_mem_write(wl, addr, p, CHUNK_SIZE); - - chunk_num++; - } - - /* 10.4 upload the last chunk */ - addr = WL1251_PART_DOWN_MEM_START + chunk_num * CHUNK_SIZE; - p = wl->fw + FW_HDR_SIZE + chunk_num * CHUNK_SIZE; - wl1251_debug(DEBUG_BOOT, "uploading fw last chunk (%zu B) 0x%p to 0x%x", - fw_data_len % CHUNK_SIZE, p, addr); - wl1251_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); - - return 0; -} - -static int wl1251_boot_upload_nvs(struct wl1251 *wl) -{ - size_t nvs_len, nvs_bytes_written, burst_len; - int nvs_start, i; - u32 dest_addr, val; - u8 *nvs_ptr, *nvs; - - nvs = wl->nvs; - if (nvs == NULL) - return -ENODEV; - - nvs_ptr = nvs; - - nvs_len = wl->nvs_len; - nvs_start = wl->fw_len; - - /* - * Layout before the actual NVS tables: - * 1 byte : burst length. - * 2 bytes: destination address. - * n bytes: data to burst copy. - * - * This is ended by a 0 length, then the NVS tables. - */ - - while (nvs_ptr[0]) { - burst_len = nvs_ptr[0]; - dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); - - /* We move our pointer to the data */ - nvs_ptr += 3; - - for (i = 0; i < burst_len; i++) { - val = (nvs_ptr[0] | (nvs_ptr[1] << 8) - | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); - - wl1251_debug(DEBUG_BOOT, - "nvs burst write 0x%x: 0x%x", - dest_addr, val); - wl1251_mem_write32(wl, dest_addr, val); - - nvs_ptr += 4; - dest_addr += 4; - } - } - - /* - * We've reached the first zero length, the first NVS table - * is 7 bytes further. - */ - nvs_ptr += 7; - nvs_len -= nvs_ptr - nvs; - nvs_len = ALIGN(nvs_len, 4); - - /* Now we must set the partition correctly */ - wl1251_set_partition(wl, nvs_start, - WL1251_PART_DOWN_MEM_SIZE, - WL1251_PART_DOWN_REG_START, - WL1251_PART_DOWN_REG_SIZE); - - /* And finally we upload the NVS tables */ - nvs_bytes_written = 0; - while (nvs_bytes_written < nvs_len) { - val = (nvs_ptr[0] | (nvs_ptr[1] << 8) - | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); - - val = cpu_to_le32(val); - - wl1251_debug(DEBUG_BOOT, - "nvs write table 0x%x: 0x%x", - nvs_start, val); - wl1251_mem_write32(wl, nvs_start, val); - - nvs_ptr += 4; - nvs_bytes_written += 4; - nvs_start += 4; - } - - return 0; -} - -int wl1251_boot(struct wl1251 *wl) -{ - int ret = 0, minor_minor_e2_ver; - u32 tmp, boot_data; - - /* halt embedded ARM CPU while loading firmware */ - wl1251_reg_write32(wl, ACX_REG_ECPU_CONTROL, ECPU_CONTROL_HALT); - - ret = wl1251_boot_soft_reset(wl); - if (ret < 0) - goto out; - - /* 2. start processing NVS file */ - ret = wl1251_boot_upload_nvs(wl); - if (ret < 0) - goto out; - - /* write firmware's last address (ie. it's length) to - * ACX_EEPROMLESS_IND_REG */ - wl1251_reg_write32(wl, ACX_EEPROMLESS_IND_REG, wl->fw_len); - - /* 6. read the EEPROM parameters */ - tmp = wl1251_reg_read32(wl, SCR_PAD2); - - /* 7. read bootdata */ - wl->boot_attr.radio_type = (tmp & 0x0000FF00) >> 8; - wl->boot_attr.major = (tmp & 0x00FF0000) >> 16; - tmp = wl1251_reg_read32(wl, SCR_PAD3); - - /* 8. check bootdata and call restart sequence */ - wl->boot_attr.minor = (tmp & 0x00FF0000) >> 16; - minor_minor_e2_ver = (tmp & 0xFF000000) >> 24; - - wl1251_debug(DEBUG_BOOT, "radioType 0x%x majorE2Ver 0x%x " - "minorE2Ver 0x%x minor_minor_e2_ver 0x%x", - wl->boot_attr.radio_type, wl->boot_attr.major, - wl->boot_attr.minor, minor_minor_e2_ver); - - ret = wl1251_boot_init_seq(wl); - if (ret < 0) - goto out; - - /* 9. NVS processing done */ - boot_data = wl1251_reg_read32(wl, ACX_REG_ECPU_CONTROL); - - wl1251_debug(DEBUG_BOOT, "halt boot_data 0x%x", boot_data); - - /* 10. check that ECPU_CONTROL_HALT bits are set in - * pWhalBus->uBootData and start uploading firmware - */ - if ((boot_data & ECPU_CONTROL_HALT) == 0) { - wl1251_error("boot failed, ECPU_CONTROL_HALT not set"); - ret = -EIO; - goto out; - } - - ret = wl1251_boot_upload_firmware(wl); - if (ret < 0) - goto out; - - /* 10.5 start firmware */ - ret = wl1251_boot_run_firmware(wl); - if (ret < 0) - goto out; - -out: - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1251_boot.h b/drivers/net/wireless/wl12xx/wl1251_boot.h deleted file mode 100644 index 90063697e8f2..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_boot.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __BOOT_H__ -#define __BOOT_H__ - -#include "wl1251.h" - -int wl1251_boot_soft_reset(struct wl1251 *wl); -int wl1251_boot_init_seq(struct wl1251 *wl); -int wl1251_boot_run_firmware(struct wl1251 *wl); -void wl1251_boot_target_enable_interrupts(struct wl1251 *wl); -int wl1251_boot(struct wl1251 *wl); - -/* number of times we try to read the INIT interrupt */ -#define INIT_LOOP 20000 - -/* delay between retries */ -#define INIT_LOOP_DELAY 50 - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.c b/drivers/net/wireless/wl12xx/wl1251_cmd.c deleted file mode 100644 index 770f260726bd..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.c +++ /dev/null @@ -1,412 +0,0 @@ -#include "wl1251_cmd.h" - -#include -#include - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_ps.h" -#include "wl1251_acx.h" - -/** - * send command to firmware - * - * @wl: wl struct - * @id: command id - * @buf: buffer containing the command, must work with dma - * @len: length of the buffer - */ -int wl1251_cmd_send(struct wl1251 *wl, u16 id, void *buf, size_t len) -{ - struct wl1251_cmd_header *cmd; - unsigned long timeout; - u32 intr; - int ret = 0; - - cmd = buf; - cmd->id = id; - cmd->status = 0; - - WARN_ON(len % 4 != 0); - - wl1251_mem_write(wl, wl->cmd_box_addr, buf, len); - - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); - - timeout = jiffies + msecs_to_jiffies(WL1251_COMMAND_TIMEOUT); - - intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - while (!(intr & WL1251_ACX_INTR_CMD_COMPLETE)) { - if (time_after(jiffies, timeout)) { - wl1251_error("command complete timeout"); - ret = -ETIMEDOUT; - goto out; - } - - msleep(1); - - intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - } - - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1251_ACX_INTR_CMD_COMPLETE); - -out: - return ret; -} - -/** - * send test command to firmware - * - * @wl: wl struct - * @buf: buffer containing the command, with all headers, must work with dma - * @len: length of the buffer - * @answer: is answer needed - */ -int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer) -{ - int ret; - - wl1251_debug(DEBUG_CMD, "cmd test"); - - ret = wl1251_cmd_send(wl, CMD_TEST, buf, buf_len); - - if (ret < 0) { - wl1251_warning("TEST command failed"); - return ret; - } - - if (answer) { - struct wl1251_command *cmd_answer; - - /* - * The test command got in, we can read the answer. - * The answer would be a wl1251_command, where the - * parameter array contains the actual answer. - */ - wl1251_mem_read(wl, wl->cmd_box_addr, buf, buf_len); - - cmd_answer = buf; - - if (cmd_answer->header.status != CMD_STATUS_SUCCESS) - wl1251_error("TEST command answer error: %d", - cmd_answer->header.status); - } - - return 0; -} - -/** - * read acx from firmware - * - * @wl: wl struct - * @id: acx id - * @buf: buffer for the response, including all headers, must work with dma - * @len: lenght of buf - */ -int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len) -{ - struct acx_header *acx = buf; - int ret; - - wl1251_debug(DEBUG_CMD, "cmd interrogate"); - - acx->id = id; - - /* payload length, does not include any headers */ - acx->len = len - sizeof(*acx); - - ret = wl1251_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); - if (ret < 0) { - wl1251_error("INTERROGATE command failed"); - goto out; - } - - /* the interrogate command got in, we can read the answer */ - wl1251_mem_read(wl, wl->cmd_box_addr, buf, len); - - acx = buf; - if (acx->cmd.status != CMD_STATUS_SUCCESS) - wl1251_error("INTERROGATE command error: %d", - acx->cmd.status); - -out: - return ret; -} - -/** - * write acx value to firmware - * - * @wl: wl struct - * @id: acx id - * @buf: buffer containing acx, including all headers, must work with dma - * @len: length of buf - */ -int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len) -{ - struct acx_header *acx = buf; - int ret; - - wl1251_debug(DEBUG_CMD, "cmd configure"); - - acx->id = id; - - /* payload length, does not include any headers */ - acx->len = len - sizeof(*acx); - - ret = wl1251_cmd_send(wl, CMD_CONFIGURE, acx, len); - if (ret < 0) { - wl1251_warning("CONFIGURE command NOK"); - return ret; - } - - return 0; -} - -int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, - void *bitmap, u16 bitmap_len, u8 bitmap_control) -{ - struct wl1251_cmd_vbm_update *vbm; - int ret; - - wl1251_debug(DEBUG_CMD, "cmd vbm"); - - vbm = kzalloc(sizeof(*vbm), GFP_KERNEL); - if (!vbm) { - ret = -ENOMEM; - goto out; - } - - /* Count and period will be filled by the target */ - vbm->tim.bitmap_ctrl = bitmap_control; - if (bitmap_len > PARTIAL_VBM_MAX) { - wl1251_warning("cmd vbm len is %d B, truncating to %d", - bitmap_len, PARTIAL_VBM_MAX); - bitmap_len = PARTIAL_VBM_MAX; - } - memcpy(vbm->tim.pvb_field, bitmap, bitmap_len); - vbm->tim.identity = identity; - vbm->tim.length = bitmap_len + 3; - - vbm->len = cpu_to_le16(bitmap_len + 5); - - ret = wl1251_cmd_send(wl, CMD_VBM, vbm, sizeof(*vbm)); - if (ret < 0) { - wl1251_error("VBM command failed"); - goto out; - } - -out: - kfree(vbm); - return 0; -} - -int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable) -{ - struct cmd_enabledisable_path *cmd; - int ret; - u16 cmd_rx, cmd_tx; - - wl1251_debug(DEBUG_CMD, "cmd data path"); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->channel = channel; - - if (enable) { - cmd_rx = CMD_ENABLE_RX; - cmd_tx = CMD_ENABLE_TX; - } else { - cmd_rx = CMD_DISABLE_RX; - cmd_tx = CMD_DISABLE_TX; - } - - ret = wl1251_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1251_error("rx %s cmd for channel %d failed", - enable ? "start" : "stop", channel); - goto out; - } - - wl1251_debug(DEBUG_BOOT, "rx %s cmd channel %d", - enable ? "start" : "stop", channel); - - ret = wl1251_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1251_error("tx %s cmd for channel %d failed", - enable ? "start" : "stop", channel); - return ret; - } - - wl1251_debug(DEBUG_BOOT, "tx %s cmd channel %d", - enable ? "start" : "stop", channel); - -out: - kfree(cmd); - return ret; -} - -int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, - u16 beacon_interval, u8 dtim_interval) -{ - struct cmd_join *join; - int ret, i; - u8 *bssid; - - join = kzalloc(sizeof(*join), GFP_KERNEL); - if (!join) { - ret = -ENOMEM; - goto out; - } - - wl1251_debug(DEBUG_CMD, "cmd join%s ch %d %d/%d", - bss_type == BSS_TYPE_IBSS ? " ibss" : "", - channel, beacon_interval, dtim_interval); - - /* Reverse order BSSID */ - bssid = (u8 *) &join->bssid_lsb; - for (i = 0; i < ETH_ALEN; i++) - bssid[i] = wl->bssid[ETH_ALEN - i - 1]; - - join->rx_config_options = wl->rx_config; - join->rx_filter_options = wl->rx_filter; - - /* - * FIXME: disable temporarily all filters because after commit - * 9cef8737 "mac80211: fix managed mode BSSID handling" broke - * association. The filter logic needs to be implemented properly - * and once that is done, this hack can be removed. - */ - join->rx_config_options = 0; - join->rx_filter_options = WL1251_DEFAULT_RX_FILTER; - - join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | - RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; - - join->beacon_interval = beacon_interval; - join->dtim_interval = dtim_interval; - join->bss_type = bss_type; - join->channel = channel; - join->ctrl = JOIN_CMD_CTRL_TX_FLUSH; - - ret = wl1251_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); - if (ret < 0) { - wl1251_error("failed to initiate cmd join"); - goto out; - } - -out: - kfree(join); - return ret; -} - -int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode) -{ - struct wl1251_cmd_ps_params *ps_params = NULL; - int ret = 0; - - wl1251_debug(DEBUG_CMD, "cmd set ps mode"); - - ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); - if (!ps_params) { - ret = -ENOMEM; - goto out; - } - - ps_params->ps_mode = ps_mode; - ps_params->send_null_data = 1; - ps_params->retries = 5; - ps_params->hang_over_period = 128; - ps_params->null_data_rate = 1; /* 1 Mbps */ - - ret = wl1251_cmd_send(wl, CMD_SET_PS_MODE, ps_params, - sizeof(*ps_params)); - if (ret < 0) { - wl1251_error("cmd set_ps_mode failed"); - goto out; - } - -out: - kfree(ps_params); - return ret; -} - -int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, - size_t len) -{ - struct cmd_read_write_memory *cmd; - int ret = 0; - - wl1251_debug(DEBUG_CMD, "cmd read memory"); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - WARN_ON(len > MAX_READ_SIZE); - len = min_t(size_t, len, MAX_READ_SIZE); - - cmd->addr = addr; - cmd->size = len; - - ret = wl1251_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1251_error("read memory command failed: %d", ret); - goto out; - } - - /* the read command got in, we can now read the answer */ - wl1251_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); - - if (cmd->header.status != CMD_STATUS_SUCCESS) - wl1251_error("error in read command result: %d", - cmd->header.status); - - memcpy(answer, cmd->value, len); - -out: - kfree(cmd); - return ret; -} - -int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, - void *buf, size_t buf_len) -{ - struct wl1251_cmd_packet_template *cmd; - size_t cmd_len; - int ret = 0; - - wl1251_debug(DEBUG_CMD, "cmd template %d", cmd_id); - - WARN_ON(buf_len > WL1251_MAX_TEMPLATE_SIZE); - buf_len = min_t(size_t, buf_len, WL1251_MAX_TEMPLATE_SIZE); - cmd_len = ALIGN(sizeof(*cmd) + buf_len, 4); - - cmd = kzalloc(cmd_len, GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->size = cpu_to_le16(buf_len); - - if (buf) - memcpy(cmd->data, buf, buf_len); - - ret = wl1251_cmd_send(wl, cmd_id, cmd, cmd_len); - if (ret < 0) { - wl1251_warning("cmd set_template failed: %d", ret); - goto out; - } - -out: - kfree(cmd); - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1251_cmd.h b/drivers/net/wireless/wl12xx/wl1251_cmd.h deleted file mode 100644 index dff798ad0ef5..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_cmd.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_CMD_H__ -#define __WL1251_CMD_H__ - -#include "wl1251.h" - -struct acx_header; - -int wl1251_cmd_send(struct wl1251 *wl, u16 type, void *buf, size_t buf_len); -int wl1251_cmd_test(struct wl1251 *wl, void *buf, size_t buf_len, u8 answer); -int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len); -int wl1251_cmd_configure(struct wl1251 *wl, u16 id, void *buf, size_t len); -int wl1251_cmd_vbm(struct wl1251 *wl, u8 identity, - void *bitmap, u16 bitmap_len, u8 bitmap_control); -int wl1251_cmd_data_path(struct wl1251 *wl, u8 channel, bool enable); -int wl1251_cmd_join(struct wl1251 *wl, u8 bss_type, u8 channel, - u16 beacon_interval, u8 dtim_interval); -int wl1251_cmd_ps_mode(struct wl1251 *wl, u8 ps_mode); -int wl1251_cmd_read_memory(struct wl1251 *wl, u32 addr, void *answer, - size_t len); -int wl1251_cmd_template_set(struct wl1251 *wl, u16 cmd_id, - void *buf, size_t buf_len); - -/* unit ms */ -#define WL1251_COMMAND_TIMEOUT 2000 - -enum wl1251_commands { - CMD_RESET = 0, - CMD_INTERROGATE = 1, /*use this to read information elements*/ - CMD_CONFIGURE = 2, /*use this to write information elements*/ - CMD_ENABLE_RX = 3, - CMD_ENABLE_TX = 4, - CMD_DISABLE_RX = 5, - CMD_DISABLE_TX = 6, - CMD_SCAN = 8, - CMD_STOP_SCAN = 9, - CMD_VBM = 10, - CMD_START_JOIN = 11, - CMD_SET_KEYS = 12, - CMD_READ_MEMORY = 13, - CMD_WRITE_MEMORY = 14, - CMD_BEACON = 19, - CMD_PROBE_RESP = 20, - CMD_NULL_DATA = 21, - CMD_PROBE_REQ = 22, - CMD_TEST = 23, - CMD_RADIO_CALIBRATE = 25, /* OBSOLETE */ - CMD_ENABLE_RX_PATH = 27, /* OBSOLETE */ - CMD_NOISE_HIST = 28, - CMD_RX_RESET = 29, - CMD_PS_POLL = 30, - CMD_QOS_NULL_DATA = 31, - CMD_LNA_CONTROL = 32, - CMD_SET_BCN_MODE = 33, - CMD_MEASUREMENT = 34, - CMD_STOP_MEASUREMENT = 35, - CMD_DISCONNECT = 36, - CMD_SET_PS_MODE = 37, - CMD_CHANNEL_SWITCH = 38, - CMD_STOP_CHANNEL_SWICTH = 39, - CMD_AP_DISCOVERY = 40, - CMD_STOP_AP_DISCOVERY = 41, - CMD_SPS_SCAN = 42, - CMD_STOP_SPS_SCAN = 43, - CMD_HEALTH_CHECK = 45, - CMD_DEBUG = 46, - CMD_TRIGGER_SCAN_TO = 47, - - NUM_COMMANDS, - MAX_COMMAND_ID = 0xFFFF, -}; - -#define MAX_CMD_PARAMS 572 - -struct wl1251_cmd_header { - u16 id; - u16 status; - /* payload */ - u8 data[0]; -} __attribute__ ((packed)); - -struct wl1251_command { - struct wl1251_cmd_header header; - u8 parameters[MAX_CMD_PARAMS]; -}; - -enum { - CMD_MAILBOX_IDLE = 0, - CMD_STATUS_SUCCESS = 1, - CMD_STATUS_UNKNOWN_CMD = 2, - CMD_STATUS_UNKNOWN_IE = 3, - CMD_STATUS_REJECT_MEAS_SG_ACTIVE = 11, - CMD_STATUS_RX_BUSY = 13, - CMD_STATUS_INVALID_PARAM = 14, - CMD_STATUS_TEMPLATE_TOO_LARGE = 15, - CMD_STATUS_OUT_OF_MEMORY = 16, - CMD_STATUS_STA_TABLE_FULL = 17, - CMD_STATUS_RADIO_ERROR = 18, - CMD_STATUS_WRONG_NESTING = 19, - CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ - CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ - MAX_COMMAND_STATUS = 0xff -}; - - -/* - * CMD_READ_MEMORY - * - * The host issues this command to read the WiLink device memory/registers. - * - * Note: The Base Band address has special handling (16 bits registers and - * addresses). For more information, see the hardware specification. - */ -/* - * CMD_WRITE_MEMORY - * - * The host issues this command to write the WiLink device memory/registers. - * - * The Base Band address has special handling (16 bits registers and - * addresses). For more information, see the hardware specification. - */ -#define MAX_READ_SIZE 256 - -struct cmd_read_write_memory { - struct wl1251_cmd_header header; - - /* The address of the memory to read from or write to.*/ - u32 addr; - - /* The amount of data in bytes to read from or write to the WiLink - * device.*/ - u32 size; - - /* The actual value read from or written to the Wilink. The source - of this field is the Host in WRITE command or the Wilink in READ - command. */ - u8 value[MAX_READ_SIZE]; -}; - -#define CMDMBOX_HEADER_LEN 4 -#define CMDMBOX_INFO_ELEM_HEADER_LEN 4 - - -struct basic_scan_parameters { - u32 rx_config_options; - u32 rx_filter_options; - - /* - * Scan options: - * bit 0: When this bit is set, passive scan. - * bit 1: Band, when this bit is set we scan - * in the 5Ghz band. - * bit 2: voice mode, 0 for normal scan. - * bit 3: scan priority, 1 for high priority. - */ - u16 scan_options; - - /* Number of channels to scan */ - u8 num_channels; - - /* Number opf probe requests to send, per channel */ - u8 num_probe_requests; - - /* Rate and modulation for probe requests */ - u16 tx_rate; - - u8 tid_trigger; - u8 ssid_len; - u32 ssid[8]; - -} __attribute__ ((packed)); - -struct basic_scan_channel_parameters { - u32 min_duration; /* in TU */ - u32 max_duration; /* in TU */ - u32 bssid_lsb; - u16 bssid_msb; - - /* - * bits 0-3: Early termination count. - * bits 4-5: Early termination condition. - */ - u8 early_termination; - - u8 tx_power_att; - u8 channel; - u8 pad[3]; -} __attribute__ ((packed)); - -/* SCAN parameters */ -#define SCAN_MAX_NUM_OF_CHANNELS 16 - -struct cmd_scan { - struct wl1251_cmd_header header; - - struct basic_scan_parameters params; - struct basic_scan_channel_parameters channels[SCAN_MAX_NUM_OF_CHANNELS]; -} __attribute__ ((packed)); - -enum { - BSS_TYPE_IBSS = 0, - BSS_TYPE_STA_BSS = 2, - BSS_TYPE_AP_BSS = 3, - MAX_BSS_TYPE = 0xFF -}; - -#define JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ -#define JOIN_CMD_CTRL_EARLY_WAKEUP_ENABLE 0x01 /* Early wakeup time */ - - -struct cmd_join { - struct wl1251_cmd_header header; - - u32 bssid_lsb; - u16 bssid_msb; - u16 beacon_interval; /* in TBTTs */ - u32 rx_config_options; - u32 rx_filter_options; - - /* - * The target uses this field to determine the rate at - * which to transmit control frame responses (such as - * ACK or CTS frames). - */ - u16 basic_rate_set; - u8 dtim_interval; - u8 tx_ctrl_frame_rate; /* OBSOLETE */ - u8 tx_ctrl_frame_mod; /* OBSOLETE */ - /* - * bits 0-2: This bitwise field specifies the type - * of BSS to start or join (BSS_TYPE_*). - * bit 4: Band - The radio band in which to join - * or start. - * 0 - 2.4GHz band - * 1 - 5GHz band - * bits 3, 5-7: Reserved - */ - u8 bss_type; - u8 channel; - u8 ssid_len; - u8 ssid[IW_ESSID_MAX_SIZE]; - u8 ctrl; /* JOIN_CMD_CTRL_* */ - u8 tx_mgt_frame_rate; /* OBSOLETE */ - u8 tx_mgt_frame_mod; /* OBSOLETE */ - u8 reserved; -} __attribute__ ((packed)); - -struct cmd_enabledisable_path { - struct wl1251_cmd_header header; - - u8 channel; - u8 padding[3]; -} __attribute__ ((packed)); - -#define WL1251_MAX_TEMPLATE_SIZE 300 - -struct wl1251_cmd_packet_template { - struct wl1251_cmd_header header; - - __le16 size; - u8 data[0]; -} __attribute__ ((packed)); - -#define TIM_ELE_ID 5 -#define PARTIAL_VBM_MAX 251 - -struct wl1251_tim { - u8 identity; - u8 length; - u8 dtim_count; - u8 dtim_period; - u8 bitmap_ctrl; - u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ -} __attribute__ ((packed)); - -/* Virtual Bit Map update */ -struct wl1251_cmd_vbm_update { - struct wl1251_cmd_header header; - __le16 len; - u8 padding[2]; - struct wl1251_tim tim; -} __attribute__ ((packed)); - -enum wl1251_cmd_ps_mode { - STATION_ACTIVE_MODE, - STATION_POWER_SAVE_MODE -}; - -struct wl1251_cmd_ps_params { - struct wl1251_cmd_header header; - - u8 ps_mode; /* STATION_* */ - u8 send_null_data; /* Do we have to send NULL data packet ? */ - u8 retries; /* Number of retires for the initial NULL data packet */ - - /* - * TUs during which the target stays awake after switching - * to power save mode. - */ - u8 hang_over_period; - u16 null_data_rate; - u8 pad[2]; -} __attribute__ ((packed)); - -struct wl1251_cmd_trigger_scan_to { - struct wl1251_cmd_header header; - - u32 timeout; -}; - -/* HW encryption keys */ -#define NUM_ACCESS_CATEGORIES_COPY 4 -#define MAX_KEY_SIZE 32 - -/* When set, disable HW encryption */ -#define DF_ENCRYPTION_DISABLE 0x01 -/* When set, disable HW decryption */ -#define DF_SNIFF_MODE_ENABLE 0x80 - -enum wl1251_cmd_key_action { - KEY_ADD_OR_REPLACE = 1, - KEY_REMOVE = 2, - KEY_SET_ID = 3, - MAX_KEY_ACTION = 0xffff, -}; - -enum wl1251_cmd_key_type { - KEY_WEP_DEFAULT = 0, - KEY_WEP_ADDR = 1, - KEY_AES_GROUP = 4, - KEY_AES_PAIRWISE = 5, - KEY_WEP_GROUP = 6, - KEY_TKIP_MIC_GROUP = 10, - KEY_TKIP_MIC_PAIRWISE = 11, -}; - -/* - * - * key_type_e key size key format - * ---------- --------- ---------- - * 0x00 5, 13, 29 Key data - * 0x01 5, 13, 29 Key data - * 0x04 16 16 bytes of key data - * 0x05 16 16 bytes of key data - * 0x0a 32 16 bytes of TKIP key data - * 8 bytes of RX MIC key data - * 8 bytes of TX MIC key data - * 0x0b 32 16 bytes of TKIP key data - * 8 bytes of RX MIC key data - * 8 bytes of TX MIC key data - * - */ - -struct wl1251_cmd_set_keys { - struct wl1251_cmd_header header; - - /* Ignored for default WEP key */ - u8 addr[ETH_ALEN]; - - /* key_action_e */ - u16 key_action; - - u16 reserved_1; - - /* key size in bytes */ - u8 key_size; - - /* key_type_e */ - u8 key_type; - u8 ssid_profile; - - /* - * TKIP, AES: frame's key id field. - * For WEP default key: key id; - */ - u8 id; - u8 reserved_2[6]; - u8 key[MAX_KEY_SIZE]; - u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; - u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; -} __attribute__ ((packed)); - - -#endif /* __WL1251_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.c b/drivers/net/wireless/wl12xx/wl1251_debugfs.c deleted file mode 100644 index 1685c09c8589..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.c +++ /dev/null @@ -1,519 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1251_debugfs.h" - -#include - -#include "wl1251.h" -#include "wl1251_acx.h" -#include "wl1251_ps.h" - -/* ms */ -#define WL1251_DEBUGFS_STATS_LIFETIME 1000 - -/* debugfs macros idea from mac80211 */ - -#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ -static ssize_t name## _read(struct file *file, char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1251 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - res = scnprintf(buf, buflen, fmt "\n", ##value); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} \ - \ -static const struct file_operations name## _ops = { \ - .read = name## _read, \ - .open = wl1251_open_file_generic, \ -}; - -#define DEBUGFS_ADD(name, parent) \ - wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ - wl, &name## _ops); \ - if (IS_ERR(wl->debugfs.name)) { \ - ret = PTR_ERR(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - goto out; \ - } - -#define DEBUGFS_DEL(name) \ - do { \ - debugfs_remove(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - } while (0) - -#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ -static ssize_t sub## _ ##name## _read(struct file *file, \ - char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1251 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - wl1251_debugfs_update_stats(wl); \ - \ - res = scnprintf(buf, buflen, fmt "\n", \ - wl->stats.fw_stats->sub.name); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} \ - \ -static const struct file_operations sub## _ ##name## _ops = { \ - .read = sub## _ ##name## _read, \ - .open = wl1251_open_file_generic, \ -}; - -#define DEBUGFS_FWSTATS_ADD(sub, name) \ - DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) - -#define DEBUGFS_FWSTATS_DEL(sub, name) \ - DEBUGFS_DEL(sub## _ ##name) - -static void wl1251_debugfs_update_stats(struct wl1251 *wl) -{ - int ret; - - mutex_lock(&wl->mutex); - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - if (wl->state == WL1251_STATE_ON && - time_after(jiffies, wl->stats.fw_stats_update + - msecs_to_jiffies(WL1251_DEBUGFS_STATS_LIFETIME))) { - wl1251_acx_statistics(wl, wl->stats.fw_stats); - wl->stats.fw_stats_update = jiffies; - } - - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -static int wl1251_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); -/* skipping wep.reserved */ -DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); -/* skipping cont_miss_bcns_spread for now */ -DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, - 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); - -DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); -DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", - wl->stats.excessive_retries); - -static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct wl1251 *wl = file->private_data; - u32 queue_len; - char buf[20]; - int res; - - queue_len = skb_queue_len(&wl->tx_queue); - - res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); - return simple_read_from_buffer(userbuf, count, ppos, buf, res); -} - -static const struct file_operations tx_queue_len_ops = { - .read = tx_queue_len_read, - .open = wl1251_open_file_generic, -}; - -static void wl1251_debugfs_delete_files(struct wl1251 *wl) -{ - DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_DEL(rx, out_of_mem); - DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); - DEBUGFS_FWSTATS_DEL(rx, hw_stuck); - DEBUGFS_FWSTATS_DEL(rx, dropped); - DEBUGFS_FWSTATS_DEL(rx, fcs_err); - DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_DEL(rx, path_reset); - DEBUGFS_FWSTATS_DEL(rx, reset_counter); - - DEBUGFS_FWSTATS_DEL(dma, rx_requested); - DEBUGFS_FWSTATS_DEL(dma, rx_errors); - DEBUGFS_FWSTATS_DEL(dma, tx_requested); - DEBUGFS_FWSTATS_DEL(dma, tx_errors); - - DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); - DEBUGFS_FWSTATS_DEL(isr, fiqs); - DEBUGFS_FWSTATS_DEL(isr, rx_headers); - DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_DEL(isr, rx_rdys); - DEBUGFS_FWSTATS_DEL(isr, irqs); - DEBUGFS_FWSTATS_DEL(isr, tx_procs); - DEBUGFS_FWSTATS_DEL(isr, decrypt_done); - DEBUGFS_FWSTATS_DEL(isr, dma0_done); - DEBUGFS_FWSTATS_DEL(isr, dma1_done); - DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); - DEBUGFS_FWSTATS_DEL(isr, commands); - DEBUGFS_FWSTATS_DEL(isr, rx_procs); - DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); - DEBUGFS_FWSTATS_DEL(isr, pci_pm); - DEBUGFS_FWSTATS_DEL(isr, wakeups); - DEBUGFS_FWSTATS_DEL(isr, low_rssi); - - DEBUGFS_FWSTATS_DEL(wep, addr_key_count); - DEBUGFS_FWSTATS_DEL(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_DEL(wep, key_not_found); - DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); - DEBUGFS_FWSTATS_DEL(wep, packets); - DEBUGFS_FWSTATS_DEL(wep, interrupt); - - DEBUGFS_FWSTATS_DEL(pwr, ps_enter); - DEBUGFS_FWSTATS_DEL(pwr, elp_enter); - DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); - DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); - DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); - DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); - DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_DEL(pwr, power_save_off); - DEBUGFS_FWSTATS_DEL(pwr, enable_ps); - DEBUGFS_FWSTATS_DEL(pwr, disable_ps); - DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_DEL(mic, rx_pkts); - DEBUGFS_FWSTATS_DEL(mic, calc_failure); - - DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); - DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); - DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); - DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); - DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_DEL(event, heart_beat); - DEBUGFS_FWSTATS_DEL(event, calibration); - DEBUGFS_FWSTATS_DEL(event, rx_mismatch); - DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); - DEBUGFS_FWSTATS_DEL(event, rx_pool); - DEBUGFS_FWSTATS_DEL(event, oom_late); - DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); - DEBUGFS_FWSTATS_DEL(event, tx_stuck); - - DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); - DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); - DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); - - DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); - - DEBUGFS_DEL(tx_queue_len); - DEBUGFS_DEL(retry_count); - DEBUGFS_DEL(excessive_retries); -} - -static int wl1251_debugfs_add_files(struct wl1251 *wl) -{ - int ret = 0; - - DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_ADD(rx, out_of_mem); - DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); - DEBUGFS_FWSTATS_ADD(rx, hw_stuck); - DEBUGFS_FWSTATS_ADD(rx, dropped); - DEBUGFS_FWSTATS_ADD(rx, fcs_err); - DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_ADD(rx, path_reset); - DEBUGFS_FWSTATS_ADD(rx, reset_counter); - - DEBUGFS_FWSTATS_ADD(dma, rx_requested); - DEBUGFS_FWSTATS_ADD(dma, rx_errors); - DEBUGFS_FWSTATS_ADD(dma, tx_requested); - DEBUGFS_FWSTATS_ADD(dma, tx_errors); - - DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); - DEBUGFS_FWSTATS_ADD(isr, fiqs); - DEBUGFS_FWSTATS_ADD(isr, rx_headers); - DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_ADD(isr, rx_rdys); - DEBUGFS_FWSTATS_ADD(isr, irqs); - DEBUGFS_FWSTATS_ADD(isr, tx_procs); - DEBUGFS_FWSTATS_ADD(isr, decrypt_done); - DEBUGFS_FWSTATS_ADD(isr, dma0_done); - DEBUGFS_FWSTATS_ADD(isr, dma1_done); - DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); - DEBUGFS_FWSTATS_ADD(isr, commands); - DEBUGFS_FWSTATS_ADD(isr, rx_procs); - DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); - DEBUGFS_FWSTATS_ADD(isr, pci_pm); - DEBUGFS_FWSTATS_ADD(isr, wakeups); - DEBUGFS_FWSTATS_ADD(isr, low_rssi); - - DEBUGFS_FWSTATS_ADD(wep, addr_key_count); - DEBUGFS_FWSTATS_ADD(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_ADD(wep, key_not_found); - DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); - DEBUGFS_FWSTATS_ADD(wep, packets); - DEBUGFS_FWSTATS_ADD(wep, interrupt); - - DEBUGFS_FWSTATS_ADD(pwr, ps_enter); - DEBUGFS_FWSTATS_ADD(pwr, elp_enter); - DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); - DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); - DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_ADD(pwr, power_save_off); - DEBUGFS_FWSTATS_ADD(pwr, enable_ps); - DEBUGFS_FWSTATS_ADD(pwr, disable_ps); - DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_ADD(mic, rx_pkts); - DEBUGFS_FWSTATS_ADD(mic, calc_failure); - - DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_ADD(event, heart_beat); - DEBUGFS_FWSTATS_ADD(event, calibration); - DEBUGFS_FWSTATS_ADD(event, rx_mismatch); - DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); - DEBUGFS_FWSTATS_ADD(event, rx_pool); - DEBUGFS_FWSTATS_ADD(event, oom_late); - DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); - DEBUGFS_FWSTATS_ADD(event, tx_stuck); - - DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); - DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); - - DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); - - DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); - DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); - DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); - -out: - if (ret < 0) - wl1251_debugfs_delete_files(wl); - - return ret; -} - -void wl1251_debugfs_reset(struct wl1251 *wl) -{ - if (wl->stats.fw_stats != NULL) - memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); - wl->stats.retry_count = 0; - wl->stats.excessive_retries = 0; -} - -int wl1251_debugfs_init(struct wl1251 *wl) -{ - int ret; - - wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - - if (IS_ERR(wl->debugfs.rootdir)) { - ret = PTR_ERR(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - goto err; - } - - wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", - wl->debugfs.rootdir); - - if (IS_ERR(wl->debugfs.fw_statistics)) { - ret = PTR_ERR(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - goto err_root; - } - - wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), - GFP_KERNEL); - - if (!wl->stats.fw_stats) { - ret = -ENOMEM; - goto err_fw; - } - - wl->stats.fw_stats_update = jiffies; - - ret = wl1251_debugfs_add_files(wl); - - if (ret < 0) - goto err_file; - - return 0; - -err_file: - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - -err_fw: - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - -err_root: - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -err: - return ret; -} - -void wl1251_debugfs_exit(struct wl1251 *wl) -{ - wl1251_debugfs_delete_files(wl); - - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -} diff --git a/drivers/net/wireless/wl12xx/wl1251_debugfs.h b/drivers/net/wireless/wl12xx/wl1251_debugfs.h deleted file mode 100644 index 6dc3d080853c..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_debugfs.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef WL1251_DEBUGFS_H -#define WL1251_DEBUGFS_H - -#include "wl1251.h" - -int wl1251_debugfs_init(struct wl1251 *wl); -void wl1251_debugfs_exit(struct wl1251 *wl); -void wl1251_debugfs_reset(struct wl1251 *wl); - -#endif /* WL1251_DEBUGFS_H */ diff --git a/drivers/net/wireless/wl12xx/wl1251_event.c b/drivers/net/wireless/wl12xx/wl1251_event.c deleted file mode 100644 index 00076c4a8a21..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_event.c +++ /dev/null @@ -1,128 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_event.h" -#include "wl1251_ps.h" - -static int wl1251_event_scan_complete(struct wl1251 *wl, - struct event_mailbox *mbox) -{ - wl1251_debug(DEBUG_EVENT, "status: 0x%x, channels: %d", - mbox->scheduled_scan_status, - mbox->scheduled_scan_channels); - - if (wl->scanning) { - mutex_unlock(&wl->mutex); - ieee80211_scan_completed(wl->hw, false); - mutex_lock(&wl->mutex); - wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan completed"); - wl->scanning = false; - } - - return 0; -} - -static void wl1251_event_mbox_dump(struct event_mailbox *mbox) -{ - wl1251_debug(DEBUG_EVENT, "MBOX DUMP:"); - wl1251_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); - wl1251_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); -} - -static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox) -{ - int ret; - u32 vector; - - wl1251_event_mbox_dump(mbox); - - vector = mbox->events_vector & ~(mbox->events_mask); - wl1251_debug(DEBUG_EVENT, "vector: 0x%x", vector); - - if (vector & SCAN_COMPLETE_EVENT_ID) { - ret = wl1251_event_scan_complete(wl, mbox); - if (ret < 0) - return ret; - } - - if (vector & BSS_LOSE_EVENT_ID) { - wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); - - if (wl->psm_requested && wl->psm) { - ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - return ret; - } - } - - return 0; -} - -int wl1251_event_unmask(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_event_mbox_mask(wl, ~(wl->event_mask)); - if (ret < 0) - return ret; - - return 0; -} - -void wl1251_event_mbox_config(struct wl1251 *wl) -{ - wl->mbox_ptr[0] = wl1251_reg_read32(wl, REG_EVENT_MAILBOX_PTR); - wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); - - wl1251_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", - wl->mbox_ptr[0], wl->mbox_ptr[1]); -} - -int wl1251_event_handle(struct wl1251 *wl, u8 mbox_num) -{ - struct event_mailbox mbox; - int ret; - - wl1251_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); - - if (mbox_num > 1) - return -EINVAL; - - /* first we read the mbox descriptor */ - wl1251_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, - sizeof(struct event_mailbox)); - - /* process the descriptor */ - ret = wl1251_event_process(wl, &mbox); - if (ret < 0) - return ret; - - /* then we let the firmware know it can go on...*/ - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); - - return 0; -} diff --git a/drivers/net/wireless/wl12xx/wl1251_event.h b/drivers/net/wireless/wl12xx/wl1251_event.h deleted file mode 100644 index be0ac54d6246..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_event.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_EVENT_H__ -#define __WL1251_EVENT_H__ - -/* - * Mbox events - * - * The event mechanism is based on a pair of event buffers (buffers A and - * B) at fixed locations in the target's memory. The host processes one - * buffer while the other buffer continues to collect events. If the host - * is not processing events, an interrupt is issued to signal that a buffer - * is ready. Once the host is done with processing events from one buffer, - * it signals the target (with an ACK interrupt) that the event buffer is - * free. - */ - -enum { - RESERVED1_EVENT_ID = BIT(0), - RESERVED2_EVENT_ID = BIT(1), - MEASUREMENT_START_EVENT_ID = BIT(2), - SCAN_COMPLETE_EVENT_ID = BIT(3), - CALIBRATION_COMPLETE_EVENT_ID = BIT(4), - ROAMING_TRIGGER_LOW_RSSI_EVENT_ID = BIT(5), - PS_REPORT_EVENT_ID = BIT(6), - SYNCHRONIZATION_TIMEOUT_EVENT_ID = BIT(7), - HEALTH_REPORT_EVENT_ID = BIT(8), - ACI_DETECTION_EVENT_ID = BIT(9), - DEBUG_REPORT_EVENT_ID = BIT(10), - MAC_STATUS_EVENT_ID = BIT(11), - DISCONNECT_EVENT_COMPLETE_ID = BIT(12), - JOIN_EVENT_COMPLETE_ID = BIT(13), - CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(14), - BSS_LOSE_EVENT_ID = BIT(15), - ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(16), - MEASUREMENT_COMPLETE_EVENT_ID = BIT(17), - AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(18), - SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(19), - PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(20), - RESET_BSS_EVENT_ID = BIT(21), - REGAINED_BSS_EVENT_ID = BIT(22), - ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID = BIT(23), - ROAMING_TRIGGER_LOW_SNR_EVENT_ID = BIT(24), - ROAMING_TRIGGER_REGAINED_SNR_EVENT_ID = BIT(25), - - DBG_EVENT_ID = BIT(26), - BT_PTA_SENSE_EVENT_ID = BIT(27), - BT_PTA_PREDICTION_EVENT_ID = BIT(28), - BT_PTA_AVALANCHE_EVENT_ID = BIT(29), - - PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(30), - - EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, -}; - -struct event_debug_report { - u8 debug_event_id; - u8 num_params; - u16 pad; - u32 report_1; - u32 report_2; - u32 report_3; -} __attribute__ ((packed)); - -struct event_mailbox { - u32 events_vector; - u32 events_mask; - u32 reserved_1; - u32 reserved_2; - - char average_rssi_level; - u8 ps_status; - u8 channel_switch_status; - u8 scheduled_scan_status; - - /* Channels scanned by the scheduled scan */ - u16 scheduled_scan_channels; - - /* If bit 0 is set -> target's fatal error */ - u16 health_report; - u16 bad_fft_counter; - u8 bt_pta_sense_info; - u8 bt_pta_protective_info; - u32 reserved; - u32 debug_report[2]; - - /* Number of FCS errors since last event */ - u32 fcs_err_counter; - - struct event_debug_report report; - u8 average_snr_level; - u8 padding[19]; -} __attribute__ ((packed)); - -int wl1251_event_unmask(struct wl1251 *wl); -void wl1251_event_mbox_config(struct wl1251 *wl); -int wl1251_event_handle(struct wl1251 *wl, u8 mbox); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_init.c b/drivers/net/wireless/wl12xx/wl1251_init.c deleted file mode 100644 index b2ee4f468fc4..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_init.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - -#include "wl1251_init.h" -#include "wl12xx_80211.h" -#include "wl1251_acx.h" -#include "wl1251_cmd.h" -#include "wl1251_reg.h" - -int wl1251_hw_init_hwenc_config(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_feature_cfg(wl); - if (ret < 0) { - wl1251_warning("couldn't set feature config"); - return ret; - } - - ret = wl1251_acx_default_key(wl, wl->default_key); - if (ret < 0) { - wl1251_warning("couldn't set default key"); - return ret; - } - - return 0; -} - -int wl1251_hw_init_templates_config(struct wl1251 *wl) -{ - int ret; - u8 partial_vbm[PARTIAL_VBM_MAX]; - - /* send empty templates for fw memory reservation */ - ret = wl1251_cmd_template_set(wl, CMD_PROBE_REQ, NULL, - sizeof(struct wl12xx_probe_req_template)); - if (ret < 0) - return ret; - - ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, NULL, - sizeof(struct wl12xx_null_data_template)); - if (ret < 0) - return ret; - - ret = wl1251_cmd_template_set(wl, CMD_PS_POLL, NULL, - sizeof(struct wl12xx_ps_poll_template)); - if (ret < 0) - return ret; - - ret = wl1251_cmd_template_set(wl, CMD_QOS_NULL_DATA, NULL, - sizeof - (struct wl12xx_qos_null_data_template)); - if (ret < 0) - return ret; - - ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, NULL, - sizeof - (struct wl12xx_probe_resp_template)); - if (ret < 0) - return ret; - - ret = wl1251_cmd_template_set(wl, CMD_BEACON, NULL, - sizeof - (struct wl12xx_beacon_template)); - if (ret < 0) - return ret; - - /* tim templates, first reserve space then allocate an empty one */ - memset(partial_vbm, 0, PARTIAL_VBM_MAX); - ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, PARTIAL_VBM_MAX, 0); - if (ret < 0) - return ret; - - ret = wl1251_cmd_vbm(wl, TIM_ELE_ID, partial_vbm, 1, 0); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter) -{ - int ret; - - ret = wl1251_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); - if (ret < 0) - return ret; - - ret = wl1251_acx_rx_config(wl, config, filter); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_phy_config(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_pd_threshold(wl); - if (ret < 0) - return ret; - - ret = wl1251_acx_slot(wl, DEFAULT_SLOT_TIME); - if (ret < 0) - return ret; - - ret = wl1251_acx_group_address_tbl(wl); - if (ret < 0) - return ret; - - ret = wl1251_acx_service_period_timeout(wl); - if (ret < 0) - return ret; - - ret = wl1251_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_beacon_filter(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_beacon_filter_opt(wl); - if (ret < 0) - return ret; - - ret = wl1251_acx_beacon_filter_table(wl); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_pta(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_sg_enable(wl); - if (ret < 0) - return ret; - - ret = wl1251_acx_sg_cfg(wl); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_energy_detection(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_cca_threshold(wl); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_bcn_dtim_options(wl); - if (ret < 0) - return ret; - - return 0; -} - -int wl1251_hw_init_power_auth(struct wl1251 *wl) -{ - return wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); -} - -int wl1251_hw_init_mem_config(struct wl1251 *wl) -{ - int ret; - - ret = wl1251_acx_mem_cfg(wl); - if (ret < 0) - return ret; - - wl->target_mem_map = kzalloc(sizeof(struct wl1251_acx_mem_map), - GFP_KERNEL); - if (!wl->target_mem_map) { - wl1251_error("couldn't allocate target memory map"); - return -ENOMEM; - } - - /* we now ask for the firmware built memory map */ - ret = wl1251_acx_mem_map(wl, wl->target_mem_map, - sizeof(struct wl1251_acx_mem_map)); - if (ret < 0) { - wl1251_error("couldn't retrieve firmware memory map"); - kfree(wl->target_mem_map); - wl->target_mem_map = NULL; - return ret; - } - - return 0; -} - -static int wl1251_hw_init_txq_fill(u8 qid, - struct acx_tx_queue_qos_config *config, - u32 num_blocks) -{ - config->qid = qid; - - switch (qid) { - case QOS_AC_BE: - config->high_threshold = - (QOS_TX_HIGH_BE_DEF * num_blocks) / 100; - config->low_threshold = - (QOS_TX_LOW_BE_DEF * num_blocks) / 100; - break; - case QOS_AC_BK: - config->high_threshold = - (QOS_TX_HIGH_BK_DEF * num_blocks) / 100; - config->low_threshold = - (QOS_TX_LOW_BK_DEF * num_blocks) / 100; - break; - case QOS_AC_VI: - config->high_threshold = - (QOS_TX_HIGH_VI_DEF * num_blocks) / 100; - config->low_threshold = - (QOS_TX_LOW_VI_DEF * num_blocks) / 100; - break; - case QOS_AC_VO: - config->high_threshold = - (QOS_TX_HIGH_VO_DEF * num_blocks) / 100; - config->low_threshold = - (QOS_TX_LOW_VO_DEF * num_blocks) / 100; - break; - default: - wl1251_error("Invalid TX queue id: %d", qid); - return -EINVAL; - } - - return 0; -} - -static int wl1251_hw_init_tx_queue_config(struct wl1251 *wl) -{ - struct acx_tx_queue_qos_config *config; - struct wl1251_acx_mem_map *wl_mem_map = wl->target_mem_map; - int ret, i; - - wl1251_debug(DEBUG_ACX, "acx tx queue config"); - - config = kzalloc(sizeof(*config), GFP_KERNEL); - if (!config) { - ret = -ENOMEM; - goto out; - } - - for (i = 0; i < MAX_NUM_OF_AC; i++) { - ret = wl1251_hw_init_txq_fill(i, config, - wl_mem_map->num_tx_mem_blocks); - if (ret < 0) - goto out; - - ret = wl1251_cmd_configure(wl, ACX_TX_QUEUE_CFG, - config, sizeof(*config)); - if (ret < 0) - goto out; - } - -out: - kfree(config); - return ret; -} - -static int wl1251_hw_init_data_path_config(struct wl1251 *wl) -{ - int ret; - - /* asking for the data path parameters */ - wl->data_path = kzalloc(sizeof(struct acx_data_path_params_resp), - GFP_KERNEL); - if (!wl->data_path) { - wl1251_error("Couldnt allocate data path parameters"); - return -ENOMEM; - } - - ret = wl1251_acx_data_path_params(wl, wl->data_path); - if (ret < 0) { - kfree(wl->data_path); - wl->data_path = NULL; - return ret; - } - - return 0; -} - - -int wl1251_hw_init(struct wl1251 *wl) -{ - struct wl1251_acx_mem_map *wl_mem_map; - int ret; - - ret = wl1251_hw_init_hwenc_config(wl); - if (ret < 0) - return ret; - - /* Template settings */ - ret = wl1251_hw_init_templates_config(wl); - if (ret < 0) - return ret; - - /* Default memory configuration */ - ret = wl1251_hw_init_mem_config(wl); - if (ret < 0) - return ret; - - /* Default data path configuration */ - ret = wl1251_hw_init_data_path_config(wl); - if (ret < 0) - goto out_free_memmap; - - /* RX config */ - ret = wl1251_hw_init_rx_config(wl, - RX_CFG_PROMISCUOUS | RX_CFG_TSF, - RX_FILTER_OPTION_DEF); - /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, - RX_FILTER_OPTION_FILTER_ALL); */ - if (ret < 0) - goto out_free_data_path; - - /* TX queues config */ - ret = wl1251_hw_init_tx_queue_config(wl); - if (ret < 0) - goto out_free_data_path; - - /* PHY layer config */ - ret = wl1251_hw_init_phy_config(wl); - if (ret < 0) - goto out_free_data_path; - - /* Beacon filtering */ - ret = wl1251_hw_init_beacon_filter(wl); - if (ret < 0) - goto out_free_data_path; - - /* Bluetooth WLAN coexistence */ - ret = wl1251_hw_init_pta(wl); - if (ret < 0) - goto out_free_data_path; - - /* Energy detection */ - ret = wl1251_hw_init_energy_detection(wl); - if (ret < 0) - goto out_free_data_path; - - /* Beacons and boradcast settings */ - ret = wl1251_hw_init_beacon_broadcast(wl); - if (ret < 0) - goto out_free_data_path; - - /* Enable data path */ - ret = wl1251_cmd_data_path(wl, wl->channel, 1); - if (ret < 0) - goto out_free_data_path; - - /* Default power state */ - ret = wl1251_hw_init_power_auth(wl); - if (ret < 0) - goto out_free_data_path; - - wl_mem_map = wl->target_mem_map; - wl1251_info("%d tx blocks at 0x%x, %d rx blocks at 0x%x", - wl_mem_map->num_tx_mem_blocks, - wl->data_path->tx_control_addr, - wl_mem_map->num_rx_mem_blocks, - wl->data_path->rx_control_addr); - - return 0; - - out_free_data_path: - kfree(wl->data_path); - - out_free_memmap: - kfree(wl->target_mem_map); - - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1251_init.h b/drivers/net/wireless/wl12xx/wl1251_init.h deleted file mode 100644 index b3b25ec885ea..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_init.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_INIT_H__ -#define __WL1251_INIT_H__ - -#include "wl1251.h" - -int wl1251_hw_init_hwenc_config(struct wl1251 *wl); -int wl1251_hw_init_templates_config(struct wl1251 *wl); -int wl1251_hw_init_rx_config(struct wl1251 *wl, u32 config, u32 filter); -int wl1251_hw_init_phy_config(struct wl1251 *wl); -int wl1251_hw_init_beacon_filter(struct wl1251 *wl); -int wl1251_hw_init_pta(struct wl1251 *wl); -int wl1251_hw_init_energy_detection(struct wl1251 *wl); -int wl1251_hw_init_beacon_broadcast(struct wl1251 *wl); -int wl1251_hw_init_power_auth(struct wl1251 *wl); -int wl1251_hw_init_mem_config(struct wl1251 *wl); -int wl1251_hw_init(struct wl1251 *wl); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_io.c b/drivers/net/wireless/wl12xx/wl1251_io.c deleted file mode 100644 index f1c232e0887f..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_io.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" - -/* FIXME: this is static data nowadays and the table can be removed */ -static enum wl12xx_acx_int_reg wl1251_io_reg_table[ACX_REG_TABLE_LEN] = { - [ACX_REG_INTERRUPT_TRIG] = (REGISTERS_BASE + 0x0474), - [ACX_REG_INTERRUPT_TRIG_H] = (REGISTERS_BASE + 0x0478), - [ACX_REG_INTERRUPT_MASK] = (REGISTERS_BASE + 0x0494), - [ACX_REG_HINT_MASK_SET] = (REGISTERS_BASE + 0x0498), - [ACX_REG_HINT_MASK_CLR] = (REGISTERS_BASE + 0x049C), - [ACX_REG_INTERRUPT_NO_CLEAR] = (REGISTERS_BASE + 0x04B0), - [ACX_REG_INTERRUPT_CLEAR] = (REGISTERS_BASE + 0x04A4), - [ACX_REG_INTERRUPT_ACK] = (REGISTERS_BASE + 0x04A8), - [ACX_REG_SLV_SOFT_RESET] = (REGISTERS_BASE + 0x0000), - [ACX_REG_EE_START] = (REGISTERS_BASE + 0x080C), - [ACX_REG_ECPU_CONTROL] = (REGISTERS_BASE + 0x0804) -}; - -static int wl1251_translate_reg_addr(struct wl1251 *wl, int addr) -{ - /* If the address is lower than REGISTERS_BASE, it means that this is - * a chip-specific register address, so look it up in the registers - * table */ - if (addr < REGISTERS_BASE) { - /* Make sure we don't go over the table */ - if (addr >= ACX_REG_TABLE_LEN) { - wl1251_error("address out of range (%d)", addr); - return -EINVAL; - } - addr = wl1251_io_reg_table[addr]; - } - - return addr - wl->physical_reg_addr + wl->virtual_reg_addr; -} - -static int wl1251_translate_mem_addr(struct wl1251 *wl, int addr) -{ - return addr - wl->physical_mem_addr + wl->virtual_mem_addr; -} - -void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len) -{ - int physical; - - physical = wl1251_translate_mem_addr(wl, addr); - - wl->if_ops->read(wl, physical, buf, len); -} - -void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len) -{ - int physical; - - physical = wl1251_translate_mem_addr(wl, addr); - - wl->if_ops->write(wl, physical, buf, len); -} - -u32 wl1251_mem_read32(struct wl1251 *wl, int addr) -{ - return wl1251_read32(wl, wl1251_translate_mem_addr(wl, addr)); -} - -void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val) -{ - wl1251_write32(wl, wl1251_translate_mem_addr(wl, addr), val); -} - -u32 wl1251_reg_read32(struct wl1251 *wl, int addr) -{ - return wl1251_read32(wl, wl1251_translate_reg_addr(wl, addr)); -} - -void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val) -{ - wl1251_write32(wl, wl1251_translate_reg_addr(wl, addr), val); -} - -/* Set the partitions to access the chip addresses. - * - * There are two VIRTUAL partitions (the memory partition and the - * registers partition), which are mapped to two different areas of the - * PHYSICAL (hardware) memory. This function also makes other checks to - * ensure that the partitions are not overlapping. In the diagram below, the - * memory partition comes before the register partition, but the opposite is - * also supported. - * - * PHYSICAL address - * space - * - * | | - * ...+----+--> mem_start - * VIRTUAL address ... | | - * space ... | | [PART_0] - * ... | | - * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size - * | | ... | | - * |MEM | ... | | - * | | ... | | - * part_size <--+----+... | | {unused area) - * | | ... | | - * |REG | ... | | - * part_size | | ... | | - * + <--+----+... ...+----+--> reg_start - * reg_size ... | | - * ... | | [PART_1] - * ... | | - * ...+----+--> reg_start + reg_size - * | | - * - */ -void wl1251_set_partition(struct wl1251 *wl, - u32 mem_start, u32 mem_size, - u32 reg_start, u32 reg_size) -{ - struct wl1251_partition partition[2]; - - wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - - /* Make sure that the two partitions together don't exceed the - * address range */ - if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { - wl1251_debug(DEBUG_SPI, "Total size exceeds maximum virtual" - " address range. Truncating partition[0]."); - mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; - wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - } - - if ((mem_start < reg_start) && - ((mem_start + mem_size) > reg_start)) { - /* Guarantee that the memory partition doesn't overlap the - * registers partition */ - wl1251_debug(DEBUG_SPI, "End of partition[0] is " - "overlapping partition[1]. Adjusted."); - mem_size = reg_start - mem_start; - wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - } else if ((reg_start < mem_start) && - ((reg_start + reg_size) > mem_start)) { - /* Guarantee that the register partition doesn't overlap the - * memory partition */ - wl1251_debug(DEBUG_SPI, "End of partition[1] is" - " overlapping partition[0]. Adjusted."); - reg_size = mem_start - reg_start; - wl1251_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1251_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - } - - partition[0].start = mem_start; - partition[0].size = mem_size; - partition[1].start = reg_start; - partition[1].size = reg_size; - - wl->physical_mem_addr = mem_start; - wl->physical_reg_addr = reg_start; - - wl->virtual_mem_addr = 0; - wl->virtual_reg_addr = mem_size; - - wl->if_ops->write(wl, HW_ACCESS_PART0_SIZE_ADDR, partition, - sizeof(partition)); -} diff --git a/drivers/net/wireless/wl12xx/wl1251_io.h b/drivers/net/wireless/wl12xx/wl1251_io.h deleted file mode 100644 index b89d2ac62efb..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_io.h +++ /dev/null @@ -1,64 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 2008 Nokia Corporation - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ -#ifndef __WL1251_IO_H__ -#define __WL1251_IO_H__ - -#include "wl1251.h" - -#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 - -#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0 -#define HW_ACCESS_PART0_START_ADDR 0x1FFC4 -#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8 -#define HW_ACCESS_PART1_START_ADDR 0x1FFCC - -#define HW_ACCESS_REGISTER_SIZE 4 - -#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 - -static inline u32 wl1251_read32(struct wl1251 *wl, int addr) -{ - u32 response; - - wl->if_ops->read(wl, addr, &response, sizeof(u32)); - - return response; -} - -static inline void wl1251_write32(struct wl1251 *wl, int addr, u32 val) -{ - wl->if_ops->write(wl, addr, &val, sizeof(u32)); -} - -/* Memory target IO, address is translated to partition 0 */ -void wl1251_mem_read(struct wl1251 *wl, int addr, void *buf, size_t len); -void wl1251_mem_write(struct wl1251 *wl, int addr, void *buf, size_t len); -u32 wl1251_mem_read32(struct wl1251 *wl, int addr); -void wl1251_mem_write32(struct wl1251 *wl, int addr, u32 val); -/* Registers IO */ -u32 wl1251_reg_read32(struct wl1251 *wl, int addr); -void wl1251_reg_write32(struct wl1251 *wl, int addr, u32 val); - -void wl1251_set_partition(struct wl1251 *wl, - u32 part_start, u32 part_size, - u32 reg_start, u32 reg_size); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_main.c b/drivers/net/wireless/wl12xx/wl1251_main.c deleted file mode 100644 index 1103256ad989..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_main.c +++ /dev/null @@ -1,1429 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "wl1251.h" -#include "wl12xx_80211.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_cmd.h" -#include "wl1251_event.h" -#include "wl1251_tx.h" -#include "wl1251_rx.h" -#include "wl1251_ps.h" -#include "wl1251_init.h" -#include "wl1251_debugfs.h" -#include "wl1251_boot.h" - -void wl1251_enable_interrupts(struct wl1251 *wl) -{ - wl->if_ops->enable_irq(wl); -} - -void wl1251_disable_interrupts(struct wl1251 *wl) -{ - wl->if_ops->disable_irq(wl); -} - -static void wl1251_power_off(struct wl1251 *wl) -{ - wl->set_power(false); -} - -static void wl1251_power_on(struct wl1251 *wl) -{ - wl->set_power(true); -} - -static int wl1251_fetch_firmware(struct wl1251 *wl) -{ - const struct firmware *fw; - struct device *dev = wiphy_dev(wl->hw->wiphy); - int ret; - - ret = request_firmware(&fw, WL1251_FW_NAME, dev); - - if (ret < 0) { - wl1251_error("could not get firmware: %d", ret); - return ret; - } - - if (fw->size % 4) { - wl1251_error("firmware size is not multiple of 32 bits: %zu", - fw->size); - ret = -EILSEQ; - goto out; - } - - wl->fw_len = fw->size; - wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); - - if (!wl->fw) { - wl1251_error("could not allocate memory for the firmware"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->fw, fw->data, wl->fw_len); - - ret = 0; - -out: - release_firmware(fw); - - return ret; -} - -static int wl1251_fetch_nvs(struct wl1251 *wl) -{ - const struct firmware *fw; - struct device *dev = wiphy_dev(wl->hw->wiphy); - int ret; - - ret = request_firmware(&fw, WL1251_NVS_NAME, dev); - - if (ret < 0) { - wl1251_error("could not get nvs file: %d", ret); - return ret; - } - - if (fw->size % 4) { - wl1251_error("nvs size is not multiple of 32 bits: %zu", - fw->size); - ret = -EILSEQ; - goto out; - } - - wl->nvs_len = fw->size; - wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); - - if (!wl->nvs) { - wl1251_error("could not allocate memory for the nvs file"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->nvs, fw->data, wl->nvs_len); - - ret = 0; - -out: - release_firmware(fw); - - return ret; -} - -static void wl1251_fw_wakeup(struct wl1251 *wl) -{ - u32 elp_reg; - - elp_reg = ELPCTRL_WAKE_UP; - wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); - elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); - - if (!(elp_reg & ELPCTRL_WLAN_READY)) - wl1251_warning("WLAN not ready"); -} - -static int wl1251_chip_wakeup(struct wl1251 *wl) -{ - int ret = 0; - - wl1251_power_on(wl); - msleep(WL1251_POWER_ON_SLEEP); - wl->if_ops->reset(wl); - - /* We don't need a real memory partition here, because we only want - * to use the registers at this point. */ - wl1251_set_partition(wl, - 0x00000000, - 0x00000000, - REGISTERS_BASE, - REGISTERS_DOWN_SIZE); - - /* ELP module wake up */ - wl1251_fw_wakeup(wl); - - /* whal_FwCtrl_BootSm() */ - - /* 0. read chip id from CHIP_ID */ - wl->chip_id = wl1251_reg_read32(wl, CHIP_ID_B); - - /* 1. check if chip id is valid */ - - switch (wl->chip_id) { - case CHIP_ID_1251_PG12: - wl1251_debug(DEBUG_BOOT, "chip id 0x%x (1251 PG12)", - wl->chip_id); - break; - case CHIP_ID_1251_PG10: - case CHIP_ID_1251_PG11: - default: - wl1251_error("unsupported chip id: 0x%x", wl->chip_id); - ret = -ENODEV; - goto out; - } - - if (wl->fw == NULL) { - ret = wl1251_fetch_firmware(wl); - if (ret < 0) - goto out; - } - - /* No NVS from netlink, try to get it from the filesystem */ - if (wl->nvs == NULL) { - ret = wl1251_fetch_nvs(wl); - if (ret < 0) - goto out; - } - -out: - return ret; -} - -static void wl1251_irq_work(struct work_struct *work) -{ - u32 intr; - struct wl1251 *wl = - container_of(work, struct wl1251, irq_work); - int ret; - - mutex_lock(&wl->mutex); - - wl1251_debug(DEBUG_IRQ, "IRQ work"); - - if (wl->state == WL1251_STATE_OFF) - goto out; - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1251_ACX_INTR_ALL); - - intr = wl1251_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); - wl1251_debug(DEBUG_IRQ, "intr: 0x%x", intr); - - if (wl->data_path) { - wl->rx_counter = - wl1251_mem_read32(wl, wl->data_path->rx_control_addr); - - /* We handle a frmware bug here */ - switch ((wl->rx_counter - wl->rx_handled) & 0xf) { - case 0: - wl1251_debug(DEBUG_IRQ, "RX: FW and host in sync"); - intr &= ~WL1251_ACX_INTR_RX0_DATA; - intr &= ~WL1251_ACX_INTR_RX1_DATA; - break; - case 1: - wl1251_debug(DEBUG_IRQ, "RX: FW +1"); - intr |= WL1251_ACX_INTR_RX0_DATA; - intr &= ~WL1251_ACX_INTR_RX1_DATA; - break; - case 2: - wl1251_debug(DEBUG_IRQ, "RX: FW +2"); - intr |= WL1251_ACX_INTR_RX0_DATA; - intr |= WL1251_ACX_INTR_RX1_DATA; - break; - default: - wl1251_warning("RX: FW and host out of sync: %d", - wl->rx_counter - wl->rx_handled); - break; - } - - wl->rx_handled = wl->rx_counter; - - - wl1251_debug(DEBUG_IRQ, "RX counter: %d", wl->rx_counter); - } - - intr &= wl->intr_mask; - - if (intr == 0) { - wl1251_debug(DEBUG_IRQ, "INTR is 0"); - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, - ~(wl->intr_mask)); - - goto out_sleep; - } - - if (intr & WL1251_ACX_INTR_RX0_DATA) { - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX0_DATA"); - wl1251_rx(wl); - } - - if (intr & WL1251_ACX_INTR_RX1_DATA) { - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_RX1_DATA"); - wl1251_rx(wl); - } - - if (intr & WL1251_ACX_INTR_TX_RESULT) { - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_TX_RESULT"); - wl1251_tx_complete(wl); - } - - if (intr & (WL1251_ACX_INTR_EVENT_A | WL1251_ACX_INTR_EVENT_B)) { - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_EVENT (0x%x)", intr); - if (intr & WL1251_ACX_INTR_EVENT_A) - wl1251_event_handle(wl, 0); - else - wl1251_event_handle(wl, 1); - } - - if (intr & WL1251_ACX_INTR_INIT_COMPLETE) - wl1251_debug(DEBUG_IRQ, "WL1251_ACX_INTR_INIT_COMPLETE"); - - wl1251_reg_write32(wl, ACX_REG_INTERRUPT_MASK, ~(wl->intr_mask)); - -out_sleep: - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -static int wl1251_join(struct wl1251 *wl, u8 bss_type, u8 channel, - u16 beacon_interval, u8 dtim_period) -{ - int ret; - - ret = wl1251_acx_frame_rates(wl, DEFAULT_HW_GEN_TX_RATE, - DEFAULT_HW_GEN_MODULATION_TYPE, - wl->tx_mgmt_frm_rate, - wl->tx_mgmt_frm_mod); - if (ret < 0) - goto out; - - - ret = wl1251_cmd_join(wl, bss_type, channel, beacon_interval, - dtim_period); - if (ret < 0) - goto out; - - /* - * FIXME: we should wait for JOIN_EVENT_COMPLETE_ID but to simplify - * locking we just sleep instead, for now - */ - msleep(10); - -out: - return ret; -} - -static void wl1251_filter_work(struct work_struct *work) -{ - struct wl1251 *wl = - container_of(work, struct wl1251, filter_work); - int ret; - - mutex_lock(&wl->mutex); - - if (wl->state == WL1251_STATE_OFF) - goto out; - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1251_join(wl, wl->bss_type, wl->channel, wl->beacon_int, - wl->dtim_period); - if (ret < 0) - goto out_sleep; - -out_sleep: - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct wl1251 *wl = hw->priv; - - skb_queue_tail(&wl->tx_queue, skb); - - /* - * The chip specific setup must run before the first TX packet - - * before that, the tx_work will not be initialized! - */ - - ieee80211_queue_work(wl->hw, &wl->tx_work); - - /* - * The workqueue is slow to process the tx_queue and we need stop - * the queue here, otherwise the queue will get too long. - */ - if (skb_queue_len(&wl->tx_queue) >= WL1251_TX_QUEUE_MAX_LENGTH) { - ieee80211_stop_queues(wl->hw); - - /* - * FIXME: this is racy, the variable is not properly - * protected. Maybe fix this by removing the stupid - * variable altogether and checking the real queue state? - */ - wl->tx_queue_stopped = true; - } - - return NETDEV_TX_OK; -} - -static int wl1251_op_start(struct ieee80211_hw *hw) -{ - struct wl1251 *wl = hw->priv; - int ret = 0; - - wl1251_debug(DEBUG_MAC80211, "mac80211 start"); - - mutex_lock(&wl->mutex); - - if (wl->state != WL1251_STATE_OFF) { - wl1251_error("cannot start because not in off state: %d", - wl->state); - ret = -EBUSY; - goto out; - } - - ret = wl1251_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1251_boot(wl); - if (ret < 0) - goto out; - - ret = wl1251_hw_init(wl); - if (ret < 0) - goto out; - - ret = wl1251_acx_station_id(wl); - if (ret < 0) - goto out; - - wl->state = WL1251_STATE_ON; - - wl1251_info("firmware booted (%s)", wl->fw_ver); - -out: - if (ret < 0) - wl1251_power_off(wl); - - mutex_unlock(&wl->mutex); - - return ret; -} - -static void wl1251_op_stop(struct ieee80211_hw *hw) -{ - struct wl1251 *wl = hw->priv; - - wl1251_info("down"); - - wl1251_debug(DEBUG_MAC80211, "mac80211 stop"); - - mutex_lock(&wl->mutex); - - WARN_ON(wl->state != WL1251_STATE_ON); - - if (wl->scanning) { - mutex_unlock(&wl->mutex); - ieee80211_scan_completed(wl->hw, true); - mutex_lock(&wl->mutex); - wl->scanning = false; - } - - wl->state = WL1251_STATE_OFF; - - wl1251_disable_interrupts(wl); - - mutex_unlock(&wl->mutex); - - cancel_work_sync(&wl->irq_work); - cancel_work_sync(&wl->tx_work); - cancel_work_sync(&wl->filter_work); - - mutex_lock(&wl->mutex); - - /* let's notify MAC80211 about the remaining pending TX frames */ - wl1251_tx_flush(wl); - wl1251_power_off(wl); - - memset(wl->bssid, 0, ETH_ALEN); - wl->listen_int = 1; - wl->bss_type = MAX_BSS_TYPE; - - wl->data_in_count = 0; - wl->rx_counter = 0; - wl->rx_handled = 0; - wl->rx_current_buffer = 0; - wl->rx_last_id = 0; - wl->next_tx_complete = 0; - wl->elp = false; - wl->psm = 0; - wl->tx_queue_stopped = false; - wl->power_level = WL1251_DEFAULT_POWER_LEVEL; - wl->channel = WL1251_DEFAULT_CHANNEL; - - wl1251_debugfs_reset(wl); - - mutex_unlock(&wl->mutex); -} - -static int wl1251_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct wl1251 *wl = hw->priv; - int ret = 0; - - wl1251_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); - - mutex_lock(&wl->mutex); - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - wl->bss_type = BSS_TYPE_STA_BSS; - break; - case NL80211_IFTYPE_ADHOC: - wl->bss_type = BSS_TYPE_IBSS; - break; - default: - ret = -EOPNOTSUPP; - goto out; - } - - if (memcmp(wl->mac_addr, conf->mac_addr, ETH_ALEN)) { - memcpy(wl->mac_addr, conf->mac_addr, ETH_ALEN); - SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); - ret = wl1251_acx_station_id(wl); - if (ret < 0) - goto out; - } - -out: - mutex_unlock(&wl->mutex); - return ret; -} - -static void wl1251_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - wl1251_debug(DEBUG_MAC80211, "mac80211 remove interface"); -} - -static int wl1251_build_null_data(struct wl1251 *wl) -{ - struct wl12xx_null_data_template template; - - if (!is_zero_ether_addr(wl->bssid)) { - memcpy(template.header.da, wl->bssid, ETH_ALEN); - memcpy(template.header.bssid, wl->bssid, ETH_ALEN); - } else { - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - } - - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - return wl1251_cmd_template_set(wl, CMD_NULL_DATA, &template, - sizeof(template)); - -} - -static int wl1251_build_ps_poll(struct wl1251 *wl, u16 aid) -{ - struct wl12xx_ps_poll_template template; - - memcpy(template.bssid, wl->bssid, ETH_ALEN); - memcpy(template.ta, wl->mac_addr, ETH_ALEN); - template.aid = aid; - template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); - - return wl1251_cmd_template_set(wl, CMD_PS_POLL, &template, - sizeof(template)); - -} - -static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct wl1251 *wl = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - int channel, ret = 0; - - channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - - wl1251_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", - channel, - conf->flags & IEEE80211_CONF_PS ? "on" : "off", - conf->power_level); - - mutex_lock(&wl->mutex); - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - if (channel != wl->channel) { - wl->channel = channel; - - ret = wl1251_join(wl, wl->bss_type, wl->channel, - wl->beacon_int, wl->dtim_period); - if (ret < 0) - goto out_sleep; - } - - ret = wl1251_build_null_data(wl); - if (ret < 0) - goto out_sleep; - - if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { - wl1251_debug(DEBUG_PSM, "psm enabled"); - - wl->psm_requested = true; - - /* - * We enter PSM only if we're already associated. - * If we're not, we'll enter it when joining an SSID, - * through the bss_info_changed() hook. - */ - ret = wl1251_ps_set_mode(wl, STATION_POWER_SAVE_MODE); - } else if (!(conf->flags & IEEE80211_CONF_PS) && - wl->psm_requested) { - wl1251_debug(DEBUG_PSM, "psm disabled"); - - wl->psm_requested = false; - - if (wl->psm) - ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE); - } - - if (conf->power_level != wl->power_level) { - ret = wl1251_acx_tx_power(wl, conf->power_level); - if (ret < 0) - goto out; - - wl->power_level = conf->power_level; - } - -out_sleep: - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -#define WL1251_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ - FIF_ALLMULTI | \ - FIF_FCSFAIL | \ - FIF_BCN_PRBRESP_PROMISC | \ - FIF_CONTROL | \ - FIF_OTHER_BSS) - -static void wl1251_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed, - unsigned int *total,u64 multicast) -{ - struct wl1251 *wl = hw->priv; - - wl1251_debug(DEBUG_MAC80211, "mac80211 configure filter"); - - *total &= WL1251_SUPPORTED_FILTERS; - changed &= WL1251_SUPPORTED_FILTERS; - - if (changed == 0) - /* no filters which we support changed */ - return; - - /* FIXME: wl->rx_config and wl->rx_filter are not protected */ - - wl->rx_config = WL1251_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1251_DEFAULT_RX_FILTER; - - if (*total & FIF_PROMISC_IN_BSS) { - wl->rx_config |= CFG_BSSID_FILTER_EN; - wl->rx_config |= CFG_RX_ALL_GOOD; - } - if (*total & FIF_ALLMULTI) - /* - * CFG_MC_FILTER_EN in rx_config needs to be 0 to receive - * all multicast frames - */ - wl->rx_config &= ~CFG_MC_FILTER_EN; - if (*total & FIF_FCSFAIL) - wl->rx_filter |= CFG_RX_FCS_ERROR; - if (*total & FIF_BCN_PRBRESP_PROMISC) { - wl->rx_config &= ~CFG_BSSID_FILTER_EN; - wl->rx_config &= ~CFG_SSID_FILTER_EN; - } - if (*total & FIF_CONTROL) - wl->rx_filter |= CFG_RX_CTL_EN; - if (*total & FIF_OTHER_BSS) - wl->rx_filter &= ~CFG_BSSID_FILTER_EN; - - /* - * FIXME: workqueues need to be properly cancelled on stop(), for - * now let's just disable changing the filter settings. They will - * be updated any on config(). - */ - /* schedule_work(&wl->filter_work); */ -} - -/* HW encryption */ -static int wl1251_set_key_type(struct wl1251 *wl, - struct wl1251_cmd_set_keys *key, - enum set_key_cmd cmd, - struct ieee80211_key_conf *mac80211_key, - const u8 *addr) -{ - switch (mac80211_key->alg) { - case ALG_WEP: - if (is_broadcast_ether_addr(addr)) - key->key_type = KEY_WEP_DEFAULT; - else - key->key_type = KEY_WEP_ADDR; - - mac80211_key->hw_key_idx = mac80211_key->keyidx; - break; - case ALG_TKIP: - if (is_broadcast_ether_addr(addr)) - key->key_type = KEY_TKIP_MIC_GROUP; - else - key->key_type = KEY_TKIP_MIC_PAIRWISE; - - mac80211_key->hw_key_idx = mac80211_key->keyidx; - break; - case ALG_CCMP: - if (is_broadcast_ether_addr(addr)) - key->key_type = KEY_AES_GROUP; - else - key->key_type = KEY_AES_PAIRWISE; - mac80211_key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - break; - default: - wl1251_error("Unknown key algo 0x%x", mac80211_key->alg); - return -EOPNOTSUPP; - } - - return 0; -} - -static int wl1251_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key) -{ - struct wl1251 *wl = hw->priv; - struct wl1251_cmd_set_keys *wl_cmd; - const u8 *addr; - int ret; - - static const u8 bcast_addr[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - wl1251_debug(DEBUG_MAC80211, "mac80211 set key"); - - wl_cmd = kzalloc(sizeof(*wl_cmd), GFP_KERNEL); - if (!wl_cmd) { - ret = -ENOMEM; - goto out; - } - - addr = sta ? sta->addr : bcast_addr; - - wl1251_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); - wl1251_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); - wl1251_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", - key->alg, key->keyidx, key->keylen, key->flags); - wl1251_dump(DEBUG_CRYPT, "KEY: ", key->key, key->keylen); - - if (is_zero_ether_addr(addr)) { - /* We dont support TX only encryption */ - ret = -EOPNOTSUPP; - goto out; - } - - mutex_lock(&wl->mutex); - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out_unlock; - - switch (cmd) { - case SET_KEY: - wl_cmd->key_action = KEY_ADD_OR_REPLACE; - break; - case DISABLE_KEY: - wl_cmd->key_action = KEY_REMOVE; - break; - default: - wl1251_error("Unsupported key cmd 0x%x", cmd); - break; - } - - ret = wl1251_set_key_type(wl, wl_cmd, cmd, key, addr); - if (ret < 0) { - wl1251_error("Set KEY type failed"); - goto out_sleep; - } - - if (wl_cmd->key_type != KEY_WEP_DEFAULT) - memcpy(wl_cmd->addr, addr, ETH_ALEN); - - if ((wl_cmd->key_type == KEY_TKIP_MIC_GROUP) || - (wl_cmd->key_type == KEY_TKIP_MIC_PAIRWISE)) { - /* - * We get the key in the following form: - * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) - * but the target is expecting: - * TKIP - RX MIC - TX MIC - */ - memcpy(wl_cmd->key, key->key, 16); - memcpy(wl_cmd->key + 16, key->key + 24, 8); - memcpy(wl_cmd->key + 24, key->key + 16, 8); - - } else { - memcpy(wl_cmd->key, key->key, key->keylen); - } - wl_cmd->key_size = key->keylen; - - wl_cmd->id = key->keyidx; - wl_cmd->ssid_profile = 0; - - wl1251_dump(DEBUG_CRYPT, "TARGET KEY: ", wl_cmd, sizeof(*wl_cmd)); - - ret = wl1251_cmd_send(wl, CMD_SET_KEYS, wl_cmd, sizeof(*wl_cmd)); - if (ret < 0) { - wl1251_warning("could not set keys"); - goto out_sleep; - } - -out_sleep: - wl1251_ps_elp_sleep(wl); - -out_unlock: - mutex_unlock(&wl->mutex); - -out: - kfree(wl_cmd); - - return ret; -} - -static int wl1251_build_basic_rates(char *rates) -{ - u8 index = 0; - - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - - return index; -} - -static int wl1251_build_extended_rates(char *rates) -{ - u8 index = 0; - - rates[index++] = IEEE80211_OFDM_RATE_6MB; - rates[index++] = IEEE80211_OFDM_RATE_9MB; - rates[index++] = IEEE80211_OFDM_RATE_12MB; - rates[index++] = IEEE80211_OFDM_RATE_18MB; - rates[index++] = IEEE80211_OFDM_RATE_24MB; - rates[index++] = IEEE80211_OFDM_RATE_36MB; - rates[index++] = IEEE80211_OFDM_RATE_48MB; - rates[index++] = IEEE80211_OFDM_RATE_54MB; - - return index; -} - - -static int wl1251_build_probe_req(struct wl1251 *wl, u8 *ssid, size_t ssid_len) -{ - struct wl12xx_probe_req_template template; - struct wl12xx_ie_rates *rates; - char *ptr; - u16 size; - - ptr = (char *)&template; - size = sizeof(struct ieee80211_header); - - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - - /* IEs */ - /* SSID */ - template.ssid.header.id = WLAN_EID_SSID; - template.ssid.header.len = ssid_len; - if (ssid_len && ssid) - memcpy(template.ssid.ssid, ssid, ssid_len); - size += sizeof(struct wl12xx_ie_header) + ssid_len; - ptr += size; - - /* Basic Rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_SUPP_RATES; - rates->header.len = wl1251_build_basic_rates(rates->rates); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; - - /* Extended rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_EXT_SUPP_RATES; - rates->header.len = wl1251_build_extended_rates(rates->rates); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - - wl1251_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); - - return wl1251_cmd_template_set(wl, CMD_PROBE_REQ, &template, - size); -} - -static int wl1251_hw_scan(struct wl1251 *wl, u8 *ssid, size_t len, - u8 active_scan, u8 high_prio, u8 num_channels, - u8 probe_requests) -{ - struct wl1251_cmd_trigger_scan_to *trigger = NULL; - struct cmd_scan *params = NULL; - int i, ret; - u16 scan_options = 0; - - if (wl->scanning) - return -EINVAL; - - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); - params->params.rx_filter_options = - cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); - - /* High priority scan */ - if (!active_scan) - scan_options |= SCAN_PASSIVE; - if (high_prio) - scan_options |= SCAN_PRIORITY_HIGH; - params->params.scan_options = scan_options; - - params->params.num_channels = num_channels; - params->params.num_probe_requests = probe_requests; - params->params.tx_rate = cpu_to_le16(1 << 1); /* 2 Mbps */ - params->params.tid_trigger = 0; - - for (i = 0; i < num_channels; i++) { - params->channels[i].min_duration = cpu_to_le32(30000); - params->channels[i].max_duration = cpu_to_le32(60000); - memset(¶ms->channels[i].bssid_lsb, 0xff, 4); - memset(¶ms->channels[i].bssid_msb, 0xff, 2); - params->channels[i].early_termination = 0; - params->channels[i].tx_power_att = 0; - params->channels[i].channel = i + 1; - memset(params->channels[i].pad, 0, 3); - } - - for (i = num_channels; i < SCAN_MAX_NUM_OF_CHANNELS; i++) - memset(¶ms->channels[i], 0, - sizeof(struct basic_scan_channel_parameters)); - - if (len && ssid) { - params->params.ssid_len = len; - memcpy(params->params.ssid, ssid, len); - } else { - params->params.ssid_len = 0; - memset(params->params.ssid, 0, 32); - } - - ret = wl1251_build_probe_req(wl, ssid, len); - if (ret < 0) { - wl1251_error("PROBE request template failed"); - goto out; - } - - trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); - if (!trigger) - goto out; - - trigger->timeout = 0; - - ret = wl1251_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, - sizeof(*trigger)); - if (ret < 0) { - wl1251_error("trigger scan to failed for hw scan"); - goto out; - } - - wl1251_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); - - wl->scanning = true; - - ret = wl1251_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); - if (ret < 0) - wl1251_error("SCAN failed"); - - wl1251_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); - - if (params->header.status != CMD_STATUS_SUCCESS) { - wl1251_error("TEST command answer error: %d", - params->header.status); - wl->scanning = false; - ret = -EIO; - goto out; - } - -out: - kfree(params); - return ret; - -} - -static int wl1251_op_hw_scan(struct ieee80211_hw *hw, - struct cfg80211_scan_request *req) -{ - struct wl1251 *wl = hw->priv; - int ret; - u8 *ssid = NULL; - size_t ssid_len = 0; - - wl1251_debug(DEBUG_MAC80211, "mac80211 hw scan"); - - if (req->n_ssids) { - ssid = req->ssids[0].ssid; - ssid_len = req->ssids[0].ssid_len; - } - - mutex_lock(&wl->mutex); - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1251_hw_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); - - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -static int wl1251_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - struct wl1251 *wl = hw->priv; - int ret; - - mutex_lock(&wl->mutex); - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1251_acx_rts_threshold(wl, (u16) value); - if (ret < 0) - wl1251_warning("wl1251_op_set_rts_threshold failed: %d", ret); - - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - enum wl1251_cmd_ps_mode mode; - struct wl1251 *wl = hw->priv; - struct sk_buff *beacon; - int ret; - - wl1251_debug(DEBUG_MAC80211, "mac80211 bss info changed"); - - mutex_lock(&wl->mutex); - - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - - if (changed & BSS_CHANGED_ASSOC) { - if (bss_conf->assoc) { - wl->beacon_int = bss_conf->beacon_int; - wl->dtim_period = bss_conf->dtim_period; - - /* FIXME: call join */ - - wl->aid = bss_conf->aid; - - ret = wl1251_build_ps_poll(wl, wl->aid); - if (ret < 0) - goto out_sleep; - - ret = wl1251_acx_aid(wl, wl->aid); - if (ret < 0) - goto out_sleep; - - /* If we want to go in PSM but we're not there yet */ - if (wl->psm_requested && !wl->psm) { - mode = STATION_POWER_SAVE_MODE; - ret = wl1251_ps_set_mode(wl, mode); - if (ret < 0) - goto out_sleep; - } - } else { - /* use defaults when not associated */ - wl->beacon_int = WL1251_DEFAULT_BEACON_INT; - wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; - } - } - if (changed & BSS_CHANGED_ERP_SLOT) { - if (bss_conf->use_short_slot) - ret = wl1251_acx_slot(wl, SLOT_TIME_SHORT); - else - ret = wl1251_acx_slot(wl, SLOT_TIME_LONG); - if (ret < 0) { - wl1251_warning("Set slot time failed %d", ret); - goto out_sleep; - } - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - if (bss_conf->use_short_preamble) - wl1251_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); - else - wl1251_acx_set_preamble(wl, ACX_PREAMBLE_LONG); - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - if (bss_conf->use_cts_prot) - ret = wl1251_acx_cts_protect(wl, CTSPROTECT_ENABLE); - else - ret = wl1251_acx_cts_protect(wl, CTSPROTECT_DISABLE); - if (ret < 0) { - wl1251_warning("Set ctsprotect failed %d", ret); - goto out; - } - } - - if (changed & BSS_CHANGED_BSSID) { - memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN); - - ret = wl1251_build_null_data(wl); - if (ret < 0) - goto out; - - if (wl->bss_type != BSS_TYPE_IBSS) { - ret = wl1251_join(wl, wl->bss_type, wl->channel, - wl->beacon_int, wl->dtim_period); - if (ret < 0) - goto out_sleep; - wl1251_warning("Set ctsprotect failed %d", ret); - goto out_sleep; - } - } - - if (changed & BSS_CHANGED_BEACON) { - beacon = ieee80211_beacon_get(hw, vif); - ret = wl1251_cmd_template_set(wl, CMD_BEACON, beacon->data, - beacon->len); - - if (ret < 0) { - dev_kfree_skb(beacon); - goto out; - } - - ret = wl1251_cmd_template_set(wl, CMD_PROBE_RESP, beacon->data, - beacon->len); - - dev_kfree_skb(beacon); - - if (ret < 0) - goto out; - - ret = wl1251_join(wl, wl->bss_type, wl->beacon_int, - wl->channel, wl->dtim_period); - - if (ret < 0) - goto out; - } - -out_sleep: - wl1251_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_rate wl1251_rates[] = { - { .bitrate = 10, - .hw_value = 0x1, - .hw_value_short = 0x1, }, - { .bitrate = 20, - .hw_value = 0x2, - .hw_value_short = 0x2, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, - .hw_value = 0x4, - .hw_value_short = 0x4, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, - .hw_value = 0x20, - .hw_value_short = 0x20, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, - .hw_value = 0x8, - .hw_value_short = 0x8, }, - { .bitrate = 90, - .hw_value = 0x10, - .hw_value_short = 0x10, }, - { .bitrate = 120, - .hw_value = 0x40, - .hw_value_short = 0x40, }, - { .bitrate = 180, - .hw_value = 0x80, - .hw_value_short = 0x80, }, - { .bitrate = 240, - .hw_value = 0x200, - .hw_value_short = 0x200, }, - { .bitrate = 360, - .hw_value = 0x400, - .hw_value_short = 0x400, }, - { .bitrate = 480, - .hw_value = 0x800, - .hw_value_short = 0x800, }, - { .bitrate = 540, - .hw_value = 0x1000, - .hw_value_short = 0x1000, }, -}; - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_channel wl1251_channels[] = { - { .hw_value = 1, .center_freq = 2412}, - { .hw_value = 2, .center_freq = 2417}, - { .hw_value = 3, .center_freq = 2422}, - { .hw_value = 4, .center_freq = 2427}, - { .hw_value = 5, .center_freq = 2432}, - { .hw_value = 6, .center_freq = 2437}, - { .hw_value = 7, .center_freq = 2442}, - { .hw_value = 8, .center_freq = 2447}, - { .hw_value = 9, .center_freq = 2452}, - { .hw_value = 10, .center_freq = 2457}, - { .hw_value = 11, .center_freq = 2462}, - { .hw_value = 12, .center_freq = 2467}, - { .hw_value = 13, .center_freq = 2472}, -}; - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_supported_band wl1251_band_2ghz = { - .channels = wl1251_channels, - .n_channels = ARRAY_SIZE(wl1251_channels), - .bitrates = wl1251_rates, - .n_bitrates = ARRAY_SIZE(wl1251_rates), -}; - -static const struct ieee80211_ops wl1251_ops = { - .start = wl1251_op_start, - .stop = wl1251_op_stop, - .add_interface = wl1251_op_add_interface, - .remove_interface = wl1251_op_remove_interface, - .config = wl1251_op_config, - .configure_filter = wl1251_op_configure_filter, - .tx = wl1251_op_tx, - .set_key = wl1251_op_set_key, - .hw_scan = wl1251_op_hw_scan, - .bss_info_changed = wl1251_op_bss_info_changed, - .set_rts_threshold = wl1251_op_set_rts_threshold, -}; - -static int wl1251_register_hw(struct wl1251 *wl) -{ - int ret; - - if (wl->mac80211_registered) - return 0; - - SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); - - ret = ieee80211_register_hw(wl->hw); - if (ret < 0) { - wl1251_error("unable to register mac80211 hw: %d", ret); - return ret; - } - - wl->mac80211_registered = true; - - wl1251_notice("loaded"); - - return 0; -} - -int wl1251_init_ieee80211(struct wl1251 *wl) -{ - int ret; - - /* The tx descriptor buffer and the TKIP space */ - wl->hw->extra_tx_headroom = sizeof(struct tx_double_buffer_desc) - + WL1251_TKIP_IV_SPACE; - - /* unit us */ - /* FIXME: find a proper value */ - wl->hw->channel_change_time = 10000; - - wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - wl->hw->wiphy->max_scan_ssids = 1; - wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz; - - ret = wl1251_register_hw(wl); - if (ret) - goto out; - - wl1251_debugfs_init(wl); - wl1251_notice("initialized"); - - ret = 0; - -out: - return ret; -} -EXPORT_SYMBOL_GPL(wl1251_init_ieee80211); - -struct ieee80211_hw *wl1251_alloc_hw(void) -{ - struct ieee80211_hw *hw; - struct wl1251 *wl; - int i; - static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; - - hw = ieee80211_alloc_hw(sizeof(*wl), &wl1251_ops); - if (!hw) { - wl1251_error("could not alloc ieee80211_hw"); - return ERR_PTR(-ENOMEM); - } - - wl = hw->priv; - memset(wl, 0, sizeof(*wl)); - - wl->hw = hw; - - wl->data_in_count = 0; - - skb_queue_head_init(&wl->tx_queue); - - INIT_WORK(&wl->filter_work, wl1251_filter_work); - wl->channel = WL1251_DEFAULT_CHANNEL; - wl->scanning = false; - wl->default_key = 0; - wl->listen_int = 1; - wl->rx_counter = 0; - wl->rx_handled = 0; - wl->rx_current_buffer = 0; - wl->rx_last_id = 0; - wl->rx_config = WL1251_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1251_DEFAULT_RX_FILTER; - wl->elp = false; - wl->psm = 0; - wl->psm_requested = false; - wl->tx_queue_stopped = false; - wl->power_level = WL1251_DEFAULT_POWER_LEVEL; - wl->beacon_int = WL1251_DEFAULT_BEACON_INT; - wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD; - - for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) - wl->tx_frames[i] = NULL; - - wl->next_tx_complete = 0; - - INIT_WORK(&wl->irq_work, wl1251_irq_work); - INIT_WORK(&wl->tx_work, wl1251_tx_work); - - /* - * In case our MAC address is not correctly set, - * we use a random but Nokia MAC. - */ - memcpy(wl->mac_addr, nokia_oui, 3); - get_random_bytes(wl->mac_addr + 3, 3); - - wl->state = WL1251_STATE_OFF; - mutex_init(&wl->mutex); - - wl->tx_mgmt_frm_rate = DEFAULT_HW_GEN_TX_RATE; - wl->tx_mgmt_frm_mod = DEFAULT_HW_GEN_MODULATION_TYPE; - - wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL); - if (!wl->rx_descriptor) { - wl1251_error("could not allocate memory for rx descriptor"); - ieee80211_free_hw(hw); - return ERR_PTR(-ENOMEM); - } - - return hw; -} -EXPORT_SYMBOL_GPL(wl1251_alloc_hw); - -int wl1251_free_hw(struct wl1251 *wl) -{ - ieee80211_unregister_hw(wl->hw); - - wl1251_debugfs_exit(wl); - - kfree(wl->target_mem_map); - kfree(wl->data_path); - kfree(wl->fw); - wl->fw = NULL; - kfree(wl->nvs); - wl->nvs = NULL; - - kfree(wl->rx_descriptor); - wl->rx_descriptor = NULL; - - ieee80211_free_hw(wl->hw); - - return 0; -} -EXPORT_SYMBOL_GPL(wl1251_free_hw); - -MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo "); -MODULE_ALIAS("spi:wl12xx"); diff --git a/drivers/net/wireless/wl12xx/wl1251_netlink.h b/drivers/net/wireless/wl12xx/wl1251_netlink.h deleted file mode 100644 index ee36695e134e..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_netlink.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_NETLINK_H__ -#define __WL1251_NETLINK_H__ - -int wl1251_nl_register(void); -void wl1251_nl_unregister(void); - -#endif /* __WL1251_NETLINK_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.c b/drivers/net/wireless/wl12xx/wl1251_ps.c deleted file mode 100644 index c53e28727ed4..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_ps.c +++ /dev/null @@ -1,161 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1251_reg.h" -#include "wl1251_ps.h" -#include "wl1251_cmd.h" -#include "wl1251_io.h" - -#define WL1251_WAKEUP_TIMEOUT 2000 - -/* Routines to toggle sleep mode while in ELP */ -void wl1251_ps_elp_sleep(struct wl1251 *wl) -{ - if (wl->elp || !wl->psm) - return; - - wl1251_debug(DEBUG_PSM, "chip to elp"); - - wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); - - wl->elp = true; -} - -int wl1251_ps_elp_wakeup(struct wl1251 *wl) -{ - unsigned long timeout; - u32 elp_reg; - - if (!wl->elp) - return 0; - - wl1251_debug(DEBUG_PSM, "waking up chip from elp"); - - timeout = jiffies + msecs_to_jiffies(WL1251_WAKEUP_TIMEOUT); - - wl1251_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); - - elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); - - /* - * FIXME: we should wait for irq from chip but, as a temporary - * solution to simplify locking, let's poll instead - */ - while (!(elp_reg & ELPCTRL_WLAN_READY)) { - if (time_after(jiffies, timeout)) { - wl1251_error("elp wakeup timeout"); - return -ETIMEDOUT; - } - msleep(1); - elp_reg = wl1251_read32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR); - } - - wl1251_debug(DEBUG_PSM, "wakeup time: %u ms", - jiffies_to_msecs(jiffies) - - (jiffies_to_msecs(timeout) - WL1251_WAKEUP_TIMEOUT)); - - wl->elp = false; - - return 0; -} - -static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable) -{ - int ret; - - if (enable) { - wl1251_debug(DEBUG_PSM, "sleep auth psm/elp"); - - ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP); - if (ret < 0) - return ret; - - wl1251_ps_elp_sleep(wl); - } else { - wl1251_debug(DEBUG_PSM, "sleep auth cam"); - - /* - * When the target is in ELP, we can only - * access the ELP control register. Thus, - * we have to wake the target up before - * changing the power authorization. - */ - - wl1251_ps_elp_wakeup(wl); - - ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM); - if (ret < 0) - return ret; - } - - return 0; -} - -int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) -{ - int ret; - - switch (mode) { - case STATION_POWER_SAVE_MODE: - wl1251_debug(DEBUG_PSM, "entering psm"); - - ret = wl1251_acx_wake_up_conditions(wl, - WAKE_UP_EVENT_DTIM_BITMAP, - wl->listen_int); - if (ret < 0) - return ret; - - ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); - if (ret < 0) - return ret; - - ret = wl1251_ps_set_elp(wl, true); - if (ret < 0) - return ret; - - wl->psm = 1; - break; - case STATION_ACTIVE_MODE: - default: - wl1251_debug(DEBUG_PSM, "leaving psm"); - ret = wl1251_ps_set_elp(wl, false); - if (ret < 0) - return ret; - - ret = wl1251_acx_wake_up_conditions(wl, - WAKE_UP_EVENT_DTIM_BITMAP, - wl->listen_int); - if (ret < 0) - return ret; - - ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - return ret; - - wl->psm = 0; - break; - } - - return ret; -} - diff --git a/drivers/net/wireless/wl12xx/wl1251_ps.h b/drivers/net/wireless/wl12xx/wl1251_ps.h deleted file mode 100644 index db036fe12f25..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_ps.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __WL1251_PS_H__ -#define __WL1251_PS_H__ - -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1251.h" -#include "wl1251_acx.h" - -int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode); -void wl1251_ps_elp_sleep(struct wl1251 *wl); -int wl1251_ps_elp_wakeup(struct wl1251 *wl); - - -#endif /* __WL1251_PS_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_reg.h b/drivers/net/wireless/wl12xx/wl1251_reg.h deleted file mode 100644 index 06e1bd94a739..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_reg.h +++ /dev/null @@ -1,644 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __REG_H__ -#define __REG_H__ - -#include - -#define REGISTERS_BASE 0x00300000 -#define DRPW_BASE 0x00310000 - -#define REGISTERS_DOWN_SIZE 0x00008800 -#define REGISTERS_WORK_SIZE 0x0000b000 - -#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC - -/* ELP register commands */ -#define ELPCTRL_WAKE_UP 0x1 -#define ELPCTRL_WAKE_UP_WLAN_READY 0x5 -#define ELPCTRL_SLEEP 0x0 -/* ELP WLAN_READY bit */ -#define ELPCTRL_WLAN_READY 0x2 - -/* Device Configuration registers*/ -#define SOR_CFG (REGISTERS_BASE + 0x0800) -#define ECPU_CTRL (REGISTERS_BASE + 0x0804) -#define HI_CFG (REGISTERS_BASE + 0x0808) -#define EE_START (REGISTERS_BASE + 0x080C) - -#define CHIP_ID_B (REGISTERS_BASE + 0x5674) - -#define CHIP_ID_1251_PG10 (0x7010101) -#define CHIP_ID_1251_PG11 (0x7020101) -#define CHIP_ID_1251_PG12 (0x7030101) - -#define ENABLE (REGISTERS_BASE + 0x5450) - -/* Power Management registers */ -#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804) -#define ELP_CMD (REGISTERS_BASE + 0x5808) -#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810) -#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814) -#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818) - -#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) - -/* Scratch Pad registers*/ -#define SCR_PAD0 (REGISTERS_BASE + 0x5608) -#define SCR_PAD1 (REGISTERS_BASE + 0x560C) -#define SCR_PAD2 (REGISTERS_BASE + 0x5610) -#define SCR_PAD3 (REGISTERS_BASE + 0x5614) -#define SCR_PAD4 (REGISTERS_BASE + 0x5618) -#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C) -#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) -#define SCR_PAD5 (REGISTERS_BASE + 0x5624) -#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628) -#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) -#define SCR_PAD6 (REGISTERS_BASE + 0x5630) -#define SCR_PAD7 (REGISTERS_BASE + 0x5634) -#define SCR_PAD8 (REGISTERS_BASE + 0x5638) -#define SCR_PAD9 (REGISTERS_BASE + 0x563C) - -/* Spare registers*/ -#define SPARE_A1 (REGISTERS_BASE + 0x0994) -#define SPARE_A2 (REGISTERS_BASE + 0x0998) -#define SPARE_A3 (REGISTERS_BASE + 0x099C) -#define SPARE_A4 (REGISTERS_BASE + 0x09A0) -#define SPARE_A5 (REGISTERS_BASE + 0x09A4) -#define SPARE_A6 (REGISTERS_BASE + 0x09A8) -#define SPARE_A7 (REGISTERS_BASE + 0x09AC) -#define SPARE_A8 (REGISTERS_BASE + 0x09B0) -#define SPARE_B1 (REGISTERS_BASE + 0x5420) -#define SPARE_B2 (REGISTERS_BASE + 0x5424) -#define SPARE_B3 (REGISTERS_BASE + 0x5428) -#define SPARE_B4 (REGISTERS_BASE + 0x542C) -#define SPARE_B5 (REGISTERS_BASE + 0x5430) -#define SPARE_B6 (REGISTERS_BASE + 0x5434) -#define SPARE_B7 (REGISTERS_BASE + 0x5438) -#define SPARE_B8 (REGISTERS_BASE + 0x543C) - -enum wl12xx_acx_int_reg { - ACX_REG_INTERRUPT_TRIG, - ACX_REG_INTERRUPT_TRIG_H, - -/*============================================= - Host Interrupt Mask Register - 32bit (RW) - ------------------------------------------ - Setting a bit in this register masks the - corresponding interrupt to the host. - 0 - RX0 - Rx first dubble buffer Data Interrupt - 1 - TXD - Tx Data Interrupt - 2 - TXXFR - Tx Transfer Interrupt - 3 - RX1 - Rx second dubble buffer Data Interrupt - 4 - RXXFR - Rx Transfer Interrupt - 5 - EVENT_A - Event Mailbox interrupt - 6 - EVENT_B - Event Mailbox interrupt - 7 - WNONHST - Wake On Host Interrupt - 8 - TRACE_A - Debug Trace interrupt - 9 - TRACE_B - Debug Trace interrupt - 10 - CDCMP - Command Complete Interrupt - 11 - - 12 - - 13 - - 14 - ICOMP - Initialization Complete Interrupt - 16 - SG SE - Soft Gemini - Sense enable interrupt - 17 - SG SD - Soft Gemini - Sense disable interrupt - 18 - - - 19 - - - 20 - - - 21- - - Default: 0x0001 -*==============================================*/ - ACX_REG_INTERRUPT_MASK, - -/*============================================= - Host Interrupt Mask Set 16bit, (Write only) - ------------------------------------------ - Setting a bit in this register sets - the corresponding bin in ACX_HINT_MASK register - without effecting the mask - state of other bits (0 = no effect). -==============================================*/ - ACX_REG_HINT_MASK_SET, - -/*============================================= - Host Interrupt Mask Clear 16bit,(Write only) - ------------------------------------------ - Setting a bit in this register clears - the corresponding bin in ACX_HINT_MASK register - without effecting the mask - state of other bits (0 = no effect). -=============================================*/ - ACX_REG_HINT_MASK_CLR, - -/*============================================= - Host Interrupt Status Nondestructive Read - 16bit,(Read only) - ------------------------------------------ - The host can read this register to determine - which interrupts are active. - Reading this register doesn't - effect its content. -=============================================*/ - ACX_REG_INTERRUPT_NO_CLEAR, - -/*============================================= - Host Interrupt Status Clear on Read Register - 16bit,(Read only) - ------------------------------------------ - The host can read this register to determine - which interrupts are active. - Reading this register clears it, - thus making all interrupts inactive. -==============================================*/ - ACX_REG_INTERRUPT_CLEAR, - -/*============================================= - Host Interrupt Acknowledge Register - 16bit,(Write only) - ------------------------------------------ - The host can set individual bits in this - register to clear (acknowledge) the corresp. - interrupt status bits in the HINT_STS_CLR and - HINT_STS_ND registers, thus making the - assotiated interrupt inactive. (0-no effect) -==============================================*/ - ACX_REG_INTERRUPT_ACK, - -/*=============================================== - Host Software Reset - 32bit RW - ------------------------------------------ - [31:1] Reserved - 0 SOFT_RESET Soft Reset - When this bit is set, - it holds the Wlan hardware in a soft reset state. - This reset disables all MAC and baseband processor - clocks except the CardBus/PCI interface clock. - It also initializes all MAC state machines except - the host interface. It does not reload the - contents of the EEPROM. When this bit is cleared - (not self-clearing), the Wlan hardware - exits the software reset state. -===============================================*/ - ACX_REG_SLV_SOFT_RESET, - -/*=============================================== - EEPROM Burst Read Start - 32bit RW - ------------------------------------------ - [31:1] Reserved - 0 ACX_EE_START - EEPROM Burst Read Start 0 - Setting this bit starts a burst read from - the external EEPROM. - If this bit is set (after reset) before an EEPROM read/write, - the burst read starts at EEPROM address 0. - Otherwise, it starts at the address - following the address of the previous access. - TheWlan hardware hardware clears this bit automatically. - - Default: 0x00000000 -*================================================*/ - ACX_REG_EE_START, - -/* Embedded ARM CPU Control */ - -/*=============================================== - Halt eCPU - 32bit RW - ------------------------------------------ - 0 HALT_ECPU Halt Embedded CPU - This bit is the - compliment of bit 1 (MDATA2) in the SOR_CFG register. - During a hardware reset, this bit holds - the inverse of MDATA2. - When downloading firmware from the host, - set this bit (pull down MDATA2). - The host clears this bit after downloading the firmware into - zero-wait-state SSRAM. - When loading firmware from Flash, clear this bit (pull up MDATA2) - so that the eCPU can run the bootloader code in Flash - HALT_ECPU eCPU State - -------------------- - 1 halt eCPU - 0 enable eCPU - ===============================================*/ - ACX_REG_ECPU_CONTROL, - - ACX_REG_TABLE_LEN -}; - -#define ACX_SLV_SOFT_RESET_BIT BIT(0) -#define ACX_REG_EEPROM_START_BIT BIT(0) - -/* Command/Information Mailbox Pointers */ - -/*=============================================== - Command Mailbox Pointer - 32bit RW - ------------------------------------------ - This register holds the start address of - the command mailbox located in the Wlan hardware memory. - The host must read this pointer after a reset to - find the location of the command mailbox. - The Wlan hardware initializes the command mailbox - pointer with the default address of the command mailbox. - The command mailbox pointer is not valid until after - the host receives the Init Complete interrupt from - the Wlan hardware. - ===============================================*/ -#define REG_COMMAND_MAILBOX_PTR (SCR_PAD0) - -/*=============================================== - Information Mailbox Pointer - 32bit RW - ------------------------------------------ - This register holds the start address of - the information mailbox located in the Wlan hardware memory. - The host must read this pointer after a reset to find - the location of the information mailbox. - The Wlan hardware initializes the information mailbox pointer - with the default address of the information mailbox. - The information mailbox pointer is not valid - until after the host receives the Init Complete interrupt from - the Wlan hardware. - ===============================================*/ -#define REG_EVENT_MAILBOX_PTR (SCR_PAD1) - - -/* Misc */ - -#define REG_ENABLE_TX_RX (ENABLE) -/* - * Rx configuration (filter) information element - * --------------------------------------------- - */ -#define REG_RX_CONFIG (RX_CFG) -#define REG_RX_FILTER (RX_FILTER_CFG) - - -#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002 - -/* promiscuous - receives all valid frames */ -#define RX_CFG_PROMISCUOUS 0x0008 - -/* receives frames from any BSSID */ -#define RX_CFG_BSSID 0x0020 - -/* receives frames destined to any MAC address */ -#define RX_CFG_MAC 0x0010 - -#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010 -#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000 -#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020 -#define RX_CFG_ENABLE_ANY_BSSID 0x0000 - -/* discards all broadcast frames */ -#define RX_CFG_DISABLE_BCAST 0x0200 - -#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400 -#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800 -#define RX_CFG_COPY_RX_STATUS 0x2000 -#define RX_CFG_TSF 0x10000 - -#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ - RX_CFG_ENABLE_ONLY_MY_BSSID) - -#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ - | RX_CFG_ENABLE_ANY_BSSID) - -#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ - RX_CFG_ENABLE_ANY_BSSID) - -#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ - | RX_CFG_ENABLE_ONLY_MY_BSSID) - -#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \ - | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \ - | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF) - -#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC) - -#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \ - RX_CFG_ENABLE_ONLY_MY_DEST_MAC) - -#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \ - RX_CFG_ENABLE_ONLY_MY_DEST_MAC) - -#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ - | CFG_RX_CTL_EN | CFG_RX_BCN_EN\ - | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) - -#define RX_FILTER_OPTION_FILTER_ALL 0 - -#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\ - | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN) - -#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ - | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\ - | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\ - | CFG_RX_PRSP_EN) - - -/*=============================================== - EEPROM Read/Write Request 32bit RW - ------------------------------------------ - 1 EE_READ - EEPROM Read Request 1 - Setting this bit - loads a single byte of data into the EE_DATA - register from the EEPROM location specified in - the EE_ADDR register. - The Wlan hardware hardware clears this bit automatically. - EE_DATA is valid when this bit is cleared. - - 0 EE_WRITE - EEPROM Write Request - Setting this bit - writes a single byte of data from the EE_DATA register into the - EEPROM location specified in the EE_ADDR register. - The Wlan hardware hardware clears this bit automatically. -*===============================================*/ -#define ACX_EE_CTL_REG EE_CTL -#define EE_WRITE 0x00000001ul -#define EE_READ 0x00000002ul - -/*=============================================== - EEPROM Address - 32bit RW - ------------------------------------------ - This register specifies the address - within the EEPROM from/to which to read/write data. - ===============================================*/ -#define ACX_EE_ADDR_REG EE_ADDR - -/*=============================================== - EEPROM Data - 32bit RW - ------------------------------------------ - This register either holds the read 8 bits of - data from the EEPROM or the write data - to be written to the EEPROM. - ===============================================*/ -#define ACX_EE_DATA_REG EE_DATA - -/*=============================================== - EEPROM Base Address - 32bit RW - ------------------------------------------ - This register holds the upper nine bits - [23:15] of the 24-bit Wlan hardware memory - address for burst reads from EEPROM accesses. - The EEPROM provides the lower 15 bits of this address. - The MSB of the address from the EEPROM is ignored. - ===============================================*/ -#define ACX_EE_CFG EE_CFG - -/*=============================================== - GPIO Output Values -32bit, RW - ------------------------------------------ - [31:16] Reserved - [15: 0] Specify the output values (at the output driver inputs) for - GPIO[15:0], respectively. - ===============================================*/ -#define ACX_GPIO_OUT_REG GPIO_OUT -#define ACX_MAX_GPIO_LINES 15 - -/*=============================================== - Contention window -32bit, RW - ------------------------------------------ - [31:26] Reserved - [25:16] Max (0x3ff) - [15:07] Reserved - [06:00] Current contention window value - default is 0x1F - ===============================================*/ -#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG -#define ACX_CONT_WIND_MIN_MASK 0x0000007f -#define ACX_CONT_WIND_MAX 0x03ff0000 - -/*=============================================== - HI_CFG Interface Configuration Register Values - ------------------------------------------ - ===============================================*/ -#define HI_CFG_UART_ENABLE 0x00000004 -#define HI_CFG_RST232_ENABLE 0x00000008 -#define HI_CFG_CLOCK_REQ_SELECT 0x00000010 -#define HI_CFG_HOST_INT_ENABLE 0x00000020 -#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 -#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 -#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 -#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 -#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 - -/* - * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile - * for platforms using active high interrupt level - */ -#ifdef USE_ACTIVE_HIGH -#define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) -#else -#define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) - -#endif - -#define REF_FREQ_19_2 0 -#define REF_FREQ_26_0 1 -#define REF_FREQ_38_4 2 -#define REF_FREQ_40_0 3 -#define REF_FREQ_33_6 4 -#define REF_FREQ_NUM 5 - -#define LUT_PARAM_INTEGER_DIVIDER 0 -#define LUT_PARAM_FRACTIONAL_DIVIDER 1 -#define LUT_PARAM_ATTN_BB 2 -#define LUT_PARAM_ALPHA_BB 3 -#define LUT_PARAM_STOP_TIME_BB 4 -#define LUT_PARAM_BB_PLL_LOOP_FILTER 5 -#define LUT_PARAM_NUM 6 - -#define ACX_EEPROMLESS_IND_REG (SCR_PAD4) -#define USE_EEPROM 0 -#define SOFT_RESET_MAX_TIME 1000000 -#define SOFT_RESET_STALL_TIME 1000 -#define NVS_DATA_BUNDARY_ALIGNMENT 4 - - -/* Firmware image load chunk size */ -#define CHUNK_SIZE 512 - -/* Firmware image header size */ -#define FW_HDR_SIZE 8 - -#define ECPU_CONTROL_HALT 0x00000101 - - -/****************************************************************************** - - CHANNELS, BAND & REG DOMAINS definitions - -******************************************************************************/ - - -enum { - RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */ - RADIO_BAND_5GHZ = 1, /* 5 Ghz band */ - RADIO_BAND_JAPAN_4_9_GHZ = 2, - DEFAULT_BAND = RADIO_BAND_2_4GHZ, - INVALID_BAND = 0xFE, - MAX_RADIO_BANDS = 0xFF -}; - -enum { - NO_RATE = 0, - RATE_1MBPS = 0x0A, - RATE_2MBPS = 0x14, - RATE_5_5MBPS = 0x37, - RATE_6MBPS = 0x0B, - RATE_9MBPS = 0x0F, - RATE_11MBPS = 0x6E, - RATE_12MBPS = 0x0A, - RATE_18MBPS = 0x0E, - RATE_22MBPS = 0xDC, - RATE_24MBPS = 0x09, - RATE_36MBPS = 0x0D, - RATE_48MBPS = 0x08, - RATE_54MBPS = 0x0C -}; - -enum { - RATE_INDEX_1MBPS = 0, - RATE_INDEX_2MBPS = 1, - RATE_INDEX_5_5MBPS = 2, - RATE_INDEX_6MBPS = 3, - RATE_INDEX_9MBPS = 4, - RATE_INDEX_11MBPS = 5, - RATE_INDEX_12MBPS = 6, - RATE_INDEX_18MBPS = 7, - RATE_INDEX_22MBPS = 8, - RATE_INDEX_24MBPS = 9, - RATE_INDEX_36MBPS = 10, - RATE_INDEX_48MBPS = 11, - RATE_INDEX_54MBPS = 12, - RATE_INDEX_MAX = RATE_INDEX_54MBPS, - MAX_RATE_INDEX, - INVALID_RATE_INDEX = MAX_RATE_INDEX, - RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF -}; - -enum { - RATE_MASK_1MBPS = 0x1, - RATE_MASK_2MBPS = 0x2, - RATE_MASK_5_5MBPS = 0x4, - RATE_MASK_11MBPS = 0x20, -}; - -#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ -#define OFDM_RATE_BIT BIT(6) -#define PBCC_RATE_BIT BIT(7) - -enum { - CCK_LONG = 0, - CCK_SHORT = SHORT_PREAMBLE_BIT, - PBCC_LONG = PBCC_RATE_BIT, - PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT, - OFDM = OFDM_RATE_BIT -}; - -/****************************************************************************** - -Transmit-Descriptor RATE-SET field definitions... - -Define a new "Rate-Set" for TX path that incorporates the -Rate & Modulation info into a single 16-bit field. - -TxdRateSet_t: -b15 - Indicates Preamble type (1=SHORT, 0=LONG). - Notes: - Must be LONG (0) for 1Mbps rate. - Does not apply (set to 0) for RevG-OFDM rates. -b14 - Indicates PBCC encoding (1=PBCC, 0=not). - Notes: - Does not apply (set to 0) for rates 1 and 2 Mbps. - Does not apply (set to 0) for RevG-OFDM rates. -b13 - Unused (set to 0). -b12-b0 - Supported Rate indicator bits as defined below. - -******************************************************************************/ - - -/************************************************************************* - - Interrupt Trigger Register (Host -> WiLink) - -**************************************************************************/ - -/* Hardware to Embedded CPU Interrupts - first 32-bit register set */ - -/* - * Host Command Interrupt. Setting this bit masks - * the interrupt that the host issues to inform - * the FW that it has sent a command - * to the Wlan hardware Command Mailbox. - */ -#define INTR_TRIG_CMD BIT(0) - -/* - * Host Event Acknowlegde Interrupt. The host - * sets this bit to acknowledge that it received - * the unsolicited information from the event - * mailbox. - */ -#define INTR_TRIG_EVENT_ACK BIT(1) - -/* - * The host sets this bit to inform the Wlan - * FW that a TX packet is in the XFER - * Buffer #0. - */ -#define INTR_TRIG_TX_PROC0 BIT(2) - -/* - * The host sets this bit to inform the FW - * that it read a packet from RX XFER - * Buffer #0. - */ -#define INTR_TRIG_RX_PROC0 BIT(3) - -#define INTR_TRIG_DEBUG_ACK BIT(4) - -#define INTR_TRIG_STATE_CHANGED BIT(5) - - -/* Hardware to Embedded CPU Interrupts - second 32-bit register set */ - -/* - * The host sets this bit to inform the FW - * that it read a packet from RX XFER - * Buffer #1. - */ -#define INTR_TRIG_RX_PROC1 BIT(17) - -/* - * The host sets this bit to inform the Wlan - * hardware that a TX packet is in the XFER - * Buffer #1. - */ -#define INTR_TRIG_TX_PROC1 BIT(18) - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.c b/drivers/net/wireless/wl12xx/wl1251_rx.c deleted file mode 100644 index 17c54b59ef86..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_rx.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_io.h" -#include "wl1251_rx.h" -#include "wl1251_cmd.h" -#include "wl1251_acx.h" - -static void wl1251_rx_header(struct wl1251 *wl, - struct wl1251_rx_descriptor *desc) -{ - u32 rx_packet_ring_addr; - - rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr; - if (wl->rx_current_buffer) - rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; - - wl1251_mem_read(wl, rx_packet_ring_addr, desc, sizeof(*desc)); -} - -static void wl1251_rx_status(struct wl1251 *wl, - struct wl1251_rx_descriptor *desc, - struct ieee80211_rx_status *status, - u8 beacon) -{ - u64 mactime; - int ret; - - memset(status, 0, sizeof(struct ieee80211_rx_status)); - - status->band = IEEE80211_BAND_2GHZ; - status->mactime = desc->timestamp; - - /* - * The rx status timestamp is a 32 bits value while the TSF is a - * 64 bits one. - * For IBSS merging, TSF is mandatory, so we have to get it - * somehow, so we ask for ACX_TSF_INFO. - * That could be moved to the get_tsf() hook, but unfortunately, - * this one must be atomic, while our SPI routines can sleep. - */ - if ((wl->bss_type == BSS_TYPE_IBSS) && beacon) { - ret = wl1251_acx_tsf_info(wl, &mactime); - if (ret == 0) - status->mactime = mactime; - } - - status->signal = desc->rssi; - status->qual = (desc->rssi - WL1251_RX_MIN_RSSI) * 100 / - (WL1251_RX_MAX_RSSI - WL1251_RX_MIN_RSSI); - status->qual = min(status->qual, 100); - status->qual = max(status->qual, 0); - - /* - * FIXME: guessing that snr needs to be divided by two, otherwise - * the values don't make any sense - */ - status->noise = desc->rssi - desc->snr / 2; - - status->freq = ieee80211_channel_to_frequency(desc->channel); - - status->flag |= RX_FLAG_TSFT; - - if (desc->flags & RX_DESC_ENCRYPTION_MASK) { - status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; - - if (likely(!(desc->flags & RX_DESC_DECRYPT_FAIL))) - status->flag |= RX_FLAG_DECRYPTED; - - if (unlikely(desc->flags & RX_DESC_MIC_FAIL)) - status->flag |= RX_FLAG_MMIC_ERROR; - } - - if (unlikely(!(desc->flags & RX_DESC_VALID_FCS))) - status->flag |= RX_FLAG_FAILED_FCS_CRC; - - - /* FIXME: set status->rate_idx */ -} - -static void wl1251_rx_body(struct wl1251 *wl, - struct wl1251_rx_descriptor *desc) -{ - struct sk_buff *skb; - struct ieee80211_rx_status status; - u8 *rx_buffer, beacon = 0; - u16 length, *fc; - u32 curr_id, last_id_inc, rx_packet_ring_addr; - - length = WL1251_RX_ALIGN(desc->length - PLCP_HEADER_LENGTH); - curr_id = (desc->flags & RX_DESC_SEQNUM_MASK) >> RX_DESC_PACKETID_SHIFT; - last_id_inc = (wl->rx_last_id + 1) % (RX_MAX_PACKET_ID + 1); - - if (last_id_inc != curr_id) { - wl1251_warning("curr ID:%d, last ID inc:%d", - curr_id, last_id_inc); - wl->rx_last_id = curr_id; - } else { - wl->rx_last_id = last_id_inc; - } - - rx_packet_ring_addr = wl->data_path->rx_packet_ring_addr + - sizeof(struct wl1251_rx_descriptor) + 20; - if (wl->rx_current_buffer) - rx_packet_ring_addr += wl->data_path->rx_packet_ring_chunk_size; - - skb = dev_alloc_skb(length); - if (!skb) { - wl1251_error("Couldn't allocate RX frame"); - return; - } - - rx_buffer = skb_put(skb, length); - wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length); - - /* The actual lenght doesn't include the target's alignment */ - skb->len = desc->length - PLCP_HEADER_LENGTH; - - fc = (u16 *)skb->data; - - if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) - beacon = 1; - - wl1251_rx_status(wl, desc, &status, beacon); - - wl1251_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, - beacon ? "beacon" : ""); - - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx(wl->hw, skb); -} - -static void wl1251_rx_ack(struct wl1251 *wl) -{ - u32 data, addr; - - if (wl->rx_current_buffer) { - addr = ACX_REG_INTERRUPT_TRIG_H; - data = INTR_TRIG_RX_PROC1; - } else { - addr = ACX_REG_INTERRUPT_TRIG; - data = INTR_TRIG_RX_PROC0; - } - - wl1251_reg_write32(wl, addr, data); - - /* Toggle buffer ring */ - wl->rx_current_buffer = !wl->rx_current_buffer; -} - - -void wl1251_rx(struct wl1251 *wl) -{ - struct wl1251_rx_descriptor *rx_desc; - - if (wl->state != WL1251_STATE_ON) - return; - - rx_desc = wl->rx_descriptor; - - /* We first read the frame's header */ - wl1251_rx_header(wl, rx_desc); - - /* Now we can read the body */ - wl1251_rx_body(wl, rx_desc); - - /* Finally, we need to ACK the RX */ - wl1251_rx_ack(wl); - - return; -} diff --git a/drivers/net/wireless/wl12xx/wl1251_rx.h b/drivers/net/wireless/wl12xx/wl1251_rx.h deleted file mode 100644 index 563a3fde40fb..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_rx.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_RX_H__ -#define __WL1251_RX_H__ - -#include - -#include "wl1251.h" - -/* - * RX PATH - * - * The Rx path uses a double buffer and an rx_contro structure, each located - * at a fixed address in the device memory. The host keeps track of which - * buffer is available and alternates between them on a per packet basis. - * The size of each of the two buffers is large enough to hold the longest - * 802.3 packet. - * The RX path goes like that: - * 1) The target generates an interrupt each time a new packet is received. - * There are 2 RX interrupts, one for each buffer. - * 2) The host reads the received packet from one of the double buffers. - * 3) The host triggers a target interrupt. - * 4) The target prepares the next RX packet. - */ - -#define WL1251_RX_MAX_RSSI -30 -#define WL1251_RX_MIN_RSSI -95 - -#define WL1251_RX_ALIGN_TO 4 -#define WL1251_RX_ALIGN(len) (((len) + WL1251_RX_ALIGN_TO - 1) & \ - ~(WL1251_RX_ALIGN_TO - 1)) - -#define SHORT_PREAMBLE_BIT BIT(0) -#define OFDM_RATE_BIT BIT(6) -#define PBCC_RATE_BIT BIT(7) - -#define PLCP_HEADER_LENGTH 8 -#define RX_DESC_PACKETID_SHIFT 11 -#define RX_MAX_PACKET_ID 3 - -#define RX_DESC_VALID_FCS 0x0001 -#define RX_DESC_MATCH_RXADDR1 0x0002 -#define RX_DESC_MCAST 0x0004 -#define RX_DESC_STAINTIM 0x0008 -#define RX_DESC_VIRTUAL_BM 0x0010 -#define RX_DESC_BCAST 0x0020 -#define RX_DESC_MATCH_SSID 0x0040 -#define RX_DESC_MATCH_BSSID 0x0080 -#define RX_DESC_ENCRYPTION_MASK 0x0300 -#define RX_DESC_MEASURMENT 0x0400 -#define RX_DESC_SEQNUM_MASK 0x1800 -#define RX_DESC_MIC_FAIL 0x2000 -#define RX_DESC_DECRYPT_FAIL 0x4000 - -struct wl1251_rx_descriptor { - u32 timestamp; /* In microseconds */ - u16 length; /* Paylod length, including headers */ - u16 flags; - - /* - * 0 - 802.11 - * 1 - 802.3 - * 2 - IP - * 3 - Raw Codec - */ - u8 type; - - /* - * Received Rate: - * 0x0A - 1MBPS - * 0x14 - 2MBPS - * 0x37 - 5_5MBPS - * 0x0B - 6MBPS - * 0x0F - 9MBPS - * 0x6E - 11MBPS - * 0x0A - 12MBPS - * 0x0E - 18MBPS - * 0xDC - 22MBPS - * 0x09 - 24MBPS - * 0x0D - 36MBPS - * 0x08 - 48MBPS - * 0x0C - 54MBPS - */ - u8 rate; - - u8 mod_pre; /* Modulation and preamble */ - u8 channel; - - /* - * 0 - 2.4 Ghz - * 1 - 5 Ghz - */ - u8 band; - - s8 rssi; /* in dB */ - u8 rcpi; /* in dB */ - u8 snr; /* in dB */ -} __attribute__ ((packed)); - -void wl1251_rx(struct wl1251 *wl); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1251_sdio.c b/drivers/net/wireless/wl12xx/wl1251_sdio.c deleted file mode 100644 index d74b89bbda83..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_sdio.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * wl12xx SDIO routines - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - * Copyright (C) 2005 Texas Instruments Incorporated - * Copyright (C) 2008 Google Inc - * Copyright (C) 2009 Bob Copeland (me@bobcopeland.com) - */ -#include -#include -#include -#include -#include -#include -#include - -#include "wl1251.h" -#include "wl12xx_80211.h" -#include "wl1251_reg.h" -#include "wl1251_ps.h" -#include "wl1251_io.h" -#include "wl1251_tx.h" -#include "wl1251_debugfs.h" - -#ifndef SDIO_VENDOR_ID_TI -#define SDIO_VENDOR_ID_TI 0x104c -#endif - -#ifndef SDIO_DEVICE_ID_TI_WL1251 -#define SDIO_DEVICE_ID_TI_WL1251 0x9066 -#endif - -static struct sdio_func *wl_to_func(struct wl1251 *wl) -{ - return wl->if_priv; -} - -static void wl1251_sdio_interrupt(struct sdio_func *func) -{ - struct wl1251 *wl = sdio_get_drvdata(func); - - wl1251_debug(DEBUG_IRQ, "IRQ"); - - /* FIXME should be synchronous for sdio */ - ieee80211_queue_work(wl->hw, &wl->irq_work); -} - -static const struct sdio_device_id wl1251_devices[] = { - { SDIO_DEVICE(SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1251) }, - {} -}; -MODULE_DEVICE_TABLE(sdio, wl1251_devices); - - -void wl1251_sdio_read(struct wl1251 *wl, int addr, void *buf, size_t len) -{ - int ret; - struct sdio_func *func = wl_to_func(wl); - - sdio_claim_host(func); - ret = sdio_memcpy_fromio(func, buf, addr, len); - if (ret) - wl1251_error("sdio read failed (%d)", ret); - sdio_release_host(func); -} - -void wl1251_sdio_write(struct wl1251 *wl, int addr, void *buf, size_t len) -{ - int ret; - struct sdio_func *func = wl_to_func(wl); - - sdio_claim_host(func); - ret = sdio_memcpy_toio(func, addr, buf, len); - if (ret) - wl1251_error("sdio write failed (%d)", ret); - sdio_release_host(func); -} - -void wl1251_sdio_reset(struct wl1251 *wl) -{ -} - -static void wl1251_sdio_enable_irq(struct wl1251 *wl) -{ - struct sdio_func *func = wl_to_func(wl); - - sdio_claim_host(func); - sdio_claim_irq(func, wl1251_sdio_interrupt); - sdio_release_host(func); -} - -static void wl1251_sdio_disable_irq(struct wl1251 *wl) -{ - struct sdio_func *func = wl_to_func(wl); - - sdio_claim_host(func); - sdio_release_irq(func); - sdio_release_host(func); -} - -void wl1251_sdio_set_power(bool enable) -{ -} - -struct wl1251_if_operations wl1251_sdio_ops = { - .read = wl1251_sdio_read, - .write = wl1251_sdio_write, - .reset = wl1251_sdio_reset, - .enable_irq = wl1251_sdio_enable_irq, - .disable_irq = wl1251_sdio_disable_irq, -}; - -int wl1251_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) -{ - int ret; - struct wl1251 *wl; - struct ieee80211_hw *hw; - - hw = wl1251_alloc_hw(); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - wl = hw->priv; - - sdio_claim_host(func); - ret = sdio_enable_func(func); - if (ret) - goto release; - - sdio_set_block_size(func, 512); - - SET_IEEE80211_DEV(hw, &func->dev); - wl->if_priv = func; - wl->if_ops = &wl1251_sdio_ops; - wl->set_power = wl1251_sdio_set_power; - - sdio_release_host(func); - ret = wl1251_init_ieee80211(wl); - if (ret) - goto disable; - - sdio_set_drvdata(func, wl); - return ret; - -disable: - sdio_claim_host(func); - sdio_disable_func(func); -release: - sdio_release_host(func); - wl1251_free_hw(wl); - return ret; -} - -static void __devexit wl1251_sdio_remove(struct sdio_func *func) -{ - struct wl1251 *wl = sdio_get_drvdata(func); - - wl1251_free_hw(wl); - - sdio_claim_host(func); - sdio_release_irq(func); - sdio_disable_func(func); - sdio_release_host(func); -} - -static struct sdio_driver wl1251_sdio_driver = { - .name = "wl1251_sdio", - .id_table = wl1251_devices, - .probe = wl1251_sdio_probe, - .remove = __devexit_p(wl1251_sdio_remove), -}; - -static int __init wl1251_sdio_init(void) -{ - int err; - - err = sdio_register_driver(&wl1251_sdio_driver); - if (err) - wl1251_error("failed to register sdio driver: %d", err); - return err; -} - -static void __exit wl1251_sdio_exit(void) -{ - sdio_unregister_driver(&wl1251_sdio_driver); - wl1251_notice("unloaded"); -} - -module_init(wl1251_sdio_init); -module_exit(wl1251_sdio_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo "); diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.c b/drivers/net/wireless/wl12xx/wl1251_spi.c deleted file mode 100644 index 14eff2b3d4c6..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_spi.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_spi.h" - -static irqreturn_t wl1251_irq(int irq, void *cookie) -{ - struct wl1251 *wl; - - wl1251_debug(DEBUG_IRQ, "IRQ"); - - wl = cookie; - - ieee80211_queue_work(wl->hw, &wl->irq_work); - - return IRQ_HANDLED; -} - -static struct spi_device *wl_to_spi(struct wl1251 *wl) -{ - return wl->if_priv; -} - -static void wl1251_spi_reset(struct wl1251 *wl) -{ - u8 *cmd; - struct spi_transfer t; - struct spi_message m; - - cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); - if (!cmd) { - wl1251_error("could not allocate cmd for spi reset"); - return; - } - - memset(&t, 0, sizeof(t)); - spi_message_init(&m); - - memset(cmd, 0xff, WSPI_INIT_CMD_LEN); - - t.tx_buf = cmd; - t.len = WSPI_INIT_CMD_LEN; - spi_message_add_tail(&t, &m); - - spi_sync(wl_to_spi(wl), &m); - - wl1251_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); -} - -static void wl1251_spi_wake(struct wl1251 *wl) -{ - u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; - struct spi_transfer t; - struct spi_message m; - - cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); - if (!cmd) { - wl1251_error("could not allocate cmd for spi init"); - return; - } - - memset(crc, 0, sizeof(crc)); - memset(&t, 0, sizeof(t)); - spi_message_init(&m); - - /* - * Set WSPI_INIT_COMMAND - * the data is being send from the MSB to LSB - */ - cmd[2] = 0xff; - cmd[3] = 0xff; - cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; - cmd[0] = 0; - cmd[7] = 0; - cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; - cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; - - if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) - cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; - else - cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; - - cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS - | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; - - crc[0] = cmd[1]; - crc[1] = cmd[0]; - crc[2] = cmd[7]; - crc[3] = cmd[6]; - crc[4] = cmd[5]; - - cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; - cmd[4] |= WSPI_INIT_CMD_END; - - t.tx_buf = cmd; - t.len = WSPI_INIT_CMD_LEN; - spi_message_add_tail(&t, &m); - - spi_sync(wl_to_spi(wl), &m); - - wl1251_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); -} - -static void wl1251_spi_reset_wake(struct wl1251 *wl) -{ - wl1251_spi_reset(wl); - wl1251_spi_wake(wl); -} - -static void wl1251_spi_read(struct wl1251 *wl, int addr, void *buf, - size_t len) -{ - struct spi_transfer t[3]; - struct spi_message m; - u8 *busy_buf; - u32 *cmd; - - cmd = &wl->buffer_cmd; - busy_buf = wl->buffer_busyword; - - *cmd = 0; - *cmd |= WSPI_CMD_READ; - *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; - *cmd |= addr & WSPI_CMD_BYTE_ADDR; - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = cmd; - t[0].len = 4; - spi_message_add_tail(&t[0], &m); - - /* Busy and non busy words read */ - t[1].rx_buf = busy_buf; - t[1].len = WL1251_BUSY_WORD_LEN; - spi_message_add_tail(&t[1], &m); - - t[2].rx_buf = buf; - t[2].len = len; - spi_message_add_tail(&t[2], &m); - - spi_sync(wl_to_spi(wl), &m); - - /* FIXME: check busy words */ - - wl1251_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); - wl1251_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); -} - -static void wl1251_spi_write(struct wl1251 *wl, int addr, void *buf, - size_t len) -{ - struct spi_transfer t[2]; - struct spi_message m; - u32 *cmd; - - cmd = &wl->buffer_cmd; - - *cmd = 0; - *cmd |= WSPI_CMD_WRITE; - *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; - *cmd |= addr & WSPI_CMD_BYTE_ADDR; - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = cmd; - t[0].len = sizeof(*cmd); - spi_message_add_tail(&t[0], &m); - - t[1].tx_buf = buf; - t[1].len = len; - spi_message_add_tail(&t[1], &m); - - spi_sync(wl_to_spi(wl), &m); - - wl1251_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); - wl1251_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); -} - -static void wl1251_spi_enable_irq(struct wl1251 *wl) -{ - return enable_irq(wl->irq); -} - -static void wl1251_spi_disable_irq(struct wl1251 *wl) -{ - return disable_irq(wl->irq); -} - -static const struct wl1251_if_operations wl1251_spi_ops = { - .read = wl1251_spi_read, - .write = wl1251_spi_write, - .reset = wl1251_spi_reset_wake, - .enable_irq = wl1251_spi_enable_irq, - .disable_irq = wl1251_spi_disable_irq, -}; - -static int __devinit wl1251_spi_probe(struct spi_device *spi) -{ - struct wl12xx_platform_data *pdata; - struct ieee80211_hw *hw; - struct wl1251 *wl; - int ret; - - pdata = spi->dev.platform_data; - if (!pdata) { - wl1251_error("no platform data"); - return -ENODEV; - } - - hw = wl1251_alloc_hw(); - if (IS_ERR(hw)) - return PTR_ERR(hw); - - wl = hw->priv; - - SET_IEEE80211_DEV(hw, &spi->dev); - dev_set_drvdata(&spi->dev, wl); - wl->if_priv = spi; - wl->if_ops = &wl1251_spi_ops; - - /* This is the only SPI value that we need to set here, the rest - * comes from the board-peripherals file */ - spi->bits_per_word = 32; - - ret = spi_setup(spi); - if (ret < 0) { - wl1251_error("spi_setup failed"); - goto out_free; - } - - wl->set_power = pdata->set_power; - if (!wl->set_power) { - wl1251_error("set power function missing in platform data"); - return -ENODEV; - } - - wl->irq = spi->irq; - if (wl->irq < 0) { - wl1251_error("irq missing in platform data"); - return -ENODEV; - } - - ret = request_irq(wl->irq, wl1251_irq, 0, DRIVER_NAME, wl); - if (ret < 0) { - wl1251_error("request_irq() failed: %d", ret); - goto out_free; - } - - set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - - disable_irq(wl->irq); - - ret = wl1251_init_ieee80211(wl); - if (ret) - goto out_irq; - - return 0; - - out_irq: - free_irq(wl->irq, wl); - - out_free: - ieee80211_free_hw(hw); - - return ret; -} - -static int __devexit wl1251_spi_remove(struct spi_device *spi) -{ - struct wl1251 *wl = dev_get_drvdata(&spi->dev); - - free_irq(wl->irq, wl); - wl1251_free_hw(wl); - - return 0; -} - -static struct spi_driver wl1251_spi_driver = { - .driver = { - .name = "wl12xx", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = wl1251_spi_probe, - .remove = __devexit_p(wl1251_spi_remove), -}; - -static int __init wl1251_spi_init(void) -{ - int ret; - - ret = spi_register_driver(&wl1251_spi_driver); - if (ret < 0) { - wl1251_error("failed to register spi driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit wl1251_spi_exit(void) -{ - spi_unregister_driver(&wl1251_spi_driver); - - wl1251_notice("unloaded"); -} - -module_init(wl1251_spi_init); -module_exit(wl1251_spi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Kalle Valo "); diff --git a/drivers/net/wireless/wl12xx/wl1251_spi.h b/drivers/net/wireless/wl12xx/wl1251_spi.h deleted file mode 100644 index 2e273a97e7f3..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_spi.h +++ /dev/null @@ -1,61 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_SPI_H__ -#define __WL1251_SPI_H__ - -#include "wl1251_cmd.h" -#include "wl1251_acx.h" -#include "wl1251_reg.h" - -#define WSPI_CMD_READ 0x40000000 -#define WSPI_CMD_WRITE 0x00000000 -#define WSPI_CMD_FIXED 0x20000000 -#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 -#define WSPI_CMD_BYTE_LENGTH_OFFSET 17 -#define WSPI_CMD_BYTE_ADDR 0x0001FFFF - -#define WSPI_INIT_CMD_CRC_LEN 5 - -#define WSPI_INIT_CMD_START 0x00 -#define WSPI_INIT_CMD_TX 0x40 -/* the extra bypass bit is sampled by the TNET as '1' */ -#define WSPI_INIT_CMD_BYPASS_BIT 0x80 -#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 -#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 -#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 -#define WSPI_INIT_CMD_IOD 0x40 -#define WSPI_INIT_CMD_IP 0x20 -#define WSPI_INIT_CMD_CS 0x10 -#define WSPI_INIT_CMD_WS 0x08 -#define WSPI_INIT_CMD_WSPI 0x01 -#define WSPI_INIT_CMD_END 0x01 - -#define WSPI_INIT_CMD_LEN 8 - -#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ - ((WL1251_BUSY_WORD_LEN - 4) / sizeof(u32)) -#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 - -#endif /* __WL1251_SPI_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.c b/drivers/net/wireless/wl12xx/wl1251_tx.c deleted file mode 100644 index f85970615849..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_tx.c +++ /dev/null @@ -1,559 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - -#include "wl1251.h" -#include "wl1251_reg.h" -#include "wl1251_tx.h" -#include "wl1251_ps.h" -#include "wl1251_io.h" - -static bool wl1251_tx_double_buffer_busy(struct wl1251 *wl, u32 data_out_count) -{ - int used, data_in_count; - - data_in_count = wl->data_in_count; - - if (data_in_count < data_out_count) - /* data_in_count has wrapped */ - data_in_count += TX_STATUS_DATA_OUT_COUNT_MASK + 1; - - used = data_in_count - data_out_count; - - WARN_ON(used < 0); - WARN_ON(used > DP_TX_PACKET_RING_CHUNK_NUM); - - if (used >= DP_TX_PACKET_RING_CHUNK_NUM) - return true; - else - return false; -} - -static int wl1251_tx_path_status(struct wl1251 *wl) -{ - u32 status, addr, data_out_count; - bool busy; - - addr = wl->data_path->tx_control_addr; - status = wl1251_mem_read32(wl, addr); - data_out_count = status & TX_STATUS_DATA_OUT_COUNT_MASK; - busy = wl1251_tx_double_buffer_busy(wl, data_out_count); - - if (busy) - return -EBUSY; - - return 0; -} - -static int wl1251_tx_id(struct wl1251 *wl, struct sk_buff *skb) -{ - int i; - - for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) - if (wl->tx_frames[i] == NULL) { - wl->tx_frames[i] = skb; - return i; - } - - return -EBUSY; -} - -static void wl1251_tx_control(struct tx_double_buffer_desc *tx_hdr, - struct ieee80211_tx_info *control, u16 fc) -{ - *(u16 *)&tx_hdr->control = 0; - - tx_hdr->control.rate_policy = 0; - - /* 802.11 packets */ - tx_hdr->control.packet_type = 0; - - if (control->flags & IEEE80211_TX_CTL_NO_ACK) - tx_hdr->control.ack_policy = 1; - - tx_hdr->control.tx_complete = 1; - - if ((fc & IEEE80211_FTYPE_DATA) && - ((fc & IEEE80211_STYPE_QOS_DATA) || - (fc & IEEE80211_STYPE_QOS_NULLFUNC))) - tx_hdr->control.qos = 1; -} - -/* RSN + MIC = 8 + 8 = 16 bytes (worst case - AES). */ -#define MAX_MSDU_SECURITY_LENGTH 16 -#define MAX_MPDU_SECURITY_LENGTH 16 -#define WLAN_QOS_HDR_LEN 26 -#define MAX_MPDU_HEADER_AND_SECURITY (MAX_MPDU_SECURITY_LENGTH + \ - WLAN_QOS_HDR_LEN) -#define HW_BLOCK_SIZE 252 -static void wl1251_tx_frag_block_num(struct tx_double_buffer_desc *tx_hdr) -{ - u16 payload_len, frag_threshold, mem_blocks; - u16 num_mpdus, mem_blocks_per_frag; - - frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - tx_hdr->frag_threshold = cpu_to_le16(frag_threshold); - - payload_len = tx_hdr->length + MAX_MSDU_SECURITY_LENGTH; - - if (payload_len > frag_threshold) { - mem_blocks_per_frag = - ((frag_threshold + MAX_MPDU_HEADER_AND_SECURITY) / - HW_BLOCK_SIZE) + 1; - num_mpdus = payload_len / frag_threshold; - mem_blocks = num_mpdus * mem_blocks_per_frag; - payload_len -= num_mpdus * frag_threshold; - num_mpdus++; - - } else { - mem_blocks_per_frag = 0; - mem_blocks = 0; - num_mpdus = 1; - } - - mem_blocks += (payload_len / HW_BLOCK_SIZE) + 1; - - if (num_mpdus > 1) - mem_blocks += min(num_mpdus, mem_blocks_per_frag); - - tx_hdr->num_mem_blocks = mem_blocks; -} - -static int wl1251_tx_fill_hdr(struct wl1251 *wl, struct sk_buff *skb, - struct ieee80211_tx_info *control) -{ - struct tx_double_buffer_desc *tx_hdr; - struct ieee80211_rate *rate; - int id; - u16 fc; - - if (!skb) - return -EINVAL; - - id = wl1251_tx_id(wl, skb); - if (id < 0) - return id; - - fc = *(u16 *)skb->data; - tx_hdr = (struct tx_double_buffer_desc *) skb_push(skb, - sizeof(*tx_hdr)); - - tx_hdr->length = cpu_to_le16(skb->len - sizeof(*tx_hdr)); - rate = ieee80211_get_tx_rate(wl->hw, control); - tx_hdr->rate = cpu_to_le16(rate->hw_value); - tx_hdr->expiry_time = cpu_to_le32(1 << 16); - tx_hdr->id = id; - - /* FIXME: how to get the correct queue id? */ - tx_hdr->xmit_queue = 0; - - wl1251_tx_control(tx_hdr, control, fc); - wl1251_tx_frag_block_num(tx_hdr); - - return 0; -} - -/* We copy the packet to the target */ -static int wl1251_tx_send_packet(struct wl1251 *wl, struct sk_buff *skb, - struct ieee80211_tx_info *control) -{ - struct tx_double_buffer_desc *tx_hdr; - int len; - u32 addr; - - if (!skb) - return -EINVAL; - - tx_hdr = (struct tx_double_buffer_desc *) skb->data; - - if (control->control.hw_key && - control->control.hw_key->alg == ALG_TKIP) { - int hdrlen; - u16 fc; - u8 *pos; - - fc = *(u16 *)(skb->data + sizeof(*tx_hdr)); - tx_hdr->length += WL1251_TKIP_IV_SPACE; - - hdrlen = ieee80211_hdrlen(fc); - - pos = skb_push(skb, WL1251_TKIP_IV_SPACE); - memmove(pos, pos + WL1251_TKIP_IV_SPACE, - sizeof(*tx_hdr) + hdrlen); - } - - /* Revisit. This is a workaround for getting non-aligned packets. - This happens at least with EAPOL packets from the user space. - Our DMA requires packets to be aligned on a 4-byte boundary. - */ - if (unlikely((long)skb->data & 0x03)) { - int offset = (4 - (long)skb->data) & 0x03; - wl1251_debug(DEBUG_TX, "skb offset %d", offset); - - /* check whether the current skb can be used */ - if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { - unsigned char *src = skb->data; - - /* align the buffer on a 4-byte boundary */ - skb_reserve(skb, offset); - memmove(skb->data, src, skb->len); - } else { - wl1251_info("No handler, fixme!"); - return -EINVAL; - } - } - - /* Our skb->data at this point includes the HW header */ - len = WL1251_TX_ALIGN(skb->len); - - if (wl->data_in_count & 0x1) - addr = wl->data_path->tx_packet_ring_addr + - wl->data_path->tx_packet_ring_chunk_size; - else - addr = wl->data_path->tx_packet_ring_addr; - - wl1251_mem_write(wl, addr, skb->data, len); - - wl1251_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u rate 0x%x", - tx_hdr->id, skb, tx_hdr->length, tx_hdr->rate); - - return 0; -} - -static void wl1251_tx_trigger(struct wl1251 *wl) -{ - u32 data, addr; - - if (wl->data_in_count & 0x1) { - addr = ACX_REG_INTERRUPT_TRIG_H; - data = INTR_TRIG_TX_PROC1; - } else { - addr = ACX_REG_INTERRUPT_TRIG; - data = INTR_TRIG_TX_PROC0; - } - - wl1251_reg_write32(wl, addr, data); - - /* Bumping data in */ - wl->data_in_count = (wl->data_in_count + 1) & - TX_STATUS_DATA_OUT_COUNT_MASK; -} - -/* caller must hold wl->mutex */ -static int wl1251_tx_frame(struct wl1251 *wl, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info; - int ret = 0; - u8 idx; - - info = IEEE80211_SKB_CB(skb); - - if (info->control.hw_key) { - idx = info->control.hw_key->hw_key_idx; - if (unlikely(wl->default_key != idx)) { - ret = wl1251_acx_default_key(wl, idx); - if (ret < 0) - return ret; - } - } - - ret = wl1251_tx_path_status(wl); - if (ret < 0) - return ret; - - ret = wl1251_tx_fill_hdr(wl, skb, info); - if (ret < 0) - return ret; - - ret = wl1251_tx_send_packet(wl, skb, info); - if (ret < 0) - return ret; - - wl1251_tx_trigger(wl); - - return ret; -} - -void wl1251_tx_work(struct work_struct *work) -{ - struct wl1251 *wl = container_of(work, struct wl1251, tx_work); - struct sk_buff *skb; - bool woken_up = false; - int ret; - - mutex_lock(&wl->mutex); - - if (unlikely(wl->state == WL1251_STATE_OFF)) - goto out; - - while ((skb = skb_dequeue(&wl->tx_queue))) { - if (!woken_up) { - ret = wl1251_ps_elp_wakeup(wl); - if (ret < 0) - goto out; - woken_up = true; - } - - ret = wl1251_tx_frame(wl, skb); - if (ret == -EBUSY) { - /* firmware buffer is full, stop queues */ - wl1251_debug(DEBUG_TX, "tx_work: fw buffer full, " - "stop queues"); - ieee80211_stop_queues(wl->hw); - wl->tx_queue_stopped = true; - skb_queue_head(&wl->tx_queue, skb); - goto out; - } else if (ret < 0) { - dev_kfree_skb(skb); - goto out; - } - } - -out: - if (woken_up) - wl1251_ps_elp_sleep(wl); - - mutex_unlock(&wl->mutex); -} - -static const char *wl1251_tx_parse_status(u8 status) -{ - /* 8 bit status field, one character per bit plus null */ - static char buf[9]; - int i = 0; - - memset(buf, 0, sizeof(buf)); - - if (status & TX_DMA_ERROR) - buf[i++] = 'm'; - if (status & TX_DISABLED) - buf[i++] = 'd'; - if (status & TX_RETRY_EXCEEDED) - buf[i++] = 'r'; - if (status & TX_TIMEOUT) - buf[i++] = 't'; - if (status & TX_KEY_NOT_FOUND) - buf[i++] = 'k'; - if (status & TX_ENCRYPT_FAIL) - buf[i++] = 'e'; - if (status & TX_UNAVAILABLE_PRIORITY) - buf[i++] = 'p'; - - /* bit 0 is unused apparently */ - - return buf; -} - -static void wl1251_tx_packet_cb(struct wl1251 *wl, - struct tx_result *result) -{ - struct ieee80211_tx_info *info; - struct sk_buff *skb; - int hdrlen, ret; - u8 *frame; - - skb = wl->tx_frames[result->id]; - if (skb == NULL) { - wl1251_error("SKB for packet %d is NULL", result->id); - return; - } - - info = IEEE80211_SKB_CB(skb); - - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) && - (result->status == TX_SUCCESS)) - info->flags |= IEEE80211_TX_STAT_ACK; - - info->status.rates[0].count = result->ack_failures + 1; - wl->stats.retry_count += result->ack_failures; - - /* - * We have to remove our private TX header before pushing - * the skb back to mac80211. - */ - frame = skb_pull(skb, sizeof(struct tx_double_buffer_desc)); - if (info->control.hw_key && - info->control.hw_key->alg == ALG_TKIP) { - hdrlen = ieee80211_get_hdrlen_from_skb(skb); - memmove(frame + WL1251_TKIP_IV_SPACE, frame, hdrlen); - skb_pull(skb, WL1251_TKIP_IV_SPACE); - } - - wl1251_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" - " status 0x%x (%s)", - result->id, skb, result->ack_failures, result->rate, - result->status, wl1251_tx_parse_status(result->status)); - - - ieee80211_tx_status(wl->hw, skb); - - wl->tx_frames[result->id] = NULL; - - if (wl->tx_queue_stopped) { - wl1251_debug(DEBUG_TX, "cb: queue was stopped"); - - skb = skb_dequeue(&wl->tx_queue); - - /* The skb can be NULL because tx_work might have been - scheduled before the queue was stopped making the - queue empty */ - - if (skb) { - ret = wl1251_tx_frame(wl, skb); - if (ret == -EBUSY) { - /* firmware buffer is still full */ - wl1251_debug(DEBUG_TX, "cb: fw buffer " - "still full"); - skb_queue_head(&wl->tx_queue, skb); - return; - } else if (ret < 0) { - dev_kfree_skb(skb); - return; - } - } - - wl1251_debug(DEBUG_TX, "cb: waking queues"); - ieee80211_wake_queues(wl->hw); - wl->tx_queue_stopped = false; - } -} - -/* Called upon reception of a TX complete interrupt */ -void wl1251_tx_complete(struct wl1251 *wl) -{ - int i, result_index, num_complete = 0; - struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr; - - if (unlikely(wl->state != WL1251_STATE_ON)) - return; - - /* First we read the result */ - wl1251_mem_read(wl, wl->data_path->tx_complete_addr, - result, sizeof(result)); - - result_index = wl->next_tx_complete; - - for (i = 0; i < ARRAY_SIZE(result); i++) { - result_ptr = &result[result_index]; - - if (result_ptr->done_1 == 1 && - result_ptr->done_2 == 1) { - wl1251_tx_packet_cb(wl, result_ptr); - - result_ptr->done_1 = 0; - result_ptr->done_2 = 0; - - result_index = (result_index + 1) & - (FW_TX_CMPLT_BLOCK_SIZE - 1); - num_complete++; - } else { - break; - } - } - - /* Every completed frame needs to be acknowledged */ - if (num_complete) { - /* - * If we've wrapped, we have to clear - * the results in 2 steps. - */ - if (result_index > wl->next_tx_complete) { - /* Only 1 write is needed */ - wl1251_mem_write(wl, - wl->data_path->tx_complete_addr + - (wl->next_tx_complete * - sizeof(struct tx_result)), - &result[wl->next_tx_complete], - num_complete * - sizeof(struct tx_result)); - - - } else if (result_index < wl->next_tx_complete) { - /* 2 writes are needed */ - wl1251_mem_write(wl, - wl->data_path->tx_complete_addr + - (wl->next_tx_complete * - sizeof(struct tx_result)), - &result[wl->next_tx_complete], - (FW_TX_CMPLT_BLOCK_SIZE - - wl->next_tx_complete) * - sizeof(struct tx_result)); - - wl1251_mem_write(wl, - wl->data_path->tx_complete_addr, - result, - (num_complete - - FW_TX_CMPLT_BLOCK_SIZE + - wl->next_tx_complete) * - sizeof(struct tx_result)); - - } else { - /* We have to write the whole array */ - wl1251_mem_write(wl, - wl->data_path->tx_complete_addr, - result, - FW_TX_CMPLT_BLOCK_SIZE * - sizeof(struct tx_result)); - } - - } - - wl->next_tx_complete = result_index; -} - -/* caller must hold wl->mutex */ -void wl1251_tx_flush(struct wl1251 *wl) -{ - int i; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - - /* TX failure */ -/* control->flags = 0; FIXME */ - - while ((skb = skb_dequeue(&wl->tx_queue))) { - info = IEEE80211_SKB_CB(skb); - - wl1251_debug(DEBUG_TX, "flushing skb 0x%p", skb); - - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) - continue; - - ieee80211_tx_status(wl->hw, skb); - } - - for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) - if (wl->tx_frames[i] != NULL) { - skb = wl->tx_frames[i]; - info = IEEE80211_SKB_CB(skb); - - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) - continue; - - ieee80211_tx_status(wl->hw, skb); - wl->tx_frames[i] = NULL; - } -} diff --git a/drivers/net/wireless/wl12xx/wl1251_tx.h b/drivers/net/wireless/wl12xx/wl1251_tx.h deleted file mode 100644 index 7c1c1665c810..000000000000 --- a/drivers/net/wireless/wl12xx/wl1251_tx.h +++ /dev/null @@ -1,216 +0,0 @@ -/* - * This file is part of wl1251 - * - * Copyright (c) 1998-2007 Texas Instruments Incorporated - * Copyright (C) 2008 Nokia Corporation - * - * Contact: Kalle Valo - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1251_TX_H__ -#define __WL1251_TX_H__ - -#include - -/* - * - * TX PATH - * - * The Tx path uses a double buffer and a tx_control structure, each located - * at a fixed address in the device's memory. On startup, the host retrieves - * the pointers to these addresses. A double buffer allows for continuous data - * flow towards the device. The host keeps track of which buffer is available - * and alternates between these two buffers on a per packet basis. - * - * The size of each of the two buffers is large enough to hold the longest - * 802.3 packet - maximum size Ethernet packet + header + descriptor. - * TX complete indication will be received a-synchronously in a TX done cyclic - * buffer which is composed of 16 tx_result descriptors structures and is used - * in a cyclic manner. - * - * The TX (HOST) procedure is as follows: - * 1. Read the Tx path status, that will give the data_out_count. - * 2. goto 1, if not possible. - * i.e. if data_in_count - data_out_count >= HwBuffer size (2 for double - * buffer). - * 3. Copy the packet (preceded by double_buffer_desc), if possible. - * i.e. if data_in_count - data_out_count < HwBuffer size (2 for double - * buffer). - * 4. increment data_in_count. - * 5. Inform the firmware by generating a firmware internal interrupt. - * 6. FW will increment data_out_count after it reads the buffer. - * - * The TX Complete procedure: - * 1. To get a TX complete indication the host enables the tx_complete flag in - * the TX descriptor Structure. - * 2. For each packet with a Tx Complete field set, the firmware adds the - * transmit results to the cyclic buffer (txDoneRing) and sets both done_1 - * and done_2 to 1 to indicate driver ownership. - * 3. The firmware sends a Tx Complete interrupt to the host to trigger the - * host to process the new data. Note: interrupt will be send per packet if - * TX complete indication was requested in tx_control or per crossing - * aggregation threshold. - * 4. After receiving the Tx Complete interrupt, the host reads the - * TxDescriptorDone information in a cyclic manner and clears both done_1 - * and done_2 fields. - * - */ - -#define TX_COMPLETE_REQUIRED_BIT 0x80 -#define TX_STATUS_DATA_OUT_COUNT_MASK 0xf - -#define WL1251_TX_ALIGN_TO 4 -#define WL1251_TX_ALIGN(len) (((len) + WL1251_TX_ALIGN_TO - 1) & \ - ~(WL1251_TX_ALIGN_TO - 1)) -#define WL1251_TKIP_IV_SPACE 4 - -struct tx_control { - /* Rate Policy (class) index */ - unsigned rate_policy:3; - - /* When set, no ack policy is expected */ - unsigned ack_policy:1; - - /* - * Packet type: - * 0 -> 802.11 - * 1 -> 802.3 - * 2 -> IP - * 3 -> raw codec - */ - unsigned packet_type:2; - - /* If set, this is a QoS-Null or QoS-Data frame */ - unsigned qos:1; - - /* - * If set, the target triggers the tx complete INT - * upon frame sending completion. - */ - unsigned tx_complete:1; - - /* 2 bytes padding before packet header */ - unsigned xfer_pad:1; - - unsigned reserved:7; -} __attribute__ ((packed)); - - -struct tx_double_buffer_desc { - /* Length of payload, including headers. */ - u16 length; - - /* - * A bit mask that specifies the initial rate to be used - * Possible values are: - * 0x0001 - 1Mbits - * 0x0002 - 2Mbits - * 0x0004 - 5.5Mbits - * 0x0008 - 6Mbits - * 0x0010 - 9Mbits - * 0x0020 - 11Mbits - * 0x0040 - 12Mbits - * 0x0080 - 18Mbits - * 0x0100 - 22Mbits - * 0x0200 - 24Mbits - * 0x0400 - 36Mbits - * 0x0800 - 48Mbits - * 0x1000 - 54Mbits - */ - u16 rate; - - /* Time in us that a packet can spend in the target */ - u32 expiry_time; - - /* index of the TX queue used for this packet */ - u8 xmit_queue; - - /* Used to identify a packet */ - u8 id; - - struct tx_control control; - - /* - * The FW should cut the packet into fragments - * of this size. - */ - u16 frag_threshold; - - /* Numbers of HW queue blocks to be allocated */ - u8 num_mem_blocks; - - u8 reserved; -} __attribute__ ((packed)); - -enum { - TX_SUCCESS = 0, - TX_DMA_ERROR = BIT(7), - TX_DISABLED = BIT(6), - TX_RETRY_EXCEEDED = BIT(5), - TX_TIMEOUT = BIT(4), - TX_KEY_NOT_FOUND = BIT(3), - TX_ENCRYPT_FAIL = BIT(2), - TX_UNAVAILABLE_PRIORITY = BIT(1), -}; - -struct tx_result { - /* - * Ownership synchronization between the host and - * the firmware. If done_1 and done_2 are cleared, - * owned by the FW (no info ready). - */ - u8 done_1; - - /* same as double_buffer_desc->id */ - u8 id; - - /* - * Total air access duration consumed by this - * packet, including all retries and overheads. - */ - u16 medium_usage; - - /* Total media delay (from 1st EDCA AIFS counter until TX Complete). */ - u32 medium_delay; - - /* Time between host xfer and tx complete */ - u32 fw_hnadling_time; - - /* The LS-byte of the last TKIP sequence number. */ - u8 lsb_seq_num; - - /* Retry count */ - u8 ack_failures; - - /* At which rate we got a ACK */ - u16 rate; - - u16 reserved; - - /* TX_* */ - u8 status; - - /* See done_1 */ - u8 done_2; -} __attribute__ ((packed)); - -void wl1251_tx_work(struct work_struct *work); -void wl1251_tx_complete(struct wl1251 *wl); -void wl1251_tx_flush(struct wl1251 *wl); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h deleted file mode 100644 index 55818f94017b..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271.h +++ /dev/null @@ -1,407 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_H__ -#define __WL1271_H__ - -#include -#include -#include -#include -#include -#include - -#define DRIVER_NAME "wl1271" -#define DRIVER_PREFIX DRIVER_NAME ": " - -enum { - DEBUG_NONE = 0, - DEBUG_IRQ = BIT(0), - DEBUG_SPI = BIT(1), - DEBUG_BOOT = BIT(2), - DEBUG_MAILBOX = BIT(3), - DEBUG_NETLINK = BIT(4), - DEBUG_EVENT = BIT(5), - DEBUG_TX = BIT(6), - DEBUG_RX = BIT(7), - DEBUG_SCAN = BIT(8), - DEBUG_CRYPT = BIT(9), - DEBUG_PSM = BIT(10), - DEBUG_MAC80211 = BIT(11), - DEBUG_CMD = BIT(12), - DEBUG_ACX = BIT(13), - DEBUG_ALL = ~0, -}; - -#define DEBUG_LEVEL (DEBUG_NONE) - -#define DEBUG_DUMP_LIMIT 1024 - -#define wl1271_error(fmt, arg...) \ - printk(KERN_ERR DRIVER_PREFIX "ERROR " fmt "\n", ##arg) - -#define wl1271_warning(fmt, arg...) \ - printk(KERN_WARNING DRIVER_PREFIX "WARNING " fmt "\n", ##arg) - -#define wl1271_notice(fmt, arg...) \ - printk(KERN_INFO DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1271_info(fmt, arg...) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg) - -#define wl1271_debug(level, fmt, arg...) \ - do { \ - if (level & DEBUG_LEVEL) \ - printk(KERN_DEBUG DRIVER_PREFIX fmt "\n", ##arg); \ - } while (0) - -#define wl1271_dump(level, prefix, buf, len) \ - do { \ - if (level & DEBUG_LEVEL) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - 0); \ - } while (0) - -#define wl1271_dump_ascii(level, prefix, buf, len) \ - do { \ - if (level & DEBUG_LEVEL) \ - print_hex_dump(KERN_DEBUG, DRIVER_PREFIX prefix, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, \ - min_t(size_t, len, DEBUG_DUMP_LIMIT), \ - true); \ - } while (0) - -#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN | \ - CFG_BSSID_FILTER_EN) - -#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN | \ - CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \ - CFG_RX_CTL_EN | CFG_RX_BCN_EN | \ - CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) - -#define WL1271_FW_NAME "wl1271-fw.bin" -#define WL1271_NVS_NAME "wl1271-nvs.bin" - -#define WL1271_BUSY_WORD_LEN 8 - -#define WL1271_ELP_HW_STATE_ASLEEP 0 -#define WL1271_ELP_HW_STATE_IRQ 1 - -enum wl1271_state { - WL1271_STATE_OFF, - WL1271_STATE_ON, - WL1271_STATE_PLT, -}; - -enum wl1271_partition_type { - PART_DOWN, - PART_WORK, - PART_DRPW, - - PART_TABLE_LEN -}; - -struct wl1271_partition { - u32 size; - u32 start; -}; - -struct wl1271_partition_set { - struct wl1271_partition mem; - struct wl1271_partition reg; -}; - -struct wl1271; - -/* FIXME: I'm not sure about this structure name */ -struct wl1271_chip { - u32 id; - char fw_ver[21]; -}; - -struct wl1271_stats { - struct acx_statistics *fw_stats; - unsigned long fw_stats_update; - - unsigned int retry_count; - unsigned int excessive_retries; -}; - -struct wl1271_debugfs { - struct dentry *rootdir; - struct dentry *fw_statistics; - - struct dentry *tx_internal_desc_overflow; - - struct dentry *rx_out_of_mem; - struct dentry *rx_hdr_overflow; - struct dentry *rx_hw_stuck; - struct dentry *rx_dropped; - struct dentry *rx_fcs_err; - struct dentry *rx_xfr_hint_trig; - struct dentry *rx_path_reset; - struct dentry *rx_reset_counter; - - struct dentry *dma_rx_requested; - struct dentry *dma_rx_errors; - struct dentry *dma_tx_requested; - struct dentry *dma_tx_errors; - - struct dentry *isr_cmd_cmplt; - struct dentry *isr_fiqs; - struct dentry *isr_rx_headers; - struct dentry *isr_rx_mem_overflow; - struct dentry *isr_rx_rdys; - struct dentry *isr_irqs; - struct dentry *isr_tx_procs; - struct dentry *isr_decrypt_done; - struct dentry *isr_dma0_done; - struct dentry *isr_dma1_done; - struct dentry *isr_tx_exch_complete; - struct dentry *isr_commands; - struct dentry *isr_rx_procs; - struct dentry *isr_hw_pm_mode_changes; - struct dentry *isr_host_acknowledges; - struct dentry *isr_pci_pm; - struct dentry *isr_wakeups; - struct dentry *isr_low_rssi; - - struct dentry *wep_addr_key_count; - struct dentry *wep_default_key_count; - /* skipping wep.reserved */ - struct dentry *wep_key_not_found; - struct dentry *wep_decrypt_fail; - struct dentry *wep_packets; - struct dentry *wep_interrupt; - - struct dentry *pwr_ps_enter; - struct dentry *pwr_elp_enter; - struct dentry *pwr_missing_bcns; - struct dentry *pwr_wake_on_host; - struct dentry *pwr_wake_on_timer_exp; - struct dentry *pwr_tx_with_ps; - struct dentry *pwr_tx_without_ps; - struct dentry *pwr_rcvd_beacons; - struct dentry *pwr_power_save_off; - struct dentry *pwr_enable_ps; - struct dentry *pwr_disable_ps; - struct dentry *pwr_fix_tsf_ps; - /* skipping cont_miss_bcns_spread for now */ - struct dentry *pwr_rcvd_awake_beacons; - - struct dentry *mic_rx_pkts; - struct dentry *mic_calc_failure; - - struct dentry *aes_encrypt_fail; - struct dentry *aes_decrypt_fail; - struct dentry *aes_encrypt_packets; - struct dentry *aes_decrypt_packets; - struct dentry *aes_encrypt_interrupt; - struct dentry *aes_decrypt_interrupt; - - struct dentry *event_heart_beat; - struct dentry *event_calibration; - struct dentry *event_rx_mismatch; - struct dentry *event_rx_mem_empty; - struct dentry *event_rx_pool; - struct dentry *event_oom_late; - struct dentry *event_phy_transmit_error; - struct dentry *event_tx_stuck; - - struct dentry *ps_pspoll_timeouts; - struct dentry *ps_upsd_timeouts; - struct dentry *ps_upsd_max_sptime; - struct dentry *ps_upsd_max_apturn; - struct dentry *ps_pspoll_max_apturn; - struct dentry *ps_pspoll_utilization; - struct dentry *ps_upsd_utilization; - - struct dentry *rxpipe_rx_prep_beacon_drop; - struct dentry *rxpipe_descr_host_int_trig_rx_data; - struct dentry *rxpipe_beacon_buffer_thres_host_int_trig_rx_data; - struct dentry *rxpipe_missed_beacon_host_int_trig_rx_data; - struct dentry *rxpipe_tx_xfr_host_int_trig_rx_data; - - struct dentry *tx_queue_len; - - struct dentry *retry_count; - struct dentry *excessive_retries; -}; - -#define NUM_TX_QUEUES 4 -#define NUM_RX_PKT_DESC 8 - -/* FW status registers */ -struct wl1271_fw_status { - u32 intr; - u8 fw_rx_counter; - u8 drv_rx_counter; - u8 reserved; - u8 tx_results_counter; - u32 rx_pkt_descs[NUM_RX_PKT_DESC]; - u32 tx_released_blks[NUM_TX_QUEUES]; - u32 fw_localtime; - u32 padding[2]; -} __attribute__ ((packed)); - -struct wl1271_rx_mem_pool_addr { - u32 addr; - u32 addr_extra; -}; - -struct wl1271 { - struct ieee80211_hw *hw; - bool mac80211_registered; - - struct spi_device *spi; - - void (*set_power)(bool enable); - int irq; - - spinlock_t wl_lock; - - enum wl1271_state state; - struct mutex mutex; - - int physical_mem_addr; - int physical_reg_addr; - int virtual_mem_addr; - int virtual_reg_addr; - - struct wl1271_chip chip; - - int cmd_box_addr; - int event_box_addr; - - u8 *fw; - size_t fw_len; - u8 *nvs; - size_t nvs_len; - - u8 bssid[ETH_ALEN]; - u8 mac_addr[ETH_ALEN]; - u8 bss_type; - u8 ssid[IW_ESSID_MAX_SIZE + 1]; - u8 ssid_len; - u8 listen_int; - int channel; - - struct wl1271_acx_mem_map *target_mem_map; - - /* Accounting for allocated / available TX blocks on HW */ - u32 tx_blocks_freed[NUM_TX_QUEUES]; - u32 tx_blocks_available; - u8 tx_results_count; - - /* Transmitted TX packets counter for chipset interface */ - int tx_packets_count; - - /* Time-offset between host and chipset clocks */ - int time_offset; - - /* Session counter for the chipset */ - int session_counter; - - /* Frames scheduled for transmission, not handled yet */ - struct sk_buff_head tx_queue; - bool tx_queue_stopped; - - struct work_struct tx_work; - struct work_struct filter_work; - - /* Pending TX frames */ - struct sk_buff *tx_frames[16]; - - /* FW Rx counter */ - u32 rx_counter; - - /* Rx memory pool address */ - struct wl1271_rx_mem_pool_addr rx_mem_pool_addr; - - /* The target interrupt mask */ - struct work_struct irq_work; - - /* The mbox event mask */ - u32 event_mask; - - /* Mailbox pointers */ - u32 mbox_ptr[2]; - - /* Are we currently scanning */ - bool scanning; - - /* Our association ID */ - u16 aid; - - /* Default key (for WEP) */ - u32 default_key; - - unsigned int rx_config; - unsigned int rx_filter; - - /* is firmware in elp mode */ - bool elp; - - struct completion *elp_compl; - - /* we can be in psm, but not in elp, we have to differentiate */ - bool psm; - - /* PSM mode requested */ - bool psm_requested; - - /* in dBm */ - int power_level; - - struct wl1271_stats stats; - struct wl1271_debugfs debugfs; - - u32 buffer_32; - u32 buffer_cmd; - u8 buffer_busyword[WL1271_BUSY_WORD_LEN]; - struct wl1271_rx_descriptor *rx_descriptor; - - struct wl1271_fw_status *fw_status; - struct wl1271_tx_hw_res_if *tx_res_if; -}; - -int wl1271_plt_start(struct wl1271 *wl); -int wl1271_plt_stop(struct wl1271 *wl); - -#define JOIN_TIMEOUT 5000 /* 5000 milliseconds to join */ - -#define SESSION_COUNTER_MAX 7 /* maximum value for the session counter */ - -#define WL1271_DEFAULT_POWER_LEVEL 0 - -#define WL1271_TX_QUEUE_MAX_LENGTH 20 - -/* WL1271 needs a 200ms sleep after power on */ -#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */ - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c deleted file mode 100644 index f622a4092615..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_acx.c +++ /dev/null @@ -1,961 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1271_acx.h" - -#include -#include -#include -#include - -#include "wl1271.h" -#include "wl12xx_80211.h" -#include "wl1271_reg.h" -#include "wl1271_spi.h" -#include "wl1271_ps.h" - -int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, - u8 listen_interval) -{ - struct acx_wake_up_condition *wake_up; - int ret; - - wl1271_debug(DEBUG_ACX, "acx wake up conditions"); - - wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL); - if (!wake_up) { - ret = -ENOMEM; - goto out; - } - - wake_up->wake_up_event = wake_up_event; - wake_up->listen_interval = listen_interval; - - ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS, - wake_up, sizeof(*wake_up)); - if (ret < 0) { - wl1271_warning("could not set wake up conditions: %d", ret); - goto out; - } - -out: - kfree(wake_up); - return ret; -} - -int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth) -{ - struct acx_sleep_auth *auth; - int ret; - - wl1271_debug(DEBUG_ACX, "acx sleep auth"); - - auth = kzalloc(sizeof(*auth), GFP_KERNEL); - if (!auth) { - ret = -ENOMEM; - goto out; - } - - auth->sleep_auth = sleep_auth; - - ret = wl1271_cmd_configure(wl, ACX_SLEEP_AUTH, auth, sizeof(*auth)); - if (ret < 0) - return ret; - -out: - kfree(auth); - return ret; -} - -int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len) -{ - struct acx_revision *rev; - int ret; - - wl1271_debug(DEBUG_ACX, "acx fw rev"); - - rev = kzalloc(sizeof(*rev), GFP_KERNEL); - if (!rev) { - ret = -ENOMEM; - goto out; - } - - ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev)); - if (ret < 0) { - wl1271_warning("ACX_FW_REV interrogate failed"); - goto out; - } - - /* be careful with the buffer sizes */ - strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version))); - - /* - * if the firmware version string is exactly - * sizeof(rev->fw_version) long or fw_len is less than - * sizeof(rev->fw_version) it won't be null terminated - */ - buf[min(len, sizeof(rev->fw_version)) - 1] = '\0'; - -out: - kfree(rev); - return ret; -} - -int wl1271_acx_tx_power(struct wl1271 *wl, int power) -{ - struct acx_current_tx_power *acx; - int ret; - - wl1271_debug(DEBUG_ACX, "acx dot11_cur_tx_pwr"); - - if (power < 0 || power > 25) - return -EINVAL; - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->current_tx_power = power * 10; - - ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("configure of tx power failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_feature_cfg(struct wl1271 *wl) -{ - struct acx_feature_config *feature; - int ret; - - wl1271_debug(DEBUG_ACX, "acx feature cfg"); - - feature = kzalloc(sizeof(*feature), GFP_KERNEL); - if (!feature) { - ret = -ENOMEM; - goto out; - } - - /* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */ - feature->data_flow_options = 0; - feature->options = 0; - - ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG, - feature, sizeof(*feature)); - if (ret < 0) { - wl1271_error("Couldnt set HW encryption"); - goto out; - } - -out: - kfree(feature); - return ret; -} - -int wl1271_acx_mem_map(struct wl1271 *wl, struct acx_header *mem_map, - size_t len) -{ - int ret; - - wl1271_debug(DEBUG_ACX, "acx mem map"); - - ret = wl1271_cmd_interrogate(wl, ACX_MEM_MAP, mem_map, len); - if (ret < 0) - return ret; - - return 0; -} - -int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time) -{ - struct acx_rx_msdu_lifetime *acx; - int ret; - - wl1271_debug(DEBUG_ACX, "acx rx msdu life time"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->lifetime = life_time; - ret = wl1271_cmd_configure(wl, DOT11_RX_MSDU_LIFE_TIME, - acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("failed to set rx msdu life time: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter) -{ - struct acx_rx_config *rx_config; - int ret; - - wl1271_debug(DEBUG_ACX, "acx rx config"); - - rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL); - if (!rx_config) { - ret = -ENOMEM; - goto out; - } - - rx_config->config_options = config; - rx_config->filter_options = filter; - - ret = wl1271_cmd_configure(wl, ACX_RX_CFG, - rx_config, sizeof(*rx_config)); - if (ret < 0) { - wl1271_warning("failed to set rx config: %d", ret); - goto out; - } - -out: - kfree(rx_config); - return ret; -} - -int wl1271_acx_pd_threshold(struct wl1271 *wl) -{ - struct acx_packet_detection *pd; - int ret; - - wl1271_debug(DEBUG_ACX, "acx data pd threshold"); - - pd = kzalloc(sizeof(*pd), GFP_KERNEL); - if (!pd) { - ret = -ENOMEM; - goto out; - } - - /* FIXME: threshold value not set */ - - ret = wl1271_cmd_configure(wl, ACX_PD_THRESHOLD, pd, sizeof(*pd)); - if (ret < 0) { - wl1271_warning("failed to set pd threshold: %d", ret); - goto out; - } - -out: - kfree(pd); - return 0; -} - -int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time) -{ - struct acx_slot *slot; - int ret; - - wl1271_debug(DEBUG_ACX, "acx slot"); - - slot = kzalloc(sizeof(*slot), GFP_KERNEL); - if (!slot) { - ret = -ENOMEM; - goto out; - } - - slot->wone_index = STATION_WONE_INDEX; - slot->slot_time = slot_time; - - ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot)); - if (ret < 0) { - wl1271_warning("failed to set slot time: %d", ret); - goto out; - } - -out: - kfree(slot); - return ret; -} - -int wl1271_acx_group_address_tbl(struct wl1271 *wl) -{ - struct acx_dot11_grp_addr_tbl *acx; - int ret; - - wl1271_debug(DEBUG_ACX, "acx group address tbl"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - /* MAC filtering */ - acx->enabled = 0; - acx->num_groups = 0; - memset(acx->mac_table, 0, ADDRESS_GROUP_MAX_LEN); - - ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL, - acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("failed to set group addr table: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_service_period_timeout(struct wl1271 *wl) -{ - struct acx_rx_timeout *rx_timeout; - int ret; - - rx_timeout = kzalloc(sizeof(*rx_timeout), GFP_KERNEL); - if (!rx_timeout) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_ACX, "acx service period timeout"); - - rx_timeout->ps_poll_timeout = RX_TIMEOUT_PS_POLL_DEF; - rx_timeout->upsd_timeout = RX_TIMEOUT_UPSD_DEF; - - ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT, - rx_timeout, sizeof(*rx_timeout)); - if (ret < 0) { - wl1271_warning("failed to set service period timeout: %d", - ret); - goto out; - } - -out: - kfree(rx_timeout); - return ret; -} - -int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold) -{ - struct acx_rts_threshold *rts; - int ret; - - wl1271_debug(DEBUG_ACX, "acx rts threshold"); - - rts = kzalloc(sizeof(*rts), GFP_KERNEL); - if (!rts) { - ret = -ENOMEM; - goto out; - } - - rts->threshold = rts_threshold; - - ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts)); - if (ret < 0) { - wl1271_warning("failed to set rts threshold: %d", ret); - goto out; - } - -out: - kfree(rts); - return ret; -} - -int wl1271_acx_beacon_filter_opt(struct wl1271 *wl) -{ - struct acx_beacon_filter_option *beacon_filter; - int ret; - - wl1271_debug(DEBUG_ACX, "acx beacon filter opt"); - - beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL); - if (!beacon_filter) { - ret = -ENOMEM; - goto out; - } - - beacon_filter->enable = 0; - beacon_filter->max_num_beacons = 0; - - ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_OPT, - beacon_filter, sizeof(*beacon_filter)); - if (ret < 0) { - wl1271_warning("failed to set beacon filter opt: %d", ret); - goto out; - } - -out: - kfree(beacon_filter); - return ret; -} - -int wl1271_acx_beacon_filter_table(struct wl1271 *wl) -{ - struct acx_beacon_filter_ie_table *ie_table; - int ret; - - wl1271_debug(DEBUG_ACX, "acx beacon filter table"); - - ie_table = kzalloc(sizeof(*ie_table), GFP_KERNEL); - if (!ie_table) { - ret = -ENOMEM; - goto out; - } - - ie_table->num_ie = 0; - memset(ie_table->table, 0, BEACON_FILTER_TABLE_MAX_SIZE); - - ret = wl1271_cmd_configure(wl, ACX_BEACON_FILTER_TABLE, - ie_table, sizeof(*ie_table)); - if (ret < 0) { - wl1271_warning("failed to set beacon filter table: %d", ret); - goto out; - } - -out: - kfree(ie_table); - return ret; -} - -int wl1271_acx_sg_enable(struct wl1271 *wl) -{ - struct acx_bt_wlan_coex *pta; - int ret; - - wl1271_debug(DEBUG_ACX, "acx sg enable"); - - pta = kzalloc(sizeof(*pta), GFP_KERNEL); - if (!pta) { - ret = -ENOMEM; - goto out; - } - - pta->enable = SG_ENABLE; - - ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta)); - if (ret < 0) { - wl1271_warning("failed to set softgemini enable: %d", ret); - goto out; - } - -out: - kfree(pta); - return ret; -} - -int wl1271_acx_sg_cfg(struct wl1271 *wl) -{ - struct acx_bt_wlan_coex_param *param; - int ret; - - wl1271_debug(DEBUG_ACX, "acx sg cfg"); - - param = kzalloc(sizeof(*param), GFP_KERNEL); - if (!param) { - ret = -ENOMEM; - goto out; - } - - /* BT-WLAN coext parameters */ - param->min_rate = RATE_INDEX_24MBPS; - param->bt_hp_max_time = PTA_BT_HP_MAXTIME_DEF; - param->wlan_hp_max_time = PTA_WLAN_HP_MAX_TIME_DEF; - param->sense_disable_timer = PTA_SENSE_DISABLE_TIMER_DEF; - param->rx_time_bt_hp = PTA_PROTECTIVE_RX_TIME_DEF; - param->tx_time_bt_hp = PTA_PROTECTIVE_TX_TIME_DEF; - param->rx_time_bt_hp_fast = PTA_PROTECTIVE_RX_TIME_FAST_DEF; - param->tx_time_bt_hp_fast = PTA_PROTECTIVE_TX_TIME_FAST_DEF; - param->wlan_cycle_fast = PTA_CYCLE_TIME_FAST_DEF; - param->bt_anti_starvation_period = PTA_ANTI_STARVE_PERIOD_DEF; - param->next_bt_lp_packet = PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF; - param->wake_up_beacon = PTA_TIME_BEFORE_BEACON_DEF; - param->hp_dm_max_guard_time = PTA_HPDM_MAX_TIME_DEF; - param->next_wlan_packet = PTA_TIME_OUT_NEXT_WLAN_DEF; - param->antenna_type = PTA_ANTENNA_TYPE_DEF; - param->signal_type = PTA_SIGNALING_TYPE_DEF; - param->afh_leverage_on = PTA_AFH_LEVERAGE_ON_DEF; - param->quiet_cycle_num = PTA_NUMBER_QUIET_CYCLE_DEF; - param->max_cts = PTA_MAX_NUM_CTS_DEF; - param->wlan_packets_num = PTA_NUMBER_OF_WLAN_PACKETS_DEF; - param->bt_packets_num = PTA_NUMBER_OF_BT_PACKETS_DEF; - param->missed_rx_avalanche = PTA_RX_FOR_AVALANCHE_DEF; - param->wlan_elp_hp = PTA_ELP_HP_DEF; - param->bt_anti_starvation_cycles = PTA_ANTI_STARVE_NUM_CYCLE_DEF; - param->ack_mode_dual_ant = PTA_ACK_MODE_DEF; - param->pa_sd_enable = PTA_ALLOW_PA_SD_DEF; - param->pta_auto_mode_enable = PTA_AUTO_MODE_NO_CTS_DEF; - param->bt_hp_respected_num = PTA_BT_HP_RESPECTED_DEF; - - ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param)); - if (ret < 0) { - wl1271_warning("failed to set sg config: %d", ret); - goto out; - } - -out: - kfree(param); - return ret; -} - -int wl1271_acx_cca_threshold(struct wl1271 *wl) -{ - struct acx_energy_detection *detection; - int ret; - - wl1271_debug(DEBUG_ACX, "acx cca threshold"); - - detection = kzalloc(sizeof(*detection), GFP_KERNEL); - if (!detection) { - ret = -ENOMEM; - goto out; - } - - detection->rx_cca_threshold = CCA_THRSH_DISABLE_ENERGY_D; - detection->tx_energy_detection = 0; - - ret = wl1271_cmd_configure(wl, ACX_CCA_THRESHOLD, - detection, sizeof(*detection)); - if (ret < 0) { - wl1271_warning("failed to set cca threshold: %d", ret); - return ret; - } - -out: - kfree(detection); - return ret; -} - -int wl1271_acx_bcn_dtim_options(struct wl1271 *wl) -{ - struct acx_beacon_broadcast *bb; - int ret; - - wl1271_debug(DEBUG_ACX, "acx bcn dtim options"); - - bb = kzalloc(sizeof(*bb), GFP_KERNEL); - if (!bb) { - ret = -ENOMEM; - goto out; - } - - bb->beacon_rx_timeout = BCN_RX_TIMEOUT_DEF_VALUE; - bb->broadcast_timeout = BROADCAST_RX_TIMEOUT_DEF_VALUE; - bb->rx_broadcast_in_ps = RX_BROADCAST_IN_PS_DEF_VALUE; - bb->ps_poll_threshold = CONSECUTIVE_PS_POLL_FAILURE_DEF; - - ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb)); - if (ret < 0) { - wl1271_warning("failed to set rx config: %d", ret); - goto out; - } - -out: - kfree(bb); - return ret; -} - -int wl1271_acx_aid(struct wl1271 *wl, u16 aid) -{ - struct acx_aid *acx_aid; - int ret; - - wl1271_debug(DEBUG_ACX, "acx aid"); - - acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL); - if (!acx_aid) { - ret = -ENOMEM; - goto out; - } - - acx_aid->aid = aid; - - ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid)); - if (ret < 0) { - wl1271_warning("failed to set aid: %d", ret); - goto out; - } - -out: - kfree(acx_aid); - return ret; -} - -int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask) -{ - struct acx_event_mask *mask; - int ret; - - wl1271_debug(DEBUG_ACX, "acx event mbox mask"); - - mask = kzalloc(sizeof(*mask), GFP_KERNEL); - if (!mask) { - ret = -ENOMEM; - goto out; - } - - /* high event mask is unused */ - mask->high_event_mask = 0xffffffff; - - mask->event_mask = event_mask; - - ret = wl1271_cmd_configure(wl, ACX_EVENT_MBOX_MASK, - mask, sizeof(*mask)); - if (ret < 0) { - wl1271_warning("failed to set acx_event_mbox_mask: %d", ret); - goto out; - } - -out: - kfree(mask); - return ret; -} - -int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble) -{ - struct acx_preamble *acx; - int ret; - - wl1271_debug(DEBUG_ACX, "acx_set_preamble"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->preamble = preamble; - - ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of preamble failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_cts_protect(struct wl1271 *wl, - enum acx_ctsprotect_type ctsprotect) -{ - struct acx_ctsprotect *acx; - int ret; - - wl1271_debug(DEBUG_ACX, "acx_set_ctsprotect"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->ctsprotect = ctsprotect; - - ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of ctsprotect failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats) -{ - int ret; - - wl1271_debug(DEBUG_ACX, "acx statistics"); - - ret = wl1271_cmd_interrogate(wl, ACX_STATISTICS, stats, - sizeof(*stats)); - if (ret < 0) { - wl1271_warning("acx statistics failed: %d", ret); - return -ENOMEM; - } - - return 0; -} - -int wl1271_acx_rate_policies(struct wl1271 *wl) -{ - struct acx_rate_policy *acx; - int ret = 0; - - wl1271_debug(DEBUG_ACX, "acx rate policies"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } - - /* configure one default (one-size-fits-all) rate class */ - acx->rate_class_cnt = 1; - acx->rate_class[0].enabled_rates = ACX_RATE_MASK_ALL; - acx->rate_class[0].short_retry_limit = ACX_RATE_RETRY_LIMIT; - acx->rate_class[0].long_retry_limit = ACX_RATE_RETRY_LIMIT; - acx->rate_class[0].aflags = 0; - - ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of rate policies failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_ac_cfg(struct wl1271 *wl) -{ - struct acx_ac_cfg *acx; - int i, ret = 0; - - wl1271_debug(DEBUG_ACX, "acx access category config"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } - - /* - * FIXME: Configure each AC with appropriate values (most suitable - * values will probably be different for each AC. - */ - for (i = 0; i < WL1271_ACX_AC_COUNT; i++) { - acx->ac = i; - - /* - * FIXME: The following default values originate from - * the TI reference driver. What do they mean? - */ - acx->cw_min = 15; - acx->cw_max = 63; - acx->aifsn = 3; - acx->reserved = 0; - acx->tx_op_limit = 0; - - ret = wl1271_cmd_configure(wl, ACX_AC_CFG, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of access category " - "config: %d", ret); - goto out; - } - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_tid_cfg(struct wl1271 *wl) -{ - struct acx_tid_config *acx; - int i, ret = 0; - - wl1271_debug(DEBUG_ACX, "acx tid config"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } - - /* FIXME: configure each TID with a different AC reference */ - for (i = 0; i < WL1271_ACX_TID_COUNT; i++) { - acx->queue_id = i; - acx->tsid = WL1271_ACX_AC_BE; - acx->ps_scheme = WL1271_ACX_PS_SCHEME_LEGACY; - acx->ack_policy = WL1271_ACX_ACK_POLICY_LEGACY; - - ret = wl1271_cmd_configure(wl, ACX_TID_CFG, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of tid config failed: %d", ret); - goto out; - } - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_frag_threshold(struct wl1271 *wl) -{ - struct acx_frag_threshold *acx; - int ret = 0; - - wl1271_debug(DEBUG_ACX, "acx frag threshold"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD; - ret = wl1271_cmd_configure(wl, ACX_FRAG_CFG, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of frag threshold failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_tx_config_options(struct wl1271 *wl) -{ - struct acx_tx_config_options *acx; - int ret = 0; - - wl1271_debug(DEBUG_ACX, "acx tx config options"); - - acx = kzalloc(sizeof(*acx), GFP_KERNEL); - - if (!acx) { - ret = -ENOMEM; - goto out; - } - - acx->tx_compl_timeout = WL1271_ACX_TX_COMPL_TIMEOUT; - acx->tx_compl_threshold = WL1271_ACX_TX_COMPL_THRESHOLD; - ret = wl1271_cmd_configure(wl, ACX_TX_CONFIG_OPT, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_warning("Setting of tx options failed: %d", ret); - goto out; - } - -out: - kfree(acx); - return ret; -} - -int wl1271_acx_mem_cfg(struct wl1271 *wl) -{ - struct wl1271_acx_config_memory *mem_conf; - int ret; - - wl1271_debug(DEBUG_ACX, "wl1271 mem cfg"); - - mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL); - if (!mem_conf) { - ret = -ENOMEM; - goto out; - } - - /* memory config */ - mem_conf->num_stations = cpu_to_le16(DEFAULT_NUM_STATIONS); - mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS; - mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS; - mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES; - mem_conf->total_tx_descriptors = ACX_TX_DESCRIPTORS; - - ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf, - sizeof(*mem_conf)); - if (ret < 0) { - wl1271_warning("wl1271 mem config failed: %d", ret); - goto out; - } - -out: - kfree(mem_conf); - return ret; -} - -int wl1271_acx_init_mem_config(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_mem_cfg(wl); - if (ret < 0) - return ret; - - wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map), - GFP_KERNEL); - if (!wl->target_mem_map) { - wl1271_error("couldn't allocate target memory map"); - return -ENOMEM; - } - - /* we now ask for the firmware built memory map */ - ret = wl1271_acx_mem_map(wl, (void *)wl->target_mem_map, - sizeof(struct wl1271_acx_mem_map)); - if (ret < 0) { - wl1271_error("couldn't retrieve firmware memory map"); - kfree(wl->target_mem_map); - wl->target_mem_map = NULL; - return ret; - } - - /* initialize TX block book keeping */ - wl->tx_blocks_available = wl->target_mem_map->num_tx_mem_blocks; - wl1271_debug(DEBUG_TX, "available tx blocks: %d", - wl->tx_blocks_available); - - return 0; -} - -int wl1271_acx_init_rx_interrupt(struct wl1271 *wl) -{ - struct wl1271_acx_rx_config_opt *rx_conf; - int ret; - - wl1271_debug(DEBUG_ACX, "wl1271 rx interrupt config"); - - rx_conf = kzalloc(sizeof(*rx_conf), GFP_KERNEL); - if (!rx_conf) { - ret = -ENOMEM; - goto out; - } - - rx_conf->threshold = WL1271_RX_INTR_THRESHOLD_DEF; - rx_conf->timeout = WL1271_RX_INTR_TIMEOUT_DEF; - rx_conf->mblk_threshold = USHORT_MAX; /* Disabled */ - rx_conf->queue_type = RX_QUEUE_TYPE_RX_LOW_PRIORITY; - - ret = wl1271_cmd_configure(wl, ACX_RX_CONFIG_OPT, rx_conf, - sizeof(*rx_conf)); - if (ret < 0) { - wl1271_warning("wl1271 rx config opt failed: %d", ret); - goto out; - } - -out: - kfree(rx_conf); - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h deleted file mode 100644 index 9068daaf0ddf..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_acx.h +++ /dev/null @@ -1,1221 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_ACX_H__ -#define __WL1271_ACX_H__ - -#include "wl1271.h" -#include "wl1271_cmd.h" - -/************************************************************************* - - Host Interrupt Register (WiLink -> Host) - -**************************************************************************/ -/* HW Initiated interrupt Watchdog timer expiration */ -#define WL1271_ACX_INTR_WATCHDOG BIT(0) -/* Init sequence is done (masked interrupt, detection through polling only ) */ -#define WL1271_ACX_INTR_INIT_COMPLETE BIT(1) -/* Event was entered to Event MBOX #A*/ -#define WL1271_ACX_INTR_EVENT_A BIT(2) -/* Event was entered to Event MBOX #B*/ -#define WL1271_ACX_INTR_EVENT_B BIT(3) -/* Command processing completion*/ -#define WL1271_ACX_INTR_CMD_COMPLETE BIT(4) -/* Signaling the host on HW wakeup */ -#define WL1271_ACX_INTR_HW_AVAILABLE BIT(5) -/* The MISC bit is used for aggregation of RX, TxComplete and TX rate update */ -#define WL1271_ACX_INTR_DATA BIT(6) -/* Trace meassge on MBOX #A */ -#define WL1271_ACX_INTR_TRACE_A BIT(7) -/* Trace meassge on MBOX #B */ -#define WL1271_ACX_INTR_TRACE_B BIT(8) - -#define WL1271_ACX_INTR_ALL 0xFFFFFFFF -#define WL1271_ACX_ALL_EVENTS_VECTOR (WL1271_ACX_INTR_WATCHDOG | \ - WL1271_ACX_INTR_INIT_COMPLETE | \ - WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_CMD_COMPLETE | \ - WL1271_ACX_INTR_HW_AVAILABLE | \ - WL1271_ACX_INTR_DATA) - -#define WL1271_INTR_MASK (WL1271_ACX_INTR_EVENT_A | \ - WL1271_ACX_INTR_EVENT_B | \ - WL1271_ACX_INTR_DATA) - -/* Target's information element */ -struct acx_header { - struct wl1271_cmd_header cmd; - - /* acx (or information element) header */ - u16 id; - - /* payload length (not including headers */ - u16 len; -}; - -struct acx_error_counter { - struct acx_header header; - - /* The number of PLCP errors since the last time this */ - /* information element was interrogated. This field is */ - /* automatically cleared when it is interrogated.*/ - u32 PLCP_error; - - /* The number of FCS errors since the last time this */ - /* information element was interrogated. This field is */ - /* automatically cleared when it is interrogated.*/ - u32 FCS_error; - - /* The number of MPDUs without PLCP header errors received*/ - /* since the last time this information element was interrogated. */ - /* This field is automatically cleared when it is interrogated.*/ - u32 valid_frame; - - /* the number of missed sequence numbers in the squentially */ - /* values of frames seq numbers */ - u32 seq_num_miss; -} __attribute__ ((packed)); - -struct acx_revision { - struct acx_header header; - - /* - * The WiLink firmware version, an ASCII string x.x.x.x, - * that uniquely identifies the current firmware. - * The left most digit is incremented each time a - * significant change is made to the firmware, such as - * code redesign or new platform support. - * The second digit is incremented when major enhancements - * are added or major fixes are made. - * The third digit is incremented for each GA release. - * The fourth digit is incremented for each build. - * The first two digits identify a firmware release version, - * in other words, a unique set of features. - * The first three digits identify a GA release. - */ - char fw_version[20]; - - /* - * This 4 byte field specifies the WiLink hardware version. - * bits 0 - 15: Reserved. - * bits 16 - 23: Version ID - The WiLink version ID - * (1 = first spin, 2 = second spin, and so on). - * bits 24 - 31: Chip ID - The WiLink chip ID. - */ - u32 hw_version; -} __attribute__ ((packed)); - -enum wl1271_psm_mode { - /* Active mode */ - WL1271_PSM_CAM = 0, - - /* Power save mode */ - WL1271_PSM_PS = 1, - - /* Extreme low power */ - WL1271_PSM_ELP = 2, -}; - -struct acx_sleep_auth { - struct acx_header header; - - /* The sleep level authorization of the device. */ - /* 0 - Always active*/ - /* 1 - Power down mode: light / fast sleep*/ - /* 2 - ELP mode: Deep / Max sleep*/ - u8 sleep_auth; - u8 padding[3]; -} __attribute__ ((packed)); - -enum { - HOSTIF_PCI_MASTER_HOST_INDIRECT, - HOSTIF_PCI_MASTER_HOST_DIRECT, - HOSTIF_SLAVE, - HOSTIF_PKT_RING, - HOSTIF_DONTCARE = 0xFF -}; - -#define DEFAULT_UCAST_PRIORITY 0 -#define DEFAULT_RX_Q_PRIORITY 0 -#define DEFAULT_NUM_STATIONS 1 -#define DEFAULT_RXQ_PRIORITY 0 /* low 0 .. 15 high */ -#define DEFAULT_RXQ_TYPE 0x07 /* All frames, Data/Ctrl/Mgmt */ -#define TRACE_BUFFER_MAX_SIZE 256 - -#define DP_RX_PACKET_RING_CHUNK_SIZE 1600 -#define DP_TX_PACKET_RING_CHUNK_SIZE 1600 -#define DP_RX_PACKET_RING_CHUNK_NUM 2 -#define DP_TX_PACKET_RING_CHUNK_NUM 2 -#define DP_TX_COMPLETE_TIME_OUT 20 -#define FW_TX_CMPLT_BLOCK_SIZE 16 - -#define TX_MSDU_LIFETIME_MIN 0 -#define TX_MSDU_LIFETIME_MAX 3000 -#define TX_MSDU_LIFETIME_DEF 512 -#define RX_MSDU_LIFETIME_MIN 0 -#define RX_MSDU_LIFETIME_MAX 0xFFFFFFFF -#define RX_MSDU_LIFETIME_DEF 512000 - -struct acx_rx_msdu_lifetime { - struct acx_header header; - - /* - * The maximum amount of time, in TU, before the - * firmware discards the MSDU. - */ - u32 lifetime; -} __attribute__ ((packed)); - -/* - * RX Config Options Table - * Bit Definition - * === ========== - * 31:14 Reserved - * 13 Copy RX Status - when set, write three receive status words - * to top of rx'd MPDUs. - * When cleared, do not write three status words (added rev 1.5) - * 12 Reserved - * 11 RX Complete upon FCS error - when set, give rx complete - * interrupt for FCS errors, after the rx filtering, e.g. unicast - * frames not to us with FCS error will not generate an interrupt. - * 10 SSID Filter Enable - When set, the WiLink discards all beacon, - * probe request, and probe response frames with an SSID that does - * not match the SSID specified by the host in the START/JOIN - * command. - * When clear, the WiLink receives frames with any SSID. - * 9 Broadcast Filter Enable - When set, the WiLink discards all - * broadcast frames. When clear, the WiLink receives all received - * broadcast frames. - * 8:6 Reserved - * 5 BSSID Filter Enable - When set, the WiLink discards any frames - * with a BSSID that does not match the BSSID specified by the - * host. - * When clear, the WiLink receives frames from any BSSID. - * 4 MAC Addr Filter - When set, the WiLink discards any frames - * with a destination address that does not match the MAC address - * of the adaptor. - * When clear, the WiLink receives frames destined to any MAC - * address. - * 3 Promiscuous - When set, the WiLink receives all valid frames - * (i.e., all frames that pass the FCS check). - * When clear, only frames that pass the other filters specified - * are received. - * 2 FCS - When set, the WiLink includes the FCS with the received - * frame. - * When cleared, the FCS is discarded. - * 1 PLCP header - When set, write all data from baseband to frame - * buffer including PHY header. - * 0 Reserved - Always equal to 0. - * - * RX Filter Options Table - * Bit Definition - * === ========== - * 31:12 Reserved - Always equal to 0. - * 11 Association - When set, the WiLink receives all association - * related frames (association request/response, reassocation - * request/response, and disassociation). When clear, these frames - * are discarded. - * 10 Auth/De auth - When set, the WiLink receives all authentication - * and de-authentication frames. When clear, these frames are - * discarded. - * 9 Beacon - When set, the WiLink receives all beacon frames. - * When clear, these frames are discarded. - * 8 Contention Free - When set, the WiLink receives all contention - * free frames. - * When clear, these frames are discarded. - * 7 Control - When set, the WiLink receives all control frames. - * When clear, these frames are discarded. - * 6 Data - When set, the WiLink receives all data frames. - * When clear, these frames are discarded. - * 5 FCS Error - When set, the WiLink receives frames that have FCS - * errors. - * When clear, these frames are discarded. - * 4 Management - When set, the WiLink receives all management - * frames. - * When clear, these frames are discarded. - * 3 Probe Request - When set, the WiLink receives all probe request - * frames. - * When clear, these frames are discarded. - * 2 Probe Response - When set, the WiLink receives all probe - * response frames. - * When clear, these frames are discarded. - * 1 RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK - * frames. - * When clear, these frames are discarded. - * 0 Rsvd Type/Sub Type - When set, the WiLink receives all frames - * that have reserved frame types and sub types as defined by the - * 802.11 specification. - * When clear, these frames are discarded. - */ -struct acx_rx_config { - struct acx_header header; - - u32 config_options; - u32 filter_options; -} __attribute__ ((packed)); - -struct acx_packet_detection { - struct acx_header header; - - u32 threshold; -} __attribute__ ((packed)); - - -enum acx_slot_type { - SLOT_TIME_LONG = 0, - SLOT_TIME_SHORT = 1, - DEFAULT_SLOT_TIME = SLOT_TIME_SHORT, - MAX_SLOT_TIMES = 0xFF -}; - -#define STATION_WONE_INDEX 0 - -struct acx_slot { - struct acx_header header; - - u8 wone_index; /* Reserved */ - u8 slot_time; - u8 reserved[6]; -} __attribute__ ((packed)); - - -#define ADDRESS_GROUP_MAX (8) -#define ADDRESS_GROUP_MAX_LEN (ETH_ALEN * ADDRESS_GROUP_MAX) - -struct acx_dot11_grp_addr_tbl { - struct acx_header header; - - u8 enabled; - u8 num_groups; - u8 pad[2]; - u8 mac_table[ADDRESS_GROUP_MAX_LEN]; -} __attribute__ ((packed)); - - -#define RX_TIMEOUT_PS_POLL_MIN 0 -#define RX_TIMEOUT_PS_POLL_MAX (200000) -#define RX_TIMEOUT_PS_POLL_DEF (15) -#define RX_TIMEOUT_UPSD_MIN 0 -#define RX_TIMEOUT_UPSD_MAX (200000) -#define RX_TIMEOUT_UPSD_DEF (15) - -struct acx_rx_timeout { - struct acx_header header; - - /* - * The longest time the STA will wait to receive - * traffic from the AP after a PS-poll has been - * transmitted. - */ - u16 ps_poll_timeout; - - /* - * The longest time the STA will wait to receive - * traffic from the AP after a frame has been sent - * from an UPSD enabled queue. - */ - u16 upsd_timeout; -} __attribute__ ((packed)); - -#define RTS_THRESHOLD_MIN 0 -#define RTS_THRESHOLD_MAX 4096 -#define RTS_THRESHOLD_DEF 2347 - -struct acx_rts_threshold { - struct acx_header header; - - u16 threshold; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_beacon_filter_option { - struct acx_header header; - - u8 enable; - - /* - * The number of beacons without the unicast TIM - * bit set that the firmware buffers before - * signaling the host about ready frames. - * When set to 0 and the filter is enabled, beacons - * without the unicast TIM bit set are dropped. - */ - u8 max_num_beacons; - u8 pad[2]; -} __attribute__ ((packed)); - -/* - * ACXBeaconFilterEntry (not 221) - * Byte Offset Size (Bytes) Definition - * =========== ============ ========== - * 0 1 IE identifier - * 1 1 Treatment bit mask - * - * ACXBeaconFilterEntry (221) - * Byte Offset Size (Bytes) Definition - * =========== ============ ========== - * 0 1 IE identifier - * 1 1 Treatment bit mask - * 2 3 OUI - * 5 1 Type - * 6 2 Version - * - * - * Treatment bit mask - The information element handling: - * bit 0 - The information element is compared and transferred - * in case of change. - * bit 1 - The information element is transferred to the host - * with each appearance or disappearance. - * Note that both bits can be set at the same time. - */ -#define BEACON_FILTER_TABLE_MAX_IE_NUM (32) -#define BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM (6) -#define BEACON_FILTER_TABLE_IE_ENTRY_SIZE (2) -#define BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE (6) -#define BEACON_FILTER_TABLE_MAX_SIZE ((BEACON_FILTER_TABLE_MAX_IE_NUM * \ - BEACON_FILTER_TABLE_IE_ENTRY_SIZE) + \ - (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \ - BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE)) - -struct acx_beacon_filter_ie_table { - struct acx_header header; - - u8 num_ie; - u8 table[BEACON_FILTER_TABLE_MAX_SIZE]; - u8 pad[3]; -} __attribute__ ((packed)); - -enum { - SG_ENABLE = 0, - SG_DISABLE, - SG_SENSE_NO_ACTIVITY, - SG_SENSE_ACTIVE -}; - -struct acx_bt_wlan_coex { - struct acx_header header; - - /* - * 0 -> PTA enabled - * 1 -> PTA disabled - * 2 -> sense no active mode, i.e. - * an interrupt is sent upon - * BT activity. - * 3 -> PTA is switched on in response - * to the interrupt sending. - */ - u8 enable; - u8 pad[3]; -} __attribute__ ((packed)); - -#define PTA_ANTENNA_TYPE_DEF (0) -#define PTA_BT_HP_MAXTIME_DEF (2000) -#define PTA_WLAN_HP_MAX_TIME_DEF (5000) -#define PTA_SENSE_DISABLE_TIMER_DEF (1350) -#define PTA_PROTECTIVE_RX_TIME_DEF (1500) -#define PTA_PROTECTIVE_TX_TIME_DEF (1500) -#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000) -#define PTA_SIGNALING_TYPE_DEF (1) -#define PTA_AFH_LEVERAGE_ON_DEF (0) -#define PTA_NUMBER_QUIET_CYCLE_DEF (0) -#define PTA_MAX_NUM_CTS_DEF (3) -#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2) -#define PTA_NUMBER_OF_BT_PACKETS_DEF (2) -#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500) -#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000) -#define PTA_CYCLE_TIME_FAST_DEF (8700) -#define PTA_RX_FOR_AVALANCHE_DEF (5) -#define PTA_ELP_HP_DEF (0) -#define PTA_ANTI_STARVE_PERIOD_DEF (500) -#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4) -#define PTA_ALLOW_PA_SD_DEF (1) -#define PTA_TIME_BEFORE_BEACON_DEF (6300) -#define PTA_HPDM_MAX_TIME_DEF (1600) -#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550) -#define PTA_AUTO_MODE_NO_CTS_DEF (0) -#define PTA_BT_HP_RESPECTED_DEF (3) -#define PTA_WLAN_RX_MIN_RATE_DEF (24) -#define PTA_ACK_MODE_DEF (1) - -struct acx_bt_wlan_coex_param { - struct acx_header header; - - /* - * The minimum rate of a received WLAN packet in the STA, - * during protective mode, of which a new BT-HP request - * during this Rx will always be respected and gain the antenna. - */ - u32 min_rate; - - /* Max time the BT HP will be respected. */ - u16 bt_hp_max_time; - - /* Max time the WLAN HP will be respected. */ - u16 wlan_hp_max_time; - - /* - * The time between the last BT activity - * and the moment when the sense mode returns - * to SENSE_INACTIVE. - */ - u16 sense_disable_timer; - - /* Time before the next BT HP instance */ - u16 rx_time_bt_hp; - u16 tx_time_bt_hp; - - /* range: 10-20000 default: 1500 */ - u16 rx_time_bt_hp_fast; - u16 tx_time_bt_hp_fast; - - /* range: 2000-65535 default: 8700 */ - u16 wlan_cycle_fast; - - /* range: 0 - 15000 (Msec) default: 1000 */ - u16 bt_anti_starvation_period; - - /* range 400-10000(Usec) default: 3000 */ - u16 next_bt_lp_packet; - - /* Deafult: worst case for BT DH5 traffic */ - u16 wake_up_beacon; - - /* range: 0-50000(Usec) default: 1050 */ - u16 hp_dm_max_guard_time; - - /* - * This is to prevent both BT & WLAN antenna - * starvation. - * Range: 100-50000(Usec) default:2550 - */ - u16 next_wlan_packet; - - /* 0 -> shared antenna */ - u8 antenna_type; - - /* - * 0 -> TI legacy - * 1 -> Palau - */ - u8 signal_type; - - /* - * BT AFH status - * 0 -> no AFH - * 1 -> from dedicated GPIO - * 2 -> AFH on (from host) - */ - u8 afh_leverage_on; - - /* - * The number of cycles during which no - * TX will be sent after 1 cycle of RX - * transaction in protective mode - */ - u8 quiet_cycle_num; - - /* - * The maximum number of CTSs that will - * be sent for receiving RX packet in - * protective mode - */ - u8 max_cts; - - /* - * The number of WLAN packets - * transferred in common mode before - * switching to BT. - */ - u8 wlan_packets_num; - - /* - * The number of BT packets - * transferred in common mode before - * switching to WLAN. - */ - u8 bt_packets_num; - - /* range: 1-255 default: 5 */ - u8 missed_rx_avalanche; - - /* range: 0-1 default: 1 */ - u8 wlan_elp_hp; - - /* range: 0 - 15 default: 4 */ - u8 bt_anti_starvation_cycles; - - u8 ack_mode_dual_ant; - - /* - * Allow PA_SD assertion/de-assertion - * during enabled BT activity. - */ - u8 pa_sd_enable; - - /* - * Enable/Disable PTA in auto mode: - * Support Both Active & P.S modes - */ - u8 pta_auto_mode_enable; - - /* range: 0 - 20 default: 1 */ - u8 bt_hp_respected_num; -} __attribute__ ((packed)); - -#define CCA_THRSH_ENABLE_ENERGY_D 0x140A -#define CCA_THRSH_DISABLE_ENERGY_D 0xFFEF - -struct acx_energy_detection { - struct acx_header header; - - /* The RX Clear Channel Assessment threshold in the PHY */ - u16 rx_cca_threshold; - u8 tx_energy_detection; - u8 pad; -} __attribute__ ((packed)); - -#define BCN_RX_TIMEOUT_DEF_VALUE 10000 -#define BROADCAST_RX_TIMEOUT_DEF_VALUE 20000 -#define RX_BROADCAST_IN_PS_DEF_VALUE 1 -#define CONSECUTIVE_PS_POLL_FAILURE_DEF 4 - -struct acx_beacon_broadcast { - struct acx_header header; - - u16 beacon_rx_timeout; - u16 broadcast_timeout; - - /* Enables receiving of broadcast packets in PS mode */ - u8 rx_broadcast_in_ps; - - /* Consecutive PS Poll failures before updating the host */ - u8 ps_poll_threshold; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_event_mask { - struct acx_header header; - - u32 event_mask; - u32 high_event_mask; /* Unused */ -} __attribute__ ((packed)); - -#define CFG_RX_FCS BIT(2) -#define CFG_RX_ALL_GOOD BIT(3) -#define CFG_UNI_FILTER_EN BIT(4) -#define CFG_BSSID_FILTER_EN BIT(5) -#define CFG_MC_FILTER_EN BIT(6) -#define CFG_MC_ADDR0_EN BIT(7) -#define CFG_MC_ADDR1_EN BIT(8) -#define CFG_BC_REJECT_EN BIT(9) -#define CFG_SSID_FILTER_EN BIT(10) -#define CFG_RX_INT_FCS_ERROR BIT(11) -#define CFG_RX_INT_ENCRYPTED BIT(12) -#define CFG_RX_WR_RX_STATUS BIT(13) -#define CFG_RX_FILTER_NULTI BIT(14) -#define CFG_RX_RESERVE BIT(15) -#define CFG_RX_TIMESTAMP_TSF BIT(16) - -#define CFG_RX_RSV_EN BIT(0) -#define CFG_RX_RCTS_ACK BIT(1) -#define CFG_RX_PRSP_EN BIT(2) -#define CFG_RX_PREQ_EN BIT(3) -#define CFG_RX_MGMT_EN BIT(4) -#define CFG_RX_FCS_ERROR BIT(5) -#define CFG_RX_DATA_EN BIT(6) -#define CFG_RX_CTL_EN BIT(7) -#define CFG_RX_CF_EN BIT(8) -#define CFG_RX_BCN_EN BIT(9) -#define CFG_RX_AUTH_EN BIT(10) -#define CFG_RX_ASSOC_EN BIT(11) - -#define SCAN_PASSIVE BIT(0) -#define SCAN_5GHZ_BAND BIT(1) -#define SCAN_TRIGGERED BIT(2) -#define SCAN_PRIORITY_HIGH BIT(3) - -struct acx_feature_config { - struct acx_header header; - - u32 options; - u32 data_flow_options; -} __attribute__ ((packed)); - -struct acx_current_tx_power { - struct acx_header header; - - u8 current_tx_power; - u8 padding[3]; -} __attribute__ ((packed)); - -enum acx_wake_up_event { - WAKE_UP_EVENT_BEACON_BITMAP = 0x01, /* Wake on every Beacon*/ - WAKE_UP_EVENT_DTIM_BITMAP = 0x02, /* Wake on every DTIM*/ - WAKE_UP_EVENT_N_DTIM_BITMAP = 0x04, /* Wake on every Nth DTIM */ - WAKE_UP_EVENT_N_BEACONS_BITMAP = 0x08, /* Wake on every Nth Beacon */ - WAKE_UP_EVENT_BITS_MASK = 0x0F -}; - -struct acx_wake_up_condition { - struct acx_header header; - - u8 wake_up_event; /* Only one bit can be set */ - u8 listen_interval; - u8 pad[2]; -} __attribute__ ((packed)); - -struct acx_aid { - struct acx_header header; - - /* - * To be set when associated with an AP. - */ - u16 aid; - u8 pad[2]; -} __attribute__ ((packed)); - -enum acx_preamble_type { - ACX_PREAMBLE_LONG = 0, - ACX_PREAMBLE_SHORT = 1 -}; - -struct acx_preamble { - struct acx_header header; - - /* - * When set, the WiLink transmits the frames with a short preamble and - * when cleared, the WiLink transmits the frames with a long preamble. - */ - u8 preamble; - u8 padding[3]; -} __attribute__ ((packed)); - -enum acx_ctsprotect_type { - CTSPROTECT_DISABLE = 0, - CTSPROTECT_ENABLE = 1 -}; - -struct acx_ctsprotect { - struct acx_header header; - u8 ctsprotect; - u8 padding[3]; -} __attribute__ ((packed)); - -struct acx_tx_statistics { - u32 internal_desc_overflow; -} __attribute__ ((packed)); - -struct acx_rx_statistics { - u32 out_of_mem; - u32 hdr_overflow; - u32 hw_stuck; - u32 dropped; - u32 fcs_err; - u32 xfr_hint_trig; - u32 path_reset; - u32 reset_counter; -} __attribute__ ((packed)); - -struct acx_dma_statistics { - u32 rx_requested; - u32 rx_errors; - u32 tx_requested; - u32 tx_errors; -} __attribute__ ((packed)); - -struct acx_isr_statistics { - /* host command complete */ - u32 cmd_cmplt; - - /* fiqisr() */ - u32 fiqs; - - /* (INT_STS_ND & INT_TRIG_RX_HEADER) */ - u32 rx_headers; - - /* (INT_STS_ND & INT_TRIG_RX_CMPLT) */ - u32 rx_completes; - - /* (INT_STS_ND & INT_TRIG_NO_RX_BUF) */ - u32 rx_mem_overflow; - - /* (INT_STS_ND & INT_TRIG_S_RX_RDY) */ - u32 rx_rdys; - - /* irqisr() */ - u32 irqs; - - /* (INT_STS_ND & INT_TRIG_TX_PROC) */ - u32 tx_procs; - - /* (INT_STS_ND & INT_TRIG_DECRYPT_DONE) */ - u32 decrypt_done; - - /* (INT_STS_ND & INT_TRIG_DMA0) */ - u32 dma0_done; - - /* (INT_STS_ND & INT_TRIG_DMA1) */ - u32 dma1_done; - - /* (INT_STS_ND & INT_TRIG_TX_EXC_CMPLT) */ - u32 tx_exch_complete; - - /* (INT_STS_ND & INT_TRIG_COMMAND) */ - u32 commands; - - /* (INT_STS_ND & INT_TRIG_RX_PROC) */ - u32 rx_procs; - - /* (INT_STS_ND & INT_TRIG_PM_802) */ - u32 hw_pm_mode_changes; - - /* (INT_STS_ND & INT_TRIG_ACKNOWLEDGE) */ - u32 host_acknowledges; - - /* (INT_STS_ND & INT_TRIG_PM_PCI) */ - u32 pci_pm; - - /* (INT_STS_ND & INT_TRIG_ACM_WAKEUP) */ - u32 wakeups; - - /* (INT_STS_ND & INT_TRIG_LOW_RSSI) */ - u32 low_rssi; -} __attribute__ ((packed)); - -struct acx_wep_statistics { - /* WEP address keys configured */ - u32 addr_key_count; - - /* default keys configured */ - u32 default_key_count; - - u32 reserved; - - /* number of times that WEP key not found on lookup */ - u32 key_not_found; - - /* number of times that WEP key decryption failed */ - u32 decrypt_fail; - - /* WEP packets decrypted */ - u32 packets; - - /* WEP decrypt interrupts */ - u32 interrupt; -} __attribute__ ((packed)); - -#define ACX_MISSED_BEACONS_SPREAD 10 - -struct acx_pwr_statistics { - /* the amount of enters into power save mode (both PD & ELP) */ - u32 ps_enter; - - /* the amount of enters into ELP mode */ - u32 elp_enter; - - /* the amount of missing beacon interrupts to the host */ - u32 missing_bcns; - - /* the amount of wake on host-access times */ - u32 wake_on_host; - - /* the amount of wake on timer-expire */ - u32 wake_on_timer_exp; - - /* the number of packets that were transmitted with PS bit set */ - u32 tx_with_ps; - - /* the number of packets that were transmitted with PS bit clear */ - u32 tx_without_ps; - - /* the number of received beacons */ - u32 rcvd_beacons; - - /* the number of entering into PowerOn (power save off) */ - u32 power_save_off; - - /* the number of entries into power save mode */ - u16 enable_ps; - - /* - * the number of exits from power save, not including failed PS - * transitions - */ - u16 disable_ps; - - /* - * the number of times the TSF counter was adjusted because - * of drift - */ - u32 fix_tsf_ps; - - /* Gives statistics about the spread continuous missed beacons. - * The 16 LSB are dedicated for the PS mode. - * The 16 MSB are dedicated for the PS mode. - * cont_miss_bcns_spread[0] - single missed beacon. - * cont_miss_bcns_spread[1] - two continuous missed beacons. - * cont_miss_bcns_spread[2] - three continuous missed beacons. - * ... - * cont_miss_bcns_spread[9] - ten and more continuous missed beacons. - */ - u32 cont_miss_bcns_spread[ACX_MISSED_BEACONS_SPREAD]; - - /* the number of beacons in awake mode */ - u32 rcvd_awake_beacons; -} __attribute__ ((packed)); - -struct acx_mic_statistics { - u32 rx_pkts; - u32 calc_failure; -} __attribute__ ((packed)); - -struct acx_aes_statistics { - u32 encrypt_fail; - u32 decrypt_fail; - u32 encrypt_packets; - u32 decrypt_packets; - u32 encrypt_interrupt; - u32 decrypt_interrupt; -} __attribute__ ((packed)); - -struct acx_event_statistics { - u32 heart_beat; - u32 calibration; - u32 rx_mismatch; - u32 rx_mem_empty; - u32 rx_pool; - u32 oom_late; - u32 phy_transmit_error; - u32 tx_stuck; -} __attribute__ ((packed)); - -struct acx_ps_statistics { - u32 pspoll_timeouts; - u32 upsd_timeouts; - u32 upsd_max_sptime; - u32 upsd_max_apturn; - u32 pspoll_max_apturn; - u32 pspoll_utilization; - u32 upsd_utilization; -} __attribute__ ((packed)); - -struct acx_rxpipe_statistics { - u32 rx_prep_beacon_drop; - u32 descr_host_int_trig_rx_data; - u32 beacon_buffer_thres_host_int_trig_rx_data; - u32 missed_beacon_host_int_trig_rx_data; - u32 tx_xfr_host_int_trig_rx_data; -} __attribute__ ((packed)); - -struct acx_statistics { - struct acx_header header; - - struct acx_tx_statistics tx; - struct acx_rx_statistics rx; - struct acx_dma_statistics dma; - struct acx_isr_statistics isr; - struct acx_wep_statistics wep; - struct acx_pwr_statistics pwr; - struct acx_aes_statistics aes; - struct acx_mic_statistics mic; - struct acx_event_statistics event; - struct acx_ps_statistics ps; - struct acx_rxpipe_statistics rxpipe; -} __attribute__ ((packed)); - -#define ACX_MAX_RATE_CLASSES 8 -#define ACX_RATE_MASK_UNSPECIFIED 0 -#define ACX_RATE_MASK_ALL 0x1eff -#define ACX_RATE_RETRY_LIMIT 10 - -struct acx_rate_class { - u32 enabled_rates; - u8 short_retry_limit; - u8 long_retry_limit; - u8 aflags; - u8 reserved; -}; - -struct acx_rate_policy { - struct acx_header header; - - u32 rate_class_cnt; - struct acx_rate_class rate_class[ACX_MAX_RATE_CLASSES]; -} __attribute__ ((packed)); - -#define WL1271_ACX_AC_COUNT 4 - -struct acx_ac_cfg { - struct acx_header header; - u8 ac; - u8 cw_min; - u16 cw_max; - u8 aifsn; - u8 reserved; - u16 tx_op_limit; -} __attribute__ ((packed)); - -enum wl1271_acx_ac { - WL1271_ACX_AC_BE = 0, - WL1271_ACX_AC_BK = 1, - WL1271_ACX_AC_VI = 2, - WL1271_ACX_AC_VO = 3, - WL1271_ACX_AC_CTS2SELF = 4, - WL1271_ACX_AC_ANY_TID = 0x1F, - WL1271_ACX_AC_INVALID = 0xFF, -}; - -enum wl1271_acx_ps_scheme { - WL1271_ACX_PS_SCHEME_LEGACY = 0, - WL1271_ACX_PS_SCHEME_UPSD_TRIGGER = 1, - WL1271_ACX_PS_SCHEME_LEGACY_PSPOLL = 2, - WL1271_ACX_PS_SCHEME_SAPSD = 3, -}; - -enum wl1271_acx_ack_policy { - WL1271_ACX_ACK_POLICY_LEGACY = 0, - WL1271_ACX_ACK_POLICY_NO_ACK = 1, - WL1271_ACX_ACK_POLICY_BLOCK = 2, -}; - -#define WL1271_ACX_TID_COUNT 7 - -struct acx_tid_config { - struct acx_header header; - u8 queue_id; - u8 channel_type; - u8 tsid; - u8 ps_scheme; - u8 ack_policy; - u8 padding[3]; - u32 apsd_conf[2]; -} __attribute__ ((packed)); - -struct acx_frag_threshold { - struct acx_header header; - u16 frag_threshold; - u8 padding[2]; -} __attribute__ ((packed)); - -#define WL1271_ACX_TX_COMPL_TIMEOUT 5 -#define WL1271_ACX_TX_COMPL_THRESHOLD 5 - -struct acx_tx_config_options { - struct acx_header header; - u16 tx_compl_timeout; /* msec */ - u16 tx_compl_threshold; /* number of packets */ -} __attribute__ ((packed)); - -#define ACX_RX_MEM_BLOCKS 64 -#define ACX_TX_MIN_MEM_BLOCKS 64 -#define ACX_TX_DESCRIPTORS 32 -#define ACX_NUM_SSID_PROFILES 1 - -struct wl1271_acx_config_memory { - struct acx_header header; - - u8 rx_mem_block_num; - u8 tx_min_mem_block_num; - u8 num_stations; - u8 num_ssid_profiles; - u32 total_tx_descriptors; -} __attribute__ ((packed)); - -struct wl1271_acx_mem_map { - struct acx_header header; - - void *code_start; - void *code_end; - - void *wep_defkey_start; - void *wep_defkey_end; - - void *sta_table_start; - void *sta_table_end; - - void *packet_template_start; - void *packet_template_end; - - /* Address of the TX result interface (control block) */ - u32 tx_result; - u32 tx_result_queue_start; - - void *queue_memory_start; - void *queue_memory_end; - - u32 packet_memory_pool_start; - u32 packet_memory_pool_end; - - void *debug_buffer1_start; - void *debug_buffer1_end; - - void *debug_buffer2_start; - void *debug_buffer2_end; - - /* Number of blocks FW allocated for TX packets */ - u32 num_tx_mem_blocks; - - /* Number of blocks FW allocated for RX packets */ - u32 num_rx_mem_blocks; - - /* the following 4 fields are valid in SLAVE mode only */ - u8 *tx_cbuf; - u8 *rx_cbuf; - void *rx_ctrl; - void *tx_ctrl; -} __attribute__ ((packed)); - -enum wl1271_acx_rx_queue_type { - RX_QUEUE_TYPE_RX_LOW_PRIORITY, /* All except the high priority */ - RX_QUEUE_TYPE_RX_HIGH_PRIORITY, /* Management and voice packets */ - RX_QUEUE_TYPE_NUM, - RX_QUEUE_TYPE_MAX = USHORT_MAX -}; - -#define WL1271_RX_INTR_THRESHOLD_DEF 0 /* no pacing, send interrupt on - * every event */ -#define WL1271_RX_INTR_THRESHOLD_MIN 0 -#define WL1271_RX_INTR_THRESHOLD_MAX 15 - -#define WL1271_RX_INTR_TIMEOUT_DEF 5 -#define WL1271_RX_INTR_TIMEOUT_MIN 1 -#define WL1271_RX_INTR_TIMEOUT_MAX 100 - -struct wl1271_acx_rx_config_opt { - struct acx_header header; - - u16 mblk_threshold; - u16 threshold; - u16 timeout; - u8 queue_type; - u8 reserved; -} __attribute__ ((packed)); - -enum { - ACX_WAKE_UP_CONDITIONS = 0x0002, - ACX_MEM_CFG = 0x0003, - ACX_SLOT = 0x0004, - ACX_AC_CFG = 0x0007, - ACX_MEM_MAP = 0x0008, - ACX_AID = 0x000A, - /* ACX_FW_REV is missing in the ref driver, but seems to work */ - ACX_FW_REV = 0x000D, - ACX_MEDIUM_USAGE = 0x000F, - ACX_RX_CFG = 0x0010, - ACX_TX_QUEUE_CFG = 0x0011, /* FIXME: only used by wl1251 */ - ACX_STATISTICS = 0x0013, /* Debug API */ - ACX_PWR_CONSUMPTION_STATISTICS = 0x0014, - ACX_FEATURE_CFG = 0x0015, - ACX_TID_CFG = 0x001A, - ACX_PS_RX_STREAMING = 0x001B, - ACX_BEACON_FILTER_OPT = 0x001F, - ACX_NOISE_HIST = 0x0021, - ACX_HDK_VERSION = 0x0022, /* ??? */ - ACX_PD_THRESHOLD = 0x0023, - ACX_TX_CONFIG_OPT = 0x0024, - ACX_CCA_THRESHOLD = 0x0025, - ACX_EVENT_MBOX_MASK = 0x0026, - ACX_CONN_MONIT_PARAMS = 0x002D, - ACX_CONS_TX_FAILURE = 0x002F, - ACX_BCN_DTIM_OPTIONS = 0x0031, - ACX_SG_ENABLE = 0x0032, - ACX_SG_CFG = 0x0033, - ACX_BEACON_FILTER_TABLE = 0x0038, - ACX_ARP_IP_FILTER = 0x0039, - ACX_ROAMING_STATISTICS_TBL = 0x003B, - ACX_RATE_POLICY = 0x003D, - ACX_CTS_PROTECTION = 0x003E, - ACX_SLEEP_AUTH = 0x003F, - ACX_PREAMBLE_TYPE = 0x0040, - ACX_ERROR_CNT = 0x0041, - ACX_IBSS_FILTER = 0x0044, - ACX_SERVICE_PERIOD_TIMEOUT = 0x0045, - ACX_TSF_INFO = 0x0046, - ACX_CONFIG_PS_WMM = 0x0049, - ACX_ENABLE_RX_DATA_FILTER = 0x004A, - ACX_SET_RX_DATA_FILTER = 0x004B, - ACX_GET_DATA_FILTER_STATISTICS = 0x004C, - ACX_RX_CONFIG_OPT = 0x004E, - ACX_FRAG_CFG = 0x004F, - ACX_BET_ENABLE = 0x0050, - ACX_RSSI_SNR_TRIGGER = 0x0051, - ACX_RSSI_SNR_WEIGHTS = 0x0051, - ACX_KEEP_ALIVE_MODE = 0x0052, - ACX_SET_KEEP_ALIVE_CONFIG = 0x0054, - ACX_BA_SESSION_RESPONDER_POLICY = 0x0055, - ACX_BA_SESSION_INITIATOR_POLICY = 0x0056, - ACX_PEER_HT_CAP = 0x0057, - ACX_HT_BSS_OPERATION = 0x0058, - ACX_COEX_ACTIVITY = 0x0059, - DOT11_RX_MSDU_LIFE_TIME = 0x1004, - DOT11_CUR_TX_PWR = 0x100D, - DOT11_RX_DOT11_MODE = 0x1012, - DOT11_RTS_THRESHOLD = 0x1013, - DOT11_GROUP_ADDRESS_TBL = 0x1014, - - MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL, - - MAX_IE = 0xFFFF -}; - - -int wl1271_acx_wake_up_conditions(struct wl1271 *wl, u8 wake_up_event, - u8 listen_interval); -int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth); -int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len); -int wl1271_acx_tx_power(struct wl1271 *wl, int power); -int wl1271_acx_feature_cfg(struct wl1271 *wl); -int wl1271_acx_mem_map(struct wl1271 *wl, - struct acx_header *mem_map, size_t len); -int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl, u32 life_time); -int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter); -int wl1271_acx_pd_threshold(struct wl1271 *wl); -int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time); -int wl1271_acx_group_address_tbl(struct wl1271 *wl); -int wl1271_acx_service_period_timeout(struct wl1271 *wl); -int wl1271_acx_rts_threshold(struct wl1271 *wl, u16 rts_threshold); -int wl1271_acx_beacon_filter_opt(struct wl1271 *wl); -int wl1271_acx_beacon_filter_table(struct wl1271 *wl); -int wl1271_acx_sg_enable(struct wl1271 *wl); -int wl1271_acx_sg_cfg(struct wl1271 *wl); -int wl1271_acx_cca_threshold(struct wl1271 *wl); -int wl1271_acx_bcn_dtim_options(struct wl1271 *wl); -int wl1271_acx_aid(struct wl1271 *wl, u16 aid); -int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask); -int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble); -int wl1271_acx_cts_protect(struct wl1271 *wl, - enum acx_ctsprotect_type ctsprotect); -int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats); -int wl1271_acx_rate_policies(struct wl1271 *wl); -int wl1271_acx_ac_cfg(struct wl1271 *wl); -int wl1271_acx_tid_cfg(struct wl1271 *wl); -int wl1271_acx_frag_threshold(struct wl1271 *wl); -int wl1271_acx_tx_config_options(struct wl1271 *wl); -int wl1271_acx_mem_cfg(struct wl1271 *wl); -int wl1271_acx_init_mem_config(struct wl1271 *wl); -int wl1271_acx_init_rx_interrupt(struct wl1271 *wl); - -#endif /* __WL1271_ACX_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c deleted file mode 100644 index 8228ef474a7e..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_boot.c +++ /dev/null @@ -1,541 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include - -#include "wl1271_acx.h" -#include "wl1271_reg.h" -#include "wl1271_boot.h" -#include "wl1271_spi.h" -#include "wl1271_event.h" - -static struct wl1271_partition_set part_table[PART_TABLE_LEN] = { - [PART_DOWN] = { - .mem = { - .start = 0x00000000, - .size = 0x000177c0 - }, - .reg = { - .start = REGISTERS_BASE, - .size = 0x00008800 - }, - }, - - [PART_WORK] = { - .mem = { - .start = 0x00040000, - .size = 0x00014fc0 - }, - .reg = { - .start = REGISTERS_BASE, - .size = 0x0000b000 - }, - }, - - [PART_DRPW] = { - .mem = { - .start = 0x00040000, - .size = 0x00014fc0 - }, - .reg = { - .start = DRPW_BASE, - .size = 0x00006000 - } - } -}; - -static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag) -{ - u32 cpu_ctrl; - - /* 10.5.0 run the firmware (I) */ - cpu_ctrl = wl1271_reg_read32(wl, ACX_REG_ECPU_CONTROL); - - /* 10.5.1 run the firmware (II) */ - cpu_ctrl |= flag; - wl1271_reg_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl); -} - -static void wl1271_boot_fw_version(struct wl1271 *wl) -{ - struct wl1271_static_data static_data; - - wl1271_spi_mem_read(wl, wl->cmd_box_addr, - &static_data, sizeof(static_data)); - - strncpy(wl->chip.fw_ver, static_data.fw_version, - sizeof(wl->chip.fw_ver)); - - /* make sure the string is NULL-terminated */ - wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0'; -} - -static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf, - size_t fw_data_len, u32 dest) -{ - int addr, chunk_num, partition_limit; - u8 *p; - - /* whal_FwCtrl_LoadFwImageSm() */ - - wl1271_debug(DEBUG_BOOT, "starting firmware upload"); - - wl1271_debug(DEBUG_BOOT, "fw_data_len %zd chunk_size %d", - fw_data_len, CHUNK_SIZE); - - - if ((fw_data_len % 4) != 0) { - wl1271_error("firmware length not multiple of four"); - return -EIO; - } - - wl1271_set_partition(wl, dest, - part_table[PART_DOWN].mem.size, - part_table[PART_DOWN].reg.start, - part_table[PART_DOWN].reg.size); - - /* 10.1 set partition limit and chunk num */ - chunk_num = 0; - partition_limit = part_table[PART_DOWN].mem.size; - - while (chunk_num < fw_data_len / CHUNK_SIZE) { - /* 10.2 update partition, if needed */ - addr = dest + (chunk_num + 2) * CHUNK_SIZE; - if (addr > partition_limit) { - addr = dest + chunk_num * CHUNK_SIZE; - partition_limit = chunk_num * CHUNK_SIZE + - part_table[PART_DOWN].mem.size; - - /* FIXME: Over 80 chars! */ - wl1271_set_partition(wl, - addr, - part_table[PART_DOWN].mem.size, - part_table[PART_DOWN].reg.start, - part_table[PART_DOWN].reg.size); - } - - /* 10.3 upload the chunk */ - addr = dest + chunk_num * CHUNK_SIZE; - p = buf + chunk_num * CHUNK_SIZE; - wl1271_debug(DEBUG_BOOT, "uploading fw chunk 0x%p to 0x%x", - p, addr); - wl1271_spi_mem_write(wl, addr, p, CHUNK_SIZE); - - chunk_num++; - } - - /* 10.4 upload the last chunk */ - addr = dest + chunk_num * CHUNK_SIZE; - p = buf + chunk_num * CHUNK_SIZE; - wl1271_debug(DEBUG_BOOT, "uploading fw last chunk (%zd B) 0x%p to 0x%x", - fw_data_len % CHUNK_SIZE, p, addr); - wl1271_spi_mem_write(wl, addr, p, fw_data_len % CHUNK_SIZE); - - return 0; -} - -static int wl1271_boot_upload_firmware(struct wl1271 *wl) -{ - u32 chunks, addr, len; - u8 *fw; - - fw = wl->fw; - chunks = be32_to_cpup((u32 *) fw); - fw += sizeof(u32); - - wl1271_debug(DEBUG_BOOT, "firmware chunks to be uploaded: %u", chunks); - - while (chunks--) { - addr = be32_to_cpup((u32 *) fw); - fw += sizeof(u32); - len = be32_to_cpup((u32 *) fw); - fw += sizeof(u32); - - if (len > 300000) { - wl1271_info("firmware chunk too long: %u", len); - return -EINVAL; - } - wl1271_debug(DEBUG_BOOT, "chunk %d addr 0x%x len %u", - chunks, addr, len); - wl1271_boot_upload_firmware_chunk(wl, fw, len, addr); - fw += len; - } - - return 0; -} - -static int wl1271_boot_upload_nvs(struct wl1271 *wl) -{ - size_t nvs_len, burst_len; - int i; - u32 dest_addr, val; - u8 *nvs_ptr, *nvs, *nvs_aligned; - - nvs = wl->nvs; - if (nvs == NULL) - return -ENODEV; - - nvs_ptr = nvs; - - nvs_len = wl->nvs_len; - - /* Update the device MAC address into the nvs */ - nvs[11] = wl->mac_addr[0]; - nvs[10] = wl->mac_addr[1]; - nvs[6] = wl->mac_addr[2]; - nvs[5] = wl->mac_addr[3]; - nvs[4] = wl->mac_addr[4]; - nvs[3] = wl->mac_addr[5]; - - /* - * Layout before the actual NVS tables: - * 1 byte : burst length. - * 2 bytes: destination address. - * n bytes: data to burst copy. - * - * This is ended by a 0 length, then the NVS tables. - */ - - /* FIXME: Do we need to check here whether the LSB is 1? */ - while (nvs_ptr[0]) { - burst_len = nvs_ptr[0]; - dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8)); - - /* FIXME: Due to our new wl1271_translate_reg_addr function, - we need to add the REGISTER_BASE to the destination */ - dest_addr += REGISTERS_BASE; - - /* We move our pointer to the data */ - nvs_ptr += 3; - - for (i = 0; i < burst_len; i++) { - val = (nvs_ptr[0] | (nvs_ptr[1] << 8) - | (nvs_ptr[2] << 16) | (nvs_ptr[3] << 24)); - - wl1271_debug(DEBUG_BOOT, - "nvs burst write 0x%x: 0x%x", - dest_addr, val); - wl1271_reg_write32(wl, dest_addr, val); - - nvs_ptr += 4; - dest_addr += 4; - } - } - - /* - * We've reached the first zero length, the first NVS table - * is 7 bytes further. - */ - nvs_ptr += 7; - nvs_len -= nvs_ptr - nvs; - nvs_len = ALIGN(nvs_len, 4); - - /* FIXME: The driver sets the partition here, but this is not needed, - since it sets to the same one as currently in use */ - /* Now we must set the partition correctly */ - wl1271_set_partition(wl, - part_table[PART_WORK].mem.start, - part_table[PART_WORK].mem.size, - part_table[PART_WORK].reg.start, - part_table[PART_WORK].reg.size); - - /* Copy the NVS tables to a new block to ensure alignment */ - nvs_aligned = kmemdup(nvs_ptr, nvs_len, GFP_KERNEL); - - /* And finally we upload the NVS tables */ - /* FIXME: In wl1271, we upload everything at once. - No endianness handling needed here?! The ref driver doesn't do - anything about it at this point */ - wl1271_spi_mem_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len); - - kfree(nvs_aligned); - return 0; -} - -static void wl1271_boot_enable_interrupts(struct wl1271 *wl) -{ - enable_irq(wl->irq); - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); - wl1271_reg_write32(wl, HI_CFG, HI_CFG_DEF_VAL); -} - -static int wl1271_boot_soft_reset(struct wl1271 *wl) -{ - unsigned long timeout; - u32 boot_data; - - /* perform soft reset */ - wl1271_reg_write32(wl, ACX_REG_SLV_SOFT_RESET, ACX_SLV_SOFT_RESET_BIT); - - /* SOFT_RESET is self clearing */ - timeout = jiffies + usecs_to_jiffies(SOFT_RESET_MAX_TIME); - while (1) { - boot_data = wl1271_reg_read32(wl, ACX_REG_SLV_SOFT_RESET); - wl1271_debug(DEBUG_BOOT, "soft reset bootdata 0x%x", boot_data); - if ((boot_data & ACX_SLV_SOFT_RESET_BIT) == 0) - break; - - if (time_after(jiffies, timeout)) { - /* 1.2 check pWhalBus->uSelfClearTime if the - * timeout was reached */ - wl1271_error("soft reset timeout"); - return -1; - } - - udelay(SOFT_RESET_STALL_TIME); - } - - /* disable Rx/Tx */ - wl1271_reg_write32(wl, ENABLE, 0x0); - - /* disable auto calibration on start*/ - wl1271_reg_write32(wl, SPARE_A2, 0xffff); - - return 0; -} - -static int wl1271_boot_run_firmware(struct wl1271 *wl) -{ - int loop, ret; - u32 chip_id, interrupt; - - wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT); - - chip_id = wl1271_reg_read32(wl, CHIP_ID_B); - - wl1271_debug(DEBUG_BOOT, "chip id after firmware boot: 0x%x", chip_id); - - if (chip_id != wl->chip.id) { - wl1271_error("chip id doesn't match after firmware boot"); - return -EIO; - } - - /* wait for init to complete */ - loop = 0; - while (loop++ < INIT_LOOP) { - udelay(INIT_LOOP_DELAY); - interrupt = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - - if (interrupt == 0xffffffff) { - wl1271_error("error reading hardware complete " - "init indication"); - return -EIO; - } - /* check that ACX_INTR_INIT_COMPLETE is enabled */ - else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) { - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1271_ACX_INTR_INIT_COMPLETE); - break; - } - } - - if (loop >= INIT_LOOP) { - wl1271_error("timeout waiting for the hardware to " - "complete initialization"); - return -EIO; - } - - /* get hardware config command mail box */ - wl->cmd_box_addr = wl1271_reg_read32(wl, REG_COMMAND_MAILBOX_PTR); - - /* get hardware config event mail box */ - wl->event_box_addr = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR); - - /* set the working partition to its "running" mode offset */ - wl1271_set_partition(wl, - part_table[PART_WORK].mem.start, - part_table[PART_WORK].mem.size, - part_table[PART_WORK].reg.start, - part_table[PART_WORK].reg.size); - - wl1271_debug(DEBUG_MAILBOX, "cmd_box_addr 0x%x event_box_addr 0x%x", - wl->cmd_box_addr, wl->event_box_addr); - - wl1271_boot_fw_version(wl); - - /* - * in case of full asynchronous mode the firmware event must be - * ready to receive event from the command mailbox - */ - - /* enable gpio interrupts */ - wl1271_boot_enable_interrupts(wl); - - /* unmask all mbox events */ - wl->event_mask = 0xffffffff; - - ret = wl1271_event_unmask(wl); - if (ret < 0) { - wl1271_error("EVENT mask setting failed"); - return ret; - } - - wl1271_event_mbox_config(wl); - - /* firmware startup completed */ - return 0; -} - -static int wl1271_boot_write_irq_polarity(struct wl1271 *wl) -{ - u32 polarity, status, i; - - wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY); - wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_READ); - - /* Wait until the command is complete (ie. bit 18 is set) */ - for (i = 0; i < OCP_CMD_LOOP; i++) { - polarity = wl1271_reg_read32(wl, OCP_DATA_READ); - if (polarity & OCP_READY_MASK) - break; - } - if (i == OCP_CMD_LOOP) { - wl1271_error("OCP command timeout!"); - return -EIO; - } - - status = polarity & OCP_STATUS_MASK; - if (status != OCP_STATUS_OK) { - wl1271_error("OCP command failed (%d)", status); - return -EIO; - } - - /* We use HIGH polarity, so unset the LOW bit */ - polarity &= ~POLARITY_LOW; - - wl1271_reg_write32(wl, OCP_POR_CTR, OCP_REG_POLARITY); - wl1271_reg_write32(wl, OCP_DATA_WRITE, polarity); - wl1271_reg_write32(wl, OCP_CMD, OCP_CMD_WRITE); - - return 0; -} - -int wl1271_boot(struct wl1271 *wl) -{ - int ret = 0; - u32 tmp, clk, pause; - - if (REF_CLOCK == 0 || REF_CLOCK == 2) - /* ref clk: 19.2/38.4 */ - clk = 0x3; - else if (REF_CLOCK == 1 || REF_CLOCK == 3) - /* ref clk: 26/52 */ - clk = 0x5; - - wl1271_reg_write32(wl, PLL_PARAMETERS, clk); - - pause = wl1271_reg_read32(wl, PLL_PARAMETERS); - - wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause); - - pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be - * WU_COUNTER_PAUSE_VAL instead of - * 0x3ff (magic number ). How does - * this work?! */ - pause |= WU_COUNTER_PAUSE_VAL; - wl1271_reg_write32(wl, WU_COUNTER_PAUSE, pause); - - /* Continue the ELP wake up sequence */ - wl1271_reg_write32(wl, WELP_ARM_COMMAND, WELP_ARM_COMMAND_VAL); - udelay(500); - - wl1271_set_partition(wl, - part_table[PART_DRPW].mem.start, - part_table[PART_DRPW].mem.size, - part_table[PART_DRPW].reg.start, - part_table[PART_DRPW].reg.size); - - /* Read-modify-write DRPW_SCRATCH_START register (see next state) - to be used by DRPw FW. The RTRIM value will be added by the FW - before taking DRPw out of reset */ - - wl1271_debug(DEBUG_BOOT, "DRPW_SCRATCH_START %08x", DRPW_SCRATCH_START); - clk = wl1271_reg_read32(wl, DRPW_SCRATCH_START); - - wl1271_debug(DEBUG_BOOT, "clk2 0x%x", clk); - - /* 2 */ - clk |= (REF_CLOCK << 1) << 4; - wl1271_reg_write32(wl, DRPW_SCRATCH_START, clk); - - wl1271_set_partition(wl, - part_table[PART_WORK].mem.start, - part_table[PART_WORK].mem.size, - part_table[PART_WORK].reg.start, - part_table[PART_WORK].reg.size); - - /* Disable interrupts */ - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); - - ret = wl1271_boot_soft_reset(wl); - if (ret < 0) - goto out; - - /* 2. start processing NVS file */ - ret = wl1271_boot_upload_nvs(wl); - if (ret < 0) - goto out; - - /* write firmware's last address (ie. it's length) to - * ACX_EEPROMLESS_IND_REG */ - wl1271_debug(DEBUG_BOOT, "ACX_EEPROMLESS_IND_REG"); - - wl1271_reg_write32(wl, ACX_EEPROMLESS_IND_REG, ACX_EEPROMLESS_IND_REG); - - tmp = wl1271_reg_read32(wl, CHIP_ID_B); - - wl1271_debug(DEBUG_BOOT, "chip id 0x%x", tmp); - - /* 6. read the EEPROM parameters */ - tmp = wl1271_reg_read32(wl, SCR_PAD2); - - ret = wl1271_boot_write_irq_polarity(wl); - if (ret < 0) - goto out; - - /* FIXME: Need to check whether this is really what we want */ - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_ALL_EVENTS_VECTOR); - - /* WL1271: The reference driver skips steps 7 to 10 (jumps directly - * to upload_fw) */ - - ret = wl1271_boot_upload_firmware(wl); - if (ret < 0) - goto out; - - /* 10.5 start firmware */ - ret = wl1271_boot_run_firmware(wl); - if (ret < 0) - goto out; - - /* set the wl1271 default filters */ - wl->rx_config = WL1271_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1271_DEFAULT_RX_FILTER; - - wl1271_event_mbox_config(wl); - -out: - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.h b/drivers/net/wireless/wl12xx/wl1271_boot.h deleted file mode 100644 index b0d8fb46a439..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_boot.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __BOOT_H__ -#define __BOOT_H__ - -#include "wl1271.h" - -int wl1271_boot(struct wl1271 *wl); - -#define WL1271_NO_SUBBANDS 8 -#define WL1271_NO_POWER_LEVELS 4 -#define WL1271_FW_VERSION_MAX_LEN 20 - -struct wl1271_static_data { - u8 mac_address[ETH_ALEN]; - u8 padding[2]; - u8 fw_version[WL1271_FW_VERSION_MAX_LEN]; - u32 hw_version; - u8 tx_power_table[WL1271_NO_SUBBANDS][WL1271_NO_POWER_LEVELS]; -}; - -/* number of times we try to read the INIT interrupt */ -#define INIT_LOOP 20000 - -/* delay between retries */ -#define INIT_LOOP_DELAY 50 - -#define REF_CLOCK 2 -#define WU_COUNTER_PAUSE_VAL 0x3FF -#define WELP_ARM_COMMAND_VAL 0x4 - -#define OCP_CMD_LOOP 32 - -#define OCP_CMD_WRITE 0x1 -#define OCP_CMD_READ 0x2 - -#define OCP_READY_MASK BIT(18) -#define OCP_STATUS_MASK (BIT(16) | BIT(17)) - -#define OCP_STATUS_NO_RESP 0x00000 -#define OCP_STATUS_OK 0x10000 -#define OCP_STATUS_REQ_FAILED 0x20000 -#define OCP_STATUS_RESP_ERROR 0x30000 - -#define OCP_REG_POLARITY 0x30032 - -#define CMD_MBOX_ADDRESS 0x407B4 - -#define POLARITY_LOW BIT(1) - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c deleted file mode 100644 index 2a4351ff54dc..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.c +++ /dev/null @@ -1,813 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include - -#include "wl1271.h" -#include "wl1271_reg.h" -#include "wl1271_spi.h" -#include "wl1271_acx.h" -#include "wl12xx_80211.h" -#include "wl1271_cmd.h" - -/* - * send command to firmware - * - * @wl: wl struct - * @id: command id - * @buf: buffer containing the command, must work with dma - * @len: length of the buffer - */ -int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len) -{ - struct wl1271_cmd_header *cmd; - unsigned long timeout; - u32 intr; - int ret = 0; - - cmd = buf; - cmd->id = id; - cmd->status = 0; - - WARN_ON(len % 4 != 0); - - wl1271_spi_mem_write(wl, wl->cmd_box_addr, buf, len); - - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_CMD); - - timeout = jiffies + msecs_to_jiffies(WL1271_COMMAND_TIMEOUT); - - intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - while (!(intr & WL1271_ACX_INTR_CMD_COMPLETE)) { - if (time_after(jiffies, timeout)) { - wl1271_error("command complete timeout"); - ret = -ETIMEDOUT; - goto out; - } - - msleep(1); - - intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR); - } - - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_ACK, - WL1271_ACX_INTR_CMD_COMPLETE); - -out: - return ret; -} - -int wl1271_cmd_cal_channel_tune(struct wl1271 *wl) -{ - struct wl1271_cmd_cal_channel_tune *cmd; - int ret = 0; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd->test.id = TEST_CMD_CHANNEL_TUNE; - - cmd->band = WL1271_CHANNEL_TUNE_BAND_2_4; - /* set up any channel, 7 is in the middle of the range */ - cmd->channel = 7; - - ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); - if (ret < 0) - wl1271_warning("TEST_CMD_CHANNEL_TUNE failed"); - - kfree(cmd); - return ret; -} - -int wl1271_cmd_cal_update_ref_point(struct wl1271 *wl) -{ - struct wl1271_cmd_cal_update_ref_point *cmd; - int ret = 0; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd->test.id = TEST_CMD_UPDATE_PD_REFERENCE_POINT; - - /* FIXME: still waiting for the correct values */ - cmd->ref_power = 0; - cmd->ref_detector = 0; - - cmd->sub_band = WL1271_PD_REFERENCE_POINT_BAND_B_G; - - ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); - if (ret < 0) - wl1271_warning("TEST_CMD_UPDATE_PD_REFERENCE_POINT failed"); - - kfree(cmd); - return ret; -} - -int wl1271_cmd_cal_p2g(struct wl1271 *wl) -{ - struct wl1271_cmd_cal_p2g *cmd; - int ret = 0; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - cmd->test.id = TEST_CMD_P2G_CAL; - - cmd->sub_band_mask = WL1271_CAL_P2G_BAND_B_G; - - ret = wl1271_cmd_test(wl, cmd, sizeof(*cmd), 0); - if (ret < 0) - wl1271_warning("TEST_CMD_P2G_CAL failed"); - - kfree(cmd); - return ret; -} - -int wl1271_cmd_cal(struct wl1271 *wl) -{ - /* - * FIXME: we must make sure that we're not sleeping when calibration - * is done - */ - int ret; - - wl1271_notice("performing tx calibration"); - - ret = wl1271_cmd_cal_channel_tune(wl); - if (ret < 0) - return ret; - - ret = wl1271_cmd_cal_update_ref_point(wl); - if (ret < 0) - return ret; - - ret = wl1271_cmd_cal_p2g(wl); - if (ret < 0) - return ret; - - return ret; -} - -int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, - u16 beacon_interval, u8 wait) -{ - static bool do_cal = true; - unsigned long timeout; - struct wl1271_cmd_join *join; - int ret, i; - u8 *bssid; - - /* FIXME: remove when we get calibration from the factory */ - if (do_cal) { - ret = wl1271_cmd_cal(wl); - if (ret < 0) - wl1271_warning("couldn't calibrate"); - else - do_cal = false; - } - - - join = kzalloc(sizeof(*join), GFP_KERNEL); - if (!join) { - ret = -ENOMEM; - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd join"); - - /* Reverse order BSSID */ - bssid = (u8 *) &join->bssid_lsb; - for (i = 0; i < ETH_ALEN; i++) - bssid[i] = wl->bssid[ETH_ALEN - i - 1]; - - join->rx_config_options = wl->rx_config; - join->rx_filter_options = wl->rx_filter; - - join->basic_rate_set = RATE_MASK_1MBPS | RATE_MASK_2MBPS | - RATE_MASK_5_5MBPS | RATE_MASK_11MBPS; - - join->beacon_interval = beacon_interval; - join->dtim_interval = dtim_interval; - join->bss_type = bss_type; - join->channel = wl->channel; - join->ssid_len = wl->ssid_len; - memcpy(join->ssid, wl->ssid, wl->ssid_len); - join->ctrl = WL1271_JOIN_CMD_CTRL_TX_FLUSH; - - /* increment the session counter */ - wl->session_counter++; - if (wl->session_counter >= SESSION_COUNTER_MAX) - wl->session_counter = 0; - - join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET; - - - ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join)); - if (ret < 0) { - wl1271_error("failed to initiate cmd join"); - goto out_free; - } - - timeout = msecs_to_jiffies(JOIN_TIMEOUT); - - /* - * ugly hack: we should wait for JOIN_EVENT_COMPLETE_ID but to - * simplify locking we just sleep instead, for now - */ - if (wait) - msleep(10); - -out_free: - kfree(join); - -out: - return ret; -} - -/** - * send test command to firmware - * - * @wl: wl struct - * @buf: buffer containing the command, with all headers, must work with dma - * @len: length of the buffer - * @answer: is answer needed - */ -int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer) -{ - int ret; - - wl1271_debug(DEBUG_CMD, "cmd test"); - - ret = wl1271_cmd_send(wl, CMD_TEST, buf, buf_len); - - if (ret < 0) { - wl1271_warning("TEST command failed"); - return ret; - } - - if (answer) { - struct wl1271_command *cmd_answer; - - /* - * The test command got in, we can read the answer. - * The answer would be a wl1271_command, where the - * parameter array contains the actual answer. - */ - wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, buf_len); - - cmd_answer = buf; - - if (cmd_answer->header.status != CMD_STATUS_SUCCESS) - wl1271_error("TEST command answer error: %d", - cmd_answer->header.status); - } - - return 0; -} - -/** - * read acx from firmware - * - * @wl: wl struct - * @id: acx id - * @buf: buffer for the response, including all headers, must work with dma - * @len: lenght of buf - */ -int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len) -{ - struct acx_header *acx = buf; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd interrogate"); - - acx->id = id; - - /* payload length, does not include any headers */ - acx->len = len - sizeof(*acx); - - ret = wl1271_cmd_send(wl, CMD_INTERROGATE, acx, sizeof(*acx)); - if (ret < 0) { - wl1271_error("INTERROGATE command failed"); - goto out; - } - - /* the interrogate command got in, we can read the answer */ - wl1271_spi_mem_read(wl, wl->cmd_box_addr, buf, len); - - acx = buf; - if (acx->cmd.status != CMD_STATUS_SUCCESS) - wl1271_error("INTERROGATE command error: %d", - acx->cmd.status); - -out: - return ret; -} - -/** - * write acx value to firmware - * - * @wl: wl struct - * @id: acx id - * @buf: buffer containing acx, including all headers, must work with dma - * @len: length of buf - */ -int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len) -{ - struct acx_header *acx = buf; - int ret; - - wl1271_debug(DEBUG_CMD, "cmd configure"); - - acx->id = id; - - /* payload length, does not include any headers */ - acx->len = len - sizeof(*acx); - - ret = wl1271_cmd_send(wl, CMD_CONFIGURE, acx, len); - if (ret < 0) { - wl1271_warning("CONFIGURE command NOK"); - return ret; - } - - return 0; -} - -int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable) -{ - struct cmd_enabledisable_path *cmd; - int ret; - u16 cmd_rx, cmd_tx; - - wl1271_debug(DEBUG_CMD, "cmd data path"); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->channel = channel; - - if (enable) { - cmd_rx = CMD_ENABLE_RX; - cmd_tx = CMD_ENABLE_TX; - } else { - cmd_rx = CMD_DISABLE_RX; - cmd_tx = CMD_DISABLE_TX; - } - - ret = wl1271_cmd_send(wl, cmd_rx, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1271_error("rx %s cmd for channel %d failed", - enable ? "start" : "stop", channel); - goto out; - } - - wl1271_debug(DEBUG_BOOT, "rx %s cmd channel %d", - enable ? "start" : "stop", channel); - - ret = wl1271_cmd_send(wl, cmd_tx, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1271_error("tx %s cmd for channel %d failed", - enable ? "start" : "stop", channel); - return ret; - } - - wl1271_debug(DEBUG_BOOT, "tx %s cmd channel %d", - enable ? "start" : "stop", channel); - -out: - kfree(cmd); - return ret; -} - -int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode) -{ - struct wl1271_cmd_ps_params *ps_params = NULL; - int ret = 0; - - /* FIXME: this should be in ps.c */ - ret = wl1271_acx_wake_up_conditions(wl, WAKE_UP_EVENT_DTIM_BITMAP, - wl->listen_int); - if (ret < 0) { - wl1271_error("couldn't set wake up conditions"); - goto out; - } - - wl1271_debug(DEBUG_CMD, "cmd set ps mode"); - - ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL); - if (!ps_params) { - ret = -ENOMEM; - goto out; - } - - ps_params->ps_mode = ps_mode; - ps_params->send_null_data = 1; - ps_params->retries = 5; - ps_params->hang_over_period = 128; - ps_params->null_data_rate = 1; /* 1 Mbps */ - - ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params, - sizeof(*ps_params)); - if (ret < 0) { - wl1271_error("cmd set_ps_mode failed"); - goto out; - } - -out: - kfree(ps_params); - return ret; -} - -int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, - size_t len) -{ - struct cmd_read_write_memory *cmd; - int ret = 0; - - wl1271_debug(DEBUG_CMD, "cmd read memory"); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - WARN_ON(len > MAX_READ_SIZE); - len = min_t(size_t, len, MAX_READ_SIZE); - - cmd->addr = addr; - cmd->size = len; - - ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1271_error("read memory command failed: %d", ret); - goto out; - } - - /* the read command got in, we can now read the answer */ - wl1271_spi_mem_read(wl, wl->cmd_box_addr, cmd, sizeof(*cmd)); - - if (cmd->header.status != CMD_STATUS_SUCCESS) - wl1271_error("error in read command result: %d", - cmd->header.status); - - memcpy(answer, cmd->value, len); - -out: - kfree(cmd); - return ret; -} - -int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, - u8 active_scan, u8 high_prio, u8 num_channels, - u8 probe_requests) -{ - - struct wl1271_cmd_trigger_scan_to *trigger = NULL; - struct wl1271_cmd_scan *params = NULL; - int i, ret; - u16 scan_options = 0; - - if (wl->scanning) - return -EINVAL; - - params = kzalloc(sizeof(*params), GFP_KERNEL); - if (!params) - return -ENOMEM; - - params->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD); - params->params.rx_filter_options = - cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN); - - if (!active_scan) - scan_options |= WL1271_SCAN_OPT_PASSIVE; - if (high_prio) - scan_options |= WL1271_SCAN_OPT_PRIORITY_HIGH; - params->params.scan_options = scan_options; - - params->params.num_channels = num_channels; - params->params.num_probe_requests = probe_requests; - params->params.tx_rate = cpu_to_le32(RATE_MASK_2MBPS); - params->params.tid_trigger = 0; - params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; - - for (i = 0; i < num_channels; i++) { - params->channels[i].min_duration = - cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION); - params->channels[i].max_duration = - cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION); - memset(¶ms->channels[i].bssid_lsb, 0xff, 4); - memset(¶ms->channels[i].bssid_msb, 0xff, 2); - params->channels[i].early_termination = 0; - params->channels[i].tx_power_att = WL1271_SCAN_CURRENT_TX_PWR; - params->channels[i].channel = i + 1; - } - - if (len && ssid) { - params->params.ssid_len = len; - memcpy(params->params.ssid, ssid, len); - } - - ret = wl1271_cmd_build_probe_req(wl, ssid, len); - if (ret < 0) { - wl1271_error("PROBE request template failed"); - goto out; - } - - trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); - if (!trigger) { - ret = -ENOMEM; - goto out; - } - - /* disable the timeout */ - trigger->timeout = 0; - - ret = wl1271_cmd_send(wl, CMD_TRIGGER_SCAN_TO, trigger, - sizeof(*trigger)); - if (ret < 0) { - wl1271_error("trigger scan to failed for hw scan"); - goto out; - } - - wl1271_dump(DEBUG_SCAN, "SCAN: ", params, sizeof(*params)); - - wl->scanning = true; - - ret = wl1271_cmd_send(wl, CMD_SCAN, params, sizeof(*params)); - if (ret < 0) { - wl1271_error("SCAN failed"); - goto out; - } - - wl1271_spi_mem_read(wl, wl->cmd_box_addr, params, sizeof(*params)); - - if (params->header.status != CMD_STATUS_SUCCESS) { - wl1271_error("Scan command error: %d", - params->header.status); - wl->scanning = false; - ret = -EIO; - goto out; - } - -out: - kfree(params); - return ret; -} - -int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, - void *buf, size_t buf_len) -{ - struct wl1271_cmd_template_set *cmd; - int ret = 0; - - wl1271_debug(DEBUG_CMD, "cmd template_set %d", template_id); - - WARN_ON(buf_len > WL1271_CMD_TEMPL_MAX_SIZE); - buf_len = min_t(size_t, buf_len, WL1271_CMD_TEMPL_MAX_SIZE); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->len = cpu_to_le16(buf_len); - cmd->template_type = template_id; - cmd->enabled_rates = ACX_RATE_MASK_UNSPECIFIED; - cmd->short_retry_limit = ACX_RATE_RETRY_LIMIT; - cmd->long_retry_limit = ACX_RATE_RETRY_LIMIT; - - if (buf) - memcpy(cmd->template_data, buf, buf_len); - - ret = wl1271_cmd_send(wl, CMD_SET_TEMPLATE, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1271_warning("cmd set_template failed: %d", ret); - goto out_free; - } - -out_free: - kfree(cmd); - -out: - return ret; -} - -static int wl1271_build_basic_rates(char *rates) -{ - u8 index = 0; - - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB; - rates[index++] = IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB; - - return index; -} - -static int wl1271_build_extended_rates(char *rates) -{ - u8 index = 0; - - rates[index++] = IEEE80211_OFDM_RATE_6MB; - rates[index++] = IEEE80211_OFDM_RATE_9MB; - rates[index++] = IEEE80211_OFDM_RATE_12MB; - rates[index++] = IEEE80211_OFDM_RATE_18MB; - rates[index++] = IEEE80211_OFDM_RATE_24MB; - rates[index++] = IEEE80211_OFDM_RATE_36MB; - rates[index++] = IEEE80211_OFDM_RATE_48MB; - rates[index++] = IEEE80211_OFDM_RATE_54MB; - - return index; -} - -int wl1271_cmd_build_null_data(struct wl1271 *wl) -{ - struct wl12xx_null_data_template template; - - if (!is_zero_ether_addr(wl->bssid)) { - memcpy(template.header.da, wl->bssid, ETH_ALEN); - memcpy(template.header.bssid, wl->bssid, ETH_ALEN); - } else { - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - } - - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA | - IEEE80211_STYPE_NULLFUNC); - - return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template, - sizeof(template)); - -} - -int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid) -{ - struct wl12xx_ps_poll_template template; - - memcpy(template.bssid, wl->bssid, ETH_ALEN); - memcpy(template.ta, wl->mac_addr, ETH_ALEN); - template.aid = aid; - template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL); - - return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template, - sizeof(template)); - -} - -int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len) -{ - struct wl12xx_probe_req_template template; - struct wl12xx_ie_rates *rates; - char *ptr; - u16 size; - - ptr = (char *)&template; - size = sizeof(struct ieee80211_header); - - memset(template.header.da, 0xff, ETH_ALEN); - memset(template.header.bssid, 0xff, ETH_ALEN); - memcpy(template.header.sa, wl->mac_addr, ETH_ALEN); - template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ); - - /* IEs */ - /* SSID */ - template.ssid.header.id = WLAN_EID_SSID; - template.ssid.header.len = ssid_len; - if (ssid_len && ssid) - memcpy(template.ssid.ssid, ssid, ssid_len); - size += sizeof(struct wl12xx_ie_header) + ssid_len; - ptr += size; - - /* Basic Rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_SUPP_RATES; - rates->header.len = wl1271_build_basic_rates(rates->rates); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - ptr += sizeof(struct wl12xx_ie_header) + rates->header.len; - - /* Extended rates */ - rates = (struct wl12xx_ie_rates *)ptr; - rates->header.id = WLAN_EID_EXT_SUPP_RATES; - rates->header.len = wl1271_build_extended_rates(rates->rates); - size += sizeof(struct wl12xx_ie_header) + rates->header.len; - - wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size); - - return wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, - &template, size); -} - -int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id) -{ - struct wl1271_cmd_set_keys *cmd; - int ret = 0; - - wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id); - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - cmd->id = id; - cmd->key_action = KEY_SET_ID; - cmd->key_type = KEY_WEP; - - ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1271_warning("cmd set_default_wep_key failed: %d", ret); - goto out; - } - -out: - kfree(cmd); - - return ret; -} - -int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, - u8 key_size, const u8 *key, const u8 *addr) -{ - struct wl1271_cmd_set_keys *cmd; - int ret = 0; - - cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); - if (!cmd) { - ret = -ENOMEM; - goto out; - } - - if (key_type != KEY_WEP) - memcpy(cmd->addr, addr, ETH_ALEN); - - cmd->key_action = action; - cmd->key_size = key_size; - cmd->key_type = key_type; - - /* we have only one SSID profile */ - cmd->ssid_profile = 0; - - cmd->id = id; - - /* FIXME: this is from wl1251, needs to be checked */ - if (key_type == KEY_TKIP) { - /* - * We get the key in the following form: - * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes) - * but the target is expecting: - * TKIP - RX MIC - TX MIC - */ - memcpy(cmd->key, key, 16); - memcpy(cmd->key + 16, key + 24, 8); - memcpy(cmd->key + 24, key + 16, 8); - - } else { - memcpy(cmd->key, key, key_size); - } - - wl1271_dump(DEBUG_CRYPT, "TARGET KEY: ", cmd, sizeof(*cmd)); - - ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd)); - if (ret < 0) { - wl1271_warning("could not set keys"); - goto out; - } - -out: - kfree(cmd); - - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h deleted file mode 100644 index 951a8447a516..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_cmd.h +++ /dev/null @@ -1,464 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_CMD_H__ -#define __WL1271_CMD_H__ - -#include "wl1271.h" - -struct acx_header; - -int wl1271_cmd_send(struct wl1271 *wl, u16 type, void *buf, size_t buf_len); -int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type, u8 dtim_interval, - u16 beacon_interval, u8 wait); -int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); -int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); -int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len); -int wl1271_cmd_data_path(struct wl1271 *wl, u8 channel, bool enable); -int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode); -int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer, - size_t len); -int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len, - u8 active_scan, u8 high_prio, u8 num_channels, - u8 probe_requests); -int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id, - void *buf, size_t buf_len); -int wl1271_cmd_build_null_data(struct wl1271 *wl); -int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid); -int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len); -int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id); -int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type, - u8 key_size, const u8 *key, const u8 *addr); - -enum wl1271_commands { - CMD_INTERROGATE = 1, /*use this to read information elements*/ - CMD_CONFIGURE = 2, /*use this to write information elements*/ - CMD_ENABLE_RX = 3, - CMD_ENABLE_TX = 4, - CMD_DISABLE_RX = 5, - CMD_DISABLE_TX = 6, - CMD_SCAN = 8, - CMD_STOP_SCAN = 9, - CMD_START_JOIN = 11, - CMD_SET_KEYS = 12, - CMD_READ_MEMORY = 13, - CMD_WRITE_MEMORY = 14, - CMD_SET_TEMPLATE = 19, - CMD_TEST = 23, - CMD_NOISE_HIST = 28, - CMD_LNA_CONTROL = 32, - CMD_SET_BCN_MODE = 33, - CMD_MEASUREMENT = 34, - CMD_STOP_MEASUREMENT = 35, - CMD_DISCONNECT = 36, - CMD_SET_PS_MODE = 37, - CMD_CHANNEL_SWITCH = 38, - CMD_STOP_CHANNEL_SWICTH = 39, - CMD_AP_DISCOVERY = 40, - CMD_STOP_AP_DISCOVERY = 41, - CMD_SPS_SCAN = 42, - CMD_STOP_SPS_SCAN = 43, - CMD_HEALTH_CHECK = 45, - CMD_DEBUG = 46, - CMD_TRIGGER_SCAN_TO = 47, - CMD_CONNECTION_SCAN_CFG = 48, - CMD_CONNECTION_SCAN_SSID_CFG = 49, - CMD_START_PERIODIC_SCAN = 50, - CMD_STOP_PERIODIC_SCAN = 51, - CMD_SET_STA_STATE = 52, - - NUM_COMMANDS, - MAX_COMMAND_ID = 0xFFFF, -}; - -#define MAX_CMD_PARAMS 572 - -enum cmd_templ { - CMD_TEMPL_NULL_DATA = 0, - CMD_TEMPL_BEACON, - CMD_TEMPL_CFG_PROBE_REQ_2_4, - CMD_TEMPL_CFG_PROBE_REQ_5, - CMD_TEMPL_PROBE_RESPONSE, - CMD_TEMPL_QOS_NULL_DATA, - CMD_TEMPL_PS_POLL, - CMD_TEMPL_KLV, - CMD_TEMPL_DISCONNECT, - CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */ - CMD_TEMPL_PROBE_REQ_5, /* for firmware internal use only */ - CMD_TEMPL_BAR, /* for firmware internal use only */ - CMD_TEMPL_CTS, /* - * For CTS-to-self (FastCTS) mechanism - * for BT/WLAN coexistence (SoftGemini). */ - CMD_TEMPL_MAX = 0xff -}; - -/* unit ms */ -#define WL1271_COMMAND_TIMEOUT 2000 -#define WL1271_CMD_TEMPL_MAX_SIZE 252 - -struct wl1271_cmd_header { - u16 id; - u16 status; - /* payload */ - u8 data[0]; -} __attribute__ ((packed)); - -#define WL1271_CMD_MAX_PARAMS 572 - -struct wl1271_command { - struct wl1271_cmd_header header; - u8 parameters[WL1271_CMD_MAX_PARAMS]; -} __attribute__ ((packed)); - -enum { - CMD_MAILBOX_IDLE = 0, - CMD_STATUS_SUCCESS = 1, - CMD_STATUS_UNKNOWN_CMD = 2, - CMD_STATUS_UNKNOWN_IE = 3, - CMD_STATUS_REJECT_MEAS_SG_ACTIVE = 11, - CMD_STATUS_RX_BUSY = 13, - CMD_STATUS_INVALID_PARAM = 14, - CMD_STATUS_TEMPLATE_TOO_LARGE = 15, - CMD_STATUS_OUT_OF_MEMORY = 16, - CMD_STATUS_STA_TABLE_FULL = 17, - CMD_STATUS_RADIO_ERROR = 18, - CMD_STATUS_WRONG_NESTING = 19, - CMD_STATUS_TIMEOUT = 21, /* Driver internal use.*/ - CMD_STATUS_FW_RESET = 22, /* Driver internal use.*/ - MAX_COMMAND_STATUS = 0xff -}; - - -/* - * CMD_READ_MEMORY - * - * The host issues this command to read the WiLink device memory/registers. - * - * Note: The Base Band address has special handling (16 bits registers and - * addresses). For more information, see the hardware specification. - */ -/* - * CMD_WRITE_MEMORY - * - * The host issues this command to write the WiLink device memory/registers. - * - * The Base Band address has special handling (16 bits registers and - * addresses). For more information, see the hardware specification. - */ -#define MAX_READ_SIZE 256 - -struct cmd_read_write_memory { - struct wl1271_cmd_header header; - - /* The address of the memory to read from or write to.*/ - u32 addr; - - /* The amount of data in bytes to read from or write to the WiLink - * device.*/ - u32 size; - - /* The actual value read from or written to the Wilink. The source - of this field is the Host in WRITE command or the Wilink in READ - command. */ - u8 value[MAX_READ_SIZE]; -}; - -#define CMDMBOX_HEADER_LEN 4 -#define CMDMBOX_INFO_ELEM_HEADER_LEN 4 - -enum { - BSS_TYPE_IBSS = 0, - BSS_TYPE_STA_BSS = 2, - BSS_TYPE_AP_BSS = 3, - MAX_BSS_TYPE = 0xFF -}; - -#define WL1271_JOIN_CMD_CTRL_TX_FLUSH 0x80 /* Firmware flushes all Tx */ -#define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1 - -struct wl1271_cmd_join { - struct wl1271_cmd_header header; - - u32 bssid_lsb; - u16 bssid_msb; - u16 beacon_interval; /* in TBTTs */ - u32 rx_config_options; - u32 rx_filter_options; - - /* - * The target uses this field to determine the rate at - * which to transmit control frame responses (such as - * ACK or CTS frames). - */ - u32 basic_rate_set; - u8 dtim_interval; - /* - * bits 0-2: This bitwise field specifies the type - * of BSS to start or join (BSS_TYPE_*). - * bit 4: Band - The radio band in which to join - * or start. - * 0 - 2.4GHz band - * 1 - 5GHz band - * bits 3, 5-7: Reserved - */ - u8 bss_type; - u8 channel; - u8 ssid_len; - u8 ssid[IW_ESSID_MAX_SIZE]; - u8 ctrl; /* JOIN_CMD_CTRL_* */ - u8 reserved[3]; -} __attribute__ ((packed)); - -struct cmd_enabledisable_path { - struct wl1271_cmd_header header; - - u8 channel; - u8 padding[3]; -} __attribute__ ((packed)); - -struct wl1271_cmd_template_set { - struct wl1271_cmd_header header; - - u16 len; - u8 template_type; - u8 index; /* relevant only for KLV_TEMPLATE type */ - u32 enabled_rates; - u8 short_retry_limit; - u8 long_retry_limit; - u8 aflags; - u8 reserved; - u8 template_data[WL1271_CMD_TEMPL_MAX_SIZE]; -} __attribute__ ((packed)); - -#define TIM_ELE_ID 5 -#define PARTIAL_VBM_MAX 251 - -struct wl1271_tim { - u8 identity; - u8 length; - u8 dtim_count; - u8 dtim_period; - u8 bitmap_ctrl; - u8 pvb_field[PARTIAL_VBM_MAX]; /* Partial Virtual Bitmap */ -} __attribute__ ((packed)); - -enum wl1271_cmd_ps_mode { - STATION_ACTIVE_MODE, - STATION_POWER_SAVE_MODE -}; - -struct wl1271_cmd_ps_params { - struct wl1271_cmd_header header; - - u8 ps_mode; /* STATION_* */ - u8 send_null_data; /* Do we have to send NULL data packet ? */ - u8 retries; /* Number of retires for the initial NULL data packet */ - - /* - * TUs during which the target stays awake after switching - * to power save mode. - */ - u8 hang_over_period; - u32 null_data_rate; -} __attribute__ ((packed)); - -/* HW encryption keys */ -#define NUM_ACCESS_CATEGORIES_COPY 4 -#define MAX_KEY_SIZE 32 - -/* When set, disable HW encryption */ -#define DF_ENCRYPTION_DISABLE 0x01 -/* When set, disable HW decryption */ -#define DF_SNIFF_MODE_ENABLE 0x80 - -enum wl1271_cmd_key_action { - KEY_ADD_OR_REPLACE = 1, - KEY_REMOVE = 2, - KEY_SET_ID = 3, - MAX_KEY_ACTION = 0xffff, -}; - -enum wl1271_cmd_key_type { - KEY_NONE = 0, - KEY_WEP = 1, - KEY_TKIP = 2, - KEY_AES = 3, - KEY_GEM = 4 -}; - -/* FIXME: Add description for key-types */ - -struct wl1271_cmd_set_keys { - struct wl1271_cmd_header header; - - /* Ignored for default WEP key */ - u8 addr[ETH_ALEN]; - - /* key_action_e */ - u16 key_action; - - u16 reserved_1; - - /* key size in bytes */ - u8 key_size; - - /* key_type_e */ - u8 key_type; - u8 ssid_profile; - - /* - * TKIP, AES: frame's key id field. - * For WEP default key: key id; - */ - u8 id; - u8 reserved_2[6]; - u8 key[MAX_KEY_SIZE]; - u16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY]; - u32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY]; -} __attribute__ ((packed)); - - -#define WL1271_SCAN_MAX_CHANNELS 24 -#define WL1271_SCAN_DEFAULT_TAG 1 -#define WL1271_SCAN_CURRENT_TX_PWR 0 -#define WL1271_SCAN_OPT_ACTIVE 0 -#define WL1271_SCAN_OPT_PASSIVE 1 -#define WL1271_SCAN_OPT_PRIORITY_HIGH 4 -#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */ -#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */ - -struct basic_scan_params { - u32 rx_config_options; - u32 rx_filter_options; - /* Scan option flags (WL1271_SCAN_OPT_*) */ - u16 scan_options; - /* Number of scan channels in the list (maximum 30) */ - u8 num_channels; - /* This field indicates the number of probe requests to send - per channel for an active scan */ - u8 num_probe_requests; - /* Rate bit field for sending the probes */ - u32 tx_rate; - u8 tid_trigger; - u8 ssid_len; - /* in order to align */ - u8 padding1[2]; - u8 ssid[IW_ESSID_MAX_SIZE]; - /* Band to scan */ - u8 band; - u8 use_ssid_list; - u8 scan_tag; - u8 padding2; -} __attribute__ ((packed)); - -struct basic_scan_channel_params { - /* Duration in TU to wait for frames on a channel for active scan */ - u32 min_duration; - u32 max_duration; - u32 bssid_lsb; - u16 bssid_msb; - u8 early_termination; - u8 tx_power_att; - u8 channel; - /* FW internal use only! */ - u8 dfs_candidate; - u8 activity_detected; - u8 pad; -} __attribute__ ((packed)); - -struct wl1271_cmd_scan { - struct wl1271_cmd_header header; - - struct basic_scan_params params; - struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS]; -} __attribute__ ((packed)); - -struct wl1271_cmd_trigger_scan_to { - struct wl1271_cmd_header header; - - u32 timeout; -}; - -struct wl1271_cmd_test_header { - u8 id; - u8 padding[3]; -}; - -enum wl1271_channel_tune_bands { - WL1271_CHANNEL_TUNE_BAND_2_4, - WL1271_CHANNEL_TUNE_BAND_5, - WL1271_CHANNEL_TUNE_BAND_4_9 -}; - -#define WL1271_PD_REFERENCE_POINT_BAND_B_G 0 - -#define TEST_CMD_P2G_CAL 0x02 -#define TEST_CMD_CHANNEL_TUNE 0x0d -#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d - -struct wl1271_cmd_cal_channel_tune { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - u8 band; - u8 channel; - - u16 radio_status; -} __attribute__ ((packed)); - -struct wl1271_cmd_cal_update_ref_point { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - s32 ref_power; - s32 ref_detector; - u8 sub_band; - u8 padding[3]; -} __attribute__ ((packed)); - -#define MAX_TLV_LENGTH 400 -#define MAX_NVS_VERSION_LENGTH 12 - -#define WL1271_CAL_P2G_BAND_B_G BIT(0) - -struct wl1271_cmd_cal_p2g { - struct wl1271_cmd_header header; - - struct wl1271_cmd_test_header test; - - u16 len; - u8 buf[MAX_TLV_LENGTH]; - u8 type; - u8 padding; - - s16 radio_status; - u8 nvs_version[MAX_NVS_VERSION_LENGTH]; - - u8 sub_band_mask; - u8 padding2; -} __attribute__ ((packed)); - -#endif /* __WL1271_CMD_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c deleted file mode 100644 index c1805e5f8964..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c +++ /dev/null @@ -1,518 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1271_debugfs.h" - -#include - -#include "wl1271.h" -#include "wl1271_acx.h" -#include "wl1271_ps.h" - -/* ms */ -#define WL1271_DEBUGFS_STATS_LIFETIME 1000 - -/* debugfs macros idea from mac80211 */ - -#define DEBUGFS_READONLY_FILE(name, buflen, fmt, value...) \ -static ssize_t name## _read(struct file *file, char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - res = scnprintf(buf, buflen, fmt "\n", ##value); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} \ - \ -static const struct file_operations name## _ops = { \ - .read = name## _read, \ - .open = wl1271_open_file_generic, \ -}; - -#define DEBUGFS_ADD(name, parent) \ - wl->debugfs.name = debugfs_create_file(#name, 0400, parent, \ - wl, &name## _ops); \ - if (IS_ERR(wl->debugfs.name)) { \ - ret = PTR_ERR(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - goto out; \ - } - -#define DEBUGFS_DEL(name) \ - do { \ - debugfs_remove(wl->debugfs.name); \ - wl->debugfs.name = NULL; \ - } while (0) - -#define DEBUGFS_FWSTATS_FILE(sub, name, buflen, fmt) \ -static ssize_t sub## _ ##name## _read(struct file *file, \ - char __user *userbuf, \ - size_t count, loff_t *ppos) \ -{ \ - struct wl1271 *wl = file->private_data; \ - char buf[buflen]; \ - int res; \ - \ - wl1271_debugfs_update_stats(wl); \ - \ - res = scnprintf(buf, buflen, fmt "\n", \ - wl->stats.fw_stats->sub.name); \ - return simple_read_from_buffer(userbuf, count, ppos, buf, res); \ -} \ - \ -static const struct file_operations sub## _ ##name## _ops = { \ - .read = sub## _ ##name## _read, \ - .open = wl1271_open_file_generic, \ -}; - -#define DEBUGFS_FWSTATS_ADD(sub, name) \ - DEBUGFS_ADD(sub## _ ##name, wl->debugfs.fw_statistics) - -#define DEBUGFS_FWSTATS_DEL(sub, name) \ - DEBUGFS_DEL(sub## _ ##name) - -static void wl1271_debugfs_update_stats(struct wl1271 *wl) -{ - int ret; - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - if (wl->state == WL1271_STATE_ON && - time_after(jiffies, wl->stats.fw_stats_update + - msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { - wl1271_acx_statistics(wl, wl->stats.fw_stats); - wl->stats.fw_stats_update = jiffies; - } - - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -static int wl1271_open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -DEBUGFS_FWSTATS_FILE(tx, internal_desc_overflow, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rx, out_of_mem, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hdr_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, hw_stuck, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, dropped, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, fcs_err, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, xfr_hint_trig, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, path_reset, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rx, reset_counter, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(dma, rx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, rx_errors, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_requested, 20, "%u"); -DEBUGFS_FWSTATS_FILE(dma, tx_errors, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(isr, cmd_cmplt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, fiqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_headers, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_mem_overflow, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_rdys, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, irqs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, decrypt_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma0_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, dma1_done, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, tx_exch_complete, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, commands, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, rx_procs, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, hw_pm_mode_changes, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, host_acknowledges, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, pci_pm, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, wakeups, 20, "%u"); -DEBUGFS_FWSTATS_FILE(isr, low_rssi, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(wep, addr_key_count, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, default_key_count, 20, "%u"); -/* skipping wep.reserved */ -DEBUGFS_FWSTATS_FILE(wep, key_not_found, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(wep, interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(pwr, ps_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, elp_enter, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, missing_bcns, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_host, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, wake_on_timer_exp, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_with_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, tx_without_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, rcvd_beacons, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, power_save_off, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, enable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, disable_ps, 20, "%u"); -DEBUGFS_FWSTATS_FILE(pwr, fix_tsf_ps, 20, "%u"); -/* skipping cont_miss_bcns_spread for now */ -DEBUGFS_FWSTATS_FILE(pwr, rcvd_awake_beacons, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(mic, rx_pkts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(mic, calc_failure, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(aes, encrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_fail, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_packets, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, encrypt_interrupt, 20, "%u"); -DEBUGFS_FWSTATS_FILE(aes, decrypt_interrupt, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(event, heart_beat, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, calibration, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mismatch, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_mem_empty, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, rx_pool, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, oom_late, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, phy_transmit_error, 20, "%u"); -DEBUGFS_FWSTATS_FILE(event, tx_stuck, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(ps, pspoll_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_timeouts, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_sptime, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_max_apturn, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, pspoll_utilization, 20, "%u"); -DEBUGFS_FWSTATS_FILE(ps, upsd_utilization, 20, "%u"); - -DEBUGFS_FWSTATS_FILE(rxpipe, rx_prep_beacon_drop, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, descr_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, beacon_buffer_thres_host_int_trig_rx_data, - 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, missed_beacon_host_int_trig_rx_data, 20, "%u"); -DEBUGFS_FWSTATS_FILE(rxpipe, tx_xfr_host_int_trig_rx_data, 20, "%u"); - -DEBUGFS_READONLY_FILE(retry_count, 20, "%u", wl->stats.retry_count); -DEBUGFS_READONLY_FILE(excessive_retries, 20, "%u", - wl->stats.excessive_retries); - -static ssize_t tx_queue_len_read(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct wl1271 *wl = file->private_data; - u32 queue_len; - char buf[20]; - int res; - - queue_len = skb_queue_len(&wl->tx_queue); - - res = scnprintf(buf, sizeof(buf), "%u\n", queue_len); - return simple_read_from_buffer(userbuf, count, ppos, buf, res); -} - -static const struct file_operations tx_queue_len_ops = { - .read = tx_queue_len_read, - .open = wl1271_open_file_generic, -}; - -static void wl1271_debugfs_delete_files(struct wl1271 *wl) -{ - DEBUGFS_FWSTATS_DEL(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_DEL(rx, out_of_mem); - DEBUGFS_FWSTATS_DEL(rx, hdr_overflow); - DEBUGFS_FWSTATS_DEL(rx, hw_stuck); - DEBUGFS_FWSTATS_DEL(rx, dropped); - DEBUGFS_FWSTATS_DEL(rx, fcs_err); - DEBUGFS_FWSTATS_DEL(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_DEL(rx, path_reset); - DEBUGFS_FWSTATS_DEL(rx, reset_counter); - - DEBUGFS_FWSTATS_DEL(dma, rx_requested); - DEBUGFS_FWSTATS_DEL(dma, rx_errors); - DEBUGFS_FWSTATS_DEL(dma, tx_requested); - DEBUGFS_FWSTATS_DEL(dma, tx_errors); - - DEBUGFS_FWSTATS_DEL(isr, cmd_cmplt); - DEBUGFS_FWSTATS_DEL(isr, fiqs); - DEBUGFS_FWSTATS_DEL(isr, rx_headers); - DEBUGFS_FWSTATS_DEL(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_DEL(isr, rx_rdys); - DEBUGFS_FWSTATS_DEL(isr, irqs); - DEBUGFS_FWSTATS_DEL(isr, tx_procs); - DEBUGFS_FWSTATS_DEL(isr, decrypt_done); - DEBUGFS_FWSTATS_DEL(isr, dma0_done); - DEBUGFS_FWSTATS_DEL(isr, dma1_done); - DEBUGFS_FWSTATS_DEL(isr, tx_exch_complete); - DEBUGFS_FWSTATS_DEL(isr, commands); - DEBUGFS_FWSTATS_DEL(isr, rx_procs); - DEBUGFS_FWSTATS_DEL(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_DEL(isr, host_acknowledges); - DEBUGFS_FWSTATS_DEL(isr, pci_pm); - DEBUGFS_FWSTATS_DEL(isr, wakeups); - DEBUGFS_FWSTATS_DEL(isr, low_rssi); - - DEBUGFS_FWSTATS_DEL(wep, addr_key_count); - DEBUGFS_FWSTATS_DEL(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_DEL(wep, key_not_found); - DEBUGFS_FWSTATS_DEL(wep, decrypt_fail); - DEBUGFS_FWSTATS_DEL(wep, packets); - DEBUGFS_FWSTATS_DEL(wep, interrupt); - - DEBUGFS_FWSTATS_DEL(pwr, ps_enter); - DEBUGFS_FWSTATS_DEL(pwr, elp_enter); - DEBUGFS_FWSTATS_DEL(pwr, missing_bcns); - DEBUGFS_FWSTATS_DEL(pwr, wake_on_host); - DEBUGFS_FWSTATS_DEL(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_DEL(pwr, tx_with_ps); - DEBUGFS_FWSTATS_DEL(pwr, tx_without_ps); - DEBUGFS_FWSTATS_DEL(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_DEL(pwr, power_save_off); - DEBUGFS_FWSTATS_DEL(pwr, enable_ps); - DEBUGFS_FWSTATS_DEL(pwr, disable_ps); - DEBUGFS_FWSTATS_DEL(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_DEL(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_DEL(mic, rx_pkts); - DEBUGFS_FWSTATS_DEL(mic, calc_failure); - - DEBUGFS_FWSTATS_DEL(aes, encrypt_fail); - DEBUGFS_FWSTATS_DEL(aes, decrypt_fail); - DEBUGFS_FWSTATS_DEL(aes, encrypt_packets); - DEBUGFS_FWSTATS_DEL(aes, decrypt_packets); - DEBUGFS_FWSTATS_DEL(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_DEL(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_DEL(event, heart_beat); - DEBUGFS_FWSTATS_DEL(event, calibration); - DEBUGFS_FWSTATS_DEL(event, rx_mismatch); - DEBUGFS_FWSTATS_DEL(event, rx_mem_empty); - DEBUGFS_FWSTATS_DEL(event, rx_pool); - DEBUGFS_FWSTATS_DEL(event, oom_late); - DEBUGFS_FWSTATS_DEL(event, phy_transmit_error); - DEBUGFS_FWSTATS_DEL(event, tx_stuck); - - DEBUGFS_FWSTATS_DEL(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_DEL(ps, upsd_timeouts); - DEBUGFS_FWSTATS_DEL(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_DEL(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_DEL(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_DEL(ps, pspoll_utilization); - DEBUGFS_FWSTATS_DEL(ps, upsd_utilization); - - DEBUGFS_FWSTATS_DEL(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_DEL(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_DEL(rxpipe, tx_xfr_host_int_trig_rx_data); - - DEBUGFS_DEL(tx_queue_len); - DEBUGFS_DEL(retry_count); - DEBUGFS_DEL(excessive_retries); -} - -static int wl1271_debugfs_add_files(struct wl1271 *wl) -{ - int ret = 0; - - DEBUGFS_FWSTATS_ADD(tx, internal_desc_overflow); - - DEBUGFS_FWSTATS_ADD(rx, out_of_mem); - DEBUGFS_FWSTATS_ADD(rx, hdr_overflow); - DEBUGFS_FWSTATS_ADD(rx, hw_stuck); - DEBUGFS_FWSTATS_ADD(rx, dropped); - DEBUGFS_FWSTATS_ADD(rx, fcs_err); - DEBUGFS_FWSTATS_ADD(rx, xfr_hint_trig); - DEBUGFS_FWSTATS_ADD(rx, path_reset); - DEBUGFS_FWSTATS_ADD(rx, reset_counter); - - DEBUGFS_FWSTATS_ADD(dma, rx_requested); - DEBUGFS_FWSTATS_ADD(dma, rx_errors); - DEBUGFS_FWSTATS_ADD(dma, tx_requested); - DEBUGFS_FWSTATS_ADD(dma, tx_errors); - - DEBUGFS_FWSTATS_ADD(isr, cmd_cmplt); - DEBUGFS_FWSTATS_ADD(isr, fiqs); - DEBUGFS_FWSTATS_ADD(isr, rx_headers); - DEBUGFS_FWSTATS_ADD(isr, rx_mem_overflow); - DEBUGFS_FWSTATS_ADD(isr, rx_rdys); - DEBUGFS_FWSTATS_ADD(isr, irqs); - DEBUGFS_FWSTATS_ADD(isr, tx_procs); - DEBUGFS_FWSTATS_ADD(isr, decrypt_done); - DEBUGFS_FWSTATS_ADD(isr, dma0_done); - DEBUGFS_FWSTATS_ADD(isr, dma1_done); - DEBUGFS_FWSTATS_ADD(isr, tx_exch_complete); - DEBUGFS_FWSTATS_ADD(isr, commands); - DEBUGFS_FWSTATS_ADD(isr, rx_procs); - DEBUGFS_FWSTATS_ADD(isr, hw_pm_mode_changes); - DEBUGFS_FWSTATS_ADD(isr, host_acknowledges); - DEBUGFS_FWSTATS_ADD(isr, pci_pm); - DEBUGFS_FWSTATS_ADD(isr, wakeups); - DEBUGFS_FWSTATS_ADD(isr, low_rssi); - - DEBUGFS_FWSTATS_ADD(wep, addr_key_count); - DEBUGFS_FWSTATS_ADD(wep, default_key_count); - /* skipping wep.reserved */ - DEBUGFS_FWSTATS_ADD(wep, key_not_found); - DEBUGFS_FWSTATS_ADD(wep, decrypt_fail); - DEBUGFS_FWSTATS_ADD(wep, packets); - DEBUGFS_FWSTATS_ADD(wep, interrupt); - - DEBUGFS_FWSTATS_ADD(pwr, ps_enter); - DEBUGFS_FWSTATS_ADD(pwr, elp_enter); - DEBUGFS_FWSTATS_ADD(pwr, missing_bcns); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_host); - DEBUGFS_FWSTATS_ADD(pwr, wake_on_timer_exp); - DEBUGFS_FWSTATS_ADD(pwr, tx_with_ps); - DEBUGFS_FWSTATS_ADD(pwr, tx_without_ps); - DEBUGFS_FWSTATS_ADD(pwr, rcvd_beacons); - DEBUGFS_FWSTATS_ADD(pwr, power_save_off); - DEBUGFS_FWSTATS_ADD(pwr, enable_ps); - DEBUGFS_FWSTATS_ADD(pwr, disable_ps); - DEBUGFS_FWSTATS_ADD(pwr, fix_tsf_ps); - /* skipping cont_miss_bcns_spread for now */ - DEBUGFS_FWSTATS_ADD(pwr, rcvd_awake_beacons); - - DEBUGFS_FWSTATS_ADD(mic, rx_pkts); - DEBUGFS_FWSTATS_ADD(mic, calc_failure); - - DEBUGFS_FWSTATS_ADD(aes, encrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, decrypt_fail); - DEBUGFS_FWSTATS_ADD(aes, encrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, decrypt_packets); - DEBUGFS_FWSTATS_ADD(aes, encrypt_interrupt); - DEBUGFS_FWSTATS_ADD(aes, decrypt_interrupt); - - DEBUGFS_FWSTATS_ADD(event, heart_beat); - DEBUGFS_FWSTATS_ADD(event, calibration); - DEBUGFS_FWSTATS_ADD(event, rx_mismatch); - DEBUGFS_FWSTATS_ADD(event, rx_mem_empty); - DEBUGFS_FWSTATS_ADD(event, rx_pool); - DEBUGFS_FWSTATS_ADD(event, oom_late); - DEBUGFS_FWSTATS_ADD(event, phy_transmit_error); - DEBUGFS_FWSTATS_ADD(event, tx_stuck); - - DEBUGFS_FWSTATS_ADD(ps, pspoll_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_timeouts); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_sptime); - DEBUGFS_FWSTATS_ADD(ps, upsd_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_max_apturn); - DEBUGFS_FWSTATS_ADD(ps, pspoll_utilization); - DEBUGFS_FWSTATS_ADD(ps, upsd_utilization); - - DEBUGFS_FWSTATS_ADD(rxpipe, rx_prep_beacon_drop); - DEBUGFS_FWSTATS_ADD(rxpipe, descr_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, beacon_buffer_thres_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data); - DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data); - - DEBUGFS_ADD(tx_queue_len, wl->debugfs.rootdir); - DEBUGFS_ADD(retry_count, wl->debugfs.rootdir); - DEBUGFS_ADD(excessive_retries, wl->debugfs.rootdir); - -out: - if (ret < 0) - wl1271_debugfs_delete_files(wl); - - return ret; -} - -void wl1271_debugfs_reset(struct wl1271 *wl) -{ - memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats)); - wl->stats.retry_count = 0; - wl->stats.excessive_retries = 0; -} - -int wl1271_debugfs_init(struct wl1271 *wl) -{ - int ret; - - wl->debugfs.rootdir = debugfs_create_dir(KBUILD_MODNAME, NULL); - - if (IS_ERR(wl->debugfs.rootdir)) { - ret = PTR_ERR(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - goto err; - } - - wl->debugfs.fw_statistics = debugfs_create_dir("fw-statistics", - wl->debugfs.rootdir); - - if (IS_ERR(wl->debugfs.fw_statistics)) { - ret = PTR_ERR(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - goto err_root; - } - - wl->stats.fw_stats = kzalloc(sizeof(*wl->stats.fw_stats), - GFP_KERNEL); - - if (!wl->stats.fw_stats) { - ret = -ENOMEM; - goto err_fw; - } - - wl->stats.fw_stats_update = jiffies; - - ret = wl1271_debugfs_add_files(wl); - - if (ret < 0) - goto err_file; - - return 0; - -err_file: - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - -err_fw: - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - -err_root: - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -err: - return ret; -} - -void wl1271_debugfs_exit(struct wl1271 *wl) -{ - wl1271_debugfs_delete_files(wl); - - kfree(wl->stats.fw_stats); - wl->stats.fw_stats = NULL; - - debugfs_remove(wl->debugfs.fw_statistics); - wl->debugfs.fw_statistics = NULL; - - debugfs_remove(wl->debugfs.rootdir); - wl->debugfs.rootdir = NULL; - -} diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.h b/drivers/net/wireless/wl12xx/wl1271_debugfs.h deleted file mode 100644 index 00a45b2669ad..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_debugfs.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef WL1271_DEBUGFS_H -#define WL1271_DEBUGFS_H - -#include "wl1271.h" - -int wl1271_debugfs_init(struct wl1271 *wl); -void wl1271_debugfs_exit(struct wl1271 *wl); -void wl1271_debugfs_reset(struct wl1271 *wl); - -#endif /* WL1271_DEBUGFS_H */ diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c deleted file mode 100644 index f3afd4a6ff33..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_event.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1271.h" -#include "wl1271_reg.h" -#include "wl1271_spi.h" -#include "wl1271_event.h" -#include "wl1271_ps.h" - -static int wl1271_event_scan_complete(struct wl1271 *wl, - struct event_mailbox *mbox) -{ - wl1271_debug(DEBUG_EVENT, "status: 0x%x", - mbox->scheduled_scan_status); - - if (wl->scanning) { - mutex_unlock(&wl->mutex); - ieee80211_scan_completed(wl->hw, false); - mutex_lock(&wl->mutex); - wl->scanning = false; - } - - return 0; -} - -static void wl1271_event_mbox_dump(struct event_mailbox *mbox) -{ - wl1271_debug(DEBUG_EVENT, "MBOX DUMP:"); - wl1271_debug(DEBUG_EVENT, "\tvector: 0x%x", mbox->events_vector); - wl1271_debug(DEBUG_EVENT, "\tmask: 0x%x", mbox->events_mask); -} - -static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox) -{ - int ret; - u32 vector; - - wl1271_event_mbox_dump(mbox); - - vector = mbox->events_vector & ~(mbox->events_mask); - wl1271_debug(DEBUG_EVENT, "vector: 0x%x", vector); - - if (vector & SCAN_COMPLETE_EVENT_ID) { - ret = wl1271_event_scan_complete(wl, mbox); - if (ret < 0) - return ret; - } - - if (vector & BSS_LOSE_EVENT_ID) { - wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT"); - - if (wl->psm_requested && wl->psm) { - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - return ret; - } - } - - return 0; -} - -int wl1271_event_unmask(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_event_mbox_mask(wl, ~(wl->event_mask)); - if (ret < 0) - return ret; - - return 0; -} - -void wl1271_event_mbox_config(struct wl1271 *wl) -{ - wl->mbox_ptr[0] = wl1271_reg_read32(wl, REG_EVENT_MAILBOX_PTR); - wl->mbox_ptr[1] = wl->mbox_ptr[0] + sizeof(struct event_mailbox); - - wl1271_debug(DEBUG_EVENT, "MBOX ptrs: 0x%x 0x%x", - wl->mbox_ptr[0], wl->mbox_ptr[1]); -} - -int wl1271_event_handle(struct wl1271 *wl, u8 mbox_num) -{ - struct event_mailbox mbox; - int ret; - - wl1271_debug(DEBUG_EVENT, "EVENT on mbox %d", mbox_num); - - if (mbox_num > 1) - return -EINVAL; - - /* first we read the mbox descriptor */ - wl1271_spi_mem_read(wl, wl->mbox_ptr[mbox_num], &mbox, - sizeof(struct event_mailbox)); - - /* process the descriptor */ - ret = wl1271_event_process(wl, &mbox); - if (ret < 0) - return ret; - - /* then we let the firmware know it can go on...*/ - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_TRIG, INTR_TRIG_EVENT_ACK); - - return 0; -} diff --git a/drivers/net/wireless/wl12xx/wl1271_event.h b/drivers/net/wireless/wl12xx/wl1271_event.h deleted file mode 100644 index 2cdce7c34bf0..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_event.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_EVENT_H__ -#define __WL1271_EVENT_H__ - -/* - * Mbox events - * - * The event mechanism is based on a pair of event buffers (buffers A and - * B) at fixed locations in the target's memory. The host processes one - * buffer while the other buffer continues to collect events. If the host - * is not processing events, an interrupt is issued to signal that a buffer - * is ready. Once the host is done with processing events from one buffer, - * it signals the target (with an ACK interrupt) that the event buffer is - * free. - */ - -enum { - MEASUREMENT_START_EVENT_ID = BIT(8), - MEASUREMENT_COMPLETE_EVENT_ID = BIT(9), - SCAN_COMPLETE_EVENT_ID = BIT(10), - SCHEDULED_SCAN_COMPLETE_EVENT_ID = BIT(11), - AP_DISCOVERY_COMPLETE_EVENT_ID = BIT(12), - PS_REPORT_EVENT_ID = BIT(13), - PSPOLL_DELIVERY_FAILURE_EVENT_ID = BIT(14), - DISCONNECT_EVENT_COMPLETE_ID = BIT(15), - JOIN_EVENT_COMPLETE_ID = BIT(16), - CHANNEL_SWITCH_COMPLETE_EVENT_ID = BIT(17), - BSS_LOSE_EVENT_ID = BIT(18), - REGAINED_BSS_EVENT_ID = BIT(19), - ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID = BIT(20), - SOFT_GEMINI_SENSE_EVENT_ID = BIT(22), - SOFT_GEMINI_PREDICTION_EVENT_ID = BIT(23), - SOFT_GEMINI_AVALANCHE_EVENT_ID = BIT(24), - PLT_RX_CALIBRATION_COMPLETE_EVENT_ID = BIT(25), - DBG_EVENT_ID = BIT(26), - HEALTH_CHECK_REPLY_EVENT_ID = BIT(27), - PERIODIC_SCAN_COMPLETE_EVENT_ID = BIT(28), - PERIODIC_SCAN_REPORT_EVENT_ID = BIT(29), - BA_SESSION_TEAR_DOWN_EVENT_ID = BIT(30), - EVENT_MBOX_ALL_EVENT_ID = 0x7fffffff, -}; - -struct event_debug_report { - u8 debug_event_id; - u8 num_params; - u16 pad; - u32 report_1; - u32 report_2; - u32 report_3; -} __attribute__ ((packed)); - -#define NUM_OF_RSSI_SNR_TRIGGERS 8 - -struct event_mailbox { - u32 events_vector; - u32 events_mask; - u32 reserved_1; - u32 reserved_2; - - u8 dbg_event_id; - u8 num_relevant_params; - u16 reserved_3; - u32 event_report_p1; - u32 event_report_p2; - u32 event_report_p3; - - u8 number_of_scan_results; - u8 scan_tag; - u8 reserved_4[2]; - u32 compl_scheduled_scan_status; - - u16 scheduled_scan_attended_channels; - u8 soft_gemini_sense_info; - u8 soft_gemini_protective_info; - s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS]; - u8 channel_switch_status; - u8 scheduled_scan_status; - u8 ps_status; - - u8 reserved_5[29]; -} __attribute__ ((packed)); - -int wl1271_event_unmask(struct wl1271 *wl); -void wl1271_event_mbox_config(struct wl1271 *wl); -int wl1271_event_handle(struct wl1271 *wl, u8 mbox); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c deleted file mode 100644 index 490df217605a..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_init.c +++ /dev/null @@ -1,397 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - -#include "wl1271_init.h" -#include "wl12xx_80211.h" -#include "wl1271_acx.h" -#include "wl1271_cmd.h" -#include "wl1271_reg.h" - -static int wl1271_init_hwenc_config(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_feature_cfg(wl); - if (ret < 0) { - wl1271_warning("couldn't set feature config"); - return ret; - } - - ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key); - if (ret < 0) { - wl1271_warning("couldn't set default key"); - return ret; - } - - return 0; -} - -static int wl1271_init_templates_config(struct wl1271 *wl) -{ - int ret; - - /* send empty templates for fw memory reservation */ - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL, - sizeof(struct wl12xx_probe_req_template)); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL, - sizeof(struct wl12xx_null_data_template)); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL, - sizeof(struct wl12xx_ps_poll_template)); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL, - sizeof - (struct wl12xx_qos_null_data_template)); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL, - sizeof - (struct wl12xx_probe_resp_template)); - if (ret < 0) - return ret; - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL, - sizeof - (struct wl12xx_beacon_template)); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter) -{ - int ret; - - ret = wl1271_acx_rx_msdu_life_time(wl, RX_MSDU_LIFETIME_DEF); - if (ret < 0) - return ret; - - ret = wl1271_acx_rx_config(wl, config, filter); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_phy_config(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_pd_threshold(wl); - if (ret < 0) - return ret; - - ret = wl1271_acx_slot(wl, DEFAULT_SLOT_TIME); - if (ret < 0) - return ret; - - ret = wl1271_acx_group_address_tbl(wl); - if (ret < 0) - return ret; - - ret = wl1271_acx_service_period_timeout(wl); - if (ret < 0) - return ret; - - ret = wl1271_acx_rts_threshold(wl, RTS_THRESHOLD_DEF); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_beacon_filter(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_beacon_filter_opt(wl); - if (ret < 0) - return ret; - - ret = wl1271_acx_beacon_filter_table(wl); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_pta(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_sg_enable(wl); - if (ret < 0) - return ret; - - ret = wl1271_acx_sg_cfg(wl); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_energy_detection(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_cca_threshold(wl); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_beacon_broadcast(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_bcn_dtim_options(wl); - if (ret < 0) - return ret; - - return 0; -} - -static int wl1271_init_general_parms(struct wl1271 *wl) -{ - struct wl1271_general_parms *gen_parms; - int ret; - - gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL); - if (!gen_parms) - return -ENOMEM; - - gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM; - - gen_parms->ref_clk = REF_CLK_38_4_E; - /* FIXME: magic numbers */ - gen_parms->settling_time = 5; - gen_parms->clk_valid_on_wakeup = 0; - gen_parms->dc2dcmode = 0; - gen_parms->single_dual_band = 0; - gen_parms->tx_bip_fem_autodetect = 1; - gen_parms->tx_bip_fem_manufacturer = 1; - gen_parms->settings = 1; - - ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0); - if (ret < 0) { - wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed"); - return ret; - } - - kfree(gen_parms); - return 0; -} - -static int wl1271_init_radio_parms(struct wl1271 *wl) -{ - /* - * FIXME: All these magic numbers should be moved to some place where - * they can be configured (separate file?) - */ - - struct wl1271_radio_parms *radio_parms; - int ret; - u8 compensation[] = { 0xec, 0xf6, 0x00, 0x0c, 0x18, 0xf8, 0xfc, 0x00, - 0x08, 0x10, 0xf0, 0xf8, 0x00, 0x0a, 0x14 }; - - u8 tx_rate_limits_normal[] = { 0x1e, 0x1f, 0x22, 0x24, 0x28, 0x29 }; - u8 tx_rate_limits_degraded[] = { 0x1b, 0x1c, 0x1e, 0x20, 0x24, 0x25 }; - - u8 tx_channel_limits_11b[] = { 0x22, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x22, 0x50, - 0x22, 0x50 }; - - u8 tx_channel_limits_ofdm[] = { 0x20, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x50, 0x50, - 0x50, 0x50, 0x20, 0x50, - 0x20, 0x50 }; - - u8 tx_pdv_rate_offsets[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - - u8 tx_ibias[] = { 0x1a, 0x1a, 0x1a, 0x1a, 0x1a, 0x27 }; - - radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL); - if (!radio_parms) - return -ENOMEM; - - radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM; - - /* Static radio parameters */ - radio_parms->rx_trace_loss = 10; - radio_parms->tx_trace_loss = 10; - memcpy(radio_parms->rx_rssi_and_proc_compens, compensation, - sizeof(compensation)); - - /* We don't set the 5GHz -- N/A */ - - /* Dynamic radio parameters */ - radio_parms->tx_ref_pd_voltage = cpu_to_le16(0x24e); - radio_parms->tx_ref_power = 0x78; - radio_parms->tx_offset_db = 0x0; - - memcpy(radio_parms->tx_rate_limits_normal, tx_rate_limits_normal, - sizeof(tx_rate_limits_normal)); - memcpy(radio_parms->tx_rate_limits_degraded, tx_rate_limits_degraded, - sizeof(tx_rate_limits_degraded)); - - memcpy(radio_parms->tx_channel_limits_11b, tx_channel_limits_11b, - sizeof(tx_channel_limits_11b)); - memcpy(radio_parms->tx_channel_limits_ofdm, tx_channel_limits_ofdm, - sizeof(tx_channel_limits_ofdm)); - memcpy(radio_parms->tx_pdv_rate_offsets, tx_pdv_rate_offsets, - sizeof(tx_pdv_rate_offsets)); - memcpy(radio_parms->tx_ibias, tx_ibias, - sizeof(tx_ibias)); - - radio_parms->rx_fem_insertion_loss = 0x14; - - ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0); - if (ret < 0) - wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed"); - - kfree(radio_parms); - return ret; -} - -int wl1271_hw_init(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_init_general_parms(wl); - if (ret < 0) - return ret; - - ret = wl1271_init_radio_parms(wl); - if (ret < 0) - return ret; - - /* Template settings */ - ret = wl1271_init_templates_config(wl); - if (ret < 0) - return ret; - - /* Default memory configuration */ - ret = wl1271_acx_init_mem_config(wl); - if (ret < 0) - return ret; - - /* RX config */ - ret = wl1271_init_rx_config(wl, - RX_CFG_PROMISCUOUS | RX_CFG_TSF, - RX_FILTER_OPTION_DEF); - /* RX_CONFIG_OPTION_ANY_DST_ANY_BSS, - RX_FILTER_OPTION_FILTER_ALL); */ - if (ret < 0) - goto out_free_memmap; - - /* PHY layer config */ - ret = wl1271_init_phy_config(wl); - if (ret < 0) - goto out_free_memmap; - - /* Beacon filtering */ - ret = wl1271_init_beacon_filter(wl); - if (ret < 0) - goto out_free_memmap; - - /* Configure TX patch complete interrupt behavior */ - ret = wl1271_acx_tx_config_options(wl); - if (ret < 0) - goto out_free_memmap; - - /* RX complete interrupt pacing */ - ret = wl1271_acx_init_rx_interrupt(wl); - if (ret < 0) - goto out_free_memmap; - - /* Bluetooth WLAN coexistence */ - ret = wl1271_init_pta(wl); - if (ret < 0) - goto out_free_memmap; - - /* Energy detection */ - ret = wl1271_init_energy_detection(wl); - if (ret < 0) - goto out_free_memmap; - - /* Beacons and boradcast settings */ - ret = wl1271_init_beacon_broadcast(wl); - if (ret < 0) - goto out_free_memmap; - - /* Default fragmentation threshold */ - ret = wl1271_acx_frag_threshold(wl); - if (ret < 0) - goto out_free_memmap; - - /* Default TID configuration */ - ret = wl1271_acx_tid_cfg(wl); - if (ret < 0) - goto out_free_memmap; - - /* Default AC configuration */ - ret = wl1271_acx_ac_cfg(wl); - if (ret < 0) - goto out_free_memmap; - - /* Configure TX rate classes */ - ret = wl1271_acx_rate_policies(wl); - if (ret < 0) - goto out_free_memmap; - - /* Enable data path */ - ret = wl1271_cmd_data_path(wl, wl->channel, 1); - if (ret < 0) - goto out_free_memmap; - - /* Configure for ELP power saving */ - ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP); - if (ret < 0) - goto out_free_memmap; - - /* Configure HW encryption */ - ret = wl1271_init_hwenc_config(wl); - if (ret < 0) - goto out_free_memmap; - - return 0; - - out_free_memmap: - kfree(wl->target_mem_map); - - return ret; -} diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h deleted file mode 100644 index bd8ff0fa2272..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_init.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_INIT_H__ -#define __WL1271_INIT_H__ - -#include "wl1271.h" - -int wl1271_hw_init_power_auth(struct wl1271 *wl); -int wl1271_hw_init(struct wl1271 *wl); - -/* These are not really a TEST_CMD, but the ref driver uses them as such */ -#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19 -#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E - -struct wl1271_general_parms { - u8 id; - u8 padding[3]; - - u8 ref_clk; - u8 settling_time; - u8 clk_valid_on_wakeup; - u8 dc2dcmode; - u8 single_dual_band; - - u8 tx_bip_fem_autodetect; - u8 tx_bip_fem_manufacturer; - u8 settings; -} __attribute__ ((packed)); - -enum ref_clk_enum { - REF_CLK_19_2_E, - REF_CLK_26_E, - REF_CLK_38_4_E, - REF_CLK_52_E -}; - -#define RSSI_AND_PROCESS_COMPENSATION_SIZE 15 -#define NUMBER_OF_SUB_BANDS_5 7 -#define NUMBER_OF_RATE_GROUPS 6 -#define NUMBER_OF_CHANNELS_2_4 14 -#define NUMBER_OF_CHANNELS_5 35 - -struct wl1271_radio_parms { - u8 id; - u8 padding[3]; - - /* Static radio parameters */ - /* 2.4GHz */ - u8 rx_trace_loss; - u8 tx_trace_loss; - s8 rx_rssi_and_proc_compens[RSSI_AND_PROCESS_COMPENSATION_SIZE]; - - /* 5GHz */ - u8 rx_trace_loss_5[NUMBER_OF_SUB_BANDS_5]; - u8 tx_trace_loss_5[NUMBER_OF_SUB_BANDS_5]; - s8 rx_rssi_and_proc_compens_5[RSSI_AND_PROCESS_COMPENSATION_SIZE]; - - /* Dynamic radio parameters */ - /* 2.4GHz */ - s16 tx_ref_pd_voltage; - s8 tx_ref_power; - s8 tx_offset_db; - - s8 tx_rate_limits_normal[NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_degraded[NUMBER_OF_RATE_GROUPS]; - - s8 tx_channel_limits_11b[NUMBER_OF_CHANNELS_2_4]; - s8 tx_channel_limits_ofdm[NUMBER_OF_CHANNELS_2_4]; - s8 tx_pdv_rate_offsets[NUMBER_OF_RATE_GROUPS]; - - u8 tx_ibias[NUMBER_OF_RATE_GROUPS]; - u8 rx_fem_insertion_loss; - - u8 padding2; - - /* 5GHz */ - s16 tx_ref_pd_voltage_5[NUMBER_OF_SUB_BANDS_5]; - s8 tx_ref_power_5[NUMBER_OF_SUB_BANDS_5]; - s8 tx_offset_db_5[NUMBER_OF_SUB_BANDS_5]; - - s8 tx_rate_limits_normal_5[NUMBER_OF_RATE_GROUPS]; - s8 tx_rate_limits_degraded_5[NUMBER_OF_RATE_GROUPS]; - - s8 tx_channel_limits_ofdm_5[NUMBER_OF_CHANNELS_5]; - s8 tx_pdv_rate_offsets_5[NUMBER_OF_RATE_GROUPS]; - - /* FIXME: this is inconsistent with the types for 2.4GHz */ - s8 tx_ibias_5[NUMBER_OF_RATE_GROUPS]; - s8 rx_fem_insertion_loss_5[NUMBER_OF_SUB_BANDS_5]; - - u8 padding3[2]; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c deleted file mode 100644 index 27298b19d5bd..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_main.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "wl1271.h" -#include "wl12xx_80211.h" -#include "wl1271_reg.h" -#include "wl1271_spi.h" -#include "wl1271_event.h" -#include "wl1271_tx.h" -#include "wl1271_rx.h" -#include "wl1271_ps.h" -#include "wl1271_init.h" -#include "wl1271_debugfs.h" -#include "wl1271_cmd.h" -#include "wl1271_boot.h" - -static int wl1271_plt_init(struct wl1271 *wl) -{ - int ret; - - ret = wl1271_acx_init_mem_config(wl); - if (ret < 0) - return ret; - - ret = wl1271_cmd_data_path(wl, wl->channel, 1); - if (ret < 0) - return ret; - - return 0; -} - -static void wl1271_disable_interrupts(struct wl1271 *wl) -{ - disable_irq(wl->irq); -} - -static void wl1271_power_off(struct wl1271 *wl) -{ - wl->set_power(false); -} - -static void wl1271_power_on(struct wl1271 *wl) -{ - wl->set_power(true); -} - -static void wl1271_fw_status(struct wl1271 *wl, struct wl1271_fw_status *status) -{ - u32 total = 0; - int i; - - /* - * FIXME: Reading the FW status directly from the registers seems to - * be the right thing to do, but it doesn't work. And in the - * reference driver, there is a workaround called - * USE_SDIO_24M_WORKAROUND, which reads the status from memory - * instead, so we do the same here. - */ - - wl1271_spi_mem_read(wl, STATUS_MEM_ADDRESS, status, sizeof(*status)); - - wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, " - "drv_rx_counter = %d, tx_results_counter = %d)", - status->intr, - status->fw_rx_counter, - status->drv_rx_counter, - status->tx_results_counter); - - /* update number of available TX blocks */ - for (i = 0; i < NUM_TX_QUEUES; i++) { - u32 cnt = status->tx_released_blks[i] - wl->tx_blocks_freed[i]; - wl->tx_blocks_freed[i] = status->tx_released_blks[i]; - wl->tx_blocks_available += cnt; - total += cnt; - } - - /* if more blocks are available now, schedule some tx work */ - if (total && !skb_queue_empty(&wl->tx_queue)) - schedule_work(&wl->tx_work); - - /* update the host-chipset time offset */ - wl->time_offset = jiffies_to_usecs(jiffies) - status->fw_localtime; -} - -#define WL1271_IRQ_MAX_LOOPS 10 -static void wl1271_irq_work(struct work_struct *work) -{ - u32 intr, ctr = WL1271_IRQ_MAX_LOOPS; - int ret; - struct wl1271 *wl = - container_of(work, struct wl1271, irq_work); - - mutex_lock(&wl->mutex); - - wl1271_debug(DEBUG_IRQ, "IRQ work"); - - if (wl->state == WL1271_STATE_OFF) - goto out; - - ret = wl1271_ps_elp_wakeup(wl, true); - if (ret < 0) - goto out; - - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL); - - intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); - if (!intr) { - wl1271_debug(DEBUG_IRQ, "Zero interrupt received."); - goto out_sleep; - } - - intr &= WL1271_INTR_MASK; - - do { - wl1271_fw_status(wl, wl->fw_status); - - - if (intr & (WL1271_ACX_INTR_EVENT_A | - WL1271_ACX_INTR_EVENT_B)) { - wl1271_debug(DEBUG_IRQ, - "WL1271_ACX_INTR_EVENT (0x%x)", intr); - if (intr & WL1271_ACX_INTR_EVENT_A) - wl1271_event_handle(wl, 0); - else - wl1271_event_handle(wl, 1); - } - - if (intr & WL1271_ACX_INTR_INIT_COMPLETE) - wl1271_debug(DEBUG_IRQ, - "WL1271_ACX_INTR_INIT_COMPLETE"); - - if (intr & WL1271_ACX_INTR_HW_AVAILABLE) - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE"); - - if (intr & WL1271_ACX_INTR_DATA) { - u8 tx_res_cnt = wl->fw_status->tx_results_counter - - wl->tx_results_count; - - wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA"); - - /* check for tx results */ - if (tx_res_cnt) - wl1271_tx_complete(wl, tx_res_cnt); - - wl1271_rx(wl, wl->fw_status); - } - - intr = wl1271_reg_read32(wl, ACX_REG_INTERRUPT_CLEAR); - intr &= WL1271_INTR_MASK; - } while (intr && --ctr); - -out_sleep: - wl1271_reg_write32(wl, ACX_REG_INTERRUPT_MASK, - WL1271_ACX_INTR_ALL & ~(WL1271_INTR_MASK)); - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -static irqreturn_t wl1271_irq(int irq, void *cookie) -{ - struct wl1271 *wl; - unsigned long flags; - - wl1271_debug(DEBUG_IRQ, "IRQ"); - - wl = cookie; - - /* complete the ELP completion */ - spin_lock_irqsave(&wl->wl_lock, flags); - if (wl->elp_compl) { - complete(wl->elp_compl); - wl->elp_compl = NULL; - } - - schedule_work(&wl->irq_work); - spin_unlock_irqrestore(&wl->wl_lock, flags); - - return IRQ_HANDLED; -} - -static int wl1271_fetch_firmware(struct wl1271 *wl) -{ - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, WL1271_FW_NAME, &wl->spi->dev); - - if (ret < 0) { - wl1271_error("could not get firmware: %d", ret); - return ret; - } - - if (fw->size % 4) { - wl1271_error("firmware size is not multiple of 32 bits: %zu", - fw->size); - ret = -EILSEQ; - goto out; - } - - wl->fw_len = fw->size; - wl->fw = kmalloc(wl->fw_len, GFP_KERNEL); - - if (!wl->fw) { - wl1271_error("could not allocate memory for the firmware"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->fw, fw->data, wl->fw_len); - - ret = 0; - -out: - release_firmware(fw); - - return ret; -} - -static int wl1271_fetch_nvs(struct wl1271 *wl) -{ - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, WL1271_NVS_NAME, &wl->spi->dev); - - if (ret < 0) { - wl1271_error("could not get nvs file: %d", ret); - return ret; - } - - if (fw->size % 4) { - wl1271_error("nvs size is not multiple of 32 bits: %zu", - fw->size); - ret = -EILSEQ; - goto out; - } - - wl->nvs_len = fw->size; - wl->nvs = kmalloc(wl->nvs_len, GFP_KERNEL); - - if (!wl->nvs) { - wl1271_error("could not allocate memory for the nvs file"); - ret = -ENOMEM; - goto out; - } - - memcpy(wl->nvs, fw->data, wl->nvs_len); - - ret = 0; - -out: - release_firmware(fw); - - return ret; -} - -static void wl1271_fw_wakeup(struct wl1271 *wl) -{ - u32 elp_reg; - - elp_reg = ELPCTRL_WAKE_UP; - wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, elp_reg); -} - -static int wl1271_setup(struct wl1271 *wl) -{ - wl->fw_status = kmalloc(sizeof(*wl->fw_status), GFP_KERNEL); - if (!wl->fw_status) - return -ENOMEM; - - wl->tx_res_if = kmalloc(sizeof(*wl->tx_res_if), GFP_KERNEL); - if (!wl->tx_res_if) { - kfree(wl->fw_status); - return -ENOMEM; - } - - INIT_WORK(&wl->irq_work, wl1271_irq_work); - INIT_WORK(&wl->tx_work, wl1271_tx_work); - return 0; -} - -static int wl1271_chip_wakeup(struct wl1271 *wl) -{ - int ret = 0; - - wl1271_power_on(wl); - msleep(WL1271_POWER_ON_SLEEP); - wl1271_spi_reset(wl); - wl1271_spi_init(wl); - - /* We don't need a real memory partition here, because we only want - * to use the registers at this point. */ - wl1271_set_partition(wl, - 0x00000000, - 0x00000000, - REGISTERS_BASE, - REGISTERS_DOWN_SIZE); - - /* ELP module wake up */ - wl1271_fw_wakeup(wl); - - /* whal_FwCtrl_BootSm() */ - - /* 0. read chip id from CHIP_ID */ - wl->chip.id = wl1271_reg_read32(wl, CHIP_ID_B); - - /* 1. check if chip id is valid */ - - switch (wl->chip.id) { - case CHIP_ID_1271_PG10: - wl1271_warning("chip id 0x%x (1271 PG10) support is obsolete", - wl->chip.id); - - ret = wl1271_setup(wl); - if (ret < 0) - goto out; - break; - case CHIP_ID_1271_PG20: - wl1271_debug(DEBUG_BOOT, "chip id 0x%x (1271 PG20)", - wl->chip.id); - - ret = wl1271_setup(wl); - if (ret < 0) - goto out; - break; - default: - wl1271_error("unsupported chip id: 0x%x", wl->chip.id); - ret = -ENODEV; - goto out; - } - - if (wl->fw == NULL) { - ret = wl1271_fetch_firmware(wl); - if (ret < 0) - goto out; - } - - /* No NVS from netlink, try to get it from the filesystem */ - if (wl->nvs == NULL) { - ret = wl1271_fetch_nvs(wl); - if (ret < 0) - goto out; - } - -out: - return ret; -} - -static void wl1271_filter_work(struct work_struct *work) -{ - struct wl1271 *wl = - container_of(work, struct wl1271, filter_work); - int ret; - - mutex_lock(&wl->mutex); - - if (wl->state == WL1271_STATE_OFF) - goto out; - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - /* FIXME: replace the magic numbers with proper definitions */ - ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); - if (ret < 0) - goto out_sleep; - -out_sleep: - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - -int wl1271_plt_start(struct wl1271 *wl) -{ - int ret; - - mutex_lock(&wl->mutex); - - wl1271_notice("power up"); - - if (wl->state != WL1271_STATE_OFF) { - wl1271_error("cannot go into PLT state because not " - "in off state: %d", wl->state); - ret = -EBUSY; - goto out; - } - - wl->state = WL1271_STATE_PLT; - - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1271_boot(wl); - if (ret < 0) - goto out; - - wl1271_notice("firmware booted in PLT mode (%s)", wl->chip.fw_ver); - - ret = wl1271_plt_init(wl); - if (ret < 0) - goto out; - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -int wl1271_plt_stop(struct wl1271 *wl) -{ - int ret = 0; - - mutex_lock(&wl->mutex); - - wl1271_notice("power down"); - - if (wl->state != WL1271_STATE_PLT) { - wl1271_error("cannot power down because not in PLT " - "state: %d", wl->state); - ret = -EBUSY; - goto out; - } - - wl1271_disable_interrupts(wl); - wl1271_power_off(wl); - - wl->state = WL1271_STATE_OFF; - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - - -static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct wl1271 *wl = hw->priv; - - skb_queue_tail(&wl->tx_queue, skb); - - /* - * The chip specific setup must run before the first TX packet - - * before that, the tx_work will not be initialized! - */ - - schedule_work(&wl->tx_work); - - /* - * The workqueue is slow to process the tx_queue and we need stop - * the queue here, otherwise the queue will get too long. - */ - if (skb_queue_len(&wl->tx_queue) >= WL1271_TX_QUEUE_MAX_LENGTH) { - ieee80211_stop_queues(wl->hw); - - /* - * FIXME: this is racy, the variable is not properly - * protected. Maybe fix this by removing the stupid - * variable altogether and checking the real queue state? - */ - wl->tx_queue_stopped = true; - } - - return NETDEV_TX_OK; -} - -static int wl1271_op_start(struct ieee80211_hw *hw) -{ - struct wl1271 *wl = hw->priv; - int ret = 0; - - wl1271_debug(DEBUG_MAC80211, "mac80211 start"); - - mutex_lock(&wl->mutex); - - if (wl->state != WL1271_STATE_OFF) { - wl1271_error("cannot start because not in off state: %d", - wl->state); - ret = -EBUSY; - goto out; - } - - ret = wl1271_chip_wakeup(wl); - if (ret < 0) - goto out; - - ret = wl1271_boot(wl); - if (ret < 0) - goto out; - - ret = wl1271_hw_init(wl); - if (ret < 0) - goto out; - - wl->state = WL1271_STATE_ON; - - wl1271_info("firmware booted (%s)", wl->chip.fw_ver); - -out: - if (ret < 0) - wl1271_power_off(wl); - - mutex_unlock(&wl->mutex); - - return ret; -} - -static void wl1271_op_stop(struct ieee80211_hw *hw) -{ - struct wl1271 *wl = hw->priv; - int i; - - wl1271_info("down"); - - wl1271_debug(DEBUG_MAC80211, "mac80211 stop"); - - mutex_lock(&wl->mutex); - - WARN_ON(wl->state != WL1271_STATE_ON); - - if (wl->scanning) { - mutex_unlock(&wl->mutex); - ieee80211_scan_completed(wl->hw, true); - mutex_lock(&wl->mutex); - wl->scanning = false; - } - - wl->state = WL1271_STATE_OFF; - - wl1271_disable_interrupts(wl); - - mutex_unlock(&wl->mutex); - - cancel_work_sync(&wl->irq_work); - cancel_work_sync(&wl->tx_work); - cancel_work_sync(&wl->filter_work); - - mutex_lock(&wl->mutex); - - /* let's notify MAC80211 about the remaining pending TX frames */ - wl1271_tx_flush(wl); - wl1271_power_off(wl); - - memset(wl->bssid, 0, ETH_ALEN); - memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); - wl->ssid_len = 0; - wl->listen_int = 1; - wl->bss_type = MAX_BSS_TYPE; - - wl->rx_counter = 0; - wl->elp = false; - wl->psm = 0; - wl->tx_queue_stopped = false; - wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - wl->tx_blocks_available = 0; - wl->tx_results_count = 0; - wl->tx_packets_count = 0; - wl->time_offset = 0; - wl->session_counter = 0; - for (i = 0; i < NUM_TX_QUEUES; i++) - wl->tx_blocks_freed[i] = 0; - - wl1271_debugfs_reset(wl); - mutex_unlock(&wl->mutex); -} - -static int wl1271_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct wl1271 *wl = hw->priv; - int ret = 0; - - wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM", - conf->type, conf->mac_addr); - - mutex_lock(&wl->mutex); - - switch (conf->type) { - case NL80211_IFTYPE_STATION: - wl->bss_type = BSS_TYPE_STA_BSS; - break; - case NL80211_IFTYPE_ADHOC: - wl->bss_type = BSS_TYPE_IBSS; - break; - default: - ret = -EOPNOTSUPP; - goto out; - } - - /* FIXME: what if conf->mac_addr changes? */ - -out: - mutex_unlock(&wl->mutex); - return ret; -} - -static void wl1271_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface"); -} - -#if 0 -static int wl1271_op_config_interface(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_if_conf *conf) -{ - struct wl1271 *wl = hw->priv; - struct sk_buff *beacon; - int ret; - - wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM", - conf->bssid); - wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid, - conf->ssid_len); - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - memcpy(wl->bssid, conf->bssid, ETH_ALEN); - - ret = wl1271_cmd_build_null_data(wl); - if (ret < 0) - goto out_sleep; - - wl->ssid_len = conf->ssid_len; - if (wl->ssid_len) - memcpy(wl->ssid, conf->ssid, wl->ssid_len); - - if (wl->bss_type != BSS_TYPE_IBSS) { - /* FIXME: replace the magic numbers with proper definitions */ - ret = wl1271_cmd_join(wl, wl->bss_type, 5, 100, 1); - if (ret < 0) - goto out_sleep; - } - - if (conf->changed & IEEE80211_IFCC_BEACON) { - beacon = ieee80211_beacon_get(hw, vif); - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, - beacon->data, beacon->len); - - if (ret < 0) { - dev_kfree_skb(beacon); - goto out_sleep; - } - - ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, - beacon->data, beacon->len); - - dev_kfree_skb(beacon); - - if (ret < 0) - goto out_sleep; - - /* FIXME: replace the magic numbers with proper definitions */ - ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); - - if (ret < 0) - goto out_sleep; - } - -out_sleep: - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} -#endif - -static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct wl1271 *wl = hw->priv; - struct ieee80211_conf *conf = &hw->conf; - int channel, ret = 0; - - channel = ieee80211_frequency_to_channel(conf->channel->center_freq); - - wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d", - channel, - conf->flags & IEEE80211_CONF_PS ? "on" : "off", - conf->power_level); - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - if (channel != wl->channel) { - u8 old_channel = wl->channel; - wl->channel = channel; - - /* FIXME: use beacon interval provided by mac80211 */ - ret = wl1271_cmd_join(wl, wl->bss_type, 1, 100, 0); - if (ret < 0) { - wl->channel = old_channel; - goto out_sleep; - } - } - - ret = wl1271_cmd_build_null_data(wl); - if (ret < 0) - goto out_sleep; - - if (conf->flags & IEEE80211_CONF_PS && !wl->psm_requested) { - wl1271_info("psm enabled"); - - wl->psm_requested = true; - - /* - * We enter PSM only if we're already associated. - * If we're not, we'll enter it when joining an SSID, - * through the bss_info_changed() hook. - */ - ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); - } else if (!(conf->flags & IEEE80211_CONF_PS) && - wl->psm_requested) { - wl1271_info("psm disabled"); - - wl->psm_requested = false; - - if (wl->psm) - ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE); - } - - if (conf->power_level != wl->power_level) { - ret = wl1271_acx_tx_power(wl, conf->power_level); - if (ret < 0) - goto out; - - wl->power_level = conf->power_level; - } - -out_sleep: - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -#define WL1271_SUPPORTED_FILTERS (FIF_PROMISC_IN_BSS | \ - FIF_ALLMULTI | \ - FIF_FCSFAIL | \ - FIF_BCN_PRBRESP_PROMISC | \ - FIF_CONTROL | \ - FIF_OTHER_BSS) - -static void wl1271_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed, - unsigned int *total,u64 multicast) -{ - struct wl1271 *wl = hw->priv; - - wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter"); - - *total &= WL1271_SUPPORTED_FILTERS; - changed &= WL1271_SUPPORTED_FILTERS; - - if (changed == 0) - return; - - /* FIXME: wl->rx_config and wl->rx_filter are not protected */ - wl->rx_config = WL1271_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1271_DEFAULT_RX_FILTER; - - /* - * FIXME: workqueues need to be properly cancelled on stop(), for - * now let's just disable changing the filter settings. They will - * be updated any on config(). - */ - /* schedule_work(&wl->filter_work); */ -} - -static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, - struct ieee80211_vif *vif, - struct ieee80211_sta *sta, - struct ieee80211_key_conf *key_conf) -{ - struct wl1271 *wl = hw->priv; - const u8 *addr; - int ret; - u8 key_type; - - static const u8 bcast_addr[ETH_ALEN] = - { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; - - wl1271_debug(DEBUG_MAC80211, "mac80211 set key"); - - addr = sta ? sta->addr : bcast_addr; - - wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd); - wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN); - wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x", - key_conf->alg, key_conf->keyidx, - key_conf->keylen, key_conf->flags); - wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); - - if (is_zero_ether_addr(addr)) { - /* We dont support TX only encryption */ - ret = -EOPNOTSUPP; - goto out; - } - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out_unlock; - - switch (key_conf->alg) { - case ALG_WEP: - key_type = KEY_WEP; - - key_conf->hw_key_idx = key_conf->keyidx; - break; - case ALG_TKIP: - key_type = KEY_TKIP; - - key_conf->hw_key_idx = key_conf->keyidx; - break; - case ALG_CCMP: - key_type = KEY_AES; - - key_conf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; - break; - default: - wl1271_error("Unknown key algo 0x%x", key_conf->alg); - - ret = -EOPNOTSUPP; - goto out_sleep; - } - - switch (cmd) { - case SET_KEY: - ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE, - key_conf->keyidx, key_type, - key_conf->keylen, key_conf->key, - addr); - if (ret < 0) { - wl1271_error("Could not add or replace key"); - goto out_sleep; - } - break; - - case DISABLE_KEY: - ret = wl1271_cmd_set_key(wl, KEY_REMOVE, - key_conf->keyidx, key_type, - key_conf->keylen, key_conf->key, - addr); - if (ret < 0) { - wl1271_error("Could not remove key"); - goto out_sleep; - } - break; - - default: - wl1271_error("Unsupported key cmd 0x%x", cmd); - ret = -EOPNOTSUPP; - goto out_sleep; - - break; - } - -out_sleep: - wl1271_ps_elp_sleep(wl); - -out_unlock: - mutex_unlock(&wl->mutex); - -out: - return ret; -} - -static int wl1271_op_hw_scan(struct ieee80211_hw *hw, - struct cfg80211_scan_request *req) -{ - struct wl1271 *wl = hw->priv; - int ret; - u8 *ssid = NULL; - size_t ssid_len = 0; - - wl1271_debug(DEBUG_MAC80211, "mac80211 hw scan"); - - if (req->n_ssids) { - ssid = req->ssids[0].ssid; - ssid_len = req->ssids[0].ssid_len; - } - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - ret = wl1271_cmd_scan(hw->priv, ssid, ssid_len, 1, 0, 13, 3); - - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) -{ - struct wl1271 *wl = hw->priv; - int ret; - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - ret = wl1271_acx_rts_threshold(wl, (u16) value); - if (ret < 0) - wl1271_warning("wl1271_op_set_rts_threshold failed: %d", ret); - - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); - - return ret; -} - -static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changed) -{ - enum wl1271_cmd_ps_mode mode; - struct wl1271 *wl = hw->priv; - int ret; - - wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed"); - - mutex_lock(&wl->mutex); - - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - - if (changed & BSS_CHANGED_ASSOC) { - if (bss_conf->assoc) { - wl->aid = bss_conf->aid; - - ret = wl1271_cmd_build_ps_poll(wl, wl->aid); - if (ret < 0) - goto out_sleep; - - ret = wl1271_acx_aid(wl, wl->aid); - if (ret < 0) - goto out_sleep; - - /* If we want to go in PSM but we're not there yet */ - if (wl->psm_requested && !wl->psm) { - mode = STATION_POWER_SAVE_MODE; - ret = wl1271_ps_set_mode(wl, mode); - if (ret < 0) - goto out_sleep; - } - } - } - if (changed & BSS_CHANGED_ERP_SLOT) { - if (bss_conf->use_short_slot) - ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT); - else - ret = wl1271_acx_slot(wl, SLOT_TIME_LONG); - if (ret < 0) { - wl1271_warning("Set slot time failed %d", ret); - goto out_sleep; - } - } - - if (changed & BSS_CHANGED_ERP_PREAMBLE) { - if (bss_conf->use_short_preamble) - wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT); - else - wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG); - } - - if (changed & BSS_CHANGED_ERP_CTS_PROT) { - if (bss_conf->use_cts_prot) - ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE); - else - ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE); - if (ret < 0) { - wl1271_warning("Set ctsprotect failed %d", ret); - goto out_sleep; - } - } - -out_sleep: - wl1271_ps_elp_sleep(wl); - -out: - mutex_unlock(&wl->mutex); -} - - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_rate wl1271_rates[] = { - { .bitrate = 10, - .hw_value = 0x1, - .hw_value_short = 0x1, }, - { .bitrate = 20, - .hw_value = 0x2, - .hw_value_short = 0x2, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, - .hw_value = 0x4, - .hw_value_short = 0x4, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, - .hw_value = 0x20, - .hw_value_short = 0x20, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, - .hw_value = 0x8, - .hw_value_short = 0x8, }, - { .bitrate = 90, - .hw_value = 0x10, - .hw_value_short = 0x10, }, - { .bitrate = 120, - .hw_value = 0x40, - .hw_value_short = 0x40, }, - { .bitrate = 180, - .hw_value = 0x80, - .hw_value_short = 0x80, }, - { .bitrate = 240, - .hw_value = 0x200, - .hw_value_short = 0x200, }, - { .bitrate = 360, - .hw_value = 0x400, - .hw_value_short = 0x400, }, - { .bitrate = 480, - .hw_value = 0x800, - .hw_value_short = 0x800, }, - { .bitrate = 540, - .hw_value = 0x1000, - .hw_value_short = 0x1000, }, -}; - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_channel wl1271_channels[] = { - { .hw_value = 1, .center_freq = 2412}, - { .hw_value = 2, .center_freq = 2417}, - { .hw_value = 3, .center_freq = 2422}, - { .hw_value = 4, .center_freq = 2427}, - { .hw_value = 5, .center_freq = 2432}, - { .hw_value = 6, .center_freq = 2437}, - { .hw_value = 7, .center_freq = 2442}, - { .hw_value = 8, .center_freq = 2447}, - { .hw_value = 9, .center_freq = 2452}, - { .hw_value = 10, .center_freq = 2457}, - { .hw_value = 11, .center_freq = 2462}, - { .hw_value = 12, .center_freq = 2467}, - { .hw_value = 13, .center_freq = 2472}, -}; - -/* can't be const, mac80211 writes to this */ -static struct ieee80211_supported_band wl1271_band_2ghz = { - .channels = wl1271_channels, - .n_channels = ARRAY_SIZE(wl1271_channels), - .bitrates = wl1271_rates, - .n_bitrates = ARRAY_SIZE(wl1271_rates), -}; - -static const struct ieee80211_ops wl1271_ops = { - .start = wl1271_op_start, - .stop = wl1271_op_stop, - .add_interface = wl1271_op_add_interface, - .remove_interface = wl1271_op_remove_interface, - .config = wl1271_op_config, -/* .config_interface = wl1271_op_config_interface, */ - .configure_filter = wl1271_op_configure_filter, - .tx = wl1271_op_tx, - .set_key = wl1271_op_set_key, - .hw_scan = wl1271_op_hw_scan, - .bss_info_changed = wl1271_op_bss_info_changed, - .set_rts_threshold = wl1271_op_set_rts_threshold, -}; - -static int wl1271_register_hw(struct wl1271 *wl) -{ - int ret; - - if (wl->mac80211_registered) - return 0; - - SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr); - - ret = ieee80211_register_hw(wl->hw); - if (ret < 0) { - wl1271_error("unable to register mac80211 hw: %d", ret); - return ret; - } - - wl->mac80211_registered = true; - - wl1271_notice("loaded"); - - return 0; -} - -static int wl1271_init_ieee80211(struct wl1271 *wl) -{ - /* - * The tx descriptor buffer and the TKIP space. - * - * FIXME: add correct 1271 descriptor size - */ - wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE; - - /* unit us */ - /* FIXME: find a proper value */ - wl->hw->channel_change_time = 10000; - - wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | - IEEE80211_HW_NOISE_DBM; - - wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); - wl->hw->wiphy->max_scan_ssids = 1; - wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz; - - SET_IEEE80211_DEV(wl->hw, &wl->spi->dev); - - return 0; -} - -static void wl1271_device_release(struct device *dev) -{ - -} - -static struct platform_device wl1271_device = { - .name = "wl1271", - .id = -1, - - /* device model insists to have a release function */ - .dev = { - .release = wl1271_device_release, - }, -}; - -#define WL1271_DEFAULT_CHANNEL 0 -static int __devinit wl1271_probe(struct spi_device *spi) -{ - struct wl12xx_platform_data *pdata; - struct ieee80211_hw *hw; - struct wl1271 *wl; - int ret, i; - static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf}; - - pdata = spi->dev.platform_data; - if (!pdata) { - wl1271_error("no platform data"); - return -ENODEV; - } - - hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); - if (!hw) { - wl1271_error("could not alloc ieee80211_hw"); - return -ENOMEM; - } - - wl = hw->priv; - memset(wl, 0, sizeof(*wl)); - - wl->hw = hw; - dev_set_drvdata(&spi->dev, wl); - wl->spi = spi; - - skb_queue_head_init(&wl->tx_queue); - - INIT_WORK(&wl->filter_work, wl1271_filter_work); - wl->channel = WL1271_DEFAULT_CHANNEL; - wl->scanning = false; - wl->default_key = 0; - wl->listen_int = 1; - wl->rx_counter = 0; - wl->rx_config = WL1271_DEFAULT_RX_CONFIG; - wl->rx_filter = WL1271_DEFAULT_RX_FILTER; - wl->elp = false; - wl->psm = 0; - wl->psm_requested = false; - wl->tx_queue_stopped = false; - wl->power_level = WL1271_DEFAULT_POWER_LEVEL; - - /* We use the default power on sleep time until we know which chip - * we're using */ - for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) - wl->tx_frames[i] = NULL; - - spin_lock_init(&wl->wl_lock); - - /* - * In case our MAC address is not correctly set, - * we use a random but Nokia MAC. - */ - memcpy(wl->mac_addr, nokia_oui, 3); - get_random_bytes(wl->mac_addr + 3, 3); - - wl->state = WL1271_STATE_OFF; - mutex_init(&wl->mutex); - - wl->rx_descriptor = kmalloc(sizeof(*wl->rx_descriptor), GFP_KERNEL); - if (!wl->rx_descriptor) { - wl1271_error("could not allocate memory for rx descriptor"); - ret = -ENOMEM; - goto out_free; - } - - /* This is the only SPI value that we need to set here, the rest - * comes from the board-peripherals file */ - spi->bits_per_word = 32; - - ret = spi_setup(spi); - if (ret < 0) { - wl1271_error("spi_setup failed"); - goto out_free; - } - - wl->set_power = pdata->set_power; - if (!wl->set_power) { - wl1271_error("set power function missing in platform data"); - ret = -ENODEV; - goto out_free; - } - - wl->irq = spi->irq; - if (wl->irq < 0) { - wl1271_error("irq missing in platform data"); - ret = -ENODEV; - goto out_free; - } - - ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl); - if (ret < 0) { - wl1271_error("request_irq() failed: %d", ret); - goto out_free; - } - - set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING); - - disable_irq(wl->irq); - - ret = platform_device_register(&wl1271_device); - if (ret) { - wl1271_error("couldn't register platform device"); - goto out_irq; - } - dev_set_drvdata(&wl1271_device.dev, wl); - - ret = wl1271_init_ieee80211(wl); - if (ret) - goto out_platform; - - ret = wl1271_register_hw(wl); - if (ret) - goto out_platform; - - wl1271_debugfs_init(wl); - - wl1271_notice("initialized"); - - return 0; - - out_platform: - platform_device_unregister(&wl1271_device); - - out_irq: - free_irq(wl->irq, wl); - - out_free: - kfree(wl->rx_descriptor); - wl->rx_descriptor = NULL; - - ieee80211_free_hw(hw); - - return ret; -} - -static int __devexit wl1271_remove(struct spi_device *spi) -{ - struct wl1271 *wl = dev_get_drvdata(&spi->dev); - - ieee80211_unregister_hw(wl->hw); - - wl1271_debugfs_exit(wl); - platform_device_unregister(&wl1271_device); - free_irq(wl->irq, wl); - kfree(wl->target_mem_map); - kfree(wl->fw); - wl->fw = NULL; - kfree(wl->nvs); - wl->nvs = NULL; - - kfree(wl->rx_descriptor); - wl->rx_descriptor = NULL; - - kfree(wl->fw_status); - kfree(wl->tx_res_if); - - ieee80211_free_hw(wl->hw); - - return 0; -} - - -static struct spi_driver wl1271_spi_driver = { - .driver = { - .name = "wl1271", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - - .probe = wl1271_probe, - .remove = __devexit_p(wl1271_remove), -}; - -static int __init wl1271_init(void) -{ - int ret; - - ret = spi_register_driver(&wl1271_spi_driver); - if (ret < 0) { - wl1271_error("failed to register spi driver: %d", ret); - goto out; - } - -out: - return ret; -} - -static void __exit wl1271_exit(void) -{ - spi_unregister_driver(&wl1271_spi_driver); - - wl1271_notice("unloaded"); -} - -module_init(wl1271_init); -module_exit(wl1271_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Luciano Coelho "); diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c deleted file mode 100644 index 1dc74b0c7736..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_ps.c +++ /dev/null @@ -1,142 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1271_reg.h" -#include "wl1271_ps.h" -#include "wl1271_spi.h" - -#define WL1271_WAKEUP_TIMEOUT 500 - -/* Routines to toggle sleep mode while in ELP */ -void wl1271_ps_elp_sleep(struct wl1271 *wl) -{ - /* - * FIXME: due to a problem in the firmware (causing a firmware - * crash), ELP entry is prevented below. Remove the "true" to - * re-enable ELP entry. - */ - if (true || wl->elp || !wl->psm) - return; - - /* - * Go to ELP unless there is work already pending - pending work - * will immediately wakeup the chipset anyway. - */ - if (!work_pending(&wl->irq_work) && !work_pending(&wl->tx_work)) { - wl1271_debug(DEBUG_PSM, "chip to elp"); - wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_SLEEP); - wl->elp = true; - } -} - -int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake) -{ - DECLARE_COMPLETION_ONSTACK(compl); - unsigned long flags; - int ret; - u32 start_time = jiffies; - bool pending = false; - - if (!wl->elp) - return 0; - - wl1271_debug(DEBUG_PSM, "waking up chip from elp"); - - /* - * The spinlock is required here to synchronize both the work and - * the completion variable in one entity. - */ - spin_lock_irqsave(&wl->wl_lock, flags); - if (work_pending(&wl->irq_work) || chip_awake) - pending = true; - else - wl->elp_compl = &compl; - spin_unlock_irqrestore(&wl->wl_lock, flags); - - wl1271_write32(wl, HW_ACCESS_ELP_CTRL_REG_ADDR, ELPCTRL_WAKE_UP); - - if (!pending) { - ret = wait_for_completion_timeout( - &compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT)); - if (ret == 0) { - wl1271_error("ELP wakeup timeout!"); - ret = -ETIMEDOUT; - goto err; - } else if (ret < 0) { - wl1271_error("ELP wakeup completion error."); - goto err; - } - } - - wl->elp = false; - - wl1271_debug(DEBUG_PSM, "wakeup time: %u ms", - jiffies_to_msecs(jiffies - start_time)); - goto out; - -err: - spin_lock_irqsave(&wl->wl_lock, flags); - wl->elp_compl = NULL; - spin_unlock_irqrestore(&wl->wl_lock, flags); - return ret; - -out: - return 0; -} - -int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode) -{ - int ret; - - switch (mode) { - case STATION_POWER_SAVE_MODE: - wl1271_debug(DEBUG_PSM, "entering psm"); - ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE); - if (ret < 0) - return ret; - - wl1271_ps_elp_sleep(wl); - if (ret < 0) - return ret; - - wl->psm = 1; - break; - case STATION_ACTIVE_MODE: - default: - wl1271_debug(DEBUG_PSM, "leaving psm"); - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - return ret; - - ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE); - if (ret < 0) - return ret; - - wl->psm = 0; - break; - } - - return ret; -} - - diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h deleted file mode 100644 index de2bd3c7dc9c..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_ps.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_PS_H__ -#define __WL1271_PS_H__ - -#include "wl1271.h" -#include "wl1271_acx.h" - -int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode); -void wl1271_ps_elp_sleep(struct wl1271 *wl); -int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake); - - -#endif /* __WL1271_PS_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_reg.h b/drivers/net/wireless/wl12xx/wl1271_reg.h deleted file mode 100644 index f8ed4a4fc691..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_reg.h +++ /dev/null @@ -1,758 +0,0 @@ -/* - * This file is part of wl12xx - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __REG_H__ -#define __REG_H__ - -#include - -#define REGISTERS_BASE 0x00300000 -#define DRPW_BASE 0x00310000 - -#define REGISTERS_DOWN_SIZE 0x00008800 -#define REGISTERS_WORK_SIZE 0x0000b000 - -#define HW_ACCESS_ELP_CTRL_REG_ADDR 0x1FFFC -#define STATUS_MEM_ADDRESS 0x40400 - -/* ELP register commands */ -#define ELPCTRL_WAKE_UP 0x1 -#define ELPCTRL_WAKE_UP_WLAN_READY 0x5 -#define ELPCTRL_SLEEP 0x0 -/* ELP WLAN_READY bit */ -#define ELPCTRL_WLAN_READY 0x2 - -/*=============================================== - Host Software Reset - 32bit RW - ------------------------------------------ - [31:1] Reserved - 0 SOFT_RESET Soft Reset - When this bit is set, - it holds the Wlan hardware in a soft reset state. - This reset disables all MAC and baseband processor - clocks except the CardBus/PCI interface clock. - It also initializes all MAC state machines except - the host interface. It does not reload the - contents of the EEPROM. When this bit is cleared - (not self-clearing), the Wlan hardware - exits the software reset state. -===============================================*/ -#define ACX_REG_SLV_SOFT_RESET (REGISTERS_BASE + 0x0000) - -#define WL1271_SLV_REG_DATA (REGISTERS_BASE + 0x0008) -#define WL1271_SLV_REG_ADATA (REGISTERS_BASE + 0x000c) -#define WL1271_SLV_MEM_DATA (REGISTERS_BASE + 0x0018) -/* - * Interrupt registers. - * 64 bit interrupt sources registers ws ced. - * sme interupts were removed and new ones were added. - * Order was changed. - */ -#define FIQ_MASK (REGISTERS_BASE + 0x0400) -#define FIQ_MASK_L (REGISTERS_BASE + 0x0400) -#define FIQ_MASK_H (REGISTERS_BASE + 0x0404) -#define FIQ_MASK_SET (REGISTERS_BASE + 0x0408) -#define FIQ_MASK_SET_L (REGISTERS_BASE + 0x0408) -#define FIQ_MASK_SET_H (REGISTERS_BASE + 0x040C) -#define FIQ_MASK_CLR (REGISTERS_BASE + 0x0410) -#define FIQ_MASK_CLR_L (REGISTERS_BASE + 0x0410) -#define FIQ_MASK_CLR_H (REGISTERS_BASE + 0x0414) -#define IRQ_MASK (REGISTERS_BASE + 0x0418) -#define IRQ_MASK_L (REGISTERS_BASE + 0x0418) -#define IRQ_MASK_H (REGISTERS_BASE + 0x041C) -#define IRQ_MASK_SET (REGISTERS_BASE + 0x0420) -#define IRQ_MASK_SET_L (REGISTERS_BASE + 0x0420) -#define IRQ_MASK_SET_H (REGISTERS_BASE + 0x0424) -#define IRQ_MASK_CLR (REGISTERS_BASE + 0x0428) -#define IRQ_MASK_CLR_L (REGISTERS_BASE + 0x0428) -#define IRQ_MASK_CLR_H (REGISTERS_BASE + 0x042C) -#define ECPU_MASK (REGISTERS_BASE + 0x0448) -#define FIQ_STS_L (REGISTERS_BASE + 0x044C) -#define FIQ_STS_H (REGISTERS_BASE + 0x0450) -#define IRQ_STS_L (REGISTERS_BASE + 0x0454) -#define IRQ_STS_H (REGISTERS_BASE + 0x0458) -#define INT_STS_ND (REGISTERS_BASE + 0x0464) -#define INT_STS_RAW_L (REGISTERS_BASE + 0x0464) -#define INT_STS_RAW_H (REGISTERS_BASE + 0x0468) -#define INT_STS_CLR (REGISTERS_BASE + 0x04B4) -#define INT_STS_CLR_L (REGISTERS_BASE + 0x04B4) -#define INT_STS_CLR_H (REGISTERS_BASE + 0x04B8) -#define INT_ACK (REGISTERS_BASE + 0x046C) -#define INT_ACK_L (REGISTERS_BASE + 0x046C) -#define INT_ACK_H (REGISTERS_BASE + 0x0470) -#define INT_TRIG (REGISTERS_BASE + 0x0474) -#define INT_TRIG_L (REGISTERS_BASE + 0x0474) -#define INT_TRIG_H (REGISTERS_BASE + 0x0478) -#define HOST_STS_L (REGISTERS_BASE + 0x045C) -#define HOST_STS_H (REGISTERS_BASE + 0x0460) -#define HOST_MASK (REGISTERS_BASE + 0x0430) -#define HOST_MASK_L (REGISTERS_BASE + 0x0430) -#define HOST_MASK_H (REGISTERS_BASE + 0x0434) -#define HOST_MASK_SET (REGISTERS_BASE + 0x0438) -#define HOST_MASK_SET_L (REGISTERS_BASE + 0x0438) -#define HOST_MASK_SET_H (REGISTERS_BASE + 0x043C) -#define HOST_MASK_CLR (REGISTERS_BASE + 0x0440) -#define HOST_MASK_CLR_L (REGISTERS_BASE + 0x0440) -#define HOST_MASK_CLR_H (REGISTERS_BASE + 0x0444) - -#define ACX_REG_INTERRUPT_TRIG (REGISTERS_BASE + 0x0474) -#define ACX_REG_INTERRUPT_TRIG_H (REGISTERS_BASE + 0x0478) - -/* Host Interrupts*/ -#define HINT_MASK (REGISTERS_BASE + 0x0494) -#define HINT_MASK_SET (REGISTERS_BASE + 0x0498) -#define HINT_MASK_CLR (REGISTERS_BASE + 0x049C) -#define HINT_STS_ND_MASKED (REGISTERS_BASE + 0x04A0) -/*1150 spec calls this HINT_STS_RAW*/ -#define HINT_STS_ND (REGISTERS_BASE + 0x04B0) -#define HINT_STS_CLR (REGISTERS_BASE + 0x04A4) -#define HINT_ACK (REGISTERS_BASE + 0x04A8) -#define HINT_TRIG (REGISTERS_BASE + 0x04AC) - -/*============================================= - Host Interrupt Mask Register - 32bit (RW) - ------------------------------------------ - Setting a bit in this register masks the - corresponding interrupt to the host. - 0 - RX0 - Rx first dubble buffer Data Interrupt - 1 - TXD - Tx Data Interrupt - 2 - TXXFR - Tx Transfer Interrupt - 3 - RX1 - Rx second dubble buffer Data Interrupt - 4 - RXXFR - Rx Transfer Interrupt - 5 - EVENT_A - Event Mailbox interrupt - 6 - EVENT_B - Event Mailbox interrupt - 7 - WNONHST - Wake On Host Interrupt - 8 - TRACE_A - Debug Trace interrupt - 9 - TRACE_B - Debug Trace interrupt - 10 - CDCMP - Command Complete Interrupt - 11 - - 12 - - 13 - - 14 - ICOMP - Initialization Complete Interrupt - 16 - SG SE - Soft Gemini - Sense enable interrupt - 17 - SG SD - Soft Gemini - Sense disable interrupt - 18 - - - 19 - - - 20 - - - 21- - - Default: 0x0001 -*==============================================*/ -#define ACX_REG_INTERRUPT_MASK (REGISTERS_BASE + 0x04DC) - -/*============================================= - Host Interrupt Mask Set 16bit, (Write only) - ------------------------------------------ - Setting a bit in this register sets - the corresponding bin in ACX_HINT_MASK register - without effecting the mask - state of other bits (0 = no effect). -==============================================*/ -#define ACX_REG_HINT_MASK_SET (REGISTERS_BASE + 0x04E0) - -/*============================================= - Host Interrupt Mask Clear 16bit,(Write only) - ------------------------------------------ - Setting a bit in this register clears - the corresponding bin in ACX_HINT_MASK register - without effecting the mask - state of other bits (0 = no effect). -=============================================*/ -#define ACX_REG_HINT_MASK_CLR (REGISTERS_BASE + 0x04E4) - -/*============================================= - Host Interrupt Status Nondestructive Read - 16bit,(Read only) - ------------------------------------------ - The host can read this register to determine - which interrupts are active. - Reading this register doesn't - effect its content. -=============================================*/ -#define ACX_REG_INTERRUPT_NO_CLEAR (REGISTERS_BASE + 0x04E8) - -/*============================================= - Host Interrupt Status Clear on Read Register - 16bit,(Read only) - ------------------------------------------ - The host can read this register to determine - which interrupts are active. - Reading this register clears it, - thus making all interrupts inactive. -==============================================*/ -#define ACX_REG_INTERRUPT_CLEAR (REGISTERS_BASE + 0x04F8) - -/*============================================= - Host Interrupt Acknowledge Register - 16bit,(Write only) - ------------------------------------------ - The host can set individual bits in this - register to clear (acknowledge) the corresp. - interrupt status bits in the HINT_STS_CLR and - HINT_STS_ND registers, thus making the - assotiated interrupt inactive. (0-no effect) -==============================================*/ -#define ACX_REG_INTERRUPT_ACK (REGISTERS_BASE + 0x04F0) - -#define RX_DRIVER_DUMMY_WRITE_ADDRESS (REGISTERS_BASE + 0x0534) -#define RX_DRIVER_COUNTER_ADDRESS (REGISTERS_BASE + 0x0538) - -/* Device Configuration registers*/ -#define SOR_CFG (REGISTERS_BASE + 0x0800) - -/* Embedded ARM CPU Control */ - -/*=============================================== - Halt eCPU - 32bit RW - ------------------------------------------ - 0 HALT_ECPU Halt Embedded CPU - This bit is the - compliment of bit 1 (MDATA2) in the SOR_CFG register. - During a hardware reset, this bit holds - the inverse of MDATA2. - When downloading firmware from the host, - set this bit (pull down MDATA2). - The host clears this bit after downloading the firmware into - zero-wait-state SSRAM. - When loading firmware from Flash, clear this bit (pull up MDATA2) - so that the eCPU can run the bootloader code in Flash - HALT_ECPU eCPU State - -------------------- - 1 halt eCPU - 0 enable eCPU - ===============================================*/ -#define ACX_REG_ECPU_CONTROL (REGISTERS_BASE + 0x0804) - -#define HI_CFG (REGISTERS_BASE + 0x0808) - -/*=============================================== - EEPROM Burst Read Start - 32bit RW - ------------------------------------------ - [31:1] Reserved - 0 ACX_EE_START - EEPROM Burst Read Start 0 - Setting this bit starts a burst read from - the external EEPROM. - If this bit is set (after reset) before an EEPROM read/write, - the burst read starts at EEPROM address 0. - Otherwise, it starts at the address - following the address of the previous access. - TheWlan hardware hardware clears this bit automatically. - - Default: 0x00000000 -*================================================*/ -#define ACX_REG_EE_START (REGISTERS_BASE + 0x080C) - -#define OCP_POR_CTR (REGISTERS_BASE + 0x09B4) -#define OCP_DATA_WRITE (REGISTERS_BASE + 0x09B8) -#define OCP_DATA_READ (REGISTERS_BASE + 0x09BC) -#define OCP_CMD (REGISTERS_BASE + 0x09C0) - -#define WL1271_HOST_WR_ACCESS (REGISTERS_BASE + 0x09F8) - -#define CHIP_ID_B (REGISTERS_BASE + 0x5674) - -#define CHIP_ID_1271_PG10 (0x4030101) -#define CHIP_ID_1271_PG20 (0x4030111) - -#define ENABLE (REGISTERS_BASE + 0x5450) - -/* Power Management registers */ -#define ELP_CFG_MODE (REGISTERS_BASE + 0x5804) -#define ELP_CMD (REGISTERS_BASE + 0x5808) -#define PLL_CAL_TIME (REGISTERS_BASE + 0x5810) -#define CLK_REQ_TIME (REGISTERS_BASE + 0x5814) -#define CLK_BUF_TIME (REGISTERS_BASE + 0x5818) - -#define CFG_PLL_SYNC_CNT (REGISTERS_BASE + 0x5820) - -/* Scratch Pad registers*/ -#define SCR_PAD0 (REGISTERS_BASE + 0x5608) -#define SCR_PAD1 (REGISTERS_BASE + 0x560C) -#define SCR_PAD2 (REGISTERS_BASE + 0x5610) -#define SCR_PAD3 (REGISTERS_BASE + 0x5614) -#define SCR_PAD4 (REGISTERS_BASE + 0x5618) -#define SCR_PAD4_SET (REGISTERS_BASE + 0x561C) -#define SCR_PAD4_CLR (REGISTERS_BASE + 0x5620) -#define SCR_PAD5 (REGISTERS_BASE + 0x5624) -#define SCR_PAD5_SET (REGISTERS_BASE + 0x5628) -#define SCR_PAD5_CLR (REGISTERS_BASE + 0x562C) -#define SCR_PAD6 (REGISTERS_BASE + 0x5630) -#define SCR_PAD7 (REGISTERS_BASE + 0x5634) -#define SCR_PAD8 (REGISTERS_BASE + 0x5638) -#define SCR_PAD9 (REGISTERS_BASE + 0x563C) - -/* Spare registers*/ -#define SPARE_A1 (REGISTERS_BASE + 0x0994) -#define SPARE_A2 (REGISTERS_BASE + 0x0998) -#define SPARE_A3 (REGISTERS_BASE + 0x099C) -#define SPARE_A4 (REGISTERS_BASE + 0x09A0) -#define SPARE_A5 (REGISTERS_BASE + 0x09A4) -#define SPARE_A6 (REGISTERS_BASE + 0x09A8) -#define SPARE_A7 (REGISTERS_BASE + 0x09AC) -#define SPARE_A8 (REGISTERS_BASE + 0x09B0) -#define SPARE_B1 (REGISTERS_BASE + 0x5420) -#define SPARE_B2 (REGISTERS_BASE + 0x5424) -#define SPARE_B3 (REGISTERS_BASE + 0x5428) -#define SPARE_B4 (REGISTERS_BASE + 0x542C) -#define SPARE_B5 (REGISTERS_BASE + 0x5430) -#define SPARE_B6 (REGISTERS_BASE + 0x5434) -#define SPARE_B7 (REGISTERS_BASE + 0x5438) -#define SPARE_B8 (REGISTERS_BASE + 0x543C) - -#define PLL_PARAMETERS (REGISTERS_BASE + 0x6040) -#define WU_COUNTER_PAUSE (REGISTERS_BASE + 0x6008) -#define WELP_ARM_COMMAND (REGISTERS_BASE + 0x6100) -#define DRPW_SCRATCH_START (DRPW_BASE + 0x002C) - - -#define ACX_SLV_SOFT_RESET_BIT BIT(1) -#define ACX_REG_EEPROM_START_BIT BIT(1) - -/* Command/Information Mailbox Pointers */ - -/*=============================================== - Command Mailbox Pointer - 32bit RW - ------------------------------------------ - This register holds the start address of - the command mailbox located in the Wlan hardware memory. - The host must read this pointer after a reset to - find the location of the command mailbox. - The Wlan hardware initializes the command mailbox - pointer with the default address of the command mailbox. - The command mailbox pointer is not valid until after - the host receives the Init Complete interrupt from - the Wlan hardware. - ===============================================*/ -#define REG_COMMAND_MAILBOX_PTR (SCR_PAD0) - -/*=============================================== - Information Mailbox Pointer - 32bit RW - ------------------------------------------ - This register holds the start address of - the information mailbox located in the Wlan hardware memory. - The host must read this pointer after a reset to find - the location of the information mailbox. - The Wlan hardware initializes the information mailbox pointer - with the default address of the information mailbox. - The information mailbox pointer is not valid - until after the host receives the Init Complete interrupt from - the Wlan hardware. - ===============================================*/ -#define REG_EVENT_MAILBOX_PTR (SCR_PAD1) - - -/* Misc */ - -#define REG_ENABLE_TX_RX (ENABLE) -/* - * Rx configuration (filter) information element - * --------------------------------------------- - */ -#define REG_RX_CONFIG (RX_CFG) -#define REG_RX_FILTER (RX_FILTER_CFG) - - -#define RX_CFG_ENABLE_PHY_HEADER_PLCP 0x0002 - -/* promiscuous - receives all valid frames */ -#define RX_CFG_PROMISCUOUS 0x0008 - -/* receives frames from any BSSID */ -#define RX_CFG_BSSID 0x0020 - -/* receives frames destined to any MAC address */ -#define RX_CFG_MAC 0x0010 - -#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC 0x0010 -#define RX_CFG_ENABLE_ANY_DEST_MAC 0x0000 -#define RX_CFG_ENABLE_ONLY_MY_BSSID 0x0020 -#define RX_CFG_ENABLE_ANY_BSSID 0x0000 - -/* discards all broadcast frames */ -#define RX_CFG_DISABLE_BCAST 0x0200 - -#define RX_CFG_ENABLE_ONLY_MY_SSID 0x0400 -#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800 -#define RX_CFG_COPY_RX_STATUS 0x2000 -#define RX_CFG_TSF 0x10000 - -#define RX_CONFIG_OPTION_ANY_DST_MY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ - RX_CFG_ENABLE_ONLY_MY_BSSID) - -#define RX_CONFIG_OPTION_MY_DST_ANY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ - | RX_CFG_ENABLE_ANY_BSSID) - -#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \ - RX_CFG_ENABLE_ANY_BSSID) - -#define RX_CONFIG_OPTION_MY_DST_MY_BSS (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\ - | RX_CFG_ENABLE_ONLY_MY_BSSID) - -#define RX_CONFIG_OPTION_FOR_SCAN (RX_CFG_ENABLE_PHY_HEADER_PLCP \ - | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \ - | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF) - -#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC) - -#define RX_CONFIG_OPTION_FOR_JOIN (RX_CFG_ENABLE_ONLY_MY_BSSID | \ - RX_CFG_ENABLE_ONLY_MY_DEST_MAC) - -#define RX_CONFIG_OPTION_FOR_IBSS_JOIN (RX_CFG_ENABLE_ONLY_MY_SSID | \ - RX_CFG_ENABLE_ONLY_MY_DEST_MAC) - -#define RX_FILTER_OPTION_DEF (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ - | CFG_RX_CTL_EN | CFG_RX_BCN_EN\ - | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN) - -#define RX_FILTER_OPTION_FILTER_ALL 0 - -#define RX_FILTER_OPTION_DEF_PRSP_BCN (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\ - | CFG_RX_RCTS_ACK | CFG_RX_BCN_EN) - -#define RX_FILTER_OPTION_JOIN (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\ - | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\ - | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\ - | CFG_RX_PRSP_EN) - - -/*=============================================== - Phy regs - ===============================================*/ -#define ACX_PHY_ADDR_REG SBB_ADDR -#define ACX_PHY_DATA_REG SBB_DATA -#define ACX_PHY_CTRL_REG SBB_CTL -#define ACX_PHY_REG_WR_MASK 0x00000001ul -#define ACX_PHY_REG_RD_MASK 0x00000002ul - - -/*=============================================== - EEPROM Read/Write Request 32bit RW - ------------------------------------------ - 1 EE_READ - EEPROM Read Request 1 - Setting this bit - loads a single byte of data into the EE_DATA - register from the EEPROM location specified in - the EE_ADDR register. - The Wlan hardware hardware clears this bit automatically. - EE_DATA is valid when this bit is cleared. - - 0 EE_WRITE - EEPROM Write Request - Setting this bit - writes a single byte of data from the EE_DATA register into the - EEPROM location specified in the EE_ADDR register. - The Wlan hardware hardware clears this bit automatically. -*===============================================*/ -#define ACX_EE_CTL_REG EE_CTL -#define EE_WRITE 0x00000001ul -#define EE_READ 0x00000002ul - -/*=============================================== - EEPROM Address - 32bit RW - ------------------------------------------ - This register specifies the address - within the EEPROM from/to which to read/write data. - ===============================================*/ -#define ACX_EE_ADDR_REG EE_ADDR - -/*=============================================== - EEPROM Data - 32bit RW - ------------------------------------------ - This register either holds the read 8 bits of - data from the EEPROM or the write data - to be written to the EEPROM. - ===============================================*/ -#define ACX_EE_DATA_REG EE_DATA - -/*=============================================== - EEPROM Base Address - 32bit RW - ------------------------------------------ - This register holds the upper nine bits - [23:15] of the 24-bit Wlan hardware memory - address for burst reads from EEPROM accesses. - The EEPROM provides the lower 15 bits of this address. - The MSB of the address from the EEPROM is ignored. - ===============================================*/ -#define ACX_EE_CFG EE_CFG - -/*=============================================== - GPIO Output Values -32bit, RW - ------------------------------------------ - [31:16] Reserved - [15: 0] Specify the output values (at the output driver inputs) for - GPIO[15:0], respectively. - ===============================================*/ -#define ACX_GPIO_OUT_REG GPIO_OUT -#define ACX_MAX_GPIO_LINES 15 - -/*=============================================== - Contention window -32bit, RW - ------------------------------------------ - [31:26] Reserved - [25:16] Max (0x3ff) - [15:07] Reserved - [06:00] Current contention window value - default is 0x1F - ===============================================*/ -#define ACX_CONT_WIND_CFG_REG CONT_WIND_CFG -#define ACX_CONT_WIND_MIN_MASK 0x0000007f -#define ACX_CONT_WIND_MAX 0x03ff0000 - -/* - * Indirect slave register/memory registers - * ---------------------------------------- - */ -#define HW_SLAVE_REG_ADDR_REG 0x00000004 -#define HW_SLAVE_REG_DATA_REG 0x00000008 -#define HW_SLAVE_REG_CTRL_REG 0x0000000c - -#define SLAVE_AUTO_INC 0x00010000 -#define SLAVE_NO_AUTO_INC 0x00000000 -#define SLAVE_HOST_LITTLE_ENDIAN 0x00000000 - -#define HW_SLAVE_MEM_ADDR_REG SLV_MEM_ADDR -#define HW_SLAVE_MEM_DATA_REG SLV_MEM_DATA -#define HW_SLAVE_MEM_CTRL_REG SLV_MEM_CTL -#define HW_SLAVE_MEM_ENDIAN_REG SLV_END_CTL - -#define HW_FUNC_EVENT_INT_EN 0x8000 -#define HW_FUNC_EVENT_MASK_REG 0x00000034 - -#define ACX_MAC_TIMESTAMP_REG (MAC_TIMESTAMP) - -/*=============================================== - HI_CFG Interface Configuration Register Values - ------------------------------------------ - ===============================================*/ -#define HI_CFG_UART_ENABLE 0x00000004 -#define HI_CFG_RST232_ENABLE 0x00000008 -#define HI_CFG_CLOCK_REQ_SELECT 0x00000010 -#define HI_CFG_HOST_INT_ENABLE 0x00000020 -#define HI_CFG_VLYNQ_OUTPUT_ENABLE 0x00000040 -#define HI_CFG_HOST_INT_ACTIVE_LOW 0x00000080 -#define HI_CFG_UART_TX_OUT_GPIO_15 0x00000100 -#define HI_CFG_UART_TX_OUT_GPIO_14 0x00000200 -#define HI_CFG_UART_TX_OUT_GPIO_7 0x00000400 - -/* - * NOTE: USE_ACTIVE_HIGH compilation flag should be defined in makefile - * for platforms using active high interrupt level - */ -#ifdef USE_ACTIVE_HIGH -#define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) -#else -#define HI_CFG_DEF_VAL \ - (HI_CFG_UART_ENABLE | \ - HI_CFG_RST232_ENABLE | \ - HI_CFG_CLOCK_REQ_SELECT | \ - HI_CFG_HOST_INT_ENABLE) - -#endif - -#define REF_FREQ_19_2 0 -#define REF_FREQ_26_0 1 -#define REF_FREQ_38_4 2 -#define REF_FREQ_40_0 3 -#define REF_FREQ_33_6 4 -#define REF_FREQ_NUM 5 - -#define LUT_PARAM_INTEGER_DIVIDER 0 -#define LUT_PARAM_FRACTIONAL_DIVIDER 1 -#define LUT_PARAM_ATTN_BB 2 -#define LUT_PARAM_ALPHA_BB 3 -#define LUT_PARAM_STOP_TIME_BB 4 -#define LUT_PARAM_BB_PLL_LOOP_FILTER 5 -#define LUT_PARAM_NUM 6 - -#define ACX_EEPROMLESS_IND_REG (SCR_PAD4) -#define USE_EEPROM 0 -#define SOFT_RESET_MAX_TIME 1000000 -#define SOFT_RESET_STALL_TIME 1000 -#define NVS_DATA_BUNDARY_ALIGNMENT 4 - - -/* Firmware image load chunk size */ -#define CHUNK_SIZE 512 - -/* Firmware image header size */ -#define FW_HDR_SIZE 8 - -#define ECPU_CONTROL_HALT 0x00000101 - - -/****************************************************************************** - - CHANNELS, BAND & REG DOMAINS definitions - -******************************************************************************/ - - -enum { - RADIO_BAND_2_4GHZ = 0, /* 2.4 Ghz band */ - RADIO_BAND_5GHZ = 1, /* 5 Ghz band */ - RADIO_BAND_JAPAN_4_9_GHZ = 2, - DEFAULT_BAND = RADIO_BAND_2_4GHZ, - INVALID_BAND = 0xFE, - MAX_RADIO_BANDS = 0xFF -}; - -enum { - NO_RATE = 0, - RATE_1MBPS = 0x0A, - RATE_2MBPS = 0x14, - RATE_5_5MBPS = 0x37, - RATE_6MBPS = 0x0B, - RATE_9MBPS = 0x0F, - RATE_11MBPS = 0x6E, - RATE_12MBPS = 0x0A, - RATE_18MBPS = 0x0E, - RATE_22MBPS = 0xDC, - RATE_24MBPS = 0x09, - RATE_36MBPS = 0x0D, - RATE_48MBPS = 0x08, - RATE_54MBPS = 0x0C -}; - -enum { - RATE_INDEX_1MBPS = 0, - RATE_INDEX_2MBPS = 1, - RATE_INDEX_5_5MBPS = 2, - RATE_INDEX_6MBPS = 3, - RATE_INDEX_9MBPS = 4, - RATE_INDEX_11MBPS = 5, - RATE_INDEX_12MBPS = 6, - RATE_INDEX_18MBPS = 7, - RATE_INDEX_22MBPS = 8, - RATE_INDEX_24MBPS = 9, - RATE_INDEX_36MBPS = 10, - RATE_INDEX_48MBPS = 11, - RATE_INDEX_54MBPS = 12, - RATE_INDEX_MAX = RATE_INDEX_54MBPS, - MAX_RATE_INDEX, - INVALID_RATE_INDEX = MAX_RATE_INDEX, - RATE_INDEX_ENUM_MAX_SIZE = 0x7FFFFFFF -}; - -enum { - RATE_MASK_1MBPS = 0x1, - RATE_MASK_2MBPS = 0x2, - RATE_MASK_5_5MBPS = 0x4, - RATE_MASK_11MBPS = 0x20, -}; - -#define SHORT_PREAMBLE_BIT BIT(0) /* CCK or Barker depending on the rate */ -#define OFDM_RATE_BIT BIT(6) -#define PBCC_RATE_BIT BIT(7) - -enum { - CCK_LONG = 0, - CCK_SHORT = SHORT_PREAMBLE_BIT, - PBCC_LONG = PBCC_RATE_BIT, - PBCC_SHORT = PBCC_RATE_BIT | SHORT_PREAMBLE_BIT, - OFDM = OFDM_RATE_BIT -}; - -/****************************************************************************** - -Transmit-Descriptor RATE-SET field definitions... - -Define a new "Rate-Set" for TX path that incorporates the -Rate & Modulation info into a single 16-bit field. - -TxdRateSet_t: -b15 - Indicates Preamble type (1=SHORT, 0=LONG). - Notes: - Must be LONG (0) for 1Mbps rate. - Does not apply (set to 0) for RevG-OFDM rates. -b14 - Indicates PBCC encoding (1=PBCC, 0=not). - Notes: - Does not apply (set to 0) for rates 1 and 2 Mbps. - Does not apply (set to 0) for RevG-OFDM rates. -b13 - Unused (set to 0). -b12-b0 - Supported Rate indicator bits as defined below. - -******************************************************************************/ - - -#define TNETW1251_CHIP_ID_PG1_0 0x07010101 -#define TNETW1251_CHIP_ID_PG1_1 0x07020101 -#define TNETW1251_CHIP_ID_PG1_2 0x07030101 - -/************************************************************************* - - Interrupt Trigger Register (Host -> WiLink) - -**************************************************************************/ - -/* Hardware to Embedded CPU Interrupts - first 32-bit register set */ - -/* - * Host Command Interrupt. Setting this bit masks - * the interrupt that the host issues to inform - * the FW that it has sent a command - * to the Wlan hardware Command Mailbox. - */ -#define INTR_TRIG_CMD BIT(0) - -/* - * Host Event Acknowlegde Interrupt. The host - * sets this bit to acknowledge that it received - * the unsolicited information from the event - * mailbox. - */ -#define INTR_TRIG_EVENT_ACK BIT(1) - -/* - * The host sets this bit to inform the Wlan - * FW that a TX packet is in the XFER - * Buffer #0. - */ -#define INTR_TRIG_TX_PROC0 BIT(2) - -/* - * The host sets this bit to inform the FW - * that it read a packet from RX XFER - * Buffer #0. - */ -#define INTR_TRIG_RX_PROC0 BIT(3) - -#define INTR_TRIG_DEBUG_ACK BIT(4) - -#define INTR_TRIG_STATE_CHANGED BIT(5) - - -/* Hardware to Embedded CPU Interrupts - second 32-bit register set */ - -/* - * The host sets this bit to inform the FW - * that it read a packet from RX XFER - * Buffer #1. - */ -#define INTR_TRIG_RX_PROC1 BIT(17) - -/* - * The host sets this bit to inform the Wlan - * hardware that a TX packet is in the XFER - * Buffer #1. - */ -#define INTR_TRIG_TX_PROC1 BIT(18) - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.c b/drivers/net/wireless/wl12xx/wl1271_rx.c deleted file mode 100644 index ad8b6904c5eb..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_rx.c +++ /dev/null @@ -1,200 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include "wl1271.h" -#include "wl1271_acx.h" -#include "wl1271_reg.h" -#include "wl1271_rx.h" -#include "wl1271_spi.h" - -static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status, - u32 drv_rx_counter) -{ - return status->rx_pkt_descs[drv_rx_counter] & RX_MEM_BLOCK_MASK; -} - -static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status, - u32 drv_rx_counter) -{ - return (status->rx_pkt_descs[drv_rx_counter] & RX_BUF_SIZE_MASK) >> - RX_BUF_SIZE_SHIFT_DIV; -} - -/* The values of this table must match the wl1271_rates[] array */ -static u8 wl1271_rx_rate_to_idx[] = { - /* MCS rates are used only with 11n */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS7 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS6 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS5 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS4 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS3 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS2 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS1 */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_MCS0 */ - - 11, /* WL1271_RATE_54 */ - 10, /* WL1271_RATE_48 */ - 9, /* WL1271_RATE_36 */ - 8, /* WL1271_RATE_24 */ - - /* TI-specific rate */ - WL1271_RX_RATE_UNSUPPORTED, /* WL1271_RATE_22 */ - - 7, /* WL1271_RATE_18 */ - 6, /* WL1271_RATE_12 */ - 3, /* WL1271_RATE_11 */ - 5, /* WL1271_RATE_9 */ - 4, /* WL1271_RATE_6 */ - 2, /* WL1271_RATE_5_5 */ - 1, /* WL1271_RATE_2 */ - 0 /* WL1271_RATE_1 */ -}; - -static void wl1271_rx_status(struct wl1271 *wl, - struct wl1271_rx_descriptor *desc, - struct ieee80211_rx_status *status, - u8 beacon) -{ - memset(status, 0, sizeof(struct ieee80211_rx_status)); - - if ((desc->flags & WL1271_RX_DESC_BAND_MASK) == WL1271_RX_DESC_BAND_BG) - status->band = IEEE80211_BAND_2GHZ; - else - wl1271_warning("unsupported band 0x%x", - desc->flags & WL1271_RX_DESC_BAND_MASK); - - /* - * FIXME: Add mactime handling. For IBSS (ad-hoc) we need to get the - * timestamp from the beacon (acx_tsf_info). In BSS mode (infra) we - * only need the mactime for monitor mode. For now the mactime is - * not valid, so RX_FLAG_TSFT should not be set - */ - status->signal = desc->rssi; - - /* FIXME: Should this be optimized? */ - status->qual = (desc->rssi - WL1271_RX_MIN_RSSI) * 100 / - (WL1271_RX_MAX_RSSI - WL1271_RX_MIN_RSSI); - status->qual = min(status->qual, 100); - status->qual = max(status->qual, 0); - - /* - * FIXME: In wl1251, the SNR should be divided by two. In wl1271 we - * need to divide by two for now, but TI has been discussing about - * changing it. This needs to be rechecked. - */ - status->noise = desc->rssi - (desc->snr >> 1); - - status->freq = ieee80211_channel_to_frequency(desc->channel); - - if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) { - status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED; - - if (likely(!(desc->flags & WL1271_RX_DESC_DECRYPT_FAIL))) - status->flag |= RX_FLAG_DECRYPTED; - - if (unlikely(desc->flags & WL1271_RX_DESC_MIC_FAIL)) - status->flag |= RX_FLAG_MMIC_ERROR; - } - - status->rate_idx = wl1271_rx_rate_to_idx[desc->rate]; - - if (status->rate_idx == WL1271_RX_RATE_UNSUPPORTED) - wl1271_warning("unsupported rate"); -} - -static void wl1271_rx_handle_data(struct wl1271 *wl, u32 length) -{ - struct ieee80211_rx_status rx_status; - struct wl1271_rx_descriptor *desc; - struct sk_buff *skb; - u16 *fc; - u8 *buf; - u8 beacon = 0; - - skb = dev_alloc_skb(length); - if (!skb) { - wl1271_error("Couldn't allocate RX frame"); - return; - } - - buf = skb_put(skb, length); - wl1271_spi_reg_read(wl, WL1271_SLV_MEM_DATA, buf, length, true); - - /* the data read starts with the descriptor */ - desc = (struct wl1271_rx_descriptor *) buf; - - /* now we pull the descriptor out of the buffer */ - skb_pull(skb, sizeof(*desc)); - - fc = (u16 *)skb->data; - if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON) - beacon = 1; - - wl1271_rx_status(wl, desc, &rx_status, beacon); - - wl1271_debug(DEBUG_RX, "rx skb 0x%p: %d B %s", skb, skb->len, - beacon ? "beacon" : ""); - - memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); - ieee80211_rx(wl->hw, skb); -} - -void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status) -{ - struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map; - u32 buf_size; - u32 fw_rx_counter = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK; - u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; - u32 mem_block; - - while (drv_rx_counter != fw_rx_counter) { - mem_block = wl1271_rx_get_mem_block(status, drv_rx_counter); - buf_size = wl1271_rx_get_buf_size(status, drv_rx_counter); - - if (buf_size == 0) { - wl1271_warning("received empty data"); - break; - } - - wl->rx_mem_pool_addr.addr = - (mem_block << 8) + wl_mem_map->packet_memory_pool_start; - wl->rx_mem_pool_addr.addr_extra = - wl->rx_mem_pool_addr.addr + 4; - - /* Choose the block we want to read */ - wl1271_spi_reg_write(wl, WL1271_SLV_REG_DATA, - &wl->rx_mem_pool_addr, - sizeof(wl->rx_mem_pool_addr), false); - - wl1271_rx_handle_data(wl, buf_size); - - wl->rx_counter++; - drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK; - } - - wl1271_reg_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter); - - /* This is a workaround for some problems in the chip */ - wl1271_reg_write32(wl, RX_DRIVER_DUMMY_WRITE_ADDRESS, 0x1); - -} diff --git a/drivers/net/wireless/wl12xx/wl1271_rx.h b/drivers/net/wireless/wl12xx/wl1271_rx.h deleted file mode 100644 index d1ca60e43a25..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_rx.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_RX_H__ -#define __WL1271_RX_H__ - -#include - -#define WL1271_RX_MAX_RSSI -30 -#define WL1271_RX_MIN_RSSI -95 - -#define WL1271_RX_ALIGN_TO 4 -#define WL1271_RX_ALIGN(len) (((len) + WL1271_RX_ALIGN_TO - 1) & \ - ~(WL1271_RX_ALIGN_TO - 1)) - -#define SHORT_PREAMBLE_BIT BIT(0) -#define OFDM_RATE_BIT BIT(6) -#define PBCC_RATE_BIT BIT(7) - -#define PLCP_HEADER_LENGTH 8 -#define RX_DESC_PACKETID_SHIFT 11 -#define RX_MAX_PACKET_ID 3 - -#define NUM_RX_PKT_DESC_MOD_MASK 7 -#define WL1271_RX_RATE_UNSUPPORTED 0xFF - -#define RX_DESC_VALID_FCS 0x0001 -#define RX_DESC_MATCH_RXADDR1 0x0002 -#define RX_DESC_MCAST 0x0004 -#define RX_DESC_STAINTIM 0x0008 -#define RX_DESC_VIRTUAL_BM 0x0010 -#define RX_DESC_BCAST 0x0020 -#define RX_DESC_MATCH_SSID 0x0040 -#define RX_DESC_MATCH_BSSID 0x0080 -#define RX_DESC_ENCRYPTION_MASK 0x0300 -#define RX_DESC_MEASURMENT 0x0400 -#define RX_DESC_SEQNUM_MASK 0x1800 -#define RX_DESC_MIC_FAIL 0x2000 -#define RX_DESC_DECRYPT_FAIL 0x4000 - -/* - * RX Descriptor flags: - * - * Bits 0-1 - band - * Bit 2 - STBC - * Bit 3 - A-MPDU - * Bit 4 - HT - * Bits 5-7 - encryption - */ -#define WL1271_RX_DESC_BAND_MASK 0x03 -#define WL1271_RX_DESC_ENCRYPT_MASK 0xE0 - -#define WL1271_RX_DESC_BAND_BG 0x00 -#define WL1271_RX_DESC_BAND_J 0x01 -#define WL1271_RX_DESC_BAND_A 0x02 - -#define WL1271_RX_DESC_STBC BIT(2) -#define WL1271_RX_DESC_A_MPDU BIT(3) -#define WL1271_RX_DESC_HT BIT(4) - -#define WL1271_RX_DESC_ENCRYPT_WEP 0x20 -#define WL1271_RX_DESC_ENCRYPT_TKIP 0x40 -#define WL1271_RX_DESC_ENCRYPT_AES 0x60 -#define WL1271_RX_DESC_ENCRYPT_GEM 0x80 - -/* - * RX Descriptor status - * - * Bits 0-2 - status - * Bits 3-7 - reserved - */ -#define WL1271_RX_DESC_STATUS_MASK 0x07 - -#define WL1271_RX_DESC_SUCCESS 0x00 -#define WL1271_RX_DESC_DECRYPT_FAIL 0x01 -#define WL1271_RX_DESC_MIC_FAIL 0x02 -#define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03 - -#define RX_MEM_BLOCK_MASK 0xFF -#define RX_BUF_SIZE_MASK 0xFFF00 -#define RX_BUF_SIZE_SHIFT_DIV 6 - -struct wl1271_rx_descriptor { - u16 length; - u8 status; - u8 flags; - u8 rate; - u8 channel; - s8 rssi; - u8 snr; - u32 timestamp; - u8 packet_class; - u8 process_id; - u8 pad_len; - u8 reserved; -} __attribute__ ((packed)); - -void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c deleted file mode 100644 index 4a12880c16a8..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_spi.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include - -#include "wl1271.h" -#include "wl12xx_80211.h" -#include "wl1271_spi.h" - -static int wl1271_translate_reg_addr(struct wl1271 *wl, int addr) -{ - return addr - wl->physical_reg_addr + wl->virtual_reg_addr; -} - -static int wl1271_translate_mem_addr(struct wl1271 *wl, int addr) -{ - return addr - wl->physical_mem_addr + wl->virtual_mem_addr; -} - - -void wl1271_spi_reset(struct wl1271 *wl) -{ - u8 *cmd; - struct spi_transfer t; - struct spi_message m; - - cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); - if (!cmd) { - wl1271_error("could not allocate cmd for spi reset"); - return; - } - - memset(&t, 0, sizeof(t)); - spi_message_init(&m); - - memset(cmd, 0xff, WSPI_INIT_CMD_LEN); - - t.tx_buf = cmd; - t.len = WSPI_INIT_CMD_LEN; - spi_message_add_tail(&t, &m); - - spi_sync(wl->spi, &m); - - wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN); -} - -void wl1271_spi_init(struct wl1271 *wl) -{ - u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd; - struct spi_transfer t; - struct spi_message m; - - cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL); - if (!cmd) { - wl1271_error("could not allocate cmd for spi init"); - return; - } - - memset(crc, 0, sizeof(crc)); - memset(&t, 0, sizeof(t)); - spi_message_init(&m); - - /* - * Set WSPI_INIT_COMMAND - * the data is being send from the MSB to LSB - */ - cmd[2] = 0xff; - cmd[3] = 0xff; - cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX; - cmd[0] = 0; - cmd[7] = 0; - cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3; - cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN; - - if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0) - cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY; - else - cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY; - - cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS - | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS; - - crc[0] = cmd[1]; - crc[1] = cmd[0]; - crc[2] = cmd[7]; - crc[3] = cmd[6]; - crc[4] = cmd[5]; - - cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1; - cmd[4] |= WSPI_INIT_CMD_END; - - t.tx_buf = cmd; - t.len = WSPI_INIT_CMD_LEN; - spi_message_add_tail(&t, &m); - - spi_sync(wl->spi, &m); - - wl1271_dump(DEBUG_SPI, "spi init -> ", cmd, WSPI_INIT_CMD_LEN); -} - -/* Set the SPI partitions to access the chip addresses - * - * There are two VIRTUAL (SPI) partitions (the memory partition and the - * registers partition), which are mapped to two different areas of the - * PHYSICAL (hardware) memory. This function also makes other checks to - * ensure that the partitions are not overlapping. In the diagram below, the - * memory partition comes before the register partition, but the opposite is - * also supported. - * - * PHYSICAL address - * space - * - * | | - * ...+----+--> mem_start - * VIRTUAL address ... | | - * space ... | | [PART_0] - * ... | | - * 0x00000000 <--+----+... ...+----+--> mem_start + mem_size - * | | ... | | - * |MEM | ... | | - * | | ... | | - * part_size <--+----+... | | {unused area) - * | | ... | | - * |REG | ... | | - * part_size | | ... | | - * + <--+----+... ...+----+--> reg_start - * reg_size ... | | - * ... | | [PART_1] - * ... | | - * ...+----+--> reg_start + reg_size - * | | - * - */ -int wl1271_set_partition(struct wl1271 *wl, - u32 mem_start, u32 mem_size, - u32 reg_start, u32 reg_size) -{ - struct wl1271_partition *partition; - struct spi_transfer t; - struct spi_message m; - size_t len, cmd_len; - u32 *cmd; - int addr; - - cmd_len = sizeof(u32) + 2 * sizeof(struct wl1271_partition); - cmd = kzalloc(cmd_len, GFP_KERNEL); - if (!cmd) - return -ENOMEM; - - spi_message_init(&m); - memset(&t, 0, sizeof(t)); - - partition = (struct wl1271_partition *) (cmd + 1); - addr = HW_ACCESS_PART0_SIZE_ADDR; - len = 2 * sizeof(struct wl1271_partition); - - *cmd |= WSPI_CMD_WRITE; - *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; - *cmd |= addr & WSPI_CMD_BYTE_ADDR; - - wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - - /* Make sure that the two partitions together don't exceed the - * address range */ - if ((mem_size + reg_size) > HW_ACCESS_MEMORY_MAX_RANGE) { - wl1271_debug(DEBUG_SPI, "Total size exceeds maximum virtual" - " address range. Truncating partition[0]."); - mem_size = HW_ACCESS_MEMORY_MAX_RANGE - reg_size; - wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - } - - if ((mem_start < reg_start) && - ((mem_start + mem_size) > reg_start)) { - /* Guarantee that the memory partition doesn't overlap the - * registers partition */ - wl1271_debug(DEBUG_SPI, "End of partition[0] is " - "overlapping partition[1]. Adjusted."); - mem_size = reg_start - mem_start; - wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - } else if ((reg_start < mem_start) && - ((reg_start + reg_size) > mem_start)) { - /* Guarantee that the register partition doesn't overlap the - * memory partition */ - wl1271_debug(DEBUG_SPI, "End of partition[1] is" - " overlapping partition[0]. Adjusted."); - reg_size = mem_start - reg_start; - wl1271_debug(DEBUG_SPI, "mem_start %08X mem_size %08X", - mem_start, mem_size); - wl1271_debug(DEBUG_SPI, "reg_start %08X reg_size %08X", - reg_start, reg_size); - } - - partition[0].start = mem_start; - partition[0].size = mem_size; - partition[1].start = reg_start; - partition[1].size = reg_size; - - wl->physical_mem_addr = mem_start; - wl->physical_reg_addr = reg_start; - - wl->virtual_mem_addr = 0; - wl->virtual_reg_addr = mem_size; - - t.tx_buf = cmd; - t.len = cmd_len; - spi_message_add_tail(&t, &m); - - spi_sync(wl->spi, &m); - - kfree(cmd); - - return 0; -} - -void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) -{ - struct spi_transfer t[3]; - struct spi_message m; - u8 *busy_buf; - u32 *cmd; - - cmd = &wl->buffer_cmd; - busy_buf = wl->buffer_busyword; - - *cmd = 0; - *cmd |= WSPI_CMD_READ; - *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; - *cmd |= addr & WSPI_CMD_BYTE_ADDR; - - if (fixed) - *cmd |= WSPI_CMD_FIXED; - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = cmd; - t[0].len = 4; - spi_message_add_tail(&t[0], &m); - - /* Busy and non busy words read */ - t[1].rx_buf = busy_buf; - t[1].len = WL1271_BUSY_WORD_LEN; - spi_message_add_tail(&t[1], &m); - - t[2].rx_buf = buf; - t[2].len = len; - spi_message_add_tail(&t[2], &m); - - spi_sync(wl->spi, &m); - - /* FIXME: check busy words */ - - wl1271_dump(DEBUG_SPI, "spi_read cmd -> ", cmd, sizeof(*cmd)); - wl1271_dump(DEBUG_SPI, "spi_read buf <- ", buf, len); -} - -void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed) -{ - struct spi_transfer t[2]; - struct spi_message m; - u32 *cmd; - - cmd = &wl->buffer_cmd; - - *cmd = 0; - *cmd |= WSPI_CMD_WRITE; - *cmd |= (len << WSPI_CMD_BYTE_LENGTH_OFFSET) & WSPI_CMD_BYTE_LENGTH; - *cmd |= addr & WSPI_CMD_BYTE_ADDR; - - if (fixed) - *cmd |= WSPI_CMD_FIXED; - - spi_message_init(&m); - memset(t, 0, sizeof(t)); - - t[0].tx_buf = cmd; - t[0].len = sizeof(*cmd); - spi_message_add_tail(&t[0], &m); - - t[1].tx_buf = buf; - t[1].len = len; - spi_message_add_tail(&t[1], &m); - - spi_sync(wl->spi, &m); - - wl1271_dump(DEBUG_SPI, "spi_write cmd -> ", cmd, sizeof(*cmd)); - wl1271_dump(DEBUG_SPI, "spi_write buf -> ", buf, len); -} - -void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, - size_t len) -{ - int physical; - - physical = wl1271_translate_mem_addr(wl, addr); - - wl1271_spi_read(wl, physical, buf, len, false); -} - -void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, - size_t len) -{ - int physical; - - physical = wl1271_translate_mem_addr(wl, addr); - - wl1271_spi_write(wl, physical, buf, len, false); -} - -void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) -{ - int physical; - - physical = wl1271_translate_reg_addr(wl, addr); - - wl1271_spi_read(wl, physical, buf, len, fixed); -} - -void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed) -{ - int physical; - - physical = wl1271_translate_reg_addr(wl, addr); - - wl1271_spi_write(wl, physical, buf, len, fixed); -} - -u32 wl1271_mem_read32(struct wl1271 *wl, int addr) -{ - return wl1271_read32(wl, wl1271_translate_mem_addr(wl, addr)); -} - -void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val) -{ - wl1271_write32(wl, wl1271_translate_mem_addr(wl, addr), val); -} - -u32 wl1271_reg_read32(struct wl1271 *wl, int addr) -{ - return wl1271_read32(wl, wl1271_translate_reg_addr(wl, addr)); -} - -void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val) -{ - wl1271_write32(wl, wl1271_translate_reg_addr(wl, addr), val); -} diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.h b/drivers/net/wireless/wl12xx/wl1271_spi.h deleted file mode 100644 index 2c9968458646..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_spi.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2008-2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_SPI_H__ -#define __WL1271_SPI_H__ - -#include "wl1271_reg.h" - -#define HW_ACCESS_MEMORY_MAX_RANGE 0x1FFC0 - -#define HW_ACCESS_PART0_SIZE_ADDR 0x1FFC0 -#define HW_ACCESS_PART0_START_ADDR 0x1FFC4 -#define HW_ACCESS_PART1_SIZE_ADDR 0x1FFC8 -#define HW_ACCESS_PART1_START_ADDR 0x1FFCC - -#define HW_ACCESS_REGISTER_SIZE 4 - -#define HW_ACCESS_PRAM_MAX_RANGE 0x3c000 - -#define WSPI_CMD_READ 0x40000000 -#define WSPI_CMD_WRITE 0x00000000 -#define WSPI_CMD_FIXED 0x20000000 -#define WSPI_CMD_BYTE_LENGTH 0x1FFE0000 -#define WSPI_CMD_BYTE_LENGTH_OFFSET 17 -#define WSPI_CMD_BYTE_ADDR 0x0001FFFF - -#define WSPI_INIT_CMD_CRC_LEN 5 - -#define WSPI_INIT_CMD_START 0x00 -#define WSPI_INIT_CMD_TX 0x40 -/* the extra bypass bit is sampled by the TNET as '1' */ -#define WSPI_INIT_CMD_BYPASS_BIT 0x80 -#define WSPI_INIT_CMD_FIXEDBUSY_LEN 0x07 -#define WSPI_INIT_CMD_EN_FIXEDBUSY 0x80 -#define WSPI_INIT_CMD_DIS_FIXEDBUSY 0x00 -#define WSPI_INIT_CMD_IOD 0x40 -#define WSPI_INIT_CMD_IP 0x20 -#define WSPI_INIT_CMD_CS 0x10 -#define WSPI_INIT_CMD_WS 0x08 -#define WSPI_INIT_CMD_WSPI 0x01 -#define WSPI_INIT_CMD_END 0x01 - -#define WSPI_INIT_CMD_LEN 8 - -#define HW_ACCESS_WSPI_FIXED_BUSY_LEN \ - ((WL1271_BUSY_WORD_LEN - 4) / sizeof(u32)) -#define HW_ACCESS_WSPI_INIT_CMD_MASK 0 - - -/* Raw target IO, address is not translated */ -void wl1271_spi_write(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed); -void wl1271_spi_read(struct wl1271 *wl, int addr, void *buf, - size_t len, bool fixed); - -/* Memory target IO, address is tranlated to partition 0 */ -void wl1271_spi_mem_read(struct wl1271 *wl, int addr, void *buf, size_t len); -void wl1271_spi_mem_write(struct wl1271 *wl, int addr, void *buf, size_t len); -u32 wl1271_mem_read32(struct wl1271 *wl, int addr); -void wl1271_mem_write32(struct wl1271 *wl, int addr, u32 val); - -/* Registers IO */ -void wl1271_spi_reg_read(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed); -void wl1271_spi_reg_write(struct wl1271 *wl, int addr, void *buf, size_t len, - bool fixed); -u32 wl1271_reg_read32(struct wl1271 *wl, int addr); -void wl1271_reg_write32(struct wl1271 *wl, int addr, u32 val); - -/* INIT and RESET words */ -void wl1271_spi_reset(struct wl1271 *wl); -void wl1271_spi_init(struct wl1271 *wl); -int wl1271_set_partition(struct wl1271 *wl, - u32 part_start, u32 part_size, - u32 reg_start, u32 reg_size); - -static inline u32 wl1271_read32(struct wl1271 *wl, int addr) -{ - wl1271_spi_read(wl, addr, &wl->buffer_32, - sizeof(wl->buffer_32), false); - - return wl->buffer_32; -} - -static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val) -{ - wl->buffer_32 = val; - wl1271_spi_write(wl, addr, &wl->buffer_32, - sizeof(wl->buffer_32), false); -} - -#endif /* __WL1271_SPI_H__ */ diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c deleted file mode 100644 index ff221258b941..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_tx.c +++ /dev/null @@ -1,378 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include - -#include "wl1271.h" -#include "wl1271_spi.h" -#include "wl1271_reg.h" -#include "wl1271_ps.h" -#include "wl1271_tx.h" - -static int wl1271_tx_id(struct wl1271 *wl, struct sk_buff *skb) -{ - int i; - - for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) - if (wl->tx_frames[i] == NULL) { - wl->tx_frames[i] = skb; - return i; - } - - return -EBUSY; -} - -static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra) -{ - struct wl1271_tx_hw_descr *desc; - u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; - u32 total_blocks, excluded; - int id, ret = -EBUSY; - - /* allocate free identifier for the packet */ - id = wl1271_tx_id(wl, skb); - if (id < 0) - return id; - - /* approximate the number of blocks required for this packet - in the firmware */ - /* FIXME: try to figure out what is done here and make it cleaner */ - total_blocks = (skb->len) >> TX_HW_BLOCK_SHIFT_DIV; - excluded = (total_blocks << 2) + (skb->len & 0xff) + 34; - total_blocks += (excluded > 252) ? 2 : 1; - total_blocks += TX_HW_BLOCK_SPARE; - - if (total_blocks <= wl->tx_blocks_available) { - desc = (struct wl1271_tx_hw_descr *)skb_push( - skb, total_len - skb->len); - - desc->extra_mem_blocks = TX_HW_BLOCK_SPARE; - desc->total_mem_blocks = total_blocks; - desc->id = id; - - wl->tx_blocks_available -= total_blocks; - - ret = 0; - - wl1271_debug(DEBUG_TX, - "tx_allocate: size: %d, blocks: %d, id: %d", - total_len, total_blocks, id); - } else - wl->tx_frames[id] = NULL; - - return ret; -} - -static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, - u32 extra, struct ieee80211_tx_info *control) -{ - struct wl1271_tx_hw_descr *desc; - int pad; - - desc = (struct wl1271_tx_hw_descr *) skb->data; - - /* configure packet life time */ - desc->start_time = jiffies_to_usecs(jiffies) - wl->time_offset; - desc->life_time = TX_HW_MGMT_PKT_LIFETIME_TU; - - /* configure the tx attributes */ - desc->tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER; - /* FIXME: do we know the packet priority? can we identify mgmt - packets, and use max prio for them at least? */ - desc->tid = 0; - desc->aid = TX_HW_DEFAULT_AID; - desc->reserved = 0; - - /* align the length (and store in terms of words) */ - pad = WL1271_TX_ALIGN(skb->len); - desc->length = pad >> 2; - - /* calculate number of padding bytes */ - pad = pad - skb->len; - desc->tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD; - - wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad); - return 0; -} - -static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb, - struct ieee80211_tx_info *control) -{ - - struct wl1271_tx_hw_descr *desc; - int len; - - /* FIXME: This is a workaround for getting non-aligned packets. - This happens at least with EAPOL packets from the user space. - Our DMA requires packets to be aligned on a 4-byte boundary. - */ - if (unlikely((long)skb->data & 0x03)) { - int offset = (4 - (long)skb->data) & 0x03; - wl1271_debug(DEBUG_TX, "skb offset %d", offset); - - /* check whether the current skb can be used */ - if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) { - unsigned char *src = skb->data; - - /* align the buffer on a 4-byte boundary */ - skb_reserve(skb, offset); - memmove(skb->data, src, skb->len); - } else { - wl1271_info("No handler, fixme!"); - return -EINVAL; - } - } - - len = WL1271_TX_ALIGN(skb->len); - - /* perform a fixed address block write with the packet */ - wl1271_spi_reg_write(wl, WL1271_SLV_MEM_DATA, skb->data, len, true); - - /* write packet new counter into the write access register */ - wl->tx_packets_count++; - wl1271_reg_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); - - desc = (struct wl1271_tx_hw_descr *) skb->data; - wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", - desc->id, skb, len, desc->length); - - return 0; -} - -/* caller must hold wl->mutex */ -static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) -{ - struct ieee80211_tx_info *info; - u32 extra = 0; - int ret = 0; - u8 idx; - - if (!skb) - return -EINVAL; - - info = IEEE80211_SKB_CB(skb); - - if (info->control.hw_key && - info->control.hw_key->alg == ALG_TKIP) - extra = WL1271_TKIP_IV_SPACE; - - if (info->control.hw_key) { - idx = info->control.hw_key->hw_key_idx; - - /* FIXME: do we have to do this if we're not using WEP? */ - if (unlikely(wl->default_key != idx)) { - ret = wl1271_cmd_set_default_wep_key(wl, idx); - if (ret < 0) - return ret; - } - } - - ret = wl1271_tx_allocate(wl, skb, extra); - if (ret < 0) - return ret; - - ret = wl1271_tx_fill_hdr(wl, skb, extra, info); - if (ret < 0) - return ret; - - ret = wl1271_tx_send_packet(wl, skb, info); - if (ret < 0) - return ret; - - return ret; -} - -void wl1271_tx_work(struct work_struct *work) -{ - struct wl1271 *wl = container_of(work, struct wl1271, tx_work); - struct sk_buff *skb; - bool woken_up = false; - int ret; - - mutex_lock(&wl->mutex); - - if (unlikely(wl->state == WL1271_STATE_OFF)) - goto out; - - while ((skb = skb_dequeue(&wl->tx_queue))) { - if (!woken_up) { - ret = wl1271_ps_elp_wakeup(wl, false); - if (ret < 0) - goto out; - woken_up = true; - } - - ret = wl1271_tx_frame(wl, skb); - if (ret == -EBUSY) { - /* firmware buffer is full, stop queues */ - wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, " - "stop queues"); - ieee80211_stop_queues(wl->hw); - wl->tx_queue_stopped = true; - skb_queue_head(&wl->tx_queue, skb); - goto out; - } else if (ret < 0) { - dev_kfree_skb(skb); - goto out; - } else if (wl->tx_queue_stopped) { - /* firmware buffer has space, restart queues */ - wl1271_debug(DEBUG_TX, - "complete_packet: waking queues"); - ieee80211_wake_queues(wl->hw); - wl->tx_queue_stopped = false; - } - } - -out: - if (woken_up) - wl1271_ps_elp_sleep(wl); - - mutex_unlock(&wl->mutex); -} - -static void wl1271_tx_complete_packet(struct wl1271 *wl, - struct wl1271_tx_hw_res_descr *result) -{ - - struct ieee80211_tx_info *info; - struct sk_buff *skb; - u32 header_len; - int id = result->id; - - /* check for id legality */ - if (id >= TX_HW_RESULT_QUEUE_LEN || wl->tx_frames[id] == NULL) { - wl1271_warning("TX result illegal id: %d", id); - return; - } - - skb = wl->tx_frames[id]; - info = IEEE80211_SKB_CB(skb); - - /* update packet status */ - if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { - if (result->status == TX_SUCCESS) - info->flags |= IEEE80211_TX_STAT_ACK; - if (result->status & TX_RETRY_EXCEEDED) { - /* FIXME */ - /* info->status.excessive_retries = 1; */ - wl->stats.excessive_retries++; - } - } - - /* FIXME */ - /* info->status.retry_count = result->ack_failures; */ - wl->stats.retry_count += result->ack_failures; - - /* get header len */ - if (info->control.hw_key && - info->control.hw_key->alg == ALG_TKIP) - header_len = WL1271_TKIP_IV_SPACE + - sizeof(struct wl1271_tx_hw_descr); - else - header_len = sizeof(struct wl1271_tx_hw_descr); - - wl1271_debug(DEBUG_TX, "tx status id %u skb 0x%p failures %u rate 0x%x" - " status 0x%x", - result->id, skb, result->ack_failures, - result->rate_class_index, result->status); - - /* remove private header from packet */ - skb_pull(skb, header_len); - - /* return the packet to the stack */ - ieee80211_tx_status(wl->hw, skb); - wl->tx_frames[result->id] = NULL; -} - -/* Called upon reception of a TX complete interrupt */ -void wl1271_tx_complete(struct wl1271 *wl, u32 count) -{ - struct wl1271_acx_mem_map *memmap = - (struct wl1271_acx_mem_map *)wl->target_mem_map; - u32 i; - - wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); - - /* read the tx results from the chipset */ - wl1271_spi_mem_read(wl, memmap->tx_result, - wl->tx_res_if, sizeof(*wl->tx_res_if)); - - /* verify that the result buffer is not getting overrun */ - if (count > TX_HW_RESULT_QUEUE_LEN) { - wl1271_warning("TX result overflow from chipset: %d", count); - count = TX_HW_RESULT_QUEUE_LEN; - } - - /* process the results */ - for (i = 0; i < count; i++) { - struct wl1271_tx_hw_res_descr *result; - u8 offset = wl->tx_results_count & TX_HW_RESULT_QUEUE_LEN_MASK; - - /* process the packet */ - result = &(wl->tx_res_if->tx_results_queue[offset]); - wl1271_tx_complete_packet(wl, result); - - wl->tx_results_count++; - } - - /* write host counter to chipset (to ack) */ - wl1271_mem_write32(wl, memmap->tx_result + - offsetof(struct wl1271_tx_hw_res_if, - tx_result_host_counter), - wl->tx_res_if->tx_result_fw_counter); -} - -/* caller must hold wl->mutex */ -void wl1271_tx_flush(struct wl1271 *wl) -{ - int i; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - - /* TX failure */ -/* control->flags = 0; FIXME */ - - while ((skb = skb_dequeue(&wl->tx_queue))) { - info = IEEE80211_SKB_CB(skb); - - wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); - - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) - continue; - - ieee80211_tx_status(wl->hw, skb); - } - - for (i = 0; i < FW_TX_CMPLT_BLOCK_SIZE; i++) - if (wl->tx_frames[i] != NULL) { - skb = wl->tx_frames[i]; - info = IEEE80211_SKB_CB(skb); - - if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) - continue; - - ieee80211_tx_status(wl->hw, skb); - wl->tx_frames[i] = NULL; - } -} diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h deleted file mode 100644 index 4a614067ddba..000000000000 --- a/drivers/net/wireless/wl12xx/wl1271_tx.h +++ /dev/null @@ -1,130 +0,0 @@ -/* - * This file is part of wl1271 - * - * Copyright (C) 1998-2009 Texas Instruments. All rights reserved. - * Copyright (C) 2009 Nokia Corporation - * - * Contact: Luciano Coelho - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#ifndef __WL1271_TX_H__ -#define __WL1271_TX_H__ - -#define TX_HW_BLOCK_SPARE 2 -#define TX_HW_BLOCK_SHIFT_DIV 8 - -#define TX_HW_MGMT_PKT_LIFETIME_TU 2000 -/* The chipset reference driver states, that the "aid" value 1 - * is for infra-BSS, but is still always used */ -#define TX_HW_DEFAULT_AID 1 - -#define TX_HW_ATTR_SAVE_RETRIES BIT(0) -#define TX_HW_ATTR_HEADER_PAD BIT(1) -#define TX_HW_ATTR_SESSION_COUNTER (BIT(2) | BIT(3) | BIT(4)) -#define TX_HW_ATTR_RATE_POLICY (BIT(5) | BIT(6) | BIT(7) | \ - BIT(8) | BIT(9)) -#define TX_HW_ATTR_LAST_WORD_PAD (BIT(10) | BIT(11)) -#define TX_HW_ATTR_TX_CMPLT_REQ BIT(12) - -#define TX_HW_ATTR_OFST_SAVE_RETRIES 0 -#define TX_HW_ATTR_OFST_HEADER_PAD 1 -#define TX_HW_ATTR_OFST_SESSION_COUNTER 2 -#define TX_HW_ATTR_OFST_RATE_POLICY 5 -#define TX_HW_ATTR_OFST_LAST_WORD_PAD 10 -#define TX_HW_ATTR_OFST_TX_CMPLT_REQ 12 - -#define TX_HW_RESULT_QUEUE_LEN 16 -#define TX_HW_RESULT_QUEUE_LEN_MASK 0xf - -#define WL1271_TX_ALIGN_TO 4 -#define WL1271_TX_ALIGN(len) (((len) + WL1271_TX_ALIGN_TO - 1) & \ - ~(WL1271_TX_ALIGN_TO - 1)) -#define WL1271_TKIP_IV_SPACE 4 - -struct wl1271_tx_hw_descr { - /* Length of packet in words, including descriptor+header+data */ - u16 length; - /* Number of extra memory blocks to allocate for this packet in - addition to the number of blocks derived from the packet length */ - u8 extra_mem_blocks; - /* Total number of memory blocks allocated by the host for this packet. - Must be equal or greater than the actual blocks number allocated by - HW!! */ - u8 total_mem_blocks; - /* Device time (in us) when the packet arrived to the driver */ - u32 start_time; - /* Max delay in TUs until transmission. The last device time the - packet can be transmitted is: startTime+(1024*LifeTime) */ - u16 life_time; - /* Bitwise fields - see TX_ATTR... definitions above. */ - u16 tx_attr; - /* Packet identifier used also in the Tx-Result. */ - u8 id; - /* The packet TID value (as User-Priority) */ - u8 tid; - /* Identifier of the remote STA in IBSS, 1 in infra-BSS */ - u8 aid; - u8 reserved; -} __attribute__ ((packed)); - -enum wl1271_tx_hw_res_status { - TX_SUCCESS = 0, - TX_HW_ERROR = 1, - TX_DISABLED = 2, - TX_RETRY_EXCEEDED = 3, - TX_TIMEOUT = 4, - TX_KEY_NOT_FOUND = 5, - TX_PEER_NOT_FOUND = 6, - TX_SESSION_MISMATCH = 7 -}; - -struct wl1271_tx_hw_res_descr { - /* Packet Identifier - same value used in the Tx descriptor.*/ - u8 id; - /* The status of the transmission, indicating success or one of - several possible reasons for failure. */ - u8 status; - /* Total air access duration including all retrys and overheads.*/ - u16 medium_usage; - /* The time passed from host xfer to Tx-complete.*/ - u32 fw_handling_time; - /* Total media delay - (from 1st EDCA AIFS counter until TX Complete). */ - u32 medium_delay; - /* LS-byte of last TKIP seq-num (saved per AC for recovery). */ - u8 lsb_security_sequence_number; - /* Retry count - number of transmissions without successful ACK.*/ - u8 ack_failures; - /* The rate that succeeded getting ACK - (Valid only if status=SUCCESS). */ - u8 rate_class_index; - /* for 4-byte alignment. */ - u8 spare; -} __attribute__ ((packed)); - -struct wl1271_tx_hw_res_if { - u32 tx_result_fw_counter; - u32 tx_result_host_counter; - struct wl1271_tx_hw_res_descr tx_results_queue[TX_HW_RESULT_QUEUE_LEN]; -} __attribute__ ((packed)); - -void wl1271_tx_work(struct work_struct *work); -void wl1271_tx_complete(struct wl1271 *wl, u32 count); -void wl1271_tx_flush(struct wl1271 *wl); - -#endif diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h deleted file mode 100644 index 657c2dbcb7d3..000000000000 --- a/drivers/net/wireless/wl12xx/wl12xx_80211.h +++ /dev/null @@ -1,156 +0,0 @@ -#ifndef __WL12XX_80211_H__ -#define __WL12XX_80211_H__ - -#include /* ETH_ALEN */ - -/* RATES */ -#define IEEE80211_CCK_RATE_1MB 0x02 -#define IEEE80211_CCK_RATE_2MB 0x04 -#define IEEE80211_CCK_RATE_5MB 0x0B -#define IEEE80211_CCK_RATE_11MB 0x16 -#define IEEE80211_OFDM_RATE_6MB 0x0C -#define IEEE80211_OFDM_RATE_9MB 0x12 -#define IEEE80211_OFDM_RATE_12MB 0x18 -#define IEEE80211_OFDM_RATE_18MB 0x24 -#define IEEE80211_OFDM_RATE_24MB 0x30 -#define IEEE80211_OFDM_RATE_36MB 0x48 -#define IEEE80211_OFDM_RATE_48MB 0x60 -#define IEEE80211_OFDM_RATE_54MB 0x6C -#define IEEE80211_BASIC_RATE_MASK 0x80 - -#define IEEE80211_CCK_RATE_1MB_MASK (1<<0) -#define IEEE80211_CCK_RATE_2MB_MASK (1<<1) -#define IEEE80211_CCK_RATE_5MB_MASK (1<<2) -#define IEEE80211_CCK_RATE_11MB_MASK (1<<3) -#define IEEE80211_OFDM_RATE_6MB_MASK (1<<4) -#define IEEE80211_OFDM_RATE_9MB_MASK (1<<5) -#define IEEE80211_OFDM_RATE_12MB_MASK (1<<6) -#define IEEE80211_OFDM_RATE_18MB_MASK (1<<7) -#define IEEE80211_OFDM_RATE_24MB_MASK (1<<8) -#define IEEE80211_OFDM_RATE_36MB_MASK (1<<9) -#define IEEE80211_OFDM_RATE_48MB_MASK (1<<10) -#define IEEE80211_OFDM_RATE_54MB_MASK (1<<11) - -#define IEEE80211_CCK_RATES_MASK 0x0000000F -#define IEEE80211_CCK_BASIC_RATES_MASK (IEEE80211_CCK_RATE_1MB_MASK | \ - IEEE80211_CCK_RATE_2MB_MASK) -#define IEEE80211_CCK_DEFAULT_RATES_MASK (IEEE80211_CCK_BASIC_RATES_MASK | \ - IEEE80211_CCK_RATE_5MB_MASK | \ - IEEE80211_CCK_RATE_11MB_MASK) - -#define IEEE80211_OFDM_RATES_MASK 0x00000FF0 -#define IEEE80211_OFDM_BASIC_RATES_MASK (IEEE80211_OFDM_RATE_6MB_MASK | \ - IEEE80211_OFDM_RATE_12MB_MASK | \ - IEEE80211_OFDM_RATE_24MB_MASK) -#define IEEE80211_OFDM_DEFAULT_RATES_MASK (IEEE80211_OFDM_BASIC_RATES_MASK | \ - IEEE80211_OFDM_RATE_9MB_MASK | \ - IEEE80211_OFDM_RATE_18MB_MASK | \ - IEEE80211_OFDM_RATE_36MB_MASK | \ - IEEE80211_OFDM_RATE_48MB_MASK | \ - IEEE80211_OFDM_RATE_54MB_MASK) -#define IEEE80211_DEFAULT_RATES_MASK (IEEE80211_OFDM_DEFAULT_RATES_MASK | \ - IEEE80211_CCK_DEFAULT_RATES_MASK) - - -/* This really should be 8, but not for our firmware */ -#define MAX_SUPPORTED_RATES 32 -#define COUNTRY_STRING_LEN 3 -#define MAX_COUNTRY_TRIPLETS 32 - -/* Headers */ -struct ieee80211_header { - __le16 frame_ctl; - __le16 duration_id; - u8 da[ETH_ALEN]; - u8 sa[ETH_ALEN]; - u8 bssid[ETH_ALEN]; - __le16 seq_ctl; - u8 payload[0]; -} __attribute__ ((packed)); - -struct wl12xx_ie_header { - u8 id; - u8 len; -} __attribute__ ((packed)); - -/* IEs */ - -struct wl12xx_ie_ssid { - struct wl12xx_ie_header header; - char ssid[IW_ESSID_MAX_SIZE]; -} __attribute__ ((packed)); - -struct wl12xx_ie_rates { - struct wl12xx_ie_header header; - u8 rates[MAX_SUPPORTED_RATES]; -} __attribute__ ((packed)); - -struct wl12xx_ie_ds_params { - struct wl12xx_ie_header header; - u8 channel; -} __attribute__ ((packed)); - -struct country_triplet { - u8 channel; - u8 num_channels; - u8 max_tx_power; -} __attribute__ ((packed)); - -struct wl12xx_ie_country { - struct wl12xx_ie_header header; - u8 country_string[COUNTRY_STRING_LEN]; - struct country_triplet triplets[MAX_COUNTRY_TRIPLETS]; -} __attribute__ ((packed)); - - -/* Templates */ - -struct wl12xx_beacon_template { - struct ieee80211_header header; - __le32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - struct wl12xx_ie_ssid ssid; - struct wl12xx_ie_rates rates; - struct wl12xx_ie_rates ext_rates; - struct wl12xx_ie_ds_params ds_params; - struct wl12xx_ie_country country; -} __attribute__ ((packed)); - -struct wl12xx_null_data_template { - struct ieee80211_header header; -} __attribute__ ((packed)); - -struct wl12xx_ps_poll_template { - u16 fc; - u16 aid; - u8 bssid[ETH_ALEN]; - u8 ta[ETH_ALEN]; -} __attribute__ ((packed)); - -struct wl12xx_qos_null_data_template { - struct ieee80211_header header; - __le16 qos_ctl; -} __attribute__ ((packed)); - -struct wl12xx_probe_req_template { - struct ieee80211_header header; - struct wl12xx_ie_ssid ssid; - struct wl12xx_ie_rates rates; - struct wl12xx_ie_rates ext_rates; -} __attribute__ ((packed)); - - -struct wl12xx_probe_resp_template { - struct ieee80211_header header; - __le32 time_stamp[2]; - __le16 beacon_interval; - __le16 capability; - struct wl12xx_ie_ssid ssid; - struct wl12xx_ie_rates rates; - struct wl12xx_ie_rates ext_rates; - struct wl12xx_ie_ds_params ds_params; - struct wl12xx_ie_country country; -} __attribute__ ((packed)); - -#endif diff --git a/drivers/net/wireless/wl3501.h b/drivers/net/wireless/wl3501.h deleted file mode 100644 index 8bce1a550a22..000000000000 --- a/drivers/net/wireless/wl3501.h +++ /dev/null @@ -1,616 +0,0 @@ -#ifndef __WL3501_H__ -#define __WL3501_H__ - -#include -#include - -/* define for WLA 2.0 */ -#define WL3501_BLKSZ 256 -/* - * ID for input Signals of DRIVER block - * bit[7-5] is block ID: 000 - * bit[4-0] is signal ID -*/ -enum wl3501_signals { - WL3501_SIG_ALARM, - WL3501_SIG_MD_CONFIRM, - WL3501_SIG_MD_IND, - WL3501_SIG_ASSOC_CONFIRM, - WL3501_SIG_ASSOC_IND, - WL3501_SIG_AUTH_CONFIRM, - WL3501_SIG_AUTH_IND, - WL3501_SIG_DEAUTH_CONFIRM, - WL3501_SIG_DEAUTH_IND, - WL3501_SIG_DISASSOC_CONFIRM, - WL3501_SIG_DISASSOC_IND, - WL3501_SIG_GET_CONFIRM, - WL3501_SIG_JOIN_CONFIRM, - WL3501_SIG_PWR_MGMT_CONFIRM, - WL3501_SIG_REASSOC_CONFIRM, - WL3501_SIG_REASSOC_IND, - WL3501_SIG_SCAN_CONFIRM, - WL3501_SIG_SET_CONFIRM, - WL3501_SIG_START_CONFIRM, - WL3501_SIG_RESYNC_CONFIRM, - WL3501_SIG_SITE_CONFIRM, - WL3501_SIG_SAVE_CONFIRM, - WL3501_SIG_RFTEST_CONFIRM, -/* - * ID for input Signals of MLME block - * bit[7-5] is block ID: 010 - * bit[4-0] is signal ID - */ - WL3501_SIG_ASSOC_REQ = 0x20, - WL3501_SIG_AUTH_REQ, - WL3501_SIG_DEAUTH_REQ, - WL3501_SIG_DISASSOC_REQ, - WL3501_SIG_GET_REQ, - WL3501_SIG_JOIN_REQ, - WL3501_SIG_PWR_MGMT_REQ, - WL3501_SIG_REASSOC_REQ, - WL3501_SIG_SCAN_REQ, - WL3501_SIG_SET_REQ, - WL3501_SIG_START_REQ, - WL3501_SIG_MD_REQ, - WL3501_SIG_RESYNC_REQ, - WL3501_SIG_SITE_REQ, - WL3501_SIG_SAVE_REQ, - WL3501_SIG_RF_TEST_REQ, - WL3501_SIG_MM_CONFIRM = 0x60, - WL3501_SIG_MM_IND, -}; - -enum wl3501_mib_attribs { - WL3501_MIB_ATTR_STATION_ID, - WL3501_MIB_ATTR_AUTH_ALGORITHMS, - WL3501_MIB_ATTR_AUTH_TYPE, - WL3501_MIB_ATTR_MEDIUM_OCCUPANCY_LIMIT, - WL3501_MIB_ATTR_CF_POLLABLE, - WL3501_MIB_ATTR_CFP_PERIOD, - WL3501_MIB_ATTR_CFPMAX_DURATION, - WL3501_MIB_ATTR_AUTH_RESP_TMOUT, - WL3501_MIB_ATTR_RX_DTIMS, - WL3501_MIB_ATTR_PRIV_OPT_IMPLEMENTED, - WL3501_MIB_ATTR_PRIV_INVOKED, - WL3501_MIB_ATTR_WEP_DEFAULT_KEYS, - WL3501_MIB_ATTR_WEP_DEFAULT_KEY_ID, - WL3501_MIB_ATTR_WEP_KEY_MAPPINGS, - WL3501_MIB_ATTR_WEP_KEY_MAPPINGS_LEN, - WL3501_MIB_ATTR_EXCLUDE_UNENCRYPTED, - WL3501_MIB_ATTR_WEP_ICV_ERROR_COUNT, - WL3501_MIB_ATTR_WEP_UNDECRYPTABLE_COUNT, - WL3501_MIB_ATTR_WEP_EXCLUDED_COUNT, - WL3501_MIB_ATTR_MAC_ADDR, - WL3501_MIB_ATTR_GROUP_ADDRS, - WL3501_MIB_ATTR_RTS_THRESHOLD, - WL3501_MIB_ATTR_SHORT_RETRY_LIMIT, - WL3501_MIB_ATTR_LONG_RETRY_LIMIT, - WL3501_MIB_ATTR_FRAG_THRESHOLD, - WL3501_MIB_ATTR_MAX_TX_MSDU_LIFETIME, - WL3501_MIB_ATTR_MAX_RX_LIFETIME, - WL3501_MIB_ATTR_MANUFACTURER_ID, - WL3501_MIB_ATTR_PRODUCT_ID, - WL3501_MIB_ATTR_TX_FRAG_COUNT, - WL3501_MIB_ATTR_MULTICAST_TX_FRAME_COUNT, - WL3501_MIB_ATTR_FAILED_COUNT, - WL3501_MIB_ATTR_RX_FRAG_COUNT, - WL3501_MIB_ATTR_MULTICAST_RX_COUNT, - WL3501_MIB_ATTR_FCS_ERROR_COUNT, - WL3501_MIB_ATTR_RETRY_COUNT, - WL3501_MIB_ATTR_MULTIPLE_RETRY_COUNT, - WL3501_MIB_ATTR_RTS_SUCCESS_COUNT, - WL3501_MIB_ATTR_RTS_FAILURE_COUNT, - WL3501_MIB_ATTR_ACK_FAILURE_COUNT, - WL3501_MIB_ATTR_FRAME_DUPLICATE_COUNT, - WL3501_MIB_ATTR_PHY_TYPE, - WL3501_MIB_ATTR_REG_DOMAINS_SUPPORT, - WL3501_MIB_ATTR_CURRENT_REG_DOMAIN, - WL3501_MIB_ATTR_SLOT_TIME, - WL3501_MIB_ATTR_CCA_TIME, - WL3501_MIB_ATTR_RX_TX_TURNAROUND_TIME, - WL3501_MIB_ATTR_TX_PLCP_DELAY, - WL3501_MIB_ATTR_RX_TX_SWITCH_TIME, - WL3501_MIB_ATTR_TX_RAMP_ON_TIME, - WL3501_MIB_ATTR_TX_RF_DELAY, - WL3501_MIB_ATTR_SIFS_TIME, - WL3501_MIB_ATTR_RX_RF_DELAY, - WL3501_MIB_ATTR_RX_PLCP_DELAY, - WL3501_MIB_ATTR_MAC_PROCESSING_DELAY, - WL3501_MIB_ATTR_TX_RAMP_OFF_TIME, - WL3501_MIB_ATTR_PREAMBLE_LEN, - WL3501_MIB_ATTR_PLCP_HEADER_LEN, - WL3501_MIB_ATTR_MPDU_DURATION_FACTOR, - WL3501_MIB_ATTR_AIR_PROPAGATION_TIME, - WL3501_MIB_ATTR_TEMP_TYPE, - WL3501_MIB_ATTR_CW_MIN, - WL3501_MIB_ATTR_CW_MAX, - WL3501_MIB_ATTR_SUPPORT_DATA_RATES_TX, - WL3501_MIB_ATTR_SUPPORT_DATA_RATES_RX, - WL3501_MIB_ATTR_MPDU_MAX_LEN, - WL3501_MIB_ATTR_SUPPORT_TX_ANTENNAS, - WL3501_MIB_ATTR_CURRENT_TX_ANTENNA, - WL3501_MIB_ATTR_SUPPORT_RX_ANTENNAS, - WL3501_MIB_ATTR_DIVERSITY_SUPPORT, - WL3501_MIB_ATTR_DIVERSITY_SELECTION_RS, - WL3501_MIB_ATTR_NR_SUPPORTED_PWR_LEVELS, - WL3501_MIB_ATTR_TX_PWR_LEVEL1, - WL3501_MIB_ATTR_TX_PWR_LEVEL2, - WL3501_MIB_ATTR_TX_PWR_LEVEL3, - WL3501_MIB_ATTR_TX_PWR_LEVEL4, - WL3501_MIB_ATTR_TX_PWR_LEVEL5, - WL3501_MIB_ATTR_TX_PWR_LEVEL6, - WL3501_MIB_ATTR_TX_PWR_LEVEL7, - WL3501_MIB_ATTR_TX_PWR_LEVEL8, - WL3501_MIB_ATTR_CURRENT_TX_PWR_LEVEL, - WL3501_MIB_ATTR_CURRENT_CHAN, - WL3501_MIB_ATTR_CCA_MODE_SUPPORTED, - WL3501_MIB_ATTR_CURRENT_CCA_MODE, - WL3501_MIB_ATTR_ED_THRESHOLD, - WL3501_MIB_ATTR_SINTHESIZER_LOCKED, - WL3501_MIB_ATTR_CURRENT_PWR_STATE, - WL3501_MIB_ATTR_DOZE_TURNON_TIME, - WL3501_MIB_ATTR_RCR33, - WL3501_MIB_ATTR_DEFAULT_CHAN, - WL3501_MIB_ATTR_SSID, - WL3501_MIB_ATTR_PWR_MGMT_ENABLE, - WL3501_MIB_ATTR_NET_CAPABILITY, - WL3501_MIB_ATTR_ROUTING, -}; - -enum wl3501_net_type { - WL3501_NET_TYPE_INFRA, - WL3501_NET_TYPE_ADHOC, - WL3501_NET_TYPE_ANY_BSS, -}; - -enum wl3501_scan_type { - WL3501_SCAN_TYPE_ACTIVE, - WL3501_SCAN_TYPE_PASSIVE, -}; - -enum wl3501_tx_result { - WL3501_TX_RESULT_SUCCESS, - WL3501_TX_RESULT_NO_BSS, - WL3501_TX_RESULT_RETRY_LIMIT, -}; - -enum wl3501_sys_type { - WL3501_SYS_TYPE_OPEN, - WL3501_SYS_TYPE_SHARE_KEY, -}; - -enum wl3501_status { - WL3501_STATUS_SUCCESS, - WL3501_STATUS_INVALID, - WL3501_STATUS_TIMEOUT, - WL3501_STATUS_REFUSED, - WL3501_STATUS_MANY_REQ, - WL3501_STATUS_ALREADY_BSS, -}; - -#define WL3501_MGMT_CAPABILITY_ESS 0x0001 /* see 802.11 p.58 */ -#define WL3501_MGMT_CAPABILITY_IBSS 0x0002 /* - " - */ -#define WL3501_MGMT_CAPABILITY_CF_POLLABLE 0x0004 /* - " - */ -#define WL3501_MGMT_CAPABILITY_CF_POLL_REQUEST 0x0008 /* - " - */ -#define WL3501_MGMT_CAPABILITY_PRIVACY 0x0010 /* - " - */ - -#define IW_REG_DOMAIN_FCC 0x10 /* Channel 1 to 11 USA */ -#define IW_REG_DOMAIN_DOC 0x20 /* Channel 1 to 11 Canada */ -#define IW_REG_DOMAIN_ETSI 0x30 /* Channel 1 to 13 Europe */ -#define IW_REG_DOMAIN_SPAIN 0x31 /* Channel 10 to 11 Spain */ -#define IW_REG_DOMAIN_FRANCE 0x32 /* Channel 10 to 13 France */ -#define IW_REG_DOMAIN_MKK 0x40 /* Channel 14 Japan */ -#define IW_REG_DOMAIN_MKK1 0x41 /* Channel 1-14 Japan */ -#define IW_REG_DOMAIN_ISRAEL 0x50 /* Channel 3 - 9 Israel */ - -#define IW_MGMT_RATE_LABEL_MANDATORY 128 /* MSB */ - -enum iw_mgmt_rate_labels { - IW_MGMT_RATE_LABEL_1MBIT = 2, - IW_MGMT_RATE_LABEL_2MBIT = 4, - IW_MGMT_RATE_LABEL_5_5MBIT = 11, - IW_MGMT_RATE_LABEL_11MBIT = 22, -}; - -enum iw_mgmt_info_element_ids { - IW_MGMT_INFO_ELEMENT_SSID, /* Service Set Identity */ - IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, - IW_MGMT_INFO_ELEMENT_FH_PARAMETER_SET, - IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, - IW_MGMT_INFO_ELEMENT_CS_PARAMETER_SET, - IW_MGMT_INFO_ELEMENT_CS_TIM, /* Traffic Information Map */ - IW_MGMT_INFO_ELEMENT_IBSS_PARAMETER_SET, - /* 7-15: Reserved, unused */ - IW_MGMT_INFO_ELEMENT_CHALLENGE_TEXT = 16, - /* 17-31 Reserved for challenge text extension */ - /* 32-255 Reserved, unused */ -}; - -struct iw_mgmt_info_element { - u8 id; /* one of enum iw_mgmt_info_element_ids, - but sizeof(enum) > sizeof(u8) :-( */ - u8 len; - u8 data[0]; -} __attribute__ ((packed)); - -struct iw_mgmt_essid_pset { - struct iw_mgmt_info_element el; - u8 essid[IW_ESSID_MAX_SIZE]; -} __attribute__ ((packed)); - -/* - * According to 802.11 Wireless Netowors, the definitive guide - O'Reilly - * Pg 75 - */ -#define IW_DATA_RATE_MAX_LABELS 8 - -struct iw_mgmt_data_rset { - struct iw_mgmt_info_element el; - u8 data_rate_labels[IW_DATA_RATE_MAX_LABELS]; -} __attribute__ ((packed)); - -struct iw_mgmt_ds_pset { - struct iw_mgmt_info_element el; - u8 chan; -} __attribute__ ((packed)); - -struct iw_mgmt_cf_pset { - struct iw_mgmt_info_element el; - u8 cfp_count; - u8 cfp_period; - u16 cfp_max_duration; - u16 cfp_dur_remaining; -} __attribute__ ((packed)); - -struct iw_mgmt_ibss_pset { - struct iw_mgmt_info_element el; - u16 atim_window; -} __attribute__ ((packed)); - -struct wl3501_tx_hdr { - u16 tx_cnt; - u8 sync[16]; - u16 sfd; - u8 signal; - u8 service; - u16 len; - u16 crc16; - u16 frame_ctrl; - u16 duration_id; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq_ctrl; - u8 addr4[ETH_ALEN]; -}; - -struct wl3501_rx_hdr { - u16 rx_next_blk; - u16 rc_next_frame_blk; - u8 rx_blk_ctrl; - u8 rx_next_frame; - u8 rx_next_frame1; - u8 rssi; - char time[8]; - u8 signal; - u8 service; - u16 len; - u16 crc16; - u16 frame_ctrl; - u16 duration; - u8 addr1[ETH_ALEN]; - u8 addr2[ETH_ALEN]; - u8 addr3[ETH_ALEN]; - u16 seq; - u8 addr4[ETH_ALEN]; -}; - -struct wl3501_start_req { - u16 next_blk; - u8 sig_id; - u8 bss_type; - u16 beacon_period; - u16 dtim_period; - u16 probe_delay; - u16 cap_info; - struct iw_mgmt_essid_pset ssid; - struct iw_mgmt_data_rset bss_basic_rset; - struct iw_mgmt_data_rset operational_rset; - struct iw_mgmt_cf_pset cf_pset; - struct iw_mgmt_ds_pset ds_pset; - struct iw_mgmt_ibss_pset ibss_pset; -}; - -struct wl3501_assoc_req { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 timeout; - u16 cap_info; - u16 listen_interval; - u8 mac_addr[ETH_ALEN]; -}; - -struct wl3501_assoc_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 status; -}; - -struct wl3501_assoc_ind { - u16 next_blk; - u8 sig_id; - u8 mac_addr[ETH_ALEN]; -}; - -struct wl3501_auth_req { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 type; - u16 timeout; - u8 mac_addr[ETH_ALEN]; -}; - -struct wl3501_auth_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 type; - u16 status; - u8 mac_addr[ETH_ALEN]; -}; - -struct wl3501_get_req { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 mib_attrib; -}; - -struct wl3501_get_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 mib_status; - u16 mib_attrib; - u8 mib_value[100]; -}; - -struct wl3501_join_req { - u16 next_blk; - u8 sig_id; - u8 reserved; - struct iw_mgmt_data_rset operational_rset; - u16 reserved2; - u16 timeout; - u16 probe_delay; - u8 timestamp[8]; - u8 local_time[8]; - u16 beacon_period; - u16 dtim_period; - u16 cap_info; - u8 bss_type; - u8 bssid[ETH_ALEN]; - struct iw_mgmt_essid_pset ssid; - struct iw_mgmt_ds_pset ds_pset; - struct iw_mgmt_cf_pset cf_pset; - struct iw_mgmt_ibss_pset ibss_pset; - struct iw_mgmt_data_rset bss_basic_rset; -}; - -struct wl3501_join_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 status; -}; - -struct wl3501_pwr_mgmt_req { - u16 next_blk; - u8 sig_id; - u8 pwr_save; - u8 wake_up; - u8 receive_dtims; -}; - -struct wl3501_pwr_mgmt_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 status; -}; - -struct wl3501_scan_req { - u16 next_blk; - u8 sig_id; - u8 bss_type; - u16 probe_delay; - u16 min_chan_time; - u16 max_chan_time; - u8 chan_list[14]; - u8 bssid[ETH_ALEN]; - struct iw_mgmt_essid_pset ssid; - enum wl3501_scan_type scan_type; -}; - -struct wl3501_scan_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 status; - char timestamp[8]; - char localtime[8]; - u16 beacon_period; - u16 dtim_period; - u16 cap_info; - u8 bss_type; - u8 bssid[ETH_ALEN]; - struct iw_mgmt_essid_pset ssid; - struct iw_mgmt_ds_pset ds_pset; - struct iw_mgmt_cf_pset cf_pset; - struct iw_mgmt_ibss_pset ibss_pset; - struct iw_mgmt_data_rset bss_basic_rset; - u8 rssi; -}; - -struct wl3501_start_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 status; -}; - -struct wl3501_md_req { - u16 next_blk; - u8 sig_id; - u8 routing; - u16 data; - u16 size; - u8 pri; - u8 service_class; - u8 daddr[ETH_ALEN]; - u8 saddr[ETH_ALEN]; -}; - -struct wl3501_md_ind { - u16 next_blk; - u8 sig_id; - u8 routing; - u16 data; - u16 size; - u8 reception; - u8 pri; - u8 service_class; - u8 daddr[ETH_ALEN]; - u8 saddr[ETH_ALEN]; -}; - -struct wl3501_md_confirm { - u16 next_blk; - u8 sig_id; - u8 reserved; - u16 data; - u8 status; - u8 pri; - u8 service_class; -}; - -struct wl3501_resync_req { - u16 next_blk; - u8 sig_id; -}; - -/* Definitions for supporting clone adapters. */ -/* System Interface Registers (SIR space) */ -#define WL3501_NIC_GCR ((u8)0x00) /* SIR0 - General Conf Register */ -#define WL3501_NIC_BSS ((u8)0x01) /* SIR1 - Bank Switching Select Reg */ -#define WL3501_NIC_LMAL ((u8)0x02) /* SIR2 - Local Mem addr Reg [7:0] */ -#define WL3501_NIC_LMAH ((u8)0x03) /* SIR3 - Local Mem addr Reg [14:8] */ -#define WL3501_NIC_IODPA ((u8)0x04) /* SIR4 - I/O Data Port A */ -#define WL3501_NIC_IODPB ((u8)0x05) /* SIR5 - I/O Data Port B */ -#define WL3501_NIC_IODPC ((u8)0x06) /* SIR6 - I/O Data Port C */ -#define WL3501_NIC_IODPD ((u8)0x07) /* SIR7 - I/O Data Port D */ - -/* Bits in GCR */ -#define WL3501_GCR_SWRESET ((u8)0x80) -#define WL3501_GCR_CORESET ((u8)0x40) -#define WL3501_GCR_DISPWDN ((u8)0x20) -#define WL3501_GCR_ECWAIT ((u8)0x10) -#define WL3501_GCR_ECINT ((u8)0x08) -#define WL3501_GCR_INT2EC ((u8)0x04) -#define WL3501_GCR_ENECINT ((u8)0x02) -#define WL3501_GCR_DAM ((u8)0x01) - -/* Bits in BSS (Bank Switching Select Register) */ -#define WL3501_BSS_FPAGE0 ((u8)0x20) /* Flash memory page0 */ -#define WL3501_BSS_FPAGE1 ((u8)0x28) -#define WL3501_BSS_FPAGE2 ((u8)0x30) -#define WL3501_BSS_FPAGE3 ((u8)0x38) -#define WL3501_BSS_SPAGE0 ((u8)0x00) /* SRAM page0 */ -#define WL3501_BSS_SPAGE1 ((u8)0x08) -#define WL3501_BSS_SPAGE2 ((u8)0x10) -#define WL3501_BSS_SPAGE3 ((u8)0x18) - -/* Define Driver Interface */ -/* Refer IEEE 802.11 */ -/* Tx packet header, include PLCP and MPDU */ -/* Tx PLCP Header */ -struct wl3501_80211_tx_plcp_hdr { - u8 sync[16]; - u16 sfd; - u8 signal; - u8 service; - u16 len; - u16 crc16; -} __attribute__ ((packed)); - -struct wl3501_80211_tx_hdr { - struct wl3501_80211_tx_plcp_hdr pclp_hdr; - struct ieee80211_hdr mac_hdr; -} __attribute__ ((packed)); - -/* - Reserve the beginning Tx space for descriptor use. - - TxBlockOffset --> *----*----*----*----* \ - (TxFreeDesc) | 0 | 1 | 2 | 3 | \ - | 4 | 5 | 6 | 7 | | - | 8 | 9 | 10 | 11 | TX_DESC * 20 - | 12 | 13 | 14 | 15 | | - | 16 | 17 | 18 | 19 | / - TxBufferBegin --> *----*----*----*----* / - (TxBufferHead) | | - (TxBufferTail) | | - | Send Buffer | - | | - | | - *-------------------* - TxBufferEnd -------------------------/ - -*/ - -struct wl3501_card { - int base_addr; - u8 mac_addr[ETH_ALEN]; - spinlock_t lock; - wait_queue_head_t wait; - struct wl3501_get_confirm sig_get_confirm; - struct wl3501_pwr_mgmt_confirm sig_pwr_mgmt_confirm; - u16 tx_buffer_size; - u16 tx_buffer_head; - u16 tx_buffer_tail; - u16 tx_buffer_cnt; - u16 esbq_req_start; - u16 esbq_req_end; - u16 esbq_req_head; - u16 esbq_req_tail; - u16 esbq_confirm_start; - u16 esbq_confirm_end; - u16 esbq_confirm; - struct iw_mgmt_essid_pset essid; - struct iw_mgmt_essid_pset keep_essid; - u8 bssid[ETH_ALEN]; - int net_type; - char nick[32]; - char card_name[32]; - char firmware_date[32]; - u8 chan; - u8 cap_info; - u16 start_seg; - u16 bss_cnt; - u16 join_sta_bss; - u8 rssi; - u8 adhoc_times; - u8 reg_domain; - u8 version[2]; - struct wl3501_scan_confirm bss_set[20]; - - struct iw_statistics wstats; - struct iw_spy_data spy_data; - struct iw_public_data wireless_data; - struct dev_node_t node; - struct pcmcia_device *p_dev; -}; -#endif diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c deleted file mode 100644 index 4f1e0cfe609b..000000000000 --- a/drivers/net/wireless/wl3501_cs.c +++ /dev/null @@ -1,2130 +0,0 @@ -/* - * WL3501 Wireless LAN PCMCIA Card Driver for Linux - * Written originally for Linux 2.0.30 by Fox Chen, mhchen@golf.ccl.itri.org.tw - * Ported to 2.2, 2.4 & 2.5 by Arnaldo Carvalho de Melo - * Wireless extensions in 2.4 by Gustavo Niemeyer - * - * References used by Fox Chen while writing the original driver for 2.0.30: - * - * 1. WL24xx packet drivers (tooasm.asm) - * 2. Access Point Firmware Interface Specification for IEEE 802.11 SUTRO - * 3. IEEE 802.11 - * 4. Linux network driver (/usr/src/linux/drivers/net) - * 5. ISA card driver - wl24.c - * 6. Linux PCMCIA skeleton driver - skeleton.c - * 7. Linux PCMCIA 3c589 network driver - 3c589_cs.c - * - * Tested with WL2400 firmware 1.2, Linux 2.0.30, and pcmcia-cs-2.9.12 - * 1. Performance: about 165 Kbytes/sec in TCP/IP with Ad-Hoc mode. - * rsh 192.168.1.3 "dd if=/dev/zero bs=1k count=1000" > /dev/null - * (Specification 2M bits/sec. is about 250 Kbytes/sec., but we must deduct - * ETHER/IP/UDP/TCP header, and acknowledgement overhead) - * - * Tested with Planet AP in 2.4.17, 184 Kbytes/s in UDP in Infrastructure mode, - * 173 Kbytes/s in TCP. - * - * Tested with Planet AP in 2.5.73-bk, 216 Kbytes/s in Infrastructure mode - * with a SMP machine (dual pentium 100), using pktgen, 432 pps (pkt_size = 60) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "wl3501.h" - -#ifndef __i386__ -#define slow_down_io() -#endif - -/* For rough constant delay */ -#define WL3501_NOPLOOP(n) { int x = 0; while (x++ < n) slow_down_io(); } - -/* - * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If you do not - * define PCMCIA_DEBUG at all, all the debug code will be left out. If you - * compile with PCMCIA_DEBUG=0, the debug code will be present but disabled -- - * but it can then be enabled for specific modules at load time with a - * 'pc_debug=#' option to insmod. - */ -#define PCMCIA_DEBUG 0 -#ifdef PCMCIA_DEBUG -static int pc_debug = PCMCIA_DEBUG; -module_param(pc_debug, int, 0); -#define dprintk(n, format, args...) \ - { if (pc_debug > (n)) \ - printk(KERN_INFO "%s: " format "\n", __func__ , ##args); } -#else -#define dprintk(n, format, args...) -#endif - -#define wl3501_outb(a, b) { outb(a, b); slow_down_io(); } -#define wl3501_outb_p(a, b) { outb_p(a, b); slow_down_io(); } -#define wl3501_outsb(a, b, c) { outsb(a, b, c); slow_down_io(); } - -#define WL3501_RELEASE_TIMEOUT (25 * HZ) -#define WL3501_MAX_ADHOC_TRIES 16 - -#define WL3501_RESUME 0 -#define WL3501_SUSPEND 1 - -/* - * The event() function is this driver's Card Services event handler. It will - * be called by Card Services when an appropriate card status event is - * received. The config() and release() entry points are used to configure or - * release a socket, in response to card insertion and ejection events. They - * are invoked from the wl24 event handler. - */ -static int wl3501_config(struct pcmcia_device *link); -static void wl3501_release(struct pcmcia_device *link); - -/* - * The dev_info variable is the "key" that is used to match up this - * device driver with appropriate cards, through the card configuration - * database. - */ -static dev_info_t wl3501_dev_info = "wl3501_cs"; - -static const struct { - int reg_domain; - int min, max, deflt; -} iw_channel_table[] = { - { - .reg_domain = IW_REG_DOMAIN_FCC, - .min = 1, - .max = 11, - .deflt = 1, - }, - { - .reg_domain = IW_REG_DOMAIN_DOC, - .min = 1, - .max = 11, - .deflt = 1, - }, - { - .reg_domain = IW_REG_DOMAIN_ETSI, - .min = 1, - .max = 13, - .deflt = 1, - }, - { - .reg_domain = IW_REG_DOMAIN_SPAIN, - .min = 10, - .max = 11, - .deflt = 10, - }, - { - .reg_domain = IW_REG_DOMAIN_FRANCE, - .min = 10, - .max = 13, - .deflt = 10, - }, - { - .reg_domain = IW_REG_DOMAIN_MKK, - .min = 14, - .max = 14, - .deflt = 14, - }, - { - .reg_domain = IW_REG_DOMAIN_MKK1, - .min = 1, - .max = 14, - .deflt = 1, - }, - { - .reg_domain = IW_REG_DOMAIN_ISRAEL, - .min = 3, - .max = 9, - .deflt = 9, - }, -}; - -/** - * iw_valid_channel - validate channel in regulatory domain - * @reg_comain - regulatory domain - * @channel - channel to validate - * - * Returns 0 if invalid in the specified regulatory domain, non-zero if valid. - */ -static int iw_valid_channel(int reg_domain, int channel) -{ - int i, rc = 0; - - for (i = 0; i < ARRAY_SIZE(iw_channel_table); i++) - if (reg_domain == iw_channel_table[i].reg_domain) { - rc = channel >= iw_channel_table[i].min && - channel <= iw_channel_table[i].max; - break; - } - return rc; -} - -/** - * iw_default_channel - get default channel for a regulatory domain - * @reg_comain - regulatory domain - * - * Returns the default channel for a regulatory domain - */ -static int iw_default_channel(int reg_domain) -{ - int i, rc = 1; - - for (i = 0; i < ARRAY_SIZE(iw_channel_table); i++) - if (reg_domain == iw_channel_table[i].reg_domain) { - rc = iw_channel_table[i].deflt; - break; - } - return rc; -} - -static void iw_set_mgmt_info_element(enum iw_mgmt_info_element_ids id, - struct iw_mgmt_info_element *el, - void *value, int len) -{ - el->id = id; - el->len = len; - memcpy(el->data, value, len); -} - -static void iw_copy_mgmt_info_element(struct iw_mgmt_info_element *to, - struct iw_mgmt_info_element *from) -{ - iw_set_mgmt_info_element(from->id, to, from->data, from->len); -} - -static inline void wl3501_switch_page(struct wl3501_card *this, u8 page) -{ - wl3501_outb(page, this->base_addr + WL3501_NIC_BSS); -} - -/* - * Get Ethernet MAC addresss. - * - * WARNING: We switch to FPAGE0 and switc back again. - * Making sure there is no other WL function beening called by ISR. - */ -static int wl3501_get_flash_mac_addr(struct wl3501_card *this) -{ - int base_addr = this->base_addr; - - /* get MAC addr */ - wl3501_outb(WL3501_BSS_FPAGE3, base_addr + WL3501_NIC_BSS); /* BSS */ - wl3501_outb(0x00, base_addr + WL3501_NIC_LMAL); /* LMAL */ - wl3501_outb(0x40, base_addr + WL3501_NIC_LMAH); /* LMAH */ - - /* wait for reading EEPROM */ - WL3501_NOPLOOP(100); - this->mac_addr[0] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->mac_addr[1] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->mac_addr[2] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->mac_addr[3] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->mac_addr[4] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->mac_addr[5] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->reg_domain = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - wl3501_outb(WL3501_BSS_FPAGE0, base_addr + WL3501_NIC_BSS); - wl3501_outb(0x04, base_addr + WL3501_NIC_LMAL); - wl3501_outb(0x40, base_addr + WL3501_NIC_LMAH); - WL3501_NOPLOOP(100); - this->version[0] = inb(base_addr + WL3501_NIC_IODPA); - WL3501_NOPLOOP(100); - this->version[1] = inb(base_addr + WL3501_NIC_IODPA); - /* switch to SRAM Page 0 (for safety) */ - wl3501_switch_page(this, WL3501_BSS_SPAGE0); - - /* The MAC addr should be 00:60:... */ - return this->mac_addr[0] == 0x00 && this->mac_addr[1] == 0x60; -} - -/** - * wl3501_set_to_wla - Move 'size' bytes from PC to card - * @dest: Card addressing space - * @src: PC addressing space - * @size: Bytes to move - * - * Move 'size' bytes from PC to card. (Shouldn't be interrupted) - */ -static void wl3501_set_to_wla(struct wl3501_card *this, u16 dest, void *src, - int size) -{ - /* switch to SRAM Page 0 */ - wl3501_switch_page(this, (dest & 0x8000) ? WL3501_BSS_SPAGE1 : - WL3501_BSS_SPAGE0); - /* set LMAL and LMAH */ - wl3501_outb(dest & 0xff, this->base_addr + WL3501_NIC_LMAL); - wl3501_outb(((dest >> 8) & 0x7f), this->base_addr + WL3501_NIC_LMAH); - - /* rep out to Port A */ - wl3501_outsb(this->base_addr + WL3501_NIC_IODPA, src, size); -} - -/** - * wl3501_get_from_wla - Move 'size' bytes from card to PC - * @src: Card addressing space - * @dest: PC addressing space - * @size: Bytes to move - * - * Move 'size' bytes from card to PC. (Shouldn't be interrupted) - */ -static void wl3501_get_from_wla(struct wl3501_card *this, u16 src, void *dest, - int size) -{ - /* switch to SRAM Page 0 */ - wl3501_switch_page(this, (src & 0x8000) ? WL3501_BSS_SPAGE1 : - WL3501_BSS_SPAGE0); - /* set LMAL and LMAH */ - wl3501_outb(src & 0xff, this->base_addr + WL3501_NIC_LMAL); - wl3501_outb((src >> 8) & 0x7f, this->base_addr + WL3501_NIC_LMAH); - - /* rep get from Port A */ - insb(this->base_addr + WL3501_NIC_IODPA, dest, size); -} - -/* - * Get/Allocate a free Tx Data Buffer - * - * *--------------*-----------------*----------------------------------* - * | PLCP | MAC Header | DST SRC Data ... | - * | (24 bytes) | (30 bytes) | (6) (6) (Ethernet Row Data) | - * *--------------*-----------------*----------------------------------* - * \ \- IEEE 802.11 -/ \-------------- len --------------/ - * \-struct wl3501_80211_tx_hdr--/ \-------- Ethernet Frame -------/ - * - * Return = Postion in Card - */ -static u16 wl3501_get_tx_buffer(struct wl3501_card *this, u16 len) -{ - u16 next, blk_cnt = 0, zero = 0; - u16 full_len = sizeof(struct wl3501_80211_tx_hdr) + len; - u16 ret = 0; - - if (full_len > this->tx_buffer_cnt * 254) - goto out; - ret = this->tx_buffer_head; - while (full_len) { - if (full_len < 254) - full_len = 0; - else - full_len -= 254; - wl3501_get_from_wla(this, this->tx_buffer_head, &next, - sizeof(next)); - if (!full_len) - wl3501_set_to_wla(this, this->tx_buffer_head, &zero, - sizeof(zero)); - this->tx_buffer_head = next; - blk_cnt++; - /* if buffer is not enough */ - if (!next && full_len) { - this->tx_buffer_head = ret; - ret = 0; - goto out; - } - } - this->tx_buffer_cnt -= blk_cnt; -out: - return ret; -} - -/* - * Free an allocated Tx Buffer. ptr must be correct position. - */ -static void wl3501_free_tx_buffer(struct wl3501_card *this, u16 ptr) -{ - /* check if all space is not free */ - if (!this->tx_buffer_head) - this->tx_buffer_head = ptr; - else - wl3501_set_to_wla(this, this->tx_buffer_tail, - &ptr, sizeof(ptr)); - while (ptr) { - u16 next; - - this->tx_buffer_cnt++; - wl3501_get_from_wla(this, ptr, &next, sizeof(next)); - this->tx_buffer_tail = ptr; - ptr = next; - } -} - -static int wl3501_esbq_req_test(struct wl3501_card *this) -{ - u8 tmp; - - wl3501_get_from_wla(this, this->esbq_req_head + 3, &tmp, sizeof(tmp)); - return tmp & 0x80; -} - -static void wl3501_esbq_req(struct wl3501_card *this, u16 *ptr) -{ - u16 tmp = 0; - - wl3501_set_to_wla(this, this->esbq_req_head, ptr, 2); - wl3501_set_to_wla(this, this->esbq_req_head + 2, &tmp, sizeof(tmp)); - this->esbq_req_head += 4; - if (this->esbq_req_head >= this->esbq_req_end) - this->esbq_req_head = this->esbq_req_start; -} - -static int wl3501_esbq_exec(struct wl3501_card *this, void *sig, int sig_size) -{ - int rc = -EIO; - - if (wl3501_esbq_req_test(this)) { - u16 ptr = wl3501_get_tx_buffer(this, sig_size); - if (ptr) { - wl3501_set_to_wla(this, ptr, sig, sig_size); - wl3501_esbq_req(this, &ptr); - rc = 0; - } - } - return rc; -} - -static int wl3501_get_mib_value(struct wl3501_card *this, u8 index, - void *bf, int size) -{ - struct wl3501_get_req sig = { - .sig_id = WL3501_SIG_GET_REQ, - .mib_attrib = index, - }; - unsigned long flags; - int rc = -EIO; - - spin_lock_irqsave(&this->lock, flags); - if (wl3501_esbq_req_test(this)) { - u16 ptr = wl3501_get_tx_buffer(this, sizeof(sig)); - if (ptr) { - wl3501_set_to_wla(this, ptr, &sig, sizeof(sig)); - wl3501_esbq_req(this, &ptr); - this->sig_get_confirm.mib_status = 255; - spin_unlock_irqrestore(&this->lock, flags); - rc = wait_event_interruptible(this->wait, - this->sig_get_confirm.mib_status != 255); - if (!rc) - memcpy(bf, this->sig_get_confirm.mib_value, - size); - goto out; - } - } - spin_unlock_irqrestore(&this->lock, flags); -out: - return rc; -} - -static int wl3501_pwr_mgmt(struct wl3501_card *this, int suspend) -{ - struct wl3501_pwr_mgmt_req sig = { - .sig_id = WL3501_SIG_PWR_MGMT_REQ, - .pwr_save = suspend, - .wake_up = !suspend, - .receive_dtims = 10, - }; - unsigned long flags; - int rc = -EIO; - - spin_lock_irqsave(&this->lock, flags); - if (wl3501_esbq_req_test(this)) { - u16 ptr = wl3501_get_tx_buffer(this, sizeof(sig)); - if (ptr) { - wl3501_set_to_wla(this, ptr, &sig, sizeof(sig)); - wl3501_esbq_req(this, &ptr); - this->sig_pwr_mgmt_confirm.status = 255; - spin_unlock_irqrestore(&this->lock, flags); - rc = wait_event_interruptible(this->wait, - this->sig_pwr_mgmt_confirm.status != 255); - printk(KERN_INFO "%s: %s status=%d\n", __func__, - suspend ? "suspend" : "resume", - this->sig_pwr_mgmt_confirm.status); - goto out; - } - } - spin_unlock_irqrestore(&this->lock, flags); -out: - return rc; -} - -/** - * wl3501_send_pkt - Send a packet. - * @this - card - * - * Send a packet. - * - * data = Ethernet raw frame. (e.g. data[0] - data[5] is Dest MAC Addr, - * data[6] - data[11] is Src MAC Addr) - * Ref: IEEE 802.11 - */ -static int wl3501_send_pkt(struct wl3501_card *this, u8 *data, u16 len) -{ - u16 bf, sig_bf, next, tmplen, pktlen; - struct wl3501_md_req sig = { - .sig_id = WL3501_SIG_MD_REQ, - }; - u8 *pdata = (char *)data; - int rc = -EIO; - - if (wl3501_esbq_req_test(this)) { - sig_bf = wl3501_get_tx_buffer(this, sizeof(sig)); - rc = -ENOMEM; - if (!sig_bf) /* No free buffer available */ - goto out; - bf = wl3501_get_tx_buffer(this, len + 26 + 24); - if (!bf) { - /* No free buffer available */ - wl3501_free_tx_buffer(this, sig_bf); - goto out; - } - rc = 0; - memcpy(&sig.daddr[0], pdata, 12); - pktlen = len - 12; - pdata += 12; - sig.data = bf; - if (((*pdata) * 256 + (*(pdata + 1))) > 1500) { - u8 addr4[ETH_ALEN] = { - [0] = 0xAA, [1] = 0xAA, [2] = 0x03, [4] = 0x00, - }; - - wl3501_set_to_wla(this, bf + 2 + - offsetof(struct wl3501_tx_hdr, addr4), - addr4, sizeof(addr4)); - sig.size = pktlen + 24 + 4 + 6; - if (pktlen > (254 - sizeof(struct wl3501_tx_hdr))) { - tmplen = 254 - sizeof(struct wl3501_tx_hdr); - pktlen -= tmplen; - } else { - tmplen = pktlen; - pktlen = 0; - } - wl3501_set_to_wla(this, - bf + 2 + sizeof(struct wl3501_tx_hdr), - pdata, tmplen); - pdata += tmplen; - wl3501_get_from_wla(this, bf, &next, sizeof(next)); - bf = next; - } else { - sig.size = pktlen + 24 + 4 - 2; - pdata += 2; - pktlen -= 2; - if (pktlen > (254 - sizeof(struct wl3501_tx_hdr) + 6)) { - tmplen = 254 - sizeof(struct wl3501_tx_hdr) + 6; - pktlen -= tmplen; - } else { - tmplen = pktlen; - pktlen = 0; - } - wl3501_set_to_wla(this, bf + 2 + - offsetof(struct wl3501_tx_hdr, addr4), - pdata, tmplen); - pdata += tmplen; - wl3501_get_from_wla(this, bf, &next, sizeof(next)); - bf = next; - } - while (pktlen > 0) { - if (pktlen > 254) { - tmplen = 254; - pktlen -= 254; - } else { - tmplen = pktlen; - pktlen = 0; - } - wl3501_set_to_wla(this, bf + 2, pdata, tmplen); - pdata += tmplen; - wl3501_get_from_wla(this, bf, &next, sizeof(next)); - bf = next; - } - wl3501_set_to_wla(this, sig_bf, &sig, sizeof(sig)); - wl3501_esbq_req(this, &sig_bf); - } -out: - return rc; -} - -static int wl3501_mgmt_resync(struct wl3501_card *this) -{ - struct wl3501_resync_req sig = { - .sig_id = WL3501_SIG_RESYNC_REQ, - }; - - return wl3501_esbq_exec(this, &sig, sizeof(sig)); -} - -static inline int wl3501_fw_bss_type(struct wl3501_card *this) -{ - return this->net_type == IW_MODE_INFRA ? WL3501_NET_TYPE_INFRA : - WL3501_NET_TYPE_ADHOC; -} - -static inline int wl3501_fw_cap_info(struct wl3501_card *this) -{ - return this->net_type == IW_MODE_INFRA ? WL3501_MGMT_CAPABILITY_ESS : - WL3501_MGMT_CAPABILITY_IBSS; -} - -static int wl3501_mgmt_scan(struct wl3501_card *this, u16 chan_time) -{ - struct wl3501_scan_req sig = { - .sig_id = WL3501_SIG_SCAN_REQ, - .scan_type = WL3501_SCAN_TYPE_ACTIVE, - .probe_delay = 0x10, - .min_chan_time = chan_time, - .max_chan_time = chan_time, - .bss_type = wl3501_fw_bss_type(this), - }; - - this->bss_cnt = this->join_sta_bss = 0; - return wl3501_esbq_exec(this, &sig, sizeof(sig)); -} - -static int wl3501_mgmt_join(struct wl3501_card *this, u16 stas) -{ - struct wl3501_join_req sig = { - .sig_id = WL3501_SIG_JOIN_REQ, - .timeout = 10, - .ds_pset = { - .el = { - .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, - .len = 1, - }, - .chan = this->chan, - }, - }; - - memcpy(&sig.beacon_period, &this->bss_set[stas].beacon_period, 72); - return wl3501_esbq_exec(this, &sig, sizeof(sig)); -} - -static int wl3501_mgmt_start(struct wl3501_card *this) -{ - struct wl3501_start_req sig = { - .sig_id = WL3501_SIG_START_REQ, - .beacon_period = 400, - .dtim_period = 1, - .ds_pset = { - .el = { - .id = IW_MGMT_INFO_ELEMENT_DS_PARAMETER_SET, - .len = 1, - }, - .chan = this->chan, - }, - .bss_basic_rset = { - .el = { - .id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, - .len = 2, - }, - .data_rate_labels = { - [0] = IW_MGMT_RATE_LABEL_MANDATORY | - IW_MGMT_RATE_LABEL_1MBIT, - [1] = IW_MGMT_RATE_LABEL_MANDATORY | - IW_MGMT_RATE_LABEL_2MBIT, - }, - }, - .operational_rset = { - .el = { - .id = IW_MGMT_INFO_ELEMENT_SUPPORTED_RATES, - .len = 2, - }, - .data_rate_labels = { - [0] = IW_MGMT_RATE_LABEL_MANDATORY | - IW_MGMT_RATE_LABEL_1MBIT, - [1] = IW_MGMT_RATE_LABEL_MANDATORY | - IW_MGMT_RATE_LABEL_2MBIT, - }, - }, - .ibss_pset = { - .el = { - .id = IW_MGMT_INFO_ELEMENT_IBSS_PARAMETER_SET, - .len = 2, - }, - .atim_window = 10, - }, - .bss_type = wl3501_fw_bss_type(this), - .cap_info = wl3501_fw_cap_info(this), - }; - - iw_copy_mgmt_info_element(&sig.ssid.el, &this->essid.el); - iw_copy_mgmt_info_element(&this->keep_essid.el, &this->essid.el); - return wl3501_esbq_exec(this, &sig, sizeof(sig)); -} - -static void wl3501_mgmt_scan_confirm(struct wl3501_card *this, u16 addr) -{ - u16 i = 0; - int matchflag = 0; - struct wl3501_scan_confirm sig; - - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - if (sig.status == WL3501_STATUS_SUCCESS) { - dprintk(3, "success"); - if ((this->net_type == IW_MODE_INFRA && - (sig.cap_info & WL3501_MGMT_CAPABILITY_ESS)) || - (this->net_type == IW_MODE_ADHOC && - (sig.cap_info & WL3501_MGMT_CAPABILITY_IBSS)) || - this->net_type == IW_MODE_AUTO) { - if (!this->essid.el.len) - matchflag = 1; - else if (this->essid.el.len == 3 && - !memcmp(this->essid.essid, "ANY", 3)) - matchflag = 1; - else if (this->essid.el.len != sig.ssid.el.len) - matchflag = 0; - else if (memcmp(this->essid.essid, sig.ssid.essid, - this->essid.el.len)) - matchflag = 0; - else - matchflag = 1; - if (matchflag) { - for (i = 0; i < this->bss_cnt; i++) { - if (!memcmp(this->bss_set[i].bssid, - sig.bssid, ETH_ALEN)) { - matchflag = 0; - break; - } - } - } - if (matchflag && (i < 20)) { - memcpy(&this->bss_set[i].beacon_period, - &sig.beacon_period, 73); - this->bss_cnt++; - this->rssi = sig.rssi; - } - } - } else if (sig.status == WL3501_STATUS_TIMEOUT) { - dprintk(3, "timeout"); - this->join_sta_bss = 0; - for (i = this->join_sta_bss; i < this->bss_cnt; i++) - if (!wl3501_mgmt_join(this, i)) - break; - this->join_sta_bss = i; - if (this->join_sta_bss == this->bss_cnt) { - if (this->net_type == IW_MODE_INFRA) - wl3501_mgmt_scan(this, 100); - else { - this->adhoc_times++; - if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES) - wl3501_mgmt_start(this); - else - wl3501_mgmt_scan(this, 100); - } - } - } -} - -/** - * wl3501_block_interrupt - Mask interrupt from SUTRO - * @this - card - * - * Mask interrupt from SUTRO. (i.e. SUTRO cannot interrupt the HOST) - * Return: 1 if interrupt is originally enabled - */ -static int wl3501_block_interrupt(struct wl3501_card *this) -{ - u8 old = inb(this->base_addr + WL3501_NIC_GCR); - u8 new = old & (~(WL3501_GCR_ECINT | WL3501_GCR_INT2EC | - WL3501_GCR_ENECINT)); - - wl3501_outb(new, this->base_addr + WL3501_NIC_GCR); - return old & WL3501_GCR_ENECINT; -} - -/** - * wl3501_unblock_interrupt - Enable interrupt from SUTRO - * @this - card - * - * Enable interrupt from SUTRO. (i.e. SUTRO can interrupt the HOST) - * Return: 1 if interrupt is originally enabled - */ -static int wl3501_unblock_interrupt(struct wl3501_card *this) -{ - u8 old = inb(this->base_addr + WL3501_NIC_GCR); - u8 new = (old & ~(WL3501_GCR_ECINT | WL3501_GCR_INT2EC)) | - WL3501_GCR_ENECINT; - - wl3501_outb(new, this->base_addr + WL3501_NIC_GCR); - return old & WL3501_GCR_ENECINT; -} - -/** - * wl3501_receive - Receive data from Receive Queue. - * - * Receive data from Receive Queue. - * - * @this: card - * @bf: address of host - * @size: size of buffer. - */ -static u16 wl3501_receive(struct wl3501_card *this, u8 *bf, u16 size) -{ - u16 next_addr, next_addr1; - u8 *data = bf + 12; - - size -= 12; - wl3501_get_from_wla(this, this->start_seg + 2, - &next_addr, sizeof(next_addr)); - if (size > WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr)) { - wl3501_get_from_wla(this, - this->start_seg + - sizeof(struct wl3501_rx_hdr), data, - WL3501_BLKSZ - - sizeof(struct wl3501_rx_hdr)); - size -= WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr); - data += WL3501_BLKSZ - sizeof(struct wl3501_rx_hdr); - } else { - wl3501_get_from_wla(this, - this->start_seg + - sizeof(struct wl3501_rx_hdr), - data, size); - size = 0; - } - while (size > 0) { - if (size > WL3501_BLKSZ - 5) { - wl3501_get_from_wla(this, next_addr + 5, data, - WL3501_BLKSZ - 5); - size -= WL3501_BLKSZ - 5; - data += WL3501_BLKSZ - 5; - wl3501_get_from_wla(this, next_addr + 2, &next_addr1, - sizeof(next_addr1)); - next_addr = next_addr1; - } else { - wl3501_get_from_wla(this, next_addr + 5, data, size); - size = 0; - } - } - return 0; -} - -static void wl3501_esbq_req_free(struct wl3501_card *this) -{ - u8 tmp; - u16 addr; - - if (this->esbq_req_head == this->esbq_req_tail) - goto out; - wl3501_get_from_wla(this, this->esbq_req_tail + 3, &tmp, sizeof(tmp)); - if (!(tmp & 0x80)) - goto out; - wl3501_get_from_wla(this, this->esbq_req_tail, &addr, sizeof(addr)); - wl3501_free_tx_buffer(this, addr); - this->esbq_req_tail += 4; - if (this->esbq_req_tail >= this->esbq_req_end) - this->esbq_req_tail = this->esbq_req_start; -out: - return; -} - -static int wl3501_esbq_confirm(struct wl3501_card *this) -{ - u8 tmp; - - wl3501_get_from_wla(this, this->esbq_confirm + 3, &tmp, sizeof(tmp)); - return tmp & 0x80; -} - -static void wl3501_online(struct net_device *dev) -{ - struct wl3501_card *this = netdev_priv(dev); - - printk(KERN_INFO "%s: Wireless LAN online. BSSID: %pM\n", - dev->name, this->bssid); - netif_wake_queue(dev); -} - -static void wl3501_esbq_confirm_done(struct wl3501_card *this) -{ - u8 tmp = 0; - - wl3501_set_to_wla(this, this->esbq_confirm + 3, &tmp, sizeof(tmp)); - this->esbq_confirm += 4; - if (this->esbq_confirm >= this->esbq_confirm_end) - this->esbq_confirm = this->esbq_confirm_start; -} - -static int wl3501_mgmt_auth(struct wl3501_card *this) -{ - struct wl3501_auth_req sig = { - .sig_id = WL3501_SIG_AUTH_REQ, - .type = WL3501_SYS_TYPE_OPEN, - .timeout = 1000, - }; - - dprintk(3, "entry"); - memcpy(sig.mac_addr, this->bssid, ETH_ALEN); - return wl3501_esbq_exec(this, &sig, sizeof(sig)); -} - -static int wl3501_mgmt_association(struct wl3501_card *this) -{ - struct wl3501_assoc_req sig = { - .sig_id = WL3501_SIG_ASSOC_REQ, - .timeout = 1000, - .listen_interval = 5, - .cap_info = this->cap_info, - }; - - dprintk(3, "entry"); - memcpy(sig.mac_addr, this->bssid, ETH_ALEN); - return wl3501_esbq_exec(this, &sig, sizeof(sig)); -} - -static void wl3501_mgmt_join_confirm(struct net_device *dev, u16 addr) -{ - struct wl3501_card *this = netdev_priv(dev); - struct wl3501_join_confirm sig; - - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - if (sig.status == WL3501_STATUS_SUCCESS) { - if (this->net_type == IW_MODE_INFRA) { - if (this->join_sta_bss < this->bss_cnt) { - const int i = this->join_sta_bss; - memcpy(this->bssid, - this->bss_set[i].bssid, ETH_ALEN); - this->chan = this->bss_set[i].ds_pset.chan; - iw_copy_mgmt_info_element(&this->keep_essid.el, - &this->bss_set[i].ssid.el); - wl3501_mgmt_auth(this); - } - } else { - const int i = this->join_sta_bss; - - memcpy(&this->bssid, &this->bss_set[i].bssid, ETH_ALEN); - this->chan = this->bss_set[i].ds_pset.chan; - iw_copy_mgmt_info_element(&this->keep_essid.el, - &this->bss_set[i].ssid.el); - wl3501_online(dev); - } - } else { - int i; - this->join_sta_bss++; - for (i = this->join_sta_bss; i < this->bss_cnt; i++) - if (!wl3501_mgmt_join(this, i)) - break; - this->join_sta_bss = i; - if (this->join_sta_bss == this->bss_cnt) { - if (this->net_type == IW_MODE_INFRA) - wl3501_mgmt_scan(this, 100); - else { - this->adhoc_times++; - if (this->adhoc_times > WL3501_MAX_ADHOC_TRIES) - wl3501_mgmt_start(this); - else - wl3501_mgmt_scan(this, 100); - } - } - } -} - -static inline void wl3501_alarm_interrupt(struct net_device *dev, - struct wl3501_card *this) -{ - if (this->net_type == IW_MODE_INFRA) { - printk(KERN_INFO "Wireless LAN offline\n"); - netif_stop_queue(dev); - wl3501_mgmt_resync(this); - } -} - -static inline void wl3501_md_confirm_interrupt(struct net_device *dev, - struct wl3501_card *this, - u16 addr) -{ - struct wl3501_md_confirm sig; - - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - wl3501_free_tx_buffer(this, sig.data); - if (netif_queue_stopped(dev)) - netif_wake_queue(dev); -} - -static inline void wl3501_md_ind_interrupt(struct net_device *dev, - struct wl3501_card *this, u16 addr) -{ - struct wl3501_md_ind sig; - struct sk_buff *skb; - u8 rssi, addr4[ETH_ALEN]; - u16 pkt_len; - - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - this->start_seg = sig.data; - wl3501_get_from_wla(this, - sig.data + offsetof(struct wl3501_rx_hdr, rssi), - &rssi, sizeof(rssi)); - this->rssi = rssi <= 63 ? (rssi * 100) / 64 : 255; - - wl3501_get_from_wla(this, - sig.data + - offsetof(struct wl3501_rx_hdr, addr4), - &addr4, sizeof(addr4)); - if (!(addr4[0] == 0xAA && addr4[1] == 0xAA && - addr4[2] == 0x03 && addr4[4] == 0x00)) { - printk(KERN_INFO "Insupported packet type!\n"); - return; - } - pkt_len = sig.size + 12 - 24 - 4 - 6; - - skb = dev_alloc_skb(pkt_len + 5); - - if (!skb) { - printk(KERN_WARNING "%s: Can't alloc a sk_buff of size %d.\n", - dev->name, pkt_len); - dev->stats.rx_dropped++; - } else { - skb->dev = dev; - skb_reserve(skb, 2); /* IP headers on 16 bytes boundaries */ - skb_copy_to_linear_data(skb, (unsigned char *)&sig.daddr, 12); - wl3501_receive(this, skb->data, pkt_len); - skb_put(skb, pkt_len); - skb->protocol = eth_type_trans(skb, dev); - dev->stats.rx_packets++; - dev->stats.rx_bytes += skb->len; - netif_rx(skb); - } -} - -static inline void wl3501_get_confirm_interrupt(struct wl3501_card *this, - u16 addr, void *sig, int size) -{ - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &this->sig_get_confirm, - sizeof(this->sig_get_confirm)); - wake_up(&this->wait); -} - -static inline void wl3501_start_confirm_interrupt(struct net_device *dev, - struct wl3501_card *this, - u16 addr) -{ - struct wl3501_start_confirm sig; - - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - if (sig.status == WL3501_STATUS_SUCCESS) - netif_wake_queue(dev); -} - -static inline void wl3501_assoc_confirm_interrupt(struct net_device *dev, - u16 addr) -{ - struct wl3501_card *this = netdev_priv(dev); - struct wl3501_assoc_confirm sig; - - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - - if (sig.status == WL3501_STATUS_SUCCESS) - wl3501_online(dev); -} - -static inline void wl3501_auth_confirm_interrupt(struct wl3501_card *this, - u16 addr) -{ - struct wl3501_auth_confirm sig; - - dprintk(3, "entry"); - wl3501_get_from_wla(this, addr, &sig, sizeof(sig)); - - if (sig.status == WL3501_STATUS_SUCCESS) - wl3501_mgmt_association(this); - else - wl3501_mgmt_resync(this); -} - -static inline void wl3501_rx_interrupt(struct net_device *dev) -{ - int morepkts; - u16 addr; - u8 sig_id; - struct wl3501_card *this = netdev_priv(dev); - - dprintk(3, "entry"); -loop: - morepkts = 0; - if (!wl3501_esbq_confirm(this)) - goto free; - wl3501_get_from_wla(this, this->esbq_confirm, &addr, sizeof(addr)); - wl3501_get_from_wla(this, addr + 2, &sig_id, sizeof(sig_id)); - - switch (sig_id) { - case WL3501_SIG_DEAUTH_IND: - case WL3501_SIG_DISASSOC_IND: - case WL3501_SIG_ALARM: - wl3501_alarm_interrupt(dev, this); - break; - case WL3501_SIG_MD_CONFIRM: - wl3501_md_confirm_interrupt(dev, this, addr); - break; - case WL3501_SIG_MD_IND: - wl3501_md_ind_interrupt(dev, this, addr); - break; - case WL3501_SIG_GET_CONFIRM: - wl3501_get_confirm_interrupt(this, addr, - &this->sig_get_confirm, - sizeof(this->sig_get_confirm)); - break; - case WL3501_SIG_PWR_MGMT_CONFIRM: - wl3501_get_confirm_interrupt(this, addr, - &this->sig_pwr_mgmt_confirm, - sizeof(this->sig_pwr_mgmt_confirm)); - break; - case WL3501_SIG_START_CONFIRM: - wl3501_start_confirm_interrupt(dev, this, addr); - break; - case WL3501_SIG_SCAN_CONFIRM: - wl3501_mgmt_scan_confirm(this, addr); - break; - case WL3501_SIG_JOIN_CONFIRM: - wl3501_mgmt_join_confirm(dev, addr); - break; - case WL3501_SIG_ASSOC_CONFIRM: - wl3501_assoc_confirm_interrupt(dev, addr); - break; - case WL3501_SIG_AUTH_CONFIRM: - wl3501_auth_confirm_interrupt(this, addr); - break; - case WL3501_SIG_RESYNC_CONFIRM: - wl3501_mgmt_resync(this); /* FIXME: should be resync_confirm */ - break; - } - wl3501_esbq_confirm_done(this); - morepkts = 1; - /* free request if necessary */ -free: - wl3501_esbq_req_free(this); - if (morepkts) - goto loop; -} - -static inline void wl3501_ack_interrupt(struct wl3501_card *this) -{ - wl3501_outb(WL3501_GCR_ECINT, this->base_addr + WL3501_NIC_GCR); -} - -/** - * wl3501_interrupt - Hardware interrupt from card. - * @irq - Interrupt number - * @dev_id - net_device - * - * We must acknowledge the interrupt as soon as possible, and block the - * interrupt from the same card immediately to prevent re-entry. - * - * Before accessing the Control_Status_Block, we must lock SUTRO first. - * On the other hand, to prevent SUTRO from malfunctioning, we must - * unlock the SUTRO as soon as possible. - */ -static irqreturn_t wl3501_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - struct wl3501_card *this; - - this = netdev_priv(dev); - spin_lock(&this->lock); - wl3501_ack_interrupt(this); - wl3501_block_interrupt(this); - wl3501_rx_interrupt(dev); - wl3501_unblock_interrupt(this); - spin_unlock(&this->lock); - - return IRQ_HANDLED; -} - -static int wl3501_reset_board(struct wl3501_card *this) -{ - u8 tmp = 0; - int i, rc = 0; - - /* Coreset */ - wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR); - wl3501_outb_p(0, this->base_addr + WL3501_NIC_GCR); - wl3501_outb_p(WL3501_GCR_CORESET, this->base_addr + WL3501_NIC_GCR); - - /* Reset SRAM 0x480 to zero */ - wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp)); - - /* Start up */ - wl3501_outb_p(0, this->base_addr + WL3501_NIC_GCR); - - WL3501_NOPLOOP(1024 * 50); - - wl3501_unblock_interrupt(this); /* acme: was commented */ - - /* Polling Self_Test_Status */ - for (i = 0; i < 10000; i++) { - wl3501_get_from_wla(this, 0x480, &tmp, sizeof(tmp)); - - if (tmp == 'W') { - /* firmware complete all test successfully */ - tmp = 'A'; - wl3501_set_to_wla(this, 0x480, &tmp, sizeof(tmp)); - goto out; - } - WL3501_NOPLOOP(10); - } - printk(KERN_WARNING "%s: failed to reset the board!\n", __func__); - rc = -ENODEV; -out: - return rc; -} - -static int wl3501_init_firmware(struct wl3501_card *this) -{ - u16 ptr, next; - int rc = wl3501_reset_board(this); - - if (rc) - goto fail; - this->card_name[0] = '\0'; - wl3501_get_from_wla(this, 0x1a00, - this->card_name, sizeof(this->card_name)); - this->card_name[sizeof(this->card_name) - 1] = '\0'; - this->firmware_date[0] = '\0'; - wl3501_get_from_wla(this, 0x1a40, - this->firmware_date, sizeof(this->firmware_date)); - this->firmware_date[sizeof(this->firmware_date) - 1] = '\0'; - /* Switch to SRAM Page 0 */ - wl3501_switch_page(this, WL3501_BSS_SPAGE0); - /* Read parameter from card */ - wl3501_get_from_wla(this, 0x482, &this->esbq_req_start, 2); - wl3501_get_from_wla(this, 0x486, &this->esbq_req_end, 2); - wl3501_get_from_wla(this, 0x488, &this->esbq_confirm_start, 2); - wl3501_get_from_wla(this, 0x48c, &this->esbq_confirm_end, 2); - wl3501_get_from_wla(this, 0x48e, &this->tx_buffer_head, 2); - wl3501_get_from_wla(this, 0x492, &this->tx_buffer_size, 2); - this->esbq_req_tail = this->esbq_req_head = this->esbq_req_start; - this->esbq_req_end += this->esbq_req_start; - this->esbq_confirm = this->esbq_confirm_start; - this->esbq_confirm_end += this->esbq_confirm_start; - /* Initial Tx Buffer */ - this->tx_buffer_cnt = 1; - ptr = this->tx_buffer_head; - next = ptr + WL3501_BLKSZ; - while ((next - this->tx_buffer_head) < this->tx_buffer_size) { - this->tx_buffer_cnt++; - wl3501_set_to_wla(this, ptr, &next, sizeof(next)); - ptr = next; - next = ptr + WL3501_BLKSZ; - } - rc = 0; - next = 0; - wl3501_set_to_wla(this, ptr, &next, sizeof(next)); - this->tx_buffer_tail = ptr; -out: - return rc; -fail: - printk(KERN_WARNING "%s: failed!\n", __func__); - goto out; -} - -static int wl3501_close(struct net_device *dev) -{ - struct wl3501_card *this = netdev_priv(dev); - int rc = -ENODEV; - unsigned long flags; - struct pcmcia_device *link; - link = this->p_dev; - - spin_lock_irqsave(&this->lock, flags); - link->open--; - - /* Stop wl3501_hard_start_xmit() from now on */ - netif_stop_queue(dev); - wl3501_ack_interrupt(this); - - /* Mask interrupts from the SUTRO */ - wl3501_block_interrupt(this); - - rc = 0; - printk(KERN_INFO "%s: WL3501 closed\n", dev->name); - spin_unlock_irqrestore(&this->lock, flags); - return rc; -} - -/** - * wl3501_reset - Reset the SUTRO. - * @dev - network device - * - * It is almost the same as wl3501_open(). In fact, we may just wl3501_close() - * and wl3501_open() again, but I wouldn't like to free_irq() when the driver - * is running. It seems to be dangerous. - */ -static int wl3501_reset(struct net_device *dev) -{ - struct wl3501_card *this = netdev_priv(dev); - int rc = -ENODEV; - - wl3501_block_interrupt(this); - - if (wl3501_init_firmware(this)) { - printk(KERN_WARNING "%s: Can't initialize Firmware!\n", - dev->name); - /* Free IRQ, and mark IRQ as unused */ - free_irq(dev->irq, dev); - goto out; - } - - /* - * Queue has to be started only when the Card is Started - */ - netif_stop_queue(dev); - this->adhoc_times = 0; - wl3501_ack_interrupt(this); - wl3501_unblock_interrupt(this); - wl3501_mgmt_scan(this, 100); - dprintk(1, "%s: device reset", dev->name); - rc = 0; -out: - return rc; -} - -static void wl3501_tx_timeout(struct net_device *dev) -{ - struct wl3501_card *this = netdev_priv(dev); - struct net_device_stats *stats = &dev->stats; - unsigned long flags; - int rc; - - stats->tx_errors++; - spin_lock_irqsave(&this->lock, flags); - rc = wl3501_reset(dev); - spin_unlock_irqrestore(&this->lock, flags); - if (rc) - printk(KERN_ERR "%s: Error %d resetting card on Tx timeout!\n", - dev->name, rc); - else { - dev->trans_start = jiffies; - netif_wake_queue(dev); - } -} - -/* - * Return : 0 - OK - * 1 - Could not transmit (dev_queue_xmit will queue it) - * and try to sent it later - */ -static netdev_tx_t wl3501_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - int enabled, rc; - struct wl3501_card *this = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&this->lock, flags); - enabled = wl3501_block_interrupt(this); - dev->trans_start = jiffies; - rc = wl3501_send_pkt(this, skb->data, skb->len); - if (enabled) - wl3501_unblock_interrupt(this); - if (rc) { - ++dev->stats.tx_dropped; - netif_stop_queue(dev); - } else { - ++dev->stats.tx_packets; - dev->stats.tx_bytes += skb->len; - kfree_skb(skb); - - if (this->tx_buffer_cnt < 2) - netif_stop_queue(dev); - } - spin_unlock_irqrestore(&this->lock, flags); - return NETDEV_TX_OK; -} - -static int wl3501_open(struct net_device *dev) -{ - int rc = -ENODEV; - struct wl3501_card *this = netdev_priv(dev); - unsigned long flags; - struct pcmcia_device *link; - link = this->p_dev; - - spin_lock_irqsave(&this->lock, flags); - if (!pcmcia_dev_present(link)) - goto out; - netif_device_attach(dev); - link->open++; - - /* Initial WL3501 firmware */ - dprintk(1, "%s: Initialize WL3501 firmware...", dev->name); - if (wl3501_init_firmware(this)) - goto fail; - /* Initial device variables */ - this->adhoc_times = 0; - /* Acknowledge Interrupt, for cleaning last state */ - wl3501_ack_interrupt(this); - - /* Enable interrupt from card after all */ - wl3501_unblock_interrupt(this); - wl3501_mgmt_scan(this, 100); - rc = 0; - dprintk(1, "%s: WL3501 opened", dev->name); - printk(KERN_INFO "%s: Card Name: %s\n" - "%s: Firmware Date: %s\n", - dev->name, this->card_name, - dev->name, this->firmware_date); -out: - spin_unlock_irqrestore(&this->lock, flags); - return rc; -fail: - printk(KERN_WARNING "%s: Can't initialize firmware!\n", dev->name); - goto out; -} - -static struct iw_statistics *wl3501_get_wireless_stats(struct net_device *dev) -{ - struct wl3501_card *this = netdev_priv(dev); - struct iw_statistics *wstats = &this->wstats; - u32 value; /* size checked: it is u32 */ - - memset(wstats, 0, sizeof(*wstats)); - wstats->status = netif_running(dev); - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_ICV_ERROR_COUNT, - &value, sizeof(value))) - wstats->discard.code += value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_UNDECRYPTABLE_COUNT, - &value, sizeof(value))) - wstats->discard.code += value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_EXCLUDED_COUNT, - &value, sizeof(value))) - wstats->discard.code += value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_RETRY_COUNT, - &value, sizeof(value))) - wstats->discard.retries = value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_FAILED_COUNT, - &value, sizeof(value))) - wstats->discard.misc += value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_RTS_FAILURE_COUNT, - &value, sizeof(value))) - wstats->discard.misc += value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_ACK_FAILURE_COUNT, - &value, sizeof(value))) - wstats->discard.misc += value; - if (!wl3501_get_mib_value(this, WL3501_MIB_ATTR_FRAME_DUPLICATE_COUNT, - &value, sizeof(value))) - wstats->discard.misc += value; - return wstats; -} - -static void wl3501_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - strlcpy(info->driver, wl3501_dev_info, sizeof(info->driver)); -} - -static const struct ethtool_ops ops = { - .get_drvinfo = wl3501_get_drvinfo -}; - -/** - * wl3501_detach - deletes a driver "instance" - * @link - FILL_IN - * - * This deletes a driver "instance". The device is de-registered with Card - * Services. If it has been released, all local data structures are freed. - * Otherwise, the structures will be freed when the device is released. - */ -static void wl3501_detach(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - /* If the device is currently configured and active, we won't actually - * delete it yet. Instead, it is marked so that when the release() - * function is called, that will trigger a proper detach(). */ - - while (link->open > 0) - wl3501_close(dev); - - netif_device_detach(dev); - wl3501_release(link); - - if (link->priv) - free_netdev(link->priv); - - return; -} - -static int wl3501_get_name(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - strlcpy(wrqu->name, "IEEE 802.11-DS", sizeof(wrqu->name)); - return 0; -} - -static int wl3501_set_freq(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - int channel = wrqu->freq.m; - int rc = -EINVAL; - - if (iw_valid_channel(this->reg_domain, channel)) { - this->chan = channel; - rc = wl3501_reset(dev); - } - return rc; -} - -static int wl3501_get_freq(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - wrqu->freq.m = ieee80211_dsss_chan_to_freq(this->chan) * 100000; - wrqu->freq.e = 1; - return 0; -} - -static int wl3501_set_mode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - int rc = -EINVAL; - - if (wrqu->mode == IW_MODE_INFRA || - wrqu->mode == IW_MODE_ADHOC || - wrqu->mode == IW_MODE_AUTO) { - struct wl3501_card *this = netdev_priv(dev); - - this->net_type = wrqu->mode; - rc = wl3501_reset(dev); - } - return rc; -} - -static int wl3501_get_mode(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - wrqu->mode = this->net_type; - return 0; -} - -static int wl3501_get_sens(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - wrqu->sens.value = this->rssi; - wrqu->sens.disabled = !wrqu->sens.value; - wrqu->sens.fixed = 1; - return 0; -} - -static int wl3501_get_range(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - - /* Set the length (very important for backward compatibility) */ - wrqu->data.length = sizeof(*range); - - /* Set all the info we don't care or don't know about to zero */ - memset(range, 0, sizeof(*range)); - - /* Set the Wireless Extension versions */ - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = 1; - range->throughput = 2 * 1000 * 1000; /* ~2 Mb/s */ - /* FIXME: study the code to fill in more fields... */ - return 0; -} - -static int wl3501_set_wap(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - static const u8 bcast[ETH_ALEN] = { 255, 255, 255, 255, 255, 255 }; - int rc = -EINVAL; - - /* FIXME: we support other ARPHRDs...*/ - if (wrqu->ap_addr.sa_family != ARPHRD_ETHER) - goto out; - if (!memcmp(bcast, wrqu->ap_addr.sa_data, ETH_ALEN)) { - /* FIXME: rescan? */ - } else - memcpy(this->bssid, wrqu->ap_addr.sa_data, ETH_ALEN); - /* FIXME: rescan? deassoc & scan? */ - rc = 0; -out: - return rc; -} - -static int wl3501_get_wap(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - wrqu->ap_addr.sa_family = ARPHRD_ETHER; - memcpy(wrqu->ap_addr.sa_data, this->bssid, ETH_ALEN); - return 0; -} - -static int wl3501_set_scan(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * FIXME: trigger scanning with a reset, yes, I'm lazy - */ - return wl3501_reset(dev); -} - -static int wl3501_get_scan(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - int i; - char *current_ev = extra; - struct iw_event iwe; - - for (i = 0; i < this->bss_cnt; ++i) { - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, this->bss_set[i].bssid, ETH_ALEN); - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_ADDR_LEN); - iwe.cmd = SIOCGIWESSID; - iwe.u.data.flags = 1; - iwe.u.data.length = this->bss_set[i].ssid.el.len; - current_ev = iwe_stream_add_point(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, - this->bss_set[i].ssid.essid); - iwe.cmd = SIOCGIWMODE; - iwe.u.mode = this->bss_set[i].bss_type; - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_UINT_LEN); - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = this->bss_set[i].ds_pset.chan; - iwe.u.freq.e = 0; - current_ev = iwe_stream_add_event(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, IW_EV_FREQ_LEN); - iwe.cmd = SIOCGIWENCODE; - if (this->bss_set[i].cap_info & WL3501_MGMT_CAPABILITY_PRIVACY) - iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - iwe.u.data.length = 0; - current_ev = iwe_stream_add_point(info, current_ev, - extra + IW_SCAN_MAX_DATA, - &iwe, NULL); - } - /* Length of data */ - wrqu->data.length = (current_ev - extra); - wrqu->data.flags = 0; /* FIXME: set properly these flags */ - return 0; -} - -static int wl3501_set_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - if (wrqu->data.flags) { - iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID, - &this->essid.el, - extra, wrqu->data.length); - } else { /* We accept any ESSID */ - iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID, - &this->essid.el, "ANY", 3); - } - return wl3501_reset(dev); -} - -static int wl3501_get_essid(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&this->lock, flags); - wrqu->essid.flags = 1; - wrqu->essid.length = this->essid.el.len; - memcpy(extra, this->essid.essid, this->essid.el.len); - spin_unlock_irqrestore(&this->lock, flags); - return 0; -} - -static int wl3501_set_nick(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - if (wrqu->data.length > sizeof(this->nick)) - return -E2BIG; - strlcpy(this->nick, extra, wrqu->data.length); - return 0; -} - -static int wl3501_get_nick(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - struct wl3501_card *this = netdev_priv(dev); - - strlcpy(extra, this->nick, 32); - wrqu->data.length = strlen(extra); - return 0; -} - -static int wl3501_get_rate(struct net_device *dev, struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - /* - * FIXME: have to see from where to get this info, perhaps this card - * works at 1 Mbit/s too... for now leave at 2 Mbit/s that is the most - * common with the Planet Access Points. -acme - */ - wrqu->bitrate.value = 2000000; - wrqu->bitrate.fixed = 1; - return 0; -} - -static int wl3501_get_rts_threshold(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u16 threshold; /* size checked: it is u16 */ - struct wl3501_card *this = netdev_priv(dev); - int rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_RTS_THRESHOLD, - &threshold, sizeof(threshold)); - if (!rc) { - wrqu->rts.value = threshold; - wrqu->rts.disabled = threshold >= 2347; - wrqu->rts.fixed = 1; - } - return rc; -} - -static int wl3501_get_frag_threshold(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u16 threshold; /* size checked: it is u16 */ - struct wl3501_card *this = netdev_priv(dev); - int rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_FRAG_THRESHOLD, - &threshold, sizeof(threshold)); - if (!rc) { - wrqu->frag.value = threshold; - wrqu->frag.disabled = threshold >= 2346; - wrqu->frag.fixed = 1; - } - return rc; -} - -static int wl3501_get_txpow(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u16 txpow; - struct wl3501_card *this = netdev_priv(dev); - int rc = wl3501_get_mib_value(this, - WL3501_MIB_ATTR_CURRENT_TX_PWR_LEVEL, - &txpow, sizeof(txpow)); - if (!rc) { - wrqu->txpower.value = txpow; - wrqu->txpower.disabled = 0; - /* - * From the MIB values I think this can be configurable, - * as it lists several tx power levels -acme - */ - wrqu->txpower.fixed = 0; - wrqu->txpower.flags = IW_TXPOW_MWATT; - } - return rc; -} - -static int wl3501_get_retry(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u8 retry; /* size checked: it is u8 */ - struct wl3501_card *this = netdev_priv(dev); - int rc = wl3501_get_mib_value(this, - WL3501_MIB_ATTR_LONG_RETRY_LIMIT, - &retry, sizeof(retry)); - if (rc) - goto out; - if (wrqu->retry.flags & IW_RETRY_LONG) { - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_LONG; - goto set_value; - } - rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_SHORT_RETRY_LIMIT, - &retry, sizeof(retry)); - if (rc) - goto out; - wrqu->retry.flags = IW_RETRY_LIMIT | IW_RETRY_SHORT; -set_value: - wrqu->retry.value = retry; - wrqu->retry.disabled = 0; -out: - return rc; -} - -static int wl3501_get_encode(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u8 implemented, restricted, keys[100], len_keys, tocopy; - struct wl3501_card *this = netdev_priv(dev); - int rc = wl3501_get_mib_value(this, - WL3501_MIB_ATTR_PRIV_OPT_IMPLEMENTED, - &implemented, sizeof(implemented)); - if (rc) - goto out; - if (!implemented) { - wrqu->encoding.flags = IW_ENCODE_DISABLED; - goto out; - } - rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_EXCLUDE_UNENCRYPTED, - &restricted, sizeof(restricted)); - if (rc) - goto out; - wrqu->encoding.flags = restricted ? IW_ENCODE_RESTRICTED : - IW_ENCODE_OPEN; - rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_KEY_MAPPINGS_LEN, - &len_keys, sizeof(len_keys)); - if (rc) - goto out; - rc = wl3501_get_mib_value(this, WL3501_MIB_ATTR_WEP_KEY_MAPPINGS, - keys, len_keys); - if (rc) - goto out; - tocopy = min_t(u8, len_keys, wrqu->encoding.length); - tocopy = min_t(u8, tocopy, 100); - wrqu->encoding.length = tocopy; - memcpy(extra, keys, tocopy); -out: - return rc; -} - -static int wl3501_get_power(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, char *extra) -{ - u8 pwr_state; - struct wl3501_card *this = netdev_priv(dev); - int rc = wl3501_get_mib_value(this, - WL3501_MIB_ATTR_CURRENT_PWR_STATE, - &pwr_state, sizeof(pwr_state)); - if (rc) - goto out; - wrqu->power.disabled = !pwr_state; - wrqu->power.flags = IW_POWER_ON; -out: - return rc; -} - -static const iw_handler wl3501_handler[] = { - [SIOCGIWNAME - SIOCIWFIRST] = wl3501_get_name, - [SIOCSIWFREQ - SIOCIWFIRST] = wl3501_set_freq, - [SIOCGIWFREQ - SIOCIWFIRST] = wl3501_get_freq, - [SIOCSIWMODE - SIOCIWFIRST] = wl3501_set_mode, - [SIOCGIWMODE - SIOCIWFIRST] = wl3501_get_mode, - [SIOCGIWSENS - SIOCIWFIRST] = wl3501_get_sens, - [SIOCGIWRANGE - SIOCIWFIRST] = wl3501_get_range, - [SIOCSIWSPY - SIOCIWFIRST] = iw_handler_set_spy, - [SIOCGIWSPY - SIOCIWFIRST] = iw_handler_get_spy, - [SIOCSIWTHRSPY - SIOCIWFIRST] = iw_handler_set_thrspy, - [SIOCGIWTHRSPY - SIOCIWFIRST] = iw_handler_get_thrspy, - [SIOCSIWAP - SIOCIWFIRST] = wl3501_set_wap, - [SIOCGIWAP - SIOCIWFIRST] = wl3501_get_wap, - [SIOCSIWSCAN - SIOCIWFIRST] = wl3501_set_scan, - [SIOCGIWSCAN - SIOCIWFIRST] = wl3501_get_scan, - [SIOCSIWESSID - SIOCIWFIRST] = wl3501_set_essid, - [SIOCGIWESSID - SIOCIWFIRST] = wl3501_get_essid, - [SIOCSIWNICKN - SIOCIWFIRST] = wl3501_set_nick, - [SIOCGIWNICKN - SIOCIWFIRST] = wl3501_get_nick, - [SIOCGIWRATE - SIOCIWFIRST] = wl3501_get_rate, - [SIOCGIWRTS - SIOCIWFIRST] = wl3501_get_rts_threshold, - [SIOCGIWFRAG - SIOCIWFIRST] = wl3501_get_frag_threshold, - [SIOCGIWTXPOW - SIOCIWFIRST] = wl3501_get_txpow, - [SIOCGIWRETRY - SIOCIWFIRST] = wl3501_get_retry, - [SIOCGIWENCODE - SIOCIWFIRST] = wl3501_get_encode, - [SIOCGIWPOWER - SIOCIWFIRST] = wl3501_get_power, -}; - -static const struct iw_handler_def wl3501_handler_def = { - .num_standard = ARRAY_SIZE(wl3501_handler), - .standard = (iw_handler *)wl3501_handler, - .get_wireless_stats = wl3501_get_wireless_stats, -}; - -static const struct net_device_ops wl3501_netdev_ops = { - .ndo_open = wl3501_open, - .ndo_stop = wl3501_close, - .ndo_start_xmit = wl3501_hard_start_xmit, - .ndo_tx_timeout = wl3501_tx_timeout, - .ndo_change_mtu = eth_change_mtu, - .ndo_set_mac_address = eth_mac_addr, - .ndo_validate_addr = eth_validate_addr, -}; - -/** - * wl3501_attach - creates an "instance" of the driver - * - * Creates an "instance" of the driver, allocating local data structures for - * one device. The device is registered with Card Services. - * - * The dev_link structure is initialized, but we don't actually configure the - * card at this point -- we wait until we receive a card insertion event. - */ -static int wl3501_probe(struct pcmcia_device *p_dev) -{ - struct net_device *dev; - struct wl3501_card *this; - - /* The io structure describes IO port mapping */ - p_dev->io.NumPorts1 = 16; - p_dev->io.Attributes1 = IO_DATA_PATH_WIDTH_8; - p_dev->io.IOAddrLines = 5; - - /* Interrupt setup */ - p_dev->irq.Attributes = IRQ_TYPE_DYNAMIC_SHARING | IRQ_HANDLE_PRESENT; - p_dev->irq.IRQInfo1 = IRQ_LEVEL_ID; - p_dev->irq.Handler = wl3501_interrupt; - - /* General socket configuration */ - p_dev->conf.Attributes = CONF_ENABLE_IRQ; - p_dev->conf.IntType = INT_MEMORY_AND_IO; - p_dev->conf.ConfigIndex = 1; - - dev = alloc_etherdev(sizeof(struct wl3501_card)); - if (!dev) - goto out_link; - - - dev->netdev_ops = &wl3501_netdev_ops; - dev->watchdog_timeo = 5 * HZ; - - this = netdev_priv(dev); - this->wireless_data.spy_data = &this->spy_data; - this->p_dev = p_dev; - dev->wireless_data = &this->wireless_data; - dev->wireless_handlers = &wl3501_handler_def; - SET_ETHTOOL_OPS(dev, &ops); - netif_stop_queue(dev); - p_dev->priv = p_dev->irq.Instance = dev; - - return wl3501_config(p_dev); -out_link: - return -ENOMEM; -} - -#define CS_CHECK(fn, ret) \ -do { last_fn = (fn); if ((last_ret = (ret)) != 0) goto cs_failed; } while (0) - -/** - * wl3501_config - configure the PCMCIA socket and make eth device available - * @link - FILL_IN - * - * wl3501_config() is scheduled to run after a CARD_INSERTION event is - * received, to configure the PCMCIA socket, and to make the ethernet device - * available to the system. - */ -static int wl3501_config(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - int i = 0, j, last_fn, last_ret; - struct wl3501_card *this; - - /* Try allocating IO ports. This tries a few fixed addresses. If you - * want, you can also read the card's config table to pick addresses -- - * see the serial driver for an example. */ - - for (j = 0x280; j < 0x400; j += 0x20) { - /* The '^0x300' is so that we probe 0x300-0x3ff first, then - * 0x200-0x2ff, and so on, because this seems safer */ - link->io.BasePort1 = j; - link->io.BasePort2 = link->io.BasePort1 + 0x10; - i = pcmcia_request_io(link, &link->io); - if (i == 0) - break; - } - if (i != 0) { - cs_error(link, RequestIO, i); - goto failed; - } - - /* Now allocate an interrupt line. Note that this does not actually - * assign a handler to the interrupt. */ - - CS_CHECK(RequestIRQ, pcmcia_request_irq(link, &link->irq)); - - /* This actually configures the PCMCIA socket -- setting up the I/O - * windows and the interrupt mapping. */ - - CS_CHECK(RequestConfiguration, pcmcia_request_configuration(link, &link->conf)); - - dev->irq = link->irq.AssignedIRQ; - dev->base_addr = link->io.BasePort1; - SET_NETDEV_DEV(dev, &handle_to_dev(link)); - if (register_netdev(dev)) { - printk(KERN_NOTICE "wl3501_cs: register_netdev() failed\n"); - goto failed; - } - - this = netdev_priv(dev); - /* - * At this point, the dev_node_t structure(s) should be initialized and - * arranged in a linked list at link->dev_node. - */ - link->dev_node = &this->node; - - this->base_addr = dev->base_addr; - - if (!wl3501_get_flash_mac_addr(this)) { - printk(KERN_WARNING "%s: Cant read MAC addr in flash ROM?\n", - dev->name); - goto failed; - } - strcpy(this->node.dev_name, dev->name); - - for (i = 0; i < 6; i++) - dev->dev_addr[i] = ((char *)&this->mac_addr)[i]; - - /* print probe information */ - printk(KERN_INFO "%s: wl3501 @ 0x%3.3x, IRQ %d, " - "MAC addr in flash ROM:%pM\n", - dev->name, this->base_addr, (int)dev->irq, - dev->dev_addr); - /* - * Initialize card parameters - added by jss - */ - this->net_type = IW_MODE_INFRA; - this->bss_cnt = 0; - this->join_sta_bss = 0; - this->adhoc_times = 0; - iw_set_mgmt_info_element(IW_MGMT_INFO_ELEMENT_SSID, &this->essid.el, - "ANY", 3); - this->card_name[0] = '\0'; - this->firmware_date[0] = '\0'; - this->rssi = 255; - this->chan = iw_default_channel(this->reg_domain); - strlcpy(this->nick, "Planet WL3501", sizeof(this->nick)); - spin_lock_init(&this->lock); - init_waitqueue_head(&this->wait); - netif_start_queue(dev); - return 0; - -cs_failed: - cs_error(link, last_fn, last_ret); -failed: - wl3501_release(link); - return -ENODEV; -} - -/** - * wl3501_release - unregister the net, release PCMCIA configuration - * @arg - link - * - * After a card is removed, wl3501_release() will unregister the net device, - * and release the PCMCIA configuration. If the device is still open, this - * will be postponed until it is closed. - */ -static void wl3501_release(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - /* Unlink the device chain */ - if (link->dev_node) - unregister_netdev(dev); - - pcmcia_disable_device(link); -} - -static int wl3501_suspend(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - wl3501_pwr_mgmt(netdev_priv(dev), WL3501_SUSPEND); - if (link->open) - netif_device_detach(dev); - - return 0; -} - -static int wl3501_resume(struct pcmcia_device *link) -{ - struct net_device *dev = link->priv; - - wl3501_pwr_mgmt(netdev_priv(dev), WL3501_RESUME); - if (link->open) { - wl3501_reset(dev); - netif_device_attach(dev); - } - - return 0; -} - - -static struct pcmcia_device_id wl3501_ids[] = { - PCMCIA_DEVICE_MANF_CARD(0xd601, 0x0001), - PCMCIA_DEVICE_NULL -}; -MODULE_DEVICE_TABLE(pcmcia, wl3501_ids); - -static struct pcmcia_driver wl3501_driver = { - .owner = THIS_MODULE, - .drv = { - .name = "wl3501_cs", - }, - .probe = wl3501_probe, - .remove = wl3501_detach, - .id_table = wl3501_ids, - .suspend = wl3501_suspend, - .resume = wl3501_resume, -}; - -static int __init wl3501_init_module(void) -{ - return pcmcia_register_driver(&wl3501_driver); -} - -static void __exit wl3501_exit_module(void) -{ - pcmcia_unregister_driver(&wl3501_driver); -} - -module_init(wl3501_init_module); -module_exit(wl3501_exit_module); - -MODULE_AUTHOR("Fox Chen , " - "Arnaldo Carvalho de Melo ," - "Gustavo Niemeyer "); -MODULE_DESCRIPTION("Planet wl3501 wireless driver"); -MODULE_LICENSE("GPL"); diff --git a/drivers/net/wireless/wlan/Makefile b/drivers/net/wireless/wlan/Makefile deleted file mode 100644 index fcfa4e1d49d1..000000000000 --- a/drivers/net/wireless/wlan/Makefile +++ /dev/null @@ -1,4 +0,0 @@ - -obj-m += wlan.o - - diff --git a/drivers/net/wireless/wlan/wlan.c b/drivers/net/wireless/wlan/wlan.c deleted file mode 100644 index 9d3f5b14fd45..000000000000 --- a/drivers/net/wireless/wlan/wlan.c +++ /dev/null @@ -1,22 +0,0 @@ - -#include -#include - -extern int if_sdio_init_module2(void); -extern void if_sdio_exit_module(void); - -static int wlan_init_module(void) -{ - printk("Loading wlan driver..........\n"); - return if_sdio_init_module2(); -} - -static void wlan_exit_module(void) -{ - printk("move wlan driver..........\n"); - if_sdio_exit_module(); -} -module_init(wlan_init_module); -module_exit(wlan_exit_module); - -MODULE_LICENSE("GPL V2"); diff --git a/drivers/net/wireless/zd1201.c b/drivers/net/wireless/zd1201.c deleted file mode 100644 index bc81974a2bc7..000000000000 --- a/drivers/net/wireless/zd1201.c +++ /dev/null @@ -1,1922 +0,0 @@ -/* - * Driver for ZyDAS zd1201 based wireless USB devices. - * - * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Parts of this driver have been derived from a wlan-ng version - * modified by ZyDAS. They also made documentation available, thanks! - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "zd1201.h" - -static struct usb_device_id zd1201_table[] = { - {USB_DEVICE(0x0586, 0x3400)}, /* Peabird Wireless USB Adapter */ - {USB_DEVICE(0x0ace, 0x1201)}, /* ZyDAS ZD1201 Wireless USB Adapter */ - {USB_DEVICE(0x050d, 0x6051)}, /* Belkin F5D6051 usb adapter */ - {USB_DEVICE(0x0db0, 0x6823)}, /* MSI UB11B usb adapter */ - {USB_DEVICE(0x1044, 0x8005)}, /* GIGABYTE GN-WLBZ201 usb adapter */ - {} -}; - -static int ap; /* Are we an AP or a normal station? */ - -#define ZD1201_VERSION "0.15" - -MODULE_AUTHOR("Jeroen Vreeken "); -MODULE_DESCRIPTION("Driver for ZyDAS ZD1201 based USB Wireless adapters"); -MODULE_VERSION(ZD1201_VERSION); -MODULE_LICENSE("GPL"); -module_param(ap, int, 0); -MODULE_PARM_DESC(ap, "If non-zero Access Point firmware will be loaded"); -MODULE_DEVICE_TABLE(usb, zd1201_table); - - -static int zd1201_fw_upload(struct usb_device *dev, int apfw) -{ - const struct firmware *fw_entry; - const char *data; - unsigned long len; - int err; - unsigned char ret; - char *buf; - char *fwfile; - - if (apfw) - fwfile = "zd1201-ap.fw"; - else - fwfile = "zd1201.fw"; - - err = request_firmware(&fw_entry, fwfile, &dev->dev); - if (err) { - dev_err(&dev->dev, "Failed to load %s firmware file!\n", fwfile); - dev_err(&dev->dev, "Make sure the hotplug firmware loader is installed.\n"); - dev_err(&dev->dev, "Goto http://linux-lc100020.sourceforge.net for more info.\n"); - return err; - } - - data = fw_entry->data; - len = fw_entry->size; - - buf = kmalloc(1024, GFP_ATOMIC); - if (!buf) - goto exit; - - while (len > 0) { - int translen = (len > 1024) ? 1024 : len; - memcpy(buf, data, translen); - - err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0, - USB_DIR_OUT | 0x40, 0, 0, buf, translen, - ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - len -= translen; - data += translen; - } - - err = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), 0x2, - USB_DIR_OUT | 0x40, 0, 0, NULL, 0, ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - err = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), 0x4, - USB_DIR_IN | 0x40, 0,0, &ret, sizeof(ret), ZD1201_FW_TIMEOUT); - if (err < 0) - goto exit; - - if (ret & 0x80) { - err = -EIO; - goto exit; - } - - err = 0; -exit: - kfree(buf); - release_firmware(fw_entry); - return err; -} - -static void zd1201_usbfree(struct urb *urb) -{ - struct zd1201 *zd = urb->context; - - switch(urb->status) { - case -EILSEQ: - case -ENODEV: - case -ETIME: - case -ENOENT: - case -EPIPE: - case -EOVERFLOW: - case -ESHUTDOWN: - dev_warn(&zd->usb->dev, "%s: urb failed: %d\n", - zd->dev->name, urb->status); - } - - kfree(urb->transfer_buffer); - usb_free_urb(urb); - return; -} - -/* cmdreq message: - u32 type - u16 cmd - u16 parm0 - u16 parm1 - u16 parm2 - u8 pad[4] - - total: 4 + 2 + 2 + 2 + 2 + 4 = 16 -*/ -static int zd1201_docmd(struct zd1201 *zd, int cmd, int parm0, - int parm1, int parm2) -{ - unsigned char *command; - int ret; - struct urb *urb; - - command = kmalloc(16, GFP_ATOMIC); - if (!command) - return -ENOMEM; - - *((__le32*)command) = cpu_to_le32(ZD1201_USB_CMDREQ); - *((__le16*)&command[4]) = cpu_to_le16(cmd); - *((__le16*)&command[6]) = cpu_to_le16(parm0); - *((__le16*)&command[8]) = cpu_to_le16(parm1); - *((__le16*)&command[10])= cpu_to_le16(parm2); - - urb = usb_alloc_urb(0, GFP_ATOMIC); - if (!urb) { - kfree(command); - return -ENOMEM; - } - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), - command, 16, zd1201_usbfree, zd); - ret = usb_submit_urb(urb, GFP_ATOMIC); - if (ret) { - kfree(command); - usb_free_urb(urb); - } - - return ret; -} - -/* Callback after sending out a packet */ -static void zd1201_usbtx(struct urb *urb) -{ - struct zd1201 *zd = urb->context; - netif_wake_queue(zd->dev); - return; -} - -/* Incoming data */ -static void zd1201_usbrx(struct urb *urb) -{ - struct zd1201 *zd = urb->context; - int free = 0; - unsigned char *data = urb->transfer_buffer; - struct sk_buff *skb; - unsigned char type; - - if (!zd) - return; - - switch(urb->status) { - case -EILSEQ: - case -ENODEV: - case -ETIME: - case -ENOENT: - case -EPIPE: - case -EOVERFLOW: - case -ESHUTDOWN: - dev_warn(&zd->usb->dev, "%s: rx urb failed: %d\n", - zd->dev->name, urb->status); - free = 1; - goto exit; - } - - if (urb->status != 0 || urb->actual_length == 0) - goto resubmit; - - type = data[0]; - if (type == ZD1201_PACKET_EVENTSTAT || type == ZD1201_PACKET_RESOURCE) { - memcpy(zd->rxdata, data, urb->actual_length); - zd->rxlen = urb->actual_length; - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - } - /* Info frame */ - if (type == ZD1201_PACKET_INQUIRE) { - int i = 0; - unsigned short infotype, framelen, copylen; - framelen = le16_to_cpu(*(__le16*)&data[4]); - infotype = le16_to_cpu(*(__le16*)&data[6]); - - if (infotype == ZD1201_INF_LINKSTATUS) { - short linkstatus; - - linkstatus = le16_to_cpu(*(__le16*)&data[8]); - switch(linkstatus) { - case 1: - netif_carrier_on(zd->dev); - break; - case 2: - netif_carrier_off(zd->dev); - break; - case 3: - netif_carrier_off(zd->dev); - break; - case 4: - netif_carrier_on(zd->dev); - break; - default: - netif_carrier_off(zd->dev); - } - goto resubmit; - } - if (infotype == ZD1201_INF_ASSOCSTATUS) { - short status = le16_to_cpu(*(__le16*)(data+8)); - int event; - union iwreq_data wrqu; - - switch (status) { - case ZD1201_ASSOCSTATUS_STAASSOC: - case ZD1201_ASSOCSTATUS_REASSOC: - event = IWEVREGISTERED; - break; - case ZD1201_ASSOCSTATUS_DISASSOC: - case ZD1201_ASSOCSTATUS_ASSOCFAIL: - case ZD1201_ASSOCSTATUS_AUTHFAIL: - default: - event = IWEVEXPIRED; - } - memcpy(wrqu.addr.sa_data, data+10, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - - /* Send event to user space */ - wireless_send_event(zd->dev, event, &wrqu, NULL); - - goto resubmit; - } - if (infotype == ZD1201_INF_AUTHREQ) { - union iwreq_data wrqu; - - memcpy(wrqu.addr.sa_data, data+8, ETH_ALEN); - wrqu.addr.sa_family = ARPHRD_ETHER; - /* There isn't a event that trully fits this request. - We assume that userspace will be smart enough to - see a new station being expired and sends back a - authstation ioctl to authorize it. */ - wireless_send_event(zd->dev, IWEVEXPIRED, &wrqu, NULL); - goto resubmit; - } - /* Other infotypes are handled outside this handler */ - zd->rxlen = 0; - while (i < urb->actual_length) { - copylen = le16_to_cpu(*(__le16*)&data[i+2]); - /* Sanity check, sometimes we get junk */ - if (copylen+zd->rxlen > sizeof(zd->rxdata)) - break; - memcpy(zd->rxdata+zd->rxlen, data+i+4, copylen); - zd->rxlen += copylen; - i += 64; - } - if (i >= urb->actual_length) { - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - } - goto resubmit; - } - /* Actual data */ - if (data[urb->actual_length-1] == ZD1201_PACKET_RXDATA) { - int datalen = urb->actual_length-1; - unsigned short len, fc, seq; - struct hlist_node *node; - - len = ntohs(*(__be16 *)&data[datalen-2]); - if (len>datalen) - len=datalen; - fc = le16_to_cpu(*(__le16 *)&data[datalen-16]); - seq = le16_to_cpu(*(__le16 *)&data[datalen-24]); - - if (zd->monitor) { - if (datalen < 24) - goto resubmit; - if (!(skb = dev_alloc_skb(datalen+24))) - goto resubmit; - - memcpy(skb_put(skb, 2), &data[datalen-16], 2); - memcpy(skb_put(skb, 2), &data[datalen-2], 2); - memcpy(skb_put(skb, 6), &data[datalen-14], 6); - memcpy(skb_put(skb, 6), &data[datalen-22], 6); - memcpy(skb_put(skb, 6), &data[datalen-8], 6); - memcpy(skb_put(skb, 2), &data[datalen-24], 2); - memcpy(skb_put(skb, len), data, len); - skb->protocol = eth_type_trans(skb, zd->dev); - zd->dev->stats.rx_packets++; - zd->dev->stats.rx_bytes += skb->len; - netif_rx(skb); - goto resubmit; - } - - if ((seq & IEEE80211_SCTL_FRAG) || - (fc & IEEE80211_FCTL_MOREFRAGS)) { - struct zd1201_frag *frag = NULL; - char *ptr; - - if (datalen<14) - goto resubmit; - if ((seq & IEEE80211_SCTL_FRAG) == 0) { - frag = kmalloc(sizeof(*frag), GFP_ATOMIC); - if (!frag) - goto resubmit; - skb = dev_alloc_skb(IEEE80211_MAX_DATA_LEN +14+2); - if (!skb) { - kfree(frag); - goto resubmit; - } - frag->skb = skb; - frag->seq = seq & IEEE80211_SCTL_SEQ; - skb_reserve(skb, 2); - memcpy(skb_put(skb, 12), &data[datalen-14], 12); - memcpy(skb_put(skb, 2), &data[6], 2); - memcpy(skb_put(skb, len), data+8, len); - hlist_add_head(&frag->fnode, &zd->fraglist); - goto resubmit; - } - hlist_for_each_entry(frag, node, &zd->fraglist, fnode) - if (frag->seq == (seq&IEEE80211_SCTL_SEQ)) - break; - if (!frag) - goto resubmit; - skb = frag->skb; - ptr = skb_put(skb, len); - if (ptr) - memcpy(ptr, data+8, len); - if (fc & IEEE80211_FCTL_MOREFRAGS) - goto resubmit; - hlist_del_init(&frag->fnode); - kfree(frag); - } else { - if (datalen<14) - goto resubmit; - skb = dev_alloc_skb(len + 14 + 2); - if (!skb) - goto resubmit; - skb_reserve(skb, 2); - memcpy(skb_put(skb, 12), &data[datalen-14], 12); - memcpy(skb_put(skb, 2), &data[6], 2); - memcpy(skb_put(skb, len), data+8, len); - } - skb->protocol = eth_type_trans(skb, zd->dev); - zd->dev->stats.rx_packets++; - zd->dev->stats.rx_bytes += skb->len; - netif_rx(skb); - } -resubmit: - memset(data, 0, ZD1201_RXSIZE); - - urb->status = 0; - urb->dev = zd->usb; - if(usb_submit_urb(urb, GFP_ATOMIC)) - free = 1; - -exit: - if (free) { - zd->rxlen = 0; - zd->rxdatas = 1; - wake_up(&zd->rxdataq); - kfree(urb->transfer_buffer); - } - return; -} - -static int zd1201_getconfig(struct zd1201 *zd, int rid, void *riddata, - unsigned int riddatalen) -{ - int err; - int i = 0; - int code; - int rid_fid; - int length; - unsigned char *pdata; - - zd->rxdatas = 0; - err = zd1201_docmd(zd, ZD1201_CMDCODE_ACCESS, rid, 0, 0); - if (err) - return err; - - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - code = le16_to_cpu(*(__le16*)(&zd->rxdata[4])); - rid_fid = le16_to_cpu(*(__le16*)(&zd->rxdata[6])); - length = le16_to_cpu(*(__le16*)(&zd->rxdata[8])); - if (length > zd->rxlen) - length = zd->rxlen-6; - - /* If access bit is not on, then error */ - if ((code & ZD1201_ACCESSBIT) != ZD1201_ACCESSBIT || rid_fid != rid ) - return -EINVAL; - - /* Not enough buffer for allocating data */ - if (riddatalen != (length - 4)) { - dev_dbg(&zd->usb->dev, "riddatalen mismatches, expected=%u, (packet=%u) length=%u, rid=0x%04X, rid_fid=0x%04X\n", - riddatalen, zd->rxlen, length, rid, rid_fid); - return -ENODATA; - } - - zd->rxdatas = 0; - /* Issue SetRxRid commnd */ - err = zd1201_docmd(zd, ZD1201_CMDCODE_SETRXRID, rid, 0, length); - if (err) - return err; - - /* Receive RID record from resource packets */ - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - if (zd->rxdata[zd->rxlen - 1] != ZD1201_PACKET_RESOURCE) { - dev_dbg(&zd->usb->dev, "Packet type mismatch: 0x%x not 0x3\n", - zd->rxdata[zd->rxlen-1]); - return -EINVAL; - } - - /* Set the data pointer and received data length */ - pdata = zd->rxdata; - length = zd->rxlen; - - do { - int actual_length; - - actual_length = (length > 64) ? 64 : length; - - if (pdata[0] != 0x3) { - dev_dbg(&zd->usb->dev, "Rx Resource packet type error: %02X\n", - pdata[0]); - return -EINVAL; - } - - if (actual_length != 64) { - /* Trim the last packet type byte */ - actual_length--; - } - - /* Skip the 4 bytes header (RID length and RID) */ - if (i == 0) { - pdata += 8; - actual_length -= 8; - } else { - pdata += 4; - actual_length -= 4; - } - - memcpy(riddata, pdata, actual_length); - riddata += actual_length; - pdata += actual_length; - length -= 64; - i++; - } while (length > 0); - - return 0; -} - -/* - * resreq: - * byte type - * byte sequence - * u16 reserved - * byte data[12] - * total: 16 - */ -static int zd1201_setconfig(struct zd1201 *zd, int rid, void *buf, int len, int wait) -{ - int err; - unsigned char *request; - int reqlen; - char seq=0; - struct urb *urb; - gfp_t gfp_mask = wait ? GFP_NOIO : GFP_ATOMIC; - - len += 4; /* first 4 are for header */ - - zd->rxdatas = 0; - zd->rxlen = 0; - for (seq=0; len > 0; seq++) { - request = kmalloc(16, gfp_mask); - if (!request) - return -ENOMEM; - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) { - kfree(request); - return -ENOMEM; - } - memset(request, 0, 16); - reqlen = len>12 ? 12 : len; - request[0] = ZD1201_USB_RESREQ; - request[1] = seq; - request[2] = 0; - request[3] = 0; - if (request[1] == 0) { - /* add header */ - *(__le16*)&request[4] = cpu_to_le16((len-2+1)/2); - *(__le16*)&request[6] = cpu_to_le16(rid); - memcpy(request+8, buf, reqlen-4); - buf += reqlen-4; - } else { - memcpy(request+4, buf, reqlen); - buf += reqlen; - } - - len -= reqlen; - - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, - zd->endp_out2), request, 16, zd1201_usbfree, zd); - err = usb_submit_urb(urb, gfp_mask); - if (err) - goto err; - } - - request = kmalloc(16, gfp_mask); - if (!request) - return -ENOMEM; - urb = usb_alloc_urb(0, gfp_mask); - if (!urb) { - kfree(request); - return -ENOMEM; - } - *((__le32*)request) = cpu_to_le32(ZD1201_USB_CMDREQ); - *((__le16*)&request[4]) = - cpu_to_le16(ZD1201_CMDCODE_ACCESS|ZD1201_ACCESSBIT); - *((__le16*)&request[6]) = cpu_to_le16(rid); - *((__le16*)&request[8]) = cpu_to_le16(0); - *((__le16*)&request[10]) = cpu_to_le16(0); - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out2), - request, 16, zd1201_usbfree, zd); - err = usb_submit_urb(urb, gfp_mask); - if (err) - goto err; - - if (wait) { - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen || le16_to_cpu(*(__le16*)&zd->rxdata[6]) != rid) { - dev_dbg(&zd->usb->dev, "wrong or no RID received\n"); - } - } - - return 0; -err: - kfree(request); - usb_free_urb(urb); - return err; -} - -static inline int zd1201_getconfig16(struct zd1201 *zd, int rid, short *val) -{ - int err; - __le16 zdval; - - err = zd1201_getconfig(zd, rid, &zdval, sizeof(__le16)); - if (err) - return err; - *val = le16_to_cpu(zdval); - return 0; -} - -static inline int zd1201_setconfig16(struct zd1201 *zd, int rid, short val) -{ - __le16 zdval = cpu_to_le16(val); - return (zd1201_setconfig(zd, rid, &zdval, sizeof(__le16), 1)); -} - -static int zd1201_drvr_start(struct zd1201 *zd) -{ - int err, i; - short max; - __le16 zdmax; - unsigned char *buffer; - - buffer = kzalloc(ZD1201_RXSIZE, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - - usb_fill_bulk_urb(zd->rx_urb, zd->usb, - usb_rcvbulkpipe(zd->usb, zd->endp_in), buffer, ZD1201_RXSIZE, - zd1201_usbrx, zd); - - err = usb_submit_urb(zd->rx_urb, GFP_KERNEL); - if (err) - goto err_buffer; - - err = zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); - if (err) - goto err_urb; - - err = zd1201_getconfig(zd, ZD1201_RID_CNFMAXTXBUFFERNUMBER, &zdmax, - sizeof(__le16)); - if (err) - goto err_urb; - - max = le16_to_cpu(zdmax); - for (i=0; irx_urb); - return err; -err_buffer: - kfree(buffer); - return err; -} - -/* Magic alert: The firmware doesn't seem to like the MAC state being - * toggled in promisc (aka monitor) mode. - * (It works a number of times, but will halt eventually) - * So we turn it of before disabling and on after enabling if needed. - */ -static int zd1201_enable(struct zd1201 *zd) -{ - int err; - - if (zd->mac_enabled) - return 0; - - err = zd1201_docmd(zd, ZD1201_CMDCODE_ENABLE, 0, 0, 0); - if (!err) - zd->mac_enabled = 1; - - if (zd->monitor) - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 1); - - return err; -} - -static int zd1201_disable(struct zd1201 *zd) -{ - int err; - - if (!zd->mac_enabled) - return 0; - if (zd->monitor) { - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err) - return err; - } - - err = zd1201_docmd(zd, ZD1201_CMDCODE_DISABLE, 0, 0, 0); - if (!err) - zd->mac_enabled = 0; - return err; -} - -static int zd1201_mac_reset(struct zd1201 *zd) -{ - if (!zd->mac_enabled) - return 0; - zd1201_disable(zd); - return zd1201_enable(zd); -} - -static int zd1201_join(struct zd1201 *zd, char *essid, int essidlen) -{ - int err, val; - char buf[IW_ESSID_MAX_SIZE+2]; - - err = zd1201_disable(zd); - if (err) - return err; - - val = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; - val |= ZD1201_CNFAUTHENTICATION_SHAREDKEY; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, val); - if (err) - return err; - - *(__le16 *)buf = cpu_to_le16(essidlen); - memcpy(buf+2, essid, essidlen); - if (!zd->ap) { /* Normal station */ - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } else { /* AP */ - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } - - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, - zd->dev->dev_addr, zd->dev->addr_len, 1); - if (err) - return err; - - err = zd1201_enable(zd); - if (err) - return err; - - msleep(100); - return 0; -} - -static int zd1201_net_open(struct net_device *dev) -{ - struct zd1201 *zd = netdev_priv(dev); - - /* Start MAC with wildcard if no essid set */ - if (!zd->mac_enabled) - zd1201_join(zd, zd->essid, zd->essidlen); - netif_start_queue(dev); - - return 0; -} - -static int zd1201_net_stop(struct net_device *dev) -{ - netif_stop_queue(dev); - return 0; -} - -/* - RFC 1042 encapsulates Ethernet frames in 802.11 frames - by prefixing them with 0xaa, 0xaa, 0x03) followed by a SNAP OID of 0 - (0x00, 0x00, 0x00). Zd requires an additional padding, copy - of ethernet addresses, length of the standard RFC 1042 packet - and a command byte (which is nul for tx). - - tx frame (from Wlan NG): - RFC 1042: - llc 0xAA 0xAA 0x03 (802.2 LLC) - snap 0x00 0x00 0x00 (Ethernet encapsulated) - type 2 bytes, Ethernet type field - payload (minus eth header) - Zydas specific: - padding 1B if (skb->len+8+1)%64==0 - Eth MAC addr 12 bytes, Ethernet MAC addresses - length 2 bytes, RFC 1042 packet length - (llc+snap+type+payload) - zd 1 null byte, zd1201 packet type - */ -static netdev_tx_t zd1201_hard_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct zd1201 *zd = netdev_priv(dev); - unsigned char *txbuf = zd->txdata; - int txbuflen, pad = 0, err; - struct urb *urb = zd->tx_urb; - - if (!zd->mac_enabled || zd->monitor) { - dev->stats.tx_dropped++; - kfree_skb(skb); - return NETDEV_TX_OK; - } - netif_stop_queue(dev); - - txbuflen = skb->len + 8 + 1; - if (txbuflen%64 == 0) { - pad = 1; - txbuflen++; - } - txbuf[0] = 0xAA; - txbuf[1] = 0xAA; - txbuf[2] = 0x03; - txbuf[3] = 0x00; /* rfc1042 */ - txbuf[4] = 0x00; - txbuf[5] = 0x00; - - skb_copy_from_linear_data_offset(skb, 12, txbuf + 6, skb->len - 12); - if (pad) - txbuf[skb->len-12+6]=0; - skb_copy_from_linear_data(skb, txbuf + skb->len - 12 + 6 + pad, 12); - *(__be16*)&txbuf[skb->len+6+pad] = htons(skb->len-12+6); - txbuf[txbuflen-1] = 0; - - usb_fill_bulk_urb(urb, zd->usb, usb_sndbulkpipe(zd->usb, zd->endp_out), - txbuf, txbuflen, zd1201_usbtx, zd); - - err = usb_submit_urb(zd->tx_urb, GFP_ATOMIC); - if (err) { - dev->stats.tx_errors++; - netif_start_queue(dev); - } else { - dev->stats.tx_packets++; - dev->stats.tx_bytes += skb->len; - dev->trans_start = jiffies; - } - kfree_skb(skb); - - return NETDEV_TX_OK; -} - -static void zd1201_tx_timeout(struct net_device *dev) -{ - struct zd1201 *zd = netdev_priv(dev); - - if (!zd) - return; - dev_warn(&zd->usb->dev, "%s: TX timeout, shooting down urb\n", - dev->name); - usb_unlink_urb(zd->tx_urb); - dev->stats.tx_errors++; - /* Restart the timeout to quiet the watchdog: */ - dev->trans_start = jiffies; -} - -static int zd1201_set_mac_address(struct net_device *dev, void *p) -{ - struct sockaddr *addr = p; - struct zd1201 *zd = netdev_priv(dev); - int err; - - if (!zd) - return -ENODEV; - - err = zd1201_setconfig(zd, ZD1201_RID_CNFOWNMACADDR, - addr->sa_data, dev->addr_len, 1); - if (err) - return err; - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - return zd1201_mac_reset(zd); -} - -static struct iw_statistics *zd1201_get_wireless_stats(struct net_device *dev) -{ - struct zd1201 *zd = netdev_priv(dev); - - return &zd->iwstats; -} - -static void zd1201_set_multicast(struct net_device *dev) -{ - struct zd1201 *zd = netdev_priv(dev); - struct dev_mc_list *mc = dev->mc_list; - unsigned char reqbuf[ETH_ALEN*ZD1201_MAXMULTI]; - int i; - - if (dev->mc_count > ZD1201_MAXMULTI) - return; - - for (i=0; imc_count; i++) { - memcpy(reqbuf+i*ETH_ALEN, mc->dmi_addr, ETH_ALEN); - mc = mc->next; - } - zd1201_setconfig(zd, ZD1201_RID_CNFGROUPADDRESS, reqbuf, - dev->mc_count*ETH_ALEN, 0); - -} - -static int zd1201_config_commit(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = netdev_priv(dev); - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_name(struct net_device *dev, - struct iw_request_info *info, char *name, char *extra) -{ - strcpy(name, "IEEE 802.11b"); - return 0; -} - -static int zd1201_set_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short channel = 0; - int err; - - if (freq->e == 0) - channel = freq->m; - else { - channel = ieee80211_freq_to_dsss_chan(freq->m); - if (channel < 0) - channel = 0; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, channel); - if (err) - return err; - - zd1201_mac_reset(zd); - - return 0; -} - -static int zd1201_get_freq(struct net_device *dev, - struct iw_request_info *info, struct iw_freq *freq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short channel; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFOWNCHANNEL, &channel); - if (err) - return err; - freq->e = 0; - freq->m = channel; - - return 0; -} - -static int zd1201_set_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short porttype, monitor = 0; - unsigned char buffer[IW_ESSID_MAX_SIZE+2]; - int err; - - if (zd->ap) { - if (*mode != IW_MODE_MASTER) - return -EINVAL; - return 0; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_PROMISCUOUSMODE, 0); - if (err) - return err; - zd->dev->type = ARPHRD_ETHER; - switch(*mode) { - case IW_MODE_MONITOR: - monitor = 1; - zd->dev->type = ARPHRD_IEEE80211; - /* Make sure we are no longer associated with by - setting an 'impossible' essid. - (otherwise we mess up firmware) - */ - zd1201_join(zd, "\0-*#\0", 5); - /* Put port in pIBSS */ - case 8: /* No pseudo-IBSS in wireless extensions (yet) */ - porttype = ZD1201_PORTTYPE_PSEUDOIBSS; - break; - case IW_MODE_ADHOC: - porttype = ZD1201_PORTTYPE_IBSS; - break; - case IW_MODE_INFRA: - porttype = ZD1201_PORTTYPE_BSS; - break; - default: - return -EINVAL; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); - if (err) - return err; - if (zd->monitor && !monitor) { - zd1201_disable(zd); - *(__le16 *)buffer = cpu_to_le16(zd->essidlen); - memcpy(buffer+2, zd->essid, zd->essidlen); - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, - buffer, IW_ESSID_MAX_SIZE+2, 1); - if (err) - return err; - } - zd->monitor = monitor; - /* If monitor mode is set we don't actually turn it on here since it - * is done during mac reset anyway (see zd1201_mac_enable). - */ - zd1201_mac_reset(zd); - - return 0; -} - -static int zd1201_get_mode(struct net_device *dev, - struct iw_request_info *info, __u32 *mode, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short porttype; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPORTTYPE, &porttype); - if (err) - return err; - switch(porttype) { - case ZD1201_PORTTYPE_IBSS: - *mode = IW_MODE_ADHOC; - break; - case ZD1201_PORTTYPE_BSS: - *mode = IW_MODE_INFRA; - break; - case ZD1201_PORTTYPE_WDS: - *mode = IW_MODE_REPEAT; - break; - case ZD1201_PORTTYPE_PSEUDOIBSS: - *mode = 8;/* No Pseudo-IBSS... */ - break; - case ZD1201_PORTTYPE_AP: - *mode = IW_MODE_MASTER; - break; - default: - dev_dbg(&zd->usb->dev, "Unknown porttype: %d\n", - porttype); - *mode = IW_MODE_AUTO; - } - if (zd->monitor) - *mode = IW_MODE_MONITOR; - - return 0; -} - -static int zd1201_get_range(struct net_device *dev, - struct iw_request_info *info, struct iw_point *wrq, char *extra) -{ - struct iw_range *range = (struct iw_range *)extra; - - wrq->length = sizeof(struct iw_range); - memset(range, 0, sizeof(struct iw_range)); - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = WIRELESS_EXT; - - range->max_qual.qual = 128; - range->max_qual.level = 128; - range->max_qual.noise = 128; - range->max_qual.updated = 7; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = ZD1201_NUMKEYS; - - range->num_bitrates = 4; - range->bitrate[0] = 1000000; - range->bitrate[1] = 2000000; - range->bitrate[2] = 5500000; - range->bitrate[3] = 11000000; - - range->min_rts = 0; - range->min_frag = ZD1201_FRAGMIN; - range->max_rts = ZD1201_RTSMAX; - range->min_frag = ZD1201_FRAGMAX; - - return 0; -} - -/* Little bit of magic here: we only get the quality if we poll - * for it, and we never get an actual request to trigger such - * a poll. Therefore we 'assume' that the user will soon ask for - * the stats after asking the bssid. - */ -static int zd1201_get_wap(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *ap_addr, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - unsigned char buffer[6]; - - if (!zd1201_getconfig(zd, ZD1201_RID_COMMSQUALITY, buffer, 6)) { - /* Unfortunately the quality and noise reported is useless. - they seem to be accumulators that increase until you - read them, unless we poll on a fixed interval we can't - use them - */ - /*zd->iwstats.qual.qual = le16_to_cpu(((__le16 *)buffer)[0]);*/ - zd->iwstats.qual.level = le16_to_cpu(((__le16 *)buffer)[1]); - /*zd->iwstats.qual.noise = le16_to_cpu(((__le16 *)buffer)[2]);*/ - zd->iwstats.qual.updated = 2; - } - - return zd1201_getconfig(zd, ZD1201_RID_CURRENTBSSID, ap_addr->sa_data, 6); -} - -static int zd1201_set_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) -{ - /* We do everything in get_scan */ - return 0; -} - -static int zd1201_get_scan(struct net_device *dev, - struct iw_request_info *info, struct iw_point *srq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - int err, i, j, enabled_save; - struct iw_event iwe; - char *cev = extra; - char *end_buf = extra + IW_SCAN_MAX_DATA; - - /* No scanning in AP mode */ - if (zd->ap) - return -EOPNOTSUPP; - - /* Scan doesn't seem to work if disabled */ - enabled_save = zd->mac_enabled; - zd1201_enable(zd); - - zd->rxdatas = 0; - err = zd1201_docmd(zd, ZD1201_CMDCODE_INQUIRE, - ZD1201_INQ_SCANRESULTS, 0, 0); - if (err) - return err; - - wait_event_interruptible(zd->rxdataq, zd->rxdatas); - if (!zd->rxlen) - return -EIO; - - if (le16_to_cpu(*(__le16*)&zd->rxdata[2]) != ZD1201_INQ_SCANRESULTS) - return -EIO; - - for(i=8; irxlen; i+=62) { - iwe.cmd = SIOCGIWAP; - iwe.u.ap_addr.sa_family = ARPHRD_ETHER; - memcpy(iwe.u.ap_addr.sa_data, zd->rxdata+i+6, 6); - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_ADDR_LEN); - - iwe.cmd = SIOCGIWESSID; - iwe.u.data.length = zd->rxdata[i+16]; - iwe.u.data.flags = 1; - cev = iwe_stream_add_point(info, cev, end_buf, - &iwe, zd->rxdata+i+18); - - iwe.cmd = SIOCGIWMODE; - if (zd->rxdata[i+14]&0x01) - iwe.u.mode = IW_MODE_MASTER; - else - iwe.u.mode = IW_MODE_ADHOC; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_UINT_LEN); - - iwe.cmd = SIOCGIWFREQ; - iwe.u.freq.m = zd->rxdata[i+0]; - iwe.u.freq.e = 0; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_FREQ_LEN); - - iwe.cmd = SIOCGIWRATE; - iwe.u.bitrate.fixed = 0; - iwe.u.bitrate.disabled = 0; - for (j=0; j<10; j++) if (zd->rxdata[i+50+j]) { - iwe.u.bitrate.value = (zd->rxdata[i+50+j]&0x7f)*500000; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_PARAM_LEN); - } - - iwe.cmd = SIOCGIWENCODE; - iwe.u.data.length = 0; - if (zd->rxdata[i+14]&0x10) - iwe.u.data.flags = IW_ENCODE_ENABLED; - else - iwe.u.data.flags = IW_ENCODE_DISABLED; - cev = iwe_stream_add_point(info, cev, end_buf, &iwe, NULL); - - iwe.cmd = IWEVQUAL; - iwe.u.qual.qual = zd->rxdata[i+4]; - iwe.u.qual.noise= zd->rxdata[i+2]/10-100; - iwe.u.qual.level = (256+zd->rxdata[i+4]*100)/255-100; - iwe.u.qual.updated = 7; - cev = iwe_stream_add_event(info, cev, end_buf, - &iwe, IW_EV_QUAL_LEN); - } - - if (!enabled_save) - zd1201_disable(zd); - - srq->length = cev - extra; - srq->flags = 0; - - return 0; -} - -static int zd1201_set_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = netdev_priv(dev); - - if (data->length > IW_ESSID_MAX_SIZE) - return -EINVAL; - if (data->length < 1) - data->length = 1; - zd->essidlen = data->length; - memset(zd->essid, 0, IW_ESSID_MAX_SIZE+1); - memcpy(zd->essid, essid, data->length); - return zd1201_join(zd, zd->essid, zd->essidlen); -} - -static int zd1201_get_essid(struct net_device *dev, - struct iw_request_info *info, struct iw_point *data, char *essid) -{ - struct zd1201 *zd = netdev_priv(dev); - - memcpy(essid, zd->essid, zd->essidlen); - data->flags = 1; - data->length = zd->essidlen; - - return 0; -} - -static int zd1201_get_nick(struct net_device *dev, struct iw_request_info *info, - struct iw_point *data, char *nick) -{ - strcpy(nick, "zd1201"); - data->flags = 1; - data->length = strlen(nick); - return 0; -} - -static int zd1201_set_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short rate; - int err; - - switch (rrq->value) { - case 1000000: - rate = ZD1201_RATEB1; - break; - case 2000000: - rate = ZD1201_RATEB2; - break; - case 5500000: - rate = ZD1201_RATEB5; - break; - case 11000000: - default: - rate = ZD1201_RATEB11; - break; - } - if (!rrq->fixed) { /* Also enable all lower bitrates */ - rate |= rate-1; - } - - err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, rate); - if (err) - return err; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_rate(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short rate; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CURRENTTXRATE, &rate); - if (err) - return err; - - switch(rate) { - case 1: - rrq->value = 1000000; - break; - case 2: - rrq->value = 2000000; - break; - case 5: - rrq->value = 5500000; - break; - case 11: - rrq->value = 11000000; - break; - default: - rrq->value = 0; - } - rrq->fixed = 0; - rrq->disabled = 0; - - return 0; -} - -static int zd1201_set_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - int err; - short val = rts->value; - - if (rts->disabled || !rts->fixed) - val = ZD1201_RTSMAX; - if (val > ZD1201_RTSMAX) - return -EINVAL; - if (val < 0) - return -EINVAL; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, val); - if (err) - return err; - return zd1201_mac_reset(zd); -} - -static int zd1201_get_rts(struct net_device *dev, struct iw_request_info *info, - struct iw_param *rts, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short rtst; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFRTSTHRESHOLD, &rtst); - if (err) - return err; - rts->value = rtst; - rts->disabled = (rts->value == ZD1201_RTSMAX); - rts->fixed = 1; - - return 0; -} - -static int zd1201_set_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - int err; - short val = frag->value; - - if (frag->disabled || !frag->fixed) - val = ZD1201_FRAGMAX; - if (val > ZD1201_FRAGMAX) - return -EINVAL; - if (val < ZD1201_FRAGMIN) - return -EINVAL; - if (val & 1) - return -EINVAL; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, val); - if (err) - return err; - return zd1201_mac_reset(zd); -} - -static int zd1201_get_frag(struct net_device *dev, struct iw_request_info *info, - struct iw_param *frag, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short fragt; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFFRAGTHRESHOLD, &fragt); - if (err) - return err; - frag->value = fragt; - frag->disabled = (frag->value == ZD1201_FRAGMAX); - frag->fixed = 1; - - return 0; -} - -static int zd1201_set_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - return 0; -} - -static int zd1201_get_retry(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - return 0; -} - -static int zd1201_set_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) -{ - struct zd1201 *zd = netdev_priv(dev); - short i; - int err, rid; - - if (erq->length > ZD1201_MAXKEYLEN) - return -EINVAL; - - i = (erq->flags & IW_ENCODE_INDEX)-1; - if (i == -1) { - err = zd1201_getconfig16(zd,ZD1201_RID_CNFDEFAULTKEYID,&i); - if (err) - return err; - } else { - err = zd1201_setconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, i); - if (err) - return err; - } - - if (i < 0 || i >= ZD1201_NUMKEYS) - return -EINVAL; - - rid = ZD1201_RID_CNFDEFAULTKEY0 + i; - err = zd1201_setconfig(zd, rid, key, erq->length, 1); - if (err) - return err; - zd->encode_keylen[i] = erq->length; - memcpy(zd->encode_keys[i], key, erq->length); - - i=0; - if (!(erq->flags & IW_ENCODE_DISABLED & IW_ENCODE_MODE)) { - i |= 0x01; - zd->encode_enabled = 1; - } else - zd->encode_enabled = 0; - if (erq->flags & IW_ENCODE_RESTRICTED & IW_ENCODE_MODE) { - i |= 0x02; - zd->encode_restricted = 1; - } else - zd->encode_restricted = 0; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFWEBFLAGS, i); - if (err) - return err; - - if (zd->encode_enabled) - i = ZD1201_CNFAUTHENTICATION_SHAREDKEY; - else - i = ZD1201_CNFAUTHENTICATION_OPENSYSTEM; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFAUTHENTICATION, i); - if (err) - return err; - - return zd1201_mac_reset(zd); -} - -static int zd1201_get_encode(struct net_device *dev, - struct iw_request_info *info, struct iw_point *erq, char *key) -{ - struct zd1201 *zd = netdev_priv(dev); - short i; - int err; - - if (zd->encode_enabled) - erq->flags = IW_ENCODE_ENABLED; - else - erq->flags = IW_ENCODE_DISABLED; - if (zd->encode_restricted) - erq->flags |= IW_ENCODE_RESTRICTED; - else - erq->flags |= IW_ENCODE_OPEN; - - i = (erq->flags & IW_ENCODE_INDEX) -1; - if (i == -1) { - err = zd1201_getconfig16(zd, ZD1201_RID_CNFDEFAULTKEYID, &i); - if (err) - return err; - } - if (i<0 || i>= ZD1201_NUMKEYS) - return -EINVAL; - - erq->flags |= i+1; - - erq->length = zd->encode_keylen[i]; - memcpy(key, zd->encode_keys[i], erq->length); - - return 0; -} - -static int zd1201_set_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short enabled, duration, level; - int err; - - enabled = vwrq->disabled ? 0 : 1; - if (enabled) { - if (vwrq->flags & IW_POWER_PERIOD) { - duration = vwrq->value; - err = zd1201_setconfig16(zd, - ZD1201_RID_CNFMAXSLEEPDURATION, duration); - if (err) - return err; - goto out; - } - if (vwrq->flags & IW_POWER_TIMEOUT) { - err = zd1201_getconfig16(zd, - ZD1201_RID_CNFMAXSLEEPDURATION, &duration); - if (err) - return err; - level = vwrq->value * 4 / duration; - if (level > 4) - level = 4; - if (level < 0) - level = 0; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPMEPS, - level); - if (err) - return err; - goto out; - } - return -EINVAL; - } -out: - return zd1201_setconfig16(zd, ZD1201_RID_CNFPMENABLED, enabled); -} - -static int zd1201_get_power(struct net_device *dev, - struct iw_request_info *info, struct iw_param *vwrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short enabled, level, duration; - int err; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMENABLED, &enabled); - if (err) - return err; - err = zd1201_getconfig16(zd, ZD1201_RID_CNFPMEPS, &level); - if (err) - return err; - err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXSLEEPDURATION, &duration); - if (err) - return err; - vwrq->disabled = enabled ? 0 : 1; - if (vwrq->flags & IW_POWER_TYPE) { - if (vwrq->flags & IW_POWER_PERIOD) { - vwrq->value = duration; - vwrq->flags = IW_POWER_PERIOD; - } else { - vwrq->value = duration * level / 4; - vwrq->flags = IW_POWER_TIMEOUT; - } - } - if (vwrq->flags & IW_POWER_MODE) { - if (enabled && level) - vwrq->flags = IW_POWER_UNICAST_R; - else - vwrq->flags = IW_POWER_ALL_R; - } - - return 0; -} - - -static const iw_handler zd1201_iw_handler[] = -{ - (iw_handler) zd1201_config_commit, /* SIOCSIWCOMMIT */ - (iw_handler) zd1201_get_name, /* SIOCGIWNAME */ - (iw_handler) NULL, /* SIOCSIWNWID */ - (iw_handler) NULL, /* SIOCGIWNWID */ - (iw_handler) zd1201_set_freq, /* SIOCSIWFREQ */ - (iw_handler) zd1201_get_freq, /* SIOCGIWFREQ */ - (iw_handler) zd1201_set_mode, /* SIOCSIWMODE */ - (iw_handler) zd1201_get_mode, /* SIOCGIWMODE */ - (iw_handler) NULL, /* SIOCSIWSENS */ - (iw_handler) NULL, /* SIOCGIWSENS */ - (iw_handler) NULL, /* SIOCSIWRANGE */ - (iw_handler) zd1201_get_range, /* SIOCGIWRANGE */ - (iw_handler) NULL, /* SIOCSIWPRIV */ - (iw_handler) NULL, /* SIOCGIWPRIV */ - (iw_handler) NULL, /* SIOCSIWSTATS */ - (iw_handler) NULL, /* SIOCGIWSTATS */ - (iw_handler) NULL, /* SIOCSIWSPY */ - (iw_handler) NULL, /* SIOCGIWSPY */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL/*zd1201_set_wap*/, /* SIOCSIWAP */ - (iw_handler) zd1201_get_wap, /* SIOCGIWAP */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* SIOCGIWAPLIST */ - (iw_handler) zd1201_set_scan, /* SIOCSIWSCAN */ - (iw_handler) zd1201_get_scan, /* SIOCGIWSCAN */ - (iw_handler) zd1201_set_essid, /* SIOCSIWESSID */ - (iw_handler) zd1201_get_essid, /* SIOCGIWESSID */ - (iw_handler) NULL, /* SIOCSIWNICKN */ - (iw_handler) zd1201_get_nick, /* SIOCGIWNICKN */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) NULL, /* -- hole -- */ - (iw_handler) zd1201_set_rate, /* SIOCSIWRATE */ - (iw_handler) zd1201_get_rate, /* SIOCGIWRATE */ - (iw_handler) zd1201_set_rts, /* SIOCSIWRTS */ - (iw_handler) zd1201_get_rts, /* SIOCGIWRTS */ - (iw_handler) zd1201_set_frag, /* SIOCSIWFRAG */ - (iw_handler) zd1201_get_frag, /* SIOCGIWFRAG */ - (iw_handler) NULL, /* SIOCSIWTXPOW */ - (iw_handler) NULL, /* SIOCGIWTXPOW */ - (iw_handler) zd1201_set_retry, /* SIOCSIWRETRY */ - (iw_handler) zd1201_get_retry, /* SIOCGIWRETRY */ - (iw_handler) zd1201_set_encode, /* SIOCSIWENCODE */ - (iw_handler) zd1201_get_encode, /* SIOCGIWENCODE */ - (iw_handler) zd1201_set_power, /* SIOCSIWPOWER */ - (iw_handler) zd1201_get_power, /* SIOCGIWPOWER */ -}; - -static int zd1201_set_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - - if (!zd->ap) - return -EOPNOTSUPP; - - return zd1201_setconfig16(zd, ZD1201_RID_CNFHOSTAUTH, rrq->value); -} - -static int zd1201_get_hostauth(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short hostauth; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFHOSTAUTH, &hostauth); - if (err) - return err; - rrq->value = hostauth; - rrq->fixed = 1; - - return 0; -} - -static int zd1201_auth_sta(struct net_device *dev, - struct iw_request_info *info, struct sockaddr *sta, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - unsigned char buffer[10]; - - if (!zd->ap) - return -EOPNOTSUPP; - - memcpy(buffer, sta->sa_data, ETH_ALEN); - *(short*)(buffer+6) = 0; /* 0==success, 1==failure */ - *(short*)(buffer+8) = 0; - - return zd1201_setconfig(zd, ZD1201_RID_AUTHENTICATESTA, buffer, 10, 1); -} - -static int zd1201_set_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, rrq->value); - if (err) - return err; - return 0; -} - -static int zd1201_get_maxassoc(struct net_device *dev, - struct iw_request_info *info, struct iw_param *rrq, char *extra) -{ - struct zd1201 *zd = netdev_priv(dev); - short maxassoc; - int err; - - if (!zd->ap) - return -EOPNOTSUPP; - - err = zd1201_getconfig16(zd, ZD1201_RID_CNFMAXASSOCSTATIONS, &maxassoc); - if (err) - return err; - rrq->value = maxassoc; - rrq->fixed = 1; - - return 0; -} - -static const iw_handler zd1201_private_handler[] = { - (iw_handler) zd1201_set_hostauth, /* ZD1201SIWHOSTAUTH */ - (iw_handler) zd1201_get_hostauth, /* ZD1201GIWHOSTAUTH */ - (iw_handler) zd1201_auth_sta, /* ZD1201SIWAUTHSTA */ - (iw_handler) NULL, /* nothing to get */ - (iw_handler) zd1201_set_maxassoc, /* ZD1201SIMAXASSOC */ - (iw_handler) zd1201_get_maxassoc, /* ZD1201GIMAXASSOC */ -}; - -static const struct iw_priv_args zd1201_private_args[] = { - { ZD1201SIWHOSTAUTH, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "sethostauth" }, - { ZD1201GIWHOSTAUTH, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "gethostauth" }, - { ZD1201SIWAUTHSTA, IW_PRIV_TYPE_ADDR | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "authstation" }, - { ZD1201SIWMAXASSOC, IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - IW_PRIV_TYPE_NONE, "setmaxassoc" }, - { ZD1201GIWMAXASSOC, IW_PRIV_TYPE_NONE, - IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getmaxassoc" }, -}; - -static const struct iw_handler_def zd1201_iw_handlers = { - .num_standard = ARRAY_SIZE(zd1201_iw_handler), - .num_private = ARRAY_SIZE(zd1201_private_handler), - .num_private_args = ARRAY_SIZE(zd1201_private_args), - .standard = (iw_handler *)zd1201_iw_handler, - .private = (iw_handler *)zd1201_private_handler, - .private_args = (struct iw_priv_args *) zd1201_private_args, - .get_wireless_stats = zd1201_get_wireless_stats, -}; - -static const struct net_device_ops zd1201_netdev_ops = { - .ndo_open = zd1201_net_open, - .ndo_stop = zd1201_net_stop, - .ndo_start_xmit = zd1201_hard_start_xmit, - .ndo_tx_timeout = zd1201_tx_timeout, - .ndo_set_multicast_list = zd1201_set_multicast, - .ndo_set_mac_address = zd1201_set_mac_address, - .ndo_change_mtu = eth_change_mtu, - .ndo_validate_addr = eth_validate_addr, -}; - -static int zd1201_probe(struct usb_interface *interface, - const struct usb_device_id *id) -{ - struct zd1201 *zd; - struct net_device *dev; - struct usb_device *usb; - int err; - short porttype; - char buf[IW_ESSID_MAX_SIZE+2]; - - usb = interface_to_usbdev(interface); - - dev = alloc_etherdev(sizeof(*zd)); - if (!dev) - return -ENOMEM; - zd = netdev_priv(dev); - zd->dev = dev; - - zd->ap = ap; - zd->usb = usb; - zd->removed = 0; - init_waitqueue_head(&zd->rxdataq); - INIT_HLIST_HEAD(&zd->fraglist); - - err = zd1201_fw_upload(usb, zd->ap); - if (err) { - dev_err(&usb->dev, "zd1201 firmware upload failed: %d\n", err); - goto err_zd; - } - - zd->endp_in = 1; - zd->endp_out = 1; - zd->endp_out2 = 2; - zd->rx_urb = usb_alloc_urb(0, GFP_KERNEL); - zd->tx_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!zd->rx_urb || !zd->tx_urb) - goto err_zd; - - mdelay(100); - err = zd1201_drvr_start(zd); - if (err) - goto err_zd; - - err = zd1201_setconfig16(zd, ZD1201_RID_CNFMAXDATALEN, 2312); - if (err) - goto err_start; - - err = zd1201_setconfig16(zd, ZD1201_RID_TXRATECNTL, - ZD1201_RATEB1 | ZD1201_RATEB2 | ZD1201_RATEB5 | ZD1201_RATEB11); - if (err) - goto err_start; - - dev->netdev_ops = &zd1201_netdev_ops; - dev->wireless_handlers = &zd1201_iw_handlers; - dev->watchdog_timeo = ZD1201_TX_TIMEOUT; - strcpy(dev->name, "wlan%d"); - - err = zd1201_getconfig(zd, ZD1201_RID_CNFOWNMACADDR, - dev->dev_addr, dev->addr_len); - if (err) - goto err_start; - - /* Set wildcard essid to match zd->essid */ - *(__le16 *)buf = cpu_to_le16(0); - err = zd1201_setconfig(zd, ZD1201_RID_CNFDESIREDSSID, buf, - IW_ESSID_MAX_SIZE+2, 1); - if (err) - goto err_start; - - if (zd->ap) - porttype = ZD1201_PORTTYPE_AP; - else - porttype = ZD1201_PORTTYPE_BSS; - err = zd1201_setconfig16(zd, ZD1201_RID_CNFPORTTYPE, porttype); - if (err) - goto err_start; - - SET_NETDEV_DEV(dev, &usb->dev); - - err = register_netdev(dev); - if (err) - goto err_start; - dev_info(&usb->dev, "%s: ZD1201 USB Wireless interface\n", - dev->name); - - usb_set_intfdata(interface, zd); - zd1201_enable(zd); /* zd1201 likes to startup enabled, */ - zd1201_disable(zd); /* interfering with all the wifis in range */ - return 0; - -err_start: - /* Leave the device in reset state */ - zd1201_docmd(zd, ZD1201_CMDCODE_INIT, 0, 0, 0); -err_zd: - usb_free_urb(zd->tx_urb); - usb_free_urb(zd->rx_urb); - free_netdev(dev); - return err; -} - -static void zd1201_disconnect(struct usb_interface *interface) -{ - struct zd1201 *zd=(struct zd1201 *)usb_get_intfdata(interface); - struct hlist_node *node, *node2; - struct zd1201_frag *frag; - - if (!zd) - return; - usb_set_intfdata(interface, NULL); - - hlist_for_each_entry_safe(frag, node, node2, &zd->fraglist, fnode) { - hlist_del_init(&frag->fnode); - kfree_skb(frag->skb); - kfree(frag); - } - - if (zd->tx_urb) { - usb_kill_urb(zd->tx_urb); - usb_free_urb(zd->tx_urb); - } - if (zd->rx_urb) { - usb_kill_urb(zd->rx_urb); - usb_free_urb(zd->rx_urb); - } - - if (zd->dev) { - unregister_netdev(zd->dev); - free_netdev(zd->dev); - } -} - -#ifdef CONFIG_PM - -static int zd1201_suspend(struct usb_interface *interface, - pm_message_t message) -{ - struct zd1201 *zd = usb_get_intfdata(interface); - - netif_device_detach(zd->dev); - - zd->was_enabled = zd->mac_enabled; - - if (zd->was_enabled) - return zd1201_disable(zd); - else - return 0; -} - -static int zd1201_resume(struct usb_interface *interface) -{ - struct zd1201 *zd = usb_get_intfdata(interface); - - if (!zd || !zd->dev) - return -ENODEV; - - netif_device_attach(zd->dev); - - if (zd->was_enabled) - return zd1201_enable(zd); - else - return 0; -} - -#else - -#define zd1201_suspend NULL -#define zd1201_resume NULL - -#endif - -static struct usb_driver zd1201_usb = { - .name = "zd1201", - .probe = zd1201_probe, - .disconnect = zd1201_disconnect, - .id_table = zd1201_table, - .suspend = zd1201_suspend, - .resume = zd1201_resume, -}; - -static int __init zd1201_init(void) -{ - return usb_register(&zd1201_usb); -} - -static void __exit zd1201_cleanup(void) -{ - usb_deregister(&zd1201_usb); -} - -module_init(zd1201_init); -module_exit(zd1201_cleanup); diff --git a/drivers/net/wireless/zd1201.h b/drivers/net/wireless/zd1201.h deleted file mode 100644 index dd7ea1f35bef..000000000000 --- a/drivers/net/wireless/zd1201.h +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright (c) 2004, 2005 Jeroen Vreeken (pe1rxq@amsat.org) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * Parts of this driver have been derived from a wlan-ng version - * modified by ZyDAS. - * Copyright (C) 1999 AbsoluteValue Systems, Inc. All Rights Reserved. - */ - -#ifndef _INCLUDE_ZD1201_H_ -#define _INCLUDE_ZD1201_H_ - -#define ZD1201_NUMKEYS 4 -#define ZD1201_MAXKEYLEN 13 -#define ZD1201_MAXMULTI 16 -#define ZD1201_FRAGMAX 2500 -#define ZD1201_FRAGMIN 256 -#define ZD1201_RTSMAX 2500 - -#define ZD1201_RXSIZE 3000 - -struct zd1201 { - struct usb_device *usb; - int removed; - struct net_device *dev; - struct iw_statistics iwstats; - - int endp_in; - int endp_out; - int endp_out2; - struct urb *rx_urb; - struct urb *tx_urb; - - unsigned char rxdata[ZD1201_RXSIZE]; - int rxlen; - wait_queue_head_t rxdataq; - int rxdatas; - struct hlist_head fraglist; - unsigned char txdata[ZD1201_RXSIZE]; - - int ap; - char essid[IW_ESSID_MAX_SIZE+1]; - int essidlen; - int mac_enabled; - int was_enabled; - int monitor; - int encode_enabled; - int encode_restricted; - unsigned char encode_keys[ZD1201_NUMKEYS][ZD1201_MAXKEYLEN]; - int encode_keylen[ZD1201_NUMKEYS]; -}; - -struct zd1201_frag { - struct hlist_node fnode; - int seq; - struct sk_buff *skb; -}; - -#define ZD1201SIWHOSTAUTH SIOCIWFIRSTPRIV -#define ZD1201GIWHOSTAUTH ZD1201SIWHOSTAUTH+1 -#define ZD1201SIWAUTHSTA SIOCIWFIRSTPRIV+2 -#define ZD1201SIWMAXASSOC SIOCIWFIRSTPRIV+4 -#define ZD1201GIWMAXASSOC ZD1201SIWMAXASSOC+1 - -#define ZD1201_FW_TIMEOUT (1000) - -#define ZD1201_TX_TIMEOUT (2000) - -#define ZD1201_USB_CMDREQ 0 -#define ZD1201_USB_RESREQ 1 - -#define ZD1201_CMDCODE_INIT 0x00 -#define ZD1201_CMDCODE_ENABLE 0x01 -#define ZD1201_CMDCODE_DISABLE 0x02 -#define ZD1201_CMDCODE_ALLOC 0x0a -#define ZD1201_CMDCODE_INQUIRE 0x11 -#define ZD1201_CMDCODE_SETRXRID 0x17 -#define ZD1201_CMDCODE_ACCESS 0x21 - -#define ZD1201_PACKET_EVENTSTAT 0x0 -#define ZD1201_PACKET_RXDATA 0x1 -#define ZD1201_PACKET_INQUIRE 0x2 -#define ZD1201_PACKET_RESOURCE 0x3 - -#define ZD1201_ACCESSBIT 0x0100 - -#define ZD1201_RID_CNFPORTTYPE 0xfc00 -#define ZD1201_RID_CNFOWNMACADDR 0xfc01 -#define ZD1201_RID_CNFDESIREDSSID 0xfc02 -#define ZD1201_RID_CNFOWNCHANNEL 0xfc03 -#define ZD1201_RID_CNFOWNSSID 0xfc04 -#define ZD1201_RID_CNFMAXDATALEN 0xfc07 -#define ZD1201_RID_CNFPMENABLED 0xfc09 -#define ZD1201_RID_CNFPMEPS 0xfc0a -#define ZD1201_RID_CNFMAXSLEEPDURATION 0xfc0c -#define ZD1201_RID_CNFDEFAULTKEYID 0xfc23 -#define ZD1201_RID_CNFDEFAULTKEY0 0xfc24 -#define ZD1201_RID_CNFDEFAULTKEY1 0xfc25 -#define ZD1201_RID_CNFDEFAULTKEY2 0xfc26 -#define ZD1201_RID_CNFDEFAULTKEY3 0xfc27 -#define ZD1201_RID_CNFWEBFLAGS 0xfc28 -#define ZD1201_RID_CNFAUTHENTICATION 0xfc2a -#define ZD1201_RID_CNFMAXASSOCSTATIONS 0xfc2b -#define ZD1201_RID_CNFHOSTAUTH 0xfc2e -#define ZD1201_RID_CNFGROUPADDRESS 0xfc80 -#define ZD1201_RID_CNFFRAGTHRESHOLD 0xfc82 -#define ZD1201_RID_CNFRTSTHRESHOLD 0xfc83 -#define ZD1201_RID_TXRATECNTL 0xfc84 -#define ZD1201_RID_PROMISCUOUSMODE 0xfc85 -#define ZD1201_RID_CNFBASICRATES 0xfcb3 -#define ZD1201_RID_AUTHENTICATESTA 0xfce3 -#define ZD1201_RID_CURRENTBSSID 0xfd42 -#define ZD1201_RID_COMMSQUALITY 0xfd43 -#define ZD1201_RID_CURRENTTXRATE 0xfd44 -#define ZD1201_RID_CNFMAXTXBUFFERNUMBER 0xfda0 -#define ZD1201_RID_CURRENTCHANNEL 0xfdc1 - -#define ZD1201_INQ_SCANRESULTS 0xf101 - -#define ZD1201_INF_LINKSTATUS 0xf200 -#define ZD1201_INF_ASSOCSTATUS 0xf201 -#define ZD1201_INF_AUTHREQ 0xf202 - -#define ZD1201_ASSOCSTATUS_STAASSOC 0x1 -#define ZD1201_ASSOCSTATUS_REASSOC 0x2 -#define ZD1201_ASSOCSTATUS_DISASSOC 0x3 -#define ZD1201_ASSOCSTATUS_ASSOCFAIL 0x4 -#define ZD1201_ASSOCSTATUS_AUTHFAIL 0x5 - -#define ZD1201_PORTTYPE_IBSS 0 -#define ZD1201_PORTTYPE_BSS 1 -#define ZD1201_PORTTYPE_WDS 2 -#define ZD1201_PORTTYPE_PSEUDOIBSS 3 -#define ZD1201_PORTTYPE_AP 6 - -#define ZD1201_RATEB1 1 -#define ZD1201_RATEB2 2 -#define ZD1201_RATEB5 4 /* 5.5 really, but 5 is shorter :) */ -#define ZD1201_RATEB11 8 - -#define ZD1201_CNFAUTHENTICATION_OPENSYSTEM 0x0001 -#define ZD1201_CNFAUTHENTICATION_SHAREDKEY 0x0002 - -#endif /* _INCLUDE_ZD1201_H_ */ diff --git a/drivers/net/wireless/zd1211rw/Kconfig b/drivers/net/wireless/zd1211rw/Kconfig deleted file mode 100644 index 74b31eafe72d..000000000000 --- a/drivers/net/wireless/zd1211rw/Kconfig +++ /dev/null @@ -1,19 +0,0 @@ -config ZD1211RW - tristate "ZyDAS ZD1211/ZD1211B USB-wireless support" - depends on USB && MAC80211 && WLAN_80211 && EXPERIMENTAL - select FW_LOADER - ---help--- - This is an experimental driver for the ZyDAS ZD1211/ZD1211B wireless - chip, present in many USB-wireless adapters. - - Device firmware is required alongside this driver. You can download - the firmware distribution from http://zd1211.ath.cx/get-firmware - -config ZD1211RW_DEBUG - bool "ZyDAS ZD1211 debugging" - depends on ZD1211RW - ---help--- - ZD1211 debugging messages. Choosing Y will result in additional debug - messages being saved to your kernel logs, which may help debug any - problems. - diff --git a/drivers/net/wireless/zd1211rw/Makefile b/drivers/net/wireless/zd1211rw/Makefile deleted file mode 100644 index 1907eafb9b16..000000000000 --- a/drivers/net/wireless/zd1211rw/Makefile +++ /dev/null @@ -1,11 +0,0 @@ -obj-$(CONFIG_ZD1211RW) += zd1211rw.o - -zd1211rw-objs := zd_chip.o zd_mac.o \ - zd_rf_al2230.o zd_rf_rf2959.o \ - zd_rf_al7230b.o zd_rf_uw2453.o \ - zd_rf.o zd_usb.o - -ifeq ($(CONFIG_ZD1211RW_DEBUG),y) -EXTRA_CFLAGS += -DDEBUG -endif - diff --git a/drivers/net/wireless/zd1211rw/zd_chip.c b/drivers/net/wireless/zd1211rw/zd_chip.c deleted file mode 100644 index 4e79a9800134..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_chip.c +++ /dev/null @@ -1,1639 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -/* This file implements all the hardware specific functions for the ZD1211 - * and ZD1211B chips. Support for the ZD1211B was possible after Timothy - * Legge sent me a ZD1211B device. Thank you Tim. -- Uli - */ - -#include -#include - -#include "zd_def.h" -#include "zd_chip.h" -#include "zd_mac.h" -#include "zd_rf.h" - -void zd_chip_init(struct zd_chip *chip, - struct ieee80211_hw *hw, - struct usb_interface *intf) -{ - memset(chip, 0, sizeof(*chip)); - mutex_init(&chip->mutex); - zd_usb_init(&chip->usb, hw, intf); - zd_rf_init(&chip->rf); -} - -void zd_chip_clear(struct zd_chip *chip) -{ - ZD_ASSERT(!mutex_is_locked(&chip->mutex)); - zd_usb_clear(&chip->usb); - zd_rf_clear(&chip->rf); - mutex_destroy(&chip->mutex); - ZD_MEMCLEAR(chip, sizeof(*chip)); -} - -static int scnprint_mac_oui(struct zd_chip *chip, char *buffer, size_t size) -{ - u8 *addr = zd_mac_get_perm_addr(zd_chip_to_mac(chip)); - return scnprintf(buffer, size, "%02x-%02x-%02x", - addr[0], addr[1], addr[2]); -} - -/* Prints an identifier line, which will support debugging. */ -static int scnprint_id(struct zd_chip *chip, char *buffer, size_t size) -{ - int i = 0; - - i = scnprintf(buffer, size, "zd1211%s chip ", - zd_chip_is_zd1211b(chip) ? "b" : ""); - i += zd_usb_scnprint_id(&chip->usb, buffer+i, size-i); - i += scnprintf(buffer+i, size-i, " "); - i += scnprint_mac_oui(chip, buffer+i, size-i); - i += scnprintf(buffer+i, size-i, " "); - i += zd_rf_scnprint_id(&chip->rf, buffer+i, size-i); - i += scnprintf(buffer+i, size-i, " pa%1x %c%c%c%c%c", chip->pa_type, - chip->patch_cck_gain ? 'g' : '-', - chip->patch_cr157 ? '7' : '-', - chip->patch_6m_band_edge ? '6' : '-', - chip->new_phy_layout ? 'N' : '-', - chip->al2230s_bit ? 'S' : '-'); - return i; -} - -static void print_id(struct zd_chip *chip) -{ - char buffer[80]; - - scnprint_id(chip, buffer, sizeof(buffer)); - buffer[sizeof(buffer)-1] = 0; - dev_info(zd_chip_dev(chip), "%s\n", buffer); -} - -static zd_addr_t inc_addr(zd_addr_t addr) -{ - u16 a = (u16)addr; - /* Control registers use byte addressing, but everything else uses word - * addressing. */ - if ((a & 0xf000) == CR_START) - a += 2; - else - a += 1; - return (zd_addr_t)a; -} - -/* Read a variable number of 32-bit values. Parameter count is not allowed to - * exceed USB_MAX_IOREAD32_COUNT. - */ -int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, const zd_addr_t *addr, - unsigned int count) -{ - int r; - int i; - zd_addr_t *a16; - u16 *v16; - unsigned int count16; - - if (count > USB_MAX_IOREAD32_COUNT) - return -EINVAL; - - /* Allocate a single memory block for values and addresses. */ - count16 = 2*count; - a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)), - GFP_KERNEL); - if (!a16) { - dev_dbg_f(zd_chip_dev(chip), - "error ENOMEM in allocation of a16\n"); - r = -ENOMEM; - goto out; - } - v16 = (u16 *)(a16 + count16); - - for (i = 0; i < count; i++) { - int j = 2*i; - /* We read the high word always first. */ - a16[j] = inc_addr(addr[i]); - a16[j+1] = addr[i]; - } - - r = zd_ioread16v_locked(chip, v16, a16, count16); - if (r) { - dev_dbg_f(zd_chip_dev(chip), - "error: zd_ioread16v_locked. Error number %d\n", r); - goto out; - } - - for (i = 0; i < count; i++) { - int j = 2*i; - values[i] = (v16[j] << 16) | v16[j+1]; - } - -out: - kfree((void *)a16); - return r; -} - -int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, - unsigned int count) -{ - int i, j, r; - struct zd_ioreq16 *ioreqs16; - unsigned int count16; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - - if (count == 0) - return 0; - if (count > USB_MAX_IOWRITE32_COUNT) - return -EINVAL; - - /* Allocate a single memory block for values and addresses. */ - count16 = 2*count; - ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_KERNEL); - if (!ioreqs16) { - r = -ENOMEM; - dev_dbg_f(zd_chip_dev(chip), - "error %d in ioreqs16 allocation\n", r); - goto out; - } - - for (i = 0; i < count; i++) { - j = 2*i; - /* We write the high word always first. */ - ioreqs16[j].value = ioreqs[i].value >> 16; - ioreqs16[j].addr = inc_addr(ioreqs[i].addr); - ioreqs16[j+1].value = ioreqs[i].value; - ioreqs16[j+1].addr = ioreqs[i].addr; - } - - r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16); -#ifdef DEBUG - if (r) { - dev_dbg_f(zd_chip_dev(chip), - "error %d in zd_usb_write16v\n", r); - } -#endif /* DEBUG */ -out: - kfree(ioreqs16); - return r; -} - -int zd_iowrite16a_locked(struct zd_chip *chip, - const struct zd_ioreq16 *ioreqs, unsigned int count) -{ - int r; - unsigned int i, j, t, max; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - for (i = 0; i < count; i += j + t) { - t = 0; - max = count-i; - if (max > USB_MAX_IOWRITE16_COUNT) - max = USB_MAX_IOWRITE16_COUNT; - for (j = 0; j < max; j++) { - if (!ioreqs[i+j].addr) { - t = 1; - break; - } - } - - r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j); - if (r) { - dev_dbg_f(zd_chip_dev(chip), - "error zd_usb_iowrite16v. Error number %d\n", - r); - return r; - } - } - - return 0; -} - -/* Writes a variable number of 32 bit registers. The functions will split - * that in several USB requests. A split can be forced by inserting an IO - * request with an zero address field. - */ -int zd_iowrite32a_locked(struct zd_chip *chip, - const struct zd_ioreq32 *ioreqs, unsigned int count) -{ - int r; - unsigned int i, j, t, max; - - for (i = 0; i < count; i += j + t) { - t = 0; - max = count-i; - if (max > USB_MAX_IOWRITE32_COUNT) - max = USB_MAX_IOWRITE32_COUNT; - for (j = 0; j < max; j++) { - if (!ioreqs[i+j].addr) { - t = 1; - break; - } - } - - r = _zd_iowrite32v_locked(chip, &ioreqs[i], j); - if (r) { - dev_dbg_f(zd_chip_dev(chip), - "error _zd_iowrite32v_locked." - " Error number %d\n", r); - return r; - } - } - - return 0; -} - -int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_ioread16_locked(chip, value, addr); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_ioread32_locked(chip, value, addr); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_iowrite16_locked(chip, value, addr); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_iowrite32_locked(chip, value, addr); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, - u32 *values, unsigned int count) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_ioread32v_locked(chip, values, addresses, count); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, - unsigned int count) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_iowrite32a_locked(chip, ioreqs, count); - mutex_unlock(&chip->mutex); - return r; -} - -static int read_pod(struct zd_chip *chip, u8 *rf_type) -{ - int r; - u32 value; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_ioread32_locked(chip, &value, E2P_POD); - if (r) - goto error; - dev_dbg_f(zd_chip_dev(chip), "E2P_POD %#010x\n", value); - - /* FIXME: AL2230 handling (Bit 7 in POD) */ - *rf_type = value & 0x0f; - chip->pa_type = (value >> 16) & 0x0f; - chip->patch_cck_gain = (value >> 8) & 0x1; - chip->patch_cr157 = (value >> 13) & 0x1; - chip->patch_6m_band_edge = (value >> 21) & 0x1; - chip->new_phy_layout = (value >> 31) & 0x1; - chip->al2230s_bit = (value >> 7) & 0x1; - chip->link_led = ((value >> 4) & 1) ? LED1 : LED2; - chip->supports_tx_led = 1; - if (value & (1 << 24)) { /* LED scenario */ - if (value & (1 << 29)) - chip->supports_tx_led = 0; - } - - dev_dbg_f(zd_chip_dev(chip), - "RF %s %#01x PA type %#01x patch CCK %d patch CR157 %d " - "patch 6M %d new PHY %d link LED%d tx led %d\n", - zd_rf_name(*rf_type), *rf_type, - chip->pa_type, chip->patch_cck_gain, - chip->patch_cr157, chip->patch_6m_band_edge, - chip->new_phy_layout, - chip->link_led == LED1 ? 1 : 2, - chip->supports_tx_led); - return 0; -error: - *rf_type = 0; - chip->pa_type = 0; - chip->patch_cck_gain = 0; - chip->patch_cr157 = 0; - chip->patch_6m_band_edge = 0; - chip->new_phy_layout = 0; - return r; -} - -/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and - * CR_MAC_ADDR_P2 must be overwritten - */ -int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr) -{ - int r; - struct zd_ioreq32 reqs[2] = { - [0] = { .addr = CR_MAC_ADDR_P1 }, - [1] = { .addr = CR_MAC_ADDR_P2 }, - }; - - if (mac_addr) { - reqs[0].value = (mac_addr[3] << 24) - | (mac_addr[2] << 16) - | (mac_addr[1] << 8) - | mac_addr[0]; - reqs[1].value = (mac_addr[5] << 8) - | mac_addr[4]; - dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr); - } else { - dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n"); - } - - mutex_lock(&chip->mutex); - r = zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain) -{ - int r; - u32 value; - - mutex_lock(&chip->mutex); - r = zd_ioread32_locked(chip, &value, E2P_SUBID); - mutex_unlock(&chip->mutex); - if (r) - return r; - - *regdomain = value >> 16; - dev_dbg_f(zd_chip_dev(chip), "regdomain: %#04x\n", *regdomain); - - return 0; -} - -static int read_values(struct zd_chip *chip, u8 *values, size_t count, - zd_addr_t e2p_addr, u32 guard) -{ - int r; - int i; - u32 v; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - for (i = 0;;) { - r = zd_ioread32_locked(chip, &v, - (zd_addr_t)((u16)e2p_addr+i/2)); - if (r) - return r; - v -= guard; - if (i+4 < count) { - values[i++] = v; - values[i++] = v >> 8; - values[i++] = v >> 16; - values[i++] = v >> 24; - continue; - } - for (;i < count; i++) - values[i] = v >> (8*(i%3)); - return 0; - } -} - -static int read_pwr_cal_values(struct zd_chip *chip) -{ - return read_values(chip, chip->pwr_cal_values, - E2P_CHANNEL_COUNT, E2P_PWR_CAL_VALUE1, - 0); -} - -static int read_pwr_int_values(struct zd_chip *chip) -{ - return read_values(chip, chip->pwr_int_values, - E2P_CHANNEL_COUNT, E2P_PWR_INT_VALUE1, - E2P_PWR_INT_GUARD); -} - -static int read_ofdm_cal_values(struct zd_chip *chip) -{ - int r; - int i; - static const zd_addr_t addresses[] = { - E2P_36M_CAL_VALUE1, - E2P_48M_CAL_VALUE1, - E2P_54M_CAL_VALUE1, - }; - - for (i = 0; i < 3; i++) { - r = read_values(chip, chip->ofdm_cal_values[i], - E2P_CHANNEL_COUNT, addresses[i], 0); - if (r) - return r; - } - return 0; -} - -static int read_cal_int_tables(struct zd_chip *chip) -{ - int r; - - r = read_pwr_cal_values(chip); - if (r) - return r; - r = read_pwr_int_values(chip); - if (r) - return r; - r = read_ofdm_cal_values(chip); - if (r) - return r; - return 0; -} - -/* phy means physical registers */ -int zd_chip_lock_phy_regs(struct zd_chip *chip) -{ - int r; - u32 tmp; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_ioread32_locked(chip, &tmp, CR_REG1); - if (r) { - dev_err(zd_chip_dev(chip), "error ioread32(CR_REG1): %d\n", r); - return r; - } - - tmp &= ~UNLOCK_PHY_REGS; - - r = zd_iowrite32_locked(chip, tmp, CR_REG1); - if (r) - dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); - return r; -} - -int zd_chip_unlock_phy_regs(struct zd_chip *chip) -{ - int r; - u32 tmp; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_ioread32_locked(chip, &tmp, CR_REG1); - if (r) { - dev_err(zd_chip_dev(chip), - "error ioread32(CR_REG1): %d\n", r); - return r; - } - - tmp |= UNLOCK_PHY_REGS; - - r = zd_iowrite32_locked(chip, tmp, CR_REG1); - if (r) - dev_err(zd_chip_dev(chip), "error iowrite32(CR_REG1): %d\n", r); - return r; -} - -/* CR157 can be optionally patched by the EEPROM for original ZD1211 */ -static int patch_cr157(struct zd_chip *chip) -{ - int r; - u16 value; - - if (!chip->patch_cr157) - return 0; - - r = zd_ioread16_locked(chip, &value, E2P_PHY_REG); - if (r) - return r; - - dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value >> 8); - return zd_iowrite32_locked(chip, value >> 8, CR157); -} - -/* - * 6M band edge can be optionally overwritten for certain RF's - * Vendor driver says: for FCC regulation, enabled per HWFeature 6M band edge - * bit (for AL2230, AL2230S) - */ -static int patch_6m_band_edge(struct zd_chip *chip, u8 channel) -{ - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - if (!chip->patch_6m_band_edge) - return 0; - - return zd_rf_patch_6m_band_edge(&chip->rf, channel); -} - -/* Generic implementation of 6M band edge patching, used by most RFs via - * zd_rf_generic_patch_6m() */ -int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel) -{ - struct zd_ioreq16 ioreqs[] = { - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR47, 0x1e }, - }; - - /* FIXME: Channel 11 is not the edge for all regulatory domains. */ - if (channel == 1 || channel == 11) - ioreqs[0].value = 0x12; - - dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel); - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int zd1211_hw_reset_phy(struct zd_chip *chip) -{ - static const struct zd_ioreq16 ioreqs[] = { - { CR0, 0x0a }, { CR1, 0x06 }, { CR2, 0x26 }, - { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xa0 }, - { CR10, 0x81 }, { CR11, 0x00 }, { CR12, 0x7f }, - { CR13, 0x8c }, { CR14, 0x80 }, { CR15, 0x3d }, - { CR16, 0x20 }, { CR17, 0x1e }, { CR18, 0x0a }, - { CR19, 0x48 }, { CR20, 0x0c }, { CR21, 0x0c }, - { CR22, 0x23 }, { CR23, 0x90 }, { CR24, 0x14 }, - { CR25, 0x40 }, { CR26, 0x10 }, { CR27, 0x19 }, - { CR28, 0x7f }, { CR29, 0x80 }, { CR30, 0x4b }, - { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, - { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, - { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, - { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, - { CR43, 0x10 }, { CR44, 0x12 }, { CR46, 0xff }, - { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, - { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, - { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, - { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, - { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, - { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, - { CR79, 0x68 }, { CR80, 0x64 }, { CR81, 0x64 }, - { CR82, 0x00 }, { CR83, 0x00 }, { CR84, 0x00 }, - { CR85, 0x02 }, { CR86, 0x00 }, { CR87, 0x00 }, - { CR88, 0xff }, { CR89, 0xfc }, { CR90, 0x00 }, - { CR91, 0x00 }, { CR92, 0x00 }, { CR93, 0x08 }, - { CR94, 0x00 }, { CR95, 0x00 }, { CR96, 0xff }, - { CR97, 0xe7 }, { CR98, 0x00 }, { CR99, 0x00 }, - { CR100, 0x00 }, { CR101, 0xae }, { CR102, 0x02 }, - { CR103, 0x00 }, { CR104, 0x03 }, { CR105, 0x65 }, - { CR106, 0x04 }, { CR107, 0x00 }, { CR108, 0x0a }, - { CR109, 0xaa }, { CR110, 0xaa }, { CR111, 0x25 }, - { CR112, 0x25 }, { CR113, 0x00 }, { CR119, 0x1e }, - { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, - { }, - { CR5, 0x00 }, { CR6, 0x00 }, { CR7, 0x00 }, - { CR8, 0x00 }, { CR9, 0x20 }, { CR12, 0xf0 }, - { CR20, 0x0e }, { CR21, 0x0e }, { CR27, 0x10 }, - { CR44, 0x33 }, { CR47, 0x1E }, { CR83, 0x24 }, - { CR84, 0x04 }, { CR85, 0x00 }, { CR86, 0x0C }, - { CR87, 0x12 }, { CR88, 0x0C }, { CR89, 0x00 }, - { CR90, 0x10 }, { CR91, 0x08 }, { CR93, 0x00 }, - { CR94, 0x01 }, { CR95, 0x00 }, { CR96, 0x50 }, - { CR97, 0x37 }, { CR98, 0x35 }, { CR101, 0x13 }, - { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, - { CR105, 0x12 }, { CR109, 0x27 }, { CR110, 0x27 }, - { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, - { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, - { CR117, 0xfc }, { CR118, 0xfa }, { CR120, 0x4f }, - { CR125, 0xaa }, { CR127, 0x03 }, { CR128, 0x14 }, - { CR129, 0x12 }, { CR130, 0x10 }, { CR131, 0x0C }, - { CR136, 0xdf }, { CR137, 0x40 }, { CR138, 0xa0 }, - { CR139, 0xb0 }, { CR140, 0x99 }, { CR141, 0x82 }, - { CR142, 0x54 }, { CR143, 0x1c }, { CR144, 0x6c }, - { CR147, 0x07 }, { CR148, 0x4c }, { CR149, 0x50 }, - { CR150, 0x0e }, { CR151, 0x18 }, { CR160, 0xfe }, - { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, - { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, - { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, - { CR170, 0xba }, { CR171, 0xba }, - /* Note: CR204 must lead the CR203 */ - { CR204, 0x7d }, - { }, - { CR203, 0x30 }, - }; - - int r, t; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - - r = zd_chip_lock_phy_regs(chip); - if (r) - goto out; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - goto unlock; - - r = patch_cr157(chip); -unlock: - t = zd_chip_unlock_phy_regs(chip); - if (t && !r) - r = t; -out: - return r; -} - -static int zd1211b_hw_reset_phy(struct zd_chip *chip) -{ - static const struct zd_ioreq16 ioreqs[] = { - { CR0, 0x14 }, { CR1, 0x06 }, { CR2, 0x26 }, - { CR3, 0x38 }, { CR4, 0x80 }, { CR9, 0xe0 }, - { CR10, 0x81 }, - /* power control { { CR11, 1 << 6 }, */ - { CR11, 0x00 }, - { CR12, 0xf0 }, { CR13, 0x8c }, { CR14, 0x80 }, - { CR15, 0x3d }, { CR16, 0x20 }, { CR17, 0x1e }, - { CR18, 0x0a }, { CR19, 0x48 }, - { CR20, 0x10 }, /* Org:0x0E, ComTrend:RalLink AP */ - { CR21, 0x0e }, { CR22, 0x23 }, { CR23, 0x90 }, - { CR24, 0x14 }, { CR25, 0x40 }, { CR26, 0x10 }, - { CR27, 0x10 }, { CR28, 0x7f }, { CR29, 0x80 }, - { CR30, 0x4b }, /* ASIC/FWT, no jointly decoder */ - { CR31, 0x60 }, { CR32, 0x43 }, { CR33, 0x08 }, - { CR34, 0x06 }, { CR35, 0x0a }, { CR36, 0x00 }, - { CR37, 0x00 }, { CR38, 0x38 }, { CR39, 0x0c }, - { CR40, 0x84 }, { CR41, 0x2a }, { CR42, 0x80 }, - { CR43, 0x10 }, { CR44, 0x33 }, { CR46, 0xff }, - { CR47, 0x1E }, { CR48, 0x26 }, { CR49, 0x5b }, - { CR64, 0xd0 }, { CR65, 0x04 }, { CR66, 0x58 }, - { CR67, 0xc9 }, { CR68, 0x88 }, { CR69, 0x41 }, - { CR70, 0x23 }, { CR71, 0x10 }, { CR72, 0xff }, - { CR73, 0x32 }, { CR74, 0x30 }, { CR75, 0x65 }, - { CR76, 0x41 }, { CR77, 0x1b }, { CR78, 0x30 }, - { CR79, 0xf0 }, { CR80, 0x64 }, { CR81, 0x64 }, - { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, - { CR85, 0x00 }, { CR86, 0x0c }, { CR87, 0x12 }, - { CR88, 0x0c }, { CR89, 0x00 }, { CR90, 0x58 }, - { CR91, 0x04 }, { CR92, 0x00 }, { CR93, 0x00 }, - { CR94, 0x01 }, - { CR95, 0x20 }, /* ZD1211B */ - { CR96, 0x50 }, { CR97, 0x37 }, { CR98, 0x35 }, - { CR99, 0x00 }, { CR100, 0x01 }, { CR101, 0x13 }, - { CR102, 0x27 }, { CR103, 0x27 }, { CR104, 0x18 }, - { CR105, 0x12 }, { CR106, 0x04 }, { CR107, 0x00 }, - { CR108, 0x0a }, { CR109, 0x27 }, { CR110, 0x27 }, - { CR111, 0x27 }, { CR112, 0x27 }, { CR113, 0x27 }, - { CR114, 0x27 }, { CR115, 0x26 }, { CR116, 0x24 }, - { CR117, 0xfc }, { CR118, 0xfa }, { CR119, 0x1e }, - { CR125, 0x90 }, { CR126, 0x00 }, { CR127, 0x00 }, - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR131, 0x0c }, { CR136, 0xdf }, { CR137, 0xa0 }, - { CR138, 0xa8 }, { CR139, 0xb4 }, { CR140, 0x98 }, - { CR141, 0x82 }, { CR142, 0x53 }, { CR143, 0x1c }, - { CR144, 0x6c }, { CR147, 0x07 }, { CR148, 0x40 }, - { CR149, 0x40 }, /* Org:0x50 ComTrend:RalLink AP */ - { CR150, 0x14 }, /* Org:0x0E ComTrend:RalLink AP */ - { CR151, 0x18 }, { CR159, 0x70 }, { CR160, 0xfe }, - { CR161, 0xee }, { CR162, 0xaa }, { CR163, 0xfa }, - { CR164, 0xfa }, { CR165, 0xea }, { CR166, 0xbe }, - { CR167, 0xbe }, { CR168, 0x6a }, { CR169, 0xba }, - { CR170, 0xba }, { CR171, 0xba }, - /* Note: CR204 must lead the CR203 */ - { CR204, 0x7d }, - {}, - { CR203, 0x30 }, - }; - - int r, t; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - - r = zd_chip_lock_phy_regs(chip); - if (r) - goto out; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - t = zd_chip_unlock_phy_regs(chip); - if (t && !r) - r = t; -out: - return r; -} - -static int hw_reset_phy(struct zd_chip *chip) -{ - return zd_chip_is_zd1211b(chip) ? zd1211b_hw_reset_phy(chip) : - zd1211_hw_reset_phy(chip); -} - -static int zd1211_hw_init_hmac(struct zd_chip *chip) -{ - static const struct zd_ioreq32 ioreqs[] = { - { CR_ZD1211_RETRY_MAX, 0x2 }, - { CR_RX_THRESHOLD, 0x000c0640 }, - }; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int zd1211b_hw_init_hmac(struct zd_chip *chip) -{ - static const struct zd_ioreq32 ioreqs[] = { - { CR_ZD1211B_RETRY_MAX, 0x02020202 }, - { CR_ZD1211B_CWIN_MAX_MIN_AC0, 0x007f003f }, - { CR_ZD1211B_CWIN_MAX_MIN_AC1, 0x007f003f }, - { CR_ZD1211B_CWIN_MAX_MIN_AC2, 0x003f001f }, - { CR_ZD1211B_CWIN_MAX_MIN_AC3, 0x001f000f }, - { CR_ZD1211B_AIFS_CTL1, 0x00280028 }, - { CR_ZD1211B_AIFS_CTL2, 0x008C003C }, - { CR_ZD1211B_TXOP, 0x01800824 }, - { CR_RX_THRESHOLD, 0x000c0eff, }, - }; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int hw_init_hmac(struct zd_chip *chip) -{ - int r; - static const struct zd_ioreq32 ioreqs[] = { - { CR_ACK_TIMEOUT_EXT, 0x20 }, - { CR_ADDA_MBIAS_WARMTIME, 0x30000808 }, - { CR_SNIFFER_ON, 0 }, - { CR_RX_FILTER, STA_RX_FILTER }, - { CR_GROUP_HASH_P1, 0x00 }, - { CR_GROUP_HASH_P2, 0x80000000 }, - { CR_REG1, 0xa4 }, - { CR_ADDA_PWR_DWN, 0x7f }, - { CR_BCN_PLCP_CFG, 0x00f00401 }, - { CR_PHY_DELAY, 0x00 }, - { CR_ACK_TIMEOUT_EXT, 0x80 }, - { CR_ADDA_PWR_DWN, 0x00 }, - { CR_ACK_TIME_80211, 0x100 }, - { CR_RX_PE_DELAY, 0x70 }, - { CR_PS_CTRL, 0x10000000 }, - { CR_RTS_CTS_RATE, 0x02030203 }, - { CR_AFTER_PNP, 0x1 }, - { CR_WEP_PROTECT, 0x114 }, - { CR_IFS_VALUE, IFS_VALUE_DEFAULT }, - { CR_CAM_MODE, MODE_AP_WDS}, - }; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_iowrite32a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - - return zd_chip_is_zd1211b(chip) ? - zd1211b_hw_init_hmac(chip) : zd1211_hw_init_hmac(chip); -} - -struct aw_pt_bi { - u32 atim_wnd_period; - u32 pre_tbtt; - u32 beacon_interval; -}; - -static int get_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) -{ - int r; - static const zd_addr_t aw_pt_bi_addr[] = - { CR_ATIM_WND_PERIOD, CR_PRE_TBTT, CR_BCN_INTERVAL }; - u32 values[3]; - - r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr, - ARRAY_SIZE(aw_pt_bi_addr)); - if (r) { - memset(s, 0, sizeof(*s)); - return r; - } - - s->atim_wnd_period = values[0]; - s->pre_tbtt = values[1]; - s->beacon_interval = values[2]; - return 0; -} - -static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s) -{ - struct zd_ioreq32 reqs[3]; - - if (s->beacon_interval <= 5) - s->beacon_interval = 5; - if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval) - s->pre_tbtt = s->beacon_interval - 1; - if (s->atim_wnd_period >= s->pre_tbtt) - s->atim_wnd_period = s->pre_tbtt - 1; - - reqs[0].addr = CR_ATIM_WND_PERIOD; - reqs[0].value = s->atim_wnd_period; - reqs[1].addr = CR_PRE_TBTT; - reqs[1].value = s->pre_tbtt; - reqs[2].addr = CR_BCN_INTERVAL; - reqs[2].value = s->beacon_interval; - - return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs)); -} - - -static int set_beacon_interval(struct zd_chip *chip, u32 interval) -{ - int r; - struct aw_pt_bi s; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = get_aw_pt_bi(chip, &s); - if (r) - return r; - s.beacon_interval = interval; - return set_aw_pt_bi(chip, &s); -} - -int zd_set_beacon_interval(struct zd_chip *chip, u32 interval) -{ - int r; - - mutex_lock(&chip->mutex); - r = set_beacon_interval(chip, interval); - mutex_unlock(&chip->mutex); - return r; -} - -static int hw_init(struct zd_chip *chip) -{ - int r; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = hw_reset_phy(chip); - if (r) - return r; - - r = hw_init_hmac(chip); - if (r) - return r; - - return set_beacon_interval(chip, 100); -} - -static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset) -{ - return (zd_addr_t)((u16)chip->fw_regs_base + offset); -} - -#ifdef DEBUG -static int dump_cr(struct zd_chip *chip, const zd_addr_t addr, - const char *addr_string) -{ - int r; - u32 value; - - r = zd_ioread32_locked(chip, &value, addr); - if (r) { - dev_dbg_f(zd_chip_dev(chip), - "error reading %s. Error number %d\n", addr_string, r); - return r; - } - - dev_dbg_f(zd_chip_dev(chip), "%s %#010x\n", - addr_string, (unsigned int)value); - return 0; -} - -static int test_init(struct zd_chip *chip) -{ - int r; - - r = dump_cr(chip, CR_AFTER_PNP, "CR_AFTER_PNP"); - if (r) - return r; - r = dump_cr(chip, CR_GPI_EN, "CR_GPI_EN"); - if (r) - return r; - return dump_cr(chip, CR_INTERRUPT, "CR_INTERRUPT"); -} - -static void dump_fw_registers(struct zd_chip *chip) -{ - const zd_addr_t addr[4] = { - fw_reg_addr(chip, FW_REG_FIRMWARE_VER), - fw_reg_addr(chip, FW_REG_USB_SPEED), - fw_reg_addr(chip, FW_REG_FIX_TX_RATE), - fw_reg_addr(chip, FW_REG_LED_LINK_STATUS), - }; - - int r; - u16 values[4]; - - r = zd_ioread16v_locked(chip, values, (const zd_addr_t*)addr, - ARRAY_SIZE(addr)); - if (r) { - dev_dbg_f(zd_chip_dev(chip), "error %d zd_ioread16v_locked\n", - r); - return; - } - - dev_dbg_f(zd_chip_dev(chip), "FW_FIRMWARE_VER %#06hx\n", values[0]); - dev_dbg_f(zd_chip_dev(chip), "FW_USB_SPEED %#06hx\n", values[1]); - dev_dbg_f(zd_chip_dev(chip), "FW_FIX_TX_RATE %#06hx\n", values[2]); - dev_dbg_f(zd_chip_dev(chip), "FW_LINK_STATUS %#06hx\n", values[3]); -} -#endif /* DEBUG */ - -static int print_fw_version(struct zd_chip *chip) -{ - int r; - u16 version; - - r = zd_ioread16_locked(chip, &version, - fw_reg_addr(chip, FW_REG_FIRMWARE_VER)); - if (r) - return r; - - dev_info(zd_chip_dev(chip),"firmware version %04hx\n", version); - return 0; -} - -static int set_mandatory_rates(struct zd_chip *chip, int gmode) -{ - u32 rates; - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - /* This sets the mandatory rates, which only depend from the standard - * that the device is supporting. Until further notice we should try - * to support 802.11g also for full speed USB. - */ - if (!gmode) - rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M; - else - rates = CR_RATE_1M|CR_RATE_2M|CR_RATE_5_5M|CR_RATE_11M| - CR_RATE_6M|CR_RATE_12M|CR_RATE_24M; - - return zd_iowrite32_locked(chip, rates, CR_MANDATORY_RATE_TBL); -} - -int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, - int preamble) -{ - u32 value = 0; - - dev_dbg_f(zd_chip_dev(chip), "preamble=%x\n", preamble); - value |= preamble << RTSCTS_SH_RTS_PMB_TYPE; - value |= preamble << RTSCTS_SH_CTS_PMB_TYPE; - - /* We always send 11M RTS/self-CTS messages, like the vendor driver. */ - value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_RTS_RATE; - value |= ZD_RX_CCK << RTSCTS_SH_RTS_MOD_TYPE; - value |= ZD_PURE_RATE(ZD_CCK_RATE_11M) << RTSCTS_SH_CTS_RATE; - value |= ZD_RX_CCK << RTSCTS_SH_CTS_MOD_TYPE; - - return zd_iowrite32_locked(chip, value, CR_RTS_CTS_RATE); -} - -int zd_chip_enable_hwint(struct zd_chip *chip) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_iowrite32_locked(chip, HWINT_ENABLED, CR_INTERRUPT); - mutex_unlock(&chip->mutex); - return r; -} - -static int disable_hwint(struct zd_chip *chip) -{ - return zd_iowrite32_locked(chip, HWINT_DISABLED, CR_INTERRUPT); -} - -int zd_chip_disable_hwint(struct zd_chip *chip) -{ - int r; - - mutex_lock(&chip->mutex); - r = disable_hwint(chip); - mutex_unlock(&chip->mutex); - return r; -} - -static int read_fw_regs_offset(struct zd_chip *chip) -{ - int r; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_ioread16_locked(chip, (u16*)&chip->fw_regs_base, - FWRAW_REGS_ADDR); - if (r) - return r; - dev_dbg_f(zd_chip_dev(chip), "fw_regs_base: %#06hx\n", - (u16)chip->fw_regs_base); - - return 0; -} - -/* Read mac address using pre-firmware interface */ -int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr) -{ - dev_dbg_f(zd_chip_dev(chip), "\n"); - return zd_usb_read_fw(&chip->usb, E2P_MAC_ADDR_P1, addr, - ETH_ALEN); -} - -int zd_chip_init_hw(struct zd_chip *chip) -{ - int r; - u8 rf_type; - - dev_dbg_f(zd_chip_dev(chip), "\n"); - - mutex_lock(&chip->mutex); - -#ifdef DEBUG - r = test_init(chip); - if (r) - goto out; -#endif - r = zd_iowrite32_locked(chip, 1, CR_AFTER_PNP); - if (r) - goto out; - - r = read_fw_regs_offset(chip); - if (r) - goto out; - - /* GPI is always disabled, also in the other driver. - */ - r = zd_iowrite32_locked(chip, 0, CR_GPI_EN); - if (r) - goto out; - r = zd_iowrite32_locked(chip, CWIN_SIZE, CR_CWMIN_CWMAX); - if (r) - goto out; - /* Currently we support IEEE 802.11g for full and high speed USB. - * It might be discussed, whether we should suppport pure b mode for - * full speed USB. - */ - r = set_mandatory_rates(chip, 1); - if (r) - goto out; - /* Disabling interrupts is certainly a smart thing here. - */ - r = disable_hwint(chip); - if (r) - goto out; - r = read_pod(chip, &rf_type); - if (r) - goto out; - r = hw_init(chip); - if (r) - goto out; - r = zd_rf_init_hw(&chip->rf, rf_type); - if (r) - goto out; - - r = print_fw_version(chip); - if (r) - goto out; - -#ifdef DEBUG - dump_fw_registers(chip); - r = test_init(chip); - if (r) - goto out; -#endif /* DEBUG */ - - r = read_cal_int_tables(chip); - if (r) - goto out; - - print_id(chip); -out: - mutex_unlock(&chip->mutex); - return r; -} - -static int update_pwr_int(struct zd_chip *chip, u8 channel) -{ - u8 value = chip->pwr_int_values[channel - 1]; - return zd_iowrite16_locked(chip, value, CR31); -} - -static int update_pwr_cal(struct zd_chip *chip, u8 channel) -{ - u8 value = chip->pwr_cal_values[channel-1]; - return zd_iowrite16_locked(chip, value, CR68); -} - -static int update_ofdm_cal(struct zd_chip *chip, u8 channel) -{ - struct zd_ioreq16 ioreqs[3]; - - ioreqs[0].addr = CR67; - ioreqs[0].value = chip->ofdm_cal_values[OFDM_36M_INDEX][channel-1]; - ioreqs[1].addr = CR66; - ioreqs[1].value = chip->ofdm_cal_values[OFDM_48M_INDEX][channel-1]; - ioreqs[2].addr = CR65; - ioreqs[2].value = chip->ofdm_cal_values[OFDM_54M_INDEX][channel-1]; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int update_channel_integration_and_calibration(struct zd_chip *chip, - u8 channel) -{ - int r; - - if (!zd_rf_should_update_pwr_int(&chip->rf)) - return 0; - - r = update_pwr_int(chip, channel); - if (r) - return r; - if (zd_chip_is_zd1211b(chip)) { - static const struct zd_ioreq16 ioreqs[] = { - { CR69, 0x28 }, - {}, - { CR69, 0x2a }, - }; - - r = update_ofdm_cal(chip, channel); - if (r) - return r; - r = update_pwr_cal(chip, channel); - if (r) - return r; - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - } - - return 0; -} - -/* The CCK baseband gain can be optionally patched by the EEPROM */ -static int patch_cck_gain(struct zd_chip *chip) -{ - int r; - u32 value; - - if (!chip->patch_cck_gain || !zd_rf_should_patch_cck_gain(&chip->rf)) - return 0; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_ioread32_locked(chip, &value, E2P_PHY_REG); - if (r) - return r; - dev_dbg_f(zd_chip_dev(chip), "patching value %x\n", value & 0xff); - return zd_iowrite16_locked(chip, value & 0xff, CR47); -} - -int zd_chip_set_channel(struct zd_chip *chip, u8 channel) -{ - int r, t; - - mutex_lock(&chip->mutex); - r = zd_chip_lock_phy_regs(chip); - if (r) - goto out; - r = zd_rf_set_channel(&chip->rf, channel); - if (r) - goto unlock; - r = update_channel_integration_and_calibration(chip, channel); - if (r) - goto unlock; - r = patch_cck_gain(chip); - if (r) - goto unlock; - r = patch_6m_band_edge(chip, channel); - if (r) - goto unlock; - r = zd_iowrite32_locked(chip, 0, CR_CONFIG_PHILIPS); -unlock: - t = zd_chip_unlock_phy_regs(chip); - if (t && !r) - r = t; -out: - mutex_unlock(&chip->mutex); - return r; -} - -u8 zd_chip_get_channel(struct zd_chip *chip) -{ - u8 channel; - - mutex_lock(&chip->mutex); - channel = chip->rf.channel; - mutex_unlock(&chip->mutex); - return channel; -} - -int zd_chip_control_leds(struct zd_chip *chip, enum led_status status) -{ - const zd_addr_t a[] = { - fw_reg_addr(chip, FW_REG_LED_LINK_STATUS), - CR_LED, - }; - - int r; - u16 v[ARRAY_SIZE(a)]; - struct zd_ioreq16 ioreqs[ARRAY_SIZE(a)] = { - [0] = { fw_reg_addr(chip, FW_REG_LED_LINK_STATUS) }, - [1] = { CR_LED }, - }; - u16 other_led; - - mutex_lock(&chip->mutex); - r = zd_ioread16v_locked(chip, v, (const zd_addr_t *)a, ARRAY_SIZE(a)); - if (r) - goto out; - - other_led = chip->link_led == LED1 ? LED2 : LED1; - - switch (status) { - case ZD_LED_OFF: - ioreqs[0].value = FW_LINK_OFF; - ioreqs[1].value = v[1] & ~(LED1|LED2); - break; - case ZD_LED_SCANNING: - ioreqs[0].value = FW_LINK_OFF; - ioreqs[1].value = v[1] & ~other_led; - if (get_seconds() % 3 == 0) { - ioreqs[1].value &= ~chip->link_led; - } else { - ioreqs[1].value |= chip->link_led; - } - break; - case ZD_LED_ASSOCIATED: - ioreqs[0].value = FW_LINK_TX; - ioreqs[1].value = v[1] & ~other_led; - ioreqs[1].value |= chip->link_led; - break; - default: - r = -EINVAL; - goto out; - } - - if (v[0] != ioreqs[0].value || v[1] != ioreqs[1].value) { - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - goto out; - } - r = 0; -out: - mutex_unlock(&chip->mutex); - return r; -} - -int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates) -{ - int r; - - if (cr_rates & ~(CR_RATES_80211B|CR_RATES_80211G)) - return -EINVAL; - - mutex_lock(&chip->mutex); - r = zd_iowrite32_locked(chip, cr_rates, CR_BASIC_RATE_TBL); - mutex_unlock(&chip->mutex); - return r; -} - -static int ofdm_qual_db(u8 status_quality, u8 zd_rate, unsigned int size) -{ - static const u16 constants[] = { - 715, 655, 585, 540, 470, 410, 360, 315, - 270, 235, 205, 175, 150, 125, 105, 85, - 65, 50, 40, 25, 15 - }; - - int i; - u32 x; - - /* It seems that their quality parameter is somehow per signal - * and is now transferred per bit. - */ - switch (zd_rate) { - case ZD_OFDM_RATE_6M: - case ZD_OFDM_RATE_12M: - case ZD_OFDM_RATE_24M: - size *= 2; - break; - case ZD_OFDM_RATE_9M: - case ZD_OFDM_RATE_18M: - case ZD_OFDM_RATE_36M: - case ZD_OFDM_RATE_54M: - size *= 4; - size /= 3; - break; - case ZD_OFDM_RATE_48M: - size *= 3; - size /= 2; - break; - default: - return -EINVAL; - } - - x = (10000 * status_quality)/size; - for (i = 0; i < ARRAY_SIZE(constants); i++) { - if (x > constants[i]) - break; - } - - switch (zd_rate) { - case ZD_OFDM_RATE_6M: - case ZD_OFDM_RATE_9M: - i += 3; - break; - case ZD_OFDM_RATE_12M: - case ZD_OFDM_RATE_18M: - i += 5; - break; - case ZD_OFDM_RATE_24M: - case ZD_OFDM_RATE_36M: - i += 9; - break; - case ZD_OFDM_RATE_48M: - case ZD_OFDM_RATE_54M: - i += 15; - break; - default: - return -EINVAL; - } - - return i; -} - -static int ofdm_qual_percent(u8 status_quality, u8 zd_rate, unsigned int size) -{ - int r; - - r = ofdm_qual_db(status_quality, zd_rate, size); - ZD_ASSERT(r >= 0); - if (r < 0) - r = 0; - - r = (r * 100)/29; - return r <= 100 ? r : 100; -} - -static unsigned int log10times100(unsigned int x) -{ - static const u8 log10[] = { - 0, - 0, 30, 47, 60, 69, 77, 84, 90, 95, 100, - 104, 107, 111, 114, 117, 120, 123, 125, 127, 130, - 132, 134, 136, 138, 139, 141, 143, 144, 146, 147, - 149, 150, 151, 153, 154, 155, 156, 157, 159, 160, - 161, 162, 163, 164, 165, 166, 167, 168, 169, 169, - 170, 171, 172, 173, 174, 174, 175, 176, 177, 177, - 178, 179, 179, 180, 181, 181, 182, 183, 183, 184, - 185, 185, 186, 186, 187, 188, 188, 189, 189, 190, - 190, 191, 191, 192, 192, 193, 193, 194, 194, 195, - 195, 196, 196, 197, 197, 198, 198, 199, 199, 200, - 200, 200, 201, 201, 202, 202, 202, 203, 203, 204, - 204, 204, 205, 205, 206, 206, 206, 207, 207, 207, - 208, 208, 208, 209, 209, 210, 210, 210, 211, 211, - 211, 212, 212, 212, 213, 213, 213, 213, 214, 214, - 214, 215, 215, 215, 216, 216, 216, 217, 217, 217, - 217, 218, 218, 218, 219, 219, 219, 219, 220, 220, - 220, 220, 221, 221, 221, 222, 222, 222, 222, 223, - 223, 223, 223, 224, 224, 224, 224, - }; - - return x < ARRAY_SIZE(log10) ? log10[x] : 225; -} - -enum { - MAX_CCK_EVM_DB = 45, -}; - -static int cck_evm_db(u8 status_quality) -{ - return (20 * log10times100(status_quality)) / 100; -} - -static int cck_snr_db(u8 status_quality) -{ - int r = MAX_CCK_EVM_DB - cck_evm_db(status_quality); - ZD_ASSERT(r >= 0); - return r; -} - -static int cck_qual_percent(u8 status_quality) -{ - int r; - - r = cck_snr_db(status_quality); - r = (100*r)/17; - return r <= 100 ? r : 100; -} - -static inline u8 zd_rate_from_ofdm_plcp_header(const void *rx_frame) -{ - return ZD_OFDM | zd_ofdm_plcp_header_rate(rx_frame); -} - -u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, - const struct rx_status *status) -{ - return (status->frame_status&ZD_RX_OFDM) ? - ofdm_qual_percent(status->signal_quality_ofdm, - zd_rate_from_ofdm_plcp_header(rx_frame), - size) : - cck_qual_percent(status->signal_quality_cck); -} - -/** - * zd_rx_rate - report zd-rate - * @rx_frame - received frame - * @rx_status - rx_status as given by the device - * - * This function converts the rate as encoded in the received packet to the - * zd-rate, we are using on other places in the driver. - */ -u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status) -{ - u8 zd_rate; - if (status->frame_status & ZD_RX_OFDM) { - zd_rate = zd_rate_from_ofdm_plcp_header(rx_frame); - } else { - switch (zd_cck_plcp_header_signal(rx_frame)) { - case ZD_CCK_PLCP_SIGNAL_1M: - zd_rate = ZD_CCK_RATE_1M; - break; - case ZD_CCK_PLCP_SIGNAL_2M: - zd_rate = ZD_CCK_RATE_2M; - break; - case ZD_CCK_PLCP_SIGNAL_5M5: - zd_rate = ZD_CCK_RATE_5_5M; - break; - case ZD_CCK_PLCP_SIGNAL_11M: - zd_rate = ZD_CCK_RATE_11M; - break; - default: - zd_rate = 0; - } - } - - return zd_rate; -} - -int zd_chip_switch_radio_on(struct zd_chip *chip) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_switch_radio_on(&chip->rf); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_chip_switch_radio_off(struct zd_chip *chip) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_switch_radio_off(&chip->rf); - mutex_unlock(&chip->mutex); - return r; -} - -int zd_chip_enable_int(struct zd_chip *chip) -{ - int r; - - mutex_lock(&chip->mutex); - r = zd_usb_enable_int(&chip->usb); - mutex_unlock(&chip->mutex); - return r; -} - -void zd_chip_disable_int(struct zd_chip *chip) -{ - mutex_lock(&chip->mutex); - zd_usb_disable_int(&chip->usb); - mutex_unlock(&chip->mutex); -} - -int zd_chip_enable_rxtx(struct zd_chip *chip) -{ - int r; - - mutex_lock(&chip->mutex); - zd_usb_enable_tx(&chip->usb); - r = zd_usb_enable_rx(&chip->usb); - mutex_unlock(&chip->mutex); - return r; -} - -void zd_chip_disable_rxtx(struct zd_chip *chip) -{ - mutex_lock(&chip->mutex); - zd_usb_disable_rx(&chip->usb); - zd_usb_disable_tx(&chip->usb); - mutex_unlock(&chip->mutex); -} - -int zd_rfwritev_locked(struct zd_chip *chip, - const u32* values, unsigned int count, u8 bits) -{ - int r; - unsigned int i; - - for (i = 0; i < count; i++) { - r = zd_rfwrite_locked(chip, values[i], bits); - if (r) - return r; - } - - return 0; -} - -/* - * We can optionally program the RF directly through CR regs, if supported by - * the hardware. This is much faster than the older method. - */ -int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value) -{ - struct zd_ioreq16 ioreqs[] = { - { CR244, (value >> 16) & 0xff }, - { CR243, (value >> 8) & 0xff }, - { CR242, value & 0xff }, - }; - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -int zd_rfwritev_cr_locked(struct zd_chip *chip, - const u32 *values, unsigned int count) -{ - int r; - unsigned int i; - - for (i = 0; i < count; i++) { - r = zd_rfwrite_cr_locked(chip, values[i]); - if (r) - return r; - } - - return 0; -} - -int zd_chip_set_multicast_hash(struct zd_chip *chip, - struct zd_mc_hash *hash) -{ - struct zd_ioreq32 ioreqs[] = { - { CR_GROUP_HASH_P1, hash->low }, - { CR_GROUP_HASH_P2, hash->high }, - }; - - return zd_iowrite32a(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -u64 zd_chip_get_tsf(struct zd_chip *chip) -{ - int r; - static const zd_addr_t aw_pt_bi_addr[] = - { CR_TSF_LOW_PART, CR_TSF_HIGH_PART }; - u32 values[2]; - u64 tsf; - - mutex_lock(&chip->mutex); - r = zd_ioread32v_locked(chip, values, (const zd_addr_t *)aw_pt_bi_addr, - ARRAY_SIZE(aw_pt_bi_addr)); - mutex_unlock(&chip->mutex); - if (r) - return 0; - - tsf = values[1]; - tsf = (tsf << 32) | values[0]; - - return tsf; -} diff --git a/drivers/net/wireless/zd1211rw/zd_chip.h b/drivers/net/wireless/zd1211rw/zd_chip.h deleted file mode 100644 index 678c139a840c..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_chip.h +++ /dev/null @@ -1,955 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#ifndef _ZD_CHIP_H -#define _ZD_CHIP_H - -#include "zd_rf.h" -#include "zd_usb.h" - -/* Header for the Media Access Controller (MAC) and the Baseband Processor - * (BBP). It appears that the ZD1211 wraps the old ZD1205 with USB glue and - * adds a processor for handling the USB protocol. - */ - -/* Address space */ -enum { - /* CONTROL REGISTERS */ - CR_START = 0x9000, - - - /* FIRMWARE */ - FW_START = 0xee00, - - - /* EEPROM */ - E2P_START = 0xf800, - E2P_LEN = 0x800, - - /* EEPROM layout */ - E2P_LOAD_CODE_LEN = 0xe, /* base 0xf800 */ - E2P_LOAD_VECT_LEN = 0x9, /* base 0xf80e */ - /* E2P_DATA indexes into this */ - E2P_DATA_LEN = 0x7e, /* base 0xf817 */ - E2P_BOOT_CODE_LEN = 0x760, /* base 0xf895 */ - E2P_INTR_VECT_LEN = 0xb, /* base 0xfff5 */ - - /* Some precomputed offsets into the EEPROM */ - E2P_DATA_OFFSET = E2P_LOAD_CODE_LEN + E2P_LOAD_VECT_LEN, - E2P_BOOT_CODE_OFFSET = E2P_DATA_OFFSET + E2P_DATA_LEN, -}; - -#define CTL_REG(offset) ((zd_addr_t)(CR_START + (offset))) -#define E2P_DATA(offset) ((zd_addr_t)(E2P_START + E2P_DATA_OFFSET + (offset))) -#define FWRAW_DATA(offset) ((zd_addr_t)(FW_START + (offset))) - -/* 8-bit hardware registers */ -#define CR0 CTL_REG(0x0000) -#define CR1 CTL_REG(0x0004) -#define CR2 CTL_REG(0x0008) -#define CR3 CTL_REG(0x000C) - -#define CR5 CTL_REG(0x0010) -/* bit 5: if set short preamble used - * bit 6: filter band - Japan channel 14 on, else off - */ -#define CR6 CTL_REG(0x0014) -#define CR7 CTL_REG(0x0018) -#define CR8 CTL_REG(0x001C) - -#define CR4 CTL_REG(0x0020) - -#define CR9 CTL_REG(0x0024) -/* bit 2: antenna switch (together with CR10) */ -#define CR10 CTL_REG(0x0028) -/* bit 1: antenna switch (together with CR9) - * RF2959 controls with CR11 radion on and off - */ -#define CR11 CTL_REG(0x002C) -/* bit 6: TX power control for OFDM - * RF2959 controls with CR10 radio on and off - */ -#define CR12 CTL_REG(0x0030) -#define CR13 CTL_REG(0x0034) -#define CR14 CTL_REG(0x0038) -#define CR15 CTL_REG(0x003C) -#define CR16 CTL_REG(0x0040) -#define CR17 CTL_REG(0x0044) -#define CR18 CTL_REG(0x0048) -#define CR19 CTL_REG(0x004C) -#define CR20 CTL_REG(0x0050) -#define CR21 CTL_REG(0x0054) -#define CR22 CTL_REG(0x0058) -#define CR23 CTL_REG(0x005C) -#define CR24 CTL_REG(0x0060) /* CCA threshold */ -#define CR25 CTL_REG(0x0064) -#define CR26 CTL_REG(0x0068) -#define CR27 CTL_REG(0x006C) -#define CR28 CTL_REG(0x0070) -#define CR29 CTL_REG(0x0074) -#define CR30 CTL_REG(0x0078) -#define CR31 CTL_REG(0x007C) /* TX power control for RF in CCK mode */ -#define CR32 CTL_REG(0x0080) -#define CR33 CTL_REG(0x0084) -#define CR34 CTL_REG(0x0088) -#define CR35 CTL_REG(0x008C) -#define CR36 CTL_REG(0x0090) -#define CR37 CTL_REG(0x0094) -#define CR38 CTL_REG(0x0098) -#define CR39 CTL_REG(0x009C) -#define CR40 CTL_REG(0x00A0) -#define CR41 CTL_REG(0x00A4) -#define CR42 CTL_REG(0x00A8) -#define CR43 CTL_REG(0x00AC) -#define CR44 CTL_REG(0x00B0) -#define CR45 CTL_REG(0x00B4) -#define CR46 CTL_REG(0x00B8) -#define CR47 CTL_REG(0x00BC) /* CCK baseband gain - * (patch value might be in EEPROM) - */ -#define CR48 CTL_REG(0x00C0) -#define CR49 CTL_REG(0x00C4) -#define CR50 CTL_REG(0x00C8) -#define CR51 CTL_REG(0x00CC) /* TX power control for RF in 6-36M modes */ -#define CR52 CTL_REG(0x00D0) /* TX power control for RF in 48M mode */ -#define CR53 CTL_REG(0x00D4) /* TX power control for RF in 54M mode */ -#define CR54 CTL_REG(0x00D8) -#define CR55 CTL_REG(0x00DC) -#define CR56 CTL_REG(0x00E0) -#define CR57 CTL_REG(0x00E4) -#define CR58 CTL_REG(0x00E8) -#define CR59 CTL_REG(0x00EC) -#define CR60 CTL_REG(0x00F0) -#define CR61 CTL_REG(0x00F4) -#define CR62 CTL_REG(0x00F8) -#define CR63 CTL_REG(0x00FC) -#define CR64 CTL_REG(0x0100) -#define CR65 CTL_REG(0x0104) /* OFDM 54M calibration */ -#define CR66 CTL_REG(0x0108) /* OFDM 48M calibration */ -#define CR67 CTL_REG(0x010C) /* OFDM 36M calibration */ -#define CR68 CTL_REG(0x0110) /* CCK calibration */ -#define CR69 CTL_REG(0x0114) -#define CR70 CTL_REG(0x0118) -#define CR71 CTL_REG(0x011C) -#define CR72 CTL_REG(0x0120) -#define CR73 CTL_REG(0x0124) -#define CR74 CTL_REG(0x0128) -#define CR75 CTL_REG(0x012C) -#define CR76 CTL_REG(0x0130) -#define CR77 CTL_REG(0x0134) -#define CR78 CTL_REG(0x0138) -#define CR79 CTL_REG(0x013C) -#define CR80 CTL_REG(0x0140) -#define CR81 CTL_REG(0x0144) -#define CR82 CTL_REG(0x0148) -#define CR83 CTL_REG(0x014C) -#define CR84 CTL_REG(0x0150) -#define CR85 CTL_REG(0x0154) -#define CR86 CTL_REG(0x0158) -#define CR87 CTL_REG(0x015C) -#define CR88 CTL_REG(0x0160) -#define CR89 CTL_REG(0x0164) -#define CR90 CTL_REG(0x0168) -#define CR91 CTL_REG(0x016C) -#define CR92 CTL_REG(0x0170) -#define CR93 CTL_REG(0x0174) -#define CR94 CTL_REG(0x0178) -#define CR95 CTL_REG(0x017C) -#define CR96 CTL_REG(0x0180) -#define CR97 CTL_REG(0x0184) -#define CR98 CTL_REG(0x0188) -#define CR99 CTL_REG(0x018C) -#define CR100 CTL_REG(0x0190) -#define CR101 CTL_REG(0x0194) -#define CR102 CTL_REG(0x0198) -#define CR103 CTL_REG(0x019C) -#define CR104 CTL_REG(0x01A0) -#define CR105 CTL_REG(0x01A4) -#define CR106 CTL_REG(0x01A8) -#define CR107 CTL_REG(0x01AC) -#define CR108 CTL_REG(0x01B0) -#define CR109 CTL_REG(0x01B4) -#define CR110 CTL_REG(0x01B8) -#define CR111 CTL_REG(0x01BC) -#define CR112 CTL_REG(0x01C0) -#define CR113 CTL_REG(0x01C4) -#define CR114 CTL_REG(0x01C8) -#define CR115 CTL_REG(0x01CC) -#define CR116 CTL_REG(0x01D0) -#define CR117 CTL_REG(0x01D4) -#define CR118 CTL_REG(0x01D8) -#define CR119 CTL_REG(0x01DC) -#define CR120 CTL_REG(0x01E0) -#define CR121 CTL_REG(0x01E4) -#define CR122 CTL_REG(0x01E8) -#define CR123 CTL_REG(0x01EC) -#define CR124 CTL_REG(0x01F0) -#define CR125 CTL_REG(0x01F4) -#define CR126 CTL_REG(0x01F8) -#define CR127 CTL_REG(0x01FC) -#define CR128 CTL_REG(0x0200) -#define CR129 CTL_REG(0x0204) -#define CR130 CTL_REG(0x0208) -#define CR131 CTL_REG(0x020C) -#define CR132 CTL_REG(0x0210) -#define CR133 CTL_REG(0x0214) -#define CR134 CTL_REG(0x0218) -#define CR135 CTL_REG(0x021C) -#define CR136 CTL_REG(0x0220) -#define CR137 CTL_REG(0x0224) -#define CR138 CTL_REG(0x0228) -#define CR139 CTL_REG(0x022C) -#define CR140 CTL_REG(0x0230) -#define CR141 CTL_REG(0x0234) -#define CR142 CTL_REG(0x0238) -#define CR143 CTL_REG(0x023C) -#define CR144 CTL_REG(0x0240) -#define CR145 CTL_REG(0x0244) -#define CR146 CTL_REG(0x0248) -#define CR147 CTL_REG(0x024C) -#define CR148 CTL_REG(0x0250) -#define CR149 CTL_REG(0x0254) -#define CR150 CTL_REG(0x0258) -#define CR151 CTL_REG(0x025C) -#define CR152 CTL_REG(0x0260) -#define CR153 CTL_REG(0x0264) -#define CR154 CTL_REG(0x0268) -#define CR155 CTL_REG(0x026C) -#define CR156 CTL_REG(0x0270) -#define CR157 CTL_REG(0x0274) -#define CR158 CTL_REG(0x0278) -#define CR159 CTL_REG(0x027C) -#define CR160 CTL_REG(0x0280) -#define CR161 CTL_REG(0x0284) -#define CR162 CTL_REG(0x0288) -#define CR163 CTL_REG(0x028C) -#define CR164 CTL_REG(0x0290) -#define CR165 CTL_REG(0x0294) -#define CR166 CTL_REG(0x0298) -#define CR167 CTL_REG(0x029C) -#define CR168 CTL_REG(0x02A0) -#define CR169 CTL_REG(0x02A4) -#define CR170 CTL_REG(0x02A8) -#define CR171 CTL_REG(0x02AC) -#define CR172 CTL_REG(0x02B0) -#define CR173 CTL_REG(0x02B4) -#define CR174 CTL_REG(0x02B8) -#define CR175 CTL_REG(0x02BC) -#define CR176 CTL_REG(0x02C0) -#define CR177 CTL_REG(0x02C4) -#define CR178 CTL_REG(0x02C8) -#define CR179 CTL_REG(0x02CC) -#define CR180 CTL_REG(0x02D0) -#define CR181 CTL_REG(0x02D4) -#define CR182 CTL_REG(0x02D8) -#define CR183 CTL_REG(0x02DC) -#define CR184 CTL_REG(0x02E0) -#define CR185 CTL_REG(0x02E4) -#define CR186 CTL_REG(0x02E8) -#define CR187 CTL_REG(0x02EC) -#define CR188 CTL_REG(0x02F0) -#define CR189 CTL_REG(0x02F4) -#define CR190 CTL_REG(0x02F8) -#define CR191 CTL_REG(0x02FC) -#define CR192 CTL_REG(0x0300) -#define CR193 CTL_REG(0x0304) -#define CR194 CTL_REG(0x0308) -#define CR195 CTL_REG(0x030C) -#define CR196 CTL_REG(0x0310) -#define CR197 CTL_REG(0x0314) -#define CR198 CTL_REG(0x0318) -#define CR199 CTL_REG(0x031C) -#define CR200 CTL_REG(0x0320) -#define CR201 CTL_REG(0x0324) -#define CR202 CTL_REG(0x0328) -#define CR203 CTL_REG(0x032C) /* I2C bus template value & flash control */ -#define CR204 CTL_REG(0x0330) -#define CR205 CTL_REG(0x0334) -#define CR206 CTL_REG(0x0338) -#define CR207 CTL_REG(0x033C) -#define CR208 CTL_REG(0x0340) -#define CR209 CTL_REG(0x0344) -#define CR210 CTL_REG(0x0348) -#define CR211 CTL_REG(0x034C) -#define CR212 CTL_REG(0x0350) -#define CR213 CTL_REG(0x0354) -#define CR214 CTL_REG(0x0358) -#define CR215 CTL_REG(0x035C) -#define CR216 CTL_REG(0x0360) -#define CR217 CTL_REG(0x0364) -#define CR218 CTL_REG(0x0368) -#define CR219 CTL_REG(0x036C) -#define CR220 CTL_REG(0x0370) -#define CR221 CTL_REG(0x0374) -#define CR222 CTL_REG(0x0378) -#define CR223 CTL_REG(0x037C) -#define CR224 CTL_REG(0x0380) -#define CR225 CTL_REG(0x0384) -#define CR226 CTL_REG(0x0388) -#define CR227 CTL_REG(0x038C) -#define CR228 CTL_REG(0x0390) -#define CR229 CTL_REG(0x0394) -#define CR230 CTL_REG(0x0398) -#define CR231 CTL_REG(0x039C) -#define CR232 CTL_REG(0x03A0) -#define CR233 CTL_REG(0x03A4) -#define CR234 CTL_REG(0x03A8) -#define CR235 CTL_REG(0x03AC) -#define CR236 CTL_REG(0x03B0) - -#define CR240 CTL_REG(0x03C0) -/* bit 7: host-controlled RF register writes - * CR241-CR245: for hardware controlled writing of RF bits, not needed for - * USB - */ -#define CR241 CTL_REG(0x03C4) -#define CR242 CTL_REG(0x03C8) -#define CR243 CTL_REG(0x03CC) -#define CR244 CTL_REG(0x03D0) -#define CR245 CTL_REG(0x03D4) - -#define CR251 CTL_REG(0x03EC) /* only used for activation and deactivation of - * Airoha RFs AL2230 and AL7230B - */ -#define CR252 CTL_REG(0x03F0) -#define CR253 CTL_REG(0x03F4) -#define CR254 CTL_REG(0x03F8) -#define CR255 CTL_REG(0x03FC) - -#define CR_MAX_PHY_REG 255 - -/* Taken from the ZYDAS driver, not all of them are relevant for the ZD1211 - * driver. - */ - -#define CR_RF_IF_CLK CTL_REG(0x0400) -#define CR_RF_IF_DATA CTL_REG(0x0404) -#define CR_PE1_PE2 CTL_REG(0x0408) -#define CR_PE2_DLY CTL_REG(0x040C) -#define CR_LE1 CTL_REG(0x0410) -#define CR_LE2 CTL_REG(0x0414) -/* Seems to enable/disable GPI (General Purpose IO?) */ -#define CR_GPI_EN CTL_REG(0x0418) -#define CR_RADIO_PD CTL_REG(0x042C) -#define CR_RF2948_PD CTL_REG(0x042C) -#define CR_ENABLE_PS_MANUAL_AGC CTL_REG(0x043C) -#define CR_CONFIG_PHILIPS CTL_REG(0x0440) -#define CR_SA2400_SER_AP CTL_REG(0x0444) -#define CR_I2C_WRITE CTL_REG(0x0444) -#define CR_SA2400_SER_RP CTL_REG(0x0448) -#define CR_RADIO_PE CTL_REG(0x0458) -#define CR_RST_BUS_MASTER CTL_REG(0x045C) -#define CR_RFCFG CTL_REG(0x0464) -#define CR_HSTSCHG CTL_REG(0x046C) -#define CR_PHY_ON CTL_REG(0x0474) -#define CR_RX_DELAY CTL_REG(0x0478) -#define CR_RX_PE_DELAY CTL_REG(0x047C) -#define CR_GPIO_1 CTL_REG(0x0490) -#define CR_GPIO_2 CTL_REG(0x0494) -#define CR_EncryBufMux CTL_REG(0x04A8) -#define CR_PS_CTRL CTL_REG(0x0500) -#define CR_ADDA_PWR_DWN CTL_REG(0x0504) -#define CR_ADDA_MBIAS_WARMTIME CTL_REG(0x0508) -#define CR_MAC_PS_STATE CTL_REG(0x050C) - -#define CR_INTERRUPT CTL_REG(0x0510) -#define INT_TX_COMPLETE (1 << 0) -#define INT_RX_COMPLETE (1 << 1) -#define INT_RETRY_FAIL (1 << 2) -#define INT_WAKEUP (1 << 3) -#define INT_DTIM_NOTIFY (1 << 5) -#define INT_CFG_NEXT_BCN (1 << 6) -#define INT_BUS_ABORT (1 << 7) -#define INT_TX_FIFO_READY (1 << 8) -#define INT_UART (1 << 9) -#define INT_TX_COMPLETE_EN (1 << 16) -#define INT_RX_COMPLETE_EN (1 << 17) -#define INT_RETRY_FAIL_EN (1 << 18) -#define INT_WAKEUP_EN (1 << 19) -#define INT_DTIM_NOTIFY_EN (1 << 21) -#define INT_CFG_NEXT_BCN_EN (1 << 22) -#define INT_BUS_ABORT_EN (1 << 23) -#define INT_TX_FIFO_READY_EN (1 << 24) -#define INT_UART_EN (1 << 25) - -#define CR_TSF_LOW_PART CTL_REG(0x0514) -#define CR_TSF_HIGH_PART CTL_REG(0x0518) - -/* Following three values are in time units (1024us) - * Following condition must be met: - * atim < tbtt < bcn - */ -#define CR_ATIM_WND_PERIOD CTL_REG(0x051C) -#define CR_BCN_INTERVAL CTL_REG(0x0520) -#define CR_PRE_TBTT CTL_REG(0x0524) -/* in units of TU(1024us) */ - -/* for UART support */ -#define CR_UART_RBR_THR_DLL CTL_REG(0x0540) -#define CR_UART_DLM_IER CTL_REG(0x0544) -#define CR_UART_IIR_FCR CTL_REG(0x0548) -#define CR_UART_LCR CTL_REG(0x054c) -#define CR_UART_MCR CTL_REG(0x0550) -#define CR_UART_LSR CTL_REG(0x0554) -#define CR_UART_MSR CTL_REG(0x0558) -#define CR_UART_ECR CTL_REG(0x055c) -#define CR_UART_STATUS CTL_REG(0x0560) - -#define CR_PCI_TX_ADDR_P1 CTL_REG(0x0600) -#define CR_PCI_TX_AddR_P2 CTL_REG(0x0604) -#define CR_PCI_RX_AddR_P1 CTL_REG(0x0608) -#define CR_PCI_RX_AddR_P2 CTL_REG(0x060C) - -/* must be overwritten if custom MAC address will be used */ -#define CR_MAC_ADDR_P1 CTL_REG(0x0610) -#define CR_MAC_ADDR_P2 CTL_REG(0x0614) -#define CR_BSSID_P1 CTL_REG(0x0618) -#define CR_BSSID_P2 CTL_REG(0x061C) -#define CR_BCN_PLCP_CFG CTL_REG(0x0620) - -/* Group hash table for filtering incoming packets. - * - * The group hash table is 64 bit large and split over two parts. The first - * part is the lower part. The upper 6 bits of the last byte of the target - * address are used as index. Packets are received if the hash table bit is - * set. This is used for multicast handling, but for broadcasts (address - * ff:ff:ff:ff:ff:ff) the highest bit in the second table must also be set. - */ -#define CR_GROUP_HASH_P1 CTL_REG(0x0624) -#define CR_GROUP_HASH_P2 CTL_REG(0x0628) - -#define CR_RX_TIMEOUT CTL_REG(0x062C) - -/* Basic rates supported by the BSS. When producing ACK or CTS messages, the - * device will use a rate in this table that is less than or equal to the rate - * of the incoming frame which prompted the response. */ -#define CR_BASIC_RATE_TBL CTL_REG(0x0630) -#define CR_RATE_1M (1 << 0) /* 802.11b */ -#define CR_RATE_2M (1 << 1) /* 802.11b */ -#define CR_RATE_5_5M (1 << 2) /* 802.11b */ -#define CR_RATE_11M (1 << 3) /* 802.11b */ -#define CR_RATE_6M (1 << 8) /* 802.11g */ -#define CR_RATE_9M (1 << 9) /* 802.11g */ -#define CR_RATE_12M (1 << 10) /* 802.11g */ -#define CR_RATE_18M (1 << 11) /* 802.11g */ -#define CR_RATE_24M (1 << 12) /* 802.11g */ -#define CR_RATE_36M (1 << 13) /* 802.11g */ -#define CR_RATE_48M (1 << 14) /* 802.11g */ -#define CR_RATE_54M (1 << 15) /* 802.11g */ -#define CR_RATES_80211G 0xff00 -#define CR_RATES_80211B 0x000f - -/* Mandatory rates required in the BSS. When producing ACK or CTS messages, if - * the device could not find an appropriate rate in CR_BASIC_RATE_TBL, it will - * look for a rate in this table that is less than or equal to the rate of - * the incoming frame. */ -#define CR_MANDATORY_RATE_TBL CTL_REG(0x0634) -#define CR_RTS_CTS_RATE CTL_REG(0x0638) - -/* These are all bit indexes in CR_RTS_CTS_RATE, so remember to shift. */ -#define RTSCTS_SH_RTS_RATE 0 -#define RTSCTS_SH_EXP_CTS_RATE 4 -#define RTSCTS_SH_RTS_MOD_TYPE 8 -#define RTSCTS_SH_RTS_PMB_TYPE 9 -#define RTSCTS_SH_CTS_RATE 16 -#define RTSCTS_SH_CTS_MOD_TYPE 24 -#define RTSCTS_SH_CTS_PMB_TYPE 25 - -#define CR_WEP_PROTECT CTL_REG(0x063C) -#define CR_RX_THRESHOLD CTL_REG(0x0640) - -/* register for controlling the LEDS */ -#define CR_LED CTL_REG(0x0644) -/* masks for controlling LEDs */ -#define LED1 (1 << 8) -#define LED2 (1 << 9) -#define LED_SW (1 << 10) - -/* Seems to indicate that the configuration is over. - */ -#define CR_AFTER_PNP CTL_REG(0x0648) -#define CR_ACK_TIME_80211 CTL_REG(0x0658) - -#define CR_RX_OFFSET CTL_REG(0x065c) - -#define CR_BCN_LENGTH CTL_REG(0x0664) -#define CR_PHY_DELAY CTL_REG(0x066C) -#define CR_BCN_FIFO CTL_REG(0x0670) -#define CR_SNIFFER_ON CTL_REG(0x0674) - -#define CR_ENCRYPTION_TYPE CTL_REG(0x0678) -#define NO_WEP 0 -#define WEP64 1 -#define WEP128 5 -#define WEP256 6 -#define ENC_SNIFFER 8 - -#define CR_ZD1211_RETRY_MAX CTL_REG(0x067C) - -#define CR_REG1 CTL_REG(0x0680) -/* Setting the bit UNLOCK_PHY_REGS disallows the write access to physical - * registers, so one could argue it is a LOCK bit. But calling it - * LOCK_PHY_REGS makes it confusing. - */ -#define UNLOCK_PHY_REGS (1 << 7) - -#define CR_DEVICE_STATE CTL_REG(0x0684) -#define CR_UNDERRUN_CNT CTL_REG(0x0688) - -#define CR_RX_FILTER CTL_REG(0x068c) -#define RX_FILTER_ASSOC_REQUEST (1 << 0) -#define RX_FILTER_ASSOC_RESPONSE (1 << 1) -#define RX_FILTER_REASSOC_REQUEST (1 << 2) -#define RX_FILTER_REASSOC_RESPONSE (1 << 3) -#define RX_FILTER_PROBE_REQUEST (1 << 4) -#define RX_FILTER_PROBE_RESPONSE (1 << 5) -/* bits 6 and 7 reserved */ -#define RX_FILTER_BEACON (1 << 8) -#define RX_FILTER_ATIM (1 << 9) -#define RX_FILTER_DISASSOC (1 << 10) -#define RX_FILTER_AUTH (1 << 11) -#define RX_FILTER_DEAUTH (1 << 12) -#define RX_FILTER_PSPOLL (1 << 26) -#define RX_FILTER_RTS (1 << 27) -#define RX_FILTER_CTS (1 << 28) -#define RX_FILTER_ACK (1 << 29) -#define RX_FILTER_CFEND (1 << 30) -#define RX_FILTER_CFACK (1 << 31) - -/* Enable bits for all frames you are interested in. */ -#define STA_RX_FILTER (RX_FILTER_ASSOC_REQUEST | RX_FILTER_ASSOC_RESPONSE | \ - RX_FILTER_REASSOC_REQUEST | RX_FILTER_REASSOC_RESPONSE | \ - RX_FILTER_PROBE_REQUEST | RX_FILTER_PROBE_RESPONSE | \ - (0x3 << 6) /* vendor driver sets these reserved bits */ | \ - RX_FILTER_BEACON | RX_FILTER_ATIM | RX_FILTER_DISASSOC | \ - RX_FILTER_AUTH | RX_FILTER_DEAUTH | \ - (0x7 << 13) /* vendor driver sets these reserved bits */ | \ - RX_FILTER_PSPOLL | RX_FILTER_ACK) /* 0x2400ffff */ - -#define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \ - RX_FILTER_CFEND | RX_FILTER_CFACK) - -#define BCN_MODE_IBSS 0x2000000 - -/* Monitor mode sets filter to 0xfffff */ - -#define CR_ACK_TIMEOUT_EXT CTL_REG(0x0690) -#define CR_BCN_FIFO_SEMAPHORE CTL_REG(0x0694) - -#define CR_IFS_VALUE CTL_REG(0x0698) -#define IFS_VALUE_DIFS_SH 0 -#define IFS_VALUE_EIFS_SH 12 -#define IFS_VALUE_SIFS_SH 24 -#define IFS_VALUE_DEFAULT (( 50 << IFS_VALUE_DIFS_SH) | \ - (1148 << IFS_VALUE_EIFS_SH) | \ - ( 10 << IFS_VALUE_SIFS_SH)) - -#define CR_RX_TIME_OUT CTL_REG(0x069C) -#define CR_TOTAL_RX_FRM CTL_REG(0x06A0) -#define CR_CRC32_CNT CTL_REG(0x06A4) -#define CR_CRC16_CNT CTL_REG(0x06A8) -#define CR_DECRYPTION_ERR_UNI CTL_REG(0x06AC) -#define CR_RX_FIFO_OVERRUN CTL_REG(0x06B0) - -#define CR_DECRYPTION_ERR_MUL CTL_REG(0x06BC) - -#define CR_NAV_CNT CTL_REG(0x06C4) -#define CR_NAV_CCA CTL_REG(0x06C8) -#define CR_RETRY_CNT CTL_REG(0x06CC) - -#define CR_READ_TCB_ADDR CTL_REG(0x06E8) -#define CR_READ_RFD_ADDR CTL_REG(0x06EC) -#define CR_CWMIN_CWMAX CTL_REG(0x06F0) -#define CR_TOTAL_TX_FRM CTL_REG(0x06F4) - -/* CAM: Continuous Access Mode (power management) */ -#define CR_CAM_MODE CTL_REG(0x0700) -#define MODE_IBSS 0x0 -#define MODE_AP 0x1 -#define MODE_STA 0x2 -#define MODE_AP_WDS 0x3 - -#define CR_CAM_ROLL_TB_LOW CTL_REG(0x0704) -#define CR_CAM_ROLL_TB_HIGH CTL_REG(0x0708) -#define CR_CAM_ADDRESS CTL_REG(0x070C) -#define CR_CAM_DATA CTL_REG(0x0710) - -#define CR_ROMDIR CTL_REG(0x0714) - -#define CR_DECRY_ERR_FLG_LOW CTL_REG(0x0714) -#define CR_DECRY_ERR_FLG_HIGH CTL_REG(0x0718) - -#define CR_WEPKEY0 CTL_REG(0x0720) -#define CR_WEPKEY1 CTL_REG(0x0724) -#define CR_WEPKEY2 CTL_REG(0x0728) -#define CR_WEPKEY3 CTL_REG(0x072C) -#define CR_WEPKEY4 CTL_REG(0x0730) -#define CR_WEPKEY5 CTL_REG(0x0734) -#define CR_WEPKEY6 CTL_REG(0x0738) -#define CR_WEPKEY7 CTL_REG(0x073C) -#define CR_WEPKEY8 CTL_REG(0x0740) -#define CR_WEPKEY9 CTL_REG(0x0744) -#define CR_WEPKEY10 CTL_REG(0x0748) -#define CR_WEPKEY11 CTL_REG(0x074C) -#define CR_WEPKEY12 CTL_REG(0x0750) -#define CR_WEPKEY13 CTL_REG(0x0754) -#define CR_WEPKEY14 CTL_REG(0x0758) -#define CR_WEPKEY15 CTL_REG(0x075c) -#define CR_TKIP_MODE CTL_REG(0x0760) - -#define CR_EEPROM_PROTECT0 CTL_REG(0x0758) -#define CR_EEPROM_PROTECT1 CTL_REG(0x075C) - -#define CR_DBG_FIFO_RD CTL_REG(0x0800) -#define CR_DBG_SELECT CTL_REG(0x0804) -#define CR_FIFO_Length CTL_REG(0x0808) - - -#define CR_RSSI_MGC CTL_REG(0x0810) - -#define CR_PON CTL_REG(0x0818) -#define CR_RX_ON CTL_REG(0x081C) -#define CR_TX_ON CTL_REG(0x0820) -#define CR_CHIP_EN CTL_REG(0x0824) -#define CR_LO_SW CTL_REG(0x0828) -#define CR_TXRX_SW CTL_REG(0x082C) -#define CR_S_MD CTL_REG(0x0830) - -#define CR_USB_DEBUG_PORT CTL_REG(0x0888) -#define CR_ZD1211B_CWIN_MAX_MIN_AC0 CTL_REG(0x0b00) -#define CR_ZD1211B_CWIN_MAX_MIN_AC1 CTL_REG(0x0b04) -#define CR_ZD1211B_CWIN_MAX_MIN_AC2 CTL_REG(0x0b08) -#define CR_ZD1211B_CWIN_MAX_MIN_AC3 CTL_REG(0x0b0c) -#define CR_ZD1211B_AIFS_CTL1 CTL_REG(0x0b10) -#define CR_ZD1211B_AIFS_CTL2 CTL_REG(0x0b14) -#define CR_ZD1211B_TXOP CTL_REG(0x0b20) -#define CR_ZD1211B_RETRY_MAX CTL_REG(0x0b28) - -/* Used to detect PLL lock */ -#define UW2453_INTR_REG ((zd_addr_t)0x85c1) - -#define CWIN_SIZE 0x007f043f - - -#define HWINT_ENABLED 0x004f0000 -#define HWINT_DISABLED 0 - -#define E2P_PWR_INT_GUARD 8 -#define E2P_CHANNEL_COUNT 14 - -/* If you compare this addresses with the ZYDAS orignal driver, please notify - * that we use word mapping for the EEPROM. - */ - -/* - * Upper 16 bit contains the regulatory domain. - */ -#define E2P_SUBID E2P_DATA(0x00) -#define E2P_POD E2P_DATA(0x02) -#define E2P_MAC_ADDR_P1 E2P_DATA(0x04) -#define E2P_MAC_ADDR_P2 E2P_DATA(0x06) -#define E2P_PWR_CAL_VALUE1 E2P_DATA(0x08) -#define E2P_PWR_CAL_VALUE2 E2P_DATA(0x0a) -#define E2P_PWR_CAL_VALUE3 E2P_DATA(0x0c) -#define E2P_PWR_CAL_VALUE4 E2P_DATA(0x0e) -#define E2P_PWR_INT_VALUE1 E2P_DATA(0x10) -#define E2P_PWR_INT_VALUE2 E2P_DATA(0x12) -#define E2P_PWR_INT_VALUE3 E2P_DATA(0x14) -#define E2P_PWR_INT_VALUE4 E2P_DATA(0x16) - -/* Contains a bit for each allowed channel. It gives for Europe (ETSI 0x30) - * also only 11 channels. */ -#define E2P_ALLOWED_CHANNEL E2P_DATA(0x18) - -#define E2P_DEVICE_VER E2P_DATA(0x20) -#define E2P_PHY_REG E2P_DATA(0x25) -#define E2P_36M_CAL_VALUE1 E2P_DATA(0x28) -#define E2P_36M_CAL_VALUE2 E2P_DATA(0x2a) -#define E2P_36M_CAL_VALUE3 E2P_DATA(0x2c) -#define E2P_36M_CAL_VALUE4 E2P_DATA(0x2e) -#define E2P_11A_INT_VALUE1 E2P_DATA(0x30) -#define E2P_11A_INT_VALUE2 E2P_DATA(0x32) -#define E2P_11A_INT_VALUE3 E2P_DATA(0x34) -#define E2P_11A_INT_VALUE4 E2P_DATA(0x36) -#define E2P_48M_CAL_VALUE1 E2P_DATA(0x38) -#define E2P_48M_CAL_VALUE2 E2P_DATA(0x3a) -#define E2P_48M_CAL_VALUE3 E2P_DATA(0x3c) -#define E2P_48M_CAL_VALUE4 E2P_DATA(0x3e) -#define E2P_48M_INT_VALUE1 E2P_DATA(0x40) -#define E2P_48M_INT_VALUE2 E2P_DATA(0x42) -#define E2P_48M_INT_VALUE3 E2P_DATA(0x44) -#define E2P_48M_INT_VALUE4 E2P_DATA(0x46) -#define E2P_54M_CAL_VALUE1 E2P_DATA(0x48) /* ??? */ -#define E2P_54M_CAL_VALUE2 E2P_DATA(0x4a) -#define E2P_54M_CAL_VALUE3 E2P_DATA(0x4c) -#define E2P_54M_CAL_VALUE4 E2P_DATA(0x4e) -#define E2P_54M_INT_VALUE1 E2P_DATA(0x50) -#define E2P_54M_INT_VALUE2 E2P_DATA(0x52) -#define E2P_54M_INT_VALUE3 E2P_DATA(0x54) -#define E2P_54M_INT_VALUE4 E2P_DATA(0x56) - -/* This word contains the base address of the FW_REG_ registers below */ -#define FWRAW_REGS_ADDR FWRAW_DATA(0x1d) - -/* All 16 bit values, offset from the address in FWRAW_REGS_ADDR */ -enum { - FW_REG_FIRMWARE_VER = 0, - /* non-zero if USB high speed connection */ - FW_REG_USB_SPEED = 1, - FW_REG_FIX_TX_RATE = 2, - /* Seems to be able to control LEDs over the firmware */ - FW_REG_LED_LINK_STATUS = 3, - FW_REG_SOFT_RESET = 4, - FW_REG_FLASH_CHK = 5, -}; - -/* Values for FW_LINK_STATUS */ -#define FW_LINK_OFF 0x0 -#define FW_LINK_TX 0x1 -/* 0x2 - link led on? */ - -enum { - /* indices for ofdm_cal_values */ - OFDM_36M_INDEX = 0, - OFDM_48M_INDEX = 1, - OFDM_54M_INDEX = 2, -}; - -struct zd_chip { - struct zd_usb usb; - struct zd_rf rf; - struct mutex mutex; - /* Base address of FW_REG_ registers */ - zd_addr_t fw_regs_base; - /* EepSetPoint in the vendor driver */ - u8 pwr_cal_values[E2P_CHANNEL_COUNT]; - /* integration values in the vendor driver */ - u8 pwr_int_values[E2P_CHANNEL_COUNT]; - /* SetPointOFDM in the vendor driver */ - u8 ofdm_cal_values[3][E2P_CHANNEL_COUNT]; - u16 link_led; - unsigned int pa_type:4, - patch_cck_gain:1, patch_cr157:1, patch_6m_band_edge:1, - new_phy_layout:1, al2230s_bit:1, - supports_tx_led:1; -}; - -static inline struct zd_chip *zd_usb_to_chip(struct zd_usb *usb) -{ - return container_of(usb, struct zd_chip, usb); -} - -static inline struct zd_chip *zd_rf_to_chip(struct zd_rf *rf) -{ - return container_of(rf, struct zd_chip, rf); -} - -#define zd_chip_dev(chip) (&(chip)->usb.intf->dev) - -void zd_chip_init(struct zd_chip *chip, - struct ieee80211_hw *hw, - struct usb_interface *intf); -void zd_chip_clear(struct zd_chip *chip); -int zd_chip_read_mac_addr_fw(struct zd_chip *chip, u8 *addr); -int zd_chip_init_hw(struct zd_chip *chip); -int zd_chip_reset(struct zd_chip *chip); - -static inline int zd_chip_is_zd1211b(struct zd_chip *chip) -{ - return chip->usb.is_zd1211b; -} - -static inline int zd_ioread16v_locked(struct zd_chip *chip, u16 *values, - const zd_addr_t *addresses, - unsigned int count) -{ - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_usb_ioread16v(&chip->usb, values, addresses, count); -} - -static inline int zd_ioread16_locked(struct zd_chip *chip, u16 *value, - const zd_addr_t addr) -{ - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_usb_ioread16(&chip->usb, value, addr); -} - -int zd_ioread32v_locked(struct zd_chip *chip, u32 *values, - const zd_addr_t *addresses, unsigned int count); - -static inline int zd_ioread32_locked(struct zd_chip *chip, u32 *value, - const zd_addr_t addr) -{ - return zd_ioread32v_locked(chip, value, (const zd_addr_t *)&addr, 1); -} - -static inline int zd_iowrite16_locked(struct zd_chip *chip, u16 value, - zd_addr_t addr) -{ - struct zd_ioreq16 ioreq; - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - ioreq.addr = addr; - ioreq.value = value; - - return zd_usb_iowrite16v(&chip->usb, &ioreq, 1); -} - -int zd_iowrite16a_locked(struct zd_chip *chip, - const struct zd_ioreq16 *ioreqs, unsigned int count); - -int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, - unsigned int count); - -static inline int zd_iowrite32_locked(struct zd_chip *chip, u32 value, - zd_addr_t addr) -{ - struct zd_ioreq32 ioreq; - - ioreq.addr = addr; - ioreq.value = value; - - return _zd_iowrite32v_locked(chip, &ioreq, 1); -} - -int zd_iowrite32a_locked(struct zd_chip *chip, - const struct zd_ioreq32 *ioreqs, unsigned int count); - -static inline int zd_rfwrite_locked(struct zd_chip *chip, u32 value, u8 bits) -{ - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - return zd_usb_rfwrite(&chip->usb, value, bits); -} - -int zd_rfwrite_cr_locked(struct zd_chip *chip, u32 value); - -int zd_rfwritev_locked(struct zd_chip *chip, - const u32* values, unsigned int count, u8 bits); -int zd_rfwritev_cr_locked(struct zd_chip *chip, - const u32* values, unsigned int count); - -/* Locking functions for reading and writing registers. - * The different parameters are intentional. - */ -int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value); -int zd_iowrite16(struct zd_chip *chip, zd_addr_t addr, u16 value); -int zd_ioread32(struct zd_chip *chip, zd_addr_t addr, u32 *value); -int zd_iowrite32(struct zd_chip *chip, zd_addr_t addr, u32 value); -int zd_ioread32v(struct zd_chip *chip, const zd_addr_t *addresses, - u32 *values, unsigned int count); -int zd_iowrite32a(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs, - unsigned int count); - -int zd_chip_set_channel(struct zd_chip *chip, u8 channel); -static inline u8 _zd_chip_get_channel(struct zd_chip *chip) -{ - return chip->rf.channel; -} -u8 zd_chip_get_channel(struct zd_chip *chip); -int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain); -int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr); -int zd_chip_switch_radio_on(struct zd_chip *chip); -int zd_chip_switch_radio_off(struct zd_chip *chip); -int zd_chip_enable_int(struct zd_chip *chip); -void zd_chip_disable_int(struct zd_chip *chip); -int zd_chip_enable_rxtx(struct zd_chip *chip); -void zd_chip_disable_rxtx(struct zd_chip *chip); -int zd_chip_enable_hwint(struct zd_chip *chip); -int zd_chip_disable_hwint(struct zd_chip *chip); -int zd_chip_generic_patch_6m_band(struct zd_chip *chip, int channel); -int zd_chip_set_rts_cts_rate_locked(struct zd_chip *chip, int preamble); - -static inline int zd_get_encryption_type(struct zd_chip *chip, u32 *type) -{ - return zd_ioread32(chip, CR_ENCRYPTION_TYPE, type); -} - -static inline int zd_set_encryption_type(struct zd_chip *chip, u32 type) -{ - return zd_iowrite32(chip, CR_ENCRYPTION_TYPE, type); -} - -static inline int zd_chip_get_basic_rates(struct zd_chip *chip, u16 *cr_rates) -{ - return zd_ioread16(chip, CR_BASIC_RATE_TBL, cr_rates); -} - -int zd_chip_set_basic_rates(struct zd_chip *chip, u16 cr_rates); - -int zd_chip_lock_phy_regs(struct zd_chip *chip); -int zd_chip_unlock_phy_regs(struct zd_chip *chip); - -enum led_status { - ZD_LED_OFF = 0, - ZD_LED_SCANNING = 1, - ZD_LED_ASSOCIATED = 2, -}; - -int zd_chip_control_leds(struct zd_chip *chip, enum led_status status); - -int zd_set_beacon_interval(struct zd_chip *chip, u32 interval); - -static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval) -{ - return zd_ioread32(chip, CR_BCN_INTERVAL, interval); -} - -struct rx_status; - -u8 zd_rx_qual_percent(const void *rx_frame, unsigned int size, - const struct rx_status *status); - -u8 zd_rx_rate(const void *rx_frame, const struct rx_status *status); - -struct zd_mc_hash { - u32 low; - u32 high; -}; - -static inline void zd_mc_clear(struct zd_mc_hash *hash) -{ - hash->low = 0; - /* The interfaces must always received broadcasts. - * The hash of the broadcast address ff:ff:ff:ff:ff:ff is 63. - */ - hash->high = 0x80000000; -} - -static inline void zd_mc_add_all(struct zd_mc_hash *hash) -{ - hash->low = hash->high = 0xffffffff; -} - -static inline void zd_mc_add_addr(struct zd_mc_hash *hash, u8 *addr) -{ - unsigned int i = addr[5] >> 2; - if (i < 32) { - hash->low |= 1 << i; - } else { - hash->high |= 1 << (i-32); - } -} - -int zd_chip_set_multicast_hash(struct zd_chip *chip, - struct zd_mc_hash *hash); - -u64 zd_chip_get_tsf(struct zd_chip *chip); - -#endif /* _ZD_CHIP_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_def.h b/drivers/net/wireless/zd1211rw/zd_def.h deleted file mode 100644 index 6ac597ffd3b9..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_def.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#ifndef _ZD_DEF_H -#define _ZD_DEF_H - -#include -#include -#include - -typedef u16 __nocast zd_addr_t; - -#define dev_printk_f(level, dev, fmt, args...) \ - dev_printk(level, dev, "%s() " fmt, __func__, ##args) - -#ifdef DEBUG -# define dev_dbg_f(dev, fmt, args...) \ - dev_printk_f(KERN_DEBUG, dev, fmt, ## args) -# define dev_dbg_f_limit(dev, fmt, args...) do { \ - if (net_ratelimit()) \ - dev_printk_f(KERN_DEBUG, dev, fmt, ## args); \ -} while (0) -#else -# define dev_dbg_f(dev, fmt, args...) do { (void)(dev); } while (0) -# define dev_dbg_f_limit(dev, fmt, args...) do { (void)(dev); } while (0) -#endif /* DEBUG */ - -#ifdef DEBUG -# define ZD_ASSERT(x) \ -do { \ - if (!(x)) { \ - pr_debug("%s:%d ASSERT %s VIOLATED!\n", \ - __FILE__, __LINE__, __stringify(x)); \ - dump_stack(); \ - } \ -} while (0) -#else -# define ZD_ASSERT(x) do { } while (0) -#endif - -#ifdef DEBUG -# define ZD_MEMCLEAR(pointer, size) memset((pointer), 0xff, (size)) -#else -# define ZD_MEMCLEAR(pointer, size) do { } while (0) -#endif - -#endif /* _ZD_DEF_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_mac.c b/drivers/net/wireless/zd1211rw/zd_mac.c deleted file mode 100644 index 6d666359a42f..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_mac.c +++ /dev/null @@ -1,1056 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * Copyright (C) 2006-2007 Michael Wu - * Copyright (C) 2007-2008 Luis R. Rodriguez - * - * 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 - */ - -#include -#include -#include -#include -#include - -#include "zd_def.h" -#include "zd_chip.h" -#include "zd_mac.h" -#include "zd_rf.h" - -struct zd_reg_alpha2_map { - u32 reg; - char alpha2[2]; -}; - -static struct zd_reg_alpha2_map reg_alpha2_map[] = { - { ZD_REGDOMAIN_FCC, "US" }, - { ZD_REGDOMAIN_IC, "CA" }, - { ZD_REGDOMAIN_ETSI, "DE" }, /* Generic ETSI, use most restrictive */ - { ZD_REGDOMAIN_JAPAN, "JP" }, - { ZD_REGDOMAIN_JAPAN_ADD, "JP" }, - { ZD_REGDOMAIN_SPAIN, "ES" }, - { ZD_REGDOMAIN_FRANCE, "FR" }, -}; - -/* This table contains the hardware specific values for the modulation rates. */ -static const struct ieee80211_rate zd_rates[] = { - { .bitrate = 10, - .hw_value = ZD_CCK_RATE_1M, }, - { .bitrate = 20, - .hw_value = ZD_CCK_RATE_2M, - .hw_value_short = ZD_CCK_RATE_2M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 55, - .hw_value = ZD_CCK_RATE_5_5M, - .hw_value_short = ZD_CCK_RATE_5_5M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 110, - .hw_value = ZD_CCK_RATE_11M, - .hw_value_short = ZD_CCK_RATE_11M | ZD_CCK_PREA_SHORT, - .flags = IEEE80211_RATE_SHORT_PREAMBLE }, - { .bitrate = 60, - .hw_value = ZD_OFDM_RATE_6M, - .flags = 0 }, - { .bitrate = 90, - .hw_value = ZD_OFDM_RATE_9M, - .flags = 0 }, - { .bitrate = 120, - .hw_value = ZD_OFDM_RATE_12M, - .flags = 0 }, - { .bitrate = 180, - .hw_value = ZD_OFDM_RATE_18M, - .flags = 0 }, - { .bitrate = 240, - .hw_value = ZD_OFDM_RATE_24M, - .flags = 0 }, - { .bitrate = 360, - .hw_value = ZD_OFDM_RATE_36M, - .flags = 0 }, - { .bitrate = 480, - .hw_value = ZD_OFDM_RATE_48M, - .flags = 0 }, - { .bitrate = 540, - .hw_value = ZD_OFDM_RATE_54M, - .flags = 0 }, -}; - -static const struct ieee80211_channel zd_channels[] = { - { .center_freq = 2412, .hw_value = 1 }, - { .center_freq = 2417, .hw_value = 2 }, - { .center_freq = 2422, .hw_value = 3 }, - { .center_freq = 2427, .hw_value = 4 }, - { .center_freq = 2432, .hw_value = 5 }, - { .center_freq = 2437, .hw_value = 6 }, - { .center_freq = 2442, .hw_value = 7 }, - { .center_freq = 2447, .hw_value = 8 }, - { .center_freq = 2452, .hw_value = 9 }, - { .center_freq = 2457, .hw_value = 10 }, - { .center_freq = 2462, .hw_value = 11 }, - { .center_freq = 2467, .hw_value = 12 }, - { .center_freq = 2472, .hw_value = 13 }, - { .center_freq = 2484, .hw_value = 14 }, -}; - -static void housekeeping_init(struct zd_mac *mac); -static void housekeeping_enable(struct zd_mac *mac); -static void housekeeping_disable(struct zd_mac *mac); - -static int zd_reg2alpha2(u8 regdomain, char *alpha2) -{ - unsigned int i; - struct zd_reg_alpha2_map *reg_map; - for (i = 0; i < ARRAY_SIZE(reg_alpha2_map); i++) { - reg_map = ®_alpha2_map[i]; - if (regdomain == reg_map->reg) { - alpha2[0] = reg_map->alpha2[0]; - alpha2[1] = reg_map->alpha2[1]; - return 0; - } - } - return 1; -} - -int zd_mac_preinit_hw(struct ieee80211_hw *hw) -{ - int r; - u8 addr[ETH_ALEN]; - struct zd_mac *mac = zd_hw_mac(hw); - - r = zd_chip_read_mac_addr_fw(&mac->chip, addr); - if (r) - return r; - - SET_IEEE80211_PERM_ADDR(hw, addr); - - return 0; -} - -int zd_mac_init_hw(struct ieee80211_hw *hw) -{ - int r; - struct zd_mac *mac = zd_hw_mac(hw); - struct zd_chip *chip = &mac->chip; - char alpha2[2]; - u8 default_regdomain; - - r = zd_chip_enable_int(chip); - if (r) - goto out; - r = zd_chip_init_hw(chip); - if (r) - goto disable_int; - - ZD_ASSERT(!irqs_disabled()); - - r = zd_read_regdomain(chip, &default_regdomain); - if (r) - goto disable_int; - spin_lock_irq(&mac->lock); - mac->regdomain = mac->default_regdomain = default_regdomain; - spin_unlock_irq(&mac->lock); - - /* We must inform the device that we are doing encryption/decryption in - * software at the moment. */ - r = zd_set_encryption_type(chip, ENC_SNIFFER); - if (r) - goto disable_int; - - r = zd_reg2alpha2(mac->regdomain, alpha2); - if (r) - goto disable_int; - - r = regulatory_hint(hw->wiphy, alpha2); -disable_int: - zd_chip_disable_int(chip); -out: - return r; -} - -void zd_mac_clear(struct zd_mac *mac) -{ - flush_workqueue(zd_workqueue); - zd_chip_clear(&mac->chip); - ZD_ASSERT(!spin_is_locked(&mac->lock)); - ZD_MEMCLEAR(mac, sizeof(struct zd_mac)); -} - -static int set_rx_filter(struct zd_mac *mac) -{ - unsigned long flags; - u32 filter = STA_RX_FILTER; - - spin_lock_irqsave(&mac->lock, flags); - if (mac->pass_ctrl) - filter |= RX_FILTER_CTRL; - spin_unlock_irqrestore(&mac->lock, flags); - - return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter); -} - -static int set_mc_hash(struct zd_mac *mac) -{ - struct zd_mc_hash hash; - zd_mc_clear(&hash); - return zd_chip_set_multicast_hash(&mac->chip, &hash); -} - -static int zd_op_start(struct ieee80211_hw *hw) -{ - struct zd_mac *mac = zd_hw_mac(hw); - struct zd_chip *chip = &mac->chip; - struct zd_usb *usb = &chip->usb; - int r; - - if (!usb->initialized) { - r = zd_usb_init_hw(usb); - if (r) - goto out; - } - - r = zd_chip_enable_int(chip); - if (r < 0) - goto out; - - r = zd_chip_set_basic_rates(chip, CR_RATES_80211B | CR_RATES_80211G); - if (r < 0) - goto disable_int; - r = set_rx_filter(mac); - if (r) - goto disable_int; - r = set_mc_hash(mac); - if (r) - goto disable_int; - r = zd_chip_switch_radio_on(chip); - if (r < 0) - goto disable_int; - r = zd_chip_enable_rxtx(chip); - if (r < 0) - goto disable_radio; - r = zd_chip_enable_hwint(chip); - if (r < 0) - goto disable_rxtx; - - housekeeping_enable(mac); - return 0; -disable_rxtx: - zd_chip_disable_rxtx(chip); -disable_radio: - zd_chip_switch_radio_off(chip); -disable_int: - zd_chip_disable_int(chip); -out: - return r; -} - -static void zd_op_stop(struct ieee80211_hw *hw) -{ - struct zd_mac *mac = zd_hw_mac(hw); - struct zd_chip *chip = &mac->chip; - struct sk_buff *skb; - struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue; - - /* The order here deliberately is a little different from the open() - * method, since we need to make sure there is no opportunity for RX - * frames to be processed by mac80211 after we have stopped it. - */ - - zd_chip_disable_rxtx(chip); - housekeeping_disable(mac); - flush_workqueue(zd_workqueue); - - zd_chip_disable_hwint(chip); - zd_chip_switch_radio_off(chip); - zd_chip_disable_int(chip); - - - while ((skb = skb_dequeue(ack_wait_queue))) - dev_kfree_skb_any(skb); -} - -/** - * tx_status - reports tx status of a packet if required - * @hw - a &struct ieee80211_hw pointer - * @skb - a sk-buffer - * @flags: extra flags to set in the TX status info - * @ackssi: ACK signal strength - * @success - True for successful transmission of the frame - * - * This information calls ieee80211_tx_status_irqsafe() if required by the - * control information. It copies the control information into the status - * information. - * - * If no status information has been requested, the skb is freed. - */ -static void tx_status(struct ieee80211_hw *hw, struct sk_buff *skb, - int ackssi, bool success) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - ieee80211_tx_info_clear_status(info); - - if (success) - info->flags |= IEEE80211_TX_STAT_ACK; - info->status.ack_signal = ackssi; - ieee80211_tx_status_irqsafe(hw, skb); -} - -/** - * zd_mac_tx_failed - callback for failed frames - * @dev: the mac80211 wireless device - * - * This function is called if a frame couldn't be succesfully be - * transferred. The first frame from the tx queue, will be selected and - * reported as error to the upper layers. - */ -void zd_mac_tx_failed(struct ieee80211_hw *hw) -{ - struct sk_buff_head *q = &zd_hw_mac(hw)->ack_wait_queue; - struct sk_buff *skb; - - skb = skb_dequeue(q); - if (skb == NULL) - return; - - tx_status(hw, skb, 0, 0); -} - -/** - * zd_mac_tx_to_dev - callback for USB layer - * @skb: a &sk_buff pointer - * @error: error value, 0 if transmission successful - * - * Informs the MAC layer that the frame has successfully transferred to the - * device. If an ACK is required and the transfer to the device has been - * successful, the packets are put on the @ack_wait_queue with - * the control set removed. - */ -void zd_mac_tx_to_dev(struct sk_buff *skb, int error) -{ - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - struct ieee80211_hw *hw = info->rate_driver_data[0]; - - skb_pull(skb, sizeof(struct zd_ctrlset)); - if (unlikely(error || - (info->flags & IEEE80211_TX_CTL_NO_ACK))) { - tx_status(hw, skb, 0, !error); - } else { - struct sk_buff_head *q = - &zd_hw_mac(hw)->ack_wait_queue; - - skb_queue_tail(q, skb); - while (skb_queue_len(q) > ZD_MAC_MAX_ACK_WAITERS) - zd_mac_tx_failed(hw); - } -} - -static int zd_calc_tx_length_us(u8 *service, u8 zd_rate, u16 tx_length) -{ - /* ZD_PURE_RATE() must be used to remove the modulation type flag of - * the zd-rate values. - */ - static const u8 rate_divisor[] = { - [ZD_PURE_RATE(ZD_CCK_RATE_1M)] = 1, - [ZD_PURE_RATE(ZD_CCK_RATE_2M)] = 2, - /* Bits must be doubled. */ - [ZD_PURE_RATE(ZD_CCK_RATE_5_5M)] = 11, - [ZD_PURE_RATE(ZD_CCK_RATE_11M)] = 11, - [ZD_PURE_RATE(ZD_OFDM_RATE_6M)] = 6, - [ZD_PURE_RATE(ZD_OFDM_RATE_9M)] = 9, - [ZD_PURE_RATE(ZD_OFDM_RATE_12M)] = 12, - [ZD_PURE_RATE(ZD_OFDM_RATE_18M)] = 18, - [ZD_PURE_RATE(ZD_OFDM_RATE_24M)] = 24, - [ZD_PURE_RATE(ZD_OFDM_RATE_36M)] = 36, - [ZD_PURE_RATE(ZD_OFDM_RATE_48M)] = 48, - [ZD_PURE_RATE(ZD_OFDM_RATE_54M)] = 54, - }; - - u32 bits = (u32)tx_length * 8; - u32 divisor; - - divisor = rate_divisor[ZD_PURE_RATE(zd_rate)]; - if (divisor == 0) - return -EINVAL; - - switch (zd_rate) { - case ZD_CCK_RATE_5_5M: - bits = (2*bits) + 10; /* round up to the next integer */ - break; - case ZD_CCK_RATE_11M: - if (service) { - u32 t = bits % 11; - *service &= ~ZD_PLCP_SERVICE_LENGTH_EXTENSION; - if (0 < t && t <= 3) { - *service |= ZD_PLCP_SERVICE_LENGTH_EXTENSION; - } - } - bits += 10; /* round up to the next integer */ - break; - } - - return bits/divisor; -} - -static void cs_set_control(struct zd_mac *mac, struct zd_ctrlset *cs, - struct ieee80211_hdr *header, - struct ieee80211_tx_info *info) -{ - /* - * CONTROL TODO: - * - if backoff needed, enable bit 0 - * - if burst (backoff not needed) disable bit 0 - */ - - cs->control = 0; - - /* First fragment */ - if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) - cs->control |= ZD_CS_NEED_RANDOM_BACKOFF; - - /* No ACK expected (multicast, etc.) */ - if (info->flags & IEEE80211_TX_CTL_NO_ACK) - cs->control |= ZD_CS_NO_ACK; - - /* PS-POLL */ - if (ieee80211_is_pspoll(header->frame_control)) - cs->control |= ZD_CS_PS_POLL_FRAME; - - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) - cs->control |= ZD_CS_RTS; - - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) - cs->control |= ZD_CS_SELF_CTS; - - /* FIXME: Management frame? */ -} - -static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon) -{ - struct zd_mac *mac = zd_hw_mac(hw); - int r; - u32 tmp, j = 0; - /* 4 more bytes for tail CRC */ - u32 full_len = beacon->len + 4; - - r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0); - if (r < 0) - return r; - r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); - if (r < 0) - return r; - - while (tmp & 0x2) { - r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp); - if (r < 0) - return r; - if ((++j % 100) == 0) { - printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n"); - if (j >= 500) { - printk(KERN_ERR "Giving up beacon config.\n"); - return -ETIMEDOUT; - } - } - msleep(1); - } - - r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1); - if (r < 0) - return r; - if (zd_chip_is_zd1211b(&mac->chip)) { - r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1); - if (r < 0) - return r; - } - - for (j = 0 ; j < beacon->len; j++) { - r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, - *((u8 *)(beacon->data + j))); - if (r < 0) - return r; - } - - for (j = 0; j < 4; j++) { - r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0); - if (r < 0) - return r; - } - - r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1); - if (r < 0) - return r; - - /* 802.11b/g 2.4G CCK 1Mb - * 802.11a, not yet implemented, uses different values (see GPL vendor - * driver) - */ - return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 | - (full_len << 19)); -} - -static int fill_ctrlset(struct zd_mac *mac, - struct sk_buff *skb) -{ - int r; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - unsigned int frag_len = skb->len + FCS_LEN; - unsigned int packet_length; - struct ieee80211_rate *txrate; - struct zd_ctrlset *cs = (struct zd_ctrlset *) - skb_push(skb, sizeof(struct zd_ctrlset)); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - - ZD_ASSERT(frag_len <= 0xffff); - - txrate = ieee80211_get_tx_rate(mac->hw, info); - - cs->modulation = txrate->hw_value; - if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE) - cs->modulation = txrate->hw_value_short; - - cs->tx_length = cpu_to_le16(frag_len); - - cs_set_control(mac, cs, hdr, info); - - packet_length = frag_len + sizeof(struct zd_ctrlset) + 10; - ZD_ASSERT(packet_length <= 0xffff); - /* ZD1211B: Computing the length difference this way, gives us - * flexibility to compute the packet length. - */ - cs->packet_length = cpu_to_le16(zd_chip_is_zd1211b(&mac->chip) ? - packet_length - frag_len : packet_length); - - /* - * CURRENT LENGTH: - * - transmit frame length in microseconds - * - seems to be derived from frame length - * - see Cal_Us_Service() in zdinlinef.h - * - if macp->bTxBurstEnable is enabled, then multiply by 4 - * - bTxBurstEnable is never set in the vendor driver - * - * SERVICE: - * - "for PLCP configuration" - * - always 0 except in some situations at 802.11b 11M - * - see line 53 of zdinlinef.h - */ - cs->service = 0; - r = zd_calc_tx_length_us(&cs->service, ZD_RATE(cs->modulation), - le16_to_cpu(cs->tx_length)); - if (r < 0) - return r; - cs->current_length = cpu_to_le16(r); - cs->next_frame_length = 0; - - return 0; -} - -/** - * zd_op_tx - transmits a network frame to the device - * - * @dev: mac80211 hardware device - * @skb: socket buffer - * @control: the control structure - * - * This function transmit an IEEE 802.11 network frame to the device. The - * control block of the skbuff will be initialized. If necessary the incoming - * mac80211 queues will be stopped. - */ -static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb) -{ - struct zd_mac *mac = zd_hw_mac(hw); - struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); - int r; - - r = fill_ctrlset(mac, skb); - if (r) - goto fail; - - info->rate_driver_data[0] = hw; - - r = zd_usb_tx(&mac->chip.usb, skb); - if (r) - goto fail; - return 0; - -fail: - dev_kfree_skb(skb); - return 0; -} - -/** - * filter_ack - filters incoming packets for acknowledgements - * @dev: the mac80211 device - * @rx_hdr: received header - * @stats: the status for the received packet - * - * This functions looks for ACK packets and tries to match them with the - * frames in the tx queue. If a match is found the frame will be dequeued and - * the upper layers is informed about the successful transmission. If - * mac80211 queues have been stopped and the number of frames still to be - * transmitted is low the queues will be opened again. - * - * Returns 1 if the frame was an ACK, 0 if it was ignored. - */ -static int filter_ack(struct ieee80211_hw *hw, struct ieee80211_hdr *rx_hdr, - struct ieee80211_rx_status *stats) -{ - struct sk_buff *skb; - struct sk_buff_head *q; - unsigned long flags; - - if (!ieee80211_is_ack(rx_hdr->frame_control)) - return 0; - - q = &zd_hw_mac(hw)->ack_wait_queue; - spin_lock_irqsave(&q->lock, flags); - skb_queue_walk(q, skb) { - struct ieee80211_hdr *tx_hdr; - - tx_hdr = (struct ieee80211_hdr *)skb->data; - if (likely(!memcmp(tx_hdr->addr2, rx_hdr->addr1, ETH_ALEN))) - { - __skb_unlink(skb, q); - tx_status(hw, skb, stats->signal, 1); - goto out; - } - } -out: - spin_unlock_irqrestore(&q->lock, flags); - return 1; -} - -int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length) -{ - struct zd_mac *mac = zd_hw_mac(hw); - struct ieee80211_rx_status stats; - const struct rx_status *status; - struct sk_buff *skb; - int bad_frame = 0; - __le16 fc; - int need_padding; - int i; - u8 rate; - - if (length < ZD_PLCP_HEADER_SIZE + 10 /* IEEE80211_1ADDR_LEN */ + - FCS_LEN + sizeof(struct rx_status)) - return -EINVAL; - - memset(&stats, 0, sizeof(stats)); - - /* Note about pass_failed_fcs and pass_ctrl access below: - * mac locking intentionally omitted here, as this is the only unlocked - * reader and the only writer is configure_filter. Plus, if there were - * any races accessing these variables, it wouldn't really matter. - * If mac80211 ever provides a way for us to access filter flags - * from outside configure_filter, we could improve on this. Also, this - * situation may change once we implement some kind of DMA-into-skb - * RX path. */ - - /* Caller has to ensure that length >= sizeof(struct rx_status). */ - status = (struct rx_status *) - (buffer + (length - sizeof(struct rx_status))); - if (status->frame_status & ZD_RX_ERROR) { - if (mac->pass_failed_fcs && - (status->frame_status & ZD_RX_CRC32_ERROR)) { - stats.flag |= RX_FLAG_FAILED_FCS_CRC; - bad_frame = 1; - } else { - return -EINVAL; - } - } - - stats.freq = zd_channels[_zd_chip_get_channel(&mac->chip) - 1].center_freq; - stats.band = IEEE80211_BAND_2GHZ; - stats.signal = status->signal_strength; - stats.qual = zd_rx_qual_percent(buffer, - length - sizeof(struct rx_status), - status); - - rate = zd_rx_rate(buffer, status); - - /* todo: return index in the big switches in zd_rx_rate instead */ - for (i = 0; i < mac->band.n_bitrates; i++) - if (rate == mac->band.bitrates[i].hw_value) - stats.rate_idx = i; - - length -= ZD_PLCP_HEADER_SIZE + sizeof(struct rx_status); - buffer += ZD_PLCP_HEADER_SIZE; - - /* Except for bad frames, filter each frame to see if it is an ACK, in - * which case our internal TX tracking is updated. Normally we then - * bail here as there's no need to pass ACKs on up to the stack, but - * there is also the case where the stack has requested us to pass - * control frames on up (pass_ctrl) which we must consider. */ - if (!bad_frame && - filter_ack(hw, (struct ieee80211_hdr *)buffer, &stats) - && !mac->pass_ctrl) - return 0; - - fc = get_unaligned((__le16*)buffer); - need_padding = ieee80211_is_data_qos(fc) ^ ieee80211_has_a4(fc); - - skb = dev_alloc_skb(length + (need_padding ? 2 : 0)); - if (skb == NULL) - return -ENOMEM; - if (need_padding) { - /* Make sure the the payload data is 4 byte aligned. */ - skb_reserve(skb, 2); - } - - memcpy(skb_put(skb, length), buffer, length); - - memcpy(IEEE80211_SKB_RXCB(skb), &stats, sizeof(stats)); - ieee80211_rx_irqsafe(hw, skb); - return 0; -} - -static int zd_op_add_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct zd_mac *mac = zd_hw_mac(hw); - - /* using NL80211_IFTYPE_UNSPECIFIED to indicate no mode selected */ - if (mac->type != NL80211_IFTYPE_UNSPECIFIED) - return -EOPNOTSUPP; - - switch (conf->type) { - case NL80211_IFTYPE_MONITOR: - case NL80211_IFTYPE_MESH_POINT: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - mac->type = conf->type; - break; - default: - return -EOPNOTSUPP; - } - - return zd_write_mac_addr(&mac->chip, conf->mac_addr); -} - -static void zd_op_remove_interface(struct ieee80211_hw *hw, - struct ieee80211_if_init_conf *conf) -{ - struct zd_mac *mac = zd_hw_mac(hw); - mac->type = NL80211_IFTYPE_UNSPECIFIED; - zd_set_beacon_interval(&mac->chip, 0); - zd_write_mac_addr(&mac->chip, NULL); -} - -static int zd_op_config(struct ieee80211_hw *hw, u32 changed) -{ - struct zd_mac *mac = zd_hw_mac(hw); - struct ieee80211_conf *conf = &hw->conf; - - return zd_chip_set_channel(&mac->chip, conf->channel->hw_value); -} - -static void zd_process_intr(struct work_struct *work) -{ - u16 int_status; - struct zd_mac *mac = container_of(work, struct zd_mac, process_intr); - - int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4)); - if (int_status & INT_CFG_NEXT_BCN) - dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n"); - else - dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n"); - - zd_chip_enable_hwint(&mac->chip); -} - - -static void set_multicast_hash_handler(struct work_struct *work) -{ - struct zd_mac *mac = - container_of(work, struct zd_mac, set_multicast_hash_work); - struct zd_mc_hash hash; - - spin_lock_irq(&mac->lock); - hash = mac->multicast_hash; - spin_unlock_irq(&mac->lock); - - zd_chip_set_multicast_hash(&mac->chip, &hash); -} - -static void set_rx_filter_handler(struct work_struct *work) -{ - struct zd_mac *mac = - container_of(work, struct zd_mac, set_rx_filter_work); - int r; - - dev_dbg_f(zd_mac_dev(mac), "\n"); - r = set_rx_filter(mac); - if (r) - dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r); -} - -static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw, - int mc_count, struct dev_addr_list *mclist) -{ - struct zd_mac *mac = zd_hw_mac(hw); - struct zd_mc_hash hash; - int i; - - zd_mc_clear(&hash); - - for (i = 0; i < mc_count; i++) { - if (!mclist) - break; - dev_dbg_f(zd_mac_dev(mac), "mc addr %pM\n", mclist->dmi_addr); - zd_mc_add_addr(&hash, mclist->dmi_addr); - mclist = mclist->next; - } - - return hash.low | ((u64)hash.high << 32); -} - -#define SUPPORTED_FIF_FLAGS \ - (FIF_PROMISC_IN_BSS | FIF_ALLMULTI | FIF_FCSFAIL | FIF_CONTROL | \ - FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC) -static void zd_op_configure_filter(struct ieee80211_hw *hw, - unsigned int changed_flags, - unsigned int *new_flags, - u64 multicast) -{ - struct zd_mc_hash hash = { - .low = multicast, - .high = multicast >> 32, - }; - struct zd_mac *mac = zd_hw_mac(hw); - unsigned long flags; - - /* Only deal with supported flags */ - changed_flags &= SUPPORTED_FIF_FLAGS; - *new_flags &= SUPPORTED_FIF_FLAGS; - - /* changed_flags is always populated but this driver - * doesn't support all FIF flags so its possible we don't - * need to do anything */ - if (!changed_flags) - return; - - if (*new_flags & (FIF_PROMISC_IN_BSS | FIF_ALLMULTI)) - zd_mc_add_all(&hash); - - spin_lock_irqsave(&mac->lock, flags); - mac->pass_failed_fcs = !!(*new_flags & FIF_FCSFAIL); - mac->pass_ctrl = !!(*new_flags & FIF_CONTROL); - mac->multicast_hash = hash; - spin_unlock_irqrestore(&mac->lock, flags); - - /* XXX: these can be called here now, can sleep now! */ - queue_work(zd_workqueue, &mac->set_multicast_hash_work); - - if (changed_flags & FIF_CONTROL) - queue_work(zd_workqueue, &mac->set_rx_filter_work); - - /* no handling required for FIF_OTHER_BSS as we don't currently - * do BSSID filtering */ - /* FIXME: in future it would be nice to enable the probe response - * filter (so that the driver doesn't see them) until - * FIF_BCN_PRBRESP_PROMISC is set. however due to atomicity here, we'd - * have to schedule work to enable prbresp reception, which might - * happen too late. For now we'll just listen and forward them all the - * time. */ -} - -static void set_rts_cts_work(struct work_struct *work) -{ - struct zd_mac *mac = - container_of(work, struct zd_mac, set_rts_cts_work); - unsigned long flags; - unsigned int short_preamble; - - mutex_lock(&mac->chip.mutex); - - spin_lock_irqsave(&mac->lock, flags); - mac->updating_rts_rate = 0; - short_preamble = mac->short_preamble; - spin_unlock_irqrestore(&mac->lock, flags); - - zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble); - mutex_unlock(&mac->chip.mutex); -} - -static void zd_op_bss_info_changed(struct ieee80211_hw *hw, - struct ieee80211_vif *vif, - struct ieee80211_bss_conf *bss_conf, - u32 changes) -{ - struct zd_mac *mac = zd_hw_mac(hw); - unsigned long flags; - int associated; - - dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes); - - if (mac->type == NL80211_IFTYPE_MESH_POINT || - mac->type == NL80211_IFTYPE_ADHOC) { - associated = true; - if (changes & BSS_CHANGED_BEACON) { - struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); - - if (beacon) { - zd_mac_config_beacon(hw, beacon); - kfree_skb(beacon); - } - } - - if (changes & BSS_CHANGED_BEACON_ENABLED) { - u32 interval; - - if (bss_conf->enable_beacon) - interval = BCN_MODE_IBSS | - bss_conf->beacon_int; - else - interval = 0; - - zd_set_beacon_interval(&mac->chip, interval); - } - } else - associated = is_valid_ether_addr(bss_conf->bssid); - - spin_lock_irq(&mac->lock); - mac->associated = associated; - spin_unlock_irq(&mac->lock); - - /* TODO: do hardware bssid filtering */ - - if (changes & BSS_CHANGED_ERP_PREAMBLE) { - spin_lock_irqsave(&mac->lock, flags); - mac->short_preamble = bss_conf->use_short_preamble; - if (!mac->updating_rts_rate) { - mac->updating_rts_rate = 1; - /* FIXME: should disable TX here, until work has - * completed and RTS_CTS reg is updated */ - queue_work(zd_workqueue, &mac->set_rts_cts_work); - } - spin_unlock_irqrestore(&mac->lock, flags); - } -} - -static u64 zd_op_get_tsf(struct ieee80211_hw *hw) -{ - struct zd_mac *mac = zd_hw_mac(hw); - return zd_chip_get_tsf(&mac->chip); -} - -static const struct ieee80211_ops zd_ops = { - .tx = zd_op_tx, - .start = zd_op_start, - .stop = zd_op_stop, - .add_interface = zd_op_add_interface, - .remove_interface = zd_op_remove_interface, - .config = zd_op_config, - .prepare_multicast = zd_op_prepare_multicast, - .configure_filter = zd_op_configure_filter, - .bss_info_changed = zd_op_bss_info_changed, - .get_tsf = zd_op_get_tsf, -}; - -struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf) -{ - struct zd_mac *mac; - struct ieee80211_hw *hw; - - hw = ieee80211_alloc_hw(sizeof(struct zd_mac), &zd_ops); - if (!hw) { - dev_dbg_f(&intf->dev, "out of memory\n"); - return NULL; - } - - mac = zd_hw_mac(hw); - - memset(mac, 0, sizeof(*mac)); - spin_lock_init(&mac->lock); - mac->hw = hw; - - mac->type = NL80211_IFTYPE_UNSPECIFIED; - - memcpy(mac->channels, zd_channels, sizeof(zd_channels)); - memcpy(mac->rates, zd_rates, sizeof(zd_rates)); - mac->band.n_bitrates = ARRAY_SIZE(zd_rates); - mac->band.bitrates = mac->rates; - mac->band.n_channels = ARRAY_SIZE(zd_channels); - mac->band.channels = mac->channels; - - hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band; - - hw->flags = IEEE80211_HW_RX_INCLUDES_FCS | - IEEE80211_HW_SIGNAL_UNSPEC; - - hw->wiphy->interface_modes = - BIT(NL80211_IFTYPE_MESH_POINT) | - BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC); - - hw->max_signal = 100; - hw->queues = 1; - hw->extra_tx_headroom = sizeof(struct zd_ctrlset); - - skb_queue_head_init(&mac->ack_wait_queue); - - zd_chip_init(&mac->chip, hw, intf); - housekeeping_init(mac); - INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler); - INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work); - INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler); - INIT_WORK(&mac->process_intr, zd_process_intr); - - SET_IEEE80211_DEV(hw, &intf->dev); - return hw; -} - -#define LINK_LED_WORK_DELAY HZ - -static void link_led_handler(struct work_struct *work) -{ - struct zd_mac *mac = - container_of(work, struct zd_mac, housekeeping.link_led_work.work); - struct zd_chip *chip = &mac->chip; - int is_associated; - int r; - - spin_lock_irq(&mac->lock); - is_associated = mac->associated; - spin_unlock_irq(&mac->lock); - - r = zd_chip_control_leds(chip, - is_associated ? ZD_LED_ASSOCIATED : ZD_LED_SCANNING); - if (r) - dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r); - - queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work, - LINK_LED_WORK_DELAY); -} - -static void housekeeping_init(struct zd_mac *mac) -{ - INIT_DELAYED_WORK(&mac->housekeeping.link_led_work, link_led_handler); -} - -static void housekeeping_enable(struct zd_mac *mac) -{ - dev_dbg_f(zd_mac_dev(mac), "\n"); - queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work, - 0); -} - -static void housekeeping_disable(struct zd_mac *mac) -{ - dev_dbg_f(zd_mac_dev(mac), "\n"); - cancel_rearming_delayed_workqueue(zd_workqueue, - &mac->housekeeping.link_led_work); - zd_chip_control_leds(&mac->chip, ZD_LED_OFF); -} diff --git a/drivers/net/wireless/zd1211rw/zd_mac.h b/drivers/net/wireless/zd1211rw/zd_mac.h deleted file mode 100644 index 7c2759118d13..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_mac.h +++ /dev/null @@ -1,291 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#ifndef _ZD_MAC_H -#define _ZD_MAC_H - -#include -#include - -#include "zd_chip.h" - -struct zd_ctrlset { - u8 modulation; - __le16 tx_length; - u8 control; - /* stores only the difference to tx_length on ZD1211B */ - __le16 packet_length; - __le16 current_length; - u8 service; - __le16 next_frame_length; -} __attribute__((packed)); - -#define ZD_CS_RESERVED_SIZE 25 - -/* The field modulation of struct zd_ctrlset controls the bit rate, the use - * of short or long preambles in 802.11b (CCK mode) or the use of 802.11a or - * 802.11g in OFDM mode. - * - * The term zd-rate is used for the combination of the modulation type flag - * and the "pure" rate value. - */ -#define ZD_PURE_RATE_MASK 0x0f -#define ZD_MODULATION_TYPE_MASK 0x10 -#define ZD_RATE_MASK (ZD_PURE_RATE_MASK|ZD_MODULATION_TYPE_MASK) -#define ZD_PURE_RATE(modulation) ((modulation) & ZD_PURE_RATE_MASK) -#define ZD_MODULATION_TYPE(modulation) ((modulation) & ZD_MODULATION_TYPE_MASK) -#define ZD_RATE(modulation) ((modulation) & ZD_RATE_MASK) - -/* The two possible modulation types. Notify that 802.11b doesn't use the CCK - * codeing for the 1 and 2 MBit/s rate. We stay with the term here to remain - * consistent with uses the term at other places. - */ -#define ZD_CCK 0x00 -#define ZD_OFDM 0x10 - -/* The ZD1211 firmware uses proprietary encodings of the 802.11b (CCK) rates. - * For OFDM the PLCP rate encodings are used. We combine these "pure" rates - * with the modulation type flag and call the resulting values zd-rates. - */ -#define ZD_CCK_RATE_1M (ZD_CCK|0x00) -#define ZD_CCK_RATE_2M (ZD_CCK|0x01) -#define ZD_CCK_RATE_5_5M (ZD_CCK|0x02) -#define ZD_CCK_RATE_11M (ZD_CCK|0x03) -#define ZD_OFDM_RATE_6M (ZD_OFDM|ZD_OFDM_PLCP_RATE_6M) -#define ZD_OFDM_RATE_9M (ZD_OFDM|ZD_OFDM_PLCP_RATE_9M) -#define ZD_OFDM_RATE_12M (ZD_OFDM|ZD_OFDM_PLCP_RATE_12M) -#define ZD_OFDM_RATE_18M (ZD_OFDM|ZD_OFDM_PLCP_RATE_18M) -#define ZD_OFDM_RATE_24M (ZD_OFDM|ZD_OFDM_PLCP_RATE_24M) -#define ZD_OFDM_RATE_36M (ZD_OFDM|ZD_OFDM_PLCP_RATE_36M) -#define ZD_OFDM_RATE_48M (ZD_OFDM|ZD_OFDM_PLCP_RATE_48M) -#define ZD_OFDM_RATE_54M (ZD_OFDM|ZD_OFDM_PLCP_RATE_54M) - -/* The bit 5 of the zd_ctrlset modulation field controls the preamble in CCK - * mode or the 802.11a/802.11g selection in OFDM mode. - */ -#define ZD_CCK_PREA_LONG 0x00 -#define ZD_CCK_PREA_SHORT 0x20 -#define ZD_OFDM_MODE_11G 0x00 -#define ZD_OFDM_MODE_11A 0x20 - -/* zd_ctrlset control field */ -#define ZD_CS_NEED_RANDOM_BACKOFF 0x01 -#define ZD_CS_NO_ACK 0x02 - -#define ZD_CS_FRAME_TYPE_MASK 0x0c -#define ZD_CS_DATA_FRAME 0x00 -#define ZD_CS_PS_POLL_FRAME 0x04 -#define ZD_CS_MANAGEMENT_FRAME 0x08 -#define ZD_CS_NO_SEQUENCE_CTL_FRAME 0x0c - -#define ZD_CS_WAKE_DESTINATION 0x10 -#define ZD_CS_RTS 0x20 -#define ZD_CS_ENCRYPT 0x40 -#define ZD_CS_SELF_CTS 0x80 - -/* Incoming frames are prepended by a PLCP header */ -#define ZD_PLCP_HEADER_SIZE 5 - -struct rx_length_info { - __le16 length[3]; - __le16 tag; -} __attribute__((packed)); - -#define RX_LENGTH_INFO_TAG 0x697e - -struct rx_status { - u8 signal_quality_cck; - /* rssi */ - u8 signal_strength; - u8 signal_quality_ofdm; - u8 decryption_type; - u8 frame_status; -} __attribute__((packed)); - -/* rx_status field decryption_type */ -#define ZD_RX_NO_WEP 0 -#define ZD_RX_WEP64 1 -#define ZD_RX_TKIP 2 -#define ZD_RX_AES 4 -#define ZD_RX_WEP128 5 -#define ZD_RX_WEP256 6 - -/* rx_status field frame_status */ -#define ZD_RX_FRAME_MODULATION_MASK 0x01 -#define ZD_RX_CCK 0x00 -#define ZD_RX_OFDM 0x01 - -#define ZD_RX_TIMEOUT_ERROR 0x02 -#define ZD_RX_FIFO_OVERRUN_ERROR 0x04 -#define ZD_RX_DECRYPTION_ERROR 0x08 -#define ZD_RX_CRC32_ERROR 0x10 -#define ZD_RX_NO_ADDR1_MATCH_ERROR 0x20 -#define ZD_RX_CRC16_ERROR 0x40 -#define ZD_RX_ERROR 0x80 - -enum mac_flags { - MAC_FIXED_CHANNEL = 0x01, -}; - -struct housekeeping { - struct delayed_work link_led_work; -}; - -#define ZD_MAC_STATS_BUFFER_SIZE 16 - -#define ZD_MAC_MAX_ACK_WAITERS 10 - -struct zd_mac { - struct zd_chip chip; - spinlock_t lock; - spinlock_t intr_lock; - struct ieee80211_hw *hw; - struct housekeeping housekeeping; - struct work_struct set_multicast_hash_work; - struct work_struct set_rts_cts_work; - struct work_struct set_rx_filter_work; - struct work_struct process_intr; - struct zd_mc_hash multicast_hash; - u8 intr_buffer[USB_MAX_EP_INT_BUFFER]; - u8 regdomain; - u8 default_regdomain; - int type; - int associated; - struct sk_buff_head ack_wait_queue; - struct ieee80211_channel channels[14]; - struct ieee80211_rate rates[12]; - struct ieee80211_supported_band band; - - /* Short preamble (used for RTS/CTS) */ - unsigned int short_preamble:1; - - /* flags to indicate update in progress */ - unsigned int updating_rts_rate:1; - - /* whether to pass frames with CRC errors to stack */ - unsigned int pass_failed_fcs:1; - - /* whether to pass control frames to stack */ - unsigned int pass_ctrl:1; -}; - -#define ZD_REGDOMAIN_FCC 0x10 -#define ZD_REGDOMAIN_IC 0x20 -#define ZD_REGDOMAIN_ETSI 0x30 -#define ZD_REGDOMAIN_SPAIN 0x31 -#define ZD_REGDOMAIN_FRANCE 0x32 -#define ZD_REGDOMAIN_JAPAN_ADD 0x40 -#define ZD_REGDOMAIN_JAPAN 0x41 - -enum { - MIN_CHANNEL24 = 1, - MAX_CHANNEL24 = 14, -}; - -#define ZD_PLCP_SERVICE_LENGTH_EXTENSION 0x80 - -struct ofdm_plcp_header { - u8 prefix[3]; - __le16 service; -} __attribute__((packed)); - -static inline u8 zd_ofdm_plcp_header_rate(const struct ofdm_plcp_header *header) -{ - return header->prefix[0] & 0xf; -} - -/* The following defines give the encoding of the 4-bit rate field in the - * OFDM (802.11a/802.11g) PLCP header. Notify that these values are used to - * define the zd-rate values for OFDM. - * - * See the struct zd_ctrlset definition in zd_mac.h. - */ -#define ZD_OFDM_PLCP_RATE_6M 0xb -#define ZD_OFDM_PLCP_RATE_9M 0xf -#define ZD_OFDM_PLCP_RATE_12M 0xa -#define ZD_OFDM_PLCP_RATE_18M 0xe -#define ZD_OFDM_PLCP_RATE_24M 0x9 -#define ZD_OFDM_PLCP_RATE_36M 0xd -#define ZD_OFDM_PLCP_RATE_48M 0x8 -#define ZD_OFDM_PLCP_RATE_54M 0xc - -struct cck_plcp_header { - u8 signal; - u8 service; - __le16 length; - __le16 crc16; -} __attribute__((packed)); - -static inline u8 zd_cck_plcp_header_signal(const struct cck_plcp_header *header) -{ - return header->signal; -} - -/* These defines give the encodings of the signal field in the 802.11b PLCP - * header. The signal field gives the bit rate of the following packet. Even - * if technically wrong we use CCK here also for the 1 MBit/s and 2 MBit/s - * rate to stay consistent with Zydas and our use of the term. - * - * Notify that these values are *not* used in the zd-rates. - */ -#define ZD_CCK_PLCP_SIGNAL_1M 0x0a -#define ZD_CCK_PLCP_SIGNAL_2M 0x14 -#define ZD_CCK_PLCP_SIGNAL_5M5 0x37 -#define ZD_CCK_PLCP_SIGNAL_11M 0x6e - -static inline struct zd_mac *zd_hw_mac(struct ieee80211_hw *hw) -{ - return hw->priv; -} - -static inline struct zd_mac *zd_chip_to_mac(struct zd_chip *chip) -{ - return container_of(chip, struct zd_mac, chip); -} - -static inline struct zd_mac *zd_usb_to_mac(struct zd_usb *usb) -{ - return zd_chip_to_mac(zd_usb_to_chip(usb)); -} - -static inline u8 *zd_mac_get_perm_addr(struct zd_mac *mac) -{ - return mac->hw->wiphy->perm_addr; -} - -#define zd_mac_dev(mac) (zd_chip_dev(&(mac)->chip)) - -struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf); -void zd_mac_clear(struct zd_mac *mac); - -int zd_mac_preinit_hw(struct ieee80211_hw *hw); -int zd_mac_init_hw(struct ieee80211_hw *hw); - -int zd_mac_rx(struct ieee80211_hw *hw, const u8 *buffer, unsigned int length); -void zd_mac_tx_failed(struct ieee80211_hw *hw); -void zd_mac_tx_to_dev(struct sk_buff *skb, int error); - -#ifdef DEBUG -void zd_dump_rx_status(const struct rx_status *status); -#else -#define zd_dump_rx_status(status) -#endif /* DEBUG */ - -#endif /* _ZD_MAC_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf.c b/drivers/net/wireless/zd1211rw/zd_rf.c deleted file mode 100644 index c875ee05e22e..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_rf.c +++ /dev/null @@ -1,182 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#include -#include - -#include "zd_def.h" -#include "zd_rf.h" -#include "zd_mac.h" -#include "zd_chip.h" - -static const char * const rfs[] = { - [0] = "unknown RF0", - [1] = "unknown RF1", - [UW2451_RF] = "UW2451_RF", - [UCHIP_RF] = "UCHIP_RF", - [AL2230_RF] = "AL2230_RF", - [AL7230B_RF] = "AL7230B_RF", - [THETA_RF] = "THETA_RF", - [AL2210_RF] = "AL2210_RF", - [MAXIM_NEW_RF] = "MAXIM_NEW_RF", - [UW2453_RF] = "UW2453_RF", - [AL2230S_RF] = "AL2230S_RF", - [RALINK_RF] = "RALINK_RF", - [INTERSIL_RF] = "INTERSIL_RF", - [RF2959_RF] = "RF2959_RF", - [MAXIM_NEW2_RF] = "MAXIM_NEW2_RF", - [PHILIPS_RF] = "PHILIPS_RF", -}; - -const char *zd_rf_name(u8 type) -{ - if (type & 0xf0) - type = 0; - return rfs[type]; -} - -void zd_rf_init(struct zd_rf *rf) -{ - memset(rf, 0, sizeof(*rf)); - - /* default to update channel integration, as almost all RF's do want - * this */ - rf->update_channel_int = 1; -} - -void zd_rf_clear(struct zd_rf *rf) -{ - if (rf->clear) - rf->clear(rf); - ZD_MEMCLEAR(rf, sizeof(*rf)); -} - -int zd_rf_init_hw(struct zd_rf *rf, u8 type) -{ - int r = 0; - int t; - struct zd_chip *chip = zd_rf_to_chip(rf); - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - switch (type) { - case RF2959_RF: - r = zd_rf_init_rf2959(rf); - break; - case AL2230_RF: - case AL2230S_RF: - r = zd_rf_init_al2230(rf); - break; - case AL7230B_RF: - r = zd_rf_init_al7230b(rf); - break; - case MAXIM_NEW_RF: - case UW2453_RF: - r = zd_rf_init_uw2453(rf); - break; - default: - dev_err(zd_chip_dev(chip), - "RF %s %#x is not supported\n", zd_rf_name(type), type); - rf->type = 0; - return -ENODEV; - } - - if (r) - return r; - - rf->type = type; - - r = zd_chip_lock_phy_regs(chip); - if (r) - return r; - t = rf->init_hw(rf); - r = zd_chip_unlock_phy_regs(chip); - if (t) - r = t; - return r; -} - -int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size) -{ - return scnprintf(buffer, size, "%s", zd_rf_name(rf->type)); -} - -int zd_rf_set_channel(struct zd_rf *rf, u8 channel) -{ - int r; - - ZD_ASSERT(mutex_is_locked(&zd_rf_to_chip(rf)->mutex)); - if (channel < MIN_CHANNEL24) - return -EINVAL; - if (channel > MAX_CHANNEL24) - return -EINVAL; - dev_dbg_f(zd_chip_dev(zd_rf_to_chip(rf)), "channel: %d\n", channel); - - r = rf->set_channel(rf, channel); - if (r >= 0) - rf->channel = channel; - return r; -} - -int zd_switch_radio_on(struct zd_rf *rf) -{ - int r, t; - struct zd_chip *chip = zd_rf_to_chip(rf); - - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_chip_lock_phy_regs(chip); - if (r) - return r; - t = rf->switch_radio_on(rf); - r = zd_chip_unlock_phy_regs(chip); - if (t) - r = t; - return r; -} - -int zd_switch_radio_off(struct zd_rf *rf) -{ - int r, t; - struct zd_chip *chip = zd_rf_to_chip(rf); - - /* TODO: move phy regs handling to zd_chip */ - ZD_ASSERT(mutex_is_locked(&chip->mutex)); - r = zd_chip_lock_phy_regs(chip); - if (r) - return r; - t = rf->switch_radio_off(rf); - r = zd_chip_unlock_phy_regs(chip); - if (t) - r = t; - return r; -} - -int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel) -{ - if (!rf->patch_6m_band_edge) - return 0; - - return rf->patch_6m_band_edge(rf, channel); -} - -int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel) -{ - return zd_chip_generic_patch_6m_band(zd_rf_to_chip(rf), channel); -} - diff --git a/drivers/net/wireless/zd1211rw/zd_rf.h b/drivers/net/wireless/zd1211rw/zd_rf.h deleted file mode 100644 index 79dc1035592d..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_rf.h +++ /dev/null @@ -1,111 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#ifndef _ZD_RF_H -#define _ZD_RF_H - -#define UW2451_RF 0x2 -#define UCHIP_RF 0x3 -#define AL2230_RF 0x4 -#define AL7230B_RF 0x5 /* a,b,g */ -#define THETA_RF 0x6 -#define AL2210_RF 0x7 -#define MAXIM_NEW_RF 0x8 -#define UW2453_RF 0x9 -#define AL2230S_RF 0xa -#define RALINK_RF 0xb -#define INTERSIL_RF 0xc -#define RF2959_RF 0xd -#define MAXIM_NEW2_RF 0xe -#define PHILIPS_RF 0xf - -#define RF_CHANNEL(ch) [(ch)-1] - -/* Provides functions of the RF transceiver. */ - -enum { - RF_REG_BITS = 6, - RF_VALUE_BITS = 18, - RF_RV_BITS = RF_REG_BITS + RF_VALUE_BITS, -}; - -struct zd_rf { - u8 type; - - u8 channel; - - /* whether channel integration and calibration should be updated - * defaults to 1 (yes) */ - u8 update_channel_int:1; - - /* whether CR47 should be patched from the EEPROM, if the appropriate - * flag is set in the POD. The vendor driver suggests that this should - * be done for all RF's, but a bug in their code prevents but their - * HW_OverWritePhyRegFromE2P() routine from ever taking effect. */ - u8 patch_cck_gain:1; - - /* private RF driver data */ - void *priv; - - /* RF-specific functions */ - int (*init_hw)(struct zd_rf *rf); - int (*set_channel)(struct zd_rf *rf, u8 channel); - int (*switch_radio_on)(struct zd_rf *rf); - int (*switch_radio_off)(struct zd_rf *rf); - int (*patch_6m_band_edge)(struct zd_rf *rf, u8 channel); - void (*clear)(struct zd_rf *rf); -}; - -const char *zd_rf_name(u8 type); -void zd_rf_init(struct zd_rf *rf); -void zd_rf_clear(struct zd_rf *rf); -int zd_rf_init_hw(struct zd_rf *rf, u8 type); - -int zd_rf_scnprint_id(struct zd_rf *rf, char *buffer, size_t size); - -int zd_rf_set_channel(struct zd_rf *rf, u8 channel); - -int zd_switch_radio_on(struct zd_rf *rf); -int zd_switch_radio_off(struct zd_rf *rf); - -int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); -int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); - -static inline int zd_rf_should_update_pwr_int(struct zd_rf *rf) -{ - return rf->update_channel_int; -} - -static inline int zd_rf_should_patch_cck_gain(struct zd_rf *rf) -{ - return rf->patch_cck_gain; -} - -int zd_rf_patch_6m_band_edge(struct zd_rf *rf, u8 channel); -int zd_rf_generic_patch_6m(struct zd_rf *rf, u8 channel); - -/* Functions for individual RF chips */ - -int zd_rf_init_rf2959(struct zd_rf *rf); -int zd_rf_init_al2230(struct zd_rf *rf); -int zd_rf_init_al7230b(struct zd_rf *rf); -int zd_rf_init_uw2453(struct zd_rf *rf); - -#endif /* _ZD_RF_H */ diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c b/drivers/net/wireless/zd1211rw/zd_rf_al2230.c deleted file mode 100644 index 74a8f7a55591..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_rf_al2230.c +++ /dev/null @@ -1,442 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#include - -#include "zd_rf.h" -#include "zd_usb.h" -#include "zd_chip.h" - -#define IS_AL2230S(chip) ((chip)->al2230s_bit || (chip)->rf.type == AL2230S_RF) - -static const u32 zd1211_al2230_table[][3] = { - RF_CHANNEL( 1) = { 0x03f790, 0x033331, 0x00000d, }, - RF_CHANNEL( 2) = { 0x03f790, 0x0b3331, 0x00000d, }, - RF_CHANNEL( 3) = { 0x03e790, 0x033331, 0x00000d, }, - RF_CHANNEL( 4) = { 0x03e790, 0x0b3331, 0x00000d, }, - RF_CHANNEL( 5) = { 0x03f7a0, 0x033331, 0x00000d, }, - RF_CHANNEL( 6) = { 0x03f7a0, 0x0b3331, 0x00000d, }, - RF_CHANNEL( 7) = { 0x03e7a0, 0x033331, 0x00000d, }, - RF_CHANNEL( 8) = { 0x03e7a0, 0x0b3331, 0x00000d, }, - RF_CHANNEL( 9) = { 0x03f7b0, 0x033331, 0x00000d, }, - RF_CHANNEL(10) = { 0x03f7b0, 0x0b3331, 0x00000d, }, - RF_CHANNEL(11) = { 0x03e7b0, 0x033331, 0x00000d, }, - RF_CHANNEL(12) = { 0x03e7b0, 0x0b3331, 0x00000d, }, - RF_CHANNEL(13) = { 0x03f7c0, 0x033331, 0x00000d, }, - RF_CHANNEL(14) = { 0x03e7c0, 0x066661, 0x00000d, }, -}; - -static const u32 zd1211b_al2230_table[][3] = { - RF_CHANNEL( 1) = { 0x09efc0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL( 2) = { 0x09efc0, 0x8cccd0, 0xb00000, }, - RF_CHANNEL( 3) = { 0x09e7c0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL( 4) = { 0x09e7c0, 0x8cccd0, 0xb00000, }, - RF_CHANNEL( 5) = { 0x05efc0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL( 6) = { 0x05efc0, 0x8cccd0, 0xb00000, }, - RF_CHANNEL( 7) = { 0x05e7c0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL( 8) = { 0x05e7c0, 0x8cccd0, 0xb00000, }, - RF_CHANNEL( 9) = { 0x0defc0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL(10) = { 0x0defc0, 0x8cccd0, 0xb00000, }, - RF_CHANNEL(11) = { 0x0de7c0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL(12) = { 0x0de7c0, 0x8cccd0, 0xb00000, }, - RF_CHANNEL(13) = { 0x03efc0, 0x8cccc0, 0xb00000, }, - RF_CHANNEL(14) = { 0x03e7c0, 0x866660, 0xb00000, }, -}; - -static const struct zd_ioreq16 zd1211b_ioreqs_shared_1[] = { - { CR240, 0x57 }, { CR9, 0xe0 }, -}; - -static const struct zd_ioreq16 ioreqs_init_al2230s[] = { - { CR47, 0x1e }, /* MARK_002 */ - { CR106, 0x22 }, - { CR107, 0x2a }, /* MARK_002 */ - { CR109, 0x13 }, /* MARK_002 */ - { CR118, 0xf8 }, /* MARK_002 */ - { CR119, 0x12 }, { CR122, 0xe0 }, - { CR128, 0x10 }, /* MARK_001 from 0xe->0x10 */ - { CR129, 0x0e }, /* MARK_001 from 0xd->0x0e */ - { CR130, 0x10 }, /* MARK_001 from 0xb->0x0d */ -}; - -static int zd1211b_al2230_finalize_rf(struct zd_chip *chip) -{ - int r; - static const struct zd_ioreq16 ioreqs[] = { - { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, - { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, - { CR203, 0x06 }, - { }, - - { CR240, 0x80 }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - - /* related to antenna selection? */ - if (chip->new_phy_layout) { - r = zd_iowrite16_locked(chip, 0xe1, CR9); - if (r) - return r; - } - - return zd_iowrite16_locked(chip, 0x06, CR203); -} - -static int zd1211_al2230_init_hw(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs_init[] = { - { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, - { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, - { CR44, 0x33 }, { CR106, 0x2a }, { CR107, 0x1a }, - { CR109, 0x09 }, { CR110, 0x27 }, { CR111, 0x2b }, - { CR112, 0x2b }, { CR119, 0x0a }, { CR10, 0x89 }, - /* for newest (3rd cut) AL2300 */ - { CR17, 0x28 }, - { CR26, 0x93 }, { CR34, 0x30 }, - /* for newest (3rd cut) AL2300 */ - { CR35, 0x3e }, - { CR41, 0x24 }, { CR44, 0x32 }, - /* for newest (3rd cut) AL2300 */ - { CR46, 0x96 }, - { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, - { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, - { CR92, 0x0a }, { CR99, 0x28 }, { CR100, 0x00 }, - { CR101, 0x13 }, { CR102, 0x27 }, { CR106, 0x24 }, - { CR107, 0x2a }, { CR109, 0x09 }, { CR110, 0x13 }, - { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x27 }, - /* for newest (3rd cut) AL2300 */ - { CR115, 0x24 }, - { CR116, 0x24 }, { CR117, 0xf4 }, { CR118, 0xfc }, - { CR119, 0x10 }, { CR120, 0x4f }, { CR121, 0x77 }, - { CR122, 0xe0 }, { CR137, 0x88 }, { CR252, 0xff }, - { CR253, 0xff }, - }; - - static const struct zd_ioreq16 ioreqs_pll[] = { - /* shdnb(PLL_ON)=0 */ - { CR251, 0x2f }, - /* shdnb(PLL_ON)=1 */ - { CR251, 0x3f }, - { CR138, 0x28 }, { CR203, 0x06 }, - }; - - static const u32 rv1[] = { - /* Channel 1 */ - 0x03f790, - 0x033331, - 0x00000d, - - 0x0b3331, - 0x03b812, - 0x00fff3, - }; - - static const u32 rv2[] = { - 0x000da4, - 0x0f4dc5, /* fix freq shift, 0x04edc5 */ - 0x0805b6, - 0x011687, - 0x000688, - 0x0403b9, /* external control TX power (CR31) */ - 0x00dbba, - 0x00099b, - 0x0bdffc, - 0x00000d, - 0x00500f, - }; - - static const u32 rv3[] = { - 0x00d00f, - 0x004c0f, - 0x00540f, - 0x00700f, - 0x00500f, - }; - - r = zd_iowrite16a_locked(chip, ioreqs_init, ARRAY_SIZE(ioreqs_init)); - if (r) - return r; - - if (IS_AL2230S(chip)) { - r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s, - ARRAY_SIZE(ioreqs_init_al2230s)); - if (r) - return r; - } - - r = zd_rfwritev_locked(chip, rv1, ARRAY_SIZE(rv1), RF_RV_BITS); - if (r) - return r; - - /* improve band edge for AL2230S */ - if (IS_AL2230S(chip)) - r = zd_rfwrite_locked(chip, 0x000824, RF_RV_BITS); - else - r = zd_rfwrite_locked(chip, 0x0005a4, RF_RV_BITS); - if (r) - return r; - - r = zd_rfwritev_locked(chip, rv2, ARRAY_SIZE(rv2), RF_RV_BITS); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs_pll, ARRAY_SIZE(ioreqs_pll)); - if (r) - return r; - - r = zd_rfwritev_locked(chip, rv3, ARRAY_SIZE(rv3), RF_RV_BITS); - if (r) - return r; - - return 0; -} - -static int zd1211b_al2230_init_hw(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs1[] = { - { CR10, 0x89 }, { CR15, 0x20 }, - { CR17, 0x2B }, /* for newest(3rd cut) AL2230 */ - { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, - { CR28, 0x3e }, { CR29, 0x00 }, - { CR33, 0x28 }, /* 5621 */ - { CR34, 0x30 }, - { CR35, 0x3e }, /* for newest(3rd cut) AL2230 */ - { CR41, 0x24 }, { CR44, 0x32 }, - { CR46, 0x99 }, /* for newest(3rd cut) AL2230 */ - { CR47, 0x1e }, - - /* ZD1211B 05.06.10 */ - { CR48, 0x06 }, { CR49, 0xf9 }, { CR51, 0x01 }, - { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, - { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, - { CR69, 0x28 }, - - { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, - { CR87, 0x0a }, { CR89, 0x04 }, - { CR91, 0x00 }, /* 5621 */ - { CR92, 0x0a }, - { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ - { CR99, 0x00 }, /* 5621 */ - { CR101, 0x13 }, { CR102, 0x27 }, - { CR106, 0x24 }, /* for newest(3rd cut) AL2230 */ - { CR107, 0x2a }, - { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ - { CR110, 0x1f }, /* 4804, for 1212 new algorithm */ - { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x27 }, - { CR115, 0x26 }, /* 24->26 at 4902 for newest(3rd cut) AL2230 */ - { CR116, 0x24 }, - { CR117, 0xfa }, /* for 1211b */ - { CR118, 0xfa }, /* for 1211b */ - { CR119, 0x10 }, - { CR120, 0x4f }, - { CR121, 0x6c }, /* for 1211b */ - { CR122, 0xfc }, /* E0->FC at 4902 */ - { CR123, 0x57 }, /* 5623 */ - { CR125, 0xad }, /* 4804, for 1212 new algorithm */ - { CR126, 0x6c }, /* 5614 */ - { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ - { CR137, 0x50 }, /* 5614 */ - { CR138, 0xa8 }, - { CR144, 0xac }, /* 5621 */ - { CR150, 0x0d }, { CR252, 0x34 }, { CR253, 0x34 }, - }; - - static const u32 rv1[] = { - 0x8cccd0, - 0x481dc0, - 0xcfff00, - 0x25a000, - }; - - static const u32 rv2[] = { - /* To improve AL2230 yield, improve phase noise, 4713 */ - 0x25a000, - 0xa3b2f0, - - 0x6da010, /* Reg6 update for MP versio */ - 0xe36280, /* Modified by jxiao for Bor-Chin on 2004/08/02 */ - 0x116000, - 0x9dc020, /* External control TX power (CR31) */ - 0x5ddb00, /* RegA update for MP version */ - 0xd99000, /* RegB update for MP version */ - 0x3ffbd0, /* RegC update for MP version */ - 0xb00000, /* RegD update for MP version */ - - /* improve phase noise and remove phase calibration,4713 */ - 0xf01a00, - }; - - static const struct zd_ioreq16 ioreqs2[] = { - { CR251, 0x2f }, /* shdnb(PLL_ON)=0 */ - { CR251, 0x7f }, /* shdnb(PLL_ON)=1 */ - }; - - static const u32 rv3[] = { - /* To improve AL2230 yield, 4713 */ - 0xf01b00, - 0xf01e00, - 0xf01a00, - }; - - static const struct zd_ioreq16 ioreqs3[] = { - /* related to 6M band edge patching, happens unconditionally */ - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - }; - - r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, - ARRAY_SIZE(zd1211b_ioreqs_shared_1)); - if (r) - return r; - r = zd_iowrite16a_locked(chip, ioreqs1, ARRAY_SIZE(ioreqs1)); - if (r) - return r; - - if (IS_AL2230S(chip)) { - r = zd_iowrite16a_locked(chip, ioreqs_init_al2230s, - ARRAY_SIZE(ioreqs_init_al2230s)); - if (r) - return r; - } - - r = zd_rfwritev_cr_locked(chip, zd1211b_al2230_table[0], 3); - if (r) - return r; - r = zd_rfwritev_cr_locked(chip, rv1, ARRAY_SIZE(rv1)); - if (r) - return r; - - if (IS_AL2230S(chip)) - r = zd_rfwrite_locked(chip, 0x241000, RF_RV_BITS); - else - r = zd_rfwrite_locked(chip, 0x25a000, RF_RV_BITS); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv2, ARRAY_SIZE(rv2)); - if (r) - return r; - r = zd_iowrite16a_locked(chip, ioreqs2, ARRAY_SIZE(ioreqs2)); - if (r) - return r; - r = zd_rfwritev_cr_locked(chip, rv3, ARRAY_SIZE(rv3)); - if (r) - return r; - r = zd_iowrite16a_locked(chip, ioreqs3, ARRAY_SIZE(ioreqs3)); - if (r) - return r; - return zd1211b_al2230_finalize_rf(chip); -} - -static int zd1211_al2230_set_channel(struct zd_rf *rf, u8 channel) -{ - int r; - const u32 *rv = zd1211_al2230_table[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR138, 0x28 }, - { CR203, 0x06 }, - }; - - r = zd_rfwritev_locked(chip, rv, 3, RF_RV_BITS); - if (r) - return r; - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int zd1211b_al2230_set_channel(struct zd_rf *rf, u8 channel) -{ - int r; - const u32 *rv = zd1211b_al2230_table[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - - r = zd_iowrite16a_locked(chip, zd1211b_ioreqs_shared_1, - ARRAY_SIZE(zd1211b_ioreqs_shared_1)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv, 3); - if (r) - return r; - - return zd1211b_al2230_finalize_rf(chip); -} - -static int zd1211_al2230_switch_radio_on(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x3f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int zd1211b_al2230_switch_radio_on(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x7f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int al2230_switch_radio_off(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x04 }, - { CR251, 0x2f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -int zd_rf_init_al2230(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - - rf->switch_radio_off = al2230_switch_radio_off; - if (zd_chip_is_zd1211b(chip)) { - rf->init_hw = zd1211b_al2230_init_hw; - rf->set_channel = zd1211b_al2230_set_channel; - rf->switch_radio_on = zd1211b_al2230_switch_radio_on; - } else { - rf->init_hw = zd1211_al2230_init_hw; - rf->set_channel = zd1211_al2230_set_channel; - rf->switch_radio_on = zd1211_al2230_switch_radio_on; - } - rf->patch_6m_band_edge = zd_rf_generic_patch_6m; - rf->patch_cck_gain = 1; - return 0; -} diff --git a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c b/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c deleted file mode 100644 index 65095d661e6b..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_rf_al7230b.c +++ /dev/null @@ -1,495 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#include - -#include "zd_rf.h" -#include "zd_usb.h" -#include "zd_chip.h" - -static const u32 chan_rv[][2] = { - RF_CHANNEL( 1) = { 0x09ec00, 0x8cccc8 }, - RF_CHANNEL( 2) = { 0x09ec00, 0x8cccd8 }, - RF_CHANNEL( 3) = { 0x09ec00, 0x8cccc0 }, - RF_CHANNEL( 4) = { 0x09ec00, 0x8cccd0 }, - RF_CHANNEL( 5) = { 0x05ec00, 0x8cccc8 }, - RF_CHANNEL( 6) = { 0x05ec00, 0x8cccd8 }, - RF_CHANNEL( 7) = { 0x05ec00, 0x8cccc0 }, - RF_CHANNEL( 8) = { 0x05ec00, 0x8cccd0 }, - RF_CHANNEL( 9) = { 0x0dec00, 0x8cccc8 }, - RF_CHANNEL(10) = { 0x0dec00, 0x8cccd8 }, - RF_CHANNEL(11) = { 0x0dec00, 0x8cccc0 }, - RF_CHANNEL(12) = { 0x0dec00, 0x8cccd0 }, - RF_CHANNEL(13) = { 0x03ec00, 0x8cccc8 }, - RF_CHANNEL(14) = { 0x03ec00, 0x866660 }, -}; - -static const u32 std_rv[] = { - 0x4ff821, - 0xc5fbfc, - 0x21ebfe, - 0xafd401, /* freq shift 0xaad401 */ - 0x6cf56a, - 0xe04073, - 0x193d76, - 0x9dd844, - 0x500007, - 0xd8c010, -}; - -static const u32 rv_init1[] = { - 0x3c9000, - 0xbfffff, - 0x700000, - 0xf15d58, -}; - -static const u32 rv_init2[] = { - 0xf15d59, - 0xf15d5c, - 0xf15d58, -}; - -static const struct zd_ioreq16 ioreqs_sw[] = { - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR38, 0x38 }, { CR136, 0xdf }, -}; - -static int zd1211b_al7230b_finalize(struct zd_chip *chip) -{ - int r; - static const struct zd_ioreq16 ioreqs[] = { - { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, - { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, - { CR203, 0x04 }, - { }, - { CR240, 0x80 }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - - if (chip->new_phy_layout) { - /* antenna selection? */ - r = zd_iowrite16_locked(chip, 0xe5, CR9); - if (r) - return r; - } - - return zd_iowrite16_locked(chip, 0x04, CR203); -} - -static int zd1211_al7230b_init_hw(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - - /* All of these writes are identical to AL2230 unless otherwise - * specified */ - static const struct zd_ioreq16 ioreqs_1[] = { - /* This one is 7230-specific, and happens before the rest */ - { CR240, 0x57 }, - { }, - - { CR15, 0x20 }, { CR23, 0x40 }, { CR24, 0x20 }, - { CR26, 0x11 }, { CR28, 0x3e }, { CR29, 0x00 }, - { CR44, 0x33 }, - /* This value is different for 7230 (was: 0x2a) */ - { CR106, 0x22 }, - { CR107, 0x1a }, { CR109, 0x09 }, { CR110, 0x27 }, - { CR111, 0x2b }, { CR112, 0x2b }, { CR119, 0x0a }, - /* This happened further down in AL2230, - * and the value changed (was: 0xe0) */ - { CR122, 0xfc }, - { CR10, 0x89 }, - /* for newest (3rd cut) AL2300 */ - { CR17, 0x28 }, - { CR26, 0x93 }, { CR34, 0x30 }, - /* for newest (3rd cut) AL2300 */ - { CR35, 0x3e }, - { CR41, 0x24 }, { CR44, 0x32 }, - /* for newest (3rd cut) AL2300 */ - { CR46, 0x96 }, - { CR47, 0x1e }, { CR79, 0x58 }, { CR80, 0x30 }, - { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, - { CR92, 0x0a }, { CR99, 0x28 }, - /* This value is different for 7230 (was: 0x00) */ - { CR100, 0x02 }, - { CR101, 0x13 }, { CR102, 0x27 }, - /* This value is different for 7230 (was: 0x24) */ - { CR106, 0x22 }, - /* This value is different for 7230 (was: 0x2a) */ - { CR107, 0x3f }, - { CR109, 0x09 }, - /* This value is different for 7230 (was: 0x13) */ - { CR110, 0x1f }, - { CR111, 0x1f }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x27 }, - /* for newest (3rd cut) AL2300 */ - { CR115, 0x24 }, - /* This value is different for 7230 (was: 0x24) */ - { CR116, 0x3f }, - /* This value is different for 7230 (was: 0xf4) */ - { CR117, 0xfa }, - { CR118, 0xfc }, { CR119, 0x10 }, { CR120, 0x4f }, - { CR121, 0x77 }, { CR137, 0x88 }, - /* This one is 7230-specific */ - { CR138, 0xa8 }, - /* This value is different for 7230 (was: 0xff) */ - { CR252, 0x34 }, - /* This value is different for 7230 (was: 0xff) */ - { CR253, 0x34 }, - - /* PLL_OFF */ - { CR251, 0x2f }, - }; - - static const struct zd_ioreq16 ioreqs_2[] = { - { CR251, 0x3f }, /* PLL_ON */ - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR38, 0x38 }, { CR136, 0xdf }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, chan_rv[0], ARRAY_SIZE(chan_rv[0])); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv_init1, ARRAY_SIZE(rv_init1)); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv_init2, ARRAY_SIZE(rv_init2)); - if (r) - return r; - - r = zd_iowrite16_locked(chip, 0x06, CR203); - if (r) - return r; - r = zd_iowrite16_locked(chip, 0x80, CR240); - if (r) - return r; - - return 0; -} - -static int zd1211b_al7230b_init_hw(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs_1[] = { - { CR240, 0x57 }, { CR9, 0x9 }, - { }, - { CR10, 0x8b }, { CR15, 0x20 }, - { CR17, 0x2B }, /* for newest (3rd cut) AL2230 */ - { CR20, 0x10 }, /* 4N25->Stone Request */ - { CR23, 0x40 }, { CR24, 0x20 }, { CR26, 0x93 }, - { CR28, 0x3e }, { CR29, 0x00 }, - { CR33, 0x28 }, /* 5613 */ - { CR34, 0x30 }, - { CR35, 0x3e }, /* for newest (3rd cut) AL2230 */ - { CR41, 0x24 }, { CR44, 0x32 }, - { CR46, 0x99 }, /* for newest (3rd cut) AL2230 */ - { CR47, 0x1e }, - - /* ZD1215 5610 */ - { CR48, 0x00 }, { CR49, 0x00 }, { CR51, 0x01 }, - { CR52, 0x80 }, { CR53, 0x7e }, { CR65, 0x00 }, - { CR66, 0x00 }, { CR67, 0x00 }, { CR68, 0x00 }, - { CR69, 0x28 }, - - { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, - { CR87, 0x0A }, { CR89, 0x04 }, - { CR90, 0x58 }, /* 5112 */ - { CR91, 0x00 }, /* 5613 */ - { CR92, 0x0a }, - { CR98, 0x8d }, /* 4804, for 1212 new algorithm */ - { CR99, 0x00 }, { CR100, 0x02 }, { CR101, 0x13 }, - { CR102, 0x27 }, - { CR106, 0x20 }, /* change to 0x24 for AL7230B */ - { CR109, 0x13 }, /* 4804, for 1212 new algorithm */ - { CR112, 0x1f }, - }; - - static const struct zd_ioreq16 ioreqs_new_phy[] = { - { CR107, 0x28 }, - { CR110, 0x1f }, /* 5127, 0x13->0x1f */ - { CR111, 0x1f }, /* 0x13 to 0x1f for AL7230B */ - { CR116, 0x2a }, { CR118, 0xfa }, { CR119, 0x12 }, - { CR121, 0x6c }, /* 5613 */ - }; - - static const struct zd_ioreq16 ioreqs_old_phy[] = { - { CR107, 0x24 }, - { CR110, 0x13 }, /* 5127, 0x13->0x1f */ - { CR111, 0x13 }, /* 0x13 to 0x1f for AL7230B */ - { CR116, 0x24 }, { CR118, 0xfc }, { CR119, 0x11 }, - { CR121, 0x6a }, /* 5613 */ - }; - - static const struct zd_ioreq16 ioreqs_2[] = { - { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x24 }, - { CR117, 0xfa }, { CR120, 0x4f }, - { CR122, 0xfc }, /* E0->FCh at 4901 */ - { CR123, 0x57 }, /* 5613 */ - { CR125, 0xad }, /* 4804, for 1212 new algorithm */ - { CR126, 0x6c }, /* 5613 */ - { CR127, 0x03 }, /* 4804, for 1212 new algorithm */ - { CR130, 0x10 }, - { CR131, 0x00 }, /* 5112 */ - { CR137, 0x50 }, /* 5613 */ - { CR138, 0xa8 }, /* 5112 */ - { CR144, 0xac }, /* 5613 */ - { CR148, 0x40 }, /* 5112 */ - { CR149, 0x40 }, /* 4O07, 50->40 */ - { CR150, 0x1a }, /* 5112, 0C->1A */ - { CR252, 0x34 }, { CR253, 0x34 }, - { CR251, 0x2f }, /* PLL_OFF */ - }; - - static const struct zd_ioreq16 ioreqs_3[] = { - { CR251, 0x7f }, /* PLL_ON */ - { CR128, 0x14 }, { CR129, 0x12 }, { CR130, 0x10 }, - { CR38, 0x38 }, { CR136, 0xdf }, - }; - - r = zd_iowrite16a_locked(chip, ioreqs_1, ARRAY_SIZE(ioreqs_1)); - if (r) - return r; - - if (chip->new_phy_layout) - r = zd_iowrite16a_locked(chip, ioreqs_new_phy, - ARRAY_SIZE(ioreqs_new_phy)); - else - r = zd_iowrite16a_locked(chip, ioreqs_old_phy, - ARRAY_SIZE(ioreqs_old_phy)); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs_2, ARRAY_SIZE(ioreqs_2)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, chan_rv[0], ARRAY_SIZE(chan_rv[0])); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv_init1, ARRAY_SIZE(rv_init1)); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs_3, ARRAY_SIZE(ioreqs_3)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv_init2, ARRAY_SIZE(rv_init2)); - if (r) - return r; - - return zd1211b_al7230b_finalize(chip); -} - -static int zd1211_al7230b_set_channel(struct zd_rf *rf, u8 channel) -{ - int r; - const u32 *rv = chan_rv[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { - /* PLL_ON */ - { CR251, 0x3f }, - { CR203, 0x06 }, { CR240, 0x08 }, - }; - - r = zd_iowrite16_locked(chip, 0x57, CR240); - if (r) - return r; - - /* PLL_OFF */ - r = zd_iowrite16_locked(chip, 0x2f, CR251); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); - if (r) - return r; - - r = zd_rfwrite_cr_locked(chip, 0x3c9000); - if (r) - return r; - r = zd_rfwrite_cr_locked(chip, 0xf15d58); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs_sw, ARRAY_SIZE(ioreqs_sw)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv, 2); - if (r) - return r; - - r = zd_rfwrite_cr_locked(chip, 0x3c9000); - if (r) - return r; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int zd1211b_al7230b_set_channel(struct zd_rf *rf, u8 channel) -{ - int r; - const u32 *rv = chan_rv[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - - r = zd_iowrite16_locked(chip, 0x57, CR240); - if (r) - return r; - r = zd_iowrite16_locked(chip, 0xe4, CR9); - if (r) - return r; - - /* PLL_OFF */ - r = zd_iowrite16_locked(chip, 0x2f, CR251); - if (r) - return r; - r = zd_rfwritev_cr_locked(chip, std_rv, ARRAY_SIZE(std_rv)); - if (r) - return r; - - r = zd_rfwrite_cr_locked(chip, 0x3c9000); - if (r) - return r; - r = zd_rfwrite_cr_locked(chip, 0xf15d58); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs_sw, ARRAY_SIZE(ioreqs_sw)); - if (r) - return r; - - r = zd_rfwritev_cr_locked(chip, rv, 2); - if (r) - return r; - - r = zd_rfwrite_cr_locked(chip, 0x3c9000); - if (r) - return r; - - r = zd_iowrite16_locked(chip, 0x7f, CR251); - if (r) - return r; - - return zd1211b_al7230b_finalize(chip); -} - -static int zd1211_al7230b_switch_radio_on(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x3f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int zd1211b_al7230b_switch_radio_on(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, - { CR251, 0x7f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int al7230b_switch_radio_off(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x04 }, - { CR251, 0x2f }, - }; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -/* ZD1211B+AL7230B 6m band edge patching differs slightly from other - * configurations */ -static int zd1211b_al7230b_patch_6m(struct zd_rf *rf, u8 channel) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - struct zd_ioreq16 ioreqs[] = { - { CR128, 0x14 }, { CR129, 0x12 }, - }; - - /* FIXME: Channel 11 is not the edge for all regulatory domains. */ - if (channel == 1) { - ioreqs[0].value = 0x0e; - ioreqs[1].value = 0x10; - } else if (channel == 11) { - ioreqs[0].value = 0x10; - ioreqs[1].value = 0x10; - } - - dev_dbg_f(zd_chip_dev(chip), "patching for channel %d\n", channel); - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -int zd_rf_init_al7230b(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - - if (zd_chip_is_zd1211b(chip)) { - rf->init_hw = zd1211b_al7230b_init_hw; - rf->switch_radio_on = zd1211b_al7230b_switch_radio_on; - rf->set_channel = zd1211b_al7230b_set_channel; - rf->patch_6m_band_edge = zd1211b_al7230b_patch_6m; - } else { - rf->init_hw = zd1211_al7230b_init_hw; - rf->switch_radio_on = zd1211_al7230b_switch_radio_on; - rf->set_channel = zd1211_al7230b_set_channel; - rf->patch_6m_band_edge = zd_rf_generic_patch_6m; - rf->patch_cck_gain = 1; - } - - rf->switch_radio_off = al7230b_switch_radio_off; - - return 0; -} diff --git a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c b/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c deleted file mode 100644 index 0597d862fbd2..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c +++ /dev/null @@ -1,282 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#include - -#include "zd_rf.h" -#include "zd_usb.h" -#include "zd_chip.h" - -static const u32 rf2959_table[][2] = { - RF_CHANNEL( 1) = { 0x181979, 0x1e6666 }, - RF_CHANNEL( 2) = { 0x181989, 0x1e6666 }, - RF_CHANNEL( 3) = { 0x181999, 0x1e6666 }, - RF_CHANNEL( 4) = { 0x1819a9, 0x1e6666 }, - RF_CHANNEL( 5) = { 0x1819b9, 0x1e6666 }, - RF_CHANNEL( 6) = { 0x1819c9, 0x1e6666 }, - RF_CHANNEL( 7) = { 0x1819d9, 0x1e6666 }, - RF_CHANNEL( 8) = { 0x1819e9, 0x1e6666 }, - RF_CHANNEL( 9) = { 0x1819f9, 0x1e6666 }, - RF_CHANNEL(10) = { 0x181a09, 0x1e6666 }, - RF_CHANNEL(11) = { 0x181a19, 0x1e6666 }, - RF_CHANNEL(12) = { 0x181a29, 0x1e6666 }, - RF_CHANNEL(13) = { 0x181a39, 0x1e6666 }, - RF_CHANNEL(14) = { 0x181a60, 0x1c0000 }, -}; - -#if 0 -static int bits(u32 rw, int from, int to) -{ - rw &= ~(0xffffffffU << (to+1)); - rw >>= from; - return rw; -} - -static int bit(u32 rw, int bit) -{ - return bits(rw, bit, bit); -} - -static void dump_regwrite(u32 rw) -{ - int reg = bits(rw, 18, 22); - int rw_flag = bits(rw, 23, 23); - PDEBUG("rf2959 %#010x reg %d rw %d", rw, reg, rw_flag); - - switch (reg) { - case 0: - PDEBUG("reg0 CFG1 ref_sel %d hybernate %d rf_vco_reg_en %d" - " if_vco_reg_en %d if_vga_en %d", - bits(rw, 14, 15), bit(rw, 3), bit(rw, 2), bit(rw, 1), - bit(rw, 0)); - break; - case 1: - PDEBUG("reg1 IFPLL1 pll_en1 %d kv_en1 %d vtc_en1 %d lpf1 %d" - " cpl1 %d pdp1 %d autocal_en1 %d ld_en1 %d ifloopr %d" - " ifloopc %d dac1 %d", - bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), - bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), - bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0, 3)); - break; - case 2: - PDEBUG("reg2 IFPLL2 n1 %d num1 %d", - bits(rw, 6, 17), bits(rw, 0, 5)); - break; - case 3: - PDEBUG("reg3 IFPLL3 num %d", bits(rw, 0, 17)); - break; - case 4: - PDEBUG("reg4 IFPLL4 dn1 %#04x ct_def1 %d kv_def1 %d", - bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); - break; - case 5: - PDEBUG("reg5 RFPLL1 pll_en %d kv_en %d vtc_en %d lpf %d cpl %d" - " pdp %d autocal_en %d ld_en %d rfloopr %d rfloopc %d" - " dac %d", - bit(rw, 17), bit(rw, 16), bit(rw, 15), bit(rw, 14), - bit(rw, 13), bit(rw, 12), bit(rw, 11), bit(rw, 10), - bits(rw, 7, 9), bits(rw, 4, 6), bits(rw, 0,3)); - break; - case 6: - PDEBUG("reg6 RFPLL2 n %d num %d", - bits(rw, 6, 17), bits(rw, 0, 5)); - break; - case 7: - PDEBUG("reg7 RFPLL3 num2 %d", bits(rw, 0, 17)); - break; - case 8: - PDEBUG("reg8 RFPLL4 dn %#06x ct_def %d kv_def %d", - bits(rw, 8, 16), bits(rw, 4, 7), bits(rw, 0, 3)); - break; - case 9: - PDEBUG("reg9 CAL1 tvco %d tlock %d m_ct_value %d ld_window %d", - bits(rw, 13, 17), bits(rw, 8, 12), bits(rw, 3, 7), - bits(rw, 0, 2)); - break; - case 10: - PDEBUG("reg10 TXRX1 rxdcfbbyps %d pcontrol %d txvgc %d" - " rxlpfbw %d txlpfbw %d txdiffmode %d txenmode %d" - " intbiasen %d tybypass %d", - bit(rw, 17), bits(rw, 15, 16), bits(rw, 10, 14), - bits(rw, 7, 9), bits(rw, 4, 6), bit(rw, 3), bit(rw, 2), - bit(rw, 1), bit(rw, 0)); - break; - case 11: - PDEBUG("reg11 PCNT1 mid_bias %d p_desired %d pc_offset %d" - " tx_delay %d", - bits(rw, 15, 17), bits(rw, 9, 14), bits(rw, 3, 8), - bits(rw, 0, 2)); - break; - case 12: - PDEBUG("reg12 PCNT2 max_power %d mid_power %d min_power %d", - bits(rw, 12, 17), bits(rw, 6, 11), bits(rw, 0, 5)); - break; - case 13: - PDEBUG("reg13 VCOT1 rfpll vco comp %d ifpll vco comp %d" - " lobias %d if_biasbuf %d if_biasvco %d rf_biasbuf %d" - " rf_biasvco %d", - bit(rw, 17), bit(rw, 16), bit(rw, 15), - bits(rw, 8, 9), bits(rw, 5, 7), bits(rw, 3, 4), - bits(rw, 0, 2)); - break; - case 14: - PDEBUG("reg14 IQCAL rx_acal %d rx_pcal %d" - " tx_acal %d tx_pcal %d", - bits(rw, 13, 17), bits(rw, 9, 12), bits(rw, 4, 8), - bits(rw, 0, 3)); - break; - } -} -#endif /* 0 */ - -static int rf2959_init_hw(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { - { CR2, 0x1E }, { CR9, 0x20 }, { CR10, 0x89 }, - { CR11, 0x00 }, { CR15, 0xD0 }, { CR17, 0x68 }, - { CR19, 0x4a }, { CR20, 0x0c }, { CR21, 0x0E }, - { CR23, 0x48 }, - /* normal size for cca threshold */ - { CR24, 0x14 }, - /* { CR24, 0x20 }, */ - { CR26, 0x90 }, { CR27, 0x30 }, { CR29, 0x20 }, - { CR31, 0xb2 }, { CR32, 0x43 }, { CR33, 0x28 }, - { CR38, 0x30 }, { CR34, 0x0f }, { CR35, 0xF0 }, - { CR41, 0x2a }, { CR46, 0x7F }, { CR47, 0x1E }, - { CR51, 0xc5 }, { CR52, 0xc5 }, { CR53, 0xc5 }, - { CR79, 0x58 }, { CR80, 0x30 }, { CR81, 0x30 }, - { CR82, 0x00 }, { CR83, 0x24 }, { CR84, 0x04 }, - { CR85, 0x00 }, { CR86, 0x10 }, { CR87, 0x2A }, - { CR88, 0x10 }, { CR89, 0x24 }, { CR90, 0x18 }, - /* { CR91, 0x18 }, */ - /* should solve continous CTS frame problems */ - { CR91, 0x00 }, - { CR92, 0x0a }, { CR93, 0x00 }, { CR94, 0x01 }, - { CR95, 0x00 }, { CR96, 0x40 }, { CR97, 0x37 }, - { CR98, 0x05 }, { CR99, 0x28 }, { CR100, 0x00 }, - { CR101, 0x13 }, { CR102, 0x27 }, { CR103, 0x27 }, - { CR104, 0x18 }, { CR105, 0x12 }, - /* normal size */ - { CR106, 0x1a }, - /* { CR106, 0x22 }, */ - { CR107, 0x24 }, { CR108, 0x0a }, { CR109, 0x13 }, - { CR110, 0x2F }, { CR111, 0x27 }, { CR112, 0x27 }, - { CR113, 0x27 }, { CR114, 0x27 }, { CR115, 0x40 }, - { CR116, 0x40 }, { CR117, 0xF0 }, { CR118, 0xF0 }, - { CR119, 0x16 }, - /* no TX continuation */ - { CR122, 0x00 }, - /* { CR122, 0xff }, */ - { CR127, 0x03 }, { CR131, 0x08 }, { CR138, 0x28 }, - { CR148, 0x44 }, { CR150, 0x10 }, { CR169, 0xBB }, - { CR170, 0xBB }, - }; - - static const u32 rv[] = { - 0x000007, /* REG0(CFG1) */ - 0x07dd43, /* REG1(IFPLL1) */ - 0x080959, /* REG2(IFPLL2) */ - 0x0e6666, - 0x116a57, /* REG4 */ - 0x17dd43, /* REG5 */ - 0x1819f9, /* REG6 */ - 0x1e6666, - 0x214554, - 0x25e7fa, - 0x27fffa, - /* The Zydas driver somehow forgets to set this value. It's - * only set for Japan. We are using internal power control - * for now. - */ - 0x294128, /* internal power */ - /* 0x28252c, */ /* External control TX power */ - /* CR31_CCK, CR51_6-36M, CR52_48M, CR53_54M */ - 0x2c0000, - 0x300000, - 0x340000, /* REG13(0xD) */ - 0x381e0f, /* REG14(0xE) */ - /* Bogus, RF2959's data sheet doesn't know register 27, which is - * actually referenced here. The commented 0x11 is 17. - */ - 0x6c180f, /* REG27(0x11) */ - }; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - - return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); -} - -static int rf2959_set_channel(struct zd_rf *rf, u8 channel) -{ - int i, r; - const u32 *rv = rf2959_table[channel-1]; - struct zd_chip *chip = zd_rf_to_chip(rf); - - for (i = 0; i < 2; i++) { - r = zd_rfwrite_locked(chip, rv[i], RF_RV_BITS); - if (r) - return r; - } - return 0; -} - -static int rf2959_switch_radio_on(struct zd_rf *rf) -{ - static const struct zd_ioreq16 ioreqs[] = { - { CR10, 0x89 }, - { CR11, 0x00 }, - }; - struct zd_chip *chip = zd_rf_to_chip(rf); - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int rf2959_switch_radio_off(struct zd_rf *rf) -{ - static const struct zd_ioreq16 ioreqs[] = { - { CR10, 0x15 }, - { CR11, 0x81 }, - }; - struct zd_chip *chip = zd_rf_to_chip(rf); - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -int zd_rf_init_rf2959(struct zd_rf *rf) -{ - struct zd_chip *chip = zd_rf_to_chip(rf); - - if (zd_chip_is_zd1211b(chip)) { - dev_err(zd_chip_dev(chip), - "RF2959 is currently not supported for ZD1211B" - " devices\n"); - return -ENODEV; - } - rf->init_hw = rf2959_init_hw; - rf->set_channel = rf2959_set_channel; - rf->switch_radio_on = rf2959_switch_radio_on; - rf->switch_radio_off = rf2959_switch_radio_off; - return 0; -} diff --git a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c b/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c deleted file mode 100644 index 439799b84876..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c +++ /dev/null @@ -1,537 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#include - -#include "zd_rf.h" -#include "zd_usb.h" -#include "zd_chip.h" - -/* This RF programming code is based upon the code found in v2.16.0.0 of the - * ZyDAS vendor driver. Unlike other RF's, Ubec publish full technical specs - * for this RF on their website, so we're able to understand more than - * usual as to what is going on. Thumbs up for Ubec for doing that. */ - -/* The 3-wire serial interface provides access to 8 write-only registers. - * The data format is a 4 bit register address followed by a 20 bit value. */ -#define UW2453_REGWRITE(reg, val) ((((reg) & 0xf) << 20) | ((val) & 0xfffff)) - -/* For channel tuning, we have to configure registers 1 (synthesizer), 2 (synth - * fractional divide ratio) and 3 (VCO config). - * - * We configure the RF to produce an interrupt when the PLL is locked onto - * the configured frequency. During initialization, we run through a variety - * of different VCO configurations on channel 1 until we detect a PLL lock. - * When this happens, we remember which VCO configuration produced the lock - * and use it later. Actually, we use the configuration *after* the one that - * produced the lock, which seems odd, but it works. - * - * If we do not see a PLL lock on any standard VCO config, we fall back on an - * autocal configuration, which has a fixed (as opposed to per-channel) VCO - * config and different synth values from the standard set (divide ratio - * is still shared with the standard set). */ - -/* The per-channel synth values for all standard VCO configurations. These get - * written to register 1. */ -static const u8 uw2453_std_synth[] = { - RF_CHANNEL( 1) = 0x47, - RF_CHANNEL( 2) = 0x47, - RF_CHANNEL( 3) = 0x67, - RF_CHANNEL( 4) = 0x67, - RF_CHANNEL( 5) = 0x67, - RF_CHANNEL( 6) = 0x67, - RF_CHANNEL( 7) = 0x57, - RF_CHANNEL( 8) = 0x57, - RF_CHANNEL( 9) = 0x57, - RF_CHANNEL(10) = 0x57, - RF_CHANNEL(11) = 0x77, - RF_CHANNEL(12) = 0x77, - RF_CHANNEL(13) = 0x77, - RF_CHANNEL(14) = 0x4f, -}; - -/* This table stores the synthesizer fractional divide ratio for *all* VCO - * configurations (both standard and autocal). These get written to register 2. - */ -static const u16 uw2453_synth_divide[] = { - RF_CHANNEL( 1) = 0x999, - RF_CHANNEL( 2) = 0x99b, - RF_CHANNEL( 3) = 0x998, - RF_CHANNEL( 4) = 0x99a, - RF_CHANNEL( 5) = 0x999, - RF_CHANNEL( 6) = 0x99b, - RF_CHANNEL( 7) = 0x998, - RF_CHANNEL( 8) = 0x99a, - RF_CHANNEL( 9) = 0x999, - RF_CHANNEL(10) = 0x99b, - RF_CHANNEL(11) = 0x998, - RF_CHANNEL(12) = 0x99a, - RF_CHANNEL(13) = 0x999, - RF_CHANNEL(14) = 0xccc, -}; - -/* Here is the data for all the standard VCO configurations. We shrink our - * table a little by observing that both channels in a consecutive pair share - * the same value. We also observe that the high 4 bits ([0:3] in the specs) - * are all 'Reserved' and are always set to 0x4 - we chop them off in the data - * below. */ -#define CHAN_TO_PAIRIDX(a) ((a - 1) / 2) -#define RF_CHANPAIR(a,b) [CHAN_TO_PAIRIDX(a)] -static const u16 uw2453_std_vco_cfg[][7] = { - { /* table 1 */ - RF_CHANPAIR( 1, 2) = 0x664d, - RF_CHANPAIR( 3, 4) = 0x604d, - RF_CHANPAIR( 5, 6) = 0x6675, - RF_CHANPAIR( 7, 8) = 0x6475, - RF_CHANPAIR( 9, 10) = 0x6655, - RF_CHANPAIR(11, 12) = 0x6455, - RF_CHANPAIR(13, 14) = 0x6665, - }, - { /* table 2 */ - RF_CHANPAIR( 1, 2) = 0x666d, - RF_CHANPAIR( 3, 4) = 0x606d, - RF_CHANPAIR( 5, 6) = 0x664d, - RF_CHANPAIR( 7, 8) = 0x644d, - RF_CHANPAIR( 9, 10) = 0x6675, - RF_CHANPAIR(11, 12) = 0x6475, - RF_CHANPAIR(13, 14) = 0x6655, - }, - { /* table 3 */ - RF_CHANPAIR( 1, 2) = 0x665d, - RF_CHANPAIR( 3, 4) = 0x605d, - RF_CHANPAIR( 5, 6) = 0x666d, - RF_CHANPAIR( 7, 8) = 0x646d, - RF_CHANPAIR( 9, 10) = 0x664d, - RF_CHANPAIR(11, 12) = 0x644d, - RF_CHANPAIR(13, 14) = 0x6675, - }, - { /* table 4 */ - RF_CHANPAIR( 1, 2) = 0x667d, - RF_CHANPAIR( 3, 4) = 0x607d, - RF_CHANPAIR( 5, 6) = 0x665d, - RF_CHANPAIR( 7, 8) = 0x645d, - RF_CHANPAIR( 9, 10) = 0x666d, - RF_CHANPAIR(11, 12) = 0x646d, - RF_CHANPAIR(13, 14) = 0x664d, - }, - { /* table 5 */ - RF_CHANPAIR( 1, 2) = 0x6643, - RF_CHANPAIR( 3, 4) = 0x6043, - RF_CHANPAIR( 5, 6) = 0x667d, - RF_CHANPAIR( 7, 8) = 0x647d, - RF_CHANPAIR( 9, 10) = 0x665d, - RF_CHANPAIR(11, 12) = 0x645d, - RF_CHANPAIR(13, 14) = 0x666d, - }, - { /* table 6 */ - RF_CHANPAIR( 1, 2) = 0x6663, - RF_CHANPAIR( 3, 4) = 0x6063, - RF_CHANPAIR( 5, 6) = 0x6643, - RF_CHANPAIR( 7, 8) = 0x6443, - RF_CHANPAIR( 9, 10) = 0x667d, - RF_CHANPAIR(11, 12) = 0x647d, - RF_CHANPAIR(13, 14) = 0x665d, - }, - { /* table 7 */ - RF_CHANPAIR( 1, 2) = 0x6653, - RF_CHANPAIR( 3, 4) = 0x6053, - RF_CHANPAIR( 5, 6) = 0x6663, - RF_CHANPAIR( 7, 8) = 0x6463, - RF_CHANPAIR( 9, 10) = 0x6643, - RF_CHANPAIR(11, 12) = 0x6443, - RF_CHANPAIR(13, 14) = 0x667d, - }, - { /* table 8 */ - RF_CHANPAIR( 1, 2) = 0x6673, - RF_CHANPAIR( 3, 4) = 0x6073, - RF_CHANPAIR( 5, 6) = 0x6653, - RF_CHANPAIR( 7, 8) = 0x6453, - RF_CHANPAIR( 9, 10) = 0x6663, - RF_CHANPAIR(11, 12) = 0x6463, - RF_CHANPAIR(13, 14) = 0x6643, - }, - { /* table 9 */ - RF_CHANPAIR( 1, 2) = 0x664b, - RF_CHANPAIR( 3, 4) = 0x604b, - RF_CHANPAIR( 5, 6) = 0x6673, - RF_CHANPAIR( 7, 8) = 0x6473, - RF_CHANPAIR( 9, 10) = 0x6653, - RF_CHANPAIR(11, 12) = 0x6453, - RF_CHANPAIR(13, 14) = 0x6663, - }, - { /* table 10 */ - RF_CHANPAIR( 1, 2) = 0x666b, - RF_CHANPAIR( 3, 4) = 0x606b, - RF_CHANPAIR( 5, 6) = 0x664b, - RF_CHANPAIR( 7, 8) = 0x644b, - RF_CHANPAIR( 9, 10) = 0x6673, - RF_CHANPAIR(11, 12) = 0x6473, - RF_CHANPAIR(13, 14) = 0x6653, - }, - { /* table 11 */ - RF_CHANPAIR( 1, 2) = 0x665b, - RF_CHANPAIR( 3, 4) = 0x605b, - RF_CHANPAIR( 5, 6) = 0x666b, - RF_CHANPAIR( 7, 8) = 0x646b, - RF_CHANPAIR( 9, 10) = 0x664b, - RF_CHANPAIR(11, 12) = 0x644b, - RF_CHANPAIR(13, 14) = 0x6673, - }, - -}; - -/* The per-channel synth values for autocal. These get written to register 1. */ -static const u16 uw2453_autocal_synth[] = { - RF_CHANNEL( 1) = 0x6847, - RF_CHANNEL( 2) = 0x6847, - RF_CHANNEL( 3) = 0x6867, - RF_CHANNEL( 4) = 0x6867, - RF_CHANNEL( 5) = 0x6867, - RF_CHANNEL( 6) = 0x6867, - RF_CHANNEL( 7) = 0x6857, - RF_CHANNEL( 8) = 0x6857, - RF_CHANNEL( 9) = 0x6857, - RF_CHANNEL(10) = 0x6857, - RF_CHANNEL(11) = 0x6877, - RF_CHANNEL(12) = 0x6877, - RF_CHANNEL(13) = 0x6877, - RF_CHANNEL(14) = 0x684f, -}; - -/* The VCO configuration for autocal (all channels) */ -static const u16 UW2453_AUTOCAL_VCO_CFG = 0x6662; - -/* TX gain settings. The array index corresponds to the TX power integration - * values found in the EEPROM. The values get written to register 7. */ -static u32 uw2453_txgain[] = { - [0x00] = 0x0e313, - [0x01] = 0x0fb13, - [0x02] = 0x0e093, - [0x03] = 0x0f893, - [0x04] = 0x0ea93, - [0x05] = 0x1f093, - [0x06] = 0x1f493, - [0x07] = 0x1f693, - [0x08] = 0x1f393, - [0x09] = 0x1f35b, - [0x0a] = 0x1e6db, - [0x0b] = 0x1ff3f, - [0x0c] = 0x1ffff, - [0x0d] = 0x361d7, - [0x0e] = 0x37fbf, - [0x0f] = 0x3ff8b, - [0x10] = 0x3ff33, - [0x11] = 0x3fb3f, - [0x12] = 0x3ffff, -}; - -/* RF-specific structure */ -struct uw2453_priv { - /* index into synth/VCO config tables where PLL lock was found - * -1 means autocal */ - int config; -}; - -#define UW2453_PRIV(rf) ((struct uw2453_priv *) (rf)->priv) - -static int uw2453_synth_set_channel(struct zd_chip *chip, int channel, - bool autocal) -{ - int r; - int idx = channel - 1; - u32 val; - - if (autocal) - val = UW2453_REGWRITE(1, uw2453_autocal_synth[idx]); - else - val = UW2453_REGWRITE(1, uw2453_std_synth[idx]); - - r = zd_rfwrite_locked(chip, val, RF_RV_BITS); - if (r) - return r; - - return zd_rfwrite_locked(chip, - UW2453_REGWRITE(2, uw2453_synth_divide[idx]), RF_RV_BITS); -} - -static int uw2453_write_vco_cfg(struct zd_chip *chip, u16 value) -{ - /* vendor driver always sets these upper bits even though the specs say - * they are reserved */ - u32 val = 0x40000 | value; - return zd_rfwrite_locked(chip, UW2453_REGWRITE(3, val), RF_RV_BITS); -} - -static int uw2453_init_mode(struct zd_chip *chip) -{ - static const u32 rv[] = { - UW2453_REGWRITE(0, 0x25f98), /* enter IDLE mode */ - UW2453_REGWRITE(0, 0x25f9a), /* enter CAL_VCO mode */ - UW2453_REGWRITE(0, 0x25f94), /* enter RX/TX mode */ - UW2453_REGWRITE(0, 0x27fd4), /* power down RSSI circuit */ - }; - - return zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); -} - -static int uw2453_set_tx_gain_level(struct zd_chip *chip, int channel) -{ - u8 int_value = chip->pwr_int_values[channel - 1]; - - if (int_value >= ARRAY_SIZE(uw2453_txgain)) { - dev_dbg_f(zd_chip_dev(chip), "can't configure TX gain for " - "int value %x on channel %d\n", int_value, channel); - return 0; - } - - return zd_rfwrite_locked(chip, - UW2453_REGWRITE(7, uw2453_txgain[int_value]), RF_RV_BITS); -} - -static int uw2453_init_hw(struct zd_rf *rf) -{ - int i, r; - int found_config = -1; - u16 intr_status; - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { - { CR10, 0x89 }, { CR15, 0x20 }, - { CR17, 0x28 }, /* 6112 no change */ - { CR23, 0x38 }, { CR24, 0x20 }, { CR26, 0x93 }, - { CR27, 0x15 }, { CR28, 0x3e }, { CR29, 0x00 }, - { CR33, 0x28 }, { CR34, 0x30 }, - { CR35, 0x43 }, /* 6112 3e->43 */ - { CR41, 0x24 }, { CR44, 0x32 }, - { CR46, 0x92 }, /* 6112 96->92 */ - { CR47, 0x1e }, - { CR48, 0x04 }, /* 5602 Roger */ - { CR49, 0xfa }, { CR79, 0x58 }, { CR80, 0x30 }, - { CR81, 0x30 }, { CR87, 0x0a }, { CR89, 0x04 }, - { CR91, 0x00 }, { CR92, 0x0a }, { CR98, 0x8d }, - { CR99, 0x28 }, { CR100, 0x02 }, - { CR101, 0x09 }, /* 6112 13->1f 6220 1f->13 6407 13->9 */ - { CR102, 0x27 }, - { CR106, 0x1c }, /* 5d07 5112 1f->1c 6220 1c->1f 6221 1f->1c */ - { CR107, 0x1c }, /* 6220 1c->1a 5221 1a->1c */ - { CR109, 0x13 }, - { CR110, 0x1f }, /* 6112 13->1f 6221 1f->13 6407 13->0x09 */ - { CR111, 0x13 }, { CR112, 0x1f }, { CR113, 0x27 }, - { CR114, 0x23 }, /* 6221 27->23 */ - { CR115, 0x24 }, /* 6112 24->1c 6220 1c->24 */ - { CR116, 0x24 }, /* 6220 1c->24 */ - { CR117, 0xfa }, /* 6112 fa->f8 6220 f8->f4 6220 f4->fa */ - { CR118, 0xf0 }, /* 5d07 6112 f0->f2 6220 f2->f0 */ - { CR119, 0x1a }, /* 6112 1a->10 6220 10->14 6220 14->1a */ - { CR120, 0x4f }, - { CR121, 0x1f }, /* 6220 4f->1f */ - { CR122, 0xf0 }, { CR123, 0x57 }, { CR125, 0xad }, - { CR126, 0x6c }, { CR127, 0x03 }, - { CR128, 0x14 }, /* 6302 12->11 */ - { CR129, 0x12 }, /* 6301 10->0f */ - { CR130, 0x10 }, { CR137, 0x50 }, { CR138, 0xa8 }, - { CR144, 0xac }, { CR146, 0x20 }, { CR252, 0xff }, - { CR253, 0xff }, - }; - - static const u32 rv[] = { - UW2453_REGWRITE(4, 0x2b), /* configure reciever gain */ - UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */ - UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */ - UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */ - - /* enter CAL_FIL mode, TX gain set by registers, RX gain set by pins, - * RSSI circuit powered down, reduced RSSI range */ - UW2453_REGWRITE(0, 0x25f9c), /* 5d01 cal_fil */ - - /* synthesizer configuration for channel 1 */ - UW2453_REGWRITE(1, 0x47), - UW2453_REGWRITE(2, 0x999), - - /* disable manual VCO band selection */ - UW2453_REGWRITE(3, 0x7602), - - /* enable manual VCO band selection, configure current level */ - UW2453_REGWRITE(3, 0x46063), - }; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - - r = zd_rfwritev_locked(chip, rv, ARRAY_SIZE(rv), RF_RV_BITS); - if (r) - return r; - - r = uw2453_init_mode(chip); - if (r) - return r; - - /* Try all standard VCO configuration settings on channel 1 */ - for (i = 0; i < ARRAY_SIZE(uw2453_std_vco_cfg) - 1; i++) { - /* Configure synthesizer for channel 1 */ - r = uw2453_synth_set_channel(chip, 1, false); - if (r) - return r; - - /* Write VCO config */ - r = uw2453_write_vco_cfg(chip, uw2453_std_vco_cfg[i][0]); - if (r) - return r; - - /* ack interrupt event */ - r = zd_iowrite16_locked(chip, 0x0f, UW2453_INTR_REG); - if (r) - return r; - - /* check interrupt status */ - r = zd_ioread16_locked(chip, &intr_status, UW2453_INTR_REG); - if (r) - return r; - - if (!(intr_status & 0xf)) { - dev_dbg_f(zd_chip_dev(chip), - "PLL locked on configuration %d\n", i); - found_config = i; - break; - } - } - - if (found_config == -1) { - /* autocal */ - dev_dbg_f(zd_chip_dev(chip), - "PLL did not lock, using autocal\n"); - - r = uw2453_synth_set_channel(chip, 1, true); - if (r) - return r; - - r = uw2453_write_vco_cfg(chip, UW2453_AUTOCAL_VCO_CFG); - if (r) - return r; - } - - /* To match the vendor driver behaviour, we use the configuration after - * the one that produced a lock. */ - UW2453_PRIV(rf)->config = found_config + 1; - - return zd_iowrite16_locked(chip, 0x06, CR203); -} - -static int uw2453_set_channel(struct zd_rf *rf, u8 channel) -{ - int r; - u16 vco_cfg; - int config = UW2453_PRIV(rf)->config; - bool autocal = (config == -1); - struct zd_chip *chip = zd_rf_to_chip(rf); - - static const struct zd_ioreq16 ioreqs[] = { - { CR80, 0x30 }, { CR81, 0x30 }, { CR79, 0x58 }, - { CR12, 0xf0 }, { CR77, 0x1b }, { CR78, 0x58 }, - }; - - r = uw2453_synth_set_channel(chip, channel, autocal); - if (r) - return r; - - if (autocal) - vco_cfg = UW2453_AUTOCAL_VCO_CFG; - else - vco_cfg = uw2453_std_vco_cfg[config][CHAN_TO_PAIRIDX(channel)]; - - r = uw2453_write_vco_cfg(chip, vco_cfg); - if (r) - return r; - - r = uw2453_init_mode(chip); - if (r) - return r; - - r = zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); - if (r) - return r; - - r = uw2453_set_tx_gain_level(chip, channel); - if (r) - return r; - - return zd_iowrite16_locked(chip, 0x06, CR203); -} - -static int uw2453_switch_radio_on(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - struct zd_ioreq16 ioreqs[] = { - { CR11, 0x00 }, { CR251, 0x3f }, - }; - - /* enter RXTX mode */ - r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f94), RF_RV_BITS); - if (r) - return r; - - if (zd_chip_is_zd1211b(chip)) - ioreqs[1].value = 0x7f; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static int uw2453_switch_radio_off(struct zd_rf *rf) -{ - int r; - struct zd_chip *chip = zd_rf_to_chip(rf); - static const struct zd_ioreq16 ioreqs[] = { - { CR11, 0x04 }, { CR251, 0x2f }, - }; - - /* enter IDLE mode */ - /* FIXME: shouldn't we go to SLEEP? sent email to zydas */ - r = zd_rfwrite_locked(chip, UW2453_REGWRITE(0, 0x25f90), RF_RV_BITS); - if (r) - return r; - - return zd_iowrite16a_locked(chip, ioreqs, ARRAY_SIZE(ioreqs)); -} - -static void uw2453_clear(struct zd_rf *rf) -{ - kfree(rf->priv); -} - -int zd_rf_init_uw2453(struct zd_rf *rf) -{ - rf->init_hw = uw2453_init_hw; - rf->set_channel = uw2453_set_channel; - rf->switch_radio_on = uw2453_switch_radio_on; - rf->switch_radio_off = uw2453_switch_radio_off; - rf->patch_6m_band_edge = zd_rf_generic_patch_6m; - rf->clear = uw2453_clear; - /* we have our own TX integration code */ - rf->update_channel_int = 0; - - rf->priv = kmalloc(sizeof(struct uw2453_priv), GFP_KERNEL); - if (rf->priv == NULL) - return -ENOMEM; - - return 0; -} - diff --git a/drivers/net/wireless/zd1211rw/zd_usb.c b/drivers/net/wireless/zd1211rw/zd_usb.c deleted file mode 100644 index 23a6a6d4863b..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_usb.c +++ /dev/null @@ -1,1564 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * Copyright (C) 2006-2007 Michael Wu - * - * 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 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "zd_def.h" -#include "zd_mac.h" -#include "zd_usb.h" - -static struct usb_device_id usb_ids[] = { - /* ZD1211 */ - { USB_DEVICE(0x0105, 0x145f), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0586, 0x3401), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0586, 0x3402), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0586, 0x3407), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0586, 0x3409), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x079b, 0x004a), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0ace, 0x1211), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0ace, 0xa211), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0b05, 0x170c), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0b3b, 0x1630), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0b3b, 0x5630), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0df6, 0x9071), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x0df6, 0x9075), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x126f, 0xa006), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x129b, 0x1666), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x13b1, 0x001e), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x1435, 0x0711), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x14ea, 0xab13), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 }, - { USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 }, - /* ZD1211B */ - { USB_DEVICE(0x0053, 0x5301), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0411, 0x00da), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0471, 0x1236), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0471, 0x1237), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x050d, 0x705c), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x054c, 0x0257), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x340a), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x340f), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x3410), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x3412), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0586, 0x3413), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x079b, 0x0062), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x07b8, 0x6001), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x07fa, 0x1196), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x083a, 0x4505), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x083a, 0xe501), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x083a, 0xe503), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x083a, 0xe506), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0ace, 0x1215), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0ace, 0xb215), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0b05, 0x171b), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0baf, 0x0121), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0cde, 0x001a), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x0df6, 0x0036), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x129b, 0x1667), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x13b1, 0x0024), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x157e, 0x300d), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x1582, 0x6003), .driver_info = DEVICE_ZD1211B }, - { USB_DEVICE(0x2019, 0x5303), .driver_info = DEVICE_ZD1211B }, - /* "Driverless" devices that need ejecting */ - { USB_DEVICE(0x0ace, 0x2011), .driver_info = DEVICE_INSTALLER }, - { USB_DEVICE(0x0ace, 0x20ff), .driver_info = DEVICE_INSTALLER }, - {} -}; - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("USB driver for devices with the ZD1211 chip."); -MODULE_AUTHOR("Ulrich Kunitz"); -MODULE_AUTHOR("Daniel Drake"); -MODULE_VERSION("1.0"); -MODULE_DEVICE_TABLE(usb, usb_ids); - -#define FW_ZD1211_PREFIX "zd1211/zd1211_" -#define FW_ZD1211B_PREFIX "zd1211/zd1211b_" - -/* USB device initialization */ -static void int_urb_complete(struct urb *urb); - -static int request_fw_file( - const struct firmware **fw, const char *name, struct device *device) -{ - int r; - - dev_dbg_f(device, "fw name %s\n", name); - - r = request_firmware(fw, name, device); - if (r) - dev_err(device, - "Could not load firmware file %s. Error number %d\n", - name, r); - return r; -} - -static inline u16 get_bcdDevice(const struct usb_device *udev) -{ - return le16_to_cpu(udev->descriptor.bcdDevice); -} - -enum upload_code_flags { - REBOOT = 1, -}; - -/* Ensures that MAX_TRANSFER_SIZE is even. */ -#define MAX_TRANSFER_SIZE (USB_MAX_TRANSFER_SIZE & ~1) - -static int upload_code(struct usb_device *udev, - const u8 *data, size_t size, u16 code_offset, int flags) -{ - u8 *p; - int r; - - /* USB request blocks need "kmalloced" buffers. - */ - p = kmalloc(MAX_TRANSFER_SIZE, GFP_KERNEL); - if (!p) { - dev_err(&udev->dev, "out of memory\n"); - r = -ENOMEM; - goto error; - } - - size &= ~1; - while (size > 0) { - size_t transfer_size = size <= MAX_TRANSFER_SIZE ? - size : MAX_TRANSFER_SIZE; - - dev_dbg_f(&udev->dev, "transfer size %zu\n", transfer_size); - - memcpy(p, data, transfer_size); - r = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), - USB_REQ_FIRMWARE_DOWNLOAD, - USB_DIR_OUT | USB_TYPE_VENDOR, - code_offset, 0, p, transfer_size, 1000 /* ms */); - if (r < 0) { - dev_err(&udev->dev, - "USB control request for firmware upload" - " failed. Error number %d\n", r); - goto error; - } - transfer_size = r & ~1; - - size -= transfer_size; - data += transfer_size; - code_offset += transfer_size/sizeof(u16); - } - - if (flags & REBOOT) { - u8 ret; - - /* Use "DMA-aware" buffer. */ - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - USB_REQ_FIRMWARE_CONFIRM, - USB_DIR_IN | USB_TYPE_VENDOR, - 0, 0, p, sizeof(ret), 5000 /* ms */); - if (r != sizeof(ret)) { - dev_err(&udev->dev, - "control request firmeware confirmation failed." - " Return value %d\n", r); - if (r >= 0) - r = -ENODEV; - goto error; - } - ret = p[0]; - if (ret & 0x80) { - dev_err(&udev->dev, - "Internal error while downloading." - " Firmware confirm return value %#04x\n", - (unsigned int)ret); - r = -ENODEV; - goto error; - } - dev_dbg_f(&udev->dev, "firmware confirm return value %#04x\n", - (unsigned int)ret); - } - - r = 0; -error: - kfree(p); - return r; -} - -static u16 get_word(const void *data, u16 offset) -{ - const __le16 *p = data; - return le16_to_cpu(p[offset]); -} - -static char *get_fw_name(struct zd_usb *usb, char *buffer, size_t size, - const char* postfix) -{ - scnprintf(buffer, size, "%s%s", - usb->is_zd1211b ? - FW_ZD1211B_PREFIX : FW_ZD1211_PREFIX, - postfix); - return buffer; -} - -static int handle_version_mismatch(struct zd_usb *usb, - const struct firmware *ub_fw) -{ - struct usb_device *udev = zd_usb_to_usbdev(usb); - const struct firmware *ur_fw = NULL; - int offset; - int r = 0; - char fw_name[128]; - - r = request_fw_file(&ur_fw, - get_fw_name(usb, fw_name, sizeof(fw_name), "ur"), - &udev->dev); - if (r) - goto error; - - r = upload_code(udev, ur_fw->data, ur_fw->size, FW_START, REBOOT); - if (r) - goto error; - - offset = (E2P_BOOT_CODE_OFFSET * sizeof(u16)); - r = upload_code(udev, ub_fw->data + offset, ub_fw->size - offset, - E2P_START + E2P_BOOT_CODE_OFFSET, REBOOT); - - /* At this point, the vendor driver downloads the whole firmware - * image, hacks around with version IDs, and uploads it again, - * completely overwriting the boot code. We do not do this here as - * it is not required on any tested devices, and it is suspected to - * cause problems. */ -error: - release_firmware(ur_fw); - return r; -} - -static int upload_firmware(struct zd_usb *usb) -{ - int r; - u16 fw_bcdDevice; - u16 bcdDevice; - struct usb_device *udev = zd_usb_to_usbdev(usb); - const struct firmware *ub_fw = NULL; - const struct firmware *uph_fw = NULL; - char fw_name[128]; - - bcdDevice = get_bcdDevice(udev); - - r = request_fw_file(&ub_fw, - get_fw_name(usb, fw_name, sizeof(fw_name), "ub"), - &udev->dev); - if (r) - goto error; - - fw_bcdDevice = get_word(ub_fw->data, E2P_DATA_OFFSET); - - if (fw_bcdDevice != bcdDevice) { - dev_info(&udev->dev, - "firmware version %#06x and device bootcode version " - "%#06x differ\n", fw_bcdDevice, bcdDevice); - if (bcdDevice <= 0x4313) - dev_warn(&udev->dev, "device has old bootcode, please " - "report success or failure\n"); - - r = handle_version_mismatch(usb, ub_fw); - if (r) - goto error; - } else { - dev_dbg_f(&udev->dev, - "firmware device id %#06x is equal to the " - "actual device id\n", fw_bcdDevice); - } - - - r = request_fw_file(&uph_fw, - get_fw_name(usb, fw_name, sizeof(fw_name), "uphr"), - &udev->dev); - if (r) - goto error; - - r = upload_code(udev, uph_fw->data, uph_fw->size, FW_START, REBOOT); - if (r) { - dev_err(&udev->dev, - "Could not upload firmware code uph. Error number %d\n", - r); - } - - /* FALL-THROUGH */ -error: - release_firmware(ub_fw); - release_firmware(uph_fw); - return r; -} - -/* Read data from device address space using "firmware interface" which does - * not require firmware to be loaded. */ -int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len) -{ - int r; - struct usb_device *udev = zd_usb_to_usbdev(usb); - u8 *buf; - - /* Use "DMA-aware" buffer. */ - buf = kmalloc(len, GFP_KERNEL); - if (!buf) - return -ENOMEM; - r = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), - USB_REQ_FIRMWARE_READ_DATA, USB_DIR_IN | 0x40, addr, 0, - buf, len, 5000); - if (r < 0) { - dev_err(&udev->dev, - "read over firmware interface failed: %d\n", r); - goto exit; - } else if (r != len) { - dev_err(&udev->dev, - "incomplete read over firmware interface: %d/%d\n", - r, len); - r = -EIO; - goto exit; - } - r = 0; - memcpy(data, buf, len); -exit: - kfree(buf); - return r; -} - -#define urb_dev(urb) (&(urb)->dev->dev) - -static inline void handle_regs_int(struct urb *urb) -{ - struct zd_usb *usb = urb->context; - struct zd_usb_interrupt *intr = &usb->intr; - int len; - u16 int_num; - - ZD_ASSERT(in_interrupt()); - spin_lock(&intr->lock); - - int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2)); - if (int_num == CR_INTERRUPT) { - struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context)); - memcpy(&mac->intr_buffer, urb->transfer_buffer, - USB_MAX_EP_INT_BUFFER); - schedule_work(&mac->process_intr); - } else if (intr->read_regs_enabled) { - intr->read_regs.length = len = urb->actual_length; - - if (len > sizeof(intr->read_regs.buffer)) - len = sizeof(intr->read_regs.buffer); - memcpy(intr->read_regs.buffer, urb->transfer_buffer, len); - intr->read_regs_enabled = 0; - complete(&intr->read_regs.completion); - goto out; - } - -out: - spin_unlock(&intr->lock); -} - -static void int_urb_complete(struct urb *urb) -{ - int r; - struct usb_int_header *hdr; - - switch (urb->status) { - case 0: - break; - case -ESHUTDOWN: - case -EINVAL: - case -ENODEV: - case -ENOENT: - case -ECONNRESET: - case -EPIPE: - goto kfree; - default: - goto resubmit; - } - - if (urb->actual_length < sizeof(hdr)) { - dev_dbg_f(urb_dev(urb), "error: urb %p to small\n", urb); - goto resubmit; - } - - hdr = urb->transfer_buffer; - if (hdr->type != USB_INT_TYPE) { - dev_dbg_f(urb_dev(urb), "error: urb %p wrong type\n", urb); - goto resubmit; - } - - switch (hdr->id) { - case USB_INT_ID_REGS: - handle_regs_int(urb); - break; - case USB_INT_ID_RETRY_FAILED: - zd_mac_tx_failed(zd_usb_to_hw(urb->context)); - break; - default: - dev_dbg_f(urb_dev(urb), "error: urb %p unknown id %x\n", urb, - (unsigned int)hdr->id); - goto resubmit; - } - -resubmit: - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) { - dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb); - goto kfree; - } - return; -kfree: - kfree(urb->transfer_buffer); -} - -static inline int int_urb_interval(struct usb_device *udev) -{ - switch (udev->speed) { - case USB_SPEED_HIGH: - return 4; - case USB_SPEED_LOW: - return 10; - case USB_SPEED_FULL: - default: - return 1; - } -} - -static inline int usb_int_enabled(struct zd_usb *usb) -{ - unsigned long flags; - struct zd_usb_interrupt *intr = &usb->intr; - struct urb *urb; - - spin_lock_irqsave(&intr->lock, flags); - urb = intr->urb; - spin_unlock_irqrestore(&intr->lock, flags); - return urb != NULL; -} - -int zd_usb_enable_int(struct zd_usb *usb) -{ - int r; - struct usb_device *udev; - struct zd_usb_interrupt *intr = &usb->intr; - void *transfer_buffer = NULL; - struct urb *urb; - - dev_dbg_f(zd_usb_dev(usb), "\n"); - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) { - r = -ENOMEM; - goto out; - } - - ZD_ASSERT(!irqs_disabled()); - spin_lock_irq(&intr->lock); - if (intr->urb) { - spin_unlock_irq(&intr->lock); - r = 0; - goto error_free_urb; - } - intr->urb = urb; - spin_unlock_irq(&intr->lock); - - /* TODO: make it a DMA buffer */ - r = -ENOMEM; - transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL); - if (!transfer_buffer) { - dev_dbg_f(zd_usb_dev(usb), - "couldn't allocate transfer_buffer\n"); - goto error_set_urb_null; - } - - udev = zd_usb_to_usbdev(usb); - usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN), - transfer_buffer, USB_MAX_EP_INT_BUFFER, - int_urb_complete, usb, - intr->interval); - - dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb); - r = usb_submit_urb(urb, GFP_KERNEL); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "Couldn't submit urb. Error number %d\n", r); - goto error; - } - - return 0; -error: - kfree(transfer_buffer); -error_set_urb_null: - spin_lock_irq(&intr->lock); - intr->urb = NULL; - spin_unlock_irq(&intr->lock); -error_free_urb: - usb_free_urb(urb); -out: - return r; -} - -void zd_usb_disable_int(struct zd_usb *usb) -{ - unsigned long flags; - struct zd_usb_interrupt *intr = &usb->intr; - struct urb *urb; - - spin_lock_irqsave(&intr->lock, flags); - urb = intr->urb; - if (!urb) { - spin_unlock_irqrestore(&intr->lock, flags); - return; - } - intr->urb = NULL; - spin_unlock_irqrestore(&intr->lock, flags); - - usb_kill_urb(urb); - dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb); - usb_free_urb(urb); -} - -static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer, - unsigned int length) -{ - int i; - const struct rx_length_info *length_info; - - if (length < sizeof(struct rx_length_info)) { - /* It's not a complete packet anyhow. */ - return; - } - length_info = (struct rx_length_info *) - (buffer + length - sizeof(struct rx_length_info)); - - /* It might be that three frames are merged into a single URB - * transaction. We have to check for the length info tag. - * - * While testing we discovered that length_info might be unaligned, - * because if USB transactions are merged, the last packet will not - * be padded. Unaligned access might also happen if the length_info - * structure is not present. - */ - if (get_unaligned_le16(&length_info->tag) == RX_LENGTH_INFO_TAG) - { - unsigned int l, k, n; - for (i = 0, l = 0;; i++) { - k = get_unaligned_le16(&length_info->length[i]); - if (k == 0) - return; - n = l+k; - if (n > length) - return; - zd_mac_rx(zd_usb_to_hw(usb), buffer+l, k); - if (i >= 2) - return; - l = (n+3) & ~3; - } - } else { - zd_mac_rx(zd_usb_to_hw(usb), buffer, length); - } -} - -static void rx_urb_complete(struct urb *urb) -{ - struct zd_usb *usb; - struct zd_usb_rx *rx; - const u8 *buffer; - unsigned int length; - - switch (urb->status) { - case 0: - break; - case -ESHUTDOWN: - case -EINVAL: - case -ENODEV: - case -ENOENT: - case -ECONNRESET: - case -EPIPE: - return; - default: - dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); - goto resubmit; - } - - buffer = urb->transfer_buffer; - length = urb->actual_length; - usb = urb->context; - rx = &usb->rx; - - if (length%rx->usb_packet_size > rx->usb_packet_size-4) { - /* If there is an old first fragment, we don't care. */ - dev_dbg_f(urb_dev(urb), "*** first fragment ***\n"); - ZD_ASSERT(length <= ARRAY_SIZE(rx->fragment)); - spin_lock(&rx->lock); - memcpy(rx->fragment, buffer, length); - rx->fragment_length = length; - spin_unlock(&rx->lock); - goto resubmit; - } - - spin_lock(&rx->lock); - if (rx->fragment_length > 0) { - /* We are on a second fragment, we believe */ - ZD_ASSERT(length + rx->fragment_length <= - ARRAY_SIZE(rx->fragment)); - dev_dbg_f(urb_dev(urb), "*** second fragment ***\n"); - memcpy(rx->fragment+rx->fragment_length, buffer, length); - handle_rx_packet(usb, rx->fragment, - rx->fragment_length + length); - rx->fragment_length = 0; - spin_unlock(&rx->lock); - } else { - spin_unlock(&rx->lock); - handle_rx_packet(usb, buffer, length); - } - -resubmit: - usb_submit_urb(urb, GFP_ATOMIC); -} - -static struct urb *alloc_rx_urb(struct zd_usb *usb) -{ - struct usb_device *udev = zd_usb_to_usbdev(usb); - struct urb *urb; - void *buffer; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return NULL; - buffer = usb_buffer_alloc(udev, USB_MAX_RX_SIZE, GFP_KERNEL, - &urb->transfer_dma); - if (!buffer) { - usb_free_urb(urb); - return NULL; - } - - usb_fill_bulk_urb(urb, udev, usb_rcvbulkpipe(udev, EP_DATA_IN), - buffer, USB_MAX_RX_SIZE, - rx_urb_complete, usb); - urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; - - return urb; -} - -static void free_rx_urb(struct urb *urb) -{ - if (!urb) - return; - usb_buffer_free(urb->dev, urb->transfer_buffer_length, - urb->transfer_buffer, urb->transfer_dma); - usb_free_urb(urb); -} - -int zd_usb_enable_rx(struct zd_usb *usb) -{ - int i, r; - struct zd_usb_rx *rx = &usb->rx; - struct urb **urbs; - - dev_dbg_f(zd_usb_dev(usb), "\n"); - - r = -ENOMEM; - urbs = kcalloc(RX_URBS_COUNT, sizeof(struct urb *), GFP_KERNEL); - if (!urbs) - goto error; - for (i = 0; i < RX_URBS_COUNT; i++) { - urbs[i] = alloc_rx_urb(usb); - if (!urbs[i]) - goto error; - } - - ZD_ASSERT(!irqs_disabled()); - spin_lock_irq(&rx->lock); - if (rx->urbs) { - spin_unlock_irq(&rx->lock); - r = 0; - goto error; - } - rx->urbs = urbs; - rx->urbs_count = RX_URBS_COUNT; - spin_unlock_irq(&rx->lock); - - for (i = 0; i < RX_URBS_COUNT; i++) { - r = usb_submit_urb(urbs[i], GFP_KERNEL); - if (r) - goto error_submit; - } - - return 0; -error_submit: - for (i = 0; i < RX_URBS_COUNT; i++) { - usb_kill_urb(urbs[i]); - } - spin_lock_irq(&rx->lock); - rx->urbs = NULL; - rx->urbs_count = 0; - spin_unlock_irq(&rx->lock); -error: - if (urbs) { - for (i = 0; i < RX_URBS_COUNT; i++) - free_rx_urb(urbs[i]); - } - return r; -} - -void zd_usb_disable_rx(struct zd_usb *usb) -{ - int i; - unsigned long flags; - struct urb **urbs; - unsigned int count; - struct zd_usb_rx *rx = &usb->rx; - - spin_lock_irqsave(&rx->lock, flags); - urbs = rx->urbs; - count = rx->urbs_count; - spin_unlock_irqrestore(&rx->lock, flags); - if (!urbs) - return; - - for (i = 0; i < count; i++) { - usb_kill_urb(urbs[i]); - free_rx_urb(urbs[i]); - } - kfree(urbs); - - spin_lock_irqsave(&rx->lock, flags); - rx->urbs = NULL; - rx->urbs_count = 0; - spin_unlock_irqrestore(&rx->lock, flags); -} - -/** - * zd_usb_disable_tx - disable transmission - * @usb: the zd1211rw-private USB structure - * - * Frees all URBs in the free list and marks the transmission as disabled. - */ -void zd_usb_disable_tx(struct zd_usb *usb) -{ - struct zd_usb_tx *tx = &usb->tx; - unsigned long flags; - struct list_head *pos, *n; - - spin_lock_irqsave(&tx->lock, flags); - list_for_each_safe(pos, n, &tx->free_urb_list) { - list_del(pos); - usb_free_urb(list_entry(pos, struct urb, urb_list)); - } - tx->enabled = 0; - tx->submitted_urbs = 0; - /* The stopped state is ignored, relying on ieee80211_wake_queues() - * in a potentionally following zd_usb_enable_tx(). - */ - spin_unlock_irqrestore(&tx->lock, flags); -} - -/** - * zd_usb_enable_tx - enables transmission - * @usb: a &struct zd_usb pointer - * - * This function enables transmission and prepares the &zd_usb_tx data - * structure. - */ -void zd_usb_enable_tx(struct zd_usb *usb) -{ - unsigned long flags; - struct zd_usb_tx *tx = &usb->tx; - - spin_lock_irqsave(&tx->lock, flags); - tx->enabled = 1; - tx->submitted_urbs = 0; - ieee80211_wake_queues(zd_usb_to_hw(usb)); - tx->stopped = 0; - spin_unlock_irqrestore(&tx->lock, flags); -} - -/** - * alloc_tx_urb - provides an tx URB - * @usb: a &struct zd_usb pointer - * - * Allocates a new URB. If possible takes the urb from the free list in - * usb->tx. - */ -static struct urb *alloc_tx_urb(struct zd_usb *usb) -{ - struct zd_usb_tx *tx = &usb->tx; - unsigned long flags; - struct list_head *entry; - struct urb *urb; - - spin_lock_irqsave(&tx->lock, flags); - if (list_empty(&tx->free_urb_list)) { - urb = usb_alloc_urb(0, GFP_ATOMIC); - goto out; - } - entry = tx->free_urb_list.next; - list_del(entry); - urb = list_entry(entry, struct urb, urb_list); -out: - spin_unlock_irqrestore(&tx->lock, flags); - return urb; -} - -/** - * free_tx_urb - frees a used tx URB - * @usb: a &struct zd_usb pointer - * @urb: URB to be freed - * - * Frees the the transmission URB, which means to put it on the free URB - * list. - */ -static void free_tx_urb(struct zd_usb *usb, struct urb *urb) -{ - struct zd_usb_tx *tx = &usb->tx; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - if (!tx->enabled) { - usb_free_urb(urb); - goto out; - } - list_add(&urb->urb_list, &tx->free_urb_list); -out: - spin_unlock_irqrestore(&tx->lock, flags); -} - -static void tx_dec_submitted_urbs(struct zd_usb *usb) -{ - struct zd_usb_tx *tx = &usb->tx; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - --tx->submitted_urbs; - if (tx->stopped && tx->submitted_urbs <= ZD_USB_TX_LOW) { - ieee80211_wake_queues(zd_usb_to_hw(usb)); - tx->stopped = 0; - } - spin_unlock_irqrestore(&tx->lock, flags); -} - -static void tx_inc_submitted_urbs(struct zd_usb *usb) -{ - struct zd_usb_tx *tx = &usb->tx; - unsigned long flags; - - spin_lock_irqsave(&tx->lock, flags); - ++tx->submitted_urbs; - if (!tx->stopped && tx->submitted_urbs > ZD_USB_TX_HIGH) { - ieee80211_stop_queues(zd_usb_to_hw(usb)); - tx->stopped = 1; - } - spin_unlock_irqrestore(&tx->lock, flags); -} - -/** - * tx_urb_complete - completes the execution of an URB - * @urb: a URB - * - * This function is called if the URB has been transferred to a device or an - * error has happened. - */ -static void tx_urb_complete(struct urb *urb) -{ - int r; - struct sk_buff *skb; - struct ieee80211_tx_info *info; - struct zd_usb *usb; - - switch (urb->status) { - case 0: - break; - case -ESHUTDOWN: - case -EINVAL: - case -ENODEV: - case -ENOENT: - case -ECONNRESET: - case -EPIPE: - dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); - break; - default: - dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status); - goto resubmit; - } -free_urb: - skb = (struct sk_buff *)urb->context; - /* - * grab 'usb' pointer before handing off the skb (since - * it might be freed by zd_mac_tx_to_dev or mac80211) - */ - info = IEEE80211_SKB_CB(skb); - usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb; - zd_mac_tx_to_dev(skb, urb->status); - free_tx_urb(usb, urb); - tx_dec_submitted_urbs(usb); - return; -resubmit: - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) { - dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r); - goto free_urb; - } -} - -/** - * zd_usb_tx: initiates transfer of a frame of the device - * - * @usb: the zd1211rw-private USB structure - * @skb: a &struct sk_buff pointer - * - * This function tranmits a frame to the device. It doesn't wait for - * completion. The frame must contain the control set and have all the - * control set information available. - * - * The function returns 0 if the transfer has been successfully initiated. - */ -int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb) -{ - int r; - struct usb_device *udev = zd_usb_to_usbdev(usb); - struct urb *urb; - - urb = alloc_tx_urb(usb); - if (!urb) { - r = -ENOMEM; - goto out; - } - - usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT), - skb->data, skb->len, tx_urb_complete, skb); - - r = usb_submit_urb(urb, GFP_ATOMIC); - if (r) - goto error; - tx_inc_submitted_urbs(usb); - return 0; -error: - free_tx_urb(usb, urb); -out: - return r; -} - -static inline void init_usb_interrupt(struct zd_usb *usb) -{ - struct zd_usb_interrupt *intr = &usb->intr; - - spin_lock_init(&intr->lock); - intr->interval = int_urb_interval(zd_usb_to_usbdev(usb)); - init_completion(&intr->read_regs.completion); - intr->read_regs.cr_int_addr = cpu_to_le16((u16)CR_INTERRUPT); -} - -static inline void init_usb_rx(struct zd_usb *usb) -{ - struct zd_usb_rx *rx = &usb->rx; - spin_lock_init(&rx->lock); - if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) { - rx->usb_packet_size = 512; - } else { - rx->usb_packet_size = 64; - } - ZD_ASSERT(rx->fragment_length == 0); -} - -static inline void init_usb_tx(struct zd_usb *usb) -{ - struct zd_usb_tx *tx = &usb->tx; - spin_lock_init(&tx->lock); - tx->enabled = 0; - tx->stopped = 0; - INIT_LIST_HEAD(&tx->free_urb_list); - tx->submitted_urbs = 0; -} - -void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, - struct usb_interface *intf) -{ - memset(usb, 0, sizeof(*usb)); - usb->intf = usb_get_intf(intf); - usb_set_intfdata(usb->intf, hw); - init_usb_interrupt(usb); - init_usb_tx(usb); - init_usb_rx(usb); -} - -void zd_usb_clear(struct zd_usb *usb) -{ - usb_set_intfdata(usb->intf, NULL); - usb_put_intf(usb->intf); - ZD_MEMCLEAR(usb, sizeof(*usb)); - /* FIXME: usb_interrupt, usb_tx, usb_rx? */ -} - -static const char *speed(enum usb_device_speed speed) -{ - switch (speed) { - case USB_SPEED_LOW: - return "low"; - case USB_SPEED_FULL: - return "full"; - case USB_SPEED_HIGH: - return "high"; - default: - return "unknown speed"; - } -} - -static int scnprint_id(struct usb_device *udev, char *buffer, size_t size) -{ - return scnprintf(buffer, size, "%04hx:%04hx v%04hx %s", - le16_to_cpu(udev->descriptor.idVendor), - le16_to_cpu(udev->descriptor.idProduct), - get_bcdDevice(udev), - speed(udev->speed)); -} - -int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size) -{ - struct usb_device *udev = interface_to_usbdev(usb->intf); - return scnprint_id(udev, buffer, size); -} - -#ifdef DEBUG -static void print_id(struct usb_device *udev) -{ - char buffer[40]; - - scnprint_id(udev, buffer, sizeof(buffer)); - buffer[sizeof(buffer)-1] = 0; - dev_dbg_f(&udev->dev, "%s\n", buffer); -} -#else -#define print_id(udev) do { } while (0) -#endif - -static int eject_installer(struct usb_interface *intf) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_interface *iface_desc = &intf->altsetting[0]; - struct usb_endpoint_descriptor *endpoint; - unsigned char *cmd; - u8 bulk_out_ep; - int r; - - /* Find bulk out endpoint */ - endpoint = &iface_desc->endpoint[1].desc; - if (usb_endpoint_dir_out(endpoint) && - usb_endpoint_xfer_bulk(endpoint)) { - bulk_out_ep = endpoint->bEndpointAddress; - } else { - dev_err(&udev->dev, - "zd1211rw: Could not find bulk out endpoint\n"); - return -ENODEV; - } - - cmd = kzalloc(31, GFP_KERNEL); - if (cmd == NULL) - return -ENODEV; - - /* USB bulk command block */ - cmd[0] = 0x55; /* bulk command signature */ - cmd[1] = 0x53; /* bulk command signature */ - cmd[2] = 0x42; /* bulk command signature */ - cmd[3] = 0x43; /* bulk command signature */ - cmd[14] = 6; /* command length */ - - cmd[15] = 0x1b; /* SCSI command: START STOP UNIT */ - cmd[19] = 0x2; /* eject disc */ - - dev_info(&udev->dev, "Ejecting virtual installer media...\n"); - r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep), - cmd, 31, NULL, 2000); - kfree(cmd); - if (r) - return r; - - /* At this point, the device disconnects and reconnects with the real - * ID numbers. */ - - usb_set_intfdata(intf, NULL); - return 0; -} - -int zd_usb_init_hw(struct zd_usb *usb) -{ - int r; - struct zd_mac *mac = zd_usb_to_mac(usb); - - dev_dbg_f(zd_usb_dev(usb), "\n"); - - r = upload_firmware(usb); - if (r) { - dev_err(zd_usb_dev(usb), - "couldn't load firmware. Error number %d\n", r); - return r; - } - - r = usb_reset_configuration(zd_usb_to_usbdev(usb)); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "couldn't reset configuration. Error number %d\n", r); - return r; - } - - r = zd_mac_init_hw(mac->hw); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "couldn't initialize mac. Error number %d\n", r); - return r; - } - - usb->initialized = 1; - return 0; -} - -static int probe(struct usb_interface *intf, const struct usb_device_id *id) -{ - int r; - struct usb_device *udev = interface_to_usbdev(intf); - struct zd_usb *usb; - struct ieee80211_hw *hw = NULL; - - print_id(udev); - - if (id->driver_info & DEVICE_INSTALLER) - return eject_installer(intf); - - switch (udev->speed) { - case USB_SPEED_LOW: - case USB_SPEED_FULL: - case USB_SPEED_HIGH: - break; - default: - dev_dbg_f(&intf->dev, "Unknown USB speed\n"); - r = -ENODEV; - goto error; - } - - r = usb_reset_device(udev); - if (r) { - dev_err(&intf->dev, - "couldn't reset usb device. Error number %d\n", r); - goto error; - } - - hw = zd_mac_alloc_hw(intf); - if (hw == NULL) { - r = -ENOMEM; - goto error; - } - - usb = &zd_hw_mac(hw)->chip.usb; - usb->is_zd1211b = (id->driver_info == DEVICE_ZD1211B) != 0; - - r = zd_mac_preinit_hw(hw); - if (r) { - dev_dbg_f(&intf->dev, - "couldn't initialize mac. Error number %d\n", r); - goto error; - } - - r = ieee80211_register_hw(hw); - if (r) { - dev_dbg_f(&intf->dev, - "couldn't register device. Error number %d\n", r); - goto error; - } - - dev_dbg_f(&intf->dev, "successful\n"); - dev_info(&intf->dev, "%s\n", wiphy_name(hw->wiphy)); - return 0; -error: - usb_reset_device(interface_to_usbdev(intf)); - if (hw) { - zd_mac_clear(zd_hw_mac(hw)); - ieee80211_free_hw(hw); - } - return r; -} - -static void disconnect(struct usb_interface *intf) -{ - struct ieee80211_hw *hw = zd_intf_to_hw(intf); - struct zd_mac *mac; - struct zd_usb *usb; - - /* Either something really bad happened, or we're just dealing with - * a DEVICE_INSTALLER. */ - if (hw == NULL) - return; - - mac = zd_hw_mac(hw); - usb = &mac->chip.usb; - - dev_dbg_f(zd_usb_dev(usb), "\n"); - - ieee80211_unregister_hw(hw); - - /* Just in case something has gone wrong! */ - zd_usb_disable_rx(usb); - zd_usb_disable_int(usb); - - /* If the disconnect has been caused by a removal of the - * driver module, the reset allows reloading of the driver. If the - * reset will not be executed here, the upload of the firmware in the - * probe function caused by the reloading of the driver will fail. - */ - usb_reset_device(interface_to_usbdev(intf)); - - zd_mac_clear(mac); - ieee80211_free_hw(hw); - dev_dbg(&intf->dev, "disconnected\n"); -} - -static struct usb_driver driver = { - .name = KBUILD_MODNAME, - .id_table = usb_ids, - .probe = probe, - .disconnect = disconnect, -}; - -struct workqueue_struct *zd_workqueue; - -static int __init usb_init(void) -{ - int r; - - pr_debug("%s usb_init()\n", driver.name); - - zd_workqueue = create_singlethread_workqueue(driver.name); - if (zd_workqueue == NULL) { - printk(KERN_ERR "%s couldn't create workqueue\n", driver.name); - return -ENOMEM; - } - - r = usb_register(&driver); - if (r) { - destroy_workqueue(zd_workqueue); - printk(KERN_ERR "%s usb_register() failed. Error number %d\n", - driver.name, r); - return r; - } - - pr_debug("%s initialized\n", driver.name); - return 0; -} - -static void __exit usb_exit(void) -{ - pr_debug("%s usb_exit()\n", driver.name); - usb_deregister(&driver); - destroy_workqueue(zd_workqueue); -} - -module_init(usb_init); -module_exit(usb_exit); - -static int usb_int_regs_length(unsigned int count) -{ - return sizeof(struct usb_int_regs) + count * sizeof(struct reg_data); -} - -static void prepare_read_regs_int(struct zd_usb *usb) -{ - struct zd_usb_interrupt *intr = &usb->intr; - - spin_lock_irq(&intr->lock); - intr->read_regs_enabled = 1; - INIT_COMPLETION(intr->read_regs.completion); - spin_unlock_irq(&intr->lock); -} - -static void disable_read_regs_int(struct zd_usb *usb) -{ - struct zd_usb_interrupt *intr = &usb->intr; - - spin_lock_irq(&intr->lock); - intr->read_regs_enabled = 0; - spin_unlock_irq(&intr->lock); -} - -static int get_results(struct zd_usb *usb, u16 *values, - struct usb_req_read_regs *req, unsigned int count) -{ - int r; - int i; - struct zd_usb_interrupt *intr = &usb->intr; - struct read_regs_int *rr = &intr->read_regs; - struct usb_int_regs *regs = (struct usb_int_regs *)rr->buffer; - - spin_lock_irq(&intr->lock); - - r = -EIO; - /* The created block size seems to be larger than expected. - * However results appear to be correct. - */ - if (rr->length < usb_int_regs_length(count)) { - dev_dbg_f(zd_usb_dev(usb), - "error: actual length %d less than expected %d\n", - rr->length, usb_int_regs_length(count)); - goto error_unlock; - } - if (rr->length > sizeof(rr->buffer)) { - dev_dbg_f(zd_usb_dev(usb), - "error: actual length %d exceeds buffer size %zu\n", - rr->length, sizeof(rr->buffer)); - goto error_unlock; - } - - for (i = 0; i < count; i++) { - struct reg_data *rd = ®s->regs[i]; - if (rd->addr != req->addr[i]) { - dev_dbg_f(zd_usb_dev(usb), - "rd[%d] addr %#06hx expected %#06hx\n", i, - le16_to_cpu(rd->addr), - le16_to_cpu(req->addr[i])); - goto error_unlock; - } - values[i] = le16_to_cpu(rd->value); - } - - r = 0; -error_unlock: - spin_unlock_irq(&intr->lock); - return r; -} - -int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, - const zd_addr_t *addresses, unsigned int count) -{ - int r; - int i, req_len, actual_req_len; - struct usb_device *udev; - struct usb_req_read_regs *req = NULL; - unsigned long timeout; - - if (count < 1) { - dev_dbg_f(zd_usb_dev(usb), "error: count is zero\n"); - return -EINVAL; - } - if (count > USB_MAX_IOREAD16_COUNT) { - dev_dbg_f(zd_usb_dev(usb), - "error: count %u exceeds possible max %u\n", - count, USB_MAX_IOREAD16_COUNT); - return -EINVAL; - } - if (in_atomic()) { - dev_dbg_f(zd_usb_dev(usb), - "error: io in atomic context not supported\n"); - return -EWOULDBLOCK; - } - if (!usb_int_enabled(usb)) { - dev_dbg_f(zd_usb_dev(usb), - "error: usb interrupt not enabled\n"); - return -EWOULDBLOCK; - } - - req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16); - req = kmalloc(req_len, GFP_KERNEL); - if (!req) - return -ENOMEM; - req->id = cpu_to_le16(USB_REQ_READ_REGS); - for (i = 0; i < count; i++) - req->addr[i] = cpu_to_le16((u16)addresses[i]); - - udev = zd_usb_to_usbdev(usb); - prepare_read_regs_int(usb); - r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), - req, req_len, &actual_req_len, 1000 /* ms */); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "error in usb_bulk_msg(). Error number %d\n", r); - goto error; - } - if (req_len != actual_req_len) { - dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n" - " req_len %d != actual_req_len %d\n", - req_len, actual_req_len); - r = -EIO; - goto error; - } - - timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion, - msecs_to_jiffies(1000)); - if (!timeout) { - disable_read_regs_int(usb); - dev_dbg_f(zd_usb_dev(usb), "read timed out\n"); - r = -ETIMEDOUT; - goto error; - } - - r = get_results(usb, values, req, count); -error: - kfree(req); - return r; -} - -int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, - unsigned int count) -{ - int r; - struct usb_device *udev; - struct usb_req_write_regs *req = NULL; - int i, req_len, actual_req_len; - - if (count == 0) - return 0; - if (count > USB_MAX_IOWRITE16_COUNT) { - dev_dbg_f(zd_usb_dev(usb), - "error: count %u exceeds possible max %u\n", - count, USB_MAX_IOWRITE16_COUNT); - return -EINVAL; - } - if (in_atomic()) { - dev_dbg_f(zd_usb_dev(usb), - "error: io in atomic context not supported\n"); - return -EWOULDBLOCK; - } - - req_len = sizeof(struct usb_req_write_regs) + - count * sizeof(struct reg_data); - req = kmalloc(req_len, GFP_KERNEL); - if (!req) - return -ENOMEM; - - req->id = cpu_to_le16(USB_REQ_WRITE_REGS); - for (i = 0; i < count; i++) { - struct reg_data *rw = &req->reg_writes[i]; - rw->addr = cpu_to_le16((u16)ioreqs[i].addr); - rw->value = cpu_to_le16(ioreqs[i].value); - } - - udev = zd_usb_to_usbdev(usb); - r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), - req, req_len, &actual_req_len, 1000 /* ms */); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "error in usb_bulk_msg(). Error number %d\n", r); - goto error; - } - if (req_len != actual_req_len) { - dev_dbg_f(zd_usb_dev(usb), - "error in usb_bulk_msg()" - " req_len %d != actual_req_len %d\n", - req_len, actual_req_len); - r = -EIO; - goto error; - } - - /* FALL-THROUGH with r == 0 */ -error: - kfree(req); - return r; -} - -int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits) -{ - int r; - struct usb_device *udev; - struct usb_req_rfwrite *req = NULL; - int i, req_len, actual_req_len; - u16 bit_value_template; - - if (in_atomic()) { - dev_dbg_f(zd_usb_dev(usb), - "error: io in atomic context not supported\n"); - return -EWOULDBLOCK; - } - if (bits < USB_MIN_RFWRITE_BIT_COUNT) { - dev_dbg_f(zd_usb_dev(usb), - "error: bits %d are smaller than" - " USB_MIN_RFWRITE_BIT_COUNT %d\n", - bits, USB_MIN_RFWRITE_BIT_COUNT); - return -EINVAL; - } - if (bits > USB_MAX_RFWRITE_BIT_COUNT) { - dev_dbg_f(zd_usb_dev(usb), - "error: bits %d exceed USB_MAX_RFWRITE_BIT_COUNT %d\n", - bits, USB_MAX_RFWRITE_BIT_COUNT); - return -EINVAL; - } -#ifdef DEBUG - if (value & (~0UL << bits)) { - dev_dbg_f(zd_usb_dev(usb), - "error: value %#09x has bits >= %d set\n", - value, bits); - return -EINVAL; - } -#endif /* DEBUG */ - - dev_dbg_f(zd_usb_dev(usb), "value %#09x bits %d\n", value, bits); - - r = zd_usb_ioread16(usb, &bit_value_template, CR203); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "error %d: Couldn't read CR203\n", r); - goto out; - } - bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA); - - req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16); - req = kmalloc(req_len, GFP_KERNEL); - if (!req) - return -ENOMEM; - - req->id = cpu_to_le16(USB_REQ_WRITE_RF); - /* 1: 3683a, but not used in ZYDAS driver */ - req->value = cpu_to_le16(2); - req->bits = cpu_to_le16(bits); - - for (i = 0; i < bits; i++) { - u16 bv = bit_value_template; - if (value & (1 << (bits-1-i))) - bv |= RF_DATA; - req->bit_values[i] = cpu_to_le16(bv); - } - - udev = zd_usb_to_usbdev(usb); - r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT), - req, req_len, &actual_req_len, 1000 /* ms */); - if (r) { - dev_dbg_f(zd_usb_dev(usb), - "error in usb_bulk_msg(). Error number %d\n", r); - goto out; - } - if (req_len != actual_req_len) { - dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()" - " req_len %d != actual_req_len %d\n", - req_len, actual_req_len); - r = -EIO; - goto out; - } - - /* FALL-THROUGH with r == 0 */ -out: - kfree(req); - return r; -} diff --git a/drivers/net/wireless/zd1211rw/zd_usb.h b/drivers/net/wireless/zd1211rw/zd_usb.h deleted file mode 100644 index 049f8b91f020..000000000000 --- a/drivers/net/wireless/zd1211rw/zd_usb.h +++ /dev/null @@ -1,266 +0,0 @@ -/* ZD1211 USB-WLAN driver for Linux - * - * Copyright (C) 2005-2007 Ulrich Kunitz - * Copyright (C) 2006-2007 Daniel Drake - * - * 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 - */ - -#ifndef _ZD_USB_H -#define _ZD_USB_H - -#include -#include -#include -#include -#include - -#include "zd_def.h" - -#define ZD_USB_TX_HIGH 5 -#define ZD_USB_TX_LOW 2 - -enum devicetype { - DEVICE_ZD1211 = 0, - DEVICE_ZD1211B = 1, - DEVICE_INSTALLER = 2, -}; - -enum endpoints { - EP_CTRL = 0, - EP_DATA_OUT = 1, - EP_DATA_IN = 2, - EP_INT_IN = 3, - EP_REGS_OUT = 4, -}; - -enum { - USB_MAX_TRANSFER_SIZE = 4096, /* bytes */ - /* FIXME: The original driver uses this value. We have to check, - * whether the MAX_TRANSFER_SIZE is sufficient and this needs only be - * used if one combined frame is split over two USB transactions. - */ - USB_MAX_RX_SIZE = 4800, /* bytes */ - USB_MAX_IOWRITE16_COUNT = 15, - USB_MAX_IOWRITE32_COUNT = USB_MAX_IOWRITE16_COUNT/2, - USB_MAX_IOREAD16_COUNT = 15, - USB_MAX_IOREAD32_COUNT = USB_MAX_IOREAD16_COUNT/2, - USB_MIN_RFWRITE_BIT_COUNT = 16, - USB_MAX_RFWRITE_BIT_COUNT = 28, - USB_MAX_EP_INT_BUFFER = 64, - USB_ZD1211B_BCD_DEVICE = 0x4810, -}; - -enum control_requests { - USB_REQ_WRITE_REGS = 0x21, - USB_REQ_READ_REGS = 0x22, - USB_REQ_WRITE_RF = 0x23, - USB_REQ_PROG_FLASH = 0x24, - USB_REQ_EEPROM_START = 0x0128, /* ? request is a byte */ - USB_REQ_EEPROM_MID = 0x28, - USB_REQ_EEPROM_END = 0x0228, /* ? request is a byte */ - USB_REQ_FIRMWARE_DOWNLOAD = 0x30, - USB_REQ_FIRMWARE_CONFIRM = 0x31, - USB_REQ_FIRMWARE_READ_DATA = 0x32, -}; - -struct usb_req_read_regs { - __le16 id; - __le16 addr[0]; -} __attribute__((packed)); - -struct reg_data { - __le16 addr; - __le16 value; -} __attribute__((packed)); - -struct usb_req_write_regs { - __le16 id; - struct reg_data reg_writes[0]; -} __attribute__((packed)); - -enum { - RF_IF_LE = 0x02, - RF_CLK = 0x04, - RF_DATA = 0x08, -}; - -struct usb_req_rfwrite { - __le16 id; - __le16 value; - /* 1: 3683a */ - /* 2: other (default) */ - __le16 bits; - /* RF2595: 24 */ - __le16 bit_values[0]; - /* (CR203 & ~(RF_IF_LE | RF_CLK | RF_DATA)) | (bit ? RF_DATA : 0) */ -} __attribute__((packed)); - -/* USB interrupt */ - -enum usb_int_id { - USB_INT_TYPE = 0x01, - USB_INT_ID_REGS = 0x90, - USB_INT_ID_RETRY_FAILED = 0xa0, -}; - -enum usb_int_flags { - USB_INT_READ_REGS_EN = 0x01, -}; - -struct usb_int_header { - u8 type; /* must always be 1 */ - u8 id; -} __attribute__((packed)); - -struct usb_int_regs { - struct usb_int_header hdr; - struct reg_data regs[0]; -} __attribute__((packed)); - -struct usb_int_retry_fail { - struct usb_int_header hdr; - u8 new_rate; - u8 _dummy; - u8 addr[ETH_ALEN]; - u8 ibss_wakeup_dest; -} __attribute__((packed)); - -struct read_regs_int { - struct completion completion; - /* Stores the USB int structure and contains the USB address of the - * first requested register before request. - */ - u8 buffer[USB_MAX_EP_INT_BUFFER]; - int length; - __le16 cr_int_addr; -}; - -struct zd_ioreq16 { - zd_addr_t addr; - u16 value; -}; - -struct zd_ioreq32 { - zd_addr_t addr; - u32 value; -}; - -struct zd_usb_interrupt { - struct read_regs_int read_regs; - spinlock_t lock; - struct urb *urb; - int interval; - u8 read_regs_enabled:1; -}; - -static inline struct usb_int_regs *get_read_regs(struct zd_usb_interrupt *intr) -{ - return (struct usb_int_regs *)intr->read_regs.buffer; -} - -#define RX_URBS_COUNT 5 - -struct zd_usb_rx { - spinlock_t lock; - u8 fragment[2*USB_MAX_RX_SIZE]; - unsigned int fragment_length; - unsigned int usb_packet_size; - struct urb **urbs; - int urbs_count; -}; - -/** - * struct zd_usb_tx - structure used for transmitting frames - * @lock: lock for transmission - * @free_urb_list: list of free URBs, contains all the URBs, which can be used - * @submitted_urbs: atomic integer that counts the URBs having sent to the - * device, which haven't been completed - * @enabled: enabled flag, indicates whether tx is enabled - * @stopped: indicates whether higher level tx queues are stopped - */ -struct zd_usb_tx { - spinlock_t lock; - struct list_head free_urb_list; - int submitted_urbs; - int enabled; - int stopped; -}; - -/* Contains the usb parts. The structure doesn't require a lock because intf - * will not be changed after initialization. - */ -struct zd_usb { - struct zd_usb_interrupt intr; - struct zd_usb_rx rx; - struct zd_usb_tx tx; - struct usb_interface *intf; - u8 is_zd1211b:1, initialized:1; -}; - -#define zd_usb_dev(usb) (&usb->intf->dev) - -static inline struct usb_device *zd_usb_to_usbdev(struct zd_usb *usb) -{ - return interface_to_usbdev(usb->intf); -} - -static inline struct ieee80211_hw *zd_intf_to_hw(struct usb_interface *intf) -{ - return usb_get_intfdata(intf); -} - -static inline struct ieee80211_hw *zd_usb_to_hw(struct zd_usb *usb) -{ - return zd_intf_to_hw(usb->intf); -} - -void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw, - struct usb_interface *intf); -int zd_usb_init_hw(struct zd_usb *usb); -void zd_usb_clear(struct zd_usb *usb); - -int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size); - -int zd_usb_enable_int(struct zd_usb *usb); -void zd_usb_disable_int(struct zd_usb *usb); - -int zd_usb_enable_rx(struct zd_usb *usb); -void zd_usb_disable_rx(struct zd_usb *usb); - -void zd_usb_enable_tx(struct zd_usb *usb); -void zd_usb_disable_tx(struct zd_usb *usb); - -int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb); - -int zd_usb_ioread16v(struct zd_usb *usb, u16 *values, - const zd_addr_t *addresses, unsigned int count); - -static inline int zd_usb_ioread16(struct zd_usb *usb, u16 *value, - const zd_addr_t addr) -{ - return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1); -} - -int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs, - unsigned int count); - -int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits); - -int zd_usb_read_fw(struct zd_usb *usb, zd_addr_t addr, u8 *data, u16 len); - -extern struct workqueue_struct *zd_workqueue; - -#endif /* _ZD_USB_H */